Patchwork ppc: bpf_jit: support MOD operation

login
register
mail settings
Submitter Vladimir Murzin
Date Aug. 27, 2013, 10:49 p.m.
Message ID <1377643792-10327-1-git-send-email-murzin.v@gmail.com>
Download mbox | patch
Permalink /patch/270266/
State Superseded
Headers show

Comments

Vladimir Murzin - Aug. 27, 2013, 10:49 p.m.
commit b6069a9570 (filter: add MOD operation) added generic
support for modulus operation in BPF.

This patch brings JIT support for PPC64

Signed-off-by: Vladimir Murzin <murzin.v@gmail.com>
---
 arch/powerpc/net/bpf_jit_comp.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)
Vladimir Murzin - Sept. 2, 2013, 5:48 p.m.
Ping

On Wed, Aug 28, 2013 at 02:49:52AM +0400, Vladimir Murzin wrote:
> commit b6069a9570 (filter: add MOD operation) added generic
> support for modulus operation in BPF.
> 
> This patch brings JIT support for PPC64
> 
> Signed-off-by: Vladimir Murzin <murzin.v@gmail.com>
> ---
>  arch/powerpc/net/bpf_jit_comp.c | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
> 
> diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
> index bf56e33..96f24dc 100644
> --- a/arch/powerpc/net/bpf_jit_comp.c
> +++ b/arch/powerpc/net/bpf_jit_comp.c
> @@ -193,6 +193,28 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
>  				PPC_MUL(r_A, r_A, r_scratch1);
>  			}
>  			break;
> +		case BPF_S_ALU_MOD_X: /* A %= X; */
> +			ctx->seen |= SEEN_XREG;
> +			PPC_CMPWI(r_X, 0);
> +			if (ctx->pc_ret0 != -1) {
> +				PPC_BCC(COND_EQ, addrs[ctx->pc_ret0]);
> +			} else {
> +				PPC_BCC_SHORT(COND_NE, (ctx->idx*4)+12);
> +				PPC_LI(r_ret, 0);
> +				PPC_JMP(exit_addr);
> +			}
> +			PPC_DIVWU(r_scratch1, r_A, r_X);
> +			PPC_MUL(r_scratch1, r_X, r_scratch1);
> +			PPC_SUB(r_A, r_A, r_scratch1);
> +			break;
> +		case BPF_S_ALU_MOD_K: /* A %= K; */
> +#define r_scratch2 (r_scratch1 + 1)
> +			PPC_LI32(r_scratch2, K);
> +			PPC_DIVWU(r_scratch1, r_A, r_scratch2);
> +			PPC_MUL(r_scratch1, r_scratch2, r_scratch1);
> +			PPC_SUB(r_A, r_A, r_scratch1);
> +#undef r_scratch2
> +			break;
>  		case BPF_S_ALU_DIV_X: /* A /= X; */
>  			ctx->seen |= SEEN_XREG;
>  			PPC_CMPWI(r_X, 0);
> -- 
> 1.8.1.5
>
Benjamin Herrenschmidt - Sept. 2, 2013, 8:45 p.m.
On Mon, 2013-09-02 at 19:48 +0200, Vladimir Murzin wrote:
> Ping
> 
> On Wed, Aug 28, 2013 at 02:49:52AM +0400, Vladimir Murzin wrote:
> > commit b6069a9570 (filter: add MOD operation) added generic
> > support for modulus operation in BPF.
> >
Sorry, nobody got a chance to review that yet. Unfortunately Matt
doesn't work for us anymore and none of us has experience with the
BPF code, so somebody (possibly me) will need to spend a bit of time
figuring it out before verifying that is correct.

Do you have a test case/suite by any chance ?

Ben.

