Date   

[PATCH v2] fixed return value violations

Mingqiang Chi
 

From: Mingqiang Chi <mingqiang.chi@...>

v1-->v2:
ignore the return value for add_timer

Mingqiang Chi (1):
hv:fixed several return value violations

hypervisor/arch/x86/guest/vlapic.c | 19 +++++++++++++++----
hypervisor/arch/x86/irq.c | 2 +-
hypervisor/arch/x86/timer.c | 4 +++-
hypervisor/arch/x86/trusty.c | 14 +++++++-------
hypervisor/boot/reloc.c | 2 +-
hypervisor/boot/sbl/multiboot.c | 4 ++--
hypervisor/debug/shell.c | 5 +++--
7 files changed, 32 insertions(+), 18 deletions(-)

--
2.7.4


[PATCH v2] hv:fixed several return value violations

Mingqiang Chi
 

From: Mingqiang Chi <mingqiang.chi@...>

-- ignore the return value for add_timer
-- add (void) before several functions(memset/memcpy/
vcpu_get_xxx)

v1-->v2:
ignore the return value for add_timer
Signed-off-by: Mingqiang Chi <mingqiang.chi@...>
---
hypervisor/arch/x86/guest/vlapic.c | 19 +++++++++++++++----
hypervisor/arch/x86/irq.c | 2 +-
hypervisor/arch/x86/timer.c | 4 +++-
hypervisor/arch/x86/trusty.c | 14 +++++++-------
hypervisor/boot/reloc.c | 2 +-
hypervisor/boot/sbl/multiboot.c | 4 ++--
hypervisor/debug/shell.c | 5 +++--
7 files changed, 32 insertions(+), 18 deletions(-)

diff --git a/hypervisor/arch/x86/guest/vlapic.c b/hypervisor/arch/x86/guest/vlapic.c
index 1fcdfdb..06e5057 100644
--- a/hypervisor/arch/x86/guest/vlapic.c
+++ b/hypervisor/arch/x86/guest/vlapic.c
@@ -394,7 +394,11 @@ static void vlapic_icrtmr_write_handler(struct acrn_vlapic *vlapic)

del_timer(&vtimer->timer);
if (set_expiration(vlapic)) {
- add_timer(&vtimer->timer);
+ /* vlapic_create_timer has been called,
+ * and timer->fire_tsc is not 0, here
+ * add_timer should not return error
+ */
+ (void)add_timer(&vtimer->timer);
}
}

@@ -428,8 +432,11 @@ static void vlapic_set_tsc_deadline_msr(struct acrn_vlapic *vlapic,
/* transfer guest tsc to host tsc */
val -= exec_vmread64(VMX_TSC_OFFSET_FULL);
timer->fire_tsc = val;
-
- add_timer(timer);
+ /* vlapic_create_timer has been called,
+ * and timer->fire_tsc is not 0,here
+ * add_timer should not return error
+ */
+ (void)add_timer(timer);
} else {
timer->fire_tsc = 0UL;
}
@@ -1311,7 +1318,11 @@ vlapic_svr_write_handler(struct acrn_vlapic *vlapic)
dev_dbg(ACRN_DBG_LAPIC, "vlapic is software-enabled");
if (vlapic_lvtt_period(vlapic)) {
if (set_expiration(vlapic)) {
- add_timer(&vlapic->vtimer.timer);
+ /* vlapic_create_timer has been called,
+ * and timer->fire_tsc is not 0,here
+ * add_timer should not return error
+ */
+ (void)add_timer(&vlapic->vtimer.timer);
}
}
}
diff --git a/hypervisor/arch/x86/irq.c b/hypervisor/arch/x86/irq.c
index 464b131..f574afc 100644
--- a/hypervisor/arch/x86/irq.c
+++ b/hypervisor/arch/x86/irq.c
@@ -571,7 +571,7 @@ void free_irq(uint32_t irq)

desc->action = NULL;
desc->priv_data = NULL;
- memset(desc->name, '\0', 32U);
+ (void)memset(desc->name, '\0', 32U);

