[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] Nested Virtualization: p2m infrastructure
# 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |