diff --git a/doc/acrn.doxyfile b/doc/acrn.doxyfile index 1e83b6da6..8b5dda58d 100644 --- a/doc/acrn.doxyfile +++ b/doc/acrn.doxyfile @@ -802,7 +802,8 @@ INPUT = custom-doxygen/mainpage.md \ ../hypervisor/include/arch/x86/guest/vlapic.h \ ../hypervisor/include/arch/x86/guest/vioapic.h \ ../hypervisor/include/arch/x86/guest/vpic.h \ - ../hypervisor/include/arch/x86/ioreq.h \ + ../hypervisor/include/arch/x86/io_req.h \ + ../hypervisor/include/arch/x86/io_emul.h \ ../hypervisor/include/arch/x86/assign.h \ ../hypervisor/include/common/hypercall.h \ ../hypervisor/include/public/acrn_common.h \ diff --git a/hypervisor/Makefile b/hypervisor/Makefile index cedc17b21..b239f7b53 100644 --- a/hypervisor/Makefile +++ b/hypervisor/Makefile @@ -157,7 +157,7 @@ C_SRCS += arch/x86/irq.c C_SRCS += arch/x86/timer.c C_SRCS += arch/x86/ept.c S_SRCS += arch/x86/vmx_asm.S -C_SRCS += arch/x86/io.c +C_SRCS += arch/x86/io_emul.c C_SRCS += arch/x86/virq.c C_SRCS += arch/x86/vmexit.c C_SRCS += arch/x86/vmx.c @@ -196,7 +196,7 @@ C_SRCS += common/hypercall.c C_SRCS += common/trusty_hypercall.c C_SRCS += common/schedule.c C_SRCS += common/vm_load.c -C_SRCS += common/io_request.c +C_SRCS += common/io_req.c C_SRCS += common/ptdev.c C_SRCS += common/static_checks.c diff --git a/hypervisor/arch/x86/io.c b/hypervisor/arch/x86/io_emul.c similarity index 99% rename from hypervisor/arch/x86/io.c rename to hypervisor/arch/x86/io_emul.c index 13f341880..165acb430 100644 --- a/hypervisor/arch/x86/io.c +++ b/hypervisor/arch/x86/io_emul.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 Intel Corporation. All rights reserved. + * Copyright (C) 2019 Intel Corporation. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ diff --git a/hypervisor/common/io_request.c b/hypervisor/common/io_req.c similarity index 99% rename from hypervisor/common/io_request.c rename to hypervisor/common/io_req.c index 39fb6aef0..e4e10ae04 100644 --- a/hypervisor/common/io_request.c +++ b/hypervisor/common/io_req.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 Intel Corporation. + * Copyright (C) 2019 Intel Corporation. * SPDX-License-Identifier: BSD-3-Clause */ diff --git a/hypervisor/include/arch/x86/hv_arch.h b/hypervisor/include/arch/x86/hv_arch.h index 1d7718c46..23d8ae4b4 100644 --- a/hypervisor/include/arch/x86/hv_arch.h +++ b/hypervisor/include/arch/x86/hv_arch.h @@ -14,7 +14,8 @@ #include #include #include -#include +#include +#include #include #include #include diff --git a/hypervisor/include/arch/x86/io.h b/hypervisor/include/arch/x86/io.h index e6cf3ae35..1162cd69a 100644 --- a/hypervisor/include/arch/x86/io.h +++ b/hypervisor/include/arch/x86/io.h @@ -9,20 +9,6 @@ #include -/* 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 EMUL_PIO_IDX_MAX (RTC_PIO_IDX + 1U) - /* Write 1 byte to specified I/O port */ static inline void pio_write8(uint8_t value, uint16_t port) { diff --git a/hypervisor/include/arch/x86/io_emul.h b/hypervisor/include/arch/x86/io_emul.h new file mode 100644 index 000000000..5934a55e3 --- /dev/null +++ b/hypervisor/include/arch/x86/io_emul.h @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_EMUL_H +#define IO_EMUL_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 EMUL_PIO_IDX_MAX (RTC_PIO_IDX + 1U) + +/** + * @brief General post-work for MMIO emulation + * + * @param vcpu The virtual CPU that triggers the MMIO access + * @param io_req The I/O request holding the details of the MMIO access + * + * @pre io_req->type == REQ_MMIO + * + * @remark This function must be called when \p io_req is completed, after + * either a previous call to emulate_io() returning 0 or the corresponding VHM + * request transferring to the COMPLETE state. + */ +void emulate_mmio_post(const struct acrn_vcpu *vcpu, const struct io_request *io_req); + +/** + * @brief Post-work of VHM requests for MMIO emulation + * + * @param vcpu The virtual CPU that triggers the MMIO access + * + * @pre vcpu->req.type == REQ_MMIO + * + * @remark This function must be called after the VHM request corresponding to + * \p vcpu being transferred to the COMPLETE state. + */ +void dm_emulate_mmio_post(struct acrn_vcpu *vcpu); + +/** + * @brief General post-work for all kinds of VHM requests for I/O emulation + * + * @param vcpu The virtual CPU that triggers the MMIO access + */ +void emulate_io_post(struct acrn_vcpu *vcpu); + +/** + * @brief Emulate \p io_req for \p vcpu + * + * Handle an I/O request by either invoking a hypervisor-internal handler or + * deliver to VHM. + * + * @param vcpu The virtual CPU that triggers the MMIO access + * @param io_req The I/O request holding the details of the MMIO access + * + * @retval 0 Successfully emulated by registered handlers. + * @retval IOREQ_PENDING The I/O request is delivered to VHM. + * @retval -EIO The request spans multiple devices and cannot be emulated. + * @retval -EINVAL \p io_req has an invalid type. + * @retval <0 on other errors during emulation. + */ +int32_t emulate_io(struct acrn_vcpu *vcpu, struct io_request *io_req); + +/** + * @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 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 Initialize the I/O bitmap for \p vm + * + * @param vm The VM whose I/O bitmap is to be initialized + */ +void setup_io_bitmap(struct acrn_vm *vm); + +/** + * @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 */ diff --git a/hypervisor/include/arch/x86/ioreq.h b/hypervisor/include/arch/x86/io_req.h similarity index 57% rename from hypervisor/include/arch/x86/ioreq.h rename to hypervisor/include/arch/x86/io_req.h index 66cbf9384..3d486fb78 100644 --- a/hypervisor/include/arch/x86/ioreq.h +++ b/hypervisor/include/arch/x86/io_req.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 Intel Corporation. All rights reserved. + * Copyright (C) 2019 Intel Corporation. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -169,114 +169,6 @@ struct mem_io_node { /* External Interfaces */ -/** - * @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 Initialize the I/O bitmap for \p vm - * - * @param vm The VM whose I/O bitmaps are to be initialized - */ -void setup_io_bitmap(struct acrn_vm *vm); - -/** - * @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); - -/** - * @brief General post-work for MMIO emulation - * - * @param vcpu The virtual CPU that triggers the MMIO access - * @param io_req The I/O request holding the details of the MMIO access - * - * @pre io_req->type == REQ_MMIO - * - * @remark This function must be called when \p io_req is completed, after - * either a previous call to emulate_io() returning 0 or the corresponding VHM - * request transferring to the COMPLETE state. - */ -void emulate_mmio_post(const struct acrn_vcpu *vcpu, const struct io_request *io_req); - -/** - * @brief Post-work of VHM requests for MMIO emulation - * - * @param vcpu The virtual CPU that triggers the MMIO access - * - * @pre vcpu->req.type == REQ_MMIO - * - * @remark This function must be called after the VHM request corresponding to - * \p vcpu being transferred to the COMPLETE state. - */ -void dm_emulate_mmio_post(struct acrn_vcpu *vcpu); - -/** - * @brief Emulate \p io_req for \p vcpu - * - * Handle an I/O request by either invoking a hypervisor-internal handler or - * deliver to VHM. - * - * @param vcpu The virtual CPU that triggers the MMIO access - * @param io_req The I/O request holding the details of the MMIO access - * - * @retval 0 Successfully emulated by registered handlers. - * @retval IOREQ_PENDING The I/O request is delivered to VHM. - * @retval -EIO The request spans multiple devices and cannot be emulated. - * @retval -EINVAL \p io_req has an invalid type. - * @retval <0 on other errors during emulation. - */ -int32_t emulate_io(struct acrn_vcpu *vcpu, struct io_request *io_req); - -/** - * @brief General post-work for all kinds of VHM requests for I/O emulation - * - * @param vcpu The virtual CPU that triggers the MMIO access - */ -void emulate_io_post(struct acrn_vcpu *vcpu); - /** * @brief Deliver \p io_req to SOS and suspend \p vcpu till its completion *