Message ID | 1458560014-28862-6-git-send-email-lvivier@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Mon, 21 Mar 2016 12:33:34 +0100 Laurent Vivier <lvivier@redhat.com> wrote: > For lswx in little-endian mode, an alignment interrupt occurs. > > Signed-off-by: Laurent Vivier <lvivier@redhat.com> > Reviewed-by: Thomas Huth <thuth@redhat.com> I'm not entirely clear here; will the test fail if the alignment exception doesn't occur in little endian mode? The general trend in Power has been for less and less things to trigger alignment exceptions, so failing to cause an alignment exception shouldn't cause a test failure (as long as the unaligned case is correctly processed, of course). > --- > powerpc/emulator.c | 22 ++++++++++++++++++++++ > 1 file changed, 22 insertions(+) > > diff --git a/powerpc/emulator.c b/powerpc/emulator.c > index 8d0dde2..87ef4a9 100644 > --- a/powerpc/emulator.c > +++ b/powerpc/emulator.c > @@ -7,6 +7,7 @@ > > static int verbose; > static int volatile is_invalid; > +static int volatile alignment; > > static void program_check_handler(struct pt_regs *regs, void *opaque) > { > @@ -30,6 +31,18 @@ static void program_check_handler(struct pt_regs *regs, void *opaque) > regs->nip += 4; > } > > +static void alignment_handler(struct pt_regs *regs, void *opaque) > +{ > + int *data = opaque; > + > + printf("Detected alignment exception 0x%016lx: %08x\n", > + regs->nip, *(uint32_t*)regs->nip); > + > + *data = 1; > + > + regs->nip += 4; > +} > + > static void test_illegal(void) > { > report_prefix_push("invalid"); > @@ -73,6 +86,8 @@ static void test_64bit(void) > * - RT <= RA or RB < RT + (n + 4) is invalid or result is undefined > * - RT == RA == 0 is invalid > * > + * For lswx in little-endian mode, an alignment interrupt always occurs. > + * > */ > > static void test_lswx(void) > @@ -90,6 +105,7 @@ static void test_lswx(void) > > /* check incomplete register filling */ > > + alignment = 0; > asm volatile ("mtxer %[len];" > "li r12,-1;" > "mr r11, r12;" > @@ -103,7 +119,12 @@ static void test_lswx(void) > : > "xer", "r11", "r12", "memory"); > > +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ > + report("alignment", alignment); > + return; > +#else > report("partial", regs[0] == 0x01020300 && regs[1] == (uint64_t)-1); > +#endif > > /* check an old know bug: the number of bytes is used as > * the number of registers, so try 32 bytes. > @@ -200,6 +221,7 @@ int main(int argc, char **argv) > int i; > > handle_exception(0x700, program_check_handler, (void *)&is_invalid); > + handle_exception(0x600, alignment_handler, (void *)&alignment); > > for (i = 0; i < argc; i++) { > if (strcmp(argv[i], "-v") == 0) { > -- > 2.5.0 >
On 22.03.2016 00:56, David Gibson wrote: > On Mon, 21 Mar 2016 12:33:34 +0100 > Laurent Vivier <lvivier@redhat.com> wrote: > >> For lswx in little-endian mode, an alignment interrupt occurs. >> >> Signed-off-by: Laurent Vivier <lvivier@redhat.com> >> Reviewed-by: Thomas Huth <thuth@redhat.com> > > I'm not entirely clear here; will the test fail if the alignment > exception doesn't occur in little endian mode? I think so, yes. > The general trend in Power has been for less and less things to trigger > alignment exceptions, so failing to cause an alignment exception > shouldn't cause a test failure (as long as the unaligned case is > correctly processed, of course). According to the PowerISA 2.07, chapter 6.5.8, lswx should always trigger an alignment exception in little endian mode. So that's architected behavior and the test should be OK, as far as I can see... In case this gets changed with a future CPU, I think the test could be adapted later, too? Thomas
On 22/03/2016 09:12, Thomas Huth wrote: > On 22.03.2016 00:56, David Gibson wrote: >> On Mon, 21 Mar 2016 12:33:34 +0100 >> Laurent Vivier <lvivier@redhat.com> wrote: >> >>> For lswx in little-endian mode, an alignment interrupt occurs. >>> >>> Signed-off-by: Laurent Vivier <lvivier@redhat.com> >>> Reviewed-by: Thomas Huth <thuth@redhat.com> >> >> I'm not entirely clear here; will the test fail if the alignment >> exception doesn't occur in little endian mode? > > I think so, yes. > >> The general trend in Power has been for less and less things to trigger >> alignment exceptions, so failing to cause an alignment exception >> shouldn't cause a test failure (as long as the unaligned case is >> correctly processed, of course). > > According to the PowerISA 2.07, chapter 6.5.8, lswx should always > trigger an alignment exception in little endian mode. So that's > architected behavior and the test should be OK, as far as I can see... > In case this gets changed with a future CPU, I think the test could be > adapted later, too? Exactly. Then in the kernel, the instruction is emulated. It's why I didn't understand why this test case fails with kvm in little endian mode, while is was working on a real host or in a guest. Laurent -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Tue, 22 Mar 2016 09:25:58 +0100 Laurent Vivier <lvivier@redhat.com> wrote: > On 22/03/2016 09:12, Thomas Huth wrote: > > On 22.03.2016 00:56, David Gibson wrote: > >> On Mon, 21 Mar 2016 12:33:34 +0100 > >> Laurent Vivier <lvivier@redhat.com> wrote: > >> > >>> For lswx in little-endian mode, an alignment interrupt occurs. > >>> > >>> Signed-off-by: Laurent Vivier <lvivier@redhat.com> > >>> Reviewed-by: Thomas Huth <thuth@redhat.com> > >> > >> I'm not entirely clear here; will the test fail if the alignment > >> exception doesn't occur in little endian mode? > > > > I think so, yes. > > > >> The general trend in Power has been for less and less things to trigger > >> alignment exceptions, so failing to cause an alignment exception > >> shouldn't cause a test failure (as long as the unaligned case is > >> correctly processed, of course). > > > > According to the PowerISA 2.07, chapter 6.5.8, lswx should always > > trigger an alignment exception in little endian mode. So that's > > architected behavior and the test should be OK, as far as I can see... > > In case this gets changed with a future CPU, I think the test could be > > adapted later, too? > > Exactly. > > Then in the kernel, the instruction is emulated. It's why I didn't > understand why this test case fails with kvm in little endian mode, > while is was working on a real host or in a guest. Ok, then.
diff --git a/powerpc/emulator.c b/powerpc/emulator.c index 8d0dde2..87ef4a9 100644 --- a/powerpc/emulator.c +++ b/powerpc/emulator.c @@ -7,6 +7,7 @@ static int verbose; static int volatile is_invalid; +static int volatile alignment; static void program_check_handler(struct pt_regs *regs, void *opaque) { @@ -30,6 +31,18 @@ static void program_check_handler(struct pt_regs *regs, void *opaque) regs->nip += 4; } +static void alignment_handler(struct pt_regs *regs, void *opaque) +{ + int *data = opaque; + + printf("Detected alignment exception 0x%016lx: %08x\n", + regs->nip, *(uint32_t*)regs->nip); + + *data = 1; + + regs->nip += 4; +} + static void test_illegal(void) { report_prefix_push("invalid"); @@ -73,6 +86,8 @@ static void test_64bit(void) * - RT <= RA or RB < RT + (n + 4) is invalid or result is undefined * - RT == RA == 0 is invalid * + * For lswx in little-endian mode, an alignment interrupt always occurs. + * */ static void test_lswx(void) @@ -90,6 +105,7 @@ static void test_lswx(void) /* check incomplete register filling */ + alignment = 0; asm volatile ("mtxer %[len];" "li r12,-1;" "mr r11, r12;" @@ -103,7 +119,12 @@ static void test_lswx(void) : "xer", "r11", "r12", "memory"); +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + report("alignment", alignment); + return; +#else report("partial", regs[0] == 0x01020300 && regs[1] == (uint64_t)-1); +#endif /* check an old know bug: the number of bytes is used as * the number of registers, so try 32 bytes. @@ -200,6 +221,7 @@ int main(int argc, char **argv) int i; handle_exception(0x700, program_check_handler, (void *)&is_invalid); + handle_exception(0x600, alignment_handler, (void *)&alignment); for (i = 0; i < argc; i++) { if (strcmp(argv[i], "-v") == 0) {