From 8ad0fd98a30163b5ee94cc1d1bb5e4c44df33e92 Mon Sep 17 00:00:00 2001 From: Zide Chen Date: Wed, 27 Feb 2019 09:54:58 -0800 Subject: [PATCH] hv: implement NEED_SHUTDOWN_VM request to idle thread For pre-launched VMs and SOS, VM shutdown should not be executed in the current VM context. - implement NEED_SHUTDOWN_VM request so that the BSP of the target VM can shut down the guest in idle thread. - implement shutdown_vm_from_idle() to shut down target VM. Tracked-On: #2700 Signed-off-by: Zide Chen Signed-off-by: Sainath Grandhi Acked-by: Eddie Dong --- hypervisor/Makefile | 1 + hypervisor/arch/x86/guest/vm_reset.c | 19 +++++++++++++++++++ hypervisor/common/hv_main.c | 3 +++ hypervisor/common/schedule.c | 17 +++++++++++++++++ hypervisor/include/arch/x86/guest/vm_reset.h | 12 ++++++++++++ hypervisor/include/arch/x86/per_cpu.h | 2 ++ hypervisor/include/common/schedule.h | 3 +++ 7 files changed, 57 insertions(+) create mode 100644 hypervisor/arch/x86/guest/vm_reset.c create mode 100644 hypervisor/include/arch/x86/guest/vm_reset.h diff --git a/hypervisor/Makefile b/hypervisor/Makefile index c83213b57..511d45568 100644 --- a/hypervisor/Makefile +++ b/hypervisor/Makefile @@ -213,6 +213,7 @@ C_SRCS += arch/x86/guest/vmcs.c C_SRCS += arch/x86/guest/vmexit.c S_SRCS += arch/x86/guest/vmx_asm.S C_SRCS += arch/x86/guest/trusty.c +C_SRCS += arch/x86/guest/vm_reset.c C_SRCS += arch/x86/cat.c C_SRCS += arch/x86/lib/memory.c C_SRCS += lib/string.c diff --git a/hypervisor/arch/x86/guest/vm_reset.c b/hypervisor/arch/x86/guest/vm_reset.c new file mode 100644 index 000000000..b004ef978 --- /dev/null +++ b/hypervisor/arch/x86/guest/vm_reset.c @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +void shutdown_vm_from_idle(uint16_t pcpu_id) +{ + struct acrn_vm *vm = get_vm_from_vmid(per_cpu(shutdown_vm_id, pcpu_id)); + const struct acrn_vcpu *vcpu = vcpu_from_vid(vm, BOOT_CPU_ID); + + if (vcpu->pcpu_id == pcpu_id) { + (void)shutdown_vm(vm); + } +} diff --git a/hypervisor/common/hv_main.c b/hypervisor/common/hv_main.c index 1c9163d26..7c1f48625 100644 --- a/hypervisor/common/hv_main.c +++ b/hypervisor/common/hv_main.c @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -88,6 +89,8 @@ void default_idle(__unused struct sched_object *obj) schedule(); } else if (need_offline(pcpu_id) != 0) { cpu_dead(); + } else if (need_shutdown_vm(pcpu_id)) { + shutdown_vm_from_idle(pcpu_id); } else { CPU_IRQ_ENABLE(); cpu_do_idle(); diff --git a/hypervisor/common/schedule.c b/hypervisor/common/schedule.c index 54a2e987f..3c7237512 100644 --- a/hypervisor/common/schedule.c +++ b/hypervisor/common/schedule.c @@ -152,6 +152,23 @@ int32_t need_offline(uint16_t pcpu_id) return bitmap_test_and_clear_lock(NEED_OFFLINE, &ctx->flags); } +void make_shutdown_vm_request(uint16_t pcpu_id) +{ + struct sched_context *ctx = &per_cpu(sched_ctx, pcpu_id); + + bitmap_set_lock(NEED_SHUTDOWN_VM, &ctx->flags); + if (get_pcpu_id() != pcpu_id) { + send_single_ipi(pcpu_id, VECTOR_NOTIFY_VCPU); + } +} + +bool need_shutdown_vm(uint16_t pcpu_id) +{ + struct sched_context *ctx = &per_cpu(sched_ctx, pcpu_id); + + return bitmap_test_and_clear_lock(NEED_SHUTDOWN_VM, &ctx->flags); +} + static void prepare_switch(struct sched_object *prev, struct sched_object *next) { if ((prev != NULL) && (prev->prepare_switch_out != NULL)) { diff --git a/hypervisor/include/arch/x86/guest/vm_reset.h b/hypervisor/include/arch/x86/guest/vm_reset.h new file mode 100644 index 000000000..d83ba307e --- /dev/null +++ b/hypervisor/include/arch/x86/guest/vm_reset.h @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef VM_RESET_H_ +#define VM_RESET_H_ + +void shutdown_vm_from_idle(uint16_t pcpu_id); + +#endif /* VM_RESET_H_ */ diff --git a/hypervisor/include/arch/x86/per_cpu.h b/hypervisor/include/arch/x86/per_cpu.h index 3d302ebf2..3e324751c 100644 --- a/hypervisor/include/arch/x86/per_cpu.h +++ b/hypervisor/include/arch/x86/per_cpu.h @@ -18,6 +18,7 @@ #include #include #include +#include struct per_cpu_region { /* vmxon_region MUST be 4KB-aligned */ @@ -52,6 +53,7 @@ struct per_cpu_region { #ifdef PROFILING_ON struct profiling_info_wrapper profiling_info; #endif + uint16_t shutdown_vm_id; } __aligned(PAGE_SIZE); /* per_cpu_region size aligned with PAGE_SIZE */ extern struct per_cpu_region per_cpu_data[CONFIG_MAX_PCPU_NUM]; diff --git a/hypervisor/include/common/schedule.h b/hypervisor/include/common/schedule.h index bbf32b1b9..3cd45a915 100644 --- a/hypervisor/include/common/schedule.h +++ b/hypervisor/include/common/schedule.h @@ -10,6 +10,7 @@ #define NEED_RESCHEDULE (1U) #define NEED_OFFLINE (2U) +#define NEED_SHUTDOWN_VM (3U) #define DEL_MODE_INIT (1U) #define DEL_MODE_IPI (2U) @@ -50,6 +51,8 @@ void make_reschedule_request(uint16_t pcpu_id, uint16_t delmode); bool need_reschedule(uint16_t pcpu_id); void make_pcpu_offline(uint16_t pcpu_id); int32_t need_offline(uint16_t pcpu_id); +void make_shutdown_vm_request(uint16_t pcpu_id); +bool need_shutdown_vm(uint16_t pcpu_id); void schedule(void); void run_sched_thread(struct sched_object *obj);