diff options
Diffstat (limited to 'arch/arm')
86 files changed, 4917 insertions, 3144 deletions
diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 11fefd85b..0895fc0ba 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -12,91 +12,101 @@ # # Copyright (C) 1995-1999 by Russell King -# GCC 2.7 uses different options to later compilers; sort out which we have -CONFIG_GCC_NEW := $(shell if $(CC) --version 2>&1 | grep '^2\.7' > /dev/null; then echo n; else echo y; fi) +LD := $(CROSS_COMPILE)ld +OBJCOPY := $(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S +CPP := $(CC) -E +PERL := perl +LINKFLAGS := -X -T arch/arm/vmlinux.lds +ARCHCC := $(word 1,$(CC)) + + +CFLAGS_PIPE := -pipe +CFLAGS := $(CFLAGS) $(CFLAGS_PIPE) + +ifdef CONFIG_FRAME_POINTER +CFLAGS := $(CFLAGS:-fomit-frame-pointer=) +endif + +ifdef CONFIG_DEBUG_INFO +CFLAGS += -g +endif -# See if this is ld "2.9.4" or later -NEW_LINKER := $(shell if $(LD) --gc-sections --version >/dev/null 2>&1; then echo y; else echo n; fi) -# CFLAGS_PROC - processor dependent CFLAGS -# PROCESSOR - processor type -# TEXTADDR - Uncompressed kernel link text address -# ZTEXTADDR - Compressed kernel link text address -# ZRELADDR - Compressed kernel relocating address -# (point at which uncompressed kernel is loaded). +# GCC 2.7 uses different options to later compilers; sort out which we have +NEW_GCC := $(shell if $(CC) --version 2>&1 | grep '^2\.7' > /dev/null; then echo n; else echo y; fi) # # select flags depending on the compiler # -ifeq ($(CONFIG_GCC_NEW),y) - CFLAGS_PROC := -mshort-load-bytes -msoft-float - CFLAGS_PROC_CPU_26 := -mcpu=arm3 -Os - CFLAGS_PROC_CPU_32v3 := -march=armv3 - CFLAGS_PROC_CPU_32v4 := -march=armv4 - CFLAGS_ARM6 := -mtune=arm6 - CFLAGS_ARM7 := -mtune=arm7 - CFLAGS_SA110 := -mtune=strongarm110 +ifeq ($(NEW_GCC),y) +CFLAGS += -mshort-load-bytes -msoft-float +CFLAGS_PROC_CPU_26 := -mcpu=arm3 -Os +CFLAGS_PROC_CPU_32v3 := -march=armv3 +CFLAGS_PROC_CPU_32v4 := -march=armv4 +CFLAGS_ARM6 := -mtune=arm6 +CFLAGS_ARM7 := -mtune=arm7 +CFLAGS_SA110 := -mtune=strongarm110 else - CFLAGS_PROC := - CFLAGS_PROC_CPU_26 := -m3 - CFLAGS_PROC_CPU_32v3 := - CFLAGS_PROC_CPU_32v4 := - CFLAGS_ARM6 := -m6 - CFLAGS_ARM7 := -m6 - CFLAGS_SA110 := -m6 +CFLAGS_PROC_CPU_26 := -m3 +CFLAGS_PROC_CPU_32v3 := +CFLAGS_PROC_CPU_32v4 := +CFLAGS_ARM6 := -m6 +CFLAGS_ARM7 := -m6 +CFLAGS_SA110 := -m6 endif +# See if this is ld "2.9.4" or later +NEW_LINKER := $(shell if $(LD) --gc-sections --version >/dev/null 2>&1; then echo y; else echo n; fi) + ifeq ($(NEW_LINKER),y) - ASFLAGS_PROC := -mno-fpu - ASFLAGS_PROC_CPU_26 := -mapcs-26 - ASFLAGS_PROC_CPU_32v3 := -mapcs-32 -marmv3m - ASFLAGS_PROC_CPU_32v4 := -mapcs-32 -marmv4t - LINKFLAGS := -p +AFLAGS += -mno-fpu +AFLAGS_PROC_CPU_26 := -mapcs-26 +AFLAGS_PROC_CPU_32v3 := -mapcs-32 -marmv3m +AFLAGS_PROC_CPU_32v4 := -mapcs-32 -marmv4t +LINKFLAGS := -p $(LINKFLAGS) else - ASFLAGS_PROC := - ASFLAGS_PROC_CPU_26 := -m3 - ASFLAGS_PROC_CPU_32v3 := -m6 - ASFLAGS_PROC_CPU_32v4 := -m6 - LINKFLAGS := +AFLAGS_PROC_CPU_26 := -m3 +AFLAGS_PROC_CPU_32v3 := -m6 +AFLAGS_PROC_CPU_32v4 := -m6 endif +# +# Select CPU dependent flags +# ifeq ($(CONFIG_CPU_26),y) - PROCESSOR = armo - TEXTADDR = 0x02080000 - ZTEXTADDR = 0x01800000 - ZRELADDR = 0x02080000 - CFLAGS_PROC += $(CFLAGS_PROC_CPU_26) - ASFLAGS_PROC += $(ASFLAGS_PROC_CPU_26) + PROCESSOR = armo + TEXTADDR = 0x02080000 + CFLAGS += $(CFLAGS_PROC_CPU_26) + AFLAGS += $(AFLAGS_PROC_CPU_26) endif ifeq ($(CONFIG_CPU_32),y) - PROCESSOR = armv - TEXTADDR = 0xC0008000 - ifeq ($(CONFIG_CPU_32v4),y) - CFLAGS_PROC += $(CFLAGS_PROC_CPU_32v4) - ASFLAGS_PROC += $(ASFLAGS_PROC_CPU_32v4) - else - CFLAGS_PROC += $(CFLAGS_PROC_CPU_32v3) - ASFLAGS_PROC += $(ASFLAGS_PROC_CPU_32v3) - endif - # - # Exactly one of the following must be selected - # - ifeq ($(CONFIG_CPU_ARM6),y) - CFLAGS_PROC += $(CFLAGS_ARM6) - else - ifeq ($(CONFIG_CPU_ARM7),y) - CFLAGS_PROC += $(CFLAGS_ARM7) - else - ifeq ($(CONFIG_CPU_SA110),y) - CFLAGS_PROC += $(CFLAGS_SA110) - endif - endif - endif + PROCESSOR = armv + TEXTADDR = 0xC0008000 + ifeq ($(CONFIG_CPU_32v4),y) + CFLAGS += $(CFLAGS_PROC_CPU_32v4) + AFLAGS += $(AFLAGS_PROC_CPU_32v4) + else + CFLAGS += $(CFLAGS_PROC_CPU_32v3) + AFLAGS += $(AFLAGS_PROC_CPU_32v3) + endif + # + # Exactly one of the following must be selected + # + ifeq ($(CONFIG_CPU_ARM6),y) + CFLAGS += $(CFLAGS_ARM6) + else + ifeq ($(CONFIG_CPU_ARM7),y) + CFLAGS += $(CFLAGS_ARM7) + else + ifeq ($(CONFIG_CPU_SA110),y) + CFLAGS += $(CFLAGS_SA110) + endif + endif + endif endif - -COMPRESSED_HEAD = head.o +GCCLIB := $(shell $(CC) $(CFLAGS) --print-libgcc-file-name) ifeq ($(CONFIG_ARCH_A5K),y) MACHINE = a5k @@ -111,22 +121,16 @@ endif ifeq ($(CONFIG_ARCH_RPC),y) MACHINE = rpc ARCHDIR = rpc -ZTEXTADDR = 0x10008000 -ZRELADDR = 0x10008000 endif ifeq ($(CONFIG_ARCH_EBSA110),y) MACHINE = ebsa110 ARCHDIR = ebsa110 -ZTEXTADDR = 0x00008000 -ZRELADDR = 0x00008000 endif ifeq ($(CONFIG_FOOTBRIDGE),y) MACHINE = footbridge ARCHDIR = ebsa285 -ZTEXTADDR = 0x00008000 -ZRELADDR = 0x00008000 endif ifeq ($(CONFIG_ARCH_CO285),y) @@ -136,56 +140,31 @@ endif ifeq ($(CONFIG_ARCH_NEXUSPCI),y) MACHINE = nexuspci ARCHDIR = nexuspci -ZTEXTADDR = 0x40200000 -ZRELADDR = 0x40008000 -COMPRESSED_EXTRA = $(TOPDIR)/arch/arm/lib/ll_char_wr_scc.o -COMPRESSED_HEAD = head-nexuspci.o endif - - -PERL = perl -LD = $(CROSS_COMPILE)ld -OBJCOPY = $(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S -OBJDUMP = $(CROSS_COMPILE)objdump -CPP = $(CC) -E -ARCHCC := $(word 1,$(CC)) -GCCLIB := `$(CC) $(CFLAGS_PROC) --print-libgcc-file-name` -HOSTCFLAGS := $(CFLAGS:-fomit-frame-pointer=) -ifeq ($(CONFIG_FRAME_POINTER),y) -CFLAGS := $(CFLAGS:-fomit-frame-pointer=) -endif -CFLAGS := $(CFLAGS_PROC) $(CFLAGS) -pipe -ASFLAGS := $(ASFLAGS_PROC) $(ASFLAGS) -LINKFLAGS += -X -T $(TOPDIR)/arch/arm/vmlinux-$(PROCESSOR).lds -e stext -ZLINKFLAGS = -Ttext $(ZTEXTADDR) - -# If we're intending to debug the kernel, make sure it has line number -# information. This gets stripped out when building (z)Image so it doesn't -# add anything to the footprint of the running kernel. -ifeq ($(CONFIG_DEBUG_INFO),y) -CFLAGS += -g +ifeq ($(CONFIG_ARCH_SA1100),u) +MACHINE = sa1100 +ARCHDIR = sa1100 endif HEAD := arch/arm/kernel/head-$(PROCESSOR).o \ arch/arm/kernel/init_task.o -SUBDIRS := arch/arm/special $(SUBDIRS) arch/arm/lib arch/arm/kernel \ - arch/arm/mm arch/arm/nwfpe +SUBDIRS += arch/arm/kernel arch/arm/mm arch/arm/lib \ + arch/arm/special arch/arm/nwfpe CORE_FILES := arch/arm/kernel/kernel.o arch/arm/mm/mm.o $(CORE_FILES) LIBS := arch/arm/lib/lib.a $(LIBS) $(GCCLIB) DRIVERS += arch/arm/special/special.a -ifeq ($(CONFIG_ARCH_ACORN),y) -SUBDIRS += drivers/acorn/block drivers/acorn/char drivers/acorn/net \ - drivers/acorn/scsi -DRIVERS += drivers/acorn/block/acorn-block.a \ - drivers/acorn/char/acorn-char.a \ - drivers/acorn/net/acorn-net.a \ - drivers/acorn/scsi/acorn-scsi.a +ifeq ($(CONFIG_NWFPE),y) +CORE_FILES += arch/arm/nwfpe/math-emu.o endif -ifeq ($(CONFIG_NWFPE),y) -DRIVERS += arch/arm/nwfpe/math-emu.a +ifeq ($(CONFIG_ARCH_ACORN),y) +SUBDIRS += drivers/acorn +DRIVERS += drivers/acorn/block/acorn-block.a +DRIVERS += drivers/acorn/char/acorn-char.a +DRIVERS += drivers/acorn/net/acorn-net.a +DRIVERS += drivers/acorn/scsi/acorn-scsi.a endif MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot @@ -203,14 +182,9 @@ archsymlinks: $(RM) include/asm-arm/arch include/asm-arm/proc (cd include/asm-arm; ln -sf arch-$(ARCHDIR) arch; ln -sf proc-$(PROCESSOR) proc) -# We need to rebuild the linker script -# each time, in case the architecture has -# changed. -.PHONY: arch/arm/vmlinux-$(PROCESSOR).lds - -vmlinux: arch/arm/vmlinux-$(PROCESSOR).lds +vmlinux: arch/arm/vmlinux.lds -arch/arm/vmlinux-$(PROCESSOR).lds: $(TOPDIR)/arch/arm/vmlinux-$(PROCESSOR).lds.in +arch/arm/vmlinux.lds: arch/arm/vmlinux-$(PROCESSOR).lds.in dummy @sed 's/TEXTADDR/$(TEXTADDR)/' <$< >$@ arch/arm/kernel: dummy @@ -225,15 +199,13 @@ arch/arm/lib: dummy zImage zinstall Image install: vmlinux @$(MAKEBOOT) $@ -# Once we've finished integrating the sources, the @$(MAKE) will disappear archmrproper: - rm -f include/asm-arm/arch include/asm-arm/proc @$(MAKE) -C arch/$(ARCH)/special mrproper - rm -f $(TOPDIR)/arch/arm/vmlinux-*.lds + $(RM) include/asm-arm/arch include/asm-arm/proc archclean: @$(MAKEBOOT) clean - $(RM) arch/arm/lib/constants.h + $(RM) arch/arm/lib/constants.h arch/arm/vmlinux.lds archdep: @$(MAKEBOOT) dep @@ -244,6 +216,10 @@ Img:; @$(MAKEBOOT) Image i:; @$(MAKEBOOT) install zi:; @$(MAKEBOOT) zinstall +# +# Configuration targets. Use these to select a +# configuration for your architecture +# a5k_config: $(RM) arch/arm/defconfig cp arch/arm/def-configs/a5k arch/arm/defconfig @@ -260,3 +236,16 @@ rpc_config: $(RM) arch/arm/defconfig cp arch/arm/def-configs/rpc arch/arm/defconfig +brutus_config: + $(RM) arch/arm/defconfig + cp arch/arm/def-configs/brutus arch/arm/defconfig + +victor_config: + $(RM) arch/arm/defconfig + cp arch/arm/def-configs/victor arch/arm/defconfig + +empeg_config: + $(RM) arch/arm/defconfig + cp arch/arm/def-configs/empeg arch/arm/defconfig + + diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index e31e8b288..3c0478ab3 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -2,47 +2,97 @@ # linux/arch/arm/boot/compressed/Makefile # # create a compressed vmlinuz image from the original vmlinux -# -# With this config, max compressed image size = 640k -# Uncompressed image size = 1.3M (text+data) -SYSTEM =$(TOPDIR)/vmlinux -HEAD =$(COMPRESSED_HEAD) -OBJS =$(HEAD) misc.o $(COMPRESSED_EXTRA) -CFLAGS =-O2 -DSTDC_HEADERS $(CFLAGS_PROC) -ARFLAGS =rc -FONTC =$(TOPDIR)/drivers/video/font_acorn_8x8.c +HEAD = head.o +OBJS = misc.o +SYSTEM = $(TOPDIR)/vmlinux +CFLAGS = -O2 -DSTDC_HEADERS $(CFLAGS_PROC) +FONTC = $(TOPDIR)/drivers/video/font_acorn_8x8.c +ZLDFLAGS = -X -T vmlinux.lds +# +# Architecture dependencies +# ifeq ($(CONFIG_ARCH_ACORN),y) -OBJS += ll_char_wr.o font.o +OBJS += ll_char_wr.o font.o +endif + +ifeq ($(CONFIG_CPU_26),y) +ZTEXTADDR = 0x02080000 +endif + +ifeq ($(CONFIG_ARCH_RPC),y) +ZTEXTADDR = 0x10008000 +endif + +ifeq ($(CONFIG_ARCH_EBSA110),y) +ZTEXTADDR = 0x00008000 +endif + +ifeq ($(CONFIG_FOOTBRIDGE),y) +ZTEXTADDR = 0x00008000 +endif + +ifeq ($(CONFIG_ARCH_NETWINDER),y) +OBJS += head-netwinder.o endif -ifeq ($(NEW_LINKER),y) -BINFMT := elf32-littlearm +ifeq ($(CONFIG_ARCH_NEXUSPCI),y) +HEAD = head-nexuspci.o +OBJS += $(TOPDIR)/arch/arm/lib/ll_char_wr_scc.o +ZTEXTADDR = 0x40200000 +ZRELADDR = 0x40008000 +endif + +ifeq ($(CONFIG_ARCH_SA110),y) +ifeq ($(CONFIG_SA1100_VICTOR),y) +HEAD = head-victor.o +ZTEXTADDR = 0x00002000 +ZBSSADDR = 0xc0100000 else -BINFMT := elf32-arm +ZTEXTADDR = 0xc0008000 +endif +ZRELADDR = 0xc0008000 +endif + +# +# If you don't define ZRELADDR above, +# then it defaults to ZTEXTADDR +# +ifeq ($(ZRELADDR),) +ZRELADDR = $(ZTEXTADDR) endif +SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/LOAD_ADDR/$(ZRELADDR)/; + +ifneq ($(ZBSSADDR),) +SEDFLAGS += s/BSS_START/$(ZBSSADDR)/ +else +SEDFLAGS += s/BSS_START/ALIGN(4)/ +endif all: vmlinux -vmlinux: $(OBJS) piggy.o - $(LD) $(ZLINKFLAGS) -o vmlinux $(OBJS) piggy.o +vmlinux: $(HEAD) $(OBJS) piggy.o vmlinux.lds + $(LD) $(ZLDFLAGS) $(HEAD) $(OBJS) piggy.o $(GCCLIB) -o vmlinux $(HEAD): $(HEAD:.o=.S) - $(CC) -traditional -DLOADADDR=$(ZRELADDR) -c $(HEAD:.o=.S) + $(CC) -traditional -c $(HEAD:.o=.S) piggy.o: $(SYSTEM) - tmppiggy=_tmp_$$$$piggy; \ - rm -f $$tmppiggy $$tmppiggy.gz $$tmppiggy.lnk; \ - $(OBJCOPY) $(SYSTEM) $$tmppiggy; \ - gzip -f -9 < $$tmppiggy > $$tmppiggy.gz; \ - echo "SECTIONS { .data : { input_len = .; LONG(input_data_end - input_data) input_data = .; *(.data) input_data_end = .; }}" > $$tmppiggy.lnk; \ - $(LD) -r -o piggy.o -b binary $$tmppiggy.gz -b $(BINFMT) -T $$tmppiggy.lnk; \ - rm -f $$tmppiggy $$tmppiggy.gz $$tmppiggy.lnk; + $(OBJCOPY) $(SYSTEM) piggy + gzip -9 < piggy > piggy.gz + $(LD) -r -o $@ -b binary piggy.gz + rm -f piggy piggy.gz font.o: $(FONTC) $(CC) -Dstatic= -c -o $@ $(FONTC) -clean:; rm -f vmlinux core +vmlinux.lds: vmlinux.lds.in + @sed "$(SEDFLAGS)" < vmlinux.lds.in > $@ + +clean:; rm -f vmlinux core piggy* + +.PHONY: vmlinux.lds clean +misc.o: misc.c $(TOPDIR)/include/asm/arch/uncompress.h $(TOPDIR)/lib/inflate.c diff --git a/arch/arm/boot/compressed/head-netwinder.S b/arch/arm/boot/compressed/head-netwinder.S new file mode 100644 index 000000000..1dcdfcd14 --- /dev/null +++ b/arch/arm/boot/compressed/head-netwinder.S @@ -0,0 +1,30 @@ + .section ".start", #alloc, #execinstr + + adr r2, 1f + ldmdb r2, {r7, r8} + and r3, r2, #0xc000 + teq r3, #0x8000 + beq 2f + bic r3, r2, #0xc000 + orr r3, r3, #0x8000 + mov r0, r3 + mov r4, #64 + sub r5, r8, r7 + b 1f + + .word _start + .word __bss_start + +1: + .rept 4 + ldmia r2!, {r6, r7, r8, r9} + stmia r3!, {r6, r7, r8, r9} + .endr + subs r4, r4, #64 + bcs 1b + movs r4, r5 + mov r5, #0 + movne pc, r0 + + mov r0, #0 +2: diff --git a/arch/arm/boot/compressed/head-victor.S b/arch/arm/boot/compressed/head-victor.S new file mode 100644 index 000000000..e556383ba --- /dev/null +++ b/arch/arm/boot/compressed/head-victor.S @@ -0,0 +1,45 @@ +/* + * linux/arch/arm/boot/compressed/head-victor.S + * + * Copyright (C) 1998 Nicolas Pitre <nico@visuaide.com> + */ + +#include <linux/linkage.h> + + .text + .globl _start +_start: + @ just in case we still use an a.out loader... + nop + nop + nop + nop + nop + nop + nop + nop + + @ load different addresses + adr r2, LC0 + ldmia r2, {r4, r5, r6, sp} + + @ clear BSS + mov r2, #0 +1: str r2, [r5], #4 + cmp r5, r6 + blt 1b + + @ uncompress the kernel + mov r8, r0 @ save cmdline ptr + mov r0, r4 @ where to put uncompressed data + add r1, r6, #31 + bic r1, r1, #31 @ free memory space + add r2, r1, #65536 @ end of free mem space + bl SYMBOL_NAME(decompress_kernel) + mov r0, r8 @ retrieve cmdline ptr + mov pc, r4 @ call via EXEC entry + +LC0: .word _load_addr + .word __bss_start + .word SYMBOL_NAME(_end) + .word SYMBOL_NAME(user_stack)+4096 diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index ab2541f34..721967e4b 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -1,129 +1,232 @@ /* * linux/arch/arm/boot/compressed/head.S * - * Copyright (C) 1996,1997,1998 Russell King + * Copyright (C) 1996-1999 Russell King */ #include <linux/linkage.h> - .text + .section ".start", #alloc, #execinstr /* * sort out different calling conventions */ .align - .globl _start -_start: -start: mov r0, r0 - mov r0, r0 - mov r0, r0 - mov r0, r0 - mov r0, r0 - mov r0, r0 - mov r0, r0 +start: + .type start,#function + .rept 8 mov r0, r0 + .endr + b 1f - .word 0x016f2818 @ Magic numbers to help the loader - .word _start + .word 0x016f2818 @ Magic numbers to help the loader + .word start +1: + + /* + * some architecture specific code can + * be inserted by the linker here + */ + + .text 1: teq r0, #0 - beq 2f - mov r4, #0x02000000 - add r4, r4, #0x7C000 - mov r3, #0x4000 - sub r3, r3, #4 -1: ldmia r0!, {r5 - r12} - stmia r4!, {r5 - r12} - subs r3, r3, #32 - bpl 1b -2: adr r2, LC0 - ldmia r2, {r2, r3, r4, r5, r6, sp} - add r2, r2, #3 - add r3, r3, #3 - add sp, sp, #3 - bic r2, r2, #3 - bic r3, r3, #3 - bic sp, sp, #3 - adr r7, start - sub r6, r7, r6 -/* - * Relocate pointers - */ - add r2, r2, r6 - add r3, r3, r6 - add r5, r5, r6 - add sp, sp, r6 -/* - * Clear zero-init - */ - mov r6, #0 -1: str r6, [r2], #4 + bne 1b + mov r7, r1 @ save architecture ID + mrc p15, 0, r6, c0, c0 @ get processor ID + adr r2, LC0 + ldmia r2, {r2, r3, r4, r5, sp} + + mov r0, #0 +1: str r0, [r2], #4 @ clear bss + str r0, [r2], #4 + str r0, [r2], #4 + str r0, [r2], #4 cmp r2, r3 blt 1b - str r1, [r5] @ save architecture -/* - * Uncompress the kernel - */ - mov r1, #0x8000 - add r3, r2, r1, lsl #1 @ Add 64k for malloc - sub r1, r1, #1 - add r3, r3, r1 - bic r5, r3, r1 @ decompress kernel to after end of the compressed + + mov r1, sp @ malloc space above stack + add r2, sp, #0x10000 @ 64k max + + teq r4, r5 @ will we overwrite ourselves? + moveq r5, r2 + movne r5, r4 + mov r0, r5 - mov r1, r2 - mov r2, r0 + mov r3, r7 bl SYMBOL_NAME(decompress_kernel) - add r0, r0, #7 - bic r2, r0, #7 + + teq r4, r5 @ do we need to relocate + beq call_kernel @ the kernel? + + add r0, r0, #127 + bic r0, r0, #127 @ align the kernel length /* - * Now move the kernel to the correct location (r5 -> r4, len r0) + * r0 = decompressed kernel length + * r1-r3 = unused + * r4 = kernel execution address + * r5 = decompressed kernel start + * r6 = processor ID + * r7 = architecture ID + * r8-r14 = unused */ - mov r0, r4 @ r0 = start of real kernel - mov r1, r5 @ r1 = start of kernel image - add r3, r5, r2 @ r3 = end of kernel - adr r4, movecode - adr r5, movecodeend -1: ldmia r4!, {r6 - r12, lr} - stmia r3!, {r6 - r12, lr} - cmp r4, r5 + add r1, r5, r0 @ end of decompressed kernel + adr r2, reloc_start + adr r3, reloc_end +1: ldmia r2!, {r8 - r13} @ copy relocation code + stmia r1!, {r8 - r13} + ldmia r2!, {r8 - r13} + stmia r1!, {r8 - r13} + cmp r2, r3 blt 1b - mrc p15, 0, r5, c0, c0 - eor r5, r5, #0x44 << 24 - eor r5, r5, #0x01 << 16 - eor r5, r5, #0xa1 << 8 - movs r5, r5, lsr #4 - mov r5, #0 - mcreq p15, 0, r5, c7, c5, 0 @ flush I cache - ldr r5, LC0 + 12 @ get architecture - ldr r5, [r5] - add pc, r1, r2 @ Call move code + + eor r1, r6, #0x44 << 24 @ SA-110? + eor r1, r1, #0x01 << 16 + eor r1, r1, #0xa1 << 8 + movs r1, r1, lsr #4 + mcreq p15, 0, r1, c7, c7, 0 @ flush I & D-cache + mcreq p15, 0, r1, c7, c10, 4 @ drain WB + add pc, r5, r0 @ call relocation code /* - * r0 = length, r1 = to, r2 = from + * r0 = decompressed kernel length + * r1-r3 = unused + * r4 = kernel execution address + * r5 = decompressed kernel start + * r6 = processor ID + * r7 = architecture ID + * r8-r14 = unused */ -movecode: add r3, r1, r2 - mov r4, r0 -1: ldmia r1!, {r6 - r12, lr} - stmia r0!, {r6 - r12, lr} - cmp r1, r3 +reloc_start: add r8, r5, r0 +#if 0 + mov r0, r6 + mov r1, #8 + bl phex + mov r0, #':' + bl putc + mov r0, r5 + mov r1, #8 + bl phex + mov r0, #'-' + bl putc + mov r0, r8 + mov r1, #8 + bl phex + mov r0, #'>' + bl putc + mov r0, r4 + mov r1, #8 + bl phex + mov r0, #'\n' + bl putc +#endif + mov r0, r8 + mov r1, r4 +1: + .rept 4 + ldmia r5!, {r2, r3, r8 - r13} @ relocate kernel + stmia r1!, {r2, r3, r8 - r13} + .endr + + cmp r5, r0 blt 1b - mrc p15, 0, r0, c0, c0 - eor r0, r0, #0x44 << 24 +#if 0 + mov r8, r0 + mov r0, r5 + mov r1, #8 + bl phex + mov r0, #'-' + bl putc + mov r0, r8 + mov r1, #8 + bl phex + mov r0, #'\n' + bl putc + mov r0, r4 + bl memdump +#endif + eor r0, r6, #0x44 << 24 @ SA-110? eor r0, r0, #0x01 << 16 eor r0, r0, #0xa1 << 8 movs r0, r0, lsr #4 + mcreq p15, 0, r0, c7, c7, 0 @ flush I cache + mcreq p15, 0, r1, c7, c10, 4 @ drain WB + +call_kernel: mov r0, #0 + mov r1, r7 @ restore architecture number + mov pc, r4 @ call kernel + +phexbuf: .space 12 + +phex: adr r3, phexbuf + mov r2, #0 + strb r2, [r3, r1] +1: subs r1, r1, #1 + movmi r0, r3 + bmi puts + and r2, r0, #15 + mov r0, r0, lsr #4 + cmp r2, #10 + addge r2, r2, #7 + add r2, r2, #'0' + strb r2, [r3, r1] + b 1b + +puts: mov r3, #0x7c000000 +1: ldrb r2, [r0], #1 + teq r2, #0 + moveq pc, lr +2: strb r2, [r3, #0x3f8] + mov r1, #0x00020000 +3: subs r1, r1, #1 + bne 3b + teq r2, #'\n' + moveq r2, #'\r' + beq 2b + teq r0, #0 + bne 1b + mov pc, lr +putc: + mov r2, r0 mov r0, #0 - mcreq p15, 0, r0, c7, c5, 0 @ flush I cache - mov r1, r5 @ call kernel correctly - mov pc, r4 @ call via EXEC entry -movecodeend: - -LC0: .word SYMBOL_NAME(_edata) - .word SYMBOL_NAME(_end) - .word LOADADDR - .word SYMBOL_NAME(architecture) - .word start - .word SYMBOL_NAME(user_stack)+4096 - .align + mov r3, #0x7c000000 + b 2b - .bss -SYMBOL_NAME(architecture): - .space 4 +memdump: mov r12, r0 + mov r10, lr + mov r1, #8 + bl phex + mov r0, #'\n' + bl putc + mov r11, #0 +2: mov r0, r11, lsl #2 + mov r1, #4 + bl phex + mov r0, #':' + bl putc +1: mov r0, #' ' + bl putc + ldr r0, [r12, r11, lsl #2] + mov r1, #8 + bl phex + and r0, r11, #7 + teq r0, #3 + moveq r0, #' ' + bleq putc + and r0, r11, #7 + add r11, r11, #1 + teq r0, #7 + bne 1b + mov r0, #'\n' + bl putc + cmp r11, #64 + blt 2b + mov pc, r10 +reloc_end: + +LC0: .word __bss_start + .word _end + .word _load_addr + .word _start + .word user_stack+4096 .align + + .section ".stack" +user_stack: .space 4096 diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c index 1d8517104..66b4f2d0e 100644 --- a/arch/arm/boot/compressed/misc.c +++ b/arch/arm/boot/compressed/misc.c @@ -7,8 +7,17 @@ * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 * * Modified for ARM Linux by Russell King + * + * Nicolas Pitre <nico@visuaide.com> 1999/04/14 : + * For this code to run directly from Flash, all constant variables must + * be marked with 'const' and all other variables initialized at run-time + * only. This way all non constant variables will end up in the bss segment, + * which should point to addresses in RAM and cleared to 0 on start. + * This allows for a much quicker boot time. */ +unsigned int __machine_arch_type; + #include <asm/uaccess.h> #include <asm/arch/uncompress.h> #include <asm/proc/uncompress.h> @@ -22,7 +31,7 @@ /* * Optimised C version of memzero for the ARM. */ -extern __inline__ __ptr_t __memzero (__ptr_t s, size_t n) +void __memzero (__ptr_t s, size_t n) { union { void *vp; unsigned long *ulp; unsigned char *ucp; } u; int i; @@ -62,11 +71,8 @@ extern __inline__ __ptr_t __memzero (__ptr_t s, size_t n) if (n & 1) *u.ucp++ = 0; - return s; } -#define memzero(s,n) __memzero(s,n) - extern __inline__ __ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src, size_t __n) { @@ -157,11 +163,11 @@ static void gzip_mark(void **); static void gzip_release(void **); extern char input_data[]; -extern int input_len; +extern char input_data_end[]; static uch *output_data; static ulg output_ptr; -static ulg bytes_out = 0; +static ulg bytes_out; static void *malloc(int size); static void free(void *where); @@ -226,13 +232,14 @@ static void gzip_release(void **ptr) * Fill the input buffer. This is called only when the buffer is empty * and at least one byte is really needed. */ -int fill_inbuf() +int fill_inbuf(void) { if (insize != 0) error("ran out of input data\n"); inbuf = input_data; - insize = input_len; + insize = &input_data_end[0] - &input_data[0]; + inptr = 1; return inbuf[0]; } @@ -241,7 +248,7 @@ int fill_inbuf() * Write the output window window[0..outcnt-1] and update crc and bytes_out. * (Used for the decompressed data only.) */ -void flush_window() +void flush_window(void) { ulg c = crc; unsigned n; @@ -257,6 +264,7 @@ void flush_window() bytes_out += (ulg)outcnt; output_ptr += (ulg)outcnt; outcnt = 0; + puts("."); } static void error(char *x) @@ -270,26 +278,24 @@ static void error(char *x) while(1); /* Halt */ } -#define STACK_SIZE (4096) - -ulg user_stack [STACK_SIZE]; - #ifndef STANDALONE_DEBUG -ulg decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p) +ulg +decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p, + int arch_id) { - free_mem_ptr = free_mem_ptr_p; - free_mem_ptr_end = free_mem_ptr_end_p; - - proc_decomp_setup (); - arch_decomp_setup (); + output_data = (uch *)output_start; /* Points to kernel start */ + free_mem_ptr = free_mem_ptr_p; + free_mem_ptr_end = free_mem_ptr_end_p; + __machine_arch_type = arch_id; - output_data = (uch *)output_start; /* Points to kernel start */ + proc_decomp_setup(); + arch_decomp_setup(); makecrc(); puts("Uncompressing Linux..."); gunzip(); - puts("done.\nNow booting the kernel\n"); + puts(" done, booting the kernel.\n"); return output_ptr; } #else diff --git a/arch/arm/boot/compressed/vmlinux.lds.in b/arch/arm/boot/compressed/vmlinux.lds.in new file mode 100644 index 000000000..f7469c634 --- /dev/null +++ b/arch/arm/boot/compressed/vmlinux.lds.in @@ -0,0 +1,52 @@ +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = LOAD_ADDR; + _load_addr = .; + + . = TEXT_START; + _text = .; + + .text : { + _start = .; + head.o(.start) + *(.start) + head.o(.text) + *(.text) + *(.fixup) + *(.gnu.warning) + input_data = .; + piggy.o + input_data_end = .; + . = ALIGN(4); + } + + _etext = .; + + .data : { + *(.data) + } + + _edata = .; + + . = BSS_START; + __bss_start = .; + .bss : { + *(.bss) + } + _end = .; + + .stack : { + *(.stack) + } + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } +} + diff --git a/arch/arm/config.in b/arch/arm/config.in index 52f69bcd8..4271d12a6 100644 --- a/arch/arm/config.in +++ b/arch/arm/config.in @@ -20,7 +20,7 @@ choice 'ARM system type' \ RiscPC CONFIG_ARCH_RPC \ EBSA-110 CONFIG_ARCH_EBSA110 \ FootBridge-based CONFIG_FOOTBRIDGE" RiscPC - +# SA1100-based CONFIG_ARCH_SA1100 if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then bool 'FootBridge in HOST mode' CONFIG_HOST_FOOTBRIDGE if [ "$CONFIG_HOST_FOOTBRIDGE" = "y" ]; then @@ -31,9 +31,9 @@ if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then fi if [ "$CONFIG_HOST_FOOTBRIDGE" = "y" ]; then - bool ' Include support for Intel EBSA285' CONFIG_ARCH_EBSA285 - bool ' Include support for Chalice CATS boards' CONFIG_CATS - bool ' Include support for Corel NetWinder' CONFIG_ARCH_NETWINDER + bool ' Include support for EBSA285' CONFIG_ARCH_EBSA285 + bool ' Include support for CATS' CONFIG_CATS + bool ' Include support for NetWinder' CONFIG_ARCH_NETWINDER fi if [ "$CONFIG_ADDIN_FOOTBRIDGE" = "y" ]; then @@ -42,6 +42,18 @@ if [ "$CONFIG_ADDIN_FOOTBRIDGE" = "y" ]; then define_bool CONFIG_ARCH_CO285 y fi +if [ "$CONFIG_ARCH_SA1100" = "y" ]; then + define_bool CONFIG_CPU_SA1100 y + choice 'SA1100 implementation' \ + "Brutus CONFIG_SA1100_BRUTUS \ + empeg CONFIG_SA1100_EMPEG \ + Itsy CONFIG_SA1100_ITSY \ + LART CONFIG_SA1100_LART \ + PLEB CONFIG_SA1100_PLEB \ + Victor CONFIG_SA1100_VICTOR \ + Tifon CONFIG_SA1100_TIFON" Brutus +fi + # # Select various configuration options depending on the machine type # Easy check for Acorn-style architectures @@ -76,6 +88,7 @@ else # Select CPU and optimisation dependent on architecture # if [ "$CONFIG_ARCH_EBSA110" = "y" -o \ + "$CONFIG_ARCH_SA1100" = "y" -o \ "$CONFIG_FOOTBRIDGE" = "y" -o \ "$CONFIG_ARCH_NEXUSPCI" = "y" ]; then define_bool CONFIG_CPU_32v4 y @@ -139,21 +152,10 @@ if [ "$CONFIG_CPU_32" = "y" ]; then tristate 'RISC OS personality' CONFIG_ARTHUR fi -tristate 'Parallel port support' CONFIG_PARPORT -if [ "$CONFIG_PARPORT" != "n" ]; then - if [ "$CONFIG_ARCH_ARC" = "y" ]; then - dep_tristate ' Archimedes hardware' CONFIG_PARPORT_ARC $CONFIG_PARPORT - fi - dep_tristate ' PC-style hardware' CONFIG_PARPORT_PC $CONFIG_PARPORT - # If exactly one hardware type is selected then parport will optimise away - # support for loading any others. Defeat this if the user is keen. - if [ "$CONFIG_PARPORT_PC" = "n" -o "$CONFIG_PARPORT_ARC" = "n" ]; then - if [ "$CONFIG_PARPORT_PC" != "n" -o "$CONFIG_PARPORT_ARC" != "n" ]; then - bool ' Support foreign hardware' CONFIG_PARPORT_OTHER - fi - fi -fi +source drivers/parport/Config.in + if [ "$CONFIG_ARCH_EBSA110" = "y" -o \ + "$CONFIG_ARCH_SA1100" = "y" -o \ "$CONFIG_ARCH_NETWINDER" = "y" -o \ "$CONFIG_CATS" = "y" ]; then string 'Initial kernel command string' CONFIG_CMDLINE @@ -165,10 +167,10 @@ if [ "$CONFIG_ARCH_NETWINDER" = "y" -o \ bool 'Timer and CPU usage LEDs' CONFIG_LEDS if [ "$CONFIG_LEDS" = "y" ]; then if [ "$CONFIG_ARCH_NETWINDER" = "y" -o \ - "$CONFIG_ARCH_EBSA285" = "y" -o \ + "$CONFIG_ARCH_EBSA285" = "y" -o \ "$CONFIG_ARCH_CO285" = "y" ]; then - bool ' Timer LED' CONFIG_LEDS_TIMER - bool ' CPU usage LED' CONFIG_LEDS_CPU + bool ' Timer LED' CONFIG_LEDS_TIMER + bool ' CPU usage LED' CONFIG_LEDS_CPU fi fi fi @@ -186,11 +188,11 @@ fi source drivers/char/Config.in if [ "$CONFIG_ARCH_ACORN" = "y" ]; then - if [ "$CONFIG_MOUSE" = "y" ]; then + if [ "$CONFIG_BUSMOUSE" = "y" ]; then if [ "$CONFIG_ARCH_RPC" != "y" ]; then - define_bool CONFIG_KBDMOUSE y + define_bool CONFIG_KBDMOUSE y else - define_bool CONFIG_RPCMOUSE y + define_bool CONFIG_RPCMOUSE y fi fi fi @@ -230,7 +232,7 @@ fi # # tristate 'ISDN support' CONFIG_ISDN # if [ "$CONFIG_ISDN" != "n" ]; then -# source drivers/isdn/Config.in +# source drivers/isdn/Config.in # fi # endmenu @@ -267,17 +269,17 @@ bool 'Include debugging information in kernel binary' CONFIG_DEBUG_INFO #bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - if [ "$CONFIG_CPU_26" = "y" ]; then - bool 'Disable pgtable cache (EXPERIMENTAL)' CONFIG_NO_PGT_CACHE - fi - - # These options are only for real kernel hackers - # who want to get their hands dirty. - bool 'Kernel low-level debugging functions' CONFIG_DEBUG_LL - if [ "$CONFIG_DEBUG_LL" = "y" ]; then - if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then - bool 'Kernel low-level debugging messages via DC21285 port' CONFIG_DEBUG_DC21285_PORT - fi - fi + if [ "$CONFIG_CPU_26" = "y" ]; then + bool 'Disable pgtable cache (EXPERIMENTAL)' CONFIG_NO_PGT_CACHE + fi + + # These options are only for real kernel hackers + # who want to get their hands dirty. + bool 'Kernel low-level debugging functions' CONFIG_DEBUG_LL + if [ "$CONFIG_DEBUG_LL" = "y" ]; then + if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then + bool 'Kernel low-level debugging messages via DC21285 port' CONFIG_DEBUG_DC21285_PORT + fi + fi fi endmenu diff --git a/arch/arm/def-configs/brutus b/arch/arm/def-configs/brutus new file mode 100644 index 000000000..a700f7d17 --- /dev/null +++ b/arch/arm/def-configs/brutus @@ -0,0 +1,221 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_ARM=y + +# +# System and processor type +# +# CONFIG_ARCH_ARC is not set +# CONFIG_ARCH_A5K is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_FOOTBRIDGE is not set +CONFIG_ARCH_SA1100=y +CONFIG_CPU_SA1100=y +CONFIG_SA1100_BRUTUS=y +# CONFIG_SA1100_EMPEG is not set +# CONFIG_SA1100_ITSY is not set +# CONFIG_SA1100_LART is not set +# CONFIG_SA1100_PLEB is not set +# CONFIG_SA1100_VICTOR is not set +# CONFIG_SA1100_TIFON is not set +# CONFIG_ARCH_ACORN is not set +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set +CONFIG_CPU_32v4=y +CONFIG_CPU_SA110=y +# CONFIG_ISA_DMA is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +# CONFIG_ALIGNMENT_TRAP is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +# CONFIG_KMOD is not set + +# +# General setup +# +# CONFIG_NET is not set +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_SYSCTL is not set +CONFIG_NWFPE=y +CONFIG_BINFMT_AOUT=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set +# CONFIG_PARPORT is not set +CONFIG_CMDLINE="" + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_PCI is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# Plug and Play configuration +# +# CONFIG_PNP is not set +# CONFIG_ISAPNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_IDE is not set + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD_ONLY is not set +# CONFIG_BLK_CPQ_DA is not set + +# +# Additional Block Devices +# +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_MD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_INITRD=y +# CONFIG_BLK_DEV_XD is not set +CONFIG_PARIDE_PARPORT=y +# CONFIG_PARIDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_SERIAL_SA1100=y +# CONFIG_SERIAL_SA1100_CONSOLE is not set +# CONFIG_SERIAL is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=32 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set +# CONFIG_QIC02_TAPE is not set +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set + +# +# Video For Linux +# +# CONFIG_VIDEO_DEV is not set + +# +# Joystick support +# +# CONFIG_JOYSTICK is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_DRM is not set + +# +# USB drivers - not for the faint of heart +# +# CONFIG_USB is not set + +# +# Console drivers +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_FB=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_FB_SA1100=y +# CONFIG_FB_MATROX is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FBCON_ADVANCED is not set +CONFIG_FBCON_CFB2=y +CONFIG_FBCON_CFB4=y +CONFIG_FBCON_CFB8=y +CONFIG_FBCON_CFB16=y +CONFIG_FBCON_FONTWIDTH8_ONLY=y +CONFIG_FBCON_FONTS=y +CONFIG_FONT_8x8=y +# CONFIG_FONT_8x16 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# Filesystems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_UDF_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +CONFIG_DEVPTS_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_INFO=y +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_LL is not set diff --git a/arch/arm/def-configs/empeg b/arch/arm/def-configs/empeg new file mode 100644 index 000000000..cd3792b53 --- /dev/null +++ b/arch/arm/def-configs/empeg @@ -0,0 +1,264 @@ +# +# Example empeg-car kernel configuration file. +# +CONFIG_ARM=y + +# +# System and processor type +# +# CONFIG_ARCH_ARC is not set +# CONFIG_ARCH_A5K is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_FOOTBRIDGE is not set +CONFIG_ARCH_SA1100=y +CONFIG_CPU_SA1100=y +# CONFIG_SA1100_BRUTUS is not set +CONFIG_SA1100_EMPEG=y +# CONFIG_SA1100_ITSY is not set +# CONFIG_SA1100_PLEB is not set +# CONFIG_SA1100_VICTOR is not set +# CONFIG_EMPEG_HENRY is not set +# CONFIG_ARCH_ACORN is not set +# CONFIG_ISA_DMA is not set +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set +# CONFIG_CPU_ARM2 is not set +# CONFIG_CPU_ARM3 is not set +# CONFIG_CPU_ARM6 is not set +# CONFIG_CPU_ARM7 is not set +CONFIG_CPU_SA110=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +# CONFIG_ALIGNMENT_TRAP is not set +# CONFIG_TEXT_SECTIONS is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODVERSIONS=y +# CONFIG_KMOD is not set + +# +# General setup +# +CONFIG_NET=y +# CONFIG_SYSVIPC is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_SYSCTL is not set +CONFIG_NWFPE=y +CONFIG_BINFMT_AOUT=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set +# CONFIG_PARPORT is not set +CONFIG_CMDLINE="" + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +CONFIG_BLK_DEV_IDE=y +# CONFIG_BLK_DEV_HD_IDE is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_IDE_CHIPSETS is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_MD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_INITRD=y +# CONFIG_BLK_DEV_XD is not set +CONFIG_PARIDE_PARPORT=y +# CONFIG_PARIDE is not set +# CONFIG_BLK_DEV_HD is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_SERIAL_SA1100=y +CONFIG_SERIAL_SA1100_CONSOLE=y +# CONFIG_SERIAL is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_UNIX98_PTYS is not set +# CONFIG_MOUSE is not set +# CONFIG_QIC02_TAPE is not set +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +CONFIG_EMPEG_IR=y +CONFIG_EMPEG_USB=y + +# +# Video For Linux +# +CONFIG_VIDEO_DEV=y +# CONFIG_RADIO_RTRACK is not set +# CONFIG_RADIO_RTRACK2 is not set +# CONFIG_RADIO_AZTECH is not set +# CONFIG_RADIO_CADET is not set +# CONFIG_RADIO_MIROPCM20 is not set +# CONFIG_RADIO_GEMTEK is not set +CONFIG_RADIO_EMPEG=y +# CONFIG_VIDEO_BT848 is not set +# CONFIG_VIDEO_PMS is not set +# CONFIG_VIDEO_SAA5249 is not set +# CONFIG_RADIO_SF16FMI is not set +# CONFIG_RADIO_TYPHOON is not set +# CONFIG_RADIO_ZOLTRIX is not set + +# +# Joystick support +# +# CONFIG_JOYSTICK is not set +# CONFIG_DTLK is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set + +# +# Networking options +# +# CONFIG_PACKET is not set +# CONFIG_NETLINK is not set +# CONFIG_FIREWALL is not set +# CONFIG_FILTER is not set +# CONFIG_UNIX is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_IP_ROUTER is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_ALIAS is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_RARP is not set +# CONFIG_SKB_LARGE is not set +# CONFIG_IPV6 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_BRIDGE is not set +# CONFIG_LLC is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set +# CONFIG_CPU_IS_SLOW is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA subsystem support +# +# CONFIG_IRDA is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +# CONFIG_NET_ETHERNET is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_DLCI is not set +CONFIG_PPP=y +# CONFIG_SLIP is not set +# CONFIG_NET_RADIO is not set +# CONFIG_TR is not set +# CONFIG_SHAPER is not set +# CONFIG_HOSTESS_SV11 is not set +# CONFIG_COSA is not set +# CONFIG_RCPCI is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# Filesystems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_MINIX_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_SUNRPC is not set +# CONFIG_LOCKD is not set +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set + +# +# Partition Types +# +# CONFIG_OSF_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_SGI_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ACORN_PARTITION is not set +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_USER_BACKTRACE=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_LL is not set diff --git a/arch/arm/def-configs/footbridge b/arch/arm/def-configs/footbridge index ce85d6ffc..a3acd8954 100644 --- a/arch/arm/def-configs/footbridge +++ b/arch/arm/def-configs/footbridge @@ -17,22 +17,18 @@ CONFIG_ARCH_EBSA285=y # CONFIG_CATS is not set CONFIG_ARCH_NETWINDER=y # CONFIG_ARCH_ACORN is not set -CONFIG_PCI=y -CONFIG_ISA_DMA=y CONFIG_CPU_32=y # CONFIG_CPU_26 is not set -# CONFIG_CPU_ARM2 is not set -# CONFIG_CPU_ARM3 is not set -# CONFIG_CPU_ARM6 is not set -# CONFIG_CPU_ARM7 is not set +CONFIG_CPU_32v4=y CONFIG_CPU_SA110=y +CONFIG_PCI=y +CONFIG_ISA_DMA=y # # Code maturity level options # CONFIG_EXPERIMENTAL=y # CONFIG_ALIGNMENT_TRAP is not set -# CONFIG_TEXT_SECTIONS is not set # # Loadable module support @@ -55,15 +51,35 @@ CONFIG_BINFMT_ELF=y # CONFIG_ARTHUR is not set CONFIG_PARPORT=y CONFIG_PARPORT_PC=y +CONFIG_PARPORT_PC_FIFO=y +# CONFIG_PARPORT_PC_PCMCIA is not set +# CONFIG_PARPORT_ARC is not set +# CONFIG_PARPORT_AMIGA is not set +# CONFIG_PARPORT_MFC3 is not set +# CONFIG_PARPORT_ATARI is not set +# CONFIG_PARPORT_SUNBPP is not set +# CONFIG_PARPORT_OTHER is not set +CONFIG_PARPORT_1284=y CONFIG_CMDLINE="root=/dev/hda2 ro mem=32M parport=0x378,7 ide0=autotune" CONFIG_LEDS=y CONFIG_LEDS_TIMER=y # CONFIG_LEDS_CPU is not set # -# Plug and Play support +# I2O device support # -# CONFIG_PNP is not set +# CONFIG_I2O is not set +# CONFIG_I2O_PCI is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# Plug and Play configuration +# +CONFIG_PNP=y +CONFIG_ISAPNP=y # # Block devices @@ -76,6 +92,7 @@ CONFIG_BLK_DEV_IDE=y # # CONFIG_BLK_DEV_HD_IDE is not set CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y # CONFIG_BLK_DEV_IDECD is not set # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set @@ -89,7 +106,7 @@ CONFIG_IDEDMA_AUTO=y # CONFIG_BLK_DEV_OPTI621 is not set # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_VIA82C586 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set # CONFIG_BLK_DEV_CMD646 is not set CONFIG_BLK_DEV_SL82C105=y # CONFIG_IDE_CHIPSETS is not set @@ -136,6 +153,7 @@ CONFIG_PARIDE_KBIC=m CONFIG_PARIDE_KTTI=m CONFIG_PARIDE_ON20=m CONFIG_PARIDE_ON26=m +CONFIG_BLK_DEV_IDE_MODES=y # CONFIG_BLK_DEV_HD is not set # @@ -149,15 +167,14 @@ CONFIG_SERIAL_CONSOLE=y # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_UNIX98_PTYS is not set CONFIG_PRINTER=m -CONFIG_PRINTER_READBACK=y -CONFIG_MOUSE=y +# CONFIG_LP_CONSOLE is not set +# CONFIG_PPDEV is not set # # Mice # -# CONFIG_ATIXL_BUSMOUSE is not set # CONFIG_BUSMOUSE is not set -# CONFIG_MS_BUSMOUSE is not set +CONFIG_MOUSE=y CONFIG_PSMOUSE=y # CONFIG_82C710_MOUSE is not set # CONFIG_PC110_PAD is not set @@ -172,6 +189,8 @@ CONFIG_WATCHDOG=y CONFIG_SOFT_WATCHDOG=y # CONFIG_PCWATCHDOG is not set # CONFIG_ACQUIRE_WDT is not set +# CONFIG_21285_WATCHDOG is not set +CONFIG_977_WATCHDOG=m CONFIG_DS1620=y CONFIG_NWBUTTON=y CONFIG_NWBUTTON_REBOOT=y @@ -189,6 +208,8 @@ CONFIG_RTC=y # # CONFIG_JOYSTICK is not set # CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set # # Ftape, the floppy tape device driver @@ -196,11 +217,35 @@ CONFIG_RTC=y # CONFIG_FTAPE is not set # +# USB drivers - not for the faint of heart +# +CONFIG_USB=m +# CONFIG_USB_UHCI is not set +CONFIG_USB_OHCI=m +CONFIG_USB_OHCI_DEBUG=y +CONFIG_USB_OHCI_HCD=m +CONFIG_USB_OHCI_VROOTHUB=y +# CONFIG_USB_DEBUG_ISOC is not set +CONFIG_USB_HUB=m +CONFIG_USB_MOUSE=m +CONFIG_USB_KBD=m +CONFIG_USB_AUDIO=m +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m +# CONFIG_USB_CPIA is not set +CONFIG_USB_SCSI=m +CONFIG_USB_SCSI_DEBUG=m +# CONFIG_USB_EZUSB is not set +# CONFIG_USB_USS720 is not set +CONFIG_USB_PROC=y + +# # Console drivers # CONFIG_VGA_CONSOLE=y CONFIG_FB=y CONFIG_DUMMY_CONSOLE=y +# CONFIG_FB_CLGEN is not set # CONFIG_FB_PM2 is not set CONFIG_FB_CYBER2000=y # CONFIG_FB_MATROX is not set @@ -220,6 +265,7 @@ CONFIG_FBCON_CFB24=y # CONFIG_FBCON_IPLAN2P4 is not set # CONFIG_FBCON_IPLAN2P8 is not set # CONFIG_FBCON_MAC is not set +# CONFIG_FBCON_VGA_PLANES is not set CONFIG_FBCON_VGA=y # CONFIG_FBCON_FONTWIDTH8_ONLY is not set CONFIG_FBCON_FONTS=y @@ -235,8 +281,9 @@ CONFIG_FONT_ACORN_8x8=y # Networking options # CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set # CONFIG_NETLINK is not set -# CONFIG_FIREWALL is not set +# CONFIG_NETFILTER is not set # CONFIG_FILTER is not set CONFIG_UNIX=y CONFIG_INET=y @@ -254,15 +301,17 @@ CONFIG_IP_ALIAS=y # # (it is safe to leave these untouched) # -# CONFIG_INET_RARP is not set CONFIG_SKB_LARGE=y # CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set # # # # CONFIG_IPX is not set # CONFIG_ATALK is not set +# CONFIG_DECNET is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set # CONFIG_BRIDGE is not set @@ -271,7 +320,6 @@ CONFIG_SKB_LARGE=y # CONFIG_WAN_ROUTER is not set # CONFIG_NET_FASTROUTE is not set # CONFIG_NET_HW_FLOWCONTROL is not set -# CONFIG_CPU_IS_SLOW is not set # # QoS and/or fair queueing @@ -284,7 +332,7 @@ CONFIG_SKB_LARGE=y # CONFIG_HAMRADIO is not set # -# IrDA subsystem support +# IrDA (infrared) support # # CONFIG_IRDA is not set @@ -292,9 +340,18 @@ CONFIG_SKB_LARGE=y # Network device support # CONFIG_NETDEVICES=y + +# +# ARCnet devices +# # CONFIG_ARCNET is not set # CONFIG_DUMMY is not set # CONFIG_EQUALIZER is not set +# CONFIG_NET_SB1000 is not set + +# +# Ethernet (10 or 100Mbit) +# CONFIG_NET_ETHERNET=y # CONFIG_ARM_AM79C961A is not set CONFIG_NET_VENDOR_3COM=y @@ -309,11 +366,12 @@ CONFIG_VORTEX=y # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set # CONFIG_RTL8139 is not set +# CONFIG_SIS900 is not set # CONFIG_YELLOWFIN is not set -# CONFIG_ACENIC is not set # CONFIG_NET_ISA is not set CONFIG_NET_EISA=y # CONFIG_PCNET32 is not set +# CONFIG_ACENIC is not set # CONFIG_AC3200 is not set # CONFIG_APRICOT is not set # CONFIG_CS89x0 is not set @@ -332,23 +390,32 @@ CONFIG_NE2K_PCI=y # CONFIG_NET_POCKET is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set -# CONFIG_DLCI is not set # CONFIG_PLIP is not set CONFIG_PPP=m - -# -# CCP compressors for PPP are only built as modules. -# +CONFIG_PPP_ASYNC=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m CONFIG_SLIP=m CONFIG_SLIP_COMPRESSED=y CONFIG_SLIP_SMART=y CONFIG_SLIP_MODE_SLIP6=y # CONFIG_NET_RADIO is not set + +# +# Token ring devices +# # CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set # CONFIG_SHAPER is not set + +# +# Wan interfaces +# # CONFIG_HOSTESS_SV11 is not set # CONFIG_COSA is not set -# CONFIG_RCPCI is not set +# CONFIG_SEALEVEL_4021 is not set +# CONFIG_DLCI is not set # # SCSI support @@ -359,8 +426,10 @@ CONFIG_SLIP_MODE_SLIP6=y # Sound # CONFIG_SOUND=m +# CONFIG_SOUND_CMPCI is not set # CONFIG_SOUND_ES1370 is not set # CONFIG_SOUND_ES1371 is not set +# CONFIG_SOUND_ESSSOLO1 is not set # CONFIG_SOUND_SONICVIBES is not set # CONFIG_SOUND_MSNDCLAS is not set # CONFIG_SOUND_MSNDPIN is not set @@ -410,6 +479,7 @@ CONFIG_FAT_FS=m CONFIG_MSDOS_FS=m # CONFIG_UMSDOS_FS is not set CONFIG_VFAT_FS=m +# CONFIG_EFS_FS is not set CONFIG_ISO9660_FS=m CONFIG_JOLIET=y # CONFIG_MINIX_FS is not set @@ -438,12 +508,17 @@ CONFIG_LOCKD=y # # Partition Types # +CONFIG_PARTITION_ADVANCED=y # CONFIG_OSF_PARTITION is not set # CONFIG_MAC_PARTITION is not set CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set # CONFIG_SGI_PARTITION is not set # CONFIG_SUN_PARTITION is not set # CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set CONFIG_ACORN_PARTITION=y CONFIG_ACORN_PARTITION_ADFS=y # CONFIG_ACORN_PARTITION_ICS is not set @@ -479,6 +554,7 @@ CONFIG_NLS_ISO8859_2=m # CONFIG_NLS_ISO8859_7 is not set # CONFIG_NLS_ISO8859_8 is not set # CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_14 is not set CONFIG_NLS_ISO8859_15=m # CONFIG_NLS_KOI8_R is not set @@ -487,7 +563,7 @@ CONFIG_NLS_ISO8859_15=m # CONFIG_FRAME_POINTER=y CONFIG_DEBUG_ERRORS=y -# CONFIG_DEBUG_USER is not set +CONFIG_DEBUG_USER=y # CONFIG_DEBUG_INFO is not set CONFIG_MAGIC_SYSRQ=y # CONFIG_DEBUG_LL is not set diff --git a/arch/arm/def-configs/victor b/arch/arm/def-configs/victor new file mode 100644 index 000000000..569cc458d --- /dev/null +++ b/arch/arm/def-configs/victor @@ -0,0 +1,207 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_ARM=y + +# +# System and processor type +# +# CONFIG_ARCH_ARC is not set +# CONFIG_ARCH_A5K is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_FOOTBRIDGE is not set +CONFIG_ARCH_SA1100=y +CONFIG_CPU_SA1100=y +# CONFIG_SA1100_BRUTUS is not set +# CONFIG_SA1100_EMPEG is not set +# CONFIG_SA1100_ITSY is not set +# CONFIG_SA1100_PLEB is not set +CONFIG_SA1100_VICTOR=y +# CONFIG_VICTOR_BOARD1 is not set +# CONFIG_ARCH_ACORN is not set +# CONFIG_ISA_DMA is not set +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set +# CONFIG_CPU_ARM2 is not set +# CONFIG_CPU_ARM3 is not set +# CONFIG_CPU_ARM6 is not set +# CONFIG_CPU_ARM7 is not set +CONFIG_CPU_SA110=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +# CONFIG_ALIGNMENT_TRAP is not set +# CONFIG_TEXT_SECTIONS is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +# CONFIG_KMOD is not set + +# +# General setup +# +# CONFIG_NET is not set +# CONFIG_SYSVIPC is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_SYSCTL is not set +CONFIG_NWFPE=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set +# CONFIG_PARPORT is not set +CONFIG_CMDLINE="" + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD_IDE is not set +# CONFIG_BLK_DEV_IDEDISK is not set +CONFIG_BLK_DEV_IDECD=y +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_IDE_CHIPSETS is not set + +# +# Additional Block Devices +# +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_XD is not set +CONFIG_PARIDE_PARPORT=y +# CONFIG_PARIDE is not set +# CONFIG_BLK_DEV_HD is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_SERIAL_SA1100=y +CONFIG_SERIAL_SA1100_CONSOLE=y +# CONFIG_SERIAL is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_UNIX98_PTYS is not set +# CONFIG_MOUSE is not set +# CONFIG_QIC02_TAPE is not set +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set + +# +# Video For Linux +# +# CONFIG_VIDEO_DEV is not set + +# +# Joystick support +# +# CONFIG_JOYSTICK is not set +# CONFIG_DTLK is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# Filesystems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +# CONFIG_MINIX_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_PROC_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Partition Types +# +# CONFIG_OSF_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +# CONFIG_MSDOS_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ACORN_PARTITION is not set +CONFIG_NLS=y + +# +# Native Language Support +# +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +CONFIG_NLS_CODEPAGE_850=y +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set + +# +# Kernel hacking +# +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_LL is not set diff --git a/arch/arm/defconfig b/arch/arm/defconfig index 4f1ec7e28..d289870ea 100644 --- a/arch/arm/defconfig +++ b/arch/arm/defconfig @@ -55,7 +55,7 @@ CONFIG_BINFMT_ELF=y # CONFIG_ARTHUR is not set CONFIG_PARPORT=y CONFIG_PARPORT_PC=y -CONFIG_CMDLINE="root=/dev/hda2 ro mem=32M parport=0x378,7 ide0=autotune" +CONFIG_CMDLINE="root=/dev/hda1 ro mem=32M parport=0x378,7 ide0=autotune" CONFIG_LEDS=y CONFIG_LEDS_TIMER=y # CONFIG_LEDS_CPU is not set @@ -89,7 +89,7 @@ CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_BLK_DEV_OPTI621 is not set # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_VIA82C586 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set # CONFIG_BLK_DEV_CMD646 is not set CONFIG_BLK_DEV_SL82C105=y # CONFIG_IDE_CHIPSETS is not set diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 557aa6fc5..31ca81ddc 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -22,6 +22,7 @@ O_OBJS_rpc = dma-rpc.o iic.o fiq.o O_OBJS_ebsa110 = dma-dummy.o O_OBJS_footbridge = dma-footbridge.o $(ISA_DMA_OBJS) isa.o O_OBJS_nexuspci = dma-dummy.o +O_OBJS_sa1100 = dma-dummy.o fiq.o OX_OBJS_arc = dma.o OX_OBJS_a5k = dma.o @@ -29,11 +30,16 @@ OX_OBJS_rpc = dma.o OX_OBJS_ebsa110 = OX_OBJS_footbridge= dma.o hw-footbridge.o OX_OBJS_nexuspci = +OX_OBJS_sa1100 = all: kernel.o $(HEAD_OBJ) init_task.o O_OBJS += $(O_OBJS_$(MACHINE)) +ifeq ($(CONFIG_DEBUG_LL),y) + O_OBJS += debug-$(PROCESSOR).o +endif + ifeq ($(CONFIG_MODULES),y) OX_OBJS = armksyms.o endif @@ -42,17 +48,15 @@ ifeq ($(CONFIG_ARCH_ACORN),y) OX_OBJS += ecard.o endif -ifeq ($(MACHINE),nexuspci) - ifdef CONFIG_PCI +ifeq ($(CONFIG_PCI),y) + ifeq ($(MACHINE),nexuspci) O_OBJS += plx9080.o - endif -else - ifdef CONFIG_PCI + else O_OBJS += bios32.o dec21285.o endif endif -ifdef CONFIG_LEDS +ifeq ($(CONFIG_LEDS),y) OX_OBJS += leds-$(MACHINE).o endif @@ -73,13 +77,11 @@ endif $(HEAD_OBJ): $(HEAD_OBJ:.o=.S) $(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 $@ - include $(TOPDIR)/Rules.make -$(ENTRY_OBJ): ../lib/constants.h +.S.o: + $(CC) -D__ASSEMBLY__ $(AFLAGS) $(AFLAGS_$@) -c -o $*.o $< # Spell out some dependencies that `make dep' doesn't spot -entry-armv.o: calls.S -entry-armo.o: calls.S +entry-armv.o: calls.S ../lib/constants.h +entry-armo.o: calls.S ../lib/constants.h diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index 0905d55b5..ebb2f150d 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -2,12 +2,14 @@ #include <linux/module.h> #include <linux/user.h> #include <linux/string.h> +#include <linux/fs.h> #include <linux/mm.h> #include <linux/mman.h> #include <linux/pci.h> #include <linux/delay.h> #include <linux/in6.h> +#include <asm/byteorder.h> #include <asm/elf.h> #include <asm/io.h> #include <asm/dma.h> @@ -93,6 +95,9 @@ EXPORT_SYMBOL(__ioremap); EXPORT_SYMBOL(__iounmap); #endif EXPORT_SYMBOL(kernel_thread); +EXPORT_SYMBOL(system_rev); +EXPORT_SYMBOL(system_serial_low); +EXPORT_SYMBOL(system_serial_high); EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); @@ -108,7 +113,7 @@ EXPORT_SYMBOL(cpu_clean_cache_area); EXPORT_SYMBOL(cpu_flush_ram_page); EXPORT_SYMBOL(cpu_flush_tlb_all); EXPORT_SYMBOL(cpu_flush_tlb_area); -EXPORT_SYMBOL(cpu_switch_mm); +EXPORT_SYMBOL(cpu_set_pgd); EXPORT_SYMBOL(cpu_set_pmd); EXPORT_SYMBOL(cpu_set_pte); EXPORT_SYMBOL(cpu_flush_icache_area); @@ -165,19 +170,20 @@ EXPORT_SYMBOL_NOVERS(strpbrk); EXPORT_SYMBOL_NOVERS(strtok); EXPORT_SYMBOL_NOVERS(strrchr); EXPORT_SYMBOL_NOVERS(strstr); -EXPORT_SYMBOL_NOVERS(memset); +EXPORT_SYMBOL_NOVERS(__memset); +EXPORT_SYMBOL_NOVERS(memset); /* needed for some versions of gcc */ EXPORT_SYMBOL_NOVERS(memcpy); EXPORT_SYMBOL_NOVERS(memmove); EXPORT_SYMBOL_NOVERS(memcmp); EXPORT_SYMBOL_NOVERS(memscan); -EXPORT_SYMBOL_NOVERS(memzero); +EXPORT_SYMBOL_NOVERS(__memzero); /* user mem (segment) */ #if defined(CONFIG_CPU_32) EXPORT_SYMBOL(__arch_copy_from_user); EXPORT_SYMBOL(__arch_copy_to_user); EXPORT_SYMBOL(__arch_clear_user); -EXPORT_SYMBOL(__arch_strlen_user); +EXPORT_SYMBOL(__arch_strnlen_user); #elif defined(CONFIG_CPU_26) EXPORT_SYMBOL(uaccess_kernel); EXPORT_SYMBOL(uaccess_user); diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index 35bb0a36a..3bd7a7358 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -7,6 +7,7 @@ */ #include <linux/kernel.h> #include <linux/pci.h> +#include <linux/errno.h> #include <linux/init.h> #include <asm/irq.h> @@ -73,6 +74,38 @@ struct pci_fixup pcibios_fixups[] = { }; /* + * Assign new address to PCI resource. We hope our resource information + * is complete. On the PC, we don't re-assign resources unless we are + * forced to do so. + * + * Expects start=0, end=size-1, flags=resource type. + */ + +int __init pcibios_assign_resource(struct pci_dev *dev, int i) +{ + struct resource *r = &dev->resource[i]; + struct resource *pr = pci_find_parent_resource(dev, r); + unsigned long size = r->end + 1; + unsigned long flags = 0; + + if (!pr) + return -EINVAL; + if (r->flags & IORESOURCE_IO) { + if (size > 0x100) + return -EFBIG; + if (allocate_resource(pr, r, size, 0x9000, ~0, 1024)) + return -EBUSY; + flags = PCI_BASE_ADDRESS_SPACE_IO; + } else { + if (allocate_resource(pr, r, size, 0x00100000, 0x7fffffff, size)) + return -EBUSY; + } + if (i < 6) + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4*i, r->start | flags); + return 0; +} + +/* * Assign an address to an I/O range. */ static void __init pcibios_fixup_io_addr(struct pci_dev *dev, struct resource *r, int idx) diff --git a/arch/arm/kernel/debug-armo.S b/arch/arm/kernel/debug-armo.S new file mode 100644 index 000000000..1c6aaccc3 --- /dev/null +++ b/arch/arm/kernel/debug-armo.S @@ -0,0 +1,86 @@ +/* + * linux/arch/arm/kernel/debug-armo.S + * + * Copyright (C) 1999 Russell King + * + * 26-bit debugging code + */ +#include <linux/linkage.h> + + .macro addruart,rx + mov \rx, #0x03000000 + orr \rx, \rx, #0x00010000 + orr \rx, \rx, #0x00000fe0 + .endm + + .macro senduart,rd,rx + strb \rd, [\rx] + .endm + + .macro busyuart,rd,rx +1002: ldrb \rd, [\rx, #0x14] + and \rd, \rd, #0x60 + teq \rd, #0x60 + bne 1002b + .endm + + .macro waituart,rd,rx +1001: ldrb \rd, [\rx, #0x18] + tst \rd, #0x10 + beq 1001b + .endm + + .text +/* + * Useful debugging routines + */ +ENTRY(printhex8) + mov r1, #8 + b printhex + +ENTRY(printhex4) + mov r1, #4 + b printhex + +ENTRY(printhex2) + mov r1, #2 +printhex: ldr r2, =hexbuf + add r3, r2, r1 + mov r1, #0 + strb r1, [r3] +1: and r1, r0, #15 + mov r0, r0, lsr #4 + cmp r1, #10 + addlt r1, r1, #'0' + addge r1, r1, #'a' - 10 + strb r1, [r3, #-1]! + teq r3, r2 + bne 1b + mov r0, r2 + b printascii + + .ltorg + +ENTRY(printascii) + addruart r3 + b 2f +1: waituart r2, r3 + senduart r1, r3 + busyuart r2, r3 + teq r1, #'\n' + moveq r1, #'\r' + beq 1b +2: teq r0, #0 + ldrneb r1, [r0], #1 + teqne r1, #0 + bne 1b + mov pc, lr + +ENTRY(printch) + addruart r3 + mov r1, r0 + mov r0, #0 + b 1b + + .bss +hexbuf: .space 16 diff --git a/arch/arm/kernel/debug-armv.S b/arch/arm/kernel/debug-armv.S new file mode 100644 index 000000000..fef1489b7 --- /dev/null +++ b/arch/arm/kernel/debug-armv.S @@ -0,0 +1,206 @@ +/* + * linux/arch/arm/kernel/debug-armv.S + * + * Copyright (C) 1994-1999 Russell King + * + * 32-bit debugging code + */ +#include <linux/config.h> +#include <linux/linkage.h> +#include <asm/hardware.h> +#include <asm/dec21285.h> + + .text + +/* + * Some debugging routines (useful if you've got MM problems and + * printk isn't working). For DEBUGGING ONLY!!! Do not leave + * references to these in a production kernel! + */ +#if defined(CONFIG_ARCH_RPC) + .macro addruart,rx + mov \rx, #0xe0000000 + orr \rx, \rx, #0x00010000 + orr \rx, \rx, #0x00000fe0 + .endm + + .macro senduart,rd,rx + strb \rd, [\rx] + .endm + + .macro busyuart,rd,rx +1002: ldrb \rd, [\rx, #0x14] + and \rd, \rd, #0x60 + teq \rd, #0x60 + bne 1002b + .endm + + .macro waituart,rd,rx +1001: ldrb \rd, [\rx, #0x18] + tst \rd, #0x10 + beq 1001b + .endm + +#elif defined(CONFIG_ARCH_EBSA110) + .macro addruart,rx + mov \rx, #0xf0000000 + orr \rx, \rx, #0x00000be0 + .endm + + .macro senduart,rd,rx + strb \rd, [\rx] + .endm + + .macro busyuart,rd,rx +1002: ldrb \rd, [\rx, #0x14] + and \rd, \rd, #0x60 + teq \rd, #0x60 + bne 1002b + .endm + + .macro waituart,rd,rx +1001: ldrb \rd, [\rx, #0x18] + tst \rd, #0x10 + beq 1001b + .endm + +#elif defined(CONFIG_HOST_FOOTBRIDGE) || defined(CONFIG_ADDIN_FOOTBRIDGE) +#ifndef CONFIG_DEBUG_DC21285_PORT + /* For NetWinder debugging */ + .macro addruart,rx + mov \rx, #0xff000000 + orr \rx, \rx, #0x000003f8 + .endm + + .macro senduart,rd,rx + strb \rd, [\rx] + .endm + + .macro busyuart,rd,rx +1002: ldrb \rd, [\rx, #0x5] + and \rd, \rd, #0x60 + teq \rd, #0x60 + bne 1002b + .endm + + .macro waituart,rd,rx +1001: ldrb \rd, [\rx, #0x6] + tst \rd, #0x10 + beq 1001b + .endm +#else + /* For EBSA285 debugging */ + .equ dc21285_high, ARMCSR_BASE & 0xff000000 + .equ dc21285_low, ARMCSR_BASE & 0x00ffffff + + .macro addruart,rx + mov \rx, #dc21285_high + .if dc21285_low + orr \rx, \rx, #dc21285_low + .endif + .endm + + .macro senduart,rd,rx + str \rd, [\rx, #0x160] @ UARTDR + .endm + + .macro busyuart,rd,rx +1001: ldr \rd, [\rx, #0x178] @ UARTFLG + tst \rd, #1 << 3 + bne 1001b + .endm + + .macro waituart,rd,rx + .endm +#endif +#elif defined(CONFIG_ARCH_NEXUSPCI) + .macro addruart,rx + ldr \rx, =0xfff00000 + .endm + + .macro senduart,rd,rx + str \rd, [\rx, #0xc] + .endm + + .macro busyuart,rd,rx +1001: ldr \rd, [\rx, #0x4] + tst \rd, #1 << 0 + bne 1001b + .endm + + .macro waituart,rd,rx + .endm + +#elif defined(CONFIG_ARCH_SA1100) + .macro addruart,rx + mov \rx, #0xf8000000 + add \rx, \rx, #0x00050000 + .endm + + .macro senduart,rd,rx + str \rd, [\rx, #0x14] @ UARTDR + .endm + + .macro busyuart,rd,rx +1001: ldr \rd, [\rx, #0x20] @ UTSR1 + tst \rd, #1 << 2 + beq 1001b + .endm + +#else +#error Unknown architecture +#endif + +/* + * Useful debugging routines + */ +ENTRY(printhex8) + mov r1, #8 + b printhex + +ENTRY(printhex4) + mov r1, #4 + b printhex + +ENTRY(printhex2) + mov r1, #2 +printhex: ldr r2, =hexbuf + add r3, r2, r1 + mov r1, #0 + strb r1, [r3] +1: and r1, r0, #15 + mov r0, r0, lsr #4 + cmp r1, #10 + addlt r1, r1, #'0' + addge r1, r1, #'a' - 10 + strb r1, [r3, #-1]! + teq r3, r2 + bne 1b + mov r0, r2 + b printascii + + .ltorg + +ENTRY(printascii) + addruart r3 + b 2f +1: waituart r2, r3 + senduart r1, r3 + busyuart r2, r3 + teq r1, #'\n' + moveq r1, #'\r' + beq 1b +2: teq r0, #0 + ldrneb r1, [r0], #1 + teqne r1, #0 + bne 1b + mov pc, lr + +ENTRY(printch) + addruart r3 + mov r1, r0 + mov r0, #0 + b 1b + + .bss +hexbuf: .space 16 diff --git a/arch/arm/kernel/dec21285.c b/arch/arm/kernel/dec21285.c index 6a4988b15..42a9a616f 100644 --- a/arch/arm/kernel/dec21285.c +++ b/arch/arm/kernel/dec21285.c @@ -13,241 +13,318 @@ #include <linux/init.h> #include <linux/ioport.h> +#include <asm/dec21285.h> +#include <asm/io.h> #include <asm/irq.h> #include <asm/system.h> -#include <asm/hardware.h> #define MAX_SLOTS 21 -extern void pcibios_fixup_ebsa285(struct pci_dev *dev); -extern void pcibios_init_ebsa285(void); - -int -pcibios_present(void) -{ - return 1; -} +extern int setup_arm_irq(int, struct irqaction *); +extern void pcibios_report_device_errors(void); +extern int (*pci_irq_fixup)(struct pci_dev *dev); static unsigned long -pcibios_base_address(unsigned char bus, unsigned char dev_fn) +dc21285_base_address(struct pci_dev *dev, int where) { - if (bus == 0) { - int slot = PCI_SLOT(dev_fn); - - if (slot < MAX_SLOTS) - return PCICFG0_BASE + 0xc00000 + - (slot << 11) + (PCI_FUNC(dev_fn) << 8); - else - return 0; - } else - return PCICFG1_BASE | (bus << 16) | (dev_fn << 8); + unsigned long addr = 0; + unsigned int devfn = dev->devfn; + + if (dev->bus->number != 0) + addr = PCICFG1_BASE | (dev->bus->number << 16) | (devfn << 8); + else if (devfn < PCI_DEVFN(MAX_SLOTS, 0)) + addr = PCICFG0_BASE | 0xc00000 | (devfn << 8); + + return addr; } -int -pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned char *val) +static int +dc21285_read_config_byte(struct pci_dev *dev, int where, u8 *value) { - unsigned long addr = pcibios_base_address(bus, dev_fn); - unsigned char v; + unsigned long addr = dc21285_base_address(dev, where); + u8 v; if (addr) - __asm__("ldr%?b %0, [%1, %2]" - : "=r" (v) - : "r" (addr), "r" (where)); + asm("ldr%?b %0, [%1, %2]" + : "=r" (v) : "r" (addr), "r" (where)); else v = 0xff; - *val = v; + + *value = v; + return PCIBIOS_SUCCESSFUL; } -int -pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned short *val) +static int +dc21285_read_config_word(struct pci_dev *dev, int where, u16 *value) { - unsigned long addr = pcibios_base_address(bus, dev_fn); - unsigned short v; + unsigned long addr = dc21285_base_address(dev, where); + u16 v; if (addr) - __asm__("ldr%?h %0, [%1, %2]" - : "=r" (v) - : "r" (addr), "r" (where)); + asm("ldr%?h %0, [%1, %2]" + : "=r" (v) : "r" (addr), "r" (where)); else v = 0xffff; - *val = v; + + *value = v; + return PCIBIOS_SUCCESSFUL; } -int -pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned int *val) +static int +dc21285_read_config_dword(struct pci_dev *dev, int where, u32 *value) { - unsigned long addr = pcibios_base_address(bus, dev_fn); - unsigned int v; + unsigned long addr = dc21285_base_address(dev, where); + u32 v; if (addr) - __asm__("ldr%? %0, [%1, %2]" - : "=r" (v) - : "r" (addr), "r" (where)); + asm("ldr%? %0, [%1, %2]" + : "=r" (v) : "r" (addr), "r" (where)); else v = 0xffffffff; - *val = v; + + *value = v; + return PCIBIOS_SUCCESSFUL; } -int -pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned char val) +static int +dc21285_write_config_byte(struct pci_dev *dev, int where, u8 value) { - unsigned long addr = pcibios_base_address(bus, dev_fn); + unsigned long addr = dc21285_base_address(dev, where); if (addr) - __asm__("str%?b %0, [%1, %2]" - : : "r" (val), "r" (addr), "r" (where)); + asm("str%?b %0, [%1, %2]" + : : "r" (value), "r" (addr), "r" (where)); + return PCIBIOS_SUCCESSFUL; } -int -pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned short val) +static int +dc21285_write_config_word(struct pci_dev *dev, int where, u16 value) { - unsigned long addr = pcibios_base_address(bus, dev_fn); + unsigned long addr = dc21285_base_address(dev, where); if (addr) - __asm__("str%?h %0, [%1, %2]" - : : "r" (val), "r" (addr), "r" (where)); + asm("str%?h %0, [%1, %2]" + : : "r" (value), "r" (addr), "r" (where)); + return PCIBIOS_SUCCESSFUL; } -int -pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char where, unsigned int val) +static int +dc21285_write_config_dword(struct pci_dev *dev, int where, u32 value) { - unsigned long addr = pcibios_base_address(bus, dev_fn); + unsigned long addr = dc21285_base_address(dev, where); if (addr) - __asm__("str%? %0, [%1, %2]" - : : "r" (val), "r" (addr), "r" (where)); + asm("str%? %0, [%1, %2]" + : : "r" (value), "r" (addr), "r" (where)); + return PCIBIOS_SUCCESSFUL; } -void __init pci_set_cmd(struct pci_dev *dev, unsigned short clear, unsigned short set) +static struct pci_ops dc21285_ops = { + dc21285_read_config_byte, + dc21285_read_config_word, + dc21285_read_config_dword, + dc21285_write_config_byte, + dc21285_write_config_word, + dc21285_write_config_dword, +}; + +/* + * Warn on PCI errors. + */ +static void +dc21285_error(int irq, void *dev_id, struct pt_regs *regs) { - unsigned short cmd; + static unsigned long next_warn; + unsigned long cmd = *CSR_PCICMD & 0x0000ffff; + unsigned long ctrl = (*CSR_SA110_CNTL) & 0xffffde07; + unsigned long irqstatus = *CSR_IRQ_RAWSTATUS; + int warn = time_after_eq(jiffies, next_warn); - pci_read_config_word(dev, PCI_COMMAND, &cmd); - cmd = (cmd & ~clear) | set; - pci_write_config_word(dev, PCI_COMMAND, cmd); -} + ctrl |= SA110_CNTL_DISCARDTIMER; -void __init pci_set_base_addr(struct pci_dev *dev, int idx, unsigned int addr) -{ - int reg = PCI_BASE_ADDRESS_0 + (idx << 2); + if (warn) { + next_warn = jiffies + HZ; + printk(KERN_DEBUG "PCI: "); + } - pci_write_config_dword(dev, reg, addr); - pci_read_config_dword(dev, reg, &addr); + if (irqstatus & (1 << 31)) { + if (warn) + printk("parity error "); + cmd |= 1 << 31; + } - dev->base_address[idx] = addr; -} + if (irqstatus & (1 << 30)) { + if (warn) + printk("target abort "); + cmd |= 1 << 28; + } -void __init pcibios_fixup(void) -{ - struct pci_dev *dev; + if (irqstatus & (1 << 29)) { + if (warn) + printk("master abort "); + cmd |= 1 << 29; + } - for (dev = pci_devices; dev; dev = dev->next) { - pcibios_fixup_ebsa285(dev); + if (irqstatus & (1 << 28)) { + if (warn) + printk("data parity error "); + cmd |= 1 << 24; + } - pcibios_write_config_byte(dev->bus->number, dev->devfn, - PCI_INTERRUPT_LINE, dev->irq); + if (irqstatus & (1 << 27)) { + if (warn) + printk("discard timer expired "); + ctrl &= ~SA110_CNTL_DISCARDTIMER; + } - printk(KERN_DEBUG - "PCI: %02x:%02x [%04x/%04x] on irq %d\n", - dev->bus->number, dev->devfn, - dev->vendor, dev->device, dev->irq); + if (irqstatus & (1 << 23)) { + if (warn) + printk("system error "); + ctrl |= SA110_CNTL_RXSERR; } - hw_init(); + if (warn) + printk("pc=[<%08lX>]\n", instruction_pointer(regs)); + + pcibios_report_device_errors(); + + *CSR_PCICMD = cmd; + *CSR_SA110_CNTL = ctrl; } -void __init pcibios_init(void) -{ - unsigned int mem_size = (unsigned int)high_memory - PAGE_OFFSET; - unsigned long cntl; +static struct irqaction dc21285_error_action = { + dc21285_error, SA_INTERRUPT, 0, "PCI error", NULL, NULL +}; - *CSR_SDRAMBASEMASK = (mem_size - 1) & 0x0ffc0000; - *CSR_SDRAMBASEOFFSET = 0; - *CSR_ROMBASEMASK = 0x80000000; - *CSR_CSRBASEMASK = 0; - *CSR_CSRBASEOFFSET = 0; - *CSR_PCIADDR_EXTN = 0; +static int irqmap_ebsa[] __initdata = { IRQ_IN1, IRQ_IN0, IRQ_PCI, IRQ_IN3 }; -#ifdef CONFIG_HOST_FOOTBRIDGE - /* - * Against my better judgement, Philip Blundell still seems - * to be saying that we should initialise the PCI stuff here - * when the PCI_CFN bit is not set, dispite my comment below, - * which he decided to remove. If it is not set, then - * the card is in add-in mode, and we're in a machine where - * the bus is set up by 'others'. - * - * We should therefore not mess about with the mapping in - * anyway, and we should not be using the virt_to_bus functions - * that exist in the HOST architecture mode (since they assume - * a fixed mapping). - * - * Instead, you should be using ADDIN mode, which allows for - * this situation. This does assume that you have correctly - * initialised the PCI bus, which you must have done to get - * your PC booted. - * - * Unfortunately, he seems to be blind to this. I guess he'll - * also remove all this. - * - * And THIS COMMENT STAYS, even if this gets patched, thank - * you. - */ - - /* - * Map our SDRAM at a known address in PCI space, just in case - * the firmware had other ideas. Using a nonzero base is - * necessary, since some VGA cards forcefully use PCI addresses - * in the range 0x000a0000 to 0x000c0000. (eg, S3 cards). - * - * NOTE! If you need to chec the PCI_CFN bit in the SA110 - * control register then you've configured the kernel wrong. - * If you're not using host mode, then DO NOT set - * CONFIG_HOST_FOOTBRIDGE, but use CONFIG_ADDIN_FOOTBRIDGE - * instead. In this case, you MUST supply some firmware - * to allow your PC to boot, plus we should not modify the - * mappings that the PC BIOS has set up for us. - */ - *CSR_PCICACHELINESIZE = 0x00002008; - *CSR_PCICSRBASE = 0; - *CSR_PCICSRIOBASE = 0; - *CSR_PCISDRAMBASE = virt_to_bus((void *)PAGE_OFFSET); - *CSR_PCIROMBASE = 0; - *CSR_PCICMD = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | - PCI_COMMAND_MASTER | PCI_COMMAND_FAST_BACK | - PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | - (1 << 31) | (1 << 29) | (1 << 28) | (1 << 24); -#endif +static int __init ebsa_irqval(struct pci_dev *dev) +{ + u8 pin; + + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); - /* - * Clear any existing errors - we aren't - * interested in historical data... - */ - cntl = *CSR_SA110_CNTL & 0xffffde07; - *CSR_SA110_CNTL = cntl | SA110_CNTL_RXSERR; + return irqmap_ebsa[(PCI_SLOT(dev->devfn) + pin) & 3]; +} - pcibios_init_ebsa285(); +static int irqmap_cats[] __initdata = { IRQ_PCI, IRQ_IN0, IRQ_IN1, IRQ_IN3 }; - printk(KERN_DEBUG"PCI: DEC21285 revision %02lX\n", *CSR_CLASSREV & 0xff); +static int __init cats_irqval(struct pci_dev *dev) +{ + if (dev->irq >= 128) + return 16 + (dev->irq & 0x1f); + + switch (dev->irq) { + case 1 ... 4: + return irqmap_cats[dev->irq - 1]; + + default: + printk("PCI: device %02x:%02x has unknown irq line %x\n", + dev->bus->number, dev->devfn, dev->irq); + case 0: + break; + } + return 0; } -void __init pcibios_fixup_bus(struct pci_bus *bus) +static int __init netwinder_irqval(struct pci_dev *dev) { +#define DEV(v,d) ((v)<<16|(d)) + switch (DEV(dev->vendor, dev->device)) { + case DEV(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142): + return IRQ_NETWINDER_ETHER100; + + case DEV(PCI_VENDOR_ID_WINBOND2, 0x5a5a): + return IRQ_NETWINDER_ETHER10; + + case DEV(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553): + return 0; + + case DEV(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105): + return IRQ_ISA_HARDDISK1; + + case DEV(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2000): + return IRQ_NETWINDER_VGA; + + default: + printk(KERN_ERR "PCI: %02X:%02X [%04X:%04X] unknown device\n", + dev->bus->number, dev->devfn, + dev->vendor, dev->device); + return 0; + } } -char * __init pcibios_setup(char *str) +struct pci_ops * __init dc21285_init(int pass) { - return str; + unsigned int mem_size; + unsigned long cntl; + + if (pass == 0) { + mem_size = (unsigned int)high_memory - PAGE_OFFSET; + *CSR_SDRAMBASEMASK = (mem_size - 1) & 0x0ffc0000; + *CSR_SDRAMBASEOFFSET = 0; + *CSR_ROMBASEMASK = 0x80000000; + *CSR_CSRBASEMASK = 0; + *CSR_CSRBASEOFFSET = 0; + *CSR_PCIADDR_EXTN = 0; + +#ifdef CONFIG_HOST_FOOTBRIDGE + /* + * Map our SDRAM at a known address in PCI space, just in case + * the firmware had other ideas. Using a nonzero base is + * necessary, since some VGA cards forcefully use PCI addresses + * in the range 0x000a0000 to 0x000c0000. (eg, S3 cards). + */ + *CSR_PCICACHELINESIZE = 0x00002008; + *CSR_PCICSRBASE = 0; + *CSR_PCICSRIOBASE = 0; + *CSR_PCISDRAMBASE = virt_to_bus((void *)PAGE_OFFSET); + *CSR_PCIROMBASE = 0; + *CSR_PCICMD = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER | PCI_COMMAND_FAST_BACK | + PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | + (1 << 31) | (1 << 29) | (1 << 28) | (1 << 24); +#endif + + printk(KERN_DEBUG"PCI: DC21285 footbridge, revision %02lX\n", + *CSR_CLASSREV & 0xff); + + switch (machine_arch_type) { + case MACH_TYPE_EBSA285: + pci_irq_fixup = ebsa_irqval; + break; + + case MACH_TYPE_CATS: + pci_irq_fixup = cats_irqval; + break; + + case MACH_TYPE_NETWINDER: + pci_irq_fixup = netwinder_irqval; + break; + } + + return &dc21285_ops; + } else { + /* + * Clear any existing errors - we aren't + * interested in historical data... + */ + cntl = *CSR_SA110_CNTL & 0xffffde07; + *CSR_SA110_CNTL = cntl | SA110_CNTL_RXSERR; + cntl = *CSR_PCICMD & 0x0000ffff; + *CSR_PCICMD = cntl | 1 << 31 | 1 << 29 | 1 << 28 | 1 << 24; + + /* + * Initialise PCI error IRQ after we've finished probing + */ + setup_arm_irq(IRQ_PCI_ERR, &dc21285_error_action); + + return NULL; + } } diff --git a/arch/arm/kernel/dma-dummy.c b/arch/arm/kernel/dma-dummy.c index 7efc85363..ebb9755c1 100644 --- a/arch/arm/kernel/dma-dummy.c +++ b/arch/arm/kernel/dma-dummy.c @@ -17,15 +17,18 @@ int request_dma(int channel, const char *device_id) return -EINVAL; } -void free_dma(int channel) -{ -} - -int get_dma_list(char *buf) +int no_dma(void) { return 0; } -void __init init_dma(void) -{ -} +#define GLOBAL_ALIAS(_a,_b) asm (".set " #_a "," #_b "; .globl " #_a) +GLOBAL_ALIAS(disable_dma, no_dma); +GLOBAL_ALIAS(enable_dma, no_dma); +GLOBAL_ALIAS(free_dma, no_dma); +GLOBAL_ALIAS(get_dma_residue, no_dma); +GLOBAL_ALIAS(get_dma_list, no_dma); +GLOBAL_ALIAS(set_dma_mode, no_dma); +GLOBAL_ALIAS(set_dma_count, no_dma); +GLOBAL_ALIAS(set_dma_addr, no_dma); +GLOBAL_ALIAS(init_dma, no_dma); diff --git a/arch/arm/kernel/dma-footbridge.c b/arch/arm/kernel/dma-footbridge.c index 016b11c15..65875831c 100644 --- a/arch/arm/kernel/dma-footbridge.c +++ b/arch/arm/kernel/dma-footbridge.c @@ -13,14 +13,11 @@ #include <linux/config.h> #include <linux/sched.h> -#include <linux/malloc.h> -#include <linux/mman.h> +#include <linux/errno.h> #include <linux/init.h> -#include <asm/page.h> #include <asm/dma.h> #include <asm/io.h> -#include <asm/hardware.h> #include "dma.h" #include "dma-isa.h" diff --git a/arch/arm/kernel/dma-isa.c b/arch/arm/kernel/dma-isa.c index f5f98bbac..74967a055 100644 --- a/arch/arm/kernel/dma-isa.c +++ b/arch/arm/kernel/dma-isa.c @@ -126,6 +126,13 @@ void isa_disable_dma(int channel, dma_t *dma) outb(channel | 4, isa_dma_port[channel][ISA_DMA_MASK]); } +static struct resource dma_resources[] = { + { "dma1", 0x0000, 0x000f }, + { "dma low page", 0x0080, 0x008f }, + { "dma2", 0x00c0, 0x00df }, + { "dma high page", 0x0480, 0x048f } +}; + int __init isa_init_dma(void) { int dmac_found; diff --git a/arch/arm/kernel/dma-rpc.c b/arch/arm/kernel/dma-rpc.c index e27232255..ad9afac30 100644 --- a/arch/arm/kernel/dma-rpc.c +++ b/arch/arm/kernel/dma-rpc.c @@ -357,6 +357,8 @@ int arch_set_dma_speed(dmach_t channel, dma_t *dma, int cycle) } outb(tcr, IOMD_DMATCR); + + return speed; } void __init arch_dma_init(dma_t *dma) diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c index c4b0efef8..99b2b2b1d 100644 --- a/arch/arm/kernel/ecard.c +++ b/arch/arm/kernel/ecard.c @@ -82,7 +82,7 @@ static unsigned int have_expmask; /* List of descriptions of cards which don't have an extended * identification, or chunk directories containing a description. */ -static const struct expcard_blacklist __init blacklist[] = { +static struct expcard_blacklist __initdata blacklist[] = { { MANU_ACORN, PROD_ACORN_ETHER1, "Acorn Ether1" } }; @@ -827,6 +827,8 @@ unsigned int ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed) ectcr |= 1 << slot; break; #endif + default: + break; } #ifdef IOMD_ECTCR diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 3e015d866..7e6d4fe51 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -298,6 +298,30 @@ irq_prio_ebsa110: .macro irq_prio_table .endm + +#elif defined(CONFIG_ARCH_SA1100) + + .macro disable_fiq + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base + mov r4, #0xfa000000 @ ICIP = 0xfa050000 + add r4, r4, #0x00050000 + ldr \irqstat, [r4] @ get irqs + ldr \irqnr, [r4, #4] @ ICMR = 0xfa050004 + ands \irqstat, \irqstat, \irqnr + mov \irqnr, #0 + beq 1002f +1001: tst \irqstat, #1 + addeq \irqnr, \irqnr, #1 + moveq \irqstat, \irqstat, lsr #1 + beq 1001b +1002: + .endm + + .macro irq_prio_table + .endm + #else #error Unknown architecture #endif @@ -449,11 +473,15 @@ __dabt_svc: sub sp, sp, #S_FRAME_SIZE add r5, sp, #S_SP mov r1, lr stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro + + mrs r9, cpsr @ Enable interrupts if they were tst r3, #I_BIT - mrseq r0, cpsr @ Enable interrupts if they were - biceq r0, r0, #I_BIT @ previously - msreq cpsr, r0 + biceq r9, r9, #I_BIT @ previously + mov r0, r2 +/* + * This routine must not corrupt r9 + */ #ifdef MULTI_CPU ldr r2, .LCprocfns mov lr, pc @@ -461,6 +489,7 @@ __dabt_svc: sub sp, sp, #S_FRAME_SIZE #else bl cpu_data_abort #endif + msr cpsr, r9 mov r3, sp bl SYMBOL_NAME(do_DataAbort) ldr r0, [sp, #S_PSR] @@ -544,9 +573,6 @@ __dabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go #endif mov fp, #0 - mrs r2, cpsr @ Enable interrupts if they were - bic r2, r2, #I_BIT @ previously - msr cpsr, r2 #ifdef MULTI_CPU ldr r2, .LCprocfns mov lr, pc @@ -554,6 +580,10 @@ __dabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go #else bl cpu_data_abort #endif + mrs r3, cpsr @ Enable interrupts if they were + bic r3, r3, #I_BIT @ previously + msr cpsr, r3 + mov r3, sp adrsvc al, lr, ret_from_sys_call b SYMBOL_NAME(do_DataAbort) diff --git a/arch/arm/kernel/head-armo.S b/arch/arm/kernel/head-armo.S index d6b2b79e6..df5b02ae8 100644 --- a/arch/arm/kernel/head-armo.S +++ b/arch/arm/kernel/head-armo.S @@ -1,5 +1,5 @@ /* - * linux/arch/arm/kernel/head.S + * linux/arch/arm/kernel/head-armo.S * * Copyright (C) 1994, 1995, 1996, 1997 Russell King * @@ -7,11 +7,13 @@ */ #include <linux/linkage.h> - .text - .align + .globl SYMBOL_NAME(swapper_pg_dir) + .equ SYMBOL_NAME(swapper_pg_dir), 0x0207d000 + /* * Entry point. */ + .section ".text.init",#alloc,#execinstr ENTRY(stext) ENTRY(_stext) __entry: cmp pc, #0x02000000 diff --git a/arch/arm/kernel/head-armv.S b/arch/arm/kernel/head-armv.S index e9a05aed6..16436684e 100644 --- a/arch/arm/kernel/head-armv.S +++ b/arch/arm/kernel/head-armv.S @@ -1,54 +1,60 @@ /* - * linux/arch/arm/kernel/head32.S + * linux/arch/arm/kernel/head-armv.S * - * Copyright (C) 1994-1998 Russell King + * Copyright (C) 1994-1999 Russell King * - * Kernel 32 bit startup code for ARM6 / ARM7 / StrongARM + * 32-bit kernel startup code for all architectures */ #include <linux/config.h> #include <linux/linkage.h> + +#include <asm/assembler.h> #include <asm/hardware.h> #include <asm/dec21285.h> +#if (TEXTADDR & 0xffff) != 0x8000 +#error TEXTADDR must start at 0xXXXX8000 +#endif + +#define SWAPPER_PGDIR_OFFSET 0x4000 + .globl SYMBOL_NAME(swapper_pg_dir) - .equ SYMBOL_NAME(swapper_pg_dir), TEXTADDR - 0x4000 + .equ SYMBOL_NAME(swapper_pg_dir), TEXTADDR - 0x8000 + SWAPPER_PGDIR_OFFSET .section ".text.init",#alloc,#execinstr ENTRY(stext) ENTRY(_stext) -#if (TEXTADDR & 0xffff) != 0x8000 -#error TEXTADDR must start at 0xXXXX8000 -#endif - #ifdef CONFIG_ARCH_NETWINDER +/* + * Compatability cruft for old NetWinder NeTTroms. This + * code is currently scheduled for destruction in 2.5.xx + */ + .rept 8 mov r0, r0 - mov r0, r0 - mov r0, r0 - mov r0, r0 - mov r0, r0 - mov r0, r0 - mov r0, r0 - mov r0, r0 + .endr adr r2, 1f ldmdb r2, {r7, r8} - and r3, r2, #0x0000c000 - teq r3, #0x00008000 + and r3, r2, #0xc000 + teq r3, #0x8000 beq __entry bic r3, r2, #0xc000 orr r3, r3, #0x8000 mov r0, r3 - mov r4, #32 + mov r4, #64 sub r5, r8, r7 b 1f .word _stext - .word _end + .word __bss_start -1: ldmia r2!, {r6, r7, r8, r9} +1: + .rept 4 + ldmia r2!, {r6, r7, r8, r9} stmia r3!, {r6, r7, r8, r9} - subs r4, r4, #16 + .endr + subs r4, r4, #64 bcs 1b movs r4, r5 mov r5, #0 @@ -59,78 +65,114 @@ ENTRY(_stext) #endif /* - * 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 -> DEC EBSA-110 - * r1 = 1 -> Acorn RiscPC - * r1 = 2 -> ebsit - * r1 = 3 -> nexuspci - * r1 = 4 -> DEC EBSA-285 - * r1 = 5 -> Corel Netwinder - * r1 = 6 -> CATS - * r1 = 7 -> tbox - * r1 = 8 -> SA110/21285 as co-processor - * r1 = 9 -> CL-PS7110 system - * r1 = 12 -> SA1100 based system + * Entry point. Entry *must* be called with r0 == 0, with the MMU off. + * r1 contains the unique architecture number. See + * linux/arch/arm/kernel/setup.c machine_desc[] array for the complete + * list. If you require a new number, please follow the instructions + * given in Documentation/ARM-README. */ +__entry: teq r0, #0 + movne r0, #'i' + bne __error + bl __lookup_processor_type + teq r10, #0 @ invalid processor? + moveq r0, #'p' + beq __error + bl __lookup_architecture_type + teq r7, #0 @ invalid architecture? + moveq r0, #'a' + beq __error + bl __create_page_tables + adr lr, __aligned_call + add pc, r10, #12 @ flush caches (returns ctrl reg) + +__switch_data: .long __mmap_switched + .long SYMBOL_NAME(__bss_start) + .long SYMBOL_NAME(_end) + .long SYMBOL_NAME(processor_id) + .long SYMBOL_NAME(__machine_arch_type) + .long SYMBOL_NAME(cr_alignment) + .long SYMBOL_NAME(init_task_union)+8192 + + /* + * This needs to be aligned to a cache line. + */ + .align 5 +__aligned_call: + ldr lr, __switch_data +#ifdef CONFIG_ALIGNMENT_TRAP + orr r0, r0, #2 @ ...........A. +#endif + mcr p15, 0, r0, c1, c0 + mov pc, lr + + /* + * This code follows on after the page + * table switch and jump above. + * + * r0 = processor control register + * r1 = machine ID + * r9 = processor ID + */ + .align 5 +__mmap_switched: + adr r3, __switch_data + 4 + ldmia r3, {r4, r5, r6, r7, r8, sp} @ Setup stack + + mov fp, #0 @ Clear BSS +1: cmp r4, r5 + strcc fp, [r4],#4 + bcc 1b + + str r9, [r6] @ Save processor ID + str r1, [r7] @ Save machine type + bic r2, r0, #2 @ Clear 'A' bit + stmia r8, {r0, r2} @ Save control register values + b SYMBOL_NAME(start_kernel) + -__entry: teq r0, #0 @ check for illegal entry... - bne .Lerror @ loop indefinitely - cmp r1, #9 @ 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... - * - Read processor ID register (CP#15, CR0). - */ - mrc p15, 0, r9, c0, c0 @ get Processor ID -/* 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? - beq .Lerror - eor r5, r5, r9 - tst r5, r6 - addne r10, r10, #8 - bne 1b - adr r4, .LCMachTypes - add r4, r4, r1, lsl #4 - ldmia r4, {r4, r5, r6, r7} /* - * r4 = page dir in physical ram + * Setup the initial page tables. We only setup the barest + * amount which are required to get the kernel running, which + * generally means mapping in the kernel code. + * + * We only map in 2MB of RAM, which should be sufficient in + * all cases. + * + * r4 = physical address of page tables * r5 = physical address of start of RAM - * r6 = I/O address + * r6 = physical IO address + * r7 = byte offset into page tables for IO + * r8 = page table flags */ +__create_page_tables: mov r0, r4 mov r3, #0 - add r2, r0, #0x4000 -1: str r3, [r0], #4 @ Clear page table + add r2, r0, #0x4000 @ Clear page table +1: str r3, [r0], #4 + str r3, [r0], #4 + str r3, [r0], #4 + str r3, [r0], #4 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 (TEXTADDR-0x8000) + 2MB - */ + /* + * map in two sections (2MB) for kernel. + * these are marked cacheable and bufferable. + */ add r0, r4, #(TEXTADDR - 0x8000) >> 18 - mov r3, #0x0000000c @ SECT_CACHEABLE | SECT_BUFFERABLE + mov r3, #0x0c 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 CONFIG_DEBUG_LL -/* Map in IO space - * This allows debug messages to be output via a serial - * before/while paging_init. - */ + /* + * Map in IO space for serial debugging. + * This allows debug messages to be output + * via a serial before paging_init. + */ add r0, r4, r7 orr r3, r6, r8 add r2, r0, #0x0800 @@ -147,45 +189,39 @@ __entry: teq r0, #0 @ check for illegal entry... str r3, [r0], #4 add r3, r3, #1 << 20 str r3, [r0], #4 -1: #endif #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. - */ + /* + * Map in screen at 0x02000000 & SCREEN2_BASE + * Similar reasons here - for debug. This is + * only for Acorn RiscPC architectures. + */ teq r5, #0 - addne r0, r4, #0x80 @ 02000000 + addne r0, r4, #0x80 @ 02000000 movne r3, #0x02000000 orrne r3, r3, r8 strne r3, [r0] - addne r0, r4, #0x3600 @ d8000000 + addne r0, r4, #0x3600 @ d8000000 strne r3, [r0] #endif - b aligned_call -/* - * The following should work on both v3 and v4 implementations - * Note: it seems that if the mov pc,lr is on the next cache - * line, it doesn't get fetched before the MMU starts - * translating, which prevents the kernel from booting. - * Ensure that this never happens. - */ - .align 5 -aligned_call: - mov lr, pc - mov pc, r10 @ Call processor flush (returns ctrl reg) - adr r5, __entry - sub r10, r10, r5 @ Make r10 PIC - ldr lr, .Lbranch - mcr p15, 0, r0, c1, c0 @ Enable MMU & caches. In 3 instructions - @ we lose this page! mov pc, lr -.Lerror: + + +/* + * Exception handling. Something went wrong and we can't + * proceed. We ought to tell the user, but since we + * don't have any guarantee that we're even running on + * the right architecture, we do virtually nothing. + * r0 = ascii error character + * + * Generally, only serious errors cause this. + */ +__error: #ifdef CONFIG_ARCH_RPC -/* Turn the screen red on a error - RiscPC only. +/* + * Turn the screen red on a error - RiscPC only. */ mov r0, #0x02000000 mov r3, #0x11 @@ -199,356 +235,171 @@ aligned_call: 1: mov r0, r0 b 1b -.Lbranch: .long .Lalready_done_mmap @ Real address of routine - @ 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 0x3800 - @ Acorn RiscPC - .long SYMBOL_NAME(swapper_pg_dir) - 0xc0000000 + 0x10000000 - .long 0x10000000 - .long 0x03000000 - .long 0x3800 +/* + * Read processor ID register (CP#15, CR0), and determine + * processor type. + * + * Returns: + * r5, r6, r7 corrupted + * r8 = page table flags + * r9 = processor ID + * r10 = pointer to processor structure + */ +__lookup_processor_type: + adr r5, 2f + ldmia r5, {r7, r9, r10} + sub r5, r5, r9 + add r7, r7, r5 + add r10, r10, r5 + mrc p15, 0, r9, c0, c0 @ get processor id +1: ldmia r10, {r5, r6, r8} @ value, mask, mmuflags + eor r5, r5, r9 + tst r5, r6 + moveq pc, lr + add r10, r10, #36 @ sizeof(proc_info_list) + cmp r10, r7 + blt 1b + mov r10, #0 + mov pc, lr - @ EBSIT ??? - .long SYMBOL_NAME(swapper_pg_dir) - 0xc0000000 - .long 0 - .long 0xe0000000 - .long 0x3800 +2: .long __proc_info_end + .long 2b + .long __proc_info_begin - @ NexusPCI - .long SYMBOL_NAME(swapper_pg_dir) - 0xc0000000 + 0x40000000 - .long 0x40000000 - .long 0x10000000 - .long 0x3800 - - @ 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) - .long 0x3800 - - @ Corel VNC - .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) - .long 0x3800 - - @ CATS - .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) - .long 0x3800 - - @ tbox - .long SYMBOL_NAME(swapper_pg_dir) - 0xc0000000 + 0x80000000 - .long 0x80000000 @ Address of RAM - .long 0x00400000 @ Uart - .long 0x3800 - - @ DEC EBSA285 as co-processor - .long 0x4000 @ Address of page tables (physical) - .long 0 @ Address of RAM - .long DC21285_ARMCSR_BASE @ Physical I/O base address - .long 0x7cf00000 >> 18 @ Virtual I/O base address - - @ SA1100 - .long SYMBOL_NAME(swapper_pg_dir) - 0xc0000000 + 0xc0000000 - .long 0xc0000000 - .long 0x80000000 @ IO mapping will change when kernel gets on its feet - .long 0x3800 - -.LCProcTypes: @ ARM6 / 610 - .long 0x41560600 - .long 0xffffff00 - .long 0x00000c12 - b .Larmv3_flush_early @ arm v3 flush & ctrl early setup +/* + * Lookup machine architecture + * r1 = machine architecture number + * Returns: + * r4 = physical address of page tables + * r5 = physical start address of RAM + * r6 = physical address of IO + * r7 = byte offset into page tables for IO + */ +__lookup_architecture_type: + cmp r1, #(__arch_types_end - __arch_types_start) / 16 + bge 1f + adr r4, __arch_types_start + add r4, r4, r1, lsl #4 + ldmia r4, {r4, r5, r6, r7} + add r4, r5, #SWAPPER_PGDIR_OFFSET + mov r7, r7, lsr #18 mov pc, lr - - @ ARM7 - .long 0x41007000 - .long 0xfffff000 - .long 0x00000c12 - b .Larmv3_flush_late @ arm v3 flush & ctrl late setup +1: mov r7, #0 mov pc, lr - @ ARM710 - .long 0x41007000 - .long 0xfff8f000 @ arm710 processors are weird - .long 0x00000c12 - b .Larmv3_flush_late @ arm v3 flush & ctrl late setup - mov pc, lr +/* + * Machine parameters. Each machine requires 4 words, which are: + * + * word0: unused + * word1: physical start address of RAM + * word2: physical start address of IO + * word3: virtual start address of IO + * + * The IO mappings entered here are used to set up mappings + * required for debugging information to be shown to the user. + * paging_init() does the real page table initialisation. + */ + @ 0x00 - DEC EBSA110 +__arch_types_start: + .long 0 + .long 0 + .long 0xe0000000 + .long 0xe0000000 - @ StrongARM-110 and StrongARM-1100 - .long 0x4401a100 @ 4401a100 and 4401a110 - .long 0xffffffe0 - .long 0x00000c02 - b .Larmv4_flush_early - b .Lsa_fastclock + @ 0x01 - Acorn RiscPC + .long 0 + .long 0x10000000 + .long 0x03000000 + .long 0xe0000000 + @ 0x02 - Unused + .long 0 .long 0 - .align + .long 0xe0000000 + .long 0xe0000000 -.Larmv3_flush_early: - mov r0, #0 - mcr p15, 0, r0, c7, c0 @ flush caches on v3 - mcr p15, 0, r0, c5, c0 @ flush TLBs on v3 - mcr p15, 0, r4, c2, c0 @ load page table pointer - mov r0, #0x1f @ Domains 0, 1 = client - mcr p15, 0, r0, c3, c0 @ load domain access register -#ifdef CONFIG_ALIGNMENT_TRAP - mov r0, #0x3f @ ....S..DPWCAM -#else - mov r0, #0x3d @ ....S..DPWC.M -#endif - orr r0, r0, #0x100 - mov pc, lr + @ 0x03 - NexusPCI + .long 0 + .long 0x40000000 + .long 0x10000000 + .long 0xe0000000 -.Larmv3_flush_late: - mov r0, #0 - mcr p15, 0, r0, c7, c0 @ flush caches on v3 - mcr p15, 0, r0, c5, c0 @ flush TLBs on v3 - mcr p15, 0, r4, c2, c0 @ load page table pointer - mov r0, #0x1f @ Domains 0, 1 = client - mcr p15, 0, r0, c3, c0 @ load domain access register -#ifdef CONFIG_ALIGNMENT_TRAP - mov r0, #0x7f @ ....S.LDPWCAM -#else - mov r0, #0x7d @ ....S.LDPWC.M -#endif - orr r0, r0, #0x100 - mov pc, lr + @ 0x04 - DEC EBSA285 + .long 0 + .long 0 + .long 0x24000000 @ I/O base address (0x42000000 -> 0xfe000000) + .long 0xe0000000 -.Larmv4_flush_early: - mov r0, #0 - mcr p15, 0, r0, c7, c7 @ flush I,D caches on v4 - mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4 - mcr p15, 0, r0, c8, c7 @ flush I,D TLBs on v4 - mcr p15, 0, r4, c2, c0 @ load page table pointer - mov r0, #0x1f @ Domains 0, 1 = client - mcr p15, 0, r0, c3, c0 @ load domain access register - mrc p15, 0, r0, c1, c0 @ get control register v4 - bic r0, r0, #0x0e00 - bic r0, r0, #0x0002 -#ifdef CONFIG_ALIGNMENT_TRAP - orr r0, r0, #0x003f @ I...S..DPWCAM -#else - orr r0, r0, #0x003d @ I...S..DPWC.M -#endif - orr r0, r0, #0x1100 @ v4 supports separate I cache - mov pc, lr + @ 0x05 - Rebel.com NetWinder + .long 0 + .long 0 + .long 0x24000000 @ I/O base address (0x42000000 -> 0xfe000000) + .long 0xe0000000 -.Lsa_fastclock: mcr p15, 0, r4, c15, c1, 2 @ Enable clock switching - mov pc, lr + @ 0x06 - CATS + .long 0 + .long 0 + .long 0x24000000 @ I/O base address (0x42000000 -> 0xfe000000) + .long 0xe0000000 -.LC0: .long SYMBOL_NAME(__entry) - .long SYMBOL_NAME(__machine_arch_type) - .long SYMBOL_NAME(__bss_start) - .long SYMBOL_NAME(processor_id) - .long SYMBOL_NAME(_end) - .long SYMBOL_NAME(cr_alignment) - .long SYMBOL_NAME(init_task_union)+8192 - .align - -.Lalready_done_mmap: - adr r4, .LC0 - ldmia r4, {r3, r4, r5, r6, r7, r8, sp} @ Setup stack - add r10, r10, r3 @ Add base back in - mov fp, #0 -1: cmp r5, r7 @ Clear BSS - strcc fp, [r5],#4 - bcc 1b + @ 0x07 - tbox + .long 0 + .long 0x80000000 + .long 0x00400000 @ Uart + .long 0xe0000000 - bic r2, r0, #2 @ Clear 'A' bit - stmia r8, {r0, r2} @ Save control register values + @ 0x08 - DEC EBSA285 as co-processor + .long 0 + .long 0 + .long DC21285_ARMCSR_BASE @ Physical I/O base address + .long 0x7cf00000 @ Virtual I/O base address - 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) + @ 0x09 - CL-PS7110 + .long 0 + .long 0 + .long 0 + .long 0 - .text + @ 0x0a - Acorn Archimedes + .long 0 + .long 0 + .long 0 + .long 0 -#ifdef CONFIG_DEBUG_LL -/* - * Some debugging routines (useful if you've got MM problems and - * printk isn't working). For DEBUGGING ONLY!!! Do not leave - * references to these in a production kernel! - */ -#if defined(CONFIG_ARCH_RPC) - .macro addruart,rx - mov \rx, #0xe0000000 - orr \rx, \rx, #0x00010000 - orr \rx, \rx, #0x00000fe0 - .endm - - .macro senduart,rd,rx - strb \rd, [\rx] - .endm - - .macro busyuart,rd,rx -1002: ldrb \rd, [\rx, #0x14] - and \rd, \rd, #0x60 - teq \rd, #0x60 - bne 1002b - .endm - - .macro waituart,rd,rx -1001: ldrb \rd, [\rx, #0x18] - tst \rd, #0x10 - beq 1001b - .endm - -#elif defined(CONFIG_ARCH_EBSA110) - .macro addruart,rx - mov \rx, #0xf0000000 - orr \rx, \rx, #0x00000be0 - .endm - - .macro senduart,rd,rx - strb \rd, [\rx] - .endm - - .macro busyuart,rd,rx -1002: ldrb \rd, [\rx, #0x14] - and \rd, \rd, #0x60 - teq \rd, #0x60 - bne 1002b - .endm - - .macro waituart,rd,rx -1001: ldrb \rd, [\rx, #0x18] - tst \rd, #0x10 - beq 1001b - .endm - -#elif defined(CONFIG_HOST_FOOTBRIDGE) || defined(CONFIG_ADDIN_FOOTBRIDGE) -#ifndef CONFIG_DEBUG_DC21285_PORT - /* For NetWinder debugging */ - .macro addruart,rx - mov \rx, #0xff000000 - orr \rx, \rx, #0x000003f8 - .endm - - .macro senduart,rd,rx - strb \rd, [\rx] - .endm - - .macro busyuart,rd,rx -1002: ldrb \rd, [\rx, #0x5] - and \rd, \rd, #0x60 - teq \rd, #0x60 - bne 1002b - .endm - - .macro waituart,rd,rx -1001: ldrb \rd, [\rx, #0x6] - tst \rd, #0x10 - beq 1001b - .endm -#else - /* For EBSA285 debugging */ - .equ dc21285_high, ARMCSR_BASE & 0xff000000 - .equ dc21285_low, ARMCSR_BASE & 0x00ffffff - - .macro addruart,rx - mov \rx, #dc21285_high - .if dc21285_low - orr \rx, \rx, #dc21285_low - .endif - .endm - - .macro senduart,rd,rx - str \rd, [\rx, #0x160] @ UARTDR - .endm - - .macro busyuart,rd,rx -1001: ldr \rd, [\rx, #0x178] @ UARTFLG - tst \rd, #1 << 3 - bne 1001b - .endm - - .macro waituart,rd,rx - .endm -#endif -#elif defined(CONFIG_ARCH_NEXUSPCI) - .macro addruart,rx - ldr \rx, =0xfff00000 - .endm - - .macro senduart,rd,rx - str \rd, [\rx, #0xc] - .endm - - .macro busyuart,rd,rx -1001: ldr \rd, [\rx, #0x4] - tst \rd, #1 << 0 - bne 1001b - .endm - - .macro waituart,rd,rx - .endm -#else -#error Unknown architecture -#endif + @ 0x0b - Acorn A5000 + .long 0 + .long 0 + .long 0 + .long 0 -/* - * Useful debugging routines - */ -ENTRY(printhex8) - mov r1, #8 - b printhex - -ENTRY(printhex4) - mov r1, #4 - b printhex - -ENTRY(printhex2) - mov r1, #2 -printhex: ldr r2, =hexbuf - add r3, r2, r1 - mov r1, #0 - strb r1, [r3] -1: and r1, r0, #15 - mov r0, r0, lsr #4 - cmp r1, #10 - addlt r1, r1, #'0' - addge r1, r1, #'a' - 10 - strb r1, [r3, #-1]! - teq r3, r2 - bne 1b - mov r0, r2 - b printascii - - .ltorg - -ENTRY(printascii) - addruart r3 - b 2f -1: waituart r2, r3 - senduart r1, r3 - busyuart r2, r3 - teq r1, #'\n' - moveq r1, #'\r' - beq 1b -2: teq r0, #0 - ldrneb r1, [r0], #1 - teqne r1, #0 - bne 1b - mov pc, lr + @ 0x0c - Etoile + .long 0 + .long 0 + .long 0 + .long 0 -ENTRY(printch) - addruart r3 - mov r1, r0 - mov r0, #0 - b 1b + @ 0x0d - LaCie_NAS + .long 0 + .long 0 + .long 0 + .long 0 - .bss -hexbuf: .space 16 + @ 0x0e - CL-PS7500 + .long 0 + .long 0 + .long 0 + .long 0 -#endif + @ 0x0f - Shark + .long 0 + .long 0 + .long 0 + .long 0 +__arch_types_end: + @ unknown - SA1100 + .long 0 + .long 0xc0000000 + .long 0x80000000 + .long 0xe0000000 diff --git a/arch/arm/kernel/hw-footbridge.c b/arch/arm/kernel/hw-footbridge.c index 54a64b811..117011e1d 100644 --- a/arch/arm/kernel/hw-footbridge.c +++ b/arch/arm/kernel/hw-footbridge.c @@ -25,269 +25,8 @@ #include <asm/system.h> #define IRDA_IO_BASE 0x180 -#define ETHER10_IO_BASE 0x301 #define GP1_IO_BASE 0x338 #define GP2_IO_BASE 0x33a -#define DEC21143_IO_BASE 0x401 -#define DEC21143_MEM_BASE 0x00800000 -#define CYBER2000_MEM_BASE 0x01000000 - -int have_isa_bridge; - -extern int setup_arm_irq(int, struct irqaction *); -extern void pci_set_cmd(struct pci_dev *dev, unsigned short clear, unsigned short set); -extern void pci_set_base_addr(struct pci_dev *dev, int idx, unsigned int addr); -extern void pci_set_irq_line(struct pci_dev *dev, unsigned int irq); -extern void (*kd_mksound)(unsigned int hz, unsigned int ticks); - -#ifdef CONFIG_PCI - -static int irqmap_ebsa[] __initdata = { IRQ_IN1, IRQ_IN0, IRQ_PCI, IRQ_IN3 }; - -static int __init ebsa_irqval(struct pci_dev *dev) -{ - unsigned char pin; - - pcibios_read_config_byte(dev->bus->number, - dev->devfn, - PCI_INTERRUPT_PIN, - &pin); - - return irqmap_ebsa[(PCI_SLOT(dev->devfn) + pin) & 3]; -} - -#ifdef CONFIG_CATS -static int irqmap_cats[] __initdata = { IRQ_PCI, IRQ_IN0, IRQ_IN1, IRQ_IN3 }; - -static int __init cats_irqval(struct pci_dev *dev) -{ - if (dev->irq >= 128) - return 16 + (dev->irq & 0x1f); - - switch (dev->irq) { - case 1: - case 2: - case 3: - case 4: - return irqmap_cats[dev->irq - 1]; - case 0: - return 0; - } - - printk("PCI: device %02x:%02x has unknown irq line %x\n", - dev->bus->number, dev->devfn, dev->irq); - return 0; -} -#endif - -void __init pcibios_fixup_ebsa285(struct pci_dev *dev) -{ - /* Latency timer of 32 */ - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 32); - - /* 32-byte cache line size */ - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 8); - - /* Set SysErr enable, Parity enable */ - pci_set_cmd(dev, 0, PCI_COMMAND_FAST_BACK | PCI_COMMAND_SERR | PCI_COMMAND_PARITY); - - /* If this device is an ISA bridge, set the - * have_isa_bridge flag. We will then go looking - * for things like keyboard, etc - */ - if ((dev->class >> 8) == PCI_CLASS_BRIDGE_ISA || - (dev->class >> 8) == PCI_CLASS_BRIDGE_EISA) - have_isa_bridge = !0; - - /* sort out the irq mapping for this device */ - switch (machine_arch_type) { - case MACH_TYPE_EBSA285: - dev->irq = ebsa_irqval(dev); - /* Turn on bus mastering - boot loader doesn't - * - perhaps it should! - dag - */ - pci_set_cmd(dev, 0, PCI_COMMAND_MASTER); - break; - -#ifdef CONFIG_CATS - case MACH_TYPE_CATS: - dev->irq = cats_irqval(dev); - /* Turn on bus mastering - boot loader doesn't - * - perhaps it should! - dag - */ - pci_set_cmd(dev, 0, PCI_COMMAND_MASTER); - break; -#endif -#ifdef CONFIG_ARCH_NETWINDER - case MACH_TYPE_NETWINDER: - /* disable ROM */ - pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0); - -#define DEV(v,d) ((v)<<16|(d)) - switch (DEV(dev->vendor, dev->device)) { - /* Ether 100 */ - case DEV(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142): - pci_set_base_addr(dev, 0, DEC21143_IO_BASE); - pci_set_base_addr(dev, 1, DEC21143_MEM_BASE); - pci_set_cmd(dev, 0, PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO); - /* Put the chip to sleep in case the driver isn't loaded */ - pci_write_config_dword(dev, 0x40, 0x80000000); - dev->irq = IRQ_NETWINDER_ETHER100; - break; - - /* Ether 10 */ - case DEV(PCI_VENDOR_ID_WINBOND2,0x5a5a): - pci_set_base_addr(dev, 0, ETHER10_IO_BASE); - pci_set_cmd(dev, PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY, PCI_COMMAND_IO); - dev->irq = IRQ_NETWINDER_ETHER10; - break; - - /* ISA bridge */ - case DEV(PCI_VENDOR_ID_WINBOND,PCI_DEVICE_ID_WINBOND_83C553): - pci_set_base_addr(dev, 0, 0); - pci_set_cmd(dev, PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY, PCI_COMMAND_IO); - /* - * Enable all memory requests from ISA to be channeled to PCI - */ - pci_write_config_byte(dev, 0x48, 255); - /* - * Disable ping-pong (as per errata) - */ - pci_write_config_byte(dev, 0x42, 0); - /* - * Enable PCI packet retry - */ - pci_write_config_byte(dev, 0x40, 0x22); - /* - * Do not use PCI CPU park enable, park on - * last master, disable GAT bit - */ - pci_write_config_byte(dev, 0x83, 0x02); - /* - * Default rotating priorities - */ - pci_write_config_byte(dev, 0x80, 0xe0); - /* - * Rotate bank 4 - */ - pci_write_config_byte(dev, 0x81, 0x01); - break; - - /* IDE */ - case DEV(PCI_VENDOR_ID_WINBOND,PCI_DEVICE_ID_WINBOND_82C105): - pci_set_base_addr(dev, 0, 0x1f1); - pci_set_base_addr(dev, 1, 0x3f5); - pci_set_base_addr(dev, 2, 0x171); - pci_set_base_addr(dev, 3, 0x375); - pci_set_base_addr(dev, 4, 0xe801); - pci_set_cmd(dev, PCI_COMMAND_MEMORY, PCI_COMMAND_MASTER | PCI_COMMAND_IO); - dev->irq = IRQ_ISA_HARDDISK1; - break; - - /* VGA */ - case DEV(PCI_VENDOR_ID_INTERG,0x2000): - pci_set_base_addr(dev, 0, CYBER2000_MEM_BASE); - pci_set_cmd(dev, PCI_COMMAND_MASTER, PCI_COMMAND_IO | PCI_COMMAND_MEMORY); - dev->irq = IRQ_NETWINDER_VGA; - break; - } -#endif - } -} - -static inline void -report_pci_dev_error(void) -{ - struct pci_dev *dev; - - for (dev = pci_devices; dev; dev = dev->next) { - unsigned short status; - - pci_read_config_word(dev, PCI_STATUS, &status); - if (status & 0xf900) { - printk(KERN_DEBUG "PCI: [%04X:%04X] status = %X\n", - dev->vendor, dev->device, status); - - pci_write_config_word(dev, PCI_STATUS, status & 0xf900); - } - } -} -#else -#define report_pci_dev_error() -#endif - -/* - * Warn on PCI errors. Please report any occurances! - */ -static void -irq_pci_err(int irq, void *dev_id, struct pt_regs *regs) -{ - static unsigned long next_warn; - unsigned long cmd = *CSR_PCICMD & 0x0000ffff; - unsigned long ctrl = (*CSR_SA110_CNTL) & 0xffffde07; - unsigned long irqstatus = *CSR_IRQ_RAWSTATUS; - int warn = time_after_eq(jiffies, next_warn); - - ctrl |= SA110_CNTL_DISCARDTIMER; - - if (warn) { - next_warn = jiffies + 3 * HZ / 100; - printk(KERN_DEBUG "PCI: "); - } - - if (irqstatus & (1 << 31)) { - if (warn) - printk("parity error "); - cmd |= 1 << 31; - } - - if (irqstatus & (1 << 30)) { - if (warn) - printk("target abort "); - cmd |= 1 << 28; - } - - if (irqstatus & (1 << 29)) { - if (warn) - printk("master abort "); - cmd |= 1 << 29; - } - - if (irqstatus & (1 << 28)) { - if (warn) - printk("data parity error "); - cmd |= 1 << 24; - } - - if (irqstatus & (1 << 27)) { - if (warn) - printk("discard timer expired "); - ctrl &= ~SA110_CNTL_DISCARDTIMER; - } - - if (irqstatus & (1 << 23)) { - if (warn) - printk("system error "); - ctrl |= SA110_CNTL_RXSERR; - } - - if (warn) - printk("pc=[<%08lX>]\n", instruction_pointer(regs)); - - report_pci_dev_error(); - - *CSR_PCICMD = cmd; - *CSR_SA110_CNTL = ctrl; -} - -static struct irqaction irq_pci_error = { - irq_pci_err, SA_INTERRUPT, 0, "PCI error", NULL, NULL -}; - -void __init pcibios_init_ebsa285(void) -{ - setup_arm_irq(IRQ_PCI_ERR, &irq_pci_error); -} /* * Netwinder stuff @@ -627,7 +366,7 @@ void __netwinder_text cpld_modify(int mask, int set) current_cpld = (current_cpld & ~mask) | set; - gpio_modify_io(GPIO_DATA, 0); + gpio_modify_io(GPIO_DATA | GPIO_IOCLK | GPIO_IOLOAD, 0); gpio_modify_op(GPIO_IOLOAD, 0); for (msk = 8; msk; msk >>= 1) { @@ -647,7 +386,7 @@ static void __init cpld_init(void) unsigned long flags; spin_lock_irqsave(&gpio_lock, flags); - cpld_modify(-1, CPLD_UNMUTE | 4); + cpld_modify(-1, CPLD_UNMUTE | CPLD_7111_DISABLE); spin_unlock_irqrestore(&gpio_lock, flags); } @@ -713,12 +452,15 @@ static inline void rwa010_global_init(void) dprintk("Card no = %d\n", inb(0x203)); + /* disable the modem section of the chip */ WRITE_RWA(7, 3); WRITE_RWA(0x30, 0); + /* disable the cdrom section of the chip */ WRITE_RWA(7, 4); WRITE_RWA(0x30, 0); + /* disable the MPU-401 section of the chip */ WRITE_RWA(7, 2); WRITE_RWA(0x30, 0); } @@ -925,6 +667,7 @@ void __init hw_init(void) extern void register_isa_ports(unsigned int, unsigned int, unsigned int); register_isa_ports(DC21285_PCI_MEM, DC21285_PCI_IO, 0); + #ifdef CONFIG_ARCH_NETWINDER /* * this ought to have a better home... diff --git a/arch/arm/kernel/init_task.c b/arch/arm/kernel/init_task.c index e3853f3d5..1a379ee10 100644 --- a/arch/arm/kernel/init_task.c +++ b/arch/arm/kernel/init_task.c @@ -1,4 +1,5 @@ #include <linux/mm.h> +#include <linux/fs.h> #include <linux/sched.h> #include <asm/uaccess.h> diff --git a/arch/arm/kernel/ioport.c b/arch/arm/kernel/ioport.c index bae897747..d40ea1cf1 100644 --- a/arch/arm/kernel/ioport.c +++ b/arch/arm/kernel/ioport.c @@ -9,10 +9,12 @@ #include <linux/errno.h> #include <linux/types.h> #include <linux/ioport.h> +#include <linux/mm.h> #include <asm/pgtable.h> #include <asm/uaccess.h> +#ifdef CONFIG_CPU_32 asmlinkage int sys_iopl(unsigned long turn_on) { if (turn_on && !capable(CAP_SYS_RAWIO)) @@ -25,3 +27,9 @@ asmlinkage int sys_iopl(unsigned long turn_on) return 0; } +#else +asmlinkage int sys_iopl(unsigned long turn_on) +{ + return -ENOSYS; +} +#endif diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 41e2050e6..f6c310905 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -494,8 +494,5 @@ void __init init_IRQ(void) } irq_init_irq(); -#ifdef CONFIG_ARCH_ACORN - init_FIQ(); -#endif init_dma(); } diff --git a/arch/arm/kernel/leds-footbridge.c b/arch/arm/kernel/leds-footbridge.c index 6b4cb001b..90f2fe109 100644 --- a/arch/arm/kernel/leds-footbridge.c +++ b/arch/arm/kernel/leds-footbridge.c @@ -138,7 +138,7 @@ static void __netwinder_text netwinder_leds_event(led_event_t evt) switch (evt) { case led_start: led_state |= LED_STATE_ENABLED; - hw_led_state = 0; + hw_led_state = GPIO_GREEN_LED; break; case led_stop: @@ -223,26 +223,20 @@ static void dummy_leds_event(led_event_t evt) { } -void __init +static void __init init_leds_event(led_event_t evt) { - switch (machine_arch_type) { + leds_event = dummy_leds_event; + #ifdef CONFIG_FOOTBRIDGE - case MACH_TYPE_EBSA285: - case MACH_TYPE_CO285: + if (machine_is_ebsa285() || machine_is_co285()) leds_event = ebsa285_leds_event; - break; #endif #ifdef CONFIG_ARCH_NETWINDER - case MACH_TYPE_NETWINDER: + if (machine_is_netwinder()) leds_event = netwinder_leds_event; - break; #endif - default: - leds_event = dummy_leds_event; - } - leds_event(evt); } diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 776dc9b88..ab92aae52 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -1,7 +1,7 @@ /* * linux/arch/arm/kernel/process.c * - * Copyright (C) 1996 Russell King - Converted to ARM. + * Copyright (C) 1996-1999 Russell King - Converted to ARM. * Origional Copyright (C) 1995 Linus Torvalds */ @@ -32,6 +32,7 @@ #include <asm/uaccess.h> #include <asm/system.h> +#include <asm/arch/system.h> #include <asm/io.h> extern char *processor_modes[]; @@ -60,26 +61,38 @@ void cpu_idle(void) current->priority = 0; current->counter = -100; while (1) { - if (!current->need_resched && !hlt_counter) - proc_idle(); - schedule(); + if (!hlt_counter) + arch_do_idle(); + if (current->need_resched) { + schedule(); #ifndef CONFIG_NO_PGT_CACHE - check_pgt_cache(); + check_pgt_cache(); #endif + } } } static char reboot_mode = 'h'; -void __init reboot_setup(char *str, int *ints) +int __init reboot_setup(char *str) { reboot_mode = str[0]; + return 0; } +__setup("reboot=", reboot_setup); + void machine_restart(char * __unused) { + /* + * Turn off caches, interrupts, etc + */ + cpu_proc_fin(); + arch_reset(reboot_mode); - panic("Reboot failed\n"); + + printk("Reboot failed -- System halted\n"); + while (1); } @@ -135,6 +148,35 @@ void show_regs(struct pt_regs * regs) #endif } +void show_fpregs(struct user_fp *regs) +{ + int i; + + for (i = 0; i < 8; i++) { + unsigned long *p; + char type; + + p = (unsigned long *)(regs->fpregs + i); + + switch (regs->ftype[i]) { + case 1: type = 'f'; break; + case 2: type = 'd'; break; + case 3: type = 'e'; break; + default: type = '?'; break; + } + if (regs->init_flag) + type = '?'; + + printk(" f%d(%c): %08lx %08lx %08lx%c", + i, type, p[0], p[1], p[2], i & 1 ? '\n' : ' '); + } + + + printk("FPSR: %08lx FPCR: %08lx\n", + (unsigned long)regs->fpsr, + (unsigned long)regs->fpcr); +} + /* * Task structure and kernel stack allocation. * @@ -206,6 +248,7 @@ void exit_thread(void) void flush_thread(void) { memset(¤t->thread.debug, 0, sizeof(current->thread.debug)); + memset(¤t->thread.fpstate, 0, sizeof(current->thread.fpstate)); current->used_math = 0; current->flags &= ~PF_USEDFPU; } @@ -237,12 +280,10 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, */ int dump_fpu (struct pt_regs *regs, struct user_fp *fp) { - int fpvalid = 0; - if (current->used_math) - memcpy (fp, ¤t->thread.fpstate.soft, sizeof (fp)); + memcpy(fp, ¤t->thread.fpstate.soft, sizeof (fp)); - return fpvalid; + return current->used_math; } /* @@ -281,6 +322,7 @@ void dump_thread(struct pt_regs * regs, struct user * dump) */ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) { + extern long sys_exit(int) __attribute__((noreturn)); pid_t __ret; __asm__ __volatile__( diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 6104b4dbe..0692d1a6c 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -447,8 +447,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) unsigned long tmp; ret = read_long(child, addr, &tmp); - if (ret) - put_user(tmp, (unsigned long *) data); + if (!ret) + ret = put_user(tmp, (unsigned long *) data); goto out; } diff --git a/arch/arm/kernel/semaphore.c b/arch/arm/kernel/semaphore.c index 1bb21be3f..71bf85e09 100644 --- a/arch/arm/kernel/semaphore.c +++ b/arch/arm/kernel/semaphore.c @@ -8,6 +8,7 @@ * Modified for ARM by Russell King */ #include <linux/sched.h> +#include <linux/errno.h> #include <asm/semaphore.h> diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 8258bd767..b09b3798b 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -10,36 +10,27 @@ */ #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/blk.h> -#include <linux/init.h> #include <linux/console.h> +#include <linux/init.h> #include <asm/elf.h> #include <asm/hardware.h> #include <asm/io.h> -#include <asm/pgtable.h> #include <asm/procinfo.h> -#include <asm/segment.h> #include <asm/setup.h> #include <asm/system.h> +#ifndef MEM_SIZE #define MEM_SIZE (16*1024*1024) -#define COMMAND_LINE_SIZE 256 +#endif #ifndef CONFIG_CMDLINE #define CONFIG_CMDLINE "" @@ -50,7 +41,6 @@ #endif extern void reboot_setup(char *str, int *ints); -extern void fpe_init(void); extern void disable_hlt(void); struct drive_info_struct { char dummy[32]; } drive_info; @@ -64,10 +54,9 @@ struct screen_info screen_info = { }; extern int root_mountflags; -extern int _etext, _edata, _end; +extern int _text, _etext, _edata, _end; unsigned char aux_device_present; - char elf_platform[ELF_PLATFORM_SIZE]; unsigned int elf_hwcap; @@ -76,13 +65,16 @@ unsigned int elf_hwcap; */ unsigned int processor_id; unsigned int __machine_arch_type; +unsigned int vram_size; +unsigned int system_rev; +unsigned int system_serial_low; +unsigned int system_serial_high; #ifdef MULTI_CPU struct processor processor; #endif #ifdef CONFIG_ARCH_ACORN -int memc_ctrl_reg; -int number_mfm_drives; -unsigned int vram_size; +unsigned int memc_ctrl_reg; +unsigned int number_mfm_drives; #endif static struct proc_info_item proc_info; @@ -95,39 +87,41 @@ static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', ' * symbol to be empty if not configured. */ -/* - * initial ram disk - */ -#ifdef CONFIG_BLK_DEV_INITRD -static void __init -check_initrd(unsigned long mem_start, unsigned long mem_end) +static void __init setup_processor(void) { - if (initrd_end > mem_end) { - printk ("initrd extends beyond end of memory " - "(0x%08lx > 0x%08lx) - disabling initrd\n", - initrd_end, mem_end); - initrd_start = 0; - } -} + extern struct proc_info_list __proc_info_begin, __proc_info_end; + struct proc_info_list *list; -#else -#define check_initrd(ms,me) -#endif + /* + * locate processor in the list of supported processor + * types. The linker builds this table for us from the + * entries in arch/arm/mm/proc-*.S + */ + for (list = &__proc_info_begin; list < &__proc_info_end ; list++) + if ((processor_id & list->cpu_mask) == list->cpu_val) + break; -void __init -setup_processor(void) -{ - armidindex = 0; + /* + * If processor type is unrecognised, then we + * can do nothing... + */ + if (list >= &__proc_info_end) { + printk("CPU configuration botched (ID %08x), unable " + "to continue.\n", processor_id); + while (1); + } - while ((armidlist[armidindex].id ^ processor_id) & - armidlist[armidindex].mask) - armidindex += 1; + proc_info = *list->info; - if (armidlist[armidindex].id == 0) - while (1); +#ifdef MULTI_CPU + processor = *list->proc; +#endif - processor = *armidlist[armidindex].proc; - processor._proc_init(); + sprintf(system_utsname.machine, "%s%c", list->arch_name, ENDIANNESS); + sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS); + elf_hwcap = list->elf_hwcap; + + cpu_proc_init(); } static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; @@ -135,12 +129,13 @@ static char command_line[COMMAND_LINE_SIZE] = { 0, }; char saved_command_line[COMMAND_LINE_SIZE]; static void __init -setup_mem(char *cmd_line, unsigned long *mem_start, unsigned long *mem_sz) +setup_mem(char *cmd_line, unsigned long *mem_sz) { char c = ' ', *to = command_line; int len = 0; - *mem_start = (unsigned long)&_end; + if (!*mem_sz) + *mem_sz = MEM_SIZE; for (;;) { if (c == ' ') { @@ -181,24 +176,27 @@ setup_mem(char *cmd_line, unsigned long *mem_start, unsigned long *mem_sz) } static void __init -setup_ram(int doload, int prompt, int image_start) +setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz) { #ifdef CONFIG_BLK_DEV_RAM extern int rd_doload; extern int rd_prompt; extern int rd_image_start; + extern int rd_size; rd_image_start = image_start; rd_prompt = prompt; rd_doload = doload; + + if (rd_sz) + rd_size = rd_sz; #endif } /* * initial ram disk */ -static void __init -setup_initrd(unsigned int start, unsigned int size) +static void __init setup_initrd(unsigned int start, unsigned int size) { #ifdef CONFIG_BLK_DEV_INITRD if (start) { @@ -211,30 +209,62 @@ setup_initrd(unsigned int start, unsigned int size) #endif } -#ifdef CONFIG_ARCH_ACORN -int memc_ctrl_reg; -int number_mfm_drives; -unsigned int vram_size; +static void __init check_initrd(unsigned long mem_end) +{ +#ifdef CONFIG_BLK_DEV_INITRD + if (initrd_end > mem_end) { + printk ("initrd extends beyond end of memory " + "(0x%08lx > 0x%08lx) - disabling initrd\n", + initrd_end, mem_end); + initrd_start = 0; + } #endif +} -#ifndef PARAMS_BASE -#define PARAMS_BASE NULL -#endif +/* + * Standard memory resources + */ +static struct resource system_ram = { "System RAM", 0, 0, IORESOURCE_MEM | IORESOURCE_BUSY }; +static struct resource video_ram = { "Video RAM", 0, 0, IORESOURCE_MEM }; +static struct resource kernel_code = { "Kernel code", 0, 0, IORESOURCE_MEM }; +static struct resource kernel_data = { "Kernel data", 0, 0, IORESOURCE_MEM }; +static struct resource lpt1 = { "reserved", 0x3bc, 0x3be, IORESOURCE_IO | IORESOURCE_BUSY }; +static struct resource lpt2 = { "reserved", 0x378, 0x37f, IORESOURCE_IO | IORESOURCE_BUSY }; +static struct resource lpt3 = { "reserved", 0x278, 0x27f, IORESOURCE_IO | IORESOURCE_BUSY }; + +static void __init request_standard_resources(unsigned long end) +{ + kernel_code.start = __virt_to_bus((unsigned long) &_text); + kernel_code.end = __virt_to_bus((unsigned long) &_etext - 1); + kernel_data.start = __virt_to_bus((unsigned long) &_etext); + kernel_data.end = __virt_to_bus((unsigned long) &_edata - 1); + system_ram.start = __virt_to_bus(PAGE_OFFSET); + system_ram.end = __virt_to_bus(end - 1); + + request_resource(&iomem_resource, &system_ram); + request_resource(&system_ram, &kernel_code); + request_resource(&system_ram, &kernel_data); + if (video_ram.start != video_ram.end) + request_resource(&iomem_resource, &video_ram); -static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } }; -#define ENDIANNESS ((char)endian_test.l) + /* + * Some machines don't have the possibility of ever + * possessing LPT1 (lp0) and LPT3 (lp2) + */ + if (machine_is_ebsa110() || machine_is_riscpc() || + machine_is_netwinder()) + request_resource(&ioport_resource, &lpt1); + if (machine_is_riscpc()) + request_resource(&ioport_resource, &lpt2); + if (machine_is_ebsa110() || machine_is_netwinder()) + request_resource(&ioport_resource, &lpt3); +} -void __init -setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * memory_end_p) +void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * memory_end_p) { struct param_struct *params = (struct param_struct *)PARAMS_BASE; - static unsigned char smptrap; unsigned long memory_end = 0; - char *from = NULL; - - if (smptrap == 1) - return; - smptrap = 1; + char *from = default_command_line; #if defined(CONFIG_ARCH_ARC) __machine_arch_type = MACH_TYPE_ARCHIMEDES; @@ -244,10 +274,11 @@ setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * mem setup_processor(); - init_mm.start_code = TASK_SIZE; - init_mm.end_code = TASK_SIZE + (unsigned long) &_etext; - init_mm.end_data = TASK_SIZE + (unsigned long) &_edata; - init_mm.brk = TASK_SIZE + (unsigned long) &_end; + /* + * Defaults + */ + ROOT_DEV = MKDEV(0, 255); + setup_ramdisk(1, 1, 0, 0); /* * Add your machine dependencies here @@ -256,14 +287,35 @@ setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * mem case MACH_TYPE_EBSA110: /* EBSA110 locks if we execute 'wait for interrupt' */ disable_hlt(); - if (params && params->u1.s.page_size != 4096) + if (params && params->u1.s.page_size != PAGE_SIZE) params = NULL; break; +#ifdef CONFIG_ARCH_ACORN +#ifdef CONFIG_ARCH_RPC case MACH_TYPE_RISCPC: /* RiscPC can't handle half-word loads and stores */ elf_hwcap &= ~HWCAP_HALF; + { + extern void init_dram_banks(struct param_struct *); + init_dram_banks(params); + } + + switch (params->u1.s.pages_in_vram) { + case 512: + vram_size += PAGE_SIZE * 256; + case 256: + vram_size += PAGE_SIZE * 256; + default: + break; + } +#endif + case MACH_TYPE_ARCHIMEDES: + case MACH_TYPE_A5K: + memc_ctrl_reg = params->u1.s.memc_control_reg; + number_mfm_drives = (params->u1.s.adfsdrives >> 3) & 3; break; +#endif case MACH_TYPE_EBSA285: if (params) { @@ -271,6 +323,8 @@ setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * mem 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; + video_ram.start = 0x0a0000; + video_ram.end = 0x0bffff; } break; @@ -288,53 +342,67 @@ setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * mem break; case MACH_TYPE_CATS: - /* CATS must use soft-reboot */ + /* CATS uses soft-reboot by default, since hard reboots + * fail on early boards. + */ reboot_setup("s", NULL); + params = NULL; + ORIG_VIDEO_LINES = 25; + ORIG_VIDEO_POINTS = 16; + ORIG_Y = 24; + video_ram.start = 0x0a0000; + video_ram.end = 0x0bffff; break; case MACH_TYPE_NETWINDER: /* * to be fixed in a future NeTTrom */ - if (params->u1.s.page_size == 4096) { + if (params->u1.s.page_size == PAGE_SIZE) { if (params->u1.s.nr_pages != 0x2000 && params->u1.s.nr_pages != 0x4000) { printk("Warning: bad NeTTrom parameters detected, using defaults\n"); - /* - * This stuff doesn't appear to be initialised - * properly by NeTTrom 2.0.6 and 2.0.7 - */ + /* + * This stuff doesn't appear to be initialised + * properly by NeTTrom 2.0.6 and 2.0.7 + */ params->u1.s.nr_pages = 0x2000; /* 32MB */ params->u1.s.ramdisk_size = 0; params->u1.s.flags = FLAG_READONLY; params->u1.s.initrd_start = 0; params->u1.s.initrd_size = 0; params->u1.s.rd_start = 0; - params->u1.s.video_x = 0; - params->u1.s.video_y = 0; - params->u1.s.video_num_cols = 80; - params->u1.s.video_num_rows = 30; } } else { printk("Warning: no NeTTrom parameter page detected, using " "compiled-in settings\n"); params = NULL; } + video_ram.start = 0x0a0000; + video_ram.end = 0x0bffff; break; default: break; } - if (params) { - memory_end = params->u1.s.page_size * - params->u1.s.nr_pages; + if (params && params->u1.s.page_size != PAGE_SIZE) { + printk("Warning: wrong page size configuration, " + "trying to continue\n"); + params = NULL; + } - ROOT_DEV = to_kdev_t(params->u1.s.rootdev); + if (params) { + memory_end = PAGE_SIZE * params->u1.s.nr_pages; + ROOT_DEV = to_kdev_t(params->u1.s.rootdev); + system_rev = params->u1.s.system_rev; + system_serial_low = params->u1.s.system_serial_low; + system_serial_high = params->u1.s.system_serial_high; - setup_ram((params->u1.s.flags & FLAG_RDLOAD) == 0, - (params->u1.s.flags & FLAG_RDPROMPT) == 0, - params->u1.s.rd_start); + setup_ramdisk((params->u1.s.flags & FLAG_RDLOAD) == 0, + (params->u1.s.flags & FLAG_RDPROMPT) == 0, + params->u1.s.rd_start, + params->u1.s.ramdisk_size); setup_initrd(params->u1.s.initrd_start, params->u1.s.initrd_size); @@ -342,57 +410,27 @@ setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * mem if (!(params->u1.s.flags & FLAG_READONLY)) root_mountflags &= ~MS_RDONLY; -#ifdef CONFIG_ARCH_ACORN -#ifdef CONFIG_ARCH_RPC - { - extern void init_dram_banks(struct param_struct *); - init_dram_banks(params); - } -#endif - - memc_ctrl_reg = params->u1.s.memc_control_reg; - number_mfm_drives = (params->u1.s.adfsdrives >> 3) & 3; - vram_size = 0; - - switch (params->u1.s.pages_in_vram) { - case 512: - vram_size += PAGE_SIZE * 256; - case 256: - vram_size += PAGE_SIZE * 256; - default: - break; - } - - memory_end -= vram_size; -#endif - from = params->commandline; - } else { - ROOT_DEV = to_kdev_t(0x00ff); - - setup_ram(1, 1, 0); - setup_initrd(0, 0); } - if (!memory_end) - memory_end = MEM_SIZE; - - if (!from) - from = default_command_line; - -#ifdef CONFIG_NWFPE - fpe_init(); -#endif - /* Save unparsed command line copy for /proc/cmdline */ memcpy(saved_command_line, from, COMMAND_LINE_SIZE); saved_command_line[COMMAND_LINE_SIZE-1] = '\0'; - setup_mem(from, memory_start_p, &memory_end); + setup_mem(from, &memory_end); memory_end += PAGE_OFFSET; - check_initrd(*memory_start_p, memory_end); + *cmdline_p = command_line; + init_mm.start_code = (unsigned long) &_text; + init_mm.end_code = (unsigned long) &_etext; + init_mm.end_data = (unsigned long) &_edata; + init_mm.brk = (unsigned long) &_end; + *memory_start_p = (unsigned long) &_end; + *memory_end_p = memory_end; + + request_standard_resources(memory_end); + check_initrd(memory_end); #ifdef CONFIG_VT #if defined(CONFIG_VGA_CONSOLE) @@ -401,40 +439,49 @@ setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * mem conswitchp = &dummy_con; #endif #endif - - *cmdline_p = command_line; - *memory_end_p = memory_end; } static const char *machine_desc[] = { - "EBSA110", - "Acorn-RiscPC", + /* Machine name Allocater */ + "EBSA110", /* RMK */ + "Acorn-RiscPC", /* RMK */ "unknown", - "Nexus-FTV/PCI", - "EBSA285", - "Rebel-NetWinder", - "Chalice-CATS", - "unknown-TBOX", - "co-EBSA285", - "CL-PS7110", - "Acorn-Archimedes", - "Acorn-A5000" + "Nexus-FTV/PCI", /* Philip Blundell */ + "EBSA285", /* RMK */ + "Rebel-NetWinder", /* RMK */ + "Chalice-CATS", /* Philip Blundell */ + "unknown-TBOX", /* Philip Blundell */ + "co-EBSA285", /* Mark van Doesburg */ + "CL-PS7110", /* Werner Almesberger */ + "Acorn-Archimedes", /* RMK/DAG */ + "Acorn-A5000", /* RMK/PB */ + "Etoile", /* Alex de Vries */ + "LaCie_NAS", /* Benjamin Herrenschmidt */ + "CL-PS7500", /* Philip Blundell */ + "Shark" /* Alexander Schulz */ }; int get_cpuinfo(char * buffer) { - int len; - - len = sprintf(buffer, - "Processor\t: %s %s rev %d (%s)\n" - "BogoMips\t: %lu.%02lu\n" - "Hardware\t: %s\n", - proc_info.manufacturer, - proc_info.cpu_name, - (int)processor_id & 15, - elf_platform, - (loops_per_sec+2500) / 500000, - ((loops_per_sec+2500) / 5000) % 100, - machine_desc[machine_arch_type]); - return len; + char *p = buffer; + + p += sprintf(p, "Processor\t: %s %s rev %d (%s)\n", + proc_info.manufacturer, proc_info.cpu_name, + (int)processor_id & 15, elf_platform); + + p += sprintf(p, "BogoMIPS\t: %lu.%02lu\n", + (loops_per_sec+2500) / 500000, + ((loops_per_sec+2500) / 5000) % 100); + + p += sprintf(p, "Hardware\t: %s\n", + machine_desc[machine_arch_type]); + + p += sprintf(p, "Revision\t: %04x\n", + system_rev); + + p += sprintf(p, "Serial\t\t: %08x%08x\n", + system_serial_high, + system_serial_low); + + return p - buffer; } diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index 7b2f430c1..3f86f4740 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -16,6 +16,8 @@ #include <linux/ptrace.h> #include <linux/unistd.h> #include <linux/stddef.h> +#include <linux/binfmts.h> +#include <linux/tty.h> #include <asm/ucontext.h> #include <asm/uaccess.h> @@ -550,6 +552,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) default: lock_kernel(); sigaddset(¤t->signal, signr); + recalc_sigpending(current); current->flags |= PF_SIGNALED; do_exit(exit_code); /* NOTREACHED */ diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c index 94f158b3e..3d39c8d39 100644 --- a/arch/arm/kernel/sys_arm.c +++ b/arch/arm/kernel/sys_arm.c @@ -19,6 +19,7 @@ #include <linux/shm.h> #include <linux/stat.h> #include <linux/mman.h> +#include <linux/fs.h> #include <linux/file.h> #include <linux/utsname.h> diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 9f9e6934f..da0d464f6 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -365,7 +365,6 @@ asmlinkage void baddataabort(int code, unsigned long instr, struct pt_regs *regs { pgd_t *pgd; - printk ("current->thread.memmap = %08lX\n", current->thread.memmap); pgd = pgd_offset(current->mm, addr); printk ("*pgd = %08lx", pgd_val (*pgd)); if (!pgd_none (*pgd)) { diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile index 7f5ff3012..9a22fe08f 100644 --- a/arch/arm/lib/Makefile +++ b/arch/arm/lib/Makefile @@ -1,11 +1,11 @@ # # linux/arch/arm/lib/Makefile # -# Copyright (C) 1995-1998 Russell King +# Copyright (C) 1995-1999 Russell King # L_TARGET := lib.a -L_OBJS := backtrace.o bitops.o checksum.o delay.o memcpy.o \ +L_OBJS := backtrace.o bitops.o checksum.o delay.o \ string.o system.o uaccess.o ifeq ($(PROCESSOR),armo) @@ -13,7 +13,7 @@ ifeq ($(PROCESSOR),armo) endif ifdef CONFIG_ARCH_ACORN - L_OBJS += loaders.o io-acorn.o + L_OBJS += io-acorn.o ifdef CONFIG_ARCH_A5K L_OBJS += floppydma.o endif @@ -34,13 +34,13 @@ endif include $(TOPDIR)/Rules.make +.S.o: + $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c -o $*.o $< + constants.h: getconsdata.o extractconstants.pl $(PERL) extractconstants.pl $(OBJDUMP) > $@ getconsdata.o: getconsdata.c $(CC) $(CFLAGS) -c getconsdata.c -checksum.o: constants.h - -%.o: %.S - $(CC) $(CFLAGS) -D__ASSEMBLY__ -c -o $@ $< +checksum.o string.o: constants.h diff --git a/arch/arm/lib/backtrace.S b/arch/arm/lib/backtrace.S index 3789d7d4d..fd85107c3 100644 --- a/arch/arm/lib/backtrace.S +++ b/arch/arm/lib/backtrace.S @@ -21,6 +21,11 @@ ENTRY(__backtrace) mov r0, fp ENTRY(c_backtrace) + +#ifndef CONFIG_FRAME_POINTER + mov pc, lr +#else + stmfd sp!, {r4 - r8, lr} @ Save an extra register so we have a location... #ifdef CONFIG_CPU_32 tst r1, #0x10 @ 26 or 32-bit? @@ -103,3 +108,5 @@ ENTRY(c_backtrace) .align .Ldsi: .word 0x00e92dd8 >> 2 .word 0x00e92d00 >> 2 + +#endif diff --git a/arch/arm/lib/checksum.S b/arch/arm/lib/checksum.S index daf49fc94..ae78b657a 100644 --- a/arch/arm/lib/checksum.S +++ b/arch/arm/lib/checksum.S @@ -74,8 +74,9 @@ ENTRY(csum_partial) stmfd sp!, {r1 - r2, r4 - r8, fp, ip, lr, pc} .endm -#define LOAD_REGS(cond) \ - LOADREGS(##cond##ea,fp,{r1 - r2, r4 - r8, fp, sp, pc}) + .macro load_regs,flags + ldm\flags fp, {r1, r2, r4-r8, fp, sp, pc} + .endm .macro load1b, reg1 9999: ldrbt \reg1, [r0], $1 @@ -134,8 +135,9 @@ ENTRY(csum_partial) mov r9, r9, lsr #24 .endm -#define LOAD_REGS(cond) \ - LOADREGS(##cond##ea,fp,{r1 - r2, r4 - r9, fp, sp, pc}) + .macro load_regs,flags + ldm\flags fp, {r1, r2, r4-r9, fp, sp, pc}^ + .endm .macro load1b, reg1 tst r9, #0x01 @@ -245,7 +247,7 @@ ENTRY(csum_partial_copy_from_user) adcs r3, r3, r4 4: ands r2, r2, #3 adceq r0, r3, #0 - LOAD_REGS(eq) + load_regs eqea load1l r4 tst r2, #2 beq .exit @@ -259,11 +261,11 @@ ENTRY(csum_partial_copy_from_user) andne r4, r4, #255 adcnes r3, r3, r4 adcs r0, r3, #0 - LOAD_REGS(al) + load_regs ea .too_small_user: teq r2, #0 - LOAD_REGS(eq) + load_regs eqea cmp r2, #2 blt .too_small_user1 load2b ip, r8 @@ -278,7 +280,7 @@ ENTRY(csum_partial_copy_from_user) strb ip, [r1], #1 adcs r3, r3, ip .csum_exit: adc r0, r3, #0 - LOAD_REGS(al) + load_regs ea .src_not_aligned_user: cmp r2, #4 @@ -331,7 +333,7 @@ ENTRY(csum_partial_copy_from_user) mov r4, r5, lsr #8 4: ands r2, r2, #3 adceq r0, r3, #0 - LOAD_REGS(eq) + load_regs eqea tst r2, #2 beq .exit adcs r3, r3, r4, lsl #16 @@ -384,7 +386,7 @@ ENTRY(csum_partial_copy_from_user) mov r4, r5, lsr #16 4: ands r2, r2, #3 adceq r0, r3, #0 - LOAD_REGS(eq) + load_regs eqea tst r2, #2 beq .exit adcs r3, r3, r4, lsl #16 @@ -437,7 +439,7 @@ ENTRY(csum_partial_copy_from_user) mov r4, r5, lsr #24 4: ands r2, r2, #3 adceq r0, r3, #0 - LOAD_REGS(eq) + load_regs eqea tst r2, #2 beq .exit adcs r3, r3, r4, lsl #16 @@ -461,7 +463,7 @@ ENTRY(csum_partial_copy_from_user) 6002: teq r2, r1 strneb r3, [r1], #1 bne 6002b - LOAD_REGS(al) + load_regs ea #if defined(CONFIG_CPU_32) .previous #endif diff --git a/arch/arm/lib/getconsdata.c b/arch/arm/lib/getconsdata.c index 9c317b639..5b46baad0 100644 --- a/arch/arm/lib/getconsdata.c +++ b/arch/arm/lib/getconsdata.c @@ -6,7 +6,7 @@ #include <linux/config.h> #include <linux/sched.h> #include <linux/mm.h> -#include <linux/unistd.h> + #include <asm/pgtable.h> #include <asm/uaccess.h> @@ -15,13 +15,6 @@ #define OFF_TSK(n) (unsigned long)&(((struct task_struct *)0)->n) #define OFF_MM(n) (unsigned long)&(((struct mm_struct *)0)->n) -#ifdef KERNEL_DOMAIN -unsigned long DOM_KERNELDOMAIN = KERNEL_DOMAIN; -#endif -#ifdef USER_DOMAIN -unsigned long DOM_USERDOMAIN = USER_DOMAIN; -#endif - unsigned long TSK_STATE = OFF_TSK(state); unsigned long TSK_FLAGS = OFF_TSK(flags); unsigned long TSK_NEED_RESCHED = OFF_TSK(need_resched); @@ -34,10 +27,7 @@ unsigned long PGD = OFF_MM(pgd); unsigned long TSS_SAVE = OFF_TSK(thread.save); unsigned long TSS_FPESAVE = OFF_TSK(thread.fpstate.soft.save); -#ifdef CONFIG_CPU_26 -unsigned long TSS_MEMMAP = OFF_TSK(thread.memmap); -unsigned long TSS_MEMCMAP = OFF_TSK(thread.memcmap); -#elif defined(CONFIG_CPU_32) +#ifdef CONFIG_CPU_32 unsigned long TSS_DOMAIN = OFF_TSK(thread.domain); #endif @@ -86,6 +76,8 @@ unsigned long LPTE_EXEC = L_PTE_EXEC; unsigned long LPTE_DIRTY = L_PTE_DIRTY; #endif +unsigned long PAGE_SZ = PAGE_SIZE; + unsigned long KSWI_BASE = 0x900000; unsigned long KSWI_SYS_BASE = 0x9f0000; unsigned long SYS_ERROR0 = 0x9f0000; diff --git a/arch/arm/lib/loaders.S b/arch/arm/lib/loaders.S deleted file mode 100644 index 760e2e311..000000000 --- a/arch/arm/lib/loaders.S +++ /dev/null @@ -1,53 +0,0 @@ -/* - * linux/arch/arm/lib/loaders.S - * - * This file contains the ROM loaders for buggy cards - */ -#include <linux/linkage.h> -#include <asm/assembler.h> - -/* - * Oak SCSI - */ - -ENTRY(oak_scsi_loader) - b Loak_scsi_read - .word 0 -Loak_scsi_reset: bic r10, r11, #0x00ff0000 - ldr r2, [r10] - RETINSTR(mov,pc,lr) - -Loak_scsi_read: mov r2, r1, lsr #3 - and r2, r2, #15 << 9 - bic r10, r11, #0x00ff0000 - ldr r2, [r10, r2] - mov r2, r1, lsl #20 - ldrb r0, [r11, r2, lsr #18] - ldr r2, [r10] - RETINSTR(mov,pc,lr) - -ENTRY(atomwide_serial_loader) - b Latomwide_serial_read - .word 0 -Latomwide_serial_reset: mov r2, #0x3c00 - strb r2, [r11, r2] - RETINSTR(mov,pc,lr) - -Latomwide_serial_read: cmp r1, #0x8000 - RETINSTR(movhi,pc,lr) - add r0, r1, #0x800 - mov r0, r0, lsr #11 - mov r3, #0x3c00 - strb r0, [r11, r3] - mov r2, r1, lsl #21 - ldrb r0, [r11, r2, lsr #19] - strb r2, [r11, r3] - RETINSTR(mov,pc,lr) - -/* - * Cards we don't know about yet - */ -ENTRY(noloader) - mov r0, r0 - mov r0, #0 - RETINSTR(mov,pc,lr) diff --git a/arch/arm/lib/memcpy.S b/arch/arm/lib/memcpy.S deleted file mode 100644 index f26e6cb1c..000000000 --- a/arch/arm/lib/memcpy.S +++ /dev/null @@ -1,319 +0,0 @@ -/* - * linux/arch/arm/lib/segment.S - * - * Copyright (C) 1995, 1996 Russell King - * Except memcpy/memmove routine. - */ - -#include <asm/assembler.h> -#include <linux/linkage.h> - -#ifndef ENTRY -#define ENTRY(x...) \ - .globl _##x; \ -_##x: -#endif - - .text -#define ENTER \ - mov ip,sp ;\ - stmfd sp!,{r4-r9,fp,ip,lr,pc} ;\ - sub fp,ip,#4 - -#define EXIT \ - LOADREGS(ea, fp, {r4 - r9, fp, sp, pc}) - -#define EXITEQ \ - LOADREGS(eqea, fp, {r4 - r9, fp, sp, pc}) - -# Prototype: void memcpy(void *to,const void *from,unsigned long n); -# ARM3: cant use memcopy here!!! - -ENTRY(memcpy) -ENTRY(memmove) - ENTER - cmp r1, r0 - bcc 19f - subs r2, r2, #4 - blt 6f - ands ip, r0, #3 - bne 7f - ands ip, r1, #3 - bne 8f - -1: subs r2, r2, #8 - blt 5f - subs r2, r2, #0x14 - blt 3f -2: ldmia r1!,{r3 - r9, ip} - stmia r0!,{r3 - r9, ip} - subs r2, r2, #32 - bge 2b - cmn r2, #16 - ldmgeia r1!, {r3 - r6} - stmgeia r0!, {r3 - r6} - subge r2, r2, #0x10 -3: adds r2, r2, #0x14 -4: ldmgeia r1!, {r3 - r5} - stmgeia r0!, {r3 - r5} - subges r2, r2, #12 - bge 4b -5: adds r2, r2, #8 - blt 6f - subs r2, r2, #4 - ldrlt r3, [r1], #4 - strlt r3, [r0], #4 - ldmgeia r1!, {r3, r4} - stmgeia r0!, {r3, r4} - subge r2, r2, #4 - -6: adds r2, r2, #4 - EXITEQ - cmp r2, #2 - ldrb r3, [r1], #1 - strb r3, [r0], #1 - ldrgeb r3, [r1], #1 - strgeb r3, [r0], #1 - ldrgtb r3, [r1], #1 - strgtb r3, [r0], #1 - EXIT - -7: rsb ip, ip, #4 - cmp ip, #2 - ldrb r3, [r1], #1 - strb r3, [r0], #1 - ldrgeb r3, [r1], #1 - strgeb r3, [r0], #1 - ldrgtb r3, [r1], #1 - strgtb r3, [r0], #1 - subs r2, r2, ip - blt 6b - ands ip, r1, #3 - beq 1b - -8: bic r1, r1, #3 - ldr r7, [r1], #4 - cmp ip, #2 - bgt 15f - beq 11f - cmp r2, #12 - blt 10f - sub r2, r2, #12 -9: mov r3, r7, lsr #8 - ldmia r1!, {r4 - r7} - orr r3, r3, r4, lsl #24 - mov r4, r4, lsr #8 - orr r4, r4, r5, lsl #24 - mov r5, r5, lsr #8 - orr r5, r5, r6, lsl #24 - mov r6, r6, lsr #8 - orr r6, r6, r7, lsl #24 - stmia r0!, {r3 - r6} - subs r2, r2, #16 - bge 9b - adds r2, r2, #12 - blt 100f -10: mov r3, r7, lsr #8 - ldr r7, [r1], #4 - orr r3, r3, r7, lsl #24 - str r3, [r0], #4 - subs r2, r2, #4 - bge 10b -100: sub r1, r1, #3 - b 6b - -11: cmp r2, #12 - blt 13f /* */ - sub r2, r2, #12 -12: mov r3, r7, lsr #16 - ldmia r1!, {r4 - r7} - orr r3, r3, r4, lsl #16 - mov r4, r4, lsr #16 - orr r4, r4, r5, lsl #16 - mov r5, r5, lsr #16 - orr r5, r5, r6, lsl #16 - mov r6, r6, lsr #16 - orr r6, r6, r7,LSL#16 - stmia r0!, {r3 - r6} - subs r2, r2, #16 - bge 12b - adds r2, r2, #12 - blt 14f -13: mov r3, r7, lsr #16 - ldr r7, [r1], #4 - orr r3, r3, r7, lsl #16 - str r3, [r0], #4 - subs r2, r2, #4 - bge 13b -14: sub r1, r1, #2 - b 6b - -15: cmp r2, #12 - blt 17f - sub r2, r2, #12 -16: mov r3, r7, lsr #24 - ldmia r1!,{r4 - r7} - orr r3, r3, r4, lsl #8 - mov r4, r4, lsr #24 - orr r4, r4, r5, lsl #8 - mov r5, r5, lsr #24 - orr r5, r5, r6, lsl #8 - mov r6, r6, lsr #24 - orr r6, r6, r7, lsl #8 - stmia r0!, {r3 - r6} - subs r2, r2, #16 - bge 16b - adds r2, r2, #12 - blt 18f -17: mov r3, r7, lsr #24 - ldr r7, [r1], #4 - orr r3, r3, r7, lsl#8 - str r3, [r0], #4 - subs r2, r2, #4 - bge 17b -18: sub r1, r1, #1 - b 6b - - -19: add r1, r1, r2 - add r0, r0, r2 - subs r2, r2, #4 - blt 24f - ands ip, r0, #3 - bne 25f - ands ip, r1, #3 - bne 26f - -20: subs r2, r2, #8 - blt 23f - subs r2, r2, #0x14 - blt 22f -21: ldmdb r1!, {r3 - r9, ip} - stmdb r0!, {r3 - r9, ip} - subs r2, r2, #32 - bge 21b -22: cmn r2, #16 - ldmgedb r1!, {r3 - r6} - stmgedb r0!, {r3 - r6} - subge r2, r2, #16 - adds r2, r2, #20 - ldmgedb r1!, {r3 - r5} - stmgedb r0!, {r3 - r5} - subge r2, r2, #12 -23: adds r2, r2, #8 - blt 24f - subs r2, r2, #4 - ldrlt r3, [r1, #-4]! - strlt r3, [r0, #-4]! - ldmgedb r1!, {r3, r4} - stmgedb r0!, {r3, r4} - subge r2, r2, #4 - -24: adds r2, r2, #4 - EXITEQ - cmp r2, #2 - ldrb r3, [r1, #-1]! - strb r3, [r0, #-1]! - ldrgeb r3, [r1, #-1]! - strgeb r3, [r0, #-1]! - ldrgtb r3, [r1, #-1]! - strgtb r3, [r0, #-1]! - EXIT - -25: cmp ip, #2 - ldrb r3, [r1, #-1]! - strb r3, [r0, #-1]! - ldrgeb r3, [r1, #-1]! - strgeb r3, [r0, #-1]! - ldrgtb r3, [r1, #-1]! - strgtb r3, [r0, #-1]! - subs r2, r2, ip - blt 24b - ands ip, r1, #3 - beq 20b - -26: bic r1, r1, #3 - ldr r3, [r1], #0 - cmp ip, #2 - blt 34f - beq 30f - cmp r2, #12 - blt 28f - sub r2, r2, #12 -27: mov r7, r3, lsl #8 - ldmdb r1!, {r3, r4, r5, r6} - orr r7, r7, r6, lsr #24 - mov r6, r6, lsl #8 - orr r6, r6, r5, lsr #24 - mov r5, r5, lsl #8 - orr r5, r5, r4, lsr #24 - mov r4, r4, lsl #8 - orr r4, r4, r3, lsr #24 - stmdb r0!, {r4, r5, r6, r7} - subs r2, r2, #16 - bge 27b - adds r2, r2, #12 - blt 29f -28: mov ip, r3, lsl #8 - ldr r3, [r1, #-4]! - orr ip, ip, r3, lsr #24 - str ip, [r0, #-4]! - subs r2, r2, #4 - bge 28b -29: add r1, r1, #3 - b 24b - -30: cmp r2, #12 - blt 32f - sub r2, r2, #12 -31: mov r7, r3, lsl #16 - ldmdb r1!, {r3, r4, r5, r6} - orr r7, r7, r6, lsr #16 - mov r6, r6, lsl #16 - orr r6, r6, r5, lsr #16 - mov r5, r5, lsl #16 - orr r5, r5, r4, lsr #16 - mov r4, r4, lsl #16 - orr r4, r4, r3, lsr #16 - stmdb r0!, {r4, r5, r6, r7} - subs r2, r2, #16 - bge 31b - adds r2, r2, #12 - blt 33f -32: mov ip, r3, lsl #16 - ldr r3, [r1, #-4]! - orr ip, ip, r3, lsr #16 - str ip, [r0, #-4]! - subs r2, r2, #4 - bge 32b -33: add r1, r1, #2 - b 24b - -34: cmp r2, #12 - blt 36f - sub r2, r2, #12 -35: mov r7, r3, lsl #24 - ldmdb r1!, {r3, r4, r5, r6} - orr r7, r7, r6, lsr #8 - mov r6, r6, lsl #24 - orr r6, r6, r5, lsr #8 - mov r5, r5, lsl #24 - orr r5, r5, r4, lsr #8 - mov r4, r4, lsl #24 - orr r4, r4, r3, lsr #8 - stmdb r0!, {r4, r5, r6, r7} - subs r2, r2, #16 - bge 35b - adds r2, r2, #12 - blt 37f -36: mov ip, r3, lsl #24 - ldr r3, [r1, #-4]! - orr ip, ip, r3, lsr #8 - str ip, [r0, #-4]! - subs r2, r2, #4 - bge 36b -37: add r1, r1, #1 - b 24b - - .align - diff --git a/arch/arm/lib/string.S b/arch/arm/lib/string.S index 17daa9d26..ff809fd51 100644 --- a/arch/arm/lib/string.S +++ b/arch/arm/lib/string.S @@ -1,69 +1,112 @@ /* * linux/arch/arm/lib/string.S * - * Copyright (C) 1995-1998 Russell King + * Copyright (C) 1995-1999 Russell King * - * This is commonly used to clear the frame buffer and the frame - * backing buffer. As such, it will be rarely called with r2 < 32. + * ASM optimised string functions * - * Optimisations by Matthew Wilcox */ #include <linux/linkage.h> #include <asm/assembler.h> +#include "constants.h" + .text -# Prototype: char *strrchr(const char *s,char c); /* * Prototype: void memzero(void *d, size_t n) */ -ENTRY(memzero) - mov r2, r1 - mov r1, #0 -/* - * Prototype: void memsetl(unsigned long *d, unsigned long c, size_t n) - */ -ENTRY(memsetl) - teq r2, #0 - RETINSTR(moveq,pc,lr) - stmfd sp!, {lr} - mov lr, r1 - mov r3, r1 - mov ip, r1 +1: @ 4 <= r1 + cmp ip, #2 @ 1 + strltb r2, [r0], #1 @ 1 + strleb r2, [r0], #1 @ 1 + strb r2, [r0], #1 @ 1 + rsb ip, ip, #4 @ 1 + sub r1, r1, ip @ 1 + cmp r1, #3 @ 1 + bgt 2f @ 1 @ +8 + b 4f @ 1 @ +9 - @ r2 = {32 ... 4} + .align 5 -1: subs r2, r2, #32 - stmgeia r0!, {r1, r3, ip, lr} - stmgeia r0!, {r1, r3, ip, lr} - bgt 1b - LOADREGS(eqfd, sp!, {pc}) +ENTRY(__memzero) + mov r2, #0 @ 1 + cmp r1, #4 @ 1 + blt 4f @ 1 @ = 3 - @ r2 can be {-4 ... -28} + @ r1 >= 4 - cmp r2, #-16 - stmgeia r0!, {r1, r3, ip, lr} - addlts r2, r2, #16 - LOADREGS(eqfd, sp!, {pc}) + ands ip, r0, #3 @ 1 + bne 1b @ 1 @ = 5 - @ r2 can be {-4 ... -12} +2: @ r1 >= 4 && (r0 & 3) = 0 @ = 5 or 11 - cmp r2, #-8 - stmgeia r0!, {r1, r3} - strne r1, [r0] - LOADREGS(fd, sp!, {pc}) + str lr, [sp, #-4]! @ 1 + mov r3, #0 @ 1 + mov ip, #0 @ 1 + mov lr, #0 @ 1 + + @ 4 <= r1 <= 32 @ = 9 or 15 + +3: subs r1, r1, #32 @ 1 + stmgeia r0!, {r2, r3, ip, lr} @ 4 + stmgeia r0!, {r2, r3, ip, lr} @ 4 + bgt 3b @ 1 + LOADREGS(eqfd, sp!, {pc}) @ 1/2 + + @ -28 <= r1 <= -1 + + cmp r1, #-16 @ 1 + stmgeia r0!, {r2, r3, ip, lr} @ 4 + ldr lr, [sp], #4 @ 1 + addlts r1, r1, #16 @ 1 + RETINSTR(moveq,pc,lr) @ 1 - .global __page_memcpy -__page_memcpy: stmfd sp!, {r4, r5, lr} -1: subs r2, r2, #4*8 - ldmgeia r1!, {r3, r4, r5, ip} - stmgeia r0!, {r3, r4, r5, ip} - ldmgeia r1!, {r3, r4, r5, ip} - stmgeia r0!, {r3, r4, r5, ip} - bgt 1b - LOADREGS(fd, sp!, {r4, r5, pc}) - - .global memset -memset: mov r3, r0 + @ -12 <= r1 <= -1 + + cmp r1, #-8 @ 1 + stmgeia r0!, {r2, r3} @ 2 + addlts r1, r1, #8 @ 1 + RETINSTR(moveq,pc,lr) @ 1 + + @ -4 <= r1 <= -1 + + cmp r1, #-4 @ 1 + strge r2, [r0], #4 @ 1 + adds r1, r1, #4 @ 1 + RETINSTR(moveq,pc,lr) @ 1 + +4: @ 1 <= r1 <= 3 + cmp r1, #2 @ 1 + strgtb r2, [r0], #1 @ 1 + strgeb r2, [r0], #1 @ 1 + strb r2, [r0], #1 @ 1 + RETINSTR(mov,pc,lr) @ 1 + +/* + * StrongARM optimised copy_page routine + * now 1.72bytes/cycle, was 1.60 bytes/cycle + * (50MHz bus -> 86MB/s) + */ + +ENTRY(copy_page) + stmfd sp!, {r4, lr} @ 2 + mov r2, #PAGE_SZ/64 @ 1 +1: ldmia r1!, {r3, r4, ip, lr} @ 4 + subs r2, r2, #1 @ 1 + stmia r0!, {r3, r4, ip, lr} @ 4 + ldmia r1!, {r3, r4, ip, lr} @ 4+1 + stmia r0!, {r3, r4, ip, lr} @ 4 + ldmia r1!, {r3, r4, ip, lr} @ 4+1 + stmia r0!, {r3, r4, ip, lr} @ 4 + ldmia r1!, {r3, r4, ip, lr} @ 4+1 + stmia r0!, {r3, r4, ip, lr} @ 4 + bne 1b @ 1 + LOADREGS(fd, sp!, {r4, pc}) @ 3 + + .align 5 +ENTRY(memset) /* needed for some versions of gcc */ +ENTRY(__memset) + mov r3, r0 cmp r2, #16 blt 6f ands ip, r3, #3 @@ -168,3 +211,309 @@ ENTRY(memchr) 2: movne r0, #0 subeq r0, r0, #1 LOADREGS(fd, sp!, {pc}) + + +#define ENTER \ + mov ip,sp ;\ + stmfd sp!,{r4-r9,fp,ip,lr,pc} ;\ + sub fp,ip,#4 + +#define EXIT \ + LOADREGS(ea, fp, {r4 - r9, fp, sp, pc}) + +#define EXITEQ \ + LOADREGS(eqea, fp, {r4 - r9, fp, sp, pc}) + +/* + * Prototype: void memcpy(void *to,const void *from,unsigned long n); + * ARM3: cant use memcopy here!!! + */ +ENTRY(memcpy) +ENTRY(memmove) + ENTER + cmp r1, r0 + bcc 19f + subs r2, r2, #4 + blt 6f + ands ip, r0, #3 + bne 7f + ands ip, r1, #3 + bne 8f + +1: subs r2, r2, #8 + blt 5f + subs r2, r2, #0x14 + blt 3f +2: ldmia r1!,{r3 - r9, ip} + stmia r0!,{r3 - r9, ip} + subs r2, r2, #32 + bge 2b + cmn r2, #16 + ldmgeia r1!, {r3 - r6} + stmgeia r0!, {r3 - r6} + subge r2, r2, #0x10 +3: adds r2, r2, #0x14 +4: ldmgeia r1!, {r3 - r5} + stmgeia r0!, {r3 - r5} + subges r2, r2, #12 + bge 4b +5: adds r2, r2, #8 + blt 6f + subs r2, r2, #4 + ldrlt r3, [r1], #4 + strlt r3, [r0], #4 + ldmgeia r1!, {r3, r4} + stmgeia r0!, {r3, r4} + subge r2, r2, #4 + +6: adds r2, r2, #4 + EXITEQ + cmp r2, #2 + ldrb r3, [r1], #1 + strb r3, [r0], #1 + ldrgeb r3, [r1], #1 + strgeb r3, [r0], #1 + ldrgtb r3, [r1], #1 + strgtb r3, [r0], #1 + EXIT + +7: rsb ip, ip, #4 + cmp ip, #2 + ldrb r3, [r1], #1 + strb r3, [r0], #1 + ldrgeb r3, [r1], #1 + strgeb r3, [r0], #1 + ldrgtb r3, [r1], #1 + strgtb r3, [r0], #1 + subs r2, r2, ip + blt 6b + ands ip, r1, #3 + beq 1b + +8: bic r1, r1, #3 + ldr r7, [r1], #4 + cmp ip, #2 + bgt 15f + beq 11f + cmp r2, #12 + blt 10f + sub r2, r2, #12 +9: mov r3, r7, lsr #8 + ldmia r1!, {r4 - r7} + orr r3, r3, r4, lsl #24 + mov r4, r4, lsr #8 + orr r4, r4, r5, lsl #24 + mov r5, r5, lsr #8 + orr r5, r5, r6, lsl #24 + mov r6, r6, lsr #8 + orr r6, r6, r7, lsl #24 + stmia r0!, {r3 - r6} + subs r2, r2, #16 + bge 9b + adds r2, r2, #12 + blt 100f +10: mov r3, r7, lsr #8 + ldr r7, [r1], #4 + orr r3, r3, r7, lsl #24 + str r3, [r0], #4 + subs r2, r2, #4 + bge 10b +100: sub r1, r1, #3 + b 6b + +11: cmp r2, #12 + blt 13f /* */ + sub r2, r2, #12 +12: mov r3, r7, lsr #16 + ldmia r1!, {r4 - r7} + orr r3, r3, r4, lsl #16 + mov r4, r4, lsr #16 + orr r4, r4, r5, lsl #16 + mov r5, r5, lsr #16 + orr r5, r5, r6, lsl #16 + mov r6, r6, lsr #16 + orr r6, r6, r7,LSL#16 + stmia r0!, {r3 - r6} + subs r2, r2, #16 + bge 12b + adds r2, r2, #12 + blt 14f +13: mov r3, r7, lsr #16 + ldr r7, [r1], #4 + orr r3, r3, r7, lsl #16 + str r3, [r0], #4 + subs r2, r2, #4 + bge 13b +14: sub r1, r1, #2 + b 6b + +15: cmp r2, #12 + blt 17f + sub r2, r2, #12 +16: mov r3, r7, lsr #24 + ldmia r1!,{r4 - r7} + orr r3, r3, r4, lsl #8 + mov r4, r4, lsr #24 + orr r4, r4, r5, lsl #8 + mov r5, r5, lsr #24 + orr r5, r5, r6, lsl #8 + mov r6, r6, lsr #24 + orr r6, r6, r7, lsl #8 + stmia r0!, {r3 - r6} + subs r2, r2, #16 + bge 16b + adds r2, r2, #12 + blt 18f +17: mov r3, r7, lsr #24 + ldr r7, [r1], #4 + orr r3, r3, r7, lsl#8 + str r3, [r0], #4 + subs r2, r2, #4 + bge 17b +18: sub r1, r1, #1 + b 6b + + +19: add r1, r1, r2 + add r0, r0, r2 + subs r2, r2, #4 + blt 24f + ands ip, r0, #3 + bne 25f + ands ip, r1, #3 + bne 26f + +20: subs r2, r2, #8 + blt 23f + subs r2, r2, #0x14 + blt 22f +21: ldmdb r1!, {r3 - r9, ip} + stmdb r0!, {r3 - r9, ip} + subs r2, r2, #32 + bge 21b +22: cmn r2, #16 + ldmgedb r1!, {r3 - r6} + stmgedb r0!, {r3 - r6} + subge r2, r2, #16 + adds r2, r2, #20 + ldmgedb r1!, {r3 - r5} + stmgedb r0!, {r3 - r5} + subge r2, r2, #12 +23: adds r2, r2, #8 + blt 24f + subs r2, r2, #4 + ldrlt r3, [r1, #-4]! + strlt r3, [r0, #-4]! + ldmgedb r1!, {r3, r4} + stmgedb r0!, {r3, r4} + subge r2, r2, #4 + +24: adds r2, r2, #4 + EXITEQ + cmp r2, #2 + ldrb r3, [r1, #-1]! + strb r3, [r0, #-1]! + ldrgeb r3, [r1, #-1]! + strgeb r3, [r0, #-1]! + ldrgtb r3, [r1, #-1]! + strgtb r3, [r0, #-1]! + EXIT + +25: cmp ip, #2 + ldrb r3, [r1, #-1]! + strb r3, [r0, #-1]! + ldrgeb r3, [r1, #-1]! + strgeb r3, [r0, #-1]! + ldrgtb r3, [r1, #-1]! + strgtb r3, [r0, #-1]! + subs r2, r2, ip + blt 24b + ands ip, r1, #3 + beq 20b + +26: bic r1, r1, #3 + ldr r3, [r1], #0 + cmp ip, #2 + blt 34f + beq 30f + cmp r2, #12 + blt 28f + sub r2, r2, #12 +27: mov r7, r3, lsl #8 + ldmdb r1!, {r3, r4, r5, r6} + orr r7, r7, r6, lsr #24 + mov r6, r6, lsl #8 + orr r6, r6, r5, lsr #24 + mov r5, r5, lsl #8 + orr r5, r5, r4, lsr #24 + mov r4, r4, lsl #8 + orr r4, r4, r3, lsr #24 + stmdb r0!, {r4, r5, r6, r7} + subs r2, r2, #16 + bge 27b + adds r2, r2, #12 + blt 29f +28: mov ip, r3, lsl #8 + ldr r3, [r1, #-4]! + orr ip, ip, r3, lsr #24 + str ip, [r0, #-4]! + subs r2, r2, #4 + bge 28b +29: add r1, r1, #3 + b 24b + +30: cmp r2, #12 + blt 32f + sub r2, r2, #12 +31: mov r7, r3, lsl #16 + ldmdb r1!, {r3, r4, r5, r6} + orr r7, r7, r6, lsr #16 + mov r6, r6, lsl #16 + orr r6, r6, r5, lsr #16 + mov r5, r5, lsl #16 + orr r5, r5, r4, lsr #16 + mov r4, r4, lsl #16 + orr r4, r4, r3, lsr #16 + stmdb r0!, {r4, r5, r6, r7} + subs r2, r2, #16 + bge 31b + adds r2, r2, #12 + blt 33f +32: mov ip, r3, lsl #16 + ldr r3, [r1, #-4]! + orr ip, ip, r3, lsr #16 + str ip, [r0, #-4]! + subs r2, r2, #4 + bge 32b +33: add r1, r1, #2 + b 24b + +34: cmp r2, #12 + blt 36f + sub r2, r2, #12 +35: mov r7, r3, lsl #24 + ldmdb r1!, {r3, r4, r5, r6} + orr r7, r7, r6, lsr #8 + mov r6, r6, lsl #24 + orr r6, r6, r5, lsr #8 + mov r5, r5, lsl #24 + orr r5, r5, r4, lsr #8 + mov r4, r4, lsl #24 + orr r4, r4, r3, lsr #8 + stmdb r0!, {r4, r5, r6, r7} + subs r2, r2, #16 + bge 35b + adds r2, r2, #12 + blt 37f +36: mov ip, r3, lsl #24 + ldr r3, [r1, #-4]! + orr ip, ip, r3, lsr #8 + str ip, [r0, #-4]! + subs r2, r2, #4 + bge 36b +37: add r1, r1, #1 + b 24b + + .align + + diff --git a/arch/arm/lib/system.S b/arch/arm/lib/system.S deleted file mode 100644 index f037d56ff..000000000 --- a/arch/arm/lib/system.S +++ /dev/null @@ -1,20 +0,0 @@ -/* - * linux/arch/arm/lib/system.S - * - * Copyright (C) 1995, 1996 Russell King - * - * 07/06/96: Now support tasks running in SVC mode. - */ -#include <linux/linkage.h> -#include <asm/assembler.h> - - .text - -ENTRY(abort) - adr r0, .abort_msg - mov r1, lr - b SYMBOL_NAME(panic) - -.abort_msg: .ascii "Eek! Got to an abort() from %p! " - .ascii "(Please report to rmk@arm.uk.linux.org)\n\0" - .align diff --git a/arch/arm/lib/system.c b/arch/arm/lib/system.c new file mode 100644 index 000000000..f3b32cd82 --- /dev/null +++ b/arch/arm/lib/system.c @@ -0,0 +1,22 @@ +/* + * linux/arch/arm/lib/system.c + * + * Copyright (C) 1999 Russell King + * + * Converted from ASM version 04/09/1999 + */ +#include <linux/kernel.h> + +extern void abort(void) +{ + void *lr = __builtin_return_address(0); + + printk(KERN_CRIT "kernel abort from %p! (Please report to rmk@arm.linux.org.uk)\n", + lr); + + /* force an oops */ + *(int *)0 = 0; + + /* if that doesn't kill us, halt */ + panic("Oops failed to kill thread"); +} diff --git a/arch/arm/lib/uaccess-armo.S b/arch/arm/lib/uaccess-armo.S index 1a740493a..695fdf0c1 100644 --- a/arch/arm/lib/uaccess-armo.S +++ b/arch/arm/lib/uaccess-armo.S @@ -30,7 +30,7 @@ SYMBOL_NAME(uaccess_user): .word __arch_copy_to_user .word __arch_clear_user .word __arch_strncpy_from_user - .word __arch_strlen_user + .word __arch_strnlen_user @ In : r0 = x, r1 = addr, r2 = error diff --git a/arch/arm/lib/uaccess.S b/arch/arm/lib/uaccess.S index 67684cb1a..898d2ef77 100644 --- a/arch/arm/lib/uaccess.S +++ b/arch/arm/lib/uaccess.S @@ -42,11 +42,11 @@ _##x: rsb ip, ip, #4 cmp ip, #2 ldrb r3, [r1], #1 -USER( strbt r3, [r0], #1) // May fault +USER( strbt r3, [r0], #1) @ May fault ldrgeb r3, [r1], #1 -USER( strgebt r3, [r0], #1) // May fault +USER( strgebt r3, [r0], #1) @ May fault ldrgtb r3, [r1], #1 -USER( strgtbt r3, [r0], #1) // May fault +USER( strgtbt r3, [r0], #1) @ May fault sub r2, r2, ip b .c2u_dest_aligned @@ -69,8 +69,8 @@ ENTRY(__arch_copy_to_user) addmi ip, r2, #4 bmi .c2u_0nowords ldr r3, [r1], #4 -USER( strt r3, [r0], #4) // May fault - mov ip, r0, lsl #32 - PAGE_SHIFT // On each page, use a ld/st??t instruction +USER( strt r3, [r0], #4) @ May fault + mov ip, r0, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction rsb ip, ip, #0 movs ip, ip, lsr #32 - PAGE_SHIFT beq .c2u_0fupi @@ -84,31 +84,31 @@ USER( strt r3, [r0], #4) // May fault blt .c2u_0rem8lp .c2u_0cpy8lp: ldmia r1!, {r3 - r6} - stmia r0!, {r3 - r6} // Shouldn't fault + stmia r0!, {r3 - r6} @ Shouldn't fault ldmia r1!, {r3 - r6} - stmia r0!, {r3 - r6} // Shouldn't fault + stmia r0!, {r3 - r6} @ Shouldn't fault subs ip, ip, #32 bpl .c2u_0cpy8lp .c2u_0rem8lp: cmn ip, #16 ldmgeia r1!, {r3 - r6} - stmgeia r0!, {r3 - r6} // Shouldn't fault + stmgeia r0!, {r3 - r6} @ Shouldn't fault tst ip, #8 ldmneia r1!, {r3 - r4} - stmneia r0!, {r3 - r4} // Shouldn't fault + stmneia r0!, {r3 - r4} @ Shouldn't fault tst ip, #4 ldrne r3, [r1], #4 - strnet r3, [r0], #4 // Shouldn't fault + strnet r3, [r0], #4 @ Shouldn't fault ands ip, ip, #3 beq .c2u_0fupi .c2u_0nowords: teq ip, #0 beq .c2u_finished .c2u_nowords: cmp ip, #2 ldrb r3, [r1], #1 -USER( strbt r3, [r0], #1) // May fault +USER( strbt r3, [r0], #1) @ May fault ldrgeb r3, [r1], #1 -USER( strgebt r3, [r0], #1) // May fault +USER( strgebt r3, [r0], #1) @ May fault ldrgtb r3, [r1], #1 -USER( strgtbt r3, [r0], #1) // May fault +USER( strgtbt r3, [r0], #1) @ May fault b .c2u_finished .c2u_not_enough: @@ -129,7 +129,7 @@ USER( strgtbt r3, [r0], #1) // May fault mov r3, r7, lsr #8 ldr r7, [r1], #4 orr r3, r3, r7, lsl #24 -USER( strt r3, [r0], #4) // May fault +USER( strt r3, [r0], #4) @ May fault mov ip, r0, lsl #32 - PAGE_SHIFT rsb ip, ip, #0 movs ip, ip, lsr #32 - PAGE_SHIFT @@ -149,7 +149,7 @@ USER( strt r3, [r0], #4) // May fault orr r5, r5, r6, lsl #24 mov r6, r6, lsr #8 orr r6, r6, r7, lsl #24 - stmia r0!, {r3 - r6} // Shouldn't fault + stmia r0!, {r3 - r6} @ Shouldn't fault subs ip, ip, #16 bpl .c2u_1cpy8lp .c2u_1rem8lp: tst ip, #8 @@ -158,23 +158,23 @@ USER( strt r3, [r0], #4) // May fault orrne r3, r3, r4, lsl #24 movne r4, r4, lsr #8 orrne r4, r4, r7, lsl #24 - stmneia r0!, {r3 - r4} // Shouldn't fault + stmneia r0!, {r3 - r4} @ Shouldn't fault tst ip, #4 movne r3, r7, lsr #8 ldrne r7, [r1], #4 orrne r3, r3, r7, lsl #24 - strnet r3, [r0], #4 // Shouldn't fault + strnet r3, [r0], #4 @ Shouldn't fault ands ip, ip, #3 beq .c2u_1fupi .c2u_1nowords: mov r3, r7, lsr #8 teq ip, #0 beq .c2u_finished cmp ip, #2 -USER( strbt r3, [r0], #1) // May fault +USER( strbt r3, [r0], #1) @ May fault movge r3, r3, lsr #8 -USER( strgebt r3, [r0], #1) // May fault +USER( strgebt r3, [r0], #1) @ May fault movgt r3, r3, lsr #8 -USER( strgtbt r3, [r0], #1) // May fault +USER( strgtbt r3, [r0], #1) @ May fault b .c2u_finished .c2u_2fupi: subs r2, r2, #4 @@ -183,7 +183,7 @@ USER( strgtbt r3, [r0], #1) // May fault mov r3, r7, lsr #16 ldr r7, [r1], #4 orr r3, r3, r7, lsl #16 -USER( strt r3, [r0], #4) // May fault +USER( strt r3, [r0], #4) @ May fault mov ip, r0, lsl #32 - PAGE_SHIFT rsb ip, ip, #0 movs ip, ip, lsr #32 - PAGE_SHIFT @@ -203,7 +203,7 @@ USER( strt r3, [r0], #4) // May fault orr r5, r5, r6, lsl #16 mov r6, r6, lsr #16 orr r6, r6, r7, lsl #16 - stmia r0!, {r3 - r6} // Shouldn't fault + stmia r0!, {r3 - r6} @ Shouldn't fault subs ip, ip, #16 bpl .c2u_2cpy8lp .c2u_2rem8lp: tst ip, #8 @@ -212,23 +212,23 @@ USER( strt r3, [r0], #4) // May fault orrne r3, r3, r4, lsl #16 movne r4, r4, lsr #16 orrne r4, r4, r7, lsl #16 - stmneia r0!, {r3 - r4} // Shouldn't fault + stmneia r0!, {r3 - r4} @ Shouldn't fault tst ip, #4 movne r3, r7, lsr #16 ldrne r7, [r1], #4 orrne r3, r3, r7, lsl #16 - strnet r3, [r0], #4 // Shouldn't fault + strnet r3, [r0], #4 @ Shouldn't fault ands ip, ip, #3 beq .c2u_2fupi .c2u_2nowords: mov r3, r7, lsr #16 teq ip, #0 beq .c2u_finished cmp ip, #2 -USER( strbt r3, [r0], #1) // May fault +USER( strbt r3, [r0], #1) @ May fault movge r3, r3, lsr #8 -USER( strgebt r3, [r0], #1) // May fault +USER( strgebt r3, [r0], #1) @ May fault ldrgtb r3, [r1], #0 -USER( strgtbt r3, [r0], #1) // May fault +USER( strgtbt r3, [r0], #1) @ May fault b .c2u_finished .c2u_3fupi: subs r2, r2, #4 @@ -237,7 +237,7 @@ USER( strgtbt r3, [r0], #1) // May fault mov r3, r7, lsr #24 ldr r7, [r1], #4 orr r3, r3, r7, lsl #8 -USER( strt r3, [r0], #4) // May fault +USER( strt r3, [r0], #4) @ May fault mov ip, r0, lsl #32 - PAGE_SHIFT rsb ip, ip, #0 movs ip, ip, lsr #32 - PAGE_SHIFT @@ -257,7 +257,7 @@ USER( strt r3, [r0], #4) // May fault orr r5, r5, r6, lsl #8 mov r6, r6, lsr #24 orr r6, r6, r7, lsl #8 - stmia r0!, {r3 - r6} // Shouldn't fault + stmia r0!, {r3 - r6} @ Shouldn't fault subs ip, ip, #16 bpl .c2u_3cpy8lp .c2u_3rem8lp: tst ip, #8 @@ -266,23 +266,23 @@ USER( strt r3, [r0], #4) // May fault orrne r3, r3, r4, lsl #8 movne r4, r4, lsr #24 orrne r4, r4, r7, lsl #8 - stmneia r0!, {r3 - r4} // Shouldn't fault + stmneia r0!, {r3 - r4} @ Shouldn't fault tst ip, #4 movne r3, r7, lsr #24 ldrne r7, [r1], #4 orrne r3, r3, r7, lsl #8 - strnet r3, [r0], #4 // Shouldn't fault + strnet r3, [r0], #4 @ Shouldn't fault ands ip, ip, #3 beq .c2u_3fupi .c2u_3nowords: mov r3, r7, lsr #24 teq ip, #0 beq .c2u_finished cmp ip, #2 -USER( strbt r3, [r0], #1) // May fault +USER( strbt r3, [r0], #1) @ May fault ldrge r3, [r1], #0 -USER( strgebt r3, [r0], #1) // May fault +USER( strgebt r3, [r0], #1) @ May fault movgt r3, r3, lsr #8 -USER( strgtbt r3, [r0], #1) // May fault +USER( strgtbt r3, [r0], #1) @ May fault b .c2u_finished #ifndef TESTING @@ -302,11 +302,11 @@ USER( strgtbt r3, [r0], #1) // May fault .cfu_dest_not_aligned: rsb ip, ip, #4 cmp ip, #2 -USER( ldrbt r3, [r1], #1) // May fault +USER( ldrbt r3, [r1], #1) @ May fault strb r3, [r0], #1 -USER( ldrgebt r3, [r1], #1) // May fault +USER( ldrgebt r3, [r1], #1) @ May fault strgeb r3, [r0], #1 -USER( ldrgtbt r3, [r1], #1) // May fault +USER( ldrgtbt r3, [r1], #1) @ May fault strgtb r3, [r0], #1 sub r2, r2, ip b .cfu_dest_aligned @@ -330,7 +330,7 @@ ENTRY(__arch_copy_from_user) bmi .cfu_0nowords USER( ldrt r3, [r1], #4) str r3, [r0], #4 - mov ip, r1, lsl #32 - PAGE_SHIFT // On each page, use a ld/st??t instruction + mov ip, r1, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction rsb ip, ip, #0 movs ip, ip, lsr #32 - PAGE_SHIFT beq .cfu_0fupi @@ -343,31 +343,31 @@ USER( ldrt r3, [r1], #4) subs ip, ip, #32 blt .cfu_0rem8lp -.cfu_0cpy8lp: ldmia r1!, {r3 - r6} // Shouldn't fault +.cfu_0cpy8lp: ldmia r1!, {r3 - r6} @ Shouldn't fault stmia r0!, {r3 - r6} - ldmia r1!, {r3 - r6} // Shouldn't fault + ldmia r1!, {r3 - r6} @ Shouldn't fault stmia r0!, {r3 - r6} subs ip, ip, #32 bpl .cfu_0cpy8lp .cfu_0rem8lp: cmn ip, #16 - ldmgeia r1!, {r3 - r6} // Shouldn't fault + ldmgeia r1!, {r3 - r6} @ Shouldn't fault stmgeia r0!, {r3 - r6} tst ip, #8 - ldmneia r1!, {r3 - r4} // Shouldn't fault + ldmneia r1!, {r3 - r4} @ Shouldn't fault stmneia r0!, {r3 - r4} tst ip, #4 - ldrnet r3, [r1], #4 // Shouldn't fault + ldrnet r3, [r1], #4 @ Shouldn't fault strne r3, [r0], #4 ands ip, ip, #3 beq .cfu_0fupi .cfu_0nowords: teq ip, #0 beq .cfu_finished .cfu_nowords: cmp ip, #2 -USER( ldrbt r3, [r1], #1) // May fault +USER( ldrbt r3, [r1], #1) @ May fault strb r3, [r0], #1 -USER( ldrgebt r3, [r1], #1) // May fault +USER( ldrgebt r3, [r1], #1) @ May fault strgeb r3, [r0], #1 -USER( ldrgtbt r3, [r1], #1) // May fault +USER( ldrgtbt r3, [r1], #1) @ May fault strgtb r3, [r0], #1 b .cfu_finished @@ -380,7 +380,7 @@ USER( ldrgtbt r3, [r1], #1) // May fault .cfu_src_not_aligned: bic r1, r1, #3 -USER( ldrt r7, [r1], #4) // May fault +USER( ldrt r7, [r1], #4) @ May fault cmp ip, #2 bgt .cfu_3fupi beq .cfu_2fupi @@ -388,7 +388,7 @@ USER( ldrt r7, [r1], #4) // May fault addmi ip, r2, #4 bmi .cfu_1nowords mov r3, r7, lsr #8 -USER( ldrt r7, [r1], #4) // May fault +USER( ldrt r7, [r1], #4) @ May fault orr r3, r3, r7, lsl #24 str r3, [r0], #4 mov ip, r1, lsl #32 - PAGE_SHIFT @@ -402,7 +402,7 @@ USER( ldrt r7, [r1], #4) // May fault blt .cfu_1rem8lp .cfu_1cpy8lp: mov r3, r7, lsr #8 - ldmia r1!, {r4 - r7} // Shouldn't fault + ldmia r1!, {r4 - r7} @ Shouldn't fault orr r3, r3, r4, lsl #24 mov r4, r4, lsr #8 orr r4, r4, r5, lsl #24 @@ -415,14 +415,14 @@ USER( ldrt r7, [r1], #4) // May fault bpl .cfu_1cpy8lp .cfu_1rem8lp: tst ip, #8 movne r3, r7, lsr #8 - ldmneia r1!, {r4, r7} // Shouldn't fault + ldmneia r1!, {r4, r7} @ Shouldn't fault orrne r3, r3, r4, lsl #24 movne r4, r4, lsr #8 orrne r4, r4, r7, lsl #24 stmneia r0!, {r3 - r4} tst ip, #4 movne r3, r7, lsr #8 -USER( ldrnet r7, [r1], #4) // May fault +USER( ldrnet r7, [r1], #4) @ May fault orrne r3, r3, r7, lsl #24 strne r3, [r0], #4 ands ip, ip, #3 @@ -442,7 +442,7 @@ USER( ldrnet r7, [r1], #4) // May fault addmi ip, r2, #4 bmi .cfu_2nowords mov r3, r7, lsr #16 -USER( ldrt r7, [r1], #4) // May fault +USER( ldrt r7, [r1], #4) @ May fault orr r3, r3, r7, lsl #16 str r3, [r0], #4 mov ip, r1, lsl #32 - PAGE_SHIFT @@ -456,7 +456,7 @@ USER( ldrt r7, [r1], #4) // May fault blt .cfu_2rem8lp .cfu_2cpy8lp: mov r3, r7, lsr #16 - ldmia r1!, {r4 - r7} // Shouldn't fault + ldmia r1!, {r4 - r7} @ Shouldn't fault orr r3, r3, r4, lsl #16 mov r4, r4, lsr #16 orr r4, r4, r5, lsl #16 @@ -469,14 +469,14 @@ USER( ldrt r7, [r1], #4) // May fault bpl .cfu_2cpy8lp .cfu_2rem8lp: tst ip, #8 movne r3, r7, lsr #16 - ldmneia r1!, {r4, r7} // Shouldn't fault + ldmneia r1!, {r4, r7} @ Shouldn't fault orrne r3, r3, r4, lsl #16 movne r4, r4, lsr #16 orrne r4, r4, r7, lsl #16 stmneia r0!, {r3 - r4} tst ip, #4 movne r3, r7, lsr #16 -USER( ldrnet r7, [r1], #4) // May fault +USER( ldrnet r7, [r1], #4) @ May fault orrne r3, r3, r7, lsl #16 strne r3, [r0], #4 ands ip, ip, #3 @@ -488,7 +488,7 @@ USER( ldrnet r7, [r1], #4) // May fault strb r3, [r0], #1 movge r3, r3, lsr #8 strgeb r3, [r0], #1 -USER( ldrgtbt r3, [r1], #0) // May fault +USER( ldrgtbt r3, [r1], #0) @ May fault strgtb r3, [r0], #1 b .cfu_finished @@ -496,7 +496,7 @@ USER( ldrgtbt r3, [r1], #0) // May fault addmi ip, r2, #4 bmi .cfu_3nowords mov r3, r7, lsr #24 -USER( ldrt r7, [r1], #4) // May fault +USER( ldrt r7, [r1], #4) @ May fault orr r3, r3, r7, lsl #8 str r3, [r0], #4 mov ip, r1, lsl #32 - PAGE_SHIFT @@ -510,7 +510,7 @@ USER( ldrt r7, [r1], #4) // May fault blt .cfu_3rem8lp .cfu_3cpy8lp: mov r3, r7, lsr #24 - ldmia r1!, {r4 - r7} // Shouldn't fault + ldmia r1!, {r4 - r7} @ Shouldn't fault orr r3, r3, r4, lsl #8 mov r4, r4, lsr #24 orr r4, r4, r5, lsl #8 @@ -523,14 +523,14 @@ USER( ldrt r7, [r1], #4) // May fault bpl .cfu_3cpy8lp .cfu_3rem8lp: tst ip, #8 movne r3, r7, lsr #24 - ldmneia r1!, {r4, r7} // Shouldn't fault + ldmneia r1!, {r4, r7} @ Shouldn't fault orrne r3, r3, r4, lsl #8 movne r4, r4, lsr #24 orrne r4, r4, r7, lsl #8 stmneia r0!, {r3 - r4} tst ip, #4 movne r3, r7, lsr #24 -USER( ldrnet r7, [r1], #4) // May fault +USER( ldrnet r7, [r1], #4) @ May fault orrne r3, r3, r7, lsl #8 strne r3, [r0], #4 ands ip, ip, #3 @@ -540,7 +540,7 @@ USER( ldrnet r7, [r1], #4) // May fault beq .cfu_finished cmp ip, #2 strb r3, [r0], #1 -USER( ldrget r3, [r1], #0) // May fault +USER( ldrget r3, [r1], #0) @ May fault strgeb r3, [r0], #1 movgt r3, r3, lsr #8 strgtb r3, [r0], #1 @@ -553,7 +553,8 @@ USER( ldrget r3, [r1], #0) // May fault data was copied. */ 9001: ldr r0, [sp], #4 ldr r1, [sp] - bl SYMBOL_NAME(memzero) + teq r1, #0 + blne SYMBOL_NAME(__memzero) LOADREGS(fd,sp!, {r0, r4 - r7, pc}) .previous #endif @@ -597,19 +598,23 @@ USER( strnebt r2, [r0], #1) 9001: LOADREGS(fd,sp!, {r0, pc}) .previous -/* Prototype: int __arch_strlen_user(char *str) +/* Prototype: unsigned long __arch_strnlen_user(const char *str, long n) * Purpose : get length of a string in user memory * Params : str - address of string in user memory - * Returns : length of string *including terminator*, or zero on error + * Returns : length of string *including terminator* + * or zero on exception, or n + 1 if too long */ -ENTRY(__arch_strlen_user) +ENTRY(__arch_strnlen_user) stmfd sp!, {lr} mov r2, r0 1: -USER( ldrbt r1, [r0], #1) - teq r1, #0 +USER( ldrbt r3, [r0], #1) + teq r3, #0 + beq 2f + subs r1, r1, #1 bne 1b - sub r0, r0, r2 + add r0, r0, #1 +2: sub r0, r0, r2 LOADREGS(fd,sp!, {pc}) .section .fixup,"ax" diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index 42a92201f..b9bffb7c9 100644 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile @@ -8,7 +8,8 @@ # Note 2! The CFLAGS definition is now in the main makefile... O_TARGET := mm.o -O_OBJS := init.o extable.o fault-$(PROCESSOR).o small_page.o +O_OBJS := init.o extable.o fault-$(PROCESSOR).o mm-$(PROCESSOR).o \ + small_page.o ifeq ($(CONFIG_CPU_26),y) O_OBJS += proc-arm2,3.o @@ -24,13 +25,16 @@ ifeq ($(CONFIG_CPU_32),y) ifeq ($(CONFIG_CPU_SA110),y) P_OBJS += proc-sa110.o endif + ifeq ($(CONFIG_CPU_SA1100),y) + P_OBJS += proc-sa110.o + endif O_OBJS += mm-$(MACHINE).o ioremap.o $(sort $(P_OBJS)) endif include $(TOPDIR)/Rules.make -%.o: %.S - $(CC) $(CFLAGS) -D__ASSEMBLY__ -c -o $@ $< +.S.o: + $(CC) -D__ASSEMBLY__ $(AFLAGS) $(AFLAGS_$@) -traditional -c -o $*.o $< # Special dependencies fault-armv.o: fault-common.c diff --git a/arch/arm/mm/fault-armo.c b/arch/arm/mm/fault-armo.c index c51980771..19a1fff7c 100644 --- a/arch/arm/mm/fault-armo.c +++ b/arch/arm/mm/fault-armo.c @@ -23,61 +23,12 @@ #define FAULT_CODE_FORCECOW 0x80 #define FAULT_CODE_PREFETCH 0x04 #define FAULT_CODE_WRITE 0x02 -#define FAULT_CODE_USER 0x01 #define DO_COW(m) ((m) & (FAULT_CODE_WRITE|FAULT_CODE_FORCECOW)) #define READ_FAULT(m) (!((m) & FAULT_CODE_WRITE)) #include "fault-common.c" -static void *alloc_table(int size, int prio) -{ - if (size != 128) - printk("invalid table size\n"); - return (void *)get_page_8k(prio); -} - -void free_table(void *table) -{ - free_page_8k((unsigned long)table); -} - -pgd_t *get_pgd_slow(void) -{ - pgd_t *pgd = (pgd_t *)alloc_table(PTRS_PER_PGD * BYTES_PER_PTR, GFP_KERNEL); - pgd_t *init; - - if (pgd) { - init = pgd_offset(&init_mm, 0); - memzero(pgd, USER_PTRS_PER_PGD * BYTES_PER_PTR); - memcpy(pgd + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD, - (PTRS_PER_PGD - USER_PTRS_PER_PGD) * BYTES_PER_PTR); - } - return pgd; -} - -pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset) -{ - pte_t *pte; - - pte = (pte_t *)alloc_table(PTRS_PER_PTE * BYTES_PER_PTR, GFP_KERNEL); - if (pmd_none(*pmd)) { - if (pte) { - memzero(pte, PTRS_PER_PTE * BYTES_PER_PTR); - set_pmd(pmd, mk_pmd(pte)); - return pte + offset; - } - set_pmd(pmd, mk_pmd(BAD_PAGETABLE)); - return NULL; - } - free_table((void *)pte); - if (pmd_bad(*pmd)) { - __bad_pmd(pmd); - return NULL; - } - return (pte_t *) pmd_page(*pmd) + offset; -} - /* * Handle a data abort. Note that we have to handle a range of addresses * on ARM2/3 for ldm. If both pages are zero-mapped, then we have to force @@ -96,11 +47,11 @@ asmlinkage int do_PrefetchAbort(unsigned long addr, struct pt_regs *regs) { #if 0 - if (the memc mapping for this page exists - can check now...) { + if (the memc mapping for this page exists) { printk ("Page in, but got abort (undefined instruction?)\n"); return 0; } #endif - do_page_fault(addr, FAULT_CODE_USER|FAULT_CODE_PREFETCH, regs); + do_page_fault(addr, FAULT_CODE_PREFETCH, regs); return 1; } diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index 0c5582fb7..8c2df7f5e 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c @@ -25,104 +25,12 @@ #include <asm/unaligned.h> #define FAULT_CODE_READ 0x02 -#define FAULT_CODE_USER 0x01 #define DO_COW(m) (!((m) & FAULT_CODE_READ)) #define READ_FAULT(m) ((m) & FAULT_CODE_READ) #include "fault-common.c" -/* - * need to get a 16k page for level 1 - */ -pgd_t *get_pgd_slow(void) -{ - pgd_t *pgd = (pgd_t *)__get_free_pages(GFP_KERNEL,2); - pgd_t *init; - pmd_t *new_pmd; - - if (pgd) { - init = pgd_offset(&init_mm, 0); - memzero(pgd, USER_PTRS_PER_PGD * BYTES_PER_PTR); - memcpy(pgd + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD, - (PTRS_PER_PGD - USER_PTRS_PER_PGD) * BYTES_PER_PTR); - clean_cache_area(pgd, PTRS_PER_PGD * BYTES_PER_PTR); - - /* - * On ARM, first page must always be allocated - */ - if (!pmd_alloc(pgd, 0)) - goto nomem; - else { - pmd_t *old_pmd = pmd_offset(init, 0); - new_pmd = pmd_offset(pgd, 0); - - if (!pte_alloc(new_pmd, 0)) - goto nomem_pmd; - else { - pte_t *new_pte = pte_offset(new_pmd, 0); - pte_t *old_pte = pte_offset(old_pmd, 0); - - set_pte (new_pte, *old_pte); - } - } - } - return pgd; - -nomem_pmd: - pmd_free(new_pmd); -nomem: - return NULL; -} - -pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset) -{ - pte_t *pte; - - pte = (pte_t *)get_page_2k(GFP_KERNEL); - if (pmd_none(*pmd)) { - if (pte) { - memzero(pte, 2 * PTRS_PER_PTE * BYTES_PER_PTR); - clean_cache_area(pte, PTRS_PER_PTE * BYTES_PER_PTR); - pte += PTRS_PER_PTE; - set_pmd(pmd, mk_user_pmd(pte)); - return pte + offset; - } - set_pmd(pmd, mk_user_pmd(BAD_PAGETABLE)); - return NULL; - } - free_page_2k((unsigned long)pte); - if (pmd_bad(*pmd)) { - __bad_pmd(pmd); - return NULL; - } - return (pte_t *) pmd_page(*pmd) + offset; -} - -pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long offset) -{ - pte_t *pte; - - pte = (pte_t *)get_page_2k(GFP_KERNEL); - if (pmd_none(*pmd)) { - if (pte) { - memzero(pte, 2 * PTRS_PER_PTE * BYTES_PER_PTR); - clean_cache_area(pte, PTRS_PER_PTE * BYTES_PER_PTR); - pte += PTRS_PER_PTE; - set_pmd(pmd, mk_kernel_pmd(pte)); - return pte + offset; - } - set_pmd(pmd, mk_kernel_pmd(BAD_PAGETABLE)); - return NULL; - } - free_page_2k((unsigned long)pte); - if (pmd_bad(*pmd)) { - __bad_pmd_kernel(pmd); - return NULL; - } - return (pte_t *) pmd_page(*pmd) + offset; -} - #ifdef DEBUG static int sp_valid(unsigned long *sp) { @@ -406,6 +314,10 @@ do_alignment_exception(struct pt_regs *regs) #endif +#define BUG_PROC_MSG \ + "Buggy processor (%08X), trying to continue.\n" \ + "Please read http://www.arm.linux.org.uk/state.html for more information" + asmlinkage void do_DataAbort(unsigned long addr, int fsr, int error_code, struct pt_regs *regs) { @@ -416,17 +328,11 @@ do_DataAbort(unsigned long addr, int fsr, int error_code, struct pt_regs *regs) /* * I want statistical information on this problem! */ - printk(KERN_ERR "Buggy processor (%08X), " - "trying to continue.\n" - "Please send contents of /proc/cpuinfo " - "and this message to linux@arm.linux.org.uk", - fsr); + printk(KERN_ERR BUG_PROC_MSG, fsr); first = 0; } return; } - - error_code |= FAULT_CODE_USER; } #define DIE(signr,nam)\ @@ -522,6 +428,6 @@ do_DataAbort(unsigned long addr, int fsr, int error_code, struct pt_regs *regs) asmlinkage int do_PrefetchAbort(unsigned long addr, struct pt_regs *regs) { - do_page_fault(addr, FAULT_CODE_USER|FAULT_CODE_READ, regs); + do_page_fault(addr, FAULT_CODE_READ, regs); return 1; } diff --git a/arch/arm/mm/fault-common.c b/arch/arm/mm/fault-common.c index a536515af..c87fa760e 100644 --- a/arch/arm/mm/fault-common.c +++ b/arch/arm/mm/fault-common.c @@ -30,7 +30,7 @@ void __bad_pmd_kernel(pmd_t *pmd) * This is useful to dump out the page tables associated with * 'addr' in mm 'mm'. */ -void show_pte(struct mm_struct *mm, unsigned long addr) +static void show_pte(struct mm_struct *mm, unsigned long addr) { pgd_t *pgd; @@ -62,7 +62,9 @@ void show_pte(struct mm_struct *mm, unsigned long addr) pte = pte_offset(pmd, addr); printk(", *pte = %08lx", pte_val(*pte)); +#ifdef CONFIG_CPU_32 printk(", *ppte = %08lx", pte_val(pte[-PTRS_PER_PTE])); +#endif } while(0); printk("\n"); @@ -73,7 +75,7 @@ void show_pte(struct mm_struct *mm, unsigned long addr) * terminate things with extreme prejudice. */ static void -kernel_page_fault(unsigned long addr, int mode, struct pt_regs *regs, +kernel_page_fault(unsigned long addr, int write_access, struct pt_regs *regs, struct task_struct *tsk, struct mm_struct *mm) { char *reason; @@ -90,7 +92,7 @@ kernel_page_fault(unsigned long addr, int mode, struct pt_regs *regs, printk(KERN_ALERT "pgd = %p\n", mm->pgd); show_pte(mm, addr); - die("Oops", regs, mode); + die("Oops", regs, write_access); do_exit(SIGKILL); } @@ -153,7 +155,7 @@ bad_area: up(&mm->mmap_sem); /* User mode accesses just cause a SIGSEGV */ - if (mode & FAULT_CODE_USER) { + if (user_mode(regs)) { tsk->thread.error_code = mode; tsk->thread.trap_no = 14; #ifdef CONFIG_DEBUG_USER @@ -194,7 +196,7 @@ do_sigbus: force_sig(SIGBUS, tsk); /* Kernel mode? Handle exceptions or die */ - if (!(mode & FAULT_CODE_USER)) + if (!user_mode(regs)) goto no_context; } diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 4fa1ca498..115cec885 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -1,7 +1,7 @@ /* * linux/arch/arm/mm/init.c * - * Copyright (C) 1995, 1996 Russell King + * Copyright (C) 1995-1999 Russell King */ #include <linux/config.h> @@ -15,6 +15,7 @@ #include <linux/mman.h> #include <linux/mm.h> #include <linux/swap.h> +#include <linux/swapctl.h> #include <linux/smp.h> #include <linux/init.h> #ifdef CONFIG_BLK_DEV_INITRD @@ -26,14 +27,18 @@ #include <asm/pgtable.h> #include <asm/dma.h> #include <asm/hardware.h> -#include <asm/proc/mm-init.h> + +#include "map.h" pgd_t swapper_pg_dir[PTRS_PER_PGD]; #ifndef CONFIG_NO_PGT_CACHE struct pgtable_cache_struct quicklists; #endif -extern char _etext, _stext, _edata, __bss_start, _end; +extern unsigned long free_area_init(unsigned long, unsigned long); +extern void show_net_buffers(void); + +extern char _etext, _text, _edata, __bss_start, _end; extern char __init_begin, __init_end; int do_check_pgt_cache(int low, int high) @@ -67,7 +72,6 @@ int do_check_pgt_cache(int low, int high) * ZERO_PAGE is a special page that is used for zero-initialized * data and COW. */ -#if PTRS_PER_PTE != 1 pte_t *empty_bad_page_table; pte_t *__bad_pagetable(void) @@ -81,7 +85,6 @@ pte_t *__bad_pagetable(void) return empty_bad_page_table; } -#endif unsigned long *empty_zero_page; unsigned long *empty_bad_page; @@ -94,27 +97,39 @@ pte_t __bad_page(void) void show_mem(void) { - extern void show_net_buffers(void); - int i,free = 0,total = 0,reserved = 0; - int shared = 0; + int free = 0, total = 0, reserved = 0; + int shared = 0, cached = 0; + struct page *page, *end; printk("Mem-info:\n"); show_free_areas(); printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10)); - i = MAP_NR(high_memory); - while (i-- > 0) { + for (page = mem_map, end = mem_map + max_mapnr; + page < end; page++) { + if (PageSkip(page)) { + if (page->next_hash < page) + break; + page = page->next_hash; + } total++; - if (PageReserved(mem_map+i)) + if (PageReserved(page)) reserved++; - else if (!atomic_read(&mem_map[i].count)) + else if (PageSwapCache(page)) + cached++; + else if (!atomic_read(&page->count)) free++; else - shared += atomic_read(&mem_map[i].count) - 1; + shared += atomic_read(&page->count) - 1; } - printk("%d pages of RAM\n",total); - printk("%d free pages\n",free); - printk("%d reserved pages\n",reserved); - printk("%d pages shared\n",shared); + printk("%d pages of RAM\n", total); + printk("%d free pages\n", free); + printk("%d reserved pages\n", reserved); + printk("%d pages shared\n", shared); + printk("%d pages swap cached\n", cached); +#ifndef CONFIG_NO_PGT_CACHE + printk("%ld page tables cached\n", pgtable_cache_size); +#endif + show_buffers(); #ifdef CONFIG_NET show_net_buffers(); #endif @@ -125,25 +140,24 @@ void show_mem(void) */ unsigned long __init paging_init(unsigned long start_mem, unsigned long end_mem) { - extern unsigned long free_area_init(unsigned long, unsigned long); - start_mem = PAGE_ALIGN(start_mem); + empty_zero_page = (unsigned long *)start_mem; + memzero(empty_zero_page, PAGE_SIZE); start_mem += PAGE_SIZE; + empty_bad_page = (unsigned long *)start_mem; start_mem += PAGE_SIZE; -#if PTRS_PER_PTE != 1 + #ifdef CONFIG_CPU_32 start_mem += PTRS_PER_PTE * BYTES_PER_PTR; #endif empty_bad_page_table = (pte_t *)start_mem; start_mem += PTRS_PER_PTE * BYTES_PER_PTR; -#endif - memzero (empty_zero_page, PAGE_SIZE); - start_mem = setup_pagetables (start_mem, end_mem); + + start_mem = setup_page_tables(start_mem, end_mem); flush_tlb_all(); - update_memc_all(); end_mem &= PAGE_MASK; high_memory = (void *)end_mem; @@ -151,6 +165,31 @@ unsigned long __init paging_init(unsigned long start_mem, unsigned long end_mem) return free_area_init(start_mem, end_mem); } +static inline void free_unused_mem_map(void) +{ + struct page *page, *end; + + end = mem_map + max_mapnr; + + for (page = mem_map; page < end; page++) { + unsigned long low, high; + + if (!PageSkip(page)) + continue; + + low = PAGE_ALIGN((unsigned long)(page + 1)); + if (page->next_hash < page) + high = ((unsigned long)end) & PAGE_MASK; + else + high = ((unsigned long)page->next_hash) & PAGE_MASK; + + while (low < high) { + clear_bit(PG_reserved, &mem_map[MAP_NR(low)].flags); + low += PAGE_SIZE; + } + } +} + /* * mem_init() marks the free areas in the mem_map and tells us how much * memory is free. This is done after various parts of the system have @@ -158,28 +197,48 @@ unsigned long __init paging_init(unsigned long start_mem, unsigned long end_mem) */ void __init mem_init(unsigned long start_mem, unsigned long end_mem) { - extern void sound_init(void); int codepages = 0; int reservedpages = 0; int datapages = 0; - int initpages = 0; + int initpages = 0, i, min_nr; unsigned long tmp; - end_mem &= PAGE_MASK; - high_memory = (void *)end_mem; - max_mapnr = num_physpages = MAP_NR(end_mem); + end_mem &= PAGE_MASK; + high_memory = (void *)end_mem; + max_mapnr = MAP_NR(end_mem); + num_physpages = 0; + + /* setup address validity bitmap */ + start_mem = create_mem_holes(start_mem, end_mem); + + start_mem = PAGE_ALIGN(start_mem); /* mark usable pages in the mem_map[] */ - mark_usable_memory_areas(&start_mem, end_mem); + mark_usable_memory_areas(start_mem, end_mem); + + /* free unused mem_map[] entries */ + free_unused_mem_map(); #define BETWEEN(w,min,max) ((w) >= (unsigned long)(min) && \ (w) < (unsigned long)(max)) for (tmp = PAGE_OFFSET; tmp < end_mem ; tmp += PAGE_SIZE) { + if (PageSkip(mem_map+MAP_NR(tmp))) { + unsigned long next; + + next = mem_map[MAP_NR(tmp)].next_hash - mem_map; + + next = (next << PAGE_SHIFT) + PAGE_OFFSET; + + if (next < tmp || next >= end_mem) + break; + tmp = next; + } + num_physpages++; if (PageReserved(mem_map+MAP_NR(tmp))) { if (BETWEEN(tmp, &__init_begin, &__init_end)) initpages++; - else if (BETWEEN(tmp, &_stext, &_etext)) + else if (BETWEEN(tmp, &_text, &_etext)) codepages++; else if (BETWEEN(tmp, &_etext, &_edata)) datapages++; @@ -200,11 +259,24 @@ void __init mem_init(unsigned long start_mem, unsigned long end_mem) printk ("Memory: %luk/%luM available (%dk code, %dk reserved, %dk data, %dk init)\n", (unsigned long) nr_free_pages << (PAGE_SHIFT-10), - max_mapnr >> (20 - PAGE_SHIFT), - codepages << (PAGE_SHIFT-10), + num_physpages >> (20 - PAGE_SHIFT), + codepages << (PAGE_SHIFT-10), reservedpages << (PAGE_SHIFT-10), - datapages << (PAGE_SHIFT-10), - initpages << (PAGE_SHIFT-10)); + datapages << (PAGE_SHIFT-10), + initpages << (PAGE_SHIFT-10)); + + i = nr_free_pages >> 7; + if (PAGE_SIZE < 32768) + min_nr = 10; + else + min_nr = 2; + if (i < min_nr) + i = min_nr; + if (i > 256) + i = 256; + freepages.min = i; + freepages.low = i * 2; + freepages.high = i * 3; #ifdef CONFIG_CPU_26 if (max_mapnr <= 128) { @@ -240,14 +312,16 @@ void free_initmem (void) #ifdef CONFIG_FOOTBRIDGE { - extern int __netwinder_begin, __netwinder_end, __ebsa285_begin, __ebsa285_end; + extern int __netwinder_begin, __netwinder_end, + __ebsa285_begin, __ebsa285_end; if (!machine_is_netwinder()) free_area((unsigned long)(&__netwinder_begin), (unsigned long)(&__netwinder_end), "netwinder"); - if (!machine_is_ebsa285() && !machine_is_cats() && !machine_is_co285()) + if (!machine_is_ebsa285() && !machine_is_cats() && + !machine_is_co285()) free_area((unsigned long)(&__ebsa285_begin), (unsigned long)(&__ebsa285_end), "ebsa285/cats"); @@ -259,22 +333,28 @@ void free_initmem (void) void si_meminfo(struct sysinfo *val) { - int i; + struct page *page, *end; - i = MAP_NR(high_memory); val->totalram = 0; val->sharedram = 0; val->freeram = nr_free_pages << PAGE_SHIFT; val->bufferram = atomic_read(&buffermem); - while (i-- > 0) { - if (PageReserved(mem_map+i)) + for (page = mem_map, end = mem_map + max_mapnr; + page < end; page++) { + if (PageSkip(page)) { + if (page->next_hash < page) + break; + page = page->next_hash; + } + if (PageReserved(page)) continue; val->totalram++; - if (!atomic_read(&mem_map[i].count)) + if (!atomic_read(&page->count)) continue; - val->sharedram += atomic_read(&mem_map[i].count) - 1; + val->sharedram += atomic_read(&page->count) - 1; } val->totalram <<= PAGE_SHIFT; val->sharedram <<= PAGE_SHIFT; + val->totalbig = 0; + val->freebig = 0; } - diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index e4c84fa71..141644ae2 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c @@ -27,8 +27,12 @@ * FIFO. Unfortunately, it is not possible to tell the DC21285 to * flush this - flushing the area causes the bus to lock. */ - +#include <linux/errno.h> +#include <linux/mm.h> #include <linux/vmalloc.h> + +#include <asm/page.h> +#include <asm/pgtable.h> #include <asm/io.h> static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, @@ -145,5 +149,5 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag void __iounmap(void *addr) { - return vfree((void *) (PAGE_MASK & (unsigned long) addr)); + vfree((void *) (PAGE_MASK & (unsigned long) addr)); } diff --git a/arch/arm/mm/map.h b/arch/arm/mm/map.h new file mode 100644 index 000000000..a1fc92b2c --- /dev/null +++ b/arch/arm/mm/map.h @@ -0,0 +1,32 @@ +/* + * linux/arch/arm/mm/map.h + * + * Copyright (C) 1999 Russell King + * + * Page table mapping constructs and function prototypes + */ +struct map_desc { + unsigned long virtual; + unsigned long physical; + unsigned long length; + int domain:4, + prot_read:1, + prot_write:1, + cacheable:1, + bufferable:1; +}; + +struct mem_desc { + unsigned long virt_start; + unsigned long virt_end; +}; + +extern struct map_desc io_desc[]; +extern unsigned int io_desc_size; +extern struct mem_desc mem_desc[]; +extern unsigned int mem_desc_size; + +extern void mark_usable_memory_areas(unsigned long start, unsigned long end); +extern unsigned long create_mem_holes(unsigned long start, unsigned long end); +extern unsigned long setup_page_tables(unsigned long start, unsigned long end); + diff --git a/arch/arm/mm/mm-armo.c b/arch/arm/mm/mm-armo.c new file mode 100644 index 000000000..55245f4e8 --- /dev/null +++ b/arch/arm/mm/mm-armo.c @@ -0,0 +1,170 @@ +/* + * arch/arm/mm/mm-armo.c + * + * Page table sludge for older ARM processor architectures. + * + * Copyright (C) 1998-1999 Russell King + */ +#include <linux/sched.h> +#include <linux/mm.h> +#include <linux/init.h> + +#include <asm/pgtable.h> +#include <asm/page.h> +#include <asm/arch/memory.h> + +#include "map.h" + +#define MEMC_TABLE_SIZE (256*sizeof(unsigned long)) +#define PGD_TABLE_SIZE (PTRS_PER_PGD * BYTES_PER_PTR) + +/* + * FIXME: the following over-allocates by 6400% + */ +static inline void *alloc_table(int size, int prio) +{ + if (size != 128) + printk("invalid table size\n"); + return (void *)get_page_8k(prio); +} + +/* + * Allocate a page table. Note that we place the MEMC + * table before the page directory. This means we can + * easily get to both tightly-associated data structures + * with a single pointer. This function is slightly + * better - it over-allocates by only 711% + */ +static inline void *alloc_pgd_table(int priority) +{ + unsigned long pg8k; + + pg8k = get_page_8k(priority); + if (pg8k) + pg8k += MEMC_TABLE_SIZE; + + return (void *)pg8k; +} + +void free_table(void *table) +{ + unsigned long tbl = (unsigned long)table; + + tbl &= ~8191; + free_page_8k(tbl); +} + +pgd_t *get_pgd_slow(void) +{ + pgd_t *pgd = (pgd_t *)alloc_pgd_table(GFP_KERNEL); + pmd_t *new_pmd; + + if (pgd) { + pgd_t *init = pgd_offset(&init_mm, 0); + + memzero(pgd, USER_PTRS_PER_PGD * BYTES_PER_PTR); + memcpy(pgd + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD, + (PTRS_PER_PGD - USER_PTRS_PER_PGD) * BYTES_PER_PTR); + + /* + * On ARM, first page must always be allocated + */ + if (!pmd_alloc(pgd, 0)) + goto nomem; + else { + pmd_t *old_pmd = pmd_offset(init, 0); + new_pmd = pmd_offset(pgd, 0); + + if (!pte_alloc(new_pmd, 0)) + goto nomem_pmd; + else { + pte_t *new_pte = pte_offset(new_pmd, 0); + pte_t *old_pte = pte_offset(old_pmd, 0); + + set_pte (new_pte, *old_pte); + } + } + /* update MEMC tables */ + cpu_memc_update_all(pgd); + } + return pgd; + +nomem_pmd: + pmd_free(new_pmd); +nomem: + free_table(pgd); + return NULL; +} + +pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset) +{ + pte_t *pte; + + pte = (pte_t *)alloc_table(PTRS_PER_PTE * BYTES_PER_PTR, GFP_KERNEL); + if (pmd_none(*pmd)) { + if (pte) { + memzero(pte, PTRS_PER_PTE * BYTES_PER_PTR); + set_pmd(pmd, mk_pmd(pte)); + return pte + offset; + } + set_pmd(pmd, mk_pmd(BAD_PAGETABLE)); + return NULL; + } + free_table((void *)pte); + if (pmd_bad(*pmd)) { + __bad_pmd(pmd); + return NULL; + } + return (pte_t *) pmd_page(*pmd) + offset; +} + +/* + * This contains the code to setup the memory map on an ARM2/ARM250/ARM3 + * machine. This is both processor & architecture specific, and requires + * some more work to get it to fit into our separate processor and + * architecture structure. + */ +int page_nr; + +#define PTE_SIZE (PTRS_PER_PTE * BYTES_PER_PTR) + +static inline void setup_swapper_dir (int index, pte_t *ptep) +{ + set_pmd (pmd_offset (swapper_pg_dir + index, 0), mk_pmd (ptep)); +} + +unsigned long __init +setup_page_tables(unsigned long start_mem, unsigned long end_mem) +{ + unsigned int i; + union { unsigned long l; pte_t *pte; } u; + + page_nr = MAP_NR(end_mem); + + /* map in pages for (0x0000 - 0x8000) */ + u.l = ((start_mem + (PTE_SIZE-1)) & ~(PTE_SIZE-1)); + start_mem = u.l + PTE_SIZE; + memzero (u.pte, PTE_SIZE); + u.pte[0] = mk_pte(PAGE_OFFSET + 491520, PAGE_READONLY); + setup_swapper_dir (0, u.pte); + + for (i = 1; i < PTRS_PER_PGD; i++) + pgd_val(swapper_pg_dir[i]) = 0; + + return start_mem; +} + +unsigned long __init +create_mem_holes(unsigned long start, unsigned long end) +{ + return start; +} + +void __init +mark_usable_memory_areas(unsigned long start_mem, unsigned long end_mem) +{ + while (start_mem < end_mem) { + clear_bit(PG_reserved, &mem_map[MAP_NR(start_mem)].flags); + start_mem += PAGE_SIZE; + } +} diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c index 02890c55b..d52c21cc4 100644 --- a/arch/arm/mm/mm-armv.c +++ b/arch/arm/mm/mm-armv.c @@ -1,72 +1,375 @@ /* * arch/arm/mm/mm-armv.c * - * Common routines for ARM v3 and v4 architectures. + * Page table sludge for ARM v3 and v4 processor architectures. * - * Copyright (C) 1998 Russell King - * - * Do not compile this file directly! + * Copyright (C) 1998-1999 Russell King */ +#include <linux/sched.h> +#include <linux/mm.h> +#include <linux/init.h> -#ifndef MAPPING -#error MAPPING not defined - do not compile this file individually -#endif +#include <asm/pgtable.h> +#include <asm/page.h> +#include <asm/io.h> + +#include "map.h" + +unsigned long *valid_addr_bitmap; + +/* + * need to get a 16k page for level 1 + */ +pgd_t *get_pgd_slow(void) +{ + pgd_t *pgd = (pgd_t *)__get_free_pages(GFP_KERNEL,2); + pmd_t *new_pmd; + + if (pgd) { + pgd_t *init = pgd_offset(&init_mm, 0); + + memzero(pgd, USER_PTRS_PER_PGD * BYTES_PER_PTR); + memcpy(pgd + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD, + (PTRS_PER_PGD - USER_PTRS_PER_PGD) * BYTES_PER_PTR); + clean_cache_area(pgd, PTRS_PER_PGD * BYTES_PER_PTR); + + /* + * On ARM, first page must always be allocated + */ + if (!pmd_alloc(pgd, 0)) + goto nomem; + else { + pmd_t *old_pmd = pmd_offset(init, 0); + new_pmd = pmd_offset(pgd, 0); + + if (!pte_alloc(new_pmd, 0)) + goto nomem_pmd; + else { + pte_t *new_pte = pte_offset(new_pmd, 0); + pte_t *old_pte = pte_offset(old_pmd, 0); + + set_pte (new_pte, *old_pte); + } + } + } + return pgd; -static const struct mapping { - unsigned long virtual; - unsigned long physical; - unsigned long length; - int domain:4, - prot_read:1, - prot_write:1; -} mapping[] __initdata = { - MAPPING +nomem_pmd: + pmd_free(new_pmd); +nomem: + free_pages((unsigned long)pgd, 2); + return NULL; +} + +pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset) +{ + pte_t *pte; + + pte = (pte_t *)get_page_2k(GFP_KERNEL); + if (pmd_none(*pmd)) { + if (pte) { + memzero(pte, 2 * PTRS_PER_PTE * BYTES_PER_PTR); + clean_cache_area(pte, PTRS_PER_PTE * BYTES_PER_PTR); + pte += PTRS_PER_PTE; + set_pmd(pmd, mk_user_pmd(pte)); + return pte + offset; + } + set_pmd(pmd, mk_user_pmd(BAD_PAGETABLE)); + return NULL; + } + free_page_2k((unsigned long)pte); + if (pmd_bad(*pmd)) { + __bad_pmd(pmd); + return NULL; + } + return (pte_t *) pmd_page(*pmd) + offset; +} + +pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long offset) +{ + pte_t *pte; + + pte = (pte_t *)get_page_2k(GFP_KERNEL); + if (pmd_none(*pmd)) { + if (pte) { + memzero(pte, 2 * PTRS_PER_PTE * BYTES_PER_PTR); + clean_cache_area(pte, PTRS_PER_PTE * BYTES_PER_PTR); + pte += PTRS_PER_PTE; + set_pmd(pmd, mk_kernel_pmd(pte)); + return pte + offset; + } + set_pmd(pmd, mk_kernel_pmd(BAD_PAGETABLE)); + return NULL; + } + free_page_2k((unsigned long)pte); + if (pmd_bad(*pmd)) { + __bad_pmd_kernel(pmd); + return NULL; + } + return (pte_t *) pmd_page(*pmd) + offset; +} + +/* + * Create a SECTION PGD between VIRT and PHYS in domain + * DOMAIN with protection PROT + */ +static inline void +alloc_init_section(unsigned long virt, unsigned long phys, int prot) +{ + pmd_t pmd; + + pmd_val(pmd) = phys | prot; + + set_pmd(pmd_offset(pgd_offset_k(virt), virt), pmd); +} + +/* + * Add a PAGE mapping between VIRT and PHYS in domain + * DOMAIN with protection PROT. Note that due to the + * way we map the PTEs, we must allocate two PTE_SIZE'd + * blocks - one for the Linux pte table, and one for + * the hardware pte table. + */ +static inline void +alloc_init_page(unsigned long *mem, unsigned long virt, unsigned long phys, int domain, int prot) +{ + pmd_t *pmdp; + pte_t *ptep; + + pmdp = pmd_offset(pgd_offset_k(virt), virt); + +#define PTE_SIZE (PTRS_PER_PTE * BYTES_PER_PTR) + + if (pmd_none(*pmdp)) { + unsigned long memory = *mem; + + memory = (memory + PTE_SIZE - 1) & ~(PTE_SIZE - 1); + + ptep = (pte_t *)memory; + memzero(ptep, PTE_SIZE); + memory += PTE_SIZE; + + ptep = (pte_t *)memory; + memzero(ptep, PTE_SIZE); + + set_pmd(pmdp, __mk_pmd(ptep, PMD_TYPE_TABLE | PMD_DOMAIN(domain))); + + *mem = memory + PTE_SIZE; + } + +#undef PTE_SIZE + + ptep = pte_offset(pmdp, virt); + + set_pte(ptep, mk_pte_phys(phys, __pgprot(prot))); +} + +/* + * Clear any PGD mapping. On a two-level page table system, + * the clearance is done by the middle-level functions (pmd) + * rather than the top-level (pgd) functions. + */ +static inline void +free_init_section(unsigned long virt) +{ + pmd_clear(pmd_offset(pgd_offset_k(virt), virt)); +} + +/* + * Create the page directory entries and any necessary + * page tables for the mapping specified by `md'. We + * are able to cope here with varying sizes and address + * offsets, and we take full advantage of sections. + */ +static void __init +create_mapping(unsigned long *mem_ptr, struct map_desc *md) +{ + unsigned long virt, length; + int prot_sect, prot_pte; + long off; + + prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | + (md->prot_read ? L_PTE_USER : 0) | + (md->prot_write ? L_PTE_WRITE : 0) | + (md->cacheable ? L_PTE_CACHEABLE : 0) | + (md->bufferable ? L_PTE_BUFFERABLE : 0); + + prot_sect = PMD_TYPE_SECT | PMD_DOMAIN(md->domain) | + (md->prot_read ? PMD_SECT_AP_READ : 0) | + (md->prot_write ? PMD_SECT_AP_WRITE : 0) | + (md->cacheable ? PMD_SECT_CACHEABLE : 0) | + (md->bufferable ? PMD_SECT_BUFFERABLE : 0); + + virt = md->virtual; + off = md->physical - virt; + length = md->length; + + while ((virt & 1048575 || (virt + off) & 1048575) && length >= PAGE_SIZE) { + alloc_init_page(mem_ptr, virt, virt + off, md->domain, prot_pte); + + virt += PAGE_SIZE; + length -= PAGE_SIZE; + } + + while (length >= PGDIR_SIZE) { + alloc_init_section(virt, virt + off, prot_sect); + + virt += PGDIR_SIZE; + length -= PGDIR_SIZE; + } + + while (length >= PAGE_SIZE) { + alloc_init_page(mem_ptr, virt, virt + off, md->domain, prot_pte); + + virt += PAGE_SIZE; + length -= PAGE_SIZE; + } +} + +/* + * Initial boot-time mapping. This covers just the + * zero page, kernel and the flush area. NB: it + * must be sorted by virtual address, and no + * virtual address overlaps. + * init_map[2..4] are for architectures with small + * amounts of banked memory. + */ +static struct map_desc init_map[] __initdata = { + { 0, 0, PAGE_SIZE, DOMAIN_USER, 0, 0, 1, 0 }, /* zero page */ + { 0, 0, 0, DOMAIN_KERNEL, 0, 1, 1, 1 }, /* kernel memory */ + { 0, 0, 0, DOMAIN_KERNEL, 0, 1, 1, 1 }, + { 0, 0, 0, DOMAIN_KERNEL, 0, 1, 1, 1 }, + { 0, 0, 0, DOMAIN_KERNEL, 0, 1, 1, 1 }, + { 0, 0, PGDIR_SIZE, DOMAIN_KERNEL, 1, 0, 1, 1 }, /* cache flush 1 */ + { 0, 0, 0, DOMAIN_KERNEL, 1, 0, 1, 0 } /* cache flush 2 */ }; -#define SIZEOFMAP (sizeof(mapping) / sizeof(mapping[0])) +#define NR_INIT_MAPS (sizeof(init_map) / sizeof(init_map[0])) -unsigned long __init setup_io_pagetables(unsigned long start_mem) +unsigned long __init +setup_page_tables(unsigned long start_mem, unsigned long end_mem) { - const struct mapping *mp; - int i; - - for (i = 0, mp = mapping; i < SIZEOFMAP; i++, mp++) { - unsigned long virtual, physical, length; - int prot; - - virtual = mp->virtual; - physical = mp->physical; - length = mp->length; - prot = (mp->prot_read ? L_PTE_USER : 0) | (mp->prot_write ? L_PTE_WRITE : 0) - | L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY; - - while ((virtual & 1048575 || physical & 1048575) && length >= PAGE_SIZE) { - alloc_init_page(&start_mem, virtual, physical, mp->domain, prot); - length -= PAGE_SIZE; - virtual += PAGE_SIZE; - physical += PAGE_SIZE; + unsigned long address = 0; + int idx = 0; + + /* + * Correct the above mappings + */ + init_map[0].physical = + init_map[1].physical = __virt_to_phys(PAGE_OFFSET); + init_map[1].virtual = PAGE_OFFSET; + init_map[1].length = end_mem - PAGE_OFFSET; + init_map[5].physical = FLUSH_BASE_PHYS; + init_map[5].virtual = FLUSH_BASE; +#ifdef FLUSH_BASE_MINICACHE + init_map[6].physical = FLUSH_BASE_PHYS + PGDIR_SIZE; + init_map[6].virtual = FLUSH_BASE_MINICACHE; + init_map[6].length = PGDIR_SIZE; +#endif + + /* + * Firstly, go through the initial mappings, + * but clear out any pgdir entries that are + * not in the description. + */ + do { + if (address < init_map[idx].virtual || idx == NR_INIT_MAPS) { + free_init_section(address); + address += PGDIR_SIZE; + } else { + create_mapping(&start_mem, init_map + idx); + + address = init_map[idx].virtual + init_map[idx].length; + address = (address + PGDIR_SIZE - 1) & PGDIR_MASK; + + do { + idx += 1; + } while (init_map[idx].length == 0 && idx < NR_INIT_MAPS); } + } while (address != 0); + + /* + * Now, create the architecture specific mappings + */ + for (idx = 0; idx < io_desc_size; idx++) + create_mapping(&start_mem, io_desc + idx); + + flush_cache_all(); + + return start_mem; +} + +/* + * The mem_map array can get very big. Mark the end of the + * valid mem_map banks with PG_skip, and setup the address + * validity bitmap. + */ +unsigned long __init +create_mem_holes(unsigned long start_mem, unsigned long end_mem) +{ + struct page *pg = NULL; + unsigned int sz, i; - prot = (mp->prot_read ? PMD_SECT_AP_READ : 0) | - (mp->prot_write ? PMD_SECT_AP_WRITE : 0); + if (!machine_is_riscpc()) + return start_mem; - while (length >= 1048576) { - alloc_init_section(&start_mem, virtual, physical, mp->domain, prot); - length -= 1048576; - virtual += 1048576; - physical += 1048576; + sz = (end_mem - PAGE_OFFSET) >> 20; + sz = (sz + 31) >> 3; + + valid_addr_bitmap = (unsigned long *)start_mem; + start_mem += sz; + + memset(valid_addr_bitmap, 0, sz); + + if (start_mem > mem_desc[0].virt_end) + printk(KERN_CRIT "*** Error: RAM bank 0 too small\n"); + + for (i = 0; i < mem_desc_size; i++) { + unsigned int idx, end; + + if (pg) { + pg->next_hash = mem_map + + MAP_NR(mem_desc[i].virt_start); + pg = NULL; } - prot = (mp->prot_read ? L_PTE_USER : 0) | (mp->prot_write ? L_PTE_WRITE : 0) - | L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY; + idx = __kern_valid_idx(mem_desc[i].virt_start); + end = __kern_valid_idx(mem_desc[i].virt_end); + + do + set_bit(idx, valid_addr_bitmap); + while (++idx < end); + + if (mem_desc[i].virt_end < end_mem) { + pg = mem_map + MAP_NR(mem_desc[i].virt_end); - while (length >= PAGE_SIZE) { - alloc_init_page(&start_mem, virtual, physical, mp->domain, prot); - length -= PAGE_SIZE; - virtual += PAGE_SIZE; - physical += PAGE_SIZE; + set_bit(PG_skip, &pg->flags); } } + if (pg) + pg->next_hash = NULL; + return start_mem; } + +void __init +mark_usable_memory_areas(unsigned long start_mem, unsigned long end_mem) +{ + /* + * Mark all of memory from the end of kernel to end of memory + */ + while (start_mem < end_mem) { + clear_bit(PG_reserved, &mem_map[MAP_NR(start_mem)].flags); + start_mem += PAGE_SIZE; + } + + /* + * Mark memory from page 1 to start of the swapper page directory + */ + start_mem = PAGE_OFFSET + PAGE_SIZE; + while (start_mem < (unsigned long)&swapper_pg_dir) { + clear_bit(PG_reserved, &mem_map[MAP_NR(start_mem)].flags); + start_mem += PAGE_SIZE; + } +} diff --git a/arch/arm/mm/mm-ebsa110.c b/arch/arm/mm/mm-ebsa110.c index a85302473..8086bbc08 100644 --- a/arch/arm/mm/mm-ebsa110.c +++ b/arch/arm/mm/mm-ebsa110.c @@ -3,19 +3,27 @@ * * Extra MM routines for the EBSA-110 architecture * - * Copyright (C) 1998 Russell King + * Copyright (C) 1998-1999 Russell King */ -#include <linux/sched.h> #include <linux/mm.h> #include <linux/init.h> #include <asm/pgtable.h> #include <asm/page.h> -#include <asm/io.h> -#include <asm/proc/mm-init.h> + +#include "map.h" -#define MAPPING \ - { IO_BASE - PGDIR_SIZE , 0xc0000000 , PGDIR_SIZE , DOMAIN_IO, 0, 1 }, \ - { IO_BASE , IO_START , IO_SIZE , DOMAIN_IO, 0, 1 } +struct mem_desc mem_desc[] __initdata = { + 0, 0 +}; + +unsigned int __initdata mem_desc_size = 0; + +const struct map_desc io_desc[] __initdata = { + { IO_BASE - PGDIR_SIZE, 0xc0000000, PGDIR_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, + { IO_BASE , IO_START , IO_SIZE , DOMAIN_IO, 0, 1, 0, 0 } +}; + +#define SIZEOFMAP (sizeof(mapping) / sizeof(mapping[0])) -#include "mm-armv.c" +unsigned int __initdata io_desc_size = SIZEOFMAP; diff --git a/arch/arm/mm/mm-footbridge.c b/arch/arm/mm/mm-footbridge.c index ec7e64c90..74bac27ea 100644 --- a/arch/arm/mm/mm-footbridge.c +++ b/arch/arm/mm/mm-footbridge.c @@ -1,9 +1,9 @@ /* - * arch/arm/mm/mm-ebsa285.c + * arch/arm/mm/mm-footbridge.c * * Extra MM routines for the EBSA285 architecture * - * Copyright (C) 1998 Russell King, Dave Gilbert. + * Copyright (C) 1998-1999 Russell King, Dave Gilbert. */ #include <linux/config.h> #include <linux/sched.h> @@ -13,9 +13,10 @@ #include <asm/pgtable.h> #include <asm/page.h> #include <asm/io.h> -#include <asm/proc/mm-init.h> #include <asm/dec21285.h> +#include "map.h" + /* * The first entry allows us to fiddle with the EEPROM from user-space. * This entry will go away in time, once the fmu32 can mmap() the @@ -32,15 +33,15 @@ * The mapping when the footbridge is in host mode. */ #define MAPPING \ - { FLASH_BASE, DC21285_FLASH, FLASH_SIZE, DOMAIN_IO, 0, 1 }, \ - { PCIMEM_BASE, DC21285_PCI_MEM, PCIMEM_SIZE, DOMAIN_IO, 0, 1 }, \ - { PCICFG0_BASE, DC21285_PCI_TYPE_0_CONFIG, PCICFG0_SIZE, DOMAIN_IO, 0, 1 }, \ - { PCICFG1_BASE, DC21285_PCI_TYPE_1_CONFIG, PCICFG1_SIZE, DOMAIN_IO, 0, 1 }, \ - { PCIIACK_BASE, DC21285_PCI_IACK, PCIIACK_SIZE, DOMAIN_IO, 0, 1 }, \ - { WFLUSH_BASE, DC21285_OUTBOUND_WRITE_FLUSH, WFLUSH_SIZE, DOMAIN_IO, 0, 1 }, \ - { ARMCSR_BASE, DC21285_ARMCSR_BASE, ARMCSR_SIZE, DOMAIN_IO, 0, 1 }, \ - { PCIO_BASE, DC21285_PCI_IO, PCIO_SIZE, DOMAIN_IO, 0, 1 }, \ - { XBUS_BASE, 0x40000000, XBUS_SIZE, DOMAIN_IO, 0, 1 } + { FLASH_BASE, DC21285_FLASH, FLASH_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, \ + { PCIMEM_BASE, DC21285_PCI_MEM, PCIMEM_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, \ + { PCICFG0_BASE, DC21285_PCI_TYPE_0_CONFIG, PCICFG0_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, \ + { PCICFG1_BASE, DC21285_PCI_TYPE_1_CONFIG, PCICFG1_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, \ + { PCIIACK_BASE, DC21285_PCI_IACK, PCIIACK_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, \ + { WFLUSH_BASE, DC21285_OUTBOUND_WRITE_FLUSH, WFLUSH_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, \ + { ARMCSR_BASE, DC21285_ARMCSR_BASE, ARMCSR_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, \ + { PCIO_BASE, DC21285_PCI_IO, PCIO_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, \ + { XBUS_BASE, 0x40000000, XBUS_SIZE, DOMAIN_IO, 0, 1, 0, 0 } #else @@ -79,13 +80,26 @@ unsigned long __bus_to_virt(unsigned long res) * The mapping when the footbridge is in add-in mode. */ #define MAPPING \ - { PCIO_BASE, DC21285_PCI_IO, PCIO_SIZE, DOMAIN_IO, 0, 1 }, \ - { XBUS_BASE, 0x40000000, XBUS_SIZE, DOMAIN_IO, 0, 1 }, \ - { ARMCSR_BASE, DC21285_ARMCSR_BASE, ARMCSR_SIZE, DOMAIN_IO, 0, 1 }, \ - { WFLUSH_BASE, DC21285_OUTBOUND_WRITE_FLUSH, WFLUSH_SIZE, DOMAIN_IO, 0, 1 }, \ - { FLASH_BASE, DC21285_FLASH, FLASH_SIZE, DOMAIN_IO, 0, 1 }, \ - { PCIMEM_BASE, DC21285_PCI_MEM, PCIMEM_SIZE, DOMAIN_IO, 0, 1 } + { PCIO_BASE, DC21285_PCI_IO, PCIO_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, \ + { XBUS_BASE, 0x40000000, XBUS_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, \ + { ARMCSR_BASE, DC21285_ARMCSR_BASE, ARMCSR_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, \ + { WFLUSH_BASE, DC21285_OUTBOUND_WRITE_FLUSH, WFLUSH_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, \ + { FLASH_BASE, DC21285_FLASH, FLASH_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, \ + { PCIMEM_BASE, DC21285_PCI_MEM, PCIMEM_SIZE, DOMAIN_IO, 0, 1, 0, 0 } #endif -#include "mm-armv.c" +struct mem_desc mem_desc[] __initdata = { + 0, 0 +}; + +unsigned int __initdata mem_desc_size = 0; + +struct map_desc io_desc[] __initdata = { + MAPPING +}; + +#define SIZE(x) (sizeof(x) / sizeof(x[0])) + +unsigned int __initdata io_desc_size = SIZE(io_desc); + diff --git a/arch/arm/mm/mm-nexuspci.c b/arch/arm/mm/mm-nexuspci.c index a7407c130..a4ee48f8d 100644 --- a/arch/arm/mm/mm-nexuspci.c +++ b/arch/arm/mm/mm-nexuspci.c @@ -5,7 +5,7 @@ * Extra MM routines for the NexusPCI architecture * * Copyright (C) 1998 Phil Blundell - * Copyright (C) 1998 Russell King + * Copyright (C) 1998-1999 Russell King */ #include <linux/sched.h> @@ -15,13 +15,23 @@ #include <asm/pgtable.h> #include <asm/page.h> #include <asm/io.h> -#include <asm/proc/mm-init.h> + +#include "map.h" -#define MAPPING \ - { 0xfff00000, 0x10000000, 0x00001000, DOMAIN_IO, 0, 1 }, \ - { 0xffe00000, 0x20000000, 0x00001000, DOMAIN_IO, 0, 1 }, \ - { 0xffc00000, 0x60000000, 0x00001000, DOMAIN_IO, 0, 1 }, \ - { 0xfe000000, 0x80000000, 0x00100000, DOMAIN_IO, 0, 1 }, \ - { 0xfd000000, 0x88000000, 0x00100000, DOMAIN_IO, 0, 1 } +struct mem_desc mem_desc[] __initdata = { + 0, 0 +}; + +unsigned int __initdata mem_desc_size = 0; + +const struct map_desc io_desc[] __initdata = { + { 0xfff00000, 0x10000000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, + { 0xffe00000, 0x20000000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, + { 0xffc00000, 0x60000000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, + { 0xfe000000, 0x80000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, + { 0xfd000000, 0x88000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 } +}; + +#define SIZEOFMAP (sizeof(mapping) / sizeof(mapping[0])) -#include "mm-armv.c" +unsigned int __initdata io_desc_size = SIZEOFMAP; diff --git a/arch/arm/mm/mm-rpc.c b/arch/arm/mm/mm-rpc.c index 80f821245..634bb3c8f 100644 --- a/arch/arm/mm/mm-rpc.c +++ b/arch/arm/mm/mm-rpc.c @@ -3,95 +3,48 @@ * * Extra MM routines for RiscPC architecture * - * Copyright (C) 1998 Russell King + * Copyright (C) 1998-1999 Russell King */ -#include <linux/sched.h> -#include <linux/slab.h> #include <linux/init.h> -#include <asm/pgtable.h> +#include <asm/hardware.h> +#include <asm/page.h> +#include <asm/proc/domain.h> #include <asm/setup.h> -#include <asm/io.h> -#include <asm/proc/mm-init.h> -#include <asm/arch/mm-init.h> -#define NR_DRAM_BANKS 4 -#define NR_VRAM_BANKS 1 +#include "map.h" -#define NR_BANKS (NR_DRAM_BANKS + NR_VRAM_BANKS) +#define SIZE(x) (sizeof(x) / sizeof(x[0])) -#define FIRST_BANK 0 -#define FIRST_DRAM_BANK 0 -#define FIRST_VRAM_BANK NR_DRAM_BANKS - -#define BANK_SHIFT 26 -#define FIRST_DRAM_ADDR 0x10000000 - -#define PHYS_TO_BANK(x) (((x) >> BANK_SHIFT) & (NR_DRAM_BANKS - 1)) -#define BANK_TO_PHYS(x) ((FIRST_DRAM_ADDR) + \ - (((x) - FIRST_DRAM_BANK) << BANK_SHIFT)) - -struct ram_bank { - unsigned int virt_addr; /* virtual address of the *end* of this bank + 1 */ - signed int phys_offset; /* offset to physical address of this bank */ +struct mem_desc mem_desc[] __initdata = { + { 0xc0000000, 0xc0000000 }, + { 0xc4000000, 0xc4000000 }, + { 0xc8000000, 0xc8000000 }, + { 0xcc000000, 0xcc000000 } }; -static struct ram_bank rambank[NR_BANKS]; - -/* - * Return the physical (0x10000000 -> 0x20000000) address of - * the virtual (0xc0000000 -> 0xd0000000) address - */ -unsigned long __virt_to_phys(unsigned long vpage) -{ - unsigned int bank = FIRST_BANK; - - while (vpage >= rambank[bank].virt_addr && bank < NR_BANKS) - bank ++; - - return vpage - rambank[bank].phys_offset; -} - -/* - * Return the virtual (0xc0000000 -> 0xd0000000) address of - * the physical (0x10000000 -> 0x20000000) address - */ -unsigned long __phys_to_virt(unsigned long phys) -{ - unsigned int bank; - - if (phys > FIRST_DRAM_ADDR) - bank = PHYS_TO_BANK(phys); - else - bank = FIRST_VRAM_BANK; - - return phys + rambank[bank].phys_offset; -} +unsigned int __initdata mem_desc_size = SIZE(mem_desc); void __init init_dram_banks(struct param_struct *params) { unsigned int bank; - unsigned int bytes = 0; - for (bank = FIRST_DRAM_BANK; bank < NR_DRAM_BANKS; bank++) { - rambank[bank].phys_offset = PAGE_OFFSET + bytes - - BANK_TO_PHYS(bank); + for (bank = 0; bank < mem_desc_size; bank++) + mem_desc[bank].virt_end += PAGE_SIZE * + params->u1.s.pages_in_bank[bank]; - bytes += params->u1.s.pages_in_bank[bank - FIRST_DRAM_BANK] * PAGE_SIZE; - - rambank[bank].virt_addr = PAGE_OFFSET + bytes; - } - - rambank[FIRST_VRAM_BANK].phys_offset = 0xd6000000; - rambank[FIRST_VRAM_BANK].virt_addr = 0xd8000000; + params->u1.s.nr_pages = mem_desc[3].virt_end - PAGE_OFFSET; + params->u1.s.nr_pages /= PAGE_SIZE; } -#define MAPPING \ - { SCREEN2_BASE, SCREEN_START, 2*1048576, DOMAIN_IO, 0, 1 }, /* VRAM */ \ - { IO_BASE, IO_START, IO_SIZE , DOMAIN_IO, 0, 1 }, /* IO space */ \ - { EASI_BASE, EASI_START, EASI_SIZE, DOMAIN_IO, 0, 1 } /* EASI space */ -/* - * Include common routine to set up page tables - */ -#include "mm-armv.c" +struct map_desc io_desc[] __initdata = { + /* VRAM */ + { SCREEN2_BASE, SCREEN_START, 2*1048576, DOMAIN_IO, 0, 1, 0, 0 }, + /* IO space */ + { IO_BASE, IO_START, IO_SIZE , DOMAIN_IO, 0, 1, 0, 0 }, + /* EASI space */ + { EASI_BASE, EASI_START, EASI_SIZE, DOMAIN_IO, 0, 1, 0, 0 } +}; + +unsigned int __initdata io_desc_size = SIZE(io_desc); diff --git a/arch/arm/mm/mm-sa1100.c b/arch/arm/mm/mm-sa1100.c new file mode 100644 index 000000000..eba2984b6 --- /dev/null +++ b/arch/arm/mm/mm-sa1100.c @@ -0,0 +1,84 @@ +/* + * arch/arm/mm/mm-sa1100.c + * + * Extra MM routines for the SA1100 architecture + * + * Copyright (C) 1998-1999 Russell King + * Copyright (C) 1999 Hugo Fiennes + * + * 1999/09/12 Nicolas Pitre <nico@visuaide.com> + * Specific RAM implementation details are in + * linux/include/asm/arch-sa1100/memory.h now. + * Allows for better macro optimisations when possible. + */ +#include <linux/config.h> +#include <linux/mm.h> +#include <linux/init.h> + +#include <asm/pgtable.h> +#include <asm/page.h> + +#include "map.h" + +#define SIZE(x) (sizeof(x) / sizeof(x[0])) + +/* + * These are the memory size mappings for the + * SA1100. Note that LART is a special case - + * it doesn't use physical address A23 on the + * DRAM, so we effectively have 4 * 8MB in + * two banks. + */ +struct mem_desc mem_desc[] __initdata = { + /* virt start virt end */ +#if defined(CONFIG_SA1100_BRUTUS) + { 0xc0000000, 0xc0400000 }, /* 4MB */ + { 0xc1000000, 0xc1400000 }, /* 4MB */ + { 0xc2000000, 0xc2400000 }, /* 4MB */ + { 0xc3000000, 0xc3400000 } /* 4MB */ +#elif defined(CONFIG_SA1100_EMPEG) + { 0xc0000000, 0xc0400000 }, /* 4MB */ + { 0xc1000000, 0xc1400000 } /* 4MB */ +#elif defined(CONFIG_SA1100_LART) + { 0xc0000000, 0xc0800000 }, /* 16MB */ + { 0xc1000000, 0xc1800000 }, + { 0xc2000000, 0xc2800000 }, /* 16MB */ + { 0xc3000000, 0xc3800000 } +#elif defined(CONFIG_SA1100_VICTOR) + { 0xc0000000, 0xc0400000 } /* 4MB */ +#elif defined(CONFIG_SA1100_TIFON) + { 0xc0000000, 0xc1000000 }, /* 16MB */ + { 0xc1000000, 0xc2000000 } /* 16MB */ +#else +#error missing memory configuration +#endif +}; + +unsigned int __initdata mem_desc_size = SIZE(mem_desc); + +struct map_desc io_desc[] __initdata = { + /* virtual physical length domain r w c b */ +#if defined(CONFIG_SA1100_VICTOR) + { 0xd0000000, 0x00000000, 0x00200000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash */ +#elif defined(CONFIG_SA1100_EMPEG) + { EMPEG_FLASHBASE, 0x00000000, 0x00200000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash */ +#elif defined(CONFIG_SA1100_TIFON) + { 0xd0000000, 0x00000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 */ + { 0xd0800000, 0x08000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 2 */ +#endif +#ifdef CONFIG_SA1101 + { 0xdc000000, SA1101_BASE, 0x00400000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA1101 */ +#endif + { 0xe0000000, 0x20000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA0 IO */ + { 0xe4000000, 0x30000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA1 IO */ + { 0xe8000000, 0x28000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA0 attr */ + { 0xec000000, 0x38000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA1 attr */ + { 0xf0000000, 0x2c000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA0 mem */ + { 0xf4000000, 0x3c000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA1 mem */ + { 0xf8000000, 0x80000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCM */ + { 0xfa000000, 0x90000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* SCM */ + { 0xfc000000, 0xa0000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* MER */ + { 0xfe000000, 0xb0000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 } /* LCD + DMA */ +}; + +unsigned int __initdata io_desc_size = SIZE(io_desc); diff --git a/arch/arm/mm/mm-tbox.c b/arch/arm/mm/mm-tbox.c index 2cc5cc9e1..a6dd2a28f 100644 --- a/arch/arm/mm/mm-tbox.c +++ b/arch/arm/mm/mm-tbox.c @@ -5,7 +5,7 @@ * Extra MM routines for the Tbox architecture * * Copyright (C) 1998 Phil Blundell - * Copyright (C) 1998 Russell King + * Copyright (C) 1998-1999 Russell King */ #include <linux/sched.h> @@ -15,9 +15,15 @@ #include <asm/io.h> #include <asm/pgtable.h> #include <asm/page.h> -#include <asm/proc/mm-init.h> - + +#include "map.h" +struct mem_desc mem_desc[] __initdata = { + 0, 0 +}; + +unsigned int __initdata mem_desc_size = 0; + /* Logical Physical * 0xffff1000 0x00100000 DMA registers * 0xffff2000 0x00200000 MPEG @@ -34,23 +40,26 @@ * 0xffffd000 0x00d00000 Interrupt reset * 0xffffe000 0x00e00000 MPEG DMA throttle */ - -#define MAPPING \ - { 0xffff0000, 0x01000000, 0x00001000, DOMAIN_IO, 0, 1 }, \ - { 0xffff1000, 0x00100000, 0x00001000, DOMAIN_IO, 0, 1 }, \ - { 0xffff2000, 0x00200000, 0x00001000, DOMAIN_IO, 0, 1 }, \ - { 0xffff3000, 0x00300000, 0x00001000, DOMAIN_IO, 0, 1 }, \ - { 0xffff4000, 0x00400000, 0x00001000, DOMAIN_IO, 0, 1 }, \ - { 0xfe000000, 0x00400000, 0x00001000, DOMAIN_IO, 0, 1 }, \ - { 0xffff5000, 0x00500000, 0x00001000, DOMAIN_IO, 0, 1 }, \ - { 0xffff6000, 0x00600000, 0x00001000, DOMAIN_IO, 0, 1 }, \ - { 0xffff7000, 0x00700000, 0x00001000, DOMAIN_IO, 0, 1 }, \ - { 0xffff8000, 0x00800000, 0x00001000, DOMAIN_IO, 0, 1 }, \ - { 0xffff9000, 0x00900000, 0x00001000, DOMAIN_IO, 0, 1 }, \ - { 0xffffa000, 0x00a00000, 0x00001000, DOMAIN_IO, 0, 1 }, \ - { 0xffffb000, 0x00b00000, 0x00001000, DOMAIN_IO, 0, 1 }, \ - { 0xffffc000, 0x00c00000, 0x00001000, DOMAIN_IO, 0, 1 }, \ - { 0xffffd000, 0x00d00000, 0x00001000, DOMAIN_IO, 0, 1 }, \ - { 0xffffe000, 0x00e00000, 0x00001000, DOMAIN_IO, 0, 1 } - -#include "mm-armv.c" + +const struct map_desc io_desc[] __initdata = { + { 0xffff0000, 0x01000000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, + { 0xffff1000, 0x00100000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, + { 0xffff2000, 0x00200000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, + { 0xffff3000, 0x00300000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, + { 0xffff4000, 0x00400000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, + { 0xfe000000, 0x00400000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, + { 0xffff5000, 0x00500000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, + { 0xffff6000, 0x00600000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, + { 0xffff7000, 0x00700000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, + { 0xffff8000, 0x00800000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, + { 0xffff9000, 0x00900000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, + { 0xffffa000, 0x00a00000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, + { 0xffffb000, 0x00b00000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, + { 0xffffc000, 0x00c00000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, + { 0xffffd000, 0x00d00000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, + { 0xffffe000, 0x00e00000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 } +}; + +#define SIZEOFMAP (sizeof(mapping) / sizeof(mapping[0])) + +unsigned int __initdata io_desc_size = SIZEOFMAP; diff --git a/arch/arm/mm/proc-arm2,3.S b/arch/arm/mm/proc-arm2,3.S index 6ec34b612..df2e13357 100644 --- a/arch/arm/mm/proc-arm2,3.S +++ b/arch/arm/mm/proc-arm2,3.S @@ -12,349 +12,184 @@ #include "../lib/constants.h" /* - * Code common to all processors - MEMC specific not processor - * specific! + * MEMC workhorse code. It's both a horse which things it's a pig. */ - -LC1: .word SYMBOL_NAME(page_nr) -/* - * Function: arm2_3_update_map (struct task_struct *tsk) - * - * Params : tsk Task structure to be updated - * - * Purpose : Re-generate memc maps for task from its pseudo page tables - */ -_arm2_3_update_map: - mov ip, sp - stmfd sp!, {r4 - r6, fp, ip, lr, pc} - sub fp, ip, #4 - add r1, r0, #TSS_MEMCMAP - ldr r2, LC1 - ldr r2, [r2] - mov r3, #0x03f00000 - orr r3, r3, #0x00000f00 - orr r4, r3, #1 - orr r5, r3, #2 - orr r6, r3, #3 -1: stmia r1!, {r3, r4, r5, r6} @ Default mapping (null mapping) - add r3, r3, #4 - add r4, r4, #4 - add r5, r5, #4 - add r6, r6, #4 - stmia r1!, {r3, r4, r5, r6} @ Default mapping (null mapping) - add r3, r3, #4 - add r4, r4, #4 - add r5, r5, #4 - add r6, r6, #4 - subs r2, r2, #8 - bhi 1b - - adr r2, Lphystomemc32 @ r2 = conversion table to logical page number - ldr r4, [r0, #TSS_MEMMAP] @ r4 = active mem map - add r5, r4, #32 << 2 @ r5 = end of active mem map - add r0, r0, #TSS_MEMCMAP @ r0 = memc map - - mov r6, #0 -2: ldmia r4!, {r1, r3} - tst r1, #PAGE_PRESENT - blne update_map_pgd - add r6, r6, #32 << 2 - tst r3, #PAGE_PRESENT - blne update_map_pgd3 - add r6, r6, #32 << 2 - cmp r4, r5 - blt 2b - ldmea fp, {r4 - r6, fp, sp, pc}^ - -@ r0,r2,r3,r4,r5 = preserve -@ r1,ip = available -@ r0 = memc map -@ r1 = pgd entry -@ r2 = conversion table -@ r6 = logical page no << 2 - -update_map_pgd3: - mov r1, r3 -update_map_pgd: stmfd sp!, {r3, r4, r5, lr} - bic r4, r1, #3 @ r4 = page table - sub r5, r6, #1 << 2 - add ip, r4, #32 << 2 @ ip = end of page table - -1: ldr r1, [r4], #4 @ get entry - add r5, r5, #1 << 2 - tst r1, #PAGE_PRESENT @ page present? - blne Lconvertmemc @ yes - ldr r1, [r4], #4 @ get entry - add r5, r5, #1 << 2 - tst r1, #PAGE_PRESENT @ page present? - blne Lconvertmemc @ yes - ldr r1, [r4], #4 @ get entry - add r5, r5, #1 << 2 - tst r1, #PAGE_PRESENT @ page present? - blne Lconvertmemc @ yes - ldr r1, [r4], #4 @ get entry - add r5, r5, #1 << 2 - tst r1, #PAGE_PRESENT @ page present? - blne Lconvertmemc @ yes - cmp r4, ip - blt 1b - ldmfd sp!, {r3, r4, r5, pc}^ - -Lconvertmemc: mov r3, r1, lsr #13 @ - and r3, r3, #0x3fc @ Convert to memc physical page no - ldr r3, [r2, r3] @ - - tst r1, #PAGE_OLD|PAGE_NOT_USER @ check for MEMC read - biceq r3, r3, #0x200 @ - tsteq r1, #PAGE_READONLY|PAGE_CLEAN @ check for MEMC write - biceq r3, r3, #0x300 @ - - orr r3, r3, r5, lsl #13 - and r1, r5, #0x01800000 >> 13 - orr r3, r3, r1 - - and r1, r3, #255 - str r3, [r0, r1, lsl #2] - movs pc, lr - /* - * Function: arm2_3_update_cache (struct task_struct *tsk, unsigned long addr, pte_t pte) - * Params : tsk Task to update - * address Address of fault. - * pte New PTE at address - * Purpose : Update the mapping for this address. - * Notes : does the ARM3 run faster if you do not use the result in the next instruction? + * Function: cpu_memc_update_entry(pgd_t *pgd, unsigned long phys_pte, unsigned long addr) + * Params : pgd Page tables/MEMC mapping + * : phys_pte physical address, or PTE + * : addr virtual address */ -_arm2_3_update_cache: - tst r2, #PAGE_PRESENT - moveqs pc, lr - mov r3, r2, lsr #13 @ Physical page no. - adr ip, Lphystomemc32 @ Convert to logical page number +ENTRY(cpu_memc_update_entry) + tst r1, #PAGE_PRESENT @ is the page present + orreq r1, r1, #PAGE_OLD | PAGE_CLEAN + moveq r2, #0x01f00000 + mov r3, r1, lsr #13 @ convert to physical page nr and r3, r3, #0x3fc - mov r1, r1, lsr #15 - ldr r3, [ip, r3] @ Convert to memc phys page no. - tst r2, #PAGE_OLD|PAGE_NOT_USER + adr ip, memc_phys_table_32 + ldr r3, [ip, r3] + tst r1, #PAGE_OLD | PAGE_NOT_USER biceq r3, r3, #0x200 - tsteq r2, #PAGE_READONLY|PAGE_CLEAN + tsteq r1, #PAGE_READONLY | PAGE_CLEAN biceq r3, r3, #0x300 - mov ip, sp, lsr #13 - orr r3, r3, r1, lsl #15 - mov ip, ip, lsl #13 - and r1, r1, #0x300 - teq ip, r0 - orr r3, r3, r1, lsl #2 - add r0, r0, #TSS_MEMCMAP + mov r2, r2, lsr #15 @ virtual -> nr + orr r3, r3, r2, lsl #15 + and r2, r2, #0x300 + orr r3, r3, r2, lsl #2 and r2, r3, #255 - streqb r3, [r3] + sub r0, r0, #256 * 4 str r3, [r0, r2, lsl #2] - movs pc, lr - -#define PCD(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af) \ - .long a0| 0x03800300; .long a1| 0x03800300;\ - .long a2| 0x03800300; .long a3| 0x03800300;\ - .long a4| 0x03800300; .long a5| 0x03800300;\ - .long a6| 0x03800300; .long a7| 0x03800300;\ - .long a8| 0x03800300; .long a9| 0x03800300;\ - .long aa| 0x03800300; .long ab| 0x03800300;\ - .long ac| 0x03800300; .long ad| 0x03800300;\ - .long ae| 0x03800300; .long af| 0x03800300 - -@ Table to map from page number to vidc page number -Lphystomemc32: PCD(0x00,0x08,0x10,0x18,0x20,0x28,0x30,0x38,0x40,0x48,0x50,0x58,0x60,0x68,0x70,0x78) - PCD(0x01,0x09,0x11,0x19,0x21,0x29,0x31,0x39,0x41,0x49,0x51,0x59,0x61,0x69,0x71,0x79) - PCD(0x04,0x0C,0x14,0x1C,0x24,0x2C,0x34,0x3C,0x44,0x4C,0x54,0x5C,0x64,0x6C,0x74,0x7C) - PCD(0x05,0x0D,0x15,0x1D,0x25,0x2D,0x35,0x3D,0x45,0x4D,0x55,0x5D,0x65,0x6D,0x75,0x7D) - PCD(0x02,0x0A,0x12,0x1A,0x22,0x2A,0x32,0x3A,0x42,0x4A,0x52,0x5A,0x62,0x6A,0x72,0x7A) - PCD(0x03,0x0B,0x13,0x1B,0x23,0x2B,0x33,0x3B,0x43,0x4B,0x53,0x5B,0x63,0x6B,0x73,0x7B) - PCD(0x06,0x0E,0x16,0x1E,0x26,0x2E,0x36,0x3E,0x46,0x4E,0x56,0x5E,0x66,0x6E,0x76,0x7E) - PCD(0x07,0x0F,0x17,0x1F,0x27,0x2F,0x37,0x3F,0x47,0x4F,0x57,0x5F,0x67,0x6F,0x77,0x7F) - PCD(0x80,0x88,0x90,0x98,0xA0,0xA8,0xB0,0xB8,0xC0,0xC8,0xD0,0xD8,0xE0,0xE8,0xF0,0xF8) - PCD(0x81,0x89,0x91,0x99,0xA1,0xA9,0xB1,0xB9,0xC1,0xC9,0xD1,0xD9,0xE1,0xE9,0xF1,0xF9) - PCD(0x84,0x8C,0x94,0x9C,0xA4,0xAC,0xB4,0xBC,0xC4,0xCC,0xD4,0xDC,0xE4,0xEC,0xF4,0xFC) - PCD(0x85,0x8D,0x95,0x9D,0xA5,0xAD,0xB5,0xBD,0xC5,0xCD,0xD5,0xDD,0xE5,0xED,0xF5,0xFD) - PCD(0x82,0x8A,0x92,0x9A,0xA2,0xAA,0xB2,0xBA,0xC2,0xCA,0xD2,0xDA,0xE2,0xEA,0xF2,0xFA) - PCD(0x83,0x8B,0x93,0x9B,0xA3,0xAB,0xB3,0xBB,0xC3,0xCB,0xD3,0xDB,0xE3,0xEB,0xF3,0xFB) - PCD(0x86,0x8E,0x96,0x9E,0xA6,0xAE,0xB6,0xBE,0xC6,0xCE,0xD6,0xDE,0xE6,0xEE,0xF6,0xFE) - PCD(0x87,0x8F,0x97,0x9F,0xA7,0xAF,0xB7,0xBF,0xC7,0xCF,0xD7,0xDF,0xE7,0xEF,0xF7,0xFF) - + strb r3, [r3] + movs pc, lr /* - * Function: arm2_3_data_abort () - * - * Params : r0 = address of aborted instruction - * - * Purpose : - * - * Returns : r0 = address of abort - * : r1 = FSR - * : r2 != 0 if writing + * Params : r0 = preserved + * : r1 = memc table base (preserved) + * : r2 = page table entry + * : r3 = preserved + * : r4 = unused + * : r5 = memc physical address translation table + * : ip = virtual address (preserved) */ - -_arm2_3_data_abort: +update_pte: + mov r4, r2, lsr #13 + and r4, r4, #0x3fc + ldr r4, [r5, r4] @ covert to MEMC page + + tst r2, #PAGE_OLD | PAGE_NOT_USER @ check for MEMC read + biceq r4, r4, #0x200 + tsteq r2, #PAGE_READONLY | PAGE_CLEAN @ check for MEMC write + biceq r4, r4, #0x300 + + orr r4, r4, ip + and r2, ip, #0x01800000 + orr r4, r4, r2, lsr #13 + + and r2, r4, #255 + str r4, [r1, r2, lsl #2] movs pc, lr -_arm2_3_check_bugs: - bics pc, lr, #0x04000000 @ Clear FIQ disable bit - /* - * Processor specific - ARM2 + * Params : r0 = preserved + * : r1 = memc table base (preserved) + * : r2 = page table base + * : r3 = preserved + * : r4 = unused + * : r5 = memc physical address translation table + * : ip = virtual address (updated) */ +update_pte_table: + stmfd sp!, {r0, lr} + bic r0, r2, #3 +1: ldr r2, [r0], #4 @ get entry + tst r2, #PAGE_PRESENT @ page present + blne update_pte @ process pte + add ip, ip, #32768 @ increment virt addr + ldr r2, [r0], #4 @ get entry + tst r2, #PAGE_PRESENT @ page present + blne update_pte @ process pte + add ip, ip, #32768 @ increment virt addr + ldr r2, [r0], #4 @ get entry + tst r2, #PAGE_PRESENT @ page present + blne update_pte @ process pte + add ip, ip, #32768 @ increment virt addr + ldr r2, [r0], #4 @ get entry + tst r2, #PAGE_PRESENT @ page present + blne update_pte @ process pte + add ip, ip, #32768 @ increment virt addr + tst ip, #32768 * 31 @ finished? + bne 1b + ldmfd sp!, {r0, pc}^ -LC0: .word SYMBOL_NAME(page_nr) /* - * Function: arm2_switch_to (struct task_struct *prev, struct task_struct *next) - * Params : prev Old task structure - * : next New task structure for process to run - * Returns : prev - * Purpose : Perform a task switch, saving the old processes state, and restoring - * the new. - * Notes : We don't fiddle with the FP registers here - we postpone this until - * the new task actually uses FP. This way, we don't swap FP for tasks - * that do not require it. + * Function: cpu_memc_update_all(pgd_t *pgd) + * Params : pgd Page tables/MEMC mapping + * Notes : this is optimised for 32k pages */ -_arm2_switch_to: - stmfd sp!, {r4 - r9, fp, lr} @ Store most regs on stack - str sp, [r0, #TSS_SAVE] @ Save sp_SVC - ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC - mov r4, r1 - add r7, r1, #TSS_MEMCMAP @ Remap MEMC - ldr r1, LC0 - ldr r1, [r1] -1: ldmia r7!, {r2, r3, r5, r6} - strb r2, [r2] - strb r3, [r3] - strb r5, [r5] - strb r6, [r6] - ldmia r7!, {r2, r3, r5, r6} - strb r2, [r2] - strb r3, [r3] - strb r5, [r5] - strb r6, [r6] - subs r1, r1, #8 - bhi 1b - ldmfd sp!, {r4 - r9, fp, pc}^ @ Load all regs saved previously +ENTRY(cpu_memc_update_all) + stmfd sp!, {r4, r5, lr} + bl clear_tables + sub r1, r0, #256 * 4 @ start of MEMC tables + adr r5, memc_phys_table_32 @ Convert to logical page number + mov ip, #0 @ virtual address +1: ldmia r0!, {r2, r3} + tst r2, #PAGE_PRESENT + addeq ip, ip, #1048576 + blne update_pte_table + mov r2, r3 + tst r2, #PAGE_PRESENT + addeq ip, ip, #1048576 + blne update_pte_table + teq ip, #32 * 1048576 + bne 1b + ldmfd sp!, {r4, r5, pc}^ /* - * Function: arm2_remap_memc (struct task_struct *tsk) - * - * Params : tsk Task structure specifing the new mapping structure - * - * Purpose : remap MEMC tables + * Build the table to map from physical page number to memc page number */ -_arm2_remap_memc: - stmfd sp!, {lr} - add r0, r0, #TSS_MEMCMAP - ldr r1, LC0 - ldr r1, [r1] -1: ldmia r0!, {r2, r3, ip, lr} - strb r2, [r2] - strb r3, [r3] - strb ip, [ip] - strb lr, [lr] - ldmia r0!, {r2, r3, ip, lr} - strb r2, [r2] - strb r3, [r3] - strb ip, [ip] - strb lr, [lr] - subs r1, r1, #8 - bhi 1b - ldmfd sp!, {pc}^ + .type memc_phys_table_32, #object +memc_phys_table_32: + .irp b7, 0x00, 0x80 + .irp b6, 0x00, 0x02 + .irp b5, 0x00, 0x04 + .irp b4, 0x00, 0x01 + + .irp b3, 0x00, 0x40 + .irp b2, 0x00, 0x20 + .irp b1, 0x00, 0x10 + .irp b0, 0x00, 0x08 + .long 0x03800300 + \b7 + \b6 + \b5 + \b4 + \b3 + \b2 + \b1 + \b0 + .endr + .endr + .endr + .endr + + .endr + .endr + .endr + .endr + .size memc_phys_table_32, . - memc_phys_table_32 /* - * Function: arm2_xchg_1 (int new, volatile void *ptr) - * - * Params : new New value to store at... - * : ptr pointer to byte-wide location - * - * Purpose : Performs an exchange operation - * - * Returns : Original byte data at 'ptr' - * - * Notes : This will have to be changed if we ever use multi-processing using these - * processors, but that is very unlikely... + * helper for cpu_memc_update_all, this clears out all + * mappings, setting them close to the top of memory, + * and inaccessible (0x01f00000). + * Params : r0 = page table pointer */ -_arm2_xchg_1: mov r2, pc - orr r2, r2, #I_BIT - teqp r2, #0 - ldrb r2, [r1] - strb r0, [r1] - mov r0, r2 - movs pc, lr +clear_tables: ldr r1, _arm3_set_pgd - 4 + ldr r2, [r1] + sub r1, r0, #256 * 4 @ start of MEMC tables + add r2, r1, r2, lsl #2 @ end of tables + mov r3, #0x03f00000 @ Default mapping (null mapping) + orr r3, r3, #0x00000f00 + orr r4, r3, #1 + orr r5, r3, #2 + orr ip, r3, #3 +1: stmia r1!, {r3, r4, r5, ip} + add r3, r3, #4 + add r4, r4, #4 + add r5, r5, #4 + add ip, ip, #4 + stmia r1!, {r3, r4, r5, ip} + add r3, r3, #4 + add r4, r4, #4 + add r5, r5, #4 + add ip, ip, #4 + teq r1, r2 + bne 1b + mov pc, lr /* - * Function: arm2_xchg_4 (int new, volatile void *ptr) - * - * Params : new New value to store at... - * : ptr pointer to word-wide location - * - * Purpose : Performs an exchange operation - * - * Returns : Original word data at 'ptr' - * - * Notes : This will have to be changed if we ever use multi-processing using these - * processors, but that is very unlikely... + * Function: *_set_pgd(pgd_t *pgd) + * Params : pgd New page tables/MEMC mapping + * Purpose : update MEMC hardware with new mapping */ -_arm2_xchg_4: mov r2, pc - orr r2, r2, #I_BIT - teqp r2, #0 + .word SYMBOL_NAME(page_nr) +_arm3_set_pgd: mcr p15, 0, r1, c1, c0, 0 @ flush cache +_arm2_set_pgd: stmfd sp!, {lr} + ldr r1, _arm3_set_pgd - 4 ldr r2, [r1] - str r0, [r1] - mov r0, r2 -/* - * fall through - */ -/* - * Function: arm2_proc_init (void) - * : arm2_proc_fin (void) - * - * Purpose : Initialise / finalise processor specifics (none required) - */ -_arm2_proc_init: -_arm2_proc_fin: movs pc, lr -/* - * Function: arm3_switch_to (struct task_struct *prev, struct task_struct *next) - * Params : prev Old task structure - * : next New task structure for process to run - * Returns : prev - * Purpose : Perform a task switch, saving the old processes state, and restoring - * the new. - * Notes : We don't fiddle with the FP registers here - we postpone this until - * the new task actually uses FP. This way, we don't swap FP for tasks - * that do not require it. - */ -_arm3_switch_to: - stmfd sp!, {r4 - r9, fp, lr} @ Store most regs on stack - str sp, [r0, #TSS_SAVE] @ Save sp_SVC - ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC - mov r4, r1 - add r7, r1, #TSS_MEMCMAP @ Remap MEMC - ldr r1, LC0 - ldr r1, [r1] -1: ldmia r7!, {r2, r3, r5, r6} - strb r2, [r2] - strb r3, [r3] - strb r5, [r5] - strb r6, [r6] - ldmia r7!, {r2, r3, r5, r6} - strb r2, [r2] - strb r3, [r3] - strb r5, [r5] - strb r6, [r6] - subs r1, r1, #8 - bhi 1b - mcr p15, 0, r7, c1, c0, 0 @ flush cache - ldmfd sp!, {r4 - r9, fp, pc}^ @ Load all regs saved previously -/* - * Function: arm3_remap_memc (struct task_struct *tsk) - * - * Params : tsk Task structure specifing the new mapping structure - * - * Purpose : remap MEMC tables - */ -_arm3_remap_memc: - stmfd sp!, {lr} - add r0, r0, #TSS_MEMCMAP - ldr r1, LC0 - ldr r1, [r1] + sub r0, r0, #256 * 4 @ start of MEMC tables + add r1, r0, r2, lsl #2 @ end of tables 1: ldmia r0!, {r2, r3, ip, lr} strb r2, [r2] strb r3, [r3] @@ -365,14 +200,12 @@ _arm3_remap_memc: strb r3, [r3] strb ip, [ip] strb lr, [lr] - subs r1, r1, #8 - bhi 1b - mcr p15, 0, r0, c1, c0, 0 @ flush cache + teq r0, r1 + bne 1b ldmfd sp!, {pc}^ /* - * Function: arm3_proc_init (void) - * + * Function: *_proc_init (void) * Purpose : Initialise the cache control registers */ _arm3_proc_init: @@ -386,43 +219,55 @@ _arm3_proc_init: mcr p15, 0, r0, c1, c0 @ ARM3 Flush mov r0, #3 mcr p15, 0, r0, c2, c0 @ ARM3 Control +_arm2_proc_init: movs pc, lr /* - * Function: arm3_proc_fin (void) - * + * Function: *_proc_fin (void) * Purpose : Finalise processor (disable caches) */ _arm3_proc_fin: mov r0, #2 mcr p15, 0, r0, c2, c0 - movs pc, lr +_arm2_proc_fin: orrs pc, lr, #I_BIT|F_BIT /* - * Function: arm3_xchg_1 (int new, volatile void *ptr) - * + * Function: *_xchg_1 (int new, volatile void *ptr) * Params : new New value to store at... * : ptr pointer to byte-wide location - * * Purpose : Performs an exchange operation - * * Returns : Original byte data at 'ptr' */ +_arm2_xchg_1: mov r2, pc + orr r2, r2, #I_BIT + teqp r2, #0 + ldrb r2, [r1] + strb r0, [r1] + mov r0, r2 + movs pc, lr + _arm3_xchg_1: swpb r0, r0, [r1] movs pc, lr /* - * Function: arm3_xchg_4 (int new, volatile void *ptr) - * + * Function: *_xchg_4 (int new, volatile void *ptr) * Params : new New value to store at... * : ptr pointer to word-wide location - * * Purpose : Performs an exchange operation - * * Returns : Original word data at 'ptr' */ +_arm2_xchg_4: mov r2, pc + orr r2, r2, #I_BIT + teqp r2, #0 + ldr r2, [r1] + str r0, [r1] + mov r0, r2 + movs pc, lr + _arm3_xchg_4: swp r0, r0, [r1] movs pc, lr +_arm2_3_check_bugs: + bics pc, lr, #0x04000000 @ Clear FIQ disable bit armvlsi_name: .asciz "ARM/VLSI" _arm2_name: .asciz "arm2" @@ -436,57 +281,42 @@ _arm3_name: .asciz "arm3" */ .globl SYMBOL_NAME(arm2_processor_functions) SYMBOL_NAME(arm2_processor_functions): - .word _arm2_switch_to @ 4 - .word _arm2_3_data_abort @ 8 - .word _arm2_3_check_bugs @ 12 - .word _arm2_proc_init @ 16 - .word _arm2_proc_fin @ 20 - - .word _arm2_remap_memc @ 24 - .word _arm2_3_update_map @ 28 - .word _arm2_3_update_cache @ 32 - .word _arm2_xchg_1 @ 36 - .word SYMBOL_NAME(abort) @ 40 - .word _arm2_xchg_4 @ 44 - - .globl SYMBOL_NAME(arm250_processor_functions) -SYMBOL_NAME(arm250_processor_functions): - .word _arm2_switch_to @ 4 - .word _arm2_3_data_abort @ 8 - .word _arm2_3_check_bugs @ 12 - .word _arm2_proc_init @ 16 - .word _arm2_proc_fin @ 20 - - .word _arm2_remap_memc @ 24 - .word _arm2_3_update_map @ 28 - .word _arm2_3_update_cache @ 32 - .word _arm3_xchg_1 @ 36 - .word SYMBOL_NAME(abort) @ 40 - .word _arm3_xchg_4 @ 44 - - .globl SYMBOL_NAME(arm3_processor_functions) -SYMBOL_NAME(arm3_processor_functions): - .word _arm3_switch_to @ 4 - .word _arm2_3_data_abort @ 8 - .word _arm2_3_check_bugs @ 12 - .word _arm3_proc_init @ 16 - .word _arm3_proc_fin @ 20 - - .word _arm3_remap_memc @ 24 - .word _arm2_3_update_map @ 28 - .word _arm2_3_update_cache @ 32 - .word _arm3_xchg_1 @ 36 - .word SYMBOL_NAME(abort) @ 40 - .word _arm3_xchg_4 @ 44 + .word _arm2_3_check_bugs + .word _arm2_proc_init + .word _arm2_proc_fin + .word _arm2_set_pgd + .word _arm2_xchg_1 + .word SYMBOL_NAME(abort) + .word _arm2_xchg_4 cpu_arm2_info: .long armvlsi_name .long _arm2_name + .globl SYMBOL_NAME(arm250_processor_functions) +SYMBOL_NAME(arm250_processor_functions): + .word _arm2_3_check_bugs + .word _arm2_proc_init + .word _arm2_proc_fin + .word _arm2_set_pgd + .word _arm3_xchg_1 + .word SYMBOL_NAME(abort) + .word _arm3_xchg_4 + cpu_arm250_info: .long armvlsi_name .long _arm250_name + .globl SYMBOL_NAME(arm3_processor_functions) +SYMBOL_NAME(arm3_processor_functions): + .word _arm2_3_check_bugs + .word _arm3_proc_init + .word _arm3_proc_fin + .word _arm3_set_pgd + .word _arm3_xchg_1 + .word SYMBOL_NAME(abort) + .word _arm3_xchg_4 + cpu_arm3_info: .long armvlsi_name .long _arm3_name @@ -501,6 +331,8 @@ arm3_elf_name: .asciz "v2" .long 0x41560200 .long 0xfffffff0 + .long 0 + mov pc, lr .long arm2_arch_name .long arm2_elf_name .long 0 @@ -509,6 +341,8 @@ arm3_elf_name: .asciz "v2" .long 0x41560250 .long 0xfffffff0 + .long 0 + mov pc, lr .long arm3_arch_name .long arm3_elf_name .long 0 @@ -517,6 +351,8 @@ arm3_elf_name: .asciz "v2" .long 0x41560300 .long 0xfffffff0 + .long 0 + mov pc, lr .long arm3_arch_name .long arm3_elf_name .long 0 diff --git a/arch/arm/mm/proc-arm6,7.S b/arch/arm/mm/proc-arm6,7.S index 67fb0aa8b..f3819fa01 100644 --- a/arch/arm/mm/proc-arm6,7.S +++ b/arch/arm/mm/proc-arm6,7.S @@ -9,6 +9,7 @@ #include <linux/linkage.h> #include <asm/assembler.h> #include <asm/procinfo.h> +#include <asm/errno.h> #include "../lib/constants.h" /* @@ -70,6 +71,19 @@ ENTRY(cpu_arm7_flush_tlb_area) mov pc, lr /* + * Function: arm6_7_flush_tlb_page (unsigned long address, int flags) + * + * Params : address Address + * : flags b0 = I-TLB as well + * + * Purpose : flush a TLB entry + */ +ENTRY(cpu_arm6_flush_tlb_page) +ENTRY(cpu_arm7_flush_tlb_page) + mcr p15, 0, r0, c6, c0, 0 @ flush TLB + mov pc, lr + +/* * Function: arm6_7_data_abort () * * Params : r0 = address of aborted instruction @@ -89,6 +103,16 @@ msg: .ascii "DA*%p=%p\n\0" .align ENTRY(cpu_arm6_data_abort) +Ldata_simple: + ldr r4, [r0] @ read instruction causing problem + mov r2, r4, lsr #19 @ r2 b1 = L + and r2, r2, #2 @ check read/write bit + mrc p15, 0, r0, c6, c0, 0 @ get FAR + mrc p15, 0, r1, c5, c0, 0 @ get FSR + and r1, r1, #15 + mov pc, lr + +ENTRY(cpu_arm7_data_abort) ldr r4, [r0] @ read instruction causing problem mov r2, r4, lsr #19 @ r2 b1 = L and r1, r4, #15 << 24 @@ -98,10 +122,10 @@ ENTRY(cpu_arm6_data_abort) b Ldata_unknown b Ldata_unknown b Ldata_unknown - b Ldata_earlyldrpost @ ldr rd, [rn], #m - b Ldata_simple @ ldr rd, [rn, #m] @ RegVal - b Ldata_earlyldrpost @ ldr rd, [rn], rm - b Ldata_simple @ ldr rd, [rn, rm] + b Ldata_lateldrpostconst @ ldr rd, [rn], #m + b Ldata_lateldrpreconst @ ldr rd, [rn, #m] @ RegVal + b Ldata_lateldrpostreg @ ldr rd, [rn], rm + b Ldata_lateldrprereg @ ldr rd, [rn, rm] b Ldata_ldmstm @ ldm*a rn, <rlist> b Ldata_ldmstm @ ldm*b rn, <rlist> b Ldata_unknown @@ -119,29 +143,6 @@ Ldata_unknown: @ Part of jumptable bl SYMBOL_NAME(panic) Lstop: b Lstop -ENTRY(cpu_arm7_data_abort) - ldr r4, [r0] @ read instruction causing problem - mov r2, r4, lsr #19 @ r2 b1 = L - and r1, r4, #15 << 24 - add pc, pc, r1, lsr #22 @ Now branch to the relevent processing routine - movs pc, lr - b Ldata_unknown - b Ldata_unknown - b Ldata_unknown - b Ldata_unknown - b Ldata_lateldrpostconst @ ldr rd, [rn], #m - b Ldata_lateldrpreconst @ ldr rd, [rn, #m] @ RegVal - b Ldata_lateldrpostreg @ ldr rd, [rn], rm - b Ldata_lateldrprereg @ ldr rd, [rn, rm] - b Ldata_ldmstm @ ldm*a rn, <rlist> - b Ldata_ldmstm @ ldm*b rn, <rlist> - b Ldata_unknown - b Ldata_unknown - b Ldata_simple @ ldc rd, [rn], #m @ Same as ldr rd, [rn], #m - b Ldata_simple @ ldc rd, [rn, #m] - b Ldata_unknown - b Ldata_unknown - Ldata_ldmstm: tst r4, #1 << 21 @ check writeback bit beq Ldata_simple @@ -165,31 +166,16 @@ Ldata_ldmstm: tst r4, #1 << 21 @ check writeback bit add r7, r0, r7, lsl #2 @ Do correction (signed) str r7, [sp, r5, lsr #14] @ Put register -Ldata_simple: and r2, r2, #2 @ check read/write bit - mrc p15, 0, r0, c6, c0, 0 @ get FAR - mrc p15, 0, r1, c5, c0, 0 @ get FSR - and r1, r1, #15 - mov pc, lr - -Ldata_earlyldrpost: - tst r2, #4 - and r2, r2, #2 @ check read/write bit - orrne r2, r2, #1 @ T bit - mrc p15, 0, r0, c6, c0, 0 @ get FAR - mrc p15, 0, r1, c5, c0, 0 @ get FSR - and r1, r1, #15 - mov pc, lr - Ldata_lateldrpostconst: movs r1, r4, lsl #20 @ Get offset - beq Ldata_earlyldrpost @ if offset is zero, no effect + beq Ldata_simple @ if offset is zero, no effect and r5, r4, #15 << 16 @ Get Rn ldr r0, [sp, r5, lsr #14] tst r4, #1 << 23 @ U bit subne r0, r0, r1, lsr #20 addeq r0, r0, r1, lsr #20 str r0, [sp, r5, lsr #14] @ Put register - b Ldata_earlyldrpost + b Ldata_simple Ldata_lateldrpreconst: tst r4, #1 << 21 @ check writeback bit @@ -252,7 +238,7 @@ Ldata_lateldrpostreg: subne r0, r0, r1 addeq r0, r0, r1 str r0, [sp, r5, lsr #14] @ Put register - b Ldata_earlyldrpost + b Ldata_simple Ldata_lateldrprereg: tst r4, #1 << 21 @ check writeback bit @@ -319,10 +305,24 @@ ENTRY(cpu_arm7_check_bugs) mrs ip, cpsr bic ip, ip, #F_BIT msr cpsr, ip + mov pc, lr + ENTRY(cpu_arm6_proc_init) ENTRY(cpu_arm7_proc_init) + mov pc, lr + ENTRY(cpu_arm6_proc_fin) ENTRY(cpu_arm7_proc_fin) + mrs r0, cpsr + orr r0, r0, #F_BIT | I_BIT + msr cpsr, r0 + mov r0, #0x31 @ ....S..DP...M + mcr p15, 0, r0, c1, c0, 0 @ disable caches + mov pc, lr + +ENTRY(cpu_arm6_do_idle) +ENTRY(cpu_arm7_do_idle) + mov r0, #-EINVAL mov pc, lr /* @@ -381,23 +381,22 @@ ENTRY(cpu_arm6_set_pte) ENTRY(cpu_arm7_set_pte) str r1, [r0], #-1024 @ linux version + eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY + bic r2, r1, #0xff0 bic r2, r2, #3 orr r2, r2, #HPTE_TYPE_SMALL - tst r1, #LPTE_USER | LPTE_EXEC + tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec? orrne r2, r2, #HPTE_AP_READ - tst r1, #LPTE_WRITE - tstne r1, #LPTE_DIRTY - orrne r2, r2, #HPTE_AP_WRITE + tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty? + orreq r2, r2, #HPTE_AP_WRITE - tst r1, #LPTE_PRESENT - tstne r1, #LPTE_YOUNG - moveq r2, #0 + tst r1, #LPTE_PRESENT | LPTE_YOUNG @ Present and Young + movne r2, #0 str r2, [r0] @ hardware version - mcr p15, 0, r0, c7, c10, 1 @ clean D entry (drain is done by TLB fns) mov pc, lr /* @@ -407,13 +406,9 @@ ENTRY(cpu_arm7_set_pte) */ ENTRY(cpu_arm6_reset) ENTRY(cpu_arm7_reset) - mrs r1, cpsr - orr r1, r1, #F_BIT|I_BIT - msr cpsr, r1 mov r0, #0 mcr p15, 0, r0, c7, c0, 0 @ flush cache mcr p15, 0, r0, c5, c0, 0 @ flush TLB - mov r1, #F_BIT | I_BIT | 3 mov pc, lr cpu_armvlsi_name: @@ -428,6 +423,26 @@ cpu_arm710_name: .section ".text.init", #alloc, #execinstr +__arm6_setup: mov r0, #0 + mcr p15, 0, r0, c7, c0 @ flush caches on v3 + mcr p15, 0, r0, c5, c0 @ flush TLBs on v3 + mcr p15, 0, r4, c2, c0 @ load page table pointer + mov r0, #0x1f @ Domains 0, 1 = client + mcr p15, 0, r0, c3, c0 @ load domain access register + mov r0, #0x3d @ ....S..DPWC.M + orr r0, r0, #0x100 + mov pc, lr + +__arm7_setup: mov r0, #0 + mcr p15, 0, r0, c7, c0 @ flush caches on v3 + mcr p15, 0, r0, c5, c0 @ flush TLBs on v3 + mcr p15, 0, r4, c2, c0 @ load page table pointer + mov r0, #0x1f @ Domains 0, 1 = client + mcr p15, 0, r0, c3, c0 @ load domain access register + mov r0, #0x7d @ ....S.LDPWC.M + orr r0, r0, #0x100 + mov pc, lr + /* * Purpose : Function pointers used to access above functions - all calls * come through these @@ -452,6 +467,8 @@ ENTRY(arm6_processor_functions) .word cpu_arm6_flush_icache_area .word cpu_arm6_cache_wback_area .word cpu_arm6_cache_purge_area + .word cpu_arm6_flush_tlb_page + .word cpu_arm7_do_idle .size arm6_processor_functions, . - arm6_processor_functions /* @@ -478,6 +495,8 @@ ENTRY(arm7_processor_functions) .word cpu_arm7_flush_icache_area .word cpu_arm7_cache_wback_area .word cpu_arm7_cache_purge_area + .word cpu_arm7_flush_tlb_page + .word cpu_arm7_do_idle .size arm7_processor_functions, . - arm7_processor_functions .type cpu_arm6_info, #object @@ -519,9 +538,11 @@ cpu_elf_name: .asciz "v3" __arm6_proc_info: .long 0x41560600 .long 0xfffffff0 + .long 0x00000c12 + b __arm6_setup .long cpu_arch_name .long cpu_elf_name - .long HWCAP_SWP + .long HWCAP_SWP | HWCAP_26BIT .long cpu_arm6_info .long arm6_processor_functions .size __arm6_proc_info, . - __arm6_proc_info @@ -530,9 +551,11 @@ __arm6_proc_info: __arm610_proc_info: .long 0x41560610 .long 0xfffffff0 + .long 0x00000c12 + b __arm6_setup .long cpu_arch_name .long cpu_elf_name - .long HWCAP_SWP + .long HWCAP_SWP | HWCAP_26BIT .long cpu_arm610_info .long arm6_processor_functions .size __arm610_proc_info, . - __arm610_proc_info @@ -541,9 +564,11 @@ __arm610_proc_info: __arm7_proc_info: .long 0x41007000 .long 0xffffff00 + .long 0x00000c12 + b __arm7_setup .long cpu_arch_name .long cpu_elf_name - .long HWCAP_SWP + .long HWCAP_SWP | HWCAP_26BIT .long cpu_arm7_info .long arm7_processor_functions .size __arm7_proc_info, . - __arm7_proc_info @@ -552,9 +577,11 @@ __arm7_proc_info: __arm710_proc_info: .long 0x41007100 .long 0xfff8ff00 + .long 0x00000c12 + b __arm7_setup .long cpu_arch_name .long cpu_elf_name - .long HWCAP_SWP + .long HWCAP_SWP | HWCAP_26BIT .long cpu_arm710_info .long arm7_processor_functions .size __arm710_proc_info, . - __arm710_proc_info diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S index aecc223af..73c0f83df 100644 --- a/arch/arm/mm/proc-sa110.S +++ b/arch/arm/mm/proc-sa110.S @@ -4,7 +4,7 @@ * (C) 1997-1999 Russell King * * These are the low level assembler for performing cache and TLB - * functions on the sa110. + * functions on the StrongARM-110 and StrongARM-1100 */ #include <linux/linkage.h> #include <asm/assembler.h> @@ -17,6 +17,27 @@ */ #define MAX_AREA_SIZE 32768 + .macro flush_110_dcache rd, ra, re + add \re, \ra, #16384 @ only necessary for 16k +1001: ldr \rd, [\ra], #32 + teq \re, \ra + bne 1001b + .endm + + .macro flush_1100_dcache rd, ra, re + add \re, \ra, #8192 @ only necessary for 8k +1001: ldr \rd, [\ra], #32 + teq \re, \ra + bne 1001b +#ifdef FLUSH_BASE_MINICACHE + add \ra, \ra, #FLUSH_BASE_MINICACHE - FLUSH_BASE + add \re, \ra, #512 @ only 512 bytes +1002: ldr \rd, [\ra], #32 + teq \re, \ra + bne 1002b +#endif + .endm + .data Lclean_switch: .long 0 .text @@ -36,12 +57,27 @@ cpu_sa110_flush_cache_all_r2: eor r1, r1, #1 str r1, [r3] addne ip, ip, #32768 - add r1, ip, #16384 @ only necessary for 16k -1: ldr r3, [ip], #32 - teq r1, ip - bne 1b + flush_110_dcache r3, ip, r1 + mov ip, #0 + teq r2, #0 + mcrne p15, 0, ip, c7, c5, 0 @ flush I cache + mcr p15, 0, ip, c7, c10, 4 @ drain WB + mov pc, lr + + .align 5 +ENTRY(cpu_sa1100_flush_cache_all) @ preserves r0 + mov r2, #1 +cpu_sa1100_flush_cache_all_r2: + ldr r3, =Lclean_switch + ldr ip, =FLUSH_BASE + ldr r1, [r3] + ands r1, r1, #1 + eor r1, r1, #1 + str r1, [r3] + addne ip, ip, #32768 + flush_1100_dcache r3, ip, r1 mov ip, #0 - tst r2, #1 + teq r2, #0 mcrne p15, 0, ip, c7, c5, 0 @ flush I cache mcr p15, 0, ip, c7, c10, 4 @ drain WB mov pc, lr @@ -66,11 +102,17 @@ ENTRY(cpu_sa110_flush_cache_area) add r0, r0, #32 cmp r0, r1 blt 1b - tst r2, #1 + teq r2, #0 movne r0, #0 mcrne p15, 0, r0, c7, c5, 0 @ flush I cache mov pc, lr +ENTRY(cpu_sa1100_flush_cache_area) + sub r3, r1, r0 + cmp r3, #MAX_AREA_SIZE + bgt cpu_sa1100_flush_cache_all_r2 + b 1b + /* * Function: sa110_cache_wback_area(unsigned long address, unsigned long end) * Params : address Area start address @@ -94,6 +136,13 @@ ENTRY(cpu_sa110_cache_wback_area) mcr p15, 0, r2, c7, c10, 4 @ drain WB mov pc, lr +ENTRY(cpu_sa1100_cache_wback_area) + sub r3, r1, r0 + cmp r3, #MAX_AREA_SIZE + mov r2, #0 + bgt cpu_sa1100_flush_cache_all_r2 + bic r0, r0, #31 + b 1b /* * Function: sa110_cache_purge_area(unsigned long address, unsigned long end) * Params : address Area start address @@ -105,6 +154,7 @@ ENTRY(cpu_sa110_cache_wback_area) */ .align 5 ENTRY(cpu_sa110_cache_purge_area) +ENTRY(cpu_sa1100_cache_purge_area) tst r0, #31 bic r0, r0, #31 mcrne p15, 0, r0, c7, c10, 1 @ clean D entry @@ -123,6 +173,7 @@ ENTRY(cpu_sa110_cache_purge_area) */ .align 5 ENTRY(cpu_sa110_flush_cache_entry) +ENTRY(cpu_sa1100_flush_cache_entry) mov r1, #0 mcr p15, 0, r0, c7, c10, 1 @ clean D entry mcr p15, 0, r1, c7, c10, 4 @ drain WB @@ -136,6 +187,7 @@ ENTRY(cpu_sa110_flush_cache_entry) * for page table purposes. */ ENTRY(cpu_sa110_clean_cache_area) +ENTRY(cpu_sa1100_clean_cache_area) 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry (drain is done by TLB fns) add r0, r0, #32 subs r1, r1, #32 @@ -149,6 +201,7 @@ ENTRY(cpu_sa110_clean_cache_area) */ .align 5 ENTRY(cpu_sa110_flush_ram_page) +ENTRY(cpu_sa1100_flush_ram_page) mov r1, #4096 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry add r0, r0, #32 @@ -170,6 +223,7 @@ ENTRY(cpu_sa110_flush_ram_page) */ .align 5 ENTRY(cpu_sa110_flush_tlb_all) +ENTRY(cpu_sa1100_flush_tlb_all) mov r0, #0 mcr p15, 0, r0, c7, c10, 4 @ drain WB mcr p15, 0, r0, c8, c7, 0 @ flush I & D tlbs @@ -184,6 +238,7 @@ ENTRY(cpu_sa110_flush_tlb_all) */ .align 5 ENTRY(cpu_sa110_flush_tlb_area) +ENTRY(cpu_sa1100_flush_tlb_area) mov r3, #0 mcr p15, 0, r3, c7, c10, 4 @ drain WB 1: cmp r0, r1 @@ -193,12 +248,35 @@ ENTRY(cpu_sa110_flush_tlb_area) mcrlt p15, 0, r0, c8, c6, 1 @ flush D TLB entry addlt r0, r0, #4096 blt 1b - tst r2, #1 + teq r2, #0 mcrne p15, 0, r3, c8, c5, 0 @ flush I TLB mov pc, lr +/* + * Function: sa110_flush_tlb_page (unsigned long address, int flags) + * Params : address Address to flush + * : flags b0 = I-TLB as well + * Purpose : flush a TLB entry + */ + .align 5 +ENTRY(cpu_sa110_flush_tlb_page) +ENTRY(cpu_sa1100_flush_tlb_page) + mov r3, #0 + mcr p15, 0, r3, c7, c10, 4 @ drain WB + mcr p15, 0, r0, c8, c6, 1 @ flush D TLB entry + teq r1, #0 + mcrne p15, 0, r3, c8, c5, 0 @ flush I TLB + mov pc, lr + +/* + * Function: sa110_flush_icache_area (unsigned long address, unsigned long size) + * Params : address Address of area to flush + * : size Size of area to flush + * Purpose : flush an area from the Icache + */ .align 5 ENTRY(cpu_sa110_flush_icache_area) +ENTRY(cpu_sa1100_flush_icache_area) 1: mcr p15, 0, r0, c7, c10, 1 @ Clean D entry add r0, r0, #32 subs r1, r1, #32 @@ -218,6 +296,7 @@ ENTRY(cpu_sa110_flush_icache_area) */ .align 5 ENTRY(cpu_sa110_data_abort) +ENTRY(cpu_sa1100_data_abort) ldr r2, [r0] @ read instruction causing problem mrc p15, 0, r0, c6, c0, 0 @ get FAR mov r2, r2, lsr #19 @ b1 = L @@ -237,16 +316,30 @@ ENTRY(cpu_sa110_data_abort) .align 5 ENTRY(cpu_sa110_set_pgd) ldr r3, =Lclean_switch + ldr ip, =FLUSH_BASE ldr r2, [r3] ands r2, r2, #1 eor r2, r2, #1 str r2, [r3] - ldr r2, =FLUSH_BASE - addne r2, r2, #32768 - add r1, r2, #16384 @ only necessary for 16k -1: ldr r3, [r2], #32 - teq r1, r2 - bne 1b + addne ip, ip, #32768 + flush_110_dcache r3, ip, r1 + mov r1, #0 + mcr p15, 0, r1, c7, c5, 0 @ flush I cache + mcr p15, 0, r1, c7, c10, 4 @ drain WB + mcr p15, 0, r0, c2, c0, 0 @ load page table pointer + mcr p15, 0, r1, c8, c7, 0 @ flush TLBs + mov pc, lr + + .align 5 +ENTRY(cpu_sa1100_set_pgd) + ldr r3, =Lclean_switch + ldr ip, =FLUSH_BASE + ldr r2, [r3] + ands r2, r2, #1 + eor r2, r2, #1 + str r2, [r3] + addne ip, ip, #32768 + flush_1100_dcache r3, ip, r1 mov r1, #0 mcr p15, 0, r1, c7, c5, 0 @ flush I cache mcr p15, 0, r1, c7, c10, 4 @ drain WB @@ -262,9 +355,10 @@ ENTRY(cpu_sa110_set_pgd) */ .align 5 ENTRY(cpu_sa110_set_pmd) +ENTRY(cpu_sa1100_set_pmd) str r1, [r0] mcr p15, 0, r0, c7, c10, 1 @ clean D entry - mcr p15, 0, r0, c7, c10, 4 @ drain WB (TLB bypasses WB) + mcr p15, 0, r0, c7, c10, 4 @ drain WB mov pc, lr /* @@ -275,6 +369,7 @@ ENTRY(cpu_sa110_set_pmd) */ .align 5 ENTRY(cpu_sa110_set_pte) +ENTRY(cpu_sa1100_set_pte) str r1, [r0], #-1024 @ linux version eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY @@ -294,8 +389,8 @@ ENTRY(cpu_sa110_set_pte) str r2, [r0] @ hardware version mov r0, r0 - mcr p15, 0, r0, c7, c10, 1 @ clean D entry (drain is done by TLB fns) - mcr p15, 0, r0, c7, c10, 4 @ drain WB (TLB bypasses WB) + mcr p15, 0, r0, c7, c10, 1 @ clean D entry + mcr p15, 0, r0, c7, c10, 4 @ drain WB mov pc, lr /* @@ -305,12 +400,39 @@ ENTRY(cpu_sa110_set_pte) * Notes : This processor does not require these */ ENTRY(cpu_sa110_check_bugs) +ENTRY(cpu_sa1100_check_bugs) mrs ip, cpsr bic ip, ip, #F_BIT msr cpsr, ip + mov pc, lr ENTRY(cpu_sa110_proc_init) +ENTRY(cpu_sa1100_proc_init) + mov r0, #0 + mcr p15, 0, r0, c15, c1, 2 @ Enable clock switching + mov pc, lr + ENTRY(cpu_sa110_proc_fin) +ENTRY(cpu_sa1100_proc_fin) + mrs r0, cpsr + orr r0, r0, #F_BIT | I_BIT + msr cpsr, r0 + mov r0, #0 + mcr p15, 0, r0, c15, c2, 2 @ Disable clock switching + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x1100 @ ...i...s........ + bic r0, r0, #0x000e @ ............wca. + mcr p15, 0, r0, c1, c0, 0 @ disable caches + mov pc, lr + + .align 5 +ENTRY(cpu_sa110_do_idle) +ENTRY(cpu_sa1100_do_idle) + mov r0, #0 + mcr p15, 0, r0, c15, c2, 2 @ Disable clock switching + @ load from uncacheable loc? + mcr p15, 0, r0, c15, c8, 2 @ Wait for interrupt + mcr p15, 0, r0, c15, c1, 2 @ Enable clock switching mov pc, lr /* @@ -318,17 +440,13 @@ ENTRY(cpu_sa110_proc_fin) * Notes : This sets up everything for a reset */ ENTRY(cpu_sa110_reset) - mrs r1, cpsr - orr r1, r1, #F_BIT | I_BIT - msr cpsr, r1 +ENTRY(cpu_sa1100_reset) stmfd sp!, {r1, lr} - mov r2, #1 bl cpu_sa110_flush_cache_all bl cpu_sa110_flush_tlb_all mcr p15, 0, ip, c7, c7, 0 @ flush I,D caches mrc p15, 0, r0, c1, c0, 0 @ ctrl register - bic r0, r0, #0x1800 - bic r0, r0, #0x000f + bic r0, r0, #1 @ ...............m ldmfd sp!, {r1, pc} /* * Purpose : Function pointers used to access above functions - all calls @@ -338,10 +456,26 @@ ENTRY(cpu_sa110_reset) cpu_manu_name: .asciz "Intel" ENTRY(cpu_sa110_name) .asciz "sa110" +ENTRY(cpu_sa1100_name) + .asciz "sa1100" .align .section ".text.init", #alloc, #execinstr +__sa110_setup: mov r0, #0 + mcr p15, 0, r0, c7, c7 @ flush I,D caches on v4 + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4 + mcr p15, 0, r0, c8, c7 @ flush I,D TLBs on v4 + mcr p15, 0, r4, c2, c0 @ load page table pointer + mov r0, #0x1f @ Domains 0, 1 = client + mcr p15, 0, r0, c3, c0 @ load domain access register + mrc p15, 0, r0, c1, c0 @ get control register v4 + bic r0, r0, #0x0e00 @ ....??r......... + bic r0, r0, #0x0002 @ ..............a. + orr r0, r0, #0x003d @ ..........DPWC.M + orr r0, r0, #0x1100 @ ...I...S........ + mov pc, lr + .type sa110_processor_functions, #object ENTRY(sa110_processor_functions) .word cpu_sa110_data_abort @@ -362,7 +496,8 @@ ENTRY(sa110_processor_functions) .word cpu_sa110_flush_icache_area .word cpu_sa110_cache_wback_area .word cpu_sa110_cache_purge_area - + .word cpu_sa110_flush_tlb_page + .word cpu_sa110_do_idle .size sa110_processor_functions, . - sa110_processor_functions .type cpu_sa110_info, #object @@ -371,6 +506,36 @@ cpu_sa110_info: .long cpu_sa110_name .size cpu_sa110_info, . - cpu_sa110_info + + .type sa1100_processor_functions, #object +ENTRY(sa1100_processor_functions) + .word cpu_sa1100_data_abort + .word cpu_sa1100_check_bugs + .word cpu_sa1100_proc_init + .word cpu_sa1100_proc_fin + .word cpu_sa1100_flush_cache_all + .word cpu_sa1100_flush_cache_area + .word cpu_sa1100_flush_cache_entry + .word cpu_sa1100_clean_cache_area + .word cpu_sa1100_flush_ram_page + .word cpu_sa1100_flush_tlb_all + .word cpu_sa1100_flush_tlb_area + .word cpu_sa1100_set_pgd + .word cpu_sa1100_set_pmd + .word cpu_sa1100_set_pte + .word cpu_sa1100_reset + .word cpu_sa1100_flush_icache_area + .word cpu_sa1100_cache_wback_area + .word cpu_sa1100_cache_purge_area + .word cpu_sa1100_flush_tlb_page + .word cpu_sa1100_do_idle + .size sa1100_processor_functions, . - sa1100_processor_functions + +cpu_sa1100_info: + .long cpu_manu_name + .long cpu_sa1100_name + .size cpu_sa1100_info, . - cpu_sa1100_info + .type cpu_arch_name, #object cpu_arch_name: .asciz "armv4" .size cpu_arch_name, . - cpu_arch_name @@ -385,9 +550,26 @@ cpu_elf_name: .asciz "v4" __sa110_proc_info: .long 0x4401a100 .long 0xfffffff0 + .long 0x00000c02 + b __sa110_setup .long cpu_arch_name .long cpu_elf_name - .long HWCAP_SWP | HWCAP_HALF + .long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT .long cpu_sa110_info .long sa110_processor_functions .size __sa110_proc_info, . - __sa110_proc_info + + .type __sa1100_proc_info,#object +__sa1100_proc_info: + .long 0x4401a110 + .long 0xfffffff0 + .long 0x00000c02 + b __sa110_setup + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT + .long cpu_sa1100_info + .long sa1100_processor_functions + .size __sa1100_proc_info, . - __sa1100_proc_info + + diff --git a/arch/arm/nwfpe/ChangeLog b/arch/arm/nwfpe/ChangeLog index e160d36c3..8d76e09ba 100644 --- a/arch/arm/nwfpe/ChangeLog +++ b/arch/arm/nwfpe/ChangeLog @@ -1,10 +1,50 @@ -1998-11-23 Scott Bambrough <scottb@corelcomputer.com> +1999-08-19 Scott Bambrough <scottb@netwinder.org> + + * fpmodule.c - Changed version number to 0.95 + * fpa11.h - modified FPA11, FPREG structures + * fpa11.c - Changes due to FPA11, FPREG structure alterations. + * fpa11_cpdo.c - Changes due to FPA11, FPREG structure alterations. + * fpa11_cpdt.c - Changes due to FPA11, FPREG structure alterations. + * fpa11_cprt.c - Changes due to FPA11, FPREG structure alterations. + * single_cpdo.c - Changes due to FPA11, FPREG structure alterations. + * double_cpdo.c - Changes due to FPA11, FPREG structure alterations. + * extended_cpdo.c - Changes due to FPA11, FPREG structure alterations. + + * I discovered several bugs. First and worst is that the kernel + passes in a pointer to the FPE's state area. This is defined + as a struct user_fp (see user.h). This pointer was cast to a + FPA11*. Unfortunately FPA11 and user_fp are of different sizes; + user_fp is smaller. This meant that the FPE scribbled on things + below its area, which is bad, as the area is in the thread_struct + embedded in the process task structure. Thus we were scribbling + over one of the most important structures in the entire OS. + + * user_fp and FPA11 have now been harmonized. Most of the changes + in the above code were dereferencing problems due to moving the + register type out of FPREG, and getting rid of the union variable + fpvalue. + + * Second I noticed resetFPA11 was not always being called for a + task. This should happen on the first floating point exception + that occurs. It is controlled by init_flag in FPA11. The + comment in the code beside init_flag state the kernel guarantees + this to be zero. Not so. I found that the kernel recycles task + structures, and that recycled ones may not have init_flag zeroed. + I couldn't even find anything that guarantees it is zeroed when + when the task structure is initially allocated. In any case + I now initialize the entire FPE state in the thread structure to + zero when allocated and recycled. See alloc_task_struct() and + flush_thread() in arch/arm/process.c. The change to + alloc_task_struct() may not be necessary, but I left it in for + completeness (better safe than sorry). + +1998-11-23 Scott Bambrough <scottb@netwinder.org> * README.FPE - fix typo in description of lfm/sfm instructions * NOTES - Added file to describe known bugs/problems * fpmodule.c - Changed version number to 0.94 -1998-11-20 Scott Bambrough <scottb@corelcomputer.com> +1998-11-20 Scott Bambrough <scottb@netwinder.org> * README.FPE - fix description of URD, NRM instructions * TODO - remove URD, NRM instructions from TODO list @@ -12,7 +52,7 @@ * double_cpdo.c - implement URD, NRM * extended_cpdo.c - implement URD, NRM -1998-11-19 Scott Bambrough <scottb@corelcomputer.com> +1998-11-19 Scott Bambrough <scottb@netwinder.org> * ChangeLog - Added this file to track changes made. * fpa11.c - added code to initialize register types to typeNone diff --git a/arch/arm/nwfpe/Makefile b/arch/arm/nwfpe/Makefile index 5db79c6d4..a14371e5d 100644 --- a/arch/arm/nwfpe/Makefile +++ b/arch/arm/nwfpe/Makefile @@ -14,16 +14,15 @@ else NWFPE_OBJS += entry.o endif -L_TARGET := math-emu.a - ifeq ($(CONFIG_NWFPE),y) -L_OBJS = $(NWFPE_OBJS) +O_TARGET := math-emu.o +O_OBJS = $(NWFPE_OBJS) else ifeq ($(CONFIG_NWFPE),m) M_OBJS = nwfpe.o MI_OBJS = $(NWFPE_OBJS) endif -endif +endif include $(TOPDIR)/Rules.make diff --git a/arch/arm/nwfpe/double_cpdo.c b/arch/arm/nwfpe/double_cpdo.c index 3db9e7066..0415f31e0 100644 --- a/arch/arm/nwfpe/double_cpdo.c +++ b/arch/arm/nwfpe/double_cpdo.c @@ -19,7 +19,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "config.h" #include "softfloat.h" #include "fpopcode.h" #include "fpa11.h" @@ -54,14 +53,14 @@ unsigned int DoubleCPDO(const unsigned int opcode) } else { - switch (fpa11->fpreg[Fm].fType) + switch (fpa11->fType[Fm]) { case typeSingle: - rFm = float32_to_float64(fpa11->fpreg[Fm].fValue.fSingle); + rFm = float32_to_float64(fpa11->fpreg[Fm].fSingle); break; case typeDouble: - rFm = fpa11->fpreg[Fm].fValue.fDouble; + rFm = fpa11->fpreg[Fm].fDouble; break; case typeExtended: @@ -80,14 +79,14 @@ unsigned int DoubleCPDO(const unsigned int opcode) if (!MONADIC_INSTRUCTION(opcode)) { Fn = getFn(opcode); - switch (fpa11->fpreg[Fn].fType) + switch (fpa11->fType[Fn]) { case typeSingle: - rFn = float32_to_float64(fpa11->fpreg[Fn].fValue.fSingle); + rFn = float32_to_float64(fpa11->fpreg[Fn].fSingle); break; case typeDouble: - rFn = fpa11->fpreg[Fn].fValue.fDouble; + rFn = fpa11->fpreg[Fn].fDouble; break; default: return 0; @@ -100,62 +99,62 @@ unsigned int DoubleCPDO(const unsigned int opcode) { /* dyadic opcodes */ case ADF_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_add(rFn,rFm); + fpa11->fpreg[Fd].fDouble = float64_add(rFn,rFm); break; case MUF_CODE: case FML_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_mul(rFn,rFm); + fpa11->fpreg[Fd].fDouble = float64_mul(rFn,rFm); break; - case SUF_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_sub(rFn,rFm); + case SUF_CODE: + fpa11->fpreg[Fd].fDouble = float64_sub(rFn,rFm); break; case RSF_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_sub(rFm,rFn); + fpa11->fpreg[Fd].fDouble = float64_sub(rFm,rFn); break; case DVF_CODE: case FDV_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_div(rFn,rFm); + fpa11->fpreg[Fd].fDouble = float64_div(rFn,rFm); break; case RDF_CODE: case FRD_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_div(rFm,rFn); + fpa11->fpreg[Fd].fDouble = float64_div(rFm,rFn); break; #if 0 case POW_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_pow(rFn,rFm); + fpa11->fpreg[Fd].fDouble = float64_pow(rFn,rFm); break; case RPW_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_pow(rFm,rFn); + fpa11->fpreg[Fd].fDouble = float64_pow(rFm,rFn); break; #endif case RMF_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_rem(rFn,rFm); + fpa11->fpreg[Fd].fDouble = float64_rem(rFn,rFm); break; #if 0 case POL_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_pol(rFn,rFm); + fpa11->fpreg[Fd].fDouble = float64_pol(rFn,rFm); break; #endif /* monadic opcodes */ case MVF_CODE: - fpa11->fpreg[Fd].fValue.fDouble = rFm; + fpa11->fpreg[Fd].fDouble = rFm; break; case MNF_CODE: { unsigned int *p = (unsigned int*)&rFm; p[1] ^= 0x80000000; - fpa11->fpreg[Fd].fValue.fDouble = rFm; + fpa11->fpreg[Fd].fDouble = rFm; } break; @@ -163,55 +162,55 @@ unsigned int DoubleCPDO(const unsigned int opcode) { unsigned int *p = (unsigned int*)&rFm; p[1] &= 0x7fffffff; - fpa11->fpreg[Fd].fValue.fDouble = rFm; + fpa11->fpreg[Fd].fDouble = rFm; } break; case RND_CODE: case URD_CODE: - fpa11->fpreg[Fd].fValue.fDouble = + fpa11->fpreg[Fd].fDouble = int32_to_float64(float64_to_int32(rFm)); break; case SQT_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_sqrt(rFm); + fpa11->fpreg[Fd].fDouble = float64_sqrt(rFm); break; #if 0 case LOG_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_log(rFm); + fpa11->fpreg[Fd].fDouble = float64_log(rFm); break; case LGN_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_ln(rFm); + fpa11->fpreg[Fd].fDouble = float64_ln(rFm); break; case EXP_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_exp(rFm); + fpa11->fpreg[Fd].fDouble = float64_exp(rFm); break; case SIN_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_sin(rFm); + fpa11->fpreg[Fd].fDouble = float64_sin(rFm); break; case COS_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_cos(rFm); + fpa11->fpreg[Fd].fDouble = float64_cos(rFm); break; case TAN_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_tan(rFm); + fpa11->fpreg[Fd].fDouble = float64_tan(rFm); break; case ASN_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_arcsin(rFm); + fpa11->fpreg[Fd].fDouble = float64_arcsin(rFm); break; case ACS_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_arccos(rFm); + fpa11->fpreg[Fd].fDouble = float64_arccos(rFm); break; case ATN_CODE: - fpa11->fpreg[Fd].fValue.fDouble = float64_arctan(rFm); + fpa11->fpreg[Fd].fDouble = float64_arctan(rFm); break; #endif @@ -224,7 +223,7 @@ unsigned int DoubleCPDO(const unsigned int opcode) } } - if (0 != nRc) fpa11->fpreg[Fd].fType = typeDouble; + if (0 != nRc) fpa11->fType[Fd] = typeDouble; return nRc; } diff --git a/arch/arm/nwfpe/entry.S b/arch/arm/nwfpe/entry.S index 6f0077fbe..f6a9a9799 100644 --- a/arch/arm/nwfpe/entry.S +++ b/arch/arm/nwfpe/entry.S @@ -3,7 +3,7 @@ (c) Corel Computer Corporation, 1998 (c) Philip Blundell 1998-1999 - Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com> + Direct questions, comments to Scott Bambrough <scottb@netwinder.org> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -85,14 +85,15 @@ nwfpe_enter: mov r10, lr @ save the failure-return addresses ldr r5, [r4, #60] @ get contents of PC; - ldr r0, [r5, #-4] @ get actual instruction into r0 + sub r8, r5, #4 +.Lx2: ldrt r0, [r8], #0 @ get actual instruction into r0 emulate: bl EmulateAll @ emulate the instruction cmp r0, #0 @ was emulation successful moveq pc, r10 @ no, return failure next: -__x1: ldrt r6, [r5], #4 @ get the next instruction and +.Lx1: ldrt r6, [r5], #4 @ get the next instruction and @ increment PC and r2, r6, #0x0F000000 @ test for FP insns @@ -114,13 +115,15 @@ __x1: ldrt r6, [r5], #4 @ get the next instruction and mov r0, r6 @ prepare for EmulateAll() b emulate @ if r0 != 0, goto EmulateAll - @ We need to be prepared for the instruction at __x1 to fault. - @ Emit the appropriate exception gunk to fix things up. + @ We need to be prepared for the instruction at .Lx1 or .Lx2 + @ to fault. .section .fixup,"ax" .align -__f1: mov pc, r9 +.Lfix: mov pc, r9 .previous + .section __ex_table,"a" .align 3 - .long __x1, __f1 + .long .Lx2, .Lfix + .long .Lx1, .Lfix .previous diff --git a/arch/arm/nwfpe/entry26.S b/arch/arm/nwfpe/entry26.S index 6b1ec3354..5108ce63d 100644 --- a/arch/arm/nwfpe/entry26.S +++ b/arch/arm/nwfpe/entry26.S @@ -3,7 +3,7 @@ (c) Corel Computer Corporation, 1998 (c) Philip Blundell 1998-1999 - Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com> + Direct questions, comments to Scott Bambrough <scottb@netwinder.org> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/arch/arm/nwfpe/extended_cpdo.c b/arch/arm/nwfpe/extended_cpdo.c index 4f55333fc..810f57102 100644 --- a/arch/arm/nwfpe/extended_cpdo.c +++ b/arch/arm/nwfpe/extended_cpdo.c @@ -19,7 +19,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "config.h" #include "softfloat.h" #include "fpopcode.h" #include "fpa11.h" @@ -52,18 +51,18 @@ unsigned int ExtendedCPDO(const unsigned int opcode) } else { - switch (fpa11->fpreg[Fm].fType) + switch (fpa11->fType[Fm]) { case typeSingle: - rFm = float32_to_floatx80(fpa11->fpreg[Fm].fValue.fSingle); + rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle); break; case typeDouble: - rFm = float64_to_floatx80(fpa11->fpreg[Fm].fValue.fDouble); + rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble); break; case typeExtended: - rFm = fpa11->fpreg[Fm].fValue.fExtended; + rFm = fpa11->fpreg[Fm].fExtended; break; default: return 0; @@ -73,18 +72,18 @@ unsigned int ExtendedCPDO(const unsigned int opcode) if (!MONADIC_INSTRUCTION(opcode)) { Fn = getFn(opcode); - switch (fpa11->fpreg[Fn].fType) + switch (fpa11->fType[Fn]) { case typeSingle: - rFn = float32_to_floatx80(fpa11->fpreg[Fn].fValue.fSingle); + rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle); break; case typeDouble: - rFn = float64_to_floatx80(fpa11->fpreg[Fn].fValue.fDouble); + rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble); break; case typeExtended: - rFn = fpa11->fpreg[Fn].fValue.fExtended; + rFn = fpa11->fpreg[Fn].fExtended; break; default: return 0; @@ -96,112 +95,112 @@ unsigned int ExtendedCPDO(const unsigned int opcode) { /* dyadic opcodes */ case ADF_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_add(rFn,rFm); + fpa11->fpreg[Fd].fExtended = floatx80_add(rFn,rFm); break; case MUF_CODE: case FML_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_mul(rFn,rFm); + fpa11->fpreg[Fd].fExtended = floatx80_mul(rFn,rFm); break; case SUF_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_sub(rFn,rFm); + fpa11->fpreg[Fd].fExtended = floatx80_sub(rFn,rFm); break; case RSF_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_sub(rFm,rFn); + fpa11->fpreg[Fd].fExtended = floatx80_sub(rFm,rFn); break; case DVF_CODE: case FDV_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_div(rFn,rFm); + fpa11->fpreg[Fd].fExtended = floatx80_div(rFn,rFm); break; case RDF_CODE: case FRD_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_div(rFm,rFn); + fpa11->fpreg[Fd].fExtended = floatx80_div(rFm,rFn); break; #if 0 case POW_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_pow(rFn,rFm); + fpa11->fpreg[Fd].fExtended = floatx80_pow(rFn,rFm); break; case RPW_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_pow(rFm,rFn); + fpa11->fpreg[Fd].fExtended = floatx80_pow(rFm,rFn); break; #endif case RMF_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_rem(rFn,rFm); + fpa11->fpreg[Fd].fExtended = floatx80_rem(rFn,rFm); break; #if 0 case POL_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_pol(rFn,rFm); + fpa11->fpreg[Fd].fExtended = floatx80_pol(rFn,rFm); break; #endif /* monadic opcodes */ case MVF_CODE: - fpa11->fpreg[Fd].fValue.fExtended = rFm; + fpa11->fpreg[Fd].fExtended = rFm; break; case MNF_CODE: rFm.high ^= 0x8000; - fpa11->fpreg[Fd].fValue.fExtended = rFm; + fpa11->fpreg[Fd].fExtended = rFm; break; case ABS_CODE: rFm.high &= 0x7fff; - fpa11->fpreg[Fd].fValue.fExtended = rFm; + fpa11->fpreg[Fd].fExtended = rFm; break; case RND_CODE: case URD_CODE: - fpa11->fpreg[Fd].fValue.fExtended = + fpa11->fpreg[Fd].fExtended = int32_to_floatx80(floatx80_to_int32(rFm)); break; case SQT_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_sqrt(rFm); + fpa11->fpreg[Fd].fExtended = floatx80_sqrt(rFm); break; #if 0 case LOG_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_log(rFm); + fpa11->fpreg[Fd].fExtended = floatx80_log(rFm); break; case LGN_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_ln(rFm); + fpa11->fpreg[Fd].fExtended = floatx80_ln(rFm); break; case EXP_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_exp(rFm); + fpa11->fpreg[Fd].fExtended = floatx80_exp(rFm); break; case SIN_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_sin(rFm); + fpa11->fpreg[Fd].fExtended = floatx80_sin(rFm); break; case COS_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_cos(rFm); + fpa11->fpreg[Fd].fExtended = floatx80_cos(rFm); break; case TAN_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_tan(rFm); + fpa11->fpreg[Fd].fExtended = floatx80_tan(rFm); break; case ASN_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_arcsin(rFm); + fpa11->fpreg[Fd].fExtended = floatx80_arcsin(rFm); break; case ACS_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_arccos(rFm); + fpa11->fpreg[Fd].fExtended = floatx80_arccos(rFm); break; case ATN_CODE: - fpa11->fpreg[Fd].fValue.fExtended = floatx80_arctan(rFm); + fpa11->fpreg[Fd].fExtended = floatx80_arctan(rFm); break; #endif @@ -214,7 +213,7 @@ unsigned int ExtendedCPDO(const unsigned int opcode) } } - if (0 != nRc) fpa11->fpreg[Fd].fType = typeExtended; + if (0 != nRc) fpa11->fType[Fd] = typeExtended; return nRc; } diff --git a/arch/arm/nwfpe/fpa11.c b/arch/arm/nwfpe/fpa11.c index 3e11d5ddd..dfc4663b7 100644 --- a/arch/arm/nwfpe/fpa11.c +++ b/arch/arm/nwfpe/fpa11.c @@ -19,9 +19,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "config.h" +#include <asm/system.h> + #include "fpa11.h" -#include "milieu.h" #include "fpopcode.h" #include "fpmodule.h" @@ -39,17 +39,18 @@ FPA11 *fpa11; void resetFPA11(void) { int i; - /* initialize the registers */ + + /* initialize the register type array */ for (i=0;i<=7;i++) { - fpa11->fpreg[i].fType = typeNone; + fpa11->fType[i] = typeNone; } /* FPSR: set system id to FP_EMULATOR, clear all other bits */ fpa11->fpsr = FP_EMULATOR; /* FPCR: set SB, AB and DA bits, clear all others */ -#if MAINTAIN_FPCR +#if MAINTAIN_FPCR fpa11->fpcr = MASK_RESET; #endif } @@ -128,6 +129,9 @@ void SetRoundingPrecision(const unsigned int opcode) unsigned int EmulateAll(unsigned int opcode) { unsigned int nRc = 0; + unsigned long flags; + + save_flags(flags); sti(); if (fpa11->initflag == 0) /* good place for __builtin_expect */ { @@ -162,6 +166,8 @@ unsigned int EmulateAll(unsigned int opcode) nRc = 0; } + restore_flags(flags); + return(nRc); } diff --git a/arch/arm/nwfpe/fpa11.h b/arch/arm/nwfpe/fpa11.h index f7040dbb6..c55ac6f9b 100644 --- a/arch/arm/nwfpe/fpa11.h +++ b/arch/arm/nwfpe/fpa11.h @@ -31,25 +31,25 @@ #define typeDouble 0x02 #define typeExtended 0x03 -typedef struct tagFPREG { - unsigned int fType; - union { - float32 fSingle; - float64 fDouble; - floatx80 fExtended; - } fValue; +typedef union tagFPREG { + float32 fSingle; + float64 fDouble; + floatx80 fExtended; } FPREG; /* FPA11 device model */ typedef struct tagFPA11 { + FPREG fpreg[8]; /* 8 floating point registers */ + FPSR fpsr; /* floating point status register */ + FPCR fpcr; /* floating point control register */ + unsigned char fType[8]; /* type of floating point value held in + floating point registers. One of none + single, double or extended. */ int initflag; /* this is special. The kernel guarantees to set it to 0 when a thread is launched, so we can use it to detect whether this instance of the emulator needs to be initialised. */ - FPREG fpreg[8]; /* 8 floating point registers */ - FPSR fpsr; /* floating point status register */ - FPCR fpcr; /* floating point control register */ } FPA11; extern void resetFPA11(void); diff --git a/arch/arm/nwfpe/fpa11.inl b/arch/arm/nwfpe/fpa11.inl index 321ab7c1c..bc86317a2 100644 --- a/arch/arm/nwfpe/fpa11.inl +++ b/arch/arm/nwfpe/fpa11.inl @@ -2,7 +2,7 @@ NetWinder Floating Point Emulator (c) Corel Computer Corporation, 1998 - Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com> + Direct questions, comments to Scott Bambrough <scottb@netwinder.org> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/arch/arm/nwfpe/fpa11_cpdo.c b/arch/arm/nwfpe/fpa11_cpdo.c index 19dd08802..fd39a59f7 100644 --- a/arch/arm/nwfpe/fpa11_cpdo.c +++ b/arch/arm/nwfpe/fpa11_cpdo.c @@ -19,7 +19,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "config.h" #include "fpa11.h" #include "fpopcode.h" @@ -48,14 +47,14 @@ unsigned int EmulateCPDO(const unsigned int opcode) if (MONADIC_INSTRUCTION(opcode)) nType = nDest; else - nType = fpa11->fpreg[getFn(opcode)].fType; + nType = fpa11->fType[getFn(opcode)]; if (!CONSTANT_FM(opcode)) { register unsigned int Fm = getFm(opcode); - if (nType < fpa11->fpreg[Fm].fType) + if (nType < fpa11->fType[Fm]) { - nType = fpa11->fpreg[Fm].fType; + nType = fpa11->fType[Fm]; } } @@ -71,7 +70,7 @@ unsigned int EmulateCPDO(const unsigned int opcode) destination register is the correct size. If not force it to be. */ Fd = getFd(opcode); - nType = fpa11->fpreg[Fd].fType; + nType = fpa11->fType[Fd]; if ((0 != nRc) && (nDest != nType)) { switch (nDest) @@ -79,38 +78,38 @@ unsigned int EmulateCPDO(const unsigned int opcode) case typeSingle: { if (typeDouble == nType) - fpa11->fpreg[Fd].fValue.fSingle = - float64_to_float32(fpa11->fpreg[Fd].fValue.fDouble); + fpa11->fpreg[Fd].fSingle = + float64_to_float32(fpa11->fpreg[Fd].fDouble); else - fpa11->fpreg[Fd].fValue.fSingle = - floatx80_to_float32(fpa11->fpreg[Fd].fValue.fExtended); + fpa11->fpreg[Fd].fSingle = + floatx80_to_float32(fpa11->fpreg[Fd].fExtended); } break; case typeDouble: { if (typeSingle == nType) - fpa11->fpreg[Fd].fValue.fDouble = - float32_to_float64(fpa11->fpreg[Fd].fValue.fSingle); + fpa11->fpreg[Fd].fDouble = + float32_to_float64(fpa11->fpreg[Fd].fSingle); else - fpa11->fpreg[Fd].fValue.fDouble = - floatx80_to_float64(fpa11->fpreg[Fd].fValue.fExtended); + fpa11->fpreg[Fd].fDouble = + floatx80_to_float64(fpa11->fpreg[Fd].fExtended); } break; case typeExtended: { if (typeSingle == nType) - fpa11->fpreg[Fd].fValue.fExtended = - float32_to_floatx80(fpa11->fpreg[Fd].fValue.fSingle); + fpa11->fpreg[Fd].fExtended = + float32_to_floatx80(fpa11->fpreg[Fd].fSingle); else - fpa11->fpreg[Fd].fValue.fExtended = - float64_to_floatx80(fpa11->fpreg[Fd].fValue.fDouble); + fpa11->fpreg[Fd].fExtended = + float64_to_floatx80(fpa11->fpreg[Fd].fDouble); } break; } - fpa11->fpreg[Fd].fType = nDest; + fpa11->fType[Fd] = nDest; } return nRc; diff --git a/arch/arm/nwfpe/fpa11_cpdt.c b/arch/arm/nwfpe/fpa11_cpdt.c index e32bf3421..0bad18769 100644 --- a/arch/arm/nwfpe/fpa11_cpdt.c +++ b/arch/arm/nwfpe/fpa11_cpdt.c @@ -20,7 +20,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "config.h" #include "softfloat.h" #include "fpopcode.h" #include "fpa11.h" @@ -32,16 +31,16 @@ extern __inline__ void loadSingle(const unsigned int Fn,const unsigned int *pMem) { - fpa11->fpreg[Fn].fType = typeSingle; - get_user(fpa11->fpreg[Fn].fValue.fSingle, pMem); + fpa11->fType[Fn] = typeSingle; + get_user(fpa11->fpreg[Fn].fSingle, pMem); } extern __inline__ void loadDouble(const unsigned int Fn,const unsigned int *pMem) { unsigned int *p; - p = (unsigned int*)&fpa11->fpreg[Fn].fValue.fDouble; - fpa11->fpreg[Fn].fType = typeDouble; + p = (unsigned int*)&fpa11->fpreg[Fn].fDouble; + fpa11->fType[Fn] = typeDouble; get_user(p[0], &pMem[1]); get_user(p[1], &pMem[0]); /* sign & exponent */ } @@ -50,8 +49,8 @@ extern __inline__ void loadExtended(const unsigned int Fn,const unsigned int *pMem) { unsigned int *p; - p = (unsigned int*)&fpa11->fpreg[Fn].fValue.fExtended; - fpa11->fpreg[Fn].fType = typeExtended; + p = (unsigned int*)&fpa11->fpreg[Fn].fExtended; + fpa11->fType[Fn] = typeExtended; get_user(p[0], &pMem[0]); /* sign & exponent */ get_user(p[1], &pMem[2]); /* ls bits */ get_user(p[2], &pMem[1]); /* ms bits */ @@ -63,11 +62,11 @@ void loadMultiple(const unsigned int Fn,const unsigned int *pMem) register unsigned int *p; unsigned long x; - p = (unsigned int*)&(fpa11->fpreg[Fn].fValue); + p = (unsigned int*)&(fpa11->fpreg[Fn]); get_user(x, &pMem[0]); - fpa11->fpreg[Fn].fType = (x >> 14) & 0x00000003; + fpa11->fType[Fn] = (x >> 14) & 0x00000003; - switch (fpa11->fpreg[Fn].fType) + switch (fpa11->fType[Fn]) { case typeSingle: case typeDouble: @@ -94,17 +93,17 @@ void storeSingle(const unsigned int Fn,unsigned int *pMem) float32 val; register unsigned int *p = (unsigned int*)&val; - switch (fpa11->fpreg[Fn].fType) + switch (fpa11->fType[Fn]) { case typeDouble: - val = float64_to_float32(fpa11->fpreg[Fn].fValue.fDouble); + val = float64_to_float32(fpa11->fpreg[Fn].fDouble); break; case typeExtended: - val = floatx80_to_float32(fpa11->fpreg[Fn].fValue.fExtended); + val = floatx80_to_float32(fpa11->fpreg[Fn].fExtended); break; - default: val = fpa11->fpreg[Fn].fValue.fSingle; + default: val = fpa11->fpreg[Fn].fSingle; } put_user(p[0], pMem); @@ -116,17 +115,17 @@ void storeDouble(const unsigned int Fn,unsigned int *pMem) float64 val; register unsigned int *p = (unsigned int*)&val; - switch (fpa11->fpreg[Fn].fType) + switch (fpa11->fType[Fn]) { case typeSingle: - val = float32_to_float64(fpa11->fpreg[Fn].fValue.fSingle); + val = float32_to_float64(fpa11->fpreg[Fn].fSingle); break; case typeExtended: - val = floatx80_to_float64(fpa11->fpreg[Fn].fValue.fExtended); + val = floatx80_to_float64(fpa11->fpreg[Fn].fExtended); break; - default: val = fpa11->fpreg[Fn].fValue.fDouble; + default: val = fpa11->fpreg[Fn].fDouble; } put_user(p[1], &pMem[0]); /* msw */ put_user(p[0], &pMem[1]); /* lsw */ @@ -138,17 +137,17 @@ void storeExtended(const unsigned int Fn,unsigned int *pMem) floatx80 val; register unsigned int *p = (unsigned int*)&val; - switch (fpa11->fpreg[Fn].fType) + switch (fpa11->fType[Fn]) { case typeSingle: - val = float32_to_floatx80(fpa11->fpreg[Fn].fValue.fSingle); + val = float32_to_floatx80(fpa11->fpreg[Fn].fSingle); break; case typeDouble: - val = float64_to_floatx80(fpa11->fpreg[Fn].fValue.fDouble); + val = float64_to_floatx80(fpa11->fpreg[Fn].fDouble); break; - default: val = fpa11->fpreg[Fn].fValue.fExtended; + default: val = fpa11->fpreg[Fn].fExtended; } put_user(p[0], &pMem[0]); /* sign & exp */ @@ -161,8 +160,8 @@ void storeMultiple(const unsigned int Fn,unsigned int *pMem) { register unsigned int nType, *p; - p = (unsigned int*)&(fpa11->fpreg[Fn].fValue); - nType = fpa11->fpreg[Fn].fType; + p = (unsigned int*)&(fpa11->fpreg[Fn]); + nType = fpa11->fType[Fn]; switch (nType) { @@ -187,12 +186,17 @@ void storeMultiple(const unsigned int Fn,unsigned int *pMem) unsigned int PerformLDF(const unsigned int opcode) { - unsigned int *pBase, *pAddress, *pFinal, nRc = 1; - + unsigned int *pBase, *pAddress, *pFinal, nRc = 1, + write_back = WRITE_BACK(opcode); + //fp_printk("PerformLDF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode)); pBase = (unsigned int*)readRegister(getRn(opcode)); - if (REG_PC == getRn(opcode)) pBase += 2; + if (REG_PC == getRn(opcode)) + { + pBase += 2; + write_back = 0; + } pFinal = pBase; if (BIT_UP_SET(opcode)) @@ -210,19 +214,24 @@ unsigned int PerformLDF(const unsigned int opcode) default: nRc = 0; } - if (WRITE_BACK(opcode)) writeRegister(getRn(opcode),(unsigned int)pFinal); + if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal); return nRc; } unsigned int PerformSTF(const unsigned int opcode) { - unsigned int *pBase, *pAddress, *pFinal, nRc = 1; + unsigned int *pBase, *pAddress, *pFinal, nRc = 1, + write_back = WRITE_BACK(opcode); //fp_printk("PerformSTF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode)); SetRoundingMode(ROUND_TO_NEAREST); pBase = (unsigned int*)readRegister(getRn(opcode)); - if (REG_PC == getRn(opcode)) pBase += 2; + if (REG_PC == getRn(opcode)) + { + pBase += 2; + write_back = 0; + } pFinal = pBase; if (BIT_UP_SET(opcode)) @@ -240,15 +249,21 @@ unsigned int PerformSTF(const unsigned int opcode) default: nRc = 0; } - if (WRITE_BACK(opcode)) writeRegister(getRn(opcode),(unsigned int)pFinal); + if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal); return nRc; } unsigned int PerformLFM(const unsigned int opcode) { - unsigned int i, Fd, *pBase, *pAddress, *pFinal; + unsigned int i, Fd, *pBase, *pAddress, *pFinal, + write_back = WRITE_BACK(opcode); + pBase = (unsigned int*)readRegister(getRn(opcode)); - if (REG_PC == getRn(opcode)) pBase += 2; + if (REG_PC == getRn(opcode)) + { + pBase += 2; + write_back = 0; + } pFinal = pBase; if (BIT_UP_SET(opcode)) @@ -266,16 +281,21 @@ unsigned int PerformLFM(const unsigned int opcode) if (Fd == 8) Fd = 0; } - if (WRITE_BACK(opcode)) writeRegister(getRn(opcode),(unsigned int)pFinal); + if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal); return 1; } unsigned int PerformSFM(const unsigned int opcode) { - unsigned int i, Fd, *pBase, *pAddress, *pFinal; + unsigned int i, Fd, *pBase, *pAddress, *pFinal, + write_back = WRITE_BACK(opcode); pBase = (unsigned int*)readRegister(getRn(opcode)); - if (REG_PC == getRn(opcode)) pBase += 2; + if (REG_PC == getRn(opcode)) + { + pBase += 2; + write_back = 0; + } pFinal = pBase; if (BIT_UP_SET(opcode)) @@ -293,7 +313,7 @@ unsigned int PerformSFM(const unsigned int opcode) if (Fd == 8) Fd = 0; } - if (WRITE_BACK(opcode)) writeRegister(getRn(opcode),(unsigned int)pFinal); + if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal); return 1; } diff --git a/arch/arm/nwfpe/fpa11_cprt.c b/arch/arm/nwfpe/fpa11_cprt.c index cbfde092e..d479ee932 100644 --- a/arch/arm/nwfpe/fpa11_cprt.c +++ b/arch/arm/nwfpe/fpa11_cprt.c @@ -20,7 +20,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "config.h" #include "milieu.h" #include "softfloat.h" #include "fpopcode.h" @@ -65,37 +64,10 @@ unsigned int EmulateCPRT(const unsigned int opcode) case WFS_CODE >> 20: writeFPSR(readRegister(getRd(opcode))); break; case RFS_CODE >> 20: writeRegister(getRd(opcode),readFPSR()); break; -#if 0 - /* ?? Not at all sure about the mode checks here. Linux never - calls the emulator from a non-USR fault but we always run in SVC - mode. Is there even any point trying to emulate the way FPA11 - behaves in this respect? - - No - and I quote: 'The FPCR may only be present in some - implementations: it is there to control the hardware in an - implementation-specific manner, ... The user mode of the - ARM is not permitted to use this register, and the WFC and - RFC instructions will trap if tried from user mode.' - Therefore, we do not provide the RFC and WFC instructions. - (rmk, 3/05/1999) - */ - case WFC_CODE >> 20: - { - int mode = 0; - __asm__ volatile ("mrs %0, cpsr; and %0, %0, #0x1f;" : : "g" (mode)); - nRc = (0x13 == mode) ? 1 : 0; /* in SVC processor mode? */ - if (nRc) writeFPCR(readRegister(getRd(opcode))); - } - break; - - case RFC_CODE >> 20: - { - int mode = 0; - __asm__ volatile ("mrs %0, cpsr; and %0, %0, #0x1f;" : : "g" (mode)); - nRc = (0x13 == mode) ? 1 : 0; /* in SVC processor mode? */ - if (nRc) writeRegister(getRd(opcode),readFPCR()); break; - } - break; +#if 0 /* We currently have no use for the FPCR, so there's no point + in emulating it. */ + case WFC_CODE >> 20: writeFPCR(readRegister(getRd(opcode))); + case RFC_CODE >> 20: writeRegister(getRd(opcode),readFPCR()); break; #endif default: nRc = 0; @@ -114,24 +86,24 @@ unsigned int PerformFLT(const unsigned int opcode) { case ROUND_SINGLE: { - fpa11->fpreg[getFn(opcode)].fType = typeSingle; - fpa11->fpreg[getFn(opcode)].fValue.fSingle = + fpa11->fType[getFn(opcode)] = typeSingle; + fpa11->fpreg[getFn(opcode)].fSingle = int32_to_float32(readRegister(getRd(opcode))); } break; case ROUND_DOUBLE: { - fpa11->fpreg[getFn(opcode)].fType = typeDouble; - fpa11->fpreg[getFn(opcode)].fValue.fDouble = + fpa11->fType[getFn(opcode)] = typeDouble; + fpa11->fpreg[getFn(opcode)].fDouble = int32_to_float64(readRegister(getRd(opcode))); } break; case ROUND_EXTENDED: { - fpa11->fpreg[getFn(opcode)].fType = typeExtended; - fpa11->fpreg[getFn(opcode)].fValue.fExtended = + fpa11->fType[getFn(opcode)] = typeExtended; + fpa11->fpreg[getFn(opcode)].fExtended = int32_to_floatx80(readRegister(getRd(opcode))); } break; @@ -149,26 +121,26 @@ unsigned int PerformFIX(const unsigned int opcode) SetRoundingMode(opcode); - switch (fpa11->fpreg[Fn].fType) + switch (fpa11->fType[Fn]) { case typeSingle: { writeRegister(getRd(opcode), - float32_to_int32(fpa11->fpreg[Fn].fValue.fSingle)); + float32_to_int32(fpa11->fpreg[Fn].fSingle)); } break; case typeDouble: { writeRegister(getRd(opcode), - float64_to_int32(fpa11->fpreg[Fn].fValue.fDouble)); + float64_to_int32(fpa11->fpreg[Fn].fDouble)); } break; case typeExtended: { writeRegister(getRd(opcode), - floatx80_to_int32(fpa11->fpreg[Fn].fValue.fExtended)); + floatx80_to_int32(fpa11->fpreg[Fn].fExtended)); } break; @@ -226,27 +198,27 @@ static unsigned int PerformComparison(const unsigned int opcode) ?? Might be some mileage in avoiding this conversion if possible. Eg, if both operands are 32-bit, detect this and do a 32-bit comparison (cheaper than an 80-bit one). */ - switch (fpa11->fpreg[Fn].fType) + switch (fpa11->fType[Fn]) { case typeSingle: //fp_printk("single.\n"); - if (float32_is_nan(fpa11->fpreg[Fn].fValue.fSingle)) + if (float32_is_nan(fpa11->fpreg[Fn].fSingle)) goto unordered; - rFn = float32_to_floatx80(fpa11->fpreg[Fn].fValue.fSingle); + rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle); break; case typeDouble: //fp_printk("double.\n"); - if (float64_is_nan(fpa11->fpreg[Fn].fValue.fDouble)) + if (float64_is_nan(fpa11->fpreg[Fn].fDouble)) goto unordered; - rFn = float64_to_floatx80(fpa11->fpreg[Fn].fValue.fDouble); + rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble); break; case typeExtended: //fp_printk("extended.\n"); - if (floatx80_is_nan(fpa11->fpreg[Fn].fValue.fExtended)) + if (floatx80_is_nan(fpa11->fpreg[Fn].fExtended)) goto unordered; - rFn = fpa11->fpreg[Fn].fValue.fExtended; + rFn = fpa11->fpreg[Fn].fExtended; break; default: return 0; @@ -262,27 +234,27 @@ static unsigned int PerformComparison(const unsigned int opcode) else { //fp_printk("Fm = r%d which contains a ",Fm); - switch (fpa11->fpreg[Fm].fType) + switch (fpa11->fType[Fm]) { case typeSingle: //fp_printk("single.\n"); - if (float32_is_nan(fpa11->fpreg[Fm].fValue.fSingle)) + if (float32_is_nan(fpa11->fpreg[Fm].fSingle)) goto unordered; - rFm = float32_to_floatx80(fpa11->fpreg[Fm].fValue.fSingle); + rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle); break; case typeDouble: //fp_printk("double.\n"); - if (float64_is_nan(fpa11->fpreg[Fm].fValue.fDouble)) + if (float64_is_nan(fpa11->fpreg[Fm].fDouble)) goto unordered; - rFm = float64_to_floatx80(fpa11->fpreg[Fm].fValue.fDouble); + rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble); break; case typeExtended: //fp_printk("extended.\n"); - if (floatx80_is_nan(fpa11->fpreg[Fm].fValue.fExtended)) + if (floatx80_is_nan(fpa11->fpreg[Fm].fExtended)) goto unordered; - rFm = fpa11->fpreg[Fm].fValue.fExtended; + rFm = fpa11->fpreg[Fm].fExtended; break; default: return 0; @@ -303,6 +275,7 @@ static unsigned int PerformComparison(const unsigned int opcode) the data sheet, observation of how the Acorn emulator actually behaves (and how programs expect it to) and guesswork. */ flags |= CC_OVERFLOW; + flags &= ~(CC_ZERO | CC_NEGATIVE); if (BIT_AC & readFPSR()) flags |= CC_CARRY; diff --git a/arch/arm/nwfpe/fpmodule.c b/arch/arm/nwfpe/fpmodule.c index de28e39f5..b9ca935eb 100644 --- a/arch/arm/nwfpe/fpmodule.c +++ b/arch/arm/nwfpe/fpmodule.c @@ -1,3 +1,4 @@ + /* NetWinder Floating Point Emulator (c) Rebel.com, 1998-1999 @@ -20,30 +21,16 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "config.h" - -#ifdef MODULE #include <linux/module.h> #include <linux/version.h> -#else -#define MOD_INC_USE_COUNT -#define MOD_DEC_USE_COUNT -#endif +#include <linux/config.h> /* XXX */ #include <linux/types.h> #include <linux/kernel.h> #include <linux/signal.h> #include <linux/sched.h> -#include <linux/mm.h> #include <linux/init.h> -#include <linux/spinlock.h> - -#include <asm/system.h> -#include <asm/uaccess.h> -#include <asm/io.h> -#include <asm/atomic.h> -#include <asm/pgtable.h> /* XXX */ #include "softfloat.h" @@ -62,7 +49,7 @@ typedef struct task_struct* PTASK; int fp_printk(const char *,...); void fp_send_sig(unsigned long sig, PTASK p, int priv); #if LINUX_VERSION_CODE > 0x20115 -MODULE_AUTHOR("Scott Bambrough <scottb@netwinder.org>"); +MODULE_AUTHOR("Scott Bambrough <scottb@rebel.com>"); MODULE_DESCRIPTION("NWFPE floating point emulator"); #endif @@ -73,57 +60,51 @@ MODULE_DESCRIPTION("NWFPE floating point emulator"); #endif /* kernel function prototypes required */ -void C_SYMBOL_NAME(fp_setup)(void); +void fp_setup(void); /* external declarations for saved kernel symbols */ -extern unsigned int C_SYMBOL_NAME(kern_fp_enter); +extern void (*kern_fp_enter)(void); + +/* Original value of fp_enter from kernel before patched by fpe_init. */ +static void (*orig_fp_enter)(void); /* forward declarations */ extern void nwfpe_enter(void); -/* Original value of fp_enter from kernel before patched by fpe_init. */ -static unsigned int orig_fp_enter; - /* Address of user registers on the kernel stack. */ unsigned int *userRegisters; -void __init C_SYMBOL_NAME(fpe_version)(void) +void __init fpe_version(void) { static const char szTitle[] = "<4>NetWinder Floating Point Emulator "; - static const char szVersion[] = "V0.94.1 "; + static const char szVersion[] = "V0.95 "; static const char szCopyright[] = "(c) 1998-1999 Rebel.com\n"; - C_SYMBOL_NAME(fp_printk)(szTitle); - C_SYMBOL_NAME(fp_printk)(szVersion); - C_SYMBOL_NAME(fp_printk)(szCopyright); + fp_printk(szTitle); + fp_printk(szVersion); + fp_printk(szCopyright); } int __init fpe_init(void) { - /* Display title, version and copyright information. */ - C_SYMBOL_NAME(fpe_version)(); - - /* Save pointer to the old FP handler and then patch ourselves in */ - orig_fp_enter = C_SYMBOL_NAME(kern_fp_enter); - C_SYMBOL_NAME(kern_fp_enter) = (unsigned int)C_SYMBOL_NAME(nwfpe_enter); + if (sizeof(FPA11) > sizeof(union fp_state)) + printk(KERN_ERR "nwfpe: bad structure size\n"); + else { + /* Display title, version and copyright information. */ + fpe_version(); + + /* Save pointer to the old FP handler and then patch ourselves in */ + orig_fp_enter = kern_fp_enter; + kern_fp_enter = nwfpe_enter; + } return 0; } -#ifdef MODULE -int init_module(void) -{ - return(fpe_init()); -} - -void cleanup_module(void) +void __exit fpe_exit(void) { /* Restore the values we saved earlier. */ - C_SYMBOL_NAME(kern_fp_enter) = orig_fp_enter; + kern_fp_enter = orig_fp_enter; } -#endif - -#define _ARM_pc 60 -#define _ARM_cpsr 64 /* ScottB: November 4, 1998 @@ -135,7 +116,7 @@ fpmodule.c to integrate with the NetBSD kernel (I hope!). [1/1/99: Not quite true any more unfortunately. There is Linux-specific code to access data in user space in some other source files at the -moment. --philb] +moment (grep for get_user / put_user calls). --philb] float_exception_flags is a global variable in SoftFloat. @@ -147,8 +128,9 @@ cumulative exceptions flag byte are set and we return. void float_raise(signed char flags) { -#if 0 - printk(KERN_DEBUG "NWFPE: exception %08x at %08x from %08x\n", flags, +#ifdef CONFIG_DEBUG_USER + printk(KERN_DEBUG "NWFPE: %s[%d] takes exception %08x at %p from %08x\n", + current->comm, current->pid, flags, __builtin_return_address(0), userRegisters[15]); #endif @@ -156,7 +138,7 @@ void float_raise(signed char flags) if (readFPSR() & (flags << 16)) { /* raise exception */ - C_SYMBOL_NAME(fp_send_sig)(SIGFPE,C_SYMBOL_NAME(current),1); + fp_send_sig(SIGFPE, current, 1); } else { @@ -164,3 +146,6 @@ void float_raise(signed char flags) writeFPSR(flags); } } + +module_init(fpe_init); +module_exit(fpe_exit); diff --git a/arch/arm/nwfpe/fpmodule.inl b/arch/arm/nwfpe/fpmodule.inl index c76b7fd55..127b24218 100644 --- a/arch/arm/nwfpe/fpmodule.inl +++ b/arch/arm/nwfpe/fpmodule.inl @@ -1,23 +1,23 @@ /* NetWinder Floating Point Emulator - (c) Corel Computer Corporation, 1998 + (c) Rebel.com, 1998-1999 - Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com> + Direct questions, comments to Scott Bambrough <scottb@netwinder.org> - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ /* Address of user registers on the kernel stack. */ extern unsigned int *userRegisters; @@ -25,64 +25,60 @@ extern unsigned int *userRegisters; extern __inline__ unsigned int readRegister(const unsigned int nReg) { - /* Note: The CPU thinks it has dealt with the current instruction. As - a result the program counter has been advanced to the next - instruction, and points 4 bytes beyond the actual instruction - that caused the invalid instruction trap to occur. We adjust - for this in this routine. LDF/STF instructions with Rn = PC - depend on the PC being correct, as they use PC+8 in their - address calculations. */ - unsigned int val = userRegisters[nReg]; - - if (REG_PC == nReg) - val -= 4; - - return val; + /* Note: The CPU thinks it has dealt with the current instruction. As + a result the program counter has been advanced to the next + instruction, and points 4 bytes beyond the actual instruction + that caused the invalid instruction trap to occur. We adjust + for this in this routine. LDF/STF instructions with Rn = PC + depend on the PC being correct, as they use PC+8 in their + address calculations. */ + unsigned int val = userRegisters[nReg]; + if (REG_PC == nReg) val -= 4; + return val; } extern __inline__ void writeRegister(const unsigned int nReg, const unsigned int val) { - userRegisters[nReg] = val; + userRegisters[nReg] = val; } extern __inline__ unsigned int readCPSR(void) { - return (readRegister(REG_CPSR)); + return(readRegister(REG_CPSR)); } extern __inline__ void writeCPSR(const unsigned int val) { - writeRegister(REG_CPSR, val); + writeRegister(REG_CPSR,val); } extern __inline__ unsigned int readConditionCodes(void) { #ifdef __FPEM_TEST__ - return (0); + return(0); #else - return (readCPSR() & CC_MASK); + return(readCPSR() & CC_MASK); #endif } extern __inline__ void writeConditionCodes(const unsigned int val) { - unsigned int rval; - - /* - * Operate directly on userRegisters since - * the CPSR may be the PC register itself. - */ - rval = userRegisters[REG_CPSR] & ~CC_MASK; - userRegisters[REG_CPSR] = rval | (val & CC_MASK); + unsigned int rval; + /* + * Operate directly on userRegisters since + * the CPSR may be the PC register itself. + */ + rval = userRegisters[REG_CPSR] & ~CC_MASK; + userRegisters[REG_CPSR] = rval | (val & CC_MASK); } extern __inline__ unsigned int readMemoryInt(unsigned int *pMem) { - return *pMem; + return *pMem; } diff --git a/arch/arm/nwfpe/fpopcode.c b/arch/arm/nwfpe/fpopcode.c index 0d12f7269..4b01b43c6 100644 --- a/arch/arm/nwfpe/fpopcode.c +++ b/arch/arm/nwfpe/fpopcode.c @@ -19,7 +19,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "config.h" #include "softfloat.h" #include "fpopcode.h" #include "fpsr.h" diff --git a/arch/arm/nwfpe/single_cpdo.c b/arch/arm/nwfpe/single_cpdo.c index a2a9f6f81..77bb73515 100644 --- a/arch/arm/nwfpe/single_cpdo.c +++ b/arch/arm/nwfpe/single_cpdo.c @@ -19,8 +19,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "config.h" -#include "milieu.h" #include "softfloat.h" #include "fpopcode.h" #include "fpa11.h" @@ -51,10 +49,10 @@ unsigned int SingleCPDO(const unsigned int opcode) } else { - switch (fpa11->fpreg[Fm].fType) + switch (fpa11->fType[Fm]) { case typeSingle: - rFm = fpa11->fpreg[Fm].fValue.fSingle; + rFm = fpa11->fpreg[Fm].fSingle; break; default: return 0; @@ -64,10 +62,10 @@ unsigned int SingleCPDO(const unsigned int opcode) if (!MONADIC_INSTRUCTION(opcode)) { Fn = getFn(opcode); - switch (fpa11->fpreg[Fn].fType) + switch (fpa11->fType[Fn]) { case typeSingle: - rFn = fpa11->fpreg[Fn].fValue.fSingle; + rFn = fpa11->fpreg[Fn].fSingle; break; default: return 0; @@ -79,112 +77,112 @@ unsigned int SingleCPDO(const unsigned int opcode) { /* dyadic opcodes */ case ADF_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_add(rFn,rFm); + fpa11->fpreg[Fd].fSingle = float32_add(rFn,rFm); break; case MUF_CODE: case FML_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_mul(rFn,rFm); + fpa11->fpreg[Fd].fSingle = float32_mul(rFn,rFm); break; case SUF_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_sub(rFn,rFm); + fpa11->fpreg[Fd].fSingle = float32_sub(rFn,rFm); break; case RSF_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_sub(rFm,rFn); + fpa11->fpreg[Fd].fSingle = float32_sub(rFm,rFn); break; case DVF_CODE: case FDV_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_div(rFn,rFm); + fpa11->fpreg[Fd].fSingle = float32_div(rFn,rFm); break; case RDF_CODE: case FRD_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_div(rFm,rFn); + fpa11->fpreg[Fd].fSingle = float32_div(rFm,rFn); break; #if 0 case POW_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_pow(rFn,rFm); + fpa11->fpreg[Fd].fSingle = float32_pow(rFn,rFm); break; case RPW_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_pow(rFm,rFn); + fpa11->fpreg[Fd].fSingle = float32_pow(rFm,rFn); break; #endif case RMF_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_rem(rFn,rFm); + fpa11->fpreg[Fd].fSingle = float32_rem(rFn,rFm); break; #if 0 case POL_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_pol(rFn,rFm); + fpa11->fpreg[Fd].fSingle = float32_pol(rFn,rFm); break; #endif /* monadic opcodes */ case MVF_CODE: - fpa11->fpreg[Fd].fValue.fSingle = rFm; + fpa11->fpreg[Fd].fSingle = rFm; break; case MNF_CODE: rFm ^= 0x80000000; - fpa11->fpreg[Fd].fValue.fSingle = rFm; + fpa11->fpreg[Fd].fSingle = rFm; break; case ABS_CODE: rFm &= 0x7fffffff; - fpa11->fpreg[Fd].fValue.fSingle = rFm; + fpa11->fpreg[Fd].fSingle = rFm; break; case RND_CODE: case URD_CODE: - fpa11->fpreg[Fd].fValue.fSingle = + fpa11->fpreg[Fd].fSingle = int32_to_float32(float32_to_int32(rFm)); break; case SQT_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_sqrt(rFm); + fpa11->fpreg[Fd].fSingle = float32_sqrt(rFm); break; #if 0 case LOG_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_log(rFm); + fpa11->fpreg[Fd].fSingle = float32_log(rFm); break; case LGN_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_ln(rFm); + fpa11->fpreg[Fd].fSingle = float32_ln(rFm); break; case EXP_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_exp(rFm); + fpa11->fpreg[Fd].fSingle = float32_exp(rFm); break; case SIN_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_sin(rFm); + fpa11->fpreg[Fd].fSingle = float32_sin(rFm); break; case COS_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_cos(rFm); + fpa11->fpreg[Fd].fSingle = float32_cos(rFm); break; case TAN_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_tan(rFm); + fpa11->fpreg[Fd].fSingle = float32_tan(rFm); break; case ASN_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_arcsin(rFm); + fpa11->fpreg[Fd].fSingle = float32_arcsin(rFm); break; case ACS_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_arccos(rFm); + fpa11->fpreg[Fd].fSingle = float32_arccos(rFm); break; case ATN_CODE: - fpa11->fpreg[Fd].fValue.fSingle = float32_arctan(rFm); + fpa11->fpreg[Fd].fSingle = float32_arctan(rFm); break; #endif @@ -197,7 +195,7 @@ unsigned int SingleCPDO(const unsigned int opcode) } } - if (0 != nRc) fpa11->fpreg[Fd].fType = typeSingle; + if (0 != nRc) fpa11->fType[Fd] = typeSingle; return nRc; } diff --git a/arch/arm/vmlinux-armo.lds.in b/arch/arm/vmlinux-armo.lds.in index f336370b4..446f49924 100644 --- a/arch/arm/vmlinux-armo.lds.in +++ b/arch/arm/vmlinux-armo.lds.in @@ -3,16 +3,36 @@ * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz> */ OUTPUT_ARCH(arm) -ENTRY(_start) +ENTRY(stext) SECTIONS { . = TEXTADDR; + __init_begin = .; + .text.init : { *(.text.init) } + __proc_info_begin = .; + .proc.info : { *(.proc.info) } + __proc_info_end = .; + .data.init : { *(.data.init) } + . = ALIGN(16); + __setup_start = .; + .setup.init : { *(.setup.init) } + __setup_end = .; + __initcall_start = .; + .initcall.init : { *(.initcall.init) } + __initcall_end = .; + . = ALIGN(32768); + __init_end = .; + + .init.task : { + *(.init.task) + } + _text = .; /* Text and read-only data */ .text : { *(.text) *(.fixup) *(.gnu.warning) - } = 0x9090 + } .text.lock : { *(.text.lock) } /* out-of-line lock text */ .rodata : { *(.rodata) } .kstrtab : { *(.kstrtab) } @@ -26,27 +46,17 @@ SECTIONS __ksymtab : { *(__ksymtab) } __stop___ksymtab = .; + .got : { *(.got) } /* Global offset table */ + _etext = .; /* End of text section */ - . = ALIGN(8192); .data : { /* Data */ - *(.init.task) *(.data) CONSTRUCTORS } _edata = .; /* End of data section */ - . = ALIGN(32768); /* Init code and data */ - __init_begin = .; - .text.init : { *(.text.init) } - __proc_info_begin = .; - .proc.info : { *(.proc.info) } - __proc_info_end = .; - .data.init : { *(.data.init) } - . = ALIGN(32768); - __init_end = .; - __bss_start = .; /* BSS */ .bss : { *(.bss) diff --git a/arch/arm/vmlinux-armv.lds.in b/arch/arm/vmlinux-armv.lds.in index a1f6d414b..f83109875 100644 --- a/arch/arm/vmlinux-armv.lds.in +++ b/arch/arm/vmlinux-armv.lds.in @@ -3,11 +3,10 @@ * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz> */ OUTPUT_ARCH(arm) -ENTRY(_start) +ENTRY(stext) SECTIONS { . = TEXTADDR; - _text = .; /* Text and read-only data */ .text : { } /* Set text start address */ __init_begin = .; /* Init code and data */ @@ -38,6 +37,7 @@ SECTIONS . = ALIGN(4096); __netwinder_end = .; + _text = .; /* Text and read-only data */ .text.real : { /* Real text segment */ *(.text) *(.fixup) @@ -57,6 +57,8 @@ SECTIONS __ksymtab : { *(__ksymtab) } __stop___ksymtab = .; + .got : { *(.got) } /* Global offset table */ + _etext = .; /* End of text section */ . = ALIGN(8192); |