void kgdboe_io_cleanup(void) { /* We don't check for race conditions between running code by other cores and unloading the module! There is always a small chance that unloading this module would cause a kernel panic because another core is executing a function hooked by us. As normally you don't need to load/unload this module all the time (just execute the 'detach' command in GDB and connect back when ready), we don't check for it here. */ kgdb_unregister_io_module(&kgdboe_io_ops); netpoll_wrapper_free(s_pKgdboeNetpoll); nethook_cleanup(); s_pKgdboeNetpoll = NULL; }
int kgdboe_io_init(const char *device_name, int port, const char *local_ip, bool force_single_core) { int err; u8 ipaddr[4]; spin_lock_init(&exception_lock); s_pKgdboeNetpoll = netpoll_wrapper_create(device_name, port, local_ip); if (!s_pKgdboeNetpoll) return -EINVAL; if (force_single_core) { force_single_cpu_mode(); } else if (!nethook_initialize(s_pKgdboeNetpoll->pDeviceWithHandler)) { printk(KERN_ERR "kgdboe: failed to guarantee cross-CPU network " "API synchronization. Aborting. Try enabling " "single-CPU mode.\n"); return -EINVAL; } err = kgdb_register_io_module(&kgdboe_io_ops); if (err != 0) { netpoll_wrapper_free(s_pKgdboeNetpoll); s_pKgdboeNetpoll = NULL; return err; } netpoll_wrapper_set_callback(s_pKgdboeNetpoll, kgdboe_rx_handler, NULL); memcpy(ipaddr, &ip_addr_as_int(s_pKgdboeNetpoll->netpoll_obj.local_ip), 4); printk(KERN_INFO "kgdboe: Successfully initialized. Use the following " "gdb command to attach:\n"); printk(KERN_INFO "\ttarget remote udp:%d.%d.%d.%d:%d\n", ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3], s_pKgdboeNetpoll->netpoll_obj.local_port); return 0; }
struct netpoll_wrapper *netpoll_wrapper_create(const char *pDeviceName, int localPort, const char *pOptionalLocalIp) { struct net_device *pDevice; struct netpoll_wrapper *pResult; int localIp; int err; if (!pDeviceName || !localPort) { printk(KERN_ERR "kgdboe: cannot create a netpoll wrapper without a device name\n"); return NULL; } pDevice = dev_get_by_name(&init_net, pDeviceName); if (!pDevice) { printk(KERN_ERR "kgdboe: Cannot find network device by name: %s\n", pDeviceName); return NULL; } if (pOptionalLocalIp) { localIp = in_aton(pOptionalLocalIp); if (!localIp) { printk(KERN_ERR "kgdboe: Invalid local IP: %s\n", pOptionalLocalIp); return NULL; } } else { if (!pDevice->ip_ptr) { printk(KERN_ERR "kgdboe: %s does not have an in_device associated. Cannot get default IP address.\n", pDeviceName); return NULL; } if (!pDevice->ip_ptr->ifa_list) { printk(KERN_ERR "kgdboe: %s does not have a in_ifaddr struct associated. Cannot get default IP address.\n", pDeviceName); return NULL; } localIp = pDevice->ip_ptr->ifa_list->ifa_local; } pResult = (struct netpoll_wrapper *)kmalloc(sizeof(struct netpoll_wrapper), GFP_KERNEL); if (!pResult) { printk(KERN_ERR "kgdboe: cannot allocate memory for netpoll wrapper\n"); return NULL; } memset(pResult, 0, sizeof(*pResult)); #ifdef NETPOLL_POLL_DEV_USABLE pResult->netpoll_poll_dev = (void(*)(struct net_device *))kallsyms_lookup_name("netpoll_poll_dev"); if (!pResult->netpoll_poll_dev) { printk(KERN_ERR "kgdboe: Cannot find netpoll_poll_dev(). Aborting.\n"); netpoll_wrapper_free(pResult); return NULL; } #else pResult->zap_completion_queue = (void(*)(void))kallsyms_lookup_name("zap_completion_queue"); if (!pResult->zap_completion_queue) { printk(KERN_ERR "kgdboe: Cannot find zap_completion_queue(). Aborting.\n"); netpoll_wrapper_free(pResult); return NULL; } #endif rtnl_lock(); err = netdev_rx_handler_register(pDevice, netpoll_wrapper_rx_handler, pResult); rtnl_unlock(); if (err < 0) { printk(KERN_ERR "kgdboe: Failed to register rx handler for %s, code %d\n", pDeviceName, err); netpoll_wrapper_free(pResult); return NULL; } register_tracepoint_wrapper(netif_receive_skb, hook_receive_skb, pResult); pResult->tracepoint_registered = true; pResult->pDeviceWithHandler = pDevice; strncpy(pResult->netpoll_obj.dev_name, pDeviceName, sizeof(pResult->netpoll_obj.dev_name)); pResult->netpoll_obj.name = "kgdboe"; pResult->netpoll_obj.local_port = localPort; memset(pResult->netpoll_obj.remote_mac, 0xFF, sizeof(pResult->netpoll_obj.remote_mac)); err = netpoll_setup(&pResult->netpoll_obj); if (err < 0) { printk(KERN_ERR "kgdboe: Failed to setup netpoll for %s, code %d\n", pDeviceName, err); netpoll_wrapper_free(pResult); return NULL; } pResult->netpoll_initialized = true; return pResult; }