From: David Gibson <david@gibson.dropbear.id.au>
To: Laurent Vivier <lvivier@redhat.com>
Cc: qemu-devel@nongnu.org, thuth@redhat.com,
Greg Kurz <groug@kaod.org>,
qemu-ppc@nongnu.org, Gerd Hoffmann <kraxel@redhat.com>,
dgibson@redhat.com
Subject: Re: [Qemu-devel] [Qemu-ppc] [PATCH 1/4] libqos: add PPC64 PCI support
Date: Tue, 27 Sep 2016 13:48:36 +1000 [thread overview]
Message-ID: <20160927034836.GA30322@umbus.fritz.box> (raw)
In-Reply-To: <1474899049-12506-2-git-send-email-lvivier@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 15973 bytes --]
On Mon, Sep 26, 2016 at 04:10:46PM +0200, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier <lvivier@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
> ---
> tests/Makefile.include | 1 +
> tests/libqos/pci-pc.c | 22 ----
> tests/libqos/pci-spapr.c | 280 +++++++++++++++++++++++++++++++++++++++++++++++
> tests/libqos/pci-spapr.h | 17 +++
> tests/libqos/pci.c | 22 +++-
> tests/libqos/rtas.c | 45 ++++++++
> tests/libqos/rtas.h | 4 +
> 7 files changed, 368 insertions(+), 23 deletions(-)
> create mode 100644 tests/libqos/pci-spapr.c
> create mode 100644 tests/libqos/pci-spapr.h
>
> diff --git a/tests/Makefile.include b/tests/Makefile.include
> index d8101b3..967426a 100644
> --- a/tests/Makefile.include
> +++ b/tests/Makefile.include
> @@ -589,6 +589,7 @@ libqos-obj-y += tests/libqos/i2c.o tests/libqos/libqos.o
> libqos-spapr-obj-y = $(libqos-obj-y) tests/libqos/malloc-spapr.o
> libqos-spapr-obj-y += tests/libqos/libqos-spapr.o
> libqos-spapr-obj-y += tests/libqos/rtas.o
> +libqos-spapr-obj-y += tests/libqos/pci-spapr.o
> libqos-pc-obj-y = $(libqos-obj-y) tests/libqos/pci-pc.o
> libqos-pc-obj-y += tests/libqos/malloc-pc.o tests/libqos/libqos-pc.o
> libqos-pc-obj-y += tests/libqos/ahci.o
> diff --git a/tests/libqos/pci-pc.c b/tests/libqos/pci-pc.c
> index 1ae2d37..82066b8 100644
> --- a/tests/libqos/pci-pc.c
> +++ b/tests/libqos/pci-pc.c
> @@ -255,28 +255,6 @@ void qpci_free_pc(QPCIBus *bus)
> g_free(s);
> }
>
> -void qpci_plug_device_test(const char *driver, const char *id,
> - uint8_t slot, const char *opts)
> -{
> - QDict *response;
> - char *cmd;
> -
> - cmd = g_strdup_printf("{'execute': 'device_add',"
> - " 'arguments': {"
> - " 'driver': '%s',"
> - " 'addr': '%d',"
> - " %s%s"
> - " 'id': '%s'"
> - "}}", driver, slot,
> - opts ? opts : "", opts ? "," : "",
> - id);
> - response = qmp(cmd);
> - g_free(cmd);
> - g_assert(response);
> - g_assert(!qdict_haskey(response, "error"));
> - QDECREF(response);
> -}
> -
> void qpci_unplug_acpi_device_test(const char *id, uint8_t slot)
> {
> QDict *response;
> diff --git a/tests/libqos/pci-spapr.c b/tests/libqos/pci-spapr.c
> new file mode 100644
> index 0000000..30fbcbd
> --- /dev/null
> +++ b/tests/libqos/pci-spapr.c
> @@ -0,0 +1,280 @@
> +/*
> + * libqos PCI bindings for SPAPR
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "libqtest.h"
> +#include "libqos/pci-spapr.h"
> +#include "libqos/rtas.h"
> +
> +#include "hw/pci/pci_regs.h"
> +
> +#include "qemu-common.h"
> +#include "qemu/host-utils.h"
> +
> +
> +/* From include/hw/pci-host/spapr.h */
> +
> +#define SPAPR_PCI_BASE_BUID 0x800000020000000ULL
> +
> +#define SPAPR_PCI_MEM_WIN_BUS_OFFSET 0x80000000ULL
> +
> +#define SPAPR_PCI_WINDOW_BASE 0x10000000000ULL
> +#define SPAPR_PCI_WINDOW_SPACING 0x1000000000ULL
> +#define SPAPR_PCI_MMIO_WIN_OFF 0xA0000000
> +#define SPAPR_PCI_MMIO_WIN_SIZE (SPAPR_PCI_WINDOW_SPACING - \
> + SPAPR_PCI_MEM_WIN_BUS_OFFSET)
> +#define SPAPR_PCI_IO_WIN_OFF 0x80000000
> +#define SPAPR_PCI_IO_WIN_SIZE 0x10000
> +
> +/* index is the phb index */
> +
> +#define BUIDBASE(index) (SPAPR_PCI_BASE_BUID + (index))
> +#define PCIBASE(index) (SPAPR_PCI_WINDOW_BASE + \
> + (index) * SPAPR_PCI_WINDOW_SPACING)
> +#define IOBASE(index) (PCIBASE(index) + SPAPR_PCI_IO_WIN_OFF)
> +#define MMIOBASE(index) (PCIBASE(index) + SPAPR_PCI_MMIO_WIN_OFF)
> +
> +typedef struct QPCIBusSPAPR {
> + QPCIBus bus;
> + QGuestAllocator *alloc;
> +
> + uint64_t pci_hole_start;
> + uint64_t pci_hole_size;
> + uint64_t pci_hole_alloc;
> +
> + uint32_t pci_iohole_start;
> + uint32_t pci_iohole_size;
> + uint32_t pci_iohole_alloc;
> +} QPCIBusSPAPR;
> +
> +static uint8_t qpci_spapr_io_readb(QPCIBus *bus, void *addr)
> +{
> + uint64_t port = (uint64_t)addr;
> + uint8_t v;
> + if (port < SPAPR_PCI_IO_WIN_SIZE) {
> + v = readb(IOBASE(0) + port);
> + } else {
> + v = readb(MMIOBASE(0) + port);
> + }
> + return v;
> +}
> +
> +static uint16_t qpci_spapr_io_readw(QPCIBus *bus, void *addr)
> +{
> + uint64_t port = (uint64_t)addr;
> + uint16_t v;
> + if (port < SPAPR_PCI_IO_WIN_SIZE) {
> + v = readw(IOBASE(0) + port);
> + } else {
> + v = readw(MMIOBASE(0) + port);
> + }
> + return be16_to_cpu(v);
> +}
> +
> +static uint32_t qpci_spapr_io_readl(QPCIBus *bus, void *addr)
> +{
> + uint64_t port = (uint64_t)addr;
> + uint32_t v;
> + if (port < SPAPR_PCI_IO_WIN_SIZE) {
> + v = readl(IOBASE(0) + port);
> + } else {
> + v = readl(MMIOBASE(0) + port);
> + }
> + return be32_to_cpu(v);
> +}
> +
> +static void qpci_spapr_io_writeb(QPCIBus *bus, void *addr, uint8_t value)
> +{
> + uint64_t port = (uint64_t)addr;
> + if (port < SPAPR_PCI_IO_WIN_SIZE) {
> + writeb(IOBASE(0) + port, value);
> + } else {
> + writeb(MMIOBASE(0) + port, value);
> + }
> +}
> +
> +static void qpci_spapr_io_writew(QPCIBus *bus, void *addr, uint16_t value)
> +{
> + uint64_t port = (uint64_t)addr;
> + if (port < SPAPR_PCI_IO_WIN_SIZE) {
> + writew(IOBASE(0) + port, cpu_to_be16(value));
> + } else {
> + writew(MMIOBASE(0) + port, cpu_to_be16(value));
> + }
> +}
> +
> +static void qpci_spapr_io_writel(QPCIBus *bus, void *addr, uint32_t value)
> +{
> + uint64_t port = (uint64_t)addr;
> + if (port < SPAPR_PCI_IO_WIN_SIZE) {
> + writel(IOBASE(0) + port, cpu_to_be32(value));
> + } else {
> + writel(MMIOBASE(0) + port, cpu_to_be32(value));
> + }
> +}
> +
> +static uint8_t qpci_spapr_config_readb(QPCIBus *bus, int devfn, uint8_t offset)
> +{
> + QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> + uint32_t config_addr = (devfn << 8) | offset;
> + return qrtas_ibm_read_pci_config(s->alloc, BUIDBASE(0),
> + config_addr, 1);
> +}
> +
> +static uint16_t qpci_spapr_config_readw(QPCIBus *bus, int devfn, uint8_t offset)
> +{
> + QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> + uint32_t config_addr = (devfn << 8) | offset;
> + return qrtas_ibm_read_pci_config(s->alloc, BUIDBASE(0),
> + config_addr, 2);
> +}
> +
> +static uint32_t qpci_spapr_config_readl(QPCIBus *bus, int devfn, uint8_t offset)
> +{
> + QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> + uint32_t config_addr = (devfn << 8) | offset;
> + return qrtas_ibm_read_pci_config(s->alloc, BUIDBASE(0),
> + config_addr, 4);
> +}
> +
> +static void qpci_spapr_config_writeb(QPCIBus *bus, int devfn, uint8_t offset,
> + uint8_t value)
> +{
> + QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> + uint32_t config_addr = (devfn << 8) | offset;
> + qrtas_ibm_write_pci_config(s->alloc, BUIDBASE(0),
> + config_addr, 1, value);
> +}
> +
> +static void qpci_spapr_config_writew(QPCIBus *bus, int devfn, uint8_t offset,
> + uint16_t value)
> +{
> + QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> + uint32_t config_addr = (devfn << 8) | offset;
> + qrtas_ibm_write_pci_config(s->alloc, BUIDBASE(0),
> + config_addr, 2, value);
> +}
> +
> +static void qpci_spapr_config_writel(QPCIBus *bus, int devfn, uint8_t offset,
> + uint32_t value)
> +{
> + QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> + uint32_t config_addr = (devfn << 8) | offset;
> + qrtas_ibm_write_pci_config(s->alloc, BUIDBASE(0),
> + config_addr, 4, value);
> +}
> +
> +static void *qpci_spapr_iomap(QPCIBus *bus, QPCIDevice *dev, int barno,
> + uint64_t *sizeptr)
> +{
> + QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> + static const int bar_reg_map[] = {
> + PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2,
> + PCI_BASE_ADDRESS_3, PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5,
> + };
> + int bar_reg;
> + uint32_t addr;
> + uint64_t size;
> + uint32_t io_type;
> +
> + g_assert(barno >= 0 && barno <= 5);
> + bar_reg = bar_reg_map[barno];
> +
> + qpci_config_writel(dev, bar_reg, 0xFFFFFFFF);
> + addr = qpci_config_readl(dev, bar_reg);
> +
> + io_type = addr & PCI_BASE_ADDRESS_SPACE;
> + if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
> + addr &= PCI_BASE_ADDRESS_IO_MASK;
> + } else {
> + addr &= PCI_BASE_ADDRESS_MEM_MASK;
> + }
> +
> + size = (1ULL << ctzl(addr));
> + if (size == 0) {
> + return NULL;
> + }
> + if (sizeptr) {
> + *sizeptr = size;
> + }
> +
> + if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
> + uint16_t loc;
> +
> + g_assert(QEMU_ALIGN_UP(s->pci_iohole_alloc, size) + size
> + <= s->pci_iohole_size);
> + s->pci_iohole_alloc = QEMU_ALIGN_UP(s->pci_iohole_alloc, size);
> + loc = s->pci_iohole_start + s->pci_iohole_alloc;
> + s->pci_iohole_alloc += size;
> +
> + qpci_config_writel(dev, bar_reg, loc | PCI_BASE_ADDRESS_SPACE_IO);
> +
> + return (void *)(unsigned long)loc;
> + } else {
> + uint64_t loc;
> +
> + g_assert(QEMU_ALIGN_UP(s->pci_hole_alloc, size) + size
> + <= s->pci_hole_size);
> + s->pci_hole_alloc = QEMU_ALIGN_UP(s->pci_hole_alloc, size);
> + loc = s->pci_hole_start + s->pci_hole_alloc;
> + s->pci_hole_alloc += size;
> +
> + qpci_config_writel(dev, bar_reg, loc);
> +
> + return (void *)(unsigned long)loc;
> + }
> +}
> +
> +static void qpci_spapr_iounmap(QPCIBus *bus, void *data)
> +{
> + /* FIXME */
> +}
> +
> +QPCIBus *qpci_init_spapr(QGuestAllocator *alloc)
> +{
> + QPCIBusSPAPR *ret;
> +
> + ret = g_malloc(sizeof(*ret));
> +
> + ret->alloc = alloc;
> +
> + ret->bus.io_readb = qpci_spapr_io_readb;
> + ret->bus.io_readw = qpci_spapr_io_readw;
> + ret->bus.io_readl = qpci_spapr_io_readl;
> +
> + ret->bus.io_writeb = qpci_spapr_io_writeb;
> + ret->bus.io_writew = qpci_spapr_io_writew;
> + ret->bus.io_writel = qpci_spapr_io_writel;
> +
> + ret->bus.config_readb = qpci_spapr_config_readb;
> + ret->bus.config_readw = qpci_spapr_config_readw;
> + ret->bus.config_readl = qpci_spapr_config_readl;
> +
> + ret->bus.config_writeb = qpci_spapr_config_writeb;
> + ret->bus.config_writew = qpci_spapr_config_writew;
> + ret->bus.config_writel = qpci_spapr_config_writel;
> +
> + ret->bus.iomap = qpci_spapr_iomap;
> + ret->bus.iounmap = qpci_spapr_iounmap;
> +
> + ret->pci_hole_start = 0xC0000000;
> + ret->pci_hole_size = SPAPR_PCI_MMIO_WIN_SIZE;
> + ret->pci_hole_alloc = 0;
> +
> + ret->pci_iohole_start = 0xc000;
> + ret->pci_iohole_size = SPAPR_PCI_IO_WIN_SIZE;
> + ret->pci_iohole_alloc = 0;
> +
> + return &ret->bus;
> +}
> +
> +void qpci_free_spapr(QPCIBus *bus)
> +{
> + QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
> +
> + g_free(s);
> +}
> diff --git a/tests/libqos/pci-spapr.h b/tests/libqos/pci-spapr.h
> new file mode 100644
> index 0000000..4192126
> --- /dev/null
> +++ b/tests/libqos/pci-spapr.h
> @@ -0,0 +1,17 @@
> +/*
> + * libqos PCI bindings for SPAPR
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + */
> +
> +#ifndef LIBQOS_PCI_SPAPR_H
> +#define LIBQOS_PCI_SPAPR_H
> +
> +#include "libqos/malloc.h"
> +#include "libqos/pci.h"
> +
> +QPCIBus *qpci_init_spapr(QGuestAllocator *alloc);
> +void qpci_free_spapr(QPCIBus *bus);
> +
> +#endif
> diff --git a/tests/libqos/pci.c b/tests/libqos/pci.c
> index ed78d91..c3f3382 100644
> --- a/tests/libqos/pci.c
> +++ b/tests/libqos/pci.c
> @@ -263,4 +263,24 @@ void qpci_iounmap(QPCIDevice *dev, void *data)
> dev->bus->iounmap(dev->bus, data);
> }
>
> -
> +void qpci_plug_device_test(const char *driver, const char *id,
> + uint8_t slot, const char *opts)
> +{
> + QDict *response;
> + char *cmd;
> +
> + cmd = g_strdup_printf("{'execute': 'device_add',"
> + " 'arguments': {"
> + " 'driver': '%s',"
> + " 'addr': '%d',"
> + " %s%s"
> + " 'id': '%s'"
> + "}}", driver, slot,
> + opts ? opts : "", opts ? "," : "",
> + id);
> + response = qmp(cmd);
> + g_free(cmd);
> + g_assert(response);
> + g_assert(!qdict_haskey(response, "error"));
> + QDECREF(response);
> +}
> diff --git a/tests/libqos/rtas.c b/tests/libqos/rtas.c
> index 820321a..0269803 100644
> --- a/tests/libqos/rtas.c
> +++ b/tests/libqos/rtas.c
> @@ -69,3 +69,48 @@ int qrtas_get_time_of_day(QGuestAllocator *alloc, struct tm *tm, uint32_t *ns)
>
> return res;
> }
> +
> +uint32_t qrtas_ibm_read_pci_config(QGuestAllocator *alloc, uint64_t buid,
> + uint32_t addr, uint32_t size)
> +{
> + int res;
> + uint32_t args[4], ret[2];
> +
> + args[0] = addr;
> + args[1] = buid >> 32;
> + args[2] = buid & 0xffffffff;
> + args[3] = size;
> + res = qrtas_call(alloc, "ibm,read-pci-config", 4, args, 2, ret);
> + if (res != 0) {
> + return -1;
> + }
> +
> + if (ret[0] != 0) {
> + return -1;
> + }
> +
> + return ret[1];
> +}
> +
> +int qrtas_ibm_write_pci_config(QGuestAllocator *alloc, uint64_t buid,
> + uint32_t addr, uint32_t size, uint32_t val)
> +{
> + int res;
> + uint32_t args[5], ret[1];
> +
> + args[0] = addr;
> + args[1] = buid >> 32;
> + args[2] = buid & 0xffffffff;
> + args[3] = size;
> + args[4] = val;
> + res = qrtas_call(alloc, "ibm,write-pci-config", 5, args, 1, ret);
> + if (res != 0) {
> + return -1;
> + }
> +
> + if (ret[0] != 0) {
> + return -1;
> + }
> +
> + return 0;
> +}
> diff --git a/tests/libqos/rtas.h b/tests/libqos/rtas.h
> index a1b60a8..498eb19 100644
> --- a/tests/libqos/rtas.h
> +++ b/tests/libqos/rtas.h
> @@ -8,4 +8,8 @@
> #include "libqos/malloc.h"
>
> int qrtas_get_time_of_day(QGuestAllocator *alloc, struct tm *tm, uint32_t *ns);
> +uint32_t qrtas_ibm_read_pci_config(QGuestAllocator *alloc, uint64_t buid,
> + uint32_t addr, uint32_t size);
> +int qrtas_ibm_write_pci_config(QGuestAllocator *alloc, uint64_t buid,
> + uint32_t addr, uint32_t size, uint32_t val);
> #endif /* LIBQOS_RTAS_H */
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
next prev parent reply other threads:[~2016-09-27 3:54 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-09-26 14:10 [Qemu-devel] [PATCH 0/4] tests: enable ohci/uhci/xhci tests on PPC64 Laurent Vivier
2016-09-26 14:10 ` [Qemu-devel] [PATCH 1/4] libqos: add PPC64 PCI support Laurent Vivier
2016-09-27 3:48 ` David Gibson [this message]
2016-09-26 14:10 ` [Qemu-devel] [PATCH 2/4] libqos: add PCI management in qtest_vboot()/qtest_shutdown() Laurent Vivier
2016-09-27 3:48 ` [Qemu-devel] [Qemu-ppc] " David Gibson
2016-09-27 7:33 ` Laurent Vivier
2016-09-27 8:29 ` David Gibson
2016-09-26 14:10 ` [Qemu-devel] [PATCH 3/4] libqos: use generic qtest_shutdown() Laurent Vivier
2016-09-27 3:49 ` [Qemu-devel] [Qemu-ppc] " David Gibson
2016-09-26 14:10 ` [Qemu-devel] [PATCH 4/4] tests: enable ohci/uhci/xhci tests on PPC64 Laurent Vivier
2016-09-27 3:53 ` [Qemu-devel] [Qemu-ppc] " David Gibson
2016-09-27 7:43 ` Laurent Vivier
2016-09-27 12:23 ` Laurent Vivier
2016-09-28 3:05 ` David Gibson
2016-09-26 15:12 ` [Qemu-devel] [PATCH 0/4] " no-reply
2016-09-27 3:54 ` [Qemu-devel] [Qemu-ppc] " David Gibson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20160927034836.GA30322@umbus.fritz.box \
--to=david@gibson.dropbear.id.au \
--cc=dgibson@redhat.com \
--cc=groug@kaod.org \
--cc=kraxel@redhat.com \
--cc=lvivier@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=qemu-ppc@nongnu.org \
--cc=thuth@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.