diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-02-15 02:15:32 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-02-15 02:15:32 +0000 |
commit | 86464aed71025541805e7b1515541aee89879e33 (patch) | |
tree | e01a457a4912a8553bc65524aa3125d51f29f810 /arch/ppc/kernel | |
parent | 88f99939ecc6a95a79614574cb7d95ffccfc3466 (diff) |
Merge with Linux 2.2.1.
Diffstat (limited to 'arch/ppc/kernel')
-rw-r--r-- | arch/ppc/kernel/Makefile | 9 | ||||
-rw-r--r-- | arch/ppc/kernel/apus_setup.c | 4 | ||||
-rw-r--r-- | arch/ppc/kernel/head.S | 162 | ||||
-rw-r--r-- | arch/ppc/kernel/idle.c | 21 | ||||
-rw-r--r-- | arch/ppc/kernel/irq.c | 75 | ||||
-rw-r--r-- | arch/ppc/kernel/mbx_setup.c | 28 | ||||
-rw-r--r-- | arch/ppc/kernel/misc.S | 185 | ||||
-rw-r--r-- | arch/ppc/kernel/pci.c | 33 | ||||
-rw-r--r-- | arch/ppc/kernel/ppc_htab.c | 3 | ||||
-rw-r--r-- | arch/ppc/kernel/ppc_ksyms.c | 19 | ||||
-rw-r--r-- | arch/ppc/kernel/prep_pci.c | 20 | ||||
-rw-r--r-- | arch/ppc/kernel/prep_setup.c | 5 | ||||
-rw-r--r-- | arch/ppc/kernel/process.c | 24 | ||||
-rw-r--r-- | arch/ppc/kernel/ptrace.c | 4 | ||||
-rw-r--r-- | arch/ppc/kernel/setup.c | 31 | ||||
-rw-r--r-- | arch/ppc/kernel/smp.c | 60 | ||||
-rw-r--r-- | arch/ppc/kernel/time.c | 53 | ||||
-rw-r--r-- | arch/ppc/kernel/traps.c | 3 |
18 files changed, 573 insertions, 166 deletions
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index 4846d5ebb..d047c2086 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile @@ -15,8 +15,7 @@ OX_OBJS := ppc_ksyms.o setup.o O_OBJS := traps.o irq.o idle.o time.o process.o signal.o syscalls.o misc.o \ - bitops.o ptrace.o align.o ppc_htab.o feature.o - + bitops.o ptrace.o align.o ppc_htab.o ifdef CONFIG_PCI O_OBJS += pci.o endif @@ -33,15 +32,17 @@ else ifeq ($(CONFIG_APUS),y) O_OBJS += apus_setup.o prom.o openpic.o else +ifneq ($(CONFIG_MBX),y) O_OBJS += prep_time.o pmac_time.o chrp_time.o \ pmac_setup.o pmac_support.o \ prep_pci.o pmac_pci.o chrp_pci.o \ - residual.o prom.o openpic.o + residual.o prom.o openpic.o feature.o OX_OBJS += chrp_setup.o prep_setup.o endif endif +endif -ifdef SMP +ifdef CONFIG_SMP O_OBJS += smp.o endif diff --git a/arch/ppc/kernel/apus_setup.c b/arch/ppc/kernel/apus_setup.c index 93c2fe2d1..c3a81ad3e 100644 --- a/arch/ppc/kernel/apus_setup.c +++ b/arch/ppc/kernel/apus_setup.c @@ -329,9 +329,9 @@ unsigned long mm_ptov (unsigned long paddr) int i; for (i = 0; i < kmap_chunk_count;){ - unsigned long virt = kmap_chunks[i++]; - unsigned long size = kmap_chunks[i++]; unsigned long phys = kmap_chunks[i++]; + unsigned long size = kmap_chunks[i++]; + unsigned long virt = kmap_chunks[i++]; if (paddr >= phys && paddr < (phys + size)){ ret = virt + paddr - phys; diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S index 4c528beb8..d7b791387 100644 --- a/arch/ppc/kernel/head.S +++ b/arch/ppc/kernel/head.S @@ -1,7 +1,7 @@ /* * arch/ppc/kernel/head.S * - * $Id: head.S,v 1.111 1998/11/10 01:10:32 paulus Exp $ + * $Id: head.S,v 1.114 1998/12/28 10:28:45 paulus Exp $ * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) @@ -148,6 +148,10 @@ _start: * r4: virtual address of boot_infos_t * r5: 0 * + * APUS + * r3: 'APUS' + * Linux/m68k style BootInfo structure at &_end. + * * PREP * This is jumped to on prep systems right after the kernel is relocated * to its proper place in memory by the boot loader. The expected layout @@ -528,9 +532,10 @@ HardwareInterrupt: stw r3,(_CCR+4)(r21); #endif - addi r3,r1,STACK_FRAME_OVERHEAD; - li r20,MSR_KERNEL; - bl transfer_to_handler; + addi r3,r1,STACK_FRAME_OVERHEAD + li r20,MSR_KERNEL + li r4,0 + bl transfer_to_handler .long do_IRQ; .long int_return @@ -1195,18 +1200,34 @@ stack_ovf: * physical address of the hash table are known. These definitions * of Hash_base and Hash_bits below are just an example. */ -/* - * Note that the 603s won't come here, since the 603 - * loads tlb directly into the tlb from the linux tables, while - * others (601, 604, etc.) call hash_page() to load entries from - * the linux tables into the hash table. -- Cort - */ Hash_base = 0x180000 Hash_bits = 12 /* e.g. 256kB hash table */ Hash_msk = (((1 << Hash_bits) - 1) * 64) - + + .globl hash_table_lock +hash_table_lock: +.long 0 + .globl hash_page hash_page: +#ifdef __SMP__ + lis r2,hash_table_lock@h + ori r2,r2,hash_table_lock@l + tophys(r2,r2,r6) + lis r6,100000000@h + mtctr r6 + lwz r0,PROCESSOR-TSS(r5) + or r0,r0,r6 +10: lwarx r6,0,r2 + cmpi 0,r6,0 + bne- 12f + stwcx. r0,0,r2 + beq+ 11f +12: cmpw r6,r0 + bdnzf 2,10b + tw 31,31,31 +11: +#endif /* Get PTE (linux-style) and check access */ lwz r5,PG_TABLES(r5) tophys(r5,r5,r2) /* convert to phys addr */ @@ -1253,6 +1274,9 @@ hash_page_patch_A: li r2,8 /* PTEs/group */ bne 10f /* no PTE: go look for an empty slot */ tlbie r3 /* invalidate TLB entry */ +#ifdef __SMP__ + tlbsync +#endif /* Search the primary PTEG for a PTE whose 1st word matches r5 */ mtctr r2 @@ -1297,7 +1321,6 @@ hash_page_patch_C: bdnzf 2,2b beq+ found_empty -#if 1 /* * Choose an arbitrary slot in the primary PTEG to overwrite. * Since both the primary and secondary PTEGs are full, and we @@ -1313,26 +1336,6 @@ hash_page_patch_C: andi. r2,r2,0x38 stw r2,next_slot@l(0) add r3,r4,r2 -#else - /* now, allow 2nd hash as well as 1st */ - lwz r2,next_slot@l(0) - addi r2,r2,8 - andi. r2,r2,0x78 - stw r2,next_slot@l(0) - cmpi 0,0,r2,0x38 /* if it's the 2nd hash */ - bgt second_evict -first_evict: - xori r5,r5,0x40 /* clear H bit again */ - add r3,r4,r2 - b 11f -second_evict: - .globl hash_page_patch_D -hash_page_patch_D: - xoris r3,r4,Hash_msk>>16 /* compute secondary hash */ - xori r3,r3,0xffc0 - subi r2,r2,0x40 - addi r3,r3,r2 -#endif 11: /* update counter of evicted pages */ lis r2,htab_evicts@h @@ -1372,6 +1375,13 @@ found_slot: addi r3,r3,1 stw r3,0(r2) +#ifdef __SMP__ + lis r2,hash_table_lock@ha + tophys(r2,r2,r6) + li r0,0 + stw r0,hash_table_lock@l(r2) +#endif + /* Return from the exception */ lwz r3,_CCR(r21) lwz r4,_LINK(r21) @@ -1392,6 +1402,12 @@ found_slot: rfi hash_page_out: +#ifdef __SMP__ + lis r2,hash_table_lock@ha + tophys(r2,r2,r6) + li r0,0 + stw r0,hash_table_lock@l(r2) +#endif blr next_slot: .long 0 @@ -1709,6 +1725,9 @@ start_here: 2: SYNC /* Force all PTE updates to finish */ tlbia /* Clear all TLB entries */ +#ifdef __SMP__ + tlbsync +#endif #ifndef CONFIG_8xx mtspr SDR1,r6 li r0,16 /* load up segment register values */ @@ -1980,16 +1999,13 @@ _GLOBAL(_switch) /* FALL THROUGH into int_return */ #ifdef __SMP__ - /* drop scheduler_lock since we weren't called by schedule() */ + /* call schedule_tail if this is the first time for a child process */ lwz r5,TSS_SMP_FORK_RET(r4) cmpi 0,r5,0 beq+ int_return li r3,0 - lis r5,scheduler_lock@ha stw r3,TSS_SMP_FORK_RET(r4) - stw r3,scheduler_lock@l+4(r5) /* owner_pc */ - stw r3,scheduler_lock@l+8(r5) /* owner_cpu */ - stw r3,scheduler_lock@l(r5) /* lock */ + bl schedule_tail #endif /* __SMP__ */ /* @@ -2089,6 +2105,7 @@ _GLOBAL(fake_interrupt) li r0,0x0fac stw r0,TRAP(r1) addi r3,r1,STACK_FRAME_OVERHEAD + li r4,1 bl do_IRQ addi r1,r1,INT_FRAME_SIZE+STACK_UNDERHEAD lwz r0,4(r1) @@ -2206,8 +2223,31 @@ _GLOBAL(flush_hash_segments) rlwinm r0,r0,16,27,31 lis r9,PVR_603_LIKE@h rlwnm. r0,r9,r0,0,0 - bne 99f + beq+ 99f + tlbia + isync + blr +99: #endif /* NO_RELOAD_HTAB */ +#ifdef __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 */ + mfmsr r10 + sync + rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */ + mtmsr r0 + SYNC + lis r9,hash_table_lock@h + ori r9,r9,hash_table_lock@l + lwz r8,PROCESSOR(r2) + oris r8,r8,8 +10: lwarx r6,0,r9 + cmpi 0,r6,0 + bne- 10b + stwcx. r8,0,r9 + bne- 10b +#endif rlwinm r3,r3,7,1,24 /* put VSID lower limit in position */ oris r3,r3,0x8000 /* set V bit */ rlwinm r4,r4,7,1,24 /* put VSID upper limit in position */ @@ -2229,8 +2269,16 @@ _GLOBAL(flush_hash_segments) stw r0,0(r5) /* invalidate entry */ 2: bdnz 1b /* continue with loop */ sync -99: tlbia + tlbia isync +#ifdef __SMP__ + tlbsync + lis r3,hash_table_lock@ha + li r0,0 + stw r0,hash_table_lock@l(r3) + mtmsr r10 + SYNC +#endif blr /* @@ -2244,8 +2292,31 @@ _GLOBAL(flush_hash_page) rlwinm r0,r0,16,27,31 lis r9,PVR_603_LIKE@h rlwnm. r0,r9,r0,0,0 - bne 99f + beq+ 99f + tlbie r4 /* in hw tlb too */ + isync + blr +99: #endif /* NO_RELOAD_HTAB */ +#ifdef __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 */ + mfmsr r10 + sync + rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */ + mtmsr r0 + SYNC + lis r9,hash_table_lock@h + ori r9,r9,hash_table_lock@l + lwz r8,PROCESSOR(r2) + oris r8,r8,9 +10: lwarx r6,0,r9 + cmpi 0,r6,0 + bne- 10b + stwcx. r8,0,r9 + bne- 10b +#endif rlwinm r3,r3,11,1,20 /* put context into vsid */ rlwimi r3,r4,11,21,24 /* put top 4 bits of va into vsid */ oris r3,r3,0x8000 /* set V (valid) bit */ @@ -2278,10 +2349,19 @@ _GLOBAL(flush_hash_page) 3: li r0,0 stw r0,0(r7) /* invalidate entry */ 4: sync -99: tlbie r4 /* in hw tlb too */ + tlbie r4 /* in hw tlb too */ isync +#ifdef __SMP__ + tlbsync + lis r3,hash_table_lock@h + li r0,0 + stw r0,hash_table_lock@l(r3) + mtmsr r10 + SYNC +#endif blr #endif /* CONFIG_8xx */ + /* * This routine is just here to keep GCC happy - sigh... */ diff --git a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c index b6c338946..af163699b 100644 --- a/arch/ppc/kernel/idle.c +++ b/arch/ppc/kernel/idle.c @@ -1,5 +1,5 @@ /* - * $Id: idle.c,v 1.56 1998/10/13 19:14:36 paulus Exp $ + * $Id: idle.c,v 1.57 1998/12/28 10:28:46 paulus Exp $ * * Idle daemon for PowerPC. Idle daemon will handle any action * that needs to be taken when the system becomes idle. @@ -41,26 +41,25 @@ unsigned long powersave_nap = 0; int idled(void *unused) { - int ret = -EPERM; - + /* endless loop with no priority at all */ + current->priority = 0; + current->counter = -100; for (;;) { __sti(); - /* endless loop with no priority at all */ - current->priority = 0; - current->counter = 0; - check_pgt_cache(); if ( !current->need_resched && zero_paged_on ) zero_paged(); if ( !current->need_resched && htab_reclaim_on ) htab_reclaim(); if ( !current->need_resched ) power_save(); - run_task_queue(&tq_scheduler); - schedule(); + +#ifdef __SMP__ + if (current->need_resched) +#endif + schedule(); } - ret = 0; - return ret; + return 0; } #ifdef __SMP__ diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c index a180e5f0a..f4a7c7143 100644 --- a/arch/ppc/kernel/irq.c +++ b/arch/ppc/kernel/irq.c @@ -1,4 +1,6 @@ /* + * $Id: irq.c,v 1.91 1998/12/28 10:28:47 paulus Exp $ + * * arch/ppc/kernel/irq.c * * Derived from arch/i386/kernel/irq.c @@ -6,6 +8,7 @@ * Adapted from arch/i386 by Gary Thomas * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * Updated and modified by Cort Dougan (cort@cs.nmt.edu) + * Copyright (C) 1996 Cort Dougan * Adapted for Power Macintosh by Paul Mackerras * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). @@ -309,14 +312,14 @@ static void __openfirmware chrp_unmask_irq(unsigned int irq_nr) static void mbx_mask_irq(unsigned int irq_nr) { cached_irq_mask[0] &= ~(1 << (31-irq_nr)); - ((immap_t *)MBX_IMAP_ADDR)->im_siu_conf.sc_simask = + ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = cached_irq_mask[0]; } static void mbx_unmask_irq(unsigned int irq_nr) { cached_irq_mask[0] |= (1 << (31-irq_nr)); - ((immap_t *)MBX_IMAP_ADDR)->im_siu_conf.sc_simask = + ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = cached_irq_mask[0]; } #endif /* CONFIG_8xx */ @@ -454,7 +457,6 @@ static inline void wait_on_bh(void) } -#define MAXCOUNT 100000000 static inline void wait_on_irq(int cpu) { int count = MAXCOUNT; @@ -507,7 +509,7 @@ static inline void wait_on_irq(int cpu) void synchronize_bh(void) { if (atomic_read(&global_bh_count) && !in_interrupt()) - wait_on_bh(); + wait_on_bh(); } @@ -529,6 +531,8 @@ void synchronize_irq(void) static inline void get_irqlock(int cpu) { + unsigned int loops = MAXCOUNT; + if (test_and_set_bit(0,&global_irq_lock)) { /* do we already hold the lock? */ if ((unsigned char) cpu == global_irq_holder) @@ -536,12 +540,17 @@ static inline void get_irqlock(int cpu) /* Uhhuh.. Somebody else got it. Wait.. */ do { do { - + if (loops-- == 0) { + printk("get_irqlock(%d) waiting, global_irq_holder=%d\n", cpu, global_irq_holder); +#ifdef CONFIG_XMON + xmon(0); +#endif + } } while (test_bit(0,&global_irq_lock)); } while (test_and_set_bit(0,&global_irq_lock)); } /* - * We also to make sure that nobody else is running + * We also need to make sure that nobody else is running * in an interrupt context. */ wait_on_irq(cpu); @@ -637,7 +646,7 @@ void __global_restore_flags(unsigned long flags) #endif /* __SMP__ */ -asmlinkage void do_IRQ(struct pt_regs *regs) +asmlinkage void do_IRQ(struct pt_regs *regs, int isfake) { int irq; unsigned long bits; @@ -656,9 +665,14 @@ asmlinkage void do_IRQ(struct pt_regs *regs) #ifdef __SMP__ if ( cpu != 0 ) { - if (!atomic_read(&n_lost_interrupts)) + if (!isfake) { extern void smp_message_recv(void); +#ifdef CONFIG_XMON + static int xmon_2nd; + if (xmon_2nd) + xmon(regs); +#endif smp_message_recv(); goto out; } @@ -666,6 +680,25 @@ asmlinkage void do_IRQ(struct pt_regs *regs) mess with the controller from the second cpu -- Cort */ goto out; } + + { + unsigned int loops = MAXCOUNT; + while (test_bit(0, &global_irq_lock)) { + if (smp_processor_id() == global_irq_holder) { + printk("uh oh, interrupt while we hold global irq lock!\n"); +#ifdef CONFIG_XMON + xmon(0); +#endif + break; + } + if (loops-- == 0) { + printk("do_IRQ waiting for irq lock (holder=%d)\n", global_irq_holder); +#ifdef CONFIG_XMON + xmon(0); +#endif + } + } + } #endif /* __SMP__ */ switch ( _machine ) @@ -799,9 +832,13 @@ apus_out: } if (irq < 0) { - printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n", - irq, regs->nip); - spurious_interrupts++; + /* we get here with Gatwick but the 'bogus' isn't correct in that case -- Cort */ + if ( irq != second_irq ) + { + printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n", + irq, regs->nip); + spurious_interrupts++; + } goto out; } @@ -809,7 +846,7 @@ apus_out: /* For MPC8xx, read the SIVEC register and shift the bits down * to get the irq number. */ - bits = ((immap_t *)MBX_IMAP_ADDR)->im_siu_conf.sc_sivec; + bits = ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sivec; irq = bits >> 26; #endif /* CONFIG_8xx */ mask_and_ack_irq(irq); @@ -1089,17 +1126,6 @@ __initfunc(void init_IRQ(void)) */ if ( _prep_type == _PREP_IBM ) irq_mode2 |= 0xa0; - /* - * Sound on the Powerstack reportedly needs to be edge triggered - */ - if ( _prep_type == _PREP_Motorola ) - { - irq_mode2 &= ~0x04L; - irq_mode2 = 0xca; - outb( irq_mode1 , 0x4d0 ); - outb( irq_mode2 , 0x4d1 ); - } - } break; #ifdef CONFIG_APUS @@ -1116,8 +1142,7 @@ __initfunc(void init_IRQ(void)) /* This routine will fix some missing interrupt values in the device tree * on the gatwick mac-io controller used by some PowerBooks */ -__pmac -static void pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base) +static void __init pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base) { struct device_node *node; static struct interrupt_info int_pool[4]; diff --git a/arch/ppc/kernel/mbx_setup.c b/arch/ppc/kernel/mbx_setup.c index 9d26e27d1..90647dcd9 100644 --- a/arch/ppc/kernel/mbx_setup.c +++ b/arch/ppc/kernel/mbx_setup.c @@ -1,4 +1,6 @@ /* + * $Id: mbx_setup.c,v 1.5 1998/12/29 18:55:07 cort Exp $ + * * linux/arch/ppc/kernel/setup.c * * Copyright (C) 1995 Linus Torvalds @@ -51,17 +53,27 @@ extern int rd_image_start; /* starting block # of image */ extern char saved_command_line[256]; extern unsigned long find_available_memory(void); -extern void mbx_cpm_reset(uint); - +extern void m8xx_cpm_reset(uint); -void mbx_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq) +/* this really does make things cleaner -- Cort */ +void __init powermac_init(void) { +} - *p = 0; - *irq = 0; +void __init adbdev_init(void) +{ +} - if (base != 0) /* Only map the first ATA flash drive */ - return; +void __init mbx_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq) +{ + ide_ioreg_t port = base; + int i = 8; + + while (i--) + *p++ = port++; + *p++ = base + 0x206; + if (irq != NULL) + *irq = 0; #ifdef ATA_FLASH base = (unsigned long) ioremap(PCMCIA_MEM_ADDR, 0x200); for (i = 0; i < 8; ++i) @@ -88,7 +100,7 @@ mbx_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p)) /* Reset the Communication Processor Module. */ - mbx_cpm_reset(cpm_page); + m8xx_cpm_reset(cpm_page); #ifdef notdef ROOT_DEV = to_kdev_t(0x0301); /* hda1 */ diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index f13508d96..e4589b1e0 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S @@ -383,6 +383,177 @@ _GLOBAL(_set_THRM3) mtspr THRM3,r3 blr +_GLOBAL(_get_PVR) + mfspr r3,PVR + blr +/* + L2CR functions + Copyright © 1997-1998 by PowerLogix R & D, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +/* + Thur, Dec. 12, 1998. + - First public release, contributed by PowerLogix. + + Author: Terry Greeniaus (tgree@phys.ualberta.ca) + Please e-mail updates to this file to me, thanks! +*/ + +_GLOBAL(_set_L2CR) + /* Usage: + + When setting the L2CR register, you must do a few special things. If you are enabling the + cache, you must perform a global invalidate. If you are disabling the cache, you must + flush the cache contents first. This routine takes care of doing these things. When first + enabling the cache, make sure you pass in the L2CR you want, as well as passing in the + global invalidate bit set. A global invalidate will only be performed if the L2I bit is set + in applyThis. When enabling the cache, you should also set the L2E bit in applyThis. If you + want to modify the L2CR contents after the cache has been enabled, the recommended + procedure is to first call __setL2CR(0) to disable the cache and then call it again with + the new values for L2CR. Examples: + + _setL2CR(0) - disables the cache + _setL2CR(0xB3A04000) - enables my G3 upgrade card: + - L2E set to turn on the cache + - L2SIZ set to 1MB + - L2CLK set to 1:1 + - L2RAM set to pipelined syncronous late-write + - L2I set to perform a global invalidation + - L2OH set to 0.5 nS + - L2DF set because this upgrade card requires it + + A similar call should work for your card. You need to know the correct setting for your + card and then place them in the fields I have outlined above. Other fields support optional + features, such as L2DO which caches only data, or L2TS which causes cache pushes from + the L1 cache to go to the L2 cache instead of to main memory. + */ + + /* Make sure this is a 750 chip */ + mfspr r4,PVR + rlwinm r4,r4,16,16,31 + cmplwi r4,0x0008 + beq thisIs750 + li r3,-1 + blr + +thisIs750: + /* Get the current enable bit of the L2CR into r4 */ + mfspr r4,L2CR + rlwinm r4,r4,0,0,0 + + /* See if we want to perform a global inval this time. */ + rlwinm r6,r3,0,10,10 /* r6 contains the new invalidate bit */ + rlwinm. r5,r3,0,0,0 /* r5 contains the new enable bit */ + rlwinm r3,r3,0,11,9 /* Turn off the invalidate bit */ + rlwinm r3,r3,0,1,31 /* Turn off the enable bit */ + or r3,r3,r4 /* Keep the enable bit the same as it was for now. */ + bne dontDisableCache /* Only disable the cache if L2CRApply has the enable bit off */ + +disableCache: + /* Disable the cache. First, we turn off data relocation. */ + mfmsr r7 + rlwinm r4,r7,0,28,26 /* Turn off DR bit */ + rlwinm r4,r4,0,17,15 /* Turn off EE bit - an external exception while we are flushing + the cache is fatal (comment this line and see!) */ + sync + mtmsr r4 + sync + + /* + Now, read the first 2MB of memory to put new data in the cache. + (Actually we only need the size of the L2 cache plus + the size of the L1 cache, but 2MB will cover everything just to be safe). + */ + lis r4,0x0001 + mtctr r4 + li r4,0 +loadLoop: + lwzx r0,r0,r4 + addi r4,r4,0x0020 /* Go to start of next cache line */ + bdnz loadLoop + + /* Now, flush the first 2MB of memory */ + lis r4,0x0001 + mtctr r4 + li r4,0 + sync +flushLoop: + dcbf r0,r4 + addi r4,r4,0x0020 /* Go to start of next cache line */ + bdnz flushLoop + + /* Turn off the L2CR enable bit. */ + rlwinm r3,r3,0,1,31 + + /* Reenable data relocation. */ + sync + mtmsr r7 + sync + +dontDisableCache: + /* Set up the L2CR configuration bits */ + sync + mtspr L2CR,r3 + sync + cmplwi r6,0 + beq noInval + + /* Perform a global invalidation */ + oris r3,r3,0x0020 + sync + mtspr 1017,r3 + sync +invalCompleteLoop: /* Wait for the invalidation to complete */ + mfspr r3,1017 + rlwinm. r4,r3,0,31,31 + bne invalCompleteLoop + + rlwinm r3,r3,0,11,9; /* Turn off the L2I bit */ + sync + mtspr L2CR,r3 + sync + +noInval: + /* See if we need to enable the cache */ + cmplwi r5,0 + beqlr + +enableCache: + /* Enable the cache */ + oris r3,r3,0x8000 + mtspr L2CR,r3 + sync + blr + +_GLOBAL(_get_L2CR) + /* Make sure this is a 750 chip */ + mfspr r3,PVR + rlwinm r3,r3,16,16,31 + cmplwi r3,0x0008 + li r3,0 + bnelr + + /* Return the L2CR contents */ + mfspr r3,L2CR + blr + +/* --- End of PowerLogix code --- + */ + +/* _GLOBAL(_get_L2CR) mfspr r3,L2CR blr @@ -391,9 +562,7 @@ _GLOBAL(_set_L2CR) mtspr L2CR,r3 blr -_GLOBAL(_get_PVR) - mfspr r3,PVR - blr +*/ /* * These are used in the alignment trap handler when emulating @@ -441,16 +610,6 @@ _GLOBAL(__kernel_thread) bnelr /* return if parent */ mtlr r4 /* fn addr in lr */ mr r3,r5 /* load arg and call fn */ -#if 0/*def __SMP__*/ - /* drop scheduler_lock since schedule() called us */ - lis r4,scheduler_lock@ha - li r5,0 - stw r5,scheduler_lock@l+4(r4) /* owner_pc */ - stw r5,scheduler_lock@l+8(r4) /* owner_cpu */ - stw r5,scheduler_lock@l(r4) - sync - isync -#endif /* __SMP__ */ blrl li r0,__NR_exit /* exit after child exits */ li r3,0 diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c index 359446f4f..1dfa3a6c8 100644 --- a/arch/ppc/kernel/pci.c +++ b/arch/ppc/kernel/pci.c @@ -1,5 +1,5 @@ /* - * $Id: pci.c,v 1.39 1998/10/13 20:59:04 cort Exp $ + * $Id: pci.c,v 1.43 1998/12/29 18:55:11 cort Exp $ * Common pmac/prep/chrp pci routines. -- Cort */ @@ -123,8 +123,8 @@ __initfunc(void pcibios_init(void)) __initfunc(void setup_pci_ptrs(void)) { - PPC_DEVICE *hostbridge; #ifndef CONFIG_MBX + PPC_DEVICE *hostbridge; switch (_machine) { case _MACH_prep: hostbridge=residual_find_device(PROCESSORDEVICE, NULL, @@ -188,13 +188,8 @@ __initfunc(void pcibios_fixup(void)) extern struct bridge_data **bridges; extern unsigned char *Motherboard_map; extern unsigned char *Motherboard_routes; - - /* - * FIXME: This is broken: We should not assign IRQ's to IRQless - * devices (look at PCI_INTERRUPT_PIN) and we also should - * honor the existence of multi-function devices where - * different functions have different interrupt pins. [mj] - */ + unsigned char i; +#ifndef CONFIG_MBX switch (_machine ) { case _MACH_prep: @@ -208,6 +203,21 @@ __initfunc(void pcibios_fixup(void)) */ unsigned char d = PCI_SLOT(dev->devfn); dev->irq = Motherboard_routes[Motherboard_map[d]]; + for ( i = 0 ; i <= 5 ; i++ ) + { + if ( dev->base_address[i] > 0x10000000 ) + { + printk("Relocating PCI address %x -> %x\n", + dev->base_address[i], + (dev->base_address[i] & 0x00FFFFFF) + | 0x01000000); + dev->base_address[i] = + (dev->base_address[i] & 0x00FFFFFF) | 0x01000000; + pci_write_config_dword(dev, + PCI_BASE_ADDRESS_0+(i*0x4), + dev->base_address[i] ); + } + } #if 0 /* * If we have residual data and if it knows about this @@ -255,6 +265,11 @@ __initfunc(void pcibios_fixup(void)) } break; } +#else /* CONFIG_MBX */ + for(dev=pci_devices; dev; dev=dev->next) + { + } +#endif /* CONFIG_MBX */ } __initfunc(void pcibios_fixup_bus(struct pci_bus *bus)) diff --git a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c index 3aa0534ea..30123c076 100644 --- a/arch/ppc/kernel/ppc_htab.c +++ b/arch/ppc/kernel/ppc_htab.c @@ -1,5 +1,5 @@ /* - * $Id: ppc_htab.c,v 1.25 1998/08/26 10:28:26 davem Exp $ + * $Id: ppc_htab.c,v 1.26 1998/12/10 00:24:23 cort Exp $ * * PowerPC hash table management proc entry. Will show information * about the current hash table and will allow changes to it. @@ -569,6 +569,7 @@ int proc_dol2crvec(ctl_table *table, int write, struct file *filp, break; buffer += len; left -= len; + _set_L2CR(0); _set_L2CR(val); while ( _get_L2CR() & 0x1 ) /* wait for invalidate to finish */; diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index ea5f6db0d..1b7753dd0 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c @@ -25,6 +25,7 @@ #include <asm/pci-bridge.h> #include <asm/irq.h> #include <asm/feature.h> +#include <asm/spinlock.h> #define __KERNEL_SYSCALLS__ #include <linux/unistd.h> @@ -32,7 +33,7 @@ extern void transfer_to_handler(void); extern void int_return(void); extern void syscall_trace(void); -extern void do_IRQ(struct pt_regs *regs); +extern void do_IRQ(struct pt_regs *regs, int isfake); extern void MachineCheckException(struct pt_regs *regs); extern void AlignmentException(struct pt_regs *regs); extern void ProgramCheckException(struct pt_regs *regs); @@ -156,6 +157,19 @@ EXPORT_SYMBOL(_get_PVR); EXPORT_SYMBOL(giveup_fpu); EXPORT_SYMBOL(flush_icache_range); EXPORT_SYMBOL(xchg_u32); +#ifdef __SMP__ +EXPORT_SYMBOL(__global_cli); +EXPORT_SYMBOL(__global_sti); +EXPORT_SYMBOL(__global_save_flags); +EXPORT_SYMBOL(__global_restore_flags); +EXPORT_SYMBOL(_spin_lock); +EXPORT_SYMBOL(_spin_unlock); +EXPORT_SYMBOL(spin_trylock); +EXPORT_SYMBOL(_read_lock); +EXPORT_SYMBOL(_read_unlock); +EXPORT_SYMBOL(_write_lock); +EXPORT_SYMBOL(_write_unlock); +#endif #ifndef CONFIG_MACH_SPECIFIC EXPORT_SYMBOL(_machine); @@ -180,12 +194,15 @@ EXPORT_SYMBOL(find_compatible_devices); EXPORT_SYMBOL(find_path_device); EXPORT_SYMBOL(find_phandle); EXPORT_SYMBOL(get_property); +EXPORT_SYMBOL(device_is_compatible); EXPORT_SYMBOL(pci_io_base); EXPORT_SYMBOL(pci_device_loc); EXPORT_SYMBOL(feature_set); EXPORT_SYMBOL(feature_clear); EXPORT_SYMBOL(feature_test); +#ifdef CONFIG_SCSI EXPORT_SYMBOL(note_scsi_host); +#endif EXPORT_SYMBOL(kd_mksound); #ifdef CONFIG_PMAC EXPORT_SYMBOL(nvram_read_byte); diff --git a/arch/ppc/kernel/prep_pci.c b/arch/ppc/kernel/prep_pci.c index b7d94d208..b48f7a1fc 100644 --- a/arch/ppc/kernel/prep_pci.c +++ b/arch/ppc/kernel/prep_pci.c @@ -1,5 +1,5 @@ /* - * $Id: prep_pci.c,v 1.23 1998/10/21 10:52:24 cort Exp $ + * $Id: prep_pci.c,v 1.24 1998/12/10 02:39:51 cort Exp $ * PReP pci functions. * Originally by Gary Thomas * rewritten and updated by Cort Dougan (cort@cs.nmt.edu) @@ -107,7 +107,7 @@ static char Omaha_pci_IRQ_routes[] __prepdata = }; /* Motorola PowerStack */ -static char Blackhawk_pci_IRQ_map[16] __prepdata = +static char Blackhawk_pci_IRQ_map[19] __prepdata = { 0, /* Slot 0 - unused */ 0, /* Slot 1 - unused */ @@ -125,6 +125,9 @@ static char Blackhawk_pci_IRQ_map[16] __prepdata = 0, /* Slot 13 - unused */ 1, /* Slot 14 - Ethernet */ 0, /* Slot 15 - unused */ + 1, /* Slot P7 */ + 2, /* Slot P6 */ + 3, /* Slot P5 */ }; static char Blackhawk_pci_IRQ_routes[] __prepdata = @@ -132,7 +135,7 @@ static char Blackhawk_pci_IRQ_routes[] __prepdata = 0, /* Line 0 - Unused */ 9, /* Line 1 */ 11, /* Line 2 */ - 14, /* Line 3 */ + 15, /* Line 3 */ 15 /* Line 4 */ }; @@ -226,6 +229,7 @@ static char ibm8xx_pci_IRQ_map[23] __prepdata = { 0, /* Slot 21 - unused */ 2, /* Slot 22 - PCI slot 1 PCIINTx# (See below) */ }; + static char ibm8xx_pci_IRQ_routes[] __prepdata = { 0, /* Line 0 - unused */ 13, /* Line 1 */ @@ -440,6 +444,8 @@ __initfunc(unsigned long route_pci_interrupts(void)) if ( _prep_type == _PREP_Motorola) { + unsigned short irq_mode; + switch (inb(0x800) & 0xF0) { case 0x10: /* MVME16xx */ @@ -474,6 +480,14 @@ __initfunc(unsigned long route_pci_interrupts(void)) Motherboard_routes = Blackhawk_pci_IRQ_routes; break; } + /* AJF adjust level/edge control according to routes */ + irq_mode = 0; + for (i = 1; i <= 4; i++) + { + irq_mode |= ( 1 << Motherboard_routes[i] ); + } + outb( irq_mode & 0xff, 0x4d0 ); + outb( (irq_mode >> 8) & 0xff, 0x4d1 ); } else if ( _prep_type == _PREP_IBM ) { unsigned char pl_id; diff --git a/arch/ppc/kernel/prep_setup.c b/arch/ppc/kernel/prep_setup.c index e596f9ea5..72752e11f 100644 --- a/arch/ppc/kernel/prep_setup.c +++ b/arch/ppc/kernel/prep_setup.c @@ -189,11 +189,6 @@ prep_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p)) /* Enable L2. Assume we don't need to flush -- Cort*/ *(unsigned char *)(0x8000081c) = *(unsigned char *)(0x8000081c)|3; - /* make the serial port the console */ - /* strcat(cmd_line,"console=ttyS0,9600n8"); */ - /* use the normal console but send output to the serial port, too */ - /*strcat(cmd_line,"console=tty0 console=ttyS0,9600n8");*/ - sprintf(cmd_line,"%s console=tty0 console=ttyS0,9600n8", cmd_line); printk("Boot arguments: %s\n", cmd_line); #ifdef CONFIG_SOUND_CS4232 diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c index 5ea55cee9..ebe64a429 100644 --- a/arch/ppc/kernel/process.c +++ b/arch/ppc/kernel/process.c @@ -1,4 +1,6 @@ /* + * $Id: process.c,v 1.70 1999/01/07 16:28:59 cort Exp $ + * * linux/arch/ppc/kernel/process.c * * Derived from "arch/i386/kernel/process.c" @@ -180,13 +182,6 @@ switch_to(struct task_struct *prev, struct task_struct *new) if ( prev->tss.regs->msr & MSR_FP ) smp_giveup_fpu(prev); - /* be noisy about processor changes for debugging -- Cort */ - if ( (new->last_processor != NO_PROC_ID) && - (new->last_processor != new->processor) ) - printk("switch_to(): changing cpu's %d -> %d %s/%d\n", - new->last_processor,new->processor, - new->comm,new->pid); - prev->last_processor = prev->processor; current_set[smp_processor_id()] = new; #endif /* __SMP__ */ @@ -236,6 +231,19 @@ void show_regs(struct pt_regs * regs) out: } +void instruction_dump (unsigned long *pc) +{ + int i; + + if((((unsigned long) pc) & 3)) + return; + + printk("Instruction DUMP:"); + for(i = -3; i < 6; i++) + printk("%c%08lx%c",i?' ':'<',pc[i],i?' ':'>'); + printk("\n"); +} + void exit_thread(void) { if (last_task_used_math == current) @@ -450,6 +458,7 @@ print_backtrace(unsigned long *sp) printk("\n"); } +#if 0 /* * Low level print for debugging - Cort */ @@ -537,3 +546,4 @@ __initfunc(void ll_puts(const char *s)) orig_x = x; orig_y = y; } +#endif diff --git a/arch/ppc/kernel/ptrace.c b/arch/ppc/kernel/ptrace.c index 62b2b03af..e2c6b13a0 100644 --- a/arch/ppc/kernel/ptrace.c +++ b/arch/ppc/kernel/ptrace.c @@ -362,7 +362,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) case PTRACE_PEEKDATA: { unsigned long tmp; + down(&child->mm->mmap_sem); ret = read_long(child, addr, &tmp); + up(&child->mm->mmap_sem); if (ret < 0) goto out; ret = verify_area(VERIFY_WRITE, (void *) data, sizeof(long)); @@ -410,7 +412,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) /* If I and D space are separate, this will have to be fixed. */ case PTRACE_POKETEXT: /* write the word at location addr. */ case PTRACE_POKEDATA: + down(&child->mm->mmap_sem); ret = write_long(child,addr,data); + up(&child->mm->mmap_sem); goto out; case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c index 706c1dde2..50cd70889 100644 --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c @@ -1,5 +1,5 @@ /* - * $Id: setup.c,v 1.117 1998/11/09 19:55:53 geert Exp $ + * $Id: setup.c,v 1.122 1998/12/31 20:51:19 cort Exp $ * Common prep/pmac/chrp boot and setup code. */ @@ -35,7 +35,7 @@ extern unsigned long m68k_machtype; extern int parse_bootinfo(const struct bi_record *); extern char _end[]; #ifdef CONFIG_APUS -struct mem_info ramdisk; +extern struct mem_info ramdisk; unsigned long isa_io_base; unsigned long isa_mem_base; unsigned long pci_dram_offset; @@ -259,6 +259,9 @@ void ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq) break; } #endif +#if defined(CONFIG_MBX) + mbx_ide_init_hwif_ports(p,base,irq); +#endif } EXPORT_SYMBOL(ide_init_hwif_ports); #endif @@ -464,9 +467,9 @@ int get_cpuinfo(char *buffer) * Find out what kind of machine we're on and save any data we need * from the early boot process (devtree is copied on pmac by prom_init() ) */ -__initfunc(unsigned long +unsigned long __init identify_machine(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7)) + unsigned long r6, unsigned long r7) { extern void setup_pci_ptrs(void); @@ -491,6 +494,9 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5, char *model; have_of = 1; + + /* prom_init has already been called from __start */ + finish_device_tree(); /* ask the OF info if we're a chrp or pmac */ model = get_property(find_path_device("/"), "device_type", NULL); if ( model && !strncmp("chrp",model,4) ) @@ -510,8 +516,10 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5, if ( have_of ) { +#ifdef CONFIG_MACH_SPECIFIC /* prom_init has already been called from __start */ finish_device_tree(); +#endif /* CONFIG_MACH_SPECIFIC */ /* * If we were booted via quik, r3 points to the physical * address of the command-line parameters. @@ -665,7 +673,7 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5, #else /* CONFIG_MBX */ if ( r3 ) - memcpy( (void *)&res,(void *)(r3+KERNELBASE), sizeof(bd_t) ); + memcpy( (void *)res,(void *)(r3+KERNELBASE), sizeof(bd_t) ); #ifdef CONFIG_PCI setup_pci_ptrs(); @@ -693,9 +701,22 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5, extern int __map_without_bats; __map_without_bats = 1; } + return 0; } +/* Checks "l2cr=xxxx" command-line option */ +void ppc_setup_l2cr(char *str, int *ints) +{ + if ( (_get_PVR() >> 16) == 8) + { + unsigned long val = simple_strtoul(str, NULL, 0); + printk(KERN_INFO "l2cr set to %lx\n", val); + _set_L2CR(0); + _set_L2CR(val); + } +} + __initfunc(void setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * memory_end_p)) { diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c index 75445925f..ba505e133 100644 --- a/arch/ppc/kernel/smp.c +++ b/arch/ppc/kernel/smp.c @@ -1,5 +1,5 @@ /* - * $Id: smp.c,v 1.36 1998/10/08 01:17:48 cort Exp $ + * $Id: smp.c,v 1.39 1998/12/28 10:28:51 paulus Exp $ * * Smp support for ppc. * @@ -43,6 +43,7 @@ spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED; unsigned int prof_multiplier[NR_CPUS]; unsigned int prof_counter[NR_CPUS]; int first_cpu_booted = 0; +cycles_t cacheflush_time; /* all cpu mappings are 1-1 -- Cort */ int cpu_number_map[NR_CPUS] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,}; @@ -144,7 +145,14 @@ void smp_message_recv(void) void smp_send_reschedule(int cpu) { - smp_message_pass(cpu, MSG_RESCHEDULE, 0, 0); + /* This is only used if `cpu' is running an idle task, + so it will reschedule itself anyway... */ + /*smp_message_pass(cpu, MSG_RESCHEDULE, 0, 0);*/ +} + +void smp_send_stop(void) +{ + smp_message_pass(MSG_ALL_BUT_SELF, MSG_STOP_CPU, 0, 0); } spinlock_t mesg_pass_lock = SPIN_LOCK_UNLOCKED; @@ -152,7 +160,7 @@ void smp_message_pass(int target, int msg, unsigned long data, int wait) { if ( _machine != _MACH_Pmac ) return; - /*printk("SMP %d: sending smp message\n", current->processor);*/ +printk("SMP %d: sending smp message %x\n", current->processor, msg); if (smp_processor_id() ) printk("pass from cpu 1\n"); spin_lock(&mesg_pass_lock); #define OTHER (~smp_processor_id() & 1) @@ -179,17 +187,18 @@ if (smp_processor_id() ) printk("pass from cpu 1\n"); spin_unlock(&mesg_pass_lock); } -__initfunc(void smp_boot_cpus(void)) +void __init smp_boot_cpus(void) { extern struct task_struct *current_set[NR_CPUS]; extern void __secondary_start(void); int i; struct task_struct *p; - + unsigned long a; + printk("Entering SMP Mode...\n"); first_cpu_booted = 1; - dcbf(&first_cpu_booted); + /*dcbf(&first_cpu_booted);*/ for (i = 0; i < NR_CPUS; i++) { prof_counter[i] = 1; @@ -200,7 +209,13 @@ __initfunc(void smp_boot_cpus(void)) smp_store_cpu_info(0); active_kernel_processor = 0; current->processor = 0; - + + /* + * XXX very rough, assumes 20 bus cycles to read a cache line, + * timebase increments every 4 bus cycles, 32kB L1 data cache. + */ + cacheflush_time = 5 * 1024; + if ( _machine != _MACH_Pmac ) { printk("SMP not supported on this machine.\n"); @@ -213,10 +228,16 @@ __initfunc(void smp_boot_cpus(void)) if ( !p ) panic("No idle task for secondary processor\n"); p->processor = 1; + p->has_cpu = 1; current_set[1] = p; /* need to flush here since secondary bat's aren't setup */ - dcbf((void *)¤t_set[1]); + /* XXX ??? */ + for (a = KERNELBASE; a < KERNELBASE + 0x800000; a += 32) + asm volatile("dcbf 0,%0" : : "r" (a) : "memory"); + asm volatile("sync"); + + /*dcbf((void *)¤t_set[1]);*/ /* setup entry point of secondary processor */ *(volatile unsigned long *)(0xf2800000) = (unsigned long)__secondary_start-KERNELBASE; @@ -238,7 +259,7 @@ __initfunc(void smp_boot_cpus(void)) if(cpu_callin_map[1]) { printk("Processor %d found.\n", smp_num_cpus); smp_num_cpus++; -#if 0 /* this sync's the decr's, but we don't want this now -- Cort */ +#if 1 /* this sync's the decr's, but we don't want this now -- Cort */ set_dec(decrementer_count); #endif } else { @@ -251,19 +272,17 @@ __initfunc(void smp_boot_cpus(void)) smp_message_pass(1,0xf0f0, 0, 0); } -__initfunc(void smp_commence(void)) +void __init smp_commence(void) { printk("SMP %d: smp_commence()\n",current->processor); /* * Lets the callin's below out of their loop. */ - local_flush_tlb_all(); smp_commenced = 1; - local_flush_tlb_all(); } /* intel needs this */ -__initfunc(void initialize_secondary(void)) +void __init initialize_secondary(void) { } @@ -275,33 +294,34 @@ asmlinkage int __init start_secondary(void *unused) return cpu_idle(NULL); } -__initfunc(void smp_callin(void)) +void __init smp_callin(void) { printk("SMP %d: smp_callin()\n",current->processor); smp_store_cpu_info(current->processor); set_dec(decrementer_count); - +#if 0 current->mm->mmap->vm_page_prot = PAGE_SHARED; current->mm->mmap->vm_start = PAGE_OFFSET; current->mm->mmap->vm_end = init_task.mm->mmap->vm_end; - - cpu_callin_map[current->processor] = current->processor; +#endif + cpu_callin_map[current->processor] = 1; while(!smp_commenced) barrier(); __sti(); + printk("SMP %d: smp_callin done\n", current->processor); } -__initfunc(void smp_setup(char *str, int *ints)) +void __init smp_setup(char *str, int *ints) { printk("SMP %d: smp_setup()\n",current->processor); } -__initfunc(int setup_profiling_timer(unsigned int multiplier)) +int __init setup_profiling_timer(unsigned int multiplier) { return 0; } -__initfunc(void smp_store_cpu_info(int id)) +void __init smp_store_cpu_info(int id) { struct cpuinfo_PPC *c = &cpu_data[id]; diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c index 8bada0e69..32f60a236 100644 --- a/arch/ppc/kernel/time.c +++ b/arch/ppc/kernel/time.c @@ -1,5 +1,5 @@ /* - * $Id: time.c,v 1.36 1998/10/10 12:16:08 geert Exp $ + * $Id: time.c,v 1.39 1998/12/28 10:28:51 paulus Exp $ * Common time routines among all ppc machines. * * Written by Cort Dougan (cort@cs.nmt.edu) to merge @@ -17,6 +17,9 @@ * This is then divided by 4, providing a 8192 Hz clock into the PIT. * Since it is not possible to get a nice 100 Hz clock out of this, without * creating a software PLL, I have set HZ to 128. -- Dan + * + * 1997-09-10 Updated NTP code according to technical memorandum Jan '96 + * "A Kernel Model for Precision Timekeeping" by Dave Mills */ #include <linux/config.h> @@ -78,6 +81,26 @@ void timer_interrupt(struct pt_regs * regs) unsigned dcache_locked = unlock_dcache(); hardirq_enter(cpu); +#ifdef __SMP__ + { + unsigned int loops = 100000000; + while (test_bit(0, &global_irq_lock)) { + if (smp_processor_id() == global_irq_holder) { + printk("uh oh, interrupt while we hold global irq lock!\n"); +#ifdef CONFIG_XMON + xmon(0); +#endif + break; + } + if (loops-- == 0) { + printk("do_IRQ waiting for irq lock (holder=%d)\n", global_irq_holder); +#ifdef CONFIG_XMON + xmon(0); +#endif + } + } + } +#endif /* __SMP__ */ while ((dval = get_dec()) < 0) { /* @@ -133,9 +156,9 @@ void timebase_interrupt(int irq, void * dev, struct pt_regs * regs) static int mbx_set_rtc_time(unsigned long time) { - ((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_rtck = KAPWR_KEY; - ((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_rtc = time; - ((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_rtck = ~KAPWR_KEY; + ((immap_t *)IMAP_ADDR)->im_sitk.sitk_rtck = KAPWR_KEY; + ((immap_t *)IMAP_ADDR)->im_sit.sit_rtc = time; + ((immap_t *)IMAP_ADDR)->im_sitk.sitk_rtck = ~KAPWR_KEY; return(0); } #endif /* CONFIG_MBX */ @@ -150,12 +173,15 @@ void do_gettimeofday(struct timeval *tv) save_flags(flags); cli(); *tv = xtime; + /* XXX we don't seem to have the decrementers synced properly yet */ +#ifndef __SMP__ tv->tv_usec += (decrementer_count - get_dec()) * count_period_num / count_period_den; if (tv->tv_usec >= 1000000) { tv->tv_usec -= 1000000; tv->tv_sec++; } +#endif restore_flags(flags); } @@ -172,6 +198,11 @@ void do_settimeofday(struct timeval *tv) xtime.tv_sec = tv->tv_sec; xtime.tv_usec = tv->tv_usec - frac_tick; set_dec(frac_tick * count_period_den / count_period_num); + time_adjust = 0; /* stop active adjtime() */ + time_status |= STA_UNSYNC; + time_state = TIME_ERROR; /* p. 24, (a) */ + time_maxerror = NTP_PHASE_LIMIT; + time_esterror = NTP_PHASE_LIMIT; restore_flags(flags); } @@ -227,13 +258,13 @@ __initfunc(void time_init(void)) * modify these registers we have to write the key value to * the key location associated with the register. */ - ((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_tbscrk = KAPWR_KEY; - ((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_rtcsck = KAPWR_KEY; + ((immap_t *)IMAP_ADDR)->im_sitk.sitk_tbscrk = KAPWR_KEY; + ((immap_t *)IMAP_ADDR)->im_sitk.sitk_rtcsck = KAPWR_KEY; /* Disable the RTC one second and alarm interrupts. */ - ((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_rtcsc &= + ((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc &= ~(RTCSC_SIE | RTCSC_ALE); /* Enabling the decrementer also enables the timebase interrupts @@ -241,7 +272,7 @@ __initfunc(void time_init(void)) * we have to enable the timebase). The decrementer interrupt * is wired into the vector table, nothing to do here for that. */ - ((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_tbscr = + ((immap_t *)IMAP_ADDR)->im_sit.sit_tbscr = ((mk_int_int_mask(DEC_INTERRUPT) << 8) | (TBSCR_TBF | TBSCR_TBE)); if (request_irq(DEC_INTERRUPT, timebase_interrupt, 0, "tbint", NULL) != 0) @@ -249,7 +280,7 @@ __initfunc(void time_init(void)) /* Get time from the RTC. */ - xtime.tv_sec = ((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_rtc; + xtime.tv_sec = ((immap_t *)IMAP_ADDR)->im_sit.sit_rtc; xtime.tv_usec = 0; #endif /* CONFIG_MBX */ @@ -343,10 +374,10 @@ __initfunc(void prep_calibrate_decr_handler(int irq, void *dev, struct pt_regs * */ __initfunc(void mbx_calibrate_decr(void)) { - bd_t *binfo = (bd_t *)&res; + bd_t *binfo = (bd_t *)res; int freq, fp, divisor; - if ((((immap_t *)MBX_IMAP_ADDR)->im_clkrst.car_sccr & 0x02000000) == 0) + if ((((immap_t *)IMAP_ADDR)->im_clkrst.car_sccr & 0x02000000) == 0) printk("WARNING: Wrong decrementer source clock.\n"); /* The manual says the frequency is in Hz, but it is really diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index af02252f9..fa5184af2 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c @@ -79,6 +79,7 @@ _exception(int signr, struct pt_regs *regs) debugger(regs); #endif print_backtrace((unsigned long *)regs->gpr[1]); + instruction_dump((unsigned long *)regs->nip); panic("Exception in kernel pc %lx signal %d",regs->nip,signr); } force_sig(signr, current); @@ -126,6 +127,7 @@ MachineCheckException(struct pt_regs *regs) debugger(regs); #endif print_backtrace((unsigned long *)regs->gpr[1]); + instruction_dump((unsigned long *)regs->nip); panic("machine check"); } _exception(SIGSEGV, regs); @@ -219,6 +221,7 @@ StackOverflow(struct pt_regs *regs) #endif show_regs(regs); print_backtrace((unsigned long *)regs->gpr[1]); + instruction_dump((unsigned long *)regs->nip); panic("kernel stack overflow"); } |