mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
x86/mm/p2m: Move p2m code in HVMOP_[gs]et_mem_access into p2m.c
It uses p2m internals like the p2m lock and function pointers so belongs behind the p2m interface. Signed-off-by: Tim Deegan <Tim.Deegan@citrix.com>
This commit is contained in:
1 parent
801827bf8d
commit
3b0bcb8909
3 files changed
+115
-84
No files matched your search
+9
-84
@@ -3814,21 +3814,6 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
|
||||
{
|
||||
struct xen_hvm_set_mem_access a;
|
||||
struct domain *d;
|
||||
struct p2m_domain *p2m;
|
||||
unsigned long pfn;
|
||||
|
||||
p2m_access_t memaccess[] = {
|
||||
p2m_access_n,
|
||||
p2m_access_r,
|
||||
p2m_access_w,
|
||||
p2m_access_rw,
|
||||
p2m_access_x,
|
||||
p2m_access_rx,
|
||||
p2m_access_wx,
|
||||
p2m_access_rwx,
|
||||
p2m_access_rx2rw,
|
||||
0, /* HVMMEM_access_default -- will get set below */
|
||||
};
|
||||
|
||||
if ( copy_from_guest(&a, arg, 1) )
|
||||
return -EFAULT;
|
||||
@@ -3841,42 +3826,13 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
|
||||
if ( !is_hvm_domain(d) )
|
||||
goto param_fail5;
|
||||
|
||||
p2m = p2m_get_hostp2m(d);
|
||||
memaccess[HVMMEM_access_default] = p2m->default_access;
|
||||
|
||||
/* If request to set default access */
|
||||
if ( a.first_pfn == ~0ull )
|
||||
{
|
||||
rc = 0;
|
||||
p2m->default_access = memaccess[a.hvmmem_access];
|
||||
goto param_fail5;
|
||||
}
|
||||
|
||||
rc = -EINVAL;
|
||||
if ( (a.first_pfn > domain_get_maximum_gpfn(d)) ||
|
||||
((a.first_pfn + a.nr - 1) < a.first_pfn) ||
|
||||
((a.first_pfn + a.nr - 1) > domain_get_maximum_gpfn(d)) )
|
||||
goto param_fail5;
|
||||
|
||||
if ( a.hvmmem_access >= ARRAY_SIZE(memaccess) )
|
||||
goto param_fail5;
|
||||
|
||||
for ( pfn = a.first_pfn; pfn < a.first_pfn + a.nr; pfn++ )
|
||||
{
|
||||
p2m_type_t t;
|
||||
mfn_t mfn;
|
||||
int success;
|
||||
|
||||
mfn = gfn_to_mfn_unshare(d, pfn, &t);
|
||||
|
||||
p2m_lock(p2m);
|
||||
success = p2m->set_entry(p2m, pfn, mfn, 0, t, memaccess[a.hvmmem_access]);
|
||||
p2m_unlock(p2m);
|
||||
if ( !success )
|
||||
goto param_fail5;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
rc = p2m_set_mem_access(d, a.first_pfn, a.nr, a.hvmmem_access);
|
||||
|
||||
param_fail5:
|
||||
rcu_unlock_domain(d);
|
||||
@@ -3887,23 +3843,7 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
|
||||
{
|
||||
struct xen_hvm_get_mem_access a;
|
||||
struct domain *d;
|
||||
struct p2m_domain *p2m;
|
||||
p2m_type_t t;
|
||||
p2m_access_t ac;
|
||||
mfn_t mfn;
|
||||
|
||||
/* Interface access to internal p2m accesses */
|
||||
hvmmem_access_t memaccess[] = {
|
||||
HVMMEM_access_n,
|
||||
HVMMEM_access_r,
|
||||
HVMMEM_access_w,
|
||||
HVMMEM_access_rw,
|
||||
HVMMEM_access_x,
|
||||
HVMMEM_access_rx,
|
||||
HVMMEM_access_wx,
|
||||
HVMMEM_access_rwx,
|
||||
HVMMEM_access_rx2rw
|
||||
};
|
||||
hvmmem_access_t access;
|
||||
|
||||
if ( copy_from_guest(&a, arg, 1) )
|
||||
return -EFAULT;
|
||||
@@ -3916,30 +3856,15 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
|
||||
if ( !is_hvm_domain(d) )
|
||||
goto param_fail6;
|
||||
|
||||
p2m = p2m_get_hostp2m(d);
|
||||
|
||||
if ( a.pfn == ~0ull )
|
||||
{
|
||||
a.hvmmem_access = memaccess[p2m->default_access];
|
||||
}
|
||||
else {
|
||||
rc = -EINVAL;
|
||||
if ( (a.pfn > domain_get_maximum_gpfn(d)) )
|
||||
goto param_fail6;
|
||||
rc = -EINVAL;
|
||||
if ( (a.pfn > domain_get_maximum_gpfn(d)) && a.pfn != ~0ull )
|
||||
goto param_fail6;
|
||||
|
||||
rc = -ESRCH;
|
||||
mfn = p2m->get_entry(p2m, a.pfn, &t, &ac, p2m_query);
|
||||
|
||||
if ( mfn_x(mfn) == INVALID_MFN )
|
||||
goto param_fail6;
|
||||
|
||||
rc = -ERANGE;
|
||||
if ( ac >= ARRAY_SIZE(memaccess) )
|
||||
goto param_fail6;
|
||||
|
||||
a.hvmmem_access = memaccess[ac];
|
||||
}
|
||||
rc = p2m_get_mem_access(d, a.pfn, &access);
|
||||
if ( rc != 0 )
|
||||
goto param_fail6;
|
||||
|
||||
a.hvmmem_access = access;
|
||||
rc = copy_to_guest(arg, &a, 1) ? -EFAULT : 0;
|
||||
|
||||
param_fail6:
|
||||
|
||||
@@ -915,6 +915,101 @@ void p2m_mem_access_resume(struct p2m_domain *p2m)
|
||||
* was available */
|
||||
mem_event_unpause_vcpus(d);
|
||||
}
|
||||
|
||||
|
||||
/* Set access type for a region of pfns.
|
||||
* If start_pfn == -1ul, sets the default access type */
|
||||
int p2m_set_mem_access(struct domain *d, unsigned long start_pfn,
|
||||
uint32_t nr, hvmmem_access_t access)
|
||||
{
|
||||
struct p2m_domain *p2m = p2m_get_hostp2m(d);
|
||||
unsigned long pfn;
|
||||
p2m_access_t a;
|
||||
p2m_type_t t;
|
||||
mfn_t mfn;
|
||||
int rc = 0;
|
||||
|
||||
/* N.B. _not_ static: initializer depends on p2m->default_access */
|
||||
p2m_access_t memaccess[] = {
|
||||
p2m_access_n,
|
||||
p2m_access_r,
|
||||
p2m_access_w,
|
||||
p2m_access_rw,
|
||||
p2m_access_x,
|
||||
p2m_access_rx,
|
||||
p2m_access_wx,
|
||||
p2m_access_rwx,
|
||||
p2m_access_rx2rw,
|
||||
p2m->default_access,
|
||||
};
|
||||
|
||||
if ( access >= HVMMEM_access_default || access < 0 )
|
||||
return -EINVAL;
|
||||
|
||||
a = memaccess[access];
|
||||
|
||||
/* If request to set default access */
|
||||
if ( start_pfn == ~0ull )
|
||||
{
|
||||
p2m->default_access = a;
|
||||
return 0;
|
||||
}
|
||||
|
||||
p2m_lock(p2m);
|
||||
for ( pfn = start_pfn; pfn < start_pfn + nr; pfn++ )
|
||||
{
|
||||
mfn = gfn_to_mfn_query(d, pfn, &t);
|
||||
if ( p2m->set_entry(p2m, pfn, mfn, 0, t, a) == 0 )
|
||||
{
|
||||
rc = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
p2m_unlock(p2m);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Get access type for a pfn
|
||||
* If pfn == -1ul, gets the default access type */
|
||||
int p2m_get_mem_access(struct domain *d, unsigned long pfn,
|
||||
hvmmem_access_t *access)
|
||||
{
|
||||
struct p2m_domain *p2m = p2m_get_hostp2m(d);
|
||||
p2m_type_t t;
|
||||
p2m_access_t a;
|
||||
mfn_t mfn;
|
||||
|
||||
static const hvmmem_access_t memaccess[] = {
|
||||
HVMMEM_access_n,
|
||||
HVMMEM_access_r,
|
||||
HVMMEM_access_w,
|
||||
HVMMEM_access_rw,
|
||||
HVMMEM_access_x,
|
||||
HVMMEM_access_rx,
|
||||
HVMMEM_access_wx,
|
||||
HVMMEM_access_rwx,
|
||||
HVMMEM_access_rx2rw
|
||||
};
|
||||
|
||||
/* If request to get default access */
|
||||
if ( pfn == ~0ull )
|
||||
{
|
||||
*access = memaccess[p2m->default_access];
|
||||
return 0;
|
||||
}
|
||||
|
||||
mfn = p2m->get_entry(p2m, pfn, &t, &a, p2m_query);
|
||||
if ( mfn_x(mfn) == INVALID_MFN )
|
||||
return -ESRCH;
|
||||
|
||||
if ( a >= ARRAY_SIZE(memaccess) || a < 0 )
|
||||
return -ERANGE;
|
||||
|
||||
*access = memaccess[a];
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif /* __x86_64__ */
|
||||
|
||||
static struct p2m_domain *
|
||||
|
||||
@@ -553,6 +553,17 @@ void p2m_mem_access_check(unsigned long gpa, bool_t gla_valid, unsigned long gla
|
||||
bool_t access_r, bool_t access_w, bool_t access_x);
|
||||
/* Resumes the running of the VCPU, restarting the last instruction */
|
||||
void p2m_mem_access_resume(struct p2m_domain *p2m);
|
||||
|
||||
/* Set access type for a region of pfns.
|
||||
* If start_pfn == -1ul, sets the default access type */
|
||||
int p2m_set_mem_access(struct domain *d, unsigned long start_pfn,
|
||||
uint32_t nr, hvmmem_access_t access);
|
||||
|
||||
/* Get access type for a pfn
|
||||
* If pfn == -1ul, gets the default access type */
|
||||
int p2m_get_mem_access(struct domain *d, unsigned long pfn,
|
||||
hvmmem_access_t *access);
|
||||
|
||||
#else
|
||||
static inline void p2m_mem_access_check(unsigned long gpa, bool_t gla_valid,
|
||||
unsigned long gla, bool_t access_r,
|
||||
|
||||