diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-09-19 19:15:08 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-09-19 19:15:08 +0000 |
commit | 03ba4131783cc9e872f8bb26a03f15bc11f27564 (patch) | |
tree | 88db8dba75ae06ba3bad08e42c5e52efc162535c /arch/arm/kernel | |
parent | 257730f99381dd26e10b832fce4c94cae7ac1176 (diff) |
- Merge with Linux 2.1.121.
- Bugfixes.
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/Makefile | 14 | ||||
-rw-r--r-- | arch/arm/kernel/armksyms.c | 66 | ||||
-rw-r--r-- | arch/arm/kernel/dec21285.c | 161 | ||||
-rw-r--r-- | arch/arm/kernel/dma-ebsa285.c | 184 | ||||
-rw-r--r-- | arch/arm/kernel/dma-rpc.c | 32 | ||||
-rw-r--r-- | arch/arm/kernel/ecard.c | 43 | ||||
-rw-r--r-- | arch/arm/kernel/entry-armv.S | 68 | ||||
-rw-r--r-- | arch/arm/kernel/entry-common.S | 46 | ||||
-rw-r--r-- | arch/arm/kernel/fiq.c | 179 | ||||
-rw-r--r-- | arch/arm/kernel/head-armo.S | 2 | ||||
-rw-r--r-- | arch/arm/kernel/head-armv.S | 172 | ||||
-rw-r--r-- | arch/arm/kernel/init_task.c | 4 | ||||
-rw-r--r-- | arch/arm/kernel/ioport.c | 79 | ||||
-rw-r--r-- | arch/arm/kernel/irq.c | 293 | ||||
-rw-r--r-- | arch/arm/kernel/leds-ebsa110.c | 30 | ||||
-rw-r--r-- | arch/arm/kernel/leds-ebsa285.c | 2 | ||||
-rw-r--r-- | arch/arm/kernel/process.c | 29 | ||||
-rw-r--r-- | arch/arm/kernel/ptrace.c | 23 | ||||
-rw-r--r-- | arch/arm/kernel/setup-ebsa110.c | 191 | ||||
-rw-r--r-- | arch/arm/kernel/setup.c | 322 | ||||
-rw-r--r-- | arch/arm/kernel/signal.c | 171 | ||||
-rw-r--r-- | arch/arm/kernel/sys_arm.c | 8 | ||||
-rw-r--r-- | arch/arm/kernel/time.c | 2 | ||||
-rw-r--r-- | arch/arm/kernel/traps.c | 24 |
24 files changed, 1212 insertions, 933 deletions
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 7795dd0bc..542ca995a 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -9,7 +9,8 @@ HEAD_OBJ = head-$(PROCESSOR).o ENTRY_OBJ = entry-$(PROCESSOR).o O_TARGET := kernel.o -O_OBJS := $(ENTRY_OBJ) ioport.o irq.o process.o ptrace.o signal.o sys_arm.o time.o traps.o +O_OBJS := $(ENTRY_OBJ) ioport.o irq.o process.o ptrace.o setup.o \ + signal.o sys_arm.o time.o traps.o fiq.o all: lib kernel.o $(HEAD_OBJ) init_task.o @@ -20,7 +21,7 @@ O_OBJS += armksyms.o endif ifdef CONFIG_ARCH_ACORN - O_OBJS += setup.o ecard.o iic.o + O_OBJS += ecard.o iic.o ifdef CONFIG_ARCH_ARC O_OBJS += oldlatches.o endif @@ -29,25 +30,26 @@ ifdef CONFIG_ARCH_ACORN endif ifeq ($(MACHINE),ebsa110) - O_OBJS += setup-ebsa110.o dma-dummy.o + O_OBJS += dma-dummy.o leds-ebsa110.o endif ifeq ($(MACHINE),ebsa285) - O_OBJS += dma-dummy.o leds-ebsa285.o setup-ebsa110.o + OX_OBJS += dma.o + O_OBJS += dma-ebsa285.o leds-ebsa285.o ifdef CONFIG_PCI O_OBJS += dec21285.o endif endif ifeq ($(MACHINE),nexuspci) - O_OBJS += setup-ebsa110.o dma-dummy.o + O_OBJS += dma-dummy.o ifdef CONFIG_PCI O_OBJS += plx9080.o endif endif $(HEAD_OBJ): $(HEAD_OBJ:.o=.S) - $(CC) -D__ASSEMBLY__ -traditional -c $(HEAD_OBJ:.o=.S) -o $@ + $(CC) -D__ASSEMBLY__ -DTEXTADDR=$(TEXTADDR) -traditional -c $(HEAD_OBJ:.o=.S) -o $@ $(ENTRY_OBJ): $(ENTRY_OBJ:.o=.S) $(CC) $(CFLAGS) -D__ASSEMBLY__ -c $(ENTRY_OBJ:.o=.S) -o $@ diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index 5c2f1b502..149349b4a 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -12,10 +12,13 @@ #include <asm/io.h> #include <asm/dma.h> #include <asm/pgtable.h> +#include <asm/system.h> #include <asm/uaccess.h> extern void dump_thread(struct pt_regs *, struct user *); extern int dump_fpu(struct pt_regs *, struct user_fp_struct *); +extern void inswb(unsigned int port, void *to, int len); +extern void outswb(unsigned int port, const void *to, int len); /* * libgcc functions - functions that are used internally by the @@ -40,33 +43,27 @@ extern void __udivsi3(void); extern void __umoddi3(void); extern void __umodsi3(void); -extern void inswb(unsigned int port, void *to, int len); -extern void outswb(unsigned int port, const void *to, int len); - -/* - * floating point math emulator support. - * These will not change. If they do, then a new version - * of the emulator will have to be compiled... - * fp_current is never actually dereferenced - it is just - * used as a pointer to pass back for send_sig(). - */ -extern void (*fp_save)(unsigned char *); -extern void (*fp_restore)(unsigned char *); -extern void fp_setup(void); -extern void fpreturn(void); -extern void fpundefinstr(void); extern void fp_enter(void); -extern void fp_printk(void); -extern struct task_struct *fp_current; -extern void fp_send_sig(int); +#define EXPORT_SYMBOL_ALIAS(sym,orig) \ + const char __kstrtab_##sym##[] __attribute__((section(".kstrtab"))) = \ + __MODULE_STRING(##sym##); \ + const struct module_symbol __ksymtab_##sym __attribute__((section("__ksymtab"))) = \ + { (unsigned long)&##orig, __kstrtab_##sym }; + /* + * floating point math emulator support. + * These symbols will never change their calling convention... + */ +EXPORT_SYMBOL_ALIAS(kern_fp_enter,fp_enter); +EXPORT_SYMBOL_ALIAS(fp_printk,printk); +EXPORT_SYMBOL_ALIAS(fp_send_sig,send_sig); -/* platform dependent support */ + /* platform dependent support */ EXPORT_SYMBOL(dump_thread); EXPORT_SYMBOL(dump_fpu); EXPORT_SYMBOL(udelay); EXPORT_SYMBOL(xchg_str); -/* expansion card support */ + /* expansion card support */ #ifdef CONFIG_ARCH_ACORN EXPORT_SYMBOL(ecard_startfind); EXPORT_SYMBOL(ecard_find); @@ -77,16 +74,17 @@ EXPORT_SYMBOL(ecard_address); EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); -/* processor dependencies */ + /* processor dependencies */ EXPORT_SYMBOL(processor); +EXPORT_SYMBOL(machine_type); -/* io */ + /* io */ EXPORT_SYMBOL(outswb); EXPORT_SYMBOL(outsw); EXPORT_SYMBOL(inswb); EXPORT_SYMBOL(insw); -/* address translation */ + /* address translation */ #ifndef __virt_to_phys__is_a_macro EXPORT_SYMBOL(__virt_to_phys); #endif @@ -104,27 +102,7 @@ EXPORT_SYMBOL(quicklists); EXPORT_SYMBOL(__bad_pmd); EXPORT_SYMBOL(__bad_pmd_kernel); -#define EXPORT_VERS0(sym,orig) \ - const char __kstrtab_##sym##[] __attribute__((section(".kstrtab"))) = \ - __MODULE_STRING(##sym##_R00000000); \ - const struct module_symbol __ksymtab_##sym __attribute__((section("__ksymtab"))) = \ - { (unsigned long)&##orig, __kstrtab_##sym }; -/* - * floating point math emulator support. - * These symbols will never change their calling convention... - */ -EXPORT_VERS0(fpreturn,fpreturn); -EXPORT_VERS0(fpundefinstr,fpundefinstr); -EXPORT_VERS0(fp_enter,fp_enter); -EXPORT_VERS0(fp_save,fp_save); -EXPORT_VERS0(fp_restore,fp_restore); -EXPORT_VERS0(fp_setup,fp_setup); -EXPORT_VERS0(fp_printk,printk); -EXPORT_VERS0(fp_send_sig,send_sig); - - /* - * string / mem functions - */ + /* string / mem functions */ EXPORT_SYMBOL_NOVERS(strcpy); EXPORT_SYMBOL_NOVERS(strncpy); EXPORT_SYMBOL_NOVERS(strcat); diff --git a/arch/arm/kernel/dec21285.c b/arch/arm/kernel/dec21285.c index 11ea39e7a..de4861b82 100644 --- a/arch/arm/kernel/dec21285.c +++ b/arch/arm/kernel/dec21285.c @@ -1,31 +1,42 @@ /* * arch/arm/kernel/dec21285.c: PCI functions for DEC 21285 * - * Copyright (C) 1998 Russell King + * Copyright (C) 1998 Russell King, Phil Blundell */ #include <linux/kernel.h> #include <linux/pci.h> #include <linux/init.h> -int pcibios_present(void) +#include <asm/system.h> + +#define MAX_SLOTS 20 + +int +pcibios_present(void) { return 1; } -static unsigned long pcibios_base_address(unsigned char dev_fn) +static unsigned long +pcibios_base_address(unsigned char bus, unsigned char dev_fn) { - int slot = PCI_SLOT(dev_fn); - - if (slot < 4) - return 0xf8000000 + (1 << (19 - slot)); - else - return 0; + if (bus == 0) { + int slot = PCI_SLOT(dev_fn); + + if (slot < MAX_SLOTS) + return 0xf8c00000 + (slot << 11); + else + return 0; + } else { + return 0xf9000000 | (bus << 16) | (dev_fn << 8); + } } -int pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned char *val) +int +pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned char *val) { - unsigned long addr = pcibios_base_address(dev_fn); + unsigned long addr = pcibios_base_address(bus, dev_fn); unsigned char v; if (addr) @@ -38,10 +49,11 @@ int pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, return PCIBIOS_SUCCESSFUL; } -int pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned short *val) +int +pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned short *val) { - unsigned long addr = pcibios_base_address(dev_fn); + unsigned long addr = pcibios_base_address(bus, dev_fn); unsigned short v; if (addr) @@ -54,10 +66,11 @@ int pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, return PCIBIOS_SUCCESSFUL; } -int pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned int *val) +int +pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned int *val) { - unsigned long addr = pcibios_base_address(dev_fn); + unsigned long addr = pcibios_base_address(bus, dev_fn); unsigned int v; if (addr) @@ -70,10 +83,11 @@ int pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, return PCIBIOS_SUCCESSFUL; } -int pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned char val) +int +pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned char val) { - unsigned long addr = pcibios_base_address(dev_fn); + unsigned long addr = pcibios_base_address(bus, dev_fn); if (addr) __asm__("str%?b %0, [%1, %2]" @@ -81,10 +95,11 @@ int pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, return PCIBIOS_SUCCESSFUL; } -int pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned short val) +int +pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned short val) { - unsigned long addr = pcibios_base_address(dev_fn); + unsigned long addr = pcibios_base_address(bus, dev_fn); if (addr) __asm__("str%?h %0, [%1, %2]" @@ -92,10 +107,11 @@ int pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, return PCIBIOS_SUCCESSFUL; } -int pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned int val) +int +pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned int val) { - unsigned long addr = pcibios_base_address(dev_fn); + unsigned long addr = pcibios_base_address(bus, dev_fn); if (addr) __asm__("str%? %0, [%1, %2]" @@ -103,35 +119,72 @@ int pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, return PCIBIOS_SUCCESSFUL; } -static int irq[] = { 18, 8, 9, 11 }; +static int irqmap_ebsa[] __initdata = { 9, 8, 18, 11 }; +static int irqmap_cats[] __initdata = { 18, 8, 9, 11 }; -__initfunc(void pcibios_fixup(void)) +__initfunc(static int ebsa_irqval(struct pci_dev *dev)) { - struct pci_dev *dev; unsigned char pin; - unsigned int cmd; + + pcibios_read_config_byte(dev->bus->number, + dev->devfn, + PCI_INTERRUPT_PIN, + &pin); + + return irqmap_ebsa[(PCI_SLOT(dev->devfn) + pin) & 3]; +} - for (dev = pci_devices; dev; dev = dev->next) { - pcibios_read_config_byte(dev->bus->number, - dev->devfn, - PCI_INTERRUPT_PIN, - &pin); +__initfunc(static int cats_irqval(struct pci_dev *dev)) +{ + if (dev->irq >= 128) + return 32 + (dev->irq & 0x1f); + + switch (dev->irq) { + case 1: + case 2: + case 3: + case 4: + return irqmap_cats[dev->irq - 1]; + case 0: + return 0; + } - dev->irq = irq[(PCI_SLOT(dev->devfn) + pin) & 3]; + printk("PCI: device %02x:%02x has unknown irq line %x\n", + dev->bus->number, dev->devfn, dev->irq); + return 0; +} - pcibios_write_config_byte(dev->bus->number, - dev->devfn, - PCI_INTERRUPT_LINE, - dev->irq); +__initfunc(void pcibios_fixup(void)) +{ + struct pci_dev *dev; + unsigned char cmd; - printk("PCI: %02x:%02x [%04x/%04x] pin %d irq %d\n", + for (dev = pci_devices; dev; dev = dev->next) { + /* sort out the irq mapping for this device */ + switch (machine_type) { + case MACH_TYPE_EBSA285: + dev->irq = ebsa_irqval(dev); + break; + case MACH_TYPE_CATS: + dev->irq = cats_irqval(dev); + break; + } + pcibios_write_config_byte(dev->bus->number, dev->devfn, + PCI_INTERRUPT_LINE, dev->irq); + + printk(KERN_DEBUG + "PCI: %02x:%02x [%04x/%04x] on irq %d\n", dev->bus->number, dev->devfn, - dev->vendor, dev->device, - pin, dev->irq); - - /* Turn on bus mastering - boot loader doesn't - perhaps it should! */ - pcibios_read_config_byte(dev->bus->number, dev->devfn, PCI_COMMAND, &cmd); - pcibios_write_config_byte(dev->bus->number, dev->devfn, PCI_COMMAND, cmd | PCI_COMMAND_MASTER); + dev->vendor, dev->device, dev->irq); + + /* Turn on bus mastering - boot loader doesn't + * - perhaps it should! - dag + */ + pcibios_read_config_byte(dev->bus->number, dev->devfn, + PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MASTER; + pcibios_write_config_byte(dev->bus->number, dev->devfn, + PCI_COMMAND, cmd); } } @@ -141,10 +194,16 @@ __initfunc(void pcibios_init(void)) rev = *(unsigned char *)0xfe000008; printk("DEC21285 PCI revision %02X\n", rev); -} -__initfunc(void pcibios_fixup_bus(struct pci_bus *bus)) -{ + /* + * Map our SDRAM at a known address in PCI space, just in case + * the firmware had other ideas. Using a nonzero base is slightly + * bizarre but apparently necessary to avoid problems with some + * video cards. + * + * We should really only do this if we are the configuration master. + */ + *((unsigned long *)0xfe000018) = 0x10000000; } __initfunc(void pcibios_fixup_bus(struct pci_bus *bus)) diff --git a/arch/arm/kernel/dma-ebsa285.c b/arch/arm/kernel/dma-ebsa285.c new file mode 100644 index 000000000..74af95584 --- /dev/null +++ b/arch/arm/kernel/dma-ebsa285.c @@ -0,0 +1,184 @@ +/* + * arch/arm/kernel/dma-ebsa285.c + * + * Copyright (C) 1998 Phil Blundell + * + * DMA functions specific to EBSA-285/CATS architectures + */ + +#include <linux/config.h> +#include <linux/sched.h> +#include <linux/malloc.h> +#include <linux/mman.h> +#include <linux/init.h> + +#include <asm/page.h> +#include <asm/pgtable.h> +#include <asm/dma.h> +#include <asm/io.h> +#include <asm/hardware.h> + +#include "dma.h" + +/* 8237 DMA controllers */ +#define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */ +#define IO_DMA2_BASE 0xC0 /* 16 bit master DMA, ch 4(=slave input)..7 */ + +/* 8237 DMA controller registers */ +#define DMA1_CMD_REG 0x08 /* command register (w) */ +#define DMA1_STAT_REG 0x08 /* status register (r) */ +#define DMA1_REQ_REG 0x09 /* request register (w) */ +#define DMA1_MASK_REG 0x0A /* single-channel mask (w) */ +#define DMA1_MODE_REG 0x0B /* mode register (w) */ +#define DMA1_CLEAR_FF_REG 0x0C /* clear pointer flip-flop (w) */ +#define DMA1_TEMP_REG 0x0D /* Temporary Register (r) */ +#define DMA1_RESET_REG 0x0D /* Master Clear (w) */ +#define DMA1_CLR_MASK_REG 0x0E /* Clear Mask */ +#define DMA1_MASK_ALL_REG 0x0F /* all-channels mask (w) */ + +#define DMA2_CMD_REG 0xD0 /* command register (w) */ +#define DMA2_STAT_REG 0xD0 /* status register (r) */ +#define DMA2_REQ_REG 0xD2 /* request register (w) */ +#define DMA2_MASK_REG 0xD4 /* single-channel mask (w) */ +#define DMA2_MODE_REG 0xD6 /* mode register (w) */ +#define DMA2_CLEAR_FF_REG 0xD8 /* clear pointer flip-flop (w) */ +#define DMA2_TEMP_REG 0xDA /* Temporary Register (r) */ +#define DMA2_RESET_REG 0xDA /* Master Clear (w) */ +#define DMA2_CLR_MASK_REG 0xDC /* Clear Mask */ +#define DMA2_MASK_ALL_REG 0xDE /* all-channels mask (w) */ + +int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_name) +{ + /* 21285 internal channels */ + if (channel == 0 || channel == 1) + return 0; + + /* ISA channels */ +// if (machine_is_cats() && ((channel >= 2 && channel <= 5) || +// (channel >= 7 && channel <= 9))) +// return 0; + + return -EINVAL; +} + +void arch_free_dma(dmach_t channel, dma_t *dma) +{ + /* nothing to do */ +} + +int arch_get_dma_residue(dmach_t channel, dma_t *dma) +{ + int residue = 0; + + switch (channel) { + case 0: + case 1: + break; +#ifdef CONFIG_CATS + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: +#endif + } + return residue; +} + +void arch_enable_dma(dmach_t channel, dma_t *dma) +{ + switch (channel) { + case 0: + case 1: + /* + * Not yet implemented + */ + break; +#ifdef CONFIG_CATS + case 2: + case 3: + case 4: + case 5: + case 7: + case 8: + case 9: + if (dma->invalid) { + static unsigned char dma_page[] = { 0x87, 0x83, 0x81, 0x82, + 0x00, 0x8b, 0x89, 0x8a }; + unsigned long int address = dma->buf.address, + length = dma->buf.length - 1; + outb(address >> 24, dma_page[channel - DMA_ISA_BASE] | 0x400); + outb(address >> 16, dma_page[channel - DMA_ISA_BASE]); + if (channel >= DMA_ISA_BASE + 5) { + outb(0, DMA2_CLEAR_FF_REG); + outb(address >> 1, + IO_DMA2_BASE + ((channel - DMA_ISA_BASE - 4) << 2)); + outb(address >> 9, + IO_DMA2_BASE + ((channel - DMA_ISA_BASE - 4) << 2)); + outb((length >> 1) & 0xfe, + IO_DMA2_BASE + 1 + ((channel - DMA_ISA_BASE - 4) << 2)); + outb(length >> 9, + IO_DMA2_BASE + 1 + ((channel - DMA_ISA_BASE - 4) << 2)); + outb(dma->dma_mode | (channel - DMA_ISA_BASE - 4), DMA2_MODE_REG); + } else { + outb(0, DMA1_CLEAR_FF_REG); + outb(address >> 0, IO_DMA1_BASE + ((channel - DMA_ISA_BASE) << 1)); + outb(address >> 8, IO_DMA1_BASE + ((channel - DMA_ISA_BASE) << 1)); + outb(length >> 0, + IO_DMA1_BASE + 1 + ((channel - DMA_ISA_BASE) << 1)); + outb(length >> 8, + IO_DMA1_BASE + 1 + ((channel - DMA_ISA_BASE) << 1)); + outb(dma->dma_mode | (channel - DMA_ISA_BASE), DMA1_MODE_REG); + } + switch (dma->dma_mode) { + case DMA_MODE_READ: + dma_cache_inv(__bus_to_virt(address), length + 1); + break; + case DMA_MODE_WRITE: + dma_cache_wback(__bus_to_virt(address), length + 1); + break; + } + dma->invalid = 0; + } + + if (channel >= DMA_ISA_BASE + 5) + outb(channel - DMA_ISA_BASE - 4, DMA2_MASK_REG); + else + outb(channel - DMA_ISA_BASE, DMA1_MASK_REG); +#endif + } +} + +void arch_disable_dma(dmach_t channel, dma_t *dma) +{ + switch (channel) { + case 0: + case 1: + /* + * Not yet implemented + */ + break; +#ifdef CONFIG_CATS + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + if (channel >= DMA_ISA_BASE + 5) + outb(channel - DMA_ISA_BASE, DMA2_MASK_REG); + else + outb((channel - DMA_ISA_BASE) | 4, DMA1_MASK_REG); +#endif + } +} + +__initfunc(void arch_dma_init(dma_t *dma)) +{ + /* Nothing to do */ +} diff --git a/arch/arm/kernel/dma-rpc.c b/arch/arm/kernel/dma-rpc.c index 301b32071..00cd95e79 100644 --- a/arch/arm/kernel/dma-rpc.c +++ b/arch/arm/kernel/dma-rpc.c @@ -20,7 +20,7 @@ #include "dma.h" -static struct fiq_handler fh = { "floppydma", NULL }; +static struct fiq_handler fh = { NULL, "floppydma", NULL, NULL }; #if 0 typedef enum { @@ -155,8 +155,8 @@ static void arch_dma_handle(int irq, void *dev_id, struct pt_regs *regs) } } while (dma->sg && (status & DMA_ST_INT)); - if (!no_buffer) - enable_irq(irq); + if (no_buffer) + disable_irq(irq); } int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_name) @@ -172,7 +172,8 @@ int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_name) case DMA_S0: case DMA_S1: save_flags_cli(flags); - ret = request_irq(dma->dma_irq, arch_dma_handle, SA_INTERRUPT, dev_name, dma); + ret = request_irq(dma->dma_irq, arch_dma_handle, + SA_INTERRUPT, dev_name, dma); if (!ret) disable_irq(dma->dma_irq); restore_flags(flags); @@ -261,8 +262,7 @@ void arch_enable_dma(dmach_t channel, dma_t *dma) case DMA_VIRTUAL_FLOPPY: { void *fiqhandler_start; unsigned int fiqhandler_length; - extern void floppy_fiqsetup(unsigned long len, unsigned long addr, - unsigned long port); + struct pt_regs regs; if (dma->dma_mode == DMA_MODE_READ) { extern unsigned char floppy_fiqin_start, floppy_fiqin_end; @@ -273,21 +273,20 @@ void arch_enable_dma(dmach_t channel, dma_t *dma) fiqhandler_start = &floppy_fiqout_start; fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start; } + + regs.ARM_r9 = dma->buf.length; + regs.ARM_r10 = __bus_to_virt(dma->buf.address); + regs.ARM_fp = (int)PCIO_FLOPPYDMABASE; + if (claim_fiq(&fh)) { printk("floppydma: couldn't claim FIQ.\n"); return; } - /* Allow access to page 0 via domains */ - __asm__ __volatile__("mcr p15, 0, %0, c3, c0" : - : "r" (DOMAIN_USER_MANAGER | - DOMAIN_KERNEL_CLIENT | - DOMAIN_IO_CLIENT)); - memcpy((void *)0x1c, fiqhandler_start, fiqhandler_length); - /* set domain register to normal */ - set_fs(get_fs()); - flush_page_to_ram(0); - floppy_fiqsetup(dma->buf.length, __bus_to_virt(dma->buf.address), (int)PCIO_FLOPPYDMABASE); + + set_fiq_handler(fiqhandler_start, fiqhandler_length); + set_fiq_regs(®s); enable_irq(dma->dma_irq); + } break; @@ -315,6 +314,7 @@ void arch_disable_dma(dmach_t channel, dma_t *dma) case DMA_VIRTUAL_FLOPPY: disable_irq(dma->dma_irq); + release_fiq(&fh); break; } } diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c index f03147e66..f7d204787 100644 --- a/arch/arm/kernel/ecard.c +++ b/arch/arm/kernel/ecard.c @@ -29,7 +29,6 @@ #include <asm/io.h> #include <asm/hardware.h> -#include <asm/arch/irq.h> #include <asm/ecard.h> #include <asm/irq.h> #include <asm/dma.h> @@ -46,7 +45,7 @@ #define BUS_ADDR(x) ((((unsigned long)(x)) << 2) + IO_BASE) extern unsigned long atomwide_serial_loader[], oak_scsi_loader[], noloader[]; -static const char blacklisted_str[] = "*loader blacklisted - not 32-bit compliant*"; +static const char blacklisted_str[] = "*loader s/w is not 32-bit compliant*"; static const struct expcard_blacklist { unsigned short manufacturer; @@ -62,7 +61,7 @@ static const struct expcard_blacklist { BLACKLIST_LOADER(MANU_OAK, PROD_OAK_SCSI, oak_scsi_loader), /* Supported cards with broken loader */ - { MANU_ALSYSTEMS, PROD_ALSYS_SCSIATAPI, noloader, "AlSystems PowerTec SCSI (loader blacklisted)" }, + { MANU_ALSYSTEMS, PROD_ALSYS_SCSIATAPI, noloader, "AlSystems PowerTec SCSI" }, /* Unsupported cards with no loader */ BLACKLIST_NOLOADER(MANU_MCS, PROD_MCS_CONNECT32) @@ -125,6 +124,7 @@ static expansioncard_ops_t ecard_default_ops = { */ void ecard_enableirq (unsigned int irqnr) { + irqnr &= 7; if (irqnr < MAX_ECARDS && irqno_to_expcard[irqnr] != -1) { ecard_t *ec = expcard + irqno_to_expcard[irqnr]; @@ -141,6 +141,7 @@ void ecard_enableirq (unsigned int irqnr) void ecard_disableirq (unsigned int irqnr) { + irqnr &= 7; if (irqnr < MAX_ECARDS && irqno_to_expcard[irqnr] != -1) { ecard_t *ec = expcard + irqno_to_expcard[irqnr]; @@ -154,6 +155,7 @@ void ecard_disableirq (unsigned int irqnr) void ecard_enablefiq (unsigned int fiqnr) { + fiqnr &= 7; if (fiqnr < MAX_ECARDS && irqno_to_expcard[fiqnr] != -1) { ecard_t *ec = expcard + irqno_to_expcard[fiqnr]; @@ -170,6 +172,7 @@ void ecard_enablefiq (unsigned int fiqnr) void ecard_disablefiq (unsigned int fiqnr) { + fiqnr &= 7; if (fiqnr < MAX_ECARDS && irqno_to_expcard[fiqnr] != -1) { ecard_t *ec = expcard + irqno_to_expcard[fiqnr]; @@ -186,7 +189,6 @@ static void ecard_irq_noexpmask(int intr_no, void *dev_id, struct pt_regs *regs) const int num_cards = ecard_numirqcards; int i, called = 0; - mask_irq (IRQ_EXPANSIONCARD); for (i = 0; i < num_cards; i++) { if (expcard[i].claimed && expcard[i].irq && (!expcard[i].irqmask || @@ -195,8 +197,7 @@ static void ecard_irq_noexpmask(int intr_no, void *dev_id, struct pt_regs *regs) called ++; } } - cli (); - unmask_irq (IRQ_EXPANSIONCARD); + cli(); if (called == 0) printk (KERN_WARNING "Wild interrupt from backplane?\n"); } @@ -433,10 +434,7 @@ int ecard_readchunk (struct in_chunk_dir *cd, ecard_t *ec, int id, int num) unsigned int ecard_address (ecard_t *ec, card_type_t type, card_speed_t speed) { switch (ec->slot_no) { - case 0: - case 1: - case 2: - case 3: + case 0 ... 3: switch (type) { case ECARD_MEMC: return MEMCECIO_BASE + (ec->slot_no << 12); @@ -449,20 +447,11 @@ unsigned int ecard_address (ecard_t *ec, card_type_t type, card_speed_t speed) } #ifdef IOCEC4IO_BASE - case 4: - case 5: - case 6: - case 7: - switch (type) { - case ECARD_MEMC: + case 4 ... 7: + if (type != ECARD_IOC) return 0; - case ECARD_IOC: - return IOCEC4IO_BASE + (speed << 17) + ((ec->slot_no - 4) << 12); - - default: - return 0; - } + return IOCEC4IO_BASE + (speed << 17) + ((ec->slot_no - 4) << 12); #endif #ifdef MEMCEC8IO_BASE case 8: @@ -558,7 +547,14 @@ __initfunc(static int ecard_probe (int card, int freeslot)) return 1; } -static struct irqaction irqexpansioncard = { ecard_irq_noexpmask, SA_INTERRUPT, 0, "expansion cards", NULL, NULL }; +static struct irqaction irqexpansioncard = { + ecard_irq_noexpmask, + SA_INTERRUPT, + 0, + "expansion cards", + NULL, + NULL +}; /* * Initialise the expansion card system. @@ -575,6 +571,7 @@ __initfunc(void ecard_init(void)) if (ecard_checkirqhw()) { printk (KERN_DEBUG "Expansion card interrupt management hardware found\n"); irqexpansioncard.handler = ecard_irq_expmask; + irqexpansioncard.flags |= SA_IRQNOMASK; have_expmask = -1; } #endif diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index a7553d350..7ecf1d59a 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -320,11 +320,19 @@ irq_prio_ebsa110: .macro mask_pc, rd, rm .endm + /* If we're optimising for StrongARM the resulting code won't + run on an ARM7 and we can save a couple of instructions. + --pb */ +#ifdef __ARM_ARCH_4__ + .macro arm700_bug_check, instr, temp + .endm +#else .macro arm700_bug_check, instr, temp and \temp, \instr, #0x0f000000 @ check for SWI teq \temp, #0x0f000000 bne .Larm700bug .endm +#endif .macro enable_irqs, temp mrs \temp, cpsr @@ -340,6 +348,7 @@ irq_prio_ebsa110: .endm +#ifndef __ARM_ARCH_4__ .Larm700bug: str lr, [r8] ldr r0, [sp, #S_PSR] @ Get calling cpsr msr spsr, r0 @@ -348,7 +357,7 @@ irq_prio_ebsa110: add sp, sp, #S_PC ldr lr, [sp], #S_FRAME_SIZE - S_PC @ Get PC and jump over PC, PSR, OLD_R0 movs pc, lr - +#endif .macro get_current_task, rd mov \rd, sp, lsr #13 @@ -672,6 +681,8 @@ __irq_invalid: sub sp, sp, #S_FRAME_SIZE @ Allocate space on stack for frame *----------------------------------------------------------------------------- * Handles floating point instructions */ +.LC2: .word SYMBOL_NAME(fp_enter) + __und_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go stmia sp, {r0 - r12} @ Save r0 - r12 add r8, sp, #S_PC @@ -681,25 +692,15 @@ __und_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go stmia r8, {r5 - r7} @ Save USR pc, cpsr, old_r0 mov fp, #0 - adr r1, .LC2 - ldmia r1, {r1, r4} - ldr r1, [r1] - get_current_task r2 - teq r1, r2 - blne SYMBOL_NAME(math_state_restore) - adrsvc al, r9, SYMBOL_NAME(fpreturn) - adrsvc al, lr, SYMBOL_NAME(fpundefinstr) - ldr pc, [r4] @ Call FP module USR entry point + adrsvc al, r9, ret_from_exception @ r9 = normal FP return + adrsvc al, lr, fpundefinstr @ lr = undefined instr return - .globl SYMBOL_NAME(fpundefinstr) -SYMBOL_NAME(fpundefinstr): @ Called by FP module on undefined instr - mov r0, lr - mov r1, sp - mrs r4, cpsr @ Enable interrupts - bic r4, r4, #I_BIT - msr cpsr, r4 - bl SYMBOL_NAME(do_undefinstr) - b ret_from_exception @ Normal FP exit +1: get_current_task r10 + mov lr, #1 + strb lr, [r10, #TSK_USED_MATH] @ set current->used_math + add r10, r10, #TSS_FPESAVE @ r10 = workspace + ldr r4, .LC2 + ldr pc, [r4] @ Call FP module USR entry point __und_svc: sub sp, sp, #S_FRAME_SIZE stmia sp, {r0 - r12} @ save r0 - r12 @@ -710,31 +711,24 @@ __und_svc: sub sp, sp, #S_FRAME_SIZE add r4, sp, #S_SP stmia r4, {r5 - r9} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro - adr r1, .LC2 - ldmia r1, {r1, r4} - ldr r1, [r1] - mov r2, sp, lsr #13 - mov r2, r2, lsl #13 - teq r1, r2 - blne SYMBOL_NAME(math_state_restore) - adrsvc al, r9, SYMBOL_NAME(fpreturnsvc) - adrsvc al, lr, SYMBOL_NAME(fpundefinstrsvc) - ldr pc, [r4] @ Call FP module SVC entry point - - .globl SYMBOL_NAME(fpundefinstrsvc) -SYMBOL_NAME(fpundefinstrsvc): + adrsvc al, r9, 3f @ r9 = normal FP return + bl 1b @ lr = undefined instr return + mov r0, r5 @ unsigned long pc mov r1, sp @ struct pt_regs *regs bl SYMBOL_NAME(do_undefinstr) - .globl SYMBOL_NAME(fpreturnsvc) -SYMBOL_NAME(fpreturnsvc): - ldr lr, [sp, #S_PSR] @ Get SVC cpsr +3: ldr lr, [sp, #S_PSR] @ Get SVC cpsr msr spsr, lr ldmia sp, {r0 - pc}^ @ Restore SVC registers -.LC2: .word SYMBOL_NAME(last_task_used_math) - .word SYMBOL_NAME(fp_enter) +fpundefinstr: mov r0, lr + mov r1, sp + mrs r4, cpsr @ Enable interrupts + bic r4, r4, #I_BIT + msr cpsr, r4 + adrsvc al, lr, ret_from_exception + b SYMBOL_NAME(do_undefinstr) __und_invalid: sub sp, sp, #S_FRAME_SIZE stmia sp, {r0 - lr} diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 422326338..6e0e9e38c 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -6,8 +6,6 @@ .globl ret_from_sys_call - .globl SYMBOL_NAME(fpreturn) -SYMBOL_NAME(fpreturn): ret_from_exception: adr r0, 1f ldmia r0, {r0, r1} @@ -36,12 +34,10 @@ ret_from_sys_call: bne SYMBOL_NAME(do_bottom_half) ret_with_reschedule: - ldr r0, 1f + 8 - ldr r0, [r0] + get_current_task r1 + ldr r0, [r1, #TSK_NEED_RESCHED] teq r0, #0 bne 2b - - get_current_task r1 ldr r1, [r1, #TSK_SIGPENDING] teq r1, #0 bne ret_signal @@ -50,7 +46,6 @@ ret_from_all: restore_user_regs 1: .word SYMBOL_NAME(bh_mask) .word SYMBOL_NAME(bh_active) - .word SYMBOL_NAME(need_resched) /*============================================================================= * SWI handler @@ -211,8 +206,11 @@ sys_sigaltstack_wrapper: * What we need to put into 0-0x1c are ldrs to branch to 0xC0000000 * (the kernel). * 0x1c onwards is reserved for FIQ, so I think that I will allocate 0xe0 onwards for - * the actuall address to jump to. + * the actual address to jump to. */ + + .section ".text.init",#alloc,#execinstr + #if defined(CONFIG_CPU_32) /* * these go into 0x00 @@ -281,39 +279,13 @@ ENTRY(trap_init) ldmfd sp!, {r4 - r7, pc}^ #endif + .previous + /*============================================================================ * FP support */ -1: .word SYMBOL_NAME(fp_save) - .word SYMBOL_NAME(fp_restore) - -.Lfpnull: mov pc, lr - - -/* - * Function to call when switching tasks to save FP state - */ -ENTRY(fpe_save) - ldr r1, 1b - ldr pc, [r1] - -/* - * Function to call when switching tasks to restore FP state - */ -ENTRY(fpe_restore) - ldr r1, 1b + 4 - ldr pc, [r1] - - .data ENTRY(fp_enter) - .word SYMBOL_NAME(fpundefinstr) - .word SYMBOL_NAME(fpundefinstrsvc) - -ENTRY(fp_save) - .word .Lfpnull -ENTRY(fp_restore) - .word .Lfpnull - + .word fpundefinstr diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c new file mode 100644 index 000000000..c32fef3c8 --- /dev/null +++ b/arch/arm/kernel/fiq.c @@ -0,0 +1,179 @@ +/* + * linux/arch/arm/kernel/fiq.c + * + * Copyright (C) 1998 Russell King + * FIQ support written by Philip Blundell <philb@gnu.org>, 1998. + * + * FIQ support re-written by Russell King to be more generic + * + * We now properly support a method by which the FIQ handlers can + * be stacked onto the vector. We still do not support sharing + * the FIQ vector itself. + * + * Operation is as follows: + * 1. Owner A claims FIQ: + * - default_fiq relinquishes control. + * 2. Owner A: + * - inserts code. + * - sets any registers, + * - enables FIQ. + * 3. Owner B claims FIQ: + * - if owner A has a relinquish function. + * - disable FIQs. + * - saves any registers. + * - returns zero. + * 4. Owner B: + * - inserts code. + * - sets any registers, + * - enables FIQ. + * 5. Owner B releases FIQ: + * - Owner A is asked to reacquire FIQ: + * - inserts code. + * - restores saved registers. + * - enables FIQ. + * 6. Goto 3 + */ +#include <linux/config.h> +#include <linux/mm.h> +#include <linux/mman.h> +#include <linux/init.h> + +#include <asm/fiq.h> +#include <asm/io.h> +#include <asm/pgtable.h> +#include <asm/system.h> +#include <asm/uaccess.h> + +#define FIQ_VECTOR 0x1c + +static unsigned long no_fiq_insn; + +#ifdef CONFIG_CPU_32 +static inline void unprotect_page_0(void) +{ + __asm__ __volatile__("mcr p15, 0, %0, c3, c0" : + : "r" (DOMAIN_USER_MANAGER | + DOMAIN_KERNEL_CLIENT | + DOMAIN_IO_CLIENT)); +} + +static inline void protect_page_0(void) +{ + set_fs(get_fs()); +} +#else + +#define unprotect_page_0() +#define protect_page_0() + +#endif + +/* Default reacquire function + * - we always relinquish FIQ control + * - we always reacquire FIQ control + */ +int fiq_def_op(void *ref, int relinquish) +{ + if (!relinquish) { + unprotect_page_0(); + *(unsigned long *)FIQ_VECTOR = no_fiq_insn; + protect_page_0(); + __flush_entry_to_ram(FIQ_VECTOR); + } + + return 0; +} + +static struct fiq_handler default_owner = + { NULL, "default", fiq_def_op, NULL }; +static struct fiq_handler *current_fiq = &default_owner; + +int get_fiq_list(char *buf) +{ + char *p = buf; + + if (current_fiq != &default_owner) + p += sprintf(p, "FIQ: %s\n", + current_fiq->name); + + return p - buf; +} + +void set_fiq_handler(void *start, unsigned int length) +{ + unprotect_page_0(); + + memcpy((void *)FIQ_VECTOR, start, length); + + protect_page_0(); +#if 0 + /* This doesn'w work correctly. Ok, it's a misuse + * of the DMA flushing code, but it ought to work. + * More investigation required. Maybe it really + * needs the cache flushed. + */ + dma_cache_wback(FIQ_VECTOR, length); +#else + processor.u.armv3v4._flush_cache_area(FIQ_VECTOR, FIQ_VECTOR + length, 1); +#endif +} + +void set_fiq_regs(struct pt_regs *regs) +{ + /* not yet - + * this is temporary to get the floppy working + * again on RiscPC. It *will* become more + * generic. + */ +#ifdef CONFIG_ARCH_ACORN + extern void floppy_fiqsetup(unsigned long len, unsigned long addr, + unsigned long port); + floppy_fiqsetup(regs->ARM_r9, regs->ARM_r10, regs->ARM_fp); +#endif +} + +void get_fiq_regs(struct pt_regs *regs) +{ + /* not yet */ +} + +int claim_fiq(struct fiq_handler *f) +{ + int ret = 0; + + if (current_fiq) { + ret = -EBUSY; + + if (current_fiq->fiq_op != NULL) + ret = current_fiq->fiq_op(current_fiq->dev_id, 1); + } + + if (!ret) { + f->next = current_fiq; + current_fiq = f; + } + + return ret; +} + +void release_fiq(struct fiq_handler *f) +{ + if (current_fiq != f) { + printk(KERN_ERR "%s FIQ trying to release %s FIQ\n", + f->name, current_fiq->name); +#ifdef CONFIG_DEBUG_ERRORS + __backtrace(); +#endif + return; + } + + do + current_fiq = current_fiq->next; + while (current_fiq->fiq_op(current_fiq->dev_id, 0)); +} + +__initfunc(void init_FIQ(void)) +{ + no_fiq_insn = *(unsigned long *)FIQ_VECTOR; + set_fs(get_fs()); +} diff --git a/arch/arm/kernel/head-armo.S b/arch/arm/kernel/head-armo.S index 80d88e890..1dc4fde13 100644 --- a/arch/arm/kernel/head-armo.S +++ b/arch/arm/kernel/head-armo.S @@ -43,7 +43,7 @@ Lcontinue: str r5, [r6] LC1: .word SYMBOL_NAME(_stext) LC0: .word SYMBOL_NAME(__bss_start) - .word SYMBOL_NAME(arm_id) + .word SYMBOL_NAME(processor_id) .word SYMBOL_NAME(_end) .word SYMBOL_NAME(init_task_union)+8192 Larm2_id: .long 0x41560200 diff --git a/arch/arm/kernel/head-armv.S b/arch/arm/kernel/head-armv.S index 2219d37c3..88e71adab 100644 --- a/arch/arm/kernel/head-armv.S +++ b/arch/arm/kernel/head-armv.S @@ -1,58 +1,54 @@ /* * linux/arch/arm/kernel/head32.S * - * Copyright (C) 1994, 1995, 1996, 1997 Russell King + * Copyright (C) 1994-1998 Russell King * * Kernel 32 bit startup code for ARM6 / ARM7 / StrongARM */ #include <linux/config.h> #include <linux/linkage.h> -#define DEBUG +#if (TEXTADDR & 0xffff) != 0x8000 +#error TEXTADDR must start at 0xXXXX8000 +#endif - .text - .align +#define DEBUG .globl SYMBOL_NAME(swapper_pg_dir) - .equ SYMBOL_NAME(swapper_pg_dir), 0xc0004000 + .equ SYMBOL_NAME(swapper_pg_dir), TEXTADDR - 0x4000 - .globl __stext + .text /* * Entry point and restart point. Entry *must* be called with r0 == 0, * MMU off. Note! These should be unique!!! Please read Documentation/ARM-README * for more information. * - * r1 = 0 -> ebsa110 - * r1 = 1 -> RPC + * r1 = 0 -> DEC EBSA-110 + * r1 = 1 -> Acorn RiscPC * r1 = 2 -> ebsit * r1 = 3 -> nexuspci - * r1 = 4 -> ebsa285 - * r1 = 5 -> vnc + * r1 = 4 -> DEC EBSA-285 + * r1 = 5 -> Corel Netwinder * r1 = 6 -> CATS + * r1 = 7 -> tbox */ + ENTRY(stext) ENTRY(_stext) -__entry: - teq r0, #0 @ check for illegal entry... +__entry: teq r0, #0 @ check for illegal entry... bne .Lerror @ loop indefinitely - cmp r1, #7 @ Unknown machine architecture + cmp r1, #8 @ Unknown machine architecture bge .Lerror -@ -@ First thing to do is to get the page tables set up so that we can call the kernel -@ in the correct place. This is relocatable code... -@ +/* First thing to do is to get the page tables set up so that we can call the kernel + * in the correct place. This is relocatable code... + * - Read processor ID register (CP#15, CR0). + */ mrc p15, 0, r9, c0, c0 @ get Processor ID -@ -@ Read processor ID register (CP#15, CR0). -@ NOTE: ARM2 & ARM250 cause an undefined instruction exception... -@ Values are: -@ XX01XXXX = ARMv4 architecture (StrongARM) -@ XX00XXXX = ARMv3 architecture -@ 4156061X = ARM 610 -@ 4156030X = ARM 3 -@ 4156025X = ARM 250 -@ 4156020X = ARM 2 -@ +/* Values are: + * XX01XXXX = ARMv4 architecture (StrongARM) + * XX00XXXX = ARMv3 architecture + * 4156061X = ARM 610 + */ adr r10, .LCProcTypes 1: ldmia r10!, {r5, r6, r8} @ Get Set, Mask, MMU Flags teq r5, #0 @ End of list? @@ -71,44 +67,51 @@ __entry: * r6 = I/O address */ mov r0, r4 - mov r1, #0 + mov r3, #0 add r2, r0, #0x4000 -1: str r1, [r0], #4 @ Clear page table +1: str r3, [r0], #4 @ Clear page table teq r0, r2 bne 1b /* * Add enough entries to allow the kernel to be called. * It will sort out the real mapping in paging_init. - * We map in 2MB of memory into 0xC0000000 - 0xC0200000 + * We map in 2MB of memory into (TEXTADDR-0x8000) + 2MB + */ + add r0, r4, #(TEXTADDR - 0x8000) >> 18 + mov r3, #0x0000000c @ SECT_CACHEABLE | SECT_BUFFERABLE + orr r3, r3, r8 + add r3, r3, r5 + str r3, [r0], #4 + add r3, r3, #1 << 20 + str r3, [r0], #4 + add r3, r3, #1 << 20 +#ifdef DEBUG +/* Map in IO space + * This allows debug messages to be output via a serial + * before/while paging_init. */ - add r0, r4, #0x3000 - mov r1, #0x0000000c @ SECT_CACHEABLE | SECT_BUFFERABLE - orr r1, r1, r8 - add r1, r1, r5 - str r1, [r0], #4 - add r1, r1, #1 << 20 - str r1, [r0], #4 - add r1, r1, #1 << 20 -@ -@ Map in IO space -@ add r0, r4, #0x3800 - orr r1, r6, r8 + orr r3, r6, r8 add r2, r0, #0x0800 -1: str r1, [r0], #4 - add r1, r1, #1 << 20 +1: str r3, [r0], #4 + add r3, r3, #1 << 20 teq r0, r2 bne 1b -@ -@ Map in screen at 0x02000000 & SCREEN2_BASE -@ +#endif +#ifdef CONFIG_ARCH_RPC +/* Map in screen at 0x02000000 & SCREEN2_BASE + * Similar reasons here - for debug, and when things go + * wrong to a certain extent. This is of limited use to + * non-Acorn RiscPC architectures though. + */ teq r5, #0 addne r0, r4, #0x80 @ 02000000 - movne r1, #0x02000000 - orrne r1, r1, r8 - strne r1, [r0] + movne r3, #0x02000000 + orrne r3, r3, r8 + strne r3, [r0] addne r0, r4, #0x3600 @ d8000000 - strne r1, [r0] + strne r3, [r0] +#endif @ @ The following should work on both v3 and v4 implementations @ @@ -122,25 +125,29 @@ __entry: mov pc, lr .Lerror: +#ifdef CONFIG_ARCH_RPC +/* Turn the screen red on a error - RiscPC only. + */ 1: mov r0, #0x02000000 - mov r1, #0x11 - orr r1, r1, r1, lsl #8 - orr r1, r1, r1, lsl #16 - str r1, [r0], #4 - str r1, [r0], #4 - str r1, [r0], #4 - str r1, [r0], #4 + mov r3, #0x11 + orr r3, r3, r3, lsl #8 + orr r3, r3, r3, lsl #16 + str r3, [r0], #4 + str r3, [r0], #4 + str r3, [r0], #4 + str r3, [r0], #4 +#endif b 1b .Lbranch: .long .Lalready_done_mmap @ Real address of routine - @ EBSA110 (pg dir phys, phys ram start, phys i/o) + @ DEC EBSA110 (pg dir phys, phys ram start, phys i/o) .LCMachTypes: .long SYMBOL_NAME(swapper_pg_dir) - 0xc0000000 @ Address of page tables (physical) .long 0 @ Address of RAM .long 0xe0000000 @ I/O address .long 0 - @ RPC + @ Acorn RiscPC .long SYMBOL_NAME(swapper_pg_dir) - 0xc0000000 + 0x10000000 .long 0x10000000 .long 0x03000000 @@ -158,7 +165,7 @@ __entry: .long 0x10000000 .long 0 - @ EBSA285 + @ DEC EBSA285 .long SYMBOL_NAME(swapper_pg_dir) - 0xc0000000 @ Address of page tables (physical) .long 0 @ Address of RAM .long 0x24000000 @ I/O base address (0x42000000 -> 0xFE000000) @@ -176,6 +183,12 @@ __entry: .long 0x24000000 @ I/O base address (0x42000000 -> 0xfe000000) .long 0 + @ tbox + .long SYMBOL_NAME(swapper_pg_dir) - 0xc0000000 + 0x80000000 + .long 0x80000000 @ Address of RAM + .long 0x00400000 @ Uart + .long 0 + .LCProcTypes: @ ARM6 / 610 .long 0x41560600 .long 0xffffff00 @@ -205,11 +218,6 @@ __entry: b .Lsa_fastclock .long 0 - -.LC0: .long SYMBOL_NAME(__bss_start) - .long SYMBOL_NAME(arm_id) - .long SYMBOL_NAME(_end) - .long SYMBOL_NAME(init_task_union)+8192 .align .Larmv3_flush_early: @@ -249,25 +257,36 @@ __entry: orr r0, r0, #0x1100 @ v4 supports separate I cache mov pc, lr + .section ".text.init",#alloc,#execinstr + .Lsa_fastclock: mcr p15, 0, r4, c15, c1, 2 @ Enable clock switching mov pc, lr +.LC0: .long SYMBOL_NAME(__entry) + .long SYMBOL_NAME(machine_type) + .long SYMBOL_NAME(__bss_start) + .long SYMBOL_NAME(processor_id) + .long SYMBOL_NAME(_end) + .long SYMBOL_NAME(init_task_union)+8192 + .align + .Lalready_done_mmap: - adr r5, __entry @ Add base back in - add r10, r10, r5 - adr r5, .LC0 - ldmia r5, {r5, r6, r8, sp} @ Setup stack - mov r4, #0 + adr r4, .LC0 + ldmia r4, {r3, r4, r5, r6, r8, sp} @ Setup stack + add r10, r10, r3 @ Add base back in + mov fp, #0 1: cmp r5, r8 @ Clear BSS - strcc r4, [r5],#4 + strcc fp, [r5],#4 bcc 1b + str r1, [r4] @ Save machine type str r9, [r6] @ Save processor ID mov lr, pc add pc, r10, #4 @ Call post-processor init mov fp, #0 b SYMBOL_NAME(start_kernel) + .text #ifdef DEBUG /* * Some debugging routines (useful if you've got MM problems and @@ -385,6 +404,9 @@ printhex: ldr r2, =hexbuf teq r3, r2 bne 1b mov r0, r2 + b printascii + + .ltorg ENTRY(printascii) addruart r3 @@ -413,7 +435,3 @@ ENTRY(printch) hexbuf: .space 16 #endif - - .text - .align 13 -ENTRY(this_must_match_init_task) diff --git a/arch/arm/kernel/init_task.c b/arch/arm/kernel/init_task.c index 90ae6952f..689c43589 100644 --- a/arch/arm/kernel/init_task.c +++ b/arch/arm/kernel/init_task.c @@ -6,7 +6,7 @@ static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; -static struct files * init_fd_array[NR_OPEN] = { NULL, }; +static struct file * init_fd_array[NR_OPEN] = { NULL, }; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; struct mm_struct init_mm = INIT_MM; @@ -21,4 +21,4 @@ struct mm_struct init_mm = INIT_MM; * * The things we do for performance.. */ -union task_union init_task_union __attribute__((__section__(".text"))) = { INIT_TASK }; +union task_union init_task_union __attribute__((__section__(".init.task"))) = { INIT_TASK }; diff --git a/arch/arm/kernel/ioport.c b/arch/arm/kernel/ioport.c index fe88df173..d375dcbdd 100644 --- a/arch/arm/kernel/ioport.c +++ b/arch/arm/kernel/ioport.c @@ -1,10 +1,7 @@ /* * linux/arch/arm/kernel/ioport.c * - * This contains the io-permission bitmap code - written by obz, with changes - * by Linus. - * - * Modifications for ARM processor Copyright (C) 1995, 1996 Russell King + * Io-port support is not used for ARM */ #include <linux/sched.h> @@ -14,85 +11,19 @@ #include <linux/ioport.h> /* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */ -asmlinkage void set_bitmap(unsigned long *bitmap, short base, short extent, int new_value) +/*asmlinkage void set_bitmap(unsigned long *bitmap, short base, short extent, int new_value) { - int mask; - unsigned long *bitmap_base = bitmap + (base >> 5); - unsigned short low_index = base & 0x1f; - int length = low_index + extent; - - if (low_index != 0) { - mask = (~0 << low_index); - if (length < 32) - mask &= ~(~0 << length); - if (new_value) - *bitmap_base++ |= mask; - else - *bitmap_base++ &= ~mask; - length -= 32; - } +}*/ - mask = (new_value ? ~0 : 0); - while (length >= 32) { - *bitmap_base++ = mask; - length -= 32; - } - - if (length > 0) { - mask = ~(~0 << length); - if (new_value) - *bitmap_base++ |= mask; - else - *bitmap_base++ &= ~mask; - } -} - -/* - * this changes the io permissions bitmap in the current task. - */ asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on) { - if (from + num <= from) - return -EINVAL; -#ifndef __arm__ - if (from + num > IO_BITMAP_SIZE*32) - return -EINVAL; -#endif - if (!capable(CAP_SYS_RAWIO)) - return -EPERM; - -#ifdef IODEBUG - printk("io: from=%d num=%d %s\n", from, num, (turn_on ? "on" : "off")); -#endif -#ifndef __arm__ - set_bitmap((unsigned long *)current->tss.io_bitmap, from, num, !turn_on); -#endif - return 0; + return -ENOSYS; } -unsigned int *stack; - -/* - * sys_iopl has to be used when you want to access the IO ports - * beyond the 0x3ff range: to get the full 65536 ports bitmapped - * you'd need 8kB of bitmaps/process, which is a bit excessive. - * - * Here we just change the eflags value on the stack: we allow - * only the super-user to do it. This depends on the stack-layout - * on system-call entry - see also fork() and the signal handling - * code. - */ asmlinkage int sys_iopl(long ebx,long ecx,long edx, long esi, long edi, long ebp, long eax, long ds, long es, long fs, long gs, long orig_eax, long eip,long cs,long eflags,long esp,long ss) { - unsigned int level = ebx; - - if (level > 3) - return -EINVAL; - if (!capable(CAP_SYS_RAWIO)) - return -EPERM; - *(&eflags) = (eflags & 0xffffcfff) | (level << 12); - return 0; + return -ENOSYS; } diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 89116048e..b4950ace2 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -3,7 +3,6 @@ * * Copyright (C) 1992 Linus Torvalds * Modifications for ARM processor Copyright (C) 1995-1998 Russell King. - * FIQ support written by Philip Blundell <philb@gnu.org>, 1998. * * This file contains the code used by various IRQ handling routines: * asking for different IRQ's should be done through these routines @@ -31,20 +30,10 @@ #include <linux/smp_lock.h> #include <linux/init.h> -#include <asm/fiq.h> #include <asm/hardware.h> #include <asm/io.h> #include <asm/pgtable.h> #include <asm/system.h> -#include <asm/arch/irq.h> - -unsigned int local_bh_count[NR_CPUS]; -unsigned int local_irq_count[NR_CPUS]; -spinlock_t irq_controller_lock; -static struct fiq_handler *current_fiq; -static unsigned long no_fiq_insn; - -#define FIQ_VECTOR ((unsigned long *)0x1c) #ifndef SMP #define irq_enter(cpu, irq) (++local_irq_count[cpu]) @@ -53,48 +42,65 @@ static unsigned long no_fiq_insn; #error SMP not supported #endif -#ifdef CONFIG_ARCH_ACORN -/* Bitmask indicating valid interrupt numbers - * (to be moved to include/asm-arm/arch-*) - */ -unsigned long validirqs[NR_IRQS / 32] = { - 0x003ffe7f, 0x000001ff, 0x000000ff, 0x00000000 +#ifndef cliIF +#define cliIF() +#endif + +unsigned int local_bh_count[NR_CPUS]; +unsigned int local_irq_count[NR_CPUS]; +spinlock_t irq_controller_lock; + +extern int get_fiq_list(char *); +extern void init_FIQ(void); + +struct irqdesc { + unsigned int nomask : 1; /* IRQ does not mask in IRQ */ + unsigned int enabled : 1; /* IRQ is currently enabled */ + unsigned int triggered: 1; /* IRQ has occurred */ + unsigned int probing : 1; /* IRQ in use for a probe */ + unsigned int probe_ok : 1; /* IRQ can be used for probe */ + unsigned int valid : 1; /* IRQ claimable */ + unsigned int unused :26; + void (*mask_ack)(unsigned int irq); /* Mask and acknowledge IRQ */ + void (*mask)(unsigned int irq); /* Mask IRQ */ + void (*unmask)(unsigned int irq); /* Unmask IRQ */ + struct irqaction *action; + unsigned int unused2[3]; }; -#define valid_irq(x) ((x) < NR_IRQS && validirqs[(x) >> 5] & (1 << ((x) & 31))) -#else +static struct irqdesc irq_desc[NR_IRQS]; -#define valid_irq(x) ((x) < NR_IRQS) -#endif +/* + * Dummy mask/unmask handler + */ +static void dummy_mask_unmask_irq(unsigned int irq) +{ +} -void disable_irq(unsigned int irq_nr) +void disable_irq(unsigned int irq) { unsigned long flags; spin_lock_irqsave(&irq_controller_lock, flags); -#ifdef cliIF - save_flags(flags); cliIF(); -#endif - mask_irq(irq_nr); + irq_desc[irq].enabled = 0; + irq_desc[irq].mask(irq); spin_unlock_irqrestore(&irq_controller_lock, flags); } -void enable_irq(unsigned int irq_nr) +void enable_irq(unsigned int irq) { unsigned long flags; spin_lock_irqsave(&irq_controller_lock, flags); -#ifdef cliIF - save_flags (flags); cliIF(); -#endif - unmask_irq(irq_nr); + irq_desc[irq].enabled = 1; + irq_desc[irq].probing = 0; + irq_desc[irq].triggered = 0; + irq_desc[irq].unmask(irq); spin_unlock_irqrestore(&irq_controller_lock, flags); } -struct irqaction *irq_action[NR_IRQS]; - int get_irq_list(char *buf) { int i; @@ -102,7 +108,7 @@ int get_irq_list(char *buf) char *p = buf; for (i = 0 ; i < NR_IRQS ; i++) { - action = irq_action[i]; + action = irq_desc[i].action; if (!action) continue; p += sprintf(p, "%3d: %10u %s", @@ -112,8 +118,8 @@ int get_irq_list(char *buf) } *p++ = '\n'; } - p += sprintf(p, "FIQ: %s\n", - current_fiq?current_fiq->name:"unused"); + + p += get_fiq_list(p); return p - buf; } @@ -122,26 +128,30 @@ int get_irq_list(char *buf) */ asmlinkage void do_IRQ(int irq, struct pt_regs * regs) { + struct irqdesc * desc = irq_desc + irq; struct irqaction * action; int status, cpu; -#if defined(HAS_IOMD) || defined(HAS_IOC) - if (irq != IRQ_EXPANSIONCARD) -#endif - { - spin_lock(&irq_controller_lock); - mask_and_ack_irq(irq); - spin_unlock(&irq_controller_lock); - } + spin_lock(&irq_controller_lock); + desc->mask_ack(irq); + spin_unlock(&irq_controller_lock); cpu = smp_processor_id(); irq_enter(cpu, irq); kstat.irqs[cpu][irq]++; + desc->triggered = 1; /* Return with this interrupt masked if no action */ status = 0; - action = *(irq + irq_action); + action = desc->action; + if (action) { + if (desc->nomask) { + spin_lock(&irq_controller_lock); + desc->unmask(irq); + spin_unlock(&irq_controller_lock); + } + if (!(action->flags & SA_INTERRUPT)) __sti(); @@ -150,33 +160,20 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs) action->handler(irq, action->dev_id, regs); action = action->next; } while (action); + if (status & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); __cli(); - switch (irq) { -#if defined(HAS_IOMD) || defined(HAS_IOC) - case IRQ_KEYBOARDTX: - case IRQ_EXPANSIONCARD: - break; -#endif -#ifdef HAS_IOMD - case IRQ_DMA0: - case IRQ_DMA1: - case IRQ_DMA2: - case IRQ_DMA3: - break; -#endif - - default: + if (!desc->nomask && desc->enabled) { spin_lock(&irq_controller_lock); - unmask_irq(irq); + desc->unmask(irq); spin_unlock(&irq_controller_lock); - break; } } irq_exit(cpu, irq); + /* * This should be conditional: we should really get * a return code from the irq handler to tell us @@ -197,9 +194,18 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs) #if defined(CONFIG_ARCH_ACORN) void do_ecard_IRQ(int irq, struct pt_regs *regs) { + struct irqdesc * desc; struct irqaction * action; + int cpu; + + desc = irq_desc + irq; + + cpu = smp_processor_id(); + kstat.irqs[cpu][irq]++; + desc->triggered = 1; + + action = desc->action; - action = *(irq + irq_action); if (action) { do { action->handler(irq, action->dev_id, regs); @@ -207,7 +213,7 @@ void do_ecard_IRQ(int irq, struct pt_regs *regs) } while (action); } else { spin_lock(&irq_controller_lock); - mask_irq (irq); + desc->mask(irq); spin_unlock(&irq_controller_lock); } } @@ -219,11 +225,18 @@ int setup_arm_irq(int irq, struct irqaction * new) struct irqaction *old, **p; unsigned long flags; - p = irq_action + irq; + if (new->flags & SA_SAMPLE_RANDOM) + rand_initialize_irq(irq); + + spin_lock_irqsave(&irq_controller_lock, flags); + + p = &irq_desc[irq].action; if ((old = *p) != NULL) { /* Can't share interrupts unless both agree to */ - if (!(old->flags & new->flags & SA_SHIRQ)) + if (!(old->flags & new->flags & SA_SHIRQ)) { + spin_unlock_irqrestore(&irq_controller_lock, flags); return -EBUSY; + } /* add new interrupt at end of irq queue */ do { @@ -233,18 +246,16 @@ int setup_arm_irq(int irq, struct irqaction * new) shared = 1; } - if (new->flags & SA_SAMPLE_RANDOM) - rand_initialize_irq(irq); - - save_flags_cli(flags); *p = new; if (!shared) { - spin_lock(&irq_controller_lock); - unmask_irq(irq); - spin_unlock(&irq_controller_lock); + irq_desc[irq].nomask = (new->flags & SA_IRQNOMASK) ? 1 : 0; + irq_desc[irq].enabled = 1; + irq_desc[irq].probing = 0; + irq_desc[irq].unmask(irq); } - restore_flags(flags); + + spin_unlock_irqrestore(&irq_controller_lock, flags); return 0; } @@ -257,8 +268,8 @@ int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *) { unsigned long retval; struct irqaction *action; - - if (!valid_irq(irq)) + + if (!irq_desc[irq].valid) return -EINVAL; if (!handler) return -EINVAL; @@ -286,14 +297,14 @@ void free_irq(unsigned int irq, void *dev_id) struct irqaction * action, **p; unsigned long flags; - if (!valid_irq(irq)) { + if (!irq_desc[irq].valid) { printk(KERN_ERR "Trying to free IRQ%d\n",irq); #ifdef CONFIG_DEBUG_ERRORS __backtrace(); #endif return; } - for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) { + for (p = &irq_desc[irq].action; (action = *p) != NULL; p = &action->next) { if (action->dev_id != dev_id) continue; @@ -310,75 +321,109 @@ void free_irq(unsigned int irq, void *dev_id) #endif } -unsigned long probe_irq_on (void) +/* Start the interrupt probing. Unlike other architectures, + * we don't return a mask of interrupts from probe_irq_on, + * but return the number of interrupts enabled for the probe. + * The interrupts which have been enabled for probing is + * instead recorded in the irq_desc structure. + */ +unsigned long probe_irq_on(void) { unsigned int i, irqs = 0; unsigned long delay; - /* first snaffle up any unassigned irqs */ - for (i = 15; i > 0; i--) { - if (!irq_action[i] && valid_irq(i)) { - enable_irq(i); - irqs |= 1 << i; - } + /* + * first snaffle up any unassigned but + * probe-able interrupts + */ + spin_lock_irq(&irq_controller_lock); + for (i = 0; i < NR_IRQS; i++) { + if (!irq_desc[i].valid || + !irq_desc[i].probe_ok || + irq_desc[i].action) + continue; + + irq_desc[i].probing = 1; + irq_desc[i].enabled = 1; + irq_desc[i].triggered = 0; + irq_desc[i].unmask(i); + irqs += 1; } + spin_unlock_irq(&irq_controller_lock); - /* wait for spurious interrupts to mask themselves out again */ + /* + * wait for spurious interrupts to mask themselves out again + */ for (delay = jiffies + HZ/10; delay > jiffies; ) /* min 100ms delay */; + /* + * now filter out any obviously spurious interrupts + */ + spin_lock_irq(&irq_controller_lock); + for (i = 0; i < NR_IRQS; i++) { + if (irq_desc[i].probing && irq_desc[i].triggered) { + irq_desc[i].probing = 0; + irqs -= 1; + } + } + spin_unlock_irq(&irq_controller_lock); + /* now filter out any obviously spurious interrupts */ - return irqs & get_enabled_irqs(); + return irqs; } -int probe_irq_off (unsigned long irqs) +/* + * Possible return values: + * >= 0 - interrupt number + * -1 - no interrupt/many interrupts + */ +int probe_irq_off(unsigned long irqs) { unsigned int i; + int irq_found = -1; - irqs &= ~get_enabled_irqs(); - if (!irqs) - return 0; - i = ffz (~irqs); - if (irqs != (irqs & (1 << i))) - i = -i; - return i; -} - -int claim_fiq(struct fiq_handler *f) -{ - if (current_fiq) { - if (current_fiq->callback == NULL || (*current_fiq->callback)()) - return -EBUSY; - } - current_fiq = f; - return 0; -} - -void release_fiq(struct fiq_handler *f) -{ - if (current_fiq != f) { - printk(KERN_ERR "%s tried to release FIQ when not owner!\n", - f->name); -#ifdef CONFIG_DEBUG_ERRORS - __backtrace(); -#endif - return; + /* + * look at the interrupts, and find exactly one + * that we were probing has been triggered + */ + spin_lock_irq(&irq_controller_lock); + for (i = 0; i < NR_IRQS; i++) { + if (irq_desc[i].probing && + irq_desc[i].triggered) { + if (irq_found != -1) { + irq_found = NO_IRQ; + goto out; + } + irq_found = i; + } } - current_fiq = NULL; - *FIQ_VECTOR = no_fiq_insn; - __flush_entry_to_ram(FIQ_VECTOR); + if (irq_found == -1) + irq_found = NO_IRQ; +out: + spin_unlock_irq(&irq_controller_lock); + return irq_found; } +/* + * Get architecture specific interrupt handlers + * and interrupt initialisation. + */ +#include <asm/arch/irq.h> + __initfunc(void init_IRQ(void)) { extern void init_dma(void); + int irq; - irq_init_irq(); - - current_fiq = NULL; - no_fiq_insn = *FIQ_VECTOR; + for (irq = 0; irq < NR_IRQS; irq++) { + irq_desc[irq].mask_ack = dummy_mask_unmask_irq; + irq_desc[irq].mask = dummy_mask_unmask_irq; + irq_desc[irq].unmask = dummy_mask_unmask_irq; + } + irq_init_irq(); + init_FIQ(); init_dma(); } - diff --git a/arch/arm/kernel/leds-ebsa110.c b/arch/arm/kernel/leds-ebsa110.c new file mode 100644 index 000000000..cc2f7a91d --- /dev/null +++ b/arch/arm/kernel/leds-ebsa110.c @@ -0,0 +1,30 @@ +/* + * arch/arm/kernel/leds-ebsa110.c + * + * Copyright (C) 1998 Russell King + * + * EBSA-110 LED control routines. We use the led as follows: + * + * - Red - toggles state every 50 timer interrupts + */ +#include <asm/hardware.h> +#include <asm/leds.h> +#include <asm/system.h> + +void leds_event(led_event_t ledevt) +{ + unsigned long flags; + + save_flags_cli(flags); + + switch(ledevt) { + case led_timer: + *(volatile unsigned char *)0xf2400000 ^= 128; + break; + + default: + break; + } + + restore_flags(flags); +} diff --git a/arch/arm/kernel/leds-ebsa285.c b/arch/arm/kernel/leds-ebsa285.c index f8add1ab7..a8cf2e775 100644 --- a/arch/arm/kernel/leds-ebsa285.c +++ b/arch/arm/kernel/leds-ebsa285.c @@ -1,5 +1,5 @@ /* - * arch/arm/kernel/leds-285.c + * arch/arm/kernel/leds-ebsa285.c * * Copyright (C) 1998 Russell King * diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index b606384c8..6ea02d891 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -38,9 +38,6 @@ #include <asm/system.h> #include <asm/io.h> -struct task_struct *last_task_used_math; - -extern void fpe_save(struct fp_soft_struct *); extern char *processor_modes[]; asmlinkage void ret_from_sys_call(void) __asm__("ret_from_sys_call"); @@ -108,7 +105,6 @@ void machine_power_off(void) { } - void show_regs(struct pt_regs * regs) { unsigned long flags; @@ -158,18 +154,14 @@ void show_regs(struct pt_regs * regs) */ void exit_thread(void) { - if (last_task_used_math == current) - last_task_used_math = NULL; } void flush_thread(void) { int i; - for (i = 0; i < 8; i++) - current->debugreg[i] = 0; - if (last_task_used_math == current) - last_task_used_math = NULL; + for (i = 0; i < NR_DEBUGS; i++) + current->tss.debug[i] = 0; current->used_math = 0; current->flags &= ~PF_USEDFPU; } @@ -189,13 +181,8 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, childregs->ARM_r0 = 0; save = ((struct context_save_struct *)(childregs)) - 1; - copy_thread_css (save); + copy_thread_css(save); p->tss.save = save; - /* - * Save current math state in p->tss.fpe_save if not already there. - */ - if (last_task_used_math == current) - fpe_save (&p->tss.fpstate.soft); return 0; } @@ -207,12 +194,8 @@ int dump_fpu (struct pt_regs *regs, struct user_fp *fp) { int fpvalid = 0; - if (current->used_math) { - if (last_task_used_math == current) - fpe_save (¤t->tss.fpstate.soft); - + if (current->used_math) memcpy (fp, ¤t->tss.fpstate.soft, sizeof (fp)); - } return fpvalid; } @@ -232,8 +215,8 @@ void dump_thread(struct pt_regs * regs, struct user * dump) dump->u_dsize = (current->mm->brk - current->mm->start_data + PAGE_SIZE - 1) >> PAGE_SHIFT; dump->u_ssize = 0; - for (i = 0; i < 8; i++) - dump->u_debugreg[i] = current->debugreg[i]; + for (i = 0; i < NR_DEBUGS; i++) + dump->u_debugreg[i] = current->tss.debug[i]; if (dump->start_stack < 0x04000000) dump->u_ssize = (0x04000000 - dump->start_stack) >> PAGE_SHIFT; diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 9ca7bc964..3df4ce886 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -3,7 +3,6 @@ /* edited by Linus Torvalds */ /* edited for ARM by Russell King */ -#include <linux/head.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/mm.h> @@ -376,7 +375,7 @@ int ptrace_set_bpt (struct task_struct *child) if (res < 0) return res; - child->debugreg[nsaved++] = alt = pc + 4; + child->tss.debug[nsaved++] = alt = pc + 4; printk ("ptrace_set_bpt: insn=%08lX pc=%08lX ", insn, pc); switch (insn & 0x0e100000) { case 0x00000000: @@ -515,20 +514,20 @@ printk ("b/bl "); } printk ("=%08lX\n", alt); if (alt != pc + 4) - child->debugreg[nsaved++] = alt; + child->tss.debug[nsaved++] = alt; for (i = 0; i < nsaved; i++) { - res = read_long (child, child->debugreg[i], &insn); + res = read_long (child, child->tss.debug[i], &insn); if (res >= 0) { - child->debugreg[i + 2] = insn; - res = write_long (child, child->debugreg[i], BREAKINST); + child->tss.debug[i + 2] = insn; + res = write_long (child, child->tss.debug[i], BREAKINST); } if (res < 0) { - child->debugreg[4] = 0; + child->tss.debug[4] = 0; return res; } } - child->debugreg[4] = nsaved; + child->tss.debug[4] = nsaved; return 0; } @@ -537,16 +536,16 @@ printk ("=%08lX\n", alt); */ int ptrace_cancel_bpt (struct task_struct *child) { - int i, nsaved = child->debugreg[4]; + int i, nsaved = child->tss.debug[4]; - child->debugreg[4] = 0; + child->tss.debug[4] = 0; if (nsaved > 2) { printk ("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved); nsaved = 2; } for (i = 0; i < nsaved; i++) - write_long (child, child->debugreg[i], child->debugreg[i + 2]); + write_long (child, child->tss.debug[i], child->tss.debug[i + 2]); return nsaved != 0; } @@ -680,7 +679,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ret = -EIO; if ((unsigned long) data > _NSIG) goto out; - child->debugreg[4] = -1; + child->tss.debug[4] = -1; child->flags &= ~PF_TRACESYS; wake_up_process(child); child->exit_code = data; diff --git a/arch/arm/kernel/setup-ebsa110.c b/arch/arm/kernel/setup-ebsa110.c deleted file mode 100644 index 2da4d6327..000000000 --- a/arch/arm/kernel/setup-ebsa110.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - * linux/arch/arm/kernel/setup-sa.c - * - * Copyright (C) 1995, 1996 Russell King - */ - -/* - * This file obtains various parameters about the system that the kernel - * is running on. - */ - -#include <linux/config.h> -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/stddef.h> -#include <linux/unistd.h> -#include <linux/ptrace.h> -#include <linux/malloc.h> -#include <linux/user.h> -#include <linux/a.out.h> -#include <linux/tty.h> -#include <linux/ioport.h> -#include <linux/delay.h> -#include <linux/major.h> -#include <linux/utsname.h> -#include <linux/init.h> -#include <linux/console.h> - -#include <asm/hardware.h> -#include <asm/pgtable.h> -#include <asm/procinfo.h> -#include <asm/segment.h> -#include <asm/setup.h> -#include <asm/system.h> - -#ifndef CONFIG_CMDLINE -#define CONFIG_CMDLINE "root=nfs rw console=ttyS1,38400n8" -#endif -#define COMMAND_LINE_SIZE 256 - -#define MEM_SIZE (16*1024*1024) - -struct screen_info screen_info; -struct processor processor; -unsigned char aux_device_present; - -extern const struct processor sa110_processor_functions; - -struct armversions armidlist[] = { - { 0x4401a100, 0xfffffff0, F_MMU|F_32BIT , "DEC", "sa110" , &sa110_processor_functions , "sa1x"}, - { 0x00000000, 0x00000000, 0 , "***", "*unknown*" , NULL , NULL } -}; - -unsigned long arm_id; -int armidindex; - -extern int root_mountflags; -extern int _etext, _edata, _end; - -static char command_line[COMMAND_LINE_SIZE] __initdata = { 0, }; - char saved_command_line[COMMAND_LINE_SIZE]; - -#ifdef CONFIG_BLK_DEV_RAM -extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */ -extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */ -extern int rd_image_start; /* starting block # of image */ - -static inline void setup_ramdisk(int start, int prompt, int load) -{ - rd_image_start = start; - rd_prompt = prompt; - rd_doload = load; -} -#else -#define setup_ramdisk(start,prompt,load) -#endif - -#ifdef PARAMS_BASE -static struct param_struct *params = (struct param_struct *)PARAMS_BASE; - -static inline char *setup_params(unsigned long *mem_end_p) -{ - ROOT_DEV = to_kdev_t(params->u1.s.rootdev); - ORIG_X = params->u1.s.video_x; - ORIG_Y = params->u1.s.video_y; - ORIG_VIDEO_COLS = params->u1.s.video_num_cols; - ORIG_VIDEO_LINES = params->u1.s.video_num_rows; - - setup_ramdisk(params->u1.s.rd_start, - (params->u1.s.flags & FLAG_RDPROMPT) == 0, - (params->u1.s.flags & FLAG_RDLOAD) == 0); - - *mem_end_p = 0xc0000000 + MEM_SIZE; - - return params->commandline; -} -#else -static char default_command_line[] = CONFIG_CMDLINE; - -static inline char *setup_params(unsigned long *mem_end_p) -{ - ROOT_DEV = 0x00ff; - - setup_ramdisk(0, 1, 1); - - *mem_end_p = 0xc0000000 + MEM_SIZE; - - return default_command_line; -} -#endif - -__initfunc(void setup_arch(char **cmdline_p, - unsigned long * memory_start_p, unsigned long * memory_end_p)) -{ - unsigned long memory_start, memory_end; - char c = ' ', *to = command_line, *from; - int len = 0; - - memory_start = (unsigned long)&_end; - - armidindex = 0; - - processor = sa110_processor_functions; - processor._proc_init(); - - from = setup_params(&memory_end); - - init_task.mm->start_code = TASK_SIZE; - init_task.mm->end_code = TASK_SIZE + (unsigned long) &_etext; - init_task.mm->end_data = TASK_SIZE + (unsigned long) &_edata; - init_task.mm->brk = TASK_SIZE + (unsigned long) &_end; - - /* Save unparsed command line copy for /proc/cmdline */ - memcpy(saved_command_line, from, COMMAND_LINE_SIZE); - saved_command_line[COMMAND_LINE_SIZE-1] = '\0'; - - for (;;) { - if (c == ' ' && - from[0] == 'm' && - from[1] == 'e' && - from[2] == 'm' && - from[3] == '=') { - memory_end = simple_strtoul(from+4, &from, 0); - if ( *from == 'K' || *from == 'k' ) { - memory_end = memory_end << 10; - from++; - } else if ( *from == 'M' || *from == 'm' ) { - memory_end = memory_end << 20; - from++; - } - memory_end = memory_end + PAGE_OFFSET; - } - c = *from++; - if (!c) - break; - if (COMMAND_LINE_SIZE <= ++len) - break; - *to++ = c; - } - - *to = '\0'; - *cmdline_p = command_line; - *memory_start_p = memory_start; - *memory_end_p = memory_end; - strcpy (system_utsname.machine, "sa110"); - -#ifdef CONFIG_FB - conswitchp = &fb_con; -#endif -} - -int get_cpuinfo(char * buffer) -{ - int len; - - len = sprintf (buffer, "CPU:\n" - "Type\t\t: %s\n" - "Revision\t: %d\n" - "Manufacturer\t: %s\n" - "32bit modes\t: %s\n" - "BogoMips\t: %lu.%02lu\n", - "sa110", - (int)arm_id & 15, - "DEC", - "yes", - (loops_per_sec+2500) / 500000, - ((loops_per_sec+2500) / 5000) % 100); - return len; -} diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index b69ce22cb..767faff9e 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -1,7 +1,7 @@ /* * linux/arch/arm/kernel/setup.c * - * Copyright (C) 1995, 1996, 1997 Russell King + * Copyright (C) 1995-1998 Russell King */ /* @@ -37,11 +37,37 @@ #include <asm/segment.h> #include <asm/setup.h> #include <asm/system.h> -#include <asm/arch/mmu.h> + +/* Work out which CPUs to support */ +#ifdef CONFIG_ARCH_ACORN +#define SUPPORT_CPU_ARM6 +#define SUPPORT_CPU_ARM7 +#define SUPPORT_CPU_SA110 +#else +#define SUPPORT_CPU_SA110 +#endif +#ifdef CONFIG_CPU_ARM6 +#define SUPPORT_CPU_ARM6 +#endif +#ifdef CONFIG_CPU_ARM7 +#define SUPPORT_CPU_ARM7 +#endif +#ifdef CONFIG_CPU_SA110 +#define SUPPORT_CPU_SA110 +#endif + +#ifndef CONFIG_CMDLINE +#define CONFIG_CMDLINE "root=nfs rw console=ttyS1,38400n8" +#endif +#define MEM_SIZE (16*1024*1024) +#define COMMAND_LINE_SIZE 256 struct drive_info_struct { char dummy[32]; } drive_info; struct screen_info screen_info = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 8 + orig_video_mode: 0, + orig_video_ega_bx: 0, + orig_video_isVGA: 1, + orig_video_points: 8 }; struct processor processor; unsigned char aux_device_present; @@ -66,35 +92,36 @@ const struct armversions armidlist[] = { { 0x41560300, 0xfffffff0, "ARM/VLSI", "arm3" , "armv2" , "v2", HWCAP_SWP, &arm3_processor_functions }, #elif defined(CONFIG_CPU_32) +#ifdef SUPPORT_CPU_ARM6 { 0x41560600, 0xfffffff0, "ARM/VLSI", "arm6" , "armv3" , "v3", HWCAP_SWP, &arm6_processor_functions }, { 0x41560610, 0xfffffff0, "ARM/VLSI", "arm610" , "armv3" , "v3", HWCAP_SWP, &arm6_processor_functions }, +#endif +#ifdef SUPPORT_CPU_ARM7 { 0x41007000, 0xffffff00, "ARM/VLSI", "arm7" , "armv3" , "v3", HWCAP_SWP, &arm7_processor_functions }, /* ARM710 IDs are non-standard */ { 0x41007100, 0xfff8ff00, "ARM/VLSI", "arm710" , "armv3" , "v3", HWCAP_SWP, &arm7_processor_functions }, +#endif +#ifdef SUPPORT_CPU_SA110 { 0x4401a100, 0xfffffff0, "DEC", "sa110" , "armv4" , "v3", HWCAP_SWP|HWCAP_HALF, &sa110_processor_functions }, #endif +#endif { 0x00000000, 0x00000000, "***", "unknown", "unknown", "**", 0, NULL } }; -static const struct param_struct *params = (struct param_struct *)PARAMS_BASE; - -unsigned long arm_id; -unsigned int vram_half_sam; +/* + * From head-armv.S + */ +unsigned int processor_id; +unsigned int machine_type; int armidindex; -int memc_ctrl_reg; -int number_ide_drives; -int number_mfm_drives; -extern int bytes_per_char_h; -extern int bytes_per_char_v; extern int root_mountflags; extern int _etext, _edata, _end; -extern unsigned long real_end_mem; /*------------------------------------------------------------------------- * Early initialisation routines for various configurable items in the @@ -107,12 +134,15 @@ extern unsigned long real_end_mem; */ #ifdef CONFIG_ARCH_RPC -extern void -init_dram_banks(const struct param_struct *params); +#include <asm/arch/mmu.h> + +unsigned int vram_half_sam; static void -setup_rpc(const struct param_struct *params) +setup_rpc(struct param_struct *params) { + extern void init_dram_banks(const struct param_struct *params); + init_dram_banks(params); switch (params->u1.s.pages_in_vram) { @@ -123,41 +153,103 @@ setup_rpc(const struct param_struct *params) default: vram_half_sam = 2048; } - - /* - * Set ROM speed to maximum - */ - outb (0x1d, IOMD_ROMCR0); } #else #define setup_rpc(x) #endif -/* - * ram disk - */ -#ifdef CONFIG_BLK_DEV_RAM -extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */ -extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */ -extern int rd_image_start; /* starting block # of image */ +#ifdef PARAMS_BASE -static void -setup_ramdisk(const struct param_struct *params) +#ifdef CONFIG_ARCH_ACORN +int memc_ctrl_reg; +int number_ide_drives; +int number_mfm_drives; +#endif + +static struct param_struct *params = (struct param_struct *)PARAMS_BASE; + +__initfunc(static char * +setup_params(unsigned long *mem_end_p)) { - rd_image_start = params->u1.s.rd_start; - rd_prompt = (params->u1.s.flags & FLAG_RDPROMPT) == 0; - rd_doload = (params->u1.s.flags & FLAG_RDLOAD) == 0; + ROOT_DEV = to_kdev_t(params->u1.s.rootdev); + ORIG_X = params->u1.s.video_x; + ORIG_Y = params->u1.s.video_y; + ORIG_VIDEO_COLS = params->u1.s.video_num_cols; + ORIG_VIDEO_LINES = params->u1.s.video_num_rows; + +#ifdef CONFIG_ARCH_ACORN +#ifndef CONFIG_FB + { + extern int bytes_per_char_h; + extern int bytes_per_char_v; + + bytes_per_char_h = params->u1.s.bytes_per_char_h; + bytes_per_char_v = params->u1.s.bytes_per_char_v; + } +#endif + memc_ctrl_reg = params->u1.s.memc_control_reg; + number_ide_drives = (params->u1.s.adfsdrives >> 6) & 3; + number_mfm_drives = (params->u1.s.adfsdrives >> 3) & 3; + + setup_rpc(params); + + if (!(params->u1.s.flags & FLAG_READONLY)) + root_mountflags &= ~MS_RDONLY; +#endif +#ifdef CONFIG_BLK_DEV_RAM + { + extern int rd_doload; + extern int rd_prompt; + extern int rd_image_start; + + rd_image_start = params->u1.s.rd_start; + rd_prompt = (params->u1.s.flags & FLAG_RDPROMPT) == 0; + rd_doload = (params->u1.s.flags & FLAG_RDLOAD) == 0; + } +#endif + +#ifdef CONFIG_ARCH_ACORN + *mem_end_p = GET_MEMORY_END(params); +#else + *mem_end_p = PAGE_OFFSET + MEM_SIZE; +#endif + + return params->commandline; } + #else -#define setup_ramdisk(p) + +static char default_command_line[] __initdata = CONFIG_CMDLINE; + +__initfunc(static char * +setup_params(unsigned long *mem_end_p)) +{ + ROOT_DEV = 0x00ff; + +#ifdef CONFIG_BLK_DEV_RAM + { + extern int rd_doload; + extern int rd_prompt; + extern int rd_image_start; + + rd_image_start = 0; + rd_prompt = 1; + rd_doload = 1; + } +#endif + + *mem_end_p = PAGE_OFFSET + MEM_SIZE; + + return default_command_line; +} #endif /* * initial ram disk */ #ifdef CONFIG_BLK_DEV_INITRD -static void -setup_initrd(const struct param_struct *params, unsigned long memory_end) +__initfunc(static void +setup_initrd(const struct param_struct *params)) { if (params->u1.s.initrd_start) { initrd_start = params->u1.s.initrd_start; @@ -166,130 +258,130 @@ setup_initrd(const struct param_struct *params, unsigned long memory_end) initrd_start = 0; initrd_end = 0; } +} - if (initrd_end > memory_end) { +__initfunc(static void +check_initrd(unsigned long mem_start, unsigned long mem_end)) +{ + if (initrd_end > mem_end) { printk ("initrd extends beyond end of memory " "(0x%08lx > 0x%08lx) - disabling initrd\n", - initrd_end, memory_end); + initrd_end, mem_end); initrd_start = 0; } } + #else -#define setup_initrd(p,m) +#define setup_initrd(p) +#define check_initrd(ms,me) #endif -static inline void -get_processor_type(void) +__initfunc(void +setup_processor(void)) { - for (armidindex = 0; ; armidindex ++) - if (!((armidlist[armidindex].id ^ arm_id) & - armidlist[armidindex].mask)) - break; + armidindex = 0; + + while ((armidlist[armidindex].id ^ processor_id) & + armidlist[armidindex].mask) + armidindex += 1; if (armidlist[armidindex].id == 0) { +#ifdef CONFIG_ARCH_ACORN int i; for (i = 0; i < 3200; i++) ((unsigned long *)SCREEN2_BASE)[i] = 0x77113322; - +#endif while (1); } + processor = *armidlist[armidindex].proc; + processor._proc_init(); } -#define COMMAND_LINE_SIZE 256 - -/* Can this be initdata? --pb - * command_line can be, saved_command_line can't though - */ -static char command_line[COMMAND_LINE_SIZE] __initdata = { 0, }; +static char command_line[COMMAND_LINE_SIZE] = { 0, }; char saved_command_line[COMMAND_LINE_SIZE]; -__initfunc(void setup_arch(char **cmdline_p, - unsigned long * memory_start_p, unsigned long * memory_end_p)) +__initfunc(static void +setup_mem(char *cmd_line, unsigned long *mem_start, unsigned long *mem_end)) +{ + char c = ' ', *to = command_line; + int len = 0; + + *mem_start = (unsigned long)&_end; + + for (;;) { + if (c == ' ' && + cmd_line[0] == 'm' && + cmd_line[1] == 'e' && + cmd_line[2] == 'm' && + cmd_line[3] == '=') { + *mem_end = simple_strtoul(cmd_line+4, &cmd_line, 0); + switch(*cmd_line) { + case 'M': + case 'm': + *mem_end <<= 10; + case 'K': + case 'k': + *mem_end <<= 10; + cmd_line++; + } + *mem_end = *mem_end + PAGE_OFFSET; + } + c = *cmd_line++; + if (!c) + break; + if (COMMAND_LINE_SIZE <= ++len) + break; + *to++ = c; + } + + *to = '\0'; +} + +__initfunc(void +setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * memory_end_p)) { static unsigned char smptrap; - unsigned long memory_start, memory_end; - char endian = 'l', c = ' ', *to = command_line; + unsigned long memory_end; + char endian = 'l'; char *from; - int len = 0; if (smptrap == 1) return; smptrap = 1; - get_processor_type (); - processor._proc_init (); + setup_processor(); -#ifndef CONFIG_FB - bytes_per_char_h = params->u1.s.bytes_per_char_h; - bytes_per_char_v = params->u1.s.bytes_per_char_v; -#endif - from = (char *)params->commandline; - ROOT_DEV = to_kdev_t (params->u1.s.rootdev); - ORIG_X = params->u1.s.video_x; - ORIG_Y = params->u1.s.video_y; - ORIG_VIDEO_COLS = params->u1.s.video_num_cols; - ORIG_VIDEO_LINES = params->u1.s.video_num_rows; - memc_ctrl_reg = params->u1.s.memc_control_reg; - number_ide_drives = (params->u1.s.adfsdrives >> 6) & 3; - number_mfm_drives = (params->u1.s.adfsdrives >> 3) & 3; + from = setup_params(&memory_end); + setup_initrd(params); - setup_rpc(params); - setup_ramdisk(params); - - if (!(params->u1.s.flags & FLAG_READONLY)) - root_mountflags &= ~MS_RDONLY; + /* Save unparsed command line copy for /proc/cmdline */ + memcpy(saved_command_line, from, COMMAND_LINE_SIZE); + saved_command_line[COMMAND_LINE_SIZE-1] = '\0'; - memory_start = MAPTOPHYS((unsigned long)&_end); - memory_end = GET_MEMORY_END(params); + setup_mem(from, memory_start_p, &memory_end); + check_initrd(*memory_start_p, memory_end); init_task.mm->start_code = TASK_SIZE; init_task.mm->end_code = TASK_SIZE + (unsigned long) &_etext; init_task.mm->end_data = TASK_SIZE + (unsigned long) &_edata; init_task.mm->brk = TASK_SIZE + (unsigned long) &_end; - /* Save unparsed command line copy for /proc/cmdline */ - memcpy(saved_command_line, from, COMMAND_LINE_SIZE); - saved_command_line[COMMAND_LINE_SIZE-1] = '\0'; - - for (;;) { - if (c == ' ' && - from[0] == 'm' && - from[1] == 'e' && - from[2] == 'm' && - from[3] == '=') { - memory_end = simple_strtoul(from+4, &from, 0); - if (*from == 'K' || *from == 'k') { - memory_end = memory_end << 10; - from++; - } else if (*from == 'M' || *from == 'm') { - memory_end = memory_end << 20; - from++; - } - memory_end = memory_end + PAGE_OFFSET; - } - c = *from++; - if (!c) - break; - if (COMMAND_LINE_SIZE <= ++len) - break; - *to++ = c; - } - - *to = '\0'; *cmdline_p = command_line; - *memory_start_p = memory_start; *memory_end_p = memory_end; - setup_initrd(params, memory_end); - sprintf(system_utsname.machine, "%s%c", armidlist[armidindex].arch_vsn, endian); sprintf(elf_platform, "%s%c", armidlist[armidindex].elf_vsn, endian); -#ifdef CONFIG_FB - conswitchp = &fb_con; +#ifdef CONFIG_VT +#if defined(CONFIG_VGA_CONSOLE) + conswitchp = &vga_con; +#elif defined(CONFIG_DUMMY_CONSOLE) + conswitchp = &dummy_con; +#endif #endif +printascii("setup_arch done\n"); } #if defined(CONFIG_ARCH_ARC) @@ -341,10 +433,10 @@ int get_cpuinfo(char * buffer) "BogoMips\t: %lu.%02lu\n" "Hardware\t: %s\n" "Optimisation\t: %s\n" - "IO Bus\t: %s\n", + "IO Bus\t\t: %s\n", armidlist[armidindex].manu, armidlist[armidindex].name, - (int)arm_id & 15, + (int)processor_id & 15, (loops_per_sec+2500) / 500000, ((loops_per_sec+2500) / 5000) % 100, HARDWARE, diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index 59e802a6c..fc5717e87 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -21,6 +21,17 @@ #include <asm/uaccess.h> #include <asm/pgtable.h> +void checksignals(void) +{ + sigset_t *blocked = ¤t->blocked; + unsigned long mask = blocked->sig[0] | sigmask(SIGKILL) | sigmask(SIGINT) | sigmask(SIGQUIT); + mask &= blocked->sig[1]; + if (~mask) { + printk("Bad signal mask\n"); + __backtrace(); + } +} + #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) #define SWI_SYS_SIGRETURN (0xef000000|(__NR_sigreturn)) @@ -137,31 +148,35 @@ struct rt_sigframe static int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) { - __get_user(regs->ARM_r0, &sc->arm_r0); - __get_user(regs->ARM_r1, &sc->arm_r1); - __get_user(regs->ARM_r2, &sc->arm_r2); - __get_user(regs->ARM_r3, &sc->arm_r3); - __get_user(regs->ARM_r4, &sc->arm_r4); - __get_user(regs->ARM_r5, &sc->arm_r5); - __get_user(regs->ARM_r6, &sc->arm_r6); - __get_user(regs->ARM_r7, &sc->arm_r7); - __get_user(regs->ARM_r8, &sc->arm_r8); - __get_user(regs->ARM_r9, &sc->arm_r9); - __get_user(regs->ARM_r10, &sc->arm_r10); - __get_user(regs->ARM_fp, &sc->arm_fp); - __get_user(regs->ARM_ip, &sc->arm_ip); - __get_user(regs->ARM_sp, &sc->arm_sp); - __get_user(regs->ARM_lr, &sc->arm_lr); - __get_user(regs->ARM_pc, &sc->arm_pc); /* security! */ + int err = 0; + + err |= __get_user(regs->ARM_r0, &sc->arm_r0); + err |= __get_user(regs->ARM_r1, &sc->arm_r1); + err |= __get_user(regs->ARM_r2, &sc->arm_r2); + err |= __get_user(regs->ARM_r3, &sc->arm_r3); + err |= __get_user(regs->ARM_r4, &sc->arm_r4); + err |= __get_user(regs->ARM_r5, &sc->arm_r5); + err |= __get_user(regs->ARM_r6, &sc->arm_r6); + err |= __get_user(regs->ARM_r7, &sc->arm_r7); + err |= __get_user(regs->ARM_r8, &sc->arm_r8); + err |= __get_user(regs->ARM_r9, &sc->arm_r9); + err |= __get_user(regs->ARM_r10, &sc->arm_r10); + err |= __get_user(regs->ARM_fp, &sc->arm_fp); + err |= __get_user(regs->ARM_ip, &sc->arm_ip); + err |= __get_user(regs->ARM_sp, &sc->arm_sp); + err |= __get_user(regs->ARM_lr, &sc->arm_lr); + err |= __get_user(regs->ARM_pc, &sc->arm_pc); #ifdef CONFIG_CPU_32 - __get_user(regs->ARM_cpsr, &sc->arm_cpsr); /* security! */ + err |= __get_user(regs->ARM_cpsr, &sc->arm_cpsr); #endif + if (!valid_user_regs(regs)) + return 1; /* send SIGTRAP if we're single-stepping */ if (ptrace_cancel_bpt (current)) send_sig (SIGTRAP, current, 1); - return regs->ARM_r0; + return err; } asmlinkage int sys_sigreturn(struct pt_regs *regs) @@ -185,11 +200,14 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs) recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); - return restore_sigcontext(regs, &frame->sc); + if (restore_sigcontext(regs, &frame->sc)) + goto badframe; + + return regs->ARM_r0; badframe: - lock_kernel(); - do_exit(SIGSEGV); + force_sig(SIGSEGV, current); + return 0; } asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) @@ -210,40 +228,47 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); - return restore_sigcontext(regs, &frame->uc.uc_mcontext); + if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) + goto badframe; + + return regs->ARM_r0; badframe: - lock_kernel(); - do_exit(SIGSEGV); + force_sig(SIGSEGV, current); + return 0; } -static void +static int setup_sigcontext(struct sigcontext *sc, /*struct _fpstate *fpstate,*/ struct pt_regs *regs, unsigned long mask) { - __put_user (regs->ARM_r0, &sc->arm_r0); - __put_user (regs->ARM_r1, &sc->arm_r1); - __put_user (regs->ARM_r2, &sc->arm_r2); - __put_user (regs->ARM_r3, &sc->arm_r3); - __put_user (regs->ARM_r4, &sc->arm_r4); - __put_user (regs->ARM_r5, &sc->arm_r5); - __put_user (regs->ARM_r6, &sc->arm_r6); - __put_user (regs->ARM_r7, &sc->arm_r7); - __put_user (regs->ARM_r8, &sc->arm_r8); - __put_user (regs->ARM_r9, &sc->arm_r9); - __put_user (regs->ARM_r10, &sc->arm_r10); - __put_user (regs->ARM_fp, &sc->arm_fp); - __put_user (regs->ARM_ip, &sc->arm_ip); - __put_user (regs->ARM_sp, &sc->arm_sp); - __put_user (regs->ARM_lr, &sc->arm_lr); - __put_user (regs->ARM_pc, &sc->arm_pc); /* security! */ + int err = 0; + + err |= __put_user (regs->ARM_r0, &sc->arm_r0); + err |= __put_user (regs->ARM_r1, &sc->arm_r1); + err |= __put_user (regs->ARM_r2, &sc->arm_r2); + err |= __put_user (regs->ARM_r3, &sc->arm_r3); + err |= __put_user (regs->ARM_r4, &sc->arm_r4); + err |= __put_user (regs->ARM_r5, &sc->arm_r5); + err |= __put_user (regs->ARM_r6, &sc->arm_r6); + err |= __put_user (regs->ARM_r7, &sc->arm_r7); + err |= __put_user (regs->ARM_r8, &sc->arm_r8); + err |= __put_user (regs->ARM_r9, &sc->arm_r9); + err |= __put_user (regs->ARM_r10, &sc->arm_r10); + err |= __put_user (regs->ARM_fp, &sc->arm_fp); + err |= __put_user (regs->ARM_ip, &sc->arm_ip); + err |= __put_user (regs->ARM_sp, &sc->arm_sp); + err |= __put_user (regs->ARM_lr, &sc->arm_lr); + err |= __put_user (regs->ARM_pc, &sc->arm_pc); #ifdef CONFIG_CPU_32 - __put_user (regs->ARM_cpsr, &sc->arm_cpsr); /* security! */ + err |= __put_user (regs->ARM_cpsr, &sc->arm_cpsr); #endif - __put_user (current->tss.trap_no, &sc->trap_no); - __put_user (current->tss.error_code, &sc->error_code); - __put_user (mask, &sc->oldmask); + err |= __put_user (current->tss.trap_no, &sc->trap_no); + err |= __put_user (current->tss.error_code, &sc->error_code); + err |= __put_user (mask, &sc->oldmask); + + return err; } static void setup_frame(int sig, struct k_sigaction *ka, @@ -251,41 +276,47 @@ static void setup_frame(int sig, struct k_sigaction *ka, { struct sigframe *frame; unsigned long retcode; + int err = 0; frame = (struct sigframe *)regs->ARM_sp - 1; if (!access_ok(VERIFT_WRITE, frame, sizeof (*frame))) goto segv_and_exit; - setup_sigcontext(&frame->sc, /*&frame->fpstate,*/ regs, set->sig[0]); + err |= setup_sigcontext(&frame->sc, /*&frame->fpstate,*/ regs, set->sig[0]); if (_NSIG_WORDS > 1) { - __copy_to_user(frame->extramask, &set->sig[1], - sizeof(frame->extramask)); + err |= __copy_to_user(frame->extramask, &set->sig[1], + sizeof(frame->extramask)); } /* Set up to return from userspace. If provided, use a stub already in userspace. */ if (ka->sa.sa_flags & SA_RESTORER) { - retcode = (unsigned long)ka->sa.sa_restorer; /* security! */ + retcode = (unsigned long)ka->sa.sa_restorer; } else { retcode = (unsigned long)&frame->retcode; - __put_user(SWI_SYS_SIGRETURN, &frame->retcode); + err |= __put_user(SWI_SYS_SIGRETURN, &frame->retcode); __flush_entry_to_ram (&frame->retcode); } + if (err) + goto segv_and_exit; + if (current->exec_domain && current->exec_domain->signal_invmap && sig < 32) regs->ARM_r0 = current->exec_domain->signal_invmap[sig]; else regs->ARM_r0 = sig; regs->ARM_sp = (unsigned long)frame; regs->ARM_lr = retcode; - regs->ARM_pc = (unsigned long)ka->sa.sa_handler; /* security! */ - return; + regs->ARM_pc = (unsigned long)ka->sa.sa_handler; + if (valid_user_regs(regs)) + return; segv_and_exit: - lock_kernel(); - do_exit (SIGSEGV); + if (sig == SIGSEGV) + ka->sa.sa_handler = SIG_DFL; + force_sig(SIGSEGV, current); } static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, @@ -293,44 +324,50 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, { struct rt_sigframe *frame; unsigned long retcode; + int err = 0; frame = (struct rt_sigframe *)regs->ARM_sp - 1; if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) goto segv_and_exit; - __put_user(&frame->info, &frame->pinfo); - __put_user(&frame->uc, &frame->puc); - __copy_to_user(&frame->info, info, sizeof(*info)); + err |= __put_user(&frame->info, &frame->pinfo); + err |= __put_user(&frame->uc, &frame->puc); + err |= __copy_to_user(&frame->info, info, sizeof(*info)); /* Clear all the bits of the ucontext we don't use. */ - __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext)); + err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext)); - setup_sigcontext(&frame->uc.uc_mcontext, /*&frame->fpstate,*/ - regs, set->sig[0]); - __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); + err |= setup_sigcontext(&frame->uc.uc_mcontext, /*&frame->fpstate,*/ + regs, set->sig[0]); + err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); /* Set up to return from userspace. If provided, use a stub already in userspace. */ if (ka->sa.sa_flags & SA_RESTORER) { - retcode = (unsigned long)ka->sa.sa_restorer; /* security! */ + retcode = (unsigned long)ka->sa.sa_restorer; } else { retcode = (unsigned long)&frame->retcode; - __put_user(SWI_SYS_RT_SIGRETURN, &frame->retcode); + err |= __put_user(SWI_SYS_RT_SIGRETURN, &frame->retcode); __flush_entry_to_ram (&frame->retcode); } + if (err) + goto segv_and_exit; + if (current->exec_domain && current->exec_domain->signal_invmap && sig < 32) regs->ARM_r0 = current->exec_domain->signal_invmap[sig]; else regs->ARM_r0 = sig; regs->ARM_sp = (unsigned long)frame; regs->ARM_lr = retcode; - regs->ARM_pc = (unsigned long)ka->sa.sa_handler; /* security! */ - return; + regs->ARM_pc = (unsigned long)ka->sa.sa_handler; + if (valid_user_regs(regs)) + return; segv_and_exit: - lock_kernel(); - do_exit (SIGSEGV); + if (sig == SIGSEGV) + ka->sa.sa_handler = SIG_DFL; + force_sig(SIGSEGV, current); } /* diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c index ba0d4eda2..56ada1dc7 100644 --- a/arch/arm/kernel/sys_arm.c +++ b/arch/arm/kernel/sys_arm.c @@ -363,14 +363,6 @@ asmlinkage int sys_olduname(struct oldold_utsname * name) asmlinkage int sys_pause(void) { - static int warned = 0; - - if (warned == 0) { - warned ++; - printk (KERN_NOTICE "%s (%d): obsolete pause call\n", - current->comm, current->pid); - } - current->state = TASK_INTERRUPTIBLE; schedule(); return -ERESTARTNOHAND; diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index 32aa6a083..7445921d9 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c @@ -62,7 +62,7 @@ extern volatile unsigned long lost_ticks; * machines were long is 32-bit! (However, as time_t is signed, we * will already get problems at other places on 2038-01-19 03:14:08) */ -static inline unsigned long mktime(unsigned int year, unsigned int mon, +unsigned long mktime(unsigned int year, unsigned int mon, unsigned int day, unsigned int hour, unsigned int min, unsigned int sec) { diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 2170dfd58..6da813aa2 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -24,9 +24,6 @@ #include <asm/atomic.h> #include <asm/pgtable.h> -extern struct task_struct *last_task_used_math; -extern void fpe_save(struct fp_soft_struct *); -extern void fpe_restore(struct fp_soft_struct *); extern void die_if_kernel(char *str, struct pt_regs *regs, int err, int ret); extern void c_backtrace (unsigned long fp, int pmode); extern int ptrace_cancel_bpt (struct task_struct *); @@ -252,26 +249,7 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason, int proc_mode) */ asmlinkage void math_state_restore (void) { - if (last_task_used_math == current) - return; - if (last_task_used_math) - /* - * Save current fp state into last_task_used_math->tss.fpe_save - */ - fpe_save (&last_task_used_math->tss.fpstate.soft); - last_task_used_math = current; - if (current->used_math) { - /* - * Restore current fp state from current->tss.fpe_save - */ - fpe_restore (¤t->tss.fpstate.soft); - } else { - /* - * initialise fp state - */ - fpe_restore (&init_task.tss.fpstate.soft); - current->used_math = 1; - } + current->used_math = 1; } asmlinkage void arm_syscall (int no, struct pt_regs *regs) |