2 * OS info memory interface
4 * Copyright IBM Corp. 2012
5 * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com>
8 #define KMSG_COMPONENT "os_info"
9 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
11 #include <linux/crash_dump.h>
12 #include <linux/kernel.h>
13 #include <linux/slab.h>
14 #include <asm/checksum.h>
15 #include <asm/lowcore.h>
16 #include <asm/os_info.h>
19 * OS info structure has to be page aligned
21 static struct os_info os_info __page_aligned_data
;
24 * Compute checksum over OS info structure
26 u32
os_info_csum(struct os_info
*os_info
)
28 int size
= sizeof(*os_info
) - offsetof(struct os_info
, version_major
);
29 return (__force u32
)csum_partial(&os_info
->version_major
, size
, 0);
33 * Add crashkernel info to OS info and update checksum
35 void os_info_crashkernel_add(unsigned long base
, unsigned long size
)
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
);
43 * Add OS info entry and update checksum
45 void os_info_entry_add(int nr
, void *ptr
, u64 size
)
47 os_info
.entry
[nr
].addr
= (u64
)(unsigned long)ptr
;
48 os_info
.entry
[nr
].size
= size
;
49 os_info
.entry
[nr
].csum
= (__force u32
)csum_partial(ptr
, size
, 0);
50 os_info
.csum
= os_info_csum(&os_info
);
54 * Initialize OS info struture and set lowcore pointer
56 void __init
os_info_init(void)
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 mem_assign_absolute(S390_lowcore
.os_info
, (unsigned long) ptr
);
67 #ifdef CONFIG_CRASH_DUMP
69 static struct os_info
*os_info_old
;
72 * Allocate and copy OS info entry from oldmem
74 static void os_info_old_alloc(int nr
, int align
)
76 unsigned long addr
, size
= 0;
77 char *buf
, *buf_align
, *msg
;
80 addr
= os_info_old
->entry
[nr
].addr
;
82 msg
= "not available";
85 size
= os_info_old
->entry
[nr
].size
;
86 buf
= kmalloc(size
+ align
- 1, GFP_KERNEL
);
91 buf_align
= PTR_ALIGN(buf
, align
);
92 if (copy_oldmem_kernel(buf_align
, (void *) addr
, size
)) {
96 csum
= (__force u32
)csum_partial(buf_align
, size
, 0);
97 if (csum
!= os_info_old
->entry
[nr
].csum
) {
98 msg
= "checksum failed";
101 os_info_old
->entry
[nr
].addr
= (u64
)(unsigned long)buf_align
;
107 os_info_old
->entry
[nr
].addr
= 0;
109 pr_info("entry %i: %s (addr=0x%lx size=%lu)\n",
110 nr
, msg
, addr
, size
);
114 * Initialize os info and os info entries from oldmem
116 static void os_info_old_init(void)
118 static int os_info_init
;
125 if (copy_oldmem_kernel(&addr
, &S390_lowcore
.os_info
, sizeof(addr
)))
127 if (addr
== 0 || addr
% PAGE_SIZE
)
129 os_info_old
= kzalloc(sizeof(*os_info_old
), GFP_KERNEL
);
132 if (copy_oldmem_kernel(os_info_old
, (void *) addr
,
133 sizeof(*os_info_old
)))
135 if (os_info_old
->magic
!= OS_INFO_MAGIC
)
137 if (os_info_old
->csum
!= os_info_csum(os_info_old
))
139 if (os_info_old
->version_major
> OS_INFO_VERSION_MAJOR
)
141 os_info_old_alloc(OS_INFO_VMCOREINFO
, 1);
142 os_info_old_alloc(OS_INFO_REIPL_BLOCK
, 1);
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
);
156 * Return pointer to os infor entry and its size
158 void *os_info_old_entry(int nr
, unsigned long *size
)
164 if (!os_info_old
->entry
[nr
].addr
)
166 *size
= (unsigned long) os_info_old
->entry
[nr
].size
;
167 return (void *)(unsigned long)os_info_old
->entry
[nr
].addr
;