static void xen_load_gdt(const struct desc_ptr *dtr) { unsigned long va = dtr->address; unsigned int size = dtr->size + 1; unsigned pages = (size + PAGE_SIZE - 1) / PAGE_SIZE; unsigned long frames[pages]; int f; /* A GDT can be up to 64k in size, which corresponds to 8192 8-byte entries, or 16 4k pages.. */ BUG_ON(size > 65536); BUG_ON(va & ~PAGE_MASK); for (f = 0; va < dtr->address + size; va += PAGE_SIZE, f++) { int level; pte_t *ptep = lookup_address(va, &level); unsigned long pfn, mfn; void *virt; BUG_ON(ptep == NULL); pfn = pte_pfn(*ptep); mfn = pfn_to_mfn(pfn); virt = __va(PFN_PHYS(pfn)); frames[f] = mfn; make_lowmem_page_readonly((void *)va); make_lowmem_page_readonly(virt); } if (HYPERVISOR_set_gdt(frames, size / sizeof(struct desc_struct))) BUG(); }
/* * load_gdt for early boot, when the gdt is only mapped once */ static void __init xen_load_gdt_boot(const struct desc_ptr *dtr) { unsigned long va = dtr->address; unsigned int size = dtr->size + 1; unsigned pages = (size + PAGE_SIZE - 1) / PAGE_SIZE; unsigned long frames[pages]; int f; /* * A GDT can be up to 64k in size, which corresponds to 8192 * 8-byte entries, or 16 4k pages.. */ BUG_ON(size > 65536); BUG_ON(va & ~PAGE_MASK); for (f = 0; va < dtr->address + size; va += PAGE_SIZE, f++) { pte_t pte; unsigned long pfn, mfn; pfn = virt_to_pfn(va); mfn = pfn_to_mfn(pfn); pte = pfn_pte(pfn, PAGE_KERNEL_RO); if (HYPERVISOR_update_va_mapping((unsigned long)va, pte, 0)) BUG(); frames[f] = mfn; } if (HYPERVISOR_set_gdt(frames, size / sizeof(struct desc_struct))) BUG(); }
/* * Load appropriate gdt descriptor; we better be running on *ci * (for the most part, this is how a CPU knows who it is). */ void gdt_init_cpu(struct cpu_info *ci) { #ifndef XEN struct region_descriptor region; size_t max_len; max_len = MAXGDTSIZ * sizeof(gdt[0]); setregion(®ion, ci->ci_gdt, max_len - 1); lgdt(®ion); #else size_t len = gdt_size[0] * sizeof(gdt[0]); unsigned long frames[len >> PAGE_SHIFT]; vaddr_t va; pt_entry_t *ptp; int f; for (va = (vaddr_t)ci->ci_gdt, f = 0; va < (vaddr_t)ci->ci_gdt + len; va += PAGE_SIZE, f++) { KASSERT(va >= VM_MIN_KERNEL_ADDRESS); ptp = kvtopte(va); frames[f] = *ptp >> PAGE_SHIFT; pmap_pte_clearbits(ptp, PG_RW); } /* printk("loading gdt %x, %d entries, %d pages", */ /* frames[0] << PAGE_SHIFT, gdt_size[0], len >> PAGE_SHIFT); */ if (HYPERVISOR_set_gdt(frames, gdt_size[0])) panic("HYPERVISOR_set_gdt failed!\n"); lgdt_finish(); #endif }
void xen_set_gdt(ulong_t *frame_list, int entries) { int err; if ((err = HYPERVISOR_set_gdt(frame_list, entries)) != 0) { /* * X_EINVAL: reserved entry or bad frames * X_EFAULT: bad address */ panic("xen_set_gdt(%p, %d): error %d", (void *)frame_list, entries, -(int)err); } }
static void xen_load_gdt(const struct desc_ptr *dtr) { unsigned long va = dtr->address; unsigned int size = dtr->size + 1; unsigned pages = (size + PAGE_SIZE - 1) / PAGE_SIZE; unsigned long frames[pages]; int f; /* * A GDT can be up to 64k in size, which corresponds to 8192 * 8-byte entries, or 16 4k pages.. */ BUG_ON(size > 65536); BUG_ON(va & ~PAGE_MASK); for (f = 0; va < dtr->address + size; va += PAGE_SIZE, f++) { int level; pte_t *ptep; unsigned long pfn, mfn; void *virt; /* * The GDT is per-cpu and is in the percpu data area. * That can be virtually mapped, so we need to do a * page-walk to get the underlying MFN for the * hypercall. The page can also be in the kernel's * linear range, so we need to RO that mapping too. */ ptep = lookup_address(va, &level); BUG_ON(ptep == NULL); pfn = pte_pfn(*ptep); mfn = pfn_to_mfn(pfn); virt = __va(PFN_PHYS(pfn)); frames[f] = mfn; make_lowmem_page_readonly((void *)va); make_lowmem_page_readonly(virt); } if (HYPERVISOR_set_gdt(frames, size / sizeof(struct desc_struct))) BUG(); }
/* * Load appropriate gdt descriptor; we better be running on *ci * (for the most part, this is how a cpu knows who it is). */ void gdt_init_cpu(struct cpu_info *ci) { size_t len = gdt_size[0] * sizeof(gdt[0]); unsigned long frames[len >> PAGE_SHIFT]; vaddr_t va; pt_entry_t *ptp; pt_entry_t *maptp; int f; for (va = (vaddr_t)ci->ci_gdt, f = 0; va < (vaddr_t)ci->ci_gdt + len; va += PAGE_SIZE, f++) { KASSERT(va >= VM_MIN_KERNEL_ADDRESS); ptp = kvtopte(va); frames[f] = *ptp >> PAGE_SHIFT; maptp = (pt_entry_t *)vtomach((vaddr_t)ptp); PTE_CLEARBITS(ptp, maptp, PG_RW); } PTE_UPDATES_FLUSH(); if (HYPERVISOR_set_gdt(frames, gdt_size[0])) panic("HYPERVISOR_set_gdt failed!\n"); lgdt_finish(); }