|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v4 27/39] arm/p2m: Add altp2m_propagate_change
This commit introduces the function "altp2m_propagate_change" that is
responsible to propagate changes applied to the host's p2m to a specific
or even all altp2m views. In this way, Xen can in-/decrease the guest's
physmem at run-time without leaving the altp2m views with
stalled/invalid entries.
Signed-off-by: Sergej Proskurin <proskurin@xxxxxxxxxxxxx>
---
Cc: Stefano Stabellini <sstabellini@xxxxxxxxxx>
Cc: Julien Grall <julien.grall@xxxxxxx>
---
v3: Cosmetic fixes.
Changed the locking mechanism to "p2m_write_lock" inside the
function "altp2m_reset".
Removed TLB flushing and resetting of the max_mapped_gfn
lowest_mapped_gfn fields within the function "altp2m_reset". These
operations are performed in the function "p2m_flush_table".
Protected altp2m_active(d) check in "altp2m_propagate_change".
The function "altp2m_propagate_change" now decides whether an entry
needs to be dropped out of the altp2m view only if the smfn value
equals INVALID_MFN.
Extended the function "altp2m_propagate_change" so that it returns
an int value to the caller. Also, the function "apply_p2m_changes"
checks the return value and fails the entire operation on error.
Moved the funtion "modify_altp2m_range" out of this commit.
v4: Use the functions "p2m_(set|get)_entry" instead of the helpers
"p2m_lookup_attr" and "modify_altp2m_entry".
---
xen/arch/arm/altp2m.c | 84 ++++++++++++++++++++++++++++++++++++++++++++
xen/arch/arm/p2m.c | 4 +++
xen/include/asm-arm/altp2m.h | 8 +++++
3 files changed, 96 insertions(+)
diff --git a/xen/arch/arm/altp2m.c b/xen/arch/arm/altp2m.c
index 8c3212780a..4883b1323b 100644
--- a/xen/arch/arm/altp2m.c
+++ b/xen/arch/arm/altp2m.c
@@ -123,6 +123,90 @@ int altp2m_set_mem_access(struct domain *d,
return rc;
}
+static inline void altp2m_reset(struct p2m_domain *p2m)
+{
+ p2m_write_lock(p2m);
+ p2m_flush_table(p2m);
+ p2m_write_unlock(p2m);
+}
+
+int altp2m_propagate_change(struct domain *d,
+ gfn_t sgfn,
+ unsigned int page_order,
+ mfn_t smfn,
+ p2m_type_t p2mt,
+ p2m_access_t p2ma)
+{
+ int rc = 0;
+ unsigned int i;
+ unsigned int reset_count = 0;
+ unsigned int last_reset_idx = ~0;
+ struct p2m_domain *p2m;
+ mfn_t m;
+
+ altp2m_lock(d);
+
+ if ( !altp2m_active(d) )
+ goto out;
+
+ for ( i = 0; i < MAX_ALTP2M; i++ )
+ {
+ p2m = d->arch.altp2m_p2m[i];
+
+ if ( p2m == NULL )
+ continue;
+
+ /*
+ * Get the altp2m mapping. If the smfn has not been dropped, a valid
+ * altp2m mapping needs to be changed/modified accordingly.
+ */
+ p2m_read_lock(p2m);
+ m = p2m_get_entry(p2m, sgfn, NULL, NULL, NULL);
+ p2m_read_unlock(p2m);
+
+ /* Check for a dropped page that may impact this altp2m. */
+ if ( mfn_eq(smfn, INVALID_MFN) &&
+ (gfn_x(sgfn) >= gfn_x(p2m->lowest_mapped_gfn)) &&
+ (gfn_x(sgfn) <= gfn_x(p2m->max_mapped_gfn)) )
+ {
+ if ( !reset_count++ )
+ {
+ altp2m_reset(p2m);
+ last_reset_idx = i;
+ }
+ else
+ {
+ /* At least 2 altp2m's impacted, so reset everything. */
+ for ( i = 0; i < MAX_ALTP2M; i++ )
+ {
+ p2m = d->arch.altp2m_p2m[i];
+
+ if ( i == last_reset_idx || p2m == NULL )
+ continue;
+
+ altp2m_reset(p2m);
+ }
+ goto out;
+ }
+ }
+ else if ( !mfn_eq(m, INVALID_MFN) )
+ {
+ /* Align the gfn and mfn to the given pager order. */
+ sgfn = _gfn(gfn_x(sgfn) & ~((1UL << page_order) - 1));
+ smfn = _mfn(mfn_x(smfn) & ~((1UL << page_order) - 1));
+
+ p2m_write_lock(p2m);
+ rc = p2m_set_entry(p2m, sgfn, (1UL << page_order), smfn, p2mt,
p2ma);
+ p2m_write_unlock(p2m);
+ }
+ }
+
+out:
+ altp2m_unlock(d);
+
+ return rc;
+}
+
static void altp2m_vcpu_reset(struct vcpu *v)
{
v->arch.ap2m_idx = INVALID_ALTP2M;
diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index e9274c74a8..dcf7be6439 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -958,6 +958,10 @@ static int __p2m_set_entry(struct p2m_domain *p2m,
else
rc = 0;
+ /* Update all affected altp2m views if necessary. */
+ if ( p2m_is_hostp2m(p2m) )
+ rc = altp2m_propagate_change(p2m->domain, sgfn, page_order, smfn, t,
a);
+
out:
unmap_domain_page(table);
diff --git a/xen/include/asm-arm/altp2m.h b/xen/include/asm-arm/altp2m.h
index f8e772f120..3e418cb0f0 100644
--- a/xen/include/asm-arm/altp2m.h
+++ b/xen/include/asm-arm/altp2m.h
@@ -80,4 +80,12 @@ int altp2m_set_mem_access(struct domain *d,
p2m_access_t a,
gfn_t gfn);
+/* Propagates changes made to hostp2m to affected altp2m views. */
+int altp2m_propagate_change(struct domain *d,
+ gfn_t sgfn,
+ unsigned int page_order,
+ mfn_t smfn,
+ p2m_type_t p2mt,
+ p2m_access_t p2ma);
+
#endif /* __ASM_ARM_ALTP2M_H */
--
2.13.3
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |