Module Name:    src
Committed By:   palle
Date:           Thu Sep  3 19:43:35 UTC 2015

Modified Files:
        src/sys/arch/sparc64/dev: iommu.c iommuvar.h vpci.c

Log Message:
sun4v: iommu setup seems to work now - device detection is now possible - parts 
from OpenBSD - ok mrg@, martin@


To generate a diff of this commit:
cvs rdiff -u -r1.108 -r1.109 src/sys/arch/sparc64/dev/iommu.c
cvs rdiff -u -r1.21 -r1.22 src/sys/arch/sparc64/dev/iommuvar.h
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/sparc64/dev/vpci.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/sparc64/dev/iommu.c
diff -u src/sys/arch/sparc64/dev/iommu.c:1.108 src/sys/arch/sparc64/dev/iommu.c:1.109
--- src/sys/arch/sparc64/dev/iommu.c:1.108	Sun Aug 24 19:09:43 2014
+++ src/sys/arch/sparc64/dev/iommu.c	Thu Sep  3 19:43:35 2015
@@ -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 @@ int iommudebug = 0x0;
 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 @@ iommu_init(char *name, struct iommu_stat
 	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 @@ iommu_init(char *name, struct iommu_stat
 	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 @@ iommu_init(char *name, struct iommu_stat
 	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 @@ iommu_reset(struct iommu_state *is)
 	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 @@ iommu_reset(struct iommu_state *is)
 /*
  * 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 @@ iommu_enter(struct strbuf_ctl *sb, vaddr
 		(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 @@ iommu_extract(struct iommu_state *is, va
  *
  * 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 @@ iommu_remove(struct iommu_state *is, vad
 	}
 }
 
+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)
 {

Index: src/sys/arch/sparc64/dev/iommuvar.h
diff -u src/sys/arch/sparc64/dev/iommuvar.h:1.21 src/sys/arch/sparc64/dev/iommuvar.h:1.22
--- src/sys/arch/sparc64/dev/iommuvar.h:1.21	Sun Mar 25 03:51:33 2012
+++ src/sys/arch/sparc64/dev/iommuvar.h	Thu Sep  3 19:43:35 2015
@@ -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 @@ struct iommu_state {
 	/* 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 */

Index: src/sys/arch/sparc64/dev/vpci.c
diff -u src/sys/arch/sparc64/dev/vpci.c:1.1 src/sys/arch/sparc64/dev/vpci.c:1.2
--- src/sys/arch/sparc64/dev/vpci.c:1.1	Thu Feb 12 04:48:37 2015
+++ src/sys/arch/sparc64/dev/vpci.c	Thu Sep  3 19:43:35 2015
@@ -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 @@ __KERNEL_RCSID(0, "$NetBSD: vpci.c,v 1.1
 #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 @@ CFATTACH_DECL_NEW(vpci, sizeof(struct vp
     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 @@ FiXME	
 		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 @@ FIXME	
 	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;
 	char *name;
 
 	pbm->vp_sb.sb_is = is;
@@ -302,6 +291,20 @@ vpci_init_iommu(struct vpci_softc *sc, s
 		panic("vpci: unable to create iommu handle");
 	}
 
+	/* Construct tsbsize */
+	if (!prom_getprop(sc->sc_node, "virtual-dma", sizeof(vdma), &nitem, 
+	    (void **)&vdma)) {
+		DPRINTF(VDB_BUSMAP, ("vpci_init_iommu: vdma[0]=0x%x  vdma[1]=0x%x\n",
+		    vdma[0], vdma[1]));
+		iobase = vdma[0];
+		iolen = vdma[1];
+		for (tsbsize = 8; (1 << (tsbsize+23)) > iolen; tsbsize--) ;
+		DPRINTF(VDB_BUSMAP, ("vpci_init_iommu: iobase=0x%x  iolen = 0x%x  tsbsize=0x%x\n",
+		    iobase, iolen, tsbsize));
+		free(vdma, M_DEVBUF);
+	} else
+		panic("vpci_init_iommu: getprop virtual-dma failed");
+	
 	/* We have no STC.  */
 	is->is_sb[0] = NULL;
 
@@ -313,13 +316,10 @@ vpci_init_iommu(struct vpci_softc *sc, s
 	/* Tell iommu how to set the TSB size.  */
 	is->is_flags = IOMMU_TSBSIZE_IN_PTSB;
 
-	/* On Oberon, we need to flush the cache. */
-	if (sc->sc_oberon)
-		is->is_flags |= IOMMU_FLUSH_CACHE;
-
+	is->is_devhandle = pbm->vp_devhandle;
 	iommu_init(name, is, tsbsize, iobase);
 }
-#endif	
+
 
 int
 vpci_print(void *aux, const char *p)
@@ -336,7 +336,7 @@ vpci_conf_read(pci_chipset_tag_t pc, pci
 	uint64_t error_flag, data;
 
 	int64_t hv_rc;
-	DPRINTF(VDB_CONF, ("%s: tag %lx reg %x ", __func__, (long)tag, reg));
+	DPRINTF(VDB_CONF_READ, ("%s: tag %lx reg %x ", __func__, (long)tag, reg));
 	hv_rc = hv_pci_config_get(pbm->vp_devhandle, PCITAG_OFFSET(tag), reg, 4,
 	    &error_flag, &data);
 	if (hv_rc != H_EOK)
@@ -344,7 +344,7 @@ vpci_conf_read(pci_chipset_tag_t pc, pci
 		    hv_rc);
 	
 	pcireg_t val = error_flag ? (pcireg_t)~0 : data;
-	DPRINTF(VDB_CONF, (" returning %08x\n", (u_int)val));
+	DPRINTF(VDB_CONF_READ, (" returning %08x\n", (u_int)val));
 	return val;
 }
 
@@ -355,14 +355,14 @@ vpci_conf_write(pci_chipset_tag_t pc, pc
 	struct vpci_pbm *pbm = pc->cookie;
 	uint64_t error_flag;
 	int64_t hv_rc;
-	DPRINTF(VDB_CONF, ("%s: tag %lx; reg %x; data %x", __func__,
+	DPRINTF(VDB_CONF_WRITE, ("%s: tag %lx; reg %x; data %x", __func__,
 		(long)tag, reg, (int)data));
 	hv_rc = hv_pci_config_put(pbm->vp_devhandle, PCITAG_OFFSET(tag), reg, 4,
             data, &error_flag);
 	if (hv_rc != H_EOK)
 		panic("hv_pci_config_put() failed - rc = %" PRId64 "\n",
 		    hv_rc);
-	DPRINTF(VDB_CONF, (" .. done\n"));
+	DPRINTF(VDB_CONF_WRITE, (" .. done\n"));
 }
 
 /*
@@ -371,8 +371,6 @@ vpci_conf_write(pci_chipset_tag_t pc, pc
 int
 vpci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp)
 {
-	DPRINTF(VDB_INTR, ("vpci_intr_map()\n"));
-
 	struct vpci_pbm *pbm = pa->pa_pc->cookie;
 	uint64_t devhandle = pbm->vp_devhandle;
 	uint64_t devino = INTINO(*ihp);
@@ -459,8 +457,8 @@ vpci_alloc_dma_tag(struct vpci_pbm *pbm)
 	dt->_dmamap_sync	= iommu_dvmamap_sync;
 	dt->_dmamem_alloc	= iommu_dvmamem_alloc;
 	dt->_dmamem_free	= iommu_dvmamem_free;
-	dt->_dmamem_map = iommu_dvmamem_map;
-	dt->_dmamem_unmap = iommu_dvmamem_unmap;
+	dt->_dmamem_map         = iommu_dvmamem_map;
+	dt->_dmamem_unmap       = iommu_dvmamem_unmap;
 	PCOPY(_dmamem_mmap);
 #undef	PCOPY
 	return (dt);
@@ -508,14 +506,14 @@ vpci_bus_map(bus_space_tag_t t, bus_addr
 	struct vpci_softc *sc = pbm->vp_sc;
 	int i, ss;
 
-	DPRINTF(VDB_BUSMAP, ("vpci_bus_map: type %d off %qx sz %qx flags %d\n",
+	DPRINTF(VDB_BUSMAP, ("vpci_bus_map: type %d off %qx sz %qx flags %d",
 	    t->type,
 	    (unsigned long long)offset,
 	    (unsigned long long)size,
 	    flags));
 
 	ss = sparc_pci_childspace(t->type);
-	DPRINTF(VDB_BUSMAP, (" cspace %d", ss));
+	DPRINTF(VDB_BUSMAP, (" cspace %d\n", ss));
 
 	if (t->parent == 0 || t->parent->sparc_bus_map == 0) {
 		printf("\n_vpci_bus_map: invalid parent");

Reply via email to