Commit 5d6aaf3f authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://one.firstfloor.org/home/andi/git/linux-2.6

* 'for-linus' of git://one.firstfloor.org/home/andi/git/linux-2.6:
  [PATCH] x86-64: Revert timer routing behaviour back to 2.6.16 state
  [PATCH] x86-64: Overlapping program headers in physical addr space fix
  [PATCH] x86-64: Put more than one cpu in TARGET_CPUS
  [PATCH] x86: Revert new unwind kernel stack termination
  [PATCH] x86-64: Use irq_domain in ioapic_retrigger_irq
  [PATCH] i386: Disable nmi watchdog on all ThinkPads
  [PATCH] x86-64: Revert interrupt backlink changes
  [PATCH] x86-64: Fix ENOSYS in system call tracing
  [PATCH] i386: Fix fake return address
  [PATCH] x86-64: x86_64 add NX mask for PTE entry
  [PATCH] x86-64: Speed up dwarf2 unwinder
  [PATCH] x86: Use -maccumulate-outgoing-args
  [PATCH] x86-64: fix page align in e820 allocator
  [PATCH] x86-64: Fix for arch/x86_64/pci/Makefile CFLAGS
  [PATCH] i386: fix .cfi_signal_frame copy-n-paste error
  [PATCH] x86-64: typo in __assign_irq_vector when updating pos for vector and offset
  [PATCH] x86-64: x86_64 hot-add memory srat.c fix
  [PATCH] i386: Update defconfig
  [PATCH] x86-64: Update defconfig
