uml: remove code made redundant by CHOOSE_MODE removal
[deliverable/linux.git] / arch / um / kernel / um_arch.c
CommitLineData
ea2ba7dc 1/*
1da177e4
LT
2 * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
1da177e4
LT
6#include "linux/kernel.h"
7#include "linux/sched.h"
8#include "linux/notifier.h"
9#include "linux/mm.h"
10#include "linux/types.h"
11#include "linux/tty.h"
12#include "linux/init.h"
13#include "linux/bootmem.h"
14#include "linux/spinlock.h"
15#include "linux/utsname.h"
16#include "linux/sysrq.h"
17#include "linux/seq_file.h"
18#include "linux/delay.h"
19#include "linux/module.h"
b4ffb6ad 20#include "linux/utsname.h"
1da177e4
LT
21#include "asm/page.h"
22#include "asm/pgtable.h"
23#include "asm/ptrace.h"
24#include "asm/elf.h"
25#include "asm/user.h"
16c11163 26#include "asm/setup.h"
1da177e4
LT
27#include "ubd_user.h"
28#include "asm/current.h"
1da177e4 29#include "kern_util.h"
4ff83ce1 30#include "as-layout.h"
eb830759 31#include "arch.h"
1da177e4
LT
32#include "kern.h"
33#include "mem_user.h"
34#include "mem.h"
1da177e4
LT
35#include "initrd.h"
36#include "init.h"
37#include "os.h"
cb66504d 38#include "skas.h"
1da177e4
LT
39
40#define DEFAULT_COMMAND_LINE "root=98:0"
41
1d1497e1 42/* Changed in add_arg and setup_arch, which run before SMP is started */
7a3a06d0 43static char __initdata command_line[COMMAND_LINE_SIZE] = { 0 };
1da177e4 44
7a3a06d0 45static void __init add_arg(char *arg)
1da177e4
LT
46{
47 if (strlen(command_line) + strlen(arg) + 1 > COMMAND_LINE_SIZE) {
48 printf("add_arg: Too many command line arguments!\n");
49 exit(1);
50 }
51 if(strlen(command_line) > 0)
52 strcat(command_line, " ");
53 strcat(command_line, arg);
54}
55
1d1497e1
JD
56/*
57 * These fields are initialized at boot time and not changed.
58 * XXX This structure is used only in the non-SMP case. Maybe this
59 * should be moved to smp.c.
60 */
61struct cpuinfo_um boot_cpu_data = {
1da177e4
LT
62 .loops_per_jiffy = 0,
63 .ipi_pipe = { -1, -1 }
64};
65
66unsigned long thread_saved_pc(struct task_struct *task)
67{
77bf4400
JD
68 /* FIXME: Need to look up userspace_pid by cpu */
69 return os_process_pc(userspace_pid[0]);
1da177e4
LT
70}
71
b4ffb6ad
JD
72/* Changed in setup_arch, which is called in early boot */
73static char host_info[(__NEW_UTS_LEN + 1) * 5];
74
1da177e4
LT
75static int show_cpuinfo(struct seq_file *m, void *v)
76{
77 int index = 0;
78
79#ifdef CONFIG_SMP
80 index = (struct cpuinfo_um *) v - cpu_data;
81 if (!cpu_online(index))
82 return 0;
83#endif
84
85 seq_printf(m, "processor\t: %d\n", index);
86 seq_printf(m, "vendor_id\t: User Mode Linux\n");
87 seq_printf(m, "model name\t: UML\n");
6aa802ce 88 seq_printf(m, "mode\t\t: skas\n");
1da177e4
LT
89 seq_printf(m, "host\t\t: %s\n", host_info);
90 seq_printf(m, "bogomips\t: %lu.%02lu\n\n",
91 loops_per_jiffy/(500000/HZ),
92 (loops_per_jiffy/(5000/HZ)) % 100);
93
a5ed1ffa 94 return 0;
1da177e4
LT
95}
96
97static void *c_start(struct seq_file *m, loff_t *pos)
98{
99 return *pos < NR_CPUS ? cpu_data + *pos : NULL;
100}
101
102static void *c_next(struct seq_file *m, void *v, loff_t *pos)
103{
104 ++*pos;
105 return c_start(m, pos);
106}
107
108static void c_stop(struct seq_file *m, void *v)
109{
110}
111
5e7672ec 112const struct seq_operations cpuinfo_op = {
1da177e4
LT
113 .start = c_start,
114 .next = c_next,
115 .stop = c_stop,
116 .show = show_cpuinfo,
117};
118
1da177e4
LT
119/* Set in linux_main */
120unsigned long host_task_size;
121unsigned long task_size;
1da177e4 122unsigned long uml_physmem;
1d1497e1 123unsigned long uml_reserved; /* Also modified in mem_init */
1da177e4
LT
124unsigned long start_vm;
125unsigned long end_vm;
1d1497e1
JD
126
127/* Set in uml_ncpus_setup */
1da177e4
LT
128int ncpus = 1;
129
1da177e4
LT
130/* Set in early boot */
131static int have_root __initdata = 0;
1d1497e1
JD
132
133/* Set in uml_mem_setup and modified in linux_main */
ae173816 134long long physmem_size = 32 * 1024 * 1024;
1da177e4 135
1da177e4
LT
136static char *usage_string =
137"User Mode Linux v%s\n"
138" available at http://user-mode-linux.sourceforge.net/\n\n";
139
140static int __init uml_version_setup(char *line, int *add)
141{
96b644bd 142 printf("%s\n", init_utsname()->release);
1da177e4
LT
143 exit(0);
144
145 return 0;
146}
147
148__uml_setup("--version", uml_version_setup,
149"--version\n"
150" Prints the version number of the kernel.\n\n"
151);
152
153static int __init uml_root_setup(char *line, int *add)
154{
155 have_root = 1;
156 return 0;
157}
158
159__uml_setup("root=", uml_root_setup,
160"root=<file containing the root fs>\n"
161" This is actually used by the generic kernel in exactly the same\n"
162" way as in any other kernel. If you configure a number of block\n"
163" devices and want to boot off something other than ubd0, you \n"
164" would use something like:\n"
165" root=/dev/ubd5\n\n"
166);
167
fbd55779
JD
168static int __init no_skas_debug_setup(char *line, int *add)
169{
170 printf("'debug' is not necessary to gdb UML in skas mode - run \n");
42fda663 171 printf("'gdb linux'");
fbd55779
JD
172
173 return 0;
174}
175
176__uml_setup("debug", no_skas_debug_setup,
177"debug\n"
178" this flag is not needed to run gdb on UML in skas mode\n\n"
179);
180
1da177e4
LT
181#ifdef CONFIG_SMP
182static int __init uml_ncpus_setup(char *line, int *add)
183{
a5ed1ffa
JD
184 if (!sscanf(line, "%d", &ncpus)) {
185 printf("Couldn't parse [%s]\n", line);
186 return -1;
187 }
1da177e4 188
a5ed1ffa 189 return 0;
1da177e4
LT
190}
191
192__uml_setup("ncpus=", uml_ncpus_setup,
193"ncpus=<# of desired CPUs>\n"
194" This tells an SMP kernel how many virtual processors to start.\n\n"
195);
196#endif
197
1da177e4
LT
198static int __init Usage(char *line, int *add)
199{
a5ed1ffa 200 const char **p;
1da177e4 201
96b644bd 202 printf(usage_string, init_utsname()->release);
a5ed1ffa
JD
203 p = &__uml_help_start;
204 while (p < &__uml_help_end) {
205 printf("%s", *p);
206 p++;
207 }
1da177e4 208 exit(0);
1da177e4
LT
209 return 0;
210}
211
212__uml_setup("--help", Usage,
213"--help\n"
214" Prints this message.\n\n"
215);
216
217static int __init uml_checksetup(char *line, int *add)
218{
219 struct uml_param *p;
220
221 p = &__uml_setup_start;
222 while(p < &__uml_setup_end) {
223 int n;
224
225 n = strlen(p->str);
226 if(!strncmp(line, p->str, n)){
227 if (p->setup_func(line + n, add)) return 1;
228 }
229 p++;
230 }
231 return 0;
232}
233
234static void __init uml_postsetup(void)
235{
236 initcall_t *p;
237
238 p = &__uml_postsetup_start;
239 while(p < &__uml_postsetup_end){
240 (*p)();
241 p++;
242 }
243 return;
244}
245
246/* Set during early boot */
247unsigned long brk_start;
248unsigned long end_iomem;
249EXPORT_SYMBOL(end_iomem);
250
251#define MIN_VMALLOC (32 * 1024 * 1024)
252
23bbd586
JD
253extern char __binary_start;
254
77bf4400
JD
255static unsigned long set_task_sizes_skas(unsigned long *task_size_out)
256{
257 /* Round up to the nearest 4M */
258 unsigned long host_task_size = ROUND_4M((unsigned long)
259 &host_task_size);
260
261 if (!skas_needs_stub)
262 *task_size_out = host_task_size;
263 else *task_size_out = CONFIG_STUB_START & PGDIR_MASK;
264
265 return host_task_size;
266}
267
7a3a06d0 268int __init linux_main(int argc, char **argv)
1da177e4
LT
269{
270 unsigned long avail, diff;
271 unsigned long virtmem_size, max_physmem;
272 unsigned int i, add;
cb66504d 273 char * mode;
1da177e4
LT
274
275 for (i = 1; i < argc; i++){
276 if((i == 1) && (argv[i][0] == ' ')) continue;
277 add = 1;
278 uml_checksetup(argv[i], &add);
279 if (add)
280 add_arg(argv[i]);
281 }
282 if(have_root == 0)
283 add_arg(DEFAULT_COMMAND_LINE);
284
60d339f6 285 os_early_checks();
cb66504d 286
42fda663
JD
287 can_do_skas();
288
289 if (proc_mm && ptrace_faultinfo)
cb66504d
PBG
290 mode = "SKAS3";
291 else
292 mode = "SKAS0";
cb66504d
PBG
293
294 printf("UML running in %s mode\n", mode);
295
6aa802ce 296 host_task_size = set_task_sizes_skas(&task_size);
1da177e4 297
ea2ba7dc 298 /*
a5ed1ffa
JD
299 * Setting up handlers to 'sig_info' struct
300 */
ea2ba7dc
GS
301 os_fill_handlinfo(handlinfo_kern);
302
1da177e4 303 brk_start = (unsigned long) sbrk(0);
77bf4400 304
1da177e4
LT
305 /* Increase physical memory size for exec-shield users
306 so they actually get what they asked for. This should
307 add zero for non-exec shield users */
308
309 diff = UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end);
310 if(diff > 1024 * 1024){
311 printf("Adding %ld bytes to physical memory to account for "
312 "exec-shield gap\n", diff);
313 physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end);
314 }
315
1d1497e1 316 uml_physmem = (unsigned long) &__binary_start & PAGE_MASK;
1da177e4
LT
317
318 /* Reserve up to 4M after the current brk */
319 uml_reserved = ROUND_4M(brk_start) + (1 << 22);
320
96b644bd 321 setup_machinename(init_utsname()->machine);
1da177e4 322
1da177e4
LT
323 highmem = 0;
324 iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK;
325 max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC;
326
327 /* Zones have to begin on a 1 << MAX_ORDER page boundary,
328 * so this makes sure that's true for highmem
329 */
330 max_physmem &= ~((1 << (PAGE_SHIFT + MAX_ORDER)) - 1);
331 if(physmem_size + iomem_size > max_physmem){
332 highmem = physmem_size + iomem_size - max_physmem;
333 physmem_size -= highmem;
334#ifndef CONFIG_HIGHMEM
335 highmem = 0;
336 printf("CONFIG_HIGHMEM not enabled - physical memory shrunk "
d9f8b62a 337 "to %Lu bytes\n", physmem_size);
1da177e4
LT
338#endif
339 }
340
341 high_physmem = uml_physmem + physmem_size;
342 end_iomem = high_physmem + iomem_size;
343 high_memory = (void *) end_iomem;
344
345 start_vm = VMALLOC_START;
346
347 setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem);
348 if(init_maps(physmem_size, iomem_size, highmem)){
d9f8b62a
JD
349 printf("Failed to allocate mem_map for %Lu bytes of physical "
350 "memory and %Lu bytes of highmem\n", physmem_size,
1da177e4
LT
351 highmem);
352 exit(1);
353 }
354
355 virtmem_size = physmem_size;
356 avail = get_kmem_end() - start_vm;
357 if(physmem_size > avail) virtmem_size = avail;
358 end_vm = start_vm + virtmem_size;
359
360 if(virtmem_size < physmem_size)
ae173816 361 printf("Kernel virtual memory size shrunk to %lu bytes\n",
1da177e4
LT
362 virtmem_size);
363
a5ed1ffa 364 uml_postsetup();
1da177e4 365
57598fd7 366 stack_protections((unsigned long) &init_thread_info);
1da177e4
LT
367 os_flush_stdout();
368
77bf4400 369 return start_uml();
1da177e4
LT
370}
371
372extern int uml_exitcode;
373
374static int panic_exit(struct notifier_block *self, unsigned long unused1,
375 void *unused2)
376{
377 bust_spinlocks(1);
378 show_regs(&(current->thread.regs));
379 bust_spinlocks(0);
380 uml_exitcode = 1;
63843c26 381 os_dump_core();
a5ed1ffa 382 return 0;
1da177e4
LT
383}
384
385static struct notifier_block panic_exit_notifier = {
386 .notifier_call = panic_exit,
387 .next = NULL,
388 .priority = 0
389};
390
391void __init setup_arch(char **cmdline_p)
392{
e041c683
AS
393 atomic_notifier_chain_register(&panic_notifier_list,
394 &panic_exit_notifier);
1da177e4 395 paging_init();
19bf7e7a 396 strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
a5ed1ffa 397 *cmdline_p = command_line;
b4ffb6ad 398 setup_hostinfo(host_info, sizeof host_info);
1da177e4
LT
399}
400
401void __init check_bugs(void)
402{
403 arch_check_bugs();
a5ed1ffa 404 os_check_bugs();
1da177e4
LT
405}
406
9a0b5817
GH
407void apply_alternatives(struct alt_instr *start, struct alt_instr *end)
408{
409}
410
c61a8416 411#ifdef CONFIG_SMP
9a0b5817
GH
412void alternatives_smp_module_add(struct module *mod, char *name,
413 void *locks, void *locks_end,
414 void *text, void *text_end)
415{
416}
417
418void alternatives_smp_module_del(struct module *mod)
1da177e4
LT
419{
420}
c61a8416 421#endif
This page took 0.281822 seconds and 5 git commands to generate.