vcpu: add get/set register APIs

there will be 3 types of vcpu runtime contexts:
- runtime contexts always saved/restored during VM exit/entry, which
  include general registers rax/rcx/rdx/rbx/rbp/rsi/rdi/r8~r15, cr2 and
  msr for spectre control (ia32_spec_ctrl)
- runtime contexts on-demand cached/updated during VM exit/entry, which
  include frequently used registers rsp, rip, efer, rflags, cr0 and cr4
- runtime contexts always read/write from/to VMCS, which include left
  registers not in above

this patch add get/set register APIs for vcpu runtime contexts, and unified
the save/restore method for them according to above description.

v3:
- update vcpu_get/set_cr0/4 as unified interface to get/set guest cr0/cr4,
  use on-demand cache for reading, but always write to VMCS for writing.

v2:
- use reg_cached/reg_updated for on-demand runtime contexts
- always read/write cr3 from/to VMCS

Signed-off-by: Jason Chen CJ <jason.cj.chen@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Jason Chen CJ 2018-07-26 14:56:47 +08:00 committed by lijinxia
parent 5aa1ad3bfc
commit 3d5d6c96ec
20 changed files with 408 additions and 325 deletions

View File

@ -110,8 +110,6 @@ inline bool vm_lapic_disabled(struct vm *vm)
enum vm_paging_mode get_vcpu_paging_mode(struct vcpu *vcpu)
{
struct run_context *cur_context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
enum vm_cpu_mode cpu_mode;
cpu_mode = get_vcpu_mode(vcpu);
@ -120,10 +118,10 @@ enum vm_paging_mode get_vcpu_paging_mode(struct vcpu *vcpu)
return PAGING_MODE_0_LEVEL;
}
else if (cpu_mode == CPU_MODE_PROTECTED) {
if ((cur_context->cr4 & CR4_PAE) != 0U) {
if ((vcpu_get_cr4(vcpu) & CR4_PAE) != 0U) {
return PAGING_MODE_3_LEVEL;
}
else if ((cur_context->cr0 & CR0_PG) != 0U) {
else if ((vcpu_get_cr0(vcpu) & CR0_PG) != 0U) {
return PAGING_MODE_2_LEVEL;
}
return PAGING_MODE_0_LEVEL;
@ -273,8 +271,6 @@ out:
int gva2gpa(struct vcpu *vcpu, uint64_t gva, uint64_t *gpa,
uint32_t *err_code)
{
struct run_context *cur_context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
enum vm_paging_mode pm = get_vcpu_paging_mode(vcpu);
struct page_walk_info pw_info;
int ret = 0;
@ -284,15 +280,14 @@ int gva2gpa(struct vcpu *vcpu, uint64_t gva, uint64_t *gpa,
}
*gpa = 0UL;
pw_info.top_entry = cur_context->cr3;
pw_info.top_entry = exec_vmread(VMX_GUEST_CR3);
pw_info.level = pm;
pw_info.is_write_access = ((*err_code & PAGE_FAULT_WR_FLAG) != 0U);
pw_info.is_inst_fetch = ((*err_code & PAGE_FAULT_ID_FLAG) != 0U);
pw_info.is_user_mode = ((exec_vmread16(VMX_GUEST_CS_SEL) & 0x3U) == 3U);
pw_info.pse = true;
pw_info.nxe =
((cur_context->ia32_efer & MSR_IA32_EFER_NXE_BIT) != 0UL);
pw_info.wp = ((cur_context->cr0 & CR0_WP) != 0UL);
pw_info.nxe = ((vcpu_get_efer(vcpu) & MSR_IA32_EFER_NXE_BIT) != 0UL);
pw_info.wp = ((vcpu_get_cr0(vcpu) & CR0_WP) != 0UL);
*err_code &= ~PAGE_FAULT_P_FLAG;
@ -304,7 +299,7 @@ int gva2gpa(struct vcpu *vcpu, uint64_t gva, uint64_t *gpa,
ret = local_gva2gpa_pae(vcpu, &pw_info, gva, gpa, err_code);
} else if (pm == PAGING_MODE_2_LEVEL) {
pw_info.width = 10U;
pw_info.pse = ((cur_context->cr4 & CR4_PSE) != 0UL);
pw_info.pse = ((vcpu_get_cr4(vcpu) & CR4_PSE) != 0UL);
pw_info.nxe = false;
ret = local_gva2gpa_common(vcpu, &pw_info, gva, gpa, err_code);
} else {

View File

@ -1643,8 +1643,7 @@ vie_calculate_gla(enum vm_cpu_mode cpu_mode, enum cpu_reg_name seg,
int
vie_init(struct instr_emul_vie *vie, struct vcpu *vcpu)
{
uint64_t guest_rip_gva =
vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].rip;
uint64_t guest_rip_gva = vcpu_get_rip(vcpu);
uint32_t inst_len = vcpu->arch_vcpu.inst_len;
uint32_t err_code;
int ret;

View File

@ -26,8 +26,6 @@ is_descriptor_table(enum cpu_reg_name reg);
int vm_get_register(struct vcpu *vcpu, enum cpu_reg_name reg, uint64_t *retval)
{
struct run_context *cur_context;
if (vcpu == NULL) {
return -EINVAL;
}
@ -37,10 +35,9 @@ int vm_get_register(struct vcpu *vcpu, enum cpu_reg_name reg, uint64_t *retval)
}
if ((reg >= CPU_REG_GENERAL_FIRST) && (reg <= CPU_REG_GENERAL_LAST)) {
cur_context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
*retval = cur_context->guest_cpu_regs.longs[reg];
} else if ((reg >= CPU_REG_NONGENERAL_FIRST) && (reg <= CPU_REG_NONGENERAL_LAST)) {
*retval = vcpu_get_gpreg(vcpu, reg);
} else if ((reg >= CPU_REG_NONGENERAL_FIRST) &&
(reg <= CPU_REG_NONGENERAL_LAST)) {
uint32_t field = get_vmcs_field(reg);
if (field != VMX_INVALID_VMCS_FIELD) {
@ -61,8 +58,6 @@ int vm_get_register(struct vcpu *vcpu, enum cpu_reg_name reg, uint64_t *retval)
int vm_set_register(struct vcpu *vcpu, enum cpu_reg_name reg, uint64_t val)
{
struct run_context *cur_context;
if (vcpu == NULL) {
return -EINVAL;
}
@ -72,10 +67,9 @@ int vm_set_register(struct vcpu *vcpu, enum cpu_reg_name reg, uint64_t val)
}
if ((reg >= CPU_REG_GENERAL_FIRST) && (reg <= CPU_REG_GENERAL_LAST)) {
cur_context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
cur_context->guest_cpu_regs.longs[reg] = val;
} else if ((reg >= CPU_REG_NONGENERAL_FIRST) && (reg <= CPU_REG_NONGENERAL_LAST)) {
vcpu_set_gpreg(vcpu, reg, val);
} else if ((reg >= CPU_REG_NONGENERAL_FIRST) &&
(reg <= CPU_REG_NONGENERAL_LAST)) {
uint32_t field = get_vmcs_field(reg);
if (field != VMX_INVALID_VMCS_FIELD) {
@ -305,8 +299,7 @@ static void get_guest_paging_info(struct vcpu *vcpu, struct instr_emul_ctxt *emu
ASSERT(emul_ctxt != NULL && vcpu != NULL, "Error in input arguments");
cpl = (uint8_t)((csar >> 5) & 3U);
emul_ctxt->paging.cr3 =
vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].cr3;
emul_ctxt->paging.cr3 = exec_vmread(VMX_GUEST_CR3);
emul_ctxt->paging.cpl = cpl;
emul_ctxt->paging.cpu_mode = get_vcpu_mode(vcpu);
emul_ctxt->paging.paging_mode = get_vcpu_paging_mode(vcpu);
@ -348,8 +341,7 @@ int decode_instruction(struct vcpu *vcpu)
if (retval < 0) {
if (retval != -EFAULT) {
pr_err("decode instruction failed @ 0x%016llx:",
vcpu->arch_vcpu.
contexts[vcpu->arch_vcpu.cur_context].rip);
vcpu_get_rip(vcpu));
}
return retval;
}
@ -363,7 +355,7 @@ int decode_instruction(struct vcpu *vcpu)
if (retval != 0) {
pr_err("decode instruction failed @ 0x%016llx:",
vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].rip);
vcpu_get_rip(vcpu));
return -EINVAL;
}

View File

@ -31,65 +31,6 @@
#define INSTR_EMUL_WRAPPER_H
#include <cpu.h>
/**
*
* Identifiers for architecturally defined registers.
*
* These register names is used in condition statement.
* Within the following groups,register name need to be
* kept in order:
* General register names group (CPU_REG_RAX~CPU_REG_R15);
* Non general register names group (CPU_REG_CR0~CPU_REG_GDTR);
* Segement register names group (CPU_REG_ES~CPU_REG_GS).
*/
enum cpu_reg_name {
/* General purpose register layout should align with
* struct cpu_gp_regs
*/
CPU_REG_RAX,
CPU_REG_RCX,
CPU_REG_RDX,
CPU_REG_RBX,
CPU_REG_RSP,
CPU_REG_RBP,
CPU_REG_RSI,
CPU_REG_RDI,
CPU_REG_R8,
CPU_REG_R9,
CPU_REG_R10,
CPU_REG_R11,
CPU_REG_R12,
CPU_REG_R13,
CPU_REG_R14,
CPU_REG_R15,
CPU_REG_CR0,
CPU_REG_CR2,
CPU_REG_CR3,
CPU_REG_CR4,
CPU_REG_DR7,
CPU_REG_RIP,
CPU_REG_RFLAGS,
/*CPU_REG_NATURAL_LAST*/
CPU_REG_EFER,
CPU_REG_PDPTE0,
CPU_REG_PDPTE1,
CPU_REG_PDPTE2,
CPU_REG_PDPTE3,
/*CPU_REG_64BIT_LAST,*/
CPU_REG_ES,
CPU_REG_CS,
CPU_REG_SS,
CPU_REG_DS,
CPU_REG_FS,
CPU_REG_GS,
CPU_REG_LDTR,
CPU_REG_TR,
CPU_REG_IDTR,
CPU_REG_GDTR
/*CPU_REG_LAST*/
};
/**
* Define the following MACRO to make range checking clear.
*

View File

@ -14,6 +14,141 @@ extern struct efi_ctx* efi_ctx;
vm_sw_loader_t vm_sw_loader;
inline uint64_t vcpu_get_gpreg(struct vcpu *vcpu, uint32_t reg)
{
struct run_context *cur_context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
return cur_context->guest_cpu_regs.longs[reg];
}
inline void vcpu_set_gpreg(struct vcpu *vcpu, uint32_t reg, uint64_t val)
{
struct run_context *cur_context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
cur_context->guest_cpu_regs.longs[reg] = val;
}
inline uint64_t vcpu_get_rip(struct vcpu *vcpu)
{
if (bitmap_test(CPU_REG_RIP, &vcpu->reg_updated) == 0 &&
bitmap_test_and_set_lock(CPU_REG_RIP, &vcpu->reg_cached) == 0)
vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].rip =
exec_vmread(VMX_GUEST_RIP);
return vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].rip;
}
inline void vcpu_set_rip(struct vcpu *vcpu, uint64_t val)
{
vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].rip = val;
bitmap_set_lock(CPU_REG_RIP, &vcpu->reg_updated);
}
inline uint64_t vcpu_get_rsp(struct vcpu *vcpu)
{
struct run_context *cur_context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
return cur_context->guest_cpu_regs.regs.rsp;
}
inline void vcpu_set_rsp(struct vcpu *vcpu, uint64_t val)
{
struct run_context *cur_context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
cur_context->guest_cpu_regs.regs.rsp = val;
bitmap_set_lock(CPU_REG_RSP, &vcpu->reg_updated);
}
inline uint64_t vcpu_get_efer(struct vcpu *vcpu)
{
if (bitmap_test(CPU_REG_EFER, &vcpu->reg_updated) == 0 &&
bitmap_test_and_set_lock(CPU_REG_EFER, &vcpu->reg_cached) == 0)
vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].ia32_efer
= exec_vmread64(VMX_GUEST_IA32_EFER_FULL);
return vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].ia32_efer;
}
inline void vcpu_set_efer(struct vcpu *vcpu, uint64_t val)
{
vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].ia32_efer = val;
bitmap_set_lock(CPU_REG_EFER, &vcpu->reg_updated);
}
inline uint64_t vcpu_get_rflags(struct vcpu *vcpu)
{
if (bitmap_test(CPU_REG_RFLAGS, &vcpu->reg_updated) == 0 &&
bitmap_test_and_set_lock(CPU_REG_RFLAGS,
&vcpu->reg_cached) == 0 && vcpu->launched)
vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].rflags =
exec_vmread(VMX_GUEST_RFLAGS);
return vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].rflags;
}
inline void vcpu_set_rflags(struct vcpu *vcpu, uint64_t val)
{
vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].rflags = val;
bitmap_set_lock(CPU_REG_RFLAGS, &vcpu->reg_updated);
}
inline uint64_t vcpu_get_cr0(struct vcpu *vcpu)
{
uint64_t mask;
if (bitmap_test_and_set_lock(CPU_REG_CR0, &vcpu->reg_cached) == 0) {
mask = exec_vmread(VMX_CR0_MASK);
vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].cr0 =
(exec_vmread(VMX_CR0_READ_SHADOW) & mask) |
(exec_vmread(VMX_GUEST_CR0) & (~mask));
}
return vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].cr0;
}
inline int vcpu_set_cr0(struct vcpu *vcpu, uint64_t val)
{
return vmx_write_cr0(vcpu, val);
}
inline uint64_t vcpu_get_cr2(struct vcpu *vcpu)
{
return vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].cr2;
}
inline void vcpu_set_cr2(struct vcpu *vcpu, uint64_t val)
{
vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].cr2 = val;
}
inline uint64_t vcpu_get_cr4(struct vcpu *vcpu)
{
uint64_t mask;
if (bitmap_test_and_set_lock(CPU_REG_CR4, &vcpu->reg_cached) == 0) {
mask = exec_vmread(VMX_CR4_MASK);
vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].cr4 =
(exec_vmread(VMX_CR4_READ_SHADOW) & mask) |
(exec_vmread(VMX_GUEST_CR4) & (~mask));
}
return vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].cr4;
}
inline int vcpu_set_cr4(struct vcpu *vcpu, uint64_t val)
{
return vmx_write_cr4(vcpu, val);
}
inline uint64_t vcpu_get_pat_ext(struct vcpu *vcpu)
{
return vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].ia32_pat;
}
inline void vcpu_set_pat_ext(struct vcpu *vcpu, uint64_t val)
{
vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].ia32_pat = val;
}
struct vcpu *get_ever_run_vcpu(uint16_t pcpu_id)
{
return per_cpu(ever_run_vcpu, pcpu_id);
@ -128,15 +263,12 @@ int create_vcpu(uint16_t pcpu_id, struct vm *vm, struct vcpu **rtn_vcpu_handle)
static void set_vcpu_mode(struct vcpu *vcpu, uint32_t cs_attr)
{
struct run_context *cur_context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
if (cur_context->ia32_efer & MSR_IA32_EFER_LMA_BIT) {
if (vcpu_get_efer(vcpu) & MSR_IA32_EFER_LMA_BIT) {
if (cs_attr & 0x2000) /* CS.L = 1 */
vcpu->arch_vcpu.cpu_mode = CPU_MODE_64BIT;
else
vcpu->arch_vcpu.cpu_mode = CPU_MODE_COMPATIBILITY;
} else if (cur_context->cr0 & CR0_PE) {
} else if (vcpu_get_cr0(vcpu) & CR0_PE) {
vcpu->arch_vcpu.cpu_mode = CPU_MODE_PROTECTED;
} else {
vcpu->arch_vcpu.cpu_mode = CPU_MODE_REAL;
@ -153,6 +285,17 @@ int start_vcpu(struct vcpu *vcpu)
ASSERT(vcpu != NULL, "Incorrect arguments");
if (bitmap_test_and_clear_lock(CPU_REG_RIP, &vcpu->reg_updated))
exec_vmwrite(VMX_GUEST_RIP, cur_context->rip);
if (bitmap_test_and_clear_lock(CPU_REG_RSP, &vcpu->reg_updated))
exec_vmwrite(VMX_GUEST_RSP,
cur_context->guest_cpu_regs.regs.rsp);
if (bitmap_test_and_clear_lock(CPU_REG_EFER, &vcpu->reg_updated))
exec_vmwrite64(VMX_GUEST_IA32_EFER_FULL,
cur_context->ia32_efer);
if (bitmap_test_and_clear_lock(CPU_REG_RFLAGS, &vcpu->reg_updated))
exec_vmwrite(VMX_GUEST_RFLAGS, cur_context->rflags);
/* If this VCPU is not already launched, launch it */
if (!vcpu->launched) {
pr_info("VM %d Starting VCPU %hu",
@ -193,27 +336,22 @@ int start_vcpu(struct vcpu *vcpu)
* instruction needs to be repeated and resume VCPU accordingly
*/
instlen = vcpu->arch_vcpu.inst_len;
rip = cur_context->rip;
exec_vmwrite(VMX_GUEST_RIP, ((rip +(uint64_t)instlen) &
rip = vcpu_get_rip(vcpu);
exec_vmwrite(VMX_GUEST_RIP, ((rip+(uint64_t)instlen) &
0xFFFFFFFFFFFFFFFFUL));
/* Resume the VM */
status = vmx_vmrun(cur_context, VM_RESUME, ibrs_type);
}
/* Save guest CR3 register */
cur_context->cr3 = exec_vmread(VMX_GUEST_CR3);
vcpu->reg_cached = 0UL;
/* Save guest IA32_EFER register */
cur_context->ia32_efer = exec_vmread64(VMX_GUEST_IA32_EFER_FULL);
set_vcpu_mode(vcpu, exec_vmread32(VMX_GUEST_CS_ATTR));
/* Obtain current VCPU instruction pointer and length */
cur_context->rip = exec_vmread(VMX_GUEST_RIP);
/* Obtain current VCPU instruction length */
vcpu->arch_vcpu.inst_len = exec_vmread32(VMX_EXIT_INSTR_LEN);
cur_context->guest_cpu_regs.regs.rsp = exec_vmread(VMX_GUEST_RSP);
cur_context->rflags = exec_vmread(VMX_GUEST_RFLAGS);
/* Obtain VM exit reason */
vcpu->arch_vcpu.exit_reason = exec_vmread32(VMX_EXIT_REASON);

View File

@ -427,7 +427,7 @@ static void vlapic_set_tsc_deadline_msr(struct acrn_vlapic *vlapic,
struct vcpu_arch *arch = &vlapic->vcpu->arch_vcpu;
/* transfer guest tsc to host tsc */
val -= arch->contexts[arch->cur_context].tsc_offset;
val -= exec_vmread64(VMX_TSC_OFFSET_FULL);
timer->fire_tsc = val;
add_timer(timer);

View File

@ -16,14 +16,12 @@ int vmcall_vmexit_handler(struct vcpu *vcpu)
{
int32_t ret = -EACCES;
struct vm *vm = vcpu->vm;
struct run_context *cur_context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
/* hypercall ID from guest*/
uint64_t hypcall_id = cur_context->guest_cpu_regs.regs.r8;
uint64_t hypcall_id = vcpu_get_gpreg(vcpu, CPU_REG_R8);
/* hypercall param1 from guest*/
uint64_t param1 = cur_context->guest_cpu_regs.regs.rdi;
uint64_t param1 = vcpu_get_gpreg(vcpu, CPU_REG_RDI);
/* hypercall param2 from guest*/
uint64_t param2 = cur_context->guest_cpu_regs.regs.rsi;
uint64_t param2 = vcpu_get_gpreg(vcpu, CPU_REG_RSI);
if (!is_hypercall_from_ring0()) {
pr_err("hypercall is only allowed from RING-0!\n");
@ -179,7 +177,7 @@ int vmcall_vmexit_handler(struct vcpu *vcpu)
}
out:
cur_context->guest_cpu_regs.regs.rax = (uint64_t)ret;
vcpu_set_gpreg(vcpu, CPU_REG_RAX, (uint64_t)ret);
TRACE_2L(TRACE_VMEXIT_VMCALL, vm->vm_id, hypcall_id);

View File

@ -147,10 +147,9 @@ int rdmsr_vmexit_handler(struct vcpu *vcpu)
int err = 0;
uint32_t msr;
uint64_t v = 0UL;
int cur_context = vcpu->arch_vcpu.cur_context;
/* Read the msr value */
msr = vcpu->arch_vcpu.contexts[cur_context].guest_cpu_regs.regs.rcx;
msr = vcpu_get_gpreg(vcpu, CPU_REG_RCX);
/* Do the required processing for each msr case */
switch (msr) {
@ -162,7 +161,7 @@ int rdmsr_vmexit_handler(struct vcpu *vcpu)
case MSR_IA32_TIME_STAMP_COUNTER:
{
/* Add the TSC_offset to host TSC to get guest TSC */
v = rdtsc() + vcpu->arch_vcpu.contexts[cur_context].tsc_offset;
v = rdtsc() + exec_vmread64(VMX_TSC_OFFSET_FULL);
break;
}
case MSR_IA32_MTRR_CAP:
@ -244,10 +243,8 @@ int rdmsr_vmexit_handler(struct vcpu *vcpu)
}
/* Store the MSR contents in RAX and RDX */
vcpu->arch_vcpu.contexts[cur_context].guest_cpu_regs.regs.rax =
v & 0xffffffffU;
vcpu->arch_vcpu.contexts[cur_context].guest_cpu_regs.regs.rdx =
v >> 32U;
vcpu_set_gpreg(vcpu, CPU_REG_RAX, v & 0xffffffffU);
vcpu_set_gpreg(vcpu, CPU_REG_RDX, v >> 32U);
TRACE_2L(TRACE_VMEXIT_RDMSR, msr, v);
@ -259,15 +256,13 @@ int wrmsr_vmexit_handler(struct vcpu *vcpu)
int err = 0;
uint32_t msr;
uint64_t v;
struct run_context *cur_context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
/* Read the MSR ID */
msr = (uint32_t)cur_context->guest_cpu_regs.regs.rcx;
msr = (uint32_t)vcpu_get_gpreg(vcpu, CPU_REG_RCX);
/* Get the MSR contents */
v = (cur_context->guest_cpu_regs.regs.rdx << 32U) |
cur_context->guest_cpu_regs.regs.rax;
v = (vcpu_get_gpreg(vcpu, CPU_REG_RDX) << 32U) |
vcpu_get_gpreg(vcpu, CPU_REG_RAX);
/* Do the required processing for each msr case */
switch (msr) {
@ -279,8 +274,7 @@ int wrmsr_vmexit_handler(struct vcpu *vcpu)
case MSR_IA32_TIME_STAMP_COUNTER:
{
/*Caculate TSC offset from changed TSC MSR value*/
cur_context->tsc_offset = v - rdtsc();
exec_vmwrite64(VMX_TSC_OFFSET_FULL, cur_context->tsc_offset);
exec_vmwrite64(VMX_TSC_OFFSET_FULL, v - rdtsc());
break;
}

View File

@ -29,13 +29,10 @@ emulate_pio_post(struct vcpu *vcpu, struct io_request *io_req)
if (pio_req->direction == REQUEST_READ) {
uint64_t value = (uint64_t)pio_req->value;
int32_t context_idx = vcpu->arch_vcpu.cur_context;
struct run_context *cur_context;
uint64_t *rax;
uint64_t rax = vcpu_get_gpreg(vcpu, CPU_REG_RAX);
cur_context = &vcpu->arch_vcpu.contexts[context_idx];
rax = &cur_context->guest_cpu_regs.regs.rax;
*rax = ((*rax) & ~mask) | (value & mask);
rax = ((rax) & ~mask) | (value & mask);
vcpu_set_gpreg(vcpu, CPU_REG_RAX, rax);
}
status = 0;
} else {
@ -323,14 +320,10 @@ int32_t pio_instr_vmexit_handler(struct vcpu *vcpu)
int32_t status;
uint64_t exit_qual;
int32_t cur_context_idx = vcpu->arch_vcpu.cur_context;
struct run_context *cur_context;
struct cpu_gp_regs *regs;
struct io_request *io_req = &vcpu->req;
struct pio_request *pio_req = &io_req->reqs.pio;
exit_qual = vcpu->arch_vcpu.exit_qualification;
cur_context = &vcpu->arch_vcpu.contexts[cur_context_idx];
regs = &cur_context->guest_cpu_regs.regs;
io_req->type = REQ_PORTIO;
io_req->processed = REQ_STATE_PENDING;
@ -338,7 +331,7 @@ int32_t pio_instr_vmexit_handler(struct vcpu *vcpu)
pio_req->address = VM_EXIT_IO_INSTRUCTION_PORT_NUMBER(exit_qual);
if (VM_EXIT_IO_INSTRUCTION_ACCESS_DIRECTION(exit_qual) == 0UL) {
pio_req->direction = REQUEST_WRITE;
pio_req->value = (uint32_t)regs->rax;
pio_req->value = (uint32_t)vcpu_get_gpreg(vcpu, CPU_REG_RAX);
} else {
pio_req->direction = REQUEST_READ;
}

View File

@ -52,13 +52,11 @@ static const uint16_t exception_type[32] = {
static bool is_guest_irq_enabled(struct vcpu *vcpu)
{
struct run_context *cur_context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
uint64_t guest_rflags, guest_state;
bool status = false;
/* Read the RFLAGS of the guest */
guest_rflags = cur_context->rflags;
guest_rflags = vcpu_get_rflags(vcpu);
/* Check the RFLAGS[IF] bit first */
if ((guest_rflags & HV_ARCH_VCPU_RFLAGS_IF) != 0UL) {
/* Interrupts are allowed */
@ -302,10 +300,7 @@ void vcpu_inject_gp(struct vcpu *vcpu, uint32_t err_code)
void vcpu_inject_pf(struct vcpu *vcpu, uint64_t addr, uint32_t err_code)
{
struct run_context *cur_context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
cur_context->cr2 = addr;
vcpu_set_cr2(vcpu, addr);
vcpu_queue_exception(vcpu, IDT_PF, err_code);
vcpu_make_request(vcpu, ACRN_REQUEST_EXCP);
}

View File

@ -243,14 +243,18 @@ static int unhandled_vmexit_handler(struct vcpu *vcpu)
int cpuid_vmexit_handler(struct vcpu *vcpu)
{
struct run_context *cur_context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
uint64_t rax, rbx, rcx, rdx;
guest_cpuid(vcpu,
(uint32_t *)&cur_context->guest_cpu_regs.regs.rax,
(uint32_t *)&cur_context->guest_cpu_regs.regs.rbx,
(uint32_t *)&cur_context->guest_cpu_regs.regs.rcx,
(uint32_t *)&cur_context->guest_cpu_regs.regs.rdx);
rax = vcpu_get_gpreg(vcpu, CPU_REG_RAX);
rbx = vcpu_get_gpreg(vcpu, CPU_REG_RBX);
rcx = vcpu_get_gpreg(vcpu, CPU_REG_RCX);
rdx = vcpu_get_gpreg(vcpu, CPU_REG_RDX);
guest_cpuid(vcpu, (uint32_t *)&rax, (uint32_t *)&rbx,
(uint32_t *)&rcx, (uint32_t *)&rdx);
vcpu_set_gpreg(vcpu, CPU_REG_RAX, rax);
vcpu_set_gpreg(vcpu, CPU_REG_RBX, rbx);
vcpu_set_gpreg(vcpu, CPU_REG_RCX, rcx);
vcpu_set_gpreg(vcpu, CPU_REG_RDX, rdx);
TRACE_2L(TRACE_VMEXIT_CPUID, (uint64_t)vcpu->vcpu_id, 0UL);
@ -260,24 +264,22 @@ int cpuid_vmexit_handler(struct vcpu *vcpu)
int cr_access_vmexit_handler(struct vcpu *vcpu)
{
int err = 0;
uint64_t *regptr;
struct run_context *cur_context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
uint64_t reg;
int idx = VM_EXIT_CR_ACCESS_REG_IDX(vcpu->arch_vcpu.exit_qualification);
ASSERT(idx>=0 && idx<=15, "index out of range");
regptr = cur_context->guest_cpu_regs.longs + idx;
reg = vcpu_get_gpreg(vcpu, idx);
switch ((VM_EXIT_CR_ACCESS_ACCESS_TYPE
(vcpu->arch_vcpu.exit_qualification) << 4) |
VM_EXIT_CR_ACCESS_CR_NUM(vcpu->arch_vcpu.exit_qualification)) {
case 0x00U:
/* mov to cr0 */
err = vmx_write_cr0(vcpu, *regptr);
err = vcpu_set_cr0(vcpu, reg);
break;
case 0x04U:
/* mov to cr4 */
err = vmx_write_cr4(vcpu, *regptr);
err = vcpu_set_cr4(vcpu, reg);
break;
case 0x08U:
/* mov to cr8 */
@ -285,16 +287,17 @@ int cr_access_vmexit_handler(struct vcpu *vcpu)
*
* set reserved bit in CR8 causes GP to guest
*/
if (*regptr & ~0xFUL) {
if (reg & ~0xFUL) {
pr_dbg("Invalid cr8 write operation from guest");
vcpu_inject_gp(vcpu, 0U);
break;
}
vlapic_set_cr8(vcpu->arch_vcpu.vlapic, *regptr);
vlapic_set_cr8(vcpu->arch_vcpu.vlapic, reg);
break;
case 0x18U:
/* mov from cr8 */
*regptr = vlapic_get_cr8(vcpu->arch_vcpu.vlapic);
reg = vlapic_get_cr8(vcpu->arch_vcpu.vlapic);
vcpu_set_gpreg(vcpu, idx, reg);
break;
default:
panic("Unhandled CR access");
@ -318,7 +321,6 @@ static int xsetbv_vmexit_handler(struct vcpu *vcpu)
{
int idx;
uint64_t val64;
struct run_context *ctx_ptr;
val64 = exec_vmread(VMX_GUEST_CR4);
if ((val64 & CR4_OSXSAVE) == 0UL) {
@ -331,16 +333,14 @@ static int xsetbv_vmexit_handler(struct vcpu *vcpu)
return -1;
}
ctx_ptr = &(vcpu->arch_vcpu.contexts[idx]);
/*to access XCR0,'rcx' should be 0*/
if (ctx_ptr->guest_cpu_regs.regs.rcx != 0UL) {
if (vcpu_get_gpreg(vcpu, CPU_REG_RCX) != 0UL) {
vcpu_inject_gp(vcpu, 0U);
return 0;
}
val64 = ((ctx_ptr->guest_cpu_regs.regs.rax) & 0xffffffffUL) |
(ctx_ptr->guest_cpu_regs.regs.rdx << 32U);
val64 = (vcpu_get_gpreg(vcpu, CPU_REG_RAX) & 0xffffffffUL) |
(vcpu_get_gpreg(vcpu, CPU_REG_RDX) << 32U);
/*bit 0(x87 state) of XCR0 can't be cleared*/
if ((val64 & 0x01UL) == 0UL) {

View File

@ -314,23 +314,18 @@ static void init_cr0_cr4_host_mask(__unused struct vcpu *vcpu)
uint64_t vmx_rdmsr_pat(struct vcpu *vcpu)
{
struct run_context *context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
/*
* note: if context->cr0.CD is set, the actual value in guest's
* IA32_PAT MSR is PAT_ALL_UC_VALUE, which may be different from
* the saved value context->ia32_pat
*/
return context->ia32_pat;
return vcpu_get_pat_ext(vcpu);
}
int vmx_wrmsr_pat(struct vcpu *vcpu, uint64_t value)
{
uint32_t i;
uint64_t field;
struct run_context *context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
for (i = 0U; i < 8U; i++) {
field = (value >> (i * 8U)) & 0xffUL;
@ -342,23 +337,21 @@ int vmx_wrmsr_pat(struct vcpu *vcpu, uint64_t value)
}
}
context->ia32_pat = value;
vcpu_set_pat_ext(vcpu, value);
/*
* If context->cr0.CD is set, we defer any further requests to write
* guest's IA32_PAT, until the time when guest's CR0.CD is being cleared
*/
if ((context->cr0 & CR0_CD) == 0UL) {
if ((vcpu_get_cr0(vcpu) & CR0_CD) == 0UL) {
exec_vmwrite64(VMX_GUEST_IA32_PAT_FULL, value);
}
return 0;
}
static bool is_cr0_write_valid(struct vcpu *vcpu, uint64_t cr0)
{
struct run_context *context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
/* Shouldn't set always off bit */
if ((cr0 & cr0_always_off_mask) != 0UL)
return false;
@ -370,8 +363,8 @@ static bool is_cr0_write_valid(struct vcpu *vcpu, uint64_t cr0)
* CR0.PG = 1, CR4.PAE = 0 and IA32_EFER.LME = 1 is invalid.
* CR0.PE = 0 and CR0.PG = 1 is invalid.
*/
if (((cr0 & CR0_PG) != 0UL) && ((context->cr4 & CR4_PAE) == 0UL) &&
((context->ia32_efer & MSR_IA32_EFER_LME_BIT) != 0UL))
if (((cr0 & CR0_PG) != 0UL) && ((vcpu_get_cr4(vcpu) & CR4_PAE) == 0UL)
&& ((vcpu_get_efer(vcpu) & MSR_IA32_EFER_LME_BIT) != 0UL))
return false;
if (((cr0 & CR0_PE) == 0UL) && ((cr0 & CR0_PG) != 0UL))
@ -411,11 +404,9 @@ static bool is_cr0_write_valid(struct vcpu *vcpu, uint64_t cr0)
*/
int vmx_write_cr0(struct vcpu *vcpu, uint64_t cr0)
{
struct run_context *context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
uint64_t cr0_vmx;
uint32_t entry_ctrls;
bool paging_enabled = !!(context->cr0 & CR0_PG);
bool paging_enabled = !!(vcpu_get_cr0(vcpu) & CR0_PG);
if (!is_cr0_write_valid(vcpu, cr0)) {
pr_dbg("Invalid cr0 write operation from guest");
@ -427,9 +418,10 @@ int vmx_write_cr0(struct vcpu *vcpu, uint64_t cr0)
* When loading a control register, reserved bit should always set
* to the value previously read.
*/
cr0 = (cr0 & ~CR0_RESERVED_MASK) | (context->cr0 & CR0_RESERVED_MASK);
cr0 = (cr0 & ~CR0_RESERVED_MASK) |
(vcpu_get_cr0(vcpu) & CR0_RESERVED_MASK);
if (((context->ia32_efer & MSR_IA32_EFER_LME_BIT) != 0UL) &&
if (((vcpu_get_efer(vcpu) & MSR_IA32_EFER_LME_BIT) != 0UL) &&
!paging_enabled && ((cr0 & CR0_PG) != 0UL)) {
/* Enable long mode */
pr_dbg("VMM: Enable long mode");
@ -437,9 +429,9 @@ int vmx_write_cr0(struct vcpu *vcpu, uint64_t cr0)
entry_ctrls |= VMX_ENTRY_CTLS_IA32E_MODE;
exec_vmwrite32(VMX_ENTRY_CONTROLS, entry_ctrls);
context->ia32_efer |= MSR_IA32_EFER_LMA_BIT;
exec_vmwrite64(VMX_GUEST_IA32_EFER_FULL, context->ia32_efer);
} else if (((context->ia32_efer & MSR_IA32_EFER_LME_BIT) != 0UL) &&
vcpu_set_efer(vcpu,
vcpu_get_efer(vcpu) | MSR_IA32_EFER_LMA_BIT);
} else if (((vcpu_get_efer(vcpu) & MSR_IA32_EFER_LME_BIT) != 0UL) &&
paging_enabled && ((cr0 & CR0_PG) == 0UL)){
/* Disable long mode */
pr_dbg("VMM: Disable long mode");
@ -447,16 +439,16 @@ int vmx_write_cr0(struct vcpu *vcpu, uint64_t cr0)
entry_ctrls &= ~VMX_ENTRY_CTLS_IA32E_MODE;
exec_vmwrite32(VMX_ENTRY_CONTROLS, entry_ctrls);
context->ia32_efer &= ~MSR_IA32_EFER_LMA_BIT;
exec_vmwrite64(VMX_GUEST_IA32_EFER_FULL, context->ia32_efer);
vcpu_set_efer(vcpu,
vcpu_get_efer(vcpu) & ~MSR_IA32_EFER_LMA_BIT);
} else {
/* CR0.PG unchanged. */
}
/* If CR0.CD or CR0.NW get changed */
if (((context->cr0 ^ cr0) & (CR0_CD | CR0_NW)) != 0UL) {
if (((vcpu_get_cr0(vcpu) ^ cr0) & (CR0_CD | CR0_NW)) != 0UL) {
/* No action if only CR0.NW is changed */
if (((context->cr0 ^ cr0) & CR0_CD) != 0UL) {
if (((vcpu_get_cr0(vcpu) ^ cr0) & CR0_CD) != 0UL) {
if ((cr0 & CR0_CD) != 0UL) {
/*
* When the guest requests to set CR0.CD, we don't allow
@ -468,7 +460,8 @@ int vmx_write_cr0(struct vcpu *vcpu, uint64_t cr0)
CACHE_FLUSH_INVALIDATE_ALL();
} else {
/* Restore IA32_PAT to enable cache again */
exec_vmwrite64(VMX_GUEST_IA32_PAT_FULL, context->ia32_pat);
exec_vmwrite64(VMX_GUEST_IA32_PAT_FULL,
vcpu_get_pat_ext(vcpu));
}
vcpu_make_request(vcpu, ACRN_REQUEST_EPT_FLUSH);
}
@ -483,7 +476,9 @@ int vmx_write_cr0(struct vcpu *vcpu, uint64_t cr0)
cr0_vmx &= ~(CR0_CD | CR0_NW);
exec_vmwrite(VMX_GUEST_CR0, cr0_vmx & 0xFFFFFFFFUL);
exec_vmwrite(VMX_CR0_READ_SHADOW, cr0 & 0xFFFFFFFFUL);
context->cr0 = cr0;
/* clear read cache, next time read should from VMCS */
bitmap_clear_lock(CPU_REG_CR0, &vcpu->reg_cached);
pr_dbg("VMM: Try to write %016llx, allow to write 0x%016llx to CR0",
cr0, cr0_vmx);
@ -491,19 +486,6 @@ int vmx_write_cr0(struct vcpu *vcpu, uint64_t cr0)
return 0;
}
int vmx_write_cr3(struct vcpu *vcpu, uint64_t cr3)
{
struct run_context *context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
/* Write to guest's CR3 */
context->cr3 = cr3;
/* Commit new value to VMCS */
exec_vmwrite(VMX_GUEST_CR3, cr3);
return 0;
}
static bool is_cr4_write_valid(struct vcpu *vcpu, uint64_t cr4)
{
/* Check if guest try to set fixed to 0 bits or reserved bits */
@ -558,8 +540,6 @@ static bool is_cr4_write_valid(struct vcpu *vcpu, uint64_t cr4)
*/
int vmx_write_cr4(struct vcpu *vcpu, uint64_t cr4)
{
struct run_context *context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
uint64_t cr4_vmx;
if (!is_cr4_write_valid(vcpu, cr4)) {
@ -572,7 +552,9 @@ int vmx_write_cr4(struct vcpu *vcpu, uint64_t cr4)
cr4_vmx = cr4_always_on_mask | cr4;
exec_vmwrite(VMX_GUEST_CR4, cr4_vmx & 0xFFFFFFFFUL);
exec_vmwrite(VMX_CR4_READ_SHADOW, cr4 & 0xFFFFFFFFUL);
context->cr4 = cr4;
/* clear read cache, next time read should from VMCS */
bitmap_clear_lock(CPU_REG_CR4, &vcpu->reg_cached);
pr_dbg("VMM: Try to write %016llx, allow to write 0x%016llx to CR4",
cr4, cr4_vmx);
@ -583,7 +565,6 @@ int vmx_write_cr4(struct vcpu *vcpu, uint64_t cr4)
static void init_guest_state(struct vcpu *vcpu)
{
uint32_t field;
uint64_t value;
uint16_t value16;
uint32_t value32;
uint64_t value64;
@ -594,8 +575,6 @@ static void init_guest_state(struct vcpu *vcpu)
uint16_t es = 0U, ss = 0U, ds = 0U, fs = 0U, gs = 0U, data32_idx;
uint16_t tr_sel = 0x70U;
struct vm *vm = vcpu->vm;
struct run_context *cur_context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
enum vm_cpu_mode vcpu_mode = get_vcpu_mode(vcpu);
pr_dbg("*********************");
@ -613,7 +592,7 @@ static void init_guest_state(struct vcpu *vcpu)
pr_dbg("Natural-width********");
if (vcpu_mode == CPU_MODE_64BIT) {
cur_context->ia32_efer = MSR_IA32_EFER_LME_BIT;
vcpu_set_efer(vcpu, MSR_IA32_EFER_LME_BIT);
}
/* Setup guest control register values
@ -621,17 +600,18 @@ static void init_guest_state(struct vcpu *vcpu)
* checked.
*/
if (vcpu_mode == CPU_MODE_REAL) {
vmx_write_cr4(vcpu, 0UL);
vmx_write_cr3(vcpu, 0UL);
vmx_write_cr0(vcpu, CR0_ET | CR0_NE);
vcpu_set_cr4(vcpu, 0UL);
exec_vmwrite(VMX_GUEST_CR3, 0UL);
vcpu_set_cr0(vcpu, CR0_ET | CR0_NE);
} else if (vcpu_mode == CPU_MODE_PROTECTED) {
vmx_write_cr4(vcpu, 0UL);
vmx_write_cr3(vcpu, 0UL);
vmx_write_cr0(vcpu, CR0_ET | CR0_NE | CR0_PE);
vcpu_set_cr4(vcpu, 0UL);
exec_vmwrite(VMX_GUEST_CR3, 0UL);
vcpu_set_cr0(vcpu, CR0_ET | CR0_NE | CR0_PE);
} else if (vcpu_mode == CPU_MODE_64BIT) {
vmx_write_cr4(vcpu, CR4_PSE | CR4_PAE | CR4_MCE);
vmx_write_cr3(vcpu, vm->arch_vm.guest_init_pml4 | CR3_PWT);
vmx_write_cr0(vcpu, CR0_PG | CR0_PE | CR0_NE);
vcpu_set_cr4(vcpu, CR4_PSE | CR4_PAE | CR4_MCE);
exec_vmwrite(VMX_GUEST_CR3,
vm->arch_vm.guest_init_pml4 | CR3_PWT);
vcpu_set_cr0(vcpu, CR0_PG | CR0_PE | CR0_NE);
} else {
/* vcpu_mode will never be CPU_MODE_COMPATIBILITY */
}
@ -639,10 +619,8 @@ static void init_guest_state(struct vcpu *vcpu)
/***************************************************/
/* Set up Flags - the value of RFLAGS on VM entry */
/***************************************************/
field = VMX_GUEST_RFLAGS;
cur_context->rflags = 0x2UL; /* Bit 1 is a active high reserved bit */
exec_vmwrite(field, cur_context->rflags);
pr_dbg("VMX_GUEST_RFLAGS: 0x%016llx ", cur_context->rflags);
vcpu_set_rflags(vcpu, 0x2UL); /* Bit 1 is a active high reserved bit */
pr_dbg("VMX_GUEST_RFLAGS: 0x%016llx ", vcpu_get_rflags(vcpu));
/***************************************************/
/* Set Code Segment - CS */
@ -1023,10 +1001,9 @@ static void init_guest_state(struct vcpu *vcpu)
value32);
value64 = PAT_POWER_ON_VALUE;
cur_context->ia32_pat = value64;
exec_vmwrite64(VMX_GUEST_IA32_PAT_FULL, value64);
pr_dbg("VMX_GUEST_IA32_PAT: 0x%016llx ",
value64);
pr_dbg("VMX_GUEST_IA32_PAT: 0x%016llx ", value64);
vcpu_set_pat_ext(vcpu, value64);
value64 = 0UL;
exec_vmwrite64(VMX_GUEST_IA32_DEBUGCTL_FULL, value64);
@ -1561,17 +1538,15 @@ static void init_exit_ctrl(__unused struct vcpu *vcpu)
static void override_uefi_vmcs(struct vcpu *vcpu)
{
uint32_t field;
struct run_context *cur_context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
if (get_vcpu_mode(vcpu) == CPU_MODE_64BIT) {
/* CR4 should be set before CR0, because when set CR0, CR4 value
* will be checked. */
/* VMXE is always on bit when set CR4, and not allowed to be set
* from input cr4 value */
vmx_write_cr4(vcpu, efi_ctx->cr4 & ~CR4_VMXE);
vmx_write_cr3(vcpu, efi_ctx->cr3);
vmx_write_cr0(vcpu, efi_ctx->cr0 | CR0_PG | CR0_PE | CR0_NE);
vcpu_set_cr4(vcpu, efi_ctx->cr4 & ~CR4_VMXE);
exec_vmwrite(VMX_GUEST_CR3, efi_ctx->cr3);
vcpu_set_cr0(vcpu, efi_ctx->cr0 | CR0_PG | CR0_PE | CR0_NE);
/* Selector */
field = VMX_GUEST_CS_SEL;
@ -1642,11 +1617,9 @@ static void override_uefi_vmcs(struct vcpu *vcpu)
}
/* Interrupt */
field = VMX_GUEST_RFLAGS;
/* clear flags for CF/PF/AF/ZF/SF/OF */
cur_context->rflags = efi_ctx->rflags & ~(0x8d5UL);
exec_vmwrite(field, cur_context->rflags);
pr_dbg("VMX_GUEST_RFLAGS: 0x%016llx ", cur_context->rflags);
vcpu_set_rflags(vcpu, efi_ctx->rflags & ~(0x8d5UL));
pr_dbg("VMX_GUEST_RFLAGS: 0x%016llx ", vcpu_get_rflags(vcpu));
}
#endif

View File

@ -54,8 +54,6 @@ void efi_spurious_handler(int vector)
int uefi_sw_loader(struct vm *vm, struct vcpu *vcpu)
{
int ret = 0;
struct run_context *cur_context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
ASSERT(vm != NULL, "Incorrect argument");
@ -67,21 +65,21 @@ int uefi_sw_loader(struct vm *vm, struct vcpu *vcpu)
vlapic_restore(vcpu->arch_vcpu.vlapic, &uefi_lapic_regs);
vcpu->entry_addr = (void *)efi_ctx->rip;
cur_context->guest_cpu_regs.regs.rax = efi_ctx->rax;
cur_context->guest_cpu_regs.regs.rbx = efi_ctx->rbx;
cur_context->guest_cpu_regs.regs.rdx = efi_ctx->rcx;
cur_context->guest_cpu_regs.regs.rcx = efi_ctx->rdx;
cur_context->guest_cpu_regs.regs.rdi = efi_ctx->rdi;
cur_context->guest_cpu_regs.regs.rsi = efi_ctx->rsi;
cur_context->guest_cpu_regs.regs.rbp = efi_ctx->rbp;
cur_context->guest_cpu_regs.regs.r8 = efi_ctx->r8;
cur_context->guest_cpu_regs.regs.r9 = efi_ctx->r9;
cur_context->guest_cpu_regs.regs.r10 = efi_ctx->r10;
cur_context->guest_cpu_regs.regs.r11 = efi_ctx->r11;
cur_context->guest_cpu_regs.regs.r12 = efi_ctx->r12;
cur_context->guest_cpu_regs.regs.r13 = efi_ctx->r13;
cur_context->guest_cpu_regs.regs.r14 = efi_ctx->r14;
cur_context->guest_cpu_regs.regs.r15 = efi_ctx->r15;
vcpu_set_gpreg(vcpu, CPU_REG_RAX, efi_ctx->rax);
vcpu_set_gpreg(vcpu, CPU_REG_RBX, efi_ctx->rbx);
vcpu_set_gpreg(vcpu, CPU_REG_RCX, efi_ctx->rcx);
vcpu_set_gpreg(vcpu, CPU_REG_RDX, efi_ctx->rdx);
vcpu_set_gpreg(vcpu, CPU_REG_RDI, efi_ctx->rdi);
vcpu_set_gpreg(vcpu, CPU_REG_RSI, efi_ctx->rsi);
vcpu_set_gpreg(vcpu, CPU_REG_RBP, efi_ctx->rbp);
vcpu_set_gpreg(vcpu, CPU_REG_R8, efi_ctx->r8);
vcpu_set_gpreg(vcpu, CPU_REG_R9, efi_ctx->r9);
vcpu_set_gpreg(vcpu, CPU_REG_R10, efi_ctx->r10);
vcpu_set_gpreg(vcpu, CPU_REG_R11, efi_ctx->r11);
vcpu_set_gpreg(vcpu, CPU_REG_R12, efi_ctx->r12);
vcpu_set_gpreg(vcpu, CPU_REG_R13, efi_ctx->r13);
vcpu_set_gpreg(vcpu, CPU_REG_R14, efi_ctx->r14);
vcpu_set_gpreg(vcpu, CPU_REG_R15, efi_ctx->r15);
/* defer irq enabling till vlapic is ready */
CPU_IRQ_ENABLE();

View File

@ -102,8 +102,7 @@ void vcpu_thread(struct vcpu *vcpu)
basic_exit_reason = vcpu->arch_vcpu.exit_reason & 0xFFFFU;
per_cpu(vmexit_cnt, vcpu->pcpu_id)[basic_exit_reason]++;
TRACE_2L(TRACE_VM_EXIT, basic_exit_reason,
vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].rip);
TRACE_2L(TRACE_VM_EXIT, basic_exit_reason, vcpu_get_rip(vcpu));
} while (1);
}

View File

@ -73,29 +73,27 @@ static uint64_t create_zero_page(struct vm *vm)
int load_guest(struct vm *vm, struct vcpu *vcpu)
{
int32_t ret = 0;
uint32_t i;
void *hva;
struct run_context *cur_context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
uint64_t lowmem_gpa_top;
hva = GPA2HVA(vm, GUEST_CFG_OFFSET);
lowmem_gpa_top = *(uint64_t *)hva;
/* hardcode vcpu entry addr(kernel entry) & rsi (zeropage)*/
(void)memset((void*)cur_context->guest_cpu_regs.longs,
0U, sizeof(uint64_t)*NUM_GPRS);
for (i = 0; i < NUM_GPRS; i++)
vcpu_set_gpreg(vcpu, i, 0UL);
hva = GPA2HVA(vm, lowmem_gpa_top -
MEM_4K - MEM_2K);
vcpu->entry_addr = (void *)(*((uint64_t *)hva));
cur_context->guest_cpu_regs.regs.rsi =
lowmem_gpa_top - MEM_4K;
vcpu_set_gpreg(vcpu, CPU_REG_RSI, lowmem_gpa_top - MEM_4K);
pr_info("%s, Set config according to predefined offset:",
__func__);
pr_info("VCPU%hu Entry: 0x%llx, RSI: 0x%016llx, cr3: 0x%016llx",
vcpu->vcpu_id, vcpu->entry_addr,
cur_context->guest_cpu_regs.regs.rsi,
vcpu_get_gpreg(vcpu, CPU_REG_RSI),
vm->arch_vm.guest_init_pml4);
return ret;
@ -105,8 +103,6 @@ int general_sw_loader(struct vm *vm, struct vcpu *vcpu)
{
int32_t ret = 0;
void *hva;
struct run_context *cur_context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
char dyn_bootargs[100] = {0};
uint32_t kernel_entry_offset;
struct zero_page *zeropage;
@ -150,11 +146,13 @@ int general_sw_loader(struct vm *vm, struct vcpu *vcpu)
/* See if guest is a Linux guest */
if (vm->sw.kernel_type == VM_LINUX_GUEST) {
uint32_t i;
/* Documentation states: ebx=0, edi=0, ebp=0, esi=ptr to
* zeropage
*/
(void)memset(cur_context->guest_cpu_regs.longs,
0U, sizeof(uint64_t) * NUM_GPRS);
for (i = 0; i < NUM_GPRS; i++)
vcpu_set_gpreg(vcpu, i, 0UL);
/* Get host-physical address for guest bootargs */
hva = GPA2HVA(vm,
@ -217,11 +215,11 @@ int general_sw_loader(struct vm *vm, struct vcpu *vcpu)
/* Create Zeropage and copy Physical Base Address of Zeropage
* in RSI
*/
cur_context->guest_cpu_regs.regs.rsi = create_zero_page(vm);
vcpu_set_gpreg(vcpu, CPU_REG_RSI, create_zero_page(vm));
pr_info("%s, RSI pointing to zero page for VM %d at GPA %X",
__func__, vm->vm_id,
cur_context->guest_cpu_regs.regs.rsi);
vcpu_get_gpreg(vcpu, CPU_REG_RSI));
} else {
pr_err("%s, Loading VM SW failed", __func__);

View File

@ -49,9 +49,6 @@ struct intr_excp_ctx *crash_ctx;
static void dump_guest_reg(struct vcpu *vcpu)
{
struct run_context *cur_context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
printf("\n\n================================================");
printf("================================\n\n");
printf("Guest Registers:\r\n");
@ -61,39 +58,39 @@ static void dump_guest_reg(struct vcpu *vcpu)
vcpu->arch_vcpu.cur_context);
printf("= RIP=0x%016llx RSP=0x%016llx "
"RFLAGS=0x%016llx\r\n",
cur_context->rip,
cur_context->guest_cpu_regs.regs.rsp,
cur_context->rflags);
vcpu_get_rip(vcpu),
vcpu_get_gpreg(vcpu, CPU_REG_RSP),
vcpu_get_rflags(vcpu));
printf("= CR0=0x%016llx CR2=0x%016llx "
" CR3=0x%016llx\r\n",
cur_context->cr0,
cur_context->cr2,
cur_context->cr3);
vcpu_get_cr0(vcpu),
vcpu_get_cr2(vcpu),
exec_vmread(VMX_GUEST_CR3));
printf("= RAX=0x%016llx RBX=0x%016llx "
"RCX=0x%016llx\r\n",
cur_context->guest_cpu_regs.regs.rax,
cur_context->guest_cpu_regs.regs.rbx,
cur_context->guest_cpu_regs.regs.rcx);
vcpu_get_gpreg(vcpu, CPU_REG_RAX),
vcpu_get_gpreg(vcpu, CPU_REG_RBX),
vcpu_get_gpreg(vcpu, CPU_REG_RCX));
printf("= RDX=0x%016llx RDI=0x%016llx "
"RSI=0x%016llx\r\n",
cur_context->guest_cpu_regs.regs.rdx,
cur_context->guest_cpu_regs.regs.rdi,
cur_context->guest_cpu_regs.regs.rsi);
vcpu_get_gpreg(vcpu, CPU_REG_RDX),
vcpu_get_gpreg(vcpu, CPU_REG_RDI),
vcpu_get_gpreg(vcpu, CPU_REG_RSI));
printf("= RBP=0x%016llx R8=0x%016llx "
"R9=0x%016llx\r\n",
cur_context->guest_cpu_regs.regs.rbp,
cur_context->guest_cpu_regs.regs.r8,
cur_context->guest_cpu_regs.regs.r9);
vcpu_get_gpreg(vcpu, CPU_REG_RBP),
vcpu_get_gpreg(vcpu, CPU_REG_R8),
vcpu_get_gpreg(vcpu, CPU_REG_R9));
printf("= R10=0x%016llx R11=0x%016llx "
"R12=0x%016llx\r\n",
cur_context->guest_cpu_regs.regs.r10,
cur_context->guest_cpu_regs.regs.r11,
cur_context->guest_cpu_regs.regs.r12);
vcpu_get_gpreg(vcpu, CPU_REG_R10),
vcpu_get_gpreg(vcpu, CPU_REG_R11),
vcpu_get_gpreg(vcpu, CPU_REG_R12));
printf("= R13=0x%016llx R14=0x%016llx "
"R15=0x%016llx\r\n",
cur_context->guest_cpu_regs.regs.r13,
cur_context->guest_cpu_regs.regs.r14,
cur_context->guest_cpu_regs.regs.r15);
vcpu_get_gpreg(vcpu, CPU_REG_R13),
vcpu_get_gpreg(vcpu, CPU_REG_R14),
vcpu_get_gpreg(vcpu, CPU_REG_R15));
printf("\r\n");
}
@ -101,11 +98,9 @@ static void dump_guest_stack(struct vcpu *vcpu)
{
uint32_t i;
uint64_t tmp[DUMP_STACK_SIZE];
struct run_context *cur_context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
uint32_t err_code = 0;
if (copy_from_gva(vcpu, tmp, cur_context->guest_cpu_regs.regs.rsp,
if (copy_from_gva(vcpu, tmp, vcpu_get_gpreg(vcpu, CPU_REG_RSP),
DUMP_STACK_SIZE, &err_code) < 0) {
printf("\r\nUnabled to Copy Guest Stack:\r\n");
return;
@ -113,11 +108,11 @@ static void dump_guest_stack(struct vcpu *vcpu)
printf("\r\nGuest Stack:\r\n");
printf("Dump stack for vcpu %hu, from gva 0x%016llx\r\n",
vcpu->vcpu_id, cur_context->guest_cpu_regs.regs.rsp);
vcpu->vcpu_id, vcpu_get_gpreg(vcpu, CPU_REG_RSP));
for (i = 0U; i < (DUMP_STACK_SIZE/32U); i++) {
printf("guest_rsp(0x%llx): 0x%016llx 0x%016llx "
"0x%016llx 0x%016llx\r\n",
(cur_context->guest_cpu_regs.regs.rsp+(i*32)),
(vcpu_get_gpreg(vcpu, CPU_REG_RSP)+(i*32)),
tmp[i*4], tmp[(i*4)+1],
tmp[(i*4)+2], tmp[(i*4)+3]);
}
@ -128,12 +123,10 @@ static void show_guest_call_trace(struct vcpu *vcpu)
{
uint64_t bp;
uint64_t count = 0UL;
struct run_context *cur_context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
int err;
uint32_t err_code;
bp = cur_context->guest_cpu_regs.regs.rbp;
bp = vcpu_get_gpreg(vcpu, CPU_REG_RBP);
printf("Guest Call Trace: **************************************\r\n");
printf("Maybe the call trace is not accurate, pls check stack!!\r\n");
/* if enable compiler option(no-omit-frame-pointer) the stack layout

View File

@ -588,7 +588,6 @@ int shell_vcpu_dumpreg(int argc, char **argv)
struct vcpu *vcpu;
uint64_t i;
uint64_t tmp[DUMPREG_SP_SIZE];
struct run_context *cur_context;
uint32_t err_code = 0;
/* User input invalidation */
@ -618,8 +617,6 @@ int shell_vcpu_dumpreg(int argc, char **argv)
return -EINVAL;
}
cur_context = &vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context];
if (vcpu->state != VCPU_PAUSED) {
shell_puts("NOTE: VCPU unPAUSEed, regdump "
"may not be accurate\r\n");
@ -630,48 +627,49 @@ int shell_vcpu_dumpreg(int argc, char **argv)
vm->vm_id, vcpu->vcpu_id);
shell_puts(temp_str);
snprintf(temp_str, MAX_STR_SIZE, "= RIP=0x%016llx RSP=0x%016llx "
"RFLAGS=0x%016llx\r\n", cur_context->rip,
cur_context->guest_cpu_regs.regs.rsp, cur_context->rflags);
"RFLAGS=0x%016llx\r\n", vcpu_get_rip(vcpu),
vcpu_get_gpreg(vcpu, CPU_REG_RSP),
vcpu_get_rflags(vcpu));
shell_puts(temp_str);
snprintf(temp_str, MAX_STR_SIZE, "= CR0=0x%016llx CR2=0x%016llx\r\n",
cur_context->cr0, cur_context->cr2);
vcpu_get_cr0(vcpu), vcpu_get_cr2(vcpu));
shell_puts(temp_str);
snprintf(temp_str, MAX_STR_SIZE, "= CR3=0x%016llx CR4=0x%016llx\r\n",
cur_context->cr3, cur_context->cr4);
exec_vmread(VMX_GUEST_CR3), vcpu_get_cr4(vcpu));
shell_puts(temp_str);
snprintf(temp_str, MAX_STR_SIZE, "= RAX=0x%016llx RBX=0x%016llx "
"RCX=0x%016llx\r\n",
cur_context->guest_cpu_regs.regs.rax,
cur_context->guest_cpu_regs.regs.rbx,
cur_context->guest_cpu_regs.regs.rcx);
vcpu_get_gpreg(vcpu, CPU_REG_RAX),
vcpu_get_gpreg(vcpu, CPU_REG_RBX),
vcpu_get_gpreg(vcpu, CPU_REG_RCX));
shell_puts(temp_str);
snprintf(temp_str, MAX_STR_SIZE, "= RDX=0x%016llx RDI=0x%016llx "
"RSI=0x%016llx\r\n",
cur_context->guest_cpu_regs.regs.rdx,
cur_context->guest_cpu_regs.regs.rdi,
cur_context->guest_cpu_regs.regs.rsi);
vcpu_get_gpreg(vcpu, CPU_REG_RDX),
vcpu_get_gpreg(vcpu, CPU_REG_RDI),
vcpu_get_gpreg(vcpu, CPU_REG_RSI));
shell_puts(temp_str);
snprintf(temp_str, MAX_STR_SIZE, "= RBP=0x%016llx R8=0x%016llx "
"R9=0x%016llx\r\n",
cur_context->guest_cpu_regs.regs.rbp,
cur_context->guest_cpu_regs.regs.r8,
cur_context->guest_cpu_regs.regs.r9);
vcpu_get_gpreg(vcpu, CPU_REG_RBP),
vcpu_get_gpreg(vcpu, CPU_REG_R8),
vcpu_get_gpreg(vcpu, CPU_REG_R9));
shell_puts(temp_str);
snprintf(temp_str, MAX_STR_SIZE, "= R10=0x%016llx R11=0x%016llx "
"R12=0x%016llx\r\n",
cur_context->guest_cpu_regs.regs.r10,
cur_context->guest_cpu_regs.regs.r11,
cur_context->guest_cpu_regs.regs.r12);
vcpu_get_gpreg(vcpu, CPU_REG_R10),
vcpu_get_gpreg(vcpu, CPU_REG_R11),
vcpu_get_gpreg(vcpu, CPU_REG_R12));
shell_puts(temp_str);
snprintf(temp_str, MAX_STR_SIZE,
"= R13=0x%016llx R14=0x%016llx R15=0x%016llx\r\n",
cur_context->guest_cpu_regs.regs.r13,
cur_context->guest_cpu_regs.regs.r14,
cur_context->guest_cpu_regs.regs.r15);
vcpu_get_gpreg(vcpu, CPU_REG_R13),
vcpu_get_gpreg(vcpu, CPU_REG_R14),
vcpu_get_gpreg(vcpu, CPU_REG_R15));
shell_puts(temp_str);
/* dump sp */
status = copy_from_gva(vcpu, tmp, cur_context->guest_cpu_regs.regs.rsp,
status = copy_from_gva(vcpu, tmp, vcpu_get_gpreg(vcpu, CPU_REG_RSP),
DUMPREG_SP_SIZE*sizeof(uint64_t), &err_code);
if (status < 0) {
/* copy_from_gva fail */
@ -680,7 +678,7 @@ int shell_vcpu_dumpreg(int argc, char **argv)
snprintf(temp_str, MAX_STR_SIZE,
"\r\nDump RSP for vm %hu, from "
"gva 0x%016llx\r\n",
vm_id, cur_context->guest_cpu_regs.regs.rsp);
vm_id, vcpu_get_gpreg(vcpu, CPU_REG_RSP));
shell_puts(temp_str);
for (i = 0UL; i < 8UL; i++) {

View File

@ -152,6 +152,65 @@
#ifndef ASSEMBLER
/**
*
* Identifiers for architecturally defined registers.
*
* These register names is used in condition statement.
* Within the following groups,register name need to be
* kept in order:
* General register names group (CPU_REG_RAX~CPU_REG_R15);
* Non general register names group (CPU_REG_CR0~CPU_REG_GDTR);
* Segement register names group (CPU_REG_ES~CPU_REG_GS).
*/
enum cpu_reg_name {
/* General purpose register layout should align with
* struct cpu_gp_regs
*/
CPU_REG_RAX,
CPU_REG_RCX,
CPU_REG_RDX,
CPU_REG_RBX,
CPU_REG_RSP,
CPU_REG_RBP,
CPU_REG_RSI,
CPU_REG_RDI,
CPU_REG_R8,
CPU_REG_R9,
CPU_REG_R10,
CPU_REG_R11,
CPU_REG_R12,
CPU_REG_R13,
CPU_REG_R14,
CPU_REG_R15,
CPU_REG_CR0,
CPU_REG_CR2,
CPU_REG_CR3,
CPU_REG_CR4,
CPU_REG_DR7,
CPU_REG_RIP,
CPU_REG_RFLAGS,
/*CPU_REG_NATURAL_LAST*/
CPU_REG_EFER,
CPU_REG_PDPTE0,
CPU_REG_PDPTE1,
CPU_REG_PDPTE2,
CPU_REG_PDPTE3,
/*CPU_REG_64BIT_LAST,*/
CPU_REG_ES,
CPU_REG_CS,
CPU_REG_SS,
CPU_REG_DS,
CPU_REG_FS,
CPU_REG_GS,
CPU_REG_LDTR,
CPU_REG_TR,
CPU_REG_IDTR,
CPU_REG_GDTR
/*CPU_REG_LAST*/
};
/**********************************/
/* EXTERNAL VARIABLES */
/**********************************/

View File

@ -263,6 +263,8 @@ struct vcpu {
#ifdef CONFIG_MTRR_ENABLED
struct mtrr_state mtrr;
#endif
uint64_t reg_cached;
uint64_t reg_updated;
};
#define is_vcpu_bsp(vcpu) ((vcpu)->vcpu_id == BOOT_CPU_ID)
@ -273,6 +275,25 @@ static inline void vcpu_retain_rip(struct vcpu *vcpu)
}
/* External Interfaces */
uint64_t vcpu_get_gpreg(struct vcpu *vcpu, uint32_t reg);
void vcpu_set_gpreg(struct vcpu *vcpu, uint32_t reg, uint64_t val);
uint64_t vcpu_get_rip(struct vcpu *vcpu);
void vcpu_set_rip(struct vcpu *vcpu, uint64_t val);
uint64_t vcpu_get_rsp(struct vcpu *vcpu);
void vcpu_set_rsp(struct vcpu *vcpu, uint64_t val);
uint64_t vcpu_get_efer(struct vcpu *vcpu);
void vcpu_set_efer(struct vcpu *vcpu, uint64_t val);
uint64_t vcpu_get_rflags(struct vcpu *vcpu);
void vcpu_set_rflags(struct vcpu *vcpu, uint64_t val);
uint64_t vcpu_get_cr0(struct vcpu *vcpu);
int vcpu_set_cr0(struct vcpu *vcpu, uint64_t val);
uint64_t vcpu_get_cr2(struct vcpu *vcpu);
void vcpu_set_cr2(struct vcpu *vcpu, uint64_t val);
uint64_t vcpu_get_cr4(struct vcpu *vcpu);
int vcpu_set_cr4(struct vcpu *vcpu, uint64_t val);
uint64_t vcpu_get_pat_ext(struct vcpu *vcpu);
void vcpu_set_pat_ext(struct vcpu *vcpu, uint64_t val);
struct vcpu* get_ever_run_vcpu(uint16_t pcpu_id);
int create_vcpu(uint16_t pcpu_id, struct vm *vm, struct vcpu **rtn_vcpu_handle);
int start_vcpu(struct vcpu *vcpu);

View File

@ -447,7 +447,6 @@ uint64_t vmx_rdmsr_pat(struct vcpu *vcpu);
int vmx_wrmsr_pat(struct vcpu *vcpu, uint64_t value);
int vmx_write_cr0(struct vcpu *vcpu, uint64_t cr0);
int vmx_write_cr3(struct vcpu *vcpu, uint64_t cr3);
int vmx_write_cr4(struct vcpu *vcpu, uint64_t cr4);
static inline enum vm_cpu_mode get_vcpu_mode(struct vcpu *vcpu)