From ec5730a75acb935bd61013f72b80dd82323a6fdb Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Mon, 14 Sep 2020 18:21:27 +1000 Subject: [PATCH] tests: Add tests for lq/stq and lqarx/stqcx. Lq and stq are tested in both BE and LE modes (though only 64-bit mode) by the 'modes' test. Lqarx and stqcx. are tested by the 'reservation' test in LE mode mode (64-bit). Signed-off-by: Paul Mackerras --- tests/modes/head.S | 60 ++++++++++ tests/modes/modes.c | 172 +++++++++++++++++++++++++++++ tests/reservation/head.S | 28 +++++ tests/reservation/reservation.c | 64 ++++++++++- tests/test_modes.bin | Bin 20512 -> 20512 bytes tests/test_modes.console_out | 2 + tests/test_reservation.bin | Bin 10896 -> 11604 bytes tests/test_reservation.console_out | 1 + 8 files changed, 326 insertions(+), 1 deletion(-) diff --git a/tests/modes/head.S b/tests/modes/head.S index d9e69dc..8b00bdd 100644 --- a/tests/modes/head.S +++ b/tests/modes/head.S @@ -230,3 +230,63 @@ restore: ld %r0,16(%r1) mtlr %r0 blr + + .global do_lq +do_lq: + lq %r6,0(%r3) + std %r6,0(%r4) + std %r7,8(%r4) + li %r3,0 + blr + + .global do_lq_np /* "non-preferred" form of lq */ +do_lq_np: + mr %r7,%r3 + lq %r6,0(%r7) + std %r6,0(%r4) + std %r7,8(%r4) + li %r3,0 + blr + + .global do_lq_bad /* illegal form of lq */ +do_lq_bad: + mr %r6,%r3 + .long 0xe0c60000 /* lq %r6,0(%r6) */ + std %r6,0(%r4) + std %r7,8(%r4) + li %r3,0 + blr + + .global do_stq +do_stq: + ld %r8,0(%r4) + ld %r9,8(%r4) + stq %r8,0(%r3) + li %r3,0 + blr + + /* big-endian versions of the above */ + .global do_lq_be +do_lq_be: + .long 0x0000c3e0 + .long 0x0000c4f8 + .long 0x0800e4f8 + .long 0x00006038 + .long 0x2000804e + + .global do_lq_np_be /* "non-preferred" form of lq */ +do_lq_np_be: + .long 0x781b677c + .long 0x0000c7e0 + .long 0x0000c4f8 + .long 0x0800e4f8 + .long 0x00006038 + .long 0x2000804e + + .global do_stq_be +do_stq_be: + .long 0x000004e9 + .long 0x080024e9 + .long 0x020003f9 + .long 0x00006038 + .long 0x2000804e diff --git a/tests/modes/modes.c b/tests/modes/modes.c index 5d0c870..c8ec9ce 100644 --- a/tests/modes/modes.c +++ b/tests/modes/modes.c @@ -12,6 +12,14 @@ extern unsigned long callit(unsigned long arg1, unsigned long arg2, unsigned long fn, unsigned long msr); +extern void do_lq(void *src, unsigned long *regs); +extern void do_lq_np(void *src, unsigned long *regs); +extern void do_lq_bad(void *src, unsigned long *regs); +extern void do_stq(void *dst, unsigned long *regs); +extern void do_lq_be(void *src, unsigned long *regs); +extern void do_lq_np_be(void *src, unsigned long *regs); +extern void do_stq_be(void *dst, unsigned long *regs); + static inline void do_tlbie(unsigned long rb, unsigned long rs) { __asm__ volatile("tlbie %0,%1" : : "r" (rb), "r" (rs) : "memory"); @@ -24,6 +32,7 @@ static inline void do_tlbie(unsigned long rb, unsigned long rs) #define PID 48 #define SPRG0 272 #define SPRG1 273 +#define SPRG3 275 #define PRTBL 720 static inline unsigned long mfspr(int sprnum) @@ -290,6 +299,167 @@ int mode_test_6(void) return 0; } +int mode_test_7(void) +{ + unsigned long quad[4] __attribute__((__aligned__(16))); + unsigned long regs[2]; + unsigned long ret, msr; + + /* + * Test lq/stq in LE mode + */ + msr = MSR_SF | MSR_LE; + quad[0] = 0x123456789abcdef0ul; + quad[1] = 0xfafa5959bcbc3434ul; + ret = callit((unsigned long)quad, (unsigned long)regs, + (unsigned long)&do_lq, msr); + if (ret) + return ret | 1; + if (regs[0] != quad[1] || regs[1] != quad[0]) + return 2; + /* unaligned may give alignment interrupt */ + quad[2] = 0x0011223344556677ul; + ret = callit((unsigned long)&quad[1], (unsigned long)regs, + (unsigned long)&do_lq, msr); + if (ret == 0) { + if (regs[0] != quad[2] || regs[1] != quad[1]) + return 3; + } else if (ret == 0x600) { + if (mfspr(SPRG0) != (unsigned long) &do_lq || + mfspr(DAR) != (unsigned long) &quad[1]) + return ret | 4; + } else + return ret | 5; + + /* try stq */ + regs[0] = 0x5238523852385238ul; + regs[1] = 0x5239523952395239ul; + ret = callit((unsigned long)quad, (unsigned long)regs, + (unsigned long)&do_stq, msr); + if (ret) + return ret | 5; + if (quad[0] != regs[1] || quad[1] != regs[0]) + return 6; + regs[0] = 0x0172686966746564ul; + regs[1] = 0xfe8d0badd00dabcdul; + ret = callit((unsigned long)quad + 1, (unsigned long)regs, + (unsigned long)&do_stq, msr); + if (ret) + return ret | 7; + if (((quad[0] >> 8) | (quad[1] << 56)) != regs[1] || + ((quad[1] >> 8) | (quad[2] << 56)) != regs[0]) + return 8; + + /* try lq non-preferred form */ + quad[0] = 0x56789abcdef01234ul; + quad[1] = 0x5959bcbc3434fafaul; + ret = callit((unsigned long)quad, (unsigned long)regs, + (unsigned long)&do_lq_np, msr); + if (ret) + return ret | 9; + if (regs[0] != quad[1] || regs[1] != quad[0]) + return 10; + /* unaligned should give alignment interrupt in uW implementation */ + quad[2] = 0x6677001122334455ul; + ret = callit((unsigned long)&quad[1], (unsigned long)regs, + (unsigned long)&do_lq_np, msr); + if (ret == 0x600) { + if (mfspr(SPRG0) != (unsigned long) &do_lq_np + 4 || + mfspr(DAR) != (unsigned long) &quad[1]) + return ret | 11; + } else + return 12; + + /* make sure lq with rt = ra causes an illegal instruction interrupt */ + ret = callit((unsigned long)quad, (unsigned long)regs, + (unsigned long)&do_lq_bad, msr); + if (ret != 0x700) + return 13; + if (mfspr(SPRG0) != (unsigned long)&do_lq_bad + 4 || + !(mfspr(SPRG3) & 0x80000)) + return 14; + return 0; +} + +int mode_test_8(void) +{ + unsigned long quad[4] __attribute__((__aligned__(16))); + unsigned long regs[2]; + unsigned long ret, msr; + + /* + * Test lq/stq in BE mode + */ + msr = MSR_SF; + quad[0] = 0x123456789abcdef0ul; + quad[1] = 0xfafa5959bcbc3434ul; + ret = callit((unsigned long)quad, (unsigned long)regs, + (unsigned long)&do_lq_be, msr); + if (ret) + return ret | 1; + if (regs[0] != quad[0] || regs[1] != quad[1]) { + print_hex(regs[0], 16); + print_string(" "); + print_hex(regs[1], 16); + print_string(" "); + return 2; + } + /* don't expect alignment interrupt */ + quad[2] = 0x0011223344556677ul; + ret = callit((unsigned long)&quad[1], (unsigned long)regs, + (unsigned long)&do_lq_be, msr); + if (ret == 0) { + if (regs[0] != quad[1] || regs[1] != quad[2]) + return 3; + } else + return ret | 5; + + /* try stq */ + regs[0] = 0x5238523852385238ul; + regs[1] = 0x5239523952395239ul; + ret = callit((unsigned long)quad, (unsigned long)regs, + (unsigned long)&do_stq_be, msr); + if (ret) + return ret | 5; + if (quad[0] != regs[0] || quad[1] != regs[1]) + return 6; + regs[0] = 0x0172686966746564ul; + regs[1] = 0xfe8d0badd00dabcdul; + ret = callit((unsigned long)quad + 1, (unsigned long)regs, + (unsigned long)&do_stq_be, msr); + if (ret) + return ret | 7; + if (((quad[0] >> 8) | (quad[1] << 56)) != regs[0] || + ((quad[1] >> 8) | (quad[2] << 56)) != regs[1]) { + print_hex(quad[0], 16); + print_string(" "); + print_hex(quad[1], 16); + print_string(" "); + print_hex(quad[2], 16); + print_string(" "); + return 8; + } + + /* try lq non-preferred form */ + quad[0] = 0x56789abcdef01234ul; + quad[1] = 0x5959bcbc3434fafaul; + ret = callit((unsigned long)quad, (unsigned long)regs, + (unsigned long)&do_lq_np_be, msr); + if (ret) + return ret | 9; + if (regs[0] != quad[0] || regs[1] != quad[1]) + return 10; + /* unaligned should not give alignment interrupt in uW implementation */ + quad[2] = 0x6677001122334455ul; + ret = callit((unsigned long)&quad[1], (unsigned long)regs, + (unsigned long)&do_lq_np_be, msr); + if (ret) + return ret | 11; + if (regs[0] != quad[1] || regs[1] != quad[2]) + return 12; + return 0; +} + int fail = 0; void do_test(int num, int (*test)(void)) @@ -334,6 +504,8 @@ int main(void) do_test(4, mode_test_4); do_test(5, mode_test_5); do_test(6, mode_test_6); + do_test(7, mode_test_7); + do_test(8, mode_test_8); return fail; } diff --git a/tests/reservation/head.S b/tests/reservation/head.S index ce258b5..4ff85ce 100644 --- a/tests/reservation/head.S +++ b/tests/reservation/head.S @@ -155,3 +155,31 @@ call_ret: ld %r31,248(%r1) addi %r1,%r1,256 blr + + .global do_lqarx +do_lqarx: + /* r3 = src, r4 = regs */ + lqarx %r10,0,%r3 + std %r10,0(%r4) + std %r11,8(%r4) + li %r3,0 + blr + + .global do_lqarx_bad +do_lqarx_bad: + /* r3 = src, r4 = regs */ + .long 0x7d405228 /* lqarx %r10,0,%r10 */ + std %r10,0(%r4) + std %r11,8(%r4) + li %r3,0 + blr + + .global do_stqcx +do_stqcx: + /* r3 = dest, r4 = regs, return CR */ + ld %r10,0(%r4) + ld %r11,8(%r4) + stqcx. %r10,0,%r3 + mfcr %r3 + oris %r3,%r3,1 /* to distinguish from trap number */ + blr diff --git a/tests/reservation/reservation.c b/tests/reservation/reservation.c index 280d76f..4df4511 100644 --- a/tests/reservation/reservation.c +++ b/tests/reservation/reservation.c @@ -7,6 +7,10 @@ extern unsigned long callit(unsigned long arg1, unsigned long arg2, unsigned long (*fn)(unsigned long, unsigned long)); +extern unsigned long do_lqarx(unsigned long src, unsigned long regs); +extern unsigned long do_lqarx_bad(unsigned long src, unsigned long regs); +extern unsigned long do_stqcx(unsigned long dst, unsigned long regs); + #define DSISR 18 #define DAR 19 #define SRR0 26 @@ -161,7 +165,7 @@ int resv_test_2(void) size = 1 << j; for (offset = 0; offset < 16; ++offset) { ret = callit(size, (unsigned long)&x[0] + offset, do_larx); - if (0 && ret == 0 && (offset & (size - 1)) != 0) + if (ret == 0 && (offset & (size - 1)) != 0) return j + 1; if (ret == 0x600) { if ((offset & (size - 1)) == 0) @@ -181,6 +185,63 @@ int resv_test_2(void) return 0; } +/* test lqarx/stqcx */ +int resv_test_3(void) +{ + unsigned long x[4] __attribute__((__aligned__(16))); + unsigned long y[2], regs[2]; + unsigned long ret, offset; + int count; + + x[0] = 0x7766554433221100ul; + x[1] = 0xffeeddccbbaa9988ul; + y[0] = 0x0badcafef00dd00dul; + y[1] = 0xdeadbeef07070707ul; + for (count = 0; count < 1000; ++count) { + ret = callit((unsigned long)x, (unsigned long)regs, do_lqarx); + if (ret) + return ret | 1; + ret = callit((unsigned long)x, (unsigned long)y, do_stqcx); + if (ret < 0x10000) + return ret | 2; + if (ret & 0x20000000) + break; + } + if (count == 1000) + return 3; + if (x[0] != y[1] || x[1] != y[0]) + return 4; + if (regs[1] != 0x7766554433221100ul || regs[0] != 0xffeeddccbbaa9988ul) + return 5; + ret = callit((unsigned long)x, (unsigned long)regs, do_stqcx); + if (ret < 0x10000 || (ret & 0x20000000)) + return ret | 12; + /* test alignment interrupts */ + for (offset = 0; offset < 16; ++offset) { + ret = callit((unsigned long)x + offset, (unsigned long)regs, do_lqarx); + if (ret == 0 && (offset & 15) != 0) + return 6; + if (ret == 0x600) { + if ((offset & 15) == 0) + return ret + 7; + } else if (ret) + return ret; + ret = callit((unsigned long)x + offset, (unsigned long)y, do_stqcx); + if (ret >= 0x10000 && (offset & 15) != 0) + return 8; + if (ret == 0x600) { + if ((offset & 15) == 0) + return ret + 9; + } else if (ret < 0x10000) + return ret; + } + /* test illegal interrupt for bad lqarx case */ + ret = callit((unsigned long)x, (unsigned long)regs, do_lqarx_bad); + if (ret != 0x700 || !(mfspr(SRR1) & 0x80000)) + return ret + 10; + return 0; +} + int fail = 0; void do_test(int num, int (*test)(void)) @@ -205,6 +266,7 @@ int main(void) do_test(1, resv_test_1); do_test(2, resv_test_2); + do_test(3, resv_test_3); return fail; } diff --git a/tests/test_modes.bin b/tests/test_modes.bin index 0c526280d1c1380597eec3e19573d3891b14a1b4..edbe0c85e906b1d2e51257604fa9ca1687263265 100755 GIT binary patch delta 2866 zcmaJ@U2GiH6+SbzcQ^i7*-0okw!+w(Ry(O3Z4%3jv3I?jf>`1Z76=qqeb|Y+`Jn}c z$`!Nem|0tX=mSUz6N#S(un}1NN)Ardw912V5>uo`3KEU-kb+GE-Az)}X%krgB)8w0 znI%pNU1>D;eskxZ?|k>1Z+2uv8X1ue7;9#eH8zUbcZkm#h`WY@G`%})EL zjbpE<8HuLTbDycYvG}D`OH%QmXeuhyG{3N*MB_B5_4cZ|Lb}H996P3F+S*h-jOVle z6g>p?*@nI59W<1XNY#({)q#D~q!~RSYrt4Z$v7nnVUm!k(n0a{=6Nv`PXbeb@%&TF z>qv<*sm;y2@rRuya*y8Ql6z*COODAH|2b|&5Ipm3@F&beG!*AJ5$sv!#W98D2IAlx z=vN4&J*-59c)jbThu+jUp!Tq;vkDxLRlq#MK~gkYkAwNwfI?NXS!xY;ZD}B`s{WAvjAbPi+NOnJtlO1a3UWihj|( z$Ez#UQ%O2(OUlL7+p9!TOb$U5RAynpEvkbTZxj_1TmgdP*F;aL zjw(HcMy}mlM+Y!}W|yl_9p0JtTQ|-Xh2@YyK{+H!Mf5{2ST%3z3$<*+CVWigBs!~b zOnh7#W8P7xUEl+Pd#A-C)a1$NE@LR zt0GUSu!H-vB{JJ?Ikr}GEg#$8P}h*&IktKa`xsb+bjtxNJn;7b1IScEaMxE}@0#?a zW?xyJ9otGtYPJ?A^}Uu-=OtKD+O?ICZd|k2SDNrGN)#$RiI1Vh`P|tI`P|>boPC8Q zW?xxOf^CJ1ifx69>g_LYRc#^YX$NSzlX34s3w#IMZQ(%zVO zfAj5<^qhUNEhOI-n7GikMv@i3?Q4HkzB+4*Z4lzV6GEq9%<;)n)CIAR`u z9WIWQ1@#`Y zA2DY9ao`yTf7-!$AI8)DefEo5tF+fXsof`=PujtbwJVLxuyz>rAjD8t1(MtLlpX8% zK`T%Fm>$uGwL$MOmrnWaVeM(mnJec%l-rsAbVBcVP?B;JhwuJIk`#Ni>kslB7ww-# z*UH94dw+Dj+<3_zi>}>}z9htnGQ4`t3}2eF{~c}il}kiN=j=7H=2iu01k>`%LcGBnKIm-pnzS2RB|dj{S_gOs z)(qSC#zOTbMrW@G@f=Y8@zVpqQubghNjokO@L7lknJ7ql$!LQ45BM@k8o delta 724 zcmXYsUr5tY6vywq=Fe@}nq-tpbDJh=PJR#hHjSMdNd-FkSf^Cebz>L)WE)$iB*lHkDfV3={2xBYFMr$eaTTtSzdx$?ax^E3K%<@ z>1Al|xWPVTVWJ}wP2p}0`*43Y&zF9T73m^Zw|N&OmR4~;=RwCb*2H4AVK;IUiK*e8 zZ_xqNA4ga2)1HRAr%7BBb?>pxihQiIKO*Y7Q42nYTwma~3tY?*{8L{D_*pwW4|dJV z%6s9CW>%*H33YN$6vQ3H__^iYggUw(OBnkxKa8HU|MujdUGV(;s-`QKT0r=?*ox;-E<(;zRk4Q3k>|X> z&`XF#yo``1VD(m4)}nI#<$O+1m)=R9({o0-%=w@fu6S(?pE31Nq|i+0P3XRD&JzNl s)uU_Z)9})Jimt(e_ecfV;ar?7O!PcPKfcR(I2|xOJv^N9jrcA906xPyRn`b8qQA0}pQ>Ndte*lZ_-by_LNlzynt4}xpw*q4@$8Cj>zlwNNHd8tNAxANu9Lz42@e|g(0Vb#%)H9IqgYia@1nZR8b@~?{ZS>Upn9O z7yM1HEDG@=qm`hKp4M|>++vguR#LY<3|m$+4L`Xx{Q~YX;u3TRBAzVc@{PnNp?$!! z{FJ}RIdV)5_4FEvA3Vl!f2T1(^+w{pha&HYmQ5kP2;Yfc3$9lD7GyLRR;i_USE!+d zk7s|-J+3*Nqj{O{r+tU_jrr}NTLsTYWVaEoCi*lJN!EsyZ}M zz)*z{!4?wlokY78qz}Czs212Y#B_ zN{aBf*2p)s1Inc|-y85NGiiP>ut%9o^S1)6tjIqOwAJBz>XzTc?9mhEzNssLHyIn8 zdbIT~#vAoB_RNM5OXa$K(Cv`aeIfcD!YtUcz*1$b8~QLr{ZoiWUer579k@+GHi3*N zFe249*`K=dm8U8`Q%|-}u#S*91Vj4l((YhUO~3>f>)1ZLVfU zbe4Z;XjTub&7u%8GCl9L5al#`2{E2^+c)hRY6d(A&fo(fh9&1YuL{l~FZHfZ~H9V*oxc3J+Hn@r_`%saZY z@yKJ8w}>CDVUHnj%L=sHWCinq{P=@Ri@P(|3-itzaVbB=V*>wJ7Q4WfNTfU%nP6}-5VW81yN`6UWfrnbEBrYkD>M2VK fPr0A{#J@bsF427BH{f1MP8LtE)ZNy9&*}aHrOBqx diff --git a/tests/test_reservation.console_out b/tests/test_reservation.console_out index 0c39ae3..623335d 100644 --- a/tests/test_reservation.console_out +++ b/tests/test_reservation.console_out @@ -1,2 +1,3 @@ test 01:PASS test 02:PASS +test 03:PASS