Commit cd4175b1 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'parisc-4.14-2' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux

Pull parisc fixes from Helge Deller:

 - Unbreak parisc bootloader by avoiding a gcc-7 optimization to convert
   multiple byte-accesses into one word-access.

 - Add missing HWPOISON page fault handler code. I completely missed
   that when I added HWPOISON support during this merge window and it
   only showed up now with the madvise07 LTP test case.

 - Fix backtrace unwinding to stop when stack start has been reached.

 - Issue warning if initrd has been loaded into memory regions with
   broken RAM modules.

 - Fix HPMC handler (parisc hardware fault handler) to comply with
   architecture specification.

 - Avoid compiler warnings about too large frame sizes.

 - Minor init-section fixes.

* 'parisc-4.14-2' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux:
  parisc: Unbreak bootloader due to gcc-7 optimizations
  parisc: Reintroduce option to gzip-compress the kernel
  parisc: Add HWPOISON page fault handler code
  parisc: Move init_per_cpu() into init section
  parisc: Check if initrd was loaded into broken RAM
  parisc: Add PDCE_CHECK instruction to HPMC handler
  parisc: Add wrapper for pdc_instr() firmware function
  parisc: Move start_parisc() into init section
  parisc: Stop unwinding at start of stack
  parisc: Fix too large frame size warnings
