Perform IOMMU cache flushes on Oberon.
authorkettenis <kettenis@openbsd.org>
Sat, 12 Jul 2008 13:08:04 +0000 (13:08 +0000)
committerkettenis <kettenis@openbsd.org>
Sat, 12 Jul 2008 13:08:04 +0000 (13:08 +0000)
sys/arch/sparc64/dev/iommu.c
sys/arch/sparc64/dev/iommureg.h
sys/arch/sparc64/dev/iommuvar.h
sys/arch/sparc64/dev/psychoreg.h
sys/arch/sparc64/dev/pyro.c
sys/arch/sparc64/dev/schizoreg.h

index c9ef4eb..50da7b3 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: iommu.c,v 1.49 2007/12/15 18:08:07 deraadt Exp $      */
+/*     $OpenBSD: iommu.c,v 1.50 2008/07/12 13:08:04 kettenis Exp $     */
 /*     $NetBSD: iommu.c,v 1.47 2002/02/08 20:03:45 eeh Exp $   */
 
 /*
@@ -263,6 +263,9 @@ iommu_reset(struct iommu_state *is)
                if (sb->sb_flush)
                        printf(", STC%d enabled", i);
        }
+
+       if (is->is_flags & IOMMU_FLUSH_CACHE)
+               IOMMUREG_WRITE(is, iommu_cache_invalidate, -1ULL);
 }
 
 /*
@@ -1807,7 +1810,7 @@ iommu_iomap_load_map(struct iommu_state *is, struct iommu_map_state *ims,
        struct iommu_page_map *ipm = &ims->ims_map;
        struct iommu_page_entry *e;
        struct strbuf_ctl *sb = ims->ims_sb;
-       int i;
+       int i, slot;
 
        if (sb->sb_flush == NULL)
                flags &= ~BUS_DMA_STREAMING;
@@ -1820,6 +1823,14 @@ iommu_iomap_load_map(struct iommu_state *is, struct iommu_map_state *ims,
        for (i = 0, e = ipm->ipm_map; i < ipm->ipm_pagecnt; ++i, ++e) {
                e->ipe_va = vmaddr;
                iommu_enter(is, sb, e->ipe_va, e->ipe_pa, flags);
+
+               /* Flush cache if necessary. */
+               slot = IOTSBSLOT(e->ipe_va, is->is_tsbsize);
+               if (is->is_flags & IOMMU_FLUSH_CACHE &&
+                   (i == (ipm->ipm_pagecnt - 1) || (slot % 8) == 7))
+                       IOMMUREG_WRITE(is, iommu_cache_flush,
+                           is->is_ptsb + slot * 8);
+
                vmaddr += PAGE_SIZE;
        }
 
@@ -1835,11 +1846,19 @@ iommu_iomap_unload_map(struct iommu_state *is, struct iommu_map_state *ims)
        struct iommu_page_map *ipm = &ims->ims_map;
        struct iommu_page_entry *e;
        struct strbuf_ctl *sb = ims->ims_sb;
-       int i;
+       int i, slot;
 
-       for (i = 0, e = ipm->ipm_map; i < ipm->ipm_pagecnt; ++i, ++e)
+       for (i = 0, e = ipm->ipm_map; i < ipm->ipm_pagecnt; ++i, ++e) {
                iommu_remove(is, sb, e->ipe_va);
 
+               /* Flush cache if necessary. */
+               slot = IOTSBSLOT(e->ipe_va, is->is_tsbsize);
+               if (is->is_flags & IOMMU_FLUSH_CACHE &&
+                   (i == (ipm->ipm_pagecnt - 1) || (slot % 8) == 7))
+                       IOMMUREG_WRITE(is, iommu_cache_flush,
+                           is->is_ptsb + slot * 8);
+       }
+
        return (0);
 }
 
index 53cc1de..153c058 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: iommureg.h,v 1.15 2007/05/29 09:53:59 sobrado Exp $   */
+/*     $OpenBSD: iommureg.h,v 1.16 2008/07/12 13:08:04 kettenis Exp $  */
 /*     $NetBSD: iommureg.h,v 1.6 2001/07/20 00:07:13 eeh Exp $ */
 
 /*
@@ -54,6 +54,11 @@ struct iommureg {
        volatile u_int64_t      iommu_cr;       /* IOMMU control register */
        volatile u_int64_t      iommu_tsb;      /* IOMMU TSB base register */
        volatile u_int64_t      iommu_flush;    /* IOMMU flush register */
