/*H:040 * This is the i386-specific code to setup and run the Guest. Interrupts * are disabled: we own the CPU. */ void lguest_arch_run_guest(struct lg_cpu *cpu) { /* * Remember the awfully-named TS bit? If the Guest has asked to set it * we set it now, so we can trap and pass that trap to the Guest if it * uses the FPU. */ if (cpu->ts && user_has_fpu()) stts(); /* * SYSENTER is an optimized way of doing system calls. We can't allow * it because it always jumps to privilege level 0. A normal Guest * won't try it because we don't advertise it in CPUID, but a malicious * Guest (or malicious Guest userspace program) could, so we tell the * CPU to disable it before running the Guest. */ if (boot_cpu_has(X86_FEATURE_SEP)) wrmsr(MSR_IA32_SYSENTER_CS, 0, 0); /* * Now we actually run the Guest. It will return when something * interesting happens, and we can examine its registers to see what it * was doing. */ run_guest_once(cpu, lguest_pages(raw_smp_processor_id())); /* * Note that the "regs" structure contains two extra entries which are * not really registers: a trap number which says what interrupt or * trap made the switcher code come back, and an error code which some * traps set. */ /* Restore SYSENTER if it's supposed to be on. */ if (boot_cpu_has(X86_FEATURE_SEP)) wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0); /* Clear the host TS bit if it was set above. */ if (cpu->ts && user_has_fpu()) clts(); /* * If the Guest page faulted, then the cr2 register will tell us the * bad virtual address. We have to grab this now, because once we * re-enable interrupts an interrupt could fault and thus overwrite * cr2, or we could even move off to a different CPU. */ if (cpu->regs->trapnum == 14) cpu->arch.last_pagefault = read_cr2(); /* * Similarly, if we took a trap because the Guest used the FPU, * we have to restore the FPU it expects to see. * math_state_restore() may sleep and we may even move off to * a different CPU. So all the critical stuff should be done * before this. */ else if (cpu->regs->trapnum == 7 && !user_has_fpu()) math_state_restore(); }
void lguest_arch_run_guest(struct lg_cpu *cpu) { if (cpu->ts) unlazy_fpu(current); if (boot_cpu_has(X86_FEATURE_SEP)) wrmsr(MSR_IA32_SYSENTER_CS, 0, 0); run_guest_once(cpu, lguest_pages(raw_smp_processor_id())); if (boot_cpu_has(X86_FEATURE_SEP)) wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0); if (cpu->regs->trapnum == 14) cpu->arch.last_pagefault = read_cr2(); else if (cpu->regs->trapnum == 7) math_state_restore(); }