From ea115f501b42415063c4747e3b5bdc95e669fe1c Mon Sep 17 00:00:00 2001 From: Bernie Innocenti Date: Mon, 19 Mar 2018 17:58:35 +0900 Subject: Add APF opcodes to read/write data memory (take 2) The new opcodes are LDDW (LoaD Data Word) and STDW (STore Data Word) The only supported addressing mode is register-indirect with immediate offset (register value + immediate value). Since there's a single register bit encoded in the opcode, the other register is implicitly used for the address operand. Hence, the following variations are possible: lddw R0, [1234]R1 ; R0 = *(R1 + 1234) lddw R1, [1234]R0 ; R1 = *(R0 + 1234) stdw R0, [1234]R1 ; *(R1 + 1234) = R0 stdw R1, [1234]R0 ; *(R0 + 1234) = R1 The immediate can also be specified to be length 0, making the memory access equivalent to a plain register-indirect with no offset. lddw R0, R1 ; R0 = *R1 lddw R1, R0 ; R1 = *R0 stdw R0, R1 ; *R1 = R0 stdw R1, R0 ; *R0 = R1 The encoding of the above instructions is a single byte, making a typical counter increment more efficient, especially when the address requires a multi-byte immediate: ldh R1, 1234 ; address of our packet counter (3 bytes) lddw R0, R1 ; load the counter from address 1234 (1 byte) add R0, 1 ; increment the counter (2 bytes) stdw R0, R1 ; write-back to data ram (1 byte) Total: 7 bytes. Defining a separate INCW instruction would reduce the above sequence down to 3 bytes (or 4 bytes if using an EXT opcode to avoid wasting opcodes). This optimization can be added at a later point if the data access patterns of production APF code justify it. Bug: 73804303 Test: runtest -x tests/net/java/android/net/apf/ApfTest.java Merged-In: I4bea29ea701cc11dc61cdcf60cc824bbe14b24f6 Merged-In: Ibbd427e12987a1eef63b41d816af05a1bd9f9170 Change-Id: Ibbd427e12987a1eef63b41d816af05a1bd9f9170 (cherry picked from commit 75410970184bf98626342588ba2eabf79cda6d38) --- apf_run.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) (limited to 'apf_run.c') diff --git a/apf_run.c b/apf_run.c index 32b4506..dab7f5e 100644 --- a/apf_run.c +++ b/apf_run.c @@ -50,13 +50,20 @@ int parse_hex(char* input, uint8_t** output) { return length; } +void print_hex(uint8_t* input, int len) { + for (int i = 0; i < len; ++i) { + printf("%02x", input[i]); + } +} + int main(int argc, char* argv[]) { - if (argc != 4) { + if (argc < 3 || argc > 5) { fprintf(stderr, - "Usage: %s \n" + "Usage: %s [] []\n" " program: APF program, in hex\n" " packet: Packet to run through program, in hex\n" - " program age: Age of program in seconds.\n", + " data: Data memory contents, in hex\n", + " age: Age of program in seconds (default: 0)\n", basename(argv[0])); exit(1); } @@ -64,11 +71,19 @@ int main(int argc, char* argv[]) { uint32_t program_len = parse_hex(argv[1], &program); uint8_t* packet; uint32_t packet_len = parse_hex(argv[2], &packet); - uint32_t filter_age = atoi(argv[3]); + uint8_t* data = NULL; + uint32_t data_len = argc > 3 ? parse_hex(argv[3], &data) : 0; + uint32_t filter_age = argc > 4 ? atoi(argv[4]) : 0; int ret = accept_packet(program, program_len, packet, packet_len, - filter_age); + data, data_len, filter_age); printf("Packet %sed\n", ret ? "pass" : "dropp"); + if (data) { + printf("Data: "); + print_hex(data, data_len); + printf("\n"); + free(data); + } free(program); free(packet); return ret; -} \ No newline at end of file +} -- cgit v1.2.3