Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 17114
b: refs/heads/master
c: 3d1229d
h: refs/heads/master
v: v3
  • Loading branch information
Michael Ellerman authored and Paul Mackerras committed Jan 9, 2006
1 parent 2abb8df commit 9c4391f
Show file tree
Hide file tree
Showing 15 changed files with 282 additions and 34 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: afcc2472d80569059b5fe71fcb67e618b9d83fa8
refs/heads/master: 3d1229d6ae92ed1994f4411b8493327ef8f4b76f
5 changes: 3 additions & 2 deletions trunk/arch/powerpc/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,9 @@ pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o pci_iommu.o \
pci_direct_iommu.o iomap.o
obj-$(CONFIG_PCI) += $(pci64-y)

kexec64-$(CONFIG_PPC64) += machine_kexec_64.o
obj-$(CONFIG_KEXEC) += $(kexec64-y)
kexec-$(CONFIG_PPC64) := machine_kexec_64.o
kexec-$(CONFIG_PPC32) := machine_kexec_32.o
obj-$(CONFIG_KEXEC) += machine_kexec.o $(kexec-y)

ifeq ($(CONFIG_PPC_ISERIES),y)
$(obj)/head_64.o: $(obj)/lparmap.s
Expand Down
67 changes: 67 additions & 0 deletions trunk/arch/powerpc/kernel/machine_kexec.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Code to handle transition of Linux booting another kernel.
*
* Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com>
* GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
* Copyright (C) 2005 IBM Corporation.
*
* This source code is licensed under the GNU General Public License,
* Version 2. See the file COPYING for more details.
*/

#include <linux/kexec.h>
#include <linux/reboot.h>
#include <linux/threads.h>
#include <asm/machdep.h>

/*
* Provide a dummy crash_notes definition until crash dump is implemented.
* This prevents breakage of crash_notes attribute in kernel/ksysfs.c.
*/
note_buf_t crash_notes[NR_CPUS];

void machine_crash_shutdown(struct pt_regs *regs)
{
if (ppc_md.machine_crash_shutdown)
ppc_md.machine_crash_shutdown();
}

/*
* Do what every setup is needed on image and the
* reboot code buffer to allow us to avoid allocations
* later.
*/
int machine_kexec_prepare(struct kimage *image)
{
if (ppc_md.machine_kexec_prepare)
return ppc_md.machine_kexec_prepare(image);
/*
* Fail if platform doesn't provide its own machine_kexec_prepare
* implementation.
*/
return -ENOSYS;
}

void machine_kexec_cleanup(struct kimage *image)
{
if (ppc_md.machine_kexec_cleanup)
ppc_md.machine_kexec_cleanup(image);
}

/*
* Do not allocate memory (or fail in any way) in machine_kexec().
* We are past the point of no return, committed to rebooting now.
*/
NORET_TYPE void machine_kexec(struct kimage *image)
{
if (ppc_md.machine_kexec)
ppc_md.machine_kexec(image);
else {
/*
* Fall back to normal restart if platform doesn't provide
* its own kexec function, and user insist to kexec...
*/
machine_restart(NULL);
}
for(;;);
}
65 changes: 65 additions & 0 deletions trunk/arch/powerpc/kernel/machine_kexec_32.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* PPC32 code to handle Linux booting another kernel.
*
* Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com>
* GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
* Copyright (C) 2005 IBM Corporation.
*
* This source code is licensed under the GNU General Public License,
* Version 2. See the file COPYING for more details.
*/

#include <linux/kexec.h>
#include <linux/mm.h>
#include <linux/string.h>
#include <asm/cacheflush.h>
#include <asm/hw_irq.h>
#include <asm/io.h>

typedef NORET_TYPE void (*relocate_new_kernel_t)(
unsigned long indirection_page,
unsigned long reboot_code_buffer,
unsigned long start_address) ATTRIB_NORET;

/*
* This is a generic machine_kexec function suitable at least for
* non-OpenFirmware embedded platforms.
* It merely copies the image relocation code to the control page and
* jumps to it.
* A platform specific function may just call this one.
*/
void default_machine_kexec(struct kimage *image)
{
const extern unsigned char relocate_new_kernel[];
const extern unsigned int relocate_new_kernel_size;
unsigned long page_list;
unsigned long reboot_code_buffer, reboot_code_buffer_phys;
relocate_new_kernel_t rnk;

/* Interrupts aren't acceptable while we reboot */
local_irq_disable();

page_list = image->head;

/* we need both effective and real address here */
reboot_code_buffer =
(unsigned long)page_address(image->control_code_page);
reboot_code_buffer_phys = virt_to_phys((void *)reboot_code_buffer);

/* copy our kernel relocation code to the control code page */
memcpy((void *)reboot_code_buffer, relocate_new_kernel,
relocate_new_kernel_size);

flush_icache_range(reboot_code_buffer,
reboot_code_buffer + KEXEC_CONTROL_CODE_SIZE);
printk(KERN_INFO "Bye!\n");

/* now call it */
rnk = (relocate_new_kernel_t) reboot_code_buffer;
(*rnk)(page_list, reboot_code_buffer_phys, image->start);
}

int default_machine_kexec_prepare(struct kimage *image)
{
return 0;
}
25 changes: 3 additions & 22 deletions trunk/arch/powerpc/kernel/machine_kexec_64.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* machine_kexec.c - handle transition of Linux booting another kernel
* PPC64 code to handle Linux booting another kernel.
*
* Copyright (C) 2004-2005, IBM Corp.
*
Expand Down Expand Up @@ -28,21 +28,7 @@

#define HASH_GROUP_SIZE 0x80 /* size of each hash group, asm/mmu.h */

/* Have this around till we move it into crash specific file */
note_buf_t crash_notes[NR_CPUS];

/* Dummy for now. Not sure if we need to have a crash shutdown in here
* and if what it will achieve. Letting it be now to compile the code
* in generic kexec environment
*/
void machine_crash_shutdown(struct pt_regs *regs)
{
/* do nothing right now */
/* smp_relase_cpus() if we want smp on panic kernel */
/* cpu_irq_down to isolate us until we are ready */
}

int machine_kexec_prepare(struct kimage *image)
int default_machine_kexec_prepare(struct kimage *image)
{
int i;
unsigned long begin, end; /* limits of segment */
Expand Down Expand Up @@ -111,11 +97,6 @@ int machine_kexec_prepare(struct kimage *image)
return 0;
}

void machine_kexec_cleanup(struct kimage *image)
{
/* we do nothing in prepare that needs to be undone */
}

#define IND_FLAGS (IND_DESTINATION | IND_INDIRECTION | IND_DONE | IND_SOURCE)

static void copy_segments(unsigned long ind)
Expand Down Expand Up @@ -283,7 +264,7 @@ extern NORET_TYPE void kexec_sequence(void *newstack, unsigned long start,
void (*clear_all)(void)) ATTRIB_NORET;

