[PATCH] uml: add host AIO support to block driver
[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"
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;
140long physmem_size = 32 * 1024 * 1024;
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
149 umid = get_umid(1);
150 if(umid != NULL){
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
336 mode_tt = force_tt ? 1 : !can_do_skas();
337#ifndef CONFIG_MODE_TT
338 if (mode_tt) {
339 /*Since CONFIG_MODE_TT is #undef'ed, force_tt cannot be 1. So,
340 * can_do_skas() returned 0, and the message is correct. */
341 printf("Support for TT mode is disabled, and no SKAS support is present on the host.\n");
342 exit(1);
343 }
344#endif
cb66504d
PBG
345
346#ifndef CONFIG_MODE_SKAS
347 mode = "TT";
348#else
349 /* Show to the user the result of selection */
350 if (mode_tt)
351 mode = "TT";
352 else if (proc_mm && ptrace_faultinfo)
353 mode = "SKAS3";
354 else
355 mode = "SKAS0";
356#endif
357
358 printf("UML running in %s mode\n", mode);
359
1da177e4
LT
360 uml_start = CHOOSE_MODE_PROC(set_task_sizes_tt, set_task_sizes_skas, 0,
361 &host_task_size, &task_size);
362
363 /* Need to check this early because mmapping happens before the
364 * kernel is running.
365 */
366 check_tmpexec();
367
368 brk_start = (unsigned long) sbrk(0);
369 CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start);
370 /* Increase physical memory size for exec-shield users
371 so they actually get what they asked for. This should
372 add zero for non-exec shield users */
373
374 diff = UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end);
375 if(diff > 1024 * 1024){
376 printf("Adding %ld bytes to physical memory to account for "
377 "exec-shield gap\n", diff);
378 physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end);
379 }
380
381 uml_physmem = uml_start;
382
383 /* Reserve up to 4M after the current brk */
384 uml_reserved = ROUND_4M(brk_start) + (1 << 22);
385
386 setup_machinename(system_utsname.machine);
387
02215759 388#ifdef CONFIG_CMDLINE_ON_HOST
1da177e4
LT
389 argv1_begin = argv[1];
390 argv1_end = &argv[1][strlen(argv[1])];
391#endif
392
393 highmem = 0;
394 iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK;
395 max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC;
396
397 /* Zones have to begin on a 1 << MAX_ORDER page boundary,
398 * so this makes sure that's true for highmem
399 */
400 max_physmem &= ~((1 << (PAGE_SHIFT + MAX_ORDER)) - 1);
401 if(physmem_size + iomem_size > max_physmem){
402 highmem = physmem_size + iomem_size - max_physmem;
403 physmem_size -= highmem;
404#ifndef CONFIG_HIGHMEM
405 highmem = 0;
406 printf("CONFIG_HIGHMEM not enabled - physical memory shrunk "
407 "to %ld bytes\n", physmem_size);
408#endif
409 }
410
411 high_physmem = uml_physmem + physmem_size;
412 end_iomem = high_physmem + iomem_size;
413 high_memory = (void *) end_iomem;
414
415 start_vm = VMALLOC_START;
416
417 setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem);
418 if(init_maps(physmem_size, iomem_size, highmem)){
419 printf("Failed to allocate mem_map for %ld bytes of physical "
420 "memory and %ld bytes of highmem\n", physmem_size,
421 highmem);
422 exit(1);
423 }
424
425 virtmem_size = physmem_size;
426 avail = get_kmem_end() - start_vm;
427 if(physmem_size > avail) virtmem_size = avail;
428 end_vm = start_vm + virtmem_size;
429
430 if(virtmem_size < physmem_size)
431 printf("Kernel virtual memory size shrunk to %ld bytes\n",
432 virtmem_size);
433
434 uml_postsetup();
435
436 task_protections((unsigned long) &init_thread_info);
437 os_flush_stdout();
438
439 return(CHOOSE_MODE(start_uml_tt(), start_uml_skas()));
440}
441
442extern int uml_exitcode;
443
444static int panic_exit(struct notifier_block *self, unsigned long unused1,
445 void *unused2)
446{
447 bust_spinlocks(1);
448 show_regs(&(current->thread.regs));
449 bust_spinlocks(0);
450 uml_exitcode = 1;
451 machine_halt();
452 return(0);
453}
454
455static struct notifier_block panic_exit_notifier = {
456 .notifier_call = panic_exit,
457 .next = NULL,
458 .priority = 0
459};
460
461void __init setup_arch(char **cmdline_p)
462{
463 notifier_chain_register(&panic_notifier_list, &panic_exit_notifier);
464 paging_init();
16c11163 465 strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
1da177e4
LT
466 *cmdline_p = command_line;
467 setup_hostinfo();
468}
469
470void __init check_bugs(void)
471{
472 arch_check_bugs();
473 check_ptrace();
474 check_sigio();
475 check_devanon();
476}
477
478void apply_alternatives(void *start, void *end)
479{
480}
This page took 0.092474 seconds and 5 git commands to generate.