@@ -2489,18 +2489,21 @@ gp_fault:
static int vmx_alloc_vlapic_mapping(struct domain *d)
{
- void *apic_va;
+ struct page_info *pg;
+ unsigned long mfn;
if ( !cpu_has_vmx_virtualize_apic_accesses )
return 0;
- apic_va = alloc_xenheap_page();
- if ( apic_va == NULL )
+ pg = alloc_domheap_page(d, MEMF_no_owner);
+ if ( !pg )
return -ENOMEM;
- share_xen_page_with_guest(virt_to_page(apic_va), d, XENSHARE_writable);
- d->arch.hvm_domain.vmx.apic_access_mfn = virt_to_mfn(apic_va);
- set_mmio_p2m_entry(d, paddr_to_pfn(APIC_DEFAULT_PHYS_BASE),
- _mfn(virt_to_mfn(apic_va)), p2m_get_hostp2m(d)->default_access);
+ mfn = page_to_mfn(pg);
+ clear_domain_page(_mfn(mfn));
+ share_xen_page_with_guest(pg, d, XENSHARE_writable);
+ d->arch.hvm_domain.vmx.apic_access_mfn = mfn;
+ set_mmio_p2m_entry(d, paddr_to_pfn(APIC_DEFAULT_PHYS_BASE), _mfn(mfn),
+ p2m_get_hostp2m(d)->default_access);
return 0;
}
@@ -2508,8 +2511,9 @@ static int vmx_alloc_vlapic_mapping(stru
static void vmx_free_vlapic_mapping(struct domain *d)
{
unsigned long mfn = d->arch.hvm_domain.vmx.apic_access_mfn;
+
if ( mfn != 0 )
- free_xenheap_page(mfn_to_virt(mfn));
+ free_shared_domheap_page(mfn_to_page(mfn));
}
static void vmx_install_vlapic_mapping(struct vcpu *v)
@@ -454,7 +454,7 @@ void share_xen_page_with_guest(
/* Only add to the allocation list if the domain isn't dying. */
if ( !d->is_dying )
{
- page->count_info |= PGC_allocated | 1;
+ page->count_info |= PGC_xen_heap | PGC_allocated | 1;
if ( unlikely(d->xenheap_pages++ == 0) )
get_knownalive_domain(d);
page_list_add_tail(page, &d->xenpage_list);
@@ -469,6 +469,17 @@ void share_xen_page_with_privileged_gues
share_xen_page_with_guest(page, dom_xen, readonly);
}
+void free_shared_domheap_page(struct page_info *page)
+{
+ if ( test_and_clear_bit(_PGC_allocated, &page->count_info) )
+ put_page(page);
+ if ( !test_and_clear_bit(_PGC_xen_heap, &page->count_info) )
+ ASSERT_UNREACHABLE();
+ page->u.inuse.type_info = 0;
+ page_set_owner(page, NULL);
+ free_domheap_page(page);
+}
+
void make_cr3(struct vcpu *v, unsigned long mfn)
{
v->arch.cr3 = mfn << PAGE_SHIFT;
@@ -276,6 +276,7 @@ extern void share_xen_page_with_guest(
struct page_info *page, struct domain *d, int readonly);
extern void share_xen_page_with_privileged_guests(
struct page_info *page, int readonly);
+extern void free_shared_domheap_page(struct page_info *page);
#define frame_table ((struct page_info *)FRAMETABLE_VIRT_START)
#define spage_table ((struct spage_info *)SPAGETABLE_VIRT_START)