Skip to content

Commit a6566b3

Browse files
committed
Added support for kernels up to 5.7.0
1 parent 29fb406 commit a6566b3

File tree

7 files changed

+142
-102
lines changed

7 files changed

+142
-102
lines changed

Diff for: kgdboe_io.c

+27-4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "kgdboe_io.h"
66
#include "netpoll_wrapper.h"
77
#include "nethook.h"
8+
#include "tracewrapper.h"
89

910
struct netpoll_wrapper *s_pKgdboeNetpoll;
1011

@@ -72,8 +73,8 @@ static int kgdboe_read_char(void)
7273

7374
BUG_ON(!s_pKgdboeNetpoll);
7475

75-
while (s_IncomingRingBufferReadPosition == s_IncomingRingBufferWritePosition)
76-
netpoll_wrapper_poll(s_pKgdboeNetpoll);
76+
while (s_IncomingRingBufferReadPosition == s_IncomingRingBufferWritePosition)
77+
netpoll_wrapper_poll(s_pKgdboeNetpoll);
7778

7879
result = s_IncomingRingBuffer[s_IncomingRingBufferReadPosition++];
7980
s_IncomingRingBufferReadPosition %= sizeof(s_IncomingRingBuffer);
@@ -112,6 +113,8 @@ static struct kgdb_io kgdboe_io_ops = {
112113

113114
int force_single_cpu_mode(void)
114115
{
116+
int cpu;
117+
115118
if (num_online_cpus() == 1)
116119
{
117120
printk(KERN_INFO "kgdboe: only one active CPU found. Skipping core shutdown.\n");
@@ -122,8 +125,20 @@ int force_single_cpu_mode(void)
122125
printk(KERN_INFO "kgdboe: you can try using multi-core mode by specifying the following argument:\n");
123126
printk(KERN_INFO "\tinsmod kgdboe.ko force_single_core = 0\n");
124127
#ifdef CONFIG_HOTPLUG_CPU
125-
for (int i = 1; i < nr_cpu_ids; i++)
126-
cpu_down(i);
128+
for_each_possible_cpu(cpu)
129+
{
130+
if (cpu == 0)
131+
continue;
132+
133+
if (!cpu_online(cpu))
134+
continue;
135+
136+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,7,0)
137+
remove_cpu(cpu);
138+
#else
139+
cpu_down(cpu);
140+
#endif
141+
}
127142
#else
128143
if (nr_cpu_ids != 1)
129144
{
@@ -144,6 +159,14 @@ int kgdboe_io_init(const char *device_name, int port, const char *local_ip, bool
144159
s_pKgdboeNetpoll = netpoll_wrapper_create(device_name, port, local_ip);
145160
if (!s_pKgdboeNetpoll)
146161
return -EINVAL;
162+
163+
int *_gro_normal_batch = kallsyms_lookup_name("gro_normal_batch");
164+
if (_gro_normal_batch)
165+
{
166+
//Unless we do this, thet network stack will internally accumulate packets before processing, greatly increasing KGDBoE latency.
167+
//See gro_normal_one() in dev.c for details.
168+
*_gro_normal_batch = 1;
169+
}
147170

148171
if (force_single_core)
149172
{

Diff for: kgdboe_main.c

+10-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ MODULE_LICENSE("GPL");
4848
static int udp_port = 31337;
4949
module_param(udp_port, int, 0444);
5050

51-
static char *device_name = "eth0";
51+
static char *device_name = "ens33";
5252
module_param(device_name, charp, 0444);
5353

5454
static char *local_ip = NULL;
@@ -57,8 +57,17 @@ module_param(local_ip, charp, 0444);
5757
static int force_single_core = 1;
5858
module_param(force_single_core, int, 0444);
5959

60+
uint64_t kallsyms_lookup_name_address;
61+
module_param(kallsyms_lookup_name_address, ullong, 0444);
62+
6063
static int __init kgdboe_init(void)
6164
{
65+
if (!kallsyms_lookup_name_address)
66+
{
67+
printk(KERN_ERR "kgdboe: this kernel version requires specifying the address of kallsyms_lookup_name explicitly. Please append 'kallsyms_lookup_name_address=0x...' to insmod command line.\n");
68+
return -EINVAL;
69+
}
70+
6271
int err = kgdboe_io_init(device_name, udp_port, local_ip, force_single_core != 0);
6372
if (err != 0)
6473
return err;

Diff for: nethook.c

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <linux/preempt.h>
1111
#include <linux/seqlock.h>
1212
#include <linux/version.h>
13+
#include "tracewrapper.h"
1314

1415
/*
1516
This file is the central place for hooking a network card driver to ensure that no other cores are executing

Diff for: netpoll_wrapper.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#include <linux/rtnetlink.h>
99
#include "tracewrapper.h"
1010

11+
#include <linux/rcupdate.h>
12+
1113
/*
1214
This file contains a wrapper around the netpoll API that encapsulates the following tasks:
1315
* Replying to ARP messages while the kernel is stopped (removed from kernel 3.15)
@@ -31,7 +33,7 @@ struct netpoll_wrapper *netpoll_wrapper_create(const char *pDeviceName, int loca
3133

3234
if (!tracepoint_available(netif_receive_skb))
3335
{
34-
printk(KERN_ERR "kgdboe: Missing tracepoints for netif_receive_skb. Aborting.\n");
36+
printk(KERN_ERR "kgdboe: Missing tracepoints for netif_receive_skb. Aborting.\n");
3537
return NULL;
3638
}
3739

Diff for: poll_copy.c

+93-94
Original file line numberDiff line numberDiff line change
@@ -1,96 +1,95 @@
1-
#include <linux/rcupdate.h>
2-
#include <linux/list.h>
3-
#include <linux/netpoll.h>
4-
#include "netpoll_wrapper.h"
5-
6-
/*
7-
This file contains copies of netpoll_poll_dev() and all related functions that are no longer usable
8-
in kernel 3.15.
9-
*/
10-
11-
#ifndef NETPOLL_POLL_DEV_USABLE
12-
13-
static int poll_one_napi(struct napi_struct *napi, int budget)
14-
{
15-
int work;
16-
17-
/* net_rx_action's ->poll() invocations and our's are
18-
* synchronized by this test which is only made while
19-
* holding the napi->poll_lock.
20-
*/
21-
if (!test_bit(NAPI_STATE_SCHED, &napi->state))
22-
return budget;
23-
24-
if (test_and_set_bit(NAPI_STATE_NPSVC, &napi->state))
25-
return budget;
26-
27-
work = napi->poll(napi, budget);
28-
WARN_ONCE(work > budget, "%pF exceeded budget in poll\n", napi->poll);
29-
30-
clear_bit(NAPI_STATE_NPSVC, &napi->state);
31-
32-
return budget - work;
33-
}
34-
1+
#include <linux/rcupdate.h>
2+
#include <linux/list.h>
3+
#include <linux/netpoll.h>
4+
#include "netpoll_wrapper.h"
5+
6+
/*
7+
This file contains copies of netpoll_poll_dev() and all related functions that are no longer usable
8+
in kernel 3.15.
9+
*/
10+
11+
#ifndef NETPOLL_POLL_DEV_USABLE
12+
13+
static int poll_one_napi(struct napi_struct *napi, int budget)
14+
{
15+
int work;
16+
17+
/* net_rx_action's ->poll() invocations and our's are
18+
* synchronized by this test which is only made while
19+
* holding the napi->poll_lock.
20+
*/
21+
if (!test_bit(NAPI_STATE_SCHED, &napi->state))
22+
return budget;
23+
24+
if (test_and_set_bit(NAPI_STATE_NPSVC, &napi->state))
25+
return budget;
26+
27+
work = napi->poll(napi, budget);
28+
29+
clear_bit(NAPI_STATE_NPSVC, &napi->state);
30+
31+
return budget - work;
32+
}
33+
3534
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0)
36-
static void poll_napi(struct net_device *dev, int budget)
37-
{
38-
struct napi_struct *napi;
39-
40-
list_for_each_entry(napi, &dev->napi_list, dev_list) {
41-
if (napi->poll_owner != smp_processor_id() &&
42-
spin_trylock(&napi->poll_lock)) {
43-
budget = poll_one_napi(napi, budget);
44-
spin_unlock(&napi->poll_lock);
45-
}
46-
}
47-
}
48-
#else
49-
static void __attribute__((optimize("O2", "-fno-omit-frame-pointer"))) poll_napi(struct net_device *dev, int budget)
50-
{
51-
struct napi_struct *napi;
52-
int cpu = smp_processor_id();
53-
54-
list_for_each_entry(napi, &dev->napi_list, dev_list) {
55-
if (cmpxchg(&napi->poll_owner, -1, cpu) == -1) {
56-
poll_one_napi(napi, budget);
57-
smp_store_release(&napi->poll_owner, -1);
58-
}
59-
}
60-
}
61-
#endif
62-
63-
void netpoll_poll_dev_copy(struct net_device *dev, void(*zap_completion_queue)(void))
64-
{
65-
const struct net_device_ops *ops;
66-
struct netpoll_info *ni = rcu_dereference_bh(dev->npinfo);
67-
int budget = 16;
68-
69-
/* Don't do any rx activity if the dev_lock mutex is held
70-
* the dev_open/close paths use this to block netpoll activity
71-
* while changing device state
72-
*/
73-
if (down_trylock(&ni->dev_lock))
74-
return;
75-
76-
if (!netif_running(dev)) {
77-
up(&ni->dev_lock);
78-
return;
79-
}
80-
81-
ops = dev->netdev_ops;
82-
if (!ops->ndo_poll_controller) {
83-
up(&ni->dev_lock);
84-
return;
85-
}
86-
87-
/* Process pending work on NIC */
88-
ops->ndo_poll_controller(dev);
89-
90-
poll_napi(dev, budget);
91-
92-
up(&ni->dev_lock);
93-
94-
zap_completion_queue();
95-
}
35+
static void poll_napi(struct net_device *dev, int budget)
36+
{
37+
struct napi_struct *napi;
38+
39+
list_for_each_entry(napi, &dev->napi_list, dev_list) {
40+
if (napi->poll_owner != smp_processor_id() &&
41+
spin_trylock(&napi->poll_lock)) {
42+
budget = poll_one_napi(napi, budget);
43+
spin_unlock(&napi->poll_lock);
44+
}
45+
}
46+
}
47+
#else
48+
static void __attribute__((optimize("O2", "-fno-omit-frame-pointer"))) poll_napi(struct net_device *dev, int budget)
49+
{
50+
struct napi_struct *napi;
51+
int cpu = smp_processor_id();
52+
53+
list_for_each_entry(napi, &dev->napi_list, dev_list) {
54+
if (cmpxchg(&napi->poll_owner, -1, cpu) == -1) {
55+
poll_one_napi(napi, budget);
56+
smp_store_release(&napi->poll_owner, -1);
57+
}
58+
}
59+
}
60+
#endif
61+
62+
void netpoll_poll_dev_copy(struct net_device *dev, void(*zap_completion_queue)(void))
63+
{
64+
const struct net_device_ops *ops;
65+
struct netpoll_info *ni = rcu_dereference_bh(dev->npinfo);
66+
int budget = 16;
67+
68+
/* Don't do any rx activity if the dev_lock mutex is held
69+
* the dev_open/close paths use this to block netpoll activity
70+
* while changing device state
71+
*/
72+
if (down_trylock(&ni->dev_lock))
73+
return;
74+
75+
if (!netif_running(dev)) {
76+
up(&ni->dev_lock);
77+
return;
78+
}
79+
80+
ops = dev->netdev_ops;
81+
if (!ops->ndo_poll_controller) {
82+
up(&ni->dev_lock);
83+
return;
84+
}
85+
86+
/* Process pending work on NIC */
87+
ops->ndo_poll_controller(dev);
88+
89+
poll_napi(dev, budget);
90+
91+
up(&ni->dev_lock);
92+
93+
zap_completion_queue();
94+
}
9695
#endif

Diff for: timerhook.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ struct timer_hook *timerhook_create(struct module *moduleToHook)
3939

4040
if (!tracepoint_available(timer_expire_entry) || !tracepoint_available(timer_expire_exit))
4141
{
42-
printk(KERN_ERR "kgdboe: Missing tracepoints for timer_expire_entry/timer_expire_exit. Aborting.\n");
42+
printk(KERN_ERR "kgdboe: Missing tracepoints for timer_expire_entry/timer_expire_exit. Aborting.\n");
4343
return NULL;
4444
}
4545

Diff for: tracewrapper.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22
#include <linux/version.h>
33
#include <linux/kallsyms.h>
44

5+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,7,0)
6+
extern uint64_t kallsyms_lookup_name_address;
7+
8+
#define kallsyms_lookup_name ((unsigned long(*)(const char *))kallsyms_lookup_name_address)
9+
#endif
10+
511
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0)
612

713
#define register_tracepoint_wrapper(tp, func, ctx) \
@@ -37,4 +43,4 @@ static struct tracepoint *do_lookup_tracepoint(const char *tracepointName, const
3743
#define tracepoint_available(tp) (kallsyms_lookup_name("__tracepoint_" #tp) || kallsyms_lookup_name("__tracepoint_ptr_" #tp))
3844

3945

40-
#endif
46+
#endif

0 commit comments

Comments
 (0)