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