> > This patch brings JIT support for PPC64
> > 
> > Signed-off-by: Vladimir Murzin <murzin.v@gmail.com>
> > ---
> >  arch/powerpc/net/bpf_jit_comp.c | 22 ++++++++++++++++++++++
> >  1 file changed, 22 insertions(+)
> > 
> > diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
> > index bf56e33..96f24dc 100644
> > --- a/arch/powerpc/net/bpf_jit_comp.c
> > +++ b/arch/powerpc/net/bpf_jit_comp.c
> > @@ -193,6 +193,28 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
> >  				PPC_MUL(r_A, r_A, r_scratch1);
> >  			}
> >  			break;
> > +		case BPF_S_ALU_MOD_X: /* A %= X; */
> > +			ctx->seen |= SEEN_XREG;
> > +			PPC_CMPWI(r_X, 0);
> > +			if (ctx->pc_ret0 != -1) {
> > +				PPC_BCC(COND_EQ, addrs[ctx->pc_ret0]);
> > +			} else {
> > +				PPC_BCC_SHORT(COND_NE, (ctx->idx*4)+12);
> > +				PPC_LI(r_ret, 0);
> > +				PPC_JMP(exit_addr);
> > +			}
> > +			PPC_DIVWU(r_scratch1, r_A, r_X);
> > +			PPC_MUL(r_scratch1, r_X, r_scratch1);
> > +			PPC_SUB(r_A, r_A, r_scratch1);
> > +			break;
> > +		case BPF_S_ALU_MOD_K: /* A %= K; */
> > +#define r_scratch2 (r_scratch1 + 1)
> > +			PPC_LI32(r_scratch2, K);
> > +			PPC_DIVWU(r_scratch1, r_A, r_scratch2);
> > +			PPC_MUL(r_scratch1, r_scratch2, r_scratch1);
> > +			PPC_SUB(r_A, r_A, r_scratch1);
> > +#undef r_scratch2
> > +			break;
> >  		case BPF_S_ALU_DIV_X: /* A /= X; */
> >  			ctx->seen |= SEEN_XREG;
> >  			PPC_CMPWI(r_X, 0);
> > -- 
> > 1.8.1.5
> >
Vladimir Murzin - Sept. 3, 2013, 7:58 p.m.
On Tue, Sep 03, 2013 at 06:45:50AM +1000, Benjamin Herrenschmidt wrote:
> On Mon, 2013-09-02 at 19:48 +0200, Vladimir Murzin wrote:
> > Ping
> > 
> > On Wed, Aug 28, 2013 at 02:49:52AM +0400, Vladimir Murzin wrote:
> > > commit b6069a9570 (filter: add MOD operation) added generic
> > > support for modulus operation in BPF.
> > >
> Sorry, nobody got a chance to review that yet. Unfortunately Matt
> doesn't work for us anymore and none of us has experience with the
> BPF code, so somebody (possibly me) will need to spend a bit of time
> figuring it out before verifying that is correct.
> 
> Do you have a test case/suite by any chance ?
> 
> Ben.
> 

Hi Ben!

Thanks for your feedback.

This patch is only compile tested. I have no real hardware, but I'll
probably bring up qemu ppc64 till end of the week...
Meanwhile, I've made simple how-to for testing. You can use it if you wish.
It is mainly based on the [1] and rechecked on x86-64.

