diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-07-26 09:38:48 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-07-26 09:38:48 -0400 |
commit | bda307ed7bdc160fcf1475a49f6c2e796fcb1294 (patch) | |
tree | aa24926a83001373cb4ac2d8be9fd1b6994e7c60 /arch/x86/kernel | |
parent | 0791e13fbb1ea4e1808d055922c3f116b924bdc9 (diff) | |
parent | 024e8ac04453b3525448c31ef39848cf675ba6db (diff) |
Merge branch 'linus' into x86/cleanups
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r-- | arch/x86/kernel/acpi/sleep.c | 4 | ||||
-rw-r--r-- | arch/x86/kernel/apm_32.c | 1 | ||||
-rw-r--r-- | arch/x86/kernel/hpet.c | 10 | ||||
-rw-r--r-- | arch/x86/kernel/irqinit_64.c | 5 | ||||
-rw-r--r-- | arch/x86/kernel/kprobes.c | 6 | ||||
-rw-r--r-- | arch/x86/kernel/module_64.c | 1 | ||||
-rw-r--r-- | arch/x86/kernel/pci-calgary_64.c | 85 | ||||
-rw-r--r-- | arch/x86/kernel/process_32.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/process_64.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/setup.c | 5 | ||||
-rw-r--r-- | arch/x86/kernel/signal_64.c | 53 | ||||
-rw-r--r-- | arch/x86/kernel/syscall_table_32.S | 6 |
12 files changed, 158 insertions, 22 deletions
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index a3ddad18aaa3..fa2161d5003b 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c | |||
@@ -150,6 +150,10 @@ static int __init acpi_sleep_setup(char *str) | |||
150 | acpi_realmode_flags |= 2; | 150 | acpi_realmode_flags |= 2; |
151 | if (strncmp(str, "s3_beep", 7) == 0) | 151 | if (strncmp(str, "s3_beep", 7) == 0) |
152 | acpi_realmode_flags |= 4; | 152 | acpi_realmode_flags |= 4; |
153 | #ifdef CONFIG_HIBERNATION | ||
154 | if (strncmp(str, "s4_nohwsig", 10) == 0) | ||
155 | acpi_no_s4_hw_signature(); | ||
156 | #endif | ||
153 | if (strncmp(str, "old_ordering", 12) == 0) | 157 | if (strncmp(str, "old_ordering", 12) == 0) |
154 | acpi_old_suspend_ordering(); | 158 | acpi_old_suspend_ordering(); |
155 | str = strchr(str, ','); | 159 | str = strchr(str, ','); |
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c index bf9b441331e9..9ee24e6bc4b0 100644 --- a/arch/x86/kernel/apm_32.c +++ b/arch/x86/kernel/apm_32.c | |||
@@ -219,7 +219,6 @@ | |||
219 | #include <linux/time.h> | 219 | #include <linux/time.h> |
220 | #include <linux/sched.h> | 220 | #include <linux/sched.h> |
221 | #include <linux/pm.h> | 221 | #include <linux/pm.h> |
222 | #include <linux/pm_legacy.h> | ||
223 | #include <linux/capability.h> | 222 | #include <linux/capability.h> |
224 | #include <linux/device.h> | 223 | #include <linux/device.h> |
225 | #include <linux/kernel.h> | 224 | #include <linux/kernel.h> |
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index 0ea6a19bfdfe..ad2b15a1334d 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c | |||
@@ -468,7 +468,7 @@ void hpet_disable(void) | |||
468 | #define RTC_NUM_INTS 1 | 468 | #define RTC_NUM_INTS 1 |
469 | 469 | ||
470 | static unsigned long hpet_rtc_flags; | 470 | static unsigned long hpet_rtc_flags; |
471 | static unsigned long hpet_prev_update_sec; | 471 | static int hpet_prev_update_sec; |
472 | static struct rtc_time hpet_alarm_time; | 472 | static struct rtc_time hpet_alarm_time; |
473 | static unsigned long hpet_pie_count; | 473 | static unsigned long hpet_pie_count; |
474 | static unsigned long hpet_t1_cmp; | 474 | static unsigned long hpet_t1_cmp; |
@@ -575,6 +575,9 @@ int hpet_set_rtc_irq_bit(unsigned long bit_mask) | |||
575 | 575 | ||
576 | hpet_rtc_flags |= bit_mask; | 576 | hpet_rtc_flags |= bit_mask; |
577 | 577 | ||
578 | if ((bit_mask & RTC_UIE) && !(oldbits & RTC_UIE)) | ||
579 | hpet_prev_update_sec = -1; | ||
580 | |||
578 | if (!oldbits) | 581 | if (!oldbits) |
579 | hpet_rtc_timer_init(); | 582 | hpet_rtc_timer_init(); |
580 | 583 | ||
@@ -652,7 +655,7 @@ static void hpet_rtc_timer_reinit(void) | |||
652 | if (hpet_rtc_flags & RTC_PIE) | 655 | if (hpet_rtc_flags & RTC_PIE) |
653 | hpet_pie_count += lost_ints; | 656 | hpet_pie_count += lost_ints; |
654 | if (printk_ratelimit()) | 657 | if (printk_ratelimit()) |
655 | printk(KERN_WARNING "rtc: lost %d interrupts\n", | 658 | printk(KERN_WARNING "hpet1: lost %d rtc interrupts\n", |
656 | lost_ints); | 659 | lost_ints); |
657 | } | 660 | } |
658 | } | 661 | } |
@@ -670,7 +673,8 @@ irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id) | |||
670 | 673 | ||
671 | if (hpet_rtc_flags & RTC_UIE && | 674 | if (hpet_rtc_flags & RTC_UIE && |
672 | curr_time.tm_sec != hpet_prev_update_sec) { | 675 | curr_time.tm_sec != hpet_prev_update_sec) { |
673 | rtc_int_flag = RTC_UF; | 676 | if (hpet_prev_update_sec >= 0) |
677 | rtc_int_flag = RTC_UF; | ||
674 | hpet_prev_update_sec = curr_time.tm_sec; | 678 | hpet_prev_update_sec = curr_time.tm_sec; |
675 | } | 679 | } |
676 | 680 | ||
diff --git a/arch/x86/kernel/irqinit_64.c b/arch/x86/kernel/irqinit_64.c index 0373e88de95a..1f26fd9ec4f4 100644 --- a/arch/x86/kernel/irqinit_64.c +++ b/arch/x86/kernel/irqinit_64.c | |||
@@ -43,10 +43,11 @@ | |||
43 | 43 | ||
44 | #define BUILD_IRQ(nr) \ | 44 | #define BUILD_IRQ(nr) \ |
45 | asmlinkage void IRQ_NAME(nr); \ | 45 | asmlinkage void IRQ_NAME(nr); \ |
46 | asm("\n.p2align\n" \ | 46 | asm("\n.text\n.p2align\n" \ |
47 | "IRQ" #nr "_interrupt:\n\t" \ | 47 | "IRQ" #nr "_interrupt:\n\t" \ |
48 | "push $~(" #nr ") ; " \ | 48 | "push $~(" #nr ") ; " \ |
49 | "jmp common_interrupt"); | 49 | "jmp common_interrupt\n" \ |
50 | ".previous"); | ||
50 | 51 | ||
51 | #define BI(x,y) \ | 52 | #define BI(x,y) \ |
52 | BUILD_IRQ(x##y) | 53 | BUILD_IRQ(x##y) |
diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c index 43c019f85f0d..6c27679ec6aa 100644 --- a/arch/x86/kernel/kprobes.c +++ b/arch/x86/kernel/kprobes.c | |||
@@ -431,7 +431,6 @@ static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs) | |||
431 | regs->ip = (unsigned long)p->ainsn.insn; | 431 | regs->ip = (unsigned long)p->ainsn.insn; |
432 | } | 432 | } |
433 | 433 | ||
434 | /* Called with kretprobe_lock held */ | ||
435 | void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, | 434 | void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, |
436 | struct pt_regs *regs) | 435 | struct pt_regs *regs) |
437 | { | 436 | { |
@@ -682,8 +681,7 @@ static __used __kprobes void *trampoline_handler(struct pt_regs *regs) | |||
682 | unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline; | 681 | unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline; |
683 | 682 | ||
684 | INIT_HLIST_HEAD(&empty_rp); | 683 | INIT_HLIST_HEAD(&empty_rp); |
685 | spin_lock_irqsave(&kretprobe_lock, flags); | 684 | kretprobe_hash_lock(current, &head, &flags); |
686 | head = kretprobe_inst_table_head(current); | ||
687 | /* fixup registers */ | 685 | /* fixup registers */ |
688 | #ifdef CONFIG_X86_64 | 686 | #ifdef CONFIG_X86_64 |
689 | regs->cs = __KERNEL_CS; | 687 | regs->cs = __KERNEL_CS; |
@@ -732,7 +730,7 @@ static __used __kprobes void *trampoline_handler(struct pt_regs *regs) | |||
732 | 730 | ||
733 | kretprobe_assert(ri, orig_ret_address, trampoline_address); | 731 | kretprobe_assert(ri, orig_ret_address, trampoline_address); |
734 | 732 | ||
735 | spin_unlock_irqrestore(&kretprobe_lock, flags); | 733 | kretprobe_hash_unlock(current, &flags); |
736 | 734 | ||
737 | hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) { | 735 | hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) { |
738 | hlist_del(&ri->hlist); | 736 | hlist_del(&ri->hlist); |
diff --git a/arch/x86/kernel/module_64.c b/arch/x86/kernel/module_64.c index 0e867676b5a5..6ba87830d4b1 100644 --- a/arch/x86/kernel/module_64.c +++ b/arch/x86/kernel/module_64.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/fs.h> | 22 | #include <linux/fs.h> |
23 | #include <linux/string.h> | 23 | #include <linux/string.h> |
24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
25 | #include <linux/mm.h> | ||
25 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
26 | #include <linux/bug.h> | 27 | #include <linux/bug.h> |
27 | 28 | ||
diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c index 151f2d171f7c..19e7fc7c2c4f 100644 --- a/arch/x86/kernel/pci-calgary_64.c +++ b/arch/x86/kernel/pci-calgary_64.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/mm.h> | 29 | #include <linux/mm.h> |
30 | #include <linux/spinlock.h> | 30 | #include <linux/spinlock.h> |
31 | #include <linux/string.h> | 31 | #include <linux/string.h> |
32 | #include <linux/crash_dump.h> | ||
32 | #include <linux/dma-mapping.h> | 33 | #include <linux/dma-mapping.h> |
33 | #include <linux/bitops.h> | 34 | #include <linux/bitops.h> |
34 | #include <linux/pci_ids.h> | 35 | #include <linux/pci_ids.h> |
@@ -167,6 +168,8 @@ static void calgary_dump_error_regs(struct iommu_table *tbl); | |||
167 | static void calioc2_handle_quirks(struct iommu_table *tbl, struct pci_dev *dev); | 168 | static void calioc2_handle_quirks(struct iommu_table *tbl, struct pci_dev *dev); |
168 | static void calioc2_tce_cache_blast(struct iommu_table *tbl); | 169 | static void calioc2_tce_cache_blast(struct iommu_table *tbl); |
169 | static void calioc2_dump_error_regs(struct iommu_table *tbl); | 170 | static void calioc2_dump_error_regs(struct iommu_table *tbl); |
171 | static void calgary_init_bitmap_from_tce_table(struct iommu_table *tbl); | ||
172 | static void get_tce_space_from_tar(void); | ||
170 | 173 | ||
171 | static struct cal_chipset_ops calgary_chip_ops = { | 174 | static struct cal_chipset_ops calgary_chip_ops = { |
172 | .handle_quirks = calgary_handle_quirks, | 175 | .handle_quirks = calgary_handle_quirks, |
@@ -830,7 +833,11 @@ static int __init calgary_setup_tar(struct pci_dev *dev, void __iomem *bbar) | |||
830 | 833 | ||
831 | tbl = pci_iommu(dev->bus); | 834 | tbl = pci_iommu(dev->bus); |
832 | tbl->it_base = (unsigned long)bus_info[dev->bus->number].tce_space; | 835 | tbl->it_base = (unsigned long)bus_info[dev->bus->number].tce_space; |
833 | tce_free(tbl, 0, tbl->it_size); | 836 | |
837 | if (is_kdump_kernel()) | ||
838 | calgary_init_bitmap_from_tce_table(tbl); | ||
839 | else | ||
840 | tce_free(tbl, 0, tbl->it_size); | ||
834 | 841 | ||
835 | if (is_calgary(dev->device)) | 842 | if (is_calgary(dev->device)) |
836 | tbl->chip_ops = &calgary_chip_ops; | 843 | tbl->chip_ops = &calgary_chip_ops; |
@@ -1209,6 +1216,10 @@ static int __init calgary_init(void) | |||
1209 | if (ret) | 1216 | if (ret) |
1210 | return ret; | 1217 | return ret; |
1211 | 1218 | ||
1219 | /* Purely for kdump kernel case */ | ||
1220 | if (is_kdump_kernel()) | ||
1221 | get_tce_space_from_tar(); | ||
1222 | |||
1212 | do { | 1223 | do { |
1213 | dev = pci_get_device(PCI_VENDOR_ID_IBM, PCI_ANY_ID, dev); | 1224 | dev = pci_get_device(PCI_VENDOR_ID_IBM, PCI_ANY_ID, dev); |
1214 | if (!dev) | 1225 | if (!dev) |
@@ -1339,6 +1350,61 @@ static int __init calgary_bus_has_devices(int bus, unsigned short pci_dev) | |||
1339 | return (val != 0xffffffff); | 1350 | return (val != 0xffffffff); |
1340 | } | 1351 | } |
1341 | 1352 | ||
1353 | /* | ||
1354 | * calgary_init_bitmap_from_tce_table(): | ||
1355 | * Funtion for kdump case. In the second/kdump kernel initialize | ||
1356 | * the bitmap based on the tce table entries obtained from first kernel | ||
1357 | */ | ||
1358 | static void calgary_init_bitmap_from_tce_table(struct iommu_table *tbl) | ||
1359 | { | ||
1360 | u64 *tp; | ||
1361 | unsigned int index; | ||
1362 | tp = ((u64 *)tbl->it_base); | ||
1363 | for (index = 0 ; index < tbl->it_size; index++) { | ||
1364 | if (*tp != 0x0) | ||
1365 | set_bit(index, tbl->it_map); | ||
1366 | tp++; | ||
1367 | } | ||
1368 | } | ||
1369 | |||
1370 | /* | ||
1371 | * get_tce_space_from_tar(): | ||
1372 | * Function for kdump case. Get the tce tables from first kernel | ||
1373 | * by reading the contents of the base adress register of calgary iommu | ||
1374 | */ | ||
1375 | static void get_tce_space_from_tar() | ||
1376 | { | ||
1377 | int bus; | ||
1378 | void __iomem *target; | ||
1379 | unsigned long tce_space; | ||
1380 | |||
1381 | for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) { | ||
1382 | struct calgary_bus_info *info = &bus_info[bus]; | ||
1383 | unsigned short pci_device; | ||
1384 | u32 val; | ||
1385 | |||
1386 | val = read_pci_config(bus, 0, 0, 0); | ||
1387 | pci_device = (val & 0xFFFF0000) >> 16; | ||
1388 | |||
1389 | if (!is_cal_pci_dev(pci_device)) | ||
1390 | continue; | ||
1391 | if (info->translation_disabled) | ||
1392 | continue; | ||
1393 | |||
1394 | if (calgary_bus_has_devices(bus, pci_device) || | ||
1395 | translate_empty_slots) { | ||
1396 | target = calgary_reg(bus_info[bus].bbar, | ||
1397 | tar_offset(bus)); | ||
1398 | tce_space = be64_to_cpu(readq(target)); | ||
1399 | tce_space = tce_space & TAR_SW_BITS; | ||
1400 | |||
1401 | tce_space = tce_space & (~specified_table_size); | ||
1402 | info->tce_space = (u64 *)__va(tce_space); | ||
1403 | } | ||
1404 | } | ||
1405 | return; | ||
1406 | } | ||
1407 | |||
1342 | void __init detect_calgary(void) | 1408 | void __init detect_calgary(void) |
1343 | { | 1409 | { |
1344 | int bus; | 1410 | int bus; |
@@ -1394,7 +1460,8 @@ void __init detect_calgary(void) | |||
1394 | return; | 1460 | return; |
1395 | } | 1461 | } |
1396 | 1462 | ||
1397 | specified_table_size = determine_tce_table_size(max_pfn * PAGE_SIZE); | 1463 | specified_table_size = determine_tce_table_size((is_kdump_kernel() ? |
1464 | saved_max_pfn : max_pfn) * PAGE_SIZE); | ||
1398 | 1465 | ||
1399 | for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) { | 1466 | for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) { |
1400 | struct calgary_bus_info *info = &bus_info[bus]; | 1467 | struct calgary_bus_info *info = &bus_info[bus]; |
@@ -1412,10 +1479,16 @@ void __init detect_calgary(void) | |||
1412 | 1479 | ||
1413 | if (calgary_bus_has_devices(bus, pci_device) || | 1480 | if (calgary_bus_has_devices(bus, pci_device) || |
1414 | translate_empty_slots) { | 1481 | translate_empty_slots) { |
1415 | tbl = alloc_tce_table(); | 1482 | /* |
1416 | if (!tbl) | 1483 | * If it is kdump kernel, find and use tce tables |
1417 | goto cleanup; | 1484 | * from first kernel, else allocate tce tables here |
1418 | info->tce_space = tbl; | 1485 | */ |
1486 | if (!is_kdump_kernel()) { | ||
1487 | tbl = alloc_tce_table(); | ||
1488 | if (!tbl) | ||
1489 | goto cleanup; | ||
1490 | info->tce_space = tbl; | ||
1491 | } | ||
1419 | calgary_found = 1; | 1492 | calgary_found = 1; |
1420 | } | 1493 | } |
1421 | } | 1494 | } |
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 0c3927accb00..53bc653ed5ca 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c | |||
@@ -128,7 +128,7 @@ void cpu_idle(void) | |||
128 | 128 | ||
129 | /* endless idle loop with no priority at all */ | 129 | /* endless idle loop with no priority at all */ |
130 | while (1) { | 130 | while (1) { |
131 | tick_nohz_stop_sched_tick(); | 131 | tick_nohz_stop_sched_tick(1); |
132 | while (!need_resched()) { | 132 | while (!need_resched()) { |
133 | 133 | ||
134 | check_pgt_cache(); | 134 | check_pgt_cache(); |
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index e8a8e1b99817..3fb62a7d9a16 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
@@ -120,7 +120,7 @@ void cpu_idle(void) | |||
120 | current_thread_info()->status |= TS_POLLING; | 120 | current_thread_info()->status |= TS_POLLING; |
121 | /* endless idle loop with no priority at all */ | 121 | /* endless idle loop with no priority at all */ |
122 | while (1) { | 122 | while (1) { |
123 | tick_nohz_stop_sched_tick(); | 123 | tick_nohz_stop_sched_tick(1); |
124 | while (!need_resched()) { | 124 | while (!need_resched()) { |
125 | 125 | ||
126 | rmb(); | 126 | rmb(); |
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index b4aacb9f52e3..b520dae02bf4 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -597,11 +597,11 @@ void __init setup_arch(char **cmdline_p) | |||
597 | memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data)); | 597 | memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data)); |
598 | visws_early_detect(); | 598 | visws_early_detect(); |
599 | pre_setup_arch_hook(); | 599 | pre_setup_arch_hook(); |
600 | early_cpu_init(); | ||
601 | #else | 600 | #else |
602 | printk(KERN_INFO "Command line: %s\n", boot_command_line); | 601 | printk(KERN_INFO "Command line: %s\n", boot_command_line); |
603 | #endif | 602 | #endif |
604 | 603 | ||
604 | early_cpu_init(); | ||
605 | early_ioremap_init(); | 605 | early_ioremap_init(); |
606 | 606 | ||
607 | ROOT_DEV = old_decode_dev(boot_params.hdr.root_dev); | 607 | ROOT_DEV = old_decode_dev(boot_params.hdr.root_dev); |
@@ -665,9 +665,6 @@ void __init setup_arch(char **cmdline_p) | |||
665 | bss_resource.start = virt_to_phys(&__bss_start); | 665 | bss_resource.start = virt_to_phys(&__bss_start); |
666 | bss_resource.end = virt_to_phys(&__bss_stop)-1; | 666 | bss_resource.end = virt_to_phys(&__bss_stop)-1; |
667 | 667 | ||
668 | #ifdef CONFIG_X86_64 | ||
669 | early_cpu_init(); | ||
670 | #endif | ||
671 | strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); | 668 | strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); |
672 | *cmdline_p = command_line; | 669 | *cmdline_p = command_line; |
673 | 670 | ||
diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 47c3d249e638..b45ef8ddd651 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c | |||
@@ -53,6 +53,59 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | |||
53 | return do_sigaltstack(uss, uoss, regs->sp); | 53 | return do_sigaltstack(uss, uoss, regs->sp); |
54 | } | 54 | } |
55 | 55 | ||
56 | /* | ||
57 | * Signal frame handlers. | ||
58 | */ | ||
59 | |||
60 | static inline int save_i387(struct _fpstate __user *buf) | ||
61 | { | ||
62 | struct task_struct *tsk = current; | ||
63 | int err = 0; | ||
64 | |||
65 | BUILD_BUG_ON(sizeof(struct user_i387_struct) != | ||
66 | sizeof(tsk->thread.xstate->fxsave)); | ||
67 | |||
68 | if ((unsigned long)buf % 16) | ||
69 | printk("save_i387: bad fpstate %p\n", buf); | ||
70 | |||
71 | if (!used_math()) | ||
72 | return 0; | ||
73 | clear_used_math(); /* trigger finit */ | ||
74 | if (task_thread_info(tsk)->status & TS_USEDFPU) { | ||
75 | err = save_i387_checking((struct i387_fxsave_struct __user *) | ||
76 | buf); | ||
77 | if (err) | ||
78 | return err; | ||
79 | task_thread_info(tsk)->status &= ~TS_USEDFPU; | ||
80 | stts(); | ||
81 | } else { | ||
82 | if (__copy_to_user(buf, &tsk->thread.xstate->fxsave, | ||
83 | sizeof(struct i387_fxsave_struct))) | ||
84 | return -1; | ||
85 | } | ||
86 | return 1; | ||
87 | } | ||
88 | |||
89 | /* | ||
90 | * This restores directly out of user space. Exceptions are handled. | ||
91 | */ | ||
92 | static inline int restore_i387(struct _fpstate __user *buf) | ||
93 | { | ||
94 | struct task_struct *tsk = current; | ||
95 | int err; | ||
96 | |||
97 | if (!used_math()) { | ||
98 | err = init_fpu(tsk); | ||
99 | if (err) | ||
100 | return err; | ||
101 | } | ||
102 | |||
103 | if (!(task_thread_info(current)->status & TS_USEDFPU)) { | ||
104 | clts(); | ||
105 | task_thread_info(current)->status |= TS_USEDFPU; | ||
106 | } | ||
107 | return restore_fpu_checking((__force struct i387_fxsave_struct *)buf); | ||
108 | } | ||
56 | 109 | ||
57 | /* | 110 | /* |
58 | * Do a signal return; undo the signal stack. | 111 | * Do a signal return; undo the signal stack. |
diff --git a/arch/x86/kernel/syscall_table_32.S b/arch/x86/kernel/syscall_table_32.S index adff5562f5fd..d44395ff34c3 100644 --- a/arch/x86/kernel/syscall_table_32.S +++ b/arch/x86/kernel/syscall_table_32.S | |||
@@ -326,3 +326,9 @@ ENTRY(sys_call_table) | |||
326 | .long sys_fallocate | 326 | .long sys_fallocate |
327 | .long sys_timerfd_settime /* 325 */ | 327 | .long sys_timerfd_settime /* 325 */ |
328 | .long sys_timerfd_gettime | 328 | .long sys_timerfd_gettime |
329 | .long sys_signalfd4 | ||
330 | .long sys_eventfd2 | ||
331 | .long sys_epoll_create1 | ||
332 | .long sys_dup3 /* 330 */ | ||
333 | .long sys_pipe2 | ||
334 | .long sys_inotify_init1 | ||