Skip to content

Commit de08c0b

Browse files
committed
Deal with the non-standard XTheadMae (Memory Attribute Extensions)
present on some T-Head CPU cores, notably the one found in the Allwinner D1 SoC. This extension allows memory attributes (cacheable, bufferable, strongly-ordered, etc.) to be specified on a per-mapping basis. Alas, it has two unfortunate properties: - It uses the same bits as the standard Svpbmt (Page Based Memory Types) extension, and the bits are completely incompatible. - Unlike Svpbmt, which if none of its extension bits are set in the PTE, results in rational behavior, if you don't set the XTheadMae attibutes in the PTE correctly, the system will blow up in your face in interesting and unpredictable ways. So, we have to probe for XTheadMae early, when we're setting up the initial MMU tables so that the kernel is mapped correctly when the MMU is enabled, and then we probe for it again to set some globals that are used when creating PTEs for new kernel and user mappings going forward. Luckily, there are combinations of XTheadMae attributes that map reasonably well to the Svpbmt types, so Svpbmt is used as the abstraction. With this, my D1 Nezha board boots to the root device prompt. \o/
1 parent f1a1e2c commit de08c0b

9 files changed

Lines changed: 180 additions & 26 deletions

File tree

sys/arch/riscv/include/pmap.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $NetBSD: pmap.h,v 1.24 2024/08/04 08:16:25 skrll Exp $ */
1+
/* $NetBSD: pmap.h,v 1.25 2025/10/12 04:08:26 thorpej Exp $ */
22

33
/*
44
* Copyright (c) 2014, 2019, 2021 The NetBSD Foundation, Inc.
@@ -153,6 +153,7 @@ void pmap_md_tlb_info_attach(struct pmap_tlb_info *, struct cpu_info *);
153153
void pmap_md_xtab_activate(struct pmap *, struct lwp *);
154154
void pmap_md_xtab_deactivate(struct pmap *);
155155

156+
void pmap_probe_pbmt(void);
156157
void pmap_bootstrap(vaddr_t, vaddr_t);
157158

158159
vsize_t pmap_kenter_range(vaddr_t, paddr_t, vsize_t, vm_prot_t, u_int);

sys/arch/riscv/include/pte.h

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $NetBSD: pte.h,v 1.14 2024/10/12 12:27:33 skrll Exp $ */
1+
/* $NetBSD: pte.h,v 1.15 2025/10/12 04:08:26 thorpej Exp $ */
22

33
/*
44
* Copyright (c) 2014, 2019, 2021 The NetBSD Foundation, Inc.
@@ -62,6 +62,36 @@ typedef uint32_t pd_entry_t;
6262
#define PTE_PBMT __BITS(62, 61) // Svpbmt
6363
#define PTE_reserved0 __BITS(60, 54) //
6464

65+
/*
66+
* Svpbmt (Page Based Memory Types) extension:
67+
*
68+
* PMA --> adhere to physical memory attributes
69+
* NC --> non-cacheable, idempotent, weakly-ordered
70+
* IO --> non-cacheable, non-idempotent, strongly-ordered
71+
*/
72+
#define PTE_PBMT_PMA __SHIFTIN(0, PTE_PBMT)
73+
#define PTE_PBMT_NC __SHIFTIN(1, PTE_PBMT)
74+
#define PTE_PBMT_IO __SHIFTIN(2, PTE_PBMT)
75+
76+
/* XTheadMae (Memory Attribute Extensions) */
77+
#define PTE_XMAE __BITS(63,59)
78+
#define PTE_XMAE_SO __BIT(63) // Strong Order
79+
#define PTE_XMAE_C __BIT(62) // Cacheable
80+
#define PTE_XMAE_B __BIT(61) // Bufferable
81+
#define PTE_XMAE_SH __BIT(60) // Shareable
82+
#define PTE_XMAE_T __BIT(59) // Trustable
83+
84+
/*
85+
* Map to the rough PBMT equivalent:
86+
*
87+
* PMA (i.e. no specific attribute) --> C B SH
88+
* NC --> B SH
89+
* IO --> SO SH
90+
*/
91+
#define PTE_XMAE_PMA ( PTE_XMAE_C | PTE_XMAE_B | PTE_XMAE_SH)
92+
#define PTE_XMAE_NC ( PTE_XMAE_B | PTE_XMAE_SH)
93+
#define PTE_XMAE_IO (PTE_XMAE_SO | PTE_XMAE_SH)
94+
6595
/* Software PTE bits. */
6696
#define PTE_RSW __BITS(9, 8)
6797
#define PTE_WIRED __BIT(9)
@@ -87,7 +117,7 @@ typedef uint32_t pd_entry_t;
87117
#define PTE_ISLEAF_P(pte) (((pte) & PTE_RWX) != 0)
88118

