diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-06-15 01:55:58 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-06-15 01:55:58 +0000 |
commit | 53b3988d474435254a3b053a68bb24ce9e439295 (patch) | |
tree | f8da8e40f01f4ad02bbd76b8c9920749b118235f /arch/ppc/kernel | |
parent | b0cb48abe83d1a4389ea938bf624f8baa82c5047 (diff) |
Merge with 2.3.99-pre9.
Diffstat (limited to 'arch/ppc/kernel')
-rw-r--r-- | arch/ppc/kernel/chrp_pci.c | 37 | ||||
-rw-r--r-- | arch/ppc/kernel/chrp_setup.c | 39 | ||||
-rw-r--r-- | arch/ppc/kernel/chrp_time.c | 9 | ||||
-rw-r--r-- | arch/ppc/kernel/entry.S | 89 | ||||
-rw-r--r-- | arch/ppc/kernel/head.S | 3 | ||||
-rw-r--r-- | arch/ppc/kernel/ppc_ksyms.c | 3 | ||||
-rw-r--r-- | arch/ppc/kernel/ptrace.c | 507 | ||||
-rw-r--r-- | arch/ppc/kernel/setup.c | 7 | ||||
-rw-r--r-- | arch/ppc/kernel/time.c | 24 | ||||
-rw-r--r-- | arch/ppc/kernel/traps.c | 9 |
10 files changed, 253 insertions, 474 deletions
diff --git a/arch/ppc/kernel/chrp_pci.c b/arch/ppc/kernel/chrp_pci.c index a2fbe5f14..e609906cb 100644 --- a/arch/ppc/kernel/chrp_pci.c +++ b/arch/ppc/kernel/chrp_pci.c @@ -17,6 +17,7 @@ #include <asm/prom.h> #include <asm/gg2.h> #include <asm/machdep.h> +#include <asm/init.h> #include "pci.h" @@ -31,7 +32,7 @@ volatile struct Hydra *Hydra = NULL; * limit the bus number to 3 bits */ -int gg2_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, +int __chrp gg2_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned char *val) { if (bus > 7) { @@ -42,7 +43,7 @@ int gg2_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, return PCIBIOS_SUCCESSFUL; } -int gg2_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, +int __chrp gg2_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned short *val) { if (bus > 7) { @@ -54,7 +55,7 @@ int gg2_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, } -int gg2_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, +int __chrp gg2_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned int *val) { if (bus > 7) { @@ -65,7 +66,7 @@ int gg2_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, return PCIBIOS_SUCCESSFUL; } -int gg2_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, +int __chrp gg2_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned char val) { if (bus > 7) @@ -74,7 +75,7 @@ int gg2_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, return PCIBIOS_SUCCESSFUL; } -int gg2_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, +int __chrp gg2_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned short val) { if (bus > 7) @@ -83,7 +84,7 @@ int gg2_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, return PCIBIOS_SUCCESSFUL; } -int gg2_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, +int __chrp gg2_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned int val) { if (bus > 7) @@ -98,7 +99,7 @@ int gg2_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, | (((o) & ~3) << 24)) unsigned int python_busnr = 0; -int python_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, +int __chrp python_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned char *val) { if (bus > python_busnr) { @@ -110,7 +111,7 @@ int python_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, return PCIBIOS_SUCCESSFUL; } -int python_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, +int __chrp python_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned short *val) { if (bus > python_busnr) { @@ -123,7 +124,7 @@ int python_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, } -int python_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, +int __chrp python_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned int *val) { if (bus > python_busnr) { @@ -135,7 +136,7 @@ int python_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, return PCIBIOS_SUCCESSFUL; } -int python_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, +int __chrp python_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned char val) { if (bus > python_busnr) @@ -145,7 +146,7 @@ int python_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, return PCIBIOS_SUCCESSFUL; } -int python_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, +int __chrp python_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned short val) { if (bus > python_busnr) @@ -156,7 +157,7 @@ int python_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, return PCIBIOS_SUCCESSFUL; } -int python_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, +int __chrp python_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned int val) { if (bus > python_busnr) @@ -167,7 +168,7 @@ int python_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, } -int rtas_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, +int __chrp rtas_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned char *val) { unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16); @@ -176,7 +177,7 @@ int rtas_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, return PCIBIOS_SUCCESSFUL; } -int rtas_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, +int __chrp rtas_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned short *val) { unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16); @@ -186,7 +187,7 @@ int rtas_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, } -int rtas_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, +int __chrp rtas_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned int *val) { unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16); @@ -195,7 +196,7 @@ int rtas_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, return PCIBIOS_SUCCESSFUL; } -int rtas_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, +int __chrp rtas_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned char val) { unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16); @@ -204,7 +205,7 @@ int rtas_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, return PCIBIOS_SUCCESSFUL; } -int rtas_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, +int __chrp rtas_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned short val) { unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16); @@ -213,7 +214,7 @@ int rtas_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, return PCIBIOS_SUCCESSFUL; } -int rtas_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, +int __chrp rtas_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned int val) { unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16); diff --git a/arch/ppc/kernel/chrp_setup.c b/arch/ppc/kernel/chrp_setup.c index 3b541c26f..d8c22e1a6 100644 --- a/arch/ppc/kernel/chrp_setup.c +++ b/arch/ppc/kernel/chrp_setup.c @@ -49,6 +49,7 @@ #include <asm/irq.h> #include <asm/hydra.h> #include <asm/keyboard.h> +#include <asm/init.h> #include "time.h" #include "local_irq.h" @@ -112,7 +113,7 @@ static const char *gg2_cachemodes[4] = { "Disabled", "Write-Through", "Copy-Back", "Transparent Mode" }; -int +int __chrp chrp_get_cpuinfo(char *buffer) { int i, len, sdramen; @@ -306,7 +307,7 @@ chrp_setup_arch(void) } } -void +void __chrp chrp_event_scan(void) { unsigned char log[1024]; @@ -317,7 +318,7 @@ chrp_event_scan(void) ppc_md.heartbeat_count = ppc_md.heartbeat_reset; } -void +void __chrp chrp_restart(char *cmd) { printk("RTAS system-reboot returned %d\n", @@ -325,7 +326,7 @@ chrp_restart(char *cmd) for (;;); } -void +void __chrp chrp_power_off(void) { /* allow power on only with power button press */ @@ -334,13 +335,13 @@ chrp_power_off(void) for (;;); } -void +void __chrp chrp_halt(void) { chrp_power_off(); } -u_int +u_int __chrp chrp_irq_cannonicalize(u_int irq) { if (irq == 2) @@ -353,7 +354,7 @@ chrp_irq_cannonicalize(u_int irq) } } -int chrp_get_irq( struct pt_regs *regs ) +int __chrp chrp_get_irq( struct pt_regs *regs ) { int irq; @@ -383,7 +384,7 @@ int chrp_get_irq( struct pt_regs *regs ) return irq; } -void chrp_post_irq(struct pt_regs* regs, int irq) +void __chrp chrp_post_irq(struct pt_regs* regs, int irq) { /* * If it's an i8259 irq then we've already done the @@ -445,7 +446,7 @@ int chrp_ide_ports_known = 0; ide_ioreg_t chrp_ide_regbase[MAX_HWIFS]; ide_ioreg_t chrp_idedma_regbase; -void +void __chrp chrp_ide_probe(void) { struct pci_dev *pdev = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, NULL); @@ -460,19 +461,19 @@ chrp_ide_probe(void) } } -void +void __chrp chrp_ide_insw(ide_ioreg_t port, void *buf, int ns) { ide_insw(port+_IO_BASE, buf, ns); } -void +void __chrp chrp_ide_outsw(ide_ioreg_t port, void *buf, int ns) { ide_outsw(port+_IO_BASE, buf, ns); } -int +int __chrp chrp_ide_default_irq(ide_ioreg_t base) { if (chrp_ide_ports_known == 0) @@ -480,7 +481,7 @@ chrp_ide_default_irq(ide_ioreg_t base) return chrp_ide_irq; } -ide_ioreg_t +ide_ioreg_t __chrp chrp_ide_default_io_base(int index) { if (chrp_ide_ports_known == 0) @@ -488,13 +489,13 @@ chrp_ide_default_io_base(int index) return chrp_ide_regbase[index]; } -int +int __chrp chrp_ide_check_region(ide_ioreg_t from, unsigned int extent) { return check_region(from, extent); } -void +void __chrp chrp_ide_request_region(ide_ioreg_t from, unsigned int extent, const char *name) @@ -502,20 +503,20 @@ chrp_ide_request_region(ide_ioreg_t from, request_region(from, extent, name); } -void +void __chrp chrp_ide_release_region(ide_ioreg_t from, unsigned int extent) { release_region(from, extent); } -void +void __chrp chrp_ide_fix_driveid(struct hd_driveid *id) { ppc_generic_ide_fix_driveid(id); } -void +void __chrp chrp_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq) { ide_ioreg_t reg = data_port; @@ -629,7 +630,7 @@ void __init if ( ppc_md.progress ) ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0x0); } -void +void __chrp chrp_progress(char *s, unsigned short hex) { extern unsigned int rtas_data; diff --git a/arch/ppc/kernel/chrp_time.c b/arch/ppc/kernel/chrp_time.c index c692b54d0..6d275e517 100644 --- a/arch/ppc/kernel/chrp_time.c +++ b/arch/ppc/kernel/chrp_time.c @@ -25,6 +25,7 @@ #include <asm/processor.h> #include <asm/nvram.h> #include <asm/prom.h> +#include <asm/init.h> #include "time.h" static int nvram_as1 = NVRAM_AS1; @@ -45,7 +46,7 @@ void __init chrp_time_init(void) nvram_data = base + 1; } -int chrp_cmos_clock_read(int addr) +int __chrp chrp_cmos_clock_read(int addr) { if (nvram_as1 != 0) outb(addr>>8, nvram_as1); @@ -53,7 +54,7 @@ int chrp_cmos_clock_read(int addr) return (inb(nvram_data)); } -void chrp_cmos_clock_write(unsigned long val, int addr) +void __chrp chrp_cmos_clock_write(unsigned long val, int addr) { if (nvram_as1 != 0) outb(addr>>8, nvram_as1); @@ -65,7 +66,7 @@ void chrp_cmos_clock_write(unsigned long val, int addr) /* * Set the hardware clock. -- Cort */ -int chrp_set_rtc_time(unsigned long nowtime) +int __chrp chrp_set_rtc_time(unsigned long nowtime) { unsigned char save_control, save_freq_select; struct rtc_time tm; @@ -111,7 +112,7 @@ int chrp_set_rtc_time(unsigned long nowtime) return 0; } -unsigned long chrp_get_rtc_time(void) +unsigned long __chrp chrp_get_rtc_time(void) { unsigned int year, mon, day, hour, min, sec; int i; diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S index cc647a58b..ad467894f 100644 --- a/arch/ppc/kernel/entry.S +++ b/arch/ppc/kernel/entry.S @@ -291,25 +291,9 @@ ret_from_intercept: * -- Cort */ cmpi 0,r3,0 - bne ret_from_except - /* - * If we're returning from user mode we do things differently - * -- Cort - */ - lwz r3,_MSR(r1) - andi. r3,r3,MSR_PR - beq+ 10f - b 8f - + beq restore .globl ret_from_except ret_from_except: -0: /* disable interrupts */ - lis r30,int_control@h - ori r30,r30,int_control@l - lwz r30,0(r30) - mtlr r30 - blrl - lwz r5,_MSR(r1) andi. r5,r5,MSR_EE beq 2f @@ -341,65 +325,58 @@ lost_irq_ret: bl do_softirq .globl do_bottom_half_ret do_bottom_half_ret: -2: /* disable interrupts */ - lis r30,int_control@h - ori r30,r30,int_control@l - lwz r30,0(r30) - mtlr r30 - blrl - lwz r3,_MSR(r1) /* Returning to user mode? */ +2: lwz r3,_MSR(r1) /* Returning to user mode? */ andi. r3,r3,MSR_PR - beq+ 10f /* if so, check need_resched and signals */ + beq+ restore /* if so, check need_resched and signals */ + .globl ret_to_user_hook +ret_to_user_hook: + nop lwz r3,NEED_RESCHED(r2) cmpi 0,r3,0 /* check need_resched flag */ beq+ 7f bl schedule - b 0b 7: lwz r5,SIGPENDING(r2) /* Check for pending unblocked signals */ cmpwi 0,r5,0 - beq+ 8f + beq+ restore li r3,0 addi r4,r1,STACK_FRAME_OVERHEAD bl do_signal .globl do_signal_ret do_signal_ret: - b 0b -8: /* - * We need to hard disable here even if RTL is active since - * being interrupted after here trashes the SPRG2 - * -- Cort - */ - mfmsr r0 /* Get current interrupt state */ - rlwinm r0,r0,0,17,15 /* clear MSR_EE in r0 */ - mtmsr r0 /* Update machine state */ - - addi r4,r1,INT_FRAME_SIZE /* size of frame */ - stw r4,THREAD+KSP(r2) /* save kernel stack pointer */ - tophys(r3,r1) - mtspr SPRG2,r3 /* phys exception stack pointer */ - b 11f -10: /* make sure we hard disable here, even if rtl is active -- Cort */ - mfmsr r0 /* Get current interrupt state */ - rlwinm r0,r0,0,17,15 /* clear MSR_EE in r0 */ - sync /* Some chip revs have problems here... */ - mtmsr r0 /* Update machine state */ -11: - lwz r2,_CTR(r1) +restore: + lwz r3,_CTR(r1) lwz r0,_LINK(r1) - mtctr r2 + mtctr r3 mtlr r0 - lwz r2,_XER(r1) - lwz r0,_CCR(r1) - mtspr XER,r2 - mtcrf 0xFF,r0 + lwz r3,_XER(r1) + mtspr XER,r3 REST_10GPRS(3, r1) REST_10GPRS(13, r1) REST_8GPRS(23, r1) REST_GPR(31, r1) - lwz r2,_NIP(r1) /* Restore environment */ + + /* make sure we hard disable here, even if rtl is active, to protect + * SRR[01] and SPRG2 -- Cort + */ + mfmsr r0 /* Get current interrupt state */ + rlwinm r0,r0,0,17,15 /* clear MSR_EE in r0 */ + sync /* Some chip revs have problems here... */ + mtmsr r0 /* Update machine state */ + + /* if returning to user mode, set new sprg2 and save kernel SP */ lwz r0,_MSR(r1) - mtspr SRR0,r2 mtspr SRR1,r0 + andi. r0,r0,MSR_PR + beq+ 1f + addi r0,r1,INT_FRAME_SIZE /* size of frame */ + stw r0,THREAD+KSP(r2) /* save kernel stack pointer */ + tophys(r2,r1) + mtspr SPRG2,r2 /* phys exception stack pointer */ +1: + lwz r2,_CCR(r1) + mtcrf 0xFF,r2 + lwz r2,_NIP(r1) + mtspr SRR0,r2 lwz r0,GPR0(r1) lwz r2,GPR2(r1) lwz r1,GPR1(r1) diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S index 6700806bd..f88c5383d 100644 --- a/arch/ppc/kernel/head.S +++ b/arch/ppc/kernel/head.S @@ -1459,7 +1459,8 @@ start_here: /* * Set up the segment registers for a new context. */ -_GLOBAL(set_context) + .globl set_context +set_context: rlwinm r3,r3,4,8,27 /* VSID = context << 4 */ addis r3,r3,0x6000 /* Set Ks, Ku bits */ li r0,12 /* TASK_SIZE / SEGMENT_SIZE */ diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index 9b7d2be31..6d7f2aff7 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c @@ -58,6 +58,7 @@ long long __ashrdi3(long long, int); long long __ashldi3(long long, int); long long __lshrdi3(long long, int); int abs(int); +extern unsigned long ret_to_user_hook; EXPORT_SYMBOL(clear_page); EXPORT_SYMBOL(do_signal); @@ -284,3 +285,5 @@ EXPORT_SYMBOL(debugger_sstep); EXPORT_SYMBOL(debugger_iabr_match); EXPORT_SYMBOL(debugger_dabr_match); EXPORT_SYMBOL(debugger_fault_handler); + +EXPORT_SYMBOL(ret_to_user_hook); diff --git a/arch/ppc/kernel/ptrace.c b/arch/ppc/kernel/ptrace.c index fe0bfcea2..3ccc8f518 100644 --- a/arch/ppc/kernel/ptrace.c +++ b/arch/ppc/kernel/ptrace.c @@ -1,7 +1,7 @@ /* * linux/arch/ppc/kernel/ptrace.c * - * PowerPC version + * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * * Derived from "arch/m68k/kernel/ptrace.c" @@ -9,14 +9,14 @@ * Taken from linux/kernel/ptrace.c and modified for M680x0. * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds * - * Modified by Cort Dougan (cort@cs.nmt.edu) + * Modified by Cort Dougan (cort@hq.fsmlabs.com) + * and Paul Mackerras (paulus@linuxcare.com.au). * * This file is subject to the terms and conditions of the GNU General * Public License. See the file README.legal in the main directory of * this archive for more details. */ -#include <stddef.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/mm.h> @@ -26,7 +26,7 @@ #include <linux/ptrace.h> #include <linux/user.h> -#include <asm/segment.h> +#include <asm/uaccess.h> #include <asm/page.h> #include <asm/pgtable.h> #include <asm/system.h> @@ -44,7 +44,7 @@ /* * Get contents of register REGNO in task TASK. */ -static inline long get_reg(struct task_struct *task, int regno) +static inline unsigned long get_reg(struct task_struct *task, int regno) { if (regno < sizeof(struct pt_regs) / sizeof(unsigned long)) return ((unsigned long *)task->thread.regs)[regno]; @@ -64,7 +64,7 @@ static inline int put_reg(struct task_struct *task, int regno, ((unsigned long *)task->thread.regs)[regno] = data; return 0; } - return -1; + return -EIO; } static inline void @@ -81,216 +81,10 @@ clear_single_step(struct task_struct *task) regs->msr &= ~MSR_SE; } -#if 0 -/* - * This routine gets a long from any process space by following the page - * tables. NOTE! You should check that the long isn't on a page boundary, - * and that it is in the task area before calling this: this routine does - * no checking. - * - */ -static unsigned long get_long(struct task_struct * tsk, - struct vm_area_struct * vma, unsigned long addr) -{ - pgd_t * pgdir; - pmd_t * pgmiddle; - pte_t * pgtable; - unsigned long page; - -repeat: - pgdir = pgd_offset(vma->vm_mm, addr); - if (pgd_none(*pgdir)) { - handle_mm_fault(tsk->mm, vma, addr, 0); - goto repeat; - } - if (pgd_bad(*pgdir)) { - printk("ptrace[1]: bad page directory %lx\n", pgd_val(*pgdir)); - pgd_clear(pgdir); - return 0; - } - pgmiddle = pmd_offset(pgdir,addr); - if (pmd_none(*pgmiddle)) { - handle_mm_fault(tsk->mm, vma, addr, 0); - goto repeat; - } - if (pmd_bad(*pgmiddle)) { - printk("ptrace[3]: bad pmd %lx\n", pmd_val(*pgmiddle)); - pmd_clear(pgmiddle); - return 0; - } - pgtable = pte_offset(pgmiddle, addr); - if (!pte_present(*pgtable)) { - handle_mm_fault(tsk->mm, vma, addr, 0); - goto repeat; - } - page = pte_page(*pgtable); -/* this is a hack for non-kernel-mapped video buffers and similar */ - if (MAP_NR(page) >= max_mapnr) - return 0; - page += addr & ~PAGE_MASK; - return *(unsigned long *) page; -} - -/* - * This routine puts a long into any process space by following the page - * tables. NOTE! You should check that the long isn't on a page boundary, - * and that it is in the task area before calling this: this routine does - * no checking. - * - * Now keeps R/W state of page so that a text page stays readonly - * even if a debugger scribbles breakpoints into it. -M.U- - */ -static void put_long(struct task_struct * tsk, struct vm_area_struct * vma, - unsigned long addr, unsigned long data) -{ - pgd_t *pgdir; - pmd_t *pgmiddle; - pte_t *pgtable; - unsigned long page; - -repeat: - pgdir = pgd_offset(vma->vm_mm, addr); - if (!pgd_present(*pgdir)) { - handle_mm_fault(tsk->mm, vma, addr, 1); - goto repeat; - } - if (pgd_bad(*pgdir)) { - printk("ptrace[2]: bad page directory %lx\n", pgd_val(*pgdir)); - pgd_clear(pgdir); - return; - } - pgmiddle = pmd_offset(pgdir,addr); - if (pmd_none(*pgmiddle)) { - handle_mm_fault(tsk->mm, vma, addr, 1); - goto repeat; - } - if (pmd_bad(*pgmiddle)) { - printk("ptrace[4]: bad pmd %lx\n", pmd_val(*pgmiddle)); - pmd_clear(pgmiddle); - return; - } - pgtable = pte_offset(pgmiddle, addr); - if (!pte_present(*pgtable)) { - handle_mm_fault(tsk->mm, vma, addr, 1); - goto repeat; - } - page = pte_page(*pgtable); - if (!pte_write(*pgtable)) { - handle_mm_fault(tsk->mm, vma, addr, 1); - goto repeat; - } -/* this is a hack for non-kernel-mapped video buffers and similar */ - if (MAP_NR(page) < max_mapnr) { - unsigned long phys_addr = page + (addr & ~PAGE_MASK); - *(unsigned long *) phys_addr = data; - flush_icache_range(phys_addr, phys_addr+4); - } -/* we're bypassing pagetables, so we have to set the dirty bit ourselves */ -/* this should also re-instate whatever read-only mode there was before */ - set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot))); - flush_tlb_all(); -} - -/* - * This routine checks the page boundaries, and that the offset is - * within the task area. It then calls get_long() to read a long. - */ -static int read_long(struct task_struct * tsk, unsigned long addr, - unsigned long * result) -{ - struct vm_area_struct * vma = find_extend_vma(tsk->mm, addr); - - if (!vma) - return -EIO; - if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) { - unsigned long low,high; - struct vm_area_struct * vma_low = vma; - - if (addr + sizeof(long) >= vma->vm_end) { - vma_low = vma->vm_next; - if (!vma_low || vma_low->vm_start != vma->vm_end) - return -EIO; - } - high = get_long(tsk, vma,addr & ~(sizeof(long)-1)); - low = get_long(tsk, vma_low,(addr+sizeof(long)) & ~(sizeof(long)-1)); - switch (addr & (sizeof(long)-1)) { - case 3: - low >>= 8; - low |= high << 24; - break; - case 2: - low >>= 16; - low |= high << 16; - break; - case 1: - low >>= 24; - low |= high << 8; - break; - } - *result = low; - } else - *result = get_long(tsk, vma,addr); - return 0; -} - -/* - * This routine checks the page boundaries, and that the offset is - * within the task area. It then calls put_long() to write a long. - */ -static int write_long(struct task_struct * tsk, unsigned long addr, - unsigned long data) -{ - struct vm_area_struct * vma = find_extend_vma(tsk->mm, addr); - - if (!vma) - return -EIO; - if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) { - unsigned long low,high; - struct vm_area_struct * vma_low = vma; - - if (addr + sizeof(long) >= vma->vm_end) { - vma_low = vma->vm_next; - if (!vma_low || vma_low->vm_start != vma->vm_end) - return -EIO; - } - high = get_long(tsk, vma,addr & ~(sizeof(long)-1)); - low = get_long(tsk, vma_low,(addr+sizeof(long)) & ~(sizeof(long)-1)); - switch (addr & (sizeof(long)-1)) { - case 0: /* shouldn't happen, but safety first */ - high = data; - break; - case 3: - low &= 0x000000ff; - low |= data << 8; - high &= ~0xff; - high |= data >> 24; - break; - case 2: - low &= 0x0000ffff; - low |= data << 16; - high &= ~0xffff; - high |= data >> 16; - break; - case 1: - low &= 0x00ffffff; - low |= data << 24; - high &= ~0xffffff; - high |= data >> 8; - break; - } - put_long(tsk, vma,addr & ~(sizeof(long)-1),high); - put_long(tsk, vma_low,(addr+sizeof(long)) & ~(sizeof(long)-1),low); - } else - put_long(tsk, vma,addr,data); - return 0; -} -#endif - -asmlinkage int sys_ptrace(long request, long pid, long addr, long data) +int sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; int ret = -EPERM; - unsigned long flags; lock_kernel(); if (request == PTRACE_TRACEME) { @@ -302,209 +96,209 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ret = 0; goto out; } - if (pid == 1) /* you may not mess with init */ - goto out; ret = -ESRCH; read_lock(&tasklist_lock); child = find_task_by_pid(pid); - read_unlock(&tasklist_lock); /* FIXME!!! */ - if ( !child ) + if (child) + get_task_struct(child); + read_unlock(&tasklist_lock); + if (!child) goto out; + ret = -EPERM; + if (pid == 1) /* you may not mess with init */ + goto out_tsk; + if (request == PTRACE_ATTACH) { if (child == current) - goto out; + goto out_tsk; if ((!child->dumpable || (current->uid != child->euid) || - (current->uid != child->uid) || (current->uid != child->suid) || + (current->uid != child->uid) || (current->gid != child->egid) || - (current->gid != child->gid) || (current->gid != child->sgid) || - (!cap_issubset(child->cap_permitted, current->cap_permitted))) + (!cap_issubset(child->cap_permitted, current->cap_permitted)) || + (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) - goto out; + goto out_tsk; /* the same process cannot be attached many times */ if (child->flags & PF_PTRACED) - goto out; + goto out_tsk; child->flags |= PF_PTRACED; - - write_lock_irqsave(&tasklist_lock, flags); + + write_lock_irq(&tasklist_lock); if (child->p_pptr != current) { REMOVE_LINKS(child); child->p_pptr = current; SET_LINKS(child); } - write_unlock_irqrestore(&tasklist_lock, flags); + write_unlock_irq(&tasklist_lock); send_sig(SIGSTOP, child, 1); ret = 0; - goto out; + goto out_tsk; } ret = -ESRCH; if (!(child->flags & PF_PTRACED)) - goto out; + goto out_tsk; if (child->state != TASK_STOPPED) { if (request != PTRACE_KILL) - goto out; + goto out_tsk; } if (child->p_pptr != current) - goto out; + goto out_tsk; switch (request) { /* when I and D space are separate, these will need to be fixed. */ - case PTRACE_PEEKTEXT: /* read word at location addr. */ - case PTRACE_PEEKDATA: { - unsigned long tmp; - int copied; + case PTRACE_PEEKTEXT: /* read word at location addr. */ + case PTRACE_PEEKDATA: { + unsigned long tmp; + int copied; + + copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); + ret = -EIO; + if (copied != sizeof(tmp)) + break; + ret = put_user(tmp,(unsigned long *) data); + break; + } - copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); - ret = -EIO; - if (copied != sizeof(tmp)) - goto out; - ret = put_user(tmp,(unsigned long *) data); - goto out; - } /* read the word at location addr in the USER area. */ - case PTRACE_PEEKUSR: { - unsigned long tmp; - - if ((addr & 3) || addr < 0 || addr > (PT_FPSCR << 2)) { - ret = -EIO; - goto out; - } - - ret = verify_area(VERIFY_WRITE, (void *) data, - sizeof(long)); - if (ret) - goto out; - tmp = 0; /* Default return condition */ - addr = addr >> 2; /* temporary hack. */ - if (addr < PT_FPR0) { - tmp = get_reg(child, addr); - } - else if (addr >= PT_FPR0 && addr <= PT_FPSCR) { - if (child->thread.regs->msr & MSR_FP) - giveup_fpu(child); - tmp = ((long *)child->thread.fpr)[addr - PT_FPR0]; - } - else - ret = -EIO; - if (!ret) - put_user(tmp,(unsigned long *) data); - goto out; + /* XXX this will need fixing for 64-bit */ + case PTRACE_PEEKUSR: { + unsigned long index, tmp; + + ret = -EIO; + /* convert to index and check */ + index = (unsigned long) addr >> 2; + if ((addr & 3) || index > PT_FPSCR) + break; + + if (addr < PT_FPR0) { + tmp = get_reg(child, (int) index); + } else { + if (child->thread.regs->msr & MSR_FP) + giveup_fpu(child); + tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0]; } + ret = put_user(tmp,(unsigned long *) data); + break; + } - /* 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: - ret = 0; - if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) - goto out; - ret = -EIO; - goto out; - case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ - ret = -EIO; - if ((addr & 3) || addr < 0 || addr >= ((PT_FPR0 + 64) << 2)) - goto out; + /* 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: + ret = 0; + if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) + break; + ret = -EIO; + break; - addr = addr >> 2; /* temporary hack. */ - - if (addr == PT_ORIG_R3) - goto out; - if (addr < PT_FPR0) { - if (put_reg(child, addr, data)) - goto out; - ret = 0; - goto out; - } - if (addr >= PT_FPR0 && addr < PT_FPR0 + 64) { - if (child->thread.regs->msr & MSR_FP) - giveup_fpu(child); - ((long *)child->thread.fpr)[addr - PT_FPR0] = data; - ret = 0; - goto out; - } - goto out; + /* write the word at location addr in the USER area */ + /* XXX this will need fixing for 64-bit */ + case PTRACE_POKEUSR: { + unsigned long index; - case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ - case PTRACE_CONT: { /* restart after signal. */ - ret = -EIO; - if ((unsigned long) data >= _NSIG) - goto out; - if (request == PTRACE_SYSCALL) - child->flags |= PF_TRACESYS; - else - child->flags &= ~PF_TRACESYS; - child->exit_code = data; - wake_up_process(child); - /* make sure the single step bit is not set. */ - clear_single_step(child); + ret = -EIO; + /* convert to index and check */ + index = (unsigned long) addr >> 2; + if ((addr & 3) || index > PT_FPSCR) + break; + + if (addr == PT_ORIG_R3) + break; + if (addr < PT_FPR0) { + ret = put_reg(child, addr, data); + } else { + if (child->thread.regs->msr & MSR_FP) + giveup_fpu(child); + ((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data; ret = 0; - goto out; } + break; + } + + case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ + case PTRACE_CONT: { /* restart after signal. */ + ret = -EIO; + if ((unsigned long) data > _NSIG) + break; + if (request == PTRACE_SYSCALL) + child->flags |= PF_TRACESYS; + else + child->flags &= ~PF_TRACESYS; + child->exit_code = data; + /* make sure the single step bit is not set. */ + clear_single_step(child); + wake_up_process(child); + ret = 0; + break; + } /* * make the child exit. Best I can do is send it a sigkill. * perhaps it should be put in the status that it wants to * exit. */ - case PTRACE_KILL: { - ret = 0; - if (child->state == TASK_ZOMBIE) /* already dead */ - goto out; - wake_up_process(child); - child->exit_code = SIGKILL; - /* make sure the single step bit is not set. */ - clear_single_step(child); - goto out; - } + case PTRACE_KILL: { + ret = 0; + if (child->state == TASK_ZOMBIE) /* already dead */ + break; + child->exit_code = SIGKILL; + /* make sure the single step bit is not set. */ + clear_single_step(child); + wake_up_process(child); + break; + } - case PTRACE_SINGLESTEP: { /* set the trap flag. */ - ret = -EIO; - if ((unsigned long) data >= _NSIG) - goto out; - child->flags &= ~PF_TRACESYS; - set_single_step(child); - child->exit_code = data; - /* give it a chance to run. */ - wake_up_process(child); - ret = 0; - goto out; - } + case PTRACE_SINGLESTEP: { /* set the trap flag. */ + ret = -EIO; + if ((unsigned long) data > _NSIG) + break; + child->flags &= ~PF_TRACESYS; + set_single_step(child); + child->exit_code = data; + /* give it a chance to run. */ + wake_up_process(child); + ret = 0; + break; + } - case PTRACE_DETACH: { /* detach a process that was attached. */ - ret = -EIO; - if ((unsigned long) data >= _NSIG) - goto out; - child->flags &= ~(PF_PTRACED|PF_TRACESYS); - wake_up_process(child); - child->exit_code = data; - write_lock_irqsave(&tasklist_lock, flags); - REMOVE_LINKS(child); - child->p_pptr = child->p_opptr; - SET_LINKS(child); - write_unlock_irqrestore(&tasklist_lock, flags); - /* make sure the single step bit is not set. */ - clear_single_step(child); - ret = 0; - goto out; - } + case PTRACE_DETACH: { /* detach a process that was attached. */ + ret = -EIO; + if ((unsigned long) data > _NSIG) + break; + child->flags &= ~(PF_PTRACED|PF_TRACESYS); + child->exit_code = data; + write_lock_irq(&tasklist_lock); + REMOVE_LINKS(child); + child->p_pptr = child->p_opptr; + SET_LINKS(child); + write_unlock_irq(&tasklist_lock); + /* make sure the single step bit is not set. */ + clear_single_step(child); + wake_up_process(child); + ret = 0; + break; + } - default: - ret = -EIO; - goto out; + default: + ret = -EIO; + break; } +out_tsk: + free_task_struct(child); out: unlock_kernel(); return ret; } -asmlinkage void syscall_trace(void) +void syscall_trace(void) { if ((current->flags & (PF_PTRACED|PF_TRACESYS)) != (PF_PTRACED|PF_TRACESYS)) - goto out; + return; current->exit_code = SIGTRAP; current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); @@ -518,5 +312,4 @@ asmlinkage void syscall_trace(void) send_sig(current->exit_code, current, 1); current->exit_code = 0; } -out: } diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c index 49a8da139..67895b87d 100644 --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c @@ -776,8 +776,11 @@ void ppc_generic_ide_fix_driveid(struct hd_driveid *id) id->word127 = __le16_to_cpu(id->word127); id->dlf = __le16_to_cpu(id->dlf); id->csfo = __le16_to_cpu(id->csfo); - for (i = 0; i < 30; i++) - id->words130_159[i] = __le16_to_cpu(id->words130_159[i]); + for (i = 0; i < 26; i++) + id->words130_155[i] = __le16_to_cpu(id->words130_155[i]); + id->word156 = __le16_to_cpu(id->word156); + for (i = 0; i < 4; i++) + id->words157_159[i] = __le16_to_cpu(id->words157_159[i]); for (i = 0; i < 96; i++) id->words160_255[i] = __le16_to_cpu(id->words160_255[i]); } diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c index b821249d9..3877d11dc 100644 --- a/arch/ppc/kernel/time.c +++ b/arch/ppc/kernel/time.c @@ -41,10 +41,7 @@ #include <asm/processor.h> #include <asm/nvram.h> #include <asm/cache.h> -/* Fixme - Why is this here? - Corey */ -#ifdef CONFIG_8xx #include <asm/8xx_immap.h> -#endif #include <asm/machdep.h> #include "time.h" @@ -62,6 +59,7 @@ time_t last_rtc_update = 0; unsigned decrementer_count; /* count value for 1e6/HZ microseconds */ unsigned count_period_num; /* 1 decrementer count equals */ unsigned count_period_den; /* count_period_num / count_period_den us */ +unsigned long last_tb; /* * timer_interrupt - gets called when the decrementer overflows, @@ -103,6 +101,8 @@ int timer_interrupt(struct pt_regs * regs) */ while ((d = get_dec()) == dval) ; + asm volatile("mftb %0" : "=r" (last_tb) ); + /* * Don't play catchup between the call to time_init() * and sti() in init/main.c. @@ -149,20 +149,21 @@ int timer_interrupt(struct pt_regs * regs) */ void do_gettimeofday(struct timeval *tv) { - unsigned long flags; + unsigned long flags, diff; save_flags(flags); cli(); *tv = xtime; /* XXX we don't seem to have the decrementers synced properly yet */ #ifndef CONFIG_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++; - } + asm volatile("mftb %0" : "=r" (diff) ); + diff -= last_tb; + + tv->tv_usec += diff * count_period_num / count_period_den; + tv->tv_sec += tv->tv_usec / 1000000; + tv->tv_usec = tv->tv_usec % 1000000; #endif + restore_flags(flags); } @@ -334,6 +335,3 @@ void to_tm(int tim, struct rtc_time * tm) */ GregorianDay(tm); } - - - diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index 28a5a5035..0701f7118 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c @@ -91,7 +91,7 @@ MachineCheckException(struct pt_regs *regs) { #if defined(CONFIG_8xx) && defined(CONFIG_PCI) /* the qspan pci read routines can cause machine checks -- Cort */ - bad_page_fault(regs,regs->dar); + bad_page_fault(regs, regs->dar); return; #endif #if defined(CONFIG_XMON) || defined(CONFIG_KGDB) @@ -214,8 +214,6 @@ AlignmentException(struct pt_regs *regs) { int fixed; - if (regs->msr & MSR_FP) - giveup_fpu(current); fixed = fix_alignment(regs); if (fixed == 1) { regs->nip += 4; /* skip over emulated instruction */ @@ -223,7 +221,10 @@ AlignmentException(struct pt_regs *regs) } if (fixed == -EFAULT) { /* fixed == -EFAULT means the operand address was bad */ - bad_page_fault(regs, regs->dar); + if (user_mode(regs)) + force_sig(SIGSEGV, current); + else + bad_page_fault(regs, regs->dar); return; } _exception(SIGBUS, regs); |