cp: revamp directory handling
[hvf.git] / cp / nucleus / init.c
blob8101acb8e2a83157b6db7ebef902cc2153dd5022
1 /*
2 * (C) Copyright 2007-2011 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
4 * This file is released under the GPLv2. See the COPYING file for more
5 * details.
6 */
8 #include <mm.h>
9 #include <dat.h>
10 #include <slab.h>
11 #include <page.h>
12 #include <buddy.h>
13 #include <io.h>
14 #include <sched.h>
15 #include <device.h>
16 #include <console.h>
17 #include <interrupt.h>
18 #include <magic.h>
19 #include <shell.h>
20 #include <sclp.h>
22 static struct psw new_io_psw = {
23 .ea = 1,
24 .ba = 1,
26 .ptr = (u64) &IO_INT,
29 static struct psw new_ext_psw = {
30 .ea = 1,
31 .ba = 1,
33 .ptr = (u64) &EXT_INT,
36 static struct psw new_svc_psw = {
37 .ea = 1,
38 .ba = 1,
40 .ptr = (u64) &SVC_INT,
43 static struct psw new_pgm_psw = {
44 .ea = 1,
45 .ba = 1,
47 .ptr = (u64) &PGM_INT,
50 u8 *int_stack_ptr;
52 struct fs *sysfs;
54 const u8 zeropage[PAGE_SIZE];
56 /* the time HVF got IPLd */
57 struct datetime ipltime;
59 static void init_int_stack(void)
61 struct page *page;
63 page = alloc_pages(0, ZONE_NORMAL);
64 BUG_ON(!page);
66 int_stack_ptr = PAGE_SIZE + (u8*)page_to_addr(page);
69 static void idle_task_body(void)
72 * Warning: hack alert! The following overrides what __init_task
73 * set, this allows us to skip the usual start_task wrapper.
75 current->regs.psw.w = 1;
76 current->regs.psw.ptr = MAGIC_PSW_IDLE_CODE;
79 * Load the new PSW that'll wait with special magic code set
81 lpswe(&current->regs.psw);
83 BUG();
86 static int __finish_loading(void *data)
88 struct console *opcon; /* operator's console */
89 u32 iplsch;
91 iplsch = (u32) (u64) data;
94 * Load the config file
96 sysfs = load_config(iplsch);
97 if (IS_ERR(sysfs))
98 BUG();
101 * IPL is more or less done
103 get_parsed_tod(&ipltime);
105 sclp_msg("IPL AT %02d:%02d:%02d UTC %04d-%02d-%02d\n\n",
106 ipltime.th, ipltime.tm, ipltime.ts, ipltime.dy,
107 ipltime.dm, ipltime.dd);
109 opcon = start_oper_console();
111 con_printf(opcon, "NOW %02d:%02d:%02d UTC %04d-%02d-%02d\n\n",
112 ipltime.th, ipltime.tm, ipltime.ts, ipltime.dy,
113 ipltime.dm, ipltime.dd);
115 spawn_oper_shell(opcon);
117 return 0;
121 * This is where everything starts
123 void start(u64 __memsize, u32 __iplsch)
125 u64 first_free_page;
126 u64 struct_page_bytes;
127 struct psw psw;
130 * ticks starts at 0
132 ticks = 0;
135 * save total system memory size
137 memsize = __memsize;
140 * Initialize struct page entries
142 init_pages();
145 * Calculate address of the first free page (we may have to round
146 * up)
148 struct_page_bytes = (memsize >> PAGE_SHIFT) * sizeof(struct page);
150 first_free_page = (u64) PAGE_INFO_BASE + struct_page_bytes;
151 if (struct_page_bytes & (PAGE_SIZE-1))
152 first_free_page += PAGE_SIZE - (struct_page_bytes & (PAGE_SIZE-1));
155 * Initialize the buddy allocator
157 init_buddy_alloc(first_free_page);
160 * Initialize slab allocator default caches
162 init_slab();
165 * Set up interrupt PSWs
167 memcpy(IO_INT_NEW_PSW, &new_io_psw, sizeof(struct psw));
168 memcpy(EXT_INT_NEW_PSW, &new_ext_psw, sizeof(struct psw));
169 memcpy(SVC_INT_NEW_PSW, &new_svc_psw, sizeof(struct psw));
170 memcpy(PGM_INT_NEW_PSW, &new_pgm_psw, sizeof(struct psw));
172 /* Turn on Low-address Protection */
173 lap_on();
176 * Set up page table entries for the nucleus
178 setup_dat();
181 * Allocate & initialize the interrupt stack
183 init_int_stack();
186 * Initialize the io subsystem
188 init_io();
191 * Register all the device drivers
193 register_drivers();
196 * Time to enable interrupts => load new psw
198 memset(&psw, 0, sizeof(struct psw));
199 psw.io = 1;
200 psw.ea = 1;
201 psw.ba = 1;
203 asm volatile(
204 " larl %%r1,0f\n"
205 " stg %%r1,%0\n"
206 " lpswe %1\n"
207 "0:\n"
208 : /* output */
209 "=m" (psw.ptr)
210 : /* input */
211 "m" (psw)
212 : /* clobbered */
213 "r1"
217 * Let's discover all the devices attached
219 scan_devices();
222 * Initialize the process scheduler
224 init_sched();
227 * Start tracking locking dependencies
229 ldep_on();
232 * Create a thread that'll finish setting everything up for us
234 create_task("*finish-loading", __finish_loading, (void*) (u64) __iplsch);
237 * THIS IS WHERE THE IDLE TASK BEGINS
240 idle_task_body();