[COMMIT master] KVM: x86: ignore access permissions for hypercall patching

2010-03-21 Thread Avi Kivity
From: Marcelo Tosatti mtosa...@redhat.com

Ignore access permissions while patching hypercall instructions.
Otherwise KVM injects a page fault when trying to patch vmcall
on read-only text regions:

Freeing initrd memory: 8843k freed
Freeing unused kernel memory: 660k freed
Write protecting the kernel text: 4780k
Write protecting the kernel read-only data: 1912k
BUG: unable to handle kernel paging request at c01292e3
IP: [c01292e3] kvm_leave_lazy_mmu+0x43/0x70
*pde = 00910067 *pte = 00129161
Oops: 0003 [#1] SMP

CC: sta...@kernel.org
Reported-and-Tested-by: Stefan Bader stefan.ba...@canonical.com
Signed-off-by: Marcelo Tosatti mtosa...@redhat.com

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index bcf52d1..9d02cc7 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3226,12 +3226,17 @@ int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t 
gpa,
 static int emulator_write_emulated_onepage(unsigned long addr,
   const void *val,
   unsigned int bytes,
-  struct kvm_vcpu *vcpu)
+  struct kvm_vcpu *vcpu,
+  bool guest_initiated)
 {
gpa_t gpa;
u32 error_code;
 
-   gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, error_code);
+
+   if (guest_initiated)
+   gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, error_code);
+   else
+   gpa = kvm_mmu_gva_to_gpa_system(vcpu, addr, error_code);
 
if (gpa == UNMAPPED_GVA) {
kvm_inject_page_fault(vcpu, addr, error_code);
@@ -3262,24 +3267,35 @@ mmio:
return X86EMUL_CONTINUE;
 }
 
-int emulator_write_emulated(unsigned long addr,
+int __emulator_write_emulated(unsigned long addr,
   const void *val,
   unsigned int bytes,
-  struct kvm_vcpu *vcpu)
+  struct kvm_vcpu *vcpu,
+  bool guest_initiated)
 {
/* Crossing a page boundary? */
if (((addr + bytes - 1) ^ addr)  PAGE_MASK) {
int rc, now;
 
now = -addr  ~PAGE_MASK;
-   rc = emulator_write_emulated_onepage(addr, val, now, vcpu);
+   rc = emulator_write_emulated_onepage(addr, val, now, vcpu,
+guest_initiated);
if (rc != X86EMUL_CONTINUE)
return rc;
addr += now;
val += now;
bytes -= now;
}
-   return emulator_write_emulated_onepage(addr, val, bytes, vcpu);
+   return emulator_write_emulated_onepage(addr, val, bytes, vcpu,
+  guest_initiated);
+}
+
+int emulator_write_emulated(unsigned long addr,
+  const void *val,
+  unsigned int bytes,
+  struct kvm_vcpu *vcpu)
+{
+   return __emulator_write_emulated(addr, val, bytes, vcpu, true);
 }
 EXPORT_SYMBOL_GPL(emulator_write_emulated);
 
@@ -3970,7 +3986,7 @@ int kvm_fix_hypercall(struct kvm_vcpu *vcpu)
 
kvm_x86_ops-patch_hypercall(vcpu, instruction);
 
-   return emulator_write_emulated(rip, instruction, 3, vcpu);
+   return __emulator_write_emulated(rip, instruction, 3, vcpu, false);
 }
 
 static u64 mk_cr_64(u64 curr_cr, u32 new_val)
--
To unsubscribe from this list: send the line unsubscribe kvm-commits in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[COMMIT master] Revert KVM: x86: ignore access permissions for hypercall patching

2010-03-21 Thread Avi Kivity
From: Marcelo Tosatti mtosa...@redhat.com

Its safer to disable the only problematic user of hypercall patching,
pvmmu.

Signed-off-by: Marcelo Tosatti mtosa...@redhat.com

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 68e8c89..bb9a24a 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3243,17 +3243,12 @@ static int emulator_write_emulated_onepage(unsigned 
long addr,
   const void *val,
   unsigned int bytes,
   struct kvm_vcpu *vcpu,
-  bool guest_initiated,
   bool mmu_only)
 {
gpa_t gpa;
u32 error_code;
 
-
-   if (guest_initiated)
-   gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, error_code);
-   else
-   gpa = kvm_mmu_gva_to_gpa_system(vcpu, addr, error_code);
+   gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, error_code);
 
