From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50033) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bViTN-0000CH-3p for qemu-devel@nongnu.org; Fri, 05 Aug 2016 12:59:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bViTK-000341-NE for qemu-devel@nongnu.org; Fri, 05 Aug 2016 12:59:48 -0400 Received: from roura.ac.upc.edu ([147.83.33.10]:52945 helo=roura.ac.upc.es) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bViTK-00033Z-A3 for qemu-devel@nongnu.org; Fri, 05 Aug 2016 12:59:46 -0400 From: =?utf-8?b?TGx1w61z?= Vilanova Date: Fri, 5 Aug 2016 18:59:45 +0200 Message-Id: <147041638509.2523.4424218032825618871.stgit@fimbulvetr.bsc.es> In-Reply-To: <147041636348.2523.2954972609232949598.stgit@fimbulvetr.bsc.es> References: <147041636348.2523.2954972609232949598.stgit@fimbulvetr.bsc.es> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Subject: [Qemu-devel] [PATCH 4/6] hypertrace: [softmmu] Add QEMU-side proxy to "guest_hypertrace" event List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Stefan Hajnoczi , "Michael S. Tsirkin" , Marcel Apfelbaum Uses a virtual device to trigger the hypertrace channel event. Signed-off-by: Llu=C3=ADs Vilanova --- hypertrace/Makefile.objs | 5 + hypertrace/softmmu.c | 243 ++++++++++++++++++++++++++++++++++++++++= ++++++ include/hw/pci/pci.h | 2=20 3 files changed, 249 insertions(+), 1 deletion(-) create mode 100644 hypertrace/softmmu.c diff --git a/hypertrace/Makefile.objs b/hypertrace/Makefile.objs index 6eb5acf..2a120b4 100644 --- a/hypertrace/Makefile.objs +++ b/hypertrace/Makefile.objs @@ -1,8 +1,11 @@ # -*- mode: makefile -*- =20 target-obj-$(CONFIG_USER_ONLY) +=3D user.o +ifdef CONFIG_PCI +target-obj-$(CONFIG_SOFTMMU) +=3D softmmu.o +endif =20 -$(obj)/user.o: $(obj)/emit.c +$(obj)/user.o $(obj)/softmmu.o: $(obj)/emit.c =20 $(obj)/emit.c: $(obj)/emit.c-timestamp $(BUILD_DIR)/config-host.mak @cmp $< $@ >/dev/null 2>&1 || cp $< $@ diff --git a/hypertrace/softmmu.c b/hypertrace/softmmu.c new file mode 100644 index 0000000..4927197 --- /dev/null +++ b/hypertrace/softmmu.c @@ -0,0 +1,243 @@ +/* + * QEMU-side management of hypertrace in softmmu emulation. + * + * Copyright (C) 2016 Llu=C3=ADs Vilanova + * + * 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. + */ + +/* + * Implementation details + * =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + * + * Both channels are provided as a virtual device with two BARs that can= be used + * through MMIO. + * + * Data channel + * ------------ + * + * The guest must mmap BAR 1 of the hypertrace virtual device, which wil= l act as + * regular writable device memory. + * + * Regular memory accesses pass data through the data channel. + * + * Control channel + * --------------- + * + * The guest must mmap BAR 0 of the hypertrace virtual device. + * + * Guest reads from that memory are intercepted by QEMU in order to retu= rn the + * size of the data channel. + * + * Guest writes into that memory are intercepted by QEMU in order to rai= se the + * "guest_hypertrace" tracing event. + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "exec/ram_addr.h" +#include "hw/pci/pci.h" +#include "migration/migration.h" +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "trace.h" + + +#define PAGE_SIZE TARGET_PAGE_SIZE + + +typedef struct HypertraceState +{ + PCIDevice dev; + + uint8_t pages; + uint64_t size; + + union + { + uint64_t v; + char a[8]; + } c_max_offset; + union + { + uint64_t v; + char a[8]; + } c_cmd; + + void *data_ptr; + MemoryRegion data; + MemoryRegion control; + + Error *migration_blocker; +} HypertraceState; + + +static uint64_t hypertrace_control_io_read(void *opaque, hwaddr addr, + unsigned size) +{ + HypertraceState *s =3D opaque; + char *mem =3D &s->c_max_offset.a[addr % sizeof(uint64_t)]; + + if (addr + size > sizeof(uint64_t)) { + error_report("error: hypertrace: Unexpected read to address %lu\= n", addr); + return 0; + } + + /* control values already have target endianess */ + + switch (size) { + case 1: + { + uint8_t *res =3D (uint8_t*)mem; + return *res; + } + case 2: + { + uint16_t *res =3D (uint16_t*)mem; + return *res; + } + case 4: + { + uint32_t *res =3D (uint32_t*)mem; + return *res; + } + case 8: + { + uint64_t *res =3D (uint64_t*)mem; + return *res; + } + default: + error_report("error: hypertrace: Unexpected read of size %d\n", = size); + return 0; + } +} + +#include "hypertrace/emit.c" + +static void hypertrace_control_io_write(void *opaque, hwaddr addr, + uint64_t data, unsigned size) +{ + HypertraceState *s =3D opaque; + char *mem =3D &s->c_cmd.a[addr % sizeof(uint64_t)]; + + if (addr < sizeof(uint64_t) || addr + size > sizeof(uint64_t) * 2) { + error_report("error: hypertrace: Unexpected write to address %lu= \n", addr); + return; + } + + /* c_cmd will have target endianess (left up to the user) */ + + switch (size) { + case 1: + { + uint8_t *res =3D (uint8_t*)mem; + *res =3D (uint8_t)data; + break; + } + case 2: + { + uint16_t *res =3D (uint16_t*)mem; + *res =3D (uint16_t)data; + break; + } + case 4: + { + uint32_t *res =3D (uint32_t*)mem; + *res =3D (uint32_t)data; + break; + } + case 8: + { + uint64_t *res =3D (uint64_t*)mem; + *res =3D (uint64_t)data; + break; + } + default: + error_report("error: hypertrace: Unexpected write of size %d\n",= size); + } + + if ((addr + size) % sizeof(s->c_cmd.v) =3D=3D 0) { + uint64_t vcontrol =3D s->c_cmd.v; + uint64_t *data_ptr =3D (uint64_t*)s->data_ptr; + data_ptr =3D &data_ptr[vcontrol * CONFIG_HYPERTRACE_ARGS * sizeo= f(uint64_t)]; + hypertrace_emit(current_cpu, data_ptr); + } +} + +static const MemoryRegionOps hypertrace_control_ops =3D { + .read =3D &hypertrace_control_io_read, + .write =3D &hypertrace_control_io_write, + .endianness =3D DEVICE_NATIVE_ENDIAN, + .impl =3D { + .min_access_size =3D 1, + .max_access_size =3D 8, + }, +}; + + +static void hypertrace_realize(PCIDevice *dev, Error **errp) +{ + HypertraceState *s =3D DO_UPCAST(HypertraceState, dev, dev); + Error *err =3D NULL; + size_t size =3D s->pages * TARGET_PAGE_SIZE; + + if (s->pages < 1) { + error_setg(errp, "hypertrace: the data channel must have one or = more pages\n"); + return; + } + s->c_max_offset.v =3D tswap64(s->size / (CONFIG_HYPERTRACE_ARGS * si= zeof(uint64_t))); + + error_setg(&s->migration_blocker, "The 'hypertrace' device cannot be= migrated"); + migrate_add_blocker(s->migration_blocker); + + pci_set_word(s->dev.config + PCI_COMMAND, + PCI_COMMAND_IO | PCI_COMMAND_MEMORY); + + /* control channel */ + memory_region_init_io(&s->control, OBJECT(s), &hypertrace_control_op= s, s, + "hypertrace.control", PAGE_SIZE); + pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->cont= rol); + + /* data channel */ + memory_region_init_ram(&s->data, OBJECT(s), "hypertrace.data", size,= &err); + if (err) { + error_propagate(errp, err); + return; + } + pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->data= ); + s->data_ptr =3D qemu_map_ram_ptr(s->data.ram_block, 0); +} + + +static Property hypertrace_properties[] =3D { + DEFINE_PROP_UINT8("pages", HypertraceState, pages, 1), + DEFINE_PROP_END_OF_LIST(), +}; + +static void hypertrace_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + PCIDeviceClass *k =3D PCI_DEVICE_CLASS(klass); + + k->realize =3D hypertrace_realize; + k->vendor_id =3D PCI_VENDOR_ID_REDHAT_QUMRANET; + k->device_id =3D PCI_DEVICE_ID_HYPERTRACE; + k->class_id =3D PCI_CLASS_MEMORY_RAM; + dc->desc =3D "Hypertrace communication channel", + dc->props =3D hypertrace_properties; +} + +static TypeInfo hypertrace_info =3D { + .name =3D "hypertrace", + .parent =3D TYPE_PCI_DEVICE, + .instance_size =3D sizeof(HypertraceState), + .class_init =3D hypertrace_class_init, +}; + +static void hypertrace_register_types(void) +{ + type_register_static(&hypertrace_info); +} + +type_init(hypertrace_register_types) diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 9ed1624..af0772f 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -80,6 +80,8 @@ #define PCI_DEVICE_ID_VIRTIO_RNG 0x1005 #define PCI_DEVICE_ID_VIRTIO_9P 0x1009 =20 +#define PCI_DEVICE_ID_HYPERTRACE 0x10f0 + #define PCI_VENDOR_ID_REDHAT 0x1b36 #define PCI_DEVICE_ID_REDHAT_BRIDGE 0x0001 #define PCI_DEVICE_ID_REDHAT_SERIAL 0x0002