Rework management of the external L2 cache on the few Indy/Indigo2 systems
authormiod <miod@openbsd.org>
Thu, 17 Jul 2014 19:51:58 +0000 (19:51 +0000)
committermiod <miod@openbsd.org>
Thu, 17 Jul 2014 19:51:58 +0000 (19:51 +0000)
which have it.

Instead of implementing external L2 maintainance at the cache routine level,
let bus_dmamap_sync(9) know about the possible existence of an external L2,
and invoke a dedicated routine to perform the necessary cache operations.

This way, the external L2 dmamap_sync function pointer can get invoked with
the physical address to operate on; this saves the pmap_extract() calls the
previous cache routine had to do.

sys/arch/sgi/sgi/bus_dma.c
sys/arch/sgi/sgi/ip22.h
sys/arch/sgi/sgi/ip22_machdep.c

index a6cf5ed..1b5bce2 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: bus_dma.c,v 1.36 2014/07/12 18:44:42 tedu Exp $ */
+/*     $OpenBSD: bus_dma.c,v 1.37 2014/07/17 19:51:58 miod Exp $ */
 
 /*
  * Copyright (c) 2003-2004 Opsycon AB  (www.opsycon.se / www.opsycon.com)
@@ -68,7 +68,7 @@
 
 #include <machine/bus.h>
 
-#if defined(TGT_INDIGO2)
+#if defined(TGT_INDY) || defined(TGT_INDIGO2)
 #include <sgi/sgi/ip22.h>
 #endif
 
@@ -311,11 +311,33 @@ _dmamap_sync(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t addr,
 {
        int nsegs;
        int curseg;
+       int how;
        struct cpu_info *ci;
 
 #ifdef TGT_COHERENT
+       /* we only need to writeback here */
        if ((op & BUS_DMASYNC_PREWRITE) == 0)
                return;
+       else
+               how = CACHE_SYNC_W;
+#else
+       /*
+        * If only PREWRITE is requested, writeback.
+        * PREWRITE with PREREAD writebacks and invalidates (since noncoherent)
+        * *all* cache levels.
+        * Otherwise, just invalidate (since noncoherent).
+        */
+       if (op & BUS_DMASYNC_PREWRITE) {
+               if (op & BUS_DMASYNC_PREREAD)
+                       how = CACHE_SYNC_X;
+               else
+                       how = CACHE_SYNC_W;
+       } else {
+               if (op & (BUS_DMASYNC_PREREAD | BUS_DMASYNC_POSTREAD))
+                       how = CACHE_SYNC_R;
+               else
+                       return;
+       }
 #endif
 
        ci = curcpu();
