diff --git a/hypervisor/arch/x86/guest/io_emul.c b/hypervisor/arch/x86/guest/io_emul.c index 500e230b5..c81d610ba 100644 --- a/hypervisor/arch/x86/guest/io_emul.c +++ b/hypervisor/arch/x86/guest/io_emul.c @@ -196,7 +196,7 @@ static void dm_emulate_io_complete(struct acrn_vcpu *vcpu) * @retval -EIO The request spans multiple devices and cannot be emulated. */ static int32_t -hv_emulate_pio(const struct acrn_vcpu *vcpu, struct io_request *io_req) +hv_emulate_pio(struct acrn_vcpu *vcpu, struct io_request *io_req) { int32_t status = -ENODEV; uint16_t port, size; @@ -215,6 +215,8 @@ hv_emulate_pio(const struct acrn_vcpu *vcpu, struct io_request *io_req) continue; } + status = 0; + if (pio_req->direction == REQUEST_WRITE) { if (handler->io_write != NULL) { if (!(handler->io_write(vm, port, size, pio_req->value))) { @@ -228,11 +230,16 @@ hv_emulate_pio(const struct acrn_vcpu *vcpu, struct io_request *io_req) pr_dbg("IO write on port %04x, data %08x", port, pio_req->value); } else { if (handler->io_read != NULL) { - pio_req->value = handler->io_read(vm, port, size); + if (!(handler->io_read(vm, vcpu, port, size))) { + /* + * If io_read return false, it indicates that we need continue + * to emulate in DM. + */ + status = -ENODEV; + } } pr_dbg("IO read on port %04x, data %08x", port, pio_req->value); } - status = 0; break; } diff --git a/hypervisor/arch/x86/guest/pm.c b/hypervisor/arch/x86/guest/pm.c index 96991459f..b732cef2a 100644 --- a/hypervisor/arch/x86/guest/pm.c +++ b/hypervisor/arch/x86/guest/pm.c @@ -121,9 +121,13 @@ static inline uint8_t get_slp_typx(uint32_t pm1_cnt) return (uint8_t)((pm1_cnt & 0x1fffU) >> BIT_SLP_TYPx); } -static uint32_t pm1ab_io_read(__unused struct acrn_vm *vm, uint16_t addr, size_t width) +static bool pm1ab_io_read(__unused struct acrn_vm *vm, struct acrn_vcpu *vcpu, uint16_t addr, size_t width) { - return pio_read(addr, width); + struct pio_request *pio_req = &vcpu->req.reqs.pio; + + pio_req->value = pio_read(addr, width); + + return true; } static inline void enter_s3(struct acrn_vm *vm, uint32_t pm1a_cnt_val, uint32_t pm1b_cnt_val) diff --git a/hypervisor/debug/vuart.c b/hypervisor/debug/vuart.c index c39307976..64214a220 100644 --- a/hypervisor/debug/vuart.c +++ b/hypervisor/debug/vuart.c @@ -248,12 +248,13 @@ done: return true; } -static uint32_t vuart_read(struct acrn_vm *vm, uint16_t offset_arg, +static bool vuart_read(struct acrn_vm *vm, struct acrn_vcpu *vcpu, uint16_t offset_arg, __unused size_t width) { uint16_t offset = offset_arg; uint8_t iir, reg, intr_reason; struct acrn_vuart *vu = vm_vuart(vm); + struct pio_request *pio_req = &vcpu->req.reqs.pio; offset -= vu->base; vuart_lock(vu); @@ -323,8 +324,10 @@ static uint32_t vuart_read(struct acrn_vm *vm, uint16_t offset_arg, } done: vuart_toggle_intr(vu); + pio_req->value = (uint32_t)reg; vuart_unlock(vu); - return (uint32_t)reg; + + return true; } static void vuart_register_io_handler(struct acrn_vm *vm) diff --git a/hypervisor/dm/vpci/vpci.c b/hypervisor/dm/vpci/vpci.c index bbf81490d..c5d8e2c15 100644 --- a/hypervisor/dm/vpci/vpci.c +++ b/hypervisor/dm/vpci/vpci.c @@ -43,13 +43,14 @@ static void pci_cfg_clear_cache(struct pci_addr_info *pi) } /** - * @pre vm != NULL + * @pre vm != NULL && vcpu != NULL */ -static uint32_t pci_cfgaddr_io_read(struct acrn_vm *vm, uint16_t addr, size_t bytes) +static bool pci_cfgaddr_io_read(struct acrn_vm *vm, struct acrn_vcpu *vcpu, uint16_t addr, size_t bytes) { uint32_t val = ~0U; struct acrn_vpci *vpci = &vm->vpci; struct pci_addr_info *pi = &vpci->addr_info; + struct pio_request *pio_req = &vcpu->req.reqs.pio; if ((addr == (uint16_t)PCI_CONFIG_ADDR) && (bytes == 4U)) { val = (uint32_t)pi->cached_bdf.value; @@ -60,7 +61,9 @@ static uint32_t pci_cfgaddr_io_read(struct acrn_vm *vm, uint16_t addr, size_t by } } - return val; + pio_req->value = val; + + return true; } /** @@ -96,17 +99,18 @@ static inline bool vpci_is_valid_access(uint32_t offset, uint32_t bytes) } /** - * @pre vm != NULL + * @pre vm != NULL && vcpu != NULL * @pre vm->vm_id < CONFIG_MAX_VM_NUM * @pre (get_vm_config(vm->vm_id)->type == PRE_LAUNCHED_VM) || (get_vm_config(vm->vm_id)->type == SOS_VM) */ -static uint32_t pci_cfgdata_io_read(struct acrn_vm *vm, uint16_t addr, size_t bytes) +static bool pci_cfgdata_io_read(struct acrn_vm *vm, struct acrn_vcpu *vcpu, uint16_t addr, size_t bytes) { struct acrn_vpci *vpci = &vm->vpci; struct pci_addr_info *pi = &vpci->addr_info; uint16_t offset = addr - PCI_CONFIG_DATA; uint32_t val = ~0U; struct acrn_vm_config *vm_config; + struct pio_request *pio_req = &vcpu->req.reqs.pio; if (pi->cached_enable) { if (vpci_is_valid_access(pi->cached_reg + offset, bytes)) { @@ -129,7 +133,9 @@ static uint32_t pci_cfgdata_io_read(struct acrn_vm *vm, uint16_t addr, size_t by pci_cfg_clear_cache(pi); } - return val; + pio_req->value = val; + + return true; } /** diff --git a/hypervisor/dm/vpic.c b/hypervisor/dm/vpic.c index b77359705..b5c8e0b84 100644 --- a/hypervisor/dm/vpic.c +++ b/hypervisor/dm/vpic.c @@ -728,15 +728,16 @@ static int32_t vpic_master_handler(struct acrn_vm *vm, bool in, uint16_t port, return ret; } -static uint32_t vpic_master_io_read(struct acrn_vm *vm, uint16_t addr, size_t width) +static bool vpic_master_io_read(struct acrn_vm *vm, struct acrn_vcpu *vcpu, uint16_t addr, size_t width) { - uint32_t val = 0U; + struct pio_request *pio_req = &vcpu->req.reqs.pio; - if (vpic_master_handler(vm, true, addr, width, &val) < 0) { + if (vpic_master_handler(vm, true, addr, width, &pio_req->value) < 0) { pr_err("pic master read port 0x%x width=%d failed\n", addr, width); } - return val; + + return true; } static bool vpic_master_io_write(struct acrn_vm *vm, uint16_t addr, size_t width, @@ -773,15 +774,15 @@ static int32_t vpic_slave_handler(struct acrn_vm *vm, bool in, uint16_t port, return ret; } -static uint32_t vpic_slave_io_read(struct acrn_vm *vm, uint16_t addr, size_t width) +static bool vpic_slave_io_read(struct acrn_vm *vm, struct acrn_vcpu *vcpu, uint16_t addr, size_t width) { - uint32_t val = 0U; + struct pio_request *pio_req = &vcpu->req.reqs.pio; - if (vpic_slave_handler(vm, true, addr, width, &val) < 0) { + if (vpic_slave_handler(vm, true, addr, width, &pio_req->value) < 0) { pr_err("pic slave read port 0x%x width=%d failed\n", addr, width); } - return val; + return true; } static bool vpic_slave_io_write(struct acrn_vm *vm, uint16_t addr, size_t width, @@ -843,14 +844,15 @@ static int32_t vpic_elc_handler(struct acrn_vm *vm, bool in, uint16_t port, size return ret; } -static uint32_t vpic_elc_io_read(struct acrn_vm *vm, uint16_t addr, size_t width) +static bool vpic_elc_io_read(struct acrn_vm *vm, struct acrn_vcpu *vcpu, uint16_t addr, size_t width) { - uint32_t val = 0U; + struct pio_request *pio_req = &vcpu->req.reqs.pio; - if (vpic_elc_handler(vm, true, addr, width, &val) < 0) { + if (vpic_elc_handler(vm, true, addr, width, &pio_req->value) < 0) { pr_err("pic elc read port 0x%x width=%d failed", addr, width); } - return val; + + return true; } static bool vpic_elc_io_write(struct acrn_vm *vm, uint16_t addr, size_t width, diff --git a/hypervisor/dm/vrtc.c b/hypervisor/dm/vrtc.c index 7e3d04598..f751d0f87 100644 --- a/hypervisor/dm/vrtc.c +++ b/hypervisor/dm/vrtc.c @@ -43,19 +43,20 @@ static uint8_t cmos_get_reg_val(uint8_t addr) return reg; } -static uint32_t vrtc_read(struct acrn_vm *vm, uint16_t addr, __unused size_t width) +static bool vrtc_read(struct acrn_vm *vm, struct acrn_vcpu *vcpu, uint16_t addr, __unused size_t width) { - uint8_t reg; uint8_t offset; + struct pio_request *pio_req = &vcpu->req.reqs.pio; offset = vm->vrtc_offset; if (addr == CMOS_ADDR_PORT) { - return vm->vrtc_offset; + pio_req->value = vm->vrtc_offset; + } else { + pio_req->value = cmos_get_reg_val(offset); } - reg = cmos_get_reg_val(offset); - return reg; + return true; } static bool vrtc_write(struct acrn_vm *vm, uint16_t addr, size_t width, diff --git a/hypervisor/include/arch/x86/io_req.h b/hypervisor/include/arch/x86/io_req.h index 9b5499758..43adcdd99 100644 --- a/hypervisor/include/arch/x86/io_req.h +++ b/hypervisor/include/arch/x86/io_req.h @@ -49,7 +49,7 @@ struct acrn_vm; struct acrn_vcpu; typedef -uint32_t (*io_read_fn_t)(struct acrn_vm *vm, uint16_t port, size_t size); +bool (*io_read_fn_t)(struct acrn_vm *vm, struct acrn_vcpu *vcpu, uint16_t port, size_t size); typedef bool (*io_write_fn_t)(struct acrn_vm *vm, uint16_t port, size_t size, uint32_t val);