if (gpa == UNMAPPED_GVA) {
kvm_inject_page_fault(vcpu, addr, error_code);
@@ -3292,7 +3287,6 @@ int __emulator_write_emulated(unsigned long addr,
   const void *val,
   unsigned int bytes,
   struct kvm_vcpu *vcpu,
-  bool guest_initiated,
   bool mmu_only)
 {
/* Crossing a page boundary? */
@@ -3301,7 +3295,7 @@ int __emulator_write_emulated(unsigned long addr,
 
now = -addr  ~PAGE_MASK;
rc = emulator_write_emulated_onepage(addr, val, now, vcpu,
-guest_initiated, mmu_only);
+mmu_only);
if (rc != X86EMUL_CONTINUE)
return rc;
addr += now;
@@ -3309,7 +3303,7 @@ int __emulator_write_emulated(unsigned long addr,
bytes -= now;
}
return emulator_write_emulated_onepage(addr, val, bytes, vcpu,
-  guest_initiated, mmu_only);
+  mmu_only);
 }
 
 int emulator_write_emulated(unsigned long addr,
@@ -3317,7 +3311,7 @@ int emulator_write_emulated(unsigned long addr,
   unsigned int bytes,
   struct kvm_vcpu *vcpu)
 {
-   return __emulator_write_emulated(addr, val, bytes, vcpu, true, false);
+   return __emulator_write_emulated(addr, val, bytes, vcpu, false);
 }
 EXPORT_SYMBOL_GPL(emulator_write_emulated);
 
@@ -3381,7 +3375,7 @@ static int emulator_cmpxchg_emulated(unsigned long addr,
if (!exchanged)
return X86EMUL_CMPXCHG_FAILED;
 
-   return __emulator_write_emulated(addr, new, bytes, vcpu, true, true);
+   return __emulator_write_emulated(addr, new, bytes, vcpu, true);
 
 emul_write:
printk_once(KERN_WARNING kvm: emulating exchange as write\n);
@@ -4083,8 +4077,7 @@ int kvm_fix_hypercall(struct kvm_vcpu *vcpu)
 
kvm_x86_ops-patch_hypercall(vcpu, instruction);
 
-   return __emulator_write_emulated(rip, instruction, 3, vcpu,
-false, false);
+   return __emulator_write_emulated(rip, instruction, 3, vcpu, false);
 }
 
 void realmode_lgdt(struct kvm_vcpu *vcpu, u16 limit, unsigned long base)
--
To unsubscribe from this list: send the line unsubscribe kvm-commits in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


KVM: x86: ignore access permissions for hypercall patching

2010-03-11 Thread Marcelo Tosatti

Ignore access permissions while patching hypercall instructions. 
Otherwise KVM injects a page fault when trying to patch vmcall 
on read-only text regions:

Freeing initrd memory: 8843k freed
Freeing unused kernel memory: 660k freed
Write protecting the kernel text: 4780k
Write protecting the kernel read-only data: 1912k
BUG: unable to handle kernel paging request at c01292e3
IP: [c01292e3] kvm_leave_lazy_mmu+0x43/0x70
*pde = 00910067 *pte = 00129161
Oops: 0003 [#1] SMP

CC: sta...@kernel.org
Reported-by: Stefan Bader stefan.ba...@canonical.com
Signed-off-by: Marcelo Tosatti mtosa...@redhat.com

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 703f637..bf5c83f 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3253,12 +3253,17 @@ int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t 
gpa,
 static int emulator_write_emulated_onepage(unsigned long addr,
   const void *val,
   unsigned int bytes,
-  struct kvm_vcpu *vcpu)
+  struct kvm_vcpu *vcpu,
+  bool guest_initiated)
 {
gpa_t gpa;
u32 error_code;
 
-   gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, error_code);
+
+   if (guest_initiated)
+   gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, error_code);
+   else
+   gpa = kvm_mmu_gva_to_gpa_system(vcpu, addr, error_code);
 
if (gpa == UNMAPPED_GVA) {
kvm_inject_page_fault(vcpu, addr, error_code);
@@ -3289,24 +3294,35 @@ mmio:
return X86EMUL_CONTINUE;
 }
 
-int emulator_write_emulated(unsigned long addr,
+int __emulator_write_emulated(unsigned long addr,
   const void *val,
   unsigned int bytes,
-  struct kvm_vcpu *vcpu)
+  struct kvm_vcpu *vcpu,
+  bool guest_initiated)
 {
/* Crossing a page boundary? */
if (((addr + bytes - 1) ^ addr)  PAGE_MASK) {
int rc, now;
 
now = -addr  ~PAGE_MASK;
-   rc = emulator_write_emulated_onepage(addr, val, now, vcpu);
+   rc = emulator_write_emulated_onepage(addr, val, now, vcpu,
+guest_initiated);
if (rc != X86EMUL_CONTINUE)
return rc;
addr += now;
val += now;
bytes -= now;
}
-   return emulator_write_emulated_onepage(addr, val, bytes, vcpu);
+   return emulator_write_emulated_onepage(addr, val, bytes, vcpu,
+  guest_initiated);
+}
+
+int emulator_write_emulated(unsigned long addr,
+  const void *val,
+  unsigned int bytes,
+  struct kvm_vcpu *vcpu)
+{
+   return __emulator_write_emulated(addr, val, bytes, vcpu, true);
 }
 EXPORT_SYMBOL_GPL(emulator_write_emulated);
 
