From patchwork Tue Feb 4 16:54:03 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Will Deacon X-Patchwork-Id: 3578011 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 9817E9F382 for ; Tue, 4 Feb 2014 16:55:30 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 8D5C62017D for ; Tue, 4 Feb 2014 16:55:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 73F6720181 for ; Tue, 4 Feb 2014 16:55:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932273AbaBDQyc (ORCPT ); Tue, 4 Feb 2014 11:54:32 -0500 Received: from cam-admin0.cambridge.arm.com ([217.140.96.50]:49664 "EHLO cam-admin0.cambridge.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932246AbaBDQy2 (ORCPT ); Tue, 4 Feb 2014 11:54:28 -0500 Received: from mudshark.cambridge.arm.com (mudshark.cambridge.arm.com [10.1.203.36]) by cam-admin0.cambridge.arm.com (8.12.6/8.12.6) with ESMTP id s14Gs9ko003410; Tue, 4 Feb 2014 16:54:10 GMT Received: by mudshark.cambridge.arm.com (Postfix, from userid 1000) id AEF8FC2B1B; Tue, 4 Feb 2014 16:54:09 +0000 (GMT) From: Will Deacon To: kvm@vger.kernel.org Cc: kvmarm@lists.cs.columbia.edu, penberg@kernel.org, marc.zyngier@arm.com, arnd@arndb.de, Will Deacon Subject: [PATCH 15/17] kvm tools: ARM: generate an fdt node for our PCI emulation Date: Tue, 4 Feb 2014 16:54:03 +0000 Message-Id: <1391532845-2177-16-git-send-email-will.deacon@arm.com> X-Mailer: git-send-email 1.8.2.2 In-Reply-To: <1391532845-2177-1-git-send-email-will.deacon@arm.com> References: <1391532845-2177-1-git-send-email-will.deacon@arm.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Spam-Status: No, score=-7.5 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch factors out some of the openfirmware PCI binding definitions from the powerpc spapr PCI code and uses them to generate appropriate FDT properties for the PCI node on ARM. Signed-off-by: Will Deacon --- tools/kvm/Makefile | 2 +- tools/kvm/arm/fdt.c | 4 ++ tools/kvm/arm/include/arm-common/pci.h | 6 ++ tools/kvm/arm/pci.c | 118 +++++++++++++++++++++++++++++++++ tools/kvm/include/kvm/of_pci.h | 44 ++++++++++++ 5 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 tools/kvm/arm/include/arm-common/pci.h create mode 100644 tools/kvm/arm/pci.c create mode 100644 tools/kvm/include/kvm/of_pci.h diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile index 29f18220c749..b87265189d1f 100644 --- a/tools/kvm/Makefile +++ b/tools/kvm/Makefile @@ -158,7 +158,7 @@ endif # ARM OBJS_ARM_COMMON := arm/fdt.o arm/gic.o arm/ioport.o arm/irq.o \ - arm/kvm.o arm/kvm-cpu.o arm/timer.o + arm/kvm.o arm/kvm-cpu.o arm/pci.o arm/timer.o HDRS_ARM_COMMON := arm/include ifeq ($(ARCH), arm) DEFINES += -DCONFIG_ARM diff --git a/tools/kvm/arm/fdt.c b/tools/kvm/arm/fdt.c index 9a34d9804930..d90fc9e1734f 100644 --- a/tools/kvm/arm/fdt.c +++ b/tools/kvm/arm/fdt.c @@ -5,6 +5,7 @@ #include "kvm/virtio-mmio.h" #include "arm-common/gic.h" +#include "arm-common/pci.h" #include @@ -155,6 +156,9 @@ static int setup_fdt(struct kvm *kvm) dev_hdr = device__next_dev(dev_hdr); } + /* PCI host controller */ + pci__generate_fdt_nodes(fdt, gic_phandle); + /* PSCI firmware */ _FDT(fdt_begin_node(fdt, "psci")); _FDT(fdt_property_string(fdt, "compatible", "arm,psci")); diff --git a/tools/kvm/arm/include/arm-common/pci.h b/tools/kvm/arm/include/arm-common/pci.h new file mode 100644 index 000000000000..ee87725ee82f --- /dev/null +++ b/tools/kvm/arm/include/arm-common/pci.h @@ -0,0 +1,6 @@ +#ifndef ARM_COMMON__PCI_H +#define ARM_COMMON__PCI_H + +void pci__generate_fdt_nodes(void *fdt, u32 gic_phandle); + +#endif /* ARM_COMMON__PCI_H */ diff --git a/tools/kvm/arm/pci.c b/tools/kvm/arm/pci.c new file mode 100644 index 000000000000..ce1932ecc3ee --- /dev/null +++ b/tools/kvm/arm/pci.c @@ -0,0 +1,118 @@ +#include "kvm/devices.h" +#include "kvm/fdt.h" +#include "kvm/of_pci.h" +#include "kvm/pci.h" +#include "kvm/util.h" + +#include "arm-common/pci.h" + +/* + * An entry in the interrupt-map table looks like: + * + */ + +struct of_gic_irq { + u32 type, num, flags; +} __attribute__((packed)); + +struct of_interrupt_map_entry { + struct of_pci_irq_mask pci_irq_mask; + u32 gic_phandle; + struct of_gic_irq gic_irq; +} __attribute__((packed)); + +void pci__generate_fdt_nodes(void *fdt, u32 gic_phandle) +{ + struct device_header *dev_hdr; + struct of_interrupt_map_entry irq_map[OF_PCI_IRQ_MAP_MAX]; + unsigned nentries = 0; + /* Describe the memory ranges (config and memory) */ + struct of_pci_ranges_entry ranges[] = { + { + .pci_addr = { + .hi = cpu_to_fdt32(of_pci_b_ss(OF_PCI_SS_CONFIG)), + .mid = 0, + .lo = 0, + }, + .cpu_addr = cpu_to_fdt64(KVM_PCI_CFG_AREA), + .length = cpu_to_fdt64(ARM_PCI_CFG_SIZE), + }, + { + .pci_addr = { + .hi = cpu_to_fdt32(of_pci_b_ss(OF_PCI_SS_IO)), + .mid = 0, + .lo = 0, + }, + .cpu_addr = cpu_to_fdt64(KVM_IOPORT_AREA), + .length = cpu_to_fdt64(ARM_IOPORT_SIZE), + }, + { + .pci_addr = { + .hi = cpu_to_fdt32(of_pci_b_ss(OF_PCI_SS_M32)), + .mid = 0, + .lo = 0, + }, + .cpu_addr = cpu_to_fdt64(KVM_PCI_MMIO_AREA), + .length = cpu_to_fdt64(ARM_PCI_MMIO_SIZE), + }, + }; + + /* Boilerplate PCI properties */ + _FDT(fdt_begin_node(fdt, "pci")); + _FDT(fdt_property_cell(fdt, "#address-cells", 0x3)); + _FDT(fdt_property_cell(fdt, "#size-cells", 0x2)); + _FDT(fdt_property_cell(fdt, "#interrupt-cells", 0x1)); + _FDT(fdt_property_string(fdt, "compatible", "linux,pci-virt")); + + _FDT(fdt_property(fdt, "ranges", ranges, sizeof(ranges))); + + /* Generate the interrupt map ... */ + dev_hdr = device__first_dev(DEVICE_BUS_PCI); + while (dev_hdr && nentries < ARRAY_SIZE(irq_map)) { + struct of_interrupt_map_entry *entry = &irq_map[nentries]; + struct pci_device_header *pci_hdr = dev_hdr->data; + u8 dev_num = dev_hdr->dev_num; + u8 pin = pci_hdr->irq_pin; + u8 irq = pci_hdr->irq_line; + + *entry = (struct of_interrupt_map_entry) { + .pci_irq_mask = { + .pci_addr = { + .hi = cpu_to_fdt32(of_pci_b_ddddd(dev_num)), + .mid = 0, + .lo = 0, + }, + .pci_pin = cpu_to_fdt32(pin), + }, + .gic_phandle = cpu_to_fdt32(gic_phandle), + .gic_irq = { + .type = cpu_to_fdt32(GIC_FDT_IRQ_TYPE_SPI), + .num = cpu_to_fdt32(irq - GIC_SPI_IRQ_BASE), + .flags = cpu_to_fdt32(GIC_FDT_IRQ_FLAGS_EDGE_LO_HI), + }, + }; + + nentries++; + dev_hdr = device__next_dev(dev_hdr); + } + + _FDT(fdt_property(fdt, "interrupt-map", irq_map, + sizeof(struct of_interrupt_map_entry) * nentries)); + + /* ... and the corresponding mask. */ + if (nentries) { + struct of_pci_irq_mask irq_mask = { + .pci_addr = { + .hi = cpu_to_fdt32(of_pci_b_ddddd(-1)), + .mid = 0, + .lo = 0, + }, + .pci_pin = cpu_to_fdt32(7), + }; + + _FDT(fdt_property(fdt, "interrupt-map-mask", &irq_mask, + sizeof(irq_mask))); + } + + _FDT(fdt_end_node(fdt)); +} diff --git a/tools/kvm/include/kvm/of_pci.h b/tools/kvm/include/kvm/of_pci.h new file mode 100644 index 000000000000..c8187ab378a1 --- /dev/null +++ b/tools/kvm/include/kvm/of_pci.h @@ -0,0 +1,44 @@ +#ifndef KVM__OF_PCI_H +#define KVM__OF_PCI_H + +#include + +/* + * Definitions for implementing parts of the OpenFirmware PCI Bus Binding + * Specification (IEEE Std 1275-1994). + */ + +struct of_pci_unit_address { + u32 hi, mid, lo; +} __attribute__((packed)); + +struct of_pci_irq_mask { + struct of_pci_unit_address pci_addr; + u32 pci_pin; +} __attribute__((packed)); + +struct of_pci_ranges_entry { + struct of_pci_unit_address pci_addr; + u64 cpu_addr; + u64 length; +} __attribute__((packed)); + +/* Macros to operate with address in OF binding to PCI */ +#define __b_x(x, p, l) (((x) & ((1<<(l))-1)) << (p)) +#define of_pci_b_n(x) __b_x((x), 31, 1) /* 0 if relocatable */ +#define of_pci_b_p(x) __b_x((x), 30, 1) /* 1 if prefetchable */ +#define of_pci_b_t(x) __b_x((x), 29, 1) /* 1 if the address is aliased */ +#define of_pci_b_ss(x) __b_x((x), 24, 2) /* the space code */ +#define of_pci_b_bbbbbbbb(x) __b_x((x), 16, 8) /* bus number */ +#define of_pci_b_ddddd(x) __b_x((x), 11, 5) /* device number */ +#define of_pci_b_fff(x) __b_x((x), 8, 3) /* function number */ +#define of_pci_b_rrrrrrrr(x) __b_x((x), 0, 8) /* register number */ + +#define OF_PCI_SS_CONFIG 0 +#define OF_PCI_SS_IO 1 +#define OF_PCI_SS_M32 2 +#define OF_PCI_SS_M64 3 + +#define OF_PCI_IRQ_MAP_MAX 256 /* 5 bit device + 3 bit pin */ + +#endif /* KVM__OF_PCI_H */