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
17 #include <interrupt.h>
22 static struct psw new_io_psw
= {
29 static struct psw new_ext_psw
= {
33 .ptr
= (u64
) &EXT_INT
,
36 static struct psw new_svc_psw
= {
40 .ptr
= (u64
) &SVC_INT
,
43 static struct psw new_pgm_psw
= {
47 .ptr
= (u64
) &PGM_INT
,
54 const u8 zeropage
[PAGE_SIZE
];
56 /* the time HVF got IPLd */
57 struct datetime ipltime
;
59 static void init_int_stack(void)
63 page
= alloc_pages(0, ZONE_NORMAL
);
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(¤t
->regs
.psw
);
86 static int __finish_loading(void *data
)
88 struct console
*opcon
; /* operator's console */
91 iplsch
= (u32
) (u64
) data
;
94 * Load the config file
96 sysfs
= load_config(iplsch
);
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
);
121 * This is where everything starts
123 void start(u64 __memsize
, u32 __iplsch
)
126 u64 struct_page_bytes
;
135 * save total system memory size
140 * Initialize struct page entries
145 * Calculate address of the first free page (we may have to round
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
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 */
176 * Set up page table entries for the nucleus
181 * Allocate & initialize the interrupt stack
186 * Initialize the io subsystem
191 * Register all the device drivers
196 * Time to enable interrupts => load new psw
198 memset(&psw
, 0, sizeof(struct psw
));
217 * Let's discover all the devices attached
222 * Initialize the process scheduler
227 * Start tracking locking dependencies
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