[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v3 2/5] tests/x86: Introduce a userspace test harness for x86_decode_lite()


  • To: Jan Beulich <jbeulich@xxxxxxxx>
  • From: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
  • Date: Tue, 4 Aug 2026 20:37:15 +0100
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=citrix.com; dmarc=pass action=none header.from=citrix.com; dkim=pass header.d=citrix.com; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=ZHm4HRFiqf/aeTm09glhME2FcmaxvO1JNLPRKicy50A=; b=QR1X279M1ywxMJXfgThHE10EYi95003jbNHG2g4zSieqAB+hjsj22OnmshUrwkvFJkVpQOHC+eOvhbvUh86aIitifkU1D51UWI2r0R9lvfT+R3Y0OuJfFqavkw1YYBwbYklyG6kbDtPKR+T8B+xeuQPdTrZG1PN7tgnW0Qn25dsTdkOkjvdCE909xoR3s7RjM3bopiVyYOaVPmxArgJ53LdHwCBbVtjD61lZqFuZEguEpZw6Yf0/sSBjn+DHQ/viGnOTJpMHC/k2MCDNVaWGKDyZBMUeJxYse3qF63WgbgoUr9szH5ZsNTOPajUEoN0h1Sz27jNOPUAI6muJoPuHVg==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=Pz2DT61shBSEzN8w+Gte4E8/Pd/ITPXBVulHj3lEE+fBPfkikKw2loC6poxtEFa57Z2+kjyLZuWdwnIE5f8jU4EE+t02Qq8yCpXBBCd/BLwNJrYg6chF7UqcN08DblvUOJIh9eYIFB0u4RC1w+CcOiT9oP2BV9L5Ik/uICs+NdNHwAan/OApBd2RlH3NzSAVz9bVgodyPxcTZt2ipUnl9ADeMYZQDqkBZIw8iKSXQVKDcwOY6qYQPcwSpGVLdcKm3YnPT6bIbJ0v10TkYkYbtZKCTJvxKYbyDbd04jTU6kiN4q2S5F/S3c+5AiuTMGiSZLdngdV1wEBnFzlZV3Prog==
  • Authentication-results: eu.smtp.expurgate.cloud; dkim=pass header.s=selector1 header.d=citrix.com header.i="@citrix.com" header.h="From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck"
  • Authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=citrix.com;
  • Autocrypt: addr=andrew.cooper3@xxxxxxxxxx; keydata= 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 6+ahAA==
  • Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>, Roger Pau Monné <roger@xxxxxxxxxxxxxx>, Teddy Astie <teddy.astie@xxxxxxxxxx>, Xen-devel <xen-devel@xxxxxxxxxxxxxxxxxxxx>
  • Delivery-date: Tue, 04 Aug 2026 19:37:31 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

On 03/08/2026 5:03 pm, Jan Beulich wrote:
> On 03.08.2026 09:20, Andrew Cooper wrote:
>> --- /dev/null
>> +++ b/tools/tests/x86-decode-lite/insns.S
>> @@ -0,0 +1,703 @@
>> +#include "macro-magic.h"
>> +
>> +        .code64
>> +
>> +        .allow_index_reg
>> +
>> +        .text
>> +
>> +DECL(tests_rel0)
>> +modrm:
>> +        /* Mod=0, Reg=0, RM {0..f} */
>> +        _ add %al, (%rax)
>> +        _ add %al, (%rcx)
>> +        _ add %al, (%rdx)
>> +        _ add %al, (%rbx)
>> +        _ add %al, (%rsp) /* SIB */
>> +        /*add %al, (%rbp)    RIP --> tests_rel4 */
>> +        _ add %al, (%rsi)
>> +        _ add %al, (%rdi)
>> +        _ add %al, (%r8)
>> +        _ add %al, (%r9)
>> +        _ add %al, (%r10)
>> +        _ add %al, (%r11)
>> +        _ add %al, (%r12) /* SIB */
>> +        /*add %al, (%r13)    RIP --> tests_rel4 */
>> +        _ add %al, (%r14)
>> +        _ add %al, (%r15)
>> +
>> +        /* Mod=1, Reg=0, RM {0..f} */
>> +        _ add %al, 0x01(%rax)
>> +        _ add %al, 0x01(%rcx)
>> +        _ add %al, 0x01(%rdx)
>> +        _ add %al, 0x01(%rbx)
>> +        _ add %al, 0x01(%rsp) /* SIB */
>> +        _ add %al, 0x01(%rbp)
>> +        _ add %al, 0x01(%rsi)
>> +        _ add %al, 0x01(%rdi)
>> +        _ add %al, 0x01(%r8)
>> +        _ add %al, 0x01(%r9)
>> +        _ add %al, 0x01(%r10)
>> +        _ add %al, 0x01(%r11)
>> +        _ add %al, 0x01(%r12) /* SIB */
>> +        _ add %al, 0x01(%r13)
>> +        _ add %al, 0x01(%r14)
>> +        _ add %al, 0x01(%r15)
>> +
>> +        /* Mod=2, Reg=0, RM {0..f} */
>> +        _ add %al, 0x7f000001(%rax)
>> +        _ add %al, 0x7f000001(%rcx)
>> +        _ add %al, 0x7f000001(%rdx)
>> +        _ add %al, 0x7f000001(%rbx)
>> +        _ add %al, 0x7f000001(%rsp) /* SIB */
>> +        _ add %al, 0x7f000001(%rbp)
>> +        _ add %al, 0x7f000001(%rsi)
>> +        _ add %al, 0x7f000001(%rdi)
>> +        _ add %al, 0x7f000001(%r8)
>> +        _ add %al, 0x7f000001(%r9)
>> +        _ add %al, 0x7f000001(%r10)
>> +        _ add %al, 0x7f000001(%r11)
>> +        _ add %al, 0x7f000001(%r12) /* SIB */
>> +        _ add %al, 0x7f000001(%r13)
>> +        _ add %al, 0x7f000001(%r14)
>> +        _ add %al, 0x7f000001(%r15)
>> +
>> +        /* Mod=3, Reg=0, RM {0..f} */
>> +        _ add %al, %al
>> +        _ add %al, %cl
>> +        _ add %al, %dl
>> +        _ add %al, %bl
>> +        _ add %al, %ah
>> +        _ add %al, %ch
>> +        _ add %al, %dh
>> +        _ add %al, %dl
> Perhaps also include %bpl, %sil, and %dil?

They're not relevant to this test, and interfere with the intentional
pattern set up.

>
>> +onebyte_row_9x:
>> +        _ nop
>> +        _ pause
>> +        _ xchg %ax, %ax
>> +        _ xchg %eax, %eax
>> +        _ xchg %rax, %rax
>> +        _ rex.w xchg %rax, %rax
>> +        _ cltq
>> +        _ cqto
>> +        _ wait
>> +        _ pushf
>> +        _ popf
>> +        _ sahf
>> +        _ lahf
>> +
>> +onebyte_row_ax:
> May I suggest onebyte_row_Ax?

Ok.

>
>> +DECL(tests_rel1)
>> +disp8:
>> +1:
>> +        _ jo   1b
>> +        _ jno  1b
>> +        _ jb   1b
>> +        _ jae  1b
>> +        _ je   1b
>> +        _ jne  1b
>> +        _ jbe  1b
>> +        _ ja   1b
>> +        _ js   1b
>> +        _ jns  1b
>> +        _ jp   1b
>> +        _ jnp  1b
>> +        _ jl   1b
>> +        _ jge  1b
>> +        _ jle  1b
>> +        _ jg   1b
>> +        _ jmp  1b
>> +
>> +disp8_rex:
>> +        _ rex.w jo   1b
>> +        _ rex.w jno  1b
>> +        _ rex.w jb   1b
>> +        _ rex.w jae  1b
>> +        _ rex.w je   1b
>> +        _ rex.w jne  1b
>> +        _ rex.w jbe  1b
>> +        _ rex.w ja   1b
>> +        _ rex.w js   1b
>> +        _ rex.w jns  1b
>> +        _ rex.w jp   1b
>> +        _ rex.w jnp  1b
>> +        _ rex.w jl   1b
>> +        _ rex.w jge  1b
>> +        _ rex.w jle  1b
>> +        _ rex.w jg   1b
>> +        _ rex.w jmp  1b
>> +END(tests_rel1)
> What's the idea behind the separate REX.W testing?

