Skip to content

Commit f3627d4

Browse files
Sainath Grandhiwenlingz
authored andcommitted
hv: Add update_vm_vlapic_state API to sync the VM vLAPIC state
This patch introduces vLAPIC state for a VM. The VM vLAPIC state can be one of the following * VM_VLAPIC_X2APIC - All the vCPUs/vLAPICs (Except for those in Disabled mode) of this VM use x2APIC mode * VM_VLAPIC_XAPIC - All the vCPUs/vLAPICs (Except for those in Disabled mode) of this VM use xAPIC mode * VM_VLAPIC_DISABLED - All the vCPUs/vLAPICs of this VM are in Disabled mode * VM_VLAPIC_TRANSITION - Some of the vCPUs/vLAPICs of this VM (Except for those in Disabled mode) are in xAPIC and the others in x2APIC Upon a vCPU updating the IA32_APIC_BASE MSR to switch LAPIC mode, this API is called to sync the vLAPIC state of the VM. Upon VM creation and reset, vLAPIC state is set to VM_VLAPIC_XAPIC, as ACRN starts the vCPUs vLAPIC in XAPIC mode. Tracked-On: #3253 Signed-off-by: Sainath Grandhi <sainath.grandhi@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
1 parent a3fdc7a commit f3627d4

File tree

3 files changed

+94
-1
lines changed

3 files changed

+94
-1
lines changed

hypervisor/arch/x86/guest/vlapic.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1763,6 +1763,7 @@ int32_t vlapic_set_apicbase(struct acrn_vlapic *vlapic, uint64_t new)
17631763
int32_t ret = 0;
17641764
uint64_t changed;
17651765
bool change_in_vlapic_mode = false;
1766+
struct acrn_vcpu *vcpu = vlapic->vcpu;
17661767

17671768

17681769
if (vlapic->msr_apicbase != new) {
@@ -1783,6 +1784,7 @@ int32_t vlapic_set_apicbase(struct acrn_vlapic *vlapic, uint64_t new)
17831784
vlapic->msr_apicbase = new;
17841785
vlapic_build_x2apic_id(vlapic);
17851786
switch_apicv_mode_x2apic(vlapic->vcpu);
1787+
update_vm_vlapic_state(vcpu->vm);
17861788
} else {
17871789
/*
17881790
* TODO: Logic to check for Invalid transitions, Invalid State

hypervisor/arch/x86/guest/vm.c

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,9 @@ int32_t create_vm(uint16_t vm_id, struct acrn_vm_config *vm_config, struct acrn_
477477

478478
INIT_LIST_HEAD(&vm->softirq_dev_entry_list);
479479
spinlock_init(&vm->softirq_dev_lock);
480+
spinlock_init(&vm->vm_lock);
481+
482+
vm->arch_vm.vlapic_state = VM_VLAPIC_XAPIC;
480483
vm->intr_inject_delay_delta = 0UL;
481484

482485
/* Set up IO bit-mask such that VM exit occurs on
@@ -622,6 +625,11 @@ int32_t reset_vm(struct acrn_vm *vm)
622625
foreach_vcpu(i, vm, vcpu) {
623626
reset_vcpu(vcpu);
624627
}
628+
/*
629+
* Set VM vLAPIC state to VM_VLAPIC_XAPIC
630+
*/
631+
632+
vm->arch_vm.vlapic_state = VM_VLAPIC_XAPIC;
625633

626634
if (is_sos_vm(vm)) {
627635
(void )vm_sw_loader(vm);
@@ -632,6 +640,7 @@ int32_t reset_vm(struct acrn_vm *vm)
632640
destroy_secure_world(vm, false);
633641
vm->sworld_control.flag.active = 0UL;
634642
vm->state = VM_CREATED;
643+
635644
ret = 0;
636645
} else {
637646
ret = -1;
@@ -759,3 +768,76 @@ void launch_vms(uint16_t pcpu_id)
759768
}
760769
}
761770
}
771+
772+
/*
773+
* @brief Update state of vLAPICs of a VM
774+
* vLAPICs of VM switch between modes in an asynchronous fashion. This API
775+
* captures the "transition" state triggered when one vLAPIC switches mode.
776+
* When the VM is created, the state is set to "xAPIC" as all vLAPICs are setup
777+
* in xAPIC mode.
778+
*
779+
* Upon reset, all LAPICs switch to xAPIC mode accroding to SDM 10.12.5
780+
* Considering VM uses x2apic mode for vLAPIC, in reset or shutdown flow, vLAPIC state
781+
* moves to "xAPIC" directly without going thru "transition".
782+
*
783+
* VM_VLAPIC_X2APIC - All the online vCPUs/vLAPICs of this VM use x2APIC mode
784+
* VM_VLAPIC_XAPIC - All the online vCPUs/vLAPICs of this VM use xAPIC mode
785+
* VM_VLAPIC_DISABLED - All the online vCPUs/vLAPICs of this VM are in Disabled mode
786+
* VM_VLAPIC_TRANSITION - Online vCPUs/vLAPICs of this VM are in between transistion
787+
*
788+
* TODO: offline_vcpu need to call this API to reflect the status of rest of the
789+
* vLAPICs that are online.
790+
*
791+
* @pre vm != NULL
792+
*/
793+
void update_vm_vlapic_state(struct acrn_vm *vm)
794+
{
795+
uint16_t i;
796+
struct acrn_vcpu *vcpu;
797+
uint16_t vcpus_in_x2apic, vcpus_in_xapic;
798+
enum vm_vlapic_state vlapic_state = VM_VLAPIC_XAPIC;
799+
800+
vcpus_in_x2apic = 0U;
801+
vcpus_in_xapic = 0U;
802+
spinlock_obtain(&vm->vm_lock);
803+
foreach_vcpu(i, vm, vcpu) {
804+
if (is_x2apic_enabled(vcpu_vlapic(vcpu))) {
805+
vcpus_in_x2apic++;
806+
} else if (is_xapic_enabled(vcpu_vlapic(vcpu))) {
807+
vcpus_in_xapic++;
808+
} else {
809+
/*
810+
* vCPU is using vLAPIC in Disabled mode
811+
*/
812+
}
813+
}
814+
815+
if ((vcpus_in_x2apic == 0U) && (vcpus_in_xapic == 0U)) {
816+
/*
817+
* Check if the counts vcpus_in_x2apic and vcpus_in_xapic are zero
818+
* VM_VLAPIC_DISABLED
819+
*/
820+
vlapic_state = VM_VLAPIC_DISABLED;
821+
} else if ((vcpus_in_x2apic != 0U) && (vcpus_in_xapic != 0U)) {
822+
/*
823+
* Check if the counts vcpus_in_x2apic and vcpus_in_xapic are non-zero
824+
* VM_VLAPIC_TRANSITION
825+
*/
826+
vlapic_state = VM_VLAPIC_TRANSITION;
827+
} else if (vcpus_in_x2apic != 0U) {
828+
/*
829+
* Check if the counts vcpus_in_x2apic is non-zero
830+
* VM_VLAPIC_X2APIC
831+
*/
832+
vlapic_state = VM_VLAPIC_X2APIC;
833+
} else {
834+
/*
835+
* Count vcpus_in_xapic is non-zero
836+
* VM_VLAPIC_XAPIC
837+
*/
838+
vlapic_state = VM_VLAPIC_XAPIC;
839+
}
840+
841+
vm->arch_vm.vlapic_state = vlapic_state;
842+
spinlock_release(&vm->vm_lock);
843+
}

