-/* $OpenBSD: acpiiort.c,v 1.3 2021/03/15 22:56:48 patrick Exp $ */
+/* $OpenBSD: acpiiort.c,v 1.4 2021/06/25 17:41:22 patrick Exp $ */
/*
* Copyright (c) 2021 Patrick Wildt <patrick@blueri.se>
*
return dmat;
}
+void
+acpiiort_smmu_reserve_region(struct acpi_iort_node *node, uint32_t rid,
+ bus_addr_t addr, bus_size_t size)
+{
+ struct acpiiort_smmu *as;
+
+ SIMPLEQ_FOREACH(as, &acpiiort_smmu_list, as_list) {
+ if (as->as_node == node) {
+ as->as_reserve(as->as_cookie, rid, addr, size);
+ return;
+ }
+ }
+}
+
bus_dma_tag_t
acpiiort_device_map(struct aml_node *root, bus_dma_tag_t dmat)
{
-/* $OpenBSD: acpiiort.h,v 1.3 2021/03/15 22:56:48 patrick Exp $ */
+/* $OpenBSD: acpiiort.h,v 1.4 2021/06/25 17:41:22 patrick Exp $ */
/*
* Copyright (c) 2021 Patrick Wildt <patrick@blueri.se>
*
void *as_cookie;
bus_dma_tag_t (*as_map)(void *, uint32_t,
bus_dma_tag_t);
+ void (*as_reserve)(void *, uint32_t,
+ bus_addr_t, bus_size_t);
};
void acpiiort_smmu_register(struct acpiiort_smmu *);
bus_dma_tag_t acpiiort_smmu_map(struct acpi_iort_node *, uint32_t, bus_dma_tag_t);
+void acpiiort_smmu_reserve_region(struct acpi_iort_node *, uint32_t, bus_addr_t, bus_size_t);
bus_dma_tag_t acpiiort_device_map(struct aml_node *, bus_dma_tag_t);
-/* $OpenBSD: acpipci.c,v 1.29 2021/05/17 17:25:13 kettenis Exp $ */
+/* $OpenBSD: acpipci.c,v 1.30 2021/06/25 17:41:22 patrick Exp $ */
/*
* Copyright (c) 2018 Mark Kettenis
*
acpipci_probe_device_hook(void *v, struct pci_attach_args *pa)
{
struct acpipci_mcfg *am = v;
+ struct acpipci_trans *at;
struct acpi_table_header *hdr;
struct acpi_iort *iort = NULL;
struct acpi_iort_node *node;
return 0;
node = (struct acpi_iort_node *)((char *)iort + offset);
- if (node->type == ACPI_IORT_SMMU)
+ if (node->type == ACPI_IORT_SMMU) {
pa->pa_dmat = acpiiort_smmu_map(node, rid, pa->pa_dmat);
+ for (at = pa->pa_iot->bus_private; at; at = at->at_next) {
+ acpiiort_smmu_reserve_region(node, rid,
+ at->at_base, at->at_size);
+ }
+ for (at = pa->pa_memt->bus_private; at; at = at->at_next) {
+ acpiiort_smmu_reserve_region(node, rid,
+ at->at_base, at->at_size);
+ }
+ }
return 0;
}
-/* $OpenBSD: apldart.c,v 1.4 2021/05/30 15:05:32 visa Exp $ */
+/* $OpenBSD: apldart.c,v 1.5 2021/06/25 17:41:22 patrick Exp $ */
/*
* Copyright (c) 2021 Mark Kettenis <kettenis@openbsd.org>
*
};
bus_dma_tag_t apldart_map(void *, uint32_t *, bus_dma_tag_t);
+void apldart_reserve(void *, uint32_t *, bus_addr_t, bus_size_t);
int apldart_intr(void *);
void apldart_flush_tlb(struct apldart_softc *);
sc->sc_id.id_node = faa->fa_node;
sc->sc_id.id_cookie = sc;
sc->sc_id.id_map = apldart_map;
+ sc->sc_id.id_reserve = apldart_reserve;
iommu_device_register(&sc->sc_id);
}
return &sc->sc_bus_dmat;
}
+void
+apldart_reserve(void *cookie, uint32_t *cells, bus_addr_t addr, bus_size_t size)
+{
+}
+
int
apldart_intr(void *arg)
{
-/* $OpenBSD: smmu.c,v 1.16 2021/06/25 12:40:29 patrick Exp $ */
+/* $OpenBSD: smmu.c,v 1.17 2021/06/25 17:41:22 patrick Exp $ */
/*
* Copyright (c) 2008-2009,2014-2016 Dale Rahn <drahn@dalerahn.com>
* Copyright (c) 2021 Patrick Wildt <patrick@blueri.se>
/* Reserve first page (to catch NULL access) */
extent_alloc_region(dom->sd_iovamap, 0, PAGE_SIZE, EX_WAITOK);
-#if 0
- /* FIXME PCIe address space */
- {
-#if 1
- /* Reserve 8040 PCI address space */
- extent_alloc_region(dom->sd_iovamap, 0xc0000000, 0x20000000,
- EX_WAITOK);
-#endif
- }
-#endif
-
SIMPLEQ_INSERT_TAIL(&sc->sc_domains, dom, sd_list);
return dom;
}
+void
+smmu_reserve_region(void *cookie, uint32_t sid, bus_addr_t addr,
+ bus_size_t size)
+{
+ struct smmu_softc *sc = cookie;
+ struct smmu_domain *dom;
+
+ dom = smmu_domain_lookup(sc, sid);
+ if (dom == NULL)
+ return;
+
+ extent_alloc_region(dom->sd_iovamap, addr, size,
+ EX_WAITOK | EX_CONFLICTOK);
+}
+
/* basically pmap follows */
/* virtual to physical helpers */
-/* $OpenBSD: smmu_acpi.c,v 1.2 2021/03/15 22:48:57 patrick Exp $ */
+/* $OpenBSD: smmu_acpi.c,v 1.3 2021/06/25 17:41:22 patrick Exp $ */
/*
* Copyright (c) 2021 Patrick Wildt <patrick@blueri.se>
*
as->as_node = node;
as->as_cookie = sc;
as->as_map = smmu_device_map;
+ as->as_reserve = smmu_reserve_region;
acpiiort_smmu_register(as);
}
-/* $OpenBSD: smmu_fdt.c,v 1.3 2021/03/15 22:48:57 patrick Exp $ */
+/* $OpenBSD: smmu_fdt.c,v 1.4 2021/06/25 17:41:22 patrick Exp $ */
/*
* Copyright (c) 2021 Patrick Wildt <patrick@blueri.se>
*
void smmu_fdt_attach(struct device *, struct device *, void *);
bus_dma_tag_t smmu_fdt_map(void *, uint32_t *, bus_dma_tag_t);
+void smmu_fdt_reserve(void *, uint32_t *, bus_addr_t, bus_size_t);
struct cfattach smmu_fdt_ca = {
sizeof(struct smmu_fdt_softc), smmu_fdt_match, smmu_fdt_attach
fsc->sc_id.id_node = faa->fa_node;
fsc->sc_id.id_cookie = fsc;
fsc->sc_id.id_map = smmu_fdt_map;
+ fsc->sc_id.id_reserve = smmu_fdt_reserve;
iommu_device_register(&fsc->sc_id);
}
return smmu_device_map(sc, cells[0], dmat);
}
+
+void
+smmu_fdt_reserve(void *cookie, uint32_t *cells, bus_addr_t addr,
+ bus_size_t size)
+{
+ struct smmu_fdt_softc *fsc = (struct smmu_fdt_softc *)cookie;
+ struct smmu_softc *sc = &fsc->sc_smmu;
+
+ return smmu_reserve_region(sc, cells[0], addr, size);
+}
-/* $OpenBSD: smmuvar.h,v 1.5 2021/06/25 12:40:29 patrick Exp $ */
+/* $OpenBSD: smmuvar.h,v 1.6 2021/06/25 17:41:22 patrick Exp $ */
/*
* Copyright (c) 2021 Patrick Wildt <patrick@blueri.se>
*
int smmu_global_irq(void *);
int smmu_context_irq(void *);
bus_dma_tag_t smmu_device_map(void *, uint32_t, bus_dma_tag_t);
+void smmu_reserve_region(void *, uint32_t, bus_addr_t, bus_size_t);
-/* $OpenBSD: dwpcie.c,v 1.33 2021/06/24 09:34:17 kettenis Exp $ */
+/* $OpenBSD: dwpcie.c,v 1.34 2021/06/25 17:41:22 patrick Exp $ */
/*
* Copyright (c) 2018 Mark Kettenis <kettenis@openbsd.org>
*
{
struct dwpcie_softc *sc = v;
uint16_t rid;
+ int i;
rid = pci_requester_id(pa->pa_pc, pa->pa_tag);
pa->pa_dmat = iommu_device_map_pci(sc->sc_node, rid, pa->pa_dmat);
+ for (i = 0; i < sc->sc_nranges; i++) {
+ iommu_reserve_region_pci(sc->sc_node, rid,
+ sc->sc_ranges[i].pci_base, sc->sc_ranges[i].size);
+ }
+
return 0;
}
-/* $OpenBSD: pciecam.c,v 1.2 2021/05/19 20:10:38 kettenis Exp $ */
+/* $OpenBSD: pciecam.c,v 1.3 2021/06/25 17:41:22 patrick Exp $ */
/*
* Copyright (c) 2013,2017 Patrick Wildt <patrick@blueri.se>
*
{
struct pciecam_softc *sc = (struct pciecam_softc *)v;
uint16_t rid;
+ int i;
rid = pci_requester_id(pa->pa_pc, pa->pa_tag);
pa->pa_dmat = iommu_device_map_pci(sc->sc_node, rid, pa->pa_dmat);
+ for (i = 0; i < sc->sc_pcirangeslen; i++) {
+ if (sc->sc_pciranges[i].flags >> 24 == 0)
+ continue;
+ iommu_reserve_region_pci(sc->sc_node, rid,
+ sc->sc_pciranges[i].pci_base, sc->sc_pciranges[i].size);
+ }
+
return 0;
}
-/* $OpenBSD: ofw_misc.c,v 1.32 2021/04/07 17:12:22 kettenis Exp $ */
+/* $OpenBSD: ofw_misc.c,v 1.33 2021/06/25 17:41:22 patrick Exp $ */
/*
* Copyright (c) 2017 Mark Kettenis
*
return dmat;
}
-bus_dma_tag_t
-iommu_device_map(int node, bus_dma_tag_t dmat)
+int
+iommu_device_lookup(int node, uint32_t *phandle, uint32_t *sid)
{
- uint32_t sid = 0;
- uint32_t phandle = 0;
uint32_t *cell;
uint32_t *map;
int len, icells, ncells;
+ int ret = 1;
len = OF_getproplen(node, "iommus");
if (len <= 0)
- return dmat;
+ return ret;
map = malloc(len, M_TEMP, M_WAITOK);
OF_getpropintarray(node, "iommus", map, len);
KASSERT(icells == 1);
- phandle = cell[0];
- sid = cell[1];
+ *phandle = cell[0];
+ *sid = cell[1];
+ ret = 0;
break;
cell += (1 + icells);
out:
free(map, M_TEMP, len);
- return iommu_device_do_map(phandle, &sid, dmat);
+ return ret;
}
-bus_dma_tag_t
-iommu_device_map_pci(int node, uint32_t rid, bus_dma_tag_t dmat)
+int
+iommu_device_lookup_pci(int node, uint32_t rid, uint32_t *phandle,
+ uint32_t *sid)
{
- uint32_t sid_base, sid = 0;
- uint32_t phandle = 0;
+ uint32_t sid_base;
uint32_t *cell;
uint32_t *map;
uint32_t mask, rid_base;
int len, length, icells, ncells;
+ int ret = 1;
len = OF_getproplen(node, "iommu-map");
if (len <= 0)
- return dmat;
+ return ret;
map = malloc(len, M_TEMP, M_WAITOK);
OF_getpropintarray(node, "iommu-map", map, len);
sid_base = cell[2];
length = cell[3];
if (rid >= rid_base && rid < rid_base + length) {
- sid = sid_base + (rid - rid_base);
- phandle = cell[1];
+ *sid = sid_base + (rid - rid_base);
+ *phandle = cell[1];
+ ret = 0;
break;
}
out:
free(map, M_TEMP, len);
+ return ret;
+}
+
+bus_dma_tag_t
+iommu_device_map(int node, bus_dma_tag_t dmat)
+{
+ uint32_t phandle, sid;
+
+ if (iommu_device_lookup(node, &phandle, &sid))
+ return dmat;
+
+ return iommu_device_do_map(phandle, &sid, dmat);
+}
+
+bus_dma_tag_t
+iommu_device_map_pci(int node, uint32_t rid, bus_dma_tag_t dmat)
+{
+ uint32_t phandle, sid;
+
+ if (iommu_device_lookup_pci(node, rid, &phandle, &sid))
+ return dmat;
+
return iommu_device_do_map(phandle, &sid, dmat);
}
+
+void
+iommu_device_do_reserve(uint32_t phandle, uint32_t *cells, bus_addr_t addr,
+ bus_size_t size)
+{
+ struct iommu_device *id;
+
+ if (phandle == 0)
+ return;
+
+ LIST_FOREACH(id, &iommu_devices, id_list) {
+ if (id->id_phandle == phandle) {
+ id->id_reserve(id->id_cookie, cells, addr, size);
+ break;
+ }
+ }
+}
+
+void
+iommu_reserve_region_pci(int node, uint32_t rid, bus_addr_t addr,
+ bus_size_t size)
+{
+ uint32_t phandle, sid;
+
+ if (iommu_device_lookup_pci(node, rid, &phandle, &sid))
+ return;
+
+ return iommu_device_do_reserve(phandle, &sid, addr, size);
+}
-/* $OpenBSD: ofw_misc.h,v 1.20 2021/04/07 17:12:22 kettenis Exp $ */
+/* $OpenBSD: ofw_misc.h,v 1.21 2021/06/25 17:41:22 patrick Exp $ */
/*
* Copyright (c) 2017 Mark Kettenis
*
int id_node;
void *id_cookie;
bus_dma_tag_t (*id_map)(void *, uint32_t *, bus_dma_tag_t);
+ void (*id_reserve)(void *, uint32_t *, bus_addr_t, bus_size_t);
LIST_ENTRY(iommu_device) id_list;
uint32_t id_phandle;
void iommu_device_register(struct iommu_device *);
bus_dma_tag_t iommu_device_map(int, bus_dma_tag_t);
bus_dma_tag_t iommu_device_map_pci(int, uint32_t, bus_dma_tag_t);
+void iommu_reserve_region_pci(int, uint32_t, bus_addr_t, bus_size_t);
#endif /* _DEV_OFW_MISC_H_ */