1 // SPDX-License-Identifier: GPL-2.0
3 * OS info memory interface
5 * Copyright IBM Corp. 2012
6 * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com>
9 #define KMSG_COMPONENT "os_info"
10 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
12 #include <linux/crash_dump.h>
13 #include <linux/kernel.h>
14 #include <linux/slab.h>
15 #include <asm/checksum.h>
16 #include <asm/lowcore.h>
17 #include <asm/os_info.h>
20 * OS info structure has to be page aligned
22 static struct os_info os_info __page_aligned_data
;
25 * Compute checksum over OS info structure
27 u32
os_info_csum(struct os_info
*os_info
)
29 int size
= sizeof(*os_info
) - offsetof(struct os_info
, version_major
);
30 return (__force u32
)csum_partial(&os_info
->version_major
, size
, 0);
34 * Add crashkernel info to OS info and update checksum
36 void os_info_crashkernel_add(unsigned long base
, unsigned long size
)
38 os_info
.crashkernel_addr
= (u64
)(unsigned long)base
;
39 os_info
.crashkernel_size
= (u64
)(unsigned long)size
;
40 os_info
.csum
= os_info_csum(&os_info
);
44 * Add OS info entry and update checksum
46 void os_info_entry_add(int nr
, void *ptr
, u64 size
)
48 os_info
.entry
[nr
].addr
= (u64
)(unsigned long)ptr
;
49 os_info
.entry
[nr
].size
= size
;
50 os_info
.entry
[nr
].csum
= (__force u32
)csum_partial(ptr
, size
, 0);
51 os_info
.csum
= os_info_csum(&os_info
);
55 * Initialize OS info struture and set lowcore pointer
57 void __init
os_info_init(void)
61 os_info
.version_major
= OS_INFO_VERSION_MAJOR
;
62 os_info
.version_minor
= OS_INFO_VERSION_MINOR
;
63 os_info
.magic
= OS_INFO_MAGIC
;
64 os_info
.csum
= os_info_csum(&os_info
);
65 mem_assign_absolute(S390_lowcore
.os_info
, (unsigned long) ptr
);
68 #ifdef CONFIG_CRASH_DUMP
70 static struct os_info
*os_info_old
;
73 * Allocate and copy OS info entry from oldmem
75 static void os_info_old_alloc(int nr
, int align
)
77 unsigned long addr
, size
= 0;
78 char *buf
, *buf_align
, *msg
;
81 addr
= os_info_old
->entry
[nr
].addr
;
83 msg
= "not available";
86 size
= os_info_old
->entry
[nr
].size
;
87 buf
= kmalloc(size
+ align
- 1, GFP_KERNEL
);
92 buf_align
= PTR_ALIGN(buf
, align
);
93 if (copy_oldmem_kernel(buf_align
, (void *) addr
, size
)) {
97 csum
= (__force u32
)csum_partial(buf_align
, size
, 0);
98 if (csum
!= os_info_old
->entry
[nr
].csum
) {
99 msg
= "checksum failed";
102 os_info_old
->entry
[nr
].addr
= (u64
)(unsigned long)buf_align
;
108 os_info_old
->entry
[nr
].addr
= 0;
110 pr_info("entry %i: %s (addr=0x%lx size=%lu)\n",
111 nr
, msg
, addr
, size
);
115 * Initialize os info and os info entries from oldmem
117 static void os_info_old_init(void)
119 static int os_info_init
;
126 if (copy_oldmem_kernel(&addr
, &S390_lowcore
.os_info
, sizeof(addr
)))
128 if (addr
== 0 || addr
% PAGE_SIZE
)
130 os_info_old
= kzalloc(sizeof(*os_info_old
), GFP_KERNEL
);
133 if (copy_oldmem_kernel(os_info_old
, (void *) addr
,
134 sizeof(*os_info_old
)))
136 if (os_info_old
->magic
!= OS_INFO_MAGIC
)
138 if (os_info_old
->csum
!= os_info_csum(os_info_old
))
140 if (os_info_old
->version_major
> OS_INFO_VERSION_MAJOR
)
142 os_info_old_alloc(OS_INFO_VMCOREINFO
, 1);
143 os_info_old_alloc(OS_INFO_REIPL_BLOCK
, 1);
144 pr_info("crashkernel: addr=0x%lx size=%lu\n",
145 (unsigned long) os_info_old
->crashkernel_addr
,
146 (unsigned long) os_info_old
->crashkernel_size
);
157 * Return pointer to os infor entry and its size
159 void *os_info_old_entry(int nr
, unsigned long *size
)
165 if (!os_info_old
->entry
[nr
].addr
)
167 *size
= (unsigned long) os_info_old
->entry
[nr
].size
;
168 return (void *)(unsigned long)os_info_old
->entry
[nr
].addr
;