mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2026-06-07 01:30:13 +00:00
The virtual pm port of RTVM is intercepted by HV. But the HV needs to inform the DM as well.
So we will forward the virtual S5 request to DM too
The handler in HV just set the pm state flag (VM_POWERING_OFF) which indicate that the RTVM is powering
off by itself. Meanwhile, there are data resources in VHM and DM should be released once we handle the PM
of RTVM in HV. So, return to DM to go through the entire VM destroy cycles to release the resources.
During the cycles, the DM will try to pause vm through hypercall. In the hypercall handler in HV, we will
check the pm state flag. If it is set, pause all the vCPUs of the vm. Otherwise, reject the request.
In this way, we can make sure that RTVM can only trigger its s5 by itself. All
other S5 request from external will be rejected.
Here is sequence chart of RTVM s5.
poweroff
+-----------+ +----------+ +-----------+ +----------+
| vBSP | | vAPs | | HV | | DM |
+-----+-----+ +----------+ +-----+-----+ +-----+----+
| | | |
| Stop all other cpus | | |
+----------------------------+ | |
| | |Disable LAPIC | |
| +<-+ | |
| | | |
| +--+ | |
| | |HLT in | |
| All other cpus stopped | |non-root mode | |
+----------------------------+ | |
| Call ACPI method to enter s5 | |
+-------------------------+---------------------> | |
| | Set s5 flag | |
| | <---------------------+ |
| | APs paused | Re-inject IOREQ TO DM
| | +-------------------> +-------------------> +
| | | Pause VM |
| | Check S5 flag: | <-------------------+
| | - If set, pause vm | VM paused |
| | - If no, reject | +-----------------> +--+
| | | Destroy VM | |Deinit works
| | | <--------------------<-+
| | | VM destroyed |
| | | +-----------------> |
+ + + +
Tracked-On: #2865
Signed-off-by: Kaige Fu <kaige.fu@intel.com>
88 lines
3.1 KiB
C
88 lines
3.1 KiB
C
/*
|
|
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#ifndef IO_EMUL_H
|
|
#define IO_EMUL_H
|
|
|
|
#include <types.h>
|
|
|
|
/* Define emulated port IO index */
|
|
#define PIC_MASTER_PIO_IDX 0U
|
|
#define PIC_SLAVE_PIO_IDX (PIC_MASTER_PIO_IDX + 1U)
|
|
#define PIC_ELC_PIO_IDX (PIC_SLAVE_PIO_IDX + 1U)
|
|
#define PCI_CFGADDR_PIO_IDX (PIC_ELC_PIO_IDX + 1U)
|
|
#define PCI_CFGDATA_PIO_IDX (PCI_CFGADDR_PIO_IDX + 1U)
|
|
#define UART_PIO_IDX (PCI_CFGDATA_PIO_IDX + 1U)
|
|
#define PM1A_EVT_PIO_IDX (UART_PIO_IDX + 1U)
|
|
#define PM1A_CNT_PIO_IDX (PM1A_EVT_PIO_IDX + 1U)
|
|
#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 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
|
|
*
|
|
* @param vcpu The virtual CPU which triggers the VM exit on I/O instruction
|
|
*/
|
|
int32_t pio_instr_vmexit_handler(struct acrn_vcpu *vcpu);
|
|
|
|
/**
|
|
* @brief EPT violation handling
|
|
*
|
|
* @param[in] vcpu the pointer that points to vcpu data structure
|
|
*
|
|
* @retval -EINVAL fail to handle the EPT violation
|
|
* @retval 0 Success to handle the EPT violation
|
|
*/
|
|
int32_t ept_violation_vmexit_handler(struct acrn_vcpu *vcpu);
|
|
|
|
/**
|
|
* @brief Allow a VM to access a port I/O range
|
|
*
|
|
* This API enables direct access from the given \p vm to the port I/O space
|
|
* starting from \p port_address to \p port_address + \p nbytes - 1.
|
|
*
|
|
* @param vm The VM whose port I/O access permissions is to be changed
|
|
* @param port_address The start address of the port I/O range
|
|
* @param nbytes The size of the range, in bytes
|
|
*/
|
|
void allow_guest_pio_access(struct acrn_vm *vm, uint16_t port_address, uint32_t nbytes);
|
|
|
|
/**
|
|
* @brief Register a port I/O handler
|
|
*
|
|
* @param vm The VM to which the port I/O handlers are registered
|
|
* @param pio_idx The emulated port io index
|
|
* @param range The emulated port io range
|
|
* @param io_read_fn_ptr The handler for emulating reads from the given range
|
|
* @param io_write_fn_ptr The handler for emulating writes to the given range
|
|
* @pre pio_idx < EMUL_PIO_IDX_MAX
|
|
*/
|
|
void register_pio_emulation_handler(struct acrn_vm *vm, uint32_t pio_idx,
|
|
const struct vm_io_range *range, io_read_fn_t io_read_fn_ptr, io_write_fn_t io_write_fn_ptr);
|
|
|
|
/**
|
|
* @brief Register a MMIO handler
|
|
*
|
|
* This API registers a MMIO handler to \p vm before it is launched.
|
|
*
|
|
* @param vm The VM to which the MMIO handler is registered
|
|
* @param read_write The handler for emulating accesses to the given range
|
|
* @param start The base address of the range \p read_write can emulate
|
|
* @param end The end of the range (exclusive) \p read_write can emulate
|
|
* @param handler_private_data Handler-specific data which will be passed to \p read_write when called
|
|
*
|
|
* @retval 0 Registration succeeds
|
|
* @retval -EINVAL \p read_write is NULL, \p end is not larger than \p start or \p vm has been launched
|
|
*/
|
|
int32_t register_mmio_emulation_handler(struct acrn_vm *vm,
|
|
hv_mem_io_handler_t read_write, uint64_t start,
|
|
uint64_t end, void *handler_private_data);
|
|
|
|
#endif /* IO_EMUL_H */
|