All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ingo Molnar <mingo@kernel.org>
To: "Bryan O'Donoghue" <pure.logic@nexus-software.ie>
Cc: linux-kernel@vger.kernel.org, corbet@lwn.net, tglx@linutronix.de,
	mingo@redhat.com, hpa@zytor.com, x86@kernel.org,
	andriy.shevchenko@linux.intel.com, boon.leong.ong@intel.com,
	fengguang.wu@intel.com, linux-doc@vger.kernel.org
Subject: Re: [PATCH] x86/intel/quark: Parameterize the kernel's IMR lock logic
Date: Thu, 18 Feb 2016 08:58:10 +0100	[thread overview]
Message-ID: <20160218075810.GA16041@gmail.com> (raw)
In-Reply-To: <1455766168-17335-1-git-send-email-pure.logic@nexus-software.ie>


* Bryan O'Donoghue <pure.logic@nexus-software.ie> wrote:

> Currently when setting up an IMR around the kernel's .text area we lock
> that IMR, preventing further modification. While superficially this appears
> to be the right thing to do, in fact this doesn't account for a legitimate
> change in the memory map such as when executing a new kernel via kexec.
> 
> In such a scenario a second kernel can have a different size and location
> to it's predecessor and can view some of the memory occupied by it's
> predecessor as legitimately usable DMA RAM. If this RAM were then
> subsequently allocated to DMA agents within the system it could conceivably
> trigger an IMR violation.
> 
> This patch fixes the this potential situation by keeping the kernel's .text
> section IMR lock bit false by default, thus ensuring that a user of the
> system will have kexec just work without having to pass special parameters
> on the kernel command line to influence the state of the kernel's IMR. If a
> user so desires then it is possible to explicitly set the lock bit to true.
> 
> The new parameter is kernel_imr and this may be set to kernel_imr=locked or
> kernel_imr=unlocked.
> 
> Signed-off-by: Bryan O'Donoghue <pure.logic@nexus-software.ie>
> Reported-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> ---
>  Documentation/kernel-parameters.txt |  7 +++++++
>  arch/x86/platform/intel-quark/imr.c | 39 +++++++++++++++++++++++++++++++------
>  2 files changed, 40 insertions(+), 6 deletions(-)
> 
> diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
> index 9a53c92..1aad1d2 100644
> --- a/Documentation/kernel-parameters.txt
> +++ b/Documentation/kernel-parameters.txt
> @@ -1359,6 +1359,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
>  			        hardware thread id mappings.
>  				Format: <cpu>:<hwthread>
>  
> +	kernel_imr=	[X86, INTEL_IMR] Control the lock bit for the Isolated
> +			Memory Region protecting the kernel's .text section on
> +			X86 architectures that support IMRs such as Quark X1000.
> +			When an IMR lock bit is set it is not possible to unset
> +			it without a CPU reset.
> +			Format : {locked | unlocked (default) }
> +
>  	keep_bootcon	[KNL]
>  			Do not unregister boot console at start. This is only
>  			useful for debugging when something happens in the window
> diff --git a/arch/x86/platform/intel-quark/imr.c b/arch/x86/platform/intel-quark/imr.c
> index c61b6c3..8249f65 100644
> --- a/arch/x86/platform/intel-quark/imr.c
> +++ b/arch/x86/platform/intel-quark/imr.c
> @@ -37,6 +37,7 @@
>  struct imr_device {
>  	struct dentry	*file;
>  	bool		init;
> +	bool		kernel_imr_locked;
>  	struct mutex	lock;
>  	int		max_imr;
>  	int		reg_base;
> @@ -568,10 +569,15 @@ static inline int imr_clear(int reg)
>   * BIOS and Grub both setup IMRs around compressed kernel, initrd memory
>   * that need to be removed before the kernel hands out one of the IMR
>   * encased addresses to a downstream DMA agent such as the SD or Ethernet.
> + * Additionally if the current kernel is executing via kexec then we need to
> + * tear down the IMR the previous kernel had setup.
> + *
>   * IMRs on Galileo are setup to immediately reset the system on violation.
>   * As a result if you're running a root filesystem from SD - you'll need
>   * the boot-time IMRs torn down or you'll find seemingly random resets when
> - * using your filesystem.
> + * using your filesystem; similarly if you're doing a kexec boot of Linux then
> + * its required to sanitize the memory map with-respect to the previous IMR
> + * settings.
>   *
>   * @idev:	pointer to imr_device structure.
>   * @return:
> @@ -592,14 +598,20 @@ static void __init imr_fixup_memmap(struct imr_device *idev)
>  	end = (unsigned long)__end_rodata - 1;
>  
>  	/*
> -	 * Setup a locked IMR around the physical extent of the kernel
> -	 * from the beginning of the .text secton to the end of the
> -	 * .rodata section as one physically contiguous block.
> +	 * Setup an IMR around the physical extent of the kernel from the
> +	 * beginning of the .text section to the end of the .rodata section
> +	 * as one physically contiguous block.
>  	 *
>  	 * We don't round up @size since it is already PAGE_SIZE aligned.
>  	 * See vmlinux.lds.S for details.
> +	 *
> +	 * By default this IMR is unlocked to enable subsequent kernels booted
> +	 * by kexec to tear down the IMR we are setting up below. Its possible
> +	 * to set this IMR to the locked state by passing kernel_imr=locked on
> +	 * the kernel command line.
>  	 */
> -	ret = imr_add_range(base, size, IMR_CPU, IMR_CPU, true);
> +	ret = imr_add_range(base, size, IMR_CPU, IMR_CPU,
> +			    imr_dev.kernel_imr_locked);
>  	if (ret < 0) {
>  		pr_err("unable to setup IMR for kernel: %zu KiB (%lx - %lx)\n",
>  			size / 1024, start, end);
> @@ -617,8 +629,23 @@ static const struct x86_cpu_id imr_ids[] __initconst = {
>  MODULE_DEVICE_TABLE(x86cpu, imr_ids);
>  
>  /**
> - * imr_init - entry point for IMR driver.
> + * imr_kernel_lock_setup - control the lock bit of the kernel's IMR
>   *
> + */
> +static int __init imr_kernel_lock_setup(char *str)
> +{
> +	if (!strcmp(str, "unlocked"))
> +		imr_dev.kernel_imr_locked = false;
> +	else if (!strcmp(str, "locked"))
> +		imr_dev.kernel_imr_locked = true;
> +	else
> +		return 0;
> +	return 1;
> +}
> +__setup("kernel_imr=", imr_kernel_lock_setup);
> +
> +/**
> + * imr_init - entry point for IMR driver.
>   * return: -ENODEV for no IMR support 0 if good to go.
>   */
>  static int __init imr_init(void)
> -- 
> 2.5.0

So why not simply do the patch below? Very few people use boot parameters, and the 
complexity does not seem to be worth it.

Furthermore I think an IMR range in itself is safe enough - it's not like such 
register state is going to be randomly corrupted, even with the 'lock' bit unset. 
So it's a perfectly fine protective measure against accidental memory corruption 
from the DMA space. It should not try to be more than that.

And once we do this, I suggest we get rid of the 'lock' parameter altogether - 
that will further simplify the code.

Thanks,

	Ingo

===============>

 arch/x86/platform/intel-quark/imr.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/platform/intel-quark/imr.c b/arch/x86/platform/intel-quark/imr.c
index 0a3736f03edc..f7c4f523910f 100644
--- a/arch/x86/platform/intel-quark/imr.c
+++ b/arch/x86/platform/intel-quark/imr.c
@@ -587,7 +587,7 @@ static void __init imr_fixup_memmap(struct imr_device *idev)
 	 * We don't round up @size since it is already PAGE_SIZE aligned.
 	 * See vmlinux.lds.S for details.
 	 */
-	ret = imr_add_range(base, size, IMR_CPU, IMR_CPU, true);
+	ret = imr_add_range(base, size, IMR_CPU, IMR_CPU, false);
 	if (ret < 0) {
 		pr_err("unable to setup IMR for kernel: %zu KiB (%lx - %lx)\n",
 			size / 1024, start, end);

  reply	other threads:[~2016-02-18  7:58 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-02-18  3:29 [PATCH] x86/intel/quark: Parameterize the kernel's IMR lock logic Bryan O'Donoghue
2016-02-18  7:58 ` Ingo Molnar [this message]
2016-02-18 10:31   ` Bryan O'Donoghue
2016-02-18 18:53     ` Ingo Molnar
2016-02-19  1:07       ` Bryan O'Donoghue

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160218075810.GA16041@gmail.com \
    --to=mingo@kernel.org \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=boon.leong.ong@intel.com \
    --cc=corbet@lwn.net \
    --cc=fengguang.wu@intel.com \
    --cc=hpa@zytor.com \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=pure.logic@nexus-software.ie \
    --cc=tglx@linutronix.de \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.