aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@shinybook.infradead.org>2005-05-03 03:14:09 -0400
committerDavid Woodhouse <dwmw2@shinybook.infradead.org>2005-05-03 03:14:09 -0400
commit27b030d58c8e72fc7a95187a791bd9406e350f02 (patch)
treeab3bab7f39a5ce5bab65578a7e08fa4dfdeb198c /arch/s390/kernel
parent79d20b14a0d651f15b0ef9a22b6cf12d284a6d38 (diff)
parent6628465e33ca694bd8fd5c3cf4eb7ff9177bc694 (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.c7
-rw-r--r--arch/s390/kernel/ptrace.c5
-rw-r--r--arch/s390/kernel/s390_ksyms.c1
-rw-r--r--arch/s390/kernel/setup.c401
-rw-r--r--arch/s390/kernel/time.c12
-rw-r--r--arch/s390/kernel/vtime.c25
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
21static int do_ioctl32_pointer(unsigned int fd, unsigned int cmd, 22static int do_ioctl32_pointer(unsigned int fd, unsigned int cmd,
@@ -58,7 +59,11 @@ COMPATIBLE_IOCTL(BIODASDPRRD)
58COMPATIBLE_IOCTL(BIODASDPSRD) 59COMPATIBLE_IOCTL(BIODASDPSRD)
59COMPATIBLE_IOCTL(BIODASDGATTR) 60COMPATIBLE_IOCTL(BIODASDGATTR)
60COMPATIBLE_IOCTL(BIODASDSATTR) 61COMPATIBLE_IOCTL(BIODASDSATTR)
61 62#if defined(CONFIG_DASD_CMB) || defined(CONFIG_DASD_CMB_MODULE)
63COMPATIBLE_IOCTL(BIODASDCMFENABLE)
64COMPATIBLE_IOCTL(BIODASDCMFDISABLE)
65COMPATIBLE_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);
34EXPORT_SYMBOL(__strncpy_from_user_asm); 34EXPORT_SYMBOL(__strncpy_from_user_asm);
35EXPORT_SYMBOL(__strnlen_user_asm); 35EXPORT_SYMBOL(__strnlen_user_asm);
36EXPORT_SYMBOL(diag10); 36EXPORT_SYMBOL(diag10);
37EXPORT_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;
53unsigned int console_irq = -1; 55unsigned int console_irq = -1;
54unsigned long memory_size = 0; 56unsigned long memory_size = 0;
55unsigned long machine_flags = 0; 57unsigned long machine_flags = 0;
56unsigned int default_storage_key = 0;
57struct { 58struct {
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
62volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */ 63volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */
64unsigned long __initdata zholes_size[MAX_NR_ZONES];
65static 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
79static struct resource code_resource = { 82static 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
84static struct resource data_resource = { 89static 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
311EXPORT_SYMBOL(machine_power_off); 318EXPORT_SYMBOL(machine_power_off);
312 319
313/* 320static void __init
314 * Setup function called from init/main.c just after the banner 321add_memory_hole(unsigned long start, unsigned long end)
315 * was printed. 322{
316 */ 323 unsigned long dma_pfn = MAX_DMA_ADDRESS >> PAGE_SHIFT;
317extern 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
319void __init setup_arch(char **cmdline_p) 335static void __init
336parse_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
393static void __init
394setup_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
442static void __init
443setup_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
470static void __init
471setup_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
560void __init
561setup_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 */
245static inline void stop_hz_timer(void) 245static 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
128static void stop_cpu_timer(void) 134static 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