[PATCHv2 3/4] Add HYPER-V apic access MSRs.

2010-01-17 Thread Gleb Natapov

Signed-off-by: Gleb Natapov g...@redhat.com
Signed-off-by: Vadim Rozenfeld vroze...@redhat.com
---
 arch/x86/include/asm/kvm_host.h |2 +
 arch/x86/kvm/lapic.c|   31 +
 arch/x86/kvm/lapic.h|8 +++
 arch/x86/kvm/x86.c  |   41 --
 include/linux/kvm.h |1 +
 5 files changed, 80 insertions(+), 3 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 67d19e4..a1f0b5d 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -363,6 +363,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..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;
+}
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);
+}
 #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,
 };
 
 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);
+   addr = kmap_atomic(page, KM_USER0);
+   clear_user_page(addr, vaddr, page);
+   kunmap_atomic(addr, KM_USER0);
+   break;
+   }
+   case HV_X64_MSR_EOI:
+   return kvm_hv_vapic_msr_write(vcpu, APIC_EOI, data);
+   case HV_X64_MSR_ICR:
+   return kvm_hv_vapic_msr_write(vcpu, APIC_ICR, data);
+   case HV_X64_MSR_TPR:
+   return kvm_hv_vapic_msr_write(vcpu, APIC_TASKPRI, data);
+   default:
+   pr_unimpl(vcpu, HYPER-V unimplemented wrmsr: 0x%x 
+ data 0x%llx\n, msr, data);
+   return 1;
+   }
 
-   return 1;
+   return 0;
 }
 
 int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
@@ -1326,6 +1354,12 @@ static int get_msr_hyperv(struct kvm_vcpu *vcpu, u32 
msr, u64 *pdata)
data = r;
break;
}
+   case HV_X64_MSR_EOI:
+   return kvm_hv_vapic_msr_read(vcpu, APIC_EOI, pdata);
+   case HV_X64_MSR_ICR:
+   return kvm_hv_vapic_msr_read(vcpu, APIC_ICR, 

Re: [PATCHv2 3/4] Add HYPER-V apic access MSRs.

2010-01-17 Thread Avi Kivity

On 01/17/2010 11:03 AM, Gleb Natapov wrote:


Signed-off-by: Gleb Natapovg...@redhat.com
Signed-off-by: Vadim Rozenfeldvroze...@redhat.com
   


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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCHv2 3/4] Add HYPER-V apic access MSRs.

2010-01-17 Thread Christoph Hellwig
On Sun, Jan 17, 2010 at 02:20:32PM +0200, Avi Kivity wrote:
 +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).

There's a clear_user_highpage helper to take care of it for you.

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCHv2 3/4] Add HYPER-V apic access MSRs.

2010-01-17 Thread Vadim Rozenfeld
On Sun, 2010-01-17 at 14:20 +0200, Avi Kivity wrote:
 On 01/17/2010 11:03 AM, Gleb Natapov wrote:
 
  Signed-off-by: Gleb Natapovg...@redhat.com
  Signed-off-by: Vadim Rozenfeldvroze...@redhat.com
 
 
 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?
At least, when it is disable, the EOI interception mechanism won't
work.   
 
 !! 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).
 


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCHv2 3/4] Add HYPER-V apic access MSRs.

2010-01-17 Thread Gleb Natapov
On Sun, Jan 17, 2010 at 02:20:32PM +0200, Avi Kivity wrote:
 On 01/17/2010 11:03 AM, Gleb Natapov wrote:
 
 Signed-off-by: Gleb Natapovg...@redhat.com
 Signed-off-by: Vadim Rozenfeldvroze...@redhat.com
 
 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).
 
This implements part of apic behaviour. It uses internal lapic functions
like apic_reg_read()/apic_reg_write(). Why move it from lapic.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.
 
The function is not used to check if vapic is enabled, so the name
should be changed.

   #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().
 
So there is no function to get struct page from user virtual address?

 +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

--
Gleb.
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCHv2 3/4] Add HYPER-V apic access MSRs.

2010-01-17 Thread Gleb Natapov
On Sun, Jan 17, 2010 at 07:32:32AM -0500, Christoph Hellwig wrote:
 On Sun, Jan 17, 2010 at 02:20:32PM +0200, Avi Kivity wrote:
  +  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).
 
 There's a clear_user_highpage helper to take care of it for you.
I copied code from the instead of using helper faction for
some unknown to me reason. Anyway if I can't get struct page from
user virtual address I can't use it. Actually I am not sure the page
should be zeroed at all. Spec only descries first dword of the page and
doesn't require zeroing the reset as far as I see.

