diff --git a/arch/mips/boards/qemu-malta/init.c b/arch/mips/boards/qemu-malta/init.c index 2a6eadb..0efc92a 100644 --- a/arch/mips/boards/qemu-malta/init.c +++ b/arch/mips/boards/qemu-malta/init.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -30,6 +31,14 @@ #include #include +static int malta_mem_init(void) +{ + barebox_add_memory_bank("ram0", 0xa0000000, SZ_256M); + + return 0; +} +mem_initcall(malta_mem_init); + static int malta_devices_init(void) { add_cfi_flash_device(0, 0x1e000000, SZ_4M, 0); diff --git a/arch/mips/boot/main_entry.c b/arch/mips/boot/main_entry.c index 8f5f6fc..a38ad31 100644 --- a/arch/mips/boot/main_entry.c +++ b/arch/mips/boot/main_entry.c @@ -25,11 +25,56 @@ #include #include #include +#include +#include extern void start_barebox(void); +extern void handle_reserved(void); void main_entry(void); +unsigned long exception_handlers[32]; + +static void set_except_vector(int n, void *addr) +{ + unsigned handler = (unsigned long) addr; + + exception_handlers[n] = handler; +} + +static void trap_init(void) +{ + extern char except_vec3_generic; + int i; + + unsigned long ebase; + + ebase = CKSEG1; + + /* + * Copy the generic exception handlers to their final destination. + * This will be overriden later as suitable for a particular + * configuration. + */ + memcpy((void *)(ebase + 0x180), &except_vec3_generic, 0x80); + + /* + * Setup default vectors + */ + for (i = 0; i <= 31; i++) { + set_except_vector(i, &handle_reserved); + } + + if (!cpu_has_4kex) + memcpy((void *)(ebase + 0x080), &except_vec3_generic, 0x80); + + /* FIXME: handle tlb */ + memcpy((void *)(ebase), &except_vec3_generic, 0x80); + + /* unset BOOT EXCEPTION VECTOR bit */ + write_c0_status(read_c0_status() & ~ST0_BEV); +} + /** * Called plainly from assembler code * @@ -48,5 +93,7 @@ r4k_cache_init(); } + trap_init(); + start_barebox(); } diff --git a/arch/mips/include/asm/addrspace.h b/arch/mips/include/asm/addrspace.h new file mode 100644 index 0000000..17d480d --- /dev/null +++ b/arch/mips/include/asm/addrspace.h @@ -0,0 +1,109 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996, 99 Ralf Baechle + * Copyright (C) 2000, 2002 Maciej W. Rozycki + * Copyright (C) 1990, 1999 by Silicon Graphics, Inc. + */ +#ifndef _ASM_ADDRSPACE_H +#define _ASM_ADDRSPACE_H + +/* + * Configure language + */ +#ifdef __ASSEMBLY__ +#define _ATYPE_ +#define _ATYPE32_ +#define _ATYPE64_ +#define _CONST64_(x) x +#else +#define _ATYPE_ __PTRDIFF_TYPE__ +#define _ATYPE32_ int +#define _ATYPE64_ __s64 +#ifdef CONFIG_64BIT +#define _CONST64_(x) x ## L +#else +#define _CONST64_(x) x ## LL +#endif +#endif + +/* + * 32-bit MIPS address spaces + */ +#ifdef __ASSEMBLY__ +#define _ACAST32_ +#define _ACAST64_ +#else +#define _ACAST32_ (_ATYPE_)(_ATYPE32_) /* widen if necessary */ +#define _ACAST64_ (_ATYPE64_) /* do _not_ narrow */ +#endif + +/* + * Returns the kernel segment base of a given address + */ +#define KSEGX(a) ((_ACAST32_(a)) & 0xe0000000) + +/* + * Returns the physical address of a CKSEGx / XKPHYS address + */ +#define CPHYSADDR(a) ((_ACAST32_(a)) & 0x1fffffff) +#define XPHYSADDR(a) ((_ACAST64_(a)) & \ + _CONST64_(0x000000ffffffffff)) + +#ifdef CONFIG_64BIT + +/* + * Memory segments (64bit kernel mode addresses) + * The compatibility segments use the full 64-bit sign extended value. Note + * the R8000 doesn't have them so don't reference these in generic MIPS code. + */ +#define XKUSEG _CONST64_(0x0000000000000000) +#define XKSSEG _CONST64_(0x4000000000000000) +#define XKPHYS _CONST64_(0x8000000000000000) +#define XKSEG _CONST64_(0xc000000000000000) +#define CKSEG0 _CONST64_(0xffffffff80000000) +#define CKSEG1 _CONST64_(0xffffffffa0000000) +#define CKSSEG _CONST64_(0xffffffffc0000000) +#define CKSEG3 _CONST64_(0xffffffffe0000000) + +#define CKSEG0ADDR(a) (CPHYSADDR(a) | CKSEG0) +#define CKSEG1ADDR(a) (CPHYSADDR(a) | CKSEG1) +#define CKSEG2ADDR(a) (CPHYSADDR(a) | CKSEG2) +#define CKSEG3ADDR(a) (CPHYSADDR(a) | CKSEG3) + +#else + +#define CKSEG0ADDR(a) (CPHYSADDR(a) | KSEG0) +#define CKSEG1ADDR(a) (CPHYSADDR(a) | KSEG1) +#define CKSEG2ADDR(a) (CPHYSADDR(a) | KSEG2) +#define CKSEG3ADDR(a) (CPHYSADDR(a) | KSEG3) + +/* + * Map an address to a certain kernel segment + */ +#define KSEG0ADDR(a) (CPHYSADDR(a) | KSEG0) +#define KSEG1ADDR(a) (CPHYSADDR(a) | KSEG1) +#define KSEG2ADDR(a) (CPHYSADDR(a) | KSEG2) +#define KSEG3ADDR(a) (CPHYSADDR(a) | KSEG3) + +/* + * Memory segments (32bit kernel mode addresses) + * These are the traditional names used in the 32-bit universe. + */ +#define KUSEG 0x00000000 +#define KSEG0 0x80000000 +#define KSEG1 0xa0000000 +#define KSEG2 0xc0000000 +#define KSEG3 0xe0000000 + +#define CKUSEG 0x00000000 +#define CKSEG0 0x80000000 +#define CKSEG1 0xa0000000 +#define CKSEG2 0xc0000000 +#define CKSEG3 0xe0000000 + +#endif + +#endif /* _ASM_ADDRSPACE_H */ diff --git a/arch/mips/include/asm/asm.h b/arch/mips/include/asm/asm.h index 608cfcf..12e1758 100644 --- a/arch/mips/include/asm/asm.h +++ b/arch/mips/include/asm/asm.h @@ -398,12 +398,4 @@ #define SSNOP sll zero, zero, 1 -#ifdef CONFIG_SGI_IP28 -/* Inhibit speculative stores to volatile (e.g.DMA) or invalid addresses. */ -#include -#define R10KCBARRIER(addr) cache Cache_Barrier, addr; -#else -#define R10KCBARRIER(addr) -#endif - #endif /* __ASM_ASM_H */ diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index befccbb..16ba38e 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -102,11 +102,6 @@ #define CP0_S3_SRSMAP $12 /* MIPSR2 */ /* - * TX39 Series - */ -#define CP0_TX39_CACHE $7 - -/* * Coprocessor 1 (FPU) register names */ #define CP1_REVISION $0 @@ -387,27 +382,6 @@ #define R5K_CONF_SE (_ULCAST_(1) << 12) #define R5K_CONF_SS (_ULCAST_(3) << 20) -/* Bits specific to the RM7000. */ -#define RM7K_CONF_SE (_ULCAST_(1) << 3) -#define RM7K_CONF_TE (_ULCAST_(1) << 12) -#define RM7K_CONF_CLK (_ULCAST_(1) << 16) -#define RM7K_CONF_TC (_ULCAST_(1) << 17) -#define RM7K_CONF_SI (_ULCAST_(3) << 20) -#define RM7K_CONF_SC (_ULCAST_(1) << 31) - -/* Bits specific to the R10000. */ -#define R10K_CONF_DN (_ULCAST_(3) << 3) -#define R10K_CONF_CT (_ULCAST_(1) << 5) -#define R10K_CONF_PE (_ULCAST_(1) << 6) -#define R10K_CONF_PM (_ULCAST_(3) << 7) -#define R10K_CONF_EC (_ULCAST_(15)<< 9) -#define R10K_CONF_SB (_ULCAST_(1) << 13) -#define R10K_CONF_SK (_ULCAST_(1) << 14) -#define R10K_CONF_SS (_ULCAST_(7) << 16) -#define R10K_CONF_SC (_ULCAST_(7) << 19) -#define R10K_CONF_DC (_ULCAST_(7) << 26) -#define R10K_CONF_IC (_ULCAST_(7) << 29) - /* Bits specific to the R30xx. */ #define R30XX_CONF_FDM (_ULCAST_(1) << 19) #define R30XX_CONF_REV (_ULCAST_(1) << 22) @@ -419,12 +393,6 @@ #define R30XX_CONF_SB (_ULCAST_(1) << 30) #define R30XX_CONF_LOCK (_ULCAST_(1) << 31) -/* Bits specific to the TX49. */ -#define TX49_CONF_DC (_ULCAST_(1) << 16) -#define TX49_CONF_IC (_ULCAST_(1) << 17) /* conflict with CONF_SC */ -#define TX49_CONF_HALT (_ULCAST_(1) << 18) -#define TX49_CONF_CWFON (_ULCAST_(1) << 27) - /* Bits specific to the MIPS32/64 PRA. */ #define MIPS_CONF_MT (_ULCAST_(7) << 7) #define MIPS_CONF_AR (_ULCAST_(7) << 10) diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile index b99bb71..a31046b 100644 --- a/arch/mips/lib/Makefile +++ b/arch/mips/lib/Makefile @@ -5,6 +5,8 @@ obj-y += ashrdi3.o obj-y += memory.o obj-y += cpu-probe.o +obj-y += traps.o +obj-y += genex.o obj-$(CONFIG_CPU_MIPS32) += c-r4k.o obj-$(CONFIG_CPU_MIPS64) += c-r4k.o diff --git a/arch/mips/lib/genex.S b/arch/mips/lib/genex.S new file mode 100644 index 0000000..d6f65a2 --- /dev/null +++ b/arch/mips/lib/genex.S @@ -0,0 +1,31 @@ +#include +#include +#include + + .text + .set macro + .set noat + .set noreorder + .align 5 + +/* Exception vector */ +NESTED(handle_reserved, 0, sp) + la k0, barebox_exc_handler + jal k0 + move a0, sp + /* will never return here */ + END(handle_reserved) + +/* General exception vector */ +NESTED(except_vec3_generic, 0, sp) + .set noat + mfc0 k1, CP0_CAUSE + la k0, exception_handlers + andi k1, k1, 0x7c + addu k0, k0, k1 + lw k0, (k0) + nop + jr k0 + nop + END(except_vec3_generic) + .set at diff --git a/arch/mips/lib/traps.c b/arch/mips/lib/traps.c new file mode 100644 index 0000000..4e167cc --- /dev/null +++ b/arch/mips/lib/traps.c @@ -0,0 +1,107 @@ +#include + +#include + +void barebox_exc_handler(void *regs); + +/* + * Trap codes from OpenBSD trap.h + */ +#define T_INT 0 /* Interrupt pending */ +#define T_TLB_MOD 1 /* TLB modified fault */ +#define T_TLB_LD_MISS 2 /* TLB miss on load or ifetch */ +#define T_TLB_ST_MISS 3 /* TLB miss on a store */ +#define T_ADDR_ERR_LD 4 /* Address error on a load or ifetch */ +#define T_ADDR_ERR_ST 5 /* Address error on a store */ +#define T_BUS_ERR_IFETCH 6 /* Bus error on an ifetch */ +#define T_BUS_ERR_LD_ST 7 /* Bus error on a load or store */ +#define T_SYSCALL 8 /* System call */ +#define T_BREAK 9 /* Breakpoint */ +#define T_RES_INST 10 /* Reserved instruction exception */ +#define T_COP_UNUSABLE 11 /* Coprocessor unusable */ +#define T_OVFLOW 12 /* Arithmetic overflow */ +#define T_TRAP 13 /* Trap instruction */ +#define T_VCEI 14 /* Virtual coherency instruction */ +#define T_FPE 15 /* Floating point exception */ +#define T_IWATCH 16 /* Inst. Watch address reference */ +#define T_DWATCH 23 /* Data Watch address reference */ +#define T_VCED 31 /* Virtual coherency data */ + +#define CR_EXC_CODE 0x0000007c +#define CR_EXC_CODE_SHIFT 2 + +static char *get_exc_name(u32 cause) +{ + switch ((cause & CR_EXC_CODE) >> CR_EXC_CODE_SHIFT) { + + case T_INT: + return "interrupt pending"; + + case T_TLB_MOD: + return "TLB modified"; + + case T_TLB_LD_MISS: + return "TLB miss on load or ifetch"; + + case T_TLB_ST_MISS: + return "TLB miss on store"; + + case T_ADDR_ERR_LD: + return "address error on load or ifetch"; + + case T_ADDR_ERR_ST: + return "address error on store"; + + case T_BUS_ERR_IFETCH: + return "bus error on ifetch"; + + case T_BUS_ERR_LD_ST: + return "bus error on load or store"; + + case T_SYSCALL: + return "system call"; + + case T_BREAK: + return "breakpoint"; + + case T_RES_INST: + return "reserved instruction"; + + case T_COP_UNUSABLE: + return "coprocessor unusable"; + + case T_OVFLOW: + return "arithmetic overflow"; + + case T_TRAP: + return "trap instruction"; + + case T_VCEI: + return "virtual coherency instruction"; + + case T_FPE: + return "floating point"; + + case T_IWATCH: + return "iwatch"; + + case T_DWATCH: + return "dwatch"; + + case T_VCED: + return "virtual coherency data"; + } + + return "unknown exception"; +} + +void barebox_exc_handler(void *regs) +{ + printf("\nOoops, %s!\n", get_exc_name(read_c0_cause())); + printf("EPC = 0x%08x\n", read_c0_epc()); + printf("CP0_STATUS = 0x%08x\n", read_c0_status()); + printf("CP0_CAUSE = 0x%08x\n", read_c0_cause()); + printf("CP0_CONFIG = 0x%08x\n\n", read_c0_config()); + + hang(); +}