# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1281368802 -3600
# Node ID e7afe98afd4372010ac4fdb7d0d7c948f821feee
# Parent 9e58c46ee63b3201a0a08b631ed4b79c72cf91a3
Nested Virtualization: p2m infrastructure
Change p2m infrastructure to operate on per-p2m instead of per-domain.
This allows us to use multiple p2m tables per-domain.
Signed-off-by: Christoph Egger <Christoph.Egger@xxxxxxx>
Acked-by: Tim Deegan <Tim.Deegan@xxxxxxxxxx>
---
xen/arch/x86/debug.c | 2
xen/arch/x86/domain.c | 2
xen/arch/x86/domctl.c | 4
xen/arch/x86/hvm/emulate.c | 10
xen/arch/x86/hvm/hvm.c | 50 +-
xen/arch/x86/hvm/mtrr.c | 2
xen/arch/x86/hvm/stdvga.c | 5
xen/arch/x86/hvm/svm/svm.c | 9
xen/arch/x86/hvm/vmx/vmx.c | 18
xen/arch/x86/mm.c | 57 +-
xen/arch/x86/mm/guest_walk.c | 15
xen/arch/x86/mm/hap/guest_walk.c | 12
xen/arch/x86/mm/hap/hap.c | 38 +
xen/arch/x86/mm/hap/p2m-ept.c | 148 ++++---
xen/arch/x86/mm/mem_event.c | 4
xen/arch/x86/mm/mem_paging.c | 9
xen/arch/x86/mm/mem_sharing.c | 31 -
xen/arch/x86/mm/p2m.c | 736 +++++++++++++++++++-------------------
xen/arch/x86/mm/shadow/common.c | 38 +
xen/arch/x86/mm/shadow/multi.c | 49 +-
xen/common/grant_table.c | 12
xen/common/memory.c | 4
xen/common/tmem_xen.c | 2
xen/include/asm-x86/guest_pt.h | 4
xen/include/asm-x86/mem_sharing.h | 6
xen/include/asm-x86/p2m.h | 134 +++---
26 files changed, 746 insertions(+), 655 deletions(-)
diff -r 9e58c46ee63b -r e7afe98afd43 xen/arch/x86/debug.c
--- a/xen/arch/x86/debug.c Mon Aug 09 16:40:18 2010 +0100
+++ b/xen/arch/x86/debug.c Mon Aug 09 16:46:42 2010 +0100
@@ -61,7 +61,7 @@ dbg_hvm_va2mfn(dbgva_t vaddr, struct dom
return INVALID_MFN;
}
- mfn = mfn_x(gfn_to_mfn(dp, gfn, &gfntype));
+ mfn = mfn_x(gfn_to_mfn(p2m_get_hostp2m(dp), gfn, &gfntype));
if ( p2m_is_readonly(gfntype) && toaddr )
{
DBGP2("kdb:p2m_is_readonly: gfntype:%x\n", gfntype);
diff -r 9e58c46ee63b -r e7afe98afd43 xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c Mon Aug 09 16:40:18 2010 +0100
+++ b/xen/arch/x86/domain.c Mon Aug 09 16:46:42 2010 +0100
@@ -151,7 +151,7 @@ void dump_pageframe_info(struct domain *
if ( is_hvm_domain(d) )
{
- p2m_pod_dump_data(d);
+ p2m_pod_dump_data(p2m_get_hostp2m(d));
}
spin_lock(&d->page_alloc_lock);
diff -r 9e58c46ee63b -r e7afe98afd43 xen/arch/x86/domctl.c
--- a/xen/arch/x86/domctl.c Mon Aug 09 16:40:18 2010 +0100
+++ b/xen/arch/x86/domctl.c Mon Aug 09 16:46:42 2010 +0100
@@ -982,7 +982,7 @@ long arch_do_domctl(
ret = iomem_permit_access(d, mfn, mfn + nr_mfns - 1);
for ( i = 0; i < nr_mfns; i++ )
- set_mmio_p2m_entry(d, gfn+i, _mfn(mfn+i));
+ set_mmio_p2m_entry(p2m_get_hostp2m(d), gfn+i, _mfn(mfn+i));
}
else
{
@@ -991,7 +991,7 @@ long arch_do_domctl(
gfn, mfn, nr_mfns);
for ( i = 0; i < nr_mfns; i++ )
- clear_mmio_p2m_entry(d, gfn+i);
+ clear_mmio_p2m_entry(p2m_get_hostp2m(d), gfn+i);
ret = iomem_deny_access(d, mfn, mfn + nr_mfns - 1);
}
diff -r 9e58c46ee63b -r e7afe98afd43 xen/arch/x86/hvm/emulate.c
--- a/xen/arch/x86/hvm/emulate.c Mon Aug 09 16:40:18 2010 +0100
+++ b/xen/arch/x86/hvm/emulate.c Mon Aug 09 16:46:42 2010 +0100
@@ -55,6 +55,7 @@ int hvmemul_do_io(
paddr_t value = ram_gpa;
int value_is_ptr = (p_data == NULL);
struct vcpu *curr = current;
+ struct p2m_domain *p2m = p2m_get_hostp2m(curr->domain);
ioreq_t *p = get_ioreq(curr);
unsigned long ram_gfn = paddr_to_pfn(ram_gpa);
p2m_type_t p2mt;
@@ -62,10 +63,10 @@ int hvmemul_do_io(
int rc;
/* Check for paged out page */
- ram_mfn = gfn_to_mfn_unshare(current->domain, ram_gfn, &p2mt, 0);
+ ram_mfn = gfn_to_mfn_unshare(p2m, ram_gfn, &p2mt, 0);
if ( p2m_is_paging(p2mt) )
{
- p2m_mem_paging_populate(curr->domain, ram_gfn);
+ p2m_mem_paging_populate(p2m, ram_gfn);
return X86EMUL_RETRY;
}
if ( p2m_is_shared(p2mt) )
@@ -638,6 +639,7 @@ static int hvmemul_rep_movs(
unsigned long saddr, daddr, bytes;
paddr_t sgpa, dgpa;
uint32_t pfec = PFEC_page_present;
+ struct p2m_domain *p2m = p2m_get_hostp2m(current->domain);
p2m_type_t p2mt;
int rc, df = !!(ctxt->regs->eflags & X86_EFLAGS_DF);
char *buf;
@@ -668,12 +670,12 @@ static int hvmemul_rep_movs(
if ( rc != X86EMUL_OKAY )
return rc;
- (void)gfn_to_mfn_current(sgpa >> PAGE_SHIFT, &p2mt);
+ (void)gfn_to_mfn(p2m, sgpa >> PAGE_SHIFT, &p2mt);
if ( !p2m_is_ram(p2mt) && !p2m_is_grant(p2mt) )
return hvmemul_do_mmio(
sgpa, reps, bytes_per_rep, dgpa, IOREQ_READ, df, NULL);
- (void)gfn_to_mfn_current(dgpa >> PAGE_SHIFT, &p2mt);
+ (void)gfn_to_mfn(p2m, dgpa >> PAGE_SHIFT, &p2mt);
if ( !p2m_is_ram(p2mt) && !p2m_is_grant(p2mt) )
return hvmemul_do_mmio(
dgpa, reps, bytes_per_rep, sgpa, IOREQ_WRITE, df, NULL);
diff -r 9e58c46ee63b -r e7afe98afd43 xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c Mon Aug 09 16:40:18 2010 +0100
+++ b/xen/arch/x86/hvm/hvm.c Mon Aug 09 16:46:42 2010 +0100
@@ -335,16 +335,17 @@ static int hvm_set_ioreq_page(
struct domain *d, struct hvm_ioreq_page *iorp, unsigned long gmfn)
{
struct page_info *page;
+ struct p2m_domain *p2m = p2m_get_hostp2m(d);
p2m_type_t p2mt;
unsigned long mfn;
void *va;
- mfn = mfn_x(gfn_to_mfn_unshare(d, gmfn, &p2mt, 0));
+ mfn = mfn_x(gfn_to_mfn_unshare(p2m, gmfn, &p2mt, 0));
if ( !p2m_is_ram(p2mt) )
return -EINVAL;
if ( p2m_is_paging(p2mt) )
{
- p2m_mem_paging_populate(d, gmfn);
+ p2m_mem_paging_populate(p2m, gmfn);
return -ENOENT;
}
if ( p2m_is_shared(p2mt) )
@@ -968,8 +969,10 @@ bool_t hvm_hap_nested_page_fault(unsigne
{
p2m_type_t p2mt;
mfn_t mfn;
-
- mfn = gfn_to_mfn_type_current(gfn, &p2mt, p2m_guest);
+ struct vcpu *v = current;
+ struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
+
+ mfn = gfn_to_mfn_guest(p2m, gfn, &p2mt);
/*
* If this GFN is emulated MMIO or marked as read-only, pass the fault
@@ -985,12 +988,12 @@ bool_t hvm_hap_nested_page_fault(unsigne
#ifdef __x86_64__
/* Check if the page has been paged out */
if ( p2m_is_paged(p2mt) || (p2mt == p2m_ram_paging_out) )
- p2m_mem_paging_populate(current->domain, gfn);
+ p2m_mem_paging_populate(p2m, gfn);
/* Mem sharing: unshare the page and try again */
if ( p2mt == p2m_ram_shared )
{
- mem_sharing_unshare_page(current->domain, gfn, 0);
+ mem_sharing_unshare_page(p2m, gfn, 0);
return 1;
}
#endif
@@ -1003,8 +1006,8 @@ bool_t hvm_hap_nested_page_fault(unsigne
* a large page, we do not change other pages type within that large
* page.
*/
- paging_mark_dirty(current->domain, mfn_x(mfn));
- p2m_change_type(current->domain, gfn, p2m_ram_logdirty, p2m_ram_rw);
+ paging_mark_dirty(v->domain, mfn_x(mfn));
+ p2m_change_type(p2m, gfn, p2m_ram_logdirty, p2m_ram_rw);
return 1;
}
@@ -1088,6 +1091,7 @@ int hvm_set_cr0(unsigned long value)
{
struct vcpu *v = current;
p2m_type_t p2mt;
+ struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
unsigned long gfn, mfn, old_value = v->arch.hvm_vcpu.guest_cr[0];
HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR0 value = %lx", value);
@@ -1126,7 +1130,7 @@ int hvm_set_cr0(unsigned long value)
{
/* The guest CR3 must be pointing to the guest physical. */
gfn = v->arch.hvm_vcpu.guest_cr[3]>>PAGE_SHIFT;
- mfn = mfn_x(gfn_to_mfn_current(gfn, &p2mt));
+ mfn = mfn_x(gfn_to_mfn(p2m, gfn, &p2mt));
if ( !p2m_is_ram(p2mt) || !mfn_valid(mfn) ||
!get_page(mfn_to_page(mfn), v->domain))
{
@@ -1213,7 +1217,8 @@ int hvm_set_cr3(unsigned long value)
{
/* Shadow-mode CR3 change. Check PDBR and update refcounts. */
HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 value = %lx", value);
- mfn = mfn_x(gfn_to_mfn_current(value >> PAGE_SHIFT, &p2mt));
+ mfn = mfn_x(gfn_to_mfn(p2m_get_hostp2m(v->domain),
+ value >> PAGE_SHIFT, &p2mt));
if ( !p2m_is_ram(p2mt) || !mfn_valid(mfn) ||
!get_page(mfn_to_page(mfn), v->domain) )
goto bad_cr3;
@@ -1356,6 +1361,8 @@ static void *hvm_map_entry(unsigned long
unsigned long gfn, mfn;
p2m_type_t p2mt;
uint32_t pfec;
+ struct vcpu *v = current;
+ struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
if ( ((va & ~PAGE_MASK) + 8) > PAGE_SIZE )
{
@@ -1372,10 +1379,10 @@ static void *hvm_map_entry(unsigned long
gfn = paging_gva_to_gfn(current, va, &pfec);
if ( pfec == PFEC_page_paged || pfec == PFEC_page_shared )
return NULL;
- mfn = mfn_x(gfn_to_mfn_unshare(current->domain, gfn, &p2mt, 0));
+ mfn = mfn_x(gfn_to_mfn_unshare(p2m, gfn, &p2mt, 0));
if ( p2m_is_paging(p2mt) )
{
- p2m_mem_paging_populate(current->domain, gfn);
+ p2m_mem_paging_populate(p2m, gfn);
return NULL;
}
if ( p2m_is_shared(p2mt) )
@@ -1742,6 +1749,7 @@ static enum hvm_copy_result __hvm_copy(
void *buf, paddr_t addr, int size, unsigned int flags, uint32_t pfec)
{
struct vcpu *curr = current;
+ struct p2m_domain *p2m = p2m_get_hostp2m(curr->domain);
unsigned long gfn, mfn;
p2m_type_t p2mt;
char *p;
@@ -1770,11 +1778,11 @@ static enum hvm_copy_result __hvm_copy(
gfn = addr >> PAGE_SHIFT;
}
- mfn = mfn_x(gfn_to_mfn_unshare(current->domain, gfn, &p2mt, 0));
+ mfn = mfn_x(gfn_to_mfn_unshare(p2m, gfn, &p2mt, 0));
if ( p2m_is_paging(p2mt) )
{
- p2m_mem_paging_populate(curr->domain, gfn);
+ p2m_mem_paging_populate(p2m, gfn);
return HVMCOPY_gfn_paged_out;
}
if ( p2m_is_shared(p2mt) )
@@ -3031,6 +3039,7 @@ long do_hvm_op(unsigned long op, XEN_GUE
{
struct xen_hvm_modified_memory a;
struct domain *d;
+ struct p2m_domain *p2m;
unsigned long pfn;
if ( copy_from_guest(&a, arg, 1) )
@@ -3058,13 +3067,14 @@ long do_hvm_op(unsigned long op, XEN_GUE
if ( !paging_mode_log_dirty(d) )
goto param_fail3;
+ p2m = p2m_get_hostp2m(d);
for ( pfn = a.first_pfn; pfn < a.first_pfn + a.nr; pfn++ )
{
p2m_type_t t;
- mfn_t mfn = gfn_to_mfn(d, pfn, &t);
+ mfn_t mfn = gfn_to_mfn(p2m, pfn, &t);
if ( p2m_is_paging(t) )
{
- p2m_mem_paging_populate(d, pfn);
+ p2m_mem_paging_populate(p2m, pfn);
rc = -EINVAL;
goto param_fail3;
@@ -3091,6 +3101,7 @@ long do_hvm_op(unsigned long op, XEN_GUE
{
struct xen_hvm_set_mem_type a;
struct domain *d;
+ struct p2m_domain *p2m;
unsigned long pfn;
/* Interface types to internal p2m types */
@@ -3120,15 +3131,16 @@ long do_hvm_op(unsigned long op, XEN_GUE
if ( a.hvmmem_type >= ARRAY_SIZE(memtype) )
goto param_fail4;
+ p2m = p2m_get_hostp2m(d);
for ( pfn = a.first_pfn; pfn < a.first_pfn + a.nr; pfn++ )
{
p2m_type_t t;
p2m_type_t nt;
mfn_t mfn;
- mfn = gfn_to_mfn_unshare(d, pfn, &t, 0);
+ mfn = gfn_to_mfn_unshare(p2m, pfn, &t, 0);
if ( p2m_is_paging(t) )
{
- p2m_mem_paging_populate(d, pfn);
+ p2m_mem_paging_populate(p2m, pfn);
rc = -EINVAL;
goto param_fail4;
@@ -3147,7 +3159,7 @@ long do_hvm_op(unsigned long op, XEN_GUE
}
else
{
- nt = p2m_change_type(d, pfn, t, memtype[a.hvmmem_type]);
+ nt = p2m_change_type(p2m, pfn, t, memtype[a.hvmmem_type]);
if ( nt != t )
{
gdprintk(XENLOG_WARNING,
diff -r 9e58c46ee63b -r e7afe98afd43 xen/arch/x86/hvm/mtrr.c
--- a/xen/arch/x86/hvm/mtrr.c Mon Aug 09 16:40:18 2010 +0100
+++ b/xen/arch/x86/hvm/mtrr.c Mon Aug 09 16:46:42 2010 +0100
@@ -399,7 +399,7 @@ uint32_t get_pat_flags(struct vcpu *v,
{
struct domain *d = v->domain;
p2m_type_t p2mt;
- gfn_to_mfn(d, paddr_to_pfn(gpaddr), &p2mt);
+ gfn_to_mfn(p2m_get_hostp2m(d), paddr_to_pfn(gpaddr), &p2mt);
if (p2m_is_ram(p2mt))
gdprintk(XENLOG_WARNING,
"Conflict occurs for a given guest l1e flags:%x "
diff -r 9e58c46ee63b -r e7afe98afd43 xen/arch/x86/hvm/stdvga.c
--- a/xen/arch/x86/hvm/stdvga.c Mon Aug 09 16:40:18 2010 +0100
+++ b/xen/arch/x86/hvm/stdvga.c Mon Aug 09 16:46:42 2010 +0100
@@ -469,6 +469,7 @@ static int mmio_move(struct hvm_hw_stdvg
int i;
int sign = p->df ? -1 : 1;
p2m_type_t p2mt;
+ struct p2m_domain *p2m = p2m_get_hostp2m(current->domain);
if ( p->data_is_ptr )
{
@@ -481,7 +482,7 @@ static int mmio_move(struct hvm_hw_stdvg
if ( hvm_copy_to_guest_phys(data, &tmp, p->size) !=
HVMCOPY_okay )
{
- (void)gfn_to_mfn_current(data >> PAGE_SHIFT, &p2mt);
+ (void)gfn_to_mfn(p2m, data >> PAGE_SHIFT, &p2mt);
/*
* The only case we handle is vga_mem <-> vga_mem.
* Anything else disables caching and leaves it to qemu-dm.
@@ -503,7 +504,7 @@ static int mmio_move(struct hvm_hw_stdvg
if ( hvm_copy_from_guest_phys(&tmp, data, p->size) !=
HVMCOPY_okay )
{
- (void)gfn_to_mfn_current(data >> PAGE_SHIFT, &p2mt);
+ (void)gfn_to_mfn(p2m, data >> PAGE_SHIFT, &p2mt);
if ( (p2mt != p2m_mmio_dm) || (data < VGA_MEM_BASE) ||
((data + p->size) > (VGA_MEM_BASE + VGA_MEM_SIZE)) )
return 0;
diff -r 9e58c46ee63b -r e7afe98afd43 xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c Mon Aug 09 16:40:18 2010 +0100
+++ b/xen/arch/x86/hvm/svm/svm.c Mon Aug 09 16:46:42 2010 +0100
@@ -232,7 +232,7 @@ static int svm_vmcb_restore(struct vcpu
{
if ( c->cr0 & X86_CR0_PG )
{
- mfn = mfn_x(gfn_to_mfn(v->domain, c->cr3 >> PAGE_SHIFT, &p2mt));
+ mfn = mfn_x(gfn_to_mfn(p2m, c->cr3 >> PAGE_SHIFT, &p2mt));
if ( !p2m_is_ram(p2mt) || !get_page(mfn_to_page(mfn), v->domain) )
{
gdprintk(XENLOG_ERR, "Invalid CR3 value=0x%"PRIx64"\n",
@@ -946,6 +946,9 @@ static void svm_do_nested_pgfault(paddr_
unsigned long gfn = gpa >> PAGE_SHIFT;
mfn_t mfn;
p2m_type_t p2mt;
+ struct p2m_domain *p2m;
+
+ p2m = p2m_get_hostp2m(current->domain);
if ( tb_init_done )
{
@@ -958,7 +961,7 @@ static void svm_do_nested_pgfault(paddr_
_d.gpa = gpa;
_d.qualification = 0;
- _d.mfn = mfn_x(gfn_to_mfn_query(current->domain, gfn, &_d.p2mt));
+ _d.mfn = mfn_x(gfn_to_mfn_query(p2m, gfn, &_d.p2mt));
__trace_var(TRC_HVM_NPF, 0, sizeof(_d), (unsigned char *)&_d);
}
@@ -967,7 +970,7 @@ static void svm_do_nested_pgfault(paddr_
return;
/* Everything else is an error. */
- mfn = gfn_to_mfn_type_current(gfn, &p2mt, p2m_guest);
+ mfn = gfn_to_mfn_guest(p2m, gfn, &p2mt);
gdprintk(XENLOG_ERR, "SVM violation gpa %#"PRIpaddr", mfn %#lx, type %i\n",
gpa, mfn_x(mfn), p2mt);
domain_crash(current->domain);
diff -r 9e58c46ee63b -r e7afe98afd43 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c Mon Aug 09 16:40:18 2010 +0100
+++ b/xen/arch/x86/hvm/vmx/vmx.c Mon Aug 09 16:46:42 2010 +0100
@@ -486,7 +486,8 @@ static int vmx_restore_cr0_cr3(
{
if ( cr0 & X86_CR0_PG )
{
- mfn = mfn_x(gfn_to_mfn(v->domain, cr3 >> PAGE_SHIFT, &p2mt));
+ mfn = mfn_x(gfn_to_mfn(p2m_get_hostp2m(v->domain),
+ cr3 >> PAGE_SHIFT, &p2mt));
if ( !p2m_is_ram(p2mt) || !get_page(mfn_to_page(mfn), v->domain) )
{
gdprintk(XENLOG_ERR, "Invalid CR3 value=0x%lx\n", cr3);
@@ -1002,7 +1003,8 @@ static void vmx_load_pdptrs(struct vcpu
if ( cr3 & 0x1fUL )
goto crash;
- mfn = mfn_x(gfn_to_mfn(v->domain, cr3 >> PAGE_SHIFT, &p2mt));
+ mfn = mfn_x(gfn_to_mfn(p2m_get_hostp2m(v->domain),
+ cr3 >> PAGE_SHIFT, &p2mt));
if ( !p2m_is_ram(p2mt) )
goto crash;
@@ -1221,7 +1223,7 @@ void ept_sync_domain(struct domain *d)
return;
ASSERT(local_irq_is_enabled());
- ASSERT(p2m_locked_by_me(d->arch.p2m));
+ ASSERT(p2m_locked_by_me(p2m_get_hostp2m(d)));
/*
* Flush active cpus synchronously. Flush others the next time this domain
@@ -1340,7 +1342,7 @@ static void vmx_set_uc_mode(struct vcpu
{
if ( paging_mode_hap(v->domain) )
ept_change_entry_emt_with_range(
- v->domain, 0, v->domain->arch.p2m->max_mapped_pfn);
+ v->domain, 0, p2m_get_hostp2m(v->domain)->max_mapped_pfn);
hvm_asid_flush_vcpu(v);
}
@@ -1893,7 +1895,8 @@ static int vmx_alloc_vlapic_mapping(stru
return -ENOMEM;
share_xen_page_with_guest(virt_to_page(apic_va), d, XENSHARE_writable);
set_mmio_p2m_entry(
- d, paddr_to_pfn(APIC_DEFAULT_PHYS_BASE), _mfn(virt_to_mfn(apic_va)));
+ p2m_get_hostp2m(d), paddr_to_pfn(APIC_DEFAULT_PHYS_BASE),
+ _mfn(virt_to_mfn(apic_va)));
d->arch.hvm_domain.vmx.apic_access_mfn = virt_to_mfn(apic_va);
return 0;
@@ -2098,6 +2101,7 @@ static void ept_handle_violation(unsigne
unsigned long gla, gfn = gpa >> PAGE_SHIFT;
mfn_t mfn;
p2m_type_t p2mt;
+ struct p2m_domain *p2m = p2m_get_hostp2m(current->domain);
if ( tb_init_done )
{
@@ -2110,7 +2114,7 @@ static void ept_handle_violation(unsigne
_d.gpa = gpa;
_d.qualification = qualification;
- _d.mfn = mfn_x(gfn_to_mfn_query(current->domain, gfn, &_d.p2mt));
+ _d.mfn = mfn_x(gfn_to_mfn_query(p2m, gfn, &_d.p2mt));
__trace_var(TRC_HVM_NPF, 0, sizeof(_d), (unsigned char *)&_d);
}
@@ -2120,7 +2124,7 @@ static void ept_handle_violation(unsigne
return;
/* Everything else is an error. */
- mfn = gfn_to_mfn_type_current(gfn, &p2mt, p2m_guest);
+ mfn = gfn_to_mfn_guest(p2m, gfn, &p2mt);
gdprintk(XENLOG_ERR, "EPT violation %#lx (%c%c%c/%c%c%c), "
"gpa %#"PRIpaddr", mfn %#lx, type %i.\n",
qualification,
diff -r 9e58c46ee63b -r e7afe98afd43 xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Mon Aug 09 16:40:18 2010 +0100
+++ b/xen/arch/x86/mm.c Mon Aug 09 16:46:42 2010 +0100
@@ -398,7 +398,7 @@ unsigned long domain_get_maximum_gpfn(st
unsigned long domain_get_maximum_gpfn(struct domain *d)
{
if ( is_hvm_domain(d) )
- return d->arch.p2m->max_mapped_pfn;
+ return p2m_get_hostp2m(d)->max_mapped_pfn;
/* NB. PV guests specify nr_pfns rather than max_pfn so we adjust here. */
return arch_get_max_pfn(d) - 1;
}
@@ -1741,7 +1741,8 @@ static int mod_l1_entry(l1_pgentry_t *pl
if ( l1e_get_flags(nl1e) & _PAGE_PRESENT )
{
/* Translate foreign guest addresses. */
- mfn = mfn_x(gfn_to_mfn(pg_dom, l1e_get_pfn(nl1e), &p2mt));
+ mfn = mfn_x(gfn_to_mfn(p2m_get_hostp2m(pg_dom),
+ l1e_get_pfn(nl1e), &p2mt));
if ( !p2m_is_ram(p2mt) || unlikely(mfn == INVALID_MFN) )
return 0;
ASSERT((mfn & ~(PADDR_MASK >> PAGE_SHIFT)) == 0);
@@ -3318,8 +3319,8 @@ int do_mmu_update(
struct page_info *page;
int rc = 0, okay = 1, i = 0;
unsigned int cmd, done = 0, pt_dom;
- struct domain *d = current->domain, *pt_owner = d, *pg_owner;
struct vcpu *v = current;
+ struct domain *d = v->domain, *pt_owner = d, *pg_owner;
struct domain_mmap_cache mapcache;
if ( unlikely(count & MMU_UPDATE_PREEMPTED) )
@@ -3403,13 +3404,13 @@ int do_mmu_update(
req.ptr -= cmd;
gmfn = req.ptr >> PAGE_SHIFT;
- mfn = mfn_x(gfn_to_mfn(pt_owner, gmfn, &p2mt));
+ mfn = mfn_x(gfn_to_mfn(p2m_get_hostp2m(pt_owner), gmfn, &p2mt));
if ( !p2m_is_valid(p2mt) )
mfn = INVALID_MFN;
if ( p2m_is_paged(p2mt) )
{
- p2m_mem_paging_populate(pg_owner, gmfn);
+ p2m_mem_paging_populate(p2m_get_hostp2m(pg_owner), gmfn);
rc = -ENOENT;
break;
@@ -3434,12 +3435,13 @@ int do_mmu_update(
{
l1_pgentry_t l1e = l1e_from_intpte(req.val);
p2m_type_t l1e_p2mt;
- gfn_to_mfn(pg_owner, l1e_get_pfn(l1e), &l1e_p2mt);
+ gfn_to_mfn(p2m_get_hostp2m(pg_owner),
+ l1e_get_pfn(l1e), &l1e_p2mt);
if ( p2m_is_paged(l1e_p2mt) )
{
- p2m_mem_paging_populate(pg_owner, l1e_get_pfn(l1e));
-
+ p2m_mem_paging_populate(p2m_get_hostp2m(pg_owner),
+ l1e_get_pfn(l1e));
rc = -ENOENT;
break;
}
@@ -3457,7 +3459,7 @@ int do_mmu_update(
/* Unshare the page for RW foreign mappings */
if ( l1e_get_flags(l1e) & _PAGE_RW )
{
- rc = mem_sharing_unshare_page(pg_owner,
+ rc =
mem_sharing_unshare_page(p2m_get_hostp2m(pg_owner),
l1e_get_pfn(l1e),
0);
if ( rc )
@@ -3475,12 +3477,12 @@ int do_mmu_update(
{
l2_pgentry_t l2e = l2e_from_intpte(req.val);
p2m_type_t l2e_p2mt;
- gfn_to_mfn(pg_owner, l2e_get_pfn(l2e), &l2e_p2mt);
+ gfn_to_mfn(p2m_get_hostp2m(pg_owner), l2e_get_pfn(l2e),
&l2e_p2mt);
if ( p2m_is_paged(l2e_p2mt) )
{
- p2m_mem_paging_populate(pg_owner, l2e_get_pfn(l2e));
-
+ p2m_mem_paging_populate(p2m_get_hostp2m(pg_owner),
+ l2e_get_pfn(l2e));
rc = -ENOENT;
break;
}
@@ -3505,12 +3507,12 @@ int do_mmu_update(
{
l3_pgentry_t l3e = l3e_from_intpte(req.val);
p2m_type_t l3e_p2mt;
- gfn_to_mfn(pg_owner, l3e_get_pfn(l3e), &l3e_p2mt);
+ gfn_to_mfn(p2m_get_hostp2m(pg_owner), l3e_get_pfn(l3e),
&l3e_p2mt);
if ( p2m_is_paged(l3e_p2mt) )
{
- p2m_mem_paging_populate(pg_owner, l3e_get_pfn(l3e));
-
+ p2m_mem_paging_populate(p2m_get_hostp2m(pg_owner),
+ l3e_get_pfn(l3e));
rc = -ENOENT;
break;
}
@@ -3536,12 +3538,13 @@ int do_mmu_update(
{
l4_pgentry_t l4e = l4e_from_intpte(req.val);
p2m_type_t l4e_p2mt;
- gfn_to_mfn(pg_owner, l4e_get_pfn(l4e), &l4e_p2mt);
+ gfn_to_mfn(p2m_get_hostp2m(pg_owner),
+ l4e_get_pfn(l4e), &l4e_p2mt);
if ( p2m_is_paged(l4e_p2mt) )
{
- p2m_mem_paging_populate(pg_owner, l4e_get_pfn(l4e));
-
+ p2m_mem_paging_populate(p2m_get_hostp2m(pg_owner),
+ l4e_get_pfn(l4e));
rc = -ENOENT;
break;
}
@@ -3923,8 +3926,8 @@ static int create_grant_p2m_mapping(uint
p2mt = p2m_grant_map_ro;
else
p2mt = p2m_grant_map_rw;
- rc = guest_physmap_add_entry(current->domain, addr >> PAGE_SHIFT,
- frame, 0, p2mt);
+ rc = guest_physmap_add_entry(p2m_get_hostp2m(current->domain),
+ addr >> PAGE_SHIFT, frame, 0, p2mt);
if ( rc )
return GNTST_general_error;
else
@@ -3962,11 +3965,12 @@ static int replace_grant_p2m_mapping(
unsigned long gfn = (unsigned long)(addr >> PAGE_SHIFT);
p2m_type_t type;
mfn_t old_mfn;
+ struct domain *d = current->domain;
if ( new_addr != 0 || (flags & GNTMAP_contains_pte) )
return GNTST_general_error;
- old_mfn = gfn_to_mfn_current(gfn, &type);
+ old_mfn = gfn_to_mfn(p2m_get_hostp2m(d), gfn, &type);
if ( !p2m_is_grant(type) || mfn_x(old_mfn) != frame )
{
gdprintk(XENLOG_WARNING,
@@ -3974,7 +3978,7 @@ static int replace_grant_p2m_mapping(
type, mfn_x(old_mfn), frame);
return GNTST_general_error;
}
- guest_physmap_remove_page(current->domain, gfn, frame, 0);
+ guest_physmap_remove_page(d, gfn, frame, 0);
return GNTST_okay;
}
@@ -4581,7 +4585,8 @@ long arch_memory_op(int op, XEN_GUEST_HA
{
p2m_type_t p2mt;
- xatp.idx = mfn_x(gfn_to_mfn_unshare(d, xatp.idx, &p2mt, 0));
+ xatp.idx = mfn_x(gfn_to_mfn_unshare(p2m_get_hostp2m(d),
+ xatp.idx, &p2mt, 0));
/* If the page is still shared, exit early */
if ( p2m_is_shared(p2mt) )
{
@@ -4771,6 +4776,7 @@ long arch_memory_op(int op, XEN_GUEST_HA
{
xen_pod_target_t target;
struct domain *d;
+ struct p2m_domain *p2m;
/* Support DOMID_SELF? */
if ( !IS_PRIV(current->domain) )
@@ -4794,9 +4800,10 @@ long arch_memory_op(int op, XEN_GUEST_HA
rc = p2m_pod_set_mem_target(d, target.target_pages);
}
+ p2m = p2m_get_hostp2m(d);
target.tot_pages = d->tot_pages;
- target.pod_cache_pages = d->arch.p2m->pod.count;
- target.pod_entries = d->arch.p2m->pod.entry_count;
+ target.pod_cache_pages = p2m->pod.count;
+ target.pod_entries = p2m->pod.entry_count;
if ( copy_to_guest(arg, &target, 1) )
{
diff -r 9e58c46ee63b -r e7afe98afd43 xen/arch/x86/mm/guest_walk.c
--- a/xen/arch/x86/mm/guest_walk.c Mon Aug 09 16:40:18 2010 +0100
+++ b/xen/arch/x86/mm/guest_walk.c Mon Aug 09 16:46:42 2010 +0100
@@ -86,17 +86,17 @@ static uint32_t set_ad_bits(void *guest_
return 0;
}
-static inline void *map_domain_gfn(struct domain *d,
+static inline void *map_domain_gfn(struct p2m_domain *p2m,
gfn_t gfn,
mfn_t *mfn,
p2m_type_t *p2mt,
uint32_t *rc)
{
/* Translate the gfn, unsharing if shared */
- *mfn = gfn_to_mfn_unshare(d, gfn_x(gfn), p2mt, 0);
+ *mfn = gfn_to_mfn_unshare(p2m, gfn_x(gfn), p2mt, 0);
if ( p2m_is_paging(*p2mt) )
{
- p2m_mem_paging_populate(d, gfn_x(gfn));
+ p2m_mem_paging_populate(p2m, gfn_x(gfn));
*rc = _PAGE_PAGED;
return NULL;
@@ -119,7 +119,8 @@ static inline void *map_domain_gfn(struc
/* Walk the guest pagetables, after the manner of a hardware walker. */
uint32_t
-guest_walk_tables(struct vcpu *v, unsigned long va, walk_t *gw,
+guest_walk_tables(struct vcpu *v, struct p2m_domain *p2m,
+ unsigned long va, walk_t *gw,
uint32_t pfec, mfn_t top_mfn, void *top_map)
{
struct domain *d = v->domain;
@@ -154,7 +155,7 @@ guest_walk_tables(struct vcpu *v, unsign
if ( rc & _PAGE_PRESENT ) goto out;
/* Map the l3 table */
- l3p = map_domain_gfn(d,
+ l3p = map_domain_gfn(p2m,
guest_l4e_get_gfn(gw->l4e),
&gw->l3mfn,
&p2mt,
@@ -181,7 +182,7 @@ guest_walk_tables(struct vcpu *v, unsign
#endif /* PAE or 64... */
/* Map the l2 table */
- l2p = map_domain_gfn(d,
+ l2p = map_domain_gfn(p2m,
guest_l3e_get_gfn(gw->l3e),
&gw->l2mfn,
&p2mt,
@@ -237,7 +238,7 @@ guest_walk_tables(struct vcpu *v, unsign
else
{
/* Not a superpage: carry on and find the l1e. */
- l1p = map_domain_gfn(d,
+ l1p = map_domain_gfn(p2m,
guest_l2e_get_gfn(gw->l2e),
&gw->l1mfn,
&p2mt,
diff -r 9e58c46ee63b -r e7afe98afd43 xen/arch/x86/mm/hap/guest_walk.c
--- a/xen/arch/x86/mm/hap/guest_walk.c Mon Aug 09 16:40:18 2010 +0100
+++ b/xen/arch/x86/mm/hap/guest_walk.c Mon Aug 09 16:46:42 2010 +0100
@@ -43,13 +43,14 @@ unsigned long hap_gva_to_gfn(GUEST_PAGIN
void *top_map;
p2m_type_t p2mt;
walk_t gw;
+ struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
/* Get the top-level table's MFN */
cr3 = v->arch.hvm_vcpu.guest_cr[3];
- top_mfn = gfn_to_mfn_unshare(v->domain, cr3 >> PAGE_SHIFT, &p2mt, 0);
+ top_mfn = gfn_to_mfn_unshare(p2m, cr3 >> PAGE_SHIFT, &p2mt, 0);
if ( p2m_is_paging(p2mt) )
{
- p2m_mem_paging_populate(v->domain, cr3 >> PAGE_SHIFT);
+ p2m_mem_paging_populate(p2m, cr3 >> PAGE_SHIFT);
pfec[0] = PFEC_page_paged;
return INVALID_GFN;
@@ -71,17 +72,17 @@ unsigned long hap_gva_to_gfn(GUEST_PAGIN
#if GUEST_PAGING_LEVELS == 3
top_map += (cr3 & ~(PAGE_MASK | 31));
#endif
- missing = guest_walk_tables(v, gva, &gw, pfec[0], top_mfn, top_map);
+ missing = guest_walk_tables(v, p2m, gva, &gw, pfec[0], top_mfn, top_map);
unmap_domain_page(top_map);
/* Interpret the answer */
if ( missing == 0 )
{
gfn_t gfn = guest_l1e_get_gfn(gw.l1e);
- gfn_to_mfn_unshare(v->domain, gfn_x(gfn), &p2mt, 0);
+ gfn_to_mfn_unshare(p2m, gfn_x(gfn), &p2mt, 0);
if ( p2m_is_paging(p2mt) )
{
- p2m_mem_paging_populate(v->domain, gfn_x(gfn));
+ p2m_mem_paging_populate(p2m, gfn_x(gfn));
pfec[0] = PFEC_page_paged;
return INVALID_GFN;
@@ -130,4 +131,3 @@ unsigned long hap_gva_to_gfn(GUEST_PAGIN
* indent-tabs-mode: nil
* End:
*/
-
diff -r 9e58c46ee63b -r e7afe98afd43 xen/arch/x86/mm/hap/hap.c
--- a/xen/arch/x86/mm/hap/hap.c Mon Aug 09 16:40:18 2010 +0100
+++ b/xen/arch/x86/mm/hap/hap.c Mon Aug 09 16:46:42 2010 +0100
@@ -70,7 +70,7 @@ static int hap_enable_vram_tracking(stru
/* set l1e entries of P2M table to be read-only. */
for (i = dirty_vram->begin_pfn; i < dirty_vram->end_pfn; i++)
- p2m_change_type(d, i, p2m_ram_rw, p2m_ram_logdirty);
+ p2m_change_type(p2m_get_hostp2m(d), i, p2m_ram_rw, p2m_ram_logdirty);
flush_tlb_mask(&d->domain_dirty_cpumask);
return 0;
@@ -90,7 +90,7 @@ static int hap_disable_vram_tracking(str
/* set l1e entries of P2M table with normal mode */
for (i = dirty_vram->begin_pfn; i < dirty_vram->end_pfn; i++)
- p2m_change_type(d, i, p2m_ram_logdirty, p2m_ram_rw);
+ p2m_change_type(p2m_get_hostp2m(d), i, p2m_ram_logdirty, p2m_ram_rw);
flush_tlb_mask(&d->domain_dirty_cpumask);
return 0;
@@ -106,7 +106,7 @@ static void hap_clean_vram_tracking(stru
/* set l1e entries of P2M table to be read-only. */
for (i = dirty_vram->begin_pfn; i < dirty_vram->end_pfn; i++)
- p2m_change_type(d, i, p2m_ram_rw, p2m_ram_logdirty);
+ p2m_change_type(p2m_get_hostp2m(d), i, p2m_ram_rw, p2m_ram_logdirty);
flush_tlb_mask(&d->domain_dirty_cpumask);
}
@@ -200,7 +200,8 @@ static int hap_enable_log_dirty(struct d
hap_unlock(d);
/* set l1e entries of P2M table to be read-only. */
- p2m_change_entry_type_global(d, p2m_ram_rw, p2m_ram_logdirty);
+ p2m_change_entry_type_global(p2m_get_hostp2m(d),
+ p2m_ram_rw, p2m_ram_logdirty);
flush_tlb_mask(&d->domain_dirty_cpumask);
return 0;
}
@@ -212,14 +213,16 @@ static int hap_disable_log_dirty(struct
hap_unlock(d);
/* set l1e entries of P2M table with normal mode */
- p2m_change_entry_type_global(d, p2m_ram_logdirty, p2m_ram_rw);
+ p2m_change_entry_type_global(p2m_get_hostp2m(d),
+ p2m_ram_logdirty, p2m_ram_rw);
return 0;
}
static void hap_clean_dirty_bitmap(struct domain *d)
{
/* set l1e entries of P2M table to be read-only. */
- p2m_change_entry_type_global(d, p2m_ram_rw, p2m_ram_logdirty);
+ p2m_change_entry_type_global(p2m_get_hostp2m(d),
+ p2m_ram_rw, p2m_ram_logdirty);
flush_tlb_mask(&d->domain_dirty_cpumask);
}
@@ -273,8 +276,9 @@ static void hap_free(struct domain *d, m
page_list_add_tail(pg, &d->arch.paging.hap.freelist);
}
-static struct page_info *hap_alloc_p2m_page(struct domain *d)
-{
+static struct page_info *hap_alloc_p2m_page(struct p2m_domain *p2m)
+{
+ struct domain *d = p2m->domain;
struct page_info *pg;
hap_lock(d);
@@ -312,8 +316,9 @@ static struct page_info *hap_alloc_p2m_p
return pg;
}
-static void hap_free_p2m_page(struct domain *d, struct page_info *pg)
-{
+static void hap_free_p2m_page(struct p2m_domain *p2m, struct page_info *pg)
+{
+ struct domain *d = p2m->domain;
hap_lock(d);
ASSERT(page_get_owner(pg) == d);
/* Should have just the one ref we gave it in alloc_p2m_page() */
@@ -594,7 +599,8 @@ int hap_enable(struct domain *d, u32 mod
/* allocate P2m table */
if ( mode & PG_translate )
{
- rv = p2m_alloc_table(d, hap_alloc_p2m_page, hap_free_p2m_page);
+ rv = p2m_alloc_table(p2m_get_hostp2m(d),
+ hap_alloc_p2m_page, hap_free_p2m_page);
if ( rv != 0 )
goto out;
}
@@ -611,7 +617,7 @@ void hap_final_teardown(struct domain *d
if ( d->arch.paging.hap.total_pages != 0 )
hap_teardown(d);
- p2m_teardown(d);
+ p2m_teardown(p2m_get_hostp2m(d));
ASSERT(d->arch.paging.hap.p2m_pages == 0);
}
@@ -711,9 +717,11 @@ static int hap_page_fault(struct vcpu *v
static int hap_page_fault(struct vcpu *v, unsigned long va,
struct cpu_user_regs *regs)
{
+ struct domain *d = v->domain;
+
HAP_ERROR("Intercepted a guest #PF (%u:%u) with HAP enabled.\n",
- v->domain->domain_id, v->vcpu_id);
- domain_crash(v->domain);
+ d->domain_id, v->vcpu_id);
+ domain_crash(d);
return 0;
}
@@ -882,5 +890,3 @@ static const struct paging_mode hap_pagi
* indent-tabs-mode: nil
* End:
*/
-
-
diff -r 9e58c46ee63b -r e7afe98afd43 xen/arch/x86/mm/hap/p2m-ept.c
--- a/xen/arch/x86/mm/hap/p2m-ept.c Mon Aug 09 16:40:18 2010 +0100
+++ b/xen/arch/x86/mm/hap/p2m-ept.c Mon Aug 09 16:46:42 2010 +0100
@@ -36,23 +36,23 @@
#define is_epte_superpage(ept_entry) ((ept_entry)->sp)
/* Non-ept "lock-and-check" wrapper */
-static int ept_pod_check_and_populate(struct domain *d, unsigned long gfn,
+static int ept_pod_check_and_populate(struct p2m_domain *p2m, unsigned long
gfn,
ept_entry_t *entry, int order,
p2m_query_t q)
{
int r;
- p2m_lock(d->arch.p2m);
+ p2m_lock(p2m);
/* Check to make sure this is still PoD */
if ( entry->avail1 != p2m_populate_on_demand )
{
- p2m_unlock(d->arch.p2m);
+ p2m_unlock(p2m);
return 0;
}
- r = p2m_pod_demand_populate(d, gfn, order, q);
-
- p2m_unlock(d->arch.p2m);
+ r = p2m_pod_demand_populate(p2m, gfn, order, q);
+
+ p2m_unlock(p2m);
return r;
}
@@ -98,11 +98,11 @@ static void ept_p2m_type_to_flags(ept_en
#define GUEST_TABLE_POD_PAGE 3
/* Fill in middle levels of ept table */
-static int ept_set_middle_entry(struct domain *d, ept_entry_t *ept_entry)
+static int ept_set_middle_entry(struct p2m_domain *p2m, ept_entry_t *ept_entry)
{
struct page_info *pg;
- pg = p2m_alloc_ptp(d, 0);
+ pg = p2m_alloc_ptp(p2m, 0);
if ( pg == NULL )
return 0;
@@ -119,7 +119,7 @@ static int ept_set_middle_entry(struct d
}
/* free ept sub tree behind an entry */
-void ept_free_entry(struct domain *d, ept_entry_t *ept_entry, int level)
+void ept_free_entry(struct p2m_domain *p2m, ept_entry_t *ept_entry, int level)
{
/* End if the entry is a leaf entry. */
if ( level == 0 || !is_epte_present(ept_entry) ||
@@ -130,14 +130,14 @@ void ept_free_entry(struct domain *d, ep
{
ept_entry_t *epte = map_domain_page(ept_entry->mfn);
for ( int i = 0; i < EPT_PAGETABLE_ENTRIES; i++ )
- ept_free_entry(d, epte + i, level - 1);
+ ept_free_entry(p2m, epte + i, level - 1);
unmap_domain_page(epte);
}
- d->arch.p2m->free_page(d, mfn_to_page(ept_entry->mfn));
-}
-
-static int ept_split_super_page(struct domain *d, ept_entry_t *ept_entry,
+ p2m->free_page(p2m, mfn_to_page(ept_entry->mfn));
+}
+
+static int ept_split_super_page(struct p2m_domain *p2m, ept_entry_t *ept_entry,
int level, int target)
{
ept_entry_t new_ept, *table;
@@ -150,7 +150,7 @@ static int ept_split_super_page(struct d
ASSERT(is_epte_superpage(ept_entry));
- if ( !ept_set_middle_entry(d, &new_ept) )
+ if ( !ept_set_middle_entry(p2m, &new_ept) )
return 0;
table = map_domain_page(new_ept.mfn);
@@ -174,7 +174,7 @@ static int ept_split_super_page(struct d
ASSERT(is_epte_superpage(epte));
- if ( !(rv = ept_split_super_page(d, epte, level - 1, target)) )
+ if ( !(rv = ept_split_super_page(p2m, epte, level - 1, target)) )
break;
}
@@ -200,7 +200,7 @@ static int ept_split_super_page(struct d
* GUEST_TABLE_POD:
* The next entry is marked populate-on-demand.
*/
-static int ept_next_level(struct domain *d, bool_t read_only,
+static int ept_next_level(struct p2m_domain *p2m, bool_t read_only,
ept_entry_t **table, unsigned long *gfn_remainder,
int next_level)
{
@@ -225,7 +225,7 @@ static int ept_next_level(struct domain
if ( read_only )
return GUEST_TABLE_MAP_FAILED;
- if ( !ept_set_middle_entry(d, ept_entry) )
+ if ( !ept_set_middle_entry(p2m, ept_entry) )
return GUEST_TABLE_MAP_FAILED;
}
@@ -245,7 +245,7 @@ static int ept_next_level(struct domain
* by observing whether any gfn->mfn translations are modified.
*/
static int
-ept_set_entry(struct domain *d, unsigned long gfn, mfn_t mfn,
+ept_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn,
unsigned int order, p2m_type_t p2mt)
{
ept_entry_t *table, *ept_entry;
@@ -259,6 +259,7 @@ ept_set_entry(struct domain *d, unsigned
uint8_t ipat = 0;
int need_modify_vtd_table = 1;
int needs_sync = 1;
+ struct domain *d = p2m->domain;
/*
* the caller must make sure:
@@ -281,7 +282,7 @@ ept_set_entry(struct domain *d, unsigned
for ( i = ept_get_wl(d); i > target; i-- )
{
- ret = ept_next_level(d, 0, &table, &gfn_remainder, i);
+ ret = ept_next_level(p2m, 0, &table, &gfn_remainder, i);
if ( !ret )
goto out;
else if ( ret != GUEST_TABLE_NORMAL_PAGE )
@@ -311,7 +312,7 @@ ept_set_entry(struct domain *d, unsigned
if ( mfn_valid(mfn_x(mfn)) || direct_mmio || p2m_is_paged(p2mt) ||
(p2mt == p2m_ram_paging_in_start) )
{
- ept_entry->emt = epte_get_entry_emt(d, gfn, mfn, &ipat,
+ ept_entry->emt = epte_get_entry_emt(p2m->domain, gfn, mfn, &ipat,
direct_mmio);
ept_entry->ipat = ipat;
ept_entry->sp = order ? 1 : 0;
@@ -337,9 +338,9 @@ ept_set_entry(struct domain *d, unsigned
split_ept_entry = *ept_entry;
- if ( !ept_split_super_page(d, &split_ept_entry, i, target) )
- {
- ept_free_entry(d, &split_ept_entry, i);
+ if ( !ept_split_super_page(p2m, &split_ept_entry, i, target) )
+ {
+ ept_free_entry(p2m, &split_ept_entry, i);
goto out;
}
@@ -349,7 +350,7 @@ ept_set_entry(struct domain *d, unsigned
/* then move to the level we want to make real changes */
for ( ; i > target; i-- )
- ept_next_level(d, 0, &table, &gfn_remainder, i);
+ ept_next_level(p2m, 0, &table, &gfn_remainder, i);
ASSERT(i == target);
@@ -374,8 +375,8 @@ ept_set_entry(struct domain *d, unsigned
/* Track the highest gfn for which we have ever had a valid mapping */
if ( mfn_valid(mfn_x(mfn)) &&
- (gfn + (1UL << order) - 1 > d->arch.p2m->max_mapped_pfn) )
- d->arch.p2m->max_mapped_pfn = gfn + (1UL << order) - 1;
+ (gfn + (1UL << order) - 1 > p2m->max_mapped_pfn) )
+ p2m->max_mapped_pfn = gfn + (1UL << order) - 1;
/* Success */
rv = 1;
@@ -384,10 +385,10 @@ out:
unmap_domain_page(table);
if ( needs_sync )
- ept_sync_domain(d);
+ ept_sync_domain(p2m->domain);
/* Now the p2m table is not shared with vt-d page table */
- if ( rv && iommu_enabled && need_iommu(d) && need_modify_vtd_table )
+ if ( rv && iommu_enabled && need_iommu(p2m->domain) &&
need_modify_vtd_table )
{
if ( p2mt == p2m_ram_rw )
{
@@ -395,22 +396,22 @@ out:
{
for ( i = 0; i < (1 << order); i++ )
iommu_map_page(
- d, gfn - offset + i, mfn_x(mfn) - offset + i,
+ p2m->domain, gfn - offset + i, mfn_x(mfn) - offset + i,
IOMMUF_readable | IOMMUF_writable);
}
else if ( !order )
iommu_map_page(
- d, gfn, mfn_x(mfn), IOMMUF_readable | IOMMUF_writable);
+ p2m->domain, gfn, mfn_x(mfn), IOMMUF_readable |
IOMMUF_writable);
}
else
{
if ( order == EPT_TABLE_ORDER )
{
for ( i = 0; i < (1 << order); i++ )
- iommu_unmap_page(d, gfn - offset + i);
+ iommu_unmap_page(p2m->domain, gfn - offset + i);
}
else if ( !order )
- iommu_unmap_page(d, gfn);
+ iommu_unmap_page(p2m->domain, gfn);
}
}
@@ -418,9 +419,11 @@ out:
}
/* Read ept p2m entries */
-static mfn_t ept_get_entry(struct domain *d, unsigned long gfn, p2m_type_t *t,
+static mfn_t ept_get_entry(struct p2m_domain *p2m,
+ unsigned long gfn, p2m_type_t *t,
p2m_query_t q)
{
+ struct domain *d = p2m->domain;
ept_entry_t *table = map_domain_page(ept_get_asr(d));
unsigned long gfn_remainder = gfn;
ept_entry_t *ept_entry;
@@ -432,7 +435,7 @@ static mfn_t ept_get_entry(struct domain
*t = p2m_mmio_dm;
/* This pfn is higher than the highest the p2m map currently holds */
- if ( gfn > d->arch.p2m->max_mapped_pfn )
+ if ( gfn > p2m->max_mapped_pfn )
goto out;
/* Should check if gfn obeys GAW here. */
@@ -440,7 +443,7 @@ static mfn_t ept_get_entry(struct domain
for ( i = ept_get_wl(d); i > 0; i-- )
{
retry:
- ret = ept_next_level(d, 1, &table, &gfn_remainder, i);
+ ret = ept_next_level(p2m, 1, &table, &gfn_remainder, i);
if ( !ret )
goto out;
else if ( ret == GUEST_TABLE_POD_PAGE )
@@ -457,7 +460,7 @@ static mfn_t ept_get_entry(struct domain
index = gfn_remainder >> ( i * EPT_TABLE_ORDER);
ept_entry = table + index;
- if ( !ept_pod_check_and_populate(d, gfn,
+ if ( !ept_pod_check_and_populate(p2m, gfn,
ept_entry, 9, q) )
goto retry;
else
@@ -480,7 +483,7 @@ static mfn_t ept_get_entry(struct domain
ASSERT(i == 0);
- if ( ept_pod_check_and_populate(d, gfn,
+ if ( ept_pod_check_and_populate(p2m, gfn,
ept_entry, 0, q) )
goto out;
}
@@ -511,9 +514,10 @@ out:
/* WARNING: Only caller doesn't care about PoD pages. So this function will
* always return 0 for PoD pages, not populate them. If that becomes
necessary,
* pass a p2m_query_t type along to distinguish. */
-static ept_entry_t ept_get_entry_content(struct domain *d, unsigned long gfn,
int *level)
-{
- ept_entry_t *table = map_domain_page(ept_get_asr(d));
+static ept_entry_t ept_get_entry_content(struct p2m_domain *p2m,
+ unsigned long gfn, int *level)
+{
+ ept_entry_t *table = map_domain_page(ept_get_asr(p2m->domain));
unsigned long gfn_remainder = gfn;
ept_entry_t *ept_entry;
ept_entry_t content = { .epte = 0 };
@@ -522,12 +526,12 @@ static ept_entry_t ept_get_entry_content
int ret=0;
/* This pfn is higher than the highest the p2m map currently holds */
- if ( gfn > d->arch.p2m->max_mapped_pfn )
+ if ( gfn > p2m->max_mapped_pfn )
goto out;
- for ( i = ept_get_wl(d); i > 0; i-- )
- {
- ret = ept_next_level(d, 1, &table, &gfn_remainder, i);
+ for ( i = ept_get_wl(p2m->domain); i > 0; i-- )
+ {
+ ret = ept_next_level(p2m, 1, &table, &gfn_remainder, i);
if ( !ret || ret == GUEST_TABLE_POD_PAGE )
goto out;
else if ( ret == GUEST_TABLE_SUPER_PAGE )
@@ -546,6 +550,7 @@ static ept_entry_t ept_get_entry_content
void ept_walk_table(struct domain *d, unsigned long gfn)
{
+ struct p2m_domain *p2m = p2m_get_hostp2m(d);
ept_entry_t *table = map_domain_page(ept_get_asr(d));
unsigned long gfn_remainder = gfn;
@@ -555,10 +560,10 @@ void ept_walk_table(struct domain *d, un
d->domain_id, gfn);
/* This pfn is higher than the highest the p2m map currently holds */
- if ( gfn > d->arch.p2m->max_mapped_pfn )
+ if ( gfn > p2m->max_mapped_pfn )
{
gdprintk(XENLOG_ERR, " gfn exceeds max_mapped_pfn %lx\n",
- d->arch.p2m->max_mapped_pfn);
+ p2m->max_mapped_pfn);
goto out;
}
@@ -593,17 +598,18 @@ out:
return;
}
-static mfn_t ept_get_entry_current(unsigned long gfn, p2m_type_t *t,
+static mfn_t ept_get_entry_current(struct p2m_domain *p2m,
+ unsigned long gfn, p2m_type_t *t,
p2m_query_t q)
{
- return ept_get_entry(current->domain, gfn, t, q);
+ return ept_get_entry(p2m, gfn, t, q);
}
/*
* To test if the new emt type is the same with old,
* return 1 to not to reset ept entry.
*/
-static int need_modify_ept_entry(struct domain *d, unsigned long gfn,
+static int need_modify_ept_entry(struct p2m_domain *p2m, unsigned long gfn,
mfn_t mfn, uint8_t o_ipat, uint8_t o_emt,
p2m_type_t p2mt)
{
@@ -611,7 +617,7 @@ static int need_modify_ept_entry(struct
uint8_t emt;
bool_t direct_mmio = (p2mt == p2m_mmio_direct);
- emt = epte_get_entry_emt(d, gfn, mfn, &ipat, direct_mmio);
+ emt = epte_get_entry_emt(p2m->domain, gfn, mfn, &ipat, direct_mmio);
if ( (emt == o_emt) && (ipat == o_ipat) )
return 0;
@@ -619,21 +625,23 @@ static int need_modify_ept_entry(struct
return 1;
}
-void ept_change_entry_emt_with_range(struct domain *d, unsigned long start_gfn,
+void ept_change_entry_emt_with_range(struct domain *d,
+ unsigned long start_gfn,
unsigned long end_gfn)
{
unsigned long gfn;
ept_entry_t e;
mfn_t mfn;
int order = 0;
-
- p2m_lock(d->arch.p2m);
+ struct p2m_domain *p2m = p2m_get_hostp2m(d);
+
+ p2m_lock(p2m);
for ( gfn = start_gfn; gfn <= end_gfn; gfn++ )
{
int level = 0;
uint64_t trunk = 0;
- e = ept_get_entry_content(d, gfn, &level);
+ e = ept_get_entry_content(p2m, gfn, &level);
if ( !p2m_has_emt(e.avail1) )
continue;
@@ -652,9 +660,9 @@ void ept_change_entry_emt_with_range(str
* Set emt for super page.
*/
order = level * EPT_TABLE_ORDER;
- if ( need_modify_ept_entry(d, gfn, mfn,
+ if ( need_modify_ept_entry(p2m, gfn, mfn,
e.ipat, e.emt, e.avail1) )
- ept_set_entry(d, gfn, mfn, order, e.avail1);
+ ept_set_entry(p2m, gfn, mfn, order, e.avail1);
gfn += trunk;
break;
}
@@ -663,11 +671,11 @@ void ept_change_entry_emt_with_range(str
}
else /* gfn assigned with 4k */
{
- if ( need_modify_ept_entry(d, gfn, mfn, e.ipat, e.emt, e.avail1) )
- ept_set_entry(d, gfn, mfn, order, e.avail1);
- }
- }
- p2m_unlock(d->arch.p2m);
+ if ( need_modify_ept_entry(p2m, gfn, mfn, e.ipat, e.emt, e.avail1)
)
+ ept_set_entry(p2m, gfn, mfn, order, e.avail1);
+ }
+ }
+ p2m_unlock(p2m);
}
/*
@@ -701,9 +709,10 @@ static void ept_change_entry_type_page(m
unmap_domain_page(epte);
}
-static void ept_change_entry_type_global(struct domain *d,
+static void ept_change_entry_type_global(struct p2m_domain *p2m,
p2m_type_t ot, p2m_type_t nt)
{
+ struct domain *d = p2m->domain;
if ( ept_get_asr(d) == 0 )
return;
@@ -714,10 +723,11 @@ static void ept_change_entry_type_global
void ept_p2m_init(struct domain *d)
{
- d->arch.p2m->set_entry = ept_set_entry;
- d->arch.p2m->get_entry = ept_get_entry;
- d->arch.p2m->get_entry_current = ept_get_entry_current;
- d->arch.p2m->change_entry_type_global = ept_change_entry_type_global;
+ struct p2m_domain *p2m = p2m_get_hostp2m(d);
+ p2m->set_entry = ept_set_entry;
+ p2m->get_entry = ept_get_entry;
+ p2m->get_entry_current = ept_get_entry_current;
+ p2m->change_entry_type_global = ept_change_entry_type_global;
}
static void ept_dump_p2m_table(unsigned char key)
@@ -742,7 +752,7 @@ static void ept_dump_p2m_table(unsigned
p2m = p2m_get_hostp2m(d);
printk("\ndomain%d EPT p2m table: \n", d->domain_id);
- for ( gfn = 0; gfn <= d->arch.p2m->max_mapped_pfn; gfn += (1 << order)
)
+ for ( gfn = 0; gfn <= p2m->max_mapped_pfn; gfn += (1 << order) )
{
gfn_remainder = gfn;
mfn = _mfn(INVALID_MFN);
@@ -750,7 +760,7 @@ static void ept_dump_p2m_table(unsigned
for ( i = ept_get_wl(d); i > 0; i-- )
{
- ret = ept_next_level(d, 1, &table, &gfn_remainder, i);
+ ret = ept_next_level(p2m, 1, &table, &gfn_remainder, i);
if ( ret != GUEST_TABLE_NORMAL_PAGE )
break;
}
diff -r 9e58c46ee63b -r e7afe98afd43 xen/arch/x86/mm/mem_event.c
--- a/xen/arch/x86/mm/mem_event.c Mon Aug 09 16:40:18 2010 +0100
+++ b/xen/arch/x86/mm/mem_event.c Mon Aug 09 16:46:42 2010 +0100
@@ -235,7 +235,7 @@ int mem_event_domctl(struct domain *d, x
/* Get MFN of ring page */
guest_get_eff_l1e(v, ring_addr, &l1e);
gfn = l1e_get_pfn(l1e);
- ring_mfn = gfn_to_mfn(dom_mem_event, gfn, &p2mt);
+ ring_mfn = gfn_to_mfn(p2m_get_hostp2m(dom_mem_event), gfn, &p2mt);
rc = -EINVAL;
if ( unlikely(!mfn_valid(mfn_x(ring_mfn))) )
@@ -244,7 +244,7 @@ int mem_event_domctl(struct domain *d, x
/* Get MFN of shared page */
guest_get_eff_l1e(v, shared_addr, &l1e);
gfn = l1e_get_pfn(l1e);
- shared_mfn = gfn_to_mfn(dom_mem_event, gfn, &p2mt);
+ shared_mfn = gfn_to_mfn(p2m_get_hostp2m(dom_mem_event), gfn,
&p2mt);
rc = -EINVAL;
if ( unlikely(!mfn_valid(mfn_x(shared_mfn))) )
diff -r 9e58c46ee63b -r e7afe98afd43 xen/arch/x86/mm/mem_paging.c
--- a/xen/arch/x86/mm/mem_paging.c Mon Aug 09 16:40:18 2010 +0100
+++ b/xen/arch/x86/mm/mem_paging.c Mon Aug 09 16:46:42 2010 +0100
@@ -29,33 +29,34 @@ int mem_paging_domctl(struct domain *d,
XEN_GUEST_HANDLE(void) u_domctl)
{
int rc;
+ struct p2m_domain *p2m = p2m_get_hostp2m(d);
switch( mec->op )
{
case XEN_DOMCTL_MEM_EVENT_OP_PAGING_NOMINATE:
{
unsigned long gfn = mec->gfn;
- rc = p2m_mem_paging_nominate(d, gfn);
+ rc = p2m_mem_paging_nominate(p2m, gfn);
}
break;
case XEN_DOMCTL_MEM_EVENT_OP_PAGING_EVICT:
{
unsigned long gfn = mec->gfn;
- rc = p2m_mem_paging_evict(d, gfn);
+ rc = p2m_mem_paging_evict(p2m, gfn);
}
break;
case XEN_DOMCTL_MEM_EVENT_OP_PAGING_PREP:
{
unsigned long gfn = mec->gfn;
- rc = p2m_mem_paging_prep(d, gfn);
+ rc = p2m_mem_paging_prep(p2m, gfn);
}
break;
case XEN_DOMCTL_MEM_EVENT_OP_PAGING_RESUME:
{
- p2m_mem_paging_resume(d);
+ p2m_mem_paging_resume(p2m);
rc = 0;
}
break;
diff -r 9e58c46ee63b -r e7afe98afd43 xen/arch/x86/mm/mem_sharing.c
--- a/xen/arch/x86/mm/mem_sharing.c Mon Aug 09 16:40:18 2010 +0100
+++ b/xen/arch/x86/mm/mem_sharing.c Mon Aug 09 16:46:42 2010 +0100
@@ -251,6 +251,7 @@ static void mem_sharing_audit(void)
list_for_each(le, &e->gfns)
{
struct domain *d;
+ struct p2m_domain *p2m;
p2m_type_t t;
mfn_t mfn;
@@ -262,7 +263,8 @@ static void mem_sharing_audit(void)
g->domain, g->gfn, mfn_x(e->mfn));
continue;
}
- mfn = gfn_to_mfn(d, g->gfn, &t);
+ p2m = p2m_get_hostp2m(d);
+ mfn = gfn_to_mfn(p2m, g->gfn, &t);
if(mfn_x(mfn) != mfn_x(e->mfn))
MEM_SHARING_DEBUG("Incorrect P2M for d=%d, PFN=%lx."
"Expecting MFN=%ld, got %ld\n",
@@ -377,7 +379,7 @@ int mem_sharing_debug_gfn(struct domain
mfn_t mfn;
struct page_info *page;
- mfn = gfn_to_mfn(d, gfn, &p2mt);
+ mfn = gfn_to_mfn(p2m_get_hostp2m(d), gfn, &p2mt);
page = mfn_to_page(mfn);
printk("Debug for domain=%d, gfn=%lx, ",
@@ -487,7 +489,7 @@ int mem_sharing_debug_gref(struct domain
return mem_sharing_debug_gfn(d, gfn);
}
-int mem_sharing_nominate_page(struct domain *d,
+int mem_sharing_nominate_page(struct p2m_domain *p2m,
unsigned long gfn,
int expected_refcnt,
shr_handle_t *phandle)
@@ -499,10 +501,11 @@ int mem_sharing_nominate_page(struct dom
shr_handle_t handle;
shr_hash_entry_t *hash_entry;
struct gfn_info *gfn_info;
+ struct domain *d = p2m->domain;
*phandle = 0UL;
- mfn = gfn_to_mfn(d, gfn, &p2mt);
+ mfn = gfn_to_mfn(p2m, gfn, &p2mt);
/* Check if mfn is valid */
ret = -EINVAL;
@@ -536,7 +539,7 @@ int mem_sharing_nominate_page(struct dom
}
/* Change the p2m type */
- if(p2m_change_type(d, gfn, p2mt, p2m_ram_shared) != p2mt)
+ if(p2m_change_type(p2m, gfn, p2mt, p2m_ram_shared) != p2mt)
{
/* This is unlikely, as the type must have changed since we've checked
* it a few lines above.
@@ -599,7 +602,7 @@ int mem_sharing_share_pages(shr_handle_t
list_del(&gfn->list);
d = get_domain_by_id(gfn->domain);
BUG_ON(!d);
- BUG_ON(set_shared_p2m_entry(d, gfn->gfn, se->mfn) == 0);
+ BUG_ON(set_shared_p2m_entry(p2m_get_hostp2m(d), gfn->gfn, se->mfn) ==
0);
put_domain(d);
list_add(&gfn->list, &se->gfns);
put_page_and_type(cpage);
@@ -618,7 +621,7 @@ err_out:
return ret;
}
-int mem_sharing_unshare_page(struct domain *d,
+int mem_sharing_unshare_page(struct p2m_domain *p2m,
unsigned long gfn,
uint16_t flags)
{
@@ -631,8 +634,9 @@ int mem_sharing_unshare_page(struct doma
struct gfn_info *gfn_info = NULL;
shr_handle_t handle;
struct list_head *le;
-
- mfn = gfn_to_mfn(d, gfn, &p2mt);
+ struct domain *d = p2m->domain;
+
+ mfn = gfn_to_mfn(p2m, gfn, &p2mt);
page = mfn_to_page(mfn);
handle = page->shr_handle;
@@ -696,7 +700,7 @@ gfn_found:
unmap_domain_page(s);
unmap_domain_page(t);
- ASSERT(set_shared_p2m_entry(d, gfn, page_to_mfn(page)) != 0);
+ ASSERT(set_shared_p2m_entry(p2m, gfn, page_to_mfn(page)) != 0);
put_page_and_type(old_page);
private_page_found:
@@ -708,7 +712,7 @@ private_page_found:
atomic_dec(&nr_saved_mfns);
shr_unlock();
- if(p2m_change_type(d, gfn, p2m_ram_shared, p2m_ram_rw) !=
+ if(p2m_change_type(p2m, gfn, p2m_ram_shared, p2m_ram_rw) !=
p2m_ram_shared)
{
printk("Could not change p2m type.\n");
@@ -740,7 +744,7 @@ int mem_sharing_domctl(struct domain *d,
shr_handle_t handle;
if(!mem_sharing_enabled(d))
return -EINVAL;
- rc = mem_sharing_nominate_page(d, gfn, 0, &handle);
+ rc = mem_sharing_nominate_page(p2m_get_hostp2m(d), gfn, 0,
&handle);
mec->u.nominate.handle = handle;
mem_sharing_audit();
}
@@ -756,7 +760,8 @@ int mem_sharing_domctl(struct domain *d,
return -EINVAL;
if(mem_sharing_gref_to_gfn(d, gref, &gfn) < 0)
return -EINVAL;
- rc = mem_sharing_nominate_page(d, gfn, 3, &handle);
+ rc = mem_sharing_nominate_page(p2m_get_hostp2m(d),
+ gfn, 3, &handle);
mec->u.nominate.handle = handle;
mem_sharing_audit();
}
diff -r 9e58c46ee63b -r e7afe98afd43 xen/arch/x86/mm/p2m.c
--- a/xen/arch/x86/mm/p2m.c Mon Aug 09 16:40:18 2010 +0100
+++ b/xen/arch/x86/mm/p2m.c Mon Aug 09 16:46:42 2010 +0100
@@ -108,9 +108,9 @@ static unsigned long p2m_type_to_flags(p
}
#if P2M_AUDIT
-static void audit_p2m(struct domain *d);
+static void audit_p2m(struct p2m_domain *p2m);
#else
-# define audit_p2m(_d) do { (void)(_d); } while(0)
+# define audit_p2m(_p2m) do { (void)(_p2m); } while(0)
#endif /* P2M_AUDIT */
// Find the next level's P2M entry, checking for out-of-range gfn's...
@@ -135,15 +135,17 @@ p2m_find_entry(void *table, unsigned lon
}
struct page_info *
-p2m_alloc_ptp(struct domain *d, unsigned long type)
+p2m_alloc_ptp(struct p2m_domain *p2m, unsigned long type)
{
struct page_info *pg;
- pg = d->arch.p2m->alloc_page(d);
+ ASSERT(p2m);
+ ASSERT(p2m->alloc_page);
+ pg = p2m->alloc_page(p2m);
if (pg == NULL)
return NULL;
- page_list_add_tail(pg, &d->arch.p2m->pages);
+ page_list_add_tail(pg, &p2m->pages);
pg->u.inuse.type_info = type | 1 | PGT_validated;
pg->count_info |= 1;
@@ -154,7 +156,7 @@ p2m_alloc_ptp(struct domain *d, unsigned
// Returns 0 on error.
//
static int
-p2m_next_level(struct domain *d, mfn_t *table_mfn, void **table,
+p2m_next_level(struct p2m_domain *p2m, mfn_t *table_mfn, void **table,
unsigned long *gfn_remainder, unsigned long gfn, u32 shift,
u32 max, unsigned long type)
{
@@ -163,7 +165,7 @@ p2m_next_level(struct domain *d, mfn_t *
l1_pgentry_t new_entry;
void *next;
int i;
- ASSERT(d->arch.p2m->alloc_page);
+ ASSERT(p2m->alloc_page);
if ( !(p2m_entry = p2m_find_entry(*table, gfn_remainder, gfn,
shift, max)) )
@@ -174,7 +176,7 @@ p2m_next_level(struct domain *d, mfn_t *
{
struct page_info *pg;
- pg = p2m_alloc_ptp(d, type);
+ pg = p2m_alloc_ptp(p2m, type);
if ( pg == NULL )
return 0;
@@ -183,7 +185,7 @@ p2m_next_level(struct domain *d, mfn_t *
switch ( type ) {
case PGT_l3_page_table:
- paging_write_p2m_entry(d, gfn,
+ paging_write_p2m_entry(p2m->domain, gfn,
p2m_entry, *table_mfn, new_entry, 4);
break;
case PGT_l2_page_table:
@@ -191,11 +193,11 @@ p2m_next_level(struct domain *d, mfn_t *
/* for PAE mode, PDPE only has PCD/PWT/P bits available */
new_entry = l1e_from_pfn(mfn_x(page_to_mfn(pg)), _PAGE_PRESENT);
#endif
- paging_write_p2m_entry(d, gfn,
+ paging_write_p2m_entry(p2m->domain, gfn,
p2m_entry, *table_mfn, new_entry, 3);
break;
case PGT_l1_page_table:
- paging_write_p2m_entry(d, gfn,
+ paging_write_p2m_entry(p2m->domain, gfn,
p2m_entry, *table_mfn, new_entry, 2);
break;
default:
@@ -212,7 +214,7 @@ p2m_next_level(struct domain *d, mfn_t *
unsigned long flags, pfn;
struct page_info *pg;
- pg = p2m_alloc_ptp(d, PGT_l2_page_table);
+ pg = p2m_alloc_ptp(p2m, PGT_l2_page_table);
if ( pg == NULL )
return 0;
@@ -223,13 +225,13 @@ p2m_next_level(struct domain *d, mfn_t *
for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ )
{
new_entry = l1e_from_pfn(pfn + (i * L1_PAGETABLE_ENTRIES), flags);
- paging_write_p2m_entry(d, gfn, l1_entry+i, *table_mfn, new_entry,
- 2);
+ paging_write_p2m_entry(p2m->domain, gfn,
+ l1_entry+i, *table_mfn, new_entry, 2);
}
unmap_domain_page(l1_entry);
new_entry = l1e_from_pfn(mfn_x(page_to_mfn(pg)),
__PAGE_HYPERVISOR|_PAGE_USER); //disable PSE
- paging_write_p2m_entry(d, gfn,
+ paging_write_p2m_entry(p2m->domain, gfn,
p2m_entry, *table_mfn, new_entry, 3);
}
@@ -240,7 +242,7 @@ p2m_next_level(struct domain *d, mfn_t *
unsigned long flags, pfn;
struct page_info *pg;
- pg = p2m_alloc_ptp(d, PGT_l1_page_table);
+ pg = p2m_alloc_ptp(p2m, PGT_l1_page_table);
if ( pg == NULL )
return 0;
@@ -257,14 +259,14 @@ p2m_next_level(struct domain *d, mfn_t *
for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )
{
new_entry = l1e_from_pfn(pfn + i, flags);
- paging_write_p2m_entry(d, gfn,
+ paging_write_p2m_entry(p2m->domain, gfn,
l1_entry+i, *table_mfn, new_entry, 1);
}
unmap_domain_page(l1_entry);
new_entry = l1e_from_pfn(mfn_x(page_to_mfn(pg)),
__PAGE_HYPERVISOR|_PAGE_USER);
- paging_write_p2m_entry(d, gfn,
+ paging_write_p2m_entry(p2m->domain, gfn,
p2m_entry, *table_mfn, new_entry, 2);
}
@@ -280,17 +282,17 @@ p2m_next_level(struct domain *d, mfn_t *
* Populate-on-demand functionality
*/
static
-int set_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn,
+int set_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn,
unsigned int page_order, p2m_type_t p2mt);
static int
-p2m_pod_cache_add(struct domain *d,
+p2m_pod_cache_add(struct p2m_domain *p2m,
struct page_info *page,
unsigned long order)
{
int i;
struct page_info *p;
- struct p2m_domain *p2md = d->arch.p2m;
+ struct domain *d = p2m->domain;
#ifndef NDEBUG
mfn_t mfn;
@@ -320,7 +322,7 @@ p2m_pod_cache_add(struct domain *d,
}
#endif
- ASSERT(p2m_locked_by_me(p2md));
+ ASSERT(p2m_locked_by_me(p2m));
/*
* Pages from domain_alloc and returned by the balloon driver aren't
@@ -347,12 +349,12 @@ p2m_pod_cache_add(struct domain *d,
switch(order)
{
case 9:
- page_list_add_tail(page, &p2md->pod.super); /* lock: page_alloc */
- p2md->pod.count += 1 << order;
+ page_list_add_tail(page, &p2m->pod.super); /* lock: page_alloc */
+ p2m->pod.count += 1 << order;
break;
case 0:
- page_list_add_tail(page, &p2md->pod.single); /* lock: page_alloc */
- p2md->pod.count += 1 ;
+ page_list_add_tail(page, &p2m->pod.single); /* lock: page_alloc */
+ p2m->pod.count += 1;
break;
default:
BUG();
@@ -371,57 +373,56 @@ p2m_pod_cache_add(struct domain *d,
* down 2-meg pages into singleton pages automatically. Returns null if
* a superpage is requested and no superpages are available. Must be called
* with the d->page_lock held. */
-static struct page_info * p2m_pod_cache_get(struct domain *d,
+static struct page_info * p2m_pod_cache_get(struct p2m_domain *p2m,
unsigned long order)
{
- struct p2m_domain *p2md = d->arch.p2m;
struct page_info *p = NULL;
int i;
- if ( order == 9 && page_list_empty(&p2md->pod.super) )
+ if ( order == 9 && page_list_empty(&p2m->pod.super) )
{
return NULL;
}
- else if ( order == 0 && page_list_empty(&p2md->pod.single) )
+ else if ( order == 0 && page_list_empty(&p2m->pod.single) )
{
unsigned long mfn;
struct page_info *q;
- BUG_ON( page_list_empty(&p2md->pod.super) );
+ BUG_ON( page_list_empty(&p2m->pod.super) );
/* Break up a superpage to make single pages. NB count doesn't
* need to be adjusted. */
- p = page_list_remove_head(&p2md->pod.super);
+ p = page_list_remove_head(&p2m->pod.super);
mfn = mfn_x(page_to_mfn(p));
for ( i=0; i<SUPERPAGE_PAGES; i++ )
{
q = mfn_to_page(_mfn(mfn+i));
- page_list_add_tail(q, &p2md->pod.single);
+ page_list_add_tail(q, &p2m->pod.single);
}
}
switch ( order )
{
case 9:
- BUG_ON( page_list_empty(&p2md->pod.super) );
- p = page_list_remove_head(&p2md->pod.super);
- p2md->pod.count -= 1 << order; /* Lock: page_alloc */
+ BUG_ON( page_list_empty(&p2m->pod.super) );
+ p = page_list_remove_head(&p2m->pod.super);
+ p2m->pod.count -= 1 << order; /* Lock: page_alloc */
break;
case 0:
- BUG_ON( page_list_empty(&p2md->pod.single) );
- p = page_list_remove_head(&p2md->pod.single);
- p2md->pod.count -= 1;
+ BUG_ON( page_list_empty(&p2m->pod.single) );
+ p = page_list_remove_head(&p2m->pod.single);
+ p2m->pod.count -= 1;
break;
default:
BUG();
}
/* Put the pages back on the domain page_list */
- for ( i = 0 ; i < (1 << order) ; i++ )
- {
- BUG_ON(page_get_owner(p + i) != d);
- page_list_add_tail(p + i, &d->page_list);
+ for ( i = 0 ; i < (1 << order); i++ )
+ {
+ BUG_ON(page_get_owner(p + i) != p2m->domain);
+ page_list_add_tail(p + i, &p2m->domain->page_list);
}
return p;
@@ -429,18 +430,18 @@ static struct page_info * p2m_pod_cache_
/* Set the size of the cache, allocating or freeing as necessary. */
static int
-p2m_pod_set_cache_target(struct domain *d, unsigned long pod_target)
-{
- struct p2m_domain *p2md = d->arch.p2m;
+p2m_pod_set_cache_target(struct p2m_domain *p2m, unsigned long pod_target)
+{
+ struct domain *d = p2m->domain;
int ret = 0;
/* Increasing the target */
- while ( pod_target > p2md->pod.count )
+ while ( pod_target > p2m->pod.count )
{
struct page_info * page;
int order;
- if ( (pod_target - p2md->pod.count) >= SUPERPAGE_PAGES )
+ if ( (pod_target - p2m->pod.count) >= SUPERPAGE_PAGES )
order = 9;
else
order = 0;
@@ -456,18 +457,18 @@ p2m_pod_set_cache_target(struct domain *
}
printk("%s: Unable to allocate domheap page for pod cache. target
%lu cachesize %d\n",
- __func__, pod_target, p2md->pod.count);
+ __func__, pod_target, p2m->pod.count);
ret = -ENOMEM;
goto out;
}
- p2m_pod_cache_add(d, page, order);
+ p2m_pod_cache_add(p2m, page, order);
}
/* Decreasing the target */
/* We hold the p2m lock here, so we don't need to worry about
* cache disappearing under our feet. */
- while ( pod_target < p2md->pod.count )
+ while ( pod_target < p2m->pod.count )
{
struct page_info * page;
int order, i;
@@ -476,13 +477,13 @@ p2m_pod_set_cache_target(struct domain *
* entries may disappear before we grab the lock. */
spin_lock(&d->page_alloc_lock);
- if ( (p2md->pod.count - pod_target) > SUPERPAGE_PAGES
- && !page_list_empty(&p2md->pod.super) )
+ if ( (p2m->pod.count - pod_target) > SUPERPAGE_PAGES
+ && !page_list_empty(&p2m->pod.super) )
order = 9;
else
order = 0;
- page = p2m_pod_cache_get(d, order);
+ page = p2m_pod_cache_get(p2m, order);
ASSERT(page != NULL);
@@ -553,14 +554,14 @@ p2m_pod_set_mem_target(struct domain *d,
p2m_pod_set_mem_target(struct domain *d, unsigned long target)
{
unsigned pod_target;
- struct p2m_domain *p2md = d->arch.p2m;
+ struct p2m_domain *p2m = p2m_get_hostp2m(d);
int ret = 0;
unsigned long populated;
- p2m_lock(p2md);
+ p2m_lock(p2m);
/* P == B: Nothing to do. */
- if ( p2md->pod.entry_count == 0 )
+ if ( p2m->pod.entry_count == 0 )
goto out;
/* Don't do anything if the domain is being torn down */
@@ -572,21 +573,21 @@ p2m_pod_set_mem_target(struct domain *d,
if ( target < d->tot_pages )
goto out;
- populated = d->tot_pages - p2md->pod.count;
+ populated = d->tot_pages - p2m->pod.count;
pod_target = target - populated;
/* B < T': Set the cache size equal to # of outstanding entries,
* let the balloon driver fill in the rest. */
- if ( pod_target > p2md->pod.entry_count )
- pod_target = p2md->pod.entry_count;
-
- ASSERT( pod_target >= p2md->pod.count );
-
- ret = p2m_pod_set_cache_target(d, pod_target);
+ if ( pod_target > p2m->pod.entry_count )
+ pod_target = p2m->pod.entry_count;
+
+ ASSERT( pod_target >= p2m->pod.count );
+
+ ret = p2m_pod_set_cache_target(p2m, pod_target);
out:
- p2m_unlock(p2md);
+ p2m_unlock(p2m);
return ret;
}
@@ -594,16 +595,16 @@ void
void
p2m_pod_empty_cache(struct domain *d)
{
- struct p2m_domain *p2md = d->arch.p2m;
+ struct p2m_domain *p2m = p2m_get_hostp2m(d);
struct page_info *page;
/* After this barrier no new PoD activities can happen. */
BUG_ON(!d->is_dying);
- spin_barrier(&p2md->lock);
+ spin_barrier(&p2m->lock);
spin_lock(&d->page_alloc_lock);
- while ( (page = page_list_remove_head(&p2md->pod.super)) )
+ while ( (page = page_list_remove_head(&p2m->pod.super)) )
{
int i;
@@ -613,18 +614,18 @@ p2m_pod_empty_cache(struct domain *d)
page_list_add_tail(page + i, &d->page_list);
}
- p2md->pod.count -= SUPERPAGE_PAGES;
- }
-
- while ( (page = page_list_remove_head(&p2md->pod.single)) )
+ p2m->pod.count -= SUPERPAGE_PAGES;
+ }
+
+ while ( (page = page_list_remove_head(&p2m->pod.single)) )
{
BUG_ON(page_get_owner(page) != d);
page_list_add_tail(page, &d->page_list);
- p2md->pod.count -= 1;
- }
-
- BUG_ON(p2md->pod.count != 0);
+ p2m->pod.count -= 1;
+ }
+
+ BUG_ON(p2m->pod.count != 0);
spin_unlock(&d->page_alloc_lock);
}
@@ -642,9 +643,9 @@ p2m_pod_decrease_reservation(struct doma
xen_pfn_t gpfn,
unsigned int order)
{
- struct p2m_domain *p2md = d->arch.p2m;
int ret=0;
int i;
+ struct p2m_domain *p2m = p2m_get_hostp2m(d);
int steal_for_cache = 0;
int pod = 0, nonpod = 0, ram = 0;
@@ -652,14 +653,14 @@ p2m_pod_decrease_reservation(struct doma
/* If we don't have any outstanding PoD entries, let things take their
* course */
- if ( p2md->pod.entry_count == 0 )
+ if ( p2m->pod.entry_count == 0 )
goto out;
/* Figure out if we need to steal some freed memory for our cache */
- steal_for_cache = ( p2md->pod.entry_count > p2md->pod.count );
-
- p2m_lock(p2md);
- audit_p2m(d);
+ steal_for_cache = ( p2m->pod.entry_count > p2m->pod.count );
+
+ p2m_lock(p2m);
+ audit_p2m(p2m);
if ( unlikely(d->is_dying) )
goto out_unlock;
@@ -670,7 +671,7 @@ p2m_pod_decrease_reservation(struct doma
{
p2m_type_t t;
- gfn_to_mfn_query(d, gpfn + i, &t);
+ gfn_to_mfn_query(p2m, gpfn + i, &t);
if ( t == p2m_populate_on_demand )
pod++;
@@ -690,9 +691,9 @@ p2m_pod_decrease_reservation(struct doma
{
/* All PoD: Mark the whole region invalid and tell caller
* we're done. */
- set_p2m_entry(d, gpfn, _mfn(INVALID_MFN), order, p2m_invalid);
- p2md->pod.entry_count-=(1<<order); /* Lock: p2m */
- BUG_ON(p2md->pod.entry_count < 0);
+ set_p2m_entry(p2m, gpfn, _mfn(INVALID_MFN), order, p2m_invalid);
+ p2m->pod.entry_count-=(1<<order); /* Lock: p2m */
+ BUG_ON(p2m->pod.entry_count < 0);
ret = 1;
goto out_entry_check;
}
@@ -710,12 +711,12 @@ p2m_pod_decrease_reservation(struct doma
mfn_t mfn;
p2m_type_t t;
- mfn = gfn_to_mfn_query(d, gpfn + i, &t);
+ mfn = gfn_to_mfn_query(p2m, gpfn + i, &t);
if ( t == p2m_populate_on_demand )
{
- set_p2m_entry(d, gpfn + i, _mfn(INVALID_MFN), 0, p2m_invalid);
- p2md->pod.entry_count--; /* Lock: p2m */
- BUG_ON(p2md->pod.entry_count < 0);
+ set_p2m_entry(p2m, gpfn + i, _mfn(INVALID_MFN), 0, p2m_invalid);
+ p2m->pod.entry_count--; /* Lock: p2m */
+ BUG_ON(p2m->pod.entry_count < 0);
pod--;
}
else if ( steal_for_cache && p2m_is_ram(t) )
@@ -726,12 +727,12 @@ p2m_pod_decrease_reservation(struct doma
page = mfn_to_page(mfn);
- set_p2m_entry(d, gpfn + i, _mfn(INVALID_MFN), 0, p2m_invalid);
+ set_p2m_entry(p2m, gpfn + i, _mfn(INVALID_MFN), 0, p2m_invalid);
set_gpfn_from_mfn(mfn_x(mfn), INVALID_M2P_ENTRY);
- p2m_pod_cache_add(d, page, 0);
-
- steal_for_cache = ( p2md->pod.entry_count > p2md->pod.count );
+ p2m_pod_cache_add(p2m, page, 0);
+
+ steal_for_cache = ( p2m->pod.entry_count > p2m->pod.count );
nonpod--;
ram--;
@@ -745,33 +746,31 @@ p2m_pod_decrease_reservation(struct doma
out_entry_check:
/* If we've reduced our "liabilities" beyond our "assets", free some */
- if ( p2md->pod.entry_count < p2md->pod.count )
- {
- p2m_pod_set_cache_target(d, p2md->pod.entry_count);
+ if ( p2m->pod.entry_count < p2m->pod.count )
+ {
+ p2m_pod_set_cache_target(p2m, p2m->pod.entry_count);
}
out_unlock:
- audit_p2m(d);
- p2m_unlock(p2md);
+ audit_p2m(p2m);
+ p2m_unlock(p2m);
out:
return ret;
}
void
-p2m_pod_dump_data(struct domain *d)
-{
- struct p2m_domain *p2md = d->arch.p2m;
-
+p2m_pod_dump_data(struct p2m_domain *p2m)
+{
printk(" PoD entries=%d cachesize=%d\n",
- p2md->pod.entry_count, p2md->pod.count);
+ p2m->pod.entry_count, p2m->pod.count);
}
/* Search for all-zero superpages to be reclaimed as superpages for the
* PoD cache. Must be called w/ p2m lock held, page_alloc lock not held. */
static int
-p2m_pod_zero_check_superpage(struct domain *d, unsigned long gfn)
+p2m_pod_zero_check_superpage(struct p2m_domain *p2m, unsigned long gfn)
{
mfn_t mfn, mfn0 = _mfn(INVALID_MFN);
p2m_type_t type, type0 = 0;
@@ -779,6 +778,7 @@ p2m_pod_zero_check_superpage(struct doma
int ret=0, reset = 0;
int i, j;
int max_ref = 1;
+ struct domain *d = p2m->domain;
if ( !superpage_aligned(gfn) )
goto out;
@@ -792,7 +792,7 @@ p2m_pod_zero_check_superpage(struct doma
for ( i=0; i<SUPERPAGE_PAGES; i++ )
{
- mfn = gfn_to_mfn_query(d, gfn + i, &type);
+ mfn = gfn_to_mfn_query(p2m, gfn + i, &type);
if ( i == 0 )
{
@@ -840,7 +840,7 @@ p2m_pod_zero_check_superpage(struct doma
}
/* Try to remove the page, restoring old mapping if it fails. */
- set_p2m_entry(d, gfn,
+ set_p2m_entry(p2m, gfn,
_mfn(POPULATE_ON_DEMAND_MFN), 9,
p2m_populate_on_demand);
@@ -892,23 +892,24 @@ p2m_pod_zero_check_superpage(struct doma
/* Finally! We've passed all the checks, and can add the mfn superpage
* back on the PoD cache, and account for the new p2m PoD entries */
- p2m_pod_cache_add(d, mfn_to_page(mfn0), 9);
- d->arch.p2m->pod.entry_count += SUPERPAGE_PAGES;
+ p2m_pod_cache_add(p2m, mfn_to_page(mfn0), 9);
+ p2m->pod.entry_count += SUPERPAGE_PAGES;
out_reset:
if ( reset )
- set_p2m_entry(d, gfn, mfn0, 9, type0);
+ set_p2m_entry(p2m, gfn, mfn0, 9, type0);
out:
return ret;
}
static void
-p2m_pod_zero_check(struct domain *d, unsigned long *gfns, int count)
+p2m_pod_zero_check(struct p2m_domain *p2m, unsigned long *gfns, int count)
{
mfn_t mfns[count];
p2m_type_t types[count];
unsigned long * map[count];
+ struct domain *d = p2m->domain;
int i, j;
int max_ref = 1;
@@ -920,7 +921,7 @@ p2m_pod_zero_check(struct domain *d, uns
/* First, get the gfn list, translate to mfns, and map the pages. */
for ( i=0; i<count; i++ )
{
- mfns[i] = gfn_to_mfn_query(d, gfns[i], types + i);
+ mfns[i] = gfn_to_mfn_query(p2m, gfns[i], types + i);
/* If this is ram, and not a pagetable or from the xen heap, and
probably not mapped
elsewhere, map it; otherwise, skip. */
if ( p2m_is_ram(types[i])
@@ -952,7 +953,7 @@ p2m_pod_zero_check(struct domain *d, uns
}
/* Try to remove the page, restoring old mapping if it fails. */
- set_p2m_entry(d, gfns[i],
+ set_p2m_entry(p2m, gfns[i],
_mfn(POPULATE_ON_DEMAND_MFN), 0,
p2m_populate_on_demand);
@@ -963,7 +964,7 @@ p2m_pod_zero_check(struct domain *d, uns
unmap_domain_page(map[i]);
map[i] = NULL;
- set_p2m_entry(d, gfns[i], mfns[i], 0, types[i]);
+ set_p2m_entry(p2m, gfns[i], mfns[i], 0, types[i]);
continue;
}
@@ -985,7 +986,7 @@ p2m_pod_zero_check(struct domain *d, uns
* check timing. */
if ( j < PAGE_SIZE/sizeof(*map[i]) )
{
- set_p2m_entry(d, gfns[i], mfns[i], 0, types[i]);
+ set_p2m_entry(p2m, gfns[i], mfns[i], 0, types[i]);
}
else
{
@@ -1005,8 +1006,8 @@ p2m_pod_zero_check(struct domain *d, uns
}
/* Add to cache, and account for the new p2m PoD entry */
- p2m_pod_cache_add(d, mfn_to_page(mfns[i]), 0);
- d->arch.p2m->pod.entry_count++;
+ p2m_pod_cache_add(p2m, mfn_to_page(mfns[i]), 0);
+ p2m->pod.entry_count++;
}
}
@@ -1014,56 +1015,53 @@ p2m_pod_zero_check(struct domain *d, uns
#define POD_SWEEP_LIMIT 1024
static void
-p2m_pod_emergency_sweep_super(struct domain *d)
-{
- struct p2m_domain *p2md = d->arch.p2m;
+p2m_pod_emergency_sweep_super(struct p2m_domain *p2m)
+{
unsigned long i, start, limit;
- if ( p2md->pod.reclaim_super == 0 )
- {
- p2md->pod.reclaim_super = (p2md->pod.max_guest>>9)<<9;
- p2md->pod.reclaim_super -= SUPERPAGE_PAGES;
+ if ( p2m->pod.reclaim_super == 0 )
+ {
+ p2m->pod.reclaim_super = (p2m->pod.max_guest>>9)<<9;
+ p2m->pod.reclaim_super -= SUPERPAGE_PAGES;
}
- start = p2md->pod.reclaim_super;
+ start = p2m->pod.reclaim_super;
limit = (start > POD_SWEEP_LIMIT) ? (start - POD_SWEEP_LIMIT) : 0;
- for ( i=p2md->pod.reclaim_super ; i > 0 ; i-=SUPERPAGE_PAGES )
- {
- p2m_pod_zero_check_superpage(d, i);
+ for ( i=p2m->pod.reclaim_super ; i > 0 ; i -= SUPERPAGE_PAGES )
+ {
+ p2m_pod_zero_check_superpage(p2m, i);
/* Stop if we're past our limit and we have found *something*.
*
* NB that this is a zero-sum game; we're increasing our cache size
* by increasing our 'debt'. Since we hold the p2m lock,
* (entry_count - count) must remain the same. */
- if ( !page_list_empty(&p2md->pod.super) && i < limit )
+ if ( !page_list_empty(&p2m->pod.super) && i < limit )
break;
}
- p2md->pod.reclaim_super = i ? i - SUPERPAGE_PAGES : 0;
-
+ p2m->pod.reclaim_super = i ? i - SUPERPAGE_PAGES : 0;
}
#define POD_SWEEP_STRIDE 16
static void
-p2m_pod_emergency_sweep(struct domain *d)
-{
- struct p2m_domain *p2md = d->arch.p2m;
+p2m_pod_emergency_sweep(struct p2m_domain *p2m)
+{
unsigned long gfns[POD_SWEEP_STRIDE];
unsigned long i, j=0, start, limit;
p2m_type_t t;
- if ( p2md->pod.reclaim_single == 0 )
- p2md->pod.reclaim_single = p2md->pod.max_guest;
-
- start = p2md->pod.reclaim_single;
+ if ( p2m->pod.reclaim_single == 0 )
+ p2m->pod.reclaim_single = p2m->pod.max_guest;
+
+ start = p2m->pod.reclaim_single;
limit = (start > POD_SWEEP_LIMIT) ? (start - POD_SWEEP_LIMIT) : 0;
/* FIXME: Figure out how to avoid superpages */
- for ( i=p2md->pod.reclaim_single ; i > 0 ; i-- )
- {
- gfn_to_mfn_query(d, i, &t );
+ for ( i=p2m->pod.reclaim_single; i > 0 ; i-- )
+ {
+ gfn_to_mfn_query(p2m, i, &t );
if ( p2m_is_ram(t) )
{
gfns[j] = i;
@@ -1071,7 +1069,7 @@ p2m_pod_emergency_sweep(struct domain *d
BUG_ON(j > POD_SWEEP_STRIDE);
if ( j == POD_SWEEP_STRIDE )
{
- p2m_pod_zero_check(d, gfns, j);
+ p2m_pod_zero_check(p2m, gfns, j);
j = 0;
}
}
@@ -1080,29 +1078,29 @@ p2m_pod_emergency_sweep(struct domain *d
* NB that this is a zero-sum game; we're increasing our cache size
* by re-increasing our 'debt'. Since we hold the p2m lock,
* (entry_count - count) must remain the same. */
- if ( p2md->pod.count > 0 && i < limit )
+ if ( p2m->pod.count > 0 && i < limit )
break;
}
if ( j )
- p2m_pod_zero_check(d, gfns, j);
-
- p2md->pod.reclaim_single = i ? i - 1 : i;
+ p2m_pod_zero_check(p2m, gfns, j);
+
+ p2m->pod.reclaim_single = i ? i - 1 : i;
}
int
-p2m_pod_demand_populate(struct domain *d, unsigned long gfn,
+p2m_pod_demand_populate(struct p2m_domain *p2m, unsigned long gfn,
unsigned int order,
p2m_query_t q)
{
+ struct domain *d = p2m->domain;
struct page_info *p = NULL; /* Compiler warnings */
unsigned long gfn_aligned;
mfn_t mfn;
- struct p2m_domain *p2md = d->arch.p2m;
int i;
- ASSERT(p2m_locked_by_me(d->arch.p2m));
+ ASSERT(p2m_locked_by_me(p2m));
/* This check is done with the p2m lock held. This will make sure that
* even if d->is_dying changes under our feet, p2m_pod_empty_cache()
@@ -1120,34 +1118,34 @@ p2m_pod_demand_populate(struct domain *d
* set_p2m_entry() should automatically shatter the 1GB page into
* 512 2MB pages. The rest of 511 calls are unnecessary.
*/
- set_p2m_entry(d, gfn_aligned, _mfn(POPULATE_ON_DEMAND_MFN), 9,
+ set_p2m_entry(p2m, gfn_aligned, _mfn(POPULATE_ON_DEMAND_MFN), 9,
p2m_populate_on_demand);
- audit_p2m(d);
- p2m_unlock(p2md);
+ audit_p2m(p2m);
+ p2m_unlock(p2m);
return 0;
}
/* If we're low, start a sweep */
- if ( order == 9 && page_list_empty(&p2md->pod.super) )
- p2m_pod_emergency_sweep_super(d);
-
- if ( page_list_empty(&p2md->pod.single) &&
+ if ( order == 9 && page_list_empty(&p2m->pod.super) )
+ p2m_pod_emergency_sweep_super(p2m);
+
+ if ( page_list_empty(&p2m->pod.single) &&
( ( order == 0 )
- || (order == 9 && page_list_empty(&p2md->pod.super) ) ) )
- p2m_pod_emergency_sweep(d);
+ || (order == 9 && page_list_empty(&p2m->pod.super) ) ) )
+ p2m_pod_emergency_sweep(p2m);
/* Keep track of the highest gfn demand-populated by a guest fault */
- if ( q == p2m_guest && gfn > p2md->pod.max_guest )
- p2md->pod.max_guest = gfn;
+ if ( q == p2m_guest && gfn > p2m->pod.max_guest )
+ p2m->pod.max_guest = gfn;
spin_lock(&d->page_alloc_lock);
- if ( p2md->pod.count == 0 )
+ if ( p2m->pod.count == 0 )
goto out_of_memory;
/* Get a page f/ the cache. A NULL return value indicates that the
* 2-meg range should be marked singleton PoD, and retried */
- if ( (p = p2m_pod_cache_get(d, order)) == NULL )
+ if ( (p = p2m_pod_cache_get(p2m, order)) == NULL )
goto remap_and_retry;
mfn = page_to_mfn(p);
@@ -1158,13 +1156,13 @@ p2m_pod_demand_populate(struct domain *d
gfn_aligned = (gfn >> order) << order;
- set_p2m_entry(d, gfn_aligned, mfn, order, p2m_ram_rw);
-
- for( i = 0 ; i < (1UL << order) ; i++ )
+ set_p2m_entry(p2m, gfn_aligned, mfn, order, p2m_ram_rw);
+
+ for( i = 0; i < (1UL << order); i++ )
set_gpfn_from_mfn(mfn_x(mfn) + i, gfn_aligned + i);
- p2md->pod.entry_count -= (1 << order); /* Lock: p2m */
- BUG_ON(p2md->pod.entry_count < 0);
+ p2m->pod.entry_count -= (1 << order); /* Lock: p2m */
+ BUG_ON(p2m->pod.entry_count < 0);
if ( tb_init_done )
{
@@ -1186,7 +1184,7 @@ out_of_memory:
spin_unlock(&d->page_alloc_lock);
printk("%s: Out of populate-on-demand memory! tot_pages %" PRIu32 "
pod_entries %" PRIi32 "\n",
- __func__, d->tot_pages, p2md->pod.entry_count);
+ __func__, d->tot_pages, p2m->pod.entry_count);
domain_crash(d);
out_fail:
return -1;
@@ -1197,7 +1195,7 @@ remap_and_retry:
/* Remap this 2-meg region in singleton chunks */
gfn_aligned = (gfn>>order)<<order;
for(i=0; i<(1<<order); i++)
- set_p2m_entry(d, gfn_aligned+i, _mfn(POPULATE_ON_DEMAND_MFN), 0,
+ set_p2m_entry(p2m, gfn_aligned+i, _mfn(POPULATE_ON_DEMAND_MFN), 0,
p2m_populate_on_demand);
if ( tb_init_done )
{
@@ -1216,44 +1214,44 @@ remap_and_retry:
}
/* Non-ept "lock-and-check" wrapper */
-static int p2m_pod_check_and_populate(struct domain *d, unsigned long gfn,
+static int p2m_pod_check_and_populate(struct p2m_domain *p2m, unsigned long
gfn,
l1_pgentry_t *p2m_entry, int order,
p2m_query_t q)
{
/* Only take the lock if we don't already have it. Otherwise it
* wouldn't be safe to do p2m lookups with the p2m lock held */
- int do_locking = !p2m_locked_by_me(d->arch.p2m);
+ int do_locking = !p2m_locked_by_me(p2m);
int r;
if ( do_locking )
- p2m_lock(d->arch.p2m);
-
- audit_p2m(d);
+ p2m_lock(p2m);
+
+ audit_p2m(p2m);
/* Check to make sure this is still PoD */
if ( p2m_flags_to_type(l1e_get_flags(*p2m_entry)) !=
p2m_populate_on_demand )
{
if ( do_locking )
- p2m_unlock(d->arch.p2m);
+ p2m_unlock(p2m);
return 0;
}
- r = p2m_pod_demand_populate(d, gfn, order, q);
-
- audit_p2m(d);
+ r = p2m_pod_demand_populate(p2m, gfn, order, q);
+
+ audit_p2m(p2m);
if ( do_locking )
- p2m_unlock(d->arch.p2m);
+ p2m_unlock(p2m);
return r;
}
// Returns 0 on error (out of memory)
static int
-p2m_set_entry(struct domain *d, unsigned long gfn, mfn_t mfn,
+p2m_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn,
unsigned int page_order, p2m_type_t p2mt)
{
// XXX -- this might be able to be faster iff current->domain == d
- mfn_t table_mfn = pagetable_get_mfn(p2m_get_pagetable(p2m_get_hostp2m(d)));
+ mfn_t table_mfn = pagetable_get_mfn(p2m_get_pagetable(p2m));
void *table =map_domain_page(mfn_x(table_mfn));
unsigned long i, gfn_remainder = gfn;
l1_pgentry_t *p2m_entry;
@@ -1273,14 +1271,14 @@ p2m_set_entry(struct domain *d, unsigned
t.gfn = gfn;
t.mfn = mfn_x(mfn);
t.p2mt = p2mt;
- t.d = d->domain_id;
+ t.d = p2m->domain->domain_id;
t.order = page_order;
__trace_var(TRC_MEM_SET_P2M_ENTRY, 0, sizeof(t), (unsigned char *)&t);
}
#if CONFIG_PAGING_LEVELS >= 4
- if ( !p2m_next_level(d, &table_mfn, &table, &gfn_remainder, gfn,
+ if ( !p2m_next_level(p2m, &table_mfn, &table, &gfn_remainder, gfn,
L4_PAGETABLE_SHIFT - PAGE_SHIFT,
L4_PAGETABLE_ENTRIES, PGT_l3_page_table) )
goto out;
@@ -1298,14 +1296,15 @@ p2m_set_entry(struct domain *d, unsigned
!(l1e_get_flags(*p2m_entry) & _PAGE_PSE) )
{
P2M_ERROR("configure P2M table L3 entry with large page\n");
- domain_crash(d);
+ domain_crash(p2m->domain);
goto out;
}
l3e_content = mfn_valid(mfn)
? l3e_from_pfn(mfn_x(mfn), p2m_type_to_flags(p2mt) | _PAGE_PSE)
: l3e_empty();
entry_content.l1 = l3e_content.l3;
- paging_write_p2m_entry(d, gfn, p2m_entry, table_mfn, entry_content, 3);
+ paging_write_p2m_entry(p2m->domain, gfn, p2m_entry,
+ table_mfn, entry_content, 3);
}
/*
@@ -1315,17 +1314,17 @@ p2m_set_entry(struct domain *d, unsigned
* in Xen's address space for translated PV guests.
* When using AMD's NPT on PAE Xen, we are restricted to 4GB.
*/
- else if ( !p2m_next_level(d, &table_mfn, &table, &gfn_remainder, gfn,
+ else if ( !p2m_next_level(p2m, &table_mfn, &table, &gfn_remainder, gfn,
L3_PAGETABLE_SHIFT - PAGE_SHIFT,
((CONFIG_PAGING_LEVELS == 3)
- ? (paging_mode_hap(d) ? 4 : 8)
+ ? (paging_mode_hap(p2m->domain) ? 4 : 8)
: L3_PAGETABLE_ENTRIES),
PGT_l2_page_table) )
goto out;
if ( page_order == 0 )
{
- if ( !p2m_next_level(d, &table_mfn, &table, &gfn_remainder, gfn,
+ if ( !p2m_next_level(p2m, &table_mfn, &table, &gfn_remainder, gfn,
L2_PAGETABLE_SHIFT - PAGE_SHIFT,
L2_PAGETABLE_ENTRIES, PGT_l1_page_table) )
goto out;
@@ -1340,7 +1339,8 @@ p2m_set_entry(struct domain *d, unsigned
entry_content = l1e_empty();
/* level 1 entry */
- paging_write_p2m_entry(d, gfn, p2m_entry, table_mfn, entry_content, 1);
+ paging_write_p2m_entry(p2m->domain, gfn, p2m_entry,
+ table_mfn, entry_content, 1);
}
else if ( page_order == 9 )
{
@@ -1354,7 +1354,7 @@ p2m_set_entry(struct domain *d, unsigned
!(l1e_get_flags(*p2m_entry) & _PAGE_PSE) )
{
P2M_ERROR("configure P2M table 4KB L2 entry with large page\n");
- domain_crash(d);
+ domain_crash(p2m->domain);
goto out;
}
@@ -1365,23 +1365,24 @@ p2m_set_entry(struct domain *d, unsigned
l2e_content = l2e_empty();
entry_content.l1 = l2e_content.l2;
- paging_write_p2m_entry(d, gfn, p2m_entry, table_mfn, entry_content, 2);
+ paging_write_p2m_entry(p2m->domain, gfn, p2m_entry,
+ table_mfn, entry_content, 2);
}
/* Track the highest gfn for which we have ever had a valid mapping */
if ( mfn_valid(mfn)
- && (gfn + (1UL << page_order) - 1 > d->arch.p2m->max_mapped_pfn) )
- d->arch.p2m->max_mapped_pfn = gfn + (1UL << page_order) - 1;
-
- if ( iommu_enabled && need_iommu(d) )
+ && (gfn + (1UL << page_order) - 1 > p2m->max_mapped_pfn) )
+ p2m->max_mapped_pfn = gfn + (1UL << page_order) - 1;
+
+ if ( iommu_enabled && need_iommu(p2m->domain) )
{
if ( p2mt == p2m_ram_rw )
for ( i = 0; i < (1UL << page_order); i++ )
- iommu_map_page(d, gfn+i, mfn_x(mfn)+i,
+ iommu_map_page(p2m->domain, gfn+i, mfn_x(mfn)+i,
IOMMUF_readable|IOMMUF_writable);
else
for ( int i = 0; i < (1UL << page_order); i++ )
- iommu_unmap_page(d, gfn+i);
+ iommu_unmap_page(p2m->domain, gfn+i);
}
/* Success */
@@ -1393,7 +1394,7 @@ out:
}
static mfn_t
-p2m_gfn_to_mfn(struct domain *d, unsigned long gfn, p2m_type_t *t,
+p2m_gfn_to_mfn(struct p2m_domain *p2m, unsigned long gfn, p2m_type_t *t,
p2m_query_t q)
{
mfn_t mfn;
@@ -1401,7 +1402,7 @@ p2m_gfn_to_mfn(struct domain *d, unsigne
l2_pgentry_t *l2e;
l1_pgentry_t *l1e;
- ASSERT(paging_mode_translate(d));
+ ASSERT(paging_mode_translate(p2m->domain));
/* XXX This is for compatibility with the old model, where anything not
* XXX marked as RAM was considered to be emulated MMIO space.
@@ -1409,9 +1410,9 @@ p2m_gfn_to_mfn(struct domain *d, unsigne
* XXX we will return p2m_invalid for unmapped gfns */
*t = p2m_mmio_dm;
- mfn = pagetable_get_mfn(p2m_get_pagetable(p2m_get_hostp2m(d)));
-
- if ( gfn > d->arch.p2m->max_mapped_pfn )
+ mfn = pagetable_get_mfn(p2m_get_pagetable(p2m));
+
+ if ( gfn > p2m->max_mapped_pfn )
/* This pfn is higher than the highest the p2m map currently holds */
return _mfn(INVALID_MFN);
@@ -1447,7 +1448,7 @@ pod_retry_l3:
{
if ( q != p2m_query )
{
- if ( !p2m_pod_demand_populate(d, gfn, 18, q) )
+ if ( !p2m_pod_demand_populate(p2m, gfn, 18, q) )
goto pod_retry_l3;
}
else
@@ -1482,8 +1483,8 @@ pod_retry_l2:
if ( p2m_flags_to_type(l2e_get_flags(*l2e)) == p2m_populate_on_demand )
{
if ( q != p2m_query ) {
- if ( !p2m_pod_check_and_populate(d, gfn,
- (l1_pgentry_t *)l2e, 9,
q) )
+ if ( !p2m_pod_check_and_populate(p2m, gfn,
+ (l1_pgentry_t *)l2e, 9, q) )
goto pod_retry_l2;
} else
*t = p2m_populate_on_demand;
@@ -1514,8 +1515,8 @@ pod_retry_l1:
if ( p2m_flags_to_type(l1e_get_flags(*l1e)) == p2m_populate_on_demand )
{
if ( q != p2m_query ) {
- if ( !p2m_pod_check_and_populate(d, gfn,
- (l1_pgentry_t *)l1e, 0,
q) )
+ if ( !p2m_pod_check_and_populate(p2m, gfn,
+ (l1_pgentry_t *)l1e, 0, q) )
goto pod_retry_l1;
} else
*t = p2m_populate_on_demand;
@@ -1533,7 +1534,8 @@ pod_retry_l1:
}
/* Read the current domain's p2m table (through the linear mapping). */
-static mfn_t p2m_gfn_to_mfn_current(unsigned long gfn, p2m_type_t *t,
+static mfn_t p2m_gfn_to_mfn_current(struct p2m_domain *p2m,
+ unsigned long gfn, p2m_type_t *t,
p2m_query_t q)
{
mfn_t mfn = _mfn(INVALID_MFN);
@@ -1544,7 +1546,7 @@ static mfn_t p2m_gfn_to_mfn_current(unsi
* XXX Once we start explicitly registering MMIO regions in the p2m
* XXX we will return p2m_invalid for unmapped gfns */
- if ( gfn <= current->domain->arch.p2m->max_mapped_pfn )
+ if ( gfn <= p2m->max_mapped_pfn )
{
l1_pgentry_t l1e = l1e_empty(), *p2m_entry;
l2_pgentry_t l2e = l2e_empty();
@@ -1574,7 +1576,7 @@ static mfn_t p2m_gfn_to_mfn_current(unsi
/* The read has succeeded, so we know that mapping exists */
if ( q != p2m_query )
{
- if ( !p2m_pod_demand_populate(current->domain, gfn, 18, q)
)
+ if ( !p2m_pod_demand_populate(p2m, gfn, 18, q) )
goto pod_retry_l3;
p2mt = p2m_invalid;
printk("%s: Allocate 1GB failed!\n", __func__);
@@ -1624,8 +1626,8 @@ static mfn_t p2m_gfn_to_mfn_current(unsi
* exits at this point. */
if ( q != p2m_query )
{
- if ( !p2m_pod_check_and_populate(current->domain, gfn,
- p2m_entry, 9, q) )
+ if ( !p2m_pod_check_and_populate(p2m, gfn,
+ p2m_entry, 9, q) )
goto pod_retry_l2;
/* Allocate failed. */
@@ -1680,8 +1682,8 @@ static mfn_t p2m_gfn_to_mfn_current(unsi
* exits at this point. */
if ( q != p2m_query )
{
- if ( !p2m_pod_check_and_populate(current->domain, gfn,
- (l1_pgentry_t
*)p2m_entry, 0, q) )
+ if ( !p2m_pod_check_and_populate(p2m, gfn,
+ (l1_pgentry_t
*)p2m_entry, 0, q) )
goto pod_retry_l1;
/* Allocate failed. */
@@ -1708,22 +1710,15 @@ out:
}
/* Init the datastructures for later use by the p2m code */
-int p2m_init(struct domain *d)
-{
- struct p2m_domain *p2m;
-
- p2m = xmalloc(struct p2m_domain);
- if ( p2m == NULL )
- return -ENOMEM;
-
- d->arch.p2m = p2m;
-
+static void p2m_initialise(struct domain *d, struct p2m_domain *p2m)
+{
memset(p2m, 0, sizeof(*p2m));
p2m_lock_init(p2m);
INIT_PAGE_LIST_HEAD(&p2m->pages);
INIT_PAGE_LIST_HEAD(&p2m->pod.super);
INIT_PAGE_LIST_HEAD(&p2m->pod.single);
+ p2m->domain = d;
p2m->set_entry = p2m_set_entry;
p2m->get_entry = p2m_gfn_to_mfn;
p2m->get_entry_current = p2m_gfn_to_mfn_current;
@@ -1732,23 +1727,34 @@ int p2m_init(struct domain *d)
if ( hap_enabled(d) && (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) )
ept_p2m_init(d);
+ return;
+}
+
+int p2m_init(struct domain *d)
+{
+ struct p2m_domain *p2m;
+
+ p2m_get_hostp2m(d) = p2m = xmalloc(struct p2m_domain);
+ if ( p2m == NULL )
+ return -ENOMEM;
+ p2m_initialise(d, p2m);
+
return 0;
}
-void p2m_change_entry_type_global(struct domain *d,
+void p2m_change_entry_type_global(struct p2m_domain *p2m,
p2m_type_t ot, p2m_type_t nt)
{
- struct p2m_domain *p2m = d->arch.p2m;
-
p2m_lock(p2m);
- p2m->change_entry_type_global(d, ot, nt);
+ p2m->change_entry_type_global(p2m, ot, nt);
p2m_unlock(p2m);
}
static
-int set_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn,
+int set_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn,
unsigned int page_order, p2m_type_t p2mt)
{
+ struct domain *d = p2m->domain;
unsigned long todo = 1ul << page_order;
unsigned int order;
int rc = 1;
@@ -1763,7 +1769,7 @@ int set_p2m_entry(struct domain *d, unsi
else
order = 0;
- if ( !d->arch.p2m->set_entry(d, gfn, mfn, order, p2mt) )
+ if ( !p2m->set_entry(p2m, gfn, mfn, order, p2mt) )
rc = 0;
gfn += 1ul << order;
if ( mfn_x(mfn) != INVALID_MFN )
@@ -1784,16 +1790,14 @@ int set_p2m_entry(struct domain *d, unsi
//
// Returns 0 for success or -errno.
//
-int p2m_alloc_table(struct domain *d,
- struct page_info * (*alloc_page)(struct domain *d),
- void (*free_page)(struct domain *d, struct page_info *pg))
-
+int p2m_alloc_table(struct p2m_domain *p2m,
+ struct page_info * (*alloc_page)(struct p2m_domain *p2m),
+ void (*free_page)(struct p2m_domain *p2m, struct page_info *pg))
{
mfn_t mfn = _mfn(INVALID_MFN);
struct page_info *page, *p2m_top;
unsigned int page_count = 0;
unsigned long gfn = -1UL;
- struct p2m_domain *p2m = p2m_get_hostp2m(d);
p2m_lock(p2m);
@@ -1809,7 +1813,7 @@ int p2m_alloc_table(struct domain *d,
p2m->alloc_page = alloc_page;
p2m->free_page = free_page;
- p2m_top = p2m_alloc_ptp(d,
+ p2m_top = p2m_alloc_ptp(p2m,
#if CONFIG_PAGING_LEVELS == 4
PGT_l4_page_table
#else
@@ -1828,13 +1832,13 @@ int p2m_alloc_table(struct domain *d,
P2M_PRINTK("populating p2m table\n");
/* Initialise physmap tables for slot zero. Other code assumes this. */
- if ( !set_p2m_entry(d, 0, _mfn(INVALID_MFN), 0,
+ if ( !set_p2m_entry(p2m, 0, _mfn(INVALID_MFN), 0,
p2m_invalid) )
goto error;
/* Copy all existing mappings from the page list and m2p */
- spin_lock(&d->page_alloc_lock);
- page_list_for_each(page, &d->page_list)
+ spin_lock(&p2m->domain->page_alloc_lock);
+ page_list_for_each(page, &p2m->domain->page_list)
{
mfn = page_to_mfn(page);
gfn = get_gpfn_from_mfn(mfn_x(mfn));
@@ -1848,17 +1852,17 @@ int p2m_alloc_table(struct domain *d,
(gfn != 0x55555555L)
#endif
&& gfn != INVALID_M2P_ENTRY
- && !set_p2m_entry(d, gfn, mfn, 0, p2m_ram_rw) )
+ && !set_p2m_entry(p2m, gfn, mfn, 0, p2m_ram_rw) )
goto error_unlock;
}
- spin_unlock(&d->page_alloc_lock);
+ spin_unlock(&p2m->domain->page_alloc_lock);
P2M_PRINTK("p2m table initialised (%u pages)\n", page_count);
p2m_unlock(p2m);
return 0;
error_unlock:
- spin_unlock(&d->page_alloc_lock);
+ spin_unlock(&p2m->domain->page_alloc_lock);
error:
P2M_PRINTK("failed to initialize p2m table, gfn=%05lx, mfn=%"
PRI_mfn "\n", gfn, mfn_x(mfn));
@@ -1866,12 +1870,11 @@ error_unlock:
return -ENOMEM;
}
-void p2m_teardown(struct domain *d)
+void p2m_teardown(struct p2m_domain *p2m)
/* Return all the p2m pages to Xen.
* We know we don't have any extra mappings to these pages */
{
struct page_info *pg;
- struct p2m_domain *p2m = p2m_get_hostp2m(d);
#ifdef __x86_64__
unsigned long gfn;
p2m_type_t t;
@@ -1883,27 +1886,28 @@ void p2m_teardown(struct domain *d)
#ifdef __x86_64__
for ( gfn=0; gfn < p2m->max_mapped_pfn; gfn++ )
{
- mfn = p2m->get_entry(d, gfn, &t, p2m_query);
+ mfn = p2m->get_entry(p2m, gfn, &t, p2m_query);
if ( mfn_valid(mfn) && (t == p2m_ram_shared) )
- BUG_ON(mem_sharing_unshare_page(d, gfn, MEM_SHARING_DESTROY_GFN));
+ BUG_ON(mem_sharing_unshare_page(p2m, gfn,
MEM_SHARING_DESTROY_GFN));
}
#endif
p2m->phys_table = pagetable_null();
while ( (pg = page_list_remove_head(&p2m->pages)) )
- p2m->free_page(d, pg);
+ p2m->free_page(p2m, pg);
p2m_unlock(p2m);
}
void p2m_final_teardown(struct domain *d)
{
+ /* Iterate over all p2m tables per domain */
xfree(d->arch.p2m);
d->arch.p2m = NULL;
}
#if P2M_AUDIT
-static void audit_p2m(struct domain *d)
+static void audit_p2m(struct p2m_domain *p2m)
{
struct page_info *page;
struct domain *od;
@@ -1913,6 +1917,7 @@ static void audit_p2m(struct domain *d)
unsigned long orphans_d = 0, orphans_i = 0, mpbad = 0, pmbad = 0;
int test_linear;
p2m_type_t type;
+ struct domain *d = p2m->domain;
if ( !paging_mode_translate(d) )
return;
@@ -1967,7 +1972,7 @@ static void audit_p2m(struct domain *d)
continue;
}
- p2mfn = gfn_to_mfn_type_foreign(d, gfn, &type, p2m_query);
+ p2mfn = gfn_to_mfn_type_p2m(p2m, gfn, &type, p2m_query);
if ( mfn_x(p2mfn) != mfn )
{
mpbad++;
@@ -1983,9 +1988,9 @@ static void audit_p2m(struct domain *d)
set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY);
}
- if ( test_linear && (gfn <= d->arch.p2m->max_mapped_pfn) )
- {
- lp2mfn = mfn_x(gfn_to_mfn_query(d, gfn, &type));
+ if ( test_linear && (gfn <= p2m->max_mapped_pfn) )
+ {
+ lp2mfn = mfn_x(gfn_to_mfn_query(p2m, gfn, &type));
if ( lp2mfn != mfn_x(p2mfn) )
{
P2M_PRINTK("linear mismatch gfn %#lx -> mfn %#lx "
@@ -2000,7 +2005,7 @@ static void audit_p2m(struct domain *d)
spin_unlock(&d->page_alloc_lock);
/* Audit part two: walk the domain's p2m table, checking the entries. */
- if ( pagetable_get_pfn(p2m_get_pagetable(p2m_get_hostp2m(d)) != 0 )
+ if ( pagetable_get_pfn(p2m_get_pagetable(p2m)) != 0 )
{
l2_pgentry_t *l2e;
l1_pgentry_t *l1e;
@@ -2009,12 +2014,12 @@ static void audit_p2m(struct domain *d)
#if CONFIG_PAGING_LEVELS == 4
l4_pgentry_t *l4e;
l3_pgentry_t *l3e;
- int i3, i4;
- l4e =
map_domain_page(mfn_x(pagetable_get_mfn(p2m_get_pagetable(p2m_get_hostp2m(d)))));
+ int i4, i3;
+ l4e =
map_domain_page(mfn_x(pagetable_get_mfn(p2m_get_pagetable(p2m))));
#else /* CONFIG_PAGING_LEVELS == 3 */
l3_pgentry_t *l3e;
int i3;
- l3e =
map_domain_page(mfn_x(pagetable_get_mfn(p2m_get_pagetable(p2m_get_hostp2m(d)))));
+ l3e =
map_domain_page(mfn_x(pagetable_get_mfn(p2m_get_pagetable(p2m))));
#endif
gfn = 0;
@@ -2144,11 +2149,11 @@ static void audit_p2m(struct domain *d)
}
- if ( entry_count != d->arch.p2m->pod.entry_count )
+ if ( entry_count != p2m->pod.entry_count )
{
printk("%s: refcounted entry count %d, audit count %d!\n",
__func__,
- d->arch.p2m->pod.entry_count,
+ p2m->pod.entry_count,
entry_count);
BUG();
}
@@ -2166,18 +2171,18 @@ static void audit_p2m(struct domain *d)
static void
-p2m_remove_page(struct domain *d, unsigned long gfn, unsigned long mfn,
+p2m_remove_page(struct p2m_domain *p2m, unsigned long gfn, unsigned long mfn,
unsigned int page_order)
{
unsigned long i;
mfn_t mfn_return;
p2m_type_t t;
- if ( !paging_mode_translate(d) )
- {
- if ( need_iommu(d) )
+ if ( !paging_mode_translate(p2m->domain) )
+ {
+ if ( need_iommu(p2m->domain) )
for ( i = 0; i < (1 << page_order); i++ )
- iommu_unmap_page(d, mfn + i);
+ iommu_unmap_page(p2m->domain, mfn + i);
return;
}
@@ -2185,23 +2190,23 @@ p2m_remove_page(struct domain *d, unsign
for ( i = 0; i < (1UL << page_order); i++ )
{
- mfn_return = d->arch.p2m->get_entry(d, gfn + i, &t, p2m_query);
+ mfn_return = p2m->get_entry(p2m, gfn + i, &t, 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(d, gfn, _mfn(INVALID_MFN), page_order, p2m_invalid);
+ set_p2m_entry(p2m, gfn, _mfn(INVALID_MFN), page_order, p2m_invalid);
}
void
-guest_physmap_remove_page(struct domain *d, unsigned long gfn,
+guest_physmap_remove_entry(struct p2m_domain *p2m, unsigned long gfn,
unsigned long mfn, unsigned int page_order)
{
- p2m_lock(d->arch.p2m);
- audit_p2m(d);
- p2m_remove_page(d, gfn, mfn, page_order);
- audit_p2m(d);
- p2m_unlock(d->arch.p2m);
+ p2m_lock(p2m);
+ audit_p2m(p2m);
+ p2m_remove_page(p2m, gfn, mfn, page_order);
+ audit_p2m(p2m);
+ p2m_unlock(p2m);
}
#if CONFIG_PAGING_LEVELS == 3
@@ -2232,7 +2237,7 @@ guest_physmap_mark_populate_on_demand(st
guest_physmap_mark_populate_on_demand(struct domain *d, unsigned long gfn,
unsigned int order)
{
- struct p2m_domain *p2md = d->arch.p2m;
+ struct p2m_domain *p2m = p2m_get_hostp2m(d);
unsigned long i;
p2m_type_t ot;
mfn_t omfn;
@@ -2245,15 +2250,15 @@ guest_physmap_mark_populate_on_demand(st
if ( rc != 0 )
return rc;
- p2m_lock(p2md);
- audit_p2m(d);
+ p2m_lock(p2m);
+ audit_p2m(p2m);
P2M_DEBUG("mark pod gfn=%#lx\n", gfn);
/* Make sure all gpfns are unused */
for ( i = 0; i < (1UL << order); i++ )
{
- omfn = gfn_to_mfn_query(d, gfn + i, &ot);
+ omfn = gfn_to_mfn_query(p2m, gfn + i, &ot);
if ( p2m_is_ram(ot) )
{
printk("%s: gfn_to_mfn returned type %d!\n",
@@ -2269,29 +2274,29 @@ guest_physmap_mark_populate_on_demand(st
}
/* Now, actually do the two-way mapping */
- if ( !set_p2m_entry(d, gfn, _mfn(POPULATE_ON_DEMAND_MFN), order,
+ if ( !set_p2m_entry(p2m, gfn, _mfn(POPULATE_ON_DEMAND_MFN), order,
p2m_populate_on_demand) )
rc = -EINVAL;
else
{
- p2md->pod.entry_count += 1 << order; /* Lock: p2m */
- p2md->pod.entry_count -= pod_count;
- BUG_ON(p2md->pod.entry_count < 0);
- }
-
- audit_p2m(d);
- p2m_unlock(p2md);
+ p2m->pod.entry_count += 1 << order; /* Lock: p2m */
+ p2m->pod.entry_count -= pod_count;
+ BUG_ON(p2m->pod.entry_count < 0);
+ }
+
+ audit_p2m(p2m);
+ p2m_unlock(p2m);
out:
return rc;
-
}
int
-guest_physmap_add_entry(struct domain *d, unsigned long gfn,
+guest_physmap_add_entry(struct p2m_domain *p2m, unsigned long gfn,
unsigned long mfn, unsigned int page_order,
p2m_type_t t)
{
+ struct domain *d = p2m->domain;
unsigned long i, ogfn;
p2m_type_t ot;
mfn_t omfn;
@@ -2321,20 +2326,20 @@ guest_physmap_add_entry(struct domain *d
if ( rc != 0 )
return rc;
- p2m_lock(d->arch.p2m);
- audit_p2m(d);
+ p2m_lock(p2m);
+ audit_p2m(p2m);
P2M_DEBUG("adding gfn=%#lx mfn=%#lx\n", gfn, mfn);
/* First, remove m->p mappings for existing p->m mappings */
for ( i = 0; i < (1UL << page_order); i++ )
{
- omfn = gfn_to_mfn_query(d, gfn + i, &ot);
+ omfn = gfn_to_mfn_query(p2m, gfn + i, &ot);
if ( p2m_is_grant(ot) )
{
/* Really shouldn't be unmapping grant maps this way */
domain_crash(d);
- p2m_unlock(d->arch.p2m);
+ p2m_unlock(p2m);
return -EINVAL;
}
else if ( p2m_is_ram(ot) )
@@ -2368,7 +2373,7 @@ guest_physmap_add_entry(struct domain *d
* address */
P2M_DEBUG("aliased! mfn=%#lx, old gfn=%#lx, new gfn=%#lx\n",
mfn + i, ogfn, gfn + i);
- omfn = gfn_to_mfn_query(d, ogfn, &ot);
+ omfn = gfn_to_mfn_query(p2m, ogfn, &ot);
/* If we get here, we know the local domain owns the page,
so it can't have been grant mapped in. */
BUG_ON( p2m_is_grant(ot) );
@@ -2378,7 +2383,7 @@ guest_physmap_add_entry(struct domain *d
P2M_DEBUG("old gfn=%#lx -> mfn %#lx\n",
ogfn , mfn_x(omfn));
if ( mfn_x(omfn) == (mfn + i) )
- p2m_remove_page(d, ogfn, mfn + i, 0);
+ p2m_remove_page(p2m, ogfn, mfn + i, 0);
}
}
}
@@ -2386,7 +2391,7 @@ guest_physmap_add_entry(struct domain *d
/* Now, actually do the two-way mapping */
if ( mfn_valid(_mfn(mfn)) )
{
- if ( !set_p2m_entry(d, gfn, _mfn(mfn), page_order, t) )
+ if ( !set_p2m_entry(p2m, gfn, _mfn(mfn), page_order, t) )
rc = -EINVAL;
if ( !p2m_is_grant(t) )
{
@@ -2398,18 +2403,18 @@ guest_physmap_add_entry(struct domain *d
{
gdprintk(XENLOG_WARNING, "Adding bad mfn to p2m map (%#lx -> %#lx)\n",
gfn, mfn);
- if ( !set_p2m_entry(d, gfn, _mfn(INVALID_MFN), page_order,
+ if ( !set_p2m_entry(p2m, gfn, _mfn(INVALID_MFN), page_order,
p2m_invalid) )
rc = -EINVAL;
else
{
- d->arch.p2m->pod.entry_count -= pod_count; /* Lock: p2m */
- BUG_ON(d->arch.p2m->pod.entry_count < 0);
- }
- }
-
- audit_p2m(d);
- p2m_unlock(d->arch.p2m);
+ p2m->pod.entry_count -= pod_count; /* Lock: p2m */
+ BUG_ON(p2m->pod.entry_count < 0);
+ }
+ }
+
+ audit_p2m(p2m);
+ p2m_unlock(p2m);
return rc;
}
@@ -2417,7 +2422,7 @@ guest_physmap_add_entry(struct domain *d
/* Walk the whole p2m table, changing any entries of the old type
* to the new type. This is used in hardware-assisted paging to
* quickly enable or diable log-dirty tracking */
-void p2m_change_type_global(struct domain *d, p2m_type_t ot, p2m_type_t nt)
+void p2m_change_type_global(struct p2m_domain *p2m, p2m_type_t ot, p2m_type_t
nt)
{
unsigned long mfn, gfn, flags;
l1_pgentry_t l1e_content;
@@ -2430,17 +2435,16 @@ void p2m_change_type_global(struct domai
l4_pgentry_t *l4e;
unsigned long i4;
#endif /* CONFIG_PAGING_LEVELS == 4 */
- struct p2m_domain *p2m = p2m_get_hostp2m(d);
BUG_ON(p2m_is_grant(ot) || p2m_is_grant(nt));
- if ( !paging_mode_translate(d) )
+ if ( !paging_mode_translate(p2m->domain) )
return;
if ( pagetable_get_pfn(p2m_get_pagetable(p2m)) == 0 )
return;
- ASSERT(p2m_locked_by_me(d->arch.p2m));
+ ASSERT(p2m_locked_by_me(p2m));
#if CONFIG_PAGING_LEVELS == 4
l4e = map_domain_page(mfn_x(pagetable_get_mfn(p2m_get_pagetable(p2m))));
@@ -2476,7 +2480,8 @@ void p2m_change_type_global(struct domai
gfn = get_gpfn_from_mfn(mfn);
flags = p2m_type_to_flags(nt);
l1e_content = l1e_from_pfn(mfn, flags | _PAGE_PSE);
- paging_write_p2m_entry(d, gfn, (l1_pgentry_t *)&l3e[i3],
+ paging_write_p2m_entry(p2m->domain, gfn,
+ (l1_pgentry_t *)&l3e[i3],
l3mfn, l1e_content, 3);
continue;
}
@@ -2506,7 +2511,8 @@ void p2m_change_type_global(struct domai
* L2_PAGETABLE_ENTRIES) * L1_PAGETABLE_ENTRIES;
flags = p2m_type_to_flags(nt);
l1e_content = l1e_from_pfn(mfn, flags | _PAGE_PSE);
- paging_write_p2m_entry(d, gfn, (l1_pgentry_t *)&l2e[i2],
+ paging_write_p2m_entry(p2m->domain, gfn,
+ (l1_pgentry_t *)&l2e[i2],
l2mfn, l1e_content, 2);
continue;
}
@@ -2529,7 +2535,7 @@ void p2m_change_type_global(struct domai
/* create a new 1le entry with the new type */
flags = p2m_type_to_flags(nt);
l1e_content = l1e_from_pfn(mfn, flags);
- paging_write_p2m_entry(d, gfn, &l1e[i1],
+ paging_write_p2m_entry(p2m->domain, gfn, &l1e[i1],
l1mfn, l1e_content, 1);
}
unmap_domain_page(l1e);
@@ -2551,7 +2557,7 @@ void p2m_change_type_global(struct domai
/* Modify the p2m type of a single gfn from ot to nt, returning the
* entry's previous type */
-p2m_type_t p2m_change_type(struct domain *d, unsigned long gfn,
+p2m_type_t p2m_change_type(struct p2m_domain *p2m, unsigned long gfn,
p2m_type_t ot, p2m_type_t nt)
{
p2m_type_t pt;
@@ -2559,31 +2565,31 @@ p2m_type_t p2m_change_type(struct domain
BUG_ON(p2m_is_grant(ot) || p2m_is_grant(nt));
- p2m_lock(d->arch.p2m);
-
- mfn = gfn_to_mfn_query(d, gfn, &pt);
+ p2m_lock(p2m);
+
+ mfn = gfn_to_mfn_query(p2m, gfn, &pt);
if ( pt == ot )
- set_p2m_entry(d, gfn, mfn, 0, nt);
-
- p2m_unlock(d->arch.p2m);
+ set_p2m_entry(p2m, gfn, mfn, 0, nt);
+
+ p2m_unlock(p2m);
return pt;
}
int
-set_mmio_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn)
+set_mmio_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn)
{
int rc = 0;
p2m_type_t ot;
mfn_t omfn;
- if ( !paging_mode_translate(d) )
+ if ( !paging_mode_translate(p2m->domain) )
return 0;
- omfn = gfn_to_mfn_query(d, gfn, &ot);
+ omfn = gfn_to_mfn_query(p2m, gfn, &ot);
if ( p2m_is_grant(ot) )
{
- domain_crash(d);
+ domain_crash(p2m->domain);
return 0;
}
else if ( p2m_is_ram(ot) )
@@ -2593,51 +2599,51 @@ set_mmio_p2m_entry(struct domain *d, uns
}
P2M_DEBUG("set mmio %lx %lx\n", gfn, mfn_x(mfn));
- p2m_lock(d->arch.p2m);
- rc = set_p2m_entry(d, gfn, mfn, 0, p2m_mmio_direct);
- p2m_unlock(d->arch.p2m);
+ p2m_lock(p2m);
+ rc = set_p2m_entry(p2m, gfn, mfn, 0, p2m_mmio_direct);
+ p2m_unlock(p2m);
if ( 0 == rc )
gdprintk(XENLOG_ERR,
"set_mmio_p2m_entry: set_p2m_entry failed! mfn=%08lx\n",
- gmfn_to_mfn(d, gfn));
+ mfn_x(gfn_to_mfn(p2m, gfn, &ot)));
return rc;
}
int
-clear_mmio_p2m_entry(struct domain *d, unsigned long gfn)
+clear_mmio_p2m_entry(struct p2m_domain *p2m, unsigned long gfn)
{
int rc = 0;
- unsigned long mfn;
-
- if ( !paging_mode_translate(d) )
+ mfn_t mfn;
+ p2m_type_t t;
+
+ if ( !paging_mode_translate(p2m->domain) )
return 0;
- mfn = gmfn_to_mfn(d, gfn);
- if ( INVALID_MFN == mfn )
+ mfn = gfn_to_mfn(p2m, gfn, &t);
+ if ( !mfn_valid(mfn) )
{
gdprintk(XENLOG_ERR,
"clear_mmio_p2m_entry: gfn_to_mfn failed! gfn=%08lx\n", gfn);
return 0;
}
- p2m_lock(d->arch.p2m);
- rc = set_p2m_entry(d, gfn, _mfn(INVALID_MFN), 0, 0);
- p2m_unlock(d->arch.p2m);
+ p2m_lock(p2m);
+ rc = set_p2m_entry(p2m, gfn, _mfn(INVALID_MFN), 0, 0);
+ p2m_unlock(p2m);
return rc;
}
-#ifdef __x86_64__
int
-set_shared_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn)
+set_shared_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn)
{
int rc = 0;
p2m_type_t ot;
mfn_t omfn;
- if ( !paging_mode_translate(d) )
+ if ( !paging_mode_translate(p2m->domain) )
return 0;
- omfn = gfn_to_mfn_query(d, gfn, &ot);
+ omfn = gfn_to_mfn_query(p2m, gfn, &ot);
/* At the moment we only allow p2m change if gfn has already been made
* sharable first */
ASSERT(p2m_is_shared(ot));
@@ -2646,22 +2652,23 @@ set_shared_p2m_entry(struct domain *d, u
set_gpfn_from_mfn(mfn_x(omfn), INVALID_M2P_ENTRY);
P2M_DEBUG("set shared %lx %lx\n", gfn, mfn_x(mfn));
- rc = set_p2m_entry(d, gfn, mfn, 0, p2m_ram_shared);
+ rc = set_p2m_entry(p2m, gfn, mfn, 0, p2m_ram_shared);
if ( 0 == rc )
gdprintk(XENLOG_ERR,
"set_mmio_p2m_entry: set_p2m_entry failed! mfn=%08lx\n",
- gmfn_to_mfn(d, gfn));
+ gmfn_to_mfn(p2m->domain, gfn));
return rc;
}
-int p2m_mem_paging_nominate(struct domain *d, unsigned long gfn)
+#ifdef __x86_64__
+int p2m_mem_paging_nominate(struct p2m_domain *p2m, unsigned long gfn)
{
struct page_info *page;
p2m_type_t p2mt;
mfn_t mfn;
int ret;
- mfn = gfn_to_mfn(d, gfn, &p2mt);
+ mfn = gfn_to_mfn(p2m, gfn, &p2mt);
/* Check if mfn is valid */
ret = -EINVAL;
@@ -2687,9 +2694,9 @@ int p2m_mem_paging_nominate(struct domai
goto out;
/* Fix p2m entry */
- p2m_lock(d->arch.p2m);
- set_p2m_entry(d, gfn, mfn, 0, p2m_ram_paging_out);
- p2m_unlock(d->arch.p2m);
+ p2m_lock(p2m);
+ set_p2m_entry(p2m, gfn, mfn, 0, p2m_ram_paging_out);
+ p2m_unlock(p2m);
ret = 0;
@@ -2697,14 +2704,15 @@ int p2m_mem_paging_nominate(struct domai
return ret;
}
-int p2m_mem_paging_evict(struct domain *d, unsigned long gfn)
+int p2m_mem_paging_evict(struct p2m_domain *p2m, unsigned long gfn)
{
struct page_info *page;
p2m_type_t p2mt;
mfn_t mfn;
+ struct domain *d = p2m->domain;
/* Get mfn */
- mfn = gfn_to_mfn(d, gfn, &p2mt);
+ mfn = gfn_to_mfn(p2m, gfn, &p2mt);
if ( unlikely(!mfn_valid(mfn)) )
return -EINVAL;
@@ -2722,9 +2730,9 @@ int p2m_mem_paging_evict(struct domain *
put_page(page);
/* Remove mapping from p2m table */
- p2m_lock(d->arch.p2m);
- set_p2m_entry(d, gfn, _mfn(PAGING_MFN), 0, p2m_ram_paged);
- p2m_unlock(d->arch.p2m);
+ p2m_lock(p2m);
+ set_p2m_entry(p2m, gfn, _mfn(PAGING_MFN), 0, p2m_ram_paged);
+ p2m_unlock(p2m);
/* Put the page back so it gets freed */
put_page(page);
@@ -2732,11 +2740,12 @@ int p2m_mem_paging_evict(struct domain *
return 0;
}
-void p2m_mem_paging_populate(struct domain *d, unsigned long gfn)
+void p2m_mem_paging_populate(struct p2m_domain *p2m, unsigned long gfn)
{
struct vcpu *v = current;
mem_event_request_t req;
p2m_type_t p2mt;
+ struct domain *d = p2m->domain;
memset(&req, 0, sizeof(req));
@@ -2747,12 +2756,12 @@ void p2m_mem_paging_populate(struct doma
/* Fix p2m mapping */
/* XXX: It seems inefficient to have this here, as it's only needed
* in one case (ept guest accessing paging out page) */
- gfn_to_mfn(d, gfn, &p2mt);
+ gfn_to_mfn(p2m, gfn, &p2mt);
if ( p2mt != p2m_ram_paging_out )
{
- p2m_lock(d->arch.p2m);
- set_p2m_entry(d, gfn, _mfn(PAGING_MFN), 0, p2m_ram_paging_in_start);
- p2m_unlock(d->arch.p2m);
+ p2m_lock(p2m);
+ set_p2m_entry(p2m, gfn, _mfn(PAGING_MFN), 0, p2m_ram_paging_in_start);
+ p2m_unlock(p2m);
}
/* Pause domain */
@@ -2770,25 +2779,26 @@ void p2m_mem_paging_populate(struct doma
mem_event_put_request(d, &req);
}
-int p2m_mem_paging_prep(struct domain *d, unsigned long gfn)
+int p2m_mem_paging_prep(struct p2m_domain *p2m, unsigned long gfn)
{
struct page_info *page;
/* Get a free page */
- page = alloc_domheap_page(d, 0);
+ page = alloc_domheap_page(p2m->domain, 0);
if ( unlikely(page == NULL) )
return -EINVAL;
/* Fix p2m mapping */
- p2m_lock(d->arch.p2m);
- set_p2m_entry(d, gfn, page_to_mfn(page), 0, p2m_ram_paging_in);
- p2m_unlock(d->arch.p2m);
+ p2m_lock(p2m);
+ set_p2m_entry(p2m, gfn, page_to_mfn(page), 0, p2m_ram_paging_in);
+ p2m_unlock(p2m);
return 0;
}
-void p2m_mem_paging_resume(struct domain *d)
-{
+void p2m_mem_paging_resume(struct p2m_domain *p2m)
+{
+ struct domain *d = p2m->domain;
mem_event_response_t rsp;
p2m_type_t p2mt;
mfn_t mfn;
@@ -2797,10 +2807,10 @@ void p2m_mem_paging_resume(struct domain
mem_event_get_response(d, &rsp);
/* Fix p2m entry */
- mfn = gfn_to_mfn(d, rsp.gfn, &p2mt);
- p2m_lock(d->arch.p2m);
- set_p2m_entry(d, rsp.gfn, mfn, 0, p2m_ram_rw);
- p2m_unlock(d->arch.p2m);
+ mfn = gfn_to_mfn(p2m, rsp.gfn, &p2mt);
+ p2m_lock(p2m);
+ set_p2m_entry(p2m, rsp.gfn, mfn, 0, p2m_ram_rw);
+ p2m_unlock(p2m);
/* Unpause domain */
if ( rsp.flags & MEM_EVENT_FLAG_VCPU_PAUSED )
diff -r 9e58c46ee63b -r e7afe98afd43 xen/arch/x86/mm/shadow/common.c
--- a/xen/arch/x86/mm/shadow/common.c Mon Aug 09 16:40:18 2010 +0100
+++ b/xen/arch/x86/mm/shadow/common.c Mon Aug 09 16:46:42 2010 +0100
@@ -1714,8 +1714,9 @@ sh_alloc_p2m_pages(struct domain *d)
// Returns 0 if no memory is available...
static struct page_info *
-shadow_alloc_p2m_page(struct domain *d)
-{
+shadow_alloc_p2m_page(struct p2m_domain *p2m)
+{
+ struct domain *d = p2m->domain;
struct page_info *pg;
mfn_t mfn;
void *p;
@@ -1741,8 +1742,9 @@ shadow_alloc_p2m_page(struct domain *d)
}
static void
-shadow_free_p2m_page(struct domain *d, struct page_info *pg)
-{
+shadow_free_p2m_page(struct p2m_domain *p2m, struct page_info *pg)
+{
+ struct domain *d = p2m->domain;
ASSERT(page_get_owner(pg) == d);
/* Should have just the one ref we gave it in alloc_p2m_page() */
if ( (pg->count_info & PGC_count_mask) != 1 )
@@ -3100,6 +3102,7 @@ int shadow_enable(struct domain *d, u32
struct page_info *pg = NULL;
uint32_t *e;
int i, rv = 0;
+ struct p2m_domain *p2m = p2m_get_hostp2m(d);
mode |= PG_SH_enable;
@@ -3135,7 +3138,8 @@ int shadow_enable(struct domain *d, u32
* to avoid possible deadlock. */
if ( mode & PG_translate )
{
- rv = p2m_alloc_table(d, shadow_alloc_p2m_page, shadow_free_p2m_page);
+ rv = p2m_alloc_table(p2m,
+ shadow_alloc_p2m_page, shadow_free_p2m_page);
if (rv != 0)
goto out_unlocked;
}
@@ -3146,7 +3150,7 @@ int shadow_enable(struct domain *d, u32
{
/* Get a single page from the shadow pool. Take it via the
* P2M interface to make freeing it simpler afterwards. */
- pg = shadow_alloc_p2m_page(d);
+ pg = shadow_alloc_p2m_page(p2m);
if ( pg == NULL )
{
rv = -ENOMEM;
@@ -3195,10 +3199,10 @@ int shadow_enable(struct domain *d, u32
out_locked:
shadow_unlock(d);
out_unlocked:
- if ( rv != 0 && !pagetable_is_null(p2m_get_pagetable(p2m_get_hostp2m(d))) )
- p2m_teardown(d);
+ if ( rv != 0 && !pagetable_is_null(p2m_get_pagetable(p2m)) )
+ p2m_teardown(p2m);
if ( rv != 0 && pg != NULL )
- shadow_free_p2m_page(d, pg);
+ shadow_free_p2m_page(p2m, pg);
domain_unpause(d);
return rv;
}
@@ -3210,6 +3214,7 @@ void shadow_teardown(struct domain *d)
struct vcpu *v;
mfn_t mfn;
struct page_info *pg;
+ struct p2m_domain *p2m = p2m_get_hostp2m(d);
ASSERT(d->is_dying);
ASSERT(d != current->domain);
@@ -3264,7 +3269,7 @@ void shadow_teardown(struct domain *d)
#endif /* (SHADOW_OPTIMIZATIONS & (SHOPT_VIRTUAL_TLB|SHOPT_OUT_OF_SYNC)) */
while ( (pg = page_list_remove_head(&d->arch.paging.shadow.p2m_freelist)) )
- shadow_free_p2m_page(d, pg);
+ shadow_free_p2m_page(p2m, pg);
if ( d->arch.paging.shadow.total_pages != 0 )
{
@@ -3298,7 +3303,7 @@ void shadow_teardown(struct domain *d)
if ( !hvm_paging_enabled(v) )
v->arch.guest_table = pagetable_null();
}
- shadow_free_p2m_page(d,
+ shadow_free_p2m_page(p2m,
pagetable_get_page(d->arch.paging.shadow.unpaged_pagetable));
d->arch.paging.shadow.unpaged_pagetable = pagetable_null();
}
@@ -3335,7 +3340,7 @@ void shadow_final_teardown(struct domain
shadow_teardown(d);
/* It is now safe to pull down the p2m map. */
- p2m_teardown(d);
+ p2m_teardown(p2m_get_hostp2m(d));
SHADOW_PRINTK("dom %u final teardown done."
" Shadow pages total = %u, free = %u, p2m=%u\n",
@@ -3657,10 +3662,11 @@ int shadow_track_dirty_vram(struct domai
unsigned long i;
p2m_type_t t;
struct sh_dirty_vram *dirty_vram = d->arch.hvm_domain.dirty_vram;
+ struct p2m_domain *p2m = p2m_get_hostp2m(d);
if (end_pfn < begin_pfn
- || begin_pfn > d->arch.p2m->max_mapped_pfn
- || end_pfn >= d->arch.p2m->max_mapped_pfn)
+ || begin_pfn > p2m->max_mapped_pfn
+ || end_pfn >= p2m->max_mapped_pfn)
return -EINVAL;
shadow_lock(d);
@@ -3729,7 +3735,7 @@ int shadow_track_dirty_vram(struct domai
/* Iterate over VRAM to track dirty bits. */
for ( i = 0; i < nr; i++ ) {
- mfn_t mfn = gfn_to_mfn(d, begin_pfn + i, &t);
+ mfn_t mfn = gfn_to_mfn(p2m, begin_pfn + i, &t);
struct page_info *page;
int dirty = 0;
paddr_t sl1ma = dirty_vram->sl1ma[i];
@@ -3814,7 +3820,7 @@ int shadow_track_dirty_vram(struct domai
/* was clean for more than two seconds, try to disable guest
* write access */
for ( i = begin_pfn; i < end_pfn; i++ ) {
- mfn_t mfn = gfn_to_mfn(d, i, &t);
+ mfn_t mfn = gfn_to_mfn(p2m, i, &t);
if (mfn_x(mfn) != INVALID_MFN)
flush_tlb |= sh_remove_write_access(d->vcpu[0], mfn,
1, 0);
}
diff -r 9e58c46ee63b -r e7afe98afd43 xen/arch/x86/mm/shadow/multi.c
--- a/xen/arch/x86/mm/shadow/multi.c Mon Aug 09 16:40:18 2010 +0100
+++ b/xen/arch/x86/mm/shadow/multi.c Mon Aug 09 16:46:42 2010 +0100
@@ -167,7 +167,7 @@ sh_walk_guest_tables(struct vcpu *v, uns
sh_walk_guest_tables(struct vcpu *v, unsigned long va, walk_t *gw,
uint32_t pfec)
{
- return guest_walk_tables(v, va, gw, pfec,
+ return guest_walk_tables(v, p2m_get_hostp2m(v->domain), va, gw, pfec,
#if GUEST_PAGING_LEVELS == 3 /* PAE */
_mfn(INVALID_MFN),
v->arch.paging.shadow.gl3e
@@ -2240,6 +2240,7 @@ static int validate_gl4e(struct vcpu *v,
shadow_l4e_t *sl4p = se;
mfn_t sl3mfn = _mfn(INVALID_MFN);
struct domain *d = v->domain;
+ struct p2m_domain *p2m = p2m_get_hostp2m(d);
p2m_type_t p2mt;
int result = 0;
@@ -2248,7 +2249,7 @@ static int validate_gl4e(struct vcpu *v,
if ( guest_l4e_get_flags(new_gl4e) & _PAGE_PRESENT )
{
gfn_t gl3gfn = guest_l4e_get_gfn(new_gl4e);
- mfn_t gl3mfn = gfn_to_mfn_query(d, gl3gfn, &p2mt);
+ mfn_t gl3mfn = gfn_to_mfn_query(p2m, gl3gfn, &p2mt);
if ( p2m_is_ram(p2mt) )
sl3mfn = get_shadow_status(v, gl3mfn, SH_type_l3_shadow);
else if ( p2mt != p2m_populate_on_demand )
@@ -2299,13 +2300,14 @@ static int validate_gl3e(struct vcpu *v,
mfn_t sl2mfn = _mfn(INVALID_MFN);
p2m_type_t p2mt;
int result = 0;
+ struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
perfc_incr(shadow_validate_gl3e_calls);
if ( guest_l3e_get_flags(new_gl3e) & _PAGE_PRESENT )
{
gfn_t gl2gfn = guest_l3e_get_gfn(new_gl3e);
- mfn_t gl2mfn = gfn_to_mfn_query(v->domain, gl2gfn, &p2mt);
+ mfn_t gl2mfn = gfn_to_mfn_query(p2m, gl2gfn, &p2mt);
if ( p2m_is_ram(p2mt) )
sl2mfn = get_shadow_status(v, gl2mfn, SH_type_l2_shadow);
else if ( p2mt != p2m_populate_on_demand )
@@ -2329,6 +2331,7 @@ static int validate_gl2e(struct vcpu *v,
guest_l2e_t new_gl2e = *(guest_l2e_t *)new_ge;
shadow_l2e_t *sl2p = se;
mfn_t sl1mfn = _mfn(INVALID_MFN);
+ struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
p2m_type_t p2mt;
int result = 0;
@@ -2354,7 +2357,7 @@ static int validate_gl2e(struct vcpu *v,
}
else
{
- mfn_t gl1mfn = gfn_to_mfn_query(v->domain, gl1gfn, &p2mt);
+ mfn_t gl1mfn = gfn_to_mfn_query(p2m, gl1gfn, &p2mt);
if ( p2m_is_ram(p2mt) )
sl1mfn = get_shadow_status(v, gl1mfn, SH_type_l1_shadow);
else if ( p2mt != p2m_populate_on_demand )
@@ -2415,6 +2418,7 @@ static int validate_gl1e(struct vcpu *v,
shadow_l1e_t *sl1p = se;
gfn_t gfn;
mfn_t gmfn;
+ struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
p2m_type_t p2mt;
int result = 0;
#if (SHADOW_OPTIMIZATIONS & SHOPT_OUT_OF_SYNC)
@@ -2424,7 +2428,7 @@ static int validate_gl1e(struct vcpu *v,
perfc_incr(shadow_validate_gl1e_calls);
gfn = guest_l1e_get_gfn(new_gl1e);
- gmfn = gfn_to_mfn_query(v->domain, gfn, &p2mt);
+ gmfn = gfn_to_mfn_query(p2m, gfn, &p2mt);
l1e_propagate_from_guest(v, new_gl1e, gmfn, &new_sl1e, ft_prefetch, p2mt);
result |= shadow_set_l1e(v, sl1p, new_sl1e, p2mt, sl1mfn);
@@ -2484,7 +2488,7 @@ void sh_resync_l1(struct vcpu *v, mfn_t
shadow_l1e_t nsl1e;
gfn = guest_l1e_get_gfn(gl1e);
- gmfn = gfn_to_mfn_query(v->domain, gfn, &p2mt);
+ gmfn = gfn_to_mfn_query(p2m_get_hostp2m(v->domain), gfn, &p2mt);
l1e_propagate_from_guest(v, gl1e, gmfn, &nsl1e, ft_prefetch, p2mt);
rc |= shadow_set_l1e(v, sl1p, nsl1e, p2mt, sl1mfn);
@@ -2810,7 +2814,7 @@ static void sh_prefetch(struct vcpu *v,
/* Look at the gfn that the l1e is pointing at */
gfn = guest_l1e_get_gfn(gl1e);
- gmfn = gfn_to_mfn_query(v->domain, gfn, &p2mt);
+ gmfn = gfn_to_mfn_query(p2m_get_hostp2m(v->domain), gfn, &p2mt);
/* Propagate the entry. */
l1e_propagate_from_guest(v, gl1e, gmfn, &sl1e, ft_prefetch, p2mt);
@@ -3166,7 +3170,7 @@ static int sh_page_fault(struct vcpu *v,
/* What mfn is the guest trying to access? */
gfn = guest_l1e_get_gfn(gw.l1e);
- gmfn = gfn_to_mfn_guest(d, gfn, &p2mt);
+ gmfn = gfn_to_mfn_guest(p2m_get_hostp2m(d), gfn, &p2mt);
if ( shadow_mode_refcounts(d) &&
((!p2m_is_valid(p2mt) && !p2m_is_grant(p2mt)) ||
@@ -4272,7 +4276,7 @@ sh_update_cr3(struct vcpu *v, int do_loc
if ( guest_l3e_get_flags(gl3e[i]) & _PAGE_PRESENT )
{
gl2gfn = guest_l3e_get_gfn(gl3e[i]);
- gl2mfn = gfn_to_mfn_query(d, gl2gfn, &p2mt);
+ gl2mfn = gfn_to_mfn_query(p2m_get_hostp2m(d), gl2gfn, &p2mt);
if ( p2m_is_ram(p2mt) )
flush |= sh_remove_write_access(v, gl2mfn, 2, 0);
}
@@ -4285,7 +4289,7 @@ sh_update_cr3(struct vcpu *v, int do_loc
if ( guest_l3e_get_flags(gl3e[i]) & _PAGE_PRESENT )
{
gl2gfn = guest_l3e_get_gfn(gl3e[i]);
- gl2mfn = gfn_to_mfn_query(d, gl2gfn, &p2mt);
+ gl2mfn = gfn_to_mfn_query(p2m_get_hostp2m(d), gl2gfn, &p2mt);
if ( p2m_is_ram(p2mt) )
sh_set_toplevel_shadow(v, i, gl2mfn, (i == 3)
? SH_type_l2h_shadow
@@ -4682,7 +4686,7 @@ static void sh_pagetable_dying(struct vc
if ( gcr3 == gpa )
fast_path = 1;
- gmfn = gfn_to_mfn_query(v->domain, _gfn(gpa >> PAGE_SHIFT), &p2mt);
+ gmfn = gfn_to_mfn_query(p2m_get_hostp2m(v->domain), _gfn(gpa >>
PAGE_SHIFT), &p2mt);
if ( !mfn_valid(gmfn) || !p2m_is_ram(p2mt) )
{
printk(XENLOG_DEBUG "sh_pagetable_dying: gpa not valid %"PRIpaddr"\n",
@@ -4702,7 +4706,7 @@ static void sh_pagetable_dying(struct vc
{
/* retrieving the l2s */
gl2a = guest_l3e_get_paddr(gl3e[i]);
- gmfn = gfn_to_mfn_query(v->domain, _gfn(gl2a >> PAGE_SHIFT),
&p2mt);
+ gmfn = gfn_to_mfn_query(p2m_get_hostp2m(v->domain), _gfn(gl2a >>
PAGE_SHIFT), &p2mt);
smfn = shadow_hash_lookup(v, mfn_x(gmfn), SH_type_l2_pae_shadow);
}
@@ -4737,7 +4741,7 @@ static void sh_pagetable_dying(struct vc
shadow_lock(v->domain);
- gmfn = gfn_to_mfn_query(v->domain, _gfn(gpa >> PAGE_SHIFT), &p2mt);
+ gmfn = gfn_to_mfn_query(p2m_get_hostp2m(v->domain), _gfn(gpa >>
PAGE_SHIFT), &p2mt);
#if GUEST_PAGING_LEVELS == 2
smfn = shadow_hash_lookup(v, mfn_x(gmfn), SH_type_l2_32_shadow);
#else
@@ -4777,6 +4781,7 @@ static mfn_t emulate_gva_to_mfn(struct v
mfn_t mfn;
p2m_type_t p2mt;
uint32_t pfec = PFEC_page_present | PFEC_write_access;
+ struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
/* Translate the VA to a GFN */
gfn = sh_gva_to_gfn(v, vaddr, &pfec);
@@ -4792,9 +4797,9 @@ static mfn_t emulate_gva_to_mfn(struct v
/* Translate the GFN to an MFN */
/* PoD: query only if shadow lock is held (to avoid deadlock) */
if ( shadow_locked_by_me(v->domain) )
- mfn = gfn_to_mfn_query(v->domain, _gfn(gfn), &p2mt);
+ mfn = gfn_to_mfn_query(p2m, _gfn(gfn), &p2mt);
else
- mfn = gfn_to_mfn(v->domain, _gfn(gfn), &p2mt);
+ mfn = gfn_to_mfn(p2m, _gfn(gfn), &p2mt);
if ( p2m_is_readonly(p2mt) )
return _mfn(READONLY_GFN);
@@ -5199,7 +5204,7 @@ int sh_audit_l1_table(struct vcpu *v, mf
{
gfn = guest_l1e_get_gfn(*gl1e);
mfn = shadow_l1e_get_mfn(*sl1e);
- gmfn = gfn_to_mfn_query(v->domain, gfn, &p2mt);
+ gmfn = gfn_to_mfn_query(p2m_get_hostp2m(v->domain), gfn,
&p2mt);
if ( !p2m_is_grant(p2mt) && mfn_x(gmfn) != mfn_x(mfn) )
AUDIT_FAIL(1, "bad translation: gfn %" SH_PRI_gfn
" --> %" PRI_mfn " != mfn %" PRI_mfn,
@@ -5243,6 +5248,7 @@ int sh_audit_l2_table(struct vcpu *v, mf
shadow_l2e_t *sl2e;
mfn_t mfn, gmfn, gl2mfn;
gfn_t gfn;
+ struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
p2m_type_t p2mt;
char *s;
int done = 0;
@@ -5269,7 +5275,7 @@ int sh_audit_l2_table(struct vcpu *v, mf
mfn = shadow_l2e_get_mfn(*sl2e);
gmfn = (guest_l2e_get_flags(*gl2e) & _PAGE_PSE)
? get_fl1_shadow_status(v, gfn)
- : get_shadow_status(v, gfn_to_mfn_query(v->domain, gfn,
&p2mt),
+ : get_shadow_status(v, gfn_to_mfn_query(p2m, gfn, &p2mt),
SH_type_l1_shadow);
if ( mfn_x(gmfn) != mfn_x(mfn) )
AUDIT_FAIL(2, "bad translation: gfn %" SH_PRI_gfn
@@ -5277,8 +5283,8 @@ int sh_audit_l2_table(struct vcpu *v, mf
" --> %" PRI_mfn " != mfn %" PRI_mfn,
gfn_x(gfn),
(guest_l2e_get_flags(*gl2e) & _PAGE_PSE) ? 0
- : mfn_x(gfn_to_mfn_query(v->domain, gfn, &p2mt)),
- mfn_x(gmfn), mfn_x(mfn));
+ : mfn_x(gfn_to_mfn_query(p2m,
+ gfn, &p2mt)), mfn_x(gmfn), mfn_x(mfn));
}
});
sh_unmap_domain_page(gp);
@@ -5316,7 +5322,7 @@ int sh_audit_l3_table(struct vcpu *v, mf
{
gfn = guest_l3e_get_gfn(*gl3e);
mfn = shadow_l3e_get_mfn(*sl3e);
- gmfn = get_shadow_status(v, gfn_to_mfn_query(v->domain, gfn,
&p2mt),
+ gmfn = get_shadow_status(v,
gfn_to_mfn_query(p2m_get_hostp2m(v->domain), gfn, &p2mt),
((GUEST_PAGING_LEVELS == 3 ||
is_pv_32on64_vcpu(v))
&& !shadow_mode_external(v->domain)
@@ -5363,7 +5369,8 @@ int sh_audit_l4_table(struct vcpu *v, mf
{
gfn = guest_l4e_get_gfn(*gl4e);
mfn = shadow_l4e_get_mfn(*sl4e);
- gmfn = get_shadow_status(v, gfn_to_mfn_query(v->domain, gfn,
&p2mt),
+ gmfn = get_shadow_status(v,
gfn_to_mfn_query(p2m_get_hostp2m(v->domain),
+ gfn, &p2mt),
SH_type_l3_shadow);
if ( mfn_x(gmfn) != mfn_x(mfn) )
AUDIT_FAIL(4, "bad translation: gfn %" SH_PRI_gfn
diff -r 9e58c46ee63b -r e7afe98afd43 xen/common/grant_table.c
--- a/xen/common/grant_table.c Mon Aug 09 16:40:18 2010 +0100
+++ b/xen/common/grant_table.c Mon Aug 09 16:46:42 2010 +0100
@@ -109,7 +109,7 @@ static unsigned inline int max_nr_maptra
#define gfn_to_mfn_private(_d, _gfn) ({ \
p2m_type_t __p2mt; \
unsigned long __x; \
- __x = mfn_x(gfn_to_mfn_unshare(_d, _gfn, &__p2mt, 1)); \
+ __x = mfn_x(gfn_to_mfn_unshare(p2m_get_hostp2m(_d), _gfn, &__p2mt, 1)); \
if ( !p2m_is_valid(__p2mt) ) \
__x = INVALID_MFN; \
__x; })
@@ -1933,12 +1933,13 @@ __gnttab_copy(
{
#ifdef CONFIG_X86
p2m_type_t p2mt;
- s_frame = mfn_x(gfn_to_mfn(sd, op->source.u.gmfn, &p2mt));
+ struct p2m_domain *p2m = p2m_get_hostp2m(sd);
+ s_frame = mfn_x(gfn_to_mfn(p2m, op->source.u.gmfn, &p2mt));
if ( !p2m_is_valid(p2mt) )
s_frame = INVALID_MFN;
if ( p2m_is_paging(p2mt) )
{
- p2m_mem_paging_populate(sd, op->source.u.gmfn);
+ p2m_mem_paging_populate(p2m, op->source.u.gmfn);
rc = -ENOENT;
goto error_out;
}
@@ -1979,12 +1980,13 @@ __gnttab_copy(
{
#ifdef CONFIG_X86
p2m_type_t p2mt;
- d_frame = mfn_x(gfn_to_mfn_unshare(dd, op->dest.u.gmfn, &p2mt, 1));
+ struct p2m_domain *p2m = p2m_get_hostp2m(dd);
+ d_frame = mfn_x(gfn_to_mfn_unshare(p2m, op->dest.u.gmfn, &p2mt, 1));
if ( !p2m_is_valid(p2mt) )
d_frame = INVALID_MFN;
if ( p2m_is_paging(p2mt) )
{
- p2m_mem_paging_populate(dd, op->dest.u.gmfn);
+ p2m_mem_paging_populate(p2m, op->dest.u.gmfn);
rc = -ENOENT;
goto error_out;
}
diff -r 9e58c46ee63b -r e7afe98afd43 xen/common/memory.c
--- a/xen/common/memory.c Mon Aug 09 16:40:18 2010 +0100
+++ b/xen/common/memory.c Mon Aug 09 16:46:42 2010 +0100
@@ -161,7 +161,7 @@ int guest_remove_page(struct domain *d,
unsigned long mfn;
#ifdef CONFIG_X86
- mfn = mfn_x(gfn_to_mfn(d, gmfn, &p2mt));
+ mfn = mfn_x(gfn_to_mfn(p2m_get_hostp2m(d), gmfn, &p2mt));
#else
mfn = gmfn_to_mfn(d, gmfn);
#endif
@@ -356,7 +356,7 @@ static long memory_exchange(XEN_GUEST_HA
p2m_type_t p2mt;
/* Shared pages cannot be exchanged */
- mfn = mfn_x(gfn_to_mfn_unshare(d, gmfn + k, &p2mt, 0));
+ mfn = mfn_x(gfn_to_mfn_unshare(p2m_get_hostp2m(d), gmfn + k,
&p2mt, 0));
if ( p2m_is_shared(p2mt) )
{
rc = -ENOMEM;
diff -r 9e58c46ee63b -r e7afe98afd43 xen/common/tmem_xen.c
--- a/xen/common/tmem_xen.c Mon Aug 09 16:40:18 2010 +0100
+++ b/xen/common/tmem_xen.c Mon Aug 09 16:46:42 2010 +0100
@@ -100,7 +100,7 @@ static inline void *cli_mfn_to_va(tmem_c
unsigned long cli_mfn;
p2m_type_t t;
- cli_mfn = mfn_x(gfn_to_mfn(current->domain, cmfn, &t));
+ cli_mfn = mfn_x(gfn_to_mfn(p2m_get_hostp2m(current->domain), cmfn, &t));
if (t != p2m_ram_rw || cli_mfn == INVALID_MFN)
return NULL;
if (pcli_mfn != NULL)
diff -r 9e58c46ee63b -r e7afe98afd43 xen/include/asm-x86/guest_pt.h
--- a/xen/include/asm-x86/guest_pt.h Mon Aug 09 16:40:18 2010 +0100
+++ b/xen/include/asm-x86/guest_pt.h Mon Aug 09 16:46:42 2010 +0100
@@ -272,8 +272,8 @@ guest_walk_to_gpa(walk_t *gw)
#define guest_walk_tables GPT_RENAME(guest_walk_tables, GUEST_PAGING_LEVELS)
extern uint32_t
-guest_walk_tables(struct vcpu *v, unsigned long va, walk_t *gw,
- uint32_t pfec, mfn_t top_mfn, void *top_map);
+guest_walk_tables(struct vcpu *v, struct p2m_domain *p2m, unsigned long va,
+ walk_t *gw, uint32_t pfec, mfn_t top_mfn, void *top_map);
/* Pretty-print the contents of a guest-walk */
static inline void print_gw(walk_t *gw)
diff -r 9e58c46ee63b -r e7afe98afd43 xen/include/asm-x86/mem_sharing.h
--- a/xen/include/asm-x86/mem_sharing.h Mon Aug 09 16:40:18 2010 +0100
+++ b/xen/include/asm-x86/mem_sharing.h Mon Aug 09 16:46:42 2010 +0100
@@ -30,17 +30,17 @@ typedef uint64_t shr_handle_t;
typedef uint64_t shr_handle_t;
unsigned int mem_sharing_get_nr_saved_mfns(void);
-int mem_sharing_nominate_page(struct domain *d,
+int mem_sharing_nominate_page(struct p2m_domain *p2m,
unsigned long gfn,
int expected_refcnt,
shr_handle_t *phandle);
#define MEM_SHARING_MUST_SUCCEED (1<<0)
#define MEM_SHARING_DESTROY_GFN (1<<1)
-int mem_sharing_unshare_page(struct domain *d,
+int mem_sharing_unshare_page(struct p2m_domain *p2m,
unsigned long gfn,
uint16_t flags);
int mem_sharing_sharing_resume(struct domain *d);
-int mem_sharing_cache_resize(struct domain *d, int new_size);
+int mem_sharing_cache_resize(struct p2m_domain *p2m, int new_size);
int mem_sharing_domctl(struct domain *d,
xen_domctl_mem_sharing_op_t *mec);
void mem_sharing_init(void);
diff -r 9e58c46ee63b -r e7afe98afd43 xen/include/asm-x86/p2m.h
--- a/xen/include/asm-x86/p2m.h Mon Aug 09 16:40:18 2010 +0100
+++ b/xen/include/asm-x86/p2m.h Mon Aug 09 16:46:42 2010 +0100
@@ -172,23 +172,28 @@ struct p2m_domain {
/* Shadow translated domain: p2m mapping */
pagetable_t phys_table;
+ struct domain *domain; /* back pointer to domain */
+
/* Pages used to construct the p2m */
struct page_list_head pages;
/* Functions to call to get or free pages for the p2m */
- struct page_info * (*alloc_page )(struct domain *d);
- void (*free_page )(struct domain *d,
+ struct page_info * (*alloc_page )(struct p2m_domain *p2m);
+ void (*free_page )(struct p2m_domain *p2m,
struct page_info *pg);
- int (*set_entry )(struct domain *d, unsigned long gfn,
+ int (*set_entry )(struct p2m_domain *p2m,
+ unsigned long gfn,
mfn_t mfn, unsigned int page_order,
p2m_type_t p2mt);
- mfn_t (*get_entry )(struct domain *d, unsigned long gfn,
+ mfn_t (*get_entry )(struct p2m_domain *p2m,
+ unsigned long gfn,
p2m_type_t *p2mt,
p2m_query_t q);
- mfn_t (*get_entry_current)(unsigned long gfn,
+ mfn_t (*get_entry_current)(struct p2m_domain *p2m,
+ unsigned long gfn,
p2m_type_t *p2mt,
p2m_query_t q);
- void (*change_entry_type_global)(struct domain *d,
+ void (*change_entry_type_global)(struct p2m_domain *p2m,
p2m_type_t ot,
p2m_type_t nt);
@@ -279,65 +284,64 @@ static inline p2m_type_t p2m_flags_to_ty
}
/* Read the current domain's p2m table. Do not populate PoD pages. */
-static inline mfn_t gfn_to_mfn_type_current(unsigned long gfn, p2m_type_t *t,
+static inline mfn_t gfn_to_mfn_type_current(struct p2m_domain *p2m,
+ unsigned long gfn, p2m_type_t *t,
p2m_query_t q)
{
- return current->domain->arch.p2m->get_entry_current(gfn, t, q);
-}
-
-/* Read another domain's P2M table, mapping pages as we go.
+ return p2m->get_entry_current(p2m, gfn, t, q);
+}
+
+/* Read P2M table, mapping pages as we go.
* Do not populate PoD pages. */
-static inline
-mfn_t gfn_to_mfn_type_foreign(struct domain *d, unsigned long gfn, p2m_type_t
*t,
- p2m_query_t q)
-{
- return d->arch.p2m->get_entry(d, gfn, t, q);
-}
+static inline mfn_t
+gfn_to_mfn_type_p2m(struct p2m_domain *p2m, unsigned long gfn,
+ p2m_type_t *t, p2m_query_t q)
+{
+ return p2m->get_entry(p2m, gfn, t, q);
+}
+
/* General conversion function from gfn to mfn */
-static inline mfn_t _gfn_to_mfn_type(struct domain *d,
+static inline mfn_t _gfn_to_mfn_type(struct p2m_domain *p2m,
unsigned long gfn, p2m_type_t *t,
p2m_query_t q)
{
- if ( !paging_mode_translate(d) )
+ if ( !p2m || !paging_mode_translate(p2m->domain) )
{
/* Not necessarily true, but for non-translated guests, we claim
* it's the most generic kind of memory */
*t = p2m_ram_rw;
return _mfn(gfn);
}
- if ( likely(current->domain == d) )
- return gfn_to_mfn_type_current(gfn, t, q);
+ if ( likely(current->domain == p2m->domain) )
+ return gfn_to_mfn_type_current(p2m, gfn, t, q);
else
- return gfn_to_mfn_type_foreign(d, gfn, t, q);
-}
-
-#define gfn_to_mfn(d, g, t) _gfn_to_mfn_type((d), (g), (t), p2m_alloc)
-#define gfn_to_mfn_query(d, g, t) _gfn_to_mfn_type((d), (g), (t), p2m_query)
-#define gfn_to_mfn_guest(d, g, t) _gfn_to_mfn_type((d), (g), (t), p2m_guest)
-
-#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,
+ return gfn_to_mfn_type_p2m(p2m, gfn, t, q);
+}
+
+#define gfn_to_mfn(p2m, g, t) _gfn_to_mfn_type((p2m), (g), (t), p2m_alloc)
+#define gfn_to_mfn_query(p2m, g, t) _gfn_to_mfn_type((p2m), (g), (t),
p2m_query)
+#define gfn_to_mfn_guest(p2m, g, t) _gfn_to_mfn_type((p2m), (g), (t),
p2m_guest)
+
+static inline mfn_t gfn_to_mfn_unshare(struct p2m_domain *p2m,
unsigned long gfn,
p2m_type_t *p2mt,
int must_succeed)
{
mfn_t mfn;
- mfn = gfn_to_mfn(d, gfn, p2mt);
+ mfn = gfn_to_mfn(p2m, gfn, p2mt);
#ifdef __x86_64__
if ( p2m_is_shared(*p2mt) )
{
- if ( mem_sharing_unshare_page(d, gfn,
+ if ( mem_sharing_unshare_page(p2m, gfn,
must_succeed
? MEM_SHARING_MUST_SUCCEED : 0) )
{
BUG_ON(must_succeed);
return mfn;
}
- mfn = gfn_to_mfn(d, gfn, p2mt);
+ mfn = gfn_to_mfn(p2m, gfn, p2mt);
}
#endif
@@ -350,7 +354,7 @@ static inline unsigned long gmfn_to_mfn(
{
mfn_t mfn;
p2m_type_t t;
- mfn = gfn_to_mfn(d, gpfn, &t);
+ mfn = gfn_to_mfn(d->arch.p2m, gpfn, &t);
if ( p2m_is_valid(t) )
return mfn_x(mfn);
return INVALID_MFN;
@@ -374,16 +378,16 @@ int p2m_init(struct domain *d);
* build the p2m, and to release it again at the end of day.
*
* Returns 0 for success or -errno. */
-int p2m_alloc_table(struct domain *d,
- struct page_info * (*alloc_page)(struct domain *d),
- void (*free_page)(struct domain *d, struct page_info *pg));
+int p2m_alloc_table(struct p2m_domain *p2m,
+ struct page_info * (*alloc_page)(struct p2m_domain *p2m),
+ void (*free_page)(struct p2m_domain *p2m, struct page_info
*pg));
/* Return all the p2m resources to Xen. */
-void p2m_teardown(struct domain *d);
+void p2m_teardown(struct p2m_domain *p2m);
void p2m_final_teardown(struct domain *d);
/* Dump PoD information about the domain */
-void p2m_pod_dump_data(struct domain *d);
+void p2m_pod_dump_data(struct p2m_domain *p2m);
/* Move all pages from the populate-on-demand cache to the domain page_list
* (usually in preparation for domain destruction) */
@@ -402,14 +406,18 @@ p2m_pod_decrease_reservation(struct doma
/* Called by p2m code when demand-populating a PoD page */
int
-p2m_pod_demand_populate(struct domain *d, unsigned long gfn,
+p2m_pod_demand_populate(struct p2m_domain *p2m, unsigned long gfn,
unsigned int order,
p2m_query_t q);
/* Add a page to a domain's p2m table */
-int guest_physmap_add_entry(struct domain *d, unsigned long gfn,
+int guest_physmap_add_entry(struct p2m_domain *p2m, unsigned long gfn,
unsigned long mfn, unsigned int page_order,
p2m_type_t t);
+
+/* Remove a page from a domain's p2m table */
+void guest_physmap_remove_entry(struct p2m_domain *p2m, unsigned long gfn,
+ unsigned long mfn, unsigned int page_order);
/* Set a p2m range as populate-on-demand */
int guest_physmap_mark_populate_on_demand(struct domain *d, unsigned long gfn,
@@ -419,49 +427,55 @@ int guest_physmap_mark_populate_on_deman
*
* Return 0 for success
*/
-static inline int guest_physmap_add_page(struct domain *d, unsigned long gfn,
+static inline int guest_physmap_add_page(struct domain *d,
+ unsigned long gfn,
unsigned long mfn,
unsigned int page_order)
{
- return guest_physmap_add_entry(d, gfn, mfn, page_order, p2m_ram_rw);
+ return guest_physmap_add_entry(d->arch.p2m, gfn, mfn, page_order,
p2m_ram_rw);
}
/* Remove a page from a domain's p2m table */
-void guest_physmap_remove_page(struct domain *d, unsigned long gfn,
- unsigned long mfn, unsigned int page_order);
+static inline void guest_physmap_remove_page(struct domain *d,
+ unsigned long gfn,
+ unsigned long mfn, unsigned int page_order)
+{
+ guest_physmap_remove_entry(d->arch.p2m, gfn, mfn, page_order);
+}
/* Change types across all p2m entries in a domain */
-void p2m_change_type_global(struct domain *d, p2m_type_t ot, p2m_type_t nt);
-void p2m_change_entry_type_global(struct domain *d, p2m_type_t ot, p2m_type_t
nt);
+void p2m_change_type_global(struct p2m_domain *p2m, p2m_type_t ot, p2m_type_t
nt);
+void p2m_change_entry_type_global(struct p2m_domain *p2m, p2m_type_t ot,
p2m_type_t nt);
/* Compare-exchange the type of a single p2m entry */
-p2m_type_t p2m_change_type(struct domain *d, unsigned long gfn,
+p2m_type_t p2m_change_type(struct p2m_domain *p2m, unsigned long gfn,
p2m_type_t ot, p2m_type_t nt);
/* Set mmio addresses in the p2m table (for pass-through) */
-int set_mmio_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn);
-int clear_mmio_p2m_entry(struct domain *d, unsigned long gfn);
+int set_mmio_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn);
+int clear_mmio_p2m_entry(struct p2m_domain *p2m, unsigned long gfn);
#ifdef __x86_64__
/* Modify p2m table for shared gfn */
-int set_shared_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn);
+int set_shared_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn);
+
/* Check if a nominated gfn is valid to be paged out */
-int p2m_mem_paging_nominate(struct domain *d, unsigned long gfn);
+int p2m_mem_paging_nominate(struct p2m_domain *p2m, unsigned long gfn);
/* Evict a frame */
-int p2m_mem_paging_evict(struct domain *d, unsigned long gfn);
+int p2m_mem_paging_evict(struct p2m_domain *p2m, unsigned long gfn);
/* Start populating a paged out frame */
-void p2m_mem_paging_populate(struct domain *d, unsigned long gfn);
+void p2m_mem_paging_populate(struct p2m_domain *p2m, unsigned long gfn);
/* Prepare the p2m for paging a frame in */
-int p2m_mem_paging_prep(struct domain *d, unsigned long gfn);
+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 domain *d);
+void p2m_mem_paging_resume(struct p2m_domain *p2m);
#else
-static inline void p2m_mem_paging_populate(struct domain *d, unsigned long gfn)
+static inline void p2m_mem_paging_populate(struct p2m_domain *p2m, unsigned
long gfn)
{ }
#endif
-struct page_info *p2m_alloc_ptp(struct domain *d, unsigned long type);
+struct page_info *p2m_alloc_ptp(struct p2m_domain *p2m, unsigned long type);
#endif /* _XEN_P2M_H */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|