Changeset 3fcea34 in mainline for kernel/arch


Ignore:
Timestamp:
2024-09-20T12:16:28Z (16 months ago)
Author:
Jiří Zárevúcky <zarevucky.jiri@…>
Branches:
master
Children:
d3109ff
Parents:
2cf8f994
git-author:
Jiří Zárevúcky <zarevucky.jiri@…> (2024-09-20 11:42:13)
git-committer:
Jiří Zárevúcky <zarevucky.jiri@…> (2024-09-20 12:16:28)
Message:

Simplify the SYS_THREAD_CREATE syscall interface

Removed the beefy uarg structure. Instead, the syscall gets two
parameters: %pc (program counter) and %sp (stack pointer). It starts
a thread with those values in corresponding registers, with no other
fuss whatsoever.

libc initializes threads by storing any other needed arguments on
the stack and retrieving them in thread_entry. Importantly, this
includes the address of the
thread_main function which is now
called indirectly to fix dynamic linking issues on some archs.

There's a bit of weirdness on SPARC and IA-64, because of their
stacked register handling. The current solution is that we require
some space *above* the stack pointer to be available for those
architectures. I think for SPARC, it can be made more normal.

For the remaining ones, we can (probably) just set the initial
%sp to the top edge of the stack. There's some lingering offsets
on some archs just because I didn't want to accidentally break
anything. The initial thread bringup should be functionally
unchanged from the previous state, and no binaries are currently
multithreaded except thread1 test, so there should be minimal
risk of breakage. Naturally, I tested all available emulator
builds, save for msim.

