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