1. get the tcpdump utility (git clone git://bpf.tcpdump.org/tcpdump)
2. get the libcap library (git clone git://bpf.tcpdump.org/libpcap)
2.1. apply patch for libcap [2] (against libcap-1.3 branch)
2.2. build libcap (./configure && make && ln -s libcap.so.1.3.0 libcap.so)
3. build tcpdump (LDFLAGS="-L/path/to/libcap" ./configure && make)
4. run 

# ./tcpdump -d "(ip[2:2] - 20) % 5 != 0 && ip[6] & 0x20 = 0x20"
(000) ldh [14]
(001) jeq #0x800 jt 2 jf 10
(002) ldh [18]
(003) sub #20
(004) mod #5
(005) jeq #0x0 jt 10 jf 6
(006) ldb [22]
(007) and #0x20
(008) jeq #0x20 jt 9 jf 10
(009) ret #65535
(010) ret #0

to get pseudo code (we are interested the most into line #4)

5. enable bpf jit compiler

# echo 2 > /proc/sys/net/core/bpf_jit_enable 

6. run

./tcpdump -nv "(ip[2:2] - 20) % 5 != 0 && ip[6] & 0x20 = 0x20"

7. check dmesg for lines starting with (output for x86-64 is provided as an example)

[ 3768.329253] flen=11 proglen=99 pass=3 image=ffffffffa003c000
[ 3768.329254] JIT code: ffffffffa003c000: 55 48 89 e5 48 83 ec 60 48 89 5d f8 44 8b 4f 60
[ 3768.329255] JIT code: ffffffffa003c010: 44 2b 4f 64 4c 8b 87 c0 00 00 00 0f b7 47 76 86
[ 3768.329256] JIT code: ffffffffa003c020: c4 3d 00 08 00 00 75 37 be 02 00 00 00 e8 9f 3e
[ 3768.329257] JIT code: ffffffffa003c030: 02 e1 83 e8 14 31 d2 b9 05 00 00 00 f7 f1 89 d0
[ 3768.329258] JIT code: ffffffffa003c040: 85 c0 74 1b be 06 00 00 00 e8 9f 3e 02 e1 25 20
[ 3768.329259] JIT code: ffffffffa003c050: 00 00 00 83 f8 20 75 07 b8 ff ff 00 00 eb 02 31
[ 3768.329259] JIT code: ffffffffa003c060: c0 c9 c3

8. make sure generated opcodes (JIT code) implement pseudo code form step 4.

Reference
[1] http://comments.gmane.org/gmane.linux.network/242456
[2] http://permalink.gmane.org/gmane.network.tcpdump.devel/5973

P.S.
I hope net people will corect me if I'm wrong there

Cheers
Vladimir Murzin

> > > This patch brings JIT support for PPC64
> > > 
> > > Signed-off-by: Vladimir Murzin <murzin.v@gmail.com>
> > > ---
> > >  arch/powerpc/net/bpf_jit_comp.c | 22 ++++++++++++++++++++++
> > >  1 file changed, 22 insertions(+)
> > > 
> > > diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
> > > index bf56e33..96f24dc 100644
> > > --- a/arch/powerpc/net/bpf_jit_comp.c
> > > +++ b/arch/powerpc/net/bpf_jit_comp.c
> > > @@ -193,6 +193,28 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
> > >  				PPC_MUL(r_A, r_A, r_scratch1);
> > >  			}
> > >  			break;
> > > +		case BPF_S_ALU_MOD_X: /* A %= X; */
> > > +			ctx->seen |= SEEN_XREG;
> > > +			PPC_CMPWI(r_X, 0);
> > > +			if (ctx->pc_ret0 != -1) {
> > > +				PPC_BCC(COND_EQ, addrs[ctx->pc_ret0]);
> > > +			} else {
> > > +				PPC_BCC_SHORT(COND_NE, (ctx->idx*4)+12);
> > > +				PPC_LI(r_ret, 0);
> > > +				PPC_JMP(exit_addr);
> > > +			}
> > > +			PPC_DIVWU(r_scratch1, r_A, r_X);
> > > +			PPC_MUL(r_scratch1, r_X, r_scratch1);
> > > +			PPC_SUB(r_A, r_A, r_scratch1);
> > > +			break;
> > > +		case BPF_S_ALU_MOD_K: /* A %= K; */
> > > +#define r_scratch2 (r_scratch1 + 1)
> > > +			PPC_LI32(r_scratch2, K);
> > > +			PPC_DIVWU(r_scratch1, r_A, r_scratch2);
> > > +			PPC_MUL(r_scratch1, r_scratch2, r_scratch1);
> > > +			PPC_SUB(r_A, r_A, r_scratch1);
> > > +#undef r_scratch2
> > > +			break;
> > >  		case BPF_S_ALU_DIV_X: /* A /= X; */
> > >  			ctx->seen |= SEEN_XREG;
> > >  			PPC_CMPWI(r_X, 0);
> > > -- 
> > > 1.8.1.5
> > > 
> 
>
Daniel Borkmann - Sept. 3, 2013, 8:52 p.m.
On 09/03/2013 09:58 PM, Vladimir Murzin wrote:
> On Tue, Sep 03, 2013 at 06:45:50AM +1000, Benjamin Herrenschmidt wrote:
>> On Mon, 2013-09-02 at 19:48 +0200, Vladimir Murzin wrote:
>>> Ping
>>>
>>> On Wed, Aug 28, 2013 at 02:49:52AM +0400, Vladimir Murzin wrote:
>>>> commit b6069a9570 (filter: add MOD operation) added generic
>>>> support for modulus operation in BPF.
>>>>
>> Sorry, nobody got a chance to review that yet. Unfortunately Matt
>> doesn't work for us anymore and none of us has experience with the
>> BPF code, so somebody (possibly me) will need to spend a bit of time
>> figuring it out before verifying that is correct.
>>
>> Do you have a test case/suite by any chance ?
>>
>> Ben.
>>
>
> Hi Ben!
>
> Thanks for your feedback.
>
> This patch is only compile tested. I have no real hardware, but I'll
> probably bring up qemu ppc64 till end of the week...
> Meanwhile, I've made simple how-to for testing. You can use it if you wish.
> It is mainly based on the [1] and rechecked on x86-64.

Please also cc netdev on BPF related changes.

Actually, your test plan can be further simplified ...

For retrieving and disassembling the JIT image, we have bpf_jit_disasm [1].

  1) echo 2 > /proc/sys/net/core/bpf_jit_enable
  2) ... attach filter ...
  3) bpf_jit_disasm -o

For generating a simple stupid test filter, you can use bpfc [2] (also
see its man page). E.g. ...

   # cat blub
   ldi #10
   mod #8
   ret a
   # bpfc blub
   { 0x0, 0, 0, 0x0000000a },
   { 0x94, 0, 0, 0x00000008 },
   { 0x16, 0, 0, 0x00000000 },

And load this array e.g. either into a small C program that attaches this
as BPF filter, or simply do bpfc blub > blub2 and run netsniff-ng -f blub2\
-s -i eth0, that should also do it.

Then, when attached, the kernel should truncate incoming frames for pf_packet
into max length of 2, just as an example.

   [1] kernel tree, tools/net/bpf_jit_disasm.c
   [2] git clone git://github.com/borkmann/netsniff-ng.git

> 1. get the tcpdump utility (git clone git://bpf.tcpdump.org/tcpdump)
> 2. get the libcap library (git clone git://bpf.tcpdump.org/libpcap)
> 2.1. apply patch for libcap [2] (against libcap-1.3 branch)
> 2.2. build libcap (./configure && make && ln -s libcap.so.1.3.0 libcap.so)
> 3. build tcpdump (LDFLAGS="-L/path/to/libcap" ./configure && make)
> 4. run
>
> # ./tcpdump -d "(ip[2:2] - 20) % 5 != 0 && ip[6] & 0x20 = 0x20"
> (000) ldh [14]
> (001) jeq #0x800 jt 2 jf 10
> (002) ldh [18]
> (003) sub #20
> (004) mod #5
> (005) jeq #0x0 jt 10 jf 6
> (006) ldb [22]
> (007) and #0x20
> (008) jeq #0x20 jt 9 jf 10
> (009) ret #65535
> (010) ret #0
>
> to get pseudo code (we are interested the most into line #4)
>
> 5. enable bpf jit compiler
>
> # echo 2 > /proc/sys/net/core/bpf_jit_enable
>
> 6. run
>
> ./tcpdump -nv "(ip[2:2] - 20) % 5 != 0 && ip[6] & 0x20 = 0x20"
>
> 7. check dmesg for lines starting with (output for x86-64 is provided as an example)
>
> [ 3768.329253] flen=11 proglen=99 pass=3 image=ffffffffa003c000
> [ 3768.329254] JIT code: ffffffffa003c000: 55 48 89 e5 48 83 ec 60 48 89 5d f8 44 8b 4f 60
> [ 3768.329255] JIT code: ffffffffa003c010: 44 2b 4f 64 4c 8b 87 c0 00 00 00 0f b7 47 76 86
> [ 3768.329256] JIT code: ffffffffa003c020: c4 3d 00 08 00 00 75 37 be 02 00 00 00 e8 9f 3e
> [ 3768.329257] JIT code: ffffffffa003c030: 02 e1 83 e8 14 31 d2 b9 05 00 00 00 f7 f1 89 d0
> [ 3768.329258] JIT code: ffffffffa003c040: 85 c0 74 1b be 06 00 00 00 e8 9f 3e 02 e1 25 20
> [ 3768.329259] JIT code: ffffffffa003c050: 00 00 00 83 f8 20 75 07 b8 ff ff 00 00 eb 02 31
> [ 3768.329259] JIT code: ffffffffa003c060: c0 c9 c3
>
> 8. make sure generated opcodes (JIT code) implement pseudo code form step 4.
>
> Reference
> [1] http://comments.gmane.org/gmane.linux.network/242456
> [2] http://permalink.gmane.org/gmane.network.tcpdump.devel/5973
>
> P.S.
> I hope net people will corect me if I'm wrong there
>
> Cheers
> Vladimir Murzin
>
>>>> This patch brings JIT support for PPC64
>>>>
>>>> Signed-off-by: Vladimir Murzin <murzin.v@gmail.com>
Daniel Borkmann - Sept. 4, 2013, 7:04 a.m.
On 09/03/2013 10:52 PM, Daniel Borkmann wrote:
> On 09/03/2013 09:58 PM, Vladimir Murzin wrote:
[...]
>>> Do you have a test case/suite by any chance ?
>>>
>>> Ben.
>>>
>>
>> Hi Ben!
>>
>> Thanks for your feedback.
>>
>> This patch is only compile tested. I have no real hardware, but I'll
>> probably bring up qemu ppc64 till end of the week...
>> Meanwhile, I've made simple how-to for testing. You can use it if you wish.
>> It is mainly based on the [1] and rechecked on x86-64.
>
> Please also cc netdev on BPF related changes.
>
> Actually, your test plan can be further simplified ...
>
> For retrieving and disassembling the JIT image, we have bpf_jit_disasm [1].
>
>   1) echo 2 > /proc/sys/net/core/bpf_jit_enable
>   2) ... attach filter ...
>   3) bpf_jit_disasm -o
>
> For generating a simple stupid test filter, you can use bpfc [2] (also
> see its man page). E.g. ...
>
>    # cat blub
>    ldi #10
>    mod #8
>    ret a
>    # bpfc blub
>    { 0x0, 0, 0, 0x0000000a },
>    { 0x94, 0, 0, 0x00000008 },
>    { 0x16, 0, 0, 0x00000000 },

