diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2022-10-17 19:51:55 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2022-10-17 19:51:55 +0000 |
commit | d694a3399e32e73d81f9480b93b12556e1ba0073 (patch) | |
tree | 8577bd8adf625c88c69ece721921fd85e99390bd /sys/arch | |
parent | bc66683144037559685499cf0334177c2727eebd (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.c | 32 |
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; |