static int set_mode(uint32 width, uint32 height) { out_reg(SVGA_REG_WIDTH, width); out_reg(SVGA_REG_HEIGHT, height); vcons.fb_offset = in_reg(SVGA_REG_FB_OFFSET); vcons.bytes_per_line = in_reg(SVGA_REG_BYTES_PER_LINE); vcons.red_mask = in_reg(SVGA_REG_RED_MASK); vcons.green_mask = in_reg(SVGA_REG_GREEN_MASK); vcons.blue_mask = in_reg(SVGA_REG_BLUE_MASK); out_reg(SVGA_REG_ENABLE, 1); vcons.scrn_width = width; vcons.scrn_height = height; return 0; }
static void test_ivshmem_server(bool msi) { IVState state1, state2, *s1, *s2; ServerThread thread; IvshmemServer server; int ret, vm1, vm2; int nvectors = 2; guint64 end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND; ret = ivshmem_server_init(&server, tmpserver, tmpshm, true, TMPSHMSIZE, nvectors, g_test_verbose()); g_assert_cmpint(ret, ==, 0); ret = ivshmem_server_start(&server); g_assert_cmpint(ret, ==, 0); thread.server = &server; ret = pipe(thread.pipe); g_assert_cmpint(ret, ==, 0); thread.thread = g_thread_new("ivshmem-server", server_thread, &thread); g_assert(thread.thread != NULL); setup_vm_with_server(&state1, nvectors, msi); s1 = &state1; setup_vm_with_server(&state2, nvectors, msi); s2 = &state2; /* check got different VM ids */ vm1 = in_reg(s1, IVPOSITION); vm2 = in_reg(s2, IVPOSITION); g_assert_cmpint(vm1, >=, 0); g_assert_cmpint(vm2, >=, 0); g_assert_cmpint(vm1, !=, vm2); /* check number of MSI-X vectors */ global_qtest = s1->qs->qts; if (msi) { ret = qpci_msix_table_size(s1->dev); g_assert_cmpuint(ret, ==, nvectors); } /* TODO test behavior before MSI-X is enabled */ /* ping vm2 -> vm1 on vector 0 */ if (msi) { ret = qpci_msix_pending(s1->dev, 0); g_assert_cmpuint(ret, ==, 0); } else {
static void writeFIFO(uint32 value) { uint32* vmwareFIFO = (uint32*)vcons.fifo_base; /* Need to sync? */ if ((vmwareFIFO[SVGA_FIFO_NEXT_CMD] + sizeof(uint32) == vmwareFIFO[SVGA_FIFO_STOP]) || (vmwareFIFO[SVGA_FIFO_NEXT_CMD] == vmwareFIFO[SVGA_FIFO_MAX] - sizeof(uint32) && vmwareFIFO[SVGA_FIFO_STOP] == vmwareFIFO[SVGA_FIFO_MIN])) { out_reg(SVGA_REG_SYNC, 1); while (in_reg(SVGA_REG_BUSY)) ; } vmwareFIFO[vmwareFIFO[SVGA_FIFO_NEXT_CMD] / sizeof(uint32)] = value; if(vmwareFIFO[SVGA_FIFO_NEXT_CMD] == vmwareFIFO[SVGA_FIFO_MAX] - sizeof(uint32)) { vmwareFIFO[SVGA_FIFO_NEXT_CMD] = vmwareFIFO[SVGA_FIFO_MIN]; } else { vmwareFIFO[SVGA_FIFO_NEXT_CMD] += sizeof(uint32); } // vmwareFIFO[SVGA_FIFO_NEXT_CMD] += sizeof(uint32); // if (vmwareFIFO[SVGA_FIFO_NEXT_CMD] == vmwareFIFO[SVGA_FIFO_MAX]) // { // vmwareFIFO[SVGA_FIFO_NEXT_CMD] = vmwareFIFO[SVGA_FIFO_MIN]; // } }
frame_t frame(tmp_label_t name, list_t formals) { frame_t p = checked_malloc(sizeof(*p)); list_t formal = formals, q = NULL; int i = 0; p->name = name; p->locals = NULL; p->local_count = 0; for (; formal; formal = formal->next, i++) { fr_access_t access; if (formal->b || i >= K) access = in_frame(i * FR_WORD_SIZE); else access = in_reg(temp()); if (q) { q->next = list(access, NULL); q = q->next; } else p->formals = q = list(access, NULL); } return p; }
static void test_ivshmem_single(void) { IVState state, *s; uint32_t data[1024]; int i; setup_vm(&state); s = &state; /* initial state of readable registers */ g_assert_cmpuint(in_reg(s, INTRMASK), ==, 0); g_assert_cmpuint(in_reg(s, INTRSTATUS), ==, 0); g_assert_cmpuint(in_reg(s, IVPOSITION), ==, 0); /* trigger interrupt via registers */ out_reg(s, INTRMASK, 0xffffffff); g_assert_cmpuint(in_reg(s, INTRMASK), ==, 0xffffffff); out_reg(s, INTRSTATUS, 1); /* check interrupt status */ g_assert_cmpuint(in_reg(s, INTRSTATUS), ==, 1); /* reading clears */ g_assert_cmpuint(in_reg(s, INTRSTATUS), ==, 0); /* TODO intercept actual interrupt (needs qtest work) */ /* invalid register access */ out_reg(s, IVPOSITION, 1); in_reg(s, DOORBELL); /* ring the (non-functional) doorbell */ out_reg(s, DOORBELL, 8 << 16); /* write shared memory */ for (i = 0; i < G_N_ELEMENTS(data); i++) { data[i] = i; } write_mem(s, 0, data, sizeof(data)); /* verify write */ for (i = 0; i < G_N_ELEMENTS(data); i++) { g_assert_cmpuint(((uint32_t *)tmpshmem)[i], ==, i); } /* read it back and verify read */ memset(data, 0, sizeof(data)); read_mem(s, 0, data, sizeof(data)); for (i = 0; i < G_N_ELEMENTS(data); i++) { g_assert_cmpuint(data[i], ==, i); } cleanup_vm(s); }
fr_access_t fr_alloc_local(frame_t fr, bool escape) { fr_access_t access; if (escape) { fr->local_count++; /* -2 for the the return address and frame pointer. */ access = in_frame(FR_WORD_SIZE * (-2 - fr->local_count)); } else access = in_reg(temp()); if (fr->locals) { list_t p = fr->locals; while (p->next) p = p->next; p->next = list(access, NULL); } else fr->locals = list(access, NULL); return access; }
void bios_create_smap() { rm_ctx ctx; e820map map; e820entry *ent, tmp; u32 base, size; int i; /* setup initial context */ btab->p_set_ctx(0, &ctx); /* get system memory map */ map.n_map = 0; base = bdat->bd_base; size = bdat->bd_size; do { ctx.eax = 0x0000E820; ctx.edx = 0x534D4150; ctx.ecx = sizeof(e820entry); ctx.es = rm_seg(&map.map[map.n_map]); ctx.di = rm_off(&map.map[map.n_map]); if ( (btab->p_bios_call(0x15, &ctx) == 0) || (ctx.eax != 0x534D4150) ) { break; } } while ( (++map.n_map < E820MAX) && (ctx.ebx != 0) ); /* append my real mode block to second region */ if ( (map.n_map >= 2) && (map.map[0].type == E820_RAM) && (map.map[1].type == E820_RESERVED) && (map.map[0].base == 0) && (map.map[1].base == map.map[0].size) && (base + size == map.map[0].size) ) { map.map[0].size = base; map.map[1].base = map.map[0].size; map.map[1].size += size; } /* build new memory map without my regions */ for (i = 0; i < map.n_map; i++) { ent = &map.map[i]; if ( (ent->type == E820_RAM) && (in_reg(base, ent->base, ent->size) != 0) ) { tmp.base = ent->base; tmp.size = base - ent->base; tmp.type = ent->type; add_smap(&tmp); tmp.base = base; tmp.size = size; tmp.type = E820_RESERVED; add_smap(&tmp); if (ent->base + ent->size > base + size) { tmp.base = base + size; tmp.size = ent->base + ent->size - tmp.base; tmp.type = ent->type; add_smap(&tmp); } } else { add_smap(ent); } } }
static int pe2mod(wchar_t *in, wchar_t *out) { IMAGE_DOS_HEADER *d_head; IMAGE_NT_HEADERS *n_head; IMAGE_SECTION_HEADER *t_sect; boot_mod *b_mod = NULL; HMODULE image = NULL; u32 *reloc = NULL; int resl = 1; u32 r_num, offs; HANDLE h_out; u32 i, found; u32 code_off; u32 bytes, n; u8 *s_data; u32 s_size; do { if ( (image = LoadLibraryEx(in, NULL, DONT_RESOLVE_DLL_REFERENCES)) == NULL ) { break; } d_head = pv(dSZ(image) & ~(PAGE_SIZE - 1)); n_head = addof(d_head, d_head->e_lfanew); t_sect = IMAGE_FIRST_SECTION(n_head); found = 0; /* find '.text' section */ for (i = 0; i < n_head->FileHeader.NumberOfSections; i++, t_sect++) { if (_stricmp(t_sect->Name, ".text") == 0) { found = 1; break; } } if (found == 0) { wprintf(L"Invalid PE image %s, section '.text' is not found\n", in); break; } if ( (reloc = calloc(1, n_head->OptionalHeader.SizeOfImage)) == NULL ) { break; } if ( (b_mod = calloc(1, n_head->OptionalHeader.SizeOfImage)) == NULL ) { break; } if (r_num = pe_save_relocs(d_head, reloc)) { /* save needed relocs */ for (i = 0, n = 0; i < r_num; i++) { if (in_reg(reloc[i], t_sect->VirtualAddress, t_sect->Misc.VirtualSize) != 0) { b_mod->relocs[n++] = reloc[i]; } } b_mod->n_rels = n; code_off = _align(sizeof(boot_mod) + n * sizeof(u32), 16); } else { code_off = _align(sizeof(boot_mod), 16); } s_data = addof(d_head, t_sect->VirtualAddress); s_size = t_sect->SizeOfRawData; /* find minimum section RAW size */ for (i = t_sect->SizeOfRawData - 1; i != 0; i--, s_size--) { if (s_data[i] != 0) break; } b_mod->mod_sign = 'DCBM'; b_mod->raw_size = s_size + code_off; b_mod->virt_size = t_sect->Misc.VirtualSize + code_off; b_mod->entry_rva = n_head->OptionalHeader.AddressOfEntryPoint - t_sect->VirtualAddress + code_off; memcpy(addof(b_mod, code_off), s_data, s_size); /* rebase image and fix relocs */ for (i = 0; i < b_mod->n_rels; i++) { offs = b_mod->relocs[i] - t_sect->VirtualAddress + code_off; p32(addof(b_mod, offs))[0] -= n_head->OptionalHeader.ImageBase + t_sect->VirtualAddress - code_off; b_mod->relocs[i] = offs; } h_out = CreateFile( out, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); if (h_out != INVALID_HANDLE_VALUE) { if (WriteFile(h_out, b_mod, b_mod->raw_size, &bytes, NULL) != 0) { wprintf(L"Boot module OK (Virtual size: %d, Raw size: %d, EP: %d)\n", b_mod->virt_size, b_mod->raw_size, b_mod->entry_rva); resl = 0; } CloseHandle(h_out); } else { wprintf(L"Can not write to %s", out); } } while (0); if (reloc != NULL) { free(reloc); } if (b_mod != NULL) { free(b_mod); } if (image != NULL) { FreeLibrary(image); } return resl; }
static int find_and_map(void) { int err; pci_module_hooks *pci; pci_info pinfo; aspace_id kai = vm_get_kernel_aspace_id(); int i; bool foundit; if(module_get(PCI_BUS_MODULE_NAME, 0, (void **)&pci) < 0) { dprintf("vmware: no pci bus found..\n"); err = ERR_NOT_FOUND; goto error0; } foundit = false; for(i = 0; pci->get_nth_pci_info(i, &pinfo) >= NO_ERROR; i++) { dprintf("vmware: looking at 0x%x:0x%x\n", pinfo.vendor_id, pinfo.device_id); if(pinfo.vendor_id == PCI_VENDOR_ID_VMWARE && (pinfo.device_id == PCI_DEVICE_ID_VMWARE_SVGA2 || pinfo.device_id == PCI_DEVICE_ID_VMWARE_SVGA)) { foundit = true; break; } } if(!foundit) { dprintf("vmware: didn't find device on pci bus\n"); err = ERR_NOT_FOUND; goto error0; } switch(pinfo.device_id) { case PCI_DEVICE_ID_VMWARE_SVGA: dprintf("vmware SVGA device detected at pci %d:%d:%d\n", pinfo.bus, pinfo.device, pinfo.function); vcons.index_port = SVGA_LEGACY_BASE_PORT + SVGA_INDEX_PORT * 4; vcons.value_port = SVGA_LEGACY_BASE_PORT + SVGA_VALUE_PORT * 4; break; case PCI_DEVICE_ID_VMWARE_SVGA2: dprintf("vmware SVGA2 device detected at pci %d:%d:%d\n", pinfo.bus, pinfo.device, pinfo.function); vcons.index_port = pinfo.u.h0.base_registers[0] + SVGA_INDEX_PORT; vcons.value_port = pinfo.u.h0.base_registers[0] + SVGA_VALUE_PORT; break; } vcons.fb_phys_base = pinfo.u.h0.base_registers[1]; vcons.fb_size = MIN(pinfo.u.h0.base_register_sizes[1], SVGA_FB_MAX_SIZE); vcons.fifo_phys_base = pinfo.u.h0.base_registers[2]; vcons.fifo_size = MIN(pinfo.u.h0.base_register_sizes[2], SVGA_MEM_SIZE); dprintf("vmware: index port 0x%x, value port 0x%x\n", vcons.index_port, vcons.value_port); dprintf("vmware: phys base 0x%x, size 0x%X\n", vcons.fb_phys_base, vcons.fb_size); dprintf("vmware: fifo phys base 0x%x, fifo size 0x%X\n", vcons.fifo_phys_base, vcons.fifo_size); vcons.fb_region = vm_map_physical_memory(kai, "vmw:fb", (void **)&vcons.fb_base, REGION_ADDR_ANY_ADDRESS, vcons.fb_size, LOCK_KERNEL | LOCK_RW, vcons.fb_phys_base); if (vcons.fb_region < 0) { err = vcons.fb_region; dprintf("Error mapping frame buffer: %x\n", err); goto error0; } vcons.fifo_region = vm_map_physical_memory(kai, "vmw:fifo", (void **)&vcons.fifo_base, REGION_ADDR_ANY_ADDRESS, vcons.fifo_size, LOCK_KERNEL | LOCK_RW, vcons.fifo_phys_base); if (vcons.fifo_region < 0) { err = vcons.fifo_region; dprintf("Error mapping vmw::fifo: %x\n", err); goto error1; } // XXX this makes the emulation unhappy (crashes vmware) // out_reg(SVGA_REG_ID, SVGA_ID_2); // vcons.svga_id = in_reg(SVGA_REG_ID); // dprintf("vmware: svga version %d\n", vcons.svga_id); vcons.bits_per_pixel = in_reg(SVGA_REG_BITS_PER_PIXEL); dprintf("vmware: bpp %d\n", vcons.bits_per_pixel); err = NO_ERROR; goto error0; // unmap vcons.fifo_region vm_delete_region(kai, vcons.fifo_region); error1: // unmap vcons.fb_region vm_delete_region(kai, vcons.fb_region); error0: return err; }
static void test_ivshmem_server(void) { IVState state1, state2, *s1, *s2; ServerThread thread; IvshmemServer server; int ret, vm1, vm2; int nvectors = 2; guint64 end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND; ret = ivshmem_server_init(&server, tmpserver, tmpshm, true, TMPSHMSIZE, nvectors, g_test_verbose()); g_assert_cmpint(ret, ==, 0); ret = ivshmem_server_start(&server); g_assert_cmpint(ret, ==, 0); thread.server = &server; ret = pipe(thread.pipe); g_assert_cmpint(ret, ==, 0); thread.thread = g_thread_new("ivshmem-server", server_thread, &thread); g_assert(thread.thread != NULL); setup_vm_with_server(&state1, nvectors); s1 = &state1; setup_vm_with_server(&state2, nvectors); s2 = &state2; /* check got different VM ids */ vm1 = in_reg(s1, IVPOSITION); vm2 = in_reg(s2, IVPOSITION); g_assert_cmpint(vm1, >=, 0); g_assert_cmpint(vm2, >=, 0); g_assert_cmpint(vm1, !=, vm2); /* check number of MSI-X vectors */ ret = qpci_msix_table_size(s1->dev); g_assert_cmpuint(ret, ==, nvectors); /* TODO test behavior before MSI-X is enabled */ /* ping vm2 -> vm1 on vector 0 */ ret = qpci_msix_pending(s1->dev, 0); g_assert_cmpuint(ret, ==, 0); out_reg(s2, DOORBELL, vm1 << 16); do { g_usleep(10000); ret = qpci_msix_pending(s1->dev, 0); } while (ret == 0 && g_get_monotonic_time() < end_time); g_assert_cmpuint(ret, !=, 0); /* ping vm1 -> vm2 on vector 1 */ ret = qpci_msix_pending(s2->dev, 1); g_assert_cmpuint(ret, ==, 0); out_reg(s1, DOORBELL, vm2 << 16 | 1); do { g_usleep(10000); ret = qpci_msix_pending(s2->dev, 1); } while (ret == 0 && g_get_monotonic_time() < end_time); g_assert_cmpuint(ret, !=, 0); cleanup_vm(s2); cleanup_vm(s1); if (qemu_write_full(thread.pipe[1], "q", 1) != 1) { g_error("qemu_write_full: %s", g_strerror(errno)); } g_thread_join(thread.thread); ivshmem_server_close(&server); close(thread.pipe[1]); close(thread.pipe[0]); }