/* too late to fail here */
void machine_kexec(struct kimage *image)
void default_machine_kexec(struct kimage *image)
{

/* prepare control code if any */
Expand Down
113 changes: 113 additions & 0 deletions trunk/arch/powerpc/kernel/misc_32.S
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
* Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
* and Paul Mackerras.
*
* kexec bits:
* Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com>
* GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
*
* 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
Expand All @@ -24,6 +28,8 @@
#include <asm/ppc_asm.h>
#include <asm/thread_info.h>
#include <asm/asm-offsets.h>
#include <asm/processor.h>
#include <asm/kexec.h>

.text

Expand Down Expand Up @@ -1006,3 +1012,110 @@ _GLOBAL(execve)
*/
_GLOBAL(__main)
blr

#ifdef CONFIG_KEXEC
/*
* Must be relocatable PIC code callable as a C function.
*/
.globl relocate_new_kernel
relocate_new_kernel:
/* r3 = page_list */
/* r4 = reboot_code_buffer */
/* r5 = start_address */

li r0, 0

/*
* Set Machine Status Register to a known status,
* switch the MMU off and jump to 1: in a single step.
*/

mr r8, r0
ori r8, r8, MSR_RI|MSR_ME
mtspr SPRN_SRR1, r8
addi r8, r4, 1f - relocate_new_kernel
mtspr SPRN_SRR0, r8
sync
rfi

1:
/* from this point address translation is turned off */
/* and interrupts are disabled */

/* set a new stack at the bottom of our page... */
/* (not really needed now) */
addi r1, r4, KEXEC_CONTROL_CODE_SIZE - 8 /* for LR Save+Back Chain */
stw r0, 0(r1)

/* Do the copies */
li r6, 0 /* checksum */
mr r0, r3
b 1f

0: /* top, read another word for the indirection page */
lwzu r0, 4(r3)

1:
/* is it a destination page? (r8) */
rlwinm. r7, r0, 0, 31, 31 /* IND_DESTINATION (1<<0) */
beq 2f

rlwinm r8, r0, 0, 0, 19 /* clear kexec flags, page align */
b 0b

2: /* is it an indirection page? (r3) */
rlwinm. r7, r0, 0, 30, 30 /* IND_INDIRECTION (1<<1) */
beq 2f

rlwinm r3, r0, 0, 0, 19 /* clear kexec flags, page align */
subi r3, r3, 4
b 0b

2: /* are we done? */
rlwinm. r7, r0, 0, 29, 29 /* IND_DONE (1<<2) */
beq 2f
b 3f

2: /* is it a source page? (r9) */
rlwinm. r7, r0, 0, 28, 28 /* IND_SOURCE (1<<3) */
beq 0b

rlwinm r9, r0, 0, 0, 19 /* clear kexec flags, page align */

li r7, PAGE_SIZE / 4
mtctr r7
subi r9, r9, 4
subi r8, r8, 4
9:
lwzu r0, 4(r9) /* do the copy */
xor r6, r6, r0
stwu r0, 4(r8)
dcbst 0, r8
sync
icbi 0, r8
bdnz 9b

addi r9, r9, 4
addi r8, r8, 4
b 0b

3:

/* To be certain of avoiding problems with self-modifying code
* execute a serializing instruction here.
*/
isync
sync

/* jump to the entry point, usually the setup routine */
mtlr r5
blrl

1: b 1b

relocate_new_kernel_end:

.globl relocate_new_kernel_size
relocate_new_kernel_size:
.long relocate_new_kernel_end - relocate_new_kernel
#endif
4 changes: 2 additions & 2 deletions trunk/arch/powerpc/kernel/setup-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ EXPORT_SYMBOL(ppc_do_canonicalize_irqs);
/* also used by kexec */
void machine_shutdown(void)
{
if (ppc_md.nvram_sync)
ppc_md.nvram_sync();
if (ppc_md.machine_shutdown)
ppc_md.machine_shutdown();
}

void machine_restart(char *cmd)
Expand Down
5 changes: 5 additions & 0 deletions trunk/arch/powerpc/platforms/cell/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <asm/mmu.h>
#include <asm/processor.h>
#include <asm/io.h>
#include <asm/kexec.h>
#include <asm/pgtable.h>
#include <asm/prom.h>
#include <asm/rtas.h>
Expand Down Expand Up @@ -138,4 +139,8 @@ struct machdep_calls __initdata cell_md = {
.set_rtc_time = rtas_set_rtc_time,
.calibrate_decr = generic_calibrate_decr,
.progress = cell_progress,
#ifdef CONFIG_KEXEC
.machine_kexec = default_machine_kexec,
.machine_kexec_prepare = default_machine_kexec_prepare,
#endif
};
5 changes: 5 additions & 0 deletions trunk/arch/powerpc/platforms/maple/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#include <asm/pgtable.h>
#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/kexec.h>
#include <asm/pci-bridge.h>
#include <asm/iommu.h>
#include <asm/machdep.h>
Expand Down Expand Up @@ -292,4 +293,8 @@ struct machdep_calls __initdata maple_md = {
.calibrate_decr = generic_calibrate_decr,
.progress = maple_progress,
.idle_loop = native_idle,
#ifdef CONFIG_KEXEC
.machine_kexec = default_machine_kexec,
.machine_kexec_prepare = default_machine_kexec_prepare,
#endif
};
1 change: 1 addition & 0 deletions trunk/arch/powerpc/platforms/powermac/nvram.c
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,7 @@ static int __init core99_nvram_setup(struct device_node *dp)
ppc_md.nvram_write = core99_nvram_write;
ppc_md.nvram_size = core99_nvram_size;
ppc_md.nvram_sync = core99_nvram_sync;
ppc_md.machine_shutdown = core99_nvram_sync;
/*
* Maybe we could be smarter here though making an exclusive list
* of known flash chips is a bit nasty as older OF didn't provide us
Expand Down
Loading

0 comments on commit 9c4391f

Please sign in to comment.