All of lore.kernel.org
 help / color / mirror / Atom feed
* bitopts functions overflowing page boundarys
@ 2005-05-28  4:43 Scott Parish
  2005-05-28  9:01 ` Keir Fraser
  0 siblings, 1 reply; 5+ messages in thread
From: Scott Parish @ 2005-05-28  4:43 UTC (permalink / raw)
  To: xen-devel

[-- Attachment #1: Type: text/plain, Size: 961 bytes --]

u.inuse.type_info is at the end of the pfn_info structure, and is
u32 for both x86_32 and x86_64--in this location it can also be the
last 32 bits of a page.

several functions use bitopts.h functions to manipulate this member, and
on x86_64 these functions use u64 instructions, which will overflow the
page boundary, and possibly the end of memory as we see here:

   (XEN) &page->u.inuse.type_info = 0xffff828402fffffc
   (XEN) CPU:    0
   (XEN) EIP:    e010:[<ffff830000129089>]      

   <registers and stack ommitted>

   (XEN) Pagetable walk from ffff828403000000:
   (XEN)  L4 = 00000000016a5063
   (XEN)   L3 = 00000000016a6063
   (XEN)    L2 = 0000000000000000 

   ****************************************
   Panic on CPU0:
   CPU0 FATAL PAGE FAULT
   [error_code=0002]
   Faulting linear address: ffff828403000000
   ****************************************

the attached patch fixes this.

sRp

-- 
Scott Parish
Signed-off-by: srparish@us.ibm.com

[-- Attachment #2: 32bit.diff --]
[-- Type: text/plain, Size: 6607 bytes --]

diff -rN -u -p old-xen-64-4/xen/arch/x86/domain.c new-xen-64-4/xen/arch/x86/domain.c
--- old-xen-64-4/xen/arch/x86/domain.c	2005-05-25 18:41:08.000000000 +0000
+++ new-xen-64-4/xen/arch/x86/domain.c	2005-05-28 02:52:19.000000000 +0000
@@ -927,10 +927,10 @@ static void relinquish_memory(struct dom
             continue;
         }
 
-        if ( test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) )
+        if ( test_and_clear_bit32(_PGT_pinned, &page->u.inuse.type_info) )
             put_page_and_type(page);
 
-        if ( test_and_clear_bit(_PGC_allocated, &page->count_info) )
+        if ( test_and_clear_bit32(_PGC_allocated, &page->count_info) )
             put_page(page);
 
         /*
diff -rN -u -p old-xen-64-4/xen/arch/x86/domain_build.c new-xen-64-4/xen/arch/x86/domain_build.c
--- old-xen-64-4/xen/arch/x86/domain_build.c	2005-05-25 18:41:08.000000000 +0000
+++ new-xen-64-4/xen/arch/x86/domain_build.c	2005-05-28 02:41:41.000000000 +0000
@@ -309,7 +309,7 @@ int construct_dom0(struct domain *d,
             /* Get another ref to L2 page so that it can be pinned. */
             if ( !get_page_and_type(page, d, PGT_l2_page_table) )
                 BUG();
-            set_bit(_PGT_pinned, &page->u.inuse.type_info);
+            set_bit32(_PGT_pinned, &page->u.inuse.type_info);
         }
         else
         {
diff -rN -u -p old-xen-64-4/xen/arch/x86/mm.c new-xen-64-4/xen/arch/x86/mm.c
--- old-xen-64-4/xen/arch/x86/mm.c	2005-05-24 17:35:00.000000000 +0000
+++ new-xen-64-4/xen/arch/x86/mm.c	2005-05-28 02:45:37.000000000 +0000
@@ -1299,7 +1299,7 @@ int get_page_type(struct pfn_info *page,
         }
 
         /* Noone else is updating simultaneously. */
-        __set_bit(_PGT_validated, &page->u.inuse.type_info);
+        __set_bit32(_PGT_validated, &page->u.inuse.type_info);
     }
 
     return 1;
@@ -1522,8 +1522,8 @@ int do_mmuext_op(
                 break;
             }
             
-            if ( unlikely(test_and_set_bit(_PGT_pinned,
-                                           &page->u.inuse.type_info)) )
+            if ( unlikely(test_and_set_bit32(_PGT_pinned,
+                                             &page->u.inuse.type_info)) )
             {
                 MEM_LOG("Mfn %lx already pinned", op.mfn);
                 put_page_and_type(page);
@@ -1553,8 +1553,8 @@ int do_mmuext_op(
                 MEM_LOG("Mfn %lx bad domain (dom=%p)",
                         op.mfn, page_get_owner(page));
             }
-            else if ( likely(test_and_clear_bit(_PGT_pinned, 
-                                                &page->u.inuse.type_info)) )
+            else if ( likely(test_and_clear_bit32(_PGT_pinned, 
+                                                  &page->u.inuse.type_info)) )
             {
                 put_page_and_type(page);
                 put_page(page);
diff -rN -u -p old-xen-64-4/xen/arch/x86/shadow.c new-xen-64-4/xen/arch/x86/shadow.c
--- old-xen-64-4/xen/arch/x86/shadow.c	2005-05-25 18:41:08.000000000 +0000
+++ new-xen-64-4/xen/arch/x86/shadow.c	2005-05-28 02:52:53.000000000 +0000
@@ -81,7 +81,7 @@ shadow_promote(struct domain *d, unsigne
         FSH_LOG("%s: couldn't find/remove all write accesses, gpfn=%lx gmfn=%lx",
                 __func__, gpfn, gmfn);
 #if 1 || defined(LIVE_DANGEROUSLY)
-        set_bit(_PGC_page_table, &page->count_info);
+        set_bit32(_PGC_page_table, &page->count_info);
         return 1;
 #endif
         return 0;
@@ -103,14 +103,15 @@ shadow_promote(struct domain *d, unsigne
     //
     if ( unlikely(!get_page(page, d)) )
         BUG(); // XXX -- needs more thought for a graceful failure
-    if ( unlikely(test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info)) )
+    if ( unlikely(test_and_clear_bit32(_PGT_pinned,
+                                       &page->u.inuse.type_info)) )
     {
         pinned = 1;
         put_page_and_type(page);
     }
     if ( get_page_type(page, PGT_base_page_table) )
     {
-        set_bit(_PGC_page_table, &page->count_info);
+        set_bit32(_PGC_page_table, &page->count_info);
         put_page_type(page);
     }
     else
diff -rN -u -p old-xen-64-4/xen/common/dom_mem_ops.c new-xen-64-4/xen/common/dom_mem_ops.c
--- old-xen-64-4/xen/common/dom_mem_ops.c	2005-05-24 17:35:00.000000000 +0000
+++ new-xen-64-4/xen/common/dom_mem_ops.c	2005-05-28 02:53:10.000000000 +0000
@@ -106,10 +106,10 @@ free_dom_mem(struct domain *d,
                 return i;
             }
 
-            if ( test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) )
+            if ( test_and_clear_bit32(_PGT_pinned, &page->u.inuse.type_info) )
                 put_page_and_type(page);
             
-            if ( test_and_clear_bit(_PGC_allocated, &page->count_info) )
+            if ( test_and_clear_bit32(_PGC_allocated, &page->count_info) )
                 put_page(page);
 
             shadow_sync_and_drop_references(d, page);
diff -rN -u -p old-xen-64-4/xen/include/asm-x86/bitops.h new-xen-64-4/xen/include/asm-x86/bitops.h
--- old-xen-64-4/xen/include/asm-x86/bitops.h	2005-05-25 18:41:08.000000000 +0000
+++ new-xen-64-4/xen/include/asm-x86/bitops.h	2005-05-28 04:06:14.000000000 +0000
@@ -46,6 +46,14 @@ static __inline__ void set_bit(long nr, 
 		:"dIr" (nr));
 }
 
+static __inline__ void set_bit32(int nr, volatile void * addr)
+{
+	__asm__ __volatile__( LOCK_PREFIX
+		"btsl %1,%0"
+		:"=m" (ADDR)
+		:"dIr" (nr));
+}
+
 /**
  * __set_bit - Set a bit in memory
  * @nr: the bit to set
@@ -63,6 +71,14 @@ static __inline__ void __set_bit(long nr
 		:"dIr" (nr));
 }
 
+static __inline__ void __set_bit32(int nr, volatile void * addr)
+{
+	__asm__(
+		"btsl %1,%0"
+		:"=m" (ADDR)
+		:"dIr" (nr));
+}
+
 /**
  * clear_bit - Clears a bit in memory
  * @nr: Bit to clear
@@ -136,6 +152,17 @@ static __inline__ int test_and_set_bit(l
 	return oldbit;
 }
 
+static __inline__ int test_and_set_bit32(int nr, volatile void * addr)
+{
+	int oldbit;
+
+	__asm__ __volatile__( LOCK_PREFIX
+		"btsl %2,%1\n\tsbbl %0,%0"
+		:"=r" (oldbit),"=m" (ADDR)
+		:"dIr" (nr) : "memory");
+	return oldbit;
+}
+
 /**
  * __test_and_set_bit - Set a bit and return its old value
  * @nr: Bit to set
@@ -175,6 +202,17 @@ static __inline__ int test_and_clear_bit
 	return oldbit;
 }
 
+static __inline__ int test_and_clear_bit32(int nr, volatile void * addr)
+{
+	int oldbit;
+
+	__asm__ __volatile__( LOCK_PREFIX
+		"btrl %2,%1\n\tsbbl %0,%0"
+		:"=r" (oldbit),"=m" (ADDR)
+		:"dIr" (nr) : "memory");
+	return oldbit;
+}
+
 /**
  * __test_and_clear_bit - Clear a bit and return its old value
  * @nr: Bit to set


[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: bitopts functions overflowing page boundarys
  2005-05-28  4:43 bitopts functions overflowing page boundarys Scott Parish
@ 2005-05-28  9:01 ` Keir Fraser
  2005-05-28  9:04   ` Scott Parish
  0 siblings, 1 reply; 5+ messages in thread
From: Keir Fraser @ 2005-05-28  9:01 UTC (permalink / raw)
  To: Scott Parish; +Cc: xen-devel


On 28 May 2005, at 05:43, Scott Parish wrote:

> u.inuse.type_info is at the end of the pfn_info structure, and is
> u32 for both x86_32 and x86_64--in this location it can also be the
> last 32 bits of a page.
>
> several functions use bitopts.h functions to manipulate this member, 
> and
> on x86_64 these functions use u64 instructions, which will overflow the
> page boundary, and possibly the end of memory as we see here:

You really see this in practise? I'm very surprised. The memory map 
would have to be just big enough that the last pfn_info structure falls 
at the end of an aligned 2MB boundary. If you reduce max_page by 1, 
does the problem disappear?

  -- Keir

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: bitopts functions overflowing page boundarys
  2005-05-28  9:01 ` Keir Fraser
