mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-07-31 07:20:55 +00:00
hv: emulate reset register 0xcf9 and 0x64
- post-launched RTVM: intercept both PIO ports so that hypervisor has a chance to set VM_POWERING_OFF flag. - all other type of VMs: deny these 2 ports from guest access so that guests are not able to reset host. Tracked-On: #2700 Signed-off-by: Zide Chen <zide.chen@intel.com> Signed-off-by: Sainath Grandhi <sainath.grandhi@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
8ad0fd98a3
commit
9aa3fe646b
@ -8,6 +8,7 @@
|
||||
#include <errno.h>
|
||||
#include <sprintf.h>
|
||||
#include <vm.h>
|
||||
#include <vm_reset.h>
|
||||
#include <bits.h>
|
||||
#include <e820.h>
|
||||
#include <multiboot.h>
|
||||
@ -423,6 +424,8 @@ int32_t create_vm(uint16_t vm_id, struct acrn_vm_config *vm_config, struct acrn_
|
||||
|
||||
vpci_init(vm);
|
||||
|
||||
register_reset_port_handler(vm);
|
||||
|
||||
/* vpic wire_mode default is INTR */
|
||||
vm->wire_mode = VPIC_WIRE_INTR;
|
||||
|
||||
|
@ -5,8 +5,102 @@
|
||||
*/
|
||||
|
||||
#include <vm.h>
|
||||
#include <vm_reset.h>
|
||||
#include <io.h>
|
||||
#include <logmsg.h>
|
||||
#include <per_cpu.h>
|
||||
#include <vm_reset.h>
|
||||
|
||||
/**
|
||||
* @pre vcpu != NULL && vm != NULL
|
||||
*/
|
||||
static bool handle_reset_reg_read(struct acrn_vm *vm, struct acrn_vcpu *vcpu, __unused uint16_t addr,
|
||||
__unused size_t bytes)
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
if (is_postlaunched_vm(vm)) {
|
||||
/* re-inject to DM */
|
||||
ret = false;
|
||||
} else {
|
||||
/*
|
||||
* - keyboard control/status register 0x64: ACRN doesn't expose kbd controller to the guest.
|
||||
* - reset control register 0xcf9: hide this from guests for now.
|
||||
*/
|
||||
vcpu->req.reqs.pio.value = ~0U;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @pre vm != NULL
|
||||
*/
|
||||
static bool handle_common_reset_reg_write(struct acrn_vm *vm, bool reset)
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
if (is_postlaunched_vm(vm)) {
|
||||
/* re-inject to DM */
|
||||
ret = false;
|
||||
|
||||
if (reset && is_rt_vm(vm)) {
|
||||
vm->state = VM_POWERING_OFF;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* ignore writes from SOS or pre-launched VMs.
|
||||
* equivalent to hide this port from guests.
|
||||
*/
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @pre vm != NULL
|
||||
*/
|
||||
static bool handle_kb_write(struct acrn_vm *vm, __unused uint16_t addr, size_t bytes, uint32_t val)
|
||||
{
|
||||
/* ignore commands other than system reset */
|
||||
return handle_common_reset_reg_write(vm, ((bytes == 1U) && (val == 0xfeU)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset Control register at I/O port 0xcf9.
|
||||
* Bit 1 - 0: "soft" reset. Force processor begin execution at power-on reset vector.
|
||||
* 1: "hard" reset. e.g. assert PLTRST# (if implemented) to do a host reset.
|
||||
* Bit 2 - initiates a system reset when it transitions from 0 to 1.
|
||||
* Bit 3 - 1: full reset (aka code reset), SLP_S3#/4#/5# or similar pins are asserted for full power cycle.
|
||||
* 0: will be dropped if system in S3/S4/S5.
|
||||
*/
|
||||
/**
|
||||
* @pre vm != NULL
|
||||
*/
|
||||
static bool handle_cf9_write(struct acrn_vm *vm, __unused uint16_t addr, size_t bytes, uint32_t val)
|
||||
{
|
||||
/* We don't differentiate among hard/soft/warm/cold reset */
|
||||
return handle_common_reset_reg_write(vm, ((bytes == 1U) && ((val & 0x4U) == 0x4U) && ((val & 0xaU) != 0U)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @pre vm != NULL
|
||||
*/
|
||||
void register_reset_port_handler(struct acrn_vm *vm)
|
||||
{
|
||||
/* Don't support SOS and pre-launched VM re-launch for now. */
|
||||
if (!is_postlaunched_vm(vm) || is_rt_vm(vm)) {
|
||||
struct vm_io_range io_range = {
|
||||
.flags = IO_ATTR_RW,
|
||||
.len = 1U
|
||||
};
|
||||
|
||||
io_range.base = 0x64U;
|
||||
register_pio_emulation_handler(vm, KB_PIO_IDX, &io_range, handle_reset_reg_read, handle_kb_write);
|
||||
|
||||
io_range.base = 0xcf9U;
|
||||
register_pio_emulation_handler(vm, CF9_PIO_IDX, &io_range, handle_reset_reg_read, handle_cf9_write);
|
||||
}
|
||||
}
|
||||
|
||||
void shutdown_vm_from_idle(uint16_t pcpu_id)
|
||||
{
|
||||
|
@ -7,6 +7,7 @@
|
||||
#ifndef VM_RESET_H_
|
||||
#define VM_RESET_H_
|
||||
|
||||
void register_reset_port_handler(struct acrn_vm *vm);
|
||||
void shutdown_vm_from_idle(uint16_t pcpu_id);
|
||||
|
||||
#endif /* VM_RESET_H_ */
|
||||
|
@ -24,7 +24,9 @@
|
||||
#define PM1B_CNT_PIO_IDX (PM1B_EVT_PIO_IDX + 1U)
|
||||
#define RTC_PIO_IDX (PM1B_CNT_PIO_IDX + 1U)
|
||||
#define VIRTUAL_PM1A_CNT_PIO_IDX (RTC_PIO_IDX + 1U)
|
||||
#define EMUL_PIO_IDX_MAX (VIRTUAL_PM1A_CNT_PIO_IDX + 1U)
|
||||
#define KB_PIO_IDX (VIRTUAL_PM1A_CNT_PIO_IDX + 1U)
|
||||
#define CF9_PIO_IDX (KB_PIO_IDX + 1U)
|
||||
#define EMUL_PIO_IDX_MAX (CF9_PIO_IDX + 1U)
|
||||
|
||||
/**
|
||||
* @brief The handler of VM exits on I/O instructions
|
||||
|
Loading…
Reference in New Issue
Block a user