[PATCH 3/3] netpoll: kgdb-over-ethernet

From: Matt Mackall
Date: Wed Sep 10 2003 - 02:49:07 EST


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(-)

diff -puN drivers/net/kgdb_eth.c~kgdb-netpoll drivers/net/kgdb_eth.c
--- l/drivers/net/kgdb_eth.c~kgdb-netpoll 2003-09-10 02:34:15.000000000 -0500
+++ l-mpm/drivers/net/kgdb_eth.c 2003-09-10 02:34:16.000000000 -0500
@@ -7,36 +7,26 @@
*
* Twiddled for 2.6 by Robert Walsh <rjwalsh@xxxxxxxxxxxx>
* and wangdi <wangdi@xxxxxxxxxxxxx>.
+ *
+ * Refactored for netpoll API by Matt Mackall <mpm@xxxxxxxxxxx>
+ *
*/

-#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);
diff -puN include/linux/netdevice.h~kgdb-netpoll include/linux/netdevice.h
--- l/include/linux/netdevice.h~kgdb-netpoll 2003-09-10 02:34:15.000000000 -0500
+++ l-mpm/include/linux/netdevice.h 2003-09-10 02:34:16.000000000 -0500
@@ -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
diff -puN ./arch/i386/kernel/kgdb_stub.c~kgdb-netpoll ./arch/i386/kernel/kgdb_stub.c
--- l/./arch/i386/kernel/kgdb_stub.c~kgdb-netpoll 2003-09-10 02:34:15.000000000 -0500
+++ l-mpm/./arch/i386/kernel/kgdb_stub.c 2003-09-10 02:34:16.000000000 -0500
@@ -138,8 +138,6 @@ extern int eth_getDebugChar(void); /*
extern void eth_flushDebugChar(void); /* flush pending characters */
extern void kgdb_eth_set_trapmode(int);
extern void kgdb_eth_reply_arp(void); /*send arp request */
-extern volatile int kgdb_eth_is_initializing;
-

/************************************************************************/
/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
@@ -281,13 +279,13 @@ malloc(int size)