@ 2005-05-28  9:04   ` Scott Parish
  2005-05-28  9:51     ` Keir Fraser
  0 siblings, 1 reply; 5+ messages in thread
From: Scott Parish @ 2005-05-28  9:04 UTC (permalink / raw)
  To: Keir Fraser; +Cc: xen-devel

On Sat, May 28, 2005 at 10:01:27AM +0100, Keir Fraser wrote:

> 
> On 28 May 2005, at 05:43, Scott Parish wrote:
> 
> >u.inuse.type_info is at the end of the pfn_info structure, and is
> >u32 for both x86_32 and x86_64--in this location it can also be the
> >last 32 bits of a page.
> >
> >several functions use bitopts.h functions to manipulate this member, 
> >and
> >on x86_64 these functions use u64 instructions, which will overflow the
> >page boundary, and possibly the end of memory as we see here:
> 
> You really see this in practise? I'm very surprised. The memory map 
> would have to be just big enough that the last pfn_info structure falls 
> at the end of an aligned 2MB boundary. If you reduce max_page by 1, 
> does the problem disappear?

Here's the memory map for one of the boxes we're seeing this on:

(XEN) Physical RAM map:
(XEN)  0000000000000000 - 000000000009dc00 (usable)
(XEN)  000000000009dc00 - 00000000000a0000 (reserved)
(XEN)  00000000000d0000 - 0000000000100000 (reserved)
(XEN)  0000000000100000 - 00000000dff60000 (usable)
(XEN)  00000000dff60000 - 00000000dff72000 (ACPI data)
(XEN)  00000000dff72000 - 00000000dff80000 (ACPI NVS)
(XEN)  00000000dff80000 - 00000000e0000000 (reserved)
(XEN)  00000000fec00000 - 00000000fec00400 (reserved)
(XEN)  00000000fee00000 - 00000000fee01000 (reserved)
(XEN)  00000000fff80000 - 0000000100000000 (reserved)
(XEN)  0000000100000000 - 0000000180000000 (usable)