Plus something like ...

ldxi #0
mod x
ret a

For longer-term testing, also trinity has BPF support. ;)

> And load this array e.g. either into a small C program that attaches this
> as BPF filter, or simply do bpfc blub > blub2 and run netsniff-ng -f blub2\
> -s -i eth0, that should also do it.
>
> Then, when attached, the kernel should truncate incoming frames for pf_packet
> into max length of 2, just as an example.
>
>    [1] kernel tree, tools/net/bpf_jit_disasm.c
>    [2] git clone git://github.com/borkmann/netsniff-ng.git
Vladimir Murzin - Sept. 11, 2013, 4:15 p.m.
On Wed, Sep 04, 2013 at 09:04:04AM +0200, Daniel Borkmann wrote:
> On 09/03/2013 10:52 PM, Daniel Borkmann wrote:
> > On 09/03/2013 09:58 PM, Vladimir Murzin wrote:
> [...]
> >>> Do you have a test case/suite by any chance ?
> >>>
> >>> Ben.
> >>>
> >>
> >> Hi Ben!
> >>
> >> Thanks for your feedback.
> >>
> >> This patch is only compile tested. I have no real hardware, but I'll
> >> probably bring up qemu ppc64 till end of the week...
> >> Meanwhile, I've made simple how-to for testing. You can use it if you wish.
> >> It is mainly based on the [1] and rechecked on x86-64.

Finally I've managed to bring up qemu ppc64 and done simple testing. As a
result I could see difference in opcodes for divide instruction - I've just
sent the patch for that.

WRT mod instruction result is:

For BPF program

(000) ldh      [12]
(001) jeq      #0x800           jt 2	jf 10
(002) ldh      [16]
(003) sub      #20
(004) mod      #5
(005) jeq      #0x0             jt 10	jf 6
(006) ldb      [20]
(007) and      #0x20
(008) jeq      #0x20            jt 9	jf 10
(009) ret      #65535
(010) ret      #0

The following code is generated (with patch divw to divwu applied)

244 bytes emitted from JIT compiler (pass:3, flen:11)
d0000000015c0018 + <x>:
   0:	mflr    r0
   4:	std     r0,16(r1)
   8:	std     r14,-144(r1)
   c:	std     r15,-136(r1)
  10:	stdu    r1,-288(r1)
  14:	lwz     r7,108(r3)
  18:	lwz     r15,104(r3)
  1c:	subf    r15,r7,r15
  20:	ld      r14,216(r3)
  24:	lis     r7,-16384
  28:	rldicr  r7,r7,32,31
  2c:	oris    r7,r7,9
  30:	ori     r7,r7,43428
  34:	mtlr    r7
  38:	li      r6,12
  3c:	blrl
  40:	blt-    0x00000000000000dc
  44:	nop
  48:	cmplwi  r4,2048
  4c:	bne-    0x00000000000000d8
  50:	nop
  54:	lis     r7,-16384
  58:	rldicr  r7,r7,32,31
  5c:	oris    r7,r7,9
  60:	ori     r7,r7,43428
  64:	mtlr    r7
  68:	li      r6,16
  6c:	blrl
  70:	blt-    0x00000000000000dc
  74:	nop
  78:	addi    r4,r4,-20
  7c:	li      r8,5
  80:	divwu   r7,r4,r8
  84:	mullw   r7,r8,r7
  88:	subf    r4,r7,r4
  8c:	cmplwi  r4,0
  90:	beq-    0x00000000000000d8
  94:	nop
  98:	lis     r7,-16384
  9c:	rldicr  r7,r7,32,31
  a0:	oris    r7,r7,9
  a4:	ori     r7,r7,43456
  a8:	mtlr    r7
  ac:	li      r6,20
  b0:	blrl
  b4:	blt-    0x00000000000000dc
  b8:	nop
  bc:	andi.   r4,r4,32
  c0:	cmplwi  r4,32
  c4:	bne-    0x00000000000000d8
  c8:	nop
  cc:	li      r3,-1
  d0:	addis   r3,r3,1
  d4:	b       0x00000000000000dc
  d8:	li      r3,0
  dc:	addi    r1,r1,288
  e0:	ld      r0,16(r1)
  e4:	mtlr    r0
  e8:	ld      r14,-144(r1)
  ec:	ld      r15,-136(r1)
  f0:	blr

Raw codes are

flen=11 proglen=244 pass=3 image=d0000000015c0018
JIT code: 00000000: 7c 08 02 a6 f8 01 00 10 f9 c1 ff 70 f9 e1 ff 78
JIT code: 00000010: f8 21 fe e1 80 e3 00 6c 81 e3 00 68 7d e7 78 50
JIT code: 00000020: e9 c3 00 d8 3c e0 c0 00 78 e7 07 c6 64 e7 00 09
JIT code: 00000030: 60 e7 a9 a4 7c e8 03 a6 38 c0 00 0c 4e 80 00 21
JIT code: 00000040: 41 80 00 9c 60 00 00 00 28 04 08 00 40 82 00 8c
JIT code: 00000050: 60 00 00 00 3c e0 c0 00 78 e7 07 c6 64 e7 00 09
JIT code: 00000060: 60 e7 a9 a4 7c e8 03 a6 38 c0 00 10 4e 80 00 21
JIT code: 00000070: 41 80 00 6c 60 00 00 00 38 84 ff ec 39 00 00 05
JIT code: 00000080: 7c e4 43 96 7c e8 39 d6 7c 87 20 50 28 04 00 00
JIT code: 00000090: 41 82 00 48 60 00 00 00 3c e0 c0 00 78 e7 07 c6
JIT code: 000000a0: 64 e7 00 09 60 e7 a9 c0 7c e8 03 a6 38 c0 00 14
JIT code: 000000b0: 4e 80 00 21 41 80 00 28 60 00 00 00 70 84 00 20
JIT code: 000000c0: 28 04 00 20 40 82 00 14 60 00 00 00 38 60 ff ff
JIT code: 000000d0: 3c 63 00 01 48 00 00 08 38 60 00 00 38 21 01 20
JIT code: 000000e0: e8 01 00 10 7c 08 03 a6 e9 c1 ff 70 e9 e1 ff 78
JIT code: 000000f0: 4e 80 00 20

Ben,

How do you feel about it?

> >
> > Please also cc netdev on BPF related changes.
> >
> > Actually, your test plan can be further simplified ...
> >
> > For retrieving and disassembling the JIT image, we have bpf_jit_disasm [1].
> >
> >   1) echo 2 > /proc/sys/net/core/bpf_jit_enable
> >   2) ... attach filter ...
> >   3) bpf_jit_disasm -o
> >
> > For generating a simple stupid test filter, you can use bpfc [2] (also
> > see its man page). E.g. ...
> >
> >    # cat blub
> >    ldi #10
> >    mod #8
> >    ret a
> >    # bpfc blub
> >    { 0x0, 0, 0, 0x0000000a },
> >    { 0x94, 0, 0, 0x00000008 },
> >    { 0x16, 0, 0, 0x00000000 },
> 
> Plus something like ...
> 
> ldxi #0
> mod x
> ret a
> 

Thanks Daniel!

Unfortunately, I couldn't trigger JIT compiler with the pair bpfc/netsniff-ng
(even for x86-64). I guess I missed something. I'd be very grateful if you
point at my mistakes.

> For longer-term testing, also trinity has BPF support. ;)
> 

Wow! Could do give some hint how to run this for BPF only?

> > And load this array e.g. either into a small C program that attaches this
> > as BPF filter, or simply do bpfc blub > blub2 and run netsniff-ng -f blub2\
> > -s -i eth0, that should also do it.
> >
> > Then, when attached, the kernel should truncate incoming frames for pf_packet
> > into max length of 2, just as an example.
> >
> >    [1] kernel tree, tools/net/bpf_jit_disasm.c
> >    [2] git clone git://github.com/borkmann/netsniff-ng.git

Thanks
Vladimir
Matt Evans - Sept. 12, 2013, 1:18 a.m.
Hi Ben, Vladimir,


