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

@@ -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__);