netpoll: kgdb-over-ethernet
Subsystems (3)
PATCH 3/3 netpoll: kgdb-over-ethernet
This is also against test5-mm1
This patch refactors kgdb-over-ethernet to use the netpoll API and removes the obsoleted CONFIG_NET_POLL_CONTROLLER code. It also cleans up some minor rough edges. Works with most NICs with no special drivers.
l-mpm/./arch/i386/kernel/kgdb_stub.c | 84 ----- l-mpm/./include/asm/kgdb.h | 7 l-mpm/Documentation/i386/kgdb/kgdbeth.txt | 88 +---- l-mpm/arch/i386/lib/kgdb_serial.c | 2 l-mpm/drivers/net/Makefile | 3 l-mpm/drivers/net/kgdb_eth.c | 452 ++++-------------------------- l-mpm/include/linux/netdevice.h | 3 7 files changed, 100 insertions(+), 539 deletions(-)
drivers/net/kgdb_eth.c renamed from drivers/net/kgdb_eth.c~kgdb-netpoll +61 -391
@@ -7,36 +7,26 @@* * Twiddled for 2.6 by Robert Walsh <[email protected]> * and wangdi <[email protected]>. +* +* Refactored for netpoll API by Matt Mackall <[email protected]> +* */ -#include <linux/module.h> -#include <linux/errno.h> -#include <linux/signal.h> #include <linux/sched.h> -#include <linux/timer.h> #include <linux/interrupt.h> #include <linux/config.h> -#include <linux/major.h> #include <linux/string.h> -#include <linux/fcntl.h> -#include <linux/termios.h> -#include <asm/kgdb.h> -#include <linux/if_ether.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/delay.h> -#include <net/tcp.h> -#include <net/udp.h> +#include <linux/netpoll.h> #include <asm/system.h> +#include <asm/kgdb.h> #include <asm/io.h> -#include <asm/segment.h> #include <asm/bitops.h> #include <asm/system.h> #include <asm/irq.h> #include <asm/atomic.h> +#define GDB_BUF_SIZE 512/* power of 2, please */ static char kgdb_buf[GDB_BUF_SIZE ] ;
@@ -44,26 +34,29 @@ static int kgdb_buf_in_inx ;static atomic_t kgdb_buf_in_cnt ;static int kgdb_buf_out_inx ; +#define ETH_QUEUE_SIZE 256 +static char eth_queue[ETH_QUEUE_SIZE ]; +static int outgoing_queue; +extern void set_debug_traps (void ) ;/* GDB routine */ extern void breakpoint (void ); -unsigned int kgdb_remoteip =0 ; -unsigned short kgdb_listenport =6443 ; -unsigned short kgdb_sendport=6442 ; -int kgdb_eth =-1 ;/* Default tty mode */ -unsigned char kgdb_remotemac[6 ] = {0xff ,0xff ,0xff ,0xff ,0xff ,0xff }; -unsigned char kgdb_localmac[6 ] = {0xff ,0xff ,0xff ,0xff ,0xff ,0xff }; -volatile int kgdb_eth_is_initializing =0 ; -int kgdb_eth_need_breakpoint[NR_CPUS ]; +int kgdboe =0 ;/* Default tty mode */ +int kgdb_eth_need_breakpoint[NR_CPUS ]; -struct net_device *kgdb_netdevice =NULL ; +static void rx_hook (struct netpoll *np,int port,char *msg,int len); -/* -* Get a char if available, return -1 if nothing available. -* Empty the receive buffer first, then look at the interface hardware. -*/ -static int -read_char (void ) +static struct netpoll np = { + .name ="kgdboe" , + .dev_name ="eth0" , + .rx_hook = rx_hook, + .local_port =6443 , + .remote_port =6442 , + .local_mac = {0xff ,0xff ,0xff ,0xff ,0xff ,0xff }, + .remote_mac = {0xff ,0xff ,0xff ,0xff ,0xff ,0xff }, +}; + +static int read_char (void ) {/* intr routine has queued chars */ if (atomic_read (&kgdb_buf_in_cnt) !=0 )
@@ -79,283 +72,30 @@ read_char(void)return -1 ;/* no data */ } -/* -* Wait until the interface can accept a char, then write it. -*/ -static void -write_buffer (char *buf,int len) +static void write_buffer (char *buf,int len) { -int total_len, eth_len, ip_len, udp_len; -struct in_device *in_dev; -struct sk_buff *skb; -struct udphdr *udph; -struct iphdr *iph; -struct ethhdr *eth; - -if (!(in_dev = (struct in_device *) kgdb_netdevice->ip_ptr)) { -panic ("No in_device available for interface!\n" ); - } - -if (!(in_dev->ifa_list)) { -panic ("No interface address set for interface!\n" ); - } - - udp_len = len +sizeof (struct udphdr ); - ip_len = eth_len = udp_len +sizeof (struct iphdr ); - total_len = eth_len +ETH_HLEN ; - -if (!(skb =alloc_skb (total_len,GFP_ATOMIC ))) { +if (!np.dev)return ; - } -atomic_set (&skb->users,1 ); -skb_reserve (skb, total_len - len); - -memcpy (skb->data, (unsigned char *) buf, len); - skb->len += len; - - udph = (struct udphdr *)skb_push (skb,sizeof (*udph)); - udph->source =htons (kgdb_listenport); - udph->dest =htons (kgdb_sendport); - udph->len =htons (udp_len); - udph->check =0 ; - - iph = (struct iphdr *)skb_push (skb,sizeof (*iph)); - iph->version =4 ; - iph->ihl =5 ; - iph->tos =0 ; - iph->tot_len =htons (ip_len); - iph->id =0 ; - iph->frag_off =0 ; - iph->ttl =64 ; - iph->protocol =IPPROTO_UDP ; - iph->check =0 ; - iph->saddr = in_dev->ifa_list->ifa_address; - iph->daddr = kgdb_remoteip; - iph->check =ip_fast_csum ((unsigned char *)iph, iph->ihl); - - eth = (struct ethhdr *)skb_push (skb,ETH_HLEN ); - eth->h_proto =htons (ETH_P_IP ); -memcpy (eth->h_source, kgdb_localmac, kgdb_netdevice->addr_len); -memcpy (eth->h_dest, kgdb_remotemac, kgdb_netdevice->addr_len); - -repeat: -spin_lock (&kgdb_netdevice->xmit_lock); - kgdb_netdevice->xmit_lock_owner =smp_processor_id (); - -if (netif_queue_stopped (kgdb_netdevice)) { - kgdb_netdevice->xmit_lock_owner =-1 ; -spin_unlock (&kgdb_netdevice->xmit_lock); - - kgdb_netdevice->poll_controller (kgdb_netdevice); - goto repeat; - } - - kgdb_netdevice->hard_start_xmit (skb, kgdb_netdevice); - kgdb_netdevice->xmit_lock_owner =-1 ; -spin_unlock (&kgdb_netdevice->xmit_lock); +netpoll_send_udp (&np, buf, len); }/* -* In the interrupt state the target machine will not respond to any -* arp requests, so handle them here. -*/ - -static struct sk_buff *send_skb =NULL ; - -void -kgdb_eth_reply_arp (void ) -{ -if (send_skb) { -spin_lock (&kgdb_netdevice->xmit_lock); - kgdb_netdevice->xmit_lock_owner =smp_processor_id (); - kgdb_netdevice->hard_start_xmit (send_skb, kgdb_netdevice); - kgdb_netdevice->xmit_lock_owner =-1 ; -spin_unlock (&kgdb_netdevice->xmit_lock); - send_skb =NULL ; - } -} - -static int -make_arp_request (struct sk_buff *skb) -{ -struct arphdr *arp; -unsigned char *arp_ptr; -int type =ARPOP_REPLY ; -int ptype =ETH_P_ARP ; -u32 sip, tip; -unsigned char *sha, *tha; -struct in_device *in_dev = (struct in_device *) kgdb_netdevice->ip_ptr; - -/* No arp on this interface */ - -if (kgdb_netdevice->flags &IFF_NOARP ) { -return 0 ; - } - -if (!pskb_may_pull (skb, (sizeof (struct arphdr ) + - (2 * kgdb_netdevice->addr_len) + - (2 *sizeof (u32))))) { -return 0 ; - } - - skb->h.raw = skb->nh.raw = skb->data; - arp = skb->nh.arph; - -if ((arp->ar_hrd !=htons (ARPHRD_ETHER ) && - arp->ar_hrd !=htons (ARPHRD_IEEE802 )) || - arp->ar_pro !=htons (ETH_P_IP )) { -return 0 ; - } - -/* Understand only these message types */ - -if (arp->ar_op !=htons (ARPOP_REQUEST )) { -return 0 ; - } - -/* Extract fields */ - - arp_ptr= (unsigned char *)(arp+1 ); - sha = arp_ptr; - arp_ptr += kgdb_netdevice->addr_len; -memcpy (&sip, arp_ptr,4 ); - arp_ptr +=4 ; - tha = arp_ptr; - arp_ptr += kgdb_netdevice->addr_len; -memcpy (&tip, arp_ptr,4 ); - -if (tip != in_dev->ifa_list->ifa_address) { -return 0 ; - } - -if (kgdb_remoteip != sip) { -return 0 ; - } - -/* -* Check for bad requests for 127.x.x.x and requests for multicast -* addresses. If this is one such, delete it. -*/ - -if (LOOPBACK (tip) ||MULTICAST (tip)) { -return 0 ; - } - -/* reply to the ARP request */ - - send_skb =alloc_skb (sizeof (struct arphdr ) +2 * (kgdb_netdevice->addr_len +4 ) +LL_RESERVED_SPACE (kgdb_netdevice),GFP_ATOMIC ); - -if (send_skb ==NULL ) { -return 0 ; - } - -skb_reserve (send_skb,LL_RESERVED_SPACE (kgdb_netdevice)); - send_skb->nh.raw = send_skb->data; - arp = (struct arphdr *)skb_put (send_skb,sizeof (struct arphdr ) +2 * (kgdb_netdevice->addr_len +4 )); - send_skb->dev = kgdb_netdevice; - send_skb->protocol =htons (ETH_P_ARP ); - -/* Fill the device header for the ARP frame */ - -if (kgdb_netdevice->hard_header && - kgdb_netdevice->hard_header (send_skb, kgdb_netdevice, ptype, - kgdb_remotemac, kgdb_localmac, - send_skb->len) <0 ) { -kfree_skb (send_skb); -return 0 ; - } - -/* -* Fill out the arp protocol part. -* -* we only support ethernet device type, -* which (according to RFC 1390) should always equal 1 (Ethernet). -*/ - - arp->ar_hrd =htons (kgdb_netdevice->type); - arp->ar_pro =htons (ETH_P_IP ); - - arp->ar_hln = kgdb_netdevice->addr_len; - arp->ar_pln =4 ; - arp->ar_op =htons (type); - - arp_ptr=(unsigned char *)(arp +1 ); - -memcpy (arp_ptr, kgdb_netdevice->dev_addr, kgdb_netdevice->addr_len); - arp_ptr += kgdb_netdevice->addr_len; -memcpy (arp_ptr, &tip,4 ); - arp_ptr +=4 ; -memcpy (arp_ptr, kgdb_localmac, kgdb_netdevice->addr_len); - arp_ptr += kgdb_netdevice->addr_len; -memcpy (arp_ptr, &sip,4 ); -return 0 ; -} - - -/* * Accept an skbuff from net_device layer and add the payload onto * kgdb buffer -* -* When the kgdb stub routine getDebugChar() is called it draws characters -* out of the buffer until it is empty and then reads directly from the -* serial port. -* -* We do not attempt to write chars from the interrupt routine since -* the stubs do all of that via putDebugChar() which writes one byte -* after waiting for the interface to become ready. -* -* The debug stubs like to run with interrupts disabled since, after all, -* they run as a consequence of a breakpoint in the kernel. -* -* NOTE: Return value of 1 means it was for us and is an indication to -* the calling driver to destroy the sk_buff and not send it up the stack. */ -int -kgdb_net_interrupt (struct sk_buff *skb) +static void rx_hook (struct netpoll *np,int port,char *msg,int len) { -unsigned char chr; -struct iphdr *iph = (struct iphdr *)skb->data; -struct udphdr *udph= (struct udphdr *)(skb->data+(iph->ihl<<2 )); -unsigned char *data = (unsigned char *) udph +sizeof (struct udphdr ); -int len; -int i; - -if ((kgdb_eth !=-1 ) && (!kgdb_netdevice) && - (iph->protocol ==IPPROTO_UDP ) && - (be16_to_cpu (udph->dest) == kgdb_listenport)) { - kgdb_sendport =be16_to_cpu (udph->source); - -while (kgdb_eth_is_initializing) - ; -if (!kgdb_netdevice) -kgdb_eth_hook (); -if (!kgdb_netdevice) { -/* Lets not even try again. */ - kgdb_eth =-1 ; -return 0 ; - } - } -if (!kgdb_netdevice) { -return 0 ; - } -if (skb->protocol ==__constant_htons (ETH_P_ARP ) && !send_skb) { -make_arp_request (skb); -return 0 ; - } -if (iph->protocol !=IPPROTO_UDP ) { -return 0 ; - } +int i, chr; -if (be16_to_cpu (udph->dest) != kgdb_listenport) { -return 0 ; - } + np->remote_port = port; - len = (be16_to_cpu (iph->tot_len) - - (sizeof (struct udphdr ) +sizeof (struct iphdr ))); +/* This is gdb trying to attach */ +if (!kgdb_eth_is_trapped () && len ==8 && !strncmp (msg,"$Hc-1#09" ,8 )) + kgdb_eth_need_breakpoint[smp_processor_id ()] =1 ;for (i =0 ; i < len; i++) { - chr = data[i]; + chr = msg[i];if (chr ==3 ) { kgdb_eth_need_breakpoint[smp_processor_id ()] =1 ;continue ;
@@ -371,112 +111,55 @@ kgdb_net_interrupt(struct sk_buff *skb) kgdb_buf_in_inx &= (GDB_BUF_SIZE -1 );atomic_inc (&kgdb_buf_in_cnt); } - -if (!kgdb_netdevice->kgdb_is_trapped) { -/* -* If a new gdb instance is trying to attach, we need to -* break here. -*/ -if (!strncmp (data,"$Hc-1#09" ,8 )) - kgdb_eth_need_breakpoint[smp_processor_id ()] =1 ; - } -return 1 ; } -EXPORT_SYMBOL (kgdb_net_interrupt); -int -kgdb_eth_hook (void ) +static int option_setup (char *opt) { -char kgdb_netdev[16 ]; -extern void kgdb_respond_ok (void ); - -if (kgdb_remotemac[0 ] ==0xff ) { -panic ("ERROR! 'gdbeth_remotemac' option not set!\n" ); - } -if (kgdb_localmac[0 ] ==0xff ) { -panic ("ERROR! 'gdbeth_localmac' option not set!\n" ); - } -if (kgdb_remoteip ==0 ) { -panic ("ERROR! 'gdbeth_remoteip' option not set!\n" ); - } +return netpoll_parse_options (&np, opt); +} -sprintf (kgdb_netdev,"eth%d" ,kgdb_eth); +__setup ("kgdboe=" , option_setup); +static int init_kgdboe (void ) +{#ifdef CONFIG_SMP if (num_online_cpus () >CONFIG_NO_KGDB_CPUS ) {printk ("kgdb: too manu cpus. Cannot enable debugger with more than %d cpus\n" ,CONFIG_NO_KGDB_CPUS );return -1 ; }#endif -for (kgdb_netdevice = dev_base; - kgdb_netdevice !=NULL ; - kgdb_netdevice = kgdb_netdevice->next) { -if (strncmp (kgdb_netdevice->name, kgdb_netdev,IFNAMSIZ ) ==0 ) { -break ; - } - } -if (!kgdb_netdevice) { -printk ("KGDB NET : Unable to find interface %s\n" ,kgdb_netdev); -return -ENODEV ; - } -/* -* Call GDB routine to setup the exception vectors for the debugger -*/ set_debug_traps (); -/* -* Call the breakpoint() routine in GDB to start the debugging -* session. -*/ - kgdb_eth_is_initializing =1 ; - kgdb_eth_need_breakpoint[smp_processor_id ()] =1 ; +if (!np.remote_ip ||netpoll_setup (&np)) +return 1 ; + + kgdboe =1 ; + +printk (KERN_INFO "kgdb: debugging over ethernet enabled\n" ); +return 0 ; } -/* -* getDebugChar -* -* This is a GDB stub routine. It waits for a character from the -* serial interface and then returns it. If there is no serial -* interface connection then it returns a bogus value which will -* almost certainly cause the system to hang. -*/ -int -eth_getDebugChar (void ) +int eth_getDebugChar (void ) { -volatile int chr; +int chr; + +while ((chr =read_char ()) <0 ) +netpoll_poll (&np); -while ((chr =read_char ()) <0 ) { -if (send_skb) { -kgdb_eth_reply_arp (); - } -if (kgdb_netdevice->poll_controller) { - kgdb_netdevice->poll_controller (kgdb_netdevice); - }else { -printk ("KGDB NET: Error - Device %s is not supported!\n" , kgdb_netdevice->name); -panic ("Please add support for kgdb net to this driver" ); - } - }return chr; } -#define ETH_QUEUE_SIZE 256 -static char eth_queue[ETH_QUEUE_SIZE ]; -static int outgoing_queue; - -void -eth_flushDebugChar (void ) +void eth_flushDebugChar (void ) {if (outgoing_queue) {write_buffer (eth_queue, outgoing_queue); - outgoing_queue =0 ; } } -static void -put_char_on_queue (int chr) +static void put_char_on_queue (int chr) { eth_queue[outgoing_queue++] = chr;if (outgoing_queue ==ETH_QUEUE_SIZE )
@@ -485,33 +168,20 @@ put_char_on_queue(int chr) } } -/* -* eth_putDebugChar -* -* This is a GDB stub routine. It waits until the interface is ready -* to transmit a char and then sends it. -*/ -void -eth_putDebugChar (int chr) +void eth_putDebugChar (int chr) {put_char_on_queue (chr);/* this routine will wait */ } -void -kgdb_eth_set_trapmode (int mode) +void kgdb_eth_set_trapmode (int mode) { -if (!kgdb_netdevice) { -return ; - } - kgdb_netdevice->kgdb_is_trapped = mode; + np.need_arp = mode; } -int -kgdb_eth_is_trapped () +int kgdb_eth_is_trapped () { -if (!kgdb_netdevice) { -return 0 ; - } -return kgdb_netdevice->kgdb_is_trapped; +return np.need_arp; } +EXPORT_SYMBOL (kgdb_eth_is_trapped); +module_init (init_kgdboe);
include/linux/netdevice.h renamed from include/linux/netdevice.h~kgdb-netpoll +0 -3
@@ -459,9 +459,6 @@ struct net_device/* bridge stuff */ struct net_bridge_port *br_port; -#ifdef CONFIG_KGDB -int kgdb_is_trapped; -#endif #ifdef CONFIG_NET_POLL_CONTROLLER void (*poll_controller)(struct net_device *);#endif
./arch/i386/kernel/kgdb_stub.c renamed from ./arch/i386/kernel/kgdb_stub.c~kgdb-netpoll +8 -76
142 lines not on this page · raw message
./include/asm/kgdb.h renamed from ./include/asm/kgdb.h~kgdb-netpoll +1 -6
@@ -21,12 +21,7 @@ extern void breakpoint(void);struct sk_buff ; -extern int kgdb_eth; -extern unsigned kgdb_remoteip; -extern unsigned short kgdb_listenport; -extern unsigned short kgdb_sendport; -extern unsigned char kgdb_remotemac[6 ]; -extern unsigned char kgdb_localmac[6 ]; +extern int kgdboe;extern int kgdb_eth_need_breakpoint[];extern int kgdb_tty_hook (void );
diff -puN drivers/net/3c59x.c~kgdb-netpoll drivers/net/3c59x.c
diff -puN drivers/net/eepro100.c~kgdb-netpoll drivers/net/eepro100.c diff -puN drivers/net/tlan.c~kgdb-netpoll drivers/net/tlan.c
diff -puN drivers/net/tulip/tulip_core.c~kgdb-netpoll drivers/net/tulip/tulip_core.c
arch/i386/lib/kgdb_serial.c renamed from arch/i386/lib/kgdb_serial.c~kgdb-netpoll +1 -1
@@ -386,7 +386,7 @@ static spinlock_t one_at_atime = SPIN_LOstatic int __init kgdb_enable_ints (void ) { -if (kgdb_eth !=-1 ) { +if (kgdboe) {return 0 ; }if (gdb_async_info ==NULL ) {
drivers/net/Makefile renamed from drivers/net/Makefile~kgdb-netpoll +1 -2
@@ -32,8 +32,6 @@ obj-$(CONFIG_BMAC) += bmac.o obj-$(CONFIG_OAKNET) += oaknet.o 8390.o -obj-$(CONFIG_KGDB) += kgdb_eth.o - obj-$(CONFIG_DGRS) += dgrs.o obj-$(CONFIG_RCPCI) += rcpci.o obj-$(CONFIG_VORTEX) += 3c59x.o
@@ -199,3 +197,4 @@ include $(TOPDIR)/drivers/usb/net/Makefi # Must come after all NICs it might use obj-$(CONFIG_NETCONSOLE) += netconsole.o +obj-$(CONFIG_KGDB) += kgdb_eth.o
Documentation/i386/kgdb/kgdbeth.txt renamed from Documentation/i386/kgdb/kgdbeth.txt~kgdb-netpoll +28 -63
124 lines not on this page · raw message
_
Signature · 1 line
Matt Mackall : http://www.selenic.com : of or relating to the moon