From: Andrew Cooper Date: Mon, 6 Mar 2017 11:58:05 +0000 (+0000) Subject: Drop test_wants_user_mappings infrastructure X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=1d68cab2189bd035002ecc32cce154f979f9eff5;p=people%2Fandrewcoop%2Fxen-test-framework.git Drop test_wants_user_mappings infrastructure As noted in Errata, the test_wants_user_mappings infrastructure has problems for pv32pae environments on Xen 4.6 and earlier, if Xen leaks SMEP/SMAP settings into the guest. Now that all tests have moved to the new .text.user infrastructure, drop test_wants_user_mappings. Signed-off-by: Andrew Cooper --- diff --git a/arch/x86/boot/head_hvm.S b/arch/x86/boot/head_hvm.S index 07ec34f..f5bdf42 100644 --- a/arch/x86/boot/head_hvm.S +++ b/arch/x86/boot/head_hvm.S @@ -10,21 +10,6 @@ GLOBAL(_start) /* HVM common setup. */ #if CONFIG_PAGING_LEVELS > 0 /* Paging setup for CR3 and CR4 */ - /* Set _PAGE_USER on leaf mappings if a test wants them. */ - cmpb $0, test_wants_user_mappings - je .Lskip_user - - mov $l1_identmap, %edx - mov $l2_identmap_end, %ecx - sub %edx, %ecx - shr $PTE_ORDER, %ecx - add $PTE_SIZE, %edx /* Avoid setting _PAGE_USER in the NULL entry. */ -.Lnext_pte: - orb $_PAGE_USER, (%edx) - add $PTE_SIZE, %edx - loop .Lnext_pte -.Lskip_user: - #if CONFIG_PAGING_LEVELS == 2 mov $X86_CR4_PSE, %eax #elif CONFIG_PAGING_LEVELS == 3 || CONFIG_PAGING_LEVELS == 4 diff --git a/arch/x86/hvm/traps.c b/arch/x86/hvm/traps.c index 102af86..b734670 100644 --- a/arch/x86/hvm/traps.c +++ b/arch/x86/hvm/traps.c @@ -155,30 +155,25 @@ void arch_init_traps(void) gdt[GDTE_TSS] = (typeof(*gdt))INIT_GDTE((unsigned long)&tss, 0x67, 0x89); ltr(GDTE_TSS * 8); - /* - * If we haven't applied blanket PAGE_USER mappings, remap the structures - * which specifically want to be user. - */ - if ( !test_wants_user_mappings ) - { - unsigned long gfn = virt_to_gfn(user_stack); + /* Remap user areas with _PAGE_USER. */ + unsigned long gfn = virt_to_gfn(user_stack); - if ( gfn >= ARRAY_SIZE(l1_identmap) ) - panic("user_stack[] outside of l1_identmap[]\n"); + if ( gfn >= ARRAY_SIZE(l1_identmap) ) + panic("user_stack[] outside of l1_identmap[]\n"); - l1_identmap[gfn] |= _PAGE_USER; + l1_identmap[gfn] |= _PAGE_USER; - extern const char __start_user_text[], __end_user_text[]; - unsigned long end = virt_to_gfn(__end_user_text); + extern const char __start_user_text[], __end_user_text[]; + unsigned long end = virt_to_gfn(__end_user_text); - if ( gfn >= ARRAY_SIZE(l1_identmap) ) - panic("__{start,end}_user_text[] outside of l1_identmap[]\n"); + if ( gfn >= ARRAY_SIZE(l1_identmap) ) + panic("__{start,end}_user_text[] outside of l1_identmap[]\n"); - for ( gfn = virt_to_gfn(__start_user_text); gfn < end; ++gfn ) - l1_identmap[gfn] |= _PAGE_USER; + for ( gfn = virt_to_gfn(__start_user_text); gfn < end; ++gfn ) + l1_identmap[gfn] |= _PAGE_USER; + if ( CONFIG_PAGING_LEVELS > 0 ) write_cr3((unsigned long)&cr3_target); - } } void __noreturn arch_crash_hard(void) diff --git a/arch/x86/pv/traps.c b/arch/x86/pv/traps.c index 1eef8d8..a318f69 100644 --- a/arch/x86/pv/traps.c +++ b/arch/x86/pv/traps.c @@ -122,118 +122,22 @@ void arch_init_traps(void) panic("Failed to set user %%cr3: %d\n", rc); #elif defined(__i386__) - if ( test_wants_user_mappings ) - { - /* - * XTF uses a shared user/kernel address space, and _PAGE_USER must be - * set to permit cpl3 access to the virtual addresses without taking a - * pagefault. - * - * PV guests and Xen share a virtual address space, and before Xen - * 4.7, Xen's setting of CR4.{SMEP,SMAP} leaked with 32bit PV guests. - * On hardware which supports SMEP/SMAP, older versions of Xen must be - * booted with 'smep=0 smap=0' for pv32pae tests to run. - */ - - /* - * First, probe whether Xen is leaking its SMEP/SMAP settings. - */ - intpte_t nl1e = pte_from_gfn(pfn_to_mfn(0), PF_SYM(AD, U, RW, P)); - bool leaked = false; - - /* Remap the page at 0 with _PAGE_USER. */ - rc = hypercall_update_va_mapping(NULL, nl1e, UVMF_INVLPG); - if ( rc ) - panic("Failed to remap page at NULL with _PAGE_USER: %d\n", rc); - - /* - * Write a `ret` instruction into the page at 0 (will be caught by - * leaked SMAP), then attempt to call at the `ret` instruction (will - * be caught by leaked SMEP). - */ - asm volatile ("1: movb $0xc3, (%[ptr]);" - "call *%[ptr];" - "jmp 3f;" - "2: ret;" - "3:" - _ASM_EXTABLE_HANDLER(1b, 3b, ex_pf_user) - _ASM_EXTABLE_HANDLER(0xfff, 2b, ex_pf_user) - : "+a" (leaked) - : [ptr] "r" (0xfff)); - - if ( leaked ) - panic("Xen's SMEP/SMAP settings leaked into guest context.\n" - "Must boot this Xen with 'smep=0 smap=0' to run this test.\n"); - - /* - * If we have got this far, SMEP/SMAP are not leaking into guest - * context. Proceed with remapping all mappings as _PAGE_USER. - */ - uint64_t *l3 = _p(start_info->pt_base); - unsigned long va = 0; - - while ( va < __HYPERVISOR_VIRT_START_PAE ) - { - unsigned int i3 = l3_table_offset(va); - - if ( !(l3[i3] & _PAGE_PRESENT) ) - { - va += 1UL << L3_PT_SHIFT; - continue; - } + /* Remap user areas with _PAGE_USER. */ + intpte_t nl1e = pte_from_virt(user_stack, PF_SYM(AD, U, RW, P)); - uint64_t *l2 = maddr_to_virt(pte_to_paddr(l3[i3])); - unsigned int i2 = l2_table_offset(va); + if ( hypercall_update_va_mapping(user_stack, nl1e, UVMF_INVLPG) ) + panic("Unable to remap user_stack with _PAGE_USER\n"); - if ( !(l2[i2] & _PAGE_PRESENT) ) - { - va += 1UL << L2_PT_SHIFT; - continue; - } - - uint64_t *l1 = maddr_to_virt(pte_to_paddr(l2[i2])); - unsigned int i1 = l1_table_offset(va); - - if ( !(l1[i1] & _PAGE_PRESENT) ) - { - va += 1UL << L1_PT_SHIFT; - continue; - } - - if ( !(l1[i1] & _PAGE_USER) ) - { - rc = hypercall_update_va_mapping(_p(va), l1[i1] | _PAGE_USER, - UVMF_INVLPG); - if ( rc ) - panic("update_va_mapping(%p, 0x%016"PRIx64") failed: %d\n", - _p(va), l1[i1] | _PAGE_USER, rc); - } - - va += 1UL << L1_PT_SHIFT; - } - } - else + extern const char __start_user_text[], __end_user_text[]; + unsigned long va = (unsigned long)__start_user_text; + while ( va < (unsigned long)__end_user_text ) { - /* - * If we haven't applied blanket PAGE_USER mappings, remap the - * structures which specifically want to be user. - */ - intpte_t nl1e = pte_from_virt(user_stack, PF_SYM(AD, U, RW, P)); - - if ( hypercall_update_va_mapping(user_stack, nl1e, UVMF_INVLPG) ) - panic("Unable to remap user_stack with _PAGE_USER\n"); - - extern const char __start_user_text[], __end_user_text[]; - unsigned long va = (unsigned long)__start_user_text; - while ( va < (unsigned long)__end_user_text ) - { - nl1e = pte_from_virt(_p(va), PF_SYM(AD, U, RW, P)); + nl1e = pte_from_virt(_p(va), PF_SYM(AD, U, RW, P)); - if ( hypercall_update_va_mapping(_p(va), nl1e, UVMF_INVLPG) ) - panic("Unable to remap user_text with _PAGE_USER\n"); + if ( hypercall_update_va_mapping(_p(va), nl1e, UVMF_INVLPG) ) + panic("Unable to remap user_text with _PAGE_USER\n"); - va += PAGE_SIZE; - } + va += PAGE_SIZE; } #endif diff --git a/arch/x86/setup.c b/arch/x86/setup.c index 45fef99..7c5973e 100644 --- a/arch/x86/setup.c +++ b/arch/x86/setup.c @@ -213,7 +213,6 @@ bool xtf_has_fep = false; * test_needs_* indicates options required by the test, without which the test * isn't worth running. */ -bool __weak test_wants_user_mappings = false; bool __weak test_needs_fep = false; void test_setup(void) diff --git a/docs/mainpage.dox b/docs/mainpage.dox index 491328e..e32053e 100644 --- a/docs/mainpage.dox +++ b/docs/mainpage.dox @@ -73,15 +73,6 @@ To run tests on a Xen host: (see @ref errata first) @section errata Errata -- Xen 4.6 and earlier running on hardware with SMEP (Intel IvyBridge/AMD - Excavator and later) or SMAP (Intel Broadwell/AMD Zen or later) leaked its - SMEP/SMAP settings into 32bit PV guests, which interferes with some tests. - Xen 4.7 and later is fixed not to leak its SMAP/SMEP settings. - - To run certain pv32pae tests against Xen 4.6 or earlier on such hardware, - Xen must be booted with `"smep=0 smap=0"`. Affected pv32pae tests will - probe for leaked settings and panic with a suitable error. - - For the paths of binaries, `xl` accepts either an absolute path, or certain relative paths (`/etc/xen/` or `$CWD` for `kernel=`, `$libdir/xen/boot` for `firmware_override=`). The default `xtfdir=` is configured correctly for diff --git a/include/xtf/test.h b/include/xtf/test.h index 1584e50..9e3dd29 100644 --- a/include/xtf/test.h +++ b/include/xtf/test.h @@ -24,20 +24,6 @@ extern const char test_title[]; */ extern bool xtf_has_fep; -/** - * Boolean indicating whether the test wants user mappings or not. - * - * Some tests want an easy transition between supervisor and user modes. For - * such tests, this requires running on _PAGE_USER mappings, and they must - * opt-in. - * - * @see @ref errata - * - * The framework variable is a weak reference, and may be overridden by a test - * wishing to change the default. - */ -extern bool test_wants_user_mappings; - /** * Boolean indicating whether the test is entirely predicated on the available * of the Force Emulation Prefix.