Implement uncached mappings on the StarFive JH7100 SoC, where the hardware
authorkettenis <kettenis@openbsd.org>
Mon, 17 Oct 2022 19:51:54 +0000 (19:51 +0000)
committerkettenis <kettenis@openbsd.org>
Mon, 17 Oct 2022 19:51:54 +0000 (19:51 +0000)
provides allows bypassing the L2 cache by using a physical address alias.

ok miod@

sys/arch/riscv64/riscv64/pmap.c

index d0413e0..b51eb55 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pmap.c,v 1.23 2022/09/10 20:35:29 miod Exp $  */
+/*     $OpenBSD: pmap.c,v 1.24 2022/10/17 19:51:54 kettenis Exp $      */
 
 /*
  * Copyright (c) 2019-2020 Brian Bamsch <bbamsch@google.com>
@@ -30,6 +30,8 @@
 #include <machine/riscvreg.h>
 #include <machine/sbi.h>
 
+#include <dev/ofw/fdt.h>
+
 #ifdef MULTIPROCESSOR
 
 static inline int
@@ -204,6 +206,9 @@ struct mem_region *pmap_allocated = &pmap_allocated_regions[0];
 int pmap_cnt_avail, pmap_cnt_allocated;
 uint64_t pmap_avail_kvo;
 
+paddr_t pmap_cached_start, pmap_cached_end;
+paddr_t pmap_uncached_start, pmap_uncached_end;
+
 static inline void
 pmap_lock(struct pmap *pmap)
 {
@@ -631,6 +636,7 @@ _pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot, int flags, int cache)
 {
        pmap_t pm = pmap_kernel();
        struct pte_desc *pted;
+       struct vm_page *pg;
 
        pted = pmap_vp_lookup(pm, va, NULL);
 
@@ -657,6 +663,10 @@ _pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot, int flags, int cache)
        pmap_pte_insert(pted);
 
        tlb_flush_page(pm, va & ~PAGE_MASK);
+
+       pg = PHYS_TO_VM_PAGE(pa);
+       if (pg && cache == PMAP_CACHE_CI)
+               cpu_dcache_wbinv_range(pa & ~PAGE_MASK, PAGE_SIZE);
 }
 
 void
@@ -741,6 +751,8 @@ pmap_fill_pte(pmap_t pm, vaddr_t va, paddr_t pa, struct pte_desc *pted,
        case PMAP_CACHE_WT:
                break;
        case PMAP_CACHE_CI:
+               if (pa >= pmap_cached_start && pa <= pmap_cached_end)
+                       pa += (pmap_uncached_start - pmap_cached_start);
                break;
        case PMAP_CACHE_DEV:
                break;
@@ -1171,6 +1183,15 @@ pmap_bootstrap(long kvo, vaddr_t l1pt, vaddr_t kernelstart, vaddr_t kernelend,
        vaddr_t vstart;
        int i, j, k;
        int lb_idx2, ub_idx2;
+       void *node;
+
+       node = fdt_find_node("/");
+       if (fdt_is_compatible(node, "starfive,jh7100")) {
+               pmap_cached_start = 0x0080000000ULL;
+               pmap_cached_end = 0x087fffffffULL;
+               pmap_uncached_start = 0x1000000000ULL;
+               pmap_uncached_end = 0x17ffffffffULL;
+       }
 
        pmap_setup_avail(memstart, memend, kvo);
        pmap_remove_avail(kernelstart + kvo, kernelend + kvo);
@@ -1407,6 +1428,7 @@ int
 pmap_extract(pmap_t pm, vaddr_t va, paddr_t *pap)
 {
        struct pte_desc *pted;
+       paddr_t pa;
 
        pmap_lock(pm);
        pted = pmap_vp_lookup(pm, va, NULL);
@@ -1414,8 +1436,12 @@ pmap_extract(pmap_t pm, vaddr_t va, paddr_t *pap)
                pmap_unlock(pm);
                return 0;
        }
-       if (pap != NULL)
-               *pap = (pted->pted_pte & PTE_RPGN) | (va & PAGE_MASK);
+       if (pap != NULL) {
+               pa = pted->pted_pte & PTE_RPGN;
+               if (pa >= pmap_uncached_start && pa <= pmap_uncached_end)
+                       pa -= (pmap_uncached_start - pmap_cached_start);
+               *pap = pa | (va & PAGE_MASK);
+       }
        pmap_unlock(pm);
 
        return 1;