Adds a new kernel arg, totalmem=, to specify the amount of physical memory (whereas the prveious available option had only been mem=, which limits the address of physical memory) 07/19/2010 patch written by Sarina Canelake (sarina.canelake@xxxxxxxxxx) diff -up xen/arch/x86/e820.c.orig xen/arch/x86/e820.c --- xen/arch/x86/e820.c.orig 2010-07-19 11:50:49.000000000 -0600 +++ xen/arch/x86/e820.c 2010-07-19 11:52:13.000000000 -0600 @@ -10,10 +10,14 @@ #include #include -/* opt_mem: Limit of physical RAM. Any RAM beyond this point is ignored. */ +/* opt_mem: Limit address of physical RAM. Any RAM beyond this point is ignored. */ static unsigned long long __initdata opt_mem; size_param("mem", opt_mem); +/* opt_totalmem: Limit amount of physical RAM; any RAM beyond this point is ignored. */ +static unsigned long long __initdata opt_totalmem; +size_param("totalmem", opt_totalmem); + /* opt_nomtrr_check: Don't clip ram to highest cacheable MTRR. */ static int __initdata e820_mtrr_clip = -1; boolean_param("e820-mtrr-clip", e820_mtrr_clip); @@ -416,6 +420,77 @@ static void __init clip_to_limit(uint64_ } } +static void __init clip_to_totalmem_limit(uint64_t totalmem_limit, char *warnmsg) +{ + int i; + char _warnmsg[160]; + uint64_t old_limit, test_limit, start_addr = 0; + + for ( ; ; ) + { + test_limit = 0; old_limit = 0; + /* Find a RAM region needing clipping. */ + for ( i=0; i < e820.nr_map; i++ ) + { + /* Try adding this region's memory; test if exceeds */ + test_limit = old_limit + e820.map[i].size; + if ( (e820.map[i].type == E820_RAM) && + (test_limit > totalmem_limit) ) + { + /* If exceeds we need to mark this region as unusable. Determine + the starting address of where to start the unusable segment. */ + if ( start_addr == 0 ) { + start_addr = e820.map[i].addr + (totalmem_limit - old_limit); + + } + else + start_addr = e820.map[i].addr; + + break; + } + + old_limit = test_limit; + } + + /* If none found, we are done. */ + if ( i == e820.nr_map ) + break; + + /* We try to convert clipped RAM areas to E820_UNUSABLE + (need to give an address to start from marking at unusable)*/ + if ( e820_change_range_type(&e820, start_addr, + e820.map[i].addr + e820.map[i].size, + E820_RAM, E820_UNUSABLE) ) + continue; + + /* + * If the type change fails (e.g., not space in table) then we clip or + * delete the region as appropriate. + */ + if ( old_limit < totalmem_limit ) + { + e820.map[i].size = totalmem_limit - old_limit; + } + else + { + memmove(&e820.map[i], &e820.map[i+1], + (e820.nr_map - i - 1) * sizeof(struct e820entry)); + e820.nr_map--; + } + } + + if ( old_limit ) + { + if ( warnmsg ) + { + snprintf(_warnmsg, sizeof(_warnmsg), warnmsg, (long)(totalmem_limit>>30)); + printk("WARNING: %s\n", _warnmsg); + } + printk("Truncating RAM from %lukB to %lukB\n", + (unsigned long)(old_limit >> 10), (unsigned long)(totalmem_limit >> 10)); + } +} + /* Conservative estimate of top-of-RAM by looking for MTRR WB regions. */ #define MSR_MTRRphysBase(reg) (0x200 + 2 * (reg)) #define MSR_MTRRphysMask(reg) (0x200 + 2 * (reg) + 1) @@ -513,6 +588,9 @@ static void __init machine_specific_memo if ( opt_mem ) clip_to_limit(opt_mem, NULL); + else if ( opt_totalmem ) + clip_to_totalmem_limit(opt_totalmem, NULL); + #ifdef __i386__ clip_to_limit((1ULL << 30) * MACHPHYS_MBYTES, "Only the first %lu GB of the physical memory map "