Commit 94a6b54fd6d2d3321066cb4db7abeeb417af9365

Authored by pbrook
1 parent b0457b69

Implement dynamic guest ram allocation.

Signed-off-by: Paul Brook <paul@codesourcery.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@7088 c046a42c-6fe2-441c-8c8c-71466251a162
cpu-all.h
@@ -854,11 +854,10 @@ typedef unsigned long ram_addr_t; @@ -854,11 +854,10 @@ typedef unsigned long ram_addr_t;
854 854
855 /* memory API */ 855 /* memory API */
856 856
857 -extern ram_addr_t phys_ram_size;  
858 extern int phys_ram_fd; 857 extern int phys_ram_fd;
859 -extern uint8_t *phys_ram_base;  
860 extern uint8_t *phys_ram_dirty; 858 extern uint8_t *phys_ram_dirty;
861 extern ram_addr_t ram_size; 859 extern ram_addr_t ram_size;
  860 +extern ram_addr_t last_ram_offset;
862 861
863 /* physical memory access */ 862 /* physical memory access */
864 863
exec-all.h
@@ -370,6 +370,9 @@ void kqemu_record_dump(void); @@ -370,6 +370,9 @@ void kqemu_record_dump(void);
370 370
371 extern uint32_t kqemu_comm_base; 371 extern uint32_t kqemu_comm_base;
372 372
  373 +extern ram_addr_t kqemu_phys_ram_size;
  374 +extern uint8_t *kqemu_phys_ram_base;
  375 +
373 static inline int kqemu_is_ok(CPUState *env) 376 static inline int kqemu_is_ok(CPUState *env)
374 { 377 {
375 return(env->kqemu_enabled && 378 return(env->kqemu_enabled &&
@@ -107,12 +107,22 @@ static unsigned long code_gen_buffer_max_size; @@ -107,12 +107,22 @@ static unsigned long code_gen_buffer_max_size;
107 uint8_t *code_gen_ptr; 107 uint8_t *code_gen_ptr;
108 108
109 #if !defined(CONFIG_USER_ONLY) 109 #if !defined(CONFIG_USER_ONLY)
110 -ram_addr_t phys_ram_size;  
111 int phys_ram_fd; 110 int phys_ram_fd;
112 -uint8_t *phys_ram_base;  
113 uint8_t *phys_ram_dirty; 111 uint8_t *phys_ram_dirty;
114 static int in_migration; 112 static int in_migration;
115 -static ram_addr_t phys_ram_alloc_offset = 0; 113 +
  114 +typedef struct RAMBlock {
  115 + uint8_t *host;
  116 + ram_addr_t offset;
  117 + ram_addr_t length;
  118 + struct RAMBlock *next;
  119 +} RAMBlock;
  120 +
  121 +static RAMBlock *ram_blocks;
  122 +/* TODO: When we implement (and use) ram deallocation (e.g. for hotplug)
  123 + then we can no longet assume contiguous ram offsets, and external uses
  124 + of this variable will break. */
  125 +ram_addr_t last_ram_offset;
116 #endif 126 #endif
117 127
118 CPUState *first_cpu; 128 CPUState *first_cpu;
@@ -411,7 +421,7 @@ static void code_gen_alloc(unsigned long tb_size) @@ -411,7 +421,7 @@ static void code_gen_alloc(unsigned long tb_size)
411 code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE; 421 code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
412 #else 422 #else
413 /* XXX: needs ajustments */ 423 /* XXX: needs ajustments */
414 - code_gen_buffer_size = (unsigned long)(phys_ram_size / 4); 424 + code_gen_buffer_size = (unsigned long)(ram_size / 4);
415 #endif 425 #endif
416 } 426 }
417 if (code_gen_buffer_size < MIN_CODE_GEN_BUFFER_SIZE) 427 if (code_gen_buffer_size < MIN_CODE_GEN_BUFFER_SIZE)
@@ -2419,22 +2429,55 @@ void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size) @@ -2419,22 +2429,55 @@ void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size)
2419 kvm_uncoalesce_mmio_region(addr, size); 2429 kvm_uncoalesce_mmio_region(addr, size);
2420 } 2430 }
2421 2431
  2432 +#ifdef USE_KQEMU
