]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - arch/um/kernel/um_arch.c
[PATCH] uml: move libc-dependent code from signal_user.c
[mirror_ubuntu-zesty-kernel.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"
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
196#ifdef CONFIG_SMP
197static int __init uml_ncpus_setup(char *line, int *add)
198{
199 if (!sscanf(line, "%d", &ncpus)) {
200 printf("Couldn't parse [%s]\n", line);
201 return -1;
202 }
203
204 return 0;
205}
206
207__uml_setup("ncpus=", uml_ncpus_setup,
208"ncpus=<# of desired CPUs>\n"
209" This tells an SMP kernel how many virtual processors to start.\n\n"
210);
211#endif
212
213static int force_tt = 0;
214
215#if defined(CONFIG_MODE_TT) && defined(CONFIG_MODE_SKAS)
216#define DEFAULT_TT 0
217
218static int __init mode_tt_setup(char *line, int *add)
219{
220 force_tt = 1;
221 return(0);
222}
223
224#else
225#ifdef CONFIG_MODE_SKAS
226
227#define DEFAULT_TT 0
228
229static int __init mode_tt_setup(char *line, int *add)
230{
231 printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n");
232 return(0);
233}
234
235#else
236#ifdef CONFIG_MODE_TT
237
238#define DEFAULT_TT 1
239
240static int __init mode_tt_setup(char *line, int *add)
241{
242 printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n");
243 return(0);
244}
245
246#else
247
248#error Either CONFIG_MODE_TT or CONFIG_MODE_SKAS must be enabled
249
250#endif
251#endif
252#endif
253
254__uml_setup("mode=tt", mode_tt_setup,
255"mode=tt\n"
256" When both CONFIG_MODE_TT and CONFIG_MODE_SKAS are enabled, this option\n"
257" forces UML to run in tt (tracing thread) mode. It is not the default\n"
258" because it's slower and less secure than skas mode.\n\n"
259);
260
261int mode_tt = DEFAULT_TT;
262
263static int __init Usage(char *line, int *add)
264{
265 const char **p;
266
267 printf(usage_string, system_utsname.release);
268 p = &__uml_help_start;
269 while (p < &__uml_help_end) {
270 printf("%s", *p);
271 p++;
272 }
273 exit(0);
274
275 return 0;
276}
277
278__uml_setup("--help", Usage,
279"--help\n"
280" Prints this message.\n\n"
281);
282
283static int __init uml_checksetup(char *line, int *add)
284{
285 struct uml_param *p;
286
287 p = &__uml_setup_start;
288 while(p < &__uml_setup_end) {
289 int n;
290
291 n = strlen(p->str);
292 if(!strncmp(line, p->str, n)){
293 if (p->setup_func(line + n, add)) return 1;
294 }
295 p++;
296 }
297 return 0;
298}
299
300static void __init uml_postsetup(void)
301{
302 initcall_t *p;
303
304 p = &__uml_postsetup_start;
305 while(p < &__uml_postsetup_end){
306 (*p)();
307 p++;
308 }
309 return;
310}
311
312/* Set during early boot */
313unsigned long brk_start;
314unsigned long end_iomem;
315EXPORT_SYMBOL(end_iomem);
316
317#define MIN_VMALLOC (32 * 1024 * 1024)
318
319int linux_main(int argc, char **argv)
320{
321 unsigned long avail, diff;
322 unsigned long virtmem_size, max_physmem;
323 unsigned int i, add;
cb66504d 324 char * mode;
1da177e4
LT
325
326 for (i = 1; i < argc; i++){
327 if((i == 1) && (argv[i][0] == ' ')) continue;
328 add = 1;
329 uml_checksetup(argv[i], &add);
330 if (add)
331 add_arg(argv[i]);
332 }
333 if(have_root == 0)
334 add_arg(DEFAULT_COMMAND_LINE);
335
60d339f6 336 os_early_checks();
8923648c
PBG
337 if (force_tt)
338 clear_can_do_skas();
1da177e4
LT
339 mode_tt = force_tt ? 1 : !can_do_skas();
340#ifndef CONFIG_MODE_TT
341 if (mode_tt) {
342 /*Since CONFIG_MODE_TT is #undef'ed, force_tt cannot be 1. So,
343 * can_do_skas() returned 0, and the message is correct. */
344 printf("Support for TT mode is disabled, and no SKAS support is present on the host.\n");
345 exit(1);
346 }
347#endif
cb66504d
PBG
348
349#ifndef CONFIG_MODE_SKAS
350 mode = "TT";
351#else
352 /* Show to the user the result of selection */
353 if (mode_tt)
354 mode = "TT";
355 else if (proc_mm && ptrace_faultinfo)
356 mode = "SKAS3";
357 else
358 mode = "SKAS0";
359#endif
360
361 printf("UML running in %s mode\n", mode);
362
1da177e4
LT
363 uml_start = CHOOSE_MODE_PROC(set_task_sizes_tt, set_task_sizes_skas, 0,
364 &host_task_size, &task_size);
365
1da177e4
LT
366 brk_start = (unsigned long) sbrk(0);
367 CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start);
368 /* Increase physical memory size for exec-shield users
369 so they actually get what they asked for. This should
370 add zero for non-exec shield users */
371
372 diff = UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end);
373 if(diff > 1024 * 1024){
374 printf("Adding %ld bytes to physical memory to account for "
375 "exec-shield gap\n", diff);
376 physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end);
377 }
378
379 uml_physmem = uml_start;
380
381 /* Reserve up to 4M after the current brk */
382 uml_reserved = ROUND_4M(brk_start) + (1 << 22);
383
384 setup_machinename(system_utsname.machine);
385
02215759 386#ifdef CONFIG_CMDLINE_ON_HOST
1da177e4
LT
387 argv1_begin = argv[1];
388 argv1_end = &argv[1][strlen(argv[1])];
389#endif
390
391 highmem = 0;
392 iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK;
393 max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC;
394
395 /* Zones have to begin on a 1 << MAX_ORDER page boundary,
396 * so this makes sure that's true for highmem
397 */
398 max_physmem &= ~((1 << (PAGE_SHIFT + MAX_ORDER)) - 1);
399 if(physmem_size + iomem_size > max_physmem){
400 highmem = physmem_size + iomem_size - max_physmem;
401 physmem_size -= highmem;
402#ifndef CONFIG_HIGHMEM
403 highmem = 0;
404 printf("CONFIG_HIGHMEM not enabled - physical memory shrunk "
ae173816 405 "to %lu bytes\n", physmem_size);
1da177e4
LT
406#endif
407 }
408
409 high_physmem = uml_physmem + physmem_size;
410 end_iomem = high_physmem + iomem_size;
411 high_memory = (void *) end_iomem;
412
413 start_vm = VMALLOC_START;
414
415 setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem);
416 if(init_maps(physmem_size, iomem_size, highmem)){
ae173816
JD
417 printf("Failed to allocate mem_map for %lu bytes of physical "
418 "memory and %lu bytes of highmem\n", physmem_size,
1da177e4
LT
419 highmem);
420 exit(1);
421 }
422
423 virtmem_size = physmem_size;
424 avail = get_kmem_end() - start_vm;
425 if(physmem_size > avail) virtmem_size = avail;
426 end_vm = start_vm + virtmem_size;
427
428 if(virtmem_size < physmem_size)
ae173816 429 printf("Kernel virtual memory size shrunk to %lu bytes\n",
1da177e4
LT
430 virtmem_size);
431
432 uml_postsetup();
433
434 task_protections((unsigned long) &init_thread_info);
435 os_flush_stdout();
436
437 return(CHOOSE_MODE(start_uml_tt(), start_uml_skas()));
438}
439
440extern int uml_exitcode;
441
442static int panic_exit(struct notifier_block *self, unsigned long unused1,
443 void *unused2)
444{
445 bust_spinlocks(1);
446 show_regs(&(current->thread.regs));
447 bust_spinlocks(0);
448 uml_exitcode = 1;
449 machine_halt();
450 return(0);
451}
452
453static struct notifier_block panic_exit_notifier = {
454 .notifier_call = panic_exit,
455 .next = NULL,
456 .priority = 0
457};
458
459void __init setup_arch(char **cmdline_p)
460{
461 notifier_chain_register(&panic_notifier_list, &panic_exit_notifier);
462 paging_init();
16c11163 463 strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
1da177e4
LT
464 *cmdline_p = command_line;
465 setup_hostinfo();
466}
467
468void __init check_bugs(void)
469{
470 arch_check_bugs();
1da177e4
LT
471 check_sigio();
472 check_devanon();
473}
474
475void apply_alternatives(void *start, void *end)
476{
477}