summaryrefslogtreecommitdiffstats
path: root/arch/ppc/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc/kernel')
-rw-r--r--arch/ppc/kernel/chrp_pci.c37
-rw-r--r--arch/ppc/kernel/chrp_setup.c39
-rw-r--r--arch/ppc/kernel/chrp_time.c9
-rw-r--r--arch/ppc/kernel/entry.S89
-rw-r--r--arch/ppc/kernel/head.S3
-rw-r--r--arch/ppc/kernel/ppc_ksyms.c3
-rw-r--r--arch/ppc/kernel/ptrace.c507
-rw-r--r--arch/ppc/kernel/setup.c7
-rw-r--r--arch/ppc/kernel/time.c24
-rw-r--r--arch/ppc/kernel/traps.c9
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);