@@ -3997,7 +4013,7 @@ int kvm_fix_hypercall(struct kvm_vcpu *vcpu)
 
kvm_x86_ops-patch_hypercall(vcpu, instruction);
 
-   return emulator_write_emulated(rip, instruction, 3, vcpu);
+   return __emulator_write_emulated(rip, instruction, 3, vcpu, false);
 }
 
 static u64 mk_cr_64(u64 curr_cr, u32 new_val)
--
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: KVM: x86: ignore access permissions for hypercall patching

2010-03-11 Thread Stefan Bader
With this patch applied on top, I was able to boot my guest on a AMD host 
system.

Marcelo Tosatti wrote:
 Ignore access permissions while patching hypercall instructions. 
 Otherwise KVM injects a page fault when trying to patch vmcall 
 on read-only text regions:
 
 Freeing initrd memory: 8843k freed
 Freeing unused kernel memory: 660k freed
 Write protecting the kernel text: 4780k
 Write protecting the kernel read-only data: 1912k
 BUG: unable to handle kernel paging request at c01292e3
 IP: [c01292e3] kvm_leave_lazy_mmu+0x43/0x70
 *pde = 00910067 *pte = 00129161
 Oops: 0003 [#1] SMP
 
 CC: sta...@kernel.org
 Reported-by: Stefan Bader stefan.ba...@canonical.com
 Signed-off-by: Marcelo Tosatti mtosa...@redhat.com
Tested-by: Stefan Bader stefan.ba...@canonical.com
 
 diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
 index 703f637..bf5c83f 100644
 --- a/arch/x86/kvm/x86.c
 +++ b/arch/x86/kvm/x86.c
 @@ -3253,12 +3253,17 @@ int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t 
 gpa,
  static int emulator_write_emulated_onepage(unsigned long addr,
  const void *val,
  unsigned int bytes,
 -struct kvm_vcpu *vcpu)
 +struct kvm_vcpu *vcpu,
 +bool guest_initiated)
  {
   gpa_t gpa;
   u32 error_code;
  
 - gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, error_code);
 +
 + if (guest_initiated)
 + gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, error_code);
 + else
 + gpa = kvm_mmu_gva_to_gpa_system(vcpu, addr, error_code);
  
   if (gpa == UNMAPPED_GVA) {
   kvm_inject_page_fault(vcpu, addr, error_code);
 @@ -3289,24 +3294,35 @@ mmio:
   return X86EMUL_CONTINUE;
  }
  
 -int emulator_write_emulated(unsigned long addr,
 +int __emulator_write_emulated(unsigned long addr,
  const void *val,
  unsigned int bytes,
 -struct kvm_vcpu *vcpu)
 +struct kvm_vcpu *vcpu,
 +bool guest_initiated)
  {
   /* Crossing a page boundary? */
   if (((addr + bytes - 1) ^ addr)  PAGE_MASK) {
   int rc, now;
  
   now = -addr  ~PAGE_MASK;
 - rc = emulator_write_emulated_onepage(addr, val, now, vcpu);
 + rc = emulator_write_emulated_onepage(addr, val, now, vcpu,
 +  guest_initiated);
   if (rc != X86EMUL_CONTINUE)
   return rc;
   addr += now;
   val += now;
   bytes -= now;
   }
 - return emulator_write_emulated_onepage(addr, val, bytes, vcpu);
 + return emulator_write_emulated_onepage(addr, val, bytes, vcpu,
 +guest_initiated);
 +}
 +
 +int emulator_write_emulated(unsigned long addr,
 +const void *val,
 +unsigned int bytes,
 +struct kvm_vcpu *vcpu)
 +{
 + return __emulator_write_emulated(addr, val, bytes, vcpu, true);
  }
  EXPORT_SYMBOL_GPL(emulator_write_emulated);
  
 @@ -3997,7 +4013,7 @@ int kvm_fix_hypercall(struct kvm_vcpu *vcpu)
  
   kvm_x86_ops-patch_hypercall(vcpu, instruction);
  
 - return emulator_write_emulated(rip, instruction, 3, vcpu);
 + return __emulator_write_emulated(rip, instruction, 3, vcpu, false);
  }
  
  static u64 mk_cr_64(u64 curr_cr, u32 new_val)

