aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/bpf/arraymap.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/bpf/arraymap.c')
-rw-r--r--kernel/bpf/arraymap.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c
index 6b6f41f0b211..bcf9955fac95 100644
--- a/kernel/bpf/arraymap.c
+++ b/kernel/bpf/arraymap.c
@@ -1,4 +1,5 @@
1/* Copyright (c) 2011-2014 PLUMgrid, http://plumgrid.com 1/* Copyright (c) 2011-2014 PLUMgrid, http://plumgrid.com
2 * Copyright (c) 2016,2017 Facebook
2 * 3 *
3 * This program is free software; you can redistribute it and/or 4 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of version 2 of the GNU General Public 5 * modify it under the terms of version 2 of the GNU General Public
@@ -113,6 +114,33 @@ static void *array_map_lookup_elem(struct bpf_map *map, void *key)
113 return array->value + array->elem_size * index; 114 return array->value + array->elem_size * index;
114} 115}
115 116
117/* emit BPF instructions equivalent to C code of array_map_lookup_elem() */
118static u32 array_map_gen_lookup(struct bpf_map *map, struct bpf_insn *insn_buf)
119{
120 struct bpf_array *array = container_of(map, struct bpf_array, map);
121 struct bpf_insn *insn = insn_buf;
122 u32 elem_size = array->elem_size;
123 const int ret = BPF_REG_0;
124 const int map_ptr = BPF_REG_1;
125 const int index = BPF_REG_2;
126
127 *insn++ = BPF_ALU64_IMM(BPF_ADD, map_ptr, offsetof(struct bpf_array, value));
128 *insn++ = BPF_LDX_MEM(BPF_W, ret, index, 0);
129 *insn++ = BPF_JMP_IMM(BPF_JGE, ret, array->map.max_entries,
130 elem_size == 1 ? 2 : 3);
131 if (elem_size == 1) {
132 /* nop */
133 } else if (is_power_of_2(elem_size)) {
134 *insn++ = BPF_ALU64_IMM(BPF_LSH, ret, ilog2(elem_size));
135 } else {
136 *insn++ = BPF_ALU64_IMM(BPF_MUL, ret, elem_size);
137 }
138 *insn++ = BPF_ALU64_REG(BPF_ADD, ret, map_ptr);
139 *insn++ = BPF_JMP_IMM(BPF_JA, 0, 0, 1);
140 *insn++ = BPF_MOV64_IMM(ret, 0);
141 return insn - insn_buf;
142}
143
116/* Called from eBPF program */ 144/* Called from eBPF program */
117static void *percpu_array_map_lookup_elem(struct bpf_map *map, void *key) 145static void *percpu_array_map_lookup_elem(struct bpf_map *map, void *key)
118{ 146{
@@ -267,6 +295,7 @@ static const struct bpf_map_ops array_ops = {
267 .map_lookup_elem = array_map_lookup_elem, 295 .map_lookup_elem = array_map_lookup_elem,
268 .map_update_elem = array_map_update_elem, 296 .map_update_elem = array_map_update_elem,
269 .map_delete_elem = array_map_delete_elem, 297 .map_delete_elem = array_map_delete_elem,
298 .map_gen_lookup = array_map_gen_lookup,
270}; 299};
271 300
272static struct bpf_map_type_list array_type __ro_after_init = { 301static struct bpf_map_type_list array_type __ro_after_init = {