*dusts off very thick PPC cobwebs*  Sorry for the delay as I'm travelling, didn't get to this until now.

On 02/09/2013, at 9:45 PM, Benjamin Herrenschmidt wrote:

> On Mon, 2013-09-02 at 19:48 +0200, Vladimir Murzin wrote:
>> Ping
>> 
>> On Wed, Aug 28, 2013 at 02:49:52AM +0400, Vladimir Murzin wrote:
>>> commit b6069a9570 (filter: add MOD operation) added generic
>>> support for modulus operation in BPF.
>>> 
> Sorry, nobody got a chance to review that yet. Unfortunately Matt
> doesn't work for us anymore and none of us has experience with the
> BPF code, so somebody (possibly me) will need to spend a bit of time
> figuring it out before verifying that is correct.
> 
> Do you have a test case/suite by any chance ?
> 
> Ben.
> 
>>> This patch brings JIT support for PPC64
>>> 
>>> Signed-off-by: Vladimir Murzin <murzin.v@gmail.com>
>>> ---
>>> arch/powerpc/net/bpf_jit_comp.c | 22 ++++++++++++++++++++++
>>> 1 file changed, 22 insertions(+)
>>> 
>>> diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
>>> index bf56e33..96f24dc 100644
>>> --- a/arch/powerpc/net/bpf_jit_comp.c
>>> +++ b/arch/powerpc/net/bpf_jit_comp.c
>>> @@ -193,6 +193,28 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
>>> 				PPC_MUL(r_A, r_A, r_scratch1);
>>> 			}
>>> 			break;
>>> +		case BPF_S_ALU_MOD_X: /* A %= X; */
>>> +			ctx->seen |= SEEN_XREG;
>>> +			PPC_CMPWI(r_X, 0);
>>> +			if (ctx->pc_ret0 != -1) {
>>> +				PPC_BCC(COND_EQ, addrs[ctx->pc_ret0]);
>>> +			} else {
>>> +				PPC_BCC_SHORT(COND_NE, (ctx->idx*4)+12);
>>> +				PPC_LI(r_ret, 0);
>>> +				PPC_JMP(exit_addr);
>>> +			}
>>> +			PPC_DIVWU(r_scratch1, r_A, r_X);
>>> +			PPC_MUL(r_scratch1, r_X, r_scratch1);
>>> +			PPC_SUB(r_A, r_A, r_scratch1);
>>> +			break;

Without having compiled & tested this, it looks fine to me (especially with the corrected DIVWU opcode in the other patch, oops...).

>>> +		case BPF_S_ALU_MOD_K: /* A %= K; */
>>> +#define r_scratch2 (r_scratch1 + 1)
>>> +			PPC_LI32(r_scratch2, K);
>>> +			PPC_DIVWU(r_scratch1, r_A, r_scratch2);
>>> +			PPC_MUL(r_scratch1, r_scratch2, r_scratch1);
>>> +			PPC_SUB(r_A, r_A, r_scratch1);
>>> +#undef r_scratch2
>>> +			break;

If you need another scratch register, it should really be defined in bpf_jit.h instead.

Once you define r_scratch2 in there,

Acked-by: Matt Evans <matt@ozlabs.org>


Thanks!


Matt




