Exemple #1
0
static void read_guest_memory(struct lg_cpu *cpu) {
	int i;
	struct file *memory;
	memory = file_open("/tmp/lgmemory", O_RDWR, 0644);
	for (i = 0; i < cpu->lg->pfn_limit; i++) {
		file_read(memory, i * PAGE_SIZE, page_buffer, PAGE_SIZE);
		__lgwrite(cpu, i * PAGE_SIZE, page_buffer, PAGE_SIZE);
	}
	file_close(memory);
}
/*
 * Our hypercalls mechanism used to be based on direct software interrupts.
 * After Anthony's "Refactor hypercall infrastructure" kvm patch, we decided to
 * change over to using kvm hypercalls.
 *
 * KVM_HYPERCALL is actually a "vmcall" instruction, which generates an invalid
 * opcode fault (fault 6) on non-VT cpus, so the easiest solution seemed to be
 * an *emulation approach*: if the fault was really produced by an hypercall
 * (is_hypercall() does exactly this check), we can just call the corresponding
 * hypercall host implementation function.
 *
 * But these invalid opcode faults are notably slower than software interrupts.
 * So we implemented the *patching (or rewriting) approach*: every time we hit
 * the KVM_HYPERCALL opcode in Guest code, we patch it to the old "int 0x1f"
 * opcode, so next time the Guest calls this hypercall it will use the
 * faster trap mechanism.
 *
 * Matias even benchmarked it to convince you: this shows the average cycle
 * cost of a hypercall.  For each alternative solution mentioned above we've
 * made 5 runs of the benchmark:
 *
 * 1) direct software interrupt: 2915, 2789, 2764, 2721, 2898
 * 2) emulation technique: 3410, 3681, 3466, 3392, 3780
 * 3) patching (rewrite) technique: 2977, 2975, 2891, 2637, 2884
 *
 * One two-line function is worth a 20% hypercall speed boost!
 */
static void rewrite_hypercall(struct lg_cpu *cpu)
{
	/*
	 * This are the opcodes we use to patch the Guest.  The opcode for "int
	 * $0x1f" is "0xcd 0x1f" but vmcall instruction is 3 bytes long, so we
	 * complete the sequence with a NOP (0x90).
	 */
	u8 insn[3] = {0xcd, 0x1f, 0x90};

	__lgwrite(cpu, guest_pa(cpu, cpu->regs->eip), insn, sizeof(insn));
	/*
	 * The above write might have caused a copy of that page to be made
	 * (if it was read-only).  We need to make sure the Guest has
	 * up-to-date pagetables.  As this doesn't happen often, we can just
	 * drop them all.
	 */
	guest_pagetable_clear_all(cpu);
}