reset: detect highest severity guest dynamically
For guest reset, if the highest severity guest reset will reset system. There is vm flag to call out the highest severity guest in specific scenario which is a static guest severity assignment. There is case that the static highest severity guest is shutdown and the highest severity guest should be transfer to other guest. For example, in ISD scenario, if RTVM (static highest severity guest) is shutdown, SOS should be highest severity guest instead. The is_highest_severity_vm() is updated to detect highest severity guest dynamically. And promote the highest severity guest reset to system reset. Also remove the GUEST_FLAG_HIGHEST_SEVERITY definition. Tracked-On: #4270 Signed-off-by: Yin Fengwei <fengwei.yin@intel.com>
This commit is contained in:
parent
bfa19e9104
commit
f7df43e7cd
|
@ -117,14 +117,35 @@ bool is_rt_vm(const struct acrn_vm *vm)
|
|||
return ((vm_config->guest_flags & GUEST_FLAG_RT) != 0U);
|
||||
}
|
||||
|
||||
static struct acrn_vm *get_highest_severity_vm(void)
|
||||
{
|
||||
uint16_t vm_id, highest_vm_id = 0U;
|
||||
struct acrn_vm *vm = NULL;
|
||||
struct acrn_vm_config *vm_config;
|
||||
|
||||
for (vm_id = 1U; vm_id < CONFIG_MAX_VM_NUM; vm_id++) {
|
||||
vm = get_vm_from_vmid(vm_id);
|
||||
|
||||
if (is_poweroff_vm(vm)) {
|
||||
/* If vm is non-existed or shutdown, it's not highest severity VM */
|
||||
continue;
|
||||
}
|
||||
|
||||
vm_config = get_vm_config(vm_id);
|
||||
if (vm_config->severity > get_vm_config(highest_vm_id)->severity) {
|
||||
highest_vm_id = vm_id;
|
||||
}
|
||||
}
|
||||
|
||||
return get_vm_from_vmid(highest_vm_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @pre vm != NULL && vm_config != NULL && vm->vmid < CONFIG_MAX_VM_NUM
|
||||
*/
|
||||
bool is_highest_severity_vm(const struct acrn_vm *vm)
|
||||
{
|
||||
struct acrn_vm_config *vm_config = get_vm_config(vm->vm_id);
|
||||
|
||||
return ((vm_config->guest_flags & GUEST_FLAG_HIGHEST_SEVERITY) != 0U);
|
||||
return (get_highest_severity_vm() == vm);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -82,27 +82,35 @@ static bool handle_common_reset_reg_write(struct acrn_vm *vm, bool reset)
|
|||
{
|
||||
bool ret = true;
|
||||
|
||||
if (is_highest_severity_vm(vm)) {
|
||||
if (reset) {
|
||||
if (is_highest_severity_vm(vm)) {
|
||||
reset_host();
|
||||
}
|
||||
} else if (is_postlaunched_vm(vm)) {
|
||||
/* re-inject to DM */
|
||||
ret = false;
|
||||
|
||||
if (reset && is_rt_vm(vm)) {
|
||||
if (is_rt_vm(vm)) {
|
||||
vm->state = VM_POWERING_OFF;
|
||||
}
|
||||
} else if (is_prelaunched_vm(vm)) {
|
||||
/* Don't support re-launch for now, just shutdown the guest */
|
||||
pause_vm(vm);
|
||||
|
||||
struct acrn_vcpu *bsp = vcpu_from_vid(vm, BOOT_CPU_ID);
|
||||
per_cpu(shutdown_vm_id, pcpuid_from_vcpu(bsp)) = vm->vm_id;
|
||||
make_shutdown_vm_request(pcpuid_from_vcpu(bsp));
|
||||
} else {
|
||||
/*
|
||||
* ignore writes from SOS.
|
||||
* If it's SOS reset while RTVM is still alive
|
||||
* or pre-launched VM reset,
|
||||
* ACRN doesn't support re-launch, just shutdown the guest.
|
||||
*/
|
||||
const struct acrn_vcpu *bsp = vcpu_from_vid(vm, BOOT_CPU_ID);
|
||||
|
||||
pause_vm(vm);
|
||||
per_cpu(shutdown_vm_id, pcpuid_from_vcpu(bsp)) = vm->vm_id;
|
||||
make_shutdown_vm_request(pcpuid_from_vcpu(bsp));
|
||||
}
|
||||
} else {
|
||||
if (is_postlaunched_vm(vm)) {
|
||||
/* If post-launched VM write none reset value, re-inject to DM */
|
||||
ret = false;
|
||||
}
|
||||
/*
|
||||
* ignore writes from SOS and pre-launched VM.
|
||||
* equivalent to hide this port from guests.
|
||||
*/
|
||||
}
|
||||
|
@ -158,15 +166,13 @@ static bool handle_cf9_write(struct acrn_vcpu *vcpu, __unused uint16_t addr, siz
|
|||
*/
|
||||
static bool handle_reset_reg_write(struct acrn_vcpu *vcpu, uint16_t addr, size_t bytes, uint32_t val)
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
if (bytes == 1U) {
|
||||
struct acpi_reset_reg *reset_reg = get_host_reset_reg_data();
|
||||
|
||||
if (val == reset_reg->val) {
|
||||
if (is_highest_severity_vm(vcpu->vm)) {
|
||||
reset_host();
|
||||
} else {
|
||||
/* ignore reset request */
|
||||
}
|
||||
ret = handle_common_reset_reg_write(vcpu->vm, true);
|
||||
} else {
|
||||
/*
|
||||
* ACPI defines the reset value but doesn't specify the meaning of other values.
|
||||
|
@ -177,7 +183,7 @@ static bool handle_reset_reg_write(struct acrn_vcpu *vcpu, uint16_t addr, size_t
|
|||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -53,7 +53,6 @@
|
|||
#define GUEST_FLAG_CLOS_REQUIRED (1UL << 3U) /* Whether CLOS is required */
|
||||
#define GUEST_FLAG_HIDE_MTRR (1UL << 4U) /* Whether hide MTRR from VM */
|
||||
#define GUEST_FLAG_RT (1UL << 5U) /* Whether the vm is RT-VM */
|
||||
#define GUEST_FLAG_HIGHEST_SEVERITY (1UL << 6U) /* Whether has the highest severity */
|
||||
|
||||
/* TODO: We may need to get this addr from guest ACPI instead of hardcode here */
|
||||
#define VIRTUAL_PM1A_CNT_ADDR 0x404U
|
||||
|
|
Loading…
Reference in New Issue