From 7e450a8f50ac12fc8f69b6ce555254c84efcf407 Mon Sep 17 00:00:00 2001 From: Jean-Christophe Dubois Date: Wed, 22 Nov 2017 07:32:50 +0100 Subject: [PATCH 01/25] target/sparc: remove MemoryRegionSection check code from sparc_cpu_get_phys_page_debug() This code is preventing the MMU debug code from displaying virtual mappings of IO devices (anything that is not located in the RAM). Before this patch, Qemu would output 0xffffffffffffffff (-1) as the physical address corresponding to an IO device virtual address. With this patch the intended physical address is displayed. Signed-off-by: Jean-Christophe Dubois Signed-off-by: Mark Cave-Ayland --- target/sparc/mmu_helper.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/target/sparc/mmu_helper.c b/target/sparc/mmu_helper.c index d5b6c1e48c..f2d2250e7a 100644 --- a/target/sparc/mmu_helper.c +++ b/target/sparc/mmu_helper.c @@ -857,18 +857,12 @@ hwaddr sparc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) CPUSPARCState *env = &cpu->env; hwaddr phys_addr; int mmu_idx = cpu_mmu_index(env, false); - MemoryRegionSection section; if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 2, mmu_idx) != 0) { if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 0, mmu_idx) != 0) { return -1; } } - section = memory_region_find(get_system_memory(), phys_addr, 1); - memory_region_unref(section.mr); - if (!int128_nz(section.size)) { - return -1; - } return phys_addr; } #endif From 28edc7c92a7491a9c077fd5b5686e5a226b8138b Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Thu, 21 Dec 2017 07:32:57 +0000 Subject: [PATCH 02/25] apb: move QOM macros and typedefs from apb.c to apb.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This also includes the related IOMMUState typedef and defines. Signed-off-by: Mark Cave-Ayland Reviewed-by: Artyom Tarasenko Reviewed-by: Philippe Mathieu-Daudé --- hw/pci-host/apb.c | 85 -------------------------------------- include/hw/pci-host/apb.h | 86 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 85 deletions(-) diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c index 64025cd8cc..f743a4e312 100644 --- a/hw/pci-host/apb.c +++ b/hw/pci-host/apb.c @@ -82,91 +82,6 @@ do { printf("IOMMU: " fmt , ## __VA_ARGS__); } while (0) #define MAX_IVEC 0x40 #define NO_IRQ_REQUEST (MAX_IVEC + 1) -#define IOMMU_PAGE_SIZE_8K (1ULL << 13) -#define IOMMU_PAGE_MASK_8K (~(IOMMU_PAGE_SIZE_8K - 1)) -#define IOMMU_PAGE_SIZE_64K (1ULL << 16) -#define IOMMU_PAGE_MASK_64K (~(IOMMU_PAGE_SIZE_64K - 1)) - -#define IOMMU_NREGS 3 - -#define IOMMU_CTRL 0x0 -#define IOMMU_CTRL_TBW_SIZE (1ULL << 2) -#define IOMMU_CTRL_MMU_EN (1ULL) - -#define IOMMU_CTRL_TSB_SHIFT 16 - -#define IOMMU_BASE 0x8 -#define IOMMU_FLUSH 0x10 - -#define IOMMU_TTE_DATA_V (1ULL << 63) -#define IOMMU_TTE_DATA_SIZE (1ULL << 61) -#define IOMMU_TTE_DATA_W (1ULL << 1) - -#define IOMMU_TTE_PHYS_MASK_8K 0x1ffffffe000ULL -#define IOMMU_TTE_PHYS_MASK_64K 0x1ffffff8000ULL - -#define IOMMU_TSB_8K_OFFSET_MASK_8M 0x00000000007fe000ULL -#define IOMMU_TSB_8K_OFFSET_MASK_16M 0x0000000000ffe000ULL -#define IOMMU_TSB_8K_OFFSET_MASK_32M 0x0000000001ffe000ULL -#define IOMMU_TSB_8K_OFFSET_MASK_64M 0x0000000003ffe000ULL -#define IOMMU_TSB_8K_OFFSET_MASK_128M 0x0000000007ffe000ULL -#define IOMMU_TSB_8K_OFFSET_MASK_256M 0x000000000fffe000ULL -#define IOMMU_TSB_8K_OFFSET_MASK_512M 0x000000001fffe000ULL -#define IOMMU_TSB_8K_OFFSET_MASK_1G 0x000000003fffe000ULL - -#define IOMMU_TSB_64K_OFFSET_MASK_64M 0x0000000003ff0000ULL -#define IOMMU_TSB_64K_OFFSET_MASK_128M 0x0000000007ff0000ULL -#define IOMMU_TSB_64K_OFFSET_MASK_256M 0x000000000fff0000ULL -#define IOMMU_TSB_64K_OFFSET_MASK_512M 0x000000001fff0000ULL -#define IOMMU_TSB_64K_OFFSET_MASK_1G 0x000000003fff0000ULL -#define IOMMU_TSB_64K_OFFSET_MASK_2G 0x000000007fff0000ULL - -typedef struct IOMMUState { - AddressSpace iommu_as; - IOMMUMemoryRegion iommu; - - uint64_t regs[IOMMU_NREGS]; -} IOMMUState; - -#define TYPE_APB "pbm" - -#define APB_DEVICE(obj) \ - OBJECT_CHECK(APBState, (obj), TYPE_APB) - -#define TYPE_APB_IOMMU_MEMORY_REGION "pbm-iommu-memory-region" - -typedef struct APBState { - PCIHostState parent_obj; - - MemoryRegion apb_config; - MemoryRegion pci_config; - MemoryRegion pci_mmio; - MemoryRegion pci_ioport; - uint64_t pci_irq_in; - IOMMUState iommu; - uint32_t pci_control[16]; - uint32_t pci_irq_map[8]; - uint32_t pci_err_irq_map[4]; - uint32_t obio_irq_map[32]; - qemu_irq *pbm_irqs; - qemu_irq *ivec_irqs; - unsigned int irq_request; - uint32_t reset_control; - unsigned int nr_resets; -} APBState; - -#define TYPE_PBM_PCI_BRIDGE "pbm-bridge" -#define PBM_PCI_BRIDGE(obj) \ - OBJECT_CHECK(PBMPCIBridge, (obj), TYPE_PBM_PCI_BRIDGE) - -typedef struct PBMPCIBridge { - /*< private >*/ - PCIBridge parent_obj; - - /* Is this busA with in-built devices (ebus)? */ - bool busA; -} PBMPCIBridge; - static inline void pbm_set_request(APBState *s, unsigned int irq_num) { APB_DPRINTF("%s: request irq %d\n", __func__, irq_num); diff --git a/include/hw/pci-host/apb.h b/include/hw/pci-host/apb.h index b19bd55c40..5d39c03bc4 100644 --- a/include/hw/pci-host/apb.h +++ b/include/hw/pci-host/apb.h @@ -2,6 +2,92 @@ #define PCI_HOST_APB_H #include "qemu-common.h" +#include "hw/pci/pci_host.h" + +#define IOMMU_NREGS 3 + +#define IOMMU_PAGE_SIZE_8K (1ULL << 13) +#define IOMMU_PAGE_MASK_8K (~(IOMMU_PAGE_SIZE_8K - 1)) +#define IOMMU_PAGE_SIZE_64K (1ULL << 16) +#define IOMMU_PAGE_MASK_64K (~(IOMMU_PAGE_SIZE_64K - 1)) + +#define IOMMU_CTRL 0x0 +#define IOMMU_CTRL_TBW_SIZE (1ULL << 2) +#define IOMMU_CTRL_MMU_EN (1ULL) + +#define IOMMU_CTRL_TSB_SHIFT 16 + +#define IOMMU_BASE 0x8 +#define IOMMU_FLUSH 0x10 + +#define IOMMU_TTE_DATA_V (1ULL << 63) +#define IOMMU_TTE_DATA_SIZE (1ULL << 61) +#define IOMMU_TTE_DATA_W (1ULL << 1) + +#define IOMMU_TTE_PHYS_MASK_8K 0x1ffffffe000ULL +#define IOMMU_TTE_PHYS_MASK_64K 0x1ffffff8000ULL + +#define IOMMU_TSB_8K_OFFSET_MASK_8M 0x00000000007fe000ULL +#define IOMMU_TSB_8K_OFFSET_MASK_16M 0x0000000000ffe000ULL +#define IOMMU_TSB_8K_OFFSET_MASK_32M 0x0000000001ffe000ULL +#define IOMMU_TSB_8K_OFFSET_MASK_64M 0x0000000003ffe000ULL +#define IOMMU_TSB_8K_OFFSET_MASK_128M 0x0000000007ffe000ULL +#define IOMMU_TSB_8K_OFFSET_MASK_256M 0x000000000fffe000ULL +#define IOMMU_TSB_8K_OFFSET_MASK_512M 0x000000001fffe000ULL +#define IOMMU_TSB_8K_OFFSET_MASK_1G 0x000000003fffe000ULL + +#define IOMMU_TSB_64K_OFFSET_MASK_64M 0x0000000003ff0000ULL +#define IOMMU_TSB_64K_OFFSET_MASK_128M 0x0000000007ff0000ULL +#define IOMMU_TSB_64K_OFFSET_MASK_256M 0x000000000fff0000ULL +#define IOMMU_TSB_64K_OFFSET_MASK_512M 0x000000001fff0000ULL +#define IOMMU_TSB_64K_OFFSET_MASK_1G 0x000000003fff0000ULL +#define IOMMU_TSB_64K_OFFSET_MASK_2G 0x000000007fff0000ULL + +typedef struct IOMMUState { + AddressSpace iommu_as; + IOMMUMemoryRegion iommu; + + uint64_t regs[IOMMU_NREGS]; +} IOMMUState; + +#define TYPE_APB "pbm" + +#define APB_DEVICE(obj) \ + OBJECT_CHECK(APBState, (obj), TYPE_APB) + +#define TYPE_APB_IOMMU_MEMORY_REGION "pbm-iommu-memory-region" + +typedef struct APBState { + PCIHostState parent_obj; + + MemoryRegion apb_config; + MemoryRegion pci_config; + MemoryRegion pci_mmio; + MemoryRegion pci_ioport; + uint64_t pci_irq_in; + IOMMUState iommu; + uint32_t pci_control[16]; + uint32_t pci_irq_map[8]; + uint32_t pci_err_irq_map[4]; + uint32_t obio_irq_map[32]; + qemu_irq *pbm_irqs; + qemu_irq *ivec_irqs; + unsigned int irq_request; + uint32_t reset_control; + unsigned int nr_resets; +} APBState; + +typedef struct PBMPCIBridge { + /*< private >*/ + PCIBridge parent_obj; + + /* Is this busA with in-built devices (ebus)? */ + bool busA; +} PBMPCIBridge; + +#define TYPE_PBM_PCI_BRIDGE "pbm-bridge" +#define PBM_PCI_BRIDGE(obj) \ + OBJECT_CHECK(PBMPCIBridge, (obj), TYPE_PBM_PCI_BRIDGE) PCIBus *pci_apb_init(hwaddr special_base, hwaddr mem_base, From ad6856e875ee0f60fb89c74b0410fd99c2c5e9a2 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Thu, 21 Dec 2017 07:32:57 +0000 Subject: [PATCH 03/25] sun4u: ebus QOMify tidy-up MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The main change here is to introduce the proper TYPE_EBUS/EBUS QOM macros and remove the use of DO_UPCAST. Alongside this there are some a couple of minor cosmetic changes and a rename of pci_ebus_realize() to ebus_realize() since the ebus device is always what is effectively a PCI-ISA bridge. Signed-off-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé --- hw/sparc64/sun4u.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index 1672f256e7..394b7d6c59 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -81,11 +81,16 @@ struct hwdef { }; typedef struct EbusState { - PCIDevice pci_dev; + /*< private >*/ + PCIDevice parent_obj; + MemoryRegion bar0; MemoryRegion bar1; } EbusState; +#define TYPE_EBUS "ebus" +#define EBUS(obj) OBJECT_CHECK(EbusState, (obj), TYPE_EBUS) + void DMA_init(ISABus *bus, int high_page_enable) { } @@ -236,9 +241,9 @@ pci_ebus_init(PCIDevice *pci_dev, qemu_irq *irqs) return isa_bus; } -static void pci_ebus_realize(PCIDevice *pci_dev, Error **errp) +static void ebus_realize(PCIDevice *pci_dev, Error **errp) { - EbusState *s = DO_UPCAST(EbusState, pci_dev, pci_dev); + EbusState *s = EBUS(pci_dev); if (!isa_bus_new(DEVICE(pci_dev), get_system_memory(), pci_address_space_io(pci_dev), errp)) { @@ -264,7 +269,7 @@ static void ebus_class_init(ObjectClass *klass, void *data) { PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->realize = pci_ebus_realize; + k->realize = ebus_realize; k->vendor_id = PCI_VENDOR_ID_SUN; k->device_id = PCI_DEVICE_ID_SUN_EBUS; k->revision = 0x01; @@ -272,10 +277,10 @@ static void ebus_class_init(ObjectClass *klass, void *data) } static const TypeInfo ebus_info = { - .name = "ebus", + .name = TYPE_EBUS, .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(EbusState), .class_init = ebus_class_init, + .instance_size = sizeof(EbusState), .interfaces = (InterfaceInfo[]) { { INTERFACE_CONVENTIONAL_PCI_DEVICE }, { }, @@ -463,7 +468,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem, pci_busA->slot_reserved_mask = 0xfffffff1; pci_busB->slot_reserved_mask = 0xfffffff0; - ebus = pci_create_multifunction(pci_busA, PCI_DEVFN(1, 0), true, "ebus"); + ebus = pci_create_multifunction(pci_busA, PCI_DEVFN(1, 0), true, TYPE_EBUS); qdev_init_nofail(DEVICE(ebus)); isa_bus = pci_ebus_init(ebus, pbm_irqs); From 8c40b8d9fb596cd1e9517d0176043c478bb8e7e2 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Thu, 21 Dec 2017 07:32:57 +0000 Subject: [PATCH 04/25] sun4u: move ISABus inside of EBusState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the EBus is effectively a PCI-ISA bridge then the underlying ISA bus should be contained within the PCI bridge itself. Signed-off-by: Mark Cave-Ayland Reviewed-by: Artyom Tarasenko Reviewed-by: Philippe Mathieu-Daudé --- hw/sparc64/sun4u.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index 394b7d6c59..63b4aaa6eb 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -84,6 +84,7 @@ typedef struct EbusState { /*< private >*/ PCIDevice parent_obj; + ISABus *isa_bus; MemoryRegion bar0; MemoryRegion bar1; } EbusState; @@ -245,8 +246,10 @@ static void ebus_realize(PCIDevice *pci_dev, Error **errp) { EbusState *s = EBUS(pci_dev); - if (!isa_bus_new(DEVICE(pci_dev), get_system_memory(), - pci_address_space_io(pci_dev), errp)) { + s->isa_bus = isa_bus_new(DEVICE(pci_dev), get_system_memory(), + pci_address_space_io(pci_dev), errp); + if (!s->isa_bus) { + error_setg(errp, "unable to instantiate EBUS ISA bus"); return; } From c796eddaad58301611315ae3c16f3ef26ccf207a Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Thu, 21 Dec 2017 07:32:57 +0000 Subject: [PATCH 05/25] sun4u: remove pci_ebus_init() function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is initialisation that should really take place in the ebus realize function. As part of this we also rework the ebus IRQ mapping so that instead of having to pass in the array of pbm_irqs, we obtain a reference to them by looking up the APB device during ebus realize. Signed-off-by: Mark Cave-Ayland Reviewed-by: Artyom Tarasenko Reviewed-by: Philippe Mathieu-Daudé --- hw/pci-host/apb.c | 4 +--- hw/sparc64/sun4u.c | 29 ++++++++++++++--------------- include/hw/pci-host/apb.h | 3 +-- 3 files changed, 16 insertions(+), 20 deletions(-) diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c index f743a4e312..b0f80f63eb 100644 --- a/hw/pci-host/apb.c +++ b/hw/pci-host/apb.c @@ -614,8 +614,7 @@ static void apb_pci_bridge_realize(PCIDevice *dev, Error **errp) PCIBus *pci_apb_init(hwaddr special_base, hwaddr mem_base, - qemu_irq *ivec_irqs, PCIBus **busA, PCIBus **busB, - qemu_irq **pbm_irqs) + qemu_irq *ivec_irqs, PCIBus **busA, PCIBus **busB) { DeviceState *dev; SysBusDevice *s; @@ -646,7 +645,6 @@ PCIBus *pci_apb_init(hwaddr special_base, memory_region_init(&d->pci_mmio, OBJECT(s), "pci-mmio", 0x100000000ULL); memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio); - *pbm_irqs = d->pbm_irqs; d->ivec_irqs = ivec_irqs; pci_create_simple(phb->bus, 0, "pbm-pci"); diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index 63b4aaa6eb..f3203ea887 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -230,21 +230,11 @@ static void isa_irq_handler(void *opaque, int n, int level) } /* EBUS (Eight bit bus) bridge */ -static ISABus * -pci_ebus_init(PCIDevice *pci_dev, qemu_irq *irqs) -{ - qemu_irq *isa_irq; - ISABus *isa_bus; - - isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(pci_dev), "isa.0")); - isa_irq = qemu_allocate_irqs(isa_irq_handler, irqs, 16); - isa_bus_irqs(isa_bus, isa_irq); - return isa_bus; -} - static void ebus_realize(PCIDevice *pci_dev, Error **errp) { EbusState *s = EBUS(pci_dev); + APBState *apb; + qemu_irq *isa_irq; s->isa_bus = isa_bus_new(DEVICE(pci_dev), get_system_memory(), pci_address_space_io(pci_dev), errp); @@ -253,6 +243,15 @@ static void ebus_realize(PCIDevice *pci_dev, Error **errp) return; } + apb = APB_DEVICE(object_resolve_path_type("", TYPE_APB, NULL)); + if (!apb) { + error_setg(errp, "unable to locate APB PCI host bridge"); + return; + } + + isa_irq = qemu_allocate_irqs(isa_irq_handler, apb->pbm_irqs, 16); + isa_bus_irqs(s->isa_bus, isa_irq); + pci_dev->config[0x04] = 0x06; // command = bus master, pci mem pci_dev->config[0x05] = 0x00; pci_dev->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error @@ -443,7 +442,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem, PCIDevice *ebus, *pci_dev; ISABus *isa_bus; SysBusDevice *s; - qemu_irq *ivec_irqs, *pbm_irqs; + qemu_irq *ivec_irqs; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; DriveInfo *fd[MAX_FD]; DeviceState *dev; @@ -462,7 +461,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem, ivec_irqs = qemu_allocate_irqs(sparc64_cpu_set_ivec_irq, cpu, IVEC_MAX); pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, ivec_irqs, &pci_busA, - &pci_busB, &pbm_irqs); + &pci_busB); /* Only in-built Simba PBMs can exist on the root bus, slot 0 on busA is reserved (leaving no slots free after on-board devices) however slots @@ -474,7 +473,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem, ebus = pci_create_multifunction(pci_busA, PCI_DEVFN(1, 0), true, TYPE_EBUS); qdev_init_nofail(DEVICE(ebus)); - isa_bus = pci_ebus_init(ebus, pbm_irqs); + isa_bus = EBUS(ebus)->isa_bus; i = 0; if (hwdef->console_serial_base) { diff --git a/include/hw/pci-host/apb.h b/include/hw/pci-host/apb.h index 5d39c03bc4..35d7d5ad7b 100644 --- a/include/hw/pci-host/apb.h +++ b/include/hw/pci-host/apb.h @@ -91,6 +91,5 @@ typedef struct PBMPCIBridge { PCIBus *pci_apb_init(hwaddr special_base, hwaddr mem_base, - qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3, - qemu_irq **pbm_irqs); + qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3); #endif From 0fe22ffbbc6b65fe6bd453b37120edba91fc169e Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Thu, 21 Dec 2017 07:32:57 +0000 Subject: [PATCH 06/25] sun4u: move initialisation of all ISABus devices into ebus_realize() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This belongs in the PCI-ISA bridge rather than at the machine level. Signed-off-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Artyom Tarasenko --- hw/sparc64/sun4u.c | 78 +++++++++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 32 deletions(-) diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index f3203ea887..b441f1ecdb 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -85,6 +85,7 @@ typedef struct EbusState { PCIDevice parent_obj; ISABus *isa_bus; + uint64_t console_serial_base; MemoryRegion bar0; MemoryRegion bar1; } EbusState; @@ -234,7 +235,10 @@ static void ebus_realize(PCIDevice *pci_dev, Error **errp) { EbusState *s = EBUS(pci_dev); APBState *apb; + DeviceState *dev; qemu_irq *isa_irq; + DriveInfo *fd[MAX_FD]; + int i; s->isa_bus = isa_bus_new(DEVICE(pci_dev), get_system_memory(), pci_address_space_io(pci_dev), errp); @@ -252,6 +256,38 @@ static void ebus_realize(PCIDevice *pci_dev, Error **errp) isa_irq = qemu_allocate_irqs(isa_irq_handler, apb->pbm_irqs, 16); isa_bus_irqs(s->isa_bus, isa_irq); + /* Serial ports */ + i = 0; + if (s->console_serial_base) { + serial_mm_init(pci_address_space(pci_dev), s->console_serial_base, + 0, NULL, 115200, serial_hds[i], DEVICE_BIG_ENDIAN); + i++; + } + serial_hds_isa_init(s->isa_bus, i, MAX_SERIAL_PORTS); + + /* Parallel ports */ + parallel_hds_isa_init(s->isa_bus, MAX_PARALLEL_PORTS); + + /* Keyboard */ + isa_create_simple(s->isa_bus, "i8042"); + + /* Floppy */ + for (i = 0; i < MAX_FD; i++) { + fd[i] = drive_get(IF_FLOPPY, 0, i); + } + dev = DEVICE(isa_create(s->isa_bus, TYPE_ISA_FDC)); + if (fd[0]) { + qdev_prop_set_drive(dev, "driveA", blk_by_legacy_dinfo(fd[0]), + &error_abort); + } + if (fd[1]) { + qdev_prop_set_drive(dev, "driveB", blk_by_legacy_dinfo(fd[1]), + &error_abort); + } + qdev_prop_set_uint32(dev, "dma", -1); + qdev_init_nofail(dev); + + /* PCI */ pci_dev->config[0x04] = 0x06; // command = bus master, pci mem pci_dev->config[0x05] = 0x00; pci_dev->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error @@ -267,15 +303,23 @@ static void ebus_realize(PCIDevice *pci_dev, Error **errp) pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->bar1); } +static Property ebus_properties[] = { + DEFINE_PROP_UINT64("console-serial-base", EbusState, + console_serial_base, 0), + DEFINE_PROP_END_OF_LIST(), +}; + static void ebus_class_init(ObjectClass *klass, void *data) { PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); k->realize = ebus_realize; k->vendor_id = PCI_VENDOR_ID_SUN; k->device_id = PCI_DEVICE_ID_SUN_EBUS; k->revision = 0x01; k->class_id = PCI_CLASS_BRIDGE_OTHER; + dc->props = ebus_properties; } static const TypeInfo ebus_info = { @@ -440,11 +484,9 @@ static void sun4uv_init(MemoryRegion *address_space_mem, uint64_t initrd_addr, initrd_size, kernel_addr, kernel_size, kernel_entry; PCIBus *pci_bus, *pci_busA, *pci_busB; PCIDevice *ebus, *pci_dev; - ISABus *isa_bus; SysBusDevice *s; qemu_irq *ivec_irqs; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; - DriveInfo *fd[MAX_FD]; DeviceState *dev; FWCfgState *fw_cfg; NICInfo *nd; @@ -471,20 +513,10 @@ static void sun4uv_init(MemoryRegion *address_space_mem, pci_busB->slot_reserved_mask = 0xfffffff0; ebus = pci_create_multifunction(pci_busA, PCI_DEVFN(1, 0), true, TYPE_EBUS); + qdev_prop_set_uint64(DEVICE(ebus), "console-serial-base", + hwdef->console_serial_base); qdev_init_nofail(DEVICE(ebus)); - isa_bus = EBUS(ebus)->isa_bus; - - i = 0; - if (hwdef->console_serial_base) { - serial_mm_init(address_space_mem, hwdef->console_serial_base, 0, - NULL, 115200, serial_hds[i], DEVICE_BIG_ENDIAN); - i++; - } - - serial_hds_isa_init(isa_bus, i, MAX_SERIAL_PORTS); - parallel_hds_isa_init(isa_bus, MAX_PARALLEL_PORTS); - pci_dev = pci_create_simple(pci_busA, PCI_DEVFN(2, 0), "VGA"); memset(&macaddr, 0, sizeof(MACAddr)); @@ -523,24 +555,6 @@ static void sun4uv_init(MemoryRegion *address_space_mem, qdev_init_nofail(&pci_dev->qdev); pci_ide_create_devs(pci_dev, hd); - isa_create_simple(isa_bus, "i8042"); - - /* Floppy */ - for(i = 0; i < MAX_FD; i++) { - fd[i] = drive_get(IF_FLOPPY, 0, i); - } - dev = DEVICE(isa_create(isa_bus, TYPE_ISA_FDC)); - if (fd[0]) { - qdev_prop_set_drive(dev, "driveA", blk_by_legacy_dinfo(fd[0]), - &error_abort); - } - if (fd[1]) { - qdev_prop_set_drive(dev, "driveB", blk_by_legacy_dinfo(fd[1]), - &error_abort); - } - qdev_prop_set_uint32(dev, "dma", -1); - qdev_init_nofail(dev); - /* Map NVRAM into I/O (ebus) space */ nvram = m48t59_init(NULL, 0, 0, NVRAM_SIZE, 1968, 59); s = SYS_BUS_DEVICE(nvram); From b26f441903f8d6efcd0501ec6d0a2c8a51a13eae Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Thu, 21 Dec 2017 07:32:57 +0000 Subject: [PATCH 07/25] apb: APB QOMify tidy-up MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use DeviceClass rather than SysBusDeviceClass in pbm_host_class_init() and adjust pci_pbm_init_device() accordingly. Signed-off-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé --- hw/pci-host/apb.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c index b0f80f63eb..c7837efb7a 100644 --- a/hw/pci-host/apb.c +++ b/hw/pci-host/apb.c @@ -705,12 +705,12 @@ static const MemoryRegionOps pci_config_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -static int pci_pbm_init_device(SysBusDevice *dev) +static int pci_pbm_init_device(DeviceState *dev) { - APBState *s; + APBState *s = APB_DEVICE(dev); + SysBusDevice *sbd = SYS_BUS_DEVICE(s); unsigned int i; - s = APB_DEVICE(dev); for (i = 0; i < 8; i++) { s->pci_irq_map[i] = (0x1f << 6) | (i << 2); } @@ -728,18 +728,18 @@ static int pci_pbm_init_device(SysBusDevice *dev) memory_region_init_io(&s->apb_config, OBJECT(s), &apb_config_ops, s, "apb-config", 0x10000); /* at region 0 */ - sysbus_init_mmio(dev, &s->apb_config); + sysbus_init_mmio(sbd, &s->apb_config); memory_region_init_io(&s->pci_config, OBJECT(s), &pci_config_ops, s, "apb-pci-config", 0x1000000); /* at region 1 */ - sysbus_init_mmio(dev, &s->pci_config); + sysbus_init_mmio(sbd, &s->pci_config); /* pci_ioport */ memory_region_init(&s->pci_ioport, OBJECT(s), "apb-pci-ioport", 0x1000000); /* at region 2 */ - sysbus_init_mmio(dev, &s->pci_ioport); + sysbus_init_mmio(sbd, &s->pci_ioport); return 0; } @@ -783,11 +783,10 @@ static const TypeInfo pbm_pci_host_info = { static void pbm_host_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = pci_pbm_init_device; - set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + dc->init = pci_pbm_init_device; dc->reset = pci_pbm_reset; + set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); } static const TypeInfo pbm_host_info = { From 588978c0a1e9f5596a12d124b530bdf698ed9104 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Thu, 21 Dec 2017 07:32:57 +0000 Subject: [PATCH 08/25] apb: return APBState from pci_apb_init() rather than PCIBus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a first step towards removing pci_apb_init() completely. Signed-off-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Artyom Tarasenko --- hw/pci-host/apb.c | 8 ++++---- hw/sparc64/sun4u.c | 6 ++++-- include/hw/pci-host/apb.h | 6 +++--- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c index c7837efb7a..0c709992ec 100644 --- a/hw/pci-host/apb.c +++ b/hw/pci-host/apb.c @@ -612,9 +612,9 @@ static void apb_pci_bridge_realize(PCIDevice *dev, Error **errp) pci_bridge_update_mappings(PCI_BRIDGE(br)); } -PCIBus *pci_apb_init(hwaddr special_base, - hwaddr mem_base, - qemu_irq *ivec_irqs, PCIBus **busA, PCIBus **busB) +APBState *pci_apb_init(hwaddr special_base, + hwaddr mem_base, + qemu_irq *ivec_irqs, PCIBus **busA, PCIBus **busB) { DeviceState *dev; SysBusDevice *s; @@ -675,7 +675,7 @@ PCIBus *pci_apb_init(hwaddr special_base, qdev_init_nofail(&pci_dev->qdev); *busA = pci_bridge_get_sec_bus(br); - return phb->bus; + return d; } static void pci_pbm_reset(DeviceState *d) diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index b441f1ecdb..a64ddc569d 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -482,6 +482,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem, Nvram *nvram; unsigned int i; uint64_t initrd_addr, initrd_size, kernel_addr, kernel_size, kernel_entry; + APBState *apb; PCIBus *pci_bus, *pci_busA, *pci_busB; PCIDevice *ebus, *pci_dev; SysBusDevice *s; @@ -502,8 +503,9 @@ static void sun4uv_init(MemoryRegion *address_space_mem, prom_init(hwdef->prom_addr, bios_name); ivec_irqs = qemu_allocate_irqs(sparc64_cpu_set_ivec_irq, cpu, IVEC_MAX); - pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, ivec_irqs, &pci_busA, - &pci_busB); + apb = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, ivec_irqs, &pci_busA, + &pci_busB); + pci_bus = PCI_HOST_BRIDGE(apb)->bus; /* Only in-built Simba PBMs can exist on the root bus, slot 0 on busA is reserved (leaving no slots free after on-board devices) however slots diff --git a/include/hw/pci-host/apb.h b/include/hw/pci-host/apb.h index 35d7d5ad7b..a4ef51adc8 100644 --- a/include/hw/pci-host/apb.h +++ b/include/hw/pci-host/apb.h @@ -89,7 +89,7 @@ typedef struct PBMPCIBridge { #define PBM_PCI_BRIDGE(obj) \ OBJECT_CHECK(PBMPCIBridge, (obj), TYPE_PBM_PCI_BRIDGE) -PCIBus *pci_apb_init(hwaddr special_base, - hwaddr mem_base, - qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3); +APBState *pci_apb_init(hwaddr special_base, + hwaddr mem_base, + qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3); #endif From 2a4d6af51b8330bfd7a7dd677927b8dd2f5f5f08 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Thu, 21 Dec 2017 07:32:57 +0000 Subject: [PATCH 09/25] apb: use gpios to wire up the apb device to the SPARC CPU IRQs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Artyom Tarasenko --- hw/pci-host/apb.c | 6 ++---- hw/sparc64/sparc64.c | 2 ++ hw/sparc64/sun4u.c | 12 ++++++++---- include/hw/pci-host/apb.h | 6 ++++-- include/hw/sparc/sparc64.h | 2 ++ 5 files changed, 18 insertions(+), 10 deletions(-) diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c index 0c709992ec..c0b97e41bf 100644 --- a/hw/pci-host/apb.c +++ b/hw/pci-host/apb.c @@ -79,7 +79,6 @@ do { printf("IOMMU: " fmt , ## __VA_ARGS__); } while (0) #define RESET_WCMASK 0x98000000 #define RESET_WMASK 0x60000000 -#define MAX_IVEC 0x40 #define NO_IRQ_REQUEST (MAX_IVEC + 1) static inline void pbm_set_request(APBState *s, unsigned int irq_num) @@ -614,7 +613,7 @@ static void apb_pci_bridge_realize(PCIDevice *dev, Error **errp) APBState *pci_apb_init(hwaddr special_base, hwaddr mem_base, - qemu_irq *ivec_irqs, PCIBus **busA, PCIBus **busB) + PCIBus **busA, PCIBus **busB) { DeviceState *dev; SysBusDevice *s; @@ -645,8 +644,6 @@ APBState *pci_apb_init(hwaddr special_base, memory_region_init(&d->pci_mmio, OBJECT(s), "pci-mmio", 0x100000000ULL); memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio); - d->ivec_irqs = ivec_irqs; - pci_create_simple(phb->bus, 0, "pbm-pci"); /* APB IOMMU */ @@ -721,6 +718,7 @@ static int pci_pbm_init_device(DeviceState *dev) s->obio_irq_map[i] = ((0x1f << 6) | 0x20) + i; } s->pbm_irqs = qemu_allocate_irqs(pci_apb_set_irq, s, MAX_IVEC); + qdev_init_gpio_out_named(DEVICE(s), s->ivec_irqs, "ivec-irq", MAX_IVEC); s->irq_request = NO_IRQ_REQUEST; s->pci_irq_in = 0ULL; diff --git a/hw/sparc64/sparc64.c b/hw/sparc64/sparc64.c index 9453e2c390..95a06f00b2 100644 --- a/hw/sparc64/sparc64.c +++ b/hw/sparc64/sparc64.c @@ -350,6 +350,8 @@ SPARCCPU *sparc64_cpu_devinit(const char *cpu_type, uint64_t prom_addr) uint32_t hstick_frequency = 100 * 1000000; cpu = SPARC_CPU(cpu_create(cpu_type)); + qdev_init_gpio_in_named(DEVICE(cpu), sparc64_cpu_set_ivec_irq, + "ivec-irq", IVEC_MAX); env = &cpu->env; env->tick = cpu_timer_create("tick", cpu, tick_irq, diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index a64ddc569d..2afd3f28dd 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -486,7 +486,6 @@ static void sun4uv_init(MemoryRegion *address_space_mem, PCIBus *pci_bus, *pci_busA, *pci_busB; PCIDevice *ebus, *pci_dev; SysBusDevice *s; - qemu_irq *ivec_irqs; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; DeviceState *dev; FWCfgState *fw_cfg; @@ -502,9 +501,14 @@ static void sun4uv_init(MemoryRegion *address_space_mem, prom_init(hwdef->prom_addr, bios_name); - ivec_irqs = qemu_allocate_irqs(sparc64_cpu_set_ivec_irq, cpu, IVEC_MAX); - apb = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, ivec_irqs, &pci_busA, - &pci_busB); + apb = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, &pci_busA, &pci_busB); + + /* Wire up PCI interrupts to CPU */ + for (i = 0; i < IVEC_MAX; i++) { + qdev_connect_gpio_out_named(DEVICE(apb), "ivec-irq", i, + qdev_get_gpio_in_named(DEVICE(cpu), "ivec-irq", i)); + } + pci_bus = PCI_HOST_BRIDGE(apb)->bus; /* Only in-built Simba PBMs can exist on the root bus, slot 0 on busA is diff --git a/include/hw/pci-host/apb.h b/include/hw/pci-host/apb.h index a4ef51adc8..f7ead680f3 100644 --- a/include/hw/pci-host/apb.h +++ b/include/hw/pci-host/apb.h @@ -50,6 +50,8 @@ typedef struct IOMMUState { uint64_t regs[IOMMU_NREGS]; } IOMMUState; +#define MAX_IVEC 0x40 + #define TYPE_APB "pbm" #define APB_DEVICE(obj) \ @@ -71,7 +73,7 @@ typedef struct APBState { uint32_t pci_err_irq_map[4]; uint32_t obio_irq_map[32]; qemu_irq *pbm_irqs; - qemu_irq *ivec_irqs; + qemu_irq ivec_irqs[MAX_IVEC]; unsigned int irq_request; uint32_t reset_control; unsigned int nr_resets; @@ -91,5 +93,5 @@ typedef struct PBMPCIBridge { APBState *pci_apb_init(hwaddr special_base, hwaddr mem_base, - qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3); + PCIBus **bus2, PCIBus **bus3); #endif diff --git a/include/hw/sparc/sparc64.h b/include/hw/sparc/sparc64.h index ca3bb4be71..5af4344459 100644 --- a/include/hw/sparc/sparc64.h +++ b/include/hw/sparc/sparc64.h @@ -1,4 +1,6 @@ +#define IVEC_MAX 0x40 + SPARCCPU *sparc64_cpu_devinit(const char *cpu_type, uint64_t prom_addr); void sparc64_cpu_set_ivec_irq(void *opaque, int irq, int level); From 4272ad40189c73324da59047f5232ec795111c4b Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Thu, 21 Dec 2017 07:32:57 +0000 Subject: [PATCH 10/25] apb: move the two secondary PCI bridges objects into APBState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This enables us to remove these parameters from pci_apb_init(). Signed-off-by: Mark Cave-Ayland Reviewed-by: Artyom Tarasenko Reviewed-by: Philippe Mathieu-Daudé --- hw/pci-host/apb.c | 14 +++++--------- hw/sparc64/sun4u.c | 5 ++++- include/hw/pci-host/apb.h | 5 +++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c index c0b97e41bf..823661a8a6 100644 --- a/hw/pci-host/apb.c +++ b/hw/pci-host/apb.c @@ -612,8 +612,7 @@ static void apb_pci_bridge_realize(PCIDevice *dev, Error **errp) } APBState *pci_apb_init(hwaddr special_base, - hwaddr mem_base, - PCIBus **busA, PCIBus **busB) + hwaddr mem_base) { DeviceState *dev; SysBusDevice *s; @@ -621,7 +620,6 @@ APBState *pci_apb_init(hwaddr special_base, APBState *d; IOMMUState *is; PCIDevice *pci_dev; - PCIBridge *br; /* Ultrasparc PBM main bus */ dev = qdev_create(NULL, TYPE_APB); @@ -659,18 +657,16 @@ APBState *pci_apb_init(hwaddr special_base, /* APB secondary busses */ pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 0), true, TYPE_PBM_PCI_BRIDGE); - br = PCI_BRIDGE(pci_dev); - pci_bridge_map_irq(br, "pciB", pci_pbm_map_irq); + d->bridgeB = PCI_BRIDGE(pci_dev); + pci_bridge_map_irq(d->bridgeB, "pciB", pci_pbm_map_irq); qdev_init_nofail(&pci_dev->qdev); - *busB = pci_bridge_get_sec_bus(br); pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 1), true, TYPE_PBM_PCI_BRIDGE); - br = PCI_BRIDGE(pci_dev); - pci_bridge_map_irq(br, "pciA", pci_pbm_map_irq); + d->bridgeA = PCI_BRIDGE(pci_dev); + pci_bridge_map_irq(d->bridgeA, "pciA", pci_pbm_map_irq); qdev_prop_set_bit(DEVICE(pci_dev), "busA", true); qdev_init_nofail(&pci_dev->qdev); - *busA = pci_bridge_get_sec_bus(br); return d; } diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index 2afd3f28dd..47952befcb 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -27,6 +27,7 @@ #include "cpu.h" #include "hw/hw.h" #include "hw/pci/pci.h" +#include "hw/pci/pci_bridge.h" #include "hw/pci/pci_bus.h" #include "hw/pci-host/apb.h" #include "hw/i386/pc.h" @@ -501,7 +502,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem, prom_init(hwdef->prom_addr, bios_name); - apb = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, &pci_busA, &pci_busB); + apb = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE); /* Wire up PCI interrupts to CPU */ for (i = 0; i < IVEC_MAX; i++) { @@ -510,6 +511,8 @@ static void sun4uv_init(MemoryRegion *address_space_mem, } pci_bus = PCI_HOST_BRIDGE(apb)->bus; + pci_busA = pci_bridge_get_sec_bus(apb->bridgeA); + pci_busB = pci_bridge_get_sec_bus(apb->bridgeB); /* Only in-built Simba PBMs can exist on the root bus, slot 0 on busA is reserved (leaving no slots free after on-board devices) however slots diff --git a/include/hw/pci-host/apb.h b/include/hw/pci-host/apb.h index f7ead680f3..ae15d8ce59 100644 --- a/include/hw/pci-host/apb.h +++ b/include/hw/pci-host/apb.h @@ -68,6 +68,8 @@ typedef struct APBState { MemoryRegion pci_ioport; uint64_t pci_irq_in; IOMMUState iommu; + PCIBridge *bridgeA; + PCIBridge *bridgeB; uint32_t pci_control[16]; uint32_t pci_irq_map[8]; uint32_t pci_err_irq_map[4]; @@ -92,6 +94,5 @@ typedef struct PBMPCIBridge { OBJECT_CHECK(PBMPCIBridge, (obj), TYPE_PBM_PCI_BRIDGE) APBState *pci_apb_init(hwaddr special_base, - hwaddr mem_base, - PCIBus **bus2, PCIBus **bus3); + hwaddr mem_base); #endif From cacd05805eeea393ec929fe841f9a68aa2140d92 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Thu, 21 Dec 2017 07:32:57 +0000 Subject: [PATCH 11/25] apb: remove pci_apb_init() and instantiate APB device using qdev MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit By making the special_base and mem_base values qdev properties, we can move the remaining parts of pci_apb_init() into the pbm init() and realize() functions. This finally allows us to instantiate the APB directly using standard qdev create/init functions in sun4u.c. Signed-off-by: Mark Cave-Ayland Reviewed-by: Artyom Tarasenko Reviewed-by: Philippe Mathieu-Daudé --- hw/pci-host/apb.c | 126 +++++++++++++++++++------------------- hw/sparc64/sun4u.c | 6 +- include/hw/pci-host/apb.h | 4 +- 3 files changed, 69 insertions(+), 67 deletions(-) diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c index 823661a8a6..787be744a2 100644 --- a/hw/pci-host/apb.c +++ b/hw/pci-host/apb.c @@ -611,66 +611,6 @@ static void apb_pci_bridge_realize(PCIDevice *dev, Error **errp) pci_bridge_update_mappings(PCI_BRIDGE(br)); } -APBState *pci_apb_init(hwaddr special_base, - hwaddr mem_base) -{ - DeviceState *dev; - SysBusDevice *s; - PCIHostState *phb; - APBState *d; - IOMMUState *is; - PCIDevice *pci_dev; - - /* Ultrasparc PBM main bus */ - dev = qdev_create(NULL, TYPE_APB); - d = APB_DEVICE(dev); - phb = PCI_HOST_BRIDGE(dev); - phb->bus = pci_register_bus(DEVICE(phb), "pci", - pci_apb_set_irq, pci_apb_map_irq, d, - &d->pci_mmio, - &d->pci_ioport, - 0, 32, TYPE_PCI_BUS); - qdev_init_nofail(dev); - s = SYS_BUS_DEVICE(dev); - /* apb_config */ - sysbus_mmio_map(s, 0, special_base); - /* PCI configuration space */ - sysbus_mmio_map(s, 1, special_base + 0x1000000ULL); - /* pci_ioport */ - sysbus_mmio_map(s, 2, special_base + 0x2000000ULL); - - memory_region_init(&d->pci_mmio, OBJECT(s), "pci-mmio", 0x100000000ULL); - memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio); - - pci_create_simple(phb->bus, 0, "pbm-pci"); - - /* APB IOMMU */ - is = &d->iommu; - memset(is, 0, sizeof(IOMMUState)); - - memory_region_init_iommu(&is->iommu, sizeof(is->iommu), - TYPE_APB_IOMMU_MEMORY_REGION, OBJECT(dev), - "iommu-apb", UINT64_MAX); - address_space_init(&is->iommu_as, MEMORY_REGION(&is->iommu), "pbm-as"); - pci_setup_iommu(phb->bus, pbm_pci_dma_iommu, is); - - /* APB secondary busses */ - pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 0), true, - TYPE_PBM_PCI_BRIDGE); - d->bridgeB = PCI_BRIDGE(pci_dev); - pci_bridge_map_irq(d->bridgeB, "pciB", pci_pbm_map_irq); - qdev_init_nofail(&pci_dev->qdev); - - pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 1), true, - TYPE_PBM_PCI_BRIDGE); - d->bridgeA = PCI_BRIDGE(pci_dev); - pci_bridge_map_irq(d->bridgeA, "pciA", pci_pbm_map_irq); - qdev_prop_set_bit(DEVICE(pci_dev), "busA", true); - qdev_init_nofail(&pci_dev->qdev); - - return d; -} - static void pci_pbm_reset(DeviceState *d) { unsigned int i; @@ -698,10 +638,62 @@ static const MemoryRegionOps pci_config_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -static int pci_pbm_init_device(DeviceState *dev) +static void pci_pbm_realize(DeviceState *dev, Error **errp) { APBState *s = APB_DEVICE(dev); + PCIHostState *phb = PCI_HOST_BRIDGE(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(s); + PCIDevice *pci_dev; + IOMMUState *is; + + /* apb_config */ + sysbus_mmio_map(sbd, 0, s->special_base); + /* PCI configuration space */ + sysbus_mmio_map(sbd, 1, s->special_base + 0x1000000ULL); + /* pci_ioport */ + sysbus_mmio_map(sbd, 2, s->special_base + 0x2000000ULL); + + memory_region_init(&s->pci_mmio, OBJECT(s), "pci-mmio", 0x100000000ULL); + memory_region_add_subregion(get_system_memory(), s->mem_base, + &s->pci_mmio); + + phb->bus = pci_register_bus(dev, "pci", + pci_apb_set_irq, pci_apb_map_irq, s, + &s->pci_mmio, + &s->pci_ioport, + 0, 32, TYPE_PCI_BUS); + + pci_create_simple(phb->bus, 0, "pbm-pci"); + + /* APB IOMMU */ + is = &s->iommu; + memset(is, 0, sizeof(IOMMUState)); + + memory_region_init_iommu(&is->iommu, sizeof(is->iommu), + TYPE_APB_IOMMU_MEMORY_REGION, OBJECT(dev), + "iommu-apb", UINT64_MAX); + address_space_init(&is->iommu_as, MEMORY_REGION(&is->iommu), "pbm-as"); + pci_setup_iommu(phb->bus, pbm_pci_dma_iommu, is); + + /* APB secondary busses */ + pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 0), true, + TYPE_PBM_PCI_BRIDGE); + s->bridgeB = PCI_BRIDGE(pci_dev); + pci_bridge_map_irq(s->bridgeB, "pciB", pci_pbm_map_irq); + qdev_init_nofail(&pci_dev->qdev); + + pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 1), true, + TYPE_PBM_PCI_BRIDGE); + s->bridgeA = PCI_BRIDGE(pci_dev); + pci_bridge_map_irq(s->bridgeA, "pciA", pci_pbm_map_irq); + qdev_prop_set_bit(DEVICE(pci_dev), "busA", true); + qdev_init_nofail(&pci_dev->qdev); +} + +static void pci_pbm_init(Object *obj) +{ + APBState *s = APB_DEVICE(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); unsigned int i; for (i = 0; i < 8; i++) { @@ -734,8 +726,6 @@ static int pci_pbm_init_device(DeviceState *dev) /* at region 2 */ sysbus_init_mmio(sbd, &s->pci_ioport); - - return 0; } static void pbm_pci_host_realize(PCIDevice *d, Error **errp) @@ -774,12 +764,19 @@ static const TypeInfo pbm_pci_host_info = { }, }; +static Property pbm_pci_host_properties[] = { + DEFINE_PROP_UINT64("special-base", APBState, special_base, 0), + DEFINE_PROP_UINT64("mem-base", APBState, mem_base, 0), + DEFINE_PROP_END_OF_LIST(), +}; + static void pbm_host_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - dc->init = pci_pbm_init_device; + dc->realize = pci_pbm_realize; dc->reset = pci_pbm_reset; + dc->props = pbm_pci_host_properties; set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); } @@ -787,6 +784,7 @@ static const TypeInfo pbm_host_info = { .name = TYPE_APB, .parent = TYPE_PCI_HOST_BRIDGE, .instance_size = sizeof(APBState), + .instance_init = pci_pbm_init, .class_init = pbm_host_class_init, }; diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index 47952befcb..0a30fb8d08 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -502,7 +502,11 @@ static void sun4uv_init(MemoryRegion *address_space_mem, prom_init(hwdef->prom_addr, bios_name); - apb = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE); + /* Init APB (PCI host bridge) */ + apb = APB_DEVICE(qdev_create(NULL, TYPE_APB)); + qdev_prop_set_uint64(DEVICE(apb), "special-base", APB_SPECIAL_BASE); + qdev_prop_set_uint64(DEVICE(apb), "mem-base", APB_MEM_BASE); + qdev_init_nofail(DEVICE(apb)); /* Wire up PCI interrupts to CPU */ for (i = 0; i < IVEC_MAX; i++) { diff --git a/include/hw/pci-host/apb.h b/include/hw/pci-host/apb.h index ae15d8ce59..f0074f7a51 100644 --- a/include/hw/pci-host/apb.h +++ b/include/hw/pci-host/apb.h @@ -62,6 +62,8 @@ typedef struct IOMMUState { typedef struct APBState { PCIHostState parent_obj; + hwaddr special_base; + hwaddr mem_base; MemoryRegion apb_config; MemoryRegion pci_config; MemoryRegion pci_mmio; @@ -93,6 +95,4 @@ typedef struct PBMPCIBridge { #define PBM_PCI_BRIDGE(obj) \ OBJECT_CHECK(PBMPCIBridge, (obj), TYPE_PBM_PCI_BRIDGE) -APBState *pci_apb_init(hwaddr special_base, - hwaddr mem_base); #endif From d9e4d6829c14d3e3d71906b0dc7e7ec9a77654bf Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Thu, 21 Dec 2017 07:32:57 +0000 Subject: [PATCH 12/25] apb: split pci_pbm_map_irq() into separate functions for bus A and bus B After the previous refactoring it is now possible to use separate functions to improve the clarity of the interrupt paths. Signed-off-by: Mark Cave-Ayland Reviewed-by: Artyom Tarasenko --- hw/pci-host/apb.c | 47 +++++++++++++++++++++-------------------------- 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c index 787be744a2..8bdbbfd214 100644 --- a/hw/pci-host/apb.c +++ b/hw/pci-host/apb.c @@ -517,32 +517,27 @@ static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num) return irq_num; } -static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num) +static int pci_pbmA_map_irq(PCIDevice *pci_dev, int irq_num) { - PBMPCIBridge *br = PBM_PCI_BRIDGE(pci_bridge_get_device( - PCI_BUS(qdev_get_parent_bus(DEVICE(pci_dev))))); - - int bus_offset; - if (br->busA) { - bus_offset = 0x0; - - /* The on-board devices have fixed (legacy) OBIO intnos */ - switch (PCI_SLOT(pci_dev->devfn)) { - case 1: - /* Onboard NIC */ - return 0x21; - case 3: - /* Onboard IDE */ - return 0x20; - - default: - /* Normal intno, fall through */ - break; - } - } else { - bus_offset = 0x10; + /* The on-board devices have fixed (legacy) OBIO intnos */ + switch (PCI_SLOT(pci_dev->devfn)) { + case 1: + /* Onboard NIC */ + return 0x21; + case 3: + /* Onboard IDE */ + return 0x20; + default: + /* Normal intno, fall through */ + break; } - return (bus_offset + (PCI_SLOT(pci_dev->devfn) << 2) + irq_num) & 0x1f; + + return ((PCI_SLOT(pci_dev->devfn) << 2) + irq_num) & 0x1f; +} + +static int pci_pbmB_map_irq(PCIDevice *pci_dev, int irq_num) +{ + return (0x10 + (PCI_SLOT(pci_dev->devfn) << 2) + irq_num) & 0x1f; } static void pci_apb_set_irq(void *opaque, int irq_num, int level) @@ -679,13 +674,13 @@ static void pci_pbm_realize(DeviceState *dev, Error **errp) pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 0), true, TYPE_PBM_PCI_BRIDGE); s->bridgeB = PCI_BRIDGE(pci_dev); - pci_bridge_map_irq(s->bridgeB, "pciB", pci_pbm_map_irq); + pci_bridge_map_irq(s->bridgeB, "pciB", pci_pbmB_map_irq); qdev_init_nofail(&pci_dev->qdev); pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 1), true, TYPE_PBM_PCI_BRIDGE); s->bridgeA = PCI_BRIDGE(pci_dev); - pci_bridge_map_irq(s->bridgeA, "pciA", pci_pbm_map_irq); + pci_bridge_map_irq(s->bridgeA, "pciA", pci_pbmA_map_irq); qdev_prop_set_bit(DEVICE(pci_dev), "busA", true); qdev_init_nofail(&pci_dev->qdev); } From 33c5eb02c4f51515896a5a13cb68f6f01ce8d0af Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Thu, 21 Dec 2017 07:32:57 +0000 Subject: [PATCH 13/25] apb: remove busA property from PBMPCIBridge state Since the previous commit the only remaining use of the qdev busA property is to configure the PCI bridge in front of the onboard ebus devices differently to allow early OpenBIOS serial console access. Instead we can now manually update the PCI configuration for bridge A in pci_pbm_reset() and thus completely remove the busA property from the PBMPCIBridge state. Signed-off-by: Mark Cave-Ayland Reviewed-by: Artyom Tarasenko --- hw/pci-host/apb.c | 29 +++++++++++++---------------- include/hw/pci-host/apb.h | 3 --- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c index 8bdbbfd214..5562f1adfd 100644 --- a/hw/pci-host/apb.c +++ b/hw/pci-host/apb.c @@ -581,18 +581,11 @@ static void apb_pci_bridge_realize(PCIDevice *dev, Error **errp) * the reset value should be zero unless the boot pin is tied high * (which is true) and thus it should be PCI_COMMAND_MEMORY. */ - uint16_t cmd = PCI_COMMAND_MEMORY; PBMPCIBridge *br = PBM_PCI_BRIDGE(dev); pci_bridge_initfn(dev, TYPE_PCI_BUS); - /* If initialising busA, ensure that we allow IO transactions so that - we get the early serial console until OpenBIOS configures the bridge */ - if (br->busA) { - cmd |= PCI_COMMAND_IO; - } - - pci_set_word(dev->config + PCI_COMMAND, cmd); + pci_set_word(dev->config + PCI_COMMAND, PCI_COMMAND_MEMORY); pci_set_word(dev->config + PCI_STATUS, PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ | PCI_STATUS_DEVSEL_MEDIUM); @@ -608,8 +601,10 @@ static void apb_pci_bridge_realize(PCIDevice *dev, Error **errp) static void pci_pbm_reset(DeviceState *d) { - unsigned int i; APBState *s = APB_DEVICE(d); + PCIDevice *pci_dev; + unsigned int i; + uint16_t cmd; for (i = 0; i < 8; i++) { s->pci_irq_map[i] &= PBM_PCI_IMR_MASK; @@ -625,6 +620,15 @@ static void pci_pbm_reset(DeviceState *d) /* Power on reset */ s->reset_control = POR; } + + /* As this is the busA PCI bridge which contains the on-board devices + * attached to the ebus, ensure that we initially allow IO transactions + * so that we get the early serial console until OpenBIOS can properly + * configure the PCI bridge itself */ + pci_dev = PCI_DEVICE(s->bridgeA); + cmd = pci_get_word(pci_dev->config + PCI_COMMAND); + pci_set_word(pci_dev->config + PCI_COMMAND, cmd | PCI_COMMAND_IO); + pci_bridge_update_mappings(PCI_BRIDGE(pci_dev)); } static const MemoryRegionOps pci_config_ops = { @@ -681,7 +685,6 @@ static void pci_pbm_realize(DeviceState *dev, Error **errp) TYPE_PBM_PCI_BRIDGE); s->bridgeA = PCI_BRIDGE(pci_dev); pci_bridge_map_irq(s->bridgeA, "pciA", pci_pbmA_map_irq); - qdev_prop_set_bit(DEVICE(pci_dev), "busA", true); qdev_init_nofail(&pci_dev->qdev); } @@ -783,11 +786,6 @@ static const TypeInfo pbm_host_info = { .class_init = pbm_host_class_init, }; -static Property pbm_pci_properties[] = { - DEFINE_PROP_BOOL("busA", PBMPCIBridge, busA, false), - DEFINE_PROP_END_OF_LIST(), -}; - static void pbm_pci_bridge_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -803,7 +801,6 @@ static void pbm_pci_bridge_class_init(ObjectClass *klass, void *data) set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); dc->reset = pci_bridge_reset; dc->vmsd = &vmstate_pci_device; - dc->props = pbm_pci_properties; } static const TypeInfo pbm_pci_bridge_info = { diff --git a/include/hw/pci-host/apb.h b/include/hw/pci-host/apb.h index f0074f7a51..dd49437ff1 100644 --- a/include/hw/pci-host/apb.h +++ b/include/hw/pci-host/apb.h @@ -86,9 +86,6 @@ typedef struct APBState { typedef struct PBMPCIBridge { /*< private >*/ PCIBridge parent_obj; - - /* Is this busA with in-built devices (ebus)? */ - bool busA; } PBMPCIBridge; #define TYPE_PBM_PCI_BRIDGE "pbm-bridge" From 4b10c8d7012eea39e96819545eb21d28228831c6 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Thu, 21 Dec 2017 07:32:57 +0000 Subject: [PATCH 14/25] ebus: wire up OBIO interrupts to APB pbm via qdev GPIOs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This enables us to remove the static array mapping in the ISA IRQ handler (and the embedded reference to the APB device) by formalising the interrupt wiring via the qdev GPIO API. For more clarity we replace the APB OBIO interrupt numbers with constants designating the interrupt source, and rename isa_irq_handler() to ebus_isa_irq_handler(). Signed-off-by: Mark Cave-Ayland Reviewed-by: Artyom Tarasenko Reviewed-by: Philippe Mathieu-Daudé --- hw/pci-host/apb.c | 2 +- hw/sparc64/sun4u.c | 47 ++++++++++++++++++++------------------- include/hw/pci-host/apb.h | 8 ++++++- 3 files changed, 32 insertions(+), 25 deletions(-) diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c index 5562f1adfd..54edbddb03 100644 --- a/hw/pci-host/apb.c +++ b/hw/pci-host/apb.c @@ -703,7 +703,7 @@ static void pci_pbm_init(Object *obj) for (i = 0; i < 32; i++) { s->obio_irq_map[i] = ((0x1f << 6) | 0x20) + i; } - s->pbm_irqs = qemu_allocate_irqs(pci_apb_set_irq, s, MAX_IVEC); + qdev_init_gpio_in_named(DEVICE(s), pci_apb_set_irq, "pbm-irq", MAX_IVEC); qdev_init_gpio_out_named(DEVICE(s), s->ivec_irqs, "ivec-irq", MAX_IVEC); s->irq_request = NO_IRQ_REQUEST; s->pci_irq_in = 0ULL; diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index 0a30fb8d08..1456c3370d 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -86,6 +86,7 @@ typedef struct EbusState { PCIDevice parent_obj; ISABus *isa_bus; + qemu_irq isa_bus_irqs[ISA_NUM_IRQS]; uint64_t console_serial_base; MemoryRegion bar0; MemoryRegion bar1; @@ -211,23 +212,15 @@ typedef struct ResetData { uint64_t prom_addr; } ResetData; -static void isa_irq_handler(void *opaque, int n, int level) +static void ebus_isa_irq_handler(void *opaque, int n, int level) { - static const int isa_irq_to_ivec[16] = { - [1] = 0x29, /* keyboard */ - [4] = 0x2b, /* serial */ - [6] = 0x27, /* floppy */ - [7] = 0x22, /* parallel */ - [12] = 0x2a, /* mouse */ - }; - qemu_irq *irqs = opaque; - int ivec; + EbusState *s = EBUS(opaque); + qemu_irq irq = s->isa_bus_irqs[n]; - assert(n < ARRAY_SIZE(isa_irq_to_ivec)); - ivec = isa_irq_to_ivec[n]; - EBUS_DPRINTF("Set ISA IRQ %d level %d -> ivec 0x%x\n", n, level, ivec); - if (ivec) { - qemu_set_irq(irqs[ivec], level); + /* Pass ISA bus IRQs onto their gpio equivalent */ + EBUS_DPRINTF("Set ISA IRQ %d level %d\n", n, level); + if (irq) { + qemu_set_irq(irq, level); } } @@ -235,7 +228,6 @@ static void isa_irq_handler(void *opaque, int n, int level) static void ebus_realize(PCIDevice *pci_dev, Error **errp) { EbusState *s = EBUS(pci_dev); - APBState *apb; DeviceState *dev; qemu_irq *isa_irq; DriveInfo *fd[MAX_FD]; @@ -248,14 +240,11 @@ static void ebus_realize(PCIDevice *pci_dev, Error **errp) return; } - apb = APB_DEVICE(object_resolve_path_type("", TYPE_APB, NULL)); - if (!apb) { - error_setg(errp, "unable to locate APB PCI host bridge"); - return; - } - - isa_irq = qemu_allocate_irqs(isa_irq_handler, apb->pbm_irqs, 16); + /* ISA bus */ + isa_irq = qemu_allocate_irqs(ebus_isa_irq_handler, s, ISA_NUM_IRQS); isa_bus_irqs(s->isa_bus, isa_irq); + qdev_init_gpio_out_named(DEVICE(s), s->isa_bus_irqs, "isa-irq", + ISA_NUM_IRQS); /* Serial ports */ i = 0; @@ -530,6 +519,18 @@ static void sun4uv_init(MemoryRegion *address_space_mem, hwdef->console_serial_base); qdev_init_nofail(DEVICE(ebus)); + /* Wire up "well-known" ISA IRQs to APB legacy obio IRQs */ + qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 7, + qdev_get_gpio_in_named(DEVICE(apb), "pbm-irq", OBIO_LPT_IRQ)); + qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 6, + qdev_get_gpio_in_named(DEVICE(apb), "pbm-irq", OBIO_FDD_IRQ)); + qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 1, + qdev_get_gpio_in_named(DEVICE(apb), "pbm-irq", OBIO_KBD_IRQ)); + qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 12, + qdev_get_gpio_in_named(DEVICE(apb), "pbm-irq", OBIO_MSE_IRQ)); + qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 4, + qdev_get_gpio_in_named(DEVICE(apb), "pbm-irq", OBIO_SER_IRQ)); + pci_dev = pci_create_simple(pci_busA, PCI_DEVFN(2, 0), "VGA"); memset(&macaddr, 0, sizeof(MACAddr)); diff --git a/include/hw/pci-host/apb.h b/include/hw/pci-host/apb.h index dd49437ff1..09ebd53f60 100644 --- a/include/hw/pci-host/apb.h +++ b/include/hw/pci-host/apb.h @@ -52,6 +52,13 @@ typedef struct IOMMUState { #define MAX_IVEC 0x40 +/* OBIO IVEC IRQs */ +#define OBIO_LPT_IRQ 0x22 +#define OBIO_FDD_IRQ 0x27 +#define OBIO_KBD_IRQ 0x29 +#define OBIO_MSE_IRQ 0x2a +#define OBIO_SER_IRQ 0x2b + #define TYPE_APB "pbm" #define APB_DEVICE(obj) \ @@ -76,7 +83,6 @@ typedef struct APBState { uint32_t pci_irq_map[8]; uint32_t pci_err_irq_map[4]; uint32_t obio_irq_map[32]; - qemu_irq *pbm_irqs; qemu_irq ivec_irqs[MAX_IVEC]; unsigned int irq_request; uint32_t reset_control; From a5546222e3eafc9b6bc784c1bffbc8e1614d5e5b Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Thu, 21 Dec 2017 07:32:57 +0000 Subject: [PATCH 15/25] apb: replace OBIO interrupt numbers in pci_pbmA_map_irq() with constants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Following on from the previous commit, we can also do the same with with legacy OBIO interrupts in pci_pbmA_map_irq(). Signed-off-by: Mark Cave-Ayland Reviewed-by: Artyom Tarasenko Reviewed-by: Philippe Mathieu-Daudé --- hw/pci-host/apb.c | 4 ++-- include/hw/pci-host/apb.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c index 54edbddb03..44b08c090e 100644 --- a/hw/pci-host/apb.c +++ b/hw/pci-host/apb.c @@ -523,10 +523,10 @@ static int pci_pbmA_map_irq(PCIDevice *pci_dev, int irq_num) switch (PCI_SLOT(pci_dev->devfn)) { case 1: /* Onboard NIC */ - return 0x21; + return OBIO_NIC_IRQ; case 3: /* Onboard IDE */ - return 0x20; + return OBIO_HDD_IRQ; default: /* Normal intno, fall through */ break; diff --git a/include/hw/pci-host/apb.h b/include/hw/pci-host/apb.h index 09ebd53f60..6194c8cbad 100644 --- a/include/hw/pci-host/apb.h +++ b/include/hw/pci-host/apb.h @@ -53,6 +53,8 @@ typedef struct IOMMUState { #define MAX_IVEC 0x40 /* OBIO IVEC IRQs */ +#define OBIO_HDD_IRQ 0x20 +#define OBIO_NIC_IRQ 0x21 #define OBIO_LPT_IRQ 0x22 #define OBIO_FDD_IRQ 0x27 #define OBIO_KBD_IRQ 0x29 From 8bcf1c7962c297ea4cf47a8f7400afca38bc270f Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Thu, 21 Dec 2017 07:32:57 +0000 Subject: [PATCH 16/25] sparc64: introduce trace-events for hw/sparc64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is in preparation for switching code in hw/sparc64 from DPRINTF over to trace events. Signed-off-by: Mark Cave-Ayland Reviewed-by: Artyom Tarasenko Reviewed-by: Philippe Mathieu-Daudé --- Makefile.objs | 1 + hw/sparc64/trace-events | 1 + 2 files changed, 2 insertions(+) create mode 100644 hw/sparc64/trace-events diff --git a/Makefile.objs b/Makefile.objs index 285c6f3c15..c8b1bba593 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -140,6 +140,7 @@ trace-events-subdirs += hw/input trace-events-subdirs += hw/timer trace-events-subdirs += hw/dma trace-events-subdirs += hw/sparc +trace-events-subdirs += hw/sparc64 trace-events-subdirs += hw/sd trace-events-subdirs += hw/isa trace-events-subdirs += hw/mem diff --git a/hw/sparc64/trace-events b/hw/sparc64/trace-events new file mode 100644 index 0000000000..9284b1fbad --- /dev/null +++ b/hw/sparc64/trace-events @@ -0,0 +1 @@ +# See docs/devel/tracing.txt for syntax documentation. From 69520948e10dde53cb2f49a0c2809847347ae042 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Thu, 21 Dec 2017 07:32:57 +0000 Subject: [PATCH 17/25] sun4u: switch from EBUS_DPRINTF() macro to trace-events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Artyom Tarasenko --- hw/sparc64/sun4u.c | 12 ++---------- hw/sparc64/trace-events | 3 +++ 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index 1456c3370d..5d802bdfde 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -47,17 +47,9 @@ #include "hw/ide/pci.h" #include "hw/loader.h" #include "elf.h" +#include "trace.h" #include "qemu/cutils.h" -//#define DEBUG_EBUS - -#ifdef DEBUG_EBUS -#define EBUS_DPRINTF(fmt, ...) \ - do { printf("EBUS: " fmt , ## __VA_ARGS__); } while (0) -#else -#define EBUS_DPRINTF(fmt, ...) -#endif - #define KERNEL_LOAD_ADDR 0x00404000 #define CMDLINE_ADDR 0x003ff000 #define PROM_SIZE_MAX (4 * 1024 * 1024) @@ -218,7 +210,7 @@ static void ebus_isa_irq_handler(void *opaque, int n, int level) qemu_irq irq = s->isa_bus_irqs[n]; /* Pass ISA bus IRQs onto their gpio equivalent */ - EBUS_DPRINTF("Set ISA IRQ %d level %d\n", n, level); + trace_ebus_isa_irq_handler(n, level); if (irq) { qemu_set_irq(irq, level); } diff --git a/hw/sparc64/trace-events b/hw/sparc64/trace-events index 9284b1fbad..04d80b7f70 100644 --- a/hw/sparc64/trace-events +++ b/hw/sparc64/trace-events @@ -1 +1,4 @@ # See docs/devel/tracing.txt for syntax documentation. + +# hw/sparc64/sun4u.c +ebus_isa_irq_handler(int n, int level) "Set ISA IRQ %d level %d" From ba51ef25571c58d09dcfe1f67056b30327dfaa46 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Mon, 8 Jan 2018 18:16:34 +0000 Subject: [PATCH 18/25] sun4m: move sun4m_iommu.c from hw/dma to hw/sparc This seems more appropriate and brings sun4m in line with the other architectures. Signed-off-by: Mark Cave-Ayland Acked-by: Artyom Tarasenko --- hw/dma/Makefile.objs | 1 - hw/dma/trace-events | 10 ---------- hw/sparc/Makefile.objs | 2 +- hw/{dma => sparc}/sun4m_iommu.c | 11 ++++++----- hw/sparc/trace-events | 10 ++++++++++ 5 files changed, 17 insertions(+), 17 deletions(-) rename hw/{dma => sparc}/sun4m_iommu.c (98%) diff --git a/hw/dma/Makefile.objs b/hw/dma/Makefile.objs index 087c8e6855..0b3a009b87 100644 --- a/hw/dma/Makefile.objs +++ b/hw/dma/Makefile.objs @@ -8,7 +8,6 @@ common-obj-$(CONFIG_XILINX_AXI) += xilinx_axidma.o common-obj-$(CONFIG_ZYNQ_DEVCFG) += xlnx-zynq-devcfg.o common-obj-$(CONFIG_ETRAXFS) += etraxfs_dma.o common-obj-$(CONFIG_STP2000) += sparc32_dma.o -common-obj-$(CONFIG_SUN4M) += sun4m_iommu.o obj-$(CONFIG_XLNX_ZYNQMP) += xlnx_dpdma.o obj-$(CONFIG_OMAP) += omap_dma.o soc_dma.o diff --git a/hw/dma/trace-events b/hw/dma/trace-events index 6b367f053b..22f53d0ff2 100644 --- a/hw/dma/trace-events +++ b/hw/dma/trace-events @@ -18,15 +18,5 @@ sparc32_dma_mem_writel(uint64_t addr, uint32_t old, uint32_t val) "write dmareg sparc32_dma_enable_raise(void) "Raise DMA enable" sparc32_dma_enable_lower(void) "Lower DMA enable" -# hw/dma/sun4m_iommu.c -sun4m_iommu_mem_readl(uint64_t addr, uint32_t ret) "read reg[0x%"PRIx64"] = 0x%x" -sun4m_iommu_mem_writel(uint64_t addr, uint32_t val) "write reg[0x%"PRIx64"] = 0x%x" -sun4m_iommu_mem_writel_ctrl(uint64_t iostart) "iostart = 0x%"PRIx64 -sun4m_iommu_mem_writel_tlbflush(uint32_t val) "tlb flush 0x%x" -sun4m_iommu_mem_writel_pgflush(uint32_t val) "page flush 0x%x" -sun4m_iommu_page_get_flags(uint64_t pa, uint64_t iopte, uint32_t ret) "get flags addr 0x%"PRIx64" => pte 0x%"PRIx64", *pte = 0x%x" -sun4m_iommu_translate_pa(uint64_t addr, uint64_t pa, uint32_t iopte) "xlate dva 0x%"PRIx64" => pa 0x%"PRIx64" iopte = 0x%x" -sun4m_iommu_bad_addr(uint64_t addr) "bad addr 0x%"PRIx64 - # hw/dma/i8257.c i8257_unregistered_dma(int nchan, int dma_pos, int dma_len) "unregistered DMA channel used nchan=%d dma_pos=%d dma_len=%d" diff --git a/hw/sparc/Makefile.objs b/hw/sparc/Makefile.objs index c987b5b5df..e2d0828c39 100644 --- a/hw/sparc/Makefile.objs +++ b/hw/sparc/Makefile.objs @@ -1 +1 @@ -obj-y += sun4m.o leon3.o +obj-y += sun4m_iommu.o sun4m.o leon3.o diff --git a/hw/dma/sun4m_iommu.c b/hw/sparc/sun4m_iommu.c similarity index 98% rename from hw/dma/sun4m_iommu.c rename to hw/sparc/sun4m_iommu.c index 30a05e8823..72a9af555f 100644 --- a/hw/dma/sun4m_iommu.c +++ b/hw/sparc/sun4m_iommu.c @@ -125,7 +125,7 @@ #define IOMMU_PAGE_SHIFT 12 #define IOMMU_PAGE_SIZE (1 << IOMMU_PAGE_SHIFT) -#define IOMMU_PAGE_MASK ~(IOMMU_PAGE_SIZE - 1) +#define IOMMU_PAGE_MASK (~(IOMMU_PAGE_SIZE - 1)) static uint64_t iommu_mem_read(void *opaque, hwaddr addr, unsigned size) @@ -218,8 +218,8 @@ static void iommu_mem_write(void *opaque, hwaddr addr, s->regs[saddr] = val & IOMMU_SBCFG_MASK; break; case IOMMU_ARBEN: - // XXX implement SBus probing: fault when reading unmapped - // addresses, fault cause and address stored to MMU/IOMMU + /* XXX implement SBus probing: fault when reading unmapped + addresses, fault cause and address stored to MMU/IOMMU */ s->regs[saddr] = (val & IOMMU_ARBEN_MASK) | IOMMU_MID; break; case IOMMU_MASK_ID: @@ -272,8 +272,9 @@ static void iommu_bad_addr(IOMMUState *s, hwaddr addr, trace_sun4m_iommu_bad_addr(addr); s->regs[IOMMU_AFSR] = IOMMU_AFSR_ERR | IOMMU_AFSR_LE | IOMMU_AFSR_RESV | IOMMU_AFSR_FAV; - if (!is_write) + if (!is_write) { s->regs[IOMMU_AFSR] |= IOMMU_AFSR_RD; + } s->regs[IOMMU_AFAR] = addr; qemu_irq_raise(s->irq); } @@ -322,7 +323,7 @@ static IOMMUTLBEntry sun4m_translate_iommu(IOMMUMemoryRegion *iommu, } static const VMStateDescription vmstate_iommu = { - .name ="iommu", + .name = "iommu", .version_id = 2, .minimum_version_id = 2, .fields = (VMStateField[]) { diff --git a/hw/sparc/trace-events b/hw/sparc/trace-events index efd765cbe6..6e7259f8f8 100644 --- a/hw/sparc/trace-events +++ b/hw/sparc/trace-events @@ -6,6 +6,16 @@ sun4m_cpu_reset_interrupt(unsigned int level) "Reset CPU IRQ %d" sun4m_cpu_set_irq_raise(int level) "Raise CPU IRQ %d" sun4m_cpu_set_irq_lower(int level) "Lower CPU IRQ %d" +# hw/sparc/sun4m_iommu.c +sun4m_iommu_mem_readl(uint64_t addr, uint32_t ret) "read reg[0x%"PRIx64"] = 0x%x" +sun4m_iommu_mem_writel(uint64_t addr, uint32_t val) "write reg[0x%"PRIx64"] = 0x%x" +sun4m_iommu_mem_writel_ctrl(uint64_t iostart) "iostart = 0x%"PRIx64 +sun4m_iommu_mem_writel_tlbflush(uint32_t val) "tlb flush 0x%x" +sun4m_iommu_mem_writel_pgflush(uint32_t val) "page flush 0x%x" +sun4m_iommu_page_get_flags(uint64_t pa, uint64_t iopte, uint32_t ret) "get flags addr 0x%"PRIx64" => pte 0x%"PRIx64", *pte = 0x%x" +sun4m_iommu_translate_pa(uint64_t addr, uint64_t pa, uint32_t iopte) "xlate dva 0x%"PRIx64" => pa 0x%"PRIx64" iopte = 0x%x" +sun4m_iommu_bad_addr(uint64_t addr) "bad addr 0x%"PRIx64 + # hw/sparc/leon3.c leon3_set_irq(int intno) "Set CPU IRQ %d" leon3_reset_irq(int intno) "Reset CPU IRQ %d" From 1527f4886c88c8ac7faf507122580e964c2259a7 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Mon, 8 Jan 2018 18:16:34 +0000 Subject: [PATCH 19/25] sun4m: move IOMMU declarations from sun4m.h to sun4m_iommu.h Also updating the relevant .c files as required. Signed-off-by: Mark Cave-Ayland Acked-by: Artyom Tarasenko --- hw/dma/sparc32_dma.c | 1 + hw/sparc/sun4m.c | 1 + hw/sparc/sun4m_iommu.c | 1 + include/hw/sparc/sun4m.h | 21 -------------- include/hw/sparc/sun4m_iommu.h | 51 ++++++++++++++++++++++++++++++++++ 5 files changed, 54 insertions(+), 21 deletions(-) create mode 100644 include/hw/sparc/sun4m_iommu.h diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c index 01afb758b6..c04ad79305 100644 --- a/hw/dma/sparc32_dma.c +++ b/hw/dma/sparc32_dma.c @@ -29,6 +29,7 @@ #include "hw/hw.h" #include "hw/sparc/sparc32_dma.h" #include "hw/sparc/sun4m.h" +#include "hw/sparc/sun4m_iommu.h" #include "hw/sysbus.h" #include "sysemu/dma.h" #include "qapi/error.h" diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index e71648404c..efaff5849d 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -29,6 +29,7 @@ #include "qemu/error-report.h" #include "qemu/timer.h" #include "hw/sparc/sun4m.h" +#include "hw/sparc/sun4m_iommu.h" #include "hw/timer/m48t59.h" #include "hw/sparc/sparc32_dma.h" #include "hw/block/fdc.h" diff --git a/hw/sparc/sun4m_iommu.c b/hw/sparc/sun4m_iommu.c index 72a9af555f..311c82d2bb 100644 --- a/hw/sparc/sun4m_iommu.c +++ b/hw/sparc/sun4m_iommu.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "hw/sparc/sun4m.h" +#include "hw/sparc/sun4m_iommu.h" #include "hw/sysbus.h" #include "exec/address-spaces.h" #include "trace.h" diff --git a/include/hw/sparc/sun4m.h b/include/hw/sparc/sun4m.h index c557b0dd53..9e06467ac2 100644 --- a/include/hw/sparc/sun4m.h +++ b/include/hw/sparc/sun4m.h @@ -8,27 +8,6 @@ /* Devices used by sparc32 system. */ -/* iommu.c */ -#define TYPE_SUN4M_IOMMU "sun4m-iommu" -#define SUN4M_IOMMU(obj) OBJECT_CHECK(IOMMUState, (obj), TYPE_SUN4M_IOMMU) - -#define TYPE_SUN4M_IOMMU_MEMORY_REGION "sun4m-iommu-memory-region" - -#define IOMMU_NREGS (4 * 4096 / 4) - -typedef struct IOMMUState { - SysBusDevice parent_obj; - - AddressSpace iommu_as; - IOMMUMemoryRegion iommu; - - MemoryRegion iomem; - uint32_t regs[IOMMU_NREGS]; - hwaddr iostart; - qemu_irq irq; - uint32_t version; -} IOMMUState; - /* sparc32_dma.c */ #include "hw/sparc/sparc32_dma.h" diff --git a/include/hw/sparc/sun4m_iommu.h b/include/hw/sparc/sun4m_iommu.h new file mode 100644 index 0000000000..938937eb04 --- /dev/null +++ b/include/hw/sparc/sun4m_iommu.h @@ -0,0 +1,51 @@ +/* + * QEMU Sun4m iommu emulation + * + * Copyright (c) 2003-2005 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef SUN4M_IOMMU_H +#define SUN4M_IOMMU_H + +#include "qemu-common.h" +#include "hw/sysbus.h" + +#define IOMMU_NREGS (4 * 4096 / 4) + +typedef struct IOMMUState { + SysBusDevice parent_obj; + + AddressSpace iommu_as; + IOMMUMemoryRegion iommu; + + MemoryRegion iomem; + uint32_t regs[IOMMU_NREGS]; + hwaddr iostart; + qemu_irq irq; + uint32_t version; +} IOMMUState; + +#define TYPE_SUN4M_IOMMU "sun4m-iommu" +#define SUN4M_IOMMU(obj) OBJECT_CHECK(IOMMUState, (obj), TYPE_SUN4M_IOMMU) + +#define TYPE_SUN4M_IOMMU_MEMORY_REGION "sun4m-iommu-memory-region" + +#endif From f5980f757c028ec68ff8442c418db8462415af2a Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Mon, 8 Jan 2018 18:16:34 +0000 Subject: [PATCH 20/25] sun4m: remove include/hw/sparc/sun4m.h and all references to it With the previous commit there is now nothing left in sun4m.h so it can be removed, along with all remaining references to it. Signed-off-by: Mark Cave-Ayland Acked-by: Artyom Tarasenko --- hw/dma/sparc32_dma.c | 1 - hw/intc/slavio_intctl.c | 1 - hw/net/lance.c | 2 +- hw/sparc/sun4m.c | 1 - hw/sparc/sun4m_iommu.c | 1 - hw/timer/slavio_timer.c | 1 - include/hw/sparc/sun4m.h | 14 -------------- 7 files changed, 1 insertion(+), 20 deletions(-) delete mode 100644 include/hw/sparc/sun4m.h diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c index c04ad79305..7b00a27de6 100644 --- a/hw/dma/sparc32_dma.c +++ b/hw/dma/sparc32_dma.c @@ -28,7 +28,6 @@ #include "qemu/osdep.h" #include "hw/hw.h" #include "hw/sparc/sparc32_dma.h" -#include "hw/sparc/sun4m.h" #include "hw/sparc/sun4m_iommu.h" #include "hw/sysbus.h" #include "sysemu/dma.h" diff --git a/hw/intc/slavio_intctl.c b/hw/intc/slavio_intctl.c index 84e0bee4a9..817e02617e 100644 --- a/hw/intc/slavio_intctl.c +++ b/hw/intc/slavio_intctl.c @@ -23,7 +23,6 @@ */ #include "qemu/osdep.h" -#include "hw/sparc/sun4m.h" #include "monitor/monitor.h" #include "hw/sysbus.h" #include "hw/intc/intc.h" diff --git a/hw/net/lance.c b/hw/net/lance.c index 23929fd1e6..0028bc525d 100644 --- a/hw/net/lance.c +++ b/hw/net/lance.c @@ -40,7 +40,7 @@ #include "net/net.h" #include "qemu/timer.h" #include "qemu/sockets.h" -#include "hw/sparc/sun4m.h" +#include "hw/sparc/sparc32_dma.h" #include "hw/net/lance.h" #include "trace.h" #include "sysemu/sysemu.h" diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index efaff5849d..dd0038095b 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -28,7 +28,6 @@ #include "hw/sysbus.h" #include "qemu/error-report.h" #include "qemu/timer.h" -#include "hw/sparc/sun4m.h" #include "hw/sparc/sun4m_iommu.h" #include "hw/timer/m48t59.h" #include "hw/sparc/sparc32_dma.h" diff --git a/hw/sparc/sun4m_iommu.c b/hw/sparc/sun4m_iommu.c index 311c82d2bb..b677601fc6 100644 --- a/hw/sparc/sun4m_iommu.c +++ b/hw/sparc/sun4m_iommu.c @@ -23,7 +23,6 @@ */ #include "qemu/osdep.h" -#include "hw/sparc/sun4m.h" #include "hw/sparc/sun4m_iommu.h" #include "hw/sysbus.h" #include "exec/address-spaces.h" diff --git a/hw/timer/slavio_timer.c b/hw/timer/slavio_timer.c index a8cc9c0148..4694b653a7 100644 --- a/hw/timer/slavio_timer.c +++ b/hw/timer/slavio_timer.c @@ -23,7 +23,6 @@ */ #include "qemu/osdep.h" -#include "hw/sparc/sun4m.h" #include "qemu/timer.h" #include "hw/ptimer.h" #include "hw/sysbus.h" diff --git a/include/hw/sparc/sun4m.h b/include/hw/sparc/sun4m.h deleted file mode 100644 index 9e06467ac2..0000000000 --- a/include/hw/sparc/sun4m.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef SUN4M_H -#define SUN4M_H - -#include "qemu-common.h" -#include "exec/hwaddr.h" -#include "qapi/qmp/types.h" -#include "hw/sysbus.h" - -/* Devices used by sparc32 system. */ - -/* sparc32_dma.c */ -#include "hw/sparc/sparc32_dma.h" - -#endif From aea5b071012d3507885724362913d0b71dd6c303 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Mon, 8 Jan 2018 18:16:34 +0000 Subject: [PATCH 21/25] apb: QOMify IOMMU This is in preparation to split the IOMMU device out of the APB. As part of this commit we also enforce separation of the IOMMU and APB devices by using a QOM object link to pass the IOMMU reference and accessing the IOMMU registers via a separate memory region mapped into the APB config space rather than directly. Signed-off-by: Mark Cave-Ayland Acked-by: Artyom Tarasenko --- hw/pci-host/apb.c | 77 +++++++++++++++++++++++++++++---------- hw/sparc64/sun4u.c | 7 +++- include/hw/pci-host/apb.h | 8 +++- 3 files changed, 70 insertions(+), 22 deletions(-) diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c index 44b08c090e..060e6e6d1c 100644 --- a/hw/pci-host/apb.c +++ b/hw/pci-host/apb.c @@ -36,6 +36,7 @@ #include "hw/pci-host/apb.h" #include "sysemu/sysemu.h" #include "exec/address-spaces.h" +#include "qapi/error.h" #include "qemu/log.h" /* debug APB */ @@ -250,8 +251,8 @@ static IOMMUTLBEntry pbm_translate_iommu(IOMMUMemoryRegion *iommu, hwaddr addr, return ret; } -static void iommu_config_write(void *opaque, hwaddr addr, - uint64_t val, unsigned size) +static void iommu_mem_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) { IOMMUState *is = opaque; @@ -295,7 +296,7 @@ static void iommu_config_write(void *opaque, hwaddr addr, } } -static uint64_t iommu_config_read(void *opaque, hwaddr addr, unsigned size) +static uint64_t iommu_mem_read(void *opaque, hwaddr addr, unsigned size) { IOMMUState *is = opaque; uint64_t val; @@ -344,7 +345,6 @@ static void apb_config_writel (void *opaque, hwaddr addr, uint64_t val, unsigned size) { APBState *s = opaque; - IOMMUState *is = &s->iommu; APB_DPRINTF("%s: addr " TARGET_FMT_plx " val %" PRIx64 "\n", __func__, addr, val); @@ -352,9 +352,6 @@ static void apb_config_writel (void *opaque, hwaddr addr, case 0x30 ... 0x4f: /* DMA error registers */ /* XXX: not implemented yet */ break; - case 0x200 ... 0x217: /* IOMMU */ - iommu_config_write(is, (addr & 0x1f), val, size); - break; case 0xc00 ... 0xc3f: /* PCI interrupt control */ if (addr & 4) { unsigned int ino = (addr & 0x3f) >> 3; @@ -426,7 +423,6 @@ static uint64_t apb_config_readl (void *opaque, hwaddr addr, unsigned size) { APBState *s = opaque; - IOMMUState *is = &s->iommu; uint32_t val; switch (addr & 0xffff) { @@ -434,9 +430,6 @@ static uint64_t apb_config_readl (void *opaque, val = 0; /* XXX: not implemented yet */ break; - case 0x200 ... 0x217: /* IOMMU */ - val = iommu_config_read(is, (addr & 0x1f), size); - break; case 0xc00 ... 0xc3f: /* PCI interrupt control */ if (addr & 4) { val = s->pci_irq_map[(addr & 0x3f) >> 3]; @@ -643,7 +636,6 @@ static void pci_pbm_realize(DeviceState *dev, Error **errp) PCIHostState *phb = PCI_HOST_BRIDGE(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(s); PCIDevice *pci_dev; - IOMMUState *is; /* apb_config */ sysbus_mmio_map(sbd, 0, s->special_base); @@ -665,14 +657,9 @@ static void pci_pbm_realize(DeviceState *dev, Error **errp) pci_create_simple(phb->bus, 0, "pbm-pci"); /* APB IOMMU */ - is = &s->iommu; - memset(is, 0, sizeof(IOMMUState)); - - memory_region_init_iommu(&is->iommu, sizeof(is->iommu), - TYPE_APB_IOMMU_MEMORY_REGION, OBJECT(dev), - "iommu-apb", UINT64_MAX); - address_space_init(&is->iommu_as, MEMORY_REGION(&is->iommu), "pbm-as"); - pci_setup_iommu(phb->bus, pbm_pci_dma_iommu, is); + memory_region_add_subregion_overlap(&s->apb_config, 0x200, + sysbus_mmio_get_region(SYS_BUS_DEVICE(s->iommu), 0), 1); + pci_setup_iommu(phb->bus, pbm_pci_dma_iommu, s->iommu); /* APB secondary busses */ pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 0), true, @@ -708,6 +695,12 @@ static void pci_pbm_init(Object *obj) s->irq_request = NO_IRQ_REQUEST; s->pci_irq_in = 0ULL; + /* IOMMU */ + object_property_add_link(obj, "iommu", TYPE_SUN4U_IOMMU, + (Object **) &s->iommu, + qdev_prop_allow_set_link_before_realize, + 0, NULL); + /* apb_config */ memory_region_init_io(&s->apb_config, OBJECT(s), &apb_config_ops, s, "apb-config", 0x10000); @@ -814,6 +807,49 @@ static const TypeInfo pbm_pci_bridge_info = { }, }; +static const MemoryRegionOps iommu_mem_ops = { + .read = iommu_mem_read, + .write = iommu_mem_write, + .endianness = DEVICE_BIG_ENDIAN, +}; + +static void iommu_reset(DeviceState *d) +{ + IOMMUState *s = SUN4U_IOMMU(d); + + memset(s->regs, 0, IOMMU_NREGS * sizeof(uint64_t)); +} + +static void iommu_init(Object *obj) +{ + IOMMUState *s = SUN4U_IOMMU(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_iommu(&s->iommu, sizeof(s->iommu), + TYPE_APB_IOMMU_MEMORY_REGION, OBJECT(s), + "iommu-apb", UINT64_MAX); + address_space_init(&s->iommu_as, MEMORY_REGION(&s->iommu), "pbm-as"); + + memory_region_init_io(&s->iomem, obj, &iommu_mem_ops, s, "iommu", + IOMMU_NREGS * sizeof(uint64_t)); + sysbus_init_mmio(sbd, &s->iomem); +} + +static void iommu_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = iommu_reset; +} + +static const TypeInfo pbm_iommu_info = { + .name = TYPE_SUN4U_IOMMU, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(IOMMUState), + .instance_init = iommu_init, + .class_init = iommu_class_init, +}; + static void pbm_iommu_memory_region_class_init(ObjectClass *klass, void *data) { IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass); @@ -832,6 +868,7 @@ static void pbm_register_types(void) type_register_static(&pbm_host_info); type_register_static(&pbm_pci_host_info); type_register_static(&pbm_pci_bridge_info); + type_register_static(&pbm_iommu_info); type_register_static(&pbm_iommu_memory_region_info); } diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index 5d802bdfde..aaee3de03a 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -469,7 +469,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem, PCIDevice *ebus, *pci_dev; SysBusDevice *s; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; - DeviceState *dev; + DeviceState *iommu, *dev; FWCfgState *fw_cfg; NICInfo *nd; MACAddr macaddr; @@ -478,6 +478,10 @@ static void sun4uv_init(MemoryRegion *address_space_mem, /* init CPUs */ cpu = sparc64_cpu_devinit(machine->cpu_type, hwdef->prom_addr); + /* IOMMU */ + iommu = qdev_create(NULL, TYPE_SUN4U_IOMMU); + qdev_init_nofail(iommu); + /* set up devices */ ram_init(0, machine->ram_size); @@ -487,6 +491,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem, apb = APB_DEVICE(qdev_create(NULL, TYPE_APB)); qdev_prop_set_uint64(DEVICE(apb), "special-base", APB_SPECIAL_BASE); qdev_prop_set_uint64(DEVICE(apb), "mem-base", APB_MEM_BASE); + object_property_set_link(OBJECT(apb), OBJECT(iommu), "iommu", &error_abort); qdev_init_nofail(DEVICE(apb)); /* Wire up PCI interrupts to CPU */ diff --git a/include/hw/pci-host/apb.h b/include/hw/pci-host/apb.h index 6194c8cbad..33dbc7a8cb 100644 --- a/include/hw/pci-host/apb.h +++ b/include/hw/pci-host/apb.h @@ -44,12 +44,18 @@ #define IOMMU_TSB_64K_OFFSET_MASK_2G 0x000000007fff0000ULL typedef struct IOMMUState { + SysBusDevice parent_obj; + AddressSpace iommu_as; IOMMUMemoryRegion iommu; + MemoryRegion iomem; uint64_t regs[IOMMU_NREGS]; } IOMMUState; +#define TYPE_SUN4U_IOMMU "sun4u-iommu" +#define SUN4U_IOMMU(obj) OBJECT_CHECK(IOMMUState, (obj), TYPE_SUN4U_IOMMU) + #define MAX_IVEC 0x40 /* OBIO IVEC IRQs */ @@ -78,7 +84,7 @@ typedef struct APBState { MemoryRegion pci_mmio; MemoryRegion pci_ioport; uint64_t pci_irq_in; - IOMMUState iommu; + IOMMUState *iommu; PCIBridge *bridgeA; PCIBridge *bridgeB; uint32_t pci_control[16]; From 0ea833c24999093be6369f9145333bd10acfad76 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Mon, 8 Jan 2018 18:16:34 +0000 Subject: [PATCH 22/25] sun4u: split IOMMU device out from apb.c to sun4u_iommu.c By separating the sun4u IOMMU device into new sun4u_iommu.c and sun4m_iommu.h files we noticeably simplify apb.c whilst bringing sun4u in line with all the other IOMMU-supporting architectures. Signed-off-by: Mark Cave-Ayland Acked-by: Artyom Tarasenko --- hw/pci-host/apb.c | 273 ------------------------- hw/sparc64/Makefile.objs | 1 + hw/sparc64/sun4u.c | 1 + hw/sparc64/sun4u_iommu.c | 350 +++++++++++++++++++++++++++++++++ include/hw/pci-host/apb.h | 57 +----- include/hw/sparc/sun4u_iommu.h | 50 +++++ 6 files changed, 403 insertions(+), 329 deletions(-) create mode 100644 hw/sparc64/sun4u_iommu.c create mode 100644 include/hw/sparc/sun4u_iommu.h diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c index 060e6e6d1c..3e796fb6fc 100644 --- a/hw/pci-host/apb.c +++ b/hw/pci-host/apb.c @@ -49,16 +49,6 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0) #define APB_DPRINTF(fmt, ...) #endif -/* debug IOMMU */ -//#define DEBUG_IOMMU - -#ifdef DEBUG_IOMMU -#define IOMMU_DPRINTF(fmt, ...) \ -do { printf("IOMMU: " fmt , ## __VA_ARGS__); } while (0) -#else -#define IOMMU_DPRINTF(fmt, ...) -#endif - /* * Chipset docs: * PBM: "UltraSPARC IIi User's Manual", @@ -136,211 +126,6 @@ static AddressSpace *pbm_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn) return &is->iommu_as; } -/* Called from RCU critical section */ -static IOMMUTLBEntry pbm_translate_iommu(IOMMUMemoryRegion *iommu, hwaddr addr, - IOMMUAccessFlags flag) -{ - IOMMUState *is = container_of(iommu, IOMMUState, iommu); - hwaddr baseaddr, offset; - uint64_t tte; - uint32_t tsbsize; - IOMMUTLBEntry ret = { - .target_as = &address_space_memory, - .iova = 0, - .translated_addr = 0, - .addr_mask = ~(hwaddr)0, - .perm = IOMMU_NONE, - }; - - if (!(is->regs[IOMMU_CTRL >> 3] & IOMMU_CTRL_MMU_EN)) { - /* IOMMU disabled, passthrough using standard 8K page */ - ret.iova = addr & IOMMU_PAGE_MASK_8K; - ret.translated_addr = addr; - ret.addr_mask = IOMMU_PAGE_MASK_8K; - ret.perm = IOMMU_RW; - - return ret; - } - - baseaddr = is->regs[IOMMU_BASE >> 3]; - tsbsize = (is->regs[IOMMU_CTRL >> 3] >> IOMMU_CTRL_TSB_SHIFT) & 0x7; - - if (is->regs[IOMMU_CTRL >> 3] & IOMMU_CTRL_TBW_SIZE) { - /* 64K */ - switch (tsbsize) { - case 0: - offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_64M) >> 13; - break; - case 1: - offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_128M) >> 13; - break; - case 2: - offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_256M) >> 13; - break; - case 3: - offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_512M) >> 13; - break; - case 4: - offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_1G) >> 13; - break; - case 5: - offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_2G) >> 13; - break; - default: - /* Not implemented, error */ - return ret; - } - } else { - /* 8K */ - switch (tsbsize) { - case 0: - offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_8M) >> 10; - break; - case 1: - offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_16M) >> 10; - break; - case 2: - offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_32M) >> 10; - break; - case 3: - offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_64M) >> 10; - break; - case 4: - offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_128M) >> 10; - break; - case 5: - offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_256M) >> 10; - break; - case 6: - offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_512M) >> 10; - break; - case 7: - offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_1G) >> 10; - break; - } - } - - tte = address_space_ldq_be(&address_space_memory, baseaddr + offset, - MEMTXATTRS_UNSPECIFIED, NULL); - - if (!(tte & IOMMU_TTE_DATA_V)) { - /* Invalid mapping */ - return ret; - } - - if (tte & IOMMU_TTE_DATA_W) { - /* Writeable */ - ret.perm = IOMMU_RW; - } else { - ret.perm = IOMMU_RO; - } - - /* Extract phys */ - if (tte & IOMMU_TTE_DATA_SIZE) { - /* 64K */ - ret.iova = addr & IOMMU_PAGE_MASK_64K; - ret.translated_addr = tte & IOMMU_TTE_PHYS_MASK_64K; - ret.addr_mask = (IOMMU_PAGE_SIZE_64K - 1); - } else { - /* 8K */ - ret.iova = addr & IOMMU_PAGE_MASK_8K; - ret.translated_addr = tte & IOMMU_TTE_PHYS_MASK_8K; - ret.addr_mask = (IOMMU_PAGE_SIZE_8K - 1); - } - - return ret; -} - -static void iommu_mem_write(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - IOMMUState *is = opaque; - - IOMMU_DPRINTF("IOMMU config write: 0x%" HWADDR_PRIx " val: %" PRIx64 - " size: %d\n", addr, val, size); - - switch (addr) { - case IOMMU_CTRL: - if (size == 4) { - is->regs[IOMMU_CTRL >> 3] &= 0xffffffffULL; - is->regs[IOMMU_CTRL >> 3] |= val << 32; - } else { - is->regs[IOMMU_CTRL >> 3] = val; - } - break; - case IOMMU_CTRL + 0x4: - is->regs[IOMMU_CTRL >> 3] &= 0xffffffff00000000ULL; - is->regs[IOMMU_CTRL >> 3] |= val & 0xffffffffULL; - break; - case IOMMU_BASE: - if (size == 4) { - is->regs[IOMMU_BASE >> 3] &= 0xffffffffULL; - is->regs[IOMMU_BASE >> 3] |= val << 32; - } else { - is->regs[IOMMU_BASE >> 3] = val; - } - break; - case IOMMU_BASE + 0x4: - is->regs[IOMMU_BASE >> 3] &= 0xffffffff00000000ULL; - is->regs[IOMMU_BASE >> 3] |= val & 0xffffffffULL; - break; - case IOMMU_FLUSH: - case IOMMU_FLUSH + 0x4: - break; - default: - qemu_log_mask(LOG_UNIMP, - "apb iommu: Unimplemented register write " - "reg 0x%" HWADDR_PRIx " size 0x%x value 0x%" PRIx64 "\n", - addr, size, val); - break; - } -} - -static uint64_t iommu_mem_read(void *opaque, hwaddr addr, unsigned size) -{ - IOMMUState *is = opaque; - uint64_t val; - - switch (addr) { - case IOMMU_CTRL: - if (size == 4) { - val = is->regs[IOMMU_CTRL >> 3] >> 32; - } else { - val = is->regs[IOMMU_CTRL >> 3]; - } - break; - case IOMMU_CTRL + 0x4: - val = is->regs[IOMMU_CTRL >> 3] & 0xffffffffULL; - break; - case IOMMU_BASE: - if (size == 4) { - val = is->regs[IOMMU_BASE >> 3] >> 32; - } else { - val = is->regs[IOMMU_BASE >> 3]; - } - break; - case IOMMU_BASE + 0x4: - val = is->regs[IOMMU_BASE >> 3] & 0xffffffffULL; - break; - case IOMMU_FLUSH: - case IOMMU_FLUSH + 0x4: - val = 0; - break; - default: - qemu_log_mask(LOG_UNIMP, - "apb iommu: Unimplemented register read " - "reg 0x%" HWADDR_PRIx " size 0x%x\n", - addr, size); - val = 0; - break; - } - - IOMMU_DPRINTF("IOMMU config read: 0x%" HWADDR_PRIx " val: %" PRIx64 - " size: %d\n", addr, val, size); - - return val; -} - static void apb_config_writel (void *opaque, hwaddr addr, uint64_t val, unsigned size) { @@ -807,69 +592,11 @@ static const TypeInfo pbm_pci_bridge_info = { }, }; -static const MemoryRegionOps iommu_mem_ops = { - .read = iommu_mem_read, - .write = iommu_mem_write, - .endianness = DEVICE_BIG_ENDIAN, -}; - -static void iommu_reset(DeviceState *d) -{ - IOMMUState *s = SUN4U_IOMMU(d); - - memset(s->regs, 0, IOMMU_NREGS * sizeof(uint64_t)); -} - -static void iommu_init(Object *obj) -{ - IOMMUState *s = SUN4U_IOMMU(obj); - SysBusDevice *sbd = SYS_BUS_DEVICE(obj); - - memory_region_init_iommu(&s->iommu, sizeof(s->iommu), - TYPE_APB_IOMMU_MEMORY_REGION, OBJECT(s), - "iommu-apb", UINT64_MAX); - address_space_init(&s->iommu_as, MEMORY_REGION(&s->iommu), "pbm-as"); - - memory_region_init_io(&s->iomem, obj, &iommu_mem_ops, s, "iommu", - IOMMU_NREGS * sizeof(uint64_t)); - sysbus_init_mmio(sbd, &s->iomem); -} - -static void iommu_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->reset = iommu_reset; -} - -static const TypeInfo pbm_iommu_info = { - .name = TYPE_SUN4U_IOMMU, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(IOMMUState), - .instance_init = iommu_init, - .class_init = iommu_class_init, -}; - -static void pbm_iommu_memory_region_class_init(ObjectClass *klass, void *data) -{ - IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass); - - imrc->translate = pbm_translate_iommu; -} - -static const TypeInfo pbm_iommu_memory_region_info = { - .parent = TYPE_IOMMU_MEMORY_REGION, - .name = TYPE_APB_IOMMU_MEMORY_REGION, - .class_init = pbm_iommu_memory_region_class_init, -}; - static void pbm_register_types(void) { type_register_static(&pbm_host_info); type_register_static(&pbm_pci_host_info); type_register_static(&pbm_pci_bridge_info); - type_register_static(&pbm_iommu_info); - type_register_static(&pbm_iommu_memory_region_info); } type_init(pbm_register_types) diff --git a/hw/sparc64/Makefile.objs b/hw/sparc64/Makefile.objs index cf9de21133..117e0ff27d 100644 --- a/hw/sparc64/Makefile.objs +++ b/hw/sparc64/Makefile.objs @@ -1,3 +1,4 @@ obj-y += sparc64.o +obj-y += sun4u_iommu.o obj-y += sun4u.o obj-y += niagara.o \ No newline at end of file diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index aaee3de03a..ec45ec2801 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -29,6 +29,7 @@ #include "hw/pci/pci.h" #include "hw/pci/pci_bridge.h" #include "hw/pci/pci_bus.h" +#include "hw/pci/pci_host.h" #include "hw/pci-host/apb.h" #include "hw/i386/pc.h" #include "hw/char/serial.h" diff --git a/hw/sparc64/sun4u_iommu.c b/hw/sparc64/sun4u_iommu.c new file mode 100644 index 0000000000..e5aa817edb --- /dev/null +++ b/hw/sparc64/sun4u_iommu.c @@ -0,0 +1,350 @@ +/* + * QEMU sun4u IOMMU emulation + * + * Copyright (c) 2006 Fabrice Bellard + * Copyright (c) 2012,2013 Artyom Tarasenko + * Copyright (c) 2017 Mark Cave-Ayland + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "hw/sysbus.h" +#include "hw/sparc/sun4u_iommu.h" +#include "exec/address-spaces.h" +#include "qapi/error.h" +#include "qemu/log.h" + +/* debug IOMMU */ +//#define DEBUG_IOMMU + +#ifdef DEBUG_IOMMU +#define IOMMU_DPRINTF(fmt, ...) \ +do { printf("IOMMU: " fmt , ## __VA_ARGS__); } while (0) +#else +#define IOMMU_DPRINTF(fmt, ...) +#endif + + +#define IOMMU_PAGE_SIZE_8K (1ULL << 13) +#define IOMMU_PAGE_MASK_8K (~(IOMMU_PAGE_SIZE_8K - 1)) +#define IOMMU_PAGE_SIZE_64K (1ULL << 16) +#define IOMMU_PAGE_MASK_64K (~(IOMMU_PAGE_SIZE_64K - 1)) + +#define IOMMU_CTRL 0x0 +#define IOMMU_CTRL_TBW_SIZE (1ULL << 2) +#define IOMMU_CTRL_MMU_EN (1ULL) + +#define IOMMU_CTRL_TSB_SHIFT 16 + +#define IOMMU_BASE 0x8 +#define IOMMU_FLUSH 0x10 + +#define IOMMU_TTE_DATA_V (1ULL << 63) +#define IOMMU_TTE_DATA_SIZE (1ULL << 61) +#define IOMMU_TTE_DATA_W (1ULL << 1) + +#define IOMMU_TTE_PHYS_MASK_8K 0x1ffffffe000ULL +#define IOMMU_TTE_PHYS_MASK_64K 0x1ffffff8000ULL + +#define IOMMU_TSB_8K_OFFSET_MASK_8M 0x00000000007fe000ULL +#define IOMMU_TSB_8K_OFFSET_MASK_16M 0x0000000000ffe000ULL +#define IOMMU_TSB_8K_OFFSET_MASK_32M 0x0000000001ffe000ULL +#define IOMMU_TSB_8K_OFFSET_MASK_64M 0x0000000003ffe000ULL +#define IOMMU_TSB_8K_OFFSET_MASK_128M 0x0000000007ffe000ULL +#define IOMMU_TSB_8K_OFFSET_MASK_256M 0x000000000fffe000ULL +#define IOMMU_TSB_8K_OFFSET_MASK_512M 0x000000001fffe000ULL +#define IOMMU_TSB_8K_OFFSET_MASK_1G 0x000000003fffe000ULL + +#define IOMMU_TSB_64K_OFFSET_MASK_64M 0x0000000003ff0000ULL +#define IOMMU_TSB_64K_OFFSET_MASK_128M 0x0000000007ff0000ULL +#define IOMMU_TSB_64K_OFFSET_MASK_256M 0x000000000fff0000ULL +#define IOMMU_TSB_64K_OFFSET_MASK_512M 0x000000001fff0000ULL +#define IOMMU_TSB_64K_OFFSET_MASK_1G 0x000000003fff0000ULL +#define IOMMU_TSB_64K_OFFSET_MASK_2G 0x000000007fff0000ULL + + +/* Called from RCU critical section */ +static IOMMUTLBEntry pbm_translate_iommu(IOMMUMemoryRegion *iommu, hwaddr addr, + IOMMUAccessFlags flag) +{ + IOMMUState *is = container_of(iommu, IOMMUState, iommu); + hwaddr baseaddr, offset; + uint64_t tte; + uint32_t tsbsize; + IOMMUTLBEntry ret = { + .target_as = &address_space_memory, + .iova = 0, + .translated_addr = 0, + .addr_mask = ~(hwaddr)0, + .perm = IOMMU_NONE, + }; + + if (!(is->regs[IOMMU_CTRL >> 3] & IOMMU_CTRL_MMU_EN)) { + /* IOMMU disabled, passthrough using standard 8K page */ + ret.iova = addr & IOMMU_PAGE_MASK_8K; + ret.translated_addr = addr; + ret.addr_mask = IOMMU_PAGE_MASK_8K; + ret.perm = IOMMU_RW; + + return ret; + } + + baseaddr = is->regs[IOMMU_BASE >> 3]; + tsbsize = (is->regs[IOMMU_CTRL >> 3] >> IOMMU_CTRL_TSB_SHIFT) & 0x7; + + if (is->regs[IOMMU_CTRL >> 3] & IOMMU_CTRL_TBW_SIZE) { + /* 64K */ + switch (tsbsize) { + case 0: + offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_64M) >> 13; + break; + case 1: + offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_128M) >> 13; + break; + case 2: + offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_256M) >> 13; + break; + case 3: + offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_512M) >> 13; + break; + case 4: + offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_1G) >> 13; + break; + case 5: + offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_2G) >> 13; + break; + default: + /* Not implemented, error */ + return ret; + } + } else { + /* 8K */ + switch (tsbsize) { + case 0: + offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_8M) >> 10; + break; + case 1: + offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_16M) >> 10; + break; + case 2: + offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_32M) >> 10; + break; + case 3: + offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_64M) >> 10; + break; + case 4: + offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_128M) >> 10; + break; + case 5: + offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_256M) >> 10; + break; + case 6: + offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_512M) >> 10; + break; + case 7: + offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_1G) >> 10; + break; + } + } + + tte = address_space_ldq_be(&address_space_memory, baseaddr + offset, + MEMTXATTRS_UNSPECIFIED, NULL); + + if (!(tte & IOMMU_TTE_DATA_V)) { + /* Invalid mapping */ + return ret; + } + + if (tte & IOMMU_TTE_DATA_W) { + /* Writeable */ + ret.perm = IOMMU_RW; + } else { + ret.perm = IOMMU_RO; + } + + /* Extract phys */ + if (tte & IOMMU_TTE_DATA_SIZE) { + /* 64K */ + ret.iova = addr & IOMMU_PAGE_MASK_64K; + ret.translated_addr = tte & IOMMU_TTE_PHYS_MASK_64K; + ret.addr_mask = (IOMMU_PAGE_SIZE_64K - 1); + } else { + /* 8K */ + ret.iova = addr & IOMMU_PAGE_MASK_8K; + ret.translated_addr = tte & IOMMU_TTE_PHYS_MASK_8K; + ret.addr_mask = (IOMMU_PAGE_SIZE_8K - 1); + } + + return ret; +} + +static void iommu_mem_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + IOMMUState *is = opaque; + + IOMMU_DPRINTF("IOMMU config write: 0x%" HWADDR_PRIx " val: %" PRIx64 + " size: %d\n", addr, val, size); + + switch (addr) { + case IOMMU_CTRL: + if (size == 4) { + is->regs[IOMMU_CTRL >> 3] &= 0xffffffffULL; + is->regs[IOMMU_CTRL >> 3] |= val << 32; + } else { + is->regs[IOMMU_CTRL >> 3] = val; + } + break; + case IOMMU_CTRL + 0x4: + is->regs[IOMMU_CTRL >> 3] &= 0xffffffff00000000ULL; + is->regs[IOMMU_CTRL >> 3] |= val & 0xffffffffULL; + break; + case IOMMU_BASE: + if (size == 4) { + is->regs[IOMMU_BASE >> 3] &= 0xffffffffULL; + is->regs[IOMMU_BASE >> 3] |= val << 32; + } else { + is->regs[IOMMU_BASE >> 3] = val; + } + break; + case IOMMU_BASE + 0x4: + is->regs[IOMMU_BASE >> 3] &= 0xffffffff00000000ULL; + is->regs[IOMMU_BASE >> 3] |= val & 0xffffffffULL; + break; + case IOMMU_FLUSH: + case IOMMU_FLUSH + 0x4: + break; + default: + qemu_log_mask(LOG_UNIMP, + "apb iommu: Unimplemented register write " + "reg 0x%" HWADDR_PRIx " size 0x%x value 0x%" PRIx64 "\n", + addr, size, val); + break; + } +} + +static uint64_t iommu_mem_read(void *opaque, hwaddr addr, unsigned size) +{ + IOMMUState *is = opaque; + uint64_t val; + + switch (addr) { + case IOMMU_CTRL: + if (size == 4) { + val = is->regs[IOMMU_CTRL >> 3] >> 32; + } else { + val = is->regs[IOMMU_CTRL >> 3]; + } + break; + case IOMMU_CTRL + 0x4: + val = is->regs[IOMMU_CTRL >> 3] & 0xffffffffULL; + break; + case IOMMU_BASE: + if (size == 4) { + val = is->regs[IOMMU_BASE >> 3] >> 32; + } else { + val = is->regs[IOMMU_BASE >> 3]; + } + break; + case IOMMU_BASE + 0x4: + val = is->regs[IOMMU_BASE >> 3] & 0xffffffffULL; + break; + case IOMMU_FLUSH: + case IOMMU_FLUSH + 0x4: + val = 0; + break; + default: + qemu_log_mask(LOG_UNIMP, + "apb iommu: Unimplemented register read " + "reg 0x%" HWADDR_PRIx " size 0x%x\n", + addr, size); + val = 0; + break; + } + + IOMMU_DPRINTF("IOMMU config read: 0x%" HWADDR_PRIx " val: %" PRIx64 + " size: %d\n", addr, val, size); + + return val; +} + +static const MemoryRegionOps iommu_mem_ops = { + .read = iommu_mem_read, + .write = iommu_mem_write, + .endianness = DEVICE_BIG_ENDIAN, +}; + +static void iommu_reset(DeviceState *d) +{ + IOMMUState *s = SUN4U_IOMMU(d); + + memset(s->regs, 0, IOMMU_NREGS * sizeof(uint64_t)); +} + +static void iommu_init(Object *obj) +{ + IOMMUState *s = SUN4U_IOMMU(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_iommu(&s->iommu, sizeof(s->iommu), + TYPE_APB_IOMMU_MEMORY_REGION, OBJECT(s), + "iommu-apb", UINT64_MAX); + address_space_init(&s->iommu_as, MEMORY_REGION(&s->iommu), "pbm-as"); + + memory_region_init_io(&s->iomem, obj, &iommu_mem_ops, s, "iommu", + IOMMU_NREGS * sizeof(uint64_t)); + sysbus_init_mmio(sbd, &s->iomem); +} + +static void iommu_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = iommu_reset; +} + +static const TypeInfo pbm_iommu_info = { + .name = TYPE_SUN4U_IOMMU, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(IOMMUState), + .instance_init = iommu_init, + .class_init = iommu_class_init, +}; + +static void pbm_iommu_memory_region_class_init(ObjectClass *klass, void *data) +{ + IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass); + + imrc->translate = pbm_translate_iommu; +} + +static const TypeInfo pbm_iommu_memory_region_info = { + .parent = TYPE_IOMMU_MEMORY_REGION, + .name = TYPE_APB_IOMMU_MEMORY_REGION, + .class_init = pbm_iommu_memory_region_class_init, +}; + +static void pbm_register_types(void) +{ + type_register_static(&pbm_iommu_info); + type_register_static(&pbm_iommu_memory_region_info); +} + +type_init(pbm_register_types) diff --git a/include/hw/pci-host/apb.h b/include/hw/pci-host/apb.h index 33dbc7a8cb..604d899b1e 100644 --- a/include/hw/pci-host/apb.h +++ b/include/hw/pci-host/apb.h @@ -1,60 +1,7 @@ #ifndef PCI_HOST_APB_H #define PCI_HOST_APB_H -#include "qemu-common.h" -#include "hw/pci/pci_host.h" - -#define IOMMU_NREGS 3 - -#define IOMMU_PAGE_SIZE_8K (1ULL << 13) -#define IOMMU_PAGE_MASK_8K (~(IOMMU_PAGE_SIZE_8K - 1)) -#define IOMMU_PAGE_SIZE_64K (1ULL << 16) -#define IOMMU_PAGE_MASK_64K (~(IOMMU_PAGE_SIZE_64K - 1)) - -#define IOMMU_CTRL 0x0 -#define IOMMU_CTRL_TBW_SIZE (1ULL << 2) -#define IOMMU_CTRL_MMU_EN (1ULL) - -#define IOMMU_CTRL_TSB_SHIFT 16 - -#define IOMMU_BASE 0x8 -#define IOMMU_FLUSH 0x10 - -#define IOMMU_TTE_DATA_V (1ULL << 63) -#define IOMMU_TTE_DATA_SIZE (1ULL << 61) -#define IOMMU_TTE_DATA_W (1ULL << 1) - -#define IOMMU_TTE_PHYS_MASK_8K 0x1ffffffe000ULL -#define IOMMU_TTE_PHYS_MASK_64K 0x1ffffff8000ULL - -#define IOMMU_TSB_8K_OFFSET_MASK_8M 0x00000000007fe000ULL -#define IOMMU_TSB_8K_OFFSET_MASK_16M 0x0000000000ffe000ULL -#define IOMMU_TSB_8K_OFFSET_MASK_32M 0x0000000001ffe000ULL -#define IOMMU_TSB_8K_OFFSET_MASK_64M 0x0000000003ffe000ULL -#define IOMMU_TSB_8K_OFFSET_MASK_128M 0x0000000007ffe000ULL -#define IOMMU_TSB_8K_OFFSET_MASK_256M 0x000000000fffe000ULL -#define IOMMU_TSB_8K_OFFSET_MASK_512M 0x000000001fffe000ULL -#define IOMMU_TSB_8K_OFFSET_MASK_1G 0x000000003fffe000ULL - -#define IOMMU_TSB_64K_OFFSET_MASK_64M 0x0000000003ff0000ULL -#define IOMMU_TSB_64K_OFFSET_MASK_128M 0x0000000007ff0000ULL -#define IOMMU_TSB_64K_OFFSET_MASK_256M 0x000000000fff0000ULL -#define IOMMU_TSB_64K_OFFSET_MASK_512M 0x000000001fff0000ULL -#define IOMMU_TSB_64K_OFFSET_MASK_1G 0x000000003fff0000ULL -#define IOMMU_TSB_64K_OFFSET_MASK_2G 0x000000007fff0000ULL - -typedef struct IOMMUState { - SysBusDevice parent_obj; - - AddressSpace iommu_as; - IOMMUMemoryRegion iommu; - - MemoryRegion iomem; - uint64_t regs[IOMMU_NREGS]; -} IOMMUState; - -#define TYPE_SUN4U_IOMMU "sun4u-iommu" -#define SUN4U_IOMMU(obj) OBJECT_CHECK(IOMMUState, (obj), TYPE_SUN4U_IOMMU) +#include "hw/sparc/sun4u_iommu.h" #define MAX_IVEC 0x40 @@ -72,8 +19,6 @@ typedef struct IOMMUState { #define APB_DEVICE(obj) \ OBJECT_CHECK(APBState, (obj), TYPE_APB) -#define TYPE_APB_IOMMU_MEMORY_REGION "pbm-iommu-memory-region" - typedef struct APBState { PCIHostState parent_obj; diff --git a/include/hw/sparc/sun4u_iommu.h b/include/hw/sparc/sun4u_iommu.h new file mode 100644 index 0000000000..bc4506b5b0 --- /dev/null +++ b/include/hw/sparc/sun4u_iommu.h @@ -0,0 +1,50 @@ +/* + * QEMU sun4u IOMMU emulation + * + * Copyright (c) 2006 Fabrice Bellard + * Copyright (c) 2012,2013 Artyom Tarasenko + * Copyright (c) 2017 Mark Cave-Ayland + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef SUN4U_IOMMU_H +#define SUN4U_IOMMU_H + +#include "qemu-common.h" +#include "hw/sysbus.h" + +#define IOMMU_NREGS 3 + +typedef struct IOMMUState { + SysBusDevice parent_obj; + + AddressSpace iommu_as; + IOMMUMemoryRegion iommu; + + MemoryRegion iomem; + uint64_t regs[IOMMU_NREGS]; +} IOMMUState; + +#define TYPE_SUN4U_IOMMU "sun4u-iommu" +#define SUN4U_IOMMU(obj) OBJECT_CHECK(IOMMUState, (obj), TYPE_SUN4U_IOMMU) + +#define TYPE_APB_IOMMU_MEMORY_REGION "pbm-iommu-memory-region" + +#endif From 4c9fbc38e3559d7540c8bd5cf76915dd21ccad7f Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Mon, 8 Jan 2018 18:16:34 +0000 Subject: [PATCH 23/25] sun4u_iommu: update to reflect IOMMU is no longer part of the APB device Signed-off-by: Mark Cave-Ayland Acked-by: Artyom Tarasenko --- hw/sparc64/sun4u_iommu.c | 35 +++++++++++++++++----------------- include/hw/sparc/sun4u_iommu.h | 2 +- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/hw/sparc64/sun4u_iommu.c b/hw/sparc64/sun4u_iommu.c index e5aa817edb..612fec4c64 100644 --- a/hw/sparc64/sun4u_iommu.c +++ b/hw/sparc64/sun4u_iommu.c @@ -81,8 +81,9 @@ do { printf("IOMMU: " fmt , ## __VA_ARGS__); } while (0) /* Called from RCU critical section */ -static IOMMUTLBEntry pbm_translate_iommu(IOMMUMemoryRegion *iommu, hwaddr addr, - IOMMUAccessFlags flag) +static IOMMUTLBEntry sun4u_translate_iommu(IOMMUMemoryRegion *iommu, + hwaddr addr, + IOMMUAccessFlags flag) { IOMMUState *is = container_of(iommu, IOMMUState, iommu); hwaddr baseaddr, offset; @@ -233,7 +234,7 @@ static void iommu_mem_write(void *opaque, hwaddr addr, break; default: qemu_log_mask(LOG_UNIMP, - "apb iommu: Unimplemented register write " + "sun4u-iommu: Unimplemented register write " "reg 0x%" HWADDR_PRIx " size 0x%x value 0x%" PRIx64 "\n", addr, size, val); break; @@ -272,7 +273,7 @@ static uint64_t iommu_mem_read(void *opaque, hwaddr addr, unsigned size) break; default: qemu_log_mask(LOG_UNIMP, - "apb iommu: Unimplemented register read " + "sun4u-iommu: Unimplemented register read " "reg 0x%" HWADDR_PRIx " size 0x%x\n", addr, size); val = 0; @@ -304,9 +305,9 @@ static void iommu_init(Object *obj) SysBusDevice *sbd = SYS_BUS_DEVICE(obj); memory_region_init_iommu(&s->iommu, sizeof(s->iommu), - TYPE_APB_IOMMU_MEMORY_REGION, OBJECT(s), - "iommu-apb", UINT64_MAX); - address_space_init(&s->iommu_as, MEMORY_REGION(&s->iommu), "pbm-as"); + TYPE_SUN4U_IOMMU_MEMORY_REGION, OBJECT(s), + "iommu-sun4u", UINT64_MAX); + address_space_init(&s->iommu_as, MEMORY_REGION(&s->iommu), "iommu-as"); memory_region_init_io(&s->iomem, obj, &iommu_mem_ops, s, "iommu", IOMMU_NREGS * sizeof(uint64_t)); @@ -320,7 +321,7 @@ static void iommu_class_init(ObjectClass *klass, void *data) dc->reset = iommu_reset; } -static const TypeInfo pbm_iommu_info = { +static const TypeInfo iommu_info = { .name = TYPE_SUN4U_IOMMU, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(IOMMUState), @@ -328,23 +329,23 @@ static const TypeInfo pbm_iommu_info = { .class_init = iommu_class_init, }; -static void pbm_iommu_memory_region_class_init(ObjectClass *klass, void *data) +static void sun4u_iommu_memory_region_class_init(ObjectClass *klass, void *data) { IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass); - imrc->translate = pbm_translate_iommu; + imrc->translate = sun4u_translate_iommu; } -static const TypeInfo pbm_iommu_memory_region_info = { +static const TypeInfo sun4u_iommu_memory_region_info = { .parent = TYPE_IOMMU_MEMORY_REGION, - .name = TYPE_APB_IOMMU_MEMORY_REGION, - .class_init = pbm_iommu_memory_region_class_init, + .name = TYPE_SUN4U_IOMMU_MEMORY_REGION, + .class_init = sun4u_iommu_memory_region_class_init, }; -static void pbm_register_types(void) +static void iommu_register_types(void) { - type_register_static(&pbm_iommu_info); - type_register_static(&pbm_iommu_memory_region_info); + type_register_static(&iommu_info); + type_register_static(&sun4u_iommu_memory_region_info); } -type_init(pbm_register_types) +type_init(iommu_register_types) diff --git a/include/hw/sparc/sun4u_iommu.h b/include/hw/sparc/sun4u_iommu.h index bc4506b5b0..a760172e8e 100644 --- a/include/hw/sparc/sun4u_iommu.h +++ b/include/hw/sparc/sun4u_iommu.h @@ -45,6 +45,6 @@ typedef struct IOMMUState { #define TYPE_SUN4U_IOMMU "sun4u-iommu" #define SUN4U_IOMMU(obj) OBJECT_CHECK(IOMMUState, (obj), TYPE_SUN4U_IOMMU) -#define TYPE_APB_IOMMU_MEMORY_REGION "pbm-iommu-memory-region" +#define TYPE_SUN4U_IOMMU_MEMORY_REGION "sun4u-iommu-memory-region" #endif From 09ecbb785b7f84053d835fd360bffaf871418566 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Mon, 8 Jan 2018 18:16:34 +0000 Subject: [PATCH 24/25] sun4u_iommu: convert from IOMMU_DPRINTF to trace-events Signed-off-by: Mark Cave-Ayland Acked-by: Artyom Tarasenko --- hw/sparc64/sun4u_iommu.c | 17 +++-------------- hw/sparc64/trace-events | 4 ++++ 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/hw/sparc64/sun4u_iommu.c b/hw/sparc64/sun4u_iommu.c index 612fec4c64..51fbc394ce 100644 --- a/hw/sparc64/sun4u_iommu.c +++ b/hw/sparc64/sun4u_iommu.c @@ -30,16 +30,7 @@ #include "exec/address-spaces.h" #include "qapi/error.h" #include "qemu/log.h" - -/* debug IOMMU */ -//#define DEBUG_IOMMU - -#ifdef DEBUG_IOMMU -#define IOMMU_DPRINTF(fmt, ...) \ -do { printf("IOMMU: " fmt , ## __VA_ARGS__); } while (0) -#else -#define IOMMU_DPRINTF(fmt, ...) -#endif +#include "trace.h" #define IOMMU_PAGE_SIZE_8K (1ULL << 13) @@ -201,8 +192,7 @@ static void iommu_mem_write(void *opaque, hwaddr addr, { IOMMUState *is = opaque; - IOMMU_DPRINTF("IOMMU config write: 0x%" HWADDR_PRIx " val: %" PRIx64 - " size: %d\n", addr, val, size); + trace_sun4u_iommu_mem_write(addr, val, size); switch (addr) { case IOMMU_CTRL: @@ -280,8 +270,7 @@ static uint64_t iommu_mem_read(void *opaque, hwaddr addr, unsigned size) break; } - IOMMU_DPRINTF("IOMMU config read: 0x%" HWADDR_PRIx " val: %" PRIx64 - " size: %d\n", addr, val, size); + trace_sun4u_iommu_mem_read(addr, val, size); return val; } diff --git a/hw/sparc64/trace-events b/hw/sparc64/trace-events index 04d80b7f70..052352feea 100644 --- a/hw/sparc64/trace-events +++ b/hw/sparc64/trace-events @@ -2,3 +2,7 @@ # hw/sparc64/sun4u.c ebus_isa_irq_handler(int n, int level) "Set ISA IRQ %d level %d" + +# hw/sparc64/sun4u_iommu.c +sun4u_iommu_mem_read(uint64_t addr, uint64_t val, int size) "addr: 0x%"PRIx64" val: 0x%"PRIx64" size: %d" +sun4u_iommu_mem_write(uint64_t addr, uint64_t val, int size) "addr: 0x%"PRIx64" val: 0x%"PRIx64" size: %d" From 602c993a3e7d26a10967cd6ddc8349384e1fb53b Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Mon, 8 Jan 2018 18:16:34 +0000 Subject: [PATCH 25/25] sun4u_iommu: add trace event for IOMMU translations Signed-off-by: Mark Cave-Ayland Acked-by: Artyom Tarasenko --- hw/sparc64/sun4u_iommu.c | 2 ++ hw/sparc64/trace-events | 1 + 2 files changed, 3 insertions(+) diff --git a/hw/sparc64/sun4u_iommu.c b/hw/sparc64/sun4u_iommu.c index 51fbc394ce..4cf8e69be9 100644 --- a/hw/sparc64/sun4u_iommu.c +++ b/hw/sparc64/sun4u_iommu.c @@ -184,6 +184,8 @@ static IOMMUTLBEntry sun4u_translate_iommu(IOMMUMemoryRegion *iommu, ret.addr_mask = (IOMMU_PAGE_SIZE_8K - 1); } + trace_sun4u_iommu_translate(ret.iova, ret.translated_addr, tte); + return ret; } diff --git a/hw/sparc64/trace-events b/hw/sparc64/trace-events index 052352feea..2ee2d75f70 100644 --- a/hw/sparc64/trace-events +++ b/hw/sparc64/trace-events @@ -6,3 +6,4 @@ ebus_isa_irq_handler(int n, int level) "Set ISA IRQ %d level %d" # hw/sparc64/sun4u_iommu.c sun4u_iommu_mem_read(uint64_t addr, uint64_t val, int size) "addr: 0x%"PRIx64" val: 0x%"PRIx64" size: %d" sun4u_iommu_mem_write(uint64_t addr, uint64_t val, int size) "addr: 0x%"PRIx64" val: 0x%"PRIx64" size: %d" +sun4u_iommu_translate(uint64_t addr, uint64_t trans_addr, uint64_t tte) "xlate 0x%"PRIx64" => pa 0x%"PRIx64" tte: 0x%"PRIx64