source: mainline/kernel/arch/ia64/src/ia64.c@ 6ecf5b8

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 6ecf5b8 was 2902e1bb, checked in by Martin Decky <martin@…>, 13 years ago

add support for variable uspace stack size
create individual address space areas for stacks of additional threads (instead of allocating the stack from heap)
avoid memory leaks in program_create()

  • Property mode set to 100644
File size: 7.2 KB
Line 
1/*
2 * Copyright (c) 2005 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 ia64
30 * @{
31 */
32/** @file
33 */
34
35#include <arch.h>
36#include <typedefs.h>
37#include <errno.h>
38#include <interrupt.h>
39#include <macros.h>
40#include <str.h>
41#include <userspace.h>
42#include <console/console.h>
43#include <syscall/syscall.h>
44#include <sysinfo/sysinfo.h>
45#include <arch/drivers/it.h>
46#include <arch/drivers/kbd.h>
47#include <arch/legacyio.h>
48#include <genarch/drivers/ega/ega.h>
49#include <genarch/drivers/i8042/i8042.h>
50#include <genarch/drivers/ns16550/ns16550.h>
51#include <genarch/drivers/legacy/ia32/io.h>
52#include <genarch/kbrd/kbrd.h>
53#include <genarch/srln/srln.h>
54#include <mm/page.h>
55#include <mm/km.h>
56
57#ifdef MACHINE_ski
58#include <arch/drivers/ski.h>
59#endif
60
61/* NS16550 as a COM 1 */
62#define NS16550_IRQ (4 + LEGACY_INTERRUPT_BASE)
63
64bootinfo_t *bootinfo;
65
66static uint64_t iosapic_base = 0xfec00000;
67uintptr_t legacyio_virt_base = 0;
68
69/** Performs ia64-specific initialization before main_bsp() is called. */
70void arch_pre_main(void)
71{
72 init.cnt = min3(bootinfo->taskmap.cnt, TASKMAP_MAX_RECORDS,
73 CONFIG_INIT_TASKS);
74 size_t i;
75
76 for (i = 0; i < init.cnt; i++) {
77 init.tasks[i].paddr =
78 (uintptr_t) bootinfo->taskmap.tasks[i].addr;
79 init.tasks[i].size = bootinfo->taskmap.tasks[i].size;
80 str_cpy(init.tasks[i].name, CONFIG_TASK_NAME_BUFLEN,
81 bootinfo->taskmap.tasks[i].name);
82 }
83}
84
85void arch_pre_mm_init(void)
86{
87}
88
89static void iosapic_init(void)
90{
91 uintptr_t IOSAPIC = km_map(iosapic_base, PAGE_SIZE,
92 PAGE_WRITE | PAGE_NOT_CACHEABLE);
93 int i;
94
95 int myid, myeid;
96
97 myid = ia64_get_cpu_id();
98 myeid = ia64_get_cpu_eid();
99
100 for (i = 0; i < 16; i++) {
101 if (i == 2)
102 continue; /* Disable Cascade interrupt */
103 ((uint32_t *)(IOSAPIC + 0x00))[0] = 0x10 + 2 * i;
104 srlz_d();
105 ((uint32_t *)(IOSAPIC + 0x10))[0] = LEGACY_INTERRUPT_BASE + i;
106 srlz_d();
107 ((uint32_t *)(IOSAPIC + 0x00))[0] = 0x10 + 2 * i + 1;
108 srlz_d();
109 ((uint32_t *)(IOSAPIC + 0x10))[0] = myid << (56 - 32) |
110 myeid << (48 - 32);
111 srlz_d();
112 }
113
114}
115
116void arch_post_mm_init(void)
117{
118 if (config.cpu_active == 1) {
119 /* Map the page with legacy I/O. */
120 legacyio_virt_base = km_map(LEGACYIO_PHYS_BASE, LEGACYIO_SIZE,
121 PAGE_WRITE | PAGE_NOT_CACHEABLE);
122
123 iosapic_init();
124 irq_init(INR_COUNT, INR_COUNT);
125 }
126 it_init();
127}
128
129void arch_post_cpu_init(void)
130{
131}
132
133void arch_pre_smp_init(void)
134{
135}
136
137void arch_post_smp_init(void)
138{
139 static const char *platform;
140
141 /* Set platform name. */
142#ifdef MACHINE_ski
143 platform = "ski";
144#endif
145#ifdef MACHINE_i460GX
146 platform = "pc";
147#endif
148 sysinfo_set_item_data("platform", NULL, (void *) platform,
149 str_size(platform));
150
151#ifdef MACHINE_ski
152 ski_instance_t *ski_instance = skiin_init();
153 if (ski_instance) {
154 srln_instance_t *srln_instance = srln_init();
155 if (srln_instance) {
156 indev_t *sink = stdin_wire();
157 indev_t *srln = srln_wire(srln_instance, sink);
158 skiin_wire(ski_instance, srln);
159 }
160 }
161
162 outdev_t *skidev = skiout_init();
163 if (skidev)
164 stdout_wire(skidev);
165#endif
166
167#ifdef CONFIG_EGA
168 outdev_t *egadev = ega_init(EGA_BASE, EGA_VIDEORAM);
169 if (egadev)
170 stdout_wire(egadev);
171#endif
172
173#ifdef CONFIG_NS16550
174 ns16550_instance_t *ns16550_instance
175 = ns16550_init((ns16550_t *) NS16550_BASE, NS16550_IRQ, NULL, NULL);
176 if (ns16550_instance) {
177 srln_instance_t *srln_instance = srln_init();
178 if (srln_instance) {
179 indev_t *sink = stdin_wire();
180 indev_t *srln = srln_wire(srln_instance, sink);
181 ns16550_wire(ns16550_instance, srln);
182 }
183 }
184
185 sysinfo_set_item_val("kbd", NULL, true);
186 sysinfo_set_item_val("kbd.inr", NULL, NS16550_IRQ);
187 sysinfo_set_item_val("kbd.type", NULL, KBD_NS16550);
188 sysinfo_set_item_val("kbd.address.physical", NULL,
189 (uintptr_t) NS16550_BASE);
190#endif
191
192#ifdef CONFIG_I8042
193 i8042_instance_t *i8042_instance = i8042_init((i8042_t *) I8042_BASE,
194 IRQ_KBD);
195 if (i8042_instance) {
196 kbrd_instance_t *kbrd_instance = kbrd_init();
197 if (kbrd_instance) {
198 indev_t *sink = stdin_wire();
199 indev_t *kbrd = kbrd_wire(kbrd_instance, sink);
200 i8042_wire(i8042_instance, kbrd);
201 }
202 }
203#endif
204
205 sysinfo_set_item_val("ia64_iospace", NULL, true);
206 sysinfo_set_item_val("ia64_iospace.address", NULL, true);
207 sysinfo_set_item_val("ia64_iospace.address.virtual", NULL, LEGACYIO_USER_BASE);
208}
209
210
211/** Enter userspace and never return. */
212void userspace(uspace_arg_t *kernel_uarg)
213{
214 psr_t psr;
215 rsc_t rsc;
216
217 psr.value = psr_read();
218 psr.cpl = PL_USER;
219 psr.i = true; /* start with interrupts enabled */
220 psr.ic = true;
221 psr.ri = 0; /* start with instruction #0 */
222 psr.bn = 1; /* start in bank 0 */
223
224 asm volatile ("mov %0 = ar.rsc\n" : "=r" (rsc.value));
225 rsc.loadrs = 0;
226 rsc.be = false;
227 rsc.pl = PL_USER;
228 rsc.mode = 3; /* eager mode */
229
230 /*
231 * Switch to userspace.
232 *
233 * When calculating stack addresses, mind the stack split between the
234 * memory stack and the RSE stack. Each occuppies
235 * uspace_stack_size / 2 bytes.
236 */
237 switch_to_userspace((uintptr_t) kernel_uarg->uspace_entry,
238 ((uintptr_t) kernel_uarg->uspace_stack) +
239 kernel_uarg->uspace_stack_size / 2 -
240 ALIGN_UP(STACK_ITEM_SIZE, STACK_ALIGNMENT),
241 ((uintptr_t) kernel_uarg->uspace_stack) +
242 kernel_uarg->uspace_stack_size / 2,
243 (uintptr_t) kernel_uarg->uspace_uarg, psr.value, rsc.value);
244
245 while (1);
246}
247
248/** Set thread-local-storage pointer.
249 *
250 * We use r13 (a.k.a. tp) for this purpose.
251 */
252sysarg_t sys_tls_set(uintptr_t addr)
253{
254 return EOK;
255}
256
257void arch_reboot(void)
258{
259 pio_write_8((ioport8_t *)0x64, 0xfe);
260 while (1);
261}
262
263/** Construct function pointer
264 *
265 * @param fptr function pointer structure
266 * @param addr function address
267 * @param caller calling function address
268 *
269 * @return address of the function pointer
270 *
271 */
272void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller)
273{
274 fptr->fnc = (sysarg_t) addr;
275 fptr->gp = ((sysarg_t *) caller)[1];
276
277 return (void *) fptr;
278}
279
280void irq_initialize_arch(irq_t *irq)
281{
282 (void) irq;
283}
284
285/** @}
286 */
Note: See TracBrowser for help on using the repository browser.