Skip to content

Commit d3a126c

Browse files
dcpleungcfriedt
authored andcommitted
xtensa: userspace: handle load/store ring exception
When a page can be accessed by both kernel and user threads, the autofill DTLB may contain an entry for kernel thread. This will result in load/store ring exception when it is accessed by user thread later. In this case, we need to invalidate all associated TLBs related to kernel access so hardware can reload the page table the correct permission for user thread. Signed-off-by: Daniel Leung <daniel.leung@intel.com>
1 parent 9f0f596 commit d3a126c

File tree

4 files changed

+80
-0
lines changed

4 files changed

+80
-0
lines changed

arch/xtensa/core/ptables.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <zephyr/kernel/mm.h>
1212
#include <zephyr/toolchain.h>
1313
#include <xtensa/corebits.h>
14+
#include <xtensa_asm2_context.h>
1415
#include <xtensa_mmu_priv.h>
1516

1617
#include <kernel_arch_func.h>
@@ -1172,6 +1173,53 @@ int arch_buffer_validate(const void *addr, size_t size, int write)
11721173
return mem_buffer_validate(addr, size, write, XTENSA_MMU_USER_RING);
11731174
}
11741175

1176+
bool xtensa_exc_load_store_ring_error_check(void *bsa_p)
1177+
{
1178+
uintptr_t ring, vaddr;
1179+
_xtensa_irq_bsa_t *bsa = (_xtensa_irq_bsa_t *)bsa_p;
1180+
1181+
ring = (bsa->ps & XCHAL_PS_RING_MASK) >> XCHAL_PS_RING_SHIFT;
1182+
1183+
if (ring != XTENSA_MMU_USER_RING) {
1184+
return true;
1185+
}
1186+
1187+
vaddr = bsa->excvaddr;
1188+
1189+
if (arch_buffer_validate((void *)vaddr, sizeof(uint32_t), false) != 0) {
1190+
/* User thread DO NOT have access to this memory according to
1191+
* page table. so this is a true access violation.
1192+
*/
1193+
return true;
1194+
}
1195+
1196+
/* User thread has access to this memory according to
1197+
* page table. so this is not a true access violation.
1198+
*
1199+
* Now we need to find all associated auto-refilled DTLBs
1200+
* and invalidate them. So that hardware can reload
1201+
* from page table with correct permission for user
1202+
* thread.
1203+
*/
1204+
while (true) {
1205+
uint32_t dtlb_entry = xtensa_dtlb_probe((void *)vaddr);
1206+
1207+
if ((dtlb_entry & XTENSA_MMU_PDTLB_HIT) != XTENSA_MMU_PDTLB_HIT) {
1208+
/* No more DTLB entry found. */
1209+
return false;
1210+
}
1211+
1212+
if ((dtlb_entry & XTENSA_MMU_PDTLB_WAY_MASK) >=
1213+
XTENSA_MMU_NUM_TLB_AUTOREFILL_WAYS) {
1214+
return false;
1215+
}
1216+
1217+
xtensa_dtlb_entry_invalidate_sync(dtlb_entry);
1218+
}
1219+
1220+
return false;
1221+
}
1222+
11751223
#ifdef CONFIG_XTENSA_MMU_FLUSH_AUTOREFILL_DTLBS_ON_SWAP
11761224
/* This is only used when swapping page tables and auto-refill DTLBs
11771225
* needing to be invalidated. Otherwise, SWAP_PAGE_TABLE assembly

arch/xtensa/core/vector_handlers.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,13 @@ void *xtensa_excint1_c(void *esf)
630630
xtensa_lazy_hifi_load(thread->arch.hifi_regs);
631631
break;
632632
#endif /* CONFIG_XTENSA_LAZY_HIFI_SHARING */
633+
#if defined(CONFIG_XTENSA_MMU) && defined(CONFIG_USERSPACE)
634+
case EXCCAUSE_LOAD_STORE_RING:
635+
if (!xtensa_exc_load_store_ring_error_check(bsa)) {
636+
break;
637+
}
638+
__fallthrough;
639+
#endif /* CONFIG_XTENSA_MMU && CONFIG_USERSPACE */
633640
default:
634641
reason = K_ERR_CPU_EXCEPTION;
635642

arch/xtensa/include/xtensa_internal.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,22 @@ void xtensa_userspace_enter(k_thread_entry_t user_entry,
7474
*/
7575
bool xtensa_mem_kernel_has_access(const void *addr, size_t size, int write);
7676

77+
/**
78+
* @brief Check if it is a true load/store ring exception.
79+
*
80+
* When a page can be accessed by both kernel and user threads, the autofill DTLB
81+
* may contain an entry for kernel thread. This will result in load/store ring
82+
* exception when it is accessed by user thread later. In this case, this will
83+
* invalidate all associated TLBs related to kernel access so hardware can reload
84+
* the page table the correct permission for user thread.
85+
*
86+
* @param bsa_p Pointer to BSA struct.
87+
*
88+
* @retval True This is a true access violation.
89+
* @retval False Access violation is due to incorrectly cached auto-refilled TLB.
90+
*/
91+
bool xtensa_exc_load_store_ring_error_check(void *bsa_p);
92+
7793
/**
7894
* @}
7995
*/

arch/xtensa/include/xtensa_mmu_priv.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,15 @@
213213
*/
214214
#define XTENSA_MMU_PDTLB_HIT BIT(4)
215215

216+
/**
217+
* PDTLB WAY mask.
218+
*
219+
* For more information see
220+
* Xtensa Instruction Set Architecture (ISA) Reference Manual
221+
* 4.6.5.7 Formats for Probing MMU Option TLB Entries
222+
*/
223+
#define XTENSA_MMU_PDTLB_WAY_MASK 0xFU
224+
216225
/**
217226
* Virtual address where the page table is mapped
218227
*/

0 commit comments

Comments
 (0)