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:
Yin Fengwei 2019-12-12 15:58:35 +08:00 committed by wenlingz
parent bfa19e9104
commit f7df43e7cd
3 changed files with 54 additions and 28 deletions

View File

@ -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);
}
/**

View File

@ -82,29 +82,37 @@ 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 (reset) {
if (is_highest_severity_vm(vm)) {
reset_host();
}
} else if (is_postlaunched_vm(vm)) {
/* re-inject to DM */
ret = false;
} else if (is_postlaunched_vm(vm)) {
/* re-inject to DM */
ret = false;
if (reset && 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);
if (is_rt_vm(vm)) {
vm->state = VM_POWERING_OFF;
}
} else {
/*
* 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);
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));
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.
* equivalent to hide this port from guests.
*/
* ignore writes from SOS and pre-launched VM.
* equivalent to hide this port from guests.
*/
}
return ret;
@ -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;
}
/**

View File

@ -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