Location:
kernel/arch
Files:
15 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/abs32le/src/userspace.c

    r2cf8f994 r3fcea34  
    3636#include <stdbool.h>
    3737#include <arch.h>
    38 #include <abi/proc/uarg.h>
    3938#include <mm/as.h>
    4039
    41 void userspace(uspace_arg_t *kernel_uarg)
     40uintptr_t arch_get_initial_sp(uintptr_t stack_base, uintptr_t stack_size)
     41{
     42        return stack_base + stack_size;
     43}
     44
     45void userspace(uintptr_t pc, uintptr_t sp)
    4246{
    4347        /*
  • kernel/arch/amd64/src/userspace.c

    r2cf8f994 r3fcea34  
    3939#include <stdint.h>
    4040#include <arch.h>
    41 #include <abi/proc/uarg.h>
    4241#include <mm/as.h>
     42
     43uintptr_t arch_get_initial_sp(uintptr_t stack_base, uintptr_t stack_size)
     44{
     45        return stack_base + stack_size;
     46}
    4347
    4448/** Enter userspace
     
    4751 *
    4852 */
    49 void userspace(uspace_arg_t *kernel_uarg)
     53void userspace(uintptr_t pc, uintptr_t sp)
    5054{
    5155        uint64_t rflags = read_rflags();
     
    6064            "pushq %[utext_des]\n"
    6165            "pushq %[entry]\n"
    62             "movq %[uarg], %%rax\n"
    6366
    6467            /* %rdi is defined to hold pcb_ptr - set it to 0 */
     
    6669            "iretq\n"
    6770            :: [udata_des] "i" (GDT_SELECTOR(UDATA_DES) | PL_USER),
    68               [stack_top] "r" (kernel_uarg->uspace_stack +
    69               kernel_uarg->uspace_stack_size),
     71              [stack_top] "r" (sp),
    7072              [rflags] "r" (rflags),
    7173              [utext_des] "i" (GDT_SELECTOR(UTEXT_DES) | PL_USER),
    72               [entry] "r" (kernel_uarg->uspace_entry),
    73               [uarg] "r" (kernel_uarg->uspace_uarg)
    74             : "rax"
     74              [entry] "r" (pc)
    7575        );
    7676
  • kernel/arch/arm32/src/userspace.c

    r2cf8f994 r3fcea34  
    6161} ustate_t;
    6262
     63uintptr_t arch_get_initial_sp(uintptr_t stack_base, uintptr_t stack_size)
     64{
     65        return stack_base + stack_size;
     66}
     67
    6368/** Change processor mode
    6469 *
     
    6671 *
    6772 */
    68 void userspace(uspace_arg_t *kernel_uarg)
     73void userspace(uintptr_t pc, uintptr_t sp)
    6974{
    70         volatile ustate_t ustate;
    71 
    72         /* set first parameter */
    73         ustate.r0 = kernel_uarg->uspace_uarg;
    74 
    75         /* %r1 is defined to hold pcb_ptr - set it to 0 */
    76         ustate.r1 = 0;
     75        volatile ustate_t ustate = { };
    7776
    7877        /* pass the RAS page address in %r2 */
    7978        ustate.r2 = (uintptr_t) ras_page;
    8079
    81         /* clear other registers */
    82         ustate.r3 = 0;
    83         ustate.r4 = 0;
    84         ustate.r5 = 0;
    85         ustate.r6 = 0;
    86         ustate.r7 = 0;
    87         ustate.r8 = 0;
    88         ustate.r9 = 0;
    89         ustate.r10 = 0;
    90         ustate.r11 = 0;
    91         ustate.r12 = 0;
    92         ustate.lr = 0;
    93 
    94         /* set user stack */
    95         ustate.sp = kernel_uarg->uspace_stack +
    96             kernel_uarg->uspace_stack_size;
    97 
    98         /* set where uspace execution starts */
    99         ustate.pc = kernel_uarg->uspace_entry;
     80        ustate.sp = sp;
     81        ustate.pc = pc;
    10082
    10183        /* status register in user mode */
  • kernel/arch/arm64/src/arm64.c

    r2cf8f994 r3fcea34  
    146146}
    147147
     148uintptr_t arch_get_initial_sp(uintptr_t stack_base, uintptr_t stack_size)
     149{
     150        return stack_base + stack_size;
     151}
     152
    148153/** Change processor mode.
    149154 *
    150155 * @param kernel_uarg Userspace settings (entry point, stack, ...).
    151156 */
    152 void userspace(uspace_arg_t *kernel_uarg)
     157void userspace(uintptr_t pc, uintptr_t sp)
    153158{
    154159        /* Prepare return to EL0. */
     
    157162
    158163        /* Set program entry. */
    159         ELR_EL1_write(kernel_uarg->uspace_entry);
     164        ELR_EL1_write(pc);
    160165
    161166        /* Set user stack. */
    162         SP_EL0_write(kernel_uarg->uspace_stack +
    163             kernel_uarg->uspace_stack_size);
     167        SP_EL0_write(sp);
    164168
    165169        /* Clear Thread ID register. */
     
    170174             * Reset the kernel stack to its base value.
    171175             *
    172              * Clear all general-purpose registers,
    173              * except x0 that holds an argument for
    174              * the user space.
     176             * Clear all general-purpose registers.
    175177             */
    176178            "mov sp, %[kstack]\n"
    177             "mov x0, %[uspace_uarg]\n"
     179            "mov x0, #0\n"
    178180            "mov x1, #0\n"
    179181            "mov x2, #0\n"
     
    207209            "mov x30, #0\n"
    208210            "eret\n"
    209             :: [uspace_uarg] "r" (kernel_uarg->uspace_uarg),
    210               [kstack] "r" (((uint64_t) (THREAD->kstack)) +
     211            :: [kstack] "r" (((uint64_t) (THREAD->kstack)) +
    211212              MEM_STACK_SIZE - SP_DELTA)
    212213        );
  • kernel/arch/ia32/src/userspace.c

    r2cf8f994 r3fcea34  
    3838#include <stdint.h>
    3939#include <arch.h>
    40 #include <abi/proc/uarg.h>
    4140#include <mm/as.h>
    4241#include <arch/cpu.h>
    4342#include <arch/asm.h>
     43
     44uintptr_t arch_get_initial_sp(uintptr_t stack_base, uintptr_t stack_size)
     45{
     46        return stack_base + stack_size;
     47}
    4448
    4549/** Enter userspace
     
    4852 *
    4953 */
    50 void userspace(uspace_arg_t *kernel_uarg)
     54void userspace(uintptr_t pc, uintptr_t sp)
    5155{
    5256        uint32_t eflags = read_eflags();
     
    6165            "pushl %[utext_des]\n"
    6266            "pushl %[entry]\n"
    63             "movl %[uarg], %%eax\n"
    6467
    6568            /* %edi is defined to hold pcb_ptr - set it to 0 */
     
    7073            : [eflags_mask] "i" (~EFLAGS_NT),
    7174              [udata_des] "i" (GDT_SELECTOR(UDATA_DES) | PL_USER),
    72               [stack_top] "r" (kernel_uarg->uspace_stack +
    73               kernel_uarg->uspace_stack_size),
     75              [stack_top] "r" (sp),
    7476              [eflags] "r" ((eflags & ~(EFLAGS_NT)) | EFLAGS_IF),
    7577              [utext_des] "i" (GDT_SELECTOR(UTEXT_DES) | PL_USER),
    76               [entry] "r" (kernel_uarg->uspace_entry),
    77               [uarg] "r" (kernel_uarg->uspace_uarg),
     78              [entry] "r" (pc),
    7879              [vreg_des] "r" (GDT_SELECTOR(VREG_DES))
    7980            : "eax");
  • kernel/arch/ia64/src/ia64.c

    r2cf8f994 r3fcea34  
    218218}
    219219
     220uintptr_t arch_get_initial_sp(uintptr_t stack_base, uintptr_t stack_size)
     221{
     222        return ALIGN_DOWN(stack_base + stack_size / 2, STACK_ALIGNMENT);
     223}
     224
    220225/** Enter userspace and never return. */
    221 void userspace(uspace_arg_t *kernel_uarg)
     226void userspace(uintptr_t pc, uintptr_t sp)
    222227{
    223228        psr_t psr;
     
    241246         *
    242247         * When calculating stack addresses, mind the stack split between the
    243          * memory stack and the RSE stack. Each occuppies
    244          * uspace_stack_size / 2 bytes.
     248         * memory stack and the RSE stack.
     249         * Memory stack occupies area under sp, while RSE stack occupies area above.
    245250         */
    246         switch_to_userspace(kernel_uarg->uspace_entry,
    247             kernel_uarg->uspace_stack +
    248             kernel_uarg->uspace_stack_size / 2 -
    249             ALIGN_UP(STACK_ITEM_SIZE, STACK_ALIGNMENT),
    250             kernel_uarg->uspace_stack +
    251             kernel_uarg->uspace_stack_size / 2,
    252             kernel_uarg->uspace_uarg, psr.value, rsc.value);
     251        switch_to_userspace(pc,
     252            sp, sp + ALIGN_UP(STACK_ITEM_SIZE, STACK_ALIGNMENT),
     253            0, psr.value, rsc.value);
    253254
    254255        while (true)
  • kernel/arch/mips32/include/arch/asm.h

    r2cf8f994 r3fcea34  
    8181extern void cpu_halt(void) __attribute__((noreturn));
    8282extern void asm_delay_loop(uint32_t);
    83 extern void userspace_asm(uintptr_t, uintptr_t, uintptr_t);
     83extern void userspace_asm(uintptr_t, uintptr_t);
    8484
    8585extern ipl_t interrupts_disable(void);
  • kernel/arch/mips32/src/mips32.c

    r2cf8f994 r3fcea34  
    163163}
    164164
    165 void userspace(uspace_arg_t *kernel_uarg)
     165uintptr_t arch_get_initial_sp(uintptr_t stack_base, uintptr_t stack_size)
     166{
     167        return stack_base + stack_size;
     168}
     169
     170void userspace(uintptr_t pc, uintptr_t sp)
    166171{
    167172        /* EXL = 1, UM = 1, IE = 1 */
    168173        cp0_status_write(cp0_status_read() | (cp0_status_exl_exception_bit |
    169174            cp0_status_um_bit | cp0_status_ie_enabled_bit));
    170         cp0_epc_write(kernel_uarg->uspace_entry);
    171         userspace_asm(kernel_uarg->uspace_stack +
    172             kernel_uarg->uspace_stack_size,
    173             kernel_uarg->uspace_uarg,
    174             kernel_uarg->uspace_entry);
     175        cp0_epc_write(pc);
     176        userspace_asm(sp, pc);
    175177
    176178        while (true)
  • kernel/arch/mips32/src/start.S

    r2cf8f994 r3fcea34  
    339339FUNCTION_BEGIN(userspace_asm)
    340340        move $sp, $a0
    341         move $v0, $a1
    342         move $t9, $a2      /* set up correct entry into PIC code */
    343         xor $a0, $a0, $a0  /* $a0 is defined to hold pcb_ptr */
    344                            /* set it to 0 */
     341        xor $a0, $a0, $a0  /* $a0 is defined to hold pcb_ptr, set it to 0 */
     342        xor $fp, $fp, $fp  // FIXME: wipe all userspace-accessible registers
     343        xor $ra, $ra, $ra
    345344        eret
    346345FUNCTION_END(userspace_asm)
  • kernel/arch/ppc32/src/ppc32.c

    r2cf8f994 r3fcea34  
    4949#include <mm/km.h>
    5050#include <time/clock.h>
    51 #include <abi/proc/uarg.h>
    5251#include <console/console.h>
    5352#include <sysinfo/sysinfo.h>
     
    290289}
    291290
    292 void userspace(uspace_arg_t *kernel_uarg)
    293 {
    294         userspace_asm(kernel_uarg->uspace_uarg,
    295             kernel_uarg->uspace_stack +
    296             kernel_uarg->uspace_stack_size - SP_DELTA,
    297             kernel_uarg->uspace_entry);
    298 
     291uintptr_t arch_get_initial_sp(uintptr_t stack_base, uintptr_t stack_size)
     292{
     293        return stack_base + stack_size - SP_DELTA;
     294}
     295
     296void userspace(uintptr_t pc, uintptr_t sp)
     297{
     298        userspace_asm(0, sp, pc);
    299299        unreachable();
    300300}
  • kernel/arch/riscv64/src/userspace.c

    r2cf8f994 r3fcea34  
    3333 */
    3434
    35 #include <abi/proc/uarg.h>
    3635#include <userspace.h>
    3736
    38 void userspace(uspace_arg_t *kernel_uarg)
     37uintptr_t arch_get_initial_sp(uintptr_t stack_base, uintptr_t stack_size)
     38{
     39        return stack_base + stack_size;
     40}
     41
     42void userspace(uintptr_t pc, uintptr_t sp)
    3943{
    4044        // FIXME
  • kernel/arch/sparc64/src/sun4u/asm.S

    r2cf8f994 r3fcea34  
    8383 */
    8484FUNCTION_BEGIN(switch_to_userspace)
    85         save %o1, -(STACK_WINDOW_SAVE_AREA_SIZE + STACK_ARG_SAVE_AREA_SIZE), %sp
     85        save %o1, 0, %sp
    8686        flushw
    8787        wrpr %g0, 0, %cleanwin          ! avoid information leak
  • kernel/arch/sparc64/src/sun4u/sparc64.c

    r2cf8f994 r3fcea34  
    159159}
    160160
     161uintptr_t arch_get_initial_sp(uintptr_t stack_base, uintptr_t stack_size)
     162{
     163        return ALIGN_DOWN(stack_base + stack_size - STACK_WINDOW_SAVE_AREA_SIZE - STACK_ARG_SAVE_AREA_SIZE, 16) - STACK_BIAS;
     164}
     165
    161166/** Switch to userspace. */
    162 void userspace(uspace_arg_t *kernel_uarg)
     167void userspace(uintptr_t pc, uintptr_t sp)
    163168{
    164169        (void) interrupts_disable();
    165         switch_to_userspace(kernel_uarg->uspace_entry,
    166             kernel_uarg->uspace_stack +
    167             kernel_uarg->uspace_stack_size -
    168             (ALIGN_UP(STACK_ITEM_SIZE, STACK_ALIGNMENT) + STACK_BIAS),
    169             kernel_uarg->uspace_uarg);
     170        switch_to_userspace(pc, sp, 0);
    170171
    171172        /* Not reached */
  • kernel/arch/sparc64/src/sun4v/asm.S

    r2cf8f994 r3fcea34  
    4141 */
    4242FUNCTION_BEGIN(switch_to_userspace)
    43         save %o1, -(STACK_WINDOW_SAVE_AREA_SIZE + STACK_ARG_SAVE_AREA_SIZE), %sp
     43        save %o1, 0, %sp
    4444        flushw
    4545        wrpr %g0, 0, %cleanwin          ! avoid information leak
  • kernel/arch/sparc64/src/sun4v/sparc64.c

    r2cf8f994 r3fcea34  
    157157}
    158158
     159uintptr_t arch_get_initial_sp(uintptr_t stack_base, uintptr_t stack_size)
     160{
     161        return ALIGN_DOWN(stack_base + stack_size - STACK_WINDOW_SAVE_AREA_SIZE - STACK_ARG_SAVE_AREA_SIZE, 16) - STACK_BIAS;
     162}
     163
    159164/** Switch to userspace. */
    160 void userspace(uspace_arg_t *kernel_uarg)
     165void userspace(uintptr_t pc, uintptr_t sp)
    161166{
    162167        (void) interrupts_disable();
    163         switch_to_userspace(kernel_uarg->uspace_entry,
    164             kernel_uarg->uspace_stack +
    165             kernel_uarg->uspace_stack_size -
    166             (ALIGN_UP(STACK_ITEM_SIZE, STACK_ALIGNMENT) + STACK_BIAS),
    167             kernel_uarg->uspace_uarg);
     168        switch_to_userspace(pc, sp, 0);
    168169
    169170        /* Not reached */
Note: See TracChangeset for help on using the changeset viewer.