spinlock_irqrestore_release(&desc->irq_lock, rflags);
irq_desc_try_free_vector(desc->irq);
diff --git a/hypervisor/arch/x86/timer.c b/hypervisor/arch/x86/timer.c
index 3c2401d..06ee564 100644
--- a/hypervisor/arch/x86/timer.c
+++ b/hypervisor/arch/x86/timer.c
@@ -17,7 +17,9 @@ static void run_timer(struct hv_timer *timer)
{
/* deadline = 0 means stop timer, we should skip */
if ((timer->func != NULL) && (timer->fire_tsc != 0UL)) {
- timer->func(timer->priv_data);
+ if (timer->func(timer->priv_data) != 0) {
+ pr_err("Timer handler return error");
+ }
}

TRACE_2L(TRACE_TIMER_ACTION_PCKUP, timer->fire_tsc, 0UL);
diff --git a/hypervisor/arch/x86/trusty.c b/hypervisor/arch/x86/trusty.c
index e410f82..cabef15 100644
--- a/hypervisor/arch/x86/trusty.c
+++ b/hypervisor/arch/x86/trusty.c
@@ -210,10 +210,10 @@ void destroy_secure_world(struct vm *vm, bool need_clr_mem)
static void save_world_ctx(struct vcpu *vcpu, struct ext_context *ext_ctx)
{
/* cache on-demand run_context for efer/rflags/rsp/rip */
- vcpu_get_efer(vcpu);
- vcpu_get_rflags(vcpu);
- vcpu_get_rsp(vcpu);
- vcpu_get_rip(vcpu);
+ (void)vcpu_get_efer(vcpu);
+ (void)vcpu_get_rflags(vcpu);
+ (void)vcpu_get_rsp(vcpu);
+ (void)vcpu_get_rip(vcpu);

/* VMCS GUEST field */
ext_ctx->vmx_cr0 = exec_vmread(VMX_GUEST_CR0);
@@ -426,7 +426,7 @@ bool initialize_trusty(struct vcpu *vcpu, uint64_t param)
struct vm *vm = vcpu->vm;
struct trusty_boot_param boot_param;

- memset(&boot_param, 0U, sizeof(boot_param));
+ (void)memset(&boot_param, 0U, sizeof(boot_param));
if (copy_from_gpa(vcpu->vm, &boot_param, param, sizeof(boot_param))) {
pr_err("%s: Unable to copy trusty_boot_param\n", __func__);
return false;
@@ -497,7 +497,7 @@ void trusty_set_dseed(void *dseed, uint8_t dseed_num)

void save_sworld_context(struct vcpu *vcpu)
{
- memcpy_s(&vcpu->vm->sworld_snapshot,
+ (void)memcpy_s(&vcpu->vm->sworld_snapshot,
sizeof(struct cpu_context),
&vcpu->arch_vcpu.contexts[SECURE_WORLD],
sizeof(struct cpu_context));
@@ -513,7 +513,7 @@ void restore_sworld_context(struct vcpu *vcpu)
sworld_ctl->sworld_memory.length,
TRUSTY_EPT_REBASE_GPA);

- memcpy_s(&vcpu->arch_vcpu.contexts[SECURE_WORLD],
+ (void)memcpy_s(&vcpu->arch_vcpu.contexts[SECURE_WORLD],
sizeof(struct cpu_context),
&vcpu->vm->sworld_snapshot,
sizeof(struct cpu_context));
diff --git a/hypervisor/boot/reloc.c b/hypervisor/boot/reloc.c
index 6ff1b0a..b5429a4 100644
--- a/hypervisor/boot/reloc.c
+++ b/hypervisor/boot/reloc.c
@@ -219,7 +219,7 @@ uint64_t prepare_trampoline(void)
pr_dbg("trampoline code: %llx size %x", dest_pa, size);

/* Copy segment for AP initialization code below 1MB */
- memcpy_s(HPA2HVA(dest_pa), (size_t)size, &_ld_trampoline_load,
+ (void)memcpy_s(HPA2HVA(dest_pa), (size_t)size, &_ld_trampoline_load,
(size_t)size);
update_trampoline_code_refs(dest_pa);
trampoline_start16_paddr = dest_pa;
diff --git a/hypervisor/boot/sbl/multiboot.c b/hypervisor/boot/sbl/multiboot.c
index 63b3e49..9fab2fc 100644
--- a/hypervisor/boot/sbl/multiboot.c
+++ b/hypervisor/boot/sbl/multiboot.c
@@ -177,7 +177,7 @@ static void *parse_image_boot_params(struct vm *vm, char *cmdline)
*/
arg_end = strchr(arg, ' ');
len = arg_end ? (uint32_t)(arg_end - arg) : strnlen_s(arg, MEM_2K);
- memset(arg, ' ', len);
+ (void)memset(arg, ' ', len);

return (void *)boot_params;

@@ -297,7 +297,7 @@ int init_vm_boot_info(struct vm *vm)
* kernel cmdline
*/
if (boot_params_addr != NULL) {
- memset(buf, 0U, sizeof(buf));
+ (void)memset(buf, 0U, sizeof(buf));
snprintf(buf, MAX_BOOT_PARAMS_LEN, "%s0x%X ",
boot_params_arg,
HVA2GPA(vm, (uint64_t)boot_params_addr));
diff --git a/hypervisor/debug/shell.c b/hypervisor/debug/shell.c
index 6cad80b..6e389a4 100644
--- a/hypervisor/debug/shell.c
+++ b/hypervisor/debug/shell.c
@@ -813,18 +813,19 @@ static int shell_show_vioapic_info(int argc, char **argv)

static int shell_show_ioapic_info(__unused int argc, __unused char **argv)
{
+ int err = 0;
char *temp_str = alloc_pages(2U);

if (temp_str == NULL) {
return -ENOMEM;
}

- get_ioapic_info(temp_str, 2 * CPU_PAGE_SIZE);
+ err = get_ioapic_info(temp_str, 2 * CPU_PAGE_SIZE);
shell_puts(temp_str);

free(temp_str);

- return 0;
+ return err;
}

static int shell_show_vmexit_profile(__unused int argc, __unused char **argv)
--
2.7.4


Re: [RFC PATCH 0/2] simple level trigger interrupt handle

Chen, Jason CJ
 

On Thu, Aug 16, 2018 at 06:56:41PM +0800, Li, Fei1 wrote:
This patch tries to simple the level trigger mode interrupt handle. For
guest ptdev interrupt, we don't need to mask or unmask the interrupt by
ourself. We could let the guest decide when should mask or unamsk the
interrupt by itself. If the guest uses handle_fasteoi_irq to handle the
level trigger mode interrupt, we may not need to mask and unmask the interrupt
in hypervisor.

================================================================================================================

For ptdev level interrupt, the previous process:

ACRN Hypervisor:
dispatch_interrupt ---> common_dev_handler_level
|
|
|
(1) GSI_MASK_IRQ
|
(2) send_lapic_eoi
|
(3) action(desc->irq, desc->priv_data) ---> inject the interrupt to vlapic

Guest Kernel:
virtual interrupt injected ---> handle_fasteoi_irq
|
|
|
(1) handle_irq_event(desc);
|
(2) cond_unmask_eoi_irq(desc, chip); ---> eoi and vmexit


ACRN Hypervisor:
eoi and vmexit ---> veoi_vmexit_handler ---> vioapic_process_eoi ---> ptdev_intx_ack
|
|
|
GSI_UNMASK_IRQ(phys_irq);

================================================================================================================

For ptdev level interrupt, current process:

ACRN Hypervisor:
dispatch_interrupt ---> common_dev_handler_level
|
|
|
(1) action(desc->irq, desc->priv_data) ---> inject the interrupt to vlapic
|
(2) send_lapic_eoi
should we send_lapic_eoi only after guest eoi?


Guest Kernel:
virtual interrupt injected ---> handle_fasteoi_irq
|
|
|
(1) handle_irq_event(desc);
|
(2) cond_unmask_eoi_irq(desc, chip); ---> eoi and vmexit


ACRN Hypervisor:
eoi and vmexit ---> veoi_vmexit_handler ---> vioapic_process_eoi ---> ptdev_intx_ack
|
|
|

================================================================================================================

Li, Fei1 (2):
hv: ptdev: simplify ptdev_intx_pin_remap logic
hv: irq: emulate fast eoi to handle level interrupt

hypervisor/arch/x86/assign.c | 55 ++----------------------------------
hypervisor/arch/x86/ioapic.c | 22 ---------------
hypervisor/arch/x86/irq.c | 24 ++++------------
hypervisor/include/arch/x86/ioapic.h | 3 --
4 files changed, 8 insertions(+), 96 deletions(-)

--
2.7.4
--

Thanks

Jason


[PATCH 6/7] dm: virtio: implement vhost chardev interfaces

Jian Jun Chen
 

vhost proxy interacts with vhost kernel thru vhost char dev. Internal
interfaces are implemented based on ioctls of vhost char dev in this
patch.

Signed-off-by: Jian Jun Chen <jian.jun.chen@...>
---
devicemodel/hw/pci/virtio/vhost.c | 81 +++++++++++++++++++------------
1 file changed, 51 insertions(+), 30 deletions(-)

diff --git a/devicemodel/hw/pci/virtio/vhost.c b/devicemodel/hw/pci/virtio/vhost.c
index bd50ed1..715000c 100644
--- a/devicemodel/hw/pci/virtio/vhost.c
+++ b/devicemodel/hw/pci/virtio/vhost.c
@@ -29,126 +29,147 @@ static int vhost_debug;
#define DPRINTF(params) do { if (vhost_debug) printf params; } while (0)
#define WPRINTF(params) (printf params)

+static inline
+int vhost_kernel_ioctl(struct vhost_dev *vdev,
+ unsigned long int request,
+ void *arg)
+{
+ int rc;
+
+ rc = ioctl(vdev->fd, request, arg);
+ if (rc < 0)
+ WPRINTF(("%s failed, fd = %d, request = 0x%lx,"
+ " rc = %d, errno = %d\n",
+ __func__, vdev->fd, request, rc, errno));
+ return rc;
+}
+
static void
vhost_kernel_init(struct vhost_dev *vdev, struct virtio_base *base,
int fd, int vq_idx, uint32_t busyloop_timeout)
{
- /* to be implemented */
+ vdev->base = base;
+ vdev->fd = fd;
+ vdev->vq_idx = vq_idx;
+ vdev->busyloop_timeout = busyloop_timeout;
}

static void
vhost_kernel_deinit(struct vhost_dev *vdev)
{
- /* to be implemented */
+ vdev->base = NULL;
+ vdev->vq_idx = 0;
+ vdev->busyloop_timeout = 0;
+ if (vdev->fd > 0) {
+ close(vdev->fd);
+ vdev->fd = -1;
+ }
}

static int
vhost_kernel_set_mem_table(struct vhost_dev *vdev,
struct vhost_memory *mem)
{
- /* to be implemented */
- return -1;
+ return vhost_kernel_ioctl(vdev, VHOST_SET_MEM_TABLE, mem);
}

static int
vhost_kernel_set_vring_addr(struct vhost_dev *vdev,
struct vhost_vring_addr *addr)
{
- /* to be implemented */
- return -1;
+ return vhost_kernel_ioctl(vdev, VHOST_SET_VRING_ADDR, addr);
}

static int
vhost_kernel_set_vring_num(struct vhost_dev *vdev,
struct vhost_vring_state *ring)
{
- /* to be implemented */
- return -1;
+ return vhost_kernel_ioctl(vdev, VHOST_SET_VRING_NUM, ring);
}

static int
vhost_kernel_set_vring_base(struct vhost_dev *vdev,
struct vhost_vring_state *ring)
{
- /* to be implemented */
- return -1;
+ return vhost_kernel_ioctl(vdev, VHOST_SET_VRING_BASE, ring);
}

static int
vhost_kernel_get_vring_base(struct vhost_dev *vdev,
struct vhost_vring_state *ring)
{
- /* to be implemented */
- return -1;
+ return vhost_kernel_ioctl(vdev, VHOST_GET_VRING_BASE, ring);
}

static int
vhost_kernel_set_vring_kick(struct vhost_dev *vdev,
struct vhost_vring_file *file)
{
- /* to be implemented */
- return -1;
+ return vhost_kernel_ioctl(vdev, VHOST_SET_VRING_KICK, file);
}

static int
vhost_kernel_set_vring_call(struct vhost_dev *vdev,
struct vhost_vring_file *file)
{
- /* to be implemented */
- return -1;
+ return vhost_kernel_ioctl(vdev, VHOST_SET_VRING_CALL, file);
}

static int
vhost_kernel_set_vring_busyloop_timeout(struct vhost_dev *vdev,
struct vhost_vring_state *s)
{
- /* to be implemented */
- return -1;
+#ifdef VHOST_SET_VRING_BUSYLOOP_TIMEOUT
+ return vhost_kernel_ioctl(vdev, VHOST_SET_VRING_BUSYLOOP_TIMEOUT, s);
+#else
+ return 0;
+#endif
}

static int
vhost_kernel_set_features(struct vhost_dev *vdev,
uint64_t features)
{
- /* to be implemented */
- return -1;
+ return vhost_kernel_ioctl(vdev, VHOST_SET_FEATURES, &features);
}

static int
vhost_kernel_get_features(struct vhost_dev *vdev,
uint64_t *features)
{
- /* to be implemented */
- return -1;
+ return vhost_kernel_ioctl(vdev, VHOST_GET_FEATURES, features);
}

static int
vhost_kernel_set_owner(struct vhost_dev *vdev)
{
- /* to be implemented */
- return -1;
+ return vhost_kernel_ioctl(vdev, VHOST_SET_OWNER, NULL);
}

static int
vhost_kernel_reset_device(struct vhost_dev *vdev)
{
- /* to be implemented */
- return -1;
+ return vhost_kernel_ioctl(vdev, VHOST_RESET_OWNER, NULL);
}

static int
vhost_kernel_net_set_backend(struct vhost_dev *vdev,
struct vhost_vring_file *file)
{
- /* to be implemented */
- return -1;
+ return vhost_kernel_ioctl(vdev, VHOST_NET_SET_BACKEND, file);
}

static int
vhost_eventfd_test_and_clear(int fd)
{
- /* to be implemented */
- return -1;
+ uint64_t count = 0;
+ int rc;
+
+ /* a read will set the count to zero */
+ rc = read(fd, &count, sizeof(count));
+ DPRINTF(("%s, rc = %d, errno = %d, count = %ld\n",
+ __func__, rc, errno, count));
+ return rc > 0 ? 1 : 0;
}

static void
--
2.17.1


[PATCH 5/7] dm: virtio: implement vhost_vq_register_eventfd

Jian Jun Chen
 

There are 2 eventfds for one virtqueue, one is for kick and the other
is for notify. eventfd used for kick is associated with a PIO/MMIO
region. eventfd used for notify is associated with a MSIx/INTx. The
eventfd pair is registered to VHM thru VHM char dev.

VHM irqfd currently only support MSIx. If INTx is used, vhost proxy
uses mevent to poll the call fd from vhost then inject interrupt to
guest.

Signed-off-by: Jian Jun Chen <jian.jun.chen@...>
---
devicemodel/hw/pci/virtio/vhost.c | 131 +++++++++++++++++++++++++++++-
1 file changed, 129 insertions(+), 2 deletions(-)

diff --git a/devicemodel/hw/pci/virtio/vhost.c b/devicemodel/hw/pci/virtio/vhost.c
index 921059e..bd50ed1 100644
--- a/devicemodel/hw/pci/virtio/vhost.c
+++ b/devicemodel/hw/pci/virtio/vhost.c
@@ -151,12 +151,139 @@ vhost_eventfd_test_and_clear(int fd)
return -1;
}

+static void
+vhost_vq_notify(int fd __attribute__((unused)),
+ enum ev_type t __attribute__((unused)),
+ void *arg)
+{
+ struct vhost_vq *vq = arg;
+ struct virtio_vq_info *vqi;
+ struct vhost_dev *vdev;
+
+ vdev = vq->dev;
+ vqi = &vdev->base->queues[vdev->vq_idx + vq->idx];
+ vq_interrupt(vdev->base, vqi);
+}
+
static int
vhost_vq_register_eventfd(struct vhost_dev *vdev,
int idx, bool is_register)
{
- /* to be implemented */
- return -1;
+ struct acrn_ioeventfd ioeventfd = {0};
+ struct acrn_irqfd irqfd = {0};
+ struct virtio_base *base;
+ struct vhost_vq *vq;
+ struct virtio_vq_info *vqi;
+ struct pcibar *bar;
+ int rc = -1;
+
+ /* this interface is called only by vhost_vq_start,
+ * parameters have been checked there
+ */
+ base = vdev->base;
+ vqi = &vdev->base->queues[vdev->vq_idx + idx];
+ vq = &vdev->vqs[idx];
+
+ if (!is_register) {
+ ioeventfd.flags = ACRN_IOEVENTFD_FLAG_DEASSIGN;
+ irqfd.flags = ACRN_IRQFD_FLAG_DEASSIGN;
+ }
+
+ /* register ioeventfd for kick */
+ if (base->device_caps & VIRTIO_FLAG_VERSION_1) {
+ /* in the current implementation, if virtio 1.0 with pio
+ * notity, its bar idx should be set to non-zero
+ */
+ if (base->modern_pio_bar_idx) {
+ bar = &vdev->base->dev->bar[base->modern_pio_bar_idx];
+ ioeventfd.data = vdev->vq_idx + idx;
+ ioeventfd.addr = bar->addr;
+ ioeventfd.len = 2;
+ ioeventfd.flags |= (ACRN_IOEVENTFD_FLAG_DATAMATCH |
+ ACRN_IOEVENTFD_FLAG_PIO);
+ ioeventfd.fd = vq->kick_fd;
+ DPRINTF(("%s: [ioeventfd: %d][0x%lx@%d]\n",
+ __func__, ioeventfd.fd,
+ ioeventfd.addr, ioeventfd.len));
+ rc = vm_ioeventfd(vdev->base->dev->vmctx, &ioeventfd);
+ } else if (base->modern_mmio_bar_idx) {
+ bar = &vdev->base->dev->bar[base->modern_mmio_bar_idx];
+ ioeventfd.data = 0;
+ ioeventfd.addr = bar->addr + VIRTIO_CAP_NOTIFY_OFFSET
+ + (vdev->vq_idx + idx) *
+ VIRTIO_MODERN_NOTIFY_OFF_MULT;
+ ioeventfd.len = 2;
+ /* no additional flag bit should be set for MMIO */
+ ioeventfd.fd = vq->kick_fd;
+ DPRINTF(("%s: [ioeventfd: %d][0x%lx@%d]\n",
+ __func__, ioeventfd.fd,
+ ioeventfd.addr, ioeventfd.len));
+ rc = vm_ioeventfd(vdev->base->dev->vmctx, &ioeventfd);
+ } else {
+ WPRINTF(("%s: invalid virtio 1.0 parameters, 0x%lx\n",
+ __func__, base->device_caps));
+ return -1;
+ }
+ } else {
+ bar = &vdev->base->dev->bar[base->legacy_pio_bar_idx];
+ ioeventfd.data = vdev->vq_idx + idx;
+ ioeventfd.addr = bar->addr + VIRTIO_CR_QNOTIFY;
+ ioeventfd.len = 2;
+ ioeventfd.flags |= (ACRN_IOEVENTFD_FLAG_DATAMATCH |
+ ACRN_IOEVENTFD_FLAG_PIO);
+ ioeventfd.fd = vq->kick_fd;
+ DPRINTF(("%s: [ioeventfd: %d][0x%lx@%d]\n",
+ __func__, ioeventfd.fd,
+ ioeventfd.addr, ioeventfd.len));
+ rc = vm_ioeventfd(vdev->base->dev->vmctx, &ioeventfd);
+ }
+
+ if (rc < 0) {
+ WPRINTF(("%s: vm_ioeventfd failed rc = %d, errno = %d\n",
+ __func__, rc, errno));
+ return -1;
+ }
+
+ /* register irqfd for notify */
+ if (pci_msix_enabled(base->dev)) {
+ struct msix_table_entry *mte;
+ struct acrn_msi_entry msi;
+
+ mte = &vdev->base->dev->msix.table[vqi->msix_idx];
+ msi.msi_addr = mte->addr;
+ msi.msi_data = mte->msg_data;
+ irqfd.fd = vq->call_fd;
+ /* no additional flag bit should be set */
+ irqfd.msi = msi;
+ DPRINTF(("%s: [irqfd: %d][MSIX: %d]\n",
+ __func__, irqfd.fd, vqi->msix_idx));
+ rc = vm_irqfd(vdev->base->dev->vmctx, &irqfd);
+ } else {
+ if (is_register) {
+ vq->mevp = mevent_add(vq->call_fd, EVF_READ,
+ vhost_vq_notify, vq);
+ if (!vq->mevp) {
+ WPRINTF(("%s, mevent_add failed\n", __func__));
+ rc = -1;
+ }
+ } else if (vq->mevp) {
+ mevent_delete(vq->mevp);
+ vq->mevp = NULL;
+ }
+ }
+
+ if (rc < 0) {
+ WPRINTF(("%s: vm_irqfd failed rc = %d, errno = %d\n",
+ __func__, rc, errno));
+ /* unregister ioeventfd */
+ if (is_register) {
+ ioeventfd.flags |= ACRN_IOEVENTFD_FLAG_DEASSIGN;
+ vm_ioeventfd(vdev->base->dev->vmctx, &ioeventfd);
+ }
+ return -1;
+ }
+
+ return 0;
}

static int
--
2.17.1


[PATCH 7/7] dm: virtio-net: add vhost net support

Jian Jun Chen
 

One additional command parameter is added for virtio-net to support
vhost net. The command line for vhost net is as follows:
-s n,virtio-net,tap_xxx,vhost

Signed-off-by: Jian Jun Chen <jian.jun.chen@...>
---
devicemodel/hw/pci/virtio/virtio_net.c | 227 +++++++++++++++++++++++--
1 file changed, 211 insertions(+), 16 deletions(-)

diff --git a/devicemodel/hw/pci/virtio/virtio_net.c b/devicemodel/hw/pci/virtio/virtio_net.c
index 00a6d02..d8ba35b 100644
--- a/devicemodel/hw/pci/virtio/virtio_net.c
+++ b/devicemodel/hw/pci/virtio/virtio_net.c
@@ -44,6 +44,7 @@
#include "pci_core.h"
#include "mevent.h"
#include "virtio.h"
+#include "vhost.h"
#include "netmap_user.h"
#include <linux/if_tun.h>

@@ -72,11 +73,18 @@
#define VIRTIO_NET_F_CTRL_VLAN (1 << 19) /* control channel VLAN filtering */
#define VIRTIO_NET_F_GUEST_ANNOUNCE \
(1 << 21) /* guest can send gratuitous pkts */
+#define VHOST_NET_F_VIRTIO_NET_HDR \
+ (1 << 27) /* vhost provides virtio_net_hdr */

#define VIRTIO_NET_S_HOSTCAPS \
(VIRTIO_NET_F_MAC | VIRTIO_NET_F_MRG_RXBUF | VIRTIO_NET_F_STATUS | \
VIRTIO_FLAG_NOTIFY_ON_EMPTY | VIRTIO_RING_FLAG_INDIRECT_DESC)

+#define VIRTIO_NET_S_VHOSTCAPS \
+ (VIRTIO_FLAG_NOTIFY_ON_EMPTY | VIRTIO_RING_FLAG_INDIRECT_DESC | \
+ VIRTIO_RING_FLAG_EVENT_IDX | VIRTIO_NET_F_MRG_RXBUF | \
+ VIRTIO_FLAG_VERSION_1)
+
/* is address mcast/bcast? */
#define ETHER_IS_MULTICAST(addr) (*(addr) & 0x01)

@@ -117,6 +125,16 @@ static int virtio_net_debug;
#define DPRINTF(params) do { if (virtio_net_debug) printf params; } while (0)
#define WPRINTF(params) (printf params)

+/*
+ * vhost device struct
+ */
+struct vhost_net {
+ struct vhost_dev vdev;
+ struct vhost_vq vqs[2];
+ int tapfd;
+ bool vhost_started;
+};
+
/*
* Per-device struct
*/
@@ -150,13 +168,24 @@ struct virtio_net {
void (*virtio_net_rx)(struct virtio_net *net);
void (*virtio_net_tx)(struct virtio_net *net, struct iovec *iov,
int iovcnt, int len);
+
+ struct vhost_net *vhost_net;
+ bool use_vhost;
};

static void virtio_net_reset(void *vdev);
static void virtio_net_tx_stop(struct virtio_net *net);
-static int virtio_net_cfgread(void *vdev, int offset, int size, uint32_t *retval);
-static int virtio_net_cfgwrite(void *vdev, int offset, int size, uint32_t value);
+static int virtio_net_cfgread(void *vdev, int offset, int size,
+ uint32_t *retval);
+static int virtio_net_cfgwrite(void *vdev, int offset, int size,
+ uint32_t value);
static void virtio_net_neg_features(void *vdev, uint64_t negotiated_features);
+static void virtio_net_set_status(void *vdev, uint64_t status);
+static struct vhost_net *vhost_net_init(struct virtio_base *base, int vhostfd,
+ int tapfd, int vq_idx);
+static int vhost_net_deinit(struct vhost_net *vhost_net);
+static int vhost_net_start(struct vhost_net *vhost_net);
+static int vhost_net_stop(struct vhost_net *vhost_net);

static struct virtio_ops virtio_net_ops = {
"vtnet", /* our name */
@@ -167,7 +196,7 @@ static struct virtio_ops virtio_net_ops = {
virtio_net_cfgread, /* read PCI config */
virtio_net_cfgwrite, /* write PCI config */
virtio_net_neg_features, /* apply negotiated features */
- NULL, /* called on guest set status */
+ virtio_net_set_status, /* called on guest set status */
};

static struct ether_addr *
@@ -802,7 +831,8 @@ virtio_net_tap_open(char *devname)

rc = ioctl(tunfd, TUNSETIFF, (void *)&ifr);
if (rc < 0) {
- WPRINTF(("open of tap device %s failed\n", devname));
+ WPRINTF(("open of tap device %s failed: %d\n",
+ devname, errno));
close(tunfd);
return -1;
}
@@ -816,6 +846,7 @@ virtio_net_tap_setup(struct virtio_net *net, char *devname)
{
char tbuf[80 + 5]; /* room for "acrn_" prefix */
char *tbuf_ptr;
+ int vhost_fd = -1;

tbuf_ptr = tbuf;

@@ -847,12 +878,29 @@ virtio_net_tap_setup(struct virtio_net *net, char *devname)
net->tapfd = -1;
}

- net->mevp = mevent_add(net->tapfd, EVF_READ,
- virtio_net_rx_callback, net);
- if (net->mevp == NULL) {
- WPRINTF(("Could not register event\n"));
- close(net->tapfd);
- net->tapfd = -1;
+ if (net->use_vhost) {
+ vhost_fd = open("/dev/vhost-net", O_RDWR);
+ if (vhost_fd < 0)
+ WPRINTF(("open of vhost-net failed\n"));
+ else {
+ net->vhost_net = vhost_net_init(&net->base, vhost_fd,
+ net->tapfd, 0);
+ if (!net->vhost_net) {
+ WPRINTF(("vhost_net_init failed\n"));
+ close(vhost_fd);
+ vhost_fd = -1;
+ }
+ }
+ }
+
+ if (vhost_fd < 0) {
+ net->mevp = mevent_add(net->tapfd, EVF_READ,
+ virtio_net_rx_callback, net);
+ if (net->mevp == NULL) {
+ WPRINTF(("Could not register event\n"));
+ close(net->tapfd);
+ net->tapfd = -1;
+ }
}
}

@@ -887,6 +935,7 @@ virtio_net_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
struct virtio_net *net;
char *devname;
char *vtopts;
+ char *opt;
int mac_provided;
pthread_mutexattr_t attr;
int rc;
@@ -931,6 +980,7 @@ virtio_net_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
mac_provided = 0;
net->tapfd = -1;
net->nmd = NULL;
+ net->vhost_net = NULL;
if (opts != NULL) {
int err;

@@ -942,13 +992,18 @@ virtio_net_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)

(void) strsep(&vtopts, ",");

- if (vtopts != NULL) {
- err = virtio_net_parsemac(vtopts, net->config.mac);
- if (err != 0) {
- free(devname);
- return err;
+ while ((opt = strsep(&vtopts, ",")) != NULL) {
+ if (strcmp("vhost", opt) == 0)
+ net->use_vhost = true;
+ else {
+ err = virtio_net_parsemac(opt,
+ net->config.mac);
+ if (err != 0) {
+ free(devname);
+ return err;
+ }
+ mac_provided = 1;
}
- mac_provided = 1;
}

if (strncmp(devname, "vale", 4) == 0)
@@ -1072,6 +1127,45 @@ virtio_net_neg_features(void *vdev, uint64_t negotiated_features)
}
}

+static void
+virtio_net_set_status(void *vdev, uint64_t status)
+{
+ struct virtio_net *net = vdev;
+ int rc;
+
+ if (!net->vhost_net)
+ return;
+
+ if (!net->vhost_net->vhost_started &&
+ (status & VIRTIO_CR_STATUS_DRIVER_OK)) {
+ if (net->mevp) {
+ mevent_delete(net->mevp);
+ net->mevp = NULL;
+ }
+
+ rc = vhost_net_start(net->vhost_net);
+ if (rc < 0) {
+ WPRINTF(("%s: vhost_net_start failed\n", __func__));
+ return;
+ }
+ } else if (net->vhost_net->vhost_started &&
+ ((status & VIRTIO_CR_STATUS_DRIVER_OK) == 0)) {
+ rc = vhost_net_stop(net->vhost_net);
+ if (rc < 0)
+ WPRINTF(("%s: vhost_net_start failed\n", __func__));
+
+ if (!net->mevp) {
+ net->mevp = mevent_add(net->tapfd, EVF_READ,
+ virtio_net_rx_callback, net);
+ if (net->mevp == NULL) {
+ WPRINTF(("Could not register event\n"));
+ close(net->tapfd);
+ net->tapfd = -1;
+ }
+ }
+ }
+}
+
static void
virtio_net_deinit(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
{
@@ -1082,6 +1176,13 @@ virtio_net_deinit(struct vmctx *ctx, struct pci_vdev *dev, char *opts)

virtio_net_tx_stop(net);

+ if (net->vhost_net) {
+ vhost_net_stop(net->vhost_net);
+ vhost_net_deinit(net->vhost_net);
+ free(net->vhost_net);
+ net->vhost_net = NULL;
+ }
+
if (net->tapfd >= 0) {
close(net->tapfd);
net->tapfd = -1;
@@ -1098,6 +1199,100 @@ virtio_net_deinit(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
fprintf(stderr, "%s: NULL!\n", __func__);
}

+struct vhost_net *vhost_net_init(struct virtio_base *base, int vhostfd,
+ int tapfd, int vq_idx)
+{
+ struct vhost_net *vhost_net = NULL;
+ uint64_t vhost_features = VIRTIO_NET_S_VHOSTCAPS;
+ uint64_t backend_features = VHOST_NET_F_VIRTIO_NET_HDR;
+ uint32_t busyloop_timeout = 0;
+ int rc;
+
+ vhost_net = calloc(1, sizeof(struct vhost_net));
+ if (!vhost_net) {
+ WPRINTF(("%s, out of memory\n", __func__));
+ goto fail;
+ }
+
+ /* pre-init before calling vhost_dev_init */
+ vhost_net->vdev.nvqs = ARRAY_SIZE(vhost_net->vqs);
+ vhost_net->vdev.vqs = vhost_net->vqs;
+ vhost_net->tapfd = tapfd;
+
+ rc = vhost_dev_init(&vhost_net->vdev, base, vhostfd, vq_idx,
+ vhost_features, backend_features, busyloop_timeout);
+ if (rc < 0) {
+ WPRINTF(("%s, vhost_dev_init failed\n", __func__));
+ goto fail;
+ }
+
+ return vhost_net;
+fail:
+ if (vhost_net)
+ free(vhost_net);
+ return NULL;
+}
+
+int vhost_net_deinit(struct vhost_net *vhost_net)
+{
+ return vhost_dev_deinit(&vhost_net->vdev);
+}
+
+int vhost_net_start(struct vhost_net *vhost_net)
+{
+ int rc;
+
+ if (vhost_net->vhost_started) {
+ WPRINTF(("%s, already started\n", __func__));
+ return 0;
+ }
+
+ rc = vhost_dev_start(&vhost_net->vdev);
+ if (rc < 0) {
+ WPRINTF(("%s, vhost_dev_start failed\n", __func__));
+ goto fail;
+ }
+
+ /* if the backend is the TAP */
+ if (vhost_net->tapfd > 0) {
+ rc = vhost_net_set_backend(&vhost_net->vdev,
+ vhost_net->tapfd);
+ if (rc < 0) {
+ WPRINTF(("%s, vhost_set_backend failed\n", __func__));
+ goto fail_set_backend;
+ }
+ }
+
+ vhost_net->vhost_started = true;
+ return 0;
+
+fail_set_backend:
+ vhost_dev_stop(&vhost_net->vdev);
+fail:
+ return -1;
+}
+
+int vhost_net_stop(struct vhost_net *vhost_net)
+{
+ int rc;
+
+ if (!vhost_net->vhost_started) {
+ WPRINTF(("%s, already stopped\n", __func__));
+ return 0;
+ }
+
+ /* if the backend is the TAP */
+ if (vhost_net->tapfd > 0)
+ vhost_net_set_backend(&vhost_net->vdev, -1);
+
+ rc = vhost_dev_stop(&vhost_net->vdev);
+ if (rc < 0)
+ WPRINTF(("%s, vhost_dev_start failed\n", __func__));
+
+ vhost_net->vhost_started = false;
+ return rc;
+}
+
struct pci_vdev_ops pci_ops_virtio_net = {
.class_name = "virtio-net",
.vdev_init = virtio_net_init,
--
2.17.1


[PATCH 4/7] dm: virtio: implement vhost_set_mem_table

Jian Jun Chen
 

vhost kernel driver needs the information of memory mapping between GPA
and the virtual addresses in device model process. This is required for
virtqueue related operations. This patch gets memory mapping information
from vmctx then conveys to vhost.

Signed-off-by: Jian Jun Chen <jian.jun.chen@...>
---
devicemodel/hw/pci/virtio/vhost.c | 65 ++++++++++++++++++++++++++++++-
1 file changed, 63 insertions(+), 2 deletions(-)

diff --git a/devicemodel/hw/pci/virtio/vhost.c b/devicemodel/hw/pci/virtio/vhost.c
index f5b674a..921059e 100644
--- a/devicemodel/hw/pci/virtio/vhost.c
+++ b/devicemodel/hw/pci/virtio/vhost.c
@@ -42,6 +42,14 @@ vhost_kernel_deinit(struct vhost_dev *vdev)
/* to be implemented */
}

+static int
+vhost_kernel_set_mem_table(struct vhost_dev *vdev,
+ struct vhost_memory *mem)
+{
+ /* to be implemented */
+ return -1;
+}
+
static int
vhost_kernel_set_vring_addr(struct vhost_dev *vdev,
struct vhost_vring_addr *addr)
@@ -367,8 +375,61 @@ vhost_vq_stop(struct vhost_dev *vdev, int idx)
static int
vhost_set_mem_table(struct vhost_dev *vdev)
{
- /* to be implemented */
- return -1;
+ struct vmctx *ctx;
+ struct vhost_memory *mem;
+ uint32_t nregions = 0;
+ int rc;
+
+ ctx = vdev->base->dev->vmctx;
+ if (ctx->lowmem > 0)
+ nregions++;
+ if (ctx->highmem > 0)
+ nregions++;
+
+ mem = calloc(1, sizeof(struct vhost_memory) +
+ sizeof(struct vhost_memory_region) * nregions);
+ if (!mem) {
+ WPRINTF(("%s, out of memory\n", __func__));
+ return -1;
+ }
+
+ nregions = 0;
+ if (ctx->lowmem > 0) {
+ mem->regions[nregions].guest_phys_addr = (uintptr_t)0;
+ mem->regions[nregions].memory_size = ctx->lowmem;
+ mem->regions[nregions].userspace_addr =
+ (uintptr_t)ctx->baseaddr;
+ DPRINTF(("%s: [%d][0x%llx -> 0x%llx, 0x%llx]\n",
+ __func__, nregions,
+ mem->regions[nregions].guest_phys_addr,
+ mem->regions[nregions].userspace_addr,
+ mem->regions[nregions].memory_size));
+ nregions++;
+ }
+
+ if (ctx->highmem > 0) {
+ mem->regions[nregions].guest_phys_addr = 4*GB;
+ mem->regions[nregions].memory_size = ctx->highmem;
+ mem->regions[nregions].userspace_addr =
+ (uintptr_t)(ctx->baseaddr + 4*GB);
+ DPRINTF(("%s: [%d][0x%llx -> 0x%llx, 0x%llx]\n",
+ __func__, nregions,
+ mem->regions[nregions].guest_phys_addr,
+ mem->regions[nregions].userspace_addr,
+ mem->regions[nregions].memory_size));
+ nregions++;
+ }
+
+ mem->nregions = nregions;
+ mem->padding = 0;
+ rc = vhost_kernel_set_mem_table(vdev, mem);
+ free(mem);
+ if (rc < 0) {
+ WPRINTF(("%s, set_mem_table failed\n", __func__));
+ return -1;
+ }
+
+ return 0;
}

int
--
2.17.1


[PATCH 2/7] dm: virtio: add vhost support

Jian Jun Chen
 

This patch adds the vhost support to the device model virtio. A vhost
proxy is implemented based on the virtio framework and vhost char dev.
Key data structures and external interfaces are implemented in this
patch.

Signed-off-by: Jian Jun Chen <jian.jun.chen@...>
---
devicemodel/Makefile | 1 +
devicemodel/hw/pci/virtio/vhost.c | 329 ++++++++++++++++++++++++++++++
devicemodel/include/vhost.h | 104 ++++++++++
3 files changed, 434 insertions(+)
create mode 100644 devicemodel/hw/pci/virtio/vhost.c
create mode 100644 devicemodel/include/vhost.h

diff --git a/devicemodel/Makefile b/devicemodel/Makefile
index a72b5b2..ee1f111 100644
--- a/devicemodel/Makefile
+++ b/devicemodel/Makefile
@@ -60,6 +60,7 @@ SRCS += hw/usb_core.c
SRCS += hw/uart_core.c
SRCS += hw/pci/virtio/virtio.c
SRCS += hw/pci/virtio/virtio_kernel.c
+SRCS += hw/pci/virtio/vhost.c
SRCS += hw/platform/usb_mouse.c
SRCS += hw/platform/usb_pmapper.c
SRCS += hw/platform/atkbdc.c
diff --git a/devicemodel/hw/pci/virtio/vhost.c b/devicemodel/hw/pci/virtio/vhost.c
new file mode 100644
index 0000000..2c658af
--- /dev/null
+++ b/devicemodel/hw/pci/virtio/vhost.c
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/uio.h>
+#include <sys/ioctl.h>
+#include <sys/eventfd.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <linux/vhost.h>
+
+#include "dm.h"
+#include "pci_core.h"
+#include "irq.h"
+#include "vmmapi.h"
+#include "vhost.h"
+
+static int vhost_debug;
+#define DPRINTF(params) do { if (vhost_debug) printf params; } while (0)
+#define WPRINTF(params) (printf params)
+
+static void
+vhost_kernel_init(struct vhost_dev *vdev, struct virtio_base *base,
+ int fd, int vq_idx, uint32_t busyloop_timeout)
+{
+ /* to be implemented */
+}
+
+static void
+vhost_kernel_deinit(struct vhost_dev *vdev)
+{
+ /* to be implemented */
+}
+
+static int
+vhost_kernel_set_vring_busyloop_timeout(struct vhost_dev *vdev,
+ struct vhost_vring_state *s)
+{
+ /* to be implemented */
+ return -1;
+}
+
+static int
+vhost_kernel_set_features(struct vhost_dev *vdev,
+ uint64_t features)
+{
+ /* to be implemented */
+ return -1;
+}
+
+static int
+vhost_kernel_get_features(struct vhost_dev *vdev,
+ uint64_t *features)
+{
+ /* to be implemented */
+ return -1;
+}
+
+static int
+vhost_kernel_set_owner(struct vhost_dev *vdev)
+{
+ /* to be implemented */
+ return -1;
+}
+
+static int
+vhost_kernel_reset_device(struct vhost_dev *vdev)
+{
+ /* to be implemented */
+ return -1;
+}
+
+static int
+vhost_kernel_net_set_backend(struct vhost_dev *vdev,
+ struct vhost_vring_file *file)
+{
+ /* to be implemented */
+ return -1;
+}
+
+static int
+vhost_vq_init(struct vhost_dev *vdev, int idx)
+{
+ /* to be implemented */
+ return -1;
+}
+
+static int
+vhost_vq_deinit(struct vhost_vq *vq)
+{
+ /* to be implemented */
+ return -1;
+}
+
+static int
+vhost_vq_start(struct vhost_dev *vdev, int idx)
+{
+ /* to be implemented */
+ return -1;
+}
+
+static int
+vhost_vq_stop(struct vhost_dev *vdev, int idx)
+{
+ /* to be implemented */
+ return -1;
+}
+
+static int
+vhost_set_mem_table(struct vhost_dev *vdev)
+{
+ /* to be implemented */
+ return -1;
+}
+
+int
+vhost_dev_init(struct vhost_dev *vdev,
+ struct virtio_base *base,
+ int fd,
+ int vq_idx,
+ uint64_t vhost_features,
+ uint64_t backend_features,
+ uint32_t busyloop_timeout)
+{
+ uint64_t features;
+ int i, rc;
+
+ /* sanity check */
+ if (!base || !base->queues || !base->vops) {
+ WPRINTF(("%s, virtio_base is not initialized\n", __func__));
+ goto fail;
+ }
+
+ if (!vdev->vqs || vdev->nvqs == 0) {
+ WPRINTF(("%s, virtqueue is not initialized\n", __func__));
+ goto fail;
+ }
+
+ if (vq_idx + vdev->nvqs > base->vops->nvq) {
+ WPRINTF(("%s, invalid vq_idx = %d\n", __func__, vq_idx));
+ goto fail;
+ }
+
+ vhost_kernel_init(vdev, base, fd, vq_idx, busyloop_timeout);
+
+ rc = vhost_kernel_get_features(vdev, &features);
+ if (rc < 0) {
+ WPRINTF(("%s, vhost_get_features failed\n", __func__));
+ goto fail;
+ }
+
+ for (i = 0; i < vdev->nvqs; i++) {
+ rc = vhost_vq_init(vdev, i);
+ if (rc < 0)
+ goto fail;
+ }
+
+ /* specific backend features to vhost */
+ vdev->backend_features = backend_features & features;
+
+ /* features supported by vhost */
+ vdev->vhost_features = vhost_features;
+
+ /*
+ * if a feature bit is not supported by either vhost or the
+ * configuration from device model specified by vhost_features,
+ * it should be disabled in device_caps, which acts as host_features
+ * when doing feature negotiation with guest. This must be done
+ * before virtio feature negotiation.
+ */
+ vdev->base->device_caps &= ~(vhost_features ^ features);
+ vdev->started = false;
+
+ return 0;
+
+fail:
+ vhost_dev_deinit(vdev);
+ return -1;
+}
+
+int
+vhost_dev_deinit(struct vhost_dev *vdev)
+{
+ int i;
+
+ if (!vdev->base || !vdev->base->queues || !vdev->base->vops)
+ return -1;
+
+ for (i = 0; i < vdev->nvqs; i++)
+ vhost_vq_deinit(&vdev->vqs[i]);
+
+ vhost_kernel_deinit(vdev);
+
+ return 0;
+}
+
+int
+vhost_dev_start(struct vhost_dev *vdev)
+{
+ struct vhost_vring_state state;
+ uint64_t features;
+ int i, rc;
+
+ if (vdev->started)
+ return 0;
+
+ /* sanity check */
+ if (!vdev->base || !vdev->base->queues || !vdev->base->vops) {
+ WPRINTF(("%s, virtio_base is not initialized\n", __func__));
+ goto fail;
+ }
+
+ if ((vdev->base->status & VIRTIO_CR_STATUS_DRIVER_OK) == 0) {
+ WPRINTF(("%s, status error 0x%x\n",
+ __func__, vdev->base->status));
+ goto fail;
+ }
+
+ rc = vhost_kernel_set_owner(vdev);
+ if (rc < 0) {
+ WPRINTF(("%s, vhost_set_owner failed\n", __func__));
+ goto fail;
+ }
+
+ /* set vhost features */
+ features = (vdev->base->negotiated_caps & vdev->vhost_features) |
+ vdev->backend_features;
+ rc = vhost_kernel_set_features(vdev, features);
+ if (rc < 0) {
+ WPRINTF(("%s, set_features failed\n", __func__));
+ goto fail;
+ }
+ DPRINTF(("%s, set_features: 0x%lx\n", __func__, features));
+
+ /* set memory table */
+ rc = vhost_set_mem_table(vdev);
+ if (rc < 0) {
+ WPRINTF(("%s, set_mem_table failed\n", __func__));
+ goto fail;
+ }
+
+ /* config busyloop timeout */
+ if (vdev->busyloop_timeout) {
+ state.num = vdev->busyloop_timeout;
+ for (i = 0; i < vdev->nvqs; i++) {
+ state.index = i;
+ rc = vhost_kernel_set_vring_busyloop_timeout(vdev,
+ &state);
+ if (rc < 0) {
+ WPRINTF(("%s, set_busyloop_timeout failed\n",
+ __func__));
+ goto fail;
+ }
+ }
+ }
+
+ /* start vhost virtqueue */
+ for (i = 0; i < vdev->nvqs; i++) {
+ rc = vhost_vq_start(vdev, i);
+ if (rc < 0)
+ goto fail_vq;
+ }
+
+ vdev->started = true;
+ return 0;
+
+fail_vq:
+ while (--i >= 0)
+ vhost_vq_stop(vdev, i);
+fail:
+ return -1;
+}
+
+int
+vhost_dev_stop(struct vhost_dev *vdev)
+{
+ int i, rc = 0;
+
+ for (i = 0; i < vdev->nvqs; i++)
+ vhost_vq_stop(vdev, i);
+
+ /* the following are done by this ioctl:
+ * 1) resources of the vhost dev are freed
+ * 2) vhost virtqueues are reset
+ */
+ rc = vhost_kernel_reset_device(vdev);
+ if (rc < 0) {
+ WPRINTF(("%s, vhost_reset_device failed\n", __func__));
+ rc = -1;
+ }
+
+ vdev->started = false;
+ return rc;
+}
+
+int
+vhost_net_set_backend(struct vhost_dev *vdev, int backend_fd)
+{
+ struct vhost_vring_file file;
+ int rc, i;
+
+ file.fd = backend_fd;
+ for (i = 0; i < vdev->nvqs; i++) {
+ file.index = i;
+ rc = vhost_kernel_net_set_backend(vdev, &file);
+ if (rc < 0)
+ goto fail;
+ }
+
+ return 0;
+fail:
+ file.fd = -1;
+ while (--i >= 0) {
+ file.index = i;
+ vhost_kernel_net_set_backend(vdev, &file);
+ }
+
+ return -1;
+}
diff --git a/devicemodel/include/vhost.h b/devicemodel/include/vhost.h
new file mode 100644
index 0000000..1d1c1c3
--- /dev/null
+++ b/devicemodel/include/vhost.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2018 Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __VHOST_H__
+#define __VHOST_H__
+
+#include "virtio.h"
+#include "mevent.h"
+
+struct vhost_vq {
+ int kick_fd; /**< fd of kick eventfd */
+ int call_fd; /**< fd of call eventfd */
+ int idx; /**< index of this vq in vhost dev */
+ struct mevent *mevp; /**< mevent for call eventfd */
+ struct vhost_dev *dev; /**< pointer to vhost_dev */
+};
+
+struct vhost_dev {
+ struct virtio_base *base;
+ /**< backpointer to virtio_base */
+ struct vhost_vq *vqs; /**< pointer to vhost_vq array */
+ int nvqs; /**< number of virtqueues */
+ int fd; /**< vhost chardev fd */
+ int vq_idx; /**< first vq's index in virtio_vq_info */
+ uint64_t vhost_features;
+ /**< vhost features subset */
+ uint64_t backend_features;
+ /**< vhost specific features */
+ uint32_t busyloop_timeout;
+ /**< vq busyloop timeout in us */
+ bool started; /**< whether vhost is started */
+};
+
+/**
+ * @brief vhost_dev initialization.
+ *
+ * This interface is called to initialize the vhost_dev. It must be called
+ * before the actual feature negoitiation with the guest OS starts.
+ *
+ * @param vdev Pointer to struct vhost_dev.
+ * @param base Pointer to struct virtio_base.
+ * @param fd fd of the vhost chardev.
+ * @param vq_idx The first virtqueue which would be used by this vhost dev.
+ * @param vhost_features Subset of vhost features which would be enabled.
+ * @param backend_features Specific vhost internal features to be enabled.
+ * @param busyloop_timeout Busy loop timeout in us.
+ *
+ * @return 0 on success and -1 on failure.
+ */
+int vhost_dev_init(struct vhost_dev *vdev, struct virtio_base *base, int fd,
+ int vq_idx, uint64_t vhost_features,
+ uint64_t backend_features, uint32_t busyloop_timeout);
+
+/**
+ * @brief vhost_dev cleanup.
+ *
+ * This interface is called to cleanup the vhost_dev.
+ *
+ * @param vdev Pointer to struct vhost_dev.
+ *
+ * @return 0 on success and -1 on failure.
+ */
+int vhost_dev_deinit(struct vhost_dev *vdev);
+
+/**
+ * @brief start vhost data plane.
+ *
+ * This interface is called to start the data plane in vhost.
+ *
+ * @param vdev Pointer to struct vhost_dev.
+ *
+ * @return 0 on success and -1 on failure.
+ */
+int vhost_dev_start(struct vhost_dev *vdev);
+
+/**
+ * @brief stop vhost data plane.
+ *
+ * This interface is called to stop the data plane in vhost.
+ *
+ * @param vdev Pointer to struct vhost_dev.
+ *
+ * @return 0 on success and -1 on failure.
+ */
+int vhost_dev_stop(struct vhost_dev *vdev);
+
+/**
+ * @brief set backend fd of vhost net.
+ *
+ * This interface is called to set the backend fd (for example tap fd)
+ * to vhost.
+ *
+ * @param vdev Pointer to struct vhost_dev.
+ * @param backend_fd fd of backend (for example tap fd).
+ *
+ * @return 0 on success and -1 on failure.
+ */
+int vhost_net_set_backend(struct vhost_dev *vdev, int backend_fd);
+
+#endif
--
2.17.1


[PATCH 3/7] dm: virtio: implement vhost_vq interfaces

Jian Jun Chen
 

vhost_vq related interfaces are implemented in this patch. They are
vhost_vq_init/vhost_vq_deinit/vhost_vq_start/vhost_vq_stop.

Signed-off-by: Jian Jun Chen <jian.jun.chen@...>
---
devicemodel/hw/pci/virtio/vhost.c | 258 +++++++++++++++++++++++++++++-
1 file changed, 253 insertions(+), 5 deletions(-)

diff --git a/devicemodel/hw/pci/virtio/vhost.c b/devicemodel/hw/pci/virtio/vhost.c
index 2c658af..f5b674a 100644
--- a/devicemodel/hw/pci/virtio/vhost.c
+++ b/devicemodel/hw/pci/virtio/vhost.c
@@ -42,6 +42,54 @@ vhost_kernel_deinit(struct vhost_dev *vdev)
/* to be implemented */
}

+static int
+vhost_kernel_set_vring_addr(struct vhost_dev *vdev,
+ struct vhost_vring_addr *addr)
+{
+ /* to be implemented */
+ return -1;
+}
+
+static int
+vhost_kernel_set_vring_num(struct vhost_dev *vdev,
+ struct vhost_vring_state *ring)
+{
+ /* to be implemented */
+ return -1;
+}
+
+static int
+vhost_kernel_set_vring_base(struct vhost_dev *vdev,
+ struct vhost_vring_state *ring)
+{
+ /* to be implemented */
+ return -1;
+}
+
+static int
+vhost_kernel_get_vring_base(struct vhost_dev *vdev,
+ struct vhost_vring_state *ring)
+{
+ /* to be implemented */
+ return -1;
+}
+
+static int
+vhost_kernel_set_vring_kick(struct vhost_dev *vdev,
+ struct vhost_vring_file *file)
+{
+ /* to be implemented */
+ return -1;
+}
+
+static int
+vhost_kernel_set_vring_call(struct vhost_dev *vdev,
+ struct vhost_vring_file *file)
+{
+ /* to be implemented */
+ return -1;
+}
+
static int
vhost_kernel_set_vring_busyloop_timeout(struct vhost_dev *vdev,
struct vhost_vring_state *s)
@@ -89,31 +137,231 @@ vhost_kernel_net_set_backend(struct vhost_dev *vdev,
}

static int
-vhost_vq_init(struct vhost_dev *vdev, int idx)
+vhost_eventfd_test_and_clear(int fd)
{
/* to be implemented */
return -1;
}

static int
-vhost_vq_deinit(struct vhost_vq *vq)
+vhost_vq_register_eventfd(struct vhost_dev *vdev,
+ int idx, bool is_register)
{
/* to be implemented */
return -1;
}

+static int
+vhost_vq_init(struct vhost_dev *vdev, int idx)
+{
+ struct vhost_vq *vq;
+ int rc;
+
+ if (!vdev || !vdev->vqs)
+ goto fail;
+
+ vq = &vdev->vqs[idx];
+ if (!vq)
+ goto fail;
+
+ rc = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
+ if (rc < 0) {
+ WPRINTF(("%s, create kick_fd failed\n", __func__));
+ goto fail;
+ }
+ vq->kick_fd = rc;
+
+ rc = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
+ if (rc < 0) {
+ WPRINTF(("%s, create call_fd failed\n", __func__));
+ goto fail_fd;
+ }
+ vq->call_fd = rc;
+
+ vq->idx = idx;
+ vq->dev = vdev;
+ return 0;
+
+fail_fd:
+ close(vq->kick_fd);
+ vq->kick_fd = -1;
+fail:
+ return -1;
+}
+
+static int
+vhost_vq_deinit(struct vhost_vq *vq)
+{
+ if (!vq)
+ return -1;
+
+ if (vq->call_fd > 0) {
+ close(vq->call_fd);
+ vq->call_fd = -1;
+ }
+
+ if (vq->kick_fd > 0) {
+ close(vq->kick_fd);
+ vq->kick_fd = -1;
+ }
+
+ return 0;
+}
+
static int
vhost_vq_start(struct vhost_dev *vdev, int idx)
{
- /* to be implemented */
+ struct vhost_vq *vq;
+ struct virtio_vq_info *vqi;
+ struct vhost_vring_state ring;
+ struct vhost_vring_addr addr;
+ struct vhost_vring_file file;
+ int rc, q_idx;
+
+ /* sanity check */
+ if (!vdev->base || !vdev->base->queues || !vdev->base->vops ||
+ !vdev->vqs) {
+ WPRINTF(("%s, vhost_dev is not initialized\n", __func__));
+ goto fail;
+ }
+
+ q_idx = idx + vdev->vq_idx;
+ if (q_idx >= vdev->base->vops->nvq) {
+ WPRINTF(("%s, invalid vq index: idx = %d, vq_idx = %d\n",
+ __func__, idx, vdev->vq_idx));
+ goto fail;
+ }
+ vqi = &vdev->base->queues[q_idx];
+ vq = &vdev->vqs[idx];
+
+ /* clear kick_fd and call_fd */
+ vhost_eventfd_test_and_clear(vq->kick_fd);
+ vhost_eventfd_test_and_clear(vq->call_fd);
+
+ /* register ioeventfd & irqfd */
+ rc = vhost_vq_register_eventfd(vdev, idx, true);
+ if (rc < 0) {
+ WPRINTF(("%s, register eventfd failed: idx = %d\n",
+ __func__, idx));
+ goto fail;
+ }
+
+ /* VHOST_SET_VRING_NUM */
+ ring.index = idx;
+ ring.num = vqi->qsize;
+ rc = vhost_kernel_set_vring_num(vdev, &ring);
+ if (rc < 0) {
+ WPRINTF(("%s, set_vring_num failed: idx = %d\n",
+ __func__, idx));
+ goto fail_vring;
+ }
+
+ /* VHOST_SET_VRING_BASE */
+ ring.num = vqi->last_avail;
+ rc = vhost_kernel_set_vring_base(vdev, &ring);
+ if (rc < 0) {
+ WPRINTF(("%s, set_vring_base failed: idx = %d,"
+ " last_avail = %d\n",
+ __func__, idx, vqi->last_avail));
+ goto fail_vring;
+ }
+
+ /* VHOST_SET_VRING_ADDR */
+ addr.index = idx;
+ addr.desc_user_addr = (uintptr_t)vqi->desc;
+ addr.avail_user_addr = (uintptr_t)vqi->avail;
+ addr.used_user_addr = (uintptr_t)vqi->used;
+ addr.log_guest_addr = (uintptr_t)NULL;
+ addr.flags = 0;
+ rc = vhost_kernel_set_vring_addr(vdev, &addr);
+ if (rc < 0) {
+ WPRINTF(("%s, set_vring_addr failed: idx = %d",
+ __func__, idx));
+ goto fail_vring;
+ }
+
+ /* VHOST_SET_VRING_CALL */
+ file.index = idx;
+ file.fd = vq->call_fd;
+ rc = vhost_kernel_set_vring_call(vdev, &file);
+ if (rc < 0) {
+ WPRINTF(("%s, set_vring_call failed\n", __func__));
+ goto fail_vring;
+ }
+
+ /* VHOST_SET_VRING_KICK */
+ file.index = idx;
+ file.fd = vq->kick_fd;
+ rc = vhost_kernel_set_vring_kick(vdev, &file);
+ if (rc < 0) {
+ WPRINTF(("%s, set_vring_kick failed: idx = %d",
+ __func__, idx));
+ goto fail_vring_kick;
+ }
+
+ return 0;
+
+fail_vring_kick:
+ file.index = idx;
+ file.fd = -1;
+ vhost_kernel_set_vring_call(vdev, &file);
+fail_vring:
+ vhost_vq_register_eventfd(vdev, idx, false);
+fail:
return -1;
}

static int
vhost_vq_stop(struct vhost_dev *vdev, int idx)
{
- /* to be implemented */
- return -1;
+ struct virtio_vq_info *vqi;
+ struct vhost_vring_file file;
+ struct vhost_vring_state ring;
+ int rc, q_idx;
+
+ /* sanity check */
+ if (!vdev->base || !vdev->base->queues || !vdev->base->vops ||
+ !vdev->vqs) {
+ WPRINTF(("%s, vhost_dev is not initialized\n", __func__));
+ return -1;
+ }
+
+ q_idx = idx + vdev->vq_idx;
+ if (q_idx >= vdev->base->vops->nvq) {
+ WPRINTF(("%s, invalid vq index: idx = %d, vq_idx = %d\n",
+ __func__, idx, vdev->vq_idx));
+ return -1;
+ }
+ vqi = &vdev->base->queues[q_idx];
+
+ file.index = idx;
+ file.fd = -1;
+
+ /* VHOST_SET_VRING_KICK */
+ vhost_kernel_set_vring_kick(vdev, &file);
+
+ /* VHOST_SET_VRING_CALL */
+ vhost_kernel_set_vring_call(vdev, &file);
+
+ /* VHOST_GET_VRING_BASE */
+ ring.index = idx;
+ rc = vhost_kernel_get_vring_base(vdev, &ring);
+ if (rc < 0)
+ WPRINTF(("%s, get_vring_base failed: idx = %d",
+ __func__, idx));
+ else
+ vqi->last_avail = ring.num;
+
+ /* update vqi->save_used */
+ vqi->save_used = vqi->used->idx;
+
+ /* unregister ioeventfd & irqfd */
+ rc = vhost_vq_register_eventfd(vdev, idx, false);
+ if (rc < 0)
+ WPRINTF(("%s, unregister eventfd failed: idx = %d\n",
+ __func__, idx));
+
+ return rc;
}

static int
--
2.17.1


[PATCH 1/7] dm: virtio: rename virtio ring structures and feature bits

Jian Jun Chen
 

Some virtio ring structures and virtio feature bits are using the
same name/definition as those in kernel header files. Kernel header
files must be included to perform ioctls to support vhost. There
are compiling errors due to duplicated definitions. In this patch
the following renamings are done:

VRING_DESC_F_NEXT -> VRING_DESC_FLAG_NEXT
VRING_DESC_F_WRITE -> VRING_DESC_FLAG_WRITE
VRING_DESC_F_INDIRECT -> VRING_DESC_FLAG_INDIRECT

VRING_AVAIL_F_NO_INTERRUPT -> VRING_AVAIL_FLAG_NO_INTERRUPT
VRING_USED_F_NO_NOTIFY -> VRING_USED_FLAG_NO_NOTIFY

VIRTIO_F_NOTIFY_ON_EMPTY -> VIRTIO_FLAG_NOTIFY_ON_EMPTY
VIRTIO_RING_F_INDIRECT_DESC -> VIRTIO_RING_FLAG_INDIRECT_DESC
VIRTIO_RING_F_EVENT_IDX -> VIRTIO_RING_FLAG_EVENT_IDX
VIRTIO_F_VERSION_1 -> VIRTIO_FLAG_VERSION_1

vring_avail -> virtio_vring_avail
vring_used -> virtio_vring_used
vring_size -> virtio_vring_size

Signed-off-by: Jian Jun Chen <jian.jun.chen@...>
---
devicemodel/hw/pci/virtio/virtio.c | 34 +++++++++++-----------
devicemodel/hw/pci/virtio/virtio_block.c | 8 ++---
devicemodel/hw/pci/virtio/virtio_console.c | 2 +-
devicemodel/hw/pci/virtio/virtio_heci.c | 12 ++++----
devicemodel/hw/pci/virtio/virtio_input.c | 2 +-
devicemodel/hw/pci/virtio/virtio_net.c | 10 +++----
devicemodel/include/virtio.h | 28 +++++++++---------
7 files changed, 48 insertions(+), 48 deletions(-)

diff --git a/devicemodel/hw/pci/virtio/virtio.c b/devicemodel/hw/pci/virtio/virtio.c
index 19458fe..ee6c4bd 100644
--- a/devicemodel/hw/pci/virtio/virtio.c
+++ b/devicemodel/hw/pci/virtio/virtio.c
@@ -193,7 +193,7 @@ virtio_vq_init(struct virtio_base *base, uint32_t pfn)
vq = &base->queues[base->curq];
vq->pfn = pfn;
phys = (uint64_t)pfn << VRING_PAGE_BITS;
- size = vring_size(vq->qsize);
+ size = virtio_vring_size(vq->qsize);
vb = paddr_guest2host(base->dev->vmctx, phys, size);

/* First page(s) are descriptors... */
@@ -201,14 +201,14 @@ virtio_vq_init(struct virtio_base *base, uint32_t pfn)
vb += vq->qsize * sizeof(struct virtio_desc);

/* ... immediately followed by "avail" ring (entirely uint16_t's) */
- vq->avail = (struct vring_avail *)vb;
+ vq->avail = (struct virtio_vring_avail *)vb;
vb += (2 + vq->qsize + 1) * sizeof(uint16_t);

/* Then it's rounded up to the next page... */
vb = (char *)roundup2((uintptr_t)vb, VRING_ALIGN);

/* ... and the last page(s) are the used ring. */
- vq->used = (struct vring_used *)vb;
+ vq->used = (struct virtio_vring_used *)vb;

/* Mark queue as allocated, and start at 0 when we use it. */
vq->flags = VQ_ALLOC;
@@ -244,13 +244,13 @@ virtio_vq_enable(struct virtio_base *base)
phys = (((uint64_t)vq->gpa_avail[1]) << 32) | vq->gpa_avail[0];
size = (2 + qsz + 1) * sizeof(uint16_t);
vb = paddr_guest2host(base->dev->vmctx, phys, size);
- vq->avail = (struct vring_avail *)vb;
+ vq->avail = (struct virtio_vring_avail *)vb;

/* used ring */
phys = (((uint64_t)vq->gpa_used[1]) << 32) | vq->gpa_used[0];
size = sizeof(uint16_t) * 3 + sizeof(struct virtio_used) * qsz;
vb = paddr_guest2host(base->dev->vmctx, phys, size);
- vq->used = (struct vring_used *)vb;
+ vq->used = (struct virtio_vring_used *)vb;

/* Mark queue as allocated, and start at 0 when we use it. */
vq->flags = VQ_ALLOC;
@@ -378,11 +378,11 @@ vq_getchain(struct virtio_vq_info *vq, uint16_t *pidx,
return -1;
}
vdir = &vq->desc[next];
- if ((vdir->flags & VRING_DESC_F_INDIRECT) == 0) {
+ if ((vdir->flags & VRING_DESC_FLAG_INDIRECT) == 0) {
_vq_record(i, vdir, ctx, iov, n_iov, flags);
i++;
} else if ((base->device_caps &
- VIRTIO_RING_F_INDIRECT_DESC) == 0) {
+ VIRTIO_RING_FLAG_INDIRECT_DESC) == 0) {
fprintf(stderr,
"%s: descriptor has forbidden INDIRECT flag, "
"driver confused?\r\n",
@@ -409,7 +409,7 @@ vq_getchain(struct virtio_vq_info *vq, uint16_t *pidx,
next = 0;
for (;;) {
vp = &vindir[next];
- if (vp->flags & VRING_DESC_F_INDIRECT) {
+ if (vp->flags & VRING_DESC_FLAG_INDIRECT) {
fprintf(stderr,
"%s: indirect desc has INDIR flag,"
" driver confused?\r\n",
@@ -419,7 +419,7 @@ vq_getchain(struct virtio_vq_info *vq, uint16_t *pidx,
_vq_record(i, vp, ctx, iov, n_iov, flags);
if (++i > VQ_MAX_DESCRIPTORS)
goto loopy;
- if ((vp->flags & VRING_DESC_F_NEXT) == 0)
+ if ((vp->flags & VRING_DESC_FLAG_NEXT) == 0)
break;
next = vp->next;
if (next >= n_indir) {
@@ -431,7 +431,7 @@ vq_getchain(struct virtio_vq_info *vq, uint16_t *pidx,
}
}
}
- if ((vdir->flags & VRING_DESC_F_NEXT) == 0)
+ if ((vdir->flags & VRING_DESC_FLAG_NEXT) == 0)
return i;
}
loopy:
@@ -464,7 +464,7 @@ void
vq_relchain(struct virtio_vq_info *vq, uint16_t idx, uint32_t iolen)
{
uint16_t uidx, mask;
- volatile struct vring_used *vuh;
+ volatile struct virtio_vring_used *vuh;
volatile struct virtio_used *vue;

/*
@@ -513,7 +513,7 @@ vq_endchains(struct virtio_vq_info *vq, int used_all_avail)
* Interrupt generation: if we're using EVENT_IDX,
* interrupt if we've crossed the event threshold.
* Otherwise interrupt is generated if we added "used" entries,
- * but suppressed by VRING_AVAIL_F_NO_INTERRUPT.
+ * but suppressed by VRING_AVAIL_FLAG_NO_INTERRUPT.
*
* In any case, though, if NOTIFY_ON_EMPTY is set and the
* entire avail was processed, we need to interrupt always.
@@ -522,9 +522,9 @@ vq_endchains(struct virtio_vq_info *vq, int used_all_avail)
old_idx = vq->save_used;
vq->save_used = new_idx = vq->used->idx;
if (used_all_avail &&
- (base->negotiated_caps & VIRTIO_F_NOTIFY_ON_EMPTY))
+ (base->negotiated_caps & VIRTIO_FLAG_NOTIFY_ON_EMPTY))
intr = 1;
- else if (base->negotiated_caps & VIRTIO_RING_F_EVENT_IDX) {
+ else if (base->negotiated_caps & VIRTIO_RING_FLAG_EVENT_IDX) {
event_idx = VQ_USED_EVENT_IDX(vq);
/*
* This calculation is per docs and the kernel
@@ -534,7 +534,7 @@ vq_endchains(struct virtio_vq_info *vq, int used_all_avail)
(uint16_t)(new_idx - old_idx);
} else {
intr = new_idx != old_idx &&
- !(vq->avail->flags & VRING_AVAIL_F_NO_INTERRUPT);
+ !(vq->avail->flags & VRING_AVAIL_FLAG_NO_INTERRUPT);
}
if (intr)
vq_interrupt(base, vq);
@@ -1020,7 +1020,7 @@ virtio_set_modern_bar(struct virtio_base *base, bool use_notify_pio)

vops = base->vops;

- if (!vops || (base->device_caps & VIRTIO_F_VERSION_1) == 0)
+ if (!vops || (base->device_caps & VIRTIO_FLAG_VERSION_1) == 0)
return -1;

if (use_notify_pio)
@@ -1036,7 +1036,7 @@ virtio_set_modern_bar(struct virtio_base *base, bool use_notify_pio)
void
virtio_dev_error(struct virtio_base *base)
{
- if (base->negotiated_caps & VIRTIO_F_VERSION_1) {
+ if (base->negotiated_caps & VIRTIO_FLAG_VERSION_1) {
/* see 2.1.2. if DRIVER_OK is set, need to send
* a device configuration change notification to the driver
*/
diff --git a/devicemodel/hw/pci/virtio/virtio_block.c b/devicemodel/hw/pci/virtio/virtio_block.c
index 0eed072..214b13d 100644
--- a/devicemodel/hw/pci/virtio/virtio_block.c
+++ b/devicemodel/hw/pci/virtio/virtio_block.c
@@ -64,7 +64,7 @@
(VIRTIO_BLK_F_SEG_MAX | \
VIRTIO_BLK_F_BLK_SIZE | \
VIRTIO_BLK_F_TOPOLOGY | \
- VIRTIO_RING_F_INDIRECT_DESC) /* indirect descriptors */
+ VIRTIO_RING_FLAG_INDIRECT_DESC) /* indirect descriptors */

/*
* Writeback cache bits
@@ -214,7 +214,7 @@ virtio_blk_proc(struct virtio_blk *blk, struct virtio_vq_info *vq)
assert(n >= 2 && n <= BLOCKIF_IOV_MAX + 2);

io = &blk->ios[idx];
- assert((flags[0] & VRING_DESC_F_WRITE) == 0);
+ assert((flags[0] & VRING_DESC_FLAG_WRITE) == 0);
assert(iov[0].iov_len == sizeof(struct virtio_blk_hdr));
vbh = iov[0].iov_base;
memcpy(&io->req.iov, &iov[1], sizeof(struct iovec) * (n - 2));
@@ -222,7 +222,7 @@ virtio_blk_proc(struct virtio_blk *blk, struct virtio_vq_info *vq)
io->req.offset = vbh->sector * DEV_BSIZE;
io->status = iov[--n].iov_base;
assert(iov[n].iov_len == 1);
- assert(flags[n] & VRING_DESC_F_WRITE);
+ assert(flags[n] & VRING_DESC_FLAG_WRITE);

/*
* XXX
@@ -240,7 +240,7 @@ virtio_blk_proc(struct virtio_blk *blk, struct virtio_vq_info *vq)
* therefore test the inverse of the descriptor bit
* to the op.
*/
- assert(((flags[i] & VRING_DESC_F_WRITE) == 0) == writeop);
+ assert(((flags[i] & VRING_DESC_FLAG_WRITE) == 0) == writeop);
iolen += iov[i].iov_len;
}
io->req.resid = iolen;
diff --git a/devicemodel/hw/pci/virtio/virtio_console.c b/devicemodel/hw/pci/virtio/virtio_console.c
index 52f77de..67f3000 100644
--- a/devicemodel/hw/pci/virtio/virtio_console.c
+++ b/devicemodel/hw/pci/virtio/virtio_console.c
@@ -409,7 +409,7 @@ virtio_console_notify_rx(void *vdev, struct virtio_vq_info *vq)

if (!port->rx_ready) {
port->rx_ready = 1;
- vq->used->flags |= VRING_USED_F_NO_NOTIFY;
+ vq->used->flags |= VRING_USED_FLAG_NO_NOTIFY;
}
}

diff --git a/devicemodel/hw/pci/virtio/virtio_heci.c b/devicemodel/hw/pci/virtio/virtio_heci.c
index e5af6fd..0f65bf3 100644
--- a/devicemodel/hw/pci/virtio/virtio_heci.c
+++ b/devicemodel/hw/pci/virtio/virtio_heci.c
@@ -972,7 +972,7 @@ static void *virtio_heci_tx_thread(void *param)
while (vheci->status != VHECI_DEINIT) {
/* note - tx mutex is locked here */
while (!vq_has_descs(vq)) {
- vq->used->flags &= ~VRING_USED_F_NO_NOTIFY;
+ vq->used->flags &= ~VRING_USED_FLAG_NO_NOTIFY;
mb();
if (vq_has_descs(vq) &&
vheci->status != VHECI_RESET)
@@ -984,7 +984,7 @@ static void *virtio_heci_tx_thread(void *param)
if (vheci->status == VHECI_DEINIT)
goto out;
}
- vq->used->flags |= VRING_USED_F_NO_NOTIFY;
+ vq->used->flags |= VRING_USED_FLAG_NO_NOTIFY;
pthread_mutex_unlock(&vheci->tx_mutex);

do {
@@ -1125,7 +1125,7 @@ static void *virtio_heci_rx_thread(void *param)
while (vheci->status != VHECI_DEINIT) {
/* note - rx mutex is locked here */
while (vq_ring_ready(vq)) {
- vq->used->flags &= ~VRING_USED_F_NO_NOTIFY;
+ vq->used->flags &= ~VRING_USED_FLAG_NO_NOTIFY;
mb();
if (vq_has_descs(vq) &&
vheci->rx_need_sched &&
@@ -1138,7 +1138,7 @@ static void *virtio_heci_rx_thread(void *param)
if (vheci->status == VHECI_DEINIT)
goto out;
}
- vq->used->flags |= VRING_USED_F_NO_NOTIFY;
+ vq->used->flags |= VRING_USED_FLAG_NO_NOTIFY;

do {
if (virtio_heci_proc_rx(vheci, vq))
@@ -1166,7 +1166,7 @@ virtio_heci_notify_rx(void *heci, struct virtio_vq_info *vq)
/* Signal the rx thread for processing */
pthread_mutex_lock(&vheci->rx_mutex);
DPRINTF(("vheci: RX: New IN buffer available!\n\r"));
- vq->used->flags |= VRING_USED_F_NO_NOTIFY;
+ vq->used->flags |= VRING_USED_FLAG_NO_NOTIFY;
pthread_cond_signal(&vheci->rx_cond);
pthread_mutex_unlock(&vheci->rx_mutex);
}
@@ -1184,7 +1184,7 @@ virtio_heci_notify_tx(void *heci, struct virtio_vq_info *vq)
/* Signal the tx thread for processing */
pthread_mutex_lock(&vheci->tx_mutex);
DPRINTF(("vheci: TX: New OUT buffer available!\n\r"));
- vq->used->flags |= VRING_USED_F_NO_NOTIFY;
+ vq->used->flags |= VRING_USED_FLAG_NO_NOTIFY;
pthread_cond_signal(&vheci->tx_cond);
pthread_mutex_unlock(&vheci->tx_mutex);
}
diff --git a/devicemodel/hw/pci/virtio/virtio_input.c b/devicemodel/hw/pci/virtio/virtio_input.c
index fa8476d..62fa319 100644
--- a/devicemodel/hw/pci/virtio/virtio_input.c
+++ b/devicemodel/hw/pci/virtio/virtio_input.c
@@ -47,7 +47,7 @@ static int virtio_input_debug;
/*
* Host capabilities
*/
-#define VIRTIO_INPUT_S_HOSTCAPS (VIRTIO_F_VERSION_1)
+#define VIRTIO_INPUT_S_HOSTCAPS (VIRTIO_FLAG_VERSION_1)

enum virtio_input_config_select {
VIRTIO_INPUT_CFG_UNSET = 0x00,
diff --git a/devicemodel/hw/pci/virtio/virtio_net.c b/devicemodel/hw/pci/virtio/virtio_net.c
index 2b5f94d..00a6d02 100644
--- a/devicemodel/hw/pci/virtio/virtio_net.c
+++ b/devicemodel/hw/pci/virtio/virtio_net.c
@@ -75,7 +75,7 @@

#define VIRTIO_NET_S_HOSTCAPS \
(VIRTIO_NET_F_MAC | VIRTIO_NET_F_MRG_RXBUF | VIRTIO_NET_F_STATUS | \
- VIRTIO_F_NOTIFY_ON_EMPTY | VIRTIO_RING_F_INDIRECT_DESC)
+ VIRTIO_FLAG_NOTIFY_ON_EMPTY | VIRTIO_RING_FLAG_INDIRECT_DESC)

/* is address mcast/bcast? */
#define ETHER_IS_MULTICAST(addr) (*(addr) & 0x01)
@@ -631,7 +631,7 @@ virtio_net_ping_rxq(void *vdev, struct virtio_vq_info *vq)
*/
if (net->rx_ready == 0) {
net->rx_ready = 1;
- vq->used->flags |= VRING_USED_F_NO_NOTIFY;
+ vq->used->flags |= VRING_USED_FLAG_NO_NOTIFY;
}
}

@@ -677,7 +677,7 @@ virtio_net_ping_txq(void *vdev, struct virtio_vq_info *vq)

/* Signal the tx thread for processing */
pthread_mutex_lock(&net->tx_mtx);
- vq->used->flags |= VRING_USED_F_NO_NOTIFY;
+ vq->used->flags |= VRING_USED_FLAG_NO_NOTIFY;
if (net->tx_in_progress == 0)
pthread_cond_signal(&net->tx_cond);
pthread_mutex_unlock(&net->tx_mtx);
@@ -711,7 +711,7 @@ virtio_net_tx_thread(void *param)
for (;;) {
/* note - tx mutex is locked here */
while (net->resetting || !vq_has_descs(vq)) {
- vq->used->flags &= ~VRING_USED_F_NO_NOTIFY;
+ vq->used->flags &= ~VRING_USED_FLAG_NO_NOTIFY;
/* memory barrier */
mb();
if (!net->resetting && vq_has_descs(vq))
@@ -726,7 +726,7 @@ virtio_net_tx_thread(void *param)
return NULL;
}
}
- vq->used->flags |= VRING_USED_F_NO_NOTIFY;
+ vq->used->flags |= VRING_USED_FLAG_NO_NOTIFY;
net->tx_in_progress = 1;
pthread_mutex_unlock(&net->tx_mtx);

diff --git a/devicemodel/include/virtio.h b/devicemodel/include/virtio.h
index ad02666..fe86729 100644
--- a/devicemodel/include/virtio.h
+++ b/devicemodel/include/virtio.h
@@ -137,9 +137,9 @@

#define VRING_ALIGN 4096

-#define VRING_DESC_F_NEXT (1 << 0)
-#define VRING_DESC_F_WRITE (1 << 1)
-#define VRING_DESC_F_INDIRECT (1 << 2)
+#define VRING_DESC_FLAG_NEXT (1 << 0)
+#define VRING_DESC_FLAG_WRITE (1 << 1)
+#define VRING_DESC_FLAG_INDIRECT (1 << 2)

struct virtio_desc { /* AKA vring_desc */
uint64_t addr; /* guest physical address */
@@ -153,17 +153,17 @@ struct virtio_used { /* AKA vring_used_elem */
uint32_t tlen; /* length written-to */
} __attribute__((packed));

-#define VRING_AVAIL_F_NO_INTERRUPT 1
+#define VRING_AVAIL_FLAG_NO_INTERRUPT 1

-struct vring_avail {
+struct virtio_vring_avail {
uint16_t flags; /* VRING_AVAIL_F_* */
uint16_t idx; /* counts to 65535, then cycles */
uint16_t ring[]; /* size N, reported in QNUM value */
/* uint16_t used_event; -- after N ring entries */
} __attribute__((packed));

-#define VRING_USED_F_NO_NOTIFY 1
-struct vring_used {
+#define VRING_USED_FLAG_NO_NOTIFY 1
+struct virtio_vring_used {
uint16_t flags; /* VRING_USED_F_* */
uint16_t idx; /* counts to 65535, then cycles */
struct virtio_used ring[];
@@ -310,12 +310,12 @@ struct vring_used {
* Feature flags.
* Note: bits 0 through 23 are reserved to each device type.
*/
-#define VIRTIO_F_NOTIFY_ON_EMPTY (1 << 24)
-#define VIRTIO_RING_F_INDIRECT_DESC (1 << 28)
-#define VIRTIO_RING_F_EVENT_IDX (1 << 29)
+#define VIRTIO_FLAG_NOTIFY_ON_EMPTY (1 << 24)
+#define VIRTIO_RING_FLAG_INDIRECT_DESC (1 << 28)
+#define VIRTIO_RING_FLAG_EVENT_IDX (1 << 29)

/* v1.0 compliant. */
-#define VIRTIO_F_VERSION_1 (1UL << 32)
+#define VIRTIO_FLAG_VERSION_1 (1UL << 32)

/* From section 2.3, "Virtqueue Configuration", of the virtio specification */
/**
@@ -327,7 +327,7 @@ struct vring_used {
* @return size of a certain virtqueue, in bytes.
*/
static inline size_t
-vring_size(u_int qsz)
+virtio_vring_size(u_int qsz)
{
size_t size;

@@ -594,9 +594,9 @@ struct virtio_vq_info {

volatile struct virtio_desc *desc;
/**< descriptor array */
- volatile struct vring_avail *avail;
+ volatile struct virtio_vring_avail *avail;
/**< the "avail" ring */
- volatile struct vring_used *used;
+ volatile struct virtio_vring_used *used;
/**< the "used" ring */

uint32_t gpa_desc[2]; /**< gpa of descriptors */
--
2.17.1


[PATCH 0/7] add vhost support in device model

Jian Jun Chen
 

This patchset implements the vhost proxy in device model. vhost proxy
acts as a framework in device model. It provides a set of unified
interfaces which can be used by virtio backend drivers in device model
to add their vhost support:
vhost_dev_init
vhost_dev_deinit
vhost_dev_start
vhost_dev_stop

vhost proxy is implemented based on the virtio framework and vhost char
dev. virtio device related information such as negotiated features and
guest memory map are conveyed to vhost in kernel. virtqueue related
information such as queue size, vring addresses and eventfd pair are
conveyed to vhost kernel as well. They are all done by ioctls of vhost
chardev.

vhost kernel interfaces to vhm thru eventfd. There are 2 eventfds for one
virtqueue, one is for kick and the other is for notify. eventfd used for
kick is associated with a PIO/MMIO region. eventfd used for notify is
associated with a MSIx/INTx. The eventfd pair is registered to VHM thru
VHM char dev.

vhost net is enabled in this patch as well which acts the first vhost
proxy client. It sets up an example about how to use the interfaces
provided by vhost proxy.

This patchset only covers the implementation of vhost proxy. ioeventfd is
implemented in VHM and will be another patchset.

Jian Jun Chen (7):
dm: virtio: rename virtio ring structures and feature bits
dm: virtio: add vhost support
dm: virtio: implement vhost_vq interfaces
dm: virtio: implement vhost_set_mem_table
dm: virtio: implement vhost_vq_register_eventfd
dm: virtio: implement vhost chardev interfaces
dm: virtio-net: add vhost net support

devicemodel/Makefile | 1 +
devicemodel/hw/pci/virtio/vhost.c | 786 +++++++++++++++++++++
devicemodel/hw/pci/virtio/virtio.c | 34 +-
devicemodel/hw/pci/virtio/virtio_block.c | 8 +-
devicemodel/hw/pci/virtio/virtio_console.c | 2 +-
devicemodel/hw/pci/virtio/virtio_heci.c | 12 +-
devicemodel/hw/pci/virtio/virtio_input.c | 2 +-
devicemodel/hw/pci/virtio/virtio_net.c | 237 ++++++-
devicemodel/include/vhost.h | 104 +++
devicemodel/include/virtio.h | 28 +-
10 files changed, 1150 insertions(+), 64 deletions(-)
create mode 100644 devicemodel/hw/pci/virtio/vhost.c
create mode 100644 devicemodel/include/vhost.h

--
2.17.1


[PATCH] HV: enlarge the CMA size for uos trusty

Liu, WeiX W
 

From: Wei Liu <weix.w.liu@...>

sometimes, there would be CMA allocate failue when doing cycle rebooting android uos.
as there are different CMA clients, and android trusty need 16M contiguous memory,
32M CMA size may make this failure easy to come out.
This patch is to enlarge the CMA sizeto 64M, which mitigate the failure.

Signed-off-by: Wei Liu <weix.w.liu@...>
Signed-off-by: Jason Chen CJ <jason.cj.chen@...>
---
devicemodel/samples/apl-mrb/sos_bootargs_debug.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/devicemodel/samples/apl-mrb/sos_bootargs_debug.txt b/devicemodel/samples/apl-mrb/sos_bootargs_debug.txt
index 1c0394a8..3500a90b 100644
--- a/devicemodel/samples/apl-mrb/sos_bootargs_debug.txt
+++ b/devicemodel/samples/apl-mrb/sos_bootargs_debug.txt
@@ -1 +1 @@
-pci_devices_ignore=(0:18:2) console=tty0 console=ttyS0 i915.nuclear_pageflip=1 root=/dev/mmcblk1p1 rw rootwait quiet loglevel=3 no_timer_check consoleblank=0 i915.enable_initial_modeset=1 i915.tsd_init=7 i915.tsd_delay=2000 video=DP-1:d video=DP-2:d i915.avail_planes_per_pipe=0x01010F i915.domain_plane_owners=0x011111110000 i915.enable_guc_loading=0 i915.enable_guc_submission=0 i915.enable_preemption=1 i915.context_priority_mode=2 i915.enable_gvt=1 i915.enable_guc=0 hvlog=2M@0x6de00000 reboot_panic=p,w cma=32M@0-
+pci_devices_ignore=(0:18:2) console=tty0 console=ttyS0 i915.nuclear_pageflip=1 root=/dev/mmcblk1p1 rw rootwait quiet loglevel=3 no_timer_check consoleblank=0 i915.enable_initial_modeset=1 i915.tsd_init=7 i915.tsd_delay=2000 video=DP-1:d video=DP-2:d i915.avail_planes_per_pipe=0x01010F i915.domain_plane_owners=0x011111110000 i915.enable_guc_loading=0 i915.enable_guc_submission=0 i915.enable_preemption=1 i915.context_priority_mode=2 i915.enable_gvt=1 i915.enable_guc=0 hvlog=2M@0x6de00000 reboot_panic=p,w cma=64M@0-
--
2.14.1


Re: Question to the patch of "samples: remove maxcpus from bootargs"

Chen, Jason CJ
 

On Fri, Aug 17, 2018 at 11:45:43AM +0800, 蔡玉龙(Cai.Yulong) wrote:
Hi Jason



I have a question for your patch committed on Jun 1 which remove the
maxcpus from kernel bootargs.



ACRN will start all physical CPUs before SOS boot up, and then recycle
the unexpected vcpu during VHM initialization, without maxcpus specified in the
kernel cmdline, SOS

will use all the vcpu assigned to it, are there any problem when recycle the
unexpected vcpu which is running a task in the SOS kernel?



As my test result, if I enable CONFIG_VM0_DESC SOS fails to boot up.
hi, yulong,

CONFIG_VM0_DESC will be removed in the future and will not be used.

Now SOS need do cpu offline for UOS cpus, please refer to below script in launch_uos.sh:

# offline SOS CPUs except BSP before launch UOS
for i in `ls -d /sys/devices/system/cpu/cpu[1-99]`; do
online=`cat $i/online`
idx=`echo $i | tr -cd "[1-99]"`
echo cpu$idx online=$online
if [ "$online" = "1" ]; then
echo 0 > $i/online
echo $idx > /sys/class/vhm/acrn_vhm/offline_cpu
fi
done




---------------------------------------------------------------------------------------

蔡玉龙 武汉海微科技有限公司

Yulong Cai Wuhan Highway Technology Corp.

武汉市东湖开发区武大园东路武大航域二区B3栋15楼

15F, Building B3, Zone 2, Hangyu, WHU Sci-Park, Wudayuan Road,

East Lake Hi-Tech Development Zone, Wuhan, Hubei, P.R.China

TEL: +86-(0)27-59905051 分机6194 FAX: +86-(0)27-59905055

Email: yulongc@... http://www.hwtc.com.cn/


--

Thanks

Jason


Re: [PATCH] hv: treewide: fix 'Struct/union not completely specified'

Shiqing Gao
 

On 8/17/2018 8:23 PM, Junjie Mao wrote:
Shiqing Gao <shiqing.gao@...> writes:

Remove the incomplete struct declarations.
These struct have been declared completely in other files.

Tracked-On: #861
Signed-off-by: Shiqing Gao <shiqing.gao@...>
---
hypervisor/include/arch/x86/guest/vlapic.h | 2 --
hypervisor/include/arch/x86/guest/vm.h | 1 -
hypervisor/include/arch/x86/vtd.h | 2 --
3 files changed, 5 deletions(-)

diff --git a/hypervisor/include/arch/x86/guest/vlapic.h b/hypervisor/include/arch/x86/guest/vlapic.h
index 548e482..16c4fb0 100644
--- a/hypervisor/include/arch/x86/guest/vlapic.h
+++ b/hypervisor/include/arch/x86/guest/vlapic.h
@@ -30,8 +30,6 @@
#ifndef _VLAPIC_H_
#define _VLAPIC_H_
-struct acrn_vlapic;
-
Simply droping it is not appropriate as it makes the following reference
to this tag unspecified (though it may work because the header where
acrn_vlapic is defined is always included before vlapic.h).

I was wondering why this issue is raised as it is common to declare a
struct without definition to hide the details (which is actually
recommended by MISRA C). Thus it looks more like false positive to me.
I see. Thanks for the explanation!

Will drop this patch.


Re: [RFC PATCH 0/2] simple level trigger interrupt handle

Eddie Dong
 

The problem is that if we send physical EOI without mask, the IOAPIC may have one more level triggered interrupt. How do you prevent that from happen?

Thx Eddie

-----Original Message-----
From: Li, Fei1
Sent: Thursday, August 16, 2018 6:57 PM
To: acrn-dev@...; Dong, Eddie <eddie.dong@...>;
Xu, Anthony <anthony.xu@...>; Chen, Jason CJ
<jason.cj.chen@...>; Yan, Like <like.yan@...>; Ren, Jack
<jack.ren@...>
Subject: [RFC PATCH 0/2] simple level trigger interrupt handle

This patch tries to simple the level trigger mode interrupt handle. For guest
ptdev interrupt, we don't need to mask or unmask the interrupt by ourself.
We could let the guest decide when should mask or unamsk the interrupt by
itself. If the guest uses handle_fasteoi_irq to handle the level trigger mode
interrupt, we may not need to mask and unmask the interrupt in hypervisor.

==============================================================
==================================================

For ptdev level interrupt, the previous process:

ACRN Hypervisor:
dispatch_interrupt ---> common_dev_handler_level
|
|
|
(1) GSI_MASK_IRQ
|
(2) send_lapic_eoi
|
(3) action(desc->irq, desc->priv_data) ---> inject the
interrupt to vlapic

Guest Kernel:
virtual interrupt injected ---> handle_fasteoi_irq
|
|
|
(1) handle_irq_event(desc);
|
(2) cond_unmask_eoi_irq(desc, chip); ---> eoi and vmexit


ACRN Hypervisor:
eoi and vmexit ---> veoi_vmexit_handler ---> vioapic_process_eoi --->
ptdev_intx_ack
|
|
|
GSI_UNMASK_IRQ(phys_irq);

==============================================================
==================================================

For ptdev level interrupt, current process:

ACRN Hypervisor:
dispatch_interrupt ---> common_dev_handler_level
|
|
|
(1) action(desc->irq, desc->priv_data) ---> inject the
interrupt to vlapic
|
(2) send_lapic_eoi

Guest Kernel:
virtual interrupt injected ---> handle_fasteoi_irq
|
|
|
(1) handle_irq_event(desc);
|
(2) cond_unmask_eoi_irq(desc, chip); ---> eoi and vmexit


ACRN Hypervisor:
eoi and vmexit ---> veoi_vmexit_handler ---> vioapic_process_eoi --->
ptdev_intx_ack
|
|
|

==============================================================
==================================================

Li, Fei1 (2):
hv: ptdev: simplify ptdev_intx_pin_remap logic
hv: irq: emulate fast eoi to handle level interrupt

hypervisor/arch/x86/assign.c | 55 ++----------------------------------
hypervisor/arch/x86/ioapic.c | 22 ---------------
hypervisor/arch/x86/irq.c | 24 ++++------------
hypervisor/include/arch/x86/ioapic.h | 3 --
4 files changed, 8 insertions(+), 96 deletions(-)

--
2.7.4


Re: [PATCH] hv: treewide: fix 'Struct/union not completely specified'

Junjie Mao
 

Shiqing Gao <shiqing.gao@...> writes:

Remove the incomplete struct declarations.
These struct have been declared completely in other files.

Tracked-On: #861
Signed-off-by: Shiqing Gao <shiqing.gao@...>
---
hypervisor/include/arch/x86/guest/vlapic.h | 2 --
hypervisor/include/arch/x86/guest/vm.h | 1 -
hypervisor/include/arch/x86/vtd.h | 2 --
3 files changed, 5 deletions(-)

diff --git a/hypervisor/include/arch/x86/guest/vlapic.h b/hypervisor/include/arch/x86/guest/vlapic.h
index 548e482..16c4fb0 100644
--- a/hypervisor/include/arch/x86/guest/vlapic.h
+++ b/hypervisor/include/arch/x86/guest/vlapic.h
@@ -30,8 +30,6 @@
#ifndef _VLAPIC_H_
#define _VLAPIC_H_

-struct acrn_vlapic;
-
Simply droping it is not appropriate as it makes the following reference
to this tag unspecified (though it may work because the header where
acrn_vlapic is defined is always included before vlapic.h).

I was wondering why this issue is raised as it is common to declare a
struct without definition to hide the details (which is actually
recommended by MISRA C). Thus it looks more like false positive to me.

--
Best Regards
Junjie Mao

/* APIC write handlers */
void vlapic_set_cr8(struct acrn_vlapic *vlapic, uint64_t val);
uint64_t vlapic_get_cr8(struct acrn_vlapic *vlapic);
diff --git a/hypervisor/include/arch/x86/guest/vm.h b/hypervisor/include/arch/x86/guest/vm.h
index 6822c1f..d7215dd 100644
--- a/hypervisor/include/arch/x86/guest/vm.h
+++ b/hypervisor/include/arch/x86/guest/vm.h
@@ -125,7 +125,6 @@ struct vcpuid_entry {
uint32_t padding;
};

-struct acrn_vpic;
struct vm {
uint16_t vm_id; /* Virtual machine identifier */
struct vm_hw_info hw; /* Reference to this VM's HW information */
diff --git a/hypervisor/include/arch/x86/vtd.h b/hypervisor/include/arch/x86/vtd.h
index 981ba7a..8af3991 100644
--- a/hypervisor/include/arch/x86/vtd.h
+++ b/hypervisor/include/arch/x86/vtd.h
@@ -465,8 +465,6 @@ struct dmar_info {

extern struct dmar_info *get_dmar_info(void);

-struct iommu_domain;
-
/* Assign a device specified by bus & devfun to a iommu domain */
int assign_iommu_device(struct iommu_domain *domain,
uint8_t bus, uint8_t devfun);


Re: [PATCH] hv:fixed several return value violations

Junjie Mao
 

Mingqiang Chi <mingqiang.chi@...> writes:

From: Mingqiang Chi <mingqiang.chi@...>

-- Add error-printing when add_timer failed
-- add (void) before several functions(memset/memcpy/
vcpu_get_xxx)

Signed-off-by: Mingqiang Chi <mingqiang.chi@...>
---
hypervisor/arch/x86/guest/vlapic.c | 14 +++++++++++---
hypervisor/arch/x86/irq.c | 2 +-
hypervisor/arch/x86/timer.c | 4 +++-
hypervisor/arch/x86/trusty.c | 14 +++++++-------
hypervisor/boot/reloc.c | 2 +-
hypervisor/boot/sbl/multiboot.c | 4 ++--
hypervisor/debug/shell.c | 5 +++--
7 files changed, 28 insertions(+), 17 deletions(-)

diff --git a/hypervisor/arch/x86/guest/vlapic.c b/hypervisor/arch/x86/guest/vlapic.c
index 5dc505b..842b13c 100644
--- a/hypervisor/arch/x86/guest/vlapic.c
+++ b/hypervisor/arch/x86/guest/vlapic.c
@@ -394,7 +394,9 @@ static void vlapic_icrtmr_write_handler(struct acrn_vlapic *vlapic)

del_timer(&vtimer->timer);
if (set_expiration(vlapic)) {
- add_timer(&vtimer->timer);
+ if (add_timer(&vtimer->timer) != 0) {
+ pr_err("%s:add timer failed", __func__);
+ }
add_timer returns an error only when:

1. the paramter is NULL (which should not be the case here)

2. timer->func is NULL (not sure if this can happen since
vlapic_create_timer() shall be called before the function above can
happen.

3. timer->fire_tsc is 0, which is impractical if rdtsc() properly does
its work.

If we consider the above cases, I was wondering whether a log is
sufficient. We can either design a proper handling for that, or assume
add_timer() shall succeed given the following constraints:

1. Only after vlapic_create_timer() is called can
vlapic_icrtmr_write_handler() be called, and

2. the hypervisor is not responsible for detecting or mitigating
abnomaly of the rdtsc instruction.

Need more comments on this.

}
}

@@ -431,7 +433,9 @@ static void vlapic_set_tsc_deadline_msr(struct acrn_vlapic *vlapic,
val -= exec_vmread64(VMX_TSC_OFFSET_FULL);
timer->fire_tsc = val;

- add_timer(timer);
+ if (add_timer(timer) != 0) {
+ pr_err("%s:add timer failed", __func__);
+ }
} else {
timer->fire_tsc = 0UL;
}
@@ -1311,7 +1315,11 @@ vlapic_svr_write_handler(struct acrn_vlapic *vlapic)
dev_dbg(ACRN_DBG_LAPIC, "vlapic is software-enabled");
if (vlapic_lvtt_period(vlapic)) {
if (set_expiration(vlapic)) {
- add_timer(&vlapic->vtimer.timer);
+ if (add_timer(&vlapic->vtimer.timer)
+ != 0) {
+ pr_err("%s:add timer failed",
+ __func__);
+ }
}
}
}
diff --git a/hypervisor/arch/x86/irq.c b/hypervisor/arch/x86/irq.c
index 464b131..f574afc 100644
--- a/hypervisor/arch/x86/irq.c
+++ b/hypervisor/arch/x86/irq.c
@@ -571,7 +571,7 @@ void free_irq(uint32_t irq)

desc->action = NULL;
desc->priv_data = NULL;
- memset(desc->name, '\0', 32U);
+ (void)memset(desc->name, '\0', 32U);

spinlock_irqrestore_release(&desc->irq_lock, rflags);
irq_desc_try_free_vector(desc->irq);
diff --git a/hypervisor/arch/x86/timer.c b/hypervisor/arch/x86/timer.c
index ce23479..6cf4d12 100644
--- a/hypervisor/arch/x86/timer.c
+++ b/hypervisor/arch/x86/timer.c
@@ -17,7 +17,9 @@ static void run_timer(struct hv_timer *timer)
{
/* deadline = 0 means stop timer, we should skip */
if ((timer->func != NULL) && (timer->fire_tsc != 0UL)) {
- timer->func(timer->priv_data);
+ if (timer->func(timer->priv_data) != 0) {
+ pr_err("Timer handler return error");
+ }
}

TRACE_2L(TRACE_TIMER_ACTION_PCKUP, timer->fire_tsc, 0UL);
diff --git a/hypervisor/arch/x86/trusty.c b/hypervisor/arch/x86/trusty.c
index e410f82..cabef15 100644
--- a/hypervisor/arch/x86/trusty.c
+++ b/hypervisor/arch/x86/trusty.c
@@ -210,10 +210,10 @@ void destroy_secure_world(struct vm *vm, bool need_clr_mem)
static void save_world_ctx(struct vcpu *vcpu, struct ext_context *ext_ctx)
{
/* cache on-demand run_context for efer/rflags/rsp/rip */
- vcpu_get_efer(vcpu);
- vcpu_get_rflags(vcpu);
- vcpu_get_rsp(vcpu);
- vcpu_get_rip(vcpu);
+ (void)vcpu_get_efer(vcpu);
+ (void)vcpu_get_rflags(vcpu);
+ (void)vcpu_get_rsp(vcpu);
+ (void)vcpu_get_rip(vcpu);

/* VMCS GUEST field */
ext_ctx->vmx_cr0 = exec_vmread(VMX_GUEST_CR0);
@@ -426,7 +426,7 @@ bool initialize_trusty(struct vcpu *vcpu, uint64_t param)
struct vm *vm = vcpu->vm;
struct trusty_boot_param boot_param;

- memset(&boot_param, 0U, sizeof(boot_param));
+ (void)memset(&boot_param, 0U, sizeof(boot_param));
if (copy_from_gpa(vcpu->vm, &boot_param, param, sizeof(boot_param))) {
pr_err("%s: Unable to copy trusty_boot_param\n", __func__);
return false;
@@ -497,7 +497,7 @@ void trusty_set_dseed(void *dseed, uint8_t dseed_num)

void save_sworld_context(struct vcpu *vcpu)
{
- memcpy_s(&vcpu->vm->sworld_snapshot,
+ (void)memcpy_s(&vcpu->vm->sworld_snapshot,
sizeof(struct cpu_context),
&vcpu->arch_vcpu.contexts[SECURE_WORLD],
sizeof(struct cpu_context));
@@ -513,7 +513,7 @@ void restore_sworld_context(struct vcpu *vcpu)
sworld_ctl->sworld_memory.length,
TRUSTY_EPT_REBASE_GPA);

- memcpy_s(&vcpu->arch_vcpu.contexts[SECURE_WORLD],
+ (void)memcpy_s(&vcpu->arch_vcpu.contexts[SECURE_WORLD],
sizeof(struct cpu_context),
&vcpu->vm->sworld_snapshot,
sizeof(struct cpu_context));
diff --git a/hypervisor/boot/reloc.c b/hypervisor/boot/reloc.c
index 6ff1b0a..b5429a4 100644
--- a/hypervisor/boot/reloc.c
+++ b/hypervisor/boot/reloc.c
@@ -219,7 +219,7 @@ uint64_t prepare_trampoline(void)
pr_dbg("trampoline code: %llx size %x", dest_pa, size);

/* Copy segment for AP initialization code below 1MB */
- memcpy_s(HPA2HVA(dest_pa), (size_t)size, &_ld_trampoline_load,
+ (void)memcpy_s(HPA2HVA(dest_pa), (size_t)size, &_ld_trampoline_load,
(size_t)size);
update_trampoline_code_refs(dest_pa);
trampoline_start16_paddr = dest_pa;
diff --git a/hypervisor/boot/sbl/multiboot.c b/hypervisor/boot/sbl/multiboot.c
index 63b3e49..9fab2fc 100644
--- a/hypervisor/boot/sbl/multiboot.c
+++ b/hypervisor/boot/sbl/multiboot.c
@@ -177,7 +177,7 @@ static void *parse_image_boot_params(struct vm *vm, char *cmdline)
*/
arg_end = strchr(arg, ' ');
len = arg_end ? (uint32_t)(arg_end - arg) : strnlen_s(arg, MEM_2K);
- memset(arg, ' ', len);
+ (void)memset(arg, ' ', len);

return (void *)boot_params;

@@ -297,7 +297,7 @@ int init_vm_boot_info(struct vm *vm)
* kernel cmdline
*/
if (boot_params_addr != NULL) {
- memset(buf, 0U, sizeof(buf));
+ (void)memset(buf, 0U, sizeof(buf));
snprintf(buf, MAX_BOOT_PARAMS_LEN, "%s0x%X ",
boot_params_arg,
HVA2GPA(vm, (uint64_t)boot_params_addr));
diff --git a/hypervisor/debug/shell.c b/hypervisor/debug/shell.c
index c6fba75..58f30ee 100644
--- a/hypervisor/debug/shell.c
+++ b/hypervisor/debug/shell.c
@@ -813,18 +813,19 @@ static int shell_show_vioapic_info(int argc, char **argv)

static int shell_show_ioapic_info(__unused int argc, __unused char **argv)
{
+ int err = 0;
char *temp_str = alloc_pages(2U);

if (temp_str == NULL) {
return -ENOMEM;
}

- get_ioapic_info(temp_str, 2 * CPU_PAGE_SIZE);
+ err = get_ioapic_info(temp_str, 2 * CPU_PAGE_SIZE);
shell_puts(temp_str);

free(temp_str);

- return 0;
+ return err;
}

static int shell_show_vmexit_profile(__unused int argc, __unused char **argv)


Question to the patch of "samples: remove maxcpus from bootargs"

Cai Yulong
 

Hi  Jason

      

       I have a question for your patch committed on Jun 1 which remove the maxcpus from kernel bootargs.

 

       ACRN will start all physical CPUs before SOS boot up, and then recycle the unexpected vcpu during VHM initialization, without maxcpus specified in the kernel cmdline, SOS

will use all the vcpu assigned to it, are there any problem when recycle the unexpected vcpu which is running a task in the SOS kernel?

 

     As my test result, if I enable CONFIG_VM0_DESC SOS fails to boot up.

 

---------------------------------------------------------------------------------------

蔡玉龙   武汉海微科技有限公司

Yulong Cai  Wuhan Highway Technology Corp.

          武汉市东湖开发区武大园东路武大航域二区B315

           15F, Building B3, Zone 2, Hangyu, WHU Sci-Park, Wudayuan Road,

           East Lake Hi-Tech Development Zone, Wuhan, Hubei, P.R.China

           TEL: +86-(0)27-59905051 分机6194        FAX: +86-(0)27-59905055

           Email: yulongc@...     http://www.hwtc.com.cn/

 


[PATCH] hv: treewide: fix 'Struct/union not completely specified'

Shiqing Gao
 

Remove the incomplete struct declarations.
These struct have been declared completely in other files.

Tracked-On: #861
Signed-off-by: Shiqing Gao <shiqing.gao@...>
---
hypervisor/include/arch/x86/guest/vlapic.h | 2 --
hypervisor/include/arch/x86/guest/vm.h | 1 -
hypervisor/include/arch/x86/vtd.h | 2 --
3 files changed, 5 deletions(-)

diff --git a/hypervisor/include/arch/x86/guest/vlapic.h b/hypervisor/include/arch/x86/guest/vlapic.h
index 548e482..16c4fb0 100644
--- a/hypervisor/include/arch/x86/guest/vlapic.h
+++ b/hypervisor/include/arch/x86/guest/vlapic.h
@@ -30,8 +30,6 @@
#ifndef _VLAPIC_H_
#define _VLAPIC_H_

-struct acrn_vlapic;
-
/* APIC write handlers */
void vlapic_set_cr8(struct acrn_vlapic *vlapic, uint64_t val);
uint64_t vlapic_get_cr8(struct acrn_vlapic *vlapic);
diff --git a/hypervisor/include/arch/x86/guest/vm.h b/hypervisor/include/arch/x86/guest/vm.h
index 6822c1f..d7215dd 100644
--- a/hypervisor/include/arch/x86/guest/vm.h
+++ b/hypervisor/include/arch/x86/guest/vm.h
@@ -125,7 +125,6 @@ struct vcpuid_entry {
uint32_t padding;
};

-struct acrn_vpic;
struct vm {
uint16_t vm_id; /* Virtual machine identifier */
struct vm_hw_info hw; /* Reference to this VM's HW information */
diff --git a/hypervisor/include/arch/x86/vtd.h b/hypervisor/include/arch/x86/vtd.h
index 981ba7a..8af3991 100644
--- a/hypervisor/include/arch/x86/vtd.h
+++ b/hypervisor/include/arch/x86/vtd.h
@@ -465,8 +465,6 @@ struct dmar_info {

extern struct dmar_info *get_dmar_info(void);

-struct iommu_domain;
-
/* Assign a device specified by bus & devfun to a iommu domain */
int assign_iommu_device(struct iommu_domain *domain,
uint8_t bus, uint8_t devfun);
--
1.9.1


Re: [PATCH] hv: lib: add find_first_zero_bit

Li, Fei1
 

On Fri, Aug 17, 2018 at 09:28:22AM +0800, Yan, Like wrote:
On Fri, Aug 17, 2018 at 08:42:16AM +0800, Li, Fei1 wrote:
On Thu, Aug 16, 2018 at 08:07:41PM +0000, Xu, Anthony wrote:
Hi Fei,

Can you send this patch out with other patches which use this function?
I think Like may need this patch to allocate number and vector for irq.
Thanks.
Yes.
I was expecting a shorter name for this func, like ffz() or ffz_ex().
OK.


Thanks,
Like



Anthony

-----Original Message-----
From: acrn-dev@... [mailto:acrn-dev@...]
On Behalf Of Li, Fei1
Sent: Thursday, August 16, 2018 8:34 AM
To: acrn-dev@...; Dong, Eddie <eddie.dong@...>; Yan,
Like <like.yan@...>
Subject: [acrn-dev] [PATCH] hv: lib: add find_first_zero_bit

Add find_first_zero_bit to find the first zero bit in a uint64_t array.
Note: the API is lockless.

Signed-off-by: Li, Fei1 <fei1.li@...>
---
hypervisor/include/lib/bits.h | 15 +++++++++++++++
1 file changed, 15 insertions(+)

diff --git a/hypervisor/include/lib/bits.h b/hypervisor/include/lib/bits.h
index ea0e8a1..15263cc 100644
--- a/hypervisor/include/lib/bits.h
+++ b/hypervisor/include/lib/bits.h
@@ -30,6 +30,9 @@
#ifndef BITS_H
#define BITS_H
#include <cpu.h>
+
+#define BITS_PER_LONG 64UL
+
/**
*
* INVALID_BIT_INDEX means when input paramter is zero,
@@ -169,6 +172,18 @@ static inline uint16_t clz64(uint64_t value)
}
}

+static inline uint64_t find_first_zero_bit(const uint64_t *addr, uint64_t size)
+{
+ uint64_t idx;
+
+ for (idx = 0; idx * BITS_PER_LONG < size; idx++) {
+ if (addr[idx] != ~0UL)
+ return min(idx * BITS_PER_LONG + ffz64(addr[idx]),
size);
+ }
+
+ return size;
+}
+
/*
* (*addr) |= (1UL<<nr);
* Note:Input parameter nr shall be less than 64.
--
2.7.4