Skip to content

Commit

Permalink
hv: refine guest AP state init function
Browse files Browse the repository at this point in the history
Because AP always is in real mode with entry defined by sipi
vector. We add function to set AP init state and move the call
to the place where AP got SIPI signal.

We also drop init_guest_context_protect because BSP state init
doesn't call this function any more.

Tracked-On: projectacrn#1231
Signed-off-by: Yin Fengwei <fengwei.yin@intel.com>
  • Loading branch information
fyin1 committed Sep 26, 2018
1 parent c72f8a1 commit 272ab65
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 88 deletions.
35 changes: 35 additions & 0 deletions hypervisor/arch/x86/guest/vcpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,41 @@ void set_vcpu_regs(struct vcpu *vcpu, struct acrn_vcpu_regs *vcpu_regs)
ctx->cr4 = vcpu_regs->cr4;
}

void set_ap_regs(struct vcpu *vcpu)
{
struct ext_context *ectx;
struct run_context *ctx;
struct segment_sel *seg;

ectx = &(vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].ext_ctx);
ctx = &(vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].run_ctx);

/* cs, ss, ds, es, fs, gs; cs will be override later. */
for (seg = &(ectx->cs); seg <= &(ectx->gs); seg++) {
seg->selector = 0U;
seg->base = 0UL;
seg->limit = 0xFFFFU;
seg->attr = REAL_MODE_DATA_SEG_AR;
}

ectx->cs.selector = (uint16_t)(vcpu->arch_vcpu.sipi_vector << 8U);
ectx->cs.base = (uint64_t)ectx->cs.selector << 4U;
ectx->cs.attr = REAL_MODE_CODE_SEG_AR;

ectx->gdtr.base = 0UL;
ectx->gdtr.limit = 0xFFFFU;
ectx->idtr.base = 0UL;
ectx->idtr.limit = 0xFFFFU;

/* cr0, cr3 and cr4 needs be set without using API.
* The real cr0/cr3/cr4 writing will be delayed to
* init_vmcs
*/
ctx->cr0 = CR0_ET | CR0_NE;
ectx->cr3 = 0;
ctx->cr4 = 0;
}

/***********************************************************************
* vcpu_id/pcpu_id mapping table:
*
Expand Down
1 change: 1 addition & 0 deletions hypervisor/arch/x86/guest/vlapic.c
Original file line number Diff line number Diff line change
Expand Up @@ -1212,6 +1212,7 @@ vlapic_icrlo_write_handler(struct acrn_vlapic *vlapic)
pr_err("Start Secondary VCPU%hu for VM[%d]...",
target_vcpu->vcpu_id,
target_vcpu->vm->vm_id);
set_ap_regs(target_vcpu);
schedule_vcpu(target_vcpu);
} else if (mode == APIC_DELMODE_SMI) {
pr_info("vlapic: SMI IPI do not support\n");
Expand Down
90 changes: 2 additions & 88 deletions hypervisor/arch/x86/vmx.c
Original file line number Diff line number Diff line change
Expand Up @@ -497,84 +497,6 @@ void vmx_write_cr4(struct vcpu *vcpu, uint64_t cr4)
cr4, cr4_vmx);
}

static void init_guest_context_real(struct vcpu *vcpu)
{
struct ext_context *ectx =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].ext_ctx;
struct segment_sel *seg;

/* cs, ss, ds, es, fs, gs; cs will be override later. */
for (seg = &(ectx->cs); seg <= &(ectx->gs); seg++) {
seg->selector = 0U;
seg->base = 0UL;
seg->limit = 0xFFFFU;
seg->attr = REAL_MODE_DATA_SEG_AR;
}