89119
#define PA_TO_PTE(pa) (((pa) >> PGSHIFT) << PTE_PPN_SHIFT)
90-
#define PTE_TO_PA(pte) (((pte) >> PTE_PPN_SHIFT) << PGSHIFT)
120+
#define PTE_TO_PA(pte) (__SHIFTOUT((pte), PTE_PPN) << PGSHIFT)
91121

92122
#if defined(_KERNEL)
93123

@@ -186,6 +216,8 @@ pte_flag_bits(struct vm_page_md *mdpg, int flags, bool kernel_p)
186216
return 0;
187217
}
188218

219+
pt_entry_t pte_enter_flags_to_pbmt(int);
220+
189221
static inline pt_entry_t
190222
pte_make_enter(paddr_t pa, struct vm_page_md *mdpg, vm_prot_t prot,
191223
int flags, bool kernel_p)
@@ -195,6 +227,7 @@ pte_make_enter(paddr_t pa, struct vm_page_md *mdpg, vm_prot_t prot,
195227
pte |= kernel_p ? PTE_KERN : PTE_USER;
196228
pte |= pte_flag_bits(mdpg, flags, kernel_p);
197229
pte |= pte_prot_bits(mdpg, prot, kernel_p);
230+
pte |= pte_enter_flags_to_pbmt(flags);
198231

199232
if (mdpg != NULL) {
200233

@@ -232,6 +265,7 @@ pte_make_kenter_pa(paddr_t pa, struct vm_page_md *mdpg, vm_prot_t prot,
232265
pte |= PTE_KERN | PTE_HARDWIRED | PTE_WIRED;
233266
pte |= pte_flag_bits(NULL, flags, true);
234267
pte |= pte_prot_bits(NULL, prot, true);
268+
pte |= pte_enter_flags_to_pbmt(flags);
235269

236270
return pte;
237271
}

sys/arch/riscv/include/sysreg.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $NetBSD: sysreg.h,v 1.33 2024/05/14 15:17:57 riastradh Exp $ */
1+
/* $NetBSD: sysreg.h,v 1.34 2025/10/12 04:08:26 thorpej Exp $ */
22

33
/*
44
* Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -38,6 +38,12 @@
3838

3939
#include <riscv/reg.h>
4040

41+
/* CPU vendors (get CSR value from SBI). */
42+
#define CPU_VENDOR_SIFIVE 0x489
43+
#define CPU_SIFIVE_ARCH_7SERIES 0x8000000000000007
44+
45+
#define CPU_VENDOR_THEAD 0x5b7
46+
4147
#define FCSR_FMASK 0 // no exception bits
4248
#define FCSR_FRM __BITS(7, 5)
4349
#define FCSR_FRM_RNE 0b000 // Round Nearest, ties to Even
@@ -333,4 +339,16 @@ csr_asid_write(uint32_t asid)
333339
csr_satp_write(satp);
334340
}
335341

342+
/* Non-standard CSRs. */
343+
static inline uintptr_t
344+
csr_thead_sxstatus_read(void)
345+
{
346+
uintptr_t __rv;
347+
asm volatile("csrr %0, 0x5c0" : "=r"(__rv) :: "memory");
348+
return __rv;
349+
}
350+
351+
#define TX_SXSTATUS_MAEE __BIT(21)
352+
#define TH_SXSTATUS_THEADISAEE __BIT(22)
353+
336354
#endif /* _RISCV_SYSREG_H_ */

sys/arch/riscv/riscv/bus_space.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $NetBSD: bus_space.c,v 1.2 2023/05/07 12:41:48 skrll Exp $ */
1+
/* $NetBSD: bus_space.c,v 1.3 2025/10/12 04:08:26 thorpej Exp $ */
22

33
/*-
44
* Copyright (c) 2022 The NetBSD Foundation, Inc.
@@ -32,7 +32,7 @@
3232
#include "opt_console.h"
3333

3434
#include <sys/cdefs.h>
35-
__KERNEL_RCSID(1, "$NetBSD: bus_space.c,v 1.2 2023/05/07 12:41:48 skrll Exp $");
35+
__KERNEL_RCSID(1, "$NetBSD: bus_space.c,v 1.3 2025/10/12 04:08:26 thorpej Exp $");
3636

3737
#include <sys/param.h>
3838
#include <sys/systm.h>
@@ -326,10 +326,8 @@ generic_bs_map(void *t, bus_addr_t bpa, bus_size_t size, int flag,
326326
else if ((flag & _RISCV_BUS_SPACE_MAP_STRONGLY_ORDERED) != 0)
327327
pmapflags = PMAP_DEV_NP;
328328
else
329-
pmapflags = PMAP_DEV;
330329
#endif
331-
332-
pmapflags = 0;
330+
pmapflags = PMAP_DEV;
333331

334332
for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) {
335333
pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE, pmapflags);

sys/arch/riscv/riscv/cpu.c

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $NetBSD: cpu.c,v 1.9 2025/10/07 06:40:33 skrll Exp $ */
1+
/* $NetBSD: cpu.c,v 1.10 2025/10/12 04:08:26 thorpej Exp $ */
22

33
/*-
44
* Copyright (c) 2023 The NetBSD Foundation, Inc.
@@ -32,7 +32,7 @@
3232
#include "opt_multiprocessor.h"
3333

3434
#include <sys/cdefs.h>
35-
__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.9 2025/10/07 06:40:33 skrll Exp $");
35+
__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.10 2025/10/12 04:08:26 thorpej Exp $");
3636

3737
#include <sys/param.h>
3838

@@ -46,6 +46,7 @@ __KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.9 2025/10/07 06:40:33 skrll Exp $");
4646
#include <riscv/cpuvar.h>
4747
#include <riscv/machdep.h>
4848
#include <riscv/sbi.h>
49+
#include <riscv/sysreg.h>
4950

5051
#ifdef MULTIPROCESSOR
5152
#define NCPUINFO MAXCPUS
@@ -65,20 +66,14 @@ void (*cpu_sdcache_wb_range)(vaddr_t, paddr_t, psize_t) = cache_nullop;
6566
u_int riscv_dcache_align = CACHE_LINE_SIZE;
6667
u_int riscv_dcache_align_mask = CACHE_LINE_SIZE - 1;
6768

68-
#define CPU_VENDOR_SIFIVE 0x489
69-
70-
#define CPU_ARCH_7SERIES 0x8000000000000007
71-
72-
#define CPU_VENDOR_THEAD 0x5b7
73-
7469
struct cpu_arch {
7570
uint64_t ca_id;
7671
const char *ca_name;
7772
};
7873

7974
struct cpu_arch cpu_arch_sifive[] = {
8075
{
81-
.ca_id = CPU_ARCH_7SERIES,
76+
.ca_id = CPU_SIFIVE_ARCH_7SERIES,
8277
.ca_name = "7-Series Processor (E7, S7, U7 series)",
8378
},
8479
{ }, // terminator

sys/arch/riscv/riscv/genassym.cf

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# $NetBSD: genassym.cf,v 1.16 2024/04/06 10:08:54 skrll Exp $
1+
# $NetBSD: genassym.cf,v 1.17 2025/10/12 04:08:26 thorpej Exp $
22

33
#-
44
# Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -227,6 +227,9 @@ define PTE_V PTE_V
227227
define PTE_KERN PTE_KERN
228228
define PTE_HARDWIRED PTE_HARDWIRED
229229

230+
define PTE_XMAE_PMA PTE_XMAE_PMA
231+
define PTE_XMAE_IO PTE_XMAE_IO
232+
230233
#define PTE_PPN0_S PTE_PPN0_S
231234
#define PTE_PPN1_S PTE_PPN1_S
232235
#define PTE_PPN2_S PTE_PPN2_S
@@ -237,6 +240,11 @@ define PTE_PPN_SHIFT PTE_PPN_SHIFT
237240
define PM_PDETAB offsetof(struct pmap, pm_pdetab)
238241
define PM_MD_PPN offsetof(struct pmap, pm_md.md_ppn)
239242

243+
define CPU_VENDOR_THEAD CPU_VENDOR_THEAD
244+
define TX_SXSTATUS_MAEE TX_SXSTATUS_MAEE
245+
246+
define SBI_EID_BASE SBI_EID_BASE
247+
define SBI_FID_BASE_GETMVENDORID SBI_FID_BASE_GETMVENDORID
240248
define SBI_LEGACY_CONSOLE_PUTCHAR SBI_LEGACY_CONSOLE_PUTCHAR
241249

242250
# for bus_space_asm

sys/arch/riscv/riscv/locore.S

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $NetBSD: locore.S,v 1.46 2025/03/02 08:14:26 skrll Exp $ */
1+
/* $NetBSD: locore.S,v 1.47 2025/10/12 04:08:26 thorpej Exp $ */
22

33
/*-
44
* Copyright (c) 2014, 2022 The NetBSD Foundation, Inc.
@@ -118,6 +118,45 @@ ENTRY_NP(start)
118118
PTR_LA s5, _C_LABEL(lwp0uspace)
119119
PTR_LA s6, _C_LABEL(bootstk)
120120

121+
/*
122+
* Before we construct the initial MMU tables, we need to know
123+
* if there are any extra PTE bits that we need to include.
124+
* (Grumble, mumble, T-Head XMAE).
125+
*
126+
* We'll push space for 2 PTE prototypes, and fill them with
127+
* zeros for now. sp[0] is for "regular memory", sp[1] is
128+
* for "devices".
129+
*/
130+
addi sp, sp, -(2 * SZREG)
131+
REG_S zero, 0(sp)
132+
REG_S zero, SZREG(sp)
133+
134+
/* Get the CPU vendor ID, which requires an SBI call. */
135+
VPRINTS("vendor: ")
136+
li a7, SBI_EID_BASE
137+
li a6, SBI_FID_BASE_GETMVENDORID
138+
ecall
139+
VPRINTXNL(a1)
140+
141+
#ifdef _LP64
142+
li a0, CPU_VENDOR_THEAD
143+
bne a0, a1, 9f /* not T-Head, skip */
144+
csrr a1, 0x5c0 /* read T-Head TX.SXSTATUS reg */
145+
li a0, TX_SXSTATUS_MAEE /* is MAEE bit set? */
146+
and a0, a0, a1
147+
beqz a0, .Lpdetab /* nope, carry on */
148+
VPRINTS("extsn: T-Head XMAE\r\n")
149+
li a0, PTE_XMAE_PMA
150+
REG_S a0, 0(sp)
151+
li a0, PTE_XMAE_IO
152+
REG_S a0, SZREG(sp)
153+
j .Lpdetab /* done. */
154+
9:
155+
#endif /* _LP64 */
156+
157+
/* Next vendor quirk check goes here. */
158+
159+
.Lpdetab:
121160
/*
122161
* Our load address is not fixed, but our VA is. We need to construct
123162
* an initial PDETAB.
@@ -218,6 +257,8 @@ ENTRY_NP(start)
218257
li s5, (VM_KERNEL_SIZE >> SEGSHIFT) // # of megapages
219258
li s6, (NBSEG >> (PGSHIFT - PTE_PPN_SHIFT)) // load for ease
220259
li s7, PTE_KERN | PTE_HARDWIRED | PTE_R | PTE_W | PTE_X
260+
REG_L a0, 0(sp)
261+
or s7, s7, a0
221262

222263
//
223264
// Fill in the PDEs for kernel.
@@ -243,6 +284,8 @@ ENTRY_NP(start)
243284
add s9, s2, t1
244285

245286
li s7, PTE_KERN | PTE_HARDWIRED | PTE_R | PTE_W
287+
REG_L a0, 0(sp)
288+
or s7, s7, a0
246289

247290
//
248291
// Fill in the PDE for the DTB. Only do one - if any more are required
@@ -261,6 +304,9 @@ ENTRY_NP(start)
261304
REG_S s0, 0(s9)
262305

263306
#ifdef CONSADDR
307+
li s7, PTE_KERN | PTE_HARDWIRED | PTE_R | PTE_W
308+
REG_L a0, SZREG(sp)
309+
or s7, s7, a0
264310
li t1, ((VM_KERNEL_IO_BASE >> SEGSHIFT) & (NPDEPG - 1)) * SZREG
265311
add s9, s2, t1
266312

@@ -279,6 +325,9 @@ ENTRY_NP(start)
279325
REG_S s0, 0(s9)
280326
#endif
281327

328+
/* Pop the PTE prototypes pushed way up above. */
329+
addi sp, sp, (2 * SZREG)
330+
282331
li a0, 'P'
283332
call _C_LABEL(uartputc)
284333

0 commit comments

Comments
 (0)