On 01/13/2010 03:59 PM, Gleb Natapov wrote:
Signed-off-by: Gleb Natapov<gleb@xxxxxxxxxx> Signed-off-by: Vadim Rozenfeld<vrozenfe@xxxxxxxxxx> --- arch/x86/include/asm/kvm_host.h | 2 + arch/x86/kvm/lapic.c | 53 +++++++++++++++++++++++++++++++++++++++ arch/x86/kvm/lapic.h | 8 ++++++ arch/x86/kvm/x86.c | 34 ++++++++++++++++++++++--- include/linux/kvm.h | 1 + 5 files changed, 94 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 7bfd468..4d82c52 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -362,6 +362,8 @@ struct kvm_vcpu_arch { /* used for guest single stepping over the given code position */ u16 singlestep_cs; unsigned long singlestep_rip; + /* fields used by HYPER-V emulation */ + u64 hv_vapic; }; struct kvm_mem_alias { diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index ba8c045..063963f 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -1246,3 +1246,56 @@ int kvm_x2apic_msr_read(struct kvm_vcpu *vcpu, u32 msr, u64 *data) return 0; } + +static u32 kvm_hv_vapic_msr2reg(u32 msr) +{ + u32 reg; + switch (msr) { + case HV_X64_MSR_EOI: + reg = APIC_EOI; + break; + case HV_X64_MSR_ICR: + reg = APIC_ICR; + break; + case HV_X64_MSR_TPR: + reg = APIC_TASKPRI; + break; + default: + reg = -1; + break; + } + + return reg; +} + +int kvm_hv_vapic_msr_write(struct kvm_vcpu *vcpu, u32 msr, u64 data) +{ + struct kvm_lapic *apic = vcpu->arch.apic; + u32 reg = kvm_hv_vapic_msr2reg(msr); + + 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 msr, u64 *data) +{ + struct kvm_lapic *apic = vcpu->arch.apic; + u32 reg = kvm_hv_vapic_msr2reg(msr), 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 think it's cleaner to put all this into the (set_msr and get_msr). You're just converting register numbers back and forth, while they are known at the call site.
#endif diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 6972b2b..e058898 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -629,7 +629,8 @@ static u32 msrs_to_save[] = { MSR_CSTAR, MSR_KERNEL_GS_BASE, MSR_SYSCALL_MASK, MSR_LSTAR, #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_GUEST_OS_ID, HV_X64_MSR_HYPERCALL, + HV_X64_MSR_APIC_ASSIST_PAGE };
, at the end.
static unsigned num_msrs_to_save; @@ -1061,10 +1062,30 @@ 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 addr; + vcpu->arch.hv_vapic = data; + if(!kvm_hv_vapic_enabled(vcpu)) + break;
Space after if.
+ addr = gfn_to_hva(vcpu->kvm, data>> + HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT); + if (kvm_is_error_hva(addr)) + return 1;
But the spec actually permits addresses outside RAM?
+ memset((void*)addr, 0, PAGE_SIZE);
clear_user_page()!
+ break; + } + case HV_X64_MSR_EOI: + case HV_X64_MSR_ICR: + case HV_X64_MSR_TPR: + return kvm_hv_vapic_msr_write(vcpu, msr, data);
Here, just call the apic function with the known apic register number. -- 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