diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/base/cpu.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 281d26784d25..982e6583cd63 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -83,6 +83,33 @@ static inline void register_cpu_control(struct cpu *cpu) } #endif /* CONFIG_HOTPLUG_CPU */ +#ifdef CONFIG_KEXEC +#include <linux/kexec.h> + +static ssize_t show_crash_notes(struct sys_device *dev, char *buf) +{ + struct cpu *cpu = container_of(dev, struct cpu, sysdev); + ssize_t rc; + unsigned long long addr; + int cpunum; + + cpunum = cpu->sysdev.id; + + /* + * Might be reading other cpu's data based on which cpu read thread + * has been scheduled. But cpu data (memory) is allocated once during + * boot up and this data does not change there after. Hence this + * operation should be safe. No locking required. + */ + get_cpu(); + addr = __pa(per_cpu_ptr(crash_notes, cpunum)); + rc = sprintf(buf, "%Lx\n", addr); + put_cpu(); + return rc; +} +static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL); +#endif + /* * register_cpu - Setup a driverfs device for a CPU. * @cpu - Callers can set the cpu->no_control field to 1, to indicate not to @@ -108,6 +135,11 @@ int __devinit register_cpu(struct cpu *cpu, int num, struct node *root) register_cpu_control(cpu); if (!error) cpu_sys_devices[num] = &cpu->sysdev; + +#ifdef CONFIG_KEXEC + if (!error) + error = sysdev_create_file(&cpu->sysdev, &attr_crash_notes); +#endif return error; } |