diff options
Diffstat (limited to 'arch/m68k/kernel')
37 files changed, 556 insertions, 553 deletions
diff --git a/arch/m68k/kernel/.gitignore b/arch/m68k/kernel/.gitignore index c5f676c3c224..bbb90f92d051 100644 --- a/arch/m68k/kernel/.gitignore +++ b/arch/m68k/kernel/.gitignore @@ -1 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0-only vmlinux.lds diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile index dbac7f8743fc..f335bf3268a1 100644 --- a/arch/m68k/kernel/Makefile +++ b/arch/m68k/kernel/Makefile @@ -3,27 +3,29 @@ # Makefile for the linux kernel. # -extra-$(CONFIG_AMIGA) := head.o -extra-$(CONFIG_ATARI) := head.o -extra-$(CONFIG_MAC) := head.o -extra-$(CONFIG_APOLLO) := head.o -extra-$(CONFIG_VME) := head.o -extra-$(CONFIG_HP300) := head.o -extra-$(CONFIG_Q40) := head.o -extra-$(CONFIG_SUN3X) := head.o -extra-$(CONFIG_SUN3) := sun3-head.o extra-y += vmlinux.lds -obj-y := entry.o irq.o module.o process.o ptrace.o +obj-$(CONFIG_AMIGA) := head.o +obj-$(CONFIG_ATARI) := head.o +obj-$(CONFIG_MAC) := head.o +obj-$(CONFIG_APOLLO) := head.o +obj-$(CONFIG_VME) := head.o +obj-$(CONFIG_HP300) := head.o +obj-$(CONFIG_Q40) := head.o +obj-$(CONFIG_SUN3X) := head.o +obj-$(CONFIG_VIRT) := head.o +obj-$(CONFIG_SUN3) := sun3-head.o + +obj-y += entry.o irq.o module.o process.o ptrace.o obj-y += setup.o signal.o sys_m68k.o syscalltable.o time.o traps.o obj-$(CONFIG_MMU_MOTOROLA) += ints.o vectors.o obj-$(CONFIG_MMU_SUN3) += ints.o vectors.o obj-$(CONFIG_PCI) += pcibios.o -obj-$(CONFIG_HAS_DMA) += dma.o +obj-$(CONFIG_M68K_NONCOHERENT_DMA) += dma.o -obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o +obj-$(CONFIG_KEXEC_CORE) += machine_kexec.o relocate_kernel.o obj-$(CONFIG_BOOTINFO_PROC) += bootinfo_proc.o obj-$(CONFIG_UBOOT) += uboot.o diff --git a/arch/m68k/kernel/asm-offsets.c b/arch/m68k/kernel/asm-offsets.c index ccea355052ef..906d73230537 100644 --- a/arch/m68k/kernel/asm-offsets.c +++ b/arch/m68k/kernel/asm-offsets.c @@ -31,7 +31,7 @@ int main(void) DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp)); DEFINE(THREAD_USP, offsetof(struct thread_struct, usp)); DEFINE(THREAD_SR, offsetof(struct thread_struct, sr)); - DEFINE(THREAD_FS, offsetof(struct thread_struct, fs)); + DEFINE(THREAD_FC, offsetof(struct thread_struct, fc)); DEFINE(THREAD_CRP, offsetof(struct thread_struct, crp)); DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0)); DEFINE(THREAD_FPREG, offsetof(struct thread_struct, fp)); diff --git a/arch/m68k/kernel/bootinfo_proc.c b/arch/m68k/kernel/bootinfo_proc.c index 3b9cab84917d..857fa2aaa748 100644 --- a/arch/m68k/kernel/bootinfo_proc.c +++ b/arch/m68k/kernel/bootinfo_proc.c @@ -26,9 +26,9 @@ static ssize_t bootinfo_read(struct file *file, char __user *buf, bootinfo_size); } -static const struct file_operations bootinfo_fops = { - .read = bootinfo_read, - .llseek = default_llseek, +static const struct proc_ops bootinfo_proc_ops = { + .proc_read = bootinfo_read, + .proc_lseek = default_llseek, }; void __init save_bootinfo(const struct bi_record *bi) @@ -67,7 +67,7 @@ static int __init init_bootinfo_procfs(void) if (!bootinfo_copy) return -ENOMEM; - pde = proc_create_data("bootinfo", 0400, NULL, &bootinfo_fops, NULL); + pde = proc_create_data("bootinfo", 0400, NULL, &bootinfo_proc_ops, NULL); if (!pde) { kfree(bootinfo_copy); return -ENOMEM; diff --git a/arch/m68k/kernel/dma.c b/arch/m68k/kernel/dma.c index 871a0e11da34..16063783aa80 100644 --- a/arch/m68k/kernel/dma.c +++ b/arch/m68k/kernel/dma.c @@ -4,20 +4,11 @@ * for more details. */ -#undef DEBUG - -#include <linux/dma-noncoherent.h> -#include <linux/device.h> +#include <linux/dma-map-ops.h> #include <linux/kernel.h> -#include <linux/platform_device.h> -#include <linux/scatterlist.h> -#include <linux/slab.h> -#include <linux/vmalloc.h> -#include <linux/export.h> - -#include <asm/pgalloc.h> +#include <asm/cacheflush.h> -#if defined(CONFIG_MMU) && !defined(CONFIG_COLDFIRE) +#ifndef CONFIG_COLDFIRE void arch_dma_prep_coherent(struct page *page, size_t size) { cache_push(page_to_phys(page), size); @@ -33,32 +24,6 @@ pgprot_t pgprot_dmacoherent(pgprot_t prot) } return prot; } -#else - -#include <asm/cacheflush.h> - -void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, - gfp_t gfp, unsigned long attrs) -{ - void *ret; - - if (dev == NULL || (*dev->dma_mask < 0xffffffff)) - gfp |= GFP_DMA; - ret = (void *)__get_free_pages(gfp, get_order(size)); - - if (ret != NULL) { - memset(ret, 0, size); - *dma_handle = virt_to_phys(ret); - } - return ret; -} - -void arch_dma_free(struct device *dev, size_t size, void *vaddr, - dma_addr_t dma_handle, unsigned long attrs) -{ - free_pages((unsigned long)vaddr, get_order(size)); -} - #endif /* CONFIG_MMU && !CONFIG_COLDFIRE */ void arch_sync_dma_for_device(phys_addr_t handle, size_t size, diff --git a/arch/m68k/kernel/early_printk.c b/arch/m68k/kernel/early_printk.c index 7d3fe08a48eb..3cc944df04f6 100644 --- a/arch/m68k/kernel/early_printk.c +++ b/arch/m68k/kernel/early_printk.c @@ -12,8 +12,8 @@ #include <linux/string.h> #include <asm/setup.h> -extern void mvme16x_cons_write(struct console *co, - const char *str, unsigned count); + +#include "../mvme16x/mvme16x.h" asmlinkage void __init debug_cons_nputs(const char *s, unsigned n); diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S index 97cd3ea5f10b..3bcdd32a6b36 100644 --- a/arch/m68k/kernel/entry.S +++ b/arch/m68k/kernel/entry.S @@ -1,13 +1,10 @@ -/* -*- mode: asm -*- +/* SPDX-License-Identifier: GPL-2.0-or-later + * -*- mode: asm -*- * * linux/arch/m68k/kernel/entry.S * * Copyright (C) 1991, 1992 Linus Torvalds * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file README.legal in the main directory of this archive - * for more details. - * * Linux/m68k support by Hamish Macdonald * * 68060 fixes by Jesper Skov @@ -36,7 +33,6 @@ #include <linux/linkage.h> #include <asm/errno.h> #include <asm/setup.h> -#include <asm/segment.h> #include <asm/traps.h> #include <asm/unistd.h> #include <asm/asm-offsets.h> @@ -69,22 +65,47 @@ ENTRY(__sys_vfork) lea %sp@(24),%sp rts +ENTRY(__sys_clone3) + SAVE_SWITCH_STACK + pea %sp@(SWITCH_STACK_SIZE) + jbsr m68k_clone3 + lea %sp@(28),%sp + rts + ENTRY(sys_sigreturn) SAVE_SWITCH_STACK - movel %sp,%sp@- | switch_stack pointer - pea %sp@(SWITCH_STACK_SIZE+4) | pt_regs pointer + movel %sp,%a1 | switch_stack pointer + lea %sp@(SWITCH_STACK_SIZE),%a0 | pt_regs pointer + lea %sp@(-84),%sp | leave a gap + movel %a1,%sp@- + movel %a0,%sp@- jbsr do_sigreturn - addql #8,%sp - RESTORE_SWITCH_STACK - rts + jra 1f | shared with rt_sigreturn() ENTRY(sys_rt_sigreturn) SAVE_SWITCH_STACK - movel %sp,%sp@- | switch_stack pointer - pea %sp@(SWITCH_STACK_SIZE+4) | pt_regs pointer + movel %sp,%a1 | switch_stack pointer + lea %sp@(SWITCH_STACK_SIZE),%a0 | pt_regs pointer + lea %sp@(-84),%sp | leave a gap + movel %a1,%sp@- + movel %a0,%sp@- + | stack contents: + | [original pt_regs address] [original switch_stack address] + | [gap] [switch_stack] [pt_regs] [exception frame] jbsr do_rt_sigreturn - addql #8,%sp + +1: + | stack contents now: + | [original pt_regs address] [original switch_stack address] + | [unused part of the gap] [moved switch_stack] [moved pt_regs] + | [replacement exception frame] + | return value of do_{rt_,}sigreturn() points to moved switch_stack. + + movel %d0,%sp | discard the leftover junk RESTORE_SWITCH_STACK + | stack contents now is just [syscall return address] [pt_regs] [frame] + | return pt_regs.d0 + movel %sp@(PT_OFF_D0+4),%d0 rts ENTRY(buserr) @@ -157,12 +178,15 @@ do_trace_entry: movel #-ENOSYS,%sp@(PT_OFF_D0)| needed for strace subql #4,%sp SAVE_SWITCH_STACK - jbsr syscall_trace + jbsr syscall_trace_enter RESTORE_SWITCH_STACK addql #4,%sp + addql #1,%d0 | optimization for cmpil #-1,%d0 + jeq ret_from_syscall movel %sp@(PT_OFF_ORIG_D0),%d0 cmpl #NR_syscalls,%d0 jcs syscall + jra ret_from_syscall badsys: movel #-ENOSYS,%sp@(PT_OFF_D0) jra ret_from_syscall @@ -170,30 +194,11 @@ badsys: do_trace_exit: subql #4,%sp SAVE_SWITCH_STACK - jbsr syscall_trace + jbsr syscall_trace_leave RESTORE_SWITCH_STACK addql #4,%sp jra .Lret_from_exception -ENTRY(ret_from_signal) - movel %curptr@(TASK_STACK),%a1 - tstb %a1@(TINFO_FLAGS+2) - jge 1f - jbsr syscall_trace -1: RESTORE_SWITCH_STACK - addql #4,%sp -/* on 68040 complete pending writebacks if any */ -#ifdef CONFIG_M68040 - bfextu %sp@(PT_OFF_FORMATVEC){#0,#4},%d0 - subql #7,%d0 | bus error frame ? - jbne 1f - movel %sp,%sp@- - jbsr berr_040cleanup - addql #4,%sp -1: -#endif - jra .Lret_from_exception - ENTRY(system_call) SAVE_ALL_SYS @@ -206,6 +211,9 @@ ENTRY(system_call) | syscall trace? tstb %a1@(TINFO_FLAGS+2) jmi do_trace_entry + | seccomp filter active? + btst #5,%a1@(TINFO_FLAGS+2) + bnes do_trace_entry cmpl #NR_syscalls,%d0 jcc badsys syscall: @@ -331,7 +339,7 @@ resume: /* save fs (sfc,%dfc) (may be pointing to kernel memory) */ movec %sfc,%d0 - movew %d0,%a0@(TASK_THREAD+THREAD_FS) + movew %d0,%a0@(TASK_THREAD+THREAD_FC) /* save usp */ /* it is better to use a movel here instead of a movew 8*) */ @@ -417,7 +425,7 @@ resume: movel %a0,%usp /* restore fs (sfc,%dfc) */ - movew %a1@(TASK_THREAD+THREAD_FS),%a0 + movew %a1@(TASK_THREAD+THREAD_FC),%a0 movec %a0,%sfc movec %a0,%dfc diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S index a54788458ca3..852255cf60de 100644 --- a/arch/m68k/kernel/head.S +++ b/arch/m68k/kernel/head.S @@ -1,4 +1,5 @@ -/* -*- mode: asm -*- +/* SPDX-License-Identifier: GPL-2.0-or-later +** -*- mode: asm -*- ** ** head.S -- This file contains the initial boot code for the ** Linux/68k kernel. @@ -25,11 +26,6 @@ ** for linux-2.1.115 ** 1999/02/11 Richard Zidlicky: added Q40 support (initial version 99/01/01) ** 2004/05/13 Kars de Jong: Finalised HP300 support -** -** This file is subject to the terms and conditions of the GNU General Public -** License. See the file README.legal in the main directory of this archive -** for more details. -** */ /* @@ -57,7 +53,7 @@ * Of course, readability is a subjective issue, so it will never be * argued that that goal was accomplished. It was merely a goal. * A key way to help make code more readable is to give good - * documentation. So, the first thing you will find is exaustive + * documentation. So, the first thing you will find is exhaustive * write-ups on the structure of the file, and the features of the * functional subroutines. * @@ -255,16 +251,17 @@ #include <linux/linkage.h> #include <linux/init.h> +#include <linux/pgtable.h> #include <asm/bootinfo.h> #include <asm/bootinfo-amiga.h> #include <asm/bootinfo-atari.h> #include <asm/bootinfo-hp300.h> #include <asm/bootinfo-mac.h> #include <asm/bootinfo-q40.h> +#include <asm/bootinfo-virt.h> #include <asm/bootinfo-vme.h> #include <asm/setup.h> #include <asm/entry.h> -#include <asm/pgtable.h> #include <asm/page.h> #include <asm/asm-offsets.h> #ifdef CONFIG_MAC @@ -534,6 +531,7 @@ func_define putn,1 #define is_not_apollo(lab) cmpl &MACH_APOLLO,%pc@(m68k_machtype); jne lab #define is_not_q40(lab) cmpl &MACH_Q40,%pc@(m68k_machtype); jne lab #define is_not_sun3x(lab) cmpl &MACH_SUN3X,%pc@(m68k_machtype); jne lab +#define is_not_virt(lab) cmpl &MACH_VIRT,%pc@(m68k_machtype); jne lab #define hasnt_leds(lab) cmpl &MACH_HP300,%pc@(m68k_machtype); \ jeq 42f; \ @@ -647,6 +645,14 @@ ENTRY(__start) L(test_notmac): #endif /* CONFIG_MAC */ +#ifdef CONFIG_VIRT + is_not_virt(L(test_notvirt)) + + get_bi_record BI_VIRT_GF_TTY_BASE + lea %pc@(L(virt_gf_tty_base)),%a1 + movel %a0@,%a1@ +L(test_notvirt): +#endif /* CONFIG_VIRT */ /* * There are ultimately two pieces of information we want for all kinds of @@ -1237,6 +1243,13 @@ L(mmu_init_not_mac): L(notsun3x): #endif +#ifdef CONFIG_VIRT + is_not_virt(L(novirt)) + mmu_map_tt #1,#0xFF000000,#0x01000000,#_PAGE_NOCACHE_S + jbra L(mmu_init_done) +L(novirt): +#endif + #ifdef CONFIG_APOLLO is_not_apollo(L(notapollo)) @@ -1304,7 +1317,7 @@ L(mmu_fixup_done): * mmu_engage * * This chunk of code performs the gruesome task of engaging the MMU. - * The reason its gruesome is because when the MMU becomes engaged it + * The reason it's gruesome is because when the MMU becomes engaged it * maps logical addresses to physical addresses. The Program Counter * register is then passed through the MMU before the next instruction * is fetched (the instruction following the engage MMU instruction). @@ -1369,7 +1382,7 @@ L(mmu_fixup_done): /* * After this point no new memory is allocated and * the start of available memory is stored in availmem. - * (The bootmem allocator requires now the physicall address.) + * (The bootmem allocator requires now the physical address.) */ movel L(memory_start),availmem @@ -1547,7 +1560,7 @@ func_return get_bi_record * seven bits of the logical address (LA) are used as an * index into the "root table." Each entry in the root * table has a bit which specifies if it's a valid pointer to a - * pointer table. Each entry defines a 32KMeg range of memory. + * pointer table. Each entry defines a 32Meg range of memory. * If an entry is invalid then that logical range of 32M is * invalid and references to that range of memory (when the MMU * is enabled) will fault. If the entry is valid, then it does @@ -1584,7 +1597,7 @@ func_return get_bi_record * bits 17..12 - index into the Page Table * bits 11..0 - offset into a particular 4K page * - * The algorithms which follows do one thing: they abstract + * The algorithms which follow do one thing: they abstract * the MMU hardware. For example, there are three kinds of * cache settings that are relevant. Either, memory is * being mapped in which case it is either Kernel Code (or @@ -2082,7 +2095,7 @@ func_return mmu_map_tt * mmu_map * * This routine will map a range of memory using a pointer - * table and allocating the pages on the fly from the kernel. + * table and allocate the pages on the fly from the kernel. * The pointer table does not have to be already linked into * the root table, this routine will do that if necessary. * @@ -2528,7 +2541,7 @@ func_start mmu_get_root_table_entry,%d0/%a1 /* Find the start of free memory, get_bi_record does this for us, * as the bootinfo structure is located directly behind the kernel - * and and we simply search for the last entry. + * we simply search for the last entry. */ get_bi_record BI_LAST addw #PAGESIZE-1,%a0 @@ -2654,7 +2667,7 @@ func_start mmu_get_page_table_entry,%d0/%a1 jne 2f /* If the page table entry doesn't exist, we allocate a complete new - * page and use it as one continues big page table which can cover + * page and use it as one continuous big page table which can cover * 4MB of memory, nearly almost all mappings have that alignment. */ get_new_page @@ -3186,6 +3199,14 @@ func_start serial_putc,%d0/%d1/%a0/%a1 3: #endif +#ifdef CONFIG_VIRT + is_not_virt(1f) + + movel L(virt_gf_tty_base),%a1 + movel %d0,%a1@(GF_PUT_CHAR) +1: +#endif + L(serial_putc_done): func_return serial_putc @@ -3865,3 +3886,9 @@ q40_mem_cptr: L(q40_do_debug): .long 0 #endif + +#if defined(CONFIG_VIRT) +GF_PUT_CHAR = 0x00 +L(virt_gf_tty_base): + .long 0 +#endif /* CONFIG_VIRT */ diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c index 5b8d66fbf383..cf2b13488476 100644 --- a/arch/m68k/kernel/ints.c +++ b/arch/m68k/kernel/ints.c @@ -26,6 +26,8 @@ #include <asm/q40ints.h> #endif +#include "ints.h" + extern u32 auto_irqhandler_fixup[]; extern u16 user_irqvec_fixup[]; diff --git a/arch/m68k/kernel/ints.h b/arch/m68k/kernel/ints.h new file mode 100644 index 000000000000..ecac6011c1a4 --- /dev/null +++ b/arch/m68k/kernel/ints.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <linux/linkage.h> + +struct pt_regs; + +asmlinkage void handle_badint(struct pt_regs *regs); diff --git a/arch/m68k/kernel/machine_kexec.c b/arch/m68k/kernel/machine_kexec.c index 206f84983120..739875540e89 100644 --- a/arch/m68k/kernel/machine_kexec.c +++ b/arch/m68k/kernel/machine_kexec.c @@ -6,6 +6,7 @@ #include <linux/kexec.h> #include <linux/mm.h> #include <linux/delay.h> +#include <linux/reboot.h> #include <asm/cacheflush.h> #include <asm/page.h> diff --git a/arch/m68k/kernel/module.lds b/arch/m68k/kernel/module.lds deleted file mode 100644 index fda94fa38243..000000000000 --- a/arch/m68k/kernel/module.lds +++ /dev/null @@ -1,7 +0,0 @@ -SECTIONS { - .m68k_fixup : { - __start_fixup = .; - *(.m68k_fixup) - __stop_fixup = .; - } -} diff --git a/arch/m68k/kernel/pcibios.c b/arch/m68k/kernel/pcibios.c index b0e110d3d2e6..9504eb19d73a 100644 --- a/arch/m68k/kernel/pcibios.c +++ b/arch/m68k/kernel/pcibios.c @@ -92,9 +92,3 @@ void pcibios_fixup_bus(struct pci_bus *bus) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 32); } } - -char *pcibios_setup(char *str) -{ - return str; -} - diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index 4e77a06735c1..2584e94e2134 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c @@ -30,13 +30,15 @@ #include <linux/init_task.h> #include <linux/mqueue.h> #include <linux/rcupdate.h> - +#include <linux/syscalls.h> #include <linux/uaccess.h> +#include <linux/elfcore.h> + #include <asm/traps.h> #include <asm/machdep.h> #include <asm/setup.h> -#include <asm/pgtable.h> +#include "process.h" asmlinkage void ret_from_fork(void); asmlinkage void ret_from_kernel_thread(void); @@ -67,12 +69,11 @@ void machine_halt(void) void machine_power_off(void) { - if (mach_power_off) - mach_power_off(); + do_kernel_power_off(); for (;;); } -void (*pm_power_off)(void) = machine_power_off; +void (*pm_power_off)(void); EXPORT_SYMBOL(pm_power_off); void show_regs(struct pt_regs * regs) @@ -92,7 +93,7 @@ void show_regs(struct pt_regs * regs) void flush_thread(void) { - current->thread.fs = __USER_DS; + current->thread.fc = USER_DATA; #ifdef CONFIG_FPU if (!FPU_IS_EMU) { unsigned long zero = 0; @@ -107,21 +108,42 @@ void flush_thread(void) * on top of pt_regs, which means that sys_clone() arguments would be * buried. We could, of course, copy them, but it's too costly for no * good reason - generic clone() would have to copy them *again* for - * do_fork() anyway. So in this case it's actually better to pass pt_regs * - * and extract arguments for do_fork() from there. Eventually we might - * go for calling do_fork() directly from the wrapper, but only after we - * are finished with do_fork() prototype conversion. + * kernel_clone() anyway. So in this case it's actually better to pass pt_regs * + * and extract arguments for kernel_clone() from there. Eventually we might + * go for calling kernel_clone() directly from the wrapper, but only after we + * are finished with kernel_clone() prototype conversion. */ asmlinkage int m68k_clone(struct pt_regs *regs) { /* regs will be equal to current_pt_regs() */ - return do_fork(regs->d1, regs->d2, 0, - (int __user *)regs->d3, (int __user *)regs->d4); + struct kernel_clone_args args = { + .flags = regs->d1 & ~CSIGNAL, + .pidfd = (int __user *)regs->d3, + .child_tid = (int __user *)regs->d4, + .parent_tid = (int __user *)regs->d3, + .exit_signal = regs->d1 & CSIGNAL, + .stack = regs->d2, + .tls = regs->d5, + }; + + return kernel_clone(&args); } -int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long arg, struct task_struct *p) +/* + * Because extra registers are saved on the stack after the sys_clone3() + * arguments, this C wrapper extracts them from pt_regs * and then calls the + * generic sys_clone3() implementation. + */ +asmlinkage int m68k_clone3(struct pt_regs *regs) { + return sys_clone3((struct clone_args __user *)regs->d1, regs->d2); +} + +int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) +{ + unsigned long clone_flags = args->flags; + unsigned long usp = args->stack; + unsigned long tls = args->tls; struct fork_frame { struct switch_stack sw; struct pt_regs regs; @@ -136,14 +158,14 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, * Must save the current SFC/DFC value, NOT the value when * the parent was last descheduled - RGH 10-08-96 */ - p->thread.fs = get_fs().seg; + p->thread.fc = USER_DATA; - if (unlikely(p->flags & PF_KTHREAD)) { + if (unlikely(args->fn)) { /* kernel thread */ memset(frame, 0, sizeof(struct fork_frame)); frame->regs.sr = PS_S; - frame->sw.a3 = usp; /* function */ - frame->sw.d7 = arg; + frame->sw.a3 = (unsigned long)args->fn; + frame->sw.d7 = (unsigned long)args->fn_arg; frame->sw.retpc = (unsigned long)ret_from_kernel_thread; p->thread.usp = 0; return 0; @@ -155,7 +177,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, p->thread.usp = usp ?: rdusp(); if (clone_flags & CLONE_SETTLS) - task_thread_info(p)->tp_value = frame->regs.d5; + task_thread_info(p)->tp_value = tls; #ifdef CONFIG_FPU if (!FPU_IS_EMU) { @@ -193,7 +215,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, } /* Fill in the fpu structure for a core dump. */ -int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu) +int elf_core_copy_task_fpregs(struct task_struct *t, elf_fpregset_t *fpu) { if (FPU_IS_EMU) { int i; @@ -242,15 +264,12 @@ int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu) return 1; } -EXPORT_SYMBOL(dump_fpu); -unsigned long get_wchan(struct task_struct *p) +unsigned long __get_wchan(struct task_struct *p) { unsigned long fp, pc; unsigned long stack_page; int count = 0; - if (!p || p == current || p->state == TASK_RUNNING) - return 0; stack_page = (unsigned long)task_stack_page(p); fp = ((struct switch_stack *)p->thread.ksp)->a6; diff --git a/arch/m68k/kernel/process.h b/arch/m68k/kernel/process.h new file mode 100644 index 000000000000..d31745f2e64b --- /dev/null +++ b/arch/m68k/kernel/process.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#include <linux/linkage.h> + +struct pt_regs; + +asmlinkage int m68k_clone(struct pt_regs *regs); +asmlinkage int m68k_clone3(struct pt_regs *regs); diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c index 748c63bd0081..c20d590e4297 100644 --- a/arch/m68k/kernel/ptrace.c +++ b/arch/m68k/kernel/ptrace.c @@ -19,13 +19,15 @@ #include <linux/ptrace.h> #include <linux/user.h> #include <linux/signal.h> -#include <linux/tracehook.h> - +#include <linux/regset.h> +#include <linux/elf.h> +#include <linux/seccomp.h> #include <linux/uaccess.h> #include <asm/page.h> -#include <asm/pgtable.h> #include <asm/processor.h> +#include "ptrace.h" + /* * does not yet catch signals sent when the child dies. * in exit.c or in signal.c. @@ -272,34 +274,77 @@ out_eio: return -EIO; } -asmlinkage void syscall_trace(void) -{ - ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0)); - /* - * this isn't the same as continuing with a signal, but it will do - * for normal use. strace only continues with a signal if the - * stopping signal is not SIGTRAP. -brl - */ - if (current->exit_code) { - send_sig(current->exit_code, current, 1); - current->exit_code = 0; - } -} - -#if defined(CONFIG_COLDFIRE) || !defined(CONFIG_MMU) asmlinkage int syscall_trace_enter(void) { int ret = 0; if (test_thread_flag(TIF_SYSCALL_TRACE)) - ret = tracehook_report_syscall_entry(task_pt_regs(current)); + ret = ptrace_report_syscall_entry(task_pt_regs(current)); + + if (secure_computing() == -1) + return -1; + return ret; } asmlinkage void syscall_trace_leave(void) { if (test_thread_flag(TIF_SYSCALL_TRACE)) - tracehook_report_syscall_exit(task_pt_regs(current), 0); + ptrace_report_syscall_exit(task_pt_regs(current), 0); +} + +#if defined(CONFIG_BINFMT_ELF_FDPIC) && defined(CONFIG_ELF_CORE) +/* + * Currently the only thing that needs to use regsets for m68k is the + * coredump support of the elf_fdpic loader. Implement the minimum + * definitions required for that. + */ +static int m68k_regset_get(struct task_struct *target, + const struct user_regset *regset, + struct membuf to) +{ + struct pt_regs *ptregs = task_pt_regs(target); + u32 uregs[ELF_NGREG]; + + ELF_CORE_COPY_REGS(uregs, ptregs); + return membuf_write(&to, uregs, sizeof(uregs)); +} + +enum m68k_regset { + REGSET_GPR, +#ifdef CONFIG_FPU + REGSET_FPU, +#endif +}; + +static const struct user_regset m68k_user_regsets[] = { + [REGSET_GPR] = { + .core_note_type = NT_PRSTATUS, + .n = ELF_NGREG, + .size = sizeof(u32), + .align = sizeof(u16), + .regset_get = m68k_regset_get, + }, +#ifdef CONFIG_FPU + [REGSET_FPU] = { + .core_note_type = NT_PRFPREG, + .n = sizeof(struct user_m68kfp_struct) / sizeof(u32), + .size = sizeof(u32), + .align = sizeof(u32), + } +#endif /* CONFIG_FPU */ +}; + +static const struct user_regset_view user_m68k_view = { + .name = "m68k", + .e_machine = EM_68K, + .ei_osabi = ELF_OSABI, + .regsets = m68k_user_regsets, + .n = ARRAY_SIZE(m68k_user_regsets) +}; + +const struct user_regset_view *task_user_regset_view(struct task_struct *task) +{ + return &user_m68k_view; } -#endif /* CONFIG_COLDFIRE */ +#endif /* CONFIG_BINFMT_ELF_FDPIC && CONFIG_ELF_CORE */ diff --git a/arch/m68k/kernel/ptrace.h b/arch/m68k/kernel/ptrace.h new file mode 100644 index 000000000000..77018037f10f --- /dev/null +++ b/arch/m68k/kernel/ptrace.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <linux/linkage.h> + +asmlinkage int syscall_trace_enter(void); +asmlinkage void syscall_trace_leave(void); diff --git a/arch/m68k/kernel/relocate_kernel.S b/arch/m68k/kernel/relocate_kernel.S index ab0f1e7d4653..f7667079e08e 100644 --- a/arch/m68k/kernel/relocate_kernel.S +++ b/arch/m68k/kernel/relocate_kernel.S @@ -26,7 +26,7 @@ ENTRY(relocate_new_kernel) lea %pc@(.Lcopy),%a4 2: addl #0x00000000,%a4 /* virt_to_phys() */ - .section ".m68k_fixup","aw" + .section .m68k_fixup,"aw" .long M68K_FIXUP_MEMOFFSET, 2b+2 .previous @@ -49,7 +49,7 @@ ENTRY(relocate_new_kernel) lea %pc@(.Lcont040),%a4 5: addl #0x00000000,%a4 /* virt_to_phys() */ - .section ".m68k_fixup","aw" + .section .m68k_fixup,"aw" .long M68K_FIXUP_MEMOFFSET, 5b+2 .previous diff --git a/arch/m68k/kernel/setup_mm.c b/arch/m68k/kernel/setup_mm.c index 528484feff80..10310b04f77d 100644 --- a/arch/m68k/kernel/setup_mm.c +++ b/arch/m68k/kernel/setup_mm.c @@ -10,13 +10,13 @@ */ #include <linux/kernel.h> +#include <linux/cpu.h> #include <linux/mm.h> #include <linux/sched.h> #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/fs.h> #include <linux/console.h> -#include <linux/genhd.h> #include <linux/errno.h> #include <linux/string.h> #include <linux/init.h> @@ -26,6 +26,7 @@ #include <linux/module.h> #include <linux/nvram.h> #include <linux/initrd.h> +#include <linux/random.h> #include <asm/bootinfo.h> #include <asm/byteorder.h> @@ -47,6 +48,7 @@ #endif #include <asm/macintosh.h> #include <asm/natfeat.h> +#include <asm/config.h> #if !FPSTATESIZE || !NR_IRQS #warning No CPU/platform type selected, your kernel will not work! @@ -82,24 +84,13 @@ static struct m68k_mem_info m68k_ramdisk __initdata; static char m68k_command_line[CL_SIZE] __initdata; -void (*mach_sched_init) (irq_handler_t handler) __initdata = NULL; +void (*mach_sched_init) (void) __initdata = NULL; /* machine dependent irq functions */ void (*mach_init_IRQ) (void) __initdata = NULL; void (*mach_get_model) (char *model); void (*mach_get_hardware_list) (struct seq_file *m); -/* machine dependent timer functions */ -int (*mach_hwclk) (int, struct rtc_time*); -EXPORT_SYMBOL(mach_hwclk); -unsigned int (*mach_get_ss)(void); -int (*mach_get_rtc_pll)(struct rtc_pll_info *); -int (*mach_set_rtc_pll)(struct rtc_pll_info *); -EXPORT_SYMBOL(mach_get_ss); -EXPORT_SYMBOL(mach_get_rtc_pll); -EXPORT_SYMBOL(mach_set_rtc_pll); void (*mach_reset)( void ); void (*mach_halt)( void ); -void (*mach_power_off)( void ); -long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */ #ifdef CONFIG_HEARTBEAT void (*mach_heartbeat) (int); EXPORT_SYMBOL(mach_heartbeat); @@ -114,38 +105,13 @@ EXPORT_SYMBOL(isa_type); EXPORT_SYMBOL(isa_sex); #endif -extern int amiga_parse_bootinfo(const struct bi_record *); -extern int atari_parse_bootinfo(const struct bi_record *); -extern int mac_parse_bootinfo(const struct bi_record *); -extern int q40_parse_bootinfo(const struct bi_record *); -extern int bvme6000_parse_bootinfo(const struct bi_record *); -extern int mvme16x_parse_bootinfo(const struct bi_record *); -extern int mvme147_parse_bootinfo(const struct bi_record *); -extern int hp300_parse_bootinfo(const struct bi_record *); -extern int apollo_parse_bootinfo(const struct bi_record *); - -extern void config_amiga(void); -extern void config_atari(void); -extern void config_mac(void); -extern void config_sun3(void); -extern void config_apollo(void); -extern void config_mvme147(void); -extern void config_mvme16x(void); -extern void config_bvme6000(void); -extern void config_hp300(void); -extern void config_q40(void); -extern void config_sun3x(void); - #define MASK_256K 0xfffc0000 -extern void paging_init(void); - static void __init m68k_parse_bootinfo(const struct bi_record *record) { + const struct bi_record *first_record = record; uint16_t tag; - save_bootinfo(record); - while ((tag = be16_to_cpu(record->tag)) != BI_LAST) { int unknown = 0; const void *data = record->data; @@ -181,10 +147,21 @@ static void __init m68k_parse_bootinfo(const struct bi_record *record) break; case BI_COMMAND_LINE: - strlcpy(m68k_command_line, data, + strscpy(m68k_command_line, data, sizeof(m68k_command_line)); break; + case BI_RNG_SEED: { + u16 len = be16_to_cpup(data); + add_bootloader_randomness(data + 2, len); + /* + * Zero the data to preserve forward secrecy, and zero the + * length to prevent kexec from using it. + */ + memzero_explicit((void *)data, len + 2); + break; + } + default: if (MACH_IS_AMIGA) unknown = amiga_parse_bootinfo(record); @@ -204,6 +181,8 @@ static void __init m68k_parse_bootinfo(const struct bi_record *record) unknown = hp300_parse_bootinfo(record); else if (MACH_IS_APOLLO) unknown = apollo_parse_bootinfo(record); + else if (MACH_IS_VIRT) + unknown = virt_parse_bootinfo(record); else unknown = 1; } @@ -213,6 +192,8 @@ static void __init m68k_parse_bootinfo(const struct bi_record *record) record = (struct bi_record *)((unsigned long)record + size); } + save_bootinfo(first_record); + m68k_realnum_memory = m68k_num_memory; #ifdef CONFIG_SINGLE_MEMORY_CHUNK if (m68k_num_memory > 1) { @@ -259,10 +240,7 @@ void __init setup_arch(char **cmdline_p) } } - init_mm.start_code = PAGE_OFFSET; - init_mm.end_code = (unsigned long)_etext; - init_mm.end_data = (unsigned long)_edata; - init_mm.brk = (unsigned long)_end; + setup_initial_init_mm((void *)PAGE_OFFSET, _etext, _edata, _end); #if defined(CONFIG_BOOTPARAM) strncpy(m68k_command_line, CONFIG_BOOTPARAM_STRING, CL_SIZE); @@ -274,10 +252,6 @@ void __init setup_arch(char **cmdline_p) parse_early_param(); -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif - switch (m68k_machtype) { #ifdef CONFIG_AMIGA case MACH_AMIGA: @@ -342,24 +316,28 @@ void __init setup_arch(char **cmdline_p) config_BSP(NULL, 0); break; #endif +#ifdef CONFIG_VIRT + case MACH_VIRT: + config_virt(); + break; +#endif default: panic("No configuration setup"); } - paging_init(); + if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && m68k_ramdisk.size) + memblock_reserve(m68k_ramdisk.addr, m68k_ramdisk.size); -#ifdef CONFIG_NATFEAT - nf_init(); -#endif + paging_init(); -#ifndef CONFIG_SUN3 -#ifdef CONFIG_BLK_DEV_INITRD - if (m68k_ramdisk.size) { - memblock_reserve(m68k_ramdisk.addr, m68k_ramdisk.size); + if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && m68k_ramdisk.size) { initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr); initrd_end = initrd_start + m68k_ramdisk.size; pr_info("initrd: %08lx - %08lx\n", initrd_start, initrd_end); } + +#ifdef CONFIG_NATFEAT + nf_init(); #endif #ifdef CONFIG_ATARI @@ -372,8 +350,6 @@ void __init setup_arch(char **cmdline_p) } #endif -#endif /* !CONFIG_SUN3 */ - /* set ISA defs early as possible */ #if defined(CONFIG_ISA) && defined(MULTI_ISA) if (MACH_IS_Q40) { @@ -527,7 +503,7 @@ static int __init proc_hardware_init(void) module_init(proc_hardware_init); #endif -void check_bugs(void) +void __init arch_cpu_finalize_init(void) { #if defined(CONFIG_FPU) && !defined(CONFIG_M68KFPU_EMU) if (m68k_fputype == 0) { diff --git a/arch/m68k/kernel/setup_no.c b/arch/m68k/kernel/setup_no.c index 3c5def10d486..37fb663559b4 100644 --- a/arch/m68k/kernel/setup_no.c +++ b/arch/m68k/kernel/setup_no.c @@ -38,7 +38,6 @@ #include <asm/bootinfo.h> #include <asm/irq.h> #include <asm/machdep.h> -#include <asm/pgtable.h> #include <asm/sections.h> unsigned long memory_start; @@ -50,13 +49,11 @@ EXPORT_SYMBOL(memory_end); char __initdata command_line[COMMAND_LINE_SIZE]; /* machine dependent timer functions */ -void (*mach_sched_init)(irq_handler_t handler) __initdata = NULL; -int (*mach_hwclk) (int, struct rtc_time*); +void (*mach_sched_init)(void) __initdata = NULL; /* machine dependent reboot functions */ void (*mach_reset)(void); void (*mach_halt)(void); -void (*mach_power_off)(void); #ifdef CONFIG_M68000 #if defined(CONFIG_M68328) @@ -88,16 +85,12 @@ void __init setup_arch(char **cmdline_p) memory_start = PAGE_ALIGN(_ramstart); memory_end = _ramend; - init_mm.start_code = (unsigned long) &_stext; - init_mm.end_code = (unsigned long) &_etext; - init_mm.end_data = (unsigned long) &_edata; - init_mm.brk = (unsigned long) 0; + setup_initial_init_mm(_stext, _etext, _edata, NULL); config_BSP(&command_line[0], sizeof(command_line)); #if defined(CONFIG_BOOTPARAM) - strncpy(&command_line[0], CONFIG_BOOTPARAM_STRING, sizeof(command_line)); - command_line[sizeof(command_line) - 1] = 0; + strscpy(&command_line[0], CONFIG_BOOTPARAM_STRING, sizeof(command_line)); #endif /* CONFIG_BOOTPARAM */ process_uboot_commandline(&command_line[0], sizeof(command_line)); @@ -107,8 +100,16 @@ void __init setup_arch(char **cmdline_p) #ifdef CONFIG_UCDIMM pr_info("uCdimm by Lineo, Inc. <www.lineo.com>\n"); #endif +#ifdef CONFIG_M68328 + pr_info("68328 support D. Jeff Dionne <jeff@uclinux.org>\n"); + pr_info("68328 support Kenneth Albanowski <kjahds@kjshds.com>\n"); +#endif +#ifdef CONFIG_M68EZ328 + pr_info("68EZ328 DragonBallEZ support (C) 1999 Rt-Control, Inc\n"); +#endif #ifdef CONFIG_M68VZ328 pr_info("M68VZ328 support by Evan Stawnyczy <e@lineo.ca>\n"); + pr_info("68VZ328 DragonBallVZ support (c) 2001 Lineo, Inc.\n"); #endif #ifdef CONFIG_COLDFIRE pr_info("COLDFIRE port done by Greg Ungerer, gerg@snapgear.com\n"); @@ -122,6 +123,7 @@ void __init setup_arch(char **cmdline_p) pr_info("Flat model support (C) 1998,1999 Kenneth Albanowski, D. Jeff Dionne\n"); #if defined( CONFIG_PILOT ) && defined( CONFIG_M68328 ) + pr_info("68328/Pilot support Bernhard Kuhn <kuhn@lpr.e-technik.tu-muenchen.de>\n"); pr_info("TRG SuperPilot FLASH card support <info@trgnet.com>\n"); #endif #if defined( CONFIG_PILOT ) && defined( CONFIG_M68EZ328 ) @@ -139,17 +141,14 @@ void __init setup_arch(char **cmdline_p) pr_debug("MEMORY -> ROMFS=0x%p-0x%06lx MEM=0x%06lx-0x%06lx\n ", __bss_stop, memory_start, memory_start, memory_end); - memblock_add(memory_start, memory_end - memory_start); + memblock_add(_rambase, memory_end - _rambase); + memblock_reserve(_rambase, memory_start - _rambase); /* Keep a copy of command line */ *cmdline_p = &command_line[0]; memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); boot_command_line[COMMAND_LINE_SIZE-1] = 0; -#if defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_DUMMY_CONSOLE) - conswitchp = &dummy_con; -#endif - /* * Give all the memory to the bootmap allocator, tell it to put the * boot mem_map at the start of memory. diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c index 05610e6924c1..e628b859ef21 100644 --- a/arch/m68k/kernel/signal.c +++ b/arch/m68k/kernel/signal.c @@ -43,15 +43,16 @@ #include <linux/tty.h> #include <linux/binfmts.h> #include <linux/extable.h> -#include <linux/tracehook.h> +#include <linux/resume_user_mode.h> #include <asm/setup.h> #include <linux/uaccess.h> -#include <asm/pgtable.h> #include <asm/traps.h> #include <asm/ucontext.h> #include <asm/cacheflush.h> +#include "signal.h" + #ifdef CONFIG_MMU /* @@ -62,25 +63,25 @@ #define FMT4SIZE 0 #else #define FORMAT 0 -#define FMT4SIZE sizeof(((struct frame *)0)->un.fmt4) +#define FMT4SIZE sizeof_field(struct frame, un.fmt4) #endif static const int frame_size_change[16] = { - [1] = -1, /* sizeof(((struct frame *)0)->un.fmt1), */ - [2] = sizeof(((struct frame *)0)->un.fmt2), - [3] = sizeof(((struct frame *)0)->un.fmt3), + [1] = -1, /* sizeof_field(struct frame, un.fmt1), */ + [2] = sizeof_field(struct frame, un.fmt2), + [3] = sizeof_field(struct frame, un.fmt3), [4] = FMT4SIZE, - [5] = -1, /* sizeof(((struct frame *)0)->un.fmt5), */ - [6] = -1, /* sizeof(((struct frame *)0)->un.fmt6), */ - [7] = sizeof(((struct frame *)0)->un.fmt7), - [8] = -1, /* sizeof(((struct frame *)0)->un.fmt8), */ - [9] = sizeof(((struct frame *)0)->un.fmt9), - [10] = sizeof(((struct frame *)0)->un.fmta), - [11] = sizeof(((struct frame *)0)->un.fmtb), - [12] = -1, /* sizeof(((struct frame *)0)->un.fmtc), */ - [13] = -1, /* sizeof(((struct frame *)0)->un.fmtd), */ - [14] = -1, /* sizeof(((struct frame *)0)->un.fmte), */ - [15] = -1, /* sizeof(((struct frame *)0)->un.fmtf), */ + [5] = -1, /* sizeof_field(struct frame, un.fmt5), */ + [6] = -1, /* sizeof_field(struct frame, un.fmt6), */ + [7] = sizeof_field(struct frame, un.fmt7), + [8] = -1, /* sizeof_field(struct frame, un.fmt8), */ + [9] = sizeof_field(struct frame, un.fmt9), + [10] = sizeof_field(struct frame, un.fmta), + [11] = sizeof_field(struct frame, un.fmtb), + [12] = -1, /* sizeof_field(struct frame, un.fmtc), */ + [13] = -1, /* sizeof_field(struct frame, un.fmtd), */ + [14] = -1, /* sizeof_field(struct frame, un.fmte), */ + [15] = -1, /* sizeof_field(struct frame, un.fmtf), */ }; static inline int frame_extra_sizes(int f) @@ -448,7 +449,7 @@ static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs) if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) { fpu_version = sc->sc_fpstate[0]; - if (CPU_IS_020_OR_030 && + if (CPU_IS_020_OR_030 && !regs->stkadj && regs->vector >= (VEC_FPBRUC * 4) && regs->vector <= (VEC_FPNAN * 4)) { /* Clear pending exception in 68882 idle frame */ @@ -511,7 +512,7 @@ static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs * if (!(CPU_IS_060 || CPU_IS_COLDFIRE)) context_size = fpstate[1]; fpu_version = fpstate[0]; - if (CPU_IS_020_OR_030 && + if (CPU_IS_020_OR_030 && !regs->stkadj && regs->vector >= (VEC_FPBRUC * 4) && regs->vector <= (VEC_FPNAN * 4)) { /* Clear pending exception in 68882 idle frame */ @@ -623,6 +624,11 @@ static inline void siginfo_build_tests(void) /* _sigfault._addr_pkey */ BUILD_BUG_ON(offsetof(siginfo_t, si_pkey) != 0x12); + /* _sigfault._perf */ + BUILD_BUG_ON(offsetof(siginfo_t, si_perf_data) != 0x10); + BUILD_BUG_ON(offsetof(siginfo_t, si_perf_type) != 0x14); + BUILD_BUG_ON(offsetof(siginfo_t, si_perf_flags) != 0x18); + /* _sigpoll */ BUILD_BUG_ON(offsetof(siginfo_t, si_band) != 0x0c); BUILD_BUG_ON(offsetof(siginfo_t, si_fd) != 0x10); @@ -638,56 +644,35 @@ static inline void siginfo_build_tests(void) static int mangle_kernel_stack(struct pt_regs *regs, int formatvec, void __user *fp) { - int fsize = frame_extra_sizes(formatvec >> 12); - if (fsize < 0) { + int extra = frame_extra_sizes(formatvec >> 12); + char buf[sizeof_field(struct frame, un)]; + + if (extra < 0) { /* * user process trying to return with weird frame format */ pr_debug("user process returning with weird frame format\n"); - return 1; + return -1; } - if (!fsize) { - regs->format = formatvec >> 12; - regs->vector = formatvec & 0xfff; - } else { - struct switch_stack *sw = (struct switch_stack *)regs - 1; - /* yes, twice as much as max(sizeof(frame.un.fmt<x>)) */ - unsigned long buf[sizeof(((struct frame *)0)->un) / 2]; - - /* that'll make sure that expansion won't crap over data */ - if (copy_from_user(buf + fsize / 4, fp, fsize)) - return 1; - - /* point of no return */ - regs->format = formatvec >> 12; - regs->vector = formatvec & 0xfff; -#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack)) - __asm__ __volatile__ ( -#ifdef CONFIG_COLDFIRE - " movel %0,%/sp\n\t" - " bra ret_from_signal\n" -#else - " movel %0,%/a0\n\t" - " subl %1,%/a0\n\t" /* make room on stack */ - " movel %/a0,%/sp\n\t" /* set stack pointer */ - /* move switch_stack and pt_regs */ - "1: movel %0@+,%/a0@+\n\t" - " dbra %2,1b\n\t" - " lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */ - " lsrl #2,%1\n\t" - " subql #1,%1\n\t" - /* copy to the gap we'd made */ - "2: movel %4@+,%/a0@+\n\t" - " dbra %1,2b\n\t" - " bral ret_from_signal\n" + if (extra && copy_from_user(buf, fp, extra)) + return -1; + regs->format = formatvec >> 12; + regs->vector = formatvec & 0xfff; + if (extra) { + void *p = (struct switch_stack *)regs - 1; + struct frame *new = (void *)regs - extra; + int size = sizeof(struct pt_regs)+sizeof(struct switch_stack); + + memmove(p - extra, p, size); + memcpy(p - extra + size, buf, extra); + current->thread.esp0 = (unsigned long)&new->ptregs; +#ifdef CONFIG_M68040 + /* on 68040 complete pending writebacks if any */ + if (new->ptregs.format == 7) // bus error frame + berr_040cleanup(new); #endif - : /* no outputs, it doesn't ever return */ - : "a" (sw), "d" (fsize), "d" (frame_offset/4-1), - "n" (frame_offset), "a" (buf + fsize/4) - : "a0"); -#undef frame_offset } - return 0; + return extra; } static inline int @@ -695,7 +680,6 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __u { int formatvec; struct sigcontext context; - int err = 0; siginfo_build_tests(); @@ -704,7 +688,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __u /* get previous context */ if (copy_from_user(&context, usc, sizeof(context))) - goto badframe; + return -1; /* restore passed registers */ regs->d0 = context.sc_d0; @@ -717,15 +701,10 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __u wrusp(context.sc_usp); formatvec = context.sc_formatvec; - err = restore_fpu_state(&context); - - if (err || mangle_kernel_stack(regs, formatvec, fp)) - goto badframe; - - return 0; + if (restore_fpu_state(&context)) + return -1; -badframe: - return 1; + return mangle_kernel_stack(regs, formatvec, fp); } static inline int @@ -742,7 +721,7 @@ rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw, err = __get_user(temp, &uc->uc_mcontext.version); if (temp != MCONTEXT_VERSION) - goto badframe; + return -1; /* restore passed registers */ err |= __get_user(regs->d0, &gregs[0]); err |= __get_user(regs->d1, &gregs[1]); @@ -771,22 +750,17 @@ rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw, err |= restore_altstack(&uc->uc_stack); if (err) - goto badframe; - - if (mangle_kernel_stack(regs, temp, &uc->uc_extra)) - goto badframe; - - return 0; + return -1; -badframe: - return 1; + return mangle_kernel_stack(regs, temp, &uc->uc_extra); } -asmlinkage int do_sigreturn(struct pt_regs *regs, struct switch_stack *sw) +asmlinkage void *do_sigreturn(struct pt_regs *regs, struct switch_stack *sw) { unsigned long usp = rdusp(); struct sigframe __user *frame = (struct sigframe __user *)(usp - 4); sigset_t set; + int size; if (!access_ok(frame, sizeof(*frame))) goto badframe; @@ -798,20 +772,22 @@ asmlinkage int do_sigreturn(struct pt_regs *regs, struct switch_stack *sw) set_current_blocked(&set); - if (restore_sigcontext(regs, &frame->sc, frame + 1)) + size = restore_sigcontext(regs, &frame->sc, frame + 1); + if (size < 0) goto badframe; - return regs->d0; + return (void *)sw - size; badframe: force_sig(SIGSEGV); - return 0; + return sw; } -asmlinkage int do_rt_sigreturn(struct pt_regs *regs, struct switch_stack *sw) +asmlinkage void *do_rt_sigreturn(struct pt_regs *regs, struct switch_stack *sw) { unsigned long usp = rdusp(); struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4); sigset_t set; + int size; if (!access_ok(frame, sizeof(*frame))) goto badframe; @@ -820,27 +796,34 @@ asmlinkage int do_rt_sigreturn(struct pt_regs *regs, struct switch_stack *sw) set_current_blocked(&set); - if (rt_restore_ucontext(regs, sw, &frame->uc)) + size = rt_restore_ucontext(regs, sw, &frame->uc); + if (size < 0) goto badframe; - return regs->d0; + return (void *)sw - size; badframe: force_sig(SIGSEGV); - return 0; + return sw; +} + +static inline struct pt_regs *rte_regs(struct pt_regs *regs) +{ + return (void *)regs + regs->stkadj; } static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, unsigned long mask) { + struct pt_regs *tregs = rte_regs(regs); sc->sc_mask = mask; sc->sc_usp = rdusp(); sc->sc_d0 = regs->d0; sc->sc_d1 = regs->d1; sc->sc_a0 = regs->a0; sc->sc_a1 = regs->a1; - sc->sc_sr = regs->sr; - sc->sc_pc = regs->pc; - sc->sc_formatvec = regs->format << 12 | regs->vector; + sc->sc_sr = tregs->sr; + sc->sc_pc = tregs->pc; + sc->sc_formatvec = tregs->format << 12 | tregs->vector; save_a5_state(sc, regs); save_fpu_state(sc, regs); } @@ -848,6 +831,7 @@ static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *regs) { struct switch_stack *sw = (struct switch_stack *)regs - 1; + struct pt_regs *tregs = rte_regs(regs); greg_t __user *gregs = uc->uc_mcontext.gregs; int err = 0; @@ -868,43 +852,50 @@ static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs * err |= __put_user(sw->a5, &gregs[13]); err |= __put_user(sw->a6, &gregs[14]); err |= __put_user(rdusp(), &gregs[15]); - err |= __put_user(regs->pc, &gregs[16]); - err |= __put_user(regs->sr, &gregs[17]); - err |= __put_user((regs->format << 12) | regs->vector, &uc->uc_formatvec); + err |= __put_user(tregs->pc, &gregs[16]); + err |= __put_user(tregs->sr, &gregs[17]); + err |= __put_user((tregs->format << 12) | tregs->vector, &uc->uc_formatvec); err |= rt_save_fpu_state(uc, regs); return err; } static inline void __user * -get_sigframe(struct ksignal *ksig, size_t frame_size) +get_sigframe(struct ksignal *ksig, struct pt_regs *tregs, size_t frame_size) { unsigned long usp = sigsp(rdusp(), ksig); + unsigned long gap = 0; - return (void __user *)((usp - frame_size) & -8UL); + if (CPU_IS_020_OR_030 && tregs->format == 0xb) { + /* USP is unreliable so use worst-case value */ + gap = 256; + } + + return (void __user *)((usp - gap - frame_size) & -8UL); } static int setup_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) { struct sigframe __user *frame; - int fsize = frame_extra_sizes(regs->format); + struct pt_regs *tregs = rte_regs(regs); + int fsize = frame_extra_sizes(tregs->format); struct sigcontext context; int err = 0, sig = ksig->sig; if (fsize < 0) { pr_debug("setup_frame: Unknown frame format %#x\n", - regs->format); + tregs->format); return -EFAULT; } - frame = get_sigframe(ksig, sizeof(*frame) + fsize); + frame = get_sigframe(ksig, tregs, sizeof(*frame) + fsize); if (fsize) err |= copy_to_user (frame + 1, regs + 1, fsize); err |= __put_user(sig, &frame->sig); - err |= __put_user(regs->vector, &frame->code); + err |= __put_user(tregs->vector, &frame->code); err |= __put_user(&frame->sc, &frame->psc); if (_NSIG_WORDS > 1) @@ -921,7 +912,8 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set, err |= __put_user(0x70004e40 + (__NR_sigreturn << 16), (long __user *)(frame->retcode)); #else - err |= __put_user((void *) ret_from_user_signal, &frame->pretcode); + err |= __put_user((long) ret_from_user_signal, + (long __user *) &frame->pretcode); #endif if (err) @@ -930,33 +922,27 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set, push_cache ((unsigned long) &frame->retcode); /* - * Set up registers for signal handler. All the state we are about - * to destroy is successfully copied to sigframe. - */ - wrusp ((unsigned long) frame); - regs->pc = (unsigned long) ksig->ka.sa.sa_handler; - adjustformat(regs); - - /* * This is subtle; if we build more than one sigframe, all but the * first one will see frame format 0 and have fsize == 0, so we won't * screw stkadj. */ - if (fsize) + if (fsize) { regs->stkadj = fsize; - - /* Prepare to skip over the extra stuff in the exception frame. */ - if (regs->stkadj) { - struct pt_regs *tregs = - (struct pt_regs *)((ulong)regs + regs->stkadj); + tregs = rte_regs(regs); pr_debug("Performing stackadjust=%04lx\n", regs->stkadj); - /* This must be copied with decreasing addresses to - handle overlaps. */ tregs->vector = 0; tregs->format = 0; - tregs->pc = regs->pc; tregs->sr = regs->sr; } + + /* + * Set up registers for signal handler. All the state we are about + * to destroy is successfully copied to sigframe. + */ + wrusp ((unsigned long) frame); + tregs->pc = (unsigned long) ksig->ka.sa.sa_handler; + adjustformat(regs); + return 0; } @@ -964,7 +950,8 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame; - int fsize = frame_extra_sizes(regs->format); + struct pt_regs *tregs = rte_regs(regs); + int fsize = frame_extra_sizes(tregs->format); int err = 0, sig = ksig->sig; if (fsize < 0) { @@ -973,7 +960,7 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, return -EFAULT; } - frame = get_sigframe(ksig, sizeof(*frame)); + frame = get_sigframe(ksig, tregs, sizeof(*frame)); if (fsize) err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize); @@ -1005,7 +992,8 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, err |= __put_user(0x4e40, (short __user *)(frame->retcode + 4)); #endif #else - err |= __put_user((void *) ret_from_user_rt_signal, &frame->pretcode); + err |= __put_user((long) ret_from_user_rt_signal, + (long __user *) &frame->pretcode); #endif /* CONFIG_MMU */ if (err) @@ -1014,33 +1002,26 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, push_cache ((unsigned long) &frame->retcode); /* - * Set up registers for signal handler. All the state we are about - * to destroy is successfully copied to sigframe. - */ - wrusp ((unsigned long) frame); - regs->pc = (unsigned long) ksig->ka.sa.sa_handler; - adjustformat(regs); - - /* * This is subtle; if we build more than one sigframe, all but the * first one will see frame format 0 and have fsize == 0, so we won't * screw stkadj. */ - if (fsize) + if (fsize) { regs->stkadj = fsize; - - /* Prepare to skip over the extra stuff in the exception frame. */ - if (regs->stkadj) { - struct pt_regs *tregs = - (struct pt_regs *)((ulong)regs + regs->stkadj); + tregs = rte_regs(regs); pr_debug("Performing stackadjust=%04lx\n", regs->stkadj); - /* This must be copied with decreasing addresses to - handle overlaps. */ tregs->vector = 0; tregs->format = 0; - tregs->pc = regs->pc; tregs->sr = regs->sr; } + + /* + * Set up registers for signal handler. All the state we are about + * to destroy is successfully copied to sigframe. + */ + wrusp ((unsigned long) frame); + tregs->pc = (unsigned long) ksig->ka.sa.sa_handler; + adjustformat(regs); return 0; } @@ -1068,7 +1049,7 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler) regs->d0 = -EINTR; break; } - /* fallthrough */ + fallthrough; case -ERESTARTNOINTR: do_restart: regs->d0 = regs->orig_d0; @@ -1130,11 +1111,12 @@ static void do_signal(struct pt_regs *regs) restore_saved_sigmask(); } -void do_notify_resume(struct pt_regs *regs) +asmlinkage void do_notify_resume(struct pt_regs *regs) { - if (test_thread_flag(TIF_SIGPENDING)) + if (test_thread_flag(TIF_NOTIFY_SIGNAL) || + test_thread_flag(TIF_SIGPENDING)) do_signal(regs); - if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) - tracehook_notify_resume(regs); + if (test_thread_flag(TIF_NOTIFY_RESUME)) + resume_user_mode_work(regs); } diff --git a/arch/m68k/kernel/signal.h b/arch/m68k/kernel/signal.h new file mode 100644 index 000000000000..498d84f82820 --- /dev/null +++ b/arch/m68k/kernel/signal.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <linux/linkage.h> + +asmlinkage void do_notify_resume(struct pt_regs *regs); +asmlinkage void *do_sigreturn(struct pt_regs *regs, struct switch_stack *sw); +asmlinkage void *do_rt_sigreturn(struct pt_regs *regs, struct switch_stack *sw); diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c index 18a4de7d5934..1af5e6082467 100644 --- a/arch/m68k/kernel/sys_m68k.c +++ b/arch/m68k/kernel/sys_m68k.c @@ -27,6 +27,7 @@ #include <asm/cachectl.h> #include <asm/traps.h> #include <asm/page.h> +#include <asm/syscalls.h> #include <asm/unistd.h> #include <asm/cacheflush.h> @@ -34,8 +35,7 @@ #include <asm/tlb.h> -asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address, - unsigned long error_code); +#include "../mm/fault.h" asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, @@ -388,6 +388,8 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) ret = -EPERM; if (!capable(CAP_SYS_ADMIN)) goto out; + + mmap_read_lock(current->mm); } else { struct vm_area_struct *vma; @@ -399,9 +401,9 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) * Verify that the specified address region actually belongs * to this process. */ - down_read(¤t->mm->mmap_sem); - vma = find_vma(current->mm, addr); - if (!vma || addr < vma->vm_start || addr + len > vma->vm_end) + mmap_read_lock(current->mm); + vma = vma_lookup(current->mm, addr); + if (!vma || addr + len > vma->vm_end) goto out_unlock; } @@ -450,7 +452,7 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) } } out_unlock: - up_read(¤t->mm->mmap_sem); + mmap_read_unlock(current->mm); out: return ret; } @@ -472,7 +474,7 @@ sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5, spinlock_t *ptl; unsigned long mem_value; - down_read(&mm->mmap_sem); + mmap_read_lock(mm); pgd = pgd_offset(mm, (unsigned long)mem); if (!pgd_present(*pgd)) goto bad_access; @@ -486,6 +488,8 @@ sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5, if (!pmd_present(*pmd)) goto bad_access; pte = pte_offset_map_lock(mm, pmd, (unsigned long)mem, &ptl); + if (!pte) + goto bad_access; if (!pte_present(*pte) || !pte_dirty(*pte) || !pte_write(*pte)) { pte_unmap_unlock(pte, ptl); @@ -501,11 +505,11 @@ sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5, __put_user(newval, mem); pte_unmap_unlock(pte, ptl); - up_read(&mm->mmap_sem); + mmap_read_unlock(mm); return mem_value; bad_access: - up_read(&mm->mmap_sem); + mmap_read_unlock(mm); /* This is not necessarily a bad access, we can get here if a memory we're trying to write to should be copied-on-write. Make the kernel do the necessary page stuff, then re-iterate. @@ -545,13 +549,13 @@ sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5, struct mm_struct *mm = current->mm; unsigned long mem_value; - down_read(&mm->mmap_sem); + mmap_read_lock(mm); mem_value = *mem; if (mem_value == oldval) *mem = newval; - up_read(&mm->mmap_sem); + mmap_read_unlock(mm); return mem_value; } diff --git a/arch/m68k/kernel/syscalls/Makefile b/arch/m68k/kernel/syscalls/Makefile index 659faefdcb1d..b265e4bc16c2 100644 --- a/arch/m68k/kernel/syscalls/Makefile +++ b/arch/m68k/kernel/syscalls/Makefile @@ -2,37 +2,31 @@ kapi := arch/$(SRCARCH)/include/generated/asm uapi := arch/$(SRCARCH)/include/generated/uapi/asm -_dummy := $(shell [ -d '$(uapi)' ] || mkdir -p '$(uapi)') \ - $(shell [ -d '$(kapi)' ] || mkdir -p '$(kapi)') +$(shell mkdir -p $(uapi) $(kapi)) -syscall := $(srctree)/$(src)/syscall.tbl -syshdr := $(srctree)/$(src)/syscallhdr.sh -systbl := $(srctree)/$(src)/syscalltbl.sh +syscall := $(src)/syscall.tbl +syshdr := $(srctree)/scripts/syscallhdr.sh +systbl := $(srctree)/scripts/syscalltbl.sh quiet_cmd_syshdr = SYSHDR $@ - cmd_syshdr = $(CONFIG_SHELL) '$(syshdr)' '$<' '$@' \ - '$(syshdr_abis_$(basetarget))' \ - '$(syshdr_pfx_$(basetarget))' \ - '$(syshdr_offset_$(basetarget))' + cmd_syshdr = $(CONFIG_SHELL) $(syshdr) --emit-nr $< $@ quiet_cmd_systbl = SYSTBL $@ - cmd_systbl = $(CONFIG_SHELL) '$(systbl)' '$<' '$@' \ - '$(systbl_abis_$(basetarget))' \ - '$(systbl_abi_$(basetarget))' \ - '$(systbl_offset_$(basetarget))' + cmd_systbl = $(CONFIG_SHELL) $(systbl) $< $@ -$(uapi)/unistd_32.h: $(syscall) $(syshdr) +$(uapi)/unistd_32.h: $(syscall) $(syshdr) FORCE $(call if_changed,syshdr) -$(kapi)/syscall_table.h: $(syscall) $(systbl) +$(kapi)/syscall_table.h: $(syscall) $(systbl) FORCE $(call if_changed,systbl) uapisyshdr-y += unistd_32.h kapisyshdr-y += syscall_table.h -targets += $(uapisyshdr-y) $(kapisyshdr-y) +uapisyshdr-y := $(addprefix $(uapi)/, $(uapisyshdr-y)) +kapisyshdr-y := $(addprefix $(kapi)/, $(kapisyshdr-y)) +targets += $(addprefix ../../../../, $(uapisyshdr-y) $(kapisyshdr-y)) PHONY += all -all: $(addprefix $(uapi)/,$(uapisyshdr-y)) -all: $(addprefix $(kapi)/,$(kapisyshdr-y)) +all: $(uapisyshdr-y) $(kapisyshdr-y) @: diff --git a/arch/m68k/kernel/syscalls/syscall.tbl b/arch/m68k/kernel/syscalls/syscall.tbl index a88a285a0e5f..7fd43fd4c9f2 100644 --- a/arch/m68k/kernel/syscalls/syscall.tbl +++ b/arch/m68k/kernel/syscalls/syscall.tbl @@ -141,7 +141,7 @@ 131 common quotactl sys_quotactl 132 common getpgid sys_getpgid 133 common fchdir sys_fchdir -134 common bdflush sys_bdflush +134 common bdflush sys_ni_syscall 135 common sysfs sys_sysfs 136 common personality sys_personality # 137 was afs_syscall @@ -156,7 +156,7 @@ 146 common writev sys_writev 147 common getsid sys_getsid 148 common fdatasync sys_fdatasync -149 common _sysctl sys_sysctl +149 common _sysctl sys_ni_syscall 150 common mlock sys_mlock 151 common munlock sys_munlock 152 common mlockall sys_mlockall @@ -255,7 +255,7 @@ 245 common io_cancel sys_io_cancel 246 common fadvise64 sys_fadvise64 247 common exit_group sys_exit_group -248 common lookup_dcookie sys_lookup_dcookie +248 common lookup_dcookie sys_ni_syscall 249 common epoll_create sys_epoll_create 250 common epoll_ctl sys_epoll_ctl 251 common epoll_wait sys_epoll_wait @@ -434,4 +434,30 @@ 432 common fsmount sys_fsmount 433 common fspick sys_fspick 434 common pidfd_open sys_pidfd_open -# 435 reserved for clone3 +435 common clone3 __sys_clone3 +436 common close_range sys_close_range +437 common openat2 sys_openat2 +438 common pidfd_getfd sys_pidfd_getfd +439 common faccessat2 sys_faccessat2 +440 common process_madvise sys_process_madvise +441 common epoll_pwait2 sys_epoll_pwait2 +442 common mount_setattr sys_mount_setattr +443 common quotactl_fd sys_quotactl_fd +444 common landlock_create_ruleset sys_landlock_create_ruleset +445 common landlock_add_rule sys_landlock_add_rule +446 common landlock_restrict_self sys_landlock_restrict_self +# 447 reserved for memfd_secret +448 common process_mrelease sys_process_mrelease +449 common futex_waitv sys_futex_waitv +450 common set_mempolicy_home_node sys_set_mempolicy_home_node +451 common cachestat sys_cachestat +452 common fchmodat2 sys_fchmodat2 +453 common map_shadow_stack sys_map_shadow_stack +454 common futex_wake sys_futex_wake +455 common futex_wait sys_futex_wait +456 common futex_requeue sys_futex_requeue +457 common statmount sys_statmount +458 common listmount sys_listmount +459 common lsm_get_self_attr sys_lsm_get_self_attr +460 common lsm_set_self_attr sys_lsm_set_self_attr +461 common lsm_list_modules sys_lsm_list_modules diff --git a/arch/m68k/kernel/syscalls/syscallhdr.sh b/arch/m68k/kernel/syscalls/syscallhdr.sh deleted file mode 100644 index 6f357d68ef44..000000000000 --- a/arch/m68k/kernel/syscalls/syscallhdr.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh -# SPDX-License-Identifier: GPL-2.0 - -in="$1" -out="$2" -my_abis=`echo "($3)" | tr ',' '|'` -prefix="$4" -offset="$5" - -fileguard=_UAPI_ASM_M68K_`basename "$out" | sed \ - -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \ - -e 's/[^A-Z0-9_]/_/g' -e 's/__/_/g'` -grep -E "^[0-9A-Fa-fXx]+[[:space:]]+${my_abis}" "$in" | sort -n | ( - printf "#ifndef %s\n" "${fileguard}" - printf "#define %s\n" "${fileguard}" - printf "\n" - - nxt=0 - while read nr abi name entry ; do - if [ -z "$offset" ]; then - printf "#define __NR_%s%s\t%s\n" \ - "${prefix}" "${name}" "${nr}" - else - printf "#define __NR_%s%s\t(%s + %s)\n" \ - "${prefix}" "${name}" "${offset}" "${nr}" - fi - nxt=$((nr+1)) - done - - printf "\n" - printf "#ifdef __KERNEL__\n" - printf "#define __NR_syscalls\t%s\n" "${nxt}" - printf "#endif\n" - printf "\n" - printf "#endif /* %s */\n" "${fileguard}" -) > "$out" diff --git a/arch/m68k/kernel/syscalls/syscalltbl.sh b/arch/m68k/kernel/syscalls/syscalltbl.sh deleted file mode 100644 index 85d78d9309ad..000000000000 --- a/arch/m68k/kernel/syscalls/syscalltbl.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh -# SPDX-License-Identifier: GPL-2.0 - -in="$1" -out="$2" -my_abis=`echo "($3)" | tr ',' '|'` -my_abi="$4" -offset="$5" - -emit() { - t_nxt="$1" - t_nr="$2" - t_entry="$3" - - while [ $t_nxt -lt $t_nr ]; do - printf "__SYSCALL(%s, sys_ni_syscall, )\n" "${t_nxt}" - t_nxt=$((t_nxt+1)) - done - printf "__SYSCALL(%s, %s, )\n" "${t_nxt}" "${t_entry}" -} - -grep -E "^[0-9A-Fa-fXx]+[[:space:]]+${my_abis}" "$in" | sort -n | ( - nxt=0 - if [ -z "$offset" ]; then - offset=0 - fi - - while read nr abi name entry ; do - emit $((nxt+offset)) $((nr+offset)) $entry - nxt=$((nr+1)) - done -) > "$out" diff --git a/arch/m68k/kernel/syscalltable.S b/arch/m68k/kernel/syscalltable.S index d329cc7b481c..e25ef4a9df30 100644 --- a/arch/m68k/kernel/syscalltable.S +++ b/arch/m68k/kernel/syscalltable.S @@ -18,9 +18,8 @@ #define sys_mmap2 sys_mmap_pgoff #endif -#define __SYSCALL(nr, entry, nargs) .long entry +#define __SYSCALL(nr, entry) .long entry .section .rodata ALIGN ENTRY(sys_call_table) #include <asm/syscall_table.h> -#undef __SYSCALL diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c index c2697a4d4ddd..a97600b2af50 100644 --- a/arch/m68k/kernel/time.c +++ b/arch/m68k/kernel/time.c @@ -35,18 +35,9 @@ unsigned long (*mach_random_get_entropy)(void); EXPORT_SYMBOL_GPL(mach_random_get_entropy); - -/* - * timer_interrupt() needs to keep up the real-time clock, - * as well as call the "xtime_update()" routine every clocktick - */ -static irqreturn_t timer_interrupt(int irq, void *dummy) -{ - xtime_update(1); - update_process_times(user_mode(get_irq_regs())); - profile_tick(CPU_PROFILING); - #ifdef CONFIG_HEARTBEAT +void timer_heartbeat(void) +{ /* use power LED as a heartbeat instead -- much more useful for debugging -- based on the version for PReP by Cort */ /* acts like an actual heart beat -- ie thump-thump-pause... */ @@ -68,11 +59,19 @@ static irqreturn_t timer_interrupt(int irq, void *dummy) dist = period / 4; } } -#endif /* CONFIG_HEARTBEAT */ - return IRQ_HANDLED; } +#endif /* CONFIG_HEARTBEAT */ #ifdef CONFIG_M68KCLASSIC +/* machine dependent timer functions */ +int (*mach_hwclk) (int, struct rtc_time*); +EXPORT_SYMBOL(mach_hwclk); + +int (*mach_get_rtc_pll)(struct rtc_pll_info *); +int (*mach_set_rtc_pll)(struct rtc_pll_info *); +EXPORT_SYMBOL(mach_get_rtc_pll); +EXPORT_SYMBOL(mach_set_rtc_pll); + #if !IS_BUILTIN(CONFIG_RTC_DRV_GENERIC) void read_persistent_clock64(struct timespec64 *ts) { @@ -154,5 +153,5 @@ module_init(rtc_init); void __init time_init(void) { - mach_sched_init(timer_interrupt); + mach_sched_init(); } diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c index 344f93d36a9a..53d0cf343d90 100644 --- a/arch/m68k/kernel/traps.c +++ b/arch/m68k/kernel/traps.c @@ -30,15 +30,19 @@ #include <linux/init.h> #include <linux/ptrace.h> #include <linux/kallsyms.h> +#include <linux/extable.h> #include <asm/setup.h> #include <asm/fpu.h> #include <linux/uaccess.h> #include <asm/traps.h> -#include <asm/pgalloc.h> #include <asm/machdep.h> +#include <asm/processor.h> #include <asm/siginfo.h> +#include <asm/tlbflush.h> +#include "traps.h" +#include "../mm/fault.h" static const char *vec_names[] = { [VEC_RESETSP] = "RESET SP", @@ -123,10 +127,6 @@ static const char *space_names[] = { }; void die_if_kernel(char *,struct pt_regs *,int); -asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address, - unsigned long error_code); -int send_fault_sig(struct pt_regs *regs); - asmlinkage void trap_c(struct frame *fp); #if defined (CONFIG_M68060) @@ -182,9 +182,8 @@ static inline void access_error060 (struct frame *fp) static inline unsigned long probe040(int iswrite, unsigned long addr, int wbs) { unsigned long mmusr; - mm_segment_t old_fs = get_fs(); - set_fs(MAKE_MM_SEG(wbs)); + set_fc(wbs); if (iswrite) asm volatile (".chip 68040; ptestw (%0); .chip 68k" : : "a" (addr)); @@ -193,7 +192,7 @@ static inline unsigned long probe040(int iswrite, unsigned long addr, int wbs) asm volatile (".chip 68040; movec %%mmusr,%0; .chip 68k" : "=r" (mmusr)); - set_fs(old_fs); + set_fc(USER_DATA); return mmusr; } @@ -202,10 +201,8 @@ static inline int do_040writeback1(unsigned short wbs, unsigned long wba, unsigned long wbd) { int res = 0; - mm_segment_t old_fs = get_fs(); - /* set_fs can not be moved, otherwise put_user() may oops */ - set_fs(MAKE_MM_SEG(wbs)); + set_fc(wbs); switch (wbs & WBSIZ_040) { case BA_SIZE_BYTE: @@ -219,9 +216,7 @@ static inline int do_040writeback1(unsigned short wbs, unsigned long wba, break; } - /* set_fs can not be moved, otherwise put_user() may oops */ - set_fs(old_fs); - + set_fc(USER_DATA); pr_debug("do_040writeback1, res=%d\n", res); @@ -369,7 +364,7 @@ disable_wb: #if defined(CONFIG_SUN3) #include <asm/sun3mmu.h> -extern int mmu_emu_handle_fault (unsigned long, int, int); +#include "../sun3/sun3.h" /* sun3 version of bus_error030 */ @@ -491,10 +486,10 @@ static inline void bus_error030 (struct frame *fp) if (buserr_type & SUN3_BUSERR_INVALID) { if (!mmu_emu_handle_fault(addr, 1, 0)) do_page_fault (&fp->ptregs, addr, 0); - } else { + } else { pr_debug("protection fault on insn access (segv).\n"); force_sig (SIGSEGV); - } + } } #else #if defined(CPU_M68020_OR_M68030) @@ -550,7 +545,8 @@ static inline void bus_error030 (struct frame *fp) errorcode |= 2; if (mmusr & (MMU_I | MMU_WP)) { - if (ssw & 4) { + /* We might have an exception table for this PC */ + if (ssw & 4 && !search_exception_tables(fp->ptregs.pc)) { pr_err("Data %s fault at %#010lx in %s (pc=%#lx)\n", ssw & RW ? "read" : "write", fp->un.fmtb.daddr, @@ -811,13 +807,13 @@ asmlinkage void buserr_c(struct frame *fp) static int kstack_depth_to_print = 48; -void show_trace(unsigned long *stack) +static void show_trace(unsigned long *stack, const char *loglvl) { unsigned long *endstack; unsigned long addr; int i; - pr_info("Call Trace:"); + printk("%sCall Trace:", loglvl); addr = (unsigned long)stack + THREAD_SIZE - 1; endstack = (unsigned long *)(addr & -THREAD_SIZE); i = 0; @@ -846,7 +842,6 @@ void show_trace(unsigned long *stack) void show_registers(struct pt_regs *regs) { struct frame *fp = (struct frame *)regs; - mm_segment_t old_fs = get_fs(); u16 c, *cp; unsigned long addr; int i; @@ -855,9 +850,9 @@ void show_registers(struct pt_regs *regs) pr_info("PC: [<%08lx>] %pS\n", regs->pc, (void *)regs->pc); pr_info("SR: %04x SP: %p a2: %08lx\n", regs->sr, regs, regs->a2); pr_info("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n", - regs->d0, regs->d1, regs->d2, regs->d3); + regs->d0, regs->d1, regs->d2, regs->d3); pr_info("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", - regs->d4, regs->d5, regs->a0, regs->a1); + regs->d4, regs->d5, regs->a0, regs->a1); pr_info("Process %s (pid: %d, task=%p)\n", current->comm, task_pid_nr(current), current); @@ -916,13 +911,12 @@ void show_registers(struct pt_regs *regs) default: pr_cont("\n"); } - show_stack(NULL, (unsigned long *)addr); + show_stack(NULL, (unsigned long *)addr, KERN_INFO); pr_info("Code:"); - set_fs(KERNEL_DS); cp = (u16 *)regs->pc; for (i = -8; i < 16; i++) { - if (get_user(c, cp + i) && i >= 0) { + if (get_kernel_nofault(c, cp + i) && i >= 0) { pr_cont(" Bad PC value."); break; } @@ -931,11 +925,11 @@ void show_registers(struct pt_regs *regs) else pr_cont(" <%04x>", c); } - set_fs(old_fs); pr_cont("\n"); } -void show_stack(struct task_struct *task, unsigned long *stack) +void show_stack(struct task_struct *task, unsigned long *stack, + const char *loglvl) { unsigned long *p; unsigned long *endstack; @@ -949,7 +943,7 @@ void show_stack(struct task_struct *task, unsigned long *stack) } endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE); - pr_info("Stack from %08lx:", (unsigned long)stack); + printk("%sStack from %08lx:", loglvl, (unsigned long)stack); p = stack; for (i = 0; i < kstack_depth_to_print; i++) { if (p + 1 > endstack) @@ -959,7 +953,7 @@ void show_stack(struct task_struct *task, unsigned long *stack) pr_cont(" %08lx", *p++); } pr_cont("\n"); - show_trace(stack); + show_trace(stack, loglvl); } /* @@ -970,7 +964,7 @@ void show_stack(struct task_struct *task, unsigned long *stack) * real 68k parts, but it won't hurt either. */ -void bad_super_trap (struct frame *fp) +static void bad_super_trap(struct frame *fp) { int vector = (fp->ptregs.vector >> 2) & 0xff; @@ -1139,7 +1133,7 @@ void die_if_kernel (char *str, struct pt_regs *fp, int nr) pr_crit("%s: %08x\n", str, nr); show_registers(fp); add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE); - do_exit(SIGSEGV); + make_task_dead(SIGSEGV); } asmlinkage void set_esp0(unsigned long ssp) @@ -1153,7 +1147,7 @@ asmlinkage void set_esp0(unsigned long ssp) */ asmlinkage void fpsp040_die(void) { - do_exit(SIGSEGV); + force_exit_sig(SIGSEGV); } #ifdef CONFIG_M68KFPU_EMU diff --git a/arch/m68k/kernel/traps.h b/arch/m68k/kernel/traps.h new file mode 100644 index 000000000000..6414b4a0e558 --- /dev/null +++ b/arch/m68k/kernel/traps.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <linux/linkage.h> + +struct frame; + +asmlinkage void buserr_c(struct frame *fp); +asmlinkage void fpemu_signal(int signal, int code, void *addr); +asmlinkage void fpsp040_die(void); +asmlinkage void set_esp0(unsigned long ssp); diff --git a/arch/m68k/kernel/uboot.c b/arch/m68k/kernel/uboot.c index 1b4c562753da..8bb1cb3a7490 100644 --- a/arch/m68k/kernel/uboot.c +++ b/arch/m68k/kernel/uboot.c @@ -26,8 +26,8 @@ #include <asm/setup.h> #include <asm/irq.h> #include <asm/machdep.h> -#include <asm/pgtable.h> #include <asm/sections.h> +#include <asm/bootinfo.h> /* * parse_uboot_commandline @@ -64,20 +64,22 @@ static void __init parse_uboot_commandline(char *commandp, int size) { extern unsigned long _init_sp; unsigned long *sp; - unsigned long uboot_kbd; - unsigned long uboot_initrd_start, uboot_initrd_end; unsigned long uboot_cmd_start, uboot_cmd_end; +#if defined(CONFIG_BLK_DEV_INITRD) + unsigned long uboot_initrd_start, uboot_initrd_end; +#endif /* if defined(CONFIG_BLK_DEV_INITRD) */ sp = (unsigned long *)_init_sp; - uboot_kbd = sp[1]; - uboot_initrd_start = sp[2]; - uboot_initrd_end = sp[3]; uboot_cmd_start = sp[4]; uboot_cmd_end = sp[5]; if (uboot_cmd_start && uboot_cmd_end) strncpy(commandp, (const char *)uboot_cmd_start, size); + #if defined(CONFIG_BLK_DEV_INITRD) + uboot_initrd_start = sp[2]; + uboot_initrd_end = sp[3]; + if (uboot_initrd_start && uboot_initrd_end && (uboot_initrd_end > uboot_initrd_start)) { initrd_start = uboot_initrd_start; diff --git a/arch/m68k/kernel/vectors.c b/arch/m68k/kernel/vectors.c index 322c977bb9ec..667e848070f4 100644 --- a/arch/m68k/kernel/vectors.c +++ b/arch/m68k/kernel/vectors.c @@ -17,6 +17,7 @@ /* * Sets up all exception vectors */ +#include <linux/cpu.h> #include <linux/sched.h> #include <linux/kernel.h> #include <linux/linkage.h> @@ -27,6 +28,8 @@ #include <asm/fpu.h> #include <asm/traps.h> +#include "vectors.h" + /* assembler routines */ asmlinkage void system_call(void); asmlinkage void buserr(void); diff --git a/arch/m68k/kernel/vectors.h b/arch/m68k/kernel/vectors.h new file mode 100644 index 000000000000..897330737ec5 --- /dev/null +++ b/arch/m68k/kernel/vectors.h @@ -0,0 +1,3 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +void base_trap_init(void); diff --git a/arch/m68k/kernel/vmlinux-nommu.lds b/arch/m68k/kernel/vmlinux-nommu.lds index 7b975420c3d9..2624fc18c131 100644 --- a/arch/m68k/kernel/vmlinux-nommu.lds +++ b/arch/m68k/kernel/vmlinux-nommu.lds @@ -48,7 +48,6 @@ SECTIONS { IRQENTRY_TEXT SOFTIRQENTRY_TEXT SCHED_TEXT - CPUIDLE_TEXT LOCK_TEXT *(.fixup) . = ALIGN(16); @@ -65,7 +64,6 @@ SECTIONS { _edata = .; EXCEPTION_TABLE(16) - NOTES . = ALIGN(PAGE_SIZE); __init_begin = .; @@ -82,12 +80,12 @@ SECTIONS { __init_end = .; } - BSS_SECTION(0, 0, 0) + BSS_SECTION(4, 0, 4) _end = .; STABS_DEBUG - .comment 0 : { *(.comment) } + ELF_DETAILS /* Sections to be discarded */ DISCARDS diff --git a/arch/m68k/kernel/vmlinux-std.lds b/arch/m68k/kernel/vmlinux-std.lds index 4d33da4e7106..1ccdd04ae462 100644 --- a/arch/m68k/kernel/vmlinux-std.lds +++ b/arch/m68k/kernel/vmlinux-std.lds @@ -19,7 +19,6 @@ SECTIONS IRQENTRY_TEXT SOFTIRQENTRY_TEXT SCHED_TEXT - CPUIDLE_TEXT LOCK_TEXT *(.fixup) *(.gnu.warning) @@ -49,7 +48,6 @@ SECTIONS *(.m68k_fixup) __stop_fixup = .; } - NOTES .init_end : { /* This ALIGN be in a section so that _end is at the end of the load segment. */ @@ -60,7 +58,7 @@ SECTIONS _end = . ; STABS_DEBUG - .comment 0 : { *(.comment) } + ELF_DETAILS /* Sections to be discarded */ DISCARDS diff --git a/arch/m68k/kernel/vmlinux-sun3.lds b/arch/m68k/kernel/vmlinux-sun3.lds index 87d9f4d08f65..f13ddcc2af5c 100644 --- a/arch/m68k/kernel/vmlinux-sun3.lds +++ b/arch/m68k/kernel/vmlinux-sun3.lds @@ -19,7 +19,6 @@ SECTIONS IRQENTRY_TEXT SOFTIRQENTRY_TEXT SCHED_TEXT - CPUIDLE_TEXT LOCK_TEXT *(.fixup) *(.gnu.warning) @@ -33,7 +32,6 @@ SECTIONS RW_DATA(16, PAGE_SIZE, THREAD_SIZE) :data /* End of data goes *here* so that freeing init code works properly. */ _edata = .; - NOTES /* will be freed after init */ . = ALIGN(PAGE_SIZE); /* Init code and data */ @@ -53,6 +51,7 @@ __init_begin = .; _end = . ; STABS_DEBUG + ELF_DETAILS /* Sections to be discarded */ DISCARDS |