#define NVRAM_REG_AMI_BIG_MEMORY_HIGH 0x35
#define NVRAM_REG_AMI_BIG_MEMORY_LOW 0x34
-
#define NVRAM_REG_CSUM_HIGH 0x2e
#define NVRAM_REG_CSUM_LOW 0x2f
#define NVRAM_REG_IBM_CENTURY_BYTE 0x32
return 0;
}
-static int set_nvram_defaults(struct vm_device * dev) {
+
+
+static void set_memory_size(struct nvram_internal * nvram, addr_t bytes) {
+ // 1. Conventional Mem: 0-640k in K
+ // 2. Extended Mem: 0-16MB in K
+ // 3. Big Mem: 0-4G in 64K
+
+ if (bytes > 640 * 1024) {
+ nvram->mem_state[NVRAM_REG_BASE_MEMORY_HIGH] = 0x02;
+ nvram->mem_state[NVRAM_REG_BASE_MEMORY_LOW] = 0x80;
+ } else {
+ uint16_t memk = bytes * 1024;
+ nvram->mem_state[NVRAM_REG_BASE_MEMORY_HIGH] = (memk >> 8) & 0x00ff;
+ nvram->mem_state[NVRAM_REG_BASE_MEMORY_LOW] = memk & 0x00ff;
+
+ return;
+ }
+
+ if (bytes > (16 * 1024 * 1024)) {
+ // Set extended memory to 15 MB
+ nvram->mem_state[NVRAM_REG_EXT_MEMORY_HIGH] = 0x3C;
+ nvram->mem_state[NVRAM_REG_EXT_MEMORY_LOW] = 0x00;
+ nvram->mem_state[NVRAM_REG_EXT_MEMORY_2ND_HIGH]= 0x3C;
+ nvram->mem_state[NVRAM_REG_EXT_MEMORY_2ND_LOW]= 0x00;
+ } else {
+ uint16_t memk = bytes * 1024;
+ nvram->mem_state[NVRAM_REG_EXT_MEMORY_HIGH] = (memk >> 8) & 0x00ff;
+ nvram->mem_state[NVRAM_REG_EXT_MEMORY_LOW] = memk & 0x00ff;
+ nvram->mem_state[NVRAM_REG_EXT_MEMORY_2ND_HIGH]= (memk >> 8) & 0x00ff;
+ nvram->mem_state[NVRAM_REG_EXT_MEMORY_2ND_LOW]= memk & 0x00ff;
+
+ return;
+ }
+
+ {
+ // Set the extended memory beyond 16 MB in 64k chunks
+ uint16_t mem_chunks = bytes * (1024 / 64);
+ nvram->mem_state[NVRAM_REG_AMI_BIG_MEMORY_HIGH] = (mem_chunks >> 8) & 0x00ff;
+ nvram->mem_state[NVRAM_REG_AMI_BIG_MEMORY_LOW] = mem_chunks & 0x00ff;
+ }
+
+ return;
+}
+
+static int init_nvram_state(struct vm_device * dev) {
struct guest_info * info = dev->vm;
struct nvram_internal * nvram_state = (struct nvram_internal *)dev->private_data;
PrintError("TODO: Set the nvram memory register to reflect info->mem_size (%p)\n", (void *)(info->mem_size));
+ memset(nvram_state->mem_state, 0, NVRAM_REG_MAX);
+
+
//
// 2 1.44 MB floppy drives
//
// For new boot sequence style, do cd, hd, floppy
nvram_state->mem_state[NVRAM_REG_BOOTSEQ_NEW_FIRST] = 0x23;
nvram_state->mem_state[NVRAM_REG_BOOTSEQ_NEW_SECOND] = 0x10;
-
-
+
+
// Set equipment byte to note 2 floppies, vga display, keyboard,math,floppy
nvram_state->mem_state[NVRAM_REG_EQUIPMENT_BYTE] = 0x4f;
- //nvram_state->mem_state[NVRAM_REG_EQUIPMENT_BYTE] = 0xf;
-
- // Set conventional memory to 640K
- nvram_state->mem_state[NVRAM_REG_BASE_MEMORY_HIGH] = 0x02;
- nvram_state->mem_state[NVRAM_REG_BASE_MEMORY_LOW] = 0x80;
-
- // Set extended memory to 15 MB
- nvram_state->mem_state[NVRAM_REG_EXT_MEMORY_HIGH] = 0x3C;
- nvram_state->mem_state[NVRAM_REG_EXT_MEMORY_LOW] = 0x00;
- nvram_state->mem_state[NVRAM_REG_EXT_MEMORY_2ND_HIGH]= 0x3C;
- nvram_state->mem_state[NVRAM_REG_EXT_MEMORY_2ND_LOW]= 0x00;
-
- // Set the extended memory beyond 16 MB to 128-16 MB
- nvram_state->mem_state[NVRAM_REG_AMI_BIG_MEMORY_HIGH] = 0x7;
- nvram_state->mem_state[NVRAM_REG_AMI_BIG_MEMORY_LOW] = 0x00;
-
- //nvram_state->mem_state[NVRAM_REG_AMI_BIG_MEMORY_HIGH]= 0x00;
- //nvram_state->mem_state[NVRAM_REG_AMI_BIG_MEMORY_LOW]= 0x00;
-
+ // nvram_state->mem_state[NVRAM_REG_EQUIPMENT_BYTE] = 0xf;
+
// This is the harddisk type.... Set accordingly...
nvram_state->mem_state[NVRAM_IBM_HD_DATA] = 0x20;
nvram_state->us = 0;
nvram_state->pus = 0;
+ set_memory_size(nvram_state, dev->vm->mem_size);
+
+ nvram_state->dev_state = NVRAM_READY;
+ nvram_state->thereg = 0;
+
return 0;
}
+
+
static int nvram_reset_device(struct vm_device * dev) {
- struct nvram_internal * data = (struct nvram_internal *) dev->private_data;
-
- PrintDebug("nvram: reset device\n");
-
- data->dev_state = NVRAM_READY;
- data->thereg = 0;
-
+
return 0;
}
static int nvram_init_device(struct vm_device * dev) {
-
- struct nvram_internal * data = (struct nvram_internal *)dev->private_data;
-
PrintDebug("nvram: init_device\n");
- memset(data->mem_state, 0, NVRAM_REG_MAX);
-
- // Would read state here
- set_nvram_defaults(dev);
-
-
-
- nvram_reset_device(dev);
+ init_nvram_state(dev);
// hook ports
v3_dev_hook_io(dev, NVRAM_REG_PORT, NULL, &nvram_write_reg_port);
#define USE_GENERIC 1
-#define ROMBIOS_START 0x000f0000
-#define VGABIOS_START 0x000c0000
info->cpu_mode = REAL;
info->mem_mode = PHYSICAL_MEM;
- // Amount of ram the Guest will have
- info->mem_size = config_ptr->mem_size;
+ // Amount of ram the Guest will have, rounded to a 4K page boundary
+ info->mem_size = config_ptr->mem_size & ~(addr_t)0xfff;
// Configure the memory map for the guest
- setup_memory_map(info, config_ptr);
+ if (setup_memory_map(info, config_ptr) == -1) {
+ PrintError("Setting up guest memory map failed...\n");
+ return -1;
+ }
// Configure the devices for the guest
setup_devices(info, config_ptr);
* We need to make sure the memory map extends to cover it
*/
static int setup_memory_map(struct guest_info * info, struct v3_vm_config * config_ptr) {
+ addr_t mem_pages = info->mem_size >> 12;
- /* layout rombios */
- {
- uint_t num_pages = (config_ptr->rombios_size + PAGE_SIZE - 1) / PAGE_SIZE;
- void * guest_mem = V3_AllocPages(num_pages);
+ PrintDebug("Setting up memory map (memory size=%dMB)\n", (uint_t)(info->mem_size / (1024 * 1024)));
- PrintDebug("Layout Region %d bytes\n", config_ptr->rombios_size);
- memcpy(V3_VAddr(guest_mem), config_ptr->rombios, config_ptr->rombios_size);
-
- v3_add_shadow_mem(info, ROMBIOS_START, ROMBIOS_START + (num_pages * PAGE_SIZE) - 1, (addr_t)guest_mem);
-
- PrintDebug("Adding Shadow Region (0x%p-0x%p) -> 0x%p\n",
- (void *)ROMBIOS_START,
- (void *)ROMBIOS_START + (num_pages * PAGE_SIZE),
- (void *)guest_mem);
+ // Fill up to the 640K hole
+ if (mem_pages >= 160) {
+ if (v3_add_shadow_mem(info, 0x0, 0xa0000, (addr_t)V3_AllocPages(160)) == -1) {
+ PrintError("Could not map full conventional memory\n");
+ return -1;
+ }
+ } else {
+ // Less than 640k of memory
+ if (v3_add_shadow_mem(info, 0x0, (mem_pages * PAGE_SIZE), (addr_t)V3_AllocPages(mem_pages)) == -1) {
+ PrintError("Could not map subset of conventional memory\n");
+ return -1;
+ };
}
+#define VGABIOS_START 0x000c0000
+#define ROMBIOS_START 0x000f0000
+
+ // VGA frame buffer
+ if (1) {
+ if (v3_add_shadow_mem(info, 0xa0000, 0xc0000, 0xa0000) == -1) {
+ PrintError("Could not map VGA framebuffer\n");
+ return -1;
+ }
+ } else {
+ v3_hook_write_mem(info, 0xa0000, 0xc0000, 0xa0000, passthrough_mem_write, NULL);
+ }
+
+
/* layout vgabios */
{
uint_t num_pages = (config_ptr->vgabios_size + PAGE_SIZE - 1) / PAGE_SIZE;
void * guest_mem = V3_AllocPages(num_pages);
+ addr_t vgabios_end = VGABIOS_START + (num_pages * PAGE_SIZE);
PrintDebug("Layout Region %d bytes\n", config_ptr->vgabios_size);
memcpy(V3_VAddr(guest_mem), config_ptr->vgabios, config_ptr->vgabios_size);
- v3_add_shadow_mem(info, VGABIOS_START, VGABIOS_START + (num_pages * PAGE_SIZE) - 1, (addr_t)guest_mem);
-
+ if (v3_add_shadow_mem(info, VGABIOS_START, vgabios_end, (addr_t)guest_mem) == -1) {
+ PrintError("Could not map VGABIOS\n");
+ return -1;
+ }
+
PrintDebug("Adding Shadow Region (0x%p-0x%p) -> 0x%p\n",
(void *)VGABIOS_START,
- (void *)VGABIOS_START + (num_pages * PAGE_SIZE),
+ (void *)vgabios_end,
(void *)guest_mem);
- }
- //
- v3_add_shadow_mem(info, 0x0, 0x9ffff, (addr_t)V3_AllocPages(160));
-
- if (1) {
- v3_add_shadow_mem(info, 0xa0000, 0xbffff, 0xa0000);
- } else {
- v3_hook_write_mem(info, 0xa0000, 0xbffff, 0xa0000, passthrough_mem_write, NULL);
- }
-
- // TEMP
- //add_shadow_region_passthrough(info, 0xc0000, 0xc8000, 0xc0000);
-
- if (1) {
- v3_add_shadow_mem(info, 0xc7000, 0xc8000, (addr_t)V3_AllocPages(1));
- if (v3_add_shadow_mem(info, 0xc8000, 0xf0000, (addr_t)V3_AllocPages(40)) == -1) {
- PrintDebug("Error adding shadow region\n");
+
+ // Fill in the space between the VGABIOS and the ROMBIOS
+ // We'll just back this to shadow memory for now....
+ if (v3_add_shadow_mem(info, vgabios_end, ROMBIOS_START,
+ (addr_t)V3_AllocPages((ROMBIOS_START - vgabios_end) / PAGE_SIZE)) == -1) {
+ PrintError("Could not map VGABIOS->ROMBIOS gap\n");
+ return -1;
}
- } else {
- v3_add_shadow_mem(info, 0xc0000, 0xc8000, 0xc0000);
- v3_add_shadow_mem(info, 0xc8000, 0xf0000, 0xc8000);
}
-
-
- if (1) {
- v3_add_shadow_mem(info, 0x100000, 0x1000000, (addr_t)V3_AllocPages(4096));
- } else {
- /* MEMORY HOOK TEST */
- v3_add_shadow_mem(info, 0x100000, 0xa00000, (addr_t)V3_AllocPages(2304));
- v3_hook_write_mem(info, 0xa00000, 0xa01000, (addr_t)V3_AllocPages(1), passthrough_mem_write, NULL);
- v3_add_shadow_mem(info, 0xa01000, 0x1000000, (addr_t)V3_AllocPages(1791));
+
+ /* layout rombios */
+ {
+ uint_t num_pages = (config_ptr->rombios_size + PAGE_SIZE - 1) / PAGE_SIZE;
+ void * guest_mem = V3_AllocPages(num_pages);
+ addr_t rombios_end = ROMBIOS_START + (num_pages * PAGE_SIZE);
+
+ PrintDebug("Layout Region %d bytes\n", config_ptr->rombios_size);
+ memcpy(V3_VAddr(guest_mem), config_ptr->rombios, config_ptr->rombios_size);
+
+ if (v3_add_shadow_mem(info, ROMBIOS_START, rombios_end, (addr_t)guest_mem) == -1) {
+ PrintError("Could not map ROMBIOS\n");
+ return -1;
+ }
+
+ PrintDebug("Adding Shadow Region (0x%p-0x%p) -> 0x%p\n",
+ (void *)ROMBIOS_START,
+ (void *)rombios_end,
+ (void *)guest_mem);
+
+ if (rombios_end != 0x100000) {
+ PrintError("ROMBIOS must reach the 1MB barrier....\n");
+ return -1;
+ }
}
- v3_add_shadow_mem(info, 0x1000000, 0x8000000, (addr_t)V3_AllocPages(32768));
-
- // test - give linux accesss to PCI space - PAD
- //v3_add_shadow_mem(info, 0xc0000000,0xffffffff,0xc0000000);
-
+
+
+ // Fill in the extended memory map....
+ {
+ int num_ext_pages = mem_pages - (0x100000 / PAGE_SIZE);
+
+ if (num_ext_pages > 0) {
+ if (v3_add_shadow_mem(info, 0x100000, info->mem_size, (addr_t)V3_AllocPages(num_ext_pages)) == -1) {
+ PrintError("Could not allocate extended shadow memory\n");
+ return -1;
+ }
+ }
+ }
print_shadow_map(info);