No problem when dom0_mem is less then 2048K; at exactly 2048 we hit
the next sized "order" which can't be fulfilled from the 0x100-0xdff60
range. All initial allocation for dom0 that i've seen that fall in the
"usable" above the hole have the problem i described.

Setting,

  max_page = init_e820(e820_raw, &e820_raw_nr) - 1;

seems to unravel a number of things. shall i preceed to figure out
what all, or is such still needed?

sRp

-- 
Scott Parish
Signed-off-by: srparish@us.ibm.com

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: bitopts functions overflowing page boundarys
  2005-05-28  9:51     ` Keir Fraser
@ 2005-05-28  9:25       ` Scott Parish
  0 siblings, 0 replies; 5+ messages in thread
From: Scott Parish @ 2005-05-28  9:25 UTC (permalink / raw)
  To: Keir Fraser; +Cc: xen-devel, Scott Parish

On Sat, May 28, 2005 at 10:51:06AM +0100, Keir Fraser wrote:

> 
> On 28 May 2005, at 10:04, Scott Parish wrote:
> 
> >o problem when dom0_mem is less then 2048K; at exactly 2048 we hit
> >the next sized "order" which can't be fulfilled from the 0x100-0xdff60
> >range. All initial allocation for dom0 that i've seen that fall in the
> >"usable" above the hole have the problem i described.
> >
> >Setting,
> >
> >  max_page = init_e820(e820_raw, &e820_raw_nr) - 1;
> >
> >seems to unravel a number of things. shall i preceed to figure out
> >what all, or is such still needed?
> 
> No, I guess this situation just isn't as unlikely as I though it would 
> be. :-)
> 
> I checked in a fixed up bitops.h that should fix the problem for you 
> without needing new bitop functions.