if (is_vcpu_bsp(vcpu)) {
/* There are two cases that we will start bsp in real
* mode:
* 1. UOS start
* 2. SOS resume from S3
*
* For 1, DM will set correct entry_addr.
* For 2, SOS resume caller will set entry_addr to
* SOS wakeup vec. According to ACPI FACS spec,
* wakeup vec should be < 1MB. So we use < 1MB
* to detect whether it's resume from S3 and we
* setup CS:IP to
* (wakeup_vec >> 4):(wakeup_vec & 0x000F)
* if it's resume from S3.
*
*/
if ((uint64_t)vcpu->entry_addr < 0x100000UL) {
ectx->cs.selector = (uint16_t)
(((uint64_t)vcpu->entry_addr & 0xFFFF0UL) >> 4U);
ectx->cs.base = (uint64_t)ectx->cs.selector << 4U;
vcpu_set_rip(vcpu, (uint64_t)vcpu->entry_addr & 0x0FUL);
} else {
/* BSP is initialized with real mode */
ectx->cs.selector = REAL_MODE_BSP_INIT_CODE_SEL;
/* For unrestricted guest, it is able
* to set a high base address
*/
ectx->cs.base = (uint64_t)vcpu->entry_addr & 0xFFFF0000UL;
vcpu_set_rip(vcpu, 0x0000FFF0UL);
}
} else {
/* AP is initialized with real mode
* and CS value is left shift 8 bits from sipi vector.
*/
ectx->cs.selector = (uint16_t)(vcpu->arch_vcpu.sipi_vector << 8U);
ectx->cs.base = (uint64_t)ectx->cs.selector << 4U;
}
ectx->cs.attr = REAL_MODE_CODE_SEG_AR;

ectx->gdtr.base = 0UL;
ectx->gdtr.limit = 0xFFFFU;
ectx->idtr.base = 0UL;
ectx->idtr.limit = 0xFFFFU;
}

/* only be called for UOS when bsp start from protected mode */
static void init_guest_context_protect(struct vcpu *vcpu)
{
struct ext_context *ectx =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].ext_ctx;
struct segment_sel *seg;

ectx->gdtr.base = create_guest_init_gdt(vcpu->vm, &ectx->gdtr.limit);
for (seg = &(ectx->cs); seg <= &(ectx->gs); seg++) {
seg->base = 0UL;
seg->limit = 0xFFFFFFFFU;
seg->attr = PROTECTED_MODE_DATA_SEG_AR;
seg->selector = 0x18U;
}
ectx->cs.attr = PROTECTED_MODE_CODE_SEG_AR;
ectx->cs.selector = 0x10U; /* Linear code segment */
vcpu_set_rip(vcpu, (uint64_t)vcpu->entry_addr);
}

/* rip, rsp, ia32_efer and rflags are written to VMCS in start_vcpu */
static void init_guest_vmx(struct vcpu *vcpu, uint64_t cr0, uint64_t cr3,
uint64_t cr4)
Expand Down Expand Up @@ -641,16 +563,8 @@ static void init_guest_state(struct vcpu *vcpu)
ctx->ext_ctx.tr.limit = 0xFFFFU;
ctx->ext_ctx.tr.attr = TR_AR;

if (vcpu_mode == CPU_MODE_REAL) {
init_guest_context_real(vcpu);
init_guest_vmx(vcpu, CR0_ET | CR0_NE, 0UL, 0UL);
} else if (is_vm0(vcpu->vm) && is_vcpu_bsp(vcpu)) {
init_guest_vmx(vcpu, ctx->run_ctx.cr0, ctx->ext_ctx.cr3,
ctx->run_ctx.cr4 & ~CR4_VMXE);
} else {
init_guest_context_protect(vcpu);
init_guest_vmx(vcpu, CR0_ET | CR0_NE | CR0_PE, 0UL, 0UL);
}
init_guest_vmx(vcpu, ctx->run_ctx.cr0, ctx->ext_ctx.cr3,
ctx->run_ctx.cr4 & ~CR4_VMXE);
}

static void init_host_state(void)
Expand Down
1 change: 1 addition & 0 deletions hypervisor/include/arch/x86/guest/vcpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ void 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);
void set_vcpu_regs(struct vcpu *vcpu, struct acrn_vcpu_regs *vcpu_regs);
void set_ap_regs(struct vcpu *vcpu);

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);
Expand Down

0 comments on commit 272ab65

Please sign in to comment.