Skip to content

Commit a5158e2

Browse files
jsun26intelwenlingz
authored andcommitted
HV: refine reset_vcpu api
The patch abstract a vcpu_reset_internal() api for internal usage, the function would not touch any vcpu state transition and just do vcpu reset processing. It will be called by create_vcpu() and reset_vcpu(). The reset_vcpu() will act as a public api and should be called only when vcpu receive INIT or vm reset/resume from S3. It should not be called when do shutdown_vm() or hcall_sos_offline_cpu(), so the patch remove reset_vcpu() in shutdown_vm() and hcall_sos_offline_cpu(). The patch also introduced reset_mode enum so that vcpu and vlapic could do different context operation according to different reset mode; Tracked-On: #4267 Signed-off-by: Victor Sun <victor.sun@intel.com> Reviewed-by: Jason Chen CJ <jason.cj.chen@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
1 parent d1a46b8 commit a5158e2

File tree

6 files changed

+47
-47
lines changed

6 files changed

+47
-47
lines changed

hypervisor/arch/x86/guest/vcpu.c

Lines changed: 33 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,35 @@ void vcpu_reset_eoi_exit_bitmaps(struct acrn_vcpu *vcpu)
193193
vcpu_make_request(vcpu, ACRN_REQUEST_EOI_EXIT_BITMAP_UPDATE);
194194
}
195195