+       volatile u_int64_t      iommu_ctxflush;
+       volatile u_int64_t      iommu_reserved[28];
+       volatile u_int64_t      iommu_cache_flush;
+       volatile u_int64_t      iommu_cache_invalidate;
+       volatile u_int64_t      iommu_reserved2[30];
 };
 
 /* streaming buffer registers */
@@ -94,7 +99,7 @@ struct iommu_strbuf {
 #define IOTTE_STREAM   0x1000000000000000LL    /* Is page streamable? */
 #define        IOTTE_LOCAL     0x0800000000000000LL    /* Accesses to same bus segment? */
 #define        IOTTE_CONTEXT   0x07ff800000000000LL    /* context number */
-#define IOTTE_PAMASK   0x000007ffffffe000LL    /* Let's assume this is correct (bits 42..13) */
+#define IOTTE_PAMASK   0x00007fffffffe000LL    /* Let's assume this is correct (bits 42..13) */
 #define IOTTE_C                0x0000000000000010LL    /* Accesses to cacheable space */
 #define IOTTE_W                0x0000000000000002LL    /* Writeable */
 #define IOTTE_SOFTWARE 0x0000000000001f80LL    /* For software use (bits 12..7) */
index 390f2d6..99d233b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: iommuvar.h,v 1.12 2008/03/09 19:27:56 kettenis Exp $  */
+/*     $OpenBSD: iommuvar.h,v 1.13 2008/07/12 13:08:04 kettenis Exp $  */
 /*     $NetBSD: iommuvar.h,v 1.9 2001/10/07 20:30:41 eeh Exp $ */
 
 /*
@@ -110,6 +110,8 @@ struct iommu_state {
        int64_t                 is_cr;          /* Control register value */
        struct mutex            is_mtx;
        struct extent           *is_dvmamap;    /* DVMA map for this instance */
+       int                     is_flags;
+#define IOMMU_FLUSH_CACHE      0x00000001
 
        struct strbuf_ctl       *is_sb[2];      /* Streaming buffers if any */
 
index 94e2975..93a0138 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: psychoreg.h,v 1.11 2006/02/06 17:19:31 jmc Exp $      */
+/*     $OpenBSD: psychoreg.h,v 1.12 2008/07/12 13:08:04 kettenis Exp $ */
 /*     $NetBSD: psychoreg.h,v 1.6.4.2 2001/09/13 01:14:40 thorpej Exp $ */
 
 /*
@@ -85,7 +85,7 @@ struct psychoreg {
 
        struct iommureg psy_iommu;                                                      /* 1fe.0000.0200,0210 */
 
-       u_int64_t       pad3[317];
+       u_int64_t       pad3[256];
 
        u_int64_t       pcia_slot0_int;         /* PCI bus a slot 0 irq map reg */      /* 1fe.0000.0c00 */
        u_int64_t       pcia_slot1_int;         /* PCI bus a slot 1 irq map reg */      /* 1fe.0000.0c08 */
index dad704e..5570e62 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pyro.c,v 1.13 2008/07/12 12:21:04 kettenis Exp $      */
+/*     $OpenBSD: pyro.c,v 1.14 2008/07/12 13:08:04 kettenis Exp $      */
 
 /*
  * Copyright (c) 2002 Jason L. Wright (jason@thought.net)
@@ -240,6 +240,10 @@ pyro_init_iommu(struct pyro_softc *sc, struct pyro_pbm *pbm)
                panic("couldn't malloc iommu name");
        snprintf(name, 32, "%s dvma", sc->sc_dv.dv_xname);
 
+       /* On Oberon, we need to flush the cache. */
+       if (sc->sc_oberon)
+               is->is_flags |= IOMMU_FLUSH_CACHE;
+
        iommu_init(name, is, tsbsize, iobase);
 }
 
index ef4d5da..af4344e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: schizoreg.h,v 1.19 2008/02/10 12:53:01 kettenis Exp $ */
+/*     $OpenBSD: schizoreg.h,v 1.20 2008/07/12 13:08:04 kettenis Exp $ */
 
 /*
  * Copyright (c) 2002 Jason L. Wright (jason@thought.net)
@@ -27,9 +27,8 @@
  */
 struct schizo_pbm_regs {
        volatile u_int64_t      _unused1[64];           /* 0x0000 - 0x01ff */
-       struct iommureg         iommu;                  /* 0x0200 - 0x0217 */
-       volatile u_int64_t      iommu_ctxflush;         /* 0x0218 - 0x021f */
-       volatile u_int64_t      _unused2[444];
+       struct iommureg         iommu;                  /* 0x0200 - 0x03ff */
+       volatile u_int64_t      _unused2[384];
        volatile u_int64_t      imap[64];
        volatile u_int64_t      _unused3[64];
        volatile u_int64_t      iclr[64];