Testing osize handling vs Imm8/Imm.

>  It almost suggests that
> tests with an operand size prefix also may want adding. Except that's
> difficult, because of ...
>
>> +DECL(tests_rel4)
>> +disp32:
>> +        _ call   other_section
>> +        _ jmp    other_section
>> +        _ jo     other_section
>> +        _ jno    other_section
>> +        _ jb     other_section
>> +        _ jae    other_section
>> +        _ je     other_section
>> +        _ jne    other_section
>> +        _ jbe    other_section
>> +        _ ja     other_section
>> +        _ js     other_section
>> +        _ jns    other_section
>> +        _ jp     other_section
>> +        _ jnp    other_section
>> +        _ jl     other_section
>> +        _ jge    other_section
>> +        _ jle    other_section
>> +        _ jg     other_section
>> +        _ xbegin other_section
>> +
>> +disp32_rex:
>> +        _ rex.w call   other_section
>> +        _ rex.w jmp    other_section
>> +        _ rex.w jo     other_section
>> +        _ rex.w jno    other_section
>> +        _ rex.w jb     other_section
>> +        _ rex.w jae    other_section
>> +        _ rex.w je     other_section
>> +        _ rex.w jne    other_section
>> +        _ rex.w jbe    other_section
>> +        _ rex.w ja     other_section
>> +        _ rex.w js     other_section
>> +        _ rex.w jns    other_section
>> +        _ rex.w jp     other_section
>> +        _ rex.w jnp    other_section
>> +        _ rex.w jl     other_section
>> +        _ rex.w jge    other_section
>> +        _ rex.w jle    other_section
>> +        _ rex.w jg     other_section
>> +        _ rex.w xbegin other_section
> ... vendor differences here. Perhaps the decoder itself would better
> reject handling of operand-size-prefixed branches.

Excluding 66-prefix is easy, but excluding rex.w on jumps is hard and
would require extra logic.

>> +opsize_branch: /* 66-prefixed branches are decoded differently by vendors */
>> +        _ data16 call   other_section
>> +        _ data16 jmp    other_section
>> +        _ data16 jo     other_section
>> +        _ data16 jno    other_section
>> +        _ data16 jb     other_section
>> +        _ data16 jae    other_section
>> +        _ data16 je     other_section
>> +        _ data16 jne    other_section
>> +        _ data16 jbe    other_section
>> +        _ data16 ja     other_section
>> +        _ data16 js     other_section
>> +        _ data16 jns    other_section
>> +        _ data16 jp     other_section
>> +        _ data16 jnp    other_section
>> +        _ data16 jl     other_section
>> +        _ data16 jge    other_section
>> +        _ data16 jle    other_section
>> +        _ data16 jg     other_section
>> +        _ data16 xbegin other_section
> Oh, you even cover the case here. For XBEGIN, however, this can only be pure
> guesswork as to AMD behavior, I suppose.

Remember that RTM is available on Zen2 if you know which chickenbits to
clobber.

I've not tried.  I expect it's more likely that they behave consistently
than differently.

> I also don't see how you force which form you want.

Binutils always produces AMD behaviour.  (As far as I can see.)

This is in the negative-tests section, which confirms that
x86_decode_lite() rejects the byte pattern.

If Binutils changes behaviour, the test will start failing.

>
>> --- /dev/null
>> +++ b/tools/tests/x86-decode-lite/main.c
>> @@ -0,0 +1,111 @@
>> +/*
>> + * Userspace test harness for x86_decode_lite().
>> + */
>> +#include <stdio.h>
>> +
>> +#include "x86-emulate.h"
>> +
>> +static unsigned int nr_failures;
>> +#define fail(t, fmt, ...)                                       \
>> +({                                                              \
>> +    const unsigned char *insn = (t)->ip;                        \
>> +                                                                \
>> +    nr_failures++;                                              \
>> +                                                                \
>> +    (void)printf("  Fail '%s' [%02x", (t)->name, *insn);        \
>> +    for ( unsigned int i = 1; i < (t)->len; i++ )               \
>> +        printf(" %02x", insn[i]);                               \
>> +    printf("]\n");                                              \
>> +                                                                \
>> +    (void)printf(fmt, ##__VA_ARGS__);                           \
>> +})
>> +
>> +struct test {
>> +    const char *name;
>> +    void *ip;
>> +    unsigned long len;
>> +};
>> +
>> +extern const struct test
>> +/* Defined in insns.S, ends with sentinel */
>> +    tests_rel0[], /* No relocatable entry */
>> +    tests_rel1[], /* disp8 */
>> +    tests_rel4[], /* disp32 or RIP-relative */
>> +    tests_unsup[]; /* Unsupported instructions */
>> +
>> +static inline void run_tests(const struct test *tests, unsigned int rel_sz)
>> +{
>> +    printf("Test rel%u\n", rel_sz);
>> +
>> +    for ( unsigned int i = 0; tests[i].name; ++i )
>> +    {
>> +        const struct test *t = &tests[i];
>> +        x86_decode_lite_t r;
>> +
>> +        /*
>> +         * Don't end strictly at t->len.  This provides better diagnostics 
>> if
>> +         * too many bytes end up getting consumed.
>> +         */
>> +        r = x86_decode_lite(t->ip, t->ip + /* t->len */ 20);
> For the excess bytes to at least be legitimate to access (not causing UB),
> shouldn't finish_arr emit enough filler bytes?

finish_arr is the wrong place, but I've folded in:

diff --git a/tools/tests/x86-decode-lite/insns.S 
b/tools/tests/x86-decode-lite/insns.S
index e52c2934c8d8..dc017016b2d2 100644
--- a/tools/tests/x86-decode-lite/insns.S
+++ b/tools/tests/x86-decode-lite/insns.S
@@ -695,6 +695,13 @@ unsup_insn: /* Instructions that would complicated decode, 
or shouldn't be used
 
 END(tests_unsup)
 
+        /*
+         * For improved diagnostics, we allow some overreading of the
+         * instruction under test.  Ensure there are good bytes to read.
+         */
+overread_padding:
+        .skip 20
+
         /* This is here to cause jmps to use their disp32 form. */
         .section .text.other_section, "ax", @progbits
 other_section:



>
>> --- /dev/null
>> +++ b/tools/tests/x86-decode-lite/x86-emulate.h
>> @@ -0,0 +1,27 @@
>> +#ifndef X86_EMULATE_H
>> +#define X86_EMULATE_H
>> +
>> +#include <assert.h>
>> +#include <stdbool.h>
>> +#include <stdint.h>
>> +#include <stdlib.h>
>> +#include <string.h>
>> +
>> +#include <xen/asm/x86-defns.h>
>> +#include <xen/asm/x86-vendors.h>
>> +
>> +#include <xen-tools/common-macros.h>
>> +
>> +#define ASSERT assert
>> +
>> +#define printk(...)
>> +
>> +#define likely
>> +#define unlikely
>> +#define cf_check
>> +#define init_or_livepatch
>> +#define init_or_livepatch_const
>> +
>> +#include "x86_emulate/x86_emulate.h"
> Why does this end up being needed?

Well, this for starters:

main.c: In function ‘run_tests’:
main.c:43:9: error: unknown type name ‘x86_decode_lite_t’
   43 |         x86_decode_lite_t r;
      |         ^~~~~~~~~~~~~~~~~
main.c:49:13: error: implicit declaration of function ‘x86_decode_lite’ 
[-Werror=implicit-function-declaration]
   49 |         r = x86_decode_lite(t->ip, t->ip + /* t->len */ 20);
      |             ^~~~~~~~~~~~~~~



~Andrew



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.