Merge branch 'linus' into x86/asm, before applying dependent patch
authorIngo Molnar <mingo@kernel.org>
Fri, 8 May 2015 11:33:33 +0000 (13:33 +0200)
committerIngo Molnar <mingo@kernel.org>
Fri, 8 May 2015 11:33:33 +0000 (13:33 +0200)
Signed-off-by: Ingo Molnar <mingo@kernel.org>
1  2 
arch/x86/Makefile
arch/x86/ia32/ia32entry.S
arch/x86/include/asm/paravirt_types.h
arch/x86/kernel/entry_64.S
arch/x86/kernel/paravirt.c
arch/x86/xen/enlighten.c

diff --combined arch/x86/Makefile
@@@ -63,7 -63,7 +63,7 @@@ ifeq ($(CONFIG_X86_32),y
                                $(call cc-option,-fno-unit-at-a-time))
  
          # CPU-specific tuning. Anything which can be shared with UML should go here.
-         include $(srctree)/arch/x86/Makefile_32.cpu
+         include arch/x86/Makefile_32.cpu
          KBUILD_CFLAGS += $(cflags-y)
  
          # temporary until string.h is fixed
@@@ -84,9 -84,6 +84,9 @@@ els
        # Use -mpreferred-stack-boundary=3 if supported.
        KBUILD_CFLAGS += $(call cc-option,-mpreferred-stack-boundary=3)
  
 +      # Use -mskip-rax-setup if supported.
 +      KBUILD_CFLAGS += $(call cc-option,-mskip-rax-setup)
 +
          # FIXME - should be integrated in Makefile.cpu (Makefile_32.cpu)
          cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8)
          cflags-$(CONFIG_MPSC) += $(call cc-option,-march=nocona)
