mm/p2m cleanups
PATCH 1/1 mm/p2m cleanups
This patch series fixes up the p2m and other x86/mm interfaces, and in particular sorts out a lot of the locking discipline.
Cheers,
Tim.
Signature · 3 lines
Tim Deegan <[email protected]> Principal Software Engineer, Xen Platform Team Citrix Systems UK Ltd. (Company #02937203, SL9 0BG)
PATCH 1/1 x86/mm/p2m: Mark internal functions static
# HG changeset patch
# User Tim Deegan <[email protected]> # Date 1307017011 -3600
# Node ID c7d0b66e41cde0cca1d9162b92b41fc6bd30cf20 # Parent 221f431092c04df90ed017f7471ce9641356d40d x86/mm/p2m: Mark internal functions static
xen/arch/x86/mm/p2m-ept.c +1 -1
@@ -164,7 +164,7 @@ static int ept_set_middle_entry(struct p }/* free ept sub tree behind an entry */ -void ept_free_entry (struct p2m_domain *p2m,ept_entry_t *ept_entry,int level) +static void ept_free_entry (struct p2m_domain *p2m,ept_entry_t *ept_entry,int level) {/* End if the entry is a leaf entry. */ if ( level == 0 || !is_epte_present(ept_entry) ||
xen/arch/x86/mm/p2m-pt.c +5 -36
66 lines not on this page · raw message
xen/arch/x86/mm/p2m.c +30 -0
@@ -161,6 +161,36 @@ int set_p2m_entry(struct p2m_domain *p2mreturn rc; } +struct page_info *p2m_alloc_ptp (struct p2m_domain *p2m,unsigned long type) +{ +struct page_info *pg; + +ASSERT (p2m); +ASSERT (p2m->domain); +ASSERT (p2m->domain->arch.paging.alloc_page); + pg = p2m->domain->arch.paging.alloc_page (p2m->domain); +if (pg ==NULL ) +return NULL ; + +page_list_add_tail (pg, &p2m->pages); + pg->u.inuse.type_info = type |1 | PGT_validated; + +return pg; +} + +void p2m_free_ptp (struct p2m_domain *p2m,struct page_info *pg) +{ +ASSERT (pg); +ASSERT (p2m); +ASSERT (p2m->domain); +ASSERT (p2m->domain->arch.paging.free_page); + +page_list_del (pg, &p2m->pages); + p2m->domain->arch.paging.free_page (p2m->domain, pg); + +return ; +} +// Allocate a new p2m table for a domain. // // The structure of the p2m table is that of a pagetable for xen (i.e. it is
xen/include/asm-x86/p2m.h +0 -11
@@ -499,21 +499,11 @@ static inline unsigned long mfn_to_gfn(s/* Init the datastructures for later use by the p2m code */ int p2m_init (struct domain *d); -/* PTE flags for various types of p2m entry */ -unsigned long p2m_type_to_flags (p2m_type_t t,mfn_t mfn); -/* Allocate a new p2m table for a domain. * * Returns 0 for success or -errno. */ int p2m_alloc_table (struct p2m_domain *p2m); -/* Find the next level's P2M entry, checking for out-of-range gfn's... -* Returns NULL on error. -*/ -l1_pgentry_t * -p2m_find_entry (void *table,unsigned long *gfn_remainder, -unsigned long gfn,uint32_t shift,uint32_t max); -/* Return all the p2m resources to Xen. */ void p2m_teardown (struct p2m_domain *p2m);void p2m_final_teardown (struct domain *d);
@@ -584,7 +574,6 @@ static inline void guest_physmap_remove_ }/* Change types across all p2m entries in a domain */ -void p2m_change_type_global (struct p2m_domain *p2m,p2m_type_t ot,p2m_type_t nt);void p2m_change_entry_type_global (struct p2m_domain *p2m,p2m_type_t ot,p2m_type_t nt);/* Compare-exchange the type of a single p2m entry */
PATCH 1/1 x86/mm/p2m: little fixes and tidying up
In reply to Tim Deegan# HG changeset patch
# User Tim Deegan <[email protected]> # Date 1307017012 -3600
# Node ID 9344034d624b2e3cd6b0025ab2051cb89bd7e04a # Parent c7d0b66e41cde0cca1d9162b92b41fc6bd30cf20 x86/mm/p2m: little fixes and tidying up
xen/arch/x86/mm/p2m-pod.c +5 -8
@@ -42,7 +42,6 @@#undef page_to_mfn#define page_to_mfn (_pg) _mfn(__page_to_mfn(_pg)) -#define SUPERPAGE_PAGES (1UL << 9)#define superpage_aligned (_x) (((_x)&(SUPERPAGE_PAGES-1))==0)/*
@@ -688,8 +687,7 @@ p2m_pod_zero_check_superpage(struct p2m_ }/* Try to remove the page, restoring old mapping if it fails. */ -set_p2m_entry (p2m, gfn, -_mfn (POPULATE_ON_DEMAND_MFN ),9 , +set_p2m_entry (p2m, gfn,_mfn (0 ),9 , p2m_populate_on_demand, p2m->default_access);/* Make none of the MFNs are used elsewhere... for example, mapped
@@ -801,8 +799,7 @@ p2m_pod_zero_check(struct p2m_domain *p2 }/* Try to remove the page, restoring old mapping if it fails. */ -set_p2m_entry (p2m, gfns[i], -_mfn (POPULATE_ON_DEMAND_MFN ),0 , +set_p2m_entry (p2m, gfns[i],_mfn (0 ),0 , p2m_populate_on_demand, p2m->default_access);/* See if the page was successfully unmapped. (Allow one refcount
@@ -966,7 +963,7 @@ p2m_pod_demand_populate(struct p2m_domai* set_p2m_entry() should automatically shatter the 1GB page into * 512 2MB pages. The rest of 511 calls are unnecessary. */ -set_p2m_entry (p2m, gfn_aligned,_mfn (POPULATE_ON_DEMAND_MFN ),9 , +set_p2m_entry (p2m, gfn_aligned,_mfn (0 ),9 , p2m_populate_on_demand, p2m->default_access);audit_p2m (p2m,1 );p2m_unlock (p2m);
@@ -1054,7 +1051,7 @@ remap_and_retry:/* Remap this 2-meg region in singleton chunks */ gfn_aligned = (gfn>>order)<<order;for (i=0 ; i<(1 <<order); i++) -set_p2m_entry (p2m, gfn_aligned+i,_mfn (POPULATE_ON_DEMAND_MFN ),0 , +set_p2m_entry (p2m, gfn_aligned+i,_mfn (0 ),0 , p2m_populate_on_demand, p2m->default_access);if ( tb_init_done ) {
@@ -1114,7 +1111,7 @@ guest_physmap_mark_populate_on_demand(st }/* Now, actually do the two-way mapping */ -if ( !set_p2m_entry (p2m, gfn,_mfn (POPULATE_ON_DEMAND_MFN ), order, +if ( !set_p2m_entry (p2m, gfn,_mfn (0 ), order, p2m_populate_on_demand, p2m->default_access) ) rc = -EINVAL ;else
xen/arch/x86/mm/p2m-pt.c +12 -16
@@ -51,9 +51,6 @@#define P2M_BASE_FLAGS \ (_PAGE_PRESENT | _PAGE_USER | _PAGE_DIRTY | _PAGE_ACCESSED) -#define SUPERPAGE_PAGES (1UL << 9) -#define superpage_aligned (_x) (((_x)&(SUPERPAGE_PAGES-1))==0) -static unsigned long p2m_type_to_flags (p2m_type_t t,mfn_t mfn) {unsigned long flags;
@@ -67,32 +64,31 @@ static unsigned long p2m_type_to_flags(p#else flags = (t &0x7UL ) <<9 ;#endif -#ifndef HAVE_GRANT_MAP_P2M -BUG_ON (p2m_is_grant (t)); + +#ifndef __x86_64__ +/* 32-bit builds don't support a lot of the p2m types */ +BUG_ON (t > p2m_populate_on_demand);#endif +switch (t) {case p2m_invalid: +case p2m_mmio_dm: +case p2m_populate_on_demand:default :return flags; +case p2m_ram_ro: +case p2m_grant_map_ro: +case p2m_ram_logdirty: +case p2m_ram_shared: +return flags |P2M_BASE_FLAGS ;case p2m_ram_rw:case p2m_grant_map_rw:return flags |P2M_BASE_FLAGS | _PAGE_RW; -case p2m_ram_logdirty: -return flags |P2M_BASE_FLAGS ; -case p2m_ram_ro: -case p2m_grant_map_ro: -return flags |P2M_BASE_FLAGS ; -case p2m_ram_shared: -return flags |P2M_BASE_FLAGS ; -case p2m_mmio_dm: -return flags;case p2m_mmio_direct:if ( !rangeset_contains_singleton (mmio_ro_ranges,mfn_x (mfn)) ) flags |= _PAGE_RW;return flags |P2M_BASE_FLAGS | _PAGE_PCD; -case p2m_populate_on_demand: -return flags; } }
xen/arch/x86/mm/p2m.c +27 -26
72 lines not on this page · raw message
xen/include/asm-x86/p2m.h +90 -84
235 lines not on this page · raw message
xen/include/asm-x86/x86_32/page.h +1 -0
@@ -15,6 +15,7 @@#define L3_PAGETABLE_ENTRIES 4#define ROOT_PAGETABLE_ENTRIES L3_PAGETABLE_ENTRIES#define SUPERPAGE_ORDER PAGETABLE_ORDER +#define SUPERPAGE_PAGES (1<<SUPERPAGE_ORDER)/* * Architecturally, physical addresses may be up to 52 bits. However, the
xen/include/asm-x86/x86_64/page.h +1 -0
@@ -17,6 +17,7 @@#define L4_PAGETABLE_ENTRIES (1<<PAGETABLE_ORDER)#define ROOT_PAGETABLE_ENTRIES L4_PAGETABLE_ENTRIES#define SUPERPAGE_ORDER PAGETABLE_ORDER +#define SUPERPAGE_PAGES (1<<SUPERPAGE_ORDER)#define __PAGE_OFFSET DIRECTMAP_VIRT_START#define __XEN_VIRT_START XEN_VIRT_START
PATCH 1/1 x86/mm/p2m: hide the current-domain fast-path inside the p2m-pt code
In reply to Tim Deegan# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1307017012 -3600
# Node ID a7d8612c9ba14ae6efbf420e213c983902433942
# Parent 9344034d624b2e3cd6b0025ab2051cb89bd7e04a x86/mm/p2m: hide the current-domain fast-path inside the p2m-pt code.
The other implementations of the p2m interface don't have this, and it will go away entirely when 32-bit builds go away, so take it out of the interface.
xen/arch/x86/hvm/hvm.c +1 -1
@@ -1212,7 +1212,7 @@ int hvm_hap_nested_page_fault(unsigned l } p2m =p2m_get_hostp2m (v->domain); - mfn =gfn_to_mfn_type_current (p2m, gfn, &p2mt, &p2ma, p2m_guest); + mfn =gfn_to_mfn_type_p2m (p2m, gfn, &p2mt, &p2ma, p2m_guest);/* Check access permissions first, then handle faults */ if ( access_valid && (mfn_x (mfn) !=INVALID_MFN ) )
xen/arch/x86/mm/p2m-ept.c +0 -8
@@ -692,13 +692,6 @@ out:return ; } -static mfn_t ept_get_entry_current (struct p2m_domain *p2m, -unsigned long gfn,p2m_type_t *t,p2m_access_t *a, -p2m_query_t q) -{ -return ept_get_entry (p2m, gfn, t, a, q); -} -/* * To test if the new emt type is the same with old, * return 1 to not to reset ept entry.
@@ -824,7 +817,6 @@ void ept_p2m_init(struct p2m_domain *p2m { p2m->set_entry = ept_set_entry; p2m->get_entry = ept_get_entry; - p2m->get_entry_current = ept_get_entry_current; p2m->change_entry_type_global = ept_change_entry_type_global; }
xen/arch/x86/mm/p2m-pt.c +178 -180
382 lines not on this page · raw message
xen/arch/x86/mm/p2m.c +0 -2
@@ -101,7 +101,6 @@ p2m_init_nestedp2m(struct domain *d)if (p2m ==NULL )return -ENOMEM ;p2m_initialise (d, p2m); - p2m->get_entry_current = p2m->get_entry; p2m->write_p2m_entry = nestedp2m_write_p2m_entry; }
@@ -956,7 +955,6 @@ p2m_flush_locked(struct p2m_domain *p2m)p2m_teardown (p2m);p2m_initialise (p2m->domain, p2m); - p2m->get_entry_current = p2m->get_entry; p2m->write_p2m_entry = nestedp2m_write_p2m_entry;return p2m_alloc_table (p2m); }
xen/include/asm-x86/p2m.h +21 -38
83 lines not on this page · raw message
PATCH 1/1 x86/mm/p2m: merge gfn_to_mfn_unshare with other gfn_to_mfn paths
In reply to Tim Deegan# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1307017012 -3600
# Node ID 0d3e0a571fdddc873d1ff3750d15db6fc58fff8e
# Parent a7d8612c9ba14ae6efbf420e213c983902433942 x86/mm/p2m: merge gfn_to_mfn_unshare with other gfn_to_mfn paths.
gfn_to_mfn_unshare() had its own function despite all other lookup types being handled in one place. Merge it into _gfn_to_mfn_type(), so that it gets the benefit of broken-page protection, for example, and tidy its interfaces up to fit.
The unsharing code still has a lot of bugs, e.g.
- failure to alloc for unshare on a foreign lookup still BUG()s,
- at least one race condition in unshare-and-retry
- p2m_* lookup types should probably be flags, not enum
but it's cleaner and will make later p2m cleanups easier.
xen/arch/x86/hvm/emulate.c +1 -1
@@ -63,7 +63,7 @@ static int hvmemul_do_io(int rc;/* Check for paged out page */ - ram_mfn =gfn_to_mfn_unshare (p2m, ram_gfn, &p2mt,0 ); + ram_mfn =gfn_to_mfn_unshare (p2m, ram_gfn, &p2mt);if (p2m_is_paging (p2mt) ) {p2m_mem_paging_populate (p2m, ram_gfn);
xen/arch/x86/hvm/hvm.c +6 -6
@@ -352,7 +352,7 @@ static int hvm_set_ioreq_page(unsigned long mfn;void *va; - mfn =mfn_x (gfn_to_mfn_unshare (p2m, gmfn, &p2mt,0 )); + mfn =mfn_x (gfn_to_mfn_unshare (p2m, gmfn, &p2mt));if ( !p2m_is_ram (p2mt) )return -EINVAL ;if (p2m_is_paging (p2mt) )
@@ -1767,7 +1767,7 @@ static void *__hvm_map_guest_frame(unsigstruct p2m_domain *p2m =p2m_get_hostp2m (current->domain); mfn =mfn_x (writable - ?gfn_to_mfn_unshare (p2m, gfn, &p2mt,0 ) + ?gfn_to_mfn_unshare (p2m, gfn, &p2mt) :gfn_to_mfn (p2m, gfn, &p2mt));if ( (p2m_is_shared (p2mt) && writable) || !p2m_is_ram (p2mt) )return NULL ;
@@ -2229,7 +2229,7 @@ static enum hvm_copy_result __hvm_copy( gfn = addr >>PAGE_SHIFT ; } - mfn =mfn_x (gfn_to_mfn_unshare (p2m, gfn, &p2mt,0 )); + mfn =mfn_x (gfn_to_mfn_unshare (p2m, gfn, &p2mt));if (p2m_is_paging (p2mt) ) {
@@ -3724,7 +3724,7 @@ long do_hvm_op(unsigned long op, XEN_GUE rc = -EINVAL ;if (is_hvm_domain (d) ) { -gfn_to_mfn_unshare (p2m_get_hostp2m (d), a.pfn, &t,0 ); +gfn_to_mfn_unshare (p2m_get_hostp2m (d), a.pfn, &t);if (p2m_is_mmio (t) ) a.mem_type = HVMMEM_mmio_dm;else if (p2m_is_readonly (t) )
@@ -3779,7 +3779,7 @@ long do_hvm_op(unsigned long op, XEN_GUEp2m_type_t t;p2m_type_t nt;mfn_t mfn; - mfn =gfn_to_mfn_unshare (p2m, pfn, &t,0 ); + mfn =gfn_to_mfn_unshare (p2m, pfn, &t);if (p2m_is_paging (t) ) {p2m_mem_paging_populate (p2m, pfn);
@@ -3877,7 +3877,7 @@ long do_hvm_op(unsigned long op, XEN_GUEmfn_t mfn;int success; - mfn =gfn_to_mfn_unshare (p2m, pfn, &t,0 ); + mfn =gfn_to_mfn_unshare (p2m, pfn, &t);p2m_lock (p2m); success = p2m->set_entry (p2m, pfn, mfn,0 , t, memaccess[a.hvmmem_access]);
xen/arch/x86/mm.c +1 -1
@@ -4653,7 +4653,7 @@ long arch_memory_op(int op, XEN_GUEST_HAp2m_type_t p2mt; xatp.idx =mfn_x (gfn_to_mfn_unshare (p2m_get_hostp2m (d), - xatp.idx, &p2mt,0 )); + xatp.idx, &p2mt));/* If the page is still shared, exit early */ if (p2m_is_shared (p2mt) ) {
xen/arch/x86/mm/guest_walk.c +1 -1
@@ -93,7 +93,7 @@ static inline void *map_domain_gfn(struc uint32_t *rc) {/* Translate the gfn, unsharing if shared */ - *mfn =gfn_to_mfn_unshare (p2m,gfn_x (gfn), p2mt,0 ); + *mfn =gfn_to_mfn_unshare (p2m,gfn_x (gfn), p2mt);if (p2m_is_paging (*p2mt) ) {p2m_mem_paging_populate (p2m,gfn_x (gfn));
xen/arch/x86/mm/hap/guest_walk.c +2 -2
@@ -57,7 +57,7 @@ unsigned long hap_p2m_ga_to_gfn(GUEST_PAwalk_t gw;/* Get the top-level table's MFN */ - top_mfn =gfn_to_mfn_unshare (p2m, cr3 >>PAGE_SHIFT , &p2mt,0 ); + top_mfn =gfn_to_mfn_unshare (p2m, cr3 >>PAGE_SHIFT , &p2mt);if (p2m_is_paging (p2mt) ) {p2m_mem_paging_populate (p2m, cr3 >>PAGE_SHIFT );
@@ -89,7 +89,7 @@ unsigned long hap_p2m_ga_to_gfn(GUEST_PAif ( missing ==0 ) {gfn_t gfn =guest_l1e_get_gfn (gw.l1e); -gfn_to_mfn_unshare (p2m,gfn_x (gfn), &p2mt,0 ); +gfn_to_mfn_unshare (p2m,gfn_x (gfn), &p2mt);if (p2m_is_paging (p2mt) ) {p2m_mem_paging_populate (p2m,gfn_x (gfn));
xen/arch/x86/mm/mem_sharing.c +14 -17
@@ -294,8 +294,7 @@ static void mem_sharing_audit(void)static struct page_info *mem_sharing_alloc_page (struct domain *d, -unsigned long gfn, -int must_succeed) +unsigned long gfn) {struct page_info * page;struct vcpu *v = current;
@@ -307,21 +306,20 @@ static struct page_info* mem_sharing_allmemset (&req,0 ,sizeof (req)); req.type =MEM_EVENT_TYPE_SHARED ; -if (must_succeed) +if ( v->domain != d ) { -/* We do not support 'must_succeed' any more. External operations such -* as grant table mappings may fail with OOM condition! -*/ -BUG (); +/* XXX This path needs some attention. For now, just fail foreign +* XXX requests to unshare if there's no memory. This replaces +* XXX old code that BUG()ed here; the callers now BUG() +* XXX elewhere. */ +gdprintk (XENLOG_ERR , +"Failed alloc on unshare path for foreign (%d) lookup\n" , + d->domain_id); +return page; } -else - { -/* All foreign attempts to unshare pages should be handled through -* 'must_succeed' case. */ -ASSERT (v->domain->domain_id == d->domain_id); -vcpu_pause_nosync (v); - req.flags |=MEM_EVENT_FLAG_VCPU_PAUSED ; - } + +vcpu_pause_nosync (v); + req.flags |=MEM_EVENT_FLAG_VCPU_PAUSED ;/* XXX: Need to reserve a request, not just check the ring! */ if (mem_event_check_ring (d))return page;
@@ -692,8 +690,7 @@ gfn_found:if (ret ==0 ) goto private_page_found; old_page = page; - page =mem_sharing_alloc_page (d, gfn, flags &MEM_SHARING_MUST_SUCCEED ); -BUG_ON (!page && (flags &MEM_SHARING_MUST_SUCCEED )); + page =mem_sharing_alloc_page (d, gfn);if (!page) {/* We've failed to obtain memory for private page. Need to re-add the
xen/common/grant_table.c +8 -2
@@ -110,7 +110,8 @@ static unsigned inline int max_nr_maptra#define gfn_to_mfn_private (_d, _gfn) ({ \ p2m_type_t __p2mt; \ unsigned long __x; \ - __x = mfn_x(gfn_to_mfn_unshare(p2m_get_hostp2m(_d), _gfn, &__p2mt, 1)); \ + __x = mfn_x(gfn_to_mfn_unshare(p2m_get_hostp2m(_d), _gfn, &__p2mt)); \ + BUG_ON(p2m_is_shared(__p2mt));/* XXX fixme */ \if ( !p2m_is_valid (__p2mt) ) \ __x =INVALID_MFN ; \ __x; })
@@ -153,7 +154,12 @@ static int __get_paged_frame(unsigned loif ( readonly ) mfn =gfn_to_mfn (p2m, gfn, &p2mt);else - mfn =gfn_to_mfn_unshare (p2m, gfn, &p2mt,1 ); + { + mfn =gfn_to_mfn_unshare (p2m, gfn, &p2mt); +BUG_ON (p2m_is_shared (p2mt)); +/* XXX Here, and above in gfn_to_mfn_private, need to handle +* XXX failure to unshare. */ + }if (p2m_is_valid (p2mt) ) { *frame =mfn_x (mfn);
xen/common/memory.c +1 -1
@@ -363,7 +363,7 @@ static long memory_exchange(XEN_GUEST_HAp2m_type_t p2mt;/* Shared pages cannot be exchanged */ - mfn =mfn_x (gfn_to_mfn_unshare (p2m_get_hostp2m (d), gmfn + k, &p2mt,0 )); + mfn =mfn_x (gfn_to_mfn_unshare (p2m_get_hostp2m (d), gmfn + k, &p2mt));if (p2m_is_shared (p2mt) ) { rc = -ENOMEM ;
xen/include/asm-x86/mem_sharing.h +0 -1
@@ -34,7 +34,6 @@ int mem_sharing_nominate_page(struct p2munsigned long gfn, int expected_refcnt, shr_handle_t *phandle); -#define MEM_SHARING_MUST_SUCCEED (1<<0)#define MEM_SHARING_DESTROY_GFN (1<<1) int mem_sharing_unshare_page(struct p2m_domain *p2m, unsigned long gfn,
xen/include/asm-x86/p2m.h +13 -29
60 lines not on this page · raw message
PATCH 1/1 x86/mm/p2m: Make p2m interfaces take struct domain arguments
In reply to Tim Deegan# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1307017012 -3600
# Node ID de0a051b36ceb01738348426fdd3d52a5776ba1a # Parent 0d3e0a571fdddc873d1ff3750d15db6fc58fff8e x86/mm/p2m: Make p2m interfaces take struct domain arguments.
As part of the nested HVM patch series, many p2m functions were changed to take pointers to p2m tables rather than to domains. This patch reverses that for almost all of them, which:
- gets rid of a lot of "p2m_get_hostp2m(d)" in code which really shouldn't have to know anything about how gfns become mfns.
- ties sharing and paging interfaces to a domain, which is what they actually act on, rather than a particular p2m table.
In developing this patch it became clear that memory-sharing and nested HVM are unlikely to work well together. I haven't tried to fix that here beyond adding some assertions around suspect paths (as this patch is big enough with just the interface changes)
xen/arch/x86/cpu/mcheck/vmce.c +2 -10
@@ -577,7 +577,6 @@ int is_vmce_ready(struct mcinfo_bank *baint unmmap_broken_page (struct domain *d,mfn_t mfn,unsigned long gfn) {mfn_t r_mfn; -struct p2m_domain *p2m;p2m_type_t pt;/* Always trust dom0's MCE handler will prevent future access */
@@ -590,18 +589,11 @@ int unmmap_broken_page(struct domain *d,if ( !is_hvm_domain (d) || !paging_mode_hap (d) )return -ENOSYS ; - p2m =p2m_get_hostp2m (d); -ASSERT (p2m); - -/* This only happen for PoD memory, which should be handled seperetely */ -if (gfn > p2m->max_mapped_pfn) -return -EINVAL ; - - r_mfn =gfn_to_mfn_query (p2m, gfn, &pt); + r_mfn =gfn_to_mfn_query (d, gfn, &pt);if (p2m_to_mask (pt) &P2M_UNMAP_TYPES ) {ASSERT (mfn_x (r_mfn) ==mfn_x (mfn)); -p2m_change_type (p2m, gfn, pt, p2m_ram_broken); +p2m_change_type (d, gfn, pt, p2m_ram_broken);return 0 ; }
xen/arch/x86/debug.c +1 -1
@@ -58,7 +58,7 @@ dbg_hvm_va2mfn(dbgva_t vaddr, struct domreturn INVALID_MFN ; } - mfn =mfn_x (gfn_to_mfn (p2m_get_hostp2m (dp), gfn, &gfntype)); + mfn =mfn_x (gfn_to_mfn (dp, gfn, &gfntype));if (p2m_is_readonly (gfntype) && toaddr ) {DBGP2 ("kdb:p2m_is_readonly: gfntype:%x\n" , gfntype);
xen/arch/x86/domain.c +1 -3
@@ -164,9 +164,7 @@ void dump_pageframe_info(struct domain * }if (is_hvm_domain (d) ) - { -p2m_pod_dump_data (p2m_get_hostp2m (d)); - } +p2m_pod_dump_data (d);spin_lock (&d->page_alloc_lock);page_list_for_each ( page, &d->xenpage_list )
xen/arch/x86/domctl.c +2 -2
@@ -977,7 +977,7 @@ long arch_do_domctl( ret =iomem_permit_access (d, mfn, mfn + nr_mfns -1 );for ( i =0 ; i < nr_mfns; i++ ) -set_mmio_p2m_entry (p2m_get_hostp2m (d), gfn+i,_mfn (mfn+i)); +set_mmio_p2m_entry (d, gfn+i,_mfn (mfn+i)); }else {
@@ -986,7 +986,7 @@ long arch_do_domctl( gfn, mfn, nr_mfns);for ( i =0 ; i < nr_mfns; i++ ) -clear_mmio_p2m_entry (p2m_get_hostp2m (d), gfn+i); +clear_mmio_p2m_entry (d, gfn+i); ret =iomem_deny_access (d, mfn, mfn + nr_mfns -1 ); }
xen/arch/x86/hvm/emulate.c +4 -6
@@ -55,7 +55,6 @@ static int hvmemul_do_io(paddr_t value = ram_gpa;int value_is_ptr = (p_data ==NULL );struct vcpu *curr = current; -struct p2m_domain *p2m =p2m_get_hostp2m (curr->domain);ioreq_t *p =get_ioreq (curr);unsigned long ram_gfn =paddr_to_pfn (ram_gpa);p2m_type_t p2mt;
@@ -63,10 +62,10 @@ static int hvmemul_do_io(int rc;/* Check for paged out page */ - ram_mfn =gfn_to_mfn_unshare (p2m, ram_gfn, &p2mt); + ram_mfn =gfn_to_mfn_unshare (curr->domain, ram_gfn, &p2mt);if (p2m_is_paging (p2mt) ) { -p2m_mem_paging_populate (p2m, ram_gfn); +p2m_mem_paging_populate (curr->domain, ram_gfn);return X86EMUL_RETRY ; }if (p2m_is_shared (p2mt) )
@@ -640,7 +639,6 @@ static int hvmemul_rep_movs(unsigned long saddr, daddr, bytes;paddr_t sgpa, dgpa;uint32_t pfec = PFEC_page_present; -struct p2m_domain *p2m =p2m_get_hostp2m (current->domain);p2m_type_t p2mt;int rc, df = !!(ctxt->regs->eflags &X86_EFLAGS_DF );char *buf;
@@ -671,12 +669,12 @@ static int hvmemul_rep_movs(if ( rc !=X86EMUL_OKAY )return rc; - (void )gfn_to_mfn (p2m, sgpa >>PAGE_SHIFT , &p2mt); + (void )gfn_to_mfn (current->domain, sgpa >>PAGE_SHIFT , &p2mt);if ( !p2m_is_ram (p2mt) && !p2m_is_grant (p2mt) )return hvmemul_do_mmio ( sgpa, reps, bytes_per_rep, dgpa,IOREQ_READ , df,NULL ); - (void )gfn_to_mfn (p2m, dgpa >>PAGE_SHIFT , &p2mt); + (void )gfn_to_mfn (current->domain, dgpa >>PAGE_SHIFT , &p2mt);if ( !p2m_is_ram (p2mt) && !p2m_is_grant (p2mt) )return hvmemul_do_mmio ( dgpa, reps, bytes_per_rep, sgpa,IOREQ_WRITE , df,NULL );
xen/arch/x86/hvm/hvm.c +23 -33
203 lines not on this page · raw message
xen/arch/x86/hvm/mtrr.c +1 -1
@@ -390,7 +390,7 @@ uint32_t get_pat_flags(struct vcpu *v, {struct domain *d = v->domain;p2m_type_t p2mt; -gfn_to_mfn (p2m_get_hostp2m (d),paddr_to_pfn (gpaddr), &p2mt); +gfn_to_mfn (d,paddr_to_pfn (gpaddr), &p2mt);if (p2m_is_ram (p2mt))gdprintk (XENLOG_WARNING , "Conflict occurs for a given guest l1e flags:%x "
xen/arch/x86/hvm/stdvga.c +3 -3
@@ -469,7 +469,7 @@ static int mmio_move(struct hvm_hw_stdvgint i;int sign = p->df ?-1 :1 ;p2m_type_t p2mt; -struct p2m_domain *p2m =p2m_get_hostp2m (current->domain); +struct domain *d = current->domain;if ( p->data_is_ptr ) {
@@ -482,7 +482,7 @@ static int mmio_move(struct hvm_hw_stdvgif (hvm_copy_to_guest_phys (data, &tmp, p->size) != HVMCOPY_okay ) { - (void )gfn_to_mfn (p2m, data >>PAGE_SHIFT , &p2mt); + (void )gfn_to_mfn (d, data >>PAGE_SHIFT , &p2mt);/* * The only case we handle is vga_mem <-> vga_mem. * Anything else disables caching and leaves it to qemu-dm.
@@ -504,7 +504,7 @@ static int mmio_move(struct hvm_hw_stdvgif (hvm_copy_from_guest_phys (&tmp, data, p->size) != HVMCOPY_okay ) { - (void )gfn_to_mfn (p2m, data >>PAGE_SHIFT , &p2mt); + (void )gfn_to_mfn (d, data >>PAGE_SHIFT , &p2mt);if ( (p2mt != p2m_mmio_dm) || (data <VGA_MEM_BASE ) || ((data + p->size) > (VGA_MEM_BASE +VGA_MEM_SIZE )) )return 0 ;
xen/arch/x86/hvm/svm/svm.c +4 -3
@@ -244,7 +244,7 @@ static int svm_vmcb_restore(struct vcpu {if ( c->cr0 &X86_CR0_PG ) { - mfn =mfn_x (gfn_to_mfn (p2m, c->cr3 >>PAGE_SHIFT , &p2mt)); + mfn =mfn_x (gfn_to_mfn (v->domain, c->cr3 >>PAGE_SHIFT , &p2mt));if ( !p2m_is_ram (p2mt) || !get_page (mfn_to_page (mfn), v->domain) ) { gdprintk(XENLOG_ERR, "Invalid CR3 value=0x%"PRIx64"\n",
@@ -1127,6 +1127,7 @@ static void svm_do_nested_pgfault(structunsigned long gfn = gpa >>PAGE_SHIFT ;mfn_t mfn;p2m_type_t p2mt; +p2m_access_t p2ma;struct p2m_domain *p2m =NULL ; ret =hvm_hap_nested_page_fault (gpa,0 , ~0ul ,0 ,0 ,0 ,0 );
@@ -1143,7 +1144,7 @@ static void svm_do_nested_pgfault(struct p2m =p2m_get_p2m (v); _d.gpa = gpa; _d.qualification =0 ; - _d.mfn =mfn_x (gfn_to_mfn_query (p2m, gfn, &_d.p2mt)); + _d.mfn =mfn_x (gfn_to_mfn_type_p2m (p2m, gfn, &_d.p2mt, &p2ma, p2m_query));__trace_var (TRC_HVM_NPF ,0 ,sizeof (_d), &_d); }
@@ -1163,7 +1164,7 @@ static void svm_do_nested_pgfault(structif ( p2m ==NULL ) p2m =p2m_get_p2m (v);/* Everything else is an error. */ - mfn =gfn_to_mfn_guest (p2m, gfn, &p2mt); + mfn =gfn_to_mfn_type_p2m (p2m, gfn, &p2mt, &p2ma, p2m_guest);gdprintk (XENLOG_ERR ,"SVM violation gpa %#" PRIpaddr", mfn %#lx, type %i\n" , gpa,mfn_x (mfn), p2mt);
xen/arch/x86/hvm/vmx/vmx.c +8 -11
@@ -476,8 +476,7 @@ static int vmx_restore_cr0_cr3( {if ( cr0 &X86_CR0_PG ) { - mfn =mfn_x (gfn_to_mfn (p2m_get_hostp2m (v->domain), - cr3 >>PAGE_SHIFT , &p2mt)); + mfn =mfn_x (gfn_to_mfn (v->domain, cr3 >>PAGE_SHIFT , &p2mt));if ( !p2m_is_ram (p2mt) || !get_page (mfn_to_page (mfn), v->domain) ) {gdprintk (XENLOG_ERR ,"Invalid CR3 value=0x%lx\n" , cr3);
@@ -993,8 +992,7 @@ static void vmx_load_pdptrs(struct vcpuif ( cr3 &0x1fUL ) goto crash; - mfn =mfn_x (gfn_to_mfn (p2m_get_hostp2m (v->domain), - cr3 >>PAGE_SHIFT , &p2mt)); + mfn =mfn_x (gfn_to_mfn (v->domain, cr3 >>PAGE_SHIFT , &p2mt));if ( !p2m_is_ram (p2mt) ) goto crash;
@@ -1752,8 +1750,7 @@ static int vmx_alloc_vlapic_mapping(struif ( apic_va ==NULL )return -ENOMEM ;share_xen_page_with_guest (virt_to_page (apic_va), d, XENSHARE_writable); -set_mmio_p2m_entry ( -p2m_get_hostp2m (d),paddr_to_pfn (APIC_DEFAULT_PHYS_BASE ), +set_mmio_p2m_entry (d,paddr_to_pfn (APIC_DEFAULT_PHYS_BASE ),_mfn (virt_to_mfn (apic_va))); d->arch.hvm_domain.vmx.apic_access_mfn =virt_to_mfn (apic_va);
@@ -1959,7 +1956,7 @@ static void ept_handle_violation(unsigneunsigned long gla, gfn = gpa >>PAGE_SHIFT ;mfn_t mfn;p2m_type_t p2mt; -struct p2m_domain *p2m =p2m_get_hostp2m (current->domain); +struct domain *d = current->domain;if ( tb_init_done ) {
@@ -1972,7 +1969,7 @@ static void ept_handle_violation(unsigne _d.gpa = gpa; _d.qualification = qualification; - _d.mfn =mfn_x (gfn_to_mfn_query (p2m, gfn, &_d.p2mt)); + _d.mfn =mfn_x (gfn_to_mfn_query (d, gfn, &_d.p2mt));__trace_var (TRC_HVM_NPF ,0 ,sizeof (_d), &_d); }
@@ -1988,7 +1985,7 @@ static void ept_handle_violation(unsignereturn ;/* Everything else is an error. */ - mfn =gfn_to_mfn_guest (p2m, gfn, &p2mt); + mfn =gfn_to_mfn_guest (d, gfn, &p2mt); gdprintk(XENLOG_ERR, "EPT violation %#lx (%c%c%c/%c%c%c), " "gpa %#"PRIpaddr", mfn %#lx, type %i.\n", qualification,
@@ -2000,7 +1997,7 @@ static void ept_handle_violation(unsigne (qualification &EPT_EFFECTIVE_EXEC ) ?'x' :'-' , gpa, mfn_x(mfn), p2mt); -ept_walk_table (current->domain, gfn); +ept_walk_table (d, gfn);if ( qualification &EPT_GLA_VALID ) {
@@ -2008,7 +2005,7 @@ static void ept_handle_violation(unsignegdprintk (XENLOG_ERR ," --- GLA %#lx\n" , gla); } -domain_crash (current->domain); +domain_crash (d); } static void vmx_failed_vmentry(unsigned int exit_reason,
xen/arch/x86/mm.c +15 -23
@@ -1808,8 +1808,7 @@ static int mod_l1_entry(l1_pgentry_t *plif (l1e_get_flags (nl1e) & _PAGE_PRESENT ) {/* Translate foreign guest addresses. */ - mfn =mfn_x (gfn_to_mfn (p2m_get_hostp2m (pg_dom), -l1e_get_pfn (nl1e), &p2mt)); + mfn =mfn_x (gfn_to_mfn (pg_dom,l1e_get_pfn (nl1e), &p2mt));if ( !p2m_is_ram (p2mt) ||unlikely (mfn ==INVALID_MFN ) )return -EINVAL ;ASSERT ((mfn & ~(PADDR_MASK >>PAGE_SHIFT )) ==0 );
@@ -3482,13 +3481,13 @@ int do_mmu_update( req.ptr -= cmd; gmfn = req.ptr >>PAGE_SHIFT ; - mfn =mfn_x (gfn_to_mfn (p2m_get_hostp2m (pt_owner), gmfn, &p2mt)); + mfn =mfn_x (gfn_to_mfn (pt_owner, gmfn, &p2mt));if ( !p2m_is_valid (p2mt) ) mfn =INVALID_MFN ;if (p2m_is_paged (p2mt) ) { -p2m_mem_paging_populate (p2m_get_hostp2m (pg_owner), gmfn); +p2m_mem_paging_populate (pg_owner, gmfn); rc = -ENOENT ;break ;
@@ -3520,13 +3519,11 @@ int do_mmu_update( {l1_pgentry_t l1e =l1e_from_intpte (req.val);p2m_type_t l1e_p2mt; -gfn_to_mfn (p2m_get_hostp2m (pg_owner), -l1e_get_pfn (l1e), &l1e_p2mt); +gfn_to_mfn (pg_owner,l1e_get_pfn (l1e), &l1e_p2mt);if (p2m_is_paged (l1e_p2mt) ) { -p2m_mem_paging_populate (p2m_get_hostp2m (pg_owner), -l1e_get_pfn (l1e)); +p2m_mem_paging_populate (pg_owner,l1e_get_pfn (l1e)); rc = -ENOENT ;break ; }
@@ -3544,7 +3541,7 @@ int do_mmu_update(/* Unshare the page for RW foreign mappings */ if (l1e_get_flags (l1e) & _PAGE_RW ) { - rc =mem_sharing_unshare_page (p2m_get_hostp2m (pg_owner), + rc =mem_sharing_unshare_page (pg_owner,l1e_get_pfn (l1e),0 );if ( rc )
@@ -3562,12 +3559,11 @@ int do_mmu_update( {l2_pgentry_t l2e =l2e_from_intpte (req.val);p2m_type_t l2e_p2mt; -gfn_to_mfn (p2m_get_hostp2m (pg_owner),l2e_get_pfn (l2e), &l2e_p2mt); +gfn_to_mfn (pg_owner,l2e_get_pfn (l2e), &l2e_p2mt);if (p2m_is_paged (l2e_p2mt) ) { -p2m_mem_paging_populate (p2m_get_hostp2m (pg_owner), -l2e_get_pfn (l2e)); +p2m_mem_paging_populate (pg_owner,l2e_get_pfn (l2e)); rc = -ENOENT ;break ; }
@@ -3591,12 +3587,11 @@ int do_mmu_update( {l3_pgentry_t l3e =l3e_from_intpte (req.val);p2m_type_t l3e_p2mt; -gfn_to_mfn (p2m_get_hostp2m (pg_owner),l3e_get_pfn (l3e), &l3e_p2mt); +gfn_to_mfn (pg_owner,l3e_get_pfn (l3e), &l3e_p2mt);if (p2m_is_paged (l3e_p2mt) ) { -p2m_mem_paging_populate (p2m_get_hostp2m (pg_owner), -l3e_get_pfn (l3e)); +p2m_mem_paging_populate (pg_owner,l3e_get_pfn (l3e)); rc = -ENOENT ;break ; }
@@ -3620,13 +3615,11 @@ int do_mmu_update( {l4_pgentry_t l4e =l4e_from_intpte (req.val);p2m_type_t l4e_p2mt; -gfn_to_mfn (p2m_get_hostp2m (pg_owner), -l4e_get_pfn (l4e), &l4e_p2mt); +gfn_to_mfn (pg_owner,l4e_get_pfn (l4e), &l4e_p2mt);if (p2m_is_paged (l4e_p2mt) ) { -p2m_mem_paging_populate (p2m_get_hostp2m (pg_owner), -l4e_get_pfn (l4e)); +p2m_mem_paging_populate (pg_owner,l4e_get_pfn (l4e)); rc = -ENOENT ;break ; }
@@ -4003,7 +3996,7 @@ static int create_grant_p2m_mapping(uint p2mt = p2m_grant_map_ro; else p2mt = p2m_grant_map_rw; - rc =guest_physmap_add_entry (p2m_get_hostp2m (current->domain), + rc =guest_physmap_add_entry (current->domain, addr >>PAGE_SHIFT , frame,0 , p2mt);if ( rc )return GNTST_general_error;
@@ -4053,7 +4046,7 @@ static int replace_grant_p2m_mapping(if ( new_addr !=0 || (flags & GNTMAP_contains_pte) )return GNTST_general_error; - old_mfn =gfn_to_mfn (p2m_get_hostp2m (d), gfn, &type); + old_mfn =gfn_to_mfn (d, gfn, &type);if ( !p2m_is_grant (type) ||mfn_x (old_mfn) != frame ) { gdprintk(XENLOG_WARNING,
@@ -4652,8 +4645,7 @@ long arch_memory_op(int op, XEN_GUEST_HA {p2m_type_t p2mt; - xatp.idx =mfn_x (gfn_to_mfn_unshare (p2m_get_hostp2m (d), - xatp.idx, &p2mt)); + xatp.idx =mfn_x (gfn_to_mfn_unshare (d, xatp.idx, &p2mt));/* If the page is still shared, exit early */ if (p2m_is_shared (p2mt) ) {
xen/arch/x86/mm/guest_walk.c +5 -3
@@ -92,12 +92,14 @@ static inline void *map_domain_gfn(struc p2m_type_t *p2mt, uint32_t *rc) { +p2m_access_t a; +/* Translate the gfn, unsharing if shared */ - *mfn =gfn_to_mfn_unshare (p2m,gfn_x (gfn), p2mt); + *mfn =gfn_to_mfn_type_p2m (p2m,gfn_x (gfn), p2mt, &a, p2m_unshare);if (p2m_is_paging (*p2mt) ) { -p2m_mem_paging_populate (p2m,gfn_x (gfn)); - +ASSERT (!p2m_is_nestedp2m (p2m)); +p2m_mem_paging_populate (p2m->domain,gfn_x (gfn)); *rc = _PAGE_PAGED;return NULL ; }
xen/arch/x86/mm/hap/guest_walk.c +8 -4
@@ -54,13 +54,16 @@ unsigned long hap_p2m_ga_to_gfn(GUEST_PAmfn_t top_mfn;void *top_map;p2m_type_t p2mt; +p2m_access_t p2ma;walk_t gw;/* Get the top-level table's MFN */ - top_mfn =gfn_to_mfn_unshare (p2m, cr3 >>PAGE_SHIFT , &p2mt); + top_mfn =gfn_to_mfn_type_p2m (p2m, cr3 >>PAGE_SHIFT , + &p2mt, &p2ma, p2m_unshare);if (p2m_is_paging (p2mt) ) { -p2m_mem_paging_populate (p2m, cr3 >>PAGE_SHIFT ); +ASSERT (!p2m_is_nestedp2m (p2m)); +p2m_mem_paging_populate (p2m->domain, cr3 >>PAGE_SHIFT ); pfec[0 ] = PFEC_page_paged;return INVALID_GFN ;
@@ -89,10 +92,11 @@ unsigned long hap_p2m_ga_to_gfn(GUEST_PAif ( missing ==0 ) {gfn_t gfn =guest_l1e_get_gfn (gw.l1e); -gfn_to_mfn_unshare (p2m,gfn_x (gfn), &p2mt); +gfn_to_mfn_type_p2m (p2m,gfn_x (gfn), &p2mt, &p2ma, p2m_unshare);if (p2m_is_paging (p2mt) ) { -p2m_mem_paging_populate (p2m,gfn_x (gfn)); +ASSERT (!p2m_is_nestedp2m (p2m)); +p2m_mem_paging_populate (p2m->domain,gfn_x (gfn)); pfec[0 ] = PFEC_page_paged;return INVALID_GFN ;
xen/arch/x86/mm/hap/hap.c +6 -9
@@ -71,7 +71,7 @@ static int hap_enable_vram_tracking(stru/* set l1e entries of P2M table to be read-only. */ for (i = dirty_vram->begin_pfn; i < dirty_vram->end_pfn; i++) -p2m_change_type (p2m_get_hostp2m (d), i, p2m_ram_rw, p2m_ram_logdirty); +p2m_change_type (d, i, p2m_ram_rw, p2m_ram_logdirty);flush_tlb_mask (d->domain_dirty_cpumask);return 0 ;
@@ -91,7 +91,7 @@ static int hap_disable_vram_tracking(str/* set l1e entries of P2M table with normal mode */ for (i = dirty_vram->begin_pfn; i < dirty_vram->end_pfn; i++) -p2m_change_type (p2m_get_hostp2m (d), i, p2m_ram_logdirty, p2m_ram_rw); +p2m_change_type (d, i, p2m_ram_logdirty, p2m_ram_rw);flush_tlb_mask (d->domain_dirty_cpumask);return 0 ;
@@ -107,7 +107,7 @@ static void hap_clean_vram_tracking(stru/* set l1e entries of P2M table to be read-only. */ for (i = dirty_vram->begin_pfn; i < dirty_vram->end_pfn; i++) -p2m_change_type (p2m_get_hostp2m (d), i, p2m_ram_rw, p2m_ram_logdirty); +p2m_change_type (d, i, p2m_ram_rw, p2m_ram_logdirty);flush_tlb_mask (d->domain_dirty_cpumask); }
@@ -201,8 +201,7 @@ static int hap_enable_log_dirty(struct dhap_unlock (d);/* set l1e entries of P2M table to be read-only. */ -p2m_change_entry_type_global (p2m_get_hostp2m (d), - p2m_ram_rw, p2m_ram_logdirty); +p2m_change_entry_type_global (d, p2m_ram_rw, p2m_ram_logdirty);flush_tlb_mask (d->domain_dirty_cpumask);return 0 ; }
@@ -214,16 +213,14 @@ static int hap_disable_log_dirty(structhap_unlock (d);/* set l1e entries of P2M table with normal mode */ -p2m_change_entry_type_global (p2m_get_hostp2m (d), - p2m_ram_logdirty, p2m_ram_rw); +p2m_change_entry_type_global (d, p2m_ram_logdirty, p2m_ram_rw);return 0 ; }static void hap_clean_dirty_bitmap (struct domain *d) {/* set l1e entries of P2M table to be read-only. */ -p2m_change_entry_type_global (p2m_get_hostp2m (d), - p2m_ram_rw, p2m_ram_logdirty); +p2m_change_entry_type_global (d, p2m_ram_rw, p2m_ram_logdirty);flush_tlb_mask (d->domain_dirty_cpumask); }
xen/arch/x86/mm/hap/nested_hap.c +3 -2
@@ -123,9 +123,10 @@ nestedhap_walk_L0_p2m(struct p2m_domain {mfn_t mfn;p2m_type_t p2mt; +p2m_access_t p2ma; -/* we use gfn_to_mfn_query() function to walk L0 P2M table */ - mfn =gfn_to_mfn_query (p2m, L1_gpa >>PAGE_SHIFT , &p2mt); +/* walk L0 P2M table */ + mfn =gfn_to_mfn_type_p2m (p2m, L1_gpa >>PAGE_SHIFT , &p2mt, &p2ma, p2m_query);if (p2m_is_paging (p2mt) ||p2m_is_shared (p2mt) || !p2m_is_ram (p2mt) )return NESTEDHVM_PAGEFAULT_ERROR ;
xen/arch/x86/mm/mem_event.c +2 -2
@@ -252,7 +252,7 @@ int mem_event_domctl(struct domain *d, x/* Get MFN of ring page */ guest_get_eff_l1e (v, ring_addr, &l1e); gfn =l1e_get_pfn (l1e); - ring_mfn =gfn_to_mfn (p2m_get_hostp2m (dom_mem_event), gfn, &p2mt); + ring_mfn =gfn_to_mfn (dom_mem_event, gfn, &p2mt); rc = -EINVAL ;if (unlikely (!mfn_valid (mfn_x (ring_mfn))) )
@@ -261,7 +261,7 @@ int mem_event_domctl(struct domain *d, x/* Get MFN of shared page */ guest_get_eff_l1e (v, shared_addr, &l1e); gfn =l1e_get_pfn (l1e); - shared_mfn =gfn_to_mfn (p2m_get_hostp2m (dom_mem_event), gfn, &p2mt); + shared_mfn =gfn_to_mfn (dom_mem_event, gfn, &p2mt); rc = -EINVAL ;if (unlikely (!mfn_valid (mfn_x (shared_mfn))) )
xen/arch/x86/mm/mem_paging.c +6 -11
@@ -28,9 +28,6 @@int mem_paging_domctl (struct domain *d,xen_domctl_mem_event_op_t *mec,XEN_GUEST_HANDLE (void ) u_domctl) { -int rc; -struct p2m_domain *p2m =p2m_get_hostp2m (d); -/* Only HAP is supported */ if ( !hap_enabled (d) )return -ENODEV ;
@@ -40,37 +37,35 @@ int mem_paging_domctl(struct domain *d,case XEN_DOMCTL_MEM_EVENT_OP_PAGING_NOMINATE : {unsigned long gfn = mec->gfn; - rc =p2m_mem_paging_nominate (p2m, gfn); +return p2m_mem_paging_nominate (d, gfn); }break ;case XEN_DOMCTL_MEM_EVENT_OP_PAGING_EVICT : {unsigned long gfn = mec->gfn; - rc =p2m_mem_paging_evict (p2m, gfn); +return p2m_mem_paging_evict (d, gfn); }break ;case XEN_DOMCTL_MEM_EVENT_OP_PAGING_PREP : {unsigned long gfn = mec->gfn; - rc =p2m_mem_paging_prep (p2m, gfn); +return p2m_mem_paging_prep (d, gfn); }break ;case XEN_DOMCTL_MEM_EVENT_OP_PAGING_RESUME : { -p2m_mem_paging_resume (p2m); - rc =0 ; +p2m_mem_paging_resume (d); +return 0 ; }break ;default : - rc = -ENOSYS ; +return -ENOSYS ;break ; } - -return rc; }
xen/arch/x86/mm/mem_sharing.c +12 -17
@@ -252,7 +252,6 @@ static void mem_sharing_audit(void)list_for_each (le, &e->gfns) {struct domain *d; -struct p2m_domain *p2m;p2m_type_t t;mfn_t mfn;
@@ -264,8 +263,7 @@ static void mem_sharing_audit(void) g->domain, g->gfn, mfn_x(e->mfn));continue ; } - p2m =p2m_get_hostp2m (d); - mfn =gfn_to_mfn (p2m, g->gfn, &t); + mfn =gfn_to_mfn (d, g->gfn, &t);if (mfn_x (mfn) !=mfn_x (e->mfn)) MEM_SHARING_DEBUG("Incorrect P2M for d=%d, PFN=%lx." "Expecting MFN=%ld, got %ld\n",
@@ -376,7 +374,7 @@ int mem_sharing_debug_gfn(struct domainp2m_type_t p2mt;mfn_t mfn; - mfn =gfn_to_mfn (p2m_get_hostp2m (d), gfn, &p2mt); + mfn =gfn_to_mfn (d, gfn, &p2mt); printk("Debug for domain=%d, gfn=%lx, ", d->domain_id,
@@ -485,7 +483,7 @@ int mem_sharing_debug_gref(struct domainreturn mem_sharing_debug_gfn (d, gfn); } -int mem_sharing_nominate_page (struct p2m_domain *p2m, +int mem_sharing_nominate_page (struct domain *d,unsigned long gfn,int expected_refcnt,shr_handle_t *phandle)
@@ -497,12 +495,11 @@ int mem_sharing_nominate_page(struct p2mshr_handle_t handle;shr_hash_entry_t *hash_entry;struct gfn_info *gfn_info; -struct domain *d = p2m->domain; *phandle =0UL ;shr_lock (); - mfn =gfn_to_mfn (p2m, gfn, &p2mt); + mfn =gfn_to_mfn (d, gfn, &p2mt);/* Check if mfn is valid */ ret = -EINVAL ;
@@ -540,7 +537,7 @@ int mem_sharing_nominate_page(struct p2m }/* Change the p2m type */ -if (p2m_change_type (p2m, gfn, p2mt, p2m_ram_shared) != p2mt) +if (p2m_change_type (d, gfn, p2mt, p2m_ram_shared) != p2mt) {/* This is unlikely, as the type must have changed since we've checked * it a few lines above.
@@ -602,7 +599,7 @@ int mem_sharing_share_pages(shr_handle_tlist_del (&gfn->list); d =get_domain_by_id (gfn->domain);BUG_ON (!d); -BUG_ON (set_shared_p2m_entry (p2m_get_hostp2m (d), gfn->gfn, se->mfn) ==0 ); +BUG_ON (set_shared_p2m_entry (d, gfn->gfn, se->mfn) ==0 );put_domain (d);list_add (&gfn->list, &se->gfns);put_page_and_type (cpage);
@@ -621,7 +618,7 @@ err_out:return ret; } -int mem_sharing_unshare_page (struct p2m_domain *p2m, +int mem_sharing_unshare_page (struct domain *d,unsigned long gfn,uint16_t flags) {
@@ -634,13 +631,12 @@ int mem_sharing_unshare_page(struct p2m_struct gfn_info *gfn_info =NULL ;shr_handle_t handle;struct list_head *le; -struct domain *d = p2m->domain;mem_sharing_audit ();/* Remove the gfn_info from the list */ shr_lock (); - mfn =gfn_to_mfn (p2m, gfn, &p2mt); + mfn =gfn_to_mfn (d, gfn, &p2mt);/* Has someone already unshared it? */ if (!p2m_is_shared (p2mt)) {
@@ -706,7 +702,7 @@ gfn_found:unmap_domain_page (s);unmap_domain_page (t); -BUG_ON (set_shared_p2m_entry (p2m, gfn,page_to_mfn (page)) ==0 ); +BUG_ON (set_shared_p2m_entry (d, gfn,page_to_mfn (page)) ==0 );put_page_and_type (old_page); private_page_found:
@@ -717,7 +713,7 @@ private_page_found:else atomic_dec (&nr_saved_mfns); -if (p2m_change_type (p2m, gfn, p2m_ram_shared, p2m_ram_rw) != +if (p2m_change_type (d, gfn, p2m_ram_shared, p2m_ram_rw) != p2m_ram_shared) {printk ("Could not change p2m type.\n" );
@@ -754,7 +750,7 @@ int mem_sharing_domctl(struct domain *d,shr_handle_t handle;if (!mem_sharing_enabled (d))return -EINVAL ; - rc =mem_sharing_nominate_page (p2m_get_hostp2m (d), gfn,0 , &handle); + rc =mem_sharing_nominate_page (d, gfn,0 , &handle); mec->u.nominate.handle = handle;mem_sharing_audit (); }
@@ -770,8 +766,7 @@ int mem_sharing_domctl(struct domain *d,return -EINVAL ;if (mem_sharing_gref_to_gfn (d, gref, &gfn) <0 )return -EINVAL ; - rc =mem_sharing_nominate_page (p2m_get_hostp2m (d), - gfn,3 , &handle); + rc =mem_sharing_nominate_page (d, gfn,3 , &handle); mec->u.nominate.handle = handle;mem_sharing_audit (); }
xen/arch/x86/mm/p2m-pod.c +8 -8
@@ -518,7 +518,7 @@ p2m_pod_decrease_reservation(struct doma {p2m_type_t t; -gfn_to_mfn_query (p2m, gpfn + i, &t); +gfn_to_mfn_query (d, gpfn + i, &t);if ( t == p2m_populate_on_demand ) pod++;
@@ -558,7 +558,7 @@ p2m_pod_decrease_reservation(struct domamfn_t mfn;p2m_type_t t; - mfn =gfn_to_mfn_query (p2m, gpfn + i, &t); + mfn =gfn_to_mfn_query (d, gpfn + i, &t);if ( t == p2m_populate_on_demand ) {set_p2m_entry (p2m, gpfn + i,_mfn (INVALID_MFN ),0 , p2m_invalid, p2m->default_access);
@@ -606,9 +606,9 @@ out:return ret; } -void -p2m_pod_dump_data (struct p2m_domain *p2m) +void p2m_pod_dump_data (struct domain *d) { +struct p2m_domain *p2m =p2m_get_hostp2m (d);printk (" PoD entries=%d cachesize=%d\n" , p2m->pod.entry_count, p2m->pod.count); }
@@ -639,7 +639,7 @@ p2m_pod_zero_check_superpage(struct p2m_for ( i=0 ; i<SUPERPAGE_PAGES ; i++ ) { - mfn =gfn_to_mfn_query (p2m, gfn + i, &type); + mfn =gfn_to_mfn_query (d, gfn + i, &type);if ( i ==0 ) {
@@ -767,7 +767,7 @@ p2m_pod_zero_check(struct p2m_domain *p2/* First, get the gfn list, translate to mfns, and map the pages. */ for ( i=0 ; i<count; i++ ) { - mfns[i] =gfn_to_mfn_query (p2m, gfns[i], types + i); + mfns[i] =gfn_to_mfn_query (d, gfns[i], types + i);/* If this is ram, and not a pagetable or from the xen heap, and probably not mapped elsewhere, map it; otherwise, skip. */ if ( p2m_is_ram(types[i])
@@ -906,7 +906,7 @@ p2m_pod_emergency_sweep(struct p2m_domai/* FIXME: Figure out how to avoid superpages */ for ( i=p2m->pod.reclaim_single; i >0 ; i-- ) { -gfn_to_mfn_query (p2m, i, &t ); +gfn_to_mfn_query (p2m->domain, i, &t );if (p2m_is_ram (t) ) { gfns[j] = i;
@@ -1095,7 +1095,7 @@ guest_physmap_mark_populate_on_demand(st/* Make sure all gpfns are unused */ for ( i =0 ; i < (1UL << order); i++ ) { - omfn =gfn_to_mfn_query (p2m, gfn + i, &ot); + omfn =gfn_to_mfn_query (d, gfn + i, &ot);if (p2m_is_ram (ot) ) { printk("%s: gfn_to_mfn returned type %d!\n",
xen/arch/x86/mm/p2m-pt.c +5 -6
@@ -677,10 +677,9 @@ out:return mfn; } -static mfn_t -p2m_gfn_to_mfn (struct p2m_domain *p2m,unsigned long gfn,p2m_type_t *t,p2m_access_t *a, -p2m_query_t q) +p2m_gfn_to_mfn (struct p2m_domain *p2m,unsigned long gfn, +p2m_type_t *t,p2m_access_t *a,p2m_query_t q) {mfn_t mfn;paddr_t addr = ((paddr_t )gfn) <<PAGE_SHIFT ;
@@ -697,8 +696,6 @@ p2m_gfn_to_mfn(struct p2m_domain *p2m, u/* Not implemented except with EPT */ *a = p2m_access_rwx; - mfn =pagetable_get_mfn (p2m_get_pagetable (p2m)); -if ( gfn > p2m->max_mapped_pfn )/* This pfn is higher than the highest the p2m map currently holds */ return _mfn (INVALID_MFN );
@@ -707,6 +704,8 @@ p2m_gfn_to_mfn(struct p2m_domain *p2m, uif ( p2m ==p2m_get_hostp2m (current->domain) )return p2m_gfn_to_mfn_current (p2m, gfn, t, a, q); + mfn =pagetable_get_mfn (p2m_get_pagetable (p2m)); +#if CONFIG_PAGING_LEVELS >=4 {l4_pgentry_t *l4e =map_domain_page (mfn_x (mfn));
@@ -1059,7 +1058,7 @@ void audit_p2m(struct p2m_domain *p2m, iif ( test_linear && (gfn <= p2m->max_mapped_pfn) ) { - lp2mfn =mfn_x (gfn_to_mfn_query (p2m, gfn, &type)); + lp2mfn =mfn_x (gfn_to_mfn_type_p2m (p2m, gfn, &type, p2m_query));if ( lp2mfn !=mfn_x (p2mfn) ) { P2M_PRINTK("linear mismatch gfn %#lx -> mfn %#lx "
xen/arch/x86/mm/p2m.c +44 -33
250 lines not on this page · raw message
xen/arch/x86/mm/shadow/common.c +2 -2
@@ -3712,7 +3712,7 @@ int shadow_track_dirty_vram(struct domai/* Iterate over VRAM to track dirty bits. */ for ( i =0 ; i < nr; i++ ) { -mfn_t mfn =gfn_to_mfn (p2m, begin_pfn + i, &t); +mfn_t mfn =gfn_to_mfn (d, begin_pfn + i, &t);struct page_info *page;int dirty =0 ;paddr_t sl1ma = dirty_vram->sl1ma[i];
@@ -3797,7 +3797,7 @@ int shadow_track_dirty_vram(struct domai/* was clean for more than two seconds, try to disable guest * write access */ for ( i = begin_pfn; i < end_pfn; i++ ) { -mfn_t mfn =gfn_to_mfn (p2m, i, &t); +mfn_t mfn =gfn_to_mfn (d, i, &t);if (mfn_x (mfn) !=INVALID_MFN ) flush_tlb |=sh_remove_write_access (d->vcpu[0 ], mfn,1 ,0 ); }
xen/arch/x86/mm/shadow/multi.c +20 -26
193 lines not on this page · raw message
xen/arch/x86/mm/shadow/types.h +2 -2
@@ -193,9 +193,9 @@ static inline shadow_l4e_t shadow_l4e_fr/* Override gfn_to_mfn to work with gfn_t */ #undef gfn_to_mfn_query -#define gfn_to_mfn_query (d, g, t) _gfn_to_mfn_type((d), gfn_x(g), (t), p2m_query) +#define gfn_to_mfn_query (d, g, t) gfn_to_mfn_type((d), gfn_x(g), (t), p2m_query)#undef gfn_to_mfn_guest -#define gfn_to_mfn_guest (d, g, t) _gfn_to_mfn_type((d), gfn_x(g), (t), p2m_guest) +#define gfn_to_mfn_guest (d, g, t) gfn_to_mfn_type((d), gfn_x(g), (t), p2m_guest)/* The shadow types needed for the various levels. */
xen/arch/x86/msi.c +1 -1
@@ -663,7 +663,7 @@ static int msix_capability_init(struct pWARN ();if ( dev->domain ) -p2m_change_entry_type_global (p2m_get_hostp2m (dev->domain), +p2m_change_entry_type_global (dev->domain, p2m_mmio_direct, p2m_mmio_direct);if ( !dev->domain || !paging_mode_translate (dev->domain) ) {
xen/common/grant_table.c +4 -6
@@ -110,7 +110,7 @@ static unsigned inline int max_nr_maptra#define gfn_to_mfn_private (_d, _gfn) ({ \ p2m_type_t __p2mt; \ unsigned long __x; \ - __x = mfn_x(gfn_to_mfn_unshare(p2m_get_hostp2m(_d), _gfn, &__p2mt)); \ + __x = mfn_x(gfn_to_mfn_unshare((_d), (_gfn), &__p2mt)); \ BUG_ON(p2m_is_shared(__p2mt));/* XXX fixme */ \if ( !p2m_is_valid (__p2mt) ) \ __x =INVALID_MFN ; \
@@ -146,16 +146,14 @@ static int __get_paged_frame(unsigned lo {int rc = GNTST_okay;#if defined(P2M_PAGED_TYPES ) || defined(P2M_SHARED_TYPES ) -struct p2m_domain *p2m;p2m_type_t p2mt;mfn_t mfn; - p2m =p2m_get_hostp2m (rd);if ( readonly ) - mfn =gfn_to_mfn (p2m, gfn, &p2mt); + mfn =gfn_to_mfn (rd, gfn, &p2mt);else { - mfn =gfn_to_mfn_unshare (p2m, gfn, &p2mt); + mfn =gfn_to_mfn_unshare (rd, gfn, &p2mt);BUG_ON (p2m_is_shared (p2mt));/* XXX Here, and above in gfn_to_mfn_private, need to handle * XXX failure to unshare. */
@@ -165,7 +163,7 @@ static int __get_paged_frame(unsigned lo *frame =mfn_x (mfn);if (p2m_is_paging (p2mt) ) { -p2m_mem_paging_populate (p2m, gfn); +p2m_mem_paging_populate (rd, gfn); rc = GNTST_eagain; } }else {
xen/common/memory.c +3 -3
@@ -162,11 +162,11 @@ int guest_remove_page(struct domain *d,unsigned long mfn;#ifdef CONFIG_X86 - mfn =mfn_x (gfn_to_mfn (p2m_get_hostp2m (d), gmfn, &p2mt)); + mfn =mfn_x (gfn_to_mfn (d, gmfn, &p2mt));if (unlikely (p2m_is_paging (p2mt)) ) {guest_physmap_remove_page (d, gmfn, mfn,0 ); -p2m_mem_paging_drop_page (p2m_get_hostp2m (d), gmfn); +p2m_mem_paging_drop_page (d, gmfn);return 1 ; }#else
@@ -363,7 +363,7 @@ static long memory_exchange(XEN_GUEST_HAp2m_type_t p2mt;/* Shared pages cannot be exchanged */ - mfn =mfn_x (gfn_to_mfn_unshare (p2m_get_hostp2m (d), gmfn + k, &p2mt)); + mfn =mfn_x (gfn_to_mfn_unshare (d, gmfn + k, &p2mt));if (p2m_is_shared (p2mt) ) { rc = -ENOMEM ;
xen/common/tmem_xen.c +1 -1
@@ -109,7 +109,7 @@ static inline void *cli_get_page(tmem_clstruct page_info *page;int ret; - cli_mfn =mfn_x (gfn_to_mfn (p2m_get_hostp2m (current->domain), cmfn, &t)); + cli_mfn =mfn_x (gfn_to_mfn (current->domain, cmfn, &t));if ( t != p2m_ram_rw || !mfn_valid (cli_mfn) )return NULL ; page =mfn_to_page (cli_mfn);
xen/include/asm-x86/guest_pt.h +1 -1
@@ -53,7 +53,7 @@ gfn_to_paddr(gfn_t gfn)/* Override gfn_to_mfn to work with gfn_t */ #undef gfn_to_mfn -#define gfn_to_mfn (d, g, t) _gfn_to_mfn_type((d), gfn_x(g), (t), p2m_alloc) +#define gfn_to_mfn (d, g, t) gfn_to_mfn_type((d), gfn_x(g), (t), p2m_alloc)/* Types of the guest's page tables and access functions for them */
xen/include/asm-x86/mem_sharing.h +2 -3
@@ -30,16 +30,15 @@typedef uint64_t shr_handle_t ;unsigned int mem_sharing_get_nr_saved_mfns (void ); -int mem_sharing_nominate_page (struct p2m_domain *p2m, +int mem_sharing_nominate_page (struct domain *d,unsigned long gfn,int expected_refcnt,shr_handle_t *phandle);#define MEM_SHARING_DESTROY_GFN (1<<1) -int mem_sharing_unshare_page (struct p2m_domain *p2m, +int mem_sharing_unshare_page (struct domain *d,unsigned long gfn,uint16_t flags);int mem_sharing_sharing_resume (struct domain *d); -int mem_sharing_cache_resize (struct p2m_domain *p2m,int new_size);int mem_sharing_domctl (struct domain *d,xen_domctl_mem_sharing_op_t *mec);void mem_sharing_init (void );
xen/include/asm-x86/p2m.h +49 -47
204 lines not on this page · raw message
PATCH 1/1 x86/mm/p2m: paging_p2m_ga_to_gfn() doesn't need so many arguments
In reply to Tim Deegan# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1307017012 -3600
# Node ID 39603c2f0dab39bf399910e180aa60deca7db680
# Parent de0a051b36ceb01738348426fdd3d52a5776ba1a x86/mm/p2m: paging_p2m_ga_to_gfn() doesn't need so many arguments
It has only one caller and is always called with p2m == hostp2m and mode == hostmode. Also, since it's only called from nested HAP code, remove the check of paging_mode_hap(). Then rename it to reflect its new interface.
xen/arch/x86/mm/hap/nested_hap.c +5 -9
@@ -143,17 +143,15 @@ nestedhap_walk_L0_p2m(struct p2m_domain* L1_gpa. The result value tells what to do next. */ static int -nestedhap_walk_L1_p2m (struct vcpu *v,struct p2m_domain *p2m, -paddr_t L2_gpa,paddr_t *L1_gpa) +nestedhap_walk_L1_p2m (struct vcpu *v,paddr_t L2_gpa,paddr_t *L1_gpa) {uint32_t pfec;unsigned long nested_cr3, gfn; -const struct paging_mode *mode =paging_get_hostmode (v); nested_cr3 =nhvm_vcpu_hostcr3 (v); -/* walk the guest table */ - gfn =paging_p2m_ga_to_gfn (v, p2m, mode, nested_cr3, L2_gpa, &pfec); +/* Walk the guest-supplied NPT table, just as if it were a pagetable */ + gfn =paging_ga_to_gfn_cr3 (v, nested_cr3, L2_gpa, &pfec);if ( gfn ==INVALID_GFN )return NESTEDHVM_PAGEFAULT_INJECT ;
@@ -178,10 +176,8 @@ nestedhvm_hap_nested_page_fault(struct v p2m =p2m_get_hostp2m (d);/* L0 p2m */ nested_p2m =p2m_get_nestedp2m (v,nhvm_vcpu_hostcr3 (v)); -/* walk the L1 P2M table, note we have to pass p2m -* and not nested_p2m here or we fail the walk forever, -* otherwise. */ - rv =nestedhap_walk_L1_p2m (v, p2m, L2_gpa, &L1_gpa); +/* walk the L1 P2M table */ + rv =nestedhap_walk_L1_p2m (v, L2_gpa, &L1_gpa);/* let caller to handle these two cases */ switch (rv) {
xen/include/asm-x86/paging.h +6 -13
@@ -265,26 +265,19 @@ unsigned long paging_gva_to_gfn(struct vunsigned long va, uint32_t *pfec); -/* Translates a guest virtual address to guest physical address -* where the specified cr3 is translated to host physical address -* using the specified p2m table. -* This allows to do page walks in the guest or even in the nested guest. -* It returns the guest's gfn or the nested guest's gfn. +/* Translate a guest address using a particular CR3 value. This is used +* to by nested HAP code, to walk the guest-supplied NPT tables as if +* they were pagetables. * Use 'paddr_t' for the guest address so it won't overflow when * guest or nested guest is in 32bit PAE mode. */ -static inline unsigned long paging_p2m_ga_to_gfn (struct vcpu *v, -struct p2m_domain *p2m, -const struct paging_mode *mode, +static inline unsigned long paging_ga_to_gfn_cr3 (struct vcpu *v,unsigned long cr3,paddr_t ga,uint32_t *pfec) { -if (is_hvm_domain (v->domain) &&paging_mode_hap (v->domain) ) -return mode->p2m_ga_to_gfn (v, p2m, cr3, ga, pfec); - -/* shadow paging */ -return paging_gva_to_gfn (v, ga, pfec); +struct p2m_domain *p2m = v->domain->arch.p2m; +return paging_get_hostmode (v)->p2m_ga_to_gfn (v, p2m, cr3, ga, pfec); }/* Update all the things that are derived from the guest's CR3.
PATCH 1/1 x86/mm: Fix memory-sharing code's locking discipline
In reply to Tim Deegan# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1307017012 -3600
# Node ID 51518c502d1b23a1cc4b325f81d17027a9d31a74 # Parent 39603c2f0dab39bf399910e180aa60deca7db680 x86/mm: Fix memory-sharing code's locking discipline.
memshr_audit is sometimes called with the shr_lock held. Make it so for every call.
Move the unsharing loop in p2m_teardown out of the p2m_lock to avoid deadlocks.
xen/arch/x86/mm/mem_sharing.c +7 -13
@@ -225,7 +225,7 @@ static void mem_sharing_audit(void)int bucket;struct page_info *pg; -shr_lock (); +ASSERT (shr_locked_by_me ());for (bucket=0 ; bucket <SHR_HASH_LENGTH ; bucket++) {
@@ -285,8 +285,6 @@ static void mem_sharing_audit(void) e = e->next; } } - -shr_unlock (); }#endif
@@ -632,10 +630,10 @@ int mem_sharing_unshare_page(struct domashr_handle_t handle;struct list_head *le; +shr_lock ();mem_sharing_audit (); +/* Remove the gfn_info from the list */ -shr_lock (); - mfn =gfn_to_mfn (d, gfn, &p2mt);/* Has someone already unshared it? */
@@ -739,7 +737,6 @@ int mem_sharing_domctl(struct domain *d,case XEN_DOMCTL_MEM_SHARING_OP_CONTROL : { d->arch.hvm_domain.mem_sharing_enabled = mec->u.enable; -mem_sharing_audit (); rc =0 ; }break ;
@@ -752,7 +749,6 @@ int mem_sharing_domctl(struct domain *d,return -EINVAL ; rc =mem_sharing_nominate_page (d, gfn,0 , &handle); mec->u.nominate.handle = handle; -mem_sharing_audit (); }break ;
@@ -768,7 +764,6 @@ int mem_sharing_domctl(struct domain *d,return -EINVAL ; rc =mem_sharing_nominate_page (d, gfn,3 , &handle); mec->u.nominate.handle = handle; -mem_sharing_audit (); }break ;
@@ -777,7 +772,6 @@ int mem_sharing_domctl(struct domain *d,shr_handle_t sh = mec->u.share.source_handle;shr_handle_t ch = mec->u.share.client_handle; rc =mem_sharing_share_pages (sh, ch); -mem_sharing_audit (); }break ;
@@ -785,7 +779,6 @@ int mem_sharing_domctl(struct domain *d, {if (!mem_sharing_enabled (d))return -EINVAL ; -mem_sharing_audit (); rc =mem_sharing_sharing_resume (d); }break ;
@@ -794,7 +787,6 @@ int mem_sharing_domctl(struct domain *d, {unsigned long gfn = mec->u.debug.u.gfn; rc =mem_sharing_debug_gfn (d, gfn); -mem_sharing_audit (); }break ;
@@ -802,7 +794,6 @@ int mem_sharing_domctl(struct domain *d, {unsigned long mfn = mec->u.debug.u.mfn; rc =mem_sharing_debug_mfn (mfn); -mem_sharing_audit (); }break ;
@@ -810,7 +801,6 @@ int mem_sharing_domctl(struct domain *d, {grant_ref_t gref = mec->u.debug.u.gref; rc =mem_sharing_debug_gref (d, gref); -mem_sharing_audit (); }break ;
@@ -819,6 +809,10 @@ int mem_sharing_domctl(struct domain *d,break ; } +shr_lock (); +mem_sharing_audit (); +shr_unlock (); +return rc; }
xen/arch/x86/mm/p2m.c +3 -3
@@ -296,12 +296,10 @@ void p2m_teardown(struct p2m_domain *p2mif (p2m ==NULL )return ; -p2m_lock (p2m); -#ifdef __x86_64__for ( gfn=0 ; gfn < p2m->max_mapped_pfn; gfn++ ) { - mfn = p2m->get_entry (p2m, gfn, &t, &a, p2m_query); + mfn =gfn_to_mfn_type_p2m (p2m, gfn, &t, &a, p2m_query);if (mfn_valid (mfn) && (t == p2m_ram_shared) ) {ASSERT (!p2m_is_nestedp2m (p2m));
@@ -311,6 +309,8 @@ void p2m_teardown(struct p2m_domain *p2m }#endif +p2m_lock (p2m); + p2m->phys_table =pagetable_null ();while ( (pg =page_list_remove_head (&p2m->pages)) )
PATCH 1/1 x86/mm/p2m: Remove recursive-locking code from set_shared_p2m_entry()
In reply to Tim Deegan# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1307017012 -3600
# Node ID dd89c48f2ac5c55e8a46159390c2c2f83a7b7742
# Parent 51518c502d1b23a1cc4b325f81d17027a9d31a74 x86/mm/p2m: Remove recursive-locking code from set_shared_p2m_entry().
It should no longer be needed now that the shr_lock discipline is fixed.
xen/arch/x86/mm/p2m.c +2 -5
@@ -601,7 +601,6 @@ set_shared_p2m_entry(struct domain *d, u {struct p2m_domain *p2m =p2m_get_hostp2m (d);int rc =0 ; -int need_lock = !p2m_locked_by_me (p2m);p2m_type_t ot;mfn_t omfn;
@@ -617,11 +616,9 @@ set_shared_p2m_entry(struct domain *d, uset_gpfn_from_mfn (mfn_x (omfn),INVALID_M2P_ENTRY );P2M_DEBUG ("set shared %lx %lx\n" , gfn,mfn_x (mfn)); -if ( need_lock ) -p2m_lock (p2m); +p2m_lock (p2m); rc =set_p2m_entry (p2m, gfn, mfn,0 , p2m_ram_shared, p2m->default_access); -if ( need_lock ) -p2m_unlock (p2m); +p2m_unlock (p2m);if (0 == rc ) gdprintk(XENLOG_ERR, "set_mmio_p2m_entry: set_p2m_entry failed! mfn=%08lx\n",
PATCH 1/1 x86/mm/p2m: Fix locking discipline around p2m updates
In reply to Tim Deegan# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1307017012 -3600
# Node ID 32f80f08d7246cac9c75d4820698e754550a425a # Parent dd89c48f2ac5c55e8a46159390c2c2f83a7b7742 x86/mm/p2m: Fix locking discipline around p2m updates.
Direct callers of the p2m setting functions must hold the p2m lock.
xen/arch/x86/mm/hap/nested_hap.c +4 -1
@@ -103,9 +103,12 @@ nestedhap_fix_p2m(struct p2m_domain *p2mASSERT (p2m);ASSERT (p2m->set_entry); - rv = p2m->set_entry (p2m, L2_gpa >>PAGE_SHIFT , +p2m_lock (p2m); + rv =set_p2m_entry (p2m, L2_gpa >>PAGE_SHIFT ,page_to_mfn (maddr_to_page (L0_gpa)),0 /*4K*/ , p2mt, p2ma); +p2m_unlock (p2m); +if (rv ==0 ) { gdprintk(XENLOG_ERR, "failed to set entry for 0x%"PRIx64" -> 0x%"PRIx64"\n",
xen/arch/x86/mm/p2m.c +2 -0
@@ -140,6 +140,8 @@ int set_p2m_entry(struct p2m_domain *p2munsigned int order;int rc =1 ; +ASSERT (p2m_locked_by_me (p2m)); +while ( todo ) {if (hap_enabled (d) )
PATCH 1/1 x86/mm/p2m: Fix locking discipline around p2m lookups
In reply to Tim Deegan# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1307017012 -3600
# Node ID 462280f8fae2fcb137d98f6f1dab105afc6745c3 # Parent 32f80f08d7246cac9c75d4820698e754550a425a x86/mm/p2m: Fix locking discipline around p2m lookups.
All gfn_to_mfn* functions except _query() might take the p2m lock, so can't be called with a p2m, shadow, hap or log_dirty lock held. The remaining offender is the memory sharing code, which calls _unshare() from inside the pagetable walker! Fixing that is too big for a cleanup patch like this one.
xen/arch/x86/hvm/mtrr.c +1 -1
@@ -390,7 +390,7 @@ uint32_t get_pat_flags(struct vcpu *v, {struct domain *d = v->domain;p2m_type_t p2mt; -gfn_to_mfn (d,paddr_to_pfn (gpaddr), &p2mt); +gfn_to_mfn_query (d,paddr_to_pfn (gpaddr), &p2mt);if (p2m_is_ram (p2mt))gdprintk (XENLOG_WARNING , "Conflict occurs for a given guest l1e flags:%x "
xen/arch/x86/mm/p2m.c +3 -3
@@ -566,7 +566,7 @@ set_mmio_p2m_entry(struct domain *d, unsif (0 == rc )gdprintk (XENLOG_ERR ,"set_mmio_p2m_entry: set_p2m_entry failed! mfn=%08lx\n" , -mfn_x (gfn_to_mfn (d, gfn, &ot))); +mfn_x (gfn_to_mfn_query (d, gfn, &ot)));return rc; }
@@ -623,8 +623,8 @@ set_shared_p2m_entry(struct domain *d, up2m_unlock (p2m);if (0 == rc )gdprintk (XENLOG_ERR , -"set_mmio_p2m_entry: set_p2m_entry failed! mfn=%08lx\n" , -gmfn_to_mfn (p2m->domain, gfn)); +"set_shared_p2m_entry: set_p2m_entry failed! mfn=%08lx\n" , +mfn_x (gfn_to_mfn_query (d, gfn, &ot)));return rc; }
xen/arch/x86/mm/shadow/common.c +2 -2
@@ -3712,7 +3712,7 @@ int shadow_track_dirty_vram(struct domai/* Iterate over VRAM to track dirty bits. */ for ( i =0 ; i < nr; i++ ) { -mfn_t mfn =gfn_to_mfn (d, begin_pfn + i, &t); +mfn_t mfn =gfn_to_mfn_query (d, begin_pfn + i, &t);struct page_info *page;int dirty =0 ;paddr_t sl1ma = dirty_vram->sl1ma[i];
@@ -3797,7 +3797,7 @@ int shadow_track_dirty_vram(struct domai/* was clean for more than two seconds, try to disable guest * write access */ for ( i = begin_pfn; i < end_pfn; i++ ) { -mfn_t mfn =gfn_to_mfn (d, i, &t); +mfn_t mfn =gfn_to_mfn_query (d, i, &t);if (mfn_x (mfn) !=INVALID_MFN ) flush_tlb |=sh_remove_write_access (d->vcpu[0 ], mfn,1 ,0 ); }
xen/include/asm-x86/p2m.h +4 -0
@@ -411,6 +411,10 @@ static inline mfn_t gfn_to_mfn_type(strureturn gfn_to_mfn_type_p2m (p2m, gfn, t, &a, q); } +/* Syntactic sugar: most callers will use one of these. +* N.B. gfn_to_mfn_query() is the _only_ one guaranteed not to take the +* p2m lock; none of the others can be called with the p2m, hap or +* shadow lock held. */ #define gfn_to_mfn (d, g, t) gfn_to_mfn_type((d), (g), (t), p2m_alloc)#define gfn_to_mfn_query (d, g, t) gfn_to_mfn_type((d), (g), (t), p2m_query)#define gfn_to_mfn_guest (d, g, t) gfn_to_mfn_type((d), (g), (t), p2m_guest)
PATCH 1/1 x86/mm/p2m: Move p2m code in HVMOP_[gs]et_mem_access into p2m.c
In reply to Tim Deegan# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1307017012 -3600
# Node ID c9ea54b4f49ad9363ef8f08fa984f2900dc147e0
# Parent 462280f8fae2fcb137d98f6f1dab105afc6745c3 x86/mm/p2m: Move p2m code in HVMOP_[gs]et_mem_access into p2m.c
It uses p2m internals like the p2m lock and function pointers so belongs behind the p2m interface.
xen/arch/x86/hvm/hvm.c +11 -86
@@ -3814,21 +3814,6 @@ long do_hvm_op(unsigned long op, XEN_GUE {struct xen_hvm_set_mem_access a;struct domain *d; -struct p2m_domain *p2m; -unsigned long pfn; - -p2m_access_t memaccess[] = { - p2m_access_n, - p2m_access_r, - p2m_access_w, - p2m_access_rw, - p2m_access_x, - p2m_access_rx, - p2m_access_wx, - p2m_access_rwx, - p2m_access_rx2rw, -0 ,/* HVMMEM_access_default -- will get set below */ - };if (copy_from_guest (&a, arg,1 ) )return -EFAULT ;
@@ -3841,42 +3826,13 @@ long do_hvm_op(unsigned long op, XEN_GUEif ( !is_hvm_domain (d) ) goto param_fail5; - p2m =p2m_get_hostp2m (d); - memaccess[HVMMEM_access_default] = p2m->default_access; - -/* If request to set default access */ -if ( a.first_pfn == ~0ull ) - { - rc =0 ; - p2m->default_access = memaccess[a.hvmmem_access]; - goto param_fail5; - } - rc = -EINVAL ;if ( (a.first_pfn >domain_get_maximum_gpfn (d)) || ((a.first_pfn + a.nr -1 ) < a.first_pfn) || ((a.first_pfn + a.nr -1 ) >domain_get_maximum_gpfn (d)) ) goto param_fail5; -if ( a.hvmmem_access >=ARRAY_SIZE (memaccess) ) - goto param_fail5; - -for ( pfn = a.first_pfn; pfn < a.first_pfn + a.nr; pfn++ ) - { -p2m_type_t t; -mfn_t mfn; -int success; - - mfn =gfn_to_mfn_unshare (d, pfn, &t); - -p2m_lock (p2m); - success = p2m->set_entry (p2m, pfn, mfn,0 , t, memaccess[a.hvmmem_access]); -p2m_unlock (p2m); -if ( !success ) - goto param_fail5; - } - - rc =0 ; + rc =p2m_set_mem_access (d, a.first_pfn, a.nr, a.hvmmem_access); param_fail5:rcu_unlock_domain (d);
@@ -3887,23 +3843,7 @@ long do_hvm_op(unsigned long op, XEN_GUE {struct xen_hvm_get_mem_access a;struct domain *d; -struct p2m_domain *p2m; -p2m_type_t t; -p2m_access_t ac; -mfn_t mfn; - -/* Interface access to internal p2m accesses */ -hvmmem_access_t memaccess[] = { - HVMMEM_access_n, - HVMMEM_access_r, - HVMMEM_access_w, - HVMMEM_access_rw, - HVMMEM_access_x, - HVMMEM_access_rx, - HVMMEM_access_wx, - HVMMEM_access_rwx, - HVMMEM_access_rx2rw - }; +hvmmem_access_t access;if (copy_from_guest (&a, arg,1 ) )return -EFAULT ;
@@ -3916,30 +3856,15 @@ long do_hvm_op(unsigned long op, XEN_GUEif ( !is_hvm_domain (d) ) goto param_fail6; - p2m =p2m_get_hostp2m (d); - -if ( a.pfn == ~0ull ) - { - a.hvmmem_access = memaccess[p2m->default_access]; - } -else { - rc = -EINVAL ; -if ( (a.pfn >domain_get_maximum_gpfn (d)) ) - goto param_fail6; - - rc = -ESRCH ; - mfn = p2m->get_entry (p2m, a.pfn, &t, &ac, p2m_query); - -if (mfn_x (mfn) ==INVALID_MFN ) - goto param_fail6; - - rc = -ERANGE ; -if ( ac >=ARRAY_SIZE (memaccess) ) - goto param_fail6; - - a.hvmmem_access = memaccess[ac]; - } - + rc = -EINVAL ; +if ( (a.pfn >domain_get_maximum_gpfn (d)) && a.pfn != ~0ull ) + goto param_fail6; + + rc =p2m_get_mem_access (d, a.pfn, &access); +if ( rc !=0 ) + goto param_fail6; + + a.hvmmem_access = access; rc =copy_to_guest (arg, &a,1 ) ? -EFAULT :0 ; param_fail6:
xen/arch/x86/mm/p2m.c +95 -0
101 lines not on this page · raw message
xen/include/asm-x86/p2m.h +11 -0
@@ -553,6 +553,17 @@ void p2m_mem_access_check(unsigned long bool_t access_r, bool_t access_w, bool_t access_x);/* Resumes the running of the VCPU, restarting the last instruction */ void p2m_mem_access_resume (struct p2m_domain *p2m); + +/* Set access type for a region of pfns. +* If start_pfn == -1ul, sets the default access type */ +int p2m_set_mem_access (struct domain *d,unsigned long start_pfn, +uint32_t nr,hvmmem_access_t access); + +/* Get access type for a pfn +* If pfn == -1ul, gets the default access type */ +int p2m_get_mem_access (struct domain *d,unsigned long pfn, +hvmmem_access_t *access); +#else static inline void p2m_mem_access_check(unsigned long gpa, bool_t gla_valid, unsigned long gla, bool_t access_r,
PATCH 1/1 x86/mm/p2m: Fix locking discipline around log-dirty teardown
In reply to Tim Deegan# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1307017012 -3600
# Node ID 51f28a7cbb3d1e42e3592e5dc45041742a100fea # Parent c9ea54b4f49ad9363ef8f08fa984f2900dc147e0 x86/mm/p2m: Fix locking discipline around log-dirty teardown.
It's not safe to call paging_free_log_dirty_page with the log-dirty lock held.
xen/arch/x86/mm/paging.c +17 -8
@@ -156,10 +156,16 @@ void paging_free_log_dirty_bitmap(struct {mfn_t *l4, *l3, *l2;int i4, i3, i2; +struct page_list_head to_free; +struct page_info *pg, *tmp;if ( !mfn_valid (d->arch.paging.log_dirty.top) )return ; +INIT_PAGE_LIST_HEAD (&to_free); + +log_dirty_lock (d); + l4 =map_domain_page (mfn_x (d->arch.paging.log_dirty.top));for ( i4 =0 ; i4 <LOGDIRTY_NODE_ENTRIES ; i4++ )
@@ -178,22 +184,28 @@ void paging_free_log_dirty_bitmap(structfor ( i2 =0 ; i2 <LOGDIRTY_NODE_ENTRIES ; i2++ )if (mfn_valid (l2[i2]) ) -paging_free_log_dirty_page (d, l2[i2]); +page_list_add_tail (mfn_to_page (l2[i2]), &to_free);unmap_domain_page (l2); -paging_free_log_dirty_page (d, l3[i3]); +page_list_add_tail (mfn_to_page (l3[i3]), &to_free); }unmap_domain_page (l3); -paging_free_log_dirty_page (d, l4[i4]); +page_list_add_tail (mfn_to_page (l4[i4]), &to_free); }unmap_domain_page (l4); -paging_free_log_dirty_page (d, d->arch.paging.log_dirty.top); +page_list_add_tail (mfn_to_page (d->arch.paging.log_dirty.top), &to_free); d->arch.paging.log_dirty.top =_mfn (INVALID_MFN );ASSERT (d->arch.paging.log_dirty.allocs ==0 ); d->arch.paging.log_dirty.failed_allocs =0 ; + +log_dirty_unlock (d); + +/* Return the memory now that we're not holding the log-dirty lock */ +page_list_for_each_safe (pg, tmp, &to_free) +paging_free_log_dirty_page (d,page_to_mfn (pg)); }int paging_log_dirty_enable (struct domain *d)
@@ -217,10 +229,8 @@ int paging_log_dirty_disable(struct domadomain_pause (d);/* Safe because the domain is paused. */ ret = d->arch.paging.log_dirty.disable_log_dirty (d); -log_dirty_lock (d);if ( !paging_mode_log_dirty (d) )paging_free_log_dirty_bitmap (d); -log_dirty_unlock (d);domain_unpause (d);return ret;
@@ -672,10 +682,9 @@ void paging_log_dirty_init(struct domain/* This function fress log dirty bitmap resources. */ static void paging_log_dirty_teardown (struct domain *d) { -log_dirty_lock (d);paging_free_log_dirty_bitmap (d); -log_dirty_unlock (d); } +/************************************************/ /* CODE FOR PAGING SUPPORT */ /************************************************/
PATCH 1/1 x86/mm: dedup the various copies of the shadow lock functions
In reply to Tim Deegan# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1307017012 -3600
# Node ID d6518e8670ab15d5a9ec49b500ecf6e67442d3a8 # Parent 51f28a7cbb3d1e42e3592e5dc45041742a100fea x86/mm: dedup the various copies of the shadow lock functions
Define the lock and unlock functions once, and list all the locks in one place so (a) it's obvious what the locking discipline is and (b) none of the locks are visible to non-mm code. Automatically enforce that these locks never get taken in the wrong order.
xen/arch/x86/hvm/vmx/vmx.c +0 -1
@@ -1215,7 +1215,6 @@ void ept_sync_domain(struct domain *d)return ;ASSERT (local_irq_is_enabled ()); -ASSERT (p2m_locked_by_me (p2m_get_hostp2m (d)));/* * Flush active cpus synchronously. Flush others the next time this domain
xen/arch/x86/mm/hap/hap.c +1 -1
@@ -572,7 +572,7 @@ static void hap_destroy_monitor_table(st/************************************************/ void hap_domain_init (struct domain *d) { -hap_lock_init (d); +mm_lock_init (&d->arch.paging.hap.lock);INIT_PAGE_LIST_HEAD (&d->arch.paging.hap.freelist); }
xen/arch/x86/mm/hap/private.h +2 -0
@@ -20,6 +20,8 @@#ifndef __HAP_PRIVATE_H__#define __HAP_PRIVATE_H__ +#include "../mm-locks.h" +/********************************************/ /* GUEST TRANSLATION FUNCS */ /********************************************/
xen/arch/x86/mm/mem_sharing.c +4 -40
66 lines not on this page · raw message
xen/arch/x86/mm/mm-locks.h new file +161 -0
161 lines not on this page · raw message
xen/arch/x86/mm/p2m-ept.c +2 -0
@@ -32,6 +32,8 @@#include <xen/keyhandler.h> #include <xen/softirq.h> +#include "mm-locks.h" +#define atomic_read_ept_entry (__pepte) \ ( (ept_entry_t) { .epte = atomic_read64(&(__pepte)->epte) } )#define atomic_write_ept_entry (__pepte, __epte) \
xen/arch/x86/mm/p2m-pod.c +3 -2
@@ -32,7 +32,8 @@#include <xen/event.h> #include <asm/hvm/nestedhvm.h> #include <asm/hvm/svm/amd-iommu-proto.h> - + +#include "mm-locks.h" /* Override macros from asm/page.h to make them work with mfn_t */ #undef mfn_to_page
@@ -375,7 +376,7 @@ p2m_pod_empty_cache(struct domain *d)/* After this barrier no new PoD activities can happen. */ BUG_ON (!d->is_dying); -spin_barrier (&p2m->lock); +spin_barrier (&p2m->lock.lock);spin_lock (&d->page_alloc_lock);
xen/arch/x86/mm/p2m-pt.c +2 -0
@@ -38,6 +38,8 @@#include <asm/hvm/nestedhvm.h> #include <asm/hvm/svm/amd-iommu-proto.h> +#include "mm-locks.h" +/* Override macros from asm/page.h to make them work with mfn_t */ #undef mfn_to_page#define mfn_to_page (_m) __mfn_to_page(mfn_x(_m))
xen/arch/x86/mm/p2m.c +4 -2
@@ -37,6 +37,8 @@#include <asm/hvm/nestedhvm.h> #include <asm/hvm/svm/amd-iommu-proto.h> +#include "mm-locks.h" +/* turn on/off 1GB host page table support for hap, default on */ static bool_t __read_mostly opt_hap_1gb =1 ;boolean_param ("hap_1gb" , opt_hap_1gb);
@@ -70,7 +72,7 @@ boolean_param("hap_2mb", opt_hap_2mb);static void p2m_initialise (struct domain *d,struct p2m_domain *p2m) {memset (p2m,0 ,sizeof (*p2m)); -p2m_lock_init (p2m); +mm_lock_init (&p2m->lock);INIT_PAGE_LIST_HEAD (&p2m->pages);INIT_PAGE_LIST_HEAD (&p2m->pod.super);INIT_PAGE_LIST_HEAD (&p2m->pod.single);
@@ -95,7 +97,7 @@ p2m_init_nestedp2m(struct domain *d)uint8_t i;struct p2m_domain *p2m; -nestedp2m_lock_init (d); +mm_lock_init (&d->arch.nested_p2m_lock);for (i =0 ; i <MAX_NESTEDP2M ; i++) { d->arch.nested_p2m[i] = p2m = xmalloc(struct p2m_domain);if (p2m ==NULL )
xen/arch/x86/mm/paging.c +9 -47
80 lines not on this page · raw message
xen/arch/x86/mm/shadow/common.c +1 -1
@@ -45,7 +45,7 @@ DEFINE_PER_CPU(uint32_t,trace_shadow_pat* Called for every domain from arch_domain_create() */ void shadow_domain_init (struct domain *d,unsigned int domcr_flags) { -shadow_lock_init (d); +mm_lock_init (&d->arch.paging.shadow.lock);INIT_PAGE_LIST_HEAD (&d->arch.paging.shadow.freelist);INIT_PAGE_LIST_HEAD (&d->arch.paging.shadow.pinned_shadows);
xen/arch/x86/mm/shadow/multi.c +1 -1
@@ -3136,7 +3136,7 @@ static int sh_page_fault(struct vcpu *v,if (unlikely (shadow_locked_by_me (d)) ) {SHADOW_ERROR ("Recursive shadow fault: lock was taken by %s\n" , - d->arch.paging.shadow.locker_function); + d->arch.paging.shadow.lock.locker_function);return 0 ; }
xen/arch/x86/mm/shadow/private.h +1 -51
64 lines not on this page · raw message
xen/include/asm-x86/domain.h +5 -12
@@ -91,9 +91,8 @@ void hypercall_page_initialise(struct do/* shadow paging extension */ /************************************************/ struct shadow_domain { -spinlock_t lock;/* shadow domain lock */ -int locker;/* processor which holds the lock */ -const char *locker_function;/* Func that took it */ +mm_lock_t lock;/* shadow domain lock */ +unsigned int opt_flags;/* runtime tunable optimizations on/off */ struct page_list_head pinned_shadows;
@@ -159,9 +158,7 @@ struct shadow_vcpu {/* hardware assisted paging */ /************************************************/ struct hap_domain { -spinlock_t lock; -int locker; -const char *locker_function; +mm_lock_t lock;struct page_list_head freelist;unsigned int total_pages;/* number of pages allocated */
@@ -174,9 +171,7 @@ struct hap_domain {/************************************************/ struct log_dirty_domain {/* log-dirty lock */ -spinlock_t lock; -int locker;/* processor that holds the lock */ -const char *locker_function;/* func that took it */ +mm_lock_t lock;/* log-dirty radix tree to record dirty pages */ mfn_t top;
@@ -280,9 +275,7 @@ struct arch_domain/* nestedhvm: translate l2 guest physical to host physical */ struct p2m_domain *nested_p2m[MAX_NESTEDP2M ]; -spinlock_t nested_p2m_lock; -int nested_p2m_locker; -const char *nested_p2m_function; +mm_lock_t nested_p2m_lock;/* NB. protected by d->event_lock and by irq_desc[irq].lock */ struct radix_tree_root irq_pirq;
xen/include/asm-x86/hap.h +0 -35
@@ -47,41 +47,6 @@ hap_unmap_domain_page(void *p) }/************************************************/ -/* locking for hap code */ -/************************************************/ -#define hap_lock_init (_d) \ - do { \ - spin_lock_init(&(_d)->arch.paging.hap.lock); \ - (_d)->arch.paging.hap.locker = -1; \ - (_d)->arch.paging.hap.locker_function = "nobody"; \ - } while (0) - -#define hap_locked_by_me (_d) \ - (current->processor == (_d)->arch.paging.hap.locker) - -#define hap_lock (_d) \ - do { \ - if ( unlikely((_d)->arch.paging.hap.locker == current->processor) )\ - { \ - printk("Error: hap lock held by %s\n", \ - (_d)->arch.paging.hap.locker_function); \ - BUG(); \ - } \ - spin_lock(&(_d)->arch.paging.hap.lock); \ - ASSERT((_d)->arch.paging.hap.locker == -1); \ - (_d)->arch.paging.hap.locker = current->processor; \ - (_d)->arch.paging.hap.locker_function = __func__; \ - } while (0) - -#define hap_unlock (_d) \ - do { \ - ASSERT((_d)->arch.paging.hap.locker == current->processor); \ - (_d)->arch.paging.hap.locker = -1; \ - (_d)->arch.paging.hap.locker_function = "nobody"; \ - spin_unlock(&(_d)->arch.paging.hap.lock); \ - } while (0) - -/************************************************/ /* hap domain level functions */ /************************************************/ void hap_domain_init (struct domain *d);
xen/include/asm-x86/mm.h +9 -0
@@ -4,6 +4,7 @@#include <xen/config.h> #include <xen/list.h> +#include <xen/spinlock.h> #include <asm/io.h> #include <asm/uaccess.h>
@@ -597,4 +598,12 @@ unsigned long domain_get_maximum_gpfn(stextern struct domain *dom_xen, *dom_io, *dom_cow;/* for vmcoreinfo */ +/* Definition of an mm lock: spinlock with extra fields for debugging */ +typedef struct mm_lock { +spinlock_t lock; +int unlock_level; +int locker;/* processor which holds the lock */ +const char *locker_function;/* func that took it */ +}mm_lock_t ; +#endif /* __ASM_X86_MM_H__ */
xen/include/asm-x86/p2m.h +1 -77
90 lines not on this page · raw message
PATCH 1/1 x86/mm: Make MM locks recursive
In reply to Tim Deegan# HG changeset patch
# User Tim Deegan <[email protected]> # Date 1307017012 -3600
# Node ID 64398d14dcd6e720ac6908ee5ae284b03832e8bc # Parent d6518e8670ab15d5a9ec49b500ecf6e67442d3a8 x86/mm: Make MM locks recursive.
This replaces a lot of open coded 'if (!locked) {lock()}' instances by making the mm locks recursive locks, but only allowing them to be taken recursively in the places that they were before.
xen/arch/x86/mm/hap/hap.c +4 -13
@@ -277,13 +277,10 @@ static void hap_free(struct domain *d, mstatic struct page_info *hap_alloc_p2m_page (struct domain *d) {struct page_info *pg; -int do_locking;/* This is called both from the p2m code (which never holds the * hap lock) and the log-dirty code (which sometimes does). */ - do_locking = !hap_locked_by_me (d); -if ( do_locking ) -hap_lock (d); +hap_lock_recursive (d); pg =hap_alloc (d);#if CONFIG_PAGING_LEVELS ==3
@@ -314,20 +311,15 @@ static struct page_info *hap_alloc_p2m_p pg->count_info |=1 ; } -if ( do_locking ) -hap_unlock (d); +hap_unlock (d);return pg; }static void hap_free_p2m_page (struct domain *d,struct page_info *pg) { -int do_locking; -/* This is called both from the p2m code (which never holds the * hap lock) and the log-dirty code (which sometimes does). */ - do_locking = !hap_locked_by_me (d); -if ( do_locking ) -hap_lock (d); +hap_lock_recursive (d);ASSERT (page_get_owner (pg) == d);/* Should have just the one ref we gave it in alloc_p2m_page() */
@@ -345,8 +337,7 @@ static void hap_free_p2m_page(struct domhap_free (d,page_to_mfn (pg));ASSERT (d->arch.paging.hap.p2m_pages >=0 ); -if ( do_locking ) -hap_unlock (d); +hap_unlock (d); }/* Return the size of the pool, rounded up to the nearest MB */
xen/arch/x86/mm/mm-locks.h +36 -29
99 lines not on this page · raw message
xen/arch/x86/mm/p2m-ept.c +5 -9
@@ -47,26 +47,22 @@ static int ept_pod_check_and_populate(st ept_entry_t *entry, int order, p2m_query_t q) { - /* Only take the lock if we don't already have it. Otherwise it - * wouldn't be safe to do p2m lookups with the p2m lock held */ - int do_locking = !p2m_locked_by_me(p2m); int r; -if ( do_locking ) -p2m_lock (p2m); +/* This is called from the p2m lookups, which can happen with or +* without the lock hed. */ +p2m_lock_recursive (p2m);/* Check to make sure this is still PoD */ if ( entry->sa_p2mt != p2m_populate_on_demand ) { -if ( do_locking ) -p2m_unlock (p2m); +p2m_unlock (p2m);return 0 ; } r =p2m_pod_demand_populate (p2m, gfn, order, q); -if ( do_locking ) -p2m_unlock (p2m); +p2m_unlock (p2m);return r; }
xen/arch/x86/mm/p2m-pt.c +5 -10
@@ -478,29 +478,24 @@ static int p2m_pod_check_and_populate(st l1_pgentry_t *p2m_entry, int order, p2m_query_t q) { - /* Only take the lock if we don't already have it. Otherwise it - * wouldn't be safe to do p2m lookups with the p2m lock held */ - int do_locking = !p2m_locked_by_me(p2m); int r; -if ( do_locking ) -p2m_lock (p2m); - +/* This is called from the p2m lookups, which can happen with or +* without the lock hed. */ +p2m_lock_recursive (p2m);audit_p2m (p2m,1 );/* Check to make sure this is still PoD */ if (p2m_flags_to_type (l1e_get_flags (*p2m_entry)) != p2m_populate_on_demand ) { -if ( do_locking ) -p2m_unlock (p2m); +p2m_unlock (p2m);return 0 ; } r =p2m_pod_demand_populate (p2m, gfn, order, q);audit_p2m (p2m,1 ); -if ( do_locking ) -p2m_unlock (p2m); +p2m_unlock (p2m);return r; }
xen/arch/x86/mm/shadow/common.c +18 -46
188 lines not on this page · raw message
xen/arch/x86/mm/shadow/multi.c +9 -10
@@ -1979,7 +1979,7 @@ static shadow_l1e_t * shadow_get_and_cre/* All pages walked are now pagetables. Safe to resync pages in case level 4 or 3 shadows were set. */ if ( resync ) -shadow_resync_all (v,0 ); +shadow_resync_all (v);#endif /* Now follow it down a level. Guaranteed to succeed. */
@@ -2273,7 +2273,7 @@ static int validate_gl4e(struct vcpu *v,#if (SHADOW_OPTIMIZATIONS &SHOPT_OUT_OF_SYNC )if (mfn_valid (sl3mfn) ) -shadow_resync_all (v,0 ); +shadow_resync_all (v);#endif }l4e_propagate_from_guest (v, new_gl4e, sl3mfn, &new_sl4e, ft_prefetch);
@@ -2330,7 +2330,7 @@ static int validate_gl3e(struct vcpu *v,#if (SHADOW_OPTIMIZATIONS &SHOPT_OUT_OF_SYNC )if (mfn_valid (sl2mfn) ) -shadow_resync_all (v,0 ); +shadow_resync_all (v);#endif }l3e_propagate_from_guest (v, new_gl3e, sl2mfn, &new_sl3e, ft_prefetch);
@@ -4172,15 +4172,15 @@ sh_update_cr3(struct vcpu *v, int do_locreturn ; } +if ( do_locking )shadow_lock (v->domain); +#if (SHADOW_OPTIMIZATIONS &SHOPT_OUT_OF_SYNC )/* Need to resync all the shadow entries on a TLB flush. Resync * current vcpus OOS pages before switching to the new shadow * tables so that the VA hint is still valid. */ -shadow_resync_current_vcpu (v, do_locking); +shadow_resync_current_vcpu (v);#endif -if ( do_locking )shadow_lock (v->domain); -ASSERT (shadow_locked_by_me (v->domain));ASSERT (v->arch.paging.mode);
@@ -4406,17 +4406,16 @@ sh_update_cr3(struct vcpu *v, int do_loc v->arch.paging.last_write_emul_ok =0 ;#endif -/* Release the lock, if we took it (otherwise it's the caller's problem) */ -if ( do_locking )shadow_unlock (v->domain); -#if (SHADOW_OPTIMIZATIONS &SHOPT_OUT_OF_SYNC )/* Need to resync all the shadow entries on a TLB flush. We only * update the shadows, leaving the pages out of sync. Also, we try * to skip synchronization of shadows not mapped in the new * tables. */ -shadow_sync_other_vcpus (v, do_locking); +shadow_sync_other_vcpus (v);#endif +/* Release the lock, if we took it (otherwise it's the caller's problem) */ +if ( do_locking )shadow_unlock (v->domain); }
xen/arch/x86/mm/shadow/private.h +7 -19
@@ -388,36 +388,24 @@ int sh_remove_write_access_from_sl1p(str/* Pull all out-of-sync shadows back into sync. If skip != 0, we try * to avoid resyncing where we think we can get away with it. */ -void sh_resync_all (struct vcpu *v,int skip,int this,int others,int do_locking); +void sh_resync_all (struct vcpu *v,int skip,int this,int others);static inline void -shadow_resync_all (struct vcpu *v,int do_locking) +shadow_resync_all (struct vcpu *v) { -sh_resync_all (v, -0 /* skip */ , -1 /* this */ , -1 /* others */ , - do_locking); +sh_resync_all (v,0 /* skip */ ,1 /* this */ ,1 /* others */ ); }static inline void -shadow_resync_current_vcpu (struct vcpu *v,int do_locking) +shadow_resync_current_vcpu (struct vcpu *v) { -sh_resync_all (v, -0 /* skip */ , -1 /* this */ , -0 /* others */ , - do_locking); +sh_resync_all (v,0 /* skip */ ,1 /* this */ ,0 /* others */ ); }static inline void -shadow_sync_other_vcpus (struct vcpu *v,int do_locking) +shadow_sync_other_vcpus (struct vcpu *v) { -sh_resync_all (v, -1 /* skip */ , -0 /* this */ , -1 /* others */ , - do_locking); +sh_resync_all (v,1 /* skip */ ,0 /* this */ ,1 /* others */ ); }void oos_audit_hash_is_present (struct domain *d,mfn_t gmfn);
PATCH 1/1 x86/mm: merge the shadow, hap and log-dirty locks into a single paging lock
In reply to Tim Deegan# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1307017012 -3600
# Node ID 2bbed46eb10ce80e920506714f7e328193a23b52
# Parent 64398d14dcd6e720ac6908ee5ae284b03832e8bc
x86/mm: merge the shadow, hap and log-dirty locks into a single paging lock.
This will allow us to simplify the locking around calls between hap/shadow and log-dirty code. Many log-dirty paths already need the shadow or HAP lock so it shouldn't increase contention that much.
xen/arch/x86/mm/hap/hap.c +30 -31
@@ -65,9 +65,9 @@ static int hap_enable_vram_tracking(strureturn -EINVAL ;/* turn on PG_log_dirty bit in paging mode */ -hap_lock (d); +paging_lock (d); d->arch.paging.mode |= PG_log_dirty; -hap_unlock (d); +paging_unlock (d);/* set l1e entries of P2M table to be read-only. */ for (i = dirty_vram->begin_pfn; i < dirty_vram->end_pfn; i++)
@@ -85,9 +85,9 @@ static int hap_disable_vram_tracking(strif ( !dirty_vram )return -EINVAL ; -hap_lock (d); +paging_lock (d); d->arch.paging.mode &= ~PG_log_dirty; -hap_unlock (d); +paging_unlock (d);/* set l1e entries of P2M table with normal mode */ for (i = dirty_vram->begin_pfn; i < dirty_vram->end_pfn; i++)
@@ -196,9 +196,9 @@ param_fail:static int hap_enable_log_dirty (struct domain *d) {/* turn on PG_log_dirty bit in paging mode */ -hap_lock (d); +paging_lock (d); d->arch.paging.mode |= PG_log_dirty; -hap_unlock (d); +paging_unlock (d);/* set l1e entries of P2M table to be read-only. */ p2m_change_entry_type_global (d, p2m_ram_rw, p2m_ram_logdirty);
@@ -208,9 +208,9 @@ static int hap_enable_log_dirty(struct dstatic int hap_disable_log_dirty (struct domain *d) { -hap_lock (d); +paging_lock (d); d->arch.paging.mode &= ~PG_log_dirty; -hap_unlock (d); +paging_unlock (d);/* set l1e entries of P2M table with normal mode */ p2m_change_entry_type_global (d, p2m_ram_logdirty, p2m_ram_rw);
@@ -248,7 +248,7 @@ static struct page_info *hap_alloc(strucstruct page_info *pg =NULL ;void *p; -ASSERT (hap_locked_by_me (d)); +ASSERT (paging_locked_by_me (d)); pg =page_list_remove_head (&d->arch.paging.hap.freelist);if (unlikely (!pg) )
@@ -268,7 +268,7 @@ static void hap_free(struct domain *d, m {struct page_info *pg =mfn_to_page (mfn); -ASSERT (hap_locked_by_me (d)); +ASSERT (paging_locked_by_me (d)); d->arch.paging.hap.free_pages++;page_list_add_tail (pg, &d->arch.paging.hap.freelist);
@@ -279,8 +279,8 @@ static struct page_info *hap_alloc_p2m_pstruct page_info *pg;/* This is called both from the p2m code (which never holds the -* hap lock) and the log-dirty code (which sometimes does). */ -hap_lock_recursive (d); +* paging lock) and the log-dirty code (which sometimes does). */ +paging_lock_recursive (d); pg =hap_alloc (d);#if CONFIG_PAGING_LEVELS ==3
@@ -311,15 +311,15 @@ static struct page_info *hap_alloc_p2m_p pg->count_info |=1 ; } -hap_unlock (d); +paging_unlock (d);return pg; }static void hap_free_p2m_page (struct domain *d,struct page_info *pg) {/* This is called both from the p2m code (which never holds the -* hap lock) and the log-dirty code (which sometimes does). */ -hap_lock_recursive (d); +* paging lock) and the log-dirty code (which sometimes does). */ +paging_lock_recursive (d);ASSERT (page_get_owner (pg) == d);/* Should have just the one ref we gave it in alloc_p2m_page() */
@@ -337,7 +337,7 @@ static void hap_free_p2m_page(struct domhap_free (d,page_to_mfn (pg));ASSERT (d->arch.paging.hap.p2m_pages >=0 ); -hap_unlock (d); +paging_unlock (d); }/* Return the size of the pool, rounded up to the nearest MB */
@@ -358,7 +358,7 @@ hap_set_allocation(struct domain *d, uns {struct page_info *pg; -ASSERT (hap_locked_by_me (d)); +ASSERT (paging_locked_by_me (d));if ( pages < d->arch.paging.hap.p2m_pages ) pages =0 ;
@@ -563,7 +563,6 @@ static void hap_destroy_monitor_table(st/************************************************/ void hap_domain_init (struct domain *d) { -mm_lock_init (&d->arch.paging.hap.lock);INIT_PAGE_LIST_HEAD (&d->arch.paging.hap.freelist); }
@@ -587,9 +586,9 @@ int hap_enable(struct domain *d, u32 modif ( old_pages ==0 ) {unsigned int r; -hap_lock (d); +paging_lock (d); r =hap_set_allocation (d,256 ,NULL ); -hap_unlock (d); +paging_unlock (d);if ( r !=0 ) {hap_set_allocation (d,0 ,NULL );
@@ -638,10 +637,10 @@ void hap_final_teardown(struct domain *dp2m_teardown (p2m_get_hostp2m (d));/* Free any memory that the p2m teardown released */ -hap_lock (d); +paging_lock (d);hap_set_allocation (d,0 ,NULL );ASSERT (d->arch.paging.hap.p2m_pages ==0 ); -hap_unlock (d); +paging_unlock (d); }void hap_teardown (struct domain *d)
@@ -652,8 +651,8 @@ void hap_teardown(struct domain *d)ASSERT (d->is_dying);ASSERT (d != current->domain); -if ( !hap_locked_by_me (d) ) -hap_lock (d);/* Keep various asserts happy */ +if ( !paging_locked_by_me (d) ) +paging_lock (d);/* Keep various asserts happy */ if (paging_mode_enabled (d) ) {
@@ -689,7 +688,7 @@ void hap_teardown(struct domain *d) d->arch.paging.mode &= ~PG_log_dirty; -hap_unlock (d); +paging_unlock (d); } int hap_domctl(struct domain *d, xen_domctl_shadow_op_t *sc,
@@ -700,9 +699,9 @@ int hap_domctl(struct domain *d, xen_domswitch ( sc->op ) {case XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION : -hap_lock (d); +paging_lock (d); rc =hap_set_allocation (d, sc->mb << (20 -PAGE_SHIFT ), &preempted); -hap_unlock (d); +paging_unlock (d);if ( preempted )/* Not finished. Set up to re-run the call. */ rc = hypercall_create_continuation(__HYPERVISOR_domctl, "h",
@@ -789,7 +788,7 @@ static void hap_update_paging_modes(stru {struct domain *d = v->domain; -hap_lock (d); +paging_lock (d); v->arch.paging.mode =hap_paging_get_mode (v);
@@ -804,7 +803,7 @@ static void hap_update_paging_modes(stru/* CR3 is effectively updated by a mode change. Flush ASIDs, etc. */ hap_update_cr3 (v,0 ); -hap_unlock (d); +paging_unlock (d); }#if CONFIG_PAGING_LEVELS ==3
@@ -861,7 +860,7 @@ hap_write_p2m_entry(struct vcpu *v, unsi* a hypercall which passes a domain and chooses mostly the first * vcpu. */ -hap_lock (d); +paging_lock (d); old_flags =l1e_get_flags (*p);if (nestedhvm_enabled (d) && (old_flags & _PAGE_PRESENT) ) {
@@ -886,7 +885,7 @@ hap_write_p2m_entry(struct vcpu *v, unsip2m_install_entry_in_monitors (d, (l3_pgentry_t *)p);#endif -hap_unlock (d); +paging_unlock (d);if ( flush_nestedp2m )p2m_flush_nestedp2m (d);
xen/arch/x86/mm/hap/nested_hap.c +2 -2
@@ -82,14 +82,14 @@ nestedp2m_write_p2m_entry(struct p2m_domstruct domain *d = p2m->domain;uint32_t old_flags; -hap_lock (d); +paging_lock (d); old_flags =l1e_get_flags (*p);safe_write_pte (p, new);if (old_flags & _PAGE_PRESENT)nestedhvm_vmcx_flushtlb (p2m); -hap_unlock (d); +paging_unlock (d); }/********************************************/
xen/arch/x86/mm/mm-locks.h +14 -43
69 lines not on this page · raw message
xen/arch/x86/mm/paging.c +17 -16
@@ -126,7 +126,7 @@ void paging_free_log_dirty_bitmap(structINIT_PAGE_LIST_HEAD (&to_free); -log_dirty_lock (d); +paging_lock (d); l4 =map_domain_page (mfn_x (d->arch.paging.log_dirty.top));
@@ -163,7 +163,7 @@ void paging_free_log_dirty_bitmap(structASSERT (d->arch.paging.log_dirty.allocs ==0 ); d->arch.paging.log_dirty.failed_allocs =0 ; -log_dirty_unlock (d); +paging_unlock (d);/* Return the memory now that we're not holding the log-dirty lock */ page_list_for_each_safe (pg, tmp, &to_free)
@@ -239,7 +239,8 @@ void paging_mark_dirty(struct domain *d, new_mfn =_mfn (INVALID_MFN ); again: -log_dirty_lock (d); +/* Recursive: this is called from inside the shadow code */ +paging_lock_recursive (d); l4 =paging_map_log_dirty_bitmap (d);if (unlikely (!l4) )
@@ -300,13 +301,13 @@ again: d->arch.paging.log_dirty.dirty_count++; } -log_dirty_unlock (d); +paging_unlock (d);if (mfn_valid (new_mfn) )paging_free_log_dirty_page (d, new_mfn);return ; oom: -log_dirty_unlock (d); +paging_unlock (d); new_mfn =paging_new_log_dirty_page (d);if ( !mfn_valid (new_mfn) )/* we've already recorded the failed allocation */
@@ -323,7 +324,8 @@ int paging_mfn_is_dirty(struct domain *dunsigned long *l1;int rv =0 ; -log_dirty_lock (d); +/* Recursive: this is called from inside the shadow code */ +paging_lock_recursive (d);ASSERT (paging_mode_log_dirty (d));/* We /really/ mean PFN here, even for non-translated guests. */
@@ -359,7 +361,7 @@ int paging_mfn_is_dirty(struct domain *dunmap_domain_page (l1); out: -log_dirty_unlock (d); +paging_unlock (d);return rv; }
@@ -375,7 +377,7 @@ int paging_log_dirty_op(struct domain *dint i4, i3, i2;domain_pause (d); -log_dirty_lock (d); +paging_lock (d); clean = (sc->op ==XEN_DOMCTL_SHADOW_OP_CLEAN );
@@ -456,7 +458,7 @@ int paging_log_dirty_op(struct domain *dif ( pages < sc->pages ) sc->pages = pages; -log_dirty_unlock (d); +paging_unlock (d);if ( clean ) {
@@ -468,7 +470,7 @@ int paging_log_dirty_op(struct domain *dreturn rv; out: -log_dirty_unlock (d); +paging_unlock (d);domain_unpause (d);return rv; }
@@ -486,7 +488,7 @@ int paging_log_dirty_range(struct domainint i2, i3, i4; d->arch.paging.log_dirty.clean_dirty_bitmap (d); -log_dirty_lock (d); +paging_lock (d); PAGING_DEBUG(LOGDIRTY, "log-dirty-range: dom %u faults=%u dirty=%u\n", d->domain_id,
@@ -611,12 +613,12 @@ int paging_log_dirty_range(struct domainif ( l4 )unmap_domain_page (l4); -log_dirty_unlock (d); +paging_unlock (d);return rv; out: -log_dirty_unlock (d); +paging_unlock (d);return rv; }
@@ -632,9 +634,6 @@ void paging_log_dirty_init(struct domainint (*disable_log_dirty)(struct domain *d), void (*clean_dirty_bitmap)(struct domain *d)) { - /* We initialize log dirty lock first */ - mm_lock_init(&d->arch.paging.log_dirty.lock); - d->arch.paging.log_dirty.enable_log_dirty = enable_log_dirty; d->arch.paging.log_dirty.disable_log_dirty = disable_log_dirty; d->arch.paging.log_dirty.clean_dirty_bitmap = clean_dirty_bitmap;
@@ -658,6 +657,8 @@ int paging_domain_init(struct domain *d,if ( (rc =p2m_init (d)) !=0 )return rc; +mm_lock_init (&d->arch.paging.lock); +/* The order of the *_init calls below is important, as the later * ones may rewrite some common fields. Shadow pagetables are the * default... */
xen/arch/x86/mm/shadow/common.c +70 -73
503 lines not on this page · raw message
xen/arch/x86/mm/shadow/multi.c +38 -38
283 lines not on this page · raw message
xen/arch/x86/mm/shadow/private.h +2 -2
@@ -533,7 +533,7 @@ static inline int sh_get_ref(struct vcpureturn 0 ; } -/* Guarded by the shadow lock, so no need for atomic update */ +/* Guarded by the paging lock, so no need for atomic update */ sp->u.sh.count = nx;/* We remember the first shadow entry that points to each shadow. */
@@ -573,7 +573,7 @@ static inline void sh_put_ref(struct vcpBUG (); } -/* Guarded by the shadow lock, so no need for atomic update */ +/* Guarded by the paging lock, so no need for atomic update */ sp->u.sh.count = nx;if (unlikely (nx ==0 ) )
xen/arch/x86/mm/shadow/types.h +1 -1
@@ -292,7 +292,7 @@ static inline shadow_l4e_t shadow_l4e_fr* MMIO emulation, and faults where the guest PTE is not present. We * record these as shadow l1 entries that have reserved bits set in * them, so we can spot them immediately in the fault handler and handle -* them without needing to hold the shadow lock or walk the guest +* them without needing to hold the paging lock or walk the guest * pagetables. * * This is only feasible for PAE and 64bit Xen: 32-bit non-PAE PTEs don't
xen/include/asm-x86/domain.h +3 -7
@@ -91,8 +91,6 @@ void hypercall_page_initialise(struct do/* shadow paging extension */ /************************************************/ struct shadow_domain { -mm_lock_t lock;/* shadow domain lock */ -unsigned int opt_flags;/* runtime tunable optimizations on/off */ struct page_list_head pinned_shadows;
@@ -158,8 +156,6 @@ struct shadow_vcpu {/* hardware assisted paging */ /************************************************/ struct hap_domain { -mm_lock_t lock; -struct page_list_head freelist;unsigned int total_pages;/* number of pages allocated */ unsigned int free_pages;/* number of pages on freelists */
@@ -170,9 +166,6 @@ struct hap_domain {/* common paging data structure */ /************************************************/ struct log_dirty_domain { -/* log-dirty lock */ -mm_lock_t lock; -/* log-dirty radix tree to record dirty pages */ mfn_t top;unsigned int allocs;
@@ -189,6 +182,9 @@ struct log_dirty_domain { };struct paging_domain { +/* paging lock */ +mm_lock_t lock; +/* flags to control paging operation */ u32 mode;/* extension for shadow paging support */
xen/include/asm-x86/p2m.h +2 -2
@@ -337,8 +337,8 @@ static inline mfn_t gfn_to_mfn_type(stru/* Syntactic sugar: most callers will use one of these. * N.B. gfn_to_mfn_query() is the _only_ one guaranteed not to take the -* p2m lock; none of the others can be called with the p2m, hap or -* shadow lock held. */ +* p2m lock; none of the others can be called with the p2m or paging +* lock held. */ #define gfn_to_mfn (d, g, t) gfn_to_mfn_type((d), (g), (t), p2m_alloc)#define gfn_to_mfn_query (d, g, t) gfn_to_mfn_type((d), (g), (t), p2m_query)#define gfn_to_mfn_guest (d, g, t) gfn_to_mfn_type((d), (g), (t), p2m_guest)
PATCH 1/1 x86/mm: simplify log-dirty page allocation
In reply to Tim Deegan# HG changeset patch
# User Tim Deegan <[email protected]> # Date 1307017012 -3600
# Node ID 9974012f48be05a981c9db05c544ffd965bd33d9 # Parent 2bbed46eb10ce80e920506714f7e328193a23b52 x86/mm: simplify log-dirty page allocation.
Now that the log-dirty code is covered by the same lock as shadow and hap activity, we no longer need to avoid doing allocs and frees with the lock held. Simplify the code accordingly.
xen/arch/x86/mm/hap/hap.c +2 -2
@@ -279,7 +279,7 @@ static struct page_info *hap_alloc_p2m_pstruct page_info *pg;/* This is called both from the p2m code (which never holds the -* paging lock) and the log-dirty code (which sometimes does). */ +* paging lock) and the log-dirty code (which always does). */ paging_lock_recursive (d); pg =hap_alloc (d);
@@ -318,7 +318,7 @@ static struct page_info *hap_alloc_p2m_pstatic void hap_free_p2m_page (struct domain *d,struct page_info *pg) {/* This is called both from the p2m code (which never holds the -* paging lock) and the log-dirty code (which sometimes does). */ +* paging lock) and the log-dirty code (which always does). */ paging_lock_recursive (d);ASSERT (page_get_owner (pg) == d);
xen/arch/x86/mm/paging.c +47 -89
255 lines not on this page · raw message
xen/arch/x86/mm/shadow/common.c +2 -2
@@ -1612,7 +1612,7 @@ shadow_alloc_p2m_page(struct domain *d)struct page_info *pg;/* This is called both from the p2m code (which never holds the -* paging lock) and the log-dirty code (which sometimes does). */ +* paging lock) and the log-dirty code (which always does). */ paging_lock_recursive (d); if ( d->arch.paging.shadow.total_pages
@@ -1654,7 +1654,7 @@ shadow_free_p2m_page(struct domain *d, spage_set_owner (pg,NULL );/* This is called both from the p2m code (which never holds the -* paging lock) and the log-dirty code (which sometimes does). */ +* paging lock) and the log-dirty code (which always does). */ paging_lock_recursive (d);shadow_free (d,page_to_mfn (pg));
xen/include/asm-x86/paging.h +2 -1
@@ -164,7 +164,8 @@ void paging_log_dirty_init(struct domain/* mark a page as dirty */ void paging_mark_dirty (struct domain *d,unsigned long guest_mfn); -/* is this guest page dirty? */ +/* is this guest page dirty? +* This is called from inside paging code, with the paging lock held. */ int paging_mfn_is_dirty (struct domain *d,mfn_t gmfn);/*
PATCH 1/1 x86/mm/shadow: emulated writes are always guest-originated actions
In reply to Tim Deegan# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1307017012 -3600
# Node ID 840e161428246f0173cb41c2409a0b9481b4a457
# Parent 9974012f48be05a981c9db05c544ffd965bd33d9 x86/mm/shadow: emulated writes are always guest-originated actions and never happen with the paging lock held.
xen/arch/x86/mm/shadow/multi.c +2 -5
@@ -4810,11 +4810,8 @@ static mfn_t emulate_gva_to_mfn(struct v }/* Translate the GFN to an MFN */ -/* PoD: query only if paging lock is held (to avoid deadlock) */ -if (paging_locked_by_me (v->domain) ) - mfn =gfn_to_mfn_query (v->domain,_gfn (gfn), &p2mt); -else - mfn =gfn_to_mfn (v->domain,_gfn (gfn), &p2mt); +ASSERT (!paging_locked_by_me (v->domain)); + mfn =gfn_to_mfn_guest (v->domain,_gfn (gfn), &p2mt);if (p2m_is_readonly (p2mt) )return _mfn (READONLY_GFN );