parents fc22617e e70ea8c0
...@@ -499,6 +499,7 @@ endif ...@@ -499,6 +499,7 @@ endif
ifdef CONFIG_UNWIND_INFO ifdef CONFIG_UNWIND_INFO
CFLAGS += -fasynchronous-unwind-tables CFLAGS += -fasynchronous-unwind-tables
LDFLAGS_vmlinux += --eh-frame-hdr
endif endif
ifdef CONFIG_DEBUG_INFO ifdef CONFIG_DEBUG_INFO
......
...@@ -42,6 +42,10 @@ cflags-$(CONFIG_REGPARM) += -mregparm=3 ...@@ -42,6 +42,10 @@ cflags-$(CONFIG_REGPARM) += -mregparm=3
# temporary until string.h is fixed # temporary until string.h is fixed
cflags-y += -ffreestanding cflags-y += -ffreestanding
# this works around some issues with generating unwind tables in older gccs
# newer gccs do it by default
cflags-y += -maccumulate-outgoing-args
# Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use # Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use
# a lot more stack due to the lack of sharing of stacklots: # a lot more stack due to the lack of sharing of stacklots:
CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then echo $(call cc-option,-fno-unit-at-a-time); fi ;) CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then echo $(call cc-option,-fno-unit-at-a-time); fi ;)
...@@ -51,8 +55,8 @@ cflags-y += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,) ...@@ -51,8 +55,8 @@ 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,) AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
# is .cfi_signal_frame supported too? # is .cfi_signal_frame supported too?
cflags-y += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,) cflags-y += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,)
AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,) AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,)
CFLAGS += $(cflags-y) CFLAGS += $(cflags-y)
......
# #
# Automatically generated make config: don't edit # Automatically generated make config: don't edit
# Linux kernel version: 2.6.19-rc1 # Linux kernel version: 2.6.19-rc2-git4
# Thu Oct 5 13:04:53 2006 # Sat Oct 21 03:38:56 2006
# #
CONFIG_X86_32=y CONFIG_X86_32=y
CONFIG_GENERIC_TIME=y CONFIG_GENERIC_TIME=y
...@@ -380,8 +380,8 @@ CONFIG_INET6_XFRM_MODE_TRANSPORT=y ...@@ -380,8 +380,8 @@ CONFIG_INET6_XFRM_MODE_TRANSPORT=y
CONFIG_INET6_XFRM_MODE_TUNNEL=y CONFIG_INET6_XFRM_MODE_TUNNEL=y
# CONFIG_INET6_XFRM_MODE_BEET is not set # CONFIG_INET6_XFRM_MODE_BEET is not set
# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
CONFIG_IPV6_SIT=y
# CONFIG_IPV6_TUNNEL is not set # CONFIG_IPV6_TUNNEL is not set
# CONFIG_IPV6_SUBTREES is not set
# CONFIG_IPV6_MULTIPLE_TABLES is not set # CONFIG_IPV6_MULTIPLE_TABLES is not set
# CONFIG_NETWORK_SECMARK is not set # CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set # CONFIG_NETFILTER is not set
...@@ -482,6 +482,13 @@ CONFIG_BLK_DEV_INITRD=y ...@@ -482,6 +482,13 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set # CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set # CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
# CONFIG_IBM_ASM is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
# #
# ATA/ATAPI/MFM/RLL support # ATA/ATAPI/MFM/RLL support
# #
...@@ -1024,6 +1031,7 @@ CONFIG_HANGCHECK_TIMER=y ...@@ -1024,6 +1031,7 @@ CONFIG_HANGCHECK_TIMER=y
# #
# Dallas's 1-wire bus # Dallas's 1-wire bus
# #
# CONFIG_W1 is not set
# #
# Hardware Monitoring support # Hardware Monitoring support
...@@ -1031,12 +1039,6 @@ CONFIG_HANGCHECK_TIMER=y ...@@ -1031,12 +1039,6 @@ CONFIG_HANGCHECK_TIMER=y
# CONFIG_HWMON is not set # CONFIG_HWMON is not set
# CONFIG_HWMON_VID is not set # CONFIG_HWMON_VID is not set
#
# Misc devices
#
# CONFIG_IBM_ASM is not set
# CONFIG_TIFM_CORE is not set
# #
# Multimedia devices # Multimedia devices
# #
...@@ -1169,7 +1171,6 @@ CONFIG_USB_HIDINPUT=y ...@@ -1169,7 +1171,6 @@ CONFIG_USB_HIDINPUT=y
# CONFIG_USB_ATI_REMOTE2 is not set # CONFIG_USB_ATI_REMOTE2 is not set
# CONFIG_USB_KEYSPAN_REMOTE is not set # CONFIG_USB_KEYSPAN_REMOTE is not set
# CONFIG_USB_APPLETOUCH is not set # CONFIG_USB_APPLETOUCH is not set
# CONFIG_USB_TRANCEVIBRATOR is not set
# #
# USB Imaging devices # USB Imaging devices
...@@ -1215,6 +1216,7 @@ CONFIG_USB_MON=y ...@@ -1215,6 +1216,7 @@ CONFIG_USB_MON=y
# CONFIG_USB_APPLEDISPLAY is not set # CONFIG_USB_APPLEDISPLAY is not set
# CONFIG_USB_SISUSBVGA is not set # CONFIG_USB_SISUSBVGA is not set
# CONFIG_USB_LD is not set # CONFIG_USB_LD is not set
# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_TEST is not set # CONFIG_USB_TEST is not set
# #
...@@ -1284,6 +1286,7 @@ CONFIG_EXT3_FS=y ...@@ -1284,6 +1286,7 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y CONFIG_EXT3_FS_POSIX_ACL=y
# CONFIG_EXT3_FS_SECURITY is not set # CONFIG_EXT3_FS_SECURITY is not set
# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set # CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y CONFIG_FS_MBCACHE=y
...@@ -1307,6 +1310,7 @@ CONFIG_DNOTIFY=y ...@@ -1307,6 +1310,7 @@ CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS_FS is not set
CONFIG_AUTOFS4_FS=y CONFIG_AUTOFS4_FS=y
# CONFIG_FUSE_FS is not set # CONFIG_FUSE_FS is not set
CONFIG_GENERIC_ACL=y
# #
# CD-ROM/DVD Filesystems # CD-ROM/DVD Filesystems
...@@ -1384,7 +1388,6 @@ CONFIG_SUNRPC=y ...@@ -1384,7 +1388,6 @@ CONFIG_SUNRPC=y
# CONFIG_CODA_FS is not set # CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set # CONFIG_AFS_FS is not set
# CONFIG_9P_FS is not set # CONFIG_9P_FS is not set
CONFIG_GENERIC_ACL=y
# #
# Partition Types # Partition Types
...@@ -1436,10 +1439,6 @@ CONFIG_NLS_ISO8859_15=y ...@@ -1436,10 +1439,6 @@ CONFIG_NLS_ISO8859_15=y
# CONFIG_NLS_KOI8_U is not set # CONFIG_NLS_KOI8_U is not set
CONFIG_NLS_UTF8=y CONFIG_NLS_UTF8=y
#
# Distributed Lock Manager
#
# #
# Instrumentation Support # Instrumentation Support
# #
...@@ -1480,6 +1479,7 @@ CONFIG_DEBUG_BUGVERBOSE=y ...@@ -1480,6 +1479,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_UNWIND_INFO=y CONFIG_UNWIND_INFO=y
CONFIG_STACK_UNWIND=y CONFIG_STACK_UNWIND=y
# CONFIG_FORCED_INLINING is not set # CONFIG_FORCED_INLINING is not set
# CONFIG_HEADERS_CHECK is not set
# CONFIG_RCU_TORTURE_TEST is not set # CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_LKDTM is not set # CONFIG_LKDTM is not set
CONFIG_EARLY_PRINTK=y CONFIG_EARLY_PRINTK=y
......
...@@ -317,7 +317,7 @@ is386: movl $2,%ecx # set MP ...@@ -317,7 +317,7 @@ is386: movl $2,%ecx # set MP
movl %eax,%gs movl %eax,%gs
lldt %ax lldt %ax
cld # gcc2 wants the direction flag cleared at all times cld # gcc2 wants the direction flag cleared at all times
pushl %eax # fake return address pushl $0 # fake return address for unwinder
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
movb ready, %cl movb ready, %cl
movb $1, ready movb $1, ready
......
...@@ -219,11 +219,11 @@ static int __init check_nmi_watchdog(void) ...@@ -219,11 +219,11 @@ static int __init check_nmi_watchdog(void)
int cpu; int cpu;
/* Enable NMI watchdog for newer systems. /* Enable NMI watchdog for newer systems.
Actually it should be safe for most systems before 2004 too except Probably safe on most older systems too, but let's be careful.
for some IBM systems that corrupt registers when NMI happens IBM ThinkPads use INT10 inside SMM and that allows early NMI inside SMM
during SMM. Unfortunately we don't have more exact information which hangs the system. Disable watchdog for all thinkpads */
on these and use this coarse check. */ if (nmi_watchdog == NMI_DEFAULT && dmi_get_year(DMI_BIOS_DATE) >= 2004 &&
if (nmi_watchdog == NMI_DEFAULT && dmi_get_year(DMI_BIOS_DATE) >= 2004) !dmi_name_in_vendors("ThinkPad"))
nmi_watchdog = NMI_LOCAL_APIC; nmi_watchdog = NMI_LOCAL_APIC;
if ((nmi_watchdog == NMI_NONE) || (nmi_watchdog == NMI_DEFAULT)) if ((nmi_watchdog == NMI_NONE) || (nmi_watchdog == NMI_DEFAULT))
......
...@@ -336,7 +336,6 @@ extern void kernel_thread_helper(void); ...@@ -336,7 +336,6 @@ extern void kernel_thread_helper(void);
int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
{ {
struct pt_regs regs; struct pt_regs regs;
int err;
memset(&regs, 0, sizeof(regs)); memset(&regs, 0, sizeof(regs));
...@@ -351,10 +350,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) ...@@ -351,10 +350,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2; regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2;
/* Ok, create the new process.. */ /* Ok, create the new process.. */
err = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL); return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
if (err == 0) /* terminate kernel stack */
task_pt_regs(current)->eip = 0;
return err;
} }
EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(kernel_thread);
......
...@@ -54,6 +54,10 @@ endif ...@@ -54,6 +54,10 @@ endif
cflags-y += $(call cc-option,-funit-at-a-time) cflags-y += $(call cc-option,-funit-at-a-time)
# prevent gcc from generating any FP code by mistake # prevent gcc from generating any FP code by mistake
cflags-y += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,) cflags-y += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,)
# this works around some issues with generating unwind tables in older gccs
# newer gccs do it by default
cflags-y += -maccumulate-outgoing-args
# do binutils support CFI? # do binutils support CFI?
cflags-y += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,) 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,) AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
......
# #
# Automatically generated make config: don't edit # Automatically generated make config: don't edit
# Linux kernel version: 2.6.19-rc1 # Linux kernel version: 2.6.19-rc2-git4
# Thu Oct 5 13:04:43 2006 # Sat Oct 21 03:38:52 2006
# #
CONFIG_X86_64=y CONFIG_X86_64=y
CONFIG_64BIT=y CONFIG_64BIT=y
...@@ -335,8 +335,8 @@ CONFIG_IPV6=y ...@@ -335,8 +335,8 @@ CONFIG_IPV6=y
# CONFIG_INET6_XFRM_MODE_TUNNEL is not set # CONFIG_INET6_XFRM_MODE_TUNNEL is not set
# CONFIG_INET6_XFRM_MODE_BEET is not set # CONFIG_INET6_XFRM_MODE_BEET is not set
# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
CONFIG_IPV6_SIT=y
# CONFIG_IPV6_TUNNEL is not set # CONFIG_IPV6_TUNNEL is not set
# CONFIG_IPV6_SUBTREES is not set
# CONFIG_IPV6_MULTIPLE_TABLES is not set # CONFIG_IPV6_MULTIPLE_TABLES is not set
# CONFIG_NETWORK_SECMARK is not set # CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set # CONFIG_NETFILTER is not set
...@@ -437,6 +437,13 @@ CONFIG_BLK_DEV_INITRD=y ...@@ -437,6 +437,13 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set # CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set # CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
# CONFIG_IBM_ASM is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
# #
# ATA/ATAPI/MFM/RLL support # ATA/ATAPI/MFM/RLL support
# #
...@@ -1008,6 +1015,7 @@ CONFIG_I2C_ISA=m ...@@ -1008,6 +1015,7 @@ CONFIG_I2C_ISA=m
# #
# Dallas's 1-wire bus # Dallas's 1-wire bus
# #
# CONFIG_W1 is not set
# #
# Hardware Monitoring support # Hardware Monitoring support
...@@ -1058,12 +1066,6 @@ CONFIG_SENSORS_SMSC47B397=m ...@@ -1058,12 +1066,6 @@ CONFIG_SENSORS_SMSC47B397=m
# CONFIG_SENSORS_HDAPS is not set # CONFIG_SENSORS_HDAPS is not set
# CONFIG_HWMON_DEBUG_CHIP is not set # CONFIG_HWMON_DEBUG_CHIP is not set
#
# Misc devices
#
# CONFIG_IBM_ASM is not set
# CONFIG_TIFM_CORE is not set
# #
# Multimedia devices # Multimedia devices
# #
...@@ -1196,7 +1198,6 @@ CONFIG_USB_HIDINPUT=y ...@@ -1196,7 +1198,6 @@ CONFIG_USB_HIDINPUT=y
# CONFIG_USB_ATI_REMOTE2 is not set # CONFIG_USB_ATI_REMOTE2 is not set
# CONFIG_USB_KEYSPAN_REMOTE is not set # CONFIG_USB_KEYSPAN_REMOTE is not set
# CONFIG_USB_APPLETOUCH is not set # CONFIG_USB_APPLETOUCH is not set
# CONFIG_USB_TRANCEVIBRATOR is not set
# #
# USB Imaging devices # USB Imaging devices
...@@ -1242,6 +1243,7 @@ CONFIG_USB_MON=y ...@@ -1242,6 +1243,7 @@ CONFIG_USB_MON=y
# CONFIG_USB_APPLEDISPLAY is not set # CONFIG_USB_APPLEDISPLAY is not set
# CONFIG_USB_SISUSBVGA is not set # CONFIG_USB_SISUSBVGA is not set
# CONFIG_USB_LD is not set # CONFIG_USB_LD is not set
# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_TEST is not set # CONFIG_USB_TEST is not set
# #
...@@ -1318,6 +1320,7 @@ CONFIG_EXT3_FS=y ...@@ -1318,6 +1320,7 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y CONFIG_EXT3_FS_POSIX_ACL=y
# CONFIG_EXT3_FS_SECURITY is not set # CONFIG_EXT3_FS_SECURITY is not set
# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set # CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y CONFIG_FS_MBCACHE=y
...@@ -1341,6 +1344,7 @@ CONFIG_DNOTIFY=y ...@@ -1341,6 +1344,7 @@ CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS_FS is not set
CONFIG_AUTOFS4_FS=y CONFIG_AUTOFS4_FS=y
# CONFIG_FUSE_FS is not set # CONFIG_FUSE_FS is not set
CONFIG_GENERIC_ACL=y
# #
# CD-ROM/DVD Filesystems # CD-ROM/DVD Filesystems
...@@ -1418,7 +1422,6 @@ CONFIG_SUNRPC=y ...@@ -1418,7 +1422,6 @@ CONFIG_SUNRPC=y
# CONFIG_CODA_FS is not set # CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set # CONFIG_AFS_FS is not set
# CONFIG_9P_FS is not set # CONFIG_9P_FS is not set
CONFIG_GENERIC_ACL=y
# #
# Partition Types # Partition Types
...@@ -1470,10 +1473,6 @@ CONFIG_NLS_ISO8859_15=y ...@@ -1470,10 +1473,6 @@ CONFIG_NLS_ISO8859_15=y
# CONFIG_NLS_KOI8_U is not set # CONFIG_NLS_KOI8_U is not set
CONFIG_NLS_UTF8=y CONFIG_NLS_UTF8=y
#
# Distributed Lock Manager
#
# #
# Instrumentation Support # Instrumentation Support
# #
...@@ -1512,6 +1511,7 @@ CONFIG_DEBUG_FS=y ...@@ -1512,6 +1511,7 @@ CONFIG_DEBUG_FS=y
CONFIG_UNWIND_INFO=y CONFIG_UNWIND_INFO=y
CONFIG_STACK_UNWIND=y CONFIG_STACK_UNWIND=y
# CONFIG_FORCED_INLINING is not set # CONFIG_FORCED_INLINING is not set
# CONFIG_HEADERS_CHECK is not set
# CONFIG_RCU_TORTURE_TEST is not set # CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_LKDTM is not set # CONFIG_LKDTM is not set
# CONFIG_DEBUG_RODATA is not set # CONFIG_DEBUG_RODATA is not set
......
...@@ -54,13 +54,13 @@ static inline int bad_addr(unsigned long *addrp, unsigned long size) ...@@ -54,13 +54,13 @@ static inline int bad_addr(unsigned long *addrp, unsigned long size)
/* various gunk below that needed for SMP startup */ /* various gunk below that needed for SMP startup */
if (addr < 0x8000) { if (addr < 0x8000) {
*addrp = 0x8000; *addrp = PAGE_ALIGN(0x8000);
return 1; return 1;
} }
/* direct mapping tables of the kernel */ /* direct mapping tables of the kernel */
if (last >= table_start<<PAGE_SHIFT && addr < table_end<<PAGE_SHIFT) { if (last >= table_start<<PAGE_SHIFT && addr < table_end<<PAGE_SHIFT) {
*addrp = table_end << PAGE_SHIFT; *addrp = PAGE_ALIGN(table_end << PAGE_SHIFT);
return 1; return 1;
} }
...@@ -68,18 +68,18 @@ static inline int bad_addr(unsigned long *addrp, unsigned long size) ...@@ -68,18 +68,18 @@ static inline int bad_addr(unsigned long *addrp, unsigned long size)
#ifdef CONFIG_BLK_DEV_INITRD #ifdef CONFIG_BLK_DEV_INITRD
if (LOADER_TYPE && INITRD_START && last >= INITRD_START && if (LOADER_TYPE && INITRD_START && last >= INITRD_START &&
addr < INITRD_START+INITRD_SIZE) { addr < INITRD_START+INITRD_SIZE) {
*addrp = INITRD_START + INITRD_SIZE; *addrp = PAGE_ALIGN(INITRD_START + INITRD_SIZE);
return 1; return 1;
} }
#endif #endif
/* kernel code */ /* kernel code */
if (last >= __pa_symbol(&_text) && last < __pa_symbol(&_end)) { if (last >= __pa_symbol(&_text) && addr < __pa_symbol(&_end)) {
*addrp = __pa_symbol(&_end); *addrp = PAGE_ALIGN(__pa_symbol(&_end));
return 1; return 1;
} }
if (last >= ebda_addr && addr < ebda_addr + ebda_size) { if (last >= ebda_addr && addr < ebda_addr + ebda_size) {
*addrp = ebda_addr + ebda_size; *addrp = PAGE_ALIGN(ebda_addr + ebda_size);
return 1; return 1;
} }
...@@ -152,7 +152,7 @@ unsigned long __init find_e820_area(unsigned long start, unsigned long end, unsi ...@@ -152,7 +152,7 @@ unsigned long __init find_e820_area(unsigned long start, unsigned long end, unsi
continue; continue;
while (bad_addr(&addr, size) && addr+size <= ei->addr+ei->size) while (bad_addr(&addr, size) && addr+size <= ei->addr+ei->size)
; ;
last = addr + size; last = PAGE_ALIGN(addr) + size;
if (last > ei->addr + ei->size) if (last > ei->addr + ei->size)
continue; continue;
if (last > end) if (last > end)
......
...@@ -61,10 +61,11 @@ static void nvidia_bugs(void) ...@@ -61,10 +61,11 @@ static void nvidia_bugs(void)
static void ati_bugs(void) static void ati_bugs(void)
{ {
#if 1 /* for testing */ if (timer_over_8254 == 1) {
printk("ATI board detected\n"); timer_over_8254 = 0;
#endif printk(KERN_INFO
/* No bugs right now */ "ATI board detected. Disabling timer routing over 8254.\n");
}
} }
struct chipset { struct chipset {
......
...@@ -315,6 +315,8 @@ tracesys: ...@@ -315,6 +315,8 @@ tracesys:
LOAD_ARGS ARGOFFSET /* reload args from stack in case ptrace changed it */ LOAD_ARGS ARGOFFSET /* reload args from stack in case ptrace changed it */
RESTORE_REST RESTORE_REST
cmpq $__NR_syscall_max,%rax cmpq $__NR_syscall_max,%rax
movq $-ENOSYS,%rcx
cmova %rcx,%rax
ja 1f ja 1f
movq %r10,%rcx /* fixup for C */ movq %r10,%rcx /* fixup for C */
call *sys_call_table(,%rax,8) call *sys_call_table(,%rax,8)
...@@ -535,8 +537,6 @@ END(stub_rt_sigreturn) ...@@ -535,8 +537,6 @@ END(stub_rt_sigreturn)
1: incl %gs:pda_irqcount 1: incl %gs:pda_irqcount
cmoveq %gs:pda_irqstackptr,%rsp cmoveq %gs:pda_irqstackptr,%rsp
push %rbp # backlink for old unwinder push %rbp # backlink for old unwinder
CFI_ADJUST_CFA_OFFSET 8
CFI_REL_OFFSET rbp,0
/* /*
* We entered an interrupt context - irqs are off: * We entered an interrupt context - irqs are off:
*/ */
...@@ -980,11 +980,6 @@ ENTRY(kernel_thread) ...@@ -980,11 +980,6 @@ ENTRY(kernel_thread)
call do_fork call do_fork
movq %rax,RAX(%rsp) movq %rax,RAX(%rsp)
xorl %edi,%edi xorl %edi,%edi
test %rax,%rax
jnz 1f
/* terminate stack in child */
movq %rdi,RIP(%rsp)
1:
/* /*
* It isn't worth to check for reschedule here, * It isn't worth to check for reschedule here,
...@@ -1176,7 +1171,6 @@ ENTRY(call_softirq) ...@@ -1176,7 +1171,6 @@ ENTRY(call_softirq)
incl %gs:pda_irqcount incl %gs:pda_irqcount
cmove %gs:pda_irqstackptr,%rsp cmove %gs:pda_irqstackptr,%rsp
push %rbp # backlink for old unwinder push %rbp # backlink for old unwinder
CFI_ADJUST_CFA_OFFSET 8
call __do_softirq call __do_softirq
leaveq leaveq
CFI_DEF_CFA_REGISTER rsp CFI_DEF_CFA_REGISTER rsp
......
...@@ -153,7 +153,7 @@ struct genapic apic_flat = { ...@@ -153,7 +153,7 @@ struct genapic apic_flat = {
static cpumask_t physflat_target_cpus(void) static cpumask_t physflat_target_cpus(void)
{ {
return cpumask_of_cpu(0); return cpu_online_map;
} }
static cpumask_t physflat_vector_allocation_domain(int cpu) static cpumask_t physflat_vector_allocation_domain(int cpu)
......
...@@ -57,7 +57,7 @@ static int no_timer_check; ...@@ -57,7 +57,7 @@ static int no_timer_check;
static int disable_timer_pin_1 __initdata; static int disable_timer_pin_1 __initdata;
int timer_over_8254 __initdata = 0; int timer_over_8254 __initdata = 1;
/* Where if anywhere is the i8259 connect in external int mode */ /* Where if anywhere is the i8259 connect in external int mode */
static struct { int pin, apic; } ioapic_i8259 = { -1, -1 }; static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
...@@ -651,12 +651,12 @@ static int __assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result) ...@@ -651,12 +651,12 @@ static int __assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result)
if (vector == IA32_SYSCALL_VECTOR) if (vector == IA32_SYSCALL_VECTOR)
goto next; goto next;
for_each_cpu_mask(new_cpu, domain) for_each_cpu_mask(new_cpu, domain)
if (per_cpu(vector_irq, cpu)[vector] != -1) if (per_cpu(vector_irq, new_cpu)[vector] != -1)
goto next; goto next;
/* Found one! */ /* Found one! */
for_each_cpu_mask(new_cpu, domain) { for_each_cpu_mask(new_cpu, domain) {
pos[cpu].vector = vector; pos[new_cpu].vector = vector;
pos[cpu].offset = offset; pos[new_cpu].offset = offset;
} }
if (old_vector >= 0) { if (old_vector >= 0) {
int old_cpu; int old_cpu;
...@@ -1255,12 +1255,15 @@ static int ioapic_retrigger_irq(unsigned int irq) ...@@ -1255,12 +1255,15 @@ static int ioapic_retrigger_irq(unsigned int irq)
{ {
cpumask_t mask; cpumask_t mask;
unsigned vector; unsigned vector;
unsigned long flags;
spin_lock_irqsave(&vector_lock, flags);
vector = irq_vector[irq]; vector = irq_vector[irq];
cpus_clear(mask); cpus_clear(mask);
cpu_set(vector >> 8, mask); cpu_set(first_cpu(irq_domain[irq]), mask);
send_IPI_mask(mask, vector & 0xff); send_IPI_mask(mask, vector);
spin_unlock_irqrestore(&vector_lock, flags);
return 1; return 1;
} }
......
...@@ -17,6 +17,7 @@ PHDRS { ...@@ -17,6 +17,7 @@ PHDRS {
text PT_LOAD FLAGS(5); /* R_E */ text PT_LOAD FLAGS(5); /* R_E */
data PT_LOAD FLAGS(7); /* RWE */ data PT_LOAD FLAGS(7); /* RWE */
user PT_LOAD FLAGS(7); /* RWE */ user PT_LOAD FLAGS(7); /* RWE */
data.init PT_LOAD FLAGS(7); /* RWE */
note PT_NOTE FLAGS(4); /* R__ */ note PT_NOTE FLAGS(4); /* R__ */
} }
SECTIONS SECTIONS
...@@ -131,7 +132,7 @@ SECTIONS ...@@ -131,7 +132,7 @@ SECTIONS
. = ALIGN(8192); /* init_task */ . = ALIGN(8192); /* init_task */
.data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) { .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
*(.data.init_task) *(.data.init_task)
} :data }:data.init
. = ALIGN(4096); . = ALIGN(4096);
.data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) { .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
......
...@@ -207,7 +207,7 @@ static inline int save_add_info(void) ...@@ -207,7 +207,7 @@ static inline int save_add_info(void)
return hotadd_percent > 0; return hotadd_percent > 0;
} }
#else #else
int update_end_of_memory(unsigned long end) {return 0;} int update_end_of_memory(unsigned long end) {return -1;}
static int hotadd_enough_memory(struct bootnode *nd) {return 1;} static int hotadd_enough_memory(struct bootnode *nd) {return 1;}
#ifdef CONFIG_MEMORY_HOTPLUG_SPARSE #ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
static inline int save_add_info(void) {return 1;} static inline int save_add_info(void) {return 1;}
...@@ -337,7 +337,7 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma) ...@@ -337,7 +337,7 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma)
push_node_boundaries(node, nd->start >> PAGE_SHIFT, push_node_boundaries(node, nd->start >> PAGE_SHIFT,
nd->end >> PAGE_SHIFT); nd->end >> PAGE_SHIFT);
if (ma->flags.hot_pluggable && !reserve_hotadd(node, start, end) < 0) { if (ma->flags.hot_pluggable && (reserve_hotadd(node, start, end) < 0)) {
/* Ignore hotadd region. Undo damage */ /* Ignore hotadd region. Undo damage */
printk(KERN_NOTICE "SRAT: Hotplug region ignored\n"); printk(KERN_NOTICE "SRAT: Hotplug region ignored\n");
*nd = oldnode; *nd = oldnode;
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
# #
# Reuse the i386 PCI subsystem # Reuse the i386 PCI subsystem
# #
CFLAGS += -Iarch/i386/pci EXTRA_CFLAGS += -Iarch/i386/pci
obj-y := i386.o obj-y := i386.o
obj-$(CONFIG_PCI_DIRECT)+= direct.o obj-$(CONFIG_PCI_DIRECT)+= direct.o
......
...@@ -326,6 +326,26 @@ char *dmi_get_system_info(int field) ...@@ -326,6 +326,26 @@ char *dmi_get_system_info(int field)
} }
EXPORT_SYMBOL(dmi_get_system_info); EXPORT_SYMBOL(dmi_get_system_info);
/**
* dmi_name_in_vendors - Check if string is anywhere in the DMI vendor information.
* @str: Case sensitive Name
*/
int dmi_name_in_vendors(char *str)
{
static int fields[] = { DMI_BIOS_VENDOR, DMI_BIOS_VERSION, DMI_SYS_VENDOR,
DMI_PRODUCT_NAME, DMI_PRODUCT_VERSION, DMI_BOARD_VENDOR,
DMI_BOARD_NAME, DMI_BOARD_VERSION, DMI_NONE };
int i;
for (i = 0; fields[i] != DMI_NONE; i++) {
int f = fields[i];
if (dmi_ident[f] && strstr(dmi_ident[f], str))
return 1;
}
return 0;
}
EXPORT_SYMBOL(dmi_name_in_vendors);
/** /**
* dmi_find_device - find onboard device by type/name * dmi_find_device - find onboard device by type/name
* @type: device type or %DMI_DEV_TYPE_ANY to match all device types * @type: device type or %DMI_DEV_TYPE_ANY to match all device types
......
...@@ -125,6 +125,10 @@ ...@@ -125,6 +125,10 @@
*(__param) \ *(__param) \
VMLINUX_SYMBOL(__stop___param) = .; \ VMLINUX_SYMBOL(__stop___param) = .; \
} \ } \
\
/* Unwind data binary search table */ \
EH_FRAME_HDR \
\
__end_rodata = .; \ __end_rodata = .; \
. = ALIGN(4096); . = ALIGN(4096);
...@@ -157,6 +161,18 @@ ...@@ -157,6 +161,18 @@
*(.kprobes.text) \ *(.kprobes.text) \
VMLINUX_SYMBOL(__kprobes_text_end) = .; VMLINUX_SYMBOL(__kprobes_text_end) = .;
#ifdef CONFIG_STACK_UNWIND
/* Unwind data binary search table */
#define EH_FRAME_HDR \
.eh_frame_hdr : AT(ADDR(.eh_frame_hdr) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start_unwind_hdr) = .; \
*(.eh_frame_hdr) \
VMLINUX_SYMBOL(__end_unwind_hdr) = .; \
}
#else
#define EH_FRAME_HDR
#endif
/* DWARF debug sections. /* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to Symbols in the DWARF debugging sections are relative to
the beginning of the section so we begin them at 0. */ the beginning of the section so we begin them at 0. */
......
...@@ -366,6 +366,7 @@ static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot) ...@@ -366,6 +366,7 @@ static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
{ {
pte_t pte; pte_t pte;
pte_val(pte) = physpage | pgprot_val(pgprot); pte_val(pte) = physpage | pgprot_val(pgprot);
pte_val(pte) &= __supported_pte_mask;
return pte; return pte;
} }
......
...@@ -122,6 +122,8 @@ extern int fix_aperture; ...@@ -122,6 +122,8 @@ extern int fix_aperture;
extern int reboot_force; extern int reboot_force;
extern int notsc_setup(char *); extern int notsc_setup(char *);
extern int timer_over_8254;
extern int gsi_irq_sharing(int gsi); extern int gsi_irq_sharing(int gsi);
extern void smp_local_timer_interrupt(void); extern void smp_local_timer_interrupt(void);
......
...@@ -69,6 +69,7 @@ extern struct dmi_device * dmi_find_device(int type, const char *name, ...@@ -69,6 +69,7 @@ extern struct dmi_device * dmi_find_device(int type, const char *name,
struct dmi_device *from); struct dmi_device *from);
extern void dmi_scan_machine(void); extern void dmi_scan_machine(void);
extern int dmi_get_year(int field); extern int dmi_get_year(int field);
extern int dmi_name_in_vendors(char *str);
#else #else
...@@ -77,6 +78,7 @@ static inline char * dmi_get_system_info(int field) { return NULL; } ...@@ -77,6 +78,7 @@ static inline char * dmi_get_system_info(int field) { return NULL; }
static inline struct dmi_device * dmi_find_device(int type, const char *name, static inline struct dmi_device * dmi_find_device(int type, const char *name,
struct dmi_device *from) { return NULL; } struct dmi_device *from) { return NULL; }
static inline int dmi_get_year(int year) { return 0; } static inline int dmi_get_year(int year) { return 0; }
static inline int dmi_name_in_vendors(char *s) { return 0; }
#endif #endif
......
...@@ -26,6 +26,7 @@ struct module; ...@@ -26,6 +26,7 @@ struct module;
* Initialize unwind support. * Initialize unwind support.
*/ */
extern void unwind_init(void); extern void unwind_init(void);
extern void unwind_setup(void);
#ifdef CONFIG_MODULES #ifdef CONFIG_MODULES
...@@ -73,6 +74,7 @@ extern int unwind_to_user(struct unwind_frame_info *); ...@@ -73,6 +74,7 @@ extern int unwind_to_user(struct unwind_frame_info *);
struct unwind_frame_info {}; struct unwind_frame_info {};
static inline void unwind_init(void) {} static inline void unwind_init(void) {}
static inline void unwind_setup(void) {}
#ifdef CONFIG_MODULES #ifdef CONFIG_MODULES
......
...@@ -503,6 +503,7 @@ asmlinkage void __init start_kernel(void) ...@@ -503,6 +503,7 @@ asmlinkage void __init start_kernel(void)
printk(KERN_NOTICE); printk(KERN_NOTICE);
printk(linux_banner); printk(linux_banner);
setup_arch(&command_line); setup_arch(&command_line);
unwind_setup();
setup_per_cpu_areas(); setup_per_cpu_areas();
smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */ smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */
......
...@@ -11,13 +11,15 @@ ...@@ -11,13 +11,15 @@
#include <linux/unwind.h> #include <linux/unwind.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/delay.h> #include <linux/bootmem.h>
#include <linux/sort.h>
#include <linux/stop_machine.h> #include <linux/stop_machine.h>
#include <asm/sections.h> #include <asm/sections.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
extern char __start_unwind[], __end_unwind[]; extern char __start_unwind[], __end_unwind[];
extern const u8 __start_unwind_hdr[], __end_unwind_hdr[];
#define MAX_STACK_DEPTH 8 #define MAX_STACK_DEPTH 8
...@@ -100,6 +102,8 @@ static struct unwind_table { ...@@ -100,6 +102,8 @@ static struct unwind_table {
} core, init; } core, init;
const void *address; const void *address;
unsigned long size; unsigned long size;
const unsigned char *header;
unsigned long hdrsz;
struct unwind_table *link; struct unwind_table *link;
const char *name; const char *name;
} root_table; } root_table;
...@@ -145,6 +149,10 @@ static struct unwind_table *find_table(unsigned long pc) ...@@ -145,6 +149,10 @@ static struct unwind_table *find_table(unsigned long pc)
return table; return table;
} }
static unsigned long read_pointer(const u8 **pLoc,
const void *end,
signed ptrType);
static void init_unwind_table(struct unwind_table *table, static void init_unwind_table(struct unwind_table *table,
const char *name, const char *name,
const void *core_start, const void *core_start,
...@@ -152,14 +160,30 @@ static void init_unwind_table(struct unwind_table *table, ...@@ -152,14 +160,30 @@ static void init_unwind_table(struct unwind_table *table,
const void *init_start, const void *init_start,
unsigned long init_size, unsigned long init_size,
const void *table_start, const void *table_start,
unsigned long table_size) unsigned long table_size,
const u8 *header_start,
unsigned long header_size)
{ {
const u8 *ptr = header_start + 4;
const u8 *end = header_start + header_size;
table->core.pc = (unsigned long)core_start; table->core.pc = (unsigned long)core_start;
table->core.range = core_size; table->core.range = core_size;
table->init.pc = (unsigned long)init_start; table->init.pc = (unsigned long)init_start;
table->init.range = init_size; table->init.range = init_size;
table->address = table_start; table->address = table_start;
table->size = table_size; table->size = table_size;
/* See if the linker provided table looks valid. */
if (header_size <= 4
|| header_start[0] != 1
|| (void *)read_pointer(&ptr, end, header_start[1]) != table_start
|| header_start[2] == DW_EH_PE_omit
|| read_pointer(&ptr, end, header_start[2]) <= 0
|| header_start[3] == DW_EH_PE_omit)
header_start = NULL;
table->hdrsz = header_size;
smp_wmb();
table->header = header_start;
table->link = NULL; table->link = NULL;
table->name = name; table->name = name;
} }
...@@ -169,7 +193,143 @@ void __init unwind_init(void) ...@@ -169,7 +193,143 @@ void __init unwind_init(void)
init_unwind_table(&root_table, "kernel", init_unwind_table(&root_table, "kernel",
_text, _end - _text, _text, _end - _text,
NULL, 0, NULL, 0,
__start_unwind, __end_unwind - __start_unwind); __start_unwind, __end_unwind - __start_unwind,
__start_unwind_hdr, __end_unwind_hdr - __start_unwind_hdr);
}
static const u32 bad_cie, not_fde;
static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *);
static signed fde_pointer_type(const u32 *cie);
struct eh_frame_hdr_table_entry {
unsigned long start, fde;
};
static int cmp_eh_frame_hdr_table_entries(const void *p1, const void *p2)
{
const struct eh_frame_hdr_table_entry *e1 = p1;
const struct eh_frame_hdr_table_entry *e2 = p2;
return (e1->start > e2->start) - (e1->start < e2->start);
}
static void swap_eh_frame_hdr_table_entries(void *p1, void *p2, int size)
{
struct eh_frame_hdr_table_entry *e1 = p1;
struct eh_frame_hdr_table_entry *e2 = p2;
unsigned long v;
v = e1->start;
e1->start = e2->start;
e2->start = v;
v = e1->fde;
e1->fde = e2->fde;
e2->fde = v;
}
static void __init setup_unwind_table(struct unwind_table *table,
void *(*alloc)(unsigned long))
{
const u8 *ptr;
unsigned long tableSize = table->size, hdrSize;
unsigned n;
const u32 *fde;
struct {
u8 version;
u8 eh_frame_ptr_enc;
u8 fde_count_enc;
u8 table_enc;
unsigned long eh_frame_ptr;
unsigned int fde_count;
struct eh_frame_hdr_table_entry table[];
} __attribute__((__packed__)) *header;
if (table->header)
return;
if (table->hdrsz)
printk(KERN_WARNING ".eh_frame_hdr for '%s' present but unusable\n",
table->name);
if (tableSize & (sizeof(*fde) - 1))
return;
for (fde = table->address, n = 0;
tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde;
tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
const u32 *cie = cie_for_fde(fde, table);
signed ptrType;
if (cie == &not_fde)
continue;
if (cie == NULL
|| cie == &bad_cie
|| (ptrType = fde_pointer_type(cie)) < 0)
return;
ptr = (const u8 *)(fde + 2);
if (!read_pointer(&ptr,
(const u8 *)(fde + 1) + *fde,
ptrType))
return;
++n;
}
if (tableSize || !n)
return;
hdrSize = 4 + sizeof(unsigned long) + sizeof(unsigned int)
+ 2 * n * sizeof(unsigned long);
header = alloc(hdrSize);
if (!header)
return;
header->version = 1;
header->eh_frame_ptr_enc = DW_EH_PE_abs|DW_EH_PE_native;
header->fde_count_enc = DW_EH_PE_abs|DW_EH_PE_data4;
header->table_enc = DW_EH_PE_abs|DW_EH_PE_native;
put_unaligned((unsigned long)table->address, &header->eh_frame_ptr);
BUILD_BUG_ON(offsetof(typeof(*header), fde_count)
% __alignof(typeof(header->fde_count)));
header->fde_count = n;
BUILD_BUG_ON(offsetof(typeof(*header), table)
% __alignof(typeof(*header->table)));
for (fde = table->address, tableSize = table->size, n = 0;
tableSize;
tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
const u32 *cie = fde + 1 - fde[1] / sizeof(*fde);
if (!fde[1])
continue; /* this is a CIE */
ptr = (const u8 *)(fde + 2);
header->table[n].start = read_pointer(&ptr,
(const u8 *)(fde + 1) + *fde,
fde_pointer_type(cie));
header->table[n].fde = (unsigned long)fde;
++n;
}
WARN_ON(n != header->fde_count);
sort(header->table,
n,
sizeof(*header->table),
cmp_eh_frame_hdr_table_entries,
swap_eh_frame_hdr_table_entries);
table->hdrsz = hdrSize;
smp_wmb();
table->header = (const void *)header;
}
static void *__init balloc(unsigned long sz)
{
return __alloc_bootmem_nopanic(sz,
sizeof(unsigned int),
__pa(MAX_DMA_ADDRESS));
}
void __init unwind_setup(void)
{
setup_unwind_table(&root_table, balloc);
} }
#ifdef CONFIG_MODULES #ifdef CONFIG_MODULES
...@@ -193,7 +353,8 @@ void *unwind_add_table(struct module *module, ...@@ -193,7 +353,8 @@ void *unwind_add_table(struct module *module,
init_unwind_table(table, module->name, init_unwind_table(table, module->name,
module->module_core, module->core_size, module->module_core, module->core_size,
module->module_init, module->init_size, module->module_init, module->init_size,
table_start, table_size); table_start, table_size,
NULL, 0);
if (last_table) if (last_table)
last_table->link = table; last_table->link = table;
...@@ -303,6 +464,26 @@ static sleb128_t get_sleb128(const u8 **pcur, const u8 *end) ...@@ -303,6 +464,26 @@ static sleb128_t get_sleb128(const u8 **pcur, const u8 *end)
return value; return value;
} }
static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *table)
{
const u32 *cie;
if (!*fde || (*fde & (sizeof(*fde) - 1)))
return &bad_cie;
if (!fde[1])
return &not_fde; /* this is a CIE */
if ((fde[1] & (sizeof(*fde) - 1))
|| fde[1] > (unsigned long)(fde + 1) - (unsigned long)table->address)
return NULL; /* this is not a valid FDE */
cie = fde + 1 - fde[1] / sizeof(*fde);
if (*cie <= sizeof(*cie) + 4
|| *cie >= fde[1] - sizeof(*fde)
|| (*cie & (sizeof(*cie) - 1))
|| cie[1])
return NULL; /* this is not a (valid) CIE */
return cie;
}
static unsigned long read_pointer(const u8 **pLoc, static unsigned long read_pointer(const u8 **pLoc,
const void *end, const void *end,
signed ptrType) signed ptrType)
...@@ -610,49 +791,108 @@ int unwind(struct unwind_frame_info *frame) ...@@ -610,49 +791,108 @@ int unwind(struct unwind_frame_info *frame)
unsigned i; unsigned i;
signed ptrType = -1; signed ptrType = -1;
uleb128_t retAddrReg = 0; uleb128_t retAddrReg = 0;
struct unwind_table *table; const struct unwind_table *table;
struct unwind_state state; struct unwind_state state;
if (UNW_PC(frame) == 0) if (UNW_PC(frame) == 0)
return -EINVAL; return -EINVAL;
if ((table = find_table(pc)) != NULL if ((table = find_table(pc)) != NULL
&& !(table->size & (sizeof(*fde) - 1))) { && !(table->size & (sizeof(*fde) - 1))) {
unsigned long tableSize = table->size; const u8 *hdr = table->header;
unsigned long tableSize;
for (fde = table->address;
tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde; smp_rmb();
tableSize -= sizeof(*fde) + *fde, if (hdr && hdr[0] == 1) {
fde += 1 + *fde / sizeof(*fde)) { switch(hdr[3] & DW_EH_PE_FORM) {
if (!*fde || (*fde & (sizeof(*fde) - 1))) case DW_EH_PE_native: tableSize = sizeof(unsigned long); break;
break; case DW_EH_PE_data2: tableSize = 2; break;
if (!fde[1]) case DW_EH_PE_data4: tableSize = 4; break;
continue; /* this is a CIE */ case DW_EH_PE_data8: tableSize = 8; break;
if ((fde[1] & (sizeof(*fde) - 1)) default: tableSize = 0; break;
|| fde[1] > (unsigned long)(fde + 1) }
- (unsigned long)table->address) ptr = hdr + 4;
continue; /* this is not a valid FDE */ end = hdr + table->hdrsz;
cie = fde + 1 - fde[1] / sizeof(*fde); if (tableSize
if (*cie <= sizeof(*cie) + 4 && read_pointer(&ptr, end, hdr[1])
|| *cie >= fde[1] - sizeof(*fde) == (unsigned long)table->address
|| (*cie & (sizeof(*cie) - 1)) && (i = read_pointer(&ptr, end, hdr[2])) > 0
|| cie[1] && i == (end - ptr) / (2 * tableSize)
|| (ptrType = fde_pointer_type(cie)) < 0) { && !((end - ptr) % (2 * tableSize))) {
cie = NULL; /* this is not a (valid) CIE */ do {
continue; const u8 *cur = ptr + (i / 2) * (2 * tableSize);
startLoc = read_pointer(&cur,
cur + tableSize,
hdr[3]);
if (pc < startLoc)
i /= 2;
else {
ptr = cur - tableSize;
i = (i + 1) / 2;
}
} while (startLoc && i > 1);
if (i == 1
&& (startLoc = read_pointer(&ptr,
ptr + tableSize,
hdr[3])) != 0
&& pc >= startLoc)
fde = (void *)read_pointer(&ptr,
ptr + tableSize,
hdr[3]);
} }
}
if (fde != NULL) {
cie = cie_for_fde(fde, table);
ptr = (const u8 *)(fde + 2); ptr = (const u8 *)(fde + 2);
startLoc = read_pointer(&ptr, if(cie != NULL
(const u8 *)(fde + 1) + *fde, && cie != &bad_cie
ptrType); && cie != &not_fde
endLoc = startLoc && (ptrType = fde_pointer_type(cie)) >= 0
+ read_pointer(&ptr, && read_pointer(&ptr,
(const u8 *)(fde + 1) + *fde, (const u8 *)(fde + 1) + *fde,
ptrType & DW_EH_PE_indirect ptrType) == startLoc) {
? ptrType if (!(ptrType & DW_EH_PE_indirect))
: ptrType & (DW_EH_PE_FORM|DW_EH_PE_signed)); ptrType &= DW_EH_PE_FORM|DW_EH_PE_signed;
if (pc >= startLoc && pc < endLoc) endLoc = startLoc
break; + read_pointer(&ptr,
cie = NULL; (const u8 *)(fde + 1) + *fde,
ptrType);
if(pc >= endLoc)
fde = NULL;
} else
fde = NULL;
}
if (fde == NULL) {
for (fde = table->address, tableSize = table->size;
cie = NULL, tableSize > sizeof(*fde)
&& tableSize - sizeof(*fde) >= *fde;
tableSize -= sizeof(*fde) + *fde,
fde += 1 + *fde / sizeof(*fde)) {
cie = cie_for_fde(fde, table);
if (cie == &bad_cie) {
cie = NULL;
break;
}
if (cie == NULL
|| cie == &not_fde
|| (ptrType = fde_pointer_type(cie)) < 0)
continue;
ptr = (const u8 *)(fde + 2);
startLoc = read_pointer(&ptr,
(const u8 *)(fde + 1) + *fde,
ptrType);
if (!startLoc)
continue;
if (!(ptrType & DW_EH_PE_indirect))
ptrType &= DW_EH_PE_FORM|DW_EH_PE_signed;
endLoc = startLoc
+ read_pointer(&ptr,
(const u8 *)(fde + 1) + *fde,
ptrType);
if (pc >= startLoc && pc < endLoc)
break;
}
} }
} }
if (cie != NULL) { if (cie != NULL) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment