diff --git a/hypervisor/Makefile b/hypervisor/Makefile index 8614c307a..c59594fa3 100644 --- a/hypervisor/Makefile +++ b/hypervisor/Makefile @@ -219,6 +219,7 @@ HW_C_SRCS += arch/x86/exception.c HW_C_SRCS += arch/x86/irq.c HW_C_SRCS += arch/x86/tsc.c HW_C_SRCS += arch/x86/tsc_deadline_timer.c +HW_C_SRCS += arch/x86/hw_thermal.c HW_C_SRCS += arch/x86/vmx.c HW_C_SRCS += arch/x86/cpu_state_tbl.c HW_C_SRCS += arch/x86/pm.c @@ -230,6 +231,7 @@ HW_C_SRCS += arch/x86/sgx.c HW_C_SRCS += common/ticks.c HW_C_SRCS += common/delay.c HW_C_SRCS += common/timer.c +HW_C_SRCS += common/thermal.c HW_C_SRCS += common/irq.c HW_C_SRCS += common/softirq.c HW_C_SRCS += common/schedule.c diff --git a/hypervisor/arch/x86/cpu.c b/hypervisor/arch/x86/cpu.c index 9b68a8d98..a8ecd0d4d 100644 --- a/hypervisor/arch/x86/cpu.c +++ b/hypervisor/arch/x86/cpu.c @@ -37,6 +37,7 @@ #include #include #include +#include #define CPU_UP_TIMEOUT 100U /* millisecond */ #define CPU_DOWN_TIMEOUT 100U /* millisecond */ @@ -268,6 +269,7 @@ void init_pcpu_post(uint16_t pcpu_id) init_interrupt(BSP_CPU_ID); timer_init(); + thermal_init(); setup_notification(); setup_pi_notification(); @@ -309,6 +311,7 @@ void init_pcpu_post(uint16_t pcpu_id) init_interrupt(pcpu_id); timer_init(); + thermal_init(); ptdev_init(); } diff --git a/hypervisor/arch/x86/guest/vcpu.c b/hypervisor/arch/x86/guest/vcpu.c index bc48c4d95..8dcc833b5 100755 --- a/hypervisor/arch/x86/guest/vcpu.c +++ b/hypervisor/arch/x86/guest/vcpu.c @@ -572,6 +572,16 @@ int32_t create_vcpu(uint16_t pcpu_id, struct acrn_vm *vm, struct acrn_vcpu **rtn */ vcpu->arch.vpid = ALLOCATED_MIN_L1_VPID + (vm->vm_id * MAX_VCPUS_PER_VM) + vcpu->vcpu_id; + /* + * There are two locally independent writing operations, namely the + * assignment of vcpu->vm and vcpu_array[]. Compilers may optimize + * and reorder writing operations while users of vcpu_array[] may + * assume the presence of vcpu->vm. A compiler barrier is added here + * to prevent compiler reordering, ensuring that assignments to + * vcpu->vm precede vcpu_array[]. + */ + cpu_compiler_barrier(); + /* * ACRN uses the following approach to manage VT-d PI notification vectors: * Allocate unique Activation Notification Vectors (ANV) for each vCPU that diff --git a/hypervisor/arch/x86/guest/virq.c b/hypervisor/arch/x86/guest/virq.c index 8b8f5dd9f..b36ce6316 100644 --- a/hypervisor/arch/x86/guest/virq.c +++ b/hypervisor/arch/x86/guest/virq.c @@ -302,6 +302,14 @@ void vcpu_inject_ss(struct acrn_vcpu *vcpu) (void)vcpu_queue_exception(vcpu, IDT_SS, 0); } +/* Inject thermal sensor interrupt to guest */ +void vcpu_inject_thermal_interrupt(struct acrn_vcpu *vcpu) +{ + if (is_vtm_configured(vcpu->vm)) { + (void)vlapic_set_local_intr(vcpu->vm, vcpu->vcpu_id, APIC_LVT_THERMAL); + }; +} + int32_t interrupt_window_vmexit_handler(struct acrn_vcpu *vcpu) { TRACE_2L(TRACE_VMEXIT_INTERRUPT_WINDOW, 0UL, 0UL); diff --git a/hypervisor/arch/x86/hw_thermal.c b/hypervisor/arch/x86/hw_thermal.c new file mode 100644 index 000000000..a48f12b68 --- /dev/null +++ b/hypervisor/arch/x86/hw_thermal.c @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2023 Intel Corporation. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* run in interrupt context */ +static void thermal_irq_handler(__unused uint32_t irq, __unused void *data) +{ + fire_softirq(SOFTIRQ_THERMAL); +} + +void init_hw_thermal(void) +{ + int32_t retval = 0; + + if (get_pcpu_id() == BSP_CPU_ID) { + retval = request_irq(THERMAL_IRQ, thermal_irq_handler, NULL, IRQF_NONE); + if (retval < 0) { + pr_err("Thermal irq setup failed\n"); + } + } + + if (retval >= 0) { + uint32_t val = THERMAL_VECTOR; + + msr_write(MSR_IA32_EXT_APIC_LVT_THERMAL, val); + } +} diff --git a/hypervisor/arch/x86/irq.c b/hypervisor/arch/x86/irq.c index b2fee20d8..8f064bd9c 100644 --- a/hypervisor/arch/x86/irq.c +++ b/hypervisor/arch/x86/irq.c @@ -32,6 +32,7 @@ static struct { uint32_t vector; } irq_static_mappings[NR_STATIC_MAPPINGS] = { {TIMER_IRQ, TIMER_VECTOR}, + {THERMAL_IRQ, THERMAL_VECTOR}, {NOTIFY_VCPU_IRQ, NOTIFY_VCPU_VECTOR}, {PMI_IRQ, PMI_VECTOR}, diff --git a/hypervisor/common/thermal.c b/hypervisor/common/thermal.c new file mode 100644 index 000000000..ef9502333 --- /dev/null +++ b/hypervisor/common/thermal.c @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2023 Intel Corporation. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +static void thermal_softirq(uint16_t pcpu_id) +{ + struct acrn_vcpu *vcpu; + uint32_t idx; + + for (idx = 0; idx < CONFIG_MAX_VM_NUM; idx++) { + vcpu = per_cpu(vcpu_array, pcpu_id)[idx]; + if (vcpu != NULL) { + vcpu_inject_thermal_interrupt(vcpu); + } + } +} + +void thermal_init(void) +{ + uint16_t pcpu_id = get_pcpu_id(); + + if (pcpu_id == BSP_CPU_ID) { + register_softirq(SOFTIRQ_THERMAL, thermal_softirq); + } + + init_hw_thermal(); +} diff --git a/hypervisor/include/arch/x86/asm/cpu.h b/hypervisor/include/arch/x86/asm/cpu.h index 7028384a1..2c14f794d 100755 --- a/hypervisor/include/arch/x86/asm/cpu.h +++ b/hypervisor/include/arch/x86/asm/cpu.h @@ -589,6 +589,12 @@ static inline void cpu_memory_barrier(void) asm volatile ("mfence\n" : : : "memory"); } +/* Prevents compilers from reordering read/write access across this barrier */ +static inline void cpu_compiler_barrier(void) +{ + asm volatile ("" : : : "memory"); +} + static inline void invlpg(unsigned long addr) { asm volatile("invlpg (%0)" ::"r" (addr) : "memory"); diff --git a/hypervisor/include/arch/x86/asm/guest/virq.h b/hypervisor/include/arch/x86/asm/guest/virq.h index aee60df4f..8836ae10a 100644 --- a/hypervisor/include/arch/x86/asm/guest/virq.h +++ b/hypervisor/include/arch/x86/asm/guest/virq.h @@ -90,6 +90,17 @@ void vcpu_inject_ud(struct acrn_vcpu *vcpu); * @pre vcpu != NULL */ void vcpu_inject_ss(struct acrn_vcpu *vcpu); + +/** + * @brief Inject thermal sensor interrupt to guest. + * + * @param[in] vcpu Pointer to vCPU. + * + * @return None + * + * @pre vcpu != NULL + */ +void vcpu_inject_thermal_interrupt(struct acrn_vcpu *vcpu); void vcpu_make_request(struct acrn_vcpu *vcpu, uint16_t eventid); /* diff --git a/hypervisor/include/arch/x86/asm/irq.h b/hypervisor/include/arch/x86/asm/irq.h index 2958848fe..51c373b82 100644 --- a/hypervisor/include/arch/x86/asm/irq.h +++ b/hypervisor/include/arch/x86/asm/irq.h @@ -22,7 +22,7 @@ #define VECTOR_INVALID (NR_MAX_VECTOR + 1U) /* # of NR_STATIC_MAPPINGS_1 entries for timer, vcpu notify, and PMI */ -#define NR_STATIC_MAPPINGS_1 3U +#define NR_STATIC_MAPPINGS_1 4U /* * The static IRQ/Vector mapping table in irq.c consists of the following entries: @@ -53,6 +53,7 @@ #define TIMER_VECTOR (VECTOR_FIXED_START) #define NOTIFY_VCPU_VECTOR (VECTOR_FIXED_START + 1U) #define PMI_VECTOR (VECTOR_FIXED_START + 2U) +#define THERMAL_VECTOR (VECTOR_FIXED_START + 3U) /* * Starting vector for posted interrupts * # of CONFIG_MAX_VM_NUM (POSTED_INTR_VECTOR ~ (POSTED_INTR_VECTOR + CONFIG_MAX_VM_NUM - 1U)) @@ -63,6 +64,7 @@ #define TIMER_IRQ (NR_IRQS - 1U) #define NOTIFY_VCPU_IRQ (NR_IRQS - 2U) #define PMI_IRQ (NR_IRQS - 3U) +#define THERMAL_IRQ (NR_IRQS - 4U) /* * Starting IRQ for posted interrupts * # of CONFIG_MAX_VM_NUM (POSTED_INTR_IRQ ~ (POSTED_INTR_IRQ + CONFIG_MAX_VM_NUM - 1U)) diff --git a/hypervisor/include/common/softirq.h b/hypervisor/include/common/softirq.h index cab6de392..27bfe7bf5 100644 --- a/hypervisor/include/common/softirq.h +++ b/hypervisor/include/common/softirq.h @@ -9,7 +9,8 @@ #define SOFTIRQ_TIMER 0U #define SOFTIRQ_PTDEV 1U -#define NR_SOFTIRQS 2U +#define SOFTIRQ_THERMAL 2U +#define NR_SOFTIRQS 3U typedef void (*softirq_handler)(uint16_t cpu_id); diff --git a/hypervisor/include/common/thermal.h b/hypervisor/include/common/thermal.h new file mode 100644 index 000000000..c9789788f --- /dev/null +++ b/hypervisor/include/common/thermal.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2023 Intel Corporation. + *- + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef COMMON_THERMAL_H +#define COMMON_THERMAL_H + +/** + * @brief Initialize thermal. + * + * @return None + */ +void thermal_init(void); + +#endif /* COMMON_THERMAL_H */ diff --git a/hypervisor/include/hw/hw_thermal.h b/hypervisor/include/hw/hw_thermal.h new file mode 100644 index 000000000..34a8b15ed --- /dev/null +++ b/hypervisor/include/hw/hw_thermal.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2023 Intel Corporation. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HW_THERMAL_H +#define HW_THERMAL_H + +#include + +void init_hw_thermal(void); + +#endif /* HW_THERMAL_H */