Skip to content

Commit aa4f879

Browse files
committed
xtensa: allow flushing auto-refill DTLBs on page table swap
This adds a new kconfig and corresponding code to allow flushing auto-refill data TLBs when page tables are swapped (e.g. during context switching). This is mainly used to avoid multi-hit TLB exception raised by certain memory access pattern. If memory is only marked for user mode access but not inside a memory domain, accessing that page in kernel mode would result in a TLB being filled with kernel ASID. When going back into user mode, access to the memory would result in another TLB being filled with the user mode ASID. Now there are two entries on the same memory page, and the multi-hit TLB exception will be raised if that memory page is accessed. This type of access is better served using memory partition and memory domain to share date. However, this type of access is not prohibited but highly discouraged. Wrapping the code in kconfig is simply because of the execution penalty as there will be unnecessary TLB refilling being done. So only enable this if necessary. Fixes #88772 Signed-off-by: Daniel Leung <daniel.leung@intel.com>
1 parent f070786 commit aa4f879

File tree

6 files changed

+58
-0
lines changed

6 files changed

+58
-0
lines changed

arch/xtensa/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,13 @@ config PRIVILEGED_STACK_SIZE
226226
# Must be multiple of CONFIG_MMU_PAGE_SIZE
227227
default 4096
228228

229+
config XTENSA_MMU_FLUSH_AUTOREFILL_DTLBS_ON_SWAP
230+
bool "Flush all auto-refill data TLBs when swapping page tables"
231+
depends on USERSPACE
232+
help
233+
This flushes (invalidates) all auto-refill data TLBs when page
234+
tables are swapped.
235+
229236
endif # XTENSA_MMU
230237

231238
endif # CPU_HAS_MMU

arch/xtensa/core/ptables.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,4 +1122,20 @@ int arch_buffer_validate(const void *addr, size_t size, int write)
11221122
return mem_buffer_validate(addr, size, write, XTENSA_MMU_USER_RING);
11231123
}
11241124

1125+
#ifdef CONFIG_XTENSA_MMU_FLUSH_AUTOREFILL_DTLBS_ON_SWAP
1126+
/* This is only used when swapping page tables and auto-refill DTLBs
1127+
* needing to be invalidated. Otherwise, SWAP_PAGE_TABLE assembly
1128+
* is used to avoid a function call.
1129+
*/
1130+
void xtensa_swap_update_page_tables(struct k_thread *incoming)
1131+
{
1132+
struct arch_mem_domain *domain =
1133+
&(incoming->mem_domain_info.mem_domain->arch);
1134+
1135+
xtensa_mmu_set_paging(domain);
1136+
1137+
xtensa_dtlb_autorefill_invalidate();
1138+
}
1139+
#endif
1140+
11251141
#endif /* CONFIG_USERSPACE */

arch/xtensa/core/userspace.S

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,8 +270,12 @@ xtensa_userspace_enter:
270270

271271
l32i a6, a1, 24
272272
#ifdef CONFIG_XTENSA_MMU
273+
#ifdef CONFIG_XTENSA_MMU_FLUSH_AUTOREFILL_DTLBS_ON_SWAP
274+
call4 xtensa_swap_update_page_tables
275+
#else
273276
SWAP_PAGE_TABLE a6, a3, a7
274277
#endif
278+
#endif
275279
#ifdef CONFIG_XTENSA_MPU
276280
call4 xtensa_mpu_map_write
277281
#endif

arch/xtensa/core/xtensa_asm2_util.S

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,12 @@ xtensa_switch:
251251
rsr a6, ZSR_CPU
252252
l32i a6, a6, ___cpu_t_current_OFFSET
253253
#ifdef CONFIG_XTENSA_MMU
254+
#ifdef CONFIG_XTENSA_MMU_FLUSH_AUTOREFILL_DTLBS_ON_SWAP
255+
call4 xtensa_swap_update_page_tables
256+
#else
254257
SWAP_PAGE_TABLE a6, a4, a7
255258
#endif
259+
#endif
256260
#ifdef CONFIG_XTENSA_MPU
257261
call4 xtensa_mpu_map_write
258262
#endif

arch/xtensa/include/xtensa_asm2_s.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,8 +395,12 @@ _xstack_call0_\@:
395395
l32i a6, a6, ___cpu_t_current_OFFSET
396396

397397
#ifdef CONFIG_XTENSA_MMU
398+
#ifdef CONFIG_XTENSA_MMU_FLUSH_AUTOREFILL_DTLBS_ON_SWAP
399+
call4 xtensa_swap_update_page_tables
400+
#else
398401
SWAP_PAGE_TABLE a6, a3, a7
399402
#endif
403+
#endif
400404
#ifdef CONFIG_XTENSA_MPU
401405
call4 xtensa_mpu_map_write
402406
#endif

arch/xtensa/include/xtensa_mmu_priv.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,29 @@ static inline void xtensa_tlb_autorefill_invalidate(void)
364364
__asm__ volatile("isync");
365365
}
366366

367+
/**
368+
* @brief Invalidate all autorefill DTLB entries.
369+
*
370+
* This should be used carefully since all refill entries in the data
371+
* TLBs are affected. The current stack page will be repopulated by
372+
* this code as it returns.
373+
*/
374+
static inline void xtensa_dtlb_autorefill_invalidate(void)
375+
{
376+
uint8_t way, i, entries;
377+
378+
entries = BIT(XCHAL_DTLB_ARF_ENTRIES_LOG2);
379+
380+
for (way = 0; way < XTENSA_MMU_NUM_TLB_AUTOREFILL_WAYS; way++) {
381+
for (i = 0; i < entries; i++) {
382+
uint32_t entry = way + (i << XTENSA_MMU_PTE_PPN_SHIFT);
383+
384+
xtensa_dtlb_entry_invalidate(entry);
385+
}
386+
}
387+
__asm__ volatile("isync");
388+
}
389+
367390
/**
368391
* @brief Set the page tables.
369392
*

0 commit comments

Comments
 (0)