diff --git a/hypervisor/arch/x86/guest/pm.c b/hypervisor/arch/x86/guest/pm.c index b732cef2a..64afcd971 100644 --- a/hypervisor/arch/x86/guest/pm.c +++ b/hypervisor/arch/x86/guest/pm.c @@ -213,3 +213,28 @@ void register_pm1ab_handler(struct acrn_vm *vm) register_gas_io_handler(vm, PM1A_CNT_PIO_IDX, &(sx_data->pm1a_cnt)); register_gas_io_handler(vm, PM1B_CNT_PIO_IDX, &(sx_data->pm1b_cnt)); } + +static bool rt_vm_pm1a_io_read(__unused struct acrn_vm *vm, __unused struct acrn_vcpu *vcpu, + __unused uint16_t addr, __unused size_t width) +{ + return false; +} + +static bool rt_vm_pm1a_io_write(__unused struct acrn_vm *vm, __unused uint16_t addr, + __unused size_t width, __unused uint32_t v) +{ + /* TODO: Check if the vm is trying to powering off itself */ + return false; +} + +void register_rt_vm_pm1a_ctl_handler(struct acrn_vm *vm) +{ + struct vm_io_range io_range; + + io_range.flags = IO_ATTR_RW; + io_range.base = RT_VM_PM1A_CNT_ADDR; + io_range.len = 1U; + + register_pio_emulation_handler(vm, RT_VM_PM1A_CNT_PIO_IDX, &io_range, + &rt_vm_pm1a_io_read, &rt_vm_pm1a_io_write); +} diff --git a/hypervisor/arch/x86/guest/vm.c b/hypervisor/arch/x86/guest/vm.c index f63c8e065..5d3502e24 100644 --- a/hypervisor/arch/x86/guest/vm.c +++ b/hypervisor/arch/x86/guest/vm.c @@ -421,6 +421,11 @@ int32_t create_vm(uint16_t vm_id, struct acrn_vm_config *vm_config, struct acrn_ /* Init full emulated vIOAPIC instance */ vioapic_init(vm); + /* Intercept the virtual pm port for RTVM */ + if (is_rt_vm(vm)) { + register_rt_vm_pm1a_ctl_handler(vm); + } + /* Populate return VM handle */ *rtn_vm = vm; vm->sw.io_shared_page = NULL; diff --git a/hypervisor/include/arch/x86/guest/guest_pm.h b/hypervisor/include/arch/x86/guest/guest_pm.h index 0730620d1..d18f8c4e3 100644 --- a/hypervisor/include/arch/x86/guest/guest_pm.h +++ b/hypervisor/include/arch/x86/guest/guest_pm.h @@ -11,5 +11,6 @@ void vm_setup_cpu_state(struct acrn_vm *vm); int32_t vm_load_pm_s_state(struct acrn_vm *vm); int32_t validate_pstate(const struct acrn_vm *vm, uint64_t perf_ctl); void register_pm1ab_handler(struct acrn_vm *vm); +void register_rt_vm_pm1a_ctl_handler(struct acrn_vm *vm); #endif /* PM_H */ diff --git a/hypervisor/include/arch/x86/guest/io_emul.h b/hypervisor/include/arch/x86/guest/io_emul.h index 7d3d28b1f..4d973681e 100644 --- a/hypervisor/include/arch/x86/guest/io_emul.h +++ b/hypervisor/include/arch/x86/guest/io_emul.h @@ -21,7 +21,8 @@ #define PM1B_EVT_PIO_IDX (PM1A_CNT_PIO_IDX + 1U) #define PM1B_CNT_PIO_IDX (PM1B_EVT_PIO_IDX + 1U) #define RTC_PIO_IDX (PM1B_CNT_PIO_IDX + 1U) -#define EMUL_PIO_IDX_MAX (RTC_PIO_IDX + 1U) +#define RT_VM_PM1A_CNT_PIO_IDX (RTC_PIO_IDX + 1U) +#define EMUL_PIO_IDX_MAX (RT_VM_PM1A_CNT_PIO_IDX + 1U) /** * @brief The handler of VM exits on I/O instructions diff --git a/hypervisor/include/public/acrn_common.h b/hypervisor/include/public/acrn_common.h index d1caf062b..90221706a 100644 --- a/hypervisor/include/public/acrn_common.h +++ b/hypervisor/include/public/acrn_common.h @@ -54,6 +54,9 @@ #define GUEST_FLAG_HIDE_MTRR (1UL << 4U) /* Whether hide MTRR from VM */ #define GUEST_FLAG_RT (1UL << 5U) /* Whether the vm is RT-VM */ +/* TODO: We may need to get this addr from guest ACPI instead of hardcode here */ +#define RT_VM_PM1A_CNT_ADDR 0x404U + /** * @brief Hypercall *