@@@ -77,6 -77,12 +77,6 @@@ ENTRY(native_usergs_sysret32
        swapgs
        sysretl
  ENDPROC(native_usergs_sysret32)
 -
 -ENTRY(native_irq_enable_sysexit)
 -      swapgs
 -      sti
 -      sysexit
 -ENDPROC(native_irq_enable_sysexit)
  #endif
  
  /*
@@@ -136,7 -142,7 +136,7 @@@ ENTRY(ia32_sysenter_target
        pushq_cfi_reg   rsi                     /* pt_regs->si */
        pushq_cfi_reg   rdx                     /* pt_regs->dx */
        pushq_cfi_reg   rcx                     /* pt_regs->cx */
 -      pushq_cfi_reg   rax                     /* pt_regs->ax */
 +      pushq_cfi       $-ENOSYS                /* pt_regs->ax */
        cld
        sub     $(10*8),%rsp /* pt_regs->r8-11,bp,bx,r12-15 not saved */
        CFI_ADJUST_CFA_OFFSET 10*8
@@@ -163,6 -169,8 +163,6 @@@ sysenter_flags_fixed
        testl   $_TIF_WORK_SYSCALL_ENTRY, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
        CFI_REMEMBER_STATE
        jnz  sysenter_tracesys
 -      cmpq    $(IA32_NR_syscalls-1),%rax
 -      ja      ia32_badsys
  sysenter_do_call:
        /* 32bit syscall -> 64bit C ABI argument conversion */
        movl    %edi,%r8d       /* arg5 */
        movl    %ebx,%edi       /* arg1 */
        movl    %edx,%edx       /* arg3 (zero extension) */
  sysenter_dispatch:
 +      cmpq    $(IA32_NR_syscalls-1),%rax
 +      ja      1f
        call    *ia32_sys_call_table(,%rax,8)
        movq    %rax,RAX(%rsp)
 +1:
        DISABLE_INTERRUPTS(CLBR_NONE)
        TRACE_IRQS_OFF
        testl   $_TIF_ALLWORK_MASK, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
@@@ -242,7 -247,9 +242,7 @@@ sysexit_from_sys_call
        movl %ebx,%esi                  /* 2nd arg: 1st syscall arg */
        movl %eax,%edi                  /* 1st arg: syscall number */
        call __audit_syscall_entry
 -      movl RAX(%rsp),%eax     /* reload syscall number */
 -      cmpq $(IA32_NR_syscalls-1),%rax
 -      ja ia32_badsys
 +      movl ORIG_RAX(%rsp),%eax        /* reload syscall number */
        movl %ebx,%edi                  /* reload 1st syscall arg */
        movl RCX(%rsp),%esi     /* reload 2nd syscall arg */
        movl RDX(%rsp),%edx     /* reload 3rd syscall arg */
@@@ -293,10 -300,13 +293,10 @@@ sysenter_tracesys
  #endif
        SAVE_EXTRA_REGS
        CLEAR_RREGS
 -      movq    $-ENOSYS,RAX(%rsp)/* ptrace can change this for a bad syscall */
        movq    %rsp,%rdi        /* &pt_regs -> arg1 */
        call    syscall_trace_enter
        LOAD_ARGS32  /* reload args from stack in case ptrace changed it */
        RESTORE_EXTRA_REGS
 -      cmpq    $(IA32_NR_syscalls-1),%rax
 -      ja      int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */
        jmp     sysenter_do_call
        CFI_ENDPROC
  ENDPROC(ia32_sysenter_target)
@@@ -366,7 -376,7 +366,7 @@@ ENTRY(ia32_cstar_target
        pushq_cfi_reg   rdx                     /* pt_regs->dx */
        pushq_cfi_reg   rbp                     /* pt_regs->cx */
        movl    %ebp,%ecx
 -      pushq_cfi_reg   rax                     /* pt_regs->ax */
 +      pushq_cfi       $-ENOSYS                /* pt_regs->ax */
        sub     $(10*8),%rsp /* pt_regs->r8-11,bp,bx,r12-15 not saved */
        CFI_ADJUST_CFA_OFFSET 10*8
  
        testl   $_TIF_WORK_SYSCALL_ENTRY, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
        CFI_REMEMBER_STATE
        jnz   cstar_tracesys
 -      cmpq $IA32_NR_syscalls-1,%rax
 -      ja  ia32_badsys
  cstar_do_call:
        /* 32bit syscall -> 64bit C ABI argument conversion */
        movl    %edi,%r8d       /* arg5 */
        movl    %ebx,%edi       /* arg1 */
        movl    %edx,%edx       /* arg3 (zero extension) */
  cstar_dispatch:
 +      cmpq    $(IA32_NR_syscalls-1),%rax
 +      ja      1f
        call *ia32_sys_call_table(,%rax,8)
        movq %rax,RAX(%rsp)
 +1:
        DISABLE_INTERRUPTS(CLBR_NONE)
        TRACE_IRQS_OFF
        testl $_TIF_ALLWORK_MASK, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
@@@ -418,6 -427,13 +418,13 @@@ sysretl_from_sys_call
         * cs and ss are loaded from MSRs.
         * (Note: 32bit->32bit SYSRET is different: since r11
         * does not exist, it merely sets eflags.IF=1).
+        *
+        * NB: On AMD CPUs with the X86_BUG_SYSRET_SS_ATTRS bug, the ss
+        * descriptor is not reinitialized.  This means that we must
+        * avoid SYSRET with SS == NULL, which could happen if we schedule,
+        * exit the kernel, and re-enter using an interrupt vector.  (All
+        * interrupt entries on x86_64 set SS to NULL.)  We prevent that
+        * from happening by reloading SS in __switch_to.
         */
        USERGS_SYSRET32
  
@@@ -441,11 -457,14 +448,11 @@@ cstar_tracesys
        xchgl %r9d,%ebp
        SAVE_EXTRA_REGS
        CLEAR_RREGS r9
 -      movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
        movq %rsp,%rdi        /* &pt_regs -> arg1 */
        call syscall_trace_enter
        LOAD_ARGS32 1   /* reload args from stack in case ptrace changed it */
        RESTORE_EXTRA_REGS
        xchgl %ebp,%r9d
 -      cmpq $(IA32_NR_syscalls-1),%rax
 -      ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */
        jmp cstar_do_call
  END(ia32_cstar_target)
                                
@@@ -504,7 -523,7 +511,7 @@@ ENTRY(ia32_syscall
        pushq_cfi_reg   rsi                     /* pt_regs->si */
        pushq_cfi_reg   rdx                     /* pt_regs->dx */
        pushq_cfi_reg   rcx                     /* pt_regs->cx */
 -      pushq_cfi_reg   rax                     /* pt_regs->ax */
 +      pushq_cfi       $-ENOSYS                /* pt_regs->ax */
        cld
        sub     $(10*8),%rsp /* pt_regs->r8-11,bp,bx,r12-15 not saved */
        CFI_ADJUST_CFA_OFFSET 10*8
        orl $TS_COMPAT, ASM_THREAD_INFO(TI_status, %rsp, SIZEOF_PTREGS)
        testl $_TIF_WORK_SYSCALL_ENTRY, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
        jnz ia32_tracesys
 -      cmpq $(IA32_NR_syscalls-1),%rax
 -      ja ia32_badsys
  ia32_do_call:
        /* 32bit syscall -> 64bit C ABI argument conversion */
        movl %edi,%r8d  /* arg5 */
        xchg %ecx,%esi  /* rsi:arg2, rcx:arg4 */
        movl %ebx,%edi  /* arg1 */
        movl %edx,%edx  /* arg3 (zero extension) */
 +      cmpq    $(IA32_NR_syscalls-1),%rax
 +      ja      1f
        call *ia32_sys_call_table(,%rax,8) # xxx: rip relative
  ia32_sysret:
        movq %rax,RAX(%rsp)
 +1:
  ia32_ret_from_sys_call:
        CLEAR_RREGS
        jmp int_ret_from_sys_call
  ia32_tracesys:
        SAVE_EXTRA_REGS
        CLEAR_RREGS
 -      movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
        movq %rsp,%rdi        /* &pt_regs -> arg1 */
        call syscall_trace_enter
        LOAD_ARGS32     /* reload args from stack in case ptrace changed it */
        RESTORE_EXTRA_REGS
 -      cmpq $(IA32_NR_syscalls-1),%rax
 -      ja  int_ret_from_sys_call       /* ia32_tracesys has set RAX(%rsp) */
        jmp ia32_do_call
 +      CFI_ENDPROC
  END(ia32_syscall)
  
 -ia32_badsys:
 -      movq $0,ORIG_RAX(%rsp)
 -      movq $-ENOSYS,%rax
 -      jmp ia32_sysret
 -
 -      CFI_ENDPROC
 -      
        .macro PTREGSCALL label, func
        ALIGN
  GLOBAL(\label)
@@@ -160,14 -160,13 +160,14 @@@ struct pv_cpu_ops 
        u64 (*read_pmc)(int counter);
        unsigned long long (*read_tscp)(unsigned int *aux);
  
 +#ifdef CONFIG_X86_32
        /*
         * Atomically enable interrupts and return to userspace.  This
 -       * is only ever used to return to 32-bit processes; in a
 -       * 64-bit kernel, it's used for 32-on-64 compat processes, but
 -       * never native 64-bit processes.  (Jump, not call.)
 +       * is only used in 32-bit kernels.  64-bit kernels use
 +       * usergs_sysret32 instead.
         */
        void (*irq_enable_sysexit)(void);
 +#endif
  
        /*
         * Switch to usermode gs and return to 64-bit usermode using
@@@ -295,7 -294,7 +295,7 @@@ struct pv_mmu_ops 
        struct paravirt_callee_save pgd_val;
        struct paravirt_callee_save make_pgd;
  
- #if PAGETABLE_LEVELS >= 3
+ #if CONFIG_PGTABLE_LEVELS >= 3
  #ifdef CONFIG_X86_PAE
        void (*set_pte_atomic)(pte_t *ptep, pte_t pteval);
        void (*pte_clear)(struct mm_struct *mm, unsigned long addr,
        struct paravirt_callee_save pmd_val;
        struct paravirt_callee_save make_pmd;
  
- #if PAGETABLE_LEVELS == 4
+ #if CONFIG_PGTABLE_LEVELS == 4
        struct paravirt_callee_save pud_val;
        struct paravirt_callee_save make_pud;
  
        void (*set_pgd)(pgd_t *pudp, pgd_t pgdval);
- #endif        /* PAGETABLE_LEVELS == 4 */
- #endif        /* PAGETABLE_LEVELS >= 3 */
+ #endif        /* CONFIG_PGTABLE_LEVELS == 4 */
+ #endif        /* CONFIG_PGTABLE_LEVELS >= 3 */
  
        struct pv_lazy_ops lazy_mode;
  
@@@ -295,6 -295,15 +295,15 @@@ system_call_fastpath
         * rflags from r11 (but RF and VM bits are forced to 0),
         * cs and ss are loaded from MSRs.
         * Restoration of rflags re-enables interrupts.
+        *
+        * NB: On AMD CPUs with the X86_BUG_SYSRET_SS_ATTRS bug, the ss
+        * descriptor is not reinitialized.  This means that we should
+        * avoid SYSRET with SS == NULL, which could happen if we schedule,
+        * exit the kernel, and re-enter using an interrupt vector.  (All
+        * interrupt entries on x86_64 set SS to NULL.)  We prevent that
+        * from happening by reloading SS in __switch_to.  (Actually
+        * detecting the failure in 64-bit userspace is tricky but can be
+        * done.)
         */
        USERGS_SYSRET64
  
@@@ -410,27 -419,26 +419,27 @@@ syscall_return
         * a completely clean 64-bit userspace context.
         */
        movq RCX(%rsp),%rcx
 -      cmpq %rcx,RIP(%rsp)             /* RCX == RIP */
 +      movq RIP(%rsp),%r11
 +      cmpq %rcx,%r11                  /* RCX == RIP */
        jne opportunistic_sysret_failed
  
        /*
         * On Intel CPUs, SYSRET with non-canonical RCX/RIP will #GP
         * in kernel space.  This essentially lets the user take over
 -       * the kernel, since userspace controls RSP.  It's not worth
 -       * testing for canonicalness exactly -- this check detects any
 -       * of the 17 high bits set, which is true for non-canonical
 -       * or kernel addresses.  (This will pessimize vsyscall=native.
 -       * Big deal.)
 +       * the kernel, since userspace controls RSP.
         *
 -       * If virtual addresses ever become wider, this will need
 +       * If width of "canonical tail" ever becomes variable, this will need
         * to be updated to remain correct on both old and new CPUs.
         */
        .ifne __VIRTUAL_MASK_SHIFT - 47
        .error "virtual address width changed -- SYSRET checks need update"
        .endif
 -      shr $__VIRTUAL_MASK_SHIFT, %rcx
 -      jnz opportunistic_sysret_failed
 +      /* Change top 16 bits to be the sign-extension of 47th bit */
 +      shl     $(64 - (__VIRTUAL_MASK_SHIFT+1)), %rcx
 +      sar     $(64 - (__VIRTUAL_MASK_SHIFT+1)), %rcx
 +      /* If this changed %rcx, it was not canonical */
 +      cmpq    %rcx, %r11
 +      jne     opportunistic_sysret_failed
  
        cmpq $__USER_CS,CS(%rsp)        /* CS must match SYSRET */
        jne opportunistic_sysret_failed
         */
  syscall_return_via_sysret:
        CFI_REMEMBER_STATE
 -      /* r11 is already restored (see code above) */
 -      RESTORE_C_REGS_EXCEPT_R11
 +      /* rcx and r11 are already restored (see code above) */
 +      RESTORE_C_REGS_EXCEPT_RCX_R11
        movq RSP(%rsp),%rsp
        USERGS_SYSRET64
        CFI_RESTORE_STATE
@@@ -525,27 -533,40 +534,27 @@@ GLOBAL(stub_execveat
        CFI_ENDPROC
  END(stub_execveat)
  
 -#ifdef CONFIG_X86_X32_ABI
 +#if defined(CONFIG_X86_X32_ABI) || defined(CONFIG_IA32_EMULATION)
        .align  8
  GLOBAL(stub_x32_execve)
 +GLOBAL(stub32_execve)
        CFI_STARTPROC
        DEFAULT_FRAME 0, 8
        call    compat_sys_execve
        jmp     return_from_execve
        CFI_ENDPROC
 +END(stub32_execve)
  END(stub_x32_execve)
        .align  8
  GLOBAL(stub_x32_execveat)
 -      CFI_STARTPROC
 -      DEFAULT_FRAME 0, 8
 -      call    compat_sys_execveat
 -      jmp     return_from_execve
 -      CFI_ENDPROC
 -END(stub_x32_execveat)
 -#endif
 -
 -#ifdef CONFIG_IA32_EMULATION
 -      .align  8
 -GLOBAL(stub32_execve)
 -      CFI_STARTPROC
 -      call    compat_sys_execve
 -      jmp     return_from_execve
 -      CFI_ENDPROC
 -END(stub32_execve)
 -      .align  8
  GLOBAL(stub32_execveat)
        CFI_STARTPROC
 +      DEFAULT_FRAME 0, 8
        call    compat_sys_execveat
        jmp     return_from_execve
        CFI_ENDPROC
  END(stub32_execveat)
 +END(stub_x32_execveat)
  #endif
  
  /*
@@@ -601,7 -622,7 +610,7 @@@ ENTRY(ret_from_fork
  
        RESTORE_EXTRA_REGS
  
 -      testl $3,CS(%rsp)                       # from kernel_thread?
 +      testb   $3, CS(%rsp)                    # from kernel_thread?
  
        /*
         * By the time we get here, we have no idea whether our pt_regs,
@@@ -665,8 -686,8 +674,8 @@@ END(irq_entries_start
  
        leaq -RBP(%rsp),%rdi    /* arg1 for \func (pointer to pt_regs) */
  
 -      testl $3, CS-RBP(%rsp)
 -      je 1f
 +      testb   $3, CS-RBP(%rsp)
 +      jz      1f
        SWAPGS
  1:
        /*
@@@ -720,8 -741,8 +729,8 @@@ ret_from_intr
        CFI_DEF_CFA_REGISTER    rsp
        CFI_ADJUST_CFA_OFFSET   RBP
  
 -      testl $3,CS(%rsp)
 -      je retint_kernel
 +      testb   $3, CS(%rsp)
 +      jz      retint_kernel
        /* Interrupt came from user space */
  
        GET_THREAD_INFO(%rcx)
@@@ -968,7 -989,7 +977,7 @@@ ENTRY(\sym
        .if \paranoid
        .if \paranoid == 1
        CFI_REMEMBER_STATE
 -      testl $3, CS(%rsp)              /* If coming from userspace, switch */
 +      testb   $3, CS(%rsp)            /* If coming from userspace, switch */
        jnz 1f                          /* stacks. */
        .endif
        call paranoid_entry
@@@ -1309,8 -1330,8 +1318,8 @@@ ENTRY(error_entry
        SAVE_C_REGS 8
        SAVE_EXTRA_REGS 8
        xorl %ebx,%ebx
 -      testl $3,CS+8(%rsp)
 -      je error_kernelspace
 +      testb   $3, CS+8(%rsp)
 +      jz      error_kernelspace
  error_swapgs:
        SWAPGS
  error_sti:
@@@ -1361,7 -1382,7 +1370,7 @@@ ENTRY(error_exit
        TRACE_IRQS_OFF
        GET_THREAD_INFO(%rcx)
        testl %eax,%eax
 -      jne retint_kernel
 +      jnz retint_kernel
        LOCKDEP_SYS_EXIT_IRQ
        movl TI_flags(%rcx),%edx
        movl $_TIF_WORK_MASK,%edi
@@@ -1606,6 -1627,7 +1615,6 @@@ end_repeat_nmi
        je 1f
        movq %r12, %cr2
  1:
 -      
        testl %ebx,%ebx                         /* swapgs needed? */
        jnz nmi_restore
  nmi_swapgs:
@@@ -154,9 -154,7 +154,9 @@@ unsigned paravirt_patch_default(u8 type
                ret = paravirt_patch_ident_64(insnbuf, len);
  
        else if (type == PARAVIRT_PATCH(pv_cpu_ops.iret) ||
 +#ifdef CONFIG_X86_32
                 type == PARAVIRT_PATCH(pv_cpu_ops.irq_enable_sysexit) ||
 +#endif
                 type == PARAVIRT_PATCH(pv_cpu_ops.usergs_sysret32) ||
                 type == PARAVIRT_PATCH(pv_cpu_ops.usergs_sysret64))
                /* If operation requires a jmp, then jmp */
@@@ -373,7 -371,7 +373,7 @@@ __visible struct pv_cpu_ops pv_cpu_ops 
  
        .load_sp0 = native_load_sp0,
  
 -#if defined(CONFIG_X86_32) || defined(CONFIG_IA32_EMULATION)
 +#if defined(CONFIG_X86_32)
        .irq_enable_sysexit = native_irq_enable_sysexit,
  #endif
  #ifdef CONFIG_X86_64
@@@ -445,7 -443,7 +445,7 @@@ struct pv_mmu_ops pv_mmu_ops = 
        .ptep_modify_prot_start = __ptep_modify_prot_start,
        .ptep_modify_prot_commit = __ptep_modify_prot_commit,
  
- #if PAGETABLE_LEVELS >= 3
+ #if CONFIG_PGTABLE_LEVELS >= 3
  #ifdef CONFIG_X86_PAE
        .set_pte_atomic = native_set_pte_atomic,
        .pte_clear = native_pte_clear,
        .pmd_val = PTE_IDENT,
        .make_pmd = PTE_IDENT,
  
- #if PAGETABLE_LEVELS == 4
+ #if CONFIG_PGTABLE_LEVELS == 4
        .pud_val = PTE_IDENT,
        .make_pud = PTE_IDENT,
  
        .set_pgd = native_set_pgd,
  #endif
- #endif /* PAGETABLE_LEVELS >= 3 */
+ #endif /* CONFIG_PGTABLE_LEVELS >= 3 */
  
        .pte_val = PTE_IDENT,
        .pgd_val = PTE_IDENT,
diff --combined arch/x86/xen/enlighten.c
@@@ -928,92 -928,6 +928,6 @@@ static void xen_io_delay(void
  {
  }
  
- #ifdef CONFIG_X86_LOCAL_APIC
- static unsigned long xen_set_apic_id(unsigned int x)
- {
-       WARN_ON(1);
-       return x;
- }
- static unsigned int xen_get_apic_id(unsigned long x)
- {
-       return ((x)>>24) & 0xFFu;
- }
- static u32 xen_apic_read(u32 reg)
- {
-       struct xen_platform_op op = {
-               .cmd = XENPF_get_cpuinfo,
-               .interface_version = XENPF_INTERFACE_VERSION,
-               .u.pcpu_info.xen_cpuid = 0,
-       };
-       int ret = 0;
-       /* Shouldn't need this as APIC is turned off for PV, and we only
-        * get called on the bootup processor. But just in case. */
-       if (!xen_initial_domain() || smp_processor_id())
-               return 0;
-       if (reg == APIC_LVR)
-               return 0x10;
-       if (reg != APIC_ID)
-               return 0;
-       ret = HYPERVISOR_dom0_op(&op);
-       if (ret)
-               return 0;
-       return op.u.pcpu_info.apic_id << 24;
- }
- static void xen_apic_write(u32 reg, u32 val)
- {
-       /* Warn to see if there's any stray references */
-       WARN_ON(1);
- }
- static u64 xen_apic_icr_read(void)
- {
-       return 0;
- }
- static void xen_apic_icr_write(u32 low, u32 id)
- {
-       /* Warn to see if there's any stray references */
-       WARN_ON(1);
- }
- static void xen_apic_wait_icr_idle(void)
- {
-         return;
- }
- static u32 xen_safe_apic_wait_icr_idle(void)
- {
-         return 0;
- }
- static void set_xen_basic_apic_ops(void)
- {
-       apic->read = xen_apic_read;
-       apic->write = xen_apic_write;
-       apic->icr_read = xen_apic_icr_read;
-       apic->icr_write = xen_apic_icr_write;
-       apic->wait_icr_idle = xen_apic_wait_icr_idle;
-       apic->safe_wait_icr_idle = xen_safe_apic_wait_icr_idle;
-       apic->set_apic_id = xen_set_apic_id;
-       apic->get_apic_id = xen_get_apic_id;
- #ifdef CONFIG_SMP
-       apic->send_IPI_allbutself = xen_send_IPI_allbutself;
-       apic->send_IPI_mask_allbutself = xen_send_IPI_mask_allbutself;
-       apic->send_IPI_mask = xen_send_IPI_mask;
-       apic->send_IPI_all = xen_send_IPI_all;
-       apic->send_IPI_self = xen_send_IPI_self;
- #endif
- }
- #endif
  static void xen_clts(void)
  {
        struct multicall_space mcs;
@@@ -1267,11 -1181,10 +1181,11 @@@ static const struct pv_cpu_ops xen_cpu_
        .read_tscp = native_read_tscp,
  
        .iret = xen_iret,
 -      .irq_enable_sysexit = xen_sysexit,
  #ifdef CONFIG_X86_64
        .usergs_sysret32 = xen_sysret32,
        .usergs_sysret64 = xen_sysret64,
 +#else
 +      .irq_enable_sysexit = xen_sysexit,
  #endif
  
        .load_tr_desc = paravirt_nop,
@@@ -1620,7 -1533,7 +1534,7 @@@ asmlinkage __visible void __init xen_st
        /*
         * set up the basic apic ops.
         */
-       set_xen_basic_apic_ops();
+       xen_init_apic();
  #endif
  
        if (xen_feature(XENFEAT_mmu_pt_update_preserve_ad)) {
                if (HYPERVISOR_dom0_op(&op) == 0)
                        boot_params.kbd_status = op.u.firmware_info.u.kbd_shift_flags;
  
-               xen_init_apic();
                /* Make sure ACS will be enabled */
                pci_request_acs();
  
@@@ -1849,6 -1760,9 +1761,9 @@@ static struct notifier_block xen_hvm_cp
  
  static void __init xen_hvm_guest_init(void)
  {
+       if (xen_pv_domain())
+               return;
        init_hvm_pv_info();
  
        xen_hvm_init_shared_info();
        xen_hvm_init_time_ops();
        xen_hvm_init_mmu_ops();
  }
+ #endif
  
  static bool xen_nopv = false;
  static __init int xen_parse_nopv(char *arg)
  }
  early_param("xen_nopv", xen_parse_nopv);
  
- static uint32_t __init xen_hvm_platform(void)
+ static uint32_t __init xen_platform(void)
  {
        if (xen_nopv)
                return 0;
  
-       if (xen_pv_domain())
-               return 0;
        return xen_cpuid_base();
  }
  
@@@ -1898,11 -1810,19 +1811,19 @@@ bool xen_hvm_need_lapic(void
  }
  EXPORT_SYMBOL_GPL(xen_hvm_need_lapic);
  
- const struct hypervisor_x86 x86_hyper_xen_hvm __refconst = {
-       .name                   = "Xen HVM",
-       .detect                 = xen_hvm_platform,
+ static void xen_set_cpu_features(struct cpuinfo_x86 *c)
+ {
+       if (xen_pv_domain())
+               clear_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS);
+ }
+ const struct hypervisor_x86 x86_hyper_xen = {
+       .name                   = "Xen",
+       .detect                 = xen_platform,
+ #ifdef CONFIG_XEN_PVHVM
        .init_platform          = xen_hvm_guest_init,
+ #endif
        .x2apic_available       = xen_x2apic_para_available,
+       .set_cpu_features       = xen_set_cpu_features,
  };
- EXPORT_SYMBOL(x86_hyper_xen_hvm);
- #endif
+ EXPORT_SYMBOL(x86_hyper_xen);