Skip to content

Commit 0115848

Browse files
committed
LoongArch: Introduce hardware page table walker
Loongson-3A6000 and newer processors have hardware page table walker (PTW) support. PTW can handle all fastpaths of TLBI/TLBL/TLBS/TLBM exceptions by hardware, software only need to handle slowpaths (page faults). BTW, PTW doesn't append _PAGE_MODIFIED for page table entries, so we change pmd_dirty() and pte_dirty() to also check _PAGE_DIRTY for the "dirty" attribute. Signed-off-by: Liang Gao <[email protected]> Signed-off-by: Jun Yi <[email protected]> Signed-off-by: Huacai Chen <[email protected]>
1 parent e031a5f commit 0115848

File tree

10 files changed

+56
-7
lines changed

10 files changed

+56
-7
lines changed

arch/loongarch/include/asm/cpu-features.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,6 @@
6464
#define cpu_has_eiodecode cpu_opt(LOONGARCH_CPU_EIODECODE)
6565
#define cpu_has_guestid cpu_opt(LOONGARCH_CPU_GUESTID)
6666
#define cpu_has_hypervisor cpu_opt(LOONGARCH_CPU_HYPERVISOR)
67-
67+
#define cpu_has_ptw cpu_opt(LOONGARCH_CPU_PTW)
6868

6969
#endif /* __ASM_CPU_FEATURES_H */

