xtensa: userspace: swap page tables via assembly code
Since the necessary register values are now pre-computed and stored in the memory domain struct, we can use them directly in various assembly locations, thus replacing the function call to xtensa_swap_update_page_tables(). Signed-off-by: Daniel Leung <daniel.leung@intel.com>
This commit is contained in:
parent
689e1121cf
commit
277fa9e8ac
8 changed files with 77 additions and 13 deletions
|
@ -71,6 +71,18 @@ GEN_OFFSET_SYM(_thread_arch_t, return_ps);
|
||||||
GEN_OFFSET_SYM(_thread_t, switch_handle);
|
GEN_OFFSET_SYM(_thread_t, switch_handle);
|
||||||
#ifdef CONFIG_XTENSA_MMU
|
#ifdef CONFIG_XTENSA_MMU
|
||||||
GEN_OFFSET_SYM(_thread_arch_t, ptables);
|
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
|
#endif
|
||||||
#ifdef CONFIG_XTENSA_MPU
|
#ifdef CONFIG_XTENSA_MPU
|
||||||
GEN_OFFSET_SYM(_thread_arch_t, mpu_map);
|
GEN_OFFSET_SYM(_thread_arch_t, mpu_map);
|
||||||
|
|
|
@ -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);
|
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 */
|
#endif /* CONFIG_USERSPACE */
|
||||||
|
|
|
@ -271,7 +271,7 @@ xtensa_userspace_enter:
|
||||||
|
|
||||||
l32i a6, a1, 24
|
l32i a6, a1, 24
|
||||||
#ifdef CONFIG_XTENSA_MMU
|
#ifdef CONFIG_XTENSA_MMU
|
||||||
call4 xtensa_swap_update_page_tables
|
SWAP_PAGE_TABLE a6, a3, a7
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_XTENSA_MPU
|
#ifdef CONFIG_XTENSA_MPU
|
||||||
call4 xtensa_mpu_map_write
|
call4 xtensa_mpu_map_write
|
||||||
|
|
|
@ -248,11 +248,10 @@ xtensa_switch:
|
||||||
s32i a6, a1, 8
|
s32i a6, a1, 8
|
||||||
s32i a7, a1, 12
|
s32i a7, a1, 12
|
||||||
|
|
||||||
/* Switch page tables */
|
|
||||||
rsr a6, ZSR_CPU
|
rsr a6, ZSR_CPU
|
||||||
l32i a6, a6, ___cpu_t_current_OFFSET
|
l32i a6, a6, ___cpu_t_current_OFFSET
|
||||||
#ifdef CONFIG_XTENSA_MMU
|
#ifdef CONFIG_XTENSA_MMU
|
||||||
call4 xtensa_swap_update_page_tables
|
SWAP_PAGE_TABLE a6, a4, a7
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_XTENSA_MPU
|
#ifdef CONFIG_XTENSA_MPU
|
||||||
call4 xtensa_mpu_map_write
|
call4 xtensa_mpu_map_write
|
||||||
|
|
|
@ -17,6 +17,28 @@
|
||||||
|
|
||||||
#define _thread_offset_to_ptables \
|
#define _thread_offset_to_ptables \
|
||||||
(___thread_t_arch_OFFSET + ___thread_arch_t_ptables_OFFSET)
|
(___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 /* CONFIG_USERSPACE */
|
||||||
|
|
||||||
#endif /* ZEPHYR_ARCH_XTENSA_INCLUDE_OFFSETS_SHORT_ARCH_H_ */
|
#endif /* ZEPHYR_ARCH_XTENSA_INCLUDE_OFFSETS_SHORT_ARCH_H_ */
|
||||||
|
|
|
@ -225,6 +225,44 @@
|
||||||
|
|
||||||
.endm
|
.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
|
* CROSS_STACK_CALL
|
||||||
*
|
*
|
||||||
|
@ -357,7 +395,7 @@ _xstack_call0_\@:
|
||||||
l32i a6, a6, ___cpu_t_current_OFFSET
|
l32i a6, a6, ___cpu_t_current_OFFSET
|
||||||
|
|
||||||
#ifdef CONFIG_XTENSA_MMU
|
#ifdef CONFIG_XTENSA_MMU
|
||||||
call4 xtensa_swap_update_page_tables
|
SWAP_PAGE_TABLE a6, a3, a7
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_XTENSA_MPU
|
#ifdef CONFIG_XTENSA_MPU
|
||||||
call4 xtensa_mpu_map_write
|
call4 xtensa_mpu_map_write
|
||||||
|
|
|
@ -81,6 +81,8 @@ struct arch_mem_domain {
|
||||||
sys_snode_t node;
|
sys_snode_t node;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct arch_mem_domain arch_mem_domain_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Generate hardware exception.
|
* @brief Generate hardware exception.
|
||||||
*
|
*
|
||||||
|
|
|
@ -162,7 +162,6 @@ SECTIONS
|
||||||
|
|
||||||
/* Userspace related stuff */
|
/* 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,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
|
/* Below are to speed up execution by avoiding TLB misses
|
||||||
* on frequently used functions.
|
* on frequently used functions.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue