Re: [PATCH] HV: hv_main: Add #ifdef HV_DEBUG before debug specific code
#ifdef
Ok then. The sbuf has a hypercall, we need compile option to cover all sbuf code...BTW, hcall side also needs this kind of compile option.I can't follow here. Can you make it more clear.
|
|
Re: [PATCH] HV: handle trusty on vm reset
LGTM, with one issue to fix.
toggle quoted messageShow quoted text
-----Original Message-----
|
|
[PATCH v3 1/1] vbs: fix virtio_vq_index_get func handling of multi VQ concurrent request.
Ong Hock Yu <ong.hock.yu@...>
Under multiple VQ use case, it is possible to have concurrent requests.
Added support to return multiple vq index from all vcpu. Signed-off-by: Ong Hock Yu <ong.hock.yu@...> --- drivers/vbs/vbs.c | 14 ++++++++------ drivers/vbs/vbs_rng.c | 2 +- include/linux/vbs/vbs.h | 8 ++++++-- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/vbs/vbs.c b/drivers/vbs/vbs.c index 65b8a0bbe3d3..a2f263cb91c0 100644 --- a/drivers/vbs/vbs.c +++ b/drivers/vbs/vbs.c @@ -148,9 +148,11 @@ long virtio_dev_deregister(struct virtio_dev_info *dev) return 0; } -int virtio_vq_index_get(struct virtio_dev_info *dev, unsigned long *ioreqs_map) +int virtio_vqs_index_get(struct virtio_dev_info *dev, + unsigned long *ioreqs_map, + int *vqs_index, int max_vqs_index) { - int val = -1; + int idx = 0; struct vhm_request *req; int vcpu; @@ -159,7 +161,7 @@ int virtio_vq_index_get(struct virtio_dev_info *dev, unsigned long *ioreqs_map) return -EINVAL; } - while (1) { + while (idx < max_vqs_index) { vcpu = find_first_bit(ioreqs_map, dev->_ctx.max_vcpu); if (vcpu == dev->_ctx.max_vcpu) break; @@ -179,9 +181,9 @@ int virtio_vq_index_get(struct virtio_dev_info *dev, unsigned long *ioreqs_map) pr_debug("%s: write request! type %d\n", __func__, req->type); if (dev->io_range_type == PIO_RANGE) - val = req->reqs.pio_request.value; + vqs_index[idx++] = req->reqs.pio_request.value; else - val = req->reqs.mmio_request.value; + vqs_index[idx++] = req->reqs.mmio_request.value; } smp_mb(); atomic_set(&req->processed, REQ_STATE_COMPLETE); @@ -189,7 +191,7 @@ int virtio_vq_index_get(struct virtio_dev_info *dev, unsigned long *ioreqs_map) } } - return val; + return idx; } static long virtio_vqs_info_set(struct virtio_dev_info *dev, diff --git a/drivers/vbs/vbs_rng.c b/drivers/vbs/vbs_rng.c index fd2bb27af66e..c5e28cc12c55 100644 --- a/drivers/vbs/vbs_rng.c +++ b/drivers/vbs/vbs_rng.c @@ -268,7 +268,7 @@ static int handle_kick(int client_id, unsigned long *ioreqs_map) return -EINVAL; } - val = virtio_vq_index_get(&rng->dev, ioreqs_map); + virtio_vqs_index_get(&rng->dev, ioreqs_map, &val, 1); if (val >= 0) handle_vq_kick(rng, val); diff --git a/include/linux/vbs/vbs.h b/include/linux/vbs/vbs.h index 30df8ebf68a0..964bacac865c 100644 --- a/include/linux/vbs/vbs.h +++ b/include/linux/vbs/vbs.h @@ -262,7 +262,7 @@ long virtio_dev_register(struct virtio_dev_info *dev); long virtio_dev_deregister(struct virtio_dev_info *dev); /** - * virtio_vq_index_get - get virtqueue index that frontend kicks + * virtio_vqs_index_get - get virtqueue indexes that frontend kicks * * This API is normally called in the VBS-K device's callback * function, to get value write to the "kick" register from @@ -270,10 +270,14 @@ long virtio_dev_deregister(struct virtio_dev_info *dev); * * @dev: Pointer to VBS-K device data struct * @ioreqs_map: requests bitmap need to handle, provided by VHM + * @vqs_index: array to store the vq indexes + * @max_vqs_index: size of vqs_index array * * Return: >=0 on virtqueue index, <0 on error */ -int virtio_vq_index_get(struct virtio_dev_info *dev, unsigned long *ioreqs_map); +int virtio_vqs_index_get(struct virtio_dev_info *dev, + unsigned long *ioreqs_map, + int *vqs_index, int max_vqs_index); /** * virtio_dev_reset - reset a VBS-K device -- 2.17.0
|
|
[PATCH] tools: acrntrace: Add ring buffer mode
Zhipeng Gong <zhipeng.gong@...>
When running longevity test and capture acrntrace, generated acrntrace
files sizes are too big. Sometimes we don't care very old trace. This patch adds ring buffer mode, fixes acrntrace file size and overwrites old trace with new trace. Signed-off-by: Zhipeng Gong <zhipeng.gong@...> --- tools/acrntrace/acrntrace.c | 44 +++++++++++++++++++++++++++++++++++++++++--- tools/acrntrace/acrntrace.h | 1 + 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/tools/acrntrace/acrntrace.c b/tools/acrntrace/acrntrace.c index 39fda35..371ffaa 100644 --- a/tools/acrntrace/acrntrace.c +++ b/tools/acrntrace/acrntrace.c @@ -37,16 +37,19 @@ static char trace_file_dir[TRACE_FILE_DIR_LEN]; static reader_struct *reader; static int pcpu_num = 0; +static int ring_buffer_size = 0; static void display_usage(void) { printf("acrntrace - tool to collect ACRN trace data\n" - "[Usage] acrntrace [-i] [period in msec] [-ch]\n\n" + "[Usage] acrntrace [-i] [period in msec] [-r] [ring buffer size] [-ch]\n\n" "[Options]\n" "\t-h: print this message\n" "\t-i: period_in_ms: specify polling interval [1-999]\n" "\t-t: max time to capture trace data (in second)\n" - "\t-c: clear the buffered old data\n"); + "\t-c: clear the buffered old data\n" + "\t-r: ring_buffer_size (in MB): enable ring buffer mode," + " where new trace overwrites old trace when full\n"); } static void timer_handler(union sigval sv) @@ -113,6 +116,15 @@ static int parse_opt(int argc, char *argv[]) timeout = ret; pr_dbg("Capture trace data for at most %ds\n", ret); break; + case 'r': + ret = atoi(optarg); + if (ret <= 0) { + pr_err("'-r' require integer greater than 0\n"); + return -EINVAL; + } + ring_buffer_size = ret * 1024 * 1024; + pr_dbg("Ring buffer size is %dM\n", ret); + break; case 'c': flags |= FLAG_CLEAR_BUF; break; @@ -206,6 +218,15 @@ static void reader_fn(param_t * param) trace_ev_t e; struct statvfs stat; uint64_t freespace; + int pos = 0; + + if (ring_buffer_size != 0) { + param->buffer = malloc(ring_buffer_size); + if (!param->buffer) { + perror("Failed to allocate ring buffer\n"); + return; + } + } pr_dbg("reader thread[%lu] created for FILE*[0x%p]\n", pthread_self(), fp); @@ -219,7 +240,13 @@ static void reader_fn(param_t * param) while (1) { do { - ret = sbuf_write(fd, sbuf); + if (ring_buffer_size != 0) { + ret = sbuf_get(sbuf, param->buffer + pos); + pos += sbuf->ele_size; + if (pos + sbuf->ele_size > ring_buffer_size) + pos = 0; + } else + ret = sbuf_write(fd, sbuf); } while (ret > 0); usleep(period); @@ -284,6 +311,17 @@ static void destory_reader(reader_struct * reader) reader->thrd = 0; } + if (ring_buffer_size != 0 && reader->param.buffer) { + int ret; + + ret = write(reader->param.trace_fd, reader->param.buffer, + ring_buffer_size); + if (ret != ring_buffer_size) { + perror("Failed to write ring buffer\n"); + } + free(reader->param.buffer); + } + if (reader->param.sbuf) { munmap(reader->param.sbuf, MMAP_SIZE); reader->param.sbuf = NULL; diff --git a/tools/acrntrace/acrntrace.h b/tools/acrntrace/acrntrace.h index ea54f4d..6615157 100644 --- a/tools/acrntrace/acrntrace.h +++ b/tools/acrntrace/acrntrace.h @@ -76,6 +76,7 @@ typedef struct { int trace_fd; shared_buf_t *sbuf; pthread_mutex_t *sbuf_lock; + uint8_t *buffer; } param_t; typedef struct { -- 2.7.4
|
|
[PATCH v2] HV: handle trusty on vm reset
Victor Sun
- clear run context when reset vcpu;
- destroy trusty without erase trusty memory when reset vm; changelog: v1 -> v2: fix misra violation on calling memset(); Signed-off-by: Sun Victor <victor.sun@...> Signed-off-by: Yin Fengwei <fengwei.yin@...> --- hypervisor/arch/x86/guest/vcpu.c | 7 +++++++ hypervisor/arch/x86/guest/vm.c | 2 ++ 2 files changed, 9 insertions(+) diff --git a/hypervisor/arch/x86/guest/vcpu.c b/hypervisor/arch/x86/guest/vcpu.c index 9dc0241..a6746d2 100644 --- a/hypervisor/arch/x86/guest/vcpu.c +++ b/hypervisor/arch/x86/guest/vcpu.c @@ -396,6 +396,7 @@ void destroy_vcpu(struct vcpu *vcpu) */ void reset_vcpu(struct vcpu *vcpu) { + int i; struct acrn_vlapic *vlapic; pr_dbg("vcpu%hu reset", vcpu->vcpu_id); @@ -419,6 +420,12 @@ void reset_vcpu(struct vcpu *vcpu) vcpu->arch_vcpu.inject_event_pending = false; (void)memset(vcpu->arch_vcpu.vmcs, 0U, CPU_PAGE_SIZE); + for (i = 0; i < NR_WORLD; i++) { + (void)memset(&vcpu->arch_vcpu.contexts[i], 0U, + sizeof(struct run_context)); + } + vcpu->arch_vcpu.cur_context = NORMAL_WORLD; + vlapic = vcpu->arch_vcpu.vlapic; vlapic_reset(vlapic); } diff --git a/hypervisor/arch/x86/guest/vm.c b/hypervisor/arch/x86/guest/vm.c index 4bfda8e..f2efbf9 100644 --- a/hypervisor/arch/x86/guest/vm.c +++ b/hypervisor/arch/x86/guest/vm.c @@ -366,6 +366,8 @@ int reset_vm(struct vm *vm) } vioapic_reset(vm->arch_vm.virt_ioapic); + destroy_secure_world(vm, false); + vm->sworld_control.flag.active = 0UL; start_vm(vm); return 0; -- 2.7.4
|
|
Re: [PATCH] HV: hv_main: Add #ifdef HV_DEBUG before debug specific code
#ifdef
On 08-13 Mon 07:59, Eddie Dong wrote:
This is part of SBUF component, what kind of compile option do we use? Let us use same one.shell command "vmexit" is the only one user of vmexit_time/cnt and we use the get_vmexit_profile, enclosed by HV_DEBUG, to access these variables. BTW, hcall side also needs this kind of compile option.I can't follow here. Can you make it more clear. -- Thanks Kaige Fu -----Original Message-----
|
|
Re: [PATCH] HV: handle trusty on vm reset
Victor Sun
On 8/13/2018 3:55 PM, Mingqiang Chi wrote:
Thanks Mingqiang, I will update it soon.-----Original Message-----(void)memset(&vcpu->arch_vcpu.contexts[i], 0U, BR, Victor + }
|
|
Re: [PATCH v2 1/3] HV: Add the emulation of CPUID with 0x16 leaf
If it is physical out of ranger, returning what hardware returns is better than fixed-zero.Hi Yakui,guest_cpuid(). We want the code to be slim to save FuSa effort. Thx Eddie
|
|
Re: [PATCH 3/4] HV: Merge hypervisor debug header files
The series are fine.
toggle quoted messageShow quoted text
Please go PR with my ACK.
-----Original Message-----
|
|
Re: [PATCH] HV: hv_main: Add #ifdef HV_DEBUG before debug specific code
#ifdef
This is part of SBUF component, what kind of compile option do we use? Let us use same one.
toggle quoted messageShow quoted text
BTW, hcall side also needs this kind of compile option.
-----Original Message-----
|
|
Re: [PATCH] HV: handle trusty on vm reset
Mingqiang Chi
toggle quoted messageShow quoted text
-----Original Message-----(void)memset(&vcpu->arch_vcpu.contexts[i], 0U, sizeof(struct run_context)); + }
|
|
[PATCH] HV: handle trusty on vm reset
Victor Sun
- clear run context when reset vcpu;
- destroy trusty without erase trusty memory when reset vm; Signed-off-by: Sun Victor <victor.sun@...> Signed-off-by: Yin Fengwei <fengwei.yin@...> --- hypervisor/arch/x86/guest/vcpu.c | 7 +++++++ hypervisor/arch/x86/guest/vm.c | 2 ++ 2 files changed, 9 insertions(+) diff --git a/hypervisor/arch/x86/guest/vcpu.c b/hypervisor/arch/x86/guest/vcpu.c index 9dc0241..a8a9f0e 100644 --- a/hypervisor/arch/x86/guest/vcpu.c +++ b/hypervisor/arch/x86/guest/vcpu.c @@ -396,6 +396,7 @@ void destroy_vcpu(struct vcpu *vcpu) */ void reset_vcpu(struct vcpu *vcpu) { + int i; struct acrn_vlapic *vlapic; pr_dbg("vcpu%hu reset", vcpu->vcpu_id); @@ -419,6 +420,12 @@ void reset_vcpu(struct vcpu *vcpu) vcpu->arch_vcpu.inject_event_pending = false; (void)memset(vcpu->arch_vcpu.vmcs, 0U, CPU_PAGE_SIZE); + for (i = 0; i < NR_WORLD; i++) { + memset(&vcpu->arch_vcpu.contexts[i], 0, + sizeof(struct run_context)); + } + vcpu->arch_vcpu.cur_context = NORMAL_WORLD; + vlapic = vcpu->arch_vcpu.vlapic; vlapic_reset(vlapic); } diff --git a/hypervisor/arch/x86/guest/vm.c b/hypervisor/arch/x86/guest/vm.c index 4bfda8e..f2efbf9 100644 --- a/hypervisor/arch/x86/guest/vm.c +++ b/hypervisor/arch/x86/guest/vm.c @@ -366,6 +366,8 @@ int reset_vm(struct vm *vm) } vioapic_reset(vm->arch_vm.virt_ioapic); + destroy_secure_world(vm, false); + vm->sworld_control.flag.active = 0UL; start_vm(vm); return 0; -- 2.7.4
|
|
[PATCH] hv:Fix misra-c return value violations for vioapic APIs
Mingqiang Chi
From: Mingqiang Chi <mingqiang.chi@...>
--Changed 4 APIs to void type vioapic_set_irqstate vioapic_assert_irq vioapic_deassert_irq vioapic_pulse_irq Signed-off-by: Mingqiang Chi <mingqiang.chi@...> --- hypervisor/common/hypercall.c | 6 +++--- hypervisor/dm/vioapic.c | 20 +++++++++----------- hypervisor/include/arch/x86/guest/vioapic.h | 6 +++--- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/hypervisor/common/hypercall.c b/hypervisor/common/hypercall.c index f8efb35..110b3b1 100644 --- a/hypervisor/common/hypercall.c +++ b/hypervisor/common/hypercall.c @@ -109,13 +109,13 @@ handle_vioapic_irqline(struct vm *vm, uint32_t irq, enum irq_mode mode) switch (mode) { case IRQ_ASSERT: - ret = vioapic_assert_irq(vm, irq); + vioapic_assert_irq(vm, irq); break; case IRQ_DEASSERT: - ret = vioapic_deassert_irq(vm, irq); + vioapic_deassert_irq(vm, irq); break; case IRQ_PULSE: - ret = vioapic_pulse_irq(vm, irq); + vioapic_pulse_irq(vm, irq); break; default: /* diff --git a/hypervisor/dm/vioapic.c b/hypervisor/dm/vioapic.c index 4692094..3724be0 100644 --- a/hypervisor/dm/vioapic.c +++ b/hypervisor/dm/vioapic.c @@ -150,14 +150,15 @@ enum irqstate { IRQSTATE_PULSE }; -static int +static void vioapic_set_irqstate(struct vm *vm, uint32_t irq, enum irqstate irqstate) { struct vioapic *vioapic; uint32_t pin = irq; if (pin >= vioapic_pincount(vm)) { - return -EINVAL; + pr_err("invalid vioapic pin number %hhu", pin); + return; } vioapic = vm_ioapic(vm); @@ -178,26 +179,23 @@ vioapic_set_irqstate(struct vm *vm, uint32_t irq, enum irqstate irqstate) panic("vioapic_set_irqstate: invalid irqstate %d", irqstate); } VIOAPIC_UNLOCK(vioapic); - - return 0; } -int +void vioapic_assert_irq(struct vm *vm, uint32_t irq) { - return vioapic_set_irqstate(vm, irq, IRQSTATE_ASSERT); + vioapic_set_irqstate(vm, irq, IRQSTATE_ASSERT); } -int -vioapic_deassert_irq(struct vm *vm, uint32_t irq) +void vioapic_deassert_irq(struct vm *vm, uint32_t irq) { - return vioapic_set_irqstate(vm, irq, IRQSTATE_DEASSERT); + vioapic_set_irqstate(vm, irq, IRQSTATE_DEASSERT); } -int +void vioapic_pulse_irq(struct vm *vm, uint32_t irq) { - return vioapic_set_irqstate(vm, irq, IRQSTATE_PULSE); + vioapic_set_irqstate(vm, irq, IRQSTATE_PULSE); } /* diff --git a/hypervisor/include/arch/x86/guest/vioapic.h b/hypervisor/include/arch/x86/guest/vioapic.h index 98ffc9e..29bb540 100644 --- a/hypervisor/include/arch/x86/guest/vioapic.h +++ b/hypervisor/include/arch/x86/guest/vioapic.h @@ -41,9 +41,9 @@ struct vioapic *vioapic_init(struct vm *vm); void vioapic_cleanup(struct vioapic *vioapic); void vioapic_reset(struct vioapic *vioapic); -int vioapic_assert_irq(struct vm *vm, uint32_t irq); -int vioapic_deassert_irq(struct vm *vm, uint32_t irq); -int vioapic_pulse_irq(struct vm *vm, uint32_t irq); +void vioapic_assert_irq(struct vm *vm, uint32_t irq); +void vioapic_deassert_irq(struct vm *vm, uint32_t irq); +void vioapic_pulse_irq(struct vm *vm, uint32_t irq); void vioapic_update_tmr(struct vcpu *vcpu); void vioapic_mmio_write(struct vm *vm, uint64_t gpa, uint32_t wval); -- 2.7.4
|
|
Re: [PATCH V3 0/3] Tools: fixed issues for S3 feature
Yan, Like
Reviewed-by: Yan, Like <like.yan@...>
toggle quoted messageShow quoted text
On Mon, Aug 13, 2018 at 10:28:47PM +0800, Tao, Yuhong wrote:
With these changes, S3 feature works.
|
|
Re: [PATCH] drm/i915/gvt: fix display messy issue which is introduced by plane pvmmio
Got it. Will simplify the description when submit PR.
toggle quoted messageShow quoted text
-----Original Message-----
From: He, Min Sent: Monday, August 13, 2018 3:13 PM To: acrn-dev@... Cc: Jiang, Fei <fei.jiang@...> Subject: RE: [acrn-dev] [PATCH] drm/i915/gvt: fix display messy issue which is introduced by plane pvmmio LGTM. But I don't think we need to talk about the reason of why it's missed in previous patch. Reviewed-by: He, Min <min.he@...> -----Original Message-----
|
|
Re: [PATCH] drm/i915/gvt: fix display messy issue which is introduced by plane pvmmio
He, Min <min.he@...>
LGTM. But I don't think we need to talk about the reason of why it's missed in
toggle quoted messageShow quoted text
previous patch. Reviewed-by: He, Min <min.he@...>
-----Original Message-----
|
|
Re: [PATCH] drm/i915/gvt: fix display messy issue which is introduced by plane pvmmio
Zhao, Yakui
toggle quoted messageShow quoted text
-----Original Message-----LGTM. Add: Reviewed-by: Zhao Yakui <yakui.zhao@...>
|
|
Re: [PATCH v2 2/3] HV: Use the pre-defined value to calculate tsc when cpuid(0x15) returns zero ecx
Zhao, Yakui
toggle quoted messageShow quoted text
-----Original Message-----As the pre-defined value is too hack, this patch is removed. Instead after it fails on CPUID 0x15, it will try the CPUID 0x16 to calculate the tsc.
|
|
Re: [PATCH v2 1/3] HV: Add the emulation of CPUID with 0x16 leaf
Zhao, Yakui
toggle quoted messageShow quoted text
-----Original Message-----After Eddie's suggestion is followed to add the limit check(>=0x15 CPUID), the mentioned check is not needed any more. I keep them so that the init_vcpuid_entry still can return the zero entry for the out-of-range CPUID input. If you think that the check is redundant, I can remove them.
|
|
[PATCH 2/2] vhm: add irqfd support for ACRN hypervisor service module
Shuo A Liu
irqfd which is based on eventfd, provides a pipe for injecting guest
interrupt through a file description writing operation. Each irqfd registered by userspace can map a interrupt of the guest to eventfd, and a writing operation on one side of the eventfd will trigger the interrupt injection on vhm side. Signed-off-by: Shuo Liu <shuo.a.liu@...> --- drivers/char/vhm/vhm_dev.c | 11 ++ drivers/vhm/Makefile | 2 +- drivers/vhm/vhm_irqfd.c | 320 +++++++++++++++++++++++++++++++++++++ include/linux/vhm/vhm_eventfd.h | 6 + include/linux/vhm/vhm_ioctl_defs.h | 8 + 5 files changed, 346 insertions(+), 1 deletion(-) create mode 100644 drivers/vhm/vhm_irqfd.c diff --git a/drivers/char/vhm/vhm_dev.c b/drivers/char/vhm/vhm_dev.c index 0ffd3b9..9e0a6e4 100644 --- a/drivers/char/vhm/vhm_dev.c +++ b/drivers/char/vhm/vhm_dev.c @@ -235,6 +235,7 @@ static long vhm_dev_ioctl(struct file *filep, } acrn_ioeventfd_init(vm->vmid); + acrn_irqfd_init(vm->vmid); pr_info("vhm: VM %d created\n", created_vm.vmid); break; @@ -276,6 +277,7 @@ static long vhm_dev_ioctl(struct file *filep, case IC_DESTROY_VM: { acrn_ioeventfd_deinit(vm->vmid); + acrn_irqfd_deinit(vm->vmid); if (vm->trusty_host_gpa) deinit_trusty(vm); ret = hcall_destroy_vm(vm->vmid); @@ -634,6 +636,15 @@ static long vhm_dev_ioctl(struct file *filep, break; } + case IC_EVENT_IRQFD: { + struct acrn_irqfd args; + + if (copy_from_user(&args, (void *)ioctl_param, sizeof(args))) + return -EFAULT; + ret = acrn_irqfd(vm->vmid, &args); + break; + } + default: pr_warn("Unknown IOCTL 0x%x\n", ioctl_num); ret = 0; diff --git a/drivers/vhm/Makefile b/drivers/vhm/Makefile index a25c65d..67a2243 100644 --- a/drivers/vhm/Makefile +++ b/drivers/vhm/Makefile @@ -1 +1 @@ -obj-y += vhm_mm.o vhm_hugetlb.o vhm_ioreq.o vhm_vm_mngt.o vhm_msi.o vhm_hypercall.o vhm_ioeventfd.o +obj-y += vhm_mm.o vhm_hugetlb.o vhm_ioreq.o vhm_vm_mngt.o vhm_msi.o vhm_hypercall.o vhm_ioeventfd.o vhm_irqfd.o diff --git a/drivers/vhm/vhm_irqfd.c b/drivers/vhm/vhm_irqfd.c new file mode 100644 index 0000000..9795893 --- /dev/null +++ b/drivers/vhm/vhm_irqfd.c @@ -0,0 +1,320 @@ +#include <linux/syscalls.h> +#include <linux/wait.h> +#include <linux/poll.h> +#include <linux/file.h> +#include <linux/list.h> +#include <linux/eventfd.h> +#include <linux/kernel.h> +#include <linux/async.h> +#include <linux/slab.h> + +#include <linux/vhm/acrn_common.h> +#include <linux/vhm/acrn_vhm_ioreq.h> +#include <linux/vhm/vhm_vm_mngt.h> +#include <linux/vhm/vhm_ioctl_defs.h> +#include <linux/vhm/vhm_hypercall.h> + +static LIST_HEAD(vhm_irqfd_clients); +static DEFINE_MUTEX(vhm_irqfds_mutex); +static ASYNC_DOMAIN_EXCLUSIVE(irqfd_domain); + +struct acrn_vhm_irqfd { + struct vhm_irqfd_info *info; + wait_queue_entry_t wait; + struct work_struct shutdown; + struct eventfd_ctx *eventfd; + struct list_head list; + poll_table pt; + struct acrn_msi_entry msi; +}; + +struct vhm_irqfd_info { + struct list_head list; + int refcnt; + uint16_t vmid; + struct workqueue_struct *wq; + + struct list_head irqfds; + spinlock_t irqfds_lock; +}; + +static struct vhm_irqfd_info *find_get_irqfd_info_by_vm(uint16_t vmid) +{ + struct vhm_irqfd_info *info = NULL; + + mutex_lock(&vhm_irqfds_mutex); + list_for_each_entry(info, &vhm_irqfd_clients, list) { + if (info->vmid == vmid) { + info->refcnt++; + mutex_unlock(&vhm_irqfds_mutex); + return info; + } + } + mutex_unlock(&vhm_irqfds_mutex); + return NULL; +} + +static void put_irqfd_info(struct vhm_irqfd_info *info) +{ + mutex_lock(&vhm_irqfds_mutex); + info->refcnt--; + if (info->refcnt == 0) { + list_del(&info->list); + kfree(info); + } + mutex_unlock(&vhm_irqfds_mutex); +} + +static void vhm_irqfd_inject(struct acrn_vhm_irqfd *irqfd) +{ + struct vhm_irqfd_info *info = irqfd->info; + + vhm_inject_msi(info->vmid, irqfd->msi.msi_addr, + irqfd->msi.msi_data); +} + +/* + * Try to find if the irqfd still in list info->irqfds + * + * assumes info->irqfds_lock is held + */ +static bool vhm_irqfd_is_active(struct vhm_irqfd_info *info, + struct acrn_vhm_irqfd *irqfd) +{ + struct acrn_vhm_irqfd *_irqfd; + + list_for_each_entry(_irqfd, &info->irqfds, list) + if (_irqfd == irqfd) + return true; + + return false; +} + +/* + * Remove irqfd and free it. + * + * assumes info->irqfds_lock is held + */ +static void vhm_irqfd_shutdown(struct acrn_vhm_irqfd *irqfd) +{ + u64 cnt; + + /* remove from wait queue */ + list_del_init(&irqfd->list); + eventfd_ctx_remove_wait_queue(irqfd->eventfd, &irqfd->wait, &cnt); + eventfd_ctx_put(irqfd->eventfd); + kfree(irqfd); +} + +static void vhm_irqfd_shutdown_work(struct work_struct *work) +{ + unsigned long flags; + struct acrn_vhm_irqfd *irqfd = + container_of(work, struct acrn_vhm_irqfd, shutdown); + struct vhm_irqfd_info *info = irqfd->info; + + spin_lock_irqsave(&info->irqfds_lock, flags); + if (vhm_irqfd_is_active(info, irqfd)) + vhm_irqfd_shutdown(irqfd); + spin_unlock_irqrestore(&info->irqfds_lock, flags); +} + +/* + * Called with wqh->lock held and interrupts disabled + */ +static int vhm_irqfd_wakeup(wait_queue_entry_t *wait, unsigned mode, + int sync, void *key) +{ + struct acrn_vhm_irqfd *irqfd = + container_of(wait, struct acrn_vhm_irqfd, wait); + unsigned long poll_bits = (unsigned long)key; + struct vhm_irqfd_info *info = irqfd->info; + + if (poll_bits & POLLIN) + /* An event has been signaled, inject an interrupt */ + vhm_irqfd_inject(irqfd); + + if (poll_bits & POLLHUP) + /* async close eventfd as shutdown need hold wqh->lock */ + queue_work(info->wq, &irqfd->shutdown); + + return 0; +} + +static void vhm_irqfd_poll_func(struct file *file, + wait_queue_head_t *wqh, poll_table *pt) +{ + struct acrn_vhm_irqfd *irqfd = + container_of(pt, struct acrn_vhm_irqfd, pt); + add_wait_queue(wqh, &irqfd->wait); +} + +static int acrn_irqfd_assign(struct vhm_irqfd_info *info, + struct acrn_irqfd *args) +{ + struct acrn_vhm_irqfd *irqfd, *tmp; + struct fd f; + struct eventfd_ctx *eventfd = NULL; + int ret = 0; + unsigned int events; + + irqfd = kzalloc(sizeof(*irqfd), GFP_KERNEL); + if (!irqfd) + return -ENOMEM; + + irqfd->info = info; + memcpy(&irqfd->msi, &args->msi, sizeof(args->msi)); + INIT_LIST_HEAD(&irqfd->list); + INIT_WORK(&irqfd->shutdown, vhm_irqfd_shutdown_work); + + f = fdget(args->fd); + if (!f.file) { + ret = -EBADF; + goto out; + } + + eventfd = eventfd_ctx_fileget(f.file); + if (IS_ERR(eventfd)) { + ret = PTR_ERR(eventfd); + goto fail; + } + + irqfd->eventfd = eventfd; + + /* + * Install our own custom wake-up handling so we are notified via + * a callback whenever someone signals the underlying eventfd + */ + init_waitqueue_func_entry(&irqfd->wait, vhm_irqfd_wakeup); + init_poll_funcptr(&irqfd->pt, vhm_irqfd_poll_func); + + spin_lock_irq(&info->irqfds_lock); + + list_for_each_entry(tmp, &info->irqfds, list) { + if (irqfd->eventfd != tmp->eventfd) + continue; + /* This fd is used for another irq already. */ + ret = -EBUSY; + spin_unlock_irq(&info->irqfds_lock); + goto fail; + } + list_add_tail(&irqfd->list, &info->irqfds); + + spin_unlock_irq(&info->irqfds_lock); + + /* Check the pending event in this stage */ + events = f.file->f_op->poll(f.file, &irqfd->pt); + + if (events & POLLIN) + vhm_irqfd_inject(irqfd); + + fdput(f); + + return 0; +fail: + if (eventfd && !IS_ERR(eventfd)) + eventfd_ctx_put(eventfd); + + fdput(f); +out: + kfree(irqfd); + return ret; +} + +static int acrn_irqfd_deassign(struct vhm_irqfd_info *info, + struct acrn_irqfd *args) +{ + struct acrn_vhm_irqfd *irqfd, *tmp; + struct eventfd_ctx *eventfd; + + eventfd = eventfd_ctx_fdget(args->fd); + if (IS_ERR(eventfd)) + return PTR_ERR(eventfd); + + spin_lock_irq(&info->irqfds_lock); + + list_for_each_entry_safe(irqfd, tmp, &info->irqfds, list) { + if (irqfd->eventfd == eventfd) { + vhm_irqfd_shutdown(irqfd); + break; + } + } + + spin_unlock_irq(&info->irqfds_lock); + eventfd_ctx_put(eventfd); + + return 0; +} + +int acrn_irqfd(uint16_t vmid, struct acrn_irqfd *args) +{ + struct vhm_irqfd_info *info; + int ret; + + info = find_get_irqfd_info_by_vm(vmid); + if (!info) + return -ENOENT; + + if (args->flags & ACRN_IRQFD_FLAG_DEASSIGN) + ret = acrn_irqfd_deassign(info, args); + else + ret = acrn_irqfd_assign(info, args); + + put_irqfd_info(info); + return ret; +} + +int acrn_irqfd_init(uint16_t vmid) +{ + struct vhm_irqfd_info *info; + + info = find_get_irqfd_info_by_vm(vmid); + if (info) { + put_irqfd_info(info); + return -EEXIST; + } + + info = kzalloc(sizeof(struct vhm_irqfd_info), GFP_KERNEL); + if (!info) { + pr_err("ACRN vhm irqfd init fail!\n"); + return -ENOMEM; + } + info->vmid = vmid; + info->refcnt = 1; + INIT_LIST_HEAD(&info->irqfds); + spin_lock_init(&info->irqfds_lock); + + info->wq = alloc_workqueue("acrn_irqfd-%d", 0, 0, vmid); + if (!info->wq) { + kfree(info); + return -ENOMEM; + } + + mutex_lock(&vhm_irqfds_mutex); + list_add(&info->list, &vhm_irqfd_clients); + mutex_unlock(&vhm_irqfds_mutex); + + pr_info("ACRN vhm irqfd init done!\n"); + return 0; +} + +void acrn_irqfd_deinit(uint16_t vmid) +{ + struct acrn_vhm_irqfd *irqfd, *tmp; + struct vhm_irqfd_info *info; + + info = find_get_irqfd_info_by_vm(vmid); + if (!info) + return; + put_irqfd_info(info); + + destroy_workqueue(info->wq); + + spin_lock_irq(&info->irqfds_lock); + list_for_each_entry_safe(irqfd, tmp, &info->irqfds, list) + vhm_irqfd_shutdown(irqfd); + spin_unlock_irq(&info->irqfds_lock); + + /* put one more to release it */ + put_irqfd_info(info); +} diff --git a/include/linux/vhm/vhm_eventfd.h b/include/linux/vhm/vhm_eventfd.h index 3c73194..7ee5843 100644 --- a/include/linux/vhm/vhm_eventfd.h +++ b/include/linux/vhm/vhm_eventfd.h @@ -7,4 +7,10 @@ int acrn_ioeventfd_init(int vmid); int acrn_ioeventfd(int vmid, struct acrn_ioeventfd *args); void acrn_ioeventfd_deinit(int vmid); +/* irqfd APIs */ +struct acrn_irqfd; +int acrn_irqfd_init(uint16_t vmid); +int acrn_irqfd(uint16_t vmid, struct acrn_irqfd *args); +void acrn_irqfd_deinit(uint16_t vmid); + #endif diff --git a/include/linux/vhm/vhm_ioctl_defs.h b/include/linux/vhm/vhm_ioctl_defs.h index ac62f1a..3cd0a00 100644 --- a/include/linux/vhm/vhm_ioctl_defs.h +++ b/include/linux/vhm/vhm_ioctl_defs.h @@ -111,6 +111,7 @@ /* VHM eventfd */ #define IC_ID_EVENT_BASE 0x70UL #define IC_EVENT_IOEVENTFD _IC_ID(IC_ID, IC_ID_EVENT_BASE + 0x00) +#define IC_EVENT_IRQFD _IC_ID(IC_ID, IC_ID_EVENT_BASE + 0x01) /** * struct vm_memseg - memory segment info for guest @@ -228,4 +229,11 @@ struct acrn_ioeventfd { uint32_t len; uint64_t data; }; + +#define ACRN_IRQFD_FLAG_DEASSIGN 0x01 +struct acrn_irqfd { + int32_t fd; + uint32_t flags; + struct acrn_msi_entry msi; +}; #endif /* __VHM_IOCTL_DEFS_H__ */ -- 2.8.3
|
|