x86 updates for 2.6.22-stable
cover x86 updates for 2.6.22-stable
Should all go into the next stable release.
Two of the patches (cfi probe and rept fix) are only pending for mainline (I hope Linus applies them today). They should not go in before hitting mainline.
-Andi
PATCH 1/5 i386: allow debuggers to access the vsyscall page with compat vDSO
From: "Jan Beulich" <[email protected]>
arch/i386/kernel/sysenter.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
arch/i386/kernel/sysenter.c +3 -1
@@ -336,7 +336,9 @@ struct vm_area_struct *get_gate_vma(struint in_gate_area (struct task_struct *task,unsigned long addr) { -return 0 ; +const struct vm_area_struct *vma =get_gate_vma (task); + +return vma && addr >= vma->vm_start && addr < vma->vm_end; }int in_gate_area_no_task (unsigned long addr)
PATCH 2/5 x86_64: Check for .cfi_rel_offset in CFI probe
In reply to Andi KleenVery old binutils have .cfi_startproc/endproc, but no .cfi_rel_offset. Check for .cfi_rel_offset too.
--- arch/i386/Makefile | 4 ++-- arch/x86_64/Makefile | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-)
arch/x86_64/Makefile +2 -2
@@ -57,8 +57,8 @@ cflags-y += $(call cc-option,-mno-sse -m cflags-y += -maccumulate-outgoing-args # do binutils support CFI? -cflags-y += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,) -AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,) +cflags-y += $(call as-instr,.cfi_startproc\n.cfi_rel_offset rsp${comma}0\n.cfi_endproc,-DCONFIG_AS_CFI=1,) +AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_rel_offset rsp${comma}0\n.cfi_endproc,-DCONFIG_AS_CFI=1,) # is .cfi_signal_frame supported too? cflags-y += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,)
arch/i386/Makefile +2 -2
@@ -51,8 +51,8 @@ cflags-y += -maccumulate-outgoing-args CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then echo $(call cc-option,-fno-unit-at-a-time); fi ;) # do binutils support CFI? -cflags-y += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,) -AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,) +cflags-y += $(call as-instr,.cfi_startproc\n.cfi_rel_offset esp${comma}0\n.cfi_endproc,-DCONFIG_AS_CFI=1,) +AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_rel_offset esp${comma}0\n.cfi_endproc,-DCONFIG_AS_CFI=1,) # is .cfi_signal_frame supported too? cflags-y += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,)
PATCH 3/5 x86_64: Change PMDS invocation to single macro
In reply to Andi KleenVery old binutils (2.12.90...) seem to have trouble with newlines in assembler macro invocation. They put them into the resulting argument expansion. In this case this lead to a parse error because a .rept expression ended up spread over multiple lines. Change the PMDS() invocation to a single line.
--- arch/x86_64/kernel/head.S | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
arch/x86_64/kernel/head.S +1 -2
@@ -326,8 +326,7 @@ NEXT_PAGE(level2_kernel_pgt) /* 40MB kernel mapping. The kernel code cannot be bigger than that. When you change this change KERNEL_TEXT_SIZE in page.h too. */ /* (2^48-(2*1024*1024*1024)-((2^39)*511)-((2^30)*510)) = 0 */ - PMDS(0x0000000000000000, __PAGE_KERNEL_LARGE_EXEC|_PAGE_GLOBAL, - KERNEL_TEXT_SIZE/PMD_SIZE) + PMDS(0x0000000000000000, __PAGE_KERNEL_LARGE_EXEC|_PAGE_GLOBAL, KERNEL_TEXT_SIZE/PMD_SIZE) /* Module mapping starts here */ .fill (PTRS_PER_PMD - (KERNEL_TEXT_SIZE/PMD_SIZE)),8,0
PATCH 4/5 i386: Fix double fault handler
In reply to Andi KleenFrom: Chuck Ebbert <[email protected]>
The new percpu code has apparently broken the doublefault handler when CONFIG_DEBUG_SPINLOCK is set. Doublefault is handled by a hardware task, making the check
SPIN_BUG_ON(lock->owner == current, lock, "recursion");
fault because it uses the FS register to access the percpu data for current, and that register is zero in the new TSS. (The trace I saw was on 2.6.20 where it was GS, but it looks like this will still happen with FS on 2.6.22.)
Initializing FS in the doublefault_tss should fix it.
AK: Also fix broken ptr_ok() and turn printks into KERN_EMERG
AK: And add a PANIC prefix to make clear the system will hang
AK: (e.g. x86-64 will recover)
arch/i386/kernel/doublefault.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
arch/i386/kernel/doublefault.c +7 -6
@@ -13,7 +13,7 @@static unsigned long doublefault_stack[DOUBLEFAULT_STACKSIZE ];#define STACK_START (unsigned long)(doublefault_stack+DOUBLEFAULT_STACKSIZE) -#define ptr_ok (x) ((x) > PAGE_OFFSET && (x) < PAGE_OFFSET + 0x1000000) +#define ptr_ok (x) ((x) > PAGE_OFFSET && (x) < PAGE_OFFSET + MAXMEM)static void doublefault_fn (void ) {
@@ -23,23 +23,23 @@ static void doublefault_fn(void)store_gdt (&gdt_desc); gdt = gdt_desc.address; -printk ("double fault, gdt at %08lx [%d bytes]\n" , gdt, gdt_desc.size); +printk (KERN_EMERG "PANIC: double fault, gdt at %08lx [%d bytes]\n" , gdt, gdt_desc.size);if (ptr_ok (gdt)) { gdt +=GDT_ENTRY_TSS <<3 ; tss = *(u16 *)(gdt+2 ); tss += *(u8 *)(gdt+4 ) <<16 ; tss += *(u8 *)(gdt+7 ) <<24 ; -printk ("double fault, tss at %08lx\n" , tss); +printk (KERN_EMERG "double fault, tss at %08lx\n" , tss);if (ptr_ok (tss)) {struct i386_hw_tss *t = (struct i386_hw_tss *)tss; -printk ("eip = %08lx, esp = %08lx\n" , t->eip, t->esp); +printk (KERN_EMERG "eip = %08lx, esp = %08lx\n" , t->eip, t->esp); -printk ("eax = %08lx, ebx = %08lx, ecx = %08lx, edx = %08lx\n" , +printk (KERN_EMERG "eax = %08lx, ebx = %08lx, ecx = %08lx, edx = %08lx\n" , t->eax, t->ebx, t->ecx, t->edx); -printk ("esi = %08lx, edi = %08lx\n" , +printk (KERN_EMERG "esi = %08lx, edi = %08lx\n" , t->esi, t->edi); } }
@@ -63,6 +63,7 @@ struct tss_struct doublefault_tss __cach .cs = __KERNEL_CS, .ss = __KERNEL_DS, .ds = __USER_DS, + .fs = __KERNEL_PERCPU, .__cr3 =__pa (swapper_pg_dir) }
PATCH 5/5 i386: Handle P6s without performance counters in nmi watchdog
In reply to Andi KleenI got an oops while booting a 32bit kernel on KVM because it doesn't implement performance counters used by the NMI watchdog. Handle this case.
--- arch/i386/kernel/cpu/perfctr-watchdog.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
arch/i386/kernel/cpu/perfctr-watchdog.c +3 -1
@@ -346,7 +346,9 @@ static int setup_p6_watchdog(unsigned nm perfctr_msr =MSR_P6_PERFCTR0 ; evntsel_msr =MSR_P6_EVNTSEL0 ; -wrmsrl (perfctr_msr,0UL ); +/* KVM doesn't implement this MSR */ +if (wrmsr_safe (perfctr_msr,0 ,0 ) <0 ) +return 0 ; evntsel =P6_EVNTSEL_INT |P6_EVNTSEL_OS