aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2007-11-26 15:32:54 +0000
committerKeir Fraser <keir.fraser@citrix.com>2007-11-26 15:32:54 +0000
commitdbccb328c8a573703fdffdfb35323fe11b086b64 (patch)
treebcd3d8a8e9d6bf2c93045aadec1da24ac9d53dba
parentcfb9675b686f87cf622cfc56a476f100639331a1 (diff)
downloadxen-dbccb328c8a573703fdffdfb35323fe11b086b64.tar.gz
xen-dbccb328c8a573703fdffdfb35323fe11b086b64.tar.bz2
xen-dbccb328c8a573703fdffdfb35323fe11b086b64.zip
x86_emulate: Emulate CPUID and HLT.
vmx realmode: Fix decode & emulate loop, add hooks for CPUID, HLT and WBINVD. Also do not hook realmode entry off of vmentry failure any more. Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
-rw-r--r--xen/arch/x86/hvm/vmx/realmode.c87
-rw-r--r--xen/arch/x86/hvm/vmx/vmx.c114
-rw-r--r--xen/arch/x86/hvm/vmx/x86_32/exits.S19
-rw-r--r--xen/arch/x86/hvm/vmx/x86_64/exits.S17
-rw-r--r--xen/arch/x86/x86_32/asm-offsets.c1
-rw-r--r--xen/arch/x86/x86_64/asm-offsets.c1
-rw-r--r--xen/arch/x86/x86_emulate.c23
-rw-r--r--xen/include/asm-x86/hvm/vmx/vmx.h4
-rw-r--r--xen/include/asm-x86/x86_emulate.h12
9 files changed, 201 insertions, 77 deletions
diff --git a/xen/arch/x86/hvm/vmx/realmode.c b/xen/arch/x86/hvm/vmx/realmode.c
index 840200eaf7..9a8a7b8743 100644
--- a/xen/arch/x86/hvm/vmx/realmode.c
+++ b/xen/arch/x86/hvm/vmx/realmode.c
@@ -29,6 +29,16 @@ struct realmode_emulate_ctxt {
unsigned long insn_buf_eip;
struct segment_register seg_reg[10];
+
+ union {
+ struct {
+ unsigned int hlt:1;
+ unsigned int mov_ss:1;
+ unsigned int sti:1;
+ unsigned int exn_raised:1;
+ } flags;
+ unsigned int flag_word;
+ };
};
static void realmode_deliver_exception(
@@ -251,14 +261,8 @@ realmode_write_segment(
struct realmode_emulate_ctxt *rm_ctxt =
container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
memcpy(&rm_ctxt->seg_reg[seg], reg, sizeof(struct segment_register));
-
if ( seg == x86_seg_ss )
- {
- u32 intr_shadow = __vmread(GUEST_INTERRUPTIBILITY_INFO);
- intr_shadow ^= VMX_INTR_SHADOW_MOV_SS;
- __vmwrite(GUEST_INTERRUPTIBILITY_INFO, intr_shadow);
- }
-
+ rm_ctxt->flags.mov_ss = 1;
return X86EMUL_OKAY;
}
@@ -337,13 +341,37 @@ static int realmode_write_rflags(
unsigned long val,
struct x86_emulate_ctxt *ctxt)
{
+ struct realmode_emulate_ctxt *rm_ctxt =
+ container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
if ( (val & X86_EFLAGS_IF) && !(ctxt->regs->eflags & X86_EFLAGS_IF) )
- {
- u32 intr_shadow = __vmread(GUEST_INTERRUPTIBILITY_INFO);
- intr_shadow ^= VMX_INTR_SHADOW_STI;
- __vmwrite(GUEST_INTERRUPTIBILITY_INFO, intr_shadow);
- }
+ rm_ctxt->flags.sti = 1;
+ return X86EMUL_OKAY;
+}
+static int realmode_wbinvd(
+ struct x86_emulate_ctxt *ctxt)
+{
+ vmx_wbinvd_intercept();
+ return X86EMUL_OKAY;
+}
+
+static int realmode_cpuid(
+ unsigned int *eax,
+ unsigned int *ebx,
+ unsigned int *ecx,
+ unsigned int *edx,
+ struct x86_emulate_ctxt *ctxt)
+{
+ vmx_cpuid_intercept(eax, ebx, ecx, edx);
+ return X86EMUL_OKAY;
+}
+
+static int realmode_hlt(
+ struct x86_emulate_ctxt *ctxt)
+{
+ struct realmode_emulate_ctxt *rm_ctxt =
+ container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
+ rm_ctxt->flags.hlt = 1;
return X86EMUL_OKAY;
}
@@ -354,6 +382,7 @@ static int realmode_inject_hw_exception(
struct realmode_emulate_ctxt *rm_ctxt =
container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
+ rm_ctxt->flags.exn_raised = 1;
realmode_deliver_exception(vector, 0, rm_ctxt);
return X86EMUL_OKAY;
@@ -383,6 +412,9 @@ static struct x86_emulate_ops realmode_emulator_ops = {
.write_io = realmode_write_io,
.read_cr = realmode_read_cr,
.write_rflags = realmode_write_rflags,
+ .wbinvd = realmode_wbinvd,
+ .cpuid = realmode_cpuid,
+ .hlt = realmode_hlt,
.inject_hw_exception = realmode_inject_hw_exception,
.inject_sw_interrupt = realmode_inject_sw_interrupt
};
@@ -393,6 +425,7 @@ int vmx_realmode(struct cpu_user_regs *regs)
struct realmode_emulate_ctxt rm_ctxt;
unsigned long intr_info;
int i, rc = 0;
+ u32 intr_shadow, new_intr_shadow;
rm_ctxt.ctxt.regs = regs;
@@ -411,6 +444,9 @@ int vmx_realmode(struct cpu_user_regs *regs)
realmode_deliver_exception((uint8_t)intr_info, 0, &rm_ctxt);
}
+ intr_shadow = __vmread(GUEST_INTERRUPTIBILITY_INFO);
+ new_intr_shadow = intr_shadow;
+
while ( !(curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE) &&
!softirq_pending(smp_processor_id()) &&
!hvm_local_events_need_delivery(curr) )
@@ -421,8 +457,35 @@ int vmx_realmode(struct cpu_user_regs *regs)
(uint32_t)(rm_ctxt.seg_reg[x86_seg_cs].base + regs->eip),
sizeof(rm_ctxt.insn_buf));
+ rm_ctxt.flag_word = 0;
+
rc = x86_emulate(&rm_ctxt.ctxt, &realmode_emulator_ops);
+ /* MOV-SS instruction toggles MOV-SS shadow, else we just clear it. */
+ if ( rm_ctxt.flags.mov_ss )
+ new_intr_shadow ^= VMX_INTR_SHADOW_MOV_SS;
+ else
+ new_intr_shadow &= ~VMX_INTR_SHADOW_MOV_SS;
+
+ /* STI instruction toggles STI shadow, else we just clear it. */
+ if ( rm_ctxt.flags.sti )
+ new_intr_shadow ^= VMX_INTR_SHADOW_STI;
+ else
+ new_intr_shadow &= ~VMX_INTR_SHADOW_STI;
+
+ /* Update interrupt shadow information in VMCS only if it changes. */
+ if ( intr_shadow != new_intr_shadow )
+ {
+ intr_shadow = new_intr_shadow;
+ __vmwrite(GUEST_INTERRUPTIBILITY_INFO, intr_shadow);
+ }
+
+ /* HLT happens after instruction retire, if no interrupt/exception. */
+ if ( unlikely(rm_ctxt.flags.hlt) &&
+ !rm_ctxt.flags.exn_raised &&
+ !hvm_local_events_need_delivery(curr) )
+ hvm_hlt(regs->eflags);
+
if ( curr->arch.hvm_vmx.real_mode_io_in_progress )
{
rc = 0;
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index b23e205f88..fd61b48823 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -1055,10 +1055,7 @@ static void vmx_update_guest_cr(struct vcpu *v, unsigned int cr)
v->arch.hvm_vcpu.hw_cr[0] =
v->arch.hvm_vcpu.guest_cr[0] |
- X86_CR0_NE | X86_CR0_PG | X86_CR0_WP;
-#ifdef VMXASSIST
- v->arch.hvm_vcpu.hw_cr[0] |= X86_CR0_PE;
-#endif
+ X86_CR0_NE | X86_CR0_PG | X86_CR0_WP | X86_CR0_PE;
__vmwrite(GUEST_CR0, v->arch.hvm_vcpu.hw_cr[0]);
__vmwrite(CR0_READ_SHADOW, v->arch.hvm_vcpu.guest_cr[0]);
break;
@@ -1254,10 +1251,11 @@ static void vmx_do_no_device_fault(void)
}
#define bitmaskof(idx) (1U << ((idx) & 31))
-static void vmx_do_cpuid(struct cpu_user_regs *regs)
+void vmx_cpuid_intercept(
+ unsigned int *eax, unsigned int *ebx,
+ unsigned int *ecx, unsigned int *edx)
{
- unsigned int input = regs->eax;
- unsigned int eax, ebx, ecx, edx;
+ unsigned int input = *eax;
#ifdef VMXASSIST
if ( input == 0x40000003 )
@@ -1266,7 +1264,7 @@ static void vmx_do_cpuid(struct cpu_user_regs *regs)
* NB. Unsupported interface for private use of VMXASSIST only.
* Note that this leaf lives at <max-hypervisor-leaf> + 1.
*/
- u64 value = ((u64)regs->edx << 32) | (u32)regs->ecx;
+ u64 value = ((u64)*edx << 32) | (u32)*ecx;
p2m_type_t p2mt;
unsigned long mfn;
struct vcpu *v = current;
@@ -1290,58 +1288,70 @@ static void vmx_do_cpuid(struct cpu_user_regs *regs)
unmap_domain_page(p);
gdprintk(XENLOG_INFO, "Output value is 0x%"PRIx64".\n", value);
- regs->ecx = (u32)value;
- regs->edx = (u32)(value >> 32);
+ *ecx = (u32)value;
+ *edx = (u32)(value >> 32);
return;
}
#endif
- hvm_cpuid(input, &eax, &ebx, &ecx, &edx);
+ hvm_cpuid(input, eax, ebx, ecx, edx);
switch ( input )
{
case 0x00000001:
- ecx &= ~VMX_VCPU_CPUID_L1_ECX_RESERVED;
- ebx &= NUM_THREADS_RESET_MASK;
- ecx &= ~(bitmaskof(X86_FEATURE_VMXE) |
- bitmaskof(X86_FEATURE_EST) |
- bitmaskof(X86_FEATURE_TM2) |
- bitmaskof(X86_FEATURE_CID) |
- bitmaskof(X86_FEATURE_PDCM) |
- bitmaskof(X86_FEATURE_DSCPL));
- edx &= ~(bitmaskof(X86_FEATURE_HT) |
- bitmaskof(X86_FEATURE_ACPI) |
- bitmaskof(X86_FEATURE_ACC) |
- bitmaskof(X86_FEATURE_DS));
+ *ecx &= ~VMX_VCPU_CPUID_L1_ECX_RESERVED;
+ *ebx &= NUM_THREADS_RESET_MASK;
+ *ecx &= ~(bitmaskof(X86_FEATURE_VMXE) |
+ bitmaskof(X86_FEATURE_EST) |
+ bitmaskof(X86_FEATURE_TM2) |
+ bitmaskof(X86_FEATURE_CID) |
+ bitmaskof(X86_FEATURE_PDCM) |
+ bitmaskof(X86_FEATURE_DSCPL));
+ *edx &= ~(bitmaskof(X86_FEATURE_HT) |
+ bitmaskof(X86_FEATURE_ACPI) |
+ bitmaskof(X86_FEATURE_ACC) |
+ bitmaskof(X86_FEATURE_DS));
break;
case 0x00000004:
- cpuid_count(input, regs->ecx, &eax, &ebx, &ecx, &edx);
- eax &= NUM_CORES_RESET_MASK;
+ cpuid_count(input, *ecx, eax, ebx, ecx, edx);
+ *eax &= NUM_CORES_RESET_MASK;
break;
case 0x00000006:
case 0x00000009:
case 0x0000000A:
- eax = ebx = ecx = edx = 0;
+ *eax = *ebx = *ecx = *edx = 0;
break;
case 0x80000001:
/* Only a few features are advertised in Intel's 0x80000001. */
- ecx &= (bitmaskof(X86_FEATURE_LAHF_LM));
- edx &= (bitmaskof(X86_FEATURE_NX) |
- bitmaskof(X86_FEATURE_LM) |
- bitmaskof(X86_FEATURE_SYSCALL));
+ *ecx &= (bitmaskof(X86_FEATURE_LAHF_LM));
+ *edx &= (bitmaskof(X86_FEATURE_NX) |
+ bitmaskof(X86_FEATURE_LM) |
+ bitmaskof(X86_FEATURE_SYSCALL));
break;
}
+ HVMTRACE_3D(CPUID, current, input,
+ ((uint64_t)*eax << 32) | *ebx, ((uint64_t)*ecx << 32) | *edx);
+}
+
+static void vmx_do_cpuid(struct cpu_user_regs *regs)
+{
+ unsigned int eax, ebx, ecx, edx;
+
+ eax = regs->eax;
+ ebx = regs->ebx;
+ ecx = regs->ecx;
+ edx = regs->edx;
+
+ vmx_cpuid_intercept(&eax, &ebx, &ecx, &edx);
+
regs->eax = eax;
regs->ebx = ebx;
regs->ecx = ecx;
regs->edx = edx;
-
- HVMTRACE_3D(CPUID, current, input,
- ((uint64_t)eax << 32) | ebx, ((uint64_t)ecx << 32) | edx);
}
#define CASE_GET_REG_P(REG, reg) \
@@ -2696,20 +2706,23 @@ static void wbinvd_ipi(void *info)
wbinvd();
}
+void vmx_wbinvd_intercept(void)
+{
+ if ( list_empty(&(domain_hvm_iommu(current->domain)->pdev_list)) )
+ return;
+
+ if ( cpu_has_wbinvd_exiting )
+ on_each_cpu(wbinvd_ipi, NULL, 1, 1);
+ else
+ wbinvd();
+}
+
static void vmx_failed_vmentry(unsigned int exit_reason,
struct cpu_user_regs *regs)
{
unsigned int failed_vmentry_reason = (uint16_t)exit_reason;
unsigned long exit_qualification = __vmread(EXIT_QUALIFICATION);
-#ifndef VMXASSIST
- if ( (failed_vmentry_reason == EXIT_REASON_INVALID_GUEST_STATE) &&
- (exit_qualification == 0) &&
- !(current->arch.hvm_vcpu.hw_cr[0] & X86_CR0_PE) &&
- (vmx_realmode(regs) == 0) )
- return;
-#endif
-
printk("Failed vm entry (exit reason 0x%x) ", exit_reason);
switch ( failed_vmentry_reason )
{
@@ -2976,24 +2989,7 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs)
{
inst_len = __get_instruction_length(); /* Safe: INVD, WBINVD */
__update_guest_eip(inst_len);
- if ( !list_empty(&(domain_hvm_iommu(v->domain)->pdev_list)) )
- {
- if ( cpu_has_wbinvd_exiting )
- {
- on_each_cpu(wbinvd_ipi, NULL, 1, 1);
- }
- else
- {
- wbinvd();
- /* Disable further WBINVD intercepts. */
- if ( (exit_reason == EXIT_REASON_WBINVD) &&
- (vmx_cpu_based_exec_control &
- CPU_BASED_ACTIVATE_SECONDARY_CONTROLS) )
- __vmwrite(SECONDARY_VM_EXEC_CONTROL,
- vmx_secondary_exec_control &
- ~SECONDARY_EXEC_WBINVD_EXITING);
- }
- }
+ vmx_wbinvd_intercept();
break;
}
diff --git a/xen/arch/x86/hvm/vmx/x86_32/exits.S b/xen/arch/x86/hvm/vmx/x86_32/exits.S
index 986900f1aa..ff0cd6f43c 100644
--- a/xen/arch/x86/hvm/vmx/x86_32/exits.S
+++ b/xen/arch/x86/hvm/vmx/x86_32/exits.S
@@ -103,7 +103,12 @@ ENTRY(vmx_asm_do_vmentry)
movl $GUEST_RFLAGS,%eax
VMWRITE(UREGS_eflags)
- cmpl $0,VCPU_vmx_launched(%ebx)
+#ifndef VMXASSIST
+ testb $X86_CR0_PE,VCPU_hvm_guest_cr0(%ebx)
+ jz vmx_goto_realmode
+#endif
+
+ cmpb $0,VCPU_vmx_launched(%ebx)
je vmx_launch
/*vmx_resume:*/
@@ -114,9 +119,19 @@ ENTRY(vmx_asm_do_vmentry)
ud2
vmx_launch:
- movl $1,VCPU_vmx_launched(%ebx)
+ movb $1,VCPU_vmx_launched(%ebx)
HVM_RESTORE_ALL_NOSEGREGS
VMLAUNCH
pushf
call vm_launch_fail
ud2
+
+#ifndef VMXASSIST
+vmx_goto_realmode:
+ sti
+ movl %esp,%eax
+ push %eax
+ call vmx_realmode
+ addl $4,%esp
+ jmp vmx_asm_do_vmentry
+#endif
diff --git a/xen/arch/x86/hvm/vmx/x86_64/exits.S b/xen/arch/x86/hvm/vmx/x86_64/exits.S
index d2cef88274..a54d7ef79c 100644
--- a/xen/arch/x86/hvm/vmx/x86_64/exits.S
+++ b/xen/arch/x86/hvm/vmx/x86_64/exits.S
@@ -121,7 +121,12 @@ ENTRY(vmx_asm_do_vmentry)
movl $GUEST_RFLAGS,%eax
VMWRITE(UREGS_eflags)
- cmpl $0,VCPU_vmx_launched(%rbx)
+#ifndef VMXASSIST
+ testb $X86_CR0_PE,VCPU_hvm_guest_cr0(%rbx)
+ jz vmx_goto_realmode
+#endif
+
+ cmpb $0,VCPU_vmx_launched(%rbx)
je vmx_launch
/*vmx_resume:*/
@@ -132,9 +137,17 @@ ENTRY(vmx_asm_do_vmentry)
ud2
vmx_launch:
- movl $1,VCPU_vmx_launched(%rbx)
+ movb $1,VCPU_vmx_launched(%rbx)
HVM_RESTORE_ALL_NOSEGREGS
VMLAUNCH
pushfq
call vm_launch_fail
ud2
+
+#ifndef VMXASSIST
+vmx_goto_realmode:
+ sti
+ movq %rsp,%rdi
+ call vmx_realmode
+ jmp vmx_asm_do_vmentry
+#endif
diff --git a/xen/arch/x86/x86_32/asm-offsets.c b/xen/arch/x86/x86_32/asm-offsets.c
index 92b25ad9a4..17beecc759 100644
--- a/xen/arch/x86/x86_32/asm-offsets.c
+++ b/xen/arch/x86/x86_32/asm-offsets.c
@@ -83,6 +83,7 @@ void __dummy__(void)
BLANK();
OFFSET(VCPU_vmx_launched, struct vcpu, arch.hvm_vmx.launched);
+ OFFSET(VCPU_hvm_guest_cr0, struct vcpu, arch.hvm_vcpu.guest_cr[0]);
OFFSET(VCPU_hvm_guest_cr2, struct vcpu, arch.hvm_vcpu.guest_cr[2]);
BLANK();
diff --git a/xen/arch/x86/x86_64/asm-offsets.c b/xen/arch/x86/x86_64/asm-offsets.c
index e91dbc1f51..ce92b848c9 100644
--- a/xen/arch/x86/x86_64/asm-offsets.c
+++ b/xen/arch/x86/x86_64/asm-offsets.c
@@ -98,6 +98,7 @@ void __dummy__(void)
BLANK();
OFFSET(VCPU_vmx_launched, struct vcpu, arch.hvm_vmx.launched);
+ OFFSET(VCPU_hvm_guest_cr0, struct vcpu, arch.hvm_vcpu.guest_cr[0]);
OFFSET(VCPU_hvm_guest_cr2, struct vcpu, arch.hvm_vcpu.guest_cr[2]);
BLANK();
diff --git a/xen/arch/x86/x86_emulate.c b/xen/arch/x86/x86_emulate.c
index b2ce122427..d6d849c14d 100644
--- a/xen/arch/x86/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate.c
@@ -167,7 +167,8 @@ static uint8_t opcode_table[256] = {
ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
/* 0xF0 - 0xF7 */
0, ImplicitOps, 0, 0,
- 0, ImplicitOps, ByteOp|DstMem|SrcNone|ModRM, DstMem|SrcNone|ModRM,
+ ImplicitOps, ImplicitOps,
+ ByteOp|DstMem|SrcNone|ModRM, DstMem|SrcNone|ModRM,
/* 0xF8 - 0xFF */
ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
ImplicitOps, ImplicitOps, ByteOp|DstMem|SrcNone|ModRM, DstMem|SrcNone|ModRM
@@ -225,7 +226,8 @@ static uint8_t twobyte_table[256] = {
ByteOp|DstMem|SrcNone|ModRM|Mov, ByteOp|DstMem|SrcNone|ModRM|Mov,
ByteOp|DstMem|SrcNone|ModRM|Mov, ByteOp|DstMem|SrcNone|ModRM|Mov,
/* 0xA0 - 0xA7 */
- ImplicitOps, ImplicitOps, 0, DstBitBase|SrcReg|ModRM, 0, 0, 0, 0,
+ ImplicitOps, ImplicitOps, ImplicitOps, DstBitBase|SrcReg|ModRM,
+ 0, 0, 0, 0,
/* 0xA8 - 0xAF */
ImplicitOps, ImplicitOps, 0, DstBitBase|SrcReg|ModRM,
0, 0, 0, DstReg|SrcMem|ModRM,
@@ -2450,6 +2452,12 @@ x86_emulate(
src.val = EXC_DB;
goto swint;
+ case 0xf4: /* hlt */
+ fail_if(ops->hlt == NULL);
+ if ( (rc = ops->hlt(ctxt)) != 0 )
+ goto done;
+ break;
+
case 0xf5: /* cmc */
_regs.eflags ^= EFLG_CF;
break;
@@ -2783,6 +2791,17 @@ x86_emulate(
src.val = x86_seg_fs;
goto pop_seg;
+ case 0xa2: /* cpuid */ {
+ unsigned int eax = _regs.eax, ebx = _regs.ebx;
+ unsigned int ecx = _regs.ecx, edx = _regs.edx;
+ fail_if(ops->cpuid == NULL);
+ if ( (rc = ops->cpuid(&eax, &ebx, &ecx, &edx, ctxt)) != 0 )
+ goto done;
+ _regs.eax = eax; _regs.ebx = ebx;
+ _regs.ecx = ecx; _regs.edx = edx;
+ break;
+ }
+
case 0xa8: /* push %%gs */
src.val = x86_seg_gs;
goto push_seg;
diff --git a/xen/include/asm-x86/hvm/vmx/vmx.h b/xen/include/asm-x86/hvm/vmx/vmx.h
index 4787226cd3..53ce887482 100644
--- a/xen/include/asm-x86/hvm/vmx/vmx.h
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h
@@ -33,6 +33,10 @@ void vmx_intr_assist(void);
void vmx_do_resume(struct vcpu *);
void set_guest_time(struct vcpu *v, u64 gtime);
void vmx_vlapic_msr_changed(struct vcpu *v);
+void vmx_cpuid_intercept(
+ unsigned int *eax, unsigned int *ebx,
+ unsigned int *ecx, unsigned int *edx);
+void vmx_wbinvd_intercept(void);
int vmx_realmode(struct cpu_user_regs *regs);
int vmx_realmode_io_complete(void);
diff --git a/xen/include/asm-x86/x86_emulate.h b/xen/include/asm-x86/x86_emulate.h
index eab9a513ae..2de071bd7f 100644
--- a/xen/include/asm-x86/x86_emulate.h
+++ b/xen/include/asm-x86/x86_emulate.h
@@ -275,6 +275,18 @@ struct x86_emulate_ops
int (*wbinvd)(
struct x86_emulate_ctxt *ctxt);
+ /* cpuid: Emulate CPUID via given set of EAX-EDX inputs/outputs. */
+ int (*cpuid)(
+ unsigned int *eax,
+ unsigned int *ebx,
+ unsigned int *ecx,
+ unsigned int *edx,
+ struct x86_emulate_ctxt *ctxt);
+
+ /* hlt: Emulate HLT. */
+ int (*hlt)(
+ struct x86_emulate_ctxt *ctxt);
+
/* inject_hw_exception */
int (*inject_hw_exception)(
uint8_t vector,