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