parents ded85032 8c031ba6
......@@ -257,6 +257,18 @@ config PARISC_PAGE_SIZE_64KB
endchoice
config PARISC_SELF_EXTRACT
bool "Build kernel as self-extracting executable"
default y
help
Say Y if you want to build the parisc kernel as a kind of
self-extracting executable.
If you say N here, the kernel will be compressed with gzip
which can be loaded by the palo bootloader directly too.
If you don't know what to do here, say Y.
config SMP
bool "Symmetric multi-processing support"
---help---
......
......@@ -129,8 +129,13 @@ Image: vmlinux
bzImage: vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
ifdef CONFIG_PARISC_SELF_EXTRACT
vmlinuz: bzImage
$(OBJCOPY) $(boot)/bzImage $@
else
vmlinuz: vmlinux
@gzip -cf -9 $< > $@
endif
install:
$(CONFIG_SHELL) $(src)/arch/parisc/install.sh \
......
......@@ -15,7 +15,7 @@ targets += misc.o piggy.o sizes.h head.o real2.o firmware.o
KBUILD_CFLAGS := -D__KERNEL__ -O2 -DBOOTLOADER
KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
KBUILD_CFLAGS += $(cflags-y) -fno-delete-null-pointer-checks
KBUILD_CFLAGS += -fno-PIE -mno-space-regs -mdisable-fpregs
KBUILD_CFLAGS += -fno-PIE -mno-space-regs -mdisable-fpregs -Os
ifndef CONFIG_64BIT
KBUILD_CFLAGS += -mfast-indirect-calls
endif
......
......@@ -24,7 +24,8 @@
/* Symbols defined by linker scripts */
extern char input_data[];
extern int input_len;
extern __le32 output_len; /* at unaligned address, little-endian */
/* output_len is inserted by the linker possibly at an unaligned address */
extern __le32 output_len __aligned(1);
extern char _text, _end;
extern char _bss, _ebss;
extern char _startcode_end;
......
......@@ -280,6 +280,7 @@ void setup_pdc(void); /* in inventory.c */
/* wrapper-functions from pdc.c */
int pdc_add_valid(unsigned long address);
int pdc_instr(unsigned int *instr);
int pdc_chassis_info(struct pdc_chassis_info *chassis_info, void *led_info, unsigned long len);
int pdc_chassis_disp(unsigned long disp);
int pdc_chassis_warn(unsigned long *warn);
......
#ifndef __ASM_SMP_H
#define __ASM_SMP_H
extern int init_per_cpu(int cpuid);
#if defined(CONFIG_SMP)
......
......@@ -232,6 +232,26 @@ int pdc_add_valid(unsigned long address)
}
EXPORT_SYMBOL(pdc_add_valid);
/**
* pdc_instr - Get instruction that invokes PDCE_CHECK in HPMC handler.
* @instr: Pointer to variable which will get instruction opcode.
*
* The return value is PDC_OK (0) in case call succeeded.
*/
int __init pdc_instr(unsigned int *instr)
{
int retval;
unsigned long flags;
spin_lock_irqsave(&pdc_lock, flags);
retval = mem_pdc_call(PDC_INSTR, 0UL, __pa(pdc_result));
convert_to_wide(pdc_result);
*instr = pdc_result[0];
spin_unlock_irqrestore(&pdc_lock, flags);
return retval;
}
/**
* pdc_chassis_info - Return chassis information.
* @result: The return buffer.
......
......@@ -15,6 +15,7 @@
#include <linux/memblock.h>
#include <linux/seq_file.h>
#include <linux/kthread.h>
#include <linux/initrd.h>
#include <asm/pdc.h>
#include <asm/pdcpat.h>
......@@ -216,8 +217,16 @@ void __init pdc_pdt_init(void)
}
for (i = 0; i < pdt_status.pdt_entries; i++) {
unsigned long addr;
report_mem_err(pdt_entry[i]);
addr = pdt_entry[i] & PDT_ADDR_PHYS_MASK;
if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) &&
addr >= initrd_start && addr < initrd_end)
pr_crit("CRITICAL: initrd possibly broken "
"due to bad memory!\n");
/* mark memory page bad */
memblock_reserve(pdt_entry[i] & PAGE_MASK, PAGE_SIZE);
}
......
......@@ -317,7 +317,7 @@ void __init collect_boot_cpu_data(void)
*
* o Enable CPU profiling hooks.
*/
int init_per_cpu(int cpunum)
int __init init_per_cpu(int cpunum)
{
int ret;
struct pdc_coproc_cfg coproc_cfg;
......
......@@ -38,6 +38,7 @@
#include <linux/export.h>
#include <linux/sched.h>
#include <linux/sched/clock.h>
#include <linux/start_kernel.h>
#include <asm/processor.h>
#include <asm/sections.h>
......@@ -48,6 +49,7 @@
#include <asm/io.h>
#include <asm/setup.h>
#include <asm/unwind.h>
#include <asm/smp.h>
static char __initdata command_line[COMMAND_LINE_SIZE];
......@@ -115,7 +117,6 @@ void __init dma_ops_init(void)
}
#endif
extern int init_per_cpu(int cpuid);
extern void collect_boot_cpu_data(void);
void __init setup_arch(char **cmdline_p)
......@@ -398,9 +399,8 @@ static int __init parisc_init(void)
}
arch_initcall(parisc_init);
void start_parisc(void)
void __init start_parisc(void)
{
extern void start_kernel(void);
extern void early_trap_init(void);
int ret, cpunum;
......
......@@ -255,12 +255,11 @@ void arch_send_call_function_single_ipi(int cpu)
static void __init
smp_cpu_init(int cpunum)
{
extern int init_per_cpu(int); /* arch/parisc/kernel/processor.c */
extern void init_IRQ(void); /* arch/parisc/kernel/irq.c */
extern void start_cpu_itimer(void); /* arch/parisc/kernel/time.c */
/* Set modes and Enable floating point coprocessor */
(void) init_per_cpu(cpunum);
init_per_cpu(cpunum);
disable_sr_hashing();
......
......@@ -817,7 +817,7 @@ void __init initialize_ivt(const void *iva)
u32 check = 0;
u32 *ivap;
u32 *hpmcp;
u32 length;
u32 length, instr;
if (strcmp((const char *)iva, "cows can fly"))
panic("IVT invalid");
......@@ -827,6 +827,14 @@ void __init initialize_ivt(const void *iva)
for (i = 0; i < 8; i++)
*ivap++ = 0;
/*
* Use PDC_INSTR firmware function to get instruction that invokes
* PDCE_CHECK in HPMC handler. See programming note at page 1-31 of
* the PA 1.1 Firmware Architecture document.
*/
if (pdc_instr(&instr) == PDC_OK)
ivap[0] = instr;
/* Compute Checksum for HPMC handler */
length = os_hpmc_size;
ivap[7] = length;
......
......@@ -14,6 +14,7 @@
#include <linux/slab.h>
#include <linux/kallsyms.h>
#include <linux/sort.h>
#include <linux/sched.h>
#include <linux/uaccess.h>
#include <asm/assembly.h>
......@@ -279,6 +280,17 @@ static void unwind_frame_regs(struct unwind_frame_info *info)
info->prev_sp = sp - 64;
info->prev_ip = 0;
/* The stack is at the end inside the thread_union
* struct. If we reach data, we have reached the
* beginning of the stack and should stop unwinding. */
if (info->prev_sp >= (unsigned long) task_thread_info(info->t) &&
info->prev_sp < ((unsigned long) task_thread_info(info->t)
+ THREAD_SZ_ALGN)) {
info->prev_sp = 0;
break;
}
if (get_user(tmp, (unsigned long *)(info->prev_sp - RP_OFFSET)))
break;
info->prev_ip = tmp;
......
......@@ -17,6 +17,7 @@
#include <linux/interrupt.h>
#include <linux/extable.h>
#include <linux/uaccess.h>
#include <linux/hugetlb.h>
#include <asm/traps.h>
......@@ -261,7 +262,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,
struct task_struct *tsk;
struct mm_struct *mm;
unsigned long acc_type;
int fault;
int fault = 0;
unsigned int flags;
if (faulthandler_disabled())
......@@ -315,7 +316,8 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,
goto out_of_memory;
else if (fault & VM_FAULT_SIGSEGV)
goto bad_area;
else if (fault & VM_FAULT_SIGBUS)
else if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON|
VM_FAULT_HWPOISON_LARGE))
goto bad_area;
BUG();
}
......@@ -352,8 +354,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,
if (user_mode(regs)) {
struct siginfo si;
show_signal_msg(regs, code, address, tsk, vma);
unsigned int lsb = 0;
switch (code) {
case 15: /* Data TLB miss fault/Data page fault */
......@@ -386,6 +387,30 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,
si.si_code = (code == 26) ? SEGV_ACCERR : SEGV_MAPERR;
break;
}
#ifdef CONFIG_MEMORY_FAILURE
if (fault & (VM_FAULT_HWPOISON|VM_FAULT_HWPOISON_LARGE)) {
printk(KERN_ERR
"MCE: Killing %s:%d due to hardware memory corruption fault at %08lx\n",
tsk->comm, tsk->pid, address);
si.si_signo = SIGBUS;
si.si_code = BUS_MCEERR_AR;
}
#endif
/*
* Either small page or large page may be poisoned.
* In other words, VM_FAULT_HWPOISON_LARGE and
* VM_FAULT_HWPOISON are mutually exclusive.
*/
if (fault & VM_FAULT_HWPOISON_LARGE)
lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault));
else if (fault & VM_FAULT_HWPOISON)
lsb = PAGE_SHIFT;
else
show_signal_msg(regs, code, address, tsk, vma);
si.si_addr_lsb = lsb;
si.si_errno = 0;
si.si_addr = (void __user *) address;
force_sig_info(si.si_signo, &si, current);
......
......@@ -219,7 +219,8 @@ config FRAME_WARN
range 0 8192
default 0 if KASAN
default 2048 if GCC_PLUGIN_LATENT_ENTROPY
default 1024 if !64BIT
default 1280 if (!64BIT && PARISC)
default 1024 if (!64BIT && !PARISC)
default 2048 if 64BIT
help
Tell gcc to warn at build time for stack frames larger than this.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment