aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--arch/i386/Makefile8
-rw-r--r--arch/i386/defconfig30
-rw-r--r--arch/i386/kernel/head.S2
-rw-r--r--arch/i386/kernel/nmi.c10
-rw-r--r--arch/i386/kernel/process.c6
-rw-r--r--arch/x86_64/Makefile4
-rw-r--r--arch/x86_64/defconfig30
-rw-r--r--arch/x86_64/kernel/e820.c14
-rw-r--r--arch/x86_64/kernel/early-quirks.c9
-rw-r--r--arch/x86_64/kernel/entry.S10
-rw-r--r--arch/x86_64/kernel/genapic_flat.c2
-rw-r--r--arch/x86_64/kernel/io_apic.c15
-rw-r--r--arch/x86_64/kernel/vmlinux.lds.S3
-rw-r--r--arch/x86_64/mm/srat.c4
-rw-r--r--arch/x86_64/pci/Makefile2
-rw-r--r--drivers/firmware/dmi_scan.c20
-rw-r--r--include/asm-generic/vmlinux.lds.h16
-rw-r--r--include/asm-x86_64/pgtable.h1
-rw-r--r--include/asm-x86_64/proto.h2
-rw-r--r--include/linux/dmi.h2
-rw-r--r--include/linux/unwind.h2
-rw-r--r--init/main.c1
-rw-r--r--kernel/unwind.c318
24 files changed, 400 insertions, 112 deletions
diff --git a/Makefile b/Makefile
index 62a1343cf327..389ff0cca9a7 100644
--- a/Makefile
+++ b/Makefile
@@ -499,6 +499,7 @@ endif
499 499
500ifdef CONFIG_UNWIND_INFO 500ifdef CONFIG_UNWIND_INFO
501CFLAGS += -fasynchronous-unwind-tables 501CFLAGS += -fasynchronous-unwind-tables
502LDFLAGS_vmlinux += --eh-frame-hdr
502endif 503endif
503 504
504ifdef CONFIG_DEBUG_INFO 505ifdef CONFIG_DEBUG_INFO
diff --git a/arch/i386/Makefile b/arch/i386/Makefile
index 7cc0b189b82b..0677908dfa06 100644
--- a/arch/i386/Makefile
+++ b/arch/i386/Makefile
@@ -42,6 +42,10 @@ cflags-$(CONFIG_REGPARM) += -mregparm=3
42# temporary until string.h is fixed 42# temporary until string.h is fixed
43cflags-y += -ffreestanding 43cflags-y += -ffreestanding
44 44
45# this works around some issues with generating unwind tables in older gccs
46# newer gccs do it by default
47cflags-y += -maccumulate-outgoing-args
48
45# Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use 49# Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use
46# a lot more stack due to the lack of sharing of stacklots: 50# a lot more stack due to the lack of sharing of stacklots:
47CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then echo $(call cc-option,-fno-unit-at-a-time); fi ;) 51CFLAGS += $(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,)
51AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,) 55AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
52 56
53# is .cfi_signal_frame supported too? 57# is .cfi_signal_frame supported too?
54cflags-y += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,) 58cflags-y += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,)
55AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,) 59AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,)
56 60
57CFLAGS += $(cflags-y) 61CFLAGS += $(cflags-y)
58 62
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index 60c0c02574f0..97aacd6bd7d8 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -1,7 +1,7 @@
1# 1#
2# Automatically generated make config: don't edit 2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.19-rc1 3# Linux kernel version: 2.6.19-rc2-git4
4# Thu Oct 5 13:04:53 2006 4# Sat Oct 21 03:38:56 2006
5# 5#
6CONFIG_X86_32=y 6CONFIG_X86_32=y
7CONFIG_GENERIC_TIME=y 7CONFIG_GENERIC_TIME=y
@@ -380,8 +380,8 @@ CONFIG_INET6_XFRM_MODE_TRANSPORT=y
380CONFIG_INET6_XFRM_MODE_TUNNEL=y 380CONFIG_INET6_XFRM_MODE_TUNNEL=y
381# CONFIG_INET6_XFRM_MODE_BEET is not set 381# CONFIG_INET6_XFRM_MODE_BEET is not set
382# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set 382# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
383CONFIG_IPV6_SIT=y
383# CONFIG_IPV6_TUNNEL is not set 384# CONFIG_IPV6_TUNNEL is not set
384# CONFIG_IPV6_SUBTREES is not set
385# CONFIG_IPV6_MULTIPLE_TABLES is not set 385# CONFIG_IPV6_MULTIPLE_TABLES is not set
386# CONFIG_NETWORK_SECMARK is not set 386# CONFIG_NETWORK_SECMARK is not set
387# CONFIG_NETFILTER is not set 387# CONFIG_NETFILTER is not set
@@ -483,6 +483,13 @@ CONFIG_BLK_DEV_INITRD=y
483# CONFIG_ATA_OVER_ETH is not set 483# CONFIG_ATA_OVER_ETH is not set
484 484
485# 485#
486# Misc devices
487#
488# CONFIG_IBM_ASM is not set
489# CONFIG_SGI_IOC4 is not set
490# CONFIG_TIFM_CORE is not set
491
492#
486# ATA/ATAPI/MFM/RLL support 493# ATA/ATAPI/MFM/RLL support
487# 494#
488CONFIG_IDE=y 495CONFIG_IDE=y
@@ -1024,6 +1031,7 @@ CONFIG_HANGCHECK_TIMER=y
1024# 1031#
1025# Dallas's 1-wire bus 1032# Dallas's 1-wire bus
1026# 1033#
1034# CONFIG_W1 is not set
1027 1035
1028# 1036#
1029# Hardware Monitoring support 1037# Hardware Monitoring support
@@ -1032,12 +1040,6 @@ CONFIG_HANGCHECK_TIMER=y
1032# CONFIG_HWMON_VID is not set 1040# CONFIG_HWMON_VID is not set
1033 1041
1034# 1042#
1035# Misc devices
1036#
1037# CONFIG_IBM_ASM is not set
1038# CONFIG_TIFM_CORE is not set
1039
1040#
1041# Multimedia devices 1043# Multimedia devices
1042# 1044#
1043# CONFIG_VIDEO_DEV is not set 1045# CONFIG_VIDEO_DEV is not set
@@ -1169,7 +1171,6 @@ CONFIG_USB_HIDINPUT=y
1169# CONFIG_USB_ATI_REMOTE2 is not set 1171# CONFIG_USB_ATI_REMOTE2 is not set
1170# CONFIG_USB_KEYSPAN_REMOTE is not set 1172# CONFIG_USB_KEYSPAN_REMOTE is not set
1171# CONFIG_USB_APPLETOUCH is not set 1173# CONFIG_USB_APPLETOUCH is not set
1172# CONFIG_USB_TRANCEVIBRATOR is not set
1173 1174
1174# 1175#
1175# USB Imaging devices 1176# USB Imaging devices
@@ -1215,6 +1216,7 @@ CONFIG_USB_MON=y
1215# CONFIG_USB_APPLEDISPLAY is not set 1216# CONFIG_USB_APPLEDISPLAY is not set
1216# CONFIG_USB_SISUSBVGA is not set 1217# CONFIG_USB_SISUSBVGA is not set
1217# CONFIG_USB_LD is not set 1218# CONFIG_USB_LD is not set
1219# CONFIG_USB_TRANCEVIBRATOR is not set
1218# CONFIG_USB_TEST is not set 1220# CONFIG_USB_TEST is not set
1219 1221
1220# 1222#
@@ -1284,6 +1286,7 @@ CONFIG_EXT3_FS=y
1284CONFIG_EXT3_FS_XATTR=y 1286CONFIG_EXT3_FS_XATTR=y
1285CONFIG_EXT3_FS_POSIX_ACL=y 1287CONFIG_EXT3_FS_POSIX_ACL=y
1286# CONFIG_EXT3_FS_SECURITY is not set 1288# CONFIG_EXT3_FS_SECURITY is not set
1289# CONFIG_EXT4DEV_FS is not set
1287CONFIG_JBD=y 1290CONFIG_JBD=y
1288# CONFIG_JBD_DEBUG is not set 1291# CONFIG_JBD_DEBUG is not set
1289CONFIG_FS_MBCACHE=y 1292CONFIG_FS_MBCACHE=y
@@ -1307,6 +1310,7 @@ CONFIG_DNOTIFY=y
1307# CONFIG_AUTOFS_FS is not set 1310# CONFIG_AUTOFS_FS is not set
1308CONFIG_AUTOFS4_FS=y 1311CONFIG_AUTOFS4_FS=y
1309# CONFIG_FUSE_FS is not set 1312# CONFIG_FUSE_FS is not set
1313CONFIG_GENERIC_ACL=y
1310 1314
1311# 1315#
1312# CD-ROM/DVD Filesystems 1316# CD-ROM/DVD Filesystems
@@ -1384,7 +1388,6 @@ CONFIG_SUNRPC=y
1384# CONFIG_CODA_FS is not set 1388# CONFIG_CODA_FS is not set
1385# CONFIG_AFS_FS is not set 1389# CONFIG_AFS_FS is not set
1386# CONFIG_9P_FS is not set 1390# CONFIG_9P_FS is not set
1387CONFIG_GENERIC_ACL=y
1388 1391
1389# 1392#
1390# Partition Types 1393# Partition Types
@@ -1437,10 +1440,6 @@ CONFIG_NLS_ISO8859_15=y
1437CONFIG_NLS_UTF8=y 1440CONFIG_NLS_UTF8=y
1438 1441
1439# 1442#
1440# Distributed Lock Manager
1441#
1442
1443#
1444# Instrumentation Support 1443# Instrumentation Support
1445# 1444#
1446CONFIG_PROFILING=y 1445CONFIG_PROFILING=y
@@ -1480,6 +1479,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
1480CONFIG_UNWIND_INFO=y 1479CONFIG_UNWIND_INFO=y
1481CONFIG_STACK_UNWIND=y 1480CONFIG_STACK_UNWIND=y
1482# CONFIG_FORCED_INLINING is not set 1481# CONFIG_FORCED_INLINING is not set
1482# CONFIG_HEADERS_CHECK is not set
1483# CONFIG_RCU_TORTURE_TEST is not set 1483# CONFIG_RCU_TORTURE_TEST is not set
1484# CONFIG_LKDTM is not set 1484# CONFIG_LKDTM is not set
1485CONFIG_EARLY_PRINTK=y 1485CONFIG_EARLY_PRINTK=y
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index be9d883c62ce..ca31f18d277c 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -317,7 +317,7 @@ is386: movl $2,%ecx # set MP
317 movl %eax,%gs 317 movl %eax,%gs
318 lldt %ax 318 lldt %ax
319 cld # gcc2 wants the direction flag cleared at all times 319 cld # gcc2 wants the direction flag cleared at all times
320 pushl %eax # fake return address 320 pushl $0 # fake return address for unwinder
321#ifdef CONFIG_SMP 321#ifdef CONFIG_SMP
322 movb ready, %cl 322 movb ready, %cl
323 movb $1, ready 323 movb $1, ready
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index 3e8e3adb0489..eaafe233a5da 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -219,11 +219,11 @@ static int __init check_nmi_watchdog(void)
219 int cpu; 219 int cpu;
220 220
221 /* Enable NMI watchdog for newer systems. 221 /* Enable NMI watchdog for newer systems.
222 Actually it should be safe for most systems before 2004 too except 222 Probably safe on most older systems too, but let's be careful.
223 for some IBM systems that corrupt registers when NMI happens 223 IBM ThinkPads use INT10 inside SMM and that allows early NMI inside SMM
224 during SMM. Unfortunately we don't have more exact information 224 which hangs the system. Disable watchdog for all thinkpads */
225 on these and use this coarse check. */ 225 if (nmi_watchdog == NMI_DEFAULT && dmi_get_year(DMI_BIOS_DATE) >= 2004 &&
226 if (nmi_watchdog == NMI_DEFAULT && dmi_get_year(DMI_BIOS_DATE) >= 2004) 226 !dmi_name_in_vendors("ThinkPad"))
227 nmi_watchdog = NMI_LOCAL_APIC; 227 nmi_watchdog = NMI_LOCAL_APIC;
228 228
229 if ((nmi_watchdog == NMI_NONE) || (nmi_watchdog == NMI_DEFAULT)) 229 if ((nmi_watchdog == NMI_NONE) || (nmi_watchdog == NMI_DEFAULT))
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 57d375900afb..1e1fa3e391a3 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -336,7 +336,6 @@ extern void kernel_thread_helper(void);
336int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) 336int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
337{ 337{
338 struct pt_regs regs; 338 struct pt_regs regs;
339 int err;
340 339
341 memset(&regs, 0, sizeof(regs)); 340 memset(&regs, 0, sizeof(regs));
342 341
@@ -351,10 +350,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
351 regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2; 350 regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2;
352 351
353 /* Ok, create the new process.. */ 352 /* Ok, create the new process.. */
354 err = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL); 353 return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
355 if (err == 0) /* terminate kernel stack */
356 task_pt_regs(current)->eip = 0;
357 return err;
358} 354}
359EXPORT_SYMBOL(kernel_thread); 355EXPORT_SYMBOL(kernel_thread);
360 356
diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile
index 1c0f18d4f887..13972148058d 100644
--- a/arch/x86_64/Makefile
+++ b/arch/x86_64/Makefile
@@ -54,6 +54,10 @@ endif
54cflags-y += $(call cc-option,-funit-at-a-time) 54cflags-y += $(call cc-option,-funit-at-a-time)
55# prevent gcc from generating any FP code by mistake 55# prevent gcc from generating any FP code by mistake
56cflags-y += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,) 56cflags-y += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,)
57# this works around some issues with generating unwind tables in older gccs
58# newer gccs do it by default
59cflags-y += -maccumulate-outgoing-args
60
57# do binutils support CFI? 61# do binutils support CFI?
58cflags-y += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,) 62cflags-y += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
59AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,) 63AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig
index 47bfba6e9dc4..0f5d44e86be5 100644
--- a/arch/x86_64/defconfig
+++ b/arch/x86_64/defconfig
@@ -1,7 +1,7 @@
1# 1#
2# Automatically generated make config: don't edit 2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.19-rc1 3# Linux kernel version: 2.6.19-rc2-git4
4# Thu Oct 5 13:04:43 2006 4# Sat Oct 21 03:38:52 2006
5# 5#
6CONFIG_X86_64=y 6CONFIG_X86_64=y
7CONFIG_64BIT=y 7CONFIG_64BIT=y
@@ -335,8 +335,8 @@ CONFIG_IPV6=y
335# CONFIG_INET6_XFRM_MODE_TUNNEL is not set 335# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
336# CONFIG_INET6_XFRM_MODE_BEET is not set 336# CONFIG_INET6_XFRM_MODE_BEET is not set
337# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set 337# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
338CONFIG_IPV6_SIT=y
338# CONFIG_IPV6_TUNNEL is not set 339# CONFIG_IPV6_TUNNEL is not set
339# CONFIG_IPV6_SUBTREES is not set
340# CONFIG_IPV6_MULTIPLE_TABLES is not set 340# CONFIG_IPV6_MULTIPLE_TABLES is not set
341# CONFIG_NETWORK_SECMARK is not set 341# CONFIG_NETWORK_SECMARK is not set
342# CONFIG_NETFILTER is not set 342# CONFIG_NETFILTER is not set
@@ -438,6 +438,13 @@ CONFIG_BLK_DEV_INITRD=y
438# CONFIG_ATA_OVER_ETH is not set 438# CONFIG_ATA_OVER_ETH is not set
439 439
440# 440#
441# Misc devices
442#
443# CONFIG_IBM_ASM is not set
444# CONFIG_SGI_IOC4 is not set
445# CONFIG_TIFM_CORE is not set
446
447#
441# ATA/ATAPI/MFM/RLL support 448# ATA/ATAPI/MFM/RLL support
442# 449#
443CONFIG_IDE=y 450CONFIG_IDE=y
@@ -1008,6 +1015,7 @@ CONFIG_I2C_ISA=m
1008# 1015#
1009# Dallas's 1-wire bus 1016# Dallas's 1-wire bus
1010# 1017#
1018# CONFIG_W1 is not set
1011 1019
1012# 1020#
1013# Hardware Monitoring support 1021# Hardware Monitoring support
@@ -1059,12 +1067,6 @@ CONFIG_SENSORS_SMSC47B397=m
1059# CONFIG_HWMON_DEBUG_CHIP is not set 1067# CONFIG_HWMON_DEBUG_CHIP is not set
1060 1068
1061# 1069#
1062# Misc devices
1063#
1064# CONFIG_IBM_ASM is not set
1065# CONFIG_TIFM_CORE is not set
1066
1067#
1068# Multimedia devices 1070# Multimedia devices
1069# 1071#
1070# CONFIG_VIDEO_DEV is not set 1072# CONFIG_VIDEO_DEV is not set
@@ -1196,7 +1198,6 @@ CONFIG_USB_HIDINPUT=y
1196# CONFIG_USB_ATI_REMOTE2 is not set 1198# CONFIG_USB_ATI_REMOTE2 is not set
1197# CONFIG_USB_KEYSPAN_REMOTE is not set 1199# CONFIG_USB_KEYSPAN_REMOTE is not set
1198# CONFIG_USB_APPLETOUCH is not set 1200# CONFIG_USB_APPLETOUCH is not set
1199# CONFIG_USB_TRANCEVIBRATOR is not set
1200 1201
1201# 1202#
1202# USB Imaging devices 1203# USB Imaging devices
@@ -1242,6 +1243,7 @@ CONFIG_USB_MON=y
1242# CONFIG_USB_APPLEDISPLAY is not set 1243# CONFIG_USB_APPLEDISPLAY is not set
1243# CONFIG_USB_SISUSBVGA is not set 1244# CONFIG_USB_SISUSBVGA is not set
1244# CONFIG_USB_LD is not set 1245# CONFIG_USB_LD is not set
1246# CONFIG_USB_TRANCEVIBRATOR is not set
1245# CONFIG_USB_TEST is not set 1247# CONFIG_USB_TEST is not set
1246 1248
1247# 1249#
@@ -1318,6 +1320,7 @@ CONFIG_EXT3_FS=y
1318CONFIG_EXT3_FS_XATTR=y 1320CONFIG_EXT3_FS_XATTR=y
1319CONFIG_EXT3_FS_POSIX_ACL=y 1321CONFIG_EXT3_FS_POSIX_ACL=y
1320# CONFIG_EXT3_FS_SECURITY is not set 1322# CONFIG_EXT3_FS_SECURITY is not set
1323# CONFIG_EXT4DEV_FS is not set
1321CONFIG_JBD=y 1324CONFIG_JBD=y
1322# CONFIG_JBD_DEBUG is not set 1325# CONFIG_JBD_DEBUG is not set
1323CONFIG_FS_MBCACHE=y 1326CONFIG_FS_MBCACHE=y
@@ -1341,6 +1344,7 @@ CONFIG_DNOTIFY=y
1341# CONFIG_AUTOFS_FS is not set 1344# CONFIG_AUTOFS_FS is not set
1342CONFIG_AUTOFS4_FS=y 1345CONFIG_AUTOFS4_FS=y
1343# CONFIG_FUSE_FS is not set 1346# CONFIG_FUSE_FS is not set
1347CONFIG_GENERIC_ACL=y
1344 1348
1345# 1349#
1346# CD-ROM/DVD Filesystems 1350# CD-ROM/DVD Filesystems
@@ -1418,7 +1422,6 @@ CONFIG_SUNRPC=y
1418# CONFIG_CODA_FS is not set 1422# CONFIG_CODA_FS is not set
1419# CONFIG_AFS_FS is not set 1423# CONFIG_AFS_FS is not set
1420# CONFIG_9P_FS is not set 1424# CONFIG_9P_FS is not set
1421CONFIG_GENERIC_ACL=y
1422 1425
1423# 1426#
1424# Partition Types 1427# Partition Types
@@ -1471,10 +1474,6 @@ CONFIG_NLS_ISO8859_15=y
1471CONFIG_NLS_UTF8=y 1474CONFIG_NLS_UTF8=y
1472 1475
1473# 1476#
1474# Distributed Lock Manager
1475#
1476
1477#
1478# Instrumentation Support 1477# Instrumentation Support
1479# 1478#
1480CONFIG_PROFILING=y 1479CONFIG_PROFILING=y
@@ -1512,6 +1511,7 @@ CONFIG_DEBUG_FS=y
1512CONFIG_UNWIND_INFO=y 1511CONFIG_UNWIND_INFO=y
1513CONFIG_STACK_UNWIND=y 1512CONFIG_STACK_UNWIND=y
1514# CONFIG_FORCED_INLINING is not set 1513# CONFIG_FORCED_INLINING is not set
1514# CONFIG_HEADERS_CHECK is not set
1515# CONFIG_RCU_TORTURE_TEST is not set 1515# CONFIG_RCU_TORTURE_TEST is not set
1516# CONFIG_LKDTM is not set 1516# CONFIG_LKDTM is not set
1517# CONFIG_DEBUG_RODATA is not set 1517# CONFIG_DEBUG_RODATA is not set
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c
index b3f0908668ec..a75c829c2b02 100644
--- a/arch/x86_64/kernel/e820.c
+++ b/arch/x86_64/kernel/e820.c
@@ -54,13 +54,13 @@ static inline int bad_addr(unsigned long *addrp, unsigned long size)
54 54
55 /* various gunk below that needed for SMP startup */ 55 /* various gunk below that needed for SMP startup */
56 if (addr < 0x8000) { 56 if (addr < 0x8000) {
57 *addrp = 0x8000; 57 *addrp = PAGE_ALIGN(0x8000);
58 return 1; 58 return 1;
59 } 59 }
60 60
61 /* direct mapping tables of the kernel */ 61 /* direct mapping tables of the kernel */
62 if (last >= table_start<<PAGE_SHIFT && addr < table_end<<PAGE_SHIFT) { 62 if (last >= table_start<<PAGE_SHIFT && addr < table_end<<PAGE_SHIFT) {
63 *addrp = table_end << PAGE_SHIFT; 63 *addrp = PAGE_ALIGN(table_end << PAGE_SHIFT);
64 return 1; 64 return 1;
65 } 65 }
66 66
@@ -68,18 +68,18 @@ static inline int bad_addr(unsigned long *addrp, unsigned long size)
68#ifdef CONFIG_BLK_DEV_INITRD 68#ifdef CONFIG_BLK_DEV_INITRD
69 if (LOADER_TYPE && INITRD_START && last >= INITRD_START && 69 if (LOADER_TYPE && INITRD_START && last >= INITRD_START &&
70 addr < INITRD_START+INITRD_SIZE) { 70 addr < INITRD_START+INITRD_SIZE) {
71 *addrp = INITRD_START + INITRD_SIZE; 71 *addrp = PAGE_ALIGN(INITRD_START + INITRD_SIZE);
72 return 1; 72 return 1;
73 } 73 }
74#endif 74#endif
75 /* kernel code */ 75 /* kernel code */
76 if (last >= __pa_symbol(&_text) && last < __pa_symbol(&_end)) { 76 if (last >= __pa_symbol(&_text) && addr < __pa_symbol(&_end)) {
77 *addrp = __pa_symbol(&_end); 77 *addrp = PAGE_ALIGN(__pa_symbol(&_end));
78 return 1; 78 return 1;
79 } 79 }
80 80
81 if (last >= ebda_addr && addr < ebda_addr + ebda_size) { 81 if (last >= ebda_addr && addr < ebda_addr + ebda_size) {
82 *addrp = ebda_addr + ebda_size; 82 *addrp = PAGE_ALIGN(ebda_addr + ebda_size);
83 return 1; 83 return 1;
84 } 84 }
85 85
@@ -152,7 +152,7 @@ unsigned long __init find_e820_area(unsigned long start, unsigned long end, unsi
152 continue; 152 continue;
153 while (bad_addr(&addr, size) && addr+size <= ei->addr+ei->size) 153 while (bad_addr(&addr, size) && addr+size <= ei->addr+ei->size)
154 ; 154 ;
155 last = addr + size; 155 last = PAGE_ALIGN(addr) + size;
156 if (last > ei->addr + ei->size) 156 if (last > ei->addr + ei->size)
157 continue; 157 continue;
158 if (last > end) 158 if (last > end)
diff --git a/arch/x86_64/kernel/early-quirks.c b/arch/x86_64/kernel/early-quirks.c
index 208e38a372c1..2b1245d86258 100644
--- a/arch/x86_64/kernel/early-quirks.c
+++ b/arch/x86_64/kernel/early-quirks.c
@@ -61,10 +61,11 @@ static void nvidia_bugs(void)
61 61
62static void ati_bugs(void) 62static void ati_bugs(void)
63{ 63{
64#if 1 /* for testing */ 64 if (timer_over_8254 == 1) {
65 printk("ATI board detected\n"); 65 timer_over_8254 = 0;
66#endif 66 printk(KERN_INFO
67 /* No bugs right now */ 67 "ATI board detected. Disabling timer routing over 8254.\n");
68 }
68} 69}
69 70
70struct chipset { 71struct chipset {
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index 38a7b2d528e2..7d401b00d822 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -315,6 +315,8 @@ tracesys:
315 LOAD_ARGS ARGOFFSET /* reload args from stack in case ptrace changed it */ 315 LOAD_ARGS ARGOFFSET /* reload args from stack in case ptrace changed it */
316 RESTORE_REST 316 RESTORE_REST
317 cmpq $__NR_syscall_max,%rax 317 cmpq $__NR_syscall_max,%rax
318 movq $-ENOSYS,%rcx
319 cmova %rcx,%rax
318 ja 1f 320 ja 1f
319 movq %r10,%rcx /* fixup for C */ 321 movq %r10,%rcx /* fixup for C */
320 call *sys_call_table(,%rax,8) 322 call *sys_call_table(,%rax,8)
@@ -535,8 +537,6 @@ END(stub_rt_sigreturn)
5351: incl %gs:pda_irqcount 5371: incl %gs:pda_irqcount
536 cmoveq %gs:pda_irqstackptr,%rsp 538 cmoveq %gs:pda_irqstackptr,%rsp
537 push %rbp # backlink for old unwinder 539 push %rbp # backlink for old unwinder
538 CFI_ADJUST_CFA_OFFSET 8
539 CFI_REL_OFFSET rbp,0
540 /* 540 /*
541 * We entered an interrupt context - irqs are off: 541 * We entered an interrupt context - irqs are off:
542 */ 542 */
@@ -980,11 +980,6 @@ ENTRY(kernel_thread)
980 call do_fork 980 call do_fork
981 movq %rax,RAX(%rsp) 981 movq %rax,RAX(%rsp)
982 xorl %edi,%edi 982 xorl %edi,%edi
983 test %rax,%rax
984 jnz 1f
985 /* terminate stack in child */
986 movq %rdi,RIP(%rsp)
9871:
988 983
989 /* 984 /*
990 * It isn't worth to check for reschedule here, 985 * It isn't worth to check for reschedule here,
@@ -1176,7 +1171,6 @@ ENTRY(call_softirq)
1176 incl %gs:pda_irqcount 1171 incl %gs:pda_irqcount
1177 cmove %gs:pda_irqstackptr,%rsp 1172 cmove %gs:pda_irqstackptr,%rsp
1178 push %rbp # backlink for old unwinder 1173 push %rbp # backlink for old unwinder
1179 CFI_ADJUST_CFA_OFFSET 8
1180 call __do_softirq 1174 call __do_softirq
1181 leaveq 1175 leaveq
1182 CFI_DEF_CFA_REGISTER rsp 1176 CFI_DEF_CFA_REGISTER rsp
diff --git a/arch/x86_64/kernel/genapic_flat.c b/arch/x86_64/kernel/genapic_flat.c
index 0dfc223c1839..7c01db8fa9d1 100644
--- a/arch/x86_64/kernel/genapic_flat.c
+++ b/arch/x86_64/kernel/genapic_flat.c
@@ -153,7 +153,7 @@ struct genapic apic_flat = {
153 153
154static cpumask_t physflat_target_cpus(void) 154static cpumask_t physflat_target_cpus(void)
155{ 155{
156 return cpumask_of_cpu(0); 156 return cpu_online_map;
157} 157}
158 158
159static cpumask_t physflat_vector_allocation_domain(int cpu) 159static cpumask_t physflat_vector_allocation_domain(int cpu)
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index 49e94f7994c5..b000017e4b5d 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -57,7 +57,7 @@ static int no_timer_check;
57 57
58static int disable_timer_pin_1 __initdata; 58static int disable_timer_pin_1 __initdata;
59 59
60int timer_over_8254 __initdata = 0; 60int timer_over_8254 __initdata = 1;
61 61
62/* Where if anywhere is the i8259 connect in external int mode */ 62/* Where if anywhere is the i8259 connect in external int mode */
63static struct { int pin, apic; } ioapic_i8259 = { -1, -1 }; 63static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
@@ -651,12 +651,12 @@ next:
651 if (vector == IA32_SYSCALL_VECTOR) 651 if (vector == IA32_SYSCALL_VECTOR)
652 goto next; 652 goto next;
653 for_each_cpu_mask(new_cpu, domain) 653 for_each_cpu_mask(new_cpu, domain)
654 if (per_cpu(vector_irq, cpu)[vector] != -1) 654 if (per_cpu(vector_irq, new_cpu)[vector] != -1)
655 goto next; 655 goto next;
656 /* Found one! */ 656 /* Found one! */
657 for_each_cpu_mask(new_cpu, domain) { 657 for_each_cpu_mask(new_cpu, domain) {
658 pos[cpu].vector = vector; 658 pos[new_cpu].vector = vector;
659 pos[cpu].offset = offset; 659 pos[new_cpu].offset = offset;
660 } 660 }
661 if (old_vector >= 0) { 661 if (old_vector >= 0) {
662 int old_cpu; 662 int old_cpu;
@@ -1255,12 +1255,15 @@ static int ioapic_retrigger_irq(unsigned int irq)
1255{ 1255{
1256 cpumask_t mask; 1256 cpumask_t mask;
1257 unsigned vector; 1257 unsigned vector;
1258 unsigned long flags;
1258 1259
1260 spin_lock_irqsave(&vector_lock, flags);
1259 vector = irq_vector[irq]; 1261 vector = irq_vector[irq];
1260 cpus_clear(mask); 1262 cpus_clear(mask);
1261 cpu_set(vector >> 8, mask); 1263 cpu_set(first_cpu(irq_domain[irq]), mask);
1262 1264
1263 send_IPI_mask(mask, vector & 0xff); 1265 send_IPI_mask(mask, vector);
1266 spin_unlock_irqrestore(&vector_lock, flags);
1264 1267
1265 return 1; 1268 return 1;
1266} 1269}
diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S
index b9df2ab6529f..1283614c9b24 100644
--- a/arch/x86_64/kernel/vmlinux.lds.S
+++ b/arch/x86_64/kernel/vmlinux.lds.S
@@ -17,6 +17,7 @@ PHDRS {
17 text PT_LOAD FLAGS(5); /* R_E */ 17 text PT_LOAD FLAGS(5); /* R_E */
18 data PT_LOAD FLAGS(7); /* RWE */ 18 data PT_LOAD FLAGS(7); /* RWE */
19 user PT_LOAD FLAGS(7); /* RWE */ 19 user PT_LOAD FLAGS(7); /* RWE */
20 data.init PT_LOAD FLAGS(7); /* RWE */
20 note PT_NOTE FLAGS(4); /* R__ */ 21 note PT_NOTE FLAGS(4); /* R__ */
21} 22}
22SECTIONS 23SECTIONS
@@ -131,7 +132,7 @@ SECTIONS
131 . = ALIGN(8192); /* init_task */ 132 . = ALIGN(8192); /* init_task */
132 .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) { 133 .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
133 *(.data.init_task) 134 *(.data.init_task)
134 } :data 135 }:data.init
135 136
136 . = ALIGN(4096); 137 . = ALIGN(4096);
137 .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) { 138 .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c
index 3cc0544e25f5..1087e150a218 100644
--- a/arch/x86_64/mm/srat.c
+++ b/arch/x86_64/mm/srat.c
@@ -207,7 +207,7 @@ static inline int save_add_info(void)
207 return hotadd_percent > 0; 207 return hotadd_percent > 0;
208} 208}
209#else 209#else
210int update_end_of_memory(unsigned long end) {return 0;} 210int update_end_of_memory(unsigned long end) {return -1;}
211static int hotadd_enough_memory(struct bootnode *nd) {return 1;} 211static int hotadd_enough_memory(struct bootnode *nd) {return 1;}
212#ifdef CONFIG_MEMORY_HOTPLUG_SPARSE 212#ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
213static inline int save_add_info(void) {return 1;} 213static inline int save_add_info(void) {return 1;}
@@ -337,7 +337,7 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma)
337 push_node_boundaries(node, nd->start >> PAGE_SHIFT, 337 push_node_boundaries(node, nd->start >> PAGE_SHIFT,
338 nd->end >> PAGE_SHIFT); 338 nd->end >> PAGE_SHIFT);
339 339
340 if (ma->flags.hot_pluggable && !reserve_hotadd(node, start, end) < 0) { 340 if (ma->flags.hot_pluggable && (reserve_hotadd(node, start, end) < 0)) {
341 /* Ignore hotadd region. Undo damage */ 341 /* Ignore hotadd region. Undo damage */
342 printk(KERN_NOTICE "SRAT: Hotplug region ignored\n"); 342 printk(KERN_NOTICE "SRAT: Hotplug region ignored\n");
343 *nd = oldnode; 343 *nd = oldnode;
diff --git a/arch/x86_64/pci/Makefile b/arch/x86_64/pci/Makefile
index 1eb18f421edf..149aba05a5b8 100644
--- a/arch/x86_64/pci/Makefile
+++ b/arch/x86_64/pci/Makefile
@@ -3,7 +3,7 @@
3# 3#
4# Reuse the i386 PCI subsystem 4# Reuse the i386 PCI subsystem
5# 5#
6CFLAGS += -Iarch/i386/pci 6EXTRA_CFLAGS += -Iarch/i386/pci
7 7
8obj-y := i386.o 8obj-y := i386.o
9obj-$(CONFIG_PCI_DIRECT)+= direct.o 9obj-$(CONFIG_PCI_DIRECT)+= direct.o
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index b8b596d5778d..37deee6c0c1c 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -326,6 +326,26 @@ char *dmi_get_system_info(int field)
326} 326}
327EXPORT_SYMBOL(dmi_get_system_info); 327EXPORT_SYMBOL(dmi_get_system_info);
328 328
329
330/**
331 * dmi_name_in_vendors - Check if string is anywhere in the DMI vendor information.
332 * @str: Case sensitive Name
333 */
334int dmi_name_in_vendors(char *str)
335{
336 static int fields[] = { DMI_BIOS_VENDOR, DMI_BIOS_VERSION, DMI_SYS_VENDOR,
337 DMI_PRODUCT_NAME, DMI_PRODUCT_VERSION, DMI_BOARD_VENDOR,
338 DMI_BOARD_NAME, DMI_BOARD_VERSION, DMI_NONE };
339 int i;
340 for (i = 0; fields[i] != DMI_NONE; i++) {
341 int f = fields[i];
342 if (dmi_ident[f] && strstr(dmi_ident[f], str))
343 return 1;
344 }
345 return 0;
346}
347EXPORT_SYMBOL(dmi_name_in_vendors);
348
329/** 349/**
330 * dmi_find_device - find onboard device by type/name 350 * dmi_find_device - find onboard device by type/name
331 * @type: device type or %DMI_DEV_TYPE_ANY to match all device types 351 * @type: device type or %DMI_DEV_TYPE_ANY to match all device types
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 69240b52f8e1..9d0d11c180d9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -125,6 +125,10 @@
125 *(__param) \ 125 *(__param) \
126 VMLINUX_SYMBOL(__stop___param) = .; \ 126 VMLINUX_SYMBOL(__stop___param) = .; \
127 } \ 127 } \
128 \
129 /* Unwind data binary search table */ \
130 EH_FRAME_HDR \
131 \
128 __end_rodata = .; \ 132 __end_rodata = .; \
129 . = ALIGN(4096); 133 . = ALIGN(4096);
130 134
@@ -157,6 +161,18 @@
157 *(.kprobes.text) \ 161 *(.kprobes.text) \
158 VMLINUX_SYMBOL(__kprobes_text_end) = .; 162 VMLINUX_SYMBOL(__kprobes_text_end) = .;
159 163
164#ifdef CONFIG_STACK_UNWIND
165 /* Unwind data binary search table */
166#define EH_FRAME_HDR \
167 .eh_frame_hdr : AT(ADDR(.eh_frame_hdr) - LOAD_OFFSET) { \
168 VMLINUX_SYMBOL(__start_unwind_hdr) = .; \
169 *(.eh_frame_hdr) \
170 VMLINUX_SYMBOL(__end_unwind_hdr) = .; \
171 }
172#else
173#define EH_FRAME_HDR
174#endif
175
160 /* DWARF debug sections. 176 /* DWARF debug sections.
161 Symbols in the DWARF debugging sections are relative to 177 Symbols in the DWARF debugging sections are relative to
162 the beginning of the section so we begin them at 0. */ 178 the beginning of the section so we begin them at 0. */
diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h
index 6899e770b173..0555c1c4d8fa 100644
--- a/include/asm-x86_64/pgtable.h
+++ b/include/asm-x86_64/pgtable.h
@@ -366,6 +366,7 @@ static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
366{ 366{
367 pte_t pte; 367 pte_t pte;
368 pte_val(pte) = physpage | pgprot_val(pgprot); 368 pte_val(pte) = physpage | pgprot_val(pgprot);
369 pte_val(pte) &= __supported_pte_mask;
369 return pte; 370 return pte;
370} 371}
371 372
diff --git a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h
index c181fef786e4..e72cfcdf5344 100644
--- a/include/asm-x86_64/proto.h
+++ b/include/asm-x86_64/proto.h
@@ -122,6 +122,8 @@ extern int fix_aperture;
122extern int reboot_force; 122extern int reboot_force;
123extern int notsc_setup(char *); 123extern int notsc_setup(char *);
124 124
125extern int timer_over_8254;
126
125extern int gsi_irq_sharing(int gsi); 127extern int gsi_irq_sharing(int gsi);
126 128
127extern void smp_local_timer_interrupt(void); 129extern void smp_local_timer_interrupt(void);
diff --git a/include/linux/dmi.h b/include/linux/dmi.h
index 38dc403be70b..904bf3d2d90b 100644
--- a/include/linux/dmi.h
+++ b/include/linux/dmi.h
@@ -69,6 +69,7 @@ extern struct dmi_device * dmi_find_device(int type, const char *name,
69 struct dmi_device *from); 69 struct dmi_device *from);
70extern void dmi_scan_machine(void); 70extern void dmi_scan_machine(void);
71extern int dmi_get_year(int field); 71extern int dmi_get_year(int field);
72extern int dmi_name_in_vendors(char *str);
72 73
73#else 74#else
74 75
@@ -77,6 +78,7 @@ static inline char * dmi_get_system_info(int field) { return NULL; }
77static inline struct dmi_device * dmi_find_device(int type, const char *name, 78static inline struct dmi_device * dmi_find_device(int type, const char *name,
78 struct dmi_device *from) { return NULL; } 79 struct dmi_device *from) { return NULL; }
79static inline int dmi_get_year(int year) { return 0; } 80static inline int dmi_get_year(int year) { return 0; }
81static inline int dmi_name_in_vendors(char *s) { return 0; }
80 82
81#endif 83#endif
82 84
diff --git a/include/linux/unwind.h b/include/linux/unwind.h
index 73e1751d03dd..749928c161fb 100644
--- a/include/linux/unwind.h
+++ b/include/linux/unwind.h
@@ -26,6 +26,7 @@ struct module;
26 * Initialize unwind support. 26 * Initialize unwind support.
27 */ 27 */
28extern void unwind_init(void); 28extern void unwind_init(void);
29extern void unwind_setup(void);
29 30
30#ifdef CONFIG_MODULES 31#ifdef CONFIG_MODULES
31 32
@@ -73,6 +74,7 @@ extern int unwind_to_user(struct unwind_frame_info *);
73struct unwind_frame_info {}; 74struct unwind_frame_info {};
74 75
75static inline void unwind_init(void) {} 76static inline void unwind_init(void) {}
77static inline void unwind_setup(void) {}
76 78
77#ifdef CONFIG_MODULES 79#ifdef CONFIG_MODULES
78 80
diff --git a/init/main.c b/init/main.c
index ee123243fb53..36f608a7cfba 100644
--- a/init/main.c
+++ b/init/main.c
@@ -503,6 +503,7 @@ asmlinkage void __init start_kernel(void)
503 printk(KERN_NOTICE); 503 printk(KERN_NOTICE);
504 printk(linux_banner); 504 printk(linux_banner);
505 setup_arch(&command_line); 505 setup_arch(&command_line);
506 unwind_setup();
506 setup_per_cpu_areas(); 507 setup_per_cpu_areas();
507 smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */ 508 smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */
508 509
diff --git a/kernel/unwind.c b/kernel/unwind.c
index 2e2368607aab..f7e50d16dbf6 100644
--- a/kernel/unwind.c
+++ b/kernel/unwind.c
@@ -11,13 +11,15 @@
11 11
12#include <linux/unwind.h> 12#include <linux/unwind.h>
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/delay.h> 14#include <linux/bootmem.h>
15#include <linux/sort.h>
15#include <linux/stop_machine.h> 16#include <linux/stop_machine.h>
16#include <asm/sections.h> 17#include <asm/sections.h>
17#include <asm/uaccess.h> 18#include <asm/uaccess.h>
18#include <asm/unaligned.h> 19#include <asm/unaligned.h>
19 20
20extern char __start_unwind[], __end_unwind[]; 21extern char __start_unwind[], __end_unwind[];
22extern const u8 __start_unwind_hdr[], __end_unwind_hdr[];
21 23
22#define MAX_STACK_DEPTH 8 24#define MAX_STACK_DEPTH 8
23 25
@@ -100,6 +102,8 @@ static struct unwind_table {
100 } core, init; 102 } core, init;
101 const void *address; 103 const void *address;
102 unsigned long size; 104 unsigned long size;
105 const unsigned char *header;
106 unsigned long hdrsz;
103 struct unwind_table *link; 107 struct unwind_table *link;
104 const char *name; 108 const char *name;
105} root_table; 109} root_table;
@@ -145,6 +149,10 @@ static struct unwind_table *find_table(unsigned long pc)
145 return table; 149 return table;
146} 150}
147 151
152static unsigned long read_pointer(const u8 **pLoc,
153 const void *end,
154 signed ptrType);
155
148static void init_unwind_table(struct unwind_table *table, 156static void init_unwind_table(struct unwind_table *table,
149 const char *name, 157 const char *name,
150 const void *core_start, 158 const void *core_start,
@@ -152,14 +160,30 @@ static void init_unwind_table(struct unwind_table *table,
152 const void *init_start, 160 const void *init_start,
153 unsigned long init_size, 161 unsigned long init_size,
154 const void *table_start, 162 const void *table_start,
155 unsigned long table_size) 163 unsigned long table_size,
164 const u8 *header_start,
165 unsigned long header_size)
156{ 166{
167 const u8 *ptr = header_start + 4;
168 const u8 *end = header_start + header_size;
169
157 table->core.pc = (unsigned long)core_start; 170 table->core.pc = (unsigned long)core_start;
158 table->core.range = core_size; 171 table->core.range = core_size;
159 table->init.pc = (unsigned long)init_start; 172 table->init.pc = (unsigned long)init_start;
160 table->init.range = init_size; 173 table->init.range = init_size;
161 table->address = table_start; 174 table->address = table_start;
162 table->size = table_size; 175 table->size = table_size;
176 /* See if the linker provided table looks valid. */
177 if (header_size <= 4
178 || header_start[0] != 1
179 || (void *)read_pointer(&ptr, end, header_start[1]) != table_start
180 || header_start[2] == DW_EH_PE_omit
181 || read_pointer(&ptr, end, header_start[2]) <= 0
182 || header_start[3] == DW_EH_PE_omit)
183 header_start = NULL;
184 table->hdrsz = header_size;
185 smp_wmb();
186 table->header = header_start;
163 table->link = NULL; 187 table->link = NULL;
164 table->name = name; 188 table->name = name;
165} 189}
@@ -169,7 +193,143 @@ void __init unwind_init(void)
169 init_unwind_table(&root_table, "kernel", 193 init_unwind_table(&root_table, "kernel",
170 _text, _end - _text, 194 _text, _end - _text,
171 NULL, 0, 195 NULL, 0,
172 __start_unwind, __end_unwind - __start_unwind); 196 __start_unwind, __end_unwind - __start_unwind,
197 __start_unwind_hdr, __end_unwind_hdr - __start_unwind_hdr);
198}
199
200static const u32 bad_cie, not_fde;
201static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *);
202static signed fde_pointer_type(const u32 *cie);
203
204struct eh_frame_hdr_table_entry {
205 unsigned long start, fde;
206};
207
208static int cmp_eh_frame_hdr_table_entries(const void *p1, const void *p2)
209{
210 const struct eh_frame_hdr_table_entry *e1 = p1;
211 const struct eh_frame_hdr_table_entry *e2 = p2;
212
213 return (e1->start > e2->start) - (e1->start < e2->start);
214}
215
216static void swap_eh_frame_hdr_table_entries(void *p1, void *p2, int size)
217{
218 struct eh_frame_hdr_table_entry *e1 = p1;
219 struct eh_frame_hdr_table_entry *e2 = p2;
220 unsigned long v;
221
222 v = e1->start;
223 e1->start = e2->start;
224 e2->start = v;
225 v = e1->fde;
226 e1->fde = e2->fde;
227 e2->fde = v;
228}
229
230static void __init setup_unwind_table(struct unwind_table *table,
231 void *(*alloc)(unsigned long))
232{
233 const u8 *ptr;
234 unsigned long tableSize = table->size, hdrSize;
235 unsigned n;
236 const u32 *fde;
237 struct {
238 u8 version;
239 u8 eh_frame_ptr_enc;
240 u8 fde_count_enc;
241 u8 table_enc;
242 unsigned long eh_frame_ptr;
243 unsigned int fde_count;
244 struct eh_frame_hdr_table_entry table[];
245 } __attribute__((__packed__)) *header;
246
247 if (table->header)
248 return;
249
250 if (table->hdrsz)
251 printk(KERN_WARNING ".eh_frame_hdr for '%s' present but unusable\n",
252 table->name);
253
254 if (tableSize & (sizeof(*fde) - 1))
255 return;
256
257 for (fde = table->address, n = 0;
258 tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde;
259 tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
260 const u32 *cie = cie_for_fde(fde, table);
261 signed ptrType;
262
263 if (cie == &not_fde)
264 continue;
265 if (cie == NULL
266 || cie == &bad_cie
267 || (ptrType = fde_pointer_type(cie)) < 0)
268 return;
269 ptr = (const u8 *)(fde + 2);
270 if (!read_pointer(&ptr,
271 (const u8 *)(fde + 1) + *fde,
272 ptrType))
273 return;
274 ++n;
275 }
276
277 if (tableSize || !n)
278 return;
279
280 hdrSize = 4 + sizeof(unsigned long) + sizeof(unsigned int)
281 + 2 * n * sizeof(unsigned long);
282 header = alloc(hdrSize);
283 if (!header)
284 return;
285 header->version = 1;
286 header->eh_frame_ptr_enc = DW_EH_PE_abs|DW_EH_PE_native;
287 header->fde_count_enc = DW_EH_PE_abs|DW_EH_PE_data4;
288 header->table_enc = DW_EH_PE_abs|DW_EH_PE_native;
289 put_unaligned((unsigned long)table->address, &header->eh_frame_ptr);
290 BUILD_BUG_ON(offsetof(typeof(*header), fde_count)
291 % __alignof(typeof(header->fde_count)));
292 header->fde_count = n;
293
294 BUILD_BUG_ON(offsetof(typeof(*header), table)
295 % __alignof(typeof(*header->table)));
296 for (fde = table->address, tableSize = table->size, n = 0;
297 tableSize;
298 tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
299 const u32 *cie = fde + 1 - fde[1] / sizeof(*fde);
300
301 if (!fde[1])
302 continue; /* this is a CIE */
303 ptr = (const u8 *)(fde + 2);
304 header->table[n].start = read_pointer(&ptr,
305 (const u8 *)(fde + 1) + *fde,
306 fde_pointer_type(cie));
307 header->table[n].fde = (unsigned long)fde;
308 ++n;
309 }
310 WARN_ON(n != header->fde_count);
311
312 sort(header->table,
313 n,
314 sizeof(*header->table),
315 cmp_eh_frame_hdr_table_entries,
316 swap_eh_frame_hdr_table_entries);
317
318 table->hdrsz = hdrSize;
319 smp_wmb();
320 table->header = (const void *)header;
321}
322
323static void *__init balloc(unsigned long sz)
324{
325 return __alloc_bootmem_nopanic(sz,
326 sizeof(unsigned int),
327 __pa(MAX_DMA_ADDRESS));
328}
329
330void __init unwind_setup(void)
331{
332 setup_unwind_table(&root_table, balloc);
173} 333}
174 334
175#ifdef CONFIG_MODULES 335#ifdef CONFIG_MODULES
@@ -193,7 +353,8 @@ void *unwind_add_table(struct module *module,
193 init_unwind_table(table, module->name, 353 init_unwind_table(table, module->name,
194 module->module_core, module->core_size, 354 module->module_core, module->core_size,
195 module->module_init, module->init_size, 355 module->module_init, module->init_size,
196 table_start, table_size); 356 table_start, table_size,
357 NULL, 0);
197 358
198 if (last_table) 359 if (last_table)
199 last_table->link = table; 360 last_table->link = table;
@@ -303,6 +464,26 @@ static sleb128_t get_sleb128(const u8 **pcur, const u8 *end)
303 return value; 464 return value;
304} 465}
305 466
467static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *table)
468{
469 const u32 *cie;
470
471 if (!*fde || (*fde & (sizeof(*fde) - 1)))
472 return &bad_cie;
473 if (!fde[1])
474 return &not_fde; /* this is a CIE */
475 if ((fde[1] & (sizeof(*fde) - 1))
476 || fde[1] > (unsigned long)(fde + 1) - (unsigned long)table->address)
477 return NULL; /* this is not a valid FDE */
478 cie = fde + 1 - fde[1] / sizeof(*fde);
479 if (*cie <= sizeof(*cie) + 4
480 || *cie >= fde[1] - sizeof(*fde)
481 || (*cie & (sizeof(*cie) - 1))
482 || cie[1])
483 return NULL; /* this is not a (valid) CIE */
484 return cie;
485}
486
306static unsigned long read_pointer(const u8 **pLoc, 487static unsigned long read_pointer(const u8 **pLoc,
307 const void *end, 488 const void *end,
308 signed ptrType) 489 signed ptrType)
@@ -610,49 +791,108 @@ int unwind(struct unwind_frame_info *frame)
610 unsigned i; 791 unsigned i;
611 signed ptrType = -1; 792 signed ptrType = -1;
612 uleb128_t retAddrReg = 0; 793 uleb128_t retAddrReg = 0;
613 struct unwind_table *table; 794 const struct unwind_table *table;
614 struct unwind_state state; 795 struct unwind_state state;
615 796
616 if (UNW_PC(frame) == 0) 797 if (UNW_PC(frame) == 0)
617 return -EINVAL; 798 return -EINVAL;
618 if ((table = find_table(pc)) != NULL 799 if ((table = find_table(pc)) != NULL
619 && !(table->size & (sizeof(*fde) - 1))) { 800 && !(table->size & (sizeof(*fde) - 1))) {
620 unsigned long tableSize = table->size; 801 const u8 *hdr = table->header;
621 802 unsigned long tableSize;
622 for (fde = table->address; 803
623 tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde; 804 smp_rmb();
624 tableSize -= sizeof(*fde) + *fde, 805 if (hdr && hdr[0] == 1) {
625 fde += 1 + *fde / sizeof(*fde)) { 806 switch(hdr[3] & DW_EH_PE_FORM) {
626 if (!*fde || (*fde & (sizeof(*fde) - 1))) 807 case DW_EH_PE_native: tableSize = sizeof(unsigned long); break;
627 break; 808 case DW_EH_PE_data2: tableSize = 2; break;
628 if (!fde[1]) 809 case DW_EH_PE_data4: tableSize = 4; break;
629 continue; /* this is a CIE */ 810 case DW_EH_PE_data8: tableSize = 8; break;
630 if ((fde[1] & (sizeof(*fde) - 1)) 811 default: tableSize = 0; break;
631 || fde[1] > (unsigned long)(fde + 1) 812 }
632 - (unsigned long)table->address) 813 ptr = hdr + 4;
633 continue; /* this is not a valid FDE */ 814 end = hdr + table->hdrsz;
634 cie = fde + 1 - fde[1] / sizeof(*fde); 815 if (tableSize
635 if (*cie <= sizeof(*cie) + 4 816 && read_pointer(&ptr, end, hdr[1])
636 || *cie >= fde[1] - sizeof(*fde) 817 == (unsigned long)table->address
637 || (*cie & (sizeof(*cie) - 1)) 818 && (i = read_pointer(&ptr, end, hdr[2])) > 0
638 || cie[1] 819 && i == (end - ptr) / (2 * tableSize)
639 || (ptrType = fde_pointer_type(cie)) < 0) { 820 && !((end - ptr) % (2 * tableSize))) {
640 cie = NULL; /* this is not a (valid) CIE */ 821 do {
641 continue; 822 const u8 *cur = ptr + (i / 2) * (2 * tableSize);
823
824 startLoc = read_pointer(&cur,
825 cur + tableSize,
826 hdr[3]);
827 if (pc < startLoc)
828 i /= 2;
829 else {
830 ptr = cur - tableSize;
831 i = (i + 1) / 2;
832 }
833 } while (startLoc && i > 1);
834 if (i == 1
835 && (startLoc = read_pointer(&ptr,
836 ptr + tableSize,
837 hdr[3])) != 0
838 && pc >= startLoc)
839 fde = (void *)read_pointer(&ptr,
840 ptr + tableSize,
841 hdr[3]);
642 } 842 }
843 }
844
845 if (fde != NULL) {
846 cie = cie_for_fde(fde, table);
643 ptr = (const u8 *)(fde + 2); 847 ptr = (const u8 *)(fde + 2);
644 startLoc = read_pointer(&ptr, 848 if(cie != NULL
645 (const u8 *)(fde + 1) + *fde, 849 && cie != &bad_cie
646 ptrType); 850 && cie != &not_fde
647 endLoc = startLoc 851 && (ptrType = fde_pointer_type(cie)) >= 0
648 + read_pointer(&ptr, 852 && read_pointer(&ptr,
649 (const u8 *)(fde + 1) + *fde, 853 (const u8 *)(fde + 1) + *fde,
650 ptrType & DW_EH_PE_indirect 854 ptrType) == startLoc) {
651 ? ptrType 855 if (!(ptrType & DW_EH_PE_indirect))
652 : ptrType & (DW_EH_PE_FORM|DW_EH_PE_signed)); 856 ptrType &= DW_EH_PE_FORM|DW_EH_PE_signed;
653 if (pc >= startLoc && pc < endLoc) 857 endLoc = startLoc
654 break; 858 + read_pointer(&ptr,
655 cie = NULL; 859 (const u8 *)(fde + 1) + *fde,
860 ptrType);
861 if(pc >= endLoc)
862 fde = NULL;
863 } else
864 fde = NULL;
865 }
866 if (fde == NULL) {
867 for (fde = table->address, tableSize = table->size;
868 cie = NULL, tableSize > sizeof(*fde)
869 && tableSize - sizeof(*fde) >= *fde;
870 tableSize -= sizeof(*fde) + *fde,
871 fde += 1 + *fde / sizeof(*fde)) {
872 cie = cie_for_fde(fde, table);
873 if (cie == &bad_cie) {
874 cie = NULL;
875 break;
876 }
877 if (cie == NULL
878 || cie == &not_fde
879 || (ptrType = fde_pointer_type(cie)) < 0)
880 continue;
881 ptr = (const u8 *)(fde + 2);
882 startLoc = read_pointer(&ptr,
883 (const u8 *)(fde + 1) + *fde,
884 ptrType);
885 if (!startLoc)
886 continue;
887 if (!(ptrType & DW_EH_PE_indirect))
888 ptrType &= DW_EH_PE_FORM|DW_EH_PE_signed;
889 endLoc = startLoc
890 + read_pointer(&ptr,
891 (const u8 *)(fde + 1) + *fde,
892 ptrType);
893 if (pc >= startLoc && pc < endLoc)
894 break;
895 }
656 } 896 }
657 } 897 }
658 if (cie != NULL) { 898 if (cie != NULL) {