From 99189b4e48f34bffc0379008cc2eae1762cfc81a Mon Sep 17 00:00:00 2001 From: Victor Sun Date: Thu, 17 May 2018 16:47:54 +0800 Subject: [PATCH] HV: cleanup for io request related functions Changes: 1. Move io request related functions from hypercall.c to io_request.c since they are not hypercalls; 2. Remove acrn_insert_request_nowait() as it is never used; Signed-off-by: Victor Sun Acked-by: Eddie Dong --- hypervisor/Makefile | 1 + hypervisor/common/hypercall.c | 203 ---------------------- hypervisor/common/io_request.c | 194 +++++++++++++++++++++ hypervisor/include/arch/x86/guest/guest.h | 3 + hypervisor/include/common/hypercall.h | 3 - 5 files changed, 198 insertions(+), 206 deletions(-) create mode 100644 hypervisor/common/io_request.c diff --git a/hypervisor/Makefile b/hypervisor/Makefile index 8cddf4cfe..b82d06155 100644 --- a/hypervisor/Makefile +++ b/hypervisor/Makefile @@ -130,6 +130,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 ifdef STACK_PROTECTOR C_SRCS += common/stack_protector.c diff --git a/hypervisor/common/hypercall.c b/hypervisor/common/hypercall.c index a019faf07..184f1b0c4 100644 --- a/hypervisor/common/hypercall.c +++ b/hypervisor/common/hypercall.c @@ -819,206 +819,3 @@ int64_t hcall_get_cpu_pm_state(struct vm *vm, uint64_t cmd, uint64_t param) } } - -static void fire_vhm_interrupt(void) -{ - /* - * use vLAPIC to inject vector to SOS vcpu 0 if vlapic is enabled - * otherwise, send IPI hardcoded to CPU_BOOT_ID - */ - struct vm *vm0; - struct vcpu *vcpu; - - vm0 = get_vm_from_vmid(0); - ASSERT(vm0, "VM Pointer is NULL"); - - vcpu = vcpu_from_vid(vm0, 0); - ASSERT(vcpu, "vcpu_from_vid failed"); - - vlapic_intr_edge(vcpu, VECTOR_VIRT_IRQ_VHM); -} - -static void acrn_print_request(int vcpu_id, struct vhm_request *req) -{ - switch (req->type) { - case REQ_MMIO: - dev_dbg(ACRN_DBG_HYCALL, "[vcpu_id=%d type=MMIO]", vcpu_id); - dev_dbg(ACRN_DBG_HYCALL, - "gpa=0x%lx, R/W=%d, size=%ld value=0x%lx processed=%lx", - 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: - dev_dbg(ACRN_DBG_HYCALL, "[vcpu_id=%d type=PORTIO]", vcpu_id); - dev_dbg(ACRN_DBG_HYCALL, - "IO=0x%lx, R/W=%d, size=%ld value=0x%lx processed=%lx", - req->reqs.pio_request.address, - req->reqs.pio_request.direction, - req->reqs.pio_request.size, - req->reqs.pio_request.value, - req->processed); - break; - default: - dev_dbg(ACRN_DBG_HYCALL, "[vcpu_id=%d type=%d] NOT support type", - vcpu_id, req->type); - break; - } -} - -int acrn_insert_request_wait(struct vcpu *vcpu, struct vhm_request *req) -{ - struct vhm_request_buffer *req_buf = NULL; - long cur; - - ASSERT(sizeof(*req) == (4096/VHM_REQUEST_MAX), - "vhm_request page broken!"); - - - if (!vcpu || !req || vcpu->vm->sw.io_shared_page == NULL) - return -EINVAL; - - req_buf = (struct vhm_request_buffer *)(vcpu->vm->sw.io_shared_page); - - /* ACRN insert request to VHM and inject upcall */ - cur = vcpu->vcpu_id; - memcpy_s(&req_buf->req_queue[cur], sizeof(struct vhm_request), - req, sizeof(struct vhm_request)); - - /* Must clear the signal before we mark req valid - * Once we mark to valid, VHM may process req and signal us - * before we perform upcall. - * because VHM can work in pulling mode without wait for upcall - */ - req_buf->req_queue[cur].valid = true; - - acrn_print_request(vcpu->vcpu_id, req_buf->req_queue + cur); - - /* signal VHM */ - fire_vhm_interrupt(); - - /* pause vcpu, wait for VHM to handle the MMIO request */ - atomic_store(&vcpu->ioreq_pending, 1); - pause_vcpu(vcpu, VCPU_PAUSED); - - return 0; -} - -int acrn_insert_request_nowait(struct vcpu *vcpu, struct vhm_request *req) -{ - struct vhm_request_buffer *req_buf; - long cur; - - if (!vcpu || !req || !vcpu->vm->sw.io_shared_page) - return -EINVAL; - - req_buf = (struct vhm_request_buffer *)(vcpu->vm->sw.io_shared_page); - - /* ACRN insert request to VHM and inject upcall */ - cur = vcpu->vcpu_id; - req_buf->req_queue[cur] = *req; - req_buf->req_queue[cur].valid = true; - - /* signal VHM and yield CPU */ - fire_vhm_interrupt(); - - return 0; -} - -static void _get_req_info_(struct vhm_request *req, int *id, char *type, - char *state, char *dir, long *addr, long *val) -{ - strcpy_s(dir, 16, "NONE"); - *addr = *val = 0; - *id = req->client; - - switch (req->type) { - case REQ_PORTIO: - strcpy_s(type, 16, "PORTIO"); - if (req->reqs.pio_request.direction == REQUEST_READ) - strcpy_s(dir, 16, "READ"); - else - strcpy_s(dir, 16, "WRITE"); - *addr = req->reqs.pio_request.address; - *val = req->reqs.pio_request.value; - break; - case REQ_MMIO: - case REQ_WP: - strcpy_s(type, 16, "MMIO/WP"); - if (req->reqs.mmio_request.direction == REQUEST_READ) - strcpy_s(dir, 16, "READ"); - else - strcpy_s(dir, 16, "WRITE"); - *addr = req->reqs.mmio_request.address; - *val = req->reqs.mmio_request.value; - break; - break; - default: - strcpy_s(type, 16, "UNKNOWN"); - } - - switch (req->processed) { - case REQ_STATE_SUCCESS: - strcpy_s(state, 16, "SUCCESS"); - break; - case REQ_STATE_PENDING: - strcpy_s(state, 16, "PENDING"); - break; - case REQ_STATE_PROCESSING: - strcpy_s(state, 16, "PROCESS"); - break; - case REQ_STATE_FAILED: - strcpy_s(state, 16, "FAILED"); - break; - default: - strcpy_s(state, 16, "UNKNOWN"); - } -} - -int get_req_info(char *str, int str_max) -{ - int i, len, size = str_max, client_id; - struct vhm_request_buffer *req_buf; - struct vhm_request *req; - char type[16], state[16], dir[16]; - long addr, val; - struct list_head *pos; - struct vm *vm; - - len = snprintf(str, size, - "\r\nVM\tVCPU\tCID\tTYPE\tSTATE\tDIR\tADDR\t\t\tVAL"); - size -= len; - str += len; - - spinlock_obtain(&vm_list_lock); - list_for_each(pos, &vm_list) { - vm = list_entry(pos, struct vm, list); - req_buf = (struct vhm_request_buffer *)vm->sw.io_shared_page; - if (req_buf) { - for (i = 0; i < VHM_REQUEST_MAX; i++) { - req = req_buf->req_queue + i; - if (req->valid) { - _get_req_info_(req, &client_id, type, - state, dir, &addr, &val); - len = snprintf(str, size, - "\r\n%d\t%d\t%d\t%s\t%s\t%s", - vm->attr.id, i, client_id, type, - state, dir); - size -= len; - str += len; - - len = snprintf(str, size, - "\t0x%016llx\t0x%016llx", - addr, val); - size -= len; - str += len; - } - } - } - } - spinlock_release(&vm_list_lock); - snprintf(str, size, "\r\n"); - return 0; -} diff --git a/hypervisor/common/io_request.c b/hypervisor/common/io_request.c new file mode 100644 index 000000000..17e114b11 --- /dev/null +++ b/hypervisor/common/io_request.c @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2018 Intel Corporation. + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#define ACRN_DBG_IOREQUEST 6 + +static void fire_vhm_interrupt(void) +{ + /* + * use vLAPIC to inject vector to SOS vcpu 0 if vlapic is enabled + * otherwise, send IPI hardcoded to CPU_BOOT_ID + */ + struct vm *vm0; + struct vcpu *vcpu; + + vm0 = get_vm_from_vmid(0); + ASSERT(vm0, "VM Pointer is NULL"); + + vcpu = vcpu_from_vid(vm0, 0); + ASSERT(vcpu, "vcpu_from_vid failed"); + + vlapic_intr_edge(vcpu, VECTOR_VIRT_IRQ_VHM); +} + +static void acrn_print_request(int vcpu_id, struct vhm_request *req) +{ + switch (req->type) { + case REQ_MMIO: + dev_dbg(ACRN_DBG_IOREQUEST, "[vcpu_id=%d type=MMIO]", vcpu_id); + dev_dbg(ACRN_DBG_IOREQUEST, + "gpa=0x%lx, R/W=%d, size=%ld value=0x%lx processed=%lx", + 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: + dev_dbg(ACRN_DBG_IOREQUEST, "[vcpu_id=%d type=PORTIO]", vcpu_id); + dev_dbg(ACRN_DBG_IOREQUEST, + "IO=0x%lx, R/W=%d, size=%ld value=0x%lx processed=%lx", + req->reqs.pio_request.address, + req->reqs.pio_request.direction, + req->reqs.pio_request.size, + req->reqs.pio_request.value, + req->processed); + break; + default: + dev_dbg(ACRN_DBG_IOREQUEST, "[vcpu_id=%d type=%d] NOT support type", + vcpu_id, req->type); + break; + } +} + +int acrn_insert_request_wait(struct vcpu *vcpu, struct vhm_request *req) +{ + struct vhm_request_buffer *req_buf = NULL; + long cur; + + ASSERT(sizeof(*req) == (4096/VHM_REQUEST_MAX), + "vhm_request page broken!"); + + + if (!vcpu || !req || vcpu->vm->sw.io_shared_page == NULL) + return -EINVAL; + + req_buf = (struct vhm_request_buffer *)(vcpu->vm->sw.io_shared_page); + + /* ACRN insert request to VHM and inject upcall */ + cur = vcpu->vcpu_id; + memcpy_s(&req_buf->req_queue[cur], sizeof(struct vhm_request), + req, sizeof(struct vhm_request)); + + /* Must clear the signal before we mark req valid + * Once we mark to valid, VHM may process req and signal us + * before we perform upcall. + * because VHM can work in pulling mode without wait for upcall + */ + req_buf->req_queue[cur].valid = true; + + acrn_print_request(vcpu->vcpu_id, req_buf->req_queue + cur); + + /* signal VHM */ + fire_vhm_interrupt(); + + /* pause vcpu, wait for VHM to handle the MMIO request */ + atomic_store(&vcpu->ioreq_pending, 1); + pause_vcpu(vcpu, VCPU_PAUSED); + + return 0; +} + +static void _get_req_info_(struct vhm_request *req, int *id, char *type, + char *state, char *dir, long *addr, long *val) +{ + strcpy_s(dir, 16, "NONE"); + *addr = *val = 0; + *id = req->client; + + switch (req->type) { + case REQ_PORTIO: + strcpy_s(type, 16, "PORTIO"); + if (req->reqs.pio_request.direction == REQUEST_READ) + strcpy_s(dir, 16, "READ"); + else + strcpy_s(dir, 16, "WRITE"); + *addr = req->reqs.pio_request.address; + *val = req->reqs.pio_request.value; + break; + case REQ_MMIO: + case REQ_WP: + strcpy_s(type, 16, "MMIO/WP"); + if (req->reqs.mmio_request.direction == REQUEST_READ) + strcpy_s(dir, 16, "READ"); + else + strcpy_s(dir, 16, "WRITE"); + *addr = req->reqs.mmio_request.address; + *val = req->reqs.mmio_request.value; + break; + break; + default: + strcpy_s(type, 16, "UNKNOWN"); + } + + switch (req->processed) { + case REQ_STATE_SUCCESS: + strcpy_s(state, 16, "SUCCESS"); + break; + case REQ_STATE_PENDING: + strcpy_s(state, 16, "PENDING"); + break; + case REQ_STATE_PROCESSING: + strcpy_s(state, 16, "PROCESS"); + break; + case REQ_STATE_FAILED: + strcpy_s(state, 16, "FAILED"); + break; + default: + strcpy_s(state, 16, "UNKNOWN"); + } +} + +int get_req_info(char *str, int str_max) +{ + int i, len, size = str_max, client_id; + struct vhm_request_buffer *req_buf; + struct vhm_request *req; + char type[16], state[16], dir[16]; + long addr, val; + struct list_head *pos; + struct vm *vm; + + len = snprintf(str, size, + "\r\nVM\tVCPU\tCID\tTYPE\tSTATE\tDIR\tADDR\t\t\tVAL"); + size -= len; + str += len; + + spinlock_obtain(&vm_list_lock); + list_for_each(pos, &vm_list) { + vm = list_entry(pos, struct vm, list); + req_buf = (struct vhm_request_buffer *)vm->sw.io_shared_page; + if (req_buf) { + for (i = 0; i < VHM_REQUEST_MAX; i++) { + req = req_buf->req_queue + i; + if (req->valid) { + _get_req_info_(req, &client_id, type, + state, dir, &addr, &val); + len = snprintf(str, size, + "\r\n%d\t%d\t%d\t%s\t%s\t%s", + vm->attr.id, i, client_id, type, + state, dir); + size -= len; + str += len; + + len = snprintf(str, size, + "\t0x%016llx\t0x%016llx", + addr, val); + size -= len; + str += len; + } + } + } + } + spinlock_release(&vm_list_lock); + snprintf(str, size, "\r\n"); + return 0; +} diff --git a/hypervisor/include/arch/x86/guest/guest.h b/hypervisor/include/arch/x86/guest/guest.h index f9e6fb944..ca65c9119 100644 --- a/hypervisor/include/arch/x86/guest/guest.h +++ b/hypervisor/include/arch/x86/guest/guest.h @@ -58,6 +58,9 @@ enum { struct vhm_request; +int acrn_insert_request_wait(struct vcpu *vcpu, struct vhm_request *req); +int get_req_info(char *str, int str_max); + /* * VCPU related APIs */ diff --git a/hypervisor/include/common/hypercall.h b/hypervisor/include/common/hypercall.h index 66604ab52..da40a6d2c 100644 --- a/hypervisor/include/common/hypercall.h +++ b/hypervisor/include/common/hypercall.h @@ -40,9 +40,6 @@ struct vhm_request; bool is_hypercall_from_ring0(void); -int acrn_insert_request_wait(struct vcpu *vcpu, struct vhm_request *req); -int acrn_insert_request_nowait(struct vcpu *vcpu, struct vhm_request *req); -int get_req_info(char *str, int str_max); int acrn_vpic_inject_irq(struct vm *vm, int irq, enum irq_mode mode);