From 48f2a10a71bb4bc3053142996dd581ebcfa3e3ab Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Tue, 21 Apr 2020 17:43:56 +0100 Subject: [PATCH] x86/hvm: Introduce control register handling for CET Allow CR4.CET to be set, based on the CPUID policy (although these bits are not selectable yet for VMs). CR4.CET needs interlocing with CR0.WP to prohibit CET && !WP as a legal combination. Signed-off-by: Andrew Cooper Acked-by: Jan Beulich --- xen/arch/x86/hvm/hvm.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index ae37bc434a..28beacc45b 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -976,11 +976,12 @@ const char *hvm_efer_valid(const struct vcpu *v, uint64_t value, unsigned long hvm_cr4_guest_valid_bits(const struct domain *d) { const struct cpuid_policy *p = d->arch.cpuid; - bool mce, vmxe; + bool mce, vmxe, cet; /* Logic broken out simply to aid readability below. */ mce = p->basic.mce || p->basic.mca; vmxe = p->basic.vmx && nestedhvm_enabled(d); + cet = p->feat.cet_ss || p->feat.cet_ibt; return ((p->basic.vme ? X86_CR4_VME | X86_CR4_PVI : 0) | (p->basic.tsc ? X86_CR4_TSD : 0) | @@ -999,7 +1000,8 @@ unsigned long hvm_cr4_guest_valid_bits(const struct domain *d) (p->basic.xsave ? X86_CR4_OSXSAVE : 0) | (p->feat.smep ? X86_CR4_SMEP : 0) | (p->feat.smap ? X86_CR4_SMAP : 0) | - (p->feat.pku ? X86_CR4_PKE : 0)); + (p->feat.pku ? X86_CR4_PKE : 0) | + (cet ? X86_CR4_CET : 0)); } static int hvm_load_cpu_ctxt(struct domain *d, hvm_domain_context_t *h) @@ -2289,6 +2291,12 @@ int hvm_set_cr0(unsigned long value, bool may_defer) } } + if ( !(value & X86_CR0_WP) && (v->arch.hvm.guest_cr[4] & X86_CR4_CET) ) + { + gprintk(XENLOG_DEBUG, "Trying to clear WP with CET set\n"); + return X86EMUL_EXCEPTION; + } + if ( (value & X86_CR0_PG) && !(old_value & X86_CR0_PG) ) { if ( v->arch.hvm.guest_efer & EFER_LME ) @@ -2444,6 +2452,12 @@ int hvm_set_cr4(unsigned long value, bool may_defer) } } + if ( (value & X86_CR4_CET) && !(v->arch.hvm.guest_cr[0] & X86_CR0_WP) ) + { + gprintk(XENLOG_DEBUG, "Trying to set CET without WP\n"); + return X86EMUL_EXCEPTION; + } + old_cr = v->arch.hvm.guest_cr[4]; if ( (value & X86_CR4_PCIDE) && !(old_cr & X86_CR4_PCIDE) && -- 2.30.2