@@ -353,28 +375,17 @@ _dmamap_sync(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t addr,
 #endif
 
                if (ssize != 0) {
-#ifdef TGT_COHERENT
-                       /* we only need to writeback here */
-                       Mips_IOSyncDCache(ci, vaddr, ssize, CACHE_SYNC_W);
-#else
+                       Mips_IOSyncDCache(ci, vaddr, ssize, how);
+#if defined(TGT_INDY) || defined(TGT_INDIGO2)
                        /*
-                        * If only PREWRITE is requested, writeback.
-                        * PREWRITE with PREREAD writebacks
-                        * and invalidates (if noncoherent) *all* cache levels.
-                        * Otherwise, just invalidate (if noncoherent).
+                        * Also flush external L2 if available - this could
+                        * (and used to) be done in Mips_IOSyncDCache, but
+                        * as the external L2 is physically addressed, this
+                        * would require the physical address to be
+                        * recomputed, although we know it here.
                         */
-                       if (op & BUS_DMASYNC_PREWRITE) {
-                               if (op & BUS_DMASYNC_PREREAD)
-                                       Mips_IOSyncDCache(ci, vaddr,
-                                           ssize, CACHE_SYNC_X);
-                               else
-                                       Mips_IOSyncDCache(ci, vaddr,
-                                           ssize, CACHE_SYNC_W);
-                       } else
-                       if (op & (BUS_DMASYNC_PREREAD | BUS_DMASYNC_POSTREAD)) {
-                               Mips_IOSyncDCache(ci, vaddr,
-                                   ssize, CACHE_SYNC_R);
-                       }
+                       if (ip22_extsync != NULL)
+                               (*ip22_extsync)(ci, paddr, ssize, how);
 #endif
                        size -= ssize;
                }
index a01127e..8885c0c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip22.h,v 1.8 2012/09/29 21:46:02 miod Exp $   */
+/*     $OpenBSD: ip22.h,v 1.9 2014/07/17 19:51:58 miod Exp $   */
 
 /*
  * Copyright (c) 2012 Miodrag Vallat.
@@ -46,3 +46,4 @@ int   ip22_slow_mode(void);
 int    ip22_restore_mode(int);
 
 void   ip22_ConfigCache(struct cpu_info *);
+extern void (*ip22_extsync)(struct cpu_info *, paddr_t, size_t, int);
index 2326c50..00c5da6 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip22_machdep.c,v 1.19 2014/07/02 17:44:35 miod Exp $  */
+/*     $OpenBSD: ip22_machdep.c,v 1.20 2014/07/17 19:51:58 miod Exp $  */
 
 /*
  * Copyright (c) 2012 Miodrag Vallat.
@@ -62,9 +62,12 @@ int  hpc_old = 0;
 int    bios_year;
 int    ip22_ecc = 0;
 
+void   (*ip22_extsync)(struct cpu_info *, paddr_t, size_t, int);
+
 void   ip22_arcbios_walk(void);
 int    ip22_arcbios_walk_component(arc_config_t *);
 void   ip22_cache_halt(int);
+void   ip22_cache_sync(struct cpu_info *, paddr_t, size_t, int);
 void   ip22_ecc_halt(int);
 void   ip22_ecc_init(int);
 void   ip22_memory_setup(void);
@@ -780,7 +783,7 @@ ip22_ConfigCache(struct cpu_info *ci)
        ci->ci_l2 = l2;
 
        ci->ci_SyncCache = ip22_SyncCache;
-       ci->ci_IOSyncDCache = ip22_IOSyncDCache;
+       ip22_extsync = ip22_cache_sync;
 
        md_halt = ip22_cache_halt;
        ip22_l2_enable();
@@ -803,14 +806,10 @@ ip22_SyncCache(struct cpu_info *ci)
 }
 
 void
-ip22_IOSyncDCache(struct cpu_info *ci, vaddr_t _va, size_t _sz, int how)
+ip22_cache_sync(struct cpu_info *ci, paddr_t _pa, size_t _sz, int how)
 {
-       vaddr_t va;
        size_t sz;
-       paddr_t pa;
-
-       /* do whatever L1 work is necessary */
-       Mips5k_IOSyncDCache(ci, _va, _sz, how);
+       paddr_t pa, tagbase;
 
        switch (how) {
        default:
@@ -819,34 +818,20 @@ ip22_IOSyncDCache(struct cpu_info *ci, vaddr_t _va, size_t _sz, int how)
        case CACHE_SYNC_X:
        case CACHE_SYNC_R:
                /* extend the range to integral cache lines */
-               va = _va & ~(IP22_L2_LINE - 1);
-               sz = ((_va + _sz + IP22_L2_LINE - 1) & ~(IP22_L2_LINE - 1)) -
-                   va;
+               pa = _pa & ~(IP22_L2_LINE - 1);
+               sz = ((_pa + _sz + IP22_L2_LINE - 1) & ~(IP22_L2_LINE - 1)) -
+                   pa;
+
+               pa &= ci->ci_l2.size - 1;
+               tagbase = PHYS_TO_XKPHYS(IP22_CACHE_TAG_ADDRESS, CCA_NC);
 
                while (sz != 0) {
-                       /* get the proper physical address */
-                       if (pmap_extract(pmap_kernel(), va, &pa) == 0) {
-#ifdef DIAGNOSTIC
-                               panic("%s: invalid va %p",
-                                   __func__, (void *)va);
-#else
-                               /* should not happen */
-#endif
-                       }
+                       /* word write: invalidate line */
+                       *(volatile uint32_t *)(tagbase | pa) = 0;
 
+                       pa += IP22_L2_LINE;
                        pa &= ci->ci_l2.size - 1;
-                       pa |= PHYS_TO_XKPHYS(IP22_CACHE_TAG_ADDRESS, CCA_NC);
-
-                       while (sz != 0) {
-                               /* word write: invalidate line */
-                               *(volatile uint32_t *)pa = 0;
-
-                               pa += IP22_L2_LINE;
-                               va += IP22_L2_LINE;
-                               sz -= IP22_L2_LINE;
-                               if ((va & PAGE_MASK) == 0)
-                                       break;  /* need pmap_extract() */
-                       }
+                       sz -= IP22_L2_LINE;
                }
                break;
        }