Update Linux to v5.4.2
Change-Id: Idf6911045d9d382da2cfe01b1edff026404ac8fd
diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile
index e5de34d..2663c8f 100644
--- a/arch/parisc/kernel/Makefile
+++ b/arch/parisc/kernel/Makefile
@@ -7,16 +7,18 @@
obj-y := cache.o pacache.o setup.o pdt.o traps.o time.o irq.o \
pa7300lc.o syscall.o entry.o sys_parisc.o firmware.o \
- ptrace.o hardware.o inventory.o drivers.o \
+ ptrace.o hardware.o inventory.o drivers.o alternative.o \
signal.o hpmc.o real2.o parisc_ksyms.o unaligned.o \
- process.o processor.o pdc_cons.o pdc_chassis.o unwind.o
+ process.o processor.o pdc_cons.o pdc_chassis.o unwind.o \
+ patch.o
ifdef CONFIG_FUNCTION_TRACER
# Do not profile debug and lowlevel utilities
-CFLAGS_REMOVE_ftrace.o = -pg
-CFLAGS_REMOVE_cache.o = -pg
-CFLAGS_REMOVE_perf.o = -pg
-CFLAGS_REMOVE_unwind.o = -pg
+CFLAGS_REMOVE_ftrace.o = $(CC_FLAGS_FTRACE)
+CFLAGS_REMOVE_cache.o = $(CC_FLAGS_FTRACE)
+CFLAGS_REMOVE_perf.o = $(CC_FLAGS_FTRACE)
+CFLAGS_REMOVE_unwind.o = $(CC_FLAGS_FTRACE)
+CFLAGS_REMOVE_patch.o = $(CC_FLAGS_FTRACE)
endif
obj-$(CONFIG_SMP) += smp.o
@@ -32,3 +34,8 @@
obj-$(CONFIG_PARISC_CPU_TOPOLOGY) += topology.o
obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
+obj-$(CONFIG_JUMP_LABEL) += jump_label.o
+obj-$(CONFIG_KGDB) += kgdb.o
+obj-$(CONFIG_KPROBES) += kprobes.o
+obj-$(CONFIG_KEXEC) += kexec.o relocate_kernel.o
+obj-$(CONFIG_KEXEC_FILE) += kexec_file.o
diff --git a/arch/parisc/kernel/alternative.c b/arch/parisc/kernel/alternative.c
new file mode 100644
index 0000000..3c66d5c
--- /dev/null
+++ b/arch/parisc/kernel/alternative.c
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Alternative live-patching for parisc.
+ * Copyright (C) 2018 Helge Deller <deller@gmx.de>
+ *
+ */
+
+#include <asm/processor.h>
+#include <asm/sections.h>
+#include <asm/alternative.h>
+
+#include <linux/module.h>
+
+static int no_alternatives;
+static int __init setup_no_alternatives(char *str)
+{
+ no_alternatives = 1;
+ return 1;
+}
+__setup("no-alternatives", setup_no_alternatives);
+
+void __init_or_module apply_alternatives(struct alt_instr *start,
+ struct alt_instr *end, const char *module_name)
+{
+ struct alt_instr *entry;
+ int index = 0, applied = 0;
+ int num_cpus = num_online_cpus();
+
+ for (entry = start; entry < end; entry++, index++) {
+
+ u32 *from, cond, replacement;
+ s32 len;
+
+ from = (u32 *)((ulong)&entry->orig_offset + entry->orig_offset);
+ len = entry->len;
+ cond = entry->cond;
+ replacement = entry->replacement;
+
+ WARN_ON(!cond);
+
+ if (cond != ALT_COND_ALWAYS && no_alternatives)
+ continue;
+
+ pr_debug("Check %d: Cond 0x%x, Replace %02d instructions @ 0x%px with 0x%08x\n",
+ index, cond, len, from, replacement);
+
+ if ((cond & ALT_COND_NO_SMP) && (num_cpus != 1))
+ continue;
+ if ((cond & ALT_COND_NO_DCACHE) && (cache_info.dc_size != 0))
+ continue;
+ if ((cond & ALT_COND_NO_ICACHE) && (cache_info.ic_size != 0))
+ continue;
+ if ((cond & ALT_COND_RUN_ON_QEMU) && !running_on_qemu)
+ continue;
+
+ /*
+ * If the PDC_MODEL capabilities has Non-coherent IO-PDIR bit
+ * set (bit #61, big endian), we have to flush and sync every
+ * time IO-PDIR is changed in Ike/Astro.
+ */
+ if ((cond & ALT_COND_NO_IOC_FDC) &&
+ ((boot_cpu_data.cpu_type <= pcxw_) ||
+ (boot_cpu_data.pdc.capabilities & PDC_MODEL_IOPDIR_FDC)))
+ continue;
+
+ /* Want to replace pdtlb by a pdtlb,l instruction? */
+ if (replacement == INSN_PxTLB) {
+ replacement = *from;
+ if (boot_cpu_data.cpu_type >= pcxu) /* >= pa2.0 ? */
+ replacement |= (1 << 10); /* set el bit */
+ }
+
+ /*
+ * Replace instruction with NOPs?
+ * For long distance insert a branch instruction instead.
+ */
+ if (replacement == INSN_NOP && len > 1)
+ replacement = 0xe8000002 + (len-2)*8; /* "b,n .+8" */
+
+ pr_debug("ALTERNATIVE %3d: Cond %2x, Replace %2d instructions to 0x%08x @ 0x%px (%pS)\n",
+ index, cond, len, replacement, from, from);
+
+ if (len < 0) {
+ /* Replace multiple instruction by new code */
+ u32 *source;
+ len = -len;
+ source = (u32 *)((ulong)&entry->replacement + entry->replacement);
+ memcpy(from, source, 4 * len);
+ } else {
+ /* Replace by one instruction */
+ *from = replacement;
+ }
+ applied++;
+ }
+
+ pr_info("%s%salternatives: applied %d out of %d patches\n",
+ module_name ? : "", module_name ? " " : "",
+ applied, index);
+}
+
+
+void __init apply_alternatives_all(void)
+{
+ set_kernel_text_rw(1);
+
+ apply_alternatives((struct alt_instr *) &__alt_instructions,
+ (struct alt_instr *) &__alt_instructions_end, NULL);
+
+ set_kernel_text_rw(0);
+}
diff --git a/arch/parisc/kernel/asm-offsets.c b/arch/parisc/kernel/asm-offsets.c
index dfff8a0..aa79d35 100644
--- a/arch/parisc/kernel/asm-offsets.c
+++ b/arch/parisc/kernel/asm-offsets.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Generate definitions needed by assembly language modules.
* This code generates raw asm output which is post-processed to extract
@@ -11,20 +12,6 @@
* Copyright (C) 2001 Richard Hirst <rhirst at parisc-linux.org>
* Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
* Copyright (C) 2003 James Bottomley <jejb at parisc-linux.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/types.h>
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index bddd2ac..a82b3ea 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -29,26 +29,34 @@
#include <asm/sections.h>
#include <asm/shmparam.h>
-int split_tlb __read_mostly;
-int dcache_stride __read_mostly;
-int icache_stride __read_mostly;
+int split_tlb __ro_after_init;
+int dcache_stride __ro_after_init;
+int icache_stride __ro_after_init;
EXPORT_SYMBOL(dcache_stride);
void flush_dcache_page_asm(unsigned long phys_addr, unsigned long vaddr);
EXPORT_SYMBOL(flush_dcache_page_asm);
+void purge_dcache_page_asm(unsigned long phys_addr, unsigned long vaddr);
void flush_icache_page_asm(unsigned long phys_addr, unsigned long vaddr);
-/* On some machines (e.g. ones with the Merced bus), there can be
+/* On some machines (i.e., ones with the Merced bus), there can be
* only a single PxTLB broadcast at a time; this must be guaranteed
- * by software. We put a spinlock around all TLB flushes to
- * ensure this.
+ * by software. We need a spinlock around all TLB flushes to ensure
+ * this.
*/
-DEFINE_SPINLOCK(pa_tlb_lock);
+DEFINE_SPINLOCK(pa_tlb_flush_lock);
-struct pdc_cache_info cache_info __read_mostly;
+/* Swapper page setup lock. */
+DEFINE_SPINLOCK(pa_swapper_pg_lock);
+
+#if defined(CONFIG_64BIT) && defined(CONFIG_SMP)
+int pa_serialize_tlb_flushes __ro_after_init;
+#endif
+
+struct pdc_cache_info cache_info __ro_after_init;
#ifndef CONFIG_PA20
-static struct pdc_btlb_info btlb_info __read_mostly;
+static struct pdc_btlb_info btlb_info __ro_after_init;
#endif
#ifdef CONFIG_SMP
@@ -303,6 +311,17 @@
preempt_enable();
}
+static inline void
+__purge_cache_page(struct vm_area_struct *vma, unsigned long vmaddr,
+ unsigned long physaddr)
+{
+ preempt_disable();
+ purge_dcache_page_asm(physaddr, vmaddr);
+ if (vma->vm_flags & VM_EXEC)
+ flush_icache_page_asm(physaddr, vmaddr);
+ preempt_enable();
+}
+
void flush_dcache_page(struct page *page)
{
struct address_space *mapping = page_mapping_file(page);
@@ -362,10 +381,10 @@
EXPORT_SYMBOL(flush_kernel_icache_range_asm);
#define FLUSH_THRESHOLD 0x80000 /* 0.5MB */
-static unsigned long parisc_cache_flush_threshold __read_mostly = FLUSH_THRESHOLD;
+static unsigned long parisc_cache_flush_threshold __ro_after_init = FLUSH_THRESHOLD;
-#define FLUSH_TLB_THRESHOLD (2*1024*1024) /* 2MB initial TLB threshold */
-static unsigned long parisc_tlb_flush_threshold __read_mostly = FLUSH_TLB_THRESHOLD;
+#define FLUSH_TLB_THRESHOLD (16*1024) /* 16 KiB minimum TLB threshold */
+static unsigned long parisc_tlb_flush_threshold __ro_after_init = FLUSH_TLB_THRESHOLD;
void __init parisc_setup_cache_timing(void)
{
@@ -404,10 +423,6 @@
goto set_tlb_threshold;
}
- alltime = mfctl(16);
- flush_tlb_all();
- alltime = mfctl(16) - alltime;
-
size = 0;
start = (unsigned long) _text;
rangetime = mfctl(16);
@@ -418,13 +433,19 @@
}
rangetime = mfctl(16) - rangetime;
- printk(KERN_DEBUG "Whole TLB flush %lu cycles, flushing %lu bytes %lu cycles\n",
+ alltime = mfctl(16);
+ flush_tlb_all();
+ alltime = mfctl(16) - alltime;
+
+ printk(KERN_INFO "Whole TLB flush %lu cycles, Range flush %lu bytes %lu cycles\n",
alltime, size, rangetime);
- threshold = PAGE_ALIGN(num_online_cpus() * size * alltime / rangetime);
+ threshold = PAGE_ALIGN((num_online_cpus() * size * alltime) / rangetime);
+ printk(KERN_INFO "Calculated TLB flush threshold %lu KiB\n",
+ threshold/1024);
set_tlb_threshold:
- if (threshold)
+ if (threshold > parisc_tlb_flush_threshold)
parisc_tlb_flush_threshold = threshold;
printk(KERN_INFO "TLB flush threshold set to %lu KiB\n",
parisc_tlb_flush_threshold/1024);
@@ -477,18 +498,6 @@
/* Purge TLB entries for small ranges using the pdtlb and
pitlb instructions. These instructions execute locally
but cause a purge request to be broadcast to other TLBs. */
- if (likely(!split_tlb)) {
- while (start < end) {
- purge_tlb_start(flags);
- mtsp(sid, 1);
- pdtlb(start);
- purge_tlb_end(flags);
- start += PAGE_SIZE;
- }
- return 0;
- }
-
- /* split TLB case */
while (start < end) {
purge_tlb_start(flags);
mtsp(sid, 1);
@@ -573,9 +582,12 @@
pfn = pte_pfn(*ptep);
if (!pfn_valid(pfn))
continue;
- if (unlikely(mm->context))
+ if (unlikely(mm->context)) {
flush_tlb_page(vma, addr);
- __flush_cache_page(vma, addr, PFN_PHYS(pfn));
+ __flush_cache_page(vma, addr, PFN_PHYS(pfn));
+ } else {
+ __purge_cache_page(vma, addr, PFN_PHYS(pfn));
+ }
}
}
}
@@ -610,9 +622,12 @@
continue;
pfn = pte_pfn(*ptep);
if (pfn_valid(pfn)) {
- if (unlikely(vma->vm_mm->context))
+ if (unlikely(vma->vm_mm->context)) {
flush_tlb_page(vma, addr);
- __flush_cache_page(vma, addr, PFN_PHYS(pfn));
+ __flush_cache_page(vma, addr, PFN_PHYS(pfn));
+ } else {
+ __purge_cache_page(vma, addr, PFN_PHYS(pfn));
+ }
}
}
}
@@ -621,9 +636,12 @@
flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long pfn)
{
if (pfn_valid(pfn)) {
- if (likely(vma->vm_mm->context))
+ if (likely(vma->vm_mm->context)) {
flush_tlb_page(vma, vmaddr);
- __flush_cache_page(vma, vmaddr, PFN_PHYS(pfn));
+ __flush_cache_page(vma, vmaddr, PFN_PHYS(pfn));
+ } else {
+ __purge_cache_page(vma, vmaddr, PFN_PHYS(pfn));
+ }
}
}
diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c
index 5eb979d..3b330e5 100644
--- a/arch/parisc/kernel/drivers.c
+++ b/arch/parisc/kernel/drivers.c
@@ -1,11 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* drivers.c
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
* Copyright (c) 1999 The Puffin Group
* Copyright (c) 2001 Matthew Wilcox for Hewlett Packard
* Copyright (c) 2001 Helge Deller <deller@gmx.de>
@@ -38,9 +34,10 @@
#include <asm/io.h>
#include <asm/pdc.h>
#include <asm/parisc-device.h>
+#include <asm/ropes.h>
/* See comments in include/asm-parisc/pci.h */
-const struct dma_map_ops *hppa_dma_ops __read_mostly;
+const struct dma_map_ops *hppa_dma_ops __ro_after_init;
EXPORT_SYMBOL(hppa_dma_ops);
static struct device root = {
@@ -257,6 +254,30 @@
return ret ? d.dev : NULL;
}
+static int __init is_IKE_device(struct device *dev, void *data)
+{
+ struct parisc_device *pdev = to_parisc_device(dev);
+
+ if (!check_dev(dev))
+ return 0;
+ if (pdev->id.hw_type != HPHW_BCPORT)
+ return 0;
+ if (IS_IKE(pdev) ||
+ (pdev->id.hversion == REO_MERCED_PORT) ||
+ (pdev->id.hversion == REOG_MERCED_PORT)) {
+ return 1;
+ }
+ return 0;
+}
+
+int __init machine_has_merced_bus(void)
+{
+ int ret;
+
+ ret = for_each_padev(is_IKE_device, NULL);
+ return ret ? 1 : 0;
+}
+
/**
* find_pa_parent_type - Find a parent of a specific type
* @dev: The device to start searching from
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index d2f9227..b96d744 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
*
@@ -6,20 +7,6 @@
* Copyright (C) 1999 SuSE GmbH Nuernberg
* Copyright (C) 2000 Hewlett-Packard (John Marvin)
* Copyright (C) 1999 Hewlett-Packard (Frank Rowand)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <asm/asm-offsets.h>
@@ -38,6 +25,7 @@
#include <asm/ldcw.h>
#include <asm/traps.h>
#include <asm/thread_info.h>
+#include <asm/alternative.h>
#include <linux/linkage.h>
@@ -49,12 +37,8 @@
.import pa_tlb_lock,data
.macro load_pa_tlb_lock reg
-#if __PA_LDCW_ALIGNMENT > 4
- load32 PA(pa_tlb_lock) + __PA_LDCW_ALIGNMENT-1, \reg
- depi 0,31,__PA_LDCW_ALIGN_ORDER, \reg
-#else
- load32 PA(pa_tlb_lock), \reg
-#endif
+ mfctl %cr25,\reg
+ addil L%(PAGE_SIZE << (PGD_ALLOC_ORDER - 1)),\reg
.endm
/* space_to_prot macro creates a prot id from a space id */
@@ -393,6 +377,7 @@
*/
.macro space_check spc,tmp,fault
mfsp %sr7,\tmp
+ /* check against %r0 which is same value as LINUX_GATEWAY_SPACE */
or,COND(<>) %r0,\spc,%r0 /* user may execute gateway page
* as kernel, so defeat the space
* check if it is */
@@ -426,13 +411,10 @@
ldw,s \index(\pmd),\pmd
bb,>=,n \pmd,_PxD_PRESENT_BIT,\fault
dep %r0,31,PxD_FLAG_SHIFT,\pmd /* clear flags */
- copy \pmd,%r9
- SHLREG %r9,PxD_VALUE_SHIFT,\pmd
+ SHLREG \pmd,PxD_VALUE_SHIFT,\pmd
extru \va,31-PAGE_SHIFT,ASM_BITS_PER_PTE,\index
dep %r0,31,PAGE_SHIFT,\pmd /* clear offset */
shladd \index,BITS_PER_PTE_ENTRY,\pmd,\pmd /* pmd is now pte */
- LDREG %r0(\pmd),\pte
- bb,>=,n \pte,_PAGE_PRESENT_BIT,\fault
.endm
/* Look up PTE in a 3-Level scheme.
@@ -448,7 +430,6 @@
.macro L3_ptep pgd,pte,index,va,fault
#if CONFIG_PGTABLE_LEVELS == 3 /* we might have a 2-Level scheme, e.g. with 16kb page size */
extrd,u \va,63-ASM_PGDIR_SHIFT,ASM_BITS_PER_PGD,\index
- copy %r0,\pte
extrd,u,*= \va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0
ldw,s \index(\pgd),\pgd
extrd,u,*= \va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0
@@ -463,37 +444,43 @@
L2_ptep \pgd,\pte,\index,\va,\fault
.endm
- /* Acquire pa_tlb_lock lock and recheck page is still present. */
+ /* Acquire pa_tlb_lock lock and check page is present. */
.macro tlb_lock spc,ptp,pte,tmp,tmp1,fault
#ifdef CONFIG_SMP
- cmpib,COND(=),n 0,\spc,2f
+98: cmpib,COND(=),n 0,\spc,2f
load_pa_tlb_lock \tmp
1: LDCW 0(\tmp),\tmp1
cmpib,COND(=) 0,\tmp1,1b
nop
LDREG 0(\ptp),\pte
- bb,<,n \pte,_PAGE_PRESENT_BIT,2f
+ bb,<,n \pte,_PAGE_PRESENT_BIT,3f
+ LDCW 0(\tmp),\tmp1
b \fault
- stw \spc,0(\tmp)
-2:
+ stw \spc,0(\tmp)
+99: ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP)
#endif
+2: LDREG 0(\ptp),\pte
+ bb,>=,n \pte,_PAGE_PRESENT_BIT,\fault
+3:
.endm
/* Release pa_tlb_lock lock without reloading lock address. */
- .macro tlb_unlock0 spc,tmp
+ .macro tlb_unlock0 spc,tmp,tmp1
#ifdef CONFIG_SMP
+98: or,COND(=) %r0,\spc,%r0
+ LDCW 0(\tmp),\tmp1
or,COND(=) %r0,\spc,%r0
- sync
- or,COND(=) %r0,\spc,%r0
- stw \spc,0(\tmp)
+ stw \spc,0(\tmp)
+99: ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP)
#endif
.endm
/* Release pa_tlb_lock lock. */
- .macro tlb_unlock1 spc,tmp
+ .macro tlb_unlock1 spc,tmp,tmp1
#ifdef CONFIG_SMP
- load_pa_tlb_lock \tmp
- tlb_unlock0 \spc,\tmp
+98: load_pa_tlb_lock \tmp
+99: ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP)
+ tlb_unlock0 \spc,\tmp,\tmp1
#endif
.endm
@@ -910,9 +897,9 @@
* Only do signals if we are returning to user space
*/
LDREG PT_IASQ0(%r16), %r20
- cmpib,COND(=),n 0,%r20,intr_restore /* backward */
+ cmpib,COND(=),n LINUX_GATEWAY_SPACE, %r20, intr_restore /* backward */
LDREG PT_IASQ1(%r16), %r20
- cmpib,COND(=),n 0,%r20,intr_restore /* backward */
+ cmpib,COND(=),n LINUX_GATEWAY_SPACE, %r20, intr_restore /* backward */
/* NOTE: We need to enable interrupts if we have to deliver
* signals. We used to do this earlier but it caused kernel
@@ -1176,7 +1163,7 @@
idtlbt pte,prot
- tlb_unlock1 spc,t0
+ tlb_unlock1 spc,t0,t1
rfir
nop
@@ -1202,7 +1189,7 @@
idtlbt pte,prot
- tlb_unlock1 spc,t0
+ tlb_unlock1 spc,t0,t1
rfir
nop
@@ -1236,7 +1223,7 @@
mtsp t1, %sr1 /* Restore sr1 */
- tlb_unlock1 spc,t0
+ tlb_unlock1 spc,t0,t1
rfir
nop
@@ -1269,7 +1256,7 @@
mtsp t1, %sr1 /* Restore sr1 */
- tlb_unlock1 spc,t0
+ tlb_unlock1 spc,t0,t1
rfir
nop
@@ -1298,7 +1285,7 @@
idtlbt pte,prot
- tlb_unlock1 spc,t0
+ tlb_unlock1 spc,t0,t1
rfir
nop
@@ -1326,7 +1313,7 @@
idtlbt pte,prot
- tlb_unlock1 spc,t0
+ tlb_unlock1 spc,t0,t1
rfir
nop
@@ -1433,7 +1420,7 @@
iitlbt pte,prot
- tlb_unlock1 spc,t0
+ tlb_unlock1 spc,t0,t1
rfir
nop
@@ -1457,7 +1444,7 @@
iitlbt pte,prot
- tlb_unlock1 spc,t0
+ tlb_unlock1 spc,t0,t1
rfir
nop
@@ -1491,7 +1478,7 @@
mtsp t1, %sr1 /* Restore sr1 */
- tlb_unlock1 spc,t0
+ tlb_unlock1 spc,t0,t1
rfir
nop
@@ -1515,7 +1502,7 @@
mtsp t1, %sr1 /* Restore sr1 */
- tlb_unlock1 spc,t0
+ tlb_unlock1 spc,t0,t1
rfir
nop
@@ -1545,7 +1532,7 @@
iitlbt pte,prot
- tlb_unlock1 spc,t0
+ tlb_unlock1 spc,t0,t1
rfir
nop
@@ -1565,7 +1552,7 @@
iitlbt pte,prot
- tlb_unlock1 spc,t0
+ tlb_unlock1 spc,t0,t1
rfir
nop
@@ -1595,7 +1582,7 @@
idtlbt pte,prot
- tlb_unlock0 spc,t0
+ tlb_unlock0 spc,t0,t1
rfir
nop
#else
@@ -1621,7 +1608,7 @@
mtsp t1, %sr1 /* Restore sr1 */
- tlb_unlock0 spc,t0
+ tlb_unlock0 spc,t0,t1
rfir
nop
@@ -1641,7 +1628,7 @@
idtlbt pte,prot
- tlb_unlock0 spc,t0
+ tlb_unlock0 spc,t0,t1
rfir
nop
#endif
@@ -1658,7 +1645,7 @@
itlb_fault:
b intr_save
- ldi 6,%r8
+ ldi PARISC_ITLB_TRAP,%r8
nadtlb_fault:
b intr_save
@@ -1745,6 +1732,7 @@
.endm
fork_like clone
+fork_like clone3
fork_like fork
fork_like vfork
@@ -2008,6 +1996,7 @@
* calling mcount(), and 2 instructions for ftrace_stub(). That way we
* have all on one L1 cacheline.
*/
+ ldi 0, %arg3
b ftrace_function_trampoline
copy %r3, %arg2 /* caller original %sp */
ftrace_stub:
@@ -2025,6 +2014,168 @@
#endif
ENDPROC_CFI(mcount)
+#ifdef CONFIG_DYNAMIC_FTRACE
+
+#ifdef CONFIG_64BIT
+#define FTRACE_FRAME_SIZE (2*FRAME_SIZE)
+#else
+#define FTRACE_FRAME_SIZE FRAME_SIZE
+#endif
+ENTRY_CFI(ftrace_caller, caller,frame=FTRACE_FRAME_SIZE,CALLS,SAVE_RP,SAVE_SP)
+ftrace_caller:
+ .global ftrace_caller
+
+ STREG %r3, -FTRACE_FRAME_SIZE+1*REG_SZ(%sp)
+ ldo -FTRACE_FRAME_SIZE(%sp), %r3
+ STREG %rp, -RP_OFFSET(%r3)
+
+ /* Offset 0 is already allocated for %r1 */
+ STREG %r23, 2*REG_SZ(%r3)
+ STREG %r24, 3*REG_SZ(%r3)
+ STREG %r25, 4*REG_SZ(%r3)
+ STREG %r26, 5*REG_SZ(%r3)
+ STREG %r28, 6*REG_SZ(%r3)
+ STREG %r29, 7*REG_SZ(%r3)
+#ifdef CONFIG_64BIT
+ STREG %r19, 8*REG_SZ(%r3)
+ STREG %r20, 9*REG_SZ(%r3)
+ STREG %r21, 10*REG_SZ(%r3)
+ STREG %r22, 11*REG_SZ(%r3)
+ STREG %r27, 12*REG_SZ(%r3)
+ STREG %r31, 13*REG_SZ(%r3)
+ loadgp
+ ldo -16(%sp),%r29
+#endif
+ LDREG 0(%r3), %r25
+ copy %rp, %r26
+ ldo -8(%r25), %r25
+ ldi 0, %r23 /* no pt_regs */
+ b,l ftrace_function_trampoline, %rp
+ copy %r3, %r24
+
+ LDREG -RP_OFFSET(%r3), %rp
+ LDREG 2*REG_SZ(%r3), %r23
+ LDREG 3*REG_SZ(%r3), %r24
+ LDREG 4*REG_SZ(%r3), %r25
+ LDREG 5*REG_SZ(%r3), %r26
+ LDREG 6*REG_SZ(%r3), %r28
+ LDREG 7*REG_SZ(%r3), %r29
+#ifdef CONFIG_64BIT
+ LDREG 8*REG_SZ(%r3), %r19
+ LDREG 9*REG_SZ(%r3), %r20
+ LDREG 10*REG_SZ(%r3), %r21
+ LDREG 11*REG_SZ(%r3), %r22
+ LDREG 12*REG_SZ(%r3), %r27
+ LDREG 13*REG_SZ(%r3), %r31
+#endif
+ LDREG 1*REG_SZ(%r3), %r3
+
+ LDREGM -FTRACE_FRAME_SIZE(%sp), %r1
+ /* Adjust return point to jump back to beginning of traced function */
+ ldo -4(%r1), %r1
+ bv,n (%r1)
+
+ENDPROC_CFI(ftrace_caller)
+
+#ifdef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS
+ENTRY_CFI(ftrace_regs_caller,caller,frame=FTRACE_FRAME_SIZE+PT_SZ_ALGN,
+ CALLS,SAVE_RP,SAVE_SP)
+ftrace_regs_caller:
+ .global ftrace_regs_caller
+
+ ldo -FTRACE_FRAME_SIZE(%sp), %r1
+ STREG %rp, -RP_OFFSET(%r1)
+
+ copy %sp, %r1
+ ldo PT_SZ_ALGN(%sp), %sp
+
+ STREG %rp, PT_GR2(%r1)
+ STREG %r3, PT_GR3(%r1)
+ STREG %r4, PT_GR4(%r1)
+ STREG %r5, PT_GR5(%r1)
+ STREG %r6, PT_GR6(%r1)
+ STREG %r7, PT_GR7(%r1)
+ STREG %r8, PT_GR8(%r1)
+ STREG %r9, PT_GR9(%r1)
+ STREG %r10, PT_GR10(%r1)
+ STREG %r11, PT_GR11(%r1)
+ STREG %r12, PT_GR12(%r1)
+ STREG %r13, PT_GR13(%r1)
+ STREG %r14, PT_GR14(%r1)
+ STREG %r15, PT_GR15(%r1)
+ STREG %r16, PT_GR16(%r1)
+ STREG %r17, PT_GR17(%r1)
+ STREG %r18, PT_GR18(%r1)
+ STREG %r19, PT_GR19(%r1)
+ STREG %r20, PT_GR20(%r1)
+ STREG %r21, PT_GR21(%r1)
+ STREG %r22, PT_GR22(%r1)
+ STREG %r23, PT_GR23(%r1)
+ STREG %r24, PT_GR24(%r1)
+ STREG %r25, PT_GR25(%r1)
+ STREG %r26, PT_GR26(%r1)
+ STREG %r27, PT_GR27(%r1)
+ STREG %r28, PT_GR28(%r1)
+ STREG %r29, PT_GR29(%r1)
+ STREG %r30, PT_GR30(%r1)
+ STREG %r31, PT_GR31(%r1)
+ mfctl %cr11, %r26
+ STREG %r26, PT_SAR(%r1)
+
+ copy %rp, %r26
+ LDREG -FTRACE_FRAME_SIZE-PT_SZ_ALGN(%sp), %r25
+ ldo -8(%r25), %r25
+ ldo -FTRACE_FRAME_SIZE(%r1), %arg2
+ b,l ftrace_function_trampoline, %rp
+ copy %r1, %arg3 /* struct pt_regs */
+
+ ldo -PT_SZ_ALGN(%sp), %r1
+
+ LDREG PT_SAR(%r1), %rp
+ mtctl %rp, %cr11
+
+ LDREG PT_GR2(%r1), %rp
+ LDREG PT_GR3(%r1), %r3
+ LDREG PT_GR4(%r1), %r4
+ LDREG PT_GR5(%r1), %r5
+ LDREG PT_GR6(%r1), %r6
+ LDREG PT_GR7(%r1), %r7
+ LDREG PT_GR8(%r1), %r8
+ LDREG PT_GR9(%r1), %r9
+ LDREG PT_GR10(%r1),%r10
+ LDREG PT_GR11(%r1),%r11
+ LDREG PT_GR12(%r1),%r12
+ LDREG PT_GR13(%r1),%r13
+ LDREG PT_GR14(%r1),%r14
+ LDREG PT_GR15(%r1),%r15
+ LDREG PT_GR16(%r1),%r16
+ LDREG PT_GR17(%r1),%r17
+ LDREG PT_GR18(%r1),%r18
+ LDREG PT_GR19(%r1),%r19
+ LDREG PT_GR20(%r1),%r20
+ LDREG PT_GR21(%r1),%r21
+ LDREG PT_GR22(%r1),%r22
+ LDREG PT_GR23(%r1),%r23
+ LDREG PT_GR24(%r1),%r24
+ LDREG PT_GR25(%r1),%r25
+ LDREG PT_GR26(%r1),%r26
+ LDREG PT_GR27(%r1),%r27
+ LDREG PT_GR28(%r1),%r28
+ LDREG PT_GR29(%r1),%r29
+ LDREG PT_GR30(%r1),%r30
+ LDREG PT_GR31(%r1),%r31
+
+ ldo -PT_SZ_ALGN(%sp), %sp
+ LDREGM -FTRACE_FRAME_SIZE(%sp), %r1
+ /* Adjust return point to jump back to beginning of traced function */
+ ldo -4(%r1), %r1
+ bv,n (%r1)
+
+ENDPROC_CFI(ftrace_regs_caller)
+
+#endif
+#endif
+
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
.align 8
ENTRY_CFI(return_to_handler, caller,frame=FRAME_SIZE)
diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c
index 6d471c0..1d976f2 100644
--- a/arch/parisc/kernel/firmware.c
+++ b/arch/parisc/kernel/firmware.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* arch/parisc/kernel/firmware.c - safe PDC access routines
*
@@ -12,12 +13,6 @@
* Copyright 2003 Grant Grundler <grundler parisc-linux org>
* Copyright 2003,2004 Ryan Bradetich <rbrad@parisc-linux.org>
* Copyright 2004,2006 Thibaut VARENE <varenet@parisc-linux.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
*/
/* I think it would be in everyone's best interest to follow this
@@ -87,7 +82,7 @@
/* Firmware needs to be initially set to narrow to determine the
* actual firmware width. */
-int parisc_narrow_firmware __read_mostly = 1;
+int parisc_narrow_firmware __ro_after_init = 1;
#endif
/* On most currently-supported platforms, IODC I/O calls are 32-bit calls
@@ -317,6 +312,19 @@
}
/**
+ * pdc_cpu_rendenzvous - Stop currently executing CPU
+ * @retval: -1 on error, 0 on success
+ */
+int __pdc_cpu_rendezvous(void)
+{
+ if (is_pdc_pat())
+ return mem_pdc_call(PDC_PAT_CPU, PDC_PAT_CPU_RENDEZVOUS);
+ else
+ return mem_pdc_call(PDC_PROC, 1, 0);
+}
+
+
+/**
* pdc_chassis_warn - Fetches chassis warnings
* @retval: -1 on error, 0 on success
*/
@@ -569,6 +577,30 @@
}
/**
+ * pdc_model_platform_info - Returns machine product and serial number.
+ * @orig_prod_num: Return buffer for original product number.
+ * @current_prod_num: Return buffer for current product number.
+ * @serial_no: Return buffer for serial number.
+ *
+ * Returns strings containing the original and current product numbers and the
+ * serial number of the system.
+ */
+int pdc_model_platform_info(char *orig_prod_num, char *current_prod_num,
+ char *serial_no)
+{
+ int retval;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pdc_lock, flags);
+ retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_GET_PLATFORM_INFO,
+ __pa(orig_prod_num), __pa(current_prod_num), __pa(serial_no));
+ convert_to_wide(pdc_result);
+ spin_unlock_irqrestore(&pdc_lock, flags);
+
+ return retval;
+}
+
+/**
* pdc_cache_info - Return cache and TLB information.
* @cache_info: The return buffer.
*
@@ -1326,6 +1358,36 @@
}
/**
+ * pdc_pat_cell_info - Retrieve the cell's information.
+ * @info: The pointer to a struct pdc_pat_cell_info_rtn_block.
+ * @actcnt: The number of bytes which should be written to info.
+ * @offset: offset of the structure.
+ * @cell_number: The cell number which should be asked, or -1 for current cell.
+ *
+ * This PDC call returns information about the given cell (or all cells).
+ */
+int pdc_pat_cell_info(struct pdc_pat_cell_info_rtn_block *info,
+ unsigned long *actcnt, unsigned long offset,
+ unsigned long cell_number)
+{
+ int retval;
+ unsigned long flags;
+ struct pdc_pat_cell_info_rtn_block result;
+
+ spin_lock_irqsave(&pdc_lock, flags);
+ retval = mem_pdc_call(PDC_PAT_CELL, PDC_PAT_CELL_GET_INFO,
+ __pa(pdc_result), __pa(&result), *actcnt,
+ offset, cell_number);
+ if (!retval) {
+ *actcnt = pdc_result[0];
+ memcpy(info, &result, *actcnt);
+ }
+ spin_unlock_irqrestore(&pdc_lock, flags);
+
+ return retval;
+}
+
+/**
* pdc_pat_cpu_get_number - Retrieve the cpu number.
* @cpu_info: The return buffer.
* @hpa: The Hard Physical Address of the CPU.
@@ -1413,6 +1475,33 @@
}
/**
+ * pdc_pat_pd_get_PDC_interface_revisions - Retrieve PDC interface revisions.
+ * @legacy_rev: The legacy revision.
+ * @pat_rev: The PAT revision.
+ * @pdc_cap: The PDC capabilities.
+ *
+ */
+int pdc_pat_pd_get_pdc_revisions(unsigned long *legacy_rev,
+ unsigned long *pat_rev, unsigned long *pdc_cap)
+{
+ int retval;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pdc_lock, flags);
+ retval = mem_pdc_call(PDC_PAT_PD, PDC_PAT_PD_GET_PDC_INTERF_REV,
+ __pa(pdc_result));
+ if (retval == PDC_OK) {
+ *legacy_rev = pdc_result[0];
+ *pat_rev = pdc_result[1];
+ *pdc_cap = pdc_result[2];
+ }
+ spin_unlock_irqrestore(&pdc_lock, flags);
+
+ return retval;
+}
+
+
+/**
* pdc_pat_io_pci_cfg_read - Read PCI configuration space.
* @pci_addr: PCI configuration space address for which the read request is being made.
* @pci_size: Size of read in bytes. Valid values are 1, 2, and 4.
diff --git a/arch/parisc/kernel/ftrace.c b/arch/parisc/kernel/ftrace.c
index e46a415..b836fc6 100644
--- a/arch/parisc/kernel/ftrace.c
+++ b/arch/parisc/kernel/ftrace.c
@@ -7,17 +7,19 @@
* Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com>
*
* future possible enhancements:
- * - add CONFIG_DYNAMIC_FTRACE
* - add CONFIG_STACK_TRACER
*/
#include <linux/init.h>
#include <linux/ftrace.h>
+#include <linux/uaccess.h>
+#include <linux/kprobes.h>
+#include <linux/ptrace.h>
#include <asm/assembly.h>
#include <asm/sections.h>
#include <asm/ftrace.h>
-
+#include <asm/patch.h>
#define __hot __attribute__ ((__section__ (".text.hot")))
@@ -48,20 +50,22 @@
void notrace __hot ftrace_function_trampoline(unsigned long parent,
unsigned long self_addr,
- unsigned long org_sp_gr3)
+ unsigned long org_sp_gr3,
+ struct pt_regs *regs)
{
- extern ftrace_func_t ftrace_trace_function; /* depends on CONFIG_DYNAMIC_FTRACE */
- extern int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace);
+#ifndef CONFIG_DYNAMIC_FTRACE
+ extern ftrace_func_t ftrace_trace_function;
+#endif
+ extern struct ftrace_ops *function_trace_op;
- if (ftrace_trace_function != ftrace_stub) {
- /* struct ftrace_ops *op, struct pt_regs *regs); */
- ftrace_trace_function(parent, self_addr, NULL, NULL);
- return;
- }
+ if (function_trace_op->flags & FTRACE_OPS_FL_ENABLED &&
+ ftrace_trace_function != ftrace_stub)
+ ftrace_trace_function(self_addr, parent,
+ function_trace_op, regs);
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
if (ftrace_graph_return != (trace_func_graph_ret_t) ftrace_stub ||
- ftrace_graph_entry != ftrace_graph_entry_stub) {
+ ftrace_graph_entry != ftrace_graph_entry_stub) {
unsigned long *parent_rp;
/* calculate pointer to %rp in stack */
@@ -76,3 +80,166 @@
#endif
}
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+int ftrace_enable_ftrace_graph_caller(void)
+{
+ return 0;
+}
+
+int ftrace_disable_ftrace_graph_caller(void)
+{
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+
+int __init ftrace_dyn_arch_init(void)
+{
+ return 0;
+}
+int ftrace_update_ftrace_func(ftrace_func_t func)
+{
+ return 0;
+}
+
+int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
+ unsigned long addr)
+{
+ return 0;
+}
+
+unsigned long ftrace_call_adjust(unsigned long addr)
+{
+ return addr+(FTRACE_PATCHABLE_FUNCTION_SIZE-1)*4;
+}
+
+int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+ u32 insn[FTRACE_PATCHABLE_FUNCTION_SIZE];
+ u32 *tramp;
+ int size, ret, i;
+ void *ip;
+
+#ifdef CONFIG_64BIT
+ unsigned long addr2 =
+ (unsigned long)dereference_function_descriptor((void *)addr);
+
+ u32 ftrace_trampoline[] = {
+ 0x73c10208, /* std,ma r1,100(sp) */
+ 0x0c2110c1, /* ldd -10(r1),r1 */
+ 0xe820d002, /* bve,n (r1) */
+ addr2 >> 32,
+ addr2 & 0xffffffff,
+ 0xe83f1fd7, /* b,l,n .-14,r1 */
+ };
+
+ u32 ftrace_trampoline_unaligned[] = {
+ addr2 >> 32,
+ addr2 & 0xffffffff,
+ 0x37de0200, /* ldo 100(sp),sp */
+ 0x73c13e01, /* std r1,-100(sp) */
+ 0x34213ff9, /* ldo -4(r1),r1 */
+ 0x50213fc1, /* ldd -20(r1),r1 */
+ 0xe820d002, /* bve,n (r1) */
+ 0xe83f1fcf, /* b,l,n .-20,r1 */
+ };
+
+ BUILD_BUG_ON(ARRAY_SIZE(ftrace_trampoline_unaligned) >
+ FTRACE_PATCHABLE_FUNCTION_SIZE);
+#else
+ u32 ftrace_trampoline[] = {
+ (u32)addr,
+ 0x6fc10080, /* stw,ma r1,40(sp) */
+ 0x48213fd1, /* ldw -18(r1),r1 */
+ 0xe820c002, /* bv,n r0(r1) */
+ 0xe83f1fdf, /* b,l,n .-c,r1 */
+ };
+#endif
+
+ BUILD_BUG_ON(ARRAY_SIZE(ftrace_trampoline) >
+ FTRACE_PATCHABLE_FUNCTION_SIZE);
+
+ size = sizeof(ftrace_trampoline);
+ tramp = ftrace_trampoline;
+
+#ifdef CONFIG_64BIT
+ if (rec->ip & 0x4) {
+ size = sizeof(ftrace_trampoline_unaligned);
+ tramp = ftrace_trampoline_unaligned;
+ }
+#endif
+
+ ip = (void *)(rec->ip + 4 - size);
+
+ ret = probe_kernel_read(insn, ip, size);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < size / 4; i++) {
+ if (insn[i] != INSN_NOP)
+ return -EINVAL;
+ }
+
+ __patch_text_multiple(ip, tramp, size);
+ return 0;
+}
+
+int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
+ unsigned long addr)
+{
+ u32 insn[FTRACE_PATCHABLE_FUNCTION_SIZE];
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(insn); i++)
+ insn[i] = INSN_NOP;
+
+ __patch_text((void *)rec->ip, INSN_NOP);
+ __patch_text_multiple((void *)rec->ip + 4 - sizeof(insn),
+ insn, sizeof(insn)-4);
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_KPROBES_ON_FTRACE
+void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
+ struct ftrace_ops *ops, struct pt_regs *regs)
+{
+ struct kprobe_ctlblk *kcb;
+ struct kprobe *p = get_kprobe((kprobe_opcode_t *)ip);
+
+ if (unlikely(!p) || kprobe_disabled(p))
+ return;
+
+ if (kprobe_running()) {
+ kprobes_inc_nmissed_count(p);
+ return;
+ }
+
+ __this_cpu_write(current_kprobe, p);
+
+ kcb = get_kprobe_ctlblk();
+ kcb->kprobe_status = KPROBE_HIT_ACTIVE;
+
+ regs->iaoq[0] = ip;
+ regs->iaoq[1] = ip + 4;
+
+ if (!p->pre_handler || !p->pre_handler(p, regs)) {
+ regs->iaoq[0] = ip + 4;
+ regs->iaoq[1] = ip + 8;
+
+ if (unlikely(p->post_handler)) {
+ kcb->kprobe_status = KPROBE_HIT_SSDONE;
+ p->post_handler(p, regs, 0);
+ }
+ }
+ __this_cpu_write(current_kprobe, NULL);
+}
+NOKPROBE_SYMBOL(kprobe_ftrace_handler);
+
+int arch_prepare_kprobe_ftrace(struct kprobe *p)
+{
+ p->ainsn.insn = NULL;
+ return 0;
+}
+#endif
diff --git a/arch/parisc/kernel/hardware.c b/arch/parisc/kernel/hardware.c
index a205895..98c5203 100644
--- a/arch/parisc/kernel/hardware.c
+++ b/arch/parisc/kernel/hardware.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Hardware descriptions for HP 9000 based hardware, including
* system types, SCSI controllers, DMA controllers, HPPB controllers
@@ -9,21 +10,6 @@
*
* Copyright 1999 by Alex deVries <alex@onefishtwo.ca>
* and copyright 1999 The Puffin Group Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
*/
diff --git a/arch/parisc/kernel/head.S b/arch/parisc/kernel/head.S
index fbb4e43..951a339 100644
--- a/arch/parisc/kernel/head.S
+++ b/arch/parisc/kernel/head.S
@@ -22,7 +22,7 @@
#include <linux/linkage.h>
#include <linux/init.h>
- .level LEVEL
+ .level PA_ASM_LEVEL
__INITDATA
ENTRY(boot_args)
@@ -258,7 +258,7 @@
ldo R%PA(fault_vector_11)(%r10),%r10
$is_pa20:
- .level LEVEL /* restore 1.1 || 2.0w */
+ .level PA_ASM_LEVEL /* restore 1.1 || 2.0w */
#endif /*!CONFIG_64BIT*/
load32 PA(fault_vector_20),%r10
@@ -329,6 +329,19 @@
mtsp %r0,%sr6
mtsp %r0,%sr7
+#ifdef CONFIG_64BIT
+ /*
+ * Enable Wide mode early, in case the task_struct for the idle
+ * task in smp_init_current_idle_task was allocated above 4GB.
+ */
+1: mfia %rp /* clear upper part of pcoq */
+ ldo 2f-1b(%rp),%rp
+ depdi 0,31,32,%rp
+ bv (%rp)
+ ssm PSW_SM_W,%r0
+2:
+#endif
+
/* Initialize the SP - monarch sets up smp_init_current_idle_task */
load32 PA(smp_init_current_idle_task),%sp
LDREG 0(%sp),%sp /* load task address */
@@ -363,7 +376,7 @@
ENDPROC(parisc_kernel_start)
#ifndef CONFIG_64BIT
- .section .data..read_mostly
+ .section .data..ro_after_init
.align 4
.export $global$,data
diff --git a/arch/parisc/kernel/hpmc.S b/arch/parisc/kernel/hpmc.S
index fde6541..81de5e2 100644
--- a/arch/parisc/kernel/hpmc.S
+++ b/arch/parisc/kernel/hpmc.S
@@ -1,23 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* HPMC (High Priority Machine Check) handler.
*
* Copyright (C) 1999 Philipp Rumpf <prumpf@tux.org>
* Copyright (C) 1999 Hewlett-Packard (Frank Rowand)
* Copyright (C) 2000 Hewlett-Packard (John Marvin)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
diff --git a/arch/parisc/kernel/inventory.c b/arch/parisc/kernel/inventory.c
index b0fe19a..9298f22 100644
--- a/arch/parisc/kernel/inventory.c
+++ b/arch/parisc/kernel/inventory.c
@@ -1,11 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* inventory.c
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
* Copyright (c) 1999 The Puffin Group (David Kennedy and Alex deVries)
* Copyright (c) 2001 Matthew Wilcox for Hewlett-Packard
*
@@ -31,6 +27,7 @@
#include <asm/processor.h>
#include <asm/page.h>
#include <asm/parisc-device.h>
+#include <asm/tlbflush.h>
/*
** Debug options
@@ -38,11 +35,12 @@
*/
#undef DEBUG_PAT
-int pdc_type __read_mostly = PDC_TYPE_ILLEGAL;
+int pdc_type __ro_after_init = PDC_TYPE_ILLEGAL;
/* cell number and location (PAT firmware only) */
-unsigned long parisc_cell_num __read_mostly;
-unsigned long parisc_cell_loc __read_mostly;
+unsigned long parisc_cell_num __ro_after_init;
+unsigned long parisc_cell_loc __ro_after_init;
+unsigned long parisc_pat_pdc_cap __ro_after_init;
void __init setup_pdc(void)
@@ -81,12 +79,21 @@
#ifdef CONFIG_64BIT
status = pdc_pat_cell_get_number(&cell_info);
if (status == PDC_OK) {
+ unsigned long legacy_rev, pat_rev;
pdc_type = PDC_TYPE_PAT;
pr_cont("64 bit PAT.\n");
parisc_cell_num = cell_info.cell_num;
parisc_cell_loc = cell_info.cell_loc;
pr_info("PAT: Running on cell %lu and location %lu.\n",
parisc_cell_num, parisc_cell_loc);
+ status = pdc_pat_pd_get_pdc_revisions(&legacy_rev,
+ &pat_rev, &parisc_pat_pdc_cap);
+ pr_info("PAT: legacy revision 0x%lx, pat_rev 0x%lx, pdc_cap 0x%lx, S-PTLB %d, HPMC_RENDEZ %d.\n",
+ legacy_rev, pat_rev, parisc_pat_pdc_cap,
+ parisc_pat_pdc_cap
+ & PDC_PAT_CAPABILITY_BIT_SIMULTANEOUS_PTLB ? 1:0,
+ parisc_pat_pdc_cap
+ & PDC_PAT_CAPABILITY_BIT_PDC_HPMC_RENDEZ ? 1:0);
return;
}
#endif
@@ -628,4 +635,10 @@
}
printk(KERN_INFO "Found devices:\n");
print_parisc_devices();
+
+#if defined(CONFIG_64BIT) && defined(CONFIG_SMP)
+ pa_serialize_tlb_flushes = machine_has_merced_bus();
+ if (pa_serialize_tlb_flushes)
+ pr_info("Merced bus found: Enable PxTLB serialization.\n");
+#endif
}
diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c
index 0ca2540..e5fcfb7 100644
--- a/arch/parisc/kernel/irq.c
+++ b/arch/parisc/kernel/irq.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Code to handle x86 style IRQs plus some generic interrupt stuff.
*
@@ -6,20 +7,6 @@
* Copyright (C) 1999 SuSE GmbH (Philipp Rumpf, prumpf@tux.org)
* Copyright (C) 1999-2000 Grant Grundler
* Copyright (c) 2005 Matthew Wilcox
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/bitops.h>
#include <linux/errno.h>
@@ -117,7 +104,10 @@
return -EINVAL;
/* whatever mask they set, we just allow one CPU */
- cpu_dest = cpumask_first_and(dest, cpu_online_mask);
+ cpu_dest = cpumask_next_and(d->irq & (num_online_cpus()-1),
+ dest, cpu_online_mask);
+ if (cpu_dest >= nr_cpu_ids)
+ cpu_dest = cpumask_first_and(dest, cpu_online_mask);
return cpu_dest;
}
@@ -175,10 +165,16 @@
# endif
#endif
#ifdef CONFIG_SMP
- seq_printf(p, "%*s: ", prec, "RES");
- for_each_online_cpu(j)
- seq_printf(p, "%10u ", irq_stats(j)->irq_resched_count);
- seq_puts(p, " Rescheduling interrupts\n");
+ if (num_online_cpus() > 1) {
+ seq_printf(p, "%*s: ", prec, "RES");
+ for_each_online_cpu(j)
+ seq_printf(p, "%10u ", irq_stats(j)->irq_resched_count);
+ seq_puts(p, " Rescheduling interrupts\n");
+ seq_printf(p, "%*s: ", prec, "CAL");
+ for_each_online_cpu(j)
+ seq_printf(p, "%10u ", irq_stats(j)->irq_call_count);
+ seq_puts(p, " Function call interrupts\n");
+ }
#endif
seq_printf(p, "%*s: ", prec, "UAH");
for_each_online_cpu(j)
diff --git a/arch/parisc/kernel/jump_label.c b/arch/parisc/kernel/jump_label.c
new file mode 100644
index 0000000..d2f3cb1
--- /dev/null
+++ b/arch/parisc/kernel/jump_label.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Helge Deller <deller@gmx.de>
+ *
+ * Based on arch/arm64/kernel/jump_label.c
+ */
+#include <linux/kernel.h>
+#include <linux/jump_label.h>
+#include <linux/bug.h>
+#include <asm/alternative.h>
+#include <asm/patch.h>
+
+static inline int reassemble_17(int as17)
+{
+ return (((as17 & 0x10000) >> 16) |
+ ((as17 & 0x0f800) << 5) |
+ ((as17 & 0x00400) >> 8) |
+ ((as17 & 0x003ff) << 3));
+}
+
+void arch_jump_label_transform(struct jump_entry *entry,
+ enum jump_label_type type)
+{
+ void *addr = (void *)jump_entry_code(entry);
+ u32 insn;
+
+ if (type == JUMP_LABEL_JMP) {
+ void *target = (void *)jump_entry_target(entry);
+ int distance = target - addr;
+ /*
+ * Encode the PA1.1 "b,n" instruction with a 17-bit
+ * displacement. In case we hit the BUG(), we could use
+ * another branch instruction with a 22-bit displacement on
+ * 64-bit CPUs instead. But this seems sufficient for now.
+ */
+ distance -= 8;
+ BUG_ON(distance > 262143 || distance < -262144);
+ insn = 0xe8000002 | reassemble_17(distance >> 2);
+ } else {
+ insn = INSN_NOP;
+ }
+
+ patch_text(addr, insn);
+}
+
+void arch_jump_label_transform_static(struct jump_entry *entry,
+ enum jump_label_type type)
+{
+ /*
+ * We use the architected NOP in arch_static_branch, so there's no
+ * need to patch an identical NOP over the top of it here. The core
+ * will call arch_jump_label_transform from a module notifier if the
+ * NOP needs to be replaced by a branch.
+ */
+}
diff --git a/arch/parisc/kernel/kexec.c b/arch/parisc/kernel/kexec.c
new file mode 100644
index 0000000..5eb7f30
--- /dev/null
+++ b/arch/parisc/kernel/kexec.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/kernel.h>
+#include <linux/console.h>
+#include <linux/kexec.h>
+#include <linux/delay.h>
+#include <asm/cacheflush.h>
+#include <asm/sections.h>
+
+extern void relocate_new_kernel(unsigned long head,
+ unsigned long start,
+ unsigned long phys);
+
+extern const unsigned int relocate_new_kernel_size;
+extern unsigned int kexec_initrd_start_offset;
+extern unsigned int kexec_initrd_end_offset;
+extern unsigned int kexec_cmdline_offset;
+extern unsigned int kexec_free_mem_offset;
+
+static void kexec_show_segment_info(const struct kimage *kimage,
+ unsigned long n)
+{
+ pr_debug(" segment[%lu]: %016lx - %016lx, 0x%lx bytes, %lu pages\n",
+ n,
+ kimage->segment[n].mem,
+ kimage->segment[n].mem + kimage->segment[n].memsz,
+ (unsigned long)kimage->segment[n].memsz,
+ (unsigned long)kimage->segment[n].memsz / PAGE_SIZE);
+}
+
+static void kexec_image_info(const struct kimage *kimage)
+{
+ unsigned long i;
+
+ pr_debug("kexec kimage info:\n");
+ pr_debug(" type: %d\n", kimage->type);
+ pr_debug(" start: %lx\n", kimage->start);
+ pr_debug(" head: %lx\n", kimage->head);
+ pr_debug(" nr_segments: %lu\n", kimage->nr_segments);
+
+ for (i = 0; i < kimage->nr_segments; i++)
+ kexec_show_segment_info(kimage, i);
+
+#ifdef CONFIG_KEXEC_FILE
+ if (kimage->file_mode) {
+ pr_debug("cmdline: %.*s\n", (int)kimage->cmdline_buf_len,
+ kimage->cmdline_buf);
+ }
+#endif
+}
+
+void machine_kexec_cleanup(struct kimage *kimage)
+{
+}
+
+void machine_crash_shutdown(struct pt_regs *regs)
+{
+}
+
+void machine_shutdown(void)
+{
+ smp_send_stop();
+ while (num_online_cpus() > 1) {
+ cpu_relax();
+ mdelay(1);
+ }
+}
+
+void machine_kexec(struct kimage *image)
+{
+#ifdef CONFIG_64BIT
+ Elf64_Fdesc desc;
+#endif
+ void (*reloc)(unsigned long head,
+ unsigned long start,
+ unsigned long phys);
+
+ unsigned long phys = page_to_phys(image->control_code_page);
+ void *virt = (void *)__fix_to_virt(FIX_TEXT_KEXEC);
+ struct kimage_arch *arch = &image->arch;
+
+ set_fixmap(FIX_TEXT_KEXEC, phys);
+
+ flush_cache_all();
+
+#ifdef CONFIG_64BIT
+ reloc = (void *)&desc;
+ desc.addr = (long long)virt;
+#else
+ reloc = (void *)virt;
+#endif
+
+ memcpy(virt, dereference_function_descriptor(relocate_new_kernel),
+ relocate_new_kernel_size);
+
+ *(unsigned long *)(virt + kexec_cmdline_offset) = arch->cmdline;
+ *(unsigned long *)(virt + kexec_initrd_start_offset) = arch->initrd_start;
+ *(unsigned long *)(virt + kexec_initrd_end_offset) = arch->initrd_end;
+ *(unsigned long *)(virt + kexec_free_mem_offset) = PAGE0->mem_free;
+
+ flush_cache_all();
+ flush_tlb_all();
+ local_irq_disable();
+
+ reloc(image->head & PAGE_MASK, image->start, phys);
+}
+
+int machine_kexec_prepare(struct kimage *image)
+{
+ kexec_image_info(image);
+ return 0;
+}
diff --git a/arch/parisc/kernel/kexec_file.c b/arch/parisc/kernel/kexec_file.c
new file mode 100644
index 0000000..8c53420
--- /dev/null
+++ b/arch/parisc/kernel/kexec_file.c
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Load ELF vmlinux file for the kexec_file_load syscall.
+ *
+ * Copyright (c) 2019 Sven Schnelle <svens@stackframe.org>
+ *
+ */
+#include <linux/elf.h>
+#include <linux/kexec.h>
+#include <linux/libfdt.h>
+#include <linux/module.h>
+#include <linux/of_fdt.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+static void *elf_load(struct kimage *image, char *kernel_buf,
+ unsigned long kernel_len, char *initrd,
+ unsigned long initrd_len, char *cmdline,
+ unsigned long cmdline_len)
+{
+ int ret, i;
+ unsigned long kernel_load_addr;
+ struct elfhdr ehdr;
+ struct kexec_elf_info elf_info;
+ struct kexec_buf kbuf = { .image = image, .buf_min = 0,
+ .buf_max = -1UL, };
+
+ ret = kexec_build_elf_info(kernel_buf, kernel_len, &ehdr, &elf_info);
+ if (ret)
+ goto out;
+
+ ret = kexec_elf_load(image, &ehdr, &elf_info, &kbuf, &kernel_load_addr);
+ if (ret)
+ goto out;
+
+ image->start = __pa(elf_info.ehdr->e_entry);
+
+ for (i = 0; i < image->nr_segments; i++)
+ image->segment[i].mem = __pa(image->segment[i].mem);
+
+ pr_debug("Loaded the kernel at 0x%lx, entry at 0x%lx\n",
+ kernel_load_addr, image->start);
+
+ if (initrd != NULL) {
+ kbuf.buffer = initrd;
+ kbuf.bufsz = kbuf.memsz = initrd_len;
+ kbuf.buf_align = PAGE_SIZE;
+ kbuf.top_down = false;
+ kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
+ ret = kexec_add_buffer(&kbuf);
+ if (ret)
+ goto out;
+
+ pr_debug("Loaded initrd at 0x%lx\n", kbuf.mem);
+ image->arch.initrd_start = kbuf.mem;
+ image->arch.initrd_end = kbuf.mem + initrd_len;
+ }
+
+ if (cmdline != NULL) {
+ kbuf.buffer = cmdline;
+ kbuf.bufsz = kbuf.memsz = ALIGN(cmdline_len, 8);
+ kbuf.buf_align = PAGE_SIZE;
+ kbuf.top_down = false;
+ kbuf.buf_min = PAGE0->mem_free + PAGE_SIZE;
+ kbuf.buf_max = kernel_load_addr;
+ kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
+ ret = kexec_add_buffer(&kbuf);
+ if (ret)
+ goto out;
+
+ pr_debug("Loaded cmdline at 0x%lx\n", kbuf.mem);
+ image->arch.cmdline = kbuf.mem;
+ }
+out:
+ return NULL;
+}
+
+const struct kexec_file_ops kexec_elf_ops = {
+ .probe = kexec_elf_probe,
+ .load = elf_load,
+};
+
+const struct kexec_file_ops * const kexec_file_loaders[] = {
+ &kexec_elf_ops,
+ NULL
+};
diff --git a/arch/parisc/kernel/kgdb.c b/arch/parisc/kernel/kgdb.c
new file mode 100644
index 0000000..664278d
--- /dev/null
+++ b/arch/parisc/kernel/kgdb.c
@@ -0,0 +1,209 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PA-RISC KGDB support
+ *
+ * Copyright (c) 2019 Sven Schnelle <svens@stackframe.org>
+ *
+ */
+
+#include <linux/kgdb.h>
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/notifier.h>
+#include <linux/kdebug.h>
+#include <linux/uaccess.h>
+#include <asm/ptrace.h>
+#include <asm/traps.h>
+#include <asm/processor.h>
+#include <asm/patch.h>
+#include <asm/cacheflush.h>
+
+const struct kgdb_arch arch_kgdb_ops = {
+ .gdb_bpt_instr = { 0x03, 0xff, 0xa0, 0x1f }
+};
+
+static int __kgdb_notify(struct die_args *args, unsigned long cmd)
+{
+ struct pt_regs *regs = args->regs;
+
+ if (kgdb_handle_exception(1, args->signr, cmd, regs))
+ return NOTIFY_DONE;
+ return NOTIFY_STOP;
+}
+
+static int kgdb_notify(struct notifier_block *self,
+ unsigned long cmd, void *ptr)
+{
+ unsigned long flags;
+ int ret;
+
+ local_irq_save(flags);
+ ret = __kgdb_notify(ptr, cmd);
+ local_irq_restore(flags);
+
+ return ret;
+}
+
+static struct notifier_block kgdb_notifier = {
+ .notifier_call = kgdb_notify,
+ .priority = -INT_MAX,
+};
+
+int kgdb_arch_init(void)
+{
+ return register_die_notifier(&kgdb_notifier);
+}
+
+void kgdb_arch_exit(void)
+{
+ unregister_die_notifier(&kgdb_notifier);
+}
+
+void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+{
+ struct parisc_gdb_regs *gr = (struct parisc_gdb_regs *)gdb_regs;
+
+ memset(gr, 0, sizeof(struct parisc_gdb_regs));
+
+ memcpy(gr->gpr, regs->gr, sizeof(gr->gpr));
+ memcpy(gr->fr, regs->fr, sizeof(gr->fr));
+
+ gr->sr0 = regs->sr[0];
+ gr->sr1 = regs->sr[1];
+ gr->sr2 = regs->sr[2];
+ gr->sr3 = regs->sr[3];
+ gr->sr4 = regs->sr[4];
+ gr->sr5 = regs->sr[5];
+ gr->sr6 = regs->sr[6];
+ gr->sr7 = regs->sr[7];
+
+ gr->sar = regs->sar;
+ gr->iir = regs->iir;
+ gr->isr = regs->isr;
+ gr->ior = regs->ior;
+ gr->ipsw = regs->ipsw;
+ gr->cr27 = regs->cr27;
+
+ gr->iaoq_f = regs->iaoq[0];
+ gr->iasq_f = regs->iasq[0];
+
+ gr->iaoq_b = regs->iaoq[1];
+ gr->iasq_b = regs->iasq[1];
+}
+
+void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+{
+ struct parisc_gdb_regs *gr = (struct parisc_gdb_regs *)gdb_regs;
+
+
+ memcpy(regs->gr, gr->gpr, sizeof(regs->gr));
+ memcpy(regs->fr, gr->fr, sizeof(regs->fr));
+
+ regs->sr[0] = gr->sr0;
+ regs->sr[1] = gr->sr1;
+ regs->sr[2] = gr->sr2;
+ regs->sr[3] = gr->sr3;
+ regs->sr[4] = gr->sr4;
+ regs->sr[5] = gr->sr5;
+ regs->sr[6] = gr->sr6;
+ regs->sr[7] = gr->sr7;
+
+ regs->sar = gr->sar;
+ regs->iir = gr->iir;
+ regs->isr = gr->isr;
+ regs->ior = gr->ior;
+ regs->ipsw = gr->ipsw;
+ regs->cr27 = gr->cr27;
+
+ regs->iaoq[0] = gr->iaoq_f;
+ regs->iasq[0] = gr->iasq_f;
+
+ regs->iaoq[1] = gr->iaoq_b;
+ regs->iasq[1] = gr->iasq_b;
+}
+
+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs,
+ struct task_struct *task)
+{
+ struct pt_regs *regs = task_pt_regs(task);
+ unsigned long gr30, iaoq;
+
+ gr30 = regs->gr[30];
+ iaoq = regs->iaoq[0];
+
+ regs->gr[30] = regs->ksp;
+ regs->iaoq[0] = regs->kpc;
+ pt_regs_to_gdb_regs(gdb_regs, regs);
+
+ regs->gr[30] = gr30;
+ regs->iaoq[0] = iaoq;
+
+}
+
+static void step_instruction_queue(struct pt_regs *regs)
+{
+ regs->iaoq[0] = regs->iaoq[1];
+ regs->iaoq[1] += 4;
+}
+
+void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip)
+{
+ regs->iaoq[0] = ip;
+ regs->iaoq[1] = ip + 4;
+}
+
+int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
+{
+ int ret = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,
+ BREAK_INSTR_SIZE);
+ if (ret)
+ return ret;
+
+ __patch_text((void *)bpt->bpt_addr,
+ *(unsigned int *)&arch_kgdb_ops.gdb_bpt_instr);
+ return ret;
+}
+
+int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
+{
+ __patch_text((void *)bpt->bpt_addr, *(unsigned int *)&bpt->saved_instr);
+ return 0;
+}
+
+int kgdb_arch_handle_exception(int trap, int signo,
+ int err_code, char *inbuf, char *outbuf,
+ struct pt_regs *regs)
+{
+ unsigned long addr;
+ char *p = inbuf + 1;
+
+ switch (inbuf[0]) {
+ case 'D':
+ case 'c':
+ case 'k':
+ kgdb_contthread = NULL;
+ kgdb_single_step = 0;
+
+ if (kgdb_hex2long(&p, &addr))
+ kgdb_arch_set_pc(regs, addr);
+ else if (trap == 9 && regs->iir ==
+ PARISC_KGDB_COMPILED_BREAK_INSN)
+ step_instruction_queue(regs);
+ return 0;
+ case 's':
+ kgdb_single_step = 1;
+ if (kgdb_hex2long(&p, &addr)) {
+ kgdb_arch_set_pc(regs, addr);
+ } else if (trap == 9 && regs->iir ==
+ PARISC_KGDB_COMPILED_BREAK_INSN) {
+ step_instruction_queue(regs);
+ mtctl(-1, 0);
+ } else {
+ mtctl(0, 0);
+ }
+ regs->gr[0] |= PSW_R;
+ return 0;
+
+ }
+ return -1;
+}
diff --git a/arch/parisc/kernel/kprobes.c b/arch/parisc/kernel/kprobes.c
new file mode 100644
index 0000000..77ec518
--- /dev/null
+++ b/arch/parisc/kernel/kprobes.c
@@ -0,0 +1,290 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * arch/parisc/kernel/kprobes.c
+ *
+ * PA-RISC kprobes implementation
+ *
+ * Copyright (c) 2019 Sven Schnelle <svens@stackframe.org>
+ */
+
+#include <linux/types.h>
+#include <linux/kprobes.h>
+#include <linux/slab.h>
+#include <asm/cacheflush.h>
+#include <asm/patch.h>
+
+DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
+DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
+
+int __kprobes arch_prepare_kprobe(struct kprobe *p)
+{
+ if ((unsigned long)p->addr & 3UL)
+ return -EINVAL;
+
+ p->ainsn.insn = get_insn_slot();
+ if (!p->ainsn.insn)
+ return -ENOMEM;
+
+ memcpy(p->ainsn.insn, p->addr,
+ MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
+ p->opcode = *p->addr;
+ flush_insn_slot(p);
+ return 0;
+}
+
+void __kprobes arch_remove_kprobe(struct kprobe *p)
+{
+ if (!p->ainsn.insn)
+ return;
+
+ free_insn_slot(p->ainsn.insn, 0);
+ p->ainsn.insn = NULL;
+}
+
+void __kprobes arch_arm_kprobe(struct kprobe *p)
+{
+ patch_text(p->addr, PARISC_KPROBES_BREAK_INSN);
+}
+
+void __kprobes arch_disarm_kprobe(struct kprobe *p)
+{
+ patch_text(p->addr, p->opcode);
+}
+
+static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
+{
+ kcb->prev_kprobe.kp = kprobe_running();
+ kcb->prev_kprobe.status = kcb->kprobe_status;
+}
+
+static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+{
+ __this_cpu_write(current_kprobe, kcb->prev_kprobe.kp);
+ kcb->kprobe_status = kcb->prev_kprobe.status;
+}
+
+static inline void __kprobes set_current_kprobe(struct kprobe *p)
+{
+ __this_cpu_write(current_kprobe, p);
+}
+
+static void __kprobes setup_singlestep(struct kprobe *p,
+ struct kprobe_ctlblk *kcb, struct pt_regs *regs)
+{
+ kcb->iaoq[0] = regs->iaoq[0];
+ kcb->iaoq[1] = regs->iaoq[1];
+ regs->iaoq[0] = (unsigned long)p->ainsn.insn;
+ mtctl(0, 0);
+ regs->gr[0] |= PSW_R;
+}
+
+int __kprobes parisc_kprobe_break_handler(struct pt_regs *regs)
+{
+ struct kprobe *p;
+ struct kprobe_ctlblk *kcb;
+
+ preempt_disable();
+
+ kcb = get_kprobe_ctlblk();
+ p = get_kprobe((unsigned long *)regs->iaoq[0]);
+
+ if (!p) {
+ preempt_enable_no_resched();
+ return 0;
+ }
+
+ if (kprobe_running()) {
+ /*
+ * We have reentered the kprobe_handler, since another kprobe
+ * was hit while within the handler, we save the original
+ * kprobes and single step on the instruction of the new probe
+ * without calling any user handlers to avoid recursive
+ * kprobes.
+ */
+ save_previous_kprobe(kcb);
+ set_current_kprobe(p);
+ kprobes_inc_nmissed_count(p);
+ setup_singlestep(p, kcb, regs);
+ kcb->kprobe_status = KPROBE_REENTER;
+ return 1;
+ }
+
+ set_current_kprobe(p);
+ kcb->kprobe_status = KPROBE_HIT_ACTIVE;
+
+ /* If we have no pre-handler or it returned 0, we continue with
+ * normal processing. If we have a pre-handler and it returned
+ * non-zero - which means user handler setup registers to exit
+ * to another instruction, we must skip the single stepping.
+ */
+
+ if (!p->pre_handler || !p->pre_handler(p, regs)) {
+ setup_singlestep(p, kcb, regs);
+ kcb->kprobe_status = KPROBE_HIT_SS;
+ } else {
+ reset_current_kprobe();
+ preempt_enable_no_resched();
+ }
+ return 1;
+}
+
+int __kprobes parisc_kprobe_ss_handler(struct pt_regs *regs)
+{
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+ struct kprobe *p = kprobe_running();
+
+ if (!p)
+ return 0;
+
+ if (regs->iaoq[0] != (unsigned long)p->ainsn.insn+4)
+ return 0;
+
+ /* restore back original saved kprobe variables and continue */
+ if (kcb->kprobe_status == KPROBE_REENTER) {
+ restore_previous_kprobe(kcb);
+ return 1;
+ }
+
+ /* for absolute branch instructions we can copy iaoq_b. for relative
+ * branch instructions we need to calculate the new address based on the
+ * difference between iaoq_f and iaoq_b. We cannot use iaoq_b without
+ * modificationt because it's based on our ainsn.insn address.
+ */
+
+ if (p->post_handler)
+ p->post_handler(p, regs, 0);
+
+ switch (regs->iir >> 26) {
+ case 0x38: /* BE */
+ case 0x39: /* BE,L */
+ case 0x3a: /* BV */
+ case 0x3b: /* BVE */
+ /* for absolute branches, regs->iaoq[1] has already the right
+ * address
+ */
+ regs->iaoq[0] = kcb->iaoq[1];
+ break;
+ default:
+ regs->iaoq[1] = kcb->iaoq[0];
+ regs->iaoq[1] += (regs->iaoq[1] - regs->iaoq[0]) + 4;
+ regs->iaoq[0] = kcb->iaoq[1];
+ break;
+ }
+ kcb->kprobe_status = KPROBE_HIT_SSDONE;
+ reset_current_kprobe();
+ return 1;
+}
+
+static inline void kretprobe_trampoline(void)
+{
+ asm volatile("nop");
+ asm volatile("nop");
+}
+
+static int __kprobes trampoline_probe_handler(struct kprobe *p,
+ struct pt_regs *regs);
+
+static struct kprobe trampoline_p = {
+ .pre_handler = trampoline_probe_handler
+};
+
+static int __kprobes trampoline_probe_handler(struct kprobe *p,
+ struct pt_regs *regs)
+{
+ struct kretprobe_instance *ri = NULL;
+ struct hlist_head *head, empty_rp;
+ struct hlist_node *tmp;
+ unsigned long flags, orig_ret_address = 0;
+ unsigned long trampoline_address = (unsigned long)trampoline_p.addr;
+ kprobe_opcode_t *correct_ret_addr = NULL;
+
+ INIT_HLIST_HEAD(&empty_rp);
+ kretprobe_hash_lock(current, &head, &flags);
+
+ /*
+ * It is possible to have multiple instances associated with a given
+ * task either because multiple functions in the call path have
+ * a return probe installed on them, and/or more than one return
+ * probe was registered for a target function.
+ *
+ * We can handle this because:
+ * - instances are always inserted at the head of the list
+ * - when multiple return probes are registered for the same
+ * function, the first instance's ret_addr will point to the
+ * real return address, and all the rest will point to
+ * kretprobe_trampoline
+ */
+ hlist_for_each_entry_safe(ri, tmp, head, hlist) {
+ if (ri->task != current)
+ /* another task is sharing our hash bucket */
+ continue;
+
+ orig_ret_address = (unsigned long)ri->ret_addr;
+
+ if (orig_ret_address != trampoline_address)
+ /*
+ * This is the real return address. Any other
+ * instances associated with this task are for
+ * other calls deeper on the call stack
+ */
+ break;
+ }
+
+ kretprobe_assert(ri, orig_ret_address, trampoline_address);
+
+ correct_ret_addr = ri->ret_addr;
+ hlist_for_each_entry_safe(ri, tmp, head, hlist) {
+ if (ri->task != current)
+ /* another task is sharing our hash bucket */
+ continue;
+
+ orig_ret_address = (unsigned long)ri->ret_addr;
+ if (ri->rp && ri->rp->handler) {
+ __this_cpu_write(current_kprobe, &ri->rp->kp);
+ get_kprobe_ctlblk()->kprobe_status = KPROBE_HIT_ACTIVE;
+ ri->ret_addr = correct_ret_addr;
+ ri->rp->handler(ri, regs);
+ __this_cpu_write(current_kprobe, NULL);
+ }
+
+ recycle_rp_inst(ri, &empty_rp);
+
+ if (orig_ret_address != trampoline_address)
+ /*
+ * This is the real return address. Any other
+ * instances associated with this task are for
+ * other calls deeper on the call stack
+ */
+ break;
+ }
+
+ kretprobe_hash_unlock(current, &flags);
+
+ hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
+ hlist_del(&ri->hlist);
+ kfree(ri);
+ }
+ instruction_pointer_set(regs, orig_ret_address);
+ return 1;
+}
+
+void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
+ struct pt_regs *regs)
+{
+ ri->ret_addr = (kprobe_opcode_t *)regs->gr[2];
+
+ /* Replace the return addr with trampoline addr. */
+ regs->gr[2] = (unsigned long)trampoline_p.addr;
+}
+
+int __kprobes arch_trampoline_kprobe(struct kprobe *p)
+{
+ return p->addr == trampoline_p.addr;
+}
+
+int __init arch_init_kprobes(void)
+{
+ trampoline_p.addr = (kprobe_opcode_t *)
+ dereference_function_descriptor(kretprobe_trampoline);
+ return register_kprobe(&trampoline_p);
+}
diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c
index b5b3cb0..ac5f349 100644
--- a/arch/parisc/kernel/module.c
+++ b/arch/parisc/kernel/module.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/* Kernel dynamically loadable module help for PARISC.
*
* The best reference for this stuff is probably the Processor-
@@ -8,22 +9,6 @@
* Copyright (C) 2003 Randolph Chung <tausq at debian . org>
* Copyright (C) 2008 Helge Deller <deller@gmx.de>
*
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- *
* Notes:
* - PLT stub handling
* On 32bit (and sometimes 64bit) and with big kernel modules like xfs or
@@ -48,9 +33,9 @@
* However, SEGREL32 is used only for PARISC unwind entries, and we want
* those entries to have an absolute address, and not just an offset.
*
- * The unwind table mechanism has the ability to specify an offset for
+ * The unwind table mechanism has the ability to specify an offset for
* the unwind table; however, because we split off the init functions into
- * a different piece of memory, it is not possible to do this using a
+ * a different piece of memory, it is not possible to do this using a
* single offset. Instead, we use the above hack for now.
*/
@@ -68,12 +53,6 @@
#include <asm/unwind.h>
#include <asm/sections.h>
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(fmt...)
-#endif
-
#define RELOC_REACHABLE(val, bits) \
(( ( !((val) & (1<<((bits)-1))) && ((val)>>(bits)) != 0 ) || \
( ((val) & (1<<((bits)-1))) && ((val)>>(bits)) != (((__typeof__(val))(~0))>>((bits)+2)))) ? \
@@ -315,7 +294,7 @@
* sizeof(struct stub_entry);
}
-#define CONST
+#define CONST
int module_frob_arch_sections(CONST Elf_Ehdr *hdr,
CONST Elf_Shdr *sechdrs,
CONST char *secstrings,
@@ -401,7 +380,7 @@
got[i].addr = value;
out:
- DEBUGP("GOT ENTRY %d[%x] val %lx\n", i, i*sizeof(struct got_entry),
+ pr_debug("GOT ENTRY %d[%lx] val %lx\n", i, i*sizeof(struct got_entry),
value);
return i * sizeof(struct got_entry);
}
@@ -554,7 +533,7 @@
//unsigned long dp = (unsigned long)$global$;
register unsigned long dp asm ("r27");
- DEBUGP("Applying relocate section %u to %u\n", relsec,
+ pr_debug("Applying relocate section %u to %u\n", relsec,
targetsec);
for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
/* This is where to make the change */
@@ -578,7 +557,7 @@
#if 0
#define r(t) ELF32_R_TYPE(rel[i].r_info)==t ? #t :
- DEBUGP("Symbol %s loc 0x%x val 0x%x addend 0x%x: %s\n",
+ pr_debug("Symbol %s loc 0x%x val 0x%x addend 0x%x: %s\n",
strtab + sym->st_name,
(uint32_t)loc, val, addend,
r(R_PARISC_PLABEL32)
@@ -619,7 +598,7 @@
/* See note about special handling of SEGREL32 at
* the beginning of this file.
*/
- *loc = fsel(val, addend);
+ *loc = fsel(val, addend);
break;
case R_PARISC_SECREL32:
/* 32-bit section relative address. */
@@ -698,7 +677,7 @@
Elf_Addr loc0;
unsigned int targetsec = sechdrs[relsec].sh_info;
- DEBUGP("Applying relocate section %u to %u\n", relsec,
+ pr_debug("Applying relocate section %u to %u\n", relsec,
targetsec);
for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
/* This is where to make the change */
@@ -740,7 +719,7 @@
case R_PARISC_LTOFF21L:
/* LT-relative; left 21 bits */
val = get_got(me, val, addend);
- DEBUGP("LTOFF21L Symbol %s loc %p val %lx\n",
+ pr_debug("LTOFF21L Symbol %s loc %p val %llx\n",
strtab + sym->st_name,
loc, val);
val = lrsel(val, 0);
@@ -751,14 +730,14 @@
/* LT-relative; right 14 bits */
val = get_got(me, val, addend);
val = rrsel(val, 0);
- DEBUGP("LTOFF14R Symbol %s loc %p val %lx\n",
+ pr_debug("LTOFF14R Symbol %s loc %p val %llx\n",
strtab + sym->st_name,
loc, val);
*loc = mask(*loc, 14) | reassemble_14(val);
break;
case R_PARISC_PCREL22F:
/* PC-relative; 22 bits */
- DEBUGP("PCREL22F Symbol %s loc %p val %lx\n",
+ pr_debug("PCREL22F Symbol %s loc %p val %llx\n",
strtab + sym->st_name,
loc, val);
val += addend;
@@ -790,7 +769,7 @@
val = get_stub(me, val, addend, ELF_STUB_GOT,
loc0, targetsec);
}
- DEBUGP("STUB FOR %s loc %lx, val %lx+%lx at %lx\n",
+ pr_debug("STUB FOR %s loc %px, val %llx+%llx at %llx\n",
strtab + sym->st_name, loc, sym->st_value,
addend, val);
val = (val - dot - 8)/4;
@@ -801,6 +780,10 @@
/* 32-bit PC relative address */
*loc = val - dot - 8 + addend;
break;
+ case R_PARISC_PCREL64:
+ /* 64-bit PC relative address */
+ *loc64 = val - dot - 8 + addend;
+ break;
case R_PARISC_DIR64:
/* 64-bit effective address */
*loc64 = val + addend;
@@ -810,7 +793,7 @@
/* See note about special handling of SEGREL32 at
* the beginning of this file.
*/
- *loc = fsel(val, addend);
+ *loc = fsel(val, addend);
break;
case R_PARISC_SECREL32:
/* 32-bit section relative address. */
@@ -820,14 +803,14 @@
/* 64-bit function address */
if(in_local(me, (void *)(val + addend))) {
*loc64 = get_fdesc(me, val+addend);
- DEBUGP("FDESC for %s at %p points to %lx\n",
+ pr_debug("FDESC for %s at %llx points to %llx\n",
strtab + sym->st_name, *loc64,
((Elf_Fdesc *)*loc64)->addr);
} else {
/* if the symbol is not local to this
* module then val+addend is a pointer
* to the function descriptor */
- DEBUGP("Non local FPTR64 Symbol %s loc %p val %lx\n",
+ pr_debug("Non local FPTR64 Symbol %s loc %p val %llx\n",
strtab + sym->st_name,
loc, val);
*loc64 = val + addend;
@@ -858,7 +841,7 @@
end = table + sechdrs[me->arch.unwind_section].sh_size;
gp = (Elf_Addr)me->core_layout.base + me->arch.got_offset;
- DEBUGP("register_unwind_table(), sect = %d at 0x%p - 0x%p (gp=0x%lx)\n",
+ pr_debug("register_unwind_table(), sect = %d at 0x%p - 0x%p (gp=0x%lx)\n",
me->arch.unwind_section, table, end, gp);
me->arch.unwind = unwind_table_add(me->name, 0, gp, table, end);
}
@@ -877,6 +860,9 @@
int i;
unsigned long nsyms;
const char *strtab = NULL;
+ const Elf_Shdr *s;
+ char *secstrings;
+ int err, symindex = -1;
Elf_Sym *newptr, *oldptr;
Elf_Shdr *symhdr = NULL;
#ifdef DEBUG
@@ -903,6 +889,7 @@
if(sechdrs[i].sh_type == SHT_SYMTAB
&& (sechdrs[i].sh_flags & SHF_ALLOC)) {
int strindex = sechdrs[i].sh_link;
+ symindex = i;
/* FIXME: AWFUL HACK
* The cast is to drop the const from
* the sechdrs pointer */
@@ -912,7 +899,7 @@
}
}
- DEBUGP("module %s: strtab %p, symhdr %p\n",
+ pr_debug("module %s: strtab %p, symhdr %p\n",
me->name, strtab, symhdr);
if(me->arch.got_count > MAX_GOTS) {
@@ -931,7 +918,7 @@
oldptr = (void *)symhdr->sh_addr;
newptr = oldptr + 1; /* we start counting at 1 */
nsyms = symhdr->sh_size / sizeof(Elf_Sym);
- DEBUGP("OLD num_symtab %lu\n", nsyms);
+ pr_debug("OLD num_symtab %lu\n", nsyms);
for (i = 1; i < nsyms; i++) {
oldptr++; /* note, count starts at 1 so preincrement */
@@ -946,8 +933,36 @@
}
nsyms = newptr - (Elf_Sym *)symhdr->sh_addr;
- DEBUGP("NEW num_symtab %lu\n", nsyms);
+ pr_debug("NEW num_symtab %lu\n", nsyms);
symhdr->sh_size = nsyms * sizeof(Elf_Sym);
+
+ /* find .altinstructions section */
+ secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+ for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
+ void *aseg = (void *) s->sh_addr;
+ char *secname = secstrings + s->sh_name;
+
+ if (!strcmp(".altinstructions", secname))
+ /* patch .altinstructions */
+ apply_alternatives(aseg, aseg + s->sh_size, me->name);
+
+ /* For 32 bit kernels we're compiling modules with
+ * -ffunction-sections so we must relocate the addresses in the
+ *__mcount_loc section.
+ */
+ if (symindex != -1 && !strcmp(secname, "__mcount_loc")) {
+ if (s->sh_type == SHT_REL)
+ err = apply_relocate((Elf_Shdr *)sechdrs,
+ strtab, symindex,
+ s - sechdrs, me);
+ else if (s->sh_type == SHT_RELA)
+ err = apply_relocate_add((Elf_Shdr *)sechdrs,
+ strtab, symindex,
+ s - sechdrs, me);
+ if (err)
+ return err;
+ }
+ }
return 0;
}
diff --git a/arch/parisc/kernel/module.lds b/arch/parisc/kernel/module.lds
new file mode 100644
index 0000000..1a9a92a
--- /dev/null
+++ b/arch/parisc/kernel/module.lds
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+SECTIONS {
+ __mcount_loc : {
+ *(__patchable_function_entries)
+ }
+}
diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S
index f33bf2d..fa092ed 100644
--- a/arch/parisc/kernel/pacache.S
+++ b/arch/parisc/kernel/pacache.S
@@ -1,22 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* PARISC TLB and cache flushing support
* Copyright (C) 2000-2001 Hewlett-Packard (John Marvin)
* Copyright (C) 2001 Matthew Wilcox (willy at parisc-linux.org)
* Copyright (C) 2002 Richard Hirst (rhirst with parisc-linux.org)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
@@ -37,6 +24,7 @@
#include <asm/pgtable.h>
#include <asm/cache.h>
#include <asm/ldcw.h>
+#include <asm/alternative.h>
#include <linux/linkage.h>
#include <linux/init.h>
@@ -75,7 +63,7 @@
/* Flush Instruction Tlb */
- LDREG ITLB_SID_BASE(%r1), %r20
+88: LDREG ITLB_SID_BASE(%r1), %r20
LDREG ITLB_SID_STRIDE(%r1), %r21
LDREG ITLB_SID_COUNT(%r1), %r22
LDREG ITLB_OFF_BASE(%r1), %arg0
@@ -115,6 +103,7 @@
add %r21, %r20, %r20 /* increment space */
fitdone:
+ ALTERNATIVE(88b, fitdone, ALT_COND_NO_SPLIT_TLB, INSN_NOP)
/* Flush Data Tlb */
@@ -185,12 +174,21 @@
2: bv %r0(%r2)
nop
+
+ /*
+ * When running in qemu, drop whole flush_tlb_all_local function and
+ * replace by one pdtlbe instruction, for which QEMU will drop all
+ * local TLB entries.
+ */
+3: pdtlbe %r0(%sr1,%r0)
+ bv,n %r0(%r2)
+ ALTERNATIVE_CODE(flush_tlb_all_local, 2, ALT_COND_RUN_ON_QEMU, 3b)
ENDPROC_CFI(flush_tlb_all_local)
.import cache_info,data
ENTRY_CFI(flush_instruction_cache_local)
- load32 cache_info, %r1
+88: load32 cache_info, %r1
/* Flush Instruction Cache */
@@ -243,6 +241,7 @@
fisync:
sync
mtsm %r22 /* restore I-bit */
+89: ALTERNATIVE(88b, 89b, ALT_COND_NO_ICACHE, INSN_NOP)
bv %r0(%r2)
nop
ENDPROC_CFI(flush_instruction_cache_local)
@@ -250,7 +249,7 @@
.import cache_info, data
ENTRY_CFI(flush_data_cache_local)
- load32 cache_info, %r1
+88: load32 cache_info, %r1
/* Flush Data Cache */
@@ -304,40 +303,11 @@
syncdma
sync
mtsm %r22 /* restore I-bit */
+89: ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP)
bv %r0(%r2)
nop
ENDPROC_CFI(flush_data_cache_local)
-/* Macros to serialize TLB purge operations on SMP. */
-
- .macro tlb_lock la,flags,tmp
-#ifdef CONFIG_SMP
-#if __PA_LDCW_ALIGNMENT > 4
- load32 pa_tlb_lock + __PA_LDCW_ALIGNMENT-1, \la
- depi 0,31,__PA_LDCW_ALIGN_ORDER, \la
-#else
- load32 pa_tlb_lock, \la
-#endif
- rsm PSW_SM_I,\flags
-1: LDCW 0(\la),\tmp
- cmpib,<>,n 0,\tmp,3f
-2: ldw 0(\la),\tmp
- cmpb,<> %r0,\tmp,1b
- nop
- b,n 2b
-3:
-#endif
- .endm
-
- .macro tlb_unlock la,flags,tmp
-#ifdef CONFIG_SMP
- ldi 1,\tmp
- sync
- stw \tmp,0(\la)
- mtsm \flags
-#endif
- .endm
-
/* Clear page using kernel mapping. */
ENTRY_CFI(clear_page_asm)
@@ -595,10 +565,10 @@
pdtlb,l %r0(%r28)
pdtlb,l %r0(%r29)
#else
- tlb_lock %r20,%r21,%r22
- pdtlb %r0(%r28)
- pdtlb %r0(%r29)
- tlb_unlock %r20,%r21,%r22
+0: pdtlb %r0(%r28)
+1: pdtlb %r0(%r29)
+ ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, INSN_PxTLB)
+ ALTERNATIVE(1b, 1b+4, ALT_COND_NO_SMP, INSN_PxTLB)
#endif
#ifdef CONFIG_64BIT
@@ -735,9 +705,8 @@
#ifdef CONFIG_PA20
pdtlb,l %r0(%r28)
#else
- tlb_lock %r20,%r21,%r22
- pdtlb %r0(%r28)
- tlb_unlock %r20,%r21,%r22
+0: pdtlb %r0(%r28)
+ ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, INSN_PxTLB)
#endif
#ifdef CONFIG_64BIT
@@ -812,12 +781,11 @@
#ifdef CONFIG_PA20
pdtlb,l %r0(%r28)
#else
- tlb_lock %r20,%r21,%r22
- pdtlb %r0(%r28)
- tlb_unlock %r20,%r21,%r22
+0: pdtlb %r0(%r28)
+ ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, INSN_PxTLB)
#endif
- ldil L%dcache_stride, %r1
+88: ldil L%dcache_stride, %r1
ldw R%dcache_stride(%r1), r31
#ifdef CONFIG_64BIT
@@ -828,8 +796,7 @@
add %r28, %r25, %r25
sub %r25, r31, %r25
-
-1: fdc,m r31(%r28)
+1: fdc,m r31(%r28)
fdc,m r31(%r28)
fdc,m r31(%r28)
fdc,m r31(%r28)
@@ -844,14 +811,74 @@
fdc,m r31(%r28)
fdc,m r31(%r28)
fdc,m r31(%r28)
- cmpb,COND(<<) %r28, %r25,1b
+ cmpb,COND(>>) %r25, %r28, 1b /* predict taken */
fdc,m r31(%r28)
+89: ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP)
sync
bv %r0(%r2)
nop
ENDPROC_CFI(flush_dcache_page_asm)
+ENTRY_CFI(purge_dcache_page_asm)
+ ldil L%(TMPALIAS_MAP_START), %r28
+#ifdef CONFIG_64BIT
+#if (TMPALIAS_MAP_START >= 0x80000000)
+ depdi 0, 31,32, %r28 /* clear any sign extension */
+#endif
+ convert_phys_for_tlb_insert20 %r26 /* convert phys addr to tlb insert format */
+ depd %r25, 63,22, %r28 /* Form aliased virtual address 'to' */
+ depdi 0, 63,PAGE_SHIFT, %r28 /* Clear any offset bits */
+#else
+ extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */
+ depw %r25, 31,22, %r28 /* Form aliased virtual address 'to' */
+ depwi 0, 31,PAGE_SHIFT, %r28 /* Clear any offset bits */
+#endif
+
+ /* Purge any old translation */
+
+#ifdef CONFIG_PA20
+ pdtlb,l %r0(%r28)
+#else
+0: pdtlb %r0(%r28)
+ ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, INSN_PxTLB)
+#endif
+
+88: ldil L%dcache_stride, %r1
+ ldw R%dcache_stride(%r1), r31
+
+#ifdef CONFIG_64BIT
+ depdi,z 1, 63-PAGE_SHIFT,1, %r25
+#else
+ depwi,z 1, 31-PAGE_SHIFT,1, %r25
+#endif
+ add %r28, %r25, %r25
+ sub %r25, r31, %r25
+
+1: pdc,m r31(%r28)
+ pdc,m r31(%r28)
+ pdc,m r31(%r28)
+ pdc,m r31(%r28)
+ pdc,m r31(%r28)
+ pdc,m r31(%r28)
+ pdc,m r31(%r28)
+ pdc,m r31(%r28)
+ pdc,m r31(%r28)
+ pdc,m r31(%r28)
+ pdc,m r31(%r28)
+ pdc,m r31(%r28)
+ pdc,m r31(%r28)
+ pdc,m r31(%r28)
+ pdc,m r31(%r28)
+ cmpb,COND(>>) %r25, %r28, 1b /* predict taken */
+ pdc,m r31(%r28)
+
+89: ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP)
+ sync
+ bv %r0(%r2)
+ nop
+ENDPROC_CFI(purge_dcache_page_asm)
+
ENTRY_CFI(flush_icache_page_asm)
ldil L%(TMPALIAS_MAP_START), %r28
#ifdef CONFIG_64BIT
@@ -874,15 +901,17 @@
#ifdef CONFIG_PA20
pdtlb,l %r0(%r28)
- pitlb,l %r0(%sr4,%r28)
+1: pitlb,l %r0(%sr4,%r28)
+ ALTERNATIVE(1b, 1b+4, ALT_COND_NO_SPLIT_TLB, INSN_NOP)
#else
- tlb_lock %r20,%r21,%r22
- pdtlb %r0(%r28)
- pitlb %r0(%sr4,%r28)
- tlb_unlock %r20,%r21,%r22
+0: pdtlb %r0(%r28)
+1: pitlb %r0(%sr4,%r28)
+ ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, INSN_PxTLB)
+ ALTERNATIVE(1b, 1b+4, ALT_COND_NO_SMP, INSN_PxTLB)
+ ALTERNATIVE(1b, 1b+4, ALT_COND_NO_SPLIT_TLB, INSN_NOP)
#endif
- ldil L%icache_stride, %r1
+88: ldil L%icache_stride, %r1
ldw R%icache_stride(%r1), %r31
#ifdef CONFIG_64BIT
@@ -893,7 +922,6 @@
add %r28, %r25, %r25
sub %r25, %r31, %r25
-
/* fic only has the type 26 form on PA1.1, requiring an
* explicit space specification, so use %sr4 */
1: fic,m %r31(%sr4,%r28)
@@ -911,16 +939,17 @@
fic,m %r31(%sr4,%r28)
fic,m %r31(%sr4,%r28)
fic,m %r31(%sr4,%r28)
- cmpb,COND(<<) %r28, %r25,1b
+ cmpb,COND(>>) %r25, %r28, 1b /* predict taken */
fic,m %r31(%sr4,%r28)
+89: ALTERNATIVE(88b, 89b, ALT_COND_NO_ICACHE, INSN_NOP)
sync
bv %r0(%r2)
nop
ENDPROC_CFI(flush_icache_page_asm)
ENTRY_CFI(flush_kernel_dcache_page_asm)
- ldil L%dcache_stride, %r1
+88: ldil L%dcache_stride, %r1
ldw R%dcache_stride(%r1), %r23
#ifdef CONFIG_64BIT
@@ -931,7 +960,6 @@
add %r26, %r25, %r25
sub %r25, %r23, %r25
-
1: fdc,m %r23(%r26)
fdc,m %r23(%r26)
fdc,m %r23(%r26)
@@ -947,16 +975,17 @@
fdc,m %r23(%r26)
fdc,m %r23(%r26)
fdc,m %r23(%r26)
- cmpb,COND(<<) %r26, %r25,1b
+ cmpb,COND(>>) %r25, %r26, 1b /* predict taken */
fdc,m %r23(%r26)
+89: ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP)
sync
bv %r0(%r2)
nop
ENDPROC_CFI(flush_kernel_dcache_page_asm)
ENTRY_CFI(purge_kernel_dcache_page_asm)
- ldil L%dcache_stride, %r1
+88: ldil L%dcache_stride, %r1
ldw R%dcache_stride(%r1), %r23
#ifdef CONFIG_64BIT
@@ -982,74 +1011,183 @@
pdc,m %r23(%r26)
pdc,m %r23(%r26)
pdc,m %r23(%r26)
- cmpb,COND(<<) %r26, %r25, 1b
+ cmpb,COND(>>) %r25, %r26, 1b /* predict taken */
pdc,m %r23(%r26)
+89: ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP)
sync
bv %r0(%r2)
nop
ENDPROC_CFI(purge_kernel_dcache_page_asm)
ENTRY_CFI(flush_user_dcache_range_asm)
- ldil L%dcache_stride, %r1
+88: ldil L%dcache_stride, %r1
ldw R%dcache_stride(%r1), %r23
ldo -1(%r23), %r21
ANDCM %r26, %r21, %r26
-1: cmpb,COND(<<),n %r26, %r25, 1b
+#ifdef CONFIG_64BIT
+ depd,z %r23, 59, 60, %r21
+#else
+ depw,z %r23, 27, 28, %r21
+#endif
+ add %r26, %r21, %r22
+ cmpb,COND(>>),n %r22, %r25, 2f /* predict not taken */
+1: add %r22, %r21, %r22
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ cmpb,COND(<<=) %r22, %r25, 1b /* predict taken */
fdc,m %r23(%sr3, %r26)
+2: cmpb,COND(>>),n %r25, %r26, 2b
+ fdc,m %r23(%sr3, %r26)
+
+89: ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP)
sync
bv %r0(%r2)
nop
ENDPROC_CFI(flush_user_dcache_range_asm)
ENTRY_CFI(flush_kernel_dcache_range_asm)
- ldil L%dcache_stride, %r1
+88: ldil L%dcache_stride, %r1
ldw R%dcache_stride(%r1), %r23
ldo -1(%r23), %r21
ANDCM %r26, %r21, %r26
-1: cmpb,COND(<<),n %r26, %r25,1b
+#ifdef CONFIG_64BIT
+ depd,z %r23, 59, 60, %r21
+#else
+ depw,z %r23, 27, 28, %r21
+#endif
+ add %r26, %r21, %r22
+ cmpb,COND(>>),n %r22, %r25, 2f /* predict not taken */
+1: add %r22, %r21, %r22
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ cmpb,COND(<<=) %r22, %r25, 1b /* predict taken */
+ fdc,m %r23(%r26)
+
+2: cmpb,COND(>>),n %r25, %r26, 2b /* predict taken */
fdc,m %r23(%r26)
sync
+89: ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP)
syncdma
bv %r0(%r2)
nop
ENDPROC_CFI(flush_kernel_dcache_range_asm)
ENTRY_CFI(purge_kernel_dcache_range_asm)
- ldil L%dcache_stride, %r1
+88: ldil L%dcache_stride, %r1
ldw R%dcache_stride(%r1), %r23
ldo -1(%r23), %r21
ANDCM %r26, %r21, %r26
-1: cmpb,COND(<<),n %r26, %r25,1b
+#ifdef CONFIG_64BIT
+ depd,z %r23, 59, 60, %r21
+#else
+ depw,z %r23, 27, 28, %r21
+#endif
+ add %r26, %r21, %r22
+ cmpb,COND(>>),n %r22, %r25, 2f /* predict not taken */
+1: add %r22, %r21, %r22
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ cmpb,COND(<<=) %r22, %r25, 1b /* predict taken */
+ pdc,m %r23(%r26)
+
+2: cmpb,COND(>>),n %r25, %r26, 2b /* predict taken */
pdc,m %r23(%r26)
sync
+89: ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP)
syncdma
bv %r0(%r2)
nop
ENDPROC_CFI(purge_kernel_dcache_range_asm)
ENTRY_CFI(flush_user_icache_range_asm)
- ldil L%icache_stride, %r1
+88: ldil L%icache_stride, %r1
ldw R%icache_stride(%r1), %r23
ldo -1(%r23), %r21
ANDCM %r26, %r21, %r26
-1: cmpb,COND(<<),n %r26, %r25,1b
+#ifdef CONFIG_64BIT
+ depd,z %r23, 59, 60, %r21
+#else
+ depw,z %r23, 27, 28, %r21
+#endif
+ add %r26, %r21, %r22
+ cmpb,COND(>>),n %r22, %r25, 2f /* predict not taken */
+1: add %r22, %r21, %r22
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ cmpb,COND(<<=) %r22, %r25, 1b /* predict taken */
fic,m %r23(%sr3, %r26)
+2: cmpb,COND(>>),n %r25, %r26, 2b
+ fic,m %r23(%sr3, %r26)
+
+89: ALTERNATIVE(88b, 89b, ALT_COND_NO_ICACHE, INSN_NOP)
sync
bv %r0(%r2)
nop
ENDPROC_CFI(flush_user_icache_range_asm)
ENTRY_CFI(flush_kernel_icache_page)
- ldil L%icache_stride, %r1
+88: ldil L%icache_stride, %r1
ldw R%icache_stride(%r1), %r23
#ifdef CONFIG_64BIT
@@ -1076,23 +1214,51 @@
fic,m %r23(%sr4, %r26)
fic,m %r23(%sr4, %r26)
fic,m %r23(%sr4, %r26)
- cmpb,COND(<<) %r26, %r25, 1b
+ cmpb,COND(>>) %r25, %r26, 1b /* predict taken */
fic,m %r23(%sr4, %r26)
+89: ALTERNATIVE(88b, 89b, ALT_COND_NO_ICACHE, INSN_NOP)
sync
bv %r0(%r2)
nop
ENDPROC_CFI(flush_kernel_icache_page)
ENTRY_CFI(flush_kernel_icache_range_asm)
- ldil L%icache_stride, %r1
+88: ldil L%icache_stride, %r1
ldw R%icache_stride(%r1), %r23
ldo -1(%r23), %r21
ANDCM %r26, %r21, %r26
-1: cmpb,COND(<<),n %r26, %r25, 1b
+#ifdef CONFIG_64BIT
+ depd,z %r23, 59, 60, %r21
+#else
+ depw,z %r23, 27, 28, %r21
+#endif
+ add %r26, %r21, %r22
+ cmpb,COND(>>),n %r22, %r25, 2f /* predict not taken */
+1: add %r22, %r21, %r22
+ fic,m %r23(%sr4, %r26)
+ fic,m %r23(%sr4, %r26)
+ fic,m %r23(%sr4, %r26)
+ fic,m %r23(%sr4, %r26)
+ fic,m %r23(%sr4, %r26)
+ fic,m %r23(%sr4, %r26)
+ fic,m %r23(%sr4, %r26)
+ fic,m %r23(%sr4, %r26)
+ fic,m %r23(%sr4, %r26)
+ fic,m %r23(%sr4, %r26)
+ fic,m %r23(%sr4, %r26)
+ fic,m %r23(%sr4, %r26)
+ fic,m %r23(%sr4, %r26)
+ fic,m %r23(%sr4, %r26)
+ fic,m %r23(%sr4, %r26)
+ cmpb,COND(<<=) %r22, %r25, 1b /* predict taken */
fic,m %r23(%sr4, %r26)
+2: cmpb,COND(>>),n %r25, %r26, 2b /* predict taken */
+ fic,m %r23(%sr4, %r26)
+
+89: ALTERNATIVE(88b, 89b, ALT_COND_NO_ICACHE, INSN_NOP)
sync
bv %r0(%r2)
nop
diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c
index 7baa226..8ed409e 100644
--- a/arch/parisc/kernel/parisc_ksyms.c
+++ b/arch/parisc/kernel/parisc_ksyms.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Architecture-specific kernel symbols
*
@@ -8,20 +9,6 @@
* Copyright (C) 2002-2003 Matthew Wilcox <willy at parisc-linux.org>
* Copyright (C) 2002 Randolph Chung <tausq at parisc-linux.org>
* Copyright (C) 2002-2007 Helge Deller <deller with parisc-linux.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/module.h>
@@ -30,6 +17,10 @@
#include <linux/string.h>
EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(strcpy);
+EXPORT_SYMBOL(strncpy);
+EXPORT_SYMBOL(strcat);
#include <linux/atomic.h>
EXPORT_SYMBOL(__xchg8);
@@ -138,12 +129,6 @@
EXPORT_SYMBOL($$dyncall);
#endif
-#ifdef CONFIG_DISCONTIGMEM
-#include <asm/mmzone.h>
-EXPORT_SYMBOL(node_data);
-EXPORT_SYMBOL(pfnnid_map);
-#endif
-
#ifdef CONFIG_FUNCTION_TRACER
extern void _mcount(void);
EXPORT_SYMBOL(_mcount);
diff --git a/arch/parisc/kernel/patch.c b/arch/parisc/kernel/patch.c
new file mode 100644
index 0000000..80a0ab3
--- /dev/null
+++ b/arch/parisc/kernel/patch.c
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: GPL-2.0
+ /*
+ * functions to patch RO kernel text during runtime
+ *
+ * Copyright (c) 2019 Sven Schnelle <svens@stackframe.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/kprobes.h>
+#include <linux/mm.h>
+#include <linux/stop_machine.h>
+
+#include <asm/cacheflush.h>
+#include <asm/fixmap.h>
+#include <asm/patch.h>
+
+struct patch {
+ void *addr;
+ u32 *insn;
+ unsigned int len;
+};
+
+static DEFINE_RAW_SPINLOCK(patch_lock);
+
+static void __kprobes *patch_map(void *addr, int fixmap, unsigned long *flags,
+ int *need_unmap)
+{
+ unsigned long uintaddr = (uintptr_t) addr;
+ bool module = !core_kernel_text(uintaddr);
+ struct page *page;
+
+ *need_unmap = 0;
+ if (module && IS_ENABLED(CONFIG_STRICT_MODULE_RWX))
+ page = vmalloc_to_page(addr);
+ else if (!module && IS_ENABLED(CONFIG_STRICT_KERNEL_RWX))
+ page = virt_to_page(addr);
+ else
+ return addr;
+
+ *need_unmap = 1;
+ set_fixmap(fixmap, page_to_phys(page));
+ if (flags)
+ raw_spin_lock_irqsave(&patch_lock, *flags);
+ else
+ __acquire(&patch_lock);
+
+ return (void *) (__fix_to_virt(fixmap) + (uintaddr & ~PAGE_MASK));
+}
+
+static void __kprobes patch_unmap(int fixmap, unsigned long *flags)
+{
+ clear_fixmap(fixmap);
+
+ if (flags)
+ raw_spin_unlock_irqrestore(&patch_lock, *flags);
+ else
+ __release(&patch_lock);
+}
+
+void __kprobes __patch_text_multiple(void *addr, u32 *insn, unsigned int len)
+{
+ unsigned long start = (unsigned long)addr;
+ unsigned long end = (unsigned long)addr + len;
+ unsigned long flags;
+ u32 *p, *fixmap;
+ int mapped;
+
+ /* Make sure we don't have any aliases in cache */
+ flush_kernel_vmap_range(addr, len);
+ flush_icache_range(start, end);
+
+ p = fixmap = patch_map(addr, FIX_TEXT_POKE0, &flags, &mapped);
+
+ while (len >= 4) {
+ *p++ = *insn++;
+ addr += sizeof(u32);
+ len -= sizeof(u32);
+ if (len && offset_in_page(addr) == 0) {
+ /*
+ * We're crossing a page boundary, so
+ * need to remap
+ */
+ flush_kernel_vmap_range((void *)fixmap,
+ (p-fixmap) * sizeof(*p));
+ if (mapped)
+ patch_unmap(FIX_TEXT_POKE0, &flags);
+ p = fixmap = patch_map(addr, FIX_TEXT_POKE0, &flags,
+ &mapped);
+ }
+ }
+
+ flush_kernel_vmap_range((void *)fixmap, (p-fixmap) * sizeof(*p));
+ if (mapped)
+ patch_unmap(FIX_TEXT_POKE0, &flags);
+ flush_icache_range(start, end);
+}
+
+void __kprobes __patch_text(void *addr, u32 insn)
+{
+ __patch_text_multiple(addr, &insn, sizeof(insn));
+}
+
+static int __kprobes patch_text_stop_machine(void *data)
+{
+ struct patch *patch = data;
+
+ __patch_text_multiple(patch->addr, patch->insn, patch->len);
+ return 0;
+}
+
+void __kprobes patch_text(void *addr, unsigned int insn)
+{
+ struct patch patch = {
+ .addr = addr,
+ .insn = &insn,
+ .len = sizeof(insn),
+ };
+
+ stop_machine_cpuslocked(patch_text_stop_machine, &patch, NULL);
+}
+
+void __kprobes patch_text_multiple(void *addr, u32 *insn, unsigned int len)
+{
+
+ struct patch patch = {
+ .addr = addr,
+ .insn = insn,
+ .len = len
+ };
+
+ stop_machine_cpuslocked(patch_text_stop_machine, &patch, NULL);
+}
diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c
index 04c48f1..ca35d9a 100644
--- a/arch/parisc/kernel/pci-dma.c
+++ b/arch/parisc/kernel/pci-dma.c
@@ -394,17 +394,20 @@
__initcall(pcxl_dma_init);
-static void *pcxl_dma_alloc(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag, unsigned long attrs)
+void *arch_dma_alloc(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
{
unsigned long vaddr;
unsigned long paddr;
int order;
+ if (boot_cpu_data.cpu_type != pcxl2 && boot_cpu_data.cpu_type != pcxl)
+ return NULL;
+
order = get_order(size);
size = 1 << (order + PAGE_SHIFT);
vaddr = pcxl_alloc_range(size);
- paddr = __get_free_pages(flag, order);
+ paddr = __get_free_pages(gfp | __GFP_ZERO, order);
flush_kernel_dcache_range(paddr, size);
paddr = __pa(paddr);
map_uncached_pages(vaddr, size, paddr);
@@ -421,44 +424,19 @@
return (void *)vaddr;
}
-static void *pcx_dma_alloc(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag, unsigned long attrs)
-{
- void *addr;
-
- if ((attrs & DMA_ATTR_NON_CONSISTENT) == 0)
- return NULL;
-
- addr = (void *)__get_free_pages(flag, get_order(size));
- if (addr)
- *dma_handle = (dma_addr_t)virt_to_phys(addr);
-
- return addr;
-}
-
-void *arch_dma_alloc(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
-{
-
- if (boot_cpu_data.cpu_type == pcxl2 || boot_cpu_data.cpu_type == pcxl)
- return pcxl_dma_alloc(dev, size, dma_handle, gfp, attrs);
- else
- return pcx_dma_alloc(dev, size, dma_handle, gfp, attrs);
-}
-
void arch_dma_free(struct device *dev, size_t size, void *vaddr,
dma_addr_t dma_handle, unsigned long attrs)
{
int order = get_order(size);
- if (boot_cpu_data.cpu_type == pcxl2 || boot_cpu_data.cpu_type == pcxl) {
- size = 1 << (order + PAGE_SHIFT);
- unmap_uncached_pages((unsigned long)vaddr, size);
- pcxl_free_range((unsigned long)vaddr, size);
+ WARN_ON_ONCE(boot_cpu_data.cpu_type != pcxl2 &&
+ boot_cpu_data.cpu_type != pcxl);
- vaddr = __va(dma_handle);
- }
- free_pages((unsigned long)vaddr, get_order(size));
+ size = 1 << (order + PAGE_SHIFT);
+ unmap_uncached_pages((unsigned long)vaddr, size);
+ pcxl_free_range((unsigned long)vaddr, size);
+
+ free_pages((unsigned long)__va(dma_handle), order);
}
void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c
index ae684ac..cf285b1 100644
--- a/arch/parisc/kernel/pci.c
+++ b/arch/parisc/kernel/pci.c
@@ -34,25 +34,14 @@
#define DBG_RES(x...)
#endif
-/* To be used as: mdelay(pci_post_reset_delay);
- *
- * post_reset is the time the kernel should stall to prevent anyone from
- * accessing the PCI bus once #RESET is de-asserted.
- * PCI spec somewhere says 1 second but with multi-PCI bus systems,
- * this makes the boot time much longer than necessary.
- * 20ms seems to work for all the HP PCI implementations to date.
- *
- * #define pci_post_reset_delay 50
- */
+struct pci_port_ops *pci_port __ro_after_init;
+struct pci_bios_ops *pci_bios __ro_after_init;
-struct pci_port_ops *pci_port __read_mostly;
-struct pci_bios_ops *pci_bios __read_mostly;
-
-static int pci_hba_count __read_mostly;
+static int pci_hba_count __ro_after_init;
/* parisc_pci_hba used by pci_port->in/out() ops to lookup bus data. */
#define PCI_HBA_MAX 32
-static struct pci_hba_data *parisc_pci_hba[PCI_HBA_MAX] __read_mostly;
+static struct pci_hba_data *parisc_pci_hba[PCI_HBA_MAX] __ro_after_init;
/********************************************************************
diff --git a/arch/parisc/kernel/pdc_chassis.c b/arch/parisc/kernel/pdc_chassis.c
index 28e0748..75ae88d 100644
--- a/arch/parisc/kernel/pdc_chassis.c
+++ b/arch/parisc/kernel/pdc_chassis.c
@@ -1,22 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* interfaces to Chassis Codes via PDC (firmware)
*
* Copyright (C) 2002 Laurent Canet <canetl@esiee.fr>
* Copyright (C) 2002-2006 Thibaut VARENE <varenet@parisc-linux.org>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2, as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
* TODO: poll chassis warns, trigger (configurable) machine shutdown when
* needed.
* Find out how to get Chassis warnings out of PAT boxes?
diff --git a/arch/parisc/kernel/pdc_cons.c b/arch/parisc/kernel/pdc_cons.c
index c46bf29..7ed404c 100644
--- a/arch/parisc/kernel/pdc_cons.c
+++ b/arch/parisc/kernel/pdc_cons.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* PDC Console support - ie use firmware to dump text via boot console
*
@@ -13,21 +14,6 @@
* Copyright (C) 2001 Thomas Bogendoerfer <tsbogend at parisc-linux.org>
* Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
* Copyright (C) 2010 Guy Martin <gmsoft at tuxicoman.be>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
diff --git a/arch/parisc/kernel/perf.c b/arch/parisc/kernel/perf.c
index 0813359..6766836 100644
--- a/arch/parisc/kernel/perf.c
+++ b/arch/parisc/kernel/perf.c
@@ -1,22 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Parisc performance counters
* Copyright (C) 2001 Randolph Chung <tausq@debian.org>
*
* This code is derived, with permission, from HP/UX sources.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
diff --git a/arch/parisc/kernel/perf_asm.S b/arch/parisc/kernel/perf_asm.S
index fa6ea99..8fceabb 100644
--- a/arch/parisc/kernel/perf_asm.S
+++ b/arch/parisc/kernel/perf_asm.S
@@ -1,22 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/* low-level asm for "intrigue" (PA8500-8700 CPU perf counters)
*
* Copyright (C) 2001 Randolph Chung <tausq at parisc-linux.org>
* Copyright (C) 2001 Hewlett-Packard (Grant Grundler)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <asm/assembly.h>
diff --git a/arch/parisc/kernel/perf_images.h b/arch/parisc/kernel/perf_images.h
index 7fef964..7afa2fd 100644
--- a/arch/parisc/kernel/perf_images.h
+++ b/arch/parisc/kernel/perf_images.h
@@ -1,22 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Imagine for use with the Onyx (PCX-U) CPU interface
*
* Copyright (C) 2001 Randolph Chung <tausq at parisc-linux.org>
* Copyright (C) 2001 Hewlett-Packard (Grant Grundler)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef PERF_IMAGES_H
#define PERF_IMAGES_H
@@ -25,7 +12,7 @@
#define PCXU_IMAGE_SIZE 584
-static uint32_t onyx_images[][PCXU_IMAGE_SIZE/sizeof(uint32_t)] __read_mostly = {
+static uint32_t onyx_images[][PCXU_IMAGE_SIZE/sizeof(uint32_t)] __ro_after_init = {
/*
* CPI:
*
@@ -2093,7 +2080,7 @@
};
#define PCXW_IMAGE_SIZE 576
-static uint32_t cuda_images[][PCXW_IMAGE_SIZE/sizeof(uint32_t)] __read_mostly = {
+static uint32_t cuda_images[][PCXW_IMAGE_SIZE/sizeof(uint32_t)] __ro_after_init = {
/*
* CPI: FROM CPI.IDF (Image 0)
*
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
index eb39e7e..ecc5c27 100644
--- a/arch/parisc/kernel/process.c
+++ b/arch/parisc/kernel/process.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* PARISC Architecture-dependent parts of process handling
* based on the work for i386
@@ -15,21 +16,6 @@
* Copyright (C) 2001-2002 Ryan Bradetich <rbrad at parisc-linux.org>
* Copyright (C) 2001-2014 Helge Deller <deller@gmx.de>
* Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdarg.h>
@@ -192,7 +178,8 @@
* QEMU idle the host too.
*/
-int running_on_qemu __read_mostly;
+int running_on_qemu __ro_after_init;
+EXPORT_SYMBOL(running_on_qemu);
void __cpuidle arch_cpu_idle_dead(void)
{
@@ -210,12 +197,6 @@
static int __init parisc_idle_init(void)
{
- const char *marker;
-
- /* check QEMU/SeaBIOS marker in PAGE0 */
- marker = (char *) &PAGE0->pad0;
- running_on_qemu = (memcmp(marker, "SeaBIOS", 8) == 0);
-
if (!running_on_qemu)
cpu_idle_poll_ctrl(1);
diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c
index 82bd0d0..13f771f 100644
--- a/arch/parisc/kernel/processor.c
+++ b/arch/parisc/kernel/processor.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Initial setup-routines for HP 9000 based hardware.
*
@@ -9,21 +10,6 @@
* Modifications copyright 2001 Ryan Bradetich <rbradetich@uswest.net>
*
* Initial PA-RISC Version: 04-23-1999 by Helge Deller
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
*/
#include <linux/delay.h>
#include <linux/init.h>
@@ -43,10 +29,10 @@
#include <asm/irq.h> /* for struct irq_region */
#include <asm/parisc-device.h>
-struct system_cpuinfo_parisc boot_cpu_data __read_mostly;
+struct system_cpuinfo_parisc boot_cpu_data __ro_after_init;
EXPORT_SYMBOL(boot_cpu_data);
#ifdef CONFIG_PA8X00
-int _parisc_requires_coherency __read_mostly;
+int _parisc_requires_coherency __ro_after_init;
EXPORT_SYMBOL(_parisc_requires_coherency);
#endif
@@ -242,6 +228,7 @@
void __init collect_boot_cpu_data(void)
{
unsigned long cr16_seed;
+ char orig_prod_num[64], current_prod_num[64], serial_no[64];
memset(&boot_cpu_data, 0, sizeof(boot_cpu_data));
@@ -301,6 +288,15 @@
_parisc_requires_coherency = (boot_cpu_data.cpu_type == mako) ||
(boot_cpu_data.cpu_type == mako2);
#endif
+
+ if (pdc_model_platform_info(orig_prod_num, current_prod_num, serial_no) == PDC_OK) {
+ printk(KERN_INFO "product %s, original product %s, S/N: %s\n",
+ current_prod_num[0] ? current_prod_num : "n/a",
+ orig_prod_num, serial_no);
+ add_device_randomness(orig_prod_num, strlen(orig_prod_num));
+ add_device_randomness(current_prod_num, strlen(current_prod_num));
+ add_device_randomness(serial_no, strlen(serial_no));
+ }
}
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
index 2582df1..9f6ff7b 100644
--- a/arch/parisc/kernel/ptrace.c
+++ b/arch/parisc/kernel/ptrace.c
@@ -88,9 +88,9 @@
ptrace_disable(task);
/* Don't wake up the task, but let the
parent know something happened. */
- force_sig_fault(SIGTRAP, TRAP_TRACE,
- (void __user *) (task_regs(task)->iaoq[0] & ~3),
- task);
+ force_sig_fault_to_task(SIGTRAP, TRAP_TRACE,
+ (void __user *) (task_regs(task)->iaoq[0] & ~3),
+ task);
/* notify_parent(task, SIGCHLD); */
return;
}
@@ -167,6 +167,9 @@
if ((addr & (sizeof(unsigned long)-1)) ||
addr >= sizeof(struct pt_regs))
break;
+ if (addr == PT_IAOQ0 || addr == PT_IAOQ1) {
+ data |= 3; /* ensure userspace privilege */
+ }
if ((addr >= PT_GR1 && addr <= PT_GR31) ||
addr == PT_IAOQ0 || addr == PT_IAOQ1 ||
(addr >= PT_FR0 && addr <= PT_FR31 + 4) ||
@@ -228,16 +231,18 @@
static compat_ulong_t translate_usr_offset(compat_ulong_t offset)
{
- if (offset < 0)
- return sizeof(struct pt_regs);
- else if (offset <= 32*4) /* gr[0..31] */
- return offset * 2 + 4;
- else if (offset <= 32*4+32*8) /* gr[0..31] + fr[0..31] */
- return offset + 32*4;
- else if (offset < sizeof(struct pt_regs)/2 + 32*4)
- return offset * 2 + 4 - 32*8;
+ compat_ulong_t pos;
+
+ if (offset < 32*4) /* gr[0..31] */
+ pos = offset * 2 + 4;
+ else if (offset < 32*4+32*8) /* fr[0] ... fr[31] */
+ pos = (offset - 32*4) + PT_FR0;
+ else if (offset < sizeof(struct pt_regs)/2 + 32*4) /* sr[0] ... ipsw */
+ pos = (offset - 32*4 - 32*8) * 2 + PT_SR0 + 4;
else
- return sizeof(struct pt_regs);
+ pos = sizeof(struct pt_regs);
+
+ return pos;
}
long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
@@ -281,9 +286,12 @@
addr = translate_usr_offset(addr);
if (addr >= sizeof(struct pt_regs))
break;
+ if (addr == PT_IAOQ0+4 || addr == PT_IAOQ1+4) {
+ data |= 3; /* ensure userspace privilege */
+ }
if (addr >= PT_FR0 && addr <= PT_FR31 + 4) {
/* Special case, fp regs are 64 bits anyway */
- *(__u64 *) ((char *) task_regs(child) + addr) = data;
+ *(__u32 *) ((char *) task_regs(child) + addr) = data;
ret = 0;
}
else if ((addr >= PT_GR1+4 && addr <= PT_GR31+4) ||
@@ -308,15 +316,29 @@
long do_syscall_trace_enter(struct pt_regs *regs)
{
- if (test_thread_flag(TIF_SYSCALL_TRACE) &&
- tracehook_report_syscall_entry(regs)) {
+ if (test_thread_flag(TIF_SYSCALL_TRACE)) {
+ int rc = tracehook_report_syscall_entry(regs);
+
/*
- * Tracing decided this syscall should not happen or the
- * debugger stored an invalid system call number. Skip
- * the system call and the system call restart handling.
+ * As tracesys_next does not set %r28 to -ENOSYS
+ * when %r20 is set to -1, initialize it here.
*/
- regs->gr[20] = -1UL;
- goto out;
+ regs->gr[28] = -ENOSYS;
+
+ if (rc) {
+ /*
+ * A nonzero return code from
+ * tracehook_report_syscall_entry() tells us
+ * to prevent the syscall execution. Skip
+ * the syscall call and the syscall restart handling.
+ *
+ * Note that the tracer may also just change
+ * regs->gr[20] to an invalid syscall number,
+ * that is handled by tracesys_next.
+ */
+ regs->gr[20] = -1UL;
+ return -1;
+ }
}
/* Do the secure computing check after ptrace. */
@@ -340,7 +362,6 @@
regs->gr[24] & 0xffffffff,
regs->gr[23] & 0xffffffff);
-out:
/*
* Sign extend the syscall number to 64bit since it may have been
* modified by a compat ptrace call
@@ -483,7 +504,8 @@
return;
case RI(iaoq[0]):
case RI(iaoq[1]):
- regs->iaoq[num - RI(iaoq[0])] = val;
+ /* set 2 lowest bits to ensure userspace privilege: */
+ regs->iaoq[num - RI(iaoq[0])] = val | 3;
return;
case RI(sar): regs->sar = val;
return;
@@ -776,3 +798,38 @@
return roff->name;
return NULL;
}
+
+/**
+ * regs_within_kernel_stack() - check the address in the stack
+ * @regs: pt_regs which contains kernel stack pointer.
+ * @addr: address which is checked.
+ *
+ * regs_within_kernel_stack() checks @addr is within the kernel stack page(s).
+ * If @addr is within the kernel stack, it returns true. If not, returns false.
+ */
+int regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr)
+{
+ return ((addr & ~(THREAD_SIZE - 1)) ==
+ (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1)));
+}
+
+/**
+ * regs_get_kernel_stack_nth() - get Nth entry of the stack
+ * @regs: pt_regs which contains kernel stack pointer.
+ * @n: stack entry number.
+ *
+ * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
+ * is specified by @regs. If the @n th entry is NOT in the kernel stack,
+ * this returns 0.
+ */
+unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n)
+{
+ unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs);
+
+ addr -= n;
+
+ if (!regs_within_kernel_stack(regs, (unsigned long)addr))
+ return 0;
+
+ return *addr;
+}
diff --git a/arch/parisc/kernel/relocate_kernel.S b/arch/parisc/kernel/relocate_kernel.S
new file mode 100644
index 0000000..2561e52
--- /dev/null
+++ b/arch/parisc/kernel/relocate_kernel.S
@@ -0,0 +1,149 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#include <linux/linkage.h>
+#include <linux/kexec.h>
+
+#include <asm/assembly.h>
+#include <asm/asm-offsets.h>
+#include <asm/page.h>
+#include <asm/setup.h>
+#include <asm/psw.h>
+
+.level PA_ASM_LEVEL
+
+.macro kexec_param name
+.align 8
+ENTRY(kexec\()_\name)
+#ifdef CONFIG_64BIT
+ .dword 0
+#else
+ .word 0
+#endif
+
+ENTRY(kexec\()_\name\()_offset)
+ .word kexec\()_\name - relocate_new_kernel
+.endm
+
+.text
+
+/* args:
+ * r26 - kimage->head
+ * r25 - start address of kernel
+ * r24 - physical address of relocate code
+ */
+
+ENTRY_CFI(relocate_new_kernel)
+0: copy %arg1, %rp
+ /* disable I and Q bit, so we are allowed to execute RFI */
+ rsm PSW_SM_I, %r0
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ rsm PSW_SM_Q, %r0
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ /*
+ * After return-from-interrupt, we want to run without Code/Data
+ * translation enabled just like on a normal boot.
+ */
+
+ /* calculate new physical execution address */
+ ldo 1f-0b(%arg2), %r1
+ mtctl %r0, %cr17 /* IIASQ */
+ mtctl %r0, %cr17 /* IIASQ */
+ mtctl %r1, %cr18 /* IIAOQ */
+ ldo 4(%r1),%r1
+ mtctl %r1, %cr18 /* IIAOQ */
+#ifdef CONFIG_64BIT
+ depdi,z 1, PSW_W_BIT, 1, %r1
+ mtctl %r1, %cr22 /* IPSW */
+#else
+ mtctl %r0, %cr22 /* IPSW */
+#endif
+ /* lets go... */
+ rfi
+1: nop
+ nop
+
+.Lloop:
+ LDREG,ma REG_SZ(%arg0), %r3
+ /* If crash kernel, no copy needed */
+ cmpib,COND(=),n 0,%r3,boot
+
+ bb,<,n %r3, 31 - IND_DONE_BIT, boot
+ bb,>=,n %r3, 31 - IND_INDIRECTION_BIT, .Lnotind
+ /* indirection, load and restart */
+ movb %r3, %arg0, .Lloop
+ depi 0, 31, PAGE_SHIFT, %arg0
+
+.Lnotind:
+ bb,>=,n %r3, 31 - IND_DESTINATION_BIT, .Lnotdest
+ b .Lloop
+ copy %r3, %r20
+
+.Lnotdest:
+ bb,>= %r3, 31 - IND_SOURCE_BIT, .Lloop
+ depi 0, 31, PAGE_SHIFT, %r3
+ copy %r3, %r21
+
+ /* copy page */
+ copy %r0, %r18
+ zdepi 1, 31 - PAGE_SHIFT, 1, %r18
+ add %r20, %r18, %r17
+
+ depi 0, 31, PAGE_SHIFT, %r20
+.Lcopy:
+ copy %r20, %r12
+ LDREG,ma REG_SZ(%r21), %r8
+ LDREG,ma REG_SZ(%r21), %r9
+ LDREG,ma REG_SZ(%r21), %r10
+ LDREG,ma REG_SZ(%r21), %r11
+ STREG,ma %r8, REG_SZ(%r20)
+ STREG,ma %r9, REG_SZ(%r20)
+ STREG,ma %r10, REG_SZ(%r20)
+ STREG,ma %r11, REG_SZ(%r20)
+
+#ifndef CONFIG_64BIT
+ LDREG,ma REG_SZ(%r21), %r8
+ LDREG,ma REG_SZ(%r21), %r9
+ LDREG,ma REG_SZ(%r21), %r10
+ LDREG,ma REG_SZ(%r21), %r11
+ STREG,ma %r8, REG_SZ(%r20)
+ STREG,ma %r9, REG_SZ(%r20)
+ STREG,ma %r10, REG_SZ(%r20)
+ STREG,ma %r11, REG_SZ(%r20)
+#endif
+
+ fdc %r0(%r12)
+ cmpb,COND(<<) %r20,%r17,.Lcopy
+ fic (%sr4, %r12)
+ b,n .Lloop
+
+boot:
+ mtctl %r0, %cr15
+
+ LDREG kexec_free_mem-0b(%arg2), %arg0
+ LDREG kexec_cmdline-0b(%arg2), %arg1
+ LDREG kexec_initrd_end-0b(%arg2), %arg3
+ LDREG kexec_initrd_start-0b(%arg2), %arg2
+ bv,n %r0(%rp)
+
+ENDPROC_CFI(relocate_new_kernel);
+
+ENTRY(relocate_new_kernel_size)
+ .word relocate_new_kernel_size - relocate_new_kernel
+
+kexec_param cmdline
+kexec_param initrd_start
+kexec_param initrd_end
+kexec_param free_mem
diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c
index 4e87c35..53a21ce 100644
--- a/arch/parisc/kernel/setup.c
+++ b/arch/parisc/kernel/setup.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Initial setup-routines for HP 9000 based hardware.
*
@@ -9,21 +10,6 @@
* Modifications copyright 2001 Ryan Bradetich <rbradetich@uswest.net>
*
* Initial PA-RISC Version: 04-23-1999 by Helge Deller
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
*/
#include <linux/kernel.h>
@@ -40,6 +26,7 @@
#include <linux/sched/clock.h>
#include <linux/start_kernel.h>
+#include <asm/cacheflush.h>
#include <asm/processor.h>
#include <asm/sections.h>
#include <asm/pdc.h>
@@ -99,10 +86,6 @@
case pcxl2:
pa7300lc_init();
- case pcxl: /* falls through */
- case pcxs:
- case pcxt:
- hppa_dma_ops = &dma_noncoherent_ops;
break;
default:
break;
@@ -346,6 +329,13 @@
boot_cpu_data.cpu_hz / 1000000,
boot_cpu_data.cpu_hz % 1000000 );
+#if defined(CONFIG_64BIT) && defined(CONFIG_SMP)
+ /* Don't serialize TLB flushes if we run on one CPU only. */
+ if (num_online_cpus() == 1)
+ pa_serialize_tlb_flushes = 0;
+#endif
+
+ apply_alternatives_all();
parisc_setup_cache_timing();
/* These are in a non-obvious order, will fix when we have an iotree */
@@ -399,6 +389,9 @@
int ret, cpunum;
struct pdc_coproc_cfg coproc_cfg;
+ /* check QEMU/SeaBIOS marker in PAGE0 */
+ running_on_qemu = (memcmp(&PAGE0->pad0, "SeaBIOS", 8) == 0);
+
cpunum = smp_processor_id();
init_cpu_topology();
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c
index 342073f..02895a8 100644
--- a/arch/parisc/kernel/signal.c
+++ b/arch/parisc/kernel/signal.c
@@ -65,7 +65,6 @@
#define INSN_LDI_R25_1 0x34190002 /* ldi 1,%r25 (in_syscall=1) */
#define INSN_LDI_R20 0x3414015a /* ldi __NR_rt_sigreturn,%r20 */
#define INSN_BLE_SR2_R0 0xe4008200 /* be,l 0x100(%sr2,%r0),%sr0,%r31 */
-#define INSN_NOP 0x08000240 /* nop */
/* For debugging */
#define INSN_DIE_HORRIBLY 0x68000ccc /* stw %r0,0x666(%sr0,%r0) */
@@ -165,7 +164,7 @@
give_sigsegv:
DBG(1,"sys_rt_sigreturn: Sending SIGSEGV\n");
- force_sig(SIGSEGV, current);
+ force_sig(SIGSEGV);
return;
}
diff --git a/arch/parisc/kernel/signal32.c b/arch/parisc/kernel/signal32.c
index e8ef3eb..9a5ba57 100644
--- a/arch/parisc/kernel/signal32.c
+++ b/arch/parisc/kernel/signal32.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/* Signal support for 32-bit kernel builds
*
* Copyright (C) 2001 Matthew Wilcox <willy at parisc-linux.org>
@@ -5,21 +6,6 @@
*
* Code was mostly borrowed from kernel/signal.c.
* See kernel/signal.c for additional Copyrights.
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/compat.h>
diff --git a/arch/parisc/kernel/signal32.h b/arch/parisc/kernel/signal32.h
index a271dc0..f166250 100644
--- a/arch/parisc/kernel/signal32.h
+++ b/arch/parisc/kernel/signal32.h
@@ -1,20 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2001 Matthew Wilcox <willy at parisc-linux.org>
* Copyright (C) 2003 Carlos O'Donell <carlos at parisc-linux.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _PARISC64_KERNEL_SIGNAL32_H
#define _PARISC64_KERNEL_SIGNAL32_H
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
index 5e26dbe..e202c37 100644
--- a/arch/parisc/kernel/smp.c
+++ b/arch/parisc/kernel/smp.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
** SMP Support
**
@@ -11,10 +12,6 @@
** Thanks to John Curry and Ullas Ponnadi. I learned a lot from their work.
** -grant (1/12/2001)
**
-** This program is free software; you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation; either version 2 of the License, or
-** (at your option) any later version.
*/
#include <linux/types.h>
#include <linux/spinlock.h>
@@ -112,6 +109,7 @@
/* REVISIT : does PM *know* this CPU isn't available? */
set_cpu_online(smp_processor_id(), false);
local_irq_disable();
+ __pdc_cpu_rendezvous();
for (;;)
;
}
@@ -155,6 +153,7 @@
case IPI_CALL_FUNC:
smp_debug(100, KERN_DEBUG "CPU%d IPI_CALL_FUNC\n", this_cpu);
+ inc_irq_stat(irq_call_count);
generic_smp_call_function_interrupt();
break;
diff --git a/arch/parisc/kernel/stacktrace.c b/arch/parisc/kernel/stacktrace.c
index ec5835e..34bf6d6 100644
--- a/arch/parisc/kernel/stacktrace.c
+++ b/arch/parisc/kernel/stacktrace.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Stack trace management functions
*
@@ -29,22 +30,17 @@
}
}
-
/*
* Save stack-backtrace addresses into a stack_trace buffer.
*/
void save_stack_trace(struct stack_trace *trace)
{
dump_trace(current, trace);
- if (trace->nr_entries < trace->max_entries)
- trace->entries[trace->nr_entries++] = ULONG_MAX;
}
EXPORT_SYMBOL_GPL(save_stack_trace);
void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
{
dump_trace(tsk, trace);
- if (trace->nr_entries < trace->max_entries)
- trace->entries[trace->nr_entries++] = ULONG_MAX;
}
EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c
index 376ea0d..5d458a4 100644
--- a/arch/parisc/kernel/sys_parisc.c
+++ b/arch/parisc/kernel/sys_parisc.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* PARISC specific syscalls
@@ -6,21 +7,6 @@
* Copyright (C) 2000-2003 Paul Bame <bame at parisc-linux.org>
* Copyright (C) 2001 Thomas Bogendoerfer <tsbogend at parisc-linux.org>
* Copyright (C) 1999-2014 Helge Deller <deller@gmx.de>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/uaccess.h>
@@ -86,7 +72,8 @@
stack_base = STACK_SIZE_MAX;
/* Add space for stack randomization. */
- stack_base += (STACK_RND_MASK << PAGE_SHIFT);
+ if (current->flags & PF_RANDOMIZE)
+ stack_base += (STACK_RND_MASK << PAGE_SHIFT);
return PAGE_ALIGN(STACK_TOP - stack_base);
}
diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S
index f453997..97ac707 100644
--- a/arch/parisc/kernel/syscall.S
+++ b/arch/parisc/kernel/syscall.S
@@ -2,7 +2,7 @@
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
*
* System call entry code / Linux gateway page
- * Copyright (c) Matthew Wilcox 1999 <willy@bofh.ai>
+ * Copyright (c) Matthew Wilcox 1999 <willy@infradead.org>
* Licensed under the GNU GPL.
* thanks to Philipp Rumpf, Mike Shaver and various others
* sorry about the wall, puffin..
@@ -48,7 +48,7 @@
*/
#define KILL_INSN break 0,0
- .level LEVEL
+ .level PA_ASM_LEVEL
.text
@@ -640,7 +640,10 @@
sub,<> %r28, %r25, %r0
2: stw %r24, 0(%r26)
/* Free lock */
- sync
+#ifdef CONFIG_SMP
+98: LDCW 0(%sr2,%r20), %r1 /* Barrier */
+99: ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP)
+#endif
stw %r20, 0(%sr2,%r20)
#if ENABLE_LWS_DEBUG
/* Clear thread register indicator */
@@ -655,7 +658,10 @@
3:
/* Error occurred on load or store */
/* Free lock */
- sync
+#ifdef CONFIG_SMP
+98: LDCW 0(%sr2,%r20), %r1 /* Barrier */
+99: ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP)
+#endif
stw %r20, 0(%sr2,%r20)
#if ENABLE_LWS_DEBUG
stw %r0, 4(%sr2,%r20)
@@ -857,7 +863,10 @@
cas2_end:
/* Free lock */
- sync
+#ifdef CONFIG_SMP
+98: LDCW 0(%sr2,%r20), %r1 /* Barrier */
+99: ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP)
+#endif
stw %r20, 0(%sr2,%r20)
/* Enable interrupts */
ssm PSW_SM_I, %r0
@@ -868,7 +877,10 @@
22:
/* Error occurred on load or store */
/* Free lock */
- sync
+#ifdef CONFIG_SMP
+98: LDCW 0(%sr2,%r20), %r1 /* Barrier */
+99: ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP)
+#endif
stw %r20, 0(%sr2,%r20)
ssm PSW_SM_I, %r0
ldo 1(%r0),%r28
@@ -923,19 +935,24 @@
END(lws_table)
/* End of lws table */
+#define __SYSCALL(nr, entry, nargs) ASM_ULONG_INSN entry
.align 8
ENTRY(sys_call_table)
.export sys_call_table,data
-#include "syscall_table.S"
+#ifdef CONFIG_64BIT
+#include <asm/syscall_table_c32.h> /* Compat syscalls */
+#else
+#include <asm/syscall_table_32.h> /* 32-bit native syscalls */
+#endif
END(sys_call_table)
#ifdef CONFIG_64BIT
.align 8
ENTRY(sys_call_table64)
-#define SYSCALL_TABLE_64BIT
-#include "syscall_table.S"
+#include <asm/syscall_table_64.h> /* 64-bit native syscalls */
END(sys_call_table64)
#endif
+#undef __SYSCALL
/*
All light-weight-syscall atomic operations
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
deleted file mode 100644
index fe3f2a4..0000000
--- a/arch/parisc/kernel/syscall_table.S
+++ /dev/null
@@ -1,459 +0,0 @@
-/* System Call Table
- *
- * Copyright (C) 1999-2004 Matthew Wilcox <willy at parisc-linux.org>
- * Copyright (C) 2000-2001 John Marvin <jsm at parisc-linux.org>
- * Copyright (C) 2000 Alan Modra <amodra at parisc-linux.org>
- * Copyright (C) 2000-2003 Paul Bame <bame at parisc-linux.org>
- * Copyright (C) 2000 Philipp Rumpf <prumpf with tux.org>
- * Copyright (C) 2000 Michael Ang <mang with subcarrier.org>
- * Copyright (C) 2000 David Huggins-Daines <dhd with pobox.org>
- * Copyright (C) 2000 Grant Grundler <grundler at parisc-linux.org>
- * Copyright (C) 2001 Richard Hirst <rhirst with parisc-linux.org>
- * Copyright (C) 2001-2002 Ryan Bradetich <rbrad at parisc-linux.org>
- * Copyright (C) 2001-2007 Helge Deller <deller at parisc-linux.org>
- * Copyright (C) 2000-2001 Thomas Bogendoerfer <tsbogend at parisc-linux.org>
- * Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
- * Copyright (C) 2005-2006 Kyle McMartin <kyle at parisc-linux.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#if defined(CONFIG_64BIT) && !defined(SYSCALL_TABLE_64BIT)
-/* Use ENTRY_SAME for 32-bit syscalls which are the same on wide and
- * narrow palinux. Use ENTRY_DIFF for those where a 32-bit specific
- * implementation is required on wide palinux. Use ENTRY_COMP where
- * the compatibility layer has a useful 32-bit implementation.
- */
-#define ENTRY_SAME(_name_) .dword sys_##_name_
-#define ENTRY_DIFF(_name_) .dword sys32_##_name_
-#define ENTRY_UHOH(_name_) .dword sys32_##unimplemented
-#define ENTRY_OURS(_name_) .dword parisc_##_name_
-#define ENTRY_COMP(_name_) .dword compat_sys_##_name_
-#elif defined(CONFIG_64BIT) && defined(SYSCALL_TABLE_64BIT)
-#define ENTRY_SAME(_name_) .dword sys_##_name_
-#define ENTRY_DIFF(_name_) .dword sys_##_name_
-#define ENTRY_UHOH(_name_) .dword sys_##_name_
-#define ENTRY_OURS(_name_) .dword sys_##_name_
-#define ENTRY_COMP(_name_) .dword sys_##_name_
-#else
-#define ENTRY_SAME(_name_) .word sys_##_name_
-#define ENTRY_DIFF(_name_) .word sys_##_name_
-#define ENTRY_UHOH(_name_) .word sys_##_name_
-#define ENTRY_OURS(_name_) .word parisc_##_name_
-#define ENTRY_COMP(_name_) .word sys_##_name_
-#endif
-
-90: ENTRY_SAME(restart_syscall) /* 0 */
-91: ENTRY_SAME(exit)
- ENTRY_SAME(fork_wrapper)
- ENTRY_SAME(read)
- ENTRY_SAME(write)
- ENTRY_COMP(open) /* 5 */
- ENTRY_SAME(close)
- ENTRY_SAME(waitpid)
- ENTRY_SAME(creat)
- ENTRY_SAME(link)
- ENTRY_SAME(unlink) /* 10 */
- ENTRY_COMP(execve)
- ENTRY_SAME(chdir)
- /* See comments in kernel/time.c!!! Maybe we don't need this? */
- ENTRY_COMP(time)
- ENTRY_SAME(mknod)
- ENTRY_SAME(chmod) /* 15 */
- ENTRY_SAME(lchown)
- ENTRY_SAME(socket)
- /* struct stat is MAYBE identical wide and narrow ?? */
- ENTRY_COMP(newstat)
- ENTRY_COMP(lseek)
- ENTRY_SAME(getpid) /* 20 */
- /* the 'void * data' parameter may need re-packing in wide */
- ENTRY_COMP(mount)
- /* concerned about struct sockaddr in wide/narrow */
- /* ---> I think sockaddr is OK unless the compiler packs the struct */
- /* differently to align the char array */
- ENTRY_SAME(bind)
- ENTRY_SAME(setuid)
- ENTRY_SAME(getuid)
- ENTRY_COMP(stime) /* 25 */
- ENTRY_COMP(ptrace)
- ENTRY_SAME(alarm)
- /* see stat comment */
- ENTRY_COMP(newfstat)
- ENTRY_SAME(pause)
- /* struct utimbuf uses time_t which might vary */
- ENTRY_COMP(utime) /* 30 */
- /* struct sockaddr... */
- ENTRY_SAME(connect)
- ENTRY_SAME(listen)
- ENTRY_SAME(access)
- ENTRY_SAME(nice)
- /* struct sockaddr... */
- ENTRY_SAME(accept) /* 35 */
- ENTRY_SAME(sync)
- ENTRY_SAME(kill)
- ENTRY_SAME(rename)
- ENTRY_SAME(mkdir)
- ENTRY_SAME(rmdir) /* 40 */
- ENTRY_SAME(dup)
- ENTRY_SAME(pipe)
- ENTRY_COMP(times)
- /* struct sockaddr... */
- ENTRY_SAME(getsockname)
- /* it seems possible brk() could return a >4G pointer... */
- ENTRY_SAME(brk) /* 45 */
- ENTRY_SAME(setgid)
- ENTRY_SAME(getgid)
- ENTRY_SAME(signal)
- ENTRY_SAME(geteuid)
- ENTRY_SAME(getegid) /* 50 */
- ENTRY_SAME(acct)
- ENTRY_SAME(umount)
- /* struct sockaddr... */
- ENTRY_SAME(getpeername)
- ENTRY_COMP(ioctl)
- ENTRY_COMP(fcntl) /* 55 */
- ENTRY_SAME(socketpair)
- ENTRY_SAME(setpgid)
- ENTRY_SAME(send)
- ENTRY_SAME(newuname)
- ENTRY_SAME(umask) /* 60 */
- ENTRY_SAME(chroot)
- ENTRY_COMP(ustat)
- ENTRY_SAME(dup2)
- ENTRY_SAME(getppid)
- ENTRY_SAME(getpgrp) /* 65 */
- ENTRY_SAME(setsid)
- ENTRY_SAME(pivot_root)
- /* I don't like this */
- ENTRY_UHOH(sgetmask)
- ENTRY_UHOH(ssetmask)
- ENTRY_SAME(setreuid) /* 70 */
- ENTRY_SAME(setregid)
- ENTRY_SAME(mincore)
- ENTRY_COMP(sigpending)
- ENTRY_SAME(sethostname)
- /* Following 3 have linux-common-code structs containing longs -( */
- ENTRY_COMP(setrlimit) /* 75 */
- ENTRY_COMP(getrlimit)
- ENTRY_COMP(getrusage)
- /* struct timeval and timezone are maybe?? consistent wide and narrow */
- ENTRY_COMP(gettimeofday)
- ENTRY_COMP(settimeofday)
- ENTRY_SAME(getgroups) /* 80 */
- ENTRY_SAME(setgroups)
- /* struct socketaddr... */
- ENTRY_SAME(sendto)
- ENTRY_SAME(symlink)
- /* see stat comment */
- ENTRY_COMP(newlstat)
- ENTRY_SAME(readlink) /* 85 */
- ENTRY_SAME(ni_syscall) /* was uselib */
- ENTRY_SAME(swapon)
- ENTRY_SAME(reboot)
- ENTRY_SAME(mmap2)
- ENTRY_SAME(mmap) /* 90 */
- ENTRY_SAME(munmap)
- ENTRY_COMP(truncate)
- ENTRY_COMP(ftruncate)
- ENTRY_SAME(fchmod)
- ENTRY_SAME(fchown) /* 95 */
- ENTRY_SAME(getpriority)
- ENTRY_SAME(setpriority)
- ENTRY_SAME(recv)
- ENTRY_COMP(statfs)
- ENTRY_COMP(fstatfs) /* 100 */
- ENTRY_SAME(stat64)
- ENTRY_SAME(ni_syscall) /* was socketcall */
- ENTRY_SAME(syslog)
- /* even though manpage says struct timeval contains longs, ours has
- * time_t and suseconds_t -- both of which are safe wide/narrow */
- ENTRY_COMP(setitimer)
- ENTRY_COMP(getitimer) /* 105 */
- ENTRY_SAME(capget)
- ENTRY_SAME(capset)
- ENTRY_OURS(pread64)
- ENTRY_OURS(pwrite64)
- ENTRY_SAME(getcwd) /* 110 */
- ENTRY_SAME(vhangup)
- ENTRY_SAME(fstat64)
- ENTRY_SAME(vfork_wrapper)
- /* struct rusage contains longs... */
- ENTRY_COMP(wait4)
- ENTRY_SAME(swapoff) /* 115 */
- ENTRY_COMP(sysinfo)
- ENTRY_SAME(shutdown)
- ENTRY_SAME(fsync)
- ENTRY_SAME(madvise)
- ENTRY_SAME(clone_wrapper) /* 120 */
- ENTRY_SAME(setdomainname)
- ENTRY_COMP(sendfile)
- /* struct sockaddr... */
- ENTRY_SAME(recvfrom)
- /* struct timex contains longs */
- ENTRY_COMP(adjtimex)
- ENTRY_SAME(mprotect) /* 125 */
- /* old_sigset_t forced to 32 bits. Beware glibc sigset_t */
- ENTRY_COMP(sigprocmask)
- ENTRY_SAME(ni_syscall) /* create_module */
- ENTRY_SAME(init_module)
- ENTRY_SAME(delete_module)
- ENTRY_SAME(ni_syscall) /* 130: get_kernel_syms */
- /* time_t inside struct dqblk */
- ENTRY_SAME(quotactl)
- ENTRY_SAME(getpgid)
- ENTRY_SAME(fchdir)
- ENTRY_SAME(bdflush)
- ENTRY_SAME(sysfs) /* 135 */
- ENTRY_OURS(personality)
- ENTRY_SAME(ni_syscall) /* for afs_syscall */
- ENTRY_SAME(setfsuid)
- ENTRY_SAME(setfsgid)
- /* I think this might work */
- ENTRY_SAME(llseek) /* 140 */
- ENTRY_COMP(getdents)
- /* it is POSSIBLE that select will be OK because even though fd_set
- * contains longs, the macros and sizes are clever. */
- ENTRY_COMP(select)
- ENTRY_SAME(flock)
- ENTRY_SAME(msync)
- /* struct iovec contains pointers */
- ENTRY_COMP(readv) /* 145 */
- ENTRY_COMP(writev)
- ENTRY_SAME(getsid)
- ENTRY_SAME(fdatasync)
- /* struct __sysctl_args is a mess */
- ENTRY_COMP(sysctl)
- ENTRY_SAME(mlock) /* 150 */
- ENTRY_SAME(munlock)
- ENTRY_SAME(mlockall)
- ENTRY_SAME(munlockall)
- /* struct sched_param is ok for now */
- ENTRY_SAME(sched_setparam)
- ENTRY_SAME(sched_getparam) /* 155 */
- ENTRY_SAME(sched_setscheduler)
- ENTRY_SAME(sched_getscheduler)
- ENTRY_SAME(sched_yield)
- ENTRY_SAME(sched_get_priority_max)
- ENTRY_SAME(sched_get_priority_min) /* 160 */
- ENTRY_COMP(sched_rr_get_interval)
- ENTRY_COMP(nanosleep)
- ENTRY_SAME(mremap)
- ENTRY_SAME(setresuid)
- ENTRY_SAME(getresuid) /* 165 */
- ENTRY_COMP(sigaltstack)
- ENTRY_SAME(ni_syscall) /* query_module */
- ENTRY_SAME(poll)
- /* structs contain pointers and an in_addr... */
- ENTRY_SAME(ni_syscall) /* was nfsservctl */
- ENTRY_SAME(setresgid) /* 170 */
- ENTRY_SAME(getresgid)
- ENTRY_SAME(prctl)
- /* signals need a careful review */
- ENTRY_SAME(rt_sigreturn_wrapper)
- ENTRY_COMP(rt_sigaction)
- ENTRY_COMP(rt_sigprocmask) /* 175 */
- ENTRY_COMP(rt_sigpending)
- ENTRY_COMP(rt_sigtimedwait)
- /* even though the struct siginfo_t is different, it appears like
- * all the paths use values which should be same wide and narrow.
- * Also the struct is padded to 128 bytes which means we don't have
- * to worry about faulting trying to copy in a larger 64-bit
- * struct from a 32-bit user-space app.
- */
- ENTRY_COMP(rt_sigqueueinfo)
- ENTRY_COMP(rt_sigsuspend)
- ENTRY_SAME(chown) /* 180 */
- /* setsockopt() used by iptables: SO_SET_REPLACE/SO_SET_ADD_COUNTERS */
- ENTRY_COMP(setsockopt)
- ENTRY_COMP(getsockopt)
- ENTRY_COMP(sendmsg)
- ENTRY_COMP(recvmsg)
- ENTRY_SAME(semop) /* 185 */
- ENTRY_SAME(semget)
- ENTRY_COMP(semctl)
- ENTRY_COMP(msgsnd)
- ENTRY_COMP(msgrcv)
- ENTRY_SAME(msgget) /* 190 */
- ENTRY_COMP(msgctl)
- ENTRY_COMP(shmat)
- ENTRY_SAME(shmdt)
- ENTRY_SAME(shmget)
- ENTRY_COMP(shmctl) /* 195 */
- ENTRY_SAME(ni_syscall) /* streams1 */
- ENTRY_SAME(ni_syscall) /* streams2 */
- ENTRY_SAME(lstat64)
- ENTRY_OURS(truncate64)
- ENTRY_OURS(ftruncate64) /* 200 */
- ENTRY_SAME(getdents64)
- ENTRY_COMP(fcntl64)
- ENTRY_SAME(ni_syscall) /* attrctl -- dead */
- ENTRY_SAME(ni_syscall) /* acl_get -- dead */
- ENTRY_SAME(ni_syscall) /* 205 (acl_set -- dead) */
- ENTRY_SAME(gettid)
- ENTRY_OURS(readahead)
- ENTRY_SAME(tkill)
- ENTRY_COMP(sendfile64)
- ENTRY_COMP(futex) /* 210 */
- ENTRY_COMP(sched_setaffinity)
- ENTRY_COMP(sched_getaffinity)
- ENTRY_SAME(ni_syscall) /* set_thread_area */
- ENTRY_SAME(ni_syscall) /* get_thread_area */
- ENTRY_COMP(io_setup) /* 215 */
- ENTRY_SAME(io_destroy)
- ENTRY_COMP(io_getevents)
- ENTRY_COMP(io_submit)
- ENTRY_SAME(io_cancel)
- ENTRY_SAME(ni_syscall) /* 220: was alloc_hugepages */
- ENTRY_SAME(ni_syscall) /* was free_hugepages */
- ENTRY_SAME(exit_group)
- ENTRY_COMP(lookup_dcookie)
- ENTRY_SAME(epoll_create)
- ENTRY_SAME(epoll_ctl) /* 225 */
- ENTRY_SAME(epoll_wait)
- ENTRY_SAME(remap_file_pages)
- ENTRY_COMP(semtimedop)
- ENTRY_COMP(mq_open)
- ENTRY_SAME(mq_unlink) /* 230 */
- ENTRY_COMP(mq_timedsend)
- ENTRY_COMP(mq_timedreceive)
- ENTRY_COMP(mq_notify)
- ENTRY_COMP(mq_getsetattr)
- ENTRY_COMP(waitid) /* 235 */
- ENTRY_OURS(fadvise64_64)
- ENTRY_SAME(set_tid_address)
- ENTRY_SAME(setxattr)
- ENTRY_SAME(lsetxattr)
- ENTRY_SAME(fsetxattr) /* 240 */
- ENTRY_SAME(getxattr)
- ENTRY_SAME(lgetxattr)
- ENTRY_SAME(fgetxattr)
- ENTRY_SAME(listxattr)
- ENTRY_SAME(llistxattr) /* 245 */
- ENTRY_SAME(flistxattr)
- ENTRY_SAME(removexattr)
- ENTRY_SAME(lremovexattr)
- ENTRY_SAME(fremovexattr)
- ENTRY_COMP(timer_create) /* 250 */
- ENTRY_COMP(timer_settime)
- ENTRY_COMP(timer_gettime)
- ENTRY_SAME(timer_getoverrun)
- ENTRY_SAME(timer_delete)
- ENTRY_COMP(clock_settime) /* 255 */
- ENTRY_COMP(clock_gettime)
- ENTRY_COMP(clock_getres)
- ENTRY_COMP(clock_nanosleep)
- ENTRY_SAME(tgkill)
- ENTRY_COMP(mbind) /* 260 */
- ENTRY_COMP(get_mempolicy)
- ENTRY_COMP(set_mempolicy)
- ENTRY_SAME(ni_syscall) /* 263: reserved for vserver */
- ENTRY_SAME(add_key)
- ENTRY_SAME(request_key) /* 265 */
- ENTRY_COMP(keyctl)
- ENTRY_SAME(ioprio_set)
- ENTRY_SAME(ioprio_get)
- ENTRY_SAME(inotify_init)
- ENTRY_SAME(inotify_add_watch) /* 270 */
- ENTRY_SAME(inotify_rm_watch)
- ENTRY_SAME(migrate_pages)
- ENTRY_COMP(pselect6)
- ENTRY_COMP(ppoll)
- ENTRY_COMP(openat) /* 275 */
- ENTRY_SAME(mkdirat)
- ENTRY_SAME(mknodat)
- ENTRY_SAME(fchownat)
- ENTRY_COMP(futimesat)
- ENTRY_SAME(fstatat64) /* 280 */
- ENTRY_SAME(unlinkat)
- ENTRY_SAME(renameat)
- ENTRY_SAME(linkat)
- ENTRY_SAME(symlinkat)
- ENTRY_SAME(readlinkat) /* 285 */
- ENTRY_SAME(fchmodat)
- ENTRY_SAME(faccessat)
- ENTRY_SAME(unshare)
- ENTRY_COMP(set_robust_list)
- ENTRY_COMP(get_robust_list) /* 290 */
- ENTRY_SAME(splice)
- ENTRY_OURS(sync_file_range)
- ENTRY_SAME(tee)
- ENTRY_COMP(vmsplice)
- ENTRY_COMP(move_pages) /* 295 */
- ENTRY_SAME(getcpu)
- ENTRY_COMP(epoll_pwait)
- ENTRY_COMP(statfs64)
- ENTRY_COMP(fstatfs64)
- ENTRY_COMP(kexec_load) /* 300 */
- ENTRY_COMP(utimensat)
- ENTRY_COMP(signalfd)
- ENTRY_SAME(ni_syscall) /* was timerfd */
- ENTRY_SAME(eventfd)
- ENTRY_OURS(fallocate) /* 305 */
- ENTRY_SAME(timerfd_create)
- ENTRY_COMP(timerfd_settime)
- ENTRY_COMP(timerfd_gettime)
- ENTRY_COMP(signalfd4)
- ENTRY_SAME(eventfd2) /* 310 */
- ENTRY_SAME(epoll_create1)
- ENTRY_SAME(dup3)
- ENTRY_SAME(pipe2)
- ENTRY_SAME(inotify_init1)
- ENTRY_COMP(preadv) /* 315 */
- ENTRY_COMP(pwritev)
- ENTRY_COMP(rt_tgsigqueueinfo)
- ENTRY_SAME(perf_event_open)
- ENTRY_COMP(recvmmsg)
- ENTRY_SAME(accept4) /* 320 */
- ENTRY_SAME(prlimit64)
- ENTRY_SAME(fanotify_init)
- ENTRY_DIFF(fanotify_mark)
- ENTRY_COMP(clock_adjtime)
- ENTRY_SAME(name_to_handle_at) /* 325 */
- ENTRY_COMP(open_by_handle_at)
- ENTRY_SAME(syncfs)
- ENTRY_SAME(setns)
- ENTRY_COMP(sendmmsg)
- ENTRY_COMP(process_vm_readv) /* 330 */
- ENTRY_COMP(process_vm_writev)
- ENTRY_SAME(kcmp)
- ENTRY_SAME(finit_module)
- ENTRY_SAME(sched_setattr)
- ENTRY_SAME(sched_getattr) /* 335 */
- ENTRY_COMP(utimes)
- ENTRY_SAME(renameat2)
- ENTRY_SAME(seccomp)
- ENTRY_SAME(getrandom)
- ENTRY_SAME(memfd_create) /* 340 */
- ENTRY_SAME(bpf)
- ENTRY_COMP(execveat)
- ENTRY_SAME(membarrier)
- ENTRY_SAME(userfaultfd)
- ENTRY_SAME(mlock2) /* 345 */
- ENTRY_SAME(copy_file_range)
- ENTRY_COMP(preadv2)
- ENTRY_COMP(pwritev2)
- ENTRY_SAME(statx)
- ENTRY_COMP(io_pgetevents) /* 350 */
-
-
-.ifne (. - 90b) - (__NR_Linux_syscalls * (91b - 90b))
-.error "size of syscall table does not fit value of __NR_Linux_syscalls"
-.endif
-
-#undef ENTRY_SAME
-#undef ENTRY_DIFF
-#undef ENTRY_UHOH
-#undef ENTRY_COMP
-#undef ENTRY_OURS
diff --git a/arch/parisc/kernel/syscalls/Makefile b/arch/parisc/kernel/syscalls/Makefile
new file mode 100644
index 0000000..c22a21c
--- /dev/null
+++ b/arch/parisc/kernel/syscalls/Makefile
@@ -0,0 +1,55 @@
+# SPDX-License-Identifier: GPL-2.0
+kapi := arch/$(SRCARCH)/include/generated/asm
+uapi := arch/$(SRCARCH)/include/generated/uapi/asm
+
+_dummy := $(shell [ -d '$(uapi)' ] || mkdir -p '$(uapi)') \
+ $(shell [ -d '$(kapi)' ] || mkdir -p '$(kapi)')
+
+syscall := $(srctree)/$(src)/syscall.tbl
+syshdr := $(srctree)/$(src)/syscallhdr.sh
+systbl := $(srctree)/$(src)/syscalltbl.sh
+
+quiet_cmd_syshdr = SYSHDR $@
+ cmd_syshdr = $(CONFIG_SHELL) '$(syshdr)' '$<' '$@' \
+ '$(syshdr_abis_$(basetarget))' \
+ '$(syshdr_pfx_$(basetarget))' \
+ '$(syshdr_offset_$(basetarget))'
+
+quiet_cmd_systbl = SYSTBL $@
+ cmd_systbl = $(CONFIG_SHELL) '$(systbl)' '$<' '$@' \
+ '$(systbl_abis_$(basetarget))' \
+ '$(systbl_abi_$(basetarget))' \
+ '$(systbl_offset_$(basetarget))'
+
+syshdr_abis_unistd_32 := common,32
+$(uapi)/unistd_32.h: $(syscall) $(syshdr)
+ $(call if_changed,syshdr)
+
+syshdr_abis_unistd_64 := common,64
+$(uapi)/unistd_64.h: $(syscall) $(syshdr)
+ $(call if_changed,syshdr)
+
+systbl_abis_syscall_table_32 := common,32
+$(kapi)/syscall_table_32.h: $(syscall) $(systbl)
+ $(call if_changed,systbl)
+
+systbl_abis_syscall_table_64 := common,64
+$(kapi)/syscall_table_64.h: $(syscall) $(systbl)
+ $(call if_changed,systbl)
+
+systbl_abis_syscall_table_c32 := common,32
+systbl_abi_syscall_table_c32 := c32
+$(kapi)/syscall_table_c32.h: $(syscall) $(systbl)
+ $(call if_changed,systbl)
+
+uapisyshdr-y += unistd_32.h unistd_64.h
+kapisyshdr-y += syscall_table_32.h \
+ syscall_table_64.h \
+ syscall_table_c32.h
+
+targets += $(uapisyshdr-y) $(kapisyshdr-y)
+
+PHONY += all
+all: $(addprefix $(uapi)/,$(uapisyshdr-y))
+all: $(addprefix $(kapi)/,$(kapisyshdr-y))
+ @:
diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/syscalls/syscall.tbl
new file mode 100644
index 0000000..285ff51
--- /dev/null
+++ b/arch/parisc/kernel/syscalls/syscall.tbl
@@ -0,0 +1,435 @@
+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
+#
+# system call numbers and entry vectors for parisc
+#
+# The format is:
+# <number> <abi> <name> <entry point> <compat entry point>
+#
+# The <abi> can be common, 64, or 32 for this file.
+#
+0 common restart_syscall sys_restart_syscall
+1 common exit sys_exit
+2 common fork sys_fork_wrapper
+3 common read sys_read
+4 common write sys_write
+5 common open sys_open compat_sys_open
+6 common close sys_close
+7 common waitpid sys_waitpid
+8 common creat sys_creat
+9 common link sys_link
+10 common unlink sys_unlink
+11 common execve sys_execve compat_sys_execve
+12 common chdir sys_chdir
+13 32 time sys_time32
+13 64 time sys_time
+14 common mknod sys_mknod
+15 common chmod sys_chmod
+16 common lchown sys_lchown
+17 common socket sys_socket
+18 common stat sys_newstat compat_sys_newstat
+19 common lseek sys_lseek compat_sys_lseek
+20 common getpid sys_getpid
+21 common mount sys_mount compat_sys_mount
+22 common bind sys_bind
+23 common setuid sys_setuid
+24 common getuid sys_getuid
+25 32 stime sys_stime32
+25 64 stime sys_stime
+26 common ptrace sys_ptrace compat_sys_ptrace
+27 common alarm sys_alarm
+28 common fstat sys_newfstat compat_sys_newfstat
+29 common pause sys_pause
+30 32 utime sys_utime32
+30 64 utime sys_utime
+31 common connect sys_connect
+32 common listen sys_listen
+33 common access sys_access
+34 common nice sys_nice
+35 common accept sys_accept
+36 common sync sys_sync
+37 common kill sys_kill
+38 common rename sys_rename
+39 common mkdir sys_mkdir
+40 common rmdir sys_rmdir
+41 common dup sys_dup
+42 common pipe sys_pipe
+43 common times sys_times compat_sys_times
+44 common getsockname sys_getsockname
+45 common brk sys_brk
+46 common setgid sys_setgid
+47 common getgid sys_getgid
+48 common signal sys_signal
+49 common geteuid sys_geteuid
+50 common getegid sys_getegid
+51 common acct sys_acct
+52 common umount2 sys_umount
+53 common getpeername sys_getpeername
+54 common ioctl sys_ioctl compat_sys_ioctl
+55 common fcntl sys_fcntl compat_sys_fcntl
+56 common socketpair sys_socketpair
+57 common setpgid sys_setpgid
+58 common send sys_send
+59 common uname sys_newuname
+60 common umask sys_umask
+61 common chroot sys_chroot
+62 common ustat sys_ustat compat_sys_ustat
+63 common dup2 sys_dup2
+64 common getppid sys_getppid
+65 common getpgrp sys_getpgrp
+66 common setsid sys_setsid
+67 common pivot_root sys_pivot_root
+68 common sgetmask sys_sgetmask sys32_unimplemented
+69 common ssetmask sys_ssetmask sys32_unimplemented
+70 common setreuid sys_setreuid
+71 common setregid sys_setregid
+72 common mincore sys_mincore
+73 common sigpending sys_sigpending compat_sys_sigpending
+74 common sethostname sys_sethostname
+75 common setrlimit sys_setrlimit compat_sys_setrlimit
+76 common getrlimit sys_getrlimit compat_sys_getrlimit
+77 common getrusage sys_getrusage compat_sys_getrusage
+78 common gettimeofday sys_gettimeofday compat_sys_gettimeofday
+79 common settimeofday sys_settimeofday compat_sys_settimeofday
+80 common getgroups sys_getgroups
+81 common setgroups sys_setgroups
+82 common sendto sys_sendto
+83 common symlink sys_symlink
+84 common lstat sys_newlstat compat_sys_newlstat
+85 common readlink sys_readlink
+86 common uselib sys_ni_syscall
+87 common swapon sys_swapon
+88 common reboot sys_reboot
+89 common mmap2 sys_mmap2
+90 common mmap sys_mmap
+91 common munmap sys_munmap
+92 common truncate sys_truncate compat_sys_truncate
+93 common ftruncate sys_ftruncate compat_sys_ftruncate
+94 common fchmod sys_fchmod
+95 common fchown sys_fchown
+96 common getpriority sys_getpriority
+97 common setpriority sys_setpriority
+98 common recv sys_recv
+99 common statfs sys_statfs compat_sys_statfs
+100 common fstatfs sys_fstatfs compat_sys_fstatfs
+101 common stat64 sys_stat64
+# 102 was socketcall
+103 common syslog sys_syslog
+104 common setitimer sys_setitimer compat_sys_setitimer
+105 common getitimer sys_getitimer compat_sys_getitimer
+106 common capget sys_capget
+107 common capset sys_capset
+108 32 pread64 parisc_pread64
+108 64 pread64 sys_pread64
+109 32 pwrite64 parisc_pwrite64
+109 64 pwrite64 sys_pwrite64
+110 common getcwd sys_getcwd
+111 common vhangup sys_vhangup
+112 common fstat64 sys_fstat64
+113 common vfork sys_vfork_wrapper
+114 common wait4 sys_wait4 compat_sys_wait4
+115 common swapoff sys_swapoff
+116 common sysinfo sys_sysinfo compat_sys_sysinfo
+117 common shutdown sys_shutdown
+118 common fsync sys_fsync
+119 common madvise sys_madvise
+120 common clone sys_clone_wrapper
+121 common setdomainname sys_setdomainname
+122 common sendfile sys_sendfile compat_sys_sendfile
+123 common recvfrom sys_recvfrom
+124 32 adjtimex sys_adjtimex_time32
+124 64 adjtimex sys_adjtimex
+125 common mprotect sys_mprotect
+126 common sigprocmask sys_sigprocmask compat_sys_sigprocmask
+# 127 was create_module
+128 common init_module sys_init_module
+129 common delete_module sys_delete_module
+# 130 was get_kernel_syms
+131 common quotactl sys_quotactl
+132 common getpgid sys_getpgid
+133 common fchdir sys_fchdir
+134 common bdflush sys_bdflush
+135 common sysfs sys_sysfs
+136 32 personality parisc_personality
+136 64 personality sys_personality
+# 137 was afs_syscall
+138 common setfsuid sys_setfsuid
+139 common setfsgid sys_setfsgid
+140 common _llseek sys_llseek
+141 common getdents sys_getdents compat_sys_getdents
+142 common _newselect sys_select compat_sys_select
+143 common flock sys_flock
+144 common msync sys_msync
+145 common readv sys_readv compat_sys_readv
+146 common writev sys_writev compat_sys_writev
+147 common getsid sys_getsid
+148 common fdatasync sys_fdatasync
+149 common _sysctl sys_sysctl compat_sys_sysctl
+150 common mlock sys_mlock
+151 common munlock sys_munlock
+152 common mlockall sys_mlockall
+153 common munlockall sys_munlockall
+154 common sched_setparam sys_sched_setparam
+155 common sched_getparam sys_sched_getparam
+156 common sched_setscheduler sys_sched_setscheduler
+157 common sched_getscheduler sys_sched_getscheduler
+158 common sched_yield sys_sched_yield
+159 common sched_get_priority_max sys_sched_get_priority_max
+160 common sched_get_priority_min sys_sched_get_priority_min
+161 32 sched_rr_get_interval sys_sched_rr_get_interval_time32
+161 64 sched_rr_get_interval sys_sched_rr_get_interval
+162 32 nanosleep sys_nanosleep_time32
+162 64 nanosleep sys_nanosleep
+163 common mremap sys_mremap
+164 common setresuid sys_setresuid
+165 common getresuid sys_getresuid
+166 common sigaltstack sys_sigaltstack compat_sys_sigaltstack
+# 167 was query_module
+168 common poll sys_poll
+# 169 was nfsservctl
+170 common setresgid sys_setresgid
+171 common getresgid sys_getresgid
+172 common prctl sys_prctl
+173 common rt_sigreturn sys_rt_sigreturn_wrapper
+174 common rt_sigaction sys_rt_sigaction compat_sys_rt_sigaction
+175 common rt_sigprocmask sys_rt_sigprocmask compat_sys_rt_sigprocmask
+176 common rt_sigpending sys_rt_sigpending compat_sys_rt_sigpending
+177 32 rt_sigtimedwait sys_rt_sigtimedwait_time32 compat_sys_rt_sigtimedwait_time32
+177 64 rt_sigtimedwait sys_rt_sigtimedwait
+178 common rt_sigqueueinfo sys_rt_sigqueueinfo compat_sys_rt_sigqueueinfo
+179 common rt_sigsuspend sys_rt_sigsuspend compat_sys_rt_sigsuspend
+180 common chown sys_chown
+181 common setsockopt sys_setsockopt compat_sys_setsockopt
+182 common getsockopt sys_getsockopt compat_sys_getsockopt
+183 common sendmsg sys_sendmsg compat_sys_sendmsg
+184 common recvmsg sys_recvmsg compat_sys_recvmsg
+185 common semop sys_semop
+186 common semget sys_semget
+187 common semctl sys_semctl compat_sys_semctl
+188 common msgsnd sys_msgsnd compat_sys_msgsnd
+189 common msgrcv sys_msgrcv compat_sys_msgrcv
+190 common msgget sys_msgget
+191 common msgctl sys_msgctl compat_sys_msgctl
+192 common shmat sys_shmat compat_sys_shmat
+193 common shmdt sys_shmdt
+194 common shmget sys_shmget
+195 common shmctl sys_shmctl compat_sys_shmctl
+# 196 was getpmsg
+# 197 was putpmsg
+198 common lstat64 sys_lstat64
+199 32 truncate64 parisc_truncate64
+199 64 truncate64 sys_truncate64
+200 32 ftruncate64 parisc_ftruncate64
+200 64 ftruncate64 sys_ftruncate64
+201 common getdents64 sys_getdents64
+202 common fcntl64 sys_fcntl64 compat_sys_fcntl64
+# 203 was attrctl
+# 204 was acl_get
+# 205 was acl_set
+206 common gettid sys_gettid
+207 32 readahead parisc_readahead
+207 64 readahead sys_readahead
+208 common tkill sys_tkill
+209 common sendfile64 sys_sendfile64 compat_sys_sendfile64
+210 32 futex sys_futex_time32
+210 64 futex sys_futex
+211 common sched_setaffinity sys_sched_setaffinity compat_sys_sched_setaffinity
+212 common sched_getaffinity sys_sched_getaffinity compat_sys_sched_getaffinity
+# 213 was set_thread_area
+# 214 was get_thread_area
+215 common io_setup sys_io_setup compat_sys_io_setup
+216 common io_destroy sys_io_destroy
+217 32 io_getevents sys_io_getevents_time32
+217 64 io_getevents sys_io_getevents
+218 common io_submit sys_io_submit compat_sys_io_submit
+219 common io_cancel sys_io_cancel
+# 220 was alloc_hugepages
+# 221 was free_hugepages
+222 common exit_group sys_exit_group
+223 common lookup_dcookie sys_lookup_dcookie compat_sys_lookup_dcookie
+224 common epoll_create sys_epoll_create
+225 common epoll_ctl sys_epoll_ctl
+226 common epoll_wait sys_epoll_wait
+227 common remap_file_pages sys_remap_file_pages
+228 32 semtimedop sys_semtimedop_time32
+228 64 semtimedop sys_semtimedop
+229 common mq_open sys_mq_open compat_sys_mq_open
+230 common mq_unlink sys_mq_unlink
+231 32 mq_timedsend sys_mq_timedsend_time32
+231 64 mq_timedsend sys_mq_timedsend
+232 32 mq_timedreceive sys_mq_timedreceive_time32
+232 64 mq_timedreceive sys_mq_timedreceive
+233 common mq_notify sys_mq_notify compat_sys_mq_notify
+234 common mq_getsetattr sys_mq_getsetattr compat_sys_mq_getsetattr
+235 common waitid sys_waitid compat_sys_waitid
+236 32 fadvise64_64 parisc_fadvise64_64
+236 64 fadvise64_64 sys_fadvise64_64
+237 common set_tid_address sys_set_tid_address
+238 common setxattr sys_setxattr
+239 common lsetxattr sys_lsetxattr
+240 common fsetxattr sys_fsetxattr
+241 common getxattr sys_getxattr
+242 common lgetxattr sys_lgetxattr
+243 common fgetxattr sys_fgetxattr
+244 common listxattr sys_listxattr
+245 common llistxattr sys_llistxattr
+246 common flistxattr sys_flistxattr
+247 common removexattr sys_removexattr
+248 common lremovexattr sys_lremovexattr
+249 common fremovexattr sys_fremovexattr
+250 common timer_create sys_timer_create compat_sys_timer_create
+251 32 timer_settime sys_timer_settime32
+251 64 timer_settime sys_timer_settime
+252 32 timer_gettime sys_timer_gettime32
+252 64 timer_gettime sys_timer_gettime
+253 common timer_getoverrun sys_timer_getoverrun
+254 common timer_delete sys_timer_delete
+255 32 clock_settime sys_clock_settime32
+255 64 clock_settime sys_clock_settime
+256 32 clock_gettime sys_clock_gettime32
+256 64 clock_gettime sys_clock_gettime
+257 32 clock_getres sys_clock_getres_time32
+257 64 clock_getres sys_clock_getres
+258 32 clock_nanosleep sys_clock_nanosleep_time32
+258 64 clock_nanosleep sys_clock_nanosleep
+259 common tgkill sys_tgkill
+260 common mbind sys_mbind compat_sys_mbind
+261 common get_mempolicy sys_get_mempolicy compat_sys_get_mempolicy
+262 common set_mempolicy sys_set_mempolicy compat_sys_set_mempolicy
+# 263 was vserver
+264 common add_key sys_add_key
+265 common request_key sys_request_key
+266 common keyctl sys_keyctl compat_sys_keyctl
+267 common ioprio_set sys_ioprio_set
+268 common ioprio_get sys_ioprio_get
+269 common inotify_init sys_inotify_init
+270 common inotify_add_watch sys_inotify_add_watch
+271 common inotify_rm_watch sys_inotify_rm_watch
+272 common migrate_pages sys_migrate_pages
+273 32 pselect6 sys_pselect6_time32 compat_sys_pselect6_time32
+273 64 pselect6 sys_pselect6
+274 32 ppoll sys_ppoll_time32 compat_sys_ppoll_time32
+274 64 ppoll sys_ppoll
+275 common openat sys_openat compat_sys_openat
+276 common mkdirat sys_mkdirat
+277 common mknodat sys_mknodat
+278 common fchownat sys_fchownat
+279 32 futimesat sys_futimesat_time32
+279 64 futimesat sys_futimesat
+280 common fstatat64 sys_fstatat64
+281 common unlinkat sys_unlinkat
+282 common renameat sys_renameat
+283 common linkat sys_linkat
+284 common symlinkat sys_symlinkat
+285 common readlinkat sys_readlinkat
+286 common fchmodat sys_fchmodat
+287 common faccessat sys_faccessat
+288 common unshare sys_unshare
+289 common set_robust_list sys_set_robust_list compat_sys_set_robust_list
+290 common get_robust_list sys_get_robust_list compat_sys_get_robust_list
+291 common splice sys_splice
+292 32 sync_file_range parisc_sync_file_range
+292 64 sync_file_range sys_sync_file_range
+293 common tee sys_tee
+294 common vmsplice sys_vmsplice compat_sys_vmsplice
+295 common move_pages sys_move_pages compat_sys_move_pages
+296 common getcpu sys_getcpu
+297 common epoll_pwait sys_epoll_pwait compat_sys_epoll_pwait
+298 common statfs64 sys_statfs64 compat_sys_statfs64
+299 common fstatfs64 sys_fstatfs64 compat_sys_fstatfs64
+300 common kexec_load sys_kexec_load compat_sys_kexec_load
+301 32 utimensat sys_utimensat_time32
+301 64 utimensat sys_utimensat
+302 common signalfd sys_signalfd compat_sys_signalfd
+# 303 was timerfd
+304 common eventfd sys_eventfd
+305 32 fallocate parisc_fallocate
+305 64 fallocate sys_fallocate
+306 common timerfd_create sys_timerfd_create
+307 32 timerfd_settime sys_timerfd_settime32
+307 64 timerfd_settime sys_timerfd_settime
+308 32 timerfd_gettime sys_timerfd_gettime32
+308 64 timerfd_gettime sys_timerfd_gettime
+309 common signalfd4 sys_signalfd4 compat_sys_signalfd4
+310 common eventfd2 sys_eventfd2
+311 common epoll_create1 sys_epoll_create1
+312 common dup3 sys_dup3
+313 common pipe2 sys_pipe2
+314 common inotify_init1 sys_inotify_init1
+315 common preadv sys_preadv compat_sys_preadv
+316 common pwritev sys_pwritev compat_sys_pwritev
+317 common rt_tgsigqueueinfo sys_rt_tgsigqueueinfo compat_sys_rt_tgsigqueueinfo
+318 common perf_event_open sys_perf_event_open
+319 32 recvmmsg sys_recvmmsg_time32 compat_sys_recvmmsg_time32
+319 64 recvmmsg sys_recvmmsg
+320 common accept4 sys_accept4
+321 common prlimit64 sys_prlimit64
+322 common fanotify_init sys_fanotify_init
+323 common fanotify_mark sys_fanotify_mark sys32_fanotify_mark
+324 32 clock_adjtime sys_clock_adjtime32
+324 64 clock_adjtime sys_clock_adjtime
+325 common name_to_handle_at sys_name_to_handle_at
+326 common open_by_handle_at sys_open_by_handle_at compat_sys_open_by_handle_at
+327 common syncfs sys_syncfs
+328 common setns sys_setns
+329 common sendmmsg sys_sendmmsg compat_sys_sendmmsg
+330 common process_vm_readv sys_process_vm_readv compat_sys_process_vm_readv
+331 common process_vm_writev sys_process_vm_writev compat_sys_process_vm_writev
+332 common kcmp sys_kcmp
+333 common finit_module sys_finit_module
+334 common sched_setattr sys_sched_setattr
+335 common sched_getattr sys_sched_getattr
+336 32 utimes sys_utimes_time32
+336 64 utimes sys_utimes
+337 common renameat2 sys_renameat2
+338 common seccomp sys_seccomp
+339 common getrandom sys_getrandom
+340 common memfd_create sys_memfd_create
+341 common bpf sys_bpf
+342 common execveat sys_execveat compat_sys_execveat
+343 common membarrier sys_membarrier
+344 common userfaultfd sys_userfaultfd
+345 common mlock2 sys_mlock2
+346 common copy_file_range sys_copy_file_range
+347 common preadv2 sys_preadv2 compat_sys_preadv2
+348 common pwritev2 sys_pwritev2 compat_sys_pwritev2
+349 common statx sys_statx
+350 32 io_pgetevents sys_io_pgetevents_time32 compat_sys_io_pgetevents
+350 64 io_pgetevents sys_io_pgetevents
+351 common pkey_mprotect sys_pkey_mprotect
+352 common pkey_alloc sys_pkey_alloc
+353 common pkey_free sys_pkey_free
+354 common rseq sys_rseq
+355 common kexec_file_load sys_kexec_file_load sys_kexec_file_load
+# up to 402 is unassigned and reserved for arch specific syscalls
+403 32 clock_gettime64 sys_clock_gettime sys_clock_gettime
+404 32 clock_settime64 sys_clock_settime sys_clock_settime
+405 32 clock_adjtime64 sys_clock_adjtime sys_clock_adjtime
+406 32 clock_getres_time64 sys_clock_getres sys_clock_getres
+407 32 clock_nanosleep_time64 sys_clock_nanosleep sys_clock_nanosleep
+408 32 timer_gettime64 sys_timer_gettime sys_timer_gettime
+409 32 timer_settime64 sys_timer_settime sys_timer_settime
+410 32 timerfd_gettime64 sys_timerfd_gettime sys_timerfd_gettime
+411 32 timerfd_settime64 sys_timerfd_settime sys_timerfd_settime
+412 32 utimensat_time64 sys_utimensat sys_utimensat
+413 32 pselect6_time64 sys_pselect6 compat_sys_pselect6_time64
+414 32 ppoll_time64 sys_ppoll compat_sys_ppoll_time64
+416 32 io_pgetevents_time64 sys_io_pgetevents sys_io_pgetevents
+417 32 recvmmsg_time64 sys_recvmmsg compat_sys_recvmmsg_time64
+418 32 mq_timedsend_time64 sys_mq_timedsend sys_mq_timedsend
+419 32 mq_timedreceive_time64 sys_mq_timedreceive sys_mq_timedreceive
+420 32 semtimedop_time64 sys_semtimedop sys_semtimedop
+421 32 rt_sigtimedwait_time64 sys_rt_sigtimedwait compat_sys_rt_sigtimedwait_time64
+422 32 futex_time64 sys_futex sys_futex
+423 32 sched_rr_get_interval_time64 sys_sched_rr_get_interval sys_sched_rr_get_interval
+424 common pidfd_send_signal sys_pidfd_send_signal
+425 common io_uring_setup sys_io_uring_setup
+426 common io_uring_enter sys_io_uring_enter
+427 common io_uring_register sys_io_uring_register
+428 common open_tree sys_open_tree
+429 common move_mount sys_move_mount
+430 common fsopen sys_fsopen
+431 common fsconfig sys_fsconfig
+432 common fsmount sys_fsmount
+433 common fspick sys_fspick
+434 common pidfd_open sys_pidfd_open
+435 common clone3 sys_clone3_wrapper
diff --git a/arch/parisc/kernel/syscalls/syscallhdr.sh b/arch/parisc/kernel/syscalls/syscallhdr.sh
new file mode 100644
index 0000000..50242b7
--- /dev/null
+++ b/arch/parisc/kernel/syscalls/syscallhdr.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+
+in="$1"
+out="$2"
+my_abis=`echo "($3)" | tr ',' '|'`
+prefix="$4"
+offset="$5"
+
+fileguard=_UAPI_ASM_PARISC_`basename "$out" | sed \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \
+ -e 's/[^A-Z0-9_]/_/g' -e 's/__/_/g'`
+grep -E "^[0-9A-Fa-fXx]+[[:space:]]+${my_abis}" "$in" | sort -n | (
+ printf "#ifndef %s\n" "${fileguard}"
+ printf "#define %s\n" "${fileguard}"
+ printf "\n"
+
+ nxt=0
+ while read nr abi name entry compat ; do
+ if [ -z "$offset" ]; then
+ printf "#define __NR_%s%s\t%s\n" \
+ "${prefix}" "${name}" "${nr}"
+ else
+ printf "#define __NR_%s%s\t(%s + %s)\n" \
+ "${prefix}" "${name}" "${offset}" "${nr}"
+ fi
+ nxt=$((nr+1))
+ done
+
+ printf "\n"
+ printf "#ifdef __KERNEL__\n"
+ printf "#define __NR_syscalls\t%s\n" "${nxt}"
+ printf "#endif\n"
+ printf "\n"
+ printf "#endif /* %s */" "${fileguard}"
+) > "$out"
diff --git a/arch/parisc/kernel/syscalls/syscalltbl.sh b/arch/parisc/kernel/syscalls/syscalltbl.sh
new file mode 100644
index 0000000..45b5bae
--- /dev/null
+++ b/arch/parisc/kernel/syscalls/syscalltbl.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+
+in="$1"
+out="$2"
+my_abis=`echo "($3)" | tr ',' '|'`
+my_abi="$4"
+offset="$5"
+
+emit() {
+ t_nxt="$1"
+ t_nr="$2"
+ t_entry="$3"
+
+ while [ $t_nxt -lt $t_nr ]; do
+ printf "__SYSCALL(%s, sys_ni_syscall, )\n" "${t_nxt}"
+ t_nxt=$((t_nxt+1))
+ done
+ printf "__SYSCALL(%s, %s, )\n" "${t_nxt}" "${t_entry}"
+}
+
+grep -E "^[0-9A-Fa-fXx]+[[:space:]]+${my_abis}" "$in" | sort -n | (
+ nxt=0
+ if [ -z "$offset" ]; then
+ offset=0
+ fi
+
+ while read nr abi name entry compat ; do
+ if [ "$my_abi" = "c32" ] && [ ! -z "$compat" ]; then
+ emit $((nxt+offset)) $((nr+offset)) $compat
+ else
+ emit $((nxt+offset)) $((nr+offset)) $entry
+ fi
+ nxt=$((nr+1))
+ done
+) > "$out"
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
index a1e772f..0450815 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -40,7 +40,7 @@
#include <linux/timex.h>
-static unsigned long clocktick __read_mostly; /* timer cycles per tick */
+static unsigned long clocktick __ro_after_init; /* timer cycles per tick */
/*
* We keep time on PA-RISC Linux by using the Interval Timer which is
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
index abeb532..82fc011 100644
--- a/arch/parisc/kernel/traps.c
+++ b/arch/parisc/kernel/traps.c
@@ -29,6 +29,7 @@
#include <linux/bug.h>
#include <linux/ratelimit.h>
#include <linux/uaccess.h>
+#include <linux/kdebug.h>
#include <asm/assembly.h>
#include <asm/io.h>
@@ -42,6 +43,8 @@
#include <asm/unwind.h>
#include <asm/tlbflush.h>
#include <asm/cacheflush.h>
+#include <linux/kgdb.h>
+#include <linux/kprobes.h>
#include "../math-emu/math-emu.h" /* for handle_fpe() */
@@ -218,7 +221,7 @@
return;
}
- oops_in_progress = 1;
+ bust_spinlocks(1);
oops_enter();
@@ -273,7 +276,7 @@
static void handle_gdb_break(struct pt_regs *regs, int wot)
{
force_sig_fault(SIGTRAP, wot,
- (void __user *) (regs->iaoq[0] & ~3), current);
+ (void __user *) (regs->iaoq[0] & ~3));
}
static void handle_break(struct pt_regs *regs)
@@ -293,6 +296,22 @@
(tt == BUG_TRAP_TYPE_NONE) ? 9 : 0);
}
+#ifdef CONFIG_KPROBES
+ if (unlikely(iir == PARISC_KPROBES_BREAK_INSN)) {
+ parisc_kprobe_break_handler(regs);
+ return;
+ }
+
+#endif
+
+#ifdef CONFIG_KGDB
+ if (unlikely(iir == PARISC_KGDB_COMPILED_BREAK_INSN ||
+ iir == PARISC_KGDB_BREAK_INSN)) {
+ kgdb_handle_exception(9, SIGTRAP, 0, regs);
+ return;
+ }
+#endif
+
if (unlikely(iir != GDB_BREAK_INSN))
parisc_printk_ratelimited(0, regs,
KERN_DEBUG "break %d,%d: pid=%d command='%s'\n",
@@ -396,7 +415,8 @@
{
static DEFINE_SPINLOCK(terminate_lock);
- oops_in_progress = 1;
+ (void)notify_die(DIE_OOPS, msg, regs, 0, code, SIGTRAP);
+ bust_spinlocks(1);
set_eiem(0);
local_irq_disable();
@@ -430,8 +450,8 @@
}
printk("\n");
- pr_crit("%s: Code=%d (%s) regs=%p (Addr=" RFMT ")\n",
- msg, code, trap_name(code), regs, offset);
+ pr_crit("%s: Code=%d (%s) at addr " RFMT "\n",
+ msg, code, trap_name(code), offset);
show_regs(regs);
spin_unlock(&terminate_lock);
@@ -518,6 +538,19 @@
case 3:
/* Recovery counter trap */
regs->gr[0] &= ~PSW_R;
+
+#ifdef CONFIG_KPROBES
+ if (parisc_kprobe_ss_handler(regs))
+ return;
+#endif
+
+#ifdef CONFIG_KGDB
+ if (kgdb_single_step) {
+ kgdb_handle_exception(0, SIGTRAP, 0, regs);
+ return;
+ }
+#endif
+
if (user_space(regs))
handle_gdb_break(regs, TRAP_TRACE);
/* else this must be the start of a syscall - just let it run */
@@ -578,13 +611,13 @@
si_code = ILL_PRVREG;
give_sigill:
force_sig_fault(SIGILL, si_code,
- (void __user *) regs->iaoq[0], current);
+ (void __user *) regs->iaoq[0]);
return;
case 12:
/* Overflow Trap, let the userland signal handler do the cleanup */
force_sig_fault(SIGFPE, FPE_INTOVF,
- (void __user *) regs->iaoq[0], current);
+ (void __user *) regs->iaoq[0]);
return;
case 13:
@@ -596,7 +629,7 @@
* to by si_addr.
*/
force_sig_fault(SIGFPE, FPE_CONDTRAP,
- (void __user *) regs->iaoq[0], current);
+ (void __user *) regs->iaoq[0]);
return;
}
/* The kernel doesn't want to handle condition codes */
@@ -708,7 +741,7 @@
force_sig_fault(SIGSEGV, SEGV_MAPERR,
(code == 7)?
((void __user *) regs->iaoq[0]) :
- ((void __user *) regs->ior), current);
+ ((void __user *) regs->ior));
return;
case 28:
@@ -723,7 +756,7 @@
task_pid_nr(current), current->comm);
/* SIGBUS, for lack of a better one. */
force_sig_fault(SIGBUS, BUS_OBJERR,
- (void __user *)regs->ior, current);
+ (void __user *)regs->ior);
return;
}
pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC);
@@ -739,7 +772,7 @@
code, fault_space,
task_pid_nr(current), current->comm);
force_sig_fault(SIGSEGV, SEGV_MAPERR,
- (void __user *)regs->ior, current);
+ (void __user *)regs->ior);
return;
}
}
diff --git a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c
index 932bfc0..237d20d 100644
--- a/arch/parisc/kernel/unaligned.c
+++ b/arch/parisc/kernel/unaligned.c
@@ -1,23 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Unaligned memory access handler
*
* Copyright (C) 2001 Randolph Chung <tausq@debian.org>
* Significantly tweaked by LaMont Jones <lamont@debian.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
*/
#include <linux/jiffies.h>
@@ -690,14 +676,14 @@
if (ret == ERR_PAGEFAULT)
{
force_sig_fault(SIGSEGV, SEGV_MAPERR,
- (void __user *)regs->ior, current);
+ (void __user *)regs->ior);
}
else
{
force_sigbus:
/* couldn't handle it ... */
force_sig_fault(SIGBUS, BUS_ADRALN,
- (void __user *)regs->ior, current);
+ (void __user *)regs->ior);
}
return;
diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c
index 2d14f17..87ae476 100644
--- a/arch/parisc/kernel/unwind.c
+++ b/arch/parisc/kernel/unwind.c
@@ -40,7 +40,7 @@
* we can call unwind_init as early in the bootup process as
* possible (before the slab allocator is initialized)
*/
-static struct unwind_table kernel_unwind_table __read_mostly;
+static struct unwind_table kernel_unwind_table __ro_after_init;
static LIST_HEAD(unwind_tables);
static inline const struct unwind_table_entry *
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index da2e311..99cd24f 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -18,6 +18,8 @@
*(.data..vm0.pgd) \
*(.data..vm0.pte)
+#define CC_USING_PATCHABLE_FUNCTION_ENTRY
+
#include <asm-generic/vmlinux.lds.h>
/* needed for the processor specific cache alignment size */
@@ -35,6 +37,15 @@
OUTPUT_ARCH(hppa:hppa2.0w)
#endif
+#define EXIT_TEXT_SECTIONS() .exit.text : { EXIT_TEXT }
+#if !defined(CONFIG_64BIT) || defined(CONFIG_MLONGCALLS)
+#define MLONGCALL_KEEP(x)
+#define MLONGCALL_DISCARD(x) x
+#else
+#define MLONGCALL_KEEP(x) x
+#define MLONGCALL_DISCARD(x)
+#endif
+
ENTRY(parisc_kernel_start)
#ifndef CONFIG_64BIT
jiffies = jiffies_64 + 4;
@@ -47,31 +58,34 @@
__init_begin = .;
HEAD_TEXT_SECTION
- INIT_TEXT_SECTION(8)
+ MLONGCALL_DISCARD(INIT_TEXT_SECTION(8))
. = ALIGN(PAGE_SIZE);
INIT_DATA_SECTION(PAGE_SIZE)
- /* we have to discard exit text and such at runtime, not link time */
- .exit.text :
- {
- EXIT_TEXT
- }
+ MLONGCALL_DISCARD(EXIT_TEXT_SECTIONS())
.exit.data :
{
EXIT_DATA
}
PERCPU_SECTION(8)
+ . = ALIGN(4);
+ .altinstructions : {
+ __alt_instructions = .;
+ *(.altinstructions)
+ __alt_instructions_end = .;
+ }
. = ALIGN(HUGEPAGE_SIZE);
__init_end = .;
/* freed after init ends here */
_text = .; /* Text and read-only data */
_stext = .;
+ MLONGCALL_KEEP(INIT_TEXT_SECTION(8))
.text ALIGN(PAGE_SIZE) : {
TEXT_TEXT
+ LOCK_TEXT
SCHED_TEXT
CPUIDLE_TEXT
- LOCK_TEXT
KPROBES_TEXT
IRQENTRY_TEXT
SOFTIRQENTRY_TEXT
@@ -86,6 +100,7 @@
*(.lock.text) /* out-of-line lock text */
*(.gnu.warning)
}
+ MLONGCALL_KEEP(EXIT_TEXT_SECTIONS())
. = ALIGN(PAGE_SIZE);
_etext = .;
/* End of text section */