source: mainline/kernel/arch/mips32/src/mips32.c

Last change on this file was 3fcea34, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 9 months ago

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.

  • Property mode set to 100644
File size: 5.7 KB
Line 
1/*
2 * Copyright (c) 2003-2004 Jakub Jermar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup kernel_mips32
30 * @{
31 */
32/** @file
33 */
34
35#include <arch.h>
36#include <arch/arch.h>
37#include <typedefs.h>
38#include <errno.h>
39#include <interrupt.h>
40#include <macros.h>
41#include <str.h>
42#include <memw.h>
43#include <preemption.h>
44#include <userspace.h>
45#include <stdbool.h>
46#include <syscall/syscall.h>
47#include <sysinfo/sysinfo.h>
48#include <arch/debug.h>
49#include <arch/debugger.h>
50#include <arch/machine_func.h>
51
52/*
53 * Size of the code jumping to the exception handler code
54 * - J+NOP
55 */
56#define EXCEPTION_JUMP_SIZE 8
57
58#define TLB_EXC ((char *) 0x80000000)
59#define NORM_EXC ((char *) 0x80000180)
60#define CACHE_EXC ((char *) 0x80000100)
61
62static void mips32_pre_mm_init(void);
63static void mips32_post_mm_init(void);
64static void mips32_post_smp_init(void);
65
66arch_ops_t mips32_ops = {
67 .pre_mm_init = mips32_pre_mm_init,
68 .post_mm_init = mips32_post_mm_init,
69 .post_smp_init = mips32_post_smp_init,
70};
71
72arch_ops_t *arch_ops = &mips32_ops;
73
74/* Stack pointer saved when entering user mode */
75// FIXME: This won't work with SMP unless thread creation is globally serialized.
76uintptr_t supervisor_sp;
77
78size_t cpu_count = 0;
79
80#if defined(MACHINE_lmalta) || defined(MACHINE_bmalta)
81size_t sdram_size = 0;
82#endif
83
84/** Performs mips32-specific initialization before main_bsp() is called. */
85void mips32_pre_main(void *entry __attribute__((unused)), bootinfo_t *bootinfo)
86{
87 init.cnt = min3(bootinfo->taskmap.cnt, TASKMAP_MAX_RECORDS, CONFIG_INIT_TASKS);
88
89 size_t i;
90 for (i = 0; i < init.cnt; i++) {
91 init.tasks[i].paddr = KA2PA(bootinfo->taskmap.tasks[i].addr);
92 init.tasks[i].size = bootinfo->taskmap.tasks[i].size;
93 str_cpy(init.tasks[i].name, CONFIG_TASK_NAME_BUFLEN,
94 bootinfo->taskmap.tasks[i].name);
95 }
96
97 for (i = 0; i < CPUMAP_MAX_RECORDS; i++) {
98 if ((bootinfo->cpumap & (1 << i)) != 0)
99 cpu_count++;
100 }
101
102#if defined(MACHINE_lmalta) || defined(MACHINE_bmalta)
103 sdram_size = bootinfo->sdram_size;
104#endif
105
106 str_cpy(bargs, CONFIG_BOOT_ARGUMENTS_BUFLEN, bootinfo->bootargs);
107
108 /* Initialize machine_ops pointer. */
109 machine_ops_init();
110}
111
112void mips32_pre_mm_init(void)
113{
114 /* It is not assumed by default */
115 interrupts_disable();
116
117 /* Initialize dispatch table */
118 exception_init();
119
120 /* Copy the exception vectors to the right places */
121 memcpy(TLB_EXC, (char *) tlb_refill_entry, EXCEPTION_JUMP_SIZE);
122 smc_coherence(TLB_EXC, EXCEPTION_JUMP_SIZE);
123 memcpy(NORM_EXC, (char *) exception_entry, EXCEPTION_JUMP_SIZE);
124 smc_coherence(NORM_EXC, EXCEPTION_JUMP_SIZE);
125 memcpy(CACHE_EXC, (char *) cache_error_entry, EXCEPTION_JUMP_SIZE);
126 smc_coherence(CACHE_EXC, EXCEPTION_JUMP_SIZE);
127
128 /*
129 * Switch to BEV normal level so that exception vectors point to the
130 * kernel. Clear the error level.
131 */
132 cp0_status_write(cp0_status_read() &
133 ~(cp0_status_bev_bootstrap_bit | cp0_status_erl_error_bit));
134
135 /*
136 * Mask all interrupts
137 */
138 cp0_mask_all_int();
139
140 debugger_init();
141}
142
143void mips32_post_mm_init(void)
144{
145 interrupt_init();
146
147 machine_init();
148 machine_output_init();
149}
150
151void mips32_post_smp_init(void)
152{
153 /* Set platform name. */
154 sysinfo_set_item_data("platform", NULL,
155 (void *) machine_get_platform_name(),
156 str_size(machine_get_platform_name()));
157
158 machine_input_init();
159}
160
161void calibrate_delay_loop(void)
162{
163}
164
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)
171{
172 /* EXL = 1, UM = 1, IE = 1 */
173 cp0_status_write(cp0_status_read() | (cp0_status_exl_exception_bit |
174 cp0_status_um_bit | cp0_status_ie_enabled_bit));
175 cp0_epc_write(pc);
176 userspace_asm(sp, pc);
177
178 while (true)
179 ;
180}
181
182/** Perform mips32 specific tasks needed before the new task is run. */
183void before_task_runs_arch(void)
184{
185}
186
187/** Perform mips32 specific tasks needed before the new thread is scheduled. */
188void before_thread_runs_arch(void)
189{
190 supervisor_sp =
191 (uintptr_t) &THREAD->kstack[STACK_SIZE];
192}
193
194void after_thread_ran_arch(void)
195{
196}
197
198void arch_reboot(void)
199{
200 ___halt();
201 while (true)
202 ;
203}
204
205/** Construct function pointer
206 *
207 * @param fptr function pointer structure
208 * @param addr function address
209 * @param caller calling function address
210 *
211 * @return address of the function pointer
212 *
213 */
214void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller)
215{
216 return addr;
217}
218
219void irq_initialize_arch(irq_t *irq)
220{
221 (void) irq;
222}
223
224/** @}
225 */
Note: See TracBrowser for help on using the repository browser.