--
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: KVM: x86: ignore access permissions for hypercall patching

2010-03-11 Thread Gleb Natapov
On Thu, Mar 11, 2010 at 06:16:05PM -0300, Marcelo Tosatti wrote:
 
 Ignore access permissions while patching hypercall instructions. 
 Otherwise KVM injects a page fault when trying to patch vmcall 
 on read-only text regions:
 
 Freeing initrd memory: 8843k freed
 Freeing unused kernel memory: 660k freed
 Write protecting the kernel text: 4780k
 Write protecting the kernel read-only data: 1912k
 BUG: unable to handle kernel paging request at c01292e3
 IP: [c01292e3] kvm_leave_lazy_mmu+0x43/0x70
 *pde = 00910067 *pte = 00129161
 Oops: 0003 [#1] SMP
 
 CC: sta...@kernel.org
 Reported-by: Stefan Bader stefan.ba...@canonical.com
 Signed-off-by: Marcelo Tosatti mtosa...@redhat.com
 
My emulator patch series introduce kvm_write_guest_virt_system(). May be
used it here (only compile tested).


diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 3753c11..9833c25 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3157,14 +3157,18 @@ static int kvm_read_guest_virt_system(gva_t addr, void 
*val, unsigned int bytes,
return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, 0, error);
 }
 
-static int kvm_write_guest_virt(gva_t addr, void *val, unsigned int bytes,
-   struct kvm_vcpu *vcpu, u32 *error)
+static int kvm_write_guest_virt_helper(gva_t addr, void *val,
+  unsigned int bytes,
+  struct kvm_vcpu *vcpu, u32 access,
+  u32 *error)
 {
void *data = val;
int r = X86EMUL_CONTINUE;
 
+   access |= PFERR_WRITE_MASK;
+
while (bytes) {
-   gpa_t gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, error);
+   gpa_t gpa =  vcpu-arch.mmu.gva_to_gpa(vcpu, addr, access, 
error);
unsigned offset = addr  (PAGE_SIZE-1);
unsigned towrite = min(bytes, (unsigned)PAGE_SIZE - offset);
int ret;
@@ -3187,6 +3191,19 @@ out:
return r;
 }
 
+static int kvm_write_guest_virt(gva_t addr, void *val, unsigned int bytes,
+   struct kvm_vcpu *vcpu, u32 *error)
+{
+   u32 access = (kvm_x86_ops-get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
+   return kvm_write_guest_virt_helper(addr, val, bytes, vcpu, access, 
error);
+}
+
+static int kvm_write_guest_virt_system(gva_t addr, void *val,
+  unsigned int bytes,
+  struct kvm_vcpu *vcpu, u32 *error)
+{
+   return kvm_write_guest_virt_helper(addr, val, bytes, vcpu, 0, error);
+}
 
 static int emulator_read_emulated(unsigned long addr,
  void *val,
@@ -3997,7 +4014,7 @@ int kvm_fix_hypercall(struct kvm_vcpu *vcpu)
 
kvm_x86_ops-patch_hypercall(vcpu, instruction);
 
-   return emulator_write_emulated(rip, instruction, 3, vcpu);
+   return kvm_write_guest_virt_system(rip, instruction, 3, vcpu, NULL);
 }
 
 static u64 mk_cr_64(u64 curr_cr, u32 new_val)
--
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: KVM: x86: ignore access permissions for hypercall patching

2010-03-11 Thread Gleb Natapov
On Fri, Mar 12, 2010 at 07:56:00AM +0200, Gleb Natapov wrote:
 On Thu, Mar 11, 2010 at 06:16:05PM -0300, Marcelo Tosatti wrote:
  
  Ignore access permissions while patching hypercall instructions. 
  Otherwise KVM injects a page fault when trying to patch vmcall 
  on read-only text regions:
  
  Freeing initrd memory: 8843k freed
  Freeing unused kernel memory: 660k freed
  Write protecting the kernel text: 4780k
  Write protecting the kernel read-only data: 1912k
  BUG: unable to handle kernel paging request at c01292e3
  IP: [c01292e3] kvm_leave_lazy_mmu+0x43/0x70
  *pde = 00910067 *pte = 00129161
  Oops: 0003 [#1] SMP
  
  CC: sta...@kernel.org
  Reported-by: Stefan Bader stefan.ba...@canonical.com
  Signed-off-by: Marcelo Tosatti mtosa...@redhat.com
  
 My emulator patch series introduce kvm_write_guest_virt_system(). May be
 used it here (only compile tested).
 
Ignore that, it will not work.

--
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