// SPDX-License-Identifier: GPL-2.0
#include <linux/moduleloader.h>
#include <linux/workqueue.h>
#include <linux/netdevice.h>
#include <linux/filter.h>
#include <linux/bpf.h>
#include <linux/cache.h>
#include <linux/if_vlan.h>
#include <asm/cacheflush.h>
#include <asm/ptrace.h>
#include "bpf_jit_64.h"
static inline bool is_simm13(unsigned int value)
{
return value + 0x1000 < 0x2000;
}
static inline bool is_simm10(unsigned int value)
{
return value + 0x200 < 0x400;
}
static inline bool is_simm5(unsigned int value)
{
return value + 0x10 < 0x20;
}
static inline bool is_sethi(unsigned int value)
{
return (value & ~0x3fffff) == 0;
}
static void bpf_flush_icache(void *start_, void *end_)
{
/* Cheetah's I-cache is fully coherent. */
if (tlb_type == spitfire) {
unsigned long start = (unsigned long) start_;
unsigned long end = (unsigned long) end_;
start &= ~7UL;
end = (end + 7UL) & ~7UL;
while (start < end) {
flushi(start);
start += 32;
}
}
}
#define S13(X) ((X) & 0x1fff)
#define S5(X) ((X) & 0x1f)
#define IMMED 0x00002000
#define RD(X) ((X) << 25)
#define RS1(X) ((X) << 14)
#define RS2(X) ((X))
#define OP(X) ((X) << 30)
#define OP2(X) ((X) << 22)
#define OP3(X) ((X) << 19)
#define COND(X) (((X) & 0xf) << 25)
#define CBCOND(X) (((X) & 0x1f) << 25)
#define F1(X) OP(X)
#define F2(X, Y) (OP(X) | OP2(Y))
#define F3(X, Y) (OP(X) | OP3(Y))
#define ASI(X) (((X) & 0xff) << 5)
#define CONDN COND(0x0)
#define CONDE COND(0x1)
#define CONDLE COND(0x2)
#define CONDL COND(0x3)
#define CONDLEU COND(0x4)
#define CONDCS COND(0x5)
#define CONDNEG COND(0x6)
#define CONDVC COND(0x7)
#define CONDA COND(0x8)
#define CONDNE COND(0x9)
#define CONDG COND(0xa)
#define CONDGE COND(0xb)
#define CONDGU COND(0xc)
#define CONDCC COND(0xd)
#define CONDPOS COND(0xe)
#define CONDVS COND(0xf)
#define CONDGEU CONDCC
#define CONDLU CONDCS
#define WDISP22(X) (((X) >> 2) & 0x3fffff)
#define WDISP19(X) (((X) >> 2) & 0x7ffff)
/* The 10-bit branch displacement for CBCOND is split into two fields */
static u32 WDISP10(u32 off)
{
u32 ret = ((off >> 2) & 0xff) << 5;
ret |= ((off >> (2 + 8)) & 0x03) << 19;
return ret;
}
#define CBCONDE CBCOND(0x09)
#define CBCONDLE CBCOND(0x0a)
#define CBCONDL CBCOND(0x0b)
#define CBCONDLEU CBCOND(0x0c)
#define CBCONDCS CBCOND(0x0d)
#define CBCONDN CBCOND(0x0e)
#define CBCONDVS CBCOND(0x0f)
#define CBCONDNE CBCOND(0x19)
#define CBCONDG CBCOND(0x1a)
#define CBCONDGE CBCOND(0x1b)
#define CBCONDGU CBCOND(0x1c)
#define CBCONDCC CBCOND(0x1d)
#define CBCONDPOS CBCOND(0x1e)
#define CBCONDVC CBCOND(0x1f)
#define CBCONDGEU CBCONDCC
#define CBCONDLU CBCONDCS
#define ANNUL (1 << 29)
#define XCC (1 << 21)
#define BRANCH (F2(0, 1) | XCC)
#define CBCOND_OP (F2(0, 3) | XCC)
#define BA (BRANCH | CONDA)
#define BG (BRANCH | CONDG)
#define BL (BRANCH | CONDL)
#define BLE (BRANCH | CONDLE)
#define BGU (BRANCH | CONDGU)
#define BLEU (BRANCH | CONDLEU)
#define BGE (BRANCH | CONDGE)
#define BGEU (BRANCH | CONDGEU)
#define BLU (BRANCH | CONDLU)
#define BE (BRANCH | CONDE)
#define BNE (BRANCH | CONDNE)
#define SETHI(K, REG) \
(F2(0, 0x4) | RD(REG) | (((K) >> 10) & 0x3fffff))
#define OR_LO(K, REG) \
(F3(2, 0x02) | IMMED | RS1(REG) | ((K) & 0x3ff) | RD(REG))
#define ADD F3(2, 0x00)
#define AND F3(2, 0x01)
#define ANDCC F3(2, 0x11)
#define OR F3(2, 0x02)
#define XOR F3(2, 0x03)
#define SUB F3(2, 0x04)
#define SUBCC F3(2, 0x14)
#define MUL F3(2, 0x0a)
#define MULX F3(2, 0x09)
#define UDIVX F3(2, 0x0d)
#define DIV F3(2, 0x0e)
#define SLL F3(2, 0x25)
#define SLLX
|