From 6f219c58aea0121972109a3d06c79b53670be130 Mon Sep 17 00:00:00 2001 From: kettenis Date: Fri, 26 Jan 2024 16:59:47 +0000 Subject: [PATCH] Implement T-Head cache management operations which are needed to handle the incoherent hardware design of SoCs like the Allwinner D1. ok miod@, jca@ --- sys/arch/riscv64/riscv64/cpu.c | 73 +++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/sys/arch/riscv64/riscv64/cpu.c b/sys/arch/riscv64/riscv64/cpu.c index 13ae7c06072..0649c79cc01 100644 --- a/sys/arch/riscv64/riscv64/cpu.c +++ b/sys/arch/riscv64/riscv64/cpu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.c,v 1.17 2024/01/23 19:51:10 kettenis Exp $ */ +/* $OpenBSD: cpu.c,v 1.18 2024/01/26 16:59:47 kettenis Exp $ */ /* * Copyright (c) 2016 Dale Rahn @@ -27,6 +27,7 @@ #include +#include #include #include @@ -91,6 +92,12 @@ int cpu_errata_sifive_cip_1200; void cpu_opp_init(struct cpu_info *, uint32_t); +void thead_dcache_wbinv_range(paddr_t, psize_t); +void thead_dcache_inv_range(paddr_t, psize_t); +void thead_dcache_wb_range(paddr_t, psize_t); + +size_t thead_dcache_line_size; + void cpu_identify(struct cpu_info *ci) { @@ -141,6 +148,13 @@ cpu_identify(struct cpu_info *ci) /* Handle errata. */ if (mvendorid == CPU_VENDOR_SIFIVE && marchid == CPU_ARCH_U7) cpu_errata_sifive_cip_1200 = 1; + if (mvendorid == CPU_VENDOR_THEAD && marchid == 0 && mimpid == 0) { + cpu_dcache_wbinv_range = thead_dcache_wbinv_range; + cpu_dcache_inv_range = thead_dcache_inv_range; + cpu_dcache_wb_range = thead_dcache_wb_range; + thead_dcache_line_size = + OF_getpropint(ci->ci_node, "d-cache-block-size", 64); + } } #ifdef MULTIPROCESSOR @@ -309,6 +323,63 @@ cpu_cache_nop_range(paddr_t pa, psize_t len) { } +void +thead_dcache_wbinv_range(paddr_t pa, psize_t len) +{ + paddr_t end, mask; + + mask = thead_dcache_line_size - 1; + end = (pa + len + mask) & ~mask; + pa &= ~mask; + + while (pa != end) { + /* th.dcache.cipa a0 */ + __asm volatile ("mv a0, %0; .long 0x02b5000b" :: "r"(pa) + : "a0", "memory"); + pa += thead_dcache_line_size; + } + /* th.sync.s */ + __asm volatile (".long 0x0190000b" ::: "memory"); +} + +void +thead_dcache_inv_range(paddr_t pa, psize_t len) +{ + paddr_t end, mask; + + mask = thead_dcache_line_size - 1; + end = (pa + len + mask) & ~mask; + pa &= ~mask; + + while (pa != end) { + /* th.dcache.ipa a0 */ + __asm volatile ("mv a0, %0; .long 0x02a5000b" :: "r"(pa) + : "a0", "memory"); + pa += thead_dcache_line_size; + } + /* th.sync.s */ + __asm volatile (".long 0x0190000b" ::: "memory"); +} + +void +thead_dcache_wb_range(paddr_t pa, psize_t len) +{ + paddr_t end, mask; + + mask = thead_dcache_line_size - 1; + end = (pa + len + mask) & ~mask; + pa &= ~mask; + + while (pa != end) { + /* th.dcache.cpa a0 */ + __asm volatile ("mv a0, %0; .long 0x0295000b" :: "r"(pa) + : "a0", "memory"); + pa += thead_dcache_line_size; + } + /* th.sync.s */ + __asm volatile (".long 0x0190000b" ::: "memory"); +} + void (*cpu_dcache_wbinv_range)(paddr_t, psize_t) = cpu_cache_nop_range; void (*cpu_dcache_inv_range)(paddr_t, psize_t) = cpu_cache_nop_range; void (*cpu_dcache_wb_range)(paddr_t, psize_t) = cpu_cache_nop_range; -- 2.20.1