hv: enable thermal lvt interrupt

This patch can fetch the thermal lvt irq and propagate
it to VM.

At this stage we support the case that there is only one VM
governing thermal. And we pass the hardware thermal irq to this VM.

First, we register the handler for thermal lvt interrupt, its irq
vector is THERMAL_VECTOR and the handler is thermal_irq_handler().

Then, when a thermal irq occurs, it flags the SOFTIRQ_THERMAL bit
of softirq_pending, This bit triggers the thermal_softirq() function.
And this function will inject the virtual thermal irq to VM.

Tracked-On: #8595

Signed-off-by: Zhangwei6 <wei6.zhang@intel.com>
Reviewed-by: Junjie Mao <junjie.mao@intel.com>
This commit is contained in:
Zhangwei6 2023-08-30 08:18:24 +08:00 committed by acrnsi-robot
parent 78243c3f49
commit ddfcb8c3fc
13 changed files with 151 additions and 2 deletions

View File

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

View File

@ -37,6 +37,7 @@
#include <asm/tsc.h>
#include <ticks.h>
#include <delay.h>
#include <thermal.h>
#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();
}

View File

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

View File

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

View File

@ -0,0 +1,39 @@
/*
* Copyright (C) 2023 Intel Corporation.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <types.h>
#include <softirq.h>
#include <irq.h>
#include <logmsg.h>
#include <asm/cpu.h>
#include <asm/msr.h>
#include <asm/irq.h>
#include <asm/apicreg.h>
#include <hw/hw_thermal.h>
/* 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);
}
}

View File

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

View File

@ -0,0 +1,35 @@
/*
* Copyright (C) 2023 Intel Corporation.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <types.h>
#include <softirq.h>
#include <trace.h>
#include <asm/guest/virq.h>
#include <hw/hw_thermal.h>
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();
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,14 @@
/*
* Copyright (C) 2023 Intel Corporation.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef HW_THERMAL_H
#define HW_THERMAL_H
#include <types.h>
void init_hw_thermal(void);
#endif /* HW_THERMAL_H */