--
Gleb.
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCHv2 3/4] Add HYPER-V apic access MSRs.

2010-01-17 Thread Christoph Hellwig
On Sun, Jan 17, 2010 at 02:41:42PM +0200, Gleb Natapov wrote:
 I copied code from the instead of using helper faction for
 some unknown to me reason. Anyway if I can't get struct page from
 user virtual address I can't use it. Actually I am not sure the page
 should be zeroed at all. Spec only descries first dword of the page and
 doesn't require zeroing the reset as far as I see.

There's a clear_user() function that just takes a user virtual address
and a size.

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCHv2 3/4] Add HYPER-V apic access MSRs.

2010-01-17 Thread Avi Kivity

On 01/17/2010 02:36 PM, Gleb Natapov wrote:

+

+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).

 

This implements part of apic behaviour. It uses internal lapic functions
like apic_reg_read()/apic_reg_write(). Why move it from lapic.c?
   


The new functions implement hyper-v behaviour.  Why scatter them all around?

Maybe apic_reg_{read,write} need to be exported.


  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().

 

So there is no function to get struct page from user virtual address?
   


get_user_pages_fast().


--
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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCHv2 3/4] Add HYPER-V apic access MSRs.

2010-01-17 Thread Gleb Natapov
On Sun, Jan 17, 2010 at 07:44:57AM -0500, Christoph Hellwig wrote:
 On Sun, Jan 17, 2010 at 02:41:42PM +0200, Gleb Natapov wrote:
  I copied code from the instead of using helper faction for
  some unknown to me reason. Anyway if I can't get struct page from
  user virtual address I can't use it. Actually I am not sure the page
  should be zeroed at all. Spec only descries first dword of the page and
  doesn't require zeroing the reset as far as I see.
 
 There's a clear_user() function that just takes a user virtual address
 and a size.
Precisely what I need. Thanks!

--
Gleb.
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCHv2 3/4] Add HYPER-V apic access MSRs.

2010-01-17 Thread Avi Kivity

On 01/17/2010 02:46 PM, Gleb Natapov wrote:

On Sun, Jan 17, 2010 at 07:44:57AM -0500, Christoph Hellwig wrote:
   

On Sun, Jan 17, 2010 at 02:41:42PM +0200, Gleb Natapov wrote:
 

I copied code from the instead of using helper faction for
some unknown to me reason. Anyway if I can't get struct page from
user virtual address I can't use it. Actually I am not sure the page
should be zeroed at all. Spec only descries first dword of the page and
doesn't require zeroing the reset as far as I see.
   

There's a clear_user() function that just takes a user virtual address
and a size.
 

Precisely what I need. Thanks!

   


But clear_user_page() is confusingly named.  I assume it deals with 
virtually tagged caches on archs that have them?


--
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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCHv2 3/4] Add HYPER-V apic access MSRs.

2010-01-17 Thread Gleb Natapov
On Sun, Jan 17, 2010 at 02:46:46PM +0200, Avi Kivity wrote:
 On 01/17/2010 02:36 PM, Gleb Natapov wrote:
 +
 +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).
 
 This implements part of apic behaviour. It uses internal lapic functions
 like apic_reg_read()/apic_reg_write(). Why move it from lapic.c?
 
 The new functions implement hyper-v behaviour.  Why scatter them all around?
 
Each hyper-v extension is pretty much independent one from another, so
why not group things by functionality instead. All apic related code in
lapic.c.

 Maybe apic_reg_{read,write} need to be exported.
 
This is really internal API. It doesn't even check if apic is created.

   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().
 
 So there is no function to get struct page from user virtual address?
 
 get_user_pages_fast().
 
Doh.

--
Gleb.
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCHv2 3/4] Add HYPER-V apic access MSRs.

2010-01-17 Thread Avi Kivity

On 01/17/2010 02:50 PM, Gleb Natapov wrote:

I prefer putting this in x86.c (maybe later split into hyperv.c).

 

This implements part of apic behaviour. It uses internal lapic functions
like apic_reg_read()/apic_reg_write(). Why move it from lapic.c?
   

The new functions implement hyper-v behaviour.  Why scatter them all around?

 

Each hyper-v extension is pretty much independent one from another, so
why not group things by functionality instead. All apic related code in
lapic.c.

   

Maybe apic_reg_{read,write} need to be exported.

 

This is really internal API. It doesn't even check if apic is created.
   


Okay.  We can rethink it later when the code grows some more.


--
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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html