[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v6.1 3/5] p2m: change write_p2m_entry to return an error code
This is in preparation for also changing p2m_entry_modify to return an error code. No functional change intended. Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx> --- Cc: George Dunlap <george.dunlap@xxxxxxxxxxxxx> Cc: Jan Beulich <jbeulich@xxxxxxxx> Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> Cc: Wei Liu <wei.liu2@xxxxxxxxxx> Cc: Tim Deegan <tim@xxxxxxx> --- Changes since v6: - Fix line wrapping in p2m_next_level. Changes since v5: - Return -EOPNOTSUPP from _write_p2m_entry. - Use an error label in p2m_next_level. Changes since v4: - Handle errors in loops to avoid overwriting the variable containing the error code in non-debug builds. - Change error handling in p2m_next_level so it's done in a single place. Changes since v3: - Use asserts instead of bugs to check return code from write_p2m_entry from callers that don't support or expect write_p2m_entry to fail. Changes since v2: - New in this version. --- xen/arch/x86/mm/hap/hap.c | 4 +- xen/arch/x86/mm/hap/nested_hap.c | 4 +- xen/arch/x86/mm/p2m-pt.c | 73 ++++++++++++++++++++++++++------ xen/arch/x86/mm/paging.c | 12 ++++-- xen/arch/x86/mm/shadow/common.c | 4 +- xen/arch/x86/mm/shadow/none.c | 7 +-- xen/arch/x86/mm/shadow/private.h | 6 +-- xen/include/asm-x86/p2m.h | 4 +- xen/include/asm-x86/paging.h | 8 ++-- 9 files changed, 89 insertions(+), 33 deletions(-) diff --git a/xen/arch/x86/mm/hap/hap.c b/xen/arch/x86/mm/hap/hap.c index 2db7f2c04a..fdf77c59a5 100644 --- a/xen/arch/x86/mm/hap/hap.c +++ b/xen/arch/x86/mm/hap/hap.c @@ -708,7 +708,7 @@ static void hap_update_paging_modes(struct vcpu *v) put_gfn(d, cr3_gfn); } -static void +static int hap_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, l1_pgentry_t *p, l1_pgentry_t new, unsigned int level) { @@ -746,6 +746,8 @@ hap_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, l1_pgentry_t *p, if ( flush_nestedp2m ) p2m_flush_nestedp2m(d); + + return 0; } static unsigned long hap_gva_to_gfn_real_mode( diff --git a/xen/arch/x86/mm/hap/nested_hap.c b/xen/arch/x86/mm/hap/nested_hap.c index d2a07a5c79..abe5958a52 100644 --- a/xen/arch/x86/mm/hap/nested_hap.c +++ b/xen/arch/x86/mm/hap/nested_hap.c @@ -71,7 +71,7 @@ /* NESTED VIRT P2M FUNCTIONS */ /********************************************/ -void +int nestedp2m_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, l1_pgentry_t *p, l1_pgentry_t new, unsigned int level) { @@ -87,6 +87,8 @@ nestedp2m_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, flush_tlb_mask(p2m->dirty_cpumask); paging_unlock(d); + + return 0; } /********************************************/ diff --git a/xen/arch/x86/mm/p2m-pt.c b/xen/arch/x86/mm/p2m-pt.c index 04e9d81cf6..d0f35d8b47 100644 --- a/xen/arch/x86/mm/p2m-pt.c +++ b/xen/arch/x86/mm/p2m-pt.c @@ -184,6 +184,8 @@ p2m_next_level(struct p2m_domain *p2m, void **table, l1_pgentry_t *p2m_entry, new_entry; void *next; unsigned int flags; + int rc; + mfn_t mfn; if ( !(p2m_entry = p2m_find_entry(*table, gfn_remainder, gfn, shift, max)) ) @@ -194,7 +196,7 @@ p2m_next_level(struct p2m_domain *p2m, void **table, /* PoD/paging: Not present doesn't imply empty. */ if ( !flags ) { - mfn_t mfn = p2m_alloc_ptp(p2m, level); + mfn = p2m_alloc_ptp(p2m, level); if ( mfn_eq(mfn, INVALID_MFN) ) return -ENOMEM; @@ -202,13 +204,14 @@ p2m_next_level(struct p2m_domain *p2m, void **table, new_entry = l1e_from_mfn(mfn, P2M_BASE_FLAGS | _PAGE_RW); p2m_add_iommu_flags(&new_entry, level, IOMMUF_readable|IOMMUF_writable); - p2m->write_p2m_entry(p2m, gfn, p2m_entry, new_entry, level + 1); + rc = p2m->write_p2m_entry(p2m, gfn, p2m_entry, new_entry, level + 1); + if ( rc ) + goto error; } else if ( flags & _PAGE_PSE ) { /* Split superpages pages into smaller ones. */ unsigned long pfn = l1e_get_pfn(*p2m_entry); - mfn_t mfn; l1_pgentry_t *l1_entry; unsigned int i; @@ -250,14 +253,21 @@ p2m_next_level(struct p2m_domain *p2m, void **table, { new_entry = l1e_from_pfn(pfn | (i << ((level - 1) * PAGETABLE_ORDER)), flags); - p2m->write_p2m_entry(p2m, gfn, l1_entry + i, new_entry, level); + rc = p2m->write_p2m_entry(p2m, gfn, l1_entry + i, new_entry, level); + if ( rc ) + { + unmap_domain_page(l1_entry); + goto error; + } } unmap_domain_page(l1_entry); new_entry = l1e_from_mfn(mfn, P2M_BASE_FLAGS | _PAGE_RW); p2m_add_iommu_flags(&new_entry, level, IOMMUF_readable|IOMMUF_writable); - p2m->write_p2m_entry(p2m, gfn, p2m_entry, new_entry, level + 1); + rc = p2m->write_p2m_entry(p2m, gfn, p2m_entry, new_entry, level + 1); + if ( rc ) + goto error; } else ASSERT(flags & _PAGE_PRESENT); @@ -268,6 +278,12 @@ p2m_next_level(struct p2m_domain *p2m, void **table, *table = next; return 0; + + error: + ASSERT(rc && mfn_valid(mfn)); + ASSERT_UNREACHABLE(); + p2m_free_ptp(p2m, mfn_to_page(mfn)); + return rc; } /* @@ -321,7 +337,12 @@ static int p2m_pt_set_recalc_range(struct p2m_domain *p2m, if ( (l1e_get_flags(e) & _PAGE_PRESENT) && !needs_recalc(l1, e) ) { set_recalc(l1, e); - p2m->write_p2m_entry(p2m, first_gfn, pent, e, level); + err = p2m->write_p2m_entry(p2m, first_gfn, pent, e, level); + if ( err ) + { + ASSERT_UNREACHABLE(); + goto out; + } } first_gfn += 1UL << (i * PAGETABLE_ORDER); } @@ -392,14 +413,24 @@ static int do_recalc(struct p2m_domain *p2m, unsigned long gfn) !needs_recalc(l1, ent) ) { set_recalc(l1, ent); - p2m->write_p2m_entry(p2m, gfn - remainder, &ptab[i], - ent, level); + err = p2m->write_p2m_entry(p2m, gfn - remainder, &ptab[i], + ent, level); + if ( err ) + { + ASSERT_UNREACHABLE(); + goto out; + } } remainder -= 1UL << ((level - 1) * PAGETABLE_ORDER); } smp_wmb(); clear_recalc(l1, e); - p2m->write_p2m_entry(p2m, gfn, pent, e, level + 1); + err = p2m->write_p2m_entry(p2m, gfn, pent, e, level + 1); + if ( err ) + { + ASSERT_UNREACHABLE(); + goto out; + } } unmap_domain_page((void *)((unsigned long)pent & PAGE_MASK)); } @@ -444,7 +475,8 @@ static int do_recalc(struct p2m_domain *p2m, unsigned long gfn) } else clear_recalc(l1, e); - p2m->write_p2m_entry(p2m, gfn, pent, e, level + 1); + err = p2m->write_p2m_entry(p2m, gfn, pent, e, level + 1); + ASSERT(!err); } out: @@ -595,8 +627,10 @@ p2m_pt_set_entry(struct p2m_domain *p2m, gfn_t gfn_, mfn_t mfn, if ( entry_content.l1 != 0 ) p2m_add_iommu_flags(&entry_content, 0, iommu_pte_flags); - p2m->write_p2m_entry(p2m, gfn, p2m_entry, entry_content, 3); + rc = p2m->write_p2m_entry(p2m, gfn, p2m_entry, entry_content, 3); /* NB: paging_write_p2m_entry() handles tlb flushes properly */ + if ( rc ) + goto out; } else { @@ -633,8 +667,10 @@ p2m_pt_set_entry(struct p2m_domain *p2m, gfn_t gfn_, mfn_t mfn, p2m_add_iommu_flags(&entry_content, 0, iommu_pte_flags); /* level 1 entry */ - p2m->write_p2m_entry(p2m, gfn, p2m_entry, entry_content, 1); + rc = p2m->write_p2m_entry(p2m, gfn, p2m_entry, entry_content, 1); /* NB: paging_write_p2m_entry() handles tlb flushes properly */ + if ( rc ) + goto out; } else if ( page_order == PAGE_ORDER_2M ) { @@ -669,8 +705,10 @@ p2m_pt_set_entry(struct p2m_domain *p2m, gfn_t gfn_, mfn_t mfn, if ( entry_content.l1 != 0 ) p2m_add_iommu_flags(&entry_content, 0, iommu_pte_flags); - p2m->write_p2m_entry(p2m, gfn, p2m_entry, entry_content, 2); + rc = p2m->write_p2m_entry(p2m, gfn, p2m_entry, entry_content, 2); /* NB: paging_write_p2m_entry() handles tlb flushes properly */ + if ( rc ) + goto out; } /* Track the highest gfn for which we have ever had a valid mapping */ @@ -894,8 +932,15 @@ static void p2m_pt_change_entry_type_global(struct p2m_domain *p2m, if ( (l1e_get_flags(e) & _PAGE_PRESENT) && !needs_recalc(l1, e) ) { + int rc; + set_recalc(l1, e); - p2m->write_p2m_entry(p2m, gfn, &tab[i], e, 4); + rc = p2m->write_p2m_entry(p2m, gfn, &tab[i], e, 4); + if ( rc ) + { + ASSERT_UNREACHABLE(); + break; + } ++changed; } gfn += 1UL << (L4_PAGETABLE_SHIFT - PAGE_SHIFT); diff --git a/xen/arch/x86/mm/paging.c b/xen/arch/x86/mm/paging.c index e6ed3006fe..21db3eceb6 100644 --- a/xen/arch/x86/mm/paging.c +++ b/xen/arch/x86/mm/paging.c @@ -932,18 +932,22 @@ void paging_update_nestedmode(struct vcpu *v) } #endif -void paging_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, - l1_pgentry_t *p, l1_pgentry_t new, - unsigned int level) +int paging_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, + l1_pgentry_t *p, l1_pgentry_t new, + unsigned int level) { struct domain *d = p2m->domain; struct vcpu *v = current; + int rc = 0; + if ( v->domain != d ) v = d->vcpu ? d->vcpu[0] : NULL; if ( likely(v && paging_mode_enabled(d) && paging_get_hostmode(v) != NULL) ) - paging_get_hostmode(v)->write_p2m_entry(p2m, gfn, p, new, level); + rc = paging_get_hostmode(v)->write_p2m_entry(p2m, gfn, p, new, level); else safe_write_pte(p, new); + + return rc; } int paging_set_allocation(struct domain *d, unsigned int pages, bool *preempted) diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c index de7abf7150..c818112360 100644 --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -3176,7 +3176,7 @@ static void sh_unshadow_for_p2m_change(struct domain *d, unsigned long gfn, } } -void +int shadow_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, l1_pgentry_t *p, l1_pgentry_t new, unsigned int level) @@ -3211,6 +3211,8 @@ shadow_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, #endif paging_unlock(d); + + return 0; } /**************************************************************************/ diff --git a/xen/arch/x86/mm/shadow/none.c b/xen/arch/x86/mm/shadow/none.c index 316002771d..a70888bd98 100644 --- a/xen/arch/x86/mm/shadow/none.c +++ b/xen/arch/x86/mm/shadow/none.c @@ -60,11 +60,12 @@ static void _update_paging_modes(struct vcpu *v) ASSERT_UNREACHABLE(); } -static void _write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, - l1_pgentry_t *p, l1_pgentry_t new, - unsigned int level) +static int _write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, + l1_pgentry_t *p, l1_pgentry_t new, + unsigned int level) { ASSERT_UNREACHABLE(); + return -EOPNOTSUPP; } static const struct paging_mode sh_paging_none = { diff --git a/xen/arch/x86/mm/shadow/private.h b/xen/arch/x86/mm/shadow/private.h index 0aaed1edfc..580ef3e29e 100644 --- a/xen/arch/x86/mm/shadow/private.h +++ b/xen/arch/x86/mm/shadow/private.h @@ -372,9 +372,9 @@ extern int sh_remove_write_access(struct domain *d, mfn_t readonly_mfn, unsigned long fault_addr); /* Functions that atomically write PT/P2M entries and update state */ -void shadow_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, - l1_pgentry_t *p, l1_pgentry_t new, - unsigned int level); +int shadow_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, + l1_pgentry_t *p, l1_pgentry_t new, + unsigned int level); /* Update all the things that are derived from the guest's CR0/CR3/CR4. * Called to initialize paging structures if the paging mode diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h index 834d49d2d4..f4ec2becbd 100644 --- a/xen/include/asm-x86/p2m.h +++ b/xen/include/asm-x86/p2m.h @@ -265,7 +265,7 @@ struct p2m_domain { unsigned long last_gfn); void (*memory_type_changed)(struct p2m_domain *p2m); - void (*write_p2m_entry)(struct p2m_domain *p2m, + int (*write_p2m_entry)(struct p2m_domain *p2m, unsigned long gfn, l1_pgentry_t *p, l1_pgentry_t new, unsigned int level); long (*audit_p2m)(struct p2m_domain *p2m); @@ -837,7 +837,7 @@ void p2m_flush_nestedp2m(struct domain *d); /* Flushes the np2m specified by np2m_base (if it exists) */ void np2m_flush_base(struct vcpu *v, unsigned long np2m_base); -void nestedp2m_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, +int nestedp2m_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, l1_pgentry_t *p, l1_pgentry_t new, unsigned int level); /* diff --git a/xen/include/asm-x86/paging.h b/xen/include/asm-x86/paging.h index 7ec09d7b11..18a7eaeca4 100644 --- a/xen/include/asm-x86/paging.h +++ b/xen/include/asm-x86/paging.h @@ -124,7 +124,7 @@ struct paging_mode { void (*update_cr3 )(struct vcpu *v, int do_locking, bool noflush); void (*update_paging_modes )(struct vcpu *v); - void (*write_p2m_entry )(struct p2m_domain *p2m, + int (*write_p2m_entry )(struct p2m_domain *p2m, unsigned long gfn, l1_pgentry_t *p, l1_pgentry_t new, unsigned int level); @@ -340,9 +340,9 @@ static inline void safe_write_pte(l1_pgentry_t *p, l1_pgentry_t new) * we are writing. */ struct p2m_domain; -void paging_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, - l1_pgentry_t *p, l1_pgentry_t new, - unsigned int level); +int paging_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, + l1_pgentry_t *p, l1_pgentry_t new, + unsigned int level); /* * Called from the guest to indicate that the a process is being -- 2.17.2 (Apple Git-113) _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |