| # mach: bpf |
| # sim: --skb-data-offset=0x20 |
| # output: pass\nexit 0 (0x0)\n |
| /* ldabs.s |
| Tests for non-generic BPF load instructions in simulator. |
| These instructions (ld{abs,ind}{b,h,w,dw}) are used to access |
| kernel socket data from BPF programs for high performance filters. |
| |
| Register r6 is an implicit input holding a pointer to a struct sk_buff. |
| Register r0 is an implicit output, holding the fetched data. |
| |
| e.g. |
| ldabsw means: |
| r0 = ntohl (*(u32 *) (((struct sk_buff *)r6)->data + imm32)) |
| |
| ldindw means |
| r0 = ntohl (*(u32 *) (((struct sk_buff *)r6)->data + src_reg + imm32)) */ |
| |
| .include "testutils.inc" |
| |
| .text |
| .global main |
| .type main, @function |
| main: |
| /* R6 holds a pointer to a struct sk_buff, which we pretend |
| exists at 0x1000 */ |
| mov %r6, 0x1000 |
| |
| /* We configure skb-data-offset=0x20 |
| This specifies offsetof(struct sk_buff, data), where the field 'data' |
| is a pointer a data buffer, in this case at 0x2000 */ |
| stw [%r6+0x20], 0x2000 |
| |
| /* Write the value 0x7eadbeef into memory at 0x2004 |
| i.e. offset 4 within the data buffer pointed to by |
| ((struct sk_buff *)r6)->data */ |
| stw [%r6+0x1004], 0x0eadbeef |
| |
| /* Now load data[4] into r0 using the ldabsw instruction */ |
| ldabsw 0x4 |
| |
| /* ...and compare to what we expect */ |
| fail_ne32 %r0, 0x0eadbeef |
| |
| /* Repeat for a half-word (2-bytes) */ |
| sth [%r6+0x1008], 0x1234 |
| ldabsh 0x8 |
| fail_ne32 %r0, 0x1234 |
| |
| /* Repeat for a single byte */ |
| stb [%r6+0x1010], 0x5a |
| ldabsb 0x10 |
| fail_ne32 %r0, 0x5a |
| |
| /* Now, we do the same for the indirect loads */ |
| mov %r7, 0x100 |
| stw [%r6+0x1100], 0x0eedbeef |
| |
| ldindw %r7, 0x0 |
| fail_ne32 %r0, 0x0eedbeef |
| |
| /* half-word */ |
| sth [%r6+0x1104], 0x6789 |
| ldindh %r7, 0x4 |
| fail_ne32 %r0, 0x6789 |
| |
| /* byte */ |
| stb [%r6+0x1108], 0x5f |
| ldindb %r7, 0x8 |
| fail_ne32 %r0, 0x5f |
| |
| pass |