u32 prepare_for_sleep (u32 firmware_waking_vector) { u8 *p; int wakeup_entry_len; /* Get the suspend-lock to make other processors stopping or staying in the guest mode. */ get_suspend_lock (); /* Now the VMM is executed by the current processor only. Call suspend functions. */ call_initfunc ("suspend"); /* Initialize variables used by wakeup functions */ wakeup_cpucount = 0; spinlock_init (&wakeup_cpucount_lock); waking_vector = firmware_waking_vector; wakeup_prepare (); /* Copy the wakeup_entry code. */ wakeup_entry_len = wakeup_entry_end - wakeup_entry_start; p = mapmem_hphys (wakeup_entry_addr, wakeup_entry_len, MAPMEM_WRITE); memcpy (p, wakeup_entry_start, wakeup_entry_len); unmapmem (p, wakeup_entry_len); return wakeup_entry_addr; }
static void loadcfg (void) { struct loadcfg_data *d; u8 *pass, *data; ulong rbx; struct config_data *tmpbuf; if (!enable) return; current->vmctl.read_general_reg (GENERAL_REG_RBX, &rbx); rbx &= 0xFFFFFFFF; d = mapmem_hphys (rbx, sizeof *d, 0); ASSERT (d); if (d->len != sizeof *d) panic ("size mismatch: %d, %d\n", d->len, (int)sizeof *d); pass = mapmem_hphys (d->pass, d->passlen, 0); ASSERT (pass); data = mapmem_hphys (d->data, d->datalen, 0); ASSERT (data); tmpbuf = alloc (d->datalen); ASSERT (tmpbuf); #ifdef CRYPTO_VPN decryptcfg (pass, d->passlen, data, d->datalen, tmpbuf); #else panic ("cannot decrypt"); #endif unmapmem (pass, d->passlen); unmapmem (data, d->datalen); unmapmem (d, sizeof *d); config.len = 0; if ((tmpbuf->len + 15) / 16 == d->datalen / 16) { if (tmpbuf->len != sizeof config) panic ("config size mismatch: %d, %d\n", tmpbuf->len, (int)sizeof config); data = mapmem_hphys (d->data, sizeof config, MAPMEM_WRITE); ASSERT (data); memcpy (data, tmpbuf, sizeof config); unmapmem (data, d->datalen); current->vmctl.write_general_reg (GENERAL_REG_RAX, 1); } else { current->vmctl.write_general_reg (GENERAL_REG_RAX, 0); } free (tmpbuf); }
static void copy_output_buffer (void *output, u16 length) { void *p; if (!length) return; p = mapmem_hphys (OUTPUT_PARAM_BLK_ADDR, length, 0); memcpy (output, p, length); unmapmem (p, length); }
static void copy_input_buffer (void *input, u16 length) { void *p; if (!length) return; p = mapmem_hphys (INPUT_PARAM_BLK_ADDR, length, MAPMEM_WRITE); memcpy (p, input, length); unmapmem (p, length); }
void memdump_hphys(u64 hphys){ u8 * phphys; int length = 128; phphys = mapmem_hphys (hphys, length, 0); static char * hpdes; hpdes = alloc(length); memset(hpdes, 0, length); memcpy(hpdes, phphys, length); printhex(hpdes, length, (u64)hpdes); }
void tcg_measure (void *virt, u32 len) { struct TCG_HashLogExtendEvent_input_param_blk input; struct { struct TCG_HashLogExtendEvent_output_param_blk output; char buf[32]; } s; u32 *log; u32 log_phys, phys; u32 ret, feat, event, edi; u8 major, minor; void *tmp; if (!len) return; if (!int1a_TCG_StatusCheck (&ret, &major, &minor, &feat, &event, &edi)) return; phys = 0x100000; log_phys = phys + len; log = mapmem_hphys (log_phys, 32, MAPMEM_WRITE); tmp = mapmem_hphys (phys, len, MAPMEM_WRITE); memcpy (tmp, virt, len); unmapmem (tmp, len); memset (&input, 0, sizeof input); input.u.format_2.IPBLength = sizeof input.u.format_2; input.u.format_2.HashDataPtr = phys; input.u.format_2.HashDataLen = len; input.u.format_2.PCRIndex = 4; input.u.format_2.LogDataPtr = log_phys; input.u.format_2.LogDataLen = 32; memset (log, 0, 32); log[0] = input.u.format_2.PCRIndex; log[1] = 13; if (!int1a_TCG_HashLogExtendEvent (&input, &s.output, sizeof s, &ret)) printf ("TCG_HashLogExtendEvent error\n"); else printf ("EventNumber = %u\n", s.output.EventNumber); unmapmem (log, 32); }
static void copy_output_param_blk (void *output, u16 size) { void *p; u16 *length; p = mapmem_hphys (OUTPUT_PARAM_BLK_ADDR, 0x10000, 0); length = p; if (size > *length) size = *length; if (size) memcpy (output, p, size); unmapmem (p, 0x10000); }
// ページの確保 void *pro100_alloc_page(phys_t *ptr) { void *vptr; void *vptr2; phys_t pptr; alloc_page(&vptr, &pptr); vptr2 = mapmem_hphys(pptr, PAGESIZE, MAPMEM_WRITE | MAPMEM_PCD | MAPMEM_PWT | MAPMEM_PAT); *ptr = pptr; return vptr2; }
static void mmio_hphys_access (phys_t gphysaddr, bool wr, void *buf, uint len, u32 flags) { void *p; if (!len) return; p = mapmem_hphys (gphysaddr, len, (wr ? MAPMEM_WRITE : 0) | flags); ASSERT (p); if (wr) memcpy (p, buf, len); else memcpy (buf, p, len); unmapmem (p, len); }
static void copy_bios_area (void *save, void *load) { void *p; if (save) { p = mapmem_hphys (0, BIOS_AREA_SIZE, 0); if (p) { memcpy (save, p, BIOS_AREA_SIZE); unmapmem (p, BIOS_AREA_SIZE); } else { printf ("map error\n"); } } if (load) { p = mapmem_hphys (0, BIOS_AREA_SIZE, MAPMEM_WRITE); if (p) { memcpy (p, load, BIOS_AREA_SIZE); unmapmem (p, BIOS_AREA_SIZE); } else { printf ("map error\n"); } } }
static void wakeup_ap (void) { u8 buf[5]; u8 *p; /* Put a "ljmpw" instruction to the physical address 0 to avoid the alignment restriction of the SIPI. */ p = mapmem_hphys (0, 5, MAPMEM_WRITE); memcpy (buf, p, 5); p[0] = 0xEA; /* ljmpw */ p[1] = wakeup_entry_addr & 0xF; p[2] = 0; p[3] = wakeup_entry_addr >> 4; p[4] = wakeup_entry_addr >> 12; ap_start_addr (0, wakeup_ap_loopcond, NULL); memcpy (p, buf, 5); unmapmem (p, 5); }
static void boot_guest (void) { struct config_data *d; ulong rbx; if (!enable) return; if (currentcpu->cpunum != 0) panic ("boot from AP"); current->vmctl.read_general_reg (GENERAL_REG_RBX, &rbx); rbx &= 0xFFFFFFFF; d = mapmem_hphys (rbx, sizeof *d, 0); ASSERT (d); if (d->len != sizeof *d) panic ("config size mismatch: %d, %d\n", d->len, (int)sizeof *d); memcpy (&config, d, sizeof *d); unmapmem (d, sizeof *d); do_boot_guest (); }
static void wakeup_ap (void) { u8 buf[5]; u8 *p; /* Do nothing if no APs were started before suspend. It is * true when there is only one logical processor for real or * the guest OS uses BSP only on UEFI systems. */ if (num_of_processors + 1 == 1) return; /* Put a "ljmpw" instruction to the physical address 0 to avoid the alignment restriction of the SIPI. */ p = mapmem_hphys (0, 5, MAPMEM_WRITE); memcpy (buf, p, 5); p[0] = 0xEA; /* ljmpw */ p[1] = wakeup_entry_addr & 0xF; p[2] = 0; p[3] = wakeup_entry_addr >> 4; p[4] = wakeup_entry_addr >> 12; ap_start_addr (0, wakeup_ap_loopcond, NULL); memcpy (p, buf, 5); unmapmem (p, 5); }
static int memdump_msghandler (int m, int c, struct msgbuf *buf, int bufcnt) { u8 *q, *tmp; struct memdump_data *d; void *recvbuf, *sendbuf; int recvlen, sendlen, errlen; char *errbuf; int num = -1; struct memdump_gphys_data gphys_data; struct memdump_gvirt_data gvirt_data; struct memdump_hvirt_data hvirt_data; if (m != 1) return -1; if (bufcnt < 3) return -1; recvbuf = buf[0].base; recvlen = buf[0].len; sendbuf = buf[1].base; sendlen = buf[1].len; errbuf = buf[2].base; errlen = buf[2].len; if (recvlen < sizeof (struct memdump_data)) return -1; if (errlen > 0) errbuf[0] = '\0'; d = (struct memdump_data *)recvbuf; q = sendbuf; switch ((enum memdump_type)c) { case MEMDUMP_GPHYS: gphys_data.physaddr = d->physaddr; gphys_data.q = q; gphys_data.sendlen = sendlen; num = callfunc_and_getint (memdump_gphys, &gphys_data); break; case MEMDUMP_HVIRT: hvirt_data.p = (u8 *)d->virtaddr; hvirt_data.q = q; hvirt_data.sendlen = sendlen; num = callfunc_and_getint (memdump_hvirt, &hvirt_data); break; case MEMDUMP_HPHYS: tmp = mapmem_hphys (d->physaddr, sendlen, 0); if (tmp) { hvirt_data.p = tmp; hvirt_data.q = q; hvirt_data.sendlen = sendlen; num = callfunc_and_getint (memdump_hvirt, &hvirt_data); unmapmem (tmp, sendlen); } else { snprintf (errbuf, errlen, "mapmem_hphys failed (phys=0x%llX)", d->physaddr); } break; case MEMDUMP_GVIRT: gvirt_data.d = d; gvirt_data.q = q; gvirt_data.sendlen = sendlen; gvirt_data.errbuf = errbuf; gvirt_data.errlen = errlen; num = callfunc_and_getint (memdump_gvirt, &gvirt_data); break; default: return -1; } if (num != -1) snprintf (errbuf, errlen, "exception %d", num); return 0; }
static void install_int0x15_hook (void) { u64 int0x15_code, int0x15_data, int0x15_base; u64 int0x15_vector_phys = 0x15 * 4; int count, len1, len2, i; struct e820_data *q; u64 b1, l1, b2, l2; u32 n, nn1, nn2; u32 t1, t2; void *p; len1 = guest_int0x15_hook_end - guest_int0x15_hook; int0x15_code = alloc_realmodemem (len1); count = 0; for (n = 0, nn1 = 1; nn1; n = nn1) { nn1 = getfakesysmemmap (n, &b1, &l1, &t1); nn2 = getsysmemmap (n, &b2, &l2, &t2); if (nn1 == nn2 && b1 == b2 && l1 == l2 && t1 == t2) continue; count++; } len2 = count * sizeof (struct e820_data); int0x15_data = alloc_realmodemem (len2); if (int0x15_data > int0x15_code) int0x15_base = int0x15_code; else int0x15_base = int0x15_data; int0x15_base &= 0xFFFF0; /* save old interrupt vector */ read_hphys_l (int0x15_vector_phys, &guest_int0x15_orig, 0); /* write parameters properly */ guest_int0x15_e801_fake_ax = e801_fake_ax; guest_int0x15_e801_fake_bx = e801_fake_bx; guest_int0x15_e820_data_minus0x18 = int0x15_data - int0x15_base - 0x18; guest_int0x15_e820_end = int0x15_data + len2 - int0x15_base; /* copy the program code */ p = mapmem_hphys (int0x15_code, len1, MAPMEM_WRITE); memcpy (p, guest_int0x15_hook, len1); unmapmem (p, len1); /* create e820_data */ q = mapmem_hphys (int0x15_data, len2, MAPMEM_WRITE); i = 0; for (n = 0, nn1 = 1; nn1; n = nn1) { nn1 = getfakesysmemmap (n, &b1, &l1, &t1); nn2 = getsysmemmap (n, &b2, &l2, &t2); if (nn1 == nn2 && b1 == b2 && l1 == l2 && t1 == t2) continue; ASSERT (i < count); q[i].n = n; q[i].nn = nn1; q[i].base = b1; q[i].len = l1; q[i].type = t1; i++; } unmapmem (q, len2); /* set interrupt vector */ write_hphys_l (int0x15_vector_phys, (int0x15_code - int0x15_base) | (int0x15_base << 12), 0); }