2422 /* XXX: better than nothing */ 2433 /* XXX: better than nothing */
2423 -ram_addr_t qemu_ram_alloc(ram_addr_t size) 2434 +static ram_addr_t kqemu_ram_alloc(ram_addr_t size)
2424 { 2435 {
2425 ram_addr_t addr; 2436 ram_addr_t addr;
2426 - if ((phys_ram_alloc_offset + size) > phys_ram_size) { 2437 + if ((last_ram_offset + size) > kqemu_phys_ram_size) {
2427 fprintf(stderr, "Not enough memory (requested_size = %" PRIu64 ", max memory = %" PRIu64 ")\n", 2438 fprintf(stderr, "Not enough memory (requested_size = %" PRIu64 ", max memory = %" PRIu64 ")\n",
2428 - (uint64_t)size, (uint64_t)phys_ram_size); 2439 + (uint64_t)size, (uint64_t)kqemu_phys_ram_size);
2429 abort(); 2440 abort();
2430 } 2441 }
2431 - addr = phys_ram_alloc_offset;  
2432 - phys_ram_alloc_offset = TARGET_PAGE_ALIGN(phys_ram_alloc_offset + size); 2442 + addr = last_ram_offset;
  2443 + last_ram_offset = TARGET_PAGE_ALIGN(last_ram_offset + size);
2433 return addr; 2444 return addr;
2434 } 2445 }
  2446 +#endif
  2447 +
  2448 +ram_addr_t qemu_ram_alloc(ram_addr_t size)
  2449 +{
  2450 + RAMBlock *new_block;
  2451 +
  2452 +#ifdef USE_KQEMU
  2453 + if (kqemu_phys_ram_base) {
  2454 + return kqemu_ram_alloc(size);
  2455 + }
  2456 +#endif
  2457 +
  2458 + size = TARGET_PAGE_ALIGN(size);
  2459 + new_block = qemu_malloc(sizeof(*new_block));
  2460 +
  2461 + new_block->host = qemu_vmalloc(size);
  2462 + new_block->offset = last_ram_offset;
  2463 + new_block->length = size;
  2464 +
  2465 + new_block->next = ram_blocks;
  2466 + ram_blocks = new_block;
  2467 +
  2468 + phys_ram_dirty = qemu_realloc(phys_ram_dirty,
  2469 + (last_ram_offset + size) >> TARGET_PAGE_BITS);
  2470 + memset(phys_ram_dirty + (last_ram_offset >> TARGET_PAGE_BITS),
  2471 + 0xff, size >> TARGET_PAGE_BITS);
  2472 +
  2473 + last_ram_offset += size;
  2474 +
  2475 + return new_block->offset;
  2476 +}
2435 2477
2436 void qemu_ram_free(ram_addr_t addr) 2478 void qemu_ram_free(ram_addr_t addr)
2437 { 2479 {
  2480 + /* TODO: implement this. */
2438 } 2481 }
2439 2482
2440 /* Return a host pointer to ram allocated with qemu_ram_alloc. 2483 /* Return a host pointer to ram allocated with qemu_ram_alloc.
@@ -2447,14 +2490,69 @@ void qemu_ram_free(ram_addr_t addr) @@ -2447,14 +2490,69 @@ void qemu_ram_free(ram_addr_t addr)
2447 */ 2490 */
2448 void *qemu_get_ram_ptr(ram_addr_t addr) 2491 void *qemu_get_ram_ptr(ram_addr_t addr)
2449 { 2492 {
2450 - return phys_ram_base + addr; 2493 + RAMBlock *prev;
  2494 + RAMBlock **prevp;
  2495 + RAMBlock *block;
  2496 +
  2497 +#ifdef USE_KQEMU
  2498 + if (kqemu_phys_ram_base) {
  2499 + return kqemu_phys_ram_base + addr;
  2500 + }
  2501 +#endif
  2502 +
  2503 + prev = NULL;
  2504 + prevp = &ram_blocks;
  2505 + block = ram_blocks;
  2506 + while (block && (block->offset > addr
  2507 + || block->offset + block->length <= addr)) {
  2508 + if (prev)
  2509 + prevp = &prev->next;
  2510 + prev = block;
  2511 + block = block->next;
  2512 + }
  2513 + if (!block) {
  2514 + fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
  2515 + abort();
  2516 + }
  2517 + /* Move this entry to to start of the list. */
  2518 + if (prev) {
  2519 + prev->next = block->next;
  2520 + block->next = *prevp;
  2521 + *prevp = block;
  2522 + }
  2523 + return block->host + (addr - block->offset);
2451 } 2524 }
2452 2525
2453 /* Some of the softmmu routines need to translate from a host pointer 2526 /* Some of the softmmu routines need to translate from a host pointer
2454 (typically a TLB entry) back to a ram offset. */ 2527 (typically a TLB entry) back to a ram offset. */
2455 ram_addr_t qemu_ram_addr_from_host(void *ptr) 2528 ram_addr_t qemu_ram_addr_from_host(void *ptr)
2456 { 2529 {
2457 - return (uint8_t *)ptr - phys_ram_base; 2530 + RAMBlock *prev;
  2531 + RAMBlock **prevp;
  2532 + RAMBlock *block;
  2533 + uint8_t *host = ptr;
  2534 +
  2535 +#ifdef USE_KQEMU
  2536 + if (kqemu_phys_ram_base) {
  2537 + return host - kqemu_phys_ram_base;
  2538 + }
  2539 +#endif
  2540 +
  2541 + prev = NULL;
  2542 + prevp = &ram_blocks;
  2543 + block = ram_blocks;
  2544 + while (block && (block->host > host
  2545 + || block->host + block->length <= host)) {
  2546 + if (prev)
  2547 + prevp = &prev->next;
  2548 + prev = block;
  2549 + block = block->next;
  2550 + }
  2551 + if (!block) {
  2552 + fprintf(stderr, "Bad ram pointer %p\n", ptr);
  2553 + abort();
  2554 + }
  2555 + return block->offset + (host - block->host);
2458 } 2556 }
2459 2557
2460 static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr) 2558 static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
@@ -2895,9 +2993,13 @@ static void io_mem_init(void) @@ -2895,9 +2993,13 @@ static void io_mem_init(void)
2895 2993
2896 io_mem_watch = cpu_register_io_memory(0, watch_mem_read, 2994 io_mem_watch = cpu_register_io_memory(0, watch_mem_read,
2897 watch_mem_write, NULL); 2995 watch_mem_write, NULL);
2898 - /* alloc dirty bits array */  
2899 - phys_ram_dirty = qemu_vmalloc(phys_ram_size >> TARGET_PAGE_BITS);  
2900 - memset(phys_ram_dirty, 0xff, phys_ram_size >> TARGET_PAGE_BITS); 2996 +#ifdef USE_KQEMU
  2997 + if (kqemu_phys_ram_base) {
  2998 + /* alloc dirty bits array */
  2999 + phys_ram_dirty = qemu_vmalloc(kqemu_phys_ram_size >> TARGET_PAGE_BITS);
  3000 + memset(phys_ram_dirty, 0xff, kqemu_phys_ram_size >> TARGET_PAGE_BITS);
  3001 + }
  3002 +#endif
2901 } 3003 }
2902 3004
2903 /* mem_read and mem_write are arrays of functions containing the 3005 /* mem_read and mem_write are arrays of functions containing the
@@ -91,6 +91,8 @@ unsigned int nb_modified_ram_pages; @@ -91,6 +91,8 @@ unsigned int nb_modified_ram_pages;
91 uint8_t *modified_ram_pages_table; 91 uint8_t *modified_ram_pages_table;
92 int qpi_io_memory; 92 int qpi_io_memory;
93 uint32_t kqemu_comm_base; /* physical address of the QPI communication page */ 93 uint32_t kqemu_comm_base; /* physical address of the QPI communication page */
  94 +ram_addr_t kqemu_phys_ram_size;
  95 +uint8_t *kqemu_phys_ram_base;
94 96
95 #define cpuid(index, eax, ebx, ecx, edx) \ 97 #define cpuid(index, eax, ebx, ecx, edx) \
96 asm volatile ("cpuid" \ 98 asm volatile ("cpuid" \
@@ -214,13 +216,14 @@ int kqemu_init(CPUState *env) @@ -214,13 +216,14 @@ int kqemu_init(CPUState *env)
214 sizeof(uint64_t)); 216 sizeof(uint64_t));
215 if (!modified_ram_pages) 217 if (!modified_ram_pages)
216 goto fail; 218 goto fail;
217 - modified_ram_pages_table = qemu_mallocz(phys_ram_size >> TARGET_PAGE_BITS); 219 + modified_ram_pages_table =
  220 + qemu_mallocz(kqemu_phys_ram_size >> TARGET_PAGE_BITS);
218 if (!modified_ram_pages_table) 221 if (!modified_ram_pages_table)
219 goto fail; 222 goto fail;
220 223
221 memset(&kinit, 0, sizeof(kinit)); /* set the paddings to zero */ 224 memset(&kinit, 0, sizeof(kinit)); /* set the paddings to zero */
222 - kinit.ram_base = phys_ram_base;  
223 - kinit.ram_size = phys_ram_size; 225 + kinit.ram_base = kqemu_phys_ram_base;
  226 + kinit.ram_size = kqemu_phys_ram_size;