196+
/* As a vcpu reset internal API, DO NOT touch any vcpu state transition in this function. */
197+
static void vcpu_reset_internal(struct acrn_vcpu *vcpu, __unused enum reset_mode mode)
198+
{
199+
int32_t i;
200+
struct acrn_vlapic *vlapic;
201+
202+
vcpu->launched = false;
203+
vcpu->running = false;
204+
vcpu->arch.nr_sipi = 0U;
205+
206+
vcpu->arch.exception_info.exception = VECTOR_INVALID;
207+
vcpu->arch.cur_context = NORMAL_WORLD;
208+
vcpu->arch.irq_window_enabled = false;
209+
(void)memset((void *)vcpu->arch.vmcs, 0U, PAGE_SIZE);
210+
211+
for (i = 0; i < NR_WORLD; i++) {
212+
(void)memset((void *)(&vcpu->arch.contexts[i]), 0U,
213+
sizeof(struct run_context));
214+
}
215+
216+
/* TODO: we may need to add one scheduler->reset_data to reset the thread_obj */
217+
vcpu->thread_obj.notify_mode = SCHED_NOTIFY_IPI;
218+
219+
vlapic = vcpu_vlapic(vcpu);
220+
vlapic_reset(vlapic, apicv_ops);
221+
222+
reset_vcpu_regs(vcpu);
223+
}
224+
196225
struct acrn_vcpu *get_running_vcpu(uint16_t pcpu_id)
197226
{
198227
struct thread_object *curr = sched_get_current(pcpu_id);
@@ -445,12 +474,6 @@ int32_t create_vcpu(uint16_t pcpu_id, struct acrn_vm *vm, struct acrn_vcpu **rtn
445474
*/
446475
vcpu->arch.vpid = 1U + (vm->vm_id * MAX_VCPUS_PER_VM) + vcpu->vcpu_id;
447476

448-
/* Initialize exception field in VCPU context */
449-
vcpu->arch.exception_info.exception = VECTOR_INVALID;
450-
451-
/* Initialize cur context */
452-
vcpu->arch.cur_context = NORMAL_WORLD;
453-
454477
/* Create per vcpu vlapic */
455478
vlapic_create(vcpu);
456479

@@ -460,14 +483,10 @@ int32_t create_vcpu(uint16_t pcpu_id, struct acrn_vm *vm, struct acrn_vcpu **rtn
460483

461484
/* Populate the return handle */
462485
*rtn_vcpu_handle = vcpu;
463-
464-
vcpu->launched = false;
465-
vcpu->running = false;
466-
vcpu->arch.nr_sipi = 0U;
467486
vcpu->state = VCPU_INIT;
468487

469488
init_xsave(vcpu);
470-
reset_vcpu_regs(vcpu);
489+
vcpu_reset_internal(vcpu, POWER_ON_RESET);
471490
(void)memset((void *)&vcpu->req, 0U, sizeof(struct io_request));
472491
vm->hw.created_vcpus++;
473492
ret = 0;
@@ -655,40 +674,15 @@ static uint64_t build_stack_frame(struct acrn_vcpu *vcpu)
655674
/* NOTE:
656675
* vcpu should be paused before call this function.
657676
*/
658-
void reset_vcpu(struct acrn_vcpu *vcpu)
677+
void reset_vcpu(struct acrn_vcpu *vcpu, enum reset_mode mode)
659678
{
660-
int32_t i;
661-
struct acrn_vlapic *vlapic;
662-
663679
pr_dbg("vcpu%hu reset", vcpu->vcpu_id);
664680
ASSERT(vcpu->state != VCPU_RUNNING,
665681
"reset vcpu when it's running");
666682

667683
if (vcpu->state != VCPU_INIT) {
684+
vcpu_reset_internal(vcpu, mode);
668685
vcpu->state = VCPU_INIT;
669-
670-
vcpu->launched = false;
671-
vcpu->running = false;
672-
vcpu->arch.nr_sipi = 0U;
673-
674-
vcpu->arch.exception_info.exception = VECTOR_INVALID;
675-
vcpu->arch.cur_context = NORMAL_WORLD;
676-
vcpu->arch.irq_window_enabled = false;
677-
(void)memset((void *)vcpu->arch.vmcs, 0U, PAGE_SIZE);
678-
679-
for (i = 0; i < NR_WORLD; i++) {
680-
(void)memset((void *)(&vcpu->arch.contexts[i]), 0U,
681-
sizeof(struct run_context));
682-
}
683-
vcpu->arch.cur_context = NORMAL_WORLD;
684-
685-
/* TODO: we may need to add one scheduler->reset_data to reset the thread_obj */
686-
vcpu->thread_obj.notify_mode = SCHED_NOTIFY_IPI;
687-
688-
vlapic = vcpu_vlapic(vcpu);
689-
vlapic_reset(vlapic, apicv_ops);
690-
691-
reset_vcpu_regs(vcpu);
692686
}
693687
}
694688

@@ -806,7 +800,7 @@ int32_t prepare_vcpu(struct acrn_vm *vm, uint16_t pcpu_id)
806800
vcpu->thread_obj.sched_ctl = &per_cpu(sched_ctl, pcpu_id);
807801
vcpu->thread_obj.thread_entry = vcpu_thread;
808802
vcpu->thread_obj.pcpu_id = pcpu_id;
809-
vcpu->thread_obj.notify_mode = SCHED_NOTIFY_IPI;
803+
/* vcpu->thread_obj.notify_mode is initialized in vcpu_reset_internal() when create vcpu */
810804
vcpu->thread_obj.host_sp = build_stack_frame(vcpu);
811805
vcpu->thread_obj.switch_out = context_switch_out;
812806
vcpu->thread_obj.switch_in = context_switch_in;

hypervisor/arch/x86/guest/vlapic.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,7 +1163,7 @@ vlapic_process_init_sipi(struct acrn_vcpu* target_vcpu, uint32_t mode, uint32_t
11631163

11641164
/* put target vcpu to INIT state and wait for SIPI */
11651165
pause_vcpu(target_vcpu, VCPU_PAUSED);
1166-
reset_vcpu(target_vcpu);
1166+
reset_vcpu(target_vcpu, INIT_RESET);
11671167
/* new cpu model only need one SIPI to kick AP run,
11681168
* the second SIPI will be ignored as it move out of
11691169
* wait-for-SIPI state.
@@ -1686,8 +1686,6 @@ void
16861686
vlapic_init(struct acrn_vlapic *vlapic)
16871687
{
16881688
vlapic_init_timer(vlapic);
1689-
1690-
vlapic_reset(vlapic, apicv_ops);
16911689
}
16921690

16931691
void vlapic_restore(struct acrn_vlapic *vlapic, const struct lapic_regs *regs)

hypervisor/arch/x86/guest/vm.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -650,7 +650,6 @@ int32_t shutdown_vm(struct acrn_vm *vm)
650650
}
651651

652652
foreach_vcpu(i, vm, vcpu) {
653-
reset_vcpu(vcpu);
654653
offline_vcpu(vcpu);
655654

656655
if (bitmap_test(pcpuid_from_vcpu(vcpu), &mask)) {
@@ -737,7 +736,7 @@ int32_t reset_vm(struct acrn_vm *vm)
737736
}
738737

739738
foreach_vcpu(i, vm, vcpu) {
740-
reset_vcpu(vcpu);
739+
reset_vcpu(vcpu, COLD_RESET);
741740

742741
if (bitmap_test(pcpuid_from_vcpu(vcpu), &mask)) {
743742
make_pcpu_offline(pcpuid_from_vcpu(vcpu));
@@ -824,7 +823,7 @@ void resume_vm_from_s3(struct acrn_vm *vm, uint32_t wakeup_vec)
824823

825824
vm->state = VM_STARTED;
826825

827-
reset_vcpu(bsp);
826+
reset_vcpu(bsp, POWER_ON_RESET);
828827

829828
/* When SOS resume from S3, it will return to real mode
830829
* with entry set to wakeup_vec.

hypervisor/common/hypercall.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ int32_t hcall_sos_offline_cpu(struct acrn_vm *vm, uint64_t lapicid)
6464
break;
6565
}
6666
pause_vcpu(vcpu, VCPU_ZOMBIE);
67-
reset_vcpu(vcpu);
6867
offline_vcpu(vcpu);
6968
}
7069
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ enum vm_cpu_mode {
146146
CPU_MODE_64BIT, /* IA-32E mode (CS.L = 1) */
147147
};
148148

149+
enum reset_mode;
149150

150151
/* 2 worlds: 0 for Normal World, 1 for Secure World */
151152
#define NR_WORLD 2
@@ -600,10 +601,11 @@ void offline_vcpu(struct acrn_vcpu *vcpu);
600601
* Reset all fields in a vCPU instance, the vCPU state is reset to VCPU_INIT.
601602
*
602603
* @param[inout] vcpu pointer to vcpu data structure
604+
* @param[in] mode the reset mode
603605
*
604606
* @return None
605607
*/
606-
void reset_vcpu(struct acrn_vcpu *vcpu);
608+
void reset_vcpu(struct acrn_vcpu *vcpu, enum reset_mode mode);
607609

608610
/**
609611
* @brief pause the vcpu and set new state

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@
3030
#include <hyperv.h>
3131
#endif
3232

33+
enum reset_mode {
34+
POWER_ON_RESET, /* reset by hardware Power-on */
35+
COLD_RESET, /* hardware cold reset */
36+
WARM_RESET, /* behavior slightly differ from cold reset, that some MSRs might be retained. */
37+
INIT_RESET, /* reset by INIT */
38+
SOFTWARE_RESET, /* reset by software disable<->enable */
39+
};
40+
3341
struct vm_hw_info {
3442
/* vcpu array of this VM */
3543
struct acrn_vcpu vcpu_array[MAX_VCPUS_PER_VM];

0 commit comments

Comments
 (0)