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 <asm/checksum.h>
14 #include <asm/lowcore.h>
15 #include <asm/os_info.h>
18 * OS info structure has to be page aligned
20 static struct os_info os_info __page_aligned_data
;
23 * Compute checksum over OS info structure
25 u32
os_info_csum(struct os_info
*os_info
)
27 int size
= sizeof(*os_info
) - offsetof(struct os_info
, version_major
);
28 return csum_partial(&os_info
->version_major
, size
, 0);
32 * Add crashkernel info to OS info and update checksum
34 void os_info_crashkernel_add(unsigned long base
, unsigned long size
)
36 os_info
.crashkernel_addr
= (u64
)(unsigned long)base
;
37 os_info
.crashkernel_size
= (u64
)(unsigned long)size
;
38 os_info
.csum
= os_info_csum(&os_info
);
42 * Add OS info entry and update checksum
44 void os_info_entry_add(int nr
, void *ptr
, u64 size
)
46 os_info
.entry
[nr
].addr
= (u64
)(unsigned long)ptr
;
47 os_info
.entry
[nr
].size
= size
;
48 os_info
.entry
[nr
].csum
= csum_partial(ptr
, size
, 0);
49 os_info
.csum
= os_info_csum(&os_info
);
53 * Initialize OS info struture and set lowcore pointer
55 void __init
os_info_init(void)
59 os_info
.version_major
= OS_INFO_VERSION_MAJOR
;
60 os_info
.version_minor
= OS_INFO_VERSION_MINOR
;
61 os_info
.magic
= OS_INFO_MAGIC
;
62 os_info
.csum
= os_info_csum(&os_info
);
63 mem_assign_absolute(S390_lowcore
.os_info
, (unsigned long) ptr
);
66 #ifdef CONFIG_CRASH_DUMP
68 static struct os_info
*os_info_old
;
71 * Allocate and copy OS info entry from oldmem
73 static void os_info_old_alloc(int nr
, int align
)
75 unsigned long addr
, size
= 0;
76 char *buf
, *buf_align
, *msg
;
79 addr
= os_info_old
->entry
[nr
].addr
;
81 msg
= "not available";
84 size
= os_info_old
->entry
[nr
].size
;
85 buf
= kmalloc(size
+ align
- 1, GFP_KERNEL
);
90 buf_align
= PTR_ALIGN(buf
, align
);
91 if (copy_from_oldmem(buf_align
, (void *) addr
, size
)) {
95 csum
= csum_partial(buf_align
, size
, 0);
96 if (csum
!= os_info_old
->entry
[nr
].csum
) {
97 msg
= "checksum failed";
100 os_info_old
->entry
[nr
].addr
= (u64
)(unsigned long)buf_align
;
106 os_info_old
->entry
[nr
].addr
= 0;
108 pr_info("entry %i: %s (addr=0x%lx size=%lu)\n",
109 nr
, msg
, addr
, size
);
113 * Initialize os info and os info entries from oldmem
115 static void os_info_old_init(void)
117 static int os_info_init
;
124 if (copy_from_oldmem(&addr
, &S390_lowcore
.os_info
, sizeof(addr
)))
126 if (addr
== 0 || addr
% PAGE_SIZE
)
128 os_info_old
= kzalloc(sizeof(*os_info_old
), GFP_KERNEL
);
131 if (copy_from_oldmem(os_info_old
, (void *) addr
, sizeof(*os_info_old
)))
133 if (os_info_old
->magic
!= OS_INFO_MAGIC
)
135 if (os_info_old
->csum
!= os_info_csum(os_info_old
))
137 if (os_info_old
->version_major
> OS_INFO_VERSION_MAJOR
)
139 os_info_old_alloc(OS_INFO_VMCOREINFO
, 1);
140 os_info_old_alloc(OS_INFO_REIPL_BLOCK
, 1);
141 pr_info("crashkernel: addr=0x%lx size=%lu\n",
142 (unsigned long) os_info_old
->crashkernel_addr
,
143 (unsigned long) os_info_old
->crashkernel_size
);
154 * Return pointer to os infor entry and its size
156 void *os_info_old_entry(int nr
, unsigned long *size
)
162 if (!os_info_old
->entry
[nr
].addr
)
164 *size
= (unsigned long) os_info_old
->entry
[nr
].size
;
165 return (void *)(unsigned long)os_info_old
->entry
[nr
].addr
;