mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-09-04 20:19:47 +08:00 
			
		
		
		
	 a2ef5dc2c7
			
		
	
	
		a2ef5dc2c7
		
	
	
	
	
		
			
			This fixes two bugs in PVH guests:
  - Not setting EFER.NX means the NX bit in page table entries is
    ignored on Intel processors and causes reserved bit page faults on
    AMD processors.
  - After the Xen commit 7645640d6ff1 ("x86/PVH: don't set EFER_SCE for
    pvh guest") PVH guests are required to set EFER.SCE to enable the
    SYSCALL instruction.
Secondary VCPUs are started with pagetables with the NX bit set so
EFER.NX must be set before using any stack or data segment.
xen_pvh_cpu_early_init() is the new secondary VCPU entry point that
sets EFER before jumping to cpu_bringup_and_idle().
Signed-off-by: Mukesh Rathor <mukesh.rathor@oracle.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Signed-off-by: David Vrabel <david.vrabel@citrix.com>
		
	
			
		
			
				
	
	
		
			167 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			167 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| /* Xen-specific pieces of head.S, intended to be included in the right
 | |
| 	place in head.S */
 | |
| 
 | |
| #ifdef CONFIG_XEN
 | |
| 
 | |
| #include <linux/elfnote.h>
 | |
| #include <linux/init.h>
 | |
| 
 | |
| #include <asm/boot.h>
 | |
| #include <asm/asm.h>
 | |
| #include <asm/page_types.h>
 | |
| 
 | |
| #include <xen/interface/elfnote.h>
 | |
| #include <xen/interface/features.h>
 | |
| #include <asm/xen/interface.h>
 | |
| 
 | |
| #ifdef CONFIG_XEN_PVH
 | |
| #define PVH_FEATURES_STR  "|writable_descriptor_tables|auto_translated_physmap|supervisor_mode_kernel"
 | |
| /* Note the lack of 'hvm_callback_vector'. Older hypervisor will
 | |
|  * balk at this being part of XEN_ELFNOTE_FEATURES, so we put it in
 | |
|  * XEN_ELFNOTE_SUPPORTED_FEATURES which older hypervisors will ignore.
 | |
|  */
 | |
| #define PVH_FEATURES ((1 << XENFEAT_writable_page_tables) | \
 | |
| 		      (1 << XENFEAT_auto_translated_physmap) | \
 | |
| 		      (1 << XENFEAT_supervisor_mode_kernel) | \
 | |
| 		      (1 << XENFEAT_hvm_callback_vector))
 | |
| /* The XENFEAT_writable_page_tables is not stricly neccessary as we set that
 | |
|  * up regardless whether this CONFIG option is enabled or not, but it
 | |
|  * clarifies what the right flags need to be.
 | |
|  */
 | |
| #else
 | |
| #define PVH_FEATURES_STR  ""
 | |
| #define PVH_FEATURES (0)
 | |
| #endif
 | |
| 
 | |
| 	__INIT
 | |
| ENTRY(startup_xen)
 | |
| 	cld
 | |
| #ifdef CONFIG_X86_32
 | |
| 	mov %esi,xen_start_info
 | |
| 	mov $init_thread_union+THREAD_SIZE,%esp
 | |
| #else
 | |
| 	mov %rsi,xen_start_info
 | |
| 	mov $init_thread_union+THREAD_SIZE,%rsp
 | |
| #endif
 | |
| 	jmp xen_start_kernel
 | |
| 
 | |
| 	__FINIT
 | |
| 
 | |
| #ifdef CONFIG_XEN_PVH
 | |
| /*
 | |
|  * xen_pvh_early_cpu_init() - early PVH VCPU initialization
 | |
|  * @cpu:   this cpu number (%rdi)
 | |
|  * @entry: true if this is a secondary vcpu coming up on this entry
 | |
|  *         point, false if this is the boot CPU being initialized for
 | |
|  *         the first time (%rsi)
 | |
|  *
 | |
|  * Note: This is called as a function on the boot CPU, and is the entry point
 | |
|  *       on the secondary CPU.
 | |
|  */
 | |
| ENTRY(xen_pvh_early_cpu_init)
 | |
| 	mov     %rsi, %r11
 | |
| 
 | |
| 	/* Gather features to see if NX implemented. */
 | |
| 	mov     $0x80000001, %eax
 | |
| 	cpuid
 | |
| 	mov     %edx, %esi
 | |
| 
 | |
| 	mov     $MSR_EFER, %ecx
 | |
| 	rdmsr
 | |
| 	bts     $_EFER_SCE, %eax
 | |
| 
 | |
| 	bt      $20, %esi
 | |
| 	jnc     1f      	/* No NX, skip setting it */
 | |
| 	bts     $_EFER_NX, %eax
 | |
| 1:	wrmsr
 | |
| #ifdef CONFIG_SMP
 | |
| 	cmp     $0, %r11b
 | |
| 	jne     cpu_bringup_and_idle
 | |
| #endif
 | |
| 	ret
 | |
| 
 | |
| #endif /* CONFIG_XEN_PVH */
 | |
| 
 | |
| .pushsection .text
 | |
| 	.balign PAGE_SIZE
 | |
| ENTRY(hypercall_page)
 | |
