* [PATCH QEMU 00/12] vfio: pci: Enable DDW and in-kernel acceleration
From: Alexey Kardashevskiy @ 2014-07-15 9:39 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Alexey Kardashevskiy, Paul Mackerras, Gavin Shan
This makes use of kernel patchsets:
[PATCH v1 00/16] powernv: vfio: Add Dynamic DMA windows (DDW)
[PATCH v1 0/7] powerpc/iommu: kvm: Enable MultiTCE support
[PATCH v1 00/13] powerpc: kvm: Enable in-kernel acceleration for VFIO
I am posting it for reference here, reviews are still welcome but not required :)
Alexey Kardashevskiy (12):
spapr_iommu: Disable in-kernel IOMMU tables for >4GB windows
spapr_pci: Make find_phb()/find_dev() public
spapr_iommu: Make spapr_tce_find_by_liobn() public
linux headers update for DDW
spapr_rtas: Add Dynamic DMA windows (DDW) RTAS calls support
spapr: Add "ddw" machine option
spapr_pci: Enable DDW
spapr_pci_vfio: Enable DDW
vfio: Enable DDW ioctls to VFIO IOMMU driver
headers: update for KVM_CAP_SPAPR_TCE_64 and VFIO KVM device
target-ppc: kvm: make use of KVM_CREATE_SPAPR_TCE_64
vfio: Enable in-kernel acceleration via VFIO KVM device
hw/misc/vfio.c | 45 ++++++
hw/ppc/Makefile.objs | 3 +
hw/ppc/spapr.c | 15 ++
hw/ppc/spapr_iommu.c | 6 +-
hw/ppc/spapr_pci.c | 84 +++++++++--
hw/ppc/spapr_pci_vfio.c | 95 ++++++++++++
hw/ppc/spapr_rtas_ddw.c | 296 ++++++++++++++++++++++++++++++++++++++
include/hw/misc/vfio.h | 5 +
include/hw/pci-host/spapr.h | 25 ++++
include/hw/ppc/spapr.h | 8 +-
linux-headers/asm-mips/kvm_para.h | 6 +-
linux-headers/asm-powerpc/kvm.h | 9 ++
linux-headers/linux/kvm.h | 12 ++
linux-headers/linux/kvm_para.h | 3 +
linux-headers/linux/vfio.h | 37 ++++-
target-ppc/kvm.c | 47 ++++--
target-ppc/kvm_ppc.h | 10 +-
trace-events | 4 +
vl.c | 4 +
19 files changed, 683 insertions(+), 31 deletions(-)
create mode 100644 hw/ppc/spapr_rtas_ddw.c
--
2.0.0
^ permalink raw reply
* [PATCH QEMU 05/12] spapr_rtas: Add Dynamic DMA windows (DDW) RTAS calls support
From: Alexey Kardashevskiy @ 2014-07-15 9:39 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Alexey Kardashevskiy, Paul Mackerras, Gavin Shan
In-Reply-To: <1405417184-14333-1-git-send-email-aik@ozlabs.ru>
spapr_pci_vfio: Support dynamic DMA window
This adds support for Dynamic DMA Windows (DDW) option defined by
the SPAPR specification which allows to have additional DMA windows besides
the default and small one which can only handle 4K pages and which
should completely fit into first 32bit of PCI address space what makes it
less than perfect solution for high-speed PCI devices.
The existing implementation of DDW in the guest tries to create one huge
DMA window with 64K or 16MB pages and map the entire guest RAM to. If this
operation suceedes, the guest switches to dma_direct_ops and never calls
TCE hypercalls (H_PUT_TCE,...). This enables VFIO devices to use the entire
RAM and not spend time on mapping/unmapping.
This adds 4 RTAS handlers:
* ibm,query-pe-dma-window
* ibm,create-pe-dma-window
* ibm,remove-pe-dma-window
* ibm,reset-pe-dma-window
These are registered from qapi_init callback.
This adds @ddw_supported property to sPAPRPHBState to enable DDW
feature.
This adds @ddw_reset_supported property to sPAPRPHBState to enable DDW
"reset" extention (TODO: debug).
This bumps migration descriptor version as there are 2 new properties.
This adds a notifier for VFIO to provide path for calling DDW-related
ioctls via VFIO container fd.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
"Reset" is not implemented yet and it is questionable if we really want it.
---
hw/ppc/Makefile.objs | 3 +
hw/ppc/spapr_rtas_ddw.c | 296 ++++++++++++++++++++++++++++++++++++++++++++
include/hw/pci-host/spapr.h | 18 +++
include/hw/ppc/spapr.h | 7 +-
trace-events | 4 +
5 files changed, 326 insertions(+), 2 deletions(-)
create mode 100644 hw/ppc/spapr_rtas_ddw.c
diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index edd44d0..9773294 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -7,6 +7,9 @@ obj-$(CONFIG_PSERIES) += spapr_pci.o
ifeq ($(CONFIG_PCI)$(CONFIG_PSERIES)$(CONFIG_LINUX), yyy)
obj-y += spapr_pci_vfio.o
endif
+ifeq ($(CONFIG_PCI)$(CONFIG_PSERIES), yy)
+obj-y += spapr_rtas_ddw.o
+endif
# PowerPC 4xx boards
obj-y += ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o
obj-y += ppc4xx_pci.o
diff --git a/hw/ppc/spapr_rtas_ddw.c b/hw/ppc/spapr_rtas_ddw.c
new file mode 100644
index 0000000..943af2c
--- /dev/null
+++ b/hw/ppc/spapr_rtas_ddw.c
@@ -0,0 +1,296 @@
+/*
+ * QEMU sPAPR Dynamic DMA windows support
+ *
+ * Copyright (c) 2014 Alexey Kardashevskiy, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hw/ppc/spapr.h"
+#include "hw/pci-host/spapr.h"
+#include "trace.h"
+
+static inline uint32_t spapr_iommu_fixmask(uint32_t cur_mask,
+ struct ppc_one_seg_page_size *sps,
+ uint32_t query_mask,
+ int shift,
+ uint32_t add_mask)
+{
+ if ((sps->page_shift == shift) && (query_mask & add_mask)) {
+ cur_mask |= add_mask;
+ }
+ return cur_mask;
+}
+
+static void rtas_ibm_query_pe_dma_window(PowerPCCPU *cpu,
+ sPAPREnvironment *spapr,
+ uint32_t token, uint32_t nargs,
+ target_ulong args,
+ uint32_t nret, target_ulong rets)
+{
+ CPUPPCState *env = &cpu->env;
+ sPAPRPHBState *sphb;
+ sPAPRPHBClass *spc;
+ uint64_t buid;
+ uint32_t addr, pgmask = 0;
+ uint32_t windows_available = 0, page_size_mask = 0;
+ long ret, i;
+
+ if ((nargs != 3) || (nret != 5)) {
+ goto param_error_exit;
+ }
+
+ buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
+ addr = rtas_ld(args, 0);
+ sphb = spapr_pci_find_phb(spapr, buid);
+ if (!sphb) {
+ goto param_error_exit;
+ }
+
+ spc = SPAPR_PCI_HOST_BRIDGE_GET_CLASS(sphb);
+ if (!spc->ddw_query) {
+ goto hw_error_exit;
+ }
+
+ ret = spc->ddw_query(sphb, &windows_available, &page_size_mask);
+ trace_spapr_iommu_ddw_query(buid, addr, windows_available,
+ page_size_mask, pgmask, ret);
+ if (ret) {
+ goto hw_error_exit;
+ }
+
+ /* DBG! */
+ if (!(page_size_mask & DDW_PGSIZE_16M)) {
+ goto hw_error_exit;
+ }
+
+ /* Work out biggest possible page size */
+ for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) {
+ int j;
+ struct ppc_one_seg_page_size *sps = &env->sps.sps[i];
+ const struct { int shift; uint32_t mask; } masks[] = {
+ { 12, DDW_PGSIZE_4K },
+ { 16, DDW_PGSIZE_64K },
+ { 24, DDW_PGSIZE_16M },
+ { 25, DDW_PGSIZE_32M },
+ { 26, DDW_PGSIZE_64M },
+ { 27, DDW_PGSIZE_128M },
+ { 28, DDW_PGSIZE_256M },
+ { 34, DDW_PGSIZE_16G },
+ };
+ for (j = 0; j < ARRAY_SIZE(masks); ++j) {
+ pgmask = spapr_iommu_fixmask(pgmask, sps, page_size_mask,
+ masks[j].shift, masks[j].mask);
+ }
+ }
+
+ rtas_st(rets, 0, RTAS_OUT_SUCCESS);
+ rtas_st(rets, 1, windows_available);
+ /* Return maximum number as all RAM was 4K pages */
+ rtas_st(rets, 2, ram_size >> SPAPR_TCE_PAGE_SHIFT);
+ rtas_st(rets, 3, pgmask);
+ rtas_st(rets, 4, pgmask); /* DMA migration mask */
+ return;
+
+hw_error_exit:
+ rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
+ return;
+
+param_error_exit:
+ rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
+}
+
+static void rtas_ibm_create_pe_dma_window(PowerPCCPU *cpu,
+ sPAPREnvironment *spapr,
+ uint32_t token, uint32_t nargs,
+ target_ulong args,
+ uint32_t nret, target_ulong rets)
+{
+ sPAPRPHBState *sphb;
+ sPAPRPHBClass *spc;
+ sPAPRTCETable *tcet = NULL;
+ uint32_t addr, page_shift, window_shift, liobn;
+ uint64_t buid;
+ long ret;
+
+ if ((nargs != 5) || (nret != 4)) {
+ goto param_error_exit;
+ }
+
+ buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
+ addr = rtas_ld(args, 0);
+ sphb = spapr_pci_find_phb(spapr, buid);
+ if (!sphb) {
+ goto param_error_exit;
+ }
+
+ spc = SPAPR_PCI_HOST_BRIDGE_GET_CLASS(sphb);
+ if (!spc->ddw_create) {
+ goto hw_error_exit;
+ }
+
+ page_shift = rtas_ld(args, 3);
+ window_shift = rtas_ld(args, 4);
+ liobn = sphb->dma_liobn + 0x10000;
+
+ ret = spc->ddw_create(sphb, page_shift, window_shift, liobn, &tcet);
+ trace_spapr_iommu_ddw_create(buid, addr, 1 << page_shift,
+ 1 << window_shift,
+ tcet ? tcet->bus_offset : 0xbaadf00d,
+ liobn, ret);
+ if (ret || !tcet) {
+ goto hw_error_exit;
+ }
+
+ rtas_st(rets, 0, RTAS_OUT_SUCCESS);
+ rtas_st(rets, 1, liobn);
+ rtas_st(rets, 2, tcet->bus_offset >> 32);
+ rtas_st(rets, 3, tcet->bus_offset & ((uint32_t) -1));
+ return;
+
+hw_error_exit:
+ rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
+ return;
+
+param_error_exit:
+ rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
+}
+
+static void rtas_ibm_remove_pe_dma_window(PowerPCCPU *cpu,
+ sPAPREnvironment *spapr,
+ uint32_t token, uint32_t nargs,
+ target_ulong args,
+ uint32_t nret, target_ulong rets)
+{
+ sPAPRPHBState *sphb;
+ sPAPRPHBClass *spc;
+ sPAPRTCETable *tcet;
+ uint32_t liobn;
+ long ret;
+
+ if ((nargs != 1) || (nret != 1)) {
+ goto param_error_exit;
+ }
+
+ liobn = rtas_ld(args, 0);
+ tcet = spapr_tce_find_by_liobn(liobn);
+ if (!tcet) {
+ goto param_error_exit;
+ }
+
+ sphb = SPAPR_PCI_HOST_BRIDGE(OBJECT(tcet)->parent);
+ if (!sphb) {
+ goto param_error_exit;
+ }
+
+ spc = SPAPR_PCI_HOST_BRIDGE_GET_CLASS(sphb);
+ if (!spc->ddw_remove) {
+ goto hw_error_exit;
+ }
+
+ ret = spc->ddw_remove(sphb, tcet);
+ trace_spapr_iommu_ddw_remove(liobn, ret);
+ if (ret) {
+ goto hw_error_exit;
+ }
+
+ object_unparent(OBJECT(tcet));
+
+ rtas_st(rets, 0, RTAS_OUT_SUCCESS);
+ return;
+
+hw_error_exit:
+ rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
+ return;
+
+param_error_exit:
+ rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
+}
+
+static int ddw_remove_tce_table_cb(Object *child, void *opaque)
+{
+ sPAPRTCETable *tcet;
+
+ tcet = (sPAPRTCETable *) object_dynamic_cast(child, TYPE_SPAPR_TCE_TABLE);
+ if (tcet && tcet->bus_offset) {
+ object_unparent(child);
+ }
+
+ return 0;
+}
+
+static void rtas_ibm_reset_pe_dma_window(PowerPCCPU *cpu,
+ sPAPREnvironment *spapr,
+ uint32_t token, uint32_t nargs,
+ target_ulong args,
+ uint32_t nret, target_ulong rets)
+{
+ sPAPRPHBState *sphb;
+ sPAPRPHBClass *spc;
+ uint64_t buid;
+ uint32_t addr;
+ long ret;
+
+ if ((nargs != 3) || (nret != 1)) {
+ goto param_error_exit;
+ }
+
+ buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
+ addr = rtas_ld(args, 0);
+ sphb = spapr_pci_find_phb(spapr, buid);
+ if (!sphb) {
+ goto param_error_exit;
+ }
+
+ spc = SPAPR_PCI_HOST_BRIDGE_GET_CLASS(sphb);
+ if (!spc->ddw_reset) {
+ goto hw_error_exit;
+ }
+
+ ret = spc->ddw_reset(sphb);
+ trace_spapr_iommu_ddw_reset(buid, addr, ret);
+ if (ret) {
+ goto hw_error_exit;
+ }
+
+ object_child_foreach(OBJECT(sphb), ddw_remove_tce_table_cb, NULL);
+
+ rtas_st(rets, 0, RTAS_OUT_SUCCESS);
+ return;
+
+hw_error_exit:
+ rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
+ return;
+
+param_error_exit:
+ rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
+}
+
+static void spapr_rtas_ddw_init(void)
+{
+ spapr_rtas_register(RTAS_IBM_QUERY_PE_DMA_WINDOW,
+ "ibm,query-pe-dma-window",
+ rtas_ibm_query_pe_dma_window);
+ spapr_rtas_register(RTAS_IBM_CREATE_PE_DMA_WINDOW,
+ "ibm,create-pe-dma-window",
+ rtas_ibm_create_pe_dma_window);
+ spapr_rtas_register(RTAS_IBM_REMOVE_PE_DMA_WINDOW,
+ "ibm,remove-pe-dma-window",
+ rtas_ibm_remove_pe_dma_window);
+ spapr_rtas_register(RTAS_IBM_RESET_PE_DMA_WINDOW,
+ "ibm,reset-pe-dma-window",
+ rtas_ibm_reset_pe_dma_window);
+}
+
+type_init(spapr_rtas_ddw_init)
diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h
index 14c2ab0..119d326 100644
--- a/include/hw/pci-host/spapr.h
+++ b/include/hw/pci-host/spapr.h
@@ -49,6 +49,24 @@ struct sPAPRPHBClass {
PCIHostBridgeClass parent_class;
void (*finish_realize)(sPAPRPHBState *sphb, Error **errp);
+
+/* sPAPR spec defined pagesize mask values */
+#define DDW_PGSIZE_4K 0x01
+#define DDW_PGSIZE_64K 0x02
+#define DDW_PGSIZE_16M 0x04
+#define DDW_PGSIZE_32M 0x08
+#define DDW_PGSIZE_64M 0x10
+#define DDW_PGSIZE_128M 0x20
+#define DDW_PGSIZE_256M 0x40
+#define DDW_PGSIZE_16G 0x80
+
+ int (*ddw_query)(sPAPRPHBState *sphb, uint32_t *windows_available,
+ uint32_t *page_size_mask);
+ int (*ddw_create)(sPAPRPHBState *sphb, uint32_t page_shift,
+ uint32_t window_shift, uint32_t liobn,
+ sPAPRTCETable **ptcet);
+ int (*ddw_remove)(sPAPRPHBState *sphb, sPAPRTCETable *tcet);
+ int (*ddw_reset)(sPAPRPHBState *sphb);
};
typedef struct spapr_pci_msi {
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 9c5686e..afda68f 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -382,9 +382,12 @@ int spapr_allocate_irq_block(int num, bool lsi, bool msi);
#define RTAS_GET_SENSOR_STATE (RTAS_TOKEN_BASE + 0x1D)
#define RTAS_IBM_CONFIGURE_CONNECTOR (RTAS_TOKEN_BASE + 0x1E)
#define RTAS_IBM_OS_TERM (RTAS_TOKEN_BASE + 0x1F)
-#define RTAS_IBM_EXTENDED_OS_TERM (RTAS_TOKEN_BASE + 0x20)
+#define RTAS_IBM_QUERY_PE_DMA_WINDOW (RTAS_TOKEN_BASE + 0x20)
+#define RTAS_IBM_CREATE_PE_DMA_WINDOW (RTAS_TOKEN_BASE + 0x21)
+#define RTAS_IBM_REMOVE_PE_DMA_WINDOW (RTAS_TOKEN_BASE + 0x22)
+#define RTAS_IBM_RESET_PE_DMA_WINDOW (RTAS_TOKEN_BASE + 0x23)
-#define RTAS_TOKEN_MAX (RTAS_TOKEN_BASE + 0x21)
+#define RTAS_TOKEN_MAX (RTAS_TOKEN_BASE + 0x24)
/* RTAS ibm,get-system-parameter token values */
#define RTAS_SYSPARM_SPLPAR_CHARACTERISTICS 20
diff --git a/trace-events b/trace-events
index 11a17a8..5b54fbd 100644
--- a/trace-events
+++ b/trace-events
@@ -1213,6 +1213,10 @@ spapr_iommu_indirect(uint64_t liobn, uint64_t ioba, uint64_t tce, uint64_t iobaN
spapr_iommu_stuff(uint64_t liobn, uint64_t ioba, uint64_t tce_value, uint64_t npages, uint64_t ret) "liobn=%"PRIx64" ioba=0x%"PRIx64" tcevalue=0x%"PRIx64" npages=%"PRId64" ret=%"PRId64
spapr_iommu_xlate(uint64_t liobn, uint64_t ioba, uint64_t tce, unsigned perm, unsigned pgsize) "liobn=%"PRIx64" 0x%"PRIx64" -> 0x%"PRIx64" perm=%u mask=%x"
spapr_iommu_new_table(uint64_t liobn, void *tcet, void *table, int fd) "liobn=%"PRIx64" tcet=%p table=%p fd=%d"
+spapr_iommu_ddw_query(uint64_t buid, uint32_t cfgaddr, uint32_t wa, uint32_t pgz, uint32_t pgz_fixed, long ret) "buid=%"PRIx64" addr=%"PRIx32", %u windows available, sizes %"PRIx32", fixed %"PRIx32", ret = %ld"
+spapr_iommu_ddw_create(uint64_t buid, uint32_t cfgaddr, unsigned long long pg_size, unsigned long long req_size, uint64_t start, uint32_t liobn, long ret) "buid=%"PRIx64" addr=%"PRIx32", page size=0x%llx, requested=0x%llx, start addr=%"PRIx64", liobn=%"PRIx32", ret = %ld"
+spapr_iommu_ddw_remove(uint32_t liobn, long ret) "liobn=%"PRIx32", ret = %ld"
+spapr_iommu_ddw_reset(uint64_t buid, uint32_t cfgaddr, long ret) "buid=%"PRIx64" addr=%"PRIx32", ret = %ld"
# hw/ppc/ppc.c
ppc_tb_adjust(uint64_t offs1, uint64_t offs2, int64_t diff, int64_t seconds) "adjusted from 0x%"PRIx64" to 0x%"PRIx64", diff %"PRId64" (%"PRId64"s)"
--
2.0.0
^ permalink raw reply related
* [PATCH QEMU 02/12] spapr_pci: Make find_phb()/find_dev() public
From: Alexey Kardashevskiy @ 2014-07-15 9:39 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Alexey Kardashevskiy, Paul Mackerras, Gavin Shan
In-Reply-To: <1405417184-14333-1-git-send-email-aik@ozlabs.ru>
This makes find_phb()/find_dev() public and changed its names
to spapr_pci_find_phb()/spapr_pci_find_dev() as they are going to
be used from other parts of QEMU such as VFIO DDW (dynamic DMA window)
or VFIO PCI error injection or VFIO EEH handling - in all these
cases there are RTAS calls which are addressed to BUID+config_addr
in IEEE1275 format.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
hw/ppc/spapr_pci.c | 22 +++++++++++-----------
include/hw/pci-host/spapr.h | 4 ++++
2 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 9ed39a9..230b59c 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -47,7 +47,7 @@
#define RTAS_TYPE_MSI 1
#define RTAS_TYPE_MSIX 2
-static sPAPRPHBState *find_phb(sPAPREnvironment *spapr, uint64_t buid)
+sPAPRPHBState *spapr_pci_find_phb(sPAPREnvironment *spapr, uint64_t buid)
{
sPAPRPHBState *sphb;
@@ -61,10 +61,10 @@ static sPAPRPHBState *find_phb(sPAPREnvironment *spapr, uint64_t buid)
return NULL;
}
-static PCIDevice *find_dev(sPAPREnvironment *spapr, uint64_t buid,
- uint32_t config_addr)
+PCIDevice *spapr_pci_find_dev(sPAPREnvironment *spapr, uint64_t buid,
+ uint32_t config_addr)
{
- sPAPRPHBState *sphb = find_phb(spapr, buid);
+ sPAPRPHBState *sphb = spapr_pci_find_phb(spapr, buid);
PCIHostState *phb = PCI_HOST_BRIDGE(sphb);
int bus_num = (config_addr >> 16) & 0xFF;
int devfn = (config_addr >> 8) & 0xFF;
@@ -95,7 +95,7 @@ static void finish_read_pci_config(sPAPREnvironment *spapr, uint64_t buid,
return;
}
- pci_dev = find_dev(spapr, buid, addr);
+ pci_dev = spapr_pci_find_dev(spapr, buid, addr);
addr = rtas_pci_cfgaddr(addr);
if (!pci_dev || (addr % size) || (addr >= pci_config_size(pci_dev))) {
@@ -162,7 +162,7 @@ static void finish_write_pci_config(sPAPREnvironment *spapr, uint64_t buid,
return;
}
- pci_dev = find_dev(spapr, buid, addr);
+ pci_dev = spapr_pci_find_dev(spapr, buid, addr);
addr = rtas_pci_cfgaddr(addr);
if (!pci_dev || (addr % size) || (addr >= pci_config_size(pci_dev))) {
@@ -281,9 +281,9 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
}
/* Fins sPAPRPHBState */
- phb = find_phb(spapr, buid);
+ phb = spapr_pci_find_phb(spapr, buid);
if (phb) {
- pdev = find_dev(spapr, buid, config_addr);
+ pdev = spapr_pci_find_dev(spapr, buid, config_addr);
}
if (!phb || !pdev) {
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
@@ -377,9 +377,9 @@ static void rtas_ibm_query_interrupt_source_number(PowerPCCPU *cpu,
spapr_pci_msi *msi;
/* Find sPAPRPHBState */
- phb = find_phb(spapr, buid);
+ phb = spapr_pci_find_phb(spapr, buid);
if (phb) {
- pdev = find_dev(spapr, buid, config_addr);
+ pdev = spapr_pci_find_dev(spapr, buid, config_addr);
}
if (!phb || !pdev) {
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
@@ -553,7 +553,7 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
return;
}
- if (find_phb(spapr, sphb->buid)) {
+ if (spapr_pci_find_phb(spapr, sphb->buid)) {
error_setg(errp, "PCI host bridges must have unique BUIDs");
return;
}
diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h
index 32f0aa7..14c2ab0 100644
--- a/include/hw/pci-host/spapr.h
+++ b/include/hw/pci-host/spapr.h
@@ -122,4 +122,8 @@ void spapr_pci_msi_init(sPAPREnvironment *spapr, hwaddr addr);
void spapr_pci_rtas_init(void);
+sPAPRPHBState *spapr_pci_find_phb(sPAPREnvironment *spapr, uint64_t buid);
+PCIDevice *spapr_pci_find_dev(sPAPREnvironment *spapr, uint64_t buid,
+ uint32_t config_addr);
+
#endif /* __HW_SPAPR_PCI_H__ */
--
2.0.0
^ permalink raw reply related
* [PATCH QEMU 04/12] linux headers update for DDW
From: Alexey Kardashevskiy @ 2014-07-15 9:39 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Alexey Kardashevskiy, Paul Mackerras, Gavin Shan
In-Reply-To: <1405417184-14333-1-git-send-email-aik@ozlabs.ru>
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
| 37 ++++++++++++++++++++++++++++++++++++-
1 file changed, 36 insertions(+), 1 deletion(-)
--git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h
index 26c218e..f0aa97d 100644
--- a/linux-headers/linux/vfio.h
+++ b/linux-headers/linux/vfio.h
@@ -448,13 +448,48 @@ struct vfio_iommu_type1_dma_unmap {
*/
struct vfio_iommu_spapr_tce_info {
__u32 argsz;
- __u32 flags; /* reserved for future use */
+ __u32 flags;
+#define VFIO_IOMMU_SPAPR_TCE_FLAG_DDW 1 /* Support dynamic windows */
__u32 dma32_window_start; /* 32 bit window start (bytes) */
__u32 dma32_window_size; /* 32 bit window size (bytes) */
};
#define VFIO_IOMMU_SPAPR_TCE_GET_INFO _IO(VFIO_TYPE, VFIO_BASE + 12)
+/*
+ * Dynamic DMA windows
+ */
+struct vfio_iommu_spapr_tce_query {
+ __u32 argsz;
+ /* out */
+ __u32 windows_available;
+ __u32 page_size_mask;
+};
+#define VFIO_IOMMU_SPAPR_TCE_QUERY _IO(VFIO_TYPE, VFIO_BASE + 17)
+
+struct vfio_iommu_spapr_tce_create {
+ __u32 argsz;
+ /* in */
+ __u32 page_shift;
+ __u32 window_shift;
+ /* out */
+ __u64 start_addr;
+
+};
+#define VFIO_IOMMU_SPAPR_TCE_CREATE _IO(VFIO_TYPE, VFIO_BASE + 18)
+
+struct vfio_iommu_spapr_tce_remove {
+ __u32 argsz;
+ /* in */
+ __u64 start_addr;
+};
+#define VFIO_IOMMU_SPAPR_TCE_REMOVE _IO(VFIO_TYPE, VFIO_BASE + 19)
+
+struct vfio_iommu_spapr_tce_reset {
+ __u32 argsz;
+};
+#define VFIO_IOMMU_SPAPR_TCE_RESET _IO(VFIO_TYPE, VFIO_BASE + 20)
+
/* ***************************************************************** */
#endif /* VFIO_H */
--
2.0.0
^ permalink raw reply related
* [PATCH QEMU 03/12] spapr_iommu: Make spapr_tce_find_by_liobn() public
From: Alexey Kardashevskiy @ 2014-07-15 9:39 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Alexey Kardashevskiy, Paul Mackerras, Gavin Shan
In-Reply-To: <1405417184-14333-1-git-send-email-aik@ozlabs.ru>
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
hw/ppc/spapr_iommu.c | 2 +-
include/hw/ppc/spapr.h | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index 36f5d27..588d442 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -40,7 +40,7 @@ enum sPAPRTCEAccess {
static QLIST_HEAD(spapr_tce_tables, sPAPRTCETable) spapr_tce_tables;
-static sPAPRTCETable *spapr_tce_find_by_liobn(uint32_t liobn)
+sPAPRTCETable *spapr_tce_find_by_liobn(uint32_t liobn)
{
sPAPRTCETable *tcet;
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index bbba51a..9c5686e 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -467,6 +467,7 @@ struct sPAPRTCETable {
QLIST_ENTRY(sPAPRTCETable) list;
};
+sPAPRTCETable *spapr_tce_find_by_liobn(uint32_t liobn);
void spapr_events_init(sPAPREnvironment *spapr);
void spapr_events_fdt_skel(void *fdt, uint32_t epow_irq);
int spapr_h_cas_compose_response(target_ulong addr, target_ulong size);
--
2.0.0
^ permalink raw reply related
* [PATCH QEMU 06/12] spapr: Add "ddw" machine option
From: Alexey Kardashevskiy @ 2014-07-15 9:39 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Alexey Kardashevskiy, Paul Mackerras, Gavin Shan
In-Reply-To: <1405417184-14333-1-git-send-email-aik@ozlabs.ru>
This option will enable Dynamic DMA windows (DDW) support for pseries
machine.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
hw/ppc/spapr.c | 15 +++++++++++++++
vl.c | 4 ++++
2 files changed, 19 insertions(+)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index d01978f..fec295b 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -100,6 +100,7 @@ struct sPAPRMachineState {
/*< public >*/
char *kvm_type;
+ bool ddw_supported;
};
sPAPREnvironment *spapr;
@@ -1570,10 +1571,24 @@ static void spapr_set_kvm_type(Object *obj, const char *value, Error **errp)
sm->kvm_type = g_strdup(value);
}
+static bool spapr_machine_get_ddw(Object *obj, Error **errp)
+{
+ sPAPRMachineState *sms = SPAPR_MACHINE(obj);
+ return sms->ddw_supported;
+}
+
+static void spapr_machine_set_ddw(Object *obj, bool value, Error **errp)
+{
+ sPAPRMachineState *sms = SPAPR_MACHINE(obj);
+ sms->ddw_supported = value;
+}
+
static void spapr_machine_initfn(Object *obj)
{
object_property_add_str(obj, "kvm-type",
spapr_get_kvm_type, spapr_set_kvm_type, NULL);
+ object_property_add_bool(obj, "ddw", spapr_machine_get_ddw,
+ spapr_machine_set_ddw, NULL);
}
static void spapr_machine_class_init(ObjectClass *oc, void *data)
diff --git a/vl.c b/vl.c
index 6e084c2..a615fb1 100644
--- a/vl.c
+++ b/vl.c
@@ -383,6 +383,10 @@ static QemuOptsList qemu_machine_opts = {
.name = "kvm-type",
.type = QEMU_OPT_STRING,
.help = "Specifies the KVM virtualization mode (HV, PR)",
+ }, {
+ .name = "ddw",
+ .type = QEMU_OPT_BOOL,
+ .help = "Enable Dynamic DMA windows support (pseries only)",
},{
.name = PC_MACHINE_MAX_RAM_BELOW_4G,
.type = QEMU_OPT_SIZE,
--
2.0.0
^ permalink raw reply related
* [PATCH QEMU 01/12] spapr_iommu: Disable in-kernel IOMMU tables for >4GB windows
From: Alexey Kardashevskiy @ 2014-07-15 9:39 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Alexey Kardashevskiy, Paul Mackerras, Gavin Shan
In-Reply-To: <1405417184-14333-1-git-send-email-aik@ozlabs.ru>
The existing KVM_CREATE_SPAPR_TCE ioctl only support 4G windows max.
We are going to add huge DMA windows support so this will create small
window and unexpectedly fail later.
This disables KVM_CREATE_SPAPR_TCE for windows bigger that 4GB. Since
those windows are normally mapped at the boot time, there will be no
performance impact.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
hw/ppc/spapr_iommu.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index f6e32a4..36f5d27 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -113,11 +113,11 @@ static MemoryRegionIOMMUOps spapr_iommu_ops = {
static int spapr_tce_table_realize(DeviceState *dev)
{
sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev);
+ uint64_t window_size = tcet->nb_table << tcet->page_shift;
- if (kvm_enabled()) {
+ if (kvm_enabled() && !(window_size >> 32)) {
tcet->table = kvmppc_create_spapr_tce(tcet->liobn,
- tcet->nb_table <<
- tcet->page_shift,
+ window_size,
&tcet->fd,
tcet->vfio_accel);
}
--
2.0.0
^ permalink raw reply related
* [PATCH QEMU 07/12] spapr_pci: Enable DDW
From: Alexey Kardashevskiy @ 2014-07-15 9:39 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Alexey Kardashevskiy, Paul Mackerras, Gavin Shan
In-Reply-To: <1405417184-14333-1-git-send-email-aik@ozlabs.ru>
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
hw/ppc/spapr_pci.c | 62 +++++++++++++++++++++++++++++++++++++++++++++
include/hw/pci-host/spapr.h | 3 +++
2 files changed, 65 insertions(+)
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 230b59c..038a485 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -22,6 +22,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+#include "sysemu/sysemu.h"
#include "hw/hw.h"
#include "hw/pci/pci.h"
#include "hw/pci/msi.h"
@@ -781,6 +782,42 @@ static const char *spapr_phb_root_bus_path(PCIHostState *host_bridge,
return sphb->dtbusname;
}
+static int spapr_pci_ddw_query(sPAPRPHBState *sphb,
+ uint32_t *windows_available,
+ uint32_t *page_size_mask)
+{
+ *windows_available = 1;
+ *page_size_mask = DDW_PGSIZE_16M;
+
+ return 0;
+}
+
+static int spapr_pci_ddw_create(sPAPRPHBState *sphb, uint32_t page_shift,
+ uint32_t window_shift, uint32_t liobn,
+ sPAPRTCETable **ptcet)
+{
+ *ptcet = spapr_tce_new_table(DEVICE(sphb), liobn, SPAPR_PCI_TCE64_START,
+ page_shift, 1 << (window_shift - page_shift),
+ true);
+ if (!*ptcet) {
+ return -1;
+ }
+ memory_region_add_subregion(&sphb->iommu_root, (*ptcet)->bus_offset,
+ spapr_tce_get_iommu(*ptcet));
+
+ return 0;
+}
+
+static int spapr_pci_ddw_remove(sPAPRPHBState *sphb, sPAPRTCETable *tcet)
+{
+ return 0;
+}
+
+static int spapr_pci_ddw_reset(sPAPRPHBState *sphb)
+{
+ return 0;
+}
+
static void spapr_phb_class_init(ObjectClass *klass, void *data)
{
PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass);
@@ -795,6 +832,10 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data)
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
dc->cannot_instantiate_with_device_add_yet = false;
spc->finish_realize = spapr_phb_finish_realize;
+ spc->ddw_query = spapr_pci_ddw_query;
+ spc->ddw_create = spapr_pci_ddw_create;
+ spc->ddw_remove = spapr_pci_ddw_remove;
+ spc->ddw_reset = spapr_pci_ddw_reset;
}
static const TypeInfo spapr_phb_info = {
@@ -878,6 +919,14 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb,
uint32_t interrupt_map_mask[] = {
cpu_to_be32(b_ddddd(-1)|b_fff(0)), 0x0, 0x0, cpu_to_be32(-1)};
uint32_t interrupt_map[PCI_SLOT_MAX * PCI_NUM_PINS][7];
+ uint32_t ddw_applicable[] = {
+ RTAS_IBM_QUERY_PE_DMA_WINDOW,
+ RTAS_IBM_CREATE_PE_DMA_WINDOW,
+ RTAS_IBM_REMOVE_PE_DMA_WINDOW
+ };
+ uint32_t ddw_extensions[] = { 1, RTAS_IBM_RESET_PE_DMA_WINDOW };
+ sPAPRPHBClass *spc = SPAPR_PCI_HOST_BRIDGE_GET_CLASS(phb);
+ QemuOpts *machine_opts = qemu_get_machine_opts();
/* Start populating the FDT */
sprintf(nodename, "pci@%" PRIx64, phb->buid);
@@ -907,6 +956,19 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb,
_FDT(fdt_setprop_cell(fdt, bus_off, "ibm,pci-config-space-type", 0x1));
_FDT(fdt_setprop_cell(fdt, bus_off, "ibm,pe-total-#msi", XICS_IRQS));
+ /* Dynamic DMA window */
+ if (qemu_opt_get_bool(machine_opts, "ddw", true) &&
+ spc->ddw_query && spc->ddw_create && spc->ddw_remove) {
+ _FDT(fdt_setprop(fdt, bus_off, "ibm,ddw-applicable", &ddw_applicable,
+ sizeof(ddw_applicable)));
+
+ if (spc->ddw_reset) {
+ /* When enabled, the guest will remove the default 32bit window */
+ _FDT(fdt_setprop(fdt, bus_off, "ibm,ddw-extensions",
+ &ddw_extensions, sizeof(ddw_extensions)));
+ }
+ }
+
/* Build the interrupt-map, this must matches what is done
* in pci_spapr_map_irq
*/
diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h
index 119d326..f494cbb 100644
--- a/include/hw/pci-host/spapr.h
+++ b/include/hw/pci-host/spapr.h
@@ -125,6 +125,9 @@ struct sPAPRPHBVFIOState {
#define SPAPR_PCI_MEM_WIN_BUS_OFFSET 0x80000000ULL
+/* Default 64bit dynamic window offset */
+#define SPAPR_PCI_TCE64_START 0x8000000000000000ULL
+
static inline qemu_irq spapr_phb_lsi_qirq(struct sPAPRPHBState *phb, int pin)
{
return xics_get_qirq(spapr->icp, phb->lsi_table[pin].irq);
--
2.0.0
^ permalink raw reply related
* [PATCH QEMU 08/12] spapr_pci_vfio: Enable DDW
From: Alexey Kardashevskiy @ 2014-07-15 9:39 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Alexey Kardashevskiy, Paul Mackerras, Gavin Shan
In-Reply-To: <1405417184-14333-1-git-send-email-aik@ozlabs.ru>
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
hw/ppc/spapr_pci_vfio.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 73 insertions(+)
diff --git a/hw/ppc/spapr_pci_vfio.c b/hw/ppc/spapr_pci_vfio.c
index d3bddf2..b72aff0 100644
--- a/hw/ppc/spapr_pci_vfio.c
+++ b/hw/ppc/spapr_pci_vfio.c
@@ -71,6 +71,75 @@ static void spapr_phb_vfio_finish_realize(sPAPRPHBState *sphb, Error **errp)
spapr_tce_get_iommu(tcet));
}
+static int spapr_pci_vfio_ddw_query(sPAPRPHBState *sphb,
+ uint32_t *windows_available,
+ uint32_t *page_size_mask)
+{
+ sPAPRPHBVFIOState *svphb = SPAPR_PCI_VFIO_HOST_BRIDGE(sphb);
+ struct vfio_iommu_spapr_tce_query query = { .argsz = sizeof(query) };
+ int ret;
+
+ ret = vfio_container_ioctl(&sphb->iommu_as, svphb->iommugroupid,
+ VFIO_IOMMU_SPAPR_TCE_QUERY, &query);
+ if (ret) {
+ return ret;
+ }
+
+ *windows_available = query.windows_available;
+ *page_size_mask = query.page_size_mask;
+
+ return ret;
+}
+
+static int spapr_pci_vfio_ddw_create(sPAPRPHBState *sphb, uint32_t page_shift,
+ uint32_t window_shift, uint32_t liobn,
+ sPAPRTCETable **ptcet)
+{
+ sPAPRPHBVFIOState *svphb = SPAPR_PCI_VFIO_HOST_BRIDGE(sphb);
+ struct vfio_iommu_spapr_tce_create create = {
+ .argsz = sizeof(create),
+ .page_shift = page_shift,
+ .window_shift = window_shift,
+ .start_addr = 0
+ };
+ int ret;
+
+ ret = vfio_container_ioctl(&sphb->iommu_as, svphb->iommugroupid,
+ VFIO_IOMMU_SPAPR_TCE_CREATE, &create);
+ if (ret) {
+ return ret;
+ }
+
+ *ptcet = spapr_tce_new_table(DEVICE(sphb), liobn, create.start_addr,
+ page_shift, 1 << (window_shift - page_shift),
+ true);
+ memory_region_add_subregion(&sphb->iommu_root, (*ptcet)->bus_offset,
+ spapr_tce_get_iommu(*ptcet));
+
+ return ret;
+}
+
+static int spapr_pci_vfio_ddw_remove(sPAPRPHBState *sphb, sPAPRTCETable *tcet)
+{
+ sPAPRPHBVFIOState *svphb = SPAPR_PCI_VFIO_HOST_BRIDGE(sphb);
+ struct vfio_iommu_spapr_tce_remove remove = {
+ .argsz = sizeof(remove),
+ .start_addr = tcet->bus_offset
+ };
+
+ return vfio_container_ioctl(&sphb->iommu_as, svphb->iommugroupid,
+ VFIO_IOMMU_SPAPR_TCE_REMOVE, &remove);
+}
+
+static int spapr_pci_vfio_ddw_reset(sPAPRPHBState *sphb)
+{
+ sPAPRPHBVFIOState *svphb = SPAPR_PCI_VFIO_HOST_BRIDGE(sphb);
+ struct vfio_iommu_spapr_tce_reset reset = { .argsz = sizeof(reset) };
+
+ return vfio_container_ioctl(&sphb->iommu_as, svphb->iommugroupid,
+ VFIO_IOMMU_SPAPR_TCE_RESET, &reset);
+}
+
static void spapr_phb_vfio_reset(DeviceState *qdev)
{
/* Do nothing */
@@ -84,6 +153,10 @@ static void spapr_phb_vfio_class_init(ObjectClass *klass, void *data)
dc->props = spapr_phb_vfio_properties;
dc->reset = spapr_phb_vfio_reset;
spc->finish_realize = spapr_phb_vfio_finish_realize;
+ spc->ddw_query = spapr_pci_vfio_ddw_query;
+ spc->ddw_create = spapr_pci_vfio_ddw_create;
+ spc->ddw_remove = spapr_pci_vfio_ddw_remove;
+ spc->ddw_reset = spapr_pci_vfio_ddw_reset;
}
static const TypeInfo spapr_phb_vfio_info = {
--
2.0.0
^ permalink raw reply related
* [PATCH QEMU 11/12] target-ppc: kvm: make use of KVM_CREATE_SPAPR_TCE_64
From: Alexey Kardashevskiy @ 2014-07-15 9:39 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Alexey Kardashevskiy, Paul Mackerras, Gavin Shan
In-Reply-To: <1405417184-14333-1-git-send-email-aik@ozlabs.ru>
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
hw/ppc/spapr_iommu.c | 7 ++++---
target-ppc/kvm.c | 47 ++++++++++++++++++++++++++++++++++++-----------
target-ppc/kvm_ppc.h | 10 +++++++---
3 files changed, 47 insertions(+), 17 deletions(-)
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index 588d442..1710595 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -113,11 +113,12 @@ static MemoryRegionIOMMUOps spapr_iommu_ops = {
static int spapr_tce_table_realize(DeviceState *dev)
{
sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev);
- uint64_t window_size = tcet->nb_table << tcet->page_shift;
- if (kvm_enabled() && !(window_size >> 32)) {
+ if (kvm_enabled()) {
tcet->table = kvmppc_create_spapr_tce(tcet->liobn,
- window_size,
+ tcet->nb_table,
+ tcet->bus_offset,
+ tcet->page_shift,
&tcet->fd,
tcet->vfio_accel);
}
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 42718f7..cfc2599 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -62,6 +62,7 @@ static int cap_booke_sregs;
static int cap_ppc_smt;
static int cap_ppc_rma;
static int cap_spapr_tce;
+static int cap_spapr_tce_64;
static int cap_spapr_multitce;
static int cap_spapr_vfio;
static int cap_hior;
@@ -101,6 +102,7 @@ int kvm_arch_init(KVMState *s)
cap_ppc_smt = kvm_check_extension(s, KVM_CAP_PPC_SMT);
cap_ppc_rma = kvm_check_extension(s, KVM_CAP_PPC_RMA);
cap_spapr_tce = kvm_check_extension(s, KVM_CAP_SPAPR_TCE);
+ cap_spapr_tce_64 = kvm_check_extension(s, KVM_CAP_SPAPR_TCE_64);
cap_spapr_multitce = kvm_check_extension(s, KVM_CAP_SPAPR_MULTITCE);
cap_spapr_vfio = false;
cap_one_reg = kvm_check_extension(s, KVM_CAP_ONE_REG);
@@ -1655,13 +1657,10 @@ bool kvmppc_spapr_use_multitce(void)
return cap_spapr_multitce;
}
-void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd,
- bool vfio_accel)
+void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_shift,
+ uint64_t bus_offset, uint32_t page_shift,
+ int *pfd, bool vfio_accel)
{
- struct kvm_create_spapr_tce args = {
- .liobn = liobn,
- .window_size = window_size,
- };
long len;
int fd;
void *table;
@@ -1674,14 +1673,40 @@ void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd,
return NULL;
}
- fd = kvm_vm_ioctl(kvm_state, KVM_CREATE_SPAPR_TCE, &args);
- if (fd < 0) {
- fprintf(stderr, "KVM: Failed to create TCE table for liobn 0x%x\n",
- liobn);
+ if (cap_spapr_tce_64) {
+ struct kvm_create_spapr_tce_64 args = {
+ .liobn = liobn,
+ .page_shift = page_shift,
+ .offset = bus_offset >> page_shift,
+ .size = window_shift,
+ .flags = 0
+ };
+ fd = kvm_vm_ioctl(kvm_state, KVM_CREATE_SPAPR_TCE_64, &args);
+ if (fd < 0) {
+ fprintf(stderr,
+ "KVM: Failed to create TCE64 table for liobn 0x%x\n",
+ liobn);
+ return NULL;
+ }
+ } else if (cap_spapr_tce) {
+ struct kvm_create_spapr_tce args = {
+ .liobn = liobn,
+ .window_size = window_shift << page_shift,
+ };
+ if (((window_shift << page_shift) != args.window_size) || bus_offset) {
+ return NULL;
+ }
+ fd = kvm_vm_ioctl(kvm_state, KVM_CREATE_SPAPR_TCE, &args);
+ if (fd < 0) {
+ fprintf(stderr, "KVM: Failed to create TCE table for liobn 0x%x\n",
+ liobn);
+ return NULL;
+ }
+ } else {
return NULL;
}
- len = (window_size / SPAPR_TCE_PAGE_SIZE) * sizeof(uint64_t);
+ len = window_shift * sizeof(uint64_t);
/* FIXME: round this up to page size */
table = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index d9516e7..154f434 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -33,8 +33,9 @@ int kvmppc_booke_watchdog_enable(PowerPCCPU *cpu);
#ifndef CONFIG_USER_ONLY
off_t kvmppc_alloc_rma(void **rma);
bool kvmppc_spapr_use_multitce(void);
-void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd,
- bool vfio_accel);
+void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_shift,
+ uint64_t bus_offset, uint32_t page_shift,
+ int *pfd, bool vfio_accel);
int kvmppc_remove_spapr_tce(void *table, int pfd, uint32_t window_size);
int kvmppc_reset_htab(int shift_hint);
uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift);
@@ -145,7 +146,10 @@ static inline bool kvmppc_spapr_use_multitce(void)
}
static inline void *kvmppc_create_spapr_tce(uint32_t liobn,
- uint32_t window_size, int *fd,
+ uint32_t window_shift,
+ uint64_t bus_offset,
+ uint32_t page_shift,
+ int *fd,
bool vfio_accel)
{
return NULL;
--
2.0.0
^ permalink raw reply related
* [PATCH QEMU 12/12] vfio: Enable in-kernel acceleration via VFIO KVM device
From: Alexey Kardashevskiy @ 2014-07-15 9:39 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Alexey Kardashevskiy, Paul Mackerras, Gavin Shan
In-Reply-To: <1405417184-14333-1-git-send-email-aik@ozlabs.ru>
TCE hypercalls (H_PUT_TCE, H_PUT_TCE_INDIRECT, H_STUFF_TCE) use a logical bus
number (LIOBN) to identify which TCE table the request is addressed to.
However VFIO kernel driver operates with IOMMU group IDs and has no idea
about which LIOBN corresponds to which group. If the host kernel supports
in-kernel acceleration for TCE calls, we have to provide the LIOBN to IOMMU
mapping information.
This makes use of a VFIO KVM device's
KVM_DEV_VFIO_GROUP_SET_SPAPR_TCE_LIOBN attribute to set the link
between LIOBN and IOMMU group.
The vfio_container_spapr_set_liobn() helper is implemented completely
in vfio.c because kvm_vfio_spapr_tce_liobn needs a group fd and
we do not want to share resources likes that outside vfio.c.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
hw/misc/vfio.c | 41 +++++++++++++++++++++++++++++++++++++++++
hw/ppc/spapr_iommu.c | 1 +
hw/ppc/spapr_pci_vfio.c | 22 ++++++++++++++++++++++
include/hw/misc/vfio.h | 5 +++++
4 files changed, 69 insertions(+)
diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
index e7b4d6e..6e9919a 100644
--- a/hw/misc/vfio.c
+++ b/hw/misc/vfio.c
@@ -4450,3 +4450,44 @@ int vfio_container_ioctl(AddressSpace *as, int32_t groupid,
return vfio_container_do_ioctl(as, groupid, req, param);
}
+
+int vfio_container_spapr_set_liobn(AddressSpace *as,
+ int32_t groupid,
+ uint64_t liobn,
+ uint64_t start_addr)
+{
+#ifdef CONFIG_KVM
+ VFIOGroup *group;
+ int ret;
+ struct kvm_vfio_spapr_tce_liobn param = {
+ .argsz = sizeof(param),
+ .liobn = liobn,
+ .start_addr = start_addr
+ };
+ struct kvm_device_attr attr = {
+ .group = KVM_DEV_VFIO_GROUP,
+ .attr = KVM_DEV_VFIO_GROUP_SET_SPAPR_TCE_LIOBN,
+ .addr = (uint64_t)(unsigned long)¶m,
+ };
+
+ if (vfio_kvm_device_fd < 0) {
+ return 0;
+ }
+
+ group = vfio_get_group(groupid, as);
+ if (!group) {
+ return -1;
+ }
+
+ param.fd = group->fd;
+ ret = ioctl(vfio_kvm_device_fd, KVM_SET_DEVICE_ATTR, &attr);
+ if (ret) {
+ error_report("vfio: failed to setup liobn for a group: %s",
+ strerror(errno));
+ }
+
+ return ret;
+#else
+ return 0;
+#endif
+}
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index 1710595..3c2a9c9 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -126,6 +126,7 @@ static int spapr_tce_table_realize(DeviceState *dev)
if (!tcet->table) {
size_t table_size = tcet->nb_table * sizeof(uint64_t);
tcet->table = g_malloc0(table_size);
+ tcet->vfio_accel = false;
}
trace_spapr_iommu_new_table(tcet->liobn, tcet, tcet->table, tcet->fd);
diff --git a/hw/ppc/spapr_pci_vfio.c b/hw/ppc/spapr_pci_vfio.c
index b72aff0..06b4e02 100644
--- a/hw/ppc/spapr_pci_vfio.c
+++ b/hw/ppc/spapr_pci_vfio.c
@@ -21,6 +21,7 @@
#include "hw/pci-host/spapr.h"
#include "linux/vfio.h"
#include "hw/misc/vfio.h"
+#include "qemu/error-report.h"
static Property spapr_phb_vfio_properties[] = {
DEFINE_PROP_INT32("iommu", sPAPRPHBVFIOState, iommugroupid, -1),
@@ -69,6 +70,17 @@ static void spapr_phb_vfio_finish_realize(sPAPRPHBState *sphb, Error **errp)
/* Register default 32bit DMA window */
memory_region_add_subregion(&sphb->iommu_root, tcet->bus_offset,
spapr_tce_get_iommu(tcet));
+
+ if (!tcet->vfio_accel) {
+ return;
+ }
+ ret = vfio_container_spapr_set_liobn(&svphb->phb.iommu_as,
+ svphb->iommugroupid,
+ tcet->liobn,
+ tcet->bus_offset);
+ if (ret) {
+ error_report("spapr-vfio: failed to create link to IOMMU");
+ }
}
static int spapr_pci_vfio_ddw_query(sPAPRPHBState *sphb,
@@ -116,6 +128,16 @@ static int spapr_pci_vfio_ddw_create(sPAPRPHBState *sphb, uint32_t page_shift,
memory_region_add_subregion(&sphb->iommu_root, (*ptcet)->bus_offset,
spapr_tce_get_iommu(*ptcet));
+ if (!(*ptcet)->vfio_accel) {
+ return 0;
+ }
+ ret = vfio_container_spapr_set_liobn(&sphb->iommu_as, svphb->iommugroupid,
+ liobn, (*ptcet)->bus_offset);
+ if (ret) {
+ error_report("spapr-vfio: failed to create link to IOMMU");
+ ret = 0;
+ }
+
return ret;
}
diff --git a/include/hw/misc/vfio.h b/include/hw/misc/vfio.h
index 0b26cd8..8f248e2 100644
--- a/include/hw/misc/vfio.h
+++ b/include/hw/misc/vfio.h
@@ -6,4 +6,9 @@
extern int vfio_container_ioctl(AddressSpace *as, int32_t groupid,
int req, void *param);
+extern int vfio_container_spapr_set_liobn(AddressSpace *as,
+ int32_t groupid,
+ uint64_t liobn,
+ uint64_t start_addr);
+
#endif
--
2.0.0
^ permalink raw reply related
* [PATCH QEMU 10/12] headers: update for KVM_CAP_SPAPR_TCE_64 and VFIO KVM device
From: Alexey Kardashevskiy @ 2014-07-15 9:39 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Alexey Kardashevskiy, Paul Mackerras, Gavin Shan
In-Reply-To: <1405417184-14333-1-git-send-email-aik@ozlabs.ru>
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
| 6 +++++-
| 9 +++++++++
| 12 ++++++++++++
| 3 +++
4 files changed, 29 insertions(+), 1 deletion(-)
--git a/linux-headers/asm-mips/kvm_para.h b/linux-headers/asm-mips/kvm_para.h
index 14fab8f..dbb2464 100644
--- a/linux-headers/asm-mips/kvm_para.h
+++ b/linux-headers/asm-mips/kvm_para.h
@@ -1 +1,5 @@
-#include <asm-generic/kvm_para.h>
+#ifndef _ASM_MIPS_KVM_PARA_H
+#define _ASM_MIPS_KVM_PARA_H
+
+
+#endif /* _ASM_MIPS_KVM_PARA_H */
--git a/linux-headers/asm-powerpc/kvm.h b/linux-headers/asm-powerpc/kvm.h
index 2bc4a94..39325bf 100644
--- a/linux-headers/asm-powerpc/kvm.h
+++ b/linux-headers/asm-powerpc/kvm.h
@@ -333,6 +333,15 @@ struct kvm_create_spapr_tce {
__u32 window_size;
};
+/* for KVM_CAP_SPAPR_TCE_64 */
+struct kvm_create_spapr_tce_64 {
+ __u64 liobn;
+ __u32 page_shift;
+ __u64 offset; /* in pages */
+ __u64 size; /* in pages */
+ __u32 flags;
+};
+
/* for KVM_ALLOCATE_RMA */
struct kvm_allocate_rma {
__u64 rma_size;
--git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index f5d2c38..fd728d3 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -758,6 +758,8 @@ struct kvm_ppc_smmu_info {
#define KVM_CAP_VM_ATTRIBUTES 101
#define KVM_CAP_ARM_PSCI_0_2 102
#define KVM_CAP_PPC_FIXUP_HCALL 103
+#define KVM_CAP_SPAPR_TCE_VFIO 104
+#define KVM_CAP_SPAPR_TCE_64 105
#ifdef KVM_CAP_IRQ_ROUTING
@@ -947,9 +949,17 @@ struct kvm_device_attr {
#define KVM_DEV_VFIO_GROUP 1
#define KVM_DEV_VFIO_GROUP_ADD 1
#define KVM_DEV_VFIO_GROUP_DEL 2
+#define KVM_DEV_VFIO_GROUP_SET_SPAPR_TCE_LIOBN 3
#define KVM_DEV_TYPE_ARM_VGIC_V2 5
#define KVM_DEV_TYPE_FLIC 6
+struct kvm_vfio_spapr_tce_liobn {
+ __u32 argsz;
+ __s32 fd;
+ __u32 liobn;
+ __u64 start_addr;
+};
+
/*
* ioctls for VM fds
*/
@@ -1031,6 +1041,8 @@ struct kvm_s390_ucas_mapping {
/* Available with KVM_CAP_PPC_ALLOC_HTAB */
#define KVM_PPC_ALLOCATE_HTAB _IOWR(KVMIO, 0xa7, __u32)
#define KVM_CREATE_SPAPR_TCE _IOW(KVMIO, 0xa8, struct kvm_create_spapr_tce)
+#define KVM_CREATE_SPAPR_TCE_64 _IOW(KVMIO, 0xa8, \
+ struct kvm_create_spapr_tce_64)
/* Available with KVM_CAP_RMA */
#define KVM_ALLOCATE_RMA _IOR(KVMIO, 0xa9, struct kvm_allocate_rma)
/* Available with KVM_CAP_PPC_HTAB_FD */
--git a/linux-headers/linux/kvm_para.h b/linux-headers/linux/kvm_para.h
index 2dff783..e61661e 100644
--- a/linux-headers/linux/kvm_para.h
+++ b/linux-headers/linux/kvm_para.h
@@ -20,6 +20,9 @@
#define KVM_HC_FEATURES 3
#define KVM_HC_PPC_MAP_MAGIC_PAGE 4
#define KVM_HC_KICK_CPU 5
+#define KVM_HC_MIPS_GET_CLOCK_FREQ 6
+#define KVM_HC_MIPS_EXIT_VM 7
+#define KVM_HC_MIPS_CONSOLE_OUTPUT 8
/*
* hypercalls use architecture specific
--
2.0.0
^ permalink raw reply related
* [PATCH QEMU 09/12] vfio: Enable DDW ioctls to VFIO IOMMU driver
From: Alexey Kardashevskiy @ 2014-07-15 9:39 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Alexey Kardashevskiy, Paul Mackerras, Gavin Shan
In-Reply-To: <1405417184-14333-1-git-send-email-aik@ozlabs.ru>
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
hw/misc/vfio.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
index 0b9eba0..e7b4d6e 100644
--- a/hw/misc/vfio.c
+++ b/hw/misc/vfio.c
@@ -4437,6 +4437,10 @@ int vfio_container_ioctl(AddressSpace *as, int32_t groupid,
switch (req) {
case VFIO_CHECK_EXTENSION:
case VFIO_IOMMU_SPAPR_TCE_GET_INFO:
+ case VFIO_IOMMU_SPAPR_TCE_QUERY:
+ case VFIO_IOMMU_SPAPR_TCE_CREATE:
+ case VFIO_IOMMU_SPAPR_TCE_REMOVE:
+ case VFIO_IOMMU_SPAPR_TCE_RESET:
break;
default:
/* Return an error on unknown requests */
--
2.0.0
^ permalink raw reply related
* Re: [PATCH] ppc/xmon: use isxdigit/isspace/isalnum from ctype.h
From: Vincent Bernat @ 2014-07-15 9:38 UTC (permalink / raw)
To: David Laight; +Cc: Paul Mackerras, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <063D6719AE5E284EB5DD2968C1650D6D17272643@AcuExch.aculab.com>
=E2=9D=A6 15 juillet 2014 08:55 GMT, David Laight <David.Laight@ACULAB.COM=
>=C2=A0:
>> Use linux/ctype.h instead of defining custom versions of
>> isxdigit/isspace/isalnum.
>
> ...
>> -#define isspace(c) (c =3D=3D ' ' || c =3D=3D '\t' || c =3D=3D 10 || c =
=3D=3D 13 || c =3D=3D 0)
>
> That is different from the version in linux/ctype.h
> Especially for 'c =3D=3D 0', but probably also vertical tab and form feed.
OK. Looking more carefully, the one in ctype.h is 9-13 (11 is vertical
tab, 12 is form feed), 32 and 160 (non-breaking space, not ASCII).
For isxdigit, this is the same. For isalnum, the one in ctype.h does
accept non ASCII chars from 223.
Also, in xmon.c, isxdigit is defined twice.
--=20
Parenthesise to avoid ambiguity.
- The Elements of Programming Style (Kernighan & Plauger)
^ permalink raw reply
* Re: Re: [PATCH v5 2/2] [BUGFIX] kprobes: Fix "Failed to find blacklist" error on ia64 and ppc64
From: Masami Hiramatsu @ 2014-07-15 10:09 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Ingo Molnar
Cc: Jeremy Fitzhardinge, linux-ia64, sparse,
Linux Kernel Mailing List, Paul Mackerras, H. Peter Anvin,
Thomas Gleixner, linux-tip-commits, anil.s.keshavamurthy,
Suzuki K. Poulose, Fenghua Yu, Arnd Bergmann, Rusty Russell,
Chris Wright, yrl.pp-manager.tt, akataria, Tony Luck, Kevin Hao,
Linus Torvalds, rdunlap, Tony Luck, dl9pf, Andrew Morton,
linuxppc-dev, David S. Miller
In-Reply-To: <1405408602.9343.75.camel@pasglop>
(2014/07/15 16:16), Benjamin Herrenschmidt wrote:
> On Tue, 2014-07-15 at 13:19 +1000, Michael Ellerman wrote:
>
>>> Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
>>> Reported-by: Tony Luck <tony.luck@gmail.com>
>>> Tested-by: Tony Luck <tony.luck@intel.com>
>>> Cc: Michael Ellerman <mpe@ellerman.id.au>
>>
>> Tested-by: Michael Ellerman <mpe@ellerman.id.au>
>> Acked-by: Michael Ellerman <mpe@ellerman.id.au> (for powerpc)
>>
>> Ben, can you take this in your tree?
>
> Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>
> That looks more like generic material. Do we have a kprobes maintainer ?
> Andrew, do you want to take this ?
Yeah, I usually use Ingo's tip tree for kprobes maintenance.
Ingo, could you pull this as urgent-for-linus patch?
> I'm happy to put it in powerpc and send it to Linus tomorrow if nobody
> cares :-)
Thank you!
--
Masami HIRAMATSU
Software Platform Research Dept. Linux Technology Research Center
Hitachi, Ltd., Yokohama Research Laboratory
E-mail: masami.hiramatsu.pt@hitachi.com
^ permalink raw reply
* [PATCH] powerpc: Move bad_stack() below the fwnmi_data_area
From: Michael Ellerman @ 2014-07-15 10:25 UTC (permalink / raw)
To: linuxppc-dev
At the moment the allmodconfig build is failing because we run out of
space between altivec_assist() at 0x5700 and the fwnmi_data_area at
0x7000.
Fixing it permanently will take some more work, but a quick fix is to
move bad_stack() below the fwnmi_data_area. That gives us just enough
room with everything enabled.
bad_stack() is called from the common exception handlers, but it's a
non-conditional branch, so we have plenty of scope to move it further
way.
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
arch/powerpc/kernel/exceptions-64s.S | 120 +++++++++++++++++------------------
1 file changed, 60 insertions(+), 60 deletions(-)
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index b859b3665be6..647d6c75ed62 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -953,66 +953,6 @@ ppc64_runlatch_on_trampoline:
b __ppc64_runlatch_on
/*
- * Here we have detected that the kernel stack pointer is bad.
- * R9 contains the saved CR, r13 points to the paca,
- * r10 contains the (bad) kernel stack pointer,
- * r11 and r12 contain the saved SRR0 and SRR1.
- * We switch to using an emergency stack, save the registers there,
- * and call kernel_bad_stack(), which panics.
- */
-bad_stack:
- ld r1,PACAEMERGSP(r13)
- subi r1,r1,64+INT_FRAME_SIZE
- std r9,_CCR(r1)
- std r10,GPR1(r1)
- std r11,_NIP(r1)
- std r12,_MSR(r1)
- mfspr r11,SPRN_DAR
- mfspr r12,SPRN_DSISR
- std r11,_DAR(r1)
- std r12,_DSISR(r1)
- mflr r10
- mfctr r11
- mfxer r12
- std r10,_LINK(r1)
- std r11,_CTR(r1)
- std r12,_XER(r1)
- SAVE_GPR(0,r1)
- SAVE_GPR(2,r1)
- ld r10,EX_R3(r3)
- std r10,GPR3(r1)
- SAVE_GPR(4,r1)
- SAVE_4GPRS(5,r1)
- ld r9,EX_R9(r3)
- ld r10,EX_R10(r3)
- SAVE_2GPRS(9,r1)
- ld r9,EX_R11(r3)
- ld r10,EX_R12(r3)
- ld r11,EX_R13(r3)
- std r9,GPR11(r1)
- std r10,GPR12(r1)
- std r11,GPR13(r1)
-BEGIN_FTR_SECTION
- ld r10,EX_CFAR(r3)
- std r10,ORIG_GPR3(r1)
-END_FTR_SECTION_IFSET(CPU_FTR_CFAR)
- SAVE_8GPRS(14,r1)
- SAVE_10GPRS(22,r1)
- lhz r12,PACA_TRAP_SAVE(r13)
- std r12,_TRAP(r1)
- addi r11,r1,INT_FRAME_SIZE
- std r11,0(r1)
- li r12,0
- std r12,0(r11)
- ld r2,PACATOC(r13)
- ld r11,exception_marker@toc(r2)
- std r12,RESULT(r1)
- std r11,STACK_FRAME_OVERHEAD-16(r1)
-1: addi r3,r1,STACK_FRAME_OVERHEAD
- bl kernel_bad_stack
- b 1b
-
-/*
* Here r13 points to the paca, r9 contains the saved CR,
* SRR0 and SRR1 are saved in r11 and r12,
* r9 - r13 are saved in paca->exgen.
@@ -1636,3 +1576,63 @@ handle_dabr_fault:
li r5,SIGSEGV
bl bad_page_fault
b ret_from_except
+
+/*
+ * Here we have detected that the kernel stack pointer is bad.
+ * R9 contains the saved CR, r13 points to the paca,
+ * r10 contains the (bad) kernel stack pointer,
+ * r11 and r12 contain the saved SRR0 and SRR1.
+ * We switch to using an emergency stack, save the registers there,
+ * and call kernel_bad_stack(), which panics.
+ */
+bad_stack:
+ ld r1,PACAEMERGSP(r13)
+ subi r1,r1,64+INT_FRAME_SIZE
+ std r9,_CCR(r1)
+ std r10,GPR1(r1)
+ std r11,_NIP(r1)
+ std r12,_MSR(r1)
+ mfspr r11,SPRN_DAR
+ mfspr r12,SPRN_DSISR
+ std r11,_DAR(r1)
+ std r12,_DSISR(r1)
+ mflr r10
+ mfctr r11
+ mfxer r12
+ std r10,_LINK(r1)
+ std r11,_CTR(r1)
+ std r12,_XER(r1)
+ SAVE_GPR(0,r1)
+ SAVE_GPR(2,r1)
+ ld r10,EX_R3(r3)
+ std r10,GPR3(r1)
+ SAVE_GPR(4,r1)
+ SAVE_4GPRS(5,r1)
+ ld r9,EX_R9(r3)
+ ld r10,EX_R10(r3)
+ SAVE_2GPRS(9,r1)
+ ld r9,EX_R11(r3)
+ ld r10,EX_R12(r3)
+ ld r11,EX_R13(r3)
+ std r9,GPR11(r1)
+ std r10,GPR12(r1)
+ std r11,GPR13(r1)
+BEGIN_FTR_SECTION
+ ld r10,EX_CFAR(r3)
+ std r10,ORIG_GPR3(r1)
+END_FTR_SECTION_IFSET(CPU_FTR_CFAR)
+ SAVE_8GPRS(14,r1)
+ SAVE_10GPRS(22,r1)
+ lhz r12,PACA_TRAP_SAVE(r13)
+ std r12,_TRAP(r1)
+ addi r11,r1,INT_FRAME_SIZE
+ std r11,0(r1)
+ li r12,0
+ std r12,0(r11)
+ ld r2,PACATOC(r13)
+ ld r11,exception_marker@toc(r2)
+ std r12,RESULT(r1)
+ std r11,STACK_FRAME_OVERHEAD-16(r1)
+1: addi r3,r1,STACK_FRAME_OVERHEAD
+ bl kernel_bad_stack
+ b 1b
--
1.9.1
^ permalink raw reply related
* [PATCH 1/3] powerpc: Update comments in irqflags.h
From: Michael Ellerman @ 2014-07-15 11:15 UTC (permalink / raw)
To: linuxppc-dev
The comment on TRACE_ENABLE_INTS is incorrect, and appears to have
always been incorrect since the code was merged. It probably came from
an original out-of-tree patch.
Replace it with something that's correct. Also propagate the message to
RECONCILE_IRQ_STATE(), because it's potentially subtle.
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
arch/powerpc/include/asm/irqflags.h | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/include/asm/irqflags.h b/arch/powerpc/include/asm/irqflags.h
index e20eb95429a8..f2149066fe5d 100644
--- a/arch/powerpc/include/asm/irqflags.h
+++ b/arch/powerpc/include/asm/irqflags.h
@@ -32,9 +32,8 @@
#endif
/*
- * Most of the CPU's IRQ-state tracing is done from assembly code; we
- * have to call a C function so call a wrapper that saves all the
- * C-clobbered registers.
+ * These are calls to C code, so the caller must be prepared for volatiles to
+ * be clobbered.
*/
#define TRACE_ENABLE_INTS TRACE_WITH_FRAME_BUFFER(trace_hardirqs_on)
#define TRACE_DISABLE_INTS TRACE_WITH_FRAME_BUFFER(trace_hardirqs_off)
@@ -42,6 +41,9 @@
/*
* This is used by assembly code to soft-disable interrupts first and
* reconcile irq state.
+ *
+ * NB: This may call C code, so the caller must be prepared for volatiles to
+ * be clobbered.
*/
#define RECONCILE_IRQ_STATE(__rA, __rB) \
lbz __rA,PACASOFTIRQEN(r13); \
--
1.9.1
^ permalink raw reply related
* [PATCH 2/3] powerpc: Document register clobbering in EXCEPTION_COMMON()
From: Michael Ellerman @ 2014-07-15 11:15 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1405422938-27608-1-git-send-email-mpe@ellerman.id.au>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
arch/powerpc/include/asm/exception-64s.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h
index 8f35cd7d59cc..066c15cd2837 100644
--- a/arch/powerpc/include/asm/exception-64s.h
+++ b/arch/powerpc/include/asm/exception-64s.h
@@ -532,6 +532,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_CTRL)
.globl label##_common; \
label##_common: \
EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \
+ /* Volatile regs are potentially clobbered here */ \
additions; \
addi r3,r1,STACK_FRAME_OVERHEAD; \
bl hdlr; \
--
1.9.1
^ permalink raw reply related
* [PATCH 3/3] powerpc: Remove misleading DISABLE_INTS
From: Michael Ellerman @ 2014-07-15 11:15 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1405422938-27608-1-git-send-email-mpe@ellerman.id.au>
DISABLE_INTS has a long and storied history, but for some time now it
has not actually disabled interrupts.
For the open-coded exception handlers, just stop using it, instead call
RECONCILE_IRQ_STATE directly. This has the benefit of removing a level
of indirection, and making it clear that r10 & r11 are used at that
point.
For the addition case we still need a macro, so rename it to clarify
what it actually does.
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
arch/powerpc/include/asm/exception-64s.h | 11 +++++++----
arch/powerpc/kernel/exceptions-64s.S | 28 ++++++++++++++--------------
2 files changed, 21 insertions(+), 18 deletions(-)
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h
index 066c15cd2837..13a63379e496 100644
--- a/arch/powerpc/include/asm/exception-64s.h
+++ b/arch/powerpc/include/asm/exception-64s.h
@@ -513,8 +513,11 @@ label##_relon_hv: \
* runlatch, etc...
*/
-/* Exception addition: Hard disable interrupts */
-#define DISABLE_INTS RECONCILE_IRQ_STATE(r10,r11)
+/*
+ * This addition reconciles our actual IRQ state with the various software
+ * flags that track it. This may call C code.
+ */
+#define ADD_RECONCILE RECONCILE_IRQ_STATE(r10,r11)
#define ADD_NVGPRS \
bl save_nvgprs
@@ -540,7 +543,7 @@ label##_common: \
#define STD_EXCEPTION_COMMON(trap, label, hdlr) \
EXCEPTION_COMMON(trap, label, hdlr, ret_from_except, \
- ADD_NVGPRS;DISABLE_INTS)
+ ADD_NVGPRS;ADD_RECONCILE)
/*
* Like STD_EXCEPTION_COMMON, but for exceptions that can occur
@@ -549,7 +552,7 @@ label##_common: \
*/
#define STD_EXCEPTION_COMMON_ASYNC(trap, label, hdlr) \
EXCEPTION_COMMON(trap, label, hdlr, ret_from_except_lite, \
- FINISH_NAP;DISABLE_INTS;RUNLATCH_ON)
+ FINISH_NAP;ADD_RECONCILE;RUNLATCH_ON)
/*
* When the idle code in power4_idle puts the CPU into NAP mode,
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index a7d36b19221d..03a54ef03049 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -1057,7 +1057,7 @@ data_access_common:
mfspr r10,SPRN_DSISR
stw r10,PACA_EXGEN+EX_DSISR(r13)
EXCEPTION_PROLOG_COMMON(0x300, PACA_EXGEN)
- DISABLE_INTS
+ RECONCILE_IRQ_STATE(r10, r11)
ld r12,_MSR(r1)
ld r3,PACA_EXGEN+EX_DAR(r13)
lwz r4,PACA_EXGEN+EX_DSISR(r13)
@@ -1073,7 +1073,7 @@ h_data_storage_common:
stw r10,PACA_EXGEN+EX_DSISR(r13)
EXCEPTION_PROLOG_COMMON(0xe00, PACA_EXGEN)
bl save_nvgprs
- DISABLE_INTS
+ RECONCILE_IRQ_STATE(r10, r11)
addi r3,r1,STACK_FRAME_OVERHEAD
bl unknown_exception
b ret_from_except
@@ -1082,7 +1082,7 @@ h_data_storage_common:
.globl instruction_access_common
instruction_access_common:
EXCEPTION_PROLOG_COMMON(0x400, PACA_EXGEN)
- DISABLE_INTS
+ RECONCILE_IRQ_STATE(r10, r11)
ld r12,_MSR(r1)
ld r3,_NIP(r1)
andis. r4,r12,0x5820
@@ -1146,7 +1146,7 @@ slb_miss_fault:
unrecov_user_slb:
EXCEPTION_PROLOG_COMMON(0x4200, PACA_EXGEN)
- DISABLE_INTS
+ RECONCILE_IRQ_STATE(r10, r11)
bl save_nvgprs
1: addi r3,r1,STACK_FRAME_OVERHEAD
bl unrecoverable_exception
@@ -1169,7 +1169,7 @@ machine_check_common:
stw r10,PACA_EXGEN+EX_DSISR(r13)
EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC)
FINISH_NAP
- DISABLE_INTS
+ RECONCILE_IRQ_STATE(r10, r11)
ld r3,PACA_EXGEN+EX_DAR(r13)
lwz r4,PACA_EXGEN+EX_DSISR(r13)
std r3,_DAR(r1)
@@ -1192,7 +1192,7 @@ alignment_common:
std r3,_DAR(r1)
std r4,_DSISR(r1)
bl save_nvgprs
- DISABLE_INTS
+ RECONCILE_IRQ_STATE(r10, r11)
addi r3,r1,STACK_FRAME_OVERHEAD
bl alignment_exception
b ret_from_except
@@ -1202,7 +1202,7 @@ alignment_common:
program_check_common:
EXCEPTION_PROLOG_COMMON(0x700, PACA_EXGEN)
bl save_nvgprs
- DISABLE_INTS
+ RECONCILE_IRQ_STATE(r10, r11)
addi r3,r1,STACK_FRAME_OVERHEAD
bl program_check_exception
b ret_from_except
@@ -1213,7 +1213,7 @@ fp_unavailable_common:
EXCEPTION_PROLOG_COMMON(0x800, PACA_EXGEN)
bne 1f /* if from user, just load it up */
bl save_nvgprs
- DISABLE_INTS
+ RECONCILE_IRQ_STATE(r10, r11)
addi r3,r1,STACK_FRAME_OVERHEAD
bl kernel_fp_unavailable_exception
BUG_OPCODE
@@ -1232,7 +1232,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_TM)
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
2: /* User process was in a transaction */
bl save_nvgprs
- DISABLE_INTS
+ RECONCILE_IRQ_STATE(r10, r11)
addi r3,r1,STACK_FRAME_OVERHEAD
bl fp_unavailable_tm
b ret_from_except
@@ -1258,7 +1258,7 @@ BEGIN_FTR_SECTION
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
2: /* User process was in a transaction */
bl save_nvgprs
- DISABLE_INTS
+ RECONCILE_IRQ_STATE(r10, r11)
addi r3,r1,STACK_FRAME_OVERHEAD
bl altivec_unavailable_tm
b ret_from_except
@@ -1267,7 +1267,7 @@ BEGIN_FTR_SECTION
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
#endif
bl save_nvgprs
- DISABLE_INTS
+ RECONCILE_IRQ_STATE(r10, r11)
addi r3,r1,STACK_FRAME_OVERHEAD
bl altivec_unavailable_exception
b ret_from_except
@@ -1292,7 +1292,7 @@ BEGIN_FTR_SECTION
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
2: /* User process was in a transaction */
bl save_nvgprs
- DISABLE_INTS
+ RECONCILE_IRQ_STATE(r10, r11)
addi r3,r1,STACK_FRAME_OVERHEAD
bl vsx_unavailable_tm
b ret_from_except
@@ -1301,7 +1301,7 @@ BEGIN_FTR_SECTION
END_FTR_SECTION_IFSET(CPU_FTR_VSX)
#endif
bl save_nvgprs
- DISABLE_INTS
+ RECONCILE_IRQ_STATE(r10, r11)
addi r3,r1,STACK_FRAME_OVERHEAD
bl vsx_unavailable_exception
b ret_from_except
@@ -1566,7 +1566,7 @@ slb_miss_realmode:
unrecov_slb:
EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB)
- DISABLE_INTS
+ RECONCILE_IRQ_STATE(r10, r11)
bl save_nvgprs
1: addi r3,r1,STACK_FRAME_OVERHEAD
bl unrecoverable_exception
--
1.9.1
^ permalink raw reply related
* Re: [PATCH 1/6] powerpc/powernv: Enable M64 aperatus for PHB3
From: Gavin Shan @ 2014-07-15 11:35 UTC (permalink / raw)
To: Wei Yang; +Cc: linuxppc-dev, Guo Chao
In-Reply-To: <20140715025525.GA13292@richard>
On Tue, Jul 15, 2014 at 10:55:25AM +0800, Wei Yang wrote:
>On Thu, Jul 10, 2014 at 09:53:41PM +0800, Guo Chao wrote:
>>This patch enable M64 aperatus for PHB3.
>>
>>We already had platform hook (ppc_md.pcibios_window_alignment) to affect
>>the PCI resource assignment done in PCI core so that each PE's M32 resource
>>was built on basis of M32 segment size. Similarly, we're using that for
>>M64 assignment on basis of M64 segment size.
>>
>> * We're using last M64 BAR to cover M64 aperatus, and it's shared by all
>> 256 PEs.
>> * We don't support P7IOC yet. However, some function callbacks are added
>> to (struct pnv_phb) so that we can reuse them on P7IOC in future.
>> * PE, corresponding to PCI bus with large M64 BAR device attached, might
>> span multiple M64 segments. We introduce "compound" PE to cover the case.
>> The compound PE is a list of PEs and the master PE is used as before.
>> The slave PEs are just for MMIO isolation.
>>
>>Signed-off-by: Guo Chao <yan@linux.vnet.ibm.com>
>>---
>> arch/powerpc/include/asm/opal.h | 8 +-
>> arch/powerpc/platforms/powernv/pci-ioda.c | 284 ++++++++++++++++++++++++++++--
>> arch/powerpc/platforms/powernv/pci.h | 20 +++
>> 3 files changed, 297 insertions(+), 15 deletions(-)
>>
>>diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
>>index 0da1dbd..ae885cc 100644
>>--- a/arch/powerpc/include/asm/opal.h
>>+++ b/arch/powerpc/include/asm/opal.h
>>@@ -340,6 +340,12 @@ enum OpalMveEnableAction {
>> OPAL_ENABLE_MVE = 1
>> };
>>
>>+enum OpalM64EnableAction {
>>+ OPAL_DISABLE_M64 = 0,
>>+ OPAL_ENABLE_M64_SPLIT = 1,
>>+ OPAL_ENABLE_M64_NON_SPLIT = 2
>>+};
>>+
>> enum OpalPciResetScope {
>> OPAL_PHB_COMPLETE = 1, OPAL_PCI_LINK = 2, OPAL_PHB_ERROR = 3,
>> OPAL_PCI_HOT_RESET = 4, OPAL_PCI_FUNDAMENTAL_RESET = 5,
>>@@ -768,7 +774,7 @@ int64_t opal_pci_set_phb_mem_window(uint64_t phb_id, uint16_t window_type,
>> uint16_t window_num,
>> uint64_t starting_real_address,
>> uint64_t starting_pci_address,
>>- uint16_t segment_size);
>>+ uint64_t size);
>> int64_t opal_pci_map_pe_mmio_window(uint64_t phb_id, uint16_t pe_number,
>> uint16_t window_type, uint16_t window_num,
>> uint16_t segment_num);
>>diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
>>index de19ede..851e615 100644
>>--- a/arch/powerpc/platforms/powernv/pci-ioda.c
>>+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
>>@@ -36,6 +36,7 @@
>> #include <asm/tce.h>
>> #include <asm/xics.h>
>> #include <asm/debug.h>
>>+#include <asm/firmware.h>
>>
>> #include "powernv.h"
>> #include "pci.h"
>>@@ -82,6 +83,12 @@ static inline void __raw_rm_writeq(u64 val, volatile void __iomem *paddr)
>> : : "r" (val), "r" (paddr) : "memory");
>> }
>>
>>+static inline bool pnv_pci_is_mem_pref_64(unsigned long flags)
>>+{
>>+ return ((flags & (IORESOURCE_MEM_64 | IORESOURCE_PREFETCH)) ==
>>+ (IORESOURCE_MEM_64 | IORESOURCE_PREFETCH));
>>+}
>>+
>> static int pnv_ioda_alloc_pe(struct pnv_phb *phb)
>> {
>> unsigned long pe;
>>@@ -106,6 +113,243 @@ static void pnv_ioda_free_pe(struct pnv_phb *phb, int pe)
>> clear_bit(pe, phb->ioda.pe_alloc);
>> }
>>
>>+/* The default M64 BAR is shared by all PEs */
>>+static int pnv_ioda2_init_m64(struct pnv_phb *phb)
>>+{
>>+ const char *desc;
>>+ struct resource *r;
>>+ s64 rc;
>>+
>>+ /* Configure the default M64 BAR */
>>+ rc = opal_pci_set_phb_mem_window(phb->opal_id,
>>+ OPAL_M64_WINDOW_TYPE,
>>+ phb->ioda.m64_bar_idx,
>>+ phb->ioda.m64_base,
>>+ 0, /* unused */
>>+ phb->ioda.m64_size);
>>+ if (rc != OPAL_SUCCESS) {
>>+ desc = "configuring";
>>+ goto fail;
>>+ }
>>+
>>+ /* Enable the default M64 BAR */
>>+ rc = opal_pci_phb_mmio_enable(phb->opal_id,
>>+ OPAL_M64_WINDOW_TYPE,
>>+ phb->ioda.m64_bar_idx,
>>+ OPAL_ENABLE_M64_SPLIT);
>>+ if (rc != OPAL_SUCCESS) {
>>+ desc = "enabling";
>>+ goto fail;
>>+ }
>>+
>>+ /* Mark the M64 BAR assigned */
>>+ set_bit(phb->ioda.m64_bar_idx, &phb->ioda.m64_bar_alloc);
>>+
>>+ /*
>>+ * Strip off the segment used by the reserved PE, which is
>>+ * expected to be 0 or last one of PE capabicity.
>>+ */
>>+ r = &phb->hose->mem_resources[1];
>>+ if (phb->ioda.reserved_pe == 0)
>>+ r->start += phb->ioda.m64_segsize;
>>+ else if (phb->ioda.reserved_pe == (phb->ioda.total_pe - 1))
>>+ r->end -= phb->ioda.m64_segsize;
>>+ else
>>+ pr_warn(" Cannot strip M64 segment for reserved PE#%d\n",
>>+ phb->ioda.reserved_pe);
>>+
>>+ return 0;
>>+
>>+fail:
>>+ pr_warn(" Failure %lld %s M64 BAR#%d\n",
>>+ rc, desc, phb->ioda.m64_bar_idx);
>>+ opal_pci_phb_mmio_enable(phb->opal_id,
>>+ OPAL_M64_WINDOW_TYPE,
>>+ phb->ioda.m64_bar_idx,
>>+ OPAL_DISABLE_M64);
>>+ return -EIO;
>>+}
>>+
>>+static void pnv_ioda2_alloc_m64_pe(struct pnv_phb *phb)
>>+{
>>+ resource_size_t sgsz = phb->ioda.m64_segsize;
>>+ struct pci_dev *pdev;
>>+ struct resource *r;
>>+ int base, step, i;
>>+
>>+ /*
>>+ * Root bus always has full M64 range and root port has
>>+ * M64 range used in reality. So we're checking root port
>>+ * instead of root bus.
>>+ */
>>+ list_for_each_entry(pdev, &phb->hose->bus->devices, bus_list) {
>>+ for (i = PCI_BRIDGE_RESOURCES;
>>+ i <= PCI_BRIDGE_RESOURCE_END; i++) {
>>+ r = &pdev->resource[i];
>>+ if (!r->parent ||
>>+ !pnv_pci_is_mem_pref_64(r->flags))
>>+ continue;
>>+
>>+ base = (r->start - phb->ioda.m64_base) / sgsz;
>>+ for (step = 0; step < resource_size(r) / sgsz; step++)
>>+ set_bit(base + step, phb->ioda.pe_alloc);
>>+ }
>>+ }
>>+}
>>+
>>+static int pnv_ioda2_pick_m64_pe(struct pnv_phb *phb,
>>+ struct pci_bus *bus, int all)
>>+{
>>+ resource_size_t segsz = phb->ioda.m64_segsize;
>>+ struct pci_dev *pdev;
>>+ struct resource *r;
>>+ struct pnv_ioda_pe *master_pe, *pe;
>>+ unsigned long size, *pe_alloc;
>>+ bool found;
>>+ int start, i, j;
>>+
>>+ /* Root bus shouldn't use M64 */
>>+ if (pci_is_root_bus(bus))
>>+ return IODA_INVALID_PE;
>>+
>>+ /* We support only one M64 window on each bus */
>>+ found = false;
>>+ pci_bus_for_each_resource(bus, r, i) {
>>+ if (r && r->parent &&
>>+ pnv_pci_is_mem_pref_64(r->flags)) {
>>+ found = true;
>>+ break;
>>+ }
>>+ }
>>+
>>+ /* No M64 window found ? */
>>+ if (!found)
>>+ return IODA_INVALID_PE;
>>+
>>+ /* Allocate bitmap */
>>+ size = _ALIGN_UP(phb->ioda.total_pe / 8, sizeof(unsigned long));
>>+ pe_alloc = kzalloc(size, GFP_KERNEL);
>>+ if (!pe_alloc) {
>>+ pr_warn("%s: Out of memory !\n",
>>+ __func__);
>>+ return IODA_INVALID_PE;
>>+ }
>>+
>>+ /*
>>+ * Figure out reserved PE numbers by the PE
>>+ * the its child PEs.
>>+ */
>>+ start = (r->start - phb->ioda.m64_base) / segsz;
>>+ for (i = 0; i < resource_size(r) / segsz; i++)
>>+ set_bit(start + i, pe_alloc);
>>+
>>+ if (all)
>>+ goto done;
>>+
>>+ /*
>>+ * If the PE doesn't cover all subordinate buses,
>>+ * we need subtract from reserved PEs for children.
>>+ */
>>+ list_for_each_entry(pdev, &bus->devices, bus_list) {
>>+ if (!pdev->subordinate)
>>+ continue;
>>+
>>+ pci_bus_for_each_resource(pdev->subordinate, r, i) {
>>+ if (!r || !r->parent ||
>>+ !pnv_pci_is_mem_pref_64(r->flags))
>>+ continue;
>>+
>>+ start = (r->start - phb->ioda.m64_base) / segsz;
>>+ for (j = 0; j < resource_size(r) / segsz ; j++)
>>+ clear_bit(start + j, pe_alloc);
>>+ }
>>+ }
>>+
>>+ /*
>>+ * the current bus might not own M64 window and that's all
>>+ * contributed by its child buses. For the case, we needn't
>>+ * pick M64 dependent PE#.
>>+ */
>>+ if (bitmap_empty(pe_alloc, phb->ioda.total_pe)) {
>>+ kfree(pe_alloc);
>>+ return IODA_INVALID_PE;
>>+ }
>>+
>>+ /*
>>+ * Figure out the master PE and put all slave PEs to master
>>+ * PE's list to form compound PE.
>>+ */
>>+done:
>>+ master_pe = NULL;
>>+ i = -1;
>>+ while ((i = find_next_bit(pe_alloc, phb->ioda.total_pe, i + 1)) <
>>+ phb->ioda.total_pe) {
>>+ pe = &phb->ioda.pe_array[i];
>>+ pe->phb = phb;
>>+ pe->pe_number = i;
>>+
>>+ if (!master_pe) {
>>+ pe->flags |= PNV_IODA_PE_MASTER;
>>+ INIT_LIST_HEAD(&pe->slaves);
>>+ master_pe = pe;
>>+ } else {
>>+ pe->flags |= PNV_IODA_PE_SLAVE;
>>+ pe->master = master_pe;
>>+ list_add_tail(&pe->list, &master_pe->slaves);
>>+ }
>>+ }
>>+
>>+ kfree(pe_alloc);
>>+ return master_pe->pe_number;
>>+}
>>+
>>+static void __init pnv_ioda_parse_m64_window(struct pnv_phb *phb)
>>+{
>>+ struct pci_controller *hose = phb->hose;
>>+ struct device_node *dn = hose->dn;
>>+ struct resource *res;
>>+ const u32 *r;
>>+ u64 pci_addr;
>>+
>>+ if (!firmware_has_feature(FW_FEATURE_OPALv3)) {
>>+ pr_info(" Firmware too old to support M64 window\n");
>>+ return;
>>+ }
>>+
>>+ r = of_get_property(dn, "ibm,opal-m64-window", NULL);
>>+ if (!r) {
>>+ pr_info(" No <ibm,opal-m64-window> on %s\n",
>>+ dn->full_name);
>>+ return;
>>+ }
>>+
>>+ /* FIXME: Support M64 for P7IOC */
>>+ if (phb->type != PNV_PHB_IODA2) {
>>+ pr_info(" Not support M64 window\n");
>>+ return;
>>+ }
>>+
>>+ res = &hose->mem_resources[1];
>>+ res->start = of_translate_address(dn, r + 2);
>>+ res->end = res->start + of_read_number(r + 4, 2) - 1;
>>+ res->flags = (IORESOURCE_MEM | IORESOURCE_MEM_64 | IORESOURCE_PREFETCH);
>>+ pci_addr = of_read_number(r, 2);
>>+ hose->mem_offset[1] = res->start - pci_addr;
>>+
>>+ phb->ioda.m64_size = resource_size(res);
>>+ phb->ioda.m64_segsize = phb->ioda.m64_size / phb->ioda.total_pe;
>>+ phb->ioda.m64_base = pci_addr;
>>+
>>+ /* Use last M64 BAR to cover M64 window */
>>+ phb->ioda.m64_bar_idx = 15;
>>+ phb->init_m64 = pnv_ioda2_init_m64;
>>+ phb->alloc_m64_pe = pnv_ioda2_alloc_m64_pe;
>>+ phb->pick_m64_pe = pnv_ioda2_pick_m64_pe;
>>+
>>+ pr_info(" MEM 0x%016llx..0x%016llx -> 0x%016llx Prefetchable\n",
>>+ res->start, res->end, pci_addr);
>
>In pnv_pci_init_ioda_phb(), we have following code to print the M32
>information.
>
> pr_info(" %d (%d) PE's M32: 0x%x [segment=0x%x]"
> " IO: 0x%x [segment=0x%x]\n",
> phb->ioda.total_pe,
> phb->ioda.reserved_pe,
> phb->ioda.m32_size, phb->ioda.m32_segsize,
> phb->ioda.io_size, phb->ioda.io_segsize);
>
>Suggest to have similar one for M64.
>
Yeah, we needn't calculate m64_segsize with (m64_size/total_PEs) :-)
>>+}
>>+
>> /* Currently those 2 are only used when MSIs are enabled, this will change
>> * but in the meantime, we need to protect them to avoid warnings
>> */
>>@@ -363,9 +607,16 @@ static void pnv_ioda_setup_bus_PE(struct pci_bus *bus, int all)
>> struct pci_controller *hose = pci_bus_to_host(bus);
>> struct pnv_phb *phb = hose->private_data;
>> struct pnv_ioda_pe *pe;
>>- int pe_num;
>>+ int pe_num = IODA_INVALID_PE;
>>+
>>+ /* Check if PE is determined by M64 */
>>+ if (phb->pick_m64_pe)
>>+ pe_num = phb->pick_m64_pe(phb, bus, all);
>>+
>>+ /* The PE number isn't pinned by M64 */
>>+ if (pe_num == IODA_INVALID_PE)
>>+ pe_num = pnv_ioda_alloc_pe(phb);
>>
>>- pe_num = pnv_ioda_alloc_pe(phb);
>> if (pe_num == IODA_INVALID_PE) {
>> pr_warning("%s: Not enough PE# available for PCI bus %04x:%02x\n",
>> __func__, pci_domain_nr(bus), bus->number);
>>@@ -441,8 +692,15 @@ static void pnv_ioda_setup_PEs(struct pci_bus *bus)
>> static void pnv_pci_ioda_setup_PEs(void)
>> {
>> struct pci_controller *hose, *tmp;
>>+ struct pnv_phb *phb;
>>
>> list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
>>+ phb = hose->private_data;
>>+
>>+ /* M64 layout might affect PE allocation */
>>+ if (phb->alloc_m64_pe)
>>+ phb->alloc_m64_pe(phb);
>>+
>> pnv_ioda_setup_PEs(hose->bus);
>> }
>> }
>>@@ -1055,9 +1313,6 @@ static void pnv_ioda_setup_pe_seg(struct pci_controller *hose,
>> index++;
>> }
>> } else if (res->flags & IORESOURCE_MEM) {
>>- /* WARNING: Assumes M32 is mem region 0 in PHB. We need to
>>- * harden that algorithm when we start supporting M64
>>- */
>> region.start = res->start -
>> hose->mem_offset[0] -
>> phb->ioda.m32_pci_base;
>>@@ -1178,7 +1433,8 @@ static resource_size_t pnv_pci_window_alignment(struct pci_bus *bus,
>> bridge = bridge->bus->self;
>> }
>>
>>- /* We need support prefetchable memory window later */
>>+ if (pnv_pci_is_mem_pref_64(type))
>>+ return phb->ioda.m64_segsize;
>> if (type & IORESOURCE_MEM)
>> return phb->ioda.m32_segsize;
>>
>>@@ -1299,6 +1555,10 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np,
>> prop32 = of_get_property(np, "ibm,opal-reserved-pe", NULL);
>> if (prop32)
>> phb->ioda.reserved_pe = be32_to_cpup(prop32);
>>+
>>+ /* Parse 64-bit MMIO range */
>>+ pnv_ioda_parse_m64_window(phb);
>>+
>> phb->ioda.m32_size = resource_size(&hose->mem_resources[0]);
>> /* FW Has already off top 64k of M32 space (MSI space) */
>> phb->ioda.m32_size += 0x10000;
>>@@ -1334,14 +1594,6 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np,
>> /* Calculate how many 32-bit TCE segments we have */
>> phb->ioda.tce32_count = phb->ioda.m32_pci_base >> 28;
>>
>>- /* Clear unusable m64 */
>>- hose->mem_resources[1].flags = 0;
>>- hose->mem_resources[1].start = 0;
>>- hose->mem_resources[1].end = 0;
>>- hose->mem_resources[2].flags = 0;
>>- hose->mem_resources[2].start = 0;
>>- hose->mem_resources[2].end = 0;
>>-
>> #if 0 /* We should really do that ... */
>> rc = opal_pci_set_phb_mem_window(opal->phb_id,
>> window_type,
>>@@ -1404,6 +1656,10 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np,
>> ioda_eeh_phb_reset(hose, EEH_RESET_FUNDAMENTAL);
>> ioda_eeh_phb_reset(hose, OPAL_DEASSERT_RESET);
>> }
>>+
>>+ /* Configure M64 window */
>>+ if (phb->init_m64 && phb->init_m64(phb))
>>+ hose->mem_resources[1].flags = 0;
>> }
>>
>> void __init pnv_pci_init_ioda2_phb(struct device_node *np)
>>diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h
>>index 676232c..def7171 100644
>>--- a/arch/powerpc/platforms/powernv/pci.h
>>+++ b/arch/powerpc/platforms/powernv/pci.h
>>@@ -21,6 +21,8 @@ enum pnv_phb_model {
>> #define PNV_IODA_PE_DEV (1 << 0) /* PE has single PCI device */
>> #define PNV_IODA_PE_BUS (1 << 1) /* PE has primary PCI bus */
>> #define PNV_IODA_PE_BUS_ALL (1 << 2) /* PE has subordinate buses */
>>+#define PNV_IODA_PE_MASTER (1 << 3) /* Master PE in compound case */
>>+#define PNV_IODA_PE_SLAVE (1 << 4) /* Slave PE in compound case */
>>
>> /* Data associated with a PE, including IOMMU tracking etc.. */
>> struct pnv_phb;
>>@@ -64,6 +66,10 @@ struct pnv_ioda_pe {
>> */
>> int mve_number;
>>
>>+ /* PEs in compound case */
>>+ struct pnv_ioda_pe *master;
>>+ struct list_head slaves;
>>+
>> /* Link in list of PE#s */
>> struct list_head dma_link;
>> struct list_head list;
>>@@ -119,6 +125,9 @@ struct pnv_phb {
>> void (*fixup_phb)(struct pci_controller *hose);
>> u32 (*bdfn_to_pe)(struct pnv_phb *phb, struct pci_bus *bus, u32 devfn);
>> void (*shutdown)(struct pnv_phb *phb);
>>+ int (*init_m64)(struct pnv_phb *phb);
>>+ void (*alloc_m64_pe)(struct pnv_phb *phb);
>>+ int (*pick_m64_pe)(struct pnv_phb *phb, struct pci_bus *bus, int all);
>>
>> union {
>> struct {
>>@@ -129,9 +138,20 @@ struct pnv_phb {
>> /* Global bridge info */
>> unsigned int total_pe;
>> unsigned int reserved_pe;
>>+
>>+ /* 32-bit MMIO window */
>> unsigned int m32_size;
>> unsigned int m32_segsize;
>> unsigned int m32_pci_base;
>>+
>>+ /* 64-bit MMIO window */
>>+ unsigned int m64_bar_idx;
>
>idx is the abbreviation of index, which will move from the beginning to the
>end for some calculation. While the m64_bar_idx in your patch is set to a
>fixed value to mark the last(15th) M64 BAR is used.
>
>My suggestion is to rename it to m64_bar_num, which we may retrieve it from
>firmware. Then we could use this value not only to mark the last M64 BAR, but
>also could be used to track the usage of M64 BARs in later.
>
We needn't retrieve it from firmware necessarily as the phb->model and phb->type
indicates the number of M64 BARs.
>>+ unsigned long m64_size;
>>+ unsigned long m64_segsize;
>>+ unsigned long m64_base;
>>+ unsigned long m64_bar_alloc;
>>+
>>+ /* IO ports */
>> unsigned int io_size;
>> unsigned int io_segsize;
>> unsigned int io_pci_base;
Thanks,
Gavin
^ permalink raw reply
* [PATCH] ppc/xmon: use isspace/isxdigit/isalnum from linux/ctype.h
From: Vincent Bernat @ 2014-07-15 11:43 UTC (permalink / raw)
To: David Laight, Benjamin Herrenschmidt, Paul Mackerras,
linuxppc-dev@lists.ozlabs.org
Cc: Vincent Bernat
In-Reply-To: <m3pph7x8pg.fsf@neo.luffy.cx>
isxdigit() macro definition is the same.
isalnum() from linux/ctype.h will accept additional latin non-ASCII
characters. This is harmless since this macro is used in scanhex() which
parses user input.
isspace() from linux/ctype.h will accept vertical tab and form feed but
not NULL. The use of this macro is modified to accept NULL as
well. Additional characters are harmless since this macro is also only
used in scanhex().
Signed-off-by: Vincent Bernat <vincent@bernat.im>
---
arch/powerpc/xmon/xmon.c | 14 ++------------
1 file changed, 2 insertions(+), 12 deletions(-)
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index d199bfa2f1fa..55d9b48774b7 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -24,6 +24,7 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/bug.h>
+#include <linux/ctype.h>
#include <asm/ptrace.h>
#include <asm/string.h>
@@ -177,14 +178,6 @@ extern void xmon_leave(void);
#define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
#endif
-#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
- || ('a' <= (c) && (c) <= 'f') \
- || ('A' <= (c) && (c) <= 'F'))
-#define isalnum(c) (('0' <= (c) && (c) <= '9') \
- || ('a' <= (c) && (c) <= 'z') \
- || ('A' <= (c) && (c) <= 'Z'))
-#define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
-
static char *help_string = "\
Commands:\n\
b show breakpoints\n\
@@ -2121,9 +2114,6 @@ static void dump_pacas(void)
}
#endif
-#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
- || ('a' <= (c) && (c) <= 'f') \
- || ('A' <= (c) && (c) <= 'F'))
static void
dump(void)
{
@@ -2526,7 +2516,7 @@ scanhex(unsigned long *vp)
int i;
for (i=0; i<63; i++) {
c = inchar();
- if (isspace(c)) {
+ if (isspace(c) || c == '\0') {
termch = c;
break;
}
--
2.0.1
^ permalink raw reply related
* [PATCH 1/3] powerpc: Add machine_early_initcall()
From: Michael Ellerman @ 2014-07-15 12:22 UTC (permalink / raw)
To: linuxppc-dev
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
arch/powerpc/include/asm/machdep.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index f92b0b54e921..5c7e74ddee4c 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -366,6 +366,7 @@ static inline void log_error(char *buf, unsigned int err_type, int fatal)
} \
__define_initcall(__machine_initcall_##mach##_##fn, id);
+#define machine_early_initcall(mach, fn) __define_machine_initcall(mach, fn, early)
#define machine_core_initcall(mach, fn) __define_machine_initcall(mach, fn, 1)
#define machine_core_initcall_sync(mach, fn) __define_machine_initcall(mach, fn, 1s)
#define machine_postcore_initcall(mach, fn) __define_machine_initcall(mach, fn, 2)
--
1.9.1
^ permalink raw reply related
* [PATCH 2/3] powerpc/powernv: Switch powernv drivers to use machine_xxx_initcall()
From: Michael Ellerman @ 2014-07-15 12:22 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1405426945-19058-1-git-send-email-mpe@ellerman.id.au>
A lot of the code in platforms/powernv is using non-machine initcalls.
That means if a kernel built with powernv support runs on another
platform, for example pseries, the initcalls will still run.
That is usually OK, because the initcalls will check for something in
the device tree or elsewhere before doing anything, so on other
platforms they will usually just return.
But it's fishy for powernv code to be running on other platforms, so
switch them all to be machine initcalls. If we want any of them to run
on other platforms in future they should move to sysdev.
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
arch/powerpc/platforms/powernv/eeh-powernv.c | 6 +-----
arch/powerpc/platforms/powernv/opal-async.c | 3 ++-
arch/powerpc/platforms/powernv/opal-lpc.c | 2 +-
arch/powerpc/platforms/powernv/opal-memory-errors.c | 3 ++-
arch/powerpc/platforms/powernv/opal-xscom.c | 2 +-
arch/powerpc/platforms/powernv/opal.c | 9 +++++----
arch/powerpc/platforms/powernv/pci.c | 3 +--
arch/powerpc/platforms/powernv/rng.c | 2 +-
8 files changed, 14 insertions(+), 16 deletions(-)
diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c
index 56a206f32f77..998bcc18a491 100644
--- a/arch/powerpc/platforms/powernv/eeh-powernv.c
+++ b/arch/powerpc/platforms/powernv/eeh-powernv.c
@@ -398,9 +398,6 @@ static int __init eeh_powernv_init(void)
{
int ret = -EINVAL;
- if (!machine_is(powernv))
- return ret;
-
ret = eeh_ops_register(&powernv_eeh_ops);
if (!ret)
pr_info("EEH: PowerNV platform initialized\n");
@@ -409,5 +406,4 @@ static int __init eeh_powernv_init(void)
return ret;
}
-
-early_initcall(eeh_powernv_init);
+machine_early_initcall(powernv, eeh_powernv_init);
diff --git a/arch/powerpc/platforms/powernv/opal-async.c b/arch/powerpc/platforms/powernv/opal-async.c
index 32e2adfa5320..e462ab947d16 100644
--- a/arch/powerpc/platforms/powernv/opal-async.c
+++ b/arch/powerpc/platforms/powernv/opal-async.c
@@ -20,6 +20,7 @@
#include <linux/wait.h>
#include <linux/gfp.h>
#include <linux/of.h>
+#include <asm/machdep.h>
#include <asm/opal.h>
#define N_ASYNC_COMPLETIONS 64
@@ -201,4 +202,4 @@ out_opal_node:
out:
return err;
}
-subsys_initcall(opal_async_comp_init);
+machine_subsys_initcall(powernv, opal_async_comp_init);
diff --git a/arch/powerpc/platforms/powernv/opal-lpc.c b/arch/powerpc/platforms/powernv/opal-lpc.c
index f04b4d8aca5a..ad4b31df779a 100644
--- a/arch/powerpc/platforms/powernv/opal-lpc.c
+++ b/arch/powerpc/platforms/powernv/opal-lpc.c
@@ -324,7 +324,7 @@ static int opal_lpc_init_debugfs(void)
rc |= opal_lpc_debugfs_create_type(root, "fw", OPAL_LPC_FW);
return rc;
}
-device_initcall(opal_lpc_init_debugfs);
+machine_device_initcall(powernv, opal_lpc_init_debugfs);
#endif /* CONFIG_DEBUG_FS */
void opal_lpc_init(void)
diff --git a/arch/powerpc/platforms/powernv/opal-memory-errors.c b/arch/powerpc/platforms/powernv/opal-memory-errors.c
index b17a34b695ef..43db2136dbff 100644
--- a/arch/powerpc/platforms/powernv/opal-memory-errors.c
+++ b/arch/powerpc/platforms/powernv/opal-memory-errors.c
@@ -27,6 +27,7 @@
#include <linux/mm.h>
#include <linux/slab.h>
+#include <asm/machdep.h>
#include <asm/opal.h>
#include <asm/cputable.h>
@@ -143,4 +144,4 @@ static int __init opal_mem_err_init(void)
}
return 0;
}
-subsys_initcall(opal_mem_err_init);
+machine_subsys_initcall(powernv, opal_mem_err_init);
diff --git a/arch/powerpc/platforms/powernv/opal-xscom.c b/arch/powerpc/platforms/powernv/opal-xscom.c
index 4cd2ea6c0dbe..7634d1c62299 100644
--- a/arch/powerpc/platforms/powernv/opal-xscom.c
+++ b/arch/powerpc/platforms/powernv/opal-xscom.c
@@ -130,4 +130,4 @@ static int opal_xscom_init(void)
scom_init(&opal_scom_controller);
return 0;
}
-arch_initcall(opal_xscom_init);
+machine_arch_initcall(powernv, opal_xscom_init);
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 199975613fe9..6ef2e5c5bc64 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -22,6 +22,8 @@
#include <linux/kobject.h>
#include <linux/delay.h>
#include <linux/memblock.h>
+
+#include <asm/machdep.h>
#include <asm/opal.h>
#include <asm/firmware.h>
#include <asm/mce.h>
@@ -200,8 +202,7 @@ static int __init opal_register_exception_handlers(void)
return 0;
}
-
-early_initcall(opal_register_exception_handlers);
+machine_early_initcall(powernv, opal_register_exception_handlers);
int opal_notifier_register(struct notifier_block *nb)
{
@@ -368,7 +369,7 @@ static int __init opal_message_init(void)
}
return 0;
}
-early_initcall(opal_message_init);
+machine_early_initcall(powernv, opal_message_init);
int opal_get_chars(uint32_t vtermno, char *buf, int count)
{
@@ -630,7 +631,7 @@ static int __init opal_init(void)
return 0;
}
-subsys_initcall(opal_init);
+machine_subsys_initcall(powernv, opal_init);
void opal_shutdown(void)
{
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c
index f91a4e5d872e..493570c2e963 100644
--- a/arch/powerpc/platforms/powernv/pci.c
+++ b/arch/powerpc/platforms/powernv/pci.c
@@ -842,5 +842,4 @@ static int __init tce_iommu_bus_notifier_init(void)
bus_register_notifier(&pci_bus_type, &tce_iommu_bus_nb);
return 0;
}
-
-subsys_initcall_sync(tce_iommu_bus_notifier_init);
+machine_subsys_initcall_sync(powernv, tce_iommu_bus_notifier_init);
diff --git a/arch/powerpc/platforms/powernv/rng.c b/arch/powerpc/platforms/powernv/rng.c
index 1cb160dc1609..80db43944afe 100644
--- a/arch/powerpc/platforms/powernv/rng.c
+++ b/arch/powerpc/platforms/powernv/rng.c
@@ -123,4 +123,4 @@ static __init int rng_init(void)
return 0;
}
-subsys_initcall(rng_init);
+machine_subsys_initcall(powernv, rng_init);
--
1.9.1
^ permalink raw reply related
* [PATCH 3/3] powerpc/pseries: Switch pseries drivers to use machine_xxx_initcall()
From: Michael Ellerman @ 2014-07-15 12:22 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1405426945-19058-1-git-send-email-mpe@ellerman.id.au>
A lot of the code in platforms/pseries is using non-machine initcalls.
That means if a kernel built with pseries support runs on another
platform, for example powernv, the initcalls will still run.
Most of these cases are OK, though sometimes only due to luck. Some were
having more effect:
* hcall_inst_init
- Checking FW_FEATURE_LPAR which is set on ps3 & celleb.
* mobility_sysfs_init
- created sysfs files unconditionally
- but no effect due to ENOSYS from rtas_ibm_suspend_me()
* apo_pm_init
- created sysfs, allows write
- nothing checks the value written to though
* alloc_dispatch_log_kmem_cache
- creating kmem_cache on non-pseries machines
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
arch/powerpc/platforms/pseries/dtl.c | 3 ++-
arch/powerpc/platforms/pseries/eeh_pseries.c | 8 ++------
arch/powerpc/platforms/pseries/hvCall_inst.c | 2 +-
arch/powerpc/platforms/pseries/mobility.c | 3 ++-
arch/powerpc/platforms/pseries/msi.c | 3 +--
arch/powerpc/platforms/pseries/power.c | 5 +++--
arch/powerpc/platforms/pseries/ras.c | 2 +-
arch/powerpc/platforms/pseries/reconfig.c | 5 +----
arch/powerpc/platforms/pseries/rng.c | 2 +-
arch/powerpc/platforms/pseries/setup.c | 2 +-
arch/powerpc/platforms/pseries/suspend.c | 5 ++---
11 files changed, 17 insertions(+), 23 deletions(-)
diff --git a/arch/powerpc/platforms/pseries/dtl.c b/arch/powerpc/platforms/pseries/dtl.c
index 7d61498e45c0..1062f71f5a85 100644
--- a/arch/powerpc/platforms/pseries/dtl.c
+++ b/arch/powerpc/platforms/pseries/dtl.c
@@ -29,6 +29,7 @@
#include <asm/lppaca.h>
#include <asm/debug.h>
#include <asm/plpar_wrappers.h>
+#include <asm/machdep.h>
struct dtl {
struct dtl_entry *buf;
@@ -391,4 +392,4 @@ err_remove_dir:
err:
return rc;
}
-arch_initcall(dtl_init);
+machine_arch_initcall(pseries, dtl_init);
diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c
index 0bec0c02c5e7..476a5d8b0b36 100644
--- a/arch/powerpc/platforms/pseries/eeh_pseries.c
+++ b/arch/powerpc/platforms/pseries/eeh_pseries.c
@@ -743,10 +743,7 @@ static struct eeh_ops pseries_eeh_ops = {
*/
static int __init eeh_pseries_init(void)
{
- int ret = -EINVAL;
-
- if (!machine_is(pseries))
- return ret;
+ int ret;
ret = eeh_ops_register(&pseries_eeh_ops);
if (!ret)
@@ -757,5 +754,4 @@ static int __init eeh_pseries_init(void)
return ret;
}
-
-early_initcall(eeh_pseries_init);
+machine_early_initcall(pseries, eeh_pseries_init);
diff --git a/arch/powerpc/platforms/pseries/hvCall_inst.c b/arch/powerpc/platforms/pseries/hvCall_inst.c
index cf4e7736e4f1..19f15310facf 100644
--- a/arch/powerpc/platforms/pseries/hvCall_inst.c
+++ b/arch/powerpc/platforms/pseries/hvCall_inst.c
@@ -162,4 +162,4 @@ static int __init hcall_inst_init(void)
return 0;
}
-__initcall(hcall_inst_init);
+machine_device_initcall(pseries, hcall_inst_init);
diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c
index bde7ebad3949..d146fef038b8 100644
--- a/arch/powerpc/platforms/pseries/mobility.c
+++ b/arch/powerpc/platforms/pseries/mobility.c
@@ -18,6 +18,7 @@
#include <linux/delay.h>
#include <linux/slab.h>
+#include <asm/machdep.h>
#include <asm/rtas.h>
#include "pseries.h"
@@ -362,4 +363,4 @@ static int __init mobility_sysfs_init(void)
return rc;
}
-device_initcall(mobility_sysfs_init);
+machine_device_initcall(pseries, mobility_sysfs_init);
diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c
index 0c882e83c4ce..b3486dd041df 100644
--- a/arch/powerpc/platforms/pseries/msi.c
+++ b/arch/powerpc/platforms/pseries/msi.c
@@ -532,5 +532,4 @@ static int rtas_msi_init(void)
return 0;
}
-arch_initcall(rtas_msi_init);
-
+machine_arch_initcall(pseries, rtas_msi_init);
diff --git a/arch/powerpc/platforms/pseries/power.c b/arch/powerpc/platforms/pseries/power.c
index 6d6266236446..c26eadde434c 100644
--- a/arch/powerpc/platforms/pseries/power.c
+++ b/arch/powerpc/platforms/pseries/power.c
@@ -25,6 +25,7 @@
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/init.h>
+#include <asm/machdep.h>
unsigned long rtas_poweron_auto; /* default and normal state is 0 */
@@ -71,11 +72,11 @@ static int __init pm_init(void)
return -ENOMEM;
return sysfs_create_group(power_kobj, &attr_group);
}
-core_initcall(pm_init);
+machine_core_initcall(pseries, pm_init);
#else
static int __init apo_pm_init(void)
{
return (sysfs_create_file(power_kobj, &auto_poweron_attr.attr));
}
-__initcall(apo_pm_init);
+machine_device_initcall(pseries, apo_pm_init);
#endif
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
index 9c5778e6ed4b..dff05b9eb946 100644
--- a/arch/powerpc/platforms/pseries/ras.c
+++ b/arch/powerpc/platforms/pseries/ras.c
@@ -71,7 +71,7 @@ static int __init init_ras_IRQ(void)
return 0;
}
-subsys_initcall(init_ras_IRQ);
+machine_subsys_initcall(pseries, init_ras_IRQ);
#define EPOW_SHUTDOWN_NORMAL 1
#define EPOW_SHUTDOWN_ON_UPS 2
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index 0435bb65d0aa..982165955c40 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -445,13 +445,10 @@ static int proc_ppc64_create_ofdt(void)
{
struct proc_dir_entry *ent;
- if (!machine_is(pseries))
- return 0;
-
ent = proc_create("powerpc/ofdt", S_IWUSR, NULL, &ofdt_fops);
if (ent)
proc_set_size(ent, 0);
return 0;
}
-__initcall(proc_ppc64_create_ofdt);
+machine_device_initcall(pseries, proc_ppc64_create_ofdt);
diff --git a/arch/powerpc/platforms/pseries/rng.c b/arch/powerpc/platforms/pseries/rng.c
index 72a102758d4e..e09608770909 100644
--- a/arch/powerpc/platforms/pseries/rng.c
+++ b/arch/powerpc/platforms/pseries/rng.c
@@ -42,4 +42,4 @@ static __init int rng_init(void)
return 0;
}
-subsys_initcall(rng_init);
+machine_subsys_initcall(pseries, rng_init);
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index f2f40e64658f..cfe8a6389a51 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -351,7 +351,7 @@ static int alloc_dispatch_log_kmem_cache(void)
return alloc_dispatch_logs();
}
-early_initcall(alloc_dispatch_log_kmem_cache);
+machine_early_initcall(pseries, alloc_dispatch_log_kmem_cache);
static void pseries_lpar_idle(void)
{
diff --git a/arch/powerpc/platforms/pseries/suspend.c b/arch/powerpc/platforms/pseries/suspend.c
index b87b97849d4c..e76aefae2aa2 100644
--- a/arch/powerpc/platforms/pseries/suspend.c
+++ b/arch/powerpc/platforms/pseries/suspend.c
@@ -265,7 +265,7 @@ static int __init pseries_suspend_init(void)
{
int rc;
- if (!machine_is(pseries) || !firmware_has_feature(FW_FEATURE_LPAR))
+ if (!firmware_has_feature(FW_FEATURE_LPAR))
return 0;
suspend_data.token = rtas_token("ibm,suspend-me");
@@ -280,5 +280,4 @@ static int __init pseries_suspend_init(void)
suspend_set_ops(&pseries_suspend_ops);
return 0;
}
-
-__initcall(pseries_suspend_init);
+machine_device_initcall(pseries, pseries_suspend_init);
--
1.9.1
^ permalink raw reply related
* Re: bit fields && data tearing
From: Peter Hurley @ 2014-07-15 13:54 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Oleg Nesterov
Cc: Jakub Jelinek, linux-kernel, Paul Mackerras, Dan,
Paul E. McKenney, linuxppc-dev, Miroslav Franc, Richard Henderson
In-Reply-To: <1405290324.20996.71.camel@pasglop>
On 07/13/2014 06:25 PM, Benjamin Herrenschmidt wrote:
> On Sun, 2014-07-13 at 09:15 -0400, Peter Hurley wrote:
>>
>> I'm not sure I understand your point here, Ben.
>>
>> Suppose that two different spinlocks are used independently to
>> protect r-m-w access to adjacent data. In Oleg's example,
>> suppose spinlock 1 is used for access to the bitfield and
>> spinlock 2 is used for access to freeze_stop.
>>
>> What would prevent an accidental write to freeze_stop from the
>> kt_1 thread?
>
> My point was to be weary of bitfields in general because access
> to them is always R-M-W, never atomic and that seem to escape
> people regularily :-) (Among other problems such as endian etc...)
>
> As for Oleg's example, it *should* have worked because the bitfield and
> the adjacent freeze_stop should have been accessed using load/stores
> that don't actually overlap, but the compiler bug causes the bitfield
> access to not properly use the basic type of the bitfield, but escalate
> to a full 64-bit R-M-W instead, thus incorrectly R-M-W'ing the field
> next door.
Yeah, ok, so just a generic heads-up about non-atomicity of bitfields,
and not something specific to Oleg's example. Thanks.
Jonathan Corbet wrote a LWN article about this back in 2012:
http://lwn.net/Articles/478657/
I guess it's fixed in gcc 4.8, but too bad there's not a workaround for
earlier compilers (akin to -fstrict_volatile_bitfields without requiring
the volatile keyword).
Regards,
Peter Hurley
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox