| .. | .. |
|---|
| 23 | 23 | #include <linux/filter.h> |
|---|
| 24 | 24 | #include <linux/init.h> |
|---|
| 25 | 25 | #include <linux/bpf.h> |
|---|
| 26 | +#include <linux/mm.h> |
|---|
| 27 | +#include <linux/kernel.h> |
|---|
| 26 | 28 | #include <asm/cacheflush.h> |
|---|
| 27 | 29 | #include <asm/dis.h> |
|---|
| 28 | 30 | #include <asm/facility.h> |
|---|
| .. | .. |
|---|
| 38 | 40 | int size; /* Size of program and literal pool */ |
|---|
| 39 | 41 | int size_prg; /* Size of program */ |
|---|
| 40 | 42 | int prg; /* Current position in program */ |
|---|
| 41 | | - int lit_start; /* Start of literal pool */ |
|---|
| 42 | | - int lit; /* Current position in literal pool */ |
|---|
| 43 | + int lit32_start; /* Start of 32-bit literal pool */ |
|---|
| 44 | + int lit32; /* Current position in 32-bit literal pool */ |
|---|
| 45 | + int lit64_start; /* Start of 64-bit literal pool */ |
|---|
| 46 | + int lit64; /* Current position in 64-bit literal pool */ |
|---|
| 43 | 47 | int base_ip; /* Base address for literal pool */ |
|---|
| 44 | | - int ret0_ip; /* Address of return 0 */ |
|---|
| 45 | 48 | int exit_ip; /* Address of exit */ |
|---|
| 46 | 49 | int r1_thunk_ip; /* Address of expoline thunk for 'br %r1' */ |
|---|
| 47 | 50 | int r14_thunk_ip; /* Address of expoline thunk for 'br %r14' */ |
|---|
| 48 | 51 | int tail_call_start; /* Tail call start offset */ |
|---|
| 49 | | - int labels[1]; /* Labels for local jumps */ |
|---|
| 52 | + int excnt; /* Number of exception table entries */ |
|---|
| 50 | 53 | }; |
|---|
| 51 | 54 | |
|---|
| 52 | | -#define BPF_SIZE_MAX 0xffff /* Max size for program (16 bit branches) */ |
|---|
| 53 | | - |
|---|
| 54 | | -#define SEEN_MEM (1 << 0) /* use mem[] for temporary storage */ |
|---|
| 55 | | -#define SEEN_RET0 (1 << 1) /* ret0_ip points to a valid return 0 */ |
|---|
| 56 | | -#define SEEN_LITERAL (1 << 2) /* code uses literals */ |
|---|
| 57 | | -#define SEEN_FUNC (1 << 3) /* calls C functions */ |
|---|
| 58 | | -#define SEEN_TAIL_CALL (1 << 4) /* code uses tail calls */ |
|---|
| 59 | | -#define SEEN_REG_AX (1 << 5) /* code uses constant blinding */ |
|---|
| 55 | +#define SEEN_MEM BIT(0) /* use mem[] for temporary storage */ |
|---|
| 56 | +#define SEEN_LITERAL BIT(1) /* code uses literals */ |
|---|
| 57 | +#define SEEN_FUNC BIT(2) /* calls C functions */ |
|---|
| 58 | +#define SEEN_TAIL_CALL BIT(3) /* code uses tail calls */ |
|---|
| 60 | 59 | #define SEEN_STACK (SEEN_FUNC | SEEN_MEM) |
|---|
| 61 | 60 | |
|---|
| 62 | 61 | /* |
|---|
| .. | .. |
|---|
| 131 | 130 | #define _EMIT2(op) \ |
|---|
| 132 | 131 | ({ \ |
|---|
| 133 | 132 | if (jit->prg_buf) \ |
|---|
| 134 | | - *(u16 *) (jit->prg_buf + jit->prg) = op; \ |
|---|
| 133 | + *(u16 *) (jit->prg_buf + jit->prg) = (op); \ |
|---|
| 135 | 134 | jit->prg += 2; \ |
|---|
| 136 | 135 | }) |
|---|
| 137 | 136 | |
|---|
| 138 | 137 | #define EMIT2(op, b1, b2) \ |
|---|
| 139 | 138 | ({ \ |
|---|
| 140 | | - _EMIT2(op | reg(b1, b2)); \ |
|---|
| 139 | + _EMIT2((op) | reg(b1, b2)); \ |
|---|
| 141 | 140 | REG_SET_SEEN(b1); \ |
|---|
| 142 | 141 | REG_SET_SEEN(b2); \ |
|---|
| 143 | 142 | }) |
|---|
| .. | .. |
|---|
| 145 | 144 | #define _EMIT4(op) \ |
|---|
| 146 | 145 | ({ \ |
|---|
| 147 | 146 | if (jit->prg_buf) \ |
|---|
| 148 | | - *(u32 *) (jit->prg_buf + jit->prg) = op; \ |
|---|
| 147 | + *(u32 *) (jit->prg_buf + jit->prg) = (op); \ |
|---|
| 149 | 148 | jit->prg += 4; \ |
|---|
| 150 | 149 | }) |
|---|
| 151 | 150 | |
|---|
| 152 | 151 | #define EMIT4(op, b1, b2) \ |
|---|
| 153 | 152 | ({ \ |
|---|
| 154 | | - _EMIT4(op | reg(b1, b2)); \ |
|---|
| 153 | + _EMIT4((op) | reg(b1, b2)); \ |
|---|
| 155 | 154 | REG_SET_SEEN(b1); \ |
|---|
| 156 | 155 | REG_SET_SEEN(b2); \ |
|---|
| 157 | 156 | }) |
|---|
| 158 | 157 | |
|---|
| 159 | 158 | #define EMIT4_RRF(op, b1, b2, b3) \ |
|---|
| 160 | 159 | ({ \ |
|---|
| 161 | | - _EMIT4(op | reg_high(b3) << 8 | reg(b1, b2)); \ |
|---|
| 160 | + _EMIT4((op) | reg_high(b3) << 8 | reg(b1, b2)); \ |
|---|
| 162 | 161 | REG_SET_SEEN(b1); \ |
|---|
| 163 | 162 | REG_SET_SEEN(b2); \ |
|---|
| 164 | 163 | REG_SET_SEEN(b3); \ |
|---|
| .. | .. |
|---|
| 167 | 166 | #define _EMIT4_DISP(op, disp) \ |
|---|
| 168 | 167 | ({ \ |
|---|
| 169 | 168 | unsigned int __disp = (disp) & 0xfff; \ |
|---|
| 170 | | - _EMIT4(op | __disp); \ |
|---|
| 169 | + _EMIT4((op) | __disp); \ |
|---|
| 171 | 170 | }) |
|---|
| 172 | 171 | |
|---|
| 173 | 172 | #define EMIT4_DISP(op, b1, b2, disp) \ |
|---|
| 174 | 173 | ({ \ |
|---|
| 175 | | - _EMIT4_DISP(op | reg_high(b1) << 16 | \ |
|---|
| 176 | | - reg_high(b2) << 8, disp); \ |
|---|
| 174 | + _EMIT4_DISP((op) | reg_high(b1) << 16 | \ |
|---|
| 175 | + reg_high(b2) << 8, (disp)); \ |
|---|
| 177 | 176 | REG_SET_SEEN(b1); \ |
|---|
| 178 | 177 | REG_SET_SEEN(b2); \ |
|---|
| 179 | 178 | }) |
|---|
| .. | .. |
|---|
| 181 | 180 | #define EMIT4_IMM(op, b1, imm) \ |
|---|
| 182 | 181 | ({ \ |
|---|
| 183 | 182 | unsigned int __imm = (imm) & 0xffff; \ |
|---|
| 184 | | - _EMIT4(op | reg_high(b1) << 16 | __imm); \ |
|---|
| 183 | + _EMIT4((op) | reg_high(b1) << 16 | __imm); \ |
|---|
| 185 | 184 | REG_SET_SEEN(b1); \ |
|---|
| 186 | 185 | }) |
|---|
| 187 | 186 | |
|---|
| 188 | 187 | #define EMIT4_PCREL(op, pcrel) \ |
|---|
| 189 | 188 | ({ \ |
|---|
| 190 | 189 | long __pcrel = ((pcrel) >> 1) & 0xffff; \ |
|---|
| 191 | | - _EMIT4(op | __pcrel); \ |
|---|
| 190 | + _EMIT4((op) | __pcrel); \ |
|---|
| 191 | +}) |
|---|
| 192 | + |
|---|
| 193 | +#define EMIT4_PCREL_RIC(op, mask, target) \ |
|---|
| 194 | +({ \ |
|---|
| 195 | + int __rel = ((target) - jit->prg) / 2; \ |
|---|
| 196 | + _EMIT4((op) | (mask) << 20 | (__rel & 0xffff)); \ |
|---|
| 192 | 197 | }) |
|---|
| 193 | 198 | |
|---|
| 194 | 199 | #define _EMIT6(op1, op2) \ |
|---|
| 195 | 200 | ({ \ |
|---|
| 196 | 201 | if (jit->prg_buf) { \ |
|---|
| 197 | | - *(u32 *) (jit->prg_buf + jit->prg) = op1; \ |
|---|
| 198 | | - *(u16 *) (jit->prg_buf + jit->prg + 4) = op2; \ |
|---|
| 202 | + *(u32 *) (jit->prg_buf + jit->prg) = (op1); \ |
|---|
| 203 | + *(u16 *) (jit->prg_buf + jit->prg + 4) = (op2); \ |
|---|
| 199 | 204 | } \ |
|---|
| 200 | 205 | jit->prg += 6; \ |
|---|
| 201 | 206 | }) |
|---|
| .. | .. |
|---|
| 203 | 208 | #define _EMIT6_DISP(op1, op2, disp) \ |
|---|
| 204 | 209 | ({ \ |
|---|
| 205 | 210 | unsigned int __disp = (disp) & 0xfff; \ |
|---|
| 206 | | - _EMIT6(op1 | __disp, op2); \ |
|---|
| 211 | + _EMIT6((op1) | __disp, op2); \ |
|---|
| 207 | 212 | }) |
|---|
| 208 | 213 | |
|---|
| 209 | 214 | #define _EMIT6_DISP_LH(op1, op2, disp) \ |
|---|
| 210 | 215 | ({ \ |
|---|
| 211 | | - u32 _disp = (u32) disp; \ |
|---|
| 216 | + u32 _disp = (u32) (disp); \ |
|---|
| 212 | 217 | unsigned int __disp_h = _disp & 0xff000; \ |
|---|
| 213 | 218 | unsigned int __disp_l = _disp & 0x00fff; \ |
|---|
| 214 | | - _EMIT6(op1 | __disp_l, op2 | __disp_h >> 4); \ |
|---|
| 219 | + _EMIT6((op1) | __disp_l, (op2) | __disp_h >> 4); \ |
|---|
| 215 | 220 | }) |
|---|
| 216 | 221 | |
|---|
| 217 | 222 | #define EMIT6_DISP_LH(op1, op2, b1, b2, b3, disp) \ |
|---|
| 218 | 223 | ({ \ |
|---|
| 219 | | - _EMIT6_DISP_LH(op1 | reg(b1, b2) << 16 | \ |
|---|
| 224 | + _EMIT6_DISP_LH((op1) | reg(b1, b2) << 16 | \ |
|---|
| 220 | 225 | reg_high(b3) << 8, op2, disp); \ |
|---|
| 221 | 226 | REG_SET_SEEN(b1); \ |
|---|
| 222 | 227 | REG_SET_SEEN(b2); \ |
|---|
| 223 | 228 | REG_SET_SEEN(b3); \ |
|---|
| 224 | 229 | }) |
|---|
| 225 | 230 | |
|---|
| 226 | | -#define EMIT6_PCREL_LABEL(op1, op2, b1, b2, label, mask) \ |
|---|
| 231 | +#define EMIT6_PCREL_RIEB(op1, op2, b1, b2, mask, target) \ |
|---|
| 227 | 232 | ({ \ |
|---|
| 228 | | - int rel = (jit->labels[label] - jit->prg) >> 1; \ |
|---|
| 229 | | - _EMIT6(op1 | reg(b1, b2) << 16 | (rel & 0xffff), \ |
|---|
| 230 | | - op2 | mask << 12); \ |
|---|
| 233 | + unsigned int rel = (int)((target) - jit->prg) / 2; \ |
|---|
| 234 | + _EMIT6((op1) | reg(b1, b2) << 16 | (rel & 0xffff), \ |
|---|
| 235 | + (op2) | (mask) << 12); \ |
|---|
| 231 | 236 | REG_SET_SEEN(b1); \ |
|---|
| 232 | 237 | REG_SET_SEEN(b2); \ |
|---|
| 233 | 238 | }) |
|---|
| 234 | 239 | |
|---|
| 235 | | -#define EMIT6_PCREL_IMM_LABEL(op1, op2, b1, imm, label, mask) \ |
|---|
| 240 | +#define EMIT6_PCREL_RIEC(op1, op2, b1, imm, mask, target) \ |
|---|
| 236 | 241 | ({ \ |
|---|
| 237 | | - int rel = (jit->labels[label] - jit->prg) >> 1; \ |
|---|
| 238 | | - _EMIT6(op1 | (reg_high(b1) | mask) << 16 | \ |
|---|
| 239 | | - (rel & 0xffff), op2 | (imm & 0xff) << 8); \ |
|---|
| 242 | + unsigned int rel = (int)((target) - jit->prg) / 2; \ |
|---|
| 243 | + _EMIT6((op1) | (reg_high(b1) | (mask)) << 16 | \ |
|---|
| 244 | + (rel & 0xffff), (op2) | ((imm) & 0xff) << 8); \ |
|---|
| 240 | 245 | REG_SET_SEEN(b1); \ |
|---|
| 241 | | - BUILD_BUG_ON(((unsigned long) imm) > 0xff); \ |
|---|
| 246 | + BUILD_BUG_ON(((unsigned long) (imm)) > 0xff); \ |
|---|
| 242 | 247 | }) |
|---|
| 243 | 248 | |
|---|
| 244 | 249 | #define EMIT6_PCREL(op1, op2, b1, b2, i, off, mask) \ |
|---|
| 245 | 250 | ({ \ |
|---|
| 246 | | - /* Branch instruction needs 6 bytes */ \ |
|---|
| 247 | | - int rel = (addrs[i + off + 1] - (addrs[i + 1] - 6)) / 2;\ |
|---|
| 248 | | - _EMIT6(op1 | reg(b1, b2) << 16 | (rel & 0xffff), op2 | mask); \ |
|---|
| 251 | + int rel = (addrs[(i) + (off) + 1] - jit->prg) / 2; \ |
|---|
| 252 | + _EMIT6((op1) | reg(b1, b2) << 16 | (rel & 0xffff), (op2) | (mask));\ |
|---|
| 249 | 253 | REG_SET_SEEN(b1); \ |
|---|
| 250 | 254 | REG_SET_SEEN(b2); \ |
|---|
| 251 | 255 | }) |
|---|
| 252 | 256 | |
|---|
| 253 | 257 | #define EMIT6_PCREL_RILB(op, b, target) \ |
|---|
| 254 | 258 | ({ \ |
|---|
| 255 | | - int rel = (target - jit->prg) / 2; \ |
|---|
| 256 | | - _EMIT6(op | reg_high(b) << 16 | rel >> 16, rel & 0xffff); \ |
|---|
| 259 | + unsigned int rel = (int)((target) - jit->prg) / 2; \ |
|---|
| 260 | + _EMIT6((op) | reg_high(b) << 16 | rel >> 16, rel & 0xffff);\ |
|---|
| 257 | 261 | REG_SET_SEEN(b); \ |
|---|
| 258 | 262 | }) |
|---|
| 259 | 263 | |
|---|
| 260 | 264 | #define EMIT6_PCREL_RIL(op, target) \ |
|---|
| 261 | 265 | ({ \ |
|---|
| 262 | | - int rel = (target - jit->prg) / 2; \ |
|---|
| 263 | | - _EMIT6(op | rel >> 16, rel & 0xffff); \ |
|---|
| 266 | + unsigned int rel = (int)((target) - jit->prg) / 2; \ |
|---|
| 267 | + _EMIT6((op) | rel >> 16, rel & 0xffff); \ |
|---|
| 268 | +}) |
|---|
| 269 | + |
|---|
| 270 | +#define EMIT6_PCREL_RILC(op, mask, target) \ |
|---|
| 271 | +({ \ |
|---|
| 272 | + EMIT6_PCREL_RIL((op) | (mask) << 20, (target)); \ |
|---|
| 264 | 273 | }) |
|---|
| 265 | 274 | |
|---|
| 266 | 275 | #define _EMIT6_IMM(op, imm) \ |
|---|
| 267 | 276 | ({ \ |
|---|
| 268 | 277 | unsigned int __imm = (imm); \ |
|---|
| 269 | | - _EMIT6(op | (__imm >> 16), __imm & 0xffff); \ |
|---|
| 278 | + _EMIT6((op) | (__imm >> 16), __imm & 0xffff); \ |
|---|
| 270 | 279 | }) |
|---|
| 271 | 280 | |
|---|
| 272 | 281 | #define EMIT6_IMM(op, b1, imm) \ |
|---|
| 273 | 282 | ({ \ |
|---|
| 274 | | - _EMIT6_IMM(op | reg_high(b1) << 16, imm); \ |
|---|
| 283 | + _EMIT6_IMM((op) | reg_high(b1) << 16, imm); \ |
|---|
| 275 | 284 | REG_SET_SEEN(b1); \ |
|---|
| 285 | +}) |
|---|
| 286 | + |
|---|
| 287 | +#define _EMIT_CONST_U32(val) \ |
|---|
| 288 | +({ \ |
|---|
| 289 | + unsigned int ret; \ |
|---|
| 290 | + ret = jit->lit32; \ |
|---|
| 291 | + if (jit->prg_buf) \ |
|---|
| 292 | + *(u32 *)(jit->prg_buf + jit->lit32) = (u32)(val);\ |
|---|
| 293 | + jit->lit32 += 4; \ |
|---|
| 294 | + ret; \ |
|---|
| 276 | 295 | }) |
|---|
| 277 | 296 | |
|---|
| 278 | 297 | #define EMIT_CONST_U32(val) \ |
|---|
| 279 | 298 | ({ \ |
|---|
| 280 | | - unsigned int ret; \ |
|---|
| 281 | | - ret = jit->lit - jit->base_ip; \ |
|---|
| 282 | 299 | jit->seen |= SEEN_LITERAL; \ |
|---|
| 300 | + _EMIT_CONST_U32(val) - jit->base_ip; \ |
|---|
| 301 | +}) |
|---|
| 302 | + |
|---|
| 303 | +#define _EMIT_CONST_U64(val) \ |
|---|
| 304 | +({ \ |
|---|
| 305 | + unsigned int ret; \ |
|---|
| 306 | + ret = jit->lit64; \ |
|---|
| 283 | 307 | if (jit->prg_buf) \ |
|---|
| 284 | | - *(u32 *) (jit->prg_buf + jit->lit) = (u32) val; \ |
|---|
| 285 | | - jit->lit += 4; \ |
|---|
| 308 | + *(u64 *)(jit->prg_buf + jit->lit64) = (u64)(val);\ |
|---|
| 309 | + jit->lit64 += 8; \ |
|---|
| 286 | 310 | ret; \ |
|---|
| 287 | 311 | }) |
|---|
| 288 | 312 | |
|---|
| 289 | 313 | #define EMIT_CONST_U64(val) \ |
|---|
| 290 | 314 | ({ \ |
|---|
| 291 | | - unsigned int ret; \ |
|---|
| 292 | | - ret = jit->lit - jit->base_ip; \ |
|---|
| 293 | 315 | jit->seen |= SEEN_LITERAL; \ |
|---|
| 294 | | - if (jit->prg_buf) \ |
|---|
| 295 | | - *(u64 *) (jit->prg_buf + jit->lit) = (u64) val; \ |
|---|
| 296 | | - jit->lit += 8; \ |
|---|
| 297 | | - ret; \ |
|---|
| 316 | + _EMIT_CONST_U64(val) - jit->base_ip; \ |
|---|
| 298 | 317 | }) |
|---|
| 299 | 318 | |
|---|
| 300 | 319 | #define EMIT_ZERO(b1) \ |
|---|
| 301 | 320 | ({ \ |
|---|
| 302 | | - /* llgfr %dst,%dst (zero extend to 64 bit) */ \ |
|---|
| 303 | | - EMIT4(0xb9160000, b1, b1); \ |
|---|
| 304 | | - REG_SET_SEEN(b1); \ |
|---|
| 321 | + if (!fp->aux->verifier_zext) { \ |
|---|
| 322 | + /* llgfr %dst,%dst (zero extend to 64 bit) */ \ |
|---|
| 323 | + EMIT4(0xb9160000, b1, b1); \ |
|---|
| 324 | + REG_SET_SEEN(b1); \ |
|---|
| 325 | + } \ |
|---|
| 305 | 326 | }) |
|---|
| 327 | + |
|---|
| 328 | +/* |
|---|
| 329 | + * Return whether this is the first pass. The first pass is special, since we |
|---|
| 330 | + * don't know any sizes yet, and thus must be conservative. |
|---|
| 331 | + */ |
|---|
| 332 | +static bool is_first_pass(struct bpf_jit *jit) |
|---|
| 333 | +{ |
|---|
| 334 | + return jit->size == 0; |
|---|
| 335 | +} |
|---|
| 336 | + |
|---|
| 337 | +/* |
|---|
| 338 | + * Return whether this is the code generation pass. The code generation pass is |
|---|
| 339 | + * special, since we should change as little as possible. |
|---|
| 340 | + */ |
|---|
| 341 | +static bool is_codegen_pass(struct bpf_jit *jit) |
|---|
| 342 | +{ |
|---|
| 343 | + return jit->prg_buf; |
|---|
| 344 | +} |
|---|
| 345 | + |
|---|
| 346 | +/* |
|---|
| 347 | + * Return whether "rel" can be encoded as a short PC-relative offset |
|---|
| 348 | + */ |
|---|
| 349 | +static bool is_valid_rel(int rel) |
|---|
| 350 | +{ |
|---|
| 351 | + return rel >= -65536 && rel <= 65534; |
|---|
| 352 | +} |
|---|
| 353 | + |
|---|
| 354 | +/* |
|---|
| 355 | + * Return whether "off" can be reached using a short PC-relative offset |
|---|
| 356 | + */ |
|---|
| 357 | +static bool can_use_rel(struct bpf_jit *jit, int off) |
|---|
| 358 | +{ |
|---|
| 359 | + return is_valid_rel(off - jit->prg); |
|---|
| 360 | +} |
|---|
| 361 | + |
|---|
| 362 | +/* |
|---|
| 363 | + * Return whether given displacement can be encoded using |
|---|
| 364 | + * Long-Displacement Facility |
|---|
| 365 | + */ |
|---|
| 366 | +static bool is_valid_ldisp(int disp) |
|---|
| 367 | +{ |
|---|
| 368 | + return disp >= -524288 && disp <= 524287; |
|---|
| 369 | +} |
|---|
| 370 | + |
|---|
| 371 | +/* |
|---|
| 372 | + * Return whether the next 32-bit literal pool entry can be referenced using |
|---|
| 373 | + * Long-Displacement Facility |
|---|
| 374 | + */ |
|---|
| 375 | +static bool can_use_ldisp_for_lit32(struct bpf_jit *jit) |
|---|
| 376 | +{ |
|---|
| 377 | + return is_valid_ldisp(jit->lit32 - jit->base_ip); |
|---|
| 378 | +} |
|---|
| 379 | + |
|---|
| 380 | +/* |
|---|
| 381 | + * Return whether the next 64-bit literal pool entry can be referenced using |
|---|
| 382 | + * Long-Displacement Facility |
|---|
| 383 | + */ |
|---|
| 384 | +static bool can_use_ldisp_for_lit64(struct bpf_jit *jit) |
|---|
| 385 | +{ |
|---|
| 386 | + return is_valid_ldisp(jit->lit64 - jit->base_ip); |
|---|
| 387 | +} |
|---|
| 306 | 388 | |
|---|
| 307 | 389 | /* |
|---|
| 308 | 390 | * Fill whole space with illegal instructions |
|---|
| .. | .. |
|---|
| 381 | 463 | */ |
|---|
| 382 | 464 | static void save_restore_regs(struct bpf_jit *jit, int op, u32 stack_depth) |
|---|
| 383 | 465 | { |
|---|
| 384 | | - |
|---|
| 466 | + const int last = 15, save_restore_size = 6; |
|---|
| 385 | 467 | int re = 6, rs; |
|---|
| 468 | + |
|---|
| 469 | + if (is_first_pass(jit)) { |
|---|
| 470 | + /* |
|---|
| 471 | + * We don't know yet which registers are used. Reserve space |
|---|
| 472 | + * conservatively. |
|---|
| 473 | + */ |
|---|
| 474 | + jit->prg += (last - re + 1) * save_restore_size; |
|---|
| 475 | + return; |
|---|
| 476 | + } |
|---|
| 386 | 477 | |
|---|
| 387 | 478 | do { |
|---|
| 388 | 479 | rs = get_start(jit, re); |
|---|
| .. | .. |
|---|
| 394 | 485 | else |
|---|
| 395 | 486 | restore_regs(jit, rs, re, stack_depth); |
|---|
| 396 | 487 | re++; |
|---|
| 397 | | - } while (re <= 15); |
|---|
| 488 | + } while (re <= last); |
|---|
| 489 | +} |
|---|
| 490 | + |
|---|
| 491 | +static void bpf_skip(struct bpf_jit *jit, int size) |
|---|
| 492 | +{ |
|---|
| 493 | + if (size >= 6 && !is_valid_rel(size)) { |
|---|
| 494 | + /* brcl 0xf,size */ |
|---|
| 495 | + EMIT6_PCREL_RIL(0xc0f4000000, size); |
|---|
| 496 | + size -= 6; |
|---|
| 497 | + } else if (size >= 4 && is_valid_rel(size)) { |
|---|
| 498 | + /* brc 0xf,size */ |
|---|
| 499 | + EMIT4_PCREL(0xa7f40000, size); |
|---|
| 500 | + size -= 4; |
|---|
| 501 | + } |
|---|
| 502 | + while (size >= 2) { |
|---|
| 503 | + /* bcr 0,%0 */ |
|---|
| 504 | + _EMIT2(0x0700); |
|---|
| 505 | + size -= 2; |
|---|
| 506 | + } |
|---|
| 398 | 507 | } |
|---|
| 399 | 508 | |
|---|
| 400 | 509 | /* |
|---|
| .. | .. |
|---|
| 409 | 518 | /* xc STK_OFF_TCCNT(4,%r15),STK_OFF_TCCNT(%r15) */ |
|---|
| 410 | 519 | _EMIT6(0xd703f000 | STK_OFF_TCCNT, 0xf000 | STK_OFF_TCCNT); |
|---|
| 411 | 520 | } else { |
|---|
| 412 | | - /* j tail_call_start: NOP if no tail calls are used */ |
|---|
| 413 | | - EMIT4_PCREL(0xa7f40000, 6); |
|---|
| 414 | | - _EMIT2(0); |
|---|
| 521 | + /* |
|---|
| 522 | + * There are no tail calls. Insert nops in order to have |
|---|
| 523 | + * tail_call_start at a predictable offset. |
|---|
| 524 | + */ |
|---|
| 525 | + bpf_skip(jit, 6); |
|---|
| 415 | 526 | } |
|---|
| 416 | 527 | /* Tail calls have to skip above initialization */ |
|---|
| 417 | 528 | jit->tail_call_start = jit->prg; |
|---|
| 418 | 529 | /* Save registers */ |
|---|
| 419 | 530 | save_restore_regs(jit, REGS_SAVE, stack_depth); |
|---|
| 420 | 531 | /* Setup literal pool */ |
|---|
| 421 | | - if (jit->seen & SEEN_LITERAL) { |
|---|
| 422 | | - /* basr %r13,0 */ |
|---|
| 423 | | - EMIT2(0x0d00, REG_L, REG_0); |
|---|
| 424 | | - jit->base_ip = jit->prg; |
|---|
| 532 | + if (is_first_pass(jit) || (jit->seen & SEEN_LITERAL)) { |
|---|
| 533 | + if (!is_first_pass(jit) && |
|---|
| 534 | + is_valid_ldisp(jit->size - (jit->prg + 2))) { |
|---|
| 535 | + /* basr %l,0 */ |
|---|
| 536 | + EMIT2(0x0d00, REG_L, REG_0); |
|---|
| 537 | + jit->base_ip = jit->prg; |
|---|
| 538 | + } else { |
|---|
| 539 | + /* larl %l,lit32_start */ |
|---|
| 540 | + EMIT6_PCREL_RILB(0xc0000000, REG_L, jit->lit32_start); |
|---|
| 541 | + jit->base_ip = jit->lit32_start; |
|---|
| 542 | + } |
|---|
| 425 | 543 | } |
|---|
| 426 | 544 | /* Setup stack and backchain */ |
|---|
| 427 | | - if (jit->seen & SEEN_STACK) { |
|---|
| 428 | | - if (jit->seen & SEEN_FUNC) |
|---|
| 545 | + if (is_first_pass(jit) || (jit->seen & SEEN_STACK)) { |
|---|
| 546 | + if (is_first_pass(jit) || (jit->seen & SEEN_FUNC)) |
|---|
| 429 | 547 | /* lgr %w1,%r15 (backchain) */ |
|---|
| 430 | 548 | EMIT4(0xb9040000, REG_W1, REG_15); |
|---|
| 431 | 549 | /* la %bfp,STK_160_UNUSED(%r15) (BPF frame pointer) */ |
|---|
| 432 | 550 | EMIT4_DISP(0x41000000, BPF_REG_FP, REG_15, STK_160_UNUSED); |
|---|
| 433 | 551 | /* aghi %r15,-STK_OFF */ |
|---|
| 434 | 552 | EMIT4_IMM(0xa70b0000, REG_15, -(STK_OFF + stack_depth)); |
|---|
| 435 | | - if (jit->seen & SEEN_FUNC) |
|---|
| 553 | + if (is_first_pass(jit) || (jit->seen & SEEN_FUNC)) |
|---|
| 436 | 554 | /* stg %w1,152(%r15) (backchain) */ |
|---|
| 437 | 555 | EMIT6_DISP_LH(0xe3000000, 0x0024, REG_W1, REG_0, |
|---|
| 438 | 556 | REG_15, 152); |
|---|
| .. | .. |
|---|
| 444 | 562 | */ |
|---|
| 445 | 563 | static void bpf_jit_epilogue(struct bpf_jit *jit, u32 stack_depth) |
|---|
| 446 | 564 | { |
|---|
| 447 | | - /* Return 0 */ |
|---|
| 448 | | - if (jit->seen & SEEN_RET0) { |
|---|
| 449 | | - jit->ret0_ip = jit->prg; |
|---|
| 450 | | - /* lghi %b0,0 */ |
|---|
| 451 | | - EMIT4_IMM(0xa7090000, BPF_REG_0, 0); |
|---|
| 452 | | - } |
|---|
| 453 | 565 | jit->exit_ip = jit->prg; |
|---|
| 454 | 566 | /* Load exit code: lgr %r2,%b0 */ |
|---|
| 455 | 567 | EMIT4(0xb9040000, REG_2, BPF_REG_0); |
|---|
| 456 | 568 | /* Restore registers */ |
|---|
| 457 | 569 | save_restore_regs(jit, REGS_RESTORE, stack_depth); |
|---|
| 458 | | - if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable) { |
|---|
| 570 | + if (__is_defined(CC_USING_EXPOLINE) && !nospec_disable) { |
|---|
| 459 | 571 | jit->r14_thunk_ip = jit->prg; |
|---|
| 460 | 572 | /* Generate __s390_indirect_jump_r14 thunk */ |
|---|
| 461 | 573 | if (test_facility(35)) { |
|---|
| .. | .. |
|---|
| 473 | 585 | /* br %r14 */ |
|---|
| 474 | 586 | _EMIT2(0x07fe); |
|---|
| 475 | 587 | |
|---|
| 476 | | - if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable && |
|---|
| 477 | | - (jit->seen & SEEN_FUNC)) { |
|---|
| 588 | + if (__is_defined(CC_USING_EXPOLINE) && !nospec_disable && |
|---|
| 589 | + (is_first_pass(jit) || (jit->seen & SEEN_FUNC))) { |
|---|
| 478 | 590 | jit->r1_thunk_ip = jit->prg; |
|---|
| 479 | 591 | /* Generate __s390_indirect_jump_r1 thunk */ |
|---|
| 480 | 592 | if (test_facility(35)) { |
|---|
| .. | .. |
|---|
| 494 | 606 | } |
|---|
| 495 | 607 | } |
|---|
| 496 | 608 | |
|---|
| 609 | +static int get_probe_mem_regno(const u8 *insn) |
|---|
| 610 | +{ |
|---|
| 611 | + /* |
|---|
| 612 | + * insn must point to llgc, llgh, llgf or lg, which have destination |
|---|
| 613 | + * register at the same position. |
|---|
| 614 | + */ |
|---|
| 615 | + if (insn[0] != 0xe3) /* common llgc, llgh, llgf and lg prefix */ |
|---|
| 616 | + return -1; |
|---|
| 617 | + if (insn[5] != 0x90 && /* llgc */ |
|---|
| 618 | + insn[5] != 0x91 && /* llgh */ |
|---|
| 619 | + insn[5] != 0x16 && /* llgf */ |
|---|
| 620 | + insn[5] != 0x04) /* lg */ |
|---|
| 621 | + return -1; |
|---|
| 622 | + return insn[1] >> 4; |
|---|
| 623 | +} |
|---|
| 624 | + |
|---|
| 625 | +static bool ex_handler_bpf(const struct exception_table_entry *x, |
|---|
| 626 | + struct pt_regs *regs) |
|---|
| 627 | +{ |
|---|
| 628 | + int regno; |
|---|
| 629 | + u8 *insn; |
|---|
| 630 | + |
|---|
| 631 | + regs->psw.addr = extable_fixup(x); |
|---|
| 632 | + insn = (u8 *)__rewind_psw(regs->psw, regs->int_code >> 16); |
|---|
| 633 | + regno = get_probe_mem_regno(insn); |
|---|
| 634 | + if (WARN_ON_ONCE(regno < 0)) |
|---|
| 635 | + /* JIT bug - unexpected instruction. */ |
|---|
| 636 | + return false; |
|---|
| 637 | + regs->gprs[regno] = 0; |
|---|
| 638 | + return true; |
|---|
| 639 | +} |
|---|
| 640 | + |
|---|
| 641 | +static int bpf_jit_probe_mem(struct bpf_jit *jit, struct bpf_prog *fp, |
|---|
| 642 | + int probe_prg, int nop_prg) |
|---|
| 643 | +{ |
|---|
| 644 | + struct exception_table_entry *ex; |
|---|
| 645 | + s64 delta; |
|---|
| 646 | + u8 *insn; |
|---|
| 647 | + int prg; |
|---|
| 648 | + int i; |
|---|
| 649 | + |
|---|
| 650 | + if (!fp->aux->extable) |
|---|
| 651 | + /* Do nothing during early JIT passes. */ |
|---|
| 652 | + return 0; |
|---|
| 653 | + insn = jit->prg_buf + probe_prg; |
|---|
| 654 | + if (WARN_ON_ONCE(get_probe_mem_regno(insn) < 0)) |
|---|
| 655 | + /* JIT bug - unexpected probe instruction. */ |
|---|
| 656 | + return -1; |
|---|
| 657 | + if (WARN_ON_ONCE(probe_prg + insn_length(*insn) != nop_prg)) |
|---|
| 658 | + /* JIT bug - gap between probe and nop instructions. */ |
|---|
| 659 | + return -1; |
|---|
| 660 | + for (i = 0; i < 2; i++) { |
|---|
| 661 | + if (WARN_ON_ONCE(jit->excnt >= fp->aux->num_exentries)) |
|---|
| 662 | + /* Verifier bug - not enough entries. */ |
|---|
| 663 | + return -1; |
|---|
| 664 | + ex = &fp->aux->extable[jit->excnt]; |
|---|
| 665 | + /* Add extable entries for probe and nop instructions. */ |
|---|
| 666 | + prg = i == 0 ? probe_prg : nop_prg; |
|---|
| 667 | + delta = jit->prg_buf + prg - (u8 *)&ex->insn; |
|---|
| 668 | + if (WARN_ON_ONCE(delta < INT_MIN || delta > INT_MAX)) |
|---|
| 669 | + /* JIT bug - code and extable must be close. */ |
|---|
| 670 | + return -1; |
|---|
| 671 | + ex->insn = delta; |
|---|
| 672 | + /* |
|---|
| 673 | + * Always land on the nop. Note that extable infrastructure |
|---|
| 674 | + * ignores fixup field, it is handled by ex_handler_bpf(). |
|---|
| 675 | + */ |
|---|
| 676 | + delta = jit->prg_buf + nop_prg - (u8 *)&ex->fixup; |
|---|
| 677 | + if (WARN_ON_ONCE(delta < INT_MIN || delta > INT_MAX)) |
|---|
| 678 | + /* JIT bug - landing pad and extable must be close. */ |
|---|
| 679 | + return -1; |
|---|
| 680 | + ex->fixup = delta; |
|---|
| 681 | + ex->handler = (u8 *)ex_handler_bpf - (u8 *)&ex->handler; |
|---|
| 682 | + jit->excnt++; |
|---|
| 683 | + } |
|---|
| 684 | + return 0; |
|---|
| 685 | +} |
|---|
| 686 | + |
|---|
| 497 | 687 | /* |
|---|
| 498 | 688 | * Compile one eBPF instruction into s390x code |
|---|
| 499 | 689 | * |
|---|
| 500 | 690 | * NOTE: Use noinline because for gcov (-fprofile-arcs) gcc allocates a lot of |
|---|
| 501 | 691 | * stack space for the large switch statement. |
|---|
| 502 | 692 | */ |
|---|
| 503 | | -static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i) |
|---|
| 693 | +static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, |
|---|
| 694 | + int i, bool extra_pass, u32 stack_depth) |
|---|
| 504 | 695 | { |
|---|
| 505 | 696 | struct bpf_insn *insn = &fp->insnsi[i]; |
|---|
| 506 | | - int jmp_off, last, insn_count = 1; |
|---|
| 507 | 697 | u32 dst_reg = insn->dst_reg; |
|---|
| 508 | 698 | u32 src_reg = insn->src_reg; |
|---|
| 699 | + int last, insn_count = 1; |
|---|
| 509 | 700 | u32 *addrs = jit->addrs; |
|---|
| 510 | 701 | s32 imm = insn->imm; |
|---|
| 511 | 702 | s16 off = insn->off; |
|---|
| 703 | + int probe_prg = -1; |
|---|
| 512 | 704 | unsigned int mask; |
|---|
| 705 | + int nop_prg; |
|---|
| 706 | + int err; |
|---|
| 513 | 707 | |
|---|
| 514 | | - if (dst_reg == BPF_REG_AX || src_reg == BPF_REG_AX) |
|---|
| 515 | | - jit->seen |= SEEN_REG_AX; |
|---|
| 708 | + if (BPF_CLASS(insn->code) == BPF_LDX && |
|---|
| 709 | + BPF_MODE(insn->code) == BPF_PROBE_MEM) |
|---|
| 710 | + probe_prg = jit->prg; |
|---|
| 711 | + |
|---|
| 516 | 712 | switch (insn->code) { |
|---|
| 517 | 713 | /* |
|---|
| 518 | 714 | * BPF_MOV |
|---|
| .. | .. |
|---|
| 520 | 716 | case BPF_ALU | BPF_MOV | BPF_X: /* dst = (u32) src */ |
|---|
| 521 | 717 | /* llgfr %dst,%src */ |
|---|
| 522 | 718 | EMIT4(0xb9160000, dst_reg, src_reg); |
|---|
| 719 | + if (insn_is_zext(&insn[1])) |
|---|
| 720 | + insn_count = 2; |
|---|
| 523 | 721 | break; |
|---|
| 524 | 722 | case BPF_ALU64 | BPF_MOV | BPF_X: /* dst = src */ |
|---|
| 525 | 723 | /* lgr %dst,%src */ |
|---|
| .. | .. |
|---|
| 528 | 726 | case BPF_ALU | BPF_MOV | BPF_K: /* dst = (u32) imm */ |
|---|
| 529 | 727 | /* llilf %dst,imm */ |
|---|
| 530 | 728 | EMIT6_IMM(0xc00f0000, dst_reg, imm); |
|---|
| 729 | + if (insn_is_zext(&insn[1])) |
|---|
| 730 | + insn_count = 2; |
|---|
| 531 | 731 | break; |
|---|
| 532 | 732 | case BPF_ALU64 | BPF_MOV | BPF_K: /* dst = imm */ |
|---|
| 533 | 733 | /* lgfi %dst,imm */ |
|---|
| .. | .. |
|---|
| 542 | 742 | u64 imm64; |
|---|
| 543 | 743 | |
|---|
| 544 | 744 | imm64 = (u64)(u32) insn[0].imm | ((u64)(u32) insn[1].imm) << 32; |
|---|
| 545 | | - /* lg %dst,<d(imm)>(%l) */ |
|---|
| 546 | | - EMIT6_DISP_LH(0xe3000000, 0x0004, dst_reg, REG_0, REG_L, |
|---|
| 547 | | - EMIT_CONST_U64(imm64)); |
|---|
| 745 | + /* lgrl %dst,imm */ |
|---|
| 746 | + EMIT6_PCREL_RILB(0xc4080000, dst_reg, _EMIT_CONST_U64(imm64)); |
|---|
| 548 | 747 | insn_count = 2; |
|---|
| 549 | 748 | break; |
|---|
| 550 | 749 | } |
|---|
| .. | .. |
|---|
| 644 | 843 | EMIT4(0xb9970000, REG_W0, src_reg); |
|---|
| 645 | 844 | /* llgfr %dst,%rc */ |
|---|
| 646 | 845 | EMIT4(0xb9160000, dst_reg, rc_reg); |
|---|
| 846 | + if (insn_is_zext(&insn[1])) |
|---|
| 847 | + insn_count = 2; |
|---|
| 647 | 848 | break; |
|---|
| 648 | 849 | } |
|---|
| 649 | 850 | case BPF_ALU64 | BPF_DIV | BPF_X: /* dst = dst / src */ |
|---|
| .. | .. |
|---|
| 678 | 879 | EMIT4_IMM(0xa7080000, REG_W0, 0); |
|---|
| 679 | 880 | /* lr %w1,%dst */ |
|---|
| 680 | 881 | EMIT2(0x1800, REG_W1, dst_reg); |
|---|
| 681 | | - /* dl %w0,<d(imm)>(%l) */ |
|---|
| 682 | | - EMIT6_DISP_LH(0xe3000000, 0x0097, REG_W0, REG_0, REG_L, |
|---|
| 683 | | - EMIT_CONST_U32(imm)); |
|---|
| 882 | + if (!is_first_pass(jit) && can_use_ldisp_for_lit32(jit)) { |
|---|
| 883 | + /* dl %w0,<d(imm)>(%l) */ |
|---|
| 884 | + EMIT6_DISP_LH(0xe3000000, 0x0097, REG_W0, REG_0, REG_L, |
|---|
| 885 | + EMIT_CONST_U32(imm)); |
|---|
| 886 | + } else { |
|---|
| 887 | + /* lgfrl %dst,imm */ |
|---|
| 888 | + EMIT6_PCREL_RILB(0xc40c0000, dst_reg, |
|---|
| 889 | + _EMIT_CONST_U32(imm)); |
|---|
| 890 | + jit->seen |= SEEN_LITERAL; |
|---|
| 891 | + /* dlr %w0,%dst */ |
|---|
| 892 | + EMIT4(0xb9970000, REG_W0, dst_reg); |
|---|
| 893 | + } |
|---|
| 684 | 894 | /* llgfr %dst,%rc */ |
|---|
| 685 | 895 | EMIT4(0xb9160000, dst_reg, rc_reg); |
|---|
| 896 | + if (insn_is_zext(&insn[1])) |
|---|
| 897 | + insn_count = 2; |
|---|
| 686 | 898 | break; |
|---|
| 687 | 899 | } |
|---|
| 688 | 900 | case BPF_ALU64 | BPF_DIV | BPF_K: /* dst = dst / imm */ |
|---|
| .. | .. |
|---|
| 700 | 912 | EMIT4_IMM(0xa7090000, REG_W0, 0); |
|---|
| 701 | 913 | /* lgr %w1,%dst */ |
|---|
| 702 | 914 | EMIT4(0xb9040000, REG_W1, dst_reg); |
|---|
| 703 | | - /* dlg %w0,<d(imm)>(%l) */ |
|---|
| 704 | | - EMIT6_DISP_LH(0xe3000000, 0x0087, REG_W0, REG_0, REG_L, |
|---|
| 705 | | - EMIT_CONST_U64(imm)); |
|---|
| 915 | + if (!is_first_pass(jit) && can_use_ldisp_for_lit64(jit)) { |
|---|
| 916 | + /* dlg %w0,<d(imm)>(%l) */ |
|---|
| 917 | + EMIT6_DISP_LH(0xe3000000, 0x0087, REG_W0, REG_0, REG_L, |
|---|
| 918 | + EMIT_CONST_U64(imm)); |
|---|
| 919 | + } else { |
|---|
| 920 | + /* lgrl %dst,imm */ |
|---|
| 921 | + EMIT6_PCREL_RILB(0xc4080000, dst_reg, |
|---|
| 922 | + _EMIT_CONST_U64(imm)); |
|---|
| 923 | + jit->seen |= SEEN_LITERAL; |
|---|
| 924 | + /* dlgr %w0,%dst */ |
|---|
| 925 | + EMIT4(0xb9870000, REG_W0, dst_reg); |
|---|
| 926 | + } |
|---|
| 706 | 927 | /* lgr %dst,%rc */ |
|---|
| 707 | 928 | EMIT4(0xb9040000, dst_reg, rc_reg); |
|---|
| 708 | 929 | break; |
|---|
| .. | .. |
|---|
| 725 | 946 | EMIT_ZERO(dst_reg); |
|---|
| 726 | 947 | break; |
|---|
| 727 | 948 | case BPF_ALU64 | BPF_AND | BPF_K: /* dst = dst & imm */ |
|---|
| 728 | | - /* ng %dst,<d(imm)>(%l) */ |
|---|
| 729 | | - EMIT6_DISP_LH(0xe3000000, 0x0080, dst_reg, REG_0, REG_L, |
|---|
| 730 | | - EMIT_CONST_U64(imm)); |
|---|
| 949 | + if (!is_first_pass(jit) && can_use_ldisp_for_lit64(jit)) { |
|---|
| 950 | + /* ng %dst,<d(imm)>(%l) */ |
|---|
| 951 | + EMIT6_DISP_LH(0xe3000000, 0x0080, |
|---|
| 952 | + dst_reg, REG_0, REG_L, |
|---|
| 953 | + EMIT_CONST_U64(imm)); |
|---|
| 954 | + } else { |
|---|
| 955 | + /* lgrl %w0,imm */ |
|---|
| 956 | + EMIT6_PCREL_RILB(0xc4080000, REG_W0, |
|---|
| 957 | + _EMIT_CONST_U64(imm)); |
|---|
| 958 | + jit->seen |= SEEN_LITERAL; |
|---|
| 959 | + /* ngr %dst,%w0 */ |
|---|
| 960 | + EMIT4(0xb9800000, dst_reg, REG_W0); |
|---|
| 961 | + } |
|---|
| 731 | 962 | break; |
|---|
| 732 | 963 | /* |
|---|
| 733 | 964 | * BPF_OR |
|---|
| .. | .. |
|---|
| 747 | 978 | EMIT_ZERO(dst_reg); |
|---|
| 748 | 979 | break; |
|---|
| 749 | 980 | case BPF_ALU64 | BPF_OR | BPF_K: /* dst = dst | imm */ |
|---|
| 750 | | - /* og %dst,<d(imm)>(%l) */ |
|---|
| 751 | | - EMIT6_DISP_LH(0xe3000000, 0x0081, dst_reg, REG_0, REG_L, |
|---|
| 752 | | - EMIT_CONST_U64(imm)); |
|---|
| 981 | + if (!is_first_pass(jit) && can_use_ldisp_for_lit64(jit)) { |
|---|
| 982 | + /* og %dst,<d(imm)>(%l) */ |
|---|
| 983 | + EMIT6_DISP_LH(0xe3000000, 0x0081, |
|---|
| 984 | + dst_reg, REG_0, REG_L, |
|---|
| 985 | + EMIT_CONST_U64(imm)); |
|---|
| 986 | + } else { |
|---|
| 987 | + /* lgrl %w0,imm */ |
|---|
| 988 | + EMIT6_PCREL_RILB(0xc4080000, REG_W0, |
|---|
| 989 | + _EMIT_CONST_U64(imm)); |
|---|
| 990 | + jit->seen |= SEEN_LITERAL; |
|---|
| 991 | + /* ogr %dst,%w0 */ |
|---|
| 992 | + EMIT4(0xb9810000, dst_reg, REG_W0); |
|---|
| 993 | + } |
|---|
| 753 | 994 | break; |
|---|
| 754 | 995 | /* |
|---|
| 755 | 996 | * BPF_XOR |
|---|
| .. | .. |
|---|
| 771 | 1012 | EMIT_ZERO(dst_reg); |
|---|
| 772 | 1013 | break; |
|---|
| 773 | 1014 | case BPF_ALU64 | BPF_XOR | BPF_K: /* dst = dst ^ imm */ |
|---|
| 774 | | - /* xg %dst,<d(imm)>(%l) */ |
|---|
| 775 | | - EMIT6_DISP_LH(0xe3000000, 0x0082, dst_reg, REG_0, REG_L, |
|---|
| 776 | | - EMIT_CONST_U64(imm)); |
|---|
| 1015 | + if (!is_first_pass(jit) && can_use_ldisp_for_lit64(jit)) { |
|---|
| 1016 | + /* xg %dst,<d(imm)>(%l) */ |
|---|
| 1017 | + EMIT6_DISP_LH(0xe3000000, 0x0082, |
|---|
| 1018 | + dst_reg, REG_0, REG_L, |
|---|
| 1019 | + EMIT_CONST_U64(imm)); |
|---|
| 1020 | + } else { |
|---|
| 1021 | + /* lgrl %w0,imm */ |
|---|
| 1022 | + EMIT6_PCREL_RILB(0xc4080000, REG_W0, |
|---|
| 1023 | + _EMIT_CONST_U64(imm)); |
|---|
| 1024 | + jit->seen |= SEEN_LITERAL; |
|---|
| 1025 | + /* xgr %dst,%w0 */ |
|---|
| 1026 | + EMIT4(0xb9820000, dst_reg, REG_W0); |
|---|
| 1027 | + } |
|---|
| 777 | 1028 | break; |
|---|
| 778 | 1029 | /* |
|---|
| 779 | 1030 | * BPF_LSH |
|---|
| .. | .. |
|---|
| 828 | 1079 | /* |
|---|
| 829 | 1080 | * BPF_ARSH |
|---|
| 830 | 1081 | */ |
|---|
| 1082 | + case BPF_ALU | BPF_ARSH | BPF_X: /* ((s32) dst) >>= src */ |
|---|
| 1083 | + /* sra %dst,%dst,0(%src) */ |
|---|
| 1084 | + EMIT4_DISP(0x8a000000, dst_reg, src_reg, 0); |
|---|
| 1085 | + EMIT_ZERO(dst_reg); |
|---|
| 1086 | + break; |
|---|
| 831 | 1087 | case BPF_ALU64 | BPF_ARSH | BPF_X: /* ((s64) dst) >>= src */ |
|---|
| 832 | 1088 | /* srag %dst,%dst,0(%src) */ |
|---|
| 833 | 1089 | EMIT6_DISP_LH(0xeb000000, 0x000a, dst_reg, dst_reg, src_reg, 0); |
|---|
| 1090 | + break; |
|---|
| 1091 | + case BPF_ALU | BPF_ARSH | BPF_K: /* ((s32) dst >> imm */ |
|---|
| 1092 | + if (imm != 0) { |
|---|
| 1093 | + /* sra %dst,imm(%r0) */ |
|---|
| 1094 | + EMIT4_DISP(0x8a000000, dst_reg, REG_0, imm); |
|---|
| 1095 | + } |
|---|
| 1096 | + EMIT_ZERO(dst_reg); |
|---|
| 834 | 1097 | break; |
|---|
| 835 | 1098 | case BPF_ALU64 | BPF_ARSH | BPF_K: /* ((s64) dst) >>= imm */ |
|---|
| 836 | 1099 | if (imm == 0) |
|---|
| .. | .. |
|---|
| 859 | 1122 | case 16: /* dst = (u16) cpu_to_be16(dst) */ |
|---|
| 860 | 1123 | /* llghr %dst,%dst */ |
|---|
| 861 | 1124 | EMIT4(0xb9850000, dst_reg, dst_reg); |
|---|
| 1125 | + if (insn_is_zext(&insn[1])) |
|---|
| 1126 | + insn_count = 2; |
|---|
| 862 | 1127 | break; |
|---|
| 863 | 1128 | case 32: /* dst = (u32) cpu_to_be32(dst) */ |
|---|
| 864 | | - /* llgfr %dst,%dst */ |
|---|
| 865 | | - EMIT4(0xb9160000, dst_reg, dst_reg); |
|---|
| 1129 | + if (!fp->aux->verifier_zext) |
|---|
| 1130 | + /* llgfr %dst,%dst */ |
|---|
| 1131 | + EMIT4(0xb9160000, dst_reg, dst_reg); |
|---|
| 866 | 1132 | break; |
|---|
| 867 | 1133 | case 64: /* dst = (u64) cpu_to_be64(dst) */ |
|---|
| 868 | 1134 | break; |
|---|
| .. | .. |
|---|
| 877 | 1143 | EMIT4_DISP(0x88000000, dst_reg, REG_0, 16); |
|---|
| 878 | 1144 | /* llghr %dst,%dst */ |
|---|
| 879 | 1145 | EMIT4(0xb9850000, dst_reg, dst_reg); |
|---|
| 1146 | + if (insn_is_zext(&insn[1])) |
|---|
| 1147 | + insn_count = 2; |
|---|
| 880 | 1148 | break; |
|---|
| 881 | 1149 | case 32: /* dst = (u32) cpu_to_le32(dst) */ |
|---|
| 882 | 1150 | /* lrvr %dst,%dst */ |
|---|
| 883 | 1151 | EMIT4(0xb91f0000, dst_reg, dst_reg); |
|---|
| 884 | | - /* llgfr %dst,%dst */ |
|---|
| 885 | | - EMIT4(0xb9160000, dst_reg, dst_reg); |
|---|
| 1152 | + if (!fp->aux->verifier_zext) |
|---|
| 1153 | + /* llgfr %dst,%dst */ |
|---|
| 1154 | + EMIT4(0xb9160000, dst_reg, dst_reg); |
|---|
| 886 | 1155 | break; |
|---|
| 887 | 1156 | case 64: /* dst = (u64) cpu_to_le64(dst) */ |
|---|
| 888 | 1157 | /* lrvgr %dst,%dst */ |
|---|
| .. | .. |
|---|
| 965 | 1234 | * BPF_LDX |
|---|
| 966 | 1235 | */ |
|---|
| 967 | 1236 | case BPF_LDX | BPF_MEM | BPF_B: /* dst = *(u8 *)(ul) (src + off) */ |
|---|
| 1237 | + case BPF_LDX | BPF_PROBE_MEM | BPF_B: |
|---|
| 968 | 1238 | /* llgc %dst,0(off,%src) */ |
|---|
| 969 | 1239 | EMIT6_DISP_LH(0xe3000000, 0x0090, dst_reg, src_reg, REG_0, off); |
|---|
| 970 | 1240 | jit->seen |= SEEN_MEM; |
|---|
| 1241 | + if (insn_is_zext(&insn[1])) |
|---|
| 1242 | + insn_count = 2; |
|---|
| 971 | 1243 | break; |
|---|
| 972 | 1244 | case BPF_LDX | BPF_MEM | BPF_H: /* dst = *(u16 *)(ul) (src + off) */ |
|---|
| 1245 | + case BPF_LDX | BPF_PROBE_MEM | BPF_H: |
|---|
| 973 | 1246 | /* llgh %dst,0(off,%src) */ |
|---|
| 974 | 1247 | EMIT6_DISP_LH(0xe3000000, 0x0091, dst_reg, src_reg, REG_0, off); |
|---|
| 975 | 1248 | jit->seen |= SEEN_MEM; |
|---|
| 1249 | + if (insn_is_zext(&insn[1])) |
|---|
| 1250 | + insn_count = 2; |
|---|
| 976 | 1251 | break; |
|---|
| 977 | 1252 | case BPF_LDX | BPF_MEM | BPF_W: /* dst = *(u32 *)(ul) (src + off) */ |
|---|
| 1253 | + case BPF_LDX | BPF_PROBE_MEM | BPF_W: |
|---|
| 978 | 1254 | /* llgf %dst,off(%src) */ |
|---|
| 979 | 1255 | jit->seen |= SEEN_MEM; |
|---|
| 980 | 1256 | EMIT6_DISP_LH(0xe3000000, 0x0016, dst_reg, src_reg, REG_0, off); |
|---|
| 1257 | + if (insn_is_zext(&insn[1])) |
|---|
| 1258 | + insn_count = 2; |
|---|
| 981 | 1259 | break; |
|---|
| 982 | 1260 | case BPF_LDX | BPF_MEM | BPF_DW: /* dst = *(u64 *)(ul) (src + off) */ |
|---|
| 1261 | + case BPF_LDX | BPF_PROBE_MEM | BPF_DW: |
|---|
| 983 | 1262 | /* lg %dst,0(off,%src) */ |
|---|
| 984 | 1263 | jit->seen |= SEEN_MEM; |
|---|
| 985 | 1264 | EMIT6_DISP_LH(0xe3000000, 0x0004, dst_reg, src_reg, REG_0, off); |
|---|
| .. | .. |
|---|
| 989 | 1268 | */ |
|---|
| 990 | 1269 | case BPF_JMP | BPF_CALL: |
|---|
| 991 | 1270 | { |
|---|
| 992 | | - /* |
|---|
| 993 | | - * b0 = (__bpf_call_base + imm)(b1, b2, b3, b4, b5) |
|---|
| 994 | | - */ |
|---|
| 995 | | - const u64 func = (u64)__bpf_call_base + imm; |
|---|
| 1271 | + u64 func; |
|---|
| 1272 | + bool func_addr_fixed; |
|---|
| 1273 | + int ret; |
|---|
| 1274 | + |
|---|
| 1275 | + ret = bpf_jit_get_func_addr(fp, insn, extra_pass, |
|---|
| 1276 | + &func, &func_addr_fixed); |
|---|
| 1277 | + if (ret < 0) |
|---|
| 1278 | + return -1; |
|---|
| 996 | 1279 | |
|---|
| 997 | 1280 | REG_SET_SEEN(BPF_REG_5); |
|---|
| 998 | 1281 | jit->seen |= SEEN_FUNC; |
|---|
| 999 | | - /* lg %w1,<d(imm)>(%l) */ |
|---|
| 1000 | | - EMIT6_DISP_LH(0xe3000000, 0x0004, REG_W1, REG_0, REG_L, |
|---|
| 1001 | | - EMIT_CONST_U64(func)); |
|---|
| 1002 | | - if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable) { |
|---|
| 1282 | + /* lgrl %w1,func */ |
|---|
| 1283 | + EMIT6_PCREL_RILB(0xc4080000, REG_W1, _EMIT_CONST_U64(func)); |
|---|
| 1284 | + if (__is_defined(CC_USING_EXPOLINE) && !nospec_disable) { |
|---|
| 1003 | 1285 | /* brasl %r14,__s390_indirect_jump_r1 */ |
|---|
| 1004 | 1286 | EMIT6_PCREL_RILB(0xc0050000, REG_14, jit->r1_thunk_ip); |
|---|
| 1005 | 1287 | } else { |
|---|
| .. | .. |
|---|
| 1010 | 1292 | EMIT4(0xb9040000, BPF_REG_0, REG_2); |
|---|
| 1011 | 1293 | break; |
|---|
| 1012 | 1294 | } |
|---|
| 1013 | | - case BPF_JMP | BPF_TAIL_CALL: |
|---|
| 1295 | + case BPF_JMP | BPF_TAIL_CALL: { |
|---|
| 1296 | + int patch_1_clrj, patch_2_clij, patch_3_brc; |
|---|
| 1297 | + |
|---|
| 1014 | 1298 | /* |
|---|
| 1015 | 1299 | * Implicit input: |
|---|
| 1016 | 1300 | * B1: pointer to ctx |
|---|
| .. | .. |
|---|
| 1027 | 1311 | /* llgf %w1,map.max_entries(%b2) */ |
|---|
| 1028 | 1312 | EMIT6_DISP_LH(0xe3000000, 0x0016, REG_W1, REG_0, BPF_REG_2, |
|---|
| 1029 | 1313 | offsetof(struct bpf_array, map.max_entries)); |
|---|
| 1030 | | - /* clrj %b3,%w1,0xa,label0: if (u32)%b3 >= (u32)%w1 goto out */ |
|---|
| 1031 | | - EMIT6_PCREL_LABEL(0xec000000, 0x0077, BPF_REG_3, |
|---|
| 1032 | | - REG_W1, 0, 0xa); |
|---|
| 1314 | + /* if ((u32)%b3 >= (u32)%w1) goto out; */ |
|---|
| 1315 | + /* clrj %b3,%w1,0xa,out */ |
|---|
| 1316 | + patch_1_clrj = jit->prg; |
|---|
| 1317 | + EMIT6_PCREL_RIEB(0xec000000, 0x0077, BPF_REG_3, REG_W1, 0xa, |
|---|
| 1318 | + jit->prg); |
|---|
| 1033 | 1319 | |
|---|
| 1034 | 1320 | /* |
|---|
| 1035 | 1321 | * if (tail_call_cnt++ > MAX_TAIL_CALL_CNT) |
|---|
| .. | .. |
|---|
| 1037 | 1323 | */ |
|---|
| 1038 | 1324 | |
|---|
| 1039 | 1325 | if (jit->seen & SEEN_STACK) |
|---|
| 1040 | | - off = STK_OFF_TCCNT + STK_OFF + fp->aux->stack_depth; |
|---|
| 1326 | + off = STK_OFF_TCCNT + STK_OFF + stack_depth; |
|---|
| 1041 | 1327 | else |
|---|
| 1042 | 1328 | off = STK_OFF_TCCNT; |
|---|
| 1043 | 1329 | /* lhi %w0,1 */ |
|---|
| 1044 | 1330 | EMIT4_IMM(0xa7080000, REG_W0, 1); |
|---|
| 1045 | 1331 | /* laal %w1,%w0,off(%r15) */ |
|---|
| 1046 | 1332 | EMIT6_DISP_LH(0xeb000000, 0x00fa, REG_W1, REG_W0, REG_15, off); |
|---|
| 1047 | | - /* clij %w1,MAX_TAIL_CALL_CNT,0x2,label0 */ |
|---|
| 1048 | | - EMIT6_PCREL_IMM_LABEL(0xec000000, 0x007f, REG_W1, |
|---|
| 1049 | | - MAX_TAIL_CALL_CNT, 0, 0x2); |
|---|
| 1333 | + /* clij %w1,MAX_TAIL_CALL_CNT,0x2,out */ |
|---|
| 1334 | + patch_2_clij = jit->prg; |
|---|
| 1335 | + EMIT6_PCREL_RIEC(0xec000000, 0x007f, REG_W1, MAX_TAIL_CALL_CNT, |
|---|
| 1336 | + 2, jit->prg); |
|---|
| 1050 | 1337 | |
|---|
| 1051 | 1338 | /* |
|---|
| 1052 | 1339 | * prog = array->ptrs[index]; |
|---|
| .. | .. |
|---|
| 1058 | 1345 | EMIT4(0xb9160000, REG_1, BPF_REG_3); |
|---|
| 1059 | 1346 | /* sllg %r1,%r1,3: %r1 *= 8 */ |
|---|
| 1060 | 1347 | EMIT6_DISP_LH(0xeb000000, 0x000d, REG_1, REG_1, REG_0, 3); |
|---|
| 1061 | | - /* lg %r1,prog(%b2,%r1) */ |
|---|
| 1062 | | - EMIT6_DISP_LH(0xe3000000, 0x0004, REG_1, BPF_REG_2, |
|---|
| 1348 | + /* ltg %r1,prog(%b2,%r1) */ |
|---|
| 1349 | + EMIT6_DISP_LH(0xe3000000, 0x0002, REG_1, BPF_REG_2, |
|---|
| 1063 | 1350 | REG_1, offsetof(struct bpf_array, ptrs)); |
|---|
| 1064 | | - /* clgij %r1,0,0x8,label0 */ |
|---|
| 1065 | | - EMIT6_PCREL_IMM_LABEL(0xec000000, 0x007d, REG_1, 0, 0, 0x8); |
|---|
| 1351 | + /* brc 0x8,out */ |
|---|
| 1352 | + patch_3_brc = jit->prg; |
|---|
| 1353 | + EMIT4_PCREL_RIC(0xa7040000, 8, jit->prg); |
|---|
| 1066 | 1354 | |
|---|
| 1067 | 1355 | /* |
|---|
| 1068 | 1356 | * Restore registers before calling function |
|---|
| 1069 | 1357 | */ |
|---|
| 1070 | | - save_restore_regs(jit, REGS_RESTORE, fp->aux->stack_depth); |
|---|
| 1358 | + save_restore_regs(jit, REGS_RESTORE, stack_depth); |
|---|
| 1071 | 1359 | |
|---|
| 1072 | 1360 | /* |
|---|
| 1073 | 1361 | * goto *(prog->bpf_func + tail_call_start); |
|---|
| .. | .. |
|---|
| 1079 | 1367 | /* bc 0xf,tail_call_start(%r1) */ |
|---|
| 1080 | 1368 | _EMIT4(0x47f01000 + jit->tail_call_start); |
|---|
| 1081 | 1369 | /* out: */ |
|---|
| 1082 | | - jit->labels[0] = jit->prg; |
|---|
| 1370 | + if (jit->prg_buf) { |
|---|
| 1371 | + *(u16 *)(jit->prg_buf + patch_1_clrj + 2) = |
|---|
| 1372 | + (jit->prg - patch_1_clrj) >> 1; |
|---|
| 1373 | + *(u16 *)(jit->prg_buf + patch_2_clij + 2) = |
|---|
| 1374 | + (jit->prg - patch_2_clij) >> 1; |
|---|
| 1375 | + *(u16 *)(jit->prg_buf + patch_3_brc + 2) = |
|---|
| 1376 | + (jit->prg - patch_3_brc) >> 1; |
|---|
| 1377 | + } |
|---|
| 1083 | 1378 | break; |
|---|
| 1379 | + } |
|---|
| 1084 | 1380 | case BPF_JMP | BPF_EXIT: /* return b0 */ |
|---|
| 1085 | 1381 | last = (i == fp->len - 1) ? 1 : 0; |
|---|
| 1086 | | - if (last && !(jit->seen & SEEN_RET0)) |
|---|
| 1382 | + if (last) |
|---|
| 1087 | 1383 | break; |
|---|
| 1088 | | - /* j <exit> */ |
|---|
| 1089 | | - EMIT4_PCREL(0xa7f40000, jit->exit_ip - jit->prg); |
|---|
| 1384 | + if (!is_first_pass(jit) && can_use_rel(jit, jit->exit_ip)) |
|---|
| 1385 | + /* brc 0xf, <exit> */ |
|---|
| 1386 | + EMIT4_PCREL_RIC(0xa7040000, 0xf, jit->exit_ip); |
|---|
| 1387 | + else |
|---|
| 1388 | + /* brcl 0xf, <exit> */ |
|---|
| 1389 | + EMIT6_PCREL_RILC(0xc0040000, 0xf, jit->exit_ip); |
|---|
| 1090 | 1390 | break; |
|---|
| 1091 | 1391 | /* |
|---|
| 1092 | 1392 | * Branch relative (number of skipped instructions) to offset on |
|---|
| .. | .. |
|---|
| 1112 | 1412 | mask = 0xf000; /* j */ |
|---|
| 1113 | 1413 | goto branch_oc; |
|---|
| 1114 | 1414 | case BPF_JMP | BPF_JSGT | BPF_K: /* ((s64) dst > (s64) imm) */ |
|---|
| 1415 | + case BPF_JMP32 | BPF_JSGT | BPF_K: /* ((s32) dst > (s32) imm) */ |
|---|
| 1115 | 1416 | mask = 0x2000; /* jh */ |
|---|
| 1116 | 1417 | goto branch_ks; |
|---|
| 1117 | 1418 | case BPF_JMP | BPF_JSLT | BPF_K: /* ((s64) dst < (s64) imm) */ |
|---|
| 1419 | + case BPF_JMP32 | BPF_JSLT | BPF_K: /* ((s32) dst < (s32) imm) */ |
|---|
| 1118 | 1420 | mask = 0x4000; /* jl */ |
|---|
| 1119 | 1421 | goto branch_ks; |
|---|
| 1120 | 1422 | case BPF_JMP | BPF_JSGE | BPF_K: /* ((s64) dst >= (s64) imm) */ |
|---|
| 1423 | + case BPF_JMP32 | BPF_JSGE | BPF_K: /* ((s32) dst >= (s32) imm) */ |
|---|
| 1121 | 1424 | mask = 0xa000; /* jhe */ |
|---|
| 1122 | 1425 | goto branch_ks; |
|---|
| 1123 | 1426 | case BPF_JMP | BPF_JSLE | BPF_K: /* ((s64) dst <= (s64) imm) */ |
|---|
| 1427 | + case BPF_JMP32 | BPF_JSLE | BPF_K: /* ((s32) dst <= (s32) imm) */ |
|---|
| 1124 | 1428 | mask = 0xc000; /* jle */ |
|---|
| 1125 | 1429 | goto branch_ks; |
|---|
| 1126 | 1430 | case BPF_JMP | BPF_JGT | BPF_K: /* (dst_reg > imm) */ |
|---|
| 1431 | + case BPF_JMP32 | BPF_JGT | BPF_K: /* ((u32) dst_reg > (u32) imm) */ |
|---|
| 1127 | 1432 | mask = 0x2000; /* jh */ |
|---|
| 1128 | 1433 | goto branch_ku; |
|---|
| 1129 | 1434 | case BPF_JMP | BPF_JLT | BPF_K: /* (dst_reg < imm) */ |
|---|
| 1435 | + case BPF_JMP32 | BPF_JLT | BPF_K: /* ((u32) dst_reg < (u32) imm) */ |
|---|
| 1130 | 1436 | mask = 0x4000; /* jl */ |
|---|
| 1131 | 1437 | goto branch_ku; |
|---|
| 1132 | 1438 | case BPF_JMP | BPF_JGE | BPF_K: /* (dst_reg >= imm) */ |
|---|
| 1439 | + case BPF_JMP32 | BPF_JGE | BPF_K: /* ((u32) dst_reg >= (u32) imm) */ |
|---|
| 1133 | 1440 | mask = 0xa000; /* jhe */ |
|---|
| 1134 | 1441 | goto branch_ku; |
|---|
| 1135 | 1442 | case BPF_JMP | BPF_JLE | BPF_K: /* (dst_reg <= imm) */ |
|---|
| 1443 | + case BPF_JMP32 | BPF_JLE | BPF_K: /* ((u32) dst_reg <= (u32) imm) */ |
|---|
| 1136 | 1444 | mask = 0xc000; /* jle */ |
|---|
| 1137 | 1445 | goto branch_ku; |
|---|
| 1138 | 1446 | case BPF_JMP | BPF_JNE | BPF_K: /* (dst_reg != imm) */ |
|---|
| 1447 | + case BPF_JMP32 | BPF_JNE | BPF_K: /* ((u32) dst_reg != (u32) imm) */ |
|---|
| 1139 | 1448 | mask = 0x7000; /* jne */ |
|---|
| 1140 | 1449 | goto branch_ku; |
|---|
| 1141 | 1450 | case BPF_JMP | BPF_JEQ | BPF_K: /* (dst_reg == imm) */ |
|---|
| 1451 | + case BPF_JMP32 | BPF_JEQ | BPF_K: /* ((u32) dst_reg == (u32) imm) */ |
|---|
| 1142 | 1452 | mask = 0x8000; /* je */ |
|---|
| 1143 | 1453 | goto branch_ku; |
|---|
| 1144 | 1454 | case BPF_JMP | BPF_JSET | BPF_K: /* (dst_reg & imm) */ |
|---|
| 1455 | + case BPF_JMP32 | BPF_JSET | BPF_K: /* ((u32) dst_reg & (u32) imm) */ |
|---|
| 1145 | 1456 | mask = 0x7000; /* jnz */ |
|---|
| 1146 | | - /* lgfi %w1,imm (load sign extend imm) */ |
|---|
| 1147 | | - EMIT6_IMM(0xc0010000, REG_W1, imm); |
|---|
| 1148 | | - /* ngr %w1,%dst */ |
|---|
| 1149 | | - EMIT4(0xb9800000, REG_W1, dst_reg); |
|---|
| 1457 | + if (BPF_CLASS(insn->code) == BPF_JMP32) { |
|---|
| 1458 | + /* llilf %w1,imm (load zero extend imm) */ |
|---|
| 1459 | + EMIT6_IMM(0xc00f0000, REG_W1, imm); |
|---|
| 1460 | + /* nr %w1,%dst */ |
|---|
| 1461 | + EMIT2(0x1400, REG_W1, dst_reg); |
|---|
| 1462 | + } else { |
|---|
| 1463 | + /* lgfi %w1,imm (load sign extend imm) */ |
|---|
| 1464 | + EMIT6_IMM(0xc0010000, REG_W1, imm); |
|---|
| 1465 | + /* ngr %w1,%dst */ |
|---|
| 1466 | + EMIT4(0xb9800000, REG_W1, dst_reg); |
|---|
| 1467 | + } |
|---|
| 1150 | 1468 | goto branch_oc; |
|---|
| 1151 | 1469 | |
|---|
| 1152 | 1470 | case BPF_JMP | BPF_JSGT | BPF_X: /* ((s64) dst > (s64) src) */ |
|---|
| 1471 | + case BPF_JMP32 | BPF_JSGT | BPF_X: /* ((s32) dst > (s32) src) */ |
|---|
| 1153 | 1472 | mask = 0x2000; /* jh */ |
|---|
| 1154 | 1473 | goto branch_xs; |
|---|
| 1155 | 1474 | case BPF_JMP | BPF_JSLT | BPF_X: /* ((s64) dst < (s64) src) */ |
|---|
| 1475 | + case BPF_JMP32 | BPF_JSLT | BPF_X: /* ((s32) dst < (s32) src) */ |
|---|
| 1156 | 1476 | mask = 0x4000; /* jl */ |
|---|
| 1157 | 1477 | goto branch_xs; |
|---|
| 1158 | 1478 | case BPF_JMP | BPF_JSGE | BPF_X: /* ((s64) dst >= (s64) src) */ |
|---|
| 1479 | + case BPF_JMP32 | BPF_JSGE | BPF_X: /* ((s32) dst >= (s32) src) */ |
|---|
| 1159 | 1480 | mask = 0xa000; /* jhe */ |
|---|
| 1160 | 1481 | goto branch_xs; |
|---|
| 1161 | 1482 | case BPF_JMP | BPF_JSLE | BPF_X: /* ((s64) dst <= (s64) src) */ |
|---|
| 1483 | + case BPF_JMP32 | BPF_JSLE | BPF_X: /* ((s32) dst <= (s32) src) */ |
|---|
| 1162 | 1484 | mask = 0xc000; /* jle */ |
|---|
| 1163 | 1485 | goto branch_xs; |
|---|
| 1164 | 1486 | case BPF_JMP | BPF_JGT | BPF_X: /* (dst > src) */ |
|---|
| 1487 | + case BPF_JMP32 | BPF_JGT | BPF_X: /* ((u32) dst > (u32) src) */ |
|---|
| 1165 | 1488 | mask = 0x2000; /* jh */ |
|---|
| 1166 | 1489 | goto branch_xu; |
|---|
| 1167 | 1490 | case BPF_JMP | BPF_JLT | BPF_X: /* (dst < src) */ |
|---|
| 1491 | + case BPF_JMP32 | BPF_JLT | BPF_X: /* ((u32) dst < (u32) src) */ |
|---|
| 1168 | 1492 | mask = 0x4000; /* jl */ |
|---|
| 1169 | 1493 | goto branch_xu; |
|---|
| 1170 | 1494 | case BPF_JMP | BPF_JGE | BPF_X: /* (dst >= src) */ |
|---|
| 1495 | + case BPF_JMP32 | BPF_JGE | BPF_X: /* ((u32) dst >= (u32) src) */ |
|---|
| 1171 | 1496 | mask = 0xa000; /* jhe */ |
|---|
| 1172 | 1497 | goto branch_xu; |
|---|
| 1173 | 1498 | case BPF_JMP | BPF_JLE | BPF_X: /* (dst <= src) */ |
|---|
| 1499 | + case BPF_JMP32 | BPF_JLE | BPF_X: /* ((u32) dst <= (u32) src) */ |
|---|
| 1174 | 1500 | mask = 0xc000; /* jle */ |
|---|
| 1175 | 1501 | goto branch_xu; |
|---|
| 1176 | 1502 | case BPF_JMP | BPF_JNE | BPF_X: /* (dst != src) */ |
|---|
| 1503 | + case BPF_JMP32 | BPF_JNE | BPF_X: /* ((u32) dst != (u32) src) */ |
|---|
| 1177 | 1504 | mask = 0x7000; /* jne */ |
|---|
| 1178 | 1505 | goto branch_xu; |
|---|
| 1179 | 1506 | case BPF_JMP | BPF_JEQ | BPF_X: /* (dst == src) */ |
|---|
| 1507 | + case BPF_JMP32 | BPF_JEQ | BPF_X: /* ((u32) dst == (u32) src) */ |
|---|
| 1180 | 1508 | mask = 0x8000; /* je */ |
|---|
| 1181 | 1509 | goto branch_xu; |
|---|
| 1182 | 1510 | case BPF_JMP | BPF_JSET | BPF_X: /* (dst & src) */ |
|---|
| 1511 | + case BPF_JMP32 | BPF_JSET | BPF_X: /* ((u32) dst & (u32) src) */ |
|---|
| 1512 | + { |
|---|
| 1513 | + bool is_jmp32 = BPF_CLASS(insn->code) == BPF_JMP32; |
|---|
| 1514 | + |
|---|
| 1183 | 1515 | mask = 0x7000; /* jnz */ |
|---|
| 1184 | | - /* ngrk %w1,%dst,%src */ |
|---|
| 1185 | | - EMIT4_RRF(0xb9e40000, REG_W1, dst_reg, src_reg); |
|---|
| 1516 | + /* nrk or ngrk %w1,%dst,%src */ |
|---|
| 1517 | + EMIT4_RRF((is_jmp32 ? 0xb9f40000 : 0xb9e40000), |
|---|
| 1518 | + REG_W1, dst_reg, src_reg); |
|---|
| 1186 | 1519 | goto branch_oc; |
|---|
| 1187 | 1520 | branch_ks: |
|---|
| 1188 | | - /* lgfi %w1,imm (load sign extend imm) */ |
|---|
| 1189 | | - EMIT6_IMM(0xc0010000, REG_W1, imm); |
|---|
| 1190 | | - /* cgrj %dst,%w1,mask,off */ |
|---|
| 1191 | | - EMIT6_PCREL(0xec000000, 0x0064, dst_reg, REG_W1, i, off, mask); |
|---|
| 1521 | + is_jmp32 = BPF_CLASS(insn->code) == BPF_JMP32; |
|---|
| 1522 | + /* cfi or cgfi %dst,imm */ |
|---|
| 1523 | + EMIT6_IMM(is_jmp32 ? 0xc20d0000 : 0xc20c0000, |
|---|
| 1524 | + dst_reg, imm); |
|---|
| 1525 | + if (!is_first_pass(jit) && |
|---|
| 1526 | + can_use_rel(jit, addrs[i + off + 1])) { |
|---|
| 1527 | + /* brc mask,off */ |
|---|
| 1528 | + EMIT4_PCREL_RIC(0xa7040000, |
|---|
| 1529 | + mask >> 12, addrs[i + off + 1]); |
|---|
| 1530 | + } else { |
|---|
| 1531 | + /* brcl mask,off */ |
|---|
| 1532 | + EMIT6_PCREL_RILC(0xc0040000, |
|---|
| 1533 | + mask >> 12, addrs[i + off + 1]); |
|---|
| 1534 | + } |
|---|
| 1192 | 1535 | break; |
|---|
| 1193 | 1536 | branch_ku: |
|---|
| 1194 | 1537 | /* lgfi %w1,imm (load sign extend imm) */ |
|---|
| 1195 | | - EMIT6_IMM(0xc0010000, REG_W1, imm); |
|---|
| 1196 | | - /* clgrj %dst,%w1,mask,off */ |
|---|
| 1197 | | - EMIT6_PCREL(0xec000000, 0x0065, dst_reg, REG_W1, i, off, mask); |
|---|
| 1198 | | - break; |
|---|
| 1538 | + src_reg = REG_1; |
|---|
| 1539 | + EMIT6_IMM(0xc0010000, src_reg, imm); |
|---|
| 1540 | + goto branch_xu; |
|---|
| 1199 | 1541 | branch_xs: |
|---|
| 1200 | | - /* cgrj %dst,%src,mask,off */ |
|---|
| 1201 | | - EMIT6_PCREL(0xec000000, 0x0064, dst_reg, src_reg, i, off, mask); |
|---|
| 1542 | + is_jmp32 = BPF_CLASS(insn->code) == BPF_JMP32; |
|---|
| 1543 | + if (!is_first_pass(jit) && |
|---|
| 1544 | + can_use_rel(jit, addrs[i + off + 1])) { |
|---|
| 1545 | + /* crj or cgrj %dst,%src,mask,off */ |
|---|
| 1546 | + EMIT6_PCREL(0xec000000, (is_jmp32 ? 0x0076 : 0x0064), |
|---|
| 1547 | + dst_reg, src_reg, i, off, mask); |
|---|
| 1548 | + } else { |
|---|
| 1549 | + /* cr or cgr %dst,%src */ |
|---|
| 1550 | + if (is_jmp32) |
|---|
| 1551 | + EMIT2(0x1900, dst_reg, src_reg); |
|---|
| 1552 | + else |
|---|
| 1553 | + EMIT4(0xb9200000, dst_reg, src_reg); |
|---|
| 1554 | + /* brcl mask,off */ |
|---|
| 1555 | + EMIT6_PCREL_RILC(0xc0040000, |
|---|
| 1556 | + mask >> 12, addrs[i + off + 1]); |
|---|
| 1557 | + } |
|---|
| 1202 | 1558 | break; |
|---|
| 1203 | 1559 | branch_xu: |
|---|
| 1204 | | - /* clgrj %dst,%src,mask,off */ |
|---|
| 1205 | | - EMIT6_PCREL(0xec000000, 0x0065, dst_reg, src_reg, i, off, mask); |
|---|
| 1560 | + is_jmp32 = BPF_CLASS(insn->code) == BPF_JMP32; |
|---|
| 1561 | + if (!is_first_pass(jit) && |
|---|
| 1562 | + can_use_rel(jit, addrs[i + off + 1])) { |
|---|
| 1563 | + /* clrj or clgrj %dst,%src,mask,off */ |
|---|
| 1564 | + EMIT6_PCREL(0xec000000, (is_jmp32 ? 0x0077 : 0x0065), |
|---|
| 1565 | + dst_reg, src_reg, i, off, mask); |
|---|
| 1566 | + } else { |
|---|
| 1567 | + /* clr or clgr %dst,%src */ |
|---|
| 1568 | + if (is_jmp32) |
|---|
| 1569 | + EMIT2(0x1500, dst_reg, src_reg); |
|---|
| 1570 | + else |
|---|
| 1571 | + EMIT4(0xb9210000, dst_reg, src_reg); |
|---|
| 1572 | + /* brcl mask,off */ |
|---|
| 1573 | + EMIT6_PCREL_RILC(0xc0040000, |
|---|
| 1574 | + mask >> 12, addrs[i + off + 1]); |
|---|
| 1575 | + } |
|---|
| 1206 | 1576 | break; |
|---|
| 1207 | 1577 | branch_oc: |
|---|
| 1208 | | - /* brc mask,jmp_off (branch instruction needs 4 bytes) */ |
|---|
| 1209 | | - jmp_off = addrs[i + off + 1] - (addrs[i + 1] - 4); |
|---|
| 1210 | | - EMIT4_PCREL(0xa7040000 | mask << 8, jmp_off); |
|---|
| 1578 | + if (!is_first_pass(jit) && |
|---|
| 1579 | + can_use_rel(jit, addrs[i + off + 1])) { |
|---|
| 1580 | + /* brc mask,off */ |
|---|
| 1581 | + EMIT4_PCREL_RIC(0xa7040000, |
|---|
| 1582 | + mask >> 12, addrs[i + off + 1]); |
|---|
| 1583 | + } else { |
|---|
| 1584 | + /* brcl mask,off */ |
|---|
| 1585 | + EMIT6_PCREL_RILC(0xc0040000, |
|---|
| 1586 | + mask >> 12, addrs[i + off + 1]); |
|---|
| 1587 | + } |
|---|
| 1211 | 1588 | break; |
|---|
| 1589 | + } |
|---|
| 1212 | 1590 | default: /* too complex, give up */ |
|---|
| 1213 | 1591 | pr_err("Unknown opcode %02x\n", insn->code); |
|---|
| 1214 | 1592 | return -1; |
|---|
| 1215 | 1593 | } |
|---|
| 1594 | + |
|---|
| 1595 | + if (probe_prg != -1) { |
|---|
| 1596 | + /* |
|---|
| 1597 | + * Handlers of certain exceptions leave psw.addr pointing to |
|---|
| 1598 | + * the instruction directly after the failing one. Therefore, |
|---|
| 1599 | + * create two exception table entries and also add a nop in |
|---|
| 1600 | + * case two probing instructions come directly after each |
|---|
| 1601 | + * other. |
|---|
| 1602 | + */ |
|---|
| 1603 | + nop_prg = jit->prg; |
|---|
| 1604 | + /* bcr 0,%0 */ |
|---|
| 1605 | + _EMIT2(0x0700); |
|---|
| 1606 | + err = bpf_jit_probe_mem(jit, fp, probe_prg, nop_prg); |
|---|
| 1607 | + if (err < 0) |
|---|
| 1608 | + return err; |
|---|
| 1609 | + } |
|---|
| 1610 | + |
|---|
| 1216 | 1611 | return insn_count; |
|---|
| 1612 | +} |
|---|
| 1613 | + |
|---|
| 1614 | +/* |
|---|
| 1615 | + * Return whether new i-th instruction address does not violate any invariant |
|---|
| 1616 | + */ |
|---|
| 1617 | +static bool bpf_is_new_addr_sane(struct bpf_jit *jit, int i) |
|---|
| 1618 | +{ |
|---|
| 1619 | + /* On the first pass anything goes */ |
|---|
| 1620 | + if (is_first_pass(jit)) |
|---|
| 1621 | + return true; |
|---|
| 1622 | + |
|---|
| 1623 | + /* The codegen pass must not change anything */ |
|---|
| 1624 | + if (is_codegen_pass(jit)) |
|---|
| 1625 | + return jit->addrs[i] == jit->prg; |
|---|
| 1626 | + |
|---|
| 1627 | + /* Passes in between must not increase code size */ |
|---|
| 1628 | + return jit->addrs[i] >= jit->prg; |
|---|
| 1629 | +} |
|---|
| 1630 | + |
|---|
| 1631 | +/* |
|---|
| 1632 | + * Update the address of i-th instruction |
|---|
| 1633 | + */ |
|---|
| 1634 | +static int bpf_set_addr(struct bpf_jit *jit, int i) |
|---|
| 1635 | +{ |
|---|
| 1636 | + int delta; |
|---|
| 1637 | + |
|---|
| 1638 | + if (is_codegen_pass(jit)) { |
|---|
| 1639 | + delta = jit->prg - jit->addrs[i]; |
|---|
| 1640 | + if (delta < 0) |
|---|
| 1641 | + bpf_skip(jit, -delta); |
|---|
| 1642 | + } |
|---|
| 1643 | + if (WARN_ON_ONCE(!bpf_is_new_addr_sane(jit, i))) |
|---|
| 1644 | + return -1; |
|---|
| 1645 | + jit->addrs[i] = jit->prg; |
|---|
| 1646 | + return 0; |
|---|
| 1217 | 1647 | } |
|---|
| 1218 | 1648 | |
|---|
| 1219 | 1649 | /* |
|---|
| 1220 | 1650 | * Compile eBPF program into s390x code |
|---|
| 1221 | 1651 | */ |
|---|
| 1222 | | -static int bpf_jit_prog(struct bpf_jit *jit, struct bpf_prog *fp) |
|---|
| 1652 | +static int bpf_jit_prog(struct bpf_jit *jit, struct bpf_prog *fp, |
|---|
| 1653 | + bool extra_pass, u32 stack_depth) |
|---|
| 1223 | 1654 | { |
|---|
| 1224 | | - int i, insn_count; |
|---|
| 1655 | + int i, insn_count, lit32_size, lit64_size; |
|---|
| 1225 | 1656 | |
|---|
| 1226 | | - jit->lit = jit->lit_start; |
|---|
| 1657 | + jit->lit32 = jit->lit32_start; |
|---|
| 1658 | + jit->lit64 = jit->lit64_start; |
|---|
| 1227 | 1659 | jit->prg = 0; |
|---|
| 1660 | + jit->excnt = 0; |
|---|
| 1228 | 1661 | |
|---|
| 1229 | | - bpf_jit_prologue(jit, fp->aux->stack_depth); |
|---|
| 1662 | + bpf_jit_prologue(jit, stack_depth); |
|---|
| 1663 | + if (bpf_set_addr(jit, 0) < 0) |
|---|
| 1664 | + return -1; |
|---|
| 1230 | 1665 | for (i = 0; i < fp->len; i += insn_count) { |
|---|
| 1231 | | - insn_count = bpf_jit_insn(jit, fp, i); |
|---|
| 1666 | + insn_count = bpf_jit_insn(jit, fp, i, extra_pass, stack_depth); |
|---|
| 1232 | 1667 | if (insn_count < 0) |
|---|
| 1233 | 1668 | return -1; |
|---|
| 1234 | 1669 | /* Next instruction address */ |
|---|
| 1235 | | - jit->addrs[i + insn_count] = jit->prg; |
|---|
| 1670 | + if (bpf_set_addr(jit, i + insn_count) < 0) |
|---|
| 1671 | + return -1; |
|---|
| 1236 | 1672 | } |
|---|
| 1237 | | - bpf_jit_epilogue(jit, fp->aux->stack_depth); |
|---|
| 1673 | + bpf_jit_epilogue(jit, stack_depth); |
|---|
| 1238 | 1674 | |
|---|
| 1239 | | - jit->lit_start = jit->prg; |
|---|
| 1240 | | - jit->size = jit->lit; |
|---|
| 1675 | + lit32_size = jit->lit32 - jit->lit32_start; |
|---|
| 1676 | + lit64_size = jit->lit64 - jit->lit64_start; |
|---|
| 1677 | + jit->lit32_start = jit->prg; |
|---|
| 1678 | + if (lit32_size) |
|---|
| 1679 | + jit->lit32_start = ALIGN(jit->lit32_start, 4); |
|---|
| 1680 | + jit->lit64_start = jit->lit32_start + lit32_size; |
|---|
| 1681 | + if (lit64_size) |
|---|
| 1682 | + jit->lit64_start = ALIGN(jit->lit64_start, 8); |
|---|
| 1683 | + jit->size = jit->lit64_start + lit64_size; |
|---|
| 1241 | 1684 | jit->size_prg = jit->prg; |
|---|
| 1685 | + |
|---|
| 1686 | + if (WARN_ON_ONCE(fp->aux->extable && |
|---|
| 1687 | + jit->excnt != fp->aux->num_exentries)) |
|---|
| 1688 | + /* Verifier bug - too many entries. */ |
|---|
| 1689 | + return -1; |
|---|
| 1690 | + |
|---|
| 1242 | 1691 | return 0; |
|---|
| 1692 | +} |
|---|
| 1693 | + |
|---|
| 1694 | +bool bpf_jit_needs_zext(void) |
|---|
| 1695 | +{ |
|---|
| 1696 | + return true; |
|---|
| 1697 | +} |
|---|
| 1698 | + |
|---|
| 1699 | +struct s390_jit_data { |
|---|
| 1700 | + struct bpf_binary_header *header; |
|---|
| 1701 | + struct bpf_jit ctx; |
|---|
| 1702 | + int pass; |
|---|
| 1703 | +}; |
|---|
| 1704 | + |
|---|
| 1705 | +static struct bpf_binary_header *bpf_jit_alloc(struct bpf_jit *jit, |
|---|
| 1706 | + struct bpf_prog *fp) |
|---|
| 1707 | +{ |
|---|
| 1708 | + struct bpf_binary_header *header; |
|---|
| 1709 | + u32 extable_size; |
|---|
| 1710 | + u32 code_size; |
|---|
| 1711 | + |
|---|
| 1712 | + /* We need two entries per insn. */ |
|---|
| 1713 | + fp->aux->num_exentries *= 2; |
|---|
| 1714 | + |
|---|
| 1715 | + code_size = roundup(jit->size, |
|---|
| 1716 | + __alignof__(struct exception_table_entry)); |
|---|
| 1717 | + extable_size = fp->aux->num_exentries * |
|---|
| 1718 | + sizeof(struct exception_table_entry); |
|---|
| 1719 | + header = bpf_jit_binary_alloc(code_size + extable_size, &jit->prg_buf, |
|---|
| 1720 | + 8, jit_fill_hole); |
|---|
| 1721 | + if (!header) |
|---|
| 1722 | + return NULL; |
|---|
| 1723 | + fp->aux->extable = (struct exception_table_entry *) |
|---|
| 1724 | + (jit->prg_buf + code_size); |
|---|
| 1725 | + return header; |
|---|
| 1243 | 1726 | } |
|---|
| 1244 | 1727 | |
|---|
| 1245 | 1728 | /* |
|---|
| .. | .. |
|---|
| 1247 | 1730 | */ |
|---|
| 1248 | 1731 | struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp) |
|---|
| 1249 | 1732 | { |
|---|
| 1733 | + u32 stack_depth = round_up(fp->aux->stack_depth, 8); |
|---|
| 1250 | 1734 | struct bpf_prog *tmp, *orig_fp = fp; |
|---|
| 1251 | 1735 | struct bpf_binary_header *header; |
|---|
| 1736 | + struct s390_jit_data *jit_data; |
|---|
| 1252 | 1737 | bool tmp_blinded = false; |
|---|
| 1738 | + bool extra_pass = false; |
|---|
| 1253 | 1739 | struct bpf_jit jit; |
|---|
| 1254 | 1740 | int pass; |
|---|
| 1255 | 1741 | |
|---|
| .. | .. |
|---|
| 1268 | 1754 | fp = tmp; |
|---|
| 1269 | 1755 | } |
|---|
| 1270 | 1756 | |
|---|
| 1757 | + jit_data = fp->aux->jit_data; |
|---|
| 1758 | + if (!jit_data) { |
|---|
| 1759 | + jit_data = kzalloc(sizeof(*jit_data), GFP_KERNEL); |
|---|
| 1760 | + if (!jit_data) { |
|---|
| 1761 | + fp = orig_fp; |
|---|
| 1762 | + goto out; |
|---|
| 1763 | + } |
|---|
| 1764 | + fp->aux->jit_data = jit_data; |
|---|
| 1765 | + } |
|---|
| 1766 | + if (jit_data->ctx.addrs) { |
|---|
| 1767 | + jit = jit_data->ctx; |
|---|
| 1768 | + header = jit_data->header; |
|---|
| 1769 | + extra_pass = true; |
|---|
| 1770 | + pass = jit_data->pass + 1; |
|---|
| 1771 | + goto skip_init_ctx; |
|---|
| 1772 | + } |
|---|
| 1773 | + |
|---|
| 1271 | 1774 | memset(&jit, 0, sizeof(jit)); |
|---|
| 1272 | | - jit.addrs = kcalloc(fp->len + 1, sizeof(*jit.addrs), GFP_KERNEL); |
|---|
| 1775 | + jit.addrs = kvcalloc(fp->len + 1, sizeof(*jit.addrs), GFP_KERNEL); |
|---|
| 1273 | 1776 | if (jit.addrs == NULL) { |
|---|
| 1274 | 1777 | fp = orig_fp; |
|---|
| 1275 | | - goto out; |
|---|
| 1778 | + goto free_addrs; |
|---|
| 1276 | 1779 | } |
|---|
| 1277 | 1780 | /* |
|---|
| 1278 | 1781 | * Three initial passes: |
|---|
| .. | .. |
|---|
| 1280 | 1783 | * - 3: Calculate program size and addrs arrray |
|---|
| 1281 | 1784 | */ |
|---|
| 1282 | 1785 | for (pass = 1; pass <= 3; pass++) { |
|---|
| 1283 | | - if (bpf_jit_prog(&jit, fp)) { |
|---|
| 1786 | + if (bpf_jit_prog(&jit, fp, extra_pass, stack_depth)) { |
|---|
| 1284 | 1787 | fp = orig_fp; |
|---|
| 1285 | 1788 | goto free_addrs; |
|---|
| 1286 | 1789 | } |
|---|
| .. | .. |
|---|
| 1288 | 1791 | /* |
|---|
| 1289 | 1792 | * Final pass: Allocate and generate program |
|---|
| 1290 | 1793 | */ |
|---|
| 1291 | | - if (jit.size >= BPF_SIZE_MAX) { |
|---|
| 1292 | | - fp = orig_fp; |
|---|
| 1293 | | - goto free_addrs; |
|---|
| 1294 | | - } |
|---|
| 1295 | | - header = bpf_jit_binary_alloc(jit.size, &jit.prg_buf, 2, jit_fill_hole); |
|---|
| 1794 | + header = bpf_jit_alloc(&jit, fp); |
|---|
| 1296 | 1795 | if (!header) { |
|---|
| 1297 | 1796 | fp = orig_fp; |
|---|
| 1298 | 1797 | goto free_addrs; |
|---|
| 1299 | 1798 | } |
|---|
| 1300 | | - if (bpf_jit_prog(&jit, fp)) { |
|---|
| 1799 | +skip_init_ctx: |
|---|
| 1800 | + if (bpf_jit_prog(&jit, fp, extra_pass, stack_depth)) { |
|---|
| 1301 | 1801 | bpf_jit_binary_free(header); |
|---|
| 1302 | 1802 | fp = orig_fp; |
|---|
| 1303 | 1803 | goto free_addrs; |
|---|
| .. | .. |
|---|
| 1306 | 1806 | bpf_jit_dump(fp->len, jit.size, pass, jit.prg_buf); |
|---|
| 1307 | 1807 | print_fn_code(jit.prg_buf, jit.size_prg); |
|---|
| 1308 | 1808 | } |
|---|
| 1309 | | - bpf_jit_binary_lock_ro(header); |
|---|
| 1809 | + if (!fp->is_func || extra_pass) { |
|---|
| 1810 | + bpf_jit_binary_lock_ro(header); |
|---|
| 1811 | + } else { |
|---|
| 1812 | + jit_data->header = header; |
|---|
| 1813 | + jit_data->ctx = jit; |
|---|
| 1814 | + jit_data->pass = pass; |
|---|
| 1815 | + } |
|---|
| 1310 | 1816 | fp->bpf_func = (void *) jit.prg_buf; |
|---|
| 1311 | 1817 | fp->jited = 1; |
|---|
| 1312 | 1818 | fp->jited_len = jit.size; |
|---|
| 1819 | + |
|---|
| 1820 | + if (!fp->is_func || extra_pass) { |
|---|
| 1821 | + bpf_prog_fill_jited_linfo(fp, jit.addrs + 1); |
|---|
| 1313 | 1822 | free_addrs: |
|---|
| 1314 | | - kfree(jit.addrs); |
|---|
| 1823 | + kvfree(jit.addrs); |
|---|
| 1824 | + kfree(jit_data); |
|---|
| 1825 | + fp->aux->jit_data = NULL; |
|---|
| 1826 | + } |
|---|
| 1315 | 1827 | out: |
|---|
| 1316 | 1828 | if (tmp_blinded) |
|---|
| 1317 | 1829 | bpf_jit_prog_release_other(fp, fp == orig_fp ? |
|---|