summaryrefslogtreecommitdiff
path: root/arch/alpha
diff options
context:
space:
mode:
Diffstat (limited to 'arch/alpha')
-rw-r--r--arch/alpha/Kconfig13
-rw-r--r--arch/alpha/Makefile8
-rw-r--r--arch/alpha/configs/defconfig1
-rw-r--r--arch/alpha/include/asm/Kbuild1
-rw-r--r--arch/alpha/include/asm/device.h6
-rw-r--r--arch/alpha/include/asm/elf.h1
-rw-r--r--arch/alpha/include/asm/ftrace.h30
-rw-r--r--arch/alpha/include/asm/irqflags.h6
-rw-r--r--arch/alpha/include/asm/page.h1
-rw-r--r--arch/alpha/include/asm/pci.h13
-rw-r--r--arch/alpha/include/asm/pgtable.h44
-rw-r--r--arch/alpha/include/asm/ptrace.h7
-rw-r--r--arch/alpha/include/asm/seccomp.h13
-rw-r--r--arch/alpha/include/asm/string.h2
-rw-r--r--arch/alpha/include/asm/syscall.h97
-rw-r--r--arch/alpha/include/asm/thread_info.h19
-rw-r--r--arch/alpha/include/asm/timex.h4
-rw-r--r--arch/alpha/include/asm/tlb.h6
-rw-r--r--arch/alpha/include/asm/tlbflush.h4
-rw-r--r--arch/alpha/include/asm/xor.h866
-rw-r--r--arch/alpha/include/uapi/asm/errno.h4
-rw-r--r--arch/alpha/include/uapi/asm/fcntl.h34
-rw-r--r--arch/alpha/include/uapi/asm/fpu.h8
-rw-r--r--arch/alpha/include/uapi/asm/ptrace.h2
-rw-r--r--arch/alpha/include/uapi/asm/socket.h2
-rw-r--r--arch/alpha/kernel/Makefile3
-rw-r--r--arch/alpha/kernel/asm-offsets.c1
-rw-r--r--arch/alpha/kernel/core_marvel.c4
-rw-r--r--arch/alpha/kernel/core_titan.c4
-rw-r--r--arch/alpha/kernel/entry.S135
-rw-r--r--arch/alpha/kernel/io.c2
-rw-r--r--arch/alpha/kernel/irq.c8
-rw-r--r--arch/alpha/kernel/irq_alpha.c87
-rw-r--r--arch/alpha/kernel/irq_i8259.c19
-rw-r--r--arch/alpha/kernel/module.c4
-rw-r--r--arch/alpha/kernel/osf_sys.c34
-rw-r--r--arch/alpha/kernel/pci-sysfs.c394
-rw-r--r--arch/alpha/kernel/pci.c3
-rw-r--r--arch/alpha/kernel/proto.h4
-rw-r--r--arch/alpha/kernel/ptrace.c307
-rw-r--r--arch/alpha/kernel/rtc.c37
-rw-r--r--arch/alpha/kernel/setup.c3
-rw-r--r--arch/alpha/kernel/signal.c9
-rw-r--r--arch/alpha/kernel/stacktrace.c61
-rw-r--r--arch/alpha/kernel/sys_dp264.c38
-rw-r--r--arch/alpha/kernel/sys_marvel.c25
-rw-r--r--arch/alpha/kernel/sys_rawhide.c17
-rw-r--r--arch/alpha/kernel/syscalls/syscall.tbl2
-rw-r--r--arch/alpha/kernel/traps.c18
-rw-r--r--arch/alpha/kernel/vmlinux.lds.S3
-rw-r--r--arch/alpha/lib/strncpy.S83
-rw-r--r--arch/alpha/lib/styncpy.S1
-rw-r--r--arch/alpha/math-emu/math.c88
-rw-r--r--arch/alpha/mm/Makefile2
-rw-r--r--arch/alpha/mm/init.c19
-rw-r--r--arch/alpha/mm/tlbflush.c112
56 files changed, 1363 insertions, 1356 deletions
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 80367f2cf821..e53ef2d88463 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -31,15 +31,22 @@ config ALPHA
select GENERIC_SMP_IDLE_THREAD
select HAS_IOPORT
select HAVE_ARCH_AUDITSYSCALL
+ select HAVE_ARCH_SECCOMP
+ select HAVE_ARCH_SECCOMP_FILTER
+ select HAVE_ARCH_TRACEHOOK
select HAVE_MOD_ARCH_SPECIFIC
select LOCK_MM_AND_FIND_VMA
select MODULES_USE_ELF_RELA
select ODD_RT_SIGACTION
select OLD_SIGSUSPEND
+ select ARCH_STACKWALK
select CPU_NO_EFFICIENT_FFS if !ALPHA_EV67
select MMU_GATHER_NO_RANGE
+ select MMU_GATHER_RCU_TABLE_FREE
select SPARSEMEM_EXTREME if SPARSEMEM
select ZONE_DMA
+ select TRACE_IRQFLAGS_SUPPORT
+ select ARCH_WANT_FRAME_POINTERS
help
The Alpha is a 64-bit general-purpose processor designed and
marketed by the Digital Equipment Corporation of blessed memory,
@@ -76,6 +83,12 @@ config PGTABLE_LEVELS
config AUDIT_ARCH
bool
+config STACKTRACE_SUPPORT
+ def_bool y
+
+config LOCKDEP_SUPPORT
+ def_bool y
+
menu "System setup"
choice
diff --git a/arch/alpha/Makefile b/arch/alpha/Makefile
index 35445ff2e489..7074602dca94 100644
--- a/arch/alpha/Makefile
+++ b/arch/alpha/Makefile
@@ -27,10 +27,16 @@ cpuflags-$(CONFIG_ALPHA_GENERIC) := -mcpu=ev56 -mtune=ev6
cflags-y += $(cpuflags-y)
+KBUILD_CFLAGS += $(cflags-y)
+
# For TSUNAMI, we must have the assembler not emulate our instructions.
# The same is true for IRONGATE, POLARIS, PYXIS.
# BWX is most important, but we don't really want any emulation ever.
-KBUILD_CFLAGS += $(cflags-y) -Wa,-mev6
+# Only gas emulates instructions the target does not implement, and only gas
+# understands -mev6. LLVM's integrated assembler never emulates.
+ifdef CONFIG_AS_IS_GNU
+KBUILD_CFLAGS += -Wa,-mev6
+endif
libs-y += arch/alpha/lib/
diff --git a/arch/alpha/configs/defconfig b/arch/alpha/configs/defconfig
index 3280bd9e6578..29748bbd94f3 100644
--- a/arch/alpha/configs/defconfig
+++ b/arch/alpha/configs/defconfig
@@ -45,7 +45,6 @@ CONFIG_NET_TULIP=y
CONFIG_DE2104X=m
CONFIG_TULIP=y
CONFIG_TULIP_MMIO=y
-CONFIG_YELLOWFIN=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_RTC_CLASS=y
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index 483965c5a4de..b154b4e3dfa8 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -5,4 +5,5 @@ generic-y += agp.h
generic-y += asm-offsets.h
generic-y += kvm_para.h
generic-y += mcs_spinlock.h
+generic-y += ring_buffer.h
generic-y += text-patching.h
diff --git a/arch/alpha/include/asm/device.h b/arch/alpha/include/asm/device.h
deleted file mode 100644
index 9ca75a7db23e..000000000000
--- a/arch/alpha/include/asm/device.h
+++ /dev/null
@@ -1,6 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Arch specific extensions to struct device
- */
-#include <asm-generic/device.h>
-
diff --git a/arch/alpha/include/asm/elf.h b/arch/alpha/include/asm/elf.h
index 50c82187e60e..b15946621d57 100644
--- a/arch/alpha/include/asm/elf.h
+++ b/arch/alpha/include/asm/elf.h
@@ -53,6 +53,7 @@
#define EF_ALPHA_32BIT 1 /* All addresses are below 2GB */
+#define CORE_DUMP_USE_REGSET 1
/*
* ELF register definitions..
*/
diff --git a/arch/alpha/include/asm/ftrace.h b/arch/alpha/include/asm/ftrace.h
index 40a8c178f10d..7ec44134c804 100644
--- a/arch/alpha/include/asm/ftrace.h
+++ b/arch/alpha/include/asm/ftrace.h
@@ -1 +1,29 @@
-/* empty */
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_ALPHA_FTRACE_H
+#define _ASM_ALPHA_FTRACE_H
+
+#ifdef CONFIG_FRAME_POINTER
+
+static void *alpha_ftrace_return_address0(void)
+ noinline notrace;
+static void *alpha_ftrace_return_address0(void)
+{
+ return __builtin_return_address(0);
+}
+
+#define ftrace_return_address0 alpha_ftrace_return_address0()
+
+/*
+ * __builtin_return_address() requires a constant integer argument.
+ * Keep this as a macro so the value is seen at the callsite.
+ */
+#define ftrace_return_address(n) __builtin_return_address(n)
+
+#else /* !CONFIG_FRAME_POINTER */
+
+#define ftrace_return_address0 0UL
+#define ftrace_return_address(n) ((void)(n), 0UL)
+
+#endif /* CONFIG_FRAME_POINTER */
+
+#endif /* _ASM_ALPHA_FTRACE_H */
diff --git a/arch/alpha/include/asm/irqflags.h b/arch/alpha/include/asm/irqflags.h
index 9f25d4e0d37e..f207544f52de 100644
--- a/arch/alpha/include/asm/irqflags.h
+++ b/arch/alpha/include/asm/irqflags.h
@@ -26,7 +26,7 @@ extern int __min_ipl;
static inline unsigned long arch_local_save_flags(void)
{
- return rdps();
+ return getipl();
}
static inline void arch_local_irq_disable(void)
@@ -51,13 +51,13 @@ static inline void arch_local_irq_enable(void)
static inline void arch_local_irq_restore(unsigned long flags)
{
barrier();
- setipl(flags);
+ setipl(flags & 7);
barrier();
}
static inline bool arch_irqs_disabled_flags(unsigned long flags)
{
- return flags == IPL_MAX;
+ return (flags & 7) == IPL_MAX;
}
static inline bool arch_irqs_disabled(void)
diff --git a/arch/alpha/include/asm/page.h b/arch/alpha/include/asm/page.h
index d2c6667d73e9..59d01f9b77f6 100644
--- a/arch/alpha/include/asm/page.h
+++ b/arch/alpha/include/asm/page.h
@@ -11,7 +11,6 @@
#define STRICT_MM_TYPECHECKS
extern void clear_page(void *page);
-#define clear_user_page(page, vaddr, pg) clear_page(page)
#define vma_alloc_zeroed_movable_folio(vma, vaddr) \
vma_alloc_folio(GFP_HIGHUSER_MOVABLE | __GFP_ZERO, 0, vma, vaddr)
diff --git a/arch/alpha/include/asm/pci.h b/arch/alpha/include/asm/pci.h
index 6c04fcbdc8ed..ad5d1391e1fa 100644
--- a/arch/alpha/include/asm/pci.h
+++ b/arch/alpha/include/asm/pci.h
@@ -84,8 +84,17 @@ extern int pci_legacy_write(struct pci_bus *bus, loff_t port, u32 val,
extern int pci_mmap_legacy_page_range(struct pci_bus *bus,
struct vm_area_struct *vma,
enum pci_mmap_state mmap_state);
-extern void pci_adjust_legacy_attr(struct pci_bus *bus,
- enum pci_mmap_state mmap_type);
+extern bool pci_legacy_has_sparse(struct pci_bus *bus,
+ enum pci_mmap_state type);
#define HAVE_PCI_LEGACY 1
+extern const struct attribute_group pci_dev_resource_attr_group;
+extern const struct attribute_group pci_dev_resource_sparse_attr_group;
+extern const struct attribute_group pci_dev_resource_dense_attr_group;
+
+#define ARCH_PCI_DEV_GROUPS \
+ &pci_dev_resource_attr_group, \
+ &pci_dev_resource_sparse_attr_group, \
+ &pci_dev_resource_dense_attr_group,
+
#endif /* __ALPHA_PCI_H */
diff --git a/arch/alpha/include/asm/pgtable.h b/arch/alpha/include/asm/pgtable.h
index 90e7a9539102..8e00cf9dc39d 100644
--- a/arch/alpha/include/asm/pgtable.h
+++ b/arch/alpha/include/asm/pgtable.h
@@ -17,6 +17,7 @@
#include <asm/processor.h> /* For TASK_SIZE */
#include <asm/machvec.h>
#include <asm/setup.h>
+#include <linux/page_table_check.h>
struct mm_struct;
struct vm_area_struct;
@@ -126,10 +127,15 @@ struct vm_area_struct;
#define pgprot_noncached(prot) (prot)
/*
- * ZERO_PAGE is a global shared page that is always zero: used
- * for zero-mapped memory areas etc..
+ * All caching attribute macros are identity on Alpha, so the generic
+ * pgprot_modify() degenerates to tautological self-comparisons.
+ * Override it to just return newprot directly.
*/
-#define ZERO_PAGE(vaddr) (virt_to_page(ZERO_PGE))
+#define pgprot_modify pgprot_modify
+static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot)
+{
+ return newprot;
+}
/*
* On certain platforms whose physical address space can overlap KSEG,
@@ -183,6 +189,9 @@ extern inline void pud_set(pud_t * pudp, pmd_t * pmdp)
{ pud_val(*pudp) = _PAGE_TABLE | ((((unsigned long) pmdp) - PAGE_OFFSET) << (32-PAGE_SHIFT)); }
+extern void migrate_flush_tlb_page(struct vm_area_struct *vma,
+ unsigned long addr);
+
extern inline unsigned long
pmd_page_vaddr(pmd_t pmd)
{
@@ -202,7 +211,7 @@ extern inline int pte_none(pte_t pte) { return !pte_val(pte); }
extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_VALID; }
extern inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
- pte_val(*ptep) = 0;
+ WRITE_ONCE(pte_val(*ptep), 0);
}
extern inline int pmd_none(pmd_t pmd) { return !pmd_val(pmd); }
@@ -264,6 +273,33 @@ extern inline pte_t * pte_offset_kernel(pmd_t * dir, unsigned long address)
extern pgd_t swapper_pg_dir[1024];
+#ifdef CONFIG_COMPACTION
+#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+
+static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
+ unsigned long address,
+ pte_t *ptep)
+{
+ pte_t pte = READ_ONCE(*ptep);
+
+ pte_clear(mm, address, ptep);
+ return pte;
+}
+
+#define __HAVE_ARCH_PTEP_CLEAR_FLUSH
+
+static inline pte_t ptep_clear_flush(struct vm_area_struct *vma,
+ unsigned long addr, pte_t *ptep)
+{
+ struct mm_struct *mm = vma->vm_mm;
+ pte_t pte = ptep_get_and_clear(mm, addr, ptep);
+
+ page_table_check_pte_clear(mm, addr, pte);
+ migrate_flush_tlb_page(vma, addr);
+ return pte;
+}
+
+#endif
/*
* The Alpha doesn't have any external MMU info: the kernel page
* tables contain all the necessary information.
diff --git a/arch/alpha/include/asm/ptrace.h b/arch/alpha/include/asm/ptrace.h
index 3557ce64ed21..8e0a589e2d15 100644
--- a/arch/alpha/include/asm/ptrace.h
+++ b/arch/alpha/include/asm/ptrace.h
@@ -24,4 +24,11 @@ static inline unsigned long regs_return_value(struct pt_regs *regs)
return regs->r0;
}
+/* Helpers for working with the user stack pointer */
+static inline unsigned long user_stack_pointer(struct pt_regs *regs)
+{
+ /* Valid for user-mode regs */
+ return regs->usp;
+}
+
#endif
diff --git a/arch/alpha/include/asm/seccomp.h b/arch/alpha/include/asm/seccomp.h
new file mode 100644
index 000000000000..311934d20340
--- /dev/null
+++ b/arch/alpha/include/asm/seccomp.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_ALPHA_SECCOMP_H
+#define _ASM_ALPHA_SECCOMP_H
+
+#include <asm/unistd.h>
+#include <asm-generic/seccomp.h>
+#include <uapi/linux/audit.h>
+
+#define SECCOMP_ARCH_NATIVE AUDIT_ARCH_ALPHA
+#define SECCOMP_ARCH_NATIVE_NR NR_syscalls
+#define SECCOMP_ARCH_NATIVE_NAME "alpha"
+
+#endif /* _ASM_ALPHA_SECCOMP_H */
diff --git a/arch/alpha/include/asm/string.h b/arch/alpha/include/asm/string.h
index f043f91ff988..7c7545a2319a 100644
--- a/arch/alpha/include/asm/string.h
+++ b/arch/alpha/include/asm/string.h
@@ -47,8 +47,6 @@ extern inline void *__memset(void *s, int c, size_t n)
#define __HAVE_ARCH_STRCPY
extern char * strcpy(char *,const char *);
-#define __HAVE_ARCH_STRNCPY
-extern char * strncpy(char *, const char *, size_t);
#define __HAVE_ARCH_STRCAT
extern char * strcat(char *, const char *);
#define __HAVE_ARCH_STRNCAT
diff --git a/arch/alpha/include/asm/syscall.h b/arch/alpha/include/asm/syscall.h
index f21babaeed85..1e78cbd46faf 100644
--- a/arch/alpha/include/asm/syscall.h
+++ b/arch/alpha/include/asm/syscall.h
@@ -3,6 +3,10 @@
#define _ASM_ALPHA_SYSCALL_H
#include <uapi/linux/audit.h>
+#include <linux/audit.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <asm/ptrace.h>
static inline int syscall_get_arch(struct task_struct *task)
{
@@ -12,7 +16,98 @@ static inline int syscall_get_arch(struct task_struct *task)
static inline long syscall_get_return_value(struct task_struct *task,
struct pt_regs *regs)
{
- return regs->r0;
+ return regs->r19 ? -(long)regs->r0 : (long)regs->r0;
+}
+
+static inline long syscall_get_error(struct task_struct *task,
+ struct pt_regs *regs)
+{
+ return regs->r19 ? -(long)regs->r0 : 0;
+}
+
+
+/*
+ * Alpha syscall ABI / kernel conventions:
+ * - PAL provides syscall number in r0 on entry.
+ * - The kernel tracks the active syscall number in regs->r1 (mutable) and
+ * preserves the original syscall number in regs->r2 for rollback/restart.
+ * - Return value is in regs->r0, with regs->r19 ("a3") as the error flag
+ * (0=success, 1=error; on error regs->r0 holds positive errno).
+ */
+
+static inline long syscall_get_nr(struct task_struct *task,
+ struct pt_regs *regs)
+{
+ return (long)regs->r1;
+}
+
+static inline void syscall_set_nr(struct task_struct *task,
+ struct pt_regs *regs,
+ long nr)
+{
+ regs->r1 = (unsigned long)nr;
+}
+
+/*
+ * Syscall arguments:
+ * regs->r16..regs->r21 carry up to 6 syscall arguments on entry.
+ * Note: regs->r19 is also used as "a3" (error flag) on syscall return.
+ */
+
+static inline void syscall_get_arguments(struct task_struct *task,
+ struct pt_regs *regs,
+ unsigned long *args)
+{
+ args[0] = regs->r16;
+ args[1] = regs->r17;
+ args[2] = regs->r18;
+ args[3] = regs->r19;
+ args[4] = regs->r20;
+ args[5] = regs->r21;
+}
+
+static inline void syscall_set_arguments(struct task_struct *task,
+ struct pt_regs *regs,
+ const unsigned long *args)
+{
+ regs->r16 = args[0];
+ regs->r17 = args[1];
+ regs->r18 = args[2];
+ regs->r19 = args[3];
+ regs->r20 = args[4];
+ regs->r21 = args[5];
+}
+/*
+ * Set return value for a syscall.
+ * Alpha uses r0 for return value and r19 ("a3") as the error indicator:
+ * a3 = 0 => success
+ * a3 = 1 => error, and userspace interprets r0 as errno (positive).
+ *
+ * The kernel reports errors to userspace by setting a3=1 and placing a
+ * positive errno value in r0. Some syscall paths do this in entry.S,
+ * while others (e.g. seccomp/ptrace helpers) use syscall_set_return_value().
+ */
+
+static inline void syscall_set_return_value(struct task_struct *task,
+ struct pt_regs *regs,
+ int error, long val)
+{
+
+ if (error) {
+ /* error is negative errno in this tree */
+ regs->r0 = (unsigned long)(-error); /* positive errno */
+ regs->r19 = 1; /* a3 = error */
+ } else {
+ regs->r0 = (unsigned long)val;
+ regs->r19 = 0; /* a3 = success */
+ }
+}
+
+/* Restore the original syscall nr after seccomp/ptrace modified regs->r1. */
+static inline void syscall_rollback(struct task_struct *task,
+ struct pt_regs *regs)
+{
+ regs->r1 = regs->r2;
}
#endif /* _ASM_ALPHA_SYSCALL_H */
diff --git a/arch/alpha/include/asm/thread_info.h b/arch/alpha/include/asm/thread_info.h
index 98ccbca64984..1552ecca8520 100644
--- a/arch/alpha/include/asm/thread_info.h
+++ b/arch/alpha/include/asm/thread_info.h
@@ -56,7 +56,8 @@ register unsigned long *current_stack_pointer __asm__ ("$30");
* - pending work-to-be-done flags come first and must be assigned to be
* within bits 0 to 7 to fit in and immediate operand.
*
- * TIF_SYSCALL_TRACE is known to be 0 via blbs.
+ * (Historically TIF_SYSCALL_TRACE was known to be 0 via blbs, but we may
+ * also test multiple bits via masks now.)
*/
#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
#define TIF_NOTIFY_RESUME 1 /* callback before returning to user */
@@ -64,6 +65,8 @@ register unsigned long *current_stack_pointer __asm__ ("$30");
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
#define TIF_SYSCALL_AUDIT 4 /* syscall audit active */
#define TIF_NOTIFY_SIGNAL 5 /* signal notifications exist */
+#define TIF_SECCOMP 6 /* seccomp syscall filtering active */
+#define TIF_SYSCALL_TRACEPOINT 7 /* syscall tracepoint instrumentation */
#define TIF_DIE_IF_KERNEL 9 /* dik recursion lock */
#define TIF_MEMDIE 13 /* is terminating due to OOM killer */
#define TIF_POLLING_NRFLAG 14 /* idle is polling for TIF_NEED_RESCHED */
@@ -74,7 +77,21 @@ register unsigned long *current_stack_pointer __asm__ ("$30");
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
#define _TIF_NOTIFY_SIGNAL (1<<TIF_NOTIFY_SIGNAL)
+#define _TIF_SECCOMP (1<<TIF_SECCOMP)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
+#define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT)
+
+/*
+ * Work to do on syscall entry (in entry.S).
+ * If you want this to exactly mirror what entry.S checks, keep it aligned
+ * with the mask used before branching to syscall_trace_enter().
+ */
+#ifdef CONFIG_AUDITSYSCALL
+# define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP \
+ | _TIF_SYSCALL_TRACEPOINT)
+#else
+# define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT)
+#endif
/* Work to do on interrupt/exception return. */
#define _TIF_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
diff --git a/arch/alpha/include/asm/timex.h b/arch/alpha/include/asm/timex.h
index f89798da8a14..5a71ba6136b9 100644
--- a/arch/alpha/include/asm/timex.h
+++ b/arch/alpha/include/asm/timex.h
@@ -7,10 +7,6 @@
#ifndef _ASMALPHA_TIMEX_H
#define _ASMALPHA_TIMEX_H
-/* With only one or two oddballs, we use the RTC as the ticker, selecting
- the 32.768kHz reference clock, which nicely divides down to our HZ. */
-#define CLOCK_TICK_RATE 32768
-
/*
* Standard way to access the cycle counter.
* Currently only used on SMP for scheduling.
diff --git a/arch/alpha/include/asm/tlb.h b/arch/alpha/include/asm/tlb.h
index 4f79e331af5e..ad586b898fd6 100644
--- a/arch/alpha/include/asm/tlb.h
+++ b/arch/alpha/include/asm/tlb.h
@@ -4,7 +4,7 @@
#include <asm-generic/tlb.h>
-#define __pte_free_tlb(tlb, pte, address) pte_free((tlb)->mm, pte)
-#define __pmd_free_tlb(tlb, pmd, address) pmd_free((tlb)->mm, pmd)
-
+#define __pte_free_tlb(tlb, pte, address) tlb_remove_ptdesc((tlb), page_ptdesc(pte))
+#define __pmd_free_tlb(tlb, pmd, address) tlb_remove_ptdesc((tlb), virt_to_ptdesc(pmd))
+
#endif
diff --git a/arch/alpha/include/asm/tlbflush.h b/arch/alpha/include/asm/tlbflush.h
index ba4b359d6c39..0c8529997f54 100644
--- a/arch/alpha/include/asm/tlbflush.h
+++ b/arch/alpha/include/asm/tlbflush.h
@@ -58,7 +58,9 @@ flush_tlb_other(struct mm_struct *mm)
unsigned long *mmc = &mm->context[smp_processor_id()];
/* Check it's not zero first to avoid cacheline ping pong
when possible. */
- if (*mmc) *mmc = 0;
+
+ if (READ_ONCE(*mmc))
+ WRITE_ONCE(*mmc, 0);
}
#ifndef CONFIG_SMP
diff --git a/arch/alpha/include/asm/xor.h b/arch/alpha/include/asm/xor.h
deleted file mode 100644
index e0de0c233ab9..000000000000
--- a/arch/alpha/include/asm/xor.h
+++ /dev/null
@@ -1,866 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * include/asm-alpha/xor.h
- *
- * Optimized RAID-5 checksumming functions for alpha EV5 and EV6
- */
-
-extern void
-xor_alpha_2(unsigned long bytes, unsigned long * __restrict p1,
- const unsigned long * __restrict p2);
-extern void
-xor_alpha_3(unsigned long bytes, unsigned long * __restrict p1,
- const unsigned long * __restrict p2,
- const unsigned long * __restrict p3);
-extern void
-xor_alpha_4(unsigned long bytes, unsigned long * __restrict p1,
- const unsigned long * __restrict p2,
- const unsigned long * __restrict p3,
- const unsigned long * __restrict p4);
-extern void
-xor_alpha_5(unsigned long bytes, unsigned long * __restrict p1,
- const unsigned long * __restrict p2,
- const unsigned long * __restrict p3,
- const unsigned long * __restrict p4,
- const unsigned long * __restrict p5);
-
-extern void
-xor_alpha_prefetch_2(unsigned long bytes, unsigned long * __restrict p1,
- const unsigned long * __restrict p2);
-extern void
-xor_alpha_prefetch_3(unsigned long bytes, unsigned long * __restrict p1,
- const unsigned long * __restrict p2,
- const unsigned long * __restrict p3);
-extern void
-xor_alpha_prefetch_4(unsigned long bytes, unsigned long * __restrict p1,
- const unsigned long * __restrict p2,
- const unsigned long * __restrict p3,
- const unsigned long * __restrict p4);
-extern void
-xor_alpha_prefetch_5(unsigned long bytes, unsigned long * __restrict p1,
- const unsigned long * __restrict p2,
- const unsigned long * __restrict p3,
- const unsigned long * __restrict p4,
- const unsigned long * __restrict p5);
-
-asm(" \n\
- .text \n\
- .align 3 \n\
- .ent xor_alpha_2 \n\
-xor_alpha_2: \n\
- .prologue 0 \n\
- srl $16, 6, $16 \n\
- .align 4 \n\
-2: \n\
- ldq $0,0($17) \n\
- ldq $1,0($18) \n\
- ldq $2,8($17) \n\
- ldq $3,8($18) \n\
- \n\
- ldq $4,16($17) \n\
- ldq $5,16($18) \n\
- ldq $6,24($17) \n\
- ldq $7,24($18) \n\
- \n\
- ldq $19,32($17) \n\
- ldq $20,32($18) \n\
- ldq $21,40($17) \n\
- ldq $22,40($18) \n\
- \n\
- ldq $23,48($17) \n\
- ldq $24,48($18) \n\
- ldq $25,56($17) \n\
- xor $0,$1,$0 # 7 cycles from $1 load \n\
- \n\
- ldq $27,56($18) \n\
- xor $2,$3,$2 \n\
- stq $0,0($17) \n\
- xor $4,$5,$4 \n\
- \n\
- stq $2,8($17) \n\
- xor $6,$7,$6 \n\
- stq $4,16($17) \n\
- xor $19,$20,$19 \n\
- \n\
- stq $6,24($17) \n\
- xor $21,$22,$21 \n\
- stq $19,32($17) \n\
- xor $23,$24,$23 \n\
- \n\
- stq $21,40($17) \n\
- xor $25,$27,$25 \n\
- stq $23,48($17) \n\
- subq $16,1,$16 \n\
- \n\
- stq $25,56($17) \n\
- addq $17,64,$17 \n\
- addq $18,64,$18 \n\
- bgt $16,2b \n\
- \n\
- ret \n\
- .end xor_alpha_2 \n\
- \n\
- .align 3 \n\
- .ent xor_alpha_3 \n\
-xor_alpha_3: \n\
- .prologue 0 \n\
- srl $16, 6, $16 \n\
- .align 4 \n\
-3: \n\
- ldq $0,0($17) \n\
- ldq $1,0($18) \n\
- ldq $2,0($19) \n\
- ldq $3,8($17) \n\
- \n\
- ldq $4,8($18) \n\
- ldq $6,16($17) \n\
- ldq $7,16($18) \n\
- ldq $21,24($17) \n\
- \n\
- ldq $22,24($18) \n\
- ldq $24,32($17) \n\
- ldq $25,32($18) \n\
- ldq $5,8($19) \n\
- \n\
- ldq $20,16($19) \n\
- ldq $23,24($19) \n\
- ldq $27,32($19) \n\
- nop \n\
- \n\
- xor $0,$1,$1 # 8 cycles from $0 load \n\
- xor $3,$4,$4 # 6 cycles from $4 load \n\
- xor $6,$7,$7 # 6 cycles from $7 load \n\
- xor $21,$22,$22 # 5 cycles from $22 load \n\
- \n\
- xor $1,$2,$2 # 9 cycles from $2 load \n\
- xor $24,$25,$25 # 5 cycles from $25 load \n\
- stq $2,0($17) \n\
- xor $4,$5,$5 # 6 cycles from $5 load \n\
- \n\
- stq $5,8($17) \n\
- xor $7,$20,$20 # 7 cycles from $20 load \n\
- stq $20,16($17) \n\
- xor $22,$23,$23 # 7 cycles from $23 load \n\
- \n\
- stq $23,24($17) \n\
- xor $25,$27,$27 # 7 cycles from $27 load \n\
- stq $27,32($17) \n\
- nop \n\
- \n\
- ldq $0,40($17) \n\
- ldq $1,40($18) \n\
- ldq $3,48($17) \n\
- ldq $4,48($18) \n\
- \n\
- ldq $6,56($17) \n\
- ldq $7,56($18) \n\
- ldq $2,40($19) \n\
- ldq $5,48($19) \n\
- \n\
- ldq $20,56($19) \n\
- xor $0,$1,$1 # 4 cycles from $1 load \n\
- xor $3,$4,$4 # 5 cycles from $4 load \n\
- xor $6,$7,$7 # 5 cycles from $7 load \n\
- \n\
- xor $1,$2,$2 # 4 cycles from $2 load \n\
- xor $4,$5,$5 # 5 cycles from $5 load \n\
- stq $2,40($17) \n\
- xor $7,$20,$20 # 4 cycles from $20 load \n\
- \n\
- stq $5,48($17) \n\
- subq $16,1,$16 \n\
- stq $20,56($17) \n\
- addq $19,64,$19 \n\
- \n\
- addq $18,64,$18 \n\
- addq $17,64,$17 \n\
- bgt $16,3b \n\
- ret \n\
- .end xor_alpha_3 \n\
- \n\
- .align 3 \n\
- .ent xor_alpha_4 \n\
-xor_alpha_4: \n\
- .prologue 0 \n\
- srl $16, 6, $16 \n\
- .align 4 \n\
-4: \n\
- ldq $0,0($17) \n\
- ldq $1,0($18) \n\
- ldq $2,0($19) \n\
- ldq $3,0($20) \n\
- \n\
- ldq $4,8($17) \n\
- ldq $5,8($18) \n\
- ldq $6,8($19) \n\
- ldq $7,8($20) \n\
- \n\
- ldq $21,16($17) \n\
- ldq $22,16($18) \n\
- ldq $23,16($19) \n\
- ldq $24,16($20) \n\
- \n\
- ldq $25,24($17) \n\
- xor $0,$1,$1 # 6 cycles from $1 load \n\
- ldq $27,24($18) \n\
- xor $2,$3,$3 # 6 cycles from $3 load \n\
- \n\
- ldq $0,24($19) \n\
- xor $1,$3,$3 \n\
- ldq $1,24($20) \n\
- xor $4,$5,$5 # 7 cycles from $5 load \n\
- \n\
- stq $3,0($17) \n\
- xor $6,$7,$7 \n\
- xor $21,$22,$22 # 7 cycles from $22 load \n\
- xor $5,$7,$7 \n\
- \n\
- stq $7,8($17) \n\
- xor $23,$24,$24 # 7 cycles from $24 load \n\
- ldq $2,32($17) \n\
- xor $22,$24,$24 \n\
- \n\
- ldq $3,32($18) \n\
- ldq $4,32($19) \n\
- ldq $5,32($20) \n\
- xor $25,$27,$27 # 8 cycles from $27 load \n\
- \n\
- ldq $6,40($17) \n\
- ldq $7,40($18) \n\
- ldq $21,40($19) \n\
- ldq $22,40($20) \n\
- \n\
- stq $24,16($17) \n\
- xor $0,$1,$1 # 9 cycles from $1 load \n\
- xor $2,$3,$3 # 5 cycles from $3 load \n\
- xor $27,$1,$1 \n\
- \n\
- stq $1,24($17) \n\
- xor $4,$5,$5 # 5 cycles from $5 load \n\
- ldq $23,48($17) \n\
- ldq $24,48($18) \n\
- \n\
- ldq $25,48($19) \n\
- xor $3,$5,$5 \n\
- ldq $27,48($20) \n\
- ldq $0,56($17) \n\
- \n\
- ldq $1,56($18) \n\
- ldq $2,56($19) \n\
- xor $6,$7,$7 # 8 cycles from $6 load \n\
- ldq $3,56($20) \n\
- \n\
- stq $5,32($17) \n\
- xor $21,$22,$22 # 8 cycles from $22 load \n\
- xor $7,$22,$22 \n\
- xor $23,$24,$24 # 5 cycles from $24 load \n\
- \n\
- stq $22,40($17) \n\
- xor $25,$27,$27 # 5 cycles from $27 load \n\
- xor $24,$27,$27 \n\
- xor $0,$1,$1 # 5 cycles from $1 load \n\
- \n\
- stq $27,48($17) \n\
- xor $2,$3,$3 # 4 cycles from $3 load \n\
- xor $1,$3,$3 \n\
- subq $16,1,$16 \n\
- \n\
- stq $3,56($17) \n\
- addq $20,64,$20 \n\
- addq $19,64,$19 \n\
- addq $18,64,$18 \n\
- \n\
- addq $17,64,$17 \n\
- bgt $16,4b \n\
- ret \n\
- .end xor_alpha_4 \n\
- \n\
- .align 3 \n\
- .ent xor_alpha_5 \n\
-xor_alpha_5: \n\
- .prologue 0 \n\
- srl $16, 6, $16 \n\
- .align 4 \n\
-5: \n\
- ldq $0,0($17) \n\
- ldq $1,0($18) \n\
- ldq $2,0($19) \n\
- ldq $3,0($20) \n\
- \n\
- ldq $4,0($21) \n\
- ldq $5,8($17) \n\
- ldq $6,8($18) \n\
- ldq $7,8($19) \n\
- \n\
- ldq $22,8($20) \n\
- ldq $23,8($21) \n\
- ldq $24,16($17) \n\
- ldq $25,16($18) \n\
- \n\
- ldq $27,16($19) \n\
- xor $0,$1,$1 # 6 cycles from $1 load \n\
- ldq $28,16($20) \n\
- xor $2,$3,$3 # 6 cycles from $3 load \n\
- \n\
- ldq $0,16($21) \n\
- xor $1,$3,$3 \n\
- ldq $1,24($17) \n\
- xor $3,$4,$4 # 7 cycles from $4 load \n\
- \n\
- stq $4,0($17) \n\
- xor $5,$6,$6 # 7 cycles from $6 load \n\
- xor $7,$22,$22 # 7 cycles from $22 load \n\
- xor $6,$23,$23 # 7 cycles from $23 load \n\
- \n\
- ldq $2,24($18) \n\
- xor $22,$23,$23 \n\
- ldq $3,24($19) \n\
- xor $24,$25,$25 # 8 cycles from $25 load \n\
- \n\
- stq $23,8($17) \n\
- xor $25,$27,$27 # 8 cycles from $27 load \n\
- ldq $4,24($20) \n\
- xor $28,$0,$0 # 7 cycles from $0 load \n\
- \n\
- ldq $5,24($21) \n\
- xor $27,$0,$0 \n\
- ldq $6,32($17) \n\
- ldq $7,32($18) \n\
- \n\
- stq $0,16($17) \n\
- xor $1,$2,$2 # 6 cycles from $2 load \n\
- ldq $22,32($19) \n\
- xor $3,$4,$4 # 4 cycles from $4 load \n\
- \n\
- ldq $23,32($20) \n\
- xor $2,$4,$4 \n\
- ldq $24,32($21) \n\
- ldq $25,40($17) \n\
- \n\
- ldq $27,40($18) \n\
- ldq $28,40($19) \n\
- ldq $0,40($20) \n\
- xor $4,$5,$5 # 7 cycles from $5 load \n\
- \n\
- stq $5,24($17) \n\
- xor $6,$7,$7 # 7 cycles from $7 load \n\
- ldq $1,40($21) \n\
- ldq $2,48($17) \n\
- \n\
- ldq $3,48($18) \n\
- xor $7,$22,$22 # 7 cycles from $22 load \n\
- ldq $4,48($19) \n\
- xor $23,$24,$24 # 6 cycles from $24 load \n\
- \n\
- ldq $5,48($20) \n\
- xor $22,$24,$24 \n\
- ldq $6,48($21) \n\
- xor $25,$27,$27 # 7 cycles from $27 load \n\
- \n\
- stq $24,32($17) \n\
- xor $27,$28,$28 # 8 cycles from $28 load \n\
- ldq $7,56($17) \n\
- xor $0,$1,$1 # 6 cycles from $1 load \n\
- \n\
- ldq $22,56($18) \n\
- ldq $23,56($19) \n\
- ldq $24,56($20) \n\
- ldq $25,56($21) \n\
- \n\
- xor $28,$1,$1 \n\
- xor $2,$3,$3 # 9 cycles from $3 load \n\
- xor $3,$4,$4 # 9 cycles from $4 load \n\
- xor $5,$6,$6 # 8 cycles from $6 load \n\
- \n\
- stq $1,40($17) \n\
- xor $4,$6,$6 \n\
- xor $7,$22,$22 # 7 cycles from $22 load \n\
- xor $23,$24,$24 # 6 cycles from $24 load \n\
- \n\
- stq $6,48($17) \n\
- xor $22,$24,$24 \n\
- subq $16,1,$16 \n\
- xor $24,$25,$25 # 8 cycles from $25 load \n\
- \n\
- stq $25,56($17) \n\
- addq $21,64,$21 \n\
- addq $20,64,$20 \n\
- addq $19,64,$19 \n\
- \n\
- addq $18,64,$18 \n\
- addq $17,64,$17 \n\
- bgt $16,5b \n\
- ret \n\
- .end xor_alpha_5 \n\
- \n\
- .align 3 \n\
- .ent xor_alpha_prefetch_2 \n\
-xor_alpha_prefetch_2: \n\
- .prologue 0 \n\
- srl $16, 6, $16 \n\
- \n\
- ldq $31, 0($17) \n\
- ldq $31, 0($18) \n\
- \n\
- ldq $31, 64($17) \n\
- ldq $31, 64($18) \n\
- \n\
- ldq $31, 128($17) \n\
- ldq $31, 128($18) \n\
- \n\
- ldq $31, 192($17) \n\
- ldq $31, 192($18) \n\
- .align 4 \n\
-2: \n\
- ldq $0,0($17) \n\
- ldq $1,0($18) \n\
- ldq $2,8($17) \n\
- ldq $3,8($18) \n\
- \n\
- ldq $4,16($17) \n\
- ldq $5,16($18) \n\
- ldq $6,24($17) \n\
- ldq $7,24($18) \n\
- \n\
- ldq $19,32($17) \n\
- ldq $20,32($18) \n\
- ldq $21,40($17) \n\
- ldq $22,40($18) \n\
- \n\
- ldq $23,48($17) \n\
- ldq $24,48($18) \n\
- ldq $25,56($17) \n\
- ldq $27,56($18) \n\
- \n\
- ldq $31,256($17) \n\
- xor $0,$1,$0 # 8 cycles from $1 load \n\
- ldq $31,256($18) \n\
- xor $2,$3,$2 \n\
- \n\
- stq $0,0($17) \n\
- xor $4,$5,$4 \n\
- stq $2,8($17) \n\
- xor $6,$7,$6 \n\
- \n\
- stq $4,16($17) \n\
- xor $19,$20,$19 \n\
- stq $6,24($17) \n\
- xor $21,$22,$21 \n\
- \n\
- stq $19,32($17) \n\
- xor $23,$24,$23 \n\
- stq $21,40($17) \n\
- xor $25,$27,$25 \n\
- \n\
- stq $23,48($17) \n\
- subq $16,1,$16 \n\
- stq $25,56($17) \n\
- addq $17,64,$17 \n\
- \n\
- addq $18,64,$18 \n\
- bgt $16,2b \n\
- ret \n\
- .end xor_alpha_prefetch_2 \n\
- \n\
- .align 3 \n\
- .ent xor_alpha_prefetch_3 \n\
-xor_alpha_prefetch_3: \n\
- .prologue 0 \n\
- srl $16, 6, $16 \n\
- \n\
- ldq $31, 0($17) \n\
- ldq $31, 0($18) \n\
- ldq $31, 0($19) \n\
- \n\
- ldq $31, 64($17) \n\
- ldq $31, 64($18) \n\
- ldq $31, 64($19) \n\
- \n\
- ldq $31, 128($17) \n\
- ldq $31, 128($18) \n\
- ldq $31, 128($19) \n\
- \n\
- ldq $31, 192($17) \n\
- ldq $31, 192($18) \n\
- ldq $31, 192($19) \n\
- .align 4 \n\
-3: \n\
- ldq $0,0($17) \n\
- ldq $1,0($18) \n\
- ldq $2,0($19) \n\
- ldq $3,8($17) \n\
- \n\
- ldq $4,8($18) \n\
- ldq $6,16($17) \n\
- ldq $7,16($18) \n\
- ldq $21,24($17) \n\
- \n\
- ldq $22,24($18) \n\
- ldq $24,32($17) \n\
- ldq $25,32($18) \n\
- ldq $5,8($19) \n\
- \n\
- ldq $20,16($19) \n\
- ldq $23,24($19) \n\
- ldq $27,32($19) \n\
- nop \n\
- \n\
- xor $0,$1,$1 # 8 cycles from $0 load \n\
- xor $3,$4,$4 # 7 cycles from $4 load \n\
- xor $6,$7,$7 # 6 cycles from $7 load \n\
- xor $21,$22,$22 # 5 cycles from $22 load \n\
- \n\
- xor $1,$2,$2 # 9 cycles from $2 load \n\
- xor $24,$25,$25 # 5 cycles from $25 load \n\
- stq $2,0($17) \n\
- xor $4,$5,$5 # 6 cycles from $5 load \n\
- \n\
- stq $5,8($17) \n\
- xor $7,$20,$20 # 7 cycles from $20 load \n\
- stq $20,16($17) \n\
- xor $22,$23,$23 # 7 cycles from $23 load \n\
- \n\
- stq $23,24($17) \n\
- xor $25,$27,$27 # 7 cycles from $27 load \n\
- stq $27,32($17) \n\
- nop \n\
- \n\
- ldq $0,40($17) \n\
- ldq $1,40($18) \n\
- ldq $3,48($17) \n\
- ldq $4,48($18) \n\
- \n\
- ldq $6,56($17) \n\
- ldq $7,56($18) \n\
- ldq $2,40($19) \n\
- ldq $5,48($19) \n\
- \n\
- ldq $20,56($19) \n\
- ldq $31,256($17) \n\
- ldq $31,256($18) \n\
- ldq $31,256($19) \n\
- \n\
- xor $0,$1,$1 # 6 cycles from $1 load \n\
- xor $3,$4,$4 # 5 cycles from $4 load \n\
- xor $6,$7,$7 # 5 cycles from $7 load \n\
- xor $1,$2,$2 # 4 cycles from $2 load \n\
- \n\
- xor $4,$5,$5 # 5 cycles from $5 load \n\
- xor $7,$20,$20 # 4 cycles from $20 load \n\
- stq $2,40($17) \n\
- subq $16,1,$16 \n\
- \n\
- stq $5,48($17) \n\
- addq $19,64,$19 \n\
- stq $20,56($17) \n\
- addq $18,64,$18 \n\
- \n\
- addq $17,64,$17 \n\
- bgt $16,3b \n\
- ret \n\
- .end xor_alpha_prefetch_3 \n\
- \n\
- .align 3 \n\
- .ent xor_alpha_prefetch_4 \n\
-xor_alpha_prefetch_4: \n\
- .prologue 0 \n\
- srl $16, 6, $16 \n\
- \n\
- ldq $31, 0($17) \n\
- ldq $31, 0($18) \n\
- ldq $31, 0($19) \n\
- ldq $31, 0($20) \n\
- \n\
- ldq $31, 64($17) \n\
- ldq $31, 64($18) \n\
- ldq $31, 64($19) \n\
- ldq $31, 64($20) \n\
- \n\
- ldq $31, 128($17) \n\
- ldq $31, 128($18) \n\
- ldq $31, 128($19) \n\
- ldq $31, 128($20) \n\
- \n\
- ldq $31, 192($17) \n\
- ldq $31, 192($18) \n\
- ldq $31, 192($19) \n\
- ldq $31, 192($20) \n\
- .align 4 \n\
-4: \n\
- ldq $0,0($17) \n\
- ldq $1,0($18) \n\
- ldq $2,0($19) \n\
- ldq $3,0($20) \n\
- \n\
- ldq $4,8($17) \n\
- ldq $5,8($18) \n\
- ldq $6,8($19) \n\
- ldq $7,8($20) \n\
- \n\
- ldq $21,16($17) \n\
- ldq $22,16($18) \n\
- ldq $23,16($19) \n\
- ldq $24,16($20) \n\
- \n\
- ldq $25,24($17) \n\
- xor $0,$1,$1 # 6 cycles from $1 load \n\
- ldq $27,24($18) \n\
- xor $2,$3,$3 # 6 cycles from $3 load \n\
- \n\
- ldq $0,24($19) \n\
- xor $1,$3,$3 \n\
- ldq $1,24($20) \n\
- xor $4,$5,$5 # 7 cycles from $5 load \n\
- \n\
- stq $3,0($17) \n\
- xor $6,$7,$7 \n\
- xor $21,$22,$22 # 7 cycles from $22 load \n\
- xor $5,$7,$7 \n\
- \n\
- stq $7,8($17) \n\
- xor $23,$24,$24 # 7 cycles from $24 load \n\
- ldq $2,32($17) \n\
- xor $22,$24,$24 \n\
- \n\
- ldq $3,32($18) \n\
- ldq $4,32($19) \n\
- ldq $5,32($20) \n\
- xor $25,$27,$27 # 8 cycles from $27 load \n\
- \n\
- ldq $6,40($17) \n\
- ldq $7,40($18) \n\
- ldq $21,40($19) \n\
- ldq $22,40($20) \n\
- \n\
- stq $24,16($17) \n\
- xor $0,$1,$1 # 9 cycles from $1 load \n\
- xor $2,$3,$3 # 5 cycles from $3 load \n\
- xor $27,$1,$1 \n\
- \n\
- stq $1,24($17) \n\
- xor $4,$5,$5 # 5 cycles from $5 load \n\
- ldq $23,48($17) \n\
- xor $3,$5,$5 \n\
- \n\
- ldq $24,48($18) \n\
- ldq $25,48($19) \n\
- ldq $27,48($20) \n\
- ldq $0,56($17) \n\
- \n\
- ldq $1,56($18) \n\
- ldq $2,56($19) \n\
- ldq $3,56($20) \n\
- xor $6,$7,$7 # 8 cycles from $6 load \n\
- \n\
- ldq $31,256($17) \n\
- xor $21,$22,$22 # 8 cycles from $22 load \n\
- ldq $31,256($18) \n\
- xor $7,$22,$22 \n\
- \n\
- ldq $31,256($19) \n\
- xor $23,$24,$24 # 6 cycles from $24 load \n\
- ldq $31,256($20) \n\
- xor $25,$27,$27 # 6 cycles from $27 load \n\
- \n\
- stq $5,32($17) \n\
- xor $24,$27,$27 \n\
- xor $0,$1,$1 # 7 cycles from $1 load \n\
- xor $2,$3,$3 # 6 cycles from $3 load \n\
- \n\
- stq $22,40($17) \n\
- xor $1,$3,$3 \n\
- stq $27,48($17) \n\
- subq $16,1,$16 \n\
- \n\
- stq $3,56($17) \n\
- addq $20,64,$20 \n\
- addq $19,64,$19 \n\
- addq $18,64,$18 \n\
- \n\
- addq $17,64,$17 \n\
- bgt $16,4b \n\
- ret \n\
- .end xor_alpha_prefetch_4 \n\
- \n\
- .align 3 \n\
- .ent xor_alpha_prefetch_5 \n\
-xor_alpha_prefetch_5: \n\
- .prologue 0 \n\
- srl $16, 6, $16 \n\
- \n\
- ldq $31, 0($17) \n\
- ldq $31, 0($18) \n\
- ldq $31, 0($19) \n\
- ldq $31, 0($20) \n\
- ldq $31, 0($21) \n\
- \n\
- ldq $31, 64($17) \n\
- ldq $31, 64($18) \n\
- ldq $31, 64($19) \n\
- ldq $31, 64($20) \n\
- ldq $31, 64($21) \n\
- \n\
- ldq $31, 128($17) \n\
- ldq $31, 128($18) \n\
- ldq $31, 128($19) \n\
- ldq $31, 128($20) \n\
- ldq $31, 128($21) \n\
- \n\
- ldq $31, 192($17) \n\
- ldq $31, 192($18) \n\
- ldq $31, 192($19) \n\
- ldq $31, 192($20) \n\
- ldq $31, 192($21) \n\
- .align 4 \n\
-5: \n\
- ldq $0,0($17) \n\
- ldq $1,0($18) \n\
- ldq $2,0($19) \n\
- ldq $3,0($20) \n\
- \n\
- ldq $4,0($21) \n\
- ldq $5,8($17) \n\
- ldq $6,8($18) \n\
- ldq $7,8($19) \n\
- \n\
- ldq $22,8($20) \n\
- ldq $23,8($21) \n\
- ldq $24,16($17) \n\
- ldq $25,16($18) \n\
- \n\
- ldq $27,16($19) \n\
- xor $0,$1,$1 # 6 cycles from $1 load \n\
- ldq $28,16($20) \n\
- xor $2,$3,$3 # 6 cycles from $3 load \n\
- \n\
- ldq $0,16($21) \n\
- xor $1,$3,$3 \n\
- ldq $1,24($17) \n\
- xor $3,$4,$4 # 7 cycles from $4 load \n\
- \n\
- stq $4,0($17) \n\
- xor $5,$6,$6 # 7 cycles from $6 load \n\
- xor $7,$22,$22 # 7 cycles from $22 load \n\
- xor $6,$23,$23 # 7 cycles from $23 load \n\
- \n\
- ldq $2,24($18) \n\
- xor $22,$23,$23 \n\
- ldq $3,24($19) \n\
- xor $24,$25,$25 # 8 cycles from $25 load \n\
- \n\
- stq $23,8($17) \n\
- xor $25,$27,$27 # 8 cycles from $27 load \n\
- ldq $4,24($20) \n\
- xor $28,$0,$0 # 7 cycles from $0 load \n\
- \n\
- ldq $5,24($21) \n\
- xor $27,$0,$0 \n\
- ldq $6,32($17) \n\
- ldq $7,32($18) \n\
- \n\
- stq $0,16($17) \n\
- xor $1,$2,$2 # 6 cycles from $2 load \n\
- ldq $22,32($19) \n\
- xor $3,$4,$4 # 4 cycles from $4 load \n\
- \n\
- ldq $23,32($20) \n\
- xor $2,$4,$4 \n\
- ldq $24,32($21) \n\
- ldq $25,40($17) \n\
- \n\
- ldq $27,40($18) \n\
- ldq $28,40($19) \n\
- ldq $0,40($20) \n\
- xor $4,$5,$5 # 7 cycles from $5 load \n\
- \n\
- stq $5,24($17) \n\
- xor $6,$7,$7 # 7 cycles from $7 load \n\
- ldq $1,40($21) \n\
- ldq $2,48($17) \n\
- \n\
- ldq $3,48($18) \n\
- xor $7,$22,$22 # 7 cycles from $22 load \n\
- ldq $4,48($19) \n\
- xor $23,$24,$24 # 6 cycles from $24 load \n\
- \n\
- ldq $5,48($20) \n\
- xor $22,$24,$24 \n\
- ldq $6,48($21) \n\
- xor $25,$27,$27 # 7 cycles from $27 load \n\
- \n\
- stq $24,32($17) \n\
- xor $27,$28,$28 # 8 cycles from $28 load \n\
- ldq $7,56($17) \n\
- xor $0,$1,$1 # 6 cycles from $1 load \n\
- \n\
- ldq $22,56($18) \n\
- ldq $23,56($19) \n\
- ldq $24,56($20) \n\
- ldq $25,56($21) \n\
- \n\
- ldq $31,256($17) \n\
- xor $28,$1,$1 \n\
- ldq $31,256($18) \n\
- xor $2,$3,$3 # 9 cycles from $3 load \n\
- \n\
- ldq $31,256($19) \n\
- xor $3,$4,$4 # 9 cycles from $4 load \n\
- ldq $31,256($20) \n\
- xor $5,$6,$6 # 8 cycles from $6 load \n\
- \n\
- stq $1,40($17) \n\
- xor $4,$6,$6 \n\
- xor $7,$22,$22 # 7 cycles from $22 load \n\
- xor $23,$24,$24 # 6 cycles from $24 load \n\
- \n\
- stq $6,48($17) \n\
- xor $22,$24,$24 \n\
- ldq $31,256($21) \n\
- xor $24,$25,$25 # 8 cycles from $25 load \n\
- \n\
- stq $25,56($17) \n\
- subq $16,1,$16 \n\
- addq $21,64,$21 \n\
- addq $20,64,$20 \n\
- \n\
- addq $19,64,$19 \n\
- addq $18,64,$18 \n\
- addq $17,64,$17 \n\
- bgt $16,5b \n\
- \n\
- ret \n\
- .end xor_alpha_prefetch_5 \n\
-");
-
-static struct xor_block_template xor_block_alpha = {
- .name = "alpha",
- .do_2 = xor_alpha_2,
- .do_3 = xor_alpha_3,
- .do_4 = xor_alpha_4,
- .do_5 = xor_alpha_5,
-};
-
-static struct xor_block_template xor_block_alpha_prefetch = {
- .name = "alpha prefetch",
- .do_2 = xor_alpha_prefetch_2,
- .do_3 = xor_alpha_prefetch_3,
- .do_4 = xor_alpha_prefetch_4,
- .do_5 = xor_alpha_prefetch_5,
-};
-
-/* For grins, also test the generic routines. */
-#include <asm-generic/xor.h>
-
-#undef XOR_TRY_TEMPLATES
-#define XOR_TRY_TEMPLATES \
- do { \
- xor_speed(&xor_block_8regs); \
- xor_speed(&xor_block_32regs); \
- xor_speed(&xor_block_alpha); \
- xor_speed(&xor_block_alpha_prefetch); \
- } while (0)
-
-/* Force the use of alpha_prefetch if EV6, as it is significantly
- faster in the cold cache case. */
-#define XOR_SELECT_TEMPLATE(FASTEST) \
- (implver() == IMPLVER_EV6 ? &xor_block_alpha_prefetch : FASTEST)
diff --git a/arch/alpha/include/uapi/asm/errno.h b/arch/alpha/include/uapi/asm/errno.h
index 3d265f6babaf..1a99f38813c7 100644
--- a/arch/alpha/include/uapi/asm/errno.h
+++ b/arch/alpha/include/uapi/asm/errno.h
@@ -55,6 +55,7 @@
#define ENOSR 82 /* Out of streams resources */
#define ETIME 83 /* Timer expired */
#define EBADMSG 84 /* Not a data message */
+#define EFSBADCRC EBADMSG /* Bad CRC detected */
#define EPROTO 85 /* Protocol error */
#define ENODATA 86 /* No data available */
#define ENOSTR 87 /* Device not a stream */
@@ -96,6 +97,7 @@
#define EREMCHG 115 /* Remote address changed */
#define EUCLEAN 117 /* Structure needs cleaning */
+#define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */
#define ENOTNAM 118 /* Not a XENIX named type file */
#define ENAVAIL 119 /* No XENIX semaphores available */
#define EISNAM 120 /* Is a named type file */
@@ -125,4 +127,6 @@
#define EHWPOISON 139 /* Memory page has hardware error */
+#define EFTYPE 140 /* Wrong file type for the intended operation */
+
#endif
diff --git a/arch/alpha/include/uapi/asm/fcntl.h b/arch/alpha/include/uapi/asm/fcntl.h
index 50bdc8e8a271..c7e1c5cf646d 100644
--- a/arch/alpha/include/uapi/asm/fcntl.h
+++ b/arch/alpha/include/uapi/asm/fcntl.h
@@ -2,20 +2,20 @@
#ifndef _ALPHA_FCNTL_H
#define _ALPHA_FCNTL_H
-#define O_CREAT 01000 /* not fcntl */
-#define O_TRUNC 02000 /* not fcntl */
-#define O_EXCL 04000 /* not fcntl */
-#define O_NOCTTY 010000 /* not fcntl */
-
-#define O_NONBLOCK 00004
-#define O_APPEND 00010
-#define O_DSYNC 040000 /* used to be O_SYNC, see below */
-#define O_DIRECTORY 0100000 /* must be a directory */
-#define O_NOFOLLOW 0200000 /* don't follow links */
-#define O_LARGEFILE 0400000 /* will be set by the kernel on every open */
-#define O_DIRECT 02000000 /* direct disk access - should check with OSF/1 */
-#define O_NOATIME 04000000
-#define O_CLOEXEC 010000000 /* set close_on_exec */
+#define O_CREAT (1 << 9) /* not fcntl */
+#define O_TRUNC (1 << 10) /* not fcntl */
+#define O_EXCL (1 << 11) /* not fcntl */
+#define O_NOCTTY (1 << 12) /* not fcntl */
+
+#define O_NONBLOCK (1 << 2)
+#define O_APPEND (1 << 3)
+#define O_DSYNC (1 << 14) /* used to be O_SYNC, see below */
+#define O_DIRECTORY (1 << 15) /* must be a directory */
+#define O_NOFOLLOW (1 << 16) /* don't follow links */
+#define O_LARGEFILE (1 << 17) /* will be set by the kernel on every open */
+#define O_DIRECT (1 << 19) /* direct disk access - should check with OSF/1 */
+#define O_NOATIME (1 << 20)
+#define O_CLOEXEC (1 << 21) /* set close_on_exec */
/*
* Before Linux 2.6.33 only O_DSYNC semantics were implemented, but using
* the O_SYNC flag. We continue to use the existing numerical value
@@ -29,11 +29,11 @@
*
* Note: __O_SYNC must never be used directly.
*/
-#define __O_SYNC 020000000
+#define __O_SYNC (1 << 22)
#define O_SYNC (__O_SYNC|O_DSYNC)
-#define O_PATH 040000000
-#define __O_TMPFILE 0100000000
+#define O_PATH (1 << 23)
+#define __O_TMPFILE (1 << 24)
#define F_GETLK 7
#define F_SETLK 8
diff --git a/arch/alpha/include/uapi/asm/fpu.h b/arch/alpha/include/uapi/asm/fpu.h
index cea9eafa056f..d28dc36786e2 100644
--- a/arch/alpha/include/uapi/asm/fpu.h
+++ b/arch/alpha/include/uapi/asm/fpu.h
@@ -101,7 +101,12 @@ ieee_swcr_to_fpcr(unsigned long sw)
| IEEE_TRAP_ENABLE_OVF)) << 48;
fp |= (~sw & (IEEE_TRAP_ENABLE_UNF | IEEE_TRAP_ENABLE_INE)) << 57;
fp |= (sw & IEEE_MAP_UMZ ? FPCR_UNDZ | FPCR_UNFD : 0);
- fp |= (~sw & IEEE_TRAP_ENABLE_DNO) << 41;
+ /*
+ * Disable denormal operand traps only when denormal inputs are to be
+ * flushed to zero. Otherwise they must keep trapping, so that /S
+ * instructions reach the kernel emulation handler.
+ */
+ fp |= (sw & IEEE_MAP_DMZ ? FPCR_DNOD : 0);
return fp;
}
@@ -116,7 +121,6 @@ ieee_fpcr_to_swcr(unsigned long fp)
| IEEE_TRAP_ENABLE_OVF);
sw |= (~fp >> 57) & (IEEE_TRAP_ENABLE_UNF | IEEE_TRAP_ENABLE_INE);
sw |= (fp >> 47) & IEEE_MAP_UMZ;
- sw |= (~fp >> 41) & IEEE_TRAP_ENABLE_DNO;
return sw;
}
diff --git a/arch/alpha/include/uapi/asm/ptrace.h b/arch/alpha/include/uapi/asm/ptrace.h
index 72ed913a910f..9d86b2a1526e 100644
--- a/arch/alpha/include/uapi/asm/ptrace.h
+++ b/arch/alpha/include/uapi/asm/ptrace.h
@@ -43,7 +43,7 @@ struct pt_regs {
unsigned long trap_a1;
unsigned long trap_a2;
/* This makes the stack 16-byte aligned as GCC expects */
- unsigned long __pad0;
+ unsigned long usp;
/* These are saved by PAL-code: */
unsigned long ps;
unsigned long pc;
diff --git a/arch/alpha/include/uapi/asm/socket.h b/arch/alpha/include/uapi/asm/socket.h
index 5ef57f88df6b..946a5fad2691 100644
--- a/arch/alpha/include/uapi/asm/socket.h
+++ b/arch/alpha/include/uapi/asm/socket.h
@@ -155,6 +155,8 @@
#define SO_INQ 84
#define SCM_INQ SO_INQ
+#define SO_RIGHTS_NOTRUNC 85
+
#if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64
diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile
index 187cd8df2faf..4ea5c189e60e 100644
--- a/arch/alpha/kernel/Makefile
+++ b/arch/alpha/kernel/Makefile
@@ -9,7 +9,8 @@ ccflags-y := -Wno-sign-compare
obj-y := head.o entry.o traps.o process.o osf_sys.o irq.o \
irq_alpha.o signal.o setup.o ptrace.o time.o \
- systbls.o err_common.o io.o bugs.o termios.o
+ systbls.o err_common.o io.o bugs.o termios.o \
+ stacktrace.o
obj-$(CONFIG_VGA_HOSE) += console.o
obj-$(CONFIG_SMP) += smp.o
diff --git a/arch/alpha/kernel/asm-offsets.c b/arch/alpha/kernel/asm-offsets.c
index 1ebb05890499..1d3bfca319ae 100644
--- a/arch/alpha/kernel/asm-offsets.c
+++ b/arch/alpha/kernel/asm-offsets.c
@@ -29,4 +29,5 @@ static void __used foo(void)
DEFINE(HAE_CACHE, offsetof(struct alpha_machine_vector, hae_cache));
DEFINE(HAE_REG, offsetof(struct alpha_machine_vector, hae_register));
+ DEFINE(PT_REGS_USP, offsetof(struct pt_regs, usp));
}
diff --git a/arch/alpha/kernel/core_marvel.c b/arch/alpha/kernel/core_marvel.c
index d38f4d6759e4..92e3312e786e 100644
--- a/arch/alpha/kernel/core_marvel.c
+++ b/arch/alpha/kernel/core_marvel.c
@@ -861,7 +861,7 @@ marvel_agp_setup(alpha_agp_info *agp)
if (!alpha_agpgart_size)
return -ENOMEM;
- aper = kmalloc(sizeof(*aper), GFP_KERNEL);
+ aper = kmalloc_obj(*aper);
if (aper == NULL) return -ENOMEM;
aper->arena = agp->hose->sg_pci;
@@ -1059,7 +1059,7 @@ marvel_agp_info(void)
/*
* Allocate the info structure.
*/
- agp = kmalloc(sizeof(*agp), GFP_KERNEL);
+ agp = kmalloc_obj(*agp);
if (!agp)
return NULL;
diff --git a/arch/alpha/kernel/core_titan.c b/arch/alpha/kernel/core_titan.c
index 77f5d68ed04b..6b6b9e6d631f 100644
--- a/arch/alpha/kernel/core_titan.c
+++ b/arch/alpha/kernel/core_titan.c
@@ -594,7 +594,7 @@ titan_agp_setup(alpha_agp_info *agp)
if (!alpha_agpgart_size)
return -ENOMEM;
- aper = kmalloc(sizeof(struct titan_agp_aperture), GFP_KERNEL);
+ aper = kmalloc_obj(struct titan_agp_aperture);
if (aper == NULL)
return -ENOMEM;
@@ -760,7 +760,7 @@ titan_agp_info(void)
/*
* Allocate the info structure.
*/
- agp = kmalloc(sizeof(*agp), GFP_KERNEL);
+ agp = kmalloc_obj(*agp);
if (!agp)
return NULL;
diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S
index f4d41b4538c2..9f2608de2544 100644
--- a/arch/alpha/kernel/entry.S
+++ b/arch/alpha/kernel/entry.S
@@ -10,6 +10,7 @@
#include <asm/pal.h>
#include <asm/errno.h>
#include <asm/unistd.h>
+#include <linux/errno.h>
.text
.set noat
@@ -36,6 +37,77 @@
.endm
/*
+ * SYSCALL_SKIP_RETURN_RESTART_GATE
+ *
+ * Used when syscall dispatch is skipped (seccomp/ptrace injected nr=-1).
+ * - Ensure we never return r0==-1 with a3==0 (success); convert to ENOSYS.
+ * - Gate whether syscall restart is allowed by preserving restart context
+ * only for ERESTART* returns. Result:
+ * $26 = 0 => restart allowed
+ * $26 = 1 => restart NOT allowed
+ * $18 = preserved syscall nr (regs->r2) if restart allowed, else 0
+ */
+.macro SYSCALL_SKIP_RETURN_RESTART_GATE
+ /* Fix up invalid "-1 success" return state. */
+ ldq $19, 72($sp) /* a3 */
+ bne $19, 1f /* already error => skip fixup */
+
+ ldq $20, 0($sp) /* r0 */
+ lda $21, -1($31)
+ cmpeq $20, $21, $22
+ beq $22, 1f /* r0 != -1 => skip fixup */
+
+
+ lda $20, ENOSYS($31)
+ stq $20, 0($sp) /* r0 = ENOSYS */
+ lda $19, 1($31)
+ stq $19, 72($sp) /* a3 = 1 */
+1:
+ /* Restart gating: success is never restartable here. */
+ ldq $19, 72($sp) /* a3 */
+ beq $19, 3f /* success => not restartable */
+
+ ldq $20, 0($sp) /* r0 (positive errno if a3==1) */
+ lda $21, ERESTARTSYS($31)
+ cmpeq $20, $21, $22
+ bne $22, 2f
+ lda $21, ERESTARTNOINTR($31)
+ cmpeq $20, $21, $22
+ bne $22, 2f
+ lda $21, ERESTARTNOHAND($31)
+ cmpeq $20, $21, $22
+ bne $22, 2f
+ lda $21, ERESTART_RESTARTBLOCK($31)
+ cmpeq $20, $21, $22
+ bne $22, 2f
+
+3: /* Not a restart code (or success) => restart NOT allowed. */
+ addq $31, 1, $26 /* $26=1 => restart NOT allowed */
+ mov 0, $18
+ br 4f
+
+2: /* Restart allowed. */
+ ldq $18, 16($sp) /* preserved syscall nr (regs->r2) */
+ mov $31, $26 /* $26=0 => restart allowed */
+ br 4f
+4:
+.endm
+
+.macro LOCKDEP_HARDIRQS_ON_RESTORE
+#ifdef CONFIG_PROVE_LOCKING
+ /* a0 = saved PS */
+ ldq $16, SP_OFF($sp)
+
+ /* a1 = callsite IP for lockdep */
+ lda $17, 1f
+
+ jsr $26, lockdep_on_restore
+ ldgp $gp, 0($26)
+1:
+#endif
+.endm
+
+/*
* This defines the normal kernel pt-regs layout.
*
* regs 9-15 preserved by C code
@@ -368,6 +440,7 @@ CFI_START_OSF_FRAME entUna
.cfi_restore $28
.cfi_restore $29
.cfi_adjust_cfa_offset -256
+ LOCKDEP_HARDIRQS_ON_RESTORE
call_pal PAL_rti
.align 4
@@ -425,7 +498,7 @@ CFI_START_OSF_FRAME entDbg
mov $sp, $16
jsr $31, do_entDbg
CFI_END_OSF_FRAME entDbg
-
+
/*
* The system call entry point is special. Most importantly, it looks
* like a function call to userspace as far as clobbered registers. We
@@ -435,6 +508,17 @@ CFI_END_OSF_FRAME entDbg
* So much for theory. We don't take advantage of this yet.
*
* Note that a0-a2 are not saved by PALcode as with the other entry points.
+ *
+ * Alpha syscall ABI uses:
+ * - r0 for return value
+ * - r19 ("a3") as error indicator (0=success, 1=error; r0 holds errno)
+ *
+ * For seccomp/ptrace/generic syscall helpers we track the syscall
+ * number separately:
+ * - regs->r1: current (mutable) syscall number (may be changed or set to -1)
+ * - regs->r2: original syscall number for restart/rollback
+ *
+ * On entry PAL provides the syscall number in r0; copy it into r1/r2.
*/
.align 4
@@ -447,6 +531,16 @@ CFI_END_OSF_FRAME entDbg
.cfi_rel_offset $gp, 16
entSys:
SAVE_ALL
+ ldq $1, 0($sp) /* syscall nr from saved r0 */
+ stq $1, 8($sp) /* regs->r1 = shadow syscall nr */
+ stq $1, 16($sp) /* regs->r2 = restart syscall nr */
+ /* Syscalls always enter from user mode: snapshot USP into pt_regs->usp */
+ mov $0, $8
+ call_pal PAL_rdusp
+ stq $0, PT_REGS_USP($sp)
+ mov $8, $0
+
+
lda $8, 0x3fff
bic $sp, $8, $8
lda $4, NR_syscalls($31)
@@ -461,16 +555,15 @@ entSys:
.cfi_rel_offset $16, SP_OFF+24
.cfi_rel_offset $17, SP_OFF+32
.cfi_rel_offset $18, SP_OFF+40
-#ifdef CONFIG_AUDITSYSCALL
- lda $6, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT
+ lda $6, _TIF_SYSCALL_WORK
and $3, $6, $3
bne $3, strace
-#else
- blbs $3, strace /* check for SYSCALL_TRACE in disguise */
-#endif
+
beq $4, 1f
ldq $27, 0($5)
-1: jsr $26, ($27), sys_ni_syscall
+1: ldq $0, 8($sp) /* syscall nr shadow (regs->r1) */
+
+ jsr $26, ($27), sys_ni_syscall
ldgp $gp, 0($26)
blt $0, $syscall_error /* the call failed */
$ret_success:
@@ -498,6 +591,7 @@ restore_all:
bne $3, restore_fpu
restore_other:
.cfi_remember_state
+ LOCKDEP_HARDIRQS_ON_RESTORE
RESTORE_ALL
call_pal PAL_rti
@@ -509,15 +603,8 @@ ret_to_kernel:
.align 3
$syscall_error:
- /*
- * Some system calls (e.g., ptrace) can return arbitrary
- * values which might normally be mistaken as error numbers.
- * Those functions must zero $0 (v0) directly in the stack
- * frame to indicate that a negative return value wasn't an
- * error number..
- */
- ldq $18, 0($sp) /* old syscall nr (zero if success) */
- beq $18, $ret_success
+ /* Restart syscall nr comes from saved r2 (preserved even if r0 overwritten). */
+ ldq $18, 16($sp) /* old syscall nr for restart */
ldq $19, 72($sp) /* .. and this a3 */
subq $31, $0, $0 /* with error in v0 */
@@ -550,7 +637,7 @@ $work_resched:
* or got through work_notifysig already. Either case means no syscall
* restarts for us, so let $18 and $19 burn.
*/
- jsr $26, schedule
+ jsr $26, alpha_schedule_user_work
mov 0, $18
br ret_to_user
@@ -581,6 +668,8 @@ strace:
jsr $26, syscall_trace_enter /* returns the syscall number */
UNDO_SWITCH_STACK
+ stq $0, 8($sp) /* regs->r1 = shadow syscall nr */
+
/* get the arguments back.. */
ldq $16, SP_OFF+24($sp)
ldq $17, SP_OFF+32($sp)
@@ -589,6 +678,11 @@ strace:
ldq $20, 80($sp)
ldq $21, 88($sp)
+ /* nr == -1: internal skip-dispatch or userspace syscall(-1)? */
+ lda $6, -1($31)
+ cmpeq $0, $6, $6
+ bne $6, $strace_skip_call /* nr == -1 => dispatch */
+
/* get the system call pointer.. */
lda $1, NR_syscalls($31)
lda $2, sys_call_table
@@ -607,6 +701,8 @@ $strace_success:
stq $31, 72($sp) /* a3=0 => no error */
stq $0, 0($sp) /* save return value */
+$strace_skip_call:
+ SYSCALL_SKIP_RETURN_RESTART_GATE
DO_SWITCH_STACK
jsr $26, syscall_trace_leave
UNDO_SWITCH_STACK
@@ -614,8 +710,7 @@ $strace_success:
.align 3
$strace_error:
- ldq $18, 0($sp) /* old syscall nr (zero if success) */
- beq $18, $strace_success
+ ldq $18, 16($sp) /* restart syscall nr */
ldq $19, 72($sp) /* .. and this a3 */
subq $31, $0, $0 /* with error in v0 */
@@ -634,7 +729,7 @@ $strace_error:
mov $31, $26 /* tell "ret_from_sys_call" we can restart */
br ret_from_sys_call
CFI_END_OSF_FRAME entSys
-
+
/*
* Save and restore the switch stack -- aka the balance of the user context.
*/
diff --git a/arch/alpha/kernel/io.c b/arch/alpha/kernel/io.c
index c28035d6d1e6..2bad1b4fb240 100644
--- a/arch/alpha/kernel/io.c
+++ b/arch/alpha/kernel/io.c
@@ -647,7 +647,7 @@ void _memset_c_io(volatile void __iomem *to, unsigned long c, long count)
EXPORT_SYMBOL(_memset_c_io);
-#if IS_ENABLED(CONFIG_VGA_CONSOLE) || IS_ENABLED(CONFIG_MDA_CONSOLE)
+#if IS_ENABLED(CONFIG_VGA_CONSOLE)
#include <asm/vga.h>
diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c
index c67047c5d830..4a6a8b1d5a8b 100644
--- a/arch/alpha/kernel/irq.c
+++ b/arch/alpha/kernel/irq.c
@@ -72,16 +72,16 @@ int arch_show_interrupts(struct seq_file *p, int prec)
int j;
#ifdef CONFIG_SMP
- seq_puts(p, "IPI: ");
+ seq_puts(p, " IPI: ");
for_each_online_cpu(j)
seq_printf(p, "%10lu ", cpu_data[j].ipi_count);
seq_putc(p, '\n');
#endif
- seq_puts(p, "PMI: ");
+ seq_puts(p, " PMI: ");
for_each_online_cpu(j)
seq_printf(p, "%10lu ", per_cpu(irq_pmi_count, j));
- seq_puts(p, " Performance Monitoring\n");
- seq_printf(p, "ERR: %10lu\n", irq_err_count);
+ seq_puts(p, " Performance Monitoring\n");
+ seq_printf(p, " ERR: %10lu\n", irq_err_count);
return 0;
}
diff --git a/arch/alpha/kernel/irq_alpha.c b/arch/alpha/kernel/irq_alpha.c
index d17e44c99df9..1b799aafb7dc 100644
--- a/arch/alpha/kernel/irq_alpha.c
+++ b/arch/alpha/kernel/irq_alpha.c
@@ -41,7 +41,7 @@ EXPORT_SYMBOL(perf_irq);
* The main interrupt entry point.
*/
-asmlinkage void
+asmlinkage void
do_entInt(unsigned long type, unsigned long vector,
unsigned long la_ptr, struct pt_regs *regs)
{
@@ -52,42 +52,91 @@ do_entInt(unsigned long type, unsigned long vector,
* Note that there is no matching local_irq_enable() due to
* severe problems with RTI at IPL0 and some MILO PALcode
* (namely LX164).
+ *
+ * PALcode has already raised PS.IPL to the level of the interrupt
+ * being delivered. For an IPL 7 entry - a machine check or a system
+ * event - that is IPL_MAX, which is what arch_irqs_disabled() tests
+ * for, so local_irq_disable() would decide interrupts were already
+ * off and skip trace_hardirqs_off(). lockdep would then spend the
+ * whole handler believing interrupts are enabled. Drive the
+ * annotation from lockdep's own state rather than the hardware IPL.
*/
- local_irq_disable();
+ raw_local_irq_disable();
+ if (lockdep_hardirqs_enabled())
+ trace_hardirqs_off();
+
+ old_regs = set_irq_regs(regs);
+
switch (type) {
case 0:
#ifdef CONFIG_SMP
+ irq_enter();
handle_ipi(regs);
- return;
+ irq_exit();
+ break;
#else
irq_err_count++;
- printk(KERN_CRIT "Interprocessor interrupt? "
- "You must be kidding!\n");
-#endif
+ pr_crit("Interprocessor interrupt? You must be kidding!\n");
break;
+#endif
case 1:
- old_regs = set_irq_regs(regs);
+ /* handle_irq() already does irq_enter()/irq_exit() */
handle_irq(RTC_IRQ);
- set_irq_regs(old_regs);
- return;
+ break;
case 2:
- old_regs = set_irq_regs(regs);
+ irq_enter();
alpha_mv.machine_check(vector, la_ptr);
- set_irq_regs(old_regs);
- return;
+ irq_exit();
+ break;
case 3:
- old_regs = set_irq_regs(regs);
+ irq_enter();
alpha_mv.device_interrupt(vector);
- set_irq_regs(old_regs);
- return;
+ irq_exit();
+ break;
case 4:
+ irq_enter();
perf_irq(la_ptr, regs);
- return;
+ irq_exit();
+ break;
default:
- printk(KERN_CRIT "Hardware intr %ld %lx? Huh?\n",
- type, vector);
+ pr_crit("Hardware intr %lu %lx? Huh?\n", type, vector);
+ pr_crit("PC = %016lx PS=%04lx\n", regs->pc, regs->ps);
+ break;
}
- printk(KERN_CRIT "PC = %016lx PS=%04lx\n", regs->pc, regs->ps);
+
+ set_irq_regs(old_regs);
+
+ /*
+ * Intentionally no local_irq_enable(): Alpha historically avoids
+ * enabling at IPL0 here due to PAL/RTI issues (LX164/MILO note).
+ */
+}
+
+void notrace lockdep_on_restore(unsigned long ps,
+ unsigned long ip)
+{
+#ifdef CONFIG_PROVE_LOCKING
+ /* Restoring IPL==7 means interrupts remain disabled. */
+ if ((ps & 7) == 7)
+ return;
+
+ /*
+ * If hardware IRQs are already enabled here, then emitting a
+ * hardirqs-on transition is redundant.
+ */
+ if (!irqs_disabled())
+ return;
+
+ /*
+ * Only emit the transition if lockdep currently believes
+ * hardirqs are off.
+ */
+ if (lockdep_hardirqs_enabled())
+ return;
+
+ lockdep_hardirqs_on_prepare();
+ lockdep_hardirqs_on(ip);
+#endif
}
void __init
diff --git a/arch/alpha/kernel/irq_i8259.c b/arch/alpha/kernel/irq_i8259.c
index 29c6c477ac35..28f7b0680564 100644
--- a/arch/alpha/kernel/irq_i8259.c
+++ b/arch/alpha/kernel/irq_i8259.c
@@ -22,7 +22,7 @@
/* Note mask bit is true for DISABLED irqs. */
static unsigned int cached_irq_mask = 0xffff;
-static DEFINE_SPINLOCK(i8259_irq_lock);
+static DEFINE_RAW_SPINLOCK(i8259_irq_lock);
static inline void
i8259_update_irq_hw(unsigned int irq, unsigned long mask)
@@ -36,9 +36,11 @@ i8259_update_irq_hw(unsigned int irq, unsigned long mask)
inline void
i8259a_enable_irq(struct irq_data *d)
{
- spin_lock(&i8259_irq_lock);
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&i8259_irq_lock, flags);
i8259_update_irq_hw(d->irq, cached_irq_mask &= ~(1 << d->irq));
- spin_unlock(&i8259_irq_lock);
+ raw_spin_unlock_irqrestore(&i8259_irq_lock, flags);
}
static inline void
@@ -50,17 +52,20 @@ __i8259a_disable_irq(unsigned int irq)
void
i8259a_disable_irq(struct irq_data *d)
{
- spin_lock(&i8259_irq_lock);
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&i8259_irq_lock, flags);
__i8259a_disable_irq(d->irq);
- spin_unlock(&i8259_irq_lock);
+ raw_spin_unlock_irqrestore(&i8259_irq_lock, flags);
}
void
i8259a_mask_and_ack_irq(struct irq_data *d)
{
unsigned int irq = d->irq;
+ unsigned long flags;
- spin_lock(&i8259_irq_lock);
+ raw_spin_lock_irqsave(&i8259_irq_lock, flags);
__i8259a_disable_irq(irq);
/* Ack the interrupt making it the lowest priority. */
@@ -69,7 +74,7 @@ i8259a_mask_and_ack_irq(struct irq_data *d)
irq = 2;
}
outb(0xE0 | irq, 0x20); /* ack the master */
- spin_unlock(&i8259_irq_lock);
+ raw_spin_unlock_irqrestore(&i8259_irq_lock, flags);
}
struct irq_chip i8259a_irq_type = {
diff --git a/arch/alpha/kernel/module.c b/arch/alpha/kernel/module.c
index cbefa5a77384..548d1591cfa9 100644
--- a/arch/alpha/kernel/module.c
+++ b/arch/alpha/kernel/module.c
@@ -46,7 +46,7 @@ process_reloc_for_got(Elf64_Rela *rela,
goto found_entry;
}
- g = kmalloc (sizeof (*g), GFP_KERNEL);
+ g = kmalloc_obj(*g);
g->next = chains[r_sym].next;
g->r_addend = r_addend;
g->got_offset = *poffset;
@@ -93,7 +93,7 @@ module_frob_arch_sections(Elf64_Ehdr *hdr, Elf64_Shdr *sechdrs,
}
nsyms = symtab->sh_size / sizeof(Elf64_Sym);
- chains = kcalloc(nsyms, sizeof(struct got_entry), GFP_KERNEL);
+ chains = kzalloc_objs(struct got_entry, nsyms);
if (!chains) {
printk(KERN_ERR
"module %s: no memory for symbol chain buffer\n",
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index a08e8edef1a4..7b6543d2cca3 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -454,42 +454,30 @@ static int
osf_ufs_mount(const char __user *dirname,
struct ufs_args __user *args, int flags)
{
- int retval;
- struct cdfs_args tmp;
- struct filename *devname;
+ struct ufs_args tmp;
+ char *devname __free(kfree) = NULL;
- retval = -EFAULT;
if (copy_from_user(&tmp, args, sizeof(tmp)))
- goto out;
- devname = getname(tmp.devname);
- retval = PTR_ERR(devname);
+ return -EFAULT;
+ devname = strndup_user(tmp.devname, PATH_MAX);
if (IS_ERR(devname))
- goto out;
- retval = do_mount(devname->name, dirname, "ext2", flags, NULL);
- putname(devname);
- out:
- return retval;
+ return PTR_ERR(devname);
+ return do_mount(devname, dirname, "ext2", flags, NULL);
}
static int
osf_cdfs_mount(const char __user *dirname,
struct cdfs_args __user *args, int flags)
{
- int retval;
struct cdfs_args tmp;
- struct filename *devname;
+ char *devname __free(kfree) = NULL;
- retval = -EFAULT;
if (copy_from_user(&tmp, args, sizeof(tmp)))
- goto out;
- devname = getname(tmp.devname);
- retval = PTR_ERR(devname);
+ return -EFAULT;
+ devname = strndup_user(tmp.devname, PATH_MAX);
if (IS_ERR(devname))
- goto out;
- retval = do_mount(devname->name, dirname, "iso9660", flags, NULL);
- putname(devname);
- out:
- return retval;
+ return PTR_ERR(devname);
+ return do_mount(devname, dirname, "iso9660", flags, NULL);
}
static int
diff --git a/arch/alpha/kernel/pci-sysfs.c b/arch/alpha/kernel/pci-sysfs.c
index 3048758304b5..67f9822f7626 100644
--- a/arch/alpha/kernel/pci-sysfs.c
+++ b/arch/alpha/kernel/pci-sysfs.c
@@ -11,8 +11,7 @@
*/
#include <linux/sched.h>
-#include <linux/stat.h>
-#include <linux/slab.h>
+#include <linux/security.h>
#include <linux/pci.h>
static int hose_mmap_page_range(struct pci_controller *hose,
@@ -36,20 +35,18 @@ static int hose_mmap_page_range(struct pci_controller *hose,
static int __pci_mmap_fits(struct pci_dev *pdev, int num,
struct vm_area_struct *vma, int sparse)
{
+ resource_size_t len = pci_resource_len(pdev, num);
unsigned long nr, start, size;
int shift = sparse ? 5 : 0;
+ if (!len)
+ return 0;
+
nr = vma_pages(vma);
start = vma->vm_pgoff;
- size = ((pci_resource_len(pdev, num) - 1) >> (PAGE_SHIFT - shift)) + 1;
+ size = ((len - 1) >> (PAGE_SHIFT - shift)) + 1;
- if (start < size && size - start >= nr)
- return 1;
- WARN(1, "process \"%s\" tried to map%s 0x%08lx-0x%08lx on %s BAR %d "
- "(size 0x%08lx)\n",
- current->comm, sparse ? " sparse" : "", start, start + nr,
- pci_name(pdev), num, size);
- return 0;
+ return start < size && size - start >= nr;
}
/**
@@ -68,26 +65,25 @@ static int pci_mmap_resource(struct kobject *kobj,
struct vm_area_struct *vma, int sparse)
{
struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
- struct resource *res = attr->private;
+ int barno = (unsigned long)attr->private;
enum pci_mmap_state mmap_type;
struct pci_bus_region bar;
- int i;
+ int ret;
- for (i = 0; i < PCI_STD_NUM_BARS; i++)
- if (res == &pdev->resource[i])
- break;
- if (i >= PCI_STD_NUM_BARS)
- return -ENODEV;
+ ret = security_locked_down(LOCKDOWN_PCI_ACCESS);
+ if (ret)
+ return ret;
- if (res->flags & IORESOURCE_MEM && iomem_is_exclusive(res->start))
+ if (pci_resource_is_mem(pdev, barno) &&
+ iomem_is_exclusive(pci_resource_start(pdev, barno)))
return -EINVAL;
- if (!__pci_mmap_fits(pdev, i, vma, sparse))
+ if (!__pci_mmap_fits(pdev, barno, vma, sparse))
return -EINVAL;
- pcibios_resource_to_bus(pdev->bus, &bar, res);
+ pcibios_resource_to_bus(pdev->bus, &bar, pci_resource_n(pdev, barno));
vma->vm_pgoff += bar.start >> (PAGE_SHIFT - (sparse ? 5 : 0));
- mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io;
+ mmap_type = pci_resource_is_mem(pdev, barno) ? pci_mmap_mem : pci_mmap_io;
return hose_mmap_page_range(pdev->sysdata, vma, mmap_type, sparse);
}
@@ -106,34 +102,26 @@ static int pci_mmap_resource_dense(struct file *filp, struct kobject *kobj,
return pci_mmap_resource(kobj, attr, vma, 0);
}
-/**
- * pci_remove_resource_files - cleanup resource files
- * @pdev: pci_dev to cleanup
- *
- * If we created resource files for @dev, remove them from sysfs and
- * free their resources.
- */
-void pci_remove_resource_files(struct pci_dev *pdev)
-{
- int i;
-
- for (i = 0; i < PCI_STD_NUM_BARS; i++) {
- struct bin_attribute *res_attr;
-
- res_attr = pdev->res_attr[i];
- if (res_attr) {
- sysfs_remove_bin_file(&pdev->dev.kobj, res_attr);
- kfree(res_attr);
- }
-
- res_attr = pdev->res_attr_wc[i];
- if (res_attr) {
- sysfs_remove_bin_file(&pdev->dev.kobj, res_attr);
- kfree(res_attr);
- }
- }
+#define __pci_dev_resource_attr(_suffix, _bar, _name, _mmap) \
+static const struct bin_attribute \
+pci_dev_resource##_bar##_suffix##_attr = { \
+ .attr = { .name = __stringify(_name), .mode = 0600 }, \
+ .private = (void *)(unsigned long)(_bar), \
+ .mmap = (_mmap), \
}
+#define pci_dev_resource_attr(_bar) \
+ __pci_dev_resource_attr(, _bar, resource##_bar, \
+ pci_mmap_resource_dense)
+
+#define pci_dev_resource_sparse_attr(_bar) \
+ __pci_dev_resource_attr(_sparse, _bar, resource##_bar##_sparse, \
+ pci_mmap_resource_sparse)
+
+#define pci_dev_resource_dense_attr(_bar) \
+ __pci_dev_resource_attr(_dense, _bar, resource##_bar##_dense, \
+ pci_mmap_resource_dense)
+
static int sparse_mem_mmap_fits(struct pci_dev *pdev, int num)
{
struct pci_bus_region bar;
@@ -141,7 +129,7 @@ static int sparse_mem_mmap_fits(struct pci_dev *pdev, int num)
long dense_offset;
unsigned long sparse_size;
- pcibios_resource_to_bus(pdev->bus, &bar, &pdev->resource[num]);
+ pcibios_resource_to_bus(pdev->bus, &bar, pci_resource_n(pdev, num));
/* All core logic chips have 4G sparse address space, except
CIA which has 16G (see xxx_SPARSE_MEM and xxx_DENSE_MEM
@@ -153,109 +141,10 @@ static int sparse_mem_mmap_fits(struct pci_dev *pdev, int num)
return bar.end < sparse_size;
}
-static int pci_create_one_attr(struct pci_dev *pdev, int num, char *name,
- char *suffix, struct bin_attribute *res_attr,
- unsigned long sparse)
-{
- size_t size = pci_resource_len(pdev, num);
-
- sprintf(name, "resource%d%s", num, suffix);
- res_attr->mmap = sparse ? pci_mmap_resource_sparse :
- pci_mmap_resource_dense;
- res_attr->attr.name = name;
- res_attr->attr.mode = S_IRUSR | S_IWUSR;
- res_attr->size = sparse ? size << 5 : size;
- res_attr->private = &pdev->resource[num];
- return sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
-}
-
-static int pci_create_attr(struct pci_dev *pdev, int num)
-{
- /* allocate attribute structure, piggyback attribute name */
- int retval, nlen1, nlen2 = 0, res_count = 1;
- unsigned long sparse_base, dense_base;
- struct bin_attribute *attr;
- struct pci_controller *hose = pdev->sysdata;
- char *suffix, *attr_name;
-
- suffix = ""; /* Assume bwx machine, normal resourceN files. */
- nlen1 = 10;
-
- if (pdev->resource[num].flags & IORESOURCE_MEM) {
- sparse_base = hose->sparse_mem_base;
- dense_base = hose->dense_mem_base;
- if (sparse_base && !sparse_mem_mmap_fits(pdev, num)) {
- sparse_base = 0;
- suffix = "_dense";
- nlen1 = 16; /* resourceN_dense */
- }
- } else {
- sparse_base = hose->sparse_io_base;
- dense_base = hose->dense_io_base;
- }
-
- if (sparse_base) {
- suffix = "_sparse";
- nlen1 = 17;
- if (dense_base) {
- nlen2 = 16; /* resourceN_dense */
- res_count = 2;
- }
- }
-
- attr = kzalloc(sizeof(*attr) * res_count + nlen1 + nlen2, GFP_ATOMIC);
- if (!attr)
- return -ENOMEM;
-
- /* Create bwx, sparse or single dense file */
- attr_name = (char *)(attr + res_count);
- pdev->res_attr[num] = attr;
- retval = pci_create_one_attr(pdev, num, attr_name, suffix, attr,
- sparse_base);
- if (retval || res_count == 1)
- return retval;
-
- /* Create dense file */
- attr_name += nlen1;
- attr++;
- pdev->res_attr_wc[num] = attr;
- return pci_create_one_attr(pdev, num, attr_name, "_dense", attr, 0);
-}
-
-/**
- * pci_create_resource_files - create resource files in sysfs for @pdev
- * @pdev: pci_dev in question
- *
- * Walk the resources in @dev creating files for each resource available.
- *
- * Return: %0 on success, or negative error code
- */
-int pci_create_resource_files(struct pci_dev *pdev)
-{
- int i;
- int retval;
-
- /* Expose the PCI resources from this device as files */
- for (i = 0; i < PCI_STD_NUM_BARS; i++) {
-
- /* skip empty resources */
- if (!pci_resource_len(pdev, i))
- continue;
-
- retval = pci_create_attr(pdev, i);
- if (retval) {
- pci_remove_resource_files(pdev);
- return retval;
- }
- }
- return 0;
-}
-
/* Legacy I/O bus mapping stuff. */
-static int __legacy_mmap_fits(struct pci_controller *hose,
- struct vm_area_struct *vma,
- unsigned long res_size, int sparse)
+static int __legacy_mmap_fits(struct vm_area_struct *vma,
+ unsigned long res_size)
{
unsigned long nr, start, size;
@@ -263,13 +152,7 @@ static int __legacy_mmap_fits(struct pci_controller *hose,
start = vma->vm_pgoff;
size = ((res_size - 1) >> PAGE_SHIFT) + 1;
- if (start < size && size - start >= nr)
- return 1;
- WARN(1, "process \"%s\" tried to map%s 0x%08lx-0x%08lx on hose %d "
- "(size 0x%08lx)\n",
- current->comm, sparse ? " sparse" : "", start, start + nr,
- hose->index, size);
- return 0;
+ return start < size && size - start >= nr;
}
static inline int has_sparse(struct pci_controller *hose,
@@ -290,36 +173,22 @@ int pci_mmap_legacy_page_range(struct pci_bus *bus, struct vm_area_struct *vma,
int sparse = has_sparse(hose, mmap_type);
unsigned long res_size;
- res_size = (mmap_type == pci_mmap_mem) ? bus->legacy_mem->size :
- bus->legacy_io->size;
- if (!__legacy_mmap_fits(hose, vma, res_size, sparse))
+ res_size = (mmap_type == pci_mmap_mem) ? PCI_LEGACY_MEM_SIZE :
+ PCI_LEGACY_IO_SIZE;
+ if (sparse)
+ res_size <<= 5;
+
+ if (!__legacy_mmap_fits(vma, res_size))
return -EINVAL;
return hose_mmap_page_range(hose, vma, mmap_type, sparse);
}
-/**
- * pci_adjust_legacy_attr - adjustment of legacy file attributes
- * @bus: bus to create files under
- * @mmap_type: I/O port or memory
- *
- * Adjust file name and size for sparse mappings.
- */
-void pci_adjust_legacy_attr(struct pci_bus *bus, enum pci_mmap_state mmap_type)
+bool pci_legacy_has_sparse(struct pci_bus *bus, enum pci_mmap_state type)
{
struct pci_controller *hose = bus->sysdata;
- if (!has_sparse(hose, mmap_type))
- return;
-
- if (mmap_type == pci_mmap_mem) {
- bus->legacy_mem->attr.name = "legacy_mem_sparse";
- bus->legacy_mem->size <<= 5;
- } else {
- bus->legacy_io->attr.name = "legacy_io_sparse";
- bus->legacy_io->size <<= 5;
- }
- return;
+ return has_sparse(hose, type);
}
/* Legacy I/O bus read/write functions */
@@ -355,18 +224,181 @@ int pci_legacy_write(struct pci_bus *bus, loff_t port, u32 val, size_t size)
switch(size) {
case 1:
- outb(port, val);
+ outb(val, port);
return 1;
case 2:
if (port & 1)
return -EINVAL;
- outw(port, val);
+ outw(val, port);
return 2;
case 4:
if (port & 3)
return -EINVAL;
- outl(port, val);
+ outl(val, port);
return 4;
}
return -EINVAL;
}
+
+pci_dev_resource_attr(0);
+pci_dev_resource_attr(1);
+pci_dev_resource_attr(2);
+pci_dev_resource_attr(3);
+pci_dev_resource_attr(4);
+pci_dev_resource_attr(5);
+
+pci_dev_resource_sparse_attr(0);
+pci_dev_resource_sparse_attr(1);
+pci_dev_resource_sparse_attr(2);
+pci_dev_resource_sparse_attr(3);
+pci_dev_resource_sparse_attr(4);
+pci_dev_resource_sparse_attr(5);
+
+pci_dev_resource_dense_attr(0);
+pci_dev_resource_dense_attr(1);
+pci_dev_resource_dense_attr(2);
+pci_dev_resource_dense_attr(3);
+pci_dev_resource_dense_attr(4);
+pci_dev_resource_dense_attr(5);
+
+static inline enum pci_mmap_state pci_bar_mmap_type(struct pci_dev *pdev,
+ int bar)
+{
+ return pci_resource_is_mem(pdev, bar) ? pci_mmap_mem : pci_mmap_io;
+}
+
+static inline umode_t __pci_resource_attr_is_visible(struct kobject *kobj,
+ const struct bin_attribute *a,
+ int bar)
+{
+ struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
+
+ if (!pci_resource_len(pdev, bar))
+ return 0;
+
+ return a->attr.mode;
+}
+
+static umode_t pci_dev_resource_is_visible(struct kobject *kobj,
+ const struct bin_attribute *a,
+ int bar)
+{
+ struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
+ struct pci_controller *hose = pdev->sysdata;
+
+ if (has_sparse(hose, pci_bar_mmap_type(pdev, bar)))
+ return 0;
+
+ return __pci_resource_attr_is_visible(kobj, a, bar);
+}
+
+static umode_t pci_dev_resource_sparse_is_visible(struct kobject *kobj,
+ const struct bin_attribute *a,
+ int bar)
+{
+ struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
+ struct pci_controller *hose = pdev->sysdata;
+ enum pci_mmap_state type = pci_bar_mmap_type(pdev, bar);
+
+ if (!has_sparse(hose, type))
+ return 0;
+
+ if (type == pci_mmap_mem && !sparse_mem_mmap_fits(pdev, bar))
+ return 0;
+
+ return __pci_resource_attr_is_visible(kobj, a, bar);
+}
+
+static umode_t pci_dev_resource_dense_is_visible(struct kobject *kobj,
+ const struct bin_attribute *a,
+ int bar)
+{
+ struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
+ struct pci_controller *hose = pdev->sysdata;
+ enum pci_mmap_state type = pci_bar_mmap_type(pdev, bar);
+ unsigned long dense_base;
+
+ if (!has_sparse(hose, type))
+ return 0;
+
+ if (type == pci_mmap_mem && !sparse_mem_mmap_fits(pdev, bar))
+ return __pci_resource_attr_is_visible(kobj, a, bar);
+
+ dense_base = (type == pci_mmap_mem) ? hose->dense_mem_base :
+ hose->dense_io_base;
+ if (!dense_base)
+ return 0;
+
+ return __pci_resource_attr_is_visible(kobj, a, bar);
+}
+
+static inline size_t __pci_dev_resource_bin_size(struct kobject *kobj,
+ int bar, bool sparse)
+{
+ struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
+ size_t size = pci_resource_len(pdev, bar);
+
+ return sparse ? size << 5 : size;
+}
+
+static size_t pci_dev_resource_bin_size(struct kobject *kobj,
+ const struct bin_attribute *a,
+ int bar)
+{
+ return __pci_dev_resource_bin_size(kobj, bar, false);
+}
+
+static size_t pci_dev_resource_sparse_bin_size(struct kobject *kobj,
+ const struct bin_attribute *a,
+ int bar)
+{
+ return __pci_dev_resource_bin_size(kobj, bar, true);
+}
+
+static const struct bin_attribute *const pci_dev_resource_attrs[] = {
+ &pci_dev_resource0_attr,
+ &pci_dev_resource1_attr,
+ &pci_dev_resource2_attr,
+ &pci_dev_resource3_attr,
+ &pci_dev_resource4_attr,
+ &pci_dev_resource5_attr,
+ NULL,
+};
+
+static const struct bin_attribute *const pci_dev_resource_sparse_attrs[] = {
+ &pci_dev_resource0_sparse_attr,
+ &pci_dev_resource1_sparse_attr,
+ &pci_dev_resource2_sparse_attr,
+ &pci_dev_resource3_sparse_attr,
+ &pci_dev_resource4_sparse_attr,
+ &pci_dev_resource5_sparse_attr,
+ NULL,
+};
+
+static const struct bin_attribute *const pci_dev_resource_dense_attrs[] = {
+ &pci_dev_resource0_dense_attr,
+ &pci_dev_resource1_dense_attr,
+ &pci_dev_resource2_dense_attr,
+ &pci_dev_resource3_dense_attr,
+ &pci_dev_resource4_dense_attr,
+ &pci_dev_resource5_dense_attr,
+ NULL,
+};
+
+const struct attribute_group pci_dev_resource_attr_group = {
+ .bin_attrs = pci_dev_resource_attrs,
+ .is_bin_visible = pci_dev_resource_is_visible,
+ .bin_size = pci_dev_resource_bin_size,
+};
+
+const struct attribute_group pci_dev_resource_sparse_attr_group = {
+ .bin_attrs = pci_dev_resource_sparse_attrs,
+ .is_bin_visible = pci_dev_resource_sparse_is_visible,
+ .bin_size = pci_dev_resource_sparse_bin_size,
+};
+
+const struct attribute_group pci_dev_resource_dense_attr_group = {
+ .bin_attrs = pci_dev_resource_dense_attrs,
+ .is_bin_visible = pci_dev_resource_dense_is_visible,
+ .bin_size = pci_dev_resource_bin_size,
+};
diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
index 8e9b4ac86b7e..11df411b1d18 100644
--- a/arch/alpha/kernel/pci.c
+++ b/arch/alpha/kernel/pci.c
@@ -125,6 +125,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_final);
resource_size_t
pcibios_align_resource(void *data, const struct resource *res,
+ const struct resource *empty_res,
resource_size_t size, resource_size_t align)
{
struct pci_dev *dev = data;
@@ -220,7 +221,7 @@ static void pdev_save_srm_config(struct pci_dev *dev)
printed = 1;
}
- tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
+ tmp = kmalloc_obj(*tmp);
if (!tmp) {
printk(KERN_ERR "%s: kmalloc() failed!\n", __func__);
return;
diff --git a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h
index a8bc3ead776b..9b262ef09a3a 100644
--- a/arch/alpha/kernel/proto.h
+++ b/arch/alpha/kernel/proto.h
@@ -173,6 +173,7 @@ extern void do_sigreturn(struct sigcontext __user *);
struct rt_sigframe;
extern void do_rt_sigreturn(struct rt_sigframe __user *);
extern void do_work_pending(struct pt_regs *, unsigned long, unsigned long, unsigned long);
+extern void alpha_schedule_user_work(void);
/* traps.c */
extern void dik_show_regs(struct pt_regs *regs, unsigned long *r9_15);
@@ -185,6 +186,9 @@ struct allregs;
extern void do_entUna(void *, unsigned long, unsigned long, struct allregs *);
extern void do_entUnaUser(void __user *, unsigned long, unsigned long, struct pt_regs *);
+/* irq_alpha.c */
+extern void notrace lockdep_on_restore(unsigned long ps, unsigned long ip);
+
/* sys_titan.c */
extern void titan_dispatch_irqs(u64);
diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c
index fde4c68e7a0b..fc8f6cedbb28 100644
--- a/arch/alpha/kernel/ptrace.c
+++ b/arch/alpha/kernel/ptrace.c
@@ -16,15 +16,23 @@
#include <linux/security.h>
#include <linux/signal.h>
#include <linux/audit.h>
+#include <linux/seccomp.h>
+#include <asm/syscall.h>
#include <linux/uaccess.h>
#include <asm/fpu.h>
#include "proto.h"
+#include <linux/uio.h>
+#include <linux/regset.h>
#define DEBUG DBG_MEM
#undef DEBUG
+#ifndef NT_FPREGSET
+#define NT_FPREGSET NT_PRFPREG
+#endif
+
#ifdef DEBUG
enum {
DBG_MEM = (1<<0),
@@ -140,19 +148,163 @@ get_reg(struct task_struct * task, unsigned long regno)
return *get_reg_addr(task, regno);
}
+static void alpha_elf_fpregs_get(struct task_struct *target,
+ elf_fpreg_t *fpregs) /* points to ELF_NFPREG entries */
+{
+ memcpy(fpregs, task_thread_info(target)->fp, sizeof(elf_fpregset_t));
+}
+
+static void alpha_elf_fpregs_set(struct task_struct *target,
+ const elf_fpreg_t *fpregs,
+ size_t nwords)
+{
+ size_t n = min_t(size_t, nwords, ELF_NFPREG);
+
+ memcpy(task_thread_info(target)->fp, fpregs, n * sizeof(elf_fpreg_t));
+}
+
+static void alpha_elf_gregs_set(struct task_struct *child,
+ const elf_greg_t *src,
+ size_t nwords)
+{
+ struct pt_regs *pt = task_pt_regs(child);
+ struct thread_info *ti = task_thread_info(child);
+ struct switch_stack *sw = ((struct switch_stack *)pt) - 1;
+
+ /* GPRs r0..r8 live in pt_regs */
+ if (nwords > 0)
+ pt->r0 = src[0];
+ if (nwords > 1)
+ pt->r1 = src[1];
+ if (nwords > 2)
+ pt->r2 = src[2];
+ if (nwords > 3)
+ pt->r3 = src[3];
+ if (nwords > 4)
+ pt->r4 = src[4];
+ if (nwords > 5)
+ pt->r5 = src[5];
+ if (nwords > 6)
+ pt->r6 = src[6];
+ if (nwords > 7)
+ pt->r7 = src[7];
+ if (nwords > 8)
+ pt->r8 = src[8];
+
+ /* r9..r15 live in switch_stack */
+ if (nwords > 9)
+ sw->r9 = src[9];
+ if (nwords > 10)
+ sw->r10 = src[10];
+ if (nwords > 11)
+ sw->r11 = src[11];
+ if (nwords > 12)
+ sw->r12 = src[12];
+ if (nwords > 13)
+ sw->r13 = src[13];
+ if (nwords > 14)
+ sw->r14 = src[14];
+ if (nwords > 15)
+ sw->r15 = src[15];
+
+ /* r16..r28 live in pt_regs */
+ if (nwords > 16)
+ pt->r16 = src[16];
+ if (nwords > 17)
+ pt->r17 = src[17];
+ if (nwords > 18)
+ pt->r18 = src[18];
+ if (nwords > 19)
+ pt->r19 = src[19];
+ if (nwords > 20)
+ pt->r20 = src[20];
+ if (nwords > 21)
+ pt->r21 = src[21];
+ if (nwords > 22)
+ pt->r22 = src[22];
+ if (nwords > 23)
+ pt->r23 = src[23];
+ if (nwords > 24)
+ pt->r24 = src[24];
+ if (nwords > 25)
+ pt->r25 = src[25];
+ if (nwords > 26)
+ pt->r26 = src[26];
+ if (nwords > 27)
+ pt->r27 = src[27];
+ if (nwords > 28)
+ pt->r28 = src[28];
+
+ /* gp, usp, pc, unique */
+ if (nwords > 29)
+ pt->gp = src[29];
+
+ if (nwords > 30) {
+ ti->pcb.usp = src[30];
+ /*
+ * If someone ever does this to current (rare), keep the
+ * hardware usp consistent.
+ */
+ if (child == current)
+ wrusp(src[30]);
+ }
+
+ if (nwords > 31)
+ pt->pc = src[31];
+
+ if (nwords > 32)
+ ti->pcb.unique = src[32];
+
+/*
+ * PTRACE_SETREGSET can be used at a syscall-entry stop to skip the
+ * syscall by setting the syscall number to -1. The seccomp/ptrace
+ * selftests use this to synthesize errno returns.
+ *
+ * Alpha uses r19/a3 as the error flag, so a skipped syscall with a
+ * small positive r0 and a clear r19 must be normalized to an error
+ * return.
+ */
+ if (pt->r1 == (unsigned long)-1 &&
+ pt->r19 == 0 &&
+ pt->r0 > 0 &&
+ pt->r0 < MAX_ERRNO)
+ pt->r19 = 1;
+}
+
+
/*
* Write contents of register REGNO in task TASK.
*/
static int
put_reg(struct task_struct *task, unsigned long regno, unsigned long data)
{
+ struct pt_regs *regs = task_pt_regs(task);
+
if (regno == 63) {
task_thread_info(task)->ieee_state
= ((task_thread_info(task)->ieee_state & ~IEEE_SW_MASK)
| (data & IEEE_SW_MASK));
data = (data & FPCR_DYN_MASK) | ieee_swcr_to_fpcr(data);
}
+
*get_reg_addr(task, regno) = data;
+
+ /*
+ * Alpha historically exposes r0/v0 as the syscall number at a
+ * syscall-entry stop. The generic-entry conversion keeps the
+ * mutable syscall number in regs->r1, so old ptrace users such
+ * as strace that skip a syscall by poking r0 to -1 must also
+ * update the internal shadow syscall number.
+ *
+ * Do not mirror other r0 writes. strace later pokes r0 to the
+ * injected return value, e.g. 42, while r1 must remain -1.
+ */
+
+ if (regno == 0 && data == (unsigned long)-1) {
+ regs->r1 = data;
+ regs->r19 = 0;
+ }
+
return 0;
}
@@ -321,15 +473,37 @@ long arch_ptrace(struct task_struct *child, long request,
asmlinkage unsigned long syscall_trace_enter(void)
{
- unsigned long ret = 0;
struct pt_regs *regs = current_pt_regs();
+
if (test_thread_flag(TIF_SYSCALL_TRACE) &&
- ptrace_report_syscall_entry(current_pt_regs()))
- ret = -1UL;
- audit_syscall_entry(regs->r0, regs->r16, regs->r17, regs->r18, regs->r19);
- return ret ?: current_pt_regs()->r0;
+ !ptrace_report_syscall_permit_entry(regs)) {
+ syscall_set_nr(current, regs, -1);
+ if (regs->r19 == 0 && regs->r0 == (unsigned long)-1)
+ syscall_set_return_value(current, regs, -ENOSYS, 0);
+ return -1UL;
+ }
+
+ /*
+ * Do the secure computing after ptrace; failures should be fast.
+ * If this fails, seccomp may already have set up the return value
+ * (e.g. SECCOMP_RET_ERRNO / TRACE).
+ */
+ if (!seccomp_permit_syscall()) {
+ if (regs->r19 == 0 && regs->r0 == (unsigned long)-1)
+ syscall_set_return_value(current, regs, -ENOSYS, 0);
+ syscall_set_nr(current, regs, -1);
+ return -1UL;
+ }
+
+#ifdef CONFIG_AUDITSYSCALL
+ audit_syscall_entry(syscall_get_nr(current, regs),
+ regs->r16, regs->r17, regs->r18, regs->r19);
+#endif
+ return syscall_get_nr(current, regs);
}
+
+
asmlinkage void
syscall_trace_leave(void)
{
@@ -337,3 +511,126 @@ syscall_trace_leave(void)
if (test_thread_flag(TIF_SYSCALL_TRACE))
ptrace_report_syscall_exit(current_pt_regs(), 0);
}
+
+/*
+ * Minimal regset support for Alpha.
+ *
+ * Alpha-specific notes:
+ * - Do NOT use ELF_CORE_COPY_REGS(): it uses current_thread_info(),
+ * which is wrong for non-current tasks.
+ * - dump_elf_task() returns 1 unconditionally in this tree, while
+ * regset_get should return 0 on success. So call dump_elf_thread()
+ * directly and return membuf_write()'s result.
+ */
+
+static int alpha_regset_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf,
+ const void __user *ubuf)
+{
+ elf_gregset_t gregs;
+ unsigned int nwords;
+
+ if (pos + count > sizeof(gregs))
+ return -EIO;
+
+ /*
+ * Preserve registers outside the written range.
+ */
+ dump_elf_thread(gregs, task_pt_regs(target),
+ task_thread_info(target));
+
+ if (user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ gregs, 0, sizeof(gregs)))
+ return -EFAULT;
+
+ nwords = sizeof(gregs) / sizeof(elf_greg_t);
+ alpha_elf_gregs_set(target, gregs, nwords);
+
+ return 0;
+}
+
+static int alpha_fpregset_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf,
+ const void __user *ubuf)
+{
+ elf_fpregset_t fpregs;
+ unsigned int nwords;
+
+ if (pos + count > sizeof(fpregs))
+ return -EIO;
+
+ alpha_elf_fpregs_get(target, fpregs);
+
+ if (user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ fpregs, 0, sizeof(fpregs)))
+ return -EFAULT;
+
+ nwords = sizeof(fpregs) / sizeof(elf_fpreg_t);
+ alpha_elf_fpregs_set(target, fpregs, nwords);
+
+ return 0;
+}
+
+static int alpha_regset_get(struct task_struct *target,
+ const struct user_regset *regset,
+ struct membuf to)
+{
+ struct pt_regs *pt = task_pt_regs(target);
+ struct thread_info *ti = task_thread_info(target);
+ elf_gregset_t gregs;
+
+ dump_elf_thread(gregs, pt, ti);
+ return membuf_write(&to, gregs, sizeof(gregs));
+}
+
+static int alpha_fpregset_get(struct task_struct *target,
+ const struct user_regset *regset,
+ struct membuf to)
+{
+ elf_fpregset_t fpregs;
+
+ alpha_elf_fpregs_get(target, fpregs);
+ return membuf_write(&to, fpregs, sizeof(fpregs));
+}
+
+enum alpha_regset {
+ REGSET_GPR,
+ REGSET_FPR,
+};
+
+static const struct user_regset alpha_user_regsets[] = {
+ [REGSET_GPR] = {
+ .core_note_type = NT_PRSTATUS,
+ .n = ELF_NGREG,
+ .size = sizeof(elf_greg_t),
+ .align = sizeof(elf_greg_t),
+ .regset_get = alpha_regset_get,
+ .set = alpha_regset_set,
+ },
+ [REGSET_FPR] = {
+ .core_note_type = NT_PRFPREG,
+ .core_note_name = "CORE",
+ .n = ELF_NFPREG,
+ .size = sizeof(elf_fpreg_t),
+ .align = sizeof(elf_fpreg_t),
+ .regset_get = alpha_fpregset_get,
+ .set = alpha_fpregset_set,
+ },
+};
+
+static const struct user_regset_view user_alpha_view = {
+ .name = "alpha",
+ .e_machine = EM_ALPHA,
+ .ei_osabi = ELF_OSABI,
+ .regsets = alpha_user_regsets,
+ .n = ARRAY_SIZE(alpha_user_regsets),
+};
+
+const struct user_regset_view *task_user_regset_view(struct task_struct *task)
+{
+ return &user_alpha_view;
+}
diff --git a/arch/alpha/kernel/rtc.c b/arch/alpha/kernel/rtc.c
index cfdf90bc8b3f..9e7d714ef6f8 100644
--- a/arch/alpha/kernel/rtc.c
+++ b/arch/alpha/kernel/rtc.c
@@ -15,6 +15,7 @@
#include <linux/bcd.h>
#include <linux/rtc.h>
#include <linux/platform_device.h>
+#include <linux/workqueue.h>
#include "proto.h"
@@ -142,54 +143,40 @@ static const struct rtc_class_ops alpha_rtc_ops = {
};
/*
- * Similarly, except do the actual CMOS access on the boot cpu only.
- * This requires marshalling the data across an interprocessor call.
+ * Similarly, except do the actual CMOS access on the boot cpu only. The
+ * access polls for the RTC update cycle and takes rtc_lock, so run it in a
+ * worker on that cpu rather than from an interprocessor interrupt.
*/
#if defined(CONFIG_SMP) && \
(defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_MARVEL))
# define HAVE_REMOTE_RTC 1
-union remote_data {
- struct rtc_time *tm;
- long retval;
-};
-
-static void
+static long
do_remote_read(void *data)
{
- union remote_data *x = data;
- x->retval = alpha_rtc_read_time(NULL, x->tm);
+ return alpha_rtc_read_time(NULL, data);
}
static int
remote_read_time(struct device *dev, struct rtc_time *tm)
{
- union remote_data x;
- if (smp_processor_id() != boot_cpuid) {
- x.tm = tm;
- smp_call_function_single(boot_cpuid, do_remote_read, &x, 1);
- return x.retval;
- }
+ if (smp_processor_id() != boot_cpuid)
+ return work_on_cpu(boot_cpuid, do_remote_read, tm);
return alpha_rtc_read_time(NULL, tm);
}
-static void
+static long
do_remote_set(void *data)
{
- union remote_data *x = data;
- x->retval = alpha_rtc_set_time(NULL, x->tm);
+ return alpha_rtc_set_time(NULL, data);
}
static int
remote_set_time(struct device *dev, struct rtc_time *tm)
{
- union remote_data x;
- if (smp_processor_id() != boot_cpuid) {
- x.tm = tm;
- smp_call_function_single(boot_cpuid, do_remote_set, &x, 1);
- return x.retval;
- }
+ if (smp_processor_id() != boot_cpuid)
+ return work_on_cpu(boot_cpuid, do_remote_set, tm);
return alpha_rtc_set_time(NULL, tm);
}
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index bebdffafaee8..4cbcfb1852d5 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -392,7 +392,7 @@ register_cpus(void)
int i;
for_each_possible_cpu(i) {
- struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL);
+ struct cpu *p = kzalloc_obj(*p);
if (!p)
return -ENOMEM;
register_cpu(p, i);
@@ -607,7 +607,6 @@ setup_arch(char **cmdline_p)
/* Find our memory. */
setup_memory(kernel_end);
memblock_set_bottom_up(true);
- sparse_init();
/* First guess at cpu cache sizes. Do this before init_arch. */
determine_cpu_caches(cpu->type);
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index e62d1d461b1f..ce40a49b8496 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -41,6 +41,14 @@ asmlinkage void ret_from_sys_call(void);
* The OSF/1 sigprocmask calling sequence is different from the
* C sigprocmask() sequence..
*/
+
+asmlinkage void alpha_schedule_user_work(void)
+{
+ local_irq_enable();
+ schedule();
+ local_irq_disable();
+}
+
SYSCALL_DEFINE2(osf_sigprocmask, int, how, unsigned long, newmask)
{
sigset_t oldmask;
@@ -525,6 +533,7 @@ do_work_pending(struct pt_regs *regs, unsigned long thread_flags,
{
do {
if (thread_flags & _TIF_NEED_RESCHED) {
+ local_irq_enable();
schedule();
} else {
local_irq_enable();
diff --git a/arch/alpha/kernel/stacktrace.c b/arch/alpha/kernel/stacktrace.c
new file mode 100644
index 000000000000..74d95f591039
--- /dev/null
+++ b/arch/alpha/kernel/stacktrace.c
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/sched.h>
+#include <linux/sched/task_stack.h>
+#include <linux/stacktrace.h>
+#include <linux/kallsyms.h>
+
+#include <asm/thread_info.h>
+#include <asm/ptrace.h>
+
+static __always_inline unsigned long alpha_get_current_ksp(void)
+{
+ unsigned long sp;
+
+ asm volatile("mov $30, %0" : "=r"(sp));
+ return sp;
+}
+
+static void alpha_scan_kernel_stack(unsigned long ksp,
+ stack_trace_consume_fn consume_entry,
+ void *cookie)
+{
+ unsigned long *p = (unsigned long *)ksp;
+
+ if (unlikely(ksp & (sizeof(unsigned long) - 1)))
+ return;
+
+ while (!kstack_end(p)) {
+ unsigned long addr = READ_ONCE_NOCHECK(*p++);
+
+ if (!__kernel_text_address(addr))
+ continue;
+
+ if (!consume_entry(cookie, addr))
+ break;
+ }
+}
+
+noinline void arch_stack_walk(stack_trace_consume_fn consume_entry,
+ void *cookie,
+ struct task_struct *task,
+ struct pt_regs *regs)
+{
+ unsigned long ksp;
+
+ if (!task)
+ task = current;
+
+ if (regs && task == current) {
+ /*
+ * pt_regs is stored on the kernel stack; regs+1 matches
+ * what arch/alpha/kernel/traps.c uses as the trace start.
+ */
+ ksp = (unsigned long)(regs + 1);
+ } else if (task == current) {
+ ksp = alpha_get_current_ksp();
+ } else {
+ ksp = task_thread_info(task)->pcb.ksp;
+ }
+
+ alpha_scan_kernel_stack(ksp, consume_entry, cookie);
+}
diff --git a/arch/alpha/kernel/sys_dp264.c b/arch/alpha/kernel/sys_dp264.c
index 9fb445d7dca5..0a2d319bb1c8 100644
--- a/arch/alpha/kernel/sys_dp264.c
+++ b/arch/alpha/kernel/sys_dp264.c
@@ -41,7 +41,7 @@ static unsigned long cached_irq_mask;
/* dp264 boards handle at max four CPUs */
static unsigned long cpu_irq_affinity[4] = { 0UL, 0UL, 0UL, 0UL };
-DEFINE_SPINLOCK(dp264_irq_lock);
+static DEFINE_RAW_SPINLOCK(dp264_irq_lock);
static void
tsunami_update_irq_hw(unsigned long mask)
@@ -99,37 +99,45 @@ tsunami_update_irq_hw(unsigned long mask)
static void
dp264_enable_irq(struct irq_data *d)
{
- spin_lock(&dp264_irq_lock);
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&dp264_irq_lock, flags);
cached_irq_mask |= 1UL << d->irq;
tsunami_update_irq_hw(cached_irq_mask);
- spin_unlock(&dp264_irq_lock);
+ raw_spin_unlock_irqrestore(&dp264_irq_lock, flags);
}
static void
dp264_disable_irq(struct irq_data *d)
{
- spin_lock(&dp264_irq_lock);
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&dp264_irq_lock, flags);
cached_irq_mask &= ~(1UL << d->irq);
tsunami_update_irq_hw(cached_irq_mask);
- spin_unlock(&dp264_irq_lock);
+ raw_spin_unlock_irqrestore(&dp264_irq_lock, flags);
}
static void
clipper_enable_irq(struct irq_data *d)
{
- spin_lock(&dp264_irq_lock);
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&dp264_irq_lock, flags);
cached_irq_mask |= 1UL << (d->irq - 16);
tsunami_update_irq_hw(cached_irq_mask);
- spin_unlock(&dp264_irq_lock);
+ raw_spin_unlock_irqrestore(&dp264_irq_lock, flags);
}
static void
clipper_disable_irq(struct irq_data *d)
{
- spin_lock(&dp264_irq_lock);
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&dp264_irq_lock, flags);
cached_irq_mask &= ~(1UL << (d->irq - 16));
tsunami_update_irq_hw(cached_irq_mask);
- spin_unlock(&dp264_irq_lock);
+ raw_spin_unlock_irqrestore(&dp264_irq_lock, flags);
}
static void
@@ -151,10 +159,12 @@ static int
dp264_set_affinity(struct irq_data *d, const struct cpumask *affinity,
bool force)
{
- spin_lock(&dp264_irq_lock);
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&dp264_irq_lock, flags);
cpu_set_irq_affinity(d->irq, *affinity);
tsunami_update_irq_hw(cached_irq_mask);
- spin_unlock(&dp264_irq_lock);
+ raw_spin_unlock_irqrestore(&dp264_irq_lock, flags);
return 0;
}
@@ -163,10 +173,12 @@ static int
clipper_set_affinity(struct irq_data *d, const struct cpumask *affinity,
bool force)
{
- spin_lock(&dp264_irq_lock);
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&dp264_irq_lock, flags);
cpu_set_irq_affinity(d->irq - 16, *affinity);
tsunami_update_irq_hw(cached_irq_mask);
- spin_unlock(&dp264_irq_lock);
+ raw_spin_unlock_irqrestore(&dp264_irq_lock, flags);
return 0;
}
diff --git a/arch/alpha/kernel/sys_marvel.c b/arch/alpha/kernel/sys_marvel.c
index 1f99b03effc2..a37707e05e34 100644
--- a/arch/alpha/kernel/sys_marvel.c
+++ b/arch/alpha/kernel/sys_marvel.c
@@ -263,6 +263,18 @@ init_io7_irqs(struct io7 *io7,
*/
printk(" Interrupts reported to CPU at PE %u\n", boot_cpuid);
+ /* Set up the lsi irqs. */
+ for (i = 0; i < 128; ++i) {
+ irq_set_chip_and_handler(base + i, lsi_ops, handle_level_irq);
+ irq_set_status_flags(base + i, IRQ_LEVEL);
+ }
+
+ /* Set up the msi irqs. */
+ for (i = 128; i < (128 + 512); ++i) {
+ irq_set_chip_and_handler(base + i, msi_ops, handle_level_irq);
+ irq_set_status_flags(base + i, IRQ_LEVEL);
+ }
+
raw_spin_lock(&io7->irq_lock);
/* set up the error irqs */
@@ -272,12 +284,6 @@ init_io7_irqs(struct io7 *io7,
io7_redirect_irq(io7, &io7->csrs->STV_CTL.csr, boot_cpuid);
io7_redirect_irq(io7, &io7->csrs->HEI_CTL.csr, boot_cpuid);
- /* Set up the lsi irqs. */
- for (i = 0; i < 128; ++i) {
- irq_set_chip_and_handler(base + i, lsi_ops, handle_level_irq);
- irq_set_status_flags(i, IRQ_LEVEL);
- }
-
/* Disable the implemented irqs in hardware. */
for (i = 0; i < 0x60; ++i)
init_one_io7_lsi(io7, i, boot_cpuid);
@@ -285,13 +291,6 @@ init_io7_irqs(struct io7 *io7,
init_one_io7_lsi(io7, 0x74, boot_cpuid);
init_one_io7_lsi(io7, 0x75, boot_cpuid);
-
- /* Set up the msi irqs. */
- for (i = 128; i < (128 + 512); ++i) {
- irq_set_chip_and_handler(base + i, msi_ops, handle_level_irq);
- irq_set_status_flags(i, IRQ_LEVEL);
- }
-
for (i = 0; i < 16; ++i)
init_one_io7_msi(io7, i, boot_cpuid);
diff --git a/arch/alpha/kernel/sys_rawhide.c b/arch/alpha/kernel/sys_rawhide.c
index b5846ffdadce..b4a08890dce9 100644
--- a/arch/alpha/kernel/sys_rawhide.c
+++ b/arch/alpha/kernel/sys_rawhide.c
@@ -41,7 +41,7 @@ static unsigned int hose_irq_masks[4] = {
0xff0000, 0xfe0000, 0xff0000, 0xff0000
};
static unsigned int cached_irq_masks[4];
-DEFINE_SPINLOCK(rawhide_irq_lock);
+DEFINE_RAW_SPINLOCK(rawhide_irq_lock);
static inline void
rawhide_update_irq_hw(int hose, int mask)
@@ -59,6 +59,7 @@ rawhide_enable_irq(struct irq_data *d)
{
unsigned int mask, hose;
unsigned int irq = d->irq;
+ unsigned long flags;
irq -= 16;
hose = irq / 24;
@@ -68,11 +69,11 @@ rawhide_enable_irq(struct irq_data *d)
irq -= hose * 24;
mask = 1 << irq;
- spin_lock(&rawhide_irq_lock);
+ raw_spin_lock_irqsave(&rawhide_irq_lock, flags);
mask |= cached_irq_masks[hose];
cached_irq_masks[hose] = mask;
rawhide_update_irq_hw(hose, mask);
- spin_unlock(&rawhide_irq_lock);
+ raw_spin_unlock_irqrestore(&rawhide_irq_lock, flags);
}
static void
@@ -80,6 +81,7 @@ rawhide_disable_irq(struct irq_data *d)
{
unsigned int mask, hose;
unsigned int irq = d->irq;
+ unsigned long flags;
irq -= 16;
hose = irq / 24;
@@ -89,11 +91,11 @@ rawhide_disable_irq(struct irq_data *d)
irq -= hose * 24;
mask = ~(1 << irq) | hose_irq_masks[hose];
- spin_lock(&rawhide_irq_lock);
+ raw_spin_lock_irqsave(&rawhide_irq_lock, flags);
mask &= cached_irq_masks[hose];
cached_irq_masks[hose] = mask;
rawhide_update_irq_hw(hose, mask);
- spin_unlock(&rawhide_irq_lock);
+ raw_spin_unlock_irqrestore(&rawhide_irq_lock, flags);
}
static void
@@ -101,6 +103,7 @@ rawhide_mask_and_ack_irq(struct irq_data *d)
{
unsigned int mask, mask1, hose;
unsigned int irq = d->irq;
+ unsigned long flags;
irq -= 16;
hose = irq / 24;
@@ -111,7 +114,7 @@ rawhide_mask_and_ack_irq(struct irq_data *d)
mask1 = 1 << irq;
mask = ~mask1 | hose_irq_masks[hose];
- spin_lock(&rawhide_irq_lock);
+ raw_spin_lock_irqsave(&rawhide_irq_lock, flags);
mask &= cached_irq_masks[hose];
cached_irq_masks[hose] = mask;
@@ -120,7 +123,7 @@ rawhide_mask_and_ack_irq(struct irq_data *d)
/* Clear the interrupt. */
*(vuip)MCPCIA_INT_REQ(MCPCIA_HOSE2MID(hose)) = mask1;
- spin_unlock(&rawhide_irq_lock);
+ raw_spin_unlock_irqrestore(&rawhide_irq_lock, flags);
}
static struct irq_chip rawhide_irq_type = {
diff --git a/arch/alpha/kernel/syscalls/syscall.tbl b/arch/alpha/kernel/syscalls/syscall.tbl
index 3fed97478058..52e3538cc7df 100644
--- a/arch/alpha/kernel/syscalls/syscall.tbl
+++ b/arch/alpha/kernel/syscalls/syscall.tbl
@@ -510,3 +510,5 @@
578 common file_getattr sys_file_getattr
579 common file_setattr sys_file_setattr
580 common listns sys_listns
+581 common rseq_slice_yield sys_rseq_slice_yield
+582 common fchroot sys_fchroot
diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c
index 7004397937cf..cfaef96c4ce8 100644
--- a/arch/alpha/kernel/traps.c
+++ b/arch/alpha/kernel/traps.c
@@ -30,6 +30,12 @@
#include "proto.h"
+static __always_inline void alpha_snapshot_usp(struct pt_regs *regs)
+{
+ if (user_mode(regs))
+ regs->usp = rdusp();
+}
+
void
dik_show_regs(struct pt_regs *regs, unsigned long *r9_15)
{
@@ -166,12 +172,12 @@ static long dummy_emul(void) { return 0; }
long (*alpha_fp_emul_imprecise)(struct pt_regs *regs, unsigned long writemask)
= (void *)dummy_emul;
EXPORT_SYMBOL_GPL(alpha_fp_emul_imprecise);
-long (*alpha_fp_emul) (unsigned long pc)
+long (*alpha_fp_emul) (unsigned long pc, unsigned long summary)
= (void *)dummy_emul;
EXPORT_SYMBOL_GPL(alpha_fp_emul);
#else
long alpha_fp_emul_imprecise(struct pt_regs *regs, unsigned long writemask);
-long alpha_fp_emul (unsigned long pc);
+long alpha_fp_emul (unsigned long pc, unsigned long summary);
#endif
asmlinkage void
@@ -180,12 +186,13 @@ do_entArith(unsigned long summary, unsigned long write_mask,
{
long si_code = FPE_FLTINV;
+ alpha_snapshot_usp(regs);
if (summary & 1) {
/* Software-completion summary bit is set, so try to
emulate the instruction. If the processor supports
precise exceptions, we don't have to search. */
if (!amask(AMASK_PRECISE_TRAP))
- si_code = alpha_fp_emul(regs->pc - 4);
+ si_code = alpha_fp_emul(regs->pc - 4, summary);
else
si_code = alpha_fp_emul_imprecise(regs, write_mask);
if (si_code == 0)
@@ -201,6 +208,7 @@ do_entIF(unsigned long type, struct pt_regs *regs)
{
int signo, code;
+ alpha_snapshot_usp(regs);
if (type == 3) { /* FEN fault */
/* Irritating users can call PAL_clrfen to disable the
FPU for the process. The kernel will then trap in
@@ -917,7 +925,9 @@ void
trap_init(void)
{
/* Tell PAL-code what global pointer we want in the kernel. */
- register unsigned long gptr __asm__("$29");
+ unsigned long gptr;
+
+ __asm__ __volatile__("mov $29, %0" : "=r" (gptr));
wrkgp(gptr);
wrent(entArith, 1);
diff --git a/arch/alpha/kernel/vmlinux.lds.S b/arch/alpha/kernel/vmlinux.lds.S
index 2efa7dfc798a..95704e64b6a6 100644
--- a/arch/alpha/kernel/vmlinux.lds.S
+++ b/arch/alpha/kernel/vmlinux.lds.S
@@ -28,6 +28,8 @@ SECTIONS
TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
+ IRQENTRY_TEXT
+ SOFTIRQENTRY_TEXT
*(.fixup)
*(.gnu.warning)
} :text
@@ -71,6 +73,7 @@ SECTIONS
STABS_DEBUG
DWARF_DEBUG
+ MODINFO
ELF_DETAILS
DISCARDS
diff --git a/arch/alpha/lib/strncpy.S b/arch/alpha/lib/strncpy.S
deleted file mode 100644
index cb90cf022df3..000000000000
--- a/arch/alpha/lib/strncpy.S
+++ /dev/null
@@ -1,83 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * arch/alpha/lib/strncpy.S
- * Contributed by Richard Henderson (rth@tamu.edu)
- *
- * Copy no more than COUNT bytes of the null-terminated string from
- * SRC to DST. If SRC does not cover all of COUNT, the balance is
- * zeroed.
- *
- * Or, rather, if the kernel cared about that weird ANSI quirk. This
- * version has cropped that bit o' nastiness as well as assuming that
- * __stxncpy is in range of a branch.
- */
-#include <linux/export.h>
- .set noat
- .set noreorder
-
- .text
-
- .align 4
- .globl strncpy
- .ent strncpy
-strncpy:
- .frame $30, 0, $26
- .prologue 0
-
- mov $16, $0 # set return value now
- beq $18, $zerolen
- unop
- bsr $23, __stxncpy # do the work of the copy
-
- unop
- bne $18, $multiword # do we have full words left?
- subq $24, 1, $3 # nope
- subq $27, 1, $4
-
- or $3, $24, $3 # clear the bits between the last
- or $4, $27, $4 # written byte and the last byte in COUNT
- andnot $3, $4, $4
- zap $1, $4, $1
-
- stq_u $1, 0($16)
- ret
-
- .align 4
-$multiword:
- subq $27, 1, $2 # clear the final bits in the prev word
- or $2, $27, $2
- zapnot $1, $2, $1
- subq $18, 1, $18
-
- stq_u $1, 0($16)
- addq $16, 8, $16
- unop
- beq $18, 1f
-
- nop
- unop
- nop
- blbc $18, 0f
-
- stq_u $31, 0($16) # zero one word
- subq $18, 1, $18
- addq $16, 8, $16
- beq $18, 1f
-
-0: stq_u $31, 0($16) # zero two words
- subq $18, 2, $18
- stq_u $31, 8($16)
- addq $16, 16, $16
- bne $18, 0b
-
-1: ldq_u $1, 0($16) # clear the leading bits in the final word
- subq $24, 1, $2
- or $2, $24, $2
-
- zap $1, $2, $1
- stq_u $1, 0($16)
-$zerolen:
- ret
-
- .end strncpy
- EXPORT_SYMBOL(strncpy)
diff --git a/arch/alpha/lib/styncpy.S b/arch/alpha/lib/styncpy.S
index 72fc2754eb57..f1078ff12530 100644
--- a/arch/alpha/lib/styncpy.S
+++ b/arch/alpha/lib/styncpy.S
@@ -1,4 +1,3 @@
-#include "strncpy.S"
#ifdef CONFIG_ALPHA_EV67
#include "ev67-strncat.S"
#else
diff --git a/arch/alpha/math-emu/math.c b/arch/alpha/math-emu/math.c
index 68d420bfd3c0..e3f2df3729e3 100644
--- a/arch/alpha/math-emu/math.c
+++ b/arch/alpha/math-emu/math.c
@@ -52,13 +52,13 @@ MODULE_DESCRIPTION("FP Software completion module");
MODULE_LICENSE("GPL v2");
extern long (*alpha_fp_emul_imprecise)(struct pt_regs *, unsigned long);
-extern long (*alpha_fp_emul) (unsigned long pc);
+extern long (*alpha_fp_emul) (unsigned long pc, unsigned long summary);
static long (*save_emul_imprecise)(struct pt_regs *, unsigned long);
-static long (*save_emul) (unsigned long pc);
+static long (*save_emul) (unsigned long pc, unsigned long summary);
long do_alpha_fp_emul_imprecise(struct pt_regs *, unsigned long);
-long do_alpha_fp_emul(unsigned long);
+long do_alpha_fp_emul(unsigned long, unsigned long);
static int alpha_fp_emul_init_module(void)
{
@@ -86,7 +86,22 @@ module_exit(alpha_fp_emul_cleanup_module);
/*
- * Emulate the floating point instruction at address PC. Returns -1 if the
+ * Exception bits of the exception summary register (EXC_SUM). Bit 0 is the
+ * software completion bit; bits 1 through 5 report the exceptions the
+ * hardware attributed to the trapping instruction, and lie at the same
+ * positions as the corresponding IEEE_TRAP_ENABLE_* bits.
+ */
+#define EXC_SUM_INV (1UL << 1)
+#define EXC_SUM_DZE (1UL << 2)
+#define EXC_SUM_OVF (1UL << 3)
+#define EXC_SUM_UNF (1UL << 4)
+#define EXC_SUM_INE (1UL << 5)
+#define EXC_SUM_MASK (EXC_SUM_INV | EXC_SUM_DZE | EXC_SUM_OVF \
+ | EXC_SUM_UNF | EXC_SUM_INE)
+
+/*
+ * Emulate the floating point instruction at address PC. SUMMARY is the
+ * exception summary register the trap was delivered with. Returns -1 if the
* instruction to be emulated is illegal (such as with the opDEC trap), else
* the SI_CODE for a SIGFPE signal, else 0 if everything's ok.
*
@@ -95,7 +110,7 @@ module_exit(alpha_fp_emul_cleanup_module);
* stick the result of the operation into the appropriate register.
*/
long
-alpha_fp_emul (unsigned long pc)
+alpha_fp_emul (unsigned long pc, unsigned long summary)
{
FP_DECL_EX;
FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR);
@@ -300,12 +315,56 @@ done:
swcr |= (_fex << IEEE_STATUS_TO_EXCSUM_SHIFT);
current_thread_info()->ieee_state
|= (_fex << IEEE_STATUS_TO_EXCSUM_SHIFT);
+ }
- /* Update hardware control register. */
- fpcr &= (~FPCR_MASK | FPCR_DYN_MASK);
- fpcr |= ieee_swcr_to_fpcr(swcr);
- wrfpcr(fpcr);
+ /*
+ * EV6 records exception status bits in the FPCR before delivering the
+ * software completion trap, and swcr_update_status() above merged them
+ * into SWCR. Some can be wrong for the instruction we just emulated:
+ * a CVTTS of a value exactly representable as a subnormal sets FPCR_UNF
+ * even though the result is exact. Clear the exceptions the trap
+ * reported but that soft-fp did not raise.
+ */
+ if (implver() == IMPLVER_EV6) {
+ unsigned long spurious = summary & EXC_SUM_MASK;
+
+ if (spurious & (EXC_SUM_UNF | EXC_SUM_OVF)) {
+ /*
+ * EXC_SUM reports only the underflow or overflow,
+ * but the hardware sets INE alongside it in the FPCR.
+ */
+ spurious |= EXC_SUM_INE;
+ } else if (!spurious) {
+ /*
+ * No exception reported, so this was a denormal
+ * operand trap, for which INE and UNF can be
+ * fabricated as well.
+ */
+ spurious = EXC_SUM_INE | EXC_SUM_UNF;
+ }
+ /*
+ * Never clear an exception software has confirmed. Every
+ * instruction that genuinely raises one traps for software
+ * completion and is recorded in ieee_state above, so a bit
+ * found there -- including one just set from _fex -- belongs
+ * to this or an earlier instruction and must survive.
+ */
+ spurious &= ~(current_thread_info()->ieee_state
+ >> IEEE_STATUS_TO_EXCSUM_SHIFT);
+
+ swcr &= ~(spurious << IEEE_STATUS_TO_EXCSUM_SHIFT);
+ }
+
+ /*
+ * Update hardware control register. This has to happen even when
+ * soft-fp raised nothing, to clear any fabricated bits.
+ */
+ fpcr &= (~FPCR_MASK | FPCR_DYN_MASK);
+ fpcr |= ieee_swcr_to_fpcr(swcr);
+ wrfpcr(fpcr);
+
+ if (_fex) {
/* Do we generate a signal? */
_fex = _fex & swcr & IEEE_TRAP_ENABLE_MASK;
si_code = 0;
@@ -387,9 +446,16 @@ alpha_fp_emul_imprecise (struct pt_regs *regs, unsigned long write_mask)
break;
}
if (!write_mask) {
- /* Re-execute insns in the trap-shadow. */
+ /*
+ * Re-execute insns in the trap-shadow. Pass no
+ * exception summary: it describes the trap, which
+ * was taken anywhere in the shadow, and so is not
+ * attribution for this instruction. Nothing is
+ * lost, since only EV6 -- which traps precisely and
+ * never comes this way -- needs it.
+ */
regs->pc = trigger_pc + 4;
- si_code = alpha_fp_emul(trigger_pc);
+ si_code = alpha_fp_emul(trigger_pc, 0);
goto egress;
}
trigger_pc -= 4;
diff --git a/arch/alpha/mm/Makefile b/arch/alpha/mm/Makefile
index 101dbd06b4ce..2d05664058f6 100644
--- a/arch/alpha/mm/Makefile
+++ b/arch/alpha/mm/Makefile
@@ -3,4 +3,4 @@
# Makefile for the linux alpha-specific parts of the memory manager.
#
-obj-y := init.o fault.o
+obj-y := init.o fault.o tlbflush.o
diff --git a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c
index 4c5ab9cd8a0a..f4d65a60c869 100644
--- a/arch/alpha/mm/init.c
+++ b/arch/alpha/mm/init.c
@@ -63,8 +63,7 @@ pgd_alloc(struct mm_struct *mm)
static inline unsigned long
load_PCB(struct pcb_struct *pcb)
{
- register unsigned long sp __asm__("$30");
- pcb->ksp = sp;
+ pcb->ksp = (unsigned long)current_stack_pointer;
return __reload_thread(pcb);
}
@@ -208,12 +207,8 @@ callback_init(void * kernel_end)
return kernel_end;
}
-/*
- * paging_init() sets up the memory map.
- */
-void __init paging_init(void)
+void __init arch_zone_limits_init(unsigned long *max_zone_pfn)
{
- unsigned long max_zone_pfn[MAX_NR_ZONES] = {0, };
unsigned long dma_pfn;
dma_pfn = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
@@ -221,11 +216,13 @@ void __init paging_init(void)
max_zone_pfn[ZONE_DMA] = dma_pfn;
max_zone_pfn[ZONE_NORMAL] = max_pfn;
+}
- /* Initialize mem_map[]. */
- free_area_init(max_zone_pfn);
-
- /* Initialize the kernel's ZERO_PGE. */
+/*
+ * paging_init() initializes the kernel's ZERO_PGE.
+ */
+void __init paging_init(void)
+{
memset(absolute_pointer(ZERO_PGE), 0, PAGE_SIZE);
}
diff --git a/arch/alpha/mm/tlbflush.c b/arch/alpha/mm/tlbflush.c
new file mode 100644
index 000000000000..ccbc317b9a34
--- /dev/null
+++ b/arch/alpha/mm/tlbflush.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Alpha TLB shootdown helpers
+ *
+ * Copyright (C) 2025 Magnus Lindholm <linmag7@gmail.com>
+ *
+ * Alpha-specific TLB flush helpers that cannot be expressed purely
+ * as inline functions.
+ *
+ * These helpers provide combined MM context handling (ASN rollover)
+ * and immediate TLB invalidation for page migration and memory
+ * compaction paths, where lazy shootdowns are insufficient.
+ */
+
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/sched.h>
+#include <asm/tlbflush.h>
+#include <asm/pal.h>
+#include <asm/mmu_context.h>
+
+#define asn_locked() (cpu_data[smp_processor_id()].asn_lock)
+
+/*
+ * Migration/compaction helper: combine mm context (ASN) handling with an
+ * immediate per-page TLB invalidate and (for exec) an instruction barrier.
+ *
+ * This mirrors the SMP combined IPI handler semantics, but runs locally on UP.
+ */
+#ifndef CONFIG_SMP
+void migrate_flush_tlb_page(struct vm_area_struct *vma,
+ unsigned long addr)
+{
+ struct mm_struct *mm = vma->vm_mm;
+ int tbi_type = (vma->vm_flags & VM_EXEC) ? 3 : 2;
+
+ /*
+ * First do the mm-context side:
+ * If we're currently running this mm, reload a fresh context ASN.
+ * Otherwise, mark context invalid.
+ *
+ * On UP, this is mostly about matching the SMP semantics and ensuring
+ * exec/i-cache tagging assumptions hold when compaction migrates pages.
+ */
+ if (mm == current->active_mm)
+ flush_tlb_current(mm);
+ else
+ flush_tlb_other(mm);
+
+ /*
+ * Then do the immediate translation kill for this VA.
+ * For exec mappings, order instruction fetch after invalidation.
+ */
+ tbi(tbi_type, addr);
+}
+
+#else
+struct tlb_mm_and_addr {
+ struct mm_struct *mm;
+ unsigned long addr;
+ int tbi_type; /* 2 = DTB, 3 = ITB+DTB */
+};
+
+static void ipi_flush_mm_and_page(void *x)
+{
+ struct tlb_mm_and_addr *d = x;
+
+ /* Part 1: mm context side (Alpha uses ASN/context as a key mechanism). */
+ if (d->mm == current->active_mm && !asn_locked())
+ __load_new_mm_context(d->mm);
+ else
+ flush_tlb_other(d->mm);
+
+ /* Part 2: immediate per-VA invalidation on this CPU. */
+ tbi(d->tbi_type, d->addr);
+}
+
+void migrate_flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
+{
+ struct mm_struct *mm = vma->vm_mm;
+ struct tlb_mm_and_addr d = {
+ .mm = mm,
+ .addr = addr,
+ .tbi_type = (vma->vm_flags & VM_EXEC) ? 3 : 2,
+ };
+
+ /*
+ * One synchronous rendezvous: every CPU runs ipi_flush_mm_and_page().
+ * This is the "combined" version of flush_tlb_mm + per-page invalidate.
+ */
+ preempt_disable();
+ on_each_cpu(ipi_flush_mm_and_page, &d, 1);
+
+ /*
+ * mimic flush_tlb_mm()'s mm_users<=1 optimization.
+ */
+ if (atomic_read(&mm->mm_users) <= 1) {
+
+ int cpu, this_cpu;
+ this_cpu = smp_processor_id();
+
+ for (cpu = 0; cpu < NR_CPUS; cpu++) {
+ if (!cpu_online(cpu) || cpu == this_cpu)
+ continue;
+ if (READ_ONCE(mm->context[cpu]))
+ WRITE_ONCE(mm->context[cpu], 0);
+ }
+ }
+ preempt_enable();
+}
+
+#endif