splendid!

sRp

-- 
Scott Parish
Signed-off-by: srparish@us.ibm.com

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: bitopts functions overflowing page boundarys
  2005-05-28  9:04   ` Scott Parish
@ 2005-05-28  9:51     ` Keir Fraser
  2005-05-28  9:25       ` Scott Parish
  0 siblings, 1 reply; 5+ messages in thread
From: Keir Fraser @ 2005-05-28  9:51 UTC (permalink / raw)
  To: Scott Parish; +Cc: xen-devel


On 28 May 2005, at 10:04, Scott Parish wrote:

> o problem when dom0_mem is less then 2048K; at exactly 2048 we hit
> the next sized "order" which can't be fulfilled from the 0x100-0xdff60
> range. All initial allocation for dom0 that i've seen that fall in the
> "usable" above the hole have the problem i described.
>
> Setting,
>
>   max_page = init_e820(e820_raw, &e820_raw_nr) - 1;
>
> seems to unravel a number of things. shall i preceed to figure out
> what all, or is such still needed?

No, I guess this situation just isn't as unlikely as I though it would 
be. :-)

I checked in a fixed up bitops.h that should fix the problem for you 
without needing new bitop functions.

  -- Keir

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2005-05-28  9:51 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-05-28  4:43 bitopts functions overflowing page boundarys Scott Parish
2005-05-28  9:01 ` Keir Fraser
2005-05-28  9:04   ` Scott Parish
2005-05-28  9:51     ` Keir Fraser
2005-05-28  9:25       ` Scott Parish

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.