From 1498952b2417271ac4767cbcb550bf75eba24492 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Thu, 22 Mar 2018 11:50:50 +0000 Subject: [PATCH] Introduce and use __user_page_aligned_bss This avoids special casing user_stack[] as data, and allows the !test_wants_user_mappings remapping logic to become entirely generic. Signed-off-by: Andrew Cooper --- Doxyfile | 1 + arch/x86/hvm/traps.c | 19 ++++++++++++------- arch/x86/link.lds.S | 5 +++++ arch/x86/pv/traps.c | 43 ++++++++++++++++++++++++++---------------- arch/x86/setup.c | 2 +- include/xtf/compiler.h | 3 +++ 6 files changed, 49 insertions(+), 24 deletions(-) diff --git a/Doxyfile b/Doxyfile index 75f2b34..c5a53aa 100644 --- a/Doxyfile +++ b/Doxyfile @@ -2036,6 +2036,7 @@ PREDEFINED = __alias(x)= \ __noinline \ __noreturn \ __used \ + __user_page_aligned_bss \ __weak \ diff --git a/arch/x86/hvm/traps.c b/arch/x86/hvm/traps.c index 96374aa..ab095e7 100644 --- a/arch/x86/hvm/traps.c +++ b/arch/x86/hvm/traps.c @@ -95,6 +95,12 @@ int xtf_set_idte(unsigned int vector, struct xtf_idte *idte) return 0; } +static void remap_user(unsigned int start_gfn, unsigned int end_gfn) +{ + while ( start_gfn < end_gfn ) + l1_identmap[start_gfn++] |= _PAGE_USER; +} + void arch_init_traps(void) { setup_gate(X86_EXC_DE, &entry_DE, 0); @@ -131,15 +137,14 @@ void arch_init_traps(void) */ if ( !test_wants_user_mappings ) { - unsigned long gfn = virt_to_gfn(user_stack); - - 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_bss[], __end_user_bss[]; + + remap_user(virt_to_gfn(__start_user_text), + virt_to_gfn(__end_user_text)); - for ( gfn = virt_to_gfn(__start_user_text); gfn < end; ++gfn ) - l1_identmap[gfn] |= _PAGE_USER; + remap_user(virt_to_gfn(__start_user_bss), + virt_to_gfn(__end_user_bss)); write_cr3(_u(cr3_target)); } diff --git a/arch/x86/link.lds.S b/arch/x86/link.lds.S index db77d35..ca25a6c 100644 --- a/arch/x86/link.lds.S +++ b/arch/x86/link.lds.S @@ -72,6 +72,11 @@ SECTIONS . = ALIGN(PAGE_SIZE); *(.bss.page_aligned) . = ALIGN(PAGE_SIZE); + + __start_user_bss = .; + *(.bss.user.page_aligned) + . = ALIGN(PAGE_SIZE); + __end_user_bss = .; } _end = .; diff --git a/arch/x86/pv/traps.c b/arch/x86/pv/traps.c index bbc9377..4b484a6 100644 --- a/arch/x86/pv/traps.c +++ b/arch/x86/pv/traps.c @@ -87,6 +87,27 @@ static bool __maybe_unused ex_pf_user(struct cpu_regs *regs, return false; } +static int remap_linear(const void *linear, uint64_t flags) +{ + intpte_t nl1e = pte_from_virt(linear, flags); + + return hypercall_update_va_mapping(_u(linear), nl1e, UVMF_INVLPG); +} + +static int __maybe_unused remap_linear_range(const void *start, const void *end, + uint64_t flags) +{ + int ret = 0; + + while ( !ret && start < end ) + { + ret = remap_linear(start, flags); + start += PAGE_SIZE; + } + + return ret; +} + void arch_init_traps(void) { /* PV equivalent of `lidt`. */ @@ -96,8 +117,7 @@ void arch_init_traps(void) panic("Failed to set trap table: %d\n", rc); /* Register gdt[] with Xen. Need to map it read-only first. */ - if ( hypercall_update_va_mapping( - _u(gdt), pte_from_virt(gdt, PF_SYM(AD, P)), UVMF_INVLPG) ) + if ( remap_linear(gdt, PF_SYM(AD, P)) ) panic("Unable to remap gdt[] as read-only\n"); unsigned long gdt_frames[] = { @@ -234,23 +254,14 @@ void arch_init_traps(void) * 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(_u(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 linear = _u(__start_user_text); - - while ( linear < _u(__end_user_text) ) - { - nl1e = pte_from_virt(_p(linear), PF_SYM(AD, U, RW, P)); + extern const char __start_user_bss[], __end_user_bss[]; - if ( hypercall_update_va_mapping(linear, nl1e, UVMF_INVLPG) ) - panic("Unable to remap user_text with _PAGE_USER\n"); + remap_linear_range(__start_user_text, __end_user_text, + PF_SYM(AD, U, RW, P)); - linear += PAGE_SIZE; - } + remap_linear_range(__start_user_bss, __end_user_bss, + PF_SYM(AD, U, RW, P)); } #endif diff --git a/arch/x86/setup.c b/arch/x86/setup.c index 42e3c2b..3c84e96 100644 --- a/arch/x86/setup.c +++ b/arch/x86/setup.c @@ -19,7 +19,7 @@ * boot_stack[page 1] Top of work stack */ uint8_t boot_stack[3 * PAGE_SIZE] __page_aligned_bss; -uint8_t user_stack[PAGE_SIZE] __page_aligned_bss; +uint8_t user_stack[PAGE_SIZE] __user_page_aligned_bss; uint32_t x86_features[FSCAPINTS]; enum x86_vendor x86_vendor; diff --git a/include/xtf/compiler.h b/include/xtf/compiler.h index 2cc7d22..3324f47 100644 --- a/include/xtf/compiler.h +++ b/include/xtf/compiler.h @@ -34,6 +34,9 @@ #define __page_aligned_data __section(".data.page_aligned") __aligned(4096) #define __page_aligned_bss __section(".bss.page_aligned") __aligned(4096) +#define __user_page_aligned_bss \ + __section(".bss.user.page_aligned") __aligned(4096) + #endif /* XTF_COMPILER_H */ /* -- 2.39.5