From f7df43e7cd5c6cbf5cfe796634dfb6762270602e Mon Sep 17 00:00:00 2001 From: Yin Fengwei Date: Thu, 12 Dec 2019 15:58:35 +0800 Subject: [PATCH] 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 --- hypervisor/arch/x86/guest/vm.c | 27 +++++++++++-- hypervisor/arch/x86/guest/vm_reset.c | 54 ++++++++++++++----------- hypervisor/include/public/acrn_common.h | 1 - 3 files changed, 54 insertions(+), 28 deletions(-) diff --git a/hypervisor/arch/x86/guest/vm.c b/hypervisor/arch/x86/guest/vm.c index 64c1e159d..37dc29550 100644 --- a/hypervisor/arch/x86/guest/vm.c +++ b/hypervisor/arch/x86/guest/vm.c @@ -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); } /** diff --git a/hypervisor/arch/x86/guest/vm_reset.c b/hypervisor/arch/x86/guest/vm_reset.c index 9e26f0b35..6a3bc77e7 100644 --- a/hypervisor/arch/x86/guest/vm_reset.c +++ b/hypervisor/arch/x86/guest/vm_reset.c @@ -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; } /** diff --git a/hypervisor/include/public/acrn_common.h b/hypervisor/include/public/acrn_common.h index 1527aade0..c988a9b69 100644 --- a/hypervisor/include/public/acrn_common.h +++ b/hypervisor/include/public/acrn_common.h @@ -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