]> xenbits.xensource.com Git - unikraft/unikraft.git/commitdiff
plat/kvm: toggle PKE bit if HAVE_X86PKU is enabled
authorHugo Lefeuvre <hle@owl.eu.com>
Fri, 11 Dec 2020 16:35:12 +0000 (16:35 +0000)
committerSimon Kuenzer <simon.kuenzer@neclab.eu>
Mon, 21 Dec 2020 16:21:04 +0000 (17:21 +0100)
Provided that PKU is advertised by cpuid (EAX=7, ECX=0, ECX bit 4),
Memory Protection Keys can be enabled by setting bit 22 (PKE) in CR4
(see Intel 64 and IA-32 Architectures Software Developer's Manual Vol.
3A, Section 2.5 'Control Registers').

Since we do not want to pay the cost of MPK-related code when MPK is
not enabled, we introduce a new HAVE_X86PKU property; MPK code is
compile-guarded so that it does not get compiled in without
HAVE_X86PKU. HAVE_X86PKU will be set by PKU kernel libraries later on.

At boot time, if HAVE_X86PKU is enabled, the kernel now checks whether
PKU is advertised by cpuid. If not, it aborts the boot process. The
underlying idea is that images compiled with HAVE_X86PKU are
*specialized* to be executed on PKU-enabled hardware. Hence, provided
that HAVE_X86PKU is set, there is a guarantee that PKU is supported
*and* enabled, effectively removing the need for checks later at
runtime. This might benefit performance when the domain switching rate
is high.

Signed-off-by: Hugo Lefeuvre <hugo.lefeuvre@manchester.ac.uk>
Reviewed-by: Mocanu Gabriel <gabi.mocanu98@gmail.com>
lib/Config.uk
plat/common/include/x86/cpu.h
plat/common/include/x86/cpu_defs.h
plat/kvm/x86/entry64.S
plat/kvm/x86/setup.c

index e83ed30bc401268c0ce7f2b1023369f06e737a25..dac2d2fa9f54e7556017f40e922a5e7a64ccb64b 100644 (file)
@@ -28,3 +28,7 @@ config HAVE_NW_STACK
 config HAVE_SYSCALL
        bool
        default n
+
+config HAVE_X86PKU
+       bool
+       default n
index 5f1a35e462f12581e3fa1334f9a4444e2cc1245a..d4c02e0806489755bf97e8bc9daa4edcfc5d3359 100644 (file)
@@ -341,4 +341,19 @@ static inline void _init_syscall(void)
 }
 #endif /* CONFIG_HAVE_SYSCALL */
 
+#if CONFIG_HAVE_X86PKU
+static inline void _check_ospke(void)
+{
+       __u32 eax, ebx, ecx, edx;
+       cpuid(0x7, 0, &eax, &ebx, &ecx, &edx);
+       if (!(ecx & X86_CPUID7_ECX_OSPKE)) {
+               /* if PKU is not enabled, abort the boot process. Images
+                * compiled with HAVE_X86PKU are *specialized* to be executed on
+                * PKU-enabled hardware. This allows us to avoid checks later at
+                * runtime. */
+               UK_CRASH("CPU does not support PKU!\n");
+       }
+}
+#endif /* CONFIG_HAVE_X86PKU */
+
 #endif /* __PLAT_COMMON_X86_CPU_H__ */
index dcbe2c65f3f80973d3111aa8e62d724571a6c628..74cff459dbdbd071a9166dd39ec78eb183ef53bb 100644 (file)
@@ -71,6 +71,7 @@
 #define X86_CR4_OSXMMEXCPT      (1 << 10)   /* OS support for FP exceptions */
 #define X86_CR4_FSGSBASE        (1 << 16)   /* enable FSGSBASE*/
 #define X86_CR4_OSXSAVE         (1 << 18)   /* enable XSAVE, extended states */
+#define X86_CR4_PKE             (1 << 22)   /* enable protection keys */
 
 /*
  * Intel CPU features in EFER
@@ -86,6 +87,8 @@
 #define X86_CPUID1_EDX_SSE      (1 << 25)
 /* CPUID feature bits in EBX and ECX when EAX=7, ECX=0 */
 #define X86_CPUID7_EBX_FSGSBASE (1 << 0)
+#define X86_CPUID7_ECX_PKU     (1 << 3)
+#define X86_CPUID7_ECX_OSPKE   (1 << 4)
 /* CPUID feature bits when EAX=0xd, ECX=1 */
 #define X86_CPUIDD1_EAX_XSAVEOPT (1<<0)
 /* CPUID 80000001H:EDX feature list */
index 169f4c82fe320e28becc1e0b276998526b90ea18..ef5e0e778ee49ebb43b52ca387b946b243683c5b 100644 (file)
@@ -31,6 +31,9 @@
 #include <kvm-x86/traps.h>
 #include <kvm-x86/multiboot_defs.h>
 
+/* necessary for CONFIG_ macros to be accessible */
+#include <uk/config.h>
+
 #define ENTRY(x) .globl x; .type x,%function; x:
 #define END(x)   .size x, . - x
 
@@ -227,6 +230,15 @@ noxsave:
        orl $(X86_CR4_FSGSBASE), %edi
        movq %rdi, %cr4
 nofsgsbase:
+#if CONFIG_HAVE_X86PKU
+       /* check for Memory Protection Keys (PKU) */
+       testl $(X86_CPUID7_ECX_PKU), %ecx
+       jz nopku
+       /* if PKU is supported, enable it via CR4 */
+       orl $(X86_CR4_PKE), %edi
+       movq %rdi, %cr4
+nopku:
+#endif /* CONFIG_HAVE_X86PKU */
        /* done setting up CPU capabilities */
 
        /* read multiboot info pointer */
index 9c7a93a84402ca34653df321ed39c3c87a6bc311..fbc5c0d212287509cb2edcf8f722bdee8be8a861 100644 (file)
@@ -291,6 +291,10 @@ void _libkvmplat_entry(void *arg)
        _init_syscall();
 #endif /* CONFIG_HAVE_SYSCALL */
 
+#if CONFIG_HAVE_X86PKU
+       _check_ospke();
+#endif /* CONFIG_HAVE_X86PKU */
+
        /*
         * Switch away from the bootstrap stack as early as possible.
         */