From patchwork Thu Jul 27 07:10:57 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Llu=C3=ADs_Vilanova?= X-Patchwork-Id: 9866365 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id C9AF56038F for ; Thu, 27 Jul 2017 07:11:49 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BBDB3287ED for ; Thu, 27 Jul 2017 07:11:49 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AF83C287F0; Thu, 27 Jul 2017 07:11:49 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 03AAD287ED for ; Thu, 27 Jul 2017 07:11:48 +0000 (UTC) Received: from localhost ([::1]:41471 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dacxY-0008CM-39 for patchwork-qemu-devel@patchwork.kernel.org; Thu, 27 Jul 2017 03:11:48 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34544) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dacwy-0008C5-BK for qemu-devel@nongnu.org; Thu, 27 Jul 2017 03:11:13 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dacwt-0001CS-WF for qemu-devel@nongnu.org; Thu, 27 Jul 2017 03:11:12 -0400 Received: from roura.ac.upc.es ([147.83.33.10]:39506) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dacwt-0001BZ-Dq for qemu-devel@nongnu.org; Thu, 27 Jul 2017 03:11:07 -0400 Received: from correu-2.ac.upc.es (correu-2.ac.upc.es [147.83.30.92]) by roura.ac.upc.es (8.13.8/8.13.8) with ESMTP id v6R7B47A017591; Thu, 27 Jul 2017 09:11:06 +0200 Received: from localhost (unknown [31.210.188.120]) by correu-2.ac.upc.es (Postfix) with ESMTPSA id E81F2661; Thu, 27 Jul 2017 09:10:58 +0200 (CEST) From: =?utf-8?b?TGx1w61z?= Vilanova To: qemu-devel@nongnu.org Date: Thu, 27 Jul 2017 10:10:57 +0300 Message-Id: <150113945756.25904.1680815499292736130.stgit@frigg.lan> X-Mailer: git-send-email 2.13.2 In-Reply-To: <150113848793.25904.12006041120076726256.stgit@frigg.lan> References: <150113848793.25904.12006041120076726256.stgit@frigg.lan> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 X-MIME-Autoconverted: from 8bit to quoted-printable by roura.ac.upc.es id v6R7B47A017591 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x [fuzzy] X-Received-From: 147.83.33.10 Subject: [Qemu-devel] [PATCH v6 4/5] hypertrace: [softmmu] Add QEMU-side proxy to "guest_hypertrace" event X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: "Michael S. Tsirkin" , Luiz Capitulino , Stefan Hajnoczi , Marcel Apfelbaum Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP Uses a virtual device to trigger the hypertrace channel event. Signed-off-by: Lluís Vilanova --- hypertrace/Makefile.objs | 4 + hypertrace/softmmu.c | 237 ++++++++++++++++++++++++++++++++++++++++++++++ include/hw/pci/pci.h | 2 3 files changed, 243 insertions(+) create mode 100644 hypertrace/softmmu.c diff --git a/hypertrace/Makefile.objs b/hypertrace/Makefile.objs index 2bda105c2f..01c56c910c 100644 --- a/hypertrace/Makefile.objs +++ b/hypertrace/Makefile.objs @@ -1,10 +1,14 @@ # -*- mode: makefile -*- target-obj-$(CONFIG_USER_ONLY) += user.o +ifdef CONFIG_PCI +target-obj-$(CONFIG_SOFTMMU) += softmmu.o +endif target-obj-y += common.o $(obj)/user.o: $(obj)/emit.c $(obj)/common.o: $(obj)/emit.c +$(obj)/softmmu.o: $(obj)/emit.c $(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 0000000000..ecf2e86393 --- /dev/null +++ b/hypertrace/softmmu.c @@ -0,0 +1,237 @@ +/* + * QEMU-side management of hypertrace in softmmu emulation. + * + * Copyright (C) 2016-2017 Lluís Vilanova + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +/* + * Implementation details + * ====================== + * + * There are 3 channels, each a BAR of a virtual device that can be used through + * MMIO. + * + * + * - Configuration channel: Exposes configuration parameters. + * + * - Data channel: Lets guests write argument values. Each guest client should + * use a different offset to avoid concurrency problems. + * + * - Control channel: Triggers the hypertrace event on a write, providing the + * first argument. Offset in the control channel sets the offset in the data + * channel. + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "hypertrace/common.h" +#include "hypertrace/trace.h" +#include "hw/pci/pci.h" +#include "migration/blocker.h" +#include "qapi/error.h" +#include "qemu/error-report.h" + + +typedef struct HypertraceState { + PCIDevice dev; + + uint64_t max_clients; + struct hypertrace_config hconfig; + + MemoryRegion config; + void *config_ptr; + MemoryRegion data; + void *data_ptr; + MemoryRegion control; + void *control_ptr; + + Error *migration_blocker; +} HypertraceState; + + +static uint64_t hypertrace_control_io_read(void *opaque, hwaddr addr, + unsigned size) +{ + uint64_t res; + HypertraceState *s = opaque; + char *mem = &((char *)s->control_ptr)[addr]; + + switch (size) { + case 1: + { + res = ((uint8_t *)mem)[0]; + break; + } + case 2: + { + res = ((uint16_t *)mem)[0]; + break; + } + case 4: + { + res = ((uint32_t *)mem)[0]; + break; + } + case 8: + { + res = ((uint64_t *)mem)[0]; + break; + } + default: + error_report("error: hypertrace: Unexpected read of size %d", size); + abort(); + } + + return res; +} + +static void hypertrace_control_io_write(void *opaque, hwaddr addr, + uint64_t data, unsigned size) +{ + HypertraceState *s = opaque; + char *mem = &((char *)s->control_ptr)[addr]; + + switch (size) { + case 1: + { + uint8_t *res = (uint8_t *)mem; + *res = (uint8_t)data; + break; + } + case 2: + { + uint16_t *res = (uint16_t *)mem; + *res = (uint16_t)data; + break; + } + case 4: + { + uint32_t *res = (uint32_t *)mem; + *res = (uint32_t)data; + break; + } + case 8: + { + uint64_t *res = (uint64_t *)mem; + *res = (uint64_t)data; + break; + } + default: + error_report("error: hypertrace: Unexpected write of size %d", size); + abort(); + } + + if ((addr + size) % sizeof(uint64_t) == 0) { + uint64_t client = addr / sizeof(uint64_t); + uint64_t vcontrol = ((uint64_t *)s->control_ptr)[client]; + uint64_t *data_ptr = (uint64_t *)s->data_ptr; + data_ptr = &data_ptr[client * s->hconfig.client_data_size]; + hypertrace_emit(current_cpu, vcontrol, data_ptr); + } +} + +static const MemoryRegionOps hypertrace_control_ops = { + .read = &hypertrace_control_io_read, + .write = &hypertrace_control_io_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .impl = { + .min_access_size = 1, + .max_access_size = 8, + }, +}; + + +static void hypertrace_realize(PCIDevice *dev, Error **errp) +{ + Error *local_err = NULL; + struct hypertrace_config *config; + HypertraceState *s = DO_UPCAST(HypertraceState, dev, dev); + Error *err = NULL; + + if (s->max_clients < 1) { + error_setg(errp, "hypertrace: must have at least one client"); + return; + } + + hypertrace_init_config(&s->hconfig, s->max_clients); + + error_setg(&s->migration_blocker, + "The 'hypertrace' device cannot be migrated"); + migrate_add_blocker(s->migration_blocker, &local_err); + if (local_err) { + error_propagate(errp, local_err); + error_free(s->migration_blocker); + return; + } + + pci_set_word(s->dev.config + PCI_COMMAND, + PCI_COMMAND_IO | PCI_COMMAND_MEMORY); + + /* config channel */ + memory_region_init_ram(&s->config, OBJECT(s), "hypertrace.config", + TARGET_PAGE_SIZE, &err); + if (err) { + error_propagate(errp, err); + return; + } + pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->config); + s->config_ptr = qemu_map_ram_ptr(s->config.ram_block, 0); + config = s->config_ptr; + config->max_clients = tswap64(s->hconfig.max_clients); + config->client_args = tswap64(s->hconfig.client_args); + config->client_data_size = tswap64(s->hconfig.client_data_size); + config->control_size = tswap64(s->hconfig.control_size); + config->data_size = tswap64(s->hconfig.data_size); + + /* data channel */ + memory_region_init_ram(&s->data, OBJECT(s), "hypertrace.data", + s->hconfig.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 = qemu_map_ram_ptr(s->data.ram_block, 0); + + /* control channel */ + memory_region_init_io(&s->control, OBJECT(s), &hypertrace_control_ops, s, + "hypertrace.control", s->hconfig.control_size); + pci_register_bar(&s->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->control); + s->control_ptr = qemu_map_ram_ptr(s->control.ram_block, 0); +} + + +static Property hypertrace_properties[] = { + DEFINE_PROP_UINT64("max-clients", HypertraceState, max_clients, 1), + DEFINE_PROP_END_OF_LIST(), +}; + +static void hypertrace_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + + k->realize = hypertrace_realize; + k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; + k->device_id = PCI_DEVICE_ID_HYPERTRACE; + k->class_id = PCI_CLASS_MEMORY_RAM; + dc->desc = "Hypertrace communication channel", + dc->props = hypertrace_properties; +} + +static TypeInfo hypertrace_info = { + .name = "hypertrace", + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(HypertraceState), + .class_init = 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 e598b095eb..3910a9b89f 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -84,6 +84,8 @@ #define PCI_DEVICE_ID_VIRTIO_9P 0x1009 #define PCI_DEVICE_ID_VIRTIO_VSOCK 0x1012 +#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