source: mainline/kernel/arch/ppc32/src/ppc32.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: 8.1 KB
Line 
1/*
2 * Copyright (c) 2005 Martin Decky
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_ppc32
30 * @{
31 */
32/** @file
33 */
34
35#include <arch.h>
36#include <arch/arch.h>
37#include <config.h>
38#include <arch/boot/boot.h>
39#include <genarch/drivers/via-cuda/cuda.h>
40#include <genarch/kbrd/kbrd.h>
41#include <arch/interrupt.h>
42#include <interrupt.h>
43#include <genarch/fb/fb.h>
44#include <abi/fb/visuals.h>
45#include <genarch/ofw/ofw_tree.h>
46#include <genarch/ofw/pci.h>
47#include <userspace.h>
48#include <mm/page.h>
49#include <mm/km.h>
50#include <time/clock.h>
51#include <console/console.h>
52#include <sysinfo/sysinfo.h>
53#include <ddi/irq.h>
54#include <arch/drivers/pic.h>
55#include <align.h>
56#include <macros.h>
57#include <str.h>
58
59#define IRQ_COUNT 64
60#define IRQ_CUDA 10
61
62static void ppc32_pre_mm_init(void);
63static void ppc32_post_mm_init(void);
64static void ppc32_post_smp_init(void);
65
66arch_ops_t ppc32_ops = {
67 .pre_mm_init = ppc32_pre_mm_init,
68 .post_mm_init = ppc32_post_mm_init,
69 .post_smp_init = ppc32_post_smp_init,
70};
71
72arch_ops_t *arch_ops = &ppc32_ops;
73
74bootinfo_t bootinfo;
75
76static cir_t pic_cir;
77static void *pic_cir_arg;
78
79/** Performs ppc32-specific initialization before main_bsp() is called. */
80void ppc32_pre_main(bootinfo_t *bootinfo)
81{
82 /* Copy tasks map. */
83 init.cnt = min3(bootinfo->taskmap.cnt, TASKMAP_MAX_RECORDS, CONFIG_INIT_TASKS);
84 size_t i;
85 for (i = 0; i < init.cnt; i++) {
86 init.tasks[i].paddr = KA2PA(bootinfo->taskmap.tasks[i].addr);
87 init.tasks[i].size = bootinfo->taskmap.tasks[i].size;
88 str_cpy(init.tasks[i].name, CONFIG_TASK_NAME_BUFLEN,
89 bootinfo->taskmap.tasks[i].name);
90 }
91
92 /* Copy physical memory map. */
93 memmap.total = bootinfo->memmap.total;
94 memmap.cnt = min(bootinfo->memmap.cnt, MEMMAP_MAX_RECORDS);
95 for (i = 0; i < memmap.cnt; i++) {
96 memmap.zones[i].start = bootinfo->memmap.zones[i].start;
97 memmap.zones[i].size = bootinfo->memmap.zones[i].size;
98 }
99
100 /* Copy boot allocations info. */
101 ballocs.base = bootinfo->ballocs.base;
102 ballocs.size = bootinfo->ballocs.size;
103
104 /* Copy OFW tree. */
105 ofw_tree_init(bootinfo->ofw_root);
106}
107
108void ppc32_pre_mm_init(void)
109{
110 /* Initialize dispatch table */
111 interrupt_init();
112
113 ofw_tree_node_t *cpus_node;
114 ofw_tree_node_t *cpu_node;
115 ofw_tree_property_t *freq_prop;
116
117 cpus_node = ofw_tree_lookup("/cpus");
118 if (!cpus_node)
119 panic("Could not find cpus node.");
120
121 cpu_node = cpus_node->child;
122 if (!cpu_node)
123 panic("Could not find first cpu.");
124
125 freq_prop = ofw_tree_getprop(cpu_node, "timebase-frequency");
126 if (!freq_prop)
127 panic("Could not get frequency property.");
128
129 uint32_t freq;
130 freq = *((uint32_t *) freq_prop->value);
131
132 /* Start decrementer */
133 decrementer_start(freq / HZ);
134}
135
136#ifdef CONFIG_FB
137static bool display_register(ofw_tree_node_t *node, void *arg)
138{
139 uintptr_t fb_addr = 0;
140 uint32_t fb_width = 0;
141 uint32_t fb_height = 0;
142 uint32_t fb_scanline = 0;
143 unsigned int visual = VISUAL_UNKNOWN;
144
145 ofw_tree_property_t *prop = ofw_tree_getprop(node, "address");
146 if ((prop) && (prop->value))
147 fb_addr = *((uintptr_t *) prop->value);
148
149 prop = ofw_tree_getprop(node, "width");
150 if ((prop) && (prop->value))
151 fb_width = *((uint32_t *) prop->value);
152
153 prop = ofw_tree_getprop(node, "height");
154 if ((prop) && (prop->value))
155 fb_height = *((uint32_t *) prop->value);
156
157 prop = ofw_tree_getprop(node, "depth");
158 if ((prop) && (prop->value)) {
159 uint32_t fb_bpp = *((uint32_t *) prop->value);
160 switch (fb_bpp) {
161 case 8:
162 visual = VISUAL_INDIRECT_8;
163 break;
164 case 15:
165 visual = VISUAL_RGB_5_5_5_BE;
166 break;
167 case 16:
168 visual = VISUAL_RGB_5_6_5_BE;
169 break;
170 case 24:
171 visual = VISUAL_BGR_8_8_8;
172 break;
173 case 32:
174 visual = VISUAL_RGB_0_8_8_8;
175 break;
176 default:
177 visual = VISUAL_UNKNOWN;
178 }
179 }
180
181 prop = ofw_tree_getprop(node, "linebytes");
182 if ((prop) && (prop->value))
183 fb_scanline = *((uint32_t *) prop->value);
184
185 if ((fb_addr) && (fb_width > 0) && (fb_height > 0) &&
186 (fb_scanline > 0) && (visual != VISUAL_UNKNOWN)) {
187 fb_properties_t fb_prop = {
188 .addr = fb_addr,
189 .offset = 0,
190 .x = fb_width,
191 .y = fb_height,
192 .scan = fb_scanline,
193 .visual = visual,
194 };
195
196 outdev_t *fbdev = fb_init(&fb_prop);
197 if (fbdev)
198 stdout_wire(fbdev);
199 }
200
201 return true;
202}
203#endif
204
205void ppc32_post_mm_init(void)
206{
207 if (config.cpu_active == 1) {
208#ifdef CONFIG_FB
209 ofw_tree_walk_by_device_type("display", display_register, NULL);
210#endif
211 /* Map OFW information into sysinfo */
212 ofw_sysinfo_map();
213
214 /* Initialize IRQ routing */
215 irq_init(IRQ_COUNT, IRQ_COUNT);
216
217 /* Merge all zones to 1 big zone */
218 zone_merge_all();
219 }
220}
221
222static bool macio_register(ofw_tree_node_t *node, void *arg)
223{
224 ofw_pci_reg_t *assigned_address = NULL;
225
226 ofw_tree_property_t *prop = ofw_tree_getprop(node, "assigned-addresses");
227 if ((prop) && (prop->value))
228 assigned_address = ((ofw_pci_reg_t *) prop->value);
229
230 if (assigned_address) {
231 /* Initialize PIC */
232 pic_init(assigned_address[0].addr, PAGE_SIZE, &pic_cir,
233 &pic_cir_arg);
234
235#ifdef CONFIG_MAC_KBD
236 uintptr_t pa = assigned_address[0].addr + 0x16000;
237 size_t size = 2 * PAGE_SIZE;
238
239 cuda_t *cuda = (cuda_t *) km_map(pa, size, KM_NATURAL_ALIGNMENT,
240 PAGE_WRITE | PAGE_NOT_CACHEABLE);
241
242 /* Initialize I/O controller */
243 cuda_instance_t *cuda_instance =
244 cuda_init(cuda, IRQ_CUDA, pic_cir, pic_cir_arg);
245 if (cuda_instance) {
246 kbrd_instance_t *kbrd_instance = kbrd_init();
247 if (kbrd_instance) {
248 indev_t *sink = stdin_wire();
249 indev_t *kbrd = kbrd_wire(kbrd_instance, sink);
250 cuda_wire(cuda_instance, kbrd);
251 pic_enable_interrupt(IRQ_CUDA);
252 }
253 }
254
255 /*
256 * This is the necessary evil until the userspace driver is entirely
257 * self-sufficient.
258 */
259 sysinfo_set_item_val("cuda", NULL, true);
260 sysinfo_set_item_val("cuda.inr", NULL, IRQ_CUDA);
261 sysinfo_set_item_val("cuda.address.physical", NULL, pa);
262#endif
263 }
264
265 /* Consider only a single device for now */
266 return false;
267}
268
269void irq_initialize_arch(irq_t *irq)
270{
271 irq->cir = pic_cir;
272 irq->cir_arg = pic_cir_arg;
273 irq->preack = true;
274}
275
276void ppc32_post_smp_init(void)
277{
278 /* Currently the only supported platform for ppc32 is 'mac'. */
279 static const char *platform = "mac";
280
281 sysinfo_set_item_data("platform", NULL, (void *) platform,
282 str_size(platform));
283
284 ofw_tree_walk_by_device_type("mac-io", macio_register, NULL);
285}
286
287void calibrate_delay_loop(void)
288{
289}
290
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);
299 unreachable();
300}
301
302/** Construct function pointer
303 *
304 * @param fptr function pointer structure
305 * @param addr function address
306 * @param caller calling function address
307 *
308 * @return address of the function pointer
309 *
310 */
311void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller)
312{
313 return addr;
314}
315
316void arch_reboot(void)
317{
318 // TODO
319 while (true)
320 ;
321}
322
323/** @}
324 */
Note: See TracBrowser for help on using the repository browser.