diff mbox series

x86/emul: Emulate %cr8 accesses

Message ID 20250317184044.560367-1-andrew.cooper3@citrix.com (mailing list archive)
State New
Headers show
Series x86/emul: Emulate %cr8 accesses | expand

Commit Message

Andrew Cooper March 17, 2025, 6:40 p.m. UTC
Petr reports:

  (XEN) MMIO emulation failed (1): d12v1 64bit @ 0010:fffff8057ba7dfbf -> 45 0f 20 c2 ...

during introspection.

This is MOV %cr8, which is wired up for hvm_mov_{to,from}_cr(); the VMExit
fastpaths, but not for the full emulation slowpaths.  Wire %cr8 up in
hvmemul_{read,write}_cr() too.

Reported-by: Petr Beneš <w1benny@gmail.com>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Petr Beneš <w1benny@gmail.com>

Like the fastpaths, this depends on all HVM/PVH guests strictly getting an
LAPIC, which is guaranteed by XSA-256.  There's no such thing as a 64bit CPU
without a Local APIC, so no such thing as %cr8 not being TPR.
---
 xen/arch/x86/hvm/emulate.c | 10 ++++++++++
 1 file changed, 10 insertions(+)


base-commit: e7e0d485e993e97b1c816adcfc610e7c7258ce96

Comments

Jan Beulich March 18, 2025, 8:29 a.m. UTC | #1
On 17.03.2025 19:40, Andrew Cooper wrote:
> Petr reports:
> 
>   (XEN) MMIO emulation failed (1): d12v1 64bit @ 0010:fffff8057ba7dfbf -> 45 0f 20 c2 ...
> 
> during introspection.
> 
> This is MOV %cr8, which is wired up for hvm_mov_{to,from}_cr(); the VMExit
> fastpaths, but not for the full emulation slowpaths.  Wire %cr8 up in
> hvmemul_{read,write}_cr() too.
> 
> Reported-by: Petr Beneš <w1benny@gmail.com>
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Like in a few other cases I guess there's no good Fixes: tag to use, as the
omission must have been there basically forever.

> --- a/xen/arch/x86/hvm/emulate.c
> +++ b/xen/arch/x86/hvm/emulate.c
> @@ -2285,6 +2285,11 @@ static int cf_check hvmemul_read_cr(
>          *val = current->arch.hvm.guest_cr[reg];
>          TRACE(TRC_HVM_CR_READ64, reg, *val, *val >> 32);
>          return X86EMUL_OKAY;
> +
> +    case 8:
> +        *val = (vlapic_get_reg(vcpu_vlapic(current), APIC_TASKPRI) & 0xf0) >> 4;

I think it would be nice to add a #define to apicdef.h that could be utilized to
use MASK_EXTR() here (and MASK_INSR() below). Otherwise even without such a
#define I'd like to ask that we use the two macros here.

> +        return X86EMUL_OKAY;
> +
>      default:
>          break;
>      }
> @@ -2325,6 +2330,11 @@ static int cf_check hvmemul_write_cr(
>          rc = hvm_set_cr4(val, true);
>          break;
>  
> +    case 8:
> +        vlapic_set_reg(vcpu_vlapic(current), APIC_TASKPRI, ((val & 0x0f) << 4));
> +        rc = X86EMUL_OKAY;
> +        break;

Both SDM and PM say #GP upon writes to reserved bits, without there being a place
where it is said which bits are reserved. Don't we therefore need to treat bits 4
and up as must-be-zero, implying that all bits which have no meaning are reserved?

Jan
diff mbox series

Patch

diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c
index dbf6b5543adf..852240b29d74 100644
--- a/xen/arch/x86/hvm/emulate.c
+++ b/xen/arch/x86/hvm/emulate.c
@@ -2285,6 +2285,11 @@  static int cf_check hvmemul_read_cr(
         *val = current->arch.hvm.guest_cr[reg];
         TRACE(TRC_HVM_CR_READ64, reg, *val, *val >> 32);
         return X86EMUL_OKAY;
+
+    case 8:
+        *val = (vlapic_get_reg(vcpu_vlapic(current), APIC_TASKPRI) & 0xf0) >> 4;
+        return X86EMUL_OKAY;
+
     default:
         break;
     }
@@ -2325,6 +2330,11 @@  static int cf_check hvmemul_write_cr(
         rc = hvm_set_cr4(val, true);
         break;
 
+    case 8:
+        vlapic_set_reg(vcpu_vlapic(current), APIC_TASKPRI, ((val & 0x0f) << 4));
+        rc = X86EMUL_OKAY;
+        break;
+
     default:
         rc = X86EMUL_UNHANDLEABLE;
         break;