Skip to contentSkip to conversation

Clean up asm/bugs.h, identify_cpu() and update COMPAT_VDSO

PATCH In review Jeremy Fitzhardinge 3 participants 10 messages Apr 6, 2007 – Apr 7, 2007

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover Clean up asm/bugs.h, identify_cpu() and update COMPAT_VDSO

Hi Andi,

Four patches:
- clean up asm/bugs.h, by moving all the C code into its own C file
- split identify_cpu() into boot and secondary variants, so that boot-time setup functions can be marked __init
- repost of the COMPAT_VDSO patches with a bit more robustness from unknown DT_tags, and functions marked __init, since all this is boot-time only setup.

Thanks,
J

#1 lore raw

PATCH 1/4 Clean up asm-i386/bugs.h

Most of asm-i386/bugs.h is code which should be in a C file, so put it there.

---
 arch/i386/kernel/cpu/Makefile  |    2 
 arch/i386/kernel/cpu/bugs.c    |  191 +++++++++++++++++++++++++++++++++++++++
 include/asm-i386/alternative.h |    1 
 include/asm-i386/bugs.h        |  194 ----------------------------------------
 4 files changed, 197 insertions(+), 191 deletions(-)

===================================================================

arch/i386/kernel/cpu/Makefile +1 -1
@@ -2,7 +2,7 @@
 # Makefile for x86-compatible CPU details and quirks
 #
 
-obj-y	:=	common.o proc.o
+obj-y	:=	common.o proc.o bugs.o
 
 obj-y	+=	amd.o
 obj-y	+=	cyrix.o

===================================================================

arch/i386/kernel/cpu/bugs.c new file +191 -0

191 lines not on this page · raw message

===================================================================

include/asm-i386/alternative.h +1 -0
@@ -14,6 +14,7 @@ struct alt_instr {
 	u8  pad;
 };
 
+extern void alternative_instructions(void);
 extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
 
 struct module;

===================================================================

include/asm-i386/bugs.h +4 -190

202 lines not on this page · raw message

#2 lore raw

PATCH 2/4 clean up identify_cpu

In reply to Jeremy Fitzhardinge

identify_cpu() is used to identify both the boot CPU and secondary CPUs, but it performs some actions which only apply to the boot CPU. Those functions are therefore really __init functions, but because they're called by identify_cpu(), they must be marked __cpuinit.

This patch splits identify_cpu() into identify_boot_cpu() and identify_secondary_cpu(), and calls the appropriate init functions from each. Also, identify_boot_cpu() and all the functions it dominates are marked __init.

---
 arch/i386/kernel/cpu/common.c    |   25 ++++++++++++++++---------
 arch/i386/kernel/cpu/mtrr/main.c |    4 ++--
 arch/i386/kernel/smpboot.c       |    2 +-
 arch/i386/kernel/sysenter.c      |    2 +-
 include/asm-i386/processor.h     |    3 ++-
 5 files changed, 22 insertions(+), 14 deletions(-)

===================================================================

arch/i386/kernel/cpu/common.c +16 -9
@@ -390,7 +390,7 @@ __setup("serialnumber", x86_serial_nr_se
 /*
  * This does the hard work of actually picking apart the CPU stuff...
  */
-void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
+static void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
 {
 	int i;
 
@@ -501,15 +501,22 @@ void __cpuinit identify_cpu(struct cpuin
 
 	/* Init Machine Check Exception if available. */
 	mcheck_init(c);
-
-	if (c == &boot_cpu_data)
-		sysenter_setup();
+}
+
+void __init identify_boot_cpu(void)
+{
+	identify_cpu(&boot_cpu_data);
+	sysenter_setup();
 	enable_sep_cpu();
-
-	if (c == &boot_cpu_data)
-		mtrr_bp_init();
-	else
-		mtrr_ap_init();
+	mtrr_bp_init();
+}
+
+void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c)
+{
+	BUG_ON(c == &boot_cpu_data);
+	identify_cpu(c);
+	enable_sep_cpu();
+	mtrr_ap_init();
 }
 
 #ifdef CONFIG_X86_HT

===================================================================

arch/i386/kernel/cpu/mtrr/main.c +2 -2
@@ -571,7 +571,7 @@ extern void cyrix_init_mtrr(void);
 extern void cyrix_init_mtrr(void);
 extern void centaur_init_mtrr(void);
 
-static void __cpuinit init_ifs(void)
+static void __init init_ifs(void)
 {
 #ifndef CONFIG_X86_64
 	amd_init_mtrr();
@@ -639,7 +639,7 @@ static struct sysdev_driver mtrr_sysdev_
  * initialized (i.e. before smp_init()).
  * 
  */
-void __cpuinit mtrr_bp_init(void)
+void __init mtrr_bp_init(void)
 {
 	init_ifs();
 

===================================================================

arch/i386/kernel/smpboot.c +1 -1
@@ -157,7 +157,7 @@ static void __cpuinit smp_store_cpu_info
 
 	*c = boot_cpu_data;
 	if (id!=0)
-		identify_cpu(c);
+		identify_secondary_cpu(c);
 	/*
 	 * Mask B, Pentium, but not Pentium MMX
 	 */

===================================================================

arch/i386/kernel/sysenter.c +1 -1
@@ -68,7 +68,7 @@ extern const char vsyscall_sysenter_star
 extern const char vsyscall_sysenter_start, vsyscall_sysenter_end;
 static struct page *syscall_pages[1];
 
-int __cpuinit sysenter_setup(void)
+int __init sysenter_setup(void)
 {
 	void *syscall_page = (void *)get_zeroed_page(GFP_ATOMIC);
 	syscall_pages[0] = virt_to_page(syscall_page);

===================================================================

include/asm-i386/processor.h +2 -1
@@ -116,7 +116,8 @@ extern char ignore_fpu_irq;
 
 void __init cpu_detect(struct cpuinfo_x86 *c);
 
-extern void identify_cpu(struct cpuinfo_x86 *);
+extern void identify_boot_cpu(void);
+extern void identify_secondary_cpu(struct cpuinfo_x86 *);
 extern void print_cpu_info(struct cpuinfo_x86 *);
 extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
 extern unsigned short num_cache_leaves;
#3 lore raw

Re: [patch 2/4] clean up identify_cpu

Quoted 9 lines · On Fri, 06 Apr 2007 15:41:54 -0700 Jeremy Fitzhardinge <[email protected]> wrote:

identify_cpu() is used to identify both the boot CPU and secondary CPUs, but it performs some actions which only apply to the boot CPU. Those functions are therefore really __init functions, but because they're called by identify_cpu(), they must be marked __cpuinit.

This patch splits identify_cpu() into identify_boot_cpu() and identify_secondary_cpu(), and calls the appropriate init functions from each. Also, identify_boot_cpu() and all the functions it dominates are marked __init.

x86_64 uses this too.

WARNING: arch/x86_64/kernel/built-in.o - Section mismatch: reference to .init.text:mtrr_bp_init from .text.identify_cpu after 'identify_cpu' (at offset 0x655)

#4 lore raw

Re: [patch 2/4] clean up identify_cpu

Quoted 4 lines · Andrew Morton

x86_64 uses this too.

WARNING: arch/x86_64/kernel/built-in.o - Section mismatch: reference to .init.text:mtrr_bp_init from .text.identify_cpu after 'identify_cpu' (at offset 0x655)

OK, two patches to follow: a x86-64 variant of the bugs.h cleanup, and a replacement for this patch. I don't have a x86-64 compile environment on hand, so the 64 bits are completely untested, but they *look* they should work.

J

#6 lore raw

Re: [patch 2/4] clean up identify_cpu

Quoted 6 lines · Andrew Morton
Quoted 2 lines · On Sat, 07 Apr 2007 10:20:17 -0700 Jeremy Fitzhardinge <[email protected]> wrote:

I don't have a x86-64 compile environment on
hand, so the 64 bits are completely untested

http://userweb.kernel.org/~akpm/cross-compilers/

Does the alpha toolchain work for you?

For defconfig I get:
CC arch/alpha/kernel/core_cia.o
{standard input}: Assembler messages:
{standard input}:351: Error: macro requires $at register while noat in effect {standard input}:376: Error: macro requires $at register while noat in effect {standard input}:400: Error: macro requires $at register while noat in effect {standard input}:419: Error: macro requires $at register while noat in effect {standard input}:474: Error: macro requires $at register while noat in effect {standard input}:499: Error: macro requires $at register while noat in effect {standard input}:523: Error: macro requires $at register while noat in effect {standard input}:542: Error: macro requires $at register while noat in effect make[2]: *** [arch/alpha/kernel/core_cia.o] Error 1
make[1]: *** [arch/alpha/kernel] Error 2
make: *** [_all] Error 2

Same happens when I compile the same version direct from Dan's crosstool.

Sam

#7 lore raw

Re: [patch 2/4] clean up identify_cpu

Quoted 9 lines · On Sat, 7 Apr 2007 20:39:16 +0200 Sam Ravnborg <[email protected]> wrote:
Quoted 6 lines · Andrew Morton
Quoted 2 lines · On Sat, 07 Apr 2007 10:20:17 -0700 Jeremy Fitzhardinge <[email protected]> wrote:

I don't have a x86-64 compile environment on
hand, so the 64 bits are completely untested

http://userweb.kernel.org/~akpm/cross-compilers/

Does the alpha toolchain work for you?

Seems not.

Quoted 15 lines

For defconfig I get:
CC arch/alpha/kernel/core_cia.o
{standard input}: Assembler messages:
{standard input}:351: Error: macro requires $at register while noat in effect {standard input}:376: Error: macro requires $at register while noat in effect {standard input}:400: Error: macro requires $at register while noat in effect {standard input}:419: Error: macro requires $at register while noat in effect {standard input}:474: Error: macro requires $at register while noat in effect {standard input}:499: Error: macro requires $at register while noat in effect {standard input}:523: Error: macro requires $at register while noat in effect {standard input}:542: Error: macro requires $at register while noat in effect make[2]: *** [arch/alpha/kernel/core_cia.o] Error 1
make[1]: *** [arch/alpha/kernel] Error 2
make: *** [_all] Error 2

Quoted 2 lines

Same happens when I compile the same version direct from Dan's crosstool.

Me too. I always do allmodconfig with alpha, and allmodconfig doesn't include that file.

#8 lore raw

PATCH 3/4 Relocate VDSO ELF headers to match mapped location with COMPAT_VDSO

In reply to Jeremy Fitzhardinge

Some versions of libc can't deal with a VDSO which doesn't have its ELF headers matching its mapped address. COMPAT_VDSO maps the VDSO at a specific system-wide fixed address. Previously this was all done at build time, on the grounds that the fixed VDSO address is always at the top of the address space. However, a hypervisor may reserve some of that address space, pushing the fixmap address down.

This patch does the adjustment dynamically at runtime, depending on the runtime location of the VDSO fixmap.

[ Patch has been through several hands: Jan Beulich wrote the orignal
version; Zach reworked it, and Jeremy converted it to relocate phdrs as well as sections. ]

Cc Zachary Amsden <[email protected]>
Cc "Jan Beulich" <[email protected]>
Cc Eric W. Biederman <[email protected]>
Cc Andi Kleen <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Roland McGrath <[email protected]>
---
 arch/i386/kernel/entry.S    |    4 -
 arch/i386/kernel/sysenter.c |  170 +++++++++++++++++++++++++++++++++++++++----
 arch/i386/mm/pgtable.c      |    6 -
 include/asm-i386/elf.h      |   28 ++-----
 include/asm-i386/fixmap.h   |    8 --
 include/linux/elf.h         |   17 ++++
 6 files changed, 184 insertions(+), 49 deletions(-)

===================================================================

arch/i386/kernel/entry.S +0 -4
@@ -305,16 +305,12 @@ sysenter_past_esp:
 	pushl $(__USER_CS)
 	CFI_ADJUST_CFA_OFFSET 4
 	/*CFI_REL_OFFSET cs, 0*/
-#ifndef CONFIG_COMPAT_VDSO
 	/*
 	 * Push current_thread_info()->sysenter_return to the stack.
 	 * A tiny bit of offset fixup is necessary - 4*4 means the 4 words
 	 * pushed above; +8 corresponds to copy_thread's esp0 setting.
 	 */
 	pushl (TI_sysenter_return-THREAD_SIZE+8+4*4)(%esp)
-#else
-	pushl $SYSENTER_RETURN
-#endif
 	CFI_ADJUST_CFA_OFFSET 4
 	CFI_REL_OFFSET eip, 0
 

===================================================================

arch/i386/kernel/sysenter.c +155 -15

200 lines not on this page · raw message

===================================================================

arch/i386/mm/pgtable.c +0 -6
@@ -144,10 +144,8 @@ void set_pmd_pfn(unsigned long vaddr, un
 }
 
 static int fixmaps;
-#ifndef CONFIG_COMPAT_VDSO
 unsigned long __FIXADDR_TOP = 0xfffff000;
 EXPORT_SYMBOL(__FIXADDR_TOP);
-#endif
 
 void __set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t flags)
 {
@@ -173,12 +171,8 @@ void reserve_top_address(unsigned long r
 	BUG_ON(fixmaps > 0);
 	printk(KERN_INFO "Reserving virtual address space above 0x%08x\n",
 	       (int)-reserve);
-#ifdef CONFIG_COMPAT_VDSO
-	BUG_ON(reserve != 0);
-#else
 	__FIXADDR_TOP = -reserve - PAGE_SIZE;
 	__VMALLOC_RESERVE += reserve;
-#endif
 }
 
 pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)

===================================================================

include/asm-i386/elf.h +10 -18
@@ -133,39 +133,31 @@ extern int dump_task_extended_fpu (struc
 #define ELF_CORE_COPY_XFPREGS(tsk, elf_xfpregs) dump_task_extended_fpu(tsk, elf_xfpregs)
 
 #define VDSO_HIGH_BASE		(__fix_to_virt(FIX_VDSO))
-#define VDSO_BASE		((unsigned long)current->mm->context.vdso)
-
-#ifdef CONFIG_COMPAT_VDSO
-# define VDSO_COMPAT_BASE	VDSO_HIGH_BASE
-# define VDSO_PRELINK		VDSO_HIGH_BASE
-#else
-# define VDSO_COMPAT_BASE	VDSO_BASE
-# define VDSO_PRELINK		0
-#endif
+#define VDSO_CURRENT_BASE	((unsigned long)current->mm->context.vdso)
+#define VDSO_PRELINK		0
 
 #define VDSO_SYM(x) \
-		(VDSO_COMPAT_BASE + (unsigned long)(x) - VDSO_PRELINK)
+		(VDSO_CURRENT_BASE + (unsigned long)(x) - VDSO_PRELINK)
 
 #define VDSO_HIGH_EHDR		((const struct elfhdr *) VDSO_HIGH_BASE)
-#define VDSO_EHDR		((const struct elfhdr *) VDSO_COMPAT_BASE)
+#define VDSO_EHDR		((const struct elfhdr *) VDSO_CURRENT_BASE)
 
 extern void __kernel_vsyscall;
 
 #define VDSO_ENTRY		VDSO_SYM(&__kernel_vsyscall)
 
-#ifndef CONFIG_COMPAT_VDSO
+struct linux_binprm;
+
 #define ARCH_HAS_SETUP_ADDITIONAL_PAGES
-struct linux_binprm;
 extern int arch_setup_additional_pages(struct linux_binprm *bprm,
                                        int executable_stack);
-#endif
 
 extern unsigned int vdso_enabled;
 
-#define ARCH_DLINFO						\
-do if (vdso_enabled) {						\
-		NEW_AUX_ENT(AT_SYSINFO,	VDSO_ENTRY);		\
-		NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_COMPAT_BASE);	\
+#define ARCH_DLINFO							\
+do if (vdso_enabled) {							\
+		NEW_AUX_ENT(AT_SYSINFO,	VDSO_ENTRY);			\
+		NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_CURRENT_BASE);	\
 } while (0)
 
 #endif

===================================================================

include/asm-i386/fixmap.h +2 -6
@@ -19,13 +19,9 @@
  * Leave one empty page between vmalloc'ed areas and
  * the start of the fixmap.
  */
-#ifndef CONFIG_COMPAT_VDSO
 extern unsigned long __FIXADDR_TOP;
-#else
-#define __FIXADDR_TOP  0xfffff000
-#define FIXADDR_USER_START	__fix_to_virt(FIX_VDSO)
-#define FIXADDR_USER_END	__fix_to_virt(FIX_VDSO - 1)
-#endif
+#define FIXADDR_USER_START     __fix_to_virt(FIX_VDSO)
+#define FIXADDR_USER_END       __fix_to_virt(FIX_VDSO - 1)
 
 #ifndef __ASSEMBLY__
 #include <linux/kernel.h>

===================================================================

include/linux/elf.h +17 -0
@@ -83,6 +83,23 @@ typedef __s64	Elf64_Sxword;
 #define DT_DEBUG	21
 #define DT_TEXTREL	22
 #define DT_JMPREL	23
+#define DT_ENCODING	32
+#define OLD_DT_LOOS	0x60000000
+#define DT_LOOS		0x6000000d
+#define DT_HIOS		0x6ffff000
+#define DT_VALRNGLO	0x6ffffd00
+#define DT_VALRNGHI	0x6ffffdff
+#define DT_ADDRRNGLO	0x6ffffe00
+#define DT_ADDRRNGHI	0x6ffffeff
+#define DT_VERSYM	0x6ffffff0
+#define DT_RELACOUNT	0x6ffffff9
+#define DT_RELCOUNT	0x6ffffffa
+#define DT_FLAGS_1	0x6ffffffb
+#define DT_VERDEF	0x6ffffffc
+#define	DT_VERDEFNUM	0x6ffffffd
+#define DT_VERNEED	0x6ffffffe
+#define	DT_VERNEEDNUM	0x6fffffff
+#define OLD_DT_HIOS     0x6fffffff
 #define DT_LOPROC	0x70000000
 #define DT_HIPROC	0x7fffffff
 
#9 lore raw

PATCH 4/4 Make COMPAT_VDSO runtime selectable.

In reply to Jeremy Fitzhardinge

Now that relocation of the VDSO for COMPAT_VDSO users is done at runtime rather than compile time, it is possible to enable/disable compat mode at runtime.

This patch allows you to enable COMPAT_VDSO mode with "vdso=2" on the kernel command line, or via sysctl. (Switching on a running system shouldn't be done lightly; any process which was relying on the compat VDSO will be upset if it goes away.)

The COMPAT_VDSO config option still exists, but if enabled it just makes vdso_enabled default to VDSO_COMPAT.

Cc Zachary Amsden <[email protected]>
Cc "Jan Beulich" <[email protected]>
Cc Eric W. Biederman <[email protected]>
Cc Andi Kleen <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Roland McGrath <[email protected]>
---
 Documentation/kernel-parameters.txt |    1 
 arch/i386/kernel/sysenter.c         |  141 +++++++++++++++++++++++------------
 include/asm-i386/page.h             |    2 
 3 files changed, 94 insertions(+), 50 deletions(-)

===================================================================

Documentation/kernel-parameters.txt +1 -0
@@ -1807,6 +1807,7 @@ and is between 256 and 4096 characters. 
 			[USBHID] The interval which mice are to be polled at.
 
 	vdso=		[IA-32,SH]
+			vdso=2: enable compat VDSO (default with COMPAT_VDSO)
 			vdso=1: enable VDSO (default)
 			vdso=0: disable VDSO mapping
 

===================================================================

arch/i386/kernel/sysenter.c +93 -48

210 lines not on this page · raw message

===================================================================

include/asm-i386/page.h +0 -2
@@ -143,9 +143,7 @@ extern int page_is_ram(unsigned long pag
 #include <asm-generic/memory_model.h>
 #include <asm-generic/page.h>
 
-#ifndef CONFIG_COMPAT_VDSO
 #define __HAVE_ARCH_GATE_AREA 1
-#endif
 #endif /* __KERNEL__ */
 
 #endif /* _I386_PAGE_H */