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);