| #define NEXT_HYPERCALL(x) \
 | |
| 	ENTRY(xen_hypercall_##x) \
 | |
| 	.skip 32
 | |
| 
 | |
| NEXT_HYPERCALL(set_trap_table)
 | |
| NEXT_HYPERCALL(mmu_update)
 | |
| NEXT_HYPERCALL(set_gdt)
 | |
| NEXT_HYPERCALL(stack_switch)
 | |
| NEXT_HYPERCALL(set_callbacks)
 | |
| NEXT_HYPERCALL(fpu_taskswitch)
 | |
| NEXT_HYPERCALL(sched_op_compat)
 | |
| NEXT_HYPERCALL(platform_op)
 | |
| NEXT_HYPERCALL(set_debugreg)
 | |
| NEXT_HYPERCALL(get_debugreg)
 | |
| NEXT_HYPERCALL(update_descriptor)
 | |
| NEXT_HYPERCALL(ni)
 | |
| NEXT_HYPERCALL(memory_op)
 | |
| NEXT_HYPERCALL(multicall)
 | |
| NEXT_HYPERCALL(update_va_mapping)
 | |
| NEXT_HYPERCALL(set_timer_op)
 | |
| NEXT_HYPERCALL(event_channel_op_compat)
 | |
| NEXT_HYPERCALL(xen_version)
 | |
| NEXT_HYPERCALL(console_io)
 | |
| NEXT_HYPERCALL(physdev_op_compat)
 | |
| NEXT_HYPERCALL(grant_table_op)
 | |
| NEXT_HYPERCALL(vm_assist)
 | |
| NEXT_HYPERCALL(update_va_mapping_otherdomain)
 | |
| NEXT_HYPERCALL(iret)
 | |
| NEXT_HYPERCALL(vcpu_op)
 | |
| NEXT_HYPERCALL(set_segment_base)
 | |
| NEXT_HYPERCALL(mmuext_op)
 | |
| NEXT_HYPERCALL(xsm_op)
 | |
| NEXT_HYPERCALL(nmi_op)
 | |
| NEXT_HYPERCALL(sched_op)
 | |
| NEXT_HYPERCALL(callback_op)
 | |
| NEXT_HYPERCALL(xenoprof_op)
 | |
| NEXT_HYPERCALL(event_channel_op)
 | |
| NEXT_HYPERCALL(physdev_op)
 | |
| NEXT_HYPERCALL(hvm_op)
 | |
| NEXT_HYPERCALL(sysctl)
 | |
| NEXT_HYPERCALL(domctl)
 | |
| NEXT_HYPERCALL(kexec_op)
 | |
| NEXT_HYPERCALL(tmem_op) /* 38 */
 | |
| ENTRY(xen_hypercall_rsvr)
 | |
| 	.skip 320
 | |
| NEXT_HYPERCALL(mca) /* 48 */
 | |
| NEXT_HYPERCALL(arch_1)
 | |
| NEXT_HYPERCALL(arch_2)
 | |
| NEXT_HYPERCALL(arch_3)
 | |
| NEXT_HYPERCALL(arch_4)
 | |
| NEXT_HYPERCALL(arch_5)
 | |
| NEXT_HYPERCALL(arch_6)
 | |
| 	.balign PAGE_SIZE
 | |
| .popsection
 | |
| 
 | |
| 	ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS,       .asciz "linux")
 | |
| 	ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION,  .asciz "2.6")
 | |
| 	ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION,    .asciz "xen-3.0")
 | |
| #ifdef CONFIG_X86_32
 | |
| 	ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE,      _ASM_PTR __PAGE_OFFSET)
 | |
| #else
 | |
| 	ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE,      _ASM_PTR __START_KERNEL_map)
 | |
| #endif
 | |
| 	ELFNOTE(Xen, XEN_ELFNOTE_ENTRY,          _ASM_PTR startup_xen)
 | |
| 	ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, _ASM_PTR hypercall_page)
 | |
| 	ELFNOTE(Xen, XEN_ELFNOTE_FEATURES,       .ascii "!writable_page_tables|pae_pgdir_above_4gb"; .asciz PVH_FEATURES_STR)
 | |
| 	ELFNOTE(Xen, XEN_ELFNOTE_SUPPORTED_FEATURES, .long (PVH_FEATURES) |
 | |
| 						(1 << XENFEAT_writable_page_tables) |
 | |
| 						(1 << XENFEAT_dom0))
 | |
| 	ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE,       .asciz "yes")
 | |
| 	ELFNOTE(Xen, XEN_ELFNOTE_LOADER,         .asciz "generic")
 | |
| 	ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID,
 | |
| 		.quad _PAGE_PRESENT; .quad _PAGE_PRESENT)
 | |
| 	ELFNOTE(Xen, XEN_ELFNOTE_SUSPEND_CANCEL, .long 1)
 | |
| 	ELFNOTE(Xen, XEN_ELFNOTE_MOD_START_PFN,  .long 1)
 | |
| 	ELFNOTE(Xen, XEN_ELFNOTE_HV_START_LOW,   _ASM_PTR __HYPERVISOR_VIRT_START)
 | |
| 	ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   _ASM_PTR 0)
 | |
| 
 | |
| #endif /*CONFIG_XEN */
 |