From: kettenis Date: Tue, 23 Jan 2024 19:51:10 +0000 (+0000) Subject: T-Head implemented a page attribute extension that violates the RISC-V X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=84aa31c6dccc7ce19e85f1b6fd453682af038fa3;p=openbsd T-Head implemented a page attribute extension that violates the RISC-V specification. The default attributes result in memory being uncached which makes the system perform like a slug. So implement a workaround that is designed to make implementation of the Svpbmt extension that is part of the latest published RISC-V specification. This gets us a bit further booting OpenBSD on an Allwinner D1 SoC. ok mlarkin@, jca@ --- diff --git a/sys/arch/riscv64/include/pmap.h b/sys/arch/riscv64/include/pmap.h index 1f52a260ee5..1d5f3f31c6d 100644 --- a/sys/arch/riscv64/include/pmap.h +++ b/sys/arch/riscv64/include/pmap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap.h,v 1.10 2023/12/13 18:26:41 jca Exp $ */ +/* $OpenBSD: pmap.h,v 1.11 2024/01/23 19:51:10 kettenis Exp $ */ /* * Copyright (c) 2019-2020 Brian Bamsch @@ -44,8 +44,7 @@ /* cache flags */ // XXX These are duplicated from arm64 and may need some reworking #define PMAP_CACHE_CI (PMAP_MD0) /* cache inhibit */ -#define PMAP_CACHE_WT (PMAP_MD1) /* writethru */ -#define PMAP_CACHE_WB (PMAP_MD1|PMAP_MD0) /* writeback */ +#define PMAP_CACHE_WB (PMAP_MD1) /* writeback */ #define PMAP_CACHE_DEV (PMAP_MD2) /* device mapping */ #define PMAP_CACHE_BITS (PMAP_MD0|PMAP_MD1|PMAP_MD2) diff --git a/sys/arch/riscv64/include/pte.h b/sys/arch/riscv64/include/pte.h index 2dc05790b72..658ec7b18d7 100644 --- a/sys/arch/riscv64/include/pte.h +++ b/sys/arch/riscv64/include/pte.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pte.h,v 1.2 2021/05/12 01:20:52 jsg Exp $ */ +/* $OpenBSD: pte.h,v 1.3 2024/01/23 19:51:10 kettenis Exp $ */ /* * Copyright (c) 2019 Brian Bamsch @@ -39,8 +39,12 @@ #define PTE_RWX (PTE_R | PTE_W | PTE_X) #define PTE_RX (PTE_R | PTE_X) #define PTE_KERN (PTE_V | PTE_R | PTE_W | PTE_A | PTE_D) -#define PTE_PROMOTE (PTE_V | PTE_RWX | PTE_D | PTE_A | PTE_G | PTE_U | \ - PTE_SW_MANAGED | PTE_SW_WIRED + +/* T-Head extended page attributes */ +#define PTE_THEAD_SO (1ULL << 63) +#define PTE_THEAD_C (1ULL << 62) +#define PTE_THEAD_B (1ULL << 61) +#define PTE_THEAD_SH (1ULL << 60) /* Level 0 table, 512GiB per entry */ #define L0_SHIFT 39 diff --git a/sys/arch/riscv64/riscv64/cpu.c b/sys/arch/riscv64/riscv64/cpu.c index de8c1422dbc..13ae7c06072 100644 --- a/sys/arch/riscv64/riscv64/cpu.c +++ b/sys/arch/riscv64/riscv64/cpu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.c,v 1.16 2023/10/24 13:20:10 claudio Exp $ */ +/* $OpenBSD: cpu.c,v 1.17 2024/01/23 19:51:10 kettenis Exp $ */ /* * Copyright (c) 2016 Dale Rahn @@ -37,9 +37,10 @@ #include /* CPU Identification */ - #define CPU_VENDOR_SIFIVE 0x489 +#define CPU_VENDOR_THEAD 0x5b7 +/* SiFive */ #define CPU_ARCH_U5 0x0000000000000001 #define CPU_ARCH_U7 0x8000000000000007 @@ -66,6 +67,7 @@ const struct vendor { struct arch *archlist; } cpu_vendors[] = { { CPU_VENDOR_SIFIVE, "SiFive", cpu_arch_sifive }, + { CPU_VENDOR_THEAD, "T-Head", cpu_arch_none }, { 0, NULL } }; diff --git a/sys/arch/riscv64/riscv64/machdep.c b/sys/arch/riscv64/riscv64/machdep.c index eb7778d9e08..7658ba0df54 100644 --- a/sys/arch/riscv64/riscv64/machdep.c +++ b/sys/arch/riscv64/riscv64/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.33 2023/12/04 15:00:09 claudio Exp $ */ +/* $OpenBSD: machdep.c,v 1.34 2024/01/23 19:51:10 kettenis Exp $ */ /* * Copyright (c) 2014 Patrick Wildt @@ -912,7 +912,8 @@ pmap_bootstrap_bs_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size, *bshp = (bus_space_handle_t)(va + (bpa - startpa)); for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) - pmap_kenter_pa(va, pa, PROT_READ | PROT_WRITE); + pmap_kenter_cache(va, pa, PROT_READ | PROT_WRITE, + PMAP_CACHE_DEV); virtual_avail = va; diff --git a/sys/arch/riscv64/riscv64/pmap.c b/sys/arch/riscv64/riscv64/pmap.c index 1e33584f729..485f7e25e63 100644 --- a/sys/arch/riscv64/riscv64/pmap.c +++ b/sys/arch/riscv64/riscv64/pmap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap.c,v 1.37 2023/12/13 18:26:41 jca Exp $ */ +/* $OpenBSD: pmap.c,v 1.38 2024/01/23 19:51:10 kettenis Exp $ */ /* * Copyright (c) 2019-2020 Brian Bamsch @@ -216,6 +216,8 @@ vaddr_t zero_page; vaddr_t copy_src_page; vaddr_t copy_dst_page; +#define CPU_VENDOR_THEAD 0x5b7 + struct pool pmap_pmap_pool; struct pool pmap_pted_pool; struct pool pmap_vp_pool; @@ -299,6 +301,11 @@ const pt_entry_t ap_bits_kern[8] = { [PROT_EXEC|PROT_WRITE|PROT_READ] = PTE_A|PTE_X|PTE_R|PTE_D|PTE_W, }; +/* PBMT encodings for the Svpmbt modes. */ +uint64_t pmap_pma; +uint64_t pmap_nc; +uint64_t pmap_io; + /* * This is used for pmap_kernel() mappings, they are not to be removed * from the vp table because they were statically initialized at the @@ -769,8 +776,6 @@ pmap_fill_pte(pmap_t pm, vaddr_t va, paddr_t pa, struct pte_desc *pted, switch (cache) { case PMAP_CACHE_WB: break; - 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); @@ -778,7 +783,7 @@ pmap_fill_pte(pmap_t pm, vaddr_t va, paddr_t pa, struct pte_desc *pted, case PMAP_CACHE_DEV: break; default: - panic("pmap_fill_pte:invalid cache mode"); + panic("%s: invalid cache mode", __func__); } pted->pted_va |= cache; @@ -1177,9 +1182,9 @@ pmap_bootstrap_dmap(vaddr_t kern_l1, paddr_t min_pa, paddr_t max_pa) /* gigapages */ pn = (pa / PAGE_SIZE); - entry = PTE_KERN; + entry = PTE_KERN | pmap_pma; entry |= (pn << PTE_PPN0_S); - atomic_store_64(&l1[l1_slot], entry); + l1[l1_slot] = entry; } sfence_vma(); @@ -1198,8 +1203,27 @@ 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; + uint64_t marchid, mimpid; + uint32_t mvendorid; void *node; + mvendorid = sbi_get_mvendorid(); + marchid = sbi_get_marchid(); + mimpid = sbi_get_mimpid(); + + /* + * The T-Head cores implement a page attributes extension that + * violates the RISC-V privileged architecture specification. + * Work around this as best as we can by adding the + * appropriate page attributes in a way that is mostly + * compatible with the Svpbmt extension. + */ + if (mvendorid == CPU_VENDOR_THEAD && marchid == 0 && mimpid == 0) { + pmap_pma = PTE_THEAD_C | PTE_THEAD_B | PTE_THEAD_SH; + pmap_nc = PTE_THEAD_B | PTE_THEAD_SH; + pmap_io = PTE_THEAD_SO | PTE_THEAD_SH; + } + node = fdt_find_node("/"); if (fdt_is_compatible(node, "starfive,jh7100")) { pmap_cached_start = 0x0080000000ULL; @@ -1604,15 +1628,30 @@ pmap_pte_insert(struct pte_desc *pted) void pmap_pte_update(struct pte_desc *pted, uint64_t *pl3) { - pt_entry_t pte, access_bits; + uint64_t pte, access_bits; pmap_t pm = pted->pted_pmap; + uint64_t attr = 0; + + switch (pted->pted_va & PMAP_CACHE_BITS) { + case PMAP_CACHE_WB: + attr |= pmap_pma; + break; + case PMAP_CACHE_CI: + attr |= pmap_nc; + break; + case PMAP_CACHE_DEV: + attr |= pmap_io; + break; + default: + panic("%s: invalid cache mode", __func__); + } if (pm->pm_privileged) access_bits = ap_bits_kern[pted->pted_pte & PROT_MASK]; else access_bits = ap_bits_user[pted->pted_pte & PROT_MASK]; - pte = VP_Lx(pted->pted_pte) | access_bits | PTE_V; + pte = VP_Lx(pted->pted_pte) | attr | access_bits | PTE_V; *pl3 = access_bits ? pte : 0; }