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