diff options
Diffstat (limited to 'arch')
210 files changed, 5686 insertions, 6311 deletions
diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c index 0001799db..078aa7d3d 100644 --- a/arch/alpha/kernel/alpha_ksyms.c +++ b/arch/alpha/kernel/alpha_ksyms.c @@ -174,7 +174,7 @@ EXPORT_SYMBOL_NOVERS(__rwsem_wake); * SMP-specific symbols. */ -#ifdef __SMP__ +#ifdef CONFIG_SMP EXPORT_SYMBOL(kernel_flag); EXPORT_SYMBOL(synchronize_irq); EXPORT_SYMBOL(flush_tlb_all); @@ -199,10 +199,10 @@ EXPORT_SYMBOL(debug_spin_trylock); EXPORT_SYMBOL(write_lock); EXPORT_SYMBOL(read_lock); #endif -#else /* __SMP__ */ +#else /* CONFIG_SMP */ EXPORT_SYMBOL(__local_bh_count); EXPORT_SYMBOL(__local_irq_count); -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ EXPORT_SYMBOL(rtc_lock); diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index 55e622d66..33d5eead1 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -4,6 +4,7 @@ * kernel entry-points */ +#include <linux/config.h> #include <asm/system.h> #define SIGCHLD 20 @@ -706,7 +707,7 @@ signal_return: br restore_all .end entSys -#ifdef __SMP__ +#ifdef CONFIG_SMP .globl ret_from_smp_fork .align 3 .ent ret_from_smp_fork @@ -715,7 +716,7 @@ ret_from_smp_fork: mov $17,$16 jsr $31,schedule_tail .end ret_from_smp_fork -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ .align 3 .ent reschedule diff --git a/arch/alpha/kernel/head.S b/arch/alpha/kernel/head.S index 3b004b7f6..4c87ee3a7 100644 --- a/arch/alpha/kernel/head.S +++ b/arch/alpha/kernel/head.S @@ -7,6 +7,7 @@ * the kernel global pointer and jump to the kernel entry-point. */ +#include <linux/config.h> #include <asm/system.h> .globl swapper_pg_dir @@ -30,7 +31,7 @@ __start: call_pal PAL_halt .end __start -#ifdef __SMP__ +#ifdef CONFIG_SMP .align 3 .globl __smp_callin .ent __smp_callin @@ -52,7 +53,7 @@ __smp_callin: jsr $26,smp_callin call_pal PAL_halt .end __smp_callin -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ # # The following two functions are needed for supporting SRM PALcode diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c index 1f454cf48..e47fcd3ca 100644 --- a/arch/alpha/kernel/irq.c +++ b/arch/alpha/kernel/irq.c @@ -373,7 +373,7 @@ register_irq_proc (unsigned int irq) #ifdef CONFIG_SMP /* create /proc/irq/1234/smp_affinity */ - entry = create_proc_entry("smp_affinity", 0700, irq_dir[irq]); + entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]); entry->nlink = 1; entry->data = (void *)(long)irq; @@ -397,7 +397,7 @@ init_irq_proc (void) #ifdef CONFIG_SMP /* create /proc/irq/prof_cpu_mask */ - entry = create_proc_entry("prof_cpu_mask", 0700, root_irq_dir); + entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir); entry->nlink = 1; entry->data = (void *)&prof_cpu_mask; diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c index 81178976a..f9a79c1d6 100644 --- a/arch/alpha/kernel/pci.c +++ b/arch/alpha/kernel/pci.c @@ -110,10 +110,15 @@ void pcibios_align_resource(void *data, struct resource *res, unsigned long size) { struct pci_dev *dev = data; + struct pci_controler *hose = dev->sysdata; unsigned long alignto; unsigned long start = res->start; if (res->flags & IORESOURCE_IO) { + /* Make sure we start at our min on all hoses */ + if (start - hose->io_space->start < PCIBIOS_MIN_IO) + start = PCIBIOS_MIN_IO + hose->io_space->start; + /* * Aligning to 0x800 rather than the minimum base of * 0x400 is an attempt to avoid having devices in @@ -121,11 +126,18 @@ pcibios_align_resource(void *data, struct resource *res, unsigned long size) * probes for EISA cards. * * Adaptecs, especially, resent such intrusions. + * + * The de4x5 driver has the eisa probe conditionalized + * out for Alpha, so lower the minimum base back to 0x400. */ - alignto = MAX(0x800, size); + alignto = MAX(0x400, size); start = ALIGN(start, alignto); } else if (res->flags & IORESOURCE_MEM) { + /* Make sure we start at our min on all hoses */ + if (start - hose->mem_space->start < PCIBIOS_MIN_MEM) + start = PCIBIOS_MIN_MEM + hose->io_space->start; + /* * The following holds at least for the Low Cost * Alpha implementation of the PCI interface: @@ -230,7 +242,7 @@ void __init pcibios_fixup_device_resources(struct pci_dev *dev, struct pci_bus *bus) { /* Update device resources. */ - + struct pci_controler *hose = (struct pci_controler *)bus->sysdata; int i; for (i = 0; i < PCI_NUM_RESOURCES; i++) { @@ -238,10 +250,10 @@ pcibios_fixup_device_resources(struct pci_dev *dev, struct pci_bus *bus) continue; if (dev->resource[i].flags & IORESOURCE_IO) pcibios_fixup_resource(&dev->resource[i], - bus->resource[0]); + hose->io_space); else if (dev->resource[i].flags & IORESOURCE_MEM) pcibios_fixup_resource(&dev->resource[i], - bus->resource[1]); + hose->mem_space); } pcibios_assign_special(dev); } @@ -257,6 +269,12 @@ pcibios_fixup_bus(struct pci_bus *bus) bus->resource[0] = hose->io_space; bus->resource[1] = hose->mem_space; + /* If this is a bridge, get the current bases */ + if (bus->self) { + pci_read_bridge_bases(bus); + pcibios_fixup_device_resources(bus->self, bus->parent); + } + for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) { struct pci_dev *dev = pci_dev_b(ln); if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI) @@ -268,10 +286,25 @@ void __init pcibios_update_resource(struct pci_dev *dev, struct resource *root, struct resource *res, int resource) { + struct pci_controler *hose = dev->sysdata; int where; u32 reg; + if (resource < PCI_ROM_RESOURCE) where = PCI_BASE_ADDRESS_0 + (resource * 4); + else if (resource == PCI_ROM_RESOURCE) + where = dev->rom_base_reg; + else { + /* Don't update non-standard resources here */ + return; + } + + /* Point root at the hose root */ + if (res->flags & IORESOURCE_IO) + root = hose->io_space; + if (res->flags & IORESOURCE_MEM) + root = hose->mem_space; + reg = (res->start - root->start) | (res->flags & 0xf); pci_write_config_dword(dev, where, reg); if ((res->flags & (PCI_BASE_ADDRESS_SPACE @@ -319,10 +352,12 @@ void __init pcibios_fixup_pbus_ranges(struct pci_bus * bus, struct pbus_set_ranges_data * ranges) { - ranges->io_start -= bus->resource[0]->start; - ranges->io_end -= bus->resource[0]->start; - ranges->mem_start -= bus->resource[1]->start; - ranges->mem_end -= bus->resource[1]->start; + struct pci_controler *hose = (struct pci_controler *)bus->sysdata; + + ranges->io_start -= hose->io_space->start; + ranges->io_end -= hose->io_space->start; + ranges->mem_start -= hose->mem_space->start; + ranges->mem_end -= hose->mem_space->start; } int @@ -332,6 +367,94 @@ pcibios_enable_device(struct pci_dev *dev) return 0; } +#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1)) + +static void __init +pcibios_size_bridge(struct pci_bus *bus, struct pbus_set_ranges_data *outer) +{ + struct pbus_set_ranges_data inner; + struct pci_dev *dev; + struct pci_dev *bridge = bus->self; + struct pci_controler *hose = bus->sysdata; + struct list_head *ln; + + if (!bridge) + return; /* host bridge, nothing to do */ + + /* set reasonable default locations for pcibios_align_resource */ + inner.io_start = hose->io_space->start + PCIBIOS_MIN_IO; + inner.mem_start = hose->mem_space->start + PCIBIOS_MIN_MEM; + inner.io_end = inner.io_start; + inner.mem_end = inner.mem_start; + + /* Collect information about how our direct children are layed out. */ + for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) { + int i; + dev = pci_dev_b(ln); + + /* Skip bridges for now */ + if (dev->class >> 8 == PCI_CLASS_BRIDGE_PCI) + continue; + + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + struct resource res; + unsigned long size; + + memcpy(&res, &dev->resource[i], sizeof(res)); + size = res.end - res.start + 1; + + if (res.flags & IORESOURCE_IO) { + res.start = inner.io_end; + pcibios_align_resource(dev, &res, size); + inner.io_end = res.start + size; + } else if (res.flags & IORESOURCE_MEM) { + res.start = inner.mem_end; + pcibios_align_resource(dev, &res, size); + inner.mem_end = res.start + size; + } + } + } + + /* And for all of the subordinate busses. */ + for (ln=bus->children.next; ln != &bus->children; ln=ln->next) + pcibios_size_bridge(pci_bus_b(ln), &inner); + + /* turn the ending locations into sizes (subtract start) */ + inner.io_end -= inner.io_start; + inner.mem_end -= inner.mem_start; + + /* Align the sizes up by bridge rules */ + inner.io_end = ROUND_UP(inner.io_end, 4*1024); + inner.mem_end = ROUND_UP(inner.mem_end, 1*1024*1024); + + /* Adjust the bridge's allocation requirements */ + bridge->resource[0].end = bridge->resource[0].start + inner.io_end; + bridge->resource[1].end = bridge->resource[1].start + inner.mem_end; + + /* adjust parent's resource requirements */ + if (outer) { + outer->io_end = ROUND_UP(outer->io_end, 4*1024); + outer->io_end += inner.io_end; + + outer->mem_end = ROUND_UP(outer->mem_end, 1*1024*1024); + outer->mem_end += inner.mem_end; + } +} + +#undef ROUND_UP + +static void __init +pcibios_size_bridges(void) +{ + struct list_head *ln1, *ln2; + + for(ln1=pci_root_buses.next; ln1 != &pci_root_buses; ln1=ln1->next) + for(ln2 = pci_bus_b(ln1)->children.next; + ln2 != &pci_bus_b(ln1)->children; + ln2 = ln2->next) + pcibios_size_bridge(pci_bus_b(ln2), NULL); +} + void __init common_init_pci(void) { @@ -349,6 +472,7 @@ common_init_pci(void) next_busno += 1; } + pcibios_size_bridges(); pci_assign_unassigned_resources(); pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq); pci_set_bus_ranges(); diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index aa9dfbf64..27b042777 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c @@ -116,7 +116,7 @@ common_shutdown_1(void *generic_ptr) /* Clear reason to "default"; clear "bootstrap in progress". */ flags &= ~0x00ff0001UL; -#ifdef __SMP__ +#ifdef CONFIG_SMP /* Secondaries halt here. */ if (cpuid != boot_cpuid) { flags |= 0x00040000UL; /* "remain halted" */ @@ -145,7 +145,7 @@ common_shutdown_1(void *generic_ptr) } *pflags = flags; -#ifdef __SMP__ +#ifdef CONFIG_SMP /* Wait for the secondaries to halt. */ clear_bit(boot_cpuid, &cpu_present_mask); while (cpu_present_mask) @@ -184,7 +184,7 @@ common_shutdown(int mode, char *restart_cmd) struct halt_info args; args.mode = mode; args.restart_cmd = restart_cmd; -#ifdef __SMP__ +#ifdef CONFIG_SMP smp_call_function(common_shutdown_1, &args, 1, 0); #endif common_shutdown_1(&args); @@ -321,7 +321,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, stack = ((struct switch_stack *) regs) - 1; childstack = ((struct switch_stack *) childregs) - 1; *childstack = *stack; -#ifdef __SMP__ +#ifdef CONFIG_SMP childstack->r26 = (unsigned long) ret_from_smp_fork; #else childstack->r26 = (unsigned long) ret_from_sys_call; diff --git a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h index f13edeebf..e141df202 100644 --- a/arch/alpha/kernel/proto.h +++ b/arch/alpha/kernel/proto.h @@ -1,3 +1,4 @@ +#include <linux/config.h> /* Prototypes of functions used across modules here in this directory. */ #define vucp volatile unsigned char * @@ -132,7 +133,7 @@ void srm_paging_stop(void); /* irq.c */ -#ifdef __SMP__ +#ifdef CONFIG_SMP #define mcheck_expected(cpu) (cpu_data[cpu].mcheck_expected) #define mcheck_taken(cpu) (cpu_data[cpu].mcheck_taken) #define mcheck_extra(cpu) (cpu_data[cpu].mcheck_extra) diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c index 49ddca2e4..1eab8fc5b 100644 --- a/arch/alpha/kernel/setup.c +++ b/arch/alpha/kernel/setup.c @@ -484,7 +484,7 @@ setup_arch(char **cmdline_p) * Identify the flock of penguins. */ -#ifdef __SMP__ +#ifdef CONFIG_SMP setup_smp(); #endif paging_init(); @@ -930,7 +930,7 @@ int get_cpuinfo(char *buffer) unaligned[1].count, unaligned[1].pc, unaligned[1].va, platform_string(), nr_processors); -#ifdef __SMP__ +#ifdef CONFIG_SMP len += smp_info(buffer+len); #endif diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c index 6119ea371..8cac7f240 100644 --- a/arch/alpha/kernel/time.c +++ b/arch/alpha/kernel/time.c @@ -22,6 +22,7 @@ * fixed algorithm in do_gettimeofday() for calculating the precise time * from processor cycle counter (now taking lost_ticks into account) */ +#include <linux/config.h> #include <linux/errno.h> #include <linux/sched.h> #include <linux/kernel.h> @@ -90,7 +91,7 @@ void timer_interrupt(int irq, void *dev, struct pt_regs * regs) __u32 now; long nticks; -#ifndef __SMP__ +#ifndef CONFIG_SMP /* Not SMP, do kernel PC profiling here. */ if (!user_mode(regs)) alpha_do_profile(regs->pc); @@ -315,7 +316,7 @@ do_gettimeofday(struct timeval *tv) read_unlock_irqrestore(&xtime_lock, flags); -#ifdef __SMP__ +#ifdef CONFIG_SMP /* Until and unless we figure out how to get cpu cycle counters in sync and keep them there, we can't use the rpcc tricks. */ delta_usec = lost * (1000000 / HZ); @@ -361,7 +362,7 @@ do_settimeofday(struct timeval *tv) must be subtracted out here to keep a coherent view of the time. Without this, a full-tick error is possible. */ -#ifdef __SMP__ +#ifdef CONFIG_SMP delta_usec = lost_ticks * (1000000 / HZ); #else delta_usec = rpcc() - state.last_time; diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c index 76504a1ef..8edfef27d 100644 --- a/arch/alpha/kernel/traps.c +++ b/arch/alpha/kernel/traps.c @@ -95,7 +95,7 @@ die_if_kernel(char * str, struct pt_regs *regs, long err, unsigned long *r9_15) { if (regs->ps & 8) return; -#ifdef __SMP__ +#ifdef CONFIG_SMP printk("CPU %d ", hard_smp_processor_id()); #endif printk("%s(%d): %s %ld\n", current->comm, current->pid, str, err); diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c index 3d9c8e75e..1639972db 100644 --- a/arch/alpha/mm/fault.c +++ b/arch/alpha/mm/fault.c @@ -4,6 +4,7 @@ * Copyright (C) 1995 Linus Torvalds */ +#include <linux/config.h> #include <linux/sched.h> #include <linux/kernel.h> #include <linux/mm.h> @@ -34,7 +35,7 @@ extern void die_if_kernel(char *,struct pt_regs *,long, unsigned long *); * Force a new ASN for a task. */ -#ifndef __SMP__ +#ifndef CONFIG_SMP unsigned long last_asn = ASN_FIRST_VERSION; #endif @@ -139,7 +140,7 @@ good_area: * make sure we exit gracefully rather than endlessly redo * the fault. */ - fault = handle_mm_fault(current, vma, address, cause > 0); + fault = handle_mm_fault(mm, vma, address, cause > 0); up(&mm->mmap_sem); if (fault < 0) diff --git a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c index e2142b63c..2cbe9bb0f 100644 --- a/arch/alpha/mm/init.c +++ b/arch/alpha/mm/init.c @@ -37,7 +37,7 @@ extern void die_if_kernel(char *,struct pt_regs *,long); struct thread_struct original_pcb; -#ifndef __SMP__ +#ifndef CONFIG_SMP struct pgtable_cache_struct quicklists; #endif diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index 796f812ab..f60dc3564 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -6,6 +6,66 @@ #include <linux/linkage.h> .section ".start", #alloc, #execinstr + +/* + * Debugging stuff + */ + .macro kputc,val + mov r0, \val + bl putc + .endm + + .macro kphex,val,len + mov r0, \val + mov r1, #\len + bl phex + .endm + + .macro debug_reloc_start +#ifdef DEBUG + kputc #'\n' + kphex r6, 8 + kputc #':' + kphex r5, 8 + kputc #'-' + kphex r8, 8 + kputc #'>' + kphex r4, 8 + kputc #'\n' +#endif + .endm + + .macro debug_reloc_end +#ifdef DEBUG + mov r8, r0 + kphex r5, 8 + kputc #'-' + kphex r8, 8 + kputc #'\n' + mov r0, r4 + bl memdump +#endif + .endm + +#if 0 + .macro loadsp, rb + mov \rb, #0x7c000000 + .endm + + .macro writeb, rb + strb \rb, [r3, #0x3f8] + .endm +#else + .macro loadsp, rb + mov \rb, #0x03000000 + orr \rb, \rb, #0x00010000 + .endm + + .macro writeb, rb + strb \rb, [r3, #0x3f8 << 2] + .endm +#endif + /* * sort out different calling conventions */ @@ -42,6 +102,8 @@ start: cmp r2, r3 blt 1b + bl cache_on + mov r1, sp @ malloc space above stack add r2, sp, #0x10000 @ 64k max @@ -77,15 +139,87 @@ start: cmp r2, r3 blt 1b - eor r1, r6, #0x44 << 24 @ SA-110 or SA-1100? - eor r1, r1, #0x01 << 16 - eor r1, r1, #0xa1 << 8 - movs r1, r1, lsr #5 - mcreq p15, 0, r1, c7, c7, 0 @ flush I & D-cache - mcreq p15, 0, r1, c7, c10, 4 @ drain WB + bl cache_clean_flush add pc, r5, r0 @ call relocation code /* + * Page table physical address list + */ + .align 5 + .type pgtable,#object +pgtable: .word 0x00004000 @ 0x00 + .word 0x10004000 @ 0x01 + .word 0x00000000 @ 0x02 + .word 0x40004000 @ 0x03 + .word 0x00004000 @ 0x04 + .word 0x00004000 @ 0x05 + .word 0x00004000 @ 0x06 + .word 0x80004000 @ 0x07 + .word 0x00004000 @ 0x08 + .word 0x00000000 @ 0x09 + .word 0x00000000 @ 0x0a + .word 0x00000000 @ 0x0b + .word 0x00000000 @ 0x0c + .word 0x00000000 @ 0x0d + .word 0x10004000 @ 0x0e + .word 0x08004000 @ 0x0f + .word 0xc0004000 @ 0x10 + .size pgtable,. - pgtable +1: + + .type LC0, #object +LC0: .word __bss_start + .word _end + .word _load_addr + .word _start + .word user_stack+4096 + .size LC0, . - LC0 + + .align 5 +cache_on: ldr r1, proc_sa110_type + eor r1, r1, r6 + movs r1, r1, lsr #5 + movne pc, lr + cmp r7, #(1b - pgtable) >> 2 + movge pc, lr + adr r3, pgtable + ldr r3, [r3, r7, lsl #2] + teq r3, #0 + moveq pc, lr +/* + * Initialise the page tables + */ + mov r0, r3 + mov r8, r0, lsr #18 + mov r8, r8, lsl #18 @ start of RAM + add r9, r8, #0x20000000 @ the maximum RAM size + mov r1, #0x12 + orr r1, r1, #3 << 10 + add r2, r3, #16384 +1: cmp r1, r8 @ if virt > start of RAM + orrge r1, r1, #0x0c @ set cacheable, bufferable + cmp r1, r9 @ if virt > end of RAM + bicge r1, r1, #0x0c @ clear cacheable, bufferable + str r1, [r0], #4 @ 1:1 mapping + add r1, r1, #1048576 + teq r0, r2 + bne 1b + + mov r0, #0 + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer + mcr p15, 0, r0, c8, c7 @ flush I,D TLBs + mcr p15, 0, r3, c2, c0 @ load page table pointer + mov r0, #-1 + mcr p15, 0, r0, c3, c0 @ load domain access register + mrc p15, 0, r0, c1, c0 + orr r0, r0, #0x1000 @ I-cache enable +#ifndef DEBUG + orr r0, r0, #0x003d @ Write buffer, mmu +#endif + mcr p15, 0, r0, c1, c0 + mov pc, lr + +/* * r0 = decompressed kernel length * r1-r3 = unused * r4 = kernel execution address @@ -94,87 +228,68 @@ start: * r7 = architecture ID * r8-r14 = unused */ + .align 5 reloc_start: add r8, r5, r0 -#if 0 - mov r0, #'\n' - bl putc - mov r0, r6 - mov r1, #8 - bl phex - mov r0, #':' - bl putc - mov r0, r5 - mov r1, #8 - bl phex - mov r0, #'-' - bl putc - mov r0, r8 - mov r1, #8 - bl phex - mov r0, #'>' - bl putc - mov r0, r4 - mov r1, #8 - bl phex - mov r0, #'\n' - bl putc -#endif - mov r0, r8 + debug_reloc_start mov r1, r4 1: .rept 4 - ldmia r5!, {r2, r3, r8 - r13} @ relocate kernel - stmia r1!, {r2, r3, r8 - r13} + ldmia r5!, {r0, r2, r3, r9 - r13} @ relocate kernel + stmia r1!, {r0, r2, r3, r9 - r13} .endr - cmp r5, r0 + cmp r5, r8 blt 1b -#if 0 - mov r8, r0 - mov r0, r5 - mov r1, #8 - bl phex - mov r0, #'-' - bl putc - mov r0, r8 - mov r1, #8 - bl phex - mov r0, #'\n' - bl putc - mov r0, r4 - bl memdump -#endif - eor r0, r6, #0x44 << 24 @ SA-110 or SA-1100? - eor r0, r0, #0x01 << 16 - eor r0, r0, #0xa1 << 8 - movs r0, r0, lsr #5 - mcreq p15, 0, r0, c7, c7, 0 @ flush I cache - mcreq p15, 0, r1, c7, c10, 4 @ drain WB - -call_kernel: mov r0, #0 + debug_reloc_end + +call_kernel: bl cache_clean_flush + bl cache_off + mov r0, #0 mov r1, r7 @ restore architecture number mov pc, r4 @ call kernel -phexbuf: .space 12 + .type proc_sa110_type,#object +proc_sa110_type: + .word 0x4401a100 + .size proc_sa110_type, . - proc_sa110_type -#if 0 - .macro loadsp, rb - mov \rb, #0x7c000000 - .endm +/* + * Turn off StrongARM cache and MMU + */ + .align 5 +cache_off: ldr r1, proc_sa110_type + eor r1, r1, r6 + movs r1, r1, lsr #5 + movne pc, lr + mrc p15, 0, r0, c1, c0 + bic r0, r0, #0x000d + mcr p15, 0, r0, c1, c0 + mov pc, lr - .macro writeb, rb - strb \rb, [r3, #0x3f8] - .endm -#else - .macro loadsp, rb - mov \rb, #0x03000000 - orr \rb, \rb, #0x00010000 - .endm +/* + * Clean and flush the cache to maintain consistency. + */ + .align 5 +cache_clean_flush: + ldr r1, proc_sa110_type @ SA-110 or SA-1100? + eor r1, r1, r6 + movs r1, r1, lsr #5 + movne pc, lr - .macro writeb, rb - strb \rb, [r3, #0x3f8 << 2] - .endm -#endif + bic r1, pc, #31 + add r2, r1, #32768 +1: ldr r12, [r1], #32 + teq r1, r2 + bne 1b + + mcr p15, 0, r1, c7, c7, 0 @ flush I cache + mcr p15, 0, r1, c7, c10, 4 @ drain WB + mov pc, lr + +#ifdef DEBUG + .type phexbuf,#object +phexbuf: .space 12 + .size phexbuf, . - phexbuf phex: adr r3, phexbuf mov r2, #0 @@ -240,14 +355,10 @@ memdump: mov r12, r0 cmp r11, #64 blt 2b mov pc, r10 +#endif + reloc_end: -LC0: .word __bss_start - .word _end - .word _load_addr - .word _start - .word user_stack+4096 .align - .section ".stack" user_stack: .space 4096 diff --git a/arch/arm/config.in b/arch/arm/config.in index fa124b5fd..f00835051 100644 --- a/arch/arm/config.in +++ b/arch/arm/config.in @@ -137,9 +137,6 @@ else define_bool CONFIG_ISA_DMA n fi -define_bool CONFIG_SBUS n -define_bool CONFIG_PCMCIA n - if [ "$CONFIG_CPU_32" = "y" -a "$CONFIG_ARCH_EBSA110" != "y" ]; then bool 'Kernel-mode alignment trap handler' CONFIG_ALIGNMENT_TRAP fi @@ -222,7 +219,6 @@ if [ "$CONFIG_ARCH_ACORN" = "y" ]; then fi fi - #source drivers/misc/Config.in if [ "$CONFIG_VT" = "y" ]; then diff --git a/arch/arm/def-configs/ebsa110 b/arch/arm/def-configs/ebsa110 index 0e4acdebc..09fff229c 100644 --- a/arch/arm/def-configs/ebsa110 +++ b/arch/arm/def-configs/ebsa110 @@ -2,6 +2,12 @@ # Automatically generated make config: don't edit # CONFIG_ARM=y +CONFIG_UID16=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y # # System and processor type @@ -12,20 +18,13 @@ CONFIG_ARM=y CONFIG_ARCH_EBSA110=y # CONFIG_FOOTBRIDGE is not set # CONFIG_ARCH_ACORN is not set -# CONFIG_ISA_DMA is not set CONFIG_CPU_32=y # CONFIG_CPU_26 is not set -# CONFIG_CPU_ARM2 is not set -# CONFIG_CPU_ARM3 is not set -# CONFIG_CPU_ARM6 is not set -# CONFIG_CPU_ARM7 is not set +CONFIG_CPU_32v4=y CONFIG_CPU_SA110=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -# CONFIG_TEXT_SECTIONS is not set +# CONFIG_PCI is not set +# CONFIG_ISA is not set +# CONFIG_ISA_DMA is not set # # Loadable module support @@ -42,29 +41,52 @@ CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y # CONFIG_NWFPE is not set +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set CONFIG_BINFMT_AOUT=y -CONFIG_BINFMT_ELF=m +CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set + +# +# Parallel port support +# CONFIG_PARPORT=y CONFIG_PARPORT_PC=y +CONFIG_PARPORT_PC_FIFO=y +CONFIG_PARPORT_PC_SUPERIO=y +# CONFIG_PARPORT_ARC is not set +# CONFIG_PARPORT_AMIGA is not set +# CONFIG_PARPORT_MFC3 is not set +# CONFIG_PARPORT_ATARI is not set +# CONFIG_PARPORT_SUNBPP is not set +# CONFIG_PARPORT_OTHER is not set +CONFIG_PARPORT_1284=y CONFIG_CMDLINE="root=/dev/nfs rw mem=16M console=ttyS1,38400n8" CONFIG_LEDS=y # -# Plug and Play support +# I2O device support # -# CONFIG_PNP is not set +# CONFIG_I2O is not set +# CONFIG_I2O_PCI is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set # -# Block devices +# Plug and Play configuration # -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_IDE is not set +# CONFIG_PNP is not set +# CONFIG_ISAPNP is not set # -# Please see Documentation/ide.txt for help/info on IDE drives +# Block devices # -# CONFIG_BLK_DEV_HD_ONLY is not set +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set # # Additional Block Devices @@ -74,10 +96,6 @@ CONFIG_BLK_DEV_NBD=m # CONFIG_BLK_DEV_MD is not set CONFIG_BLK_DEV_RAM=y # CONFIG_BLK_DEV_INITRD is not set -# CONFIG_BLK_DEV_XD is not set -CONFIG_PARIDE_PARPORT=y -# CONFIG_PARIDE is not set -# CONFIG_BLK_DEV_HD is not set # # Character devices @@ -94,29 +112,39 @@ CONFIG_SERIAL_EXTENDED=y # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_UNIX98_PTYS is not set CONFIG_PRINTER=m -CONFIG_PRINTER_READBACK=y -CONFIG_MOUSE=y +# CONFIG_LP_CONSOLE is not set +# CONFIG_PPDEV is not set + +# +# I2C support +# +# CONFIG_I2C is not set # # Mice # -# CONFIG_ATIXL_BUSMOUSE is not set # CONFIG_BUSMOUSE is not set -# CONFIG_MS_BUSMOUSE is not set +CONFIG_MOUSE=y # CONFIG_PSMOUSE is not set # CONFIG_82C710_MOUSE is not set # CONFIG_PC110_PAD is not set + +# +# Joysticks +# +# CONFIG_JOYSTICK is not set # CONFIG_QIC02_TAPE is not set -CONFIG_WATCHDOG=y # # Watchdog Cards # +CONFIG_WATCHDOG=y # CONFIG_WATCHDOG_NOWAYOUT is not set # CONFIG_WDT is not set CONFIG_SOFT_WATCHDOG=y # CONFIG_PCWATCHDOG is not set # CONFIG_ACQUIRE_WDT is not set +# CONFIG_MIXCOMWD is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set @@ -124,64 +152,92 @@ CONFIG_SOFT_WATCHDOG=y # Video For Linux # # CONFIG_VIDEO_DEV is not set - -# -# Joystick support -# -# CONFIG_JOYSTICK is not set # CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set # # Ftape, the floppy tape device driver # # CONFIG_FTAPE is not set +# CONFIG_DRM is not set +# CONFIG_DRM_TDFX is not set +# CONFIG_AGP is not set # # Networking options # CONFIG_PACKET=m -# CONFIG_NETLINK is not set -CONFIG_FIREWALL=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK=y +CONFIG_RTNETLINK=y +# CONFIG_NETLINK_DEV is not set +CONFIG_NETFILTER=y # CONFIG_FILTER is not set CONFIG_UNIX=y CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_RTNETLINK=y +CONFIG_NETLINK=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_FWMARK=y +CONFIG_IP_ROUTE_NAT=y +# CONFIG_IP_ROUTE_MULTIPATH is not set +# CONFIG_IP_ROUTE_TOS is not set +# CONFIG_IP_ROUTE_VERBOSE is not set +# CONFIG_IP_ROUTE_LARGE_TABLES is not set CONFIG_IP_PNP=y CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set -CONFIG_IP_FIREWALL=y -CONFIG_IP_ALWAYS_DEFRAG=y -# CONFIG_IP_TRANSPARENT_PROXY is not set -CONFIG_IP_MASQUERADE=y - -# -# Protocol-specific masquerading support will be built as modules. -# -CONFIG_IP_MASQUERADE_ICMP=y - -# -# Protocol-specific masquerading support will be built as modules. -# -# CONFIG_IP_MASQUERADE_MOD is not set # CONFIG_IP_ROUTER is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set -# CONFIG_IP_ALIAS is not set +# CONFIG_IP_MROUTE is not set +CONFIG_IP_ALIAS=y +# CONFIG_ARPD is not set CONFIG_SYN_COOKIES=y # # (it is safe to leave these untouched) # -# CONFIG_INET_RARP is not set # CONFIG_SKB_LARGE is not set + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=y +CONFIG_IP_NF_FTP=y +# CONFIG_IP_NF_QUEUE is not set +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_MATCH_LIMIT=y +# CONFIG_IP_NF_MATCH_MAC is not set +CONFIG_IP_NF_MATCH_MARK=y +CONFIG_IP_NF_MATCH_MULTIPORT=y +CONFIG_IP_NF_MATCH_TOS=y +CONFIG_IP_NF_MATCH_STATE=y +# CONFIG_IP_NF_MATCH_UNCLEAN is not set +# CONFIG_IP_NF_MATCH_OWNER is not set +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +# CONFIG_IP_NF_TARGET_MIRROR is not set +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_TARGET_TOS=y +CONFIG_IP_NF_TARGET_MARK=y +CONFIG_IP_NF_TARGET_LOG=y # CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set # # # # CONFIG_IPX is not set # CONFIG_ATALK is not set +# CONFIG_DECNET is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set # CONFIG_BRIDGE is not set @@ -190,7 +246,6 @@ CONFIG_SYN_COOKIES=y # CONFIG_WAN_ROUTER is not set # CONFIG_NET_FASTROUTE is not set # CONFIG_NET_HW_FLOWCONTROL is not set -# CONFIG_CPU_IS_SLOW is not set # # QoS and/or fair queueing @@ -203,7 +258,7 @@ CONFIG_SYN_COOKIES=y # CONFIG_HAMRADIO is not set # -# IrDA subsystem support +# IrDA (infrared) support # # CONFIG_IRDA is not set @@ -211,37 +266,72 @@ CONFIG_SYN_COOKIES=y # Network device support # CONFIG_NETDEVICES=y + +# +# ARCnet devices +# # CONFIG_ARCNET is not set -# CONFIG_DUMMY is not set +CONFIG_DUMMY=m +# CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set +# CONFIG_ETHERTAP is not set +# CONFIG_NET_SB1000 is not set + +# +# Ethernet (10 or 100Mbit) +# CONFIG_NET_ETHERNET=y CONFIG_ARM_AM79C961A=y # CONFIG_NET_VENDOR_3COM is not set # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_RTL8139 is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_ACENIC is not set +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set # CONFIG_NET_ISA is not set -# CONFIG_NET_EISA is not set +# CONFIG_NET_PCI is not set # CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_YELLOWFIN is not set +# CONFIG_ACENIC is not set +# CONFIG_SK98LIN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set -# CONFIG_DLCI is not set # CONFIG_PLIP is not set CONFIG_PPP=y +CONFIG_PPP_ASYNC=y +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +# CONFIG_SLIP is not set # -# CCP compressors for PPP are only built as modules. +# Wireless LAN (non-hamradio) # -# CONFIG_SLIP is not set # CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# # CONFIG_TR is not set -# CONFIG_SHAPER is not set -# CONFIG_HOSTESS_SV11 is not set -# CONFIG_COSA is not set +# CONFIG_NET_FC is not set # CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# ATA/IDE/MFM/RLL support +# +# CONFIG_IDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set # # SCSI support @@ -249,27 +339,35 @@ CONFIG_PPP=y # CONFIG_SCSI is not set # -# Filesystems +# File systems # # CONFIG_QUOTA is not set -CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS_FS=y +CONFIG_AUTOFS4_FS=y # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set # CONFIG_FAT_FS is not set # CONFIG_MSDOS_FS is not set # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set # CONFIG_ISO9660_FS is not set # CONFIG_JOLIET is not set CONFIG_MINIX_FS=y # CONFIG_NTFS_FS is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_DEBUG is not set +# CONFIG_DEVPTS_FS is not set # CONFIG_QNX4FS_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_EXT2_FS is not set # CONFIG_SYSV_FS is not set +# CONFIG_UDF_FS is not set # CONFIG_UFS_FS is not set # @@ -287,22 +385,28 @@ CONFIG_LOCKD=y # # Partition Types # +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set # CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set # CONFIG_MAC_PARTITION is not set # CONFIG_MSDOS_PARTITION is not set # CONFIG_SGI_PARTITION is not set # CONFIG_SUN_PARTITION is not set -# CONFIG_AMIGA_PARTITION is not set -# CONFIG_ACORN_PARTITION is not set # CONFIG_NLS is not set # +# USB support +# +# CONFIG_USB is not set + +# # Kernel hacking # -CONFIG_FRAME_POINTER=y +# CONFIG_FRAME_POINTER is not set CONFIG_DEBUG_ERRORS=y # CONFIG_DEBUG_USER is not set # CONFIG_DEBUG_INFO is not set # CONFIG_MAGIC_SYSRQ is not set -# CONFIG_ARTHUR is not set # CONFIG_DEBUG_LL is not set diff --git a/arch/arm/defconfig b/arch/arm/defconfig index c5b389476..077eef8b3 100644 --- a/arch/arm/defconfig +++ b/arch/arm/defconfig @@ -536,8 +536,8 @@ CONFIG_BLK_DEV_IDEDMA=y CONFIG_IDEDMA_PCI_EXPERIMENTAL=y # CONFIG_IDEDMA_PCI_WIP is not set # CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set -# CONFIG_BLK_DEV_AEC6210 is not set -# CONFIG_AEC6210_TUNING is not set +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_AEC62XX_TUNING is not set # CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_WDC_ALI15X3 is not set # CONFIG_BLK_DEV_AMD7409 is not set diff --git a/arch/arm/kernel/arch.c b/arch/arm/kernel/arch.c index e9cca7748..717ba4ca9 100644 --- a/arch/arm/kernel/arch.c +++ b/arch/arm/kernel/arch.c @@ -1,45 +1,39 @@ /* * linux/arch/arm/kernel/arch.c * - * Architecture specifics + * Architecture specific fixups. This is where any + * parameters in the params struct are fixed up, or + * any additional architecture specific information + * is pulled from the params struct. */ #include <linux/config.h> #include <linux/tty.h> #include <linux/init.h> +#include <asm/dec21285.h> #include <asm/elf.h> #include <asm/setup.h> #include <asm/system.h> #include "arch.h" -extern unsigned int system_rev; -extern unsigned int system_serial_low; -extern unsigned int system_serial_high; - unsigned int vram_size; -#ifdef CONFIG_ARCH_ACORN -unsigned int memc_ctrl_reg; -unsigned int number_mfm_drives; -#endif extern void setup_initrd(unsigned int start, unsigned int size); extern void setup_ramdisk(int doload, int prompt, int start, unsigned int rd_sz); -/* - * Architecture specific fixups. This is where any - * parameters in the params struct are fixed up, or - * any additional architecture specific information - * is pulled from the params struct. - */ +#ifdef CONFIG_ARCH_ACORN + +unsigned int memc_ctrl_reg; +unsigned int number_mfm_drives; + static void __init fixup_acorn(struct machine_desc *desc, struct param_struct *params, char **cmdline, struct meminfo *mi) { -#ifdef CONFIG_ARCH_ACORN - int i; - if (machine_is_riscpc()) { + int i; + /* * RiscPC can't handle half-word loads and stores */ @@ -69,9 +63,36 @@ fixup_acorn(struct machine_desc *desc, struct param_struct *params, } memc_ctrl_reg = params->u1.s.memc_control_reg; number_mfm_drives = (params->u1.s.adfsdrives >> 3) & 3; -#endif } +#ifdef CONFIG_ARCH_RPC +MACHINE_START(RISCPC, "Acorn-RiscPC") + MAINTAINER("Russell King") + BOOT_MEM(0x10000000, 0x03000000, 0xe0000000) + BOOT_PARAMS(0x10000100) + DISABLE_PARPORT(0) + DISABLE_PARPORT(1) + FIXUP(fixup_acorn) +MACHINE_END +#endif +#ifdef CONFIG_ARCH_ARC +MACHINE_START(ARCHIMEDES, "Acorn-Archimedes") + MAINTAINER("Dave Gilbert") + BOOT_PARAMS(0x0207c000) + FIXUP(fixup_acorn) +MACHINE_END +#endif +#ifdef CONFIG_ARCH_A5K +MACHINE_START(A5K, "Acorn-A5000") + MAINTAINER("Russell King") + BOOT_PARAMS(0x0207c000) + FIXUP(fixup_acorn) +MACHINE_END +#endif +#endif + +#ifdef CONFIG_ARCH_EBSA285 + static void __init fixup_ebsa285(struct machine_desc *desc, struct param_struct *params, char **cmdline, struct meminfo *mi) @@ -82,6 +103,16 @@ fixup_ebsa285(struct machine_desc *desc, struct param_struct *params, ORIG_VIDEO_LINES = params->u1.s.video_num_rows; } +MACHINE_START(EBSA285, "EBSA285") + MAINTAINER("Russell King") + BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0xfe000000) + BOOT_PARAMS(0x00000100) + VIDEO(0x000a0000, 0x000bffff) + FIXUP(fixup_ebsa285) +MACHINE_END +#endif + +#ifdef CONFIG_ARCH_NETWINDER /* * Older NeTTroms either do not provide a parameters * page, or they don't supply correct information in @@ -105,6 +136,18 @@ fixup_netwinder(struct machine_desc *desc, struct param_struct *params, } } +MACHINE_START(NETWINDER, "Rebel-NetWinder") + MAINTAINER("Russell King/Rebel.com") + BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0xfe000000) + BOOT_PARAMS(0x00000100) + VIDEO(0x000a0000, 0x000bffff) + DISABLE_PARPORT(0) + DISABLE_PARPORT(2) + FIXUP(fixup_netwinder) +MACHINE_END +#endif + +#ifdef CONFIG_ARCH_CATS /* * CATS uses soft-reboot by default, since * hard reboots fail on early boards. @@ -118,11 +161,20 @@ fixup_cats(struct machine_desc *desc, struct param_struct *params, ORIG_Y = 24; } +MACHINE_START(CATS, "Chalice-CATS") + MAINTAINER("Philip Blundell") + BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0xfe000000) + SOFT_REBOOT + FIXUP(fixup_cats) +MACHINE_END +#endif + +#ifdef CONFIG_ARCH_CO285 + static void __init fixup_coebsa285(struct machine_desc *desc, struct param_struct *params, char **cmdline, struct meminfo *mi) { -#if 0 extern unsigned long boot_memory_end; extern char boot_command_line[]; @@ -131,242 +183,228 @@ fixup_coebsa285(struct machine_desc *desc, struct param_struct *params, mi->bank[0].size = boot_memory_end; *cmdline = boot_command_line; -#endif } +MACHINE_START(CO285, "co-EBSA285") + MAINTAINER("Mark van Doesburg") + BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0x7cf00000) + FIXUP(fixup_coebsa285) +MACHINE_END +#endif + +#ifdef CONFIG_ARCH_SA1100 + +extern void select_sa1100_io_desc(void); +#define SET_BANK(__nr,__start,__size) \ + mi->bank[__nr].start = (__start), \ + mi->bank[__nr].size = (__size) static void __init fixup_sa1100(struct machine_desc *desc, struct param_struct *params, char **cmdline, struct meminfo *mi) { -#ifdef CONFIG_ARCH_SA1100 - int i; - extern struct mem_desc { - unsigned long phys_start; - unsigned long length; - } mem_desc[]; - extern unsigned int mem_desc_size; - - for( i = 0; i < mem_desc_size; i++ ) { - if( i >= NR_BANKS ) { - printk( __FUNCTION__ - ": mem_desc too large for meminfo structure\n"); - break; - } - mi->bank[i].start = mem_desc[i].phys_start; - mi->bank[i].size = mem_desc[i].length; + select_sa1100_io_desc(); + + if (machine_is_assabet()) { + SET_BANK( 0, 0xc0000000, 32*1024*1024 ); + mi->nr_banks = 1; + + ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); + setup_ramdisk( 1, 0, 0, 8192 ); + setup_initrd( 0xc0800000, 3*1024*1024 ); } - mi->nr_banks = i; - -#if defined(CONFIG_SA1100_BRUTUS) - ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); - setup_ramdisk( 1, 0, 0, 8192 ); - setup_initrd( __phys_to_virt(0xd8000000), 3*1024*1024 ); -#elif defined(CONFIG_SA1100_EMPEG) - ROOT_DEV = MKDEV( 3, 1 ); /* /dev/hda1 */ - setup_ramdisk( 1, 0, 0, 4096 ); - setup_initrd( 0xd0000000+((1024-320)*1024), (320*1024) ); -#elif defined(CONFIG_SA1100_THINCLIENT) - ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); - setup_ramdisk( 1, 0, 0, 8192 ); - setup_initrd( __phys_to_virt(0xc0800000), 4*1024*1024 ); -#elif defined(CONFIG_SA1100_TIFON) - ROOT_DEV = MKDEV(UNNAMED_MAJOR, 0); - setup_ramdisk(1, 0, 0, 4096); - setup_initrd( 0xd0000000 + 0x1100004, 0x140000 ); -#elif defined(CONFIG_SA1100_VICTOR) - ROOT_DEV = MKDEV( 60, 2 ); - - /* Get command line parameters passed from the loader (if any) */ - if( *((char*)0xc0000000) ) - strcpy( default_command_line, ((char *)0xc0000000) ); - - /* power off if any problem */ - strcat( default_command_line, " panic=1" ); -#elif defined(CONFIG_SA1100_LART) - ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); - setup_ramdisk(1, 0, 0, 8192); - setup_initrd(0xc0400000, 0x00400000); -#endif -#endif -} -#define NO_PARAMS 0 -#define NO_VIDEO 0, 0 + else if (machine_is_brutus()) { + SET_BANK( 0, 0xc0000000, 4*1024*1024 ); + SET_BANK( 1, 0xc8000000, 4*1024*1024 ); + SET_BANK( 2, 0xd0000000, 4*1024*1024 ); + SET_BANK( 3, 0xd8000000, 4*1024*1024 ); + mi->nr_banks = 4; -/* - * This is the list of all architectures supported by - * this kernel. This should be integrated with the list - * in head-armv.S. - */ -static struct machine_desc machine_desc[] __attribute__ ((__section__ (".arch.info"))) = { -#ifdef CONFIG_ARCH_EBSA110 - { - MACH_TYPE_EBSA110, - "EBSA110", /* RMK */ - 0x00000400, - NO_VIDEO, - 1, 0, 1, 0, 1, - NULL - }, + ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); + setup_ramdisk( 1, 0, 0, 8192 ); + setup_initrd( __phys_to_virt(0xd8000000), 3*1024*1024 ); + } + + else if (machine_is_empeg()) { + SET_BANK( 0, 0xc0000000, 4*1024*1024 ); + SET_BANK( 1, 0xc8000000, 4*1024*1024 ); + mi->nr_banks = 2; + + ROOT_DEV = MKDEV( 3, 1 ); /* /dev/hda1 */ + setup_ramdisk( 1, 0, 0, 4096 ); + setup_initrd( 0xd0000000+((1024-320)*1024), (320*1024) ); + } + + else if (machine_is_lart()) { + /* + * Note that LART is a special case - it doesn't use physical + * address line A23 on the DRAM, so we effectively have 4 * 8MB + * in two SA1100 banks. + */ + SET_BANK( 0, 0xc0000000, 8*1024*1024 ); + SET_BANK( 1, 0xc1000000, 8*1024*1024 ); + SET_BANK( 2, 0xc8000000, 8*1024*1024 ); + SET_BANK( 3, 0xc9000000, 8*1024*1024 ); + mi->nr_banks = 4; + + ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); + setup_ramdisk(1, 0, 0, 8192); + setup_initrd(0xc0400000, 4*1024*1024); + } + + else if (machine_is_thinclient()) { + SET_BANK( 0, 0xc0000000, 16*1024*1024 ); + mi->nr_banks = 1; + + ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); + setup_ramdisk( 1, 0, 0, 8192 ); + setup_initrd( __phys_to_virt(0xc0800000), 4*1024*1024 ); + } + + else if (machine_is_tifon()) { + SET_BANK( 0, 0xc0000000, 16*1024*1024 ); + SET_BANK( 1, 0xc8000000, 16*1024*1024 ); + mi->nr_banks = 2; + + ROOT_DEV = MKDEV(UNNAMED_MAJOR, 0); + setup_ramdisk(1, 0, 0, 4096); + setup_initrd( 0xd0000000 + 0x1100004, 0x140000 ); + } + + else if (machine_is_victor()) { + SET_BANK( 0, 0xc0000000, 4*1024*1024 ); + mi->nr_banks = 1; + + ROOT_DEV = MKDEV( 60, 2 ); + + /* Get command line parameters passed from the loader (if any) */ + if( *((char*)0xc0000000) ) + strcpy( *cmdline, ((char *)0xc0000000) ); + + /* power off if any problem */ + strcat( *cmdline, " panic=1" ); + } + +} + +#ifdef CONFIG_SA1100_ASSABET +MACHINE_START(ASSABET, "Intel-Assabet") + BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) + FIXUP(fixup_sa1100) +MACHINE_END #endif -#ifdef CONFIG_ARCH_RPC - { - MACH_TYPE_RISCPC, - "Acorn-RiscPC", /* RMK */ - 0x10000100, - NO_VIDEO, - 1, 1, 0, 0, 0, - fixup_acorn - }, +#ifdef CONFIG_SA1100_BITSY +MACHINE_START(BITSY, "Compaq Bitsy") + BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) + BOOT_PARAMS(0xc0000100) + FIXUP(fixup_sa1100) +MACHINE_END #endif -#ifdef CONFIG_ARCH_NEXUSPCI - { - MACH_TYPE_NEXUSPCI, - "FTV/PCI", /* Philip Blundell */ - NO_PARAMS, - NO_VIDEO, - 0, 0, 0, 0, 0, - NULL - }, +#ifdef CONFIG_SA1100_BRUTUS +MACHINE_START(BRUTUS, "Intel Brutus (SA1100 eval board)") + BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) + FIXUP(fixup_sa1100) +MACHINE_END #endif -#ifdef CONFIG_ARCH_EBSA285 - { - MACH_TYPE_EBSA285, - "EBSA285", /* RMK */ - 0x00000100, - 0x000a0000, 0x000bffff, - 0, 0, 0, 0, 0, - fixup_ebsa285 - }, +#ifdef CONFIG_SA1100_EMPEG +MACHINE_START(EMPEG, "empeg MP3 Car Audio Player") + BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) + FIXUP(fixup_sa1100) +MACHINE_END #endif -#ifdef CONFIG_ARCH_NETWINDER - { - MACH_TYPE_NETWINDER, - "Rebel-NetWinder", /* RMK */ - 0x00000100, - 0x000a0000, 0x000bffff, - 1, 0, 1, 0, 0, - fixup_netwinder - }, +#ifdef CONFIG_SA1100_ITSY +MACHINE_START(ITSY, "Compaq Itsy") + BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) + BOOT_PARAMS(0xc0000100 + FIXUP(fixup_sa1100) +MACHINE_END #endif -#ifdef CONFIG_ARCH_CATS - { - MACH_TYPE_CATS, - "Chalice-CATS", /* Philip Blundell */ - NO_PARAMS, - 0x000a0000, 0x000bffff, - 0, 0, 0, 0, 1, - fixup_cats - }, +#ifdef CONFIG_SA1100_LART +MACHINE_START(LART, "LART") + BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) + FIXUP(fixup_sa1100) +MACHINE_END #endif -#ifdef CONFIG_ARCH_TBOX - { - MACH_TYPE_TBOX, - "unknown-TBOX", /* Philip Blundell */ - NO_PARAMS, - NO_VIDEO, - 0, 0, 0, 0, 0, - NULL - }, +#ifdef CONFIG_SA1100_PLEB +MACHINE_START(PLEB, "PLEB") + BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) + FIXUP(fixup_sa1100) +MACHINE_END #endif -#ifdef CONFIG_ARCH_CO285 - { - MACH_TYPE_CO285, - "co-EBSA285", /* Mark van Doesburg */ - NO_PARAMS, - NO_VIDEO, - 0, 0, 0, 0, 0, - fixup_coebsa285 - }, +#ifdef CONFIG_SA1100_THINCLIENT +MACHINE_START(THINCLIENT, "ADS ThinClient") + BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) + FIXUP(fixup_sa1100) +MACHINE_END #endif -#ifdef CONFIG_ARCH_CLPS7110 - { - MACH_TYPE_CLPS7110, - "CL-PS7110", /* Werner Almesberger */ - NO_PARAMS, - NO_VIDEO, - 0, 0, 0, 0, 0, - NULL - }, +#ifdef CONFIG_SA1100_TIFON +MACHINE_START(TIFON, "Tifon") + BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) + FIXUP(fixup_sa1100) +MACHINE_END #endif -#ifdef CONFIG_ARCH_ARC - { - MACH_TYPE_ARCHIMEDES, - "Acorn-Archimedes",/* RMK/DAG */ - 0x0207c000, - NO_VIDEO, - 0, 0, 0, 0, 0, - fixup_acorn - }, +#ifdef CONFIG_SA1100_VICTOR +MACHINE_START(VICTOR, "VisuAide Victor") + BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) + FIXUP(fixup_sa1100) +MACHINE_END #endif -#ifdef CONFIG_ARCH_A5K - { - MACH_TYPE_A5K, - "Acorn-A5000", /* RMK/PB */ - 0x0207c000, - NO_VIDEO, - 0, 0, 0, 0, 0, - fixup_acorn - }, +#endif + +#ifdef CONFIG_ARCH_EBSA110 +MACHINE_START(EBSA110, "EBSA110") + MAINTAINER("Russell King") + BOOT_MEM(0x00000000, 0xe0000000, 0xe0000000) + BOOT_PARAMS(0x00000400) + DISABLE_PARPORT(0) + DISABLE_PARPORT(2) + SOFT_REBOOT +MACHINE_END +#endif +#ifdef CONFIG_ARCH_NEXUSPCI +MACHINE_START(NEXUSPCI, "FTV/PCI") + MAINTAINER("Philip Blundell") + BOOT_MEM(0x40000000, 0x10000000, 0xe0000000) +MACHINE_END +#endif +#ifdef CONFIG_ARCH_TBOX +MACHINE_START(TBOX, "unknown-TBOX") + MAINTAINER("Philip Blundell") + BOOT_MEM(0x80000000, 0x00400000, 0xe0000000) +MACHINE_END +#endif +#ifdef CONFIG_ARCH_CLPS7110 +MACHINE_START(CLPS7110, "CL-PS7110") + MAINTAINER("Werner Almesberger") +MACHINE_END #endif #ifdef CONFIG_ARCH_ETOILE - { - MACH_TYPE_ETOILE, - "Etoile", /* Alex de Vries */ - NO_PARAMS, - NO_VIDEO, - 0, 0, 0, 0, 0, - NULL - }, +MACHINE_START(ETOILE, "Etoile") + MAINTAINER("Alex de Vries") +MACHINE_END #endif #ifdef CONFIG_ARCH_LACIE_NAS - { - MACH_TYPE_LACIE_NAS, - "LaCie_NAS", /* Benjamin Herrenschmidt */ - NO_PARAMS, - NO_VIDEO, - 0, 0, 0, 0, 0, - NULL - }, +MACHINE_START(LACIE_NAS, "LaCie_NAS") + MAINTAINER("Benjamin Herrenschmidt") +MACHINE_END #endif #ifdef CONFIG_ARCH_CLPS7500 - { - MACH_TYPE_CLPS7500, - "CL-PS7500", /* Philip Blundell */ - NO_PARAMS, - NO_VIDEO, - 0, 0, 0, 0, 0, - NULL - }, +MACHINE_START(CLPS7500, "CL-PS7500") + MAINTAINER("Philip Blundell") + BOOT_MEM(0x10000000, 0x03000000, 0xe0000000) +MACHINE_END #endif #ifdef CONFIG_ARCH_SHARK - { - MACH_TYPE_SHARK, - "Shark", /* Alexander Schulz */ - NO_PARAMS, - 0x06000000, 0x06000000+0x001fffff, - 0, 0, 0, 0, 0, - NULL - }, -#endif -#ifdef CONFIG_ARCH_SA1100 - { - MACH_TYPE_SA1100, - "SA1100-based", /* Nicolas Pitre */ - NO_PARAMS, - NO_VIDEO, - 0, 0, 0, 0, 0, - fixup_sa1100 - }, +MACHINE_START(SHARK, "Shark") + MAINTAINER("Alexander Schulz") + BOOT_MEM(0x08000000, 0x40000000, 0xe0000000) + VIDEO(0x06000000, 0x061fffff) +MACHINE_END #endif #ifdef CONFIG_ARCH_PERSONAL_SERVER - { - MACH_TYPE_PERSONAL_SERVER, - "Compaq Personal Server", - NO_PARAMS, - NO_VIDEO, - 0, 0, 0, 0, 0, - NULL - } +MACHINE_START(PERSONAL_SERVER, "Compaq Personal Server") + MAINTAINER("Jamey Hicks / George France") + BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0xfe000000) + BOOT_PARAMS(0x00000100) +MACHINE_END #endif -}; diff --git a/arch/arm/kernel/arch.h b/arch/arm/kernel/arch.h index b7635b11e..91de77772 100644 --- a/arch/arm/kernel/arch.h +++ b/arch/arm/kernel/arch.h @@ -1,9 +1,27 @@ +/* + * The size of struct machine_desc + * (for assembler code) + */ +#define SIZEOF_MACHINE_DESC 40 + +#ifndef __ASSEMBLY__ + struct machine_desc { + /* + * Note! The first four elements are used + * by assembler code in head-armv.S + */ unsigned int nr; /* architecture number */ + unsigned int phys_ram; /* start of physical ram */ + unsigned int phys_io; /* start of physical io */ + unsigned int virt_io; /* start of virtual io */ + const char *name; /* architecture name */ unsigned int param_offset; /* parameter page */ + unsigned int video_start; /* start of video RAM */ unsigned int video_end; /* end of video RAM */ + unsigned int reserve_lp0 :1; /* never has lp0 */ unsigned int reserve_lp1 :1; /* never has lp1 */ unsigned int reserve_lp2 :1; /* never has lp2 */ @@ -13,3 +31,43 @@ struct machine_desc { struct param_struct *, char **, struct meminfo *); }; + +/* + * Set of macros to define architecture features + */ +#define MACHINE_START(_type,_name) \ +const struct machine_desc __mach_desc_##_type \ + __attribute__((__section__(".arch.info"))) = { \ + nr: MACH_TYPE_##_type##, \ + name: _name, + +#define MAINTAINER(n) + +#define BOOT_MEM(_pram,_pio,_vio) \ + phys_ram: _pram, \ + phys_io: _pio, \ + virt_io: _vio, + +#define BOOT_PARAMS(_params) \ + param_offset: _params, + +#define VIDEO(_start,_end) \ + video_start: _start, \ + video_end: _end, + +#define DISABLE_PARPORT(_n) \ + reserve_lp##_n##: 1, + +#define BROKEN_HLT \ + broken_hlt: 1, + +#define SOFT_REBOOT \ + soft_reboot: 1, + +#define FIXUP(_func) \ + fixup: _func, + +#define MACHINE_END \ +}; + +#endif diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index 02a4f6cf0..ffd0f1b5e 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -101,6 +101,7 @@ EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(system_rev); EXPORT_SYMBOL(system_serial_low); EXPORT_SYMBOL(system_serial_high); +EXPORT_SYMBOL(mem_fclk_21285); EXPORT_SYMBOL(__bug); EXPORT_SYMBOL(__readwrite_bug); EXPORT_SYMBOL(enable_irq); diff --git a/arch/arm/kernel/arthur.c b/arch/arm/kernel/arthur.c index 77c7d7396..8a8a5510d 100644 --- a/arch/arm/kernel/arthur.c +++ b/arch/arm/kernel/arthur.c @@ -59,11 +59,7 @@ static struct exec_domain arthur_exec_domain = { PER_RISCOS, PER_RISCOS, arthur_to_linux_signals, linux_to_arthur_signals, -#ifdef MODULE - &__this_module, /* No usage counter. */ -#else - NULL, -#endif + THIS_MODULE, NULL /* Nothing after this in the list. */ }; diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index c4ccd64e3..835bce140 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -21,7 +21,7 @@ int have_isa_bridge; extern void hw_init(void); -void pcibios_report_device_errors(void) +void pcibios_report_device_errors(int warn) { struct pci_dev *dev; @@ -34,8 +34,11 @@ void pcibios_report_device_errors(void) continue; pci_write_config_word(dev, PCI_STATUS, status & 0xf900); - printk(KERN_DEBUG "PCI: %02X:%02X: status %04X on %s\n", - dev->bus->number, dev->devfn, status, dev->name); + + if (warn) + printk(KERN_DEBUG "PCI: %02X:%02X: status %04X " + "on %s\n", dev->bus->number, dev->devfn, + status, dev->name); } } @@ -48,10 +51,6 @@ void pcibios_report_device_errors(void) * - (0x48) enable all memory requests from ISA to be channeled to PCI * - (0x42) disable ping-pong (as per errata) * - (0x40) enable PCI packet retry - * - (0x44) Route INTA to IRQ11 - * - (0x83) don't use CPU park enable, park on last master, disable GAT bit - * - (0x80) default rotating priorities - * - (0x81) rotate bank 4 */ static void __init pci_fixup_83c553(struct pci_dev *dev) { @@ -64,10 +63,26 @@ static void __init pci_fixup_83c553(struct pci_dev *dev) pci_write_config_byte(dev, 0x48, 0xff); pci_write_config_byte(dev, 0x42, 0x00); pci_write_config_byte(dev, 0x40, 0x22); - pci_write_config_word(dev, 0x44, 0xb000); - pci_write_config_byte(dev, 0x83, 0x02); + + /* + * We used to set the arbiter to "park on last master" + * (bit 1 set), but unfortunately the CyberPro does not + * park the bus. We must therefore park on CPU. + */ + pci_write_config_byte(dev, 0x83, 0x00); + + /* + * Rotate priorities of each PCI request + */ pci_write_config_byte(dev, 0x80, 0xe0); pci_write_config_byte(dev, 0x81, 0x01); + + /* + * Route INTA input to IRQ 11, and set + * IRQ11 to be level sensitive. + */ + pci_write_config_word(dev, 0x44, 0xb000); + outb(0x08, 0x4d1); } static void __init pci_fixup_unassign(struct pci_dev *dev) @@ -77,6 +92,23 @@ static void __init pci_fixup_unassign(struct pci_dev *dev) } /* + * Prevent the PCI layer from seeing the resources + * allocated to this device. These resources are + * of no consequence to the PCI layer (they are + * handled elsewhere). + */ +static void __init pci_fixup_disable(struct pci_dev *dev) +{ + int i; + + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + dev->resource[i].start = 0; + dev->resource[i].end = 0; + dev->resource[i].flags = 0; + } +} + +/* * PCI IDE controllers use non-standard I/O port * decoding, respect it. */ @@ -100,6 +132,10 @@ static void __init pci_fixup_ide_bases(struct pci_dev *dev) struct pci_fixup pcibios_fixups[] = { { PCI_FIXUP_HEADER, + PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285, + pci_fixup_disable + }, { + PCI_FIXUP_HEADER, PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553, pci_fixup_83c553 }, { @@ -339,6 +375,7 @@ static int __init netwinder_map_irq(struct pci_dev *dev, u8 slot, u8 pin) case DEV(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2000): case DEV(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2010): + case DEV(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5000): return IRQ_NETWINDER_VGA; default: diff --git a/arch/arm/kernel/debug-armv.S b/arch/arm/kernel/debug-armv.S index 5802dac70..ce7f2f94c 100644 --- a/arch/arm/kernel/debug-armv.S +++ b/arch/arm/kernel/debug-armv.S @@ -68,7 +68,10 @@ #ifndef CONFIG_DEBUG_DC21285_PORT /* For NetWinder debugging */ .macro addruart,rx - mov \rx, #0xff000000 + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? + moveq \rx, #0x7c000000 @ physical + movne \rx, #0xff000000 @ virtual orr \rx, \rx, #0x000003f8 .endm @@ -133,7 +136,10 @@ #elif defined(CONFIG_ARCH_SA1100) .macro addruart,rx - mov \rx, #0xf8000000 + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? + moveq \rx, #0x80000000 @ physical base address + movne \rx, #0xf8000000 @ virtual address add \rx, \rx, #0x00050000 @ Ser3 @add \rx, \rx, #0x00010000 @ Ser1 .endm @@ -171,7 +177,7 @@ ENTRY(printhex4) ENTRY(printhex2) mov r1, #2 -printhex: ldr r2, =hexbuf +printhex: adr r2, hexbuf add r3, r2, r1 mov r1, #0 strb r1, [r3] @@ -209,5 +215,4 @@ ENTRY(printch) mov r0, #0 b 1b - .bss hexbuf: .space 16 diff --git a/arch/arm/kernel/dec21285.c b/arch/arm/kernel/dec21285.c index 64c5861f0..bc8a951e2 100644 --- a/arch/arm/kernel/dec21285.c +++ b/arch/arm/kernel/dec21285.c @@ -23,18 +23,28 @@ #define MAX_SLOTS 21 extern int setup_arm_irq(int, struct irqaction *); -extern void pcibios_report_device_errors(void); +extern void pcibios_report_device_errors(int warn); static unsigned long -dc21285_base_address(struct pci_dev *dev, int where) +dc21285_base_address(struct pci_dev *dev) { unsigned long addr = 0; unsigned int devfn = dev->devfn; - if (dev->bus->number != 0) + if (dev->bus->number == 0) { + if (PCI_SLOT(devfn) == 0) + /* + * For devfn 0, point at the 21285 + */ + addr = ARMCSR_BASE; + else { + devfn -= 1 << 3; + + if (devfn < PCI_DEVFN(MAX_SLOTS, 0)) + addr = PCICFG0_BASE | 0xc00000 | (devfn << 8); + } + } else addr = PCICFG1_BASE | (dev->bus->number << 16) | (devfn << 8); - else if (devfn < PCI_DEVFN(MAX_SLOTS, 0)) - addr = PCICFG0_BASE | 0xc00000 | (devfn << 8); return addr; } @@ -42,7 +52,7 @@ dc21285_base_address(struct pci_dev *dev, int where) static int dc21285_read_config_byte(struct pci_dev *dev, int where, u8 *value) { - unsigned long addr = dc21285_base_address(dev, where); + unsigned long addr = dc21285_base_address(dev); u8 v; if (addr) @@ -59,7 +69,7 @@ dc21285_read_config_byte(struct pci_dev *dev, int where, u8 *value) static int dc21285_read_config_word(struct pci_dev *dev, int where, u16 *value) { - unsigned long addr = dc21285_base_address(dev, where); + unsigned long addr = dc21285_base_address(dev); u16 v; if (addr) @@ -76,7 +86,7 @@ dc21285_read_config_word(struct pci_dev *dev, int where, u16 *value) static int dc21285_read_config_dword(struct pci_dev *dev, int where, u32 *value) { - unsigned long addr = dc21285_base_address(dev, where); + unsigned long addr = dc21285_base_address(dev); u32 v; if (addr) @@ -93,7 +103,7 @@ dc21285_read_config_dword(struct pci_dev *dev, int where, u32 *value) static int dc21285_write_config_byte(struct pci_dev *dev, int where, u8 value) { - unsigned long addr = dc21285_base_address(dev, where); + unsigned long addr = dc21285_base_address(dev); if (addr) asm("str%?b %0, [%1, %2]" @@ -105,7 +115,7 @@ dc21285_write_config_byte(struct pci_dev *dev, int where, u8 value) static int dc21285_write_config_word(struct pci_dev *dev, int where, u16 value) { - unsigned long addr = dc21285_base_address(dev, where); + unsigned long addr = dc21285_base_address(dev); if (addr) asm("str%?h %0, [%1, %2]" @@ -117,7 +127,7 @@ dc21285_write_config_word(struct pci_dev *dev, int where, u16 value) static int dc21285_write_config_dword(struct pci_dev *dev, int where, u32 value) { - unsigned long addr = dc21285_base_address(dev, where); + unsigned long addr = dc21285_base_address(dev); if (addr) asm("str%? %0, [%1, %2]" @@ -147,6 +157,9 @@ dc21285_error(int irq, void *dev_id, struct pt_regs *regs) unsigned long irqstatus = *CSR_IRQ_RAWSTATUS; int warn = time_after_eq(jiffies, next_warn); + if (machine_is_netwinder()) + warn = 0; + ctrl |= SA110_CNTL_DISCARDTIMER; if (warn) { @@ -193,7 +206,7 @@ dc21285_error(int irq, void *dev_id, struct pt_regs *regs) if (warn) printk("pc=[<%08lX>]\n", instruction_pointer(regs)); - pcibios_report_device_errors(); + pcibios_report_device_errors(warn); *CSR_PCICMD = cmd; *CSR_SA110_CNTL = ctrl; diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 97dfef0c1..97fcfc522 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -6,7 +6,7 @@ #define S_OFF 8 .macro get_softirq, rd -#ifdef __SMP__ +#ifdef CONFIG_SMP #error SMP not supported #else ldr \rd, __softirq_state diff --git a/arch/arm/kernel/head-armv.S b/arch/arm/kernel/head-armv.S index 27a280b8b..956d9ccd2 100644 --- a/arch/arm/kernel/head-armv.S +++ b/arch/arm/kernel/head-armv.S @@ -12,6 +12,8 @@ #include <asm/hardware.h> #include <asm/dec21285.h> +#include "arch.h" + #if (TEXTADDR & 0xffff) != 0x8000 #error TEXTADDR must start at 0xXXXX8000 #endif @@ -231,6 +233,13 @@ __create_page_tables: * Generally, only serious errors cause this. */ __error: +#ifdef CONFIG_DEBUG_LL + mov r8, r0 @ preserve r0 + adr r0, err_str + bl printascii + mov r0, r8 + bl printch +#endif #ifdef CONFIG_ARCH_RPC /* * Turn the screen red on a error - RiscPC only. @@ -247,7 +256,10 @@ __error: 1: mov r0, r0 b 1b - +#ifdef CONFIG_DEBUG_LL +err_str: .asciz "\nError: " + .align +#endif /* * Read processor ID register (CP#15, CR0), and determine @@ -262,9 +274,9 @@ __error: __lookup_processor_type: adr r5, 2f ldmia r5, {r7, r9, r10} - sub r5, r5, r9 + sub r5, r5, r10 add r7, r7, r5 - add r10, r10, r5 + add r10, r9, r5 mrc p15, 0, r9, c0, c0 @ get processor id 1: ldmia r10, {r5, r6, r8} @ value, mask, mmuflags eor r5, r5, r9 @@ -277,8 +289,10 @@ __lookup_processor_type: mov pc, lr 2: .long __proc_info_end - .long 2b .long __proc_info_begin + .long 2b + .long __arch_info_begin + .long __arch_info_end /* * Lookup machine architecture @@ -290,135 +304,18 @@ __lookup_processor_type: * r7 = byte offset into page tables for IO */ __lookup_architecture_type: - cmp r1, #(__arch_types_end - __arch_types_start) / 16 - bge 1f - adr r4, __arch_types_start - add r4, r4, r1, lsl #4 - ldmia r4, {r4, r5, r6, r7} - mov r7, r7, lsr #18 + adr r4, 2b + ldmia r4, {r2, r3, r5, r6, r7} @ throw away r2, r3 + sub r5, r4, r5 + add r4, r6, r5 + add r7, r7, r5 +1: ldr r5, [r4] + teq r5, r1 + beq 2f + add r4, r4, #SIZEOF_MACHINE_DESC + cmp r4, r7 + blt 1b + mov r7, #0 mov pc, lr -1: mov r7, #0 +2: ldmib r4, {r5, r6, r7} mov pc, lr - -/* - * Machine parameters. Each machine requires 4 words, which are: - * - * word0: unused - * word1: physical start address of RAM - * word2: physical start address of IO - * word3: virtual start address of IO - * - * The IO mappings entered here are used to set up mappings - * required for debugging information to be shown to the user. - * paging_init() does the real page table initialisation. - */ - .type __arch_types_start, #object - @ 0x00 - DEC EBSA110 -__arch_types_start: - .long 0 - .long 0 - .long 0xe0000000 - .long 0xe0000000 - - @ 0x01 - Acorn RiscPC - .long 0 - .long 0x10000000 - .long 0x03000000 - .long 0xe0000000 - - @ 0x02 - Unused - .long 0 - .long 0 - .long 0xe0000000 - .long 0xe0000000 - - @ 0x03 - NexusPCI - .long 0 - .long 0x40000000 - .long 0x10000000 - .long 0xe0000000 - - @ 0x04 - DEC EBSA285 - .long 0 - .long 0 - .long DC21285_ARMCSR_BASE - .long 0xfe000000 - - @ 0x05 - Rebel.com NetWinder - .long 0 - .long 0 - .long DC21285_ARMCSR_BASE - .long 0xfe000000 - - @ 0x06 - CATS - .long 0 - .long 0 - .long DC21285_ARMCSR_BASE - .long 0xfe000000 - - @ 0x07 - tbox - .long 0 - .long 0x80000000 - .long 0x00400000 @ Uart - .long 0xe0000000 - - @ 0x08 - DEC EBSA285 as co-processor - .long 0 - .long 0 - .long DC21285_ARMCSR_BASE @ Physical I/O base address - .long 0x7cf00000 @ Virtual I/O base address - - @ 0x09 - CL-PS7110 - .long 0 - .long 0 - .long 0 - .long 0 - - @ 0x0a - Acorn Archimedes - .long 0 - .long 0 - .long 0 - .long 0 - - @ 0x0b - Acorn A5000 - .long 0 - .long 0 - .long 0 - .long 0 - - @ 0x0c - Etoile - .long 0 - .long 0 - .long 0 - .long 0 - - @ 0x0d - LaCie_NAS - .long 0 - .long 0 - .long 0 - .long 0 - - @ 0x0e - CL-PS7500 - .long 0 - .long 0x10000000 - .long 0x03000000 - .long 0xe0000000 - - @ 0x0f - Digital Shark (DNARD) - .long 0 - .long 0x08000000 - .long 0x40000000 - .long 0xe0000000 - - @ 0x10 - SA1100 - .long 0 - .long 0xc0000000 - .long 0x80000000 - .long 0xf8000000 - - /* - * Don't add anything here unless you have an - * architecture number allocated - see - * Documentation/arm/README - */ -__arch_types_end: diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 699cea4ab..1b26ced94 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -118,10 +118,8 @@ void enable_irq(unsigned int irq) cliIF(); irq_desc[irq].probing = 0; irq_desc[irq].triggered = 0; - if (!irq_desc[irq].noautoenable) { - irq_desc[irq].enabled = 1; - irq_desc[irq].unmask(irq); - } + irq_desc[irq].enabled = 1; + irq_desc[irq].unmask(irq); spin_unlock_irqrestore(&irq_controller_lock, flags); } diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index f04b422b4..ec67dcbd0 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -5,15 +5,14 @@ */ #include <linux/config.h> #include <linux/kernel.h> -#include <linux/mm.h> #include <linux/stddef.h> #include <linux/ioport.h> #include <linux/delay.h> #include <linux/utsname.h> #include <linux/blk.h> #include <linux/console.h> -#include <linux/init.h> #include <linux/bootmem.h> +#include <linux/init.h> #include <asm/elf.h> #include <asm/hardware.h> @@ -33,6 +32,7 @@ #endif extern void paging_init(struct meminfo *); +extern void bootmem_init(struct meminfo *); extern void reboot_setup(char *str); extern void disable_hlt(void); extern int root_mountflags; @@ -43,6 +43,7 @@ unsigned int __machine_arch_type; unsigned int system_rev; unsigned int system_serial_low; unsigned int system_serial_high; +unsigned int mem_fclk_21285 = 50000000; unsigned int elf_hwcap; #ifdef MULTI_CPU @@ -199,7 +200,8 @@ parse_cmdline(struct meminfo *mi, char **cmdline_p, char *from) if (to != command_line) to -= 1; - /* If the user specifies memory size, we + /* + * If the user specifies memory size, we * blow away any automatically generated * size. */ @@ -256,137 +258,6 @@ void __init setup_initrd(unsigned int start, unsigned int size) #endif } -#define O_PFN_DOWN(x) ((x) >> PAGE_SHIFT) -#define V_PFN_DOWN(x) O_PFN_DOWN(__pa(x)) - -#define O_PFN_UP(x) (PAGE_ALIGN(x) >> PAGE_SHIFT) -#define V_PFN_UP(x) O_PFN_UP(__pa(x)) - -#define PFN_SIZE(x) ((x) >> PAGE_SHIFT) -#define PFN_RANGE(s,e) PFN_SIZE(PAGE_ALIGN((unsigned long)(e)) - \ - (((unsigned long)(s)) & PAGE_MASK)) - -/* - * FIXME: These can be removed when Ingo's cleanup patch goes in - */ -#define free_bootmem(s,sz) free_bootmem((s)<<PAGE_SHIFT, (sz)<<PAGE_SHIFT) -#define reserve_bootmem(s,sz) reserve_bootmem((s)<<PAGE_SHIFT, (sz)<<PAGE_SHIFT) - -static unsigned int __init -find_bootmap_pfn(struct meminfo *mi, unsigned int bootmap_pages) -{ - unsigned int start_pfn, bank, bootmap_pfn; - - start_pfn = V_PFN_UP(&_end); - bootmap_pfn = 0; - - /* - * FIXME: We really want to avoid allocating the bootmap - * over the top of the initrd. - */ -#ifdef CONFIG_BLK_DEV_INITRD - if (initrd_start) { - if (__pa(initrd_end) > mi->end) { - printk ("initrd extends beyond end of memory " - "(0x%08lx > 0x%08lx) - disabling initrd\n", - __pa(initrd_end), mi->end); - initrd_start = 0; - initrd_end = 0; - } - } -#endif - - for (bank = 0; bank < mi->nr_banks; bank ++) { - unsigned int start, end; - - if (mi->bank[bank].size == 0) - continue; - - start = O_PFN_UP(mi->bank[bank].start); - end = O_PFN_DOWN(mi->bank[bank].size + - mi->bank[bank].start); - - if (end < start_pfn) - continue; - - if (start < start_pfn) - start = start_pfn; - - if (end <= start) - continue; - - if (end - start >= bootmap_pages) { - bootmap_pfn = start; - break; - } - } - - if (bootmap_pfn == 0) - BUG(); - - return bootmap_pfn; -} - -/* - * Initialise the bootmem allocator. - */ -static void __init setup_bootmem(struct meminfo *mi) -{ - unsigned int end_pfn, start_pfn, bootmap_pages, bootmap_pfn; - unsigned int i; - - /* - * Calculate the physical address of the top of memory. - */ - mi->end = 0; - for (i = 0; i < mi->nr_banks; i++) { - unsigned long end; - - if (mi->bank[i].size != 0) { - end = mi->bank[i].start + mi->bank[i].size; - if (mi->end < end) - mi->end = end; - } - } - - start_pfn = O_PFN_UP(PHYS_OFFSET); - end_pfn = O_PFN_DOWN(mi->end); - bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn); - bootmap_pfn = find_bootmap_pfn(mi, bootmap_pages); - - /* - * Initialise the boot-time allocator - */ - init_bootmem_start(bootmap_pfn, start_pfn, end_pfn); - - /* - * Register all available RAM with the bootmem allocator. - */ - for (i = 0; i < mi->nr_banks; i++) - if (mi->bank[i].size) - free_bootmem(O_PFN_UP(mi->bank[i].start), - PFN_SIZE(mi->bank[i].size)); - - /* - * Register the reserved regions with bootmem - */ - reserve_bootmem(bootmap_pfn, bootmap_pages); - reserve_bootmem(V_PFN_DOWN(&_stext), PFN_RANGE(&_stext, &_end)); - -#ifdef CONFIG_CPU_32 - /* - * Reserve the page tables. These are already in use. - */ - reserve_bootmem(V_PFN_DOWN(swapper_pg_dir), - PFN_SIZE(PTRS_PER_PGD * sizeof(void *))); -#endif -#ifdef CONFIG_BLK_DEV_INITRD - if (initrd_start) - reserve_bootmem(V_PFN_DOWN(initrd_start), - PFN_RANGE(initrd_start, initrd_end)); -#endif -} - static void __init request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc) { @@ -487,6 +358,9 @@ void __init setup_arch(char **cmdline_p) system_serial_low = params->u1.s.system_serial_low; system_serial_high = params->u1.s.system_serial_high; + if (params->u1.s.mem_fclk_21285 > 0) + mem_fclk_21285 = params->u1.s.mem_fclk_21285; + setup_ramdisk((params->u1.s.flags & FLAG_RDLOAD) == 0, (params->u1.s.flags & FLAG_RDPROMPT) == 0, params->u1.s.rd_start, @@ -518,9 +392,8 @@ void __init setup_arch(char **cmdline_p) memcpy(saved_command_line, from, COMMAND_LINE_SIZE); saved_command_line[COMMAND_LINE_SIZE-1] = '\0'; parse_cmdline(&meminfo, cmdline_p, from); - setup_bootmem(&meminfo); + bootmem_init(&meminfo); request_standard_resources(&meminfo, mdesc); - paging_init(&meminfo); #ifdef CONFIG_VT diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index 0fcad67c0..c79b323a9 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c @@ -30,6 +30,7 @@ extern int setup_arm_irq(int, struct irqaction *); extern void setup_timer(void); +extern rwlock_t xtime_lock; extern volatile unsigned long lost_ticks; /* change this if you have some constant time drift */ @@ -59,7 +60,8 @@ static unsigned long dummy_gettimeoffset(void) } /* - * hook for getting the time offset + * hook for getting the time offset. Note that it is + * always called with interrupts disabled. */ unsigned long (*gettimeoffset)(void) = dummy_gettimeoffset; @@ -175,29 +177,33 @@ static void do_leds(void) void do_gettimeofday(struct timeval *tv) { unsigned long flags; + unsigned long usec, sec; - save_flags_cli (flags); - *tv = xtime; - tv->tv_usec += gettimeoffset(); + read_lock_irqsave(&xtime_lock, flags); + usec = gettimeoffset(); + { + unsigned long lost = lost_ticks; - /* - * xtime is atomically updated in timer_bh. lost_ticks is - * nonzero if the timer bottom half hasnt executed yet. - */ - if (lost_ticks) - tv->tv_usec += USECS_PER_JIFFY; - - restore_flags(flags); - - if (tv->tv_usec >= 1000000) { - tv->tv_usec -= 1000000; - tv->tv_sec++; + if (lost) + usec += lost * USECS_PER_JIFFY; } + sec = xtime.tv_sec; + usec += xtime.tv_usec; + read_unlock_irqrestore(&xtime_lock, flags); + + /* usec may have gone up a lot: be safe */ + while (usec >= 1000000) { + usec -= 1000000; + sec++; + } + + tv->tv_sec = sec; + tv->tv_usec = usec; } void do_settimeofday(struct timeval *tv) { - cli (); + write_lock_irq(&xtime_lock); /* This is revolting. We need to set the xtime.tv_usec * correctly. However, the value in this location is * is value at the last tick. @@ -205,8 +211,9 @@ void do_settimeofday(struct timeval *tv) * would have done, and then undo it! */ tv->tv_usec -= gettimeoffset(); + tv->tv_usec -= lost_ticks * USECS_PER_JIFFY; - if (tv->tv_usec < 0) { + while (tv->tv_usec < 0) { tv->tv_usec += 1000000; tv->tv_sec--; } @@ -216,7 +223,7 @@ void do_settimeofday(struct timeval *tv) time_status |= STA_UNSYNC; time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; - sti(); + write_unlock_irq(&xtime_lock); } static struct irqaction timer_irq = { diff --git a/arch/arm/lib/csumpartialcopy.S b/arch/arm/lib/csumpartialcopy.S index 7289619da..fc52662a8 100644 --- a/arch/arm/lib/csumpartialcopy.S +++ b/arch/arm/lib/csumpartialcopy.S @@ -12,16 +12,46 @@ * Params : r0 = src, r1 = dst, r2 = len, r3 = checksum * Returns : r0 = new checksum */ + + .macro save_regs + stmfd sp!, {r4 - r8, fp, ip, lr, pc} + .endm + + .macro load_regs,flags + LOADREGS(\flags,fp,{r4 - r8, fp, sp, pc}) + .endm + + .macro load1b, reg1 + ldrb \reg1, [r0], #1 + .endm + + .macro load2b, reg1, reg2 + ldrb \reg1, [r0], #1 + ldrb \reg2, [r0], #1 + .endm + + .macro load1l, reg1 + ldr \reg1, [r0], #4 + .endm + + .macro load2l, reg1, reg2 + ldr \reg1, [r0], #4 + ldr \reg2, [r0], #4 + .endm + + .macro load4l, reg1, reg2, reg3, reg4 + ldmia r0!, {\reg1, \reg2, \reg3, \reg4} + .endm + ENTRY(csum_partial_copy_nocheck) mov ip, sp - stmfd sp!, {r4 - r8, fp, ip, lr, pc} + save_regs sub fp, ip, #4 cmp r2, #4 - blt Ltoo_small + blt .too_small tst r1, #2 @ Test destination alignment - beq Ldst_aligned - ldrb ip, [r0], #1 - ldrb r8, [r0], #1 + beq .dst_aligned + load2b ip, r8 subs r2, r2, #2 @ We do not know if SRC is aligned... orr ip, ip, r8, lsl #8 adds r3, r3, ip @@ -29,12 +59,12 @@ ENTRY(csum_partial_copy_nocheck) strb ip, [r1], #1 mov ip, ip, lsr #8 strb ip, [r1], #1 @ Destination now aligned -Ldst_aligned: tst r0, #3 - bne Lsrc_not_aligned +.dst_aligned: tst r0, #3 + bne .src_not_aligned adds r3, r3, #0 bics ip, r2, #15 @ Routine for src & dst aligned - beq 3f -1: ldmia r0!, {r4, r5, r6, r7} + beq 2f +1: load4l r4, r5, r6, r7 stmia r1!, {r4, r5, r6, r7} adcs r3, r3, r4 adcs r3, r3, r5 @@ -43,65 +73,69 @@ Ldst_aligned: tst r0, #3 sub ip, ip, #16 teq ip, #0 bne 1b -3: ands ip, r2, #12 - beq 5f - tst ip, #8 +2: ands ip, r2, #12 beq 4f - ldmia r0!, {r4, r5} + tst ip, #8 + beq 3f + load2l r4, r5 stmia r1!, {r4, r5} adcs r3, r3, r4 adcs r3, r3, r5 tst ip, #4 - beq 5f -4: ldr r4, [r0], #4 + beq 4f +3: load1l r4 str r4, [r1], #4 adcs r3, r3, r4 -5: ands r2, r2, #3 +4: ands r2, r2, #3 adceq r0, r3, #0 - LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) - ldr r4, [r0], #4 + load_regs eqea + load1l r4 tst r2, #2 - beq Lexit_r4 + beq .exit adcs r3, r3, r4, lsl #16 strb r4, [r1], #1 mov r4, r4, lsr #8 strb r4, [r1], #1 mov r4, r4, lsr #8 - b Lexit_r4 +.exit: tst r2, #1 + strneb r4, [r1], #1 + andne r4, r4, #255 + adcnes r3, r3, r4 + adcs r0, r3, #0 + load_regs ea -Ltoo_small: teq r2, #0 - LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) +.too_small: teq r2, #0 + load_regs eqea cmp r2, #2 - blt Ltoo_small1 - ldrb ip, [r0], #1 - ldrb r8, [r0], #1 + blt .too_small1 + load2b ip, r8 orr ip, ip, r8, lsl #8 adds r3, r3, ip strb ip, [r1], #1 strb r8, [r1], #1 tst r2, #1 -Ltoo_small1: ldrneb r4, [r0], #1 -Lexit_r4: tst r2, #1 - strneb r4, [r1], #1 - andne r4, r4, #255 - adcnes r3, r3, r4 - adcs r0, r3, #0 - LOADREGS(ea,fp,{r4 - r8, fp, sp, pc}) +.too_small1: @ C = 0 + beq .csum_exit + load1b ip + strb ip, [r1], #1 + adcs r3, r3, ip +.csum_exit: adc r0, r3, #0 + load_regs ea -Lsrc_not_aligned: +.src_not_aligned: cmp r2, #4 - blt Ltoo_small + blt .too_small and ip, r0, #3 bic r0, r0, #3 - ldr r4, [r0], #4 + load1l r4 cmp ip, #2 - beq Lsrc2_aligned - bhi Lsrc3_aligned + beq .src2_aligned + bhi .src3_aligned mov r4, r4, lsr #8 adds r3, r3, #0 bics ip, r2, #15 beq 2f -1: ldmia r0!, {r5, r6, r7, r8} +1: load4l r5, r6, r7, r8 orr r4, r4, r5, lsl #24 mov r5, r5, lsr #8 orr r5, r5, r6, lsl #24 @@ -122,7 +156,7 @@ Lsrc_not_aligned: beq 4f tst ip, #8 beq 3f - ldmia r0!, {r5, r6} + load2l r5, r6 orr r4, r4, r5, lsl #24 mov r5, r5, lsr #8 orr r5, r5, r6, lsl #24 @@ -132,28 +166,28 @@ Lsrc_not_aligned: mov r4, r6, lsr #8 tst ip, #4 beq 4f -3: ldr r5, [r0], #4 +3: load1l r5 orr r4, r4, r5, lsl #24 str r4, [r1], #4 adcs r3, r3, r4 mov r4, r5, lsr #8 4: ands r2, r2, #3 adceq r0, r3, #0 - LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) + load_regs eqea tst r2, #2 - beq Lexit_r4 + beq .exit adcs r3, r3, r4, lsl #16 strb r4, [r1], #1 mov r4, r4, lsr #8 strb r4, [r1], #1 mov r4, r4, lsr #8 - b Lexit_r4 + b .exit -Lsrc2_aligned: mov r4, r4, lsr #16 +.src2_aligned: mov r4, r4, lsr #16 adds r3, r3, #0 bics ip, r2, #15 beq 2f -1: ldmia r0!, {r5, r6, r7, r8} +1: load4l r5, r6, r7, r8 orr r4, r4, r5, lsl #16 mov r5, r5, lsr #16 orr r5, r5, r6, lsl #16 @@ -174,7 +208,7 @@ Lsrc2_aligned: mov r4, r4, lsr #16 beq 4f tst ip, #8 beq 3f - ldmia r0!, {r5, r6} + load2l r5, r6 orr r4, r4, r5, lsl #16 mov r5, r5, lsr #16 orr r5, r5, r6, lsl #16 @@ -184,28 +218,31 @@ Lsrc2_aligned: mov r4, r4, lsr #16 mov r4, r6, lsr #16 tst ip, #4 beq 4f -3: ldr r5, [r0], #4 +3: load1l r5 orr r4, r4, r5, lsl #16 str r4, [r1], #4 adcs r3, r3, r4 mov r4, r5, lsr #16 4: ands r2, r2, #3 adceq r0, r3, #0 - LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) + load_regs eqea tst r2, #2 - beq Lexit_r4 + beq .exit adcs r3, r3, r4, lsl #16 strb r4, [r1], #1 mov r4, r4, lsr #8 strb r4, [r1], #1 - ldrb r4, [r0], #1 - b Lexit_r4 + tst r2, #1 + adceq r0, r3, #0 + load_regs eqea + load1b r4 + b .exit -Lsrc3_aligned: mov r4, r4, lsr #24 +.src3_aligned: mov r4, r4, lsr #24 adds r3, r3, #0 bics ip, r2, #15 beq 2f -1: ldmia r0!, {r5, r6, r7, r8} +1: load4l r5, r6, r7, r8 orr r4, r4, r5, lsl #8 mov r5, r5, lsr #24 orr r5, r5, r6, lsl #8 @@ -226,7 +263,7 @@ Lsrc3_aligned: mov r4, r4, lsr #24 beq 4f tst ip, #8 beq 3f - ldmia r0!, {r5, r6} + load2l r5, r6 orr r4, r4, r5, lsl #8 mov r5, r5, lsr #24 orr r5, r5, r6, lsl #8 @@ -236,22 +273,20 @@ Lsrc3_aligned: mov r4, r4, lsr #24 mov r4, r6, lsr #24 tst ip, #4 beq 4f -3: ldr r5, [r0], #4 +3: load1l r5 orr r4, r4, r5, lsl #8 str r4, [r1], #4 adcs r3, r3, r4 mov r4, r5, lsr #24 4: ands r2, r2, #3 adceq r0, r3, #0 - LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) + load_regs eqea tst r2, #2 - beq Lexit_r4 + beq .exit adcs r3, r3, r4, lsl #16 strb r4, [r1], #1 - ldr r4, [r0], #4 + load1l r4 strb r4, [r1], #1 adcs r3, r3, r4, lsl #24 mov r4, r4, lsr #8 - b Lexit_r4 - - + b .exit diff --git a/arch/arm/lib/csumpartialcopyuser.S b/arch/arm/lib/csumpartialcopyuser.S index f698c0d26..cde500440 100644 --- a/arch/arm/lib/csumpartialcopyuser.S +++ b/arch/arm/lib/csumpartialcopyuser.S @@ -153,9 +153,9 @@ ENTRY(csum_partial_copy_from_user) save_regs sub fp, ip, #4 cmp r2, #4 - blt .too_small_user + blt .too_small tst r1, #2 @ Test destination alignment - beq .dst_aligned_user + beq .dst_aligned load2b ip, r8 subs r2, r2, #2 @ We do not know if SRC is aligned... orr ip, ip, r8, lsl #8 @@ -164,9 +164,8 @@ ENTRY(csum_partial_copy_from_user) strb ip, [r1], #1 mov ip, ip, lsr #8 strb ip, [r1], #1 @ Destination now aligned -.dst_aligned_user: - tst r0, #3 - bne .src_not_aligned_user +.dst_aligned: tst r0, #3 + bne .src_not_aligned adds r3, r3, #0 bics ip, r2, #15 @ Routine for src & dst aligned beq 2f @@ -210,18 +209,17 @@ ENTRY(csum_partial_copy_from_user) adcs r0, r3, #0 load_regs ea -.too_small_user: - teq r2, #0 +.too_small: teq r2, #0 load_regs eqea cmp r2, #2 - blt .too_small_user1 + blt .too_small1 load2b ip, r8 orr ip, ip, r8, lsl #8 adds r3, r3, ip strb ip, [r1], #1 strb r8, [r1], #1 tst r2, #1 -.too_small_user1: @ C = 0 +.too_small1: @ C = 0 beq .csum_exit load1b ip strb ip, [r1], #1 @@ -229,15 +227,15 @@ ENTRY(csum_partial_copy_from_user) .csum_exit: adc r0, r3, #0 load_regs ea -.src_not_aligned_user: +.src_not_aligned: cmp r2, #4 - blt .too_small_user + blt .too_small and ip, r0, #3 bic r0, r0, #3 load1l r4 cmp ip, #2 - beq .src2_aligned_user - bhi .src3_aligned_user + beq .src2_aligned + bhi .src3_aligned mov r4, r4, lsr #8 adds r3, r3, #0 bics ip, r2, #15 @@ -290,8 +288,7 @@ ENTRY(csum_partial_copy_from_user) mov r4, r4, lsr #8 b .exit -.src2_aligned_user: - mov r4, r4, lsr #16 +.src2_aligned: mov r4, r4, lsr #16 adds r3, r3, #0 bics ip, r2, #15 beq 2f @@ -346,8 +343,7 @@ ENTRY(csum_partial_copy_from_user) load1b r4 b .exit -.src3_aligned_user: - mov r4, r4, lsr #24 +.src3_aligned: mov r4, r4, lsr #24 adds r3, r3, #0 bics ip, r2, #15 beq 2f diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c index 76d1a5c74..310107678 100644 --- a/arch/arm/mm/consistent.c +++ b/arch/arm/mm/consistent.c @@ -29,20 +29,29 @@ void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle) if (in_interrupt()) BUG(); + size = PAGE_ALIGN(size); order = get_order(size); page = __get_free_pages(gfp, order); if (!page) goto no_page; - memset((void *)page, 0, PAGE_SIZE << order); - clean_cache_area(page, PAGE_SIZE << order); + memset((void *)page, 0, size); + clean_cache_area(page, size); *dma_handle = virt_to_bus((void *)page); - ret = __ioremap(virt_to_phys((void *)page), PAGE_SIZE << order, 0); - if (ret) + ret = __ioremap(virt_to_phys((void *)page), size, 0); + if (ret) { + /* free wasted pages */ + unsigned long end = page + (PAGE_SIZE << order); + page += size; + while (page < end) { + free_page(page); + page += PAGE_SIZE; + } return ret; + } free_pages(page, order); no_page: @@ -81,18 +90,18 @@ void consistent_free(void *vaddr) /* * make an area consistent. */ -void consistent_sync(void *vaddr, size_t size, int rw) +void consistent_sync(void *vaddr, size_t size, int direction) { - switch (rw) { - case 0: + switch (direction) { + case PCI_DMA_NONE: BUG(); - case 1: /* invalidate only */ + case PCI_DMA_FROMDEVICE: /* invalidate only */ dma_cache_inv(vaddr, size); break; - case 2: /* writeback only */ + case PCI_DMA_TODEVICE: /* writeback only */ dma_cache_wback(vaddr, size); break; - case 3: /* writeback and invalidate */ + case PCI_DMA_BIDIRECTIONAL: /* writeback and invalidate */ dma_cache_wback_inv(vaddr, size); break; } diff --git a/arch/arm/mm/fault-common.c b/arch/arm/mm/fault-common.c index c34c37203..14cf5a925 100644 --- a/arch/arm/mm/fault-common.c +++ b/arch/arm/mm/fault-common.c @@ -123,7 +123,7 @@ good_area: * make sure we exit gracefully rather than endlessly redo * the fault. */ - if (!handle_mm_fault(tsk, vma, addr & PAGE_MASK, DO_COW(mode))) + if (!handle_mm_fault(mm, vma, addr & PAGE_MASK, DO_COW(mode))) goto do_sigbus; up(&mm->mmap_sem); diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index e7b8c8bb9..61feb6a55 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -1,9 +1,8 @@ /* * linux/arch/arm/mm/init.c * - * Copyright (C) 1995-1999 Russell King + * Copyright (C) 1995-2000 Russell King */ - #include <linux/config.h> #include <linux/signal.h> #include <linux/sched.h> @@ -32,9 +31,22 @@ #include "map.h" +#ifdef CONFIG_CPU_32 +#define TABLE_OFFSET (PTRS_PER_PTE) +#else +#define TABLE_OFFSET 0 +#endif +#define TABLE_SIZE ((TABLE_OFFSET + PTRS_PER_PTE) * sizeof(void *)) + static unsigned long totalram_pages; -struct meminfo meminfo; pgd_t swapper_pg_dir[PTRS_PER_PGD]; +extern int _stext, _text, _etext, _edata, _end; + +/* + * The sole use of this is to pass memory configuration + * data from paging_init to mem_init. + */ +static struct meminfo __initdata meminfo; /* * empty_bad_page is the page that is used for page faults when @@ -119,33 +131,36 @@ int do_check_pgt_cache(int low, int high) void show_mem(void) { int free = 0, total = 0, reserved = 0; - int shared = 0, cached = 0; - struct page *page, *end; + int shared = 0, cached = 0, node; printk("Mem-info:\n"); show_free_areas(); printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10)); - page = mem_map; - end = mem_map + max_mapnr; + for (node = 0; node < numnodes; node++) { + struct page *page, *end; - do { - if (PageSkip(page)) { - page = page->next_hash; - if (page == NULL) - break; - } - total++; - if (PageReserved(page)) - reserved++; - else if (PageSwapCache(page)) - cached++; - else if (!page_count(page)) - free++; - else - shared += atomic_read(&page->count) - 1; - page++; - } while (page < end); + page = NODE_MEM_MAP(node); + end = page + NODE_DATA(node)->node_size; + + do { + if (PageSkip(page)) { + page = page->next_hash; + if (page == NULL) + break; + } + total++; + if (PageReserved(page)) + reserved++; + else if (PageSwapCache(page)) + cached++; + else if (!page_count(page)) + free++; + else + shared += atomic_read(&page->count) - 1; + page++; + } while (page < end); + } printk("%d pages of RAM\n", total); printk("%d free pages\n", free); @@ -158,24 +173,173 @@ void show_mem(void) show_buffers(); } +#define O_PFN_DOWN(x) ((x) >> PAGE_SHIFT) +#define V_PFN_DOWN(x) O_PFN_DOWN(__pa(x)) + +#define O_PFN_UP(x) (PAGE_ALIGN(x) >> PAGE_SHIFT) +#define V_PFN_UP(x) O_PFN_UP(__pa(x)) + +#define PFN_SIZE(x) ((x) >> PAGE_SHIFT) +#define PFN_RANGE(s,e) PFN_SIZE(PAGE_ALIGN((unsigned long)(e)) - \ + (((unsigned long)(s)) & PAGE_MASK)) + +static unsigned int __init +find_bootmap_pfn(struct meminfo *mi, unsigned int bootmap_pages) +{ + unsigned int start_pfn, bank, bootmap_pfn; + + start_pfn = V_PFN_UP(&_end); + bootmap_pfn = 0; + + /* + * FIXME: We really want to avoid allocating the bootmap + * over the top of the initrd. + */ +#ifdef CONFIG_BLK_DEV_INITRD + if (initrd_start) { + if (__pa(initrd_end) > mi->end) { + printk ("initrd extends beyond end of memory " + "(0x%08lx > 0x%08lx) - disabling initrd\n", + __pa(initrd_end), mi->end); + initrd_start = 0; + initrd_end = 0; + } + } +#endif + + for (bank = 0; bank < mi->nr_banks; bank ++) { + unsigned int start, end; + + if (mi->bank[bank].size == 0) + continue; + + start = O_PFN_UP(mi->bank[bank].start); + end = O_PFN_DOWN(mi->bank[bank].size + + mi->bank[bank].start); + + if (end < start_pfn) + continue; + + if (start < start_pfn) + start = start_pfn; + + if (end <= start) + continue; + + if (end - start >= bootmap_pages) { + bootmap_pfn = start; + break; + } + } + + if (bootmap_pfn == 0) + BUG(); + + return bootmap_pfn; +} + +/* + * Initialise one node of the bootmem allocator. For now, we + * only initialise node 0. Notice that we have a bootmem + * bitmap per node. + */ +static void __init setup_bootmem_node(int node, struct meminfo *mi) +{ + unsigned int end_pfn, start_pfn, bootmap_pages, bootmap_pfn; + unsigned int i; + + if (node != 0) /* only initialise node 0 for now */ + return; + + start_pfn = O_PFN_UP(PHYS_OFFSET); + end_pfn = O_PFN_DOWN(mi->end); + bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn); + bootmap_pfn = find_bootmap_pfn(mi, bootmap_pages); + + /* + * Initialise the boot-time allocator + */ + init_bootmem_node(node, bootmap_pfn, start_pfn, end_pfn); + + /* + * Register all available RAM with the bootmem allocator. + */ + for (i = 0; i < mi->nr_banks; i++) + if (mi->bank[i].size) + free_bootmem_node(node, mi->bank[i].start, + PFN_SIZE(mi->bank[i].size) << PAGE_SHIFT); + + reserve_bootmem_node(node, bootmap_pfn << PAGE_SHIFT, + bootmap_pages << PAGE_SHIFT); +} + +/* + * Initialise the bootmem allocator. + */ +void __init bootmem_init(struct meminfo *mi) +{ + unsigned int i, node; + + /* + * Calculate the physical address of the top of memory. + * Note that there are no guarantees assumed about the + * ordering of the bank information. + */ + mi->end = 0; + for (i = 0; i < mi->nr_banks; i++) { + unsigned long end; + + if (mi->bank[i].size != 0) { + end = mi->bank[i].start + mi->bank[i].size; + if (mi->end < end) + mi->end = end; + } + } + + max_low_pfn = O_PFN_DOWN(mi->end - PHYS_OFFSET); + + /* + * Setup each node + */ + for (node = 0; node < numnodes; node++) + setup_bootmem_node(node, mi); + + /* + * Register the kernel text and data with bootmem. + * Note that this can only be in node 0. + */ + reserve_bootmem_node(0, V_PFN_DOWN(&_stext) << PAGE_SHIFT, + PFN_RANGE(&_stext, &_end) << PAGE_SHIFT); + +#ifdef CONFIG_CPU_32 + /* + * Reserve the page tables. These are already in use, + * and can only be in node 0. + */ + reserve_bootmem_node(0, V_PFN_DOWN(swapper_pg_dir) << PAGE_SHIFT, + PFN_SIZE(PTRS_PER_PGD * sizeof(void *)) << PAGE_SHIFT); +#endif +#ifdef CONFIG_BLK_DEV_INITRD + /* + * This may be in any bank. Currently, we assume that + * it is in bank 0. + */ + if (initrd_start) + reserve_bootmem_node(0, V_PFN_DOWN(initrd_start) << PAGE_SHIFT, + PFN_RANGE(initrd_start, initrd_end) << PAGE_SHIFT); +#endif +} + /* * paging_init() sets up the page tables... */ void __init paging_init(struct meminfo *mi) { void *zero_page, *bad_page, *bad_table; - unsigned long zone_size[MAX_NR_ZONES]; - int i; + int node; memcpy(&meminfo, mi, sizeof(meminfo)); -#ifdef CONFIG_CPU_32 -#define TABLE_OFFSET (PTRS_PER_PTE) -#else -#define TABLE_OFFSET 0 -#endif -#define TABLE_SIZE ((TABLE_OFFSET + PTRS_PER_PTE) * sizeof(void *)) - /* * allocate what we need for the bad pages */ @@ -186,31 +350,42 @@ void __init paging_init(struct meminfo *mi) /* * initialise the page tables */ - pagetable_init(); + pagetable_init(mi); flush_tlb_all(); /* - * Initialise the zones and mem_map + * initialise the zones within each node */ - for (i = 0; i < MAX_NR_ZONES; i++) - zone_size[i] = 0; + for (node = 0; node < numnodes; node++) { + unsigned long zone_size[MAX_NR_ZONES]; + unsigned long zhole_size[MAX_NR_ZONES]; + struct bootmem_data *bdata; + pg_data_t *pgdat; + int i; - /* - * Calculate the size of the zones. On ARM, we don't have - * any problems with DMA or highmem, so all memory is - * allocated to the DMA zone. - */ - for (i = 0; i < mi->nr_banks; i++) { - if (mi->bank[i].size) { - unsigned int end; - - end = (mi->bank[i].start - PHYS_OFFSET + - mi->bank[i].size) >> PAGE_SHIFT; - if (zone_size[0] < end) - zone_size[0] = end; + /* + * Initialise the zone size information. + */ + for (i = 0; i < MAX_NR_ZONES; i++) { + zone_size[i] = 0; + zhole_size[i] = 0; } + + pgdat = NODE_DATA(node); + bdata = pgdat->bdata; + + /* + * The size of this node has already been determined. + * If we need to do anything fancy with the allocation + * of this memory to the zones, now is the time to do + * it. For now, we don't touch zhole_size. + */ + zone_size[0] = bdata->node_low_pfn - + (bdata->node_boot_start >> PAGE_SHIFT); + + free_area_init_node(node, pgdat, zone_size, + bdata->node_boot_start, zhole_size); } - free_area_init(zone_size); /* * finish off the bad pages once @@ -256,32 +431,33 @@ static inline void free_unused_mem_map(void) */ void __init mem_init(void) { - extern char __init_begin, __init_end, _text, _etext, _end; + extern char __init_begin, __init_end; unsigned int codepages, datapages, initpages; - int i; + int i, node; codepages = &_etext - &_text; datapages = &_end - &_etext; initpages = &__init_end - &__init_begin; - max_mapnr = max_low_pfn; - high_memory = (void *)__va(PHYS_OFFSET + max_low_pfn * PAGE_SIZE); + high_memory = (void *)__va(meminfo.end); + max_mapnr = MAP_NR(high_memory); /* * We may have non-contiguous memory. Setup the PageSkip stuff, * and mark the areas of mem_map which can be freed */ if (meminfo.nr_banks != 1) - create_memmap_holes(); + create_memmap_holes(&meminfo); /* this will put all unused low memory onto the freelists */ - totalram_pages += free_all_bootmem(); + for (node = 0; node < numnodes; node++) + totalram_pages += free_all_bootmem_node(node); /* * Since our memory may not be contiguous, calculate the * real number of pages we have in this system */ - printk("Memory:"); + printk(KERN_INFO "Memory:"); num_physpages = 0; for (i = 0; i < meminfo.nr_banks; i++) { @@ -290,7 +466,8 @@ void __init mem_init(void) } printk(" = %luMB total\n", num_physpages >> (20 - PAGE_SHIFT)); - printk("Memory: %luKB available (%dK code, %dK data, %dK init)\n", + printk(KERN_NOTICE "Memory: %luKB available (%dK code, " + "%dK data, %dK init)\n", (unsigned long) nr_free_pages() << (PAGE_SHIFT-10), codepages >> 10, datapages >> 10, initpages >> 10); diff --git a/arch/arm/mm/map.h b/arch/arm/mm/map.h index b596c6479..1d071748d 100644 --- a/arch/arm/mm/map.h +++ b/arch/arm/mm/map.h @@ -19,7 +19,7 @@ struct map_desc { extern struct map_desc io_desc[]; extern unsigned int io_desc_size; -extern void zonesize_init(unsigned int *); -extern void create_memmap_holes(void); -extern void pagetable_init(void); +struct meminfo; +extern void create_memmap_holes(struct meminfo *); +extern void pagetable_init(struct meminfo *); diff --git a/arch/arm/mm/mm-armo.c b/arch/arm/mm/mm-armo.c index f4bf7cad5..dc1647a2d 100644 --- a/arch/arm/mm/mm-armo.c +++ b/arch/arm/mm/mm-armo.c @@ -147,7 +147,7 @@ void setup_mm_for_reboot(char mode) * some more work to get it to fit into our separate processor and * architecture structure. */ -void __init pagetable_init(void) +void __init pagetable_init(struct meminfo *mi) { pte_t *pte; int i; @@ -165,6 +165,6 @@ void __init pagetable_init(void) /* * We never have holes in the memmap */ -void __init create_memmap_holes(void) +void __init create_memmap_holes(struct meminfo *mi) { } diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c index 5d46369eb..f58bc66f5 100644 --- a/arch/arm/mm/mm-armv.c +++ b/arch/arm/mm/mm-armv.c @@ -310,7 +310,7 @@ void setup_mm_for_reboot(char mode) } } -void __init pagetable_init(void) +void __init pagetable_init(struct meminfo *mi) { struct map_desc *init_maps, *p, *q; unsigned long address = 0; @@ -335,13 +335,13 @@ void __init pagetable_init(void) p ++; - for (i = 0; i < meminfo.nr_banks; i++) { - if (meminfo.bank[i].size == 0) + for (i = 0; i < mi->nr_banks; i++) { + if (mi->bank[i].size == 0) continue; - p->physical = meminfo.bank[i].start; + p->physical = mi->bank[i].start; p->virtual = __phys_to_virt(p->physical); - p->length = meminfo.bank[i].size; + p->length = mi->bank[i].size; p->domain = DOMAIN_KERNEL; p->prot_read = 0; p->prot_write = 1; @@ -414,7 +414,7 @@ void __init pagetable_init(void) * The mem_map array can get very big. Mark the end of the valid mem_map * banks with PG_skip, and setup the address validity bitmap. */ -void __init create_memmap_holes(void) +void __init create_memmap_holes(struct meminfo *mi) { unsigned int start_pfn, end_pfn = -1; struct page *pg = NULL; @@ -423,11 +423,11 @@ void __init create_memmap_holes(void) #define PFN(x) (((x) - PHYS_OFFSET) >> PAGE_SHIFT) #define free_bootmem(s,sz) free_bootmem(((s)<<PAGE_SHIFT)+PHYS_OFFSET, (sz)<<PAGE_SHIFT) - for (i = 0; i < meminfo.nr_banks; i++) { - if (meminfo.bank[i].size == 0) + for (i = 0; i < mi->nr_banks; i++) { + if (mi->bank[i].size == 0) continue; - start_pfn = PFN(meminfo.bank[i].start); + start_pfn = PFN(mi->bank[i].start); /* * subtle here - if we have a full bank, then @@ -447,9 +447,9 @@ void __init create_memmap_holes(void) pg = NULL; } - end_pfn = PFN(meminfo.bank[i].start + meminfo.bank[i].size); + end_pfn = PFN(mi->bank[i].start + mi->bank[i].size); - if (end_pfn != PFN(meminfo.end)) + if (end_pfn != PFN(mi->end)) pg = mem_map + end_pfn; } diff --git a/arch/arm/mm/mm-ebsa110.c b/arch/arm/mm/mm-ebsa110.c index a1172b1f1..f16c93793 100644 --- a/arch/arm/mm/mm-ebsa110.c +++ b/arch/arm/mm/mm-ebsa110.c @@ -8,6 +8,7 @@ #include <linux/mm.h> #include <linux/init.h> +#include <asm/hardware.h> #include <asm/pgtable.h> #include <asm/page.h> @@ -15,7 +16,7 @@ #define SIZE(x) (sizeof(x) / sizeof(x[0])) -const struct map_desc io_desc[] __initdata = { +struct map_desc io_desc[] __initdata = { { IO_BASE - PGDIR_SIZE, 0xc0000000, PGDIR_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, { IO_BASE , IO_START , IO_SIZE , DOMAIN_IO, 0, 1, 0, 0 } }; diff --git a/arch/arm/mm/mm-rpc.c b/arch/arm/mm/mm-rpc.c index 0490cbdd0..494a61988 100644 --- a/arch/arm/mm/mm-rpc.c +++ b/arch/arm/mm/mm-rpc.c @@ -18,7 +18,7 @@ struct map_desc io_desc[] __initdata = { /* VRAM */ - { SCREEN2_BASE, SCREEN_START, 2*1048576, DOMAIN_IO, 0, 1, 0, 0 }, + { SCREEN_BASE, SCREEN_START, 2*1048576, DOMAIN_IO, 0, 1, 0, 0 }, /* IO space */ { IO_BASE, IO_START, IO_SIZE , DOMAIN_IO, 0, 1, 0, 0 }, /* EASI space */ diff --git a/arch/arm/mm/mm-sa1100.c b/arch/arm/mm/mm-sa1100.c index 1cb1a3b58..5674dbe37 100644 --- a/arch/arm/mm/mm-sa1100.c +++ b/arch/arm/mm/mm-sa1100.c @@ -9,6 +9,10 @@ * 1999/12/04 Nicolas Pitre <nico@cam.org> * Converted memory definition for struct meminfo initialisations. * Memory is listed physically now. + * + * 2000/04/07 Nicolas Pitre <nico@cam.org> + * Reworked for real-time selection of memory definitions + * */ #include <linux/config.h> @@ -23,79 +27,109 @@ #define SIZE(x) (sizeof(x) / sizeof(x[0])) -/* - * These are the RAM memory mappings for SA1100 implementations. - * Note that LART is a special case - it doesn't use physical - * address line A23 on the DRAM, so we effectively have 4 * 8MB - * in two banks. - */ -struct mem_desc { - unsigned long phys_start; - unsigned long length; -} mem_desc[] __initdata = { -#if defined(CONFIG_SA1100_BRUTUS) - { 0xc0000000, 0x00400000 }, /* 4MB */ - { 0xc8000000, 0x00400000 }, /* 4MB */ - { 0xd0000000, 0x00400000 }, /* 4MB */ - { 0xd8000000, 0x00400000 } /* 4MB */ -#elif defined(CONFIG_SA1100_EMPEG) - { 0xc0000000, 0x00400000 }, /* 4MB */ - { 0xc8000000, 0x00400000 } /* 4MB */ -#elif defined(CONFIG_SA1100_LART) - { 0xc0000000, 0x00800000 }, /* 8MB */ - { 0xc1000000, 0x00800000 }, /* 8MB */ - { 0xc8000000, 0x00800000 }, /* 8MB */ - { 0xc9000000, 0x00800000 } /* 8MB */ -#elif defined(CONFIG_SA1100_VICTOR) - { 0xc0000000, 0x00400000 } /* 4MB */ -#elif defined(CONFIG_SA1100_THINCLIENT) - { 0xc0000000, 0x01000000 } /* 16MB */ -#elif defined(CONFIG_SA1100_TIFON) - { 0xc0000000, 0x01000000 }, /* 16MB */ - { 0xc8000000, 0x01000000 } /* 16MB */ -#else -#error missing memory configuration +#define SA1100_STD_IO_MAPPING \ + /* virtual physical length domain r w c b */ \ + { 0xe0000000, 0x20000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA0 IO */ \ + { 0xe4000000, 0x30000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA1 IO */ \ + { 0xe8000000, 0x28000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA0 attr */ \ + { 0xec000000, 0x38000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA1 attr */ \ + { 0xf0000000, 0x2c000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA0 mem */ \ + { 0xf4000000, 0x3c000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA1 mem */ \ + { 0xf8000000, 0x80000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCM */ \ + { 0xfa000000, 0x90000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* SCM */ \ + { 0xfc000000, 0xa0000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* MER */ \ + { 0xfe000000, 0xb0000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 } /* LCD + DMA */ + + +static struct map_desc assabet_io_desc[] __initdata = { +#ifdef CONFIG_SA1100_ASSABET + { 0xd0000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */ + { 0xdc000000, 0x12000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* Board Control Register */ + SA1100_STD_IO_MAPPING #endif }; -unsigned int __initdata mem_desc_size = SIZE(mem_desc); +static struct map_desc bitsy_io_desc[] __initdata = { +#ifdef CONFIG_SA1100_BITSY + { 0xd0000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */ + SA1100_STD_IO_MAPPING +#endif +}; +static struct map_desc empeg_io_desc[] __initdata = { +#ifdef CONFIG_SA1100_EMPEG + { EMPEG_FLASHBASE, 0x00000000, 0x00200000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash */ + SA1100_STD_IO_MAPPING +#endif +}; -struct map_desc io_desc[] __initdata = { - /* virtual physical length domain r w c b */ -#if defined(CONFIG_SA1100_VICTOR) - { 0xd0000000, 0x00000000, 0x00200000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash */ -#elif defined(CONFIG_SA1100_EMPEG) - { EMPEG_FLASHBASE, 0x00000000, 0x00200000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash */ -#elif defined(CONFIG_SA1100_THINCLIENT) +static struct map_desc thinclient_io_desc[] __initdata = { +#ifdef CONFIG_SA1100_THINCLIENT #if 1 - /* ThinClient: only one of those... */ -// { 0xd0000000, 0x00000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 when JP1 2-4 */ - { 0xd0000000, 0x08000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 when JP1 3-4 */ + /* ThinClient: only one of those... */ +// { 0xd0000000, 0x00000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 when JP1 2-4 */ + { 0xd0000000, 0x08000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 when JP1 3-4 */ #else - /* GraphicsClient: */ - { 0xd0000000, 0x08000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 */ - { 0xd0800000, 0x18000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 3 */ + /* GraphicsClient: */ + { 0xd0000000, 0x08000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 */ + { 0xd0800000, 0x18000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 3 */ +#endif + { 0xdc000000, 0x10000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* CPLD */ + SA1100_STD_IO_MAPPING #endif -#elif defined(CONFIG_SA1100_TIFON) - { 0xd0000000, 0x00000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 */ - { 0xd0800000, 0x08000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 2 */ +}; + +static struct map_desc tifon_io_desc[] __initdata = { +#ifdef CONFIG_SA1100_TIFON + { 0xd0000000, 0x00000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 */ + { 0xd0800000, 0x08000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 2 */ + SA1100_STD_IO_MAPPING #endif -#if defined( CONFIG_SA1101 ) - { 0xdc000000, SA1101_BASE, 0x00400000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA1101 */ -#elif defined( CONFIG_SA1100_THINCLIENT ) - { 0xdc000000, 0x10000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* CPLD */ +}; + +static struct map_desc victor_io_desc[] __initdata = { +#ifdef CONFIG_SA1100_VICTOR + { 0xd0000000, 0x00000000, 0x00200000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash */ + SA1100_STD_IO_MAPPING #endif - { 0xe0000000, 0x20000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA0 IO */ - { 0xe4000000, 0x30000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA1 IO */ - { 0xe8000000, 0x28000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA0 attr */ - { 0xec000000, 0x38000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA1 attr */ - { 0xf0000000, 0x2c000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA0 mem */ - { 0xf4000000, 0x3c000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA1 mem */ - { 0xf8000000, 0x80000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCM */ - { 0xfa000000, 0x90000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* SCM */ - { 0xfc000000, 0xa0000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* MER */ - { 0xfe000000, 0xb0000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 } /* LCD + DMA */ }; -unsigned int __initdata io_desc_size = SIZE(io_desc); + +static struct map_desc default_io_desc[] __initdata = { + SA1100_STD_IO_MAPPING +}; + + +/* + * Here it would be wiser to simply assign a pointer to the appropriate + * list, but io_desc is already declared as an array in "map.h". + */ +struct map_desc io_desc[20] __initdata = { { 0, }, }; +unsigned int io_desc_size; + +void __init select_sa1100_io_desc(void) +{ + if( machine_is_assabet() ) { + memcpy( io_desc, assabet_io_desc, sizeof(assabet_io_desc) ); + io_desc_size = SIZE(assabet_io_desc); + } else if( machine_is_bitsy() ) { + memcpy( io_desc, bitsy_io_desc, sizeof(bitsy_io_desc) ); + io_desc_size = SIZE(bitsy_io_desc); + } else if( machine_is_empeg() ) { + memcpy( io_desc, empeg_io_desc, sizeof(empeg_io_desc) ); + io_desc_size = SIZE(empeg_io_desc); + } else if( machine_is_thinclient() ) { + memcpy( io_desc, thinclient_io_desc, sizeof(thinclient_io_desc) ); + io_desc_size = SIZE(thinclient_io_desc); + } else if( machine_is_tifon() ) { + memcpy( io_desc, tifon_io_desc, sizeof(tifon_io_desc) ); + io_desc_size = SIZE(tifon_io_desc); + } else if( machine_is_victor() ) { + memcpy( io_desc, victor_io_desc, sizeof(victor_io_desc) ); + io_desc_size = SIZE(victor_io_desc); + } else { + memcpy( io_desc, default_io_desc, sizeof(default_io_desc) ); + io_desc_size = SIZE(default_io_desc); + } +} + diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S index 13c1f2773..9ae5fb9d6 100644 --- a/arch/arm/mm/proc-sa110.S +++ b/arch/arm/mm/proc-sa110.S @@ -4,7 +4,9 @@ * (C) 1997-2000 Russell King * * These are the low level assembler for performing cache and TLB - * functions on the StrongARM-110 and StrongARM-1100 + * functions on the StrongARM-110, StrongARM-1100 and StrongARM-1110. + * + * Note that SA1100 and SA1110 share everything but their name and CPU ID. */ #include <linux/linkage.h> #include <asm/assembler.h> @@ -420,13 +422,12 @@ ENTRY(cpu_sa1100_proc_init) mov pc, lr ENTRY(cpu_sa110_proc_fin) -ENTRY(cpu_sa1100_proc_fin) stmfd sp!, {r1, lr} mrs r0, cpsr orr r0, r0, #F_BIT | I_BIT msr cpsr, r0 bl cpu_sa110_flush_cache_all @ clean caches - mov r0, #0 +1: mov r0, #0 mcr p15, 0, r0, c15, c2, 2 @ Disable clock switching mrc p15, 0, r0, c1, c0, 0 bic r0, r0, #0x1000 @ ...i............ @@ -434,8 +435,17 @@ ENTRY(cpu_sa1100_proc_fin) mcr p15, 0, r0, c1, c0, 0 @ disable caches ldmfd sp!, {r1, pc} +ENTRY(cpu_sa1100_proc_fin) + stmfd sp!, {r1, lr} + mrs r0, cpsr + orr r0, r0, #F_BIT | I_BIT + msr cpsr, r0 + bl cpu_sa1100_flush_cache_all @ clean caches + b 1b + + .align 5 -idle: mcr p15, 0, r0, c15, c8, 2 @ Wait for interrupt +idle: mcr p15, 0, r0, c15, c8, 2 @ Wait for interrupt, cache aligned mov r0, r0 @ safety mov pc, lr /* @@ -483,16 +493,14 @@ ENTRY(cpu_sa1100_reset) bic ip, ip, #0x1100 @ ...i...s........ mcr p15, 0, ip, c1, c0, 0 @ ctrl register mov pc, r0 -/* - * Purpose : Function pointers used to access above functions - all calls - * come through these - */ + cpu_manu_name: .asciz "Intel" -ENTRY(cpu_sa110_name) - .asciz "StrongARM-110" -ENTRY(cpu_sa1100_name) +cpu_sa110_name: .asciz "StrongARM-110" +cpu_sa1100_name: .asciz "StrongARM-1100" +cpu_sa1110_name: + .asciz "StrongARM-1110" .align .section ".text.init", #alloc, #execinstr @@ -511,6 +519,13 @@ __sa110_setup: mov r0, #0 orr r0, r0, #0x1100 @ ...I...S........ mov pc, lr + .text + +/* + * Purpose : Function pointers used to access above functions - all calls + * come through these + */ + .type sa110_processor_functions, #object ENTRY(sa110_processor_functions) .word cpu_sa110_data_abort @@ -543,6 +558,9 @@ cpu_sa110_info: .size cpu_sa110_info, . - cpu_sa110_info +/* + * SA1100 and SA1110 share the same function calls + */ .type sa1100_processor_functions, #object ENTRY(sa1100_processor_functions) .word cpu_sa1100_data_abort @@ -573,6 +591,12 @@ cpu_sa1100_info: .long cpu_sa1100_name .size cpu_sa1100_info, . - cpu_sa1100_info +cpu_sa1110_info: + .long cpu_manu_name + .long cpu_sa1110_name + .size cpu_sa1110_info, . - cpu_sa1110_info + + .type cpu_arch_name, #object cpu_arch_name: .asciz "armv4" .size cpu_arch_name, . - cpu_arch_name @@ -610,4 +634,17 @@ __sa1100_proc_info: .long sa1100_processor_functions .size __sa1100_proc_info, . - __sa1100_proc_info + .type __sa1110_proc_info,#object +__sa1110_proc_info: + .long 0x6901b110 + .long 0xfffffff0 + .long 0x00000c02 + b __sa110_setup + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT + .long cpu_sa1110_info + .long sa1100_processor_functions + .size __sa1110_proc_info, . - __sa1110_proc_info + diff --git a/arch/i386/config.in b/arch/i386/config.in index 664b77800..589c34730 100644 --- a/arch/i386/config.in +++ b/arch/i386/config.in @@ -20,48 +20,54 @@ comment 'Processor type and features' choice 'Processor family' \ "386 CONFIG_M386 \ 486/Cx486 CONFIG_M486 \ - 586/K5/5x86/6x86 CONFIG_M586 \ + 586/K5/5x86/6x86/6x86MX CONFIG_M586 \ Pentium/TSC CONFIG_M586TSC \ - PPro/6x86MX CONFIG_M686 \ + PPro CONFIG_M686 \ K6/II/III CONFIG_MK6 \ Athlon CONFIG_MK7" PPro # # Define implied options from the CPU selection here # -if [ "$CONFIG_M386" != "y" ]; then +if [ "$CONFIG_M386" = "y" ]; then + define_int CONFIG_X86_L1_CACHE_BYTES 16 +else define_bool CONFIG_X86_WP_WORKS_OK y define_bool CONFIG_X86_INVLPG y define_bool CONFIG_X86_CMPXCHG y define_bool CONFIG_X86_BSWAP y define_bool CONFIG_X86_POPAD_OK y fi -if [ "$CONFIG_M386" = "y" -o "$CONFIG_M486" = "y" ]; then - define_int CONFIG_X86_L1_CACHE_BYTES 16 -else - define_int CONFIG_X86_L1_CACHE_BYTES 32 +if [ "$CONFIG_M486" = "y" ]; then + define_int CONFIG_X86_L1_CACHE_BYTES 16 + define_bool CONFIG_X86_USE_STRING_486 y + define_bool CONFIG_X86_ALIGNMENT_16 y fi -if [ "$CONFIG_M486" = "y" -o "$CONFIG_M586" = "y" ]; then +if [ "$CONFIG_M586" = "y" ]; then + define_int CONFIG_X86_L1_CACHE_BYTES 32 define_bool CONFIG_X86_USE_STRING_486 y define_bool CONFIG_X86_ALIGNMENT_16 y fi if [ "$CONFIG_M586TSC" = "y" ]; then + define_int CONFIG_X86_L1_CACHE_BYTES 32 define_bool CONFIG_X86_USE_STRING_486 y define_bool CONFIG_X86_ALIGNMENT_16 y define_bool CONFIG_X86_TSC y fi -if [ "$CONFIG_MK6" = "y" ]; then - define_bool CONFIG_X86_ALIGNMENT_16 y - define_bool CONFIG_X86_TSC y - define_bool CONFIG_X86_USE_3DNOW y - define_bool CONFIG_X86_USE_PPRO_CHECKSUM y -fi if [ "$CONFIG_M686" = "y" ]; then + define_int CONFIG_X86_L1_CACHE_BYTES 32 define_bool CONFIG_X86_TSC y define_bool CONFIG_X86_GOOD_APIC y define_bool CONFIG_X86_PGE y define_bool CONFIG_X86_USE_PPRO_CHECKSUM y fi +if [ "$CONFIG_MK6" = "y" ]; then + define_int CONFIG_X86_L1_CACHE_BYTES 32 + define_bool CONFIG_X86_ALIGNMENT_16 y + define_bool CONFIG_X86_TSC y + define_bool CONFIG_X86_USE_PPRO_CHECKSUM y +fi if [ "$CONFIG_MK7" = "y" ]; then + define_int CONFIG_X86_L1_CACHE_BYTES 64 define_bool CONFIG_X86_TSC y define_bool CONFIG_X86_GOOD_APIC y define_bool CONFIG_X86_USE_3DNOW y diff --git a/arch/i386/defconfig b/arch/i386/defconfig index 80f68ec31..3a8d743f7 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig @@ -107,6 +107,7 @@ CONFIG_BLK_DEV_FD=y # # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_LVM is not set # CONFIG_BLK_DEV_MD is not set # CONFIG_MD_LINEAR is not set # CONFIG_MD_STRIPED is not set @@ -189,8 +190,8 @@ CONFIG_IDEPCI_SHARE_IRQ=y # CONFIG_IDEDMA_PCI_EXPERIMENTAL is not set # CONFIG_IDEDMA_PCI_WIP is not set # CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set -# CONFIG_BLK_DEV_AEC6210 is not set -# CONFIG_AEC6210_TUNING is not set +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_AEC62XX_TUNING is not set # CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_WDC_ALI15X3 is not set # CONFIG_BLK_DEV_AMD7409 is not set @@ -214,6 +215,7 @@ CONFIG_IDEPCI_SHARE_IRQ=y # CONFIG_BLK_DEV_SIS5513 is not set # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_VIA82CXXX_TUNING is not set # CONFIG_IDE_CHIPSETS is not set # CONFIG_IDEDMA_AUTO is not set CONFIG_BLK_DEV_IDE_MODES=y @@ -385,7 +387,10 @@ CONFIG_PCMCIA_PCNET=y # CONFIG_PCMCIA_XIRC2PS is not set # CONFIG_ARCNET_COM20020_CS is not set # CONFIG_PCMCIA_IBMTR is not set -# CONFIG_PCMCIA_3C575 is not set + +# +# 3Com 3c575 moved to Ethernet 10/100 menu +# # CONFIG_PCMCIA_XIRTULIP is not set CONFIG_NET_PCMCIA_RADIO=y CONFIG_PCMCIA_RAYCS=y diff --git a/arch/i386/kernel/acpi.c b/arch/i386/kernel/acpi.c index aa09400fc..e63a45e66 100644 --- a/arch/i386/kernel/acpi.c +++ b/arch/i386/kernel/acpi.c @@ -583,6 +583,8 @@ static int __init acpi_find_tables(void) dt = acpi_map_table(facp->dsdt); if (acpi_init_table(&acpi_dsdt, dt, 1)) acpi_unmap_table(dt); + + break; } else { acpi_unmap_table(dt); @@ -1127,6 +1129,7 @@ static int acpi_enter_sx(acpi_sstate_t state) // finished sleeping, update system time acpi_update_clock(); acpi_enter_dx(ACPI_D0); + acpi_sleep_state = ACPI_S0; return 0; } diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index a5f72548f..d4c35fdf0 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c @@ -4,7 +4,9 @@ * (c) 1999, 2000 Ingo Molnar <mingo@redhat.com> * * Fixes - * Maciej W. Rozycki : Bits for genuine 82489DX timers + * Maciej W. Rozycki : Bits for genuine 82489DX APICs; + * thanks to Eric Gilmore for + * testing these extensively */ #include <linux/config.h> @@ -44,32 +46,96 @@ int get_maxlvt(void) return maxlvt; } -void disable_local_APIC (void) +static void clear_local_APIC(void) { - unsigned long value; - int maxlvt; + int maxlvt; + unsigned long v; + + maxlvt = get_maxlvt(); /* - * Disable APIC + * Careful: we have to set masks only first to deassert + * any level-triggered sources. */ - value = apic_read(APIC_SPIV); - value &= ~(1<<8); - apic_write(APIC_SPIV,value); + v = apic_read(APIC_LVTT); + apic_write_around(APIC_LVTT, v | APIC_LVT_MASKED); + v = apic_read(APIC_LVT0); + apic_write_around(APIC_LVT0, v | APIC_LVT_MASKED); + v = apic_read(APIC_LVT1); + apic_write_around(APIC_LVT1, v | APIC_LVT_MASKED); + if (maxlvt >= 3) { + v = apic_read(APIC_LVTERR); + apic_write_around(APIC_LVTERR, v | APIC_LVT_MASKED); + } + if (maxlvt >= 4) { + v = apic_read(APIC_LVTPC); + apic_write_around(APIC_LVTPC, v | APIC_LVT_MASKED); + } /* * Clean APIC state for other OSs: */ - value = apic_read(APIC_SPIV); - value &= ~(1<<8); - apic_write(APIC_SPIV,value); - maxlvt = get_maxlvt(); - apic_write_around(APIC_LVTT, 0x00010000); - apic_write_around(APIC_LVT0, 0x00010000); - apic_write_around(APIC_LVT1, 0x00010000); + apic_write_around(APIC_LVTT, APIC_LVT_MASKED); + apic_write_around(APIC_LVT0, APIC_LVT_MASKED); + apic_write_around(APIC_LVT1, APIC_LVT_MASKED); if (maxlvt >= 3) - apic_write_around(APIC_LVTERR, 0x00010000); + apic_write_around(APIC_LVTERR, APIC_LVT_MASKED); if (maxlvt >= 4) - apic_write_around(APIC_LVTPC, 0x00010000); + apic_write_around(APIC_LVTPC, APIC_LVT_MASKED); +} + +void __init connect_bsp_APIC(void) +{ + if (pic_mode) { + /* + * Do not trust the local APIC being empty at bootup. + */ + clear_local_APIC(); + /* + * PIC mode, enable symmetric IO mode in the IMCR, + * i.e. connect BSP's local APIC to INT and NMI lines. + */ + printk("leaving PIC mode, enabling symmetric IO mode.\n"); + outb(0x70, 0x22); + outb(0x01, 0x23); + } +} + +void disconnect_bsp_APIC(void) +{ + if (pic_mode) { + /* + * Put the board back into PIC mode (has an effect + * only on certain older boards). Note that APIC + * interrupts, including IPIs, won't work beyond + * this point! The only exception are INIT IPIs. + */ + printk("disabling symmetric IO mode, entering PIC mode.\n"); + outb(0x70, 0x22); + outb(0x00, 0x23); + } +} + +void disable_local_APIC(void) +{ + unsigned long value; + + clear_local_APIC(); + + /* + * Disable APIC (implies clearing of registers + * for 82489DX!). + */ + value = apic_read(APIC_SPIV); + value &= ~(1<<8); + apic_write_around(APIC_SPIV, value); +} + +void __init sync_Arb_IDs(void) +{ + Dprintk("Synchronizing Arb IDs.\n"); + apic_write_around(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG + | APIC_DM_INIT); } extern void __error_in_apic_c (void); @@ -78,6 +144,9 @@ void __init setup_local_APIC (void) { unsigned long value, ver, maxlvt; + value = apic_read(APIC_LVR); + ver = GET_APIC_VERSION(value); + if ((SPURIOUS_APIC_VECTOR & 0x0f) != 0x0f) __error_in_apic_c(); @@ -87,11 +156,12 @@ void __init setup_local_APIC (void) if (!test_bit(GET_APIC_ID(apic_read(APIC_ID)), &phys_cpu_present_map)) BUG(); - value = apic_read(APIC_SPIV); + value = apic_read(APIC_SPIV); + value &= ~APIC_VECTOR_MASK; /* * Enable APIC */ - value |= (1<<8); + value |= (1<<8); /* * Some unknown Intel IO/APIC (or APIC) errata is biting us with @@ -108,7 +178,7 @@ void __init setup_local_APIC (void) */ #if 0 /* Enable focus processor (bit==0) */ - value &= ~(1<<9); + value &= ~(1<<9); #else /* Disable focus processor (bit==1) */ value |= (1<<9); @@ -117,7 +187,7 @@ void __init setup_local_APIC (void) * Set spurious IRQ vector */ value |= SPURIOUS_APIC_VECTOR; - apic_write(APIC_SPIV,value); + apic_write_around(APIC_SPIV, value); /* * Set up LVT0, LVT1: @@ -126,48 +196,44 @@ void __init setup_local_APIC (void) * strictly necessery in pure symmetric-IO mode, but sometimes * we delegate interrupts to the 8259A. */ - if (!smp_processor_id()) { - value = 0x00000700; + /* + * TODO: set up through-local-APIC from through-I/O-APIC? --macro + */ + value = apic_read(APIC_LVT0) & APIC_LVT_MASKED; + if (!smp_processor_id() && (pic_mode || !value)) { + value = APIC_DM_EXTINT; printk("enabled ExtINT on CPU#%d\n", smp_processor_id()); } else { - value = 0x00010700; + value = APIC_DM_EXTINT | APIC_LVT_MASKED; printk("masked ExtINT on CPU#%d\n", smp_processor_id()); } - apic_write_around(APIC_LVT0,value); + apic_write_around(APIC_LVT0, value); /* * only the BP should see the LINT1 NMI signal, obviously. */ if (!smp_processor_id()) - value = 0x00000400; // unmask NMI + value = APIC_DM_NMI; else - value = 0x00010400; // mask NMI - apic_write_around(APIC_LVT1,value); + value = APIC_DM_NMI | APIC_LVT_MASKED; + if (!APIC_INTEGRATED(ver)) /* 82489DX */ + value |= APIC_LVT_LEVEL_TRIGGER; + apic_write_around(APIC_LVT1, value); - value = apic_read(APIC_LVR); - ver = GET_APIC_VERSION(value); if (APIC_INTEGRATED(ver)) { /* !82489DX */ maxlvt = get_maxlvt(); - /* - * Due to the Pentium erratum 3AP. - */ - if (maxlvt > 3) { - apic_readaround(APIC_SPIV); // not strictly necessery + if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */ apic_write(APIC_ESR, 0); - } value = apic_read(APIC_ESR); printk("ESR value before enabling vector: %08lx\n", value); - value = apic_read(APIC_LVTERR); value = ERROR_APIC_VECTOR; // enables sending errors - apic_write(APIC_LVTERR,value); + apic_write_around(APIC_LVTERR, value); /* * spec says clear errors after enabling vector. */ - if (maxlvt != 3) { - apic_readaround(APIC_SPIV); + if (maxlvt > 3) apic_write(APIC_ESR, 0); - } value = apic_read(APIC_ESR); printk("ESR value after enabling vector: %08lx\n", value); } else @@ -177,22 +243,23 @@ void __init setup_local_APIC (void) * Set Task Priority to 'accept all'. We never change this * later on. */ - value = apic_read(APIC_TASKPRI); - value &= ~APIC_TPRI_MASK; - apic_write(APIC_TASKPRI,value); + value = apic_read(APIC_TASKPRI); + value &= ~APIC_TPRI_MASK; + apic_write_around(APIC_TASKPRI, value); /* * Set up the logical destination ID and put the * APIC into flat delivery mode. */ - value = apic_read(APIC_LDR); + value = apic_read(APIC_LDR); value &= ~APIC_LDR_MASK; value |= (1<<(smp_processor_id()+24)); - apic_write(APIC_LDR,value); + apic_write_around(APIC_LDR, value); - value = apic_read(APIC_DFR); - value |= SET_APIC_DFR(0xf); - apic_write(APIC_DFR, value); + /* + * Must be "all ones" explicitly for 82489DX. + */ + apic_write_around(APIC_DFR, 0xffffffff); } void __init init_apic_mappings(void) @@ -214,6 +281,13 @@ void __init init_apic_mappings(void) set_fixmap_nocache(FIX_APIC_BASE, apic_phys); Dprintk("mapped APIC to %08lx (%08lx)\n", APIC_BASE, apic_phys); + /* + * Fetch the APIC ID of the BSP in case we have a + * default configuration (or the MP table is broken). + */ + if (boot_cpu_id == -1U) + boot_cpu_id = GET_APIC_ID(apic_read(APIC_ID)); + #ifdef CONFIG_X86_IO_APIC { unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0; @@ -285,7 +359,7 @@ void __init wait_8254_wraparound(void) * chipset timer can cause. */ - } while (delta<300); + } while (delta < 300); } /* @@ -305,21 +379,19 @@ void __setup_APIC_LVTT(unsigned int clocks) { unsigned int lvtt1_value, tmp_value; - tmp_value = apic_read(APIC_LVTT); lvtt1_value = SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV) | APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR; - apic_write(APIC_LVTT, lvtt1_value); + apic_write_around(APIC_LVTT, lvtt1_value); /* * Divide PICLK by 16 */ tmp_value = apic_read(APIC_TDCR); - apic_write(APIC_TDCR, (tmp_value + apic_write_around(APIC_TDCR, (tmp_value & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE)) | APIC_TDR_DIV_16); - tmp_value = apic_read(APIC_TMICT); - apic_write(APIC_TMICT, clocks/APIC_DIVISOR); + apic_write_around(APIC_TMICT, clocks/APIC_DIVISOR); } void setup_APIC_timer(void * data) @@ -353,6 +425,12 @@ void setup_APIC_timer(void * data) t0 = apic_read(APIC_TMCCT)*APIC_DIVISOR; do { + /* + * It looks like the 82489DX cannot handle + * consecutive reads of the TMCCT register well; + * this dummy read prevents it from a lockup. + */ + apic_read(APIC_SPIV); t1 = apic_read(APIC_TMCCT)*APIC_DIVISOR; delta = (int)(t0 - t1 - slice*(smp_processor_id()+1)); } while (delta < 0); @@ -490,6 +568,41 @@ int setup_profiling_timer(unsigned int multiplier) #undef APIC_DIVISOR +#ifdef CONFIG_SMP +static inline void handle_smp_time (int user, int cpu) +{ + int system = !user; + struct task_struct * p = current; + /* + * After doing the above, we need to make like + * a normal interrupt - otherwise timer interrupts + * ignore the global interrupt lock, which is the + * WrongThing (tm) to do. + */ + + irq_enter(cpu, 0); + update_one_process(p, 1, user, system, cpu); + if (p->pid) { + p->counter -= 1; + if (p->counter <= 0) { + p->counter = 0; + p->need_resched = 1; + } + if (p->priority < DEF_PRIORITY) { + kstat.cpu_nice += user; + kstat.per_cpu_nice[cpu] += user; + } else { + kstat.cpu_user += user; + kstat.per_cpu_user[cpu] += user; + } + kstat.cpu_system += system; + kstat.per_cpu_system[cpu] += system; + + } + irq_exit(cpu, 0); +} +#endif + /* * Local timer interrupt handler. It does both profiling and * process statistics/rescheduling. @@ -502,7 +615,6 @@ int setup_profiling_timer(unsigned int multiplier) inline void smp_local_timer_interrupt(struct pt_regs * regs) { - int user = (user_mode(regs) != 0); int cpu = smp_processor_id(); /* @@ -511,13 +623,8 @@ inline void smp_local_timer_interrupt(struct pt_regs * regs) * updated with atomic operations). This is especially * useful with a profiling multiplier != 1 */ - if (!user) - x86_do_profile(regs->eip); if (--prof_counter[cpu] <= 0) { - int system = 1 - user; - struct task_struct * p = current; - /* * The multiplier may have changed since the last time we got * to this point as a result of the user writing to @@ -532,33 +639,9 @@ inline void smp_local_timer_interrupt(struct pt_regs * regs) prof_old_multiplier[cpu] = prof_counter[cpu]; } - /* - * After doing the above, we need to make like - * a normal interrupt - otherwise timer interrupts - * ignore the global interrupt lock, which is the - * WrongThing (tm) to do. - */ - - irq_enter(cpu, 0); - update_one_process(p, 1, user, system, cpu); - if (p->pid) { - p->counter -= 1; - if (p->counter <= 0) { - p->counter = 0; - p->need_resched = 1; - } - if (p->priority < DEF_PRIORITY) { - kstat.cpu_nice += user; - kstat.per_cpu_nice[cpu] += user; - } else { - kstat.cpu_user += user; - kstat.per_cpu_user[cpu] += user; - } - kstat.cpu_system += system; - kstat.per_cpu_system[cpu] += system; - - } - irq_exit(cpu, 0); +#ifdef CONFIG_SMP + handle_smp_time(user_mode(regs), cpu); +#endif } /* @@ -603,7 +686,17 @@ void smp_apic_timer_interrupt(struct pt_regs * regs) */ asmlinkage void smp_spurious_interrupt(void) { - ack_APIC_irq(); + unsigned long v; + + /* + * Check if this really is a spurious interrupt and ACK it + * if it is a vectored one. Just in case... + * Spurious interrupts should not be ACKed. + */ + v = apic_read(APIC_ISR + ((SPURIOUS_APIC_VECTOR & ~0x1f) >> 1)); + if (v & (1 << (SPURIOUS_APIC_VECTOR & 0x1f))) + ack_APIC_irq(); + /* see sw-dev-man vol 3, chapter 7.4.13.5 */ printk("spurious APIC interrupt on CPU#%d, should never happen.\n", smp_processor_id()); diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index b488d97a8..50887c15c 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S @@ -40,6 +40,7 @@ * "current" is in register %ebx during any slow entries. */ +#include <linux/config.h> #include <linux/sys.h> #include <linux/linkage.h> #include <asm/segment.h> @@ -201,7 +202,7 @@ ENTRY(system_call) call *SYMBOL_NAME(sys_call_table)(,%eax,4) movl %eax,EAX(%esp) # save the return value ENTRY(ret_from_sys_call) -#ifdef __SMP__ +#ifdef CONFIG_SMP movl processor(%ebx),%eax shll $5,%eax movl SYMBOL_NAME(softirq_state)(,%eax),%ecx @@ -256,7 +257,7 @@ badsys: ALIGN ret_from_exception: -#ifdef __SMP__ +#ifdef CONFIG_SMP GET_CURRENT(%ebx) movl processor(%ebx),%eax shll $5,%eax diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S index ee759f2bc..51ab1c8ca 100644 --- a/arch/i386/kernel/head.S +++ b/arch/i386/kernel/head.S @@ -51,7 +51,7 @@ startup_32: movl %eax,%es movl %eax,%fs movl %eax,%gs -#ifdef __SMP__ +#ifdef CONFIG_SMP orw %bx,%bx jz 1f /* @@ -105,14 +105,14 @@ startup_32: /* Set up the stack pointer */ lss stack_start,%esp -#ifdef __SMP__ +#ifdef CONFIG_SMP orw %bx,%bx jz 1f /* Initial CPU cleans BSS */ pushl $0 popfl jmp checkCPUtype 1: -#endif __SMP__ +#endif CONFIG_SMP /* * Clear BSS first so that there are no surprises... */ @@ -159,7 +159,7 @@ startup_32: rep movsl 1: -#ifdef __SMP__ +#ifdef CONFIG_SMP checkCPUtype: #endif @@ -234,7 +234,7 @@ is386: pushl %ecx # restore original EFLAGS orl $2,%eax # set MP 2: movl %eax,%cr0 call check_x87 -#ifdef __SMP__ +#ifdef CONFIG_SMP incb ready #endif lgdt gdt_descr @@ -245,7 +245,7 @@ is386: pushl %ecx # restore original EFLAGS movl %eax,%es movl %eax,%fs movl %eax,%gs -#ifdef __SMP__ +#ifdef CONFIG_SMP movl $(__KERNEL_DS), %eax movl %eax,%ss # Reload the stack pointer (segment only) #else @@ -254,7 +254,7 @@ is386: pushl %ecx # restore original EFLAGS xorl %eax,%eax lldt %ax cld # gcc2 wants the direction flag cleared at all times -#ifdef __SMP__ +#ifdef CONFIG_SMP movb ready, %cl cmpb $1,%cl je 1f # the first CPU calls start_kernel @@ -268,7 +268,7 @@ L6: jmp L6 # main should never return here, but # just in case, we know what happens. -#ifdef __SMP__ +#ifdef CONFIG_SMP ready: .byte 0 #endif diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c index 5327f24a4..584caa9c1 100644 --- a/arch/i386/kernel/i386_ksyms.c +++ b/arch/i386/kernel/i386_ksyms.c @@ -27,6 +27,11 @@ extern void dump_thread(struct pt_regs *, struct user *); extern int dump_fpu(elf_fpregset_t *); extern spinlock_t rtc_lock; +#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE) +extern void machine_real_restart(unsigned char *, int); +EXPORT_SYMBOL(machine_real_restart); +#endif + #ifdef CONFIG_SMP extern void FASTCALL( __write_lock_failed(rwlock_t *rw)); extern void FASTCALL( __read_lock_failed(rwlock_t *rw)); @@ -68,7 +73,6 @@ EXPORT_SYMBOL_NOVERS(__down_write_failed); EXPORT_SYMBOL_NOVERS(__down_read_failed); EXPORT_SYMBOL_NOVERS(__rwsem_wake); /* Networking helper routines. */ -EXPORT_SYMBOL(csum_partial_copy); EXPORT_SYMBOL(csum_partial_copy_generic); /* Delay loops */ EXPORT_SYMBOL(__udelay); @@ -84,7 +88,6 @@ EXPORT_SYMBOL_NOVERS(__put_user_4); EXPORT_SYMBOL(strtok); EXPORT_SYMBOL(strpbrk); -EXPORT_SYMBOL(strstr); EXPORT_SYMBOL(strncpy_from_user); EXPORT_SYMBOL(__strncpy_from_user); diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c index 61571ab59..334a75f88 100644 --- a/arch/i386/kernel/i8259.c +++ b/arch/i386/kernel/i8259.c @@ -415,7 +415,7 @@ void __init init_ISA_irqs (void) for (i = 0; i < NR_IRQS; i++) { irq_desc[i].status = IRQ_DISABLED; irq_desc[i].action = 0; - irq_desc[i].depth = 0; + irq_desc[i].depth = 1; if (i < 16) { /* diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 1d4445669..dfee6e4d5 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -13,7 +13,9 @@ * and Ingo Molnar <mingo@redhat.com> * * Fixes - * Maciej W. Rozycki : Bits for genuine 82489DX APICs + * Maciej W. Rozycki : Bits for genuine 82489DX APICs; + * thanks to Eric Gilmore for + * testing these extensively */ #include <linux/mm.h> @@ -46,9 +48,6 @@ struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES]; /* MP IRQ source entries */ int mp_irq_entries = 0; -/* non-0 if default (table-less) MP configuration */ -int mpc_default_type = 0; - /* * Rough estimation of how many shared IRQs there are, can * be changed anytime. @@ -166,7 +165,7 @@ static void clear_IO_APIC (void) #define MAX_PIRQS 8 int pirq_entries [MAX_PIRQS]; -int pirqs_enabled; +int pirqs_enabled = 0; int skip_ioapic_setup = 0; static int __init ioapic_setup(char *str) @@ -235,7 +234,8 @@ static int __init find_timer_pin(int type) int lbus = mp_irqs[i].mpc_srcbus; if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA || - mp_bus_id_to_type[lbus] == MP_BUS_EISA) && + mp_bus_id_to_type[lbus] == MP_BUS_EISA || + mp_bus_id_to_type[lbus] == MP_BUS_MCA) && (mp_irqs[i].mpc_irqtype == type) && (mp_irqs[i].mpc_srcbusirq == 0x00)) @@ -260,13 +260,15 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pci_pin) if (mp_ioapics[apic].mpc_apicid == mp_irqs[i].mpc_dstapic) break; - if ((apic || IO_APIC_IRQ(mp_irqs[i].mpc_dstirq)) && - (mp_bus_id_to_type[lbus] == MP_BUS_PCI) && + if ((mp_bus_id_to_type[lbus] == MP_BUS_PCI) && !mp_irqs[i].mpc_irqtype && (bus == mp_bus_id_to_pci_bus[mp_irqs[i].mpc_srcbus]) && (slot == ((mp_irqs[i].mpc_srcbusirq >> 2) & 0x1f))) { int irq = pin_2_irq(i,apic,mp_irqs[i].mpc_dstirq); + if (!(apic || IO_APIC_IRQ(irq))) + continue; + if (pci_pin == (mp_irqs[i].mpc_srcbusirq & 3)) return irq; /* @@ -298,15 +300,27 @@ static int __init EISA_ELCR(unsigned int irq) * EISA conforming in the MP table, that means its trigger type must * be read in from the ELCR */ -#define default_EISA_trigger(idx) (EISA_ELCR(mp_irqs[idx].mpc_dstirq)) +#define default_EISA_trigger(idx) (EISA_ELCR(mp_irqs[idx].mpc_srcbusirq)) #define default_EISA_polarity(idx) (0) -/* ISA interrupts are always polarity zero edge triggered, even when - * listed as conforming in the MP table. */ +/* ISA interrupts are always polarity zero edge triggered, + * when listed as conforming in the MP table. */ #define default_ISA_trigger(idx) (0) #define default_ISA_polarity(idx) (0) +/* PCI interrupts are always polarity one level triggered, + * when listed as conforming in the MP table. */ + +#define default_PCI_trigger(idx) (1) +#define default_PCI_polarity(idx) (1) + +/* MCA interrupts are always polarity zero level triggered, + * when listed as conforming in the MP table. */ + +#define default_MCA_trigger(idx) (1) +#define default_MCA_polarity(idx) (0) + static int __init MPBIOS_polarity(int idx) { int bus = mp_irqs[idx].mpc_srcbus; @@ -326,14 +340,19 @@ static int __init MPBIOS_polarity(int idx) polarity = default_ISA_polarity(idx); break; } - case MP_BUS_EISA: + case MP_BUS_EISA: /* EISA pin */ { polarity = default_EISA_polarity(idx); break; } case MP_BUS_PCI: /* PCI pin */ { - polarity = 1; + polarity = default_PCI_polarity(idx); + break; + } + case MP_BUS_MCA: /* MCA pin */ + { + polarity = default_MCA_polarity(idx); break; } default: @@ -385,19 +404,24 @@ static int __init MPBIOS_trigger(int idx) { switch (mp_bus_id_to_type[bus]) { - case MP_BUS_ISA: + case MP_BUS_ISA: /* ISA pin */ { trigger = default_ISA_trigger(idx); break; } - case MP_BUS_EISA: + case MP_BUS_EISA: /* EISA pin */ { trigger = default_EISA_trigger(idx); break; } - case MP_BUS_PCI: /* PCI pin, level */ + case MP_BUS_PCI: /* PCI pin */ { - trigger = 1; + trigger = default_PCI_trigger(idx); + break; + } + case MP_BUS_MCA: /* MCA pin */ + { + trigger = default_MCA_trigger(idx); break; } default: @@ -460,6 +484,7 @@ static int __init pin_2_irq(int idx, int apic, int pin) { case MP_BUS_ISA: /* ISA pin */ case MP_BUS_EISA: + case MP_BUS_MCA: { irq = mp_irqs[idx].mpc_srcbusirq; break; @@ -624,8 +649,8 @@ void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector) disable_8259A_irq(0); - apic_readaround(APIC_LVT0); - apic_write(APIC_LVT0, 0x00010700); // mask LVT0 + /* mask LVT0 */ + apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT); init_8259A(1); @@ -650,8 +675,8 @@ void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector) /* * Add it to the IO-APIC irq-routing table: */ - io_apic_write(0, 0x10+2*pin, *(((int *)&entry)+0)); io_apic_write(0, 0x11+2*pin, *(((int *)&entry)+1)); + io_apic_write(0, 0x10+2*pin, *(((int *)&entry)+0)); enable_8259A_irq(0); } @@ -725,8 +750,8 @@ void __init print_IO_APIC(void) printk(KERN_DEBUG ".... IRQ redirection table:\n"); - printk(KERN_DEBUG " NR Log Phy "); - printk(KERN_DEBUG "Mask Trig IRR Pol Stat Dest Deli Vect: \n"); + printk(KERN_DEBUG " NR Log Phy Mask Trig IRR Pol" + " Stat Dest Deli Vect: \n"); for (i = 0; i <= reg_01.entries; i++) { struct IO_APIC_route_entry entry; @@ -831,13 +856,8 @@ void /*__init*/ print_local_APIC(void * dummy) print_APIC_bitfield(APIC_IRR); if (APIC_INTEGRATED(ver)) { /* !82489DX */ - /* - * Due to the Pentium erratum 3AP. - */ - if (maxlvt > 3) { - apic_readaround(APIC_SPIV); // not strictly necessery + if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */ apic_write(APIC_ESR, 0); - } v = apic_read(APIC_ESR); printk(KERN_DEBUG "... APIC ESR: %08x\n", v); } @@ -879,6 +899,32 @@ void print_all_local_APICs (void) print_local_APIC(NULL); } +void /*__init*/ print_PIC(void) +{ + unsigned int v, flags; + + printk(KERN_DEBUG "\nprinting PIC contents\n"); + + v = inb(0xa1) << 8 | inb(0x21); + printk(KERN_DEBUG "... PIC IMR: %04x\n", v); + + v = inb(0xa0) << 8 | inb(0x20); + printk(KERN_DEBUG "... PIC IRR: %04x\n", v); + + __save_flags(flags); + __cli(); + outb(0x0b,0xa0); + outb(0x0b,0x20); + v = inb(0xa0) << 8 | inb(0x20); + outb(0x0a,0xa0); + outb(0x0a,0x20); + __restore_flags(flags); + printk(KERN_DEBUG "... PIC ISR: %04x\n", v); + + v = inb(0x4d1) << 8 | inb(0x4d0); + printk(KERN_DEBUG "... PIC ELCR: %04x\n", v); +} + static void __init enable_IO_APIC(void) { struct IO_APIC_reg_01 reg_01; @@ -890,16 +936,7 @@ static void __init enable_IO_APIC(void) } if (!pirqs_enabled) for (i = 0; i < MAX_PIRQS; i++) - pirq_entries[i] =- 1; - - if (pic_mode) { - /* - * PIC mode, enable symmetric IO mode in the IMCR. - */ - printk("leaving PIC mode, enabling symmetric IO mode.\n"); - outb(0x70, 0x22); - outb(0x01, 0x23); - } + pirq_entries[i] = -1; /* * The number of IO-APIC IRQ registers (== #pins): @@ -925,15 +962,7 @@ void disable_IO_APIC(void) */ clear_IO_APIC(); - /* - * Put it back into PIC mode (has an effect only on - * certain older boards) - */ - if (pic_mode) { - printk("disabling symmetric IO mode, entering PIC mode.\n"); - outb_p(0x70, 0x22); - outb_p(0x00, 0x23); - } + disconnect_bsp_APIC(); } /* @@ -986,48 +1015,6 @@ static void __init setup_ioapic_ids_from_mpc (void) } } -static void __init construct_default_ISA_mptable(void) -{ - int i, pos = 0; - const int bus_type = (mpc_default_type == 2 || mpc_default_type == 3 || - mpc_default_type == 6) ? MP_BUS_EISA : MP_BUS_ISA; - - for (i = 0; i < 16; i++) { - if (!IO_APIC_IRQ(i)) - continue; - - mp_irqs[pos].mpc_irqtype = mp_INT; - mp_irqs[pos].mpc_irqflag = 0; /* default */ - mp_irqs[pos].mpc_srcbus = 0; - mp_irqs[pos].mpc_srcbusirq = i; - mp_irqs[pos].mpc_dstapic = 0; - mp_irqs[pos].mpc_dstirq = i; - pos++; - } - mp_irq_entries = pos; - mp_bus_id_to_type[0] = bus_type; - - /* - * MP specification 1.4 defines some extra rules for default - * configurations, fix them up here: - */ - switch (mpc_default_type) - { - case 2: - /* - * IRQ0 is not connected: - */ - mp_irqs[0].mpc_irqtype = mp_ExtINT; - break; - default: - /* - * pin 2 is IRQ0: - */ - mp_irqs[0].mpc_dstirq = 2; - } - -} - /* * There is a nasty bug in some older SMP boards, their mptable lies * about the timer IRQ. We do the following to work around the situation: @@ -1041,9 +1028,17 @@ static int __init timer_irq_works(void) unsigned int t1 = jiffies; sti(); - mdelay(40); + /* Let ten ticks pass... */ + mdelay((10 * 1000) / HZ); - if (jiffies-t1>1) + /* + * Expect a few ticks at least, to be sure some possible + * glue logic does not lock up after one or two first + * ticks in a non-ExtINT mode. Also the local APIC + * might have cached one ExtINT interrupt. Finally, at + * least one tick may be lost due to delays. + */ + if (jiffies - t1 > 4) return 1; return 0; @@ -1257,8 +1252,14 @@ static struct hw_interrupt_type lapic_irq_type = { static void enable_NMI_through_LVT0 (void * dummy) { - apic_readaround(APIC_LVT0); - apic_write(APIC_LVT0, 0x00000400); // unmask and set to NMI + unsigned int v, ver; + + ver = apic_read(APIC_LVR); + ver = GET_APIC_VERSION(ver); + v = APIC_DM_NMI; /* unmask and set to NMI */ + if (!APIC_INTEGRATED(ver)) /* 82489DX */ + v |= APIC_LVT_LEVEL_TRIGGER; + apic_write_around(APIC_LVT0, v); } static void setup_nmi (void) @@ -1303,24 +1304,23 @@ static inline void check_timer(void) printk(KERN_INFO "..TIMER: vector=%d pin1=%d pin2=%d\n", vector, pin1, pin2); - /* - * Ok, does IRQ0 through the IOAPIC work? - */ - if (timer_irq_works()) { - if (nmi_watchdog) { - disable_8259A_irq(0); - init_8259A(1); - setup_nmi(); - enable_8259A_irq(0); - if (nmi_irq_works()) - return; - } else - return; - } - if (pin1 != -1) { - printk(KERN_ERR "..MP-BIOS bug: 8254 timer not connected to IO-APIC\n"); + /* + * Ok, does IRQ0 through the IOAPIC work? + */ + unmask_IO_APIC_irq(0); + if (timer_irq_works()) { + if (nmi_watchdog) { + disable_8259A_irq(0); + init_8259A(1); + setup_nmi(); + enable_8259A_irq(0); + nmi_irq_works(); + } + return; + } clear_IO_APIC_pin(0, pin1); + printk(KERN_ERR "..MP-BIOS bug: 8254 timer not connected to IO-APIC\n"); } printk(KERN_INFO "...trying to set up timer (IRQ0) through the 8259A ... "); @@ -1334,10 +1334,9 @@ static inline void check_timer(void) printk("works.\n"); if (nmi_watchdog) { setup_nmi(); - if (nmi_irq_works()) - return; - } else - return; + nmi_irq_works(); + } + return; } /* * Cleanup, just in case ... @@ -1355,9 +1354,8 @@ static inline void check_timer(void) disable_8259A_irq(0); irq_desc[0].handler = &lapic_irq_type; - init_8259A(1); // AEOI mode - apic_readaround(APIC_LVT0); - apic_write(APIC_LVT0, 0x00000000 | vector); // Fixed mode + init_8259A(1); /* AEOI mode */ + apic_write_around(APIC_LVT0, APIC_DM_FIXED | vector); /* Fixed mode */ enable_8259A_irq(0); if (timer_irq_works()) { @@ -1392,20 +1390,11 @@ void __init setup_IO_APIC(void) printk("ENABLING IO-APIC IRQs\n"); /* - * If there are no explicit MP IRQ entries, it's either one of the - * default configuration types or we are broken. In both cases it's - * fine to set up most of the low 16 IO-APIC pins to ISA defaults. - */ - if (!mp_irq_entries) { - printk("no explicit IRQ entries, using default mptable\n"); - construct_default_ISA_mptable(); - } - - /* * Set up the IO-APIC IRQ routing table by parsing the MP-BIOS * mptable: */ setup_ioapic_ids_from_mpc(); + sync_Arb_IDs(); setup_IO_APIC_irqs(); init_IO_APIC_traps(); check_timer(); @@ -1421,6 +1410,7 @@ void IO_APIC_init_uniprocessor (void) { if (!smp_found_config) return; + connect_bsp_APIC(); setup_local_APIC(); setup_IO_APIC(); setup_APIC_clocks(); diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c index a96540d6e..79155a326 100644 --- a/arch/i386/kernel/irq.c +++ b/arch/i386/kernel/irq.c @@ -462,8 +462,8 @@ int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * * @irq: Interrupt to disable * * Disable the selected interrupt line. Disables of an interrupt - * stack. Unlike disable_irq, this function does not ensure existing - * instances of the irq handler have completed before returning. + * stack. Unlike disable_irq(), this function does not ensure existing + * instances of the IRQ handler have completed before returning. * * This function may be called from IRQ context. */ @@ -1127,7 +1127,7 @@ static void register_irq_proc (unsigned int irq) irq_dir[irq] = proc_mkdir(name, root_irq_dir); /* create /proc/irq/1234/smp_affinity */ - entry = create_proc_entry("smp_affinity", 0700, irq_dir[irq]); + entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]); entry->nlink = 1; entry->data = (void *)(long)irq; @@ -1148,7 +1148,7 @@ void init_irq_proc (void) root_irq_dir = proc_mkdir("irq", 0); /* create /proc/irq/prof_cpu_mask */ - entry = create_proc_entry("prof_cpu_mask", 0700, root_irq_dir); + entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir); entry->nlink = 1; entry->data = (void *)&prof_cpu_mask; diff --git a/arch/i386/kernel/mca.c b/arch/i386/kernel/mca.c index f0f0f9f37..6c6053bf7 100644 --- a/arch/i386/kernel/mca.c +++ b/arch/i386/kernel/mca.c @@ -366,12 +366,12 @@ void mca_handle_nmi(void) /** * mca_find_adapter - scan for adapters * @id: MCA identification to search for - * @start: Starting slot + * @start: starting slot * * Search the MCA configuration for adapters matching the 16bit * ID given. The first time it should be called with start as zero * and then further calls made passing the return value of the - * previous call until MCA_NOTFOUND is returned. + * previous call until %MCA_NOTFOUND is returned. * * Disabled adapters are not reported. */ @@ -411,12 +411,12 @@ EXPORT_SYMBOL(mca_find_adapter); /** * mca_find_unused_adapter - scan for unused adapters * @id: MCA identification to search for - * @start: Starting slot + * @start: starting slot * * Search the MCA configuration for adapters matching the 16bit * ID given. The first time it should be called with start as zero * and then further calls made passing the return value of the - * previous call until MCA_NOTFOUND is returned. + * previous call until %MCA_NOTFOUND is returned. * * Adapters that have been claimed by drivers and those that * are disabled are not reported. This function thus allows a driver @@ -647,10 +647,10 @@ EXPORT_SYMBOL(mca_set_adapter_name); * function is called with the buffer, slot, and device pointer (or * some equally informative context information, or nothing, if you * prefer), and is expected to put useful information into the - * buffer. The adapter name, id, and POS registers get printed + * buffer. The adapter name, ID, and POS registers get printed * before this is called though, so don't do it again. * - * This should be called with a NULL procfn when a module + * This should be called with a %NULL @procfn when a module * unregisters, thus preventing kernel crashes and other such * nastiness. */ diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c index 030b31647..5df83a10a 100644 --- a/arch/i386/kernel/mpparse.c +++ b/arch/i386/kernel/mpparse.c @@ -9,7 +9,7 @@ * Erich Boleyn : MP v1.4 and additional changes. * Alan Cox : Added EBDA scanning * Ingo Molnar : various cleanups and rewrites - * Maciej W. Rozycki : Bits for genuine 82489DX APICs + * Maciej W. Rozycki : Bits for default MP configurations */ #include <linux/mm.h> @@ -34,7 +34,7 @@ int smp_found_config = 0; * Various Linux-internal data structures created from the * MP-table. */ -int apic_version [NR_CPUS]; +int apic_version [MAX_APICS]; int mp_bus_id_to_type [MAX_MP_BUSSES] = { -1, }; int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { -1, }; int mp_current_pci_id = 0; @@ -42,9 +42,9 @@ int pic_mode; unsigned long mp_lapic_addr = 0; /* Processor that is doing the boot up */ -unsigned int boot_cpu_id = 0; +unsigned int boot_cpu_id = -1U; /* Internal processor count */ -static unsigned int num_processors = 1; +static unsigned int num_processors = 0; /* Bitmask of physically existing CPUs */ unsigned long phys_cpu_present_map = 0; @@ -132,13 +132,12 @@ static void __init MP_processor_info (struct mpc_config_processor *m) if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) { Dprintk(" Bootup CPU\n"); boot_cpu_id = m->mpc_apicid; - } else - /* Boot CPU already counted */ - num_processors++; + } + num_processors++; - if (m->mpc_apicid > NR_CPUS) { - printk("Processor #%d unused. (Max %d processors).\n", - m->mpc_apicid, NR_CPUS); + if (m->mpc_apicid > MAX_APICS) { + printk("Processor #%d INVALID. (Max ID: %d).\n", + m->mpc_apicid, MAX_APICS); return; } ver = m->mpc_apicver; @@ -164,18 +163,18 @@ static void __init MP_bus_info (struct mpc_config_bus *m) if (strncmp(str, "ISA", 3) == 0) { mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA; - } else { - if (strncmp(str, "EISA", 4) == 0) { + } else if (strncmp(str, "EISA", 4) == 0) { mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA; - } else { - if (strncmp(str, "PCI", 3) == 0) { + } else if (strncmp(str, "PCI", 3) == 0) { mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI; mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id; mp_current_pci_id++; + } else if (strncmp(str, "MCA", 3) == 0) { + mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA; } else { printk("Unknown bustype %s\n", str); panic("cannot handle bus - mail to linux-smp@vger.rutgers.edu"); - } } } + } } static void __init MP_ioapic_info (struct mpc_config_ioapic *m) @@ -197,12 +196,22 @@ static void __init MP_ioapic_info (struct mpc_config_ioapic *m) static void __init MP_intsrc_info (struct mpc_config_intsrc *m) { mp_irqs [mp_irq_entries] = *m; + Dprintk("Int: type %d, pol %d, trig %d, bus %d," + " IRQ %02x, APIC ID %x, APIC INT %02x\n", + m->mpc_irqtype, m->mpc_irqflag & 3, + (m->mpc_irqflag >> 2) & 3, m->mpc_srcbus, + m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq); if (++mp_irq_entries == MAX_IRQ_SOURCES) panic("Max # of irq sources exceeded!!\n"); } static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m) { + Dprintk("Lint: type %d, pol %d, trig %d, bus %d," + " IRQ %02x, APIC ID %x, APIC LINT %02x\n", + m->mpc_irqtype, m->mpc_irqflag & 3, + (m->mpc_irqflag >> 2) &3, m->mpc_srcbusid, + m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint); /* * Well it seems all SMP boards in existence * use ExtINT/LVT1 == LINT0 and @@ -316,6 +325,122 @@ static int __init smp_read_mpc(struct mp_config_table *mpc) return num_processors; } +static void __init construct_default_ioirq_mptable(int mpc_default_type) +{ + struct mpc_config_intsrc intsrc; + int i; + + intsrc.mpc_type = MP_INTSRC; + intsrc.mpc_irqflag = 0; /* conforming */ + intsrc.mpc_srcbus = 0; + intsrc.mpc_dstapic = mp_ioapics[0].mpc_apicid; + + intsrc.mpc_irqtype = mp_INT; + for (i = 0; i < 16; i++) { + switch (mpc_default_type) { + case 2: + if (i == 0 || i == 13) + continue; /* IRQ0 & IRQ13 not connected */ + /* fall through */ + default: + if (i == 2) + continue; /* IRQ2 is never connected */ + } + + intsrc.mpc_srcbusirq = i; + intsrc.mpc_dstirq = i ? i : 2; /* IRQ0 to INTIN2 */ + MP_intsrc_info(&intsrc); + } + + intsrc.mpc_irqtype = mp_ExtINT; + intsrc.mpc_srcbusirq = 0; + intsrc.mpc_dstirq = 0; /* 8259A to INTIN0 */ + MP_intsrc_info(&intsrc); +} + +static inline void __init construct_default_ISA_mptable(int mpc_default_type) +{ + struct mpc_config_processor processor; + struct mpc_config_bus bus; + struct mpc_config_ioapic ioapic; + struct mpc_config_lintsrc lintsrc; + int linttypes[2] = { mp_ExtINT, mp_NMI }; + int i; + + /* + * local APIC has default address + */ + mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; + + /* + * 2 CPUs, numbered 0 & 1. + */ + processor.mpc_type = MP_PROCESSOR; + /* Either an integrated APIC or a discrete 82489DX. */ + processor.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01; + processor.mpc_cpuflag = CPU_ENABLED; + processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) | + (boot_cpu_data.x86_model << 4) | + boot_cpu_data.x86_mask; + processor.mpc_featureflag = boot_cpu_data.x86_capability; + processor.mpc_reserved[0] = 0; + processor.mpc_reserved[1] = 0; + for (i = 0; i < 2; i++) { + processor.mpc_apicid = i; + MP_processor_info(&processor); + } + + bus.mpc_type = MP_BUS; + bus.mpc_busid = 0; + switch (mpc_default_type) { + default: + printk("???\nUnknown standard configuration %d\n", + mpc_default_type); + /* fall through */ + case 1: + case 5: + memcpy(bus.mpc_bustype, "ISA ", 6); + break; + case 2: + case 6: + case 3: + memcpy(bus.mpc_bustype, "EISA ", 6); + break; + case 4: + case 7: + memcpy(bus.mpc_bustype, "MCA ", 6); + } + MP_bus_info(&bus); + if (mpc_default_type > 4) { + bus.mpc_busid = 1; + memcpy(bus.mpc_bustype, "PCI ", 6); + MP_bus_info(&bus); + } + + ioapic.mpc_type = MP_IOAPIC; + ioapic.mpc_apicid = 2; + ioapic.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01; + ioapic.mpc_flags = MPC_APIC_USABLE; + ioapic.mpc_apicaddr = 0xFEC00000; + MP_ioapic_info(&ioapic); + + /* + * We set up most of the low 16 IO-APIC pins according to MPS rules. + */ + construct_default_ioirq_mptable(mpc_default_type); + + lintsrc.mpc_type = MP_LINTSRC; + lintsrc.mpc_irqflag = 0; /* conforming */ + lintsrc.mpc_srcbusid = 0; + lintsrc.mpc_srcbusirq = 0; + lintsrc.mpc_destapic = MP_APIC_ALL; + for (i = 0; i < 2; i++) { + lintsrc.mpc_irqtype = linttypes[i]; + lintsrc.mpc_destapiclint = i; + MP_lintsrc_info(&lintsrc); + } +} + static struct intel_mp_floating *mpf_found; /* @@ -332,83 +457,43 @@ void __init get_smp_config (void) printk(" Virtual Wire compatibility mode.\n"); pic_mode = 0; } - /* - * default CPU id - if it's different in the mptable - * then we change it before first using it. - */ - boot_cpu_id = 0; + /* * Now see if we need to read further. */ if (mpf->mpf_feature1 != 0) { + printk("Default MP configuration #%d\n", mpf->mpf_feature1); + construct_default_ISA_mptable(mpf->mpf_feature1); - /* - * local APIC has default address - */ - mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; + } else if (mpf->mpf_physptr) { /* - * 2 CPUs, numbered 0 & 1. + * Read the physical hardware table. Anything here will + * override the defaults. */ - phys_cpu_present_map = 3; - num_processors = 2; + smp_read_mpc((void *)mpf->mpf_physptr); - nr_ioapics = 1; - mp_ioapics[0].mpc_apicaddr = 0xFEC00000; - mp_ioapics[0].mpc_apicid = 2; /* - * Save the default type number, we - * need it later to set the IO-APIC - * up properly: + * If there are no explicit MP IRQ entries, then we are + * broken. We set up most of the low 16 IO-APIC pins to + * ISA defaults and hope it will work. */ - mpc_default_type = mpf->mpf_feature1; + if (!mp_irq_entries) { + struct mpc_config_bus bus; - printk("Bus #0 is "); - } + printk("BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n"); - switch (mpf->mpf_feature1) { - case 1: - case 5: - printk("ISA\n"); - break; - case 2: - printk("EISA with no IRQ0 and no IRQ13 DMA chaining\n"); - break; - case 6: - case 3: - printk("EISA\n"); - break; - case 4: - case 7: - printk("MCA\n"); - break; - case 0: - if (!mpf->mpf_physptr) - BUG(); - break; - default: - printk("???\nUnknown standard configuration %d\n", - mpf->mpf_feature1); - return; - } - if (mpf->mpf_feature1 > 4) { - printk("Bus #1 is PCI\n"); + bus.mpc_type = MP_BUS; + bus.mpc_busid = 0; + memcpy(bus.mpc_bustype, "ISA ", 6); + MP_bus_info(&bus); - /* - * Set local APIC version to the integrated form. - * It's initialized to zero otherwise, representing - * a discrete 82489DX. - */ - apic_version[0] = 0x10; - apic_version[1] = 0x10; - } - /* - * Read the physical hardware table. Anything here will override the - * defaults. - */ - if (mpf->mpf_physptr) - smp_read_mpc((void *)mpf->mpf_physptr); + construct_default_ioirq_mptable(0); + } + + } else + BUG(); printk("Processors: %d\n", num_processors); /* diff --git a/arch/i386/kernel/mtrr.c b/arch/i386/kernel/mtrr.c index f5a035cc7..fb066f051 100644 --- a/arch/i386/kernel/mtrr.c +++ b/arch/i386/kernel/mtrr.c @@ -289,7 +289,7 @@ #define MTRRfix4K_F0000_MSR 0x26e #define MTRRfix4K_F8000_MSR 0x26f -#ifdef __SMP__ +#ifdef CONFIG_SMP # define MTRR_CHANGE_MASK_FIXED 0x01 # define MTRR_CHANGE_MASK_VARIABLE 0x02 # define MTRR_CHANGE_MASK_DEFTYPE 0x04 @@ -302,7 +302,7 @@ typedef u8 mtrr_type; #define LINE_SIZE 80 #define JIFFIE_TIMEOUT 100 -#ifdef __SMP__ +#ifdef CONFIG_SMP # define set_mtrr(reg,base,size,type) set_mtrr_smp (reg, base, size, type) #else # define set_mtrr(reg,base,size,type) (*set_mtrr_up) (reg, base, size, type, \ @@ -767,7 +767,7 @@ static void (*set_mtrr_up) (unsigned int reg, unsigned long base, unsigned long size, mtrr_type type, int do_safe) = NULL; -#ifdef __SMP__ +#ifdef CONFIG_SMP struct mtrr_var_range { @@ -1015,7 +1015,7 @@ static void __init mtrr_state_warn(unsigned long mask) printk ("mtrr: probably your BIOS does not setup all CPUs\n"); } /* End Function mtrr_state_warn */ -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ static char *attrib_to_str (int x) { @@ -1110,7 +1110,7 @@ static int (*get_free_region) (unsigned long base, * * Memory type region registers control the caching on newer Intel and * non Intel processors. This function allows drivers to request an - * MTRR is added. The details and hardware specifics of each processors + * MTRR is added. The details and hardware specifics of each processor's * implementation are hidden from the caller, but nevertheless the * caller should expect to need to provide a power of two size on an * equivalent power of two boundary. @@ -1125,13 +1125,13 @@ static int (*get_free_region) (unsigned long base, * * The available types are * - * MTRR_TYPE_UNCACHEABLE - No caching + * %MTRR_TYPE_UNCACHEABLE - No caching * - * MTRR_TYPE_WRITEBACK - Write data back in bursts whenever + * %MTRR_TYPE_WRITEBACK - Write data back in bursts whenever * - * MTRR_TYPE_WRCOMB - Write data back soon but allow bursts + * %MTRR_TYPE_WRCOMB - Write data back soon but allow bursts * - * MTRR_TYPE_WRTHROUGH - Cache reads but not writes + * %MTRR_TYPE_WRTHROUGH - Cache reads but not writes * * BUGS: Needs a quiet flag for the cases where drivers do not mind * failures and do not wish system log messages to be sent. @@ -1608,7 +1608,7 @@ static void compute_ascii (void) EXPORT_SYMBOL(mtrr_add); EXPORT_SYMBOL(mtrr_del); -#ifdef __SMP__ +#ifdef CONFIG_SMP typedef struct { @@ -1663,7 +1663,7 @@ static void __init cyrix_arr_init(void) struct set_mtrr_context ctxt; unsigned char ccr[7]; int ccrc[7] = { 0, 0, 0, 0, 0, 0, 0 }; -#ifdef __SMP__ +#ifdef CONFIG_SMP int i; #endif @@ -1709,7 +1709,7 @@ static void __init cyrix_arr_init(void) setCx86 (CX86_CCR5, ccr[5]); } -#ifdef __SMP__ +#ifdef CONFIG_SMP for(i=0; i<7; i++) ccr_state[i] = ccr[i]; for(i=0; i<8; i++) cyrix_get_arr(i, @@ -1782,7 +1782,7 @@ static void __init mtrr_setup(void) } } /* End Function mtrr_setup */ -#ifdef __SMP__ +#ifdef CONFIG_SMP static volatile unsigned long smp_changes_mask __initdata = 0; static struct mtrr_state smp_mtrr_state __initdata = {0, 0}; @@ -1851,12 +1851,12 @@ void __init mtrr_init_secondary_cpu(void) break; } } /* End Function mtrr_init_secondary_cpu */ -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ int __init mtrr_init(void) { if ( !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR) ) return 0; -#ifdef __SMP__ +#ifdef CONFIG_SMP switch (boot_cpu_data.x86_vendor) { case X86_VENDOR_AMD: @@ -1866,7 +1866,7 @@ int __init mtrr_init(void) mtrr_state_warn (smp_changes_mask); break; } -#else /* __SMP__ */ +#else /* CONFIG_SMP */ mtrr_setup (); switch (boot_cpu_data.x86_vendor) { @@ -1877,7 +1877,7 @@ int __init mtrr_init(void) centaur_mcr_init (); break; } -#endif /* !__SMP__ */ +#endif /* !CONFIG_SMP */ #ifdef CONFIG_PROC_FS proc_root_mtrr = create_proc_entry ("mtrr", S_IWUSR | S_IRUGO, &proc_root); diff --git a/arch/i386/kernel/pci-irq.c b/arch/i386/kernel/pci-irq.c index 8dd3f5c82..4695abdf4 100644 --- a/arch/i386/kernel/pci-irq.c +++ b/arch/i386/kernel/pci-irq.c @@ -29,7 +29,7 @@ static struct irq_routing_table *pirq_table; * Avoid using: 13, 14 and 15 (FP error and IDE). * Penalize: 3, 4, 7, 12 (known ISA uses: serial, parallel and mouse) */ -unsigned int pcibios_irq_mask = ~0; +unsigned int pcibios_irq_mask = 0xfff8; static unsigned pirq_penalty[16] = { 10000, 10000, 10000, 100, 100, 0, 0, 100, @@ -305,10 +305,7 @@ int pcibios_lookup_irq(struct pci_dev *dev, int assign) return 0; } DBG(" -> PIRQ %02x, mask %04x, excl %04x", pirq, mask, pirq_table->exclusive_irqs); - if (pcibios_irq_mask != ~0) - mask &= pcibios_irq_mask; - else - mask &= pirq_table->exclusive_irqs; + mask &= pcibios_irq_mask; /* Find the best IRQ to assign */ newirq = 0; diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 3ba1d8257..96eedb519 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -589,7 +589,6 @@ void dump_thread(struct pt_regs * regs, struct user * dump) * More important, however, is the fact that this allows us much * more flexibility. */ -extern int cpus_initialized; void __switch_to(struct task_struct *prev_p, struct task_struct *next_p) { struct thread_struct *prev = &prev_p->thread, diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 71407c0ea..ac088253f 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -495,6 +495,10 @@ static inline void parse_mem_cmdline (char ** cmdline_p) if (!memcmp(from+4, "nopentium", 9)) { from += 9+4; boot_cpu_data.x86_capability &= ~X86_FEATURE_PSE; + } else if (!memcmp(from+4, "exactmap", 8)) { + from += 8+4; + e820.nr_map = 0; + usermem = 1; } else { /* If the user specifies memory size, we * blow away any automatically generated @@ -1531,8 +1535,7 @@ int get_cpuinfo(char * buffer) return p - buffer; } -int cpus_initialized = 0; -unsigned long cpu_initialized = 0; +static unsigned long cpu_initialized __initdata = 0; /* * cpu_init() initializes state that is per-CPU. Some data is already @@ -1549,7 +1552,6 @@ void __init cpu_init (void) printk("CPU#%d already initialized!\n", nr); for (;;) __sti(); } - cpus_initialized++; printk("Initializing CPU#%d\n", nr); if (cpu_has_vme || cpu_has_tsc || cpu_has_de) diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c index c7c079194..4e813fac7 100644 --- a/arch/i386/kernel/signal.c +++ b/arch/i386/kernel/signal.c @@ -339,9 +339,9 @@ setup_sigcontext(struct sigcontext *sc, struct _fpstate *fpstate, int tmp, err = 0; tmp = 0; - __asm__("movl %%gs,%w0" : "=r"(tmp): "0"(tmp)); + __asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp)); err |= __put_user(tmp, (unsigned int *)&sc->gs); - __asm__("movl %%fs,%w0" : "=r"(tmp): "0"(tmp)); + __asm__("movl %%fs,%0" : "=r"(tmp): "0"(tmp)); err |= __put_user(tmp, (unsigned int *)&sc->fs); err |= __put_user(regs->xes, (unsigned int *)&sc->es); diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c index 12f193c71..94ba5c49f 100644 --- a/arch/i386/kernel/smp.c +++ b/arch/i386/kernel/smp.c @@ -111,108 +111,26 @@ struct tlb_state cpu_tlbstate[NR_CPUS] = {[0 ... NR_CPUS-1] = { &init_mm, 0 }}; * We use 'broadcast', CPU->CPU IPIs and self-IPIs too. */ -static unsigned int cached_APIC_ICR; -static unsigned int cached_APIC_ICR2; - -/* - * Caches reserved bits, APIC reads are (mildly) expensive - * and force otherwise unnecessary CPU synchronization. - * - * (We could cache other APIC registers too, but these are the - * main ones used in RL.) - */ -#define slow_ICR (apic_read(APIC_ICR) & ~0xFDFFF) -#define slow_ICR2 (apic_read(APIC_ICR2) & 0x00FFFFFF) - -void cache_APIC_registers (void) -{ - cached_APIC_ICR = slow_ICR; - cached_APIC_ICR2 = slow_ICR2; - mb(); -} - -static inline unsigned int __get_ICR (void) -{ -#if FORCE_READ_AROUND_WRITE - /* - * Wait for the APIC to become ready - this should never occur. It's - * a debugging check really. - */ - int count = 0; - unsigned int cfg; - - while (count < 1000) - { - cfg = slow_ICR; - if (!(cfg&(1<<12))) - return cfg; - printk("CPU #%d: ICR still busy [%08x]\n", - smp_processor_id(), cfg); - irq_err_count++; - count++; - udelay(10); - } - printk("CPU #%d: previous IPI still not cleared after 10mS\n", - smp_processor_id()); - return cfg; -#else - return cached_APIC_ICR; -#endif -} - -static inline unsigned int __get_ICR2 (void) -{ -#if FORCE_READ_AROUND_WRITE - return slow_ICR2; -#else - return cached_APIC_ICR2; -#endif -} - -#define LOGICAL_DELIVERY 1 - static inline int __prepare_ICR (unsigned int shortcut, int vector) { - unsigned int cfg; - - cfg = __get_ICR(); - cfg |= APIC_DEST_DM_FIXED|shortcut|vector -#if LOGICAL_DELIVERY - |APIC_DEST_LOGICAL -#endif - ; - - return cfg; + return APIC_DM_FIXED | shortcut | vector | APIC_DEST_LOGICAL; } static inline int __prepare_ICR2 (unsigned int mask) { - unsigned int cfg; - - cfg = __get_ICR2(); -#if LOGICAL_DELIVERY - cfg |= SET_APIC_DEST_FIELD(mask); -#else - cfg |= SET_APIC_DEST_FIELD(mask); -#endif - - return cfg; + return SET_APIC_DEST_FIELD(mask); } static inline void __send_IPI_shortcut(unsigned int shortcut, int vector) { + /* + * Subtle. In the case of the 'never do double writes' workaround + * we have to lock out interrupts to be safe. As we don't care + * of the value read we use an atomic rmw access to avoid costly + * cli/sti. Otherwise we use an even cheaper single atomic write + * to the APIC. + */ unsigned int cfg; -/* - * Subtle. In the case of the 'never do double writes' workaround we - * have to lock out interrupts to be safe. Otherwise it's just one - * single atomic write to the APIC, no need for cli/sti. - */ -#if FORCE_READ_AROUND_WRITE - unsigned long flags; - - __save_flags(flags); - __cli(); -#endif /* * No need to touch the target chip field @@ -222,10 +140,7 @@ static inline void __send_IPI_shortcut(unsigned int shortcut, int vector) /* * Send the IPI. The write to APIC_ICR fires this off. */ - apic_write(APIC_ICR, cfg); -#if FORCE_READ_AROUND_WRITE - __restore_flags(flags); -#endif + apic_write_around(APIC_ICR, cfg); } static inline void send_IPI_allbutself(int vector) @@ -252,19 +167,16 @@ void send_IPI_self(int vector) static inline void send_IPI_mask(int mask, int vector) { unsigned long cfg; -#if FORCE_READ_AROUND_WRITE unsigned long flags; __save_flags(flags); __cli(); -#endif /* * prepare target chip field */ - cfg = __prepare_ICR2(mask); - apic_write(APIC_ICR2, cfg); + apic_write_around(APIC_ICR2, cfg); /* * program the ICR @@ -274,10 +186,8 @@ static inline void send_IPI_mask(int mask, int vector) /* * Send the IPI. The write to APIC_ICR fires this off. */ - apic_write(APIC_ICR, cfg); -#if FORCE_READ_AROUND_WRITE + apic_write_around(APIC_ICR, cfg); __restore_flags(flags); -#endif } /* diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 50b743a99..ae84ff2b5 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -28,6 +28,7 @@ * from Jose Renau * Ingo Molnar : various cleanups and rewrites * Tigran Aivazian : fixed "0.00 in /proc/uptime on SMP" bug. + * Maciej W. Rozycki : Bits for genuine 82489DX APICs */ #include <linux/config.h> @@ -489,11 +490,43 @@ static int __init fork_by_hand(void) return do_fork(CLONE_VM|CLONE_PID, 0, ®s); } +#if APIC_DEBUG +static inline void inquire_remote_apic(int apicid) +{ + int i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 }; + char *names[] = { "ID", "VERSION", "SPIV" }; + int timeout, status; + + printk("Inquiring remote APIC #%d...\n", apicid); + + for (i = 0; i < sizeof(regs) / sizeof(*regs); i++) { + printk("... APIC #%d %s: ", apicid, names[i]); + + apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid)); + apic_write_around(APIC_ICR, APIC_DM_REMRD | regs[i]); + + timeout = 0; + do { + udelay(100); + status = apic_read(APIC_ICR) & APIC_ICR_RR_MASK; + } while (status == APIC_ICR_RR_INPROG && timeout++ < 1000); + + switch (status) { + case APIC_ICR_RR_VALID: + status = apic_read(APIC_RRR); + printk("%08x\n", status); + break; + default: + printk("failed\n"); + } + } +} +#endif + static void __init do_boot_cpu (int apicid) { - unsigned long cfg; struct task_struct *idle; - unsigned long send_status, accept_status; + unsigned long send_status, accept_status, boot_status, maxlvt; int timeout, num_starts, j, cpu; unsigned long start_eip; @@ -527,7 +560,7 @@ static void __init do_boot_cpu (int apicid) start_eip = setup_trampoline(); /* So we see what's up */ - printk("Booting processor %d eip %lx\n", cpu, start_eip); + printk("Booting processor %d/%d eip %lx\n", cpu, apicid, start_eip); stack_start.esp = (void *) (1024 + PAGE_SIZE + (char *)idle); /* @@ -549,16 +582,17 @@ static void __init do_boot_cpu (int apicid) * Be paranoid about clearing APIC errors. */ if (APIC_INTEGRATED(apic_version[apicid])) { - apic_readaround(APIC_SPIV); + apic_read_around(APIC_SPIV); apic_write(APIC_ESR, 0); - accept_status = (apic_read(APIC_ESR) & 0xEF); + apic_read(APIC_ESR); } /* * Status is now clean */ - send_status = 0; + send_status = 0; accept_status = 0; + boot_status = 0; /* * Starting actual IPI sequence... @@ -567,37 +601,41 @@ static void __init do_boot_cpu (int apicid) Dprintk("Asserting INIT.\n"); /* - * Turn INIT on - */ - cfg = apic_read(APIC_ICR2); - cfg &= 0x00FFFFFF; - - /* - * Target chip + * Turn INIT on target chip */ - apic_write(APIC_ICR2, cfg | SET_APIC_DEST_FIELD(apicid)); + apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid)); /* * Send IPI */ - cfg = apic_read(APIC_ICR); - cfg &= ~0xCDFFF; - cfg |= (APIC_DEST_LEVELTRIG | APIC_DEST_ASSERT | APIC_DEST_DM_INIT); - apic_write(APIC_ICR, cfg); + apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT + | APIC_DM_INIT); + + Dprintk("Waiting for send to finish...\n"); + timeout = 0; + do { + Dprintk("+"); + udelay(100); + send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; + } while (send_status && (timeout++ < 1000)); + + mdelay(10); - udelay(200); Dprintk("Deasserting INIT.\n"); /* Target chip */ - cfg = apic_read(APIC_ICR2); - cfg &= 0x00FFFFFF; - apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(apicid)); + apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid)); /* Send IPI */ - cfg = apic_read(APIC_ICR); - cfg &= ~0xCDFFF; - cfg |= (APIC_DEST_LEVELTRIG | APIC_DEST_DM_INIT); - apic_write(APIC_ICR, cfg); + apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT); + + Dprintk("Waiting for send to finish...\n"); + timeout = 0; + do { + Dprintk("+"); + udelay(100); + send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; + } while (send_status && (timeout++ < 1000)); /* * Should we send STARTUP IPIs ? @@ -616,9 +654,11 @@ static void __init do_boot_cpu (int apicid) */ Dprintk("#startup loops: %d.\n", num_starts); + maxlvt = get_maxlvt(); + for (j = 1; j <= num_starts; j++) { Dprintk("Sending STARTUP #%d.\n",j); - apic_readaround(APIC_SPIV); + apic_read_around(APIC_SPIV); apic_write(APIC_ESR, 0); apic_read(APIC_ESR); Dprintk("After apic_write.\n"); @@ -628,17 +668,12 @@ static void __init do_boot_cpu (int apicid) */ /* Target chip */ - cfg = apic_read(APIC_ICR2); - cfg &= 0x00FFFFFF; - apic_write(APIC_ICR2, cfg | SET_APIC_DEST_FIELD(apicid)); + apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid)); /* Boot on the stack */ - cfg = apic_read(APIC_ICR); - cfg &= ~0xCDFFF; - cfg |= (APIC_DEST_DM_STARTUP | (start_eip >> 12)); - /* Kick the second */ - apic_write(APIC_ICR, cfg); + apic_write_around(APIC_ICR, APIC_DM_STARTUP + | (start_eip >> 12)); Dprintk("Startup point 1.\n"); @@ -647,13 +682,20 @@ static void __init do_boot_cpu (int apicid) do { Dprintk("+"); udelay(100); - send_status = apic_read(APIC_ICR) & 0x1000; + send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; } while (send_status && (timeout++ < 1000)); /* * Give the other CPU some time to accept the IPI. */ udelay(200); + /* + * Due to the Pentium erratum 3AP. + */ + if (maxlvt > 3) { + apic_read_around(APIC_SPIV); + apic_write(APIC_ESR, 0); + } accept_status = (apic_read(APIC_ESR) & 0xEF); if (send_status || accept_status) break; @@ -676,7 +718,7 @@ static void __init do_boot_cpu (int apicid) /* * Wait 5s total for a response */ - for (timeout = 0; timeout < 1000000000; timeout++) { + for (timeout = 0; timeout < 50000; timeout++) { if (test_bit(cpu, &cpu_callin_map)) break; /* It has booted */ udelay(100); @@ -687,15 +729,22 @@ static void __init do_boot_cpu (int apicid) Dprintk("OK.\n"); printk("CPU%d: ", cpu); print_cpu_info(&cpu_data[cpu]); + Dprintk("CPU has booted.\n"); } else { + boot_status = 1; if (*((volatile unsigned char *)phys_to_virt(8192)) - == 0xA5) /* trampoline code not run */ + == 0xA5) + /* trampoline started but...? */ printk("Stuck ??\n"); else - printk("CPU booted but not responding.\n"); + /* trampoline code not run */ + printk("Not responding.\n"); +#if APIC_DEBUG + inquire_remote_apic(apicid); +#endif } - Dprintk("CPU has booted.\n"); - } else { + } + if (send_status || accept_status || boot_status) { x86_cpu_to_apicid[cpu] = -1; x86_apicid_to_cpu[apicid] = -1; cpucount--; @@ -858,6 +907,7 @@ void __init smp_boot_cpus(void) Dprintk("Getting LVT1: %x\n", reg); } + connect_bsp_APIC(); setup_local_APIC(); if (GET_APIC_ID(apic_read(APIC_ID)) != boot_cpu_id) @@ -877,7 +927,7 @@ void __init smp_boot_cpus(void) if (!(phys_cpu_present_map & (1 << apicid))) continue; - if ((max_cpus >= 0) && (max_cpus < cpucount+1)) + if ((max_cpus >= 0) && (max_cpus <= cpucount+1)) continue; do_boot_cpu(apicid); @@ -934,7 +984,6 @@ void __init smp_boot_cpus(void) printk(KERN_WARNING "WARNING: SMP operation may be unreliable with B stepping processors.\n"); Dprintk("Boot done.\n"); - cache_APIC_registers(); #ifndef CONFIG_VISWS /* * Here we can be sure that there is an IO-APIC in the system. Let's diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 3a7004970..e25f50cfd 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -696,7 +696,7 @@ static void __init set_call_gate(void *a, void *addr) ((limit) & 0x0ffff); } #define _set_tssldt_desc(n,addr,limit,type) \ -__asm__ __volatile__ ("movw %3,0(%2)\n\t" \ +__asm__ __volatile__ ("movw %w3,0(%2)\n\t" \ "movw %%ax,2(%2)\n\t" \ "rorl $16,%%eax\n\t" \ "movb %%al,4(%2)\n\t" \ diff --git a/arch/i386/kernel/visws_apic.c b/arch/i386/kernel/visws_apic.c index be80cd628..288f83e8f 100644 --- a/arch/i386/kernel/visws_apic.c +++ b/arch/i386/kernel/visws_apic.c @@ -376,7 +376,7 @@ void init_VISWS_APIC_irqs(void) for (i = 0; i < 16; i++) { irq_desc[i].status = IRQ_DISABLED; irq_desc[i].action = 0; - irq_desc[i].depth = 0; + irq_desc[i].depth = 1; /* * Cobalt IRQs are mapped to standard ISA diff --git a/arch/i386/lib/delay.c b/arch/i386/lib/delay.c index ca5eeb796..89e7940ad 100644 --- a/arch/i386/lib/delay.c +++ b/arch/i386/lib/delay.c @@ -10,11 +10,12 @@ * we have to worry about. */ +#include <linux/config.h> #include <linux/sched.h> #include <linux/delay.h> #include <asm/delay.h> -#ifdef __SMP__ +#ifdef CONFIG_SMP #include <asm/smp.h> #endif diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c index 21c9cadff..2f030f306 100644 --- a/arch/i386/mm/fault.c +++ b/arch/i386/mm/fault.c @@ -51,7 +51,7 @@ good_area: start &= PAGE_MASK; for (;;) { - if (handle_mm_fault(current, vma, start, 1) <= 0) + if (handle_mm_fault(current->mm, vma, start, 1) <= 0) goto bad_area; if (!size) break; @@ -193,7 +193,7 @@ good_area: * the fault. */ { - int fault = handle_mm_fault(tsk, vma, address, write); + int fault = handle_mm_fault(mm, vma, address, write); if (fault < 0) goto out_of_memory; if (!fault) diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile index 3ace288ef..897bca8e7 100644 --- a/arch/ia64/Makefile +++ b/arch/ia64/Makefile @@ -9,6 +9,7 @@ # NM := $(CROSS_COMPILE)nm -B +AWK := awk LINKFLAGS = -static -T arch/$(ARCH)/vmlinux.lds # next line is for HP compiler backend: @@ -16,10 +17,10 @@ LINKFLAGS = -static -T arch/$(ARCH)/vmlinux.lds # The next line is needed when compiling with the July snapshot of the Cygnus compiler: #EXTRA = -D__GCC_DOESNT_KNOW_IN_REGS__ # next two lines are for the September snapshot of the Cygnus compiler: -AFLAGS += -D__GCC_MULTIREG_RETVALS__ +AFLAGS += -D__GCC_MULTIREG_RETVALS__ -Wa,-x EXTRA = -D__GCC_MULTIREG_RETVALS__ -CFLAGS := $(CFLAGS) -pipe $(EXTRA) -ffixed-r13 -mfixed-range=f10-f15,f32-f127 +CFLAGS := $(CFLAGS) -pipe $(EXTRA) -Wa,-x -ffixed-r13 -mfixed-range=f10-f15,f32-f127 ifdef CONFIG_IA64_GENERIC CORE_FILES := arch/$(ARCH)/hp/hp.a \ @@ -34,14 +35,14 @@ ifdef CONFIG_IA64_GENERIC else # !GENERIC -ifeq ($(CONFIG_IA64_HP_SIM),y) +ifdef CONFIG_IA64_HP_SIM SUBDIRS := arch/$(ARCH)/hp \ $(SUBDIRS) CORE_FILES := arch/$(ARCH)/hp/hp.a \ $(CORE_FILES) endif -ifeq ($(CONFIG_IA64_SGI_SN1_SIM),y) +ifdef CONFIG_IA64_SGI_SN1_SIM SUBDIRS := arch/$(ARCH)/sn/sn1 \ arch/$(ARCH)/sn \ $(SUBDIRS) @@ -49,14 +50,14 @@ ifeq ($(CONFIG_IA64_SGI_SN1_SIM),y) $(CORE_FILES) endif -ifeq ($(CONFIG_IA64_SOFTSDV),y) +ifdef CONFIG_IA64_SOFTSDV SUBDIRS := arch/$(ARCH)/dig \ $(SUBDIRS) CORE_FILES := arch/$(ARCH)/dig/dig.a \ $(CORE_FILES) endif -ifeq ($(CONFIG_IA64_DIG),y) +ifdef CONFIG_IA64_DIG SUBDIRS := arch/$(ARCH)/dig \ $(SUBDIRS) CORE_FILES := arch/$(ARCH)/dig/dig.a \ @@ -65,16 +66,11 @@ endif endif # !GENERIC -ifeq ($(CONFIG_IA32_SUPPORT),y) +ifdef CONFIG_IA32_SUPPORT SUBDIRS := arch/$(ARCH)/ia32 $(SUBDIRS) CORE_FILES := arch/$(ARCH)/ia32/ia32.o $(CORE_FILES) endif -ifdef CONFIG_KDB - LIBS := $(LIBS) $(TOPDIR)/arch/$(ARCH)/kdb/kdb.a - SUBDIRS := $(SUBDIRS) arch/$(ARCH)/kdb -endif - HEAD := arch/$(ARCH)/kernel/head.o arch/ia64/kernel/init_task.o SUBDIRS := arch/$(ARCH)/tools arch/$(ARCH)/kernel arch/$(ARCH)/mm arch/$(ARCH)/lib $(SUBDIRS) diff --git a/arch/ia64/config.in b/arch/ia64/config.in index b7cce3d73..2d1a11980 100644 --- a/arch/ia64/config.in +++ b/arch/ia64/config.in @@ -4,6 +4,8 @@ mainmenu_option next_comment comment 'General setup' define_bool CONFIG_IA64 y +define_bool CONFIG_ITANIUM y # easy choice for now... ;-) + define_bool CONFIG_ISA n define_bool CONFIG_SBUS n @@ -25,7 +27,7 @@ if [ "$CONFIG_IA64_DIG" = "y" ]; then bool ' Enable BigSur hacks' CONFIG_IA64_BIGSUR_HACKS bool ' Enable Lion hacks' CONFIG_IA64_LION_HACKS bool ' Emulate PAL/SAL/EFI firmware' CONFIG_IA64_FW_EMU - bool ' Get PCI IRQ routing from firmware/ACPI' CONFIG_IA64_IRQ_ACPI + bool ' Enable IA64 Machine Check Abort' CONFIG_IA64_MCA fi if [ "$CONFIG_IA64_GENERIC" = "y" ]; then @@ -185,10 +187,5 @@ bool 'Early printk support (requires VGA!)' CONFIG_IA64_EARLY_PRINTK bool 'Turn on compare-and-exchange bug checking (slow!)' CONFIG_IA64_DEBUG_CMPXCHG bool 'Turn on irq debug checks (slow!)' CONFIG_IA64_DEBUG_IRQ bool 'Print possible IA64 hazards to console' CONFIG_IA64_PRINT_HAZARDS -bool 'Built-in Kernel Debugger support' CONFIG_KDB -if [ "$CONFIG_KDB" = "y" ]; then - bool 'Compile the kernel with frame pointers' CONFIG_KDB_FRAMEPTR - int 'KDB Kernel Symbol Table size?' CONFIG_KDB_STBSIZE 10000 -fi endmenu diff --git a/arch/ia64/defconfig b/arch/ia64/defconfig index 12854f121..00a0e05b7 100644 --- a/arch/ia64/defconfig +++ b/arch/ia64/defconfig @@ -115,8 +115,8 @@ CONFIG_BLK_DEV_IDEDMA=y CONFIG_IDEDMA_PCI_EXPERIMENTAL=y # CONFIG_IDEDMA_PCI_WIP is not set # CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set -# CONFIG_BLK_DEV_AEC6210 is not set -# CONFIG_AEC6210_TUNING is not set +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_AEC62XX_TUNING is not set # CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_WDC_ALI15X3 is not set # CONFIG_BLK_DEV_AMD7409 is not set diff --git a/arch/ia64/dig/Makefile b/arch/ia64/dig/Makefile index 8d0544ee5..f067606ee 100644 --- a/arch/ia64/dig/Makefile +++ b/arch/ia64/dig/Makefile @@ -15,7 +15,7 @@ all: dig.a O_TARGET = dig.a O_OBJS = iosapic.o setup.o -ifeq ($(CONFIG_IA64_GENERIC),y) +ifdef CONFIG_IA64_GENERIC O_OBJS += machvec.o endif diff --git a/arch/ia64/dig/iosapic.c b/arch/ia64/dig/iosapic.c index 4861aa2d9..9fd01063e 100644 --- a/arch/ia64/dig/iosapic.c +++ b/arch/ia64/dig/iosapic.c @@ -7,16 +7,20 @@ * Copyright (C) 1999-2000 David Mosberger-Tang <davidm@hpl.hp.com> * Copyright (C) 1999 VA Linux Systems * Copyright (C) 1999,2000 Walt Drummond <drummond@valinux.com> + * + * 00/04/19 D. Mosberger Rewritten to mirror more closely the x86 I/O APIC code. + * In particular, we now have separate handlers for edge + * and level triggered interrupts. */ #include <linux/config.h> #include <linux/kernel.h> #include <linux/init.h> -#include <linux/irq.h> #include <linux/pci.h> #include <linux/smp.h> #include <linux/smp_lock.h> #include <linux/string.h> +#include <linux/irq.h> #include <asm/io.h> #include <asm/iosapic.h> @@ -27,172 +31,19 @@ #undef DEBUG_IRQ_ROUTING -/* - * IRQ vectors 0..15 are treated as the legacy interrupts of the PC-AT - * platform. No new drivers should ever ask for specific irqs, but we - * provide compatibility here in case there is an old driver that does - * ask for specific irqs (serial, keyboard, stuff like that). Since - * IA-64 doesn't allow irq 0..15 to be used for external interrupts - * anyhow, this in no way prevents us from doing the Right Thing - * with new drivers. - */ +static spinlock_t iosapic_lock = SPIN_LOCK_UNLOCKED; + struct iosapic_vector iosapic_vector[NR_IRQS] = { [0 ... NR_IRQS-1] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }; -#ifndef CONFIG_IA64_IRQ_ACPI -/* - * Defines the default interrupt routing information for the LION platform - * XXX - this information should be obtained from the ACPI and hardcoded since - * we do not have ACPI AML support. - */ - -struct intr_routing_entry intr_routing[] = { - {0,0,0,2,0,0,0,0}, - {0,0,1,1,0,0,0,0}, - {0,0,2,0xff,0,0,0,0}, - {0,0,3,3,0,0,0,0}, - {0,0,4,4,0,0,0,0}, - {0,0,5,5,0,0,0,0}, - {0,0,6,6,0,0,0,0}, - {0,0,7,7,0,0,0,0}, - {0,0,8,8,0,0,0,0}, - {0,0,9,9,0,0,0,0}, - {0,0,10,10,0,0,0,0}, - {0,0,11,11,0,0,0,0}, - {0,0,12,12,0,0,0,0}, - {0,0,13,13,0,0,0,0}, - {0,0,14,14,0,0,0,0}, - {0,0,15,15,0,0,0,0}, -#ifdef CONFIG_IA64_LION_HACKS - {1, 0, 0x04, 16, 0, 0, 1, 1}, /* bus 0, device id 1, INTA */ - {1, 0, 0x05, 26, 0, 0, 1, 1}, /* bus 0, device id 1, INTB */ - {1, 0, 0x06, 36, 0, 0, 1, 1}, /* bus 0, device id 1, INTC */ - {1, 0, 0x07, 42, 0, 0, 1, 1}, /* bus 0, device id 1, INTD */ - - {1, 0, 0x08, 17, 0, 0, 1, 1}, /* bus 0, device id 2, INTA */ - {1, 0, 0x09, 27, 0, 0, 1, 1}, /* bus 0, device id 2, INTB */ - {1, 0, 0x0a, 37, 0, 0, 1, 1}, /* bus 0, device id 2, INTC */ - {1, 0, 0x0b, 42, 0, 0, 1, 1}, /* bus 0, device id 2, INTD */ - - {1, 0, 0x0f, 50, 0, 0, 1, 1}, /* bus 0, device id 3, INTD */ - - {1, 0, 0x14, 51, 0, 0, 1, 1}, /* bus 0, device id 5, INTA */ - - {1, 0, 0x18, 49, 0, 0, 1, 1}, /* bus 0, device id 6, INTA */ - - {1, 1, 0x04, 18, 0, 0, 1, 1}, /* bus 1, device id 1, INTA */ - {1, 1, 0x05, 28, 0, 0, 1, 1}, /* bus 1, device id 1, INTB */ - {1, 1, 0x06, 38, 0, 0, 1, 1}, /* bus 1, device id 1, INTC */ - {1, 1, 0x07, 43, 0, 0, 1, 1}, /* bus 1, device id 1, INTD */ - - {1, 1, 0x08, 48, 0, 0, 1, 1}, /* bus 1, device id 2, INTA */ - - {1, 1, 0x0c, 19, 0, 0, 1, 1}, /* bus 1, device id 3, INTA */ - {1, 1, 0x0d, 29, 0, 0, 1, 1}, /* bus 1, device id 3, INTB */ - {1, 1, 0x0e, 38, 0, 0, 1, 1}, /* bus 1, device id 3, INTC */ - {1, 1, 0x0f, 44, 0, 0, 1, 1}, /* bus 1, device id 3, INTD */ - - {1, 1, 0x10, 20, 0, 0, 1, 1}, /* bus 1, device id 4, INTA */ - {1, 1, 0x11, 30, 0, 0, 1, 1}, /* bus 1, device id 4, INTB */ - {1, 1, 0x12, 39, 0, 0, 1, 1}, /* bus 1, device id 4, INTC */ - {1, 1, 0x13, 45, 0, 0, 1, 1}, /* bus 1, device id 4, INTD */ - - {1, 2, 0x04, 21, 0, 0, 1, 1}, /* bus 2, device id 1, INTA */ - {1, 2, 0x05, 31, 0, 0, 1, 1}, /* bus 2, device id 1, INTB */ - {1, 2, 0x06, 39, 0, 0, 1, 1}, /* bus 2, device id 1, INTC */ - {1, 2, 0x07, 45, 0, 0, 1, 1}, /* bus 2, device id 1, INTD */ - - {1, 2, 0x08, 22, 0, 0, 1, 1}, /* bus 2, device id 2, INTA */ - {1, 2, 0x09, 32, 0, 0, 1, 1}, /* bus 2, device id 2, INTB */ - {1, 2, 0x0a, 40, 0, 0, 1, 1}, /* bus 2, device id 2, INTC */ - {1, 2, 0x0b, 46, 0, 0, 1, 1}, /* bus 2, device id 2, INTD */ - - {1, 2, 0x0c, 23, 0, 0, 1, 1}, /* bus 2, device id 3, INTA */ - {1, 2, 0x0d, 33, 0, 0, 1, 1}, /* bus 2, device id 3, INTB */ - {1, 2, 0x0e, 40, 0, 0, 1, 1}, /* bus 2, device id 3, INTC */ - {1, 2, 0x0f, 46, 0, 0, 1, 1}, /* bus 2, device id 3, INTD */ - - {1, 3, 0x04, 24, 0, 0, 1, 1}, /* bus 3, device id 1, INTA */ - {1, 3, 0x05, 34, 0, 0, 1, 1}, /* bus 3, device id 1, INTB */ - {1, 3, 0x06, 41, 0, 0, 1, 1}, /* bus 3, device id 1, INTC */ - {1, 3, 0x07, 47, 0, 0, 1, 1}, /* bus 3, device id 1, INTD */ - - {1, 3, 0x08, 25, 0, 0, 1, 1}, /* bus 3, device id 2, INTA */ - {1, 3, 0x09, 35, 0, 0, 1, 1}, /* bus 3, device id 2, INTB */ - {1, 3, 0x0a, 41, 0, 0, 1, 1}, /* bus 3, device id 2, INTC */ - {1, 3, 0x0b, 47, 0, 0, 1, 1}, /* bus 3, device id 2, INTD */ -#else - /* - * BigSur platform, bus 0, device 1,2,4 and bus 1 device 0-3 - */ - {1,1,0x0,19,0,0,1,1}, /* bus 1, device id 0, INTA */ - {1,1,0x1,18,0,0,1,1}, /* bus 1, device id 0, INTB */ - {1,1,0x2,17,0,0,1,1}, /* bus 1, device id 0, INTC */ - {1,1,0x3,16,0,0,1,1}, /* bus 1, device id 0, INTD */ - - {1,1,0x4,23,0,0,1,1}, /* bus 1, device id 1, INTA */ - {1,1,0x5,22,0,0,1,1}, /* bus 1, device id 1, INTB */ - {1,1,0x6,21,0,0,1,1}, /* bus 1, device id 1, INTC */ - {1,1,0x7,20,0,0,1,1}, /* bus 1, device id 1, INTD */ - - {1,1,0x8,27,0,0,1,1}, /* bus 1, device id 2, INTA */ - {1,1,0x9,26,0,0,1,1}, /* bus 1, device id 2, INTB */ - {1,1,0xa,25,0,0,1,1}, /* bus 1, device id 2, INTC */ - {1,1,0xb,24,0,0,1,1}, /* bus 1, device id 2, INTD */ - - {1,1,0xc,31,0,0,1,1}, /* bus 1, device id 3, INTA */ - {1,1,0xd,30,0,0,1,1}, /* bus 1, device id 3, INTB */ - {1,1,0xe,29,0,0,1,1}, /* bus 1, device id 3, INTC */ - {1,1,0xf,28,0,0,1,1}, /* bus 1, device id 3, INTD */ - - {1,0,0x4,35,0,0,1,1}, /* bus 0, device id 1, INTA */ - {1,0,0x5,34,0,0,1,1}, /* bus 0, device id 1, INTB */ - {1,0,0x6,33,0,0,1,1}, /* bus 0, device id 1, INTC */ - {1,0,0x7,32,0,0,1,1}, /* bus 0, device id 1, INTD */ - - {1,0,0x8,39,0,0,1,1}, /* bus 0, device id 2, INTA */ - {1,0,0x9,38,0,0,1,1}, /* bus 0, device id 2, INTB */ - {1,0,0xa,37,0,0,1,1}, /* bus 0, device id 2, INTC */ - {1,0,0xb,36,0,0,1,1}, /* bus 0, device id 2, INTD */ - - {1,0,0x10,43,0,0,1,1}, /* bus 0, device id 4, INTA */ - {1,0,0x11,42,0,0,1,1}, /* bus 0, device id 4, INTB */ - {1,0,0x12,41,0,0,1,1}, /* bus 0, device id 4, INTC */ - {1,0,0x13,40,0,0,1,1}, /* bus 0, device id 4, INTD */ - - {1,0,0x14,17,0,0,1,1}, /* bus 0, device id 5, INTA */ - {1,0,0x18,18,0,0,1,1}, /* bus 0, device id 6, INTA */ - {1,0,0x1c,19,0,0,1,1}, /* bus 0, device id 7, INTA */ -#endif - {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}, -}; - -int -iosapic_get_PCI_irq_vector(int bus, int slot, int pci_pin) -{ - int i = -1; - - while (intr_routing[++i].srcbus != 0xff) { - if (intr_routing[i].srcbus == BUS_PCI) { - if ((intr_routing[i].srcbusirq == ((slot << 2) | pci_pin)) - && (intr_routing[i].srcbusno == bus)) { - return(intr_routing[i].iosapic_pin); - } - } - } - return -1; -} - -#else /* CONFIG_IA64_IRQ_ACPI */ - /* * find the IRQ in the IOSAPIC map for the PCI device on bus/slot/pin */ int -iosapic_get_PCI_irq_vector(int bus, int slot, int pci_pin) +iosapic_get_PCI_irq_vector (int bus, int slot, int pci_pin) { - int i; + int i; for (i = 0; i < NR_IRQS; i++) { if ((iosapic_bustype(i) == BUS_PCI) && @@ -201,17 +52,15 @@ iosapic_get_PCI_irq_vector(int bus, int slot, int pci_pin) return i; } } - return -1; } -#endif /* !CONFIG_IA64_IRQ_ACPI */ static void set_rte (unsigned long iosapic_addr, int entry, int pol, int trigger, int delivery, long dest, int vector) { - int low32; - int high32; + u32 low32; + u32 high32; low32 = ((pol << IO_SAPIC_POLARITY_SHIFT) | (trigger << IO_SAPIC_TRIGGER_SHIFT) | @@ -221,81 +70,137 @@ set_rte (unsigned long iosapic_addr, int entry, int pol, int trigger, int delive /* dest contains both id and eid */ high32 = (dest << IO_SAPIC_DEST_SHIFT); - /* - * program the rte - */ writel(IO_SAPIC_RTE_HIGH(entry), iosapic_addr + IO_SAPIC_REG_SELECT); writel(high32, iosapic_addr + IO_SAPIC_WINDOW); writel(IO_SAPIC_RTE_LOW(entry), iosapic_addr + IO_SAPIC_REG_SELECT); writel(low32, iosapic_addr + IO_SAPIC_WINDOW); } +static void +nop (unsigned int irq) +{ + /* do nothing... */ +} static void -enable_pin (unsigned int pin, unsigned long iosapic_addr) +mask_irq (unsigned int irq) { - int low32; + unsigned long flags, iosapic_addr = iosapic_addr(irq); + u32 low32; - writel(IO_SAPIC_RTE_LOW(pin), iosapic_addr + IO_SAPIC_REG_SELECT); - low32 = readl(iosapic_addr + IO_SAPIC_WINDOW); + spin_lock_irqsave(&iosapic_lock, flags); + { + writel(IO_SAPIC_RTE_LOW(iosapic_pin(irq)), iosapic_addr + IO_SAPIC_REG_SELECT); + low32 = readl(iosapic_addr + IO_SAPIC_WINDOW); - low32 &= ~(1 << IO_SAPIC_MASK_SHIFT); /* Zero only the mask bit */ - writel(low32, iosapic_addr + IO_SAPIC_WINDOW); + low32 |= (1 << IO_SAPIC_MASK_SHIFT); /* Zero only the mask bit */ + writel(low32, iosapic_addr + IO_SAPIC_WINDOW); + } + spin_unlock_irqrestore(&iosapic_lock, flags); } - static void -disable_pin (unsigned int pin, unsigned long iosapic_addr) +unmask_irq (unsigned int irq) { - int low32; + unsigned long flags, iosapic_addr = iosapic_addr(irq); + u32 low32; - writel(IO_SAPIC_RTE_LOW(pin), iosapic_addr + IO_SAPIC_REG_SELECT); - low32 = readl(iosapic_addr + IO_SAPIC_WINDOW); + spin_lock_irqsave(&iosapic_lock, flags); + { + writel(IO_SAPIC_RTE_LOW(iosapic_pin(irq)), iosapic_addr + IO_SAPIC_REG_SELECT); + low32 = readl(iosapic_addr + IO_SAPIC_WINDOW); - low32 |= (1 << IO_SAPIC_MASK_SHIFT); /* Set only the mask bit */ - writel(low32, iosapic_addr + IO_SAPIC_WINDOW); + low32 &= ~(1 << IO_SAPIC_MASK_SHIFT); /* Zero only the mask bit */ + writel(low32, iosapic_addr + IO_SAPIC_WINDOW); + } + spin_unlock_irqrestore(&iosapic_lock, flags); +} + + +static void +iosapic_set_affinity (unsigned int irq, unsigned long mask) +{ + printk("iosapic_set_affinity: not implemented yet\n"); } -#define iosapic_shutdown_irq iosapic_disable_irq +/* + * Handlers for level-triggered interrupts. + */ static unsigned int -iosapic_startup_irq (unsigned int irq) +iosapic_startup_level_irq (unsigned int irq) { - int pin; - - pin = iosapic_pin(irq); - if (pin < 0) - /* happens during irq auto probing... */ - return 0; - set_rte(iosapic_addr(irq), pin, iosapic_polarity(irq), iosapic_trigger(irq), - iosapic_dmode(irq), (ia64_get_lid() >> 16) & 0xffff, irq); - enable_pin(pin, iosapic_addr(irq)); + unmask_irq(irq); return 0; } static void -iosapic_enable_irq (unsigned int irq) +iosapic_end_level_irq (unsigned int irq) { - int pin = iosapic_pin(irq); + writel(irq, iosapic_addr(irq) + IO_SAPIC_EOI); +} - if (pin < 0) - /* happens during irq auto probing... */ - return; - enable_pin(pin, iosapic_addr(irq)); +#define iosapic_shutdown_level_irq mask_irq +#define iosapic_enable_level_irq unmask_irq +#define iosapic_disable_level_irq mask_irq +#define iosapic_ack_level_irq nop + +struct hw_interrupt_type irq_type_iosapic_level = { + typename: "IO-SAPIC-level", + startup: iosapic_startup_level_irq, + shutdown: iosapic_shutdown_level_irq, + enable: iosapic_enable_level_irq, + disable: iosapic_disable_level_irq, + ack: iosapic_ack_level_irq, + end: iosapic_end_level_irq, + set_affinity: iosapic_set_affinity +}; + +/* + * Handlers for edge-triggered interrupts. + */ + +static unsigned int +iosapic_startup_edge_irq (unsigned int irq) +{ + unmask_irq(irq); + /* + * IOSAPIC simply drops interrupts pended while the + * corresponding pin was masked, so we can't know if an + * interrupt is pending already. Let's hope not... + */ + return 0; } static void -iosapic_disable_irq (unsigned int irq) +iosapic_ack_edge_irq (unsigned int irq) { - int pin = iosapic_pin(irq); - - if (pin < 0) - return; - disable_pin(pin, iosapic_addr(irq)); + /* + * Once we have recorded IRQ_PENDING already, we can mask the + * interrupt for real. This prevents IRQ storms from unhandled + * devices. + */ + if ((irq_desc[irq].status & (IRQ_PENDING | IRQ_DISABLED)) == (IRQ_PENDING | IRQ_DISABLED)) + mask_irq(irq); } +#define iosapic_enable_edge_irq unmask_irq +#define iosapic_disable_edge_irq nop +#define iosapic_end_edge_irq nop + +struct hw_interrupt_type irq_type_iosapic_edge = { + typename: "IO-SAPIC-edge", + startup: iosapic_startup_edge_irq, + shutdown: iosapic_disable_edge_irq, + enable: iosapic_enable_edge_irq, + disable: iosapic_disable_edge_irq, + ack: iosapic_ack_edge_irq, + end: iosapic_end_edge_irq, + set_affinity: iosapic_set_affinity +}; + unsigned int -iosapic_version(unsigned long base_addr) +iosapic_version (unsigned long base_addr) { /* * IOSAPIC Version Register return 32 bit structure like: @@ -310,99 +215,19 @@ iosapic_version(unsigned long base_addr) return readl(IO_SAPIC_WINDOW + base_addr); } -static void -iosapic_ack_irq (unsigned int irq) -{ -} - -static void -iosapic_end_irq (unsigned int irq) -{ - if (iosapic_trigger(irq) == IO_SAPIC_LEVEL) /* ACK Level trigger interrupts */ - writel(irq, iosapic_addr(irq) + IO_SAPIC_EOI); -} - -static void -iosapic_set_affinity (unsigned int irq, unsigned long mask) -{ - printk("iosapic_set_affinity: not implemented yet\n"); -} - void iosapic_init (unsigned long address) { - int i; -#ifdef CONFIG_IA64_IRQ_ACPI + struct hw_interrupt_type *irq_type; struct pci_vector_struct *vectors; - int irq; -#else - int vector; -#endif + int i, irq; - /* - * Disable the compatibility mode interrupts (8259 style), needs IN/OUT support - * enabled. - */ - outb(0xff, 0xA1); - outb(0xff, 0x21); - -#if defined(CONFIG_IA64_SOFTSDV_HACKS) - memset(iosapic_vector, 0x0, sizeof(iosapic_vector)); - for (i = 0; i < NR_IRQS; i++) { - iosapic_pin(i) = 0xff; - iosapic_addr(i) = (unsigned long) ioremap(address, 0); - } - /* XXX this should come from systab or some such: */ -# if 0 - /* this doesn't look right --davidm 00/03/07 */ - iosapic_pin(TIMER_IRQ) = 5; /* System Clock Interrupt */ -# endif - iosapic_pin(0x40) = 3; /* Keyboard */ - iosapic_pin(0x92) = 9; /* COM1 Serial Port */ - iosapic_pin(0x80) = 4; /* Periodic Interrupt */ - iosapic_pin(0xc0) = 2; /* Mouse */ - iosapic_pin(0xe0) = 1; /* IDE Disk */ - iosapic_pin(0xf0) = 6; /* E-IDE CDROM */ - iosapic_pin(0xa0) = 10; /* Real PCI Interrupt */ -#elif !defined(CONFIG_IA64_IRQ_ACPI) - /* - * For systems where the routing info in ACPI is - * unavailable/wrong, use the intr_routing information to - * initialize the iosapic array - */ - i = -1; - while (intr_routing[++i].srcbus != 0xff) { - if (intr_routing[i].srcbus == BUS_ISA) { - vector = isa_irq_to_vector(intr_routing[i].srcbusirq); - } else if (intr_routing[i].srcbus == BUS_PCI) { - vector = intr_routing[i].iosapic_pin; - } else { - printk("unknown bus type %d for intr_routing[%d]\n", - intr_routing[i].srcbus, i); - continue; - } - iosapic_pin(vector) = intr_routing[i].iosapic_pin; - iosapic_dmode(vector) = intr_routing[i].mode; - iosapic_polarity(vector) = intr_routing[i].polarity; - iosapic_trigger(vector) = intr_routing[i].trigger; -# ifdef DEBUG_IRQ_ROUTING - printk("irq[0x%x(0x%x)]:0x%x, %d, %d, %d\n", vector, intr_routing[i].srcbusirq, - iosapic_pin(vector), iosapic_dmode(vector), iosapic_polarity(vector), - iosapic_trigger(vector)); -# endif - } -#else /* !defined(CONFIG_IA64_SOFTSDV_HACKS) && defined(CONFIG_IA64_IRQ_ACPI) */ /* - * Map the legacy ISA devices into the IOAPIC data; We'll override these - * later with data from the ACPI Interrupt Source Override table. - * - * Huh, the Lion w/ FPSWA firmware has entries for _all_ of the legacy IRQs, - * including those that are not different from PC/AT standard. I don't know - * if this is a bug in the other firmware or not. I'm going to leave this code - * here, so that this works on BigSur but will go ask Intel. --wfd 2000-Jan-19 - * + * Map the legacy ISA devices into the IOSAPIC data. Some of + * these may get reprogrammed later on with data from the ACPI + * Interrupt Source Override table. */ - for (i =0 ; i < 16; i++) { + for (i = 0; i < 16; i++) { irq = isa_irq_to_vector(i); iosapic_pin(irq) = i; iosapic_bus(irq) = BUS_ISA; @@ -445,41 +270,37 @@ iosapic_init (unsigned long address) irq, iosapic_pin(irq)); #endif } -#endif /* !CONFIG_IA64_IRQ_ACPI */ -} -struct hw_interrupt_type irq_type_iosapic = { - typename: "IOSAPIC", - startup: iosapic_startup_irq, - shutdown: iosapic_shutdown_irq, - enable: iosapic_enable_irq, - disable: iosapic_disable_irq, - ack: iosapic_ack_irq, - end: iosapic_end_irq, - set_affinity: iosapic_set_affinity -}; + for (i = 0; i < NR_IRQS; ++i) { + if (iosapic_pin(i) != -1) { + if (iosapic_trigger(i) == IO_SAPIC_LEVEL) + irq_type = &irq_type_iosapic_level; + else + irq_type = &irq_type_iosapic_edge; + if (irq_desc[i].handler != &no_irq_type) + printk("dig_irq_init: warning: changing vector %d from %s to %s\n", + i, irq_desc[i].handler->typename, + irq_type->typename); + irq_desc[i].handler = irq_type; + + /* program the IOSAPIC routing table: */ + set_rte(iosapic_addr(i), iosapic_pin(i), iosapic_polarity(i), + iosapic_trigger(i), iosapic_dmode(i), + (ia64_get_lid() >> 16) & 0xffff, i); + } + } +} void dig_irq_init (void) { - int i; - /* - * Claim all non-legacy irq vectors as ours unless they're - * claimed by someone else already (e.g., timer or IPI are - * handled internally). + * Disable the compatibility mode interrupts (8259 style), needs IN/OUT support + * enabled. */ -#if 0 - for (i = IA64_MIN_VECTORED_IRQ; i <= IA64_MAX_VECTORED_IRQ; ++i) { - if (irq_desc[i].handler == &no_irq_type) - irq_desc[i].handler = &irq_type_iosapic; - } -#else - for (i = 0; i <= IA64_MAX_VECTORED_IRQ; ++i) { - if (irq_desc[i].handler == &no_irq_type) - irq_desc[i].handler = &irq_type_iosapic; - } -#endif + outb(0xff, 0xA1); + outb(0xff, 0x21); + #ifndef CONFIG_IA64_DIG iosapic_init(IO_SAPIC_DEFAULT_ADDR); #endif diff --git a/arch/ia64/dig/setup.c b/arch/ia64/dig/setup.c index 6ae40319d..133f817a1 100644 --- a/arch/ia64/dig/setup.c +++ b/arch/ia64/dig/setup.c @@ -47,17 +47,11 @@ dig_setup (char **cmdline_p) unsigned int orig_x, orig_y, num_cols, num_rows, font_height; /* - * This assumes that the EFI partition is physical disk 1 - * partition 1 and the Linux root disk is physical disk 1 - * partition 2. + * Default to /dev/sda2. This assumes that the EFI partition + * is physical disk 1 partition 1 and the Linux root disk is + * physical disk 1 partition 2. */ -#ifdef CONFIG_IA64_LION_HACKS - /* default to /dev/sda2 on Lion... */ ROOT_DEV = to_kdev_t(0x0802); /* default to second partition on first drive */ -#else - /* default to /dev/dha2 on BigSur... */ - ROOT_DEV = to_kdev_t(0x0302); /* default to second partition on first drive */ -#endif #ifdef CONFIG_SMP init_smp_config(); diff --git a/arch/ia64/hp/Makefile b/arch/ia64/hp/Makefile index 64899f4be..458269e0a 100644 --- a/arch/ia64/hp/Makefile +++ b/arch/ia64/hp/Makefile @@ -10,7 +10,7 @@ all: hp.a O_TARGET = hp.a O_OBJS = hpsim_console.o hpsim_irq.o hpsim_setup.o -ifeq ($(CONFIG_IA64_GENERIC),y) +ifdef CONFIG_IA64_GENERIC O_OBJS += hpsim_machvec.o endif diff --git a/arch/ia64/ia32/Makefile b/arch/ia64/ia32/Makefile index 82017941c..1b18cca58 100644 --- a/arch/ia64/ia32/Makefile +++ b/arch/ia64/ia32/Makefile @@ -10,7 +10,7 @@ all: ia32.o O_TARGET := ia32.o -O_OBJS := ia32_entry.o ia32_signal.o sys_ia32.o ia32_support.o binfmt_elf32.o +O_OBJS := ia32_entry.o sys_ia32.o ia32_signal.o ia32_support.o ia32_traps.o binfmt_elf32.o clean:: diff --git a/arch/ia64/ia32/binfmt_elf32.c b/arch/ia64/ia32/binfmt_elf32.c index a99983681..6f702df14 100644 --- a/arch/ia64/ia32/binfmt_elf32.c +++ b/arch/ia64/ia32/binfmt_elf32.c @@ -134,6 +134,19 @@ void ia64_elf32_init(struct pt_regs *regs) regs->cr_ipsr &= ~IA64_PSR_AC; regs->loadrs = 0; + /* + * According to the ABI %edx points to an `atexit' handler. + * Since we don't have one we'll set it to 0 and initialize + * all the other registers just to make things more deterministic, + * ala the i386 implementation. + */ + regs->r8 = 0; /* %eax */ + regs->r11 = 0; /* %ebx */ + regs->r9 = 0; /* %ecx */ + regs->r10 = 0; /* %edx */ + regs->r13 = 0; /* %ebp */ + regs->r14 = 0; /* %esi */ + regs->r15 = 0; /* %edi */ } #undef STACK_TOP diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S index bd7b0517b..ff27a02ce 100644 --- a/arch/ia64/ia32/ia32_entry.S +++ b/arch/ia64/ia32/ia32_entry.S @@ -1,14 +1,55 @@ #include <asm/offsets.h> #include <asm/signal.h> + // + // Get possibly unaligned sigmask argument into an aligned + // kernel buffer + .text + .proc ia32_rt_sigsuspend + .global ia32_rt_sigsuspend +ia32_rt_sigsuspend: + + // We'll cheat and not do an alloc here since we are ultimately + // going to do a simple branch to the IA64 sys_rt_sigsuspend. + // r32 is still the first argument which is the signal mask. + // We copy this 4-byte aligned value to an 8-byte aligned buffer + // in the task structure and then jump to the IA64 code. + + mov r8=r0 // no memory access errors yet + add r10=4,r32 + ;; +1: + ld4 r2=[r32] // get first half of sigmask + ld4 r3=[r10] // get second half of sigmask +2: + cmp.lt p6,p0=r8,r0 // check memory access + ;; +(p6) br.ret.sptk.many rp // it failed + + adds r32=IA64_TASK_THREAD_SIGMASK_OFFSET,r13 + adds r10=IA64_TASK_THREAD_SIGMASK_OFFSET+4,r13 + ;; + st4 [r32]=r2 + st4 [r10]=r3 + br.cond.sptk.many sys_rt_sigsuspend + + .section __ex_table,"a" + data4 @gprel(1b) + data4 (2b-1b)|1 + .previous + + + .endp ia32_rt_sigsuspend + .global ia32_ret_from_syscall - .proc ia64_ret_from_syscall + .proc ia32_ret_from_syscall ia32_ret_from_syscall: cmp.ge p6,p7=r8,r0 // syscall executed successfully? adds r2=IA64_PT_REGS_R8_OFFSET+16,sp // r2 = &pt_regs.r8 ;; st8 [r2]=r8 // store return value in slot for r8 br.cond.sptk.few ia64_leave_kernel + .endp ia32_ret_from_syscall // // Invoke a system call, but do some tracing before and after the call. @@ -35,10 +76,21 @@ ia32_trace_syscall: .endp ia32_trace_syscall .align 16 + .global sys32_vfork + .proc sys32_vfork +sys32_vfork: + alloc r16=ar.pfs,2,2,3,0;; + mov out0=IA64_CLONE_VFORK|IA64_CLONE_VM|SIGCHLD // out0 = clone_flags + br.cond.sptk.few .fork1 // do the work + .endp sys32_vfork + + .align 16 .global sys32_fork .proc sys32_fork sys32_fork: alloc r16=ar.pfs,2,2,3,0;; + mov out0=SIGCHLD // out0 = clone_flags +.fork1: movl r28=1f mov loc1=rp br.cond.sptk.many save_switch_stack @@ -46,7 +98,6 @@ sys32_fork: mov loc0=r16 // save ar.pfs across do_fork adds out2=IA64_SWITCH_STACK_SIZE+16,sp adds r2=IA64_SWITCH_STACK_SIZE+IA64_PT_REGS_R12_OFFSET+16,sp - mov out0=SIGCHLD // out0 = clone_flags ;; ld8 out1=[r2] // fetch usp from pt_regs.r12 br.call.sptk.few rp=do_fork @@ -88,7 +139,7 @@ ia32_syscall_table: data8 sys_setuid data8 sys_getuid data8 sys_ni_syscall /* sys_stime is not supported on IA64 */ /* 25 */ - data8 sys_ptrace + data8 sys32_ptrace data8 sys32_alarm data8 sys_ni_syscall data8 sys_ni_syscall @@ -105,7 +156,7 @@ ia32_syscall_table: data8 sys_rmdir /* 40 */ data8 sys_dup data8 sys32_pipe - data8 sys_times + data8 sys32_times data8 sys_ni_syscall /* old prof syscall holder */ data8 sys_brk /* 45 */ data8 sys_setgid @@ -139,7 +190,7 @@ ia32_syscall_table: data8 sys_sethostname data8 sys32_setrlimit /* 75 */ data8 sys32_getrlimit - data8 sys_getrusage + data8 sys32_getrusage data8 sys32_gettimeofday data8 sys32_settimeofday data8 sys_getgroups /* 80 */ @@ -241,7 +292,7 @@ ia32_syscall_table: data8 sys_rt_sigpending data8 sys_rt_sigtimedwait data8 sys_rt_sigqueueinfo - data8 sys_rt_sigsuspend + data8 ia32_rt_sigsuspend data8 sys_pread /* 180 */ data8 sys_pwrite data8 sys_chown diff --git a/arch/ia64/ia32/ia32_signal.c b/arch/ia64/ia32/ia32_signal.c index 2c2c53741..83e6c9e61 100644 --- a/arch/ia64/ia32/ia32_signal.c +++ b/arch/ia64/ia32/ia32_signal.c @@ -94,7 +94,9 @@ setup_sigcontext_ia32(struct sigcontext_ia32 *sc, struct _fpstate_ia32 *fpstate, err |= __put_user(tmp ? fpstate : NULL, &sc->fpstate); /* non-iBCS2 extensions.. */ +#endif err |= __put_user(mask, &sc->oldmask); +#if 0 err |= __put_user(current->tss.cr2, &sc->cr2); #endif @@ -196,7 +198,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size) return (void *)((esp - frame_size) & -8ul); } -static void +static int setup_frame_ia32(int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs * regs) { @@ -247,20 +249,21 @@ setup_frame_ia32(int sig, struct k_sigaction *ka, sigset_t *set, regs->eflags &= ~TF_MASK; #endif -#if 1 - printk("SIG deliver (%s:%d): sp=%p pc=%lx ra=%x\n", - current->comm, current->pid, frame, regs->cr_iip, frame->pretcode); +#if 0 + printk("SIG deliver (%s:%d): sig=%d sp=%p pc=%lx ra=%x\n", + current->comm, current->pid, sig, frame, regs->cr_iip, frame->pretcode); #endif - return; + return 1; give_sigsegv: if (sig == SIGSEGV) ka->sa.sa_handler = SIG_DFL; force_sig(SIGSEGV, current); + return 0; } -static void +static int setup_rt_frame_ia32(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs * regs) { @@ -316,29 +319,29 @@ setup_rt_frame_ia32(int sig, struct k_sigaction *ka, siginfo_t *info, regs->eflags &= ~TF_MASK; #endif -#if 1 +#if 0 printk("SIG deliver (%s:%d): sp=%p pc=%lx ra=%x\n", current->comm, current->pid, frame, regs->cr_iip, frame->pretcode); #endif - return; + return 1; give_sigsegv: if (sig == SIGSEGV) ka->sa.sa_handler = SIG_DFL; force_sig(SIGSEGV, current); + return 0; } -long +int ia32_setup_frame1 (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { /* Set up the stack frame */ if (ka->sa.sa_flags & SA_SIGINFO) - setup_rt_frame_ia32(sig, ka, info, set, regs); + return(setup_rt_frame_ia32(sig, ka, info, set, regs)); else - setup_frame_ia32(sig, ka, set, regs); - + return(setup_frame_ia32(sig, ka, set, regs)); } asmlinkage int diff --git a/arch/ia64/ia32/ia32_traps.c b/arch/ia64/ia32/ia32_traps.c new file mode 100644 index 000000000..de99a65b3 --- /dev/null +++ b/arch/ia64/ia32/ia32_traps.c @@ -0,0 +1,47 @@ +#include <linux/kernel.h> +#include <linux/sched.h> + +#include <asm/ia32.h> +#include <asm/ptrace.h> + +int +ia32_exception (struct pt_regs *regs, unsigned long isr) +{ + struct siginfo siginfo; + + switch ((isr >> 16) & 0xff) { + case 1: + case 2: + if (isr == 0) + siginfo.si_code = TRAP_TRACE; + else if (isr & 0x4) + siginfo.si_code = TRAP_BRANCH; + else + siginfo.si_code = TRAP_BRKPT; + break; + + case 3: + siginfo.si_code = TRAP_BRKPT; + break; + + case 0: /* Divide fault */ + case 4: /* Overflow */ + case 5: /* Bounds fault */ + case 6: /* Invalid Op-code */ + case 7: /* FP DNA */ + case 8: /* Double Fault */ + case 9: /* Invalid TSS */ + case 11: /* Segment not present */ + case 12: /* Stack fault */ + case 13: /* General Protection Fault */ + case 16: /* Pending FP error */ + case 17: /* Alignment check */ + case 19: /* SSE Numeric error */ + default: + return -1; + } + siginfo.si_signo = SIGTRAP; + siginfo.si_errno = 0; + send_sig_info(SIGTRAP, &siginfo, current); + return 0; +} diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c index 00eca716d..2077abe93 100644 --- a/arch/ia64/ia32/sys_ia32.c +++ b/arch/ia64/ia32/sys_ia32.c @@ -58,32 +58,6 @@ #define A(__x) ((unsigned long)(__x)) #define AA(__x) ((unsigned long)(__x)) -/* - * This is trivial, and on the face of it looks like it - * could equally well be done in user mode. - * - * Not so, for quite unobvious reasons - register pressure. - * In user mode vfork() cannot have a stack frame, and if - * done by calling the "clone()" system call directly, you - * do not have enough call-clobbered registers to hold all - * the information you need. - */ -asmlinkage int sys32_vfork( -int dummy0, -int dummy1, -int dummy2, -int dummy3, -int dummy4, -int dummy5, -int dummy6, -int dummy7, -int stack) -{ - struct pt_regs *regs = (struct pt_regs *)&stack; - - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->r12, regs); -} - static int nargs(unsigned int arg, char **ap) { @@ -842,82 +816,6 @@ asmlinkage int old_select(struct sel_arg_struct *arg) return sys32_select(a.n, a.inp, a.outp, a.exp, a.tvp); } -struct rusage32 { - struct timeval32 ru_utime; - struct timeval32 ru_stime; - int ru_maxrss; - int ru_ixrss; - int ru_idrss; - int ru_isrss; - int ru_minflt; - int ru_majflt; - int ru_nswap; - int ru_inblock; - int ru_oublock; - int ru_msgsnd; - int ru_msgrcv; - int ru_nsignals; - int ru_nvcsw; - int ru_nivcsw; -}; - -static int -put_rusage (struct rusage32 *ru, struct rusage *r) -{ - int err; - - err = put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec); - err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec); - err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec); - err |= __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec); - err |= __put_user (r->ru_maxrss, &ru->ru_maxrss); - err |= __put_user (r->ru_ixrss, &ru->ru_ixrss); - err |= __put_user (r->ru_idrss, &ru->ru_idrss); - err |= __put_user (r->ru_isrss, &ru->ru_isrss); - err |= __put_user (r->ru_minflt, &ru->ru_minflt); - err |= __put_user (r->ru_majflt, &ru->ru_majflt); - err |= __put_user (r->ru_nswap, &ru->ru_nswap); - err |= __put_user (r->ru_inblock, &ru->ru_inblock); - err |= __put_user (r->ru_oublock, &ru->ru_oublock); - err |= __put_user (r->ru_msgsnd, &ru->ru_msgsnd); - err |= __put_user (r->ru_msgrcv, &ru->ru_msgrcv); - err |= __put_user (r->ru_nsignals, &ru->ru_nsignals); - err |= __put_user (r->ru_nvcsw, &ru->ru_nvcsw); - err |= __put_user (r->ru_nivcsw, &ru->ru_nivcsw); - return err; -} - -extern asmlinkage int sys_wait4(pid_t pid,unsigned int * stat_addr, - int options, struct rusage * ru); - -asmlinkage int -sys32_wait4(__kernel_pid_t32 pid, unsigned int *stat_addr, int options, - struct rusage32 *ru) -{ - if (!ru) - return sys_wait4(pid, stat_addr, options, NULL); - else { - struct rusage r; - int ret; - unsigned int status; - mm_segment_t old_fs = get_fs(); - - set_fs (KERNEL_DS); - ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r); - set_fs (old_fs); - if (put_rusage (ru, &r)) return -EFAULT; - if (stat_addr && put_user (status, stat_addr)) - return -EFAULT; - return ret; - } -} - -asmlinkage int -sys32_waitpid(__kernel_pid_t32 pid, unsigned int *stat_addr, int options) -{ - return sys32_wait4(pid, stat_addr, options, NULL); -} - struct timespec32 { int tv_sec; int tv_nsec; @@ -1586,65 +1484,63 @@ do_sys32_semctl(int first, int second, int third, void *uptr) { union semun fourth; u32 pad; - int err = -EINVAL; + int err, err2; + struct semid64_ds s; + struct semid_ds32 *usp; + mm_segment_t old_fs; if (!uptr) - goto out; + return -EINVAL; err = -EFAULT; if (get_user (pad, (u32 *)uptr)) - goto out; + return err; if(third == SETVAL) fourth.val = (int)pad; else fourth.__pad = (void *)A(pad); - if (IPCOP_MASK (third) & - (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SEM_INFO) | - IPCOP_MASK (GETVAL) | IPCOP_MASK (GETPID) | - IPCOP_MASK (GETNCNT) | IPCOP_MASK (GETZCNT) | - IPCOP_MASK (GETALL) | IPCOP_MASK (SETALL) | - IPCOP_MASK (IPC_RMID))) { + switch (third) { + + case IPC_INFO: + case IPC_RMID: + case IPC_SET: + case SEM_INFO: + case GETVAL: + case GETPID: + case GETNCNT: + case GETZCNT: + case GETALL: + case SETVAL: + case SETALL: err = sys_semctl (first, second, third, fourth); - } else { - struct semid_ds s; - struct semid_ds32 *usp = (struct semid_ds32 *)A(pad); - mm_segment_t old_fs; - int need_back_translation; - - if (third == IPC_SET) { - err = get_user (s.sem_perm.uid, &usp->sem_perm.uid); - err |= __get_user(s.sem_perm.gid, &usp->sem_perm.gid); - err |= __get_user(s.sem_perm.mode, &usp->sem_perm.mode); - if (err) - goto out; - fourth.__pad = &s; - } - need_back_translation = - (IPCOP_MASK (third) & - (IPCOP_MASK (SEM_STAT) | IPCOP_MASK (IPC_STAT))) != 0; - if (need_back_translation) - fourth.__pad = &s; + break; + + case IPC_STAT: + case SEM_STAT: + usp = (struct semid_ds32 *)A(pad); + fourth.__pad = &s; old_fs = get_fs (); set_fs (KERNEL_DS); err = sys_semctl (first, second, third, fourth); set_fs (old_fs); - if (need_back_translation) { - int err2 = put_user(s.sem_perm.key, &usp->sem_perm.key); - err2 |= __put_user(s.sem_perm.uid, &usp->sem_perm.uid); - err2 |= __put_user(s.sem_perm.gid, &usp->sem_perm.gid); - err2 |= __put_user(s.sem_perm.cuid, - &usp->sem_perm.cuid); - err2 |= __put_user (s.sem_perm.cgid, - &usp->sem_perm.cgid); - err2 |= __put_user (s.sem_perm.mode, - &usp->sem_perm.mode); - err2 |= __put_user (s.sem_perm.seq, &usp->sem_perm.seq); - err2 |= __put_user (s.sem_otime, &usp->sem_otime); - err2 |= __put_user (s.sem_ctime, &usp->sem_ctime); - err2 |= __put_user (s.sem_nsems, &usp->sem_nsems); - if (err2) err = -EFAULT; - } + err2 = put_user(s.sem_perm.key, &usp->sem_perm.key); + err2 |= __put_user(s.sem_perm.uid, &usp->sem_perm.uid); + err2 |= __put_user(s.sem_perm.gid, &usp->sem_perm.gid); + err2 |= __put_user(s.sem_perm.cuid, + &usp->sem_perm.cuid); + err2 |= __put_user (s.sem_perm.cgid, + &usp->sem_perm.cgid); + err2 |= __put_user (s.sem_perm.mode, + &usp->sem_perm.mode); + err2 |= __put_user (s.sem_perm.seq, &usp->sem_perm.seq); + err2 |= __put_user (s.sem_otime, &usp->sem_otime); + err2 |= __put_user (s.sem_ctime, &usp->sem_ctime); + err2 |= __put_user (s.sem_nsems, &usp->sem_nsems); + if (err2) + err = -EFAULT; + break; + } -out: + return err; } @@ -1717,52 +1613,60 @@ out: static int do_sys32_msgctl (int first, int second, void *uptr) { - int err; + int err, err2; + struct msqid_ds m; + struct msqid64_ds m64; + struct msqid_ds32 *up = (struct msqid_ds32 *)uptr; + mm_segment_t old_fs; + + switch (second) { - if (IPCOP_MASK (second) & - (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (MSG_INFO) | - IPCOP_MASK (IPC_RMID))) { + case IPC_INFO: + case IPC_RMID: + case MSG_INFO: err = sys_msgctl (first, second, (struct msqid_ds *)uptr); - } else { - struct msqid_ds m; - struct msqid_ds32 *up = (struct msqid_ds32 *)uptr; - mm_segment_t old_fs; - - if (second == IPC_SET) { - err = get_user (m.msg_perm.uid, &up->msg_perm.uid); - err |= __get_user (m.msg_perm.gid, &up->msg_perm.gid); - err |= __get_user (m.msg_perm.mode, &up->msg_perm.mode); - err |= __get_user (m.msg_qbytes, &up->msg_qbytes); - if (err) - goto out; - } + break; + + case IPC_SET: + err = get_user (m.msg_perm.uid, &up->msg_perm.uid); + err |= __get_user (m.msg_perm.gid, &up->msg_perm.gid); + err |= __get_user (m.msg_perm.mode, &up->msg_perm.mode); + err |= __get_user (m.msg_qbytes, &up->msg_qbytes); + if (err) + break; old_fs = get_fs (); set_fs (KERNEL_DS); err = sys_msgctl (first, second, &m); set_fs (old_fs); - if (IPCOP_MASK (second) & - (IPCOP_MASK (MSG_STAT) | IPCOP_MASK (IPC_STAT))) { - int err2 = put_user (m.msg_perm.key, &up->msg_perm.key); - err2 |= __put_user(m.msg_perm.uid, &up->msg_perm.uid); - err2 |= __put_user(m.msg_perm.gid, &up->msg_perm.gid); - err2 |= __put_user(m.msg_perm.cuid, &up->msg_perm.cuid); - err2 |= __put_user(m.msg_perm.cgid, &up->msg_perm.cgid); - err2 |= __put_user(m.msg_perm.mode, &up->msg_perm.mode); - err2 |= __put_user(m.msg_perm.seq, &up->msg_perm.seq); - err2 |= __put_user(m.msg_stime, &up->msg_stime); - err2 |= __put_user(m.msg_rtime, &up->msg_rtime); - err2 |= __put_user(m.msg_ctime, &up->msg_ctime); - err2 |= __put_user(m.msg_cbytes, &up->msg_cbytes); - err2 |= __put_user(m.msg_qnum, &up->msg_qnum); - err2 |= __put_user(m.msg_qbytes, &up->msg_qbytes); - err2 |= __put_user(m.msg_lspid, &up->msg_lspid); - err2 |= __put_user(m.msg_lrpid, &up->msg_lrpid); - if (err2) - err = -EFAULT; - } + break; + + case IPC_STAT: + case MSG_STAT: + old_fs = get_fs (); + set_fs (KERNEL_DS); + err = sys_msgctl (first, second, &m64); + set_fs (old_fs); + err2 = put_user (m64.msg_perm.key, &up->msg_perm.key); + err2 |= __put_user(m64.msg_perm.uid, &up->msg_perm.uid); + err2 |= __put_user(m64.msg_perm.gid, &up->msg_perm.gid); + err2 |= __put_user(m64.msg_perm.cuid, &up->msg_perm.cuid); + err2 |= __put_user(m64.msg_perm.cgid, &up->msg_perm.cgid); + err2 |= __put_user(m64.msg_perm.mode, &up->msg_perm.mode); + err2 |= __put_user(m64.msg_perm.seq, &up->msg_perm.seq); + err2 |= __put_user(m64.msg_stime, &up->msg_stime); + err2 |= __put_user(m64.msg_rtime, &up->msg_rtime); + err2 |= __put_user(m64.msg_ctime, &up->msg_ctime); + err2 |= __put_user(m64.msg_cbytes, &up->msg_cbytes); + err2 |= __put_user(m64.msg_qnum, &up->msg_qnum); + err2 |= __put_user(m64.msg_qbytes, &up->msg_qbytes); + err2 |= __put_user(m64.msg_lspid, &up->msg_lspid); + err2 |= __put_user(m64.msg_lrpid, &up->msg_lrpid); + if (err2) + err = -EFAULT; + break; + } -out: return err; } @@ -1774,85 +1678,98 @@ do_sys32_shmat (int first, int second, int third, int version, void *uptr) int err = -EINVAL; if (version == 1) - goto out; + return err; err = sys_shmat (first, uptr, second, &raddr); if (err) - goto out; + return err; err = put_user (raddr, uaddr); -out: return err; } static int do_sys32_shmctl (int first, int second, void *uptr) { - int err; - - if (IPCOP_MASK (second) & - (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SHM_LOCK) - | IPCOP_MASK (SHM_UNLOCK) | IPCOP_MASK (IPC_RMID))) { + int err = -EFAULT, err2; + struct shmid_ds s; + struct shmid64_ds s64; + struct shmid_ds32 *up = (struct shmid_ds32 *)uptr; + mm_segment_t old_fs; + struct shm_info32 { + int used_ids; + u32 shm_tot, shm_rss, shm_swp; + u32 swap_attempts, swap_successes; + } *uip = (struct shm_info32 *)uptr; + struct shm_info si; + + switch (second) { + + case IPC_INFO: + case IPC_RMID: + case SHM_LOCK: + case SHM_UNLOCK: err = sys_shmctl (first, second, (struct shmid_ds *)uptr); - } else { - struct shmid_ds s; - struct shmid_ds32 *up = (struct shmid_ds32 *)uptr; - mm_segment_t old_fs; - - if (second == IPC_SET) { - err = get_user (s.shm_perm.uid, &up->shm_perm.uid); - err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid); - err |= __get_user (s.shm_perm.mode, &up->shm_perm.mode); - if (err) - goto out; - } + break; + case IPC_SET: + err = get_user (s.shm_perm.uid, &up->shm_perm.uid); + err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid); + err |= __get_user (s.shm_perm.mode, &up->shm_perm.mode); + if (err) + break; old_fs = get_fs (); set_fs (KERNEL_DS); err = sys_shmctl (first, second, &s); set_fs (old_fs); + break; + + case IPC_STAT: + case SHM_STAT: + old_fs = get_fs (); + set_fs (KERNEL_DS); + err = sys_shmctl (first, second, &s64); + set_fs (old_fs); if (err < 0) - goto out; + break; + err2 = put_user (s64.shm_perm.key, &up->shm_perm.key); + err2 |= __put_user (s64.shm_perm.uid, &up->shm_perm.uid); + err2 |= __put_user (s64.shm_perm.gid, &up->shm_perm.gid); + err2 |= __put_user (s64.shm_perm.cuid, + &up->shm_perm.cuid); + err2 |= __put_user (s64.shm_perm.cgid, + &up->shm_perm.cgid); + err2 |= __put_user (s64.shm_perm.mode, + &up->shm_perm.mode); + err2 |= __put_user (s64.shm_perm.seq, &up->shm_perm.seq); + err2 |= __put_user (s64.shm_atime, &up->shm_atime); + err2 |= __put_user (s64.shm_dtime, &up->shm_dtime); + err2 |= __put_user (s64.shm_ctime, &up->shm_ctime); + err2 |= __put_user (s64.shm_segsz, &up->shm_segsz); + err2 |= __put_user (s64.shm_nattch, &up->shm_nattch); + err2 |= __put_user (s64.shm_cpid, &up->shm_cpid); + err2 |= __put_user (s64.shm_lpid, &up->shm_lpid); + if (err2) + err = -EFAULT; + break; + + case SHM_INFO: + old_fs = get_fs (); + set_fs (KERNEL_DS); + err = sys_shmctl (first, second, &si); + set_fs (old_fs); + if (err < 0) + break; + err2 = put_user (si.used_ids, &uip->used_ids); + err2 |= __put_user (si.shm_tot, &uip->shm_tot); + err2 |= __put_user (si.shm_rss, &uip->shm_rss); + err2 |= __put_user (si.shm_swp, &uip->shm_swp); + err2 |= __put_user (si.swap_attempts, + &uip->swap_attempts); + err2 |= __put_user (si.swap_successes, + &uip->swap_successes); + if (err2) + err = -EFAULT; + break; - /* Mask it even in this case so it becomes a CSE. */ - if (second == SHM_INFO) { - struct shm_info32 { - int used_ids; - u32 shm_tot, shm_rss, shm_swp; - u32 swap_attempts, swap_successes; - } *uip = (struct shm_info32 *)uptr; - struct shm_info *kp = (struct shm_info *)&s; - int err2 = put_user (kp->used_ids, &uip->used_ids); - err2 |= __put_user (kp->shm_tot, &uip->shm_tot); - err2 |= __put_user (kp->shm_rss, &uip->shm_rss); - err2 |= __put_user (kp->shm_swp, &uip->shm_swp); - err2 |= __put_user (kp->swap_attempts, - &uip->swap_attempts); - err2 |= __put_user (kp->swap_successes, - &uip->swap_successes); - if (err2) - err = -EFAULT; - } else if (IPCOP_MASK (second) & - (IPCOP_MASK (SHM_STAT) | IPCOP_MASK (IPC_STAT))) { - int err2 = put_user (s.shm_perm.key, &up->shm_perm.key); - err2 |= __put_user (s.shm_perm.uid, &up->shm_perm.uid); - err2 |= __put_user (s.shm_perm.gid, &up->shm_perm.gid); - err2 |= __put_user (s.shm_perm.cuid, - &up->shm_perm.cuid); - err2 |= __put_user (s.shm_perm.cgid, - &up->shm_perm.cgid); - err2 |= __put_user (s.shm_perm.mode, - &up->shm_perm.mode); - err2 |= __put_user (s.shm_perm.seq, &up->shm_perm.seq); - err2 |= __put_user (s.shm_atime, &up->shm_atime); - err2 |= __put_user (s.shm_dtime, &up->shm_dtime); - err2 |= __put_user (s.shm_ctime, &up->shm_ctime); - err2 |= __put_user (s.shm_segsz, &up->shm_segsz); - err2 |= __put_user (s.shm_nattch, &up->shm_nattch); - err2 |= __put_user (s.shm_cpid, &up->shm_cpid); - err2 |= __put_user (s.shm_lpid, &up->shm_lpid); - if (err2) - err = -EFAULT; - } } -out: return err; } @@ -1865,67 +1782,54 @@ sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth) version = call >> 16; /* hack for backward compatibility */ call &= 0xffff; - if (call <= SEMCTL) - switch (call) { - case SEMOP: - /* struct sembuf is the same on 32 and 64bit :)) */ - err = sys_semop (first, (struct sembuf *)AA(ptr), - second); - goto out; - case SEMGET: - err = sys_semget (first, second, third); - goto out; - case SEMCTL: - err = do_sys32_semctl (first, second, third, - (void *)AA(ptr)); - goto out; - default: - err = -EINVAL; - goto out; - }; - if (call <= MSGCTL) - switch (call) { - case MSGSND: - err = do_sys32_msgsnd (first, second, third, - (void *)AA(ptr)); - goto out; - case MSGRCV: - err = do_sys32_msgrcv (first, second, fifth, third, - version, (void *)AA(ptr)); - goto out; - case MSGGET: - err = sys_msgget ((key_t) first, second); - goto out; - case MSGCTL: - err = do_sys32_msgctl (first, second, (void *)AA(ptr)); - goto out; - default: - err = -EINVAL; - goto out; - } - if (call <= SHMCTL) - switch (call) { - case SHMAT: - err = do_sys32_shmat (first, second, third, - version, (void *)AA(ptr)); - goto out; - case SHMDT: - err = sys_shmdt ((char *)AA(ptr)); - goto out; - case SHMGET: - err = sys_shmget (first, second, third); - goto out; - case SHMCTL: - err = do_sys32_shmctl (first, second, (void *)AA(ptr)); - goto out; - default: - err = -EINVAL; - goto out; - } + switch (call) { - err = -EINVAL; + case SEMOP: + /* struct sembuf is the same on 32 and 64bit :)) */ + err = sys_semop (first, (struct sembuf *)AA(ptr), + second); + break; + case SEMGET: + err = sys_semget (first, second, third); + break; + case SEMCTL: + err = do_sys32_semctl (first, second, third, + (void *)AA(ptr)); + break; + + case MSGSND: + err = do_sys32_msgsnd (first, second, third, + (void *)AA(ptr)); + break; + case MSGRCV: + err = do_sys32_msgrcv (first, second, fifth, third, + version, (void *)AA(ptr)); + break; + case MSGGET: + err = sys_msgget ((key_t) first, second); + break; + case MSGCTL: + err = do_sys32_msgctl (first, second, (void *)AA(ptr)); + break; + + case SHMAT: + err = do_sys32_shmat (first, second, third, + version, (void *)AA(ptr)); + break; + case SHMDT: + err = sys_shmdt ((char *)AA(ptr)); + break; + case SHMGET: + err = sys_shmget (first, second, third); + break; + case SHMCTL: + err = do_sys32_shmctl (first, second, (void *)AA(ptr)); + break; + default: + err = -EINVAL; + break; + } -out: unlock_kernel(); return err; } @@ -1949,6 +1853,537 @@ asmlinkage long sys32_time(int * tloc) return i; } +struct rusage32 { + struct timeval32 ru_utime; + struct timeval32 ru_stime; + int ru_maxrss; + int ru_ixrss; + int ru_idrss; + int ru_isrss; + int ru_minflt; + int ru_majflt; + int ru_nswap; + int ru_inblock; + int ru_oublock; + int ru_msgsnd; + int ru_msgrcv; + int ru_nsignals; + int ru_nvcsw; + int ru_nivcsw; +}; + +static int +put_rusage (struct rusage32 *ru, struct rusage *r) +{ + int err; + + err = put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec); + err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec); + err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec); + err |= __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec); + err |= __put_user (r->ru_maxrss, &ru->ru_maxrss); + err |= __put_user (r->ru_ixrss, &ru->ru_ixrss); + err |= __put_user (r->ru_idrss, &ru->ru_idrss); + err |= __put_user (r->ru_isrss, &ru->ru_isrss); + err |= __put_user (r->ru_minflt, &ru->ru_minflt); + err |= __put_user (r->ru_majflt, &ru->ru_majflt); + err |= __put_user (r->ru_nswap, &ru->ru_nswap); + err |= __put_user (r->ru_inblock, &ru->ru_inblock); + err |= __put_user (r->ru_oublock, &ru->ru_oublock); + err |= __put_user (r->ru_msgsnd, &ru->ru_msgsnd); + err |= __put_user (r->ru_msgrcv, &ru->ru_msgrcv); + err |= __put_user (r->ru_nsignals, &ru->ru_nsignals); + err |= __put_user (r->ru_nvcsw, &ru->ru_nvcsw); + err |= __put_user (r->ru_nivcsw, &ru->ru_nivcsw); + return err; +} + +extern asmlinkage int sys_wait4(pid_t pid,unsigned int * stat_addr, + int options, struct rusage * ru); + +asmlinkage int +sys32_wait4(__kernel_pid_t32 pid, unsigned int *stat_addr, int options, + struct rusage32 *ru) +{ + if (!ru) + return sys_wait4(pid, stat_addr, options, NULL); + else { + struct rusage r; + int ret; + unsigned int status; + mm_segment_t old_fs = get_fs(); + + set_fs (KERNEL_DS); + ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r); + set_fs (old_fs); + if (put_rusage (ru, &r)) return -EFAULT; + if (stat_addr && put_user (status, stat_addr)) + return -EFAULT; + return ret; + } +} + +asmlinkage int +sys32_waitpid(__kernel_pid_t32 pid, unsigned int *stat_addr, int options) +{ + return sys32_wait4(pid, stat_addr, options, NULL); +} + + +extern asmlinkage int +sys_getrusage(int who, struct rusage *ru); + +asmlinkage int +sys32_getrusage(int who, struct rusage32 *ru) +{ + struct rusage r; + int ret; + mm_segment_t old_fs = get_fs(); + + set_fs (KERNEL_DS); + ret = sys_getrusage(who, &r); + set_fs (old_fs); + if (put_rusage (ru, &r)) return -EFAULT; + return ret; +} + +struct tms32 { + __kernel_clock_t32 tms_utime; + __kernel_clock_t32 tms_stime; + __kernel_clock_t32 tms_cutime; + __kernel_clock_t32 tms_cstime; +}; + +extern asmlinkage long sys_times(struct tms * tbuf); + +asmlinkage long +sys32_times(struct tms32 *tbuf) +{ + struct tms t; + long ret; + mm_segment_t old_fs = get_fs (); + int err; + + set_fs (KERNEL_DS); + ret = sys_times(tbuf ? &t : NULL); + set_fs (old_fs); + if (tbuf) { + err = put_user (t.tms_utime, &tbuf->tms_utime); + err |= __put_user (t.tms_stime, &tbuf->tms_stime); + err |= __put_user (t.tms_cutime, &tbuf->tms_cutime); + err |= __put_user (t.tms_cstime, &tbuf->tms_cstime); + if (err) + ret = -EFAULT; + } + return ret; +} + +unsigned int +ia32_peek (struct pt_regs *regs, struct task_struct *child, unsigned long addr, unsigned int *val) +{ + size_t copied; + unsigned int ret; + + copied = access_process_vm(child, addr, val, sizeof(*val), 0); + return(copied != sizeof(ret) ? -EIO : 0); +} + +unsigned int +ia32_poke (struct pt_regs *regs, struct task_struct *child, unsigned long addr, unsigned int val) +{ + + if (access_process_vm(child, addr, &val, sizeof(val), 1) != sizeof(val)) + return -EIO; + return 0; +} + +/* + * The order in which registers are stored in the ptrace regs structure + */ +#define PT_EBX 0 +#define PT_ECX 1 +#define PT_EDX 2 +#define PT_ESI 3 +#define PT_EDI 4 +#define PT_EBP 5 +#define PT_EAX 6 +#define PT_DS 7 +#define PT_ES 8 +#define PT_FS 9 +#define PT_GS 10 +#define PT_ORIG_EAX 11 +#define PT_EIP 12 +#define PT_CS 13 +#define PT_EFL 14 +#define PT_UESP 15 +#define PT_SS 16 + +unsigned int +getreg(struct task_struct *child, int regno) +{ + struct pt_regs *child_regs; + + child_regs = ia64_task_regs(child); + switch (regno / sizeof(int)) { + + case PT_EBX: + return(child_regs->r11); + case PT_ECX: + return(child_regs->r9); + case PT_EDX: + return(child_regs->r10); + case PT_ESI: + return(child_regs->r14); + case PT_EDI: + return(child_regs->r15); + case PT_EBP: + return(child_regs->r13); + case PT_EAX: + case PT_ORIG_EAX: + return(child_regs->r8); + case PT_EIP: + return(child_regs->cr_iip); + case PT_UESP: + return(child_regs->r12); + case PT_EFL: + return(child->thread.eflag); + case PT_DS: + case PT_ES: + case PT_FS: + case PT_GS: + case PT_SS: + return((unsigned int)__USER_DS); + case PT_CS: + return((unsigned int)__USER_CS); + default: + printk("getregs:unknown register %d\n", regno); + break; + + } + return(0); +} + +void +putreg(struct task_struct *child, int regno, unsigned int value) +{ + struct pt_regs *child_regs; + + child_regs = ia64_task_regs(child); + switch (regno / sizeof(int)) { + + case PT_EBX: + child_regs->r11 = value; + break; + case PT_ECX: + child_regs->r9 = value; + break; + case PT_EDX: + child_regs->r10 = value; + break; + case PT_ESI: + child_regs->r14 = value; + break; + case PT_EDI: + child_regs->r15 = value; + break; + case PT_EBP: + child_regs->r13 = value; + break; + case PT_EAX: + case PT_ORIG_EAX: + child_regs->r8 = value; + break; + case PT_EIP: + child_regs->cr_iip = value; + break; + case PT_UESP: + child_regs->r12 = value; + break; + case PT_EFL: + child->thread.eflag = value; + break; + case PT_DS: + case PT_ES: + case PT_FS: + case PT_GS: + case PT_SS: + if (value != __USER_DS) + printk("setregs:try to set invalid segment register %d = %x\n", regno, value); + break; + case PT_CS: + if (value != __USER_CS) + printk("setregs:try to set invalid segment register %d = %x\n", regno, value); + break; + default: + printk("getregs:unknown register %d\n", regno); + break; + + } +} + +static inline void +ia32f2ia64f(void *dst, void *src) +{ + + __asm__ ("ldfe f6=[%1] ;;\n\t" + "stf.spill [%0]=f6" + : + : "r"(dst), "r"(src)); + return; +} + +static inline void +ia64f2ia32f(void *dst, void *src) +{ + + __asm__ ("ldf.fill f6=[%1] ;;\n\t" + "stfe [%0]=f6" + : + : "r"(dst), "r"(src)); + return; +} + +void +put_fpreg(int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switch_stack *swp, int tos) +{ + struct _fpreg_ia32 *f; + char buf[32]; + + f = (struct _fpreg_ia32 *)(((unsigned long)buf + 15) & ~15); + if ((regno += tos) >= 8) + regno -= 8; + switch (regno) { + + case 0: + ia64f2ia32f(f, &ptp->f8); + break; + case 1: + ia64f2ia32f(f, &ptp->f9); + break; + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + ia64f2ia32f(f, &swp->f10 + (regno - 2)); + break; + + } + __copy_to_user(reg, f, sizeof(*reg)); + return; +} + +void +get_fpreg(int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switch_stack *swp, int tos) +{ + + if ((regno += tos) >= 8) + regno -= 8; + switch (regno) { + + case 0: + __copy_from_user(&ptp->f8, reg, sizeof(*reg)); + break; + case 1: + __copy_from_user(&ptp->f9, reg, sizeof(*reg)); + break; + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + __copy_from_user(&swp->f10 + (regno - 2), reg, sizeof(*reg)); + break; + + } + return; +} + +int +save_ia32_fpstate(struct task_struct *tsk, struct _fpstate_ia32 *save) +{ + struct switch_stack *swp; + struct pt_regs *ptp; + int i, tos; + + if (!access_ok(VERIFY_WRITE, save, sizeof(*save))) + return(-EIO); + __put_user(tsk->thread.fcr, &save->cw); + __put_user(tsk->thread.fsr, &save->sw); + __put_user(tsk->thread.fsr >> 32, &save->tag); + __put_user(tsk->thread.fir, &save->ipoff); + __put_user(__USER_CS, &save->cssel); + __put_user(tsk->thread.fdr, &save->dataoff); + __put_user(__USER_DS, &save->datasel); + /* + * Stack frames start with 16-bytes of temp space + */ + swp = (struct switch_stack *)(tsk->thread.ksp + 16); + ptp = ia64_task_regs(tsk); + tos = (tsk->thread.fsr >> 11) & 3; + for (i = 0; i < 8; i++) + put_fpreg(i, &save->_st[i], ptp, swp, tos); + return(0); +} + +int +restore_ia32_fpstate(struct task_struct *tsk, struct _fpstate_ia32 *save) +{ + struct switch_stack *swp; + struct pt_regs *ptp; + int i, tos; + int fsrlo, fsrhi; + + if (!access_ok(VERIFY_READ, save, sizeof(*save))) + return(-EIO); + __get_user(tsk->thread.fcr, (unsigned int *)&save->cw); + __get_user(fsrlo, (unsigned int *)&save->sw); + __get_user(fsrhi, (unsigned int *)&save->tag); + tsk->thread.fsr = ((long)fsrhi << 32) | (long)fsrlo; + __get_user(tsk->thread.fir, (unsigned int *)&save->ipoff); + __get_user(tsk->thread.fdr, (unsigned int *)&save->dataoff); + /* + * Stack frames start with 16-bytes of temp space + */ + swp = (struct switch_stack *)(tsk->thread.ksp + 16); + ptp = ia64_task_regs(tsk); + tos = (tsk->thread.fsr >> 11) & 3; + for (i = 0; i < 8; i++) + get_fpreg(i, &save->_st[i], ptp, swp, tos); + return(0); +} + +asmlinkage long sys_ptrace(long, pid_t, unsigned long, unsigned long, long, long, long, long, long); + +/* + * Note that the IA32 version of `ptrace' calls the IA64 routine for + * many of the requests. This will only work for requests that do + * not need access to the calling processes `pt_regs' which is located + * at the address of `stack'. Once we call the IA64 `sys_ptrace' then + * the address of `stack' will not be the address of the `pt_regs'. + */ +asmlinkage long +sys32_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data, + long arg4, long arg5, long arg6, long arg7, long stack) +{ + struct pt_regs *regs = (struct pt_regs *) &stack; + struct task_struct *child; + long i, ret; + unsigned int value; + + lock_kernel(); + if (request == PTRACE_TRACEME) { + ret = sys_ptrace(request, pid, addr, data, + arg4, arg5, arg6, arg7, stack); + goto out; + } + + ret = -ESRCH; + read_lock(&tasklist_lock); + child = find_task_by_pid(pid); + read_unlock(&tasklist_lock); + if (!child) + goto out; + ret = -EPERM; + if (pid == 1) /* no messing around with init! */ + goto out; + + if (request == PTRACE_ATTACH) { + ret = sys_ptrace(request, pid, addr, data, + arg4, arg5, arg6, arg7, stack); + goto out; + } + ret = -ESRCH; + if (!(child->flags & PF_PTRACED)) + goto out; + if (child->state != TASK_STOPPED) { + if (request != PTRACE_KILL) + goto out; + } + if (child->p_pptr != current) + goto out; + + switch (request) { + case PTRACE_PEEKTEXT: + case PTRACE_PEEKDATA: /* read word at location addr */ + ret = ia32_peek(regs, child, addr, &value); + if (ret == 0) + ret = put_user(value, (unsigned int *)data); + else + ret = -EIO; + goto out; + + case PTRACE_POKETEXT: + case PTRACE_POKEDATA: /* write the word at location addr */ + ret = ia32_poke(regs, child, addr, (unsigned int)data); + goto out; + + case PTRACE_PEEKUSR: /* read word at addr in USER area */ + ret = 0; + break; + + case PTRACE_POKEUSR: /* write word at addr in USER area */ + ret = 0; + break; + + case IA32_PTRACE_GETREGS: + if (!access_ok(VERIFY_WRITE, (int *)data, 17*sizeof(int))) { + ret = -EIO; + break; + } + for ( i = 0; i < 17*sizeof(int); i += sizeof(int) ) { + __put_user(getreg(child, i),(unsigned int *) data); + data += sizeof(int); + } + ret = 0; + break; + + case IA32_PTRACE_SETREGS: + { + unsigned int tmp; + if (!access_ok(VERIFY_READ, (int *)data, 17*sizeof(int))) { + ret = -EIO; + break; + } + for ( i = 0; i < 17*sizeof(int); i += sizeof(int) ) { + __get_user(tmp, (unsigned int *) data); + putreg(child, i, tmp); + data += sizeof(int); + } + ret = 0; + break; + } + + case IA32_PTRACE_GETFPREGS: + ret = save_ia32_fpstate(child, (struct _fpstate_ia32 *)data); + break; + + case IA32_PTRACE_SETFPREGS: + ret = restore_ia32_fpstate(child, (struct _fpstate_ia32 *)data); + break; + + case PTRACE_SYSCALL: /* continue, stop after next syscall */ + case PTRACE_CONT: /* restart after signal. */ + case PTRACE_KILL: + case PTRACE_SINGLESTEP: /* execute chile for one instruction */ + case PTRACE_DETACH: /* detach a process */ + unlock_kernel(); + ret = sys_ptrace(request, pid, addr, data, + arg4, arg5, arg6, arg7, stack); + return(ret); + + default: + ret = -EIO; + break; + + } + out: + unlock_kernel(); + return ret; +} + #ifdef NOTYET /* UNTESTED FOR IA64 FROM HERE DOWN */ /* In order to reduce some races, while at the same time doing additional @@ -2719,37 +3154,6 @@ sys32_getresgid(__kernel_gid_t32 *rgid, __kernel_gid_t32 *egid, return ret; } -struct tms32 { - __kernel_clock_t32 tms_utime; - __kernel_clock_t32 tms_stime; - __kernel_clock_t32 tms_cutime; - __kernel_clock_t32 tms_cstime; -}; - -extern asmlinkage long sys_times(struct tms * tbuf); - -asmlinkage long -sys32_times(struct tms32 *tbuf) -{ - struct tms t; - long ret; - mm_segment_t old_fs = get_fs (); - int err; - - set_fs (KERNEL_DS); - ret = sys_times(tbuf ? &t : NULL); - set_fs (old_fs); - if (tbuf) { - err = put_user (t.tms_utime, &tbuf->tms_utime); - err |= __put_user (t.tms_stime, &tbuf->tms_stime); - err |= __put_user (t.tms_cutime, &tbuf->tms_cutime); - err |= __put_user (t.tms_cstime, &tbuf->tms_cstime); - if (err) - ret = -EFAULT; - } - return ret; -} - extern asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist); asmlinkage int @@ -2789,23 +3193,6 @@ sys32_setgroups(int gidsetsize, __kernel_gid_t32 *grouplist) return ret; } -extern asmlinkage int -sys_getrusage(int who, struct rusage *ru); - -asmlinkage int -sys32_getrusage(int who, struct rusage32 *ru) -{ - struct rusage r; - int ret; - mm_segment_t old_fs = get_fs(); - - set_fs (KERNEL_DS); - ret = sys_getrusage(who, &r); - set_fs (old_fs); - if (put_rusage (ru, &r)) return -EFAULT; - return ret; -} - /* XXX These as well... */ extern __inline__ struct socket * @@ -4355,4 +4742,3 @@ sys32_adjtimex(struct timex32 *utp) return ret; } #endif // NOTYET - diff --git a/arch/ia64/kdb/Makefile b/arch/ia64/kdb/Makefile deleted file mode 100644 index 2e8db3fc4..000000000 --- a/arch/ia64/kdb/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# -# Makefile for ia64-specific kdb files.. -# -# Copyright 1999, Silicon Graphics Inc. -# -# Written March 1999 by Scott Lurndal at Silicon Graphics, Inc. -# Code for IA64 written by Goutham Rao <goutham.rao@intel.com> and -# Sreenivas Subramoney <sreenivas.subramoney@intel.com> -# - -SUB_DIRS := -MOD_SUB_DIRS := $(SUB_DIRS) -ALL_SUB_DIRS := $(SUB_DIRS) - -.S.o: - $(CC) $(AFLAGS) -traditional -c $< -o $*.o - -L_TARGET = kdb.a -L_OBJS = kdbsupport.o kdb_io.o kdb_bt.o kdb_traps.o - -include $(TOPDIR)/Rules.make diff --git a/arch/ia64/kdb/kdb_bt.c b/arch/ia64/kdb/kdb_bt.c deleted file mode 100644 index dbcb7a575..000000000 --- a/arch/ia64/kdb/kdb_bt.c +++ /dev/null @@ -1,104 +0,0 @@ -/** - * Minimalist Kernel Debugger - * Machine dependent stack traceback code for IA-64. - * - * Copyright (C) 1999 Goutham Rao <goutham.rao@intel.com> - * Copyright (C) 1999 Sreenivas Subramoney <sreenivas.subramoney@intel.com> - * Intel Corporation, August 1999. - * Copyright (C) 1999 Hewlett-Packard Co - * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com> - * - * 99/12/03 D. Mosberger Reimplemented based on <asm-ia64/unwind.h> API. - * 99/12/06 D. Mosberger Added support for backtracing other processes. - */ - -#include <linux/ctype.h> -#include <linux/string.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/kdb.h> -#include <asm/system.h> -#include <asm/current.h> -#include <asm/kdbsupport.h> - -/* - * Minimal stack back trace functionality. - */ -int -kdb_bt (int argc, const char **argv, const char **envp, struct pt_regs *regs) -{ - struct task_struct *task = current; - struct ia64_frame_info info; - char *name; - int diag; - - if (strcmp(argv[0], "btp") == 0) { - unsigned long pid; - - diag = kdbgetularg(argv[1], &pid); - if (diag) - return diag; - - task = find_task_by_pid(pid); - if (!task) { - kdb_printf("No process with pid == %d found\n", pid); - return 0; - } - regs = ia64_task_regs(task); - } else if (argc) { - kdb_printf("bt <address> is unsupported for IA-64\n"); - return 0; - } - - if (task == current) { - /* - * Upon entering kdb, the stack frame looks like this: - * - * +---------------------+ - * | struct pt_regs | - * +---------------------+ - * | | - * | kernel stack | - * | | - * +=====================+ <--- top of stack upon entering kdb - * | struct pt_regs | - * +---------------------+ - * | struct switch_stack | - * +---------------------+ - */ - if (user_mode(regs)) { - /* We are not implementing stack backtrace from user mode code */ - kdb_printf ("Not in Kernel\n"); - return 0; - } - ia64_unwind_init_from_current(&info, regs); - } else { - /* - * For a blocked task, the stack frame looks like this: - * - * +---------------------+ - * | struct pt_regs | - * +---------------------+ - * | | - * | kernel stack | - * | | - * +---------------------+ - * | struct switch_stack | - * +=====================+ <--- task->thread.ksp - */ - ia64_unwind_init_from_blocked_task(&info, task); - } - - kdb_printf("Ret Address Reg Stack base Name\n\n") ; - do { - unsigned long ip = ia64_unwind_get_ip(&info); - - name = kdbnearsym(ip); - if (!name) { - kdb_printf("Interrupt\n"); - return 0; - } - kdb_printf("0x%016lx: [0x%016lx] %s\n", ip, ia64_unwind_get_bsp(&info), name); - } while (ia64_unwind_to_previous_frame(&info) >= 0); - return 0; -} diff --git a/arch/ia64/kdb/kdb_io.c b/arch/ia64/kdb/kdb_io.c deleted file mode 100644 index 0b5c6fd44..000000000 --- a/arch/ia64/kdb/kdb_io.c +++ /dev/null @@ -1,350 +0,0 @@ -/* - * Kernel Debugger Console I/O handler - * - * Copyright (C) 1999 Silicon Graphics, Inc. - * Copyright (C) Scott Lurndal (slurn@engr.sgi.com) - * Copyright (C) Scott Foehner (sfoehner@engr.sgi.com) - * Copyright (C) Srinivasa Thirumalachar (sprasad@engr.sgi.com) - * - * Written March 1999 by Scott Lurndal at Silicon Graphics, Inc. - * - * Modifications from: - * Chuck Fleckenstein 1999/07/20 - * Move kdb_info struct declaration to this file - * for cases where serial support is not compiled into - * the kernel. - * - * Masahiro Adegawa 1999/07/20 - * Handle some peculiarities of japanese 86/106 - * keyboards. - * - * marc@mucom.co.il 1999/07/20 - * Catch buffer overflow for serial input. - * - * Scott Foehner - * Port to ia64 - */ - -#include <linux/config.h> -#include <linux/kernel.h> -#include <linux/console.h> -#include <linux/serial_reg.h> -#include <linux/spinlock.h> - -#include <asm/io.h> - -#include "pc_keyb.h" - -int kdb_port = 0; - -/* - * This module contains code to read characters from the keyboard or a serial - * port. - * - * It is used by the kernel debugger, and is polled, not interrupt driven. - * - */ - -/* - * send: Send a byte to the keyboard controller. Used primarily to - * alter LED settings. - */ - -static void -kdb_kbdsend(unsigned char byte) -{ - while (inb(KBD_STATUS_REG) & KBD_STAT_IBF) - ; - outb(KBD_DATA_REG, byte); -} - -static void -kdb_kbdsetled(int leds) -{ - kdb_kbdsend(KBD_CMD_SET_LEDS); - kdb_kbdsend((unsigned char)leds); -} - -static void -console_read (char *buffer, size_t bufsize) -{ - struct console *in; - struct console *out; - char *cp, ch; - - for (in = console_drivers; in; in = in->next) { - if ((in->flags & CON_ENABLED) && (in->read || in->wait_key)) - break; - } - for (out = console_drivers; out; out = out->next) { - if ((out->flags & CON_ENABLED) && out->write) - break; - } - - if ((!in->read && !in->wait_key) || !out->write) { - panic("kdb_io: can't do console i/o!"); - } - - if (in->read) { - /* this is untested... */ - (*in->read)(in, buffer, bufsize); - return; - } - - bufsize -= 2; /* leave room for CR & NUL terminator */ - cp = buffer; - while (1) { - ch = (*in->wait_key)(in); - switch (ch) { - case '\b': - if (cp > buffer) { - --cp, ++bufsize; - (*out->write)(out, "\b \b", 3); - } - break; - - case '\025': - while (cp > buffer) { - --cp, ++bufsize; - (*out->write)(out, "\b \b", 3); - } - break; - - case '\r': - case '\n': - (*out->write)(out, "\r\n", 2); - *cp++ = '\n'; - *cp++ = '\0'; - return; - - default: - if (bufsize > 0) { - (*out->write)(out, &ch, 1); - --bufsize; - *cp++ = ch; - } - break; - } - } -} - -char * -kdb_getscancode(char *buffer, size_t bufsize) -{ - /* - * XXX Shouldn't kdb _always_ use console based I/O? That's what the console - * abstraction is for, after all... ---davidm - */ -#ifdef CONFIG_IA64_HP_SIM - extern spinlock_t console_lock; - unsigned long flags; - - spin_lock_irqsave(&console_lock, flags); - console_read(buffer, bufsize); - spin_unlock_irqrestore(&console_lock, flags); - return buffer; -#else /* !CONFIG_IA64_HP_SIM */ - char *cp = buffer; - int scancode, scanstatus; - static int shift_lock = 0; /* CAPS LOCK state (0-off, 1-on) */ - static int shift_key = 0; /* Shift next keypress */ - static int ctrl_key = 0; - static int leds = 2; /* Num lock */ - u_short keychar; - extern u_short plain_map[], shift_map[], ctrl_map[]; - - bufsize -= 2; /* Reserve space for newline and null byte */ - - /* - * If we came in via a serial console, we allow that to - * be the input window for kdb. - */ - if (kdb_port != 0) { - char ch; - int status; -#define serial_inp(info, offset) inb((info) + (offset)) -#define serial_out(info, offset, v) outb((v), (info) + (offset)) - - while(1) { - while ((status = serial_inp(kdb_port, UART_LSR)) - & UART_LSR_DR) { -readchar: - ch = serial_inp(kdb_port, UART_RX); - if (ch == 8) { /* BS */ - if (cp > buffer) { - --cp, bufsize++; - printk("%c %c", 0x08, 0x08); - } - continue; - } - serial_out(kdb_port, UART_TX, ch); - if (ch == 13) { /* CR */ - *cp++ = '\n'; - *cp++ = '\0'; - serial_out(kdb_port, UART_TX, 10); - return(buffer); - } - /* - * Discard excess characters - */ - if (bufsize > 0) { - *cp++ = ch; - bufsize--; - } - } - while (((status = serial_inp(kdb_port, UART_LSR)) - & UART_LSR_DR) == 0); - } - } - - while (1) { - - /* - * Wait for a valid scancode - */ - - while ((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0) - ; - - /* - * Fetch the scancode - */ - scancode = inb(KBD_DATA_REG); - scanstatus = inb(KBD_STATUS_REG); - - /* - * Ignore mouse events. - */ - if (scanstatus & KBD_STAT_MOUSE_OBF) - continue; - - /* - * Ignore release, trigger on make - * (except for shift keys, where we want to - * keep the shift state so long as the key is - * held down). - */ - - if (((scancode&0x7f) == 0x2a) - || ((scancode&0x7f) == 0x36)) { - /* - * Next key may use shift table - */ - if ((scancode & 0x80) == 0) { - shift_key=1; - } else { - shift_key=0; - } - continue; - } - - if ((scancode&0x7f) == 0x1d) { - /* - * Left ctrl key - */ - if ((scancode & 0x80) == 0) { - ctrl_key = 1; - } else { - ctrl_key = 0; - } - continue; - } - - if ((scancode & 0x80) != 0) - continue; - - scancode &= 0x7f; - - /* - * Translate scancode - */ - - if (scancode == 0x3a) { - /* - * Toggle caps lock - */ - shift_lock ^= 1; - leds ^= 0x4; /* toggle caps lock led */ - - kdb_kbdsetled(leds); - continue; - } - - if (scancode == 0x0e) { - /* - * Backspace - */ - if (cp > buffer) { - --cp, bufsize++; - - /* - * XXX - erase character on screen - */ - printk("%c %c", 0x08, 0x08); - } - continue; - } - - if (scancode == 0xe0) { - continue; - } - - /* - * For Japanese 86/106 keyboards - * See comment in drivers/char/pc_keyb.c. - * - Masahiro Adegawa - */ - if (scancode == 0x73) { - scancode = 0x59; - } else if (scancode == 0x7d) { - scancode = 0x7c; - } - - if (!shift_lock && !shift_key) { - keychar = plain_map[scancode]; - } else if (shift_lock || shift_key) { - keychar = shift_map[scancode]; - } else if (ctrl_key) { - keychar = ctrl_map[scancode]; - } else { - keychar = 0x0020; - printk("Unknown state/scancode (%d)\n", scancode); - } - - if ((scancode & 0x7f) == 0x1c) { - /* - * enter key. All done. - */ - printk("\n"); - break; - } - - /* - * echo the character. - */ - printk("%c", keychar&0xff); - - if (bufsize) { - --bufsize; - *cp++ = keychar&0xff; - } else { - printk("buffer overflow\n"); - break; - } - - } - - *cp++ = '\n'; /* White space for parser */ - *cp++ = '\0'; /* String termination */ - -#if defined(NOTNOW) - cp = buffer; - while (*cp) { - printk("char 0x%x\n", *cp++); - } -#endif - - return buffer; -#endif /* !CONFIG_IA64_HP_SIM */ -} - diff --git a/arch/ia64/kdb/kdb_traps.c b/arch/ia64/kdb/kdb_traps.c deleted file mode 100644 index 6358f7a30..000000000 --- a/arch/ia64/kdb/kdb_traps.c +++ /dev/null @@ -1,55 +0,0 @@ -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/sched.h> -#include <linux/kdb.h> - -static struct kdb_bp_support { - unsigned long addr ; - int slot ; -} kdb_bp_info[NR_CPUS] ; - - -extern void kdb_bp_install (void); - -/* - * This gets invoked right before a call to ia64_fault(). - * Returns zero the normal fault handler should be invoked. - */ -long -ia64_kdb_fault_handler (unsigned long vector, unsigned long isr, unsigned long ifa, - unsigned long iim, unsigned long itir, unsigned long arg5, - unsigned long arg6, unsigned long arg7, unsigned long stack) -{ - struct switch_stack *sw = (struct switch_stack *) &stack; - struct pt_regs *regs = (struct pt_regs *) (sw + 1); - int bundle_slot; - - /* - * TBD - * If KDB is configured, enter KDB for any fault. - */ - if ((vector == 29) || (vector == 35) || (vector == 36)) { - if (!user_mode(regs)) { - bundle_slot = ia64_psr(regs)->ri; - if (vector == 29) { - if (bundle_slot == 0) { - kdb_bp_info[0].addr = regs->cr_iip; - kdb_bp_info[0].slot = bundle_slot; - kdb(KDB_REASON_FLTDBG, 0, regs); - } else { - if ((bundle_slot < 3) && - (kdb_bp_info[0].addr == regs->cr_iip)) - { - ia64_psr(regs)->id = 1; - ia64_psr(regs)->db = 1; - kdb_bp_install() ; - } else /* some error ?? */ - kdb(KDB_REASON_FLTDBG, 0, regs); - } - } else /* single step or taken branch */ - kdb(KDB_REASON_DEBUG, 0, regs); - return 1; - } - } - return 0; -} diff --git a/arch/ia64/kdb/kdbsupport.c b/arch/ia64/kdb/kdbsupport.c deleted file mode 100644 index d074a01a3..000000000 --- a/arch/ia64/kdb/kdbsupport.c +++ /dev/null @@ -1,1329 +0,0 @@ -/* - * Minimalist Kernel Debugger - * - * Copyright (C) 1999 Silicon Graphics, Inc. - * Copyright (C) Scott Lurndal (slurn@engr.sgi.com) - * Copyright (C) Scott Foehner (sfoehner@engr.sgi.com) - * Copyright (C) Srinivasa Thirumalachar (sprasad@engr.sgi.com) - * Copyright (C) David Mosberger-Tang <davidm@hpl.hp.com> - * - * Written March 1999 by Scott Lurndal at Silicon Graphics, Inc. - * - * Modifications from: - * Richard Bass 1999/07/20 - * Many bug fixes and enhancements. - * Scott Foehner - * Port to ia64 - * Srinivasa Thirumalachar - * RSE support for ia64 - */ - -#include <linux/config.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/types.h> -#include <linux/sched.h> -#include <linux/mm.h> -#include <linux/kdb.h> -#include <linux/stddef.h> -#include <linux/vmalloc.h> - -#include <asm/delay.h> -#include <asm/kdbsupport.h> -#include <asm/rse.h> -#include <asm/uaccess.h> - -extern kdb_state_t kdb_state ; -k_machreg_t dbregs[KDB_DBREGS]; - -static int __init -kdb_setup (char *str) -{ - kdb_flags |= KDB_FLAG_EARLYKDB; - return 1; -} - -__setup("kdb", kdb_setup); - -static int -kdb_ia64_itm (int argc, const char **argv, const char **envp, struct pt_regs *regs) -{ - int diag; - unsigned long val; - - diag = kdbgetularg(argv[1], &val); - if (diag) - return diag; - kdb_printf("new itm=%0xlx\n", val); - - ia64_set_itm(val); - return 0; -} - -static int -kdb_ia64_sir (int argc, const char **argv, const char **envp, struct pt_regs *regs) -{ - u64 lid, tpr, lrr0, lrr1, itv, pmv, cmcv; - - asm ("mov %0=cr.lid" : "=r"(lid)); - asm ("mov %0=cr.tpr" : "=r"(tpr)); - asm ("mov %0=cr.lrr0" : "=r"(lrr0)); - asm ("mov %0=cr.lrr1" : "=r"(lrr1)); - printk("lid=0x%lx, tpr=0x%lx, lrr0=0x%lx, llr1=0x%lx\n", lid, tpr, lrr0, lrr1); - - asm ("mov %0=cr.itv" : "=r"(itv)); - asm ("mov %0=cr.pmv" : "=r"(pmv)); - asm ("mov %0=cr.cmcv" : "=r"(cmcv)); - printk("itv=0x%lx, pmv=0x%lx, cmcv=0x%lx\n", itv, pmv, cmcv); - - printk("irr=0x%016lx,0x%016lx,0x%016lx,0x%016lx\n", - ia64_get_irr0(), ia64_get_irr1(), ia64_get_irr2(), ia64_get_irr3()); - - printk("itc=0x%016lx, itm=0x%016lx\n", ia64_get_itc(), ia64_get_itm()); - return 0; -} - -void __init -kdb_init (void) -{ - extern void kdb_inittab(void); - unsigned long reg; - - kdb_inittab(); - kdb_initbptab(); -#if 0 - kdb_disinit(); -#endif - kdb_printf("kdb version %d.%d by Scott Lurndal. "\ - "Copyright SGI, All Rights Reserved\n", - KDB_MAJOR_VERSION, KDB_MINOR_VERSION); - - /* Enable debug registers */ - __asm__ ("mov %0=psr":"=r"(reg)); - reg |= IA64_PSR_DB; - __asm__ ("mov psr.l=%0"::"r"(reg)); - ia64_srlz_d(); - - /* Init kdb state */ - kdb_state.bkpt_handling_state = BKPTSTATE_NOT_HANDLED ; - - kdb_register("irr", kdb_ia64_sir, "", "Show interrupt registers", 0); - kdb_register("itm", kdb_ia64_itm, "", "Set new ITM value", 0); -} - -/* - * kdbprintf - * kdbgetword - * kdb_getstr - */ - -char * -kbd_getstr(char *buffer, size_t bufsize, char *prompt) -{ - extern char* kdb_getscancode(char *, size_t); - -#if defined(CONFIG_SMP) - kdb_printf(prompt, smp_processor_id()); -#else - kdb_printf("%s", prompt); -#endif - - return kdb_getscancode(buffer, bufsize); - -} - -int -kdb_printf(const char *fmt, ...) -{ - char buffer[256]; - va_list ap; - int diag; - int linecount; - - diag = kdbgetintenv("LINES", &linecount); - if (diag) - linecount = 22; - - va_start(ap, fmt); - vsprintf(buffer, fmt, ap); - va_end(ap); - - printk("%s", buffer); -#if 0 - if (strchr(buffer, '\n') != NULL) { - kdb_nextline++; - } - - if (kdb_nextline == linecount) { - char buf1[16]; - char buf2[32]; - extern char* kdb_getscancode(char *, size_t); - char *moreprompt; - - /* - * Pause until cr. - */ - moreprompt = kdbgetenv("MOREPROMPT"); - if (moreprompt == NULL) { - moreprompt = "more> "; - } - -#if defined(CONFIG_SMP) - if (strchr(moreprompt, '%')) { - sprintf(buf2, moreprompt, smp_processor_id()); - moreprompt = buf2; - } -#endif - - printk(moreprompt); - (void) kdb_getscancode(buf1, sizeof(buf1)); - - kdb_nextline = 1; - - if ((buf1[0] == 'q') - || (buf1[0] == 'Q')) { - kdb_longjmp(&kdbjmpbuf, 1); - } - } -#endif - return 0; -} - -unsigned long -kdbgetword(unsigned long addr, int width) -{ - /* - * This function checks the address for validity. Any address - * in the range PAGE_OFFSET to high_memory is legal, any address - * which maps to a vmalloc region is legal, and any address which - * is a user address, we use get_user() to verify validity. - */ - - if (addr < PAGE_OFFSET) { - /* - * Usermode address. - */ - unsigned long diag; - unsigned long ulval; - - switch (width) { - case 8: - { unsigned long *lp; - - lp = (unsigned long *) addr; - diag = get_user(ulval, lp); - break; - } - case 4: - { unsigned int *ip; - - ip = (unsigned int *) addr; - diag = get_user(ulval, ip); - break; - } - case 2: - { unsigned short *sp; - - sp = (unsigned short *) addr; - diag = get_user(ulval, sp); - break; - } - case 1: - { unsigned char *cp; - - cp = (unsigned char *) addr; - diag = get_user(ulval, cp); - break; - } - default: - printk("kdbgetword: Bad width\n"); - return 0L; - } - - if (diag) { - if ((kdb_flags & KDB_FLAG_SUPRESS) == 0) { - printk("kdb: Bad user address 0x%lx\n", addr); - kdb_flags |= KDB_FLAG_SUPRESS; - } - return 0L; - } - kdb_flags &= ~KDB_FLAG_SUPRESS; - return ulval; - } - - if (addr > (unsigned long)high_memory) { - extern int kdb_vmlist_check(unsigned long, unsigned long); - - if (!kdb_vmlist_check(addr, addr+width)) { - /* - * Would appear to be an illegal kernel address; - * Print a message once, and don't print again until - * a legal address is used. - */ - if ((kdb_flags & KDB_FLAG_SUPRESS) == 0) { - printk("kdb: Bad kernel address 0x%lx\n", addr); - kdb_flags |= KDB_FLAG_SUPRESS; - } - return 0L; - } - } - - /* - * A good address. Reset error flag. - */ - kdb_flags &= ~KDB_FLAG_SUPRESS; - - switch (width) { - case 8: - { unsigned long *lp; - - lp = (unsigned long *)(addr); - return *lp; - } - case 4: - { unsigned int *ip; - - ip = (unsigned int *)(addr); - return *ip; - } - case 2: - { unsigned short *sp; - - sp = (unsigned short *)(addr); - return *sp; - } - case 1: - { unsigned char *cp; - - cp = (unsigned char *)(addr); - return *cp; - } - } - - printk("kdbgetword: Bad width\n"); - return 0L; -} - -/* - * Start of breakpoint management routines - */ - -/* - * Arg: bp structure - */ - -int -kdb_allocdbreg(kdb_bp_t *bp) -{ - int i=0; - - /* For inst bkpt, just return. No hw reg alloc to be done. */ - - if (bp->bp_mode == BKPTMODE_INST) { - return i; - } else if (bp->bp_mode == BKPTMODE_DATAW) { - for(i=0; i<KDB_DBREGS; i++) { - if (dbregs[i] == 0xffffffff) { - dbregs[i] = 0; - return i; - } - } - } - - return -1; -} - -void -kdb_freedbreg(kdb_bp_t *bp) -{ - if (bp->bp_mode == BKPTMODE_DATAW) - dbregs[bp->bp_reg] = 0xffffffff; -} - -void -kdb_initdbregs(void) -{ - int i; - - for(i=0; i<KDB_DBREGS; i++) { - dbregs[i] = 0xffffffff; - } -} -int -kdbinstalltrap(int type, handler_t newh, handler_t *oldh) -{ - /* - * Usurp INTn. XXX - TBD. - */ - - return 0; -} - -int -install_instbkpt(kdb_bp_t *bp) -{ - unsigned long *addr = (unsigned long *)bp->bp_addr ; - bundle_t *bundle = (bundle_t *)bp->bp_longinst; - - /* save current bundle */ - *bundle = *(bundle_t *)addr ; - - /* Set the break point! */ - ((bundle_t *)addr)->lform.low8 = ( - (((bundle_t *)addr)->lform.low8 & ~INST_SLOT0_MASK) | - BREAK_INSTR); - - /* set flag */ - bp->bp_instvalid = 1 ; - - /* flush icache as it is stale now */ - ia64_flush_icache_page((unsigned long)addr) ; - -#ifdef KDB_DEBUG - kdb_printf ("[0x%016lx]: install 0x%016lx with 0x%016lx\n", - addr, bundle->lform.low8, addr[0]) ; -#endif - return 0 ; -} - -int -install_databkpt(kdb_bp_t *bp) -{ - unsigned long dbreg_addr = bp->bp_reg * 2; - unsigned long dbreg_cond = dbreg_addr + 1; - unsigned long value = 0x8fffffffffffffff; - unsigned long addr = (unsigned long)bp->bp_addr; - __asm__ ("mov dbr[%0]=%1"::"r"(dbreg_cond),"r"(value)); -// __asm__ ("movl %0,%%db0\n\t"::"r"(contents)); - __asm__ ("mov dbr[%0]=%1"::"r"(dbreg_addr),"r"(addr)); - ia64_insn_group_barrier(); - ia64_srlz_i(); - ia64_insn_group_barrier(); - -#ifdef KDB_DEBUG - kdb_printf("installed dbkpt at 0x%016lx\n", addr) ; -#endif - return 0; -} - -int -kdbinstalldbreg(kdb_bp_t *bp) -{ - if (bp->bp_mode == BKPTMODE_INST) { - return install_instbkpt(bp) ; - } else if (bp->bp_mode == BKPTMODE_DATAW) { - return install_databkpt(bp) ; - } - return 0; -} - -void -remove_instbkpt(kdb_bp_t *bp) -{ - unsigned long *addr = (unsigned long *)bp->bp_addr ; - bundle_t *bundle = (bundle_t *)bp->bp_longinst; - - if (!bp->bp_instvalid) - /* Nothing to remove. If we just alloced the bkpt - * but never resumed, the bp_inst will not be valid. */ - return ; - -#ifdef KDB_DEBUG - kdb_printf ("[0x%016lx]: remove 0x%016lx with 0x%016lx\n", - addr, addr[0], bundle->lform.low8) ; -#endif - - /* restore current bundle */ - *(bundle_t *)addr = *bundle ; - /* reset the flag */ - bp->bp_instvalid = 0 ; - ia64_flush_icache_page((unsigned long)addr) ; -} - -void -remove_databkpt(kdb_bp_t *bp) -{ - int regnum = bp->bp_reg ; - unsigned long dbreg_addr = regnum * 2; - unsigned long dbreg_cond = dbreg_addr + 1; - unsigned long value = 0x0fffffffffffffff; - __asm__ ("mov dbr[%0]=%1"::"r"(dbreg_cond),"r"(value)); -// __asm__ ("movl %0,%%db0\n\t"::"r"(contents)); - ia64_insn_group_barrier(); - ia64_srlz_i(); - ia64_insn_group_barrier(); - -#ifdef KDB_DEBUG - kdb_printf("removed dbkpt at 0x%016lx\n", bp->bp_addr) ; -#endif -} - -void -kdbremovedbreg(kdb_bp_t *bp) -{ - if (bp->bp_mode == BKPTMODE_INST) { - remove_instbkpt(bp) ; - } else if (bp->bp_mode == BKPTMODE_DATAW) { - remove_databkpt(bp) ; - } -} - -k_machreg_t -kdb_getdr6(void) -{ - return kdb_getdr(6); -} - -k_machreg_t -kdb_getdr7(void) -{ - return kdb_getdr(7); -} - -k_machreg_t -kdb_getdr(int regnum) -{ - k_machreg_t contents = 0; - unsigned long reg = (unsigned long)regnum; - - __asm__ ("mov %0=ibr[%1]"::"r"(contents),"r"(reg)); -// __asm__ ("mov ibr[%0]=%1"::"r"(dbreg_cond),"r"(value)); - - return contents; -} - - -k_machreg_t -kdb_getcr(int regnum) -{ - k_machreg_t contents = 0; - return contents; -} - -void -kdb_putdr6(k_machreg_t contents) -{ - kdb_putdr(6, contents); -} - -void -kdb_putdr7(k_machreg_t contents) -{ - kdb_putdr(7, contents); -} - -void -kdb_putdr(int regnum, k_machreg_t contents) -{ -} - -void -get_fault_regs(fault_regs_t *fr) -{ - fr->ifa = 0 ; - fr->isr = 0 ; - - __asm__ ("rsm psr.ic;;") ; - ia64_srlz_d(); - __asm__ ("mov %0=cr.ifa" : "=r"(fr->ifa)); - __asm__ ("mov %0=cr.isr" : "=r"(fr->isr)); - __asm__ ("ssm psr.ic;;") ; - ia64_srlz_d(); -} - -/* - * kdb_db_trap - * - * Perform breakpoint processing upon entry to the - * processor debugger fault. Determine and print - * the active breakpoint. - * - * Parameters: - * ef Exception frame containing machine register state - * reason Why did we enter kdb - fault or break - * Outputs: - * None. - * Returns: - * 0 Standard instruction or data breakpoint encountered - * 1 Single Step fault ('ss' command) - * 2 Single Step fault, caller should continue ('ssb' command) - * Locking: - * None. - * Remarks: - * Yup, there be goto's here. - */ - -int -kdb_db_trap(struct pt_regs *ef, int reason) -{ - int i, rv=0; - - /* Trying very hard to not change the interface to kdb. - * So, eventhough we have these values in the fault function - * it is not passed in but read again. - */ - fault_regs_t faultregs ; - - if (reason == KDB_REASON_FLTDBG) - get_fault_regs(&faultregs) ; - - /* NOTE : XXX: This has to be done only for data bkpts */ - /* Prevent it from continuously faulting */ - ef->cr_ipsr |= 0x0000002000000000; - - if (ef->cr_ipsr & 0x0000010000000000) { - /* single step */ - ef->cr_ipsr &= 0xfffffeffffffffff; - if ((kdb_state.bkpt_handling_state == BKPTSTATE_HANDLED) - && (kdb_state.cmd_given == CMDGIVEN_GO)) - ; - else - kdb_printf("SS trap at 0x%lx\n", ef->cr_iip + ia64_psr(ef)->ri); - rv = 1; - kdb_state.reason_for_entry = ENTRYREASON_SSTEP ; - goto handled; - } else - kdb_state.reason_for_entry = ENTRYREASON_GO ; - - /* - * Determine which breakpoint was encountered. - */ - for(i=0; i<KDB_MAXBPT; i++) { - if ((breakpoints[i].bp_enabled) - && ((breakpoints[i].bp_addr == ef->cr_iip) || - ((faultregs.ifa) && - (breakpoints[i].bp_addr == faultregs.ifa)))) { - /* - * Hit this breakpoint. Remove it while we are - * handling hit to avoid recursion. XXX ?? - */ - if (breakpoints[i].bp_addr == faultregs.ifa) - kdb_printf("Data breakpoint #%d for 0x%lx at 0x%lx\n", - i, breakpoints[i].bp_addr, ef->cr_iip + ia64_psr(ef)->ri); - else - kdb_printf("%s breakpoint #%d at 0x%lx\n", - rwtypes[0], - i, breakpoints[i].bp_addr); - - /* - * For an instruction breakpoint, disassemble - * the current instruction. - */ -#if 0 - if (rw == 0) { - kdb_id1(ef->eip); - } -#endif - - goto handled; - } - } - -#if 0 -unknown: -#endif - kdb_printf("Unknown breakpoint. Should forward. \n"); - /* Need a flag for this. The skip should be done XXX - * when a go or single step command is done for this session. - * For now it is here. - */ - ia64_increment_ip(ef) ; - return rv ; - -handled: - - /* We are here after handling a break inst/data bkpt */ - if (kdb_state.bkpt_handling_state == BKPTSTATE_NOT_HANDLED) { - kdb_state.bkpt_handling_state = BKPTSTATE_HANDLED ; - if (kdb_state.reason_for_entry == ENTRYREASON_GO) { - kdb_setsinglestep(ef) ; - kdb_state.kdb_action = ACTION_NOBPINSTALL; - /* We dont want bp install just this once */ - kdb_state.cmd_given = CMDGIVEN_UNKNOWN ; - } - } else if (kdb_state.bkpt_handling_state == BKPTSTATE_HANDLED) { - kdb_state.bkpt_handling_state = BKPTSTATE_NOT_HANDLED ; - if (kdb_state.reason_for_entry == ENTRYREASON_SSTEP) { - if (kdb_state.cmd_given == CMDGIVEN_GO) - kdb_state.kdb_action = ACTION_NOPROMPT ; - kdb_state.cmd_given = CMDGIVEN_UNKNOWN ; - } - } else - kdb_printf("Unknown value of bkpt state\n") ; - - return rv; - -} - -void -kdb_setsinglestep(struct pt_regs *regs) -{ - regs->cr_ipsr |= 0x0000010000000000; -#if 0 - regs->eflags |= EF_TF; -#endif -} - -/* - * Symbol table functions. - */ - -/* - * kdbgetsym - * - * Return the symbol table entry for the given symbol - * - * Parameters: - * symname Character string containing symbol name - * Outputs: - * Returns: - * NULL Symbol doesn't exist - * ksp Pointer to symbol table entry - * Locking: - * None. - * Remarks: - */ - -__ksymtab_t * -kdbgetsym(const char *symname) -{ - __ksymtab_t *ksp = __kdbsymtab; - int i; - - if (symname == NULL) - return NULL; - - for (i=0; i<__kdbsymtabsize; i++, ksp++) { - if (ksp->name && (strcmp(ksp->name, symname)==0)) { - return ksp; - } - } - - return NULL; -} - -/* - * kdbgetsymval - * - * Return the address of the given symbol. - * - * Parameters: - * symname Character string containing symbol name - * Outputs: - * Returns: - * 0 Symbol name is NULL - * addr Address corresponding to symname - * Locking: - * None. - * Remarks: - */ - -unsigned long -kdbgetsymval(const char *symname) -{ - __ksymtab_t *ksp = kdbgetsym(symname); - - return (ksp?ksp->value:0); -} - -/* - * kdbaddmodsym - * - * Add a symbol to the kernel debugger symbol table. Called when - * a new module is loaded into the kernel. - * - * Parameters: - * symname Character string containing symbol name - * value Value of symbol - * Outputs: - * Returns: - * 0 Successfully added to table. - * 1 Duplicate symbol - * 2 Symbol table full - * Locking: - * None. - * Remarks: - */ - -int -kdbaddmodsym(char *symname, unsigned long value) -{ - - /* - * Check for duplicate symbols. - */ - if (kdbgetsym(symname)) { - printk("kdb: Attempt to register duplicate symbol '%s' @ 0x%lx\n", - symname, value); - return 1; - } - - if (__kdbsymtabsize < __kdbmaxsymtabsize) { - __ksymtab_t *ksp = &__kdbsymtab[__kdbsymtabsize++]; - - ksp->name = symname; - ksp->value = value; - return 0; - } - - /* - * No room left in kernel symbol table. - */ - { - static int __kdbwarn = 0; - - if (__kdbwarn == 0) { - __kdbwarn++; - printk("kdb: Exceeded symbol table size. Increase CONFIG_KDB_SYMTAB_SIZE in kernel configuration\n"); - } - } - - return 2; -} - -/* - * kdbdelmodsym - * - * Add a symbol to the kernel debugger symbol table. Called when - * a new module is loaded into the kernel. - * - * Parameters: - * symname Character string containing symbol name - * value Value of symbol - * Outputs: - * Returns: - * 0 Successfully added to table. - * 1 Symbol not found - * Locking: - * None. - * Remarks: - */ - -int -kdbdelmodsym(const char *symname) -{ - __ksymtab_t *ksp, *endksp; - - if (symname == NULL) - return 1; - - /* - * Search for the symbol. If found, move - * all successive symbols down one position - * in the symbol table to avoid leaving holes. - */ - endksp = &__kdbsymtab[__kdbsymtabsize]; - for (ksp = __kdbsymtab; ksp < endksp; ksp++) { - if (ksp->name && (strcmp(ksp->name, symname) == 0)) { - endksp--; - for ( ; ksp < endksp; ksp++) { - *ksp = *(ksp + 1); - } - __kdbsymtabsize--; - return 0; - } - } - - return 1; -} - -/* - * kdbnearsym - * - * Return the name of the symbol with the nearest address - * less than 'addr'. - * - * Parameters: - * addr Address to check for symbol near - * Outputs: - * Returns: - * NULL No symbol with address less than 'addr' - * symbol Returns the actual name of the symbol. - * Locking: - * None. - * Remarks: - */ - -char * -kdbnearsym(unsigned long addr) -{ - __ksymtab_t *ksp = __kdbsymtab; - __ksymtab_t *kpp = NULL; - int i; - - for(i=0; i<__kdbsymtabsize; i++, ksp++) { - if (!ksp->name) - continue; - - if (addr == ksp->value) { - kpp = ksp; - break; - } - if (addr > ksp->value) { - if ((kpp == NULL) - || (ksp->value > kpp->value)) { - kpp = ksp; - } - } - } - - /* - * If more than 128k away, don't bother. - */ - if ((kpp == NULL) - || ((addr - kpp->value) > 0x20000)) { - return NULL; - } - - return kpp->name; -} - -/* - * kdbgetregcontents - * - * Return the contents of the register specified by the - * input string argument. Return an error if the string - * does not match a machine register. - * - * The following pseudo register names are supported: - * ®s - Prints address of exception frame - * kesp - Prints kernel stack pointer at time of fault - * sstk - Prints switch stack for ia64 - * %<regname> - Uses the value of the registers at the - * last time the user process entered kernel - * mode, instead of the registers at the time - * kdb was entered. - * - * Parameters: - * regname Pointer to string naming register - * regs Pointer to structure containing registers. - * Outputs: - * *contents Pointer to unsigned long to recieve register contents - * Returns: - * 0 Success - * KDB_BADREG Invalid register name - * Locking: - * None. - * Remarks: - * - * Note that this function is really machine independent. The kdb - * register list is not, however. - */ - -static struct kdbregs { - char *reg_name; - size_t reg_offset; -} kdbreglist[] = { - { " psr", offsetof(struct pt_regs, cr_ipsr) }, - { " ifs", offsetof(struct pt_regs, cr_ifs) }, - { " ip", offsetof(struct pt_regs, cr_iip) }, - - { "unat", offsetof(struct pt_regs, ar_unat) }, - { " pfs", offsetof(struct pt_regs, ar_pfs) }, - { " rsc", offsetof(struct pt_regs, ar_rsc) }, - - { "rnat", offsetof(struct pt_regs, ar_rnat) }, - { "bsps", offsetof(struct pt_regs, ar_bspstore) }, - { " pr", offsetof(struct pt_regs, pr) }, - - { "ldrs", offsetof(struct pt_regs, loadrs) }, - { " ccv", offsetof(struct pt_regs, ar_ccv) }, - { "fpsr", offsetof(struct pt_regs, ar_fpsr) }, - - { " b0", offsetof(struct pt_regs, b0) }, - { " b6", offsetof(struct pt_regs, b6) }, - { " b7", offsetof(struct pt_regs, b7) }, - - { " r1",offsetof(struct pt_regs, r1) }, - { " r2",offsetof(struct pt_regs, r2) }, - { " r3",offsetof(struct pt_regs, r3) }, - - { " r8",offsetof(struct pt_regs, r8) }, - { " r9",offsetof(struct pt_regs, r9) }, - { " r10",offsetof(struct pt_regs, r10) }, - - { " r11",offsetof(struct pt_regs, r11) }, - { " r12",offsetof(struct pt_regs, r12) }, - { " r13",offsetof(struct pt_regs, r13) }, - - { " r14",offsetof(struct pt_regs, r14) }, - { " r15",offsetof(struct pt_regs, r15) }, - { " r16",offsetof(struct pt_regs, r16) }, - - { " r17",offsetof(struct pt_regs, r17) }, - { " r18",offsetof(struct pt_regs, r18) }, - { " r19",offsetof(struct pt_regs, r19) }, - - { " r20",offsetof(struct pt_regs, r20) }, - { " r21",offsetof(struct pt_regs, r21) }, - { " r22",offsetof(struct pt_regs, r22) }, - - { " r23",offsetof(struct pt_regs, r23) }, - { " r24",offsetof(struct pt_regs, r24) }, - { " r25",offsetof(struct pt_regs, r25) }, - - { " r26",offsetof(struct pt_regs, r26) }, - { " r27",offsetof(struct pt_regs, r27) }, - { " r28",offsetof(struct pt_regs, r28) }, - - { " r29",offsetof(struct pt_regs, r29) }, - { " r30",offsetof(struct pt_regs, r30) }, - { " r31",offsetof(struct pt_regs, r31) }, - -}; - -static const int nkdbreglist = sizeof(kdbreglist) / sizeof(struct kdbregs); - -int -kdbgetregcontents(const char *regname, - struct pt_regs *regs, - unsigned long *contents) -{ - int i; - - if (strcmp(regname, "®s") == 0) { - *contents = (unsigned long)regs; - return 0; - } - - if (strcmp(regname, "sstk") == 0) { - *contents = (unsigned long)getprsregs(regs) ; - return 0; - } - - if (strcmp(regname, "isr") == 0) { - fault_regs_t fr ; - get_fault_regs(&fr) ; - *contents = fr.isr ; - return 0 ; - } - -#if 0 - /* XXX need to verify this */ - if (strcmp(regname, "kesp") == 0) { - *contents = (unsigned long)regs + sizeof(struct pt_regs); - return 0; - } - - if (regname[0] == '%') { - /* User registers: %%e[a-c]x, etc */ - regname++; - regs = (struct pt_regs *) - (current->thread.ksp - sizeof(struct pt_regs)); - } -#endif - - for (i=0; i<nkdbreglist; i++) { - if (strstr(kdbreglist[i].reg_name, regname)) - break; - } - - if (i == nkdbreglist) { - /* Lets check the rse maybe */ - if (regname[0] == 'r') - if (show_cur_stack_frame(regs, simple_strtoul(regname+1, 0, 0) - 31, - contents)) - return 0 ; - return KDB_BADREG; - } - - *contents = *(unsigned long *)((unsigned long)regs + - kdbreglist[i].reg_offset); - - return 0; -} - -/* - * kdbsetregcontents - * - * Set the contents of the register specified by the - * input string argument. Return an error if the string - * does not match a machine register. - * - * Supports modification of user-mode registers via - * %<register-name> - * - * Parameters: - * regname Pointer to string naming register - * regs Pointer to structure containing registers. - * contents Unsigned long containing new register contents - * Outputs: - * Returns: - * 0 Success - * KDB_BADREG Invalid register name - * Locking: - * None. - * Remarks: - */ - -int -kdbsetregcontents(const char *regname, - struct pt_regs *regs, - unsigned long contents) -{ - int i; - - if (regname[0] == '%') { - regname++; - regs = (struct pt_regs *) - (current->thread.ksp - sizeof(struct pt_regs)); - } - - for (i=0; i<nkdbreglist; i++) { - if (strnicmp(kdbreglist[i].reg_name, - regname, - strlen(regname)) == 0) - break; - } - - if ((i == nkdbreglist) - || (strlen(kdbreglist[i].reg_name) != strlen(regname))) { - return KDB_BADREG; - } - - *(unsigned long *)((unsigned long)regs + kdbreglist[i].reg_offset) = - contents; - - return 0; -} - -/* - * kdbdumpregs - * - * Dump the specified register set to the display. - * - * Parameters: - * regs Pointer to structure containing registers. - * type Character string identifying register set to dump - * extra string further identifying register (optional) - * Outputs: - * Returns: - * 0 Success - * Locking: - * None. - * Remarks: - * This function will dump the general register set if the type - * argument is NULL (struct pt_regs). The alternate register - * set types supported by this function: - * - * d Debug registers - * c Control registers - * u User registers at most recent entry to kernel - * Following not yet implemented: - * m Model Specific Registers (extra defines register #) - * r Memory Type Range Registers (extra defines register) - * - * For now, all registers are covered as follows: - * - * rd - dumps all regs - * rd %isr - current interrupt status reg, read freshly - * rd s - valid stacked regs - * rd %sstk - gets switch stack addr. dump memory and search - * rd d - debug regs, may not be too useful - * - * ARs TB Done - * Interrupt regs TB Done ?? - * OTHERS TB Decided ?? - * - * Intel wish list - * These will be implemented later - Srinivasa - * - * type action - * ---- ------ - * g dump all General static registers - * s dump all general Stacked registers - * f dump all Floating Point registers - * p dump all Predicate registers - * b dump all Branch registers - * a dump all Application registers - * c dump all Control registers - * - */ - -int -kdbdumpregs(struct pt_regs *regs, - const char *type, - const char *extra) - -{ - int i; - int count = 0; - - if (type - && (type[0] == 'u')) { - type = NULL; - regs = (struct pt_regs *) - (current->thread.ksp - sizeof(struct pt_regs)); - } - - if (type == NULL) { - for (i=0; i<nkdbreglist; i++) { - kdb_printf("%s: 0x%16.16lx ", - kdbreglist[i].reg_name, - *(unsigned long *)((unsigned long)regs + - kdbreglist[i].reg_offset)); - - if ((++count % 3) == 0) - kdb_printf("\n"); - } - - kdb_printf("®s = 0x%16.16lx\n", regs); - - return 0; - } - - switch (type[0]) { - case 'd': - { - for(i=0; i<8; i+=2) { - kdb_printf("idr%d: 0x%16.16lx idr%d: 0x%16.16lx\n", i, - kdb_getdr(i), i+1, kdb_getdr(i+1)); - - } - return 0; - } -#if 0 - case 'c': - { - unsigned long cr[5]; - - for (i=0; i<5; i++) { - cr[i] = kdb_getcr(i); - } - kdb_printf("cr0 = 0x%8.8x cr1 = 0x%8.8x cr2 = 0x%8.8x cr3 = 0x%8.8x\ncr4 = 0x%8.8x\n", - cr[0], cr[1], cr[2], cr[3], cr[4]); - return 0; - } -#endif - case 'm': - break; - case 'r': - break; - - case 's': - { - show_cur_stack_frame(regs, 0, NULL) ; - - return 0 ; - } - - case '%': - { - unsigned long contents ; - - if (!kdbgetregcontents(type+1, regs, &contents)) - kdb_printf("%s = 0x%16.16lx\n", type+1, contents) ; - else - kdb_printf("diag: Invalid register %s\n", type+1) ; - - return 0 ; - } - - default: - return KDB_BADREG; - } - - /* NOTREACHED */ - return 0; -} - -k_machreg_t -kdb_getpc(struct pt_regs *regs) -{ - return regs->cr_iip + ia64_psr(regs)->ri; -} - -int -kdb_setpc(struct pt_regs *regs, k_machreg_t newpc) -{ - regs->cr_iip = newpc & ~0xf; - ia64_psr(regs)->ri = newpc & 0x3; - return 0; -} - -void -kdb_disableint(kdbintstate_t *state) -{ - int *fp = (int *)state; - int flags; - - __save_flags(flags); - __cli(); - - *fp = flags; -} - -void -kdb_restoreint(kdbintstate_t *state) -{ - int flags = *(int *)state; - __restore_flags(flags); -} - -int -kdb_putword(unsigned long addr, unsigned long contents) -{ - *(unsigned long *)addr = contents; - return 0; -} - -int -kdb_getcurrentframe(struct pt_regs *regs) -{ -#if 0 - regs->xcs = 0; -#if defined(CONFIG_KDB_FRAMEPTR) - asm volatile("movl %%ebp,%0":"=m" (*(int *)®s->ebp)); -#endif - asm volatile("movl %%esp,%0":"=m" (*(int *)®s->esp)); -#endif - return 0; -} - -unsigned long -show_cur_stack_frame(struct pt_regs *regs, int regno, unsigned long *contents) -{ - long sof = regs->cr_ifs & ((1<<7)-1) ; /* size of frame */ - unsigned long i ; - int j; - struct switch_stack *prs_regs = getprsregs(regs) ; - unsigned long *sofptr = (prs_regs? ia64_rse_skip_regs( - (unsigned long *)prs_regs->ar_bspstore, -sof) : NULL) ; - - if (!sofptr) { - printk("Unable to display Current Stack Frame\n") ; - return 0 ; - } - - if (regno < 0) - return 0 ; - - for (i=sof, j=0;i;i--,j++) { - /* remember to skip the nat collection dword */ - if ((((unsigned long)sofptr>>3) & (((1<<6)-1))) - == ((1<<6)-1)) - sofptr++ ; - - /* return the value in the reg if regno is non zero */ - - if (regno) { - if ((j+1) == regno) { - if (contents) - *contents = *sofptr ; - return -1; - } - sofptr++ ; - } else { - printk(" r%d: %016lx ", 32+j, *sofptr++) ; - if (!((j+1)%3)) printk("\n") ; - } - } - - if (regno) { - if (!i) /* bogus rse number */ - return 0 ; - } else - printk("\n") ; - - return 0 ; -} diff --git a/arch/ia64/kdb/pc_keyb.h b/arch/ia64/kdb/pc_keyb.h deleted file mode 100644 index 3d4831a80..000000000 --- a/arch/ia64/kdb/pc_keyb.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * linux/drivers/char/pc_keyb.h - * - * PC Keyboard And Keyboard Controller - * - * (c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz> - */ - -/* - * Configuration Switches - */ - -#undef KBD_REPORT_ERR /* Report keyboard errors */ -#define KBD_REPORT_UNKN /* Report unknown scan codes */ -#define KBD_REPORT_TIMEOUTS /* Report keyboard timeouts */ -#undef KBD_IS_FOCUS_9000 /* We have the brain-damaged FOCUS-9000 keyboard */ -#undef INITIALIZE_MOUSE /* Define if your PS/2 mouse needs initialization. */ - - - -#define KBD_INIT_TIMEOUT 1000 /* Timeout in ms for initializing the keyboard */ -#define KBC_TIMEOUT 250 /* Timeout in ms for sending to keyboard controller */ -#define KBD_TIMEOUT 1000 /* Timeout in ms for keyboard command acknowledge */ - -/* - * Internal variables of the driver - */ - -extern unsigned char pckbd_read_mask; -extern unsigned char aux_device_present; - -/* - * Keyboard Controller Registers - */ - -#define KBD_STATUS_REG 0x64 /* Status register (R) */ -#define KBD_CNTL_REG 0x64 /* Controller command register (W) */ -#define KBD_DATA_REG 0x60 /* Keyboard data register (R/W) */ - -/* - * Keyboard Controller Commands - */ - -#define KBD_CCMD_READ_MODE 0x20 /* Read mode bits */ -#define KBD_CCMD_WRITE_MODE 0x60 /* Write mode bits */ -#define KBD_CCMD_GET_VERSION 0xA1 /* Get controller version */ -#define KBD_CCMD_MOUSE_DISABLE 0xA7 /* Disable mouse interface */ -#define KBD_CCMD_MOUSE_ENABLE 0xA8 /* Enable mouse interface */ -#define KBD_CCMD_TEST_MOUSE 0xA9 /* Mouse interface test */ -#define KBD_CCMD_SELF_TEST 0xAA /* Controller self test */ -#define KBD_CCMD_KBD_TEST 0xAB /* Keyboard interface test */ -#define KBD_CCMD_KBD_DISABLE 0xAD /* Keyboard interface disable */ -#define KBD_CCMD_KBD_ENABLE 0xAE /* Keyboard interface enable */ -#define KBD_CCMD_WRITE_AUX_OBUF 0xD3 /* Write to output buffer as if - initiated by the auxiliary device */ -#define KBD_CCMD_WRITE_MOUSE 0xD4 /* Write the following byte to the mouse */ - -/* - * Keyboard Commands - */ - -#define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */ -#define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */ -#define KBD_CMD_ENABLE 0xF4 /* Enable scanning */ -#define KBD_CMD_DISABLE 0xF5 /* Disable scanning */ -#define KBD_CMD_RESET 0xFF /* Reset */ - -/* - * Keyboard Replies - */ - -#define KBD_REPLY_POR 0xAA /* Power on reset */ -#define KBD_REPLY_ACK 0xFA /* Command ACK */ -#define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */ - -/* - * Status Register Bits - */ - -#define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */ -#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */ -#define KBD_STAT_SELFTEST 0x04 /* Self test successful */ -#define KBD_STAT_CMD 0x08 /* Last write was a command write (0=data) */ -#define KBD_STAT_UNLOCKED 0x10 /* Zero if keyboard locked */ -#define KBD_STAT_MOUSE_OBF 0x20 /* Mouse output buffer full */ -#define KBD_STAT_GTO 0x40 /* General receive/xmit timeout */ -#define KBD_STAT_PERR 0x80 /* Parity error */ - -#define AUX_STAT_OBF (KBD_STAT_OBF | KBD_STAT_MOUSE_OBF) - -/* - * Controller Mode Register Bits - */ - -#define KBD_MODE_KBD_INT 0x01 /* Keyboard data generate IRQ1 */ -#define KBD_MODE_MOUSE_INT 0x02 /* Mouse data generate IRQ12 */ -#define KBD_MODE_SYS 0x04 /* The system flag (?) */ -#define KBD_MODE_NO_KEYLOCK 0x08 /* The keylock doesn't affect the keyboard if set */ -#define KBD_MODE_DISABLE_KBD 0x10 /* Disable keyboard interface */ -#define KBD_MODE_DISABLE_MOUSE 0x20 /* Disable mouse interface */ -#define KBD_MODE_KCC 0x40 /* Scan code conversion to PC format */ -#define KBD_MODE_RFU 0x80 - -/* - * Mouse Commands - */ - -#define AUX_SET_RES 0xE8 /* Set resolution */ -#define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */ -#define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */ -#define AUX_GET_SCALE 0xE9 /* Get scaling factor */ -#define AUX_SET_STREAM 0xEA /* Set stream mode */ -#define AUX_SET_SAMPLE 0xF3 /* Set sample rate */ -#define AUX_ENABLE_DEV 0xF4 /* Enable aux device */ -#define AUX_DISABLE_DEV 0xF5 /* Disable aux device */ -#define AUX_RESET 0xFF /* Reset aux device */ - -#define AUX_BUF_SIZE 2048 - -struct aux_queue { - unsigned long head; - unsigned long tail; - struct wait_queue *proc_list; - struct fasync_struct *fasync; - unsigned char buf[AUX_BUF_SIZE]; -}; - diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile index 6631d33c3..225cbec5d 100644 --- a/arch/ia64/kernel/Makefile +++ b/arch/ia64/kernel/Makefile @@ -15,13 +15,13 @@ all: kernel.o head.o init_task.o O_TARGET := kernel.o -O_OBJS := acpi.o entry.o gate.o efi.o efi_stub.o irq.o irq_ia64.o irq_internal.o ivt.o \ - pal.o pci-dma.o process.o perfmon.o ptrace.o sal.o sal_stub.o semaphore.o setup.o signal.o \ - sys_ia64.o traps.o time.o unaligned.o unwind.o +O_OBJS := acpi.o entry.o gate.o efi.o efi_stub.o irq.o irq_ia64.o irq_sapic.o ivt.o \ + pal.o pci-dma.o process.o perfmon.o ptrace.o sal.o sal_stub.o semaphore.o setup.o \ + signal.o sys_ia64.o traps.o time.o unaligned.o unwind.o #O_OBJS := fpreg.o #OX_OBJS := ia64_ksyms.o -ifeq ($(CONFIG_IA64_GENERIC),y) +ifdef CONFIG_IA64_GENERIC O_OBJS += machvec.o endif @@ -30,10 +30,10 @@ O_OBJS += pci.o endif ifdef CONFIG_SMP -O_OBJS += smp.o irq_lock.o +O_OBJS += smp.o endif -ifeq ($(CONFIG_MCA),y) +ifdef CONFIG_IA64_MCA O_OBJS += mca.o mca_asm.o endif diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 078d908c8..72e10a683 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -11,12 +11,12 @@ #include <linux/config.h> #include <linux/init.h> -#include <linux/irq.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/smp.h> #include <linux/string.h> #include <linux/types.h> +#include <linux/irq.h> #include <asm/acpi-ext.h> #include <asm/page.h> @@ -27,13 +27,12 @@ #undef ACPI_DEBUG /* Guess what this does? */ #ifdef CONFIG_SMP -extern unsigned long ipi_base_addr; +extern struct smp_boot_data smp; #endif /* These are ugly but will be reclaimed by the kernel */ -int __initdata acpi_cpus = 0; -int __initdata acpi_apic_map[32]; -int __initdata cpu_cnt = 0; +int __initdata available_cpus = 0; +int __initdata total_cpus = 0; void (*pm_idle) (void); @@ -50,7 +49,7 @@ acpi_lsapic(char *p) if ((lsapic->flags & LSAPIC_PRESENT) == 0) return; - printk(" CPU %d (%.04x:%.04x): ", cpu_cnt, lsapic->eid, lsapic->id); + printk(" CPU %d (%.04x:%.04x): ", total_cpus, lsapic->eid, lsapic->id); if ((lsapic->flags & LSAPIC_ENABLED) == 0) { printk("Disabled.\n"); @@ -62,11 +61,17 @@ acpi_lsapic(char *p) if (add) { printk("Available.\n"); - acpi_cpus++; - acpi_apic_map[cpu_cnt] = (lsapic->id << 8) | lsapic->eid; + available_cpus++; +#ifdef CONFIG_SMP +# if LARGE_CPU_ID_OK + smp.cpu_map[total_cpus] = (lsapic->id << 8) | lsapic->eid; +# else + smp.cpu_map[total_cpus] = lsapic->id; +# endif +#endif } - cpu_cnt++; + total_cpus++; } /* @@ -174,7 +179,7 @@ acpi_legacy_irq(char *p) break; } -#ifdef ACPI_DEBUG +#if 1/*def ACPI_DEBUG*/ printk("Legacy ISA IRQ %x -> IA64 Vector %x IOSAPIC Pin %x Active %s %s Trigger\n", legacy->isa_irq, vector, iosapic_pin(vector), ((iosapic_polarity(vector) == IO_SAPIC_POL_LOW) ? "Low" : "High"), @@ -204,11 +209,11 @@ acpi_parse_msapic(acpi_sapic_t *msapic) { char *p, *end; - memset(&acpi_apic_map, -1, sizeof(acpi_apic_map)); + /* Base address of IPI Message Block */ + ipi_base_addr = (unsigned long) ioremap(msapic->interrupt_block, 0); #ifdef CONFIG_SMP - /* Base address of IPI Message Block */ - ipi_base_addr = ioremap(msapic->interrupt_block, 0); + memset(&smp, -1, sizeof(smp)); #endif p = (char *) (msapic + 1); @@ -238,11 +243,22 @@ acpi_parse_msapic(acpi_sapic_t *msapic) } /* Move to next table entry. */ - p += *(p + 1); +#define BAD_ACPI_TABLE +#ifdef BAD_ACPI_TABLE + /* + * Some prototype Lion's have a bad ACPI table + * requiring this fix. Without this fix, those + * machines crash during bootup. + */ + if (p[1] == 0) + p = end; + else +#endif + p += p[1]; } /* Make bootup pretty */ - printk(" %d CPUs available, %d CPUs total\n", acpi_cpus, cpu_cnt); + printk(" %d CPUs available, %d CPUs total\n", available_cpus, total_cpus); } int __init @@ -281,12 +297,15 @@ acpi_parse(acpi_rsdp_t *rsdp) continue; acpi_parse_msapic((acpi_sapic_t *) hdrp); - } /* while() */ + } - if (acpi_cpus == 0) { +#ifdef CONFIG_SMP + if (available_cpus == 0) { printk("ACPI: Found 0 CPUS; assuming 1\n"); - acpi_cpus = 1; /* We've got at least one of these, no? */ + available_cpus = 1; /* We've got at least one of these, no? */ } + smp.cpu_count = available_cpus; +#endif return 1; } diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index fc2d50558..0ce1db504 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c @@ -24,7 +24,7 @@ #include <asm/io.h> #include <asm/processor.h> -#define EFI_DEBUG +#define EFI_DEBUG 0 extern efi_status_t efi_call_phys (void *, ...); @@ -210,9 +210,8 @@ efi_memmap_walk (efi_freemem_callback_t callback, void *arg) void __init efi_init (void) { - void *efi_map_start, *efi_map_end, *p; + void *efi_map_start, *efi_map_end; efi_config_table_t *config_tables; - efi_memory_desc_t *md; efi_char16_t *c16; u64 efi_desc_size; char vendor[100] = "unknown"; @@ -278,13 +277,18 @@ efi_init (void) efi_map_end = efi_map_start + ia64_boot_param.efi_memmap_size; efi_desc_size = ia64_boot_param.efi_memdesc_size; -#ifdef EFI_DEBUG +#if EFI_DEBUG /* print EFI memory map: */ - for (i = 0, p = efi_map_start; p < efi_map_end; ++i, p += efi_desc_size) { - md = p; - printk("mem%02u: type=%u, attr=0x%lx, range=[0x%016lx-0x%016lx) (%luMB)\n", - i, md->type, md->attribute, - md->phys_addr, md->phys_addr + (md->num_pages<<12) - 1, md->num_pages >> 8); + { + efi_memory_desc_t *md = p; + void *p; + + for (i = 0, p = efi_map_start; p < efi_map_end; ++i, p += efi_desc_size) { + md = p; + printk("mem%02u: type=%u, attr=0x%lx, range=[0x%016lx-0x%016lx) (%luMB)\n", + i, md->type, md->attribute, md->phys_addr, + md->phys_addr + (md->num_pages<<12) - 1, md->num_pages >> 8); + } } #endif } diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index eb575a39c..755e3a0c1 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -25,6 +25,7 @@ #include <linux/config.h> +#include <asm/cache.h> #include <asm/errno.h> #include <asm/offsets.h> #include <asm/processor.h> @@ -228,11 +229,11 @@ save_switch_stack: stf.spill [r2]=f30,32 stf.spill [r3]=f31,24 ;; - st8.spill [r2]=r4,16 - st8.spill [r3]=r5,16 +.mem.offset 0,0; st8.spill [r2]=r4,16 +.mem.offset 8,0; st8.spill [r3]=r5,16 ;; - st8.spill [r2]=r6,16 - st8.spill [r3]=r7,16 +.mem.offset 0,0; st8.spill [r2]=r6,16 +.mem.offset 8,0; st8.spill [r3]=r7,16 ;; st8 [r2]=r21,16 // save b0 st8 [r3]=r22,16 // save b1 @@ -437,8 +438,8 @@ strace_check_retval: (p6) br.cond.sptk.few strace_error // syscall failed -> ;; // avoid RAW on r10 strace_save_retval: - st8.spill [r2]=r8 // store return value in slot for r8 - st8.spill [r3]=r10 // clear error indication in slot for r10 +.mem.offset 0,0; st8.spill [r2]=r8 // store return value in slot for r8 +.mem.offset 8,0; st8.spill [r3]=r10 // clear error indication in slot for r10 ia64_strace_leave_kernel: br.call.sptk.few rp=invoke_syscall_trace // give parent a chance to catch return value .ret6: br.cond.sptk.many ia64_leave_kernel @@ -491,7 +492,9 @@ ia64_ret_from_syscall: adds r2=IA64_PT_REGS_R8_OFFSET+16,sp // r2 = &pt_regs.r8 adds r3=IA64_PT_REGS_R8_OFFSET+32,sp // r3 = &pt_regs.r10 ;; + .mem.offset 0,0 (p6) st8.spill [r2]=r8 // store return value in slot for r8 and set unat bit + .mem.offset 8,0 (p6) st8.spill [r3]=r0 // clear error indication in slot for r10 and set unat bit (p7) br.cond.spnt.few handle_syscall_error // handle potential syscall failure @@ -504,7 +507,9 @@ ia64_leave_kernel: ;; ld4 r2=[r2] ;; - shladd r3=r2,3,r3 + shl r2=r2,SMP_LOG_CACHE_BYTES // can't use shladd here... + ;; + add r3=r2,r3 #else movl r3=softirq_state #endif @@ -550,6 +555,16 @@ back_from_resched: 2: // check & deliver pending signals: (p2) br.call.spnt.few rp=handle_signal_delivery +#if defined(CONFIG_SMP) || defined(CONFIG_IA64_SOFTSDV_HACKS) + // Check for lost ticks + mov r2 = ar.itc + mov r3 = cr.itm + ;; + sub r2 = r2, r3 + ;; + cmp.ge p6,p7 = r2, r0 +(p6) br.call.spnt.few rp=invoke_ia64_reset_itm +#endif restore_all: // start restoring the state saved on the kernel stack (struct pt_regs): @@ -735,8 +750,8 @@ handle_syscall_error: (p6) mov r9=r8 (p6) mov r10=0 ;; - st8.spill [r2]=r9 // store errno in pt_regs.r8 and set unat bit - st8.spill [r3]=r10 // store error indication in pt_regs.r10 and set unat bit +.mem.offset 0,0; st8.spill [r2]=r9 // store errno in pt_regs.r8 and set unat bit +.mem.offset 8,0; st8.spill [r3]=r10 // store error indication in pt_regs.r10 and set unat bit br.cond.sptk.many ia64_leave_kernel .endp handle_syscall_error @@ -757,6 +772,19 @@ invoke_schedule_tail: mov rp=loc1 br.ret.sptk.many rp .endp invoke_schedule_tail + + .proc invoke_ia64_reset_itm +invoke_ia64_reset_itm: + alloc loc0=ar.pfs,8,2,0,0 + mov loc1=rp + ;; + br.call.sptk.many rp=ia64_reset_itm + ;; + mov ar.pfs=loc0 + mov rp=loc1 + br.ret.sptk.many rp + .endp invoke_ia64_reset_itm + #endif /* CONFIG_SMP */ /* @@ -855,26 +883,22 @@ setup_switch_stack: .global sys_rt_sigsuspend sys_rt_sigsuspend: alloc loc0=ar.pfs,2,2,3,0 - mov r9=ar.unat // If the process is being ptraced, the signal may not actually be delivered to // the process. Instead, SIGCHLD will be sent to the parent. We need to // setup a switch_stack so ptrace can inspect the processes state if necessary. - adds r2=IA64_TASK_FLAGS_OFFSET,r13 - ;; - ld8 r2=[r2] + // Also, the process might not ptraced until stopped in sigsuspend, so this + // isn't something that we can do conditionally based upon the value of + // PF_PTRACED_BIT. mov out0=in0 // mask mov out1=in1 // sigsetsize ;; adds out2=16,sp // out1=&pt_regs - tbit.nz p16,p17=r2,PF_PTRACED_BIT -(p16) br.cond.spnt.many sigsuspend_setup_switch_stack + movl r28=back_from_sigsuspend_setup_switch_stack + mov r16=loc0 + br.cond.sptk.many save_switch_stack ;; back_from_sigsuspend_setup_switch_stack: - adds r3=-IA64_SWITCH_STACK_SIZE+IA64_SWITCH_STACK_CALLER_UNAT_OFFSET+16,sp -(p17) adds sp=-IA64_SWITCH_STACK_SIZE,sp // make space for (dummy) switch_stack - ;; -(p17) st8 [r3]=r9 // save ar.unat in sw->caller_unat mov loc1=rp // save return address br.call.sptk.many rp=ia64_rt_sigsuspend .ret12: @@ -883,32 +907,22 @@ back_from_sigsuspend_setup_switch_stack: ld8 r9=[r3] // load new unat from sw->caller_unat mov rp=loc1 ;; -(p17) adds sp=IA64_SWITCH_STACK_SIZE,sp // drop (dummy) switch_stack -(p17) mov ar.unat=r9 -(p17) mov ar.pfs=loc0 -(p17) br.ret.sptk.many rp // restore the switch stack (ptrace may have modified it): movl r28=1f br.cond.sptk.many load_switch_stack 1: br.ret.sptk.many rp // NOT REACHED - -sigsuspend_setup_switch_stack: - movl r28=back_from_sigsuspend_setup_switch_stack - mov r16=loc0 - br.cond.sptk.many save_switch_stack - // NOT REACHED - .endp sys_rt_sigsuspend .align 16 .proc sys_rt_sigreturn sys_rt_sigreturn: - alloc loc0=ar.pfs,8,1,1,0 // preserve all eight input regs in case of syscall restart! + .regstk 0,0,3,0 // inherited from gate.s:invoke_sighandler() adds out0=16,sp // out0 = &pt_regs - ;; adds sp=-IA64_SWITCH_STACK_SIZE,sp // make space for unat and padding + ;; + cmp.eq pNonSys,p0=r0,r0 // sigreturn isn't a normal syscall... br.call.sptk.few rp=ia64_rt_sigreturn .ret13: adds r3=IA64_SWITCH_STACK_CALLER_UNAT_OFFSET+16,sp @@ -918,8 +932,7 @@ sys_rt_sigreturn: ;; adds sp=IA64_SWITCH_STACK_SIZE,sp // drop (dummy) switch-stack frame mov ar.unat=r9 - mov ar.pfs=loc0 - br.ret.sptk.many rp + br rp .endp sys_rt_sigreturn .align 16 @@ -940,76 +953,6 @@ ia64_prepare_handle_unaligned: 2: br.cond.sptk.many rp // goes to ia64_leave_kernel .endp ia64_prepare_handle_unaligned -#ifdef CONFIG_KDB - // - // This gets called from ivt.S with: - // SAVE MIN with cover done - // SAVE REST done - // no parameters - // r15 has return value = ia64_leave_kernel - // - .align 16 - .global ia64_invoke_kdb - .proc ia64_invoke_kdb -ia64_invoke_kdb: - alloc r16=ar.pfs,0,0,4,0 - movl r28=1f // save_switch_stack protocol - ;; // avoid WAW on CFM - br.cond.sptk.many save_switch_stack // to flushrs -1: mov out0=4 // kdb entry reason - mov out1=0 // err number - adds out2=IA64_SWITCH_STACK_SIZE+16,sp // pt_regs - add out3=16,sp // switch_stack - br.call.sptk.few rp=kdb -.ret15: - movl r28=1f // load_switch_stack proto - br.cond.sptk.many load_switch_stack -1: br.ret.sptk.many rp - .endp ia64_invoke_kdb - - // - // When KDB is compiled in, we intercept each fault and give - // kdb a chance to run before calling the normal fault handler. - // - .align 16 - .global ia64_invoke_kdb_fault_handler - .proc ia64_invoke_kdb_fault_handler -ia64_invoke_kdb_fault_handler: - alloc r16=ar.pfs,5,1,5,0 - movl r28=1f - mov loc0=rp // save this - br.cond.sptk.many save_switch_stack // to flushrs - ;; // avoid WAW on CFM -1: mov out0=in0 // vector number - mov out1=in1 // cr.isr - mov out2=in2 // cr.ifa - mov out3=in3 // cr.iim - mov out4=in4 // cr.itir - br.call.sptk.few rp=ia64_kdb_fault_handler -.ret16: - - movl r28=1f - br.cond.sptk.many load_switch_stack -1: cmp.ne p6,p0=r8,r0 // did ia64_kdb_fault_handler return 0? - mov rp=loc0 -(p6) br.ret.spnt.many rp // no, we're done - ;; // avoid WAW on rp - mov out0=in0 // vector number - mov out1=in1 // cr.isr - mov out2=in2 // cr.ifa - mov out3=in3 // cr.iim - mov out4=in4 // cr.itir - mov in0=ar.pfs // preserve ar.pfs returned by load_switch_stack - br.call.sptk.few rp=ia64_fault // yup -> we need to invoke normal fault handler now -.ret17: - mov ar.pfs=in0 - mov rp=loc0 - br.ret.sptk.many rp - - .endp ia64_invoke_kdb_fault_handler - -#endif /* CONFIG_KDB */ - .rodata .align 8 .globl sys_call_table @@ -1198,8 +1141,8 @@ sys_call_table: data8 sys_sendmsg // 1205 data8 sys_recvmsg data8 sys_pivot_root - data8 ia64_ni_syscall - data8 ia64_ni_syscall + data8 sys_mincore + data8 sys_madvise data8 ia64_ni_syscall // 1210 data8 ia64_ni_syscall data8 ia64_ni_syscall diff --git a/arch/ia64/kernel/gate.S b/arch/ia64/kernel/gate.S index a710870c0..8eabe53d1 100644 --- a/arch/ia64/kernel/gate.S +++ b/arch/ia64/kernel/gate.S @@ -80,8 +80,6 @@ ia64_sigtramp: ld8 r10=[r3],8 // get signal handler entry point br.call.sptk.many rp=invoke_sighandler -.ret0: mov r15=__NR_rt_sigreturn - break __BREAK_SYSCALL .endp ia64_sigtramp .proc invoke_sighandler @@ -90,10 +88,9 @@ invoke_sighandler: mov b6=r10 cover // push args in interrupted frame onto backing store ;; - alloc r8=ar.pfs,0,1,3,0 // get CFM0, EC0, and CPL0 into r8 - mov r17=ar.bsp // fetch ar.bsp - mov loc0=rp // save return pointer + alloc r8=ar.pfs,0,0,3,0 // get CFM0, EC0, and CPL0 into r8 ;; + mov r17=ar.bsp // fetch ar.bsp cmp.ne p8,p0=r15,r0 // do we need to switch the rbs? mov out0=r2 // signal number (p8) br.cond.spnt.few setup_rbs // yup -> (clobbers r14 and r16) @@ -101,10 +98,11 @@ back_from_setup_rbs: adds base0=(BSP_OFF+SIGCONTEXT_OFF),sp ;; st8 [base0]=r17,(CFM_OFF-BSP_OFF) // save sc_ar_bsp + dep r8=0,r8,38,26 // clear EC0, CPL0 and reserved bits adds base1=(FR6_OFF+16+SIGCONTEXT_OFF),sp ;; - st8 [base0]=r8 // save CFM0, EC0, and CPL0 + st8 [base0]=r8 // save CFM0 adds base0=(FR6_OFF+SIGCONTEXT_OFF),sp ;; stf.spill [base0]=f6,32 @@ -124,7 +122,8 @@ back_from_setup_rbs: stf.spill [base0]=f14,32 stf.spill [base1]=f15,32 br.call.sptk.few rp=b6 // call the signal handler -.ret2: adds base0=(BSP_OFF+SIGCONTEXT_OFF),sp +.ret2: + adds base0=(BSP_OFF+SIGCONTEXT_OFF),sp ;; ld8 r15=[base0],(CFM_OFF-BSP_OFF) // fetch sc_ar_bsp and advance to CFM_OFF mov r14=ar.bsp @@ -134,23 +133,11 @@ back_from_setup_rbs: (p8) br.cond.spnt.few restore_rbs // yup -> (clobbers r14 and r16) ;; back_from_restore_rbs: - { - and r9=0x7f,r8 // r9 <- CFM0.sof - extr.u r10=r8,7,7 // r10 <- CFM0.sol - mov r11=ip - } - ;; adds base0=(FR6_OFF+SIGCONTEXT_OFF),sp - adds r11=(cont-back_from_restore_rbs),r11 - sub r9=r9,r10 // r9 <- CFM0.sof - CFM0.sol == CFM0.nout - ;; adds base1=(FR6_OFF+16+SIGCONTEXT_OFF),sp - dep r9=r9,r9,7,7 // r9.sol = r9.sof - mov b6=r11 ;; ldf.fill f6=[base0],32 ldf.fill f7=[base1],32 - mov rp=loc0 // copy return pointer out of stacked register ;; ldf.fill f8=[base0],32 ldf.fill f9=[base1],32 @@ -160,26 +147,23 @@ back_from_restore_rbs: ;; ldf.fill f12=[base0],32 ldf.fill f13=[base1],32 - mov ar.pfs=r9 ;; ldf.fill f14=[base0],32 ldf.fill f15=[base1],32 - br.ret.sptk.few b6 -cont: mov ar.pfs=r8 // ar.pfs = CFM0 - br.ret.sptk.few rp // re-establish CFM0 + mov r15=__NR_rt_sigreturn + break __BREAK_SYSCALL .endp invoke_sighandler .proc setup_rbs setup_rbs: flushrs // must be first in insn - ;; mov ar.rsc=r0 // put RSE into enforced lazy mode adds r16=(RNAT_OFF+SIGCONTEXT_OFF),sp - mov r14=ar.rnat // get rnat as updated by flushrs ;; + mov r14=ar.rnat // get rnat as updated by flushrs mov ar.bspstore=r15 // set new register backing store area - st8 [r16]=r14 // save sc_ar_rnat ;; + st8 [r16]=r14 // save sc_ar_rnat mov ar.rsc=0xf // set RSE into eager mode, pl 3 invala // invalidate ALAT br.cond.sptk.many back_from_setup_rbs diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c index 0ddfe3f05..a01432a60 100644 --- a/arch/ia64/kernel/irq.c +++ b/arch/ia64/kernel/irq.c @@ -66,7 +66,7 @@ irq_cpustat_t irq_stat [NR_CPUS]; * Controller mappings for all interrupt sources: */ irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = - { [0 ... NR_IRQS-1] = { 0, &no_irq_type, NULL, 0, SPIN_LOCK_UNLOCKED}}; + { [0 ... NR_IRQS-1] = { IRQ_DISABLED, &no_irq_type, NULL, 0, SPIN_LOCK_UNLOCKED}}; static void register_irq_proc (unsigned int irq); @@ -164,7 +164,7 @@ int get_irq_list(char *buf) p += sprintf(p, "%10u ", atomic_read(&nmi_counter(cpu_logical_map(j)))); p += sprintf(p, "\n"); -#if CONFIG_SMP +#if defined(CONFIG_SMP) && defined(__i386__) p += sprintf(p, "LOC: "); for (j = 0; j < smp_num_cpus; j++) p += sprintf(p, "%10u ", @@ -182,8 +182,8 @@ int get_irq_list(char *buf) */ #ifdef CONFIG_SMP -unsigned char global_irq_holder = NO_PROC_ID; -unsigned volatile int global_irq_lock; +unsigned int global_irq_holder = NO_PROC_ID; +volatile unsigned int global_irq_lock; extern void show_stack(unsigned long* esp); @@ -201,6 +201,10 @@ static void show(char * str) printk(" %d",local_bh_count(i)); printk(" ]\nStack dumps:"); +#ifdef __ia64__ + printk(" ]\nStack dumps: <unimplemented on IA-64---please fix me>"); + /* for now we don't have stack dumping support... */ +#elif __i386__ for(i=0;i< smp_num_cpus;i++) { unsigned long esp; if(i==cpu) @@ -219,8 +223,13 @@ static void show(char * str) esp += sizeof(struct task_struct); show_stack((void*)esp); } +#else + You lose... +#endif printk("\nCPU %d:",cpu); +#ifdef __i386__ show_stack(NULL); +#endif printk("\n"); } @@ -250,7 +259,11 @@ static void show(char * str) /* * We have to allow irqs to arrive between __sti and __cli */ -# define SYNC_OTHER_CORES(x) __asm__ __volatile__ ("nop") +# ifdef __ia64__ +# define SYNC_OTHER_CORES(x) __asm__ __volatile__ ("nop 0") +# else +# define SYNC_OTHER_CORES(x) __asm__ __volatile__ ("nop") +# endif #endif static inline void wait_on_irq(int cpu) @@ -311,7 +324,7 @@ static inline void get_irqlock(int cpu) { if (test_and_set_bit(0,&global_irq_lock)) { /* do we already hold the lock? */ - if ((unsigned char) cpu == global_irq_holder) + if (cpu == global_irq_holder) return; /* Uhhuh.. Somebody else got it. Wait.. */ do { @@ -349,6 +362,15 @@ void __global_cli(void) { unsigned int flags; +#ifdef __ia64__ + __save_flags(flags); + if (flags & IA64_PSR_I) { + int cpu = smp_processor_id(); + __cli(); + if (!local_irq_count(cpu)) + get_irqlock(cpu); + } +#else __save_flags(flags); if (flags & (1 << EFLAGS_IF_SHIFT)) { int cpu = smp_processor_id(); @@ -356,6 +378,7 @@ void __global_cli(void) if (!local_irq_count(cpu)) get_irqlock(cpu); } +#endif } void __global_sti(void) @@ -382,7 +405,11 @@ unsigned long __global_save_flags(void) int cpu = smp_processor_id(); __save_flags(flags); +#ifdef __ia64__ + local_enabled = (flags & IA64_PSR_I) != 0; +#else local_enabled = (flags >> EFLAGS_IF_SHIFT) & 1; +#endif /* default to local */ retval = 2 + local_enabled; @@ -479,11 +506,13 @@ void disable_irq(unsigned int irq) { disable_irq_nosync(irq); +#ifdef CONFIG_SMP if (!local_irq_count(smp_processor_id())) { do { barrier(); } while (irq_desc[irq].status & IRQ_INPROGRESS); } +#endif } void enable_irq(unsigned int irq) @@ -559,15 +588,12 @@ unsigned int do_IRQ(unsigned long irq, struct pt_regs *regs) /* * If there is no IRQ handler or it was disabled, exit early. - Since we set PENDING, if another processor is handling - a different instance of this same irq, the other processor - will take care of it. + * Since we set PENDING, if another processor is handling + * a different instance of this same irq, the other processor + * will take care of it. */ if (!action) -{ - desc->status = status & ~IRQ_INPROGRESS; goto out; -} /* * Edge triggered interrupts need to remember @@ -597,15 +623,6 @@ out: desc->handler->end(irq); spin_unlock(&desc->lock); -#if 0 - /* - * let kernel exit path take care of this; we want to do the - * CPU EOI before doing softirq() so a new interrupt can come - * through - */ - if (softirq_state[cpu].active & softirq_state[cpu].mask) - do_softirq(); -#endif return 1; } @@ -1019,7 +1036,7 @@ static void register_irq_proc (unsigned int irq) irq_dir[irq] = proc_mkdir(name, root_irq_dir); /* create /proc/irq/1234/smp_affinity */ - entry = create_proc_entry("smp_affinity", 0700, irq_dir[irq]); + entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]); entry->nlink = 1; entry->data = (void *)(long)irq; @@ -1040,7 +1057,7 @@ void init_irq_proc (void) root_irq_dir = proc_mkdir("irq", 0); /* create /proc/irq/prof_cpu_mask */ - entry = create_proc_entry("prof_cpu_mask", 0700, root_irq_dir); + entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir); entry->nlink = 1; entry->data = (void *)&prof_cpu_mask; diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index a2c493ba5..1a8398f85 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c @@ -25,10 +25,6 @@ #include <linux/smp_lock.h> #include <linux/threads.h> -#ifdef CONFIG_KDB -# include <linux/kdb.h> -#endif - #include <asm/bitops.h> #include <asm/delay.h> #include <asm/io.h> @@ -41,13 +37,15 @@ spinlock_t ivr_read_lock; #endif +unsigned long ipi_base_addr = IPI_DEFAULT_BASE_ADDR; /* default base addr of IPI table */ + /* * Legacy IRQ to IA-64 vector translation table. Any vector not in * this table maps to itself (ie: irq 0x30 => IA64 vector 0x30) */ -__u8 isa_irq_to_vector_map[IA64_MIN_VECTORED_IRQ] = { +__u8 isa_irq_to_vector_map[16] = { /* 8259 IRQ translation, first 16 entries */ - 0x60, 0x50, 0x0f, 0x51, 0x52, 0x53, 0x43, 0x54, + 0x60, 0x50, 0x10, 0x51, 0x52, 0x53, 0x43, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x40, 0x41 }; @@ -80,8 +78,8 @@ ia64_handle_irq (unsigned long vector, struct pt_regs *regs) #ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC # ifndef CONFIG_SMP static unsigned int max_prio = 0; -# endif unsigned int prev_prio; +# endif unsigned long eoi_ptr; # ifdef CONFIG_USB @@ -95,21 +93,25 @@ ia64_handle_irq (unsigned long vector, struct pt_regs *regs) * Stop IPIs by getting the ivr_read_lock */ spin_lock(&ivr_read_lock); + { + unsigned int tmp; - /* - * Disable PCI writes - */ - outl(0x80ff81c0, 0xcf8); - outl(0x73002188, 0xcfc); - eoi_ptr = inl(0xcfc); + /* + * Disable PCI writes + */ + outl(0x80ff81c0, 0xcf8); + tmp = inl(0xcfc); + outl(tmp | 0x400, 0xcfc); - vector = ia64_get_ivr(); + eoi_ptr = inl(0xcfc); - /* - * Enable PCI writes - */ - outl(0x73182188, 0xcfc); + vector = ia64_get_ivr(); + /* + * Enable PCI writes + */ + outl(tmp, 0xcfc); + } spin_unlock(&ivr_read_lock); # ifdef CONFIG_USB @@ -152,9 +154,6 @@ ia64_handle_irq (unsigned long vector, struct pt_regs *regs) printk("ia64_handle_irq: DANGER: less than 1KB of free stack space!!\n" "(bsp=0x%lx, sp=%lx)\n", bsp, sp); } -#ifdef CONFIG_KDB - kdb(KDB_REASON_PANIC, 0, regs); -#endif } /* @@ -175,9 +174,6 @@ ia64_handle_irq (unsigned long vector, struct pt_regs *regs) if (!pEOI) { printk("Yikes: ia64_handle_irq() without pEOI!!\n"); asm volatile ("cmp.eq p1,p0=r0,r0" : "=r"(pEOI)); -# ifdef CONFIG_KDB - kdb(KDB_REASON_PANIC, 0, regs); -# endif } } @@ -195,13 +191,13 @@ ia64_handle_irq (unsigned long vector, struct pt_regs *regs) #ifdef CONFIG_SMP -void __init -init_IRQ_SMP (void) -{ - if (request_irq(IPI_IRQ, handle_IPI, 0, "IPI", NULL)) - panic("Could not allocate IPI Interrupt Handler!"); -} +extern void handle_IPI (int irq, void *dev_id, struct pt_regs *regs); +static struct irqaction ipi_irqaction = { + handler: handle_IPI, + flags: SA_INTERRUPT, + name: "IPI" +}; #endif void __init @@ -214,13 +210,14 @@ init_IRQ (void) ia64_set_lrr0(0, 1); ia64_set_lrr1(0, 1); - irq_desc[TIMER_IRQ].handler = &irq_type_ia64_internal; + irq_desc[TIMER_IRQ].handler = &irq_type_ia64_sapic; + irq_desc[IA64_SPURIOUS_INT].handler = &irq_type_ia64_sapic; #ifdef CONFIG_SMP /* * Configure the IPI vector and handler */ - irq_desc[IPI_IRQ].handler = &irq_type_ia64_internal; - init_IRQ_SMP(); + irq_desc[IPI_IRQ].handler = &irq_type_ia64_sapic; + setup_irq(IPI_IRQ, &ipi_irqaction); #endif ia64_set_pmv(1 << 16); @@ -232,16 +229,26 @@ init_IRQ (void) ia64_set_tpr(0); } -/* TBD: - * Certain IA64 platforms can have inter-processor interrupt support. - * This interface is supposed to default to the IA64 IPI block-based - * mechanism if the platform doesn't provide a separate mechanism - * for IPIs. - * Choices : (1) Extend hw_interrupt_type interfaces - * (2) Use machine vector mechanism - * For now defining the following interface as a place holder. - */ void -ipi_send (int cpu, int vector, int delivery_mode) +ipi_send (int cpu, int vector, int delivery_mode, int redirect) { + unsigned long ipi_addr; + unsigned long ipi_data; +#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC + unsigned long flags; +#endif +# define EID 0 + + ipi_data = (delivery_mode << 8) | (vector & 0xff); + ipi_addr = ipi_base_addr | ((cpu << 8 | EID) << 4) | ((redirect & 1) << 3); + +#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC + spin_lock_irqsave(&ivr_read_lock, flags); +#endif /* CONFIG_ITANIUM_ASTEP_SPECIFIC */ + + writeq(ipi_data, ipi_addr); + +#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC + spin_unlock_irqrestore(&ivr_read_lock, flags); +#endif } diff --git a/arch/ia64/kernel/irq_internal.c b/arch/ia64/kernel/irq_internal.c deleted file mode 100644 index 2b768cec1..000000000 --- a/arch/ia64/kernel/irq_internal.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Internal Interrupt Vectors - * - * This takes care of interrupts that are generated by the CPU - * internally, such as the ITC and IPI interrupts. - * - * Copyright (C) 1999 VA Linux Systems - * Copyright (C) 1999 Walt Drummond <drummond@valinux.com> - * Copyright (C) 2000 Hewlett-Packard Co - * Copyright (C) 2000 David Mosberger-Tang <davidm@hpl.hp.com> - */ - -#include <linux/irq.h> - -static unsigned int -internal_noop_startup (unsigned int irq) -{ - return 0; -} - -static void -internal_noop (unsigned int irq) -{ - /* nuthing to do... */ -} - -struct hw_interrupt_type irq_type_ia64_internal = { - typename: "IA64-internal", - startup: internal_noop_startup, - shutdown: internal_noop, - enable: internal_noop, - disable: internal_noop, - ack: internal_noop, - end: internal_noop, - set_affinity: (void (*)(unsigned int, unsigned long)) internal_noop -}; diff --git a/arch/ia64/kernel/irq_lock.c b/arch/ia64/kernel/irq_lock.c deleted file mode 100644 index 43afeac60..000000000 --- a/arch/ia64/kernel/irq_lock.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * SMP IRQ Lock support - * - * Global interrupt locks for SMP. Allow interrupts to come in on any - * CPU, yet make cli/sti act globally to protect critical regions.. - * These function usually appear in irq.c, but I think it's cleaner this way. - * - * Copyright (C) 1999 VA Linux Systems - * Copyright (C) 1999 Walt Drummond <drummond@valinux.com> - */ - -#include <linux/sched.h> -#include <linux/interrupt.h> -#include <linux/smp.h> -#include <linux/threads.h> -#include <linux/init.h> - -#include <asm/system.h> -#include <asm/processor.h> -#include <asm/irq.h> -#include <asm/bitops.h> -#include <asm/pgtable.h> -#include <asm/delay.h> - -int global_irq_holder = NO_PROC_ID; -spinlock_t global_irq_lock; -atomic_t global_irq_count; -atomic_t global_bh_count; -spinlock_t global_bh_lock; - -#define INIT_STUCK (1<<26) - -void -irq_enter(int cpu, int irq) -{ - int stuck = INIT_STUCK; - - hardirq_enter(cpu, irq); - barrier(); - while (global_irq_lock.lock) { - if (cpu == global_irq_holder) { - break; - } - - if (!--stuck) { - printk("irq_enter stuck (irq=%d, cpu=%d, global=%d)\n", - irq, cpu,global_irq_holder); - stuck = INIT_STUCK; - } - barrier(); - } -} - -void -irq_exit(int cpu, int irq) -{ - hardirq_exit(cpu, irq); - release_irqlock(cpu); -} - -static void -show(char * str) -{ - int i; - unsigned long *stack; - int cpu = smp_processor_id(); - - printk("\n%s, CPU %d:\n", str, cpu); - printk("irq: %d [%d %d]\n", - atomic_read(&global_irq_count), local_irq_count[0], local_irq_count[1]); - printk("bh: %d [%d %d]\n", - atomic_read(&global_bh_count), local_bh_count[0], local_bh_count[1]); - - stack = (unsigned long *) &stack; - for (i = 40; i ; i--) { - unsigned long x = *++stack; - if (x > (unsigned long) &get_options && x < (unsigned long) &vsprintf) { - printk("<[%08lx]> ", x); - } - } -} - -#define MAXCOUNT 100000000 - -static inline void -wait_on_bh(void) -{ - int count = MAXCOUNT; - do { - if (!--count) { - show("wait_on_bh"); - count = ~0; - } - /* nothing .. wait for the other bh's to go away */ - } while (atomic_read(&global_bh_count) != 0); -} - -static inline void -wait_on_irq(int cpu) -{ - int count = MAXCOUNT; - - for (;;) { - - /* - * Wait until all interrupts are gone. Wait - * for bottom half handlers unless we're - * already executing in one.. - */ - if (!atomic_read(&global_irq_count)) { - if (local_bh_count[cpu] || !atomic_read(&global_bh_count)) - break; - } - - /* Duh, we have to loop. Release the lock to avoid deadlocks */ - spin_unlock(&global_irq_lock); - mb(); - - for (;;) { - if (!--count) { - show("wait_on_irq"); - count = ~0; - } - __sti(); - udelay(cpu + 1); - __cli(); - if (atomic_read(&global_irq_count)) - continue; - if (global_irq_lock.lock) - continue; - if (!local_bh_count[cpu] && atomic_read(&global_bh_count)) - continue; - if (spin_trylock(&global_irq_lock)) - break; - } - } -} - -/* - * This is called when we want to synchronize with - * bottom half handlers. We need to wait until - * no other CPU is executing any bottom half handler. - * - * Don't wait if we're already running in an interrupt - * context or are inside a bh handler. - */ -void -synchronize_bh(void) -{ - if (atomic_read(&global_bh_count)) { - int cpu = smp_processor_id(); - if (!local_irq_count[cpu] && !local_bh_count[cpu]) { - wait_on_bh(); - } - } -} - - -/* - * This is called when we want to synchronize with - * interrupts. We may for example tell a device to - * stop sending interrupts: but to make sure there - * are no interrupts that are executing on another - * CPU we need to call this function. - */ -void -synchronize_irq(void) -{ - int cpu = smp_processor_id(); - int local_count; - int global_count; - - mb(); - do { - local_count = local_irq_count[cpu]; - global_count = atomic_read(&global_irq_count); - } while (global_count != local_count); -} - -static inline void -get_irqlock(int cpu) -{ - if (!spin_trylock(&global_irq_lock)) { - /* do we already hold the lock? */ - if ((unsigned char) cpu == global_irq_holder) - return; - /* Uhhuh.. Somebody else got it. Wait.. */ - spin_lock(&global_irq_lock); - } - /* - * We also to make sure that nobody else is running - * in an interrupt context. - */ - wait_on_irq(cpu); - - /* - * Ok, finally.. - */ - global_irq_holder = cpu; -} - -/* - * A global "cli()" while in an interrupt context - * turns into just a local cli(). Interrupts - * should use spinlocks for the (very unlikely) - * case that they ever want to protect against - * each other. - * - * If we already have local interrupts disabled, - * this will not turn a local disable into a - * global one (problems with spinlocks: this makes - * save_flags+cli+sti usable inside a spinlock). - */ -void -__global_cli(void) -{ - unsigned long flags; - - __save_flags(flags); - if (flags & IA64_PSR_I) { - int cpu = smp_processor_id(); - __cli(); - if (!local_irq_count[cpu]) - get_irqlock(cpu); - } -} - -void -__global_sti(void) -{ - int cpu = smp_processor_id(); - - if (!local_irq_count[cpu]) - release_irqlock(cpu); - __sti(); -} - -/* - * SMP flags value to restore to: - * 0 - global cli - * 1 - global sti - * 2 - local cli - * 3 - local sti - */ -unsigned long -__global_save_flags(void) -{ - int retval; - int local_enabled; - unsigned long flags; - - __save_flags(flags); - local_enabled = flags & IA64_PSR_I; - /* default to local */ - retval = 2 + local_enabled; - - /* check for global flags if we're not in an interrupt */ - if (!local_irq_count[smp_processor_id()]) { - if (local_enabled) - retval = 1; - if (global_irq_holder == (unsigned char) smp_processor_id()) - retval = 0; - } - return retval; -} - -void -__global_restore_flags(unsigned long flags) -{ - switch (flags) { - case 0: - __global_cli(); - break; - case 1: - __global_sti(); - break; - case 2: - __cli(); - break; - case 3: - __sti(); - break; - default: - printk("global_restore_flags: %08lx (%08lx) from %p\n", - flags, (&flags)[-1], __builtin_return_address(0)); - } -} diff --git a/arch/ia64/kernel/irq_sapic.c b/arch/ia64/kernel/irq_sapic.c new file mode 100644 index 000000000..a431275a8 --- /dev/null +++ b/arch/ia64/kernel/irq_sapic.c @@ -0,0 +1,38 @@ +/* + * SAPIC Interrupt Controller + * + * This takes care of interrupts that are generated by the CPU's + * internal Streamlined Advanced Programmable Interrupt Controller + * (SAPIC), such as the ITC and IPI interrupts. + * + * Copyright (C) 1999 VA Linux Systems + * Copyright (C) 1999 Walt Drummond <drummond@valinux.com> + * Copyright (C) 2000 Hewlett-Packard Co + * Copyright (C) 2000 David Mosberger-Tang <davidm@hpl.hp.com> + */ + +#include <linux/sched.h> +#include <linux/irq.h> + +static unsigned int +sapic_noop_startup (unsigned int irq) +{ + return 0; +} + +static void +sapic_noop (unsigned int irq) +{ + /* nuthing to do... */ +} + +struct hw_interrupt_type irq_type_ia64_sapic = { + typename: "SAPIC", + startup: sapic_noop_startup, + shutdown: sapic_noop, + enable: sapic_noop, + disable: sapic_noop, + ack: sapic_noop, + end: sapic_noop, + set_affinity: (void (*)(unsigned int, unsigned long)) sapic_noop +}; diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S index b4592999f..56dd2a333 100644 --- a/arch/ia64/kernel/ivt.S +++ b/arch/ia64/kernel/ivt.S @@ -5,213 +5,6 @@ * Copyright (C) 1998, 1999 Stephane Eranian <eranian@hpl.hp.com> * Copyright (C) 1998-2000 David Mosberger <davidm@hpl.hp.com> */ - -#include <linux/config.h> - -#include <asm/break.h> -#include <asm/offsets.h> -#include <asm/pgtable.h> -#include <asm/processor.h> -#include <asm/ptrace.h> -#include <asm/system.h> -#include <asm/unistd.h> - -#include "entry.h" - -/* - * A couple of convenience macros that make writing and reading - * SAVE_MIN and SAVE_REST easier. - */ -#define rARPR r31 -#define rCRIFS r30 -#define rCRIPSR r29 -#define rCRIIP r28 -#define rARRSC r27 -#define rARPFS r26 -#define rARUNAT r25 -#define rARRNAT r24 -#define rARBSPSTORE r23 -#define rKRBS r22 -#define rB6 r21 -#define rR1 r20 - -/* - * DO_SAVE_MIN switches to the kernel stacks (if necessary) and saves - * the minimum state necessary that allows us to turn psr.ic back - * on. - * - * Assumed state upon entry: - * psr.ic: off - * psr.dt: off - * r31: contains saved predicates (pr) - * - * Upon exit, the state is as follows: - * psr.ic: off - * psr.dt: off - * r2 = points to &pt_regs.r16 - * r12 = kernel sp (kernel virtual address) - * r13 = points to current task_struct (kernel virtual address) - * p15 = TRUE if psr.i is set in cr.ipsr - * predicate registers (other than p6, p7, and p15), b6, r3, r8, r9, r10, r11, r14, r15: - * preserved - * - * Note that psr.ic is NOT turned on by this macro. This is so that - * we can pass interruption state as arguments to a handler. - */ -#define DO_SAVE_MIN(COVER,EXTRA) \ - mov rARRSC=ar.rsc; \ - mov rARPFS=ar.pfs; \ - mov rR1=r1; \ - mov rARUNAT=ar.unat; \ - mov rCRIPSR=cr.ipsr; \ - mov rB6=b6; /* rB6 = branch reg 6 */ \ - mov rCRIIP=cr.iip; \ - mov r1=ar.k6; /* r1 = current */ \ - ;; \ - invala; \ - extr.u r16=rCRIPSR,32,2; /* extract psr.cpl */ \ - ;; \ - cmp.eq pKern,p7=r0,r16; /* are we in kernel mode already? (psr.cpl==0) */ \ - /* switch from user to kernel RBS: */ \ - COVER; \ - ;; \ -(p7) mov ar.rsc=r0; /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \ -(p7) addl rKRBS=IA64_RBS_OFFSET,r1; /* compute base of register backing store */ \ - ;; \ -(p7) mov rARRNAT=ar.rnat; \ -(pKern) dep r1=0,sp,61,3; /* compute physical addr of sp */ \ -(p7) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1; /* compute base of memory stack */ \ -(p7) mov rARBSPSTORE=ar.bspstore; /* save ar.bspstore */ \ -(p7) dep rKRBS=-1,rKRBS,61,3; /* compute kernel virtual addr of RBS */ \ - ;; \ -(pKern) addl r1=-IA64_PT_REGS_SIZE,r1; /* if in kernel mode, use sp (r12) */ \ -(p7) mov ar.bspstore=rKRBS; /* switch to kernel RBS */ \ - ;; \ -(p7) mov r18=ar.bsp; \ -(p7) mov ar.rsc=0x3; /* set eager mode, pl 0, little-endian, loadrs=0 */ \ - \ - mov r16=r1; /* initialize first base pointer */ \ - adds r17=8,r1; /* initialize second base pointer */ \ - ;; \ - st8 [r16]=rCRIPSR,16; /* save cr.ipsr */ \ - st8 [r17]=rCRIIP,16; /* save cr.iip */ \ -(pKern) mov r18=r0; /* make sure r18 isn't NaT */ \ - ;; \ - st8 [r16]=rCRIFS,16; /* save cr.ifs */ \ - st8 [r17]=rARUNAT,16; /* save ar.unat */ \ -(p7) sub r18=r18,rKRBS; /* r18=RSE.ndirty*8 */ \ - ;; \ - st8 [r16]=rARPFS,16; /* save ar.pfs */ \ - st8 [r17]=rARRSC,16; /* save ar.rsc */ \ - tbit.nz p15,p0=rCRIPSR,IA64_PSR_I_BIT \ - ;; /* avoid RAW on r16 & r17 */ \ -(pKern) adds r16=16,r16; /* skip over ar_rnat field */ \ -(pKern) adds r17=16,r17; /* skip over ar_bspstore field */ \ -(p7) st8 [r16]=rARRNAT,16; /* save ar.rnat */ \ -(p7) st8 [r17]=rARBSPSTORE,16; /* save ar.bspstore */ \ - ;; \ - st8 [r16]=rARPR,16; /* save predicates */ \ - st8 [r17]=rB6,16; /* save b6 */ \ - shl r18=r18,16; /* compute ar.rsc to be used for "loadrs" */ \ - ;; \ - st8 [r16]=r18,16; /* save ar.rsc value for "loadrs" */ \ - st8.spill [r17]=rR1,16; /* save original r1 */ \ - cmp.ne pEOI,p0=r0,r0 /* clear pEOI by default */ \ - ;; \ - st8.spill [r16]=r2,16; \ - st8.spill [r17]=r3,16; \ - adds r2=IA64_PT_REGS_R16_OFFSET,r1; \ - ;; \ - st8.spill [r16]=r12,16; \ - st8.spill [r17]=r13,16; \ - cmp.eq pNonSys,pSys=r0,r0 /* initialize pSys=0, pNonSys=1 */ \ - ;; \ - st8.spill [r16]=r14,16; \ - st8.spill [r17]=r15,16; \ - dep r14=-1,r0,61,3; \ - ;; \ - st8.spill [r16]=r8,16; \ - st8.spill [r17]=r9,16; \ - adds r12=-16,r1; /* switch to kernel memory stack (with 16 bytes of scratch) */ \ - ;; \ - st8.spill [r16]=r10,16; \ - st8.spill [r17]=r11,16; \ - mov r13=ar.k6; /* establish `current' */ \ - ;; \ - or r2=r2,r14; /* make first base a kernel virtual address */ \ - EXTRA; \ - movl r1=__gp; /* establish kernel global pointer */ \ - ;; \ - or r12=r12,r14; /* make sp a kernel virtual address */ \ - or r13=r13,r14; /* make `current' a kernel virtual address */ \ - bsw.1;; /* switch back to bank 1 (must be last in insn group) */ - -#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC -# define STOPS nop.i 0x0;; nop.i 0x0;; nop.i 0x0;; -#else -# define STOPS -#endif - -#define SAVE_MIN_WITH_COVER DO_SAVE_MIN(cover;; mov rCRIFS=cr.ifs,) STOPS -#define SAVE_MIN_WITH_COVER_R19 DO_SAVE_MIN(cover;; mov rCRIFS=cr.ifs, mov r15=r19) STOPS -#define SAVE_MIN DO_SAVE_MIN(mov rCRIFS=r0,) STOPS - -/* - * SAVE_REST saves the remainder of pt_regs (with psr.ic on). This - * macro guarantees to preserve all predicate registers, r8, r9, r10, - * r11, r14, and r15. - * - * Assumed state upon entry: - * psr.ic: on - * psr.dt: on - * r2: points to &pt_regs.r16 - * r3: points to &pt_regs.r17 - */ -#define SAVE_REST \ - st8.spill [r2]=r16,16; \ - st8.spill [r3]=r17,16; \ - ;; \ - st8.spill [r2]=r18,16; \ - st8.spill [r3]=r19,16; \ - ;; \ - mov r16=ar.ccv; /* M-unit */ \ - movl r18=FPSR_DEFAULT /* L-unit */ \ - ;; \ - mov r17=ar.fpsr; /* M-unit */ \ - mov ar.fpsr=r18; /* M-unit */ \ - ;; \ - st8.spill [r2]=r20,16; \ - st8.spill [r3]=r21,16; \ - mov r18=b0; \ - ;; \ - st8.spill [r2]=r22,16; \ - st8.spill [r3]=r23,16; \ - mov r19=b7; \ - ;; \ - st8.spill [r2]=r24,16; \ - st8.spill [r3]=r25,16; \ - ;; \ - st8.spill [r2]=r26,16; \ - st8.spill [r3]=r27,16; \ - ;; \ - st8.spill [r2]=r28,16; \ - st8.spill [r3]=r29,16; \ - ;; \ - st8.spill [r2]=r30,16; \ - st8.spill [r3]=r31,16; \ - ;; \ - st8 [r2]=r16,16; /* ar.ccv */ \ - st8 [r3]=r17,16; /* ar.fpsr */ \ - ;; \ - st8 [r2]=r18,16; /* b0 */ \ - st8 [r3]=r19,16+8; /* b7 */ \ - ;; \ - stf.spill [r2]=f6,32; \ - stf.spill [r3]=f7,32; \ - ;; \ - stf.spill [r2]=f8,32; \ - stf.spill [r3]=f9,32 - /* * This file defines the interrupt vector table used by the CPU. * It does not include one entry per possible cause of interruption. @@ -236,9 +29,29 @@ * The table is 32KB in size and must be aligned on 32KB boundary. * (The CPU ignores the 15 lower bits of the address) * - * Table is based upon EAS2.4 (June 1998) + * Table is based upon EAS2.6 (Oct 1999) */ +#include <linux/config.h> + +#include <asm/break.h> +#include <asm/offsets.h> +#include <asm/pgtable.h> +#include <asm/processor.h> +#include <asm/ptrace.h> +#include <asm/system.h> +#include <asm/unistd.h> + +#define MINSTATE_START_SAVE_MIN /* no special action needed */ +#define MINSTATE_END_SAVE_MIN \ + or r2=r2,r14; /* make first base a kernel virtual address */ \ + or r12=r12,r14; /* make sp a kernel virtual address */ \ + or r13=r13,r14; /* make `current' a kernel virtual address */ \ + bsw.1; /* switch back to bank 1 (must be last in insn group) */ \ + ;; + +#include "minstate.h" + #define FAULT(n) \ rsm psr.dt; /* avoid nested faults due to TLB misses... */ \ ;; \ @@ -336,8 +149,8 @@ ia64_ivt: (p7) tbit.nz.unc p10,p11=r19,32 // is it an instruction TLB miss? dep r17=0,r17,0,PAGE_SHIFT // clear low bits to get page address ;; -(p10) itc.i r18;; // insert the instruction TLB entry (EAS2.6: must be last in insn group!) -(p11) itc.d r18;; // insert the data TLB entry (EAS2.6: must be last in insn group!) +(p10) itc.i r18 // insert the instruction TLB entry +(p11) itc.d r18 // insert the data TLB entry (p6) br.spnt.few page_fault // handle bad address/page not present (page fault) mov cr.ifa=r21 @@ -346,9 +159,9 @@ ia64_ivt: // the exception deferral bit. adds r16=__DIRTY_BITS_NO_ED|_PAGE_PL_0|_PAGE_AR_RW,r17 ;; -(p7) itc.d r16;; // EAS2.6: must be last in insn group! +(p7) itc.d r16 mov pr=r31,-1 // restore predicate registers - rfi;; // must be last insn in an insn group + rfi .align 1024 ///////////////////////////////////////////////////////////////////////////////////////// @@ -395,11 +208,11 @@ ia64_ivt: ;; (p7) tbit.z p6,p7=r18,0 // page present bit cleared? ;; -(p7) itc.i r18;; // insert the instruction TLB entry (EAS2.6: must be last in insn group!) +(p7) itc.i r18 // insert the instruction TLB entry (p6) br.spnt.few page_fault // handle bad address/page not present (page fault) ;; mov pr=r31,-1 // restore predicate registers - rfi;; // must be last insn in an insn group + rfi .align 1024 ///////////////////////////////////////////////////////////////////////////////////////// @@ -446,11 +259,11 @@ ia64_ivt: ;; (p7) tbit.z p6,p7=r18,0 // page present bit cleared? ;; -(p7) itc.d r18;; // insert the instruction TLB entry (EAS2.6: must be last in insn group!) +(p7) itc.d r18 // insert the instruction TLB entry (p6) br.spnt.few page_fault // handle bad address/page not present (page fault) ;; mov pr=r31,-1 // restore predicate registers - rfi;; // must be last insn in an insn group + rfi //----------------------------------------------------------------------------------- // call do_page_fault (predicates are in r31, psr.dt is off, r16 is faulting address) @@ -468,10 +281,9 @@ page_fault: ;; ssm psr.ic | psr.dt ;; - srlz.d // guarantee that interrupt collection is enabled -(p15) ssm psr.i // restore psr.i + srlz.i // guarantee that interrupt collection is enabled ;; - srlz.i // must precede "alloc"! (srlz.i implies srlz.d) +(p15) ssm psr.i // restore psr.i movl r14=ia64_leave_kernel ;; alloc r15=ar.pfs,0,0,3,0 // must be first in insn group @@ -491,15 +303,15 @@ page_fault: movl r17=__DIRTY_BITS|_PAGE_PL_0|_PAGE_AR_RX ;; shr.u r18=r16,57 // move address bit 61 to bit 4 - dep r16=0,r16,52,12 // clear top 12 bits of address + dep r16=0,r16,IA64_PHYS_BITS,(64-IA64_PHYS_BITS) // clear ed, resvd, and unimpl. phys bits ;; andcm r18=0x10,r18 // bit 4=~address-bit(61) dep r16=r17,r16,0,12 // insert PTE control bits into r16 ;; or r16=r16,r18 // set bit 4 (uncached) if the access was to region 6 ;; - itc.i r16;; // insert the TLB entry(EAS2.6: must be last in insn group!) - rfi;; // must be last insn in an insn group + itc.i r16 // insert the TLB entry + rfi .align 1024 ///////////////////////////////////////////////////////////////////////////////////////// @@ -508,15 +320,15 @@ page_fault: movl r17=__DIRTY_BITS|_PAGE_PL_0|_PAGE_AR_RW ;; shr.u r18=r16,57 // move address bit 61 to bit 4 - dep r16=0,r16,52,12 // clear top 12 bits of address + dep r16=0,r16,IA64_PHYS_BITS,(64-IA64_PHYS_BITS) // clear ed, resvd, and unimpl. phys bits ;; andcm r18=0x10,r18 // bit 4=~address-bit(61) dep r16=r17,r16,0,12 // insert PTE control bits into r16 ;; or r16=r16,r18 // set bit 4 (uncached) if the access was to region 6 ;; - itc.d r16;; // insert the TLB entry (EAS2.6: must be last in insn group!) - rfi;; // must be last insn in an insn group + itc.d r16 // insert the TLB entry + rfi .align 1024 ///////////////////////////////////////////////////////////////////////////////////////// @@ -609,27 +421,31 @@ page_fault: mov b0=r29 // restore b0 ;; st8 [r17]=r18 // store back updated PTE - itc.d r18;; // install updated PTE (EAS2.6: must be last in insn group!) - rfi;; // must be last insn in an insn group + itc.d r18 // install updated PTE + rfi .align 1024 ///////////////////////////////////////////////////////////////////////////////////////// // 0x2400 Entry 9 (size 64 bundles) Instruction Access-bit (27) // Like Entry 8, except for instruction access mov r16=cr.ifa // get the address that caused the fault -#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC +#ifdef CONFIG_ITANIUM + /* + * Erratum 10 (IFA may contain incorrect address) now has + * "NoFix" status. There are no plans for fixing this. + */ + mov r17=cr.ipsr mov r31=pr // save predicates - mov r30=cr.ipsr ;; - extr.u r17=r30,IA64_PSR_IS_BIT,1 // get instruction arch. indicator + mov r18=cr.iip + tbit.z p6,p0=r17,IA64_PSR_IS_BIT // IA64 instruction set? ;; - cmp.eq p6,p0 = r17,r0 // check if IA64 instruction set +(p6) mov r16=r18 // if so, use cr.iip instead of cr.ifa +#if 0 ;; -(p6) mov r16=cr.iip // get real faulting address - ;; -(p6) mov cr.ifa=r16 // reset IFA +#endif mov pr=r31,-1 -#endif /* CONFIG_ITANIUM_ASTEP_SPECIFIC */ +#endif /* CONFIG_ITANIUM */ movl r30=1f // load continuation point in case of nested fault ;; thash r17=r16 // compute virtual address of L3 PTE @@ -641,8 +457,8 @@ page_fault: mov b0=r29 // restore b0 ;; st8 [r17]=r18 // store back updated PTE - itc.i r18;; // install updated PTE (EAS2.6: must be last in insn group!) - rfi;; // must be last insn in an insn group + itc.i r18 // install updated PTE + rfi .align 1024 ///////////////////////////////////////////////////////////////////////////////////////// @@ -660,8 +476,8 @@ page_fault: mov b0=r29 // restore b0 ;; st8 [r17]=r18 // store back updated PTE - itc.d r18;; // install updated PTE (EAS2.6: must be last in insn group!) - rfi;; // must be last insn in an insn group + itc.d r18 // install updated PTE + rfi .align 1024 ///////////////////////////////////////////////////////////////////////////////////////// @@ -689,12 +505,11 @@ page_fault: // turn interrupt collection and data translation back on: ssm psr.ic | psr.dt - srlz.d // guarantee that interrupt collection is enabled + ;; + srlz.i // guarantee that interrupt collection is enabled cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0 ;; (p15) ssm psr.i // restore psr.i - ;; - srlz.i // ensure everybody knows psr.ic and psr.dt are back on adds r8=(IA64_PT_REGS_R8_OFFSET-IA64_PT_REGS_R16_OFFSET),r2 ;; stf8 [r8]=f1 // ensure pt_regs.r8 != 0 (see handle_syscall_error) @@ -813,11 +628,10 @@ dispatch_to_ia32_handler: ;; mov r14=cr.isr ssm psr.ic | psr.dt - srlz.d // guarantee that interrupt collection is enabled ;; -(p15) ssm psr.i + srlz.i // guarantee that interrupt collection is enabled ;; - srlz.d +(p15) ssm psr.i adds r3=8,r2 // Base pointer for SAVE_REST ;; SAVE_REST @@ -858,12 +672,13 @@ dispatch_to_ia32_handler: ld8 r16=[r16] tbit.z p8,p0=r2,5 // (current->flags & PF_TRACESYS) == 0? ;; - movl r15=ia32_ret_from_syscall mov b6=r16 + movl r15=ia32_ret_from_syscall ;; mov rp=r15 -(p8) br.call.sptk.few b6=b6 - br.call.sptk.few rp=ia32_trace_syscall // rp will be overwritten (ignored) +(p8) br.call.sptk.many b6=b6 + ;; + br.call.sptk.many rp=ia32_trace_syscall // rp will be overwritten (ignored) non_ia32_syscall: alloc r15=ar.pfs,0,0,2,0 @@ -885,13 +700,6 @@ non_ia32_syscall: FAULT(17) non_syscall: - -#ifdef CONFIG_KDB - mov r17=__IA64_BREAK_KDB - ;; - cmp.eq p8,p0=r16,r17 // is this a kernel breakpoint? -#endif - SAVE_MIN_WITH_COVER // There is no particular reason for this code to be here, other than that @@ -904,11 +712,10 @@ non_syscall: // turn interrupt collection and data translation back on: ssm psr.ic | psr.dt - srlz.d // guarantee that interrupt collection is enabled ;; -(p15) ssm psr.i // restore psr.i + srlz.i // guarantee that interrupt collection is enabled ;; - srlz.i // ensure everybody knows psr.ic and psr.dt are back on +(p15) ssm psr.i // restore psr.i movl r15=ia64_leave_kernel ;; alloc r14=ar.pfs,0,0,2,0 @@ -918,9 +725,6 @@ non_syscall: SAVE_REST mov rp=r15 ;; -#ifdef CONFIG_KDB -(p8) br.call.sptk.few b6=ia64_invoke_kdb -#endif br.call.sptk.few b6=ia64_bad_break // avoid WAW on CFM and ignore return addr .align 1024 @@ -945,11 +749,10 @@ dispatch_unaligned_handler: // mov r15=cr.ifa ssm psr.ic | psr.dt - srlz.d // guarantee that interrupt collection is enabled ;; -(p15) ssm psr.i // restore psr.i + srlz.i // guarantee that interrupt collection is enabled ;; - srlz.i +(p15) ssm psr.i // restore psr.i adds r3=8,r2 // set up second base pointer ;; SAVE_REST @@ -994,13 +797,12 @@ dispatch_to_fault_handler: mov r11=cr.itir ;; ssm psr.ic | psr.dt - srlz.d // guarantee that interrupt collection is enabled + ;; + srlz.i // guarantee that interrupt collection is enabled ;; (p15) ssm psr.i // restore psr.i adds r3=8,r2 // set up second base pointer for SAVE_REST ;; - srlz.i // must precede "alloc"! - ;; alloc r14=ar.pfs,0,0,5,0 // must be first in insn group mov out0=r15 mov out1=r8 @@ -1012,11 +814,7 @@ dispatch_to_fault_handler: movl r14=ia64_leave_kernel ;; mov rp=r14 -#ifdef CONFIG_KDB - br.call.sptk.few b6=ia64_invoke_kdb_fault_handler -#else br.call.sptk.few b6=ia64_fault -#endif // // --- End of long entries, Beginning of short entries // @@ -1121,7 +919,7 @@ dispatch_to_fault_handler: mov cr.ipsr=r16 ;; - rfi;; // and go back (must be last insn in group) + rfi // and go back .align 256 ///////////////////////////////////////////////////////////////////////////////////////// @@ -1142,11 +940,7 @@ dispatch_to_fault_handler: ;; srlz.d // ensure everyone knows psr.dt is off mov r19=30 // error vector for fault_handler (when kernel) - extr.u r16=r16,32,2 // extract psr.cpl - ;; - cmp.eq p6,p7=r0,r16 // if kernel cpl then fault else emulate -(p7) br.cond.sptk.many dispatch_unaligned_handler -(p6) br.cond.sptk.many dispatch_to_fault_handler + br.cond.sptk.many dispatch_unaligned_handler .align 256 ///////////////////////////////////////////////////////////////////////////////////////// @@ -1226,6 +1020,31 @@ dispatch_to_fault_handler: .align 256 ///////////////////////////////////////////////////////////////////////////////////////// // 0x6a00 Entry 46 (size 16 bundles) IA-32 Intercept (30,31,59,70,71) +#ifdef CONFIG_IA32_SUPPORT + rsm psr.dt + ;; + srlz.d + mov r31=pr + mov r16=cr.isr + ;; + extr.u r17=r16,16,8 // get ISR.code + mov r18=ar.eflag + mov r19=cr.iim // old eflag value + ;; + cmp.ne p2,p0=2,r17 +(p2) br.cond.spnt 1f // not a system flag fault + xor r16=r18,r19 + ;; + extr.u r17=r16,18,1 // get the eflags.ac bit + ;; + cmp.eq p2,p0=0,r17 +(p2) br.cond.spnt 1f // eflags.ac bit didn't change + ;; + mov pr=r31,-1 // restore predicate registers + rfi + +1: +#endif // CONFIG_IA32_SUPPORT FAULT(46) .align 256 diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 320c56ebc..150feac03 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -2,21 +2,37 @@ * File: mca.c * Purpose: Generic MCA handling layer * + * Updated for latest kernel + * Copyright (C) 2000 Intel + * Copyright (C) Chuck Fleckenstein (cfleck@co.intel.com) + * * Copyright (C) 1999 Silicon Graphics, Inc. * Copyright (C) Vijay Chander(vijay@engr.sgi.com) + * + * 00/03/29 C. Fleckenstein Fixed PAL/SAL update issues, began MCA bug fixes, logging issues, + * added min save state dump, added INIT handler. */ #include <linux/types.h> #include <linux/init.h> #include <linux/sched.h> +#include <linux/irq.h> +#include <linux/smp_lock.h> +#include <linux/config.h> + #include <asm/page.h> #include <asm/ptrace.h> #include <asm/system.h> #include <asm/sal.h> #include <asm/mca.h> -#include <asm/spinlock.h> + #include <asm/irq.h> #include <asm/machvec.h> + +typedef struct ia64_fptr { + unsigned long fp; + unsigned long gp; +} ia64_fptr_t; ia64_mc_info_t ia64_mc_info; ia64_mca_sal_to_os_state_t ia64_sal_to_os_handoff_state; @@ -25,6 +41,11 @@ u64 ia64_mca_proc_state_dump[256]; u64 ia64_mca_stack[1024]; u64 ia64_mca_stackframe[32]; u64 ia64_mca_bspstore[1024]; +u64 ia64_init_stack[INIT_TASK_SIZE] __attribute__((aligned(16))); + +#if defined(SAL_MPINIT_WORKAROUND) && !defined(CONFIG_SMP) +int bootstrap_processor = -1; +#endif static void ia64_mca_cmc_vector_setup(int enable, int_vector_t cmc_vector); @@ -34,7 +55,98 @@ static void ia64_mca_wakeup_all(void); static void ia64_log_init(int,int); static void ia64_log_get(int,int, prfunc_t); static void ia64_log_clear(int,int,int, prfunc_t); +extern void ia64_monarch_init_handler (void); +extern void ia64_slave_init_handler (void); + +/* + * hack for now, add platform dependent handlers + * here + */ +#ifndef PLATFORM_MCA_HANDLERS +void +mca_handler_platform (void) +{ + +} + +void +cmci_handler_platform (int cmc_irq, void *arg, struct pt_regs *ptregs) +{ + +} +/* + * This routine will be used to deal with platform specific handling + * of the init, i.e. drop into the kernel debugger on server machine, + * or if the processor is part of some parallel machine without a + * console, then we would call the appropriate debug hooks here. + */ +void +init_handler_platform (struct pt_regs *regs) +{ + /* if a kernel debugger is available call it here else just dump the registers */ + show_regs(regs); /* dump the state info */ +} + +void +log_print_platform ( void *cur_buff_ptr, prfunc_t prfunc) +{ +} + +void +ia64_mca_init_platform (void) +{ +} + +#endif /* PLATFORM_MCA_HANDLERS */ + +static char *min_state_labels[] = { + "nat", + "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", + "r9", "r10","r11", "r12","r13","r14", "r15", + "b0r16","b0r17", "b0r18", "b0r19", "b0r20", + "b0r21", "b0r22","b0r23", "b0r24", "b0r25", + "b0r26", "b0r27", "b0r28","b0r29", "b0r30", "b0r31", + "r16", "r17", "r18","r19", "r20", "r21","r22", + "r23", "r24","r25", "r26", "r27","r28", "r29", "r30","r31", + "preds", "br0", "rsc", + "iip", "ipsr", "ifs", + "xip", "xpsr", "xfs" +}; + +int ia64_pmss_dump_bank0=0; /* dump bank 0 ? */ + +/* + * routine to process and prepare to dump min_state_save + * information for debugging purposes. + * + */ +void +ia64_process_min_state_save (pal_min_state_area_t *pmss, struct pt_regs *ptregs) +{ + int i, max=57; + u64 *tpmss_ptr=(u64 *)pmss; + + /* dump out the min_state_area information */ + for (i=0;i<max;i++) { + + if(!ia64_pmss_dump_bank0) { + if(strncmp("B0",min_state_labels[i],2)==0) { + tpmss_ptr++; /* skip to next entry */ + continue; + } + } + + printk("%5s=0x%16.16lx ",min_state_labels[i],*tpmss_ptr++); + + if (((i+1)%3)==0 || ((!strcmp("GR16",min_state_labels[i])) + && !ia64_pmss_dump_bank0)) + printk("\n"); + } + /* hang city for now, until we include debugger or copy to ptregs to show: */ + while (1); +} + /* * ia64_mca_cmc_vector_setup * Setup the correctable machine check vector register in the processor @@ -83,7 +195,7 @@ mca_test(void) #endif /* #if defined(MCA_TEST) */ /* - * mca_init + * ia64_mca_init * Do all the mca specific initialization on a per-processor basis. * * 1. Register spinloop and wakeup request interrupt vectors @@ -93,7 +205,7 @@ mca_test(void) * 3. Register OS_INIT handler entry point * * 4. Initialize CMCV register to enable/disable CMC interrupt on the - * processor and hook a handler in the platform-specific mca_init. + * processor and hook a handler in the platform-specific ia64_mca_init. * * 5. Initialize MCA/CMC/INIT related log buffers maintained by the OS. * @@ -103,11 +215,20 @@ mca_test(void) * None */ void __init -mca_init(void) +ia64_mca_init(void) { - int i; + ia64_fptr_t *mon_init_ptr = (ia64_fptr_t *)ia64_monarch_init_handler; + ia64_fptr_t *slave_init_ptr = (ia64_fptr_t *)ia64_slave_init_handler; + int i; + + IA64_MCA_DEBUG("ia64_mca_init : begin\n"); + +#if defined(SAL_MPINIT_WORKAROUND) && !defined(CONFIG_SMP) + /* XXX -- workaround for SAL bug for running on MP system, but UP kernel */ + + bootstrap_processor = hard_smp_processor_id(); +#endif - MCA_DEBUG("mca_init : begin\n"); /* Clear the Rendez checkin flag for all cpus */ for(i = 0 ; i < IA64_MAXCPUS; i++) ia64_mc_info.imi_rendez_checkin[i] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE; @@ -134,14 +255,14 @@ mca_init(void) 0)) return; - MCA_DEBUG("mca_init : registered mca rendezvous spinloop and wakeup mech.\n"); + IA64_MCA_DEBUG("ia64_mca_init : registered mca rendezvous spinloop and wakeup mech.\n"); /* * Setup the correctable machine check vector */ ia64_mca_cmc_vector_setup(IA64_CMC_INT_ENABLE, IA64_MCA_CMC_INT_VECTOR); - MCA_DEBUG("mca_init : correctable mca vector setup done\n"); + IA64_MCA_DEBUG("ia64_mca_init : correctable mca vector setup done\n"); ia64_mc_info.imi_mca_handler = __pa(ia64_os_mca_dispatch); ia64_mc_info.imi_mca_handler_size = @@ -155,12 +276,15 @@ mca_init(void) return; - MCA_DEBUG("mca_init : registered os mca handler with SAL\n"); + IA64_MCA_DEBUG("ia64_mca_init : registered os mca handler with SAL\n"); - ia64_mc_info.imi_monarch_init_handler = __pa(ia64_monarch_init_handler); + ia64_mc_info.imi_monarch_init_handler = __pa(mon_init_ptr->fp); ia64_mc_info.imi_monarch_init_handler_size = IA64_INIT_HANDLER_SIZE; - ia64_mc_info.imi_slave_init_handler = __pa(ia64_slave_init_handler); + ia64_mc_info.imi_slave_init_handler = __pa(slave_init_ptr->fp); ia64_mc_info.imi_slave_init_handler_size = IA64_INIT_HANDLER_SIZE; + + IA64_MCA_DEBUG("ia64_mca_init : os init handler at %lx\n",ia64_mc_info.imi_monarch_init_handler); + /* Register the os init handler with SAL */ if (ia64_sal_set_vectors(SAL_VECTOR_OS_INIT, ia64_mc_info.imi_monarch_init_handler, @@ -173,7 +297,7 @@ mca_init(void) return; - MCA_DEBUG("mca_init : registered os init handler with SAL\n"); + IA64_MCA_DEBUG("ia64_mca_init : registered os init handler with SAL\n"); /* Initialize the areas set aside by the OS to buffer the * platform/processor error states for MCA/INIT/CMC @@ -186,9 +310,9 @@ mca_init(void) ia64_log_init(SAL_INFO_TYPE_CMC, SAL_SUB_INFO_TYPE_PROCESSOR); ia64_log_init(SAL_INFO_TYPE_CMC, SAL_SUB_INFO_TYPE_PLATFORM); - mca_init_platform(); + ia64_mca_init_platform(); - MCA_DEBUG("mca_init : platform-specific mca handling setup done\n"); + IA64_MCA_DEBUG("ia64_mca_init : platform-specific mca handling setup done\n"); #if defined(MCA_TEST) mca_test(); @@ -244,7 +368,7 @@ ia64_mca_wakeup_ipi_wait(void) void ia64_mca_wakeup(int cpu) { - ipi_send(cpu, IA64_MCA_WAKEUP_INT_VECTOR, IA64_IPI_DM_INT); + ipi_send(cpu, IA64_MCA_WAKEUP_INT_VECTOR, IA64_IPI_DM_INT, 0); ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE; } @@ -396,25 +520,6 @@ ia64_mca_ucmc_handler(void) ia64_return_to_sal_check(); } -/* - * SAL to OS entry point for INIT on the monarch processor - * This has been defined for registration purposes with SAL - * as a part of mca_init. - */ -void -ia64_monarch_init_handler() -{ -} -/* - * SAL to OS entry point for INIT on the slave processor - * This has been defined for registration purposes with SAL - * as a part of mca_init. - */ - -void -ia64_slave_init_handler() -{ -} /* * ia64_mca_cmc_int_handler * This is correctable machine check interrupt handler. @@ -450,10 +555,9 @@ ia64_mca_cmc_int_handler(int cmc_irq, void *arg, struct pt_regs *ptregs) #define IA64_MAX_LOG_SUBTYPES 2 /* Processor, Platform */ typedef struct ia64_state_log_s { - spinlock_t isl_lock; - int isl_index; - sal_log_header_t isl_log[IA64_MAX_LOGS]; - + spinlock_t isl_lock; + int isl_index; + ia64_psilog_t isl_log[IA64_MAX_LOGS]; /* need space to store header + error log */ } ia64_state_log_t; static ia64_state_log_t ia64_state_log[IA64_MAX_LOG_TYPES][IA64_MAX_LOG_SUBTYPES]; @@ -472,6 +576,53 @@ static ia64_state_log_t ia64_state_log[IA64_MAX_LOG_TYPES][IA64_MAX_LOG_SUBTYPES #define IA64_LOG_CURR_BUFFER(it, sit) (void *)(&(ia64_state_log[it][sit].isl_log[IA64_LOG_CURR_INDEX(it,sit)])) /* + * C portion of the OS INIT handler + * + * Called from ia64_<monarch/slave>_init_handler + * + * Inputs: pointer to pt_regs where processor info was saved. + * + * Returns: + * 0 if SAL must warm boot the System + * 1 if SAL must retrun to interrupted context using PAL_MC_RESUME + * + */ + +void +ia64_init_handler (struct pt_regs *regs) +{ + sal_log_processor_info_t *proc_ptr; + ia64_psilog_t *plog_ptr; + + printk("Entered OS INIT handler\n"); + + /* Get the INIT processor log */ + ia64_log_get(SAL_INFO_TYPE_INIT, SAL_SUB_INFO_TYPE_PROCESSOR, (prfunc_t)printk); + /* Get the INIT platform log */ + ia64_log_get(SAL_INFO_TYPE_INIT, SAL_SUB_INFO_TYPE_PLATFORM, (prfunc_t)printk); + +#ifdef IA64_DUMP_ALL_PROC_INFO + ia64_log_print(SAL_INFO_TYPE_INIT, SAL_SUB_INFO_TYPE_PROCESSOR, (prfunc_t)printk); +#endif + + /* + * get pointer to min state save area + * + */ + plog_ptr=(ia64_psilog_t *)IA64_LOG_CURR_BUFFER(SAL_INFO_TYPE_INIT, + SAL_SUB_INFO_TYPE_PROCESSOR); + proc_ptr = &plog_ptr->devlog.proclog; + + ia64_process_min_state_save(&proc_ptr->slpi_min_state_area,regs); + + init_handler_platform(regs); /* call platform specific routines */ + + /* Clear the INIT SAL logs now that they have been saved in the OS buffer */ + ia64_sal_clear_state_info(SAL_INFO_TYPE_INIT, SAL_SUB_INFO_TYPE_PROCESSOR); + ia64_sal_clear_state_info(SAL_INFO_TYPE_INIT, SAL_SUB_INFO_TYPE_PLATFORM); +} + +/* * ia64_log_init * Reset the OS ia64 log buffer * Inputs : info_type (SAL_INFO_TYPE_{MCA,INIT,CMC}) @@ -484,7 +635,7 @@ ia64_log_init(int sal_info_type, int sal_sub_info_type) IA64_LOG_LOCK_INIT(sal_info_type, sal_sub_info_type); IA64_LOG_NEXT_INDEX(sal_info_type, sal_sub_info_type) = 0; memset(IA64_LOG_NEXT_BUFFER(sal_info_type, sal_sub_info_type), 0, - sizeof(sal_log_header_t) * IA64_MAX_LOGS); + sizeof(ia64_psilog_t) * IA64_MAX_LOGS); } /* @@ -499,7 +650,7 @@ void ia64_log_get(int sal_info_type, int sal_sub_info_type, prfunc_t prfunc) { sal_log_header_t *log_buffer; - int s; + int s,total_len=0; IA64_LOG_LOCK(sal_info_type, sal_sub_info_type); @@ -507,9 +658,11 @@ ia64_log_get(int sal_info_type, int sal_sub_info_type, prfunc_t prfunc) /* Get the process state information */ log_buffer = IA64_LOG_NEXT_BUFFER(sal_info_type, sal_sub_info_type); - if (ia64_sal_get_state_info(sal_info_type, sal_sub_info_type ,(u64 *)log_buffer)) + if (!(total_len=ia64_sal_get_state_info(sal_info_type, sal_sub_info_type ,(u64 *)log_buffer))) prfunc("ia64_mca_log_get : Getting processor log failed\n"); + IA64_MCA_DEBUG("ia64_log_get: retrieved %d bytes of error information\n",total_len); + IA64_LOG_INDEX_INC(sal_info_type, sal_sub_info_type); IA64_LOG_UNLOCK(sal_info_type, sal_sub_info_type); @@ -542,7 +695,7 @@ ia64_log_clear(int sal_info_type, int sal_sub_info_type, int clear_os_buffer, pr /* Get the process state information */ log_buffer = IA64_LOG_CURR_BUFFER(sal_info_type, sal_sub_info_type); - memset(log_buffer, 0, sizeof(sal_log_header_t)); + memset(log_buffer, 0, sizeof(ia64_psilog_t)); IA64_LOG_INDEX_DEC(sal_info_type, sal_sub_info_type); @@ -731,11 +884,7 @@ ia64_log_processor_info_print(sal_log_header_t *lh, prfunc_t prfunc) if (lh->slh_log_type != SAL_SUB_INFO_TYPE_PROCESSOR) return; -#if defined(MCA_TEST) - slpi = &slpi_buf; -#else - slpi = (sal_log_processor_info_t *)lh->slh_log_dev_spec_info; -#endif /#if defined(MCA_TEST) */ + slpi = (sal_log_processor_info_t *)((char *)lh+sizeof(sal_log_header_t)); /* point to proc info */ if (!slpi) { prfunc("No Processor Error Log found\n"); @@ -763,14 +912,6 @@ ia64_log_processor_info_print(sal_log_header_t *lh, prfunc_t prfunc) ia64_log_processor_regs_print(slpi->slpi_fr, 128, "Floating-point", "fr", prfunc); - /* Print bank1-gr NAT register contents if valid */ - ia64_log_processor_regs_print(&slpi->slpi_bank1_nat_bits, 1, "NAT", "nat", prfunc); - - /* Print bank 1 register contents if valid */ - if (slpi->slpi_valid.slpi_bank1_gr) - ia64_log_processor_regs_print(slpi->slpi_bank1_gr, 16, "Bank1-General", "gr", - prfunc); - /* Print the cache check information if any*/ for (i = 0 ; i < MAX_CACHE_ERRORS; i++) ia64_log_cache_check_info_print(i, diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S index 3d49ac06e..81966bb99 100644 --- a/arch/ia64/kernel/mca_asm.S +++ b/arch/ia64/kernel/mca_asm.S @@ -1,7 +1,31 @@ +// +// assembly portion of the IA64 MCA handling +// +// Mods by cfleck to integrate into kernel build +// 00/03/15 davidm Added various stop bits to get a clean compile +// 00/03/29 cfleck Added code to save INIT handoff state in pt_regs format, switch to temp kstack, +// switch modes, jump to C INIT handler +// +#include <asm/offsets.h> +#include <asm/pgtable.h> #include <asm/processor.h> -#include <asm/mcaasm.h> -#include <asm/page.h> +#include <asm/mca_asm.h> #include <asm/mca.h> + +/* + * When we get an machine check, the kernel stack pointer is no longer + * valid, so we need to set a new stack pointer. + */ +#define MINSTATE_START_SAVE_MIN \ +(pKern) movl sp=ia64_init_stack+IA64_STK_OFFSET-IA64_PT_REGS_SIZE; \ + ;; + +#define MINSTATE_END_SAVE_MIN \ + or r12=r12,r14; /* make sp a kernel virtual address */ \ + or r13=r13,r14; /* make `current' a kernel virtual address */ \ + ;; + +#include "minstate.h" .psr abi64 .psr lsb @@ -54,7 +78,9 @@ 100: (p) mov temp=ip; \ ;; \ (p) adds temp=to_label-100b,temp;\ + ;; \ (p) adds temp=adjust,temp; \ + ;; \ (p) mov b1=temp ; \ (p) br b1 @@ -68,6 +94,7 @@ .global ia64_mca_stack .global ia64_mca_stackframe .global ia64_mca_bspstore + .global ia64_init_stack .text .align 16 @@ -341,6 +368,7 @@ cSaveARs: mov r3=ar16 // ar.rsc mov ar16=r0 // put RSE in enforced lazy mode mov r5=ar17 // ar.bsp + ;; mov r7=ar18;; // ar.bspstore st8 [r2]=r3,3*8 st8 [r4]=r5,3*8 @@ -575,6 +603,7 @@ restore_ARs: // mov ar16=r3 // ar.rsc // mov ar17=r5 // ar.bsp is read only mov ar16=r0 // make sure that RSE is in enforced lazy mode + ;; mov ar18=r7;; // ar.bspstore ld8 r9=[r2],8*13;; @@ -619,3 +648,146 @@ end_os_mca_restore: BRANCH(ia64_os_mca_done_restore, r2, p0, -0x20) ;; //EndStub////////////////////////////////////////////////////////////////////// + +// ok, the issue here is that we need to save state information so +// it can be useable by the kernel debugger and show regs routines. +// In order to do this, our best bet is save the current state (plus +// the state information obtain from the MIN_STATE_AREA) into a pt_regs +// format. This way we can pass it on in a useable format. +// + +// +// SAL to OS entry point for INIT on the monarch processor +// This has been defined for registration purposes with SAL +// as a part of ia64_mca_init. +// +// When we get here, the follow registers have been +// set by the SAL for our use +// +// 1. GR1 = OS INIT GP +// 2. GR8 = PAL_PROC physical address +// 3. GR9 = SAL_PROC physical address +// 4. GR10 = SAL GP (physical) +// 5. GR11 = Init Reason +// 0 = Received INIT for event other than crash dump switch +// 1 = Received wakeup at the end of an OS_MCA corrected machine check +// 2 = Received INIT dude to CrashDump switch assertion +// +// 6. GR12 = Return address to location within SAL_INIT procedure + + + .text + .align 16 +.global ia64_monarch_init_handler +.proc ia64_monarch_init_handler +ia64_monarch_init_handler: + +#if defined(SAL_MPINIT_WORKAROUND) + // + // work around SAL bug that sends all processors to monarch entry + // + .global bootstrap_processor + + movl r21=24 + movl r20=16 + mov r17=cr.lid + movl r18=bootstrap_processor + ;; + dep r18=0,r18,61,3 // convert bsp to physical address + ;; + shr r19=r17,r20 + shr r22=r17,r21 + ld4 r18=[r18] // get the BSP ID + ;; + and r19=0xf, r19 + and r22=0xf, r22 + ;; + shl r19=r19,8 // get them in the right order + ;; + or r22=r22,r19 // combine EID and LID + ;; + cmp.eq p6,p7=r22,r18 // Am I the BSP ? +(p7) br.cond.spnt slave_init_spin_me + ;; +#endif + + +// +// ok, the first thing we do is stash the information +// the SAL passed to os +// +_tmp = r2 + movl _tmp=ia64_sal_to_os_handoff_state + ;; + dep _tmp=0,_tmp, 61, 3 // get physical address + ;; + st8 [_tmp]=r1,0x08;; + st8 [_tmp]=r8,0x08;; + st8 [_tmp]=r9,0x08;; + st8 [_tmp]=r10,0x08;; + st8 [_tmp]=r11,0x08;; + st8 [_tmp]=r12,0x08;; + +// now we want to save information so we can dump registers + SAVE_MIN_WITH_COVER + ;; + mov r8=cr.ifa + mov r9=cr.isr + adds r3=8,r2 // set up second base pointer + ;; + SAVE_REST + +// ok, enough should be saved at this point to be dangerous, and supply +// information for a dump +// We need to switch to Virtual mode before hitting the C functions. +// +// +// + movl r2=IA64_PSR_IT|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFH|IA64_PSR_BN + mov r3=psr // get the current psr, minimum enabled at this point + ;; + or r2=r2,r3 + ;; + movl r3=IVirtual_Switch + ;; + mov cr.iip=r3 // short return to set the appropriate bits + mov cr.ipsr=r2 // need to do an rfi to set appropriate bits + ;; + rfi + ;; +IVirtual_Switch: + // + // We should now be running virtual + // + // Lets call the C handler to get the rest of the state info + // + alloc r14=ar.pfs,0,0,1,0 // now it's safe (must be first in insn group!) + ;; // + adds out0=16,sp // out0 = pointer to pt_regs + ;; + + br.call.sptk.few rp=ia64_init_handler + ;; + +return_from_init: + br.sptk return_from_init + + .endp + +// +// SAL to OS entry point for INIT on the slave processor +// This has been defined for registration purposes with SAL +// as a part of ia64_mca_init. +// + + .text + .align 16 +.global ia64_slave_init_handler +.proc ia64_slave_init_handler +ia64_slave_init_handler: + + +slave_init_spin_me: + br.sptk slave_init_spin_me + ;; + .endp diff --git a/arch/ia64/kernel/minstate.h b/arch/ia64/kernel/minstate.h new file mode 100644 index 000000000..bcfe1659c --- /dev/null +++ b/arch/ia64/kernel/minstate.h @@ -0,0 +1,205 @@ +#include <linux/config.h> + +#include "entry.h" + +/* + * A couple of convenience macros that make writing and reading + * SAVE_MIN and SAVE_REST easier. + */ +#define rARPR r31 +#define rCRIFS r30 +#define rCRIPSR r29 +#define rCRIIP r28 +#define rARRSC r27 +#define rARPFS r26 +#define rARUNAT r25 +#define rARRNAT r24 +#define rARBSPSTORE r23 +#define rKRBS r22 +#define rB6 r21 +#define rR1 r20 + +/* + * DO_SAVE_MIN switches to the kernel stacks (if necessary) and saves + * the minimum state necessary that allows us to turn psr.ic back + * on. + * + * Assumed state upon entry: + * psr.ic: off + * psr.dt: off + * r31: contains saved predicates (pr) + * + * Upon exit, the state is as follows: + * psr.ic: off + * psr.dt: off + * r2 = points to &pt_regs.r16 + * r12 = kernel sp (kernel virtual address) + * r13 = points to current task_struct (kernel virtual address) + * p15 = TRUE if psr.i is set in cr.ipsr + * predicate registers (other than p6, p7, and p15), b6, r3, r8, r9, r10, r11, r14, r15: + * preserved + * + * Note that psr.ic is NOT turned on by this macro. This is so that + * we can pass interruption state as arguments to a handler. + */ +#define DO_SAVE_MIN(COVER,EXTRA) \ + mov rARRSC=ar.rsc; \ + mov rARPFS=ar.pfs; \ + mov rR1=r1; \ + mov rARUNAT=ar.unat; \ + mov rCRIPSR=cr.ipsr; \ + mov rB6=b6; /* rB6 = branch reg 6 */ \ + mov rCRIIP=cr.iip; \ + mov r1=ar.k6; /* r1 = current */ \ + ;; \ + invala; \ + extr.u r16=rCRIPSR,32,2; /* extract psr.cpl */ \ + ;; \ + cmp.eq pKern,p7=r0,r16; /* are we in kernel mode already? (psr.cpl==0) */ \ + /* switch from user to kernel RBS: */ \ + COVER; \ + ;; \ + MINSTATE_START_SAVE_MIN \ +(p7) mov ar.rsc=r0; /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \ +(p7) addl rKRBS=IA64_RBS_OFFSET,r1; /* compute base of register backing store */ \ + ;; \ +(p7) mov rARRNAT=ar.rnat; \ +(pKern) dep r1=0,sp,61,3; /* compute physical addr of sp */ \ +(p7) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1; /* compute base of memory stack */ \ +(p7) mov rARBSPSTORE=ar.bspstore; /* save ar.bspstore */ \ +(p7) dep rKRBS=-1,rKRBS,61,3; /* compute kernel virtual addr of RBS */ \ + ;; \ +(pKern) addl r1=-IA64_PT_REGS_SIZE,r1; /* if in kernel mode, use sp (r12) */ \ +(p7) mov ar.bspstore=rKRBS; /* switch to kernel RBS */ \ + ;; \ +(p7) mov r18=ar.bsp; \ +(p7) mov ar.rsc=0x3; /* set eager mode, pl 0, little-endian, loadrs=0 */ \ + \ + mov r16=r1; /* initialize first base pointer */ \ + adds r17=8,r1; /* initialize second base pointer */ \ + ;; \ + st8 [r16]=rCRIPSR,16; /* save cr.ipsr */ \ + st8 [r17]=rCRIIP,16; /* save cr.iip */ \ +(pKern) mov r18=r0; /* make sure r18 isn't NaT */ \ + ;; \ + st8 [r16]=rCRIFS,16; /* save cr.ifs */ \ + st8 [r17]=rARUNAT,16; /* save ar.unat */ \ +(p7) sub r18=r18,rKRBS; /* r18=RSE.ndirty*8 */ \ + ;; \ + st8 [r16]=rARPFS,16; /* save ar.pfs */ \ + st8 [r17]=rARRSC,16; /* save ar.rsc */ \ + tbit.nz p15,p0=rCRIPSR,IA64_PSR_I_BIT \ + ;; /* avoid RAW on r16 & r17 */ \ +(pKern) adds r16=16,r16; /* skip over ar_rnat field */ \ +(pKern) adds r17=16,r17; /* skip over ar_bspstore field */ \ +(p7) st8 [r16]=rARRNAT,16; /* save ar.rnat */ \ +(p7) st8 [r17]=rARBSPSTORE,16; /* save ar.bspstore */ \ + ;; \ + st8 [r16]=rARPR,16; /* save predicates */ \ + st8 [r17]=rB6,16; /* save b6 */ \ + shl r18=r18,16; /* compute ar.rsc to be used for "loadrs" */ \ + ;; \ + st8 [r16]=r18,16; /* save ar.rsc value for "loadrs" */ \ + st8.spill [r17]=rR1,16; /* save original r1 */ \ + cmp.ne pEOI,p0=r0,r0 /* clear pEOI by default */ \ + ;; \ +.mem.offset 0,0; st8.spill [r16]=r2,16; \ +.mem.offset 8,0; st8.spill [r17]=r3,16; \ + adds r2=IA64_PT_REGS_R16_OFFSET,r1; \ + ;; \ +.mem.offset 0,0; st8.spill [r16]=r12,16; \ +.mem.offset 8,0; st8.spill [r17]=r13,16; \ + cmp.eq pNonSys,pSys=r0,r0 /* initialize pSys=0, pNonSys=1 */ \ + ;; \ +.mem.offset 0,0; st8.spill [r16]=r14,16; \ +.mem.offset 8,0; st8.spill [r17]=r15,16; \ + dep r14=-1,r0,61,3; \ + ;; \ +.mem.offset 0,0; st8.spill [r16]=r8,16; \ +.mem.offset 8,0; st8.spill [r17]=r9,16; \ + adds r12=-16,r1; /* switch to kernel memory stack (with 16 bytes of scratch) */ \ + ;; \ +.mem.offset 0,0; st8.spill [r16]=r10,16; \ +.mem.offset 8,0; st8.spill [r17]=r11,16; \ + mov r13=ar.k6; /* establish `current' */ \ + ;; \ + EXTRA; \ + movl r1=__gp; /* establish kernel global pointer */ \ + ;; \ + MINSTATE_END_SAVE_MIN + +/* + * SAVE_REST saves the remainder of pt_regs (with psr.ic on). This + * macro guarantees to preserve all predicate registers, r8, r9, r10, + * r11, r14, and r15. + * + * Assumed state upon entry: + * psr.ic: on + * psr.dt: on + * r2: points to &pt_regs.r16 + * r3: points to &pt_regs.r17 + */ +#define SAVE_REST \ +.mem.offset 0,0; st8.spill [r2]=r16,16; \ +.mem.offset 8,0; st8.spill [r3]=r17,16; \ + ;; \ +.mem.offset 0,0; st8.spill [r2]=r18,16; \ +.mem.offset 8,0; st8.spill [r3]=r19,16; \ + ;; \ + mov r16=ar.ccv; /* M-unit */ \ + movl r18=FPSR_DEFAULT /* L-unit */ \ + ;; \ + mov r17=ar.fpsr; /* M-unit */ \ + mov ar.fpsr=r18; /* M-unit */ \ + ;; \ +.mem.offset 0,0; st8.spill [r2]=r20,16; \ +.mem.offset 8,0; st8.spill [r3]=r21,16; \ + mov r18=b0; \ + ;; \ +.mem.offset 0,0; st8.spill [r2]=r22,16; \ +.mem.offset 8,0; st8.spill [r3]=r23,16; \ + mov r19=b7; \ + ;; \ +.mem.offset 0,0; st8.spill [r2]=r24,16; \ +.mem.offset 8,0; st8.spill [r3]=r25,16; \ + ;; \ +.mem.offset 0,0; st8.spill [r2]=r26,16; \ +.mem.offset 8,0; st8.spill [r3]=r27,16; \ + ;; \ +.mem.offset 0,0; st8.spill [r2]=r28,16; \ +.mem.offset 8,0; st8.spill [r3]=r29,16; \ + ;; \ +.mem.offset 0,0; st8.spill [r2]=r30,16; \ +.mem.offset 8,0; st8.spill [r3]=r31,16; \ + ;; \ + st8 [r2]=r16,16; /* ar.ccv */ \ + st8 [r3]=r17,16; /* ar.fpsr */ \ + ;; \ + st8 [r2]=r18,16; /* b0 */ \ + st8 [r3]=r19,16+8; /* b7 */ \ + ;; \ + stf.spill [r2]=f6,32; \ + stf.spill [r3]=f7,32; \ + ;; \ + stf.spill [r2]=f8,32; \ + stf.spill [r3]=f9,32 + +#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC +# define STOPS nop.i 0x0;; nop.i 0x0;; nop.i 0x0;; +#else +# define STOPS +#endif + +#define SAVE_MIN_WITH_COVER DO_SAVE_MIN(cover;; mov rCRIFS=cr.ifs,) STOPS +#define SAVE_MIN_WITH_COVER_R19 DO_SAVE_MIN(cover;; mov rCRIFS=cr.ifs, mov r15=r19) STOPS +#define SAVE_MIN DO_SAVE_MIN(mov rCRIFS=r0,) STOPS + +#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC +# define STOPS nop.i 0x0;; nop.i 0x0;; nop.i 0x0;; +#else +# define STOPS +#endif + +#define SAVE_MIN_WITH_COVER DO_SAVE_MIN(cover;; mov rCRIFS=cr.ifs,) STOPS +#define SAVE_MIN_WITH_COVER_R19 DO_SAVE_MIN(cover;; mov rCRIFS=cr.ifs, mov r15=r19) STOPS +#define SAVE_MIN DO_SAVE_MIN(mov rCRIFS=r0,) STOPS diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c index 18a8e342e..22ed4f569 100644 --- a/arch/ia64/kernel/ptrace.c +++ b/arch/ia64/kernel/ptrace.c @@ -23,6 +23,16 @@ #include <asm/uaccess.h> /* + * Bits in the PSR that we allow ptrace() to change: + * be, up, ac, mfl, mfh (the user mask; five bits total) + * db (debug breakpoint fault; one bit) + * id (instruction debug fault disable; one bit) + * dd (data debug fault disable; one bit) + * ri (restart instruction; two bits) + */ +#define CR_IPSR_CHANGE_MASK 0x06a00100003eUL + +/* * Collect the NaT bits for r1-r31 from sw->caller_unat and * sw->ar_unat and return a NaT bitset where bit i is set iff the NaT * bit of register i is set. @@ -352,6 +362,94 @@ ia64_poke (struct pt_regs *regs, struct task_struct *child, unsigned long addr, } /* + * Synchronize (i.e, write) the RSE backing store living in kernel + * space to the VM of the indicated child process. + * + * If new_bsp is non-zero, the bsp will (effectively) be updated to + * the new value upon resumption of the child process. This is + * accomplished by setting the loadrs value to zero and the bspstore + * value to the new bsp value. + * + * When new_bsp and force_loadrs_to_zero are both 0, the register + * backing store in kernel space is written to user space and the + * loadrs and bspstore values are left alone. + * + * When new_bsp is zero and force_loadrs_to_zero is 1 (non-zero), + * loadrs is set to 0, and the bspstore value is set to the old bsp + * value. This will cause the stacked registers (r32 and up) to be + * obtained entirely from the the child's memory space rather than + * from the kernel. (This makes it easier to write code for + * modifying the stacked registers in multi-threaded programs.) + * + * Note: I had originally written this function without the + * force_loadrs_to_zero parameter; it was written so that loadrs would + * always be set to zero. But I had problems with certain system + * calls apparently causing a portion of the RBS to be zeroed. (I + * still don't understand why this was happening.) Anyway, it'd + * definitely less intrusive to leave loadrs and bspstore alone if + * possible. + */ +static long +sync_kernel_register_backing_store (struct task_struct *child, + long new_bsp, + int force_loadrs_to_zero) +{ + unsigned long *krbs, bspstore, bsp, krbs_num_regs, rbs_end, addr, val; + long ndirty, ret; + struct pt_regs *child_regs; + struct switch_stack *child_stack; + + ret = 0; + child_regs = ia64_task_regs(child); + child_stack = (struct switch_stack *) child_regs - 1; + + krbs = (unsigned long *) child + IA64_RBS_OFFSET/8; + ndirty = ia64_rse_num_regs(krbs, krbs + (child_regs->loadrs >> 19)); + bspstore = child_regs->ar_bspstore; + bsp = (long) ia64_rse_skip_regs((long *)bspstore, ndirty); + krbs_num_regs = ia64_rse_num_regs(krbs, (unsigned long *) child_stack->ar_bspstore); + rbs_end = (long) ia64_rse_skip_regs((long *)bspstore, krbs_num_regs); + + /* Return early if nothing to do */ + if (bsp == new_bsp) + return 0; + + /* Write portion of backing store living on kernel stack to the child's VM. */ + for (addr = bspstore; addr < rbs_end; addr += 8) { + ret = ia64_peek(child_regs, child, addr, &val); + if (ret != 0) + return ret; + if (access_process_vm(child, addr, &val, sizeof(val), 1) != sizeof(val)) + return -EIO; + } + + if (new_bsp != 0) { + force_loadrs_to_zero = 1; + bsp = new_bsp; + } + + if (force_loadrs_to_zero) { + child_regs->loadrs = 0; + child_regs->ar_bspstore = bsp; + } + + return ret; +} + +static void +sync_thread_rbs (struct task_struct *child, int make_writable) +{ + struct task_struct *p; + read_lock(&tasklist_lock); + for_each_task(p) { + if (p->mm == child->mm && p->state != TASK_RUNNING) + sync_kernel_register_backing_store(p, 0, make_writable); + } + read_unlock(&tasklist_lock); + child->thread.flags |= IA64_THREAD_KRBS_SYNCED; +} + +/* * Ensure the state in child->thread.fph is up-to-date. */ static void @@ -375,8 +473,8 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data, struct switch_stack *child_stack; struct pt_regs *child_regs; struct task_struct *child; - unsigned long flags, *base; - long ret, regnum; + unsigned long flags, regnum, *base; + long ret; lock_kernel(); ret = -EPERM; @@ -441,6 +539,9 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data, switch (request) { case PTRACE_PEEKTEXT: case PTRACE_PEEKDATA: /* read word at location addr */ + if (!(child->thread.flags & IA64_THREAD_KRBS_SYNCED) + && atomic_read(&child->mm->mm_users) > 1) + sync_thread_rbs(child, 0); ret = ia64_peek(regs, child, addr, &data); if (ret == 0) { ret = data; @@ -450,6 +551,9 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data, case PTRACE_POKETEXT: case PTRACE_POKEDATA: /* write the word at location addr */ + if (!(child->thread.flags & IA64_THREAD_KRBS_SYNCED) + && atomic_read(&child->mm->mm_users) > 1) + sync_thread_rbs(child, 1); ret = ia64_poke(regs, child, addr, data); goto out; @@ -477,8 +581,35 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data, bspstore = (unsigned long *) child_regs->ar_bspstore; ndirty = ia64_rse_num_regs(rbs, rbs + (ret >> 19)); ret = (unsigned long) ia64_rse_skip_regs(bspstore, ndirty); + + /* + * If we're in a system call, no ``cover'' was done. So + * to make things uniform, we'll add the appropriate + * displacement onto bsp if we're in a system call. + * + * Note: It may be better to leave the system call case + * alone and subtract the amount of the cover for the + * non-syscall case. That way the reported bsp value + * would actually be the correct bsp for the child + * process. + */ + if (!(child_regs->cr_ifs & (1UL << 63))) { + ret = (unsigned long) + ia64_rse_skip_regs((unsigned long *) ret, + child_stack->ar_pfs & 0x7f); + } + } else if (addr == PT_CFM) { + /* ret currently contains pt_regs.cr_ifs */ + if ((ret & (1UL << 63)) == 0) + ret = child_stack->ar_pfs; + ret &= 0x3fffffffffUL; /* return only the CFM */ } } else { + if (!(child->thread.flags & IA64_THREAD_DBG_VALID)) { + child->thread.flags |= IA64_THREAD_DBG_VALID; + memset(child->thread.dbr, 0, sizeof child->thread.dbr); + memset(child->thread.ibr, 0, sizeof child->thread.ibr); + } if (addr >= PT_IBR) { regnum = (addr - PT_IBR) >> 3; base = &child->thread.ibr[0]; @@ -488,7 +619,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data, } if (regnum >= 8) goto out; - data = base[regnum]; + ret = base[regnum]; } regs->r8 = 0; /* ensure "ret" is not mistaken as an error code */ goto out; @@ -503,29 +634,47 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data, sync_fph(child); addr += (unsigned long) &child->thread.fph; *(unsigned long *) addr = data; - if (ret < 0) - goto out; + } else if (addr == PT_AR_BSPSTORE || addr == PT_CALLER_UNAT + || addr == PT_KERNEL_FPSR || addr == PT_K_B0 || addr == PT_K_AR_PFS + || (PT_K_AR_UNAT <= addr && addr <= PT_K_PR)) { + /* + * Don't permit changes to certain registers. + * + * We don't allow bspstore to be modified because doing + * so would mess up any modifications to bsp. (See + * sync_kernel_register_backing_store for the details.) + */ + goto out; + } else if (addr == PT_AR_BSP) { + /* FIXME? Account for lack of ``cover'' in the syscall case */ + ret = sync_kernel_register_backing_store(child, data, 1); + goto out; + } else if (addr == PT_CFM) { + child_regs = ia64_task_regs(child); + child_stack = (struct switch_stack *) child_regs - 1; + + if (child_regs->cr_ifs & (1UL << 63)) { + child_regs->cr_ifs = (child_regs->cr_ifs & ~0x3fffffffffUL) + | (data & 0x3fffffffffUL); + } else { + child_stack->ar_pfs = (child_stack->ar_pfs & ~0x3fffffffffUL) + | (data & 0x3fffffffffUL); + } } else if (addr < PT_F9+16) { /* accessing switch_stack or pt_regs */ child_regs = ia64_task_regs(child); child_stack = (struct switch_stack *) child_regs - 1; - if (addr == PT_AR_BSP) { - /* compute the loadrs value based on bsp and bspstore: */ - unsigned long *rbs, *bspstore, ndirty, *kbsp; - - bspstore = (unsigned long *) child_regs->ar_bspstore; - ndirty = ia64_rse_num_regs(bspstore, (unsigned long *) data); - rbs = (unsigned long *) child + IA64_RBS_OFFSET/8; - kbsp = ia64_rse_skip_regs(rbs, ndirty); - data = (kbsp - rbs) << 19; - } + if (addr == PT_CR_IPSR) + data = (data & CR_IPSR_CHANGE_MASK) + | (child_regs->cr_ipsr & ~CR_IPSR_CHANGE_MASK); + *(unsigned long *) ((long) child_stack + addr - PT_CALLER_UNAT) = data; } else { if (!(child->thread.flags & IA64_THREAD_DBG_VALID)) { child->thread.flags |= IA64_THREAD_DBG_VALID; - memset(current->thread.dbr, 0, sizeof current->thread.dbr); - memset(current->thread.ibr, 0, sizeof current->thread.ibr); + memset(child->thread.dbr, 0, sizeof child->thread.dbr); + memset(child->thread.ibr, 0, sizeof child->thread.ibr); } if (addr >= PT_IBR) { @@ -538,7 +687,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data, if (regnum >= 8) goto out; if (regnum & 1) { - /* force breakpoint to be effective a most for user-level: */ + /* force breakpoint to be effective only for user-level: */ data &= ~(0x7UL << 56); } base[regnum] = data; @@ -546,6 +695,23 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data, ret = 0; goto out; + case PTRACE_GETSIGINFO: + ret = -EIO; + if (!access_ok(VERIFY_WRITE, data, sizeof (siginfo_t)) + || child->thread.siginfo == 0) + goto out; + copy_to_user((siginfo_t *) data, child->thread.siginfo, sizeof (siginfo_t)); + ret = 0; + goto out; + break; + case PTRACE_SETSIGINFO: + ret = -EIO; + if (!access_ok(VERIFY_READ, data, sizeof (siginfo_t)) + || child->thread.siginfo == 0) + goto out; + copy_from_user(child->thread.siginfo, (siginfo_t *) data, sizeof (siginfo_t)); + ret = 0; + goto out; case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_CONT: /* restart after signal. */ ret = -EIO; @@ -561,6 +727,9 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data, ia64_psr(ia64_task_regs(child))->ss = 0; ia64_psr(ia64_task_regs(child))->tb = 0; + /* Turn off flag indicating that the KRBS is sync'd with child's VM: */ + child->thread.flags &= ~IA64_THREAD_KRBS_SYNCED; + wake_up_process(child); ret = 0; goto out; @@ -579,6 +748,9 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data, ia64_psr(ia64_task_regs(child))->ss = 0; ia64_psr(ia64_task_regs(child))->tb = 0; + /* Turn off flag indicating that the KRBS is sync'd with child's VM: */ + child->thread.flags &= ~IA64_THREAD_KRBS_SYNCED; + wake_up_process(child); ret = 0; goto out; @@ -597,6 +769,9 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data, } child->exit_code = data; + /* Turn off flag indicating that the KRBS is sync'd with child's VM: */ + child->thread.flags &= ~IA64_THREAD_KRBS_SYNCED; + /* give it a chance to run. */ wake_up_process(child); ret = 0; @@ -619,6 +794,9 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data, ia64_psr(ia64_task_regs(child))->ss = 0; ia64_psr(ia64_task_regs(child))->tb = 0; + /* Turn off flag indicating that the KRBS is sync'd with child's VM: */ + child->thread.flags &= ~IA64_THREAD_KRBS_SYNCED; + wake_up_process(child); ret = 0; goto out; diff --git a/arch/ia64/kernel/sal.c b/arch/ia64/kernel/sal.c index 8743f6588..f4b8ce9dd 100644 --- a/arch/ia64/kernel/sal.c +++ b/arch/ia64/kernel/sal.c @@ -139,7 +139,7 @@ ia64_sal_init (struct ia64_sal_systab *systab) case IA64_SAL_AP_EXTERNAL_INT: ap_wakeup_vector = ap->vector; # ifdef SAL_DEBUG - printk("SAL: AP wakeup using external interrupt; " + printk("SAL: AP wakeup using external interrupt " "vector 0x%lx\n", ap_wakeup_vector); # endif break; @@ -151,6 +151,36 @@ ia64_sal_init (struct ia64_sal_systab *systab) break; } #endif + case SAL_DESC_PLATFORM_FEATURE: + { + struct ia64_sal_desc_platform_feature *pf = (void *) p; + printk("SAL: Platform features "); + + if (pf->feature_mask & (1 << 0)) + printk("BusLock "); + + if (pf->feature_mask & (1 << 1)) { + printk("IRQ_Redirection "); +#ifdef CONFIG_SMP + if (no_int_routing) + smp_int_redirect &= ~SMP_IRQ_REDIRECTION; + else + smp_int_redirect |= SMP_IRQ_REDIRECTION; +#endif + } + if (pf->feature_mask & (1 << 2)) { + printk("IPI_Redirection "); +#ifdef CONFIG_SMP + if (no_int_routing) + smp_int_redirect &= ~SMP_IPI_REDIRECTION; + else + smp_int_redirect |= SMP_IPI_REDIRECTION; +#endif + } + printk("\n"); + break; + } + } p += SAL_DESC_SIZE(*p); } diff --git a/arch/ia64/kernel/sal_stub.S b/arch/ia64/kernel/sal_stub.S index 7ab16bbcd..d73851810 100644 --- a/arch/ia64/kernel/sal_stub.S +++ b/arch/ia64/kernel/sal_stub.S @@ -1,17 +1,19 @@ /* - * gcc currently does not conform to the ia-64 calling convention as far - * as returning function values are concerned. Instead of returning - * values up to 32 bytes in size in r8-r11, gcc returns any value - * bigger than a doubleword via a structure that's allocated by the - * caller and whose address is passed into the function. Since - * SAL_PROC returns values according to the calling convention, this - * stub takes care of copying r8-r11 to the place where gcc expects - * them. - * - * Copyright (C) 1998, 1999 Hewlett-Packard Co - * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com> + * Copyright (C) 1998-2000 Hewlett-Packard Co + * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com> */ #ifndef __GCC_MULTIREG_RETVALS__ + /* + * gcc currently does not conform to the ia-64 calling + * convention as far as returning function values are + * concerned. Instead of returning values up to 32 bytes in + * size in r8-r11, gcc returns any value bigger than a + * doubleword via a structure that's allocated by the caller + * and whose address is passed into the function. Since + * SAL_PROC returns values according to the calling + * convention, this stub takes care of copying r8-r11 to the + * place where gcc expects them. + */ .text .psr abi64 .psr lsb diff --git a/arch/ia64/kernel/semaphore.c b/arch/ia64/kernel/semaphore.c index 980fa4329..bc55670bf 100644 --- a/arch/ia64/kernel/semaphore.c +++ b/arch/ia64/kernel/semaphore.c @@ -310,7 +310,7 @@ __down_write_failed (struct rw_semaphore *sem, long count) do { old_count = sem->count; count = old_count - RW_LOCK_BIAS; - } while (cmpxchg(&sem->count, old_count, count) != old_count); + } while (cmpxchg_acq(&sem->count, old_count, count) != old_count); if (count == 0) return; diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index 58ddb1fb1..80838f990 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -8,10 +8,12 @@ * Copyright (C) 1999 VA Linux Systems * Copyright (C) 1999 Walt Drummond <drummond@valinux.com> * - * 02/04/00 D.Mosberger some more get_cpuinfo fixes... - * 02/01/00 R.Seth fixed get_cpuinfo for SMP - * 01/07/99 S.Eranian added the support for command line argument - * 06/24/99 W.Drummond added boot_cpu_data. + * 04/04/00 D.Mosberger renamed cpu_initialized to cpu_online_map + * 03/31/00 R.Seth cpu_initialized and current->processor fixes + * 02/04/00 D.Mosberger some more get_cpuinfo fixes... + * 02/01/00 R.Seth fixed get_cpuinfo for SMP + * 01/07/99 S.Eranian added the support for command line argument + * 06/24/99 W.Drummond added boot_cpu_data. */ #include <linux/config.h> #include <linux/init.h> @@ -32,6 +34,7 @@ #include <asm/sal.h> #include <asm/system.h> #include <asm/efi.h> +#include <asm/mca.h> extern char _end; @@ -41,10 +44,13 @@ struct cpuinfo_ia64 cpu_data[NR_CPUS]; unsigned long ia64_cycles_per_usec; struct ia64_boot_param ia64_boot_param; struct screen_info screen_info; -unsigned long cpu_initialized = 0; /* This tells _start which CPU is booting. */ int cpu_now_booting = 0; +#ifdef CONFIG_SMP +volatile unsigned long cpu_online_map; +#endif + #define COMMAND_LINE_SIZE 512 char saved_command_line[COMMAND_LINE_SIZE]; /* used in proc filesystem */ @@ -101,7 +107,6 @@ void __init setup_arch (char **cmdline_p) { unsigned long max_pfn, bootmap_start, bootmap_size; - u64 progress; /* * The secondary bootstrap loader passes us the boot @@ -147,7 +152,10 @@ setup_arch (char **cmdline_p) printk("args to kernel: %s\n", *cmdline_p); -#ifndef CONFIG_SMP +#ifdef CONFIG_SMP + bootstrap_processor = hard_smp_processor_id(); + current->processor = bootstrap_processor; +#else cpu_init(); identify_cpu(&cpu_data[0]); #endif @@ -168,6 +176,11 @@ setup_arch (char **cmdline_p) conswitchp = &dummy_con; # endif #endif + +#ifdef CONFIG_IA64_MCA + /* enable IA-64 Machine Check Abort Handling */ + ia64_mca_init(); +#endif paging_init(); platform_setup(cmdline_p); } @@ -183,8 +196,10 @@ get_cpuinfo (char *buffer) unsigned long mask; for (c = cpu_data; c < cpu_data + NR_CPUS; ++c) { - if (!(cpu_initialized & (1UL << (c - cpu_data)))) +#ifdef CONFIG_SMP + if (!(cpu_online_map & (1UL << (c - cpu_data)))) continue; +#endif mask = c->features; @@ -209,7 +224,7 @@ get_cpuinfo (char *buffer) if (mask) sprintf(cp, " 0x%lx", mask); - p += sprintf(buffer, + p += sprintf(p, "CPU# %lu\n" "\tvendor : %s\n" "\tfamily : %s\n" @@ -303,8 +318,6 @@ identify_cpu (struct cpuinfo_ia64 *c) void cpu_init (void) { - int nr = smp_processor_id(); - /* Clear the stack memory reserved for pt_regs: */ memset(ia64_task_regs(current), 0, sizeof(struct pt_regs)); @@ -318,11 +331,6 @@ cpu_init (void) */ ia64_set_dcr(IA64_DCR_DR | IA64_DCR_DK | IA64_DCR_DX | IA64_DCR_PP); ia64_set_fpu_owner(0); /* initialize ar.k5 */ - - if (test_and_set_bit(nr, &cpu_initialized)) { - printk("CPU#%d already initialized!\n", nr); - machine_halt(); - } atomic_inc(&init_mm.mm_count); current->active_mm = &init_mm; } diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c index 19be1f840..a0cca9da7 100644 --- a/arch/ia64/kernel/signal.c +++ b/arch/ia64/kernel/signal.c @@ -94,7 +94,7 @@ static long restore_sigcontext (struct sigcontext *sc, struct pt_regs *pt) { struct switch_stack *sw = (struct switch_stack *) pt - 1; - unsigned long ip, flags, nat, um; + unsigned long ip, flags, nat, um, cfm; long err; /* restore scratch that always needs gets updated during signal delivery: */ @@ -102,20 +102,24 @@ restore_sigcontext (struct sigcontext *sc, struct pt_regs *pt) err |= __get_user(nat, &sc->sc_nat); err |= __get_user(ip, &sc->sc_ip); /* instruction pointer */ - err |= __get_user(pt->ar_fpsr, &sc->sc_ar_fpsr); - err |= __get_user(pt->ar_pfs, &sc->sc_ar_pfs); + err |= __get_user(cfm, &sc->sc_cfm); err |= __get_user(um, &sc->sc_um); /* user mask */ err |= __get_user(pt->ar_rsc, &sc->sc_ar_rsc); err |= __get_user(pt->ar_ccv, &sc->sc_ar_ccv); err |= __get_user(pt->ar_unat, &sc->sc_ar_unat); + err |= __get_user(pt->ar_fpsr, &sc->sc_ar_fpsr); + err |= __get_user(pt->ar_pfs, &sc->sc_ar_pfs); err |= __get_user(pt->pr, &sc->sc_pr); /* predicates */ err |= __get_user(pt->b0, &sc->sc_br[0]); /* b0 (rp) */ - err |= __get_user(pt->b6, &sc->sc_br[6]); + err |= __get_user(pt->b6, &sc->sc_br[6]); /* b6 */ + err |= __get_user(pt->b7, &sc->sc_br[7]); /* b7 */ err |= __copy_from_user(&pt->r1, &sc->sc_gr[1], 3*8); /* r1-r3 */ err |= __copy_from_user(&pt->r8, &sc->sc_gr[8], 4*8); /* r8-r11 */ err |= __copy_from_user(&pt->r12, &sc->sc_gr[12], 4*8); /* r12-r15 */ err |= __copy_from_user(&pt->r16, &sc->sc_gr[16], 16*8); /* r16-r31 */ + pt->cr_ifs = cfm | (1UL << 63); + /* establish new instruction pointer: */ pt->cr_iip = ip & ~0x3UL; ia64_psr(pt)->ri = ip & 0x3; @@ -240,6 +244,7 @@ setup_sigcontext (struct sigcontext *sc, sigset_t *mask, struct pt_regs *pt) nat = ia64_get_nat_bits(pt, sw); err = __put_user(flags, &sc->sc_flags); + err |= __put_user(nat, &sc->sc_nat); err |= PUT_SIGSET(mask, &sc->sc_mask); err |= __put_user(pt->cr_ipsr & IA64_PSR_UM, &sc->sc_um); @@ -255,8 +260,8 @@ setup_sigcontext (struct sigcontext *sc, sigset_t *mask, struct pt_regs *pt) err |= __copy_to_user(&sc->sc_gr[1], &pt->r1, 3*8); /* r1-r3 */ err |= __copy_to_user(&sc->sc_gr[8], &pt->r8, 4*8); /* r8-r11 */ - err |= __copy_to_user(&sc->sc_gr[12], &pt->r12, 4*8); /* r12-r15 */ - err |= __copy_to_user(&sc->sc_gr[16], &pt->r16, 16*8); /* r16-r31 */ + err |= __copy_to_user(&sc->sc_gr[12], &pt->r12, 4*8); /* r12-r15 */ + err |= __copy_to_user(&sc->sc_gr[16], &pt->r16, 16*8); /* r16-r31 */ err |= __put_user(pt->cr_iip + ia64_psr(pt)->ri, &sc->sc_ip); err |= __put_user(pt->r12, &sc->sc_gr[12]); /* r12 */ @@ -415,10 +420,12 @@ ia64_do_signal (sigset_t *oldset, struct pt_regs *pt, long in_syscall) if ((current->flags & PF_PTRACED) && signr != SIGKILL) { /* Let the debugger run. */ current->exit_code = signr; + current->thread.siginfo = &info; set_current_state(TASK_STOPPED); notify_parent(current, SIGCHLD); schedule(); signr = current->exit_code; + current->thread.siginfo = 0; /* We're back. Did the debugger cancel the sig? */ if (!signr) diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c index ed5d594a6..43d9f2dde 100644 --- a/arch/ia64/kernel/smp.c +++ b/arch/ia64/kernel/smp.c @@ -6,6 +6,8 @@ * * Lots of stuff stolen from arch/alpha/kernel/smp.c * + * 00/03/31 Rohit Seth <rohit.seth@intel.com> Fixes for Bootstrap Processor & cpu_online_map + * now gets done here (instead of setup.c) * 99/10/05 davidm Update to bring it in sync with new command-line processing scheme. */ #define __KERNEL_SYSCALLS__ @@ -24,15 +26,6 @@ #include <asm/bitops.h> #include <asm/current.h> #include <asm/delay.h> - -#ifdef CONFIG_KDB -#include <linux/kdb.h> -void smp_kdb_interrupt (struct pt_regs* regs); -void kdb_global(int cpuid); -extern unsigned long smp_kdb_wait; -extern int kdb_new_cpu; -#endif - #include <asm/io.h> #include <asm/irq.h> #include <asm/page.h> @@ -47,25 +40,24 @@ extern int kdb_new_cpu; extern int cpu_idle(void * unused); extern void _start(void); -extern int cpu_now_booting; /* Used by head.S to find idle task */ -extern unsigned long cpu_initialized; /* Bitmap of available cpu's */ -extern struct cpuinfo_ia64 cpu_data[NR_CPUS]; /* Duh... */ +extern int cpu_now_booting; /* Used by head.S to find idle task */ +extern volatile unsigned long cpu_online_map; /* Bitmap of available cpu's */ +extern struct cpuinfo_ia64 cpu_data[NR_CPUS]; /* Duh... */ spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED; -#ifdef CONFIG_KDB -unsigned long cpu_online_map = 1; -#endif +struct smp_boot_data __initdata smp; +char __initdata no_int_routing = 0; +unsigned char smp_int_redirect; /* are INT and IPI redirectable by the chipset? */ volatile int __cpu_number_map[NR_CPUS] = { -1, }; /* SAPIC ID -> Logical ID */ volatile int __cpu_logical_map[NR_CPUS] = { -1, }; /* logical ID -> SAPIC ID */ int smp_num_cpus = 1; -int bootstrap_processor = -1; /* SAPIC ID of BSP */ -int smp_threads_ready = 0; /* Set when the idlers are all forked */ -unsigned long ipi_base_addr = IPI_DEFAULT_BASE_ADDR; /* Base addr of IPI table */ +int bootstrap_processor = -1; /* SAPIC ID of BSP */ +int smp_threads_ready = 0; /* Set when the idlers are all forked */ cycles_t cacheflush_time = 0; -unsigned long ap_wakeup_vector = -1; /* External Int to use to wakeup AP's */ -static int max_cpus = -1; /* Command line */ +unsigned long ap_wakeup_vector = -1; /* External Int to use to wakeup AP's */ +static int max_cpus = -1; /* Command line */ static unsigned long ipi_op[NR_CPUS]; struct smp_call_struct { void (*func) (void *info); @@ -76,20 +68,13 @@ struct smp_call_struct { }; static struct smp_call_struct *smp_call_function_data; -#ifdef CONFIG_KDB -unsigned long smp_kdb_wait = 0; /* Bitmask of waiters */ -#endif - #ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC extern spinlock_t ivr_read_lock; #endif -int use_xtp = 0; /* XXX */ - #define IPI_RESCHEDULE 0 #define IPI_CALL_FUNC 1 #define IPI_CPU_STOP 2 -#define IPI_KDB_INTERRUPT 4 /* * Setup routine for controlling SMP activation @@ -118,13 +103,22 @@ static int __init maxcpus(char *str) __setup("maxcpus=", maxcpus); +static int __init +nointroute(char *str) +{ + no_int_routing = 1; + return 1; +} + +__setup("nointroute", nointroute); + /* * Yoink this CPU from the runnable list... */ void halt_processor(void) { - clear_bit(smp_processor_id(), &cpu_initialized); + clear_bit(smp_processor_id(), &cpu_online_map); max_xtp(); __cli(); for (;;) @@ -188,12 +182,6 @@ handle_IPI(int irq, void *dev_id, struct pt_regs *regs) halt_processor(); break; -#ifdef CONFIG_KDB - case IPI_KDB_INTERRUPT: - smp_kdb_interrupt(regs); - break; -#endif - default: printk(KERN_CRIT "Unknown IPI on CPU %d: %lu\n", this_cpu, which); break; @@ -205,32 +193,6 @@ handle_IPI(int irq, void *dev_id, struct pt_regs *regs) } static inline void -send_IPI(int dest_cpu, unsigned char vector) -{ - unsigned long ipi_addr; - unsigned long ipi_data; -#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC - unsigned long flags; -#endif - - ipi_data = vector; - ipi_addr = ipi_base_addr | ((dest_cpu << 8) << 4); /* 16-bit SAPIC ID's; assume CPU bus 0 */ - mb(); - -#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC - /* - * Disable IVR reads - */ - spin_lock_irqsave(&ivr_read_lock, flags); - writeq(ipi_data, ipi_addr); - spin_unlock_irqrestore(&ivr_read_lock, flags); -#else - writeq(ipi_data, ipi_addr); -#endif /* CONFIG_ITANIUM_ASTEP_SPECIFIC */ - -} - -static inline void send_IPI_single(int dest_cpu, int op) { @@ -238,7 +200,7 @@ send_IPI_single(int dest_cpu, int op) return; ipi_op[dest_cpu] |= (1 << op); - send_IPI(dest_cpu, IPI_IRQ); + ipi_send(dest_cpu, IPI_IRQ, IA64_IPI_DM_INT, 0); } static inline void @@ -452,9 +414,11 @@ start_ap(void) ia64_clear_ic(flags); ia64_set_rr( 0, (0x1000 << 8) | (_PAGE_SIZE_1M << 2)); ia64_set_rr(PAGE_OFFSET, (ia64_rid(0, PAGE_OFFSET) << 8) | (_PAGE_SIZE_256M << 2)); + ia64_srlz_d(); ia64_itr(0x3, 1, PAGE_OFFSET, pte_val(mk_pte_phys(0, __pgprot(__DIRTY_BITS|_PAGE_PL_0|_PAGE_AR_RWX))), _PAGE_SIZE_256M); + ia64_srlz_i(); flags = (IA64_PSR_IT | IA64_PSR_IC | IA64_PSR_DT | IA64_PSR_RT | IA64_PSR_DFH | IA64_PSR_BN); @@ -492,6 +456,10 @@ smp_callin(void) smp_store_cpu_info(smp_processor_id()); smp_setup_percpu_timer(smp_processor_id()); + if (test_and_set_bit(smp_processor_id(), &cpu_online_map)) { + printk("CPU#%d already initialized!\n", smp_processor_id()); + machine_halt(); + } while (!smp_threads_ready) mb(); @@ -505,6 +473,9 @@ smp_callin(void) ia64_set_lrr1(0, 1); __sti(); /* Interrupts have been off till now. */ + + printk("SMP: CPU %d starting idle loop\n", smp_processor_id()); + cpu_idle(NULL); } @@ -565,7 +536,7 @@ smp_boot_one_cpu(int cpuid, int cpunum) cpu_now_booting = cpunum; /* Kick the AP in the butt */ - send_IPI(cpuid, ap_wakeup_vector); + ipi_send(cpuid, ap_wakeup_vector, IA64_IPI_DM_INT, 0); ia64_srlz_i(); mb(); @@ -575,24 +546,20 @@ smp_boot_one_cpu(int cpuid, int cpunum) * is waiting for smp_threads_ready to be 1 and we can move on. */ for (timeout = 0; timeout < 100000; timeout++) { - if (test_bit(cpuid, &cpu_initialized)) + if (test_bit(cpuid, &cpu_online_map)) goto alive; - udelay(10); + udelay(100); barrier(); } printk(KERN_ERR "SMP: Processor %d is stuck.\n", cpuid); - return -1; + return 0; alive: /* Remember the AP data */ __cpu_number_map[cpuid] = cpunum; -#ifdef CONFIG_KDB - cpu_online_map |= (1<<cpunum); - printk ("DEBUGGER: cpu_online_map = 0x%08x\n", cpu_online_map); -#endif __cpu_logical_map[cpunum] = cpuid; - return 0; + return 1; } @@ -607,9 +574,6 @@ smp_boot_cpus(void) { int i, cpu_count = 1; unsigned long bogosum; - int sapic_id; - extern int acpi_cpus; - extern int acpi_apic_map[32]; /* Take care of some initial bookkeeping. */ memset(&__cpu_number_map, -1, sizeof(__cpu_number_map)); @@ -634,6 +598,10 @@ smp_boot_cpus(void) #endif smp_setup_percpu_timer(bootstrap_processor); + if (test_and_set_bit(bootstrap_processor, &cpu_online_map)) { + printk("CPU#%d already initialized!\n", smp_processor_id()); + machine_halt(); + } init_idle(); /* Nothing to do when told not to. */ @@ -642,33 +610,36 @@ smp_boot_cpus(void) return; } - if (acpi_cpus > 1) { + if (max_cpus != -1) + printk("Limiting CPUs to %d\n", max_cpus); + + if (smp.cpu_count > 1) { printk(KERN_INFO "SMP: starting up secondaries.\n"); for (i = 0; i < NR_CPUS; i++) { - if (acpi_apic_map[i] == -1 || - acpi_apic_map[i] == bootstrap_processor << 8) /* XXX Fix me Walt */ + if (smp.cpu_map[i] == -1 || + smp.cpu_map[i] == bootstrap_processor) continue; - /* - * IA64 SAPIC ID's are 16-bits. See asm/smp.h for more info - */ - sapic_id = acpi_apic_map[i] >> 8; - if (smp_boot_one_cpu(sapic_id, cpu_count)) + if (smp_boot_one_cpu(smp.cpu_map[i], cpu_count) == 0) continue; cpu_count++; /* Count good CPUs only... */ + /* + * Bail if we've started as many CPUS as we've been told to. + */ + if (cpu_count == max_cpus) + break; } } if (cpu_count == 1) { printk(KERN_ERR "SMP: Bootstrap processor only.\n"); - return; } bogosum = 0; for (i = 0; i < NR_CPUS; i++) { - if (cpu_initialized & (1L << i)) + if (cpu_online_map & (1L << i)) bogosum += cpu_data[i].loops_per_sec; } @@ -733,45 +704,8 @@ init_smp_config(void) if (sal_ret < 0) { printk("SMP: Can't set SAL AP Boot Rendezvous: %s\n", ia64_sal_strerror(sal_ret)); printk(" Forcing UP mode\n"); + max_cpus = 0; smp_num_cpus = 1; } } - -#ifdef CONFIG_KDB -void smp_kdb_stop (int all, struct pt_regs* regs) -{ - if (all) - { - printk ("Sending IPI to all on CPU %i\n", smp_processor_id ()); - smp_kdb_wait = 0xffffffff; - clear_bit (smp_processor_id(), &smp_kdb_wait); - send_IPI_allbutself (IPI_KDB_INTERRUPT); - } - else - { - printk ("Sending IPI to self on CPU %i\n", - smp_processor_id ()); - set_bit (smp_processor_id(), &smp_kdb_wait); - clear_bit (__cpu_logical_map[kdb_new_cpu], &smp_kdb_wait); - smp_kdb_interrupt (regs); - } -} - -void smp_kdb_interrupt (struct pt_regs* regs) -{ - printk ("kdb: IPI on CPU %i with mask 0x%08x\n", - smp_processor_id (), smp_kdb_wait); - - /* All CPUs spin here forever */ - while (test_bit (smp_processor_id(), &smp_kdb_wait)); - - /* Enter KDB on CPU selected by KDB on the last CPU */ - if (__cpu_logical_map[kdb_new_cpu] == smp_processor_id ()) - { - kdb (KDB_REASON_SWITCH, 0, regs); - } -} - -#endif - diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c new file mode 100644 index 000000000..3550cc390 --- /dev/null +++ b/arch/ia64/kernel/smpboot.c @@ -0,0 +1,2 @@ +unsigned long cpu_online_map; + diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c index 133520b84..b88855ce4 100644 --- a/arch/ia64/kernel/time.c +++ b/arch/ia64/kernel/time.c @@ -9,11 +9,12 @@ * Copyright (C) 1999-2000 Walt Drummond <drummond@valinux.com> */ #include <linux/config.h> + #include <linux/init.h> -#include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/time.h> +#include <linux/interrupt.h> #include <asm/delay.h> #include <asm/efi.h> @@ -136,6 +137,7 @@ timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static unsigned long last_time; static unsigned char count; int cpu = smp_processor_id(); + int printed = 0; /* * Here we are in the timer irq handler. We have irqs locally @@ -145,9 +147,14 @@ timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) */ write_lock(&xtime_lock); while (1) { - /* do kernel PC profiling here. */ + /* + * Do kernel PC profiling here. We multiply the + * instruction number by four so that we can use a + * prof_shift of 2 to get instruction-level instead of + * just bundle-level accuracy. + */ if (!user_mode(regs)) - do_profile(regs->cr_iip); + do_profile(regs->cr_iip + 4*ia64_psr(regs)->ri); #ifdef CONFIG_SMP smp_do_timer(regs); @@ -172,15 +179,18 @@ timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) #if !(defined(CONFIG_IA64_SOFTSDV_HACKS) && defined(CONFIG_SMP)) /* - * SoftSDV in SMP mode is _slow_, so we do "loose" ticks, + * SoftSDV in SMP mode is _slow_, so we do "lose" ticks, * but it's really OK... */ if (count > 0 && jiffies - last_time > 5*HZ) count = 0; if (count++ == 0) { last_time = jiffies; - printk("Lost clock tick on CPU %d (now=%lx, next=%lx)!!\n", - cpu, ia64_get_itc(), itm.next[cpu]); + if (!printed) { + printk("Lost clock tick on CPU %d (now=%lx, next=%lx)!!\n", + cpu, ia64_get_itc(), itm.next[cpu]); + printed = 1; + } # ifdef CONFIG_IA64_DEBUG_IRQ printk("last_cli_ip=%lx\n", last_cli_ip); # endif @@ -303,8 +313,6 @@ void __init time_init (void) { /* we can't do request_irq() here because the kmalloc() would fail... */ - irq_desc[TIMER_IRQ].status = IRQ_DISABLED; - irq_desc[TIMER_IRQ].handler = &irq_type_ia64_internal; setup_irq(TIMER_IRQ, &timer_irqaction); efi_gettimeofday(&xtime); diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c index ddb079f13..3a7706a27 100644 --- a/arch/ia64/kernel/traps.c +++ b/arch/ia64/kernel/traps.c @@ -32,10 +32,7 @@ register double f30 asm ("f30"); register double f31 asm ("f31"); #include <linux/init.h> #include <linux/sched.h> -#ifdef CONFIG_KDB -# include <linux/kdb.h> -#endif - +#include <asm/ia32.h> #include <asm/processor.h> #include <asm/uaccess.h> @@ -88,13 +85,6 @@ die_if_kernel (char *str, struct pt_regs *regs, long err) printk("%s[%d]: %s %ld\n", current->comm, current->pid, str, err); -#ifdef CONFIG_KDB - while (1) { - kdb(KDB_REASON_PANIC, 0, regs); - printk("Cant go anywhere from Panic!\n"); - } -#endif - show_regs(regs); if (current->thread.flags & IA64_KERNEL_DEATH) { @@ -440,7 +430,18 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, case 35: /* Taken Branch Trap */ case 36: /* Single Step Trap */ switch (vector) { - case 29: siginfo.si_code = TRAP_BRKPT; break; + case 29: + siginfo.si_code = TRAP_HWBKPT; +#ifdef CONFIG_ITANIUM + /* + * Erratum 10 (IFA may contain incorrect address) now has + * "NoFix" status. There are no plans for fixing this. + */ + if (ia64_psr(regs)->is == 0) + ifa = regs->cr_iip; +#endif + siginfo.si_addr = (void *) ifa; + break; case 35: siginfo.si_code = TRAP_BRANCH; break; case 36: siginfo.si_code = TRAP_TRACE; break; } @@ -479,12 +480,18 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, break; case 45: - printk("Unexpected IA-32 exception\n"); +#ifdef CONFIG_IA32_SUPPORT + if (ia32_exception(regs, isr) == 0) + return; +#endif + printk("Unexpected IA-32 exception (Trap 45)\n"); + printk(" iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx\n", regs->cr_iip, ifa, isr); force_sig(SIGSEGV, current); - return; + break; case 46: - printk("Unexpected IA-32 intercept trap\n"); + printk("Unexpected IA-32 intercept trap (Trap 46)\n"); + printk(" iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx\n", regs->cr_iip, ifa, isr); force_sig(SIGSEGV, current); return; diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c index 014adcf35..35e8cb846 100644 --- a/arch/ia64/kernel/unaligned.c +++ b/arch/ia64/kernel/unaligned.c @@ -305,7 +305,7 @@ set_rse_reg(struct pt_regs *regs, unsigned long r1, unsigned long val, int nat) DPRINT(("rnat @%p = 0x%lx nat=%d rnatval=%lx\n", addr, rnats, nat, rnats &ia64_rse_slot_num(slot))); - if ( nat ) { + if (nat) { rnats |= __IA64_UL(1) << ia64_rse_slot_num(slot); } else { rnats &= ~(__IA64_UL(1) << ia64_rse_slot_num(slot)); @@ -385,7 +385,8 @@ get_rse_reg(struct pt_regs *regs, unsigned long r1, unsigned long *val, int *nat ia64_peek(regs, current, (unsigned long)addr, &rnats); DPRINT(("rnat @%p = 0x%lx\n", addr, rnats)); - if ( nat ) *nat = rnats >> ia64_rse_slot_num(slot) & 0x1; + if (nat) + *nat = rnats >> ia64_rse_slot_num(slot) & 0x1; } @@ -401,7 +402,7 @@ setreg(unsigned long regnum, unsigned long val, int nat, struct pt_regs *regs) /* * First takes care of stacked registers */ - if ( regnum >= IA64_FIRST_STACKED_GR ) { + if (regnum >= IA64_FIRST_STACKED_GR) { set_rse_reg(regs, regnum, val, nat); return; } @@ -414,7 +415,7 @@ setreg(unsigned long regnum, unsigned long val, int nat, struct pt_regs *regs) /* * Now look at registers in [0-31] range and init correct UNAT */ - if ( GR_IN_SW(regnum) ) { + if (GR_IN_SW(regnum)) { addr = (unsigned long)sw; unat = &sw->ar_unat; } else { @@ -437,7 +438,7 @@ setreg(unsigned long regnum, unsigned long val, int nat, struct pt_regs *regs) */ bitmask = __IA64_UL(1) << (addr >> 3 & 0x3f); DPRINT(("*0x%lx=0x%lx NaT=%d prev_unat @%p=%lx\n", addr, val, nat, unat, *unat)); - if ( nat ) { + if (nat) { *unat |= bitmask; } else { *unat &= ~bitmask; @@ -465,7 +466,7 @@ setfpreg(unsigned long regnum, struct ia64_fpreg *fpval, struct pt_regs *regs) * fly to store to the right register. * For now, we are using the (slow) save/restore way. */ - if ( regnum >= IA64_FIRST_ROTATING_FR ) { + if (regnum >= IA64_FIRST_ROTATING_FR) { /* * force a save of [32-127] to tss * we use the __() form to avoid fiddling with the dfh bit @@ -489,7 +490,7 @@ setfpreg(unsigned long regnum, struct ia64_fpreg *fpval, struct pt_regs *regs) /* * pt_regs or switch_stack ? */ - if ( FR_IN_SW(regnum) ) { + if (FR_IN_SW(regnum)) { addr = (unsigned long)sw; } else { addr = (unsigned long)regs; @@ -542,7 +543,7 @@ getfpreg(unsigned long regnum, struct ia64_fpreg *fpval, struct pt_regs *regs) * we need to force a save to the tss to get access to it. * See discussion in setfpreg() for reasons and other ways of doing this. */ - if ( regnum >= IA64_FIRST_ROTATING_FR ) { + if (regnum >= IA64_FIRST_ROTATING_FR) { /* * force a save of [32-127] to tss @@ -587,7 +588,7 @@ getreg(unsigned long regnum, unsigned long *val, int *nat, struct pt_regs *regs) struct switch_stack *sw = (struct switch_stack *)regs -1; unsigned long addr, *unat; - if ( regnum >= IA64_FIRST_STACKED_GR ) { + if (regnum >= IA64_FIRST_STACKED_GR) { get_rse_reg(regs, regnum, val, nat); return; } @@ -595,7 +596,7 @@ getreg(unsigned long regnum, unsigned long *val, int *nat, struct pt_regs *regs) /* * take care of r0 (read-only always evaluate to 0) */ - if ( regnum == 0 ) { + if (regnum == 0) { *val = 0; *nat = 0; return; @@ -604,7 +605,7 @@ getreg(unsigned long regnum, unsigned long *val, int *nat, struct pt_regs *regs) /* * Now look at registers in [0-31] range and init correct UNAT */ - if ( GR_IN_SW(regnum) ) { + if (GR_IN_SW(regnum)) { addr = (unsigned long)sw; unat = &sw->ar_unat; } else { @@ -621,7 +622,8 @@ getreg(unsigned long regnum, unsigned long *val, int *nat, struct pt_regs *regs) /* * do it only when requested */ - if ( nat ) *nat = (*unat >> (addr >> 3 & 0x3f)) & 0x1UL; + if (nat) + *nat = (*unat >> (addr >> 3 & 0x3f)) & 0x1UL; } static void @@ -633,7 +635,7 @@ emulate_load_updates(update_t type, load_store_t *ld, struct pt_regs *regs, unsi * not get to this point in the code but we keep this sanity check, * just in case. */ - if ( ld->x6_op == 1 || ld->x6_op == 3 ) { + if (ld->x6_op == 1 || ld->x6_op == 3) { printk(KERN_ERR __FUNCTION__": register update on speculative load, error\n"); die_if_kernel("unaligned reference on specualtive load with register update\n", regs, 30); @@ -644,7 +646,7 @@ emulate_load_updates(update_t type, load_store_t *ld, struct pt_regs *regs, unsi * at this point, we know that the base register to update is valid i.e., * it's not r0 */ - if ( type == UPD_IMMEDIATE ) { + if (type == UPD_IMMEDIATE) { unsigned long imm; /* @@ -670,7 +672,7 @@ emulate_load_updates(update_t type, load_store_t *ld, struct pt_regs *regs, unsi DPRINT(("ld.x=%d ld.m=%d imm=%ld r3=0x%lx\n", ld->x, ld->m, imm, ifa)); - } else if ( ld->m ) { + } else if (ld->m) { unsigned long r2; int nat_r2; @@ -719,7 +721,7 @@ emulate_load_int(unsigned long ifa, load_store_t *ld, struct pt_regs *regs) * * Note: the first argument is ignored */ - if ( access_ok(VERIFY_READ, (void *)ifa, len) < 0 ) { + if (access_ok(VERIFY_READ, (void *)ifa, len) < 0) { DPRINT(("verify area failed on %lx\n", ifa)); return -1; } @@ -737,7 +739,7 @@ emulate_load_int(unsigned long ifa, load_store_t *ld, struct pt_regs *regs) * invalidate the ALAT entry. * See comment below for explanation on how we handle ldX.a */ - if ( ld->x6_op != 0x2 ) { + if (ld->x6_op != 0x2) { /* * we rely on the macros in unaligned.h for now i.e., * we let the compiler figure out how to read memory gracefully. @@ -767,9 +769,8 @@ emulate_load_int(unsigned long ifa, load_store_t *ld, struct pt_regs *regs) /* * check for updates on any kind of loads */ - if ( ld->op == 0x5 || ld->m ) - emulate_load_updates(ld->op == 0x5 ? UPD_IMMEDIATE: UPD_REG, - ld, regs, ifa); + if (ld->op == 0x5 || ld->m) + emulate_load_updates(ld->op == 0x5 ? UPD_IMMEDIATE: UPD_REG, ld, regs, ifa); /* * handling of various loads (based on EAS2.4): @@ -882,7 +883,7 @@ emulate_store_int(unsigned long ifa, load_store_t *ld, struct pt_regs *regs) * * Note: the first argument is ignored */ - if ( access_ok(VERIFY_WRITE, (void *)ifa, len) < 0 ) { + if (access_ok(VERIFY_WRITE, (void *)ifa, len) < 0) { DPRINT(("verify area failed on %lx\n",ifa)); return -1; } @@ -926,7 +927,7 @@ emulate_store_int(unsigned long ifa, load_store_t *ld, struct pt_regs *regs) * ld->r3 can never be r0, because r0 would not generate an * unaligned access. */ - if ( ld->op == 0x5 ) { + if (ld->op == 0x5) { unsigned long imm; /* @@ -936,7 +937,7 @@ emulate_store_int(unsigned long ifa, load_store_t *ld, struct pt_regs *regs) /* * sign extend (8bits) if m set */ - if ( ld->m ) imm |= SIGN_EXT9; + if (ld->m) imm |= SIGN_EXT9; /* * ifa == r3 (NaT is necessarily cleared) */ @@ -955,7 +956,8 @@ emulate_store_int(unsigned long ifa, load_store_t *ld, struct pt_regs *regs) /* * stX.rel: use fence instead of release */ - if ( ld->x6_op == 0xd ) mb(); + if (ld->x6_op == 0xd) + mb(); return 0; } @@ -1033,7 +1035,7 @@ emulate_load_floatpair(unsigned long ifa, load_store_t *ld, struct pt_regs *regs struct ia64_fpreg fpr_final[2]; unsigned long len = float_fsz[ld->x6_sz]; - if ( access_ok(VERIFY_READ, (void *)ifa, len<<1) < 0 ) { + if (access_ok(VERIFY_READ, (void *)ifa, len<<1) < 0) { DPRINT(("verify area failed on %lx\n", ifa)); return -1; } @@ -1055,7 +1057,7 @@ emulate_load_floatpair(unsigned long ifa, load_store_t *ld, struct pt_regs *regs * ldfpX.a: we don't try to emulate anything but we must * invalidate the ALAT entry and execute updates, if any. */ - if ( ld->x6_op != 0x2 ) { + if (ld->x6_op != 0x2) { /* * does the unaligned access */ @@ -1118,7 +1120,7 @@ emulate_load_floatpair(unsigned long ifa, load_store_t *ld, struct pt_regs *regs * Check for updates: only immediate updates are available for this * instruction. */ - if ( ld->m ) { + if (ld->m) { /* * the immediate is implicit given the ldsz of the operation: @@ -1132,8 +1134,9 @@ emulate_load_floatpair(unsigned long ifa, load_store_t *ld, struct pt_regs *regs * as long as we don't come here with a ldfpX.s. * For this reason we keep this sanity check */ - if ( ld->x6_op == 1 || ld->x6_op == 3 ) { - printk(KERN_ERR "%s: register update on speculative load pair, error\n", __FUNCTION__); + if (ld->x6_op == 1 || ld->x6_op == 3) { + printk(KERN_ERR "%s: register update on speculative load pair, error\n", + __FUNCTION__); } @@ -1143,7 +1146,7 @@ emulate_load_floatpair(unsigned long ifa, load_store_t *ld, struct pt_regs *regs /* * Invalidate ALAT entries, if any, for both registers. */ - if ( ld->x6_op == 0x2 ) { + if (ld->x6_op == 0x2) { invala_fr(ld->r1); invala_fr(ld->imm); } @@ -1160,10 +1163,10 @@ emulate_load_float(unsigned long ifa, load_store_t *ld, struct pt_regs *regs) /* * check for load pair because our masking scheme is not fine grain enough - if ( ld->x == 1 ) return emulate_load_floatpair(ifa,ld,regs); + if (ld->x == 1) return emulate_load_floatpair(ifa,ld,regs); */ - if ( access_ok(VERIFY_READ, (void *)ifa, len) < 0 ) { + if (access_ok(VERIFY_READ, (void *)ifa, len) < 0) { DPRINT(("verify area failed on %lx\n", ifa)); return -1; } @@ -1187,7 +1190,7 @@ emulate_load_float(unsigned long ifa, load_store_t *ld, struct pt_regs *regs) * invalidate the ALAT entry. * See comments in ldX for descriptions on how the various loads are handled. */ - if ( ld->x6_op != 0x2 ) { + if (ld->x6_op != 0x2) { /* * does the unaligned access @@ -1243,7 +1246,7 @@ emulate_load_float(unsigned long ifa, load_store_t *ld, struct pt_regs *regs) /* * check for updates on any loads */ - if ( ld->op == 0x7 || ld->m ) + if (ld->op == 0x7 || ld->m) emulate_load_updates(ld->op == 0x7 ? UPD_IMMEDIATE: UPD_REG, ld, regs, ifa); @@ -1274,7 +1277,7 @@ emulate_store_float(unsigned long ifa, load_store_t *ld, struct pt_regs *regs) * * Note: the first argument is ignored */ - if ( access_ok(VERIFY_WRITE, (void *)ifa, len) < 0 ) { + if (access_ok(VERIFY_WRITE, (void *)ifa, len) < 0) { DPRINT(("verify area failed on %lx\n",ifa)); return -1; } @@ -1342,7 +1345,7 @@ emulate_store_float(unsigned long ifa, load_store_t *ld, struct pt_regs *regs) * ld->r3 can never be r0, because r0 would not generate an * unaligned access. */ - if ( ld->op == 0x7 ) { + if (ld->op == 0x7) { unsigned long imm; /* @@ -1352,7 +1355,8 @@ emulate_store_float(unsigned long ifa, load_store_t *ld, struct pt_regs *regs) /* * sign extend (8bits) if m set */ - if ( ld->m ) imm |= SIGN_EXT9; + if (ld->m) + imm |= SIGN_EXT9; /* * ifa == r3 (NaT is necessarily cleared) */ @@ -1384,6 +1388,28 @@ ia64_handle_unaligned(unsigned long ifa, struct pt_regs *regs) load_store_t *insn; int ret = -1; + /* + * Unaligned references in the kernel could come from unaligned + * arguments to system calls. We fault the user process in + * these cases and panic the kernel otherwise (the kernel should + * be fixed to not make unaligned accesses). + */ + if (!user_mode(regs)) { + const struct exception_table_entry *fix; + + fix = search_exception_table(regs->cr_iip); + if (fix) { + regs->r8 = -EFAULT; + if (fix->skip & 1) { + regs->r9 = 0; + } + regs->cr_iip += ((long) fix->skip) & ~15; + regs->cr_ipsr &= ~IA64_PSR_RI; /* clear exception slot number */ + return; + } + die_if_kernel("Unaligned reference while in kernel\n", regs, 30); + /* NOT_REACHED */ + } if (current->thread.flags & IA64_THREAD_UAC_SIGBUS) { struct siginfo si; @@ -1539,7 +1565,7 @@ ia64_handle_unaligned(unsigned long ifa, struct pt_regs *regs) } DPRINT(("ret=%d\n", ret)); - if ( ret ) { + if (ret) { lock_kernel(); force_sig(SIGSEGV, current); unlock_kernel(); @@ -1549,7 +1575,8 @@ ia64_handle_unaligned(unsigned long ifa, struct pt_regs *regs) * because a memory access instruction (M) can never be in the * last slot of a bundle. But let's keep it for now. */ - if ( ipsr->ri == 2 ) regs->cr_iip += 16; + if (ipsr->ri == 2) + regs->cr_iip += 16; ipsr->ri = ++ipsr->ri & 3; } diff --git a/arch/ia64/lib/clear_user.S b/arch/ia64/lib/clear_user.S index 0db4a78f8..0b9a453b1 100644 --- a/arch/ia64/lib/clear_user.S +++ b/arch/ia64/lib/clear_user.S @@ -210,6 +210,7 @@ long_do_clear: // if p7 -> coming from st4 or st1 : len3 contains what's left // We must restore lc/pr even though might not have been used. .Lexit2: + .pred.rel "mutex", p6, p7 (p6) mov len=len2 (p7) mov len=len3 ;; diff --git a/arch/ia64/lib/strlen.S b/arch/ia64/lib/strlen.S index 3062716b1..22f205656 100644 --- a/arch/ia64/lib/strlen.S +++ b/arch/ia64/lib/strlen.S @@ -186,6 +186,7 @@ recover: ;; cmp.eq p6,p0=8,val1 // val1==8 ? (p6) br.wtop.dptk.few 2b // loop until p6 == 0 + ;; // (avoid WAW on p63) sub ret0=base,orig // distance from base sub tmp=8,val1 mov pr=saved_pr,0xffffffffffff0000 diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c index 99cf5048c..02c4c5792 100644 --- a/arch/ia64/mm/fault.c +++ b/arch/ia64/mm/fault.c @@ -94,7 +94,7 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re * sure we exit gracefully rather than endlessly redo the * fault. */ - if (!handle_mm_fault(current, vma, address, (isr & IA64_ISR_W) != 0)) { + if (!handle_mm_fault(mm, vma, address, (isr & IA64_ISR_W) != 0)) { /* * We ran out of memory, or some other thing happened * to us that made us unable to handle the page fault diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index 3a630ca8c..b3047ce34 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -237,6 +237,7 @@ put_gate_page (struct page *page, unsigned long address) if (!PageReserved(page)) printk("put_gate_page: gate page at 0x%lx not in reserved memory\n", page_address(page)); + pgd = pgd_offset_k(address); /* note: this is NOT pgd_offset()! */ pmd = pmd_alloc(pgd, address); if (!pmd) { diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c index 568f7a347..acad4e200 100644 --- a/arch/ia64/mm/tlb.c +++ b/arch/ia64/mm/tlb.c @@ -138,7 +138,7 @@ flush_tlb_range (struct mm_struct *mm, unsigned long start, unsigned long end) */ ++nbits; if (((1UL << nbits) & SUPPORTED_PGBITS) == 0) - panic("flush_tlb_range: BUG: nbits=%lu\n", nbits); + panic("flush_tlb_range: BUG: nbits=%lu\n", nbits); } start &= ~((1UL << nbits) - 1); diff --git a/arch/ia64/tools/Makefile b/arch/ia64/tools/Makefile index 0491ca943..974634e17 100644 --- a/arch/ia64/tools/Makefile +++ b/arch/ia64/tools/Makefile @@ -8,6 +8,8 @@ TARGET = $(TOPDIR)/include/asm-ia64/offsets.h all: +mrproper: + clean: rm -f print_offsets.s print_offsets offsets.h diff --git a/arch/ia64/tools/print_offsets.c b/arch/ia64/tools/print_offsets.c index f1b298e21..7e5901144 100644 --- a/arch/ia64/tools/print_offsets.c +++ b/arch/ia64/tools/print_offsets.c @@ -12,6 +12,8 @@ * file, be sure to verify that the awk procedure still works (see * prin_offsets.awk). */ +#include <linux/config.h> + #include <linux/sched.h> #include <asm-ia64/processor.h> @@ -50,6 +52,9 @@ tab[] = { "IA64_TASK_PROCESSOR_OFFSET", offsetof (struct task_struct, processor) }, { "IA64_TASK_THREAD_OFFSET", offsetof (struct task_struct, thread) }, { "IA64_TASK_THREAD_KSP_OFFSET", offsetof (struct task_struct, thread.ksp) }, +#ifdef CONFIG_IA32_SUPPORT + { "IA64_TASK_THREAD_SIGMASK_OFFSET",offsetof (struct task_struct, thread.un.sigmask) }, +#endif { "IA64_TASK_PID_OFFSET", offsetof (struct task_struct, pid) }, { "IA64_TASK_MM_OFFSET", offsetof (struct task_struct, mm) }, { "IA64_PT_REGS_CR_IPSR_OFFSET", offsetof (struct pt_regs, cr_ipsr) }, @@ -63,6 +68,8 @@ tab[] = { "IA64_SIGCONTEXT_FLAGS_OFFSET", offsetof (struct sigcontext, sc_flags) }, { "IA64_SIGCONTEXT_CFM_OFFSET", offsetof (struct sigcontext, sc_cfm) }, { "IA64_SIGCONTEXT_FR6_OFFSET", offsetof (struct sigcontext, sc_fr[6]) }, + { "IA64_CLONE_VFORK", CLONE_VFORK }, + { "IA64_CLONE_VM", CLONE_VM }, }; static const char *tabs = "\t\t\t\t\t\t\t\t\t\t"; diff --git a/arch/ia64/vmlinux.lds.S b/arch/ia64/vmlinux.lds.S index b095baeb9..08e7f9f9a 100644 --- a/arch/ia64/vmlinux.lds.S +++ b/arch/ia64/vmlinux.lds.S @@ -8,7 +8,7 @@ OUTPUT_ARCH(ia64) ENTRY(_start) SECTIONS { - v = PAGE_OFFSET; /* this symbol is here to make debugging with kdb easier... */ + v = PAGE_OFFSET; /* this symbol is here to make debugging easier... */ . = KERNEL_START; @@ -39,21 +39,6 @@ SECTIONS { *(__ex_table) } __stop___ex_table = .; -#if defined(CONFIG_KDB) - /* Kernel symbols and strings for kdb */ -# define KDB_MEAN_SYMBOL_SIZE 48 -# define KDB_SPACE (CONFIG_KDB_STBSIZE * KDB_MEAN_SYMBOL_SIZE) - . = ALIGN(8); - _skdb = .; - .kdb : AT(ADDR(.kdb) - PAGE_OFFSET) - { - *(kdbsymtab) - *(kdbstrings) - } - _ekdb = .; - . = _skdb + KDB_SPACE; -#endif - /* Kernel symbol names for modules: */ .kstrtab : AT(ADDR(.kstrtab) - PAGE_OFFSET) { *(.kstrtab) } diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c index c88c4c167..3eba3d13b 100644 --- a/arch/m68k/mm/fault.c +++ b/arch/m68k/mm/fault.c @@ -99,7 +99,7 @@ good_area: * make sure we exit gracefully rather than endlessly redo * the fault. */ - fault = handle_mm_fault(current, vma, address, write); + fault = handle_mm_fault(mm, vma, address, write); if (fault < 0) goto out_of_memory; if (!fault) diff --git a/arch/mips/baget/vacserial.c b/arch/mips/baget/vacserial.c index 5090bada6..048e32ed5 100644 --- a/arch/mips/baget/vacserial.c +++ b/arch/mips/baget/vacserial.c @@ -2168,7 +2168,7 @@ int rs_read_proc(char *page, char **start, off_t off, int count, done: if (off >= len+begin) return 0; - *start = page + (begin-off); + *start = page + (off-begin); return ((count < begin+len-off) ? count : begin+len-off); } diff --git a/arch/mips/defconfig b/arch/mips/defconfig index d4570eb4e..ceeaf5015 100644 --- a/arch/mips/defconfig +++ b/arch/mips/defconfig @@ -78,6 +78,7 @@ CONFIG_KMOD=y # # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_LVM is not set # CONFIG_BLK_DEV_MD is not set # CONFIG_MD_LINEAR is not set # CONFIG_MD_STRIPED is not set diff --git a/arch/mips/defconfig-ip22 b/arch/mips/defconfig-ip22 index d4570eb4e..ceeaf5015 100644 --- a/arch/mips/defconfig-ip22 +++ b/arch/mips/defconfig-ip22 @@ -78,6 +78,7 @@ CONFIG_KMOD=y # # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_LVM is not set # CONFIG_BLK_DEV_MD is not set # CONFIG_MD_LINEAR is not set # CONFIG_MD_STRIPED is not set diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c index 78b41c448..ddf234045 100644 --- a/arch/mips/kernel/irixelf.c +++ b/arch/mips/kernel/irixelf.c @@ -717,16 +717,8 @@ static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs) set_fs(old_fs); kfree(elf_phdata); - current->personality = PER_IRIX32; - - put_exec_domain(current->exec_domain); - if (current->binfmt && current->binfmt->module) - __MOD_DEC_USE_COUNT(current->binfmt->module); - current->exec_domain = lookup_exec_domain(current->personality); - current->binfmt = &irix_format; - if (current->binfmt && current->binfmt->module) - __MOD_INC_USE_COUNT(current->binfmt->module); - + set_personality(PER_IRIX32); + set_binfmt(&irix_format); compute_creds(bprm); current->flags &= ~PF_FORKNOEXEC; bprm->p = (unsigned long) diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c index 742cc9b9d..db0229802 100644 --- a/arch/mips/kernel/sysirix.c +++ b/arch/mips/kernel/sysirix.c @@ -533,7 +533,7 @@ asmlinkage int irix_brk(unsigned long brk) int ret; lock_kernel(); - if (brk < current->mm->end_code) { + if (brk < mm->end_code) { ret = -ENOMEM; goto out; } @@ -549,9 +549,9 @@ asmlinkage int irix_brk(unsigned long brk) /* * Always allow shrinking brk */ - if (brk <= current->mm->brk) { + if (brk <= mm->brk) { mm->brk = brk; - do_munmap(newbrk, oldbrk-newbrk); + do_munmap(mm, newbrk, oldbrk-newbrk); ret = 0; goto out; } diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c index 263f2c919..e8c32219d 100644 --- a/arch/mips/mm/fault.c +++ b/arch/mips/mm/fault.c @@ -91,7 +91,7 @@ good_area: * the fault. */ { - int fault = handle_mm_fault(tsk, vma, address, write); + int fault = handle_mm_fault(mm, vma, address, write); if (fault < 0) goto out_of_memory; if (!fault) diff --git a/arch/mips64/defconfig b/arch/mips64/defconfig index 410152c15..0b72d42c1 100644 --- a/arch/mips64/defconfig +++ b/arch/mips64/defconfig @@ -72,6 +72,7 @@ CONFIG_PCI_NAMES=y # # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_LVM is not set # CONFIG_BLK_DEV_MD is not set # CONFIG_MD_LINEAR is not set # CONFIG_MD_STRIPED is not set diff --git a/arch/mips64/defconfig-ip27 b/arch/mips64/defconfig-ip27 index 410152c15..0b72d42c1 100644 --- a/arch/mips64/defconfig-ip27 +++ b/arch/mips64/defconfig-ip27 @@ -72,6 +72,7 @@ CONFIG_PCI_NAMES=y # # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_LVM is not set # CONFIG_BLK_DEV_MD is not set # CONFIG_MD_LINEAR is not set # CONFIG_MD_STRIPED is not set diff --git a/arch/mips64/mm/fault.c b/arch/mips64/mm/fault.c index fc69ab2c6..cb9a0e566 100644 --- a/arch/mips64/mm/fault.c +++ b/arch/mips64/mm/fault.c @@ -99,7 +99,7 @@ good_area: * the fault. */ { - int fault = handle_mm_fault(tsk, vma, address, write); + int fault = handle_mm_fault(mm, vma, address, write); if (fault < 0) goto out_of_memory; if (!fault) diff --git a/arch/ppc/8xx_io/uart.c b/arch/ppc/8xx_io/uart.c index 575f68a28..f5088b9e4 100644 --- a/arch/ppc/8xx_io/uart.c +++ b/arch/ppc/8xx_io/uart.c @@ -2063,7 +2063,7 @@ int rs_8xx_read_proc(char *page, char **start, off_t off, int count, done: if (off >= len+begin) return 0; - *start = page + (begin-off); + *start = page + (off-begin); return ((count < begin+len-off) ? count : begin+len-off); } diff --git a/arch/ppc/defconfig b/arch/ppc/defconfig index 8717bc055..229768b9b 100644 --- a/arch/ppc/defconfig +++ b/arch/ppc/defconfig @@ -184,8 +184,8 @@ CONFIG_BLK_DEV_IDEPCI=y CONFIG_IDEDMA_PCI_EXPERIMENTAL=y # CONFIG_IDEDMA_PCI_WIP is not set # CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set -# CONFIG_BLK_DEV_AEC6210 is not set -# CONFIG_AEC6210_TUNING is not set +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_AEC62XX_TUNING is not set # CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_WDC_ALI15X3 is not set # CONFIG_BLK_DEV_AMD7409 is not set diff --git a/arch/ppc/kernel/apus_setup.c b/arch/ppc/kernel/apus_setup.c index a54efc6fd..b93bd8193 100644 --- a/arch/ppc/kernel/apus_setup.c +++ b/arch/ppc/kernel/apus_setup.c @@ -108,18 +108,6 @@ void (*mach_floppy_eject) (void) __apusdata = NULL; #ifdef CONFIG_HEARTBEAT void (*mach_heartbeat) (int) __apusdata = NULL; extern void apus_heartbeat (void); -static int heartbeat_enabled = 1; - -void enable_heartbeat(void) -{ - heartbeat_enabled = 1; -} - -void disable_heartbeat(void) -{ - heartbeat_enabled = 0; - mach_heartbeat(0); -} #endif extern unsigned long amiga_model; diff --git a/arch/ppc/kernel/chrp_setup.c b/arch/ppc/kernel/chrp_setup.c index 21abfc84f..3b541c26f 100644 --- a/arch/ppc/kernel/chrp_setup.c +++ b/arch/ppc/kernel/chrp_setup.c @@ -422,10 +422,10 @@ void __init chrp_init_IRQ(void) request_irq(openpic_to_irq(HYDRA_INT_ADB_NMI), xmon_irq, 0, "NMI", 0); #endif /* CONFIG_XMON */ -#ifdef __SMP__ +#ifdef CONFIG_SMP request_irq(openpic_to_irq(OPENPIC_VEC_IPI), openpic_ipi_action, 0, "IPI0", 0); -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ } void __init diff --git a/arch/ppc/kernel/gemini_prom.S b/arch/ppc/kernel/gemini_prom.S index f91e992f4..0904bb0eb 100644 --- a/arch/ppc/kernel/gemini_prom.S +++ b/arch/ppc/kernel/gemini_prom.S @@ -10,6 +10,7 @@ #include "ppc_asm.tmpl" #include "ppc_defs.h" +#include <linux/config.h> #include <asm/processor.h> #include <asm/page.h> #include <asm/gemini.h> @@ -25,7 +26,7 @@ _GLOBAL(prom_init) _GLOBAL(gemini_prom_init) -#ifdef __SMP__ +#ifdef CONFIG_SMP /* Since the MMU's on, get stuff in rom space that we'll need */ lis r4,GEMINI_CPUSTAT@h ori r4,r4,GEMINI_CPUSTAT@l @@ -74,14 +75,14 @@ prom_no_mmu: addi r3,r3,1 bdnz 3b -#ifdef __SMP__ +#ifdef CONFIG_SMP /* The 750 book (and Mot/IBM support) says that this will "assist" snooping when in SMP. Not sure yet whether this should stay or leave... */ mfspr r4,HID0 ori r4,r4,HID0_ABE mtspr HID0,r4 sync -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ blr /* apparently, SMon doesn't pay attention to HID0[SRST]. Disable the MMU and diff --git a/arch/ppc/kernel/gemini_setup.c b/arch/ppc/kernel/gemini_setup.c index fcf3a701c..ae9a0bd5c 100644 --- a/arch/ppc/kernel/gemini_setup.c +++ b/arch/ppc/kernel/gemini_setup.c @@ -303,7 +303,7 @@ printk("3\n"); /* standard stuff */ cache |= ((1<<reg)<<25); -#ifdef __SMP__ +#ifdef CONFIG_SMP /* A couple errata for the 750's (both IBM and Motorola silicon) note that you can get missed cache lines on MP implementations. The workaround - if you call it that - is to make the L2 @@ -351,7 +351,7 @@ void __init gemini_init_IRQ(void) for( i=0; i < NR_IRQS; i++ ) irq_desc[i].handler = &open_pic; openpic_init(1); -#ifdef __SMP__ +#ifdef CONFIG_SMP request_irq(OPENPIC_VEC_IPI, openpic_ipi_action, 0, "IPI0", 0); request_irq(OPENPIC_VEC_IPI+1, openpic_ipi_action, @@ -360,7 +360,7 @@ void __init gemini_init_IRQ(void) 0, "IPI2 (stop CPU)", 0); request_irq(OPENPIC_VEC_IPI+3, openpic_ipi_action, 0, "IPI3 (reschedule)", 0); -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ } #define gemini_rtc_read(x) (readb(GEMINI_RTC+(x))) diff --git a/arch/ppc/kernel/hashtable.S b/arch/ppc/kernel/hashtable.S index 5593ebe18..58045be1d 100644 --- a/arch/ppc/kernel/hashtable.S +++ b/arch/ppc/kernel/hashtable.S @@ -52,7 +52,7 @@ Hash_msk = (((1 << Hash_bits) - 1) * 64) .globl hash_page hash_page: -#ifdef __SMP__ +#ifdef CONFIG_SMP SAVE_2GPRS(7,r21) eieio lis r2,hash_table_lock@h @@ -88,7 +88,7 @@ hash_page: rlwimi r5,r3,12,20,29 /* insert top 10 bits of address */ lwz r5,0(r5) /* get pmd entry */ rlwinm. r5,r5,0,0,19 /* extract address of pte page */ -#ifdef __SMP__ +#ifdef CONFIG_SMP beq- hash_page_out /* return if no mapping */ #else /* XXX it seems like the 601 will give a machine fault on the @@ -102,7 +102,7 @@ hash_page: lwz r6,0(r2) /* get linux-style pte */ ori r4,r4,1 /* set _PAGE_PRESENT bit in access */ andc. r0,r4,r6 /* check access & ~permission */ -#ifdef __SMP__ +#ifdef CONFIG_SMP bne- hash_page_out /* return if access not permitted */ #else bnelr- @@ -128,7 +128,7 @@ hash_page: rlwinm r5,r5,7,1,24 /* put VSID in 0x7fffff80 bits */ #endif /* CONFIG_PPC64 */ -#ifndef __SMP__ /* do this later for SMP */ +#ifndef CONFIG_SMP /* do this later for SMP */ #ifdef CONFIG_PPC64 ori r5,r5,1 /* set V (valid) bit */ #else /* CONFIG_PPC64 */ @@ -280,7 +280,7 @@ hash_page_patch_C: addi r4,r4,1 stw r4,htab_evicts@l(r2) -#ifndef __SMP__ +#ifndef CONFIG_SMP /* Store PTE in PTEG */ found_empty: #ifdef CONFIG_PPC64 @@ -296,7 +296,7 @@ found_slot: #endif sync -#else /* __SMP__ */ +#else /* CONFIG_SMP */ /* * Between the tlbie above and updating the hash table entry below, * another CPU could read the hash table entry and put it in its TLB. @@ -324,7 +324,7 @@ found_slot: sync oris r5,r5,0x8000 stw r5,0(r3) /* finally set V bit in PTE */ -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ /* * Update the hash table miss count. We only want misses here @@ -342,7 +342,7 @@ found_slot: addi r3,r3,1 stw r3,htab_reloads@l(r2) -#ifdef __SMP__ +#ifdef CONFIG_SMP lis r2,hash_table_lock@ha tophys(r2,r2) li r0,0 @@ -373,7 +373,7 @@ found_slot: lwz r21,GPR21(r21) rfi -#ifdef __SMP__ +#ifdef CONFIG_SMP hash_page_out: lis r2,hash_table_lock@ha tophys(r2,r2) @@ -386,7 +386,7 @@ hash_page_out: .globl hash_table_lock hash_table_lock: .long 0 -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ .data next_slot: @@ -404,13 +404,13 @@ _GLOBAL(flush_hash_segments) bne+ 99f tlbia sync -#ifdef __SMP__ +#ifdef CONFIG_SMP tlbsync sync #endif blr 99: -#ifdef __SMP__ +#ifdef CONFIG_SMP /* Note - we had better not do anything which could generate a hash table miss while we have the hash table locked, or we'll get a deadlock. -paulus */ @@ -451,7 +451,7 @@ _GLOBAL(flush_hash_segments) sync tlbia sync -#ifdef __SMP__ +#ifdef CONFIG_SMP tlbsync sync lis r3,hash_table_lock@ha @@ -473,13 +473,13 @@ _GLOBAL(flush_hash_page) bne+ 99f tlbie r4 /* in hw tlb too */ sync -#ifdef __SMP__ +#ifdef CONFIG_SMP tlbsync sync #endif blr 99: -#ifdef __SMP__ +#ifdef CONFIG_SMP /* Note - we had better not do anything which could generate a hash table miss while we have the hash table locked, or we'll get a deadlock. -paulus */ @@ -531,7 +531,7 @@ _GLOBAL(flush_hash_page) 4: sync tlbie r4 /* in hw tlb too */ sync -#ifdef __SMP__ +#ifdef CONFIG_SMP tlbsync sync li r0,0 diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S index dab413c15..218bb4ebb 100644 --- a/arch/ppc/kernel/head.S +++ b/arch/ppc/kernel/head.S @@ -189,11 +189,11 @@ __after_prom_start: #endif /* CONFIG_PPC64 */ 4: tophys(r8,r11) -#ifdef __SMP__ +#ifdef CONFIG_SMP ori r8,r8,0x12 /* R/W access, M=1 */ #else ori r8,r8,2 /* R/W access */ -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ #ifdef CONFIG_APUS ori r11,r11,BL_8M<<2|0x2 /* set up 8MB BAT registers for 604 */ #else @@ -782,7 +782,7 @@ load_up_fpu: * horrendously complex, especially when a task switches from one CPU * to another. Instead we call giveup_fpu in switch_to. */ -#ifndef __SMP__ +#ifndef CONFIG_SMP lis r6,0 /* get __pa constant */ tophys(r6,r6) addis r3,r6,last_task_used_math@ha @@ -801,18 +801,18 @@ load_up_fpu: andc r4,r4,r20 /* disable FP for previous task */ stw r4,_MSR-STACK_FRAME_OVERHEAD(r5) 1: -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ /* enable use of FP after return */ ori r23,r23,MSR_FP|MSR_FE0|MSR_FE1 mfspr r5,SPRG3 /* current task's THREAD (phys) */ lfd fr0,THREAD_FPSCR-4(r5) mtfsf 0xff,fr0 REST_32FPRS(0, r5) -#ifndef __SMP__ +#ifndef CONFIG_SMP subi r4,r5,THREAD sub r4,r4,r6 stw r4,last_task_used_math@l(r3) -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ /* restore registers and return */ lwz r3,_CCR(r21) lwz r4,_LINK(r21) @@ -868,7 +868,7 @@ load_up_altivec: * horrendously complex, especially when a task switches from one CPU * to another. Instead we call giveup_altivec in switch_to. */ -#ifndef __SMP__ +#ifndef CONFIG_SMP #ifndef CONFIG_APUS lis r6,-KERNELBASE@h #else @@ -892,7 +892,7 @@ load_up_altivec: andc r4,r4,r20 /* disable altivec for previous task */ stw r4,_MSR-STACK_FRAME_OVERHEAD(r5) 1: -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ /* enable use of AltiVec after return */ oris r23,r23,MSR_VEC@h mfspr r5,SPRG3 /* current task's THREAD (phys) */ @@ -900,11 +900,11 @@ load_up_altivec: LVX(vr0,r20,r5) MTVSCR(vr0) REST_32VR(0,r20,r5) -#ifndef __SMP__ +#ifndef CONFIG_SMP subi r4,r5,THREAD sub r4,r4,r6 stw r4,last_task_used_altivec@l(r3) -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ /* restore registers and return */ lwz r3,_CCR(r21) lwz r4,_LINK(r21) @@ -967,11 +967,11 @@ giveup_altivec: andc r4,r4,r3 /* disable AltiVec for previous task */ stw r4,_MSR-STACK_FRAME_OVERHEAD(r5) 1: -#ifndef __SMP__ +#ifndef CONFIG_SMP li r5,0 lis r4,last_task_used_altivec@ha stw r5,last_task_used_altivec@l(r4) -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ blr #endif /* CONFIG_ALTIVEC */ @@ -1002,11 +1002,11 @@ giveup_fpu: andc r4,r4,r3 /* disable FP for previous task */ stw r4,_MSR-STACK_FRAME_OVERHEAD(r5) 1: -#ifndef __SMP__ +#ifndef CONFIG_SMP li r5,0 lis r4,last_task_used_math@ha stw r5,last_task_used_math@l(r4) -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ blr /* @@ -1432,7 +1432,7 @@ start_here: SYNC /* Force all PTE updates to finish */ tlbia /* Clear all TLB entries */ sync /* wait for tlbia/tlbie to finish */ -#ifdef __SMP__ +#ifdef CONFIG_SMP tlbsync /* ... on all CPUs */ sync #endif diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S index 94cd67d3b..83f276585 100644 --- a/arch/ppc/kernel/head_8xx.S +++ b/arch/ppc/kernel/head_8xx.S @@ -698,7 +698,7 @@ __secondary_hold: * This is where the main kernel code starts. */ start_here: -#ifdef __SMP__ +#ifdef CONFIG_SMP /* if we're the second cpu stack and r2 are different * and we want to not clear the bss -- Cort */ lis r5,first_cpu_booted@h @@ -715,7 +715,7 @@ start_here: lwz r2,0(r2) b 10f 99: -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ /* ptr to current */ lis r2,init_task_union@h ori r2,r2,init_task_union@l @@ -734,9 +734,9 @@ start_here: 3: stwu r0,4(r8) bdnz 3b 2: -#ifdef __SMP__ +#ifdef CONFIG_SMP 10: -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ /* stack */ addi r1,r2,TASK_UNION_SIZE li r0,0 @@ -779,7 +779,7 @@ start_here: SYNC /* Force all PTE updates to finish */ tlbia /* Clear all TLB entries */ sync /* wait for tlbia/tlbie to finish */ -#ifdef __SMP__ +#ifdef CONFIG_SMP tlbsync /* ... on all CPUs */ sync #endif @@ -794,7 +794,7 @@ start_here: li r4,MSR_KERNEL lis r3,start_kernel@h ori r3,r3,start_kernel@l -#ifdef __SMP__ +#ifdef CONFIG_SMP /* the second time through here we go to * start_secondary(). -- Cort */ @@ -807,7 +807,7 @@ start_here: lis r3,start_secondary@h ori r3,r3,start_secondary@l 10: -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ mtspr SRR0,r3 mtspr SRR1,r4 rfi /* enable MMU and jump to start_kernel */ diff --git a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c index 7cf97b873..1d3dfd299 100644 --- a/arch/ppc/kernel/idle.c +++ b/arch/ppc/kernel/idle.c @@ -61,7 +61,7 @@ int idled(void) if ( !current->need_resched && htab_reclaim_on ) htab_reclaim(); if ( !current->need_resched ) power_save(); -#ifdef __SMP__ +#ifdef CONFIG_SMP if (current->need_resched) #endif schedule(); @@ -162,11 +162,11 @@ unsigned long get_zero_page_fast(void) : "=&r" (tmp), "=&r" (page), "+m" (zero_cache) : "r" (&zero_quicklist) : "cc" ); -#ifdef __SMP__ +#ifdef CONFIG_SMP /* if another cpu beat us above this can happen -- Cort */ if ( page == 0 ) return 0; -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ /* we can update zerocount after the fact since it is not * used for anything but control of a loop which doesn't * matter since it won't affect anything if it zeros one @@ -253,7 +253,7 @@ void zero_paged(void) /* atomically add this page to the list */ asm ( "101:lwarx %0,0,%2\n" /* reserve zero_cache */ " stw %0,0(%3)\n" /* update *pageptr */ -#ifdef __SMP__ +#ifdef CONFIG_SMP " sync\n" /* let store settle */ #endif " stwcx. %3,0,%2\n" /* update zero_cache in mem */ diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c index e4b279032..c0cc492ad 100644 --- a/arch/ppc/kernel/irq.c +++ b/arch/ppc/kernel/irq.c @@ -237,13 +237,13 @@ int get_irq_list(char *buf) if ( !action || !action->handler ) continue; len += sprintf(buf+len, "%3d: ", i); -#ifdef __SMP__ +#ifdef CONFIG_SMP for (j = 0; j < smp_num_cpus; j++) len += sprintf(buf+len, "%10u ", kstat.irqs[cpu_logical_map(j)][i]); #else len += sprintf(buf+len, "%10u ", kstat_irqs(i)); -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ if ( irq_desc[i].handler ) len += sprintf(buf+len, " %s ", irq_desc[i].handler->typename ); else @@ -254,7 +254,7 @@ int get_irq_list(char *buf) } len += sprintf(buf+len, "\n"); } -#ifdef __SMP__ +#ifdef CONFIG_SMP /* should this be per processor send/receive? */ len += sprintf(buf+len, "IPI: %10lu\n", ipi_count); #endif @@ -343,7 +343,7 @@ void __init init_IRQ(void) ppc_md.init_IRQ(); } -#ifdef __SMP__ +#ifdef CONFIG_SMP unsigned char global_irq_holder = NO_PROC_ID; unsigned volatile int global_irq_lock; atomic_t global_irq_count; @@ -611,7 +611,7 @@ void __global_restore_flags(unsigned long flags) } } } -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ static struct proc_dir_entry * root_irq_dir; static struct proc_dir_entry * irq_dir [NR_IRQS]; @@ -733,7 +733,7 @@ static void register_irq_proc (unsigned int irq) irq_dir[irq] = proc_mkdir(name, root_irq_dir); /* create /proc/irq/1234/smp_affinity */ - entry = create_proc_entry("smp_affinity", 0700, irq_dir[irq]); + entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]); entry->nlink = 1; entry->data = (void *)irq; @@ -754,7 +754,7 @@ void init_irq_proc (void) root_irq_dir = proc_mkdir("irq", 0); /* create /proc/irq/prof_cpu_mask */ - entry = create_proc_entry("prof_cpu_mask", 0700, root_irq_dir); + entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir); entry->nlink = 1; entry->data = (void *)&prof_cpu_mask; diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index 8444bb4a0..e4fbefbc3 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S @@ -142,7 +142,7 @@ _GLOBAL(_tlbia) sync tlbia sync -#ifdef __SMP__ +#ifdef CONFIG_SMP tlbsync sync #endif @@ -154,7 +154,7 @@ _GLOBAL(_tlbia) _GLOBAL(_tlbie) tlbie r3 sync -#ifdef __SMP__ +#ifdef CONFIG_SMP tlbsync sync #endif diff --git a/arch/ppc/kernel/open_pic.c b/arch/ppc/kernel/open_pic.c index 9438c57ee..a3c6cc4dd 100644 --- a/arch/ppc/kernel/open_pic.c +++ b/arch/ppc/kernel/open_pic.c @@ -101,12 +101,12 @@ void no_action(int ir1, void *dev, struct pt_regs *regs) { } -#ifdef __SMP__ +#ifdef CONFIG_SMP void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs) { smp_message_recv(cpl-OPENPIC_VEC_IPI); } -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ #ifdef __i386__ static inline u_int in_le32(volatile u_int *addr) diff --git a/arch/ppc/kernel/pmac_pic.c b/arch/ppc/kernel/pmac_pic.c index f2794ae5a..b58d69fc9 100644 --- a/arch/ppc/kernel/pmac_pic.c +++ b/arch/ppc/kernel/pmac_pic.c @@ -183,7 +183,7 @@ pmac_get_irq(struct pt_regs *regs) int irq; unsigned long bits = 0; -#ifdef __SMP__ +#ifdef CONFIG_SMP void pmac_smp_message_recv(void); /* IPI's are a hack on the powersurge -- Cort */ @@ -197,7 +197,7 @@ pmac_get_irq(struct pt_regs *regs) pmac_smp_message_recv(); return -2; /* ignore, already handled */ } -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ /* Yeah, I know, this could be a separate get_irq function */ if (has_openpic) diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index 87c8d4082..7d4c038ec 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c @@ -35,9 +35,9 @@ #include <asm/dma.h> #include <asm/machdep.h> #include <asm/hw_irq.h> -#ifdef __SMP__ +#ifdef CONFIG_SMP #include <asm/smplock.h> -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ #include "time.h" /* Tell string.h we don't want memcpy etc. as cpp defines */ @@ -76,9 +76,9 @@ EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL(disable_irq_nosync); EXPORT_SYMBOL(local_irq_count); EXPORT_SYMBOL(local_bh_count); -#ifdef __SMP__ +#ifdef CONFIG_SMP EXPORT_SYMBOL(kernel_flag); -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ #if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) EXPORT_SYMBOL(isa_io_base); @@ -189,7 +189,7 @@ EXPORT_SYMBOL(giveup_fpu); EXPORT_SYMBOL(enable_kernel_fp); EXPORT_SYMBOL(flush_icache_range); EXPORT_SYMBOL(xchg_u32); -#ifdef __SMP__ +#ifdef CONFIG_SMP EXPORT_SYMBOL(__global_cli); EXPORT_SYMBOL(__global_sti); EXPORT_SYMBOL(__global_save_flags); diff --git a/arch/ppc/kernel/prep_setup.c b/arch/ppc/kernel/prep_setup.c index 19ae61450..cb1110eca 100644 --- a/arch/ppc/kernel/prep_setup.c +++ b/arch/ppc/kernel/prep_setup.c @@ -118,7 +118,7 @@ prep_get_cpuinfo(char *buffer) extern char *Motherboard_map_name; int len, i; -#ifdef __SMP__ +#ifdef CONFIG_SMP #define CD(X) (cpu_data[n].X) #else #define CD(X) (X) @@ -624,10 +624,10 @@ prep_init_IRQ(void) for ( i = 0 ; i < 16 ; i++ ) irq_desc[i].handler = &i8259_pic; i8259_init(); -#ifdef __SMP__ +#ifdef CONFIG_SMP request_irq(openpic_to_irq(OPENPIC_VEC_SPURIOUS), openpic_ipi_action, 0, "IPI0", 0); -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ } #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c index 5c01d3c72..ce8e039c0 100644 --- a/arch/ppc/kernel/process.c +++ b/arch/ppc/kernel/process.c @@ -154,7 +154,7 @@ dump_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs) void enable_kernel_altivec(void) { -#ifdef __SMP__ +#ifdef CONFIG_SMP if (current->thread.regs && (current->thread.regs->msr & MSR_VEC)) giveup_altivec(current); else @@ -169,14 +169,14 @@ enable_kernel_altivec(void) void enable_kernel_fp(void) { -#ifdef __SMP__ +#ifdef CONFIG_SMP if (current->thread.regs && (current->thread.regs->msr & MSR_FP)) giveup_fpu(current); else giveup_fpu(NULL); /* just enables FP for kernel */ #else giveup_fpu(last_task_used_math); -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ } int @@ -208,7 +208,7 @@ _switch_to(struct task_struct *prev, struct task_struct *new, new->comm,new->pid,new->thread.regs->nip,new->processor, new->fs->root,prev->fs->root); #endif -#ifdef __SMP__ +#ifdef CONFIG_SMP /* avoid complexity of lazy save/restore of fpu * by just saving it every time we switch out if * this task used the fpu during the last quantum. @@ -236,7 +236,7 @@ _switch_to(struct task_struct *prev, struct task_struct *new, #endif /* CONFIG_ALTIVEC */ prev->last_processor = prev->processor; current_set[smp_processor_id()] = new; -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ /* Avoid the trap. On smp this this never happens since * we don't set last_task_used_altivec -- Cort */ @@ -265,9 +265,9 @@ void show_regs(struct pt_regs * regs) printk("\nlast math %p last altivec %p", last_task_used_math, last_task_used_altivec); -#ifdef __SMP__ +#ifdef CONFIG_SMP printk(" CPU: %d last CPU: %d", current->processor,current->last_processor); -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ printk("\n"); for (i = 0; i < 32; i++) @@ -319,7 +319,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, { unsigned long msr; struct pt_regs * childregs, *kregs; -#ifdef __SMP__ +#ifdef CONFIG_SMP extern void ret_from_smpfork(void); #else extern void ret_from_except(void); @@ -336,7 +336,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, p->thread.ksp = (unsigned long) childregs - STACK_FRAME_OVERHEAD; p->thread.ksp -= sizeof(struct pt_regs ) + STACK_FRAME_OVERHEAD; kregs = (struct pt_regs *)(p->thread.ksp + STACK_FRAME_OVERHEAD); -#ifdef __SMP__ +#ifdef CONFIG_SMP kregs->nip = (unsigned long)ret_from_smpfork; #else kregs->nip = (unsigned long)ret_from_except; @@ -378,9 +378,9 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, childregs->msr &= ~MSR_VEC; #endif /* CONFIG_ALTIVEC */ -#ifdef __SMP__ +#ifdef CONFIG_SMP p->last_processor = NO_PROC_ID; -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ return 0; } @@ -447,14 +447,14 @@ asmlinkage int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6, int res; lock_kernel(); res = do_fork(clone_flags, regs->gpr[1], regs); -#ifdef __SMP__ +#ifdef CONFIG_SMP /* When we clone the idle task we keep the same pid but * the return value of 0 for both causes problems. * -- Cort */ if ((current->pid == 0) && (current == &init_task)) res = 1; -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ unlock_kernel(); return res; } @@ -466,14 +466,14 @@ asmlinkage int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6, int res; res = do_fork(SIGCHLD, regs->gpr[1], regs); -#ifdef __SMP__ +#ifdef CONFIG_SMP /* When we clone the idle task we keep the same pid but * the return value of 0 for both causes problems. * -- Cort */ if ((current->pid == 0) && (current == &init_task)) res = 1; -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ return res; } diff --git a/arch/ppc/kernel/ptrace.c b/arch/ppc/kernel/ptrace.c index 3a4e3b797..fe0bfcea2 100644 --- a/arch/ppc/kernel/ptrace.c +++ b/arch/ppc/kernel/ptrace.c @@ -100,7 +100,7 @@ static unsigned long get_long(struct task_struct * tsk, repeat: pgdir = pgd_offset(vma->vm_mm, addr); if (pgd_none(*pgdir)) { - handle_mm_fault(tsk, vma, addr, 0); + handle_mm_fault(tsk->mm, vma, addr, 0); goto repeat; } if (pgd_bad(*pgdir)) { @@ -110,7 +110,7 @@ repeat: } pgmiddle = pmd_offset(pgdir,addr); if (pmd_none(*pgmiddle)) { - handle_mm_fault(tsk, vma, addr, 0); + handle_mm_fault(tsk->mm, vma, addr, 0); goto repeat; } if (pmd_bad(*pgmiddle)) { @@ -120,7 +120,7 @@ repeat: } pgtable = pte_offset(pgmiddle, addr); if (!pte_present(*pgtable)) { - handle_mm_fault(tsk, vma, addr, 0); + handle_mm_fault(tsk->mm, vma, addr, 0); goto repeat; } page = pte_page(*pgtable); @@ -151,7 +151,7 @@ static void put_long(struct task_struct * tsk, struct vm_area_struct * vma, repeat: pgdir = pgd_offset(vma->vm_mm, addr); if (!pgd_present(*pgdir)) { - handle_mm_fault(tsk, vma, addr, 1); + handle_mm_fault(tsk->mm, vma, addr, 1); goto repeat; } if (pgd_bad(*pgdir)) { @@ -161,7 +161,7 @@ repeat: } pgmiddle = pmd_offset(pgdir,addr); if (pmd_none(*pgmiddle)) { - handle_mm_fault(tsk, vma, addr, 1); + handle_mm_fault(tsk->mm, vma, addr, 1); goto repeat; } if (pmd_bad(*pgmiddle)) { @@ -171,12 +171,12 @@ repeat: } pgtable = pte_offset(pgmiddle, addr); if (!pte_present(*pgtable)) { - handle_mm_fault(tsk, vma, addr, 1); + handle_mm_fault(tsk->mm, vma, addr, 1); goto repeat; } page = pte_page(*pgtable); if (!pte_write(*pgtable)) { - handle_mm_fault(tsk, vma, addr, 1); + handle_mm_fault(tsk->mm, vma, addr, 1); goto repeat; } /* this is a hack for non-kernel-mapped video buffers and similar */ @@ -198,7 +198,7 @@ repeat: static int read_long(struct task_struct * tsk, unsigned long addr, unsigned long * result) { - struct vm_area_struct * vma = find_extend_vma(tsk, addr); + struct vm_area_struct * vma = find_extend_vma(tsk->mm, addr); if (!vma) return -EIO; @@ -240,7 +240,7 @@ static int read_long(struct task_struct * tsk, unsigned long addr, static int write_long(struct task_struct * tsk, unsigned long addr, unsigned long data) { - struct vm_area_struct * vma = find_extend_vma(tsk, addr); + struct vm_area_struct * vma = find_extend_vma(tsk->mm, addr); if (!vma) return -EIO; diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c index 30595e694..2b771ef14 100644 --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c @@ -204,7 +204,7 @@ int get_cpuinfo(char *buffer) unsigned int pvr; unsigned short maj, min; -#ifdef __SMP__ +#ifdef CONFIG_SMP #define CPU_PRESENT(x) (cpu_callin_map[(x)]) #define GET_PVR ((long int)(cpu_data[i].pvr)) #define CD(x) (cpu_data[i].x) @@ -355,13 +355,13 @@ int get_cpuinfo(char *buffer) bogosum += CD(loops_per_sec); } -#ifdef __SMP__ +#ifdef CONFIG_SMP if ( i ) len += sprintf(buffer+len, "\n"); len += sprintf(buffer+len,"total bogomips\t: %lu.%02lu\n", (bogosum+2500)/500000, (bogosum+2500)/5000 % 100); -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ /* * Ooh's and aah's info about zero'd pages in idle task diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c index b695da797..b821249d9 100644 --- a/arch/ppc/kernel/time.c +++ b/arch/ppc/kernel/time.c @@ -74,7 +74,7 @@ int timer_interrupt(struct pt_regs * regs) unsigned long cpu = smp_processor_id(); hardirq_enter(cpu); -#ifdef __SMP__ +#ifdef CONFIG_SMP { unsigned int loops = 100000000; while (test_bit(0, &global_irq_lock)) { @@ -93,7 +93,7 @@ int timer_interrupt(struct pt_regs * regs) } } } -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ dval = get_dec(); /* @@ -133,7 +133,7 @@ int timer_interrupt(struct pt_regs * regs) last_rtc_update = xtime.tv_sec; } } -#ifdef __SMP__ +#ifdef CONFIG_SMP smp_local_timer_interrupt(regs); #endif @@ -155,7 +155,7 @@ void do_gettimeofday(struct timeval *tv) cli(); *tv = xtime; /* XXX we don't seem to have the decrementers synced properly yet */ -#ifndef __SMP__ +#ifndef CONFIG_SMP tv->tv_usec += (decrementer_count - get_dec()) * count_period_num / count_period_den; if (tv->tv_usec >= 1000000) { diff --git a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c index 5fee4463b..562ce0295 100644 --- a/arch/ppc/mm/fault.c +++ b/arch/ppc/mm/fault.c @@ -135,7 +135,7 @@ good_area: if (!(vma->vm_flags & (VM_READ | VM_EXEC))) goto bad_area; } - if (!handle_mm_fault(current, vma, address, is_write)) + if (!handle_mm_fault(mm, vma, address, is_write)) goto bad_area; up(&mm->mmap_sem); /* diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c index eaa5924a2..c92abef90 100644 --- a/arch/ppc/mm/init.c +++ b/arch/ppc/mm/init.c @@ -87,7 +87,7 @@ unsigned long avail_start; extern int num_memory; extern struct mem_info memory[]; extern boot_infos_t *boot_infos; -#ifndef __SMP__ +#ifndef CONFIG_SMP struct pgtable_cache_struct quicklists; #endif @@ -278,9 +278,9 @@ void show_mem(void) show_buffers(); printk("%-8s %3s %8s %8s %8s %9s %8s", "Process", "Pid", "Ctx", "Ctx<<4", "Last Sys", "pc", "task"); -#ifdef __SMP__ +#ifdef CONFIG_SMP printk(" %3s", "CPU"); -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ printk("\n"); for_each_task(p) { @@ -294,7 +294,7 @@ void show_mem(void) (ulong)p); { int iscur = 0; -#ifdef __SMP__ +#ifdef CONFIG_SMP printk("%3d ", p->processor); if ( (p->processor != NO_PROC_ID) && (p == current_set[p->processor]) ) @@ -315,7 +315,7 @@ void show_mem(void) printk(","); printk("last math"); } -#endif /* __SMP__ */ +#endif /* CONFIG_SMP */ printk("\n"); } } @@ -495,7 +495,7 @@ local_flush_tlb_all(void) { __clear_user(Hash, Hash_size); _tlbia(); -#ifdef __SMP__ +#ifdef CONFIG_SMP smp_send_tlb_invalidate(0); #endif } @@ -511,7 +511,7 @@ local_flush_tlb_mm(struct mm_struct *mm) mm->context = NO_CONTEXT; if (mm == current->mm) activate_mm(mm, mm); -#ifdef __SMP__ +#ifdef CONFIG_SMP smp_send_tlb_invalidate(0); #endif } @@ -523,7 +523,7 @@ local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) flush_hash_page(vma->vm_mm->context, vmaddr); else flush_hash_page(0, vmaddr); -#ifdef __SMP__ +#ifdef CONFIG_SMP smp_send_tlb_invalidate(0); #endif } @@ -551,7 +551,7 @@ local_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long e { flush_hash_page(mm->context, start); } -#ifdef __SMP__ +#ifdef CONFIG_SMP smp_send_tlb_invalidate(0); #endif } @@ -575,7 +575,7 @@ mmu_context_overflow(void) } read_unlock(&tasklist_lock); flush_hash_segments(0x10, 0xffffff); -#ifdef __SMP__ +#ifdef CONFIG_SMP smp_send_tlb_invalidate(0); #endif atomic_set(&next_mmu_context, 0); @@ -663,7 +663,7 @@ void __init setbat(int index, unsigned long virt, unsigned long phys, } #define IO_PAGE (_PAGE_NO_CACHE | _PAGE_GUARDED | _PAGE_RW) -#ifdef __SMP__ +#ifdef CONFIG_SMP #define RAM_PAGE (_PAGE_RW|_PAGE_COHERENT) #else #define RAM_PAGE (_PAGE_RW) diff --git a/arch/sh/defconfig b/arch/sh/defconfig index 337e46956..ef15fb104 100644 --- a/arch/sh/defconfig +++ b/arch/sh/defconfig @@ -54,12 +54,17 @@ CONFIG_BINFMT_ELF=y # CONFIG_BLK_DEV_FD is not set # CONFIG_BLK_DEV_XD is not set # CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set # # Additional Block Devices # # CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_STRIPED is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_INITRD=y @@ -122,6 +127,7 @@ CONFIG_SERIAL_CONSOLE=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set # CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BFS_FS is not set @@ -135,17 +141,23 @@ CONFIG_SERIAL_CONSOLE=y # CONFIG_JOLIET is not set # CONFIG_MINIX_FS is not set # CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y # CONFIG_DEVFS_FS is not set # CONFIG_DEVFS_DEBUG is not set # CONFIG_DEVPTS_FS is not set # CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set # CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set +# CONFIG_SYSV_FS_WRITE is not set # CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_NCPFS_NLS is not set # # Partition Types diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile index 8996a13dc..266aafe1f 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile @@ -29,7 +29,6 @@ all: kernel.o head.o init_task.o entry.o: entry.S head.o: head.S - $(CC) $(AFLAGS) -traditional -c $*.S -o $*.o clean: diff --git a/arch/sh/kernel/entry.S b/arch/sh/kernel/entry.S index 46ad20f53..00372811c 100644 --- a/arch/sh/kernel/entry.S +++ b/arch/sh/kernel/entry.S @@ -14,6 +14,8 @@ #include <linux/linkage.h> #include <linux/config.h> +#define COMPAT_OLD_SYSCALL_ABI 1 + ! NOTE: ! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address ! to be jumped is too far, but it causes illegal slot exception. @@ -31,26 +33,24 @@ * if the order here is changed, it needs to be * updated in ptrace.c and ptrace.h * - * syscall # - * ssr - * r0 + * $r0 * ... - * r15 = stack pointer - * gbr - * mach - * macl - * pr - * spc + * $r15 = stack pointer + * $spc + * $pr + * $ssr + * $gbr + * $mach + * $macl + * syscall # * */ /* * These are offsets into the task-struct. */ -state = 0 flags = 4 sigpending = 8 -addr_limit = 12 need_resched = 20 PF_TRACESYS = 0x00000020 @@ -75,30 +75,35 @@ MMU_TEA = 0xff00000c ! TLB Exception Address Register #endif /* Offsets to the stack */ -SYSCALL_NR = 0 -SR = 4 -R0 = 8 -SP = (8+15*4) +R0 = 0 /* Return value */ +SP = (15*4) +SR = (16*4+8) +SYSCALL_NR = (16*4+6*4) + #define k0 r0 #define k1 r1 #define k2 r2 #define k3 r3 +#define k4 r4 -#define kernel_sp r4 /* r4_bank1 */ -#define ksp r4_bank /* r4_bank1 */ +#define current r7 /* r7_bank1 */ +#define g_imask r6 /* r6_bank1 */ +#define k_current r7_bank /* r7_bank1 */ +#define k_g_imask r6_bank /* r6_bank1 */ #define k_ex_code r2_bank /* r2_bank1 */ -/* Kernel mode register usage: - k0 scratch - k1 scratch - k2 scratch (Exception code) - k3 scratch (Return address) - k4 Stack base = current+8192 - k5 Global Interrupt Mask (0--15) - k6 reserved - k7 reserved -*/ +/* + * Kernel mode register usage: + * k0 scratch + * k1 scratch + * k2 scratch (Exception code) + * k3 scratch (Return address) + * k4 scratch + * k5 reserved + * k6 Global Interrupt Mask (0--15 << 4) + * k7 CURRENT (pointer to current task) + */ ! ! TLB Miss / Initial Page write exception handling @@ -114,42 +119,60 @@ SP = (8+15*4) ! this first version depends *much* on C implementation. ! -#define RESTORE_FLAGS() \ - mov.l @(SR,$r15), $r0; \ - and #0xf0, $r0; \ - shlr8 $r0; \ - cmp/eq #0x0f, $r0; \ - bt 9f; \ - mov.l __INV_IMASK, $r1; \ - stc $sr, $r0; \ - and $r1, $r0; \ - stc $r5_bank, $r1; \ - or $r1, $r0; \ - ldc $r0, $sr +#define STI() \ + mov.l __INV_IMASK, $r11; \ + stc $sr, $r10; \ + and $r11, $r10; \ + stc $k_g_imask, $r11; \ + or $r11, $r10; \ + ldc $r10, $sr .balign 4 -tlb_protection_violation_load: tlb_miss_load: - mov #-1, $r0 - mov.l $r0, @$r15 ! syscall nr = -1 mov.l 2f, $r0 mov.l @$r0, $r6 - RESTORE_FLAGS() -9: mov $r15, $r4 + STI() + mov $r15, $r4 mov.l 1f, $r0 jmp @$r0 mov #0, $r5 .balign 4 -tlb_protection_violation_store: tlb_miss_store: + mov.l 2f, $r0 + mov.l @$r0, $r6 + STI() + mov $r15, $r4 + mov.l 1f, $r0 + jmp @$r0 + mov #1, $r5 + + .balign 4 initial_page_write: - mov #-1, $r0 - mov.l $r0, @$r15 ! syscall nr = -1 mov.l 2f, $r0 mov.l @$r0, $r6 - RESTORE_FLAGS() -9: mov $r15, $r4 + STI() + mov $r15, $r4 + mov.l 1f, $r0 + jmp @$r0 + mov #1, $r5 + + .balign 4 +tlb_protection_violation_load: + mov.l 2f, $r0 + mov.l @$r0, $r6 + STI() + mov $r15, $r4 + mov.l 1f, $r0 + jmp @$r0 + mov #0, $r5 + + .balign 4 +tlb_protection_violation_store: + mov.l 2f, $r0 + mov.l @$r0, $r6 + STI() + mov $r15, $r4 mov.l 1f, $r0 jmp @$r0 mov #1, $r5 @@ -162,8 +185,6 @@ initial_page_write: .balign 4 /* Unwind the stack and jmp to the debug entry */ debug: - add #4, $r15 ! skip syscall number - mov.l @$r15+, $r11 ! SSR mov.l @$r15+, $r0 mov.l @$r15+, $r1 mov.l @$r15+, $r2 @@ -172,11 +193,10 @@ debug: mov.l @$r15+, $r5 mov.l @$r15+, $r6 mov.l @$r15+, $r7 - stc $sr, $r14 - mov.l 1f, $r9 ! BL =1, RB=1 - or $r9, $r14 - ldc $r14, $sr ! here, change the register bank - mov $r11, $k1 + stc $sr, $r8 + mov.l 1f, $r9 ! BL =1, RB=1, IMASK=0x0F + or $r9, $r8 + ldc $r8, $sr ! here, change the register bank mov.l @$r15+, $r8 mov.l @$r15+, $r9 mov.l @$r15+, $r10 @@ -185,11 +205,12 @@ debug: mov.l @$r15+, $r13 mov.l @$r15+, $r14 mov.l @$r15+, $k0 + ldc.l @$r15+, $spc + lds.l @$r15+, $pr + mov.l @$r15+, $k1 ldc.l @$r15+, $gbr lds.l @$r15+, $mach lds.l @$r15+, $macl - lds.l @$r15+, $pr - ldc.l @$r15+, $spc mov $k0, $r15 ! mov.l 2f, $k0 @@ -203,11 +224,10 @@ debug: .balign 4 error: ! - RESTORE_FLAGS() -9: mov.l 1f, $r1 - mov #-1, $r0 - jmp @$r1 - mov.l $r0, @$r15 ! syscall nr = -1 + STI() + mov.l 1f, $r0 + jmp @$r0 + nop .balign 4 1: .long SYMBOL_NAME(do_exception_error) @@ -222,76 +242,106 @@ ENTRY(ret_from_fork) bra SYMBOL_NAME(ret_from_syscall) add #4, $r15 ! pop down bogus r0 (see switch_to MACRO) -! -! The immediate value of "trapa" indicates the number of arguments -! placed on the stack. -! -! Note that TRA register contains the value = Imm x 4. -! +/* + * Old syscall interface: + * + * Syscall #: R0 + * Arguments #0 to #3: R4--R7 + * more arguments: On the stack + * TRA: (number of arguments on the stack) x 4 + * + * New syscall interface: + * + * Syscall #: R3 + * Arguments #0 to #3: R4--R7 + * Arguments #4 to #6: R0, R1, R2 + * TRA: (number of arguments + 0x10) x 4 + * + */ + system_call: - mov.l 1f, $r2 - mov.l @$r2, $r8 - ! - ! DEBUG DEBUG - ! mov.l led, $r1 - ! mov $r0, $r2 - ! mov.b $r2, @$r1 + mov.l 1f, $r9 + mov.l @$r9, $r8 ! #ifdef CONFIG_DEBUG_KERNEL_WITH_GDB_STUB - mov #0x20, $r1 - extu.b $r1, $r1 - shll2 $r1 - cmp/hs $r1, $r8 + mov #0x20, $r9 + extu.b $r9, $r9 + shll2 $r9 + cmp/hs $r9, $r8 bt debug #endif ! - mov $r0, $r2 - RESTORE_FLAGS() -9: mov.l __n_sys, $r1 - cmp/hs $r1, $r2 + mov #SYSCALL_NR, $r14 + add $r15, $r14 + ! + mov #0x40, $r9 +#ifdef COMPAT_OLD_SYSCALL_ABI + cmp/hs $r9, $r8 + mov $r0, $r10 + bf/s 0f + mov $r0, $r9 +#endif + ! New Syscall ABI + sub $r9, $r8 + shlr2 $r8 + shll8 $r8 + shll8 $r8 + mov $r3, $r10 + or $r8, $r10 ! Encode syscall # and # of arguments + ! + mov $r3, $r9 + mov #0, $r8 +0: + mov.l $r10, @$r14 ! set syscall_nr + STI() + mov.l __n_sys, $r10 + cmp/hs $r10, $r9 bt badsys ! - stc $ksp, $r1 - mov.l __tsk_flags, $r0 - add $r0, $r1 ! - mov.l @$r1, $r0 ! Is it trace? - tst #PF_TRACESYS, $r0 +#ifdef COMPAT_OLD_SYSCALL_ABI + ! Build the stack frame if TRA > 0 + mov $r8, $r10 + cmp/pl $r10 + bf 0f + mov.l @(SP,$r15), $r0 ! get original stack +7: add #-4, $r10 +4: mov.l @($r0,$r10), $r1 ! May cause address error exception.. + mov.l $r1, @-$r15 + cmp/pl $r10 + bt 7b +#endif +0: stc $k_current, $r11 + mov.l @(flags,$r11), $r10 ! Is it trace? + mov #PF_TRACESYS, $r11 + tst $r11, $r10 bt 5f ! Trace system call - mov #-ENOSYS, $r1 - mov.l $r1, @(R0,$r15) - mov.l 3f, $r1 - jsr @$r1 + mov #-ENOSYS, $r11 + mov.l $r11, @(R0,$r15) + mov.l 2f, $r11 + jsr @$r11 nop - mova 3f, $r0 + mov.l __syscall_ret_trace, $r10 bra 6f - lds $r0, $pr + lds $r10, $pr ! -5: mova syscall_ret, $r0 - lds $r0, $pr - ! Build the stack frame if TRA > 0 -6: mov $r2, $r3 - mov $r8, $r2 - cmp/pl $r8 - bf 0f - mov #SP, $r0 - mov.l @($r0,$r15), $r0 ! get original stack -7: add #-4, $r8 -4: mov.l @($r0,$r8), $r1 ! May cause address error exception.. - mov.l $r1, @-$r15 - cmp/pl $r8 - bt 7b +5: mov.l __syscall_ret, $r10 + lds $r10, $pr ! -0: mov $r3, $r0 - shll2 $r0 ! x4 - mov.l __sct, $r1 - add $r1, $r0 - mov.l @$r0, $r1 - jmp @$r1 - mov $r2, $r8 +6: mov $r9, $r10 + shll2 $r10 ! x4 + mov.l __sct, $r11 + add $r11, $r10 + mov.l @$r10, $r11 + jmp @$r11 + nop + ! In case of trace .balign 4 -3: add $r8, $r15 ! pop off the arguments +3: +#ifdef COMPAT_OLD_SYSCALL_ABI + add $r8, $r15 ! pop off the arguments +#endif mov.l $r0, @(R0,$r15) ! save the return value mov.l 2f, $r1 mova SYMBOL_NAME(ret_from_syscall), $r0 @@ -302,9 +352,12 @@ system_call: 2: .long SYMBOL_NAME(syscall_trace) __n_sys: .long NR_syscalls __sct: .long SYMBOL_NAME(sys_call_table) -__tsk_flags: .long flags-8192 ! offset from stackbase to tsk->flags -led: .long 0xa8000000 ! For my board -- gN +__syscall_ret_trace: + .long 3b +__syscall_ret: + .long SYMBOL_NAME(syscall_ret) +#ifdef COMPAT_OLD_SYSCALL_ABI .section .fixup,"ax" fixup_syscall_argerr: rts @@ -316,6 +369,7 @@ fixup_syscall_argerr: .balign 4 .long 4b,fixup_syscall_argerr .previous +#endif .balign 4 reschedule: @@ -327,23 +381,25 @@ reschedule: 1: .long SYMBOL_NAME(schedule) ENTRY(ret_from_irq) - mov.l @(SR,$r15), $r0 ! get status register + mov #SR, $r0 + mov.l @($r0,$r15), $r0 ! get status register shll $r0 shll $r0 ! kernel space? bt restore_all ! Yes, it's from kernel, go back soon ! - RESTORE_FLAGS() -9: bra ret_with_reschedule + STI() + bra ret_with_reschedule nop ENTRY(ret_from_exception) - mov.l @(SR,$r15), $r0 ! get status register + mov #SR, $r0 + mov.l @($r0,$r15), $r0 ! get status register shll $r0 shll $r0 ! kernel space? bt restore_all ! Yes, it's from kernel, go back soon ! - RESTORE_FLAGS() -9: bra ret_from_syscall + STI() + bra ret_from_syscall nop .balign 4 __INV_IMASK: @@ -351,7 +407,9 @@ __INV_IMASK: .balign 4 syscall_ret: +#ifdef COMPAT_OLD_SYSCALL_ABI add $r8, $r15 ! pop off the arguments +#endif mov.l $r0, @(R0,$r15) ! save the return value /* fall through */ @@ -366,9 +424,7 @@ handle_softirq: jsr @$r0 nop ret_with_reschedule: - stc $ksp, $r1 - mov.l __minus8192, $r0 - add $r0, $r1 + stc $k_current, $r1 mov.l @(need_resched,$r1), $r0 tst #0xff, $r0 bf reschedule @@ -389,30 +445,14 @@ __softirq_state: .long SYMBOL_NAME(softirq_state) __do_softirq: .long SYMBOL_NAME(do_softirq) -__minus8192: - .long -8192 ! offset from stackbase to tsk .balign 4 restore_all: #if defined(__SH4__) - mov.l __fpu_prepare_fd, $r1 - jsr @$r1 + mov.l __fpu_prepare_fd, $r0 + jsr @$r0 stc $sr, $r4 #endif - add #4, $r15 ! Skip syscall number - mov.l @$r15+, $r11 ! Got SSR into R11 -#if defined(__SH4__) - mov $r11, $r12 -#endif - ! - mov.l 1f, $r1 - stc $sr, $r0 - and $r1, $r0 ! Get FD - mov.l 2f, $r1 - and $r1, $r11 - or $r0, $r11 ! Inherit the FD value of SR - stc $r5_bank, $r0 - or $r0, $r11 ! Inherit the IMASK value ! mov.l @$r15+, $r0 mov.l @$r15+, $r1 @@ -422,14 +462,12 @@ restore_all: mov.l @$r15+, $r5 mov.l @$r15+, $r6 mov.l @$r15+, $r7 - stc $sr, $r14 + ! + stc $sr, $r8 mov.l __blrb_flags, $r9 ! BL =1, RB=1 - or $r9, $r14 - ldc $r14, $sr ! here, change the register bank - mov $r11, $k1 -#if defined(__SH4__) - mov $r12, $k2 -#endif + or $r9, $r8 + ldc $r8, $sr ! here, change the register bank + ! mov.l @$r15+, $r8 mov.l @$r15+, $r9 mov.l @$r15+, $r10 @@ -437,20 +475,33 @@ restore_all: mov.l @$r15+, $r12 mov.l @$r15+, $r13 mov.l @$r15+, $r14 - mov.l @$r15+, $k0 ! original stack + mov.l @$r15+, $k4 ! original stack pointer + ldc.l @$r15+, $spc + lds.l @$r15+, $pr + mov.l @$r15+, $k3 ! original SR ldc.l @$r15+, $gbr lds.l @$r15+, $mach lds.l @$r15+, $macl - lds.l @$r15+, $pr - ldc.l @$r15+, $spc - ldc $k1, $ssr + add #4, $r15 ! Skip syscall number + ! + ! Calculate new SR value + mov $k3, $k2 ! original SR value + mov.l 1f, $k1 + stc $sr, $k0 + and $k1, $k0 ! Get current FD-bit + mov.l 2f, $k1 + and $k1, $k2 ! Mask orignal SR value + or $k0, $k2 ! Inherit current FD-bit + or $g_imask, $k2 ! Inherit the IMASK-bits + ldc $k2, $ssr + ! #if defined(__SH4__) - shll $k1 - shll $k1 + shll $k2 + shll $k2 bf 9f ! user mode /* Kernel to kernel transition */ mov.l 1f, $k1 - tst $k1, $k2 + tst $k1, $k3 bf 9f ! it hadn't FPU ! Kernel to kernel and FPU was used ! There's the case we don't get FPU now @@ -462,14 +513,15 @@ restore_all: ldc $k2, $sr ! Grab FPU mov.l __init_task_flags, $k1 mov.l @$k1, $k2 - mov.l __PF_USEDFPU, $k1 - or $k1, $k2 - mov.l __init_task_flags, $k1 + mov.l __PF_USEDFPU, $k0 + or $k0, $k2 mov.l $k2, @$k1 ! Set init_task.flags |= PF_USEDFPU ! ! Restoring FPU... ! -7: fmov.s @$r15+, $fr0 +7: mov.l 3f, $k1 + lds $k1, $fpscr + fmov.s @$r15+, $fr0 fmov.s @$r15+, $fr1 fmov.s @$r15+, $fr2 fmov.s @$r15+, $fr3 @@ -489,7 +541,7 @@ restore_all: lds.l @$r15+, $fpul 9: #endif - mov $k0, $r15 + mov $k4, $r15 rte nop @@ -505,6 +557,7 @@ __PF_USEDFPU: #endif 1: .long 0x00008000 ! FD 2: .long 0xffff7f0f ! ~(IMASK+FD) +3: .long 0x00080000 ! SZ=0, PR=1 ! Exception Vector Base ! @@ -569,6 +622,9 @@ handle_exception: ! /* Currently it's not the case for GCC (only udivsi3_i4, divsi3_i4) */ sts.l $fpul, @-$r15 sts.l $fpscr, @-$r15 + mov.l 6f, $k1 + lds $k1, $fpscr + mov.l 3f, $k1 fmov.s $fr15, @-$r15 fmov.s $fr14, @-$r15 fmov.s $fr13, @-$r15 @@ -584,40 +640,47 @@ handle_exception: fmov.s $fr3, @-$r15 fmov.s $fr2, @-$r15 fmov.s $fr1, @-$r15 - fmov.s $fr0, @-$r15 bra 9f - mov.l 3f, $k1 + fmov.s $fr0, @-$r15 #else mov.l 3f, $k1 bt/s 9f ! it's from kernel to kernel transition mov $r15, $k0 ! save original stack to k0 anyway #endif 8: /* User space to kernel */ - mov $kernel_sp, $r15 ! change to kernel stack - mov.l 4f, $k1 ! let kernel release FPU -9: stc.l $spc, @-$r15 - sts.l $pr, @-$r15 + mov #0x20, $k1 + shll8 $k1 ! $k1 <= 8192 + add $current, $k1 + mov $k1, $r15 ! change to kernel stack ! - lds $k3, $pr ! Set the return address to pr + mov.l 4f, $k1 ! let kernel release FPU +9: mov #-1, $k4 + mov.l $k4, @-$r15 ! syscall_nr (default: -1) ! sts.l $macl, @-$r15 sts.l $mach, @-$r15 stc.l $gbr, @-$r15 - mov.l $k0, @-$r15 ! save orignal stack - mov.l $r14, @-$r15 + stc.l $ssr, @-$r15 + sts.l $pr, @-$r15 + stc.l $spc, @-$r15 ! - stc $sr, $r14 ! Back to normal register bank, and - or $k1, $r14 ! Block all interrupts, may release FPU - mov.l 5f, $k1 - and $k1, $r14 ! ... - ldc $r14, $sr ! ...changed here. + lds $k3, $pr ! Set the return address to pr ! + mov.l $k0, @-$r15 ! save orignal stack + mov.l $r14, @-$r15 mov.l $r13, @-$r15 mov.l $r12, @-$r15 mov.l $r11, @-$r15 mov.l $r10, @-$r15 mov.l $r9, @-$r15 mov.l $r8, @-$r15 + ! + stc $sr, $r8 ! Back to normal register bank, and + or $k1, $r8 ! Block all interrupts, may release FPU + mov.l 5f, $k1 + and $k1, $r8 ! ... + ldc $r8, $sr ! ...changed here. + ! mov.l $r7, @-$r15 mov.l $r6, @-$r15 mov.l $r5, @-$r15 @@ -626,23 +689,22 @@ handle_exception: mov.l $r2, @-$r15 mov.l $r1, @-$r15 mov.l $r0, @-$r15 - stc.l $ssr, @-$r15 - mov.l $r0, @-$r15 ! push $r0 again (for syscall number) - ! Then, dispatch to the handler, according to the excepiton code. - stc $k_ex_code, $r1 - shlr2 $r1 - shlr $r1 - mov.l 1f, $r0 - add $r1, $r0 - mov.l @$r0, $r0 - jmp @$r0 - mov.l @$r15, $r0 ! recovering $r0.. + ! Then, dispatch to the handler, according to the exception code. + stc $k_ex_code, $r8 + shlr2 $r8 + shlr $r8 + mov.l 1f, $r9 + add $r8, $r9 + mov.l @$r9, $r9 + jmp @$r9 + nop .balign 4 1: .long SYMBOL_NAME(exception_handling_table) 2: .long 0x00008000 ! FD=1 3: .long 0x000000f0 ! FD=0, IMASK=15 4: .long 0x000080f0 ! FD=1, IMASK=15 5: .long 0xcfffffff ! RB=0, BL=0 +6: .long 0x00080000 ! SZ=0, PR=1 none: rts diff --git a/arch/sh/kernel/fpu.c b/arch/sh/kernel/fpu.c index 5301a1333..cbeb60d31 100644 --- a/arch/sh/kernel/fpu.c +++ b/arch/sh/kernel/fpu.c @@ -23,6 +23,7 @@ save_fpu(struct task_struct *tsk) { asm volatile("sts.l $fpul, @-%0\n\t" "sts.l $fpscr, @-%0\n\t" + "lds %1, $fpscr\n\t" "frchg\n\t" "fmov.s $fr15, @-%0\n\t" "fmov.s $fr14, @-%0\n\t" @@ -58,7 +59,8 @@ save_fpu(struct task_struct *tsk) "fmov.s $fr1, @-%0\n\t" "fmov.s $fr0, @-%0" : /* no output */ - : "r" ((char *)(&tsk->thread.fpu.hard.status)) + : "r" ((char *)(&tsk->thread.fpu.hard.status)), + "r" (FPSCR_INIT) : "memory"); tsk->flags &= ~PF_USEDFPU; @@ -68,7 +70,8 @@ save_fpu(struct task_struct *tsk) static void restore_fpu(struct task_struct *tsk) { - asm volatile("fmov.s @%0+, $fr0\n\t" + asm volatile("lds %1, $fpscr\n\t" + "fmov.s @%0+, $fr0\n\t" "fmov.s @%0+, $fr1\n\t" "fmov.s @%0+, $fr2\n\t" "fmov.s @%0+, $fr3\n\t" @@ -105,7 +108,7 @@ restore_fpu(struct task_struct *tsk) "lds.l @%0+, $fpscr\n\t" "lds.l @%0+, $fpul\n\t" : /* no output */ - : "r" (&tsk->thread.fpu) + : "r" (&tsk->thread.fpu), "r" (FPSCR_INIT) : "memory"); } @@ -163,7 +166,6 @@ do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long { struct task_struct *tsk = current; - regs.syscall_nr = -1; regs.pc += 2; grab_fpu(); @@ -179,15 +181,34 @@ do_fpu_state_restore(unsigned long r4, unsigned long r5, unsigned long r6, { struct task_struct *tsk = current; - regs.syscall_nr = -1; - if (!user_mode(®s)) { if (tsk != &init_task) { unlazy_fpu(tsk); } tsk = &init_task; - if (tsk->flags & PF_USEDFPU) - BUG(); + if (tsk->flags & PF_USEDFPU) { + /* + * This weird situation can be occurred. + * + * There's race condition in __cli: + * + * (1) $SR --> register + * (2) Set IMASK of register + * (3) $SR <-- register + * + * Between (1) and (2), or (2) and (3) getting + * interrupt, and interrupt handler (or + * softirq) may use FPU. + * + * Then, SR.FD is overwritten by (3). + * + * This results init_task.PF_USEDFPU is on, + * with SR.FD == 1. + * + */ + release_fpu(); + return; + } } grab_fpu(); @@ -216,8 +237,8 @@ fpu_prepare_fd(unsigned long sr, unsigned long r5, unsigned long r6, grab_fpu(); else { if (!(sr & SR_FD)) { - release_fpu(); BUG(); + release_fpu(); } } return; @@ -228,16 +249,20 @@ fpu_prepare_fd(unsigned long sr, unsigned long r5, unsigned long r6, grab_fpu(); else { if (init_task.flags & PF_USEDFPU) { - init_task.flags &= ~PF_USEDFPU; - BUG(); + /* + * This weird situation can be occurred. + * See the comment in do_fpu_state_restore. + */ + grab_fpu(); + save_fpu(&init_task); } } } else { if (init_task.flags & PF_USEDFPU) save_fpu(&init_task); else { - release_fpu(); BUG(); + release_fpu(); } } } diff --git a/arch/sh/kernel/head.S b/arch/sh/kernel/head.S index ae406d22d..db3e8b0a3 100644 --- a/arch/sh/kernel/head.S +++ b/arch/sh/kernel/head.S @@ -41,12 +41,21 @@ ENTRY(_stext) ldc $r0, $sr ! Initialize global interrupt mask mov #0, $r0 - ldc $r0, $r5_bank + ldc $r0, $r6_bank ! mov.l 2f, $r0 mov $r0, $r15 ! Set initial r15 (stack pointer) - ldc $r0, $r4_bank ! and stack base + mov #0x20, $r1 ! + shll8 $r1 ! $r1 = 8192 + sub $r1, $r0 ! + ldc $r0, $r7_bank ! ... and init_task ! +#if defined(__SH4__) + ! Initialize fpu + mov.l 7f, $r0 + jsr @$r0 + nop +#endif ! Enable cache mov.l 6f, $r0 jsr @$r0 @@ -71,3 +80,6 @@ ENTRY(_stext) 4: .long SYMBOL_NAME(_end) 5: .long SYMBOL_NAME(start_kernel) 6: .long SYMBOL_NAME(cache_init) +#if defined(__SH4__) +7: .long SYMBOL_NAME(fpu_init) +#endif diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index af03ef46d..c989796d7 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c @@ -235,8 +235,6 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, struct irqaction * action; unsigned int status; - regs.syscall_nr = -1; /* It's not system call */ - /* Get IRQ number */ asm volatile("stc $r2_bank, %0\n\t" "shlr2 %0\n\t" diff --git a/arch/sh/kernel/irq_imask.c b/arch/sh/kernel/irq_imask.c index 380acf405..7237ba3b5 100644 --- a/arch/sh/kernel/irq_imask.c +++ b/arch/sh/kernel/irq_imask.c @@ -43,7 +43,7 @@ static unsigned int startup_imask_irq(unsigned int irq) } static struct hw_interrupt_type imask_irq_type = { - "Interrupt using IMASK of SR register", + "SR.IMASK", startup_imask_irq, shutdown_imask_irq, enable_imask_irq, @@ -56,13 +56,13 @@ void static inline set_interrupt_registers(int ip) { unsigned long __dummy; - asm volatile("ldc %2, $r5_bank\n\t" + asm volatile("ldc %2, $r6_bank\n\t" "stc $sr, %0\n\t" "and #0xf0, %0\n\t" - "shlr8 %0\n\t" - "cmp/eq #0x0f, %0\n\t" - "bt 1f ! CLI-ed\n\t" - "stc $sr, %0\n\t" + "shlr2 %0\n\t" + "cmp/eq #0x3c, %0\n\t" + "bt/s 1f ! CLI-ed\n\t" + " stc $sr, %0\n\t" "and %1, %0\n\t" "or %2, %0\n\t" "ldc %0, $sr\n" diff --git a/arch/sh/kernel/irq_onchip.c b/arch/sh/kernel/irq_onchip.c index 10c48fd38..36dce33fb 100644 --- a/arch/sh/kernel/irq_onchip.c +++ b/arch/sh/kernel/irq_onchip.c @@ -61,7 +61,7 @@ static unsigned int startup_onChip_irq(unsigned int irq) } static struct hw_interrupt_type onChip_irq_type = { - "On-Chip Supporting Module", + "On-Chip-IPR", startup_onChip_irq, shutdown_onChip_irq, enable_onChip_irq, @@ -193,7 +193,7 @@ static unsigned int startup_onChip2_irq(unsigned int irq) } static struct hw_interrupt_type onChip2_irq_type = { - "SH7709 Extended On-Chip Supporting Module", + "Extended-IPR", startup_onChip2_irq, shutdown_onChip2_irq, enable_onChip2_irq, diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index 97cd1fe0c..2d0f5e18a 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c @@ -136,20 +136,20 @@ void free_task_struct(struct task_struct *p) */ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) { /* Don't use this in BL=1(cli). Or else, CPU resets! */ - register unsigned long __sc0 __asm__ ("$r0") = __NR_clone; + register unsigned long __sc0 __asm__ ("$r3") = __NR_clone; register unsigned long __sc4 __asm__ ("$r4") = (long) flags | CLONE_VM; register unsigned long __sc5 __asm__ ("$r5") = 0; register unsigned long __sc8 __asm__ ("$r8") = (long) arg; register unsigned long __sc9 __asm__ ("$r9") = (long) fn; - __asm__("trapa #0\n\t" /* Linux/SH system call */ + __asm__("trapa #0x12\n\t" /* Linux/SH system call */ "tst #0xff, $r0\n\t" /* child or parent? */ "bf 1f\n\t" /* parent - jump */ "jsr @$r9\n\t" /* call fn */ " mov $r8, $r4\n\t" /* push argument */ "mov $r0, $r4\n\t" /* return value to arg of exit */ - "mov %2, $r0\n\t" /* exit */ - "trapa #0\n" + "mov %2, $r3\n\t" /* exit */ + "trapa #0x11\n" "1:" : "=z" (__sc0) : "0" (__sc0), "i" (__NR_exit), @@ -194,7 +194,11 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) fpvalid = tsk->used_math; if (fpvalid) { + unsigned long flags; + + save_and_cli(flags); unlazy_fpu(tsk); + restore_flags(flags); memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu)); } @@ -214,7 +218,11 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, struct task_struct *tsk = current; if (tsk != &init_task) { + unsigned long flags; + + save_and_cli(flags); unlazy_fpu(tsk); + restore_flags(flags); p->thread.fpu = current->thread.fpu; p->used_math = tsk->used_math; } @@ -263,16 +271,21 @@ void dump_thread(struct pt_regs * regs, struct user * dump) void __switch_to(struct task_struct *prev, struct task_struct *next) { #if defined(__SH4__) - if (prev != &init_task) + if (prev != &init_task) { + unsigned long flags; + + save_and_cli(flags); unlazy_fpu(prev); + restore_flags(flags); + } #endif /* - * Restore the kernel stack onto kernel mode register - * k4 (r4_bank1) + * Restore the kernel mode register + * k7 (r7_bank1) */ - asm volatile("ldc %0, $r4_bank" + asm volatile("ldc %0, $r7_bank" : /* no output */ - :"r" ((unsigned long)next+8192)); + :"r" (next)); } asmlinkage int sys_fork(unsigned long r4, unsigned long r5, diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 154283571..49179f08f 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -244,7 +244,7 @@ void __init setup_arch(char **cmdline_p) /* * Reserve the kernel text and - * Reserve the bootmem bitmap.We do this in two steps (first step + * Reserve the bootmem bitmap. We do this in two steps (first step * was init_bootmem()), because this catches the (definitely buggy) * case of us accidentally initializing the bootmem allocator with * an invalid RAM area. @@ -262,17 +262,17 @@ void __init setup_arch(char **cmdline_p) if (LOADER_TYPE && INITRD_START) { if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) { reserve_bootmem(INITRD_START+__MEMORY_START, INITRD_SIZE); - initrd_start = - INITRD_START ? INITRD_START + PAGE_OFFSET + __MEMORY_START : 0; + initrd_start = + INITRD_START ? INITRD_START + PAGE_OFFSET + __MEMORY_START : 0; initrd_end = initrd_start + INITRD_SIZE; } else { - printk("initrd extends beyond end of memory " - "(0x%08lx > 0x%08lx)\ndisabling initrd\n", + printk("initrd extends beyond end of memory " + "(0x%08lx > 0x%08lx)\ndisabling initrd\n", INITRD_START + INITRD_SIZE, max_low_pfn << PAGE_SHIFT); - initrd_start = 0; - } - } + initrd_start = 0; + } + } #endif #if 0 @@ -301,10 +301,9 @@ void __init setup_arch(char **cmdline_p) #endif #if defined(__SH4__) + /* We already grab/initialized FPU in head.S. Make it consisitent. */ init_task.used_math = 1; init_task.flags |= PF_USEDFPU; - grab_fpu(); - fpu_init(); #endif paging_init(); } diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c index 4b11100ae..8751d45f5 100644 --- a/arch/sh/kernel/signal.c +++ b/arch/sh/kernel/signal.c @@ -152,30 +152,36 @@ struct rt_sigframe #if defined(__SH4__) static inline int restore_sigcontext_fpu(struct sigcontext *sc) { - current->used_math = 1; + struct task_struct *tsk = current; + + tsk->used_math = 1; return __copy_from_user(&tsk->thread.fpu.hard, &sc->sc_fpregs[0], - sizeof(long)*(NUM_FPU_REGS*2+2)); + sizeof(long)*(16*2+2)); } static inline int save_sigcontext_fpu(struct sigcontext *sc) { struct task_struct *tsk = current; + unsigned long flags; if (!tsk->used_math) { - sc->owend_fp = 0; + sc->sc_ownedfp = 0; return 0; } - sc->owend_fp = 1; + sc->sc_ownedfp = 1; /* This will cause a "finit" to be triggered by the next attempted FPU operation by the 'current' process. */ tsk->used_math = 0; + save_and_cli(flags); unlazy_fpu(tsk); + restore_flags(flags); + return __copy_to_user(&sc->sc_fpregs[0], &tsk->thread.fpu.hard, - sizeof(long)*(NUM_FPU_REGS*2+2)); + sizeof(long)*(16*2+2)); } #endif @@ -206,7 +212,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *r0_p) regs->sr |= SR_FD; /* Release FPU */ clear_fpu(tsk); current->used_math = 0; - __get_user (owned_fp, &context->sc_ownedfp); + __get_user (owned_fp, &sc->sc_ownedfp); if (owned_fp) err |= restore_sigcontext_fpu(sc); } @@ -363,11 +369,11 @@ static void setup_frame(int sig, struct k_sigaction *ka, if (ka->sa.sa_flags & SA_RESTORER) { regs->pr = (unsigned long) ka->sa.sa_restorer; } else { - /* This is : mov #__NR_sigreturn,r0 ; trapa #0 */ + /* This is : mov #__NR_sigreturn,r3 ; trapa #0x10 */ #ifdef __LITTLE_ENDIAN__ - unsigned long code = 0xc300e000 | (__NR_sigreturn); + unsigned long code = 0xc310e300 | (__NR_sigreturn); #else - unsigned long code = 0xe000c300 | (__NR_sigreturn << 16); + unsigned long code = 0xe300c310 | (__NR_sigreturn << 16); #endif regs->pr = (unsigned long) frame->retcode; @@ -437,11 +443,11 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, if (ka->sa.sa_flags & SA_RESTORER) { regs->pr = (unsigned long) ka->sa.sa_restorer; } else { - /* This is : mov #__NR_rt_sigreturn,r0 ; trapa #0 */ + /* This is : mov #__NR_rt_sigreturn,r3 ; trapa #0x10 */ #ifdef __LITTLE_ENDIAN__ - unsigned long code = 0xc300e000 | (__NR_rt_sigreturn); + unsigned long code = 0xc310e300 | (__NR_rt_sigreturn); #else - unsigned long code = 0xe000c300 | (__NR_rt_sigreturn << 16); + unsigned long code = 0xe300c310 | (__NR_rt_sigreturn << 16); #endif regs->pr = (unsigned long) frame->retcode; diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c index fad3a8145..3e9cd8d28 100644 --- a/arch/sh/kernel/time.c +++ b/arch/sh/kernel/time.c @@ -33,6 +33,23 @@ #define TMU0_TCR_INIT 0x0020 #define TMU_TSTR_INIT 1 +/* RCR1 Bits */ +#define RCR1_CF 0x80 /* Carry Flag */ +#define RCR1_CIE 0x10 /* Carry Interrupt Enable */ +#define RCR1_AIE 0x08 /* Alarm Interrupt Enable */ +#define RCR1_AF 0x01 /* Alarm Flag */ + +/* RCR2 Bits */ +#define RCR2_PEF 0x80 /* PEriodic interrupt Flag */ +#define RCR2_PESMASK 0x70 /* Periodic interrupt Set */ +#define RCR2_RTCEN 0x08 /* ENable RTC */ +#define RCR2_ADJ 0x04 /* ADJustment (30-second) */ +#define RCR2_RESET 0x02 /* Reset bit */ +#define RCR2_START 0x01 /* Start bit */ + +#define RTC_IRQ 22 +#define RTC_IPR_OFFSET 0 + #if defined(__sh3__) #define TMU_TOCR 0xfffffe90 /* Byte access */ #define TMU_TSTR 0xfffffe92 /* Byte access */ @@ -43,9 +60,6 @@ #define FRQCR 0xffffff80 -#define RTC_IRQ 22 -#define RTC_IPR_OFFSET 0 - /* SH-3 RTC */ #define R64CNT 0xfffffec0 #define RSECCNT 0xfffffec2 @@ -74,9 +88,6 @@ #define FRQCR 0xffc00000 -#define RTC_IRQ 22 -#define RTC_IPR_OFFSET 0 - /* SH-4 RTC */ #define R64CNT 0xffc80000 #define RSECCNT 0xffc80004 @@ -149,7 +160,7 @@ static int set_rtc_time(unsigned long nowtime) int retval = 0; int real_seconds, real_minutes, cmos_minutes; - ctrl_outb(0x02, RCR2); /* reset pre-scaler & stop RTC */ + ctrl_outb(RCR2_RESET, RCR2); /* Reset pre-scaler & stop RTC */ cmos_minutes = ctrl_inb(RMINCNT); BCD_TO_BIN(cmos_minutes); @@ -178,7 +189,7 @@ static int set_rtc_time(unsigned long nowtime) retval = -1; } - ctrl_outb(0x01, RCR2); /* start RTC */ + ctrl_outb(RCR2_RTCEN|RCR2_START, RCR2); /* Start RTC */ return retval; } @@ -283,8 +294,8 @@ static unsigned long get_rtc_time(void) unsigned int sec, min, hr, wk, day, mon, yr, yr100; again: - ctrl_outb(0x01, RCR1); /* clear CF bit */ do { + ctrl_outb(0, RCR1); /* Clear CF-bit */ sec = ctrl_inb(RSECCNT); min = ctrl_inb(RMINCNT); hr = ctrl_inb(RHRCNT); @@ -299,7 +310,7 @@ static unsigned long get_rtc_time(void) yr = ctrl_inb(RYRCNT); yr100 = (yr == 0x99) ? 0x19 : 0x20; #endif - } while ((ctrl_inb(RCR1) & 0x80) != 0); + } while ((ctrl_inb(RCR1) & RCR1_CF) != 0); BCD_TO_BIN(yr100); BCD_TO_BIN(yr); @@ -313,7 +324,7 @@ static unsigned long get_rtc_time(void) hr > 23 || min > 59 || sec > 59) { printk(KERN_ERR "SH RTC: invalid value, resetting to 1 Jan 2000\n"); - ctrl_outb(0x02, RCR2); /* reset, stop */ + ctrl_outb(RCR2_RESET, RCR2); /* Reset & Stop */ ctrl_outb(0, RSECCNT); ctrl_outb(0, RMINCNT); ctrl_outb(0, RHRCNT); @@ -325,7 +336,7 @@ static unsigned long get_rtc_time(void) #else ctrl_outb(0, RYRCNT); #endif - ctrl_outb(0x01, RCR2); /* start */ + ctrl_outb(RCR2_RTCEN|RCR2_START, RCR2); /* Start */ goto again; } @@ -339,13 +350,13 @@ static __init unsigned int get_cpu_mhz(void) sti(); do {} while (ctrl_inb(R64CNT) != 0); - ctrl_outb(0x11, RCR1); + ctrl_outb(RCR1_CIE, RCR1); /* Enable carry interrupt */ asm volatile( "1:\t" "tst %1,%1\n\t" "bt/s 1b\n\t" " add #1,%0" - : "=&r"(count), "=&z" (__dummy) + : "=r"(count), "=z" (__dummy) : "0" (0), "1" (0)); cli(); /* @@ -373,7 +384,7 @@ static __init unsigned int get_cpu_mhz(void) static void rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - ctrl_outb(0x01, RCR1); + ctrl_outb(0, RCR1); /* Disable Carry Interrupts */ regs->regs[0] = 1; } diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c index 98431cb36..a9775f306 100644 --- a/arch/sh/kernel/traps.c +++ b/arch/sh/kernel/traps.c @@ -43,7 +43,6 @@ asmlinkage void do_##name(unsigned long r4, unsigned long r5, \ \ asm volatile("stc $r2_bank, %0": "=r" (error_code)); \ sti(); \ - regs.syscall_nr = -1; \ tsk->thread.error_code = error_code; \ tsk->thread.trap_no = trapnr; \ force_sig(signr, tsk); \ @@ -95,9 +94,9 @@ DO_ERROR( 8, SIGSEGV, "address error (store)", address_error_store, current) DO_ERROR(12, SIGILL, "reserved instruction", reserved_inst, current) DO_ERROR(13, SIGILL, "illegal slot instruction", illegal_slot_inst, current) -asmlinkage void do_exception_error (unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs regs) +asmlinkage void do_exception_error(unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7, + struct pt_regs regs) { long ex; asm volatile("stc $r2_bank, %0" : "=r" (ex)); @@ -131,7 +130,8 @@ void dump_stack(void) unsigned long *p; asm("mov $r15, %0" : "=r" (start)); - asm("stc $r4_bank, %0" : "=r" (end)); + asm("stc $r7_bank, %0" : "=r" (end)); + end += 8192; printk("%08lx:%08lx\n", (unsigned long)start, (unsigned long)end); for (p=start; p < end; p++) diff --git a/arch/sh/mm/cache.c b/arch/sh/mm/cache.c index 33bdf2114..5c28ea039 100644 --- a/arch/sh/mm/cache.c +++ b/arch/sh/mm/cache.c @@ -175,13 +175,13 @@ void cache_wback_area(unsigned long start, unsigned long end) * * For SH-4, flush (write back) Operand Cache, as Instruction Cache * doesn't have "updated" data. + * + * Assumes that called in interrupt disabled. */ static void cache_wback_all(void) { - unsigned long flags; unsigned long addr, data, i, j; - save_and_cli(flags); jump_to_P2(); for (i=0; i<CACHE_OC_NUM_ENTRIES; i++) { @@ -197,7 +197,6 @@ static void cache_wback_all(void) } back_to_P1(); - restore_flags(flags); } static void @@ -314,11 +313,11 @@ void flush_cache_all(void) { unsigned long flags; + save_and_cli(flags); /* Write back Operand Cache */ - cache_wback_all (); + cache_wback_all(); /* Then, invalidate Instruction Cache and Operand Cache */ - save_and_cli(flags); jump_to_P2(); ctrl_outl(CCR_CACHE_INIT, CCR); back_to_P1(); diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c index bf448bf8b..2369b3c04 100644 --- a/arch/sh/mm/fault.c +++ b/arch/sh/mm/fault.c @@ -55,7 +55,7 @@ good_area: start &= PAGE_MASK; for (;;) { - if (handle_mm_fault(current, vma, start, 1) <= 0) + if (handle_mm_fault(current->mm, vma, start, 1) <= 0) goto bad_area; if (!size) break; @@ -168,7 +168,7 @@ good_area: * the fault. */ { - int fault = handle_mm_fault(tsk, vma, address, writeaccess); + int fault = handle_mm_fault(mm, vma, address, writeaccess); if (fault < 0) goto out_of_memory; if (!fault) diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index bd9181933..7c8998eaa 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.52 1999/12/21 04:02:17 davem Exp $ +# $Id: Makefile,v 1.53 2000/03/31 04:06:19 davem Exp $ # Makefile for the linux kernel. # # Note! Dependencies are done automagically by 'make dep', which also diff --git a/arch/sparc/kernel/cpu.c b/arch/sparc/kernel/cpu.c index 4a9c6cdcb..0efc28f65 100644 --- a/arch/sparc/kernel/cpu.c +++ b/arch/sparc/kernel/cpu.c @@ -92,7 +92,7 @@ struct cpu_iu_info linux_sparc_chips[] = { /* Someone please write the code to support this beast! ;) */ { 2, 0, "Bipolar Integrated Technology - B5010"}, { 3, 0, "LSI Logic Corporation - unknown-type"}, - { 4, 0, "Texas Instruments, Inc. - SuperSparc 50"}, + { 4, 0, "Texas Instruments, Inc. - SuperSparc-(II)"}, /* SparcClassic -- borned STP1010TAB-50*/ { 4, 1, "Texas Instruments, Inc. - MicroSparc"}, { 4, 2, "Texas Instruments, Inc. - MicroSparc II"}, diff --git a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c index d05153f7a..742d7db97 100644 --- a/arch/sparc/kernel/ptrace.c +++ b/arch/sparc/kernel/ptrace.c @@ -60,7 +60,7 @@ pt_succ_return_linux(struct pt_regs *regs, unsigned long value, long *addr) static void pt_os_succ_return (struct pt_regs *regs, unsigned long val, long *addr) { - if (current->personality & PER_BSD) + if (current->personality == PER_SUNOS) pt_succ_return (regs, val); else pt_succ_return_linux (regs, val, addr); @@ -155,7 +155,7 @@ static inline void read_sunos_user(struct pt_regs *regs, unsigned long offset, pt_error_return(regs, EIO); return; } - if (current->personality & PER_BSD) + if (current->personality == PER_SUNOS) pt_succ_return (regs, v); else pt_succ_return_linux (regs, v, addr); @@ -310,8 +310,8 @@ asmlinkage void do_ptrace(struct pt_regs *regs) goto out; } - if (((current->personality & PER_BSD) && (request == PTRACE_SUNATTACH)) - || (!(current->personality & PER_BSD) && (request == PTRACE_ATTACH))) { + if ((current->personality == PER_SUNOS && request == PTRACE_SUNATTACH) + || (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) { unsigned long flags; if(child == current) { @@ -349,9 +349,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) pt_succ_return(regs, 0); goto out; } - if (!(child->flags & PF_PTRACED) - && ((current->personality & PER_BSD) && (request != PTRACE_SUNATTACH)) - && (!(current->personality & PER_BSD) && (request != PTRACE_ATTACH))) { + if (!(child->flags & PF_PTRACED)) { pt_error_return(regs, ESRCH); goto out; } diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c index 484ffac82..0af0b63d7 100644 --- a/arch/sparc/kernel/signal.c +++ b/arch/sparc/kernel/signal.c @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.101 2000/01/21 11:38:38 jj Exp $ +/* $Id: signal.c,v 1.102 2000/04/08 02:11:36 davem Exp $ * linux/arch/sparc/kernel/signal.c * * Copyright (C) 1991, 1992 Linus Torvalds diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c index b589712aa..ac9caa27f 100644 --- a/arch/sparc/kernel/sun4d_smp.c +++ b/arch/sparc/kernel/sun4d_smp.c @@ -8,7 +8,6 @@ #include <asm/head.h> -#include <linux/config.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/threads.h> @@ -443,38 +442,14 @@ void smp4d_message_pass(int target, int msg, unsigned long data, int wait) panic("Bogon SMP message pass."); } -/* Protects counters touched during level14 ticker */ -static spinlock_t ticker_lock = SPIN_LOCK_UNLOCKED; - -#ifdef CONFIG_PROFILE - -/* 32-bit Sparc specific profiling function. */ -static inline void sparc_do_profile(unsigned long pc) -{ - if(prof_buffer && current->pid) { - extern int _stext; - - pc -= (unsigned long) &_stext; - pc >>= prof_shift; - - spin_lock(&ticker_lock); - if(pc < prof_len) - prof_buffer[pc]++; - else - prof_buffer[prof_len - 1]++; - spin_unlock(&ticker_lock); - } -} - -#endif - extern unsigned int prof_multiplier[NR_CPUS]; extern unsigned int prof_counter[NR_CPUS]; extern void update_one_process(struct task_struct *p, unsigned long ticks, unsigned long user, unsigned long system, int cpu); - + +extern void sparc_do_profile(unsigned long pc, unsigned long o7); void smp4d_percpu_timer_interrupt(struct pt_regs *regs) { @@ -493,12 +468,13 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs) show_leds(cpu); } -#ifdef CONFIG_PROFILE if(!user_mode(regs)) - sparc_do_profile(regs->pc); -#endif + sparc_do_profile(regs->pc, regs->u_regs[UREG_RETPC]); + if(!--prof_counter[cpu]) { int user = user_mode(regs); + + irq_enter(cpu, 0); if(current->pid) { update_one_process(current, 1, user, !user, cpu); @@ -507,7 +483,6 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs) current->need_resched = 1; } - spin_lock(&ticker_lock); if(user) { if(current->priority < DEF_PRIORITY) { kstat.cpu_nice++; @@ -520,9 +495,9 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs) kstat.cpu_system++; kstat.per_cpu_system[cpu]++; } - spin_unlock(&ticker_lock); } prof_counter[cpu] = prof_multiplier[cpu]; + irq_exit(cpu, 0); } } diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c index 36c3d3c25..f0e046db3 100644 --- a/arch/sparc/kernel/sun4m_smp.c +++ b/arch/sparc/kernel/sun4m_smp.c @@ -440,27 +440,6 @@ void smp4m_cross_call_irq(void) ccall_info.processors_out[i] = 1; } -/* Protects counters touched during level14 ticker */ -static spinlock_t ticker_lock = SPIN_LOCK_UNLOCKED; - -/* 32-bit Sparc specific profiling function. */ -static inline void sparc_do_profile(unsigned long pc) -{ - if(prof_buffer && current->pid) { - extern int _stext; - - pc -= (unsigned long) &_stext; - pc >>= prof_shift; - - spin_lock(&ticker_lock); - if(pc < prof_len) - prof_buffer[pc]++; - else - prof_buffer[prof_len - 1]++; - spin_unlock(&ticker_lock); - } -} - extern unsigned int prof_multiplier[NR_CPUS]; extern unsigned int prof_counter[NR_CPUS]; @@ -468,6 +447,8 @@ extern void update_one_process(struct task_struct *p, unsigned long ticks, unsigned long user, unsigned long system, int cpu); +extern void sparc_do_profile(unsigned long pc, unsigned long o7); + void smp4m_percpu_timer_interrupt(struct pt_regs *regs) { int cpu = smp_processor_id(); @@ -475,7 +456,7 @@ void smp4m_percpu_timer_interrupt(struct pt_regs *regs) clear_profile_irq(mid_xlate[cpu]); if(!user_mode(regs)) - sparc_do_profile(regs->pc); + sparc_do_profile(regs->pc, regs->u_regs[UREG_RETPC]); if(!--prof_counter[cpu]) { int user = user_mode(regs); diff --git a/arch/sparc/kernel/sys_solaris.c b/arch/sparc/kernel/sys_solaris.c index eb79c344c..d099c4e8a 100644 --- a/arch/sparc/kernel/sys_solaris.c +++ b/arch/sparc/kernel/sys_solaris.c @@ -23,9 +23,7 @@ do_solaris_syscall (struct pt_regs *regs) int ret; lock_kernel(); - put_exec_domain(current->exec_domain); - current->personality = PER_SVR4; - current->exec_domain = lookup_exec_domain(PER_SVR4); + set_personality(PER_SVR4); if (current->exec_domain && current->exec_domain->handler){ current->exec_domain->handler (0, regs); diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c index 36670ab93..bb2c4b472 100644 --- a/arch/sparc/kernel/sys_sunos.c +++ b/arch/sparc/kernel/sys_sunos.c @@ -1,4 +1,4 @@ -/* $Id: sys_sunos.c,v 1.118 2000/03/26 11:28:56 davem Exp $ +/* $Id: sys_sunos.c,v 1.121 2000/04/13 00:55:48 davem Exp $ * sys_sunos.c: SunOS specific syscall compatibility support. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -50,6 +50,7 @@ #include <linux/socket.h> #include <linux/in.h> #include <linux/nfs.h> +#include <linux/nfs2.h> #include <linux/nfs_mount.h> /* for sunos_select */ @@ -69,7 +70,6 @@ asmlinkage unsigned long sunos_mmap(unsigned long addr, unsigned long len, down(¤t->mm->mmap_sem); lock_kernel(); - current->personality |= PER_BSD; if(flags & MAP_NORESERVE) { static int cnt; if (cnt++ < 10) @@ -170,7 +170,7 @@ asmlinkage int sunos_brk(unsigned long brk) */ if (brk <= current->mm->brk) { current->mm->brk = brk; - do_munmap(newbrk, oldbrk-newbrk); + do_munmap(current->mm, newbrk, oldbrk-newbrk); goto out; } /* @@ -582,7 +582,6 @@ asmlinkage int sunos_select(int width, fd_set *inp, fd_set *outp, fd_set *exp, s /* SunOS binaries expect that select won't change the tvp contents */ lock_kernel(); - current->personality |= STICKY_TIMEOUTS; ret = sys_select (width, inp, outp, exp, tvp); if (ret == -EINTR && tvp) { time_t sec, usec; @@ -712,7 +711,7 @@ static int sunos_nfs_mount(char *dir_name, int linux_flags, void *data) * address to create a socket and bind it to a reserved * port on this system */ - if (copy_from_user(&sunos_mount, data, sizeof(sunos_mount)) + if (copy_from_user(&sunos_mount, data, sizeof(sunos_mount))) return -EFAULT; server_fd = sys_socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); @@ -803,14 +802,14 @@ sunos_mount(char *type, char *dir, int flags, void *data) dev_fname = getname(data); } else if(strcmp(type_page, "nfs") == 0) { ret = sunos_nfs_mount (dir_page, flags, data); - goto out2 + goto out2; } else if(strcmp(type_page, "ufs") == 0) { printk("Warning: UFS filesystem mounts unsupported.\n"); ret = -ENODEV; - goto out2 + goto out2; } else if(strcmp(type_page, "proc")) { ret = -ENODEV; - goto out2 + goto out2; } ret = PTR_ERR(dev_fname); if (IS_ERR(dev_fname)) @@ -1054,18 +1053,6 @@ asmlinkage int sunos_shmsys(int op, unsigned long arg1, unsigned long arg2, return rval; } -asmlinkage int sunos_open(const char *filename, int flags, int mode) -{ - int ret; - - lock_kernel(); - current->personality |= PER_BSD; - ret = sys_open (filename, flags, mode); - unlock_kernel(); - return ret; -} - - #define SUNOS_EWOULDBLOCK 35 /* see the sunos man page read(2v) for an explanation @@ -1200,8 +1187,6 @@ sunos_sigaction(int sig, const struct old_sigaction *act, struct k_sigaction new_ka, old_ka; int ret; - current->personality |= PER_BSD; - if(act) { old_sigset_t mask; diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S index 431f03daf..5bb551a46 100644 --- a/arch/sparc/kernel/systbls.S +++ b/arch/sparc/kernel/systbls.S @@ -1,4 +1,4 @@ -/* $Id: systbls.S,v 1.96 2000/03/15 02:43:32 davem Exp $ +/* $Id: systbls.S,v 1.97 2000/04/13 00:55:49 davem Exp $ * systbls.S: System call entry point tables for OS compatibility. * The native Linux system call table lives here also. * @@ -79,7 +79,7 @@ sys_call_table: .globl sunos_sys_table sunos_sys_table: /*0*/ .long sunos_indir, sys_exit, sys_fork - .long sunos_read, sunos_write, sunos_open + .long sunos_read, sunos_write, sys_open .long sys_close, sunos_wait4, sys_creat .long sys_link, sys_unlink, sunos_execv .long sys_chdir, sunos_nosys, sys_mknod diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c index 5a03e646b..68105c421 100644 --- a/arch/sparc/kernel/time.c +++ b/arch/sparc/kernel/time.c @@ -1,4 +1,4 @@ -/* $Id: time.c,v 1.53 2000/02/09 21:11:04 davem Exp $ +/* $Id: time.c,v 1.54 2000/04/13 08:14:30 anton Exp $ * linux/arch/sparc/kernel/time.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -70,6 +70,37 @@ struct intersil *intersil_clock; #endif +static spinlock_t ticker_lock = SPIN_LOCK_UNLOCKED; + +/* 32-bit Sparc specific profiling function. */ +void sparc_do_profile(unsigned long pc, unsigned long o7) +{ + if(prof_buffer && current->pid) { + extern int _stext; + extern int __copy_user_begin, __copy_user_end; + extern int __atomic_begin, __atomic_end; + extern int __bitops_begin, __bitops_end; + + if ((pc >= (unsigned long) &__copy_user_begin && + pc < (unsigned long) &__copy_user_end) || + (pc >= (unsigned long) &__atomic_begin && + pc < (unsigned long) &__atomic_end) || + (pc >= (unsigned long) &__bitops_begin && + pc < (unsigned long) &__bitops_end)) + pc = o7; + + pc -= (unsigned long) &_stext; + pc >>= prof_shift; + + spin_lock(&ticker_lock); + if(pc < prof_len) + prof_buffer[pc]++; + else + prof_buffer[prof_len - 1]++; + spin_unlock(&ticker_lock); + } +} + __volatile__ unsigned int *master_l10_counter; __volatile__ unsigned int *master_l10_limit; @@ -82,6 +113,11 @@ void timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) /* last time the cmos clock got updated */ static long last_rtc_update=0; +#ifndef __SMP__ + if(!user_mode(regs)) + sparc_do_profile(regs->pc, regs->u_regs[UREG_RETPC]); +#endif + #ifdef CONFIG_SUN4 if((idprom->id_machtype == (SM_SUN4 | SM_4_260)) || (idprom->id_machtype == (SM_SUN4 | SM_4_110))) { diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile index f5e316534..d7b3c7554 100644 --- a/arch/sparc/lib/Makefile +++ b/arch/sparc/lib/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.33 2000/03/16 00:52:07 anton Exp $ +# $Id: Makefile,v 1.34 2000/03/31 04:06:20 davem Exp $ # Makefile for Sparc library files.. # diff --git a/arch/sparc/lib/atomic.S b/arch/sparc/lib/atomic.S index c57e61574..76c4d8164 100644 --- a/arch/sparc/lib/atomic.S +++ b/arch/sparc/lib/atomic.S @@ -10,6 +10,9 @@ .text .align 4 + .globl __atomic_begin +__atomic_begin: + #ifndef __SMP__ .globl ___xchg32_sun4c ___xchg32_sun4c: @@ -92,3 +95,6 @@ ___atomic_sub: nop; nop; nop; ! Let the bits set jmpl %o7, %g0 ! NOTE: not + 8, see callers in atomic.h mov %g4, %o7 ! Restore %o7 + + .globl __atomic_end +__atomic_end: diff --git a/arch/sparc/lib/bitops.S b/arch/sparc/lib/bitops.S index ea9ed5a6c..10fc42738 100644 --- a/arch/sparc/lib/bitops.S +++ b/arch/sparc/lib/bitops.S @@ -10,6 +10,9 @@ .text .align 4 + .globl __bitops_begin +__bitops_begin: + /* Take bits in %g2 and set them in word at %g1, * return whether bits were set in original value * in %g2. %g4 holds value to restore into %o7 @@ -159,3 +162,6 @@ ___clear_le_bit: nop; nop; nop jmpl %o7, %g0 mov %g4, %o7 + + .globl __bitops_end +__bitops_end: diff --git a/arch/sparc/lib/copy_user.S b/arch/sparc/lib/copy_user.S index 97c55f02d..239ec762d 100644 --- a/arch/sparc/lib/copy_user.S +++ b/arch/sparc/lib/copy_user.S @@ -112,6 +112,9 @@ .text .align 4 + .globl __copy_user_begin +__copy_user_begin: + .globl C_LABEL(__copy_user) dword_align: andcc %o1, 1, %g0 @@ -482,3 +485,6 @@ fixupretl: sub %o0, %g3, %o0 ba fixupretl add %g3, %o2, %g3 + + .globl __copy_user_end +__copy_user_end: diff --git a/arch/sparc/mm/Makefile b/arch/sparc/mm/Makefile index 440e4fc61..82bfaf6bf 100644 --- a/arch/sparc/mm/Makefile +++ b/arch/sparc/mm/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.36 2000/01/29 01:09:05 anton Exp $ +# $Id: Makefile,v 1.37 2000/03/31 04:06:22 davem Exp $ # Makefile for the linux Sparc-specific parts of the memory manager. # # Note! Dependencies are done automagically by 'make dep', which also diff --git a/arch/sparc/mm/fault.c b/arch/sparc/mm/fault.c index 909c46447..a2af935cb 100644 --- a/arch/sparc/mm/fault.c +++ b/arch/sparc/mm/fault.c @@ -1,4 +1,4 @@ -/* $Id: fault.c,v 1.114 2000/02/14 04:52:36 jj Exp $ +/* $Id: fault.c,v 1.115 2000/04/25 04:13:25 davem Exp $ * fault.c: Page fault handlers for the Sparc. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -250,7 +250,7 @@ good_area: * the fault. */ { - int fault = handle_mm_fault(tsk, vma, address, write); + int fault = handle_mm_fault(mm, vma, address, write); if (fault < 0) goto out_of_memory; if (!fault) @@ -450,7 +450,7 @@ good_area: if(!(vma->vm_flags & (VM_READ | VM_EXEC))) goto bad_area; } - if (!handle_mm_fault(current, vma, address, write)) + if (!handle_mm_fault(mm, vma, address, write)) goto do_sigbus; up(&mm->mmap_sem); return; diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c index 3c8b079c3..24fc68c5a 100644 --- a/arch/sparc/mm/sun4c.c +++ b/arch/sparc/mm/sun4c.c @@ -1,4 +1,4 @@ -/* $Id: sun4c.c,v 1.190 2000/02/14 04:52:34 jj Exp $ +/* $Id: sun4c.c,v 1.191 2000/04/08 02:11:41 davem Exp $ * sun4c.c: Doing in software what should be done in hardware. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) diff --git a/arch/sparc64/config.in b/arch/sparc64/config.in index 27e5549c0..3ec14ec5c 100644 --- a/arch/sparc64/config.in +++ b/arch/sparc64/config.in @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.107 2000/03/29 11:56:51 davem Exp $ +# $Id: config.in,v 1.108 2000/04/18 05:20:45 davem Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -187,6 +187,7 @@ if [ "$CONFIG_SCSI" != "n" ]; then fi fi dep_tristate 'Qlogic ISP SCSI support' CONFIG_SCSI_QLOGIC_ISP $CONFIG_SCSI + dep_tristate 'Qlogic ISP FC SCSI support' CONFIG_SCSI_QLOGIC_FC $CONFIG_SCSI fi endmenu diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig index 2f9febcbe..f969b1b5e 100644 --- a/arch/sparc64/defconfig +++ b/arch/sparc64/defconfig @@ -223,8 +223,8 @@ CONFIG_BLK_DEV_IDEDMA=y CONFIG_IDEDMA_PCI_EXPERIMENTAL=y # CONFIG_IDEDMA_PCI_WIP is not set # CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set -# CONFIG_BLK_DEV_AEC6210 is not set -# CONFIG_AEC6210_TUNING is not set +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_AEC62XX_TUNING is not set # CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_WDC_ALI15X3 is not set # CONFIG_BLK_DEV_AMD7409 is not set @@ -246,6 +246,7 @@ CONFIG_BLK_DEV_NS87415=y # CONFIG_BLK_DEV_SIS5513 is not set # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_VIA82CXXX_TUNING is not set # CONFIG_IDE_CHIPSETS is not set CONFIG_IDEDMA_AUTO=y CONFIG_BLK_DEV_IDE_MODES=y @@ -293,6 +294,7 @@ CONFIG_SCSI_NCR53C8XX_SYNC=10 # CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set # CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set CONFIG_SCSI_QLOGIC_ISP=y +CONFIG_SCSI_QLOGIC_FC=m # # Fibre Channel support @@ -370,6 +372,7 @@ CONFIG_VIDEO_DEV=y CONFIG_AUTOFS_FS=m CONFIG_AUTOFS4_FS=m # CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set CONFIG_AFFS_FS=m # CONFIG_HFS_FS is not set CONFIG_BFS_FS=m @@ -379,47 +382,52 @@ CONFIG_MSDOS_FS=m CONFIG_VFAT_FS=m CONFIG_EFS_FS=m CONFIG_CRAMFS=m +CONFIG_RAMFS=m CONFIG_ISO9660_FS=m -# CONFIG_JOLIET is not set +CONFIG_JOLIET=y CONFIG_MINIX_FS=m # CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set CONFIG_HPFS_FS=m CONFIG_PROC_FS=y # CONFIG_DEVFS_FS is not set # CONFIG_DEVFS_DEBUG is not set CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set CONFIG_ROMFS_FS=m CONFIG_EXT2_FS=y CONFIG_SYSV_FS=m -# CONFIG_SYSV_FS_WRITE is not set +CONFIG_SYSV_FS_WRITE=y CONFIG_UDF_FS=m -# CONFIG_UDF_RW is not set +CONFIG_UDF_RW=y CONFIG_UFS_FS=m -# CONFIG_UFS_FS_WRITE is not set +CONFIG_UFS_FS_WRITE=y # # Network File Systems # CONFIG_CODA_FS=m CONFIG_NFS_FS=y +CONFIG_NFS_V3=y # CONFIG_ROOT_NFS is not set CONFIG_NFSD=m -# CONFIG_NFSD_V3 is not set +CONFIG_NFSD_V3=y CONFIG_SUNRPC=y CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y CONFIG_SMB_FS=m CONFIG_NCP_FS=m -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_MOUNT_SUBDIR is not set -# CONFIG_NCPFS_NDS_DOMAINS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set +CONFIG_NCPFS_PACKET_SIGNING=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_STRONG=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_OS2_NS=y +CONFIG_NCPFS_SMALLDOS=y +CONFIG_NCPFS_MOUNT_SUBDIR=y +CONFIG_NCPFS_NDS_DOMAINS=y +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_EXTRAS=y # # Partition Types diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index 5e37c94b4..5c0d38d0d 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.52 2000/03/19 07:00:29 ecd Exp $ +# $Id: Makefile,v 1.53 2000/03/31 04:06:22 davem Exp $ # Makefile for the linux kernel. # # Note! Dependencies are done automagically by 'make dep', which also diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c index c72f7272f..9cc240293 100644 --- a/arch/sparc64/kernel/binfmt_aout32.c +++ b/arch/sparc64/kernel/binfmt_aout32.c @@ -198,7 +198,6 @@ static u32 *create_aout32_tables(char * p, struct linux_binprm * bprm) static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs) { struct exec ex; - int fd; unsigned long error; unsigned long fd_offset; unsigned long rlim; @@ -230,7 +229,7 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs) return retval; /* OK, This is the point of no return */ - current->personality = PER_LINUX; + set_personality(PER_SUNOS); current->mm->end_code = ex.a_text + (current->mm->start_code = N_TXTADDR(ex)); @@ -270,15 +269,8 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs) error_time = jiffies; } - fd = get_unused_fd(); - if (fd < 0) - return fd; - get_file(bprm->file); - fd_install(fd, bprm->file); - if (!bprm->file->f_op->mmap) { loff_t pos = fd_offset; - sys_close(fd); do_brk(0, ex.a_text+ex.a_data); bprm->file->f_op->read(bprm->file,(char *)N_TXTADDR(ex), ex.a_text+ex.a_data, &pos); @@ -291,7 +283,6 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs) fd_offset); if (error != N_TXTADDR(ex)) { - sys_close(fd); send_sig(SIGKILL, current, 0); return error; } @@ -300,20 +291,13 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs) PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, fd_offset + ex.a_text); - sys_close(fd); if (error != N_DATADDR(ex)) { send_sig(SIGKILL, current, 0); return error; } } beyond_if: - put_exec_domain(current->exec_domain); - if (current->binfmt && current->binfmt->module) - __MOD_DEC_USE_COUNT(current->binfmt->module); - current->exec_domain = lookup_exec_domain(current->personality); - current->binfmt = &aout32_format; - if (current->binfmt && current->binfmt->module) - __MOD_INC_USE_COUNT(current->binfmt->module); + set_binfmt(&aout32_format); set_brk(current->mm->start_brk, current->mm->brk); diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c index ef07fca85..c7e2fecfb 100644 --- a/arch/sparc64/kernel/ioctl32.c +++ b/arch/sparc64/kernel/ioctl32.c @@ -1,4 +1,4 @@ -/* $Id: ioctl32.c,v 1.87 2000/03/30 02:09:07 davem Exp $ +/* $Id: ioctl32.c,v 1.88 2000/04/14 10:10:34 davem Exp $ * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) @@ -1816,6 +1816,7 @@ struct atm_iobuf32 { #define ATM_GETSTATZ32 _IOW('a', ATMIOC_SARCOM+1, struct atmif_sioc32) #define ATM_GETLOOP32 _IOW('a', ATMIOC_SARCOM+2, struct atmif_sioc32) #define ATM_SETLOOP32 _IOW('a', ATMIOC_SARCOM+3, struct atmif_sioc32) +#define ATM_QUERYLOOP32 _IOW('a', ATMIOC_SARCOM+4, struct atmif_sioc32) static struct { unsigned int cmd32; @@ -1836,7 +1837,8 @@ static struct { { ATM_GETSTAT32, ATM_GETSTAT }, { ATM_GETSTATZ32, ATM_GETSTATZ }, { ATM_GETLOOP32, ATM_GETLOOP }, - { ATM_SETLOOP32, ATM_SETLOOP } + { ATM_SETLOOP32, ATM_SETLOOP }, + { ATM_QUERYLOOP32, ATM_QUERYLOOP } }; #define NR_ATM_IOCTL (sizeof(atm_ioctl_map)/sizeof(atm_ioctl_map[0])) @@ -1996,6 +1998,7 @@ static int do_atm_ioctl(unsigned int fd, unsigned int cmd32, unsigned long arg) case ATM_GETSTATZ: case ATM_GETLOOP: case ATM_SETLOOP: + case ATM_QUERYLOOP: return do_atmif_sioc(fd, cmd, arg); } @@ -3110,6 +3113,7 @@ HANDLE_IOCTL(ATM_GETSTAT32, do_atm_ioctl) HANDLE_IOCTL(ATM_GETSTATZ32, do_atm_ioctl) HANDLE_IOCTL(ATM_GETLOOP32, do_atm_ioctl) HANDLE_IOCTL(ATM_SETLOOP32, do_atm_ioctl) +HANDLE_IOCTL(ATM_QUERYLOOP32, do_atm_ioctl) HANDLE_IOCTL(SONET_GETSTAT, do_atm_ioctl) HANDLE_IOCTL(SONET_GETSTATZ, do_atm_ioctl) HANDLE_IOCTL(SONET_GETDIAG, do_atm_ioctl) diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index d2bc6baf5..6bb01d4c1 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.85 2000/03/02 02:00:24 davem Exp $ +/* $Id: irq.c,v 1.86 2000/04/15 06:02:50 davem Exp $ * irq.c: UltraSparc IRQ handling/init/registry. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -538,82 +538,43 @@ out: } /* Only uniprocessor needs this IRQ/BH locking depth, on SMP it - * lives in the per-cpu structure for cache reasons. + * lives in the brlock table for cache reasons. */ #ifndef __SMP__ unsigned int local_irq_count; unsigned int local_bh_count; - -#define irq_enter(cpu, irq) (local_irq_count++) -#define irq_exit(cpu, irq) (local_irq_count--) #else /* Who has global_irq_lock. */ unsigned char global_irq_holder = NO_PROC_ID; -/* This protects IRQ's. */ -spinlock_t global_irq_lock = SPIN_LOCK_UNLOCKED; - -/* Global IRQ locking depth. */ -atomic_t global_irq_count = ATOMIC_INIT(0); - -#define irq_enter(cpu, irq) \ -do { hardirq_enter(cpu); \ - spin_unlock_wait(&global_irq_lock); \ -} while(0) -#define irq_exit(cpu, irq) hardirq_exit(cpu) - static void show(char * str) { int cpu = smp_processor_id(); + int i; printk("\n%s, CPU %d:\n", str, cpu); - printk("irq: %d [%u %u]\n", - atomic_read(&global_irq_count), - cpu_data[0].irq_count, cpu_data[1].irq_count); - printk("bh: %d [%u %u]\n", - (spin_is_locked(&global_bh_lock) ? 1 : 0), - cpu_data[0].bh_count, cpu_data[1].bh_count); + printk("irq: %d [ ", irqs_running()); + for (i = 0; i < smp_num_cpus; i++) + printk("%u ", __brlock_array[i][BR_GLOBALIRQ_LOCK]); + printk("]\nbh: %d [ ", + (spin_is_locked(&global_bh_lock) ? 1 : 0)); + for (i = 0; i < smp_num_cpus; i++) + printk("%u ", cpu_data[i].bh_count); + printk("]\n"); } #define MAXCOUNT 100000000 +#if 0 #define SYNC_OTHER_ULTRAS(x) udelay(x+1) - -static inline void wait_on_irq(int cpu) -{ - int count = MAXCOUNT; - for(;;) { - membar("#LoadLoad"); - if (!atomic_read (&global_irq_count)) { - if (local_bh_count || ! spin_is_locked(&global_bh_lock)) - break; - } - spin_unlock (&global_irq_lock); - membar("#StoreLoad | #StoreStore"); - for(;;) { - if (!--count) { - show("wait_on_irq"); - count = ~0; - } - __sti(); - SYNC_OTHER_ULTRAS(cpu); - __cli(); - if (atomic_read(&global_irq_count)) - continue; - if (spin_is_locked (&global_irq_lock)) - continue; - if (!local_bh_count && spin_is_locked (&global_bh_lock)) - continue; - if (spin_trylock(&global_irq_lock)) - break; - } - } -} +#else +#define SYNC_OTHER_ULTRAS(x) membar("#Sync"); +#endif void synchronize_irq(void) { - if (atomic_read(&global_irq_count)) { + if (irqs_running()) { cli(); sti(); } @@ -621,15 +582,37 @@ void synchronize_irq(void) static inline void get_irqlock(int cpu) { - if (! spin_trylock(&global_irq_lock)) { - if ((unsigned char) cpu == global_irq_holder) - return; - do { - while (spin_is_locked (&global_irq_lock)) - membar("#LoadLoad"); - } while(! spin_trylock(&global_irq_lock)); + int count; + + if ((unsigned char)cpu == global_irq_holder) + return; + + count = MAXCOUNT; +again: + br_write_lock(BR_GLOBALIRQ_LOCK); + for (;;) { + spinlock_t *lock; + + if (!irqs_running() && + (local_bh_count || !spin_is_locked(&global_bh_lock))) + break; + + br_write_unlock(BR_GLOBALIRQ_LOCK); + lock = &__br_write_locks[BR_GLOBALIRQ_LOCK].lock; + while (irqs_running() || + spin_is_locked(lock) || + (!local_bh_count && spin_is_locked(&global_bh_lock))) { + if (!--count) { + show("wait_on_irq"); + count = (~0 >> 1); + } + __sti(); + SYNC_OTHER_ULTRAS(cpu); + __cli(); + } + goto again; } - wait_on_irq(cpu); + global_irq_holder = cpu; } diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c index 98b41d079..5cd905244 100644 --- a/arch/sparc64/kernel/pci_common.c +++ b/arch/sparc64/kernel/pci_common.c @@ -1,4 +1,4 @@ -/* $Id: pci_common.c,v 1.7 2000/03/25 05:18:11 davem Exp $ +/* $Id: pci_common.c,v 1.11 2000/04/26 10:48:02 davem Exp $ * pci_common.c: PCI controller common support. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -66,6 +66,27 @@ static void pci_device_delete(struct pci_dev *pdev) kfree(pdev); } +/* Older versions of OBP on PCI systems encode 64-bit MEM + * space assignments incorrectly, this fixes them up. + */ +static void __init fixup_obp_assignments(struct pcidev_cookie *pcp) +{ + int i; + + for (i = 0; i < pcp->num_prom_assignments; i++) { + struct linux_prom_pci_registers *ap; + int space; + + ap = &pcp->prom_assignments[i]; + space = ap->phys_hi >> 24; + if ((space & 0x3) == 2 && + (space & 0x4) != 0) { + ap->phys_hi &= ~(0x7 << 24); + ap->phys_hi |= 0x3 << 24; + } + } +} + /* Fill in the PCI device cookie sysdata for the given * PCI device. This cookie is the means by which one * can get to OBP and PCI controller specific information @@ -147,6 +168,8 @@ static void __init pdev_cookie_fillin(struct pci_pbm_info *pbm, (err / sizeof(pcp->prom_assignments[0])); } + fixup_obp_assignments(pcp); + pdev->sysdata = pcp; } @@ -219,10 +242,15 @@ __init get_root_resource(struct linux_prom_pci_registers *ap, return &pbm->mem_space; case 3: + /* 64-bit MEM space, these are allocated out of + * the 32-bit mem_space range for the PBM, ie. + * we just zero out the upper 32-bits. + */ + return &pbm->mem_space; + default: - /* 64-bit MEM space, unsupported. */ - printk("PCI: 64-bit MEM assignment??? " - "Tell davem@redhat.com about it!\n"); + printk("PCI: What is resource space %x? " + "Tell davem@redhat.com about it!\n", space); return NULL; }; } @@ -231,6 +259,7 @@ static struct resource * __init get_device_resource(struct linux_prom_pci_registers *ap, struct pci_dev *pdev) { + struct resource *res; int breg = (ap->phys_hi & 0xff); int space = (ap->phys_hi >> 24) & 3; @@ -240,7 +269,8 @@ __init get_device_resource(struct linux_prom_pci_registers *ap, if (space != 2) bad_assignment(ap, NULL, 0); - return &pdev->resource[PCI_ROM_RESOURCE]; + res = &pdev->resource[PCI_ROM_RESOURCE]; + break; case PCI_BASE_ADDRESS_0: case PCI_BASE_ADDRESS_1: @@ -248,12 +278,16 @@ __init get_device_resource(struct linux_prom_pci_registers *ap, case PCI_BASE_ADDRESS_3: case PCI_BASE_ADDRESS_4: case PCI_BASE_ADDRESS_5: - return &pdev->resource[(breg - PCI_BASE_ADDRESS_0) / 4]; + res = &pdev->resource[(breg - PCI_BASE_ADDRESS_0) / 4]; + break; default: bad_assignment(ap, NULL, 0); - return NULL; + res = NULL; + break; }; + + return res; } static void __init pdev_record_assignments(struct pci_pbm_info *pbm, @@ -281,6 +315,31 @@ static void __init pdev_record_assignments(struct pci_pbm_info *pbm, if ((res->start & 0xffffffffUL) != ap->phys_lo) bad_assignment(ap, res, 1); + /* If it is a 64-bit MEM space assignment, verify that + * the resource is too and that the upper 32-bits match. + */ + if (((ap->phys_hi >> 24) & 3) == 3) { + if (((res->flags & IORESOURCE_MEM) == 0) || + ((res->flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) + != PCI_BASE_ADDRESS_MEM_TYPE_64)) + bad_assignment(ap, res, 1); + if ((res->start >> 32) != ap->phys_mid) + bad_assignment(ap, res, 1); + + /* PBM cannot generate cpu initiated PIOs + * to the full 64-bit space. Therefore the + * upper 32-bits better be zero. If it is + * not, just skip it and we will assign it + * properly ourselves. + */ + if ((res->start >> 32) != 0UL) { + printk(KERN_ERR "PCI: OBP assigns out of range MEM address " + "%016lx for region %ld on device %s\n", + res->start, (res - &pdev->resource[0]), pdev->name); + continue; + } + } + /* Adjust the resource into the physical address space * of this PBM. */ @@ -425,13 +484,21 @@ static int __init pci_intmap_match(struct pci_dev *pdev, unsigned int *interrupt return 0; /* If we are underneath a PCI bridge, use PROM register - * property of parent bridge. + * property of the parent bridge which is closest to + * the PBM. */ if (pdev->bus->number != pbm->pci_first_busno) { struct pcidev_cookie *bus_pcp; + struct pci_dev *pwalk; int offset; - bus_pcp = pdev->bus->self->sysdata; + pwalk = pdev->bus->self; + while (pwalk->bus && + pwalk->bus->number != pbm->pci_first_busno) + pwalk = pwalk->bus->self; + + bus_pcp = pwalk->bus->self->sysdata; + pregs = bus_pcp->prom_regs; offset = prom_getint(bus_pcp->prom_node, "fcode-rom-offset"); diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index a45fe4740..8d7db0c9b 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -1,4 +1,4 @@ -/* $Id: pci_psycho.c,v 1.15 2000/03/25 05:18:11 davem Exp $ +/* $Id: pci_psycho.c,v 1.16 2000/04/15 10:06:16 davem Exp $ * pci_psycho.c: PSYCHO/U2P specific PCI controller support. * * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu) @@ -1074,22 +1074,34 @@ static void __init psycho_base_address_update(struct pci_dev *pdev, int resource { struct pcidev_cookie *pcp = pdev->sysdata; struct pci_pbm_info *pbm = pcp->pbm; - struct resource *res = &pdev->resource[resource]; - struct resource *root; + struct resource *res, *root; u32 reg; - int where, size; + int where, size, is_64bit; + res = &pdev->resource[resource]; + where = PCI_BASE_ADDRESS_0 + (resource * 4); + + is_64bit = 0; if (res->flags & IORESOURCE_IO) root = &pbm->io_space; - else + else { root = &pbm->mem_space; + if ((res->flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) + == PCI_BASE_ADDRESS_MEM_TYPE_64) + is_64bit = 1; + } - where = PCI_BASE_ADDRESS_0 + (resource * 4); size = res->end - res->start; pci_read_config_dword(pdev, where, ®); reg = ((reg & size) | (((u32)(res->start - root->start)) & ~size)); pci_write_config_dword(pdev, where, reg); + + /* This knows that the upper 32-bits of the address + * must be zero. Our PCI common layer enforces this. + */ + if (is_64bit) + pci_write_config_dword(pdev, where + 4, 0); } /* We have to do the config space accesses by hand, thus... */ diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index a55772179..99f7ba8ad 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -1,4 +1,4 @@ -/* $Id: pci_sabre.c,v 1.16 2000/03/25 05:18:12 davem Exp $ +/* $Id: pci_sabre.c,v 1.19 2000/04/15 13:07:51 davem Exp $ * pci_sabre.c: Sabre specific PCI controller support. * * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu) @@ -1012,22 +1012,35 @@ static void __init sabre_base_address_update(struct pci_dev *pdev, int resource) struct pcidev_cookie *pcp = pdev->sysdata; struct pci_pbm_info *pbm = pcp->pbm; struct pci_controller_info *p = pbm->parent; - struct resource *res = &pdev->resource[resource]; + struct resource *res; unsigned long base; u32 reg; - int where, size; + int where, size, is_64bit; + res = &pdev->resource[resource]; + where = PCI_BASE_ADDRESS_0 + (resource * 4); + + is_64bit = 0; if (res->flags & IORESOURCE_IO) base = p->controller_regs + SABRE_IOSPACE; - else + else { base = p->controller_regs + SABRE_MEMSPACE; + if ((res->flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) + == PCI_BASE_ADDRESS_MEM_TYPE_64) + is_64bit = 1; + } - where = PCI_BASE_ADDRESS_0 + (resource * 4); size = res->end - res->start; pci_read_config_dword(pdev, where, ®); reg = ((reg & size) | (((u32)(res->start - base)) & ~size)); pci_write_config_dword(pdev, where, reg); + + /* This knows that the upper 32-bits of the address + * must be zero. Our PCI common layer enforces this. + */ + if (is_64bit) + pci_write_config_dword(pdev, where + 4, 0); } static void __init apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus) @@ -1050,6 +1063,20 @@ static void __init apb_init(struct pci_controller_info *p, struct pci_bus *sabre /* Status register bits are "write 1 to clear". */ sabre_write_word(pdev, PCI_STATUS, 0xffff); sabre_write_word(pdev, PCI_SEC_STATUS, 0xffff); + + /* Use a primary/seconday latency timer value + * of 64. + */ + sabre_write_byte(pdev, PCI_LATENCY_TIMER, 64); + sabre_write_byte(pdev, PCI_SEC_LATENCY_TIMER, 64); + + /* Enable reporting/forwarding of master aborts, + * parity, and SERR. + */ + sabre_write_byte(pdev, PCI_BRIDGE_CONTROL, + (PCI_BRIDGE_CTL_PARITY | + PCI_BRIDGE_CTL_SERR | + PCI_BRIDGE_CTL_MASTER_ABORT)); } } } @@ -1086,17 +1113,6 @@ static void __init sabre_scan_bus(struct pci_controller_info *p) sabre_bus = pci_scan_bus(p->pci_first_busno, p->pci_ops, &p->pbm_A); - - { - unsigned int devfn; - u8 *addr; - - devfn = PCI_DEVFN(0, 0); - addr = sabre_pci_config_mkaddr(&p->pbm_A, 0, - devfn, PCI_LATENCY_TIMER); - pci_config_write8(addr, 32); - } - apb_init(p, sabre_bus); walk = &sabre_bus->children; diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c index e612d0200..ccf0c03bf 100644 --- a/arch/sparc64/kernel/power.c +++ b/arch/sparc64/kernel/power.c @@ -1,4 +1,4 @@ -/* $Id: power.c,v 1.5 1999/12/19 23:28:00 davem Exp $ +/* $Id: power.c,v 1.6 2000/04/13 00:59:59 davem Exp $ * power.c: Power management driver. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -55,8 +55,7 @@ static int powerd(void *__unused) static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL }; char *argv[] = { "/usr/bin/shutdown", "-h", "now", NULL }; - current->session = 1; - current->pgrp = 1; + daemonize(); sprintf(current->comm, "powerd"); again: diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 8ac030324..fb0e8f411 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.105 2000/03/26 09:13:48 davem Exp $ +/* $Id: process.c,v 1.106 2000/04/15 06:02:50 davem Exp $ * arch/sparc64/kernel/process.c * * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu) @@ -269,9 +269,8 @@ void __show_regs(struct pt_regs * regs) unsigned long flags; spin_lock_irqsave(®dump_lock, flags); - printk("CPU[%d]: local_irq_count[%u] global_irq_count[%d]\n", - smp_processor_id(), local_irq_count, - atomic_read(&global_irq_count)); + printk("CPU[%d]: local_irq_count[%u] irqs_running[%d]\n", + smp_processor_id(), local_irq_count, irqs_running()); #endif printk("TSTATE: %016lx TPC: %016lx TNPC: %016lx Y: %08x\n", regs->tstate, regs->tpc, regs->tnpc, regs->y); diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c index c582be060..f061c417f 100644 --- a/arch/sparc64/kernel/ptrace.c +++ b/arch/sparc64/kernel/ptrace.c @@ -68,7 +68,7 @@ pt_succ_return_linux(struct pt_regs *regs, unsigned long value, long *addr) static void pt_os_succ_return (struct pt_regs *regs, unsigned long val, long *addr) { - if (current->personality & PER_BSD) + if (current->personality == PER_SUNOS) pt_succ_return (regs, val); else pt_succ_return_linux (regs, val, addr); @@ -164,8 +164,8 @@ asmlinkage void do_ptrace(struct pt_regs *regs) goto out; } - if (((current->personality & PER_BSD) && (request == PTRACE_SUNATTACH)) - || (!(current->personality & PER_BSD) && (request == PTRACE_ATTACH))) { + if ((current->personality == PER_SUNOS && request == PTRACE_SUNATTACH) + || (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) { unsigned long flags; if(child == current) { @@ -203,9 +203,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) pt_succ_return(regs, 0); goto out; } - if (!(child->flags & PF_PTRACED) - && ((current->personality & PER_BSD) && (request != PTRACE_SUNATTACH)) - && (!(current->personality & PER_BSD) && (request != PTRACE_ATTACH))) { + if (!(child->flags & PF_PTRACED)) { pt_error_return(regs, ESRCH); goto out; } diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index c9a0d4a59..602ee9ca2 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -1,4 +1,4 @@ -/* $Id: sbus.c,v 1.10 2000/03/10 07:52:08 davem Exp $ +/* $Id: sbus.c,v 1.11 2000/04/14 09:13:04 davem Exp $ * sbus.c: UltraSparc SBUS controller support. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -315,7 +315,7 @@ void sbus_free_consistent(struct sbus_dev *sdev, size_t size, void *cpu, dma_add dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr, size_t size, int dir) { struct sbus_iommu *iommu = sdev->bus->iommu; - unsigned long npages, phys_base, flags; + unsigned long npages, pbase, flags; iopte_t *iopte; u32 dma_base, offset; unsigned long iopte_bits; @@ -323,10 +323,10 @@ dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr, size_t size, int di if (dir == SBUS_DMA_NONE) BUG(); - phys_base = (unsigned long) ptr; - offset = (u32) (phys_base & ~PAGE_MASK); - size = (PAGE_ALIGN(phys_base + size) - (phys_base & PAGE_MASK)); - phys_base = (unsigned long) __pa(phys_base & PAGE_MASK); + pbase = (unsigned long) ptr; + offset = (u32) (pbase & ~PAGE_MASK); + size = (PAGE_ALIGN(pbase + size) - (pbase & PAGE_MASK)); + pbase = (unsigned long) __pa(pbase & PAGE_MASK); spin_lock_irqsave(&iommu->lock, flags); npages = size >> PAGE_SHIFT; @@ -337,8 +337,8 @@ dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr, size_t size, int di if (dir != SBUS_DMA_TODEVICE) iopte_bits |= IOPTE_WRITE; while (npages--) { - *iopte++ = __iopte(iopte_bits | (phys_base & IOPTE_PAGE)); - phys_base += PAGE_SIZE; + *iopte++ = __iopte(iopte_bits | (pbase & IOPTE_PAGE)); + pbase += PAGE_SIZE; } npages = size >> PAGE_SHIFT; spin_unlock_irqrestore(&iommu->lock, flags); diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c index e7a50c150..efd6a64d1 100644 --- a/arch/sparc64/kernel/signal.c +++ b/arch/sparc64/kernel/signal.c @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.48 1999/12/15 22:24:52 davem Exp $ +/* $Id: signal.c,v 1.49 2000/04/08 02:11:46 davem Exp $ * arch/sparc64/kernel/signal.c * * Copyright (C) 1991, 1992 Linus Torvalds diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c index 423c5f648..1f5c03716 100644 --- a/arch/sparc64/kernel/signal32.c +++ b/arch/sparc64/kernel/signal32.c @@ -1,4 +1,4 @@ -/* $Id: signal32.c,v 1.60 2000/02/25 06:02:37 jj Exp $ +/* $Id: signal32.c,v 1.62 2000/04/12 08:10:19 davem Exp $ * arch/sparc64/kernel/signal32.c * * Copyright (C) 1991, 1992 Linus Torvalds @@ -750,8 +750,7 @@ static inline void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *reg goto sigsegv; if(pte_present(*ptep)) { - unsigned long page = (unsigned long) - __va(pte_pagenr(*ptep) << PAGE_SHIFT); + unsigned long page = page_address(pte_page(*ptep)); __asm__ __volatile__(" membar #StoreStore @@ -1176,8 +1175,7 @@ static inline void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs goto sigsegv; if(pte_present(*ptep)) { - unsigned long page = (unsigned long) - __va(pte_pagenr(*ptep) << PAGE_SHIFT); + unsigned long page = page_address(pte_page(*ptep)); __asm__ __volatile__(" membar #StoreStore diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index e9a180d2a..2ef0d1004 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -87,7 +87,6 @@ void __init smp_store_cpu_info(int id) { int i; - cpu_data[id].irq_count = 0; cpu_data[id].bh_count = 0; /* multiplier and counter set by smp_setup_percpu_timer() */ @@ -627,33 +626,7 @@ void smp_promstop_others(void) smp_cross_call(&xcall_promstop, 0, 0, 0); } -static inline void sparc64_do_profile(unsigned long pc, unsigned long o7) -{ - if (prof_buffer && current->pid) { - extern int _stext; - extern int rwlock_impl_begin, rwlock_impl_end; - extern int atomic_impl_begin, atomic_impl_end; - extern int __memcpy_begin, __memcpy_end; - extern int __bitops_begin, __bitops_end; - - if ((pc >= (unsigned long) &atomic_impl_begin && - pc < (unsigned long) &atomic_impl_end) || - (pc >= (unsigned long) &rwlock_impl_begin && - pc < (unsigned long) &rwlock_impl_end) || - (pc >= (unsigned long) &__memcpy_begin && - pc < (unsigned long) &__memcpy_end) || - (pc >= (unsigned long) &__bitops_begin && - pc < (unsigned long) &__bitops_end)) - pc = o7; - - pc -= (unsigned long) &_stext; - pc >>= prof_shift; - - if(pc >= prof_len) - pc = prof_len - 1; - atomic_inc((atomic_t *)&prof_buffer[pc]); - } -} +extern void sparc64_do_profile(unsigned long pc, unsigned long o7); static unsigned long current_tick_offset; @@ -682,40 +655,29 @@ void smp_percpu_timer_interrupt(struct pt_regs *regs) clear_softint((1UL << 0)); do { - if(!user) + if (!user) sparc64_do_profile(regs->tpc, regs->u_regs[UREG_RETPC]); - if(!--prof_counter(cpu)) - { + if (!--prof_counter(cpu)) { if (cpu == boot_cpu_id) { -/* XXX Keep this in sync with irq.c --DaveM */ -#define irq_enter(cpu, irq) \ -do { hardirq_enter(cpu); \ - spin_unlock_wait(&global_irq_lock); \ -} while(0) -#define irq_exit(cpu, irq) hardirq_exit(cpu) - irq_enter(cpu, 0); - kstat.irqs[cpu][0]++; + kstat.irqs[cpu][0]++; timer_tick_interrupt(regs); irq_exit(cpu, 0); - -#undef irq_enter -#undef irq_exit } - if(current->pid) { + if (current->pid) { unsigned int *inc, *inc2; update_one_process(current, 1, user, !user, cpu); - if(--current->counter <= 0) { + if (--current->counter <= 0) { current->counter = 0; current->need_resched = 1; } - if(user) { - if(current->priority < DEF_PRIORITY) { + if (user) { + if (current->priority < DEF_PRIORITY) { inc = &kstat.cpu_nice; inc2 = &kstat.per_cpu_nice[cpu]; } else { @@ -862,7 +824,7 @@ cycles_t cacheflush_time; static void __init smp_tune_scheduling (void) { - unsigned long flush_base, flags, *p; + unsigned long orig_flush_base, flush_base, flags, *p; unsigned int ecache_size, order; cycles_t tick1, tick2, raw; @@ -881,7 +843,8 @@ static void __init smp_tune_scheduling (void) "ecache-size", (512 * 1024)); if (ecache_size > (4 * 1024 * 1024)) ecache_size = (4 * 1024 * 1024); - flush_base = __get_free_pages(GFP_KERNEL, order = get_order(ecache_size)); + orig_flush_base = flush_base = + __get_free_pages(GFP_KERNEL, order = get_order(ecache_size)); if (flush_base != 0UL) { __save_and_cli(flags); @@ -923,7 +886,7 @@ static void __init smp_tune_scheduling (void) */ cacheflush_time = (raw - (raw >> 2)); - free_pages(flush_base, order); + free_pages(orig_flush_base, order); } else { cacheflush_time = ((ecache_size << 2) + (ecache_size << 1)); diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index fc7a8cfe5..f68d6ee9e 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -1,4 +1,4 @@ -/* $Id: sparc64_ksyms.c,v 1.80 2000/03/27 10:38:47 davem Exp $ +/* $Id: sparc64_ksyms.c,v 1.83 2000/04/19 08:38:25 davem Exp $ * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -81,6 +81,8 @@ extern int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); extern int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg); extern int (*handle_mathemu)(struct pt_regs *, struct fpustate *); extern long sparc32_open(const char * filename, int flags, int mode); +extern int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, unsigned int, unsigned long, struct file *)); +extern int unregister_ioctl32_conversion(unsigned int cmd); extern void bcopy (const char *, char *, int); extern int __ashrdi3(int, int); @@ -129,8 +131,6 @@ EXPORT_SYMBOL(kernel_flag); /* Hard IRQ locking */ EXPORT_SYMBOL(global_irq_holder); -EXPORT_SYMBOL(global_irq_lock); -EXPORT_SYMBOL(global_irq_count); EXPORT_SYMBOL(synchronize_irq); EXPORT_SYMBOL_PRIVATE(global_cli); EXPORT_SYMBOL_PRIVATE(global_sti); @@ -219,6 +219,10 @@ EXPORT_SYMBOL(pci_dma_sync_sg); EXPORT_SYMBOL(pci_dma_supported); #endif +/* IOCTL32 emulation hooks. */ +EXPORT_SYMBOL(register_ioctl32_conversion); +EXPORT_SYMBOL(unregister_ioctl32_conversion); + /* Solaris/SunOS binary compatibility */ EXPORT_SYMBOL(_sigpause_common); @@ -297,8 +301,8 @@ EXPORT_SYMBOL(move_addr_to_user); /* Special internal versions of library functions. */ EXPORT_SYMBOL(__memcpy); EXPORT_SYMBOL(__memset); -EXPORT_SYMBOL(clear_page); -EXPORT_SYMBOL(copy_page); +EXPORT_SYMBOL(_clear_page); +EXPORT_SYMBOL(_copy_page); EXPORT_SYMBOL(clear_user_page); EXPORT_SYMBOL(copy_user_page); EXPORT_SYMBOL(__bzero); diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c index 82aedbb08..16edc28f6 100644 --- a/arch/sparc64/kernel/sys_sparc.c +++ b/arch/sparc64/kernel/sys_sparc.c @@ -1,4 +1,4 @@ -/* $Id: sys_sparc.c,v 1.37 2000/03/17 05:48:46 anton Exp $ +/* $Id: sys_sparc.c,v 1.38 2000/04/13 07:30:34 jj Exp $ * linux/arch/sparc64/kernel/sys_sparc.c * * This file contains various random system calls that @@ -23,6 +23,7 @@ #include <linux/smp_lock.h> #include <linux/malloc.h> #include <linux/ipc.h> +#include <linux/personality.h> #include <asm/uaccess.h> #include <asm/ipc.h> @@ -182,6 +183,33 @@ out: return err; } +extern asmlinkage int sys_newuname(struct new_utsname * name); + +asmlinkage int sparc64_newuname(struct new_utsname * name) +{ + int ret = sys_newuname(name); + + if (current->personality == PER_LINUX32 && !ret) { + ret = copy_to_user(name->machine, "sparc\0\0", 8); + } + return ret; +} + +extern asmlinkage long sys_personality(unsigned long); + +asmlinkage int sparc64_personality(unsigned long personality) +{ + int ret; + lock_kernel(); + if (current->personality == PER_LINUX32 && personality == PER_LINUX) + personality = PER_LINUX32; + ret = sys_personality(personality); + unlock_kernel(); + if (ret == PER_LINUX32) + ret = PER_LINUX; + return ret; +} + /* Linux version of mmap */ asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, @@ -232,7 +260,7 @@ asmlinkage long sys64_munmap(unsigned long addr, size_t len) (addr < PAGE_OFFSET && addr + len > -PAGE_OFFSET)) return -EINVAL; down(¤t->mm->mmap_sem); - ret = do_munmap(addr, len); + ret = do_munmap(current->mm, addr, len); up(¤t->mm->mmap_sem); return ret; } diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index b1eb160ad..7bb75f4ae 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -1,4 +1,4 @@ -/* $Id: sys_sparc32.c,v 1.142 2000/03/24 04:17:38 davem Exp $ +/* $Id: sys_sparc32.c,v 1.145 2000/04/13 07:30:34 jj Exp $ * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -3542,6 +3542,18 @@ struct nfsctl_fhparm32 { s32 gf32_version; }; +struct nfsctl_fdparm32 { + struct sockaddr gd32_addr; + s8 gd32_path[NFS_MAXPATHLEN+1]; + s32 gd32_version; +}; + +struct nfsctl_fsparm32 { + struct sockaddr gd32_addr; + s8 gd32_path[NFS_MAXPATHLEN+1]; + s32 gd32_maxlen; +}; + struct nfsctl_arg32 { s32 ca32_version; /* safeguard */ union { @@ -3550,15 +3562,17 @@ struct nfsctl_arg32 { struct nfsctl_export32 u32_export; struct nfsctl_uidmap32 u32_umap; struct nfsctl_fhparm32 u32_getfh; - u32 u32_debug; + struct nfsctl_fdparm32 u32_getfd; + struct nfsctl_fsparm32 u32_getfs; } u; #define ca32_svc u.u32_svc #define ca32_client u.u32_client #define ca32_export u.u32_export #define ca32_umap u.u32_umap #define ca32_getfh u.u32_getfh +#define ca32_getfd u.u32_getfd +#define ca32_getfs u.u32_getfs #define ca32_authd u.u32_authd -#define ca32_debug u.u32_debug }; union nfsctl_res32 { @@ -3689,6 +3703,38 @@ static int nfs_getfh32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32 return err; } +static int nfs_getfd32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) +{ + int err; + + err = __get_user(karg->ca_version, &arg32->ca32_version); + err |= copy_from_user(&karg->ca_getfd.gd_addr, + &arg32->ca32_getfd.gd32_addr, + (sizeof(struct sockaddr))); + err |= copy_from_user(&karg->ca_getfd.gd_path, + &arg32->ca32_getfd.gd32_path, + (NFS_MAXPATHLEN+1)); + err |= __get_user(karg->ca_getfd.gd_version, + &arg32->ca32_getfd.gd32_version); + return err; +} + +static int nfs_getfs32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) +{ + int err; + + err = __get_user(karg->ca_version, &arg32->ca32_version); + err |= copy_from_user(&karg->ca_getfs.gd_addr, + &arg32->ca32_getfs.gd32_addr, + (sizeof(struct sockaddr))); + err |= copy_from_user(&karg->ca_getfs.gd_path, + &arg32->ca32_getfs.gd32_path, + (NFS_MAXPATHLEN+1)); + err |= __get_user(karg->ca_getfs.gd_maxlen, + &arg32->ca32_getfs.gd32_maxlen); + return err; +} + /* This really doesn't need translations, we are only passing * back a union which contains opaque nfs file handle data. */ @@ -3727,6 +3773,7 @@ int asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsct err = nfs_clnt32_trans(karg, arg32); break; case NFSCTL_EXPORT: + case NFSCTL_UNEXPORT: err = nfs_exp32_trans(karg, arg32); break; /* This one is unimplemented, be we're ready for it. */ @@ -3736,6 +3783,12 @@ int asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsct case NFSCTL_GETFH: err = nfs_getfh32_trans(karg, arg32); break; + case NFSCTL_GETFD: + err = nfs_getfd32_trans(karg, arg32); + break; + case NFSCTL_GETFS: + err = nfs_getfs32_trans(karg, arg32); + break; default: err = -EINVAL; break; @@ -3747,7 +3800,12 @@ int asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsct err = sys_nfsservctl(cmd, karg, kres); set_fs(oldfs); - if(!err && cmd == NFSCTL_GETFH) + if (err) + goto done; + + if((cmd == NFSCTL_GETFH) || + (cmd == NFSCTL_GETFD) || + (cmd == NFSCTL_GETFS)) err = nfs_getfh32_res_trans(kres, res32); done: @@ -3922,18 +3980,6 @@ asmlinkage int sys32_prctl(int option, u32 arg2, u32 arg3, u32 arg4, u32 arg5) } -extern asmlinkage int sys_newuname(struct new_utsname * name); - -asmlinkage int sys32_newuname(struct new_utsname * name) -{ - int ret = sys_newuname(name); - - if (current->personality == PER_LINUX32 && !ret) { - ret = copy_to_user(name->machine, "sparc\0\0", 8); - } - return ret; -} - extern asmlinkage ssize_t sys_pread(unsigned int fd, char * buf, size_t count, loff_t pos); @@ -3955,21 +4001,6 @@ asmlinkage ssize_t32 sys32_pwrite(unsigned int fd, char *ubuf, } -extern asmlinkage long sys_personality(unsigned long); - -asmlinkage int sys32_personality(unsigned long personality) -{ - int ret; - lock_kernel(); - if (current->personality == PER_LINUX32 && personality == PER_LINUX) - personality = PER_LINUX32; - ret = sys_personality(personality); - unlock_kernel(); - if (ret == PER_LINUX32) - ret = PER_LINUX; - return ret; -} - extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count); asmlinkage int sys32_sendfile(int out_fd, int in_fd, __kernel_off_t32 *offset, s32 count) diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c index 291b174ac..1370d0231 100644 --- a/arch/sparc64/kernel/sys_sunos32.c +++ b/arch/sparc64/kernel/sys_sunos32.c @@ -1,4 +1,4 @@ -/* $Id: sys_sunos32.c,v 1.43 2000/03/26 11:28:53 davem Exp $ +/* $Id: sys_sunos32.c,v 1.45 2000/04/13 00:55:49 davem Exp $ * sys_sunos32.c: SunOS binary compatability layer on sparc64. * * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu) @@ -45,6 +45,7 @@ #include <linux/socket.h> #include <linux/in.h> #include <linux/nfs.h> +#include <linux/nfs2.h> #include <linux/nfs_mount.h> /* for sunos_select */ @@ -69,7 +70,6 @@ asmlinkage u32 sunos_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 of down(¤t->mm->mmap_sem); lock_kernel(); - current->personality |= PER_BSD; if(flags & MAP_NORESERVE) { static int cnt; if (cnt++ < 10) @@ -141,7 +141,7 @@ asmlinkage int sunos_brk(u32 baddr) /* Always allow shrinking brk. */ if (brk <= current->mm->brk) { current->mm->brk = brk; - do_munmap(newbrk, oldbrk-newbrk); + do_munmap(current->mm, newbrk, oldbrk-newbrk); goto out; } /* Check against rlimit and stack.. */ @@ -549,7 +549,6 @@ asmlinkage int sunos_select(int width, u32 inp, u32 outp, u32 exp, u32 tvp_x) /* SunOS binaries expect that select won't change the tvp contents */ lock_kernel(); - current->personality |= STICKY_TIMEOUTS; ret = sys32_select (width, inp, outp, exp, tvp_x); if (ret == -EINTR && tvp_x) { struct timeval32 *tvp = (struct timeval32 *)A(tvp_x); @@ -685,7 +684,7 @@ static int sunos_nfs_mount(char *dir_name, int linux_flags, void *data) * address to create a socket and bind it to a reserved * port on this system */ - if (copy_from_user(&sunos_mount, data, sizeof(sunos_mount)) + if (copy_from_user(&sunos_mount, data, sizeof(sunos_mount))) return -EFAULT; server_fd = sys_socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); @@ -776,14 +775,14 @@ sunos_mount(char *type, char *dir, int flags, void *data) dev_fname = getname(data); } else if(strcmp(type_page, "nfs") == 0) { ret = sunos_nfs_mount (dir_page, flags, data); - goto out2 + goto out2; } else if(strcmp(type_page, "ufs") == 0) { printk("Warning: UFS filesystem mounts unsupported.\n"); ret = -ENODEV; - goto out2 + goto out2; } else if(strcmp(type_page, "proc")) { ret = -ENODEV; - goto out2 + goto out2; } ret = PTR_ERR(dev_fname); if (IS_ERR(dev_fname)) @@ -1214,7 +1213,6 @@ asmlinkage int sunos_open(u32 fname, int flags, int mode) { const char *filename = (const char *)(long)fname; - current->personality |= PER_BSD; return sparc32_open(filename, flags, mode); } @@ -1350,8 +1348,6 @@ asmlinkage int sunos_sigaction (int sig, u32 act, u32 oact) struct k_sigaction new_ka, old_ka; int ret; - current->personality |= PER_BSD; - if (act) { old_sigset_t32 mask; diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S index d86649bf7..eb02486f5 100644 --- a/arch/sparc64/kernel/systbls.S +++ b/arch/sparc64/kernel/systbls.S @@ -1,4 +1,4 @@ -/* $Id: systbls.S,v 1.71 2000/03/15 02:43:36 davem Exp $ +/* $Id: systbls.S,v 1.72 2000/04/13 07:30:34 jj Exp $ * systbls.S: System call entry point tables for OS compatibility. * The native Linux system call table lives here also. * @@ -56,8 +56,8 @@ sys_call_table32: /*170*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getdents .word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall /*180*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_sigpending, sys32_query_module - .word sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_newuname -/*190*/ .word sys32_init_module, sys32_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall + .word sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sparc64_newuname +/*190*/ .word sys32_init_module, sparc64_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall .word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys32_sigaction, sys_sgetmask /*200*/ .word sys_ssetmask, sys_sigsuspend, sys32_newlstat, sys_uselib, old32_readdir .word sys_nis_syscall, sys32_socketcall, sys_syslog, sys_nis_syscall, sys_nis_syscall @@ -115,8 +115,8 @@ sys_call_table: /*170*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents .word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall /*180*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_query_module - .word sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_newuname -/*190*/ .word sys_init_module, sys_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall + .word sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sparc64_newuname +/*190*/ .word sys_init_module, sparc64_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall .word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys_nis_syscall, sys_sgetmask /*200*/ .word sys_ssetmask, sys_nis_syscall, sys_newlstat, sys_uselib, sys_nis_syscall .word sys_nis_syscall, sys_socketcall, sys_syslog, sys_nis_syscall, sys_nis_syscall diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index e599b48cb..a955e75df 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -1,4 +1,4 @@ -/* $Id: time.c,v 1.24 2000/03/02 02:00:25 davem Exp $ +/* $Id: time.c,v 1.25 2000/04/13 05:29:44 davem Exp $ * time.c: UltraSparc timer and TOD clock support. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -67,6 +67,34 @@ static __inline__ void timer_check_rtc(void) } } +void sparc64_do_profile(unsigned long pc, unsigned long o7) +{ + if (prof_buffer && current->pid) { + extern int _stext; + extern int rwlock_impl_begin, rwlock_impl_end; + extern int atomic_impl_begin, atomic_impl_end; + extern int __memcpy_begin, __memcpy_end; + extern int __bitops_begin, __bitops_end; + + if ((pc >= (unsigned long) &atomic_impl_begin && + pc < (unsigned long) &atomic_impl_end) || + (pc >= (unsigned long) &rwlock_impl_begin && + pc < (unsigned long) &rwlock_impl_end) || + (pc >= (unsigned long) &__memcpy_begin && + pc < (unsigned long) &__memcpy_end) || + (pc >= (unsigned long) &__bitops_begin && + pc < (unsigned long) &__bitops_end)) + pc = o7; + + pc -= (unsigned long) &_stext; + pc >>= prof_shift; + + if(pc >= prof_len) + pc = prof_len - 1; + atomic_inc((atomic_t *)&prof_buffer[pc]); + } +} + static void timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) { unsigned long ticks, pstate; @@ -74,6 +102,10 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) write_lock(&xtime_lock); do { +#ifndef __SMP__ + if ((regs->tstate & TSTATE_PRIV) != 0) + sparc64_do_profile(regs->tpc, regs->u_regs[UREG_RETPC]); +#endif do_timer(regs); /* Guarentee that the following sequences execute diff --git a/arch/sparc64/lib/Makefile b/arch/sparc64/lib/Makefile index e70e28e52..548ef0ac4 100644 --- a/arch/sparc64/lib/Makefile +++ b/arch/sparc64/lib/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.21 2000/03/27 10:38:41 davem Exp $ +# $Id: Makefile,v 1.22 2000/03/31 04:06:23 davem Exp $ # Makefile for Sparc library files.. # diff --git a/arch/sparc64/lib/blockops.S b/arch/sparc64/lib/blockops.S index 9c6a8beba..9668f86d8 100644 --- a/arch/sparc64/lib/blockops.S +++ b/arch/sparc64/lib/blockops.S @@ -1,4 +1,4 @@ -/* $Id: blockops.S,v 1.24 2000/03/27 10:38:41 davem Exp $ +/* $Id: blockops.S,v 1.25 2000/04/13 04:45:58 davem Exp $ * blockops.S: UltraSparc block zero optimized routines. * * Copyright (C) 1996, 1998, 1999, 2000 David S. Miller (davem@redhat.com) @@ -26,9 +26,9 @@ .text .align 32 - .globl copy_page - .type copy_page,@function -copy_page: /* %o0=dest, %o1=src */ + .globl _copy_page + .type _copy_page,@function +_copy_page: /* %o0=dest, %o1=src */ VISEntry membar #LoadStore | #StoreStore | #StoreLoad ldda [%o1] ASI_BLK_P, %f0 @@ -205,9 +205,9 @@ copy_page_using_blkcommit: stda %f16, [%o0] ASI_BLK_COMMIT_P .align 32 - .globl clear_page - .type clear_page,@function -clear_page: /* %o0=dest */ + .globl _clear_page + .type _clear_page,@function +_clear_page: /* %o0=dest */ VISEntryHalf ba,pt %xcc, clear_page_common clr %o4 diff --git a/arch/sparc64/mm/Makefile b/arch/sparc64/mm/Makefile index 039195944..36b871af5 100644 --- a/arch/sparc64/mm/Makefile +++ b/arch/sparc64/mm/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.6 2000/01/31 01:30:49 davem Exp $ +# $Id: Makefile,v 1.7 2000/03/31 04:06:24 davem Exp $ # Makefile for the linux Sparc64-specific parts of the memory manager. # # Note! Dependencies are done automagically by 'make dep', which also diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c index 0d8152887..37b07d605 100644 --- a/arch/sparc64/mm/fault.c +++ b/arch/sparc64/mm/fault.c @@ -1,4 +1,4 @@ -/* $Id: fault.c,v 1.45 2000/03/27 10:38:51 davem Exp $ +/* $Id: fault.c,v 1.47 2000/04/25 04:13:25 davem Exp $ * arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -110,7 +110,8 @@ static unsigned int get_user_insn(unsigned long tpc) if(!pte_present(pte)) goto out; - pa = (pte_pagenr(pte) << PAGE_SHIFT) + (tpc & ~PAGE_MASK); + pa = phys_base + (pte_pagenr(pte) << PAGE_SHIFT); + pa += (tpc & ~PAGE_MASK); /* Use phys bypass so we don't pollute dtlb/dcache. */ __asm__ __volatile__("lduwa [%1] %2, %0" @@ -295,7 +296,7 @@ good_area: } { - int fault = handle_mm_fault(current, vma, + int fault = handle_mm_fault(mm, vma, address, (fault_code & FAULT_CODE_WRITE)); if (fault < 0) diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 1d2049b5f..bef1c3fac 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.149 2000/03/15 14:42:58 jj Exp $ +/* $Id: init.c,v 1.151 2000/04/26 17:09:32 davem Exp $ * arch/sparc64/mm/init.c * * Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu) @@ -738,22 +738,17 @@ pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long offset) */ pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset, unsigned long color) { - unsigned long paddr = __get_free_pages(GFP_KERNEL, 1); + struct page *page = alloc_pages(GFP_KERNEL, 1); - if (paddr) { - struct page *page2 = mem_map + MAP_NR(paddr + PAGE_SIZE); + if (page) { unsigned long *to_free; + unsigned long paddr; pte_t *pte; - /* Set count of second page, so we can free it - * seperately later on. - */ - atomic_set(&page2->count, 1); - - /* Clear out both pages now. */ + set_page_count((page + 1), 1); + paddr = page_address(page); memset((char *)paddr, 0, (PAGE_SIZE << 1)); - /* Determine which page we give to this request. */ if (!color) { pte = (pte_t *) paddr; to_free = (unsigned long *) (paddr + PAGE_SIZE); @@ -804,50 +799,42 @@ void sparc_ultra_dump_dtlb(void) } } -#undef DEBUG_BOOTMEM - extern unsigned long cmdline_memory_size; -unsigned long __init bootmem_init(void) +unsigned long __init bootmem_init(unsigned long *pages_avail) { unsigned long bootmap_size, start_pfn, end_pfn; unsigned long end_of_phys_memory = 0UL; - unsigned long bootmap_pfn; + unsigned long bootmap_pfn, bytes_avail, size; int i; - /* XXX It is a bit ambiguous here, whether we should - * XXX treat the user specified mem=xxx as total wanted - * XXX physical memory, or as a limit to the upper - * XXX physical address we allow. For now it is the - * XXX latter. -DaveM - */ -#ifdef DEBUG_BOOTMEM - prom_printf("bootmem_init: Scan sp_banks, "); -#endif + + bytes_avail = 0UL; for (i = 0; sp_banks[i].num_bytes != 0; i++) { end_of_phys_memory = sp_banks[i].base_addr + sp_banks[i].num_bytes; + bytes_avail += sp_banks[i].num_bytes; if (cmdline_memory_size) { - if (end_of_phys_memory > cmdline_memory_size) { - if (cmdline_memory_size < sp_banks[i].base_addr) { - end_of_phys_memory = - sp_banks[i-1].base_addr + - sp_banks[i-1].num_bytes; + if (bytes_avail > cmdline_memory_size) { + unsigned long slack = bytes_avail - cmdline_memory_size; + + bytes_avail -= slack; + end_of_phys_memory -= slack; + + sp_banks[i].num_bytes -= slack; + if (sp_banks[i].num_bytes == 0) { sp_banks[i].base_addr = 0xdeadbeef; - sp_banks[i].num_bytes = 0; } else { - sp_banks[i].num_bytes -= - (end_of_phys_memory - - cmdline_memory_size); - end_of_phys_memory = cmdline_memory_size; - sp_banks[++i].base_addr = 0xdeadbeef; - sp_banks[i].num_bytes = 0; + sp_banks[i+1].num_bytes = 0; + sp_banks[i+1].base_addr = 0xdeadbeef; } break; } } } + *pages_avail = bytes_avail >> PAGE_SHIFT; + /* Start with page aligned address of last symbol in kernel * image. The kernel is hard mapped below PAGE_OFFSET in a * 4MB locked TLB translation. @@ -886,50 +873,40 @@ unsigned long __init bootmem_init(void) } #endif /* Initialize the boot-time allocator. */ -#ifdef DEBUG_BOOTMEM - prom_printf("init_bootmem(spfn[%lx],bpfn[%lx],epfn[%lx])\n", - start_pfn, bootmap_pfn, end_pfn); -#endif - bootmap_size = init_bootmem(bootmap_pfn, end_pfn); + bootmap_size = init_bootmem_node(0, bootmap_pfn, phys_base>>PAGE_SHIFT, end_pfn); /* Now register the available physical memory with the * allocator. */ - for (i = 0; sp_banks[i].num_bytes != 0; i++) { -#ifdef DEBUG_BOOTMEM - prom_printf("free_bootmem: base[%lx] size[%lx]\n", - sp_banks[i].base_addr, - sp_banks[i].num_bytes); -#endif + for (i = 0; sp_banks[i].num_bytes != 0; i++) free_bootmem(sp_banks[i].base_addr, sp_banks[i].num_bytes); - } - /* Reserve the kernel text/data/bss, the bootmem bootmap and initrd. */ -#ifdef DEBUG_BOOTMEM -#ifdef CONFIG_BLK_DEV_INITRD - if (initrd_start) - prom_printf("reserve_bootmem: base[%lx] size[%lx]\n", - initrd_start, initrd_end - initrd_start); -#endif - prom_printf("reserve_bootmem: base[%lx] size[%lx]\n", - phys_base, (start_pfn << PAGE_SHIFT) - phys_base); - prom_printf("reserve_bootmem: base[%lx] size[%lx]\n", - (bootmap_pfn << PAGE_SHIFT), bootmap_size); -#endif #ifdef CONFIG_BLK_DEV_INITRD if (initrd_start) { - reserve_bootmem(initrd_start, initrd_end - initrd_start); + size = initrd_end - initrd_start; + + /* Resert the initrd image area. */ + reserve_bootmem(initrd_start, size); + *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT; + initrd_start += PAGE_OFFSET; initrd_end += PAGE_OFFSET; } #endif - reserve_bootmem(phys_base, (start_pfn << PAGE_SHIFT) - phys_base); - reserve_bootmem((bootmap_pfn << PAGE_SHIFT), bootmap_size); + /* Reserve the kernel text/data/bss. */ + size = (start_pfn << PAGE_SHIFT) - phys_base; + reserve_bootmem(phys_base, size); + *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT; + + /* Reserve the bootmem map. We do not account for it + * in pages_avail because we will release that memory + * in free_all_bootmem. + */ + size = bootmap_size; + reserve_bootmem((bootmap_pfn << PAGE_SHIFT), size); + *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT; -#ifdef DEBUG_BOOTMEM - prom_printf("init_bootmem: return end_pfn[%lx]\n", end_pfn); -#endif return end_pfn; } @@ -946,7 +923,7 @@ void __init paging_init(void) extern unsigned int sparc64_vpte_patchme2[1]; unsigned long alias_base = phys_base + PAGE_OFFSET; unsigned long second_alias_page = 0; - unsigned long pt, flags, end_pfn; + unsigned long pt, flags, end_pfn, pages_avail; unsigned long shift = alias_base - ((unsigned long)&empty_zero_page); set_bit(0, mmu_context_bmap); @@ -1001,7 +978,8 @@ void __init paging_init(void) flushi((long)&sparc64_vpte_patchme1[0]); /* Setup bootmem... */ - last_valid_pfn = end_pfn = bootmem_init(); + pages_avail = 0; + last_valid_pfn = end_pfn = bootmem_init(&pages_avail); #ifdef CONFIG_SUN_SERIAL /* This does not logically belong here, but we need to @@ -1039,10 +1017,20 @@ void __init paging_init(void) flush_tlb_all(); { - unsigned long zones_size[MAX_NR_ZONES] = { 0, 0, 0}; + unsigned long zones_size[MAX_NR_ZONES]; + unsigned long zholes_size[MAX_NR_ZONES]; + unsigned long npages; + int znum; - zones_size[ZONE_DMA] = end_pfn; - free_area_init(zones_size); + for (znum = 0; znum < MAX_NR_ZONES; znum++) + zones_size[znum] = zholes_size[znum] = 0; + + npages = end_pfn - (phys_base >> PAGE_SHIFT); + zones_size[ZONE_DMA] = npages; + zholes_size[ZONE_DMA] = npages - pages_avail; + + free_area_init_node(0, NULL, zones_size, + phys_base, zholes_size); } device_scan(); @@ -1139,9 +1127,6 @@ static void __init taint_real_pages(void) struct sparc_phys_banks saved_sp_banks[SPARC_PHYS_BANKS]; int i; -#ifdef DEBUG_BOOTMEM - prom_printf("taint_real_pages: Rescan sp_banks[].\n"); -#endif for (i = 0; i < SPARC_PHYS_BANKS; i++) { saved_sp_banks[i].base_addr = sp_banks[i].base_addr; @@ -1176,10 +1161,6 @@ static void __init taint_real_pages(void) goto do_next_page; } } -#ifdef DEBUG_BOOTMEM - prom_printf("taint: Page went away, reserve page %lx.\n", - old_start); -#endif reserve_bootmem(old_start, PAGE_SIZE); do_next_page: @@ -1188,70 +1169,6 @@ static void __init taint_real_pages(void) } } -void __init free_mem_map_range(struct page *first, struct page *last) -{ - first = (struct page *) PAGE_ALIGN((unsigned long)first); - last = (struct page *) ((unsigned long)last & PAGE_MASK); -#ifdef DEBUG_BOOTMEM - prom_printf("[%p,%p] ", first, last); -#endif - while (first < last) { - ClearPageReserved(mem_map + MAP_NR(first)); - set_page_count(mem_map + MAP_NR(first), 1); - free_page((unsigned long)first); - num_physpages++; - - first = (struct page *)((unsigned long)first + PAGE_SIZE); - } -} - -/* Walk through holes in sp_banks regions, if the mem_map array - * areas representing those holes consume a page or more, free - * up such pages. This helps a lot on machines where physical - * ram is configured such that it begins at some hugh value. - * - * The sp_banks array is sorted by base address. - */ -void __init free_unused_mem_map(void) -{ - int i; - -#ifdef DEBUG_BOOTMEM - prom_printf("free_unused_mem_map: "); -#endif - for (i = 0; sp_banks[i].num_bytes; i++) { - if (i == 0) { - struct page *first, *last; - - first = mem_map; - last = &mem_map[sp_banks[i].base_addr >> PAGE_SHIFT]; - free_mem_map_range(first, last); - } else { - struct page *first, *last; - unsigned long prev_end; - - prev_end = sp_banks[i-1].base_addr + - sp_banks[i-1].num_bytes; - prev_end = PAGE_ALIGN(prev_end); - first = &mem_map[prev_end >> PAGE_SHIFT]; - last = &mem_map[sp_banks[i].base_addr >> PAGE_SHIFT]; - - free_mem_map_range(first, last); - - if (!sp_banks[i+1].num_bytes) { - prev_end = sp_banks[i].base_addr + - sp_banks[i].num_bytes; - first = &mem_map[prev_end >> PAGE_SHIFT]; - last = &mem_map[last_valid_pfn]; - free_mem_map_range(first, last); - } - } - } -#ifdef DEBUG_BOOTMEM - prom_printf("\n"); -#endif -} - void __init mem_init(void) { unsigned long codepages, datapages, initpages; @@ -1279,16 +1196,10 @@ void __init mem_init(void) taint_real_pages(); - max_mapnr = last_valid_pfn; + max_mapnr = last_valid_pfn - (phys_base >> PAGE_SHIFT); high_memory = __va(last_valid_pfn << PAGE_SHIFT); -#ifdef DEBUG_BOOTMEM - prom_printf("mem_init: Calling free_all_bootmem().\n"); -#endif num_physpages = free_all_bootmem(); -#if 0 - free_unused_mem_map(); -#endif codepages = (((unsigned long) &etext) - ((unsigned long)&_start)); codepages = PAGE_ALIGN(codepages) >> PAGE_SHIFT; datapages = (((unsigned long) &edata) - ((unsigned long)&etext)); @@ -1317,19 +1228,6 @@ void __init mem_init(void) datapages << (PAGE_SHIFT-10), initpages << (PAGE_SHIFT-10), PAGE_OFFSET, (last_valid_pfn << PAGE_SHIFT)); - - /* NOTE NOTE NOTE NOTE - * Please keep track of things and make sure this - * always matches the code in mm/page_alloc.c -DaveM - */ - i = nr_free_pages() >> 7; - if (i < 48) - i = 48; - if (i > 256) - i = 256; - freepages.min = i; - freepages.low = i << 1; - freepages.high = freepages.low + i; } void free_initmem (void) diff --git a/arch/sparc64/prom/Makefile b/arch/sparc64/prom/Makefile index 88ca5251b..04471ab85 100644 --- a/arch/sparc64/prom/Makefile +++ b/arch/sparc64/prom/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.5 1999/12/21 04:02:26 davem Exp $ +# $Id: Makefile,v 1.6 2000/03/31 04:06:25 davem Exp $ # Makefile for the Sun Boot PROM interface library under # Linux. # diff --git a/arch/sparc64/prom/misc.c b/arch/sparc64/prom/misc.c index 8d6404fea..50b287080 100644 --- a/arch/sparc64/prom/misc.c +++ b/arch/sparc64/prom/misc.c @@ -1,4 +1,4 @@ -/* $Id: misc.c,v 1.16 1999/11/19 05:53:04 davem Exp $ +/* $Id: misc.c,v 1.17 2000/04/15 06:02:50 davem Exp $ * misc.c: Miscellaneous prom functions that don't belong * anywhere else. * @@ -64,7 +64,7 @@ prom_cmdline(void) * on SMP, we need to drop the IRQ locks we hold. */ #ifdef __SMP__ - hardirq_exit(smp_processor_id()); + irq_exit(smp_processor_id(), 0); smp_capture(); #else local_irq_count--; @@ -74,8 +74,8 @@ prom_cmdline(void) #ifdef __SMP__ smp_release(); - hardirq_enter(smp_processor_id()); - spin_unlock_wait(&global_irq_lock); + irq_enter(smp_processor_id(), 0); + spin_unlock_wait(&__br_write_locks[BR_GLOBALIRQ_LOCK].lock); #else local_irq_count++; #endif diff --git a/arch/sparc64/solaris/fs.c b/arch/sparc64/solaris/fs.c index 2c17d664d..57e50cd8d 100644 --- a/arch/sparc64/solaris/fs.c +++ b/arch/sparc64/solaris/fs.c @@ -1,4 +1,4 @@ -/* $Id: fs.c,v 1.17 2000/03/10 04:43:30 davem Exp $ +/* $Id: fs.c,v 1.18 2000/04/08 02:11:54 davem Exp $ * fs.c: fs related syscall emulation for Solaris * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -506,7 +506,7 @@ asmlinkage int solaris_fstatvfs(unsigned int fd, u32 buf) unlock_kernel(); fput(file); } -out: + return error; } diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c index c9341b0fd..ef4c9aa01 100644 --- a/arch/sparc64/solaris/misc.c +++ b/arch/sparc64/solaris/misc.c @@ -1,4 +1,4 @@ -/* $Id: misc.c,v 1.23 2000/03/13 21:57:34 davem Exp $ +/* $Id: misc.c,v 1.26 2000/04/14 09:59:02 davem Exp $ * misc.c: Miscelaneous syscall emulation for Solaris * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -54,7 +54,8 @@ static u32 do_solaris_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u64 o unsigned long retval, ret_type; lock_kernel(); - current->personality |= PER_SVR4; + /* Do we need it here? */ + set_personality(PER_SVR4); if (flags & MAP_NORESERVE) { static int cnt = 0; @@ -719,11 +720,7 @@ asmlinkage int do_sol_unimplemented(struct pt_regs *regs) asmlinkage void solaris_register(void) { - lock_kernel(); - current->personality = PER_SVR4; - put_exec_domain(current->exec_domain); - current->exec_domain = lookup_exec_domain(current->personality); - unlock_kernel(); + set_personality(PER_SVR4); } extern long solaris_to_linux_signals[], linux_to_solaris_signals[]; |