summaryrefslogtreecommitdiffstats
path: root/arch/ppc
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-06-15 01:55:58 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-06-15 01:55:58 +0000
commit53b3988d474435254a3b053a68bb24ce9e439295 (patch)
treef8da8e40f01f4ad02bbd76b8c9920749b118235f /arch/ppc
parentb0cb48abe83d1a4389ea938bf624f8baa82c5047 (diff)
Merge with 2.3.99-pre9.
Diffstat (limited to 'arch/ppc')
-rw-r--r--arch/ppc/8260_io/enet.c4
-rw-r--r--arch/ppc/8260_io/uart.c12
-rw-r--r--arch/ppc/configs/common_defconfig16
-rw-r--r--arch/ppc/defconfig15
-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
-rw-r--r--arch/ppc/mbxboot/Makefile75
-rw-r--r--arch/ppc/mbxboot/embed_config.c13
-rw-r--r--arch/ppc/mbxboot/gzimage.c8
-rw-r--r--arch/ppc/mbxboot/head_8260.S11
-rw-r--r--arch/ppc/mbxboot/misc.c9
-rw-r--r--arch/ppc/mbxboot/rdimage.c8
-rw-r--r--arch/ppc/mbxboot/vmlinux.lds152
-rw-r--r--arch/ppc/mm/fault.c93
-rw-r--r--arch/ppc/mm/init.c10
-rw-r--r--arch/ppc/treeboot/mkevimg2
-rw-r--r--arch/ppc/treeboot/mkirimg6
-rw-r--r--arch/ppc/vmlinux.lds8
26 files changed, 615 insertions, 554 deletions
diff --git a/arch/ppc/8260_io/enet.c b/arch/ppc/8260_io/enet.c
index 82ed8f9ec..4a7c20df3 100644
--- a/arch/ppc/8260_io/enet.c
+++ b/arch/ppc/8260_io/enet.c
@@ -689,8 +689,8 @@ int __init scc_enet_init(void)
cep->dirty_tx = cep->cur_tx = cep->tx_bd_base;
cep->cur_rx = cep->rx_bd_base;
- ep->sen_genscc.scc_rfcr = SCC_EB;
- ep->sen_genscc.scc_tfcr = SCC_EB;
+ ep->sen_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB;
+ ep->sen_genscc.scc_tfcr = CPMFCR_GBL | CPMFCR_EB;
/* Set maximum bytes per receive buffer.
* This appears to be an Ethernet frame size, not the buffer
diff --git a/arch/ppc/8260_io/uart.c b/arch/ppc/8260_io/uart.c
index 9e93bcdd5..c039a452c 100644
--- a/arch/ppc/8260_io/uart.c
+++ b/arch/ppc/8260_io/uart.c
@@ -2536,8 +2536,8 @@ int __init rs_8xx_init(void)
/* Set up the uart parameters in the
* parameter ram.
*/
- up->smc_rfcr = SMC_EB;
- up->smc_tfcr = SMC_EB;
+ up->smc_rfcr = CPMFCR_GBL | CPMFCR_EB;
+ up->smc_tfcr = CPMFCR_GBL | CPMFCR_EB;
/* Set this to 1 for now, so we get single
* character interrupts. Using idle charater
@@ -2579,8 +2579,8 @@ int __init rs_8xx_init(void)
/* Set up the uart parameters in the
* parameter ram.
*/
- sup->scc_genscc.scc_rfcr = SMC_EB;
- sup->scc_genscc.scc_tfcr = SMC_EB;
+ sup->scc_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB;
+ sup->scc_genscc.scc_tfcr = CPMFCR_GBL | CPMFCR_EB;
/* Set this to 1 for now, so we get single
* character interrupts. Using idle charater
@@ -2741,8 +2741,8 @@ static int __init serial_console_setup(struct console *co, char *options)
*/
up->smc_rbase = dp_addr; /* Base of receive buffer desc. */
up->smc_tbase = dp_addr+sizeof(cbd_t); /* Base of xmt buffer desc. */
- up->smc_rfcr = SMC_EB;
- up->smc_tfcr = SMC_EB;
+ up->smc_rfcr = CPMFCR_GBL | CPMFCR_EB;
+ up->smc_tfcr = CPMFCR_GBL | CPMFCR_EB;
/* Set this to 1 for now, so we get single character interrupts.
*/
diff --git a/arch/ppc/configs/common_defconfig b/arch/ppc/configs/common_defconfig
index caf15d27d..051e96402 100644
--- a/arch/ppc/configs/common_defconfig
+++ b/arch/ppc/configs/common_defconfig
@@ -15,10 +15,11 @@ CONFIG_PPC=y
CONFIG_6xx=y
# CONFIG_4xx is not set
# CONFIG_PPC64 is not set
-# CONFIG_82xx is not set
+# CONFIG_8260 is not set
# CONFIG_8xx is not set
CONFIG_ALL_PPC=y
# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
# CONFIG_APUS is not set
# CONFIG_SMP is not set
CONFIG_ALTIVEC=y
@@ -159,10 +160,10 @@ CONFIG_BLK_DEV_IDESCSI=y
# CONFIG_BLK_DEV_RZ1000 is not set
CONFIG_BLK_DEV_IDEPCI=y
# CONFIG_IDEPCI_SHARE_IRQ is not set
-# CONFIG_BLK_DEV_IDEDMA_PCI is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_IDEDMA_PCI_AUTO is not set
-# CONFIG_BLK_DEV_IDEDMA is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+CONFIG_BLK_DEV_IDEDMA=y
CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
# CONFIG_IDEDMA_PCI_WIP is not set
# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
@@ -377,6 +378,11 @@ CONFIG_PPP=y
# CONFIG_HAMRADIO is not set
#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
# ISDN subsystem
#
# CONFIG_ISDN is not set
@@ -607,6 +613,7 @@ CONFIG_SOUND=y
CONFIG_DMASOUND_AWACS=y
CONFIG_DMASOUND=y
# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
# CONFIG_SOUND_ES1370 is not set
# CONFIG_SOUND_ES1371 is not set
# CONFIG_SOUND_ESSSOLO1 is not set
@@ -688,3 +695,4 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
CONFIG_MAGIC_SYSRQ=y
# CONFIG_KGDB is not set
CONFIG_XMON=y
+
diff --git a/arch/ppc/defconfig b/arch/ppc/defconfig
index c93118bae..a14aa41ab 100644
--- a/arch/ppc/defconfig
+++ b/arch/ppc/defconfig
@@ -15,10 +15,11 @@ CONFIG_PPC=y
CONFIG_6xx=y
# CONFIG_4xx is not set
# CONFIG_PPC64 is not set
-# CONFIG_82xx is not set
+# CONFIG_8260 is not set
# CONFIG_8xx is not set
CONFIG_ALL_PPC=y
# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
# CONFIG_APUS is not set
# CONFIG_SMP is not set
CONFIG_ALTIVEC=y
@@ -159,10 +160,10 @@ CONFIG_BLK_DEV_IDESCSI=y
# CONFIG_BLK_DEV_RZ1000 is not set
CONFIG_BLK_DEV_IDEPCI=y
# CONFIG_IDEPCI_SHARE_IRQ is not set
-# CONFIG_BLK_DEV_IDEDMA_PCI is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_IDEDMA_PCI_AUTO is not set
-# CONFIG_BLK_DEV_IDEDMA is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+CONFIG_BLK_DEV_IDEDMA=y
CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
# CONFIG_IDEDMA_PCI_WIP is not set
# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
@@ -377,6 +378,11 @@ CONFIG_PPP=y
# CONFIG_HAMRADIO is not set
#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
# ISDN subsystem
#
# CONFIG_ISDN is not set
@@ -608,6 +614,7 @@ CONFIG_SOUND=y
CONFIG_DMASOUND_AWACS=y
CONFIG_DMASOUND=y
# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
# CONFIG_SOUND_ES1370 is not set
# CONFIG_SOUND_ES1371 is not set
# CONFIG_SOUND_ESSSOLO1 is not set
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);
diff --git a/arch/ppc/mbxboot/Makefile b/arch/ppc/mbxboot/Makefile
index 9dd5d64f3..53611aa58 100644
--- a/arch/ppc/mbxboot/Makefile
+++ b/arch/ppc/mbxboot/Makefile
@@ -28,14 +28,14 @@ ISZ = 0
TFTPIMAGE=/tftpboot/zImage.embedded
ifdef CONFIG_8xx
-ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00180000
-OBJECTS := head.o misc.o ../coffboot/zlib.o m8xx_tty.o
+ZLINKFLAGS = -T vmlinux.lds -Ttext 0x00180000
+OBJECTS := head.o misc.o ../coffboot/zlib.o m8xx_tty.o gzimage.o rdimage.o
CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS -fno-builtin -DCONFIG_8xx
endif
ifdef CONFIG_8260
-ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00400000
-OBJECTS := head_8260.o misc.o ../coffboot/zlib.o m8260_tty.o embed_config.o
+ZLINKFLAGS = -T vmlinux.lds -Ttext 0x00400000
+OBJECTS := head_8260.o misc.o ../coffboot/zlib.o m8260_tty.o embed_config.o gzimage.o rdimage.o
CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS -fno-builtin -DCONFIG_8260
endif
@@ -61,21 +61,32 @@ endif
all: zImage
zvmlinux.initrd: zvmlinux
- $(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp1 $(OBJECTS)
+#
+# Build the boot loader images
+#
+ $(OBJCOPY) $(OBJCOPY_ARGS) -R .gzimage gzimage.o
$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
- --add-section=initrd=ramdisk.image.gz \
- --add-section=image=../coffboot/vmlinux.gz \
- zvmlinux.initrd.tmp1 zvmlinux.initrd1
- $(CC) $(CFLAGS) -DINITRD_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd1 initrd` \
- -DINITRD_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd1 initrd` \
- -DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd1 image` \
- -DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd1 image` \
- -c -o misc.o misc.c
- $(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS)
+ --add-section=.gzimage=../coffboot/vmlinux.gz \
+ --set-section-flags=.gzimage=alloc,load,readonly,data \
+ gzimage.o
+ $(OBJCOPY) $(OBJCOPY_ARGS) -R .rdimage rdimage.o
$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
- --add-section=initrd=ramdisk.image.gz \
- --add-section=image=../coffboot/vmlinux.gz \
- zvmlinux.initrd.tmp $@
+ --add-section=.rdimage=ramdisk.image.gz \
+ --set-section-flags=.rdimage=alloc,load,readonly,data \
+ rdimage.o
+ $(LD) $(ZLINKFLAGS) -o $@ $(OBJECTS)
+#
+# Compute the sizes/offsets for the final image, and rebuild with these values.
+#
+ $(CC) $(CFLAGS) \
+ -DINITRD_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd .rdimage` \
+ -DINITRD_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd .rdimage` \
+ -DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd .gzimage` \
+ -DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd .gzimage` \
+ -c -o misc.o misc.c
+ $(LD) $(ZLINKFLAGS) -o $@ $(OBJECTS)
+ $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment $@
+ $(OBJDUMP) -h $@
zImage: zvmlinux
ln -sf zvmlinux zImage
@@ -85,23 +96,27 @@ zImage.initrd: zvmlinux.initrd
zvmlinux: $(OBJECTS) ../coffboot/vmlinux.gz
#
-# build the boot loader image and then compute the offset into it
-# for the kernel image
+# Build the boot loader images
#
- $(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS)
- $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment --add-section=image=../coffboot/vmlinux.gz \
- zvmlinux.tmp $@
#
-# then with the offset rebuild the bootloader so we know where the kernel is
+ $(OBJCOPY) $(OBJCOPY_ARGS) -R .gzimage gzimage.o
+ $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
+ --add-section=.gzimage=../coffboot/vmlinux.gz \
+ --set-section-flags=.gzimage=alloc,load,readonly,data \
+ gzimage.o
+ $(LD) $(ZLINKFLAGS) -o $@ $(OBJECTS)
+#
+# Compute the sizes/offsets for the final image, and rebuild with these values.
#
- $(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 \
- -DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux image` \
- -DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux image` \
+ $(CC) $(CFLAGS) \
+ -DINITRD_OFFSET=0 \
+ -DINITRD_SIZE=0 \
+ -DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux .gzimage` \
+ -DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux .gzimage` \
-c -o misc.o misc.c
- $(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS)
- $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment --add-section=image=../coffboot/vmlinux.gz \
- zvmlinux.tmp $@
- rm zvmlinux.tmp
+ $(LD) $(ZLINKFLAGS) -o $@ $(OBJECTS)
+ $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment $@
+ $(OBJDUMP) -h $@
znetboot : zImage
cp zImage $(TFTPIMAGE)
diff --git a/arch/ppc/mbxboot/embed_config.c b/arch/ppc/mbxboot/embed_config.c
index 1d76be70c..048f8bcfe 100644
--- a/arch/ppc/mbxboot/embed_config.c
+++ b/arch/ppc/mbxboot/embed_config.c
@@ -236,12 +236,12 @@ embed_config(bd_t *bd)
* here for those people that may load the kernel with
* a JTAG/COP tool and not the rom monitor.
*/
- bd->bi_baudrate = 115200;
- bd->bi_intfreq = 200;
- bd->bi_busfreq = 66;
- bd->bi_cpmfreq = 66;
- bd->bi_brgfreq = 33;
- bd->bi_memsize = 16 * 1024 * 1024;
+ bd->bi_baudrate = 19200;
+ bd->bi_intfreq = 165;
+ bd->bi_busfreq = 33;
+ bd->bi_cpmfreq = 132;
+ bd->bi_brgfreq = bd->bi_cpmfreq / 2; /* BRGCLK = (CPM*2/4) */
+ bd->bi_memsize = 16 * 1024 * 1024;
#endif
cp = (u_char *)def_enet_addr;
@@ -250,3 +250,4 @@ embed_config(bd_t *bd)
}
}
#endif /* EST8260 */
+
diff --git a/arch/ppc/mbxboot/gzimage.c b/arch/ppc/mbxboot/gzimage.c
new file mode 100644
index 000000000..11ce5be8e
--- /dev/null
+++ b/arch/ppc/mbxboot/gzimage.c
@@ -0,0 +1,8 @@
+/*
+ * gzimage.c
+ *
+ * Dummy file to allow a compressed zImage to be added
+ * into a linker section, accessed by the boot coode
+ */
+
+char dummy_for_gzimage;
diff --git a/arch/ppc/mbxboot/head_8260.S b/arch/ppc/mbxboot/head_8260.S
index 79377a2ac..0895ce025 100644
--- a/arch/ppc/mbxboot/head_8260.S
+++ b/arch/ppc/mbxboot/head_8260.S
@@ -9,10 +9,17 @@
* $Id: head.S,v 1.33 1999/09/08 01:06:58 cort Exp $
*
* Boot loader philosophy:
+ *
* ROM loads us to some arbitrary location
- * Move the boot code to the link address (8M)
+ * ROM loads these registers:
+ *
+ * R3 = Pointer to the board configuration data
+ * R5 = Pointer to Open Firmware data
+ *
+ * ROM jumps to start/start_
+ * Move the boot code to the link address (4 MB)
* Call decompress_kernel()
- * Relocate the initrd, zimage and residual data to 8M
+ * Relocate the initrd, zimage and residual data to 4 MB
* Decompress the kernel to 0
* Jump to the kernel entry
* -- Cort
diff --git a/arch/ppc/mbxboot/misc.c b/arch/ppc/mbxboot/misc.c
index 683f53491..d5a44df1e 100644
--- a/arch/ppc/mbxboot/misc.c
+++ b/arch/ppc/mbxboot/misc.c
@@ -25,6 +25,15 @@
#endif
/*
+ * The following references are needed to cause the linker to pull in the
+ * gzimage.o and rdimage.o files. These object files are special,
+ * since they get placed into the .gzimage and .rdimage ELF sections
+ * of the zvmlinux and zvmlinux.initrd files.
+ */
+extern char dummy_for_gzimage;
+extern char dummy_for_rdimage;
+
+/*
* Please send me load/board info and such data for hardware not
* listed here so I can keep track since things are getting tricky
* with the different load addrs with different firmware. This will
diff --git a/arch/ppc/mbxboot/rdimage.c b/arch/ppc/mbxboot/rdimage.c
new file mode 100644
index 000000000..e40fd1e2e
--- /dev/null
+++ b/arch/ppc/mbxboot/rdimage.c
@@ -0,0 +1,8 @@
+/*
+ * rdimage.c
+ *
+ * Dummy file to allow a compressed initrd to be added
+ * into a linker section, accessed by the boot coode
+ */
+
+char dummy_for_rdimage;
diff --git a/arch/ppc/mbxboot/vmlinux.lds b/arch/ppc/mbxboot/vmlinux.lds
new file mode 100644
index 000000000..2bf2c87b3
--- /dev/null
+++ b/arch/ppc/mbxboot/vmlinux.lds
@@ -0,0 +1,152 @@
+OUTPUT_ARCH(powerpc)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
+/* Do we need any of these for elf?
+ __DYNAMIC = 0; */
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+/* .init : { *(.init) } =0*/
+ .plt : { *(.plt) }
+ .text :
+ {
+ *(.text)
+ *(.fixup)
+ *(.got1)
+ }
+ _etext = .;
+ PROVIDE (etext = .);
+ .rodata :
+ {
+ *(.rodata)
+ *(.rodata1)
+ }
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x0FFF) & 0xFFFFF000;
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.got.plt) *(.got)
+ *(.dynamic)
+ CONSTRUCTORS
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ .fixup : { *(.fixup) }
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(32);
+ .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+
+ . = ALIGN(4096);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : {
+ *(.data.init);
+ __vtop_table_begin = .;
+ *(.vtop_fixup);
+ __vtop_table_end = .;
+ __ptov_table_begin = .;
+ *(.ptov_fixup);
+ __ptov_table_end = .;
+ }
+ . = ALIGN(16);
+ __setup_start = .;
+ .setup.init : { *(.setup.init) }
+ __setup_end = .;
+ __initcall_start = .;
+ .initcall.init : { *(.initcall.init) }
+ __initcall_end = .;
+ . = ALIGN(4096);
+ __init_end = .;
+
+ . = ALIGN(4096);
+ __pmac_begin = .;
+ .text.pmac : { *(.text.pmac) }
+ .data.pmac : { *(.data.pmac) }
+ . = ALIGN(4096);
+ __pmac_end = .;
+
+ . = ALIGN(4096);
+ __prep_begin = .;
+ .text.prep : { *(.text.prep) }
+ .data.prep : { *(.data.prep) }
+ . = ALIGN(4096);
+ __prep_end = .;
+
+ . = ALIGN(4096);
+ __apus_begin = .;
+ .text.apus : { *(.text.apus) }
+ .data.apus : { *(.data.apus) }
+ . = ALIGN(4096);
+ __apus_end = .;
+
+ . = ALIGN(4096);
+ __apus_begin = .;
+ .text.apus : { *(.text.apus) }
+ .data.apus : { *(.data.apus) }
+ . = ALIGN(4096);
+ __apus_end = .;
+
+ . = ALIGN(4096);
+ __openfirmware_begin = .;
+ .text.openfirmware : { *(.text.openfirmware) }
+ .data.openfirmware : { *(.data.openfirmware) }
+ . = ALIGN(4096);
+ __openfirmware_end = .;
+
+ __bss_start = .;
+ .bss :
+ {
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+ _end = . ;
+ PROVIDE (end = .);
+
+ /*
+ * For loader only: Put the zImage after everything else
+ */
+ _gzstart = . ;
+ .gzimage : { *(.gzimage) }
+ _gzend = . ;
+
+ /*
+ * For loader only: Put the initrd after zImage
+ */
+ _rdstart = . ;
+ .rdimage : { *(.rdimage) }
+ _rdend = . ;
+
+}
diff --git a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c
index 076ee56e5..7a899252f 100644
--- a/arch/ppc/mm/fault.c
+++ b/arch/ppc/mm/fault.c
@@ -62,10 +62,21 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
{
struct vm_area_struct * vma;
struct mm_struct *mm = current->mm;
+ siginfo_t info;
+ int code = SEGV_MAPERR;
#if defined(CONFIG_4xx)
int is_write = error_code & ESR_DST;
#else
int is_write = error_code & 0x02000000;
+
+ /*
+ * Fortunately the bit assignments in SRR1 for an instruction
+ * fault and DSISR for a data fault are mostly the same for the
+ * bits we are interested in. But there are some bits which
+ * indicate errors in DSISR but can validly be set in SRR1.
+ */
+ if (regs->trap == 0x400)
+ error_code &= 0x48200000;
#endif /* CONFIG_4xx */
#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
@@ -82,16 +93,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
#endif /* !CONFIG_4xx */
#endif /* CONFIG_XMON || CONFIG_KGDB */
- if (in_interrupt()) {
- static int complained;
- if (complained < 20) {
- ++complained;
- printk("page fault in interrupt handler, addr=%lx\n",
- address);
- show_regs(regs);
- }
- }
- if (current == NULL || mm == NULL) {
+ if (in_interrupt() || mm == NULL) {
bad_page_fault(regs, address);
return;
}
@@ -107,10 +109,12 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
goto bad_area;
good_area:
+ code = SEGV_ACCERR;
#if defined(CONFIG_6xx)
if (error_code & 0x95700000)
/* an error such as lwarx to I/O controller space,
address matching DABR, eciwx, etc. */
+ goto bad_area;
#endif /* CONFIG_6xx */
#if defined(CONFIG_8xx)
/* The MPC8xx seems to always set 0x80000000, which is
@@ -119,9 +123,8 @@ good_area:
*/
if (error_code & 0x10000000)
/* Guarded storage error. */
-#endif /* CONFIG_8xx */
goto bad_area;
-
+#endif /* CONFIG_8xx */
/* a write */
if (is_write) {
@@ -135,8 +138,25 @@ good_area:
if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
goto bad_area;
}
- if (!handle_mm_fault(mm, vma, address, is_write))
- goto bad_area;
+
+ /*
+ * If for any reason at all we couldn't handle the fault,
+ * make sure we exit gracefully rather than endlessly redo
+ * the fault.
+ */
+ switch (handle_mm_fault(mm, vma, address, is_write)) {
+ case 1:
+ current->min_flt++;
+ break;
+ case 2:
+ current->maj_flt++;
+ break;
+ case 0:
+ goto do_sigbus;
+ default:
+ goto out_of_memory;
+ }
+
up(&mm->mmap_sem);
/*
* keep track of tlb+htab misses that are good addrs but
@@ -147,22 +167,55 @@ good_area:
return;
bad_area:
-
up(&mm->mmap_sem);
pte_errors++;
+
+ /* User mode accesses cause a SIGSEGV */
+ if (user_mode(regs)) {
+ info.si_signo = SIGSEGV;
+ info.si_errno = 0;
+ info.si_code = code;
+ info.si_addr = (void *) address;
+ force_sig_info(SIGSEGV, &info, current);
+ return;
+ }
+
+ bad_page_fault(regs, address);
+ return;
+
+/*
+ * We ran out of memory, or some other thing happened to us that made
+ * us unable to handle the page fault gracefully.
+ */
+out_of_memory:
+ up(&mm->mmap_sem);
+ printk("VM: killing process %s\n", current->comm);
+ if (user_mode(regs))
+ do_exit(SIGKILL);
bad_page_fault(regs, address);
+ return;
+
+do_sigbus:
+ up(&mm->mmap_sem);
+ info.si_signo = SIGBUS;
+ info.si_errno = 0;
+ info.si_code = BUS_ADRERR;
+ info.si_addr = (void *)address;
+ force_sig_info (SIGBUS, &info, current);
+ if (!user_mode(regs))
+ bad_page_fault(regs, address);
}
+/*
+ * bad_page_fault is called when we have a bad access from the kernel.
+ * It is called from do_page_fault above and from some of the procedures
+ * in traps.c.
+ */
void
bad_page_fault(struct pt_regs *regs, unsigned long address)
{
unsigned long fixup;
- if (user_mode(regs)) {
- force_sig(SIGSEGV, current);
- return;
- }
-
/* Are we prepared to handle this fault? */
if ((fixup = search_exception_table(regs->nip)) != 0) {
regs->nip = fixup;
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
index 80fb7575e..fc3acdd5c 100644
--- a/arch/ppc/mm/init.c
+++ b/arch/ppc/mm/init.c
@@ -83,6 +83,7 @@ extern char _start[], _end[];
extern char etext[], _stext[];
extern char __init_begin, __init_end;
extern char __prep_begin, __prep_end;
+extern char __chrp_begin, __chrp_end;
extern char __pmac_begin, __pmac_end;
extern char __apus_begin, __apus_end;
extern char __openfirmware_begin, __openfirmware_end;
@@ -777,7 +778,7 @@ void __init free_initmem(void)
unsigned long a;
unsigned long num_freed_pages = 0, num_prep_pages = 0,
num_pmac_pages = 0, num_openfirmware_pages = 0,
- num_apus_pages = 0;
+ num_apus_pages = 0, num_chrp_pages = 0;
#define FREESEC(START,END,CNT) do { \
a = (unsigned long)(&START); \
for (; a < (unsigned long)(&END); a += PAGE_SIZE) { \
@@ -794,6 +795,7 @@ void __init free_initmem(void)
case _MACH_Pmac:
FREESEC(__apus_begin,__apus_end,num_apus_pages);
FREESEC(__prep_begin,__prep_end,num_prep_pages);
+ FREESEC(__chrp_begin,__chrp_end,num_chrp_pages);
break;
case _MACH_chrp:
FREESEC(__apus_begin,__apus_end,num_apus_pages);
@@ -803,20 +805,24 @@ void __init free_initmem(void)
case _MACH_prep:
FREESEC(__apus_begin,__apus_end,num_apus_pages);
FREESEC(__pmac_begin,__pmac_end,num_pmac_pages);
+ FREESEC(__chrp_begin,__chrp_end,num_chrp_pages);
break;
case _MACH_mbx:
FREESEC(__apus_begin,__apus_end,num_apus_pages);
FREESEC(__pmac_begin,__pmac_end,num_pmac_pages);
FREESEC(__prep_begin,__prep_end,num_prep_pages);
+ FREESEC(__chrp_begin,__chrp_end,num_chrp_pages);
break;
case _MACH_apus:
FREESEC(__pmac_begin,__pmac_end,num_pmac_pages);
FREESEC(__prep_begin,__prep_end,num_prep_pages);
+ FREESEC(__chrp_begin,__chrp_end,num_chrp_pages);
break;
case _MACH_gemini:
FREESEC(__apus_begin,__apus_end,num_apus_pages);
FREESEC(__pmac_begin,__pmac_end,num_pmac_pages);
FREESEC(__prep_begin,__prep_end,num_prep_pages);
+ FREESEC(__chrp_begin,__chrp_end,num_chrp_pages);
break;
}
@@ -829,6 +835,8 @@ void __init free_initmem(void)
if ( num_prep_pages )
printk(" %ldk prep", PGTOKB(num_prep_pages));
+ if ( num_chrp_pages )
+ printk(" %ldk chrp", PGTOKB(num_chrp_pages));
if ( num_pmac_pages )
printk(" %ldk pmac", PGTOKB(num_pmac_pages));
if ( num_openfirmware_pages )
diff --git a/arch/ppc/treeboot/mkevimg b/arch/ppc/treeboot/mkevimg
index 76f849bb7..68eb4dd3f 100644
--- a/arch/ppc/treeboot/mkevimg
+++ b/arch/ppc/treeboot/mkevimg
@@ -1,4 +1,4 @@
-#!/usr/local/bin/perl
+#!/usr/bin/perl
#
# Copyright (c) 1998-1999 TiVo, Inc.
diff --git a/arch/ppc/treeboot/mkirimg b/arch/ppc/treeboot/mkirimg
index e8aa24e3d..17a6f2328 100644
--- a/arch/ppc/treeboot/mkirimg
+++ b/arch/ppc/treeboot/mkirimg
@@ -1,4 +1,4 @@
-#!/usr/local/bin/perl
+#!/usr/bin/perl
#
# Copyright (c) 1998-1999 TiVo, Inc.
# Original ELF parsing code.
@@ -332,7 +332,7 @@ require 'elf.pl';
syswrite(OUTPUT, $ibuf, $initialOffset);
if ($imageFound) {
- $testN = pack ("I2", $bss_addr + $bss_size, $image_size);
+ $testN = pack ("N2", $bss_addr + $bss_size, $image_size);
syswrite(OUTPUT, $testN, length($testN));
printf("Updated symbol \"imageSect_start\" to 0x%08x\n",
$bss_addr + $bss_size);
@@ -342,7 +342,7 @@ require 'elf.pl';
}
if ($initrdFound) {
- $testN = pack ("I2", $bss_addr + $bss_size + $image_size, $initrd_size);
+ $testN = pack ("N2", $bss_addr + $bss_size + $image_size, $initrd_size);
syswrite(OUTPUT, $testN, length($testN));
printf("Updated symbol \"initrdSect_start\" to 0x%08x\n",
$bss_addr + $bss_size + $image_size);
diff --git a/arch/ppc/vmlinux.lds b/arch/ppc/vmlinux.lds
index 707c4ad2f..7bfdc4efb 100644
--- a/arch/ppc/vmlinux.lds
+++ b/arch/ppc/vmlinux.lds
@@ -104,6 +104,13 @@ SECTIONS
__prep_end = .;
. = ALIGN(4096);
+ __chrp_begin = .;
+ .text.chrp : { *(.text.chrp) }
+ .data.chrp : { *(.data.chrp) }
+ . = ALIGN(4096);
+ __chrp_end = .;
+
+ . = ALIGN(4096);
__apus_begin = .;
.text.apus : { *(.text.apus) }
.data.apus : { *(.data.apus) }
@@ -135,4 +142,3 @@ SECTIONS
_end = . ;
PROVIDE (end = .);
}
-