Skip to content

Commit bfa19e9

Browse files
fyin1wenlingz
authored andcommitted
pm: S5: update the system shutdown logical in ACRN
For system S5, ACRN had assumption that SOS shutdown will trigger system shutdown. So the system shutdown logical is: 1. Trap SOS shutdown 2. Wait for all other guest shutdown 3. Shutdown system The new logical is refined as: If all guest is shutdown, shutdown whole system Tracked-On: #4270 Signed-off-by: Yin Fengwei <fengwei.yin@intel.com>
1 parent 197e4a0 commit bfa19e9

File tree

4 files changed

+45
-39
lines changed

4 files changed

+45
-39
lines changed

hypervisor/arch/x86/guest/pm.c

Lines changed: 10 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <logmsg.h>
1212
#include <platform_acpi_info.h>
1313
#include <guest_pm.h>
14+
#include <per_cpu.h>
1415

1516
int32_t validate_pstate(const struct acrn_vm *vm, uint64_t perf_ctl)
1617
{
@@ -149,45 +150,18 @@ static bool pm1ab_io_read(struct acrn_vcpu *vcpu, uint16_t addr, size_t width)
149150
return true;
150151
}
151152

152-
#define POWEROFF_TIMEOUT (300U) /* default poweroff timeout is 5 minutes */
153-
/* wait for other vm shutdown done. If POWEROFF_TIMEOUT passed and there are
154-
* still some VMs active, we will force platform power off.
155-
*
156-
* TODO:
157-
* - Let user configure whether we wait for ever till all VMs powered off or
158-
* force shutdown once pre-defined timeout hit.
159-
*/
160-
static inline void wait_for_other_vm_shutdown(const struct acrn_vm *self_vm)
153+
static inline void enter_s5(struct acrn_vm *vm, uint32_t pm1a_cnt_val, uint32_t pm1b_cnt_val)
161154
{
162-
uint16_t vm_id;
163-
bool ready_for_s5;
164-
uint32_t timeout = (uint32_t)POWEROFF_TIMEOUT;
165-
struct acrn_vm *vm;
166-
167-
while (timeout != 0U) {
168-
ready_for_s5 = true;
169-
for (vm_id = 0U; vm_id < CONFIG_MAX_VM_NUM; vm_id++) {
170-
vm = get_vm_from_vmid(vm_id);
171-
172-
if ((vm != self_vm) && (!is_poweroff_vm(vm))) {
173-
ready_for_s5 = false;
174-
}
175-
}
176-
177-
if (ready_for_s5) {
178-
break;
179-
} else {
180-
udelay(1000U * 1000U); /* delay 1s in each loop */
181-
}
182-
183-
timeout--;
155+
/*
156+
* It's possible that ACRN come here from SOS and pre-launched VM. Currently, we
157+
* assume SOS has full ACPI power management stack. That means the value from SOS
158+
* should be saved and used to shutdown the system.
159+
*/
160+
if (is_sos_vm(vm)) {
161+
save_s5_reg_val(pm1a_cnt_val, pm1b_cnt_val);
184162
}
185-
}
186163

187-
static inline void enter_s5(const struct acrn_vm *vm, uint32_t pm1a_cnt_val, uint32_t pm1b_cnt_val)
188-
{
189-
wait_for_other_vm_shutdown(vm);
190-
host_enter_s5(vm->pm.sx_state_data, pm1a_cnt_val, pm1b_cnt_val);
164+
(void)shutdown_vm(vm);
191165
}
192166

193167
static inline void enter_s3(struct acrn_vm *vm, uint32_t pm1a_cnt_val, uint32_t pm1b_cnt_val)

hypervisor/arch/x86/guest/vm.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,24 @@ int32_t create_vm(uint16_t vm_id, struct acrn_vm_config *vm_config, struct acrn_
580580
return status;
581581
}
582582

583+
static bool is_ready_for_system_shutdown(void)
584+
{
585+
bool ret = true;
586+
uint16_t vm_id;
587+
struct acrn_vm *vm;
588+
589+
for (vm_id = 0U; vm_id < CONFIG_MAX_VM_NUM; vm_id++) {
590+
vm = get_vm_from_vmid(vm_id);
591+
/* TODO: Update code to cover hybrid mode */
592+
if (!is_poweroff_vm(vm)) {
593+
ret = false;
594+
break;
595+
}
596+
}
597+
598+
return ret;
599+
}
600+
583601
/*
584602
* @pre vm != NULL
585603
*/
@@ -648,6 +666,11 @@ int32_t shutdown_vm(struct acrn_vm *vm)
648666
ret = -EINVAL;
649667
}
650668

669+
if (is_ready_for_system_shutdown()) {
670+
/* If no any guest running, shutdown system */
671+
shutdown_system();
672+
}
673+
651674
/* Return status to caller */
652675
return ret;
653676
}

hypervisor/arch/x86/pm.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,9 +148,17 @@ void do_acpi_sx(const struct pm_s_state_data *sstate_data, uint32_t pm1a_cnt_val
148148
} while ((s1 & (1U << BIT_WAK_STS)) == 0U);
149149
}
150150

151-
void host_enter_s5(const struct pm_s_state_data *sstate_data, uint32_t pm1a_cnt_val, uint32_t pm1b_cnt_val)
151+
static uint32_t system_pm1a_cnt_val, system_pm1b_cnt_val;
152+
void save_s5_reg_val(uint32_t pm1a_cnt_val, uint32_t pm1b_cnt_val)
152153
{
153-
do_acpi_sx(sstate_data, pm1a_cnt_val, pm1b_cnt_val);
154+
system_pm1a_cnt_val = pm1a_cnt_val;
155+
system_pm1b_cnt_val = pm1b_cnt_val;
156+
}
157+
158+
void shutdown_system(void)
159+
{
160+
struct pm_s_state_data *sx_data = get_host_sstate_data();
161+
do_acpi_sx(sx_data, system_pm1a_cnt_val, system_pm1b_cnt_val);
154162
}
155163

156164
static void suspend_tsc(__unused void *data)

hypervisor/include/arch/x86/host_pm.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ struct acpi_reset_reg {
3131

3232
struct pm_s_state_data *get_host_sstate_data(void);
3333
void host_enter_s3(const struct pm_s_state_data *sstate_data, uint32_t pm1a_cnt_val, uint32_t pm1b_cnt_val);
34-
void host_enter_s5(const struct pm_s_state_data *sstate_data, uint32_t pm1a_cnt_val, uint32_t pm1b_cnt_val);
34+
void shutdown_system(void);
35+
void save_s5_reg_val(uint32_t pm1a_cnt_val, uint32_t pm1b_cnt_val);
3536
void do_acpi_sx(const struct pm_s_state_data *sstate_data, uint32_t pm1a_cnt_val, uint32_t pm1b_cnt_val);
3637
extern void asm_enter_s3(const struct pm_s_state_data *sstate_data, uint32_t pm1a_cnt_val, uint32_t pm1b_cnt_val);
3738
extern void restore_s3_context(void);

0 commit comments

Comments
 (0)