mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-30 08:02:30 +00:00
[PATCH] powerpc: Reroute interrupts from 0 + offset to PHYSICAL_START + offset
Regardless of where the kernel's linked we always get interrupts at low addresses. This patch creates a trampoline in the first 3 pages of memory, where interrupts land, and patches those addresses to jump into the real kernel code at PHYSICAL_START. We also need to reserve the trampoline code and a bit more in prom.c Signed-off-by: Michael Ellerman <michael@ellerman.id.au> Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
parent
8c4f1f2958
commit
0cc4746cad
5 changed files with 77 additions and 1 deletions
|
@ -34,6 +34,7 @@ obj-$(CONFIG_IBMVIO) += vio.o
|
||||||
obj-$(CONFIG_IBMEBUS) += ibmebus.o
|
obj-$(CONFIG_IBMEBUS) += ibmebus.o
|
||||||
obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o
|
obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o
|
||||||
obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvram_64.o
|
obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvram_64.o
|
||||||
|
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
|
||||||
|
|
||||||
ifeq ($(CONFIG_PPC_MERGE),y)
|
ifeq ($(CONFIG_PPC_MERGE),y)
|
||||||
|
|
||||||
|
|
53
arch/powerpc/kernel/crash_dump.c
Normal file
53
arch/powerpc/kernel/crash_dump.c
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Routines for doing kexec-based kdump.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005, IBM Corp.
|
||||||
|
*
|
||||||
|
* Created by: Michael Ellerman
|
||||||
|
*
|
||||||
|
* This source code is licensed under the GNU General Public License,
|
||||||
|
* Version 2. See the file COPYING for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#undef DEBUG
|
||||||
|
|
||||||
|
#include <asm/kdump.h>
|
||||||
|
#include <asm/lmb.h>
|
||||||
|
#include <asm/firmware.h>
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#include <asm/udbg.h>
|
||||||
|
#define DBG(fmt...) udbg_printf(fmt)
|
||||||
|
#else
|
||||||
|
#define DBG(fmt...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void __init create_trampoline(unsigned long addr)
|
||||||
|
{
|
||||||
|
/* The maximum range of a single instruction branch, is the current
|
||||||
|
* instruction's address + (32 MB - 4) bytes. For the trampoline we
|
||||||
|
* need to branch to current address + 32 MB. So we insert a nop at
|
||||||
|
* the trampoline address, then the next instruction (+ 4 bytes)
|
||||||
|
* does a branch to (32 MB - 4). The net effect is that when we
|
||||||
|
* branch to "addr" we jump to ("addr" + 32 MB). Although it requires
|
||||||
|
* two instructions it doesn't require any registers.
|
||||||
|
*/
|
||||||
|
create_instruction(addr, 0x60000000); /* nop */
|
||||||
|
create_branch(addr + 4, addr + PHYSICAL_START, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __init kdump_setup(void)
|
||||||
|
{
|
||||||
|
unsigned long i;
|
||||||
|
|
||||||
|
DBG(" -> kdump_setup()\n");
|
||||||
|
|
||||||
|
for (i = KDUMP_TRAMPOLINE_START; i < KDUMP_TRAMPOLINE_END; i += 8) {
|
||||||
|
create_trampoline(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
create_trampoline(__pa(system_reset_fwnmi) - PHYSICAL_START);
|
||||||
|
create_trampoline(__pa(machine_check_fwnmi) - PHYSICAL_START);
|
||||||
|
|
||||||
|
DBG(" <- kdump_setup()\n");
|
||||||
|
}
|
|
@ -37,6 +37,7 @@
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
#include <asm/kdump.h>
|
||||||
#include <asm/smp.h>
|
#include <asm/smp.h>
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
#include <asm/mmu.h>
|
#include <asm/mmu.h>
|
||||||
|
@ -1335,11 +1336,14 @@ void __init early_init_devtree(void *params)
|
||||||
of_scan_flat_dt(early_init_dt_scan_memory, NULL);
|
of_scan_flat_dt(early_init_dt_scan_memory, NULL);
|
||||||
lmb_enforce_memory_limit(memory_limit);
|
lmb_enforce_memory_limit(memory_limit);
|
||||||
lmb_analyze();
|
lmb_analyze();
|
||||||
lmb_reserve(0, __pa(klimit));
|
|
||||||
|
|
||||||
DBG("Phys. mem: %lx\n", lmb_phys_mem_size());
|
DBG("Phys. mem: %lx\n", lmb_phys_mem_size());
|
||||||
|
|
||||||
/* Reserve LMB regions used by kernel, initrd, dt, etc... */
|
/* Reserve LMB regions used by kernel, initrd, dt, etc... */
|
||||||
|
lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START);
|
||||||
|
#ifdef CONFIG_CRASH_DUMP
|
||||||
|
lmb_reserve(0, KDUMP_RESERVE_LIMIT);
|
||||||
|
#endif
|
||||||
early_reserve_mem();
|
early_reserve_mem();
|
||||||
|
|
||||||
DBG("Scanning CPUs ...\n");
|
DBG("Scanning CPUs ...\n");
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include <linux/serial.h>
|
#include <linux/serial.h>
|
||||||
#include <linux/serial_8250.h>
|
#include <linux/serial_8250.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
#include <asm/kdump.h>
|
||||||
#include <asm/prom.h>
|
#include <asm/prom.h>
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
|
@ -268,6 +269,10 @@ void __init early_setup(unsigned long dt_ptr)
|
||||||
}
|
}
|
||||||
ppc_md = **mach;
|
ppc_md = **mach;
|
||||||
|
|
||||||
|
#ifdef CONFIG_CRASH_DUMP
|
||||||
|
kdump_setup();
|
||||||
|
#endif
|
||||||
|
|
||||||
DBG("Found, Initializing memory management...\n");
|
DBG("Found, Initializing memory management...\n");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
13
include/asm-powerpc/kdump.h
Normal file
13
include/asm-powerpc/kdump.h
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#ifndef _PPC64_KDUMP_H
|
||||||
|
#define _PPC64_KDUMP_H
|
||||||
|
|
||||||
|
/* How many bytes to reserve at zero for kdump. The reserve limit should
|
||||||
|
* be greater or equal to the trampoline's end address. */
|
||||||
|
#define KDUMP_RESERVE_LIMIT 0x8000
|
||||||
|
|
||||||
|
#define KDUMP_TRAMPOLINE_START 0x0100
|
||||||
|
#define KDUMP_TRAMPOLINE_END 0x3000
|
||||||
|
|
||||||
|
extern void kdump_setup(void);
|
||||||
|
|
||||||
|
#endif /* __PPC64_KDUMP_H */
|
Loading…
Reference in a new issue