1 /* 2 * Copyright 2018, The Android Open Source Project 3 * 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 17 #ifndef ANDROID_APF_APF_H 18 #define ANDROID_APF_APF_H 19 20 // 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. 25 // 3. Sixteen 32-bit temporary memory slots (cleared between packets). 26 // 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 53 // the byte offset from the beginning of the packet to load from. 54 // 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 // 85 // Pre-filled temporary memory slot values 86 // 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: 89 // Slot #11 contains the size (in bytes) of the APF program. 90 // Slot #12 contains the total size of the APF buffer (program + data). 91 // 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 99 // seconds since the AP sent the program to the chipset. This may 100 // 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 124 // Number of temporary memory slots, see ldm/stm instructions. 125 #define MEMORY_ITEMS 16 126 // Upon program execution, some temporary memory slots are prefilled: 127 #define MEMORY_OFFSET_PROGRAM_SIZE 11 // Size of program (in bytes) 128 #define MEMORY_OFFSET_DATA_SIZE 12 // Total size of program + data 129 #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]" 137 #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]" 140 #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) 146 #define LI_OPCODE 13 // Load signed immediate, e.g. "li R0,5" 147 #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 155 #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]" 157 158 // Extended opcodes. These all have an opcode of EXT_OPCODE 159 // and specify the actual opcode in the immediate field. 160 #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. 164 #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) 172 173 #endif // ANDROID_APF_APF_H 174