diff options
Diffstat (limited to 'arch/xtensa/kernel')
-rw-r--r-- | arch/xtensa/kernel/coprocessor.S | 8 | ||||
-rw-r--r-- | arch/xtensa/kernel/entry.S | 53 | ||||
-rw-r--r-- | arch/xtensa/kernel/head.S | 2 | ||||
-rw-r--r-- | arch/xtensa/kernel/mcount.S | 11 | ||||
-rw-r--r-- | arch/xtensa/kernel/pci-dma.c | 12 | ||||
-rw-r--r-- | arch/xtensa/kernel/pci.c | 124 | ||||
-rw-r--r-- | arch/xtensa/kernel/platform.c | 2 | ||||
-rw-r--r-- | arch/xtensa/kernel/setup.c | 14 | ||||
-rw-r--r-- | arch/xtensa/kernel/signal.c | 28 | ||||
-rw-r--r-- | arch/xtensa/kernel/stacktrace.c | 5 | ||||
-rw-r--r-- | arch/xtensa/kernel/syscalls/syscall.tbl | 2 | ||||
-rw-r--r-- | arch/xtensa/kernel/traps.c | 12 |
12 files changed, 98 insertions, 175 deletions
diff --git a/arch/xtensa/kernel/coprocessor.S b/arch/xtensa/kernel/coprocessor.S index 92bf24a9da92..80828b95a51f 100644 --- a/arch/xtensa/kernel/coprocessor.S +++ b/arch/xtensa/kernel/coprocessor.S @@ -14,6 +14,7 @@ #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> @@ -121,7 +122,9 @@ ENTRY(coprocessor_flush) - entry a1, 32 + /* reserve 4 bytes on stack to save a0 */ + abi_entry(4) + s32i a0, a1, 0 movi a0, .Lsave_cp_regs_jump_table addx8 a3, a3, a0 @@ -131,7 +134,8 @@ ENTRY(coprocessor_flush) beqz a3, 1f callx0 a3 1: l32i a0, a1, 0 - retw + + abi_ret(4) ENDPROC(coprocessor_flush) diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index e54af8b7e0f8..9e3676879168 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 @@ -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 @@ -1003,7 +1003,41 @@ 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, user_exception + 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 + +ENDPROC(fast_illegal_instruction_user) +#endif + + /* * fast system calls. * * WARNING: The kernel doesn't save the entire user context before @@ -1359,7 +1393,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 @@ -1842,7 +1876,8 @@ ENDPROC(fast_store_prohibited) ENTRY(system_call) - entry a1, 32 + /* reserve 4 bytes on stack for function parameter */ + abi_entry(4) /* regs->syscall = regs->areg[2] */ @@ -1892,7 +1927,7 @@ ENTRY(system_call) s32i a6, a2, PT_AREG2 bnez a3, 1f - retw + abi_ret(4) 1: l32i a4, a1, 4 @@ -1901,7 +1936,7 @@ ENTRY(system_call) mov a6, a2 call4 do_syscall_trace_leave s32i a3, a2, PT_SYSCALL - retw + abi_ret(4) ENDPROC(system_call) @@ -1952,7 +1987,7 @@ ENDPROC(system_call) ENTRY(_switch_to) - entry a1, 48 + abi_entry(XTENSA_SPILL_STACK_RESERVE) mov a11, a3 # and 'next' (a3) @@ -2013,7 +2048,7 @@ ENTRY(_switch_to) wsr a14, ps rsync - retw + abi_ret(XTENSA_SPILL_STACK_RESERVE) ENDPROC(_switch_to) diff --git a/arch/xtensa/kernel/head.S b/arch/xtensa/kernel/head.S index 7f009719304e..4ae998b5a348 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 diff --git a/arch/xtensa/kernel/mcount.S b/arch/xtensa/kernel/mcount.S index 0eeda2e4a25e..5e4619f52858 100644 --- a/arch/xtensa/kernel/mcount.S +++ b/arch/xtensa/kernel/mcount.S @@ -11,6 +11,7 @@ */ #include <linux/linkage.h> +#include <asm/asmmacro.h> #include <asm/ftrace.h> /* @@ -21,13 +22,13 @@ ENTRY(_mcount) - entry a1, 16 + abi_entry_default movi a4, ftrace_trace_function l32i a4, a4, 0 movi a3, ftrace_stub bne a3, a4, 1f - retw + abi_ret_default 1: xor a7, a2, a1 movi a3, 0x3fffffff @@ -40,11 +41,11 @@ ENTRY(_mcount) addi a6, a6, -MCOUNT_INSN_SIZE callx4 a4 - retw + abi_ret_default ENDPROC(_mcount) ENTRY(ftrace_stub) - entry a1, 16 - retw + abi_entry_default + abi_ret_default ENDPROC(ftrace_stub) diff --git a/arch/xtensa/kernel/pci-dma.c b/arch/xtensa/kernel/pci-dma.c index a87f8a308cc1..154979d62b73 100644 --- a/arch/xtensa/kernel/pci-dma.c +++ b/arch/xtensa/kernel/pci-dma.c @@ -163,15 +163,11 @@ void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, *handle = phys_to_dma(dev, page_to_phys(page)); - if (attrs & DMA_ATTR_NO_KERNEL_MAPPING) { - return page; - } - #ifdef CONFIG_MMU if (PageHighMem(page)) { void *p; - p = dma_common_contiguous_remap(page, size, VM_MAP, + p = dma_common_contiguous_remap(page, size, pgprot_noncached(PAGE_KERNEL), __builtin_return_address(0)); if (!p) { @@ -192,13 +188,11 @@ void arch_dma_free(struct device *dev, size_t size, void *vaddr, unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT; struct page *page; - if (attrs & DMA_ATTR_NO_KERNEL_MAPPING) { - page = vaddr; - } else if (platform_vaddr_uncached(vaddr)) { + 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); + dma_common_free_remap(vaddr, size); #endif page = pfn_to_page(PHYS_PFN(dma_to_phys(dev, dma_handle))); } diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c index 8b823f94e568..3f32e275997a 100644 --- a/arch/xtensa/kernel/pci.c +++ b/arch/xtensa/kernel/pci.c @@ -24,23 +24,6 @@ #include <asm/pci-bridge.h> #include <asm/platform.h> -/* PCI Controller */ - - -/* - * pcibios_alloc_controller - * pcibios_enable_device - * pcibios_fixups - * pcibios_align_resource - * pcibios_fixup_bus - * pci_bus_add_device - */ - -static struct pci_controller *pci_ctrl_head; -static struct pci_controller **pci_ctrl_tail = &pci_ctrl_head; - -static int pci_bus_count; - /* * We need to avoid collisions with `mirrored' VGA ports * and other strange ISA hardware, so we always want the @@ -75,81 +58,6 @@ pcibios_align_resource(void *data, const struct resource *res, return start; } -static void __init pci_controller_apertures(struct pci_controller *pci_ctrl, - struct list_head *resources) -{ - struct resource *res; - unsigned long io_offset; - int i; - - io_offset = (unsigned long)pci_ctrl->io_space.base; - res = &pci_ctrl->io_resource; - if (!res->flags) { - if (io_offset) - pr_err("I/O resource not set for host bridge %d\n", - pci_ctrl->index); - res->start = 0; - res->end = IO_SPACE_LIMIT; - res->flags = IORESOURCE_IO; - } - res->start += io_offset; - res->end += io_offset; - pci_add_resource_offset(resources, res, io_offset); - - for (i = 0; i < 3; i++) { - res = &pci_ctrl->mem_resources[i]; - if (!res->flags) { - if (i > 0) - continue; - pr_err("Memory resource not set for host bridge %d\n", - pci_ctrl->index); - res->start = 0; - res->end = ~0U; - res->flags = IORESOURCE_MEM; - } - pci_add_resource(resources, res); - } -} - -static int __init pcibios_init(void) -{ - struct pci_controller *pci_ctrl; - struct list_head resources; - struct pci_bus *bus; - int next_busno = 0, ret; - - pr_info("PCI: Probing PCI hardware\n"); - - /* Scan all of the recorded PCI controllers. */ - for (pci_ctrl = pci_ctrl_head; pci_ctrl; pci_ctrl = pci_ctrl->next) { - pci_ctrl->last_busno = 0xff; - INIT_LIST_HEAD(&resources); - pci_controller_apertures(pci_ctrl, &resources); - bus = pci_scan_root_bus(NULL, pci_ctrl->first_busno, - pci_ctrl->ops, pci_ctrl, &resources); - if (!bus) - continue; - - pci_ctrl->bus = bus; - pci_ctrl->last_busno = bus->busn_res.end; - if (next_busno <= pci_ctrl->last_busno) - next_busno = pci_ctrl->last_busno+1; - } - pci_bus_count = next_busno; - ret = platform_pcibios_fixup(); - if (ret) - return ret; - - for (pci_ctrl = pci_ctrl_head; pci_ctrl; pci_ctrl = pci_ctrl->next) { - if (pci_ctrl->bus) - pci_bus_add_devices(pci_ctrl->bus); - } - - return 0; -} - -subsys_initcall(pcibios_init); - void pcibios_fixup_bus(struct pci_bus *bus) { if (bus->parent) { @@ -158,38 +66,6 @@ void pcibios_fixup_bus(struct pci_bus *bus) } } -void pcibios_set_master(struct pci_dev *dev) -{ - /* No special bus mastering setup handling */ -} - -int pcibios_enable_device(struct pci_dev *dev, int mask) -{ - u16 cmd, old_cmd; - int idx; - struct resource *r; - - pci_read_config_word(dev, PCI_COMMAND, &cmd); - old_cmd = cmd; - for (idx=0; idx<6; idx++) { - r = &dev->resource[idx]; - if (!r->start && r->end) { - pci_err(dev, "can't enable device: resource collisions\n"); - return -EINVAL; - } - if (r->flags & IORESOURCE_IO) - cmd |= PCI_COMMAND_IO; - if (r->flags & IORESOURCE_MEM) - cmd |= PCI_COMMAND_MEMORY; - } - if (cmd != old_cmd) { - pci_info(dev, "enabling device (%04x -> %04x)\n", old_cmd, cmd); - pci_write_config_word(dev, PCI_COMMAND, cmd); - } - - return 0; -} - /* * Platform support for /proc/bus/pci/X/Y mmap()s. * -- paulus. diff --git a/arch/xtensa/kernel/platform.c b/arch/xtensa/kernel/platform.c index 1cf008284dd2..a95ba05b0abe 100644 --- a/arch/xtensa/kernel/platform.c +++ b/arch/xtensa/kernel/platform.c @@ -34,8 +34,6 @@ _F(void, halt, (void), { while(1); }); _F(void, power_off, (void), { while(1); }); _F(void, idle, (void), { __asm__ __volatile__ ("waiti 0" ::: "memory"); }); _F(void, heartbeat, (void), { }); -_F(int, pcibios_fixup, (void), { return 0; }); -_F(void, pcibios_init, (void), { }); #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT _F(void, calibrate_ccount, (void), diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c index 176cb46bcf12..e0e1e1892b86 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 @@ -332,13 +331,11 @@ 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)); @@ -405,10 +402,6 @@ void __init setup_arch(char **cmdline_p) conswitchp = &dummy_con; # endif #endif - -#ifdef CONFIG_PCI - platform_pcibios_init(); -#endif } static DEFINE_PER_CPU(struct cpu, cpu_data); @@ -515,6 +508,7 @@ void cpu_reset(void) "add %2, %2, %7\n\t" "addi %0, %0, -1\n\t" "bnez %0, 1b\n\t" + "isync\n\t" /* Jump to identity mapping */ "jx %3\n" "2:\n\t" diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c index dc22a238ed9c..dae83cddd6ca 100644 --- a/arch/xtensa/kernel/signal.c +++ b/arch/xtensa/kernel/signal.c @@ -270,7 +270,7 @@ asmlinkage long xtensa_rt_sigreturn(long a0, long a1, long a2, long a3, return ret; badframe: - force_sig(SIGSEGV, current); + force_sig(SIGSEGV); return 0; } @@ -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 5fa0ee1c8e00..25f4de729a6d 100644 --- a/arch/xtensa/kernel/syscalls/syscall.tbl +++ b/arch/xtensa/kernel/syscalls/syscall.tbl @@ -404,3 +404,5 @@ 431 common fsconfig sys_fsconfig 432 common fsmount sys_fsmount 433 common fspick sys_fspick +434 common pidfd_open sys_pidfd_open +435 common clone3 sys_clone3 diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c index 454d53096bc9..4a6c495ce9b6 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 }, @@ -184,7 +188,7 @@ void do_unhandled(struct pt_regs *regs, unsigned long exccause) "\tEXCCAUSE is %ld\n", current->comm, task_pid_nr(current), regs->pc, exccause); - force_sig(SIGILL, current); + force_sig(SIGILL); } /* @@ -306,7 +310,7 @@ do_illegal_instruction(struct pt_regs *regs) pr_info_ratelimited("Illegal Instruction in '%s' (pid = %d, pc = %#010lx)\n", current->comm, task_pid_nr(current), regs->pc); - force_sig(SIGILL, current); + force_sig(SIGILL); } @@ -330,7 +334,7 @@ do_unaligned_user (struct pt_regs *regs) "(pid = %d, pc = %#010lx)\n", regs->excvaddr, current->comm, task_pid_nr(current), regs->pc); - force_sig_fault(SIGBUS, BUS_ADRALN, (void *) regs->excvaddr, current); + force_sig_fault(SIGBUS, BUS_ADRALN, (void *) regs->excvaddr); } #endif @@ -354,7 +358,7 @@ do_debug(struct pt_regs *regs) /* If in user mode, send SIGTRAP signal to current process */ - force_sig(SIGTRAP, current); + force_sig(SIGTRAP); } |