mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
x86/hvm/viridian: keep APIC assist page mapped...
... for the lifetime of the domain. If Xen is to make use of the APIC assist enlightenment then a persistent mapping needs to be kept, rather than the temporary one which is currently used only to initialize the page content. This patch also adds a comment block at the top of the source with information on the latest version of the spec. from Microsoft and the current URL where it may be found. Signed-off-by: Paul Durrant <paul.durrant@citrix.com> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
This commit is contained in:
1 parent
d0540cbd4a
commit
a6f2cdb633
3 files changed
+65
-21
No files matched your search
@@ -2606,6 +2606,8 @@ int hvm_vcpu_initialise(struct vcpu *v)
|
||||
|
||||
void hvm_vcpu_destroy(struct vcpu *v)
|
||||
{
|
||||
viridian_vcpu_deinit(v);
|
||||
|
||||
hvm_all_ioreq_servers_remove_vcpu(v->domain, v);
|
||||
|
||||
if ( hvm_altp2m_supported() )
|
||||
|
||||
+57
-20
@@ -1,7 +1,12 @@
|
||||
/******************************************************************************
|
||||
* viridian.c
|
||||
*
|
||||
* An implementation of the Viridian hypercall interface.
|
||||
* An implementation of some Viridian enlightenments. See Microsoft's
|
||||
* Hypervisor Top Level Functional Specification (v4.0b) at:
|
||||
*
|
||||
* https://msdn.microsoft.com/en-us/virtualization/hyperv_on_windows/develop/tlfs
|
||||
*
|
||||
* for more information.
|
||||
*/
|
||||
|
||||
#include <xen/sched.h>
|
||||
@@ -163,7 +168,7 @@ static void dump_apic_assist(const struct vcpu *v)
|
||||
{
|
||||
const union viridian_apic_assist *aa;
|
||||
|
||||
aa = &v->arch.hvm_vcpu.viridian.apic_assist;
|
||||
aa = &v->arch.hvm_vcpu.viridian.apic_assist.msr;
|
||||
|
||||
printk(XENLOG_G_INFO "%pv: VIRIDIAN APIC_ASSIST: enabled: %x pfn: %lx\n",
|
||||
v, aa->fields.enabled, (unsigned long)aa->fields.pfn);
|
||||
@@ -217,9 +222,9 @@ static void enable_hypercall_page(struct domain *d)
|
||||
static void initialize_apic_assist(struct vcpu *v)
|
||||
{
|
||||
struct domain *d = v->domain;
|
||||
unsigned long gmfn = v->arch.hvm_vcpu.viridian.apic_assist.fields.pfn;
|
||||
unsigned long gmfn = v->arch.hvm_vcpu.viridian.apic_assist.msr.fields.pfn;
|
||||
struct page_info *page = get_page_from_gfn(d, gmfn, NULL, P2M_ALLOC);
|
||||
uint8_t *p;
|
||||
void *va;
|
||||
|
||||
/*
|
||||
* We don't yet make use of the APIC assist page but by setting
|
||||
@@ -227,25 +232,49 @@ static void initialize_apic_assist(struct vcpu *v)
|
||||
* bound to support the MSR. We therefore do just enough to keep windows
|
||||
* happy.
|
||||
*
|
||||
* See http://msdn.microsoft.com/en-us/library/ff538657%28VS.85%29.aspx for
|
||||
* details of how Windows uses the page.
|
||||
* See section 13.3.4.1 of the specification for details of this
|
||||
* enlightenment.
|
||||
*/
|
||||
|
||||
if ( !page || !get_page_type(page, PGT_writable_page) )
|
||||
if ( !page )
|
||||
goto fail;
|
||||
|
||||
if ( !get_page_type(page, PGT_writable_page) )
|
||||
{
|
||||
if ( page )
|
||||
put_page(page);
|
||||
gdprintk(XENLOG_WARNING, "Bad GMFN %lx (MFN %lx)\n", gmfn,
|
||||
page ? page_to_mfn(page) : INVALID_MFN);
|
||||
return;
|
||||
put_page(page);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
p = __map_domain_page(page);
|
||||
va = __map_domain_page_global(page);
|
||||
if ( !va )
|
||||
{
|
||||
put_page_and_type(page);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
*(u32 *)p = 0;
|
||||
*(uint32_t *)va = 0;
|
||||
|
||||
unmap_domain_page(p);
|
||||
v->arch.hvm_vcpu.viridian.apic_assist.va = va;
|
||||
return;
|
||||
|
||||
fail:
|
||||
gdprintk(XENLOG_WARNING, "Bad GMFN %lx (MFN %lx)\n", gmfn,
|
||||
page ? page_to_mfn(page) : INVALID_MFN);
|
||||
}
|
||||
|
||||
static void teardown_apic_assist(struct vcpu *v)
|
||||
{
|
||||
void *va = v->arch.hvm_vcpu.viridian.apic_assist.va;
|
||||
struct page_info *page;
|
||||
|
||||
if ( !va )
|
||||
return;
|
||||
|
||||
v->arch.hvm_vcpu.viridian.apic_assist.va = NULL;
|
||||
|
||||
page = mfn_to_page(domain_page_map_to_mfn(va));
|
||||
|
||||
unmap_domain_page_global(va);
|
||||
put_page_and_type(page);
|
||||
}
|
||||
|
||||
@@ -374,9 +403,10 @@ int wrmsr_viridian_regs(uint32_t idx, uint64_t val)
|
||||
|
||||
case VIRIDIAN_MSR_APIC_ASSIST:
|
||||
perfc_incr(mshv_wrmsr_apic_msr);
|
||||
v->arch.hvm_vcpu.viridian.apic_assist.raw = val;
|
||||
teardown_apic_assist(v); /* release any previous mapping */
|
||||
v->arch.hvm_vcpu.viridian.apic_assist.msr.raw = val;
|
||||
dump_apic_assist(v);
|
||||
if (v->arch.hvm_vcpu.viridian.apic_assist.fields.enabled)
|
||||
if ( v->arch.hvm_vcpu.viridian.apic_assist.msr.fields.enabled )
|
||||
initialize_apic_assist(v);
|
||||
break;
|
||||
|
||||
@@ -485,7 +515,7 @@ int rdmsr_viridian_regs(uint32_t idx, uint64_t *val)
|
||||
|
||||
case VIRIDIAN_MSR_APIC_ASSIST:
|
||||
perfc_incr(mshv_rdmsr_apic_msr);
|
||||
*val = v->arch.hvm_vcpu.viridian.apic_assist.raw;
|
||||
*val = v->arch.hvm_vcpu.viridian.apic_assist.msr.raw;
|
||||
break;
|
||||
|
||||
case VIRIDIAN_MSR_REFERENCE_TSC:
|
||||
@@ -521,6 +551,11 @@ int rdmsr_viridian_regs(uint32_t idx, uint64_t *val)
|
||||
return 1;
|
||||
}
|
||||
|
||||
void viridian_vcpu_deinit(struct vcpu *v)
|
||||
{
|
||||
teardown_apic_assist(v);
|
||||
}
|
||||
|
||||
static DEFINE_PER_CPU(cpumask_t, ipi_cpumask);
|
||||
|
||||
int viridian_hypercall(struct cpu_user_regs *regs)
|
||||
@@ -721,7 +756,7 @@ static int viridian_save_vcpu_ctxt(struct domain *d, hvm_domain_context_t *h)
|
||||
for_each_vcpu( d, v ) {
|
||||
struct hvm_viridian_vcpu_context ctxt;
|
||||
|
||||
ctxt.apic_assist = v->arch.hvm_vcpu.viridian.apic_assist.raw;
|
||||
ctxt.apic_assist = v->arch.hvm_vcpu.viridian.apic_assist.msr.raw;
|
||||
|
||||
if ( hvm_save_entry(VIRIDIAN_VCPU, v->vcpu_id, h, &ctxt) != 0 )
|
||||
return 1;
|
||||
@@ -747,7 +782,9 @@ static int viridian_load_vcpu_ctxt(struct domain *d, hvm_domain_context_t *h)
|
||||
if ( hvm_load_entry(VIRIDIAN_VCPU, h, &ctxt) != 0 )
|
||||
return -EINVAL;
|
||||
|
||||
v->arch.hvm_vcpu.viridian.apic_assist.raw = ctxt.apic_assist;
|
||||
v->arch.hvm_vcpu.viridian.apic_assist.msr.raw = ctxt.apic_assist;
|
||||
if ( v->arch.hvm_vcpu.viridian.apic_assist.msr.fields.enabled )
|
||||
initialize_apic_assist(v);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,10 @@ union viridian_apic_assist
|
||||
|
||||
struct viridian_vcpu
|
||||
{
|
||||
union viridian_apic_assist apic_assist;
|
||||
struct {
|
||||
union viridian_apic_assist msr;
|
||||
void *va;
|
||||
} apic_assist;
|
||||
};
|
||||
|
||||
union viridian_guest_os_id
|
||||
@@ -117,6 +120,8 @@ viridian_hypercall(struct cpu_user_regs *regs);
|
||||
void viridian_time_ref_count_freeze(struct domain *d);
|
||||
void viridian_time_ref_count_thaw(struct domain *d);
|
||||
|
||||
void viridian_vcpu_deinit(struct vcpu *v);
|
||||
|
||||
#endif /* __ASM_X86_HVM_VIRIDIAN_H__ */
|
||||
|
||||
/*
|
||||
|
||||