'current' macro is mainly used to read 'task_struct' address of current process.
arch/riscv/include/asm/current.h
register struct task_struct *riscv_current_is_tp __asm__("tp");
static __always_inline struct task_struct *get_current(void)
{
return riscv_current_is_tp;
}
#define current get_current()
Body of current is 'get_current()' macro. We can deduce that "tp"(X4) holds start address of current.
Core routine of context switching in RISC-V Linux kernel is below.
ENTRY(__switch_to)
/* Save context into prev->thread */
li a4, TASK_THREAD_RA
add a3, a0, a4
add a4, a1, a4
REG_S ra, TASK_THREAD_RA_RA(a3)
REG_S sp, TASK_THREAD_SP_RA(a3)
REG_S s0, TASK_THREAD_S0_RA(a3)
REG_S s1, TASK_THREAD_S1_RA(a3)
REG_S s2, TASK_THREAD_S2_RA(a3)
REG_S s3, TASK_THREAD_S3_RA(a3)
REG_S s4, TASK_THREAD_S4_RA(a3)
REG_S s5, TASK_THREAD_S5_RA(a3)
REG_S s6, TASK_THREAD_S6_RA(a3)
REG_S s7, TASK_THREAD_S7_RA(a3)
REG_S s8, TASK_THREAD_S8_RA(a3)
REG_S s9, TASK_THREAD_S9_RA(a3)
REG_S s10, TASK_THREAD_S10_RA(a3)
REG_S s11, TASK_THREAD_S11_RA(a3)
/* Restore context from next->thread */
REG_L ra, TASK_THREAD_RA_RA(a4)
REG_L sp, TASK_THREAD_SP_RA(a4)
REG_L s0, TASK_THREAD_S0_RA(a4)
REG_L s1, TASK_THREAD_S1_RA(a4)
REG_L s2, TASK_THREAD_S2_RA(a4)
REG_L s3, TASK_THREAD_S3_RA(a4)
REG_L s4, TASK_THREAD_S4_RA(a4)
REG_L s5, TASK_THREAD_S5_RA(a4)
REG_L s6, TASK_THREAD_S6_RA(a4)
REG_L s7, TASK_THREAD_S7_RA(a4)
REG_L s8, TASK_THREAD_S8_RA(a4)
REG_L s9, TASK_THREAD_S9_RA(a4)
REG_L s10, TASK_THREAD_S10_RA(a4)
REG_L s11, TASK_THREAD_S11_RA(a4)
/* Swap the CPU entry around. */
lw a3, TASK_TI_CPU(a0)
lw a4, TASK_TI_CPU(a1)
sw a3, TASK_TI_CPU(a1)
sw a4, TASK_TI_CPU(a0)
/* The offset of thread_info in task_struct is zero. */
move tp, a1
ret
ENDPROC(__switch_to)
'move tp, a1' instruction corresponding to 'move X4, X11' is added to save the starting address of 'task_struct.
Body of 'alloc_fd' function.
fs/file.c
static int alloc_fd(unsigned start, unsigned end, unsigned flags)
{
struct files_struct *files = current->files;
The 'current' macro is used as a way to read starting address of 'task_struct'.
SP:FFFFFFFF8014E5B0|711D alloc_fd: c.addi16sp -0x60 ; -96
SP:FFFFFFFF8014E5B2|E8A2 c.sdsp x8,0x50(x2) ; x8,80(x2)
SP:FFFFFFFF8014E5B4|F852 c.sdsp x20,0x30(x2) ; x20,48(x2)
SP:FFFFFFFF8014E5B6|F456 c.sdsp x21,0x28(x2) ; x21,40(x2)
SP:FFFFFFFF8014E5B8|F05A c.sdsp x22,0x20(x2) ; x22,32(x2)
SP:FFFFFFFF8014E5BA|EC5E c.sdsp x23,0x18(x2) ; x23,24(x2)
SP:FFFFFFFF8014E5BC|E862 c.sdsp x24,0x10(x2) ; x24,16(x2)
SP:FFFFFFFF8014E5BE|EC86 c.sdsp x1,0x58(x2) ; x1,88(x2)
SP:FFFFFFFF8014E5C0|E4A6 c.sdsp x9,0x48(x2) ; x9,72(x2)
SP:FFFFFFFF8014E5C2|E0CA c.sdsp x18,0x40(x2) ; x18,64(x2)
SP:FFFFFFFF8014E5C4|FC4E c.sdsp x19,0x38(x2) ; x19,56(x2)
SP:FFFFFFFF8014E5C6|E466 c.sdsp x25,0x8(x2) ; x25,8(x2)
SP:FFFFFFFF8014E5C8|1080 c.addi4spn x8,0x60 ; x8,96
SP:FFFFFFFF8014E5CA|67823903 ld x18,0x678(x4) ; x18,1656(x4)
After 'ld x18,0x678(x4)' instruction is executed, x18 is holding the &(current->files) where 0x678 is offset of 'struct task_struct.files.
This is true because x4 holds the entry address of 'task_struct'.
fs/file.c
int __close_range(unsigned fd, unsigned max_fd, unsigned int flags)
{
struct task_struct *me = current;
struct files_struct *cur_fds = me->files, *fds = NULL;
SP:FFFFFFFF8014EC14|__close_range: c.addi16sp -0x60 ; -96
SP:FFFFFFFF8014EC16| c.sdsp x8,0x50(x2) ; x8,80(x2)
SP:FFFFFFFF8014EC18| c.sdsp x1,0x58(x2) ; x1,88(x2)
SP:FFFFFFFF8014EC1A| c.sdsp x21,0x28(x2) ; x21,40(x2)
SP:FFFFFFFF8014EC1C| c.addi4spn x8,0x60 ; x8,96
SP:FFFFFFFF8014EC1E| ld x15,0x460(x4) ; x15,1120(x4)
SP:FFFFFFFF8014EC22| sd x15,-0x58(x8) ; x15,-88(x8)
SP:FFFFFFFF8014EC26| c.li x15,0x0 ; x15,0
'RISC-V > RISC-V 빌드 및 환경' 카테고리의 다른 글
[RISC-V] How to run QEMU (Window) (0) | 2024.05.22 |
---|---|
RISC-V ISA-interpreter (0) | 2024.04.03 |
RISC-V Instruction Set Specifications [link] (0) | 2023.11.13 |
[RISC-V] sudo code for exception handling in Linux kernel (0) | 2023.11.13 |
[RISC-V Kernel build] How to build kernel for visionfive2 kernel ? (0) | 2023.11.10 |