summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2022-10-17 19:51:55 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2022-10-17 19:51:55 +0000
commitd694a3399e32e73d81f9480b93b12556e1ba0073 (patch)
tree8577bd8adf625c88c69ece721921fd85e99390bd /sys/arch
parentbc66683144037559685499cf0334177c2727eebd (diff)
Implement uncached mappings on the StarFive JH7100 SoC, where the hardware
provides allows bypassing the L2 cache by using a physical address alias. ok miod@
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/riscv64/riscv64/pmap.c32
1 files changed, 29 insertions, 3 deletions
diff --git a/sys/arch/riscv64/riscv64/pmap.c b/sys/arch/riscv64/riscv64/pmap.c
index d0413e01744..b51eb55604d 100644
--- a/sys/arch/riscv64/riscv64/pmap.c
+++ b/sys/arch/riscv64/riscv64/pmap.c
@@ -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;