mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-09-22 01:07:57 +00:00
hv: dm: Use new I/O request data structures
struct vhm_request -> struct acrn_io_request union vhm_request_buffer -> struct acrn_io_request_buffer struct pio_request -> struct acrn_pio_request struct mmio_request -> struct acrn_mmio_request struct ioreq_notify -> struct acrn_ioreq_notify VHM_REQ_PIO_INVAL -> IOREQ_PIO_INVAL VHM_REQ_MMIO_INVAL -> IOREQ_MMIO_INVAL REQ_PORTIO -> ACRN_IOREQ_TYPE_PORTIO REQ_MMIO -> ACRN_IOREQ_TYPE_MMIO REQ_PCICFG -> ACRN_IOREQ_TYPE_PCICFG REQ_WP -> ACRN_IOREQ_TYPE_WP REQUEST_READ -> ACRN_IOREQ_DIR_READ REQUEST_WRITE -> ACRN_IOREQ_DIR_WRITE REQ_STATE_PROCESSING -> ACRN_IOREQ_STATE_PROCESSING REQ_STATE_PENDING -> ACRN_IOREQ_STATE_PENDING REQ_STATE_COMPLETE -> ACRN_IOREQ_STATE_COMPLETE REQ_STATE_FREE -> ACRN_IOREQ_STATE_FREE IC_CREATE_IOREQ_CLIENT -> ACRN_IOCTL_CREATE_IOREQ_CLIENT IC_DESTROY_IOREQ_CLIENT -> ACRN_IOCTL_DESTROY_IOREQ_CLIENT IC_ATTACH_IOREQ_CLIENT -> ACRN_IOCTL_ATTACH_IOREQ_CLIENT IC_NOTIFY_REQUEST_FINISH -> ACRN_IOCTL_NOTIFY_REQUEST_FINISH IC_CLEAR_VM_IOREQ -> ACRN_IOCTL_CLEAR_VM_IOREQ HYPERVISOR_CALLBACK_VHM_VECTOR -> HYPERVISOR_CALLBACK_HSM_VECTOR arch_fire_vhm_interrupt() -> arch_fire_hsm_interrupt() get_vhm_notification_vector() -> get_hsm_notification_vector() set_vhm_notification_vector() -> set_hsm_notification_vector() acrn_vhm_notification_vector -> acrn_hsm_notification_vector get_vhm_req_state() -> get_io_req_state() set_vhm_req_state() -> set_io_req_state() Below structures have slight difference with former ones. struct acrn_ioreq_notify strcut acrn_io_request Tracked-On: #6282 Signed-off-by: Shuo A Liu <shuo.a.liu@intel.com>
This commit is contained in:
@@ -600,7 +600,7 @@ static void vie_calculate_gla(enum vm_cpu_mode cpu_mode, enum cpu_reg_name seg,
|
||||
*/
|
||||
static inline void vie_mmio_read(const struct acrn_vcpu *vcpu, uint64_t *rval)
|
||||
{
|
||||
*rval = vcpu->req.reqs.mmio.value;
|
||||
*rval = vcpu->req.reqs.mmio_request.value;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -608,7 +608,7 @@ static inline void vie_mmio_read(const struct acrn_vcpu *vcpu, uint64_t *rval)
|
||||
*/
|
||||
static inline void vie_mmio_write(struct acrn_vcpu *vcpu, uint64_t wval)
|
||||
{
|
||||
vcpu->req.reqs.mmio.value = wval;
|
||||
vcpu->req.reqs.mmio_request.value = wval;
|
||||
}
|
||||
|
||||
static void vie_calc_bytereg(const struct instr_emul_vie *vie,
|
||||
@@ -1087,7 +1087,7 @@ static int32_t emulate_movs(struct acrn_vcpu *vcpu, const struct instr_emul_vie
|
||||
|
||||
/* update the Memory Operand byte size if necessary */
|
||||
opsize = ((vie->op.op_flags & VIE_OP_F_BYTE_OP) != 0U) ? 1U : vie->opsize;
|
||||
is_mmio_write = (vcpu->req.reqs.mmio.direction == REQUEST_WRITE);
|
||||
is_mmio_write = (vcpu->req.reqs.mmio_request.direction == ACRN_IOREQ_DIR_WRITE);
|
||||
|
||||
/*
|
||||
* XXX although the MOVS instruction is only supposed to be used with
|
||||
@@ -2325,7 +2325,7 @@ static int32_t instr_check_gva(struct acrn_vcpu *vcpu, enum vm_cpu_mode cpu_mode
|
||||
}
|
||||
ret = -EFAULT;
|
||||
} else {
|
||||
err_code = (vcpu->req.reqs.mmio.direction == REQUEST_WRITE) ? PAGE_FAULT_WR_FLAG : 0U;
|
||||
err_code = (vcpu->req.reqs.mmio_request.direction == ACRN_IOREQ_DIR_WRITE) ? PAGE_FAULT_WR_FLAG : 0U;
|
||||
|
||||
ret = gva2gpa(vcpu, gva, &gpa, &err_code);
|
||||
if (ret < 0) {
|
||||
|
@@ -143,7 +143,7 @@ static inline uint8_t get_slp_typx(uint32_t pm1_cnt)
|
||||
|
||||
static bool pm1ab_io_read(struct acrn_vcpu *vcpu, uint16_t addr, size_t width)
|
||||
{
|
||||
struct pio_request *pio_req = &vcpu->req.reqs.pio;
|
||||
struct acrn_pio_request *pio_req = &vcpu->req.reqs.pio_request;
|
||||
|
||||
pio_req->value = pio_read(addr, width);
|
||||
|
||||
@@ -314,7 +314,7 @@ static void register_rt_vm_pm1a_ctl_handler(struct acrn_vm *vm)
|
||||
*/
|
||||
static bool prelaunched_vm_sleep_io_read(struct acrn_vcpu *vcpu, __unused uint16_t addr, __unused size_t width)
|
||||
{
|
||||
vcpu->req.reqs.pio.value = 0U;
|
||||
vcpu->req.reqs.pio_request.value = 0U;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@@ -2383,7 +2383,7 @@ int32_t apic_access_vmexit_handler(struct acrn_vcpu *vcpu)
|
||||
uint32_t offset;
|
||||
uint64_t qual, access_type;
|
||||
struct acrn_vlapic *vlapic;
|
||||
struct mmio_request *mmio;
|
||||
struct acrn_mmio_request *mmio;
|
||||
|
||||
qual = vcpu->arch.exit_qualification;
|
||||
access_type = apic_access_type(qual);
|
||||
@@ -2407,7 +2407,7 @@ int32_t apic_access_vmexit_handler(struct acrn_vcpu *vcpu)
|
||||
(decode_instruction(vcpu) >= 0)) {
|
||||
vlapic = vcpu_vlapic(vcpu);
|
||||
offset = (uint32_t)apic_access_offset(qual);
|
||||
mmio = &vcpu->req.reqs.mmio;
|
||||
mmio = &vcpu->req.reqs.mmio_request;
|
||||
if (access_type == TYPE_LINEAR_APIC_INST_WRITE) {
|
||||
err = emulate_instruction(vcpu);
|
||||
if (err == 0) {
|
||||
|
@@ -22,11 +22,11 @@ void triple_fault_shutdown_vm(struct acrn_vcpu *vcpu)
|
||||
struct io_request *io_req = &vcpu->req;
|
||||
|
||||
/* Device model emulates PM1A for post-launched VMs */
|
||||
io_req->io_type = REQ_PORTIO;
|
||||
io_req->reqs.pio.direction = REQUEST_WRITE;
|
||||
io_req->reqs.pio.address = VIRTUAL_PM1A_CNT_ADDR;
|
||||
io_req->reqs.pio.size = 2UL;
|
||||
io_req->reqs.pio.value = (VIRTUAL_PM1A_SLP_EN | (5U << 10U));
|
||||
io_req->io_type = ACRN_IOREQ_TYPE_PORTIO;
|
||||
io_req->reqs.pio_request.direction = ACRN_IOREQ_DIR_WRITE;
|
||||
io_req->reqs.pio_request.address = VIRTUAL_PM1A_CNT_ADDR;
|
||||
io_req->reqs.pio_request.size = 2UL;
|
||||
io_req->reqs.pio_request.value = (VIRTUAL_PM1A_SLP_EN | (5U << 10U));
|
||||
|
||||
/* Inject pm1a S5 request to SOS to shut down the guest */
|
||||
(void)emulate_io(vcpu, io_req);
|
||||
@@ -76,7 +76,7 @@ static bool handle_reset_reg_read(struct acrn_vcpu *vcpu, __unused uint16_t addr
|
||||
* - reset control register 0xcf9: hide this from guests for now.
|
||||
* - FADT reset register: the read behavior is not defined in spec, keep it simple to return all '1'.
|
||||
*/
|
||||
vcpu->req.reqs.pio.value = ~0U;
|
||||
vcpu->req.reqs.pio_request.value = ~0U;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -139,10 +139,10 @@ static bool handle_kb_read(struct acrn_vcpu *vcpu, uint16_t addr, size_t bytes)
|
||||
{
|
||||
if (is_sos_vm(vcpu->vm) && (bytes == 1U)) {
|
||||
/* In case i8042 is defined as ACPI PNP device in BIOS, HV need expose physical 0x64 port. */
|
||||
vcpu->req.reqs.pio.value = pio_read8(addr);
|
||||
vcpu->req.reqs.pio_request.value = pio_read8(addr);
|
||||
} else {
|
||||
/* ACRN will not expose kbd controller to the guest in this case. */
|
||||
vcpu->req.reqs.pio.value = ~0U;
|
||||
vcpu->req.reqs.pio_request.value = ~0U;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@@ -18,7 +18,7 @@
|
||||
#include <trace.h>
|
||||
#include <logmsg.h>
|
||||
|
||||
void arch_fire_vhm_interrupt(void)
|
||||
void arch_fire_hsm_interrupt(void)
|
||||
{
|
||||
/*
|
||||
* use vLAPIC to inject vector to SOS vcpu 0 if vlapic is enabled
|
||||
@@ -30,25 +30,25 @@ void arch_fire_vhm_interrupt(void)
|
||||
sos_vm = get_sos_vm();
|
||||
vcpu = vcpu_from_vid(sos_vm, BSP_CPU_ID);
|
||||
|
||||
vlapic_set_intr(vcpu, get_vhm_notification_vector(), LAPIC_TRIG_EDGE);
|
||||
vlapic_set_intr(vcpu, get_hsm_notification_vector(), LAPIC_TRIG_EDGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief General complete-work for port I/O emulation
|
||||
*
|
||||
* @pre io_req->io_type == REQ_PORTIO
|
||||
* @pre io_req->io_type == ACRN_IOREQ_TYPE_PORTIO
|
||||
*
|
||||
* @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
|
||||
* either a previous call to emulate_io() returning 0 or the corresponding IO
|
||||
* request having transferred to the COMPLETE state.
|
||||
*/
|
||||
void
|
||||
emulate_pio_complete(struct acrn_vcpu *vcpu, const struct io_request *io_req)
|
||||
{
|
||||
const struct pio_request *pio_req = &io_req->reqs.pio;
|
||||
const struct acrn_pio_request *pio_req = &io_req->reqs.pio_request;
|
||||
uint64_t mask = 0xFFFFFFFFUL >> (32UL - (8UL * pio_req->size));
|
||||
|
||||
if (pio_req->direction == REQUEST_READ) {
|
||||
if (pio_req->direction == ACRN_IOREQ_DIR_READ) {
|
||||
uint64_t value = (uint64_t)pio_req->value;
|
||||
uint64_t rax = vcpu_get_gpreg(vcpu, CPU_REG_RAX);
|
||||
|
||||
@@ -70,19 +70,19 @@ int32_t pio_instr_vmexit_handler(struct acrn_vcpu *vcpu)
|
||||
uint32_t mask;
|
||||
int32_t cur_context_idx = vcpu->arch.cur_context;
|
||||
struct io_request *io_req = &vcpu->req;
|
||||
struct pio_request *pio_req = &io_req->reqs.pio;
|
||||
struct acrn_pio_request *pio_req = &io_req->reqs.pio_request;
|
||||
|
||||
exit_qual = vcpu->arch.exit_qualification;
|
||||
|
||||
io_req->io_type = REQ_PORTIO;
|
||||
io_req->io_type = ACRN_IOREQ_TYPE_PORTIO;
|
||||
pio_req->size = vm_exit_io_instruction_size(exit_qual) + 1UL;
|
||||
pio_req->address = vm_exit_io_instruction_port_number(exit_qual);
|
||||
if (vm_exit_io_instruction_access_direction(exit_qual) == 0UL) {
|
||||
mask = 0xFFFFFFFFU >> (32U - (8U * pio_req->size));
|
||||
pio_req->direction = REQUEST_WRITE;
|
||||
pio_req->direction = ACRN_IOREQ_DIR_WRITE;
|
||||
pio_req->value = (uint32_t)vcpu_get_gpreg(vcpu, CPU_REG_RAX) & mask;
|
||||
} else {
|
||||
pio_req->direction = REQUEST_READ;
|
||||
pio_req->direction = ACRN_IOREQ_DIR_READ;
|
||||
}
|
||||
|
||||
TRACE_4I(TRACE_VMEXIT_IO_INSTRUCTION,
|
||||
@@ -102,7 +102,7 @@ int32_t ept_violation_vmexit_handler(struct acrn_vcpu *vcpu)
|
||||
uint64_t exit_qual;
|
||||
uint64_t gpa;
|
||||
struct io_request *io_req = &vcpu->req;
|
||||
struct mmio_request *mmio_req = &io_req->reqs.mmio;
|
||||
struct acrn_mmio_request *mmio_req = &io_req->reqs.mmio_request;
|
||||
|
||||
/* Handle page fault from guest */
|
||||
exit_qual = vcpu->arch.exit_qualification;
|
||||
@@ -125,21 +125,21 @@ int32_t ept_violation_vmexit_handler(struct acrn_vcpu *vcpu)
|
||||
status = 0;
|
||||
} else {
|
||||
|
||||
io_req->io_type = REQ_MMIO;
|
||||
io_req->io_type = ACRN_IOREQ_TYPE_MMIO;
|
||||
|
||||
/* Specify if read or write operation */
|
||||
if ((exit_qual & 0x2UL) != 0UL) {
|
||||
/* Write operation */
|
||||
mmio_req->direction = REQUEST_WRITE;
|
||||
mmio_req->direction = ACRN_IOREQ_DIR_WRITE;
|
||||
mmio_req->value = 0UL;
|
||||
|
||||
/* XXX: write access while EPT perm RX -> WP */
|
||||
if ((exit_qual & 0x38UL) == 0x28UL) {
|
||||
io_req->io_type = REQ_WP;
|
||||
io_req->io_type = ACRN_IOREQ_TYPE_WP;
|
||||
}
|
||||
} else {
|
||||
/* Read operation */
|
||||
mmio_req->direction = REQUEST_READ;
|
||||
mmio_req->direction = ACRN_IOREQ_DIR_READ;
|
||||
|
||||
/* TODO: Need to determine how sign extension is determined for
|
||||
* reads
|
||||
@@ -160,7 +160,7 @@ int32_t ept_violation_vmexit_handler(struct acrn_vcpu *vcpu)
|
||||
*/
|
||||
|
||||
/* Determine value being written. */
|
||||
if (mmio_req->direction == REQUEST_WRITE) {
|
||||
if (mmio_req->direction == ACRN_IOREQ_DIR_WRITE) {
|
||||
status = emulate_instruction(vcpu);
|
||||
if (status != 0) {
|
||||
ret = -EFAULT;
|
||||
|
@@ -527,8 +527,7 @@ int32_t hcall_inject_msi(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, __un
|
||||
*
|
||||
* @param vcpu Pointer to vCPU that initiates the hypercall
|
||||
* @param target_vm Pointer to target VM data structure
|
||||
* @param param2 guest physical address. This gpa points to
|
||||
* struct acrn_set_ioreq_buffer
|
||||
* @param param2 guest physical address. This gpa points to buffer address
|
||||
*
|
||||
* @pre is_sos_vm(vcpu->vm)
|
||||
* @return 0 on success, non-zero on error.
|
||||
@@ -542,21 +541,21 @@ int32_t hcall_set_ioreq_buffer(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm
|
||||
int32_t ret = -1;
|
||||
|
||||
if (is_created_vm(target_vm)) {
|
||||
struct acrn_set_ioreq_buffer iobuf;
|
||||
uint64_t iobuf;
|
||||
|
||||
if (copy_from_gpa(vm, &iobuf, param2, sizeof(iobuf)) == 0) {
|
||||
dev_dbg(DBG_LEVEL_HYCALL, "[%d] SET BUFFER=0x%p",
|
||||
target_vm->vm_id, iobuf.req_buf);
|
||||
target_vm->vm_id, iobuf);
|
||||
|
||||
hpa = gpa2hpa(vm, iobuf.req_buf);
|
||||
hpa = gpa2hpa(vm, iobuf);
|
||||
if (hpa == INVALID_HPA) {
|
||||
pr_err("%s,vm[%hu] gpa 0x%lx,GPA is unmapping.",
|
||||
__func__, vm->vm_id, iobuf.req_buf);
|
||||
__func__, vm->vm_id, iobuf);
|
||||
target_vm->sw.io_shared_page = NULL;
|
||||
} else {
|
||||
target_vm->sw.io_shared_page = hpa2hva(hpa);
|
||||
for (i = 0U; i < VHM_REQUEST_MAX; i++) {
|
||||
set_vhm_req_state(target_vm, i, REQ_STATE_FREE);
|
||||
for (i = 0U; i < ACRN_IO_REQUEST_MAX; i++) {
|
||||
set_io_req_state(target_vm, i, ACRN_IOREQ_STATE_FREE);
|
||||
}
|
||||
ret = 0;
|
||||
}
|
||||
@@ -1232,7 +1231,7 @@ int32_t hcall_set_callback_vector(__unused struct acrn_vcpu *vcpu, __unused stru
|
||||
pr_err("%s: Invalid passed vector\n", __func__);
|
||||
ret = -EINVAL;
|
||||
} else {
|
||||
set_vhm_notification_vector((uint32_t)param1);
|
||||
set_hsm_notification_vector((uint32_t)param1);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
|
@@ -10,34 +10,34 @@
|
||||
|
||||
#define DBG_LEVEL_IOREQ 6U
|
||||
|
||||
static uint32_t acrn_vhm_notification_vector = HYPERVISOR_CALLBACK_VHM_VECTOR;
|
||||
static uint32_t acrn_hsm_notification_vector = HYPERVISOR_CALLBACK_HSM_VECTOR;
|
||||
#define MMIO_DEFAULT_VALUE_SIZE_1 (0xFFUL)
|
||||
#define MMIO_DEFAULT_VALUE_SIZE_2 (0xFFFFUL)
|
||||
#define MMIO_DEFAULT_VALUE_SIZE_4 (0xFFFFFFFFUL)
|
||||
#define MMIO_DEFAULT_VALUE_SIZE_8 (0xFFFFFFFFFFFFFFFFUL)
|
||||
|
||||
#if defined(HV_DEBUG)
|
||||
__unused static void acrn_print_request(uint16_t vcpu_id, const struct vhm_request *req)
|
||||
__unused static void acrn_print_request(uint16_t vcpu_id, const struct acrn_io_request *req)
|
||||
{
|
||||
switch (req->type) {
|
||||
case REQ_MMIO:
|
||||
case ACRN_IOREQ_TYPE_MMIO:
|
||||
dev_dbg(DBG_LEVEL_IOREQ, "[vcpu_id=%hu type=MMIO]", vcpu_id);
|
||||
dev_dbg(DBG_LEVEL_IOREQ,
|
||||
"gpa=0x%lx, R/W=%d, size=%ld value=0x%lx processed=%lx",
|
||||
req->reqs.mmio.address,
|
||||
req->reqs.mmio.direction,
|
||||
req->reqs.mmio.size,
|
||||
req->reqs.mmio.value,
|
||||
req->reqs.mmio_request.address,
|
||||
req->reqs.mmio_request.direction,
|
||||
req->reqs.mmio_request.size,
|
||||
req->reqs.mmio_request.value,
|
||||
req->processed);
|
||||
break;
|
||||
case REQ_PORTIO:
|
||||
case ACRN_IOREQ_TYPE_PORTIO:
|
||||
dev_dbg(DBG_LEVEL_IOREQ, "[vcpu_id=%hu type=PORTIO]", vcpu_id);
|
||||
dev_dbg(DBG_LEVEL_IOREQ,
|
||||
"IO=0x%lx, R/W=%d, size=%ld value=0x%lx processed=%lx",
|
||||
req->reqs.pio.address,
|
||||
req->reqs.pio.direction,
|
||||
req->reqs.pio.size,
|
||||
req->reqs.pio.value,
|
||||
req->reqs.pio_request.address,
|
||||
req->reqs.pio_request.direction,
|
||||
req->reqs.pio_request.size,
|
||||
req->reqs.pio_request.value,
|
||||
req->processed);
|
||||
break;
|
||||
default:
|
||||
@@ -59,14 +59,14 @@ void reset_vm_ioreqs(struct acrn_vm *vm)
|
||||
{
|
||||
uint16_t i;
|
||||
|
||||
for (i = 0U; i < VHM_REQUEST_MAX; i++) {
|
||||
set_vhm_req_state(vm, i, REQ_STATE_FREE);
|
||||
for (i = 0U; i < ACRN_IO_REQUEST_MAX; i++) {
|
||||
set_io_req_state(vm, i, ACRN_IOREQ_STATE_FREE);
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool has_complete_ioreq(const struct acrn_vcpu *vcpu)
|
||||
{
|
||||
return (get_vhm_req_state(vcpu->vm, vcpu->vcpu_id) == REQ_STATE_COMPLETE);
|
||||
return (get_io_req_state(vcpu->vm, vcpu->vcpu_id) == ACRN_IOREQ_STATE_COMPLETE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,42 +79,42 @@ static inline bool has_complete_ioreq(const struct acrn_vcpu *vcpu)
|
||||
*/
|
||||
int32_t acrn_insert_request(struct acrn_vcpu *vcpu, const struct io_request *io_req)
|
||||
{
|
||||
union vhm_request_buffer *req_buf = NULL;
|
||||
struct vhm_request *vhm_req;
|
||||
struct acrn_io_request_buffer *req_buf = NULL;
|
||||
struct acrn_io_request *acrn_io_req;
|
||||
bool is_polling = false;
|
||||
int32_t ret = 0;
|
||||
uint16_t cur;
|
||||
|
||||
if ((vcpu->vm->sw.io_shared_page != NULL)
|
||||
&& (get_vhm_req_state(vcpu->vm, vcpu->vcpu_id) == REQ_STATE_FREE)) {
|
||||
&& (get_io_req_state(vcpu->vm, vcpu->vcpu_id) == ACRN_IOREQ_STATE_FREE)) {
|
||||
|
||||
req_buf = (union vhm_request_buffer *)(vcpu->vm->sw.io_shared_page);
|
||||
req_buf = (struct acrn_io_request_buffer *)(vcpu->vm->sw.io_shared_page);
|
||||
cur = vcpu->vcpu_id;
|
||||
|
||||
stac();
|
||||
vhm_req = &req_buf->req_queue[cur];
|
||||
/* ACRN insert request to VHM and inject upcall */
|
||||
vhm_req->type = io_req->io_type;
|
||||
(void)memcpy_s(&vhm_req->reqs, sizeof(union vhm_io_request),
|
||||
&io_req->reqs, sizeof(union vhm_io_request));
|
||||
acrn_io_req = &req_buf->req_slot[cur];
|
||||
/* ACRN insert request to HSM and inject upcall */
|
||||
acrn_io_req->type = io_req->io_type;
|
||||
(void)memcpy_s(&acrn_io_req->reqs, sizeof(acrn_io_req->reqs),
|
||||
&io_req->reqs, sizeof(acrn_io_req->reqs));
|
||||
if (vcpu->vm->sw.is_polling_ioreq) {
|
||||
vhm_req->completion_polling = 1U;
|
||||
acrn_io_req->completion_polling = 1U;
|
||||
is_polling = true;
|
||||
}
|
||||
clac();
|
||||
|
||||
/* Before updating the vhm_req state, enforce all fill vhm_req operations done */
|
||||
/* Before updating the acrn_io_req state, enforce all fill acrn_io_req operations done */
|
||||
cpu_write_memory_barrier();
|
||||
|
||||
/* Must clear the signal before we mark req as pending
|
||||
* Once we mark it pending, VHM may process req and signal us
|
||||
* Once we mark it pending, HSM may process req and signal us
|
||||
* before we perform upcall.
|
||||
* because VHM can work in pulling mode without wait for upcall
|
||||
* because HSM can work in pulling mode without wait for upcall
|
||||
*/
|
||||
set_vhm_req_state(vcpu->vm, vcpu->vcpu_id, REQ_STATE_PENDING);
|
||||
set_io_req_state(vcpu->vm, vcpu->vcpu_id, ACRN_IOREQ_STATE_PENDING);
|
||||
|
||||
/* signal VHM */
|
||||
arch_fire_vhm_interrupt();
|
||||
/* signal HSM */
|
||||
arch_fire_hsm_interrupt();
|
||||
|
||||
/* Polling completion of the request in polling mode */
|
||||
if (is_polling) {
|
||||
@@ -138,53 +138,53 @@ int32_t acrn_insert_request(struct acrn_vcpu *vcpu, const struct io_request *io_
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t get_vhm_req_state(struct acrn_vm *vm, uint16_t vhm_req_id)
|
||||
uint32_t get_io_req_state(struct acrn_vm *vm, uint16_t vcpu_id)
|
||||
{
|
||||
uint32_t state;
|
||||
union vhm_request_buffer *req_buf = NULL;
|
||||
struct vhm_request *vhm_req;
|
||||
struct acrn_io_request_buffer *req_buf = NULL;
|
||||
struct acrn_io_request *acrn_io_req;
|
||||
|
||||
req_buf = (union vhm_request_buffer *)vm->sw.io_shared_page;
|
||||
req_buf = (struct acrn_io_request_buffer *)vm->sw.io_shared_page;
|
||||
if (req_buf == NULL) {
|
||||
state = 0xffffffffU;
|
||||
} else {
|
||||
stac();
|
||||
vhm_req = &req_buf->req_queue[vhm_req_id];
|
||||
state = vhm_req->processed;
|
||||
acrn_io_req = &req_buf->req_slot[vcpu_id];
|
||||
state = acrn_io_req->processed;
|
||||
clac();
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
void set_vhm_req_state(struct acrn_vm *vm, uint16_t vhm_req_id, uint32_t state)
|
||||
void set_io_req_state(struct acrn_vm *vm, uint16_t vcpu_id, uint32_t state)
|
||||
{
|
||||
union vhm_request_buffer *req_buf = NULL;
|
||||
struct vhm_request *vhm_req;
|
||||
struct acrn_io_request_buffer *req_buf = NULL;
|
||||
struct acrn_io_request *acrn_io_req;
|
||||
|
||||
req_buf = (union vhm_request_buffer *)vm->sw.io_shared_page;
|
||||
req_buf = (struct acrn_io_request_buffer *)vm->sw.io_shared_page;
|
||||
if (req_buf != NULL) {
|
||||
stac();
|
||||
vhm_req = &req_buf->req_queue[vhm_req_id];
|
||||
acrn_io_req = &req_buf->req_slot[vcpu_id];
|
||||
/*
|
||||
* HV will only set processed to REQ_STATE_PENDING or REQ_STATE_FREE.
|
||||
* HV will only set processed to ACRN_IOREQ_STATE_PENDING or ACRN_IOREQ_STATE_FREE.
|
||||
* we don't need to sfence here is that even if the SOS/DM sees the previous state,
|
||||
* the only side effect is that it will defer the processing of the new IOReq.
|
||||
* It won't lead wrong processing.
|
||||
*/
|
||||
vhm_req->processed = state;
|
||||
acrn_io_req->processed = state;
|
||||
clac();
|
||||
}
|
||||
}
|
||||
|
||||
void set_vhm_notification_vector(uint32_t vector)
|
||||
void set_hsm_notification_vector(uint32_t vector)
|
||||
{
|
||||
acrn_vhm_notification_vector = vector;
|
||||
acrn_hsm_notification_vector = vector;
|
||||
}
|
||||
|
||||
uint32_t get_vhm_notification_vector(void)
|
||||
uint32_t get_hsm_notification_vector(void)
|
||||
{
|
||||
return acrn_vhm_notification_vector;
|
||||
return acrn_hsm_notification_vector;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -193,17 +193,17 @@ uint32_t get_vhm_notification_vector(void)
|
||||
* @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->io_type == REQ_MMIO
|
||||
* @pre io_req->io_type == ACRN_IOREQ_TYPE_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
|
||||
* either a previous call to emulate_io() returning 0 or the corresponding HSM
|
||||
* request transferring to the COMPLETE state.
|
||||
*/
|
||||
static void emulate_mmio_complete(struct acrn_vcpu *vcpu, const struct io_request *io_req)
|
||||
{
|
||||
const struct mmio_request *mmio_req = &io_req->reqs.mmio;
|
||||
const struct acrn_mmio_request *mmio_req = &io_req->reqs.mmio_request;
|
||||
|
||||
if (mmio_req->direction == REQUEST_READ) {
|
||||
if (mmio_req->direction == ACRN_IOREQ_DIR_READ) {
|
||||
/* Emulate instruction and update vcpu register set */
|
||||
(void)emulate_instruction(vcpu);
|
||||
}
|
||||
@@ -211,21 +211,21 @@ static void emulate_mmio_complete(struct acrn_vcpu *vcpu, const struct io_reques
|
||||
|
||||
static void complete_ioreq(struct acrn_vcpu *vcpu, struct io_request *io_req)
|
||||
{
|
||||
union vhm_request_buffer *req_buf = NULL;
|
||||
struct vhm_request *vhm_req;
|
||||
struct acrn_io_request_buffer *req_buf = NULL;
|
||||
struct acrn_io_request *acrn_io_req;
|
||||
|
||||
req_buf = (union vhm_request_buffer *)(vcpu->vm->sw.io_shared_page);
|
||||
req_buf = (struct acrn_io_request_buffer *)(vcpu->vm->sw.io_shared_page);
|
||||
|
||||
stac();
|
||||
vhm_req = &req_buf->req_queue[vcpu->vcpu_id];
|
||||
acrn_io_req = &req_buf->req_slot[vcpu->vcpu_id];
|
||||
if (io_req != NULL) {
|
||||
switch (vcpu->req.io_type) {
|
||||
case REQ_PORTIO:
|
||||
io_req->reqs.pio.value = vhm_req->reqs.pio.value;
|
||||
case ACRN_IOREQ_TYPE_PORTIO:
|
||||
io_req->reqs.pio_request.value = acrn_io_req->reqs.pio_request.value;
|
||||
break;
|
||||
|
||||
case REQ_MMIO:
|
||||
io_req->reqs.mmio.value = vhm_req->reqs.mmio.value;
|
||||
case ACRN_IOREQ_TYPE_MMIO:
|
||||
io_req->reqs.mmio_request.value = acrn_io_req->reqs.mmio_request.value;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -235,19 +235,19 @@ static void complete_ioreq(struct acrn_vcpu *vcpu, struct io_request *io_req)
|
||||
}
|
||||
|
||||
/*
|
||||
* Only HV will check whether processed is REQ_STATE_FREE on per-vCPU before inject a ioreq.
|
||||
* Only HV will set processed to REQ_STATE_FREE when ioreq is done.
|
||||
* Only HV will check whether processed is ACRN_IOREQ_STATE_FREE on per-vCPU before inject a ioreq.
|
||||
* Only HV will set processed to ACRN_IOREQ_STATE_FREE when ioreq is done.
|
||||
*/
|
||||
vhm_req->processed = REQ_STATE_FREE;
|
||||
acrn_io_req->processed = ACRN_IOREQ_STATE_FREE;
|
||||
clac();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Complete-work of VHM requests for port I/O emulation
|
||||
* @brief Complete-work of HSM requests for port I/O emulation
|
||||
*
|
||||
* @pre vcpu->req.io_type == REQ_PORTIO
|
||||
* @pre vcpu->req.io_type == ACRN_IOREQ_TYPE_PORTIO
|
||||
*
|
||||
* @remark This function must be called after the VHM request corresponding to
|
||||
* @remark This function must be called after the HSM request corresponding to
|
||||
* \p vcpu being transferred to the COMPLETE state.
|
||||
*/
|
||||
static void dm_emulate_pio_complete(struct acrn_vcpu *vcpu)
|
||||
@@ -260,13 +260,13 @@ static void dm_emulate_pio_complete(struct acrn_vcpu *vcpu)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Complete-work of VHM requests for MMIO emulation
|
||||
* @brief Complete-work of HSM requests for MMIO emulation
|
||||
*
|
||||
* @param vcpu The virtual CPU that triggers the MMIO access
|
||||
*
|
||||
* @pre vcpu->req.io_type == REQ_MMIO
|
||||
* @pre vcpu->req.io_type == ACRN_IOREQ_TYPE_MMIO
|
||||
*
|
||||
* @remark This function must be called after the VHM request corresponding to
|
||||
* @remark This function must be called after the HSM request corresponding to
|
||||
* \p vcpu being transferred to the COMPLETE state.
|
||||
*/
|
||||
static void dm_emulate_mmio_complete(struct acrn_vcpu *vcpu)
|
||||
@@ -279,13 +279,13 @@ static void dm_emulate_mmio_complete(struct acrn_vcpu *vcpu)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief General complete-work for all kinds of VHM requests for I/O emulation
|
||||
* @brief General complete-work for all kinds of HSM requests for I/O emulation
|
||||
*
|
||||
* @param vcpu The virtual CPU that triggers the MMIO access
|
||||
*/
|
||||
static void dm_emulate_io_complete(struct acrn_vcpu *vcpu)
|
||||
{
|
||||
if (get_vhm_req_state(vcpu->vm, vcpu->vcpu_id) == REQ_STATE_COMPLETE) {
|
||||
if (get_io_req_state(vcpu->vm, vcpu->vcpu_id) == ACRN_IOREQ_STATE_COMPLETE) {
|
||||
/*
|
||||
* If vcpu is in Zombie state and will be destroyed soon. Just
|
||||
* mark ioreq done and don't resume vcpu.
|
||||
@@ -294,26 +294,27 @@ static void dm_emulate_io_complete(struct acrn_vcpu *vcpu)
|
||||
complete_ioreq(vcpu, NULL);
|
||||
} else {
|
||||
switch (vcpu->req.io_type) {
|
||||
case REQ_MMIO:
|
||||
case ACRN_IOREQ_TYPE_MMIO:
|
||||
dm_emulate_mmio_complete(vcpu);
|
||||
break;
|
||||
|
||||
case REQ_PORTIO:
|
||||
case REQ_PCICFG:
|
||||
case ACRN_IOREQ_TYPE_PORTIO:
|
||||
case ACRN_IOREQ_TYPE_PCICFG:
|
||||
/*
|
||||
* REQ_PORTIO on 0xcf8 & 0xcfc may switch to REQ_PCICFG in some
|
||||
* cases. It works to apply the post-work for REQ_PORTIO on
|
||||
* REQ_PCICFG because the format of the first 28 bytes of
|
||||
* REQ_PORTIO & REQ_PCICFG requests are exactly the same and
|
||||
* post-work is mainly interested in the read value.
|
||||
* ACRN_IOREQ_TYPE_PORTIO on 0xcf8 & 0xcfc may switch to
|
||||
* ACRN_IOREQ_TYPE_PCICFG in some cases. It works to apply the post-work
|
||||
* for ACRN_IOREQ_TYPE_PORTIO on ACRN_IOREQ_TYPE_PCICFG because the
|
||||
* format of the first 28 bytes of ACRN_IOREQ_TYPE_PORTIO &
|
||||
* ACRN_IOREQ_TYPE_PCICFG requests are exactly the same and post-work
|
||||
* is mainly interested in the read value.
|
||||
*/
|
||||
dm_emulate_pio_complete(vcpu);
|
||||
break;
|
||||
|
||||
default:
|
||||
/*
|
||||
* REQ_WP can only be triggered on writes which do not need
|
||||
* post-work. Just mark the ioreq done.
|
||||
* ACRN_IOREQ_TYPE_WP can only be triggered on writes which do
|
||||
* not need post-work. Just mark the ioreq done.
|
||||
*/
|
||||
complete_ioreq(vcpu, NULL);
|
||||
break;
|
||||
@@ -331,7 +332,7 @@ static void dm_emulate_io_complete(struct acrn_vcpu *vcpu)
|
||||
static bool pio_default_read(struct acrn_vcpu *vcpu,
|
||||
__unused uint16_t addr, size_t width)
|
||||
{
|
||||
struct pio_request *pio_req = &vcpu->req.reqs.pio;
|
||||
struct acrn_pio_request *pio_req = &vcpu->req.reqs.pio_request;
|
||||
|
||||
pio_req->value = (uint32_t)((1UL << (width * 8U)) - 1UL);
|
||||
|
||||
@@ -356,9 +357,9 @@ static bool pio_default_write(__unused struct acrn_vcpu *vcpu, __unused uint16_t
|
||||
static int32_t mmio_default_access_handler(struct io_request *io_req,
|
||||
__unused void *handler_private_data)
|
||||
{
|
||||
struct mmio_request *mmio = &io_req->reqs.mmio;
|
||||
struct acrn_mmio_request *mmio = &io_req->reqs.mmio_request;
|
||||
|
||||
if (mmio->direction == REQUEST_READ) {
|
||||
if (mmio->direction == ACRN_IOREQ_DIR_READ) {
|
||||
switch (mmio->size) {
|
||||
case 1U:
|
||||
mmio->value = MMIO_DEFAULT_VALUE_SIZE_1;
|
||||
@@ -385,7 +386,7 @@ static int32_t mmio_default_access_handler(struct io_request *io_req,
|
||||
* Try handling the given request by any port I/O handler registered in the
|
||||
* hypervisor.
|
||||
*
|
||||
* @pre io_req->io_type == REQ_PORTIO
|
||||
* @pre io_req->io_type == ACRN_IOREQ_TYPE_PORTIO
|
||||
*
|
||||
* @retval 0 Successfully emulated by registered handlers.
|
||||
* @retval -ENODEV No proper handler found.
|
||||
@@ -398,7 +399,7 @@ hv_emulate_pio(struct acrn_vcpu *vcpu, struct io_request *io_req)
|
||||
uint16_t port, size;
|
||||
uint32_t idx;
|
||||
struct acrn_vm *vm = vcpu->vm;
|
||||
struct pio_request *pio_req = &io_req->reqs.pio;
|
||||
struct acrn_pio_request *pio_req = &io_req->reqs.pio_request;
|
||||
struct vm_io_handler_desc *handler;
|
||||
io_read_fn_t io_read = NULL;
|
||||
io_write_fn_t io_write = NULL;
|
||||
@@ -427,11 +428,11 @@ hv_emulate_pio(struct acrn_vcpu *vcpu, struct io_request *io_req)
|
||||
break;
|
||||
}
|
||||
|
||||
if ((pio_req->direction == REQUEST_WRITE) && (io_write != NULL)) {
|
||||
if ((pio_req->direction == ACRN_IOREQ_DIR_WRITE) && (io_write != NULL)) {
|
||||
if (io_write(vcpu, port, size, pio_req->value)) {
|
||||
status = 0;
|
||||
}
|
||||
} else if ((pio_req->direction == REQUEST_READ) && (io_read != NULL)) {
|
||||
} else if ((pio_req->direction == ACRN_IOREQ_DIR_READ) && (io_read != NULL)) {
|
||||
if (io_read(vcpu, port, size)) {
|
||||
status = 0;
|
||||
}
|
||||
@@ -440,7 +441,7 @@ hv_emulate_pio(struct acrn_vcpu *vcpu, struct io_request *io_req)
|
||||
}
|
||||
|
||||
pr_dbg("IO %s on port %04x, data %08x",
|
||||
(pio_req->direction == REQUEST_READ) ? "read" : "write", port, pio_req->value);
|
||||
(pio_req->direction == ACRN_IOREQ_DIR_READ) ? "read" : "write", port, pio_req->value);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -449,7 +450,7 @@ hv_emulate_pio(struct acrn_vcpu *vcpu, struct io_request *io_req)
|
||||
* Use registered MMIO handlers on the given request if it falls in the range of
|
||||
* any of them.
|
||||
*
|
||||
* @pre io_req->io_type == REQ_MMIO
|
||||
* @pre io_req->io_type == ACRN_IOREQ_TYPE_MMIO
|
||||
*
|
||||
* @retval 0 Successfully emulated by registered handlers.
|
||||
* @retval -ENODEV No proper handler found.
|
||||
@@ -462,7 +463,7 @@ hv_emulate_mmio(struct acrn_vcpu *vcpu, struct io_request *io_req)
|
||||
bool hold_lock = true;
|
||||
uint16_t idx;
|
||||
uint64_t address, size, base, end;
|
||||
struct mmio_request *mmio_req = &io_req->reqs.mmio;
|
||||
struct acrn_mmio_request *mmio_req = &io_req->reqs.mmio_request;
|
||||
struct mem_io_node *mmio_handler = NULL;
|
||||
hv_mem_io_handler_t read_write = NULL;
|
||||
void *handler_private_data = NULL;
|
||||
@@ -518,7 +519,7 @@ hv_emulate_mmio(struct acrn_vcpu *vcpu, struct io_request *io_req)
|
||||
* @brief Emulate \p io_req for \p vcpu
|
||||
*
|
||||
* Handle an I/O request by either invoking a hypervisor-internal handler or
|
||||
* deliver to VHM.
|
||||
* deliver to HSM.
|
||||
*
|
||||
* @pre vcpu != NULL
|
||||
* @pre vcpu->vm != NULL
|
||||
@@ -528,7 +529,7 @@ hv_emulate_mmio(struct acrn_vcpu *vcpu, struct io_request *io_req)
|
||||
* @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 ACRN_IOREQ_STATE_PENDING The I/O request is delivered to HSM.
|
||||
* @retval -EIO The request spans multiple devices and cannot be emulated.
|
||||
* @retval -EINVAL \p io_req has an invalid io_type.
|
||||
* @retval <0 on other errors during emulation.
|
||||
@@ -542,14 +543,14 @@ emulate_io(struct acrn_vcpu *vcpu, struct io_request *io_req)
|
||||
vm_config = get_vm_config(vcpu->vm->vm_id);
|
||||
|
||||
switch (io_req->io_type) {
|
||||
case REQ_PORTIO:
|
||||
case ACRN_IOREQ_TYPE_PORTIO:
|
||||
status = hv_emulate_pio(vcpu, io_req);
|
||||
if (status == 0) {
|
||||
emulate_pio_complete(vcpu, io_req);
|
||||
}
|
||||
break;
|
||||
case REQ_MMIO:
|
||||
case REQ_WP:
|
||||
case ACRN_IOREQ_TYPE_MMIO:
|
||||
case ACRN_IOREQ_TYPE_WP:
|
||||
status = hv_emulate_mmio(vcpu, io_req);
|
||||
if (status == 0) {
|
||||
emulate_mmio_complete(vcpu, io_req);
|
||||
@@ -563,9 +564,9 @@ emulate_io(struct acrn_vcpu *vcpu, struct io_request *io_req)
|
||||
|
||||
if ((status == -ENODEV) && (vm_config->load_order == POST_LAUNCHED_VM)) {
|
||||
/*
|
||||
* No handler from HV side, search from VHM in Dom0
|
||||
* No handler from HV side, search from HSM in Service VM
|
||||
*
|
||||
* ACRN insert request to VHM and inject upcall.
|
||||
* ACRN insert request to HSM and inject upcall.
|
||||
*/
|
||||
status = acrn_insert_request(vcpu, io_req);
|
||||
if (status == 0) {
|
||||
@@ -574,7 +575,7 @@ emulate_io(struct acrn_vcpu *vcpu, struct io_request *io_req)
|
||||
/* here for both IO & MMIO, the direction, address,
|
||||
* size definition is same
|
||||
*/
|
||||
struct pio_request *pio_req = &io_req->reqs.pio;
|
||||
struct acrn_pio_request *pio_req = &io_req->reqs.pio_request;
|
||||
|
||||
pr_fatal("%s Err: access dir %d, io_type %d, addr = 0x%lx, size=%lu", __func__,
|
||||
pio_req->direction, io_req->io_type,
|
||||
|
@@ -84,7 +84,7 @@ static uint32_t ioapic_pin_to_vpin(struct acrn_vm *vm, const struct acrn_vm_conf
|
||||
|
||||
static int32_t vgpio_mmio_handler(struct io_request *io_req, void *data)
|
||||
{
|
||||
struct mmio_request *mmio = &io_req->reqs.mmio;
|
||||
struct acrn_mmio_request *mmio = &io_req->reqs.mmio_request;
|
||||
struct acrn_vm *vm = (struct acrn_vm *) data;
|
||||
struct acrn_vm_config *vm_config = get_vm_config(vm->vm_id);
|
||||
int32_t ret = 0;
|
||||
@@ -99,7 +99,7 @@ static int32_t vgpio_mmio_handler(struct io_request *io_req, void *data)
|
||||
|
||||
/* all gpio registers have 4 bytes size */
|
||||
if (mmio->size == 4U) {
|
||||
if (mmio->direction == REQUEST_READ) {
|
||||
if (mmio->direction == ACRN_IOREQ_DIR_READ) {
|
||||
padbar = mmio_read32((const void *)hpa2hva((hpa & ~P2SB_PCR_SPACE_MASK) + GPIO_PADBAR));
|
||||
pad0 = padbar & P2SB_PCR_SPACE_MASK;
|
||||
value = mmio_read32((const void *)hva);
|
||||
|
@@ -556,7 +556,7 @@ get_vm_gsicount(const struct acrn_vm *vm)
|
||||
int32_t vioapic_mmio_access_handler(struct io_request *io_req, void *handler_private_data)
|
||||
{
|
||||
struct acrn_single_vioapic *vioapic = (struct acrn_single_vioapic *)handler_private_data;
|
||||
struct mmio_request *mmio = &io_req->reqs.mmio;
|
||||
struct acrn_mmio_request *mmio = &io_req->reqs.mmio_request;
|
||||
uint64_t gpa = mmio->address;
|
||||
int32_t ret = 0;
|
||||
|
||||
@@ -564,10 +564,10 @@ int32_t vioapic_mmio_access_handler(struct io_request *io_req, void *handler_pri
|
||||
if (mmio->size == 4UL) {
|
||||
uint32_t data = (uint32_t)mmio->value;
|
||||
|
||||
if (mmio->direction == REQUEST_READ) {
|
||||
if (mmio->direction == ACRN_IOREQ_DIR_READ) {
|
||||
vioapic_mmio_rw(vioapic, gpa, &data, true);
|
||||
mmio->value = (uint64_t)data;
|
||||
} else if (mmio->direction == REQUEST_WRITE) {
|
||||
} else if (mmio->direction == ACRN_IOREQ_DIR_WRITE) {
|
||||
vioapic_mmio_rw(vioapic, gpa, &data, false);
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
|
@@ -188,7 +188,7 @@ static void create_ivshmem_device(struct pci_vdev *vdev)
|
||||
static int32_t ivshmem_mmio_handler(struct io_request *io_req, void *data)
|
||||
{
|
||||
union ivshmem_doorbell doorbell;
|
||||
struct mmio_request *mmio = &io_req->reqs.mmio;
|
||||
struct acrn_mmio_request *mmio = &io_req->reqs.mmio_request;
|
||||
struct pci_vdev *vdev = (struct pci_vdev *) data;
|
||||
struct ivshmem_device *ivs_dev = (struct ivshmem_device *) vdev->priv_data;
|
||||
uint64_t offset = mmio->address - vdev->vbars[IVSHMEM_MMIO_BAR].base_gpa;
|
||||
@@ -200,7 +200,7 @@ static int32_t ivshmem_mmio_handler(struct io_request *io_req, void *data)
|
||||
* IVSHMEM_IV_POS_REG is Read-Only register and IVSHMEM_DOORBELL_REG
|
||||
* is Write-Only register, they are used for interrupt.
|
||||
*/
|
||||
if (mmio->direction == REQUEST_READ) {
|
||||
if (mmio->direction == ACRN_IOREQ_DIR_READ) {
|
||||
if (offset != IVSHMEM_DOORBELL_REG) {
|
||||
mmio->value = ivs_dev->mmio.data[offset >> 2U];
|
||||
} else {
|
||||
|
@@ -129,7 +129,7 @@ static void remap_one_vmsix_entry(const struct pci_vdev *vdev, uint32_t index)
|
||||
*/
|
||||
static int32_t pt_vmsix_handle_table_mmio_access(struct io_request *io_req, void *priv_data)
|
||||
{
|
||||
struct mmio_request *mmio = &io_req->reqs.mmio;
|
||||
struct acrn_mmio_request *mmio = &io_req->reqs.mmio_request;
|
||||
struct pci_vdev *vdev;
|
||||
uint32_t index;
|
||||
int32_t ret = 0;
|
||||
@@ -138,7 +138,7 @@ static int32_t pt_vmsix_handle_table_mmio_access(struct io_request *io_req, void
|
||||
if (vdev->user == vdev) {
|
||||
index = rw_vmsix_table(vdev, io_req);
|
||||
|
||||
if ((mmio->direction == REQUEST_WRITE) && (index < vdev->msix.table_count)) {
|
||||
if ((mmio->direction == ACRN_IOREQ_DIR_WRITE) && (index < vdev->msix.table_count)) {
|
||||
if (vdev->msix.is_vmsix_on_msi) {
|
||||
remap_one_vmsix_entry_on_msi(vdev, index);
|
||||
} else {
|
||||
|
@@ -43,7 +43,7 @@ static int32_t read_vmcs9900_cfg(const struct pci_vdev *vdev,
|
||||
|
||||
static int32_t vmcs9900_mmio_handler(struct io_request *io_req, void *data)
|
||||
{
|
||||
struct mmio_request *mmio = &io_req->reqs.mmio;
|
||||
struct acrn_mmio_request *mmio = &io_req->reqs.mmio_request;
|
||||
struct pci_vdev *vdev = (struct pci_vdev *)data;
|
||||
struct acrn_vuart *vu = vdev->priv_data;
|
||||
struct pci_vbar *vbar = &vdev->vbars[MCS9900_MMIO_BAR];
|
||||
@@ -51,7 +51,7 @@ static int32_t vmcs9900_mmio_handler(struct io_request *io_req, void *data)
|
||||
|
||||
offset = mmio->address - vbar->base_gpa;
|
||||
|
||||
if (mmio->direction == REQUEST_READ) {
|
||||
if (mmio->direction == ACRN_IOREQ_DIR_READ) {
|
||||
mmio->value = vuart_read_reg(vu, offset);
|
||||
} else {
|
||||
vuart_write_reg(vu, offset, (uint8_t) mmio->value);
|
||||
|
@@ -67,7 +67,7 @@ bool write_vmsix_cap_reg(struct pci_vdev *vdev, uint32_t offset, uint32_t bytes,
|
||||
*/
|
||||
uint32_t rw_vmsix_table(struct pci_vdev *vdev, struct io_request *io_req)
|
||||
{
|
||||
struct mmio_request *mmio = &io_req->reqs.mmio;
|
||||
struct acrn_mmio_request *mmio = &io_req->reqs.mmio_request;
|
||||
struct msix_table_entry *entry;
|
||||
uint32_t entry_offset, table_offset, index = CONFIG_MAX_MSIX_TABLE_NUM;
|
||||
uint64_t offset;
|
||||
@@ -83,14 +83,14 @@ uint32_t rw_vmsix_table(struct pci_vdev *vdev, struct io_request *io_req)
|
||||
entry = &vdev->msix.table_entries[index];
|
||||
entry_offset = table_offset % MSIX_TABLE_ENTRY_SIZE;
|
||||
|
||||
if (mmio->direction == REQUEST_READ) {
|
||||
if (mmio->direction == ACRN_IOREQ_DIR_READ) {
|
||||
(void)memcpy_s(&mmio->value, (size_t)mmio->size,
|
||||
(void *)entry + entry_offset, (size_t)mmio->size);
|
||||
} else {
|
||||
(void)memcpy_s((void *)entry + entry_offset, (size_t)mmio->size,
|
||||
&mmio->value, (size_t)mmio->size);
|
||||
}
|
||||
} else if (mmio->direction == REQUEST_READ) {
|
||||
} else if (mmio->direction == ACRN_IOREQ_DIR_READ) {
|
||||
mmio->value = 0UL;
|
||||
}
|
||||
} else {
|
||||
|
@@ -55,7 +55,7 @@ static bool vpci_pio_cfgaddr_read(struct acrn_vcpu *vcpu, uint16_t addr, size_t
|
||||
uint32_t val = ~0U;
|
||||
struct acrn_vpci *vpci = &vcpu->vm->vpci;
|
||||
union pci_cfg_addr_reg *cfg_addr = &vpci->addr;
|
||||
struct pio_request *pio_req = &vcpu->req.reqs.pio;
|
||||
struct acrn_pio_request *pio_req = &vcpu->req.reqs.pio_request;
|
||||
|
||||
if ((addr == (uint16_t)PCI_CONFIG_ADDR) && (bytes == 4U)) {
|
||||
val = cfg_addr->value;
|
||||
@@ -121,7 +121,7 @@ static bool vpci_pio_cfgdata_read(struct acrn_vcpu *vcpu, uint16_t addr, size_t
|
||||
union pci_bdf bdf;
|
||||
uint16_t offset = addr - PCI_CONFIG_DATA;
|
||||
uint32_t val = ~0U;
|
||||
struct pio_request *pio_req = &vcpu->req.reqs.pio;
|
||||
struct acrn_pio_request *pio_req = &vcpu->req.reqs.pio_request;
|
||||
|
||||
cfg_addr.value = atomic_readandclear32(&vpci->addr.value);
|
||||
if (cfg_addr.bits.enable != 0U) {
|
||||
@@ -174,7 +174,7 @@ static bool vpci_pio_cfgdata_write(struct acrn_vcpu *vcpu, uint16_t addr, size_t
|
||||
static int32_t vpci_mmio_cfg_access(struct io_request *io_req, void *private_data)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
struct mmio_request *mmio = &io_req->reqs.mmio;
|
||||
struct acrn_mmio_request *mmio = &io_req->reqs.mmio_request;
|
||||
struct acrn_vpci *vpci = (struct acrn_vpci *)private_data;
|
||||
uint64_t pci_mmcofg_base = vpci->pci_mmcfg.address;
|
||||
uint64_t address = mmio->address;
|
||||
@@ -192,7 +192,7 @@ static int32_t vpci_mmio_cfg_access(struct io_request *io_req, void *private_dat
|
||||
*/
|
||||
bdf.value = (uint16_t)((address - pci_mmcofg_base) >> 12U);
|
||||
|
||||
if (mmio->direction == REQUEST_READ) {
|
||||
if (mmio->direction == ACRN_IOREQ_DIR_READ) {
|
||||
ret = vpci_read_cfg(vpci, bdf, reg_num, (uint32_t)mmio->size, (uint32_t *)&mmio->value);
|
||||
} else {
|
||||
ret = vpci_write_cfg(vpci, bdf, reg_num, (uint32_t)mmio->size, (uint32_t)mmio->value);
|
||||
|
@@ -813,7 +813,7 @@ static int32_t vpic_primary_handler(struct acrn_vpic *vpic, bool in, uint16_t po
|
||||
*/
|
||||
static bool vpic_primary_io_read(struct acrn_vcpu *vcpu, uint16_t addr, size_t width)
|
||||
{
|
||||
struct pio_request *pio_req = &vcpu->req.reqs.pio;
|
||||
struct acrn_pio_request *pio_req = &vcpu->req.reqs.pio_request;
|
||||
|
||||
if (vpic_primary_handler(vm_pic(vcpu->vm), true, addr, width, &pio_req->value) < 0) {
|
||||
pr_err("Primary vPIC read port 0x%x width=%d failed\n",
|
||||
@@ -865,7 +865,7 @@ static int32_t vpic_secondary_handler(struct acrn_vpic *vpic, bool in, uint16_t
|
||||
*/
|
||||
static bool vpic_secondary_io_read(struct acrn_vcpu *vcpu, uint16_t addr, size_t width)
|
||||
{
|
||||
struct pio_request *pio_req = &vcpu->req.reqs.pio;
|
||||
struct acrn_pio_request *pio_req = &vcpu->req.reqs.pio_request;
|
||||
|
||||
if (vpic_secondary_handler(vm_pic(vcpu->vm), true, addr, width, &pio_req->value) < 0) {
|
||||
pr_err("Secondary vPIC read port 0x%x width=%d failed\n",
|
||||
@@ -943,7 +943,7 @@ static int32_t vpic_elc_handler(struct acrn_vpic *vpic, bool in, uint16_t port,
|
||||
*/
|
||||
static bool vpic_elc_io_read(struct acrn_vcpu *vcpu, uint16_t addr, size_t width)
|
||||
{
|
||||
struct pio_request *pio_req = &vcpu->req.reqs.pio;
|
||||
struct acrn_pio_request *pio_req = &vcpu->req.reqs.pio_request;
|
||||
|
||||
if (vpic_elc_handler(vm_pic(vcpu->vm), true, addr, width, &pio_req->value) < 0) {
|
||||
pr_err("pic elc read port 0x%x width=%d failed", addr, width);
|
||||
|
@@ -51,7 +51,7 @@ static uint8_t cmos_get_reg_val(uint8_t addr)
|
||||
static bool vrtc_read(struct acrn_vcpu *vcpu, uint16_t addr, __unused size_t width)
|
||||
{
|
||||
uint8_t offset;
|
||||
struct pio_request *pio_req = &vcpu->req.reqs.pio;
|
||||
struct acrn_pio_request *pio_req = &vcpu->req.reqs.pio_request;
|
||||
struct acrn_vm *vm = vcpu->vm;
|
||||
|
||||
offset = vm->vrtc_offset;
|
||||
|
@@ -537,7 +537,7 @@ static bool vuart_read(struct acrn_vcpu *vcpu, uint16_t offset_arg, __unused siz
|
||||
{
|
||||
uint16_t offset = offset_arg;
|
||||
struct acrn_vuart *vu = find_vuart_by_port(vcpu->vm, offset);
|
||||
struct pio_request *pio_req = &vcpu->req.reqs.pio;
|
||||
struct acrn_pio_request *pio_req = &vcpu->req.reqs.pio_request;
|
||||
|
||||
if (vu != NULL) {
|
||||
offset -= vu->port_base;
|
||||
|
@@ -52,7 +52,7 @@ int32_t ept_violation_vmexit_handler(struct acrn_vcpu *vcpu);
|
||||
* @pre io_req->io_type == REQ_PORTIO
|
||||
*
|
||||
* @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
|
||||
* either a previous call to emulate_io() returning 0 or the corresponding HSM
|
||||
* request having transferred to the COMPLETE state.
|
||||
*/
|
||||
void emulate_pio_complete(struct acrn_vcpu *vcpu, const struct io_request *io_req);
|
||||
@@ -82,10 +82,10 @@ void allow_guest_pio_access(struct acrn_vm *vm, uint16_t port_address, uint32_
|
||||
void deny_guest_pio_access(struct acrn_vm *vm, uint16_t port_address, uint32_t nbytes);
|
||||
|
||||
/**
|
||||
* @brief Fire VHM interrupt to SOS
|
||||
* @brief Fire HSM interrupt to SOS
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void arch_fire_vhm_interrupt(void);
|
||||
void arch_fire_hsm_interrupt(void);
|
||||
|
||||
#endif /* IO_EMUL_H */
|
||||
|
@@ -40,7 +40,7 @@
|
||||
*/
|
||||
#define NR_STATIC_MAPPINGS (NR_STATIC_MAPPINGS_1 + CONFIG_MAX_VM_NUM)
|
||||
|
||||
#define HYPERVISOR_CALLBACK_VHM_VECTOR 0xF3U
|
||||
#define HYPERVISOR_CALLBACK_HSM_VECTOR 0xF3U
|
||||
|
||||
/* vectors range for dynamic allocation, usually for devices */
|
||||
#define VECTOR_DYNAMIC_START 0x20U
|
||||
|
@@ -210,8 +210,7 @@ int32_t hcall_inject_msi(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint
|
||||
* @param vcpu Pointer to vCPU that initiates the hypercall
|
||||
* @param target_vm Pointer to target VM data structure
|
||||
* @param param1 not used
|
||||
* @param param2 guest physical address. This gpa points to
|
||||
* struct acrn_set_ioreq_buffer
|
||||
* @param param2 guest physical address. This gpa points to buffer address
|
||||
*
|
||||
* @pre is_sos_vm(vcpu->vm)
|
||||
* @return 0 on success, non-zero on error.
|
||||
|
@@ -25,14 +25,19 @@ struct io_request {
|
||||
/**
|
||||
* @brief Type of the request (PIO, MMIO, etc).
|
||||
*
|
||||
* Refer to vhm_request for detailed description of I/O request types.
|
||||
* Refer to acrn_io_request for detailed description of I/O request types.
|
||||
*/
|
||||
uint32_t io_type;
|
||||
|
||||
/**
|
||||
* @brief Details of this request in the same format as vhm_request.
|
||||
* @brief Details of this request in the same format as acrn_io_request.
|
||||
*/
|
||||
union vhm_io_request reqs;
|
||||
union {
|
||||
struct acrn_pio_request pio_request;
|
||||
struct acrn_pci_request pci_request;
|
||||
struct acrn_mmio_request mmio_request;
|
||||
uint64_t data[8];
|
||||
} reqs;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -105,7 +110,6 @@ struct vm_io_handler_desc {
|
||||
};
|
||||
|
||||
/* Typedef for MMIO handler and range check routine */
|
||||
struct mmio_request;
|
||||
typedef int32_t (*hv_mem_io_handler_t)(struct io_request *io_req, void *handler_private_data);
|
||||
|
||||
/**
|
||||
@@ -187,45 +191,45 @@ int32_t acrn_insert_request(struct acrn_vcpu *vcpu, const struct io_request *io_
|
||||
void reset_vm_ioreqs(struct acrn_vm *vm);
|
||||
|
||||
/**
|
||||
* @brief Get the state of VHM request
|
||||
* @brief Get the state of an IO request
|
||||
*
|
||||
* @param vm Target VM context
|
||||
* @param vhm_req_id VHM Request ID
|
||||
* @param vcpu_id VCPU ID of the IO request
|
||||
*
|
||||
* @return State of the IO Request.
|
||||
*/
|
||||
uint32_t get_vhm_req_state(struct acrn_vm *vm, uint16_t vhm_req_id);
|
||||
uint32_t get_io_req_state(struct acrn_vm *vm, uint16_t vcpu_id);
|
||||
|
||||
/**
|
||||
* @brief Set the state of VHM request
|
||||
* @brief Set the state of IO request
|
||||
*
|
||||
* @param vm Target VM context
|
||||
* @param vhm_req_id VHM Request ID
|
||||
* @param state State to be set
|
||||
* @param vcpu_id VCPU ID of the IO request
|
||||
* @param state State to be set
|
||||
* @return None
|
||||
*/
|
||||
void set_vhm_req_state(struct acrn_vm *vm, uint16_t vhm_req_id, uint32_t state);
|
||||
void set_io_req_state(struct acrn_vm *vm, uint16_t vcpu_id, uint32_t state);
|
||||
|
||||
/**
|
||||
* @brief Set the vector for HV callback VHM
|
||||
* @brief Set the vector for HV callback HSM
|
||||
*
|
||||
* @param vector vector for HV callback VHM
|
||||
* @param vector vector for HV callback HSM
|
||||
* @return None
|
||||
*/
|
||||
void set_vhm_notification_vector(uint32_t vector);
|
||||
void set_hsm_notification_vector(uint32_t vector);
|
||||
|
||||
/**
|
||||
* @brief Get the vector for HV callback VHM
|
||||
* @brief Get the vector for HV callback HSM
|
||||
*
|
||||
* @return vector for HV callbakc VH
|
||||
* @return vector for HV callbakc HSM
|
||||
*/
|
||||
uint32_t get_vhm_notification_vector(void);
|
||||
uint32_t get_hsm_notification_vector(void);
|
||||
|
||||
/**
|
||||
* @brief Emulate \p io_req for \p vcpu
|
||||
*
|
||||
* Handle an I/O request by either invoking a hypervisor-internal handler or
|
||||
* deliver to VHM.
|
||||
* deliver to HSM.
|
||||
*
|
||||
* @pre vcpu != NULL
|
||||
* @pre vcpu->vm != NULL
|
||||
@@ -235,7 +239,7 @@ uint32_t get_vhm_notification_vector(void);
|
||||
* @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 IOREQ_PENDING The I/O request is delivered to HSM.
|
||||
* @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.
|
||||
|
@@ -18,26 +18,29 @@
|
||||
#include <types.h>
|
||||
|
||||
/*
|
||||
* Common structures for ACRN/VHM/DM
|
||||
* Common structures for ACRN/HSM/DM
|
||||
*/
|
||||
|
||||
/*
|
||||
* IO request
|
||||
*/
|
||||
#define VHM_REQUEST_MAX 16U
|
||||
|
||||
#define REQ_STATE_FREE 3U
|
||||
#define REQ_STATE_PENDING 0U
|
||||
#define REQ_STATE_COMPLETE 1U
|
||||
#define REQ_STATE_PROCESSING 2U
|
||||
#define ACRN_IO_REQUEST_MAX 16U
|
||||
|
||||
#define ACRN_IOREQ_STATE_PENDING 0U
|
||||
#define ACRN_IOREQ_STATE_COMPLETE 1U
|
||||
#define ACRN_IOREQ_STATE_PROCESSING 2U
|
||||
#define ACRN_IOREQ_STATE_FREE 3U
|
||||
|
||||
#define ACRN_IOREQ_TYPE_PORTIO 0U
|
||||
#define ACRN_IOREQ_TYPE_MMIO 1U
|
||||
#define ACRN_IOREQ_TYPE_PCICFG 2U
|
||||
#define ACRN_IOREQ_TYPE_WP 3U
|
||||
|
||||
#define ACRN_IOREQ_DIR_READ 0U
|
||||
#define ACRN_IOREQ_DIR_WRITE 1U
|
||||
|
||||
#define REQ_PORTIO 0U
|
||||
#define REQ_MMIO 1U
|
||||
#define REQ_PCICFG 2U
|
||||
#define REQ_WP 3U
|
||||
|
||||
#define REQUEST_READ 0U
|
||||
#define REQUEST_WRITE 1U
|
||||
|
||||
/* IOAPIC device model info */
|
||||
#define VIOAPIC_RTE_NUM 48U /* vioapic pins */
|
||||
@@ -72,11 +75,11 @@
|
||||
/**
|
||||
* @brief Representation of a MMIO request
|
||||
*/
|
||||
struct mmio_request {
|
||||
struct acrn_mmio_request {
|
||||
/**
|
||||
* @brief Direction of the access
|
||||
*
|
||||
* Either \p REQUEST_READ or \p REQUEST_WRITE.
|
||||
* Either \p ACRN_IOREQ_DIR_READ or \p ACRN_IOREQ_DIR_WRITE.
|
||||
*/
|
||||
uint32_t direction;
|
||||
|
||||
@@ -104,11 +107,11 @@ struct mmio_request {
|
||||
/**
|
||||
* @brief Representation of a port I/O request
|
||||
*/
|
||||
struct pio_request {
|
||||
struct acrn_pio_request {
|
||||
/**
|
||||
* @brief Direction of the access
|
||||
*
|
||||
* Either \p REQUEST_READ or \p REQUEST_WRITE.
|
||||
* Either \p ACRN_IOREQ_DIR_READ or \p ACRN_IOREQ_DIR_WRITE.
|
||||
*/
|
||||
uint32_t direction;
|
||||
|
||||
@@ -136,11 +139,11 @@ struct pio_request {
|
||||
/**
|
||||
* @brief Representation of a PCI configuration space access
|
||||
*/
|
||||
struct pci_request {
|
||||
struct acrn_pci_request {
|
||||
/**
|
||||
* @brief Direction of the access
|
||||
*
|
||||
* Either \p REQUEST_READ or \p REQUEST_WRITE.
|
||||
* Either \p ACRN_IOREQ_DIR_READ or \p ACRN_IOREQ_DIR_WRITE.
|
||||
*/
|
||||
uint32_t direction;
|
||||
|
||||
@@ -180,28 +183,21 @@ struct pci_request {
|
||||
int32_t reg;
|
||||
} __aligned(8);
|
||||
|
||||
union vhm_io_request {
|
||||
struct pio_request pio;
|
||||
struct pci_request pci;
|
||||
struct mmio_request mmio;
|
||||
int64_t reserved1[8];
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 256-byte VHM requests
|
||||
* @brief 256-byte I/O requests
|
||||
*
|
||||
* The state transitions of a VHM request are:
|
||||
* The state transitions of a I/O request are:
|
||||
*
|
||||
* FREE -> PENDING -> PROCESSING -> COMPLETE -> FREE -> ...
|
||||
*
|
||||
* When a request is in COMPLETE or FREE state, the request is owned by the
|
||||
* hypervisor. SOS (VHM or DM) shall not read or write the internals of the
|
||||
* hypervisor. SOS (HSM or DM) shall not read or write the internals of the
|
||||
* request except the state.
|
||||
*
|
||||
* When a request is in PENDING or PROCESSING state, the request is owned by
|
||||
* SOS. The hypervisor shall not read or write the request other than the state.
|
||||
*
|
||||
* Based on the rules above, a typical VHM request lifecycle should looks like
|
||||
* Based on the rules above, a typical I/O request lifecycle should looks like
|
||||
* the following.
|
||||
*
|
||||
* @verbatim embed:rst:leading-asterisk
|
||||
@@ -270,9 +266,9 @@ union vhm_io_request {
|
||||
* the hypervisor, as the hypervisor shall not access the request any more.
|
||||
*
|
||||
* 2. Due to similar reasons, setting state to COMPLETE is the last operation
|
||||
* of request handling in VHM or clients in SOS.
|
||||
* of request handling in HSM or clients in SOS.
|
||||
*/
|
||||
struct vhm_request {
|
||||
struct acrn_io_request {
|
||||
/**
|
||||
* @brief Type of this request.
|
||||
*
|
||||
@@ -297,13 +293,14 @@ struct vhm_request {
|
||||
/**
|
||||
* @brief Details about this request.
|
||||
*
|
||||
* For REQ_PORTIO, this has type
|
||||
* pio_request. For REQ_MMIO and REQ_WP, this has type mmio_request. For
|
||||
* REQ_PCICFG, this has type pci_request.
|
||||
*
|
||||
* Byte offset: 64.
|
||||
*/
|
||||
union vhm_io_request reqs;
|
||||
union {
|
||||
struct acrn_pio_request pio_request;
|
||||
struct acrn_pci_request pci_request;
|
||||
struct acrn_mmio_request mmio_request;
|
||||
uint64_t data[8];
|
||||
} reqs;
|
||||
|
||||
/**
|
||||
* @brief Reserved.
|
||||
@@ -313,27 +310,27 @@ struct vhm_request {
|
||||
uint32_t reserved1;
|
||||
|
||||
/**
|
||||
* @brief The client which is distributed to handle this request.
|
||||
*
|
||||
* Accessed by VHM only.
|
||||
* @brief If this request has been handled by HSM driver.
|
||||
*
|
||||
* Byte offset: 132.
|
||||
*/
|
||||
int32_t client;
|
||||
int32_t kernel_handled;
|
||||
|
||||
/**
|
||||
* @brief The status of this request.
|
||||
*
|
||||
* Taking REQ_STATE_xxx as values.
|
||||
* Taking ACRN_IOREQ_STATE_xxx as values.
|
||||
*
|
||||
* Byte offset: 136.
|
||||
*/
|
||||
uint32_t processed;
|
||||
} __aligned(256);
|
||||
|
||||
union vhm_request_buffer {
|
||||
struct vhm_request req_queue[VHM_REQUEST_MAX];
|
||||
int8_t reserved[4096];
|
||||
struct acrn_io_request_buffer {
|
||||
union {
|
||||
struct acrn_io_request req_slot[ACRN_IO_REQUEST_MAX];
|
||||
int8_t reserved[4096];
|
||||
};
|
||||
} __aligned(4096);
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user