x86/mm: allow for building without shadow mode support Considering the complexity of the code, it seems to be a reasonable thing to allow people to disable that code entirely even outside the immediate need for this by the next patch. Signed-off-by: Jan Beulich --- There is one XXX being added to the code - while it doesn't look like we need to set v->arch.paging.mode in shadow_vcpu_init(), it may be deemed more secure to set up a table with stub function pointers. --- a/xen/arch/x86/Rules.mk +++ b/xen/arch/x86/Rules.mk @@ -32,9 +32,13 @@ x86 := y x86_32 := n x86_64 := y +shadow-paging ?= y + CFLAGS += -mno-red-zone -mno-sse -fpic CFLAGS += -fno-asynchronous-unwind-tables # -fvisibility=hidden reduces -fpic cost, if it's available ifneq ($(call cc-option,$(CC),-fvisibility=hidden,n),n) CFLAGS += -DGCC_HAS_VISIBILITY_ATTRIBUTE endif + +CFLAGS-$(shadow-paging) += -DCONFIG_SHADOW_PAGING --- a/xen/arch/x86/mm/paging.c +++ b/xen/arch/x86/mm/paging.c @@ -635,16 +635,16 @@ int paging_domain_init(struct domain *d, * don't want to leak any active log-dirty bitmaps */ d->arch.paging.log_dirty.top = _mfn(INVALID_MFN); - /* The order of the *_init calls below is important, as the later - * ones may rewrite some common fields. Shadow pagetables are the - * default... */ - shadow_domain_init(d, domcr_flags); - - /* ... but we will use hardware assistance if it's available. */ + /* + * Shadow pagetables are the default, but we will use + * hardware assistance if it's available and enabled. + */ if ( hap_enabled(d) ) hap_domain_init(d); + else + rc = shadow_domain_init(d, domcr_flags); - return 0; + return rc; } /* vcpu paging struct initialization goes here */ @@ -822,12 +822,16 @@ int paging_enable(struct domain *d, u32 * and therefore its pagetables will soon be discarded */ void pagetable_dying(struct domain *d, paddr_t gpa) { +#ifdef CONFIG_SHADOW_PAGING struct vcpu *v; ASSERT(paging_mode_shadow(d)); v = d->vcpu[0]; v->arch.paging.mode->shadow.pagetable_dying(v, gpa); +#else + BUG(); +#endif } /* Print paging-assistance info to the console */ --- a/xen/arch/x86/mm/shadow/Makefile +++ b/xen/arch/x86/mm/shadow/Makefile @@ -1,4 +1,5 @@ -obj-$(x86_64) += common.o guest_2.o guest_3.o guest_4.o +obj-y := none.o +obj-$(shadow-paging) := common.o guest_2.o guest_3.o guest_4.o guest_%.o: multi.c Makefile $(CC) $(CFLAGS) -DGUEST_PAGING_LEVELS=$* -c $< -o $@ --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -43,7 +43,7 @@ DEFINE_PER_CPU(uint32_t,trace_shadow_pat /* Set up the shadow-specific parts of a domain struct at start of day. * Called for every domain from arch_domain_create() */ -void shadow_domain_init(struct domain *d, unsigned int domcr_flags) +int shadow_domain_init(struct domain *d, unsigned int domcr_flags) { INIT_PAGE_LIST_HEAD(&d->arch.paging.shadow.freelist); INIT_PAGE_LIST_HEAD(&d->arch.paging.shadow.pinned_shadows); @@ -57,6 +57,8 @@ void shadow_domain_init(struct domain *d d->arch.paging.shadow.oos_off = (domcr_flags & DOMCRF_oos_off) ? 1 : 0; #endif d->arch.paging.shadow.pagetable_dying_op = 0; + + return 0; } /* Setup the shadow-specfic parts of a vcpu struct. Note: The most important --- /dev/null +++ b/xen/arch/x86/mm/shadow/none.c 2015-01-26 17:23:04.000000000 +0100 @@ -0,0 +1,70 @@ +#include +#include + +static int _enable_log_dirty(struct domain *d, bool_t log_global) +{ + BUG_ON(!is_pv_domain(d)); + return -EOPNOTSUPP; +} + +static int _disable_log_dirty(struct domain *d) +{ + BUG_ON(!is_pv_domain(d)); + return -EOPNOTSUPP; +} + +static void _clean_dirty_bitmap(struct domain *d) +{ + BUG_ON(!is_pv_domain(d)); +} + +int shadow_domain_init(struct domain *d, unsigned int domcr_flags) +{ + paging_log_dirty_init(d, _enable_log_dirty, + _disable_log_dirty, _clean_dirty_bitmap); + return is_pv_domain(d) ? 0 : -EOPNOTSUPP; +} + +void shadow_vcpu_init(struct vcpu *v) +{ + BUG_ON(!is_pv_domain(v->domain)); + /* XXX v->arch.paging.mode = ???; */ +} + +void shadow_teardown(struct domain *d) +{ + BUG_ON(!is_pv_domain(d)); +} + +void shadow_final_teardown(struct domain *d) +{ + BUG_ON(!is_pv_domain(d)); +} + +int shadow_enable(struct domain *d, u32 mode) +{ + BUG_ON(!is_pv_domain(d)); + return -EOPNOTSUPP; +} + +void sh_remove_shadows(struct vcpu *v, mfn_t gmfn, int fast, int all) +{ +} + +void shadow_blow_tables_per_domain(struct domain *d) +{ +} + +int shadow_track_dirty_vram(struct domain *d, + unsigned long begin_pfn, unsigned long nr, + XEN_GUEST_HANDLE_64(uint8) dirty_bitmap) +{ + BUG(); + return -EOPNOTSUPP; +} + +int shadow_domctl(struct domain *d, xen_domctl_shadow_op_t *sc, + XEN_GUEST_HANDLE_PARAM(void) u_domctl) +{ + return -EINVAL; +} --- a/xen/include/asm-x86/domain.h +++ b/xen/include/asm-x86/domain.h @@ -88,6 +88,7 @@ void hypercall_page_initialise(struct do /* shadow paging extension */ /************************************************/ struct shadow_domain { +#ifdef CONFIG_SHADOW_PAGING unsigned int opt_flags; /* runtime tunable optimizations on/off */ struct page_list_head pinned_shadows; @@ -117,9 +118,11 @@ struct shadow_domain { /* Has this domain ever used HVMOP_pagetable_dying? */ bool_t pagetable_dying_op; +#endif }; struct shadow_vcpu { +#ifdef CONFIG_SHADOW_PAGING /* PAE guests: per-vcpu shadow top-level table */ l3_pgentry_t l3table[4] __attribute__((__aligned__(32))); /* PAE guests: per-vcpu cache of the top-level *guest* entries */ @@ -145,6 +148,7 @@ struct shadow_vcpu { } oos_fixup[SHADOW_OOS_PAGES]; bool_t pagetable_dying; +#endif }; /************************************************/ --- a/xen/include/asm-x86/paging.h +++ b/xen/include/asm-x86/paging.h @@ -55,7 +55,11 @@ #define PG_external (XEN_DOMCTL_SHADOW_ENABLE_EXTERNAL << PG_mode_shift) #define paging_mode_enabled(_d) ((_d)->arch.paging.mode) +#ifdef CONFIG_SHADOW_PAGING #define paging_mode_shadow(_d) ((_d)->arch.paging.mode & PG_SH_enable) +#else +#define paging_mode_shadow(_d) ((void)(_d), 0) +#endif #define paging_mode_hap(_d) ((_d)->arch.paging.mode & PG_HAP_enable) #define paging_mode_refcounts(_d) ((_d)->arch.paging.mode & PG_refcounts) @@ -74,6 +78,7 @@ struct sh_emulate_ctxt; struct shadow_paging_mode { +#ifdef CONFIG_SHADOW_PAGING void (*detach_old_tables )(struct vcpu *v); int (*x86_emulate_write )(struct vcpu *v, unsigned long va, void *src, u32 bytes, @@ -88,6 +93,7 @@ struct shadow_paging_mode { int (*guess_wrmap )(struct vcpu *v, unsigned long vaddr, mfn_t gmfn); void (*pagetable_dying )(struct vcpu *v, paddr_t gpa); +#endif /* For outsiders to tell what mode we're in */ unsigned int shadow_levels; }; --- a/xen/include/asm-x86/shadow.h +++ b/xen/include/asm-x86/shadow.h @@ -49,7 +49,7 @@ /* Set up the shadow-specific parts of a domain struct at start of day. * Called from paging_domain_init(). */ -void shadow_domain_init(struct domain *d, unsigned int domcr_flags); +int shadow_domain_init(struct domain *d, unsigned int domcr_flags); /* Setup the shadow-specific parts of a vcpu struct. It is called by * paging_vcpu_init() in paging.c */ --- a/xen/include/xen/paging.h +++ b/xen/include/xen/paging.h @@ -7,7 +7,7 @@ #include #include -#elif defined CONFIG_SHADOW +#elif defined CONFIG_SHADOW_PAGING #include