mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
Sharable/shared pages need to be unshared in responce to a write attempt. This
is handled through custom gfn_to_mfn transation functions called from generic host page table page fault handler. This should handle both SVM and VTX alike. Signed-off-by: Grzegorz Milos <Grzegorz.Milos@citrix.com>
This commit is contained in:
1 parent
2bde77654a
commit
e8a90e0ab1
2 files changed
+38
-2
No files matched your search
+13
-2
@@ -1325,12 +1325,14 @@ static void *hvm_map_entry(unsigned long va)
|
||||
gfn = paging_gva_to_gfn(current, va, &pfec);
|
||||
if ( pfec == PFEC_page_paged )
|
||||
return NULL;
|
||||
mfn = mfn_x(gfn_to_mfn_current(gfn, &p2mt));
|
||||
mfn = mfn_x(gfn_to_mfn_unshare(current->domain, gfn, &p2mt, 0));
|
||||
if ( p2m_is_paging(p2mt) )
|
||||
{
|
||||
p2m_mem_paging_populate(current->domain, gfn);
|
||||
return NULL;
|
||||
}
|
||||
if ( p2m_is_shared(p2mt) )
|
||||
return NULL;
|
||||
if ( !p2m_is_ram(p2mt) )
|
||||
{
|
||||
gdprintk(XENLOG_ERR, "Failed to look up descriptor table entry\n");
|
||||
@@ -2986,6 +2988,10 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
|
||||
rc = -EINVAL;
|
||||
goto param_fail3;
|
||||
}
|
||||
if( p2m_is_shared(t) )
|
||||
gdprintk(XENLOG_WARNING,
|
||||
"shared pfn 0x%lx modified?\n", pfn);
|
||||
|
||||
if ( mfn_x(mfn) != INVALID_MFN )
|
||||
{
|
||||
paging_mark_dirty(d, mfn_x(mfn));
|
||||
@@ -3038,7 +3044,7 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
|
||||
p2m_type_t t;
|
||||
p2m_type_t nt;
|
||||
mfn_t mfn;
|
||||
mfn = gfn_to_mfn(d, pfn, &t);
|
||||
mfn = gfn_to_mfn_unshare(d, pfn, &t, 0);
|
||||
if ( p2m_is_paging(t) )
|
||||
{
|
||||
p2m_mem_paging_populate(d, pfn);
|
||||
@@ -3046,6 +3052,11 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
|
||||
rc = -EINVAL;
|
||||
goto param_fail4;
|
||||
}
|
||||
if ( p2m_is_shared(t) )
|
||||
{
|
||||
rc = -EINVAL;
|
||||
goto param_fail4;
|
||||
}
|
||||
if ( p2m_is_grant(t) )
|
||||
{
|
||||
gdprintk(XENLOG_WARNING,
|
||||
|
||||
@@ -308,6 +308,31 @@ static inline mfn_t _gfn_to_mfn_type(struct domain *d,
|
||||
#define gfn_to_mfn_current(g, t) gfn_to_mfn_type_current((g), (t), p2m_alloc)
|
||||
#define gfn_to_mfn_foreign(d, g, t) gfn_to_mfn_type_foreign((d), (g), (t), p2m_alloc)
|
||||
|
||||
static inline mfn_t gfn_to_mfn_unshare(struct domain *d,
|
||||
unsigned long gfn,
|
||||
p2m_type_t *p2mt,
|
||||
int must_succeed)
|
||||
{
|
||||
mfn_t mfn;
|
||||
int ret;
|
||||
|
||||
mfn = gfn_to_mfn(d, gfn, p2mt);
|
||||
if(p2m_is_shared(*p2mt))
|
||||
{
|
||||
ret = mem_sharing_unshare_page(d, gfn,
|
||||
must_succeed ? MEM_SHARING_MUST_SUCCEED : 0);
|
||||
if(ret < 0)
|
||||
{
|
||||
BUG_ON(must_succeed);
|
||||
return mfn;
|
||||
}
|
||||
mfn = gfn_to_mfn(d, gfn, p2mt);
|
||||
}
|
||||
|
||||
return mfn;
|
||||
}
|
||||
|
||||
|
||||
/* Compatibility function exporting the old untyped interface */
|
||||
static inline unsigned long gmfn_to_mfn(struct domain *d, unsigned long gpfn)
|
||||
{
|
||||
|
||||