|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] Ping: Ping#3: [PATCH v3] x86/HVM: don't #GP/#SS on wrapping virt->linear translations
>>> On 06.12.17 at 08:44, wrote:
>>>> On 04.12.17 at 17:39, <andrew.cooper3@xxxxxxxxxx> wrote:
> > On 04/12/17 10:16, Jan Beulich wrote:
> >>>>> On 25.08.17 at 16:59, wrote:
> >>>>>> On 10.08.17 at 09:19, <JBeulich@xxxxxxxx> wrote:
> >>>>>>> On 10.07.17 at 12:39, <JBeulich@xxxxxxxx> wrote:
> >>>>> Real hardware wraps silently in most cases, so we should behave the
> >>>>> same. Also split real and VM86 mode handling, as the latter really
> >>>>> ought to have limit checks applied.
> >>>>>
> >>>>> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
> >>>>> ---
> >>>>> v3: Restore 32-bit wrap check for AMD.
> >>>>> v2: Extend to non-64-bit modes. Reduce 64-bit check to a single
> >>>>> is_canonical_address() invocation.
> >> Same here - I think I've been carrying this for long enough.
> >
> > I'm not sure what to say. I'm not comfortable taking this change
> > without a regression test in place, which also serves to demonstrate the
> > correctness of the change.
> >
> > Its simply a matter of time, not any other objection to the change.
>
> Well, I had sent you a tentative XTF test long ago (non-publicly
> at the time, I believe). Here it is again. I'll send a second change
> in a minute, which iirc is necessary as prereq to the one here.
>
> Jan
No matter that hopefully no-one will exercise us currently getting
things wrong, I'd still like to re-raise the fact that the original bug
fix in this thread has been pending for a really long time, and this
XTF test has now also been sent almost 3 months ago.
Jan
> add split memory access tests
>
> Add tests to verify that accesses crossing the upper address boundary
> are being handled similarly with and without the emulator involved.
>
> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
> ---
> v2: Use FS overrides. Add 64-bit and PV tests. Remove stray '-s from
> log messages. Add "X" (ex_record_fault_eax) constraints.
>
> --- /dev/null
> +++ b/tests/split-access/Makefile
> @@ -0,0 +1,9 @@
> +include $(ROOT)/build/common.mk
> +
> +NAME := split-access
> +CATEGORY := functional
> +TEST-ENVS := $(ALL_ENVIRONMENTS)
> +
> +obj-perenv += main.o
> +
> +include $(ROOT)/build/gen.mk
> --- /dev/null
> +++ b/tests/split-access/main.c
> @@ -0,0 +1,251 @@
> +/**
> + * @file tests/split-access/main.c
> + * @ref test-split-access
> + *
> + * @page test-split-access split-access
> + *
> + * @todo Docs for test-split-access
> + *
> + * @see tests/split-access/main.c
> + */
> +#include <xtf.h>
> +
> +#include <arch/decode.h>
> +#include <arch/pagetable.h>
> +
> +const char test_title[] = "Split memory access insns";
> +
> +const void *volatile boundary = NULL;
> +
> +/* Keep the compiler from leveraging undefined behavior. */
> +#define touch(x) ({ asm ( "" : "+g" (x) ); })
> +
> +void do_mov(bool force)
> +{
> + const unsigned long *ptr = boundary;
> +
> + touch(ptr);
> + for ( --ptr; ; )
> + {
> + unsigned long val;
> + exinfo_t fault = 0;
> +
> + asm volatile ( "test %[fep], %[fep];"
> + "jz 1f;"
> + _ASM_XEN_FEP
> + "1: mov %%fs:%[src],%[dst]; 2:"
> + _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_eax)
> + : [dst] "=r" (val), "+a" (fault)
> + : [src] "m" (*ptr), [fep] "q" (force),
> + "X" (ex_record_fault_eax) );
> + if ( fault )
> + xtf_warning("Got %pe for %p\n", _p(fault), ptr);
> + else if ( val != *ptr )
> + xtf_failure("%lx != %lx for %p\n", val, *ptr, ptr);
> +
> + touch(ptr);
> + if ( ptr == boundary )
> + break;
> +
> + ptr = (void *)(long)ptr + 1;
> + }
> +}
> +
> +void do_lfs(bool force)
> +{
> + const struct __packed { unsigned long off; uint16_t sel; } *ptr =
> boundary;
> +
> + touch(ptr);
> + for ( --ptr; ; )
> + {
> + unsigned long off;
> + exinfo_t fault = 0;
> +
> + asm volatile ( "test %[fep], %[fep];"
> + "jz 1f;"
> + _ASM_XEN_FEP
> + "1: lfs %%fs:%[src],%[dst]; 2:"
> + _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_eax)
> + : [dst] "=r" (off), "+a" (fault)
> + : [src] "m" (*ptr), [fep] "q" (force),
> + "X" (ex_record_fault_eax) );
> + if ( fault )
> + xtf_warning("Got %pe for %p\n", _p(fault), ptr);
> + else if ( off != ptr->off )
> + xtf_failure("%lx != %lx for %p\n", off, ptr->off, ptr);
> +
> + touch(ptr);
> + if ( ptr == boundary )
> + break;
> +
> + ptr = (void *)(long)ptr + 1;
> + }
> +}
> +
> +#ifdef CONFIG_HVM
> +void do_lidt(bool force)
> +{
> + const desc_ptr *ptr = boundary;
> +
> + touch(ptr);
> + for ( --ptr; ; )
> + {
> + exinfo_t fault = 0;
> +
> + asm volatile ( "test %[fep], %[fep];"
> + "jz 1f;"
> + _ASM_XEN_FEP
> + "1: lidt %%fs:%[src]; 2:"
> + _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_eax)
> + : "+a" (fault)
> + : [src] "m" (*ptr), [fep] "q" (force),
> + "X" (ex_record_fault_eax) );
> + if ( fault )
> + xtf_warning("Got %pe for %p\n", _p(fault), ptr);
> + else
> + asm volatile ( "lidt %0" :: "m" (idt_ptr) );
> +
> + touch(ptr);
> + if ( ptr == boundary )
> + break;
> +
> + ptr = (void *)(long)ptr + 1;
> + }
> +}
> +#endif
> +
> +#ifndef __x86_64__
> +void do_bound(bool force)
> +{
> + const struct { unsigned long lo, hi; } *ptr = boundary;
> +
> + touch(ptr);
> + for ( --ptr; ; )
> + {
> + exinfo_t fault = 0;
> +
> + asm volatile ( "test %[fep], %[fep];"
> + "jz 1f;"
> + _ASM_XEN_FEP
> + "1: bound %[off], %%fs:%[bnd]; 2:"
> + _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_eax)
> + : "+a" (fault)
> + : [bnd] "m" (*ptr), [off] "r" (0), [fep] "q" (force),
> + "X" (ex_record_fault_eax) );
> + if ( fault )
> + xtf_warning("Got %pe for %p\n", _p(fault), ptr);
> +
> + touch(ptr);
> + if ( ptr == boundary )
> + break;
> +
> + ptr = (void *)(long)ptr + 1;
> + }
> +}
> +#endif
> +
> +void run_tests(bool force)
> +{
> + printk("Testing%s MOV\n", force ? " emulated" : "");
> + do_mov(force);
> +
> + printk("Testing%s LFS\n", force ? " emulated" : "");
> + do_lfs(force);
> +
> +#ifdef CONFIG_HVM
> + printk("Testing%s LIDT\n", force ? " emulated" : "");
> + do_lidt(force);
> +#endif
> +
> +#ifndef __x86_64__
> + printk("Testing%s BOUND\n", force ? " emulated" : "");
> + do_bound(force);
> +#endif
> +}
> +
> +void test_main(void)
> +{
> +#if defined(__x86_64__)
> + if ( !boundary )
> + {
> + asm volatile ( "push $0; pop %%fs" ::: "memory" );
> +
> +# if CONFIG_PAGING_LEVELS == 4
> + boundary = (void *)(1L << 47);
> +# elif CONFIG_PAGING_LEVELS == 5
> + boundary = (void *)(1L << 56);
> +# else
> +# error Unknown 64-bit paging mode!
> +# endif
> + printk("Testing at lower canonical boundary\n");
> + test_main();
> +
> + boundary = NULL;
> + printk("Testing at upper address boundary\n");
> + }
> +#elif defined(CONFIG_PV)
> + /* Shrink %fs limit to below the compat limit. */
> + static struct seg_desc32 __page_aligned_data desc[] = {
> + [1] = {
> + .limit0 = 0x4fff, .limit1 = 0xf, .g = 1,
> + .p = 1, .s = 1, .type = 3, .dpl = 1,
> + },
> + };
> + unsigned long frame = virt_to_mfn(desc);
> + int rc;
> +
> + rc = hypercall_update_va_mapping((unsigned long)desc,
> + pte_from_gfn(frame,
> + _PAGE_PRESENT|_PAGE_AD),
> + 0);
> + if ( !rc )
> + rc = HYPERCALL2(int, __HYPERVISOR_set_gdt, &frame, ARRAY_SIZE(desc));
> + if ( rc )
> + {
> + xtf_error("Cannot set GDT entry: %d\n", rc);
> + return;
> + }
> +
> + asm volatile ( "mov %1, %%fs; lsl %1, %0"
> + : "=r" (boundary)
> + : "r" (sizeof(*desc) | 1)
> + : "memory" );
> +#else
> + /*
> + * To better tell actual hardware behavior, zap the mapping for the last
> + * (large) page below 4Gb. That'll make us see page faults on hardware
> + * when all segmentation checks pass, rather than observing #GP/#SS due
> to
> + * the emulator being invoked anyway due to accesses touching an unmapped
> + * MMIO range. This matches x86-64 behavior at the 2^^64 boundary.
> + */
> +# if CONFIG_PAGING_LEVELS == 2
> + pse_l2_identmap[pse_l2_table_offset(~0UL)] = 0;
> +# elif CONFIG_PAGING_LEVELS == 3
> + pae_l2_identmap[pae_l2_table_offset(~0UL)] = 0;
> +# elif CONFIG_PAGING_LEVELS
> +# error Unknown 32-bit paging mode!
> +# endif
> +
> + invlpg((void *)~0UL);
> + asm volatile ( "push %%ds; pop %%fs" ::: "memory" );
> +#endif
> +
> + run_tests(false);
> +
> + if ( !xtf_has_fep )
> + xtf_skip("FEP support not detected - some tests will be skipped\n");
> + else
> + run_tests(true);
> +
> + xtf_success(NULL);
> +}
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * tab-width: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
>
>
>
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |