blob: 4722888234a587b603f444f3ee2a5f8c6dd72e92 [file] [log] [blame]
Paul Jensen497d4ee2016-05-09 10:47:56 -04001/*
Bernie Innocentid2cc2b72018-04-10 22:52:30 +09002 * Copyright 2018, The Android Open Source Project
Paul Jensen497d4ee2016-05-09 10:47:56 -04003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Bernie Innocentid2cc2b72018-04-10 22:52:30 +090017#ifndef ANDROID_APF_APF_H
18#define ANDROID_APF_APF_H
19
Paul Jensen497d4ee2016-05-09 10:47:56 -040020// A brief overview of APF:
21//
22// APF machine is composed of:
23// 1. A read-only program consisting of bytecodes as described below.
24// 2. Two 32-bit registers, called R0 and R1.
Bernie Innocentiea115f52018-03-19 17:58:35 +090025// 3. Sixteen 32-bit temporary memory slots (cleared between packets).
Paul Jensen497d4ee2016-05-09 10:47:56 -040026// 4. A read-only packet.
27// The program is executed by the interpreter below and parses the packet
28// to determine if the application processor (AP) should be woken up to
29// handle the packet or if can be dropped.
30//
31// APF bytecode description:
32//
33// The APF interpreter uses big-endian byte order for loads from the packet
34// and for storing immediates in instructions.
35//
36// Each instruction starts with a byte composed of:
37// Top 5 bits form "opcode" field, see *_OPCODE defines below.
38// Next 2 bits form "size field", which indicate the length of an immediate
39// value which follows the first byte. Values in this field:
40// 0 => immediate value is 0 and no bytes follow.
41// 1 => immediate value is 1 byte big.
42// 2 => immediate value is 2 bytes big.
43// 3 => immediate value is 4 bytes big.
44// Bottom bit forms "register" field, which indicates which register this
45// instruction operates on.
46//
47// There are three main categories of instructions:
48// Load instructions
49// These instructions load byte(s) of the packet into a register.
50// They load either 1, 2 or 4 bytes, as determined by the "opcode" field.
51// They load into the register specified by the "register" field.
52// The immediate value that follows the first byte of the instruction is
Bernie Innocentiea115f52018-03-19 17:58:35 +090053// the byte offset from the beginning of the packet to load from.
Paul Jensen497d4ee2016-05-09 10:47:56 -040054// There are "indexing" loads which add the value in R1 to the byte offset
55// to load from. The "opcode" field determines which loads are "indexing".
56// Arithmetic instructions
57// These instructions perform simple operations, like addition, on register
58// values. The result of these instructions is always written into R0. One
59// argument of the arithmetic operation is R0's value. The other argument
60// of the arithmetic operation is determined by the "register" field:
61// If the "register" field is 0 then the immediate value following
62// the first byte of the instruction is used as the other argument
63// to the arithmetic operation.
64// If the "register" field is 1 then R1's value is used as the other
65// argument to the arithmetic operation.
66// Conditional jump instructions
67// These instructions compare register R0's value with another value, and if
68// the comparison succeeds, jump (i.e. adjust the program counter). The
69// immediate value that follows the first byte of the instruction
70// represents the jump target offset, i.e. the value added to the program
71// counter if the comparison succeeds. The other value compared is
72// determined by the "register" field:
73// If the "register" field is 0 then another immediate value
74// follows the jump target offset. This immediate value is of the
75// same size as the jump target offset, and represents the value
76// to compare against.
77// If the "register" field is 1 then register R1's value is
78// compared against.
79// The type of comparison (e.g. equal to, greater than etc) is determined
80// by the "opcode" field. The comparison interprets both values being
81// compared as unsigned values.
82//
83// Miscellaneous details:
84//
Bernie Innocentiea115f52018-03-19 17:58:35 +090085// Pre-filled temporary memory slot values
Paul Jensen497d4ee2016-05-09 10:47:56 -040086// When the APF program begins execution, three of the sixteen memory slots
87// are pre-filled by the interpreter with values that may be useful for
88// programs:
Bernie Innocentid2cc2b72018-04-10 22:52:30 +090089// Slot #11 contains the size (in bytes) of the APF program.
90// Slot #12 contains the total size of the APF buffer (program + data).
Paul Jensen497d4ee2016-05-09 10:47:56 -040091// Slot #13 is filled with the IPv4 header length. This value is calculated
92// by loading the first byte of the IPv4 header and taking the
93// bottom 4 bits and multiplying their value by 4. This value is
94// set to zero if the first 4 bits after the link layer header are
95// not 4, indicating not IPv4.
96// Slot #14 is filled with size of the packet in bytes, including the
97// link-layer header if any.
98// Slot #15 is filled with the filter age in seconds. This is the number of
Bernie Innocentid2cc2b72018-04-10 22:52:30 +090099// seconds since the AP sent the program to the chipset. This may
Paul Jensen497d4ee2016-05-09 10:47:56 -0400100// be used by filters that should have a particular lifetime. For
101// example, it can be used to rate-limit particular packets to one
102// every N seconds.
103// Special jump targets:
104// When an APF program executes a jump to the byte immediately after the last
105// byte of the progam (i.e., one byte past the end of the program), this
106// signals the program has completed and determined the packet should be
107// passed to the AP.
108// When an APF program executes a jump two bytes past the end of the program,
109// this signals the program has completed and determined the packet should
110// be dropped.
111// Jump if byte sequence doesn't match:
112// This is a special instruction to facilitate matching long sequences of
113// bytes in the packet. Initially it is encoded like a conditional jump
114// instruction with two exceptions:
115// The first byte of the instruction is always followed by two immediate
116// fields: The first immediate field is the jump target offset like other
117// conditional jump instructions. The second immediate field specifies the
118// number of bytes to compare.
119// These two immediate fields are followed by a sequence of bytes. These
120// bytes are compared with the bytes in the packet starting from the
121// position specified by the value of the register specified by the
122// "register" field of the instruction.
123
Bernie Innocentiea115f52018-03-19 17:58:35 +0900124// Number of temporary memory slots, see ldm/stm instructions.
Paul Jensen497d4ee2016-05-09 10:47:56 -0400125#define MEMORY_ITEMS 16
Bernie Innocentiea115f52018-03-19 17:58:35 +0900126// Upon program execution, some temporary memory slots are prefilled:
Bernie Innocentid2cc2b72018-04-10 22:52:30 +0900127#define MEMORY_OFFSET_PROGRAM_SIZE 11 // Size of program (in bytes)
128#define MEMORY_OFFSET_DATA_SIZE 12 // Total size of program + data
Paul Jensen497d4ee2016-05-09 10:47:56 -0400129#define MEMORY_OFFSET_IPV4_HEADER_SIZE 13 // 4*([APF_FRAME_HEADER_SIZE]&15)
130#define MEMORY_OFFSET_PACKET_SIZE 14 // Size of packet in bytes.
131#define MEMORY_OFFSET_FILTER_AGE 15 // Age since filter installed in seconds.
132
133// Leave 0 opcode unused as it's a good indicator of accidental incorrect execution (e.g. data).
134#define LDB_OPCODE 1 // Load 1 byte from immediate offset, e.g. "ldb R0, [5]"
135#define LDH_OPCODE 2 // Load 2 bytes from immediate offset, e.g. "ldh R0, [5]"
136#define LDW_OPCODE 3 // Load 4 bytes from immediate offset, e.g. "ldw R0, [5]"
Bernie Innocentiea115f52018-03-19 17:58:35 +0900137#define LDBX_OPCODE 4 // Load 1 byte from immediate offset plus register, e.g. "ldbx R0, [5+R0]"
138#define LDHX_OPCODE 5 // Load 2 byte from immediate offset plus register, e.g. "ldhx R0, [5+R0]"
139#define LDWX_OPCODE 6 // Load 4 byte from immediate offset plus register, e.g. "ldwx R0, [5+R0]"
Paul Jensen497d4ee2016-05-09 10:47:56 -0400140#define ADD_OPCODE 7 // Add, e.g. "add R0,5"
141#define MUL_OPCODE 8 // Multiply, e.g. "mul R0,5"
142#define DIV_OPCODE 9 // Divide, e.g. "div R0,5"
143#define AND_OPCODE 10 // And, e.g. "and R0,5"
144#define OR_OPCODE 11 // Or, e.g. "or R0,5"
145#define SH_OPCODE 12 // Left shift, e.g, "sh R0, 5" or "sh R0, -5" (shifts right)
Bernie Innocentid2cc2b72018-04-10 22:52:30 +0900146#define LI_OPCODE 13 // Load signed immediate, e.g. "li R0,5"
Paul Jensen497d4ee2016-05-09 10:47:56 -0400147#define JMP_OPCODE 14 // Unconditional jump, e.g. "jmp label"
148#define JEQ_OPCODE 15 // Compare equal and branch, e.g. "jeq R0,5,label"
149#define JNE_OPCODE 16 // Compare not equal and branch, e.g. "jne R0,5,label"
150#define JGT_OPCODE 17 // Compare greater than and branch, e.g. "jgt R0,5,label"
151#define JLT_OPCODE 18 // Compare less than and branch, e.g. "jlt R0,5,label"
152#define JSET_OPCODE 19 // Compare any bits set and branch, e.g. "jset R0,5,label"
153#define JNEBS_OPCODE 20 // Compare not equal byte sequence, e.g. "jnebs R0,5,label,0x1122334455"
154#define EXT_OPCODE 21 // Immediate value is one of *_EXT_OPCODE
Bernie Innocentid2cc2b72018-04-10 22:52:30 +0900155#define LDDW_OPCODE 22 // Load 4 bytes from data address (register + simm): "lddw R0, [5+R1]"
156#define STDW_OPCODE 23 // Store 4 bytes to data address (register + simm): "stdw R0, [5+R1]"
Bernie Innocentiea115f52018-03-19 17:58:35 +0900157
Paul Jensen497d4ee2016-05-09 10:47:56 -0400158// Extended opcodes. These all have an opcode of EXT_OPCODE
159// and specify the actual opcode in the immediate field.
Bernie Innocentiea115f52018-03-19 17:58:35 +0900160#define LDM_EXT_OPCODE 0 // Load from temporary memory, e.g. "ldm R0,5"
161 // Values 0-15 represent loading the different temporary memory slots.
162#define STM_EXT_OPCODE 16 // Store to temporary memory, e.g. "stm R0,5"
163 // Values 16-31 represent storing to the different temporary memory slots.
Paul Jensen497d4ee2016-05-09 10:47:56 -0400164#define NOT_EXT_OPCODE 32 // Not, e.g. "not R0"
165#define NEG_EXT_OPCODE 33 // Negate, e.g. "neg R0"
166#define SWAP_EXT_OPCODE 34 // Swap, e.g. "swap R0,R1"
167#define MOV_EXT_OPCODE 35 // Move, e.g. "move R0,R1"
168
169#define EXTRACT_OPCODE(i) (((i) >> 3) & 31)
170#define EXTRACT_REGISTER(i) ((i) & 1)
171#define EXTRACT_IMM_LENGTH(i) (((i) >> 1) & 3)
Bernie Innocentid2cc2b72018-04-10 22:52:30 +0900172
173#endif // ANDROID_APF_APF_H