diff --git a/arch/xtensa/core/offsets/offsets.c b/arch/xtensa/core/offsets/offsets.c index 12fec31cb3f..f0b75c999cc 100644 --- a/arch/xtensa/core/offsets/offsets.c +++ b/arch/xtensa/core/offsets/offsets.c @@ -71,6 +71,18 @@ GEN_OFFSET_SYM(_thread_arch_t, return_ps); GEN_OFFSET_SYM(_thread_t, switch_handle); #ifdef CONFIG_XTENSA_MMU GEN_OFFSET_SYM(_thread_arch_t, ptables); + +GEN_OFFSET_SYM(_thread_t, mem_domain_info); +GEN_OFFSET_SYM(_mem_domain_info_t, mem_domain); +GEN_OFFSET_SYM(k_mem_domain_t, arch); + +GEN_OFFSET_SYM(arch_mem_domain_t, reg_asid); +GEN_OFFSET_SYM(arch_mem_domain_t, reg_ptevaddr); +GEN_OFFSET_SYM(arch_mem_domain_t, reg_ptepin_as); +GEN_OFFSET_SYM(arch_mem_domain_t, reg_ptepin_at); +GEN_OFFSET_SYM(arch_mem_domain_t, reg_vecpin_as); +GEN_OFFSET_SYM(arch_mem_domain_t, reg_vecpin_at); + #endif #ifdef CONFIG_XTENSA_MPU GEN_OFFSET_SYM(_thread_arch_t, mpu_map); diff --git a/arch/xtensa/core/ptables.c b/arch/xtensa/core/ptables.c index 95cdc8bbb26..fa7d4fb0f70 100644 --- a/arch/xtensa/core/ptables.c +++ b/arch/xtensa/core/ptables.c @@ -1122,12 +1122,4 @@ int arch_buffer_validate(const void *addr, size_t size, int write) return mem_buffer_validate(addr, size, write, XTENSA_MMU_USER_RING); } -void xtensa_swap_update_page_tables(struct k_thread *incoming) -{ - struct arch_mem_domain *domain = - &(incoming->mem_domain_info.mem_domain->arch); - - xtensa_mmu_set_paging(domain); -} - #endif /* CONFIG_USERSPACE */ diff --git a/arch/xtensa/core/userspace.S b/arch/xtensa/core/userspace.S index a7558334ca4..56888ef048f 100644 --- a/arch/xtensa/core/userspace.S +++ b/arch/xtensa/core/userspace.S @@ -271,7 +271,7 @@ xtensa_userspace_enter: l32i a6, a1, 24 #ifdef CONFIG_XTENSA_MMU - call4 xtensa_swap_update_page_tables + SWAP_PAGE_TABLE a6, a3, a7 #endif #ifdef CONFIG_XTENSA_MPU call4 xtensa_mpu_map_write diff --git a/arch/xtensa/core/xtensa_asm2_util.S b/arch/xtensa/core/xtensa_asm2_util.S index 3f8ee288ce1..6892831f52a 100644 --- a/arch/xtensa/core/xtensa_asm2_util.S +++ b/arch/xtensa/core/xtensa_asm2_util.S @@ -248,11 +248,10 @@ xtensa_switch: s32i a6, a1, 8 s32i a7, a1, 12 - /* Switch page tables */ rsr a6, ZSR_CPU l32i a6, a6, ___cpu_t_current_OFFSET #ifdef CONFIG_XTENSA_MMU - call4 xtensa_swap_update_page_tables + SWAP_PAGE_TABLE a6, a4, a7 #endif #ifdef CONFIG_XTENSA_MPU call4 xtensa_mpu_map_write diff --git a/arch/xtensa/include/offsets_short_arch.h b/arch/xtensa/include/offsets_short_arch.h index 1478241d2e6..80ece2b1dee 100644 --- a/arch/xtensa/include/offsets_short_arch.h +++ b/arch/xtensa/include/offsets_short_arch.h @@ -17,6 +17,28 @@ #define _thread_offset_to_ptables \ (___thread_t_arch_OFFSET + ___thread_arch_t_ptables_OFFSET) + +#define _thread_offset_to_mem_domain \ + (___thread_t_mem_domain_info_OFFSET + ___mem_domain_info_t_mem_domain_OFFSET) + +#define _k_mem_domain_offset_to_arch_reg_asid \ + (__k_mem_domain_t_arch_OFFSET + __arch_mem_domain_t_reg_asid_OFFSET) + +#define _k_mem_domain_offset_to_arch_reg_ptevaddr \ + (__k_mem_domain_t_arch_OFFSET + __arch_mem_domain_t_reg_ptevaddr_OFFSET) + +#define _k_mem_domain_offset_to_arch_reg_ptepin_as \ + (__k_mem_domain_t_arch_OFFSET + __arch_mem_domain_t_reg_ptepin_as_OFFSET) + +#define _k_mem_domain_offset_to_arch_reg_ptepin_at \ + (__k_mem_domain_t_arch_OFFSET + __arch_mem_domain_t_reg_ptepin_at_OFFSET) + +#define _k_mem_domain_offset_to_arch_reg_vecpin_as \ + (__k_mem_domain_t_arch_OFFSET + __arch_mem_domain_t_reg_vecpin_as_OFFSET) + +#define _k_mem_domain_offset_to_arch_reg_vecpin_at \ + (__k_mem_domain_t_arch_OFFSET + __arch_mem_domain_t_reg_vecpin_at_OFFSET) + #endif /* CONFIG_USERSPACE */ #endif /* ZEPHYR_ARCH_XTENSA_INCLUDE_OFFSETS_SHORT_ARCH_H_ */ diff --git a/arch/xtensa/include/xtensa_asm2_s.h b/arch/xtensa/include/xtensa_asm2_s.h index 8a1181e5166..198f04f80e8 100644 --- a/arch/xtensa/include/xtensa_asm2_s.h +++ b/arch/xtensa/include/xtensa_asm2_s.h @@ -225,6 +225,44 @@ .endm +#if defined(CONFIG_XTENSA_MMU) && defined(CONFIG_USERSPACE) +/* + * SWAP_PAGE_TABLE + * + * This swaps the page tables by using the pre-computed register values + * inside the architecture-specific memory domain struct. + * + * THREAD_PTR_REG is input containing pointer to the incoming thread struct. + * SC1_REG and SC2_REG are scratch registers. + * + * Note that all THREAD_PTR_REG, SC1_REG and SC2_REG are all clobbered. + * Restore the thread pointer after this if necessary. + */ +.macro SWAP_PAGE_TABLE THREAD_PTR_REG, SC1_REG, SC2_REG + l32i \THREAD_PTR_REG, \THREAD_PTR_REG, _thread_offset_to_mem_domain + + j _swap_page_table_\@ + +.align 16 +_swap_page_table_\@: + l32i \SC1_REG, \THREAD_PTR_REG, _k_mem_domain_offset_to_arch_reg_ptevaddr + l32i \SC2_REG, \THREAD_PTR_REG, _k_mem_domain_offset_to_arch_reg_asid + wsr \SC1_REG, PTEVADDR + wsr \SC2_REG, RASID + + l32i \SC1_REG, \THREAD_PTR_REG, _k_mem_domain_offset_to_arch_reg_ptepin_as + l32i \SC2_REG, \THREAD_PTR_REG, _k_mem_domain_offset_to_arch_reg_ptepin_at + wdtlb \SC2_REG, \SC1_REG + + l32i \SC1_REG, \THREAD_PTR_REG, _k_mem_domain_offset_to_arch_reg_vecpin_as + l32i \SC2_REG, \THREAD_PTR_REG, _k_mem_domain_offset_to_arch_reg_vecpin_at + wdtlb \SC2_REG, \SC1_REG + + isync +.endm + +#endif /* CONFIG_XTENSA_MMU && CONFIG_USERSPACE */ + /* * CROSS_STACK_CALL * @@ -357,7 +395,7 @@ _xstack_call0_\@: l32i a6, a6, ___cpu_t_current_OFFSET #ifdef CONFIG_XTENSA_MMU - call4 xtensa_swap_update_page_tables + SWAP_PAGE_TABLE a6, a3, a7 #endif #ifdef CONFIG_XTENSA_MPU call4 xtensa_mpu_map_write diff --git a/include/zephyr/arch/xtensa/arch.h b/include/zephyr/arch/xtensa/arch.h index 299ab6526e9..6255249f8e7 100644 --- a/include/zephyr/arch/xtensa/arch.h +++ b/include/zephyr/arch/xtensa/arch.h @@ -81,6 +81,8 @@ struct arch_mem_domain { sys_snode_t node; }; +typedef struct arch_mem_domain arch_mem_domain_t; + /** * @brief Generate hardware exception. * diff --git a/soc/cdns/dc233c/include/xtensa-dc233c.ld b/soc/cdns/dc233c/include/xtensa-dc233c.ld index fee4ace0282..83ab002e976 100644 --- a/soc/cdns/dc233c/include/xtensa-dc233c.ld +++ b/soc/cdns/dc233c/include/xtensa-dc233c.ld @@ -162,7 +162,6 @@ SECTIONS /* Userspace related stuff */ LIB_OBJ_FUNC_IN_SECT(libarch__xtensa__core.a,userspace.S.obj,xtensa_do_syscall) - LIB_OBJ_FUNC_IN_SECT(libarch__xtensa__core.a,ptables.c.obj,xtensa_swap_update_page_tables) /* Below are to speed up execution by avoiding TLB misses * on frequently used functions.