[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] x86: Fix clip_to_limit().



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1257799420 0
# Node ID a84b90980632d97ad19998165d7b130be04b77af
# Parent  ad0419c835c806e470802065fe44a59fbd725cdf
x86: Fix clip_to_limit().

There are issues in updating the e820 map in the middle of a loop that
iterates over it. For example, after memmove(&e820.map[i],
&e820.map[i+1], ...), the original e820.map[i+1] become current
e820.map[i] but the next loop count is i+1, so the original
e820.map[i+1] will be skipped.

Fix and clarify the code by making a double loop.

Original bug discovery and fix by Xiao Guangrong <ericxiao.gr@xxxxxxxxx>

Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 xen/arch/x86/e820.c |   37 +++++++++++++++++++++++++------------
 1 files changed, 25 insertions(+), 12 deletions(-)

diff -r ad0419c835c8 -r a84b90980632 xen/arch/x86/e820.c
--- a/xen/arch/x86/e820.c       Mon Nov 09 20:06:48 2009 +0000
+++ b/xen/arch/x86/e820.c       Mon Nov 09 20:43:40 2009 +0000
@@ -367,19 +367,32 @@ static void __init clip_to_limit(uint64_
     char _warnmsg[160];
     uint64_t old_limit = 0;
 
-    for ( i = 0; i < e820.nr_map; i++ )
-    {
-        if ( (e820.map[i].type != E820_RAM) ||
-             ((e820.map[i].addr + e820.map[i].size) <= limit) )
+    for ( ; ; )
+    {
+        /* Find a RAM region needing clipping. */
+        for ( i = 0; i < e820.nr_map; i++ )
+            if ( (e820.map[i].type == E820_RAM) &&
+                 ((e820.map[i].addr + e820.map[i].size) > limit) )
+                break;
+
+        /* If none found, we are done. */
+        if ( i == e820.nr_map )
+            break;        
+
+        old_limit = max_t(
+            uint64_t, old_limit, e820.map[i].addr + e820.map[i].size);
+
+        /* We try to convert clipped RAM areas to E820_UNUSABLE. */
+        if ( e820_change_range_type(&e820, max(e820.map[i].addr, limit),
+                                    e820.map[i].addr + e820.map[i].size,
+                                    E820_RAM, E820_UNUSABLE) )
             continue;
-        old_limit = e820.map[i].addr + e820.map[i].size;
-        if ( e820_change_range_type(&e820, max(e820.map[i].addr, limit),
-                                    old_limit, E820_RAM, E820_UNUSABLE) )
-        {
-            /* Start again now e820 map must have changed. */
-            i = 0;
-        }
-        else if ( e820.map[i].addr < limit )
+
+        /*
+         * If the type change fails (e.g., not space in table) then we clip or 
+         * delete the region as appropriate.
+         */
+        if ( e820.map[i].addr < limit )
         {
             e820.map[i].size = limit - e820.map[i].addr;
         }

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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.