mirror of
https://github.com/torvalds/linux.git
synced 2024-11-01 01:31:44 +00:00
70765aa4bd
I have tweaked this patch slightly to handle an empty list of pages to relocate passed to relocate_new_kernel. And I have added ppc_md.machine_crash_shutdown. To keep up with the changes in the generic kexec infrastructure. From: Albert Herranz <albert_herranz@yahoo.es> The following patch adds support for kexec on the ppc32 platform. Non-OpenFirmware based platforms are likely to work directly without additional changes on the kernel side. The kexec-tools userland package may need to be slightly updated, though. For OpenFirmware based machines, additional work is still needed on the kernel side before kexec support is ready. Benjamin Herrenschmidt is kindly working on that part. In order for a ppc platform to use the kexec kernel services it must implement some ppc_md hooks. Otherwise, kexec will be explicitly disabled, as suggested by benh. There are 3+1 new ppc_md hooks that a platform supporting kexec may implement. Two of them are mandatory for kexec to work. See include/asm-ppc/machdep.h for details. - machine_kexec_prepare(image) This function is called to make any arrangements to the image before it is loaded. This hook _MUST_ be provided by a platform in order to activate kexec support for that platform. Otherwise, the platform is considered to not support kexec and the kexec_load system call will fail (that makes all existing platforms by default non-kexec'able). - machine_kexec_cleanup(image) This function is called to make any cleanups on image after the loaded image data it is freed. This hook is optional. A platform may or may not provide this hook. - machine_kexec(image) This function is called to perform the _actual_ kexec. This hook _MUST_ be provided by a platform in order to activate kexec support for that platform. If a platform provides machine_kexec_prepare but forgets to provide machine_kexec, a kexec will fall back to a reboot. A ready-to-use machine_kexec_simple() generic function is provided to, hopefully, simplify kexec adoption for embedded platforms. A platform may call this function from its specific machine_kexec hook, like this: void myplatform_kexec(struct kimage *image) { machine_kexec_simple(image); } - machine_shutdown() This function is called to perform any machine specific shutdowns, not already done by drivers. This hook is optional. A platform may or may not provide this hook. An example (trimmed) platform specific module for a platform supporting kexec through the existing machine_kexec_simple follows: /* ... */ #ifdef CONFIG_KEXEC int myplatform_kexec_prepare(struct kimage *image) { /* here, we can place additional preparations */ return 0; /* yes, we support kexec */ } void myplatform_kexec(struct kimage *image) { machine_kexec_simple(image); } #endif /* CONFIG_KEXEC */ /* ... */ void __init platform_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) { /* ... */ #ifdef CONFIG_KEXEC ppc_md.machine_kexec_prepare = myplatform_kexec_prepare; ppc_md.machine_kexec = myplatform_kexec; #endif /* CONFIG_KEXEC */ /* ... */ } The kexec ppc kernel support has been heavily tested on the GameCube Linux port, and, as reported in the fastboot mailing list, it has been tested too on a Moto 82xx ppc by Rick Richardson. Signed-off-by: Albert Herranz <albert_herranz@yahoo.es> Signed-off-by: Eric Biederman <ebiederm@xmission.com> Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
186 lines
5.1 KiB
C
186 lines
5.1 KiB
C
#ifdef __KERNEL__
|
|
#ifndef _PPC_MACHDEP_H
|
|
#define _PPC_MACHDEP_H
|
|
|
|
#include <linux/config.h>
|
|
#include <linux/init.h>
|
|
#include <linux/kexec.h>
|
|
|
|
#include <asm/setup.h>
|
|
#include <asm/page.h>
|
|
|
|
#ifdef CONFIG_APUS
|
|
#include <asm-m68k/machdep.h>
|
|
#endif
|
|
|
|
struct pt_regs;
|
|
struct pci_bus;
|
|
struct pci_dev;
|
|
struct seq_file;
|
|
struct file;
|
|
|
|
/* We export this macro for external modules like Alsa to know if
|
|
* ppc_md.feature_call is implemented or not
|
|
*/
|
|
#define CONFIG_PPC_HAS_FEATURE_CALLS
|
|
|
|
struct machdep_calls {
|
|
void (*setup_arch)(void);
|
|
/* Optional, may be NULL. */
|
|
int (*show_cpuinfo)(struct seq_file *m);
|
|
int (*show_percpuinfo)(struct seq_file *m, int i);
|
|
/* Optional, may be NULL. */
|
|
unsigned int (*irq_canonicalize)(unsigned int irq);
|
|
void (*init_IRQ)(void);
|
|
int (*get_irq)(struct pt_regs *);
|
|
|
|
/* A general init function, called by ppc_init in init/main.c.
|
|
May be NULL. */
|
|
void (*init)(void);
|
|
|
|
void (*restart)(char *cmd);
|
|
void (*power_off)(void);
|
|
void (*halt)(void);
|
|
|
|
void (*idle)(void);
|
|
void (*power_save)(void);
|
|
|
|
long (*time_init)(void); /* Optional, may be NULL */
|
|
int (*set_rtc_time)(unsigned long nowtime);
|
|
unsigned long (*get_rtc_time)(void);
|
|
unsigned char (*rtc_read_val)(int addr);
|
|
void (*rtc_write_val)(int addr, unsigned char val);
|
|
void (*calibrate_decr)(void);
|
|
|
|
void (*heartbeat)(void);
|
|
unsigned long heartbeat_reset;
|
|
unsigned long heartbeat_count;
|
|
|
|
unsigned long (*find_end_of_memory)(void);
|
|
void (*setup_io_mappings)(void);
|
|
|
|
void (*early_serial_map)(void);
|
|
void (*progress)(char *, unsigned short);
|
|
void (*kgdb_map_scc)(void);
|
|
|
|
unsigned char (*nvram_read_val)(int addr);
|
|
void (*nvram_write_val)(int addr, unsigned char val);
|
|
void (*nvram_sync)(void);
|
|
|
|
/*
|
|
* optional PCI "hooks"
|
|
*/
|
|
|
|
/* Called after scanning the bus, before allocating resources */
|
|
void (*pcibios_fixup)(void);
|
|
|
|
/* Called after PPC generic resource fixup to perform
|
|
machine specific fixups */
|
|
void (*pcibios_fixup_resources)(struct pci_dev *);
|
|
|
|
/* Called for each PCI bus in the system when it's probed */
|
|
void (*pcibios_fixup_bus)(struct pci_bus *);
|
|
|
|
/* Called when pci_enable_device() is called (initial=0) or
|
|
* when a device with no assigned resource is found (initial=1).
|
|
* Returns 0 to allow assignment/enabling of the device. */
|
|
int (*pcibios_enable_device_hook)(struct pci_dev *, int initial);
|
|
|
|
/* For interrupt routing */
|
|
unsigned char (*pci_swizzle)(struct pci_dev *, unsigned char *);
|
|
int (*pci_map_irq)(struct pci_dev *, unsigned char, unsigned char);
|
|
|
|
/* Called in indirect_* to avoid touching devices */
|
|
int (*pci_exclude_device)(unsigned char, unsigned char);
|
|
|
|
/* Called at then very end of pcibios_init() */
|
|
void (*pcibios_after_init)(void);
|
|
|
|
/* Get access protection for /dev/mem */
|
|
pgprot_t (*phys_mem_access_prot)(struct file *file,
|
|
unsigned long offset,
|
|
unsigned long size,
|
|
pgprot_t vma_prot);
|
|
|
|
/* this is for modules, since _machine can be a define -- Cort */
|
|
int ppc_machine;
|
|
|
|
/* Motherboard/chipset features. This is a kind of general purpose
|
|
* hook used to control some machine specific features (like reset
|
|
* lines, chip power control, etc...).
|
|
*/
|
|
long (*feature_call)(unsigned int feature, ...);
|
|
|
|
#ifdef CONFIG_SMP
|
|
/* functions for dealing with other cpus */
|
|
struct smp_ops_t *smp_ops;
|
|
#endif /* CONFIG_SMP */
|
|
|
|
#ifdef CONFIG_KEXEC
|
|
/* Called to shutdown machine specific hardware not already controlled
|
|
* by other drivers.
|
|
* XXX Should we move this one out of kexec scope?
|
|
*/
|
|
void (*machine_shutdown)(void);
|
|
|
|
/* Called to do the minimal shutdown needed to run a kexec'd kernel
|
|
* to run successfully.
|
|
* XXX Should we move this one out of kexec scope?
|
|
*/
|
|
void (*machine_crash_shutdown)(void);
|
|
|
|
/* Called to do what every setup is needed on image and the
|
|
* reboot code buffer. Returns 0 on success.
|
|
* Provide your own (maybe dummy) implementation if your platform
|
|
* claims to support kexec.
|
|
*/
|
|
int (*machine_kexec_prepare)(struct kimage *image);
|
|
|
|
/* Called to handle any machine specific cleanup on image */
|
|
void (*machine_kexec_cleanup)(struct kimage *image);
|
|
|
|
/* Called to perform the _real_ kexec.
|
|
* Do NOT allocate memory or fail here. We are past the point of
|
|
* no return.
|
|
*/
|
|
void (*machine_kexec)(struct kimage *image);
|
|
#endif /* CONFIG_KEXEC */
|
|
};
|
|
|
|
extern struct machdep_calls ppc_md;
|
|
extern char cmd_line[COMMAND_LINE_SIZE];
|
|
|
|
extern void setup_pci_ptrs(void);
|
|
|
|
/*
|
|
* Power macintoshes have either a CUDA or a PMU controlling
|
|
* system reset, power, NVRAM, RTC.
|
|
*/
|
|
typedef enum sys_ctrler_kind {
|
|
SYS_CTRLER_UNKNOWN = 0,
|
|
SYS_CTRLER_CUDA = 1,
|
|
SYS_CTRLER_PMU = 2,
|
|
SYS_CTRLER_SMU = 3,
|
|
} sys_ctrler_t;
|
|
|
|
extern sys_ctrler_t sys_ctrler;
|
|
|
|
#ifdef CONFIG_SMP
|
|
struct smp_ops_t {
|
|
void (*message_pass)(int target, int msg, unsigned long data, int wait);
|
|
int (*probe)(void);
|
|
void (*kick_cpu)(int nr);
|
|
void (*setup_cpu)(int nr);
|
|
void (*space_timers)(int nr);
|
|
void (*take_timebase)(void);
|
|
void (*give_timebase)(void);
|
|
};
|
|
|
|
/* Poor default implementations */
|
|
extern void __devinit smp_generic_give_timebase(void);
|
|
extern void __devinit smp_generic_take_timebase(void);
|
|
#endif /* CONFIG_SMP */
|
|
|
|
#endif /* _PPC_MACHDEP_H */
|
|
#endif /* __KERNEL__ */
|