diff options
author | David Woodhouse <dwmw2@shinybook.infradead.org> | 2005-05-03 03:14:09 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@shinybook.infradead.org> | 2005-05-03 03:14:09 -0400 |
commit | 27b030d58c8e72fc7a95187a791bd9406e350f02 (patch) | |
tree | ab3bab7f39a5ce5bab65578a7e08fa4dfdeb198c /arch/s390/kernel | |
parent | 79d20b14a0d651f15b0ef9a22b6cf12d284a6d38 (diff) | |
parent | 6628465e33ca694bd8fd5c3cf4eb7ff9177bc694 (diff) |
Merge with master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r-- | arch/s390/kernel/compat_ioctl.c | 7 | ||||
-rw-r--r-- | arch/s390/kernel/ptrace.c | 5 | ||||
-rw-r--r-- | arch/s390/kernel/s390_ksyms.c | 1 | ||||
-rw-r--r-- | arch/s390/kernel/setup.c | 401 | ||||
-rw-r--r-- | arch/s390/kernel/time.c | 12 | ||||
-rw-r--r-- | arch/s390/kernel/vtime.c | 25 |
6 files changed, 259 insertions, 192 deletions
diff --git a/arch/s390/kernel/compat_ioctl.c b/arch/s390/kernel/compat_ioctl.c index 96571ff7115d..03d03c6d3cbb 100644 --- a/arch/s390/kernel/compat_ioctl.c +++ b/arch/s390/kernel/compat_ioctl.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #define CODE | 16 | #define CODE |
17 | #include "../../../fs/compat_ioctl.c" | 17 | #include "../../../fs/compat_ioctl.c" |
18 | #include <asm/dasd.h> | 18 | #include <asm/dasd.h> |
19 | #include <asm/cmb.h> | ||
19 | #include <asm/tape390.h> | 20 | #include <asm/tape390.h> |
20 | 21 | ||
21 | static int do_ioctl32_pointer(unsigned int fd, unsigned int cmd, | 22 | static int do_ioctl32_pointer(unsigned int fd, unsigned int cmd, |
@@ -58,7 +59,11 @@ COMPATIBLE_IOCTL(BIODASDPRRD) | |||
58 | COMPATIBLE_IOCTL(BIODASDPSRD) | 59 | COMPATIBLE_IOCTL(BIODASDPSRD) |
59 | COMPATIBLE_IOCTL(BIODASDGATTR) | 60 | COMPATIBLE_IOCTL(BIODASDGATTR) |
60 | COMPATIBLE_IOCTL(BIODASDSATTR) | 61 | COMPATIBLE_IOCTL(BIODASDSATTR) |
61 | 62 | #if defined(CONFIG_DASD_CMB) || defined(CONFIG_DASD_CMB_MODULE) | |
63 | COMPATIBLE_IOCTL(BIODASDCMFENABLE) | ||
64 | COMPATIBLE_IOCTL(BIODASDCMFDISABLE) | ||
65 | COMPATIBLE_IOCTL(BIODASDREADALLCMB) | ||
66 | #endif | ||
62 | #endif | 67 | #endif |
63 | 68 | ||
64 | #if defined(CONFIG_S390_TAPE) || defined(CONFIG_S390_TAPE_MODULE) | 69 | #if defined(CONFIG_S390_TAPE) || defined(CONFIG_S390_TAPE_MODULE) |
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 2d546c67f7c3..26889366929a 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/user.h> | 32 | #include <linux/user.h> |
33 | #include <linux/security.h> | 33 | #include <linux/security.h> |
34 | #include <linux/audit.h> | 34 | #include <linux/audit.h> |
35 | #include <linux/signal.h> | ||
35 | 36 | ||
36 | #include <asm/segment.h> | 37 | #include <asm/segment.h> |
37 | #include <asm/page.h> | 38 | #include <asm/page.h> |
@@ -609,7 +610,7 @@ do_ptrace(struct task_struct *child, long request, long addr, long data) | |||
609 | /* continue and stop at next (return from) syscall */ | 610 | /* continue and stop at next (return from) syscall */ |
610 | case PTRACE_CONT: | 611 | case PTRACE_CONT: |
611 | /* restart after signal. */ | 612 | /* restart after signal. */ |
612 | if ((unsigned long) data >= _NSIG) | 613 | if (!valid_signal(data)) |
613 | return -EIO; | 614 | return -EIO; |
614 | if (request == PTRACE_SYSCALL) | 615 | if (request == PTRACE_SYSCALL) |
615 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | 616 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
@@ -637,7 +638,7 @@ do_ptrace(struct task_struct *child, long request, long addr, long data) | |||
637 | 638 | ||
638 | case PTRACE_SINGLESTEP: | 639 | case PTRACE_SINGLESTEP: |
639 | /* set the trap flag. */ | 640 | /* set the trap flag. */ |
640 | if ((unsigned long) data >= _NSIG) | 641 | if (!valid_signal(data)) |
641 | return -EIO; | 642 | return -EIO; |
642 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | 643 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
643 | child->exit_code = data; | 644 | child->exit_code = data; |
diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c index 11fd6d556d8f..bee654abb6d3 100644 --- a/arch/s390/kernel/s390_ksyms.c +++ b/arch/s390/kernel/s390_ksyms.c | |||
@@ -34,7 +34,6 @@ EXPORT_SYMBOL(__clear_user_asm); | |||
34 | EXPORT_SYMBOL(__strncpy_from_user_asm); | 34 | EXPORT_SYMBOL(__strncpy_from_user_asm); |
35 | EXPORT_SYMBOL(__strnlen_user_asm); | 35 | EXPORT_SYMBOL(__strnlen_user_asm); |
36 | EXPORT_SYMBOL(diag10); | 36 | EXPORT_SYMBOL(diag10); |
37 | EXPORT_SYMBOL(default_storage_key); | ||
38 | 37 | ||
39 | /* | 38 | /* |
40 | * semaphore ops | 39 | * semaphore ops |
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index c879c40aa7a5..df83215beac3 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c | |||
@@ -44,6 +44,8 @@ | |||
44 | #include <asm/cpcmd.h> | 44 | #include <asm/cpcmd.h> |
45 | #include <asm/lowcore.h> | 45 | #include <asm/lowcore.h> |
46 | #include <asm/irq.h> | 46 | #include <asm/irq.h> |
47 | #include <asm/page.h> | ||
48 | #include <asm/ptrace.h> | ||
47 | 49 | ||
48 | /* | 50 | /* |
49 | * Machine setup.. | 51 | * Machine setup.. |
@@ -53,13 +55,14 @@ unsigned int console_devno = -1; | |||
53 | unsigned int console_irq = -1; | 55 | unsigned int console_irq = -1; |
54 | unsigned long memory_size = 0; | 56 | unsigned long memory_size = 0; |
55 | unsigned long machine_flags = 0; | 57 | unsigned long machine_flags = 0; |
56 | unsigned int default_storage_key = 0; | ||
57 | struct { | 58 | struct { |
58 | unsigned long addr, size, type; | 59 | unsigned long addr, size, type; |
59 | } memory_chunk[MEMORY_CHUNKS] = { { 0 } }; | 60 | } memory_chunk[MEMORY_CHUNKS] = { { 0 } }; |
60 | #define CHUNK_READ_WRITE 0 | 61 | #define CHUNK_READ_WRITE 0 |
61 | #define CHUNK_READ_ONLY 1 | 62 | #define CHUNK_READ_ONLY 1 |
62 | volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */ | 63 | volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */ |
64 | unsigned long __initdata zholes_size[MAX_NR_ZONES]; | ||
65 | static unsigned long __initdata memory_end; | ||
63 | 66 | ||
64 | /* | 67 | /* |
65 | * Setup options | 68 | * Setup options |
@@ -78,11 +81,15 @@ static char command_line[COMMAND_LINE_SIZE] = { 0, }; | |||
78 | 81 | ||
79 | static struct resource code_resource = { | 82 | static struct resource code_resource = { |
80 | .name = "Kernel code", | 83 | .name = "Kernel code", |
84 | .start = (unsigned long) &_text, | ||
85 | .end = (unsigned long) &_etext - 1, | ||
81 | .flags = IORESOURCE_BUSY | IORESOURCE_MEM, | 86 | .flags = IORESOURCE_BUSY | IORESOURCE_MEM, |
82 | }; | 87 | }; |
83 | 88 | ||
84 | static struct resource data_resource = { | 89 | static struct resource data_resource = { |
85 | .name = "Kernel data", | 90 | .name = "Kernel data", |
91 | .start = (unsigned long) &_etext, | ||
92 | .end = (unsigned long) &_edata - 1, | ||
86 | .flags = IORESOURCE_BUSY | IORESOURCE_MEM, | 93 | .flags = IORESOURCE_BUSY | IORESOURCE_MEM, |
87 | }; | 94 | }; |
88 | 95 | ||
@@ -310,90 +317,50 @@ void machine_power_off(void) | |||
310 | 317 | ||
311 | EXPORT_SYMBOL(machine_power_off); | 318 | EXPORT_SYMBOL(machine_power_off); |
312 | 319 | ||
313 | /* | 320 | static void __init |
314 | * Setup function called from init/main.c just after the banner | 321 | add_memory_hole(unsigned long start, unsigned long end) |
315 | * was printed. | 322 | { |
316 | */ | 323 | unsigned long dma_pfn = MAX_DMA_ADDRESS >> PAGE_SHIFT; |
317 | extern char _pstart, _pend, _stext; | 324 | |
325 | if (end <= dma_pfn) | ||
326 | zholes_size[ZONE_DMA] += end - start + 1; | ||
327 | else if (start > dma_pfn) | ||
328 | zholes_size[ZONE_NORMAL] += end - start + 1; | ||
329 | else { | ||
330 | zholes_size[ZONE_DMA] += dma_pfn - start + 1; | ||
331 | zholes_size[ZONE_NORMAL] += end - dma_pfn; | ||
332 | } | ||
333 | } | ||
318 | 334 | ||
319 | void __init setup_arch(char **cmdline_p) | 335 | static void __init |
336 | parse_cmdline_early(char **cmdline_p) | ||
320 | { | 337 | { |
321 | unsigned long bootmap_size; | 338 | char c = ' ', cn, *to = command_line, *from = COMMAND_LINE; |
322 | unsigned long memory_start, memory_end; | 339 | unsigned long delay = 0; |
323 | char c = ' ', cn, *to = command_line, *from = COMMAND_LINE; | ||
324 | unsigned long start_pfn, end_pfn; | ||
325 | static unsigned int smptrap=0; | ||
326 | unsigned long delay = 0; | ||
327 | struct _lowcore *lc; | ||
328 | int i; | ||
329 | 340 | ||
330 | if (smptrap) | 341 | /* Save unparsed command line copy for /proc/cmdline */ |
331 | return; | 342 | memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE); |
332 | smptrap=1; | 343 | saved_command_line[COMMAND_LINE_SIZE-1] = '\0'; |
333 | 344 | ||
334 | /* | 345 | for (;;) { |
335 | * print what head.S has found out about the machine | 346 | /* |
336 | */ | 347 | * "mem=XXX[kKmM]" sets memsize |
337 | #ifndef CONFIG_ARCH_S390X | 348 | */ |
338 | printk((MACHINE_IS_VM) ? | 349 | if (c == ' ' && strncmp(from, "mem=", 4) == 0) { |
339 | "We are running under VM (31 bit mode)\n" : | 350 | memory_end = simple_strtoul(from+4, &from, 0); |
340 | "We are running native (31 bit mode)\n"); | 351 | if ( *from == 'K' || *from == 'k' ) { |
341 | printk((MACHINE_HAS_IEEE) ? | 352 | memory_end = memory_end << 10; |
342 | "This machine has an IEEE fpu\n" : | 353 | from++; |
343 | "This machine has no IEEE fpu\n"); | 354 | } else if ( *from == 'M' || *from == 'm' ) { |
344 | #else /* CONFIG_ARCH_S390X */ | 355 | memory_end = memory_end << 20; |
345 | printk((MACHINE_IS_VM) ? | 356 | from++; |
346 | "We are running under VM (64 bit mode)\n" : | 357 | } |
347 | "We are running native (64 bit mode)\n"); | 358 | } |
348 | #endif /* CONFIG_ARCH_S390X */ | 359 | /* |
349 | 360 | * "ipldelay=XXX[sm]" sets ipl delay in seconds or minutes | |
350 | ROOT_DEV = Root_RAM0; | 361 | */ |
351 | memory_start = (unsigned long) &_end; /* fixit if use $CODELO etc*/ | 362 | if (c == ' ' && strncmp(from, "ipldelay=", 9) == 0) { |
352 | #ifndef CONFIG_ARCH_S390X | 363 | delay = simple_strtoul(from+9, &from, 0); |
353 | memory_end = memory_size & ~0x400000UL; /* align memory end to 4MB */ | ||
354 | /* | ||
355 | * We need some free virtual space to be able to do vmalloc. | ||
356 | * On a machine with 2GB memory we make sure that we have at | ||
357 | * least 128 MB free space for vmalloc. | ||
358 | */ | ||
359 | if (memory_end > 1920*1024*1024) | ||
360 | memory_end = 1920*1024*1024; | ||
361 | #else /* CONFIG_ARCH_S390X */ | ||
362 | memory_end = memory_size & ~0x200000UL; /* detected in head.s */ | ||
363 | #endif /* CONFIG_ARCH_S390X */ | ||
364 | init_mm.start_code = PAGE_OFFSET; | ||
365 | init_mm.end_code = (unsigned long) &_etext; | ||
366 | init_mm.end_data = (unsigned long) &_edata; | ||
367 | init_mm.brk = (unsigned long) &_end; | ||
368 | |||
369 | code_resource.start = (unsigned long) &_text; | ||
370 | code_resource.end = (unsigned long) &_etext - 1; | ||
371 | data_resource.start = (unsigned long) &_etext; | ||
372 | data_resource.end = (unsigned long) &_edata - 1; | ||
373 | |||
374 | /* Save unparsed command line copy for /proc/cmdline */ | ||
375 | memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE); | ||
376 | saved_command_line[COMMAND_LINE_SIZE-1] = '\0'; | ||
377 | |||
378 | for (;;) { | ||
379 | /* | ||
380 | * "mem=XXX[kKmM]" sets memsize | ||
381 | */ | ||
382 | if (c == ' ' && strncmp(from, "mem=", 4) == 0) { | ||
383 | memory_end = simple_strtoul(from+4, &from, 0); | ||
384 | if ( *from == 'K' || *from == 'k' ) { | ||
385 | memory_end = memory_end << 10; | ||
386 | from++; | ||
387 | } else if ( *from == 'M' || *from == 'm' ) { | ||
388 | memory_end = memory_end << 20; | ||
389 | from++; | ||
390 | } | ||
391 | } | ||
392 | /* | ||
393 | * "ipldelay=XXX[sm]" sets ipl delay in seconds or minutes | ||
394 | */ | ||
395 | if (c == ' ' && strncmp(from, "ipldelay=", 9) == 0) { | ||
396 | delay = simple_strtoul(from+9, &from, 0); | ||
397 | if (*from == 's' || *from == 'S') { | 364 | if (*from == 's' || *from == 'S') { |
398 | delay = delay*1000000; | 365 | delay = delay*1000000; |
399 | from++; | 366 | from++; |
@@ -403,24 +370,110 @@ void __init setup_arch(char **cmdline_p) | |||
403 | } | 370 | } |
404 | /* now wait for the requested amount of time */ | 371 | /* now wait for the requested amount of time */ |
405 | udelay(delay); | 372 | udelay(delay); |
406 | } | 373 | } |
407 | cn = *(from++); | 374 | cn = *(from++); |
408 | if (!cn) | 375 | if (!cn) |
409 | break; | 376 | break; |
410 | if (cn == '\n') | 377 | if (cn == '\n') |
411 | cn = ' '; /* replace newlines with space */ | 378 | cn = ' '; /* replace newlines with space */ |
412 | if (cn == 0x0d) | 379 | if (cn == 0x0d) |
413 | cn = ' '; /* replace 0x0d with space */ | 380 | cn = ' '; /* replace 0x0d with space */ |
414 | if (cn == ' ' && c == ' ') | 381 | if (cn == ' ' && c == ' ') |
415 | continue; /* remove additional spaces */ | 382 | continue; /* remove additional spaces */ |
416 | c = cn; | 383 | c = cn; |
417 | if (to - command_line >= COMMAND_LINE_SIZE) | 384 | if (to - command_line >= COMMAND_LINE_SIZE) |
418 | break; | 385 | break; |
419 | *(to++) = c; | 386 | *(to++) = c; |
420 | } | 387 | } |
421 | if (c == ' ' && to > command_line) to--; | 388 | if (c == ' ' && to > command_line) to--; |
422 | *to = '\0'; | 389 | *to = '\0'; |
423 | *cmdline_p = command_line; | 390 | *cmdline_p = command_line; |
391 | } | ||
392 | |||
393 | static void __init | ||
394 | setup_lowcore(void) | ||
395 | { | ||
396 | struct _lowcore *lc; | ||
397 | int lc_pages; | ||
398 | |||
399 | /* | ||
400 | * Setup lowcore for boot cpu | ||
401 | */ | ||
402 | lc_pages = sizeof(void *) == 8 ? 2 : 1; | ||
403 | lc = (struct _lowcore *) | ||
404 | __alloc_bootmem(lc_pages * PAGE_SIZE, lc_pages * PAGE_SIZE, 0); | ||
405 | memset(lc, 0, lc_pages * PAGE_SIZE); | ||
406 | lc->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY; | ||
407 | lc->restart_psw.addr = | ||
408 | PSW_ADDR_AMODE | (unsigned long) restart_int_handler; | ||
409 | lc->external_new_psw.mask = PSW_KERNEL_BITS; | ||
410 | lc->external_new_psw.addr = | ||
411 | PSW_ADDR_AMODE | (unsigned long) ext_int_handler; | ||
412 | lc->svc_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_IO | PSW_MASK_EXT; | ||
413 | lc->svc_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) system_call; | ||
414 | lc->program_new_psw.mask = PSW_KERNEL_BITS; | ||
415 | lc->program_new_psw.addr = | ||
416 | PSW_ADDR_AMODE | (unsigned long)pgm_check_handler; | ||
417 | lc->mcck_new_psw.mask = PSW_KERNEL_BITS; | ||
418 | lc->mcck_new_psw.addr = | ||
419 | PSW_ADDR_AMODE | (unsigned long) mcck_int_handler; | ||
420 | lc->io_new_psw.mask = PSW_KERNEL_BITS; | ||
421 | lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler; | ||
422 | lc->ipl_device = S390_lowcore.ipl_device; | ||
423 | lc->jiffy_timer = -1LL; | ||
424 | lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE; | ||
425 | lc->async_stack = (unsigned long) | ||
426 | __alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0) + ASYNC_SIZE; | ||
427 | #ifdef CONFIG_CHECK_STACK | ||
428 | lc->panic_stack = (unsigned long) | ||
429 | __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0) + PAGE_SIZE; | ||
430 | #endif | ||
431 | lc->current_task = (unsigned long) init_thread_union.thread_info.task; | ||
432 | lc->thread_info = (unsigned long) &init_thread_union; | ||
433 | #ifdef CONFIG_ARCH_S390X | ||
434 | if (MACHINE_HAS_DIAG44) | ||
435 | lc->diag44_opcode = 0x83000044; | ||
436 | else | ||
437 | lc->diag44_opcode = 0x07000700; | ||
438 | #endif /* CONFIG_ARCH_S390X */ | ||
439 | set_prefix((u32)(unsigned long) lc); | ||
440 | } | ||
441 | |||
442 | static void __init | ||
443 | setup_resources(void) | ||
444 | { | ||
445 | struct resource *res; | ||
446 | int i; | ||
447 | |||
448 | for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) { | ||
449 | res = alloc_bootmem_low(sizeof(struct resource)); | ||
450 | res->flags = IORESOURCE_BUSY | IORESOURCE_MEM; | ||
451 | switch (memory_chunk[i].type) { | ||
452 | case CHUNK_READ_WRITE: | ||
453 | res->name = "System RAM"; | ||
454 | break; | ||
455 | case CHUNK_READ_ONLY: | ||
456 | res->name = "System ROM"; | ||
457 | res->flags |= IORESOURCE_READONLY; | ||
458 | break; | ||
459 | default: | ||
460 | res->name = "reserved"; | ||
461 | } | ||
462 | res->start = memory_chunk[i].addr; | ||
463 | res->end = memory_chunk[i].addr + memory_chunk[i].size - 1; | ||
464 | request_resource(&iomem_resource, res); | ||
465 | request_resource(res, &code_resource); | ||
466 | request_resource(res, &data_resource); | ||
467 | } | ||
468 | } | ||
469 | |||
470 | static void __init | ||
471 | setup_memory(void) | ||
472 | { | ||
473 | unsigned long bootmap_size; | ||
474 | unsigned long start_pfn, end_pfn, init_pfn; | ||
475 | unsigned long last_rw_end; | ||
476 | int i; | ||
424 | 477 | ||
425 | /* | 478 | /* |
426 | * partially used pages are not usable - thus | 479 | * partially used pages are not usable - thus |
@@ -429,6 +482,10 @@ void __init setup_arch(char **cmdline_p) | |||
429 | start_pfn = (__pa(&_end) + PAGE_SIZE - 1) >> PAGE_SHIFT; | 482 | start_pfn = (__pa(&_end) + PAGE_SIZE - 1) >> PAGE_SHIFT; |
430 | end_pfn = max_pfn = memory_end >> PAGE_SHIFT; | 483 | end_pfn = max_pfn = memory_end >> PAGE_SHIFT; |
431 | 484 | ||
485 | /* Initialize storage key for kernel pages */ | ||
486 | for (init_pfn = 0 ; init_pfn < start_pfn; init_pfn++) | ||
487 | page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY); | ||
488 | |||
432 | /* | 489 | /* |
433 | * Initialize the boot-time allocator (with low memory only): | 490 | * Initialize the boot-time allocator (with low memory only): |
434 | */ | 491 | */ |
@@ -437,7 +494,9 @@ void __init setup_arch(char **cmdline_p) | |||
437 | /* | 494 | /* |
438 | * Register RAM areas with the bootmem allocator. | 495 | * Register RAM areas with the bootmem allocator. |
439 | */ | 496 | */ |
440 | for (i = 0; i < 16 && memory_chunk[i].size > 0; i++) { | 497 | last_rw_end = start_pfn; |
498 | |||
499 | for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) { | ||
441 | unsigned long start_chunk, end_chunk; | 500 | unsigned long start_chunk, end_chunk; |
442 | 501 | ||
443 | if (memory_chunk[i].type != CHUNK_READ_WRITE) | 502 | if (memory_chunk[i].type != CHUNK_READ_WRITE) |
@@ -450,102 +509,98 @@ void __init setup_arch(char **cmdline_p) | |||
450 | start_chunk = start_pfn; | 509 | start_chunk = start_pfn; |
451 | if (end_chunk > end_pfn) | 510 | if (end_chunk > end_pfn) |
452 | end_chunk = end_pfn; | 511 | end_chunk = end_pfn; |
453 | if (start_chunk < end_chunk) | 512 | if (start_chunk < end_chunk) { |
513 | /* Initialize storage key for RAM pages */ | ||
514 | for (init_pfn = start_chunk ; init_pfn < end_chunk; | ||
515 | init_pfn++) | ||
516 | page_set_storage_key(init_pfn << PAGE_SHIFT, | ||
517 | PAGE_DEFAULT_KEY); | ||
454 | free_bootmem(start_chunk << PAGE_SHIFT, | 518 | free_bootmem(start_chunk << PAGE_SHIFT, |
455 | (end_chunk - start_chunk) << PAGE_SHIFT); | 519 | (end_chunk - start_chunk) << PAGE_SHIFT); |
520 | if (last_rw_end < start_chunk) | ||
521 | add_memory_hole(last_rw_end, start_chunk - 1); | ||
522 | last_rw_end = end_chunk; | ||
523 | } | ||
456 | } | 524 | } |
457 | 525 | ||
458 | /* | 526 | psw_set_key(PAGE_DEFAULT_KEY); |
459 | * Reserve the bootmem bitmap itself as well. We do this in two | 527 | |
460 | * steps (first step was init_bootmem()) because this catches | 528 | if (last_rw_end < end_pfn - 1) |
461 | * the (very unlikely) case of us accidentally initializing the | 529 | add_memory_hole(last_rw_end, end_pfn - 1); |
462 | * bootmem allocator with an invalid RAM area. | 530 | |
463 | */ | 531 | /* |
464 | reserve_bootmem(start_pfn << PAGE_SHIFT, bootmap_size); | 532 | * Reserve the bootmem bitmap itself as well. We do this in two |
533 | * steps (first step was init_bootmem()) because this catches | ||
534 | * the (very unlikely) case of us accidentally initializing the | ||
535 | * bootmem allocator with an invalid RAM area. | ||
536 | */ | ||
537 | reserve_bootmem(start_pfn << PAGE_SHIFT, bootmap_size); | ||
465 | 538 | ||
466 | #ifdef CONFIG_BLK_DEV_INITRD | 539 | #ifdef CONFIG_BLK_DEV_INITRD |
467 | if (INITRD_START) { | 540 | if (INITRD_START) { |
468 | if (INITRD_START + INITRD_SIZE <= memory_end) { | 541 | if (INITRD_START + INITRD_SIZE <= memory_end) { |
469 | reserve_bootmem(INITRD_START, INITRD_SIZE); | 542 | reserve_bootmem(INITRD_START, INITRD_SIZE); |
470 | initrd_start = INITRD_START; | 543 | initrd_start = INITRD_START; |
471 | initrd_end = initrd_start + INITRD_SIZE; | 544 | initrd_end = initrd_start + INITRD_SIZE; |
472 | } else { | 545 | } else { |
473 | printk("initrd extends beyond end of memory " | 546 | printk("initrd extends beyond end of memory " |
474 | "(0x%08lx > 0x%08lx)\ndisabling initrd\n", | 547 | "(0x%08lx > 0x%08lx)\ndisabling initrd\n", |
475 | initrd_start + INITRD_SIZE, memory_end); | 548 | initrd_start + INITRD_SIZE, memory_end); |
476 | initrd_start = initrd_end = 0; | 549 | initrd_start = initrd_end = 0; |
477 | } | 550 | } |
478 | } | 551 | } |
479 | #endif | 552 | #endif |
553 | } | ||
480 | 554 | ||
481 | for (i = 0; i < 16 && memory_chunk[i].size > 0; i++) { | 555 | /* |
482 | struct resource *res; | 556 | * Setup function called from init/main.c just after the banner |
483 | 557 | * was printed. | |
484 | res = alloc_bootmem_low(sizeof(struct resource)); | 558 | */ |
485 | res->flags = IORESOURCE_BUSY | IORESOURCE_MEM; | ||
486 | |||
487 | switch (memory_chunk[i].type) { | ||
488 | case CHUNK_READ_WRITE: | ||
489 | res->name = "System RAM"; | ||
490 | break; | ||
491 | case CHUNK_READ_ONLY: | ||
492 | res->name = "System ROM"; | ||
493 | res->flags |= IORESOURCE_READONLY; | ||
494 | break; | ||
495 | default: | ||
496 | res->name = "reserved"; | ||
497 | } | ||
498 | res->start = memory_chunk[i].addr; | ||
499 | res->end = memory_chunk[i].addr + memory_chunk[i].size - 1; | ||
500 | request_resource(&iomem_resource, res); | ||
501 | request_resource(res, &code_resource); | ||
502 | request_resource(res, &data_resource); | ||
503 | } | ||
504 | 559 | ||
560 | void __init | ||
561 | setup_arch(char **cmdline_p) | ||
562 | { | ||
505 | /* | 563 | /* |
506 | * Setup lowcore for boot cpu | 564 | * print what head.S has found out about the machine |
507 | */ | 565 | */ |
508 | #ifndef CONFIG_ARCH_S390X | 566 | #ifndef CONFIG_ARCH_S390X |
509 | lc = (struct _lowcore *) __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0); | 567 | printk((MACHINE_IS_VM) ? |
510 | memset(lc, 0, PAGE_SIZE); | 568 | "We are running under VM (31 bit mode)\n" : |
569 | "We are running native (31 bit mode)\n"); | ||
570 | printk((MACHINE_HAS_IEEE) ? | ||
571 | "This machine has an IEEE fpu\n" : | ||
572 | "This machine has no IEEE fpu\n"); | ||
511 | #else /* CONFIG_ARCH_S390X */ | 573 | #else /* CONFIG_ARCH_S390X */ |
512 | lc = (struct _lowcore *) __alloc_bootmem(2*PAGE_SIZE, 2*PAGE_SIZE, 0); | 574 | printk((MACHINE_IS_VM) ? |
513 | memset(lc, 0, 2*PAGE_SIZE); | 575 | "We are running under VM (64 bit mode)\n" : |
576 | "We are running native (64 bit mode)\n"); | ||
514 | #endif /* CONFIG_ARCH_S390X */ | 577 | #endif /* CONFIG_ARCH_S390X */ |
515 | lc->restart_psw.mask = PSW_BASE_BITS; | 578 | |
516 | lc->restart_psw.addr = | 579 | ROOT_DEV = Root_RAM0; |
517 | PSW_ADDR_AMODE | (unsigned long) restart_int_handler; | 580 | #ifndef CONFIG_ARCH_S390X |
518 | lc->external_new_psw.mask = PSW_KERNEL_BITS; | 581 | memory_end = memory_size & ~0x400000UL; /* align memory end to 4MB */ |
519 | lc->external_new_psw.addr = | 582 | /* |
520 | PSW_ADDR_AMODE | (unsigned long) ext_int_handler; | 583 | * We need some free virtual space to be able to do vmalloc. |
521 | lc->svc_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_IO | PSW_MASK_EXT; | 584 | * On a machine with 2GB memory we make sure that we have at |
522 | lc->svc_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) system_call; | 585 | * least 128 MB free space for vmalloc. |
523 | lc->program_new_psw.mask = PSW_KERNEL_BITS; | 586 | */ |
524 | lc->program_new_psw.addr = | 587 | if (memory_end > 1920*1024*1024) |
525 | PSW_ADDR_AMODE | (unsigned long)pgm_check_handler; | 588 | memory_end = 1920*1024*1024; |
526 | lc->mcck_new_psw.mask = PSW_KERNEL_BITS; | 589 | #else /* CONFIG_ARCH_S390X */ |
527 | lc->mcck_new_psw.addr = | 590 | memory_end = memory_size & ~0x200000UL; /* detected in head.s */ |
528 | PSW_ADDR_AMODE | (unsigned long) mcck_int_handler; | ||
529 | lc->io_new_psw.mask = PSW_KERNEL_BITS; | ||
530 | lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler; | ||
531 | lc->ipl_device = S390_lowcore.ipl_device; | ||
532 | lc->jiffy_timer = -1LL; | ||
533 | lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE; | ||
534 | lc->async_stack = (unsigned long) | ||
535 | __alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0) + ASYNC_SIZE; | ||
536 | #ifdef CONFIG_CHECK_STACK | ||
537 | lc->panic_stack = (unsigned long) | ||
538 | __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0) + PAGE_SIZE; | ||
539 | #endif | ||
540 | lc->current_task = (unsigned long) init_thread_union.thread_info.task; | ||
541 | lc->thread_info = (unsigned long) &init_thread_union; | ||
542 | #ifdef CONFIG_ARCH_S390X | ||
543 | if (MACHINE_HAS_DIAG44) | ||
544 | lc->diag44_opcode = 0x83000044; | ||
545 | else | ||
546 | lc->diag44_opcode = 0x07000700; | ||
547 | #endif /* CONFIG_ARCH_S390X */ | 591 | #endif /* CONFIG_ARCH_S390X */ |
548 | set_prefix((u32)(unsigned long) lc); | 592 | |
593 | init_mm.start_code = PAGE_OFFSET; | ||
594 | init_mm.end_code = (unsigned long) &_etext; | ||
595 | init_mm.end_data = (unsigned long) &_edata; | ||
596 | init_mm.brk = (unsigned long) &_end; | ||
597 | |||
598 | parse_cmdline_early(cmdline_p); | ||
599 | |||
600 | setup_memory(); | ||
601 | setup_resources(); | ||
602 | setup_lowcore(); | ||
603 | |||
549 | cpu_init(); | 604 | cpu_init(); |
550 | __cpu_logical_map[0] = S390_lowcore.cpu_data.cpu_addr; | 605 | __cpu_logical_map[0] = S390_lowcore.cpu_data.cpu_addr; |
551 | 606 | ||
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 061e81138dc2..8ca485676780 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c | |||
@@ -244,7 +244,7 @@ int sysctl_hz_timer = 1; | |||
244 | */ | 244 | */ |
245 | static inline void stop_hz_timer(void) | 245 | static inline void stop_hz_timer(void) |
246 | { | 246 | { |
247 | __u64 timer; | 247 | __u64 timer, todval; |
248 | 248 | ||
249 | if (sysctl_hz_timer != 0) | 249 | if (sysctl_hz_timer != 0) |
250 | return; | 250 | return; |
@@ -265,8 +265,14 @@ static inline void stop_hz_timer(void) | |||
265 | * for the next event. | 265 | * for the next event. |
266 | */ | 266 | */ |
267 | timer = (__u64) (next_timer_interrupt() - jiffies) + jiffies_64; | 267 | timer = (__u64) (next_timer_interrupt() - jiffies) + jiffies_64; |
268 | timer = jiffies_timer_cc + timer * CLK_TICKS_PER_JIFFY; | 268 | todval = -1ULL; |
269 | asm volatile ("SCKC %0" : : "m" (timer)); | 269 | /* Be careful about overflows. */ |
270 | if (timer < (-1ULL / CLK_TICKS_PER_JIFFY)) { | ||
271 | timer = jiffies_timer_cc + timer * CLK_TICKS_PER_JIFFY; | ||
272 | if (timer >= jiffies_timer_cc) | ||
273 | todval = timer; | ||
274 | } | ||
275 | asm volatile ("SCKC %0" : : "m" (todval)); | ||
270 | } | 276 | } |
271 | 277 | ||
272 | /* | 278 | /* |
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index bb6cf02418a2..fa0726507b3d 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c | |||
@@ -122,12 +122,17 @@ static void start_cpu_timer(void) | |||
122 | struct vtimer_queue *vt_list; | 122 | struct vtimer_queue *vt_list; |
123 | 123 | ||
124 | vt_list = &per_cpu(virt_cpu_timer, smp_processor_id()); | 124 | vt_list = &per_cpu(virt_cpu_timer, smp_processor_id()); |
125 | set_vtimer(vt_list->idle); | 125 | |
126 | /* CPU timer interrupt is pending, don't reprogramm it */ | ||
127 | if (vt_list->idle & 1LL<<63) | ||
128 | return; | ||
129 | |||
130 | if (!list_empty(&vt_list->list)) | ||
131 | set_vtimer(vt_list->idle); | ||
126 | } | 132 | } |
127 | 133 | ||
128 | static void stop_cpu_timer(void) | 134 | static void stop_cpu_timer(void) |
129 | { | 135 | { |
130 | __u64 done; | ||
131 | struct vtimer_queue *vt_list; | 136 | struct vtimer_queue *vt_list; |
132 | 137 | ||
133 | vt_list = &per_cpu(virt_cpu_timer, smp_processor_id()); | 138 | vt_list = &per_cpu(virt_cpu_timer, smp_processor_id()); |
@@ -138,21 +143,17 @@ static void stop_cpu_timer(void) | |||
138 | goto fire; | 143 | goto fire; |
139 | } | 144 | } |
140 | 145 | ||
141 | /* store progress */ | 146 | /* store the actual expire value */ |
142 | asm volatile ("STPT %0" : "=m" (done)); | 147 | asm volatile ("STPT %0" : "=m" (vt_list->idle)); |
143 | 148 | ||
144 | /* | 149 | /* |
145 | * If done is negative we do not stop the CPU timer | 150 | * If the CPU timer is negative we don't reprogramm |
146 | * because we will get instantly an interrupt that | 151 | * it because we will get instantly an interrupt. |
147 | * will start the CPU timer again. | ||
148 | */ | 152 | */ |
149 | if (done & 1LL<<63) | 153 | if (vt_list->idle & 1LL<<63) |
150 | return; | 154 | return; |
151 | else | ||
152 | vt_list->offset += vt_list->to_expire - done; | ||
153 | 155 | ||
154 | /* save the actual expire value */ | 156 | vt_list->offset += vt_list->to_expire - vt_list->idle; |
155 | vt_list->idle = done; | ||
156 | 157 | ||
157 | /* | 158 | /* |
158 | * We cannot halt the CPU timer, we just write a value that | 159 | * We cannot halt the CPU timer, we just write a value that |