diff options
Diffstat (limited to 'arch/x86/xen')
-rw-r--r-- | arch/x86/xen/enlighten.c | 73 | ||||
-rw-r--r-- | arch/x86/xen/xen-asm_64.S | 2 |
2 files changed, 71 insertions, 4 deletions
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 9ff6e3cbf08f..b795470ec069 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
@@ -325,6 +325,57 @@ static unsigned long xen_store_tr(void) | |||
325 | return 0; | 325 | return 0; |
326 | } | 326 | } |
327 | 327 | ||
328 | /* | ||
329 | * If 'v' is a vmalloc mapping, then find the linear mapping of the | ||
330 | * page (if any) and also set its protections to match: | ||
331 | */ | ||
332 | static void set_aliased_prot(void *v, pgprot_t prot) | ||
333 | { | ||
334 | int level; | ||
335 | pte_t *ptep; | ||
336 | pte_t pte; | ||
337 | unsigned long pfn; | ||
338 | struct page *page; | ||
339 | |||
340 | ptep = lookup_address((unsigned long)v, &level); | ||
341 | BUG_ON(ptep == NULL); | ||
342 | |||
343 | pfn = pte_pfn(*ptep); | ||
344 | page = pfn_to_page(pfn); | ||
345 | |||
346 | pte = pfn_pte(pfn, prot); | ||
347 | |||
348 | if (HYPERVISOR_update_va_mapping((unsigned long)v, pte, 0)) | ||
349 | BUG(); | ||
350 | |||
351 | if (!PageHighMem(page)) { | ||
352 | void *av = __va(PFN_PHYS(pfn)); | ||
353 | |||
354 | if (av != v) | ||
355 | if (HYPERVISOR_update_va_mapping((unsigned long)av, pte, 0)) | ||
356 | BUG(); | ||
357 | } else | ||
358 | kmap_flush_unused(); | ||
359 | } | ||
360 | |||
361 | static void xen_alloc_ldt(struct desc_struct *ldt, unsigned entries) | ||
362 | { | ||
363 | const unsigned entries_per_page = PAGE_SIZE / LDT_ENTRY_SIZE; | ||
364 | int i; | ||
365 | |||
366 | for(i = 0; i < entries; i += entries_per_page) | ||
367 | set_aliased_prot(ldt + i, PAGE_KERNEL_RO); | ||
368 | } | ||
369 | |||
370 | static void xen_free_ldt(struct desc_struct *ldt, unsigned entries) | ||
371 | { | ||
372 | const unsigned entries_per_page = PAGE_SIZE / LDT_ENTRY_SIZE; | ||
373 | int i; | ||
374 | |||
375 | for(i = 0; i < entries; i += entries_per_page) | ||
376 | set_aliased_prot(ldt + i, PAGE_KERNEL); | ||
377 | } | ||
378 | |||
328 | static void xen_set_ldt(const void *addr, unsigned entries) | 379 | static void xen_set_ldt(const void *addr, unsigned entries) |
329 | { | 380 | { |
330 | struct mmuext_op *op; | 381 | struct mmuext_op *op; |
@@ -426,7 +477,7 @@ static void xen_write_ldt_entry(struct desc_struct *dt, int entrynum, | |||
426 | const void *ptr) | 477 | const void *ptr) |
427 | { | 478 | { |
428 | unsigned long lp = (unsigned long)&dt[entrynum]; | 479 | unsigned long lp = (unsigned long)&dt[entrynum]; |
429 | xmaddr_t mach_lp = virt_to_machine(lp); | 480 | xmaddr_t mach_lp = arbitrary_virt_to_machine(lp); |
430 | u64 entry = *(u64 *)ptr; | 481 | u64 entry = *(u64 *)ptr; |
431 | 482 | ||
432 | preempt_disable(); | 483 | preempt_disable(); |
@@ -559,7 +610,7 @@ static void xen_write_gdt_entry(struct desc_struct *dt, int entry, | |||
559 | } | 610 | } |
560 | 611 | ||
561 | static void xen_load_sp0(struct tss_struct *tss, | 612 | static void xen_load_sp0(struct tss_struct *tss, |
562 | struct thread_struct *thread) | 613 | struct thread_struct *thread) |
563 | { | 614 | { |
564 | struct multicall_space mcs = xen_mc_entry(0); | 615 | struct multicall_space mcs = xen_mc_entry(0); |
565 | MULTI_stack_switch(mcs.mc, __KERNEL_DS, thread->sp0); | 616 | MULTI_stack_switch(mcs.mc, __KERNEL_DS, thread->sp0); |
@@ -803,6 +854,19 @@ static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high) | |||
803 | ret = -EFAULT; | 854 | ret = -EFAULT; |
804 | break; | 855 | break; |
805 | #endif | 856 | #endif |
857 | |||
858 | case MSR_STAR: | ||
859 | case MSR_CSTAR: | ||
860 | case MSR_LSTAR: | ||
861 | case MSR_SYSCALL_MASK: | ||
862 | case MSR_IA32_SYSENTER_CS: | ||
863 | case MSR_IA32_SYSENTER_ESP: | ||
864 | case MSR_IA32_SYSENTER_EIP: | ||
865 | /* Fast syscall setup is all done in hypercalls, so | ||
866 | these are all ignored. Stub them out here to stop | ||
867 | Xen console noise. */ | ||
868 | break; | ||
869 | |||
806 | default: | 870 | default: |
807 | ret = native_write_msr_safe(msr, low, high); | 871 | ret = native_write_msr_safe(msr, low, high); |
808 | } | 872 | } |
@@ -1220,6 +1284,9 @@ static const struct pv_cpu_ops xen_cpu_ops __initdata = { | |||
1220 | .load_gs_index = xen_load_gs_index, | 1284 | .load_gs_index = xen_load_gs_index, |
1221 | #endif | 1285 | #endif |
1222 | 1286 | ||
1287 | .alloc_ldt = xen_alloc_ldt, | ||
1288 | .free_ldt = xen_free_ldt, | ||
1289 | |||
1223 | .store_gdt = native_store_gdt, | 1290 | .store_gdt = native_store_gdt, |
1224 | .store_idt = native_store_idt, | 1291 | .store_idt = native_store_idt, |
1225 | .store_tr = xen_store_tr, | 1292 | .store_tr = xen_store_tr, |
@@ -1324,7 +1391,7 @@ static const struct pv_mmu_ops xen_mmu_ops __initdata = { | |||
1324 | .ptep_modify_prot_commit = __ptep_modify_prot_commit, | 1391 | .ptep_modify_prot_commit = __ptep_modify_prot_commit, |
1325 | 1392 | ||
1326 | .pte_val = xen_pte_val, | 1393 | .pte_val = xen_pte_val, |
1327 | .pte_flags = native_pte_val, | 1394 | .pte_flags = native_pte_flags, |
1328 | .pgd_val = xen_pgd_val, | 1395 | .pgd_val = xen_pgd_val, |
1329 | 1396 | ||
1330 | .make_pte = xen_make_pte, | 1397 | .make_pte = xen_make_pte, |
diff --git a/arch/x86/xen/xen-asm_64.S b/arch/x86/xen/xen-asm_64.S index 4038cbfe3331..7f58304fafb3 100644 --- a/arch/x86/xen/xen-asm_64.S +++ b/arch/x86/xen/xen-asm_64.S | |||
@@ -173,7 +173,7 @@ ENTRY(xen_sysexit) | |||
173 | pushq $__USER32_CS | 173 | pushq $__USER32_CS |
174 | pushq %rdx | 174 | pushq %rdx |
175 | 175 | ||
176 | pushq $VGCF_in_syscall | 176 | pushq $0 |
177 | 1: jmp hypercall_iret | 177 | 1: jmp hypercall_iret |
178 | ENDPATCH(xen_sysexit) | 178 | ENDPATCH(xen_sysexit) |
179 | RELOC(xen_sysexit, 1b+1) | 179 | RELOC(xen_sysexit, 1b+1) |