File xen-pae-handle-64bit-addresses-correctly.patch of Package kernel

Date: Fri, 03 Nov 2006 17:34:15 -0500
From: Steven Rostedt <srostedt@redhat.com>
Subject: [PATCH RHEL5 ] -- Fix for >4G guest crashing on i386

This version also includes the fixing of the flags passed in to the 
gnttab_set_unmap_op to match the flags used for gnttab_set_map_op.  (see 
the blktapmain.c part of the patch).

The original code didn't pass in the GNTTAB_contains_pte flag to the 
unmap part of the code and this would have the code in the hypervisor 
just use the address directly. This is fine, unless the address is in 
high memory that is needed to be dereferenced with the pte. This can 
affect both the i386 and x86_64 kernels.

For the i386 PAE kernels with over 4G of RAM, this can cause the 
hypervisor to unmap the wrong page. Since the va (non-pte) arg is 
expected to be just an unsigned long size.  So the hypervisor can still 
truncate the address in this case.


New diffstat:

$ diffstat /tmp/linux-2.6-xen-gnttab-4G.patch
 drivers/xen/blktap/blktapmain.c |    6 ++++--
 include/xen/gnttab.h            |    4 ++--
 2 files changed, 6 insertions(+), 4 deletions(-)

$ diffstat /tmp/xen-gnttab-4G.patch
 arch/powerpc/mm.c                 |    4 ++--
 arch/x86/mm.c                     |   14 +++++++-------
 include/asm-powerpc/grant_table.h |    4 ++--
 include/asm-x86/grant_table.h     |    4 ++--
 4 files changed, 13 insertions(+), 13 deletions(-)

-- Steve


>[This version removes the changes to ia64]
>
>Steven Rostedt wrote:
>>Here's the fix for BZ 211633 **** BLOCKER BETA ****
>>
>>Please ACK
>>
>>
>>On i386 boxes with memory greater than 4G, guests would randomly 
>>crash.    This was found to be a bug in the use of blktap's 
>>gnttab_set_map_op and gnttab_set_unmap_op calls. Blktap would grab the 
>>pte and pass that into the gnttab_set_map_op, but that function only 
>>took a 32 bit (on i386) parameter. So the top 32 bits where truncated.
>>
>>Luckly, the actual kernel/HV ABI used a 64 bit variable to pass from 
>>kernel to HV. So it was only the function parameter that would 
>>truncate the bits.
>>
>>But that was not all.  On the Xen HV side, after grabbing the 64 bit 
>>address, it would then pass it to a function that took a 32 bit 
>>parameter.  So it too would truncate the top 32 bits of the address.
>>
>>So to fix this bug, two patches are needed.  One is for the kernel 
>>side, and the other is for the xen side.
>>
>>-- Steve
>>
>>PS. Do I need to add a patch to add these to the kernel-2.6.spec file?
>>
>>PPS. This patch will need to be added to others (FC6) as well as 
>>upstream (doing that next).
>>
>

