Commit c114728af2acdca0bd8b1d2f5792e393c775f5fc
Committed by
Martin Schwidefsky
1 parent
275c340941
Exists in
master
and in
7 other branches
[S390] add call home support
Signed-off-by: Hans-Joachim Picht <hans@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Showing 5 changed files with 254 additions and 1 deletions Side-by-side Diff
Documentation/sysctl/kernel.txt
... | ... | @@ -19,6 +19,7 @@ |
19 | 19 | show up in /proc/sys/kernel: |
20 | 20 | - acpi_video_flags |
21 | 21 | - acct |
22 | +- callhome [ S390 only ] | |
22 | 23 | - auto_msgmni |
23 | 24 | - core_pattern |
24 | 25 | - core_uses_pid |
... | ... | @@ -88,6 +89,21 @@ |
88 | 89 | That is, suspend accounting if there left <= 2% free; resume it |
89 | 90 | if we got >=4%; consider information about amount of free space |
90 | 91 | valid for 30 seconds. |
92 | + | |
93 | +============================================================== | |
94 | + | |
95 | +callhome: | |
96 | + | |
97 | +Controls the kernel's callhome behavior in case of a kernel panic. | |
98 | + | |
99 | +The s390 hardware allows an operating system to send a notification | |
100 | +to a service organization (callhome) in case of an operating system panic. | |
101 | + | |
102 | +When the value in this file is 0 (which is the default behavior) | |
103 | +nothing happens in case of a kernel panic. If this value is set to "1" | |
104 | +the complete kernel oops message is send to the IBM customer service | |
105 | +organization in case the mainframe the Linux operating system is running | |
106 | +on has a service contract with IBM. | |
91 | 107 | |
92 | 108 | ============================================================== |
93 | 109 |
drivers/s390/char/Kconfig
... | ... | @@ -82,6 +82,16 @@ |
82 | 82 | You should only select this option if you know what you are doing, |
83 | 83 | need this feature and intend to run your kernel in LPAR. |
84 | 84 | |
85 | +config SCLP_ASYNC | |
86 | + tristate "Support for Call Home via Asynchronous SCLP Records" | |
87 | + depends on S390 | |
88 | + help | |
89 | + This option enables the call home function, which is able to inform | |
90 | + the service element and connected organisations about a kernel panic. | |
91 | + You should only select this option if you know what you are doing, | |
92 | + want for inform other people about your kernel panics, | |
93 | + need this feature and intend to run your kernel in LPAR. | |
94 | + | |
85 | 95 | config S390_TAPE |
86 | 96 | tristate "S/390 tape device support" |
87 | 97 | depends on CCW |
drivers/s390/char/Makefile
... | ... | @@ -16,6 +16,7 @@ |
16 | 16 | obj-$(CONFIG_SCLP_CONSOLE) += sclp_con.o |
17 | 17 | obj-$(CONFIG_SCLP_VT220_TTY) += sclp_vt220.o |
18 | 18 | obj-$(CONFIG_SCLP_CPI) += sclp_cpi.o |
19 | +obj-$(CONFIG_SCLP_ASYNC) += sclp_async.o | |
19 | 20 | |
20 | 21 | obj-$(CONFIG_ZVM_WATCHDOG) += vmwatchdog.o |
21 | 22 | obj-$(CONFIG_VMLOGRDR) += vmlogrdr.o |
drivers/s390/char/sclp.h
... | ... | @@ -27,6 +27,7 @@ |
27 | 27 | #define EVTYP_VT220MSG 0x1A |
28 | 28 | #define EVTYP_CONFMGMDATA 0x04 |
29 | 29 | #define EVTYP_SDIAS 0x1C |
30 | +#define EVTYP_ASYNC 0x0A | |
30 | 31 | |
31 | 32 | #define EVTYP_OPCMD_MASK 0x80000000 |
32 | 33 | #define EVTYP_MSG_MASK 0x40000000 |
... | ... | @@ -38,6 +39,7 @@ |
38 | 39 | #define EVTYP_VT220MSG_MASK 0x00000040 |
39 | 40 | #define EVTYP_CONFMGMDATA_MASK 0x10000000 |
40 | 41 | #define EVTYP_SDIAS_MASK 0x00000010 |
42 | +#define EVTYP_ASYNC_MASK 0x00400000 | |
41 | 43 | |
42 | 44 | #define GNRLMSGFLGS_DOM 0x8000 |
43 | 45 | #define GNRLMSGFLGS_SNDALRM 0x4000 |
44 | 46 | |
... | ... | @@ -85,11 +87,11 @@ |
85 | 87 | } __attribute__((packed)); |
86 | 88 | |
87 | 89 | extern u64 sclp_facilities; |
88 | - | |
89 | 90 | #define SCLP_HAS_CHP_INFO (sclp_facilities & 0x8000000000000000ULL) |
90 | 91 | #define SCLP_HAS_CHP_RECONFIG (sclp_facilities & 0x2000000000000000ULL) |
91 | 92 | #define SCLP_HAS_CPU_INFO (sclp_facilities & 0x0800000000000000ULL) |
92 | 93 | #define SCLP_HAS_CPU_RECONFIG (sclp_facilities & 0x0400000000000000ULL) |
94 | + | |
93 | 95 | |
94 | 96 | struct gds_subvector { |
95 | 97 | u8 length; |
drivers/s390/char/sclp_async.c
1 | +/* | |
2 | + * Enable Asynchronous Notification via SCLP. | |
3 | + * | |
4 | + * Copyright IBM Corp. 2009 | |
5 | + * Author(s): Hans-Joachim Picht <hans@linux.vnet.ibm.com> | |
6 | + * | |
7 | + */ | |
8 | + | |
9 | +#include <linux/init.h> | |
10 | +#include <linux/module.h> | |
11 | +#include <linux/device.h> | |
12 | +#include <linux/stat.h> | |
13 | +#include <linux/string.h> | |
14 | +#include <linux/ctype.h> | |
15 | +#include <linux/kmod.h> | |
16 | +#include <linux/err.h> | |
17 | +#include <linux/errno.h> | |
18 | +#include <linux/proc_fs.h> | |
19 | +#include <linux/sysctl.h> | |
20 | +#include <linux/utsname.h> | |
21 | +#include "sclp.h" | |
22 | + | |
23 | +static int callhome_enabled; | |
24 | +static struct sclp_req *request; | |
25 | +static struct sclp_async_sccb *sccb; | |
26 | +static int sclp_async_send_wait(char *message); | |
27 | +static struct ctl_table_header *callhome_sysctl_header; | |
28 | +static DEFINE_SPINLOCK(sclp_async_lock); | |
29 | +static char nodename[64]; | |
30 | +#define SCLP_NORMAL_WRITE 0x00 | |
31 | + | |
32 | +struct async_evbuf { | |
33 | + struct evbuf_header header; | |
34 | + u64 reserved; | |
35 | + u8 rflags; | |
36 | + u8 empty; | |
37 | + u8 rtype; | |
38 | + u8 otype; | |
39 | + char comp_id[12]; | |
40 | + char data[3000]; /* there is still some space left */ | |
41 | +} __attribute__((packed)); | |
42 | + | |
43 | +struct sclp_async_sccb { | |
44 | + struct sccb_header header; | |
45 | + struct async_evbuf evbuf; | |
46 | +} __attribute__((packed)); | |
47 | + | |
48 | +static struct sclp_register sclp_async_register = { | |
49 | + .send_mask = EVTYP_ASYNC_MASK, | |
50 | +}; | |
51 | + | |
52 | +static int call_home_on_panic(struct notifier_block *self, | |
53 | + unsigned long event, void *data) | |
54 | +{ | |
55 | + strncat(data, nodename, strlen(nodename)); | |
56 | + sclp_async_send_wait(data); | |
57 | + return NOTIFY_DONE; | |
58 | +} | |
59 | + | |
60 | +static struct notifier_block call_home_panic_nb = { | |
61 | + .notifier_call = call_home_on_panic, | |
62 | + .priority = INT_MAX, | |
63 | +}; | |
64 | + | |
65 | +static int proc_handler_callhome(ctl_table *ctl, int write, struct file *filp, | |
66 | + void __user *buffer, size_t *count, | |
67 | + loff_t *ppos) | |
68 | +{ | |
69 | + unsigned long val; | |
70 | + int len, rc; | |
71 | + char buf[2]; | |
72 | + | |
73 | + if (!*count | (*ppos && !write)) { | |
74 | + *count = 0; | |
75 | + return 0; | |
76 | + } | |
77 | + if (!write) { | |
78 | + len = sprintf(buf, "%d\n", callhome_enabled); | |
79 | + buf[len] = '\0'; | |
80 | + rc = copy_to_user(buffer, buf, sizeof(buf)); | |
81 | + if (rc != 0) | |
82 | + return -EFAULT; | |
83 | + } else { | |
84 | + len = *count; | |
85 | + rc = copy_from_user(buf, buffer, sizeof(buf)); | |
86 | + if (rc != 0) | |
87 | + return -EFAULT; | |
88 | + if (strict_strtoul(buf, 0, &val) != 0) | |
89 | + return -EINVAL; | |
90 | + if (val != 0 && val != 1) | |
91 | + return -EINVAL; | |
92 | + callhome_enabled = val; | |
93 | + } | |
94 | + *count = len; | |
95 | + *ppos += len; | |
96 | + return 0; | |
97 | +} | |
98 | + | |
99 | +static struct ctl_table callhome_table[] = { | |
100 | + { | |
101 | + .procname = "callhome", | |
102 | + .mode = 0644, | |
103 | + .proc_handler = &proc_handler_callhome, | |
104 | + }, | |
105 | + { .ctl_name = 0 } | |
106 | +}; | |
107 | + | |
108 | +static struct ctl_table kern_dir_table[] = { | |
109 | + { | |
110 | + .ctl_name = CTL_KERN, | |
111 | + .procname = "kernel", | |
112 | + .maxlen = 0, | |
113 | + .mode = 0555, | |
114 | + .child = callhome_table, | |
115 | + }, | |
116 | + { .ctl_name = 0 } | |
117 | +}; | |
118 | + | |
119 | +/* | |
120 | + * Function used to transfer asynchronous notification | |
121 | + * records which waits for send completion | |
122 | + */ | |
123 | +static int sclp_async_send_wait(char *message) | |
124 | +{ | |
125 | + struct async_evbuf *evb; | |
126 | + int rc; | |
127 | + unsigned long flags; | |
128 | + | |
129 | + if (!callhome_enabled) | |
130 | + return 0; | |
131 | + sccb->evbuf.header.type = EVTYP_ASYNC; | |
132 | + sccb->evbuf.rtype = 0xA5; | |
133 | + sccb->evbuf.otype = 0x00; | |
134 | + evb = &sccb->evbuf; | |
135 | + request->command = SCLP_CMDW_WRITE_EVENT_DATA; | |
136 | + request->sccb = sccb; | |
137 | + request->status = SCLP_REQ_FILLED; | |
138 | + strncpy(sccb->evbuf.data, message, sizeof(sccb->evbuf.data)); | |
139 | + /* | |
140 | + * Retain Queue | |
141 | + * e.g. 5639CC140 500 Red Hat RHEL5 Linux for zSeries (RHEL AS) | |
142 | + */ | |
143 | + strncpy(sccb->evbuf.comp_id, "000000000", sizeof(sccb->evbuf.comp_id)); | |
144 | + sccb->evbuf.header.length = sizeof(sccb->evbuf); | |
145 | + sccb->header.length = sizeof(sccb->evbuf) + sizeof(sccb->header); | |
146 | + sccb->header.function_code = SCLP_NORMAL_WRITE; | |
147 | + rc = sclp_add_request(request); | |
148 | + if (rc) | |
149 | + return rc; | |
150 | + spin_lock_irqsave(&sclp_async_lock, flags); | |
151 | + while (request->status != SCLP_REQ_DONE && | |
152 | + request->status != SCLP_REQ_FAILED) { | |
153 | + sclp_sync_wait(); | |
154 | + } | |
155 | + spin_unlock_irqrestore(&sclp_async_lock, flags); | |
156 | + if (request->status != SCLP_REQ_DONE) | |
157 | + return -EIO; | |
158 | + rc = ((struct sclp_async_sccb *) | |
159 | + request->sccb)->header.response_code; | |
160 | + if (rc != 0x0020) | |
161 | + return -EIO; | |
162 | + if (evb->header.flags != 0x80) | |
163 | + return -EIO; | |
164 | + return rc; | |
165 | +} | |
166 | + | |
167 | +static int __init sclp_async_init(void) | |
168 | +{ | |
169 | + int rc; | |
170 | + | |
171 | + rc = sclp_register(&sclp_async_register); | |
172 | + if (rc) | |
173 | + return rc; | |
174 | + callhome_sysctl_header = register_sysctl_table(kern_dir_table); | |
175 | + if (!callhome_sysctl_header) { | |
176 | + rc = -ENOMEM; | |
177 | + goto out_sclp; | |
178 | + } | |
179 | + if (!(sclp_async_register.sclp_receive_mask & EVTYP_ASYNC_MASK)) { | |
180 | + rc = -EOPNOTSUPP; | |
181 | + goto out_sclp; | |
182 | + } | |
183 | + rc = -ENOMEM; | |
184 | + request = kzalloc(sizeof(struct sclp_req), GFP_KERNEL); | |
185 | + if (!request) | |
186 | + goto out_sys; | |
187 | + sccb = (struct sclp_async_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA); | |
188 | + if (!sccb) | |
189 | + goto out_mem; | |
190 | + rc = atomic_notifier_chain_register(&panic_notifier_list, | |
191 | + &call_home_panic_nb); | |
192 | + if (rc) | |
193 | + goto out_mem; | |
194 | + | |
195 | + strncpy(nodename, init_utsname()->nodename, 64); | |
196 | + return 0; | |
197 | + | |
198 | +out_mem: | |
199 | + kfree(request); | |
200 | + free_page((unsigned long) sccb); | |
201 | +out_sys: | |
202 | + unregister_sysctl_table(callhome_sysctl_header); | |
203 | +out_sclp: | |
204 | + sclp_unregister(&sclp_async_register); | |
205 | + return rc; | |
206 | + | |
207 | +} | |
208 | +module_init(sclp_async_init); | |
209 | + | |
210 | +static void __exit sclp_async_exit(void) | |
211 | +{ | |
212 | + atomic_notifier_chain_unregister(&panic_notifier_list, | |
213 | + &call_home_panic_nb); | |
214 | + unregister_sysctl_table(callhome_sysctl_header); | |
215 | + sclp_unregister(&sclp_async_register); | |
216 | + free_page((unsigned long) sccb); | |
217 | + kfree(request); | |
218 | +} | |
219 | +module_exit(sclp_async_exit); | |
220 | + | |
221 | +MODULE_AUTHOR("Copyright IBM Corp. 2009"); | |
222 | +MODULE_AUTHOR("Hans-Joachim Picht <hans@linux.vnet.ibm.com>"); | |
223 | +MODULE_LICENSE("GPL"); | |
224 | +MODULE_DESCRIPTION("SCLP Asynchronous Notification Records"); |