diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2019-03-12 10:15:00 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2019-03-12 10:15:00 +0000 |
commit | bc76b7148993269608c19fd3f2fc6ed3e22bf838 (patch) | |
tree | f395ace7347fba72d7d1a09bcee50142571a9724 /hw/ppc/spapr_iommu.c | |
parent | 377b155bde451d5ac545fbdcdfbf6ca17a4228f5 (diff) | |
parent | 013002f0fbf62545c0f5ea4c5c2d554a85919647 (diff) |
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-4.0-20190312' into staging
ppc patch queue for 2019-03-10
This pull requests supersedes ppc-for-4.0-20190310. Changes are:
* Fixed a bunch of minor style problems
* Suppressed warnings about Spectre/Meltdown mitigations with TCG
* Added one more patch, a preliminary fix towards the not-quite-ready
support for NVLink VFIO passthrough.
This is a final pull request before the 4.0 soft freeze. Changes
include:
* A Great Renaming to use camel case properly in spapr code
* Optimization of some vector instructions
* Support for POWER9 cpus in the powernv machine
* Fixes a regression from the last pull request in handling VSX
instructions with mixed operands from the FPR and VMX parts of the
register array
* Optimization hack to avoid scanning all the (empty) entries on a
new IOMMU window
* Add FSL I2C controller model for E500
* Support for KVM acceleration of the H_PAGE_INIT hypercall on spapr
* Update u-boot image for E500
* Enable Specre/Meltdown mitigations by default on the new machine type
* Enable large decrementer support for POWER9
# gpg: Signature made Tue 12 Mar 2019 08:14:51 GMT
# gpg: using RSA key 75F46586AE61A66CC44E87DC6C38CACA20D9B392
# gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>" [full]
# gpg: aka "David Gibson (Red Hat) <dgibson@redhat.com>" [full]
# gpg: aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>" [full]
# gpg: aka "David Gibson (kernel.org) <dwg@kernel.org>" [unknown]
# Primary key fingerprint: 75F4 6586 AE61 A66C C44E 87DC 6C38 CACA 20D9 B392
* remotes/dgibson/tags/ppc-for-4.0-20190312: (62 commits)
vfio: Make vfio_get_region_info_cap public
Suppress test warnings about missing Spectre/Meltdown mitigations with TCG
spapr: Use CamelCase properly
target/ppc: Optimize x[sv]xsigdp using deposit_i64()
target/ppc: Optimize xviexpdp() using deposit_i64()
target/ppc: add HV support for POWER9
ppc/pnv: add a "ibm,opal/power-mgt" device tree node on POWER9
ppc/pnv: add more dummy XSCOM addresses
ppc/pnv: activate XSCOM tests for POWER9
ppc/pnv: POWER9 XSCOM quad support
ppc/pnv: extend XSCOM core support for POWER9
ppc/pnv: add a OCC model for POWER9
ppc/pnv: add a OCC model class
ppc/pnv: add SerIRQ routing registers
ppc/pnv: add a LPC Controller model for POWER9
ppc/pnv: add a 'dt_isa_nodename' to the chip
ppc/pnv: add a LPC Controller class model
ppc/pnv: lpc: fix OPB address ranges
ppc/pnv: add a PSI bridge model for POWER9
ppc/pnv: add a PSI bridge class model
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/ppc/spapr_iommu.c')
-rw-r--r-- | hw/ppc/spapr_iommu.c | 107 |
1 files changed, 69 insertions, 38 deletions
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c index 37e98f9321..5aff4d5a05 100644 --- a/hw/ppc/spapr_iommu.c +++ b/hw/ppc/spapr_iommu.c @@ -32,7 +32,7 @@ #include <libfdt.h> -enum sPAPRTCEAccess { +enum SpaprTceAccess { SPAPR_TCE_FAULT = 0, SPAPR_TCE_RO = 1, SPAPR_TCE_WO = 2, @@ -42,11 +42,11 @@ enum sPAPRTCEAccess { #define IOMMU_PAGE_SIZE(shift) (1ULL << (shift)) #define IOMMU_PAGE_MASK(shift) (~(IOMMU_PAGE_SIZE(shift) - 1)) -static QLIST_HEAD(, sPAPRTCETable) spapr_tce_tables; +static QLIST_HEAD(, SpaprTceTable) spapr_tce_tables; -sPAPRTCETable *spapr_tce_find_by_liobn(target_ulong liobn) +SpaprTceTable *spapr_tce_find_by_liobn(target_ulong liobn) { - sPAPRTCETable *tcet; + SpaprTceTable *tcet; if (liobn & 0xFFFFFFFF00000000ULL) { hcall_dprintf("Request for out-of-bounds LIOBN 0x" TARGET_FMT_lx "\n", @@ -115,7 +115,7 @@ static IOMMUTLBEntry spapr_tce_translate_iommu(IOMMUMemoryRegion *iommu, IOMMUAccessFlags flag, int iommu_idx) { - sPAPRTCETable *tcet = container_of(iommu, sPAPRTCETable, iommu); + SpaprTceTable *tcet = container_of(iommu, SpaprTceTable, iommu); uint64_t tce; IOMMUTLBEntry ret = { .target_as = &address_space_memory, @@ -141,9 +141,39 @@ static IOMMUTLBEntry spapr_tce_translate_iommu(IOMMUMemoryRegion *iommu, return ret; } +static void spapr_tce_replay(IOMMUMemoryRegion *iommu_mr, IOMMUNotifier *n) +{ + MemoryRegion *mr = MEMORY_REGION(iommu_mr); + IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr); + hwaddr addr, granularity; + IOMMUTLBEntry iotlb; + SpaprTceTable *tcet = container_of(iommu_mr, SpaprTceTable, iommu); + + if (tcet->skipping_replay) { + return; + } + + granularity = memory_region_iommu_get_min_page_size(iommu_mr); + + for (addr = 0; addr < memory_region_size(mr); addr += granularity) { + iotlb = imrc->translate(iommu_mr, addr, IOMMU_NONE, n->iommu_idx); + if (iotlb.perm != IOMMU_NONE) { + n->notify(n, &iotlb); + } + + /* + * if (2^64 - MR size) < granularity, it's possible to get an + * infinite loop here. This should catch such a wraparound. + */ + if ((addr + granularity) < addr) { + break; + } + } +} + static int spapr_tce_table_pre_save(void *opaque) { - sPAPRTCETable *tcet = SPAPR_TCE_TABLE(opaque); + SpaprTceTable *tcet = SPAPR_TCE_TABLE(opaque); tcet->mig_table = tcet->table; tcet->mig_nb_table = tcet->nb_table; @@ -156,7 +186,7 @@ static int spapr_tce_table_pre_save(void *opaque) static uint64_t spapr_tce_get_min_page_size(IOMMUMemoryRegion *iommu) { - sPAPRTCETable *tcet = container_of(iommu, sPAPRTCETable, iommu); + SpaprTceTable *tcet = container_of(iommu, SpaprTceTable, iommu); return 1ULL << tcet->page_shift; } @@ -164,7 +194,7 @@ static uint64_t spapr_tce_get_min_page_size(IOMMUMemoryRegion *iommu) static int spapr_tce_get_attr(IOMMUMemoryRegion *iommu, enum IOMMUMemoryRegionAttr attr, void *data) { - sPAPRTCETable *tcet = container_of(iommu, sPAPRTCETable, iommu); + SpaprTceTable *tcet = container_of(iommu, SpaprTceTable, iommu); if (attr == IOMMU_ATTR_SPAPR_TCE_FD && kvmppc_has_cap_spapr_vfio()) { *(int *) data = tcet->fd; @@ -178,7 +208,7 @@ static void spapr_tce_notify_flag_changed(IOMMUMemoryRegion *iommu, IOMMUNotifierFlag old, IOMMUNotifierFlag new) { - struct sPAPRTCETable *tbl = container_of(iommu, sPAPRTCETable, iommu); + struct SpaprTceTable *tbl = container_of(iommu, SpaprTceTable, iommu); if (old == IOMMU_NOTIFIER_NONE && new != IOMMU_NOTIFIER_NONE) { spapr_tce_set_need_vfio(tbl, true); @@ -189,7 +219,7 @@ static void spapr_tce_notify_flag_changed(IOMMUMemoryRegion *iommu, static int spapr_tce_table_post_load(void *opaque, int version_id) { - sPAPRTCETable *tcet = SPAPR_TCE_TABLE(opaque); + SpaprTceTable *tcet = SPAPR_TCE_TABLE(opaque); uint32_t old_nb_table = tcet->nb_table; uint64_t old_bus_offset = tcet->bus_offset; uint32_t old_page_shift = tcet->page_shift; @@ -223,7 +253,7 @@ static int spapr_tce_table_post_load(void *opaque, int version_id) static bool spapr_tce_table_ex_needed(void *opaque) { - sPAPRTCETable *tcet = opaque; + SpaprTceTable *tcet = opaque; return tcet->bus_offset || tcet->page_shift != 0xC; } @@ -234,8 +264,8 @@ static const VMStateDescription vmstate_spapr_tce_table_ex = { .minimum_version_id = 1, .needed = spapr_tce_table_ex_needed, .fields = (VMStateField[]) { - VMSTATE_UINT64(bus_offset, sPAPRTCETable), - VMSTATE_UINT32(page_shift, sPAPRTCETable), + VMSTATE_UINT64(bus_offset, SpaprTceTable), + VMSTATE_UINT32(page_shift, SpaprTceTable), VMSTATE_END_OF_LIST() }, }; @@ -248,12 +278,12 @@ static const VMStateDescription vmstate_spapr_tce_table = { .post_load = spapr_tce_table_post_load, .fields = (VMStateField []) { /* Sanity check */ - VMSTATE_UINT32_EQUAL(liobn, sPAPRTCETable, NULL), + VMSTATE_UINT32_EQUAL(liobn, SpaprTceTable, NULL), /* IOMMU state */ - VMSTATE_UINT32(mig_nb_table, sPAPRTCETable), - VMSTATE_BOOL(bypass, sPAPRTCETable), - VMSTATE_VARRAY_UINT32_ALLOC(mig_table, sPAPRTCETable, mig_nb_table, 0, + VMSTATE_UINT32(mig_nb_table, SpaprTceTable), + VMSTATE_BOOL(bypass, SpaprTceTable), + VMSTATE_VARRAY_UINT32_ALLOC(mig_table, SpaprTceTable, mig_nb_table, 0, vmstate_info_uint64, uint64_t), VMSTATE_END_OF_LIST() @@ -266,7 +296,7 @@ static const VMStateDescription vmstate_spapr_tce_table = { static void spapr_tce_table_realize(DeviceState *dev, Error **errp) { - sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev); + SpaprTceTable *tcet = SPAPR_TCE_TABLE(dev); Object *tcetobj = OBJECT(tcet); gchar *tmp; @@ -288,7 +318,7 @@ static void spapr_tce_table_realize(DeviceState *dev, Error **errp) tcet); } -void spapr_tce_set_need_vfio(sPAPRTCETable *tcet, bool need_vfio) +void spapr_tce_set_need_vfio(SpaprTceTable *tcet, bool need_vfio) { size_t table_size = tcet->nb_table * sizeof(uint64_t); uint64_t *oldtable; @@ -317,9 +347,9 @@ void spapr_tce_set_need_vfio(sPAPRTCETable *tcet, bool need_vfio) tcet->fd = newfd; } -sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn) +SpaprTceTable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn) { - sPAPRTCETable *tcet; + SpaprTceTable *tcet; gchar *tmp; if (spapr_tce_find_by_liobn(liobn)) { @@ -341,7 +371,7 @@ sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn) return tcet; } -void spapr_tce_table_enable(sPAPRTCETable *tcet, +void spapr_tce_table_enable(SpaprTceTable *tcet, uint32_t page_shift, uint64_t bus_offset, uint32_t nb_table) { @@ -366,7 +396,7 @@ void spapr_tce_table_enable(sPAPRTCETable *tcet, MEMORY_REGION(&tcet->iommu)); } -void spapr_tce_table_disable(sPAPRTCETable *tcet) +void spapr_tce_table_disable(SpaprTceTable *tcet) { if (!tcet->nb_table) { return; @@ -385,7 +415,7 @@ void spapr_tce_table_disable(sPAPRTCETable *tcet) static void spapr_tce_table_unrealize(DeviceState *dev, Error **errp) { - sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev); + SpaprTceTable *tcet = SPAPR_TCE_TABLE(dev); vmstate_unregister(DEVICE(tcet), &vmstate_spapr_tce_table, tcet); @@ -394,14 +424,14 @@ static void spapr_tce_table_unrealize(DeviceState *dev, Error **errp) spapr_tce_table_disable(tcet); } -MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet) +MemoryRegion *spapr_tce_get_iommu(SpaprTceTable *tcet) { return &tcet->root; } static void spapr_tce_reset(DeviceState *dev) { - sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev); + SpaprTceTable *tcet = SPAPR_TCE_TABLE(dev); size_t table_size = tcet->nb_table * sizeof(uint64_t); if (tcet->nb_table) { @@ -409,7 +439,7 @@ static void spapr_tce_reset(DeviceState *dev) } } -static target_ulong put_tce_emu(sPAPRTCETable *tcet, target_ulong ioba, +static target_ulong put_tce_emu(SpaprTceTable *tcet, target_ulong ioba, target_ulong tce) { IOMMUTLBEntry entry; @@ -435,7 +465,7 @@ static target_ulong put_tce_emu(sPAPRTCETable *tcet, target_ulong ioba, } static target_ulong h_put_tce_indirect(PowerPCCPU *cpu, - sPAPRMachineState *spapr, + SpaprMachineState *spapr, target_ulong opcode, target_ulong *args) { int i; @@ -445,7 +475,7 @@ static target_ulong h_put_tce_indirect(PowerPCCPU *cpu, target_ulong tce_list = args[2]; target_ulong npages = args[3]; target_ulong ret = H_PARAMETER, tce = 0; - sPAPRTCETable *tcet = spapr_tce_find_by_liobn(liobn); + SpaprTceTable *tcet = spapr_tce_find_by_liobn(liobn); CPUState *cs = CPU(cpu); hwaddr page_mask, page_size; @@ -480,7 +510,7 @@ static target_ulong h_put_tce_indirect(PowerPCCPU *cpu, return ret; } -static target_ulong h_stuff_tce(PowerPCCPU *cpu, sPAPRMachineState *spapr, +static target_ulong h_stuff_tce(PowerPCCPU *cpu, SpaprMachineState *spapr, target_ulong opcode, target_ulong *args) { int i; @@ -489,7 +519,7 @@ static target_ulong h_stuff_tce(PowerPCCPU *cpu, sPAPRMachineState *spapr, target_ulong tce_value = args[2]; target_ulong npages = args[3]; target_ulong ret = H_PARAMETER; - sPAPRTCETable *tcet = spapr_tce_find_by_liobn(liobn); + SpaprTceTable *tcet = spapr_tce_find_by_liobn(liobn); hwaddr page_mask, page_size; if (!tcet) { @@ -519,14 +549,14 @@ static target_ulong h_stuff_tce(PowerPCCPU *cpu, sPAPRMachineState *spapr, return ret; } -static target_ulong h_put_tce(PowerPCCPU *cpu, sPAPRMachineState *spapr, +static target_ulong h_put_tce(PowerPCCPU *cpu, SpaprMachineState *spapr, target_ulong opcode, target_ulong *args) { target_ulong liobn = args[0]; target_ulong ioba = args[1]; target_ulong tce = args[2]; target_ulong ret = H_PARAMETER; - sPAPRTCETable *tcet = spapr_tce_find_by_liobn(liobn); + SpaprTceTable *tcet = spapr_tce_find_by_liobn(liobn); if (tcet) { hwaddr page_mask = IOMMU_PAGE_MASK(tcet->page_shift); @@ -544,7 +574,7 @@ static target_ulong h_put_tce(PowerPCCPU *cpu, sPAPRMachineState *spapr, return ret; } -static target_ulong get_tce_emu(sPAPRTCETable *tcet, target_ulong ioba, +static target_ulong get_tce_emu(SpaprTceTable *tcet, target_ulong ioba, target_ulong *tce) { unsigned long index = (ioba - tcet->bus_offset) >> tcet->page_shift; @@ -560,14 +590,14 @@ static target_ulong get_tce_emu(sPAPRTCETable *tcet, target_ulong ioba, return H_SUCCESS; } -static target_ulong h_get_tce(PowerPCCPU *cpu, sPAPRMachineState *spapr, +static target_ulong h_get_tce(PowerPCCPU *cpu, SpaprMachineState *spapr, target_ulong opcode, target_ulong *args) { target_ulong liobn = args[0]; target_ulong ioba = args[1]; target_ulong tce = 0; target_ulong ret = H_PARAMETER; - sPAPRTCETable *tcet = spapr_tce_find_by_liobn(liobn); + SpaprTceTable *tcet = spapr_tce_find_by_liobn(liobn); if (tcet) { hwaddr page_mask = IOMMU_PAGE_MASK(tcet->page_shift); @@ -619,7 +649,7 @@ int spapr_dma_dt(void *fdt, int node_off, const char *propname, } int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname, - sPAPRTCETable *tcet) + SpaprTceTable *tcet) { if (!tcet) { return 0; @@ -650,7 +680,7 @@ static void spapr_tce_table_class_init(ObjectClass *klass, void *data) static TypeInfo spapr_tce_table_info = { .name = TYPE_SPAPR_TCE_TABLE, .parent = TYPE_DEVICE, - .instance_size = sizeof(sPAPRTCETable), + .instance_size = sizeof(SpaprTceTable), .class_init = spapr_tce_table_class_init, }; @@ -659,6 +689,7 @@ static void spapr_iommu_memory_region_class_init(ObjectClass *klass, void *data) IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass); imrc->translate = spapr_tce_translate_iommu; + imrc->replay = spapr_tce_replay; imrc->get_min_page_size = spapr_tce_get_min_page_size; imrc->notify_flag_changed = spapr_tce_notify_flag_changed; imrc->get_attr = spapr_tce_get_attr; |