224 kinit.ram_dirty = phys_ram_dirty; 227 kinit.ram_dirty = phys_ram_dirty;
225 kinit.pages_to_flush = pages_to_flush; 228 kinit.pages_to_flush = pages_to_flush;
226 kinit.ram_pages_to_update = ram_pages_to_update; 229 kinit.ram_pages_to_update = ram_pages_to_update;
@@ -3094,9 +3094,9 @@ static int ram_load_v1(QEMUFile *f, void *opaque) @@ -3094,9 +3094,9 @@ static int ram_load_v1(QEMUFile *f, void *opaque)
3094 int ret; 3094 int ret;
3095 ram_addr_t i; 3095 ram_addr_t i;
3096 3096
3097 - if (qemu_get_be32(f) != phys_ram_size) 3097 + if (qemu_get_be32(f) != last_ram_offset)
3098 return -EINVAL; 3098 return -EINVAL;
3099 - for(i = 0; i < phys_ram_size; i+= TARGET_PAGE_SIZE) { 3099 + for(i = 0; i < last_ram_offset; i+= TARGET_PAGE_SIZE) {
3100 ret = ram_get_page(f, qemu_get_ram_ptr(i), TARGET_PAGE_SIZE); 3100 ret = ram_get_page(f, qemu_get_ram_ptr(i), TARGET_PAGE_SIZE);
3101 if (ret) 3101 if (ret)
3102 return ret; 3102 return ret;
@@ -3182,7 +3182,7 @@ static int ram_save_block(QEMUFile *f) @@ -3182,7 +3182,7 @@ static int ram_save_block(QEMUFile *f)
3182 ram_addr_t addr = 0; 3182 ram_addr_t addr = 0;
3183 int found = 0; 3183 int found = 0;
3184 3184
3185 - while (addr < phys_ram_size) { 3185 + while (addr < last_ram_offset) {
3186 if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) { 3186 if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) {
3187 uint8_t *p; 3187 uint8_t *p;
3188 3188
@@ -3204,7 +3204,7 @@ static int ram_save_block(QEMUFile *f) @@ -3204,7 +3204,7 @@ static int ram_save_block(QEMUFile *f)
3204 break; 3204 break;
3205 } 3205 }
3206 addr += TARGET_PAGE_SIZE; 3206 addr += TARGET_PAGE_SIZE;
3207 - current_addr = (saved_addr + addr) % phys_ram_size; 3207 + current_addr = (saved_addr + addr) % last_ram_offset;
3208 } 3208 }
3209 3209
3210 return found; 3210 return found;
@@ -3217,7 +3217,7 @@ static ram_addr_t ram_save_remaining(void) @@ -3217,7 +3217,7 @@ static ram_addr_t ram_save_remaining(void)
3217 ram_addr_t addr; 3217 ram_addr_t addr;
3218 ram_addr_t count = 0; 3218 ram_addr_t count = 0;
3219 3219
3220 - for (addr = 0; addr < phys_ram_size; addr += TARGET_PAGE_SIZE) { 3220 + for (addr = 0; addr < last_ram_offset; addr += TARGET_PAGE_SIZE) {
3221 if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) 3221 if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG))
3222 count++; 3222 count++;
3223 } 3223 }
@@ -3231,7 +3231,7 @@ static int ram_save_live(QEMUFile *f, int stage, void *opaque) @@ -3231,7 +3231,7 @@ static int ram_save_live(QEMUFile *f, int stage, void *opaque)
3231 3231
3232 if (stage == 1) { 3232 if (stage == 1) {
3233 /* Make sure all dirty bits are set */ 3233 /* Make sure all dirty bits are set */
3234 - for (addr = 0; addr < phys_ram_size; addr += TARGET_PAGE_SIZE) { 3234 + for (addr = 0; addr < last_ram_offset; addr += TARGET_PAGE_SIZE) {
3235 if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) 3235 if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG))
3236 cpu_physical_memory_set_dirty(addr); 3236 cpu_physical_memory_set_dirty(addr);
3237 } 3237 }
@@ -3239,7 +3239,7 @@ static int ram_save_live(QEMUFile *f, int stage, void *opaque) @@ -3239,7 +3239,7 @@ static int ram_save_live(QEMUFile *f, int stage, void *opaque)
3239 /* Enable dirty memory tracking */ 3239 /* Enable dirty memory tracking */
3240 cpu_physical_memory_set_dirty_tracking(1); 3240 cpu_physical_memory_set_dirty_tracking(1);
3241 3241
3242 - qemu_put_be64(f, phys_ram_size | RAM_SAVE_FLAG_MEM_SIZE); 3242 + qemu_put_be64(f, last_ram_offset | RAM_SAVE_FLAG_MEM_SIZE);
3243 } 3243 }
3244 3244
3245 while (!qemu_file_rate_limit(f)) { 3245 while (!qemu_file_rate_limit(f)) {
@@ -3272,7 +3272,7 @@ static int ram_load_dead(QEMUFile *f, void *opaque) @@ -3272,7 +3272,7 @@ static int ram_load_dead(QEMUFile *f, void *opaque)
3272 3272
3273 if (ram_decompress_open(s, f) < 0) 3273 if (ram_decompress_open(s, f) < 0)
3274 return -EINVAL; 3274 return -EINVAL;
3275 - for(i = 0; i < phys_ram_size; i+= BDRV_HASH_BLOCK_SIZE) { 3275 + for(i = 0; i < last_ram_offset; i+= BDRV_HASH_BLOCK_SIZE) {
3276 if (ram_decompress_buf(s, buf, 1) < 0) { 3276 if (ram_decompress_buf(s, buf, 1) < 0) {
3277 fprintf(stderr, "Error while reading ram block header\n"); 3277 fprintf(stderr, "Error while reading ram block header\n");
3278 goto error; 3278 goto error;
@@ -3303,7 +3303,7 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id) @@ -3303,7 +3303,7 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
3303 return ram_load_v1(f, opaque); 3303 return ram_load_v1(f, opaque);
3304 3304
3305 if (version_id == 2) { 3305 if (version_id == 2) {
3306 - if (qemu_get_be32(f) != phys_ram_size) 3306 + if (qemu_get_be32(f) != last_ram_offset)
3307 return -EINVAL; 3307 return -EINVAL;
3308 return ram_load_dead(f, opaque); 3308 return ram_load_dead(f, opaque);
3309 } 3309 }
@@ -3318,7 +3318,7 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id) @@ -3318,7 +3318,7 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
3318 addr &= TARGET_PAGE_MASK; 3318 addr &= TARGET_PAGE_MASK;
3319 3319
3320 if (flags & RAM_SAVE_FLAG_MEM_SIZE) { 3320 if (flags & RAM_SAVE_FLAG_MEM_SIZE) {
3321 - if (addr != phys_ram_size) 3321 + if (addr != last_ram_offset)
3322 return -EINVAL; 3322 return -EINVAL;
3323 } 3323 }
3324 3324
@@ -5132,31 +5132,21 @@ int main(int argc, char **argv, char **envp) @@ -5132,31 +5132,21 @@ int main(int argc, char **argv, char **envp)
5132 exit(1); 5132 exit(1);
5133 5133
5134 /* init the memory */ 5134 /* init the memory */
5135 - phys_ram_size = machine->ram_require & ~RAMSIZE_FIXED;  
5136 -  
5137 - if (machine->ram_require & RAMSIZE_FIXED) {  
5138 - if (ram_size > 0) {  
5139 - if (ram_size < phys_ram_size) {  
5140 - fprintf(stderr, "Machine `%s' requires %llu bytes of memory\n",  
5141 - machine->name, (unsigned long long) phys_ram_size);  
5142 - exit(-1);  
5143 - }  
5144 -  
5145 - phys_ram_size = ram_size;  
5146 - } else  
5147 - ram_size = phys_ram_size;  
5148 - } else {  
5149 - if (ram_size == 0)  
5150 - ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;  
5151 -  
5152 - phys_ram_size += ram_size;  
5153 - } 5135 + if (ram_size == 0)
  5136 + ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
5154 5137
5155 - phys_ram_base = qemu_vmalloc(phys_ram_size);  
5156 - if (!phys_ram_base) {  
5157 - fprintf(stderr, "Could not allocate physical memory\n");  
5158 - exit(1); 5138 +#ifdef USE_KQEMU
  5139 + /* FIXME: This is a nasty hack because kqemu can't cope with dynamic
  5140 + guest ram allocation. It needs to go away. */
  5141 + if (kqemu_allowed) {
  5142 + kqemu_phys_ram_size = ram_size + VGA_RAM_SIZE + 4 * 1024 * 1024;
  5143 + kqemu_phys_ram_base = qemu_vmalloc(kqemu_phys_ram_size);
  5144 + if (!kqemu_phys_ram_base) {
  5145 + fprintf(stderr, "Could not allocate physical memory\n");
  5146 + exit(1);
  5147 + }
5159 } 5148 }
  5149 +#endif
5160 5150
5161 /* init the dynamic translator */ 5151 /* init the dynamic translator */
5162 cpu_exec_init_all(tb_size * 1024 * 1024); 5152 cpu_exec_init_all(tb_size * 1024 * 1024);