|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v3 6/6] domain: use PGC_extra domheap page for shared_info
From: Paul Durrant <pdurrant@xxxxxxxxxx>
Currently shared_info is a shared xenheap page but shared xenheap pages
complicate future plans for live-update of Xen so it is desirable to,
where possible, not use them [1]. This patch therefore converts shared_info
into a PGC_extra domheap page. This does entail freeing shared_info during
domain_relinquish_resources() rather than domain_destroy() so care is
needed to avoid de-referencing a NULL shared_info pointer hence some
extra checks of 'is_dying' are needed.
NOTE: For Arm, the call to free_shared_info() in arch_domain_destroy() is
left in place since it is idempotent and called in the error path for
arch_domain_create().
[1] See
https://lists.xenproject.org/archives/html/xen-devel/2020-02/msg02018.html
Signed-off-by: Paul Durrant <pdurrant@xxxxxxxxxx>
---
Cc: Stefano Stabellini <sstabellini@xxxxxxxxxx>
Cc: Julien Grall <julien@xxxxxxx>
Cc: Volodymyr Babchuk <Volodymyr_Babchuk@xxxxxxxx>
Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
Cc: George Dunlap <george.dunlap@xxxxxxxxxx>
Cc: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
Cc: Jan Beulich <jbeulich@xxxxxxxx>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx>
Cc: Wei Liu <wl@xxxxxxx>
v2:
- Addressed comments from Julien
- Expanded the commit comment to explain why this patch is wanted
---
xen/arch/arm/domain.c | 2 ++
xen/arch/x86/domain.c | 3 ++-
xen/common/domain.c | 28 ++++++++++++++++++++++++----
xen/common/event_channel.c | 3 +++
xen/common/time.c | 15 +++++++++++++++
5 files changed, 46 insertions(+), 5 deletions(-)
diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 5298d80bd2..741f6dd444 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -1005,6 +1005,8 @@ int domain_relinquish_resources(struct domain *d)
BUG();
}
+ free_shared_info(d);
+
return 0;
}
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index bdcc0d972a..15db476646 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -690,7 +690,6 @@ void arch_domain_destroy(struct domain *d)
pv_domain_destroy(d);
free_perdomain_mappings(d);
- free_shared_info(d);
cleanup_domain_irq_mapping(d);
psr_domain_free(d);
@@ -2245,6 +2244,8 @@ int domain_relinquish_resources(struct domain *d)
if ( is_hvm_domain(d) )
hvm_domain_relinquish_resources(d);
+ free_shared_info(d);
+
return 0;
}
diff --git a/xen/common/domain.c b/xen/common/domain.c
index ba7a905258..886206f648 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -1650,24 +1650,44 @@ int continue_hypercall_on_cpu(
int alloc_shared_info(struct domain *d, unsigned int memflags)
{
- if ( (d->shared_info.virt = alloc_xenheap_pages(0, memflags)) == NULL )
+ struct page_info *pg;
+
+ pg = alloc_domheap_page(d, MEMF_no_refcount | memflags);
+ if ( !pg )
return -ENOMEM;
- d->shared_info.mfn = virt_to_mfn(d->shared_info.virt);
+ if ( !get_page_and_type(pg, d, PGT_writable_page) )
+ {
+ /*
+ * The domain should not be running at this point so there is
+ * no way we should reach this error path.
+ */
+ ASSERT_UNREACHABLE();
+ return -ENODATA;
+ }
+
+ d->shared_info.mfn = page_to_mfn(pg);
+ d->shared_info.virt = __map_domain_page_global(pg);
clear_page(d->shared_info.virt);
- share_xen_page_with_guest(mfn_to_page(d->shared_info.mfn), d, SHARE_rw);
return 0;
}
void free_shared_info(struct domain *d)
{
+ struct page_info *pg;
+
if ( !d->shared_info.virt )
return;
- free_xenheap_page(d->shared_info.virt);
+ unmap_domain_page_global(d->shared_info.virt);
d->shared_info.virt = NULL;
+
+ pg = mfn_to_page(d->shared_info.mfn);
+
+ put_page_alloc_ref(pg);
+ put_page_and_type(pg);
}
/*
diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c
index e86e2bfab0..a17422284d 100644
--- a/xen/common/event_channel.c
+++ b/xen/common/event_channel.c
@@ -1325,6 +1325,9 @@ void evtchn_destroy(struct domain *d)
{
unsigned int i;
+ /* This must be done before shared_info is freed */
+ BUG_ON(!d->shared_info.virt);
+
/* After this barrier no new event-channel allocations can occur. */
BUG_ON(!d->is_dying);
spin_barrier(&d->event_lock);
diff --git a/xen/common/time.c b/xen/common/time.c
index 58fa9abc40..ada02faf07 100644
--- a/xen/common/time.c
+++ b/xen/common/time.c
@@ -99,6 +99,18 @@ void update_domain_wallclock_time(struct domain *d)
uint32_t *wc_version;
uint64_t sec;
+ if ( d != current->domain )
+ {
+ /*
+ * We need to check is_dying here as, if it is set, the
+ * shared_info may have been freed. To do this safely we need
+ * hold the domain lock.
+ */
+ domain_lock(d);
+ if ( d->is_dying )
+ goto unlock;
+ }
+
spin_lock(&wc_lock);
wc_version = &shared_info(d, wc_version);
@@ -121,6 +133,9 @@ void update_domain_wallclock_time(struct domain *d)
*wc_version = version_update_end(*wc_version);
spin_unlock(&wc_lock);
+ unlock:
+ if ( d != current->domain )
+ domain_unlock(d);
}
/* Set clock to <secs,usecs> after 00:00:00 UTC, 1 January, 1970. */
--
2.20.1
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |