aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/xen/enlighten.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/xen/enlighten.c')
-rw-r--r--arch/x86/xen/enlighten.c185
1 files changed, 70 insertions, 115 deletions
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index a4e201b47f64..b106e825d266 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -30,7 +30,6 @@
30#include <xen/interface/xen.h> 30#include <xen/interface/xen.h>
31#include <xen/interface/physdev.h> 31#include <xen/interface/physdev.h>
32#include <xen/interface/vcpu.h> 32#include <xen/interface/vcpu.h>
33#include <xen/interface/sched.h>
34#include <xen/features.h> 33#include <xen/features.h>
35#include <xen/page.h> 34#include <xen/page.h>
36#include <xen/hvc-console.h> 35#include <xen/hvc-console.h>
@@ -57,6 +56,9 @@ EXPORT_SYMBOL_GPL(hypercall_page);
57DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu); 56DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu);
58DEFINE_PER_CPU(struct vcpu_info, xen_vcpu_info); 57DEFINE_PER_CPU(struct vcpu_info, xen_vcpu_info);
59 58
59enum xen_domain_type xen_domain_type = XEN_NATIVE;
60EXPORT_SYMBOL_GPL(xen_domain_type);
61
60/* 62/*
61 * Identity map, in addition to plain kernel map. This needs to be 63 * Identity map, in addition to plain kernel map. This needs to be
62 * large enough to allocate page table pages to allocate the rest. 64 * large enough to allocate page table pages to allocate the rest.
@@ -226,103 +228,68 @@ static unsigned long xen_get_debugreg(int reg)
226 return HYPERVISOR_get_debugreg(reg); 228 return HYPERVISOR_get_debugreg(reg);
227} 229}
228 230
229static unsigned long xen_save_fl(void) 231static void xen_leave_lazy(void)
230{ 232{
231 struct vcpu_info *vcpu; 233 paravirt_leave_lazy(paravirt_get_lazy_mode());
232 unsigned long flags; 234 xen_mc_flush();
233
234 vcpu = x86_read_percpu(xen_vcpu);
235
236 /* flag has opposite sense of mask */
237 flags = !vcpu->evtchn_upcall_mask;
238
239 /* convert to IF type flag
240 -0 -> 0x00000000
241 -1 -> 0xffffffff
242 */
243 return (-flags) & X86_EFLAGS_IF;
244} 235}
245 236
246static void xen_restore_fl(unsigned long flags) 237static unsigned long xen_store_tr(void)
247{ 238{
248 struct vcpu_info *vcpu; 239 return 0;
249
250 /* convert from IF type flag */
251 flags = !(flags & X86_EFLAGS_IF);
252
253 /* There's a one instruction preempt window here. We need to
254 make sure we're don't switch CPUs between getting the vcpu
255 pointer and updating the mask. */
256 preempt_disable();
257 vcpu = x86_read_percpu(xen_vcpu);
258 vcpu->evtchn_upcall_mask = flags;
259 preempt_enable_no_resched();
260
261 /* Doesn't matter if we get preempted here, because any
262 pending event will get dealt with anyway. */
263
264 if (flags == 0) {
265 preempt_check_resched();
266 barrier(); /* unmask then check (avoid races) */
267 if (unlikely(vcpu->evtchn_upcall_pending))
268 force_evtchn_callback();
269 }
270} 240}
271 241
272static void xen_irq_disable(void) 242/*
243 * Set the page permissions for a particular virtual address. If the
244 * address is a vmalloc mapping (or other non-linear mapping), then
245 * find the linear mapping of the page and also set its protections to
246 * match.
247 */
248static void set_aliased_prot(void *v, pgprot_t prot)
273{ 249{
274 /* There's a one instruction preempt window here. We need to 250 int level;
275 make sure we're don't switch CPUs between getting the vcpu 251 pte_t *ptep;
276 pointer and updating the mask. */ 252 pte_t pte;
277 preempt_disable(); 253 unsigned long pfn;
278 x86_read_percpu(xen_vcpu)->evtchn_upcall_mask = 1; 254 struct page *page;
279 preempt_enable_no_resched();
280}
281 255
282static void xen_irq_enable(void) 256 ptep = lookup_address((unsigned long)v, &level);
283{ 257 BUG_ON(ptep == NULL);
284 struct vcpu_info *vcpu;
285 258
286 /* We don't need to worry about being preempted here, since 259 pfn = pte_pfn(*ptep);
287 either a) interrupts are disabled, so no preemption, or b) 260 page = pfn_to_page(pfn);
288 the caller is confused and is trying to re-enable interrupts
289 on an indeterminate processor. */
290 261
291 vcpu = x86_read_percpu(xen_vcpu); 262 pte = pfn_pte(pfn, prot);
292 vcpu->evtchn_upcall_mask = 0;
293 263
294 /* Doesn't matter if we get preempted here, because any 264 if (HYPERVISOR_update_va_mapping((unsigned long)v, pte, 0))
295 pending event will get dealt with anyway. */ 265 BUG();
296 266
297 barrier(); /* unmask then check (avoid races) */ 267 if (!PageHighMem(page)) {
298 if (unlikely(vcpu->evtchn_upcall_pending)) 268 void *av = __va(PFN_PHYS(pfn));
299 force_evtchn_callback();
300}
301 269
302static void xen_safe_halt(void) 270 if (av != v)
303{ 271 if (HYPERVISOR_update_va_mapping((unsigned long)av, pte, 0))
304 /* Blocking includes an implicit local_irq_enable(). */ 272 BUG();
305 if (HYPERVISOR_sched_op(SCHEDOP_block, NULL) != 0) 273 } else
306 BUG(); 274 kmap_flush_unused();
307} 275}
308 276
309static void xen_halt(void) 277static void xen_alloc_ldt(struct desc_struct *ldt, unsigned entries)
310{ 278{
311 if (irqs_disabled()) 279 const unsigned entries_per_page = PAGE_SIZE / LDT_ENTRY_SIZE;
312 HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL); 280 int i;
313 else
314 xen_safe_halt();
315}
316 281
317static void xen_leave_lazy(void) 282 for(i = 0; i < entries; i += entries_per_page)
318{ 283 set_aliased_prot(ldt + i, PAGE_KERNEL_RO);
319 paravirt_leave_lazy(paravirt_get_lazy_mode());
320 xen_mc_flush();
321} 284}
322 285
323static unsigned long xen_store_tr(void) 286static void xen_free_ldt(struct desc_struct *ldt, unsigned entries)
324{ 287{
325 return 0; 288 const unsigned entries_per_page = PAGE_SIZE / LDT_ENTRY_SIZE;
289 int i;
290
291 for(i = 0; i < entries; i += entries_per_page)
292 set_aliased_prot(ldt + i, PAGE_KERNEL);
326} 293}
327 294
328static void xen_set_ldt(const void *addr, unsigned entries) 295static void xen_set_ldt(const void *addr, unsigned entries)
@@ -425,8 +392,7 @@ static void xen_load_gs_index(unsigned int idx)
425static void xen_write_ldt_entry(struct desc_struct *dt, int entrynum, 392static void xen_write_ldt_entry(struct desc_struct *dt, int entrynum,
426 const void *ptr) 393 const void *ptr)
427{ 394{
428 unsigned long lp = (unsigned long)&dt[entrynum]; 395 xmaddr_t mach_lp = arbitrary_virt_to_machine(&dt[entrynum]);
429 xmaddr_t mach_lp = virt_to_machine(lp);
430 u64 entry = *(u64 *)ptr; 396 u64 entry = *(u64 *)ptr;
431 397
432 preempt_disable(); 398 preempt_disable();
@@ -559,7 +525,7 @@ static void xen_write_gdt_entry(struct desc_struct *dt, int entry,
559} 525}
560 526
561static void xen_load_sp0(struct tss_struct *tss, 527static void xen_load_sp0(struct tss_struct *tss,
562 struct thread_struct *thread) 528 struct thread_struct *thread)
563{ 529{
564 struct multicall_space mcs = xen_mc_entry(0); 530 struct multicall_space mcs = xen_mc_entry(0);
565 MULTI_stack_switch(mcs.mc, __KERNEL_DS, thread->sp0); 531 MULTI_stack_switch(mcs.mc, __KERNEL_DS, thread->sp0);
@@ -803,6 +769,19 @@ static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high)
803 ret = -EFAULT; 769 ret = -EFAULT;
804 break; 770 break;
805#endif 771#endif
772
773 case MSR_STAR:
774 case MSR_CSTAR:
775 case MSR_LSTAR:
776 case MSR_SYSCALL_MASK:
777 case MSR_IA32_SYSENTER_CS:
778 case MSR_IA32_SYSENTER_ESP:
779 case MSR_IA32_SYSENTER_EIP:
780 /* Fast syscall setup is all done in hypercalls, so
781 these are all ignored. Stub them out here to stop
782 Xen console noise. */
783 break;
784
806 default: 785 default:
807 ret = native_write_msr_safe(msr, low, high); 786 ret = native_write_msr_safe(msr, low, high);
808 } 787 }
@@ -846,7 +825,7 @@ static void xen_alloc_ptpage(struct mm_struct *mm, u32 pfn, unsigned level)
846 SetPagePinned(page); 825 SetPagePinned(page);
847 826
848 if (!PageHighMem(page)) { 827 if (!PageHighMem(page)) {
849 make_lowmem_page_readonly(__va(PFN_PHYS(pfn))); 828 make_lowmem_page_readonly(__va(PFN_PHYS((unsigned long)pfn)));
850 if (level == PT_PTE) 829 if (level == PT_PTE)
851 pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn); 830 pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn);
852 } else 831 } else
@@ -1220,6 +1199,9 @@ static const struct pv_cpu_ops xen_cpu_ops __initdata = {
1220 .load_gs_index = xen_load_gs_index, 1199 .load_gs_index = xen_load_gs_index,
1221#endif 1200#endif
1222 1201
1202 .alloc_ldt = xen_alloc_ldt,
1203 .free_ldt = xen_free_ldt,
1204
1223 .store_gdt = native_store_gdt, 1205 .store_gdt = native_store_gdt,
1224 .store_idt = native_store_idt, 1206 .store_idt = native_store_idt,
1225 .store_tr = xen_store_tr, 1207 .store_tr = xen_store_tr,
@@ -1241,36 +1223,6 @@ static const struct pv_cpu_ops xen_cpu_ops __initdata = {
1241 }, 1223 },
1242}; 1224};
1243 1225
1244static void __init __xen_init_IRQ(void)
1245{
1246#ifdef CONFIG_X86_64
1247 int i;
1248
1249 /* Create identity vector->irq map */
1250 for(i = 0; i < NR_VECTORS; i++) {
1251 int cpu;
1252
1253 for_each_possible_cpu(cpu)
1254 per_cpu(vector_irq, cpu)[i] = i;
1255 }
1256#endif /* CONFIG_X86_64 */
1257
1258 xen_init_IRQ();
1259}
1260
1261static const struct pv_irq_ops xen_irq_ops __initdata = {
1262 .init_IRQ = __xen_init_IRQ,
1263 .save_fl = xen_save_fl,
1264 .restore_fl = xen_restore_fl,
1265 .irq_disable = xen_irq_disable,
1266 .irq_enable = xen_irq_enable,
1267 .safe_halt = xen_safe_halt,
1268 .halt = xen_halt,
1269#ifdef CONFIG_X86_64
1270 .adjust_exception_frame = xen_adjust_exception_frame,
1271#endif
1272};
1273
1274static const struct pv_apic_ops xen_apic_ops __initdata = { 1226static const struct pv_apic_ops xen_apic_ops __initdata = {
1275#ifdef CONFIG_X86_LOCAL_APIC 1227#ifdef CONFIG_X86_LOCAL_APIC
1276 .apic_write = xen_apic_write, 1228 .apic_write = xen_apic_write,
@@ -1664,6 +1616,8 @@ asmlinkage void __init xen_start_kernel(void)
1664 if (!xen_start_info) 1616 if (!xen_start_info)
1665 return; 1617 return;
1666 1618
1619 xen_domain_type = XEN_PV_DOMAIN;
1620
1667 BUG_ON(memcmp(xen_start_info->magic, "xen-3", 5) != 0); 1621 BUG_ON(memcmp(xen_start_info->magic, "xen-3", 5) != 0);
1668 1622
1669 xen_setup_features(); 1623 xen_setup_features();
@@ -1673,10 +1627,11 @@ asmlinkage void __init xen_start_kernel(void)
1673 pv_init_ops = xen_init_ops; 1627 pv_init_ops = xen_init_ops;
1674 pv_time_ops = xen_time_ops; 1628 pv_time_ops = xen_time_ops;
1675 pv_cpu_ops = xen_cpu_ops; 1629 pv_cpu_ops = xen_cpu_ops;
1676 pv_irq_ops = xen_irq_ops;
1677 pv_apic_ops = xen_apic_ops; 1630 pv_apic_ops = xen_apic_ops;
1678 pv_mmu_ops = xen_mmu_ops; 1631 pv_mmu_ops = xen_mmu_ops;
1679 1632
1633 xen_init_irq_ops();
1634
1680 if (xen_feature(XENFEAT_mmu_pt_update_preserve_ad)) { 1635 if (xen_feature(XENFEAT_mmu_pt_update_preserve_ad)) {
1681 pv_mmu_ops.ptep_modify_prot_start = xen_ptep_modify_prot_start; 1636 pv_mmu_ops.ptep_modify_prot_start = xen_ptep_modify_prot_start;
1682 pv_mmu_ops.ptep_modify_prot_commit = xen_ptep_modify_prot_commit; 1637 pv_mmu_ops.ptep_modify_prot_commit = xen_ptep_modify_prot_commit;
@@ -1700,7 +1655,7 @@ asmlinkage void __init xen_start_kernel(void)
1700 1655
1701 /* Prevent unwanted bits from being set in PTEs. */ 1656 /* Prevent unwanted bits from being set in PTEs. */
1702 __supported_pte_mask &= ~_PAGE_GLOBAL; 1657 __supported_pte_mask &= ~_PAGE_GLOBAL;
1703 if (!is_initial_xendomain()) 1658 if (!xen_initial_domain())
1704 __supported_pte_mask &= ~(_PAGE_PWT | _PAGE_PCD); 1659 __supported_pte_mask &= ~(_PAGE_PWT | _PAGE_PCD);
1705 1660
1706 /* Don't do the full vcpu_info placement stuff until we have a 1661 /* Don't do the full vcpu_info placement stuff until we have a
@@ -1735,7 +1690,7 @@ asmlinkage void __init xen_start_kernel(void)
1735 boot_params.hdr.ramdisk_size = xen_start_info->mod_len; 1690 boot_params.hdr.ramdisk_size = xen_start_info->mod_len;
1736 boot_params.hdr.cmd_line_ptr = __pa(xen_start_info->cmd_line); 1691 boot_params.hdr.cmd_line_ptr = __pa(xen_start_info->cmd_line);
1737 1692
1738 if (!is_initial_xendomain()) { 1693 if (!xen_initial_domain()) {
1739 add_preferred_console("xenboot", 0, NULL); 1694 add_preferred_console("xenboot", 0, NULL);
1740 add_preferred_console("tty", 0, NULL); 1695 add_preferred_console("tty", 0, NULL);
1741 add_preferred_console("hvc", 0, NULL); 1696 add_preferred_console("hvc", 0, NULL);