hw/pci-host/astro: Fix boot for C3700 machine

Apply the "32-bit PCI addressing on 40-bit Runway" as the default
iommu transformation.  This allows PCI devices to dma PDC memory.

Signed-off-by: Helge Deller <deller@gmx.de>
Acked-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Helge Deller 2023-11-09 18:12:20 +01:00 committed by Richard Henderson
parent fa71b4f84f
commit 8066102df1
2 changed files with 33 additions and 42 deletions

View File

@ -32,6 +32,7 @@
#include "hw/pci-host/astro.h"
#include "hw/hppa/hppa_hardware.h"
#include "migration/vmstate.h"
#include "target/hppa/cpu.h"
#include "trace.h"
#include "qom/object.h"
@ -268,22 +269,6 @@ static const MemoryRegionOps elroy_config_addr_ops = {
};
/*
* A subroutine of astro_translate_iommu that builds an IOMMUTLBEntry using the
* given translated address and mask.
*/
static bool make_iommu_tlbe(hwaddr addr, hwaddr taddr, hwaddr mask,
IOMMUTLBEntry *ret)
{
hwaddr tce_mask = ~((1ull << 12) - 1);
ret->target_as = &address_space_memory;
ret->iova = addr & tce_mask;
ret->translated_addr = taddr & tce_mask;
ret->addr_mask = ~tce_mask;
ret->perm = IOMMU_RW;
return true;
}
/* Handle PCI-to-system address translation. */
static IOMMUTLBEntry astro_translate_iommu(IOMMUMemoryRegion *iommu,
hwaddr addr,
@ -291,53 +276,59 @@ static IOMMUTLBEntry astro_translate_iommu(IOMMUMemoryRegion *iommu,
int iommu_idx)
{
AstroState *s = container_of(iommu, AstroState, iommu);
IOMMUTLBEntry ret = {
.target_as = &address_space_memory,
.iova = addr,
.translated_addr = 0,
.addr_mask = ~(hwaddr)0,
.perm = IOMMU_NONE,
};
hwaddr pdir_ptr, index, a, ibase;
hwaddr pdir_ptr, index, ibase;
hwaddr addr_mask = 0xfff; /* 4k translation */
uint64_t entry;
#define IOVP_SHIFT 12 /* equals PAGE_SHIFT */
#define PDIR_INDEX(iovp) ((iovp) >> IOVP_SHIFT)
#define IOVP_MASK PAGE_MASK
#define SBA_PDIR_VALID_BIT 0x8000000000000000ULL
addr &= ~addr_mask;
/*
* Default translation: "32-bit PCI Addressing on 40-bit Runway".
* For addresses in the 32-bit memory address range ... and then
* language which not-coincidentally matches the PSW.W=0 mapping.
*/
if (addr <= UINT32_MAX) {
entry = hppa_abs_to_phys_pa2_w0(addr);
} else {
entry = addr;
}
/* "range enable" flag cleared? */
if ((s->tlb_ibase & 1) == 0) {
make_iommu_tlbe(addr, addr, addr_mask, &ret);
return ret;
goto skip;
}
a = addr;
ibase = s->tlb_ibase & ~1ULL;
if ((a & s->tlb_imask) != ibase) {
if ((addr & s->tlb_imask) != ibase) {
/* do not translate this one! */
make_iommu_tlbe(addr, addr, addr_mask, &ret);
return ret;
goto skip;
}
index = PDIR_INDEX(a);
index = PDIR_INDEX(addr);
pdir_ptr = s->tlb_pdir_base + index * sizeof(entry);
entry = ldq_le_phys(&address_space_memory, pdir_ptr);
if (!(entry & SBA_PDIR_VALID_BIT)) { /* I/O PDIR entry valid ? */
g_assert_not_reached();
goto failure;
/* failure */
return (IOMMUTLBEntry) { .perm = IOMMU_NONE };
}
entry &= ~SBA_PDIR_VALID_BIT;
entry >>= IOVP_SHIFT;
entry <<= 12;
entry |= addr & 0xfff;
make_iommu_tlbe(addr, entry, addr_mask, &ret);
goto success;
failure:
ret = (IOMMUTLBEntry) { .perm = IOMMU_NONE };
success:
return ret;
skip:
return (IOMMUTLBEntry) {
.target_as = &address_space_memory,
.iova = addr,
.translated_addr = entry,
.addr_mask = addr_mask,
.perm = IOMMU_RW,
};
}
static AddressSpace *elroy_pcihost_set_iommu(PCIBus *bus, void *opaque,

View File

@ -29,7 +29,7 @@ pci_ss.add(when: 'CONFIG_MV64361', if_true: files('mv64361.c'))
pci_ss.add(when: 'CONFIG_VERSATILE_PCI', if_true: files('versatile.c'))
# HPPA devices
pci_ss.add(when: 'CONFIG_ASTRO', if_true: files('astro.c'))
specific_ss.add(when: 'CONFIG_ASTRO', if_true: files('astro.c'))
pci_ss.add(when: 'CONFIG_DINO', if_true: files('dino.c'))
system_ss.add_all(when: 'CONFIG_PCI', if_true: pci_ss)