hypervisor/include/arch/x86/guest/vm.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@ enum vm_state {
7676
VM_PAUSED, /* VM paused */
7777
};
7878

79+
enum vm_vlapic_state {
80+
VM_VLAPIC_DISABLED = 0U,
81+
VM_VLAPIC_XAPIC,
82+
VM_VLAPIC_X2APIC,
83+
VM_VLAPIC_TRANSITION
84+
};
85+
7986
struct vm_arch {
8087
/* I/O bitmaps A and B for this VM, MUST be 4-Kbyte aligned */
8188
uint8_t io_bitmap[PAGE_SIZE*2];
@@ -93,6 +100,7 @@ struct vm_arch {
93100
void *tmp_pg_array; /* Page array for tmp guest paging struct */
94101
struct acrn_vioapic vioapic; /* Virtual IOAPIC base address */
95102
struct acrn_vpic vpic; /* Virtual PIC */
103+
enum vm_vlapic_state vlapic_state; /* Represents vLAPIC state across vCPUs*/
96104

97105
/* reference to virtual platform to come here (as needed) */
98106
} __aligned(PAGE_SIZE);
@@ -109,7 +117,7 @@ struct acrn_vm {
109117
struct acrn_vuart vuart[MAX_VUART_NUM_PER_VM]; /* Virtual UART */
110118
enum vpic_wire_mode wire_mode;
111119
struct iommu_domain *iommu; /* iommu domain of this VM */
112-
spinlock_t spinlock; /* Spin-lock used to protect VM modifications */
120+
spinlock_t vm_lock; /* Spin-lock used to protect VM modifications */
113121

114122
uint16_t emul_mmio_regions; /* Number of emulated mmio regions */
115123
struct mem_io_node emul_mmio[CONFIG_MAX_EMULATED_MMIO_REGIONS];
@@ -218,6 +226,7 @@ bool is_lapic_pt_configured(const struct acrn_vm *vm);
218226
bool is_rt_vm(const struct acrn_vm *vm);
219227
bool is_highest_severity_vm(const struct acrn_vm *vm);
220228
bool vm_hide_mtrr(const struct acrn_vm *vm);
229+
void update_vm_vlapic_state(struct acrn_vm *vm);
221230

222231
#endif /* !ASSEMBLER */
223232

0 commit comments

Comments
 (0)