static void copy_in_guest_info(struct lg_cpu *cpu, struct lguest_pages *pages) { if (__this_cpu_read(lg_last_cpu) != cpu || cpu->last_pages != pages) { __this_cpu_write(lg_last_cpu, cpu); cpu->last_pages = pages; cpu->changed = CHANGED_ALL; } pages->state.host_cr3 = __pa(current->mm->pgd); map_switcher_in_guest(cpu, pages); pages->state.guest_tss.sp1 = cpu->esp1; pages->state.guest_tss.ss1 = cpu->ss1; if (cpu->changed & CHANGED_IDT) copy_traps(cpu, pages->state.guest_idt, default_idt_entries); if (cpu->changed & CHANGED_GDT) copy_gdt(cpu, pages->state.guest_gdt); else if (cpu->changed & CHANGED_GDT_TLS) copy_gdt_tls(cpu, pages->state.guest_gdt); cpu->changed = 0; }
/*S:010 * We approach the Switcher. * * Remember that each CPU has two pages which are visible to the Guest when it * runs on that CPU. This has to contain the state for that Guest: we copy the * state in just before we run the Guest. * * Each Guest has "changed" flags which indicate what has changed in the Guest * since it last ran. We saw this set in interrupts_and_traps.c and * segments.c. */ static void copy_in_guest_info(struct lg_cpu *cpu, struct lguest_pages *pages) { /* * Copying all this data can be quite expensive. We usually run the * same Guest we ran last time (and that Guest hasn't run anywhere else * meanwhile). If that's not the case, we pretend everything in the * Guest has changed. */ if (__this_cpu_read(lg_last_cpu) != cpu || cpu->last_pages != pages) { __this_cpu_write(lg_last_cpu, cpu); cpu->last_pages = pages; cpu->changed = CHANGED_ALL; } /* * These copies are pretty cheap, so we do them unconditionally: */ /* Save the current Host top-level page directory. */ #ifdef CONFIG_PAX_PER_CPU_PGD pages->state.host_cr3 = read_cr3(); #else pages->state.host_cr3 = __pa(current->mm->pgd); #endif /* * Set up the Guest's page tables to see this CPU's pages (and no * other CPU's pages). */ map_switcher_in_guest(cpu, pages); /* * Set up the two "TSS" members which tell the CPU what stack to use * for traps which do directly into the Guest (ie. traps at privilege * level 1). */ pages->state.guest_tss.sp1 = cpu->esp1; pages->state.guest_tss.ss1 = cpu->ss1; /* Copy direct-to-Guest trap entries. */ if (cpu->changed & CHANGED_IDT) copy_traps(cpu, pages->state.guest_idt, default_idt_entries); /* Copy all GDT entries which the Guest can change. */ if (cpu->changed & CHANGED_GDT) copy_gdt(cpu, pages->state.guest_gdt); /* If only the TLS entries have changed, copy them. */ else if (cpu->changed & CHANGED_GDT_TLS) copy_gdt_tls(cpu, pages->state.guest_gdt); /* Mark the Guest as unchanged for next time. */ cpu->changed = 0; }