There is a bug in the CKRM CPU scheduler. This has been reported to the
[linux-2.6.git] / drivers / net / netdump.c
1 /*
2  *  linux/drivers/net/netdump.c
3  *
4  *  Copyright (C) 2001  Ingo Molnar <mingo@redhat.com>
5  *  Copyright (C) 2002  Red Hat, Inc.
6  *  Copyright (C) 2004  Red Hat, Inc.
7  *
8  *  This file contains the implementation of an IRQ-safe, crash-safe
9  *  kernel console implementation that outputs kernel messages to the
10  *  network.
11  *
12  * Modification history:
13  *
14  * 2001-09-17    started by Ingo Molnar.
15  * 2002-03-14    simultaneous syslog packet option by Michael K. Johnson
16  * 2004-04-07    port to 2.6 netpoll facility by Dave Anderson and Jeff Moyer.
17  */
18 #include <linux/mm.h>
19 #include <linux/init.h>
20 #include <linux/delay.h>
21 #include <linux/random.h>
22 #include <linux/reboot.h>
23 #include <linux/module.h>
24 #include <linux/moduleparam.h>
25 #include <asm/unaligned.h>
26 #include <asm/pgtable.h>
27 #include <linux/console.h>
28 #include <linux/smp_lock.h>
29 #include <linux/elf.h>
30 #include <linux/preempt.h>
31
32 #include "netdump.h"
33 #include <linux/netpoll.h>
34
35 /*
36  *  prototypes.
37  */
38 void netdump_rx(struct netpoll *np, short source, char *data, int dlen);
39 static void send_netdump_msg(struct netpoll *np, const char *msg, unsigned int msg_len, reply_t *reply);
40 static void send_netdump_mem(struct netpoll *np, req_t *req);
41 static void netdump_startup_handshake(struct netpoll *np);
42 static void netpoll_netdump(struct pt_regs *regs);
43 static void netpoll_start_netdump(struct pt_regs *regs);
44
45
46 #include <asm/netdump.h>
47
48
49 #undef Dprintk
50 #define DEBUG 0
51 #if DEBUG
52 # define Dprintk(x...) printk(KERN_INFO x)
53 #else
54 # define Dprintk(x...)
55 #endif
56
57 MODULE_AUTHOR("Maintainer: Dave Anderson <anderson@redhat.com>");
58 MODULE_DESCRIPTION("Network kernel crash dump module");
59 MODULE_LICENSE("GPL");
60
61 static char config[256];
62 module_param_string(netdump, config, 256, 0);
63 MODULE_PARM_DESC(netdump, 
64      " netdump=[src-port]@[src-ip]/[dev],[tgt-port]@<tgt-ip>/[tgt-macaddr]\n");
65
66 static u32 magic1, magic2;
67 module_param(magic1, uint, 000);
68 module_param(magic2, uint, 000);
69
70 static struct netpoll np = {
71         .name = "netdump",
72         .dev_name = "eth0",
73         .local_port = 6666,
74         .remote_port = 6666,
75         .remote_mac = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
76         .rx_hook = netdump_rx,
77         .dump_func = netpoll_start_netdump,
78 };
79
80
81 /*
82  * NOTE: security depends on the trusted path between the netconsole
83  *       server and netconsole client, since none of the packets are
84  *       encrypted. The random magic number protects the protocol
85  *       against spoofing.
86  */
87 static u64 netdump_magic;
88
89 static spinlock_t req_lock = SPIN_LOCK_UNLOCKED;
90 static int nr_req = 0;
91 static LIST_HEAD(request_list);
92
93 static unsigned long long t0, jiffy_cycles;
94 void *netdump_stack;
95
96
97 static void update_jiffies(void)
98 {
99         static unsigned long long prev_tick;
100         platform_timestamp(t0);
101
102         /* maintain jiffies in a polling fashion, based on rdtsc. */
103         if (t0 - prev_tick >= jiffy_cycles) {
104                 prev_tick += jiffy_cycles;
105                 jiffies++;
106         }
107 }
108
109 static void add_new_req(req_t *req)
110 {
111         unsigned long flags;
112
113         spin_lock_irqsave(&req_lock, flags);
114         list_add_tail(&req->list, &request_list);
115         nr_req++;
116         Dprintk("pending requests: %d.\n", nr_req);
117         spin_unlock_irqrestore(&req_lock, flags);
118 }
119
120 static req_t *get_new_req(void)
121 {
122         req_t *req = NULL;
123         unsigned long flags;
124
125         update_jiffies();
126
127         spin_lock_irqsave(&req_lock, flags);
128         if (nr_req) {
129                 req = list_entry(request_list.next, req_t, list);
130                 list_del(&req->list);
131                 nr_req--;
132         }
133         spin_unlock_irqrestore(&req_lock, flags);
134
135         return req;
136 }
137
138 static req_t *alloc_req(void)
139 {
140         req_t *req;
141
142         req = (req_t *) kmalloc(sizeof(*req), GFP_ATOMIC);
143         return req;
144 }
145
146 static inline void print_status (req_t *req)
147 {
148         static int count = 0;
149         static int prev_jiffies = 0;
150
151         if (jiffies/HZ != prev_jiffies/HZ) {
152                 prev_jiffies = jiffies;
153                 count++;
154                 switch (count & 3) {
155                         case 0: printk("%d(%ld)/\r", nr_req, jiffies); break;
156                         case 1: printk("%d(%ld)|\r", nr_req, jiffies); break;
157                         case 2: printk("%d(%ld)\\\r", nr_req, jiffies); break;
158                         case 3: printk("%d(%ld)-\r", nr_req, jiffies); break;
159                 }
160         }
161 }
162
163 void netdump_rx(struct netpoll *np, short source, char *data, int dlen)
164 {
165         req_t *req, *__req = (req_t *)data;
166
167         if (!netdump_mode)
168                 return;
169 #if DEBUG
170         {
171                 static int packet_count;
172                 Dprintk("        %d\r", ++packet_count);
173         }
174 #endif
175
176         if (dlen < NETDUMP_REQ_SIZE) {
177                 Dprintk("... netdump_rx: len not ok.\n");
178                 return;
179         }
180
181         req = alloc_req();
182         if (!req) {
183                 printk("no more RAM to allocate request - dropping it.\n");
184                 return;
185         }
186
187         req->magic = ntohl(__req->magic);
188         req->command = ntohl(__req->command);
189         req->from = ntohl(__req->from);
190         req->to = ntohl(__req->to);
191         req->nr = ntohl(__req->nr);
192
193         Dprintk("... netdump magic:   %08Lx.\n", req->magic);
194         Dprintk("... netdump command: %08x.\n", req->command);
195         Dprintk("... netdump from:    %08x.\n", req->from);
196         Dprintk("... netdump to:      %08x.\n", req->to);
197
198         add_new_req(req);
199         return;
200 }
201
202 #define MAX_MSG_LEN HEADER_LEN + 1024
203
204 static void send_netdump_msg(struct netpoll *np, const char *msg, unsigned int msg_len, reply_t *reply)
205 {
206         /* max len should be 1024 + HEADER_LEN */
207         static unsigned char netpoll_msg[MAX_MSG_LEN + 1];
208
209         if (msg_len + HEADER_LEN > MAX_MSG_LEN + 1) {
210                 printk("CODER ERROR!!! msg_len %ud too big for send msg\n",
211                        msg_len);
212                 for (;;) local_irq_disable();
213                 /* NOTREACHED */
214         }
215
216         netpoll_msg[0] = NETDUMP_VERSION;
217         put_unaligned(htonl(reply->nr), (u32 *) (&netpoll_msg[1]));
218         put_unaligned(htonl(reply->code), (u32 *) (&netpoll_msg[5]));
219         put_unaligned(htonl(reply->info), (u32 *) (&netpoll_msg[9]));
220         memcpy(&netpoll_msg[HEADER_LEN], msg, msg_len);
221
222         netpoll_send_udp(np, netpoll_msg, HEADER_LEN + msg_len);
223 }
224
225 static void send_netdump_mem(struct netpoll *np, req_t *req)
226 {
227         int i;
228         char *kaddr;
229         char str[1024];
230         struct page *page;
231         unsigned long nr = req->from;
232         int nr_chunks = PAGE_SIZE/1024;
233         reply_t reply;
234         
235         Dprintk(" ... send_netdump_mem\n");
236         reply.nr = req->nr;
237         reply.info = 0;
238         if (req->from >= platform_max_pfn()) {
239                 sprintf(str, "page %08lx is bigger than max page # %08lx!\n", 
240                         nr, platform_max_pfn());
241                 reply.code = REPLY_ERROR;
242                 send_netdump_msg(np, str, strlen(str), &reply);
243                 return;
244         }
245         if (page_is_ram(nr))
246                 page = pfn_to_page(nr);
247         else
248                 page = ZERO_PAGE(0);
249
250         kaddr = (char *)kmap_atomic(page, KM_NETDUMP);
251
252         for (i = 0; i < nr_chunks; i++) {
253                 unsigned int offset = i*1024;
254                 reply.code = REPLY_MEM;
255                 reply.info = offset;
256                 Dprintk(" ... send_netdump_mem: sending message\n");
257                 send_netdump_msg(np, kaddr + offset, 1024, &reply);
258                 Dprintk(" ... send_netdump_mem: sent message\n");
259         }
260
261         kunmap_atomic(kaddr, KM_NETDUMP);
262         Dprintk(" ... send_netdump_mem: returning\n");
263 }
264
265 /*
266  * This function waits for the client to acknowledge the receipt
267  * of the netdump startup reply, with the possibility of packets
268  * getting lost. We resend the startup packet if no ACK is received,
269  * after a 1 second delay.
270  *
271  * (The client can test the success of the handshake via the HELLO
272  * command, and send ACKs until we enter netdump mode.)
273  */
274 static void netdump_startup_handshake(struct netpoll *np)
275 {
276         char tmp[200];
277         reply_t reply;
278         req_t *req = NULL;
279         int i;
280
281 repeat:
282         sprintf(tmp, "NETDUMP start, waiting for start-ACK.\n");
283         reply.code = REPLY_START_NETDUMP;
284         reply.nr = 0;
285         reply.info = 0;
286
287         send_netdump_msg(np, tmp, strlen(tmp), &reply);
288
289         for (i = 0; i < 10000; i++) {
290                 // wait 1 sec.
291                 udelay(100);
292                 Dprintk("handshake: polling controller ...\n");
293                 netpoll_poll(np);
294                 req = get_new_req();
295                 if (req)
296                         break;
297         }
298         if (!req)
299                 goto repeat;
300         if (req->command != COMM_START_NETDUMP_ACK) {
301                 kfree(req);
302                 goto repeat;
303         }
304         kfree(req);
305
306         printk("NETDUMP START!\n");
307 }
308
309 static char cpus_frozen[NR_CPUS] = { 0 }; 
310
311 static void freeze_cpu (void * dummy)
312 {
313         cpus_frozen[smp_processor_id()] = 1;
314         for (;;) local_irq_disable();
315 }
316
317 static void netpoll_start_netdump(struct pt_regs *regs)
318 {
319         int i;
320         unsigned long flags;
321
322         /*
323          *  The netdump code is not re-entrant for several reasons.  Most
324          *  immediately, we will switch to the base of our stack and 
325          *  overwrite all of our call history.
326          */
327         if (netdump_mode) {
328                 printk(KERN_ERR
329                 "netpoll_start_netdump: called recursively.  rebooting.\n");
330                 mdelay(3000);
331                 machine_restart(NULL);
332         }
333         netdump_mode = 1;
334
335         local_irq_save(flags);
336         preempt_disable();
337
338         smp_call_function(freeze_cpu, NULL, 1, -1);
339         mdelay(3000);
340         for (i = 0; i < NR_CPUS; i++) {
341                 if (cpus_frozen[i])
342                         printk("CPU#%d is frozen.\n", i);
343                 else if (i == smp_processor_id())
344                         printk("CPU#%d is executing netdump.\n", i);
345         }
346
347         /*
348          *  Some platforms may want to execute netdump on its own stack.
349          */
350         platform_start_netdump(netdump_stack, regs);
351
352         preempt_enable_no_resched();
353         local_irq_restore(flags);
354         return;
355 }
356
357 static void netpoll_netdump(struct pt_regs *regs)
358 {
359         reply_t reply;
360         char tmp[200];
361         struct pt_regs myregs;
362         req_t *req;
363
364         /*
365          * Just in case we are crashing within the networking code
366          * ... attempt to fix up.
367          */
368         netpoll_reset_locks(&np);
369         platform_fix_regs();
370         platform_timestamp(t0);
371         netpoll_set_trap(1); /* bypass networking stack */
372
373         printk("< netdump activated - performing handshake with the server. >\n");
374         netdump_startup_handshake(&np);
375
376         printk("< handshake completed - listening for dump requests. >\n");
377
378         while (netdump_mode) {
379                 local_irq_disable();
380                 Dprintk("main netdump loop: polling controller ...\n");
381                 netpoll_poll(&np);
382
383                 req = get_new_req();
384                 if (!req)
385                         continue;
386
387                 Dprintk("got new req, command %d.\n", req->command);
388                 print_status(req);
389                 switch (req->command) {
390                 case COMM_NONE:
391                         Dprintk("got NO command.\n");
392                         break;
393
394                 case COMM_SEND_MEM:
395                         Dprintk("got MEM command.\n");
396                         send_netdump_mem(&np, req);
397                         break;
398
399                 case COMM_EXIT:
400                         Dprintk("got EXIT command.\n");
401                         netdump_mode = 0;
402                         netpoll_set_trap(0);
403                         break;
404
405                 case COMM_REBOOT:
406                         Dprintk("got REBOOT command.\n");
407                         printk("netdump: rebooting in 3 seconds.\n");
408                         mdelay(3000);
409                         machine_restart(NULL);
410                         break;
411
412                 case COMM_HELLO:
413                         sprintf(tmp, "Hello, this is netdump version 0.%02d\n",
414                                 NETDUMP_VERSION);
415                         reply.code = REPLY_HELLO;
416                         reply.nr = req->nr;
417                         reply.info = NETDUMP_VERSION;
418                         send_netdump_msg(&np, tmp, strlen(tmp), &reply);
419                         break;
420
421                 case COMM_GET_PAGE_SIZE:
422                         sprintf(tmp, "PAGE_SIZE: %ld\n", PAGE_SIZE);
423                         reply.code = REPLY_PAGE_SIZE;
424                         reply.nr = req->nr;
425                         reply.info = PAGE_SIZE;
426                         send_netdump_msg(&np, tmp, strlen(tmp), &reply);
427                         break;
428
429                 case COMM_GET_REGS:
430                 {
431                         char *tmp2 = tmp;
432                         elf_gregset_t elf_regs;
433
434                         reply.code = REPLY_REGS;
435                         reply.nr = req->nr;
436                         reply.info = platform_max_pfn();
437                         tmp2 = tmp + sprintf(tmp, "Sending register info.\n");
438                         ELF_CORE_COPY_REGS(elf_regs, (&myregs));
439                         memcpy(tmp2, &elf_regs, sizeof(elf_regs));
440                         Dprintk("netdump: sending regs\n");
441                         send_netdump_msg(&np, tmp, 
442                                 strlen(tmp) + sizeof(elf_regs), &reply);
443                         Dprintk("netdump: sent regs\n");
444                         break;
445                 }
446
447                 case COMM_GET_NR_PAGES:
448                         reply.code = REPLY_NR_PAGES;
449                         reply.nr = req->nr;
450                         reply.info = platform_max_pfn();
451                         sprintf(tmp, 
452                                 "Number of pages: %ld\n", platform_max_pfn());
453                         send_netdump_msg(&np, tmp, strlen(tmp), &reply);
454                         break;
455
456                 case COMM_SHOW_STATE:
457                         /* send response first */
458                         reply.code = REPLY_SHOW_STATE;
459                         reply.nr = req->nr;
460                         reply.info = 0;
461
462                         send_netdump_msg(&np, tmp, strlen(tmp), &reply);
463
464                         netdump_mode = 0;
465                         if (regs)
466                                 show_regs(regs);
467                         show_state();
468                         show_mem();
469                         netdump_mode = 1;
470                         break;
471
472                 default:
473                         reply.code = REPLY_ERROR;
474                         reply.nr = req->nr;
475                         reply.info = req->command;
476                         Dprintk("got UNKNOWN command!\n");
477                         sprintf(tmp, "Got unknown command code %d!\n", 
478                                 req->command);
479                         send_netdump_msg(&np, tmp, strlen(tmp), &reply);
480                         break;
481                 }
482                 kfree(req);
483                 req = NULL;
484         }
485         sprintf(tmp, "NETDUMP end.\n");
486         reply.code = REPLY_END_NETDUMP;
487         reply.nr = 0;
488         reply.info = 0;
489         send_netdump_msg(&np, tmp, strlen(tmp), &reply);
490         printk("NETDUMP END!\n");
491 }
492
493 static int option_setup(char *opt)
494 {
495         return !netpoll_parse_options(&np, opt);
496 }
497
498 __setup("netdump=", option_setup);
499
500 static int init_netdump(void)
501 {
502         int configured = 0;
503
504         if (strlen(config))
505                 configured = option_setup(config);
506
507         if (!configured) {
508                 printk(KERN_ERR "netdump: not configured, aborting\n");
509                 return -EINVAL;
510         }
511
512         if (netpoll_setup(&np))
513                 return -EINVAL;
514
515         if (magic1 || magic2)
516                 netdump_magic = magic1 + (((u64)magic2)<<32);
517
518         /*
519          *  Allocate a separate stack for netdump.
520          */
521         platform_init_stack(&netdump_stack);
522
523         printk(KERN_INFO "netdump: network crash dump enabled\n");
524         return 0;
525 }
526
527 static void cleanup_netdump(void)
528 {
529         netpoll_cleanup(&np);
530         platform_cleanup_stack(netdump_stack);
531 }
532
533 module_init(init_netdump);
534 module_exit(cleanup_netdump);