[PATCH] bcm43xx: netlink deadlock fix
[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
6#include "linux/config.h"
7#include "linux/kernel.h"
8#include "linux/sched.h"
9#include "linux/notifier.h"
10#include "linux/mm.h"
11#include "linux/types.h"
12#include "linux/tty.h"
13#include "linux/init.h"
14#include "linux/bootmem.h"
15#include "linux/spinlock.h"
16#include "linux/utsname.h"
17#include "linux/sysrq.h"
18#include "linux/seq_file.h"
19#include "linux/delay.h"
20#include "linux/module.h"
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
LT
29#include "user_util.h"
30#include "kern_util.h"
31#include "kern.h"
32#include "mem_user.h"
33#include "mem.h"
34#include "umid.h"
35#include "initrd.h"
36#include "init.h"
37#include "os.h"
38#include "choose-mode.h"
39#include "mode_kern.h"
40#include "mode.h"
cb66504d
PBG
41#ifdef UML_CONFIG_MODE_SKAS
42#include "skas.h"
43#endif
1da177e4
LT
44
45#define DEFAULT_COMMAND_LINE "root=98:0"
46
47/* Changed in linux_main and setup_arch, which run before SMP is started */
16c11163 48static char command_line[COMMAND_LINE_SIZE] = { 0 };
1da177e4 49
16c11163 50static void add_arg(char *arg)
1da177e4
LT
51{
52 if (strlen(command_line) + strlen(arg) + 1 > COMMAND_LINE_SIZE) {
53 printf("add_arg: Too many command line arguments!\n");
54 exit(1);
55 }
56 if(strlen(command_line) > 0)
57 strcat(command_line, " ");
58 strcat(command_line, arg);
59}
60
61struct cpuinfo_um boot_cpu_data = {
62 .loops_per_jiffy = 0,
63 .ipi_pipe = { -1, -1 }
64};
65
66unsigned long thread_saved_pc(struct task_struct *task)
67{
68 return(os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas,
69 task)));
70}
71
72static int show_cpuinfo(struct seq_file *m, void *v)
73{
74 int index = 0;
75
76#ifdef CONFIG_SMP
77 index = (struct cpuinfo_um *) v - cpu_data;
78 if (!cpu_online(index))
79 return 0;
80#endif
81
82 seq_printf(m, "processor\t: %d\n", index);
83 seq_printf(m, "vendor_id\t: User Mode Linux\n");
84 seq_printf(m, "model name\t: UML\n");
85 seq_printf(m, "mode\t\t: %s\n", CHOOSE_MODE("tt", "skas"));
86 seq_printf(m, "host\t\t: %s\n", host_info);
87 seq_printf(m, "bogomips\t: %lu.%02lu\n\n",
88 loops_per_jiffy/(500000/HZ),
89 (loops_per_jiffy/(5000/HZ)) % 100);
90
91 return(0);
92}
93
94static void *c_start(struct seq_file *m, loff_t *pos)
95{
96 return *pos < NR_CPUS ? cpu_data + *pos : NULL;
97}
98
99static void *c_next(struct seq_file *m, void *v, loff_t *pos)
100{
101 ++*pos;
102 return c_start(m, pos);
103}
104
105static void c_stop(struct seq_file *m, void *v)
106{
107}
108
109struct seq_operations cpuinfo_op = {
110 .start = c_start,
111 .next = c_next,
112 .stop = c_stop,
113 .show = show_cpuinfo,
114};
115
1da177e4
LT
116/* Set in linux_main */
117unsigned long host_task_size;
118unsigned long task_size;
119
120unsigned long uml_start;
121
122/* Set in early boot */
123unsigned long uml_physmem;
124unsigned long uml_reserved;
125unsigned long start_vm;
126unsigned long end_vm;
127int ncpus = 1;
128
02215759 129#ifdef CONFIG_CMDLINE_ON_HOST
1da177e4
LT
130/* Pointer set in linux_main, the array itself is private to each thread,
131 * and changed at address space creation time so this poses no concurrency
132 * problems.
133 */
134static char *argv1_begin = NULL;
135static char *argv1_end = NULL;
136#endif
137
138/* Set in early boot */
139static int have_root __initdata = 0;
ae173816 140long long physmem_size = 32 * 1024 * 1024;
1da177e4
LT
141
142void set_cmdline(char *cmd)
143{
02215759 144#ifdef CONFIG_CMDLINE_ON_HOST
1da177e4
LT
145 char *umid, *ptr;
146
147 if(CHOOSE_MODE(honeypot, 0)) return;
148
7eebe8a9
JD
149 umid = get_umid();
150 if(*umid != '\0'){
1da177e4
LT
151 snprintf(argv1_begin,
152 (argv1_end - argv1_begin) * sizeof(*ptr),
153 "(%s) ", umid);
154 ptr = &argv1_begin[strlen(argv1_begin)];
155 }
156 else ptr = argv1_begin;
157
158 snprintf(ptr, (argv1_end - ptr) * sizeof(*ptr), "[%s]", cmd);
159 memset(argv1_begin + strlen(argv1_begin), '\0',
160 argv1_end - argv1_begin - strlen(argv1_begin));
161#endif
162}
163
164static char *usage_string =
165"User Mode Linux v%s\n"
166" available at http://user-mode-linux.sourceforge.net/\n\n";
167
168static int __init uml_version_setup(char *line, int *add)
169{
170 printf("%s\n", system_utsname.release);
171 exit(0);
172
173 return 0;
174}
175
176__uml_setup("--version", uml_version_setup,
177"--version\n"
178" Prints the version number of the kernel.\n\n"
179);
180
181static int __init uml_root_setup(char *line, int *add)
182{
183 have_root = 1;
184 return 0;
185}
186
187__uml_setup("root=", uml_root_setup,
188"root=<file containing the root fs>\n"
189" This is actually used by the generic kernel in exactly the same\n"
190" way as in any other kernel. If you configure a number of block\n"
191" devices and want to boot off something other than ubd0, you \n"
192" would use something like:\n"
193" root=/dev/ubd5\n\n"
194);
195
fbd55779
JD
196#ifndef CONFIG_MODE_TT
197
198static int __init no_skas_debug_setup(char *line, int *add)
199{
200 printf("'debug' is not necessary to gdb UML in skas mode - run \n");
201 printf("'gdb linux' and disable CONFIG_CMDLINE_ON_HOST if gdb \n");
202 printf("doesn't work as expected\n");
203
204 return 0;
205}
206
207__uml_setup("debug", no_skas_debug_setup,
208"debug\n"
209" this flag is not needed to run gdb on UML in skas mode\n\n"
210);
211
212#endif
213
1da177e4
LT
214#ifdef CONFIG_SMP
215static int __init uml_ncpus_setup(char *line, int *add)
216{
217 if (!sscanf(line, "%d", &ncpus)) {
218 printf("Couldn't parse [%s]\n", line);
219 return -1;
220 }
221
222 return 0;
223}
224
225__uml_setup("ncpus=", uml_ncpus_setup,
226"ncpus=<# of desired CPUs>\n"
227" This tells an SMP kernel how many virtual processors to start.\n\n"
228);
229#endif
230
231static int force_tt = 0;
232
233#if defined(CONFIG_MODE_TT) && defined(CONFIG_MODE_SKAS)
234#define DEFAULT_TT 0
235
236static int __init mode_tt_setup(char *line, int *add)
237{
238 force_tt = 1;
239 return(0);
240}
241
242#else
243#ifdef CONFIG_MODE_SKAS
244
245#define DEFAULT_TT 0
246
247static int __init mode_tt_setup(char *line, int *add)
248{
249 printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n");
250 return(0);
251}
252
253#else
254#ifdef CONFIG_MODE_TT
255
256#define DEFAULT_TT 1
257
258static int __init mode_tt_setup(char *line, int *add)
259{
260 printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n");
261 return(0);
262}
263
1da177e4
LT
264#endif
265#endif
266#endif
267
268__uml_setup("mode=tt", mode_tt_setup,
269"mode=tt\n"
270" When both CONFIG_MODE_TT and CONFIG_MODE_SKAS are enabled, this option\n"
271" forces UML to run in tt (tracing thread) mode. It is not the default\n"
272" because it's slower and less secure than skas mode.\n\n"
273);
274
275int mode_tt = DEFAULT_TT;
276
277static int __init Usage(char *line, int *add)
278{
279 const char **p;
280
281 printf(usage_string, system_utsname.release);
282 p = &__uml_help_start;
283 while (p < &__uml_help_end) {
284 printf("%s", *p);
285 p++;
286 }
287 exit(0);
288
289 return 0;
290}
291
292__uml_setup("--help", Usage,
293"--help\n"
294" Prints this message.\n\n"
295);
296
297static int __init uml_checksetup(char *line, int *add)
298{
299 struct uml_param *p;
300
301 p = &__uml_setup_start;
302 while(p < &__uml_setup_end) {
303 int n;
304
305 n = strlen(p->str);
306 if(!strncmp(line, p->str, n)){
307 if (p->setup_func(line + n, add)) return 1;
308 }
309 p++;
310 }
311 return 0;
312}
313
314static void __init uml_postsetup(void)
315{
316 initcall_t *p;
317
318 p = &__uml_postsetup_start;
319 while(p < &__uml_postsetup_end){
320 (*p)();
321 p++;
322 }
323 return;
324}
325
326/* Set during early boot */
327unsigned long brk_start;
328unsigned long end_iomem;
329EXPORT_SYMBOL(end_iomem);
330
331#define MIN_VMALLOC (32 * 1024 * 1024)
332
333int linux_main(int argc, char **argv)
334{
335 unsigned long avail, diff;
336 unsigned long virtmem_size, max_physmem;
337 unsigned int i, add;
cb66504d 338 char * mode;
1da177e4
LT
339
340 for (i = 1; i < argc; i++){
341 if((i == 1) && (argv[i][0] == ' ')) continue;
342 add = 1;
343 uml_checksetup(argv[i], &add);
344 if (add)
345 add_arg(argv[i]);
346 }
347 if(have_root == 0)
348 add_arg(DEFAULT_COMMAND_LINE);
349
60d339f6 350 os_early_checks();
8923648c
PBG
351 if (force_tt)
352 clear_can_do_skas();
1da177e4
LT
353 mode_tt = force_tt ? 1 : !can_do_skas();
354#ifndef CONFIG_MODE_TT
355 if (mode_tt) {
356 /*Since CONFIG_MODE_TT is #undef'ed, force_tt cannot be 1. So,
357 * can_do_skas() returned 0, and the message is correct. */
358 printf("Support for TT mode is disabled, and no SKAS support is present on the host.\n");
359 exit(1);
360 }
361#endif
cb66504d
PBG
362
363#ifndef CONFIG_MODE_SKAS
364 mode = "TT";
365#else
366 /* Show to the user the result of selection */
367 if (mode_tt)
368 mode = "TT";
369 else if (proc_mm && ptrace_faultinfo)
370 mode = "SKAS3";
371 else
372 mode = "SKAS0";
373#endif
374
375 printf("UML running in %s mode\n", mode);
376
1da177e4
LT
377 uml_start = CHOOSE_MODE_PROC(set_task_sizes_tt, set_task_sizes_skas, 0,
378 &host_task_size, &task_size);
379
ea2ba7dc
GS
380 /*
381 * Setting up handlers to 'sig_info' struct
382 */
383 os_fill_handlinfo(handlinfo_kern);
384
1da177e4
LT
385 brk_start = (unsigned long) sbrk(0);
386 CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start);
387 /* Increase physical memory size for exec-shield users
388 so they actually get what they asked for. This should
389 add zero for non-exec shield users */
390
391 diff = UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end);
392 if(diff > 1024 * 1024){
393 printf("Adding %ld bytes to physical memory to account for "
394 "exec-shield gap\n", diff);
395 physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end);
396 }
397
398 uml_physmem = uml_start;
399
400 /* Reserve up to 4M after the current brk */
401 uml_reserved = ROUND_4M(brk_start) + (1 << 22);
402
403 setup_machinename(system_utsname.machine);
404
02215759 405#ifdef CONFIG_CMDLINE_ON_HOST
1da177e4
LT
406 argv1_begin = argv[1];
407 argv1_end = &argv[1][strlen(argv[1])];
408#endif
409
410 highmem = 0;
411 iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK;
412 max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC;
413
414 /* Zones have to begin on a 1 << MAX_ORDER page boundary,
415 * so this makes sure that's true for highmem
416 */
417 max_physmem &= ~((1 << (PAGE_SHIFT + MAX_ORDER)) - 1);
418 if(physmem_size + iomem_size > max_physmem){
419 highmem = physmem_size + iomem_size - max_physmem;
420 physmem_size -= highmem;
421#ifndef CONFIG_HIGHMEM
422 highmem = 0;
423 printf("CONFIG_HIGHMEM not enabled - physical memory shrunk "
d9f8b62a 424 "to %Lu bytes\n", physmem_size);
1da177e4
LT
425#endif
426 }
427
428 high_physmem = uml_physmem + physmem_size;
429 end_iomem = high_physmem + iomem_size;
430 high_memory = (void *) end_iomem;
431
432 start_vm = VMALLOC_START;
433
434 setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem);
435 if(init_maps(physmem_size, iomem_size, highmem)){
d9f8b62a
JD
436 printf("Failed to allocate mem_map for %Lu bytes of physical "
437 "memory and %Lu bytes of highmem\n", physmem_size,
1da177e4
LT
438 highmem);
439 exit(1);
440 }
441
442 virtmem_size = physmem_size;
443 avail = get_kmem_end() - start_vm;
444 if(physmem_size > avail) virtmem_size = avail;
445 end_vm = start_vm + virtmem_size;
446
447 if(virtmem_size < physmem_size)
ae173816 448 printf("Kernel virtual memory size shrunk to %lu bytes\n",
1da177e4
LT
449 virtmem_size);
450
451 uml_postsetup();
452
453 task_protections((unsigned long) &init_thread_info);
454 os_flush_stdout();
455
456 return(CHOOSE_MODE(start_uml_tt(), start_uml_skas()));
457}
458
459extern int uml_exitcode;
460
461static int panic_exit(struct notifier_block *self, unsigned long unused1,
462 void *unused2)
463{
464 bust_spinlocks(1);
465 show_regs(&(current->thread.regs));
466 bust_spinlocks(0);
467 uml_exitcode = 1;
468 machine_halt();
469 return(0);
470}
471
472static struct notifier_block panic_exit_notifier = {
473 .notifier_call = panic_exit,
474 .next = NULL,
475 .priority = 0
476};
477
478void __init setup_arch(char **cmdline_p)
479{
e041c683
AS
480 atomic_notifier_chain_register(&panic_notifier_list,
481 &panic_exit_notifier);
1da177e4 482 paging_init();
16c11163 483 strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
1da177e4
LT
484 *cmdline_p = command_line;
485 setup_hostinfo();
486}
487
488void __init check_bugs(void)
489{
490 arch_check_bugs();
8e367065 491 os_check_bugs();
1da177e4
LT
492}
493
9a0b5817
GH
494void apply_alternatives(struct alt_instr *start, struct alt_instr *end)
495{
496}
497
498void alternatives_smp_module_add(struct module *mod, char *name,
499 void *locks, void *locks_end,
500 void *text, void *text_end)
501{
502}
503
504void alternatives_smp_module_del(struct module *mod)
1da177e4
LT
505{
506}
This page took 0.175043 seconds and 5 git commands to generate.