hvm_check_cpuid_faulting(current) )
return X86EMUL_EXCEPTION;
- hvm_funcs.cpuid_intercept(eax, ebx, ecx, edx);
+ hvm_cpuid(*eax, eax, ebx, ecx, edx);
return X86EMUL_OKAY;
}
ASSERT(v->domain == current->domain);
hvm_cpuid(0x80000000, &level, NULL, NULL, NULL);
if ( (level >> 16) == 0x8000 && level > 0x80000000 )
- {
- unsigned int dummy;
-
- level = 0x80000001;
- hvm_funcs.cpuid_intercept(&level, &dummy, &ext1_ecx, &ext1_edx);
- }
+ hvm_cpuid(0x80000001, NULL, NULL, &ext1_ecx, &ext1_edx);
}
else
{
if ( !(hvm_pae_enabled(v) || hvm_long_mode_enabled(v)) )
*edx &= ~cpufeat_mask(X86_FEATURE_PSE36);
}
+
+ /* SYSCALL is hidden outside of long mode on Intel. */
+ if ( d->arch.x86_vendor == X86_VENDOR_INTEL &&
+ !hvm_long_mode_enabled(v))
+ *edx &= ~cpufeat_mask(X86_FEATURE_SYSCALL);
+
break;
case 0x80000007:
*ebx &= hvm_featureset[FEATURESET_e8b];
break;
+
+ case 0x8000001c:
+ if ( !cpu_has_svm )
+ {
+ *eax = *ebx = *ecx = *edx = 0;
+ break;
+ }
+
+ if ( cpu_has_lwp && (v->arch.xcr0 & XSTATE_LWP) )
+ /* Turn on available bit and other features specified in lwp_cfg. */
+ *eax = (*edx & v->arch.hvm_svm.guest_lwp_cfg) | 1;
+ else
+ *eax = 0;
+ break;
}
}
vmcb_set_cr0(vmcb, vmcb_get_cr0(vmcb) & ~X86_CR0_TS);
}
-static void svm_cpuid_intercept(
- unsigned int *eax, unsigned int *ebx,
- unsigned int *ecx, unsigned int *edx)
-{
- unsigned int input = *eax;
- struct vcpu *v = current;
-
- hvm_cpuid(input, eax, ebx, ecx, edx);
-
- switch (input) {
- case 0x8000001c:
- {
- /* LWP capability CPUID */
- uint64_t lwp_cfg = v->arch.hvm_svm.guest_lwp_cfg;
-
- if ( cpu_has_lwp )
- {
- if ( !(v->arch.xcr0 & XSTATE_LWP) )
- {
- *eax = 0x0;
- break;
- }
-
- /* turn on available bit and other features specified in lwp_cfg */
- *eax = (*edx & lwp_cfg) | 0x00000001;
- }
- break;
- }
- default:
- break;
- }
-
- HVMTRACE_5D (CPUID, input, *eax, *ebx, *ecx, *edx);
-}
-
static void svm_vmexit_do_cpuid(struct cpu_user_regs *regs)
{
unsigned int eax, ebx, ecx, edx, inst_len;
ecx = regs->ecx;
edx = regs->edx;
- svm_cpuid_intercept(&eax, &ebx, &ecx, &edx);
+ hvm_cpuid(regs->_eax, &eax, &ebx, &ecx, &edx);
+ HVMTRACE_5D(CPUID, regs->_eax, eax, ebx, ecx, edx);
regs->eax = eax;
regs->ebx = ebx;
.init_hypercall_page = svm_init_hypercall_page,
.event_pending = svm_event_pending,
.invlpg = svm_invlpg,
- .cpuid_intercept = svm_cpuid_intercept,
.wbinvd_intercept = svm_wbinvd_intercept,
.fpu_dirty_intercept = svm_fpu_dirty_intercept,
.msr_read_intercept = svm_msr_read_intercept,
static void vmx_update_guest_cr(struct vcpu *v, unsigned int cr);
static void vmx_update_guest_efer(struct vcpu *v);
static void vmx_update_guest_vendor(struct vcpu *v);
-static void vmx_cpuid_intercept(
- unsigned int *eax, unsigned int *ebx,
- unsigned int *ecx, unsigned int *edx);
static void vmx_wbinvd_intercept(void);
static void vmx_fpu_dirty_intercept(void);
static int vmx_msr_read_intercept(unsigned int msr, uint64_t *msr_content);
.invlpg = vmx_invlpg,
.cpu_up = vmx_cpu_up,
.cpu_down = vmx_cpu_down,
- .cpuid_intercept = vmx_cpuid_intercept,
.wbinvd_intercept = vmx_wbinvd_intercept,
.fpu_dirty_intercept = vmx_fpu_dirty_intercept,
.msr_read_intercept = vmx_msr_read_intercept,
}
}
-static void vmx_cpuid_intercept(
- unsigned int *eax, unsigned int *ebx,
- unsigned int *ecx, unsigned int *edx)
-{
- unsigned int input = *eax;
- struct vcpu *v = current;
-
- hvm_cpuid(input, eax, ebx, ecx, edx);
-
- switch ( input )
- {
- case 0x80000001:
- /* SYSCALL is visible iff running in long mode. */
- if ( hvm_long_mode_enabled(v) )
- *edx |= cpufeat_mask(X86_FEATURE_SYSCALL);
- else
- *edx &= ~(cpufeat_mask(X86_FEATURE_SYSCALL));
-
- break;
- }
-
- HVMTRACE_5D (CPUID, input, *eax, *ebx, *ecx, *edx);
-}
-
static int vmx_do_cpuid(struct cpu_user_regs *regs)
{
unsigned int eax, ebx, ecx, edx;
leaf = regs->eax;
subleaf = regs->ecx;
- vmx_cpuid_intercept(&eax, &ebx, &ecx, &edx);
+ hvm_cpuid(leaf, &eax, &ebx, &ecx, &edx);
+ HVMTRACE_5D(CPUID, leaf, eax, ebx, ecx, edx);
regs->eax = eax;
regs->ebx = ebx;
unsigned int (*get_insn_bytes)(struct vcpu *v, uint8_t *buf);
/* Instruction intercepts: non-void return values are X86EMUL codes. */
- void (*cpuid_intercept)(
- unsigned int *eax, unsigned int *ebx,
- unsigned int *ecx, unsigned int *edx);
void (*wbinvd_intercept)(void);
void (*fpu_dirty_intercept)(void);
int (*msr_read_intercept)(unsigned int msr, uint64_t *msr_content);