mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
x86/cpuid: Introduce guest_cpuid() and struct cpuid_leaf
Longterm, pv_cpuid() and hvm_cpuid() will be merged into a single
guest_cpuid(), which is also capable of working outside of current context.
To aid this transtion, introduce guest_cpuid() with the intended API, which
simply defers back to pv_cpuid() or hvm_cpuid() as appropriate.
Introduce struct cpuid_leaf which is used to represent the results of a CPUID
query in a more efficient mannor than passing four pointers through the
calltree.
Update all codepaths which should use the new guest_cpuid() API. These are
the codepaths which have variable inputs, and (other than some specific
x86_emulate() cases) all pertain to servicing a CPUID instruction from a
guest.
The other codepaths using {pv,hvm}_cpuid() with fixed inputs will later be
adjusted to read their data straight from the policy block.
No intended functional change.
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Paul Durrant <paul.durrant@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Reviewed-by: Kevin Tian <kevint.tian@intel.com>
This commit is contained in:
1 parent
ffc103c223
commit
e94ce53418
12 files changed
+136
-129
No files matched your search
@@ -41,22 +41,21 @@ bool emul_test_make_stack_executable(void)
|
||||
}
|
||||
|
||||
int emul_test_cpuid(
|
||||
unsigned int *eax,
|
||||
unsigned int *ebx,
|
||||
unsigned int *ecx,
|
||||
unsigned int *edx,
|
||||
uint32_t leaf,
|
||||
uint32_t subleaf,
|
||||
struct cpuid_leaf *res,
|
||||
struct x86_emulate_ctxt *ctxt)
|
||||
{
|
||||
unsigned int leaf = *eax;
|
||||
|
||||
asm ("cpuid" : "+a" (*eax), "+c" (*ecx), "=d" (*edx), "=b" (*ebx));
|
||||
asm ("cpuid"
|
||||
: "=a" (res->a), "=b" (res->b), "=c" (res->c), "=d" (res->d)
|
||||
: "a" (leaf), "c" (subleaf));
|
||||
|
||||
/*
|
||||
* The emulator doesn't itself use MOVBE, so we can always run the
|
||||
* respective tests.
|
||||
*/
|
||||
if ( leaf == 1 )
|
||||
*ecx |= 1U << 22;
|
||||
res->c |= 1U << 22;
|
||||
|
||||
return X86EMUL_OKAY;
|
||||
}
|
||||
|
||||
@@ -58,61 +58,59 @@ static inline uint64_t xgetbv(uint32_t xcr)
|
||||
}
|
||||
|
||||
#define cache_line_size() ({ \
|
||||
unsigned int eax = 1, ebx, ecx = 0, edx; \
|
||||
emul_test_cpuid(&eax, &ebx, &ecx, &edx, NULL); \
|
||||
edx & (1U << 19) ? (ebx >> 5) & 0x7f8 : 0; \
|
||||
struct cpuid_leaf res; \
|
||||
emul_test_cpuid(1, 0, &res, NULL); \
|
||||
res.d & (1U << 19) ? (res.b >> 5) & 0x7f8 : 0; \
|
||||
})
|
||||
|
||||
#define cpu_has_mmx ({ \
|
||||
unsigned int eax = 1, ecx = 0, edx; \
|
||||
emul_test_cpuid(&eax, &ecx, &ecx, &edx, NULL); \
|
||||
(edx & (1U << 23)) != 0; \
|
||||
struct cpuid_leaf res; \
|
||||
emul_test_cpuid(1, 0, &res, NULL); \
|
||||
(res.d & (1U << 23)) != 0; \
|
||||
})
|
||||
|
||||
#define cpu_has_sse ({ \
|
||||
unsigned int eax = 1, ecx = 0, edx; \
|
||||
emul_test_cpuid(&eax, &ecx, &ecx, &edx, NULL); \
|
||||
(edx & (1U << 25)) != 0; \
|
||||
struct cpuid_leaf res; \
|
||||
emul_test_cpuid(1, 0, &res, NULL); \
|
||||
(res.d & (1U << 25)) != 0; \
|
||||
})
|
||||
|
||||
#define cpu_has_sse2 ({ \
|
||||
unsigned int eax = 1, ecx = 0, edx; \
|
||||
emul_test_cpuid(&eax, &ecx, &ecx, &edx, NULL); \
|
||||
(edx & (1U << 26)) != 0; \
|
||||
struct cpuid_leaf res; \
|
||||
emul_test_cpuid(1, 0, &res, NULL); \
|
||||
(res.d & (1U << 26)) != 0; \
|
||||
})
|
||||
|
||||
#define cpu_has_xsave ({ \
|
||||
unsigned int eax = 1, ecx = 0; \
|
||||
emul_test_cpuid(&eax, &eax, &ecx, &eax, NULL); \
|
||||
struct cpuid_leaf res; \
|
||||
emul_test_cpuid(1, 0, &res, NULL); \
|
||||
/* Intentionally checking OSXSAVE here. */ \
|
||||
(ecx & (1U << 27)) != 0; \
|
||||
(res.c & (1U << 27)) != 0; \
|
||||
})
|
||||
|
||||
#define cpu_has_avx ({ \
|
||||
unsigned int eax = 1, ecx = 0; \
|
||||
emul_test_cpuid(&eax, &eax, &ecx, &eax, NULL); \
|
||||
if ( !(ecx & (1U << 27)) || ((xgetbv(0) & 6) != 6) ) \
|
||||
ecx = 0; \
|
||||
(ecx & (1U << 28)) != 0; \
|
||||
struct cpuid_leaf res; \
|
||||
emul_test_cpuid(1, 0, &res, NULL); \
|
||||
if ( !(res.c & (1U << 27)) || ((xgetbv(0) & 6) != 6) ) \
|
||||
res.c = 0; \
|
||||
(res.c & (1U << 28)) != 0; \
|
||||
})
|
||||
|
||||
#define cpu_has_avx2 ({ \
|
||||
unsigned int eax = 1, ebx, ecx = 0; \
|
||||
emul_test_cpuid(&eax, &ebx, &ecx, &eax, NULL); \
|
||||
if ( !(ecx & (1U << 27)) || ((xgetbv(0) & 6) != 6) ) \
|
||||
ebx = 0; \
|
||||
struct cpuid_leaf res; \
|
||||
emul_test_cpuid(1, 0, &res, NULL); \
|
||||
if ( !(res.c & (1U << 27)) || ((xgetbv(0) & 6) != 6) ) \
|
||||
res.b = 0; \
|
||||
else { \
|
||||
eax = 7, ecx = 0; \
|
||||
emul_test_cpuid(&eax, &ebx, &ecx, &eax, NULL); \
|
||||
emul_test_cpuid(7, 0, &res, NULL); \
|
||||
} \
|
||||
(ebx & (1U << 5)) != 0; \
|
||||
(res.b & (1U << 5)) != 0; \
|
||||
})
|
||||
|
||||
int emul_test_cpuid(
|
||||
unsigned int *eax,
|
||||
unsigned int *ebx,
|
||||
unsigned int *ecx,
|
||||
unsigned int *edx,
|
||||
uint32_t leaf,
|
||||
uint32_t subleaf,
|
||||
struct cpuid_leaf *res,
|
||||
struct x86_emulate_ctxt *ctxt);
|
||||
|
||||
int emul_test_read_cr(
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <xen/init.h>
|
||||
#include <xen/lib.h>
|
||||
#include <xen/sched.h>
|
||||
#include <asm/cpuid.h>
|
||||
#include <asm/hvm/hvm.h>
|
||||
#include <asm/hvm/vmx/vmcs.h>
|
||||
@@ -17,6 +18,8 @@ uint32_t __read_mostly raw_featureset[FSCAPINTS];
|
||||
uint32_t __read_mostly pv_featureset[FSCAPINTS];
|
||||
uint32_t __read_mostly hvm_featureset[FSCAPINTS];
|
||||
|
||||
#define EMPTY_LEAF ((struct cpuid_leaf){})
|
||||
|
||||
static void __init sanitise_featureset(uint32_t *fs)
|
||||
{
|
||||
/* for_each_set_bit() uses unsigned longs. Extend with zeroes. */
|
||||
@@ -215,6 +218,38 @@ const uint32_t * __init lookup_deep_deps(uint32_t feature)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void guest_cpuid(const struct vcpu *v, uint32_t leaf,
|
||||
uint32_t subleaf, struct cpuid_leaf *res)
|
||||
{
|
||||
const struct domain *d = v->domain;
|
||||
|
||||
*res = EMPTY_LEAF;
|
||||
|
||||
/* {hvm,pv}_cpuid() have this expectation. */
|
||||
ASSERT(v == current);
|
||||
|
||||
if ( is_hvm_domain(d) )
|
||||
{
|
||||
res->c = subleaf;
|
||||
|
||||
hvm_cpuid(leaf, &res->a, &res->b, &res->c, &res->d);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct cpu_user_regs regs = *guest_cpu_user_regs();
|
||||
|
||||
regs._eax = leaf;
|
||||
regs._ecx = subleaf;
|
||||
|
||||
pv_cpuid(®s);
|
||||
|
||||
res->a = regs._eax;
|
||||
res->b = regs._ebx;
|
||||
res->c = regs._ecx;
|
||||
res->d = regs._edx;
|
||||
}
|
||||
}
|
||||
|
||||
static void __init __maybe_unused build_assertions(void)
|
||||
{
|
||||
BUILD_BUG_ON(ARRAY_SIZE(known_features) != FSCAPINTS);
|
||||
|
||||
@@ -1552,12 +1552,8 @@ static int hvmemul_wbinvd(
|
||||
return X86EMUL_OKAY;
|
||||
}
|
||||
|
||||
int hvmemul_cpuid(
|
||||
unsigned int *eax,
|
||||
unsigned int *ebx,
|
||||
unsigned int *ecx,
|
||||
unsigned int *edx,
|
||||
struct x86_emulate_ctxt *ctxt)
|
||||
int hvmemul_cpuid(uint32_t leaf, uint32_t subleaf,
|
||||
struct cpuid_leaf *res, struct x86_emulate_ctxt *ctxt)
|
||||
{
|
||||
/*
|
||||
* x86_emulate uses this function to query CPU features for its own internal
|
||||
@@ -1568,7 +1564,7 @@ int hvmemul_cpuid(
|
||||
hvm_check_cpuid_faulting(current) )
|
||||
return X86EMUL_EXCEPTION;
|
||||
|
||||
hvm_cpuid(*eax, eax, ebx, ecx, edx);
|
||||
guest_cpuid(current, leaf, subleaf, res);
|
||||
return X86EMUL_OKAY;
|
||||
}
|
||||
|
||||
|
||||
+10
-13
@@ -1572,23 +1572,20 @@ static void svm_fpu_dirty_intercept(void)
|
||||
|
||||
static void svm_vmexit_do_cpuid(struct cpu_user_regs *regs)
|
||||
{
|
||||
unsigned int eax, ebx, ecx, edx, inst_len;
|
||||
struct vcpu *curr = current;
|
||||
unsigned int inst_len;
|
||||
struct cpuid_leaf res;
|
||||
|
||||
if ( (inst_len = __get_instruction_length(current, INSTR_CPUID)) == 0 )
|
||||
if ( (inst_len = __get_instruction_length(curr, INSTR_CPUID)) == 0 )
|
||||
return;
|
||||
|
||||
eax = regs->_eax;
|
||||
ebx = regs->_ebx;
|
||||
ecx = regs->_ecx;
|
||||
edx = regs->_edx;
|
||||
guest_cpuid(curr, regs->_eax, regs->_ecx, &res);
|
||||
HVMTRACE_5D(CPUID, regs->_eax, res.a, res.b, res.c, res.d);
|
||||
|
||||
hvm_cpuid(regs->_eax, &eax, &ebx, &ecx, &edx);
|
||||
HVMTRACE_5D(CPUID, regs->_eax, eax, ebx, ecx, edx);
|
||||
|
||||
regs->rax = eax;
|
||||
regs->rbx = ebx;
|
||||
regs->rcx = ecx;
|
||||
regs->rdx = edx;
|
||||
regs->rax = res.a;
|
||||
regs->rbx = res.b;
|
||||
regs->rcx = res.c;
|
||||
regs->rdx = res.d;
|
||||
|
||||
__update_guest_eip(regs, inst_len);
|
||||
}
|
||||
|
||||
+10
-25
@@ -2361,8 +2361,9 @@ static void vmx_fpu_dirty_intercept(void)
|
||||
|
||||
static int vmx_do_cpuid(struct cpu_user_regs *regs)
|
||||
{
|
||||
unsigned int eax, ebx, ecx, edx;
|
||||
unsigned int leaf, subleaf;
|
||||
struct vcpu *curr = current;
|
||||
uint32_t leaf = regs->_eax, subleaf = regs->_ecx;
|
||||
struct cpuid_leaf res;
|
||||
|
||||
if ( hvm_check_cpuid_faulting(current) )
|
||||
{
|
||||
@@ -2370,21 +2371,13 @@ static int vmx_do_cpuid(struct cpu_user_regs *regs)
|
||||
return 1; /* Don't advance the guest IP! */
|
||||
}
|
||||
|
||||
eax = regs->_eax;
|
||||
ebx = regs->_ebx;
|
||||
ecx = regs->_ecx;
|
||||
edx = regs->_edx;
|
||||
guest_cpuid(curr, leaf, subleaf, &res);
|
||||
HVMTRACE_5D(CPUID, leaf, res.a, res.b, res.c, res.d);
|
||||
|
||||
leaf = regs->_eax;
|
||||
subleaf = regs->_ecx;
|
||||
|
||||
hvm_cpuid(leaf, &eax, &ebx, &ecx, &edx);
|
||||
HVMTRACE_5D(CPUID, leaf, eax, ebx, ecx, edx);
|
||||
|
||||
regs->rax = eax;
|
||||
regs->rbx = ebx;
|
||||
regs->rcx = ecx;
|
||||
regs->rdx = edx;
|
||||
regs->rax = res.a;
|
||||
regs->rbx = res.b;
|
||||
regs->rcx = res.c;
|
||||
regs->rdx = res.d;
|
||||
|
||||
return hvm_monitor_cpuid(get_instruction_length(), leaf, subleaf);
|
||||
}
|
||||
@@ -3559,15 +3552,7 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs)
|
||||
}
|
||||
case EXIT_REASON_CPUID:
|
||||
{
|
||||
int rc;
|
||||
|
||||
if ( is_pvh_vcpu(v) )
|
||||
{
|
||||
pv_cpuid(regs);
|
||||
rc = 0;
|
||||
}
|
||||
else
|
||||
rc = vmx_do_cpuid(regs);
|
||||
int rc = vmx_do_cpuid(regs);
|
||||
|
||||
/*
|
||||
* rc < 0 error in monitor/vm_event, crash
|
||||
|
||||
+11
-14
@@ -1412,6 +1412,7 @@ static int emulate_forced_invalid_op(struct cpu_user_regs *regs)
|
||||
{
|
||||
char sig[5], instr[2];
|
||||
unsigned long eip, rc;
|
||||
struct cpuid_leaf res;
|
||||
|
||||
eip = regs->rip;
|
||||
|
||||
@@ -1444,7 +1445,12 @@ static int emulate_forced_invalid_op(struct cpu_user_regs *regs)
|
||||
|
||||
eip += sizeof(instr);
|
||||
|
||||
pv_cpuid(regs);
|
||||
guest_cpuid(current, regs->_eax, regs->_ecx, &res);
|
||||
|
||||
regs->rax = res.a;
|
||||
regs->rbx = res.b;
|
||||
regs->rcx = res.c;
|
||||
regs->rdx = res.d;
|
||||
|
||||
instruction_done(regs, eip);
|
||||
|
||||
@@ -3254,10 +3260,10 @@ static int priv_op_wbinvd(struct x86_emulate_ctxt *ctxt)
|
||||
return X86EMUL_OKAY;
|
||||
}
|
||||
|
||||
int pv_emul_cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx,
|
||||
unsigned int *edx, struct x86_emulate_ctxt *ctxt)
|
||||
int pv_emul_cpuid(uint32_t leaf, uint32_t subleaf,
|
||||
struct cpuid_leaf *res, struct x86_emulate_ctxt *ctxt)
|
||||
{
|
||||
struct cpu_user_regs regs = *ctxt->regs;
|
||||
const struct vcpu *curr = current;
|
||||
|
||||
/*
|
||||
* x86_emulate uses this function to query CPU features for its own
|
||||
@@ -3266,7 +3272,6 @@ int pv_emul_cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx,
|
||||
*/
|
||||
if ( ctxt->opcode == X86EMUL_OPC(0x0f, 0xa2) )
|
||||
{
|
||||
const struct vcpu *curr = current;
|
||||
|
||||
/* If cpuid faulting is enabled and CPL>0 leave the #GP untouched. */
|
||||
if ( curr->arch.cpuid_faulting &&
|
||||
@@ -3274,15 +3279,7 @@ int pv_emul_cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx,
|
||||
return X86EMUL_EXCEPTION;
|
||||
}
|
||||
|
||||
regs._eax = *eax;
|
||||
regs._ecx = *ecx;
|
||||
|
||||
pv_cpuid(®s);
|
||||
|
||||
*eax = regs._eax;
|
||||
*ebx = regs._ebx;
|
||||
*ecx = regs._ecx;
|
||||
*edx = regs._edx;
|
||||
guest_cpuid(curr, leaf, subleaf, res);
|
||||
|
||||
return X86EMUL_OKAY;
|
||||
}
|
||||
|
||||
@@ -1265,19 +1265,19 @@ static bool vcpu_has(
|
||||
struct x86_emulate_ctxt *ctxt,
|
||||
const struct x86_emulate_ops *ops)
|
||||
{
|
||||
unsigned int ebx = 0, ecx = 0, edx = 0;
|
||||
struct cpuid_leaf res;
|
||||
int rc = X86EMUL_OKAY;
|
||||
|
||||
fail_if(!ops->cpuid);
|
||||
rc = ops->cpuid(&eax, &ebx, &ecx, &edx, ctxt);
|
||||
rc = ops->cpuid(eax, 0, &res, ctxt);
|
||||
if ( rc == X86EMUL_OKAY )
|
||||
{
|
||||
switch ( reg )
|
||||
{
|
||||
case EAX: reg = eax; break;
|
||||
case EBX: reg = ebx; break;
|
||||
case ECX: reg = ecx; break;
|
||||
case EDX: reg = edx; break;
|
||||
case EAX: reg = res.a; break;
|
||||
case EBX: reg = res.b; break;
|
||||
case ECX: reg = res.c; break;
|
||||
case EDX: reg = res.d; break;
|
||||
default: BUG();
|
||||
}
|
||||
if ( !(reg & (1U << bit)) )
|
||||
@@ -2722,6 +2722,7 @@ x86_emulate(
|
||||
{
|
||||
enum x86_segment seg;
|
||||
struct segment_register cs, sreg;
|
||||
struct cpuid_leaf cpuid_leaf;
|
||||
|
||||
case 0x00 ... 0x05: add: /* add */
|
||||
emulate_2op_SrcV("add", src, dst, _regs._eflags);
|
||||
@@ -4525,15 +4526,14 @@ x86_emulate(
|
||||
|
||||
case 0xfc: /* clzero */
|
||||
{
|
||||
unsigned int eax = 1, ebx = 0, dummy = 0;
|
||||
unsigned long zero = 0;
|
||||
|
||||
base = ad_bytes == 8 ? _regs.r(ax) :
|
||||
ad_bytes == 4 ? _regs._eax : _regs.ax;
|
||||
limit = 0;
|
||||
if ( vcpu_has_clflush() &&
|
||||
ops->cpuid(&eax, &ebx, &dummy, &dummy, ctxt) == X86EMUL_OKAY )
|
||||
limit = ((ebx >> 8) & 0xff) * 8;
|
||||
ops->cpuid(1, 0, &cpuid_leaf, ctxt) == X86EMUL_OKAY )
|
||||
limit = ((cpuid_leaf.b >> 8) & 0xff) * 8;
|
||||
generate_exception_if(limit < sizeof(long) ||
|
||||
(limit & (limit - 1)), EXC_UD);
|
||||
base &= ~(limit - 1);
|
||||
@@ -5265,22 +5265,18 @@ x86_emulate(
|
||||
dst.val = test_cc(b, _regs._eflags);
|
||||
break;
|
||||
|
||||
case X86EMUL_OPC(0x0f, 0xa2): /* cpuid */ {
|
||||
unsigned int eax = _regs._eax, ebx = _regs._ebx;
|
||||
unsigned int ecx = _regs._ecx, edx = _regs._edx;
|
||||
|
||||
case X86EMUL_OPC(0x0f, 0xa2): /* cpuid */
|
||||
fail_if(ops->cpuid == NULL);
|
||||
rc = ops->cpuid(&eax, &ebx, &ecx, &edx, ctxt);
|
||||
rc = ops->cpuid(_regs._eax, _regs._ecx, &cpuid_leaf, ctxt);
|
||||
generate_exception_if(rc == X86EMUL_EXCEPTION,
|
||||
EXC_GP, 0); /* CPUID Faulting? */
|
||||
if ( rc != X86EMUL_OKAY )
|
||||
goto done;
|
||||
_regs.r(ax) = eax;
|
||||
_regs.r(bx) = ebx;
|
||||
_regs.r(cx) = ecx;
|
||||
_regs.r(dx) = edx;
|
||||
_regs.r(ax) = cpuid_leaf.a;
|
||||
_regs.r(bx) = cpuid_leaf.b;
|
||||
_regs.r(cx) = cpuid_leaf.c;
|
||||
_regs.r(dx) = cpuid_leaf.d;
|
||||
break;
|
||||
}
|
||||
|
||||
case X86EMUL_OPC(0x0f, 0xa3): bt: /* bt */
|
||||
emulate_2op_SrcV_nobyte("bt", src, dst, _regs._eflags);
|
||||
|
||||
@@ -164,6 +164,11 @@ enum x86_emulate_fpu_type {
|
||||
X86EMUL_FPU_ymm /* AVX/XOP instruction set (%ymm0-%ymm7/15) */
|
||||
};
|
||||
|
||||
struct cpuid_leaf
|
||||
{
|
||||
uint32_t a, b, c, d;
|
||||
};
|
||||
|
||||
struct x86_emulate_state;
|
||||
|
||||
/*
|
||||
@@ -415,10 +420,9 @@ struct x86_emulate_ops
|
||||
* #GP[0]. Used to implement CPUID faulting.
|
||||
*/
|
||||
int (*cpuid)(
|
||||
unsigned int *eax,
|
||||
unsigned int *ebx,
|
||||
unsigned int *ecx,
|
||||
unsigned int *edx,
|
||||
uint32_t leaf,
|
||||
uint32_t subleaf,
|
||||
struct cpuid_leaf *res,
|
||||
struct x86_emulate_ctxt *ctxt);
|
||||
|
||||
/*
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#include <xen/types.h>
|
||||
#include <asm/x86_emulate.h>
|
||||
#include <public/sysctl.h>
|
||||
|
||||
extern const uint32_t known_features[FSCAPINTS];
|
||||
@@ -64,6 +65,9 @@ extern struct cpuidmasks cpuidmask_defaults;
|
||||
/* Whether or not cpuid faulting is available for the current domain. */
|
||||
DECLARE_PER_CPU(bool, cpuid_faulting_enabled);
|
||||
|
||||
void guest_cpuid(const struct vcpu *v, uint32_t leaf,
|
||||
uint32_t subleaf, struct cpuid_leaf *res);
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* !__X86_CPUID_H__ */
|
||||
|
||||
|
||||
@@ -57,12 +57,8 @@ void hvm_emulate_init_per_insn(
|
||||
unsigned int insn_bytes);
|
||||
void hvm_emulate_writeback(
|
||||
struct hvm_emulate_ctxt *hvmemul_ctxt);
|
||||
int hvmemul_cpuid(
|
||||
unsigned int *eax,
|
||||
unsigned int *ebx,
|
||||
unsigned int *ecx,
|
||||
unsigned int *edx,
|
||||
struct x86_emulate_ctxt *ctxt);
|
||||
int hvmemul_cpuid(uint32_t leaf, uint32_t subleaf,
|
||||
struct cpuid_leaf *res, struct x86_emulate_ctxt *ctxt);
|
||||
struct segment_register *hvmemul_get_seg_reg(
|
||||
enum x86_segment seg,
|
||||
struct hvm_emulate_ctxt *hvmemul_ctxt);
|
||||
|
||||
@@ -504,8 +504,8 @@ extern int mmcfg_intercept_write(enum x86_segment seg,
|
||||
void *p_data,
|
||||
unsigned int bytes,
|
||||
struct x86_emulate_ctxt *ctxt);
|
||||
int pv_emul_cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx,
|
||||
unsigned int *edx, struct x86_emulate_ctxt *ctxt);
|
||||
int pv_emul_cpuid(uint32_t leaf, uint32_t subleaf,
|
||||
struct cpuid_leaf *res, struct x86_emulate_ctxt *ctxt);
|
||||
|
||||
int ptwr_do_page_fault(struct vcpu *, unsigned long,
|
||||
struct cpu_user_regs *);
|
||||
|
||||