source: mainline/kernel/arch/ia64/src/ia64.c@ a940f1d

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a940f1d 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
RevLine 
[2a0047fc]1/*
[df4ed85]2 * Copyright (c) 2005 Jakub Jermar
[2a0047fc]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
[06e1e95]29/** @addtogroup ia64
[b45c443]30 * @{
31 */
32/** @file
33 */
34
[244f284]35#include <arch.h>
[d99c1d2]36#include <typedefs.h>
[d8db519]37#include <errno.h>
[3a2f8aa]38#include <interrupt.h>
[4872160]39#include <macros.h>
[d8db519]40#include <str.h>
[b994a60]41#include <userspace.h>
[a8c48241]42#include <console/console.h>
[e1be3b6]43#include <syscall/syscall.h>
[d8db519]44#include <sysinfo/sysinfo.h>
45#include <arch/drivers/it.h>
46#include <arch/drivers/kbd.h>
[22f0561]47#include <arch/legacyio.h>
[f245145]48#include <genarch/drivers/ega/ega.h>
[411b6a6]49#include <genarch/drivers/i8042/i8042.h>
[4c84368e]50#include <genarch/drivers/ns16550/ns16550.h>
[d8db519]51#include <genarch/drivers/legacy/ia32/io.h>
52#include <genarch/kbrd/kbrd.h>
53#include <genarch/srln/srln.h>
[22f0561]54#include <mm/page.h>
[d4673296]55#include <mm/km.h>
[22f0561]56
57#ifdef MACHINE_ski
58#include <arch/drivers/ski.h>
59#endif
[59e4864]60
[666773c]61/* NS16550 as a COM 1 */
[449d4ecc]62#define NS16550_IRQ (4 + LEGACY_INTERRUPT_BASE)
[743ffa6e]63
64bootinfo_t *bootinfo;
[586262f]65
[666773c]66static uint64_t iosapic_base = 0xfec00000;
[22f0561]67uintptr_t legacyio_virt_base = 0;
[323a5aaf]68
[06f96234]69/** Performs ia64-specific initialization before main_bsp() is called. */
[6ecc8bce]70void arch_pre_main(void)
71{
[32817cc]72 init.cnt = min3(bootinfo->taskmap.cnt, TASKMAP_MAX_RECORDS,
73 CONFIG_INIT_TASKS);
[4872160]74 size_t i;
[32817cc]75
[6c441cf8]76 for (i = 0; i < init.cnt; i++) {
[32817cc]77 init.tasks[i].paddr =
78 (uintptr_t) bootinfo->taskmap.tasks[i].addr;
[6c441cf8]79 init.tasks[i].size = bootinfo->taskmap.tasks[i].size;
[f4b1535]80 str_cpy(init.tasks[i].name, CONFIG_TASK_NAME_BUFLEN,
81 bootinfo->taskmap.tasks[i].name);
[743ffa6e]82 }
[6ecc8bce]83}
84
[244f284]85void arch_pre_mm_init(void)
86{
87}
88
[323a5aaf]89static void iosapic_init(void)
90{
[adec5b45]91 uintptr_t IOSAPIC = km_map(iosapic_base, PAGE_SIZE,
92 PAGE_WRITE | PAGE_NOT_CACHEABLE);
[323a5aaf]93 int i;
94
[2b70a6e]95 int myid, myeid;
[323a5aaf]96
[666773c]97 myid = ia64_get_cpu_id();
98 myeid = ia64_get_cpu_eid();
[50b3d30]99
[666773c]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;
[323a5aaf]104 srlz_d();
[666773c]105 ((uint32_t *)(IOSAPIC + 0x10))[0] = LEGACY_INTERRUPT_BASE + i;
[323a5aaf]106 srlz_d();
[666773c]107 ((uint32_t *)(IOSAPIC + 0x00))[0] = 0x10 + 2 * i + 1;
[323a5aaf]108 srlz_d();
[666773c]109 ((uint32_t *)(IOSAPIC + 0x10))[0] = myid << (56 - 32) |
110 myeid << (48 - 32);
[323a5aaf]111 srlz_d();
112 }
113
114}
115
[244f284]116void arch_post_mm_init(void)
117{
[666773c]118 if (config.cpu_active == 1) {
[22f0561]119 /* Map the page with legacy I/O. */
[adec5b45]120 legacyio_virt_base = km_map(LEGACYIO_PHYS_BASE, LEGACYIO_SIZE,
121 PAGE_WRITE | PAGE_NOT_CACHEABLE);
[22f0561]122
[323a5aaf]123 iosapic_init();
[59e4864]124 irq_init(INR_COUNT, INR_COUNT);
125 }
[2270bef]126 it_init();
[244f284]127}
[7453929]128
[8576bb4]129void arch_post_cpu_init(void)
130{
[26678e5]131}
132
[7453929]133void arch_pre_smp_init(void)
134{
135}
136
137void arch_post_smp_init(void)
138{
[eff1f033]139 static const char *platform;
140
141 /* Set platform name. */
142#ifdef MACHINE_ski
[3714e79]143 platform = "ski";
[eff1f033]144#endif
145#ifdef MACHINE_i460GX
[26f407e9]146 platform = "pc";
[eff1f033]147#endif
148 sysinfo_set_item_data("platform", NULL, (void *) platform,
149 str_size(platform));
150
[c2417bc]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
[a71c158]162 outdev_t *skidev = skiout_init();
163 if (skidev)
164 stdout_wire(skidev);
[1462d35]165#endif
166
[2270bef]167#ifdef CONFIG_EGA
[a71c158]168 outdev_t *egadev = ega_init(EGA_BASE, EGA_VIDEORAM);
169 if (egadev)
170 stdout_wire(egadev);
[2270bef]171#endif
[1462d35]172
[59e4864]173#ifdef CONFIG_NS16550
[c2417bc]174 ns16550_instance_t *ns16550_instance
[84afc7b]175 = ns16550_init((ns16550_t *) NS16550_BASE, NS16550_IRQ, NULL, NULL);
[c2417bc]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 }
[1462d35]184
[449d4ecc]185 sysinfo_set_item_val("kbd", NULL, true);
186 sysinfo_set_item_val("kbd.inr", NULL, NS16550_IRQ);
[4c7257b]187 sysinfo_set_item_val("kbd.type", NULL, KBD_NS16550);
[ff685c9]188 sysinfo_set_item_val("kbd.address.physical", NULL,
189 (uintptr_t) NS16550_BASE);
[449d4ecc]190#endif
191
192#ifdef CONFIG_I8042
[88dfee7]193 i8042_instance_t *i8042_instance = i8042_init((i8042_t *) I8042_BASE,
194 IRQ_KBD);
[c2417bc]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 }
[59e4864]203#endif
[88dfee7]204
[46321fb]205 sysinfo_set_item_val("ia64_iospace", NULL, true);
206 sysinfo_set_item_val("ia64_iospace.address", NULL, true);
[22f0561]207 sysinfo_set_item_val("ia64_iospace.address.virtual", NULL, LEGACYIO_USER_BASE);
[7453929]208}
[b994a60]209
[59e4864]210
[b994a60]211/** Enter userspace and never return. */
[0f250f9]212void userspace(uspace_arg_t *kernel_uarg)
[b994a60]213{
214 psr_t psr;
215 rsc_t rsc;
216
217 psr.value = psr_read();
218 psr.cpl = PL_USER;
[666773c]219 psr.i = true; /* start with interrupts enabled */
[b994a60]220 psr.ic = true;
[666773c]221 psr.ri = 0; /* start with instruction #0 */
222 psr.bn = 1; /* start in bank 0 */
[b994a60]223
[e7b7be3f]224 asm volatile ("mov %0 = ar.rsc\n" : "=r" (rsc.value));
[b994a60]225 rsc.loadrs = 0;
226 rsc.be = false;
227 rsc.pl = PL_USER;
[666773c]228 rsc.mode = 3; /* eager mode */
[b994a60]229
[2f23341]230 /*
231 * Switch to userspace.
232 *
233 * When calculating stack addresses, mind the stack split between the
[2902e1bb]234 * memory stack and the RSE stack. Each occuppies
235 * uspace_stack_size / 2 bytes.
[2f23341]236 */
[7f1c620]237 switch_to_userspace((uintptr_t) kernel_uarg->uspace_entry,
[2902e1bb]238 ((uintptr_t) kernel_uarg->uspace_stack) +
239 kernel_uarg->uspace_stack_size / 2 -
[666773c]240 ALIGN_UP(STACK_ITEM_SIZE, STACK_ALIGNMENT),
[2902e1bb]241 ((uintptr_t) kernel_uarg->uspace_stack) +
242 kernel_uarg->uspace_stack_size / 2,
[666773c]243 (uintptr_t) kernel_uarg->uspace_uarg, psr.value, rsc.value);
[2902e1bb]244
245 while (1);
[b994a60]246}
[e1be3b6]247
248/** Set thread-local-storage pointer.
249 *
250 * We use r13 (a.k.a. tp) for this purpose.
251 */
[d8db519]252sysarg_t sys_tls_set(uintptr_t addr)
[e1be3b6]253{
[d8db519]254 return EOK;
[41d33ac]255}
[b45c443]256
[f74bbaf]257void arch_reboot(void)
258{
[013c4d6]259 pio_write_8((ioport8_t *)0x64, 0xfe);
[d8db519]260 while (1);
[f74bbaf]261}
262
[6da1013f]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{
[96b02eb9]274 fptr->fnc = (sysarg_t) addr;
275 fptr->gp = ((sysarg_t *) caller)[1];
[6da1013f]276
277 return (void *) fptr;
278}
279
[3a2f8aa]280void irq_initialize_arch(irq_t *irq)
281{
282 (void) irq;
283}
284
[06e1e95]285/** @}
[b45c443]286 */
Note: See TracBrowser for help on using the repository browser.