summaryrefslogtreecommitdiffstats
path: root/arch/xtensa/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/xtensa/kernel')
-rw-r--r--arch/xtensa/kernel/Makefile3
-rw-r--r--arch/xtensa/kernel/coprocessor.S22
-rw-r--r--arch/xtensa/kernel/entry.S82
-rw-r--r--arch/xtensa/kernel/head.S15
-rw-r--r--arch/xtensa/kernel/pci-dma.c129
-rw-r--r--arch/xtensa/kernel/platform.c5
-rw-r--r--arch/xtensa/kernel/process.c10
-rw-r--r--arch/xtensa/kernel/ptrace.c18
-rw-r--r--arch/xtensa/kernel/setup.c26
-rw-r--r--arch/xtensa/kernel/signal.c30
-rw-r--r--arch/xtensa/kernel/stacktrace.c5
-rw-r--r--arch/xtensa/kernel/syscalls/syscall.tbl2
-rw-r--r--arch/xtensa/kernel/traps.c38
-rw-r--r--arch/xtensa/kernel/vectors.S3
-rw-r--r--arch/xtensa/kernel/vmlinux.lds.S158
-rw-r--r--arch/xtensa/kernel/xtensa_ksyms.c7
16 files changed, 288 insertions, 265 deletions
diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile
index 6f629027ac7d..d4082c6a121b 100644
--- a/arch/xtensa/kernel/Makefile
+++ b/arch/xtensa/kernel/Makefile
@@ -5,10 +5,11 @@
extra-y := head.o vmlinux.lds
-obj-y := align.o coprocessor.o entry.o irq.o pci-dma.o platform.o process.o \
+obj-y := align.o coprocessor.o entry.o irq.o platform.o process.o \
ptrace.o setup.o signal.o stacktrace.o syscall.o time.o traps.o \
vectors.o
+obj-$(CONFIG_MMU) += pci-dma.o
obj-$(CONFIG_PCI) += pci.o
obj-$(CONFIG_MODULES) += xtensa_ksyms.o module.o
obj-$(CONFIG_FUNCTION_TRACER) += mcount.o
diff --git a/arch/xtensa/kernel/coprocessor.S b/arch/xtensa/kernel/coprocessor.S
index 80828b95a51f..c426b846beef 100644
--- a/arch/xtensa/kernel/coprocessor.S
+++ b/arch/xtensa/kernel/coprocessor.S
@@ -15,17 +15,9 @@
#include <linux/linkage.h>
#include <asm/asm-offsets.h>
#include <asm/asmmacro.h>
-#include <asm/processor.h>
#include <asm/coprocessor.h>
-#include <asm/thread_info.h>
-#include <asm/asm-uaccess.h>
-#include <asm/unistd.h>
-#include <asm/ptrace.h>
#include <asm/current.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/signal.h>
-#include <asm/tlbflush.h>
+#include <asm/regs.h>
#if XTENSA_HAVE_COPROCESSORS
@@ -66,6 +58,8 @@
.endif; \
.long THREAD_XTREGS_CP##x
+ __XTENSA_HANDLER
+
SAVE_CP_REGS(0)
SAVE_CP_REGS(1)
SAVE_CP_REGS(2)
@@ -84,7 +78,6 @@
LOAD_CP_REGS(6)
LOAD_CP_REGS(7)
- .section ".rodata", "a"
.align 4
.Lsave_cp_regs_jump_table:
SAVE_CP_REGS_TAB(0)
@@ -106,8 +99,6 @@
LOAD_CP_REGS_TAB(6)
LOAD_CP_REGS_TAB(7)
- .previous
-
/*
* coprocessor_flush(struct thread_info*, index)
* a2 a3
@@ -153,13 +144,6 @@ ENDPROC(coprocessor_flush)
* < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
*/
-ENTRY(fast_coprocessor_double)
-
- wsr a0, excsave1
- call0 unrecoverable_exception
-
-ENDPROC(fast_coprocessor_double)
-
ENTRY(fast_coprocessor)
/* Save remaining registers a1-a3 and SAR */
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index 183fa8e0bb5b..06fbb0a171f1 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -414,7 +414,7 @@ common_exception:
movi a3, LOCKLEVEL
.Lexception:
- movi a0, 1 << PS_WOE_BIT
+ movi a0, PS_WOE_MASK
or a3, a3, a0
#else
addi a2, a2, -EXCCAUSE_LEVEL1_INTERRUPT
@@ -422,7 +422,7 @@ common_exception:
extui a3, a3, PS_INTLEVEL_SHIFT, PS_INTLEVEL_WIDTH
# a3 = PS.INTLEVEL
moveqz a3, a0, a2 # a3 = LOCKLEVEL iff interrupt
- movi a2, 1 << PS_WOE_BIT
+ movi a2, PS_WOE_MASK
or a3, a3, a2
rsr a2, exccause
#endif
@@ -520,7 +520,7 @@ common_exception_return:
call4 schedule # void schedule (void)
j 1b
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
6:
_bbci.l a4, TIF_NEED_RESCHED, 4f
@@ -529,7 +529,7 @@ common_exception_return:
l32i a4, a2, TI_PRE_COUNT
bnez a4, 4f
call4 preempt_schedule_irq
- j 1b
+ j 4f
#endif
#if XTENSA_FAKE_NMI
@@ -922,7 +922,7 @@ ENTRY(unrecoverable_exception)
wsr a1, windowbase
rsync
- movi a1, (1 << PS_WOE_BIT) | LOCKLEVEL
+ movi a1, PS_WOE_MASK | LOCKLEVEL
wsr a1, ps
rsync
@@ -939,6 +939,9 @@ ENDPROC(unrecoverable_exception)
/* -------------------------- FAST EXCEPTION HANDLERS ----------------------- */
+ __XTENSA_HANDLER
+ .literal_position
+
/*
* Fast-handler for alloca exceptions
*
@@ -1003,7 +1006,43 @@ ENTRY(fast_alloca)
4: j _WindowUnderflow4
ENDPROC(fast_alloca)
+#ifdef CONFIG_USER_ABI_CALL0_PROBE
/*
+ * fast illegal instruction handler.
+ *
+ * This is used to fix up user PS.WOE on the exception caused
+ * by the first opcode related to register window. If PS.WOE is
+ * already set it goes directly to the common user exception handler.
+ *
+ * Entry condition:
+ *
+ * a0: trashed, original value saved on stack (PT_AREG0)
+ * a1: a1
+ * a2: new stack pointer, original in DEPC
+ * a3: a3
+ * depc: a2, original value saved on stack (PT_DEPC)
+ * excsave_1: dispatch table
+ */
+
+ENTRY(fast_illegal_instruction_user)
+
+ rsr a0, ps
+ bbsi.l a0, PS_WOE_BIT, 1f
+ s32i a3, a2, PT_AREG3
+ movi a3, PS_WOE_MASK
+ or a0, a0, a3
+ wsr a0, ps
+ l32i a3, a2, PT_AREG3
+ l32i a0, a2, PT_AREG0
+ rsr a2, depc
+ rfe
+1:
+ call0 user_exception
+
+ENDPROC(fast_illegal_instruction_user)
+#endif
+
+ /*
* fast system calls.
*
* WARNING: The kernel doesn't save the entire user context before
@@ -1037,7 +1076,7 @@ ENTRY(fast_syscall_user)
_beqz a0, fast_syscall_spill_registers
_beqi a0, __NR_xtensa, fast_syscall_xtensa
- j user_exception
+ call0 user_exception
ENDPROC(fast_syscall_user)
@@ -1359,7 +1398,7 @@ ENTRY(fast_syscall_spill_registers)
rsr a3, excsave1
l32i a1, a3, EXC_TABLE_KSTK
- movi a4, (1 << PS_WOE_BIT) | LOCKLEVEL
+ movi a4, PS_WOE_MASK | LOCKLEVEL
wsr a4, ps
rsync
@@ -1728,8 +1767,8 @@ ENTRY(fast_second_level_miss)
rsr a2, ps
bbsi.l a2, PS_UM_BIT, 1f
- j _kernel_exception
-1: j _user_exception
+ call0 _kernel_exception
+1: call0 _user_exception
ENDPROC(fast_second_level_miss)
@@ -1825,13 +1864,14 @@ ENTRY(fast_store_prohibited)
rsr a2, ps
bbsi.l a2, PS_UM_BIT, 1f
- j _kernel_exception
-1: j _user_exception
+ call0 _kernel_exception
+1: call0 _user_exception
ENDPROC(fast_store_prohibited)
#endif /* CONFIG_MMU */
+ .text
/*
* System Calls.
*
@@ -1842,8 +1882,7 @@ ENDPROC(fast_store_prohibited)
ENTRY(system_call)
- /* reserve 4 bytes on stack for function parameter */
- abi_entry(4)
+ abi_entry_default
/* regs->syscall = regs->areg[2] */
@@ -1858,11 +1897,10 @@ ENTRY(system_call)
mov a6, a2
call4 do_syscall_trace_enter
+ beqz a6, .Lsyscall_exit
l32i a7, a2, PT_SYSCALL
1:
- s32i a7, a1, 4
-
/* syscall = sys_call_table[syscall_nr] */
movi a4, sys_call_table
@@ -1872,8 +1910,6 @@ ENTRY(system_call)
addx4 a4, a7, a4
l32i a4, a4, 0
- movi a5, sys_ni_syscall;
- beq a4, a5, 1f
/* Load args: arg0 - arg5 are passed via regs. */
@@ -1884,25 +1920,19 @@ ENTRY(system_call)
l32i a10, a2, PT_AREG8
l32i a11, a2, PT_AREG9
- /* Pass one additional argument to the syscall: pt_regs (on stack) */
- s32i a2, a1, 0
-
callx4 a4
1: /* regs->areg[2] = return_value */
s32i a6, a2, PT_AREG2
bnez a3, 1f
- abi_ret(4)
+.Lsyscall_exit:
+ abi_ret_default
1:
- l32i a4, a1, 4
- l32i a3, a2, PT_SYSCALL
- s32i a4, a2, PT_SYSCALL
mov a6, a2
call4 do_syscall_trace_leave
- s32i a3, a2, PT_SYSCALL
- abi_ret(4)
+ abi_ret_default
ENDPROC(system_call)
diff --git a/arch/xtensa/kernel/head.S b/arch/xtensa/kernel/head.S
index 7f009719304e..e0c1fac0910f 100644
--- a/arch/xtensa/kernel/head.S
+++ b/arch/xtensa/kernel/head.S
@@ -193,7 +193,7 @@ ENTRY(_startup)
movi a1, start_info
l32i a1, a1, 0
- movi a2, (1 << PS_WOE_BIT) | LOCKLEVEL
+ movi a2, PS_WOE_MASK | LOCKLEVEL
# WOE=1, INTLEVEL=LOCKLEVEL, UM=0
wsr a2, ps # (enable reg-windows; progmode stack)
rsync
@@ -260,6 +260,13 @@ ENTRY(_startup)
___invalidate_icache_all a2 a3
isync
+#ifdef CONFIG_XIP_KERNEL
+ /* Setup bootstrap CPU stack in XIP kernel */
+
+ movi a1, start_info
+ l32i a1, a1, 0
+#endif
+
movi a6, 0
xsr a6, excsave1
@@ -355,10 +362,10 @@ ENDPROC(cpu_restart)
* DATA section
*/
- .section ".data.init.refok"
- .align 4
+ __REFDATA
+ .align 4
ENTRY(start_info)
- .long init_thread_union + KERNEL_STACK_SIZE
+ .long init_thread_union + KERNEL_STACK_SIZE
/*
* BSS section
diff --git a/arch/xtensa/kernel/pci-dma.c b/arch/xtensa/kernel/pci-dma.c
index 65f05776d827..72b6222daa0b 100644
--- a/arch/xtensa/kernel/pci-dma.c
+++ b/arch/xtensa/kernel/pci-dma.c
@@ -44,8 +44,8 @@ static void do_cache_op(phys_addr_t paddr, size_t size,
}
}
-void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
- size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size,
+ enum dma_data_direction dir)
{
switch (dir) {
case DMA_BIDIRECTIONAL:
@@ -62,8 +62,8 @@ void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
}
}
-void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
- size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_device(phys_addr_t paddr, size_t size,
+ enum dma_data_direction dir)
{
switch (dir) {
case DMA_BIDIRECTIONAL:
@@ -81,122 +81,25 @@ void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
}
}
-#ifdef CONFIG_MMU
-bool platform_vaddr_cached(const void *p)
-{
- unsigned long addr = (unsigned long)p;
-
- return addr >= XCHAL_KSEG_CACHED_VADDR &&
- addr - XCHAL_KSEG_CACHED_VADDR < XCHAL_KSEG_SIZE;
-}
-
-bool platform_vaddr_uncached(const void *p)
-{
- unsigned long addr = (unsigned long)p;
-
- return addr >= XCHAL_KSEG_BYPASS_VADDR &&
- addr - XCHAL_KSEG_BYPASS_VADDR < XCHAL_KSEG_SIZE;
-}
-
-void *platform_vaddr_to_uncached(void *p)
-{
- return p + XCHAL_KSEG_BYPASS_VADDR - XCHAL_KSEG_CACHED_VADDR;
-}
-
-void *platform_vaddr_to_cached(void *p)
-{
- return p + XCHAL_KSEG_CACHED_VADDR - XCHAL_KSEG_BYPASS_VADDR;
-}
-#else
-bool __attribute__((weak)) platform_vaddr_cached(const void *p)
-{
- WARN_ONCE(1, "Default %s implementation is used\n", __func__);
- return true;
-}
-
-bool __attribute__((weak)) platform_vaddr_uncached(const void *p)
-{
- WARN_ONCE(1, "Default %s implementation is used\n", __func__);
- return false;
-}
-
-void __attribute__((weak)) *platform_vaddr_to_uncached(void *p)
+void arch_dma_prep_coherent(struct page *page, size_t size)
{
- WARN_ONCE(1, "Default %s implementation is used\n", __func__);
- return p;
-}
-
-void __attribute__((weak)) *platform_vaddr_to_cached(void *p)
-{
- WARN_ONCE(1, "Default %s implementation is used\n", __func__);
- return p;
+ __invalidate_dcache_range((unsigned long)page_address(page), size);
}
-#endif
/*
- * Note: We assume that the full memory space is always mapped to 'kseg'
- * Otherwise we have to use page attributes (not implemented).
+ * Memory caching is platform-dependent in noMMU xtensa configurations.
+ * The following two functions should be implemented in platform code
+ * in order to enable coherent DMA memory operations when CONFIG_MMU is not
+ * enabled.
*/
-
-void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
- gfp_t flag, unsigned long attrs)
-{
- unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
- struct page *page = NULL;
-
- /* ignore region speicifiers */
-
- flag &= ~(__GFP_DMA | __GFP_HIGHMEM);
-
- if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
- flag |= GFP_DMA;
-
- if (gfpflags_allow_blocking(flag))
- page = dma_alloc_from_contiguous(dev, count, get_order(size),
- flag & __GFP_NOWARN);
-
- if (!page)
- page = alloc_pages(flag | __GFP_ZERO, get_order(size));
-
- if (!page)
- return NULL;
-
- *handle = phys_to_dma(dev, page_to_phys(page));
-
#ifdef CONFIG_MMU
- if (PageHighMem(page)) {
- void *p;
-
- p = dma_common_contiguous_remap(page, size, VM_MAP,
- pgprot_noncached(PAGE_KERNEL),
- __builtin_return_address(0));
- if (!p) {
- if (!dma_release_from_contiguous(dev, page, count))
- __free_pages(page, get_order(size));
- }
- return p;
- }
-#endif
- BUG_ON(!platform_vaddr_cached(page_address(page)));
- __invalidate_dcache_range((unsigned long)page_address(page), size);
- return platform_vaddr_to_uncached(page_address(page));
+void *uncached_kernel_address(void *p)
+{
+ return p + XCHAL_KSEG_BYPASS_VADDR - XCHAL_KSEG_CACHED_VADDR;
}
-void arch_dma_free(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle, unsigned long attrs)
+void *cached_kernel_address(void *p)
{
- unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
- struct page *page;
-
- if (platform_vaddr_uncached(vaddr)) {
- page = virt_to_page(platform_vaddr_to_cached(vaddr));
- } else {
-#ifdef CONFIG_MMU
- dma_common_free_remap(vaddr, size, VM_MAP);
-#endif
- page = pfn_to_page(PHYS_PFN(dma_to_phys(dev, dma_handle)));
- }
-
- if (!dma_release_from_contiguous(dev, page, count))
- __free_pages(page, get_order(size));
+ return p + XCHAL_KSEG_CACHED_VADDR - XCHAL_KSEG_BYPASS_VADDR;
}
+#endif /* CONFIG_MMU */
diff --git a/arch/xtensa/kernel/platform.c b/arch/xtensa/kernel/platform.c
index a95ba05b0abe..ac1e0e566995 100644
--- a/arch/xtensa/kernel/platform.c
+++ b/arch/xtensa/kernel/platform.c
@@ -12,12 +12,10 @@
* Chris Zankel <chris@zankel.net>
*/
+#include <linux/printk.h>
#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/time.h>
#include <asm/platform.h>
#include <asm/timex.h>
-#include <asm/param.h> /* HZ */
#define _F(r,f,a,b) \
r __platform_##f a b; \
@@ -28,6 +26,7 @@
* (Please, refer to include/asm-xtensa/platform.h for more information)
*/
+_F(void, init, (bp_tag_t *first), { });
_F(void, setup, (char** cmd), { });
_F(void, restart, (void), { while(1); });
_F(void, halt, (void), { while(1); });
diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c
index db278a9e80c7..3edecc41ef8c 100644
--- a/arch/xtensa/kernel/process.c
+++ b/arch/xtensa/kernel/process.c
@@ -202,8 +202,9 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
* involved. Much simpler to just not copy those live frames across.
*/
-int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn,
- unsigned long thread_fn_arg, struct task_struct *p)
+int copy_thread_tls(unsigned long clone_flags, unsigned long usp_thread_fn,
+ unsigned long thread_fn_arg, struct task_struct *p,
+ unsigned long tls)
{
struct pt_regs *childregs = task_pt_regs(p);
@@ -264,9 +265,10 @@ int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn,
&regs->areg[XCHAL_NUM_AREGS - len/4], len);
}
- /* The thread pointer is passed in the '4th argument' (= a5) */
+ childregs->syscall = regs->syscall;
+
if (clone_flags & CLONE_SETTLS)
- childregs->threadptr = childregs->areg[5];
+ childregs->threadptr = tls;
} 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 b964f0b2d886..145742d70a9f 100644
--- a/arch/xtensa/kernel/ptrace.c
+++ b/arch/xtensa/kernel/ptrace.c
@@ -542,14 +542,28 @@ long arch_ptrace(struct task_struct *child, long request,
return ret;
}
-void do_syscall_trace_enter(struct pt_regs *regs)
+void do_syscall_trace_leave(struct pt_regs *regs);
+int do_syscall_trace_enter(struct pt_regs *regs)
{
+ if (regs->syscall == NO_SYSCALL)
+ regs->areg[2] = -ENOSYS;
+
if (test_thread_flag(TIF_SYSCALL_TRACE) &&
- tracehook_report_syscall_entry(regs))
+ tracehook_report_syscall_entry(regs)) {
+ regs->areg[2] = -ENOSYS;
regs->syscall = NO_SYSCALL;
+ return 0;
+ }
+
+ if (regs->syscall == NO_SYSCALL) {
+ do_syscall_trace_leave(regs);
+ return 0;
+ }
if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
trace_sys_enter(regs, syscall_get_nr(current, regs));
+
+ return 1;
}
void do_syscall_trace_leave(struct pt_regs *regs)
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
index 7c3106093c75..3880c765d448 100644
--- a/arch/xtensa/kernel/setup.c
+++ b/arch/xtensa/kernel/setup.c
@@ -61,7 +61,6 @@ struct screen_info screen_info = {
#ifdef CONFIG_BLK_DEV_INITRD
extern unsigned long initrd_start;
extern unsigned long initrd_end;
-int initrd_is_mapped = 0;
extern int initrd_below_start_ok;
#endif
@@ -285,6 +284,8 @@ extern char _UserExceptionVector_text_start;
extern char _UserExceptionVector_text_end;
extern char _DoubleExceptionVector_text_start;
extern char _DoubleExceptionVector_text_end;
+extern char _exception_text_start;
+extern char _exception_text_end;
#if XCHAL_EXCM_LEVEL >= 2
extern char _Level2InterruptVector_text_start;
extern char _Level2InterruptVector_text_end;
@@ -309,6 +310,10 @@ extern char _Level6InterruptVector_text_end;
extern char _SecondaryResetVector_text_start;
extern char _SecondaryResetVector_text_end;
#endif
+#ifdef CONFIG_XIP_KERNEL
+extern char _xip_start[];
+extern char _xip_end[];
+#endif
static inline int __init_memblock mem_reserve(unsigned long start,
unsigned long end)
@@ -332,18 +337,19 @@ void __init setup_arch(char **cmdline_p)
/* Reserve some memory regions */
#ifdef CONFIG_BLK_DEV_INITRD
- if (initrd_start < initrd_end) {
- initrd_is_mapped = mem_reserve(__pa(initrd_start),
- __pa(initrd_end)) == 0;
+ if (initrd_start < initrd_end &&
+ !mem_reserve(__pa(initrd_start), __pa(initrd_end)))
initrd_below_start_ok = 1;
- } else {
+ else
initrd_start = 0;
- }
#endif
mem_reserve(__pa(_stext), __pa(_end));
+#ifdef CONFIG_XIP_KERNEL
+ mem_reserve(__pa(_xip_start), __pa(_xip_end));
+#endif
-#ifdef CONFIG_VECTORS_OFFSET
+#ifdef CONFIG_VECTORS_ADDR
mem_reserve(__pa(&_WindowVectors_text_start),
__pa(&_WindowVectors_text_end));
@@ -359,6 +365,8 @@ void __init setup_arch(char **cmdline_p)
mem_reserve(__pa(&_DoubleExceptionVector_text_start),
__pa(&_DoubleExceptionVector_text_end));
+ mem_reserve(__pa(&_exception_text_start),
+ __pa(&_exception_text_end));
#if XCHAL_EXCM_LEVEL >= 2
mem_reserve(__pa(&_Level2InterruptVector_text_start),
__pa(&_Level2InterruptVector_text_end));
@@ -380,7 +388,7 @@ void __init setup_arch(char **cmdline_p)
__pa(&_Level6InterruptVector_text_end));
#endif
-#endif /* CONFIG_VECTORS_OFFSET */
+#endif /* CONFIG_VECTORS_ADDR */
#ifdef CONFIG_SMP
mem_reserve(__pa(&_SecondaryResetVector_text_start),
@@ -401,8 +409,6 @@ void __init setup_arch(char **cmdline_p)
#ifdef CONFIG_VT
# if defined(CONFIG_VGA_CONSOLE)
conswitchp = &vga_con;
-# elif defined(CONFIG_DUMMY_CONSOLE)
- conswitchp = &dummy_con;
# endif
#endif
}
diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c
index fbedf2aba09d..76cee341507b 100644
--- a/arch/xtensa/kernel/signal.c
+++ b/arch/xtensa/kernel/signal.c
@@ -236,9 +236,9 @@ restore_sigcontext(struct pt_regs *regs, struct rt_sigframe __user *frame)
* Do a signal return; undo the signal stack.
*/
-asmlinkage long xtensa_rt_sigreturn(long a0, long a1, long a2, long a3,
- long a4, long a5, struct pt_regs *regs)
+asmlinkage long xtensa_rt_sigreturn(void)
{
+ struct pt_regs *regs = current_pt_regs();
struct rt_sigframe __user *frame;
sigset_t set;
int ret;
@@ -335,7 +335,8 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
{
struct rt_sigframe *frame;
int err = 0, sig = ksig->sig;
- unsigned long sp, ra, tp;
+ unsigned long sp, ra, tp, ps;
+ unsigned int base;
sp = regs->areg[1];
@@ -385,17 +386,26 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
/* Set up registers for signal handler; preserve the threadptr */
tp = regs->threadptr;
+ ps = regs->ps;
start_thread(regs, (unsigned long) ksig->ka.sa.sa_handler,
(unsigned long) frame);
- /* Set up a stack frame for a call4
- * Note: PS.CALLINC is set to one by start_thread
- */
- regs->areg[4] = (((unsigned long) ra) & 0x3fffffff) | 0x40000000;
- regs->areg[6] = (unsigned long) sig;
- regs->areg[7] = (unsigned long) &frame->info;
- regs->areg[8] = (unsigned long) &frame->uc;
+ /* Set up a stack frame for a call4 if userspace uses windowed ABI */
+ if (ps & PS_WOE_MASK) {
+ base = 4;
+ regs->areg[base] =
+ (((unsigned long) ra) & 0x3fffffff) | 0x40000000;
+ ps = (ps & ~(PS_CALLINC_MASK | PS_OWB_MASK)) |
+ (1 << PS_CALLINC_SHIFT);
+ } else {
+ base = 0;
+ regs->areg[base] = (unsigned long) ra;
+ }
+ regs->areg[base + 2] = (unsigned long) sig;
+ regs->areg[base + 3] = (unsigned long) &frame->info;
+ regs->areg[base + 4] = (unsigned long) &frame->uc;
regs->threadptr = tp;
+ regs->ps = ps;
pr_debug("SIG rt deliver (%s:%d): signal=%d sp=%p pc=%08lx\n",
current->comm, current->pid, sig, frame, regs->pc);
diff --git a/arch/xtensa/kernel/stacktrace.c b/arch/xtensa/kernel/stacktrace.c
index b9f82510c650..c822abb93d20 100644
--- a/arch/xtensa/kernel/stacktrace.c
+++ b/arch/xtensa/kernel/stacktrace.c
@@ -44,6 +44,11 @@ void xtensa_backtrace_user(struct pt_regs *regs, unsigned int depth,
if (pc == 0 || pc >= TASK_SIZE || ufn(&frame, data))
return;
+ if (IS_ENABLED(CONFIG_USER_ABI_CALL0_ONLY) ||
+ (IS_ENABLED(CONFIG_USER_ABI_CALL0_PROBE) &&
+ !(regs->ps & PS_WOE_MASK)))
+ return;
+
/* Two steps:
*
* 1. Look through the register window for the
diff --git a/arch/xtensa/kernel/syscalls/syscall.tbl b/arch/xtensa/kernel/syscalls/syscall.tbl
index 25f4de729a6d..85a9ab1bc04d 100644
--- a/arch/xtensa/kernel/syscalls/syscall.tbl
+++ b/arch/xtensa/kernel/syscalls/syscall.tbl
@@ -406,3 +406,5 @@
433 common fspick sys_fspick
434 common pidfd_open sys_pidfd_open
435 common clone3 sys_clone3
+437 common openat2 sys_openat2
+438 common pidfd_getfd sys_pidfd_getfd
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c
index f060348c1b23..0976e27b8d5d 100644
--- a/arch/xtensa/kernel/traps.c
+++ b/arch/xtensa/kernel/traps.c
@@ -51,6 +51,7 @@
extern void kernel_exception(void);
extern void user_exception(void);
+extern void fast_illegal_instruction_user(void);
extern void fast_syscall_user(void);
extern void fast_alloca(void);
extern void fast_unaligned(void);
@@ -87,6 +88,9 @@ typedef struct {
static dispatch_init_table_t __initdata dispatch_init_table[] = {
+#ifdef CONFIG_USER_ABI_CALL0_PROBE
+{ EXCCAUSE_ILLEGAL_INSTRUCTION, USER, fast_illegal_instruction_user },
+#endif
{ EXCCAUSE_ILLEGAL_INSTRUCTION, 0, do_illegal_instruction},
{ EXCCAUSE_SYSTEM_CALL, USER, fast_syscall_user },
{ EXCCAUSE_SYSTEM_CALL, 0, system_call },
@@ -487,32 +491,27 @@ void show_trace(struct task_struct *task, unsigned long *sp)
pr_info("Call Trace:\n");
walk_stackframe(sp, show_trace_cb, NULL);
-#ifndef CONFIG_KALLSYMS
- pr_cont("\n");
-#endif
}
-static int kstack_depth_to_print = 24;
+#define STACK_DUMP_ENTRY_SIZE 4
+#define STACK_DUMP_LINE_SIZE 32
+static size_t kstack_depth_to_print = CONFIG_PRINT_STACK_DEPTH;
void show_stack(struct task_struct *task, unsigned long *sp)
{
- int i = 0;
- unsigned long *stack;
+ size_t len;
if (!sp)
sp = stack_pointer(task);
- stack = sp;
- pr_info("Stack:\n");
+ len = min((-(size_t)sp) & (THREAD_SIZE - STACK_DUMP_ENTRY_SIZE),
+ kstack_depth_to_print * STACK_DUMP_ENTRY_SIZE);
- for (i = 0; i < kstack_depth_to_print; i++) {
- if (kstack_end(sp))
- break;
- pr_cont(" %08lx", *sp++);
- if (i % 8 == 7)
- pr_cont("\n");
- }
- show_trace(task, stack);
+ pr_info("Stack:\n");
+ print_hex_dump(KERN_INFO, " ", DUMP_PREFIX_NONE,
+ STACK_DUMP_LINE_SIZE, STACK_DUMP_ENTRY_SIZE,
+ sp, len, false);
+ show_trace(task, sp);
}
DEFINE_SPINLOCK(die_lock);
@@ -520,12 +519,15 @@ DEFINE_SPINLOCK(die_lock);
void die(const char * str, struct pt_regs * regs, long err)
{
static int die_counter;
+ const char *pr = "";
+
+ if (IS_ENABLED(CONFIG_PREEMPTION))
+ pr = IS_ENABLED(CONFIG_PREEMPT_RT) ? " PREEMPT_RT" : " PREEMPT";
console_verbose();
spin_lock_irq(&die_lock);
- pr_info("%s: sig: %ld [#%d]%s\n", str, err, ++die_counter,
- IS_ENABLED(CONFIG_PREEMPT) ? " PREEMPT" : "");
+ pr_info("%s: sig: %ld [#%d]%s\n", str, err, ++die_counter, pr);
show_regs(regs);
if (!user_mode(regs))
show_stack(NULL, (unsigned long*)regs->areg[1]);
diff --git a/arch/xtensa/kernel/vectors.S b/arch/xtensa/kernel/vectors.S
index 841503d3307c..95ad1e773991 100644
--- a/arch/xtensa/kernel/vectors.S
+++ b/arch/xtensa/kernel/vectors.S
@@ -43,6 +43,7 @@
*/
#include <linux/linkage.h>
+#include <asm/asmmacro.h>
#include <asm/ptrace.h>
#include <asm/current.h>
#include <asm/asm-offsets.h>
@@ -477,7 +478,6 @@ _DoubleExceptionVector_handle_exception:
ENDPROC(_DoubleExceptionVector)
- .text
/*
* Fixup handler for TLB miss in double exception handler for window owerflow.
* We get here with windowbase set to the window that was being spilled and
@@ -505,6 +505,7 @@ ENDPROC(_DoubleExceptionVector)
* a3: exctable, original value in excsave1
*/
+ __XTENSA_HANDLER
.literal_position
ENTRY(window_overflow_restore_a0_fixup)
diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S
index 943f10639a93..d23a6e38f062 100644
--- a/arch/xtensa/kernel/vmlinux.lds.S
+++ b/arch/xtensa/kernel/vmlinux.lds.S
@@ -14,6 +14,8 @@
* Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
*/
+#define RO_EXCEPTION_TABLE_ALIGN 16
+
#include <asm-generic/vmlinux.lds.h>
#include <asm/page.h>
#include <asm/thread_info.h>
@@ -45,15 +47,20 @@ jiffies = jiffies_64;
LONG(sym ## _end); \
LONG(LOADADDR(section))
+#if !defined(CONFIG_VECTORS_ADDR) && XCHAL_HAVE_VECBASE
+#define MERGED_VECTORS 1
+#else
+#define MERGED_VECTORS 0
+#endif
+
/*
- * Macro to define a section for a vector. When CONFIG_VECTORS_OFFSET is
- * defined code for every vector is located with other init data. At startup
+ * Macro to define a section for a vector. When MERGED_VECTORS is 0
+ * code for every vector is located with other init data. At startup
* time head.S copies code for every vector to its final position according
* to description recorded in the corresponding RELOCATE_ENTRY.
*/
-#ifdef CONFIG_VECTORS_OFFSET
-#define SECTION_VECTOR(sym, section, addr, prevsec) \
+#define SECTION_VECTOR4(sym, section, addr, prevsec) \
section addr : AT(((LOADADDR(prevsec) + SIZEOF(prevsec)) + 3) & ~ 3) \
{ \
. = ALIGN(4); \
@@ -61,11 +68,10 @@ jiffies = jiffies_64;
*(section) \
sym ## _end = ABSOLUTE(.); \
}
-#else
-#define SECTION_VECTOR(section, addr) \
+
+#define SECTION_VECTOR2(section, addr) \
. = addr; \
*(section)
-#endif
/*
* Mapping of input sections to output sections when linking.
@@ -84,30 +90,32 @@ SECTIONS
/* The HEAD_TEXT section must be the first section! */
HEAD_TEXT
-#ifndef CONFIG_VECTORS_OFFSET
- . = ALIGN(PAGE_SIZE);
- _vecbase = .;
+#if MERGED_VECTORS
+ . = ALIGN(PAGE_SIZE);
+ _vecbase = .;
- SECTION_VECTOR (.WindowVectors.text, WINDOW_VECTORS_VADDR)
+ SECTION_VECTOR2 (.WindowVectors.text, WINDOW_VECTORS_VADDR)
#if XCHAL_EXCM_LEVEL >= 2
- SECTION_VECTOR (.Level2InterruptVector.text, INTLEVEL2_VECTOR_VADDR)
+ SECTION_VECTOR2 (.Level2InterruptVector.text, INTLEVEL2_VECTOR_VADDR)
#endif
#if XCHAL_EXCM_LEVEL >= 3
- SECTION_VECTOR (.Level3InterruptVector.text, INTLEVEL3_VECTOR_VADDR)
+ SECTION_VECTOR2 (.Level3InterruptVector.text, INTLEVEL3_VECTOR_VADDR)
#endif
#if XCHAL_EXCM_LEVEL >= 4
- SECTION_VECTOR (.Level4InterruptVector.text, INTLEVEL4_VECTOR_VADDR)
+ SECTION_VECTOR2 (.Level4InterruptVector.text, INTLEVEL4_VECTOR_VADDR)
#endif
#if XCHAL_EXCM_LEVEL >= 5
- SECTION_VECTOR (.Level5InterruptVector.text, INTLEVEL5_VECTOR_VADDR)
+ SECTION_VECTOR2 (.Level5InterruptVector.text, INTLEVEL5_VECTOR_VADDR)
#endif
#if XCHAL_EXCM_LEVEL >= 6
- SECTION_VECTOR (.Level6InterruptVector.text, INTLEVEL6_VECTOR_VADDR)
+ SECTION_VECTOR2 (.Level6InterruptVector.text, INTLEVEL6_VECTOR_VADDR)
#endif
- SECTION_VECTOR (.DebugInterruptVector.text, DEBUG_VECTOR_VADDR)
- SECTION_VECTOR (.KernelExceptionVector.text, KERNEL_VECTOR_VADDR)
- SECTION_VECTOR (.UserExceptionVector.text, USER_VECTOR_VADDR)
- SECTION_VECTOR (.DoubleExceptionVector.text, DOUBLEEXC_VECTOR_VADDR)
+ SECTION_VECTOR2 (.DebugInterruptVector.text, DEBUG_VECTOR_VADDR)
+ SECTION_VECTOR2 (.KernelExceptionVector.text, KERNEL_VECTOR_VADDR)
+ SECTION_VECTOR2 (.UserExceptionVector.text, USER_VECTOR_VADDR)
+ SECTION_VECTOR2 (.DoubleExceptionVector.text, DOUBLEEXC_VECTOR_VADDR)
+
+ *(.exception.text)
#endif
IRQENTRY_TEXT
@@ -117,25 +125,22 @@ SECTIONS
SCHED_TEXT
CPUIDLE_TEXT
LOCK_TEXT
-
+ *(.fixup)
}
_etext = .;
PROVIDE (etext = .);
. = ALIGN(16);
- RODATA
-
- /* Relocation table */
-
- .fixup : { *(.fixup) }
+ RO_DATA(4096)
- EXCEPTION_TABLE(16)
- NOTES
/* Data section */
+#ifdef CONFIG_XIP_KERNEL
+ INIT_TEXT_SECTION(PAGE_SIZE)
+#else
_sdata = .;
- RW_DATA_SECTION(XCHAL_ICACHE_LINESIZE, PAGE_SIZE, THREAD_SIZE)
+ RW_DATA(XCHAL_ICACHE_LINESIZE, PAGE_SIZE, THREAD_SIZE)
_edata = .;
/* Initialization code and data: */
@@ -147,6 +152,11 @@ SECTIONS
.init.data :
{
INIT_DATA
+ }
+#endif
+
+ .init.rodata :
+ {
. = ALIGN(0x4);
__tagtable_begin = .;
*(.taglist)
@@ -155,7 +165,7 @@ SECTIONS
. = ALIGN(16);
__boot_reloc_table_start = ABSOLUTE(.);
-#ifdef CONFIG_VECTORS_OFFSET
+#if !MERGED_VECTORS
RELOCATE_ENTRY(_WindowVectors_text,
.WindowVectors.text);
#if XCHAL_EXCM_LEVEL >= 2
@@ -186,13 +196,18 @@ SECTIONS
.DoubleExceptionVector.text);
RELOCATE_ENTRY(_DebugInterruptVector_text,
.DebugInterruptVector.text);
+ RELOCATE_ENTRY(_exception_text,
+ .exception.text);
+#endif
+#ifdef CONFIG_XIP_KERNEL
+ RELOCATE_ENTRY(_xip_data, .data);
+ RELOCATE_ENTRY(_xip_init_data, .init.data);
#endif
#if defined(CONFIG_SMP)
RELOCATE_ENTRY(_SecondaryResetVector_text,
.SecondaryResetVector.text);
#endif
-
__boot_reloc_table_end = ABSOLUTE(.) ;
INIT_SETUP(XCHAL_ICACHE_LINESIZE)
@@ -208,21 +223,24 @@ SECTIONS
. = ALIGN(4);
.dummy : { LONG(0) }
-#ifdef CONFIG_VECTORS_OFFSET
+#undef LAST
+#define LAST .dummy
+
+#if !MERGED_VECTORS
/* The vectors are relocated to the real position at startup time */
- SECTION_VECTOR (_WindowVectors_text,
+ SECTION_VECTOR4 (_WindowVectors_text,
.WindowVectors.text,
WINDOW_VECTORS_VADDR,
.dummy)
- SECTION_VECTOR (_DebugInterruptVector_text,
+ SECTION_VECTOR4 (_DebugInterruptVector_text,
.DebugInterruptVector.text,
DEBUG_VECTOR_VADDR,
.WindowVectors.text)
#undef LAST
#define LAST .DebugInterruptVector.text
#if XCHAL_EXCM_LEVEL >= 2
- SECTION_VECTOR (_Level2InterruptVector_text,
+ SECTION_VECTOR4 (_Level2InterruptVector_text,
.Level2InterruptVector.text,
INTLEVEL2_VECTOR_VADDR,
LAST)
@@ -230,7 +248,7 @@ SECTIONS
# define LAST .Level2InterruptVector.text
#endif
#if XCHAL_EXCM_LEVEL >= 3
- SECTION_VECTOR (_Level3InterruptVector_text,
+ SECTION_VECTOR4 (_Level3InterruptVector_text,
.Level3InterruptVector.text,
INTLEVEL3_VECTOR_VADDR,
LAST)
@@ -238,7 +256,7 @@ SECTIONS
# define LAST .Level3InterruptVector.text
#endif
#if XCHAL_EXCM_LEVEL >= 4
- SECTION_VECTOR (_Level4InterruptVector_text,
+ SECTION_VECTOR4 (_Level4InterruptVector_text,
.Level4InterruptVector.text,
INTLEVEL4_VECTOR_VADDR,
LAST)
@@ -246,7 +264,7 @@ SECTIONS
# define LAST .Level4InterruptVector.text
#endif
#if XCHAL_EXCM_LEVEL >= 5
- SECTION_VECTOR (_Level5InterruptVector_text,
+ SECTION_VECTOR4 (_Level5InterruptVector_text,
.Level5InterruptVector.text,
INTLEVEL5_VECTOR_VADDR,
LAST)
@@ -254,49 +272,95 @@ SECTIONS
# define LAST .Level5InterruptVector.text
#endif
#if XCHAL_EXCM_LEVEL >= 6
- SECTION_VECTOR (_Level6InterruptVector_text,
+ SECTION_VECTOR4 (_Level6InterruptVector_text,
.Level6InterruptVector.text,
INTLEVEL6_VECTOR_VADDR,
LAST)
# undef LAST
# define LAST .Level6InterruptVector.text
#endif
- SECTION_VECTOR (_KernelExceptionVector_text,
+ SECTION_VECTOR4 (_KernelExceptionVector_text,
.KernelExceptionVector.text,
KERNEL_VECTOR_VADDR,
LAST)
#undef LAST
- SECTION_VECTOR (_UserExceptionVector_text,
+ SECTION_VECTOR4 (_UserExceptionVector_text,
.UserExceptionVector.text,
USER_VECTOR_VADDR,
.KernelExceptionVector.text)
- SECTION_VECTOR (_DoubleExceptionVector_text,
+ SECTION_VECTOR4 (_DoubleExceptionVector_text,
.DoubleExceptionVector.text,
DOUBLEEXC_VECTOR_VADDR,
.UserExceptionVector.text)
-
- . = (LOADADDR( .DoubleExceptionVector.text ) + SIZEOF( .DoubleExceptionVector.text ) + 3) & ~ 3;
+#define LAST .DoubleExceptionVector.text
#endif
#if defined(CONFIG_SMP)
- SECTION_VECTOR (_SecondaryResetVector_text,
+ SECTION_VECTOR4 (_SecondaryResetVector_text,
.SecondaryResetVector.text,
RESET_VECTOR1_VADDR,
- .DoubleExceptionVector.text)
+ LAST)
+#undef LAST
+#define LAST .SecondaryResetVector.text
- . = LOADADDR(.SecondaryResetVector.text)+SIZEOF(.SecondaryResetVector.text);
+#endif
+#if !MERGED_VECTORS
+ SECTION_VECTOR4 (_exception_text,
+ .exception.text,
+ ,
+ LAST)
+#undef LAST
+#define LAST .exception.text
#endif
+ . = (LOADADDR(LAST) + SIZEOF(LAST) + 3) & ~ 3;
+ .dummy1 : AT(ADDR(.dummy1)) { LONG(0) }
. = ALIGN(PAGE_SIZE);
+#ifndef CONFIG_XIP_KERNEL
__init_end = .;
BSS_SECTION(0, 8192, 0)
+#endif
_end = .;
+#ifdef CONFIG_XIP_KERNEL
+ . = CONFIG_XIP_DATA_ADDR;
+
+ _xip_start = .;
+
+#undef LOAD_OFFSET
+#define LOAD_OFFSET \
+ (CONFIG_XIP_DATA_ADDR - (LOADADDR(.dummy1) + SIZEOF(.dummy1) + 3) & ~ 3)
+
+ _xip_data_start = .;
+ _sdata = .;
+ RW_DATA(XCHAL_ICACHE_LINESIZE, PAGE_SIZE, THREAD_SIZE)
+ _edata = .;
+ _xip_data_end = .;
+
+ /* Initialization data: */
+
+ STRUCT_ALIGN();
+
+ _xip_init_data_start = .;
+ __init_begin = .;
+ .init.data :
+ {
+ INIT_DATA
+ }
+ _xip_init_data_end = .;
+ __init_end = .;
+ BSS_SECTION(0, 8192, 0)
+
+ _xip_end = .;
+
+#undef LOAD_OFFSET
+#endif
+
DWARF_DEBUG
.xt.prop 0 : { KEEP(*(.xt.prop .xt.prop.* .gnu.linkonce.prop.*)) }
diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c
index 04f19de46700..4092555828b1 100644
--- a/arch/xtensa/kernel/xtensa_ksyms.c
+++ b/arch/xtensa/kernel/xtensa_ksyms.c
@@ -119,13 +119,6 @@ EXPORT_SYMBOL(__invalidate_icache_range);
// FIXME EXPORT_SYMBOL(screen_info);
#endif
-EXPORT_SYMBOL(outsb);
-EXPORT_SYMBOL(outsw);
-EXPORT_SYMBOL(outsl);
-EXPORT_SYMBOL(insb);
-EXPORT_SYMBOL(insw);
-EXPORT_SYMBOL(insl);
-
extern long common_exception_return;
EXPORT_SYMBOL(common_exception_return);
OpenPOWER on IntegriCloud