aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir@xen.org>2011-01-11 10:38:28 +0000
committerKeir Fraser <keir@xen.org>2011-01-11 10:38:28 +0000
commitee3c42ba5bffeb7fa2ea4baac6af8608c707e1b8 (patch)
tree90e8465e4e7dbf4c5c82282364db8cd6d5e9dc4d
parentbc89270b8a749773ca717a5c21dcce4a9edd7894 (diff)
downloadxen-ee3c42ba5bffeb7fa2ea4baac6af8608c707e1b8.tar.gz
xen-ee3c42ba5bffeb7fa2ea4baac6af8608c707e1b8.tar.bz2
xen-ee3c42ba5bffeb7fa2ea4baac6af8608c707e1b8.zip
xenpaging: drop paged pages in guest_remove_page
Simply drop paged-pages in guest_remove_page(), and notify xenpaging to drop its reference to the gfn. If the ring is full, the page will remain in paged-out state in xenpaging. This is not an issue, it just means this gfn will not be nominated again. Signed-off-by: Olaf Hering <olaf@aepfle.de>
-rw-r--r--tools/xenpaging/xenpaging.c39
-rw-r--r--xen/arch/x86/mm/p2m.c49
-rw-r--r--xen/common/memory.c6
-rw-r--r--xen/include/asm-x86/p2m.h4
-rw-r--r--xen/include/public/mem_event.h1
5 files changed, 72 insertions, 27 deletions
diff --git a/tools/xenpaging/xenpaging.c b/tools/xenpaging/xenpaging.c
index 0aed2128b9..cbf75085f6 100644
--- a/tools/xenpaging/xenpaging.c
+++ b/tools/xenpaging/xenpaging.c
@@ -638,25 +638,34 @@ int main(int argc, char *argv[])
goto out;
}
- /* Populate the page */
- rc = xenpaging_populate_page(paging, &req.gfn, fd, i);
- if ( rc != 0 )
+ if ( req.flags & MEM_EVENT_FLAG_DROP_PAGE )
{
- ERROR("Error populating page");
- goto out;
+ DPRINTF("drop_page ^ gfn %"PRIx64" pageslot %d\n", req.gfn, i);
+ /* Notify policy of page being dropped */
+ policy_notify_paged_in(req.gfn);
}
+ else
+ {
+ /* Populate the page */
+ rc = xenpaging_populate_page(paging, &req.gfn, fd, i);
+ if ( rc != 0 )
+ {
+ ERROR("Error populating page");
+ goto out;
+ }
- /* Prepare the response */
- rsp.gfn = req.gfn;
- rsp.p2mt = req.p2mt;
- rsp.vcpu_id = req.vcpu_id;
- rsp.flags = req.flags;
+ /* Prepare the response */
+ rsp.gfn = req.gfn;
+ rsp.p2mt = req.p2mt;
+ rsp.vcpu_id = req.vcpu_id;
+ rsp.flags = req.flags;
- rc = xenpaging_resume_page(paging, &rsp, 1);
- if ( rc != 0 )
- {
- ERROR("Error resuming page");
- goto out;
+ rc = xenpaging_resume_page(paging, &rsp, 1);
+ if ( rc != 0 )
+ {
+ ERROR("Error resuming page");
+ goto out;
+ }
}
/* Evict a new page to replace the one we just paged in */
diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
index 6f7474c043..e455ede60a 100644
--- a/xen/arch/x86/mm/p2m.c
+++ b/xen/arch/x86/mm/p2m.c
@@ -2211,12 +2211,15 @@ p2m_remove_page(struct p2m_domain *p2m, unsigned long gfn, unsigned long mfn,
P2M_DEBUG("removing gfn=%#lx mfn=%#lx\n", gfn, mfn);
- for ( i = 0; i < (1UL << page_order); i++ )
+ if ( mfn_valid(_mfn(mfn)) )
{
- mfn_return = p2m->get_entry(p2m, gfn + i, &t, &a, p2m_query);
- if ( !p2m_is_grant(t) )
- set_gpfn_from_mfn(mfn+i, INVALID_M2P_ENTRY);
- ASSERT( !p2m_is_valid(t) || mfn + i == mfn_x(mfn_return) );
+ for ( i = 0; i < (1UL << page_order); i++ )
+ {
+ mfn_return = p2m->get_entry(p2m, gfn + i, &t, &a, p2m_query);
+ if ( !p2m_is_grant(t) )
+ set_gpfn_from_mfn(mfn+i, INVALID_M2P_ENTRY);
+ ASSERT( !p2m_is_valid(t) || mfn + i == mfn_x(mfn_return) );
+ }
}
set_p2m_entry(p2m, gfn, _mfn(INVALID_MFN), page_order, p2m_invalid, p2m->default_access);
}
@@ -2772,6 +2775,25 @@ int p2m_mem_paging_evict(struct p2m_domain *p2m, unsigned long gfn)
return 0;
}
+void p2m_mem_paging_drop_page(struct p2m_domain *p2m, unsigned long gfn)
+{
+ struct vcpu *v = current;
+ mem_event_request_t req;
+ struct domain *d = p2m->domain;
+
+ /* Check that there's space on the ring for this request */
+ if ( mem_event_check_ring(d) == 0)
+ {
+ /* Send release notification to pager */
+ memset(&req, 0, sizeof(req));
+ req.flags |= MEM_EVENT_FLAG_DROP_PAGE;
+ req.gfn = gfn;
+ req.vcpu_id = v->vcpu_id;
+
+ mem_event_put_request(d, &req);
+ }
+}
+
void p2m_mem_paging_populate(struct p2m_domain *p2m, unsigned long gfn)
{
struct vcpu *v = current;
@@ -2846,13 +2868,16 @@ void p2m_mem_paging_resume(struct p2m_domain *p2m)
/* Pull the response off the ring */
mem_event_get_response(d, &rsp);
- /* Fix p2m entry */
- mfn = gfn_to_mfn(p2m, rsp.gfn, &p2mt);
- p2m_lock(p2m);
- set_p2m_entry(p2m, rsp.gfn, mfn, 0, p2m_ram_rw, p2m->default_access);
- set_gpfn_from_mfn(mfn_x(mfn), gfn);
- audit_p2m(p2m, 1);
- p2m_unlock(p2m);
+ /* Fix p2m entry if the page was not dropped */
+ if ( !(rsp.flags & MEM_EVENT_FLAG_DROP_PAGE) )
+ {
+ mfn = gfn_to_mfn(p2m, rsp.gfn, &p2mt);
+ p2m_lock(p2m);
+ set_p2m_entry(p2m, rsp.gfn, mfn, 0, p2m_ram_rw, p2m->default_access);
+ set_gpfn_from_mfn(mfn_x(mfn), rsp.gfn);
+ audit_p2m(p2m, 1);
+ p2m_unlock(p2m);
+ }
/* Unpause domain */
if ( rsp.flags & MEM_EVENT_FLAG_VCPU_PAUSED )
diff --git a/xen/common/memory.c b/xen/common/memory.c
index 33cc3f3e32..cf6482de9f 100644
--- a/xen/common/memory.c
+++ b/xen/common/memory.c
@@ -163,6 +163,12 @@ int guest_remove_page(struct domain *d, unsigned long gmfn)
#ifdef CONFIG_X86
mfn = mfn_x(gfn_to_mfn(p2m_get_hostp2m(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);
+ return 1;
+ }
#else
mfn = gmfn_to_mfn(d, gmfn);
#endif
diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h
index 4c4ce0fe05..dbd1e27d5a 100644
--- a/xen/include/asm-x86/p2m.h
+++ b/xen/include/asm-x86/p2m.h
@@ -511,6 +511,8 @@ int set_shared_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn);
int p2m_mem_paging_nominate(struct p2m_domain *p2m, unsigned long gfn);
/* Evict a frame */
int p2m_mem_paging_evict(struct p2m_domain *p2m, unsigned long gfn);
+/* Tell xenpaging to drop a paged out frame */
+void p2m_mem_paging_drop_page(struct p2m_domain *p2m, unsigned long gfn);
/* Start populating a paged out frame */
void p2m_mem_paging_populate(struct p2m_domain *p2m, unsigned long gfn);
/* Prepare the p2m for paging a frame in */
@@ -518,6 +520,8 @@ int p2m_mem_paging_prep(struct p2m_domain *p2m, unsigned long gfn);
/* Resume normal operation (in case a domain was paused) */
void p2m_mem_paging_resume(struct p2m_domain *p2m);
#else
+static inline void p2m_mem_paging_drop_page(struct p2m_domain *p2m, unsigned long gfn)
+{ }
static inline void p2m_mem_paging_populate(struct p2m_domain *p2m, unsigned long gfn)
{ }
#endif
diff --git a/xen/include/public/mem_event.h b/xen/include/public/mem_event.h
index e3271d94e0..1efd64ef3c 100644
--- a/xen/include/public/mem_event.h
+++ b/xen/include/public/mem_event.h
@@ -33,6 +33,7 @@
/* Memory event flags */
#define MEM_EVENT_FLAG_VCPU_PAUSED (1 << 0)
+#define MEM_EVENT_FLAG_DROP_PAGE (1 << 1)
/* Reasons for the memory event request */
#define MEM_EVENT_REASON_UNKNOWN 0 /* typical reason */