Skip to content

Commit

Permalink
hw/pci-host/astro: Fix boot for C3700 machine
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
hdeller authored and rth7680 committed Nov 13, 2023
1 parent fa71b4f commit 8066102
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 42 deletions.
73 changes: 32 additions & 41 deletions hw/pci-host/astro.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -268,76 +269,66 @@ 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,
IOMMUAccessFlags flag,
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,
Expand Down
2 changes: 1 addition & 1 deletion hw/pci-host/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 8066102

Please sign in to comment.