]> nv-tegra.nvidia Code Review - linux-2.6.git/commitdiff
Merge branch 'x86-xen-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 14 Sep 2009 17:23:49 +0000 (10:23 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 14 Sep 2009 17:23:49 +0000 (10:23 -0700)
* 'x86-xen-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  x86: split __phys_addr out into separate file
  xen: use stronger barrier after unlocking lock
  xen: only enable interrupts while actually blocking for spinlock
  xen: make -fstack-protector work under Xen

1  2 
arch/x86/xen/enlighten.c

diff --combined arch/x86/xen/enlighten.c
index b62ccb840cfb1a6a3a64735781249f2ef412d179,76143136dead5b58d62f6bf1557f4b8a92b53899..0dd0c2c6cae0ff1fb8aa1ce563636e7ad38ad880
@@@ -51,6 -51,7 +51,7 @@@
  #include <asm/pgtable.h>
  #include <asm/tlbflush.h>
  #include <asm/reboot.h>
+ #include <asm/stackprotector.h>
  
  #include "xen-ops.h"
  #include "mmu.h"
@@@ -330,18 -331,28 +331,28 @@@ static void xen_load_gdt(const struct d
        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.. */
+       /*
+        * 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);
+               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);
                BUG();
  }
  
+ /*
+  * load_gdt for early boot, when the gdt is only mapped once
+  */
+ static __init void 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();
+ }
  static void load_TLS_descriptor(struct thread_struct *t,
                                unsigned int cpu, unsigned int i)
  {
@@@ -581,6 -630,29 +630,29 @@@ static void xen_write_gdt_entry(struct 
        preempt_enable();
  }
  
+ /*
+  * Version of write_gdt_entry for use at early boot-time needed to
+  * update an entry as simply as possible.
+  */
+ static __init void xen_write_gdt_entry_boot(struct desc_struct *dt, int entry,
+                                           const void *desc, int type)
+ {
+       switch (type) {
+       case DESC_LDT:
+       case DESC_TSS:
+               /* ignore */
+               break;
+       default: {
+               xmaddr_t maddr = virt_to_machine(&dt[entry]);
+               if (HYPERVISOR_update_descriptor(maddr.maddr, *(u64 *)desc))
+                       dt[entry] = *(struct desc_struct *)desc;
+       }
+       }
+ }
  static void xen_load_sp0(struct tss_struct *tss,
                         struct thread_struct *thread)
  {
@@@ -714,7 -786,7 +786,7 @@@ static int xen_write_msr_safe(unsigned 
        set:
                base = ((u64)high << 32) | low;
                if (HYPERVISOR_set_segment_base(which, base) != 0)
 -                      ret = -EFAULT;
 +                      ret = -EIO;
                break;
  #endif
  
@@@ -965,6 -1037,23 +1037,23 @@@ static const struct machine_ops __initd
        .emergency_restart = xen_emergency_restart,
  };
  
+ /*
+  * Set up the GDT and segment registers for -fstack-protector.  Until
+  * we do this, we have to be careful not to call any stack-protected
+  * function, which is most of the kernel.
+  */
+ static void __init xen_setup_stackprotector(void)
+ {
+       pv_cpu_ops.write_gdt_entry = xen_write_gdt_entry_boot;
+       pv_cpu_ops.load_gdt = xen_load_gdt_boot;
+       setup_stack_canary_segment(0);
+       switch_to_new_gdt(0);
+       pv_cpu_ops.write_gdt_entry = xen_write_gdt_entry;
+       pv_cpu_ops.load_gdt = xen_load_gdt;
+ }
  /* First C function to be called on Xen boot */
  asmlinkage void __init xen_start_kernel(void)
  {
        pv_apic_ops = xen_apic_ops;
        pv_mmu_ops = xen_mmu_ops;
  
- #ifdef CONFIG_X86_64
        /*
-        * Setup percpu state.  We only need to do this for 64-bit
-        * because 32-bit already has %fs set properly.
+        * Set up some pagetable state before starting to set any ptes.
         */
-       load_percpu_segment(0);
- #endif
+       /* Prevent unwanted bits from being set in PTEs. */
+       __supported_pte_mask &= ~_PAGE_GLOBAL;
+       if (!xen_initial_domain())
+               __supported_pte_mask &= ~(_PAGE_PWT | _PAGE_PCD);
+       __supported_pte_mask |= _PAGE_IOMAP;
+       xen_setup_features();
+       /* Get mfn list */
+       if (!xen_feature(XENFEAT_auto_translated_physmap))
+               xen_build_dynamic_phys_to_machine();
+       /*
+        * Set up kernel GDT and segment registers, mainly so that
+        * -fstack-protector code can be executed.
+        */
+       xen_setup_stackprotector();
  
        xen_init_irq_ops();
        xen_init_cpuid_mask();
        set_xen_basic_apic_ops();
  #endif
  
-       xen_setup_features();
        if (xen_feature(XENFEAT_mmu_pt_update_preserve_ad)) {
                pv_mmu_ops.ptep_modify_prot_start = xen_ptep_modify_prot_start;
                pv_mmu_ops.ptep_modify_prot_commit = xen_ptep_modify_prot_commit;
  
        xen_smp_init();
  
-       /* Get mfn list */
-       if (!xen_feature(XENFEAT_auto_translated_physmap))
-               xen_build_dynamic_phys_to_machine();
        pgd = (pgd_t *)xen_start_info->pt_base;
  
-       /* Prevent unwanted bits from being set in PTEs. */
-       __supported_pte_mask &= ~_PAGE_GLOBAL;
-       if (!xen_initial_domain())
-               __supported_pte_mask &= ~(_PAGE_PWT | _PAGE_PCD);
  #ifdef CONFIG_X86_64
        /* Work out if we support NX */
        check_efer();