summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/alpha/include/asm/console.h4
-rw-r--r--arch/alpha/include/asm/page.h4
-rw-r--r--arch/alpha/include/asm/pal.h4
-rw-r--r--arch/alpha/include/asm/thread_info.h8
-rw-r--r--arch/alpha/include/uapi/asm/ioctls.h8
-rw-r--r--arch/arm/Kconfig4
-rw-r--r--arch/arm/include/asm/word-at-a-time.h10
-rw-r--r--arch/arm/mm/alignment.c6
-rw-r--r--arch/arm/mm/fault.c100
-rw-r--r--arch/csky/abiv1/inc/abi/regdef.h2
-rw-r--r--arch/csky/abiv2/inc/abi/regdef.h2
-rw-r--r--arch/csky/include/asm/barrier.h4
-rw-r--r--arch/csky/include/asm/cache.h2
-rw-r--r--arch/csky/include/asm/ftrace.h4
-rw-r--r--arch/csky/include/asm/jump_label.h4
-rw-r--r--arch/csky/include/asm/page.h4
-rw-r--r--arch/csky/include/asm/ptrace.h4
-rw-r--r--arch/csky/include/asm/sections.h1
-rw-r--r--arch/csky/include/asm/string.h2
-rw-r--r--arch/csky/include/asm/thread_info.h4
-rw-r--r--arch/csky/include/uapi/asm/ptrace.h4
-rw-r--r--arch/csky/mm/fault.c4
-rw-r--r--arch/mips/Kconfig2
-rw-r--r--arch/mips/alchemy/board-mtx1.c181
-rw-r--r--arch/mips/boot/dts/Makefile35
-rw-r--r--arch/mips/boot/dts/realtek/Makefile4
-rw-r--r--arch/mips/configs/loongson1_defconfig16
-rw-r--r--arch/mips/include/asm/pgalloc.h3
-rw-r--r--arch/mips/kernel/ftrace.c25
-rw-r--r--arch/mips/kernel/genex.S8
-rw-r--r--arch/mips/kvm/interrupt.c20
-rw-r--r--arch/nios2/include/asm/uaccess.h8
-rw-r--r--arch/s390/Kconfig2
-rw-r--r--arch/s390/boot/vmem.c16
-rw-r--r--arch/s390/include/asm/bug.h5
-rw-r--r--arch/s390/include/asm/page.h2
-rw-r--r--arch/s390/include/asm/pci.h5
-rw-r--r--arch/s390/mm/gmap_helpers.c9
-rw-r--r--arch/s390/mm/pageattr.c2
-rw-r--r--arch/s390/mm/vmem.c14
-rw-r--r--arch/s390/pci/pci.c6
-rw-r--r--arch/s390/pci/pci_bus.c18
-rw-r--r--arch/s390/pci/pci_irq.c332
-rw-r--r--arch/x86/include/asm/bug.h2
-rw-r--r--arch/x86/include/asm/string_64.h6
-rw-r--r--arch/x86/include/asm/uaccess_64.h2
46 files changed, 586 insertions, 326 deletions
diff --git a/arch/alpha/include/asm/console.h b/arch/alpha/include/asm/console.h
index 088b7b9eb15a..1cabdb6064bb 100644
--- a/arch/alpha/include/asm/console.h
+++ b/arch/alpha/include/asm/console.h
@@ -4,7 +4,7 @@
#include <uapi/asm/console.h>
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
extern long callback_puts(long unit, const char *s, long length);
extern long callback_getc(long unit);
extern long callback_open_console(void);
@@ -26,5 +26,5 @@ struct crb_struct;
struct hwrpb_struct;
extern int callback_init_done;
extern void * callback_init(void *);
-#endif /* __ASSEMBLY__ */
+#endif /* __ASSEMBLER__ */
#endif /* __AXP_CONSOLE_H */
diff --git a/arch/alpha/include/asm/page.h b/arch/alpha/include/asm/page.h
index 5ec4c77e432e..d2c6667d73e9 100644
--- a/arch/alpha/include/asm/page.h
+++ b/arch/alpha/include/asm/page.h
@@ -6,7 +6,7 @@
#include <asm/pal.h>
#include <vdso/page.h>
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
#define STRICT_MM_TYPECHECKS
@@ -74,7 +74,7 @@ typedef struct page *pgtable_t;
#define PAGE_OFFSET 0xfffffc0000000000
#endif
-#endif /* !__ASSEMBLY__ */
+#endif /* !__ASSEMBLER__ */
#define __pa(x) ((unsigned long) (x) - PAGE_OFFSET)
#define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET))
diff --git a/arch/alpha/include/asm/pal.h b/arch/alpha/include/asm/pal.h
index db2b3b18b34c..799a64c05198 100644
--- a/arch/alpha/include/asm/pal.h
+++ b/arch/alpha/include/asm/pal.h
@@ -4,7 +4,7 @@
#include <uapi/asm/pal.h>
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
extern void halt(void) __attribute__((noreturn));
#define __halt() __asm__ __volatile__ ("call_pal %0 #halt" : : "i" (PAL_halt))
@@ -183,5 +183,5 @@ qemu_get_vmtime(void)
return v0;
}
-#endif /* !__ASSEMBLY__ */
+#endif /* !__ASSEMBLER__ */
#endif /* __ALPHA_PAL_H */
diff --git a/arch/alpha/include/asm/thread_info.h b/arch/alpha/include/asm/thread_info.h
index 4a4d00b37986..98ccbca64984 100644
--- a/arch/alpha/include/asm/thread_info.h
+++ b/arch/alpha/include/asm/thread_info.h
@@ -4,14 +4,14 @@
#ifdef __KERNEL__
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
#include <asm/processor.h>
#include <asm/types.h>
#include <asm/hwrpb.h>
#include <asm/sysinfo.h>
#endif
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
struct thread_info {
struct pcb_struct pcb; /* palcode state */
@@ -44,7 +44,7 @@ register struct thread_info *__current_thread_info __asm__("$8");
register unsigned long *current_stack_pointer __asm__ ("$30");
-#endif /* __ASSEMBLY__ */
+#endif /* __ASSEMBLER__ */
/* Thread information allocation. */
#define THREAD_SIZE_ORDER 1
@@ -110,7 +110,7 @@ register unsigned long *current_stack_pointer __asm__ ("$30");
put_user(res, (int __user *)(value)); \
})
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
extern void __save_fpu(void);
static inline void save_fpu(void)
diff --git a/arch/alpha/include/uapi/asm/ioctls.h b/arch/alpha/include/uapi/asm/ioctls.h
index 971311605288..a09d04b49cc6 100644
--- a/arch/alpha/include/uapi/asm/ioctls.h
+++ b/arch/alpha/include/uapi/asm/ioctls.h
@@ -23,10 +23,10 @@
#define TCSETSW _IOW('t', 21, struct termios)
#define TCSETSF _IOW('t', 22, struct termios)
-#define TCGETA _IOR('t', 23, struct termio)
-#define TCSETA _IOW('t', 24, struct termio)
-#define TCSETAW _IOW('t', 25, struct termio)
-#define TCSETAF _IOW('t', 28, struct termio)
+#define TCGETA 0x40127417
+#define TCSETA 0x80127418
+#define TCSETAW 0x80127419
+#define TCSETAF 0x8012741c
#define TCSBRK _IO('t', 29)
#define TCXONC _IO('t', 30)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index ff61891abe53..fa83c040ee2d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -82,7 +82,7 @@ config ARM
select HAS_IOPORT
select HAVE_ARCH_AUDITSYSCALL if AEABI && !OABI_COMPAT
select HAVE_ARCH_BITREVERSE if (CPU_32v7M || CPU_32v7) && !CPU_32v6
- select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL && !CPU_ENDIAN_BE32 && MMU
+ select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL && !CPU_ENDIAN_BE32 && MMU && (!PREEMPT_RT || !SMP)
select HAVE_ARCH_KFENCE if MMU && !XIP_KERNEL
select HAVE_ARCH_KGDB if !CPU_ENDIAN_BE32 && MMU
select HAVE_ARCH_KASAN if MMU && !XIP_KERNEL
@@ -1213,7 +1213,7 @@ config HIGHMEM
config HIGHPTE
bool "Allocate 2nd-level pagetables from highmem" if EXPERT
- depends on HIGHMEM
+ depends on HIGHMEM && !PREEMPT_RT
default y
help
The VM uses one page of physical memory for each page table.
diff --git a/arch/arm/include/asm/word-at-a-time.h b/arch/arm/include/asm/word-at-a-time.h
index f9a3897b06e7..5023f98d8293 100644
--- a/arch/arm/include/asm/word-at-a-time.h
+++ b/arch/arm/include/asm/word-at-a-time.h
@@ -67,7 +67,7 @@ static inline unsigned long find_zero(unsigned long mask)
*/
static inline unsigned long load_unaligned_zeropad(const void *addr)
{
- unsigned long ret, offset;
+ unsigned long ret, tmp;
/* Load word from unaligned pointer addr */
asm(
@@ -75,9 +75,9 @@ static inline unsigned long load_unaligned_zeropad(const void *addr)
"2:\n"
" .pushsection .text.fixup,\"ax\"\n"
" .align 2\n"
- "3: and %1, %2, #0x3\n"
- " bic %2, %2, #0x3\n"
- " ldr %0, [%2]\n"
+ "3: bic %1, %2, #0x3\n"
+ " ldr %0, [%1]\n"
+ " and %1, %2, #0x3\n"
" lsl %1, %1, #0x3\n"
#ifndef __ARMEB__
" lsr %0, %0, %1\n"
@@ -90,7 +90,7 @@ static inline unsigned long load_unaligned_zeropad(const void *addr)
" .align 3\n"
" .long 1b, 3b\n"
" .popsection"
- : "=&r" (ret), "=&r" (offset)
+ : "=&r" (ret), "=&r" (tmp)
: "r" (addr), "Qo" (*(unsigned long *)addr));
return ret;
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index 3c6ddb1afdc4..812380f30ae3 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -19,10 +19,11 @@
#include <linux/init.h>
#include <linux/sched/signal.h>
#include <linux/uaccess.h>
+#include <linux/unaligned.h>
#include <asm/cp15.h>
#include <asm/system_info.h>
-#include <linux/unaligned.h>
+#include <asm/system_misc.h>
#include <asm/opcodes.h>
#include "fault.h"
@@ -809,6 +810,9 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
int thumb2_32b = 0;
int fault;
+ if (addr >= TASK_SIZE && user_mode(regs))
+ harden_branch_predictor();
+
if (interrupts_enabled(regs))
local_irq_enable();
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index 2bc828a1940c..ed4330cc3f4e 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -128,6 +128,19 @@ static inline bool is_translation_fault(unsigned int fsr)
return false;
}
+static inline bool is_permission_fault(unsigned int fsr)
+{
+ int fs = fsr_fs(fsr);
+#ifdef CONFIG_ARM_LPAE
+ if ((fs & FS_MMU_NOLL_MASK) == FS_PERM_NOLL)
+ return true;
+#else
+ if (fs == FS_L1_PERM || fs == FS_L2_PERM)
+ return true;
+#endif
+ return false;
+}
+
static void die_kernel_fault(const char *msg, struct mm_struct *mm,
unsigned long addr, unsigned int fsr,
struct pt_regs *regs)
@@ -162,6 +175,8 @@ __do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
*/
if (addr < PAGE_SIZE) {
msg = "NULL pointer dereference";
+ } else if (is_permission_fault(fsr) && fsr & FSR_LNX_PF) {
+ msg = "execution of memory";
} else {
if (is_translation_fault(fsr) &&
kfence_handle_page_fault(addr, is_write_fault(fsr), regs))
@@ -183,9 +198,6 @@ __do_user_fault(unsigned long addr, unsigned int fsr, unsigned int sig,
{
struct task_struct *tsk = current;
- if (addr > TASK_SIZE)
- harden_branch_predictor();
-
#ifdef CONFIG_DEBUG_USER
if (((user_debug & UDBG_SEGV) && (sig == SIGSEGV)) ||
((user_debug & UDBG_BUS) && (sig == SIGBUS))) {
@@ -225,19 +237,6 @@ void do_bad_area(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
}
#ifdef CONFIG_MMU
-static inline bool is_permission_fault(unsigned int fsr)
-{
- int fs = fsr_fs(fsr);
-#ifdef CONFIG_ARM_LPAE
- if ((fs & FS_MMU_NOLL_MASK) == FS_PERM_NOLL)
- return true;
-#else
- if (fs == FS_L1_PERM || fs == FS_L2_PERM)
- return true;
-#endif
- return false;
-}
-
#ifdef CONFIG_CPU_TTBR0_PAN
static inline bool ttbr0_usermode_access_allowed(struct pt_regs *regs)
{
@@ -260,6 +259,37 @@ static inline bool ttbr0_usermode_access_allowed(struct pt_regs *regs)
#endif
static int __kprobes
+do_kernel_address_page_fault(struct mm_struct *mm, unsigned long addr,
+ unsigned int fsr, struct pt_regs *regs)
+{
+ if (user_mode(regs)) {
+ /*
+ * Fault from user mode for a kernel space address. User mode
+ * should not be faulting in kernel space, which includes the
+ * vector/khelper page. Handle the branch predictor hardening
+ * while interrupts are still disabled, then send a SIGSEGV.
+ */
+ harden_branch_predictor();
+ __do_user_fault(addr, fsr, SIGSEGV, SEGV_MAPERR, regs);
+ } else {
+ /*
+ * Fault from kernel mode. Enable interrupts if they were
+ * enabled in the parent context. Section (upper page table)
+ * translation faults are handled via do_translation_fault(),
+ * so we will only get here for a non-present kernel space
+ * PTE or PTE permission fault. This may happen in exceptional
+ * circumstances and need the fixup tables to be walked.
+ */
+ if (interrupts_enabled(regs))
+ local_irq_enable();
+
+ __do_kernel_fault(mm, addr, fsr, regs);
+ }
+
+ return 0;
+}
+
+static int __kprobes
do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
{
struct mm_struct *mm = current->mm;
@@ -272,6 +302,12 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
if (kprobe_page_fault(regs, fsr))
return 0;
+ /*
+ * Handle kernel addresses faults separately, which avoids touching
+ * the mmap lock from contexts that are not able to sleep.
+ */
+ if (addr >= TASK_SIZE)
+ return do_kernel_address_page_fault(mm, addr, fsr, regs);
/* Enable interrupts if they were enabled in the parent context. */
if (interrupts_enabled(regs))
@@ -448,16 +484,20 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
* We enter here because the first level page table doesn't contain
* a valid entry for the address.
*
- * If the address is in kernel space (>= TASK_SIZE), then we are
- * probably faulting in the vmalloc() area.
+ * If this is a user address (addr < TASK_SIZE), we handle this as a
+ * normal page fault. This leaves the remainder of the function to handle
+ * kernel address translation faults.
+ *
+ * Since user mode is not permitted to access kernel addresses, pass these
+ * directly to do_kernel_address_page_fault() to handle.
*
- * If the init_task's first level page tables contains the relevant
- * entry, we copy the it to this task. If not, we send the process
- * a signal, fixup the exception, or oops the kernel.
+ * Otherwise, we're probably faulting in the vmalloc() area, so try to fix
+ * that up. Note that we must not take any locks or enable interrupts in
+ * this case.
*
- * NOTE! We MUST NOT take any locks for this case. We may be in an
- * interrupt or a critical region, and should only copy the information
- * from the master page table, nothing more.
+ * If vmalloc() fixup fails, that means the non-leaf page tables did not
+ * contain an entry for this address, so handle this via
+ * do_kernel_address_page_fault().
*/
#ifdef CONFIG_MMU
static int __kprobes
@@ -523,7 +563,8 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
return 0;
bad_area:
- do_bad_area(addr, fsr, regs);
+ do_kernel_address_page_fault(current->mm, addr, fsr, regs);
+
return 0;
}
#else /* CONFIG_MMU */
@@ -543,7 +584,16 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
static int
do_sect_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
{
+ /*
+ * If this is a kernel address, but from user mode, then userspace
+ * is trying bad stuff. Invoke the branch predictor handling.
+ * Interrupts are disabled here.
+ */
+ if (addr >= TASK_SIZE && user_mode(regs))
+ harden_branch_predictor();
+
do_bad_area(addr, fsr, regs);
+
return 0;
}
#endif /* CONFIG_ARM_LPAE */
diff --git a/arch/csky/abiv1/inc/abi/regdef.h b/arch/csky/abiv1/inc/abi/regdef.h
index 7b386fd67070..c75ecf2cafd7 100644
--- a/arch/csky/abiv1/inc/abi/regdef.h
+++ b/arch/csky/abiv1/inc/abi/regdef.h
@@ -3,7 +3,7 @@
#ifndef __ASM_CSKY_REGDEF_H
#define __ASM_CSKY_REGDEF_H
-#ifdef __ASSEMBLY__
+#ifdef __ASSEMBLER__
#define syscallid r1
#else
#define syscallid "r1"
diff --git a/arch/csky/abiv2/inc/abi/regdef.h b/arch/csky/abiv2/inc/abi/regdef.h
index 0933addbc27b..fc08d56ccdbe 100644
--- a/arch/csky/abiv2/inc/abi/regdef.h
+++ b/arch/csky/abiv2/inc/abi/regdef.h
@@ -3,7 +3,7 @@
#ifndef __ASM_CSKY_REGDEF_H
#define __ASM_CSKY_REGDEF_H
-#ifdef __ASSEMBLY__
+#ifdef __ASSEMBLER__
#define syscallid r7
#else
#define syscallid "r7"
diff --git a/arch/csky/include/asm/barrier.h b/arch/csky/include/asm/barrier.h
index 15de58b10aec..c33fdcfe3770 100644
--- a/arch/csky/include/asm/barrier.h
+++ b/arch/csky/include/asm/barrier.h
@@ -3,7 +3,7 @@
#ifndef __ASM_CSKY_BARRIER_H
#define __ASM_CSKY_BARRIER_H
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
#define nop() asm volatile ("nop\n":::"memory")
@@ -84,5 +84,5 @@
#include <asm-generic/barrier.h>
-#endif /* __ASSEMBLY__ */
+#endif /* __ASSEMBLER__ */
#endif /* __ASM_CSKY_BARRIER_H */
diff --git a/arch/csky/include/asm/cache.h b/arch/csky/include/asm/cache.h
index 4b5c09bf1d25..d575482e0fce 100644
--- a/arch/csky/include/asm/cache.h
+++ b/arch/csky/include/asm/cache.h
@@ -10,7 +10,7 @@
#define ARCH_DMA_MINALIGN L1_CACHE_BYTES
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
void dcache_wb_line(unsigned long start);
diff --git a/arch/csky/include/asm/ftrace.h b/arch/csky/include/asm/ftrace.h
index 00f9f7647e3f..21532f218058 100644
--- a/arch/csky/include/asm/ftrace.h
+++ b/arch/csky/include/asm/ftrace.h
@@ -11,7 +11,7 @@
#define MCOUNT_ADDR ((unsigned long)_mcount)
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
extern void _mcount(unsigned long);
@@ -28,5 +28,5 @@ struct dyn_arch_ftrace {
void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
unsigned long frame_pointer);
-#endif /* !__ASSEMBLY__ */
+#endif /* !__ASSEMBLER__ */
#endif /* __ASM_CSKY_FTRACE_H */
diff --git a/arch/csky/include/asm/jump_label.h b/arch/csky/include/asm/jump_label.h
index ef2e37a10a0f..603b0caa8024 100644
--- a/arch/csky/include/asm/jump_label.h
+++ b/arch/csky/include/asm/jump_label.h
@@ -3,7 +3,7 @@
#ifndef __ASM_CSKY_JUMP_LABEL_H
#define __ASM_CSKY_JUMP_LABEL_H
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
#include <linux/types.h>
@@ -48,5 +48,5 @@ void arch_jump_label_transform_static(struct jump_entry *entry,
enum jump_label_type type);
#define arch_jump_label_transform_static arch_jump_label_transform_static
-#endif /* __ASSEMBLY__ */
+#endif /* __ASSEMBLER__ */
#endif /* __ASM_CSKY_JUMP_LABEL_H */
diff --git a/arch/csky/include/asm/page.h b/arch/csky/include/asm/page.h
index 4911d0892b71..76774dbce869 100644
--- a/arch/csky/include/asm/page.h
+++ b/arch/csky/include/asm/page.h
@@ -26,7 +26,7 @@
#define PHYS_OFFSET_OFFSET (CONFIG_DRAM_BASE & (SSEG_SIZE - 1))
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
#include <linux/pfn.h>
@@ -84,5 +84,5 @@ static inline unsigned long virt_to_pfn(const void *kaddr)
#include <asm-generic/memory_model.h>
#include <asm-generic/getorder.h>
-#endif /* !__ASSEMBLY__ */
+#endif /* !__ASSEMBLER__ */
#endif /* __ASM_CSKY_PAGE_H */
diff --git a/arch/csky/include/asm/ptrace.h b/arch/csky/include/asm/ptrace.h
index 0634b7895d81..5f01839e1184 100644
--- a/arch/csky/include/asm/ptrace.h
+++ b/arch/csky/include/asm/ptrace.h
@@ -8,7 +8,7 @@
#include <linux/types.h>
#include <linux/compiler.h>
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
#define PS_S 0x80000000 /* Supervisor Mode */
@@ -98,5 +98,5 @@ static inline unsigned long regs_get_register(struct pt_regs *regs,
asmlinkage int syscall_trace_enter(struct pt_regs *regs);
asmlinkage void syscall_trace_exit(struct pt_regs *regs);
-#endif /* __ASSEMBLY__ */
+#endif /* __ASSEMBLER__ */
#endif /* __ASM_CSKY_PTRACE_H */
diff --git a/arch/csky/include/asm/sections.h b/arch/csky/include/asm/sections.h
index 83e82b7c0f6c..ee5cdf226a9b 100644
--- a/arch/csky/include/asm/sections.h
+++ b/arch/csky/include/asm/sections.h
@@ -8,5 +8,6 @@
extern char _start[];
asmlinkage void csky_start(unsigned int unused, void *dtb_start);
+asmlinkage void csky_start_secondary(void);
#endif /* __ASM_SECTIONS_H */
diff --git a/arch/csky/include/asm/string.h b/arch/csky/include/asm/string.h
index a0d81e9d6b8f..82e99f52b547 100644
--- a/arch/csky/include/asm/string.h
+++ b/arch/csky/include/asm/string.h
@@ -3,7 +3,7 @@
#ifndef _CSKY_STRING_MM_H_
#define _CSKY_STRING_MM_H_
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
#include <linux/types.h>
#include <linux/compiler.h>
#include <abi/string.h>
diff --git a/arch/csky/include/asm/thread_info.h b/arch/csky/include/asm/thread_info.h
index b5ed788f0c68..fdd4f8ad45ac 100644
--- a/arch/csky/include/asm/thread_info.h
+++ b/arch/csky/include/asm/thread_info.h
@@ -3,7 +3,7 @@
#ifndef _ASM_CSKY_THREAD_INFO_H
#define _ASM_CSKY_THREAD_INFO_H
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
#include <asm/types.h>
#include <asm/page.h>
@@ -51,7 +51,7 @@ static inline struct thread_info *current_thread_info(void)
return (struct thread_info *)(sp & ~(THREAD_SIZE - 1));
}
-#endif /* !__ASSEMBLY__ */
+#endif /* !__ASSEMBLER__ */
#define TIF_SIGPENDING 0 /* signal pending */
#define TIF_NOTIFY_RESUME 1 /* callback before returning to user */
diff --git a/arch/csky/include/uapi/asm/ptrace.h b/arch/csky/include/uapi/asm/ptrace.h
index 3be9c14334a6..90a5c36e4345 100644
--- a/arch/csky/include/uapi/asm/ptrace.h
+++ b/arch/csky/include/uapi/asm/ptrace.h
@@ -3,7 +3,7 @@
#ifndef _CSKY_PTRACE_H
#define _CSKY_PTRACE_H
-#ifndef __ASSEMBLY__
+#ifndef __ASSEMBLER__
struct pt_regs {
unsigned long tls;
@@ -47,5 +47,5 @@ struct user_fp {
unsigned long reserved;
};
-#endif /* __ASSEMBLY__ */
+#endif /* __ASSEMBLER__ */
#endif /* _CSKY_PTRACE_H */
diff --git a/arch/csky/mm/fault.c b/arch/csky/mm/fault.c
index a6ca7dff4215..7ff401108985 100644
--- a/arch/csky/mm/fault.c
+++ b/arch/csky/mm/fault.c
@@ -45,8 +45,8 @@ static inline void csky_cmpxchg_fixup(struct pt_regs *regs)
if (trap_no(regs) != VEC_TLBMODIFIED)
return;
- if (instruction_pointer(regs) == csky_cmpxchg_stw)
- instruction_pointer_set(regs, csky_cmpxchg_ldw);
+ if (instruction_pointer(regs) == (unsigned long)&csky_cmpxchg_stw)
+ instruction_pointer_set(regs, (unsigned long)&csky_cmpxchg_ldw);
return;
}
#endif
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index e8683f58fd3e..b88b97139fa8 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -658,7 +658,7 @@ config EYEQ
select USB_UHCI_BIG_ENDIAN_DESC if CPU_BIG_ENDIAN
select USB_UHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN
select USE_OF
- select HOTPLUG_PARALLEL if SMP
+ select HOTPLUG_PARALLEL if HOTPLUG_CPU
help
Select this to build a kernel supporting EyeQ SoC from Mobileye.
diff --git a/arch/mips/alchemy/board-mtx1.c b/arch/mips/alchemy/board-mtx1.c
index 68ea57511629..cb6be58808a0 100644
--- a/arch/mips/alchemy/board-mtx1.c
+++ b/arch/mips/alchemy/board-mtx1.c
@@ -9,10 +9,8 @@
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
-#include <linux/leds.h>
-#include <linux/gpio.h>
#include <linux/gpio/machine.h>
-#include <linux/gpio_keys.h>
+#include <linux/gpio/property.h>
#include <linux/input.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
@@ -80,64 +78,134 @@ void __init board_setup(void)
/******************************************************************************/
-static struct gpio_keys_button mtx1_gpio_button[] = {
- {
- .gpio = 207,
- .code = BTN_0,
- .desc = "System button",
- }
+static const struct software_node mtx1_gpiochip_node = {
+ .name = "alchemy-gpio2",
};
-static struct gpio_keys_platform_data mtx1_buttons_data = {
- .buttons = mtx1_gpio_button,
- .nbuttons = ARRAY_SIZE(mtx1_gpio_button),
+static const struct software_node mtx1_gpio_keys_node = {
+ .name = "mtx1-gpio-keys",
};
-static struct platform_device mtx1_button = {
- .name = "gpio-keys",
- .id = -1,
- .dev = {
- .platform_data = &mtx1_buttons_data,
- }
+static const struct property_entry mtx1_button_props[] = {
+ PROPERTY_ENTRY_U32("linux,code", BTN_0),
+ PROPERTY_ENTRY_GPIO("gpios", &mtx1_gpiochip_node, 7, GPIO_ACTIVE_HIGH),
+ PROPERTY_ENTRY_STRING("label", "System button"),
+ { }
};
-static struct gpiod_lookup_table mtx1_wdt_gpio_table = {
- .dev_id = "mtx1-wdt.0",
- .table = {
- /* Global number 215 is offset 15 on Alchemy GPIO 2 */
- GPIO_LOOKUP("alchemy-gpio2", 15, NULL, GPIO_ACTIVE_HIGH),
- { },
- },
+static const struct software_node mtx1_button_node = {
+ .parent = &mtx1_gpio_keys_node,
+ .properties = mtx1_button_props,
+};
+
+static const struct software_node *mtx1_gpio_keys_swnodes[] __initconst = {
+ &mtx1_gpio_keys_node,
+ &mtx1_button_node,
+ NULL
};
-static struct platform_device mtx1_wdt = {
+static void __init mtx1_keys_init(void)
+{
+ struct platform_device_info keys_info = {
+ .name = "gpio-keys",
+ .id = PLATFORM_DEVID_NONE,
+ };
+ struct platform_device *pd;
+ int err;
+
+ err = software_node_register_node_group(mtx1_gpio_keys_swnodes);
+ if (err) {
+ pr_err("failed to register gpio-keys software nodes: %d\n", err);
+ return;
+ }
+
+ keys_info.fwnode = software_node_fwnode(&mtx1_gpio_keys_node);
+
+ pd = platform_device_register_full(&keys_info);
+ err = PTR_ERR_OR_ZERO(pd);
+ if (err)
+ pr_err("failed to create gpio-keys device: %d\n", err);
+}
+
+/* Global number 215 is offset 15 on Alchemy GPIO 2 */
+static const struct property_entry mtx1_wdt_props[] = {
+ PROPERTY_ENTRY_GPIO("gpios", &mtx1_gpiochip_node, 15, GPIO_ACTIVE_HIGH),
+ { }
+};
+
+static struct platform_device_info mtx1_wdt_info __initconst = {
.name = "mtx1-wdt",
.id = 0,
+ .properties = mtx1_wdt_props,
};
-static const struct gpio_led default_leds[] = {
- {
- .name = "mtx1:green",
- .gpio = 211,
- }, {
- .name = "mtx1:red",
- .gpio = 212,
- },
+static void __init mtx1_wdt_init(void)
+{
+ struct platform_device *pd;
+ int err;
+
+ pd = platform_device_register_full(&mtx1_wdt_info);
+ err = PTR_ERR_OR_ZERO(pd);
+ if (err)
+ pr_err("failed to create gpio-keys device: %d\n", err);
+}
+
+static const struct software_node mtx1_gpio_leds_node = {
+ .name = "mtx1-leds",
};
-static struct gpio_led_platform_data mtx1_led_data = {
- .num_leds = ARRAY_SIZE(default_leds),
- .leds = default_leds,
+static const struct property_entry mtx1_green_led_props[] = {
+ PROPERTY_ENTRY_GPIO("gpios", &mtx1_gpiochip_node, 11, GPIO_ACTIVE_HIGH),
+ { }
};
-static struct platform_device mtx1_gpio_leds = {
- .name = "leds-gpio",
- .id = -1,
- .dev = {
- .platform_data = &mtx1_led_data,
- }
+static const struct software_node mtx1_green_led_node = {
+ .name = "mtx1:green",
+ .parent = &mtx1_gpio_leds_node,
+ .properties = mtx1_green_led_props,
};
+static const struct property_entry mtx1_red_led_props[] = {
+ PROPERTY_ENTRY_GPIO("gpios", &mtx1_gpiochip_node, 12, GPIO_ACTIVE_HIGH),
+ { }
+};
+
+static const struct software_node mtx1_red_led_node = {
+ .name = "mtx1:red",
+ .parent = &mtx1_gpio_leds_node,
+ .properties = mtx1_red_led_props,
+};
+
+static const struct software_node *mtx1_gpio_leds_swnodes[] = {
+ &mtx1_gpio_leds_node,
+ &mtx1_green_led_node,
+ &mtx1_red_led_node,
+ NULL
+};
+
+static void __init mtx1_leds_init(void)
+{
+ struct platform_device_info led_info = {
+ .name = "leds-gpio",
+ .id = PLATFORM_DEVID_NONE,
+ };
+ struct platform_device *led_dev;
+ int err;
+
+ err = software_node_register_node_group(mtx1_gpio_leds_swnodes);
+ if (err) {
+ pr_err("failed to register LED software nodes: %d\n", err);
+ return;
+ }
+
+ led_info.fwnode = software_node_fwnode(&mtx1_gpio_leds_node);
+
+ led_dev = platform_device_register_full(&led_info);
+ err = PTR_ERR_OR_ZERO(led_dev);
+ if (err)
+ pr_err("failed to create LED device: %d\n", err);
+}
+
static struct mtd_partition mtx1_mtd_partitions[] = {
{
.name = "filesystem",
@@ -247,9 +315,6 @@ static struct platform_device mtx1_pci_host = {
static struct platform_device *mtx1_devs[] __initdata = {
&mtx1_pci_host,
- &mtx1_gpio_leds,
- &mtx1_wdt,
- &mtx1_button,
&mtx1_mtd,
};
@@ -270,16 +335,18 @@ static int __init mtx1_register_devices(void)
au1xxx_override_eth_cfg(0, &mtx1_au1000_eth0_pdata);
- rc = gpio_request(mtx1_gpio_button[0].gpio,
- mtx1_gpio_button[0].desc);
- if (rc < 0) {
- printk(KERN_INFO "mtx1: failed to request %d\n",
- mtx1_gpio_button[0].gpio);
- goto out;
- }
- gpio_direction_input(mtx1_gpio_button[0].gpio);
-out:
- gpiod_add_lookup_table(&mtx1_wdt_gpio_table);
- return platform_add_devices(mtx1_devs, ARRAY_SIZE(mtx1_devs));
+ rc = software_node_register(&mtx1_gpiochip_node);
+ if (rc)
+ return rc;
+
+ rc = platform_add_devices(mtx1_devs, ARRAY_SIZE(mtx1_devs));
+ if (rc)
+ return rc;
+
+ mtx1_leds_init();
+ mtx1_wdt_init();
+ mtx1_keys_init();
+
+ return 0;
}
arch_initcall(mtx1_register_devices);
diff --git a/arch/mips/boot/dts/Makefile b/arch/mips/boot/dts/Makefile
index 6d9dbe945541..36c5e4c6e640 100644
--- a/arch/mips/boot/dts/Makefile
+++ b/arch/mips/boot/dts/Makefile
@@ -1,20 +1,17 @@
# SPDX-License-Identifier: GPL-2.0
-subdir-$(CONFIG_BMIPS_GENERIC) += brcm
-subdir-$(CONFIG_CAVIUM_OCTEON_SOC) += cavium-octeon
-subdir-$(CONFIG_ECONET) += econet
-subdir-$(CONFIG_EYEQ) += mobileye
-subdir-$(CONFIG_FIT_IMAGE_FDT_MARDUK) += img
-subdir-$(CONFIG_FIT_IMAGE_FDT_BOSTON) += img
-subdir-$(CONFIG_MACH_INGENIC) += ingenic
-subdir-$(CONFIG_LANTIQ) += lantiq
-subdir-$(CONFIG_MACH_LOONGSON64) += loongson
-subdir-$(CONFIG_MACH_LOONGSON32) += loongson
-subdir-$(CONFIG_SOC_VCOREIII) += mscc
-subdir-$(CONFIG_MIPS_MALTA) += mti
-subdir-$(CONFIG_LEGACY_BOARD_SEAD3) += mti
-subdir-$(CONFIG_FIT_IMAGE_FDT_NI169445) += ni
-subdir-$(CONFIG_MACH_PIC32) += pic32
-subdir-$(CONFIG_ATH79) += qca
-subdir-$(CONFIG_RALINK) += ralink
-subdir-$(CONFIG_MACH_REALTEK_RTL) += realtek
-subdir-$(CONFIG_FIT_IMAGE_FDT_XILFPGA) += xilfpga
+subdir-y += brcm
+subdir-y += cavium-octeon
+subdir-y += econet
+subdir-y += mobileye
+subdir-y += img
+subdir-y += ingenic
+subdir-y += lantiq
+subdir-y += loongson
+subdir-y += mscc
+subdir-y += mti
+subdir-y += ni
+subdir-y += pic32
+subdir-y += qca
+subdir-y += ralink
+subdir-y += realtek
+subdir-y += xilfpga
diff --git a/arch/mips/boot/dts/realtek/Makefile b/arch/mips/boot/dts/realtek/Makefile
index d2709798763f..3ac795d85236 100644
--- a/arch/mips/boot/dts/realtek/Makefile
+++ b/arch/mips/boot/dts/realtek/Makefile
@@ -1,3 +1,3 @@
# SPDX-License-Identifier: GPL-2.0
-dtb-y += cisco_sg220-26.dtb
-dtb-y += cameo-rtl9302c-2x-rtl8224-2xge.dtb
+dtb-$(CONFIG_MACH_REALTEK_RTL) += cisco_sg220-26.dtb
+dtb-$(CONFIG_MACH_REALTEK_RTL) += cameo-rtl9302c-2x-rtl8224-2xge.dtb
diff --git a/arch/mips/configs/loongson1_defconfig b/arch/mips/configs/loongson1_defconfig
index 81acae6f61c8..02d29110f702 100644
--- a/arch/mips/configs/loongson1_defconfig
+++ b/arch/mips/configs/loongson1_defconfig
@@ -13,6 +13,7 @@ CONFIG_EXPERT=y
CONFIG_PERF_EVENTS=y
CONFIG_MACH_LOONGSON32=y
# CONFIG_SUSPEND is not set
+CONFIG_JUMP_LABEL=y
# CONFIG_SECCOMP is not set
# CONFIG_GCC_PLUGINS is not set
CONFIG_MODULES=y
@@ -30,8 +31,8 @@ CONFIG_IP_PNP_DHCP=y
CONFIG_SYN_COOKIES=y
# CONFIG_INET_DIAG is not set
# CONFIG_IPV6 is not set
+# CONFIG_BQL is not set
# CONFIG_WIRELESS is not set
-# CONFIG_ETHTOOL_NETLINK is not set
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
# CONFIG_STANDALONE is not set
@@ -39,7 +40,7 @@ CONFIG_MTD=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_RAW_NAND=y
-CONFIG_MTD_NAND_LOONGSON1=y
+CONFIG_MTD_NAND_LOONGSON=y
CONFIG_MTD_UBI=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_SCSI=m
@@ -72,6 +73,7 @@ CONFIG_NETDEVICES=y
# CONFIG_NET_VENDOR_MICROCHIP is not set
# CONFIG_NET_VENDOR_MICROSEMI is not set
# CONFIG_NET_VENDOR_MICROSOFT is not set
+# CONFIG_NET_VENDOR_MUCSE is not set
# CONFIG_NET_VENDOR_NI is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
# CONFIG_NET_VENDOR_NETRONOME is not set
@@ -166,15 +168,11 @@ CONFIG_ROOT_NFS=y
CONFIG_NLS_CODEPAGE_437=m
CONFIG_NLS_ISO8859_1=m
# CONFIG_CRYPTO_HW is not set
-# CONFIG_XZ_DEC_X86 is not set
-# CONFIG_XZ_DEC_POWERPC is not set
-# CONFIG_XZ_DEC_ARM is not set
-# CONFIG_XZ_DEC_ARMTHUMB is not set
-# CONFIG_XZ_DEC_ARM64 is not set
-# CONFIG_XZ_DEC_SPARC is not set
-# CONFIG_XZ_DEC_RISCV is not set
CONFIG_DYNAMIC_DEBUG=y
# CONFIG_DEBUG_MISC is not set
CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_RCU_TRACE is not set
# CONFIG_FTRACE is not set
# CONFIG_EARLY_PRINTK is not set
+CONFIG_TEST_DHRY=m
diff --git a/arch/mips/include/asm/pgalloc.h b/arch/mips/include/asm/pgalloc.h
index 942af87f1cdd..7a04381efa0b 100644
--- a/arch/mips/include/asm/pgalloc.h
+++ b/arch/mips/include/asm/pgalloc.h
@@ -81,8 +81,7 @@ static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address)
{
pud_t *pud;
- struct ptdesc *ptdesc = pagetable_alloc(GFP_KERNEL & ~__GFP_HIGHMEM,
- PUD_TABLE_ORDER);
+ struct ptdesc *ptdesc = pagetable_alloc(GFP_KERNEL, PUD_TABLE_ORDER);
if (!ptdesc)
return NULL;
diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c
index f39e85fd58fa..b15615b28569 100644
--- a/arch/mips/kernel/ftrace.c
+++ b/arch/mips/kernel/ftrace.c
@@ -54,10 +54,20 @@ static inline void ftrace_dyn_arch_init_insns(void)
u32 *buf;
unsigned int v1;
- /* la v1, _mcount */
- v1 = 3;
- buf = (u32 *)&insn_la_mcount[0];
- UASM_i_LA(&buf, v1, MCOUNT_ADDR);
+ /* If we are not in compat space, the number of generated
+ * instructions will exceed the maximum expected limit of 2.
+ * To prevent buffer overflow, we avoid generating them.
+ * insn_la_mcount will not be used later in ftrace_make_call.
+ */
+ if (uasm_in_compat_space_p(MCOUNT_ADDR)) {
+ /* la v1, _mcount */
+ v1 = 3;
+ buf = (u32 *)&insn_la_mcount[0];
+ UASM_i_LA(&buf, v1, MCOUNT_ADDR);
+ } else {
+ pr_warn("ftrace: mcount address beyond 32 bits is not supported (%lX)\n",
+ MCOUNT_ADDR);
+ }
/* jal (ftrace_caller + 8), jump over the first two instruction */
buf = (u32 *)&insn_jal_ftrace_caller;
@@ -189,6 +199,13 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
unsigned int new;
unsigned long ip = rec->ip;
+ /* When the code to patch does not belong to the kernel code
+ * space, we must use insn_la_mcount. However, if MCOUNT_ADDR
+ * is not in compat space, insn_la_mcount is not usable.
+ */
+ if (!core_kernel_text(ip) && !uasm_in_compat_space_p(MCOUNT_ADDR))
+ return -EFAULT;
+
new = core_kernel_text(ip) ? insn_jal_ftrace_caller : insn_la_mcount[0];
#ifdef CONFIG_64BIT
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index 08c0a01d9a29..be1b049d856f 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -109,7 +109,7 @@ handle_vcei:
.align 5
LEAF(r4k_wait)
/* Keep the ISA bit clear for calculations on local labels here. */
-0: .fill 0
+0: .fill 0
/* Start of idle interrupt region. */
local_irq_enable
/*
@@ -121,7 +121,7 @@ LEAF(r4k_wait)
*/
1: .fill 0
/* The R2 EI/EHB sequence takes 8 bytes, otherwise pad up. */
- .if 1b - 0b > 32
+ .if 1b - 0b > 32
.error "overlong idle interrupt region"
.elseif 1b - 0b > 8
.align 4
@@ -146,10 +146,10 @@ r4k_wait_exit:
MFC0 k0, CP0_EPC
/* Subtract/add 2 to let the ISA bit propagate through the mask. */
PTR_LA k1, r4k_wait_insn - 2
- ori k0, r4k_wait_idle_size - 2
+ ori k0, r4k_wait_idle_size - 2
.set noreorder
bne k0, k1, \handler
- PTR_ADDIU k0, r4k_wait_exit - r4k_wait_insn + 2
+ PTR_ADDIU k0, r4k_wait_exit - r4k_wait_insn + 2
.set reorder
MTC0 k0, CP0_EPC
.set pop
diff --git a/arch/mips/kvm/interrupt.c b/arch/mips/kvm/interrupt.c
index 0277942279ea..895a6f1781fd 100644
--- a/arch/mips/kvm/interrupt.c
+++ b/arch/mips/kvm/interrupt.c
@@ -27,27 +27,11 @@ void kvm_mips_deliver_interrupts(struct kvm_vcpu *vcpu, u32 cause)
unsigned long *pending_clr = &vcpu->arch.pending_exceptions_clr;
unsigned int priority;
- if (!(*pending) && !(*pending_clr))
- return;
-
- priority = __ffs(*pending_clr);
- while (priority <= MIPS_EXC_MAX) {
+ for_each_set_bit(priority, pending_clr, MIPS_EXC_MAX + 1)
kvm_mips_callbacks->irq_clear(vcpu, priority, cause);
- priority = find_next_bit(pending_clr,
- BITS_PER_BYTE * sizeof(*pending_clr),
- priority + 1);
- }
-
- priority = __ffs(*pending);
- while (priority <= MIPS_EXC_MAX) {
+ for_each_set_bit(priority, pending, MIPS_EXC_MAX + 1)
kvm_mips_callbacks->irq_deliver(vcpu, priority, cause);
-
- priority = find_next_bit(pending,
- BITS_PER_BYTE * sizeof(*pending),
- priority + 1);
- }
-
}
int kvm_mips_pending_timer(struct kvm_vcpu *vcpu)
diff --git a/arch/nios2/include/asm/uaccess.h b/arch/nios2/include/asm/uaccess.h
index b8299082adbe..6ccc9a232c23 100644
--- a/arch/nios2/include/asm/uaccess.h
+++ b/arch/nios2/include/asm/uaccess.h
@@ -172,15 +172,15 @@ do { \
#define __put_user(x, ptr) \
({ \
- __auto_type __pu_ptr = (ptr); \
- typeof(*__pu_ptr) __pu_val = (typeof(*__pu_ptr))(x); \
+ auto __pu_ptr = (ptr); \
+ auto __pu_val = (typeof(*__pu_ptr))(x); \
__put_user_common(__pu_val, __pu_ptr); \
})
#define put_user(x, ptr) \
({ \
- __auto_type __pu_ptr = (ptr); \
- typeof(*__pu_ptr) __pu_val = (typeof(*__pu_ptr))(x); \
+ auto __pu_ptr = (ptr); \
+ auto __pu_val = (typeof(*__pu_ptr))(x); \
access_ok(__pu_ptr, sizeof(*__pu_ptr)) ? \
__put_user_common(__pu_val, __pu_ptr) : \
-EFAULT; \
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 938e5df75b2d..0e5fad5f06ca 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -238,6 +238,7 @@ config S390
select HAVE_PERF_EVENTS
select HAVE_PERF_REGS
select HAVE_PERF_USER_STACK_DUMP
+ select HAVE_POSIX_CPU_TIMERS_TASK_WORK
select HAVE_PREEMPT_DYNAMIC_KEY
select HAVE_REGS_AND_STACK_ACCESS_API
select HAVE_RELIABLE_STACKTRACE
@@ -254,6 +255,7 @@ config S390
select HOTPLUG_SMT
select IOMMU_HELPER if PCI
select IOMMU_SUPPORT if PCI
+ select IRQ_MSI_LIB if PCI
select KASAN_VMALLOC if KASAN
select LOCK_MM_AND_FIND_VMA
select MMU_GATHER_MERGE_VMAS
diff --git a/arch/s390/boot/vmem.c b/arch/s390/boot/vmem.c
index fbe64ffdfb96..7d6cc4c85af0 100644
--- a/arch/s390/boot/vmem.c
+++ b/arch/s390/boot/vmem.c
@@ -244,22 +244,10 @@ static void *boot_crst_alloc(unsigned long val)
static pte_t *boot_pte_alloc(void)
{
- static void *pte_leftover;
pte_t *pte;
- /*
- * handling pte_leftovers this way helps to avoid memory fragmentation
- * during POPULATE_KASAN_MAP_SHADOW when EDAT is off
- */
- if (!pte_leftover) {
- pte_leftover = (void *)physmem_alloc_or_die(RR_VMEM, PAGE_SIZE, PAGE_SIZE);
- pte = pte_leftover + _PAGE_TABLE_SIZE;
- __arch_set_page_dat(pte, 1);
- } else {
- pte = pte_leftover;
- pte_leftover = NULL;
- }
-
+ pte = (void *)physmem_alloc_or_die(RR_VMEM, PAGE_SIZE, PAGE_SIZE);
+ __arch_set_page_dat(pte, 1);
memset64((u64 *)pte, _PAGE_INVALID, PTRS_PER_PTE);
return pte;
}
diff --git a/arch/s390/include/asm/bug.h b/arch/s390/include/asm/bug.h
index acb4b13d98c5..ee9221bb5d18 100644
--- a/arch/s390/include/asm/bug.h
+++ b/arch/s390/include/asm/bug.h
@@ -4,11 +4,14 @@
#include <linux/stringify.h>
+#ifdef CONFIG_BUG
+
#ifndef CONFIG_DEBUG_BUGVERBOSE
#define _BUGVERBOSE_LOCATION(file, line)
#else
#define __BUGVERBOSE_LOCATION(file, line) \
.pushsection .rodata.str, "aMS", @progbits, 1; \
+ .align 2; \
10002: .ascii file "\0"; \
.popsection; \
\
@@ -52,6 +55,8 @@ do { \
#define HAVE_ARCH_BUG
+#endif /* CONFIG_BUG */
+
#include <asm-generic/bug.h>
#endif /* _ASM_S390_BUG_H */
diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h
index 9240a363c893..c1d63b613bf9 100644
--- a/arch/s390/include/asm/page.h
+++ b/arch/s390/include/asm/page.h
@@ -166,6 +166,8 @@ static inline int page_reset_referenced(unsigned long addr)
return CC_TRANSFORM(cc);
}
+int split_pud_page(pud_t *pudp, unsigned long addr);
+
/* Bits int the storage key */
#define _PAGE_CHANGED 0x02 /* HW changed bit */
#define _PAGE_REFERENCED 0x04 /* HW referenced bit */
diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h
index a32f465ecf73..c0ff19dab580 100644
--- a/arch/s390/include/asm/pci.h
+++ b/arch/s390/include/asm/pci.h
@@ -5,6 +5,7 @@
#include <linux/pci.h>
#include <linux/mutex.h>
#include <linux/iommu.h>
+#include <linux/irqdomain.h>
#include <linux/pci_hotplug.h>
#include <asm/pci_clp.h>
#include <asm/pci_debug.h>
@@ -109,6 +110,7 @@ struct zpci_bus {
struct list_head resources;
struct list_head bus_next;
struct resource bus_resource;
+ struct irq_domain *msi_parent_domain;
int topo; /* TID if topo_is_tid, PCHID otherwise */
int domain_nr;
u8 multifunction : 1;
@@ -310,6 +312,9 @@ int zpci_dma_exit_device(struct zpci_dev *zdev);
/* IRQ */
int __init zpci_irq_init(void);
void __init zpci_irq_exit(void);
+int zpci_set_irq(struct zpci_dev *zdev);
+int zpci_create_parent_msi_domain(struct zpci_bus *zbus);
+void zpci_remove_parent_msi_domain(struct zpci_bus *zbus);
/* FMB */
int zpci_fmb_enable_device(struct zpci_dev *);
diff --git a/arch/s390/mm/gmap_helpers.c b/arch/s390/mm/gmap_helpers.c
index 549f14ad08af..d41b19925a5a 100644
--- a/arch/s390/mm/gmap_helpers.c
+++ b/arch/s390/mm/gmap_helpers.c
@@ -47,6 +47,7 @@ static void ptep_zap_softleaf_entry(struct mm_struct *mm, softleaf_t entry)
void gmap_helper_zap_one_page(struct mm_struct *mm, unsigned long vmaddr)
{
struct vm_area_struct *vma;
+ unsigned long pgstev;
spinlock_t *ptl;
pgste_t pgste;
pte_t *ptep;
@@ -65,9 +66,13 @@ void gmap_helper_zap_one_page(struct mm_struct *mm, unsigned long vmaddr)
if (pte_swap(*ptep)) {
preempt_disable();
pgste = pgste_get_lock(ptep);
+ pgstev = pgste_val(pgste);
- ptep_zap_softleaf_entry(mm, softleaf_from_pte(*ptep));
- pte_clear(mm, vmaddr, ptep);
+ if ((pgstev & _PGSTE_GPS_USAGE_MASK) == _PGSTE_GPS_USAGE_UNUSED ||
+ (pgstev & _PGSTE_GPS_ZERO)) {
+ ptep_zap_softleaf_entry(mm, softleaf_from_pte(*ptep));
+ pte_clear(mm, vmaddr, ptep);
+ }
pgste_set_unlock(ptep, pgste);
preempt_enable();
diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c
index 3042647c9dbf..d3ce04a4b248 100644
--- a/arch/s390/mm/pageattr.c
+++ b/arch/s390/mm/pageattr.c
@@ -204,7 +204,7 @@ static int walk_pmd_level(pud_t *pudp, unsigned long addr, unsigned long end,
return rc;
}
-static int split_pud_page(pud_t *pudp, unsigned long addr)
+int split_pud_page(pud_t *pudp, unsigned long addr)
{
unsigned long pmd_addr, prot;
pmd_t *pm_dir, *pmdp;
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index d96587b84e81..eeadff45e0e1 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -330,10 +330,14 @@ static int modify_pud_table(p4d_t *p4d, unsigned long addr, unsigned long end,
if (pud_leaf(*pud)) {
if (IS_ALIGNED(addr, PUD_SIZE) &&
IS_ALIGNED(next, PUD_SIZE)) {
+ if (!direct)
+ vmem_free_pages(pud_deref(*pud), get_order(PUD_SIZE), altmap);
pud_clear(pud);
pages++;
+ continue;
+ } else {
+ split_pud_page(pud, addr & PUD_MASK);
}
- continue;
}
} else if (pud_none(*pud)) {
if (IS_ALIGNED(addr, PUD_SIZE) &&
@@ -433,9 +437,15 @@ static int modify_pagetable(unsigned long start, unsigned long end, bool add,
if (WARN_ON_ONCE(!PAGE_ALIGNED(start | end)))
return -EINVAL;
- /* Don't mess with any tables not fully in 1:1 mapping & vmemmap area */
+ /* Don't mess with any tables not fully in 1:1 mapping, vmemmap & kasan area */
+#ifdef CONFIG_KASAN
+ if (WARN_ON_ONCE(!(start >= KASAN_SHADOW_START && end <= KASAN_SHADOW_END) &&
+ end > __abs_lowcore))
+ return -EINVAL;
+#else
if (WARN_ON_ONCE(end > __abs_lowcore))
return -EINVAL;
+#endif
for (addr = start; addr < end; addr = next) {
next = pgd_addr_end(addr, end);
pgd = pgd_offset_k(addr);
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index 93d2c9c780fc..5a6ace9d875a 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -708,6 +708,12 @@ int zpci_reenable_device(struct zpci_dev *zdev)
if (rc)
return rc;
+ if (zdev->msi_nr_irqs > 0) {
+ rc = zpci_set_irq(zdev);
+ if (rc)
+ return rc;
+ }
+
rc = zpci_iommu_register_ioat(zdev, &status);
if (rc)
zpci_disable_device(zdev);
diff --git a/arch/s390/pci/pci_bus.c b/arch/s390/pci/pci_bus.c
index 72adc8f6e94f..66c4bd888b29 100644
--- a/arch/s390/pci/pci_bus.c
+++ b/arch/s390/pci/pci_bus.c
@@ -14,6 +14,7 @@
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/seq_file.h>
+#include <linux/irqdomain.h>
#include <linux/jump_label.h>
#include <linux/pci.h>
#include <linux/printk.h>
@@ -198,19 +199,27 @@ static int zpci_bus_create_pci_bus(struct zpci_bus *zbus, struct zpci_dev *fr, s
zbus->multifunction = zpci_bus_is_multifunction_root(fr);
zbus->max_bus_speed = fr->max_bus_speed;
+ if (zpci_create_parent_msi_domain(zbus))
+ goto out_free_domain;
+
/*
* Note that the zbus->resources are taken over and zbus->resources
* is empty after a successful call
*/
bus = pci_create_root_bus(NULL, ZPCI_BUS_NR, ops, zbus, &zbus->resources);
- if (!bus) {
- zpci_free_domain(zbus->domain_nr);
- return -EFAULT;
- }
+ if (!bus)
+ goto out_remove_msi_domain;
zbus->bus = bus;
+ dev_set_msi_domain(&zbus->bus->dev, zbus->msi_parent_domain);
return 0;
+
+out_remove_msi_domain:
+ zpci_remove_parent_msi_domain(zbus);
+out_free_domain:
+ zpci_free_domain(zbus->domain_nr);
+ return -ENOMEM;
}
static void zpci_bus_release(struct kref *kref)
@@ -231,6 +240,7 @@ static void zpci_bus_release(struct kref *kref)
mutex_lock(&zbus_list_lock);
list_del(&zbus->bus_next);
mutex_unlock(&zbus_list_lock);
+ zpci_remove_parent_msi_domain(zbus);
kfree(zbus);
}
diff --git a/arch/s390/pci/pci_irq.c b/arch/s390/pci/pci_irq.c
index 2a06df8c2498..e9dd45f3c09d 100644
--- a/arch/s390/pci/pci_irq.c
+++ b/arch/s390/pci/pci_irq.c
@@ -6,6 +6,7 @@
#include <linux/kernel_stat.h>
#include <linux/pci.h>
#include <linux/msi.h>
+#include <linux/irqchip/irq-msi-lib.h>
#include <linux/smp.h>
#include <asm/isc.h>
@@ -97,7 +98,7 @@ static int zpci_clear_directed_irq(struct zpci_dev *zdev)
}
/* Register adapter interruptions */
-static int zpci_set_irq(struct zpci_dev *zdev)
+int zpci_set_irq(struct zpci_dev *zdev)
{
int rc;
@@ -125,27 +126,53 @@ static int zpci_clear_irq(struct zpci_dev *zdev)
static int zpci_set_irq_affinity(struct irq_data *data, const struct cpumask *dest,
bool force)
{
- struct msi_desc *entry = irq_data_get_msi_desc(data);
- struct msi_msg msg = entry->msg;
- int cpu_addr = smp_cpu_get_cpu_address(cpumask_first(dest));
+ irq_data_update_affinity(data, dest);
+ return IRQ_SET_MASK_OK;
+}
- msg.address_lo &= 0xff0000ff;
- msg.address_lo |= (cpu_addr << 8);
- pci_write_msi_msg(data->irq, &msg);
+/*
+ * Encode the hwirq number for the parent domain. The encoding must be unique
+ * for each IRQ of each device in the parent domain, so it uses the devfn to
+ * identify the device and the msi_index to identify the IRQ within that device.
+ */
+static inline u32 zpci_encode_hwirq(u8 devfn, u16 msi_index)
+{
+ return (devfn << 16) | msi_index;
+}
- return IRQ_SET_MASK_OK;
+static inline u16 zpci_decode_hwirq_msi_index(irq_hw_number_t hwirq)
+{
+ return hwirq & 0xffff;
+}
+
+static void zpci_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
+{
+ struct msi_desc *desc = irq_data_get_msi_desc(data);
+ struct zpci_dev *zdev = to_zpci_dev(desc->dev);
+
+ if (irq_delivery == DIRECTED) {
+ int cpu = cpumask_first(irq_data_get_affinity_mask(data));
+
+ msg->address_lo = zdev->msi_addr & 0xff0000ff;
+ msg->address_lo |= (smp_cpu_get_cpu_address(cpu) << 8);
+ } else {
+ msg->address_lo = zdev->msi_addr & 0xffffffff;
+ }
+ msg->address_hi = zdev->msi_addr >> 32;
+ msg->data = zpci_decode_hwirq_msi_index(data->hwirq);
}
static struct irq_chip zpci_irq_chip = {
.name = "PCI-MSI",
- .irq_unmask = pci_msi_unmask_irq,
- .irq_mask = pci_msi_mask_irq,
+ .irq_compose_msi_msg = zpci_compose_msi_msg,
};
static void zpci_handle_cpu_local_irq(bool rescan)
{
struct airq_iv *dibv = zpci_ibv[smp_processor_id()];
union zpci_sic_iib iib = {{0}};
+ struct irq_domain *msi_domain;
+ irq_hw_number_t hwirq;
unsigned long bit;
int irqs_on = 0;
@@ -163,7 +190,9 @@ static void zpci_handle_cpu_local_irq(bool rescan)
continue;
}
inc_irq_stat(IRQIO_MSI);
- generic_handle_irq(airq_iv_get_data(dibv, bit));
+ hwirq = airq_iv_get_data(dibv, bit);
+ msi_domain = (struct irq_domain *)airq_iv_get_ptr(dibv, bit);
+ generic_handle_domain_irq(msi_domain, hwirq);
}
}
@@ -228,6 +257,8 @@ static void zpci_floating_irq_handler(struct airq_struct *airq,
struct tpi_info *tpi_info)
{
union zpci_sic_iib iib = {{0}};
+ struct irq_domain *msi_domain;
+ irq_hw_number_t hwirq;
unsigned long si, ai;
struct airq_iv *aibv;
int irqs_on = 0;
@@ -255,7 +286,9 @@ static void zpci_floating_irq_handler(struct airq_struct *airq,
break;
inc_irq_stat(IRQIO_MSI);
airq_iv_lock(aibv, ai);
- generic_handle_irq(airq_iv_get_data(aibv, ai));
+ hwirq = airq_iv_get_data(aibv, ai);
+ msi_domain = (struct irq_domain *)airq_iv_get_ptr(aibv, ai);
+ generic_handle_domain_irq(msi_domain, hwirq);
airq_iv_unlock(aibv, ai);
}
}
@@ -277,7 +310,9 @@ static int __alloc_airq(struct zpci_dev *zdev, int msi_vecs,
zdev->aisb = *bit;
/* Create adapter interrupt vector */
- zdev->aibv = airq_iv_create(msi_vecs, AIRQ_IV_DATA | AIRQ_IV_BITLOCK, NULL);
+ zdev->aibv = airq_iv_create(msi_vecs,
+ AIRQ_IV_PTR | AIRQ_IV_DATA | AIRQ_IV_BITLOCK,
+ NULL);
if (!zdev->aibv)
return -ENOMEM;
@@ -289,146 +324,220 @@ static int __alloc_airq(struct zpci_dev *zdev, int msi_vecs,
return 0;
}
-int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
+bool arch_restore_msi_irqs(struct pci_dev *pdev)
{
- unsigned int hwirq, msi_vecs, irqs_per_msi, i, cpu;
struct zpci_dev *zdev = to_zpci(pdev);
- struct msi_desc *msi;
- struct msi_msg msg;
- unsigned long bit;
- int cpu_addr;
- int rc, irq;
+ zpci_set_irq(zdev);
+ return true;
+}
+
+static struct airq_struct zpci_airq = {
+ .handler = zpci_floating_irq_handler,
+ .isc = PCI_ISC,
+};
+
+static void zpci_msi_teardown_directed(struct zpci_dev *zdev)
+{
+ airq_iv_free(zpci_ibv[0], zdev->msi_first_bit, zdev->max_msi);
+ zdev->msi_first_bit = -1U;
+ zdev->msi_nr_irqs = 0;
+}
+
+static void zpci_msi_teardown_floating(struct zpci_dev *zdev)
+{
+ airq_iv_release(zdev->aibv);
+ zdev->aibv = NULL;
+ airq_iv_free_bit(zpci_sbv, zdev->aisb);
zdev->aisb = -1UL;
zdev->msi_first_bit = -1U;
+ zdev->msi_nr_irqs = 0;
+}
+
+static void zpci_msi_teardown(struct irq_domain *domain, msi_alloc_info_t *arg)
+{
+ struct zpci_dev *zdev = to_zpci_dev(domain->dev);
+
+ zpci_clear_irq(zdev);
+ if (irq_delivery == DIRECTED)
+ zpci_msi_teardown_directed(zdev);
+ else
+ zpci_msi_teardown_floating(zdev);
+}
+
+static int zpci_msi_prepare(struct irq_domain *domain,
+ struct device *dev, int nvec,
+ msi_alloc_info_t *info)
+{
+ struct zpci_dev *zdev = to_zpci_dev(dev);
+ struct pci_dev *pdev = to_pci_dev(dev);
+ unsigned long bit;
+ int msi_vecs, rc;
msi_vecs = min_t(unsigned int, nvec, zdev->max_msi);
if (msi_vecs < nvec) {
- pr_info("%s requested %d irqs, allocate system limit of %d",
+ pr_info("%s requested %d IRQs, allocate system limit of %d\n",
pci_name(pdev), nvec, zdev->max_msi);
}
rc = __alloc_airq(zdev, msi_vecs, &bit);
- if (rc < 0)
+ if (rc) {
+ pr_err("Allocating adapter IRQs for %s failed\n", pci_name(pdev));
return rc;
+ }
- /*
- * Request MSI interrupts:
- * When using MSI, nvec_used interrupt sources and their irq
- * descriptors are controlled through one msi descriptor.
- * Thus the outer loop over msi descriptors shall run only once,
- * while two inner loops iterate over the interrupt vectors.
- * When using MSI-X, each interrupt vector/irq descriptor
- * is bound to exactly one msi descriptor (nvec_used is one).
- * So the inner loops are executed once, while the outer iterates
- * over the MSI-X descriptors.
- */
- hwirq = bit;
- msi_for_each_desc(msi, &pdev->dev, MSI_DESC_NOTASSOCIATED) {
- if (hwirq - bit >= msi_vecs)
- break;
- irqs_per_msi = min_t(unsigned int, msi_vecs, msi->nvec_used);
- irq = __irq_alloc_descs(-1, 0, irqs_per_msi, 0, THIS_MODULE,
- (irq_delivery == DIRECTED) ?
- msi->affinity : NULL);
- if (irq < 0)
- return -ENOMEM;
+ zdev->msi_first_bit = bit;
+ zdev->msi_nr_irqs = msi_vecs;
+ rc = zpci_set_irq(zdev);
+ if (rc) {
+ pr_err("Registering adapter IRQs for %s failed\n",
+ pci_name(pdev));
+
+ if (irq_delivery == DIRECTED)
+ zpci_msi_teardown_directed(zdev);
+ else
+ zpci_msi_teardown_floating(zdev);
+ return rc;
+ }
+ return 0;
+}
- for (i = 0; i < irqs_per_msi; i++) {
- rc = irq_set_msi_desc_off(irq, i, msi);
- if (rc)
- return rc;
- irq_set_chip_and_handler(irq + i, &zpci_irq_chip,
- handle_percpu_irq);
- }
+static int zpci_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
+ unsigned int nr_irqs, void *args)
+{
+ struct msi_desc *desc = ((msi_alloc_info_t *)args)->desc;
+ struct zpci_dev *zdev = to_zpci_dev(desc->dev);
+ struct zpci_bus *zbus = zdev->zbus;
+ unsigned int cpu, hwirq;
+ unsigned long bit;
+ int i;
- msg.data = hwirq - bit;
- if (irq_delivery == DIRECTED) {
- if (msi->affinity)
- cpu = cpumask_first(&msi->affinity->mask);
- else
- cpu = 0;
- cpu_addr = smp_cpu_get_cpu_address(cpu);
+ bit = zdev->msi_first_bit + desc->msi_index;
+ hwirq = zpci_encode_hwirq(zdev->devfn, desc->msi_index);
- msg.address_lo = zdev->msi_addr & 0xff0000ff;
- msg.address_lo |= (cpu_addr << 8);
+ if (desc->msi_index + nr_irqs > zdev->max_msi)
+ return -EINVAL;
+ for (i = 0; i < nr_irqs; i++) {
+ irq_domain_set_info(domain, virq + i, hwirq + i,
+ &zpci_irq_chip, zdev,
+ handle_percpu_irq, NULL, NULL);
+
+ if (irq_delivery == DIRECTED) {
for_each_possible_cpu(cpu) {
- for (i = 0; i < irqs_per_msi; i++)
- airq_iv_set_data(zpci_ibv[cpu],
- hwirq + i, irq + i);
+ airq_iv_set_ptr(zpci_ibv[cpu], bit + i,
+ (unsigned long)zbus->msi_parent_domain);
+ airq_iv_set_data(zpci_ibv[cpu], bit + i, hwirq + i);
}
} else {
- msg.address_lo = zdev->msi_addr & 0xffffffff;
- for (i = 0; i < irqs_per_msi; i++)
- airq_iv_set_data(zdev->aibv, hwirq + i, irq + i);
+ airq_iv_set_ptr(zdev->aibv, bit + i,
+ (unsigned long)zbus->msi_parent_domain);
+ airq_iv_set_data(zdev->aibv, bit + i, hwirq + i);
}
- msg.address_hi = zdev->msi_addr >> 32;
- pci_write_msi_msg(irq, &msg);
- hwirq += irqs_per_msi;
}
- zdev->msi_first_bit = bit;
- zdev->msi_nr_irqs = hwirq - bit;
-
- rc = zpci_set_irq(zdev);
- if (rc)
- return rc;
-
- return (zdev->msi_nr_irqs == nvec) ? 0 : zdev->msi_nr_irqs;
+ return 0;
}
-void arch_teardown_msi_irqs(struct pci_dev *pdev)
+static void zpci_msi_clear_airq(struct irq_data *d, int i)
{
- struct zpci_dev *zdev = to_zpci(pdev);
- struct msi_desc *msi;
- unsigned int i;
- int rc;
+ struct msi_desc *desc = irq_data_get_msi_desc(d);
+ struct zpci_dev *zdev = to_zpci_dev(desc->dev);
+ unsigned long bit;
+ unsigned int cpu;
+ u16 msi_index;
- /* Disable interrupts */
- rc = zpci_clear_irq(zdev);
- if (rc)
- return;
+ msi_index = zpci_decode_hwirq_msi_index(d->hwirq);
+ bit = zdev->msi_first_bit + msi_index;
- /* Release MSI interrupts */
- msi_for_each_desc(msi, &pdev->dev, MSI_DESC_ASSOCIATED) {
- for (i = 0; i < msi->nvec_used; i++) {
- irq_set_msi_desc(msi->irq + i, NULL);
- irq_free_desc(msi->irq + i);
+ if (irq_delivery == DIRECTED) {
+ for_each_possible_cpu(cpu) {
+ airq_iv_set_ptr(zpci_ibv[cpu], bit + i, 0);
+ airq_iv_set_data(zpci_ibv[cpu], bit + i, 0);
}
- msi->msg.address_lo = 0;
- msi->msg.address_hi = 0;
- msi->msg.data = 0;
- msi->irq = 0;
+ } else {
+ airq_iv_set_ptr(zdev->aibv, bit + i, 0);
+ airq_iv_set_data(zdev->aibv, bit + i, 0);
}
+}
- if (zdev->aisb != -1UL) {
- zpci_ibv[zdev->aisb] = NULL;
- airq_iv_free_bit(zpci_sbv, zdev->aisb);
- zdev->aisb = -1UL;
- }
- if (zdev->aibv) {
- airq_iv_release(zdev->aibv);
- zdev->aibv = NULL;
- }
+static void zpci_msi_domain_free(struct irq_domain *domain, unsigned int virq,
+ unsigned int nr_irqs)
+{
+ struct irq_data *d;
+ int i;
- if ((irq_delivery == DIRECTED) && zdev->msi_first_bit != -1U)
- airq_iv_free(zpci_ibv[0], zdev->msi_first_bit, zdev->msi_nr_irqs);
+ for (i = 0; i < nr_irqs; i++) {
+ d = irq_domain_get_irq_data(domain, virq + i);
+ zpci_msi_clear_airq(d, i);
+ irq_domain_reset_irq_data(d);
+ }
}
-bool arch_restore_msi_irqs(struct pci_dev *pdev)
+static const struct irq_domain_ops zpci_msi_domain_ops = {
+ .alloc = zpci_msi_domain_alloc,
+ .free = zpci_msi_domain_free,
+};
+
+static bool zpci_init_dev_msi_info(struct device *dev, struct irq_domain *domain,
+ struct irq_domain *real_parent,
+ struct msi_domain_info *info)
{
- struct zpci_dev *zdev = to_zpci(pdev);
+ if (!msi_lib_init_dev_msi_info(dev, domain, real_parent, info))
+ return false;
+
+ info->ops->msi_prepare = zpci_msi_prepare;
+ info->ops->msi_teardown = zpci_msi_teardown;
- zpci_set_irq(zdev);
return true;
}
-static struct airq_struct zpci_airq = {
- .handler = zpci_floating_irq_handler,
- .isc = PCI_ISC,
+static struct msi_parent_ops zpci_msi_parent_ops = {
+ .supported_flags = MSI_GENERIC_FLAGS_MASK |
+ MSI_FLAG_PCI_MSIX |
+ MSI_FLAG_MULTI_PCI_MSI,
+ .required_flags = MSI_FLAG_USE_DEF_DOM_OPS |
+ MSI_FLAG_USE_DEF_CHIP_OPS,
+ .init_dev_msi_info = zpci_init_dev_msi_info,
};
+int zpci_create_parent_msi_domain(struct zpci_bus *zbus)
+{
+ char fwnode_name[18];
+
+ snprintf(fwnode_name, sizeof(fwnode_name), "ZPCI_MSI_DOM_%04x", zbus->domain_nr);
+ struct irq_domain_info info = {
+ .fwnode = irq_domain_alloc_named_fwnode(fwnode_name),
+ .ops = &zpci_msi_domain_ops,
+ };
+
+ if (!info.fwnode) {
+ pr_err("Failed to allocate fwnode for MSI IRQ domain\n");
+ return -ENOMEM;
+ }
+
+ if (irq_delivery == FLOATING)
+ zpci_msi_parent_ops.required_flags |= MSI_FLAG_NO_AFFINITY;
+
+ zbus->msi_parent_domain = msi_create_parent_irq_domain(&info, &zpci_msi_parent_ops);
+ if (!zbus->msi_parent_domain) {
+ irq_domain_free_fwnode(info.fwnode);
+ pr_err("Failed to create MSI IRQ domain\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+void zpci_remove_parent_msi_domain(struct zpci_bus *zbus)
+{
+ struct fwnode_handle *fn;
+
+ fn = zbus->msi_parent_domain->fwnode;
+ irq_domain_remove(zbus->msi_parent_domain);
+ irq_domain_free_fwnode(fn);
+}
+
static void __init cpu_enable_directed_irq(void *unused)
{
union zpci_sic_iib iib = {{0}};
@@ -465,6 +574,7 @@ static int __init zpci_directed_irq_init(void)
* is only done on the first vector.
*/
zpci_ibv[cpu] = airq_iv_create(cache_line_size() * BITS_PER_BYTE,
+ AIRQ_IV_PTR |
AIRQ_IV_DATA |
AIRQ_IV_CACHELINE |
(!cpu ? AIRQ_IV_ALLOC : 0), NULL);
diff --git a/arch/x86/include/asm/bug.h b/arch/x86/include/asm/bug.h
index ee23b98353d7..d561a8443c13 100644
--- a/arch/x86/include/asm/bug.h
+++ b/arch/x86/include/asm/bug.h
@@ -129,7 +129,7 @@ do { \
#define __WARN_FLAGS(cond_str, flags) \
do { \
- __auto_type __flags = BUGFLAG_WARNING|(flags); \
+ auto __flags = BUGFLAG_WARNING|(flags); \
instrumentation_begin(); \
_BUG_FLAGS(cond_str, ASM_UD2, __flags, ARCH_WARN_REACHABLE); \
instrumentation_end(); \
diff --git a/arch/x86/include/asm/string_64.h b/arch/x86/include/asm/string_64.h
index 79e9695dc13e..4635616863f5 100644
--- a/arch/x86/include/asm/string_64.h
+++ b/arch/x86/include/asm/string_64.h
@@ -31,7 +31,7 @@ KCFI_REFERENCE(__memset);
#define __HAVE_ARCH_MEMSET16
static inline void *memset16(uint16_t *s, uint16_t v, size_t n)
{
- const __auto_type s0 = s;
+ const auto s0 = s;
asm volatile (
"rep stosw"
: "+D" (s), "+c" (n)
@@ -44,7 +44,7 @@ static inline void *memset16(uint16_t *s, uint16_t v, size_t n)
#define __HAVE_ARCH_MEMSET32
static inline void *memset32(uint32_t *s, uint32_t v, size_t n)
{
- const __auto_type s0 = s;
+ const auto s0 = s;
asm volatile (
"rep stosl"
: "+D" (s), "+c" (n)
@@ -57,7 +57,7 @@ static inline void *memset32(uint32_t *s, uint32_t v, size_t n)
#define __HAVE_ARCH_MEMSET64
static inline void *memset64(uint64_t *s, uint64_t v, size_t n)
{
- const __auto_type s0 = s;
+ const auto s0 = s;
asm volatile (
"rep stosq"
: "+D" (s), "+c" (n)
diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h
index 641f45c22f9d..915124011c27 100644
--- a/arch/x86/include/asm/uaccess_64.h
+++ b/arch/x86/include/asm/uaccess_64.h
@@ -72,7 +72,7 @@ static inline void __user *mask_user_address(const void __user *ptr)
return ret;
}
#define masked_user_access_begin(x) ({ \
- __auto_type __masked_ptr = (x); \
+ auto __masked_ptr = (x); \
__masked_ptr = mask_user_address(__masked_ptr); \
__uaccess_begin(); __masked_ptr; })