arch/loongarch/include/asm/cpu.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ enum cpu_type_enum {
9898
#define CPU_FEATURE_EIODECODE 23 /* CPU has EXTIOI interrupt pin decode mode */
9999
#define CPU_FEATURE_GUESTID 24 /* CPU has GuestID feature */
100100
#define CPU_FEATURE_HYPERVISOR 25 /* CPU has hypervisor (running in VM) */
101+
#define CPU_FEATURE_PTW 26 /* CPU has hardware page table walker */
101102

102103
#define LOONGARCH_CPU_CPUCFG BIT_ULL(CPU_FEATURE_CPUCFG)
103104
#define LOONGARCH_CPU_LAM BIT_ULL(CPU_FEATURE_LAM)
@@ -125,5 +126,6 @@ enum cpu_type_enum {
125126
#define LOONGARCH_CPU_EIODECODE BIT_ULL(CPU_FEATURE_EIODECODE)
126127
#define LOONGARCH_CPU_GUESTID BIT_ULL(CPU_FEATURE_GUESTID)
127128
#define LOONGARCH_CPU_HYPERVISOR BIT_ULL(CPU_FEATURE_HYPERVISOR)
129+
#define LOONGARCH_CPU_PTW BIT_ULL(CPU_FEATURE_PTW)
128130

129131
#endif /* _ASM_CPU_H */

arch/loongarch/include/asm/loongarch.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ __asm__(".macro parse_r var r\n\t"
135135
#define CPUCFG2_MIPSBT BIT(20)
136136
#define CPUCFG2_LSPW BIT(21)
137137
#define CPUCFG2_LAM BIT(22)
138+
#define CPUCFG2_PTW BIT(24)
138139

139140
#define LOONGARCH_CPUCFG3 0x3
140141
#define CPUCFG3_CCDMA BIT(0)
@@ -412,6 +413,9 @@ __asm__(".macro parse_r var r\n\t"
412413
#define CSR_PWCTL0_PTBASE (_ULCAST_(0x1f) << CSR_PWCTL0_PTBASE_SHIFT)
413414

414415
#define LOONGARCH_CSR_PWCTL1 0x1d /* PWCtl1 */
416+
#define CSR_PWCTL1_PTW_SHIFT 24
417+
#define CSR_PWCTL1_PTW_WIDTH 1
418+
#define CSR_PWCTL1_PTW (_ULCAST_(0x1) << CSR_PWCTL1_PTW_SHIFT)
415419
#define CSR_PWCTL1_DIR3WIDTH_SHIFT 18
416420
#define CSR_PWCTL1_DIR3WIDTH_WIDTH 5
417421
#define CSR_PWCTL1_DIR3WIDTH (_ULCAST_(0x1f) << CSR_PWCTL1_DIR3WIDTH_SHIFT)

arch/loongarch/include/asm/pgtable.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ extern pgd_t invalid_pg_dir[];
362362
*/
363363
static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; }
364364
static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
365-
static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_MODIFIED; }
365+
static inline int pte_dirty(pte_t pte) { return pte_val(pte) & (_PAGE_DIRTY | _PAGE_MODIFIED); }
366366

367367
static inline pte_t pte_mkold(pte_t pte)
368368
{
@@ -506,7 +506,7 @@ static inline pmd_t pmd_wrprotect(pmd_t pmd)
506506

507507
static inline int pmd_dirty(pmd_t pmd)
508508
{
509-
return !!(pmd_val(pmd) & _PAGE_MODIFIED);
509+
return !!(pmd_val(pmd) & (_PAGE_DIRTY | _PAGE_MODIFIED));
510510
}
511511

512512
static inline pmd_t pmd_mkclean(pmd_t pmd)

arch/loongarch/include/asm/tlb.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,9 @@ extern void handle_tlb_store(void);
158158
extern void handle_tlb_modify(void);
159159
extern void handle_tlb_refill(void);
160160
extern void handle_tlb_protect(void);
161+
extern void handle_tlb_load_ptw(void);
162+
extern void handle_tlb_store_ptw(void);
163+
extern void handle_tlb_modify_ptw(void);
161164

162165
extern void dump_tlb_all(void);
163166
extern void dump_tlb_regs(void);

arch/loongarch/include/uapi/asm/hwcap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,6 @@
1616
#define HWCAP_LOONGARCH_LBT_X86 (1 << 10)
1717
#define HWCAP_LOONGARCH_LBT_ARM (1 << 11)
1818
#define HWCAP_LOONGARCH_LBT_MIPS (1 << 12)
19+
#define HWCAP_LOONGARCH_PTW (1 << 13)
1920

2021
#endif /* _UAPI_ASM_HWCAP_H */

arch/loongarch/kernel/cpu-probe.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,10 @@ static void cpu_probe_common(struct cpuinfo_loongarch *c)
136136
c->options |= LOONGARCH_CPU_CRYPTO;
137137
elf_hwcap |= HWCAP_LOONGARCH_CRYPTO;
138138
}
139+
if (config & CPUCFG2_PTW) {
140+
c->options |= LOONGARCH_CPU_PTW;
141+
elf_hwcap |= HWCAP_LOONGARCH_PTW;
142+
}
139143
if (config & CPUCFG2_LVZP) {
140144
c->options |= LOONGARCH_CPU_LVZ;
141145
elf_hwcap |= HWCAP_LOONGARCH_LVZ;

arch/loongarch/kernel/proc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
8080
if (cpu_has_crc32) seq_printf(m, " crc32");
8181
if (cpu_has_complex) seq_printf(m, " complex");
8282
if (cpu_has_crypto) seq_printf(m, " crypto");
83+
if (cpu_has_ptw) seq_printf(m, " ptw");
8384
if (cpu_has_lvz) seq_printf(m, " lvz");
8485
if (cpu_has_lbt_x86) seq_printf(m, " lbt_x86");
8586
if (cpu_has_lbt_arm) seq_printf(m, " lbt_arm");

arch/loongarch/mm/tlb.c

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,9 @@ void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t *ptep
167167
int idx;
168168
unsigned long flags;
169169

170+
if (cpu_has_ptw)
171+
return;
172+
170173
/*
171174
* Handle debugger faulting in for debugee.
172175
*/
@@ -222,6 +225,9 @@ static void setup_ptwalker(void)
222225
pwctl0 = pte_i | pte_w << 5 | pmd_i << 10 | pmd_w << 15 | pud_i << 20 | pud_w << 25;
223226
pwctl1 = pgd_i | pgd_w << 6;
224227

228+
if (cpu_has_ptw)
229+
pwctl1 |= CSR_PWCTL1_PTW;
230+
225231
csr_write64(pwctl0, LOONGARCH_CSR_PWCTL0);
226232
csr_write64(pwctl1, LOONGARCH_CSR_PWCTL1);
227233
csr_write64((long)swapper_pg_dir, LOONGARCH_CSR_PGDH);
@@ -264,10 +270,17 @@ void setup_tlb_handler(int cpu)
264270
if (cpu == 0) {
265271
memcpy((void *)tlbrentry, handle_tlb_refill, 0x80);
266272
local_flush_icache_range(tlbrentry, tlbrentry + 0x80);
267-
set_handler(EXCCODE_TLBI * VECSIZE, handle_tlb_load, VECSIZE);
268-
set_handler(EXCCODE_TLBL * VECSIZE, handle_tlb_load, VECSIZE);
269-
set_handler(EXCCODE_TLBS * VECSIZE, handle_tlb_store, VECSIZE);
270-
set_handler(EXCCODE_TLBM * VECSIZE, handle_tlb_modify, VECSIZE);
273+
if (!cpu_has_ptw) {
274+
set_handler(EXCCODE_TLBI * VECSIZE, handle_tlb_load, VECSIZE);
275+
set_handler(EXCCODE_TLBL * VECSIZE, handle_tlb_load, VECSIZE);
276+
set_handler(EXCCODE_TLBS * VECSIZE, handle_tlb_store, VECSIZE);
277+
set_handler(EXCCODE_TLBM * VECSIZE, handle_tlb_modify, VECSIZE);
278+
} else {
279+
set_handler(EXCCODE_TLBI * VECSIZE, handle_tlb_load_ptw, VECSIZE);
280+
set_handler(EXCCODE_TLBL * VECSIZE, handle_tlb_load_ptw, VECSIZE);
281+
set_handler(EXCCODE_TLBS * VECSIZE, handle_tlb_store_ptw, VECSIZE);
282+
set_handler(EXCCODE_TLBM * VECSIZE, handle_tlb_modify_ptw, VECSIZE);
283+
}
271284
set_handler(EXCCODE_TLBNR * VECSIZE, handle_tlb_protect, VECSIZE);
272285
set_handler(EXCCODE_TLBNX * VECSIZE, handle_tlb_protect, VECSIZE);
273286
set_handler(EXCCODE_TLBPE * VECSIZE, handle_tlb_protect, VECSIZE);

arch/loongarch/mm/tlbex.S

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,13 @@ nopage_tlb_load:
190190
jr t0
191191
SYM_FUNC_END(handle_tlb_load)
192192

193+
SYM_FUNC_START(handle_tlb_load_ptw)
194+
csrwr t0, LOONGARCH_CSR_KS0
195+
csrwr t1, LOONGARCH_CSR_KS1
196+
la_abs t0, tlb_do_page_fault_0
197+
jr t0
198+
SYM_FUNC_END(handle_tlb_load_ptw)
199+
193200
SYM_FUNC_START(handle_tlb_store)
194201
csrwr t0, EXCEPTION_KS0
195202
csrwr t1, EXCEPTION_KS1
@@ -339,6 +346,13 @@ nopage_tlb_store:
339346
jr t0
340347
SYM_FUNC_END(handle_tlb_store)
341348

349+
SYM_FUNC_START(handle_tlb_store_ptw)
350+
csrwr t0, LOONGARCH_CSR_KS0
351+
csrwr t1, LOONGARCH_CSR_KS1
352+
la_abs t0, tlb_do_page_fault_1
353+
jr t0
354+
SYM_FUNC_END(handle_tlb_store_ptw)
355+
342356
SYM_FUNC_START(handle_tlb_modify)
343357
csrwr t0, EXCEPTION_KS0
344358
csrwr t1, EXCEPTION_KS1
@@ -486,6 +500,13 @@ nopage_tlb_modify:
486500
jr t0
487501
SYM_FUNC_END(handle_tlb_modify)
488502

503+
SYM_FUNC_START(handle_tlb_modify_ptw)
504+
csrwr t0, LOONGARCH_CSR_KS0
505+
csrwr t1, LOONGARCH_CSR_KS1
506+
la_abs t0, tlb_do_page_fault_1
507+
jr t0
508+
SYM_FUNC_END(handle_tlb_modify_ptw)
509+
489510
SYM_FUNC_START(handle_tlb_refill)
490511
csrwr t0, LOONGARCH_CSR_TLBRSAVE
491512
csrrd t0, LOONGARCH_CSR_PGD

0 commit comments

Comments
 (0)