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 854  
855 855 /* memory API */
856 856  
857   -extern ram_addr_t phys_ram_size;
858 857 extern int phys_ram_fd;
859   -extern uint8_t *phys_ram_base;
860 858 extern uint8_t *phys_ram_dirty;
861 859 extern ram_addr_t ram_size;
  860 +extern ram_addr_t last_ram_offset;
862 861  
863 862 /* physical memory access */
864 863  
... ...
exec-all.h
... ... @@ -370,6 +370,9 @@ void kqemu_record_dump(void);
370 370  
371 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 376 static inline int kqemu_is_ok(CPUState *env)
374 377 {
375 378 return(env->kqemu_enabled &&
... ...
... ... @@ -107,12 +107,22 @@ static unsigned long code_gen_buffer_max_size;
107 107 uint8_t *code_gen_ptr;
108 108  
109 109 #if !defined(CONFIG_USER_ONLY)
110   -ram_addr_t phys_ram_size;
111 110 int phys_ram_fd;
112   -uint8_t *phys_ram_base;
113 111 uint8_t *phys_ram_dirty;
114 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 126 #endif
117 127  
118 128 CPUState *first_cpu;
... ... @@ -411,7 +421,7 @@ static void code_gen_alloc(unsigned long tb_size)
411 421 code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
412 422 #else
413 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 425 #endif
416 426 }
417 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 2429 kvm_uncoalesce_mmio_region(addr, size);
2420 2430 }
2421 2431  
  2432 +#ifdef USE_KQEMU
2422 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 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 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 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 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 2478 void qemu_ram_free(ram_addr_t addr)
2437 2479 {
  2480 + /* TODO: implement this. */
2438 2481 }
2439 2482  
2440 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 2490 */
2448 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 2526 /* Some of the softmmu routines need to translate from a host pointer
2454 2527 (typically a TLB entry) back to a ram offset. */
2455 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 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 2993  
2896 2994 io_mem_watch = cpu_register_io_memory(0, watch_mem_read,
2897 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 3005 /* mem_read and mem_write are arrays of functions containing the
... ...
... ... @@ -91,6 +91,8 @@ unsigned int nb_modified_ram_pages;
91 91 uint8_t *modified_ram_pages_table;
92 92 int qpi_io_memory;
93 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 97 #define cpuid(index, eax, ebx, ecx, edx) \
96 98 asm volatile ("cpuid" \
... ... @@ -214,13 +216,14 @@ int kqemu_init(CPUState *env)
214 216 sizeof(uint64_t));
215 217 if (!modified_ram_pages)
216 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 221 if (!modified_ram_pages_table)
219 222 goto fail;
220 223  
221 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 227 kinit.ram_dirty = phys_ram_dirty;
225 228 kinit.pages_to_flush = pages_to_flush;
226 229 kinit.ram_pages_to_update = ram_pages_to_update;
... ...
... ... @@ -3094,9 +3094,9 @@ static int ram_load_v1(QEMUFile *f, void *opaque)
3094 3094 int ret;
3095 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 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 3100 ret = ram_get_page(f, qemu_get_ram_ptr(i), TARGET_PAGE_SIZE);
3101 3101 if (ret)
3102 3102 return ret;
... ... @@ -3182,7 +3182,7 @@ static int ram_save_block(QEMUFile *f)
3182 3182 ram_addr_t addr = 0;
3183 3183 int found = 0;
3184 3184  
3185   - while (addr < phys_ram_size) {
  3185 + while (addr < last_ram_offset) {
3186 3186 if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) {
3187 3187 uint8_t *p;
3188 3188  
... ... @@ -3204,7 +3204,7 @@ static int ram_save_block(QEMUFile *f)
3204 3204 break;
3205 3205 }
3206 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 3210 return found;
... ... @@ -3217,7 +3217,7 @@ static ram_addr_t ram_save_remaining(void)
3217 3217 ram_addr_t addr;
3218 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 3221 if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG))
3222 3222 count++;
3223 3223 }
... ... @@ -3231,7 +3231,7 @@ static int ram_save_live(QEMUFile *f, int stage, void *opaque)
3231 3231  
3232 3232 if (stage == 1) {
3233 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 3235 if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG))
3236 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 3239 /* Enable dirty memory tracking */
3240 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 3245 while (!qemu_file_rate_limit(f)) {
... ... @@ -3272,7 +3272,7 @@ static int ram_load_dead(QEMUFile *f, void *opaque)
3272 3272  
3273 3273 if (ram_decompress_open(s, f) < 0)
3274 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 3276 if (ram_decompress_buf(s, buf, 1) < 0) {
3277 3277 fprintf(stderr, "Error while reading ram block header\n");
3278 3278 goto error;
... ... @@ -3303,7 +3303,7 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
3303 3303 return ram_load_v1(f, opaque);
3304 3304  
3305 3305 if (version_id == 2) {
3306   - if (qemu_get_be32(f) != phys_ram_size)
  3306 + if (qemu_get_be32(f) != last_ram_offset)
3307 3307 return -EINVAL;
3308 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 3318 addr &= TARGET_PAGE_MASK;
3319 3319  
3320 3320 if (flags & RAM_SAVE_FLAG_MEM_SIZE) {
3321   - if (addr != phys_ram_size)
  3321 + if (addr != last_ram_offset)
3322 3322 return -EINVAL;
3323 3323 }
3324 3324  
... ... @@ -5132,31 +5132,21 @@ int main(int argc, char **argv, char **envp)
5132 5132 exit(1);
5133 5133  
5134 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 5151 /* init the dynamic translator */
5162 5152 cpu_exec_init_all(tb_size * 1024 * 1024);
... ...