guest_pku_enabled(v) )
{
unsigned int pkey = guest_l1e_get_pkey(gw->l1e);
- unsigned int pkru = read_pkru();
+ unsigned int pkru = rdpkru();
if ( read_pkru_ad(pkru, pkey) ||
((walk & PFEC_write_access) && read_pkru_wd(pkru, pkey) &&
{
const struct domain *d = v->domain;
unsigned long cr4 = mmu_cr4_features &
- ~(X86_CR4_PCIDE | X86_CR4_PGE | X86_CR4_TSD);
+ ~(X86_CR4_PCIDE | X86_CR4_PGE | X86_CR4_TSD | X86_CR4_PKE);
+
+ /*
+ * We want CR4.PKE set in HVM context when available, but don't support it
+ * in PV context at all.
+ *
+ * _PAGE_PKEY_BITS where previously software available PTE bits. In
+ * principle, we could let an aware PV guest enable PKE.
+ *
+ * However, Xen uses _PAGE_GNTTAB in debug builds which overlaps with
+ * _PAGE_PKEY_BITS, and the ownership of (and eligibility to move)
+ * software PTE bits is not considered in the PV ABI at all. For now,
+ * punt the problem to whichever unluckly person finds a compelling
+ * usecase for PKRU in PV guests.
+ */
/*
* PCIDE or PGE depends on the PCID/XPTI settings, but must not both be
if ( boot_cpu_has(X86_FEATURE_FSGSBASE) )
set_in_cr4(X86_CR4_FSGSBASE);
+ if ( boot_cpu_has(X86_FEATURE_PKU) )
+ set_in_cr4(X86_CR4_PKE);
+
if ( opt_invpcid && cpu_has_invpcid )
use_invpcid = true;
write_cr4(read_cr4() | mask);
}
-static inline unsigned int read_pkru(void)
+static inline unsigned int rdpkru(void)
{
unsigned int pkru;
- unsigned long cr4 = read_cr4();
- /*
- * _PAGE_PKEY_BITS have a conflict with _PAGE_GNTTAB used by PV guests,
- * so that X86_CR4_PKE is disabled on hypervisor. To use RDPKRU, CR4.PKE
- * gets temporarily enabled.
- */
- write_cr4(cr4 | X86_CR4_PKE);
asm volatile (".byte 0x0f,0x01,0xee"
: "=a" (pkru) : "c" (0) : "dx");
- write_cr4(cr4);
return pkru;
}