[PATCHv3 08/11] arm64: Check for selected granule support

Suzuki K. Poulose Suzuki.Poulose at arm.com
Thu Oct 15 04:25:33 PDT 2015


On Thu, Oct 15, 2015 at 11:45:15AM +0100, Mark Rutland wrote:
> On Wed, Oct 14, 2015 at 04:13:47PM -0500, Jeremy Linton wrote:
> > On 10/14/2015 06:20 AM, Suzuki K. Poulose wrote:
> > 
> > >+ * Checks if the selected granule size is supported by the CPU.
> > >+ * If it doesn't park the CPU
> > 
> > The problem is when you park the boot CPU.
> > 
> > I think for EFI there is a slightly better error mechanism. This
> > tweak will print an error and return to the EFI boot manager rather
> > than hanging the machine without any notification. Now it prints:
> > 
> > EFI stub: Booting Linux Kernel...
> > EFI stub: ERROR: 16K granule not supported by this machine
> > EFI stub: ERROR: Failed to relocate kernel
> > FS4:\>
> 
> Neat. We should definitely have checks like this in the stub.
> 
> However, we still need checks in head.S, given !EFI systems, SMP, and
> kexec, so this is a complementary mechanism.

Indeed. I meant to add the above check. The updated patch looks like :

----8>----

Author: Suzuki K. Poulose <suzuki.poulose at arm.com>
Date:   Wed Oct 14 11:25:16 2015 +0100

    arm64: Check for selected granule support
    
    Ensure that the selected page size is supported by the CPU(s). If it isn't
    park the CPU. A check is added to the EFI stub to detect if the boot CPU
    supports the page size, failing which, we fail the boot gracefully, with
    an error message.
    
    Signed-off-by: Suzuki K. Poulose <suzuki.poulose at arm.com>
    [ Added a check to EFI stub ]
    Signed-off-by: Jeremy Linton <jeremy.linton at arm.com>

diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index a7f3d4b..72d814c 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -44,6 +44,26 @@
 #define SET_PSTATE_PAN(x) __inst_arm(0xd5000000 | REG_PSTATE_PAN_IMM |\
 				     (!!x)<<8 | 0x1f)
 
+
+#define ID_AA64MMFR0_TGRAN4_SHIFT	28
+#define ID_AA64MMFR0_TGRAN64_SHIFT	24
+#define ID_AA64MMFR0_TGRAN16_SHIFT	20
+
+#define ID_AA64MMFR0_TGRAN4_NI		0xf
+#define ID_AA64MMFR0_TGRAN4_ON		0x0
+#define ID_AA64MMFR0_TGRAN64_NI		0xf
+#define ID_AA64MMFR0_TGRAN64_ON		0x0
+#define ID_AA64MMFR0_TGRAN16_NI		0x0
+#define ID_AA64MMFR0_TGRAN16_ON		0x1
+
+#if defined(CONFIG_ARM64_4K_PAGES)
+#define ID_AA64MMFR0_TGRAN_SHIFT	ID_AA64MMFR0_TGRAN4_SHIFT
+#define ID_AA64MMFR0_TGRAN_SUPPORTED	ID_AA64MMFR0_TGRAN4_ON
+#else
+#define ID_AA64MMFR0_TGRAN_SHIFT	ID_AA64MMFR0_TGRAN64_SHIFT
+#define ID_AA64MMFR0_TGRAN_SUPPORTED	ID_AA64MMFR0_TGRAN64_ON
+#endif
+
 #ifdef __ASSEMBLY__
 
 	.irp	num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30
diff --git a/arch/arm64/kernel/efi-stub.c b/arch/arm64/kernel/efi-stub.c
index 816120e..77d7de1 100644
--- a/arch/arm64/kernel/efi-stub.c
+++ b/arch/arm64/kernel/efi-stub.c
@@ -11,8 +11,15 @@
  */
 #include <linux/efi.h>
 #include <asm/efi.h>
+#include <asm/sysreg.h>
 #include <asm/sections.h>
 
+#if defined(CONFIG_ARM64_4K_PAGES)
+#define PAGE_SIZE_STR	"4K"
+#elif defined(CONFIG_ARM64_64K_PAGES)
+#define PAGE_SIZE_STR	"64K"
+#endif
+
 efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table_arg,
 					unsigned long *image_addr,
 					unsigned long *image_size,
