nfp: bpf: don't depend on high order allocations for program image
authorJakub Kicinski <jakub.kicinski@netronome.com>
Wed, 10 Jan 2018 12:26:02 +0000 (12:26 +0000)
committerDaniel Borkmann <daniel@iogearbox.net>
Wed, 10 Jan 2018 12:49:35 +0000 (13:49 +0100)
The translator pre-allocates a buffer of maximal program size.
Due to HW/FW limitations the program buffer can't currently be
longer than 128Kb, so we used to kmalloc() it, and then map for
DMA directly.

Now that the late branch resolution is copying the program image
anyway, we can just kvmalloc() the buffer.  While at it, after
translation reallocate the buffer to save space.

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
drivers/net/ethernet/netronome/nfp/bpf/jit.c
drivers/net/ethernet/netronome/nfp/bpf/offload.c

index 3a5c747fd12b44e25733a7547ced9fa65c404585..5deebbc18cfd97a2a7d7d9e6e97df26b642196e8 100644 (file)
@@ -2676,6 +2676,20 @@ static int nfp_bpf_ustore_calc(u64 *prog, unsigned int len)
        return 0;
 }
 
+static void nfp_bpf_prog_trim(struct nfp_prog *nfp_prog)
+{
+       void *prog;
+
+       prog = kvmalloc_array(nfp_prog->prog_len, sizeof(u64), GFP_KERNEL);
+       if (!prog)
+               return;
+
+       nfp_prog->__prog_alloc_len = nfp_prog->prog_len * sizeof(u64);
+       memcpy(prog, nfp_prog->prog, nfp_prog->__prog_alloc_len);
+       kvfree(nfp_prog->prog);
+       nfp_prog->prog = prog;
+}
+
 int nfp_bpf_jit(struct nfp_prog *nfp_prog)
 {
        int ret;
@@ -2691,6 +2705,8 @@ int nfp_bpf_jit(struct nfp_prog *nfp_prog)
                return -EINVAL;
        }
 
+       nfp_bpf_prog_trim(nfp_prog);
+
        return ret;
 }
 
index 5f165e1d7648b01141e0d4887bedac500ed13442..f635605507535e89b1baedc8e32b3c7212ac6a22 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/jiffies.h>
 #include <linux/timer.h>
 #include <linux/list.h>
+#include <linux/mm.h>
 
 #include <net/pkt_cls.h>
 #include <net/tc_act/tc_gact.h>
@@ -135,7 +136,7 @@ int nfp_bpf_translate(struct nfp_app *app, struct nfp_net *nn,
        max_instr = nn_readw(nn, NFP_NET_CFG_BPF_MAX_LEN);
        nfp_prog->__prog_alloc_len = max_instr * sizeof(u64);
 
-       nfp_prog->prog = kmalloc(nfp_prog->__prog_alloc_len, GFP_KERNEL);
+       nfp_prog->prog = kvmalloc(nfp_prog->__prog_alloc_len, GFP_KERNEL);
        if (!nfp_prog->prog)
                return -ENOMEM;
 
@@ -147,7 +148,7 @@ int nfp_bpf_destroy(struct nfp_app *app, struct nfp_net *nn,
 {
        struct nfp_prog *nfp_prog = prog->aux->offload->dev_priv;
 
-       kfree(nfp_prog->prog);
+       kvfree(nfp_prog->prog);
        nfp_prog_free(nfp_prog);
 
        return 0;