diff options
Diffstat (limited to 'arch/x86/include/asm/segment.h')
| -rw-r--r-- | arch/x86/include/asm/segment.h | 48 | 
1 files changed, 44 insertions, 4 deletions
| diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h index e293c122d0d5..ac3892920419 100644 --- a/arch/x86/include/asm/segment.h +++ b/arch/x86/include/asm/segment.h @@ -186,8 +186,7 @@  #define GDT_ENTRY_TLS_MIN		12  #define GDT_ENTRY_TLS_MAX		14 -/* Abused to load per CPU data from limit */ -#define GDT_ENTRY_PER_CPU		15 +#define GDT_ENTRY_CPUNODE		15  /*   * Number of entries in the GDT table: @@ -207,11 +206,11 @@  #define __USER_DS			(GDT_ENTRY_DEFAULT_USER_DS*8 + 3)  #define __USER32_DS			__USER_DS  #define __USER_CS			(GDT_ENTRY_DEFAULT_USER_CS*8 + 3) -#define __PER_CPU_SEG			(GDT_ENTRY_PER_CPU*8 + 3) +#define __CPUNODE_SEG			(GDT_ENTRY_CPUNODE*8 + 3)  #endif -#ifndef CONFIG_PARAVIRT +#ifndef CONFIG_PARAVIRT_XXL  # define get_kernel_rpl()		0  #endif @@ -225,6 +224,47 @@  #define GDT_ENTRY_TLS_ENTRIES		3  #define TLS_SIZE			(GDT_ENTRY_TLS_ENTRIES* 8) +#ifdef CONFIG_X86_64 + +/* Bit size and mask of CPU number stored in the per CPU data (and TSC_AUX) */ +#define VDSO_CPUNODE_BITS		12 +#define VDSO_CPUNODE_MASK		0xfff + +#ifndef __ASSEMBLY__ + +/* Helper functions to store/load CPU and node numbers */ + +static inline unsigned long vdso_encode_cpunode(int cpu, unsigned long node) +{ +	return (node << VDSO_CPUNODE_BITS) | cpu; +} + +static inline void vdso_read_cpunode(unsigned *cpu, unsigned *node) +{ +	unsigned int p; + +	/* +	 * Load CPU and node number from the GDT.  LSL is faster than RDTSCP +	 * and works on all CPUs.  This is volatile so that it orders +	 * correctly with respect to barrier() and to keep GCC from cleverly +	 * hoisting it out of the calling function. +	 * +	 * If RDPID is available, use it. +	 */ +	alternative_io ("lsl %[seg],%[p]", +			".byte 0xf3,0x0f,0xc7,0xf8", /* RDPID %eax/rax */ +			X86_FEATURE_RDPID, +			[p] "=a" (p), [seg] "r" (__CPUNODE_SEG)); + +	if (cpu) +		*cpu = (p & VDSO_CPUNODE_MASK); +	if (node) +		*node = (p >> VDSO_CPUNODE_BITS); +} + +#endif /* !__ASSEMBLY__ */ +#endif /* CONFIG_X86_64 */ +  #ifdef __KERNEL__  /* |