/* flags for bpf_redirect_info kern_flags */
 #define BPF_RI_F_RF_NO_DIRECT  BIT(0)  /* no napi_direct on return_frame */
 #define BPF_RI_F_RI_INIT       BIT(1)
+#define BPF_RI_F_CPU_MAP_INIT  BIT(2)
+#define BPF_RI_F_DEV_MAP_INIT  BIT(3)
+#define BPF_RI_F_XSK_MAP_INIT  BIT(4)
 
 struct bpf_redirect_info {
        u64 tgt_index;
 
 struct bpf_net_context {
        struct bpf_redirect_info ri;
+       struct list_head cpu_map_flush_list;
+       struct list_head dev_map_flush_list;
+       struct list_head xskmap_map_flush_list;
 };
 
 static inline struct bpf_net_context *bpf_net_ctx_set(struct bpf_net_context *bpf_net_ctx)
        return &bpf_net_ctx->ri;
 }
 
+static inline struct list_head *bpf_net_ctx_get_cpu_map_flush_list(void)
+{
+       struct bpf_net_context *bpf_net_ctx = bpf_net_ctx_get();
+
+       if (!(bpf_net_ctx->ri.kern_flags & BPF_RI_F_CPU_MAP_INIT)) {
+               INIT_LIST_HEAD(&bpf_net_ctx->cpu_map_flush_list);
+               bpf_net_ctx->ri.kern_flags |= BPF_RI_F_CPU_MAP_INIT;
+       }
+
+       return &bpf_net_ctx->cpu_map_flush_list;
+}
+
+static inline struct list_head *bpf_net_ctx_get_dev_flush_list(void)
+{
+       struct bpf_net_context *bpf_net_ctx = bpf_net_ctx_get();
+
+       if (!(bpf_net_ctx->ri.kern_flags & BPF_RI_F_DEV_MAP_INIT)) {
+               INIT_LIST_HEAD(&bpf_net_ctx->dev_map_flush_list);
+               bpf_net_ctx->ri.kern_flags |= BPF_RI_F_DEV_MAP_INIT;
+       }
+
+       return &bpf_net_ctx->dev_map_flush_list;
+}
+
+static inline struct list_head *bpf_net_ctx_get_xskmap_flush_list(void)
+{
+       struct bpf_net_context *bpf_net_ctx = bpf_net_ctx_get();
+
+       if (!(bpf_net_ctx->ri.kern_flags & BPF_RI_F_XSK_MAP_INIT)) {
+               INIT_LIST_HEAD(&bpf_net_ctx->xskmap_map_flush_list);
+               bpf_net_ctx->ri.kern_flags |= BPF_RI_F_XSK_MAP_INIT;
+       }
+
+       return &bpf_net_ctx->xskmap_map_flush_list;
+}
+
 /* Compute the linear packet data range [data, data_end) which
  * will be accessed by various program types (cls_bpf, act_bpf,
  * lwt, ...). Subsystems allowing direct data access must (!)
 
        struct bpf_cpu_map_entry __rcu **cpu_map;
 };
 
-static DEFINE_PER_CPU(struct list_head, cpu_map_flush_list);
-
 static struct bpf_map *cpu_map_alloc(union bpf_attr *attr)
 {
        u32 value_size = attr->value_size;
  */
 static void bq_enqueue(struct bpf_cpu_map_entry *rcpu, struct xdp_frame *xdpf)
 {
-       struct list_head *flush_list = this_cpu_ptr(&cpu_map_flush_list);
+       struct list_head *flush_list = bpf_net_ctx_get_cpu_map_flush_list();
        struct xdp_bulk_queue *bq = this_cpu_ptr(rcpu->bulkq);
 
        if (unlikely(bq->count == CPU_MAP_BULK_SIZE))
 
 void __cpu_map_flush(void)
 {
-       struct list_head *flush_list = this_cpu_ptr(&cpu_map_flush_list);
+       struct list_head *flush_list = bpf_net_ctx_get_cpu_map_flush_list();
        struct xdp_bulk_queue *bq, *tmp;
 
        list_for_each_entry_safe(bq, tmp, flush_list, flush_node) {
 #ifdef CONFIG_DEBUG_NET
 bool cpu_map_check_flush(void)
 {
-       if (list_empty(this_cpu_ptr(&cpu_map_flush_list)))
+       if (list_empty(bpf_net_ctx_get_cpu_map_flush_list()))
                return false;
        __cpu_map_flush();
        return true;
 }
 #endif
-
-static int __init cpu_map_init(void)
-{
-       int cpu;
-
-       for_each_possible_cpu(cpu)
-               INIT_LIST_HEAD(&per_cpu(cpu_map_flush_list, cpu));
-       return 0;
-}
-
-subsys_initcall(cpu_map_init);
 
        u32 n_buckets;
 };
 
-static DEFINE_PER_CPU(struct list_head, dev_flush_list);
 static DEFINE_SPINLOCK(dev_map_lock);
 static LIST_HEAD(dev_map_list);
 
  */
 void __dev_flush(void)
 {
-       struct list_head *flush_list = this_cpu_ptr(&dev_flush_list);
+       struct list_head *flush_list = bpf_net_ctx_get_dev_flush_list();
        struct xdp_dev_bulk_queue *bq, *tmp;
 
        list_for_each_entry_safe(bq, tmp, flush_list, flush_node) {
 #ifdef CONFIG_DEBUG_NET
 bool dev_check_flush(void)
 {
-       if (list_empty(this_cpu_ptr(&dev_flush_list)))
+       if (list_empty(bpf_net_ctx_get_dev_flush_list()))
                return false;
        __dev_flush();
        return true;
 static void bq_enqueue(struct net_device *dev, struct xdp_frame *xdpf,
                       struct net_device *dev_rx, struct bpf_prog *xdp_prog)
 {
-       struct list_head *flush_list = this_cpu_ptr(&dev_flush_list);
+       struct list_head *flush_list = bpf_net_ctx_get_dev_flush_list();
        struct xdp_dev_bulk_queue *bq = this_cpu_ptr(dev->xdp_bulkq);
 
        if (unlikely(bq->count == DEV_MAP_BULK_SIZE))
 
 static int __init dev_map_init(void)
 {
-       int cpu;
-
        /* Assure tracepoint shadow struct _bpf_dtab_netdev is in sync */
        BUILD_BUG_ON(offsetof(struct bpf_dtab_netdev, dev) !=
                     offsetof(struct _bpf_dtab_netdev, dev));
        register_netdevice_notifier(&dev_map_notifier);
 
-       for_each_possible_cpu(cpu)
-               INIT_LIST_HEAD(&per_cpu(dev_flush_list, cpu));
        return 0;
 }
 
 
 #define TX_BATCH_SIZE 32
 #define MAX_PER_SOCKET_BUDGET (TX_BATCH_SIZE)
 
-static DEFINE_PER_CPU(struct list_head, xskmap_flush_list);
-
 void xsk_set_rx_need_wakeup(struct xsk_buff_pool *pool)
 {
        if (pool->cached_need_wakeup & XDP_WAKEUP_RX)
 
 int __xsk_map_redirect(struct xdp_sock *xs, struct xdp_buff *xdp)
 {
-       struct list_head *flush_list = this_cpu_ptr(&xskmap_flush_list);
+       struct list_head *flush_list = bpf_net_ctx_get_xskmap_flush_list();
        int err;
 
        err = xsk_rcv(xs, xdp);
 
 void __xsk_map_flush(void)
 {
-       struct list_head *flush_list = this_cpu_ptr(&xskmap_flush_list);
+       struct list_head *flush_list = bpf_net_ctx_get_xskmap_flush_list();
        struct xdp_sock *xs, *tmp;
 
        list_for_each_entry_safe(xs, tmp, flush_list, flush_node) {
 #ifdef CONFIG_DEBUG_NET
 bool xsk_map_check_flush(void)
 {
-       if (list_empty(this_cpu_ptr(&xskmap_flush_list)))
+       if (list_empty(bpf_net_ctx_get_xskmap_flush_list()))
                return false;
        __xsk_map_flush();
        return true;
 
 static int __init xsk_init(void)
 {
-       int err, cpu;
+       int err;
 
        err = proto_register(&xsk_proto, 0 /* no slab */);
        if (err)
        if (err)
                goto out_pernet;
 
-       for_each_possible_cpu(cpu)
-               INIT_LIST_HEAD(&per_cpu(xskmap_flush_list, cpu));
        return 0;
 
 out_pernet: