Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/sparc64/dev sun4v: iommu setup seems to work now - ...
details: https://anonhg.NetBSD.org/src/rev/1aac14d55d74
branches: trunk
changeset: 340415:1aac14d55d74
user: palle <palle%NetBSD.org@localhost>
date: Thu Sep 03 19:43:35 2015 +0000
description:
sun4v: iommu setup seems to work now - device detection is now possible - parts from OpenBSD - ok mrg@, martin@
diffstat:
sys/arch/sparc64/dev/iommu.c | 109 +++++++++++++++++++++++++++++++++++----
sys/arch/sparc64/dev/iommuvar.h | 3 +-
sys/arch/sparc64/dev/vpci.c | 80 ++++++++++++++---------------
3 files changed, 139 insertions(+), 53 deletions(-)
diffs (truncated from 412 to 300 lines):
diff -r 397d7b36bb4b -r 1aac14d55d74 sys/arch/sparc64/dev/iommu.c
--- a/sys/arch/sparc64/dev/iommu.c Thu Sep 03 15:01:19 2015 +0000
+++ b/sys/arch/sparc64/dev/iommu.c Thu Sep 03 19:43:35 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: iommu.c,v 1.108 2014/08/24 19:09:43 palle Exp $ */
+/* $NetBSD: iommu.c,v 1.109 2015/09/03 19:43:35 palle Exp $ */
/*
* Copyright (c) 1999, 2000 Matthew R. Green
@@ -59,7 +59,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: iommu.c,v 1.108 2014/08/24 19:09:43 palle Exp $");
+__KERNEL_RCSID(0, "$NetBSD: iommu.c,v 1.109 2015/09/03 19:43:35 palle Exp $");
#include "opt_ddb.h"
@@ -101,6 +101,10 @@
static int iommu_strbuf_flush_done(struct strbuf_ctl *);
static void _iommu_dvmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
bus_size_t, int);
+static void iommu_enter_sun4u(struct strbuf_ctl *sb, vaddr_t va, int64_t pa, int flags);
+static void iommu_enter_sun4v(struct strbuf_ctl *sb, vaddr_t va, int64_t pa, int flags);
+static void iommu_remove_sun4u(struct iommu_state *is, vaddr_t va, size_t len);
+static void iommu_remove_sun4v(struct iommu_state *is, vaddr_t va, size_t len);
/*
* initialise the UltraSPARC IOMMU (SBUS or PCI):
@@ -118,6 +122,8 @@
struct vm_page *pg;
struct pglist pglist;
+ DPRINTF(IDB_INFO, ("iommu_init: tsbsize %x iovabase %x\n", tsbsize, iovabase));
+
/*
* Setup the iommu.
*
@@ -181,17 +187,18 @@
if (iommudebug & IDB_INFO)
{
/* Probe the iommu */
-
- printf("iommu cr=%llx tsb=%llx\n",
- (unsigned long long)bus_space_read_8(is->is_bustag,
+ if (!CPU_ISSUN4V) {
+ printf("iommu cr=%llx tsb=%llx\n",
+ (unsigned long long)bus_space_read_8(is->is_bustag,
is->is_iommu,
offsetof(struct iommureg, iommu_cr)),
- (unsigned long long)bus_space_read_8(is->is_bustag,
+ (unsigned long long)bus_space_read_8(is->is_bustag,
is->is_iommu,
offsetof(struct iommureg, iommu_tsb)));
- printf("TSB base %p phys %llx\n", (void *)is->is_tsb,
- (unsigned long long)is->is_ptsb);
- delay(1000000); /* 1 s */
+ printf("TSB base %p phys %llx\n", (void *)is->is_tsb,
+ (unsigned long long)is->is_ptsb);
+ delay(1000000); /* 1 s */
+ }
}
#endif
@@ -207,8 +214,9 @@
is->is_dvmamap = extent_create(name,
is->is_dvmabase, is->is_dvmaend,
0, 0, EX_NOWAIT);
- /* XXXMRG Check is_dvmamap is valid. */
-
+ if (!is->is_dvmamap)
+ panic("iommu_init: extent_create() failed");
+
mutex_init(&is->is_lock, MUTEX_DEFAULT, IPL_HIGH);
/*
@@ -237,6 +245,9 @@
int i;
struct strbuf_ctl *sb;
+ if (CPU_ISSUN4V)
+ return;
+
IOMMUREG_WRITE(is, iommu_tsb, is->is_ptsb);
/* Enable IOMMU in diagnostic mode */
@@ -276,9 +287,22 @@
/*
* Here are the iommu control routines.
*/
+
void
iommu_enter(struct strbuf_ctl *sb, vaddr_t va, int64_t pa, int flags)
{
+ DPRINTF(IDB_IOMMU, ("iommu_enter: va %lx pa %lx flags %x\n",
+ va, (long)pa, flags));
+ if (!CPU_ISSUN4V)
+ iommu_enter_sun4u(sb, va, pa, flags);
+ else
+ iommu_enter_sun4v(sb, va, pa, flags);
+}
+
+
+void
+iommu_enter_sun4u(struct strbuf_ctl *sb, vaddr_t va, int64_t pa, int flags)
+{
struct iommu_state *is = sb->sb_is;
int strbuf = (flags & BUS_DMA_STREAMING);
int64_t tte;
@@ -311,6 +335,35 @@
(u_long)tte));
}
+void
+iommu_enter_sun4v(struct strbuf_ctl *sb, vaddr_t va, int64_t pa, int flags)
+{
+ struct iommu_state *is = sb->sb_is;
+ u_int64_t tsbid = IOTSBSLOT(va, is->is_tsbsize);
+ paddr_t page_list[1], addr;
+ u_int64_t attr, nmapped;
+ int err;
+
+#ifdef DIAGNOSTIC
+ if (va < is->is_dvmabase || (va + PAGE_MASK) > is->is_dvmaend)
+ panic("viommu_enter: va %#lx not in DVMA space", va);
+#endif
+
+ attr = PCI_MAP_ATTR_READ | PCI_MAP_ATTR_WRITE;
+ if (flags & BUS_DMA_READ)
+ attr &= ~PCI_MAP_ATTR_READ;
+ if (flags & BUS_DMA_WRITE)
+ attr &= ~PCI_MAP_ATTR_WRITE;
+
+ page_list[0] = trunc_page(pa);
+ if (!pmap_extract(pmap_kernel(), (vaddr_t)page_list, &addr))
+ panic("viommu_enter: pmap_extract failed");
+ err = hv_pci_iommu_map(is->is_devhandle, tsbid, 1, attr,
+ addr, &nmapped);
+ if (err != H_EOK || nmapped != 1)
+ panic("hv_pci_iommu_map: err=%d, nmapped=%lu", err, (long unsigned int)nmapped);
+}
+
/*
* Find the value of a DVMA address (debug routine).
*/
@@ -334,9 +387,22 @@
*
* XXX: this function needs better internal error checking.
*/
+
+
void
iommu_remove(struct iommu_state *is, vaddr_t va, size_t len)
{
+ DPRINTF(IDB_IOMMU, ("iommu_remove: va %lx len %zu\n", va, len));
+ if (!CPU_ISSUN4V)
+ iommu_remove_sun4u(is, va, len);
+ else
+ iommu_remove_sun4v(is, va, len);
+}
+
+void
+iommu_remove_sun4u(struct iommu_state *is, vaddr_t va, size_t len)
+{
+
int slot;
#ifdef DIAGNOSTIC
@@ -389,6 +455,27 @@
}
}
+void
+iommu_remove_sun4v(struct iommu_state *is, vaddr_t va, size_t len)
+{
+ u_int64_t tsbid = IOTSBSLOT(va, is->is_tsbsize);
+ u_int64_t ndemapped;
+ int err;
+
+#ifdef DIAGNOSTIC
+ if (va < is->is_dvmabase || (va + PAGE_MASK) > is->is_dvmaend)
+ panic("iommu_remove: va 0x%lx not in DVMA space", (u_long)va);
+ if (va != trunc_page(va)) {
+ printf("iommu_remove: unaligned va: %lx\n", va);
+ va = trunc_page(va);
+ }
+#endif
+
+ err = hv_pci_iommu_demap(is->is_devhandle, tsbid, 1, &ndemapped);
+ if (err != H_EOK || ndemapped != 1)
+ panic("hv_pci_iommu_unmap: err=%d", err);
+}
+
static int
iommu_strbuf_flush_done(struct strbuf_ctl *sb)
{
diff -r 397d7b36bb4b -r 1aac14d55d74 sys/arch/sparc64/dev/iommuvar.h
--- a/sys/arch/sparc64/dev/iommuvar.h Thu Sep 03 15:01:19 2015 +0000
+++ b/sys/arch/sparc64/dev/iommuvar.h Thu Sep 03 19:43:35 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: iommuvar.h,v 1.21 2012/03/25 03:51:33 mrg Exp $ */
+/* $NetBSD: iommuvar.h,v 1.22 2015/09/03 19:43:35 palle Exp $ */
/*
* Copyright (c) 1999 Matthew R. Green
@@ -65,6 +65,7 @@
/* copies of our parents state, to allow us to be self contained */
bus_space_tag_t is_bustag; /* our bus tag */
bus_space_handle_t is_iommu; /* IOMMU registers */
+ uint64_t is_devhandle; /* for sun4v hypervisor calls */
};
/* interfaces for PCI/SBUS code */
diff -r 397d7b36bb4b -r 1aac14d55d74 sys/arch/sparc64/dev/vpci.c
--- a/sys/arch/sparc64/dev/vpci.c Thu Sep 03 15:01:19 2015 +0000
+++ b/sys/arch/sparc64/dev/vpci.c Thu Sep 03 19:43:35 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: vpci.c,v 1.1 2015/02/12 04:48:37 palle Exp $ */
+/* $NetBSD: vpci.c,v 1.2 2015/09/03 19:43:35 palle Exp $ */
/*
* Copyright (c) 2015 Palle Lyckegaard
* All rights reserved.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vpci.c,v 1.1 2015/02/12 04:48:37 palle Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vpci.c,v 1.2 2015/09/03 19:43:35 palle Exp $");
#include <sys/param.h>
#include <sys/device.h>
@@ -56,11 +56,13 @@
#include <sparc64/hypervisor.h>
#ifdef DEBUG
-#define VDB_PROM 0x01
-#define VDB_BUSMAP 0x02
-#define VDB_INTR 0x04
-#define VDB_CONF 0x08
-int vpci_debug = 0xff;
+#define VDB_PROM 0x01
+#define VDB_BUSMAP 0x02
+#define VDB_INTR 0x04
+#define VDB_CONF_READ 0x08
+#define VDB_CONF_WRITE 0x10
+#define VDB_CONF VDB_CONF_READ|VDB_CONF_WRITE
+int vpci_debug = 0x00;
#define DPRINTF(l, s) do { if (vpci_debug & l) printf s; } while (0)
#else
#define DPRINTF(l, s)
@@ -94,10 +96,7 @@
vpci_match, vpci_attach, NULL, NULL);
void vpci_init(struct vpci_softc */*FIXME, int*/, struct mainbus_attach_args *);
-#if 0
-FIXME
void vpci_init_iommu(struct vpci_softc *, struct vpci_pbm *);
-#endif
pci_chipset_tag_t vpci_alloc_chipset(struct vpci_pbm *, int,
pci_chipset_tag_t);
bus_space_tag_t vpci_alloc_mem_tag(struct vpci_pbm *);
@@ -233,20 +232,9 @@
panic("vpci: can't get bus-range");
for (int range = 0; range < nranges; range++)
DPRINTF(VDB_PROM, ("\nvpci_attach: bus-range %d %08x", range, busranges[range]));
-#if 0
-FIXME
- printf(": \"%s\", rev %d, ign %x, bus %c %d to %d\n",
- sc->sc_oberon ? "Oberon" : "Fire",
- prom_getpropint(sc->sc_node, "module-revision#", 0), sc->sc_ign,
- busa ? 'A' : 'B', busranges[0], busranges[1]);
-#else
- printf(": ign %x, bus %d to %d\n", sc->sc_ign, busranges[0], busranges[1]);
-#endif
- printf("%s: ", device_xname(sc->sc_dev));
-#if 0
-FIXME
+
vpci_init_iommu(sc, pbm);
-#endif
+
pbm->vp_memt = vpci_alloc_mem_tag(pbm);
pbm->vp_iot = vpci_alloc_io_tag(pbm);
pbm->vp_cfgt = vpci_alloc_config_tag(pbm);
@@ -284,14 +272,15 @@
config_found(sc->sc_dev, &pba, vpci_print);
}
-#if 0
-FIXME
void
vpci_init_iommu(struct vpci_softc *sc, struct vpci_pbm *pbm)
{
struct iommu_state *is = &pbm->vp_is;
- int tsbsize = 7;
+ int *vdma = NULL;
+ int nitem;
+ int tsbsize = 0;
u_int32_t iobase = -1;
+ u_int32_t iolen = 0;
Home |
Main Index |
Thread Index |
Old Index