Index: xen/arch/powerpc/mm.c
===================================================================
--- xen.orig/arch/powerpc/mm.c
+++ xen/arch/powerpc/mm.c
@@ -43,14 +43,14 @@ unsigned long max_page;
 unsigned long total_pages;
 
 int create_grant_host_mapping(
-    unsigned long addr, unsigned long frame, unsigned int flags)
+    uint64_t addr, unsigned long frame, unsigned int flags)
 {
     panic("%s called\n", __func__);
     return 1;
 }
 
 int destroy_grant_host_mapping(
-    unsigned long addr, unsigned long frame, unsigned int flags)
+    uint64_t addr, unsigned long frame, unsigned int flags)
 {
     panic("%s called\n", __func__);
     return 1;
Index: xen/arch/x86/mm.c
===================================================================
--- xen.orig/arch/x86/mm.c
+++ xen/arch/x86/mm.c
@@ -2389,7 +2389,7 @@ int do_mmu_update(
 
 
 static int create_grant_pte_mapping(
-    unsigned long pte_addr, l1_pgentry_t nl1e, struct vcpu *v)
+    uint64_t pte_addr, l1_pgentry_t nl1e, struct vcpu *v)
 {
     int rc = GNTST_okay;
     void *va;
@@ -2413,7 +2413,7 @@ static int create_grant_pte_mapping(
     }
     
     va = map_domain_page(mfn);
-    va = (void *)((unsigned long)va + (pte_addr & ~PAGE_MASK));
+    va = (void *)((unsigned long)va + ((unsigned long)pte_addr & ~PAGE_MASK));
     page = mfn_to_page(mfn);
 
     type = page->u.inuse.type_info & PGT_type_mask;
@@ -2445,7 +2445,7 @@ static int create_grant_pte_mapping(
 }
 
 static int destroy_grant_pte_mapping(
-    unsigned long addr, unsigned long frame, struct domain *d)
+    uint64_t addr, unsigned long frame, struct domain *d)
 {
     int rc = GNTST_okay;
     void *va;
@@ -2464,7 +2464,7 @@ static int destroy_grant_pte_mapping(
     }
     
     va = map_domain_page(mfn);
-    va = (void *)((unsigned long)va + (addr & ~PAGE_MASK));
+    va = (void *)((unsigned long)va + ((unsigned long)addr & ~PAGE_MASK));
     page = mfn_to_page(mfn);
 
     type = page->u.inuse.type_info & PGT_type_mask;
@@ -2485,8 +2485,9 @@ static int destroy_grant_pte_mapping(
     /* Check that the virtual address supplied is actually mapped to frame. */
     if ( unlikely((l1e_get_intpte(ol1e) >> PAGE_SHIFT) != frame) )
     {
-        MEM_LOG("PTE entry %lx for address %lx doesn't match frame %lx",
+        MEM_LOG("PTE entry %lx for address %llx doesn't match frame %lx",
-                (unsigned long)l1e_get_intpte(ol1e), addr, frame);
+                (unsigned long)l1e_get_intpte(ol1e),
+		 (unsigned long long) addr, frame);
         put_page_type(page);
         rc = GNTST_general_error;
         goto failed;
@@ -2585,7 +2585,7 @@ static int destroy_grant_va_mapping(
 }
 
 int create_grant_host_mapping(
-    unsigned long addr, unsigned long frame, unsigned int flags)
+    uint64_t addr, unsigned long frame, unsigned int flags)
 {
     l1_pgentry_t pte = l1e_from_pfn(frame, GRANT_PTE_FLAGS);
 
@@ -2600,7 +2600,7 @@ int create_grant_host_mapping(
 }
 
 int destroy_grant_host_mapping(
-    unsigned long addr, unsigned long frame, unsigned int flags)
+    uint64_t addr, unsigned long frame, unsigned int flags)
 {
     if ( flags & GNTMAP_contains_pte )
         return destroy_grant_pte_mapping(addr, frame, current->domain);
Index: xen/include/asm-powerpc/grant_table.h
===================================================================
--- xen.orig/include/asm-powerpc/grant_table.h
+++ xen/include/asm-powerpc/grant_table.h
@@ -30,9 +30,9 @@
  * must hold a reference to the page.
  */
 int create_grant_host_mapping(
-    unsigned long addr, unsigned long frame, unsigned int flags);
+    uint64_t addr, unsigned long frame, unsigned int flags);
 int destroy_grant_host_mapping(
-    unsigned long addr, unsigned long frame, unsigned int flags);
+    uint64_t addr, unsigned long frame, unsigned int flags);
 
 #define gnttab_create_shared_page(d, t, i)                               \
     do {                                                                 \
Index: xen/include/asm-x86/grant_table.h
===================================================================
--- xen.orig/include/asm-x86/grant_table.h
+++ xen/include/asm-x86/grant_table.h
@@ -14,9 +14,9 @@
  * must hold a reference to the page.
  */
 int create_grant_host_mapping(
-    unsigned long addr, unsigned long frame, unsigned int flags);
+    uint64_t addr, unsigned long frame, unsigned int flags);
 int destroy_grant_host_mapping(
-    unsigned long addr, unsigned long frame, unsigned int flags);
+    uint64_t addr, unsigned long frame, unsigned int flags);
 
 #define gnttab_create_shared_page(d, t, i)                               \
     do {                                                                 \

openSUSE Build Service is sponsored by