hap.c
来自「xen 3.2.2 源码」· C语言 代码 · 共 754 行 · 第 1/2 页
C
754 行
goto oom; m2mfn = page_to_mfn(pg); l3e = hap_map_domain_page(m3mfn); l3e[3] = l3e_from_pfn(mfn_x(m2mfn), _PAGE_PRESENT); hap_install_xen_entries_in_l2h(v, m2mfn); /* Install the monitor's own linear map */ l2e = hap_map_domain_page(m2mfn); for ( i = 0; i < L3_PAGETABLE_ENTRIES; i++ ) l2e[l2_table_offset(LINEAR_PT_VIRT_START) + i] = (l3e_get_flags(l3e[i]) & _PAGE_PRESENT) ? l2e_from_pfn(l3e_get_pfn(l3e[i]), __PAGE_HYPERVISOR) : l2e_empty(); hap_unmap_domain_page(l2e); hap_unmap_domain_page(l3e); HAP_PRINTK("new monitor table: %#lx\n", mfn_x(m3mfn)); return m3mfn; }#else { mfn_t m2mfn; if ( (pg = hap_alloc(d)) == NULL ) goto oom; m2mfn = page_to_mfn(pg);; hap_install_xen_entries_in_l2(v, m2mfn); return m2mfn; }#endif oom: HAP_ERROR("out of memory building monitor pagetable\n"); domain_crash(d); return _mfn(INVALID_MFN);}static void hap_destroy_monitor_table(struct vcpu* v, mfn_t mmfn){ struct domain *d = v->domain;#if CONFIG_PAGING_LEVELS == 3 /* Need to destroy the l2 monitor page in slot 4 too */ { l3_pgentry_t *l3e = hap_map_domain_page(mmfn); ASSERT(l3e_get_flags(l3e[3]) & _PAGE_PRESENT); hap_free(d, _mfn(l3e_get_pfn(l3e[3]))); hap_unmap_domain_page(l3e); }#endif /* Put the memory back in the pool */ hap_free(d, mmfn);}/************************************************//* HAP DOMAIN LEVEL FUNCTIONS *//************************************************/void hap_domain_init(struct domain *d){ hap_lock_init(d); INIT_LIST_HEAD(&d->arch.paging.hap.freelist); /* This domain will use HAP for log-dirty mode */ paging_log_dirty_init(d, hap_enable_log_dirty, hap_disable_log_dirty, hap_clean_dirty_bitmap);}/* return 0 for success, -errno for failure */int hap_enable(struct domain *d, u32 mode){ unsigned int old_pages; int rv = 0; domain_pause(d); /* error check */ if ( (d == current->domain) ) { rv = -EINVAL; goto out; } old_pages = d->arch.paging.hap.total_pages; if ( old_pages == 0 ) { unsigned int r; hap_lock(d); r = hap_set_allocation(d, 256, NULL); hap_unlock(d); if ( r != 0 ) { hap_set_allocation(d, 0, NULL); rv = -ENOMEM; goto out; } } /* allocate P2m table */ if ( mode & PG_translate ) { rv = p2m_alloc_table(d, hap_alloc_p2m_page, hap_free_p2m_page); if ( rv != 0 ) goto out; } d->arch.paging.mode = mode | PG_HAP_enable; out: domain_unpause(d); return rv;}void hap_final_teardown(struct domain *d){ if ( d->arch.paging.hap.total_pages != 0 ) hap_teardown(d); p2m_teardown(d); ASSERT(d->arch.paging.hap.p2m_pages == 0);}void hap_teardown(struct domain *d){ struct vcpu *v; mfn_t mfn; ASSERT(d->is_dying); ASSERT(d != current->domain); if ( !hap_locked_by_me(d) ) hap_lock(d); /* Keep various asserts happy */ if ( paging_mode_enabled(d) ) { /* release the monitor table held by each vcpu */ for_each_vcpu ( d, v ) { if ( v->arch.paging.mode && paging_mode_external(d) ) { mfn = pagetable_get_mfn(v->arch.monitor_table); if ( mfn_valid(mfn) && (mfn_x(mfn) != 0) ) hap_destroy_monitor_table(v, mfn); v->arch.monitor_table = pagetable_null(); } } } if ( d->arch.paging.hap.total_pages != 0 ) { HAP_PRINTK("teardown of domain %u starts." " pages total = %u, free = %u, p2m=%u\n", d->domain_id, d->arch.paging.hap.total_pages, d->arch.paging.hap.free_pages, d->arch.paging.hap.p2m_pages); hap_set_allocation(d, 0, NULL); HAP_PRINTK("teardown done." " pages total = %u, free = %u, p2m=%u\n", d->arch.paging.hap.total_pages, d->arch.paging.hap.free_pages, d->arch.paging.hap.p2m_pages); ASSERT(d->arch.paging.hap.total_pages == 0); } d->arch.paging.mode &= ~PG_log_dirty; hap_unlock(d);}int hap_domctl(struct domain *d, xen_domctl_shadow_op_t *sc, XEN_GUEST_HANDLE(void) u_domctl){ int rc, preempted = 0; switch ( sc->op ) { case XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION: hap_lock(d); rc = hap_set_allocation(d, sc->mb << (20 - PAGE_SHIFT), &preempted); hap_unlock(d); if ( preempted ) /* Not finished. Set up to re-run the call. */ rc = hypercall_create_continuation(__HYPERVISOR_domctl, "h", u_domctl); else /* Finished. Return the new allocation */ sc->mb = hap_get_allocation(d); return rc; case XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION: sc->mb = hap_get_allocation(d); return 0; default: HAP_ERROR("Bad hap domctl op %u\n", sc->op); return -EINVAL; }}void hap_vcpu_init(struct vcpu *v){ v->arch.paging.mode = &hap_paging_real_mode;}/************************************************//* HAP PAGING MODE FUNCTIONS *//************************************************//* * HAP guests can handle page faults (in the guest page tables) without * needing any action from Xen, so we should not be intercepting them. */static int hap_page_fault(struct vcpu *v, unsigned long va, struct cpu_user_regs *regs){ HAP_ERROR("Intercepted a guest #PF (%u:%u) with HAP enabled.\n", v->domain->domain_id, v->vcpu_id); domain_crash(v->domain); return 0;}/* * HAP guests can handle invlpg without needing any action from Xen, so * should not be intercepting it. */static int hap_invlpg(struct vcpu *v, unsigned long va){ HAP_ERROR("Intercepted a guest INVLPG (%u:%u) with HAP enabled.\n", v->domain->domain_id, v->vcpu_id); domain_crash(v->domain); return 0;}static void hap_update_cr3(struct vcpu *v, int do_locking){ v->arch.hvm_vcpu.hw_cr[3] = v->arch.hvm_vcpu.guest_cr[3]; hvm_update_guest_cr(v, 3);}static void hap_update_paging_modes(struct vcpu *v){ struct domain *d = v->domain; hap_lock(d); v->arch.paging.mode = !hvm_paging_enabled(v) ? &hap_paging_real_mode : hvm_long_mode_enabled(v) ? &hap_paging_long_mode : hvm_pae_enabled(v) ? &hap_paging_pae_mode : &hap_paging_protected_mode; if ( pagetable_is_null(v->arch.monitor_table) ) { mfn_t mmfn = hap_make_monitor_table(v); v->arch.monitor_table = pagetable_from_mfn(mmfn); make_cr3(v, mfn_x(mmfn)); hvm_update_host_cr3(v); } /* CR3 is effectively updated by a mode change. Flush ASIDs, etc. */ hap_update_cr3(v, 0); hap_unlock(d);}#if CONFIG_PAGING_LEVELS == 3static void p2m_install_entry_in_monitors(struct domain *d, l3_pgentry_t *l3e)/* Special case, only used for PAE hosts: update the mapping of the p2m * table. This is trivial in other paging modes (one top-level entry * points to the top-level p2m, no maintenance needed), but PAE makes * life difficult by needing a copy of the p2m table in eight l2h slots * in the monitor table. This function makes fresh copies when a p2m * l3e changes. */{ l2_pgentry_t *ml2e; struct vcpu *v; unsigned int index; index = ((unsigned long)l3e & ~PAGE_MASK) / sizeof(l3_pgentry_t); ASSERT(index < MACHPHYS_MBYTES>>1); for_each_vcpu ( d, v ) { if ( pagetable_get_pfn(v->arch.monitor_table) == 0 ) continue; ASSERT(paging_mode_external(v->domain)); if ( v == current ) /* OK to use linear map of monitor_table */ ml2e = __linear_l2_table + l2_linear_offset(RO_MPT_VIRT_START); else { l3_pgentry_t *ml3e; ml3e = hap_map_domain_page( pagetable_get_mfn(v->arch.monitor_table)); ASSERT(l3e_get_flags(ml3e[3]) & _PAGE_PRESENT); ml2e = hap_map_domain_page(_mfn(l3e_get_pfn(ml3e[3]))); ml2e += l2_table_offset(RO_MPT_VIRT_START); hap_unmap_domain_page(ml3e); } ml2e[index] = l2e_from_pfn(l3e_get_pfn(*l3e), __PAGE_HYPERVISOR); if ( v != current ) hap_unmap_domain_page(ml2e); }}#endifstatic voidhap_write_p2m_entry(struct vcpu *v, unsigned long gfn, l1_pgentry_t *p, mfn_t table_mfn, l1_pgentry_t new, unsigned int level){ hap_lock(v->domain); safe_write_pte(p, new);#if CONFIG_PAGING_LEVELS == 3 /* install P2M in monitor table for PAE Xen */ if ( level == 3 ) /* We have written to the p2m l3: need to sync the per-vcpu * copies of it in the monitor tables */ p2m_install_entry_in_monitors(v->domain, (l3_pgentry_t *)p);#endif hap_unlock(v->domain);}static unsigned long hap_gva_to_gfn_real_mode( struct vcpu *v, unsigned long gva, uint32_t *pfec){ return ((paddr_t)gva >> PAGE_SHIFT);}/* Entry points into this mode of the hap code. */struct paging_mode hap_paging_real_mode = { .page_fault = hap_page_fault, .invlpg = hap_invlpg, .gva_to_gfn = hap_gva_to_gfn_real_mode, .update_cr3 = hap_update_cr3, .update_paging_modes = hap_update_paging_modes, .write_p2m_entry = hap_write_p2m_entry, .guest_levels = 1};struct paging_mode hap_paging_protected_mode = { .page_fault = hap_page_fault, .invlpg = hap_invlpg, .gva_to_gfn = hap_gva_to_gfn_2level, .update_cr3 = hap_update_cr3, .update_paging_modes = hap_update_paging_modes, .write_p2m_entry = hap_write_p2m_entry, .guest_levels = 2};struct paging_mode hap_paging_pae_mode = { .page_fault = hap_page_fault, .invlpg = hap_invlpg, .gva_to_gfn = hap_gva_to_gfn_3level, .update_cr3 = hap_update_cr3, .update_paging_modes = hap_update_paging_modes, .write_p2m_entry = hap_write_p2m_entry, .guest_levels = 3};struct paging_mode hap_paging_long_mode = { .page_fault = hap_page_fault, .invlpg = hap_invlpg, .gva_to_gfn = hap_gva_to_gfn_4level, .update_cr3 = hap_update_cr3, .update_paging_modes = hap_update_paging_modes, .write_p2m_entry = hap_write_p2m_entry, .guest_levels = 4};/* * Local variables: * mode: C * c-set-style: "BSD" * c-basic-offset: 4 * indent-tabs-mode: nil * End: */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?