From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51126) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1a9ce9-00019L-7g for qemu-devel@nongnu.org; Thu, 17 Dec 2015 12:47:22 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1a9ce5-0006s6-3l for qemu-devel@nongnu.org; Thu, 17 Dec 2015 12:47:21 -0500 Received: from mx1.redhat.com ([209.132.183.28]:60011) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1a9ce4-0006rp-QZ for qemu-devel@nongnu.org; Thu, 17 Dec 2015 12:47:17 -0500 From: Paolo Bonzini Date: Thu, 17 Dec 2015 18:46:12 +0100 Message-Id: <1450374401-31352-17-git-send-email-pbonzini@redhat.com> In-Reply-To: <1450374401-31352-1-git-send-email-pbonzini@redhat.com> References: <1450374401-31352-1-git-send-email-pbonzini@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Subject: [Qemu-devel] [PULL 16/45] hw/misc: Hyper-V test device 'hyperv-testdev' List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Eduardo Habkost , kvm@vger.kernel.org, Marcelo Tosatti , Roman Kagan , Andrey Smetanin , "Denis V. Lunev" , =?UTF-8?q?Andreas=20F=C3=A4rber?= , Richard Henderson From: Andrey Smetanin 'hyperv-testdev' will be used by kvm-unit-tests to setup Hyper-V SynIC SINT's routing and to inject Hyper-V SynIC SINT's. Hyper-V test device is ISA type device that creates 0x3000 IO memory region and catches write access into it. Every write operation data decoded into ctl code and parameters for Hyper-V test device. Signed-off-by: Andrey Smetanin Reviewed-by: Roman Kagan Signed-off-by: Denis V. Lunev CC: Paolo Bonzini CC: Richard Henderson CC: Eduardo Habkost CC: "Andreas F=C3=A4rber" CC: Marcelo Tosatti CC: Roman Kagan CC: Denis V. Lunev CC: kvm@vger.kernel.org Signed-off-by: Paolo Bonzini --- default-configs/i386-softmmu.mak | 1 + default-configs/x86_64-softmmu.mak | 1 + hw/misc/Makefile.objs | 1 + hw/misc/hyperv_testdev.c | 167 +++++++++++++++++++++++++++++++= ++++++ 4 files changed, 170 insertions(+) create mode 100644 hw/misc/hyperv_testdev.c diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-soft= mmu.mak index 43c96d1..57ccff3 100644 --- a/default-configs/i386-softmmu.mak +++ b/default-configs/i386-softmmu.mak @@ -50,3 +50,4 @@ CONFIG_XIO3130=3Dy CONFIG_IOH3420=3Dy CONFIG_I82801B11=3Dy CONFIG_SMBIOS=3Dy +CONFIG_HYPERV_TESTDEV=3D$(CONFIG_KVM) diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-= softmmu.mak index dfb8095..30f5e75 100644 --- a/default-configs/x86_64-softmmu.mak +++ b/default-configs/x86_64-softmmu.mak @@ -50,3 +50,4 @@ CONFIG_XIO3130=3Dy CONFIG_IOH3420=3Dy CONFIG_I82801B11=3Dy CONFIG_SMBIOS=3Dy +CONFIG_HYPERV_TESTDEV=3D$(CONFIG_KVM) diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index 8a235df..d4765c2 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -43,3 +43,4 @@ obj-$(CONFIG_STM32F2XX_SYSCFG) +=3D stm32f2xx_syscfg.o =20 obj-$(CONFIG_PVPANIC) +=3D pvpanic.o obj-$(CONFIG_EDU) +=3D edu.o +obj-$(CONFIG_HYPERV_TESTDEV) +=3D hyperv_testdev.o diff --git a/hw/misc/hyperv_testdev.c b/hw/misc/hyperv_testdev.c new file mode 100644 index 0000000..d88844a --- /dev/null +++ b/hw/misc/hyperv_testdev.c @@ -0,0 +1,167 @@ +/* + * QEMU KVM Hyper-V test device to support Hyper-V kvm-unit-tests + * + * Copyright (C) 2015 Andrey Smetanin + * + * Authors: + * Andrey Smetanin + * + * This work is licensed under the terms of the GNU GPL, version 2 or la= ter. + * See the COPYING file in the top-level directory. + * + */ + +#include "hw/hw.h" +#include "hw/qdev.h" +#include "hw/isa/isa.h" +#include "sysemu/kvm.h" +#include "linux/kvm.h" +#include "target-i386/hyperv.h" +#include "kvm_i386.h" + +#define HV_TEST_DEV_MAX_SINT_ROUTES 64 + +struct HypervTestDev { + ISADevice parent_obj; + MemoryRegion sint_control; + HvSintRoute *sint_route[HV_TEST_DEV_MAX_SINT_ROUTES]; +}; +typedef struct HypervTestDev HypervTestDev; + +#define TYPE_HYPERV_TEST_DEV "hyperv-testdev" +#define HYPERV_TEST_DEV(obj) \ + OBJECT_CHECK(HypervTestDev, (obj), TYPE_HYPERV_TEST_DEV) + +enum { + HV_TEST_DEV_SINT_ROUTE_CREATE =3D 1, + HV_TEST_DEV_SINT_ROUTE_DESTROY, + HV_TEST_DEV_SINT_ROUTE_SET_SINT +}; + +static int alloc_sint_route_index(HypervTestDev *dev) +{ + int i; + + for (i =3D 0; i < ARRAY_SIZE(dev->sint_route); i++) { + if (dev->sint_route[i] =3D=3D NULL) { + return i; + } + } + return -1; +} + +static void free_sint_route_index(HypervTestDev *dev, int i) +{ + assert(i >=3D 0 && i < ARRAY_SIZE(dev->sint_route)); + dev->sint_route[i] =3D NULL; +} + +static int find_sint_route_index(HypervTestDev *dev, uint32_t vcpu_id, + uint32_t sint) +{ + HvSintRoute *sint_route; + int i; + + for (i =3D 0; i < ARRAY_SIZE(dev->sint_route); i++) { + sint_route =3D dev->sint_route[i]; + if (sint_route && sint_route->vcpu_id =3D=3D vcpu_id && + sint_route->sint =3D=3D sint) { + return i; + } + } + return -1; +} + +static void hv_synic_test_dev_control(HypervTestDev *dev, uint32_t ctl, + uint32_t vcpu_id, uint32_t sint) +{ + int i; + HvSintRoute *sint_route; + + switch (ctl) { + case HV_TEST_DEV_SINT_ROUTE_CREATE: + i =3D alloc_sint_route_index(dev); + assert(i >=3D 0); + sint_route =3D kvm_hv_sint_route_create(vcpu_id, sint, NULL); + assert(sint_route); + dev->sint_route[i] =3D sint_route; + break; + case HV_TEST_DEV_SINT_ROUTE_DESTROY: + i =3D find_sint_route_index(dev, vcpu_id, sint); + assert(i >=3D 0); + sint_route =3D dev->sint_route[i]; + kvm_hv_sint_route_destroy(sint_route); + free_sint_route_index(dev, i); + break; + case HV_TEST_DEV_SINT_ROUTE_SET_SINT: + i =3D find_sint_route_index(dev, vcpu_id, sint); + assert(i >=3D 0); + sint_route =3D dev->sint_route[i]; + kvm_hv_sint_route_set_sint(sint_route); + break; + default: + break; + } +} + +static void hv_test_dev_control(void *opaque, hwaddr addr, uint64_t data= , + uint32_t len) +{ + HypervTestDev *dev =3D HYPERV_TEST_DEV(opaque); + uint8_t ctl; + + ctl =3D (data >> 16ULL) & 0xFF; + switch (ctl) { + case HV_TEST_DEV_SINT_ROUTE_CREATE: + case HV_TEST_DEV_SINT_ROUTE_DESTROY: + case HV_TEST_DEV_SINT_ROUTE_SET_SINT: { + uint8_t sint =3D data & 0xFF; + uint8_t vcpu_id =3D (data >> 8ULL) & 0xFF; + hv_synic_test_dev_control(dev, ctl, vcpu_id, sint); + break; + } + default: + break; + } +} + +static const MemoryRegionOps synic_test_sint_ops =3D { + .write =3D hv_test_dev_control, + .valid.min_access_size =3D 4, + .valid.max_access_size =3D 4, + .endianness =3D DEVICE_LITTLE_ENDIAN, +}; + +static void hv_test_dev_realizefn(DeviceState *d, Error **errp) +{ + ISADevice *isa =3D ISA_DEVICE(d); + HypervTestDev *dev =3D HYPERV_TEST_DEV(d); + MemoryRegion *io =3D isa_address_space_io(isa); + + memset(dev->sint_route, 0, sizeof(dev->sint_route)); + memory_region_init_io(&dev->sint_control, OBJECT(dev), + &synic_test_sint_ops, dev, + "hyperv-testdev-ctl", 4); + memory_region_add_subregion(io, 0x3000, &dev->sint_control); +} + +static void hv_test_dev_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + set_bit(DEVICE_CATEGORY_MISC, dc->categories); + dc->realize =3D hv_test_dev_realizefn; +} + +static const TypeInfo hv_test_dev_info =3D { + .name =3D TYPE_HYPERV_TEST_DEV, + .parent =3D TYPE_ISA_DEVICE, + .instance_size =3D sizeof(HypervTestDev), + .class_init =3D hv_test_dev_class_init, +}; + +static void hv_test_dev_register_types(void) +{ + type_register_static(&hv_test_dev_info); +} +type_init(hv_test_dev_register_types); --=20 2.5.0