On 01/17/2010 11:03 AM, Gleb Natapov wrote:
Signed-off-by: Gleb Natapov<gleb@xxxxxxxxxx> Signed-off-by: Vadim Rozenfeld<vrozenfe@xxxxxxxxxx>
Changelog entry.
struct kvm_mem_alias { diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index ba8c045..4b224f9 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -1246,3 +1246,34 @@ int kvm_x2apic_msr_read(struct kvm_vcpu *vcpu, u32 msr, u64 *data) return 0; } + +int kvm_hv_vapic_msr_write(struct kvm_vcpu *vcpu, u32 reg, u64 data) +{ + struct kvm_lapic *apic = vcpu->arch.apic; + + if (!irqchip_in_kernel(vcpu->kvm)) + return 1; + + /* if this is ICR write vector before command */ + if (reg == APIC_ICR) + apic_reg_write(apic, APIC_ICR2, (u32)(data>> 32)); + return apic_reg_write(apic, reg, (u32)data); +} + +int kvm_hv_vapic_msr_read(struct kvm_vcpu *vcpu, u32 reg, u64 *data) +{ + struct kvm_lapic *apic = vcpu->arch.apic; + u32 low, high = 0; + + if (!irqchip_in_kernel(vcpu->kvm)) + return 1; + + if (apic_reg_read(apic, reg, 4,&low)) + return 1; + if (reg == APIC_ICR) + apic_reg_read(apic, APIC_ICR2, 4,&high); + + *data = (((u64)high)<< 32) | low; + + return 0; +}
I prefer putting this in x86.c (maybe later split into hyperv.c).
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h index 40010b0..d081cb6 100644 --- a/arch/x86/kvm/lapic.h +++ b/arch/x86/kvm/lapic.h @@ -48,4 +48,12 @@ void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu); int kvm_x2apic_msr_write(struct kvm_vcpu *vcpu, u32 msr, u64 data); int kvm_x2apic_msr_read(struct kvm_vcpu *vcpu, u32 msr, u64 *data); + +int kvm_hv_vapic_msr_write(struct kvm_vcpu *vcpu, u32 msr, u64 data); +int kvm_hv_vapic_msr_read(struct kvm_vcpu *vcpu, u32 msr, u64 *data); + +static inline bool kvm_hv_vapic_enabled(struct kvm_vcpu *vcpu) +{ + return !!(vcpu->arch.hv_vapic& HV_X64_MSR_APIC_ASSIST_PAGE_ENABLE); +}
Are you sure that vapic enabled is equivalent to apic assist page enable? !! not required.
#endif diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index db0b2b1..2fe555c 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -632,6 +632,7 @@ static u32 msrs_to_save[] = { #endif MSR_IA32_TSC, MSR_IA32_PERF_STATUS, MSR_IA32_CR_PAT, MSR_VM_HSAVE_PA, HV_X64_MSR_GUEST_OS_ID, HV_X64_MSR_HYPERCALL, + HV_X64_MSR_APIC_ASSIST_PAGE, };
Will be dropped by msr validation.
static unsigned num_msrs_to_save; @@ -1063,10 +1064,37 @@ static int set_msr_hyperv_pw(struct kvm_vcpu *vcpu, u32 msr, u64 data) static int set_msr_hyperv(struct kvm_vcpu *vcpu, u32 msr, u64 data) { - pr_unimpl(vcpu, "HYPER-V unimplemented wrmsr: 0x%x data 0x%llx\n", - msr, data); + switch (msr) { + case HV_X64_MSR_APIC_ASSIST_PAGE: { + unsigned long vaddr; + void *addr; + struct page *page; + vcpu->arch.hv_vapic = data; + if (!kvm_hv_vapic_enabled(vcpu)) + break; + vaddr = gfn_to_hva(vcpu->kvm, data>> + HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT); + if (kvm_is_error_hva(vaddr)) + return 1; + page = virt_to_page(vaddr);
virt_to_page() takes a kernel address, not a user address. This is get_user_pages(). But I think the whole thing is done better with put_user().
+ addr = kmap_atomic(page, KM_USER0); + clear_user_page(addr, vaddr, page); + kunmap_atomic(addr, KM_USER0);
Surprising that clear_user_page needs kmap_atomic() (but true). -- error compiling committee.c: too many arguments to function -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html