diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-26 19:53:12 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-26 19:53:12 -0800 |
commit | 9626357371b519f2b955fef399647181034a77fe (patch) | |
tree | 232abd741e773c7d3afb4ba6b02fcba03b82214d | |
parent | 2b37e9a28afbd11f899738e912fb4a617a74b462 (diff) | |
parent | 9cf81c759b7db1db593b2ca60b74ec350d5f9205 (diff) |
Merge tag 'xtensa-next-20130225' of git://github.com/czankel/xtensa-linux
Pull xtensa update from Chris Zankel:
"Added features:
- add support for thread local storage (TLS)
- add accept4 and finit_module syscalls
- support medium-priority interrupts
- add support for dc232c processor variant
- support file-base simulated disk for ISS simulator
Bug fixes:
- fix return values returned by the str[n]cmp functions
- avoid mmap cache aliasing
- fix handling of 'windowed registers' in ptrace"
* tag 'xtensa-next-20130225' of git://github.com/czankel/xtensa-linux:
xtensa: add accept4 syscall
xtensa: add support for TLS
xtensa: add missing include asm/uaccess.h to checksum.h
xtensa: do not enable GENERIC_GPIO by default
xtensa: complete ptrace handling of register windows
xtensa: add support for oprofile
xtensa: move spill_registers to traps.h
xtensa: ISS: add host file-based simulated disk
xtensa: fix str[n]cmp return value
xtensa: avoid mmap cache aliasing
xtensa: add finit_module syscall
xtensa: pull signal definitions from signal-defs.h
xtensa: fix ipc_parse_version selection
xtensa: dispatch medium-priority interrupts
xtensa: Add config files for Diamond 233L - Rev C processor variant
xtensa: use new common dtc rule
xtensa: rename prom_update_property to of_update_property
36 files changed, 1851 insertions, 115 deletions
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index cb557be492b..a5c0663c2cd 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -13,9 +13,11 @@ config XTENSA select GENERIC_CPU_DEVICES select MODULES_USE_ELF_RELA select GENERIC_PCI_IOMAP + select ARCH_WANT_IPC_PARSE_VERSION select ARCH_WANT_OPTIONAL_GPIOLIB select CLONE_BACKWARDS select IRQ_DOMAIN + select HAVE_OPROFILE help Xtensa processors are 32-bit RISC machines designed by Tensilica primarily for embedded systems. These processors are both @@ -31,7 +33,7 @@ config GENERIC_HWEIGHT def_bool y config GENERIC_GPIO - def_bool y + bool config ARCH_HAS_ILOG2_U32 def_bool n @@ -71,6 +73,12 @@ config XTENSA_VARIANT_DC232B help This variant refers to Tensilica's Diamond 232L Standard core Rev.B (LE). +config XTENSA_VARIANT_DC233C + bool "dc233c - Diamond 233L Standard Core Rev.C (LE)" + select MMU + help + This variant refers to Tensilica's Diamond 233L Standard core Rev.C (LE). + config XTENSA_VARIANT_S6000 bool "s6000 - Stretch software configurable processor" select VARIANT_IRQ_SWITCH @@ -197,6 +205,42 @@ config BUILTIN_DTB string "DTB to build into the kernel image" depends on OF +config BLK_DEV_SIMDISK + tristate "Host file-based simulated block device support" + default n + depends on XTENSA_PLATFORM_ISS + help + Create block devices that map to files in the host file system. + Device binding to host file may be changed at runtime via proc + interface provided the device is not in use. + +config BLK_DEV_SIMDISK_COUNT + int "Number of host file-based simulated block devices" + range 1 10 + depends on BLK_DEV_SIMDISK + default 2 + help + This is the default minimal number of created block devices. + Kernel/module parameter 'simdisk_count' may be used to change this + value at runtime. More file names (but no more than 10) may be + specified as parameters, simdisk_count grows accordingly. + +config SIMDISK0_FILENAME + string "Host filename for the first simulated device" + depends on BLK_DEV_SIMDISK = y + default "" + help + Attach a first simdisk to a host file. Conventionally, this file + contains a root file system. + +config SIMDISK1_FILENAME + string "Host filename for the second simulated device" + depends on BLK_DEV_SIMDISK = y && BLK_DEV_SIMDISK_COUNT != 1 + default "" + help + Another simulated disk in a host file for a buildroot-independent + storage. + source "mm/Kconfig" source "drivers/pcmcia/Kconfig" diff --git a/arch/xtensa/Makefile b/arch/xtensa/Makefile index 0aa72702f17..136224b74d4 100644 --- a/arch/xtensa/Makefile +++ b/arch/xtensa/Makefile @@ -15,6 +15,7 @@ variant-$(CONFIG_XTENSA_VARIANT_FSF) := fsf variant-$(CONFIG_XTENSA_VARIANT_DC232B) := dc232b +variant-$(CONFIG_XTENSA_VARIANT_DC233C) := dc233c variant-$(CONFIG_XTENSA_VARIANT_S6000) := s6000 variant-$(CONFIG_XTENSA_VARIANT_LINUX_CUSTOM) := custom @@ -86,9 +87,10 @@ core-y += arch/xtensa/kernel/ arch/xtensa/mm/ core-y += $(buildvar) $(buildplf) libs-y += arch/xtensa/lib/ $(LIBGCC) +drivers-$(CONFIG_OPROFILE) += arch/xtensa/oprofile/ ifneq ($(CONFIG_BUILTIN_DTB),"") -core-$(CONFIG_OF) += arch/xtensa/boot/ +core-$(CONFIG_OF) += arch/xtensa/boot/dts/ endif boot := arch/xtensa/boot @@ -101,7 +103,7 @@ zImage: vmlinux $(Q)$(MAKE) $(build)=$(boot) $@ %.dtb: - $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ + $(Q)$(MAKE) $(build)=$(boot)/dts $(boot)/dts/$@ define archhelp @echo '* zImage - Compressed kernel image (arch/xtensa/boot/images/zImage.*)' diff --git a/arch/xtensa/boot/Makefile b/arch/xtensa/boot/Makefile index 818647e815d..64ffc4b53df 100644 --- a/arch/xtensa/boot/Makefile +++ b/arch/xtensa/boot/Makefile @@ -25,18 +25,6 @@ bootdir-$(CONFIG_XTENSA_PLATFORM_ISS) += boot-elf bootdir-$(CONFIG_XTENSA_PLATFORM_XT2000) += boot-redboot boot-elf boot-uboot bootdir-$(CONFIG_XTENSA_PLATFORM_XTFPGA) += boot-redboot boot-elf boot-uboot - -BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_BUILTIN_DTB)).dtb.o -ifneq ($(CONFIG_BUILTIN_DTB),"") -obj-$(CONFIG_OF) += $(BUILTIN_DTB) -endif - -# Rule to build device tree blobs -$(obj)/%.dtb: $(src)/dts/%.dts FORCE - $(call if_changed_dep,dtc) - -clean-files := *.dtb.S - zImage Image: $(bootdir-y) $(bootdir-y): $(addprefix $(obj)/,$(subdir-y)) \ diff --git a/arch/xtensa/boot/dts/Makefile b/arch/xtensa/boot/dts/Makefile new file mode 100644 index 00000000000..5f711bba830 --- /dev/null +++ b/arch/xtensa/boot/dts/Makefile @@ -0,0 +1,15 @@ +# +# arch/xtensa/boot/dts/Makefile +# +# 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. +# +# + +BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_BUILTIN_DTB)).dtb.o +ifneq ($(CONFIG_BUILTIN_DTB),"") +obj-$(CONFIG_OF) += $(BUILTIN_DTB) +endif + +clean-files := *.dtb.S diff --git a/arch/xtensa/include/asm/atomic.h b/arch/xtensa/include/asm/atomic.h index c3f289174c1..e7fb447bce8 100644 --- a/arch/xtensa/include/asm/atomic.h +++ b/arch/xtensa/include/asm/atomic.h @@ -7,7 +7,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2001 - 2005 Tensilica Inc. + * Copyright (C) 2001 - 2008 Tensilica Inc. */ #ifndef _XTENSA_ATOMIC_H @@ -24,11 +24,11 @@ /* * This Xtensa implementation assumes that the right mechanism - * for exclusion is for locking interrupts to level 1. + * for exclusion is for locking interrupts to level EXCM_LEVEL. * * Locking interrupts looks like this: * - * rsil a15, 1 + * rsil a15, LOCKLEVEL * <code> * wsr a15, PS * rsync diff --git a/arch/xtensa/include/asm/checksum.h b/arch/xtensa/include/asm/checksum.h index aed7ad68ca4..0593de689b5 100644 --- a/arch/xtensa/include/asm/checksum.h +++ b/arch/xtensa/include/asm/checksum.h @@ -12,6 +12,7 @@ #define _XTENSA_CHECKSUM_H #include <linux/in6.h> +#include <asm/uaccess.h> #include <variant/core.h> /* diff --git a/arch/xtensa/include/asm/elf.h b/arch/xtensa/include/asm/elf.h index 264d5fa450d..eacb25a4171 100644 --- a/arch/xtensa/include/asm/elf.h +++ b/arch/xtensa/include/asm/elf.h @@ -84,7 +84,8 @@ typedef struct { elf_greg_t sar; elf_greg_t windowstart; elf_greg_t windowbase; - elf_greg_t reserved[8+48]; + elf_greg_t threadptr; + elf_greg_t reserved[7+48]; elf_greg_t a[64]; } xtensa_gregset_t; diff --git a/arch/xtensa/include/asm/pgtable.h b/arch/xtensa/include/asm/pgtable.h index c90ea5bfa1b..d7546c94da5 100644 --- a/arch/xtensa/include/asm/pgtable.h +++ b/arch/xtensa/include/asm/pgtable.h @@ -410,6 +410,10 @@ typedef pte_t *pte_addr_t; #define __HAVE_ARCH_PTEP_SET_WRPROTECT #define __HAVE_ARCH_PTEP_MKDIRTY #define __HAVE_ARCH_PTE_SAME +/* We provide our own get_unmapped_area to cope with + * SHM area cache aliasing for userland. + */ +#define HAVE_ARCH_UNMAPPED_AREA #include <asm-generic/pgtable.h> diff --git a/arch/xtensa/include/asm/processor.h b/arch/xtensa/include/asm/processor.h index e5fb6b0abdf..7e409a5b0ec 100644 --- a/arch/xtensa/include/asm/processor.h +++ b/arch/xtensa/include/asm/processor.h @@ -5,7 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2001 - 2005 Tensilica Inc. + * Copyright (C) 2001 - 2008 Tensilica Inc. */ #ifndef _XTENSA_PROCESSOR_H @@ -68,7 +68,7 @@ /* LOCKLEVEL defines the interrupt level that masks all * general-purpose interrupts. */ -#define LOCKLEVEL 1 +#define LOCKLEVEL XCHAL_EXCM_LEVEL /* WSBITS and WBBITS are the width of the WINDOWSTART and WINDOWBASE * registers diff --git a/arch/xtensa/include/asm/ptrace.h b/arch/xtensa/include/asm/ptrace.h index 682b1deac1f..81f31bc9dde 100644 --- a/arch/xtensa/include/asm/ptrace.h +++ b/arch/xtensa/include/asm/ptrace.h @@ -38,6 +38,7 @@ struct pt_regs { unsigned long syscall; /* 56 */ unsigned long icountlevel; /* 60 */ unsigned long scompare1; /* 64 */ + unsigned long threadptr; /* 68 */ /* Additional configurable registers that are used by the compiler. */ xtregs_opt_t xtregs_opt; @@ -48,7 +49,7 @@ struct pt_regs { /* current register frame. * Note: The ESF for kernel exceptions ends after 16 registers! */ - unsigned long areg[16]; /* 128 (64) */ + unsigned long areg[16]; }; #include <variant/core.h> diff --git a/arch/xtensa/include/asm/regs.h b/arch/xtensa/include/asm/regs.h index 76096a4e5b8..b24de671702 100644 --- a/arch/xtensa/include/asm/regs.h +++ b/arch/xtensa/include/asm/regs.h @@ -88,6 +88,7 @@ #define PS_UM_BIT 5 #define PS_EXCM_BIT 4 #define PS_INTLEVEL_SHIFT 0 +#define PS_INTLEVEL_WIDTH 4 #define PS_INTLEVEL_MASK 0x0000000F /* DBREAKCn register fields. */ diff --git a/arch/xtensa/include/asm/string.h b/arch/xtensa/include/asm/string.h index 405a8c49ff2..8d5d9dfadb0 100644 --- a/arch/xtensa/include/asm/string.h +++ b/arch/xtensa/include/asm/string.h @@ -74,7 +74,7 @@ static inline int strcmp(const char *__cs, const char *__ct) "beqz %2, 2f\n\t" "beq %2, %3, 1b\n" "2:\n\t" - "sub %2, %3, %2" + "sub %2, %2, %3" : "=r" (__cs), "=r" (__ct), "=&r" (__res), "=&r" (__dummy) : "0" (__cs), "1" (__ct)); @@ -99,7 +99,7 @@ static inline int strncmp(const char *__cs, const char *__ct, size_t __n) "beqz %3, 2f\n\t" "beq %2, %3, 1b\n" "2:\n\t" - "sub %2, %3, %2" + "sub %2, %2, %3" : "=r" (__cs), "=r" (__ct), "=&r" (__res), "=&r" (__dummy) : "0" (__cs), "1" (__ct), "r" (__cs+__n)); diff --git a/arch/xtensa/include/asm/timex.h b/arch/xtensa/include/asm/timex.h index 175b3d5e1b0..9e85ce8bd8d 100644 --- a/arch/xtensa/include/asm/timex.h +++ b/arch/xtensa/include/asm/timex.h @@ -5,7 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2001 - 2005 Tensilica Inc. + * Copyright (C) 2001 - 2008 Tensilica Inc. */ #ifndef _XTENSA_TIMEX_H @@ -19,13 +19,13 @@ #define _INTLEVEL(x) XCHAL_INT ## x ## _LEVEL #define INTLEVEL(x) _INTLEVEL(x) -#if INTLEVEL(XCHAL_TIMER0_INTERRUPT) == 1 +#if INTLEVEL(XCHAL_TIMER0_INTERRUPT) <= XCHAL_EXCM_LEVEL # define LINUX_TIMER 0 # define LINUX_TIMER_INT XCHAL_TIMER0_INTERRUPT -#elif INTLEVEL(XCHAL_TIMER1_INTERRUPT) == 1 +#elif INTLEVEL(XCHAL_TIMER1_INTERRUPT) <= XCHAL_EXCM_LEVEL # define LINUX_TIMER 1 # define LINUX_TIMER_INT XCHAL_TIMER1_INTERRUPT -#elif INTLEVEL(XCHAL_TIMER2_INTERRUPT) == 1 +#elif INTLEVEL(XCHAL_TIMER2_INTERRUPT) <= XCHAL_EXCM_LEVEL # define LINUX_TIMER 2 # define LINUX_TIMER_INT XCHAL_TIMER2_INTERRUPT #else diff --git a/arch/xtensa/include/asm/traps.h b/arch/xtensa/include/asm/traps.h index 54f70440185..b5464ef3cf6 100644 --- a/arch/xtensa/include/asm/traps.h +++ b/arch/xtensa/include/asm/traps.h @@ -20,4 +20,28 @@ extern void * __init trap_set_handler(int cause, void *handler); extern void do_unhandled(struct pt_regs *regs, unsigned long exccause); +static inline void spill_registers(void) +{ + unsigned int a0, ps; + + __asm__ __volatile__ ( + "movi a14, " __stringify(PS_EXCM_BIT | LOCKLEVEL) "\n\t" + "mov a12, a0\n\t" + "rsr a13, sar\n\t" + "xsr a14, ps\n\t" + "movi a0, _spill_registers\n\t" + "rsync\n\t" + "callx0 a0\n\t" + "mov a0, a12\n\t" + "wsr a13, sar\n\t" + "wsr a14, ps\n\t" + : : "a" (&a0), "a" (&ps) +#if defined(CONFIG_FRAME_POINTER) + : "a2", "a3", "a4", "a11", "a12", "a13", "a14", "a15", +#else + : "a2", "a3", "a4", "a7", "a11", "a12", "a13", "a14", "a15", +#endif + "memory"); +} + #endif /* _XTENSA_TRAPS_H */ diff --git a/arch/xtensa/include/uapi/asm/signal.h b/arch/xtensa/include/uapi/asm/signal.h index dacf716dd3e..586756ee267 100644 --- a/arch/xtensa/include/uapi/asm/signal.h +++ b/arch/xtensa/include/uapi/asm/signal.h @@ -102,16 +102,7 @@ typedef struct { #ifndef __ASSEMBLY__ -#define SIG_BLOCK 0 /* for blocking signals */ -#define SIG_UNBLOCK 1 /* for unblocking signals */ -#define SIG_SETMASK 2 /* for setting the signal mask */ - -/* Type of a signal handler. */ -typedef void (*__sighandler_t)(int); - -#define SIG_DFL ((__sighandler_t)0) /* default signal handling */ -#define SIG_IGN ((__sighandler_t)1) /* ignore signal */ -#define SIG_ERR ((__sighandler_t)-1) /* error return from signal */ +#include <asm-generic/signal-defs.h> #ifndef __KERNEL__ diff --git a/arch/xtensa/include/uapi/asm/unistd.h b/arch/xtensa/include/uapi/asm/unistd.h index 19fac3f543a..51940fec699 100644 --- a/arch/xtensa/include/uapi/asm/unistd.h +++ b/arch/xtensa/include/uapi/asm/unistd.h @@ -728,8 +728,13 @@ __SYSCALL(330, sys_prlimit64, 4) #define __NR_kcmp 331 __SYSCALL(331, sys_kcmp, 5) +#define __NR_finit_module 332 +__SYSCALL(332, sys_finit_module, 3) -#define __NR_syscall_count 332 +#define __NR_accept4 333 +__SYSCALL(333, sys_accept4, 4) + +#define __NR_syscall_count 334 /* * sysxtensa syscall handler diff --git a/arch/xtensa/kernel/asm-offsets.c b/arch/xtensa/kernel/asm-offsets.c index 0701fad170d..1915c7c889b 100644 --- a/arch/xtensa/kernel/asm-offsets.c +++ b/arch/xtensa/kernel/asm-offsets.c @@ -42,6 +42,7 @@ int main(void) DEFINE(PT_ICOUNTLEVEL, offsetof (struct pt_regs, icountlevel)); DEFINE(PT_SYSCALL, offsetof (struct pt_regs, syscall)); DEFINE(PT_SCOMPARE1, offsetof(struct pt_regs, scompare1)); + DEFINE(PT_THREADPTR, offsetof(struct pt_regs, threadptr)); DEFINE(PT_AREG, offsetof (struct pt_regs, areg[0])); DEFINE(PT_AREG0, offsetof (struct pt_regs, areg[0])); DEFINE(PT_AREG1, offsetof (struct pt_regs, areg[1])); diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index 3777fec85e7..63845f95079 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S @@ -7,7 +7,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2004-2007 by Tensilica Inc. + * Copyright (C) 2004 - 2008 by Tensilica Inc. * * Chris Zankel <chris@zankel.net> * @@ -130,6 +130,11 @@ _user_exception: s32i a3, a1, PT_SAR s32i a2, a1, PT_ICOUNTLEVEL +#if XCHAL_HAVE_THREADPTR + rur a2, threadptr + s32i a2, a1, PT_THREADPTR +#endif + /* Rotate ws so that the current windowbase is at bit0. */ /* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */ @@ -349,15 +354,16 @@ common_exception: * so we can allow exceptions and interrupts (*) again. * Set PS(EXCM = 0, UM = 0, RING = 0, OWB = 0, WOE = 1, INTLEVEL = X) * - * (*) We only allow interrupts if PS.INTLEVEL was not set to 1 before - * (interrupts disabled) and if this exception is not an interrupt. + * (*) We only allow interrupts of higher priority than current IRQ */ rsr a3, ps addi a0, a0, -4 movi a2, 1 - extui a3, a3, 0, 1 # a3 = PS.INTLEVEL[0] - moveqz a3, a2, a0 # a3 = 1 iff interrupt exception + extui a3, a3, PS_INTLEVEL_SHIFT, PS_INTLEVEL_WIDTH + # a3 = PS.INTLEVEL + movnez a2, a3, a3 # a2 = 1: level-1, > 1: high priority + moveqz a3, a2, a0 # a3 = IRQ level iff interrupt movi a2, 1 << PS_WOE_BIT or a3, a3, a2 rsr a0, exccause @@ -398,7 +404,7 @@ common_exception: callx4 a4 /* Jump here for exception exit */ - + .global common_exception_return common_exception_return: /* Jump if we are returning from kernel exceptions. */ @@ -509,6 +515,11 @@ user_exception_exit: * (if we have restored WSBITS-1 frames). */ +#if XCHAL_HAVE_THREADPTR + l32i a3, a1, PT_THREADPTR + wur a3, threadptr +#endif + 2: j common_exception_exit /* This is the kernel exception exit. @@ -641,19 +652,51 @@ common_exception_exit: l32i a0, a1, PT_DEPC l32i a3, a1, PT_AREG3 + _bltui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f + + wsr a0, depc l32i a2, a1, PT_AREG2 - _bgeui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f + l32i a0, a1, PT_AREG0 + l32i a1, a1, PT_AREG1 + rfde +1: /* Restore a0...a3 and return */ + rsr a0, ps + extui a2, a0, PS_INTLEVEL_SHIFT, PS_INTLEVEL_WIDTH + movi a0, 2f + slli a2, a2, 4 + add a0, a2, a0 + l32i a2, a1, PT_AREG2 + jx a0 + + .macro irq_exit_level level + .align 16 + .if XCHAL_EXCM_LEVEL >= \level + l32i a0, a1, PT_PC + wsr a0, epc\level l32i a0, a1, PT_AREG0 l32i a1, a1, PT_AREG1 - rfe + rfi \level + .endif + .endm -1: wsr a0, depc + .align 16 +2: l32i a0, a1, PT_AREG0 l32i a1, a1, PT_AREG1 - rfde + rfe + + .align 16 + /* no rfi for level-1 irq, handled by rfe above*/ + nop + + irq_exit_level 2 + irq_exit_level 3 + irq_exit_level 4 + irq_exit_level 5 + irq_exit_level 6 ENDPROC(kernel_exception) @@ -753,7 +796,7 @@ ENTRY(unrecoverable_exception) wsr a1, windowbase rsync - movi a1, (1 << PS_WOE_BIT) | 1 + movi a1, (1 << PS_WOE_BIT) | LOCKLEVEL wsr a1, ps rsync @@ -1474,7 +1517,7 @@ ENTRY(_spill_registers) l32i a1, a3, EXC_TABLE_KSTK wsr a3, excsave1 - movi a4, (1 << PS_WOE_BIT) | 1 + movi a4, (1 << PS_WOE_BIT) | LOCKLEVEL wsr a4, ps rsync @@ -1922,7 +1965,7 @@ ENTRY(_switch_to) s32i a6, a3, EXC_TABLE_FIXUP s32i a7, a3, EXC_TABLE_KSTK - /* restore context of the task that 'next' addresses */ + /* restore context of the task 'next' */ l32i a0, a13, THREAD_RA # restore return address l32i a1, a13, THREAD_SP # restore stack pointer diff --git a/arch/xtensa/kernel/head.S b/arch/xtensa/kernel/head.S index 91d9095284d..df88f98737f 100644 --- a/arch/xtensa/kernel/head.S +++ b/arch/xtensa/kernel/head.S @@ -7,7 +7,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2001 - 2005 Tensilica Inc. + * Copyright (C) 2001 - 2008 Tensilica Inc. * * Chris Zankel <chris@zankel.net> * Marc Gauthier <marc@tensilica.com, marc@alumni.uwaterloo.ca> @@ -128,14 +128,14 @@ ENTRY(_startup) wsr a0, cpenable #endif - /* Set PS.INTLEVEL=1, PS.WOE=0, kernel stack, PS.EXCM=0 + /* Set PS.INTLEVEL=LOCKLEVEL, PS.WOE=0, kernel stack, PS.EXCM=0 * * Note: PS.EXCM must be cleared before using any loop * instructions; otherwise, they are silently disabled, and * at most one iteration of the loop is executed. */ - movi a1, 1 + movi a1, LOCKLEVEL wsr a1, ps rsync @@ -211,7 +211,8 @@ ENTRY(_startup) movi a1, init_thread_union addi a1, a1, KERNEL_STACK_SIZE - movi a2, 0x00040001 # WOE=1, INTLEVEL=1, UM=0 + movi a2, (1 << PS_WOE_BIT) | LOCKLEVEL + # WOE=1, INTLEVEL=LOCKLEVEL, UM=0 wsr a2, ps # (enable reg-windows; progmode stack) rsync diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c index 0dd5784416d..5cd82e9f601 100644 --- a/arch/xtensa/kernel/process.c +++ b/arch/xtensa/kernel/process.c @@ -259,9 +259,10 @@ int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn, memcpy(&childregs->areg[XCHAL_NUM_AREGS - len/4], ®s->areg[XCHAL_NUM_AREGS - len/4], len); } -// FIXME: we need to set THREADPTR in thread_info... + + /* The thread pointer is passed in the '4th argument' (= a5) */ if (clone_flags & CLONE_SETTLS) - childregs->areg[2] = childregs->areg[6]; + childregs->threadptr = childregs->areg[5]; } else { p->thread.ra = MAKE_RA_FOR_CALL( (unsigned long)ret_from_kernel_thread, 1); diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c index 61fb2e9e903..562fac66475 100644 --- a/arch/xtensa/kernel/ptrace.c +++ b/arch/xtensa/kernel/ptrace.c @@ -53,9 +53,8 @@ int ptrace_getregs(struct task_struct *child, void __user *uregs) { struct pt_regs *regs = task_pt_regs(child); xtensa_gregset_t __user *gregset = uregs; - unsigned long wm = regs->wmask; unsigned long wb = regs->windowbase; - int live, i; + int i; if (!access_ok(VERIFY_WRITE, uregs, sizeof(xtensa_gregset_t))) return -EIO; @@ -67,13 +66,11 @@ int ptrace_getregs(struct task_struct *child, void __user *uregs) __put_user(regs->lcount, &gregset->lcount); __put_user(regs->windowstart, &gregset->windowstart); __put_user(regs->windowbase, &gregset->windowbase); + __put_user(regs->threadptr, &gregset->threadptr); - live = (wm & 2) ? 4 : (wm & 4) ? 8 : (wm & 8) ? 12 : 16; - - for (i = 0; i < live; i++) - __put_user(regs->areg[i],gregset->a+((wb*4+i)%XCHAL_NUM_AREGS)); - for (i = XCHAL_NUM_AREGS - (wm >> 4) * 4; i < XCHAL_NUM_AREGS; i++) - __put_user(regs->areg[i],gregset->a+((wb*4+i)%XCHAL_NUM_AREGS)); + for (i = 0; i < XCHAL_NUM_AREGS; i++) + __put_user(regs->areg[i], + gregset->a + ((wb * 4 + i) % XCHAL_NUM_AREGS)); return 0; } @@ -84,7 +81,7 @@ int ptrace_setregs(struct task_struct *child, void __user *uregs) xtensa_gregset_t *gregset = uregs; const unsigned long ps_mask = PS_CALLINC_MASK | PS_OWB_MASK; unsigned long ps; - unsigned long wb; + unsigned long wb, ws; if (!access_ok(VERIFY_WRITE, uregs, sizeof(xtensa_gregset_t))) return -EIO; @@ -94,21 +91,33 @@ int ptrace_setregs(struct task_struct *child, void __user *uregs) __get_user(regs->lbeg, &gregset->lbeg); __get_user(regs->lend, &gregset->lend); __get_user(regs->lcount, &gregset->lcount); - __get_user(regs->windowstart, &gregset->windowstart); + __get_user(ws, &gregset->windowstart); __get_user(wb, &gregset->windowbase); + __get_user(regs->threadptr, &gregset->threadptr); regs->ps = (regs->ps & ~ps_mask) | (ps & ps_mask) | (1 << PS_EXCM_BIT); if (wb >= XCHAL_NUM_AREGS / 4) return -EFAULT; - regs->windowbase = wb; + if (wb != regs->windowbase || ws != regs->windowstart) { + unsigned long rotws, wmask; + + rotws = (((ws | (ws << WSBITS)) >> wb) & + ((1 << WSBITS) - 1)) & ~1; + wmask = ((rotws ? WSBITS + 1 - ffs(rotws) : 0) << 4) | + (rotws & 0xF) | 1; + regs->windowbase = wb; + regs->windowstart = ws; + regs->wmask = wmask; + } if (wb != 0 && __copy_from_user(regs->areg + XCHAL_NUM_AREGS - wb * 4, - gregset->a, wb * 16)) + gregset->a, wb * 16)) return -EFAULT; - if (__copy_from_user(regs->areg, gregset->a + wb*4, (WSBITS-wb) * 16)) + if (__copy_from_user(regs->areg, gregset->a + wb * 4, + (WSBITS - wb) * 16)) return -EFAULT; return 0; diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c index 24c1a57abb4..6dd25ecde3f 100644 --- a/arch/xtensa/kernel/setup.c +++ b/arch/xtensa/kernel/setup.c @@ -328,6 +328,27 @@ extern char _UserExceptionVector_literal_start; extern char _UserExceptionVector_text_end; extern char _DoubleExceptionVector_literal_start; extern char _DoubleExceptionVector_text_end; +#if XCHAL_EXCM_LEVEL >= 2 +extern char _Level2InterruptVector_text_start; +extern char _Level2InterruptVector_text_end; +#endif +#if XCHAL_EXCM_LEVEL >= 3 +extern char _Level3InterruptVector_text_start; +extern char _Level3InterruptVector_text_end; +#endif +#if XCHAL_EXCM_LEVEL >= 4 +extern char _Level4InterruptVector_text_start; |