mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-01-11 23:43:15 +00:00
tests: Add tests for lq/stq, plq/pstq 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 (64-bit). Plq and pstq are tested in 64-bit LE mode by the 'prefix' test. Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
This commit is contained in:
parent
722f239c02
commit
140b930ad3
@ -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
|
||||
|
||||
@ -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");
|
||||
@ -25,6 +33,8 @@ static inline void do_tlbie(unsigned long rb, unsigned long rs)
|
||||
#define SPRG0 272
|
||||
#define SPRG1 273
|
||||
#define SPRG3 275
|
||||
#define HSRR0 314
|
||||
#define HSRR1 315
|
||||
#define PTCR 464
|
||||
|
||||
static inline unsigned long mfspr(int sprnum)
|
||||
@ -294,6 +304,166 @@ 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 a HEAI interrupt */
|
||||
ret = callit((unsigned long)quad, (unsigned long)regs,
|
||||
(unsigned long)&do_lq_bad, msr);
|
||||
if (ret != 0xe40)
|
||||
return 13;
|
||||
if (mfspr(HSRR0) != (unsigned long)&do_lq_bad + 4)
|
||||
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))
|
||||
@ -338,6 +508,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;
|
||||
}
|
||||
|
||||
@ -245,3 +245,23 @@ test_pstw:
|
||||
pstw %r3,wvar(0)
|
||||
li %r3,0
|
||||
blr
|
||||
|
||||
.globl test_plq
|
||||
test_plq:
|
||||
nop
|
||||
nop
|
||||
plq %r4,qvar(0)
|
||||
std %r4,0(%r3)
|
||||
std %r5,8(%r3)
|
||||
li %r3,0
|
||||
blr
|
||||
|
||||
.globl test_pstq
|
||||
test_pstq:
|
||||
nop
|
||||
nop
|
||||
ld %r4,0(%r3)
|
||||
ld %r5,8(%r3)
|
||||
pstq %r4,qvar(0)
|
||||
li %r3,0
|
||||
blr
|
||||
|
||||
@ -33,6 +33,8 @@ extern long test_pstd(long arg);
|
||||
extern long test_psth(long arg);
|
||||
extern long test_pstw(long arg);
|
||||
extern long test_plfd(long arg);
|
||||
extern long test_plq(long arg);
|
||||
extern long test_pstq(long arg);
|
||||
|
||||
static inline unsigned long mfspr(int sprnum)
|
||||
{
|
||||
@ -183,6 +185,39 @@ long int prefix_test_3(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long qvar[2] __attribute__((__aligned__(16)));
|
||||
#define V1 0x678912345a5a2b2bull
|
||||
#define V2 0xa0549922bbccddeeull
|
||||
|
||||
/* test plq and pstq */
|
||||
long int prefix_test_4(void)
|
||||
{
|
||||
long int ret;
|
||||
unsigned long x[2];
|
||||
|
||||
qvar[0] = V1;
|
||||
qvar[1] = V2;
|
||||
ret = trapit((long)&x, test_plq);
|
||||
if (ret)
|
||||
return ret | 1;
|
||||
if (x[0] != V1 || x[1] != V2) {
|
||||
print_hex(x[0], 16, " ");
|
||||
print_hex(x[1], 16, " ");
|
||||
return 2;
|
||||
}
|
||||
x[0] = ~V2;
|
||||
x[1] = ~V1;
|
||||
ret = trapit((long)&x, test_pstq);
|
||||
if (ret)
|
||||
return ret | 3;
|
||||
if (qvar[0] != ~V2 || qvar[1] != ~V1) {
|
||||
print_hex(qvar[0], 16, " ");
|
||||
print_hex(qvar[1], 16, " ");
|
||||
return 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fail = 0;
|
||||
|
||||
void do_test(int num, long int (*test)(void))
|
||||
@ -210,6 +245,7 @@ int main(void)
|
||||
do_test(1, prefix_test_1);
|
||||
do_test(2, prefix_test_2);
|
||||
do_test(3, prefix_test_3);
|
||||
do_test(4, prefix_test_4);
|
||||
|
||||
return fail;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
@ -180,6 +184,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 != 0xe40)
|
||||
return ret + 10;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fail = 0;
|
||||
|
||||
void do_test(int num, int (*test)(void))
|
||||
@ -204,6 +265,7 @@ int main(void)
|
||||
|
||||
do_test(1, resv_test_1);
|
||||
do_test(2, resv_test_2);
|
||||
do_test(3, resv_test_3);
|
||||
|
||||
return fail;
|
||||
}
|
||||
|
||||
Binary file not shown.
@ -4,3 +4,5 @@ test 03:PASS
|
||||
test 04:PASS
|
||||
test 05:PASS
|
||||
test 06:PASS
|
||||
test 07:PASS
|
||||
test 08:PASS
|
||||
|
||||
Binary file not shown.
@ -1,3 +1,4 @@
|
||||
test 01:PASS
|
||||
test 02:PASS
|
||||
test 03:PASS
|
||||
test 04:PASS
|
||||
|
||||
Binary file not shown.
@ -1,2 +1,3 @@
|
||||
test 01:PASS
|
||||
test 02:PASS
|
||||
test 03:PASS
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user