>>> 		case BPF_S_ALU_DIV_X: /* A /= X; */
>>> 			ctx->seen |= SEEN_XREG;
>>> 			PPC_CMPWI(r_X, 0);
>>> -- 
>>> 1.8.1.5
>>> 
>
Vladimir Murzin - Sept. 12, 2013, 2:56 a.m.
On Thu, Sep 12, 2013 at 02:18:37AM +0100, Matt Evans wrote:
> Hi Ben, Vladimir,
> 
> 
> *dusts off very thick PPC cobwebs*  Sorry for the delay as I'm travelling, didn't get to this until now.
> 
> On 02/09/2013, at 9:45 PM, Benjamin Herrenschmidt wrote:
> 
> > On Mon, 2013-09-02 at 19:48 +0200, Vladimir Murzin wrote:
> >> Ping
> >> 
> >> On Wed, Aug 28, 2013 at 02:49:52AM +0400, Vladimir Murzin wrote:
> >>> commit b6069a9570 (filter: add MOD operation) added generic
> >>> support for modulus operation in BPF.
> >>> 
> > Sorry, nobody got a chance to review that yet. Unfortunately Matt
> > doesn't work for us anymore and none of us has experience with the
> > BPF code, so somebody (possibly me) will need to spend a bit of time
> > figuring it out before verifying that is correct.
> > 
> > Do you have a test case/suite by any chance ?
> > 
> > Ben.
> > 
> >>> This patch brings JIT support for PPC64
> >>> 
> >>> Signed-off-by: Vladimir Murzin <murzin.v@gmail.com>
> >>> ---
> >>> arch/powerpc/net/bpf_jit_comp.c | 22 ++++++++++++++++++++++
> >>> 1 file changed, 22 insertions(+)
> >>> 
> >>> diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
> >>> index bf56e33..96f24dc 100644
> >>> --- a/arch/powerpc/net/bpf_jit_comp.c
> >>> +++ b/arch/powerpc/net/bpf_jit_comp.c
> >>> @@ -193,6 +193,28 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
> >>> 				PPC_MUL(r_A, r_A, r_scratch1);
> >>> 			}
> >>> 			break;
> >>> +		case BPF_S_ALU_MOD_X: /* A %= X; */
> >>> +			ctx->seen |= SEEN_XREG;
> >>> +			PPC_CMPWI(r_X, 0);
> >>> +			if (ctx->pc_ret0 != -1) {
> >>> +				PPC_BCC(COND_EQ, addrs[ctx->pc_ret0]);
> >>> +			} else {
> >>> +				PPC_BCC_SHORT(COND_NE, (ctx->idx*4)+12);
> >>> +				PPC_LI(r_ret, 0);
> >>> +				PPC_JMP(exit_addr);
> >>> +			}
> >>> +			PPC_DIVWU(r_scratch1, r_A, r_X);
> >>> +			PPC_MUL(r_scratch1, r_X, r_scratch1);
> >>> +			PPC_SUB(r_A, r_A, r_scratch1);
> >>> +			break;
> 
> Without having compiled & tested this, it looks fine to me (especially with the corrected DIVWU opcode in the other patch, oops...).
> 
> >>> +		case BPF_S_ALU_MOD_K: /* A %= K; */
> >>> +#define r_scratch2 (r_scratch1 + 1)
> >>> +			PPC_LI32(r_scratch2, K);
> >>> +			PPC_DIVWU(r_scratch1, r_A, r_scratch2);
> >>> +			PPC_MUL(r_scratch1, r_scratch2, r_scratch1);
> >>> +			PPC_SUB(r_A, r_A, r_scratch1);
> >>> +#undef r_scratch2
> >>> +			break;
> 
> If you need another scratch register, it should really be defined in bpf_jit.h instead.
> 
> Once you define r_scratch2 in there,
> 
> Acked-by: Matt Evans <matt@ozlabs.org>
> 
> 
> Thanks!
> 
> 
> Matt
> 

Thanks!

Vladimir

> 
> 
> 
> >>> 		case BPF_S_ALU_DIV_X: /* A /= X; */
> >>> 			ctx->seen |= SEEN_XREG;
> >>> 			PPC_CMPWI(r_X, 0);
> >>> -- 
> >>> 1.8.1.5
> >>> 
> > 
>

Patch

diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index bf56e33..96f24dc 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -193,6 +193,28 @@  static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
 				PPC_MUL(r_A, r_A, r_scratch1);
 			}
 			break;
+		case BPF_S_ALU_MOD_X: /* A %= X; */
+			ctx->seen |= SEEN_XREG;
+			PPC_CMPWI(r_X, 0);
+			if (ctx->pc_ret0 != -1) {
+				PPC_BCC(COND_EQ, addrs[ctx->pc_ret0]);
+			} else {
+				PPC_BCC_SHORT(COND_NE, (ctx->idx*4)+12);
+				PPC_LI(r_ret, 0);
+				PPC_JMP(exit_addr);
+			}
+			PPC_DIVWU(r_scratch1, r_A, r_X);
+			PPC_MUL(r_scratch1, r_X, r_scratch1);
+			PPC_SUB(r_A, r_A, r_scratch1);
+			break;
+		case BPF_S_ALU_MOD_K: /* A %= K; */
+#define r_scratch2 (r_scratch1 + 1)
+			PPC_LI32(r_scratch2, K);
+			PPC_DIVWU(r_scratch1, r_A, r_scratch2);
+			PPC_MUL(r_scratch1, r_scratch2, r_scratch1);
+			PPC_SUB(r_A, r_A, r_scratch1);
+#undef r_scratch2
+			break;
 		case BPF_S_ALU_DIV_X: /* A /= X; */
 			ctx->seen |= SEEN_XREG;
 			PPC_CMPWI(r_X, 0);