aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
authorMichael Holzheu <holzheu@linux.vnet.ibm.com>2012-03-11 11:59:34 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2012-03-11 11:59:29 -0400
commit4857d4bbe9821c8d732cb84455e18e12b3d79add (patch)
tree54583e3ef5c84c04f92b7b15ea6aad8224781d9b /arch/s390
parentad252ffa2a0fbb1f37e81688322034b3af037cee (diff)
[S390] kernel: Add OS info memory interface
In order to allow kdump based stand-alone dump, some information has to be passed from the old kernel to the new dump kernel. This is done via a the struct "os_info" that contains the following fields: * crashkernel base and size * reipl block * vmcoreinfo * init function A pointer to os_info is stored at a well known storage location and the whole structure as well as all fields are secured with checksums. Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/include/asm/lowcore.h8
-rw-r--r--arch/s390/include/asm/os_info.h50
-rw-r--r--arch/s390/kernel/Makefile2
-rw-r--r--arch/s390/kernel/crash_dump.c37
-rw-r--r--arch/s390/kernel/ipl.c42
-rw-r--r--arch/s390/kernel/os_info.c169
-rw-r--r--arch/s390/kernel/setup.c3
-rw-r--r--arch/s390/kernel/smp.c13
8 files changed, 304 insertions, 20 deletions
diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h
index 4e69563bc95..a47c6e221a9 100644
--- a/arch/s390/include/asm/lowcore.h
+++ b/arch/s390/include/asm/lowcore.h
@@ -154,7 +154,9 @@ struct _lowcore {
154 __u32 ipib; /* 0x0e00 */ 154 __u32 ipib; /* 0x0e00 */
155 __u32 ipib_checksum; /* 0x0e04 */ 155 __u32 ipib_checksum; /* 0x0e04 */
156 __u32 vmcore_info; /* 0x0e08 */ 156 __u32 vmcore_info; /* 0x0e08 */
157 __u8 pad_0x0e0c[0x0f00-0x0e0c]; /* 0x0e0c */ 157 __u8 pad_0x0e0c[0x0e18-0x0e0c]; /* 0x0e0c */
158 __u32 os_info; /* 0x0e18 */
159 __u8 pad_0x0e1c[0x0f00-0x0e1c]; /* 0x0e1c */
158 160
159 /* Extended facility list */ 161 /* Extended facility list */
160 __u64 stfle_fac_list[32]; /* 0x0f00 */ 162 __u64 stfle_fac_list[32]; /* 0x0f00 */
@@ -301,7 +303,9 @@ struct _lowcore {
301 __u64 ipib; /* 0x0e00 */ 303 __u64 ipib; /* 0x0e00 */
302 __u32 ipib_checksum; /* 0x0e08 */ 304 __u32 ipib_checksum; /* 0x0e08 */
303 __u64 vmcore_info; /* 0x0e0c */ 305 __u64 vmcore_info; /* 0x0e0c */
304 __u8 pad_0x0e14[0x0f00-0x0e14]; /* 0x0e14 */ 306 __u8 pad_0x0e14[0x0e18-0x0e14]; /* 0x0e14 */
307 __u64 os_info; /* 0x0e18 */
308 __u8 pad_0x0e20[0x0f00-0x0e20]; /* 0x0e20 */
305 309
306 /* Extended facility list */ 310 /* Extended facility list */
307 __u64 stfle_fac_list[32]; /* 0x0f00 */ 311 __u64 stfle_fac_list[32]; /* 0x0f00 */
diff --git a/arch/s390/include/asm/os_info.h b/arch/s390/include/asm/os_info.h
new file mode 100644
index 00000000000..d07518af09e
--- /dev/null
+++ b/arch/s390/include/asm/os_info.h
@@ -0,0 +1,50 @@
1/*
2 * OS info memory interface
3 *
4 * Copyright IBM Corp. 2012
5 * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com>
6 */
7#ifndef _ASM_S390_OS_INFO_H
8#define _ASM_S390_OS_INFO_H
9
10#define OS_INFO_VERSION_MAJOR 1
11#define OS_INFO_VERSION_MINOR 1
12#define OS_INFO_MAGIC 0x4f53494e464f535aULL /* OSINFOSZ */
13
14#define OS_INFO_VMCOREINFO 0
15#define OS_INFO_REIPL_BLOCK 1
16#define OS_INFO_INIT_FN 2
17
18struct os_info_entry {
19 u64 addr;
20 u64 size;
21 u32 csum;
22} __packed;
23
24struct os_info {
25 u64 magic;
26 u32 csum;
27 u16 version_major;
28 u16 version_minor;
29 u64 crashkernel_addr;
30 u64 crashkernel_size;
31 struct os_info_entry entry[3];
32 u8 reserved[4004];
33} __packed;
34
35void os_info_init(void);
36void os_info_entry_add(int nr, void *ptr, u64 len);
37void os_info_crashkernel_add(unsigned long base, unsigned long size);
38u32 os_info_csum(struct os_info *os_info);
39
40#ifdef CONFIG_CRASH_DUMP
41void *os_info_old_entry(int nr, unsigned long *size);
42int copy_from_oldmem(void *dest, void *src, size_t count);
43#else
44static inline void *os_info_old_entry(int nr, unsigned long *size)
45{
46 return NULL;
47}
48#endif
49
50#endif /* _ASM_S390_OS_INFO_H */
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index b2159509049..16b0b433f1f 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -23,7 +23,7 @@ CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w
23obj-y := bitmap.o traps.o time.o process.o base.o early.o setup.o vtime.o \ 23obj-y := bitmap.o traps.o time.o process.o base.o early.o setup.o vtime.o \
24 processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o \ 24 processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o \
25 debug.o irq.o ipl.o dis.o diag.o mem_detect.o sclp.o vdso.o \ 25 debug.o irq.o ipl.o dis.o diag.o mem_detect.o sclp.o vdso.o \
26 sysinfo.o jump_label.o lgr.o 26 sysinfo.o jump_label.o lgr.o os_info.o
27 27
28obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o) 28obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o)
29obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o) 29obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c
index c383ce440d9..cc1172b2687 100644
--- a/arch/s390/kernel/crash_dump.c
+++ b/arch/s390/kernel/crash_dump.c
@@ -14,6 +14,7 @@
14#include <linux/bootmem.h> 14#include <linux/bootmem.h>
15#include <linux/elf.h> 15#include <linux/elf.h>
16#include <asm/ipl.h> 16#include <asm/ipl.h>
17#include <asm/os_info.h>
17 18
18#define PTR_ADD(x, y) (((char *) (x)) + ((unsigned long) (y))) 19#define PTR_ADD(x, y) (((char *) (x)) + ((unsigned long) (y)))
19#define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y))) 20#define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y)))
@@ -51,7 +52,7 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
51/* 52/*
52 * Copy memory from old kernel 53 * Copy memory from old kernel
53 */ 54 */
54static int copy_from_oldmem(void *dest, void *src, size_t count) 55int copy_from_oldmem(void *dest, void *src, size_t count)
55{ 56{
56 unsigned long copied = 0; 57 unsigned long copied = 0;
57 int rc; 58 int rc;
@@ -224,28 +225,44 @@ static void *nt_prpsinfo(void *ptr)
224} 225}
225 226
226/* 227/*
227 * Initialize vmcoreinfo note (new kernel) 228 * Get vmcoreinfo using lowcore->vmcore_info (new kernel)
228 */ 229 */
229static void *nt_vmcoreinfo(void *ptr) 230static void *get_vmcoreinfo_old(unsigned long *size)
230{ 231{
231 char nt_name[11], *vmcoreinfo; 232 char nt_name[11], *vmcoreinfo;
232 Elf64_Nhdr note; 233 Elf64_Nhdr note;
233 void *addr; 234 void *addr;
234 235
235 if (copy_from_oldmem(&addr, &S390_lowcore.vmcore_info, sizeof(addr))) 236 if (copy_from_oldmem(&addr, &S390_lowcore.vmcore_info, sizeof(addr)))
236 return ptr; 237 return NULL;
237 memset(nt_name, 0, sizeof(nt_name)); 238 memset(nt_name, 0, sizeof(nt_name));
238 if (copy_from_oldmem(&note, addr, sizeof(note))) 239 if (copy_from_oldmem(&note, addr, sizeof(note)))
239 return ptr; 240 return NULL;
240 if (copy_from_oldmem(nt_name, addr + sizeof(note), sizeof(nt_name) - 1)) 241 if (copy_from_oldmem(nt_name, addr + sizeof(note), sizeof(nt_name) - 1))
241 return ptr; 242 return NULL;
242 if (strcmp(nt_name, "VMCOREINFO") != 0) 243 if (strcmp(nt_name, "VMCOREINFO") != 0)
243 return ptr; 244 return NULL;
244 vmcoreinfo = kzalloc_panic(note.n_descsz + 1); 245 vmcoreinfo = kzalloc_panic(note.n_descsz);
245 if (copy_from_oldmem(vmcoreinfo, addr + 24, note.n_descsz)) 246 if (copy_from_oldmem(vmcoreinfo, addr + 24, note.n_descsz))
247 return NULL;
248 *size = note.n_descsz;
249 return vmcoreinfo;
250}
251
252/*
253 * Initialize vmcoreinfo note (new kernel)
254 */
255static void *nt_vmcoreinfo(void *ptr)
256{
257 unsigned long size;
258 void *vmcoreinfo;
259
260 vmcoreinfo = os_info_old_entry(OS_INFO_VMCOREINFO, &size);
261 if (!vmcoreinfo)
262 vmcoreinfo = get_vmcoreinfo_old(&size);
263 if (!vmcoreinfo)
246 return ptr; 264 return ptr;
247 vmcoreinfo[note.n_descsz + 1] = 0; 265 return nt_init(ptr, 0, vmcoreinfo, size, "VMCOREINFO");
248 return nt_init(ptr, 0, vmcoreinfo, note.n_descsz, "VMCOREINFO");
249} 266}
250 267
251/* 268/*
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 153e21ce233..8342e65a140 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -28,6 +28,7 @@
28#include <asm/sclp.h> 28#include <asm/sclp.h>
29#include <asm/checksum.h> 29#include <asm/checksum.h>
30#include <asm/debug.h> 30#include <asm/debug.h>
31#include <asm/os_info.h>
31#include "entry.h" 32#include "entry.h"
32 33
33#define IPL_PARM_BLOCK_VERSION 0 34#define IPL_PARM_BLOCK_VERSION 0
@@ -951,6 +952,13 @@ static struct attribute_group reipl_nss_attr_group = {
951 .attrs = reipl_nss_attrs, 952 .attrs = reipl_nss_attrs,
952}; 953};
953 954
955static void set_reipl_block_actual(struct ipl_parameter_block *reipl_block)
956{
957 reipl_block_actual = reipl_block;
958 os_info_entry_add(OS_INFO_REIPL_BLOCK, reipl_block_actual,
959 reipl_block->hdr.len);
960}
961
954/* reipl type */ 962/* reipl type */
955 963
956static int reipl_set_type(enum ipl_type type) 964static int reipl_set_type(enum ipl_type type)
@@ -966,7 +974,7 @@ static int reipl_set_type(enum ipl_type type)
966 reipl_method = REIPL_METHOD_CCW_VM; 974 reipl_method = REIPL_METHOD_CCW_VM;
967 else 975 else
968 reipl_method = REIPL_METHOD_CCW_CIO; 976 reipl_method = REIPL_METHOD_CCW_CIO;
969 reipl_block_actual = reipl_block_ccw; 977 set_reipl_block_actual(reipl_block_ccw);
970 break; 978 break;
971 case IPL_TYPE_FCP: 979 case IPL_TYPE_FCP:
972 if (diag308_set_works) 980 if (diag308_set_works)
@@ -975,7 +983,7 @@ static int reipl_set_type(enum ipl_type type)
975 reipl_method = REIPL_METHOD_FCP_RO_VM; 983 reipl_method = REIPL_METHOD_FCP_RO_VM;
976 else 984 else
977 reipl_method = REIPL_METHOD_FCP_RO_DIAG; 985 reipl_method = REIPL_METHOD_FCP_RO_DIAG;
978 reipl_block_actual = reipl_block_fcp; 986 set_reipl_block_actual(reipl_block_fcp);
979 break; 987 break;
980 case IPL_TYPE_FCP_DUMP: 988 case IPL_TYPE_FCP_DUMP:
981 reipl_method = REIPL_METHOD_FCP_DUMP; 989 reipl_method = REIPL_METHOD_FCP_DUMP;
@@ -985,7 +993,7 @@ static int reipl_set_type(enum ipl_type type)
985 reipl_method = REIPL_METHOD_NSS_DIAG; 993 reipl_method = REIPL_METHOD_NSS_DIAG;
986 else 994 else
987 reipl_method = REIPL_METHOD_NSS; 995 reipl_method = REIPL_METHOD_NSS;
988 reipl_block_actual = reipl_block_nss; 996 set_reipl_block_actual(reipl_block_nss);
989 break; 997 break;
990 case IPL_TYPE_UNKNOWN: 998 case IPL_TYPE_UNKNOWN:
991 reipl_method = REIPL_METHOD_DEFAULT; 999 reipl_method = REIPL_METHOD_DEFAULT;
@@ -1257,6 +1265,29 @@ static int __init reipl_fcp_init(void)
1257 return 0; 1265 return 0;
1258} 1266}
1259 1267
1268static int __init reipl_type_init(void)
1269{
1270 enum ipl_type reipl_type = ipl_info.type;
1271 struct ipl_parameter_block *reipl_block;
1272 unsigned long size;
1273
1274 reipl_block = os_info_old_entry(OS_INFO_REIPL_BLOCK, &size);
1275 if (!reipl_block)
1276 goto out;
1277 /*
1278 * If we have an OS info reipl block, this will be used
1279 */
1280 if (reipl_block->hdr.pbt == DIAG308_IPL_TYPE_FCP) {
1281 memcpy(reipl_block_fcp, reipl_block, size);
1282 reipl_type = IPL_TYPE_FCP;
1283 } else if (reipl_block->hdr.pbt == DIAG308_IPL_TYPE_CCW) {
1284 memcpy(reipl_block_ccw, reipl_block, size);
1285 reipl_type = IPL_TYPE_CCW;
1286 }
1287out:
1288 return reipl_set_type(reipl_type);
1289}
1290
1260static int __init reipl_init(void) 1291static int __init reipl_init(void)
1261{ 1292{
1262 int rc; 1293 int rc;
@@ -1278,10 +1309,7 @@ static int __init reipl_init(void)
1278 rc = reipl_nss_init(); 1309 rc = reipl_nss_init();
1279 if (rc) 1310 if (rc)
1280 return rc; 1311 return rc;
1281 rc = reipl_set_type(ipl_info.type); 1312 return reipl_type_init();
1282 if (rc)
1283 return rc;
1284 return 0;
1285} 1313}
1286 1314
1287static struct shutdown_action __refdata reipl_action = { 1315static struct shutdown_action __refdata reipl_action = {
diff --git a/arch/s390/kernel/os_info.c b/arch/s390/kernel/os_info.c
new file mode 100644
index 00000000000..bbe522672e0
--- /dev/null
+++ b/arch/s390/kernel/os_info.c
@@ -0,0 +1,169 @@
1/*
2 * OS info memory interface
3 *
4 * Copyright IBM Corp. 2012
5 * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com>
6 */
7
8#define KMSG_COMPONENT "os_info"
9#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
10
11#include <linux/crash_dump.h>
12#include <linux/kernel.h>
13#include <asm/checksum.h>
14#include <asm/lowcore.h>
15#include <asm/system.h>
16#include <asm/os_info.h>
17
18/*
19 * OS info structure has to be page aligned
20 */
21static struct os_info os_info __page_aligned_data;
22
23/*
24 * Compute checksum over OS info structure
25 */
26u32 os_info_csum(struct os_info *os_info)
27{
28 int size = sizeof(*os_info) - offsetof(struct os_info, version_major);
29 return csum_partial(&os_info->version_major, size, 0);
30}
31
32/*
33 * Add crashkernel info to OS info and update checksum
34 */
35void os_info_crashkernel_add(unsigned long base, unsigned long size)
36{
37 os_info.crashkernel_addr = (u64)(unsigned long)base;
38 os_info.crashkernel_size = (u64)(unsigned long)size;
39 os_info.csum = os_info_csum(&os_info);
40}
41
42/*
43 * Add OS info entry and update checksum
44 */
45void os_info_entry_add(int nr, void *ptr, u64 size)
46{
47 os_info.entry[nr].addr = (u64)(unsigned long)ptr;
48 os_info.entry[nr].size = size;
49 os_info.entry[nr].csum = csum_partial(ptr, size, 0);
50 os_info.csum = os_info_csum(&os_info);
51}
52
53/*
54 * Initialize OS info struture and set lowcore pointer
55 */
56void __init os_info_init(void)
57{
58 void *ptr = &os_info;
59
60 os_info.version_major = OS_INFO_VERSION_MAJOR;
61 os_info.version_minor = OS_INFO_VERSION_MINOR;
62 os_info.magic = OS_INFO_MAGIC;
63 os_info.csum = os_info_csum(&os_info);
64 copy_to_absolute_zero(&S390_lowcore.os_info, &ptr, sizeof(ptr));
65}
66
67#ifdef CONFIG_CRASH_DUMP
68
69static struct os_info *os_info_old;
70
71/*
72 * Allocate and copy OS info entry from oldmem
73 */
74static void os_info_old_alloc(int nr, int align)
75{
76 unsigned long addr, size = 0;
77 char *buf, *buf_align, *msg;
78 u32 csum;
79
80 addr = os_info_old->entry[nr].addr;
81 if (!addr) {
82 msg = "not available";
83 goto fail;
84 }
85 size = os_info_old->entry[nr].size;
86 buf = kmalloc(size + align - 1, GFP_KERNEL);
87 if (!buf) {
88 msg = "alloc failed";
89 goto fail;
90 }
91 buf_align = PTR_ALIGN(buf, align);
92 if (copy_from_oldmem(buf_align, (void *) addr, size)) {
93 msg = "copy failed";
94 goto fail_free;
95 }
96 csum = csum_partial(buf_align, size, 0);
97 if (csum != os_info_old->entry[nr].csum) {
98 msg = "checksum failed";
99 goto fail_free;
100 }
101 os_info_old->entry[nr].addr = (u64)(unsigned long)buf_align;
102 msg = "copied";
103 goto out;
104fail_free:
105 kfree(buf);
106fail:
107 os_info_old->entry[nr].addr = 0;
108out:
109 pr_info("entry %i: %s (addr=0x%lx size=%lu)\n",
110 nr, msg, addr, size);
111}
112
113/*
114 * Initialize os info and os info entries from oldmem
115 */
116static void os_info_old_init(void)
117{
118 static int os_info_init;
119 unsigned long addr;
120
121 if (os_info_init)
122 return;
123 if (!OLDMEM_BASE)
124 goto fail;
125 if (copy_from_oldmem(&addr, &S390_lowcore.os_info, sizeof(addr)))
126 goto fail;
127 if (addr == 0 || addr % PAGE_SIZE)
128 goto fail;
129 os_info_old = kzalloc(sizeof(*os_info_old), GFP_KERNEL);
130 if (!os_info_old)
131 goto fail;
132 if (copy_from_oldmem(os_info_old, (void *) addr, sizeof(*os_info_old)))
133 goto fail_free;
134 if (os_info_old->magic != OS_INFO_MAGIC)
135 goto fail_free;
136 if (os_info_old->csum != os_info_csum(os_info_old))
137 goto fail_free;
138 if (os_info_old->version_major > OS_INFO_VERSION_MAJOR)
139 goto fail_free;
140 os_info_old_alloc(OS_INFO_VMCOREINFO, 1);
141 os_info_old_alloc(OS_INFO_REIPL_BLOCK, 1);
142 os_info_old_alloc(OS_INFO_INIT_FN, PAGE_SIZE);
143 pr_info("crashkernel: addr=0x%lx size=%lu\n",
144 (unsigned long) os_info_old->crashkernel_addr,
145 (unsigned long) os_info_old->crashkernel_size);
146 os_info_init = 1;
147 return;
148fail_free:
149 kfree(os_info_old);
150fail:
151 os_info_init = 1;
152 os_info_old = NULL;
153}
154
155/*
156 * Return pointer to os infor entry and its size
157 */
158void *os_info_old_entry(int nr, unsigned long *size)
159{
160 os_info_old_init();
161
162 if (!os_info_old)
163 return NULL;
164 if (!os_info_old->entry[nr].addr)
165 return NULL;
166 *size = (unsigned long) os_info_old->entry[nr].size;
167 return (void *)(unsigned long)os_info_old->entry[nr].addr;
168}
169#endif
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 9a3edb5f2c9..38e751278bf 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -62,6 +62,7 @@
62#include <asm/ebcdic.h> 62#include <asm/ebcdic.h>
63#include <asm/kvm_virtio.h> 63#include <asm/kvm_virtio.h>
64#include <asm/diag.h> 64#include <asm/diag.h>
65#include <asm/os_info.h>
65#include "entry.h" 66#include "entry.h"
66 67
67long psw_kernel_bits = PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_ASC_PRIMARY | 68long psw_kernel_bits = PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_ASC_PRIMARY |
@@ -778,6 +779,7 @@ static void __init reserve_crashkernel(void)
778 pr_info("Reserving %lluMB of memory at %lluMB " 779 pr_info("Reserving %lluMB of memory at %lluMB "
779 "for crashkernel (System RAM: %luMB)\n", 780 "for crashkernel (System RAM: %luMB)\n",
780 crash_size >> 20, crash_base >> 20, memory_end >> 20); 781 crash_size >> 20, crash_base >> 20, memory_end >> 20);
782 os_info_crashkernel_add(crash_base, crash_size);
781#endif 783#endif
782} 784}
783 785
@@ -1057,6 +1059,7 @@ void __init setup_arch(char **cmdline_p)
1057 1059
1058 parse_early_param(); 1060 parse_early_param();
1059 1061
1062 os_info_init();
1060 setup_ipl(); 1063 setup_ipl();
1061 setup_memory_end(); 1064 setup_memory_end();
1062 setup_addressing_mode(); 1065 setup_addressing_mode();
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index d15b6c93708..3b9e5c9f4c0 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -41,6 +41,7 @@
41#include <asm/sclp.h> 41#include <asm/sclp.h>
42#include <asm/vdso.h> 42#include <asm/vdso.h>
43#include <asm/debug.h> 43#include <asm/debug.h>
44#include <asm/os_info.h>
44#include "entry.h" 45#include "entry.h"
45 46
46enum { 47enum {
@@ -826,6 +827,17 @@ void __noreturn cpu_die(void)
826 827
827#endif /* CONFIG_HOTPLUG_CPU */ 828#endif /* CONFIG_HOTPLUG_CPU */
828 829
830static void smp_call_os_info_init_fn(void)
831{
832 int (*init_fn)(void);
833 unsigned long size;
834
835 init_fn = os_info_old_entry(OS_INFO_INIT_FN, &size);
836 if (!init_fn)
837 return;
838 init_fn();
839}
840
829void __init smp_prepare_cpus(unsigned int max_cpus) 841void __init smp_prepare_cpus(unsigned int max_cpus)
830{ 842{
831 /* request the 0x1201 emergency signal external interrupt */ 843 /* request the 0x1201 emergency signal external interrupt */
@@ -834,6 +846,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
834 /* request the 0x1202 external call external interrupt */ 846 /* request the 0x1202 external call external interrupt */
835 if (register_external_interrupt(0x1202, do_ext_call_interrupt) != 0) 847 if (register_external_interrupt(0x1202, do_ext_call_interrupt) != 0)
836 panic("Couldn't request external interrupt 0x1202"); 848 panic("Couldn't request external interrupt 0x1202");
849 smp_call_os_info_init_fn();
837 smp_detect_cpus(); 850 smp_detect_cpus();
838} 851}
839 852