@@ -25,6 +32,17 @@ efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table_arg,
 	unsigned long kernel_size, kernel_memsize = 0;
 	unsigned long nr_pages;
 	void *old_image_addr = (void *)*image_addr;
+	u64 aa64mmfr0_el1;
+
+	/*
+	 * Check to see if the CPU supports the requested pagesize
+	 */
+	asm volatile("mrs %0, ID_AA64MMFR0_EL1" : "=r" (aa64mmfr0_el1));
+	aa64mmfr0_el1 >>= ID_AA64MMFR0_TGRAN_SHIFT;
+	if ((aa64mmfr0_el1 & 0xf) != ID_AA64MMFR0_TGRAN_SUPPORTED) {
+		pr_efi_err(sys_table_arg, PAGE_SIZE_STR" granule not supported by the CPU\n");
+		return EFI_UNSUPPORTED;
+	}
 
 	/* Relocate the image, if required. */
 	kernel_size = _edata - _text;
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 7ace955..514c1cc 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -31,10 +31,11 @@
 #include <asm/cputype.h>
 #include <asm/kernel-pgtable.h>
 #include <asm/memory.h>
-#include <asm/thread_info.h>
 #include <asm/pgtable-hwdef.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
+#include <asm/sysreg.h>
+#include <asm/thread_info.h>
 #include <asm/virt.h>
 
 #define __PHYS_OFFSET	(KERNEL_START - TEXT_OFFSET)
@@ -613,10 +614,17 @@ ENDPROC(__secondary_switched)
  *  x0  = SCTLR_EL1 value for turning on the MMU.
  *  x27 = *virtual* address to jump to upon completion
  *
- * other registers depend on the function called upon completion
+ * Other registers depend on the function called upon completion.
+ *
+ * Checks if the selected granule size is supported by the CPU.
+ * If it isn't, park the CPU
  */
 	.section	".idmap.text", "ax"
 __enable_mmu:
+	mrs	x1, ID_AA64MMFR0_EL1
+	ubfx	x2, x1, #ID_AA64MMFR0_TGRAN_SHIFT, 4
+	cmp	x2, #ID_AA64MMFR0_TGRAN_SUPPORTED
+	b.ne	__no_granule_support
 	ldr	x5, =vectors
 	msr	vbar_el1, x5
 	msr	ttbr0_el1, x25			// load TTBR0
@@ -634,3 +642,8 @@ __enable_mmu:
 	isb
 	br	x27
 ENDPROC(__enable_mmu)
+
+__no_granule_support:
+	wfe
+	b __no_granule_support
+ENDPROC(__no_granule_support)

----8<----
> 
> Thanks,
> Mark.
> 
> > Signed-off-by: Jeremy Linton <jeremy.linton at arm.com>
> > ---
> >  arch/arm64/kernel/efi-stub.c | 14 ++++++++++++++
> >  1 file changed, 14 insertions(+)
> > 
> > diff --git a/arch/arm64/kernel/efi-stub.c b/arch/arm64/kernel/efi-stub.c
> > index 816120e..90fb868 100644
> > --- a/arch/arm64/kernel/efi-stub.c
> > +++ b/arch/arm64/kernel/efi-stub.c
> > @@ -25,6 +25,20 @@ efi_status_t __init
> > handle_kernel_image(efi_system_table_t *sys_table_arg,
> >         unsigned long kernel_size, kernel_memsize = 0;
> >         unsigned long nr_pages;
> >         void *old_image_addr = (void *)*image_addr;
> > +       u32 aa64mmfr0_el1;
> > +
> > +#ifdef CONFIG_ARM64_16K_PAGES
> > +       /*
> > +        * check to see if this kernel image is
> > +        * compatible with the current system
> > +        */
> > +       asm volatile("mrs %0, ID_AA64MMFR0_EL1" : "=r" (aa64mmfr0_el1));
> > +       aa64mmfr0_el1 >>= ID_AA64MMFR0_TGRAN16_SHIFT;
> > +       if ((aa64mmfr0_el1 & ID_AA64MMFR0_TGRAN4_ON) == 0) {
> > +               pr_efi_err(sys_table_arg, "16K granule not supported
> > by this machine\n");
> > +               return EFI_UNSUPPORTED;
> > +       }
> > +#endif
> > 
> >         /* Relocate the image, if required. */
> >         kernel_size = _edata - _text;
> > -- 
> > 2.4.3
> > 
> > 
> > 
> > 
> > 
> > 
> > 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
> 




More information about the linux-arm-kernel mailing list