/*
* I/O dispatch functions...
- * Based upon kgdb_eth, either call the ethernet
+ * Based upon kgdboe, either call the ethernet
* handler or the serial one..
*/
void
putDebugChar(int c)
{
- if (kgdb_eth == -1) {
+ if (!kgdboe) {
tty_putDebugChar(c);
} else {
eth_putDebugChar(c);
@@ -297,7 +295,7 @@ putDebugChar(int c)
int
getDebugChar(void)
{
- if (kgdb_eth == -1) {
+ if (!kgdboe) {
return tty_getDebugChar();
} else {
return eth_getDebugChar();
@@ -307,7 +305,7 @@ getDebugChar(void)
void
flushDebugChar(void)
{
- if (kgdb_eth == -1) {
+ if (!kgdboe) {
tty_flushDebugChar();
} else {
eth_flushDebugChar();
@@ -494,7 +492,7 @@ putpacket(char *buffer)

/* $<packet info>#<checksum>. */

- if (kgdb_eth == -1) {
+ if (!kgdboe) {
do {
if (remote_debug)
printk("T:%s\n", buffer);
@@ -1281,9 +1279,8 @@ kgdb_handle_exception(int exceptionVecto

__asm__("movl %%cr2,%0":"=r" (address));

- if (kgdb_eth != -1) {
+ if (kgdboe)
kgdb_eth_set_trapmode(1);
- }

kgdb_local_irq_save(flags);

@@ -1526,13 +1523,8 @@ kgdb_handle_exception(int exceptionVecto
remcomOutBuffer[2] = hexchars[signo % 16];
remcomOutBuffer[3] = 0;

- if (kgdb_eth_is_initializing) {
- kgdb_eth_is_initializing = 0;
- } else {
- putpacket(remcomOutBuffer);
- }
+ putpacket(remcomOutBuffer);

- kgdb_eth_reply_arp();
while (1 == 1) {
error = 0;
remcomOutBuffer[0] = 0;
@@ -1689,7 +1681,7 @@ kgdb_handle_exception(int exceptionVecto

newPC = regs.eip;

- if (kgdb_eth != -1) {
+ if (kgdboe) {
kgdb_eth_set_trapmode(0);
}

@@ -2430,63 +2422,3 @@ typedef int gdb_debug_hook(int exception
int signo, int err_code, struct pt_regs *linux_regs);
gdb_debug_hook *linux_debug_hook = &kgdb_handle_exception; /* histerical reasons... */

-static int __init kgdb_opt_kgdbeth(char *str)
-{
- kgdb_eth = simple_strtoul(str, NULL, 10);
- return 1;
-}
-
-static int __init kgdb_opt_kgdbeth_remoteip(char *str)
-{
- kgdb_remoteip = in_aton(str);
- return 1;
-}
-
-static int __init kgdb_opt_kgdbeth_listenport(char *str)
-{
- kgdb_listenport = simple_strtoul(str, NULL, 10);
- kgdb_sendport = kgdb_listenport - 1;
- return 1;
-}
-
-static int __init parse_hw_addr(char *str, unsigned char *addr)
-{
- int i;
- char *p;
-
- p = str;
- i = 0;
- while(1)
- {
- unsigned int c;
-
- sscanf(p, "%x:", &c);
- addr[i++] = c;
- while((*p != 0) && (*p != ':')) {
- p++;
- }
- if (*p == 0) {
- break;
- }
- p++;
- }
-
- return 1;
-}
-
-static int __init kgdb_opt_kgdbeth_remotemac(char *str)
-{
- return parse_hw_addr(str, kgdb_remotemac);
-}
-static int __init kgdb_opt_kgdbeth_localmac(char *str)
-{
- return parse_hw_addr(str, kgdb_localmac);
-}
-
-
-__setup("gdbeth=", kgdb_opt_kgdbeth);
-__setup("gdbeth_remoteip=", kgdb_opt_kgdbeth_remoteip);
-__setup("gdbeth_listenport=", kgdb_opt_kgdbeth_listenport);
-__setup("gdbeth_remotemac=", kgdb_opt_kgdbeth_remotemac);
-__setup("gdbeth_localmac=", kgdb_opt_kgdbeth_localmac);
-
diff -puN ./include/asm/kgdb.h~kgdb-netpoll ./include/asm/kgdb.h
--- l/./include/asm/kgdb.h~kgdb-netpoll 2003-09-10 02:34:15.000000000 -0500
+++ l-mpm/./include/asm/kgdb.h 2003-09-10 02:34:16.000000000 -0500
@@ -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
diff -puN arch/i386/lib/kgdb_serial.c~kgdb-netpoll arch/i386/lib/kgdb_serial.c
--- l/arch/i386/lib/kgdb_serial.c~kgdb-netpoll 2003-09-10 02:34:15.000000000 -0500
+++ l-mpm/arch/i386/lib/kgdb_serial.c 2003-09-10 02:34:16.000000000 -0500
@@ -386,7 +386,7 @@ static spinlock_t one_at_atime = SPIN_LO
static int __init
kgdb_enable_ints(void)
{
- if (kgdb_eth != -1) {
+ if (kgdboe) {
return 0;
}
if (gdb_async_info == NULL) {
diff -puN drivers/net/Makefile~kgdb-netpoll drivers/net/Makefile
--- l/drivers/net/Makefile~kgdb-netpoll 2003-09-10 02:34:16.000000000 -0500
+++ l-mpm/drivers/net/Makefile 2003-09-10 02:34:16.000000000 -0500
@@ -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
diff -puN Documentation/i386/kgdb/kgdbeth.txt~kgdb-netpoll Documentation/i386/kgdb/kgdbeth.txt
--- l/Documentation/i386/kgdb/kgdbeth.txt~kgdb-netpoll 2003-09-10 02:34:16.000000000 -0500
+++ l-mpm/Documentation/i386/kgdb/kgdbeth.txt 2003-09-10 02:34:16.000000000 -0500
@@ -6,16 +6,21 @@ Authors

Robert Walsh <rjwalsh@xxxxxxxxxxxx> (2.6 port)
wangdi <wangdi@xxxxxxxxxxxxx> (2.6 port)
+Matt Mackall <mpm@xxxxxxxxxxx> (netpoll api)
San Mehat (original 2.4 code)


Introduction
------------

-KGDB supports debugging over ethernet. Only a limited set of ethernet
-devices are supported right now, but adding support for new devices
-should not be too complicated. See "New Devices" below for details.
-
+KGDB supports debugging over ethernet (kgdboe) via polling of a given
+network interface. Most cards are supported automatically though some
+might need special attention when receiving packets. Debugging
+facilities are available as soon as the network driver and kgdboe have
+initialized. Unfortunately, this is too late in the boot process for
+debugging some issues, but works quite well for many others. This
+should not interfere with normal network usage and doesn't require a
+dedicated NIC.

Terminology
-----------
@@ -29,33 +34,25 @@ This document uses the following terms:
Usage
-----

-You need to use the following command-line options on the TARGET kernel:
-
- gdbeth=DEVICENUM
- gdbeth_remoteip=HOSTIPADDR
- gdbeth_remotemac=REMOTEMAC
- gdbeth_localmac=LOCALMAC
-
-kgdbeth=DEVICENUM sets the ethernet device number to listen on for
-debugging packets. e.g. kgdbeth=0 listens on eth0.
-
-kgdbeth_remoteip=HOSTIPADDR sets the IP address of the HOST machine.
-Only packets originating from this IP address will be accepted by the
-debugger. e.g. kgdbeth_remoteip=192.168.2.2
+You need to use the following command-line option on the TARGET kernel:

-kgdbeth_remotemac=REMOTEMAC sets the ethernet address of the HOST machine.
-e.g. kgdbeth_remotemac=00:07:70:12:4E:F5
+ kgdboe=[tgt-port]@<tgt-ip>/[dev],[host-port]@<host-ip>/[host-macaddr]

-kgdbeth_localmac=LOCALMAC sets the ethernet address of the TARGET machine.
-e.g. kgdbeth_localmac=00:10:9F:18:21:3C
+ where
+ tgt-port source for UDP packets (defaults to 6443)
+ tgt-ip source IP to use (interface address)
+ dev network interface (eth0)
+ host-port HOST UDP port (6442) (not really used)
+ host-ip IP address for HOST machine
+ host-macaddr ethernet MAC address for HOST (ff:ff:ff:ff:ff:ff)

-You can also set the following command-line option on the TARGET kernel:
+ examples:

- kgdbeth_listenport=PORT
+ kgdboe=7000@xxxxxxxxxxx/wlan0,7001@xxxxxxxxxxx/00:05:3C:04:47:5D
+ kgdboe=@xxxxxxxxxxx/,@192.168.0.2/

-kgdbeth_listenport sets the UDP port to listen on for gdb debugging
-packets. The default value is "6443". e.g. kgdbeth_listenport=7654
-causes the kernel to listen on UDP port 7654 for debugging packets.
+Only packets originating from the configured HOST IP address will be
+accepted by the debugger.

On the HOST side, run gdb as normal and use a remote UDP host as the
target:
@@ -72,47 +69,15 @@ target:

You can now continue as if you were debugging over a serial line.

-Observations
-------------
-
-I've used this with NFS and various other network applications (ssh,
-etc.) and it's doesn't appear to interfere with their operation in
-any way. It doesn't seem to effect the NIC it uses - i.e. you don't
-need a dedicated NIC for this.
-
Limitations
-----------

-In the inital release of this code you _must_ break into the system with the
-debugger by hand, early after boot, as described above.
-
-Otherwise, the first time the kernel tries to enter the debugger (say, via an
-oops or a BUG), the kgdb stub will doublefault and die because things aren't
-fully set up yet.
-
-Supported devices
------------------
-
-Right now, the following drivers are supported:
-
- e100 driver (drivers/net/e100/*)
- 3c59x driver (drivers/net/3c59x.c)
-
-
-New devices
------------
-
-Supporting a new device is straightforward. Just add a "poll" routine to
-the driver and hook it into the poll_controller field in the netdevice
-structure. For an example, look in drivers/net/3c59x.c and search
-for CONFIG_KGDB (two places.)
-
-The poll routine is usually quite simple - it's usually enough to just
-disable interrupts, call the device's interrupt routine and re-enable
-interrupts again.
-
+The current release of this code is exclusive of using kgdb on a
+serial interface, so you must boot without the kgdboe option to use
+serial debugging.

Bug reports
-----------

-Send bug reports to Robert Walsh <rjwalsh@xxxxxxxxxxxx>.
+Send bug reports to Robert Walsh <rjwalsh@xxxxxxxxxxxx> and Matt
+Mackall <mpm@xxxxxxxxxxx>.

_


--
Matt Mackall : http://www.selenic.com : of or relating to the moon
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/