mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
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 <jbeulich@suse.com> Reviewed-by: Tim Deegan <tim@xen.org> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
This commit is contained in:
1 parent
4b3a4238d6
commit
8f1ddea9f0
10 files changed
+146
-15
No files matched your search
@@ -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
|
||||
@@ -129,8 +129,10 @@ struct vcpu *__init alloc_dom0_vcpu0(struct domain *dom0)
|
||||
return alloc_vcpu(dom0, 0, 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SHADOW_PAGING
|
||||
static bool_t __initdata opt_dom0_shadow;
|
||||
boolean_param("dom0_shadow", opt_dom0_shadow);
|
||||
#endif
|
||||
|
||||
static char __initdata opt_dom0_ioports_disable[200] = "";
|
||||
string_param("dom0_ioports_disable", opt_dom0_ioports_disable);
|
||||
@@ -1418,6 +1420,7 @@ int __init construct_dom0(
|
||||
regs->esi = vstartinfo_start;
|
||||
regs->eflags = X86_EFLAGS_IF;
|
||||
|
||||
#ifdef CONFIG_SHADOW_PAGING
|
||||
if ( opt_dom0_shadow )
|
||||
{
|
||||
if ( is_pvh_domain(d) )
|
||||
@@ -1428,6 +1431,7 @@ int __init construct_dom0(
|
||||
if ( paging_enable(d, PG_SH_enable) == 0 )
|
||||
paging_update_paging_modes(v);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* PVH Fixme: XENFEAT_supervisor_mode_kernel has been reused in PVH with a
|
||||
|
||||
@@ -635,16 +635,16 @@ int paging_domain_init(struct domain *d, unsigned int domcr_flags)
|
||||
* 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 mode)
|
||||
* 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 */
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
obj-$(x86_64) += common.o guest_2.o guest_3.o guest_4.o
|
||||
ifeq ($(shadow-paging),y)
|
||||
obj-y += common.o guest_2.o guest_3.o guest_4.o
|
||||
else
|
||||
obj-y += none.o
|
||||
endif
|
||||
|
||||
guest_%.o: multi.c Makefile
|
||||
$(CC) $(CFLAGS) -DGUEST_PAGING_LEVELS=$* -c $< -o $@
|
||||
@@ -47,7 +47,7 @@ static void sh_clean_dirty_bitmap(struct domain *);
|
||||
|
||||
/* 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);
|
||||
@@ -61,6 +61,8 @@ void shadow_domain_init(struct domain *d, unsigned int domcr_flags)
|
||||
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
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
#include <xen/mm.h>
|
||||
#include <asm/shadow.h>
|
||||
|
||||
static int _enable_log_dirty(struct domain *d, bool_t log_global)
|
||||
{
|
||||
ASSERT(is_pv_domain(d));
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int _disable_log_dirty(struct domain *d)
|
||||
{
|
||||
ASSERT(is_pv_domain(d));
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static void _clean_dirty_bitmap(struct domain *d)
|
||||
{
|
||||
ASSERT(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;
|
||||
}
|
||||
|
||||
static int _page_fault(struct vcpu *v, unsigned long va,
|
||||
struct cpu_user_regs *regs)
|
||||
{
|
||||
ASSERT_UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _invlpg(struct vcpu *v, unsigned long va)
|
||||
{
|
||||
ASSERT_UNREACHABLE();
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static unsigned long _gva_to_gfn(struct vcpu *v, struct p2m_domain *p2m,
|
||||
unsigned long va, uint32_t *pfec)
|
||||
{
|
||||
ASSERT_UNREACHABLE();
|
||||
return INVALID_GFN;
|
||||
}
|
||||
|
||||
static void _update_cr3(struct vcpu *v, int do_locking)
|
||||
{
|
||||
ASSERT_UNREACHABLE();
|
||||
}
|
||||
|
||||
static void _update_paging_modes(struct vcpu *v)
|
||||
{
|
||||
ASSERT_UNREACHABLE();
|
||||
}
|
||||
|
||||
static void _write_p2m_entry(struct domain *d, unsigned long gfn,
|
||||
l1_pgentry_t *p, l1_pgentry_t new,
|
||||
unsigned int level)
|
||||
{
|
||||
ASSERT_UNREACHABLE();
|
||||
}
|
||||
|
||||
static const struct paging_mode sh_paging_none = {
|
||||
.page_fault = _page_fault,
|
||||
.invlpg = _invlpg,
|
||||
.gva_to_gfn = _gva_to_gfn,
|
||||
.update_cr3 = _update_cr3,
|
||||
.update_paging_modes = _update_paging_modes,
|
||||
.write_p2m_entry = _write_p2m_entry,
|
||||
};
|
||||
|
||||
void shadow_vcpu_init(struct vcpu *v)
|
||||
{
|
||||
ASSERT(is_pv_domain(v->domain));
|
||||
v->arch.paging.mode = &sh_paging_none;
|
||||
}
|
||||
@@ -88,6 +88,7 @@ void hypercall_page_initialise(struct domain *d, void *);
|
||||
/* 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
|
||||
};
|
||||
|
||||
/************************************************/
|
||||
|
||||
@@ -39,7 +39,11 @@
|
||||
#define PG_SH_shift 20
|
||||
#define PG_HAP_shift 21
|
||||
/* We're in one of the shadow modes */
|
||||
#ifdef CONFIG_SHADOW_PAGING
|
||||
#define PG_SH_enable (1U << PG_SH_shift)
|
||||
#else
|
||||
#define PG_SH_enable 0
|
||||
#endif
|
||||
#define PG_HAP_enable (1U << PG_HAP_shift)
|
||||
|
||||
/* common paging mode bits */
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -49,12 +49,14 @@
|
||||
|
||||
/* 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 */
|
||||
void shadow_vcpu_init(struct vcpu *v);
|
||||
|
||||
#ifdef CONFIG_SHADOW_PAGING
|
||||
|
||||
/* Enable an arbitrary shadow mode. Call once at domain creation. */
|
||||
int shadow_enable(struct domain *d, u32 mode);
|
||||
|
||||
@@ -77,17 +79,40 @@ void shadow_teardown(struct domain *d);
|
||||
/* Call once all of the references to the domain have gone away */
|
||||
void shadow_final_teardown(struct domain *d);
|
||||
|
||||
/* Remove all shadows of the guest mfn. */
|
||||
void sh_remove_shadows(struct vcpu *v, mfn_t gmfn, int fast, int all);
|
||||
|
||||
/* Discard _all_ mappings from the domain's shadows. */
|
||||
void shadow_blow_tables_per_domain(struct domain *d);
|
||||
|
||||
#else /* !CONFIG_SHADOW_PAGING */
|
||||
|
||||
#define shadow_teardown(d) ASSERT(is_pv_domain(d))
|
||||
#define shadow_final_teardown(d) ASSERT(is_pv_domain(d))
|
||||
#define shadow_enable(d, mode) \
|
||||
({ ASSERT(is_pv_domain(d)); -EOPNOTSUPP; })
|
||||
#define shadow_track_dirty_vram(d, begin_pfn, nr, bitmap) \
|
||||
({ ASSERT_UNREACHABLE(); -EOPNOTSUPP; })
|
||||
|
||||
static inline void sh_remove_shadows(struct vcpu *v, mfn_t gmfn,
|
||||
bool_t fast, bool_t all) {}
|
||||
|
||||
static inline void shadow_blow_tables_per_domain(struct domain *d) {}
|
||||
|
||||
static inline int shadow_domctl(struct domain *d, xen_domctl_shadow_op_t *sc,
|
||||
XEN_GUEST_HANDLE_PARAM(void) u_domctl)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SHADOW_PAGING */
|
||||
|
||||
/* Remove all shadows of the guest mfn. */
|
||||
static inline void shadow_remove_all_shadows(struct vcpu *v, mfn_t gmfn)
|
||||
{
|
||||
/* See the comment about locking in sh_remove_shadows */
|
||||
sh_remove_shadows(v, gmfn, 0 /* Be thorough */, 1 /* Must succeed */);
|
||||
}
|
||||
|
||||
/* Discard _all_ mappings from the domain's shadows. */
|
||||
void shadow_blow_tables_per_domain(struct domain *d);
|
||||
|
||||
#endif /* _XEN_SHADOW_H */
|
||||
|
||||
/*
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <asm/paging.h>
|
||||
#include <asm/p2m.h>
|
||||
|
||||
#elif defined CONFIG_SHADOW
|
||||
#elif defined CONFIG_SHADOW_PAGING
|
||||
|
||||
#include <asm/shadow.h>
|
||||
|
||||
|
||||