static void lguest_set_pud(pud_t *pudp, pud_t pudval) { native_set_pud(pudp, pudval); /* 32 bytes aligned pdpt address and the index. */ lazy_hcall2(LHCALL_SET_PGD, __pa(pudp) & 0xFFFFFFE0, (__pa(pudp) & 0x1F) / sizeof(pud_t)); }
/* OK, I lied. There are three "thread local storage" GDT entries which change * on every context switch (these three entries are how glibc implements * __thread variables). So we have a hypercall specifically for this case. */ static void lguest_load_tls(struct thread_struct *t, unsigned int cpu) { /* There's one problem which normal hardware doesn't have: the Host * can't handle us removing entries we're currently using. So we clear * the GS register here: if it's needed it'll be reloaded anyway. */ lazy_load_gs(0); lazy_hcall2(LHCALL_LOAD_TLS, __pa(&t->tls_array), cpu); }
/* The Guest calls lguest_set_pmd to set a top-level entry when !PAE. */ static void lguest_set_pmd(pmd_t *pmdp, pmd_t pmdval) { native_set_pmd(pmdp, pmdval); lazy_hcall2(LHCALL_SET_PGD, __pa(pmdp) & PAGE_MASK, (__pa(pmdp) & (PAGE_SIZE - 1)) / sizeof(pmd_t)); }
/* The Guest calls this to set a top-level entry. Again, we set the entry then * tell the Host which top-level page we changed, and the index of the entry we * changed. */ static void lguest_set_pmd(pmd_t *pmdp, pmd_t pmdval) { *pmdp = pmdval; lazy_hcall2(LHCALL_SET_PMD, __pa(pmdp) & PAGE_MASK, (__pa(pmdp) & (PAGE_SIZE - 1)) / 4); }