hv: Make bsp could start from real mode

S3 resume path for VM0 is put bsp of VM0 to real mode and jump
to the wakeup vec of VM0. So we need to extend the init_guest_state
to support start from real mode.

We apply different CS:IP setting for BSP:
 - if entry_addr of BSP is larger than 0x100000, it's not wakeup
   from S3. We assume it's guest start and set CS:IP by hardcode.
 - if entry_addr of BSP is smaller than 0x100000, it's wakeup
   from S3. We setup CS:IP according to ACPI spec.

Signed-off-by: Victor Sun <victor.sun@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Yin Fengwei 2018-06-14 22:43:15 +08:00 committed by Xie, nanlin
parent 0f9d9641d4
commit baacfdbce9
1 changed files with 38 additions and 13 deletions

View File

@ -525,13 +525,34 @@ static void init_guest_state(struct vcpu *vcpu)
/***************************************************/
if (vcpu_mode == CPU_MODE_REAL) {
if (is_vcpu_bsp(vcpu)) {
ASSERT(!is_vm0(vcpu->vm),
"VM0 bsp should not be inited as realmode");
/* BP is initialized with real mode */
sel = REAL_MODE_BSP_INIT_CODE_SEL;
/* For unrestricted guest, it is able to set a
* high base address */
base = (uint64_t)vcpu->entry_addr & 0xFFFF0000UL;
/* 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 < 0x100000) {
sel =((uint64_t)vcpu->entry_addr & 0xFFFF0)
>> 4;
base = sel << 4;
} else {
/* BSP is initialized with real mode */
sel = REAL_MODE_BSP_INIT_CODE_SEL;
/* For unrestricted guest, it is able
* to set a high base address
*/
base = (uint64_t)vcpu->entry_addr &
0xFFFF0000UL;
}
} else {
/* AP is initialized with real mode
* and CS value is left shift 8 bits from sipi vector;
@ -578,12 +599,16 @@ static void init_guest_state(struct vcpu *vcpu)
/***************************************************/
/* Set up guest instruction pointer */
field = VMX_GUEST_RIP;
if (vcpu_mode == CPU_MODE_REAL)
if (is_vcpu_bsp(vcpu))
value32 = 0x0000FFF0;
else
value32 = 0;
else
value32 = 0;
if (vcpu_mode == CPU_MODE_REAL) {
/* RIP is set here */
if (is_vcpu_bsp(vcpu)) {
if ((uint64_t)vcpu->entry_addr < 0x100000)
value32 = (uint64_t)vcpu->entry_addr & 0x0F;
else
value32 = 0x0000FFF0;
}
} else
value32 = (uint32_t)((uint64_t)vcpu->entry_addr);
pr_dbg("GUEST RIP on VMEntry %x ", value32);