diff options
Diffstat (limited to 'arch/x86')
167 files changed, 4861 insertions, 2995 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 145d703227bf..83f521aa103f 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -90,7 +90,6 @@ config X86 | |||
90 | select GENERIC_IRQ_SHOW | 90 | select GENERIC_IRQ_SHOW |
91 | select GENERIC_CLOCKEVENTS_MIN_ADJUST | 91 | select GENERIC_CLOCKEVENTS_MIN_ADJUST |
92 | select IRQ_FORCED_THREADING | 92 | select IRQ_FORCED_THREADING |
93 | select USE_GENERIC_SMP_HELPERS if SMP | ||
94 | select HAVE_BPF_JIT if X86_64 | 93 | select HAVE_BPF_JIT if X86_64 |
95 | select HAVE_ARCH_TRANSPARENT_HUGEPAGE | 94 | select HAVE_ARCH_TRANSPARENT_HUGEPAGE |
96 | select CLKEVT_I8253 | 95 | select CLKEVT_I8253 |
@@ -123,6 +122,7 @@ config X86 | |||
123 | select COMPAT_OLD_SIGACTION if IA32_EMULATION | 122 | select COMPAT_OLD_SIGACTION if IA32_EMULATION |
124 | select RTC_LIB | 123 | select RTC_LIB |
125 | select HAVE_DEBUG_STACKOVERFLOW | 124 | select HAVE_DEBUG_STACKOVERFLOW |
125 | select HAVE_IRQ_EXIT_ON_IRQ_STACK if X86_64 | ||
126 | 126 | ||
127 | config INSTRUCTION_DECODER | 127 | config INSTRUCTION_DECODER |
128 | def_bool y | 128 | def_bool y |
@@ -254,10 +254,6 @@ config ARCH_HWEIGHT_CFLAGS | |||
254 | default "-fcall-saved-ecx -fcall-saved-edx" if X86_32 | 254 | default "-fcall-saved-ecx -fcall-saved-edx" if X86_32 |
255 | default "-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11" if X86_64 | 255 | default "-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11" if X86_64 |
256 | 256 | ||
257 | config ARCH_CPU_PROBE_RELEASE | ||
258 | def_bool y | ||
259 | depends on HOTPLUG_CPU | ||
260 | |||
261 | config ARCH_SUPPORTS_UPROBES | 257 | config ARCH_SUPPORTS_UPROBES |
262 | def_bool y | 258 | def_bool y |
263 | 259 | ||
@@ -638,10 +634,10 @@ config PARAVIRT_SPINLOCKS | |||
638 | spinlock implementation with something virtualization-friendly | 634 | spinlock implementation with something virtualization-friendly |
639 | (for example, block the virtual CPU rather than spinning). | 635 | (for example, block the virtual CPU rather than spinning). |
640 | 636 | ||
641 | Unfortunately the downside is an up to 5% performance hit on | 637 | It has a minimal impact on native kernels and gives a nice performance |
642 | native kernels, with various workloads. | 638 | benefit on paravirtualized KVM / Xen kernels. |
643 | 639 | ||
644 | If you are unsure how to answer this question, answer N. | 640 | If you are unsure how to answer this question, answer Y. |
645 | 641 | ||
646 | source "arch/x86/xen/Kconfig" | 642 | source "arch/x86/xen/Kconfig" |
647 | 643 | ||
@@ -756,20 +752,25 @@ config DMI | |||
756 | BIOS code. | 752 | BIOS code. |
757 | 753 | ||
758 | config GART_IOMMU | 754 | config GART_IOMMU |
759 | bool "GART IOMMU support" if EXPERT | 755 | bool "Old AMD GART IOMMU support" |
760 | default y | ||
761 | select SWIOTLB | 756 | select SWIOTLB |
762 | depends on X86_64 && PCI && AMD_NB | 757 | depends on X86_64 && PCI && AMD_NB |
763 | ---help--- | 758 | ---help--- |
764 | Support for full DMA access of devices with 32bit memory access only | 759 | Provides a driver for older AMD Athlon64/Opteron/Turion/Sempron |
765 | on systems with more than 3GB. This is usually needed for USB, | 760 | GART based hardware IOMMUs. |
766 | sound, many IDE/SATA chipsets and some other devices. | 761 | |
767 | Provides a driver for the AMD Athlon64/Opteron/Turion/Sempron GART | 762 | The GART supports full DMA access for devices with 32-bit access |
768 | based hardware IOMMU and a software bounce buffer based IOMMU used | 763 | limitations, on systems with more than 3 GB. This is usually needed |
769 | on Intel systems and as fallback. | 764 | for USB, sound, many IDE/SATA chipsets and some other devices. |
770 | The code is only active when needed (enough memory and limited | 765 | |
771 | device) unless CONFIG_IOMMU_DEBUG or iommu=force is specified | 766 | Newer systems typically have a modern AMD IOMMU, supported via |
772 | too. | 767 | the CONFIG_AMD_IOMMU=y config option. |
768 | |||
769 | In normal configurations this driver is only active when needed: | ||
770 | there's more than 3 GB of memory and the system contains a | ||
771 | 32-bit limited device. | ||
772 | |||
773 | If unsure, say Y. | ||
773 | 774 | ||
774 | config CALGARY_IOMMU | 775 | config CALGARY_IOMMU |
775 | bool "IBM Calgary IOMMU support" | 776 | bool "IBM Calgary IOMMU support" |
@@ -825,14 +826,16 @@ config MAXSMP | |||
825 | config NR_CPUS | 826 | config NR_CPUS |
826 | int "Maximum number of CPUs" if SMP && !MAXSMP | 827 | int "Maximum number of CPUs" if SMP && !MAXSMP |
827 | range 2 8 if SMP && X86_32 && !X86_BIGSMP | 828 | range 2 8 if SMP && X86_32 && !X86_BIGSMP |
828 | range 2 512 if SMP && !MAXSMP | 829 | range 2 512 if SMP && !MAXSMP && !CPUMASK_OFFSTACK |
830 | range 2 8192 if SMP && !MAXSMP && CPUMASK_OFFSTACK && X86_64 | ||
829 | default "1" if !SMP | 831 | default "1" if !SMP |
830 | default "4096" if MAXSMP | 832 | default "8192" if MAXSMP |
831 | default "32" if SMP && (X86_NUMAQ || X86_SUMMIT || X86_BIGSMP || X86_ES7000) | 833 | default "32" if SMP && (X86_NUMAQ || X86_SUMMIT || X86_BIGSMP || X86_ES7000) |
832 | default "8" if SMP | 834 | default "8" if SMP |
833 | ---help--- | 835 | ---help--- |
834 | This allows you to specify the maximum number of CPUs which this | 836 | This allows you to specify the maximum number of CPUs which this |
835 | kernel will support. The maximum supported value is 512 and the | 837 | kernel will support. If CPUMASK_OFFSTACK is enabled, the maximum |
838 | supported value is 4096, otherwise the maximum value is 512. The | ||
836 | minimum value which makes sense is 2. | 839 | minimum value which makes sense is 2. |
837 | 840 | ||
838 | This is purely to save memory - each supported CPU adds | 841 | This is purely to save memory - each supported CPU adds |
@@ -1033,6 +1036,7 @@ config X86_REBOOTFIXUPS | |||
1033 | 1036 | ||
1034 | config MICROCODE | 1037 | config MICROCODE |
1035 | tristate "CPU microcode loading support" | 1038 | tristate "CPU microcode loading support" |
1039 | depends on CPU_SUP_AMD || CPU_SUP_INTEL | ||
1036 | select FW_LOADER | 1040 | select FW_LOADER |
1037 | ---help--- | 1041 | ---help--- |
1038 | 1042 | ||
@@ -1593,7 +1597,7 @@ config EFI_STUB | |||
1593 | This kernel feature allows a bzImage to be loaded directly | 1597 | This kernel feature allows a bzImage to be loaded directly |
1594 | by EFI firmware without the use of a bootloader. | 1598 | by EFI firmware without the use of a bootloader. |
1595 | 1599 | ||
1596 | See Documentation/x86/efi-stub.txt for more information. | 1600 | See Documentation/efi-stub.txt for more information. |
1597 | 1601 | ||
1598 | config SECCOMP | 1602 | config SECCOMP |
1599 | def_bool y | 1603 | def_bool y |
@@ -1880,6 +1884,10 @@ config USE_PERCPU_NUMA_NODE_ID | |||
1880 | def_bool y | 1884 | def_bool y |
1881 | depends on NUMA | 1885 | depends on NUMA |
1882 | 1886 | ||
1887 | config ARCH_ENABLE_SPLIT_PMD_PTLOCK | ||
1888 | def_bool y | ||
1889 | depends on X86_64 || X86_PAE | ||
1890 | |||
1883 | menu "Power management and ACPI options" | 1891 | menu "Power management and ACPI options" |
1884 | 1892 | ||
1885 | config ARCH_HIBERNATION_HEADER | 1893 | config ARCH_HIBERNATION_HEADER |
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index 78d91afb8e50..0f3621ed1db6 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug | |||
@@ -59,6 +59,16 @@ config EARLY_PRINTK_DBGP | |||
59 | with klogd/syslogd or the X server. You should normally N here, | 59 | with klogd/syslogd or the X server. You should normally N here, |
60 | unless you want to debug such a crash. You need usb debug device. | 60 | unless you want to debug such a crash. You need usb debug device. |
61 | 61 | ||
62 | config EARLY_PRINTK_EFI | ||
63 | bool "Early printk via the EFI framebuffer" | ||
64 | depends on EFI && EARLY_PRINTK | ||
65 | select FONT_SUPPORT | ||
66 | ---help--- | ||
67 | Write kernel log output directly into the EFI framebuffer. | ||
68 | |||
69 | This is useful for kernel debugging when your machine crashes very | ||
70 | early before the console code is initialized. | ||
71 | |||
62 | config X86_PTDUMP | 72 | config X86_PTDUMP |
63 | bool "Export kernel pagetable layout to userspace via debugfs" | 73 | bool "Export kernel pagetable layout to userspace via debugfs" |
64 | depends on DEBUG_KERNEL | 74 | depends on DEBUG_KERNEL |
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile index 379814bc41e3..dce69a256896 100644 --- a/arch/x86/boot/Makefile +++ b/arch/x86/boot/Makefile | |||
@@ -71,7 +71,8 @@ GCOV_PROFILE := n | |||
71 | $(obj)/bzImage: asflags-y := $(SVGA_MODE) | 71 | $(obj)/bzImage: asflags-y := $(SVGA_MODE) |
72 | 72 | ||
73 | quiet_cmd_image = BUILD $@ | 73 | quiet_cmd_image = BUILD $@ |
74 | cmd_image = $(obj)/tools/build $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/zoffset.h > $@ | 74 | cmd_image = $(obj)/tools/build $(obj)/setup.bin $(obj)/vmlinux.bin \ |
75 | $(obj)/zoffset.h $@ | ||
75 | 76 | ||
76 | $(obj)/bzImage: $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/tools/build FORCE | 77 | $(obj)/bzImage: $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/tools/build FORCE |
77 | $(call if_changed,image) | 78 | $(call if_changed,image) |
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index b7388a425f09..a7677babf946 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c | |||
@@ -19,214 +19,10 @@ | |||
19 | 19 | ||
20 | static efi_system_table_t *sys_table; | 20 | static efi_system_table_t *sys_table; |
21 | 21 | ||
22 | static void efi_char16_printk(efi_char16_t *str) | ||
23 | { | ||
24 | struct efi_simple_text_output_protocol *out; | ||
25 | |||
26 | out = (struct efi_simple_text_output_protocol *)sys_table->con_out; | ||
27 | efi_call_phys2(out->output_string, out, str); | ||
28 | } | ||
29 | |||
30 | static void efi_printk(char *str) | ||
31 | { | ||
32 | char *s8; | ||
33 | |||
34 | for (s8 = str; *s8; s8++) { | ||
35 | efi_char16_t ch[2] = { 0 }; | ||
36 | |||
37 | ch[0] = *s8; | ||
38 | if (*s8 == '\n') { | ||
39 | efi_char16_t nl[2] = { '\r', 0 }; | ||
40 | efi_char16_printk(nl); | ||
41 | } | ||
42 | |||
43 | efi_char16_printk(ch); | ||
44 | } | ||
45 | } | ||
46 | |||
47 | static efi_status_t __get_map(efi_memory_desc_t **map, unsigned long *map_size, | ||
48 | unsigned long *desc_size) | ||
49 | { | ||
50 | efi_memory_desc_t *m = NULL; | ||
51 | efi_status_t status; | ||
52 | unsigned long key; | ||
53 | u32 desc_version; | ||
54 | |||
55 | *map_size = sizeof(*m) * 32; | ||
56 | again: | ||
57 | /* | ||
58 | * Add an additional efi_memory_desc_t because we're doing an | ||
59 | * allocation which may be in a new descriptor region. | ||
60 | */ | ||
61 | *map_size += sizeof(*m); | ||
62 | status = efi_call_phys3(sys_table->boottime->allocate_pool, | ||
63 | EFI_LOADER_DATA, *map_size, (void **)&m); | ||
64 | if (status != EFI_SUCCESS) | ||
65 | goto fail; | ||
66 | |||
67 | status = efi_call_phys5(sys_table->boottime->get_memory_map, map_size, | ||
68 | m, &key, desc_size, &desc_version); | ||
69 | if (status == EFI_BUFFER_TOO_SMALL) { | ||
70 | efi_call_phys1(sys_table->boottime->free_pool, m); | ||
71 | goto again; | ||
72 | } | ||
73 | |||
74 | if (status != EFI_SUCCESS) | ||
75 | efi_call_phys1(sys_table->boottime->free_pool, m); | ||
76 | 22 | ||
77 | fail: | 23 | #include "../../../../drivers/firmware/efi/efi-stub-helper.c" |
78 | *map = m; | ||
79 | return status; | ||
80 | } | ||
81 | |||
82 | /* | ||
83 | * Allocate at the highest possible address that is not above 'max'. | ||
84 | */ | ||
85 | static efi_status_t high_alloc(unsigned long size, unsigned long align, | ||
86 | unsigned long *addr, unsigned long max) | ||
87 | { | ||
88 | unsigned long map_size, desc_size; | ||
89 | efi_memory_desc_t *map; | ||
90 | efi_status_t status; | ||
91 | unsigned long nr_pages; | ||
92 | u64 max_addr = 0; | ||
93 | int i; | ||
94 | |||
95 | status = __get_map(&map, &map_size, &desc_size); | ||
96 | if (status != EFI_SUCCESS) | ||
97 | goto fail; | ||
98 | |||
99 | nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; | ||
100 | again: | ||
101 | for (i = 0; i < map_size / desc_size; i++) { | ||
102 | efi_memory_desc_t *desc; | ||
103 | unsigned long m = (unsigned long)map; | ||
104 | u64 start, end; | ||
105 | |||
106 | desc = (efi_memory_desc_t *)(m + (i * desc_size)); | ||
107 | if (desc->type != EFI_CONVENTIONAL_MEMORY) | ||
108 | continue; | ||
109 | |||
110 | if (desc->num_pages < nr_pages) | ||
111 | continue; | ||
112 | 24 | ||
113 | start = desc->phys_addr; | ||
114 | end = start + desc->num_pages * (1UL << EFI_PAGE_SHIFT); | ||
115 | 25 | ||
116 | if ((start + size) > end || (start + size) > max) | ||
117 | continue; | ||
118 | |||
119 | if (end - size > max) | ||
120 | end = max; | ||
121 | |||
122 | if (round_down(end - size, align) < start) | ||
123 | continue; | ||
124 | |||
125 | start = round_down(end - size, align); | ||
126 | |||
127 | /* | ||
128 | * Don't allocate at 0x0. It will confuse code that | ||
129 | * checks pointers against NULL. | ||
130 | */ | ||
131 | if (start == 0x0) | ||
132 | continue; | ||
133 | |||
134 | if (start > max_addr) | ||
135 | max_addr = start; | ||
136 | } | ||
137 | |||
138 | if (!max_addr) | ||
139 | status = EFI_NOT_FOUND; | ||
140 | else { | ||
141 | status = efi_call_phys4(sys_table->boottime->allocate_pages, | ||
142 | EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA, | ||
143 | nr_pages, &max_addr); | ||
144 | if (status != EFI_SUCCESS) { | ||
145 | max = max_addr; | ||
146 | max_addr = 0; | ||
147 | goto again; | ||
148 | } | ||
149 | |||
150 | *addr = max_addr; | ||
151 | } | ||
152 | |||
153 | free_pool: | ||
154 | efi_call_phys1(sys_table->boottime->free_pool, map); | ||
155 | |||
156 | fail: | ||
157 | return status; | ||
158 | } | ||
159 | |||
160 | /* | ||
161 | * Allocate at the lowest possible address. | ||
162 | */ | ||
163 | static efi_status_t low_alloc(unsigned long size, unsigned long align, | ||
164 | unsigned long *addr) | ||
165 | { | ||
166 | unsigned long map_size, desc_size; | ||
167 | efi_memory_desc_t *map; | ||
168 | efi_status_t status; | ||
169 | unsigned long nr_pages; | ||
170 | int i; | ||
171 | |||
172 | status = __get_map(&map, &map_size, &desc_size); | ||
173 | if (status != EFI_SUCCESS) | ||
174 | goto fail; | ||
175 | |||
176 | nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; | ||
177 | for (i = 0; i < map_size / desc_size; i++) { | ||
178 | efi_memory_desc_t *desc; | ||
179 | unsigned long m = (unsigned long)map; | ||
180 | u64 start, end; | ||
181 | |||
182 | desc = (efi_memory_desc_t *)(m + (i * desc_size)); | ||
183 | |||
184 | if (desc->type != EFI_CONVENTIONAL_MEMORY) | ||
185 | continue; | ||
186 | |||
187 | if (desc->num_pages < nr_pages) | ||
188 | continue; | ||
189 | |||
190 | start = desc->phys_addr; | ||
191 | end = start + desc->num_pages * (1UL << EFI_PAGE_SHIFT); | ||
192 | |||
193 | /* | ||
194 | * Don't allocate at 0x0. It will confuse code that | ||
195 | * checks pointers against NULL. Skip the first 8 | ||
196 | * bytes so we start at a nice even number. | ||
197 | */ | ||
198 | if (start == 0x0) | ||
199 | start += 8; | ||
200 | |||
201 | start = round_up(start, align); | ||
202 | if ((start + size) > end) | ||
203 | continue; | ||
204 | |||
205 | status = efi_call_phys4(sys_table->boottime->allocate_pages, | ||
206 | EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA, | ||
207 | nr_pages, &start); | ||
208 | if (status == EFI_SUCCESS) { | ||
209 | *addr = start; | ||
210 | break; | ||
211 | } | ||
212 | } | ||
213 | |||
214 | if (i == map_size / desc_size) | ||
215 | status = EFI_NOT_FOUND; | ||
216 | |||
217 | free_pool: | ||
218 | efi_call_phys1(sys_table->boottime->free_pool, map); | ||
219 | fail: | ||
220 | return status; | ||
221 | } | ||
222 | |||
223 | static void low_free(unsigned long size, unsigned long addr) | ||
224 | { | ||
225 | unsigned long nr_pages; | ||
226 | |||
227 | nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; | ||
228 | efi_call_phys2(sys_table->boottime->free_pages, addr, nr_pages); | ||
229 | } | ||
230 | 26 | ||
231 | static void find_bits(unsigned long mask, u8 *pos, u8 *size) | 27 | static void find_bits(unsigned long mask, u8 *pos, u8 *size) |
232 | { | 28 | { |
@@ -624,242 +420,6 @@ void setup_graphics(struct boot_params *boot_params) | |||
624 | } | 420 | } |
625 | } | 421 | } |
626 | 422 | ||
627 | struct initrd { | ||
628 | efi_file_handle_t *handle; | ||
629 | u64 size; | ||
630 | }; | ||
631 | |||
632 | /* | ||
633 | * Check the cmdline for a LILO-style initrd= arguments. | ||
634 | * | ||
635 | * We only support loading an initrd from the same filesystem as the | ||
636 | * kernel image. | ||
637 | */ | ||
638 | static efi_status_t handle_ramdisks(efi_loaded_image_t *image, | ||
639 | struct setup_header *hdr) | ||
640 | { | ||
641 | struct initrd *initrds; | ||
642 | unsigned long initrd_addr; | ||
643 | efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID; | ||
644 | u64 initrd_total; | ||
645 | efi_file_io_interface_t *io; | ||
646 | efi_file_handle_t *fh; | ||
647 | efi_status_t status; | ||
648 | int nr_initrds; | ||
649 | char *str; | ||
650 | int i, j, k; | ||
651 | |||
652 | initrd_addr = 0; | ||
653 | initrd_total = 0; | ||
654 | |||
655 | str = (char *)(unsigned long)hdr->cmd_line_ptr; | ||
656 | |||
657 | j = 0; /* See close_handles */ | ||
658 | |||
659 | if (!str || !*str) | ||
660 | return EFI_SUCCESS; | ||
661 | |||
662 | for (nr_initrds = 0; *str; nr_initrds++) { | ||
663 | str = strstr(str, "initrd="); | ||
664 | if (!str) | ||
665 | break; | ||
666 | |||
667 | str += 7; | ||
668 | |||
669 | /* Skip any leading slashes */ | ||
670 | while (*str == '/' || *str == '\\') | ||
671 | str++; | ||
672 | |||
673 | while (*str && *str != ' ' && *str != '\n') | ||
674 | str++; | ||
675 | } | ||
676 | |||
677 | if (!nr_initrds) | ||
678 | return EFI_SUCCESS; | ||
679 | |||
680 | status = efi_call_phys3(sys_table->boottime->allocate_pool, | ||
681 | EFI_LOADER_DATA, | ||
682 | nr_initrds * sizeof(*initrds), | ||
683 | &initrds); | ||
684 | if (status != EFI_SUCCESS) { | ||
685 | efi_printk("Failed to alloc mem for initrds\n"); | ||
686 | goto fail; | ||
687 | } | ||
688 | |||
689 | str = (char *)(unsigned long)hdr->cmd_line_ptr; | ||
690 | for (i = 0; i < nr_initrds; i++) { | ||
691 | struct initrd *initrd; | ||
692 | efi_file_handle_t *h; | ||
693 | efi_file_info_t *info; | ||
694 | efi_char16_t filename_16[256]; | ||
695 | unsigned long info_sz; | ||
696 | efi_guid_t info_guid = EFI_FILE_INFO_ID; | ||
697 | efi_char16_t *p; | ||
698 | u64 file_sz; | ||
699 | |||
700 | str = strstr(str, "initrd="); | ||
701 | if (!str) | ||
702 | break; | ||
703 | |||
704 | str += 7; | ||
705 | |||
706 | initrd = &initrds[i]; | ||
707 | p = filename_16; | ||
708 | |||
709 | /* Skip any leading slashes */ | ||
710 | while (*str == '/' || *str == '\\') | ||
711 | str++; | ||
712 | |||
713 | while (*str && *str != ' ' && *str != '\n') { | ||
714 | if ((u8 *)p >= (u8 *)filename_16 + sizeof(filename_16)) | ||
715 | break; | ||
716 | |||
717 | if (*str == '/') { | ||
718 | *p++ = '\\'; | ||
719 | *str++; | ||
720 | } else { | ||
721 | *p++ = *str++; | ||
722 | } | ||
723 | } | ||
724 | |||
725 | *p = '\0'; | ||
726 | |||
727 | /* Only open the volume once. */ | ||
728 | if (!i) { | ||
729 | efi_boot_services_t *boottime; | ||
730 | |||
731 | boottime = sys_table->boottime; | ||
732 | |||
733 | status = efi_call_phys3(boottime->handle_protocol, | ||
734 | image->device_handle, &fs_proto, &io); | ||
735 | if (status != EFI_SUCCESS) { | ||
736 | efi_printk("Failed to handle fs_proto\n"); | ||
737 | goto free_initrds; | ||
738 | } | ||
739 | |||
740 | status = efi_call_phys2(io->open_volume, io, &fh); | ||
741 | if (status != EFI_SUCCESS) { | ||
742 | efi_printk("Failed to open volume\n"); | ||
743 | goto free_initrds; | ||
744 | } | ||
745 | } | ||
746 | |||
747 | status = efi_call_phys5(fh->open, fh, &h, filename_16, | ||
748 | EFI_FILE_MODE_READ, (u64)0); | ||
749 | if (status != EFI_SUCCESS) { | ||
750 | efi_printk("Failed to open initrd file: "); | ||
751 | efi_char16_printk(filename_16); | ||
752 | efi_printk("\n"); | ||
753 | goto close_handles; | ||
754 | } | ||
755 | |||
756 | initrd->handle = h; | ||
757 | |||
758 | info_sz = 0; | ||
759 | status = efi_call_phys4(h->get_info, h, &info_guid, | ||
760 | &info_sz, NULL); | ||
761 | if (status != EFI_BUFFER_TOO_SMALL) { | ||
762 | efi_printk("Failed to get initrd info size\n"); | ||
763 | goto close_handles; | ||
764 | } | ||
765 | |||
766 | grow: | ||
767 | status = efi_call_phys3(sys_table->boottime->allocate_pool, | ||
768 | EFI_LOADER_DATA, info_sz, &info); | ||
769 | if (status != EFI_SUCCESS) { | ||
770 | efi_printk("Failed to alloc mem for initrd info\n"); | ||
771 | goto close_handles; | ||
772 | } | ||
773 | |||
774 | status = efi_call_phys4(h->get_info, h, &info_guid, | ||
775 | &info_sz, info); | ||
776 | if (status == EFI_BUFFER_TOO_SMALL) { | ||
777 | efi_call_phys1(sys_table->boottime->free_pool, info); | ||
778 | goto grow; | ||
779 | } | ||
780 | |||
781 | file_sz = info->file_size; | ||
782 | efi_call_phys1(sys_table->boottime->free_pool, info); | ||
783 | |||
784 | if (status != EFI_SUCCESS) { | ||
785 | efi_printk("Failed to get initrd info\n"); | ||
786 | goto close_handles; | ||
787 | } | ||
788 | |||
789 | initrd->size = file_sz; | ||
790 | initrd_total += file_sz; | ||
791 | } | ||
792 | |||
793 | if (initrd_total) { | ||
794 | unsigned long addr; | ||
795 | |||
796 | /* | ||
797 | * Multiple initrd's need to be at consecutive | ||
798 | * addresses in memory, so allocate enough memory for | ||
799 | * all the initrd's. | ||
800 | */ | ||
801 | status = high_alloc(initrd_total, 0x1000, | ||
802 | &initrd_addr, hdr->initrd_addr_max); | ||
803 | if (status != EFI_SUCCESS) { | ||
804 | efi_printk("Failed to alloc highmem for initrds\n"); | ||
805 | goto close_handles; | ||
806 | } | ||
807 | |||
808 | /* We've run out of free low memory. */ | ||
809 | if (initrd_addr > hdr->initrd_addr_max) { | ||
810 | efi_printk("We've run out of free low memory\n"); | ||
811 | status = EFI_INVALID_PARAMETER; | ||
812 | goto free_initrd_total; | ||
813 | } | ||
814 | |||
815 | addr = initrd_addr; | ||
816 | for (j = 0; j < nr_initrds; j++) { | ||
817 | u64 size; | ||
818 | |||
819 | size = initrds[j].size; | ||
820 | while (size) { | ||
821 | u64 chunksize; | ||
822 | if (size > EFI_READ_CHUNK_SIZE) | ||
823 | chunksize = EFI_READ_CHUNK_SIZE; | ||
824 | else | ||
825 | chunksize = size; | ||
826 | status = efi_call_phys3(fh->read, | ||
827 | initrds[j].handle, | ||
828 | &chunksize, addr); | ||
829 | if (status != EFI_SUCCESS) { | ||
830 | efi_printk("Failed to read initrd\n"); | ||
831 | goto free_initrd_total; | ||
832 | } | ||
833 | addr += chunksize; | ||
834 | size -= chunksize; | ||
835 | } | ||
836 | |||
837 | efi_call_phys1(fh->close, initrds[j].handle); | ||
838 | } | ||
839 | |||
840 | } | ||
841 | |||
842 | efi_call_phys1(sys_table->boottime->free_pool, initrds); | ||
843 | |||
844 | hdr->ramdisk_image = initrd_addr; | ||
845 | hdr->ramdisk_size = initrd_total; | ||
846 | |||
847 | return status; | ||
848 | |||
849 | free_initrd_total: | ||
850 | low_free(initrd_total, initrd_addr); | ||
851 | |||
852 | close_handles: | ||
853 | for (k = j; k < i; k++) | ||
854 | efi_call_phys1(fh->close, initrds[k].handle); | ||
855 | free_initrds: | ||
856 | efi_call_phys1(sys_table->boottime->free_pool, initrds); | ||
857 | fail: | ||
858 | hdr->ramdisk_image = 0; | ||
859 | hdr->ramdisk_size = 0; | ||
860 | |||
861 | return status; | ||
862 | } | ||
863 | 423 | ||
864 | /* | 424 | /* |
865 | * Because the x86 boot code expects to be passed a boot_params we | 425 | * Because the x86 boot code expects to be passed a boot_params we |
@@ -875,14 +435,15 @@ struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table) | |||
875 | struct efi_info *efi; | 435 | struct efi_info *efi; |
876 | efi_loaded_image_t *image; | 436 | efi_loaded_image_t *image; |
877 | void *options; | 437 | void *options; |
878 | u32 load_options_size; | ||
879 | efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID; | 438 | efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID; |
880 | int options_size = 0; | 439 | int options_size = 0; |
881 | efi_status_t status; | 440 | efi_status_t status; |
882 | unsigned long cmdline; | 441 | char *cmdline_ptr; |
883 | u16 *s2; | 442 | u16 *s2; |
884 | u8 *s1; | 443 | u8 *s1; |
885 | int i; | 444 | int i; |
445 | unsigned long ramdisk_addr; | ||
446 | unsigned long ramdisk_size; | ||
886 | 447 | ||
887 | sys_table = _table; | 448 | sys_table = _table; |
888 | 449 | ||
@@ -893,13 +454,14 @@ struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table) | |||
893 | status = efi_call_phys3(sys_table->boottime->handle_protocol, | 454 | status = efi_call_phys3(sys_table->boottime->handle_protocol, |
894 | handle, &proto, (void *)&image); | 455 | handle, &proto, (void *)&image); |
895 | if (status != EFI_SUCCESS) { | 456 | if (status != EFI_SUCCESS) { |
896 | efi_printk("Failed to get handle for LOADED_IMAGE_PROTOCOL\n"); | 457 | efi_printk(sys_table, "Failed to get handle for LOADED_IMAGE_PROTOCOL\n"); |
897 | return NULL; | 458 | return NULL; |
898 | } | 459 | } |
899 | 460 | ||
900 | status = low_alloc(0x4000, 1, (unsigned long *)&boot_params); | 461 | status = efi_low_alloc(sys_table, 0x4000, 1, |
462 | (unsigned long *)&boot_params); | ||
901 | if (status != EFI_SUCCESS) { | 463 | if (status != EFI_SUCCESS) { |
902 | efi_printk("Failed to alloc lowmem for boot params\n"); | 464 | efi_printk(sys_table, "Failed to alloc lowmem for boot params\n"); |
903 | return NULL; | 465 | return NULL; |
904 | } | 466 | } |
905 | 467 | ||
@@ -926,40 +488,11 @@ struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table) | |||
926 | hdr->type_of_loader = 0x21; | 488 | hdr->type_of_loader = 0x21; |
927 | 489 | ||
928 | /* Convert unicode cmdline to ascii */ | 490 | /* Convert unicode cmdline to ascii */ |
929 | options = image->load_options; | 491 | cmdline_ptr = efi_convert_cmdline_to_ascii(sys_table, image, |
930 | load_options_size = image->load_options_size / 2; /* ASCII */ | 492 | &options_size); |
931 | cmdline = 0; | 493 | if (!cmdline_ptr) |
932 | s2 = (u16 *)options; | 494 | goto fail; |
933 | 495 | hdr->cmd_line_ptr = (unsigned long)cmdline_ptr; | |
934 | if (s2) { | ||
935 | while (*s2 && *s2 != '\n' && options_size < load_options_size) { | ||
936 | s2++; | ||
937 | options_size++; | ||
938 | } | ||
939 | |||
940 | if (options_size) { | ||
941 | if (options_size > hdr->cmdline_size) | ||
942 | options_size = hdr->cmdline_size; | ||
943 | |||
944 | options_size++; /* NUL termination */ | ||
945 | |||
946 | status = low_alloc(options_size, 1, &cmdline); | ||
947 | if (status != EFI_SUCCESS) { | ||
948 | efi_printk("Failed to alloc mem for cmdline\n"); | ||
949 | goto fail; | ||
950 | } | ||
951 | |||
952 | s1 = (u8 *)(unsigned long)cmdline; | ||
953 | s2 = (u16 *)options; | ||
954 | |||
955 | for (i = 0; i < options_size - 1; i++) | ||
956 | *s1++ = *s2++; | ||
957 | |||
958 | *s1 = '\0'; | ||
959 | } | ||
960 | } | ||
961 | |||
962 | hdr->cmd_line_ptr = cmdline; | ||
963 | 496 | ||
964 | hdr->ramdisk_image = 0; | 497 | hdr->ramdisk_image = 0; |
965 | hdr->ramdisk_size = 0; | 498 | hdr->ramdisk_size = 0; |
@@ -969,96 +502,64 @@ struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table) | |||
969 | 502 | ||
970 | memset(sdt, 0, sizeof(*sdt)); | 503 | memset(sdt, 0, sizeof(*sdt)); |
971 | 504 | ||
972 | status = handle_ramdisks(image, hdr); | 505 | status = handle_cmdline_files(sys_table, image, |
506 | (char *)(unsigned long)hdr->cmd_line_ptr, | ||
507 | "initrd=", hdr->initrd_addr_max, | ||
508 | &ramdisk_addr, &ramdisk_size); | ||
973 | if (status != EFI_SUCCESS) | 509 | if (status != EFI_SUCCESS) |
974 | goto fail2; | 510 | goto fail2; |
511 | hdr->ramdisk_image = ramdisk_addr; | ||
512 | hdr->ramdisk_size = ramdisk_size; | ||
975 | 513 | ||
976 | return boot_params; | 514 | return boot_params; |
977 | fail2: | 515 | fail2: |
978 | if (options_size) | 516 | efi_free(sys_table, options_size, hdr->cmd_line_ptr); |
979 | low_free(options_size, hdr->cmd_line_ptr); | ||
980 | fail: | 517 | fail: |
981 | low_free(0x4000, (unsigned long)boot_params); | 518 | efi_free(sys_table, 0x4000, (unsigned long)boot_params); |
982 | return NULL; | 519 | return NULL; |
983 | } | 520 | } |
984 | 521 | ||
985 | static efi_status_t exit_boot(struct boot_params *boot_params, | 522 | static void add_e820ext(struct boot_params *params, |
986 | void *handle) | 523 | struct setup_data *e820ext, u32 nr_entries) |
987 | { | 524 | { |
988 | struct efi_info *efi = &boot_params->efi_info; | 525 | struct setup_data *data; |
989 | struct e820entry *e820_map = &boot_params->e820_map[0]; | ||
990 | struct e820entry *prev = NULL; | ||
991 | unsigned long size, key, desc_size, _size; | ||
992 | efi_memory_desc_t *mem_map; | ||
993 | efi_status_t status; | 526 | efi_status_t status; |
994 | __u32 desc_version; | 527 | unsigned long size; |
995 | bool called_exit = false; | ||
996 | u8 nr_entries; | ||
997 | int i; | ||
998 | |||
999 | size = sizeof(*mem_map) * 32; | ||
1000 | |||
1001 | again: | ||
1002 | size += sizeof(*mem_map) * 2; | ||
1003 | _size = size; | ||
1004 | status = low_alloc(size, 1, (unsigned long *)&mem_map); | ||
1005 | if (status != EFI_SUCCESS) | ||
1006 | return status; | ||
1007 | |||
1008 | get_map: | ||
1009 | status = efi_call_phys5(sys_table->boottime->get_memory_map, &size, | ||
1010 | mem_map, &key, &desc_size, &desc_version); | ||
1011 | if (status == EFI_BUFFER_TOO_SMALL) { | ||
1012 | low_free(_size, (unsigned long)mem_map); | ||
1013 | goto again; | ||
1014 | } | ||
1015 | 528 | ||
1016 | if (status != EFI_SUCCESS) | 529 | e820ext->type = SETUP_E820_EXT; |
1017 | goto free_mem_map; | 530 | e820ext->len = nr_entries * sizeof(struct e820entry); |
531 | e820ext->next = 0; | ||
1018 | 532 | ||
1019 | memcpy(&efi->efi_loader_signature, EFI_LOADER_SIGNATURE, sizeof(__u32)); | 533 | data = (struct setup_data *)(unsigned long)params->hdr.setup_data; |
1020 | efi->efi_systab = (unsigned long)sys_table; | ||
1021 | efi->efi_memdesc_size = desc_size; | ||
1022 | efi->efi_memdesc_version = desc_version; | ||
1023 | efi->efi_memmap = (unsigned long)mem_map; | ||
1024 | efi->efi_memmap_size = size; | ||
1025 | |||
1026 | #ifdef CONFIG_X86_64 | ||
1027 | efi->efi_systab_hi = (unsigned long)sys_table >> 32; | ||
1028 | efi->efi_memmap_hi = (unsigned long)mem_map >> 32; | ||
1029 | #endif | ||
1030 | 534 | ||
1031 | /* Might as well exit boot services now */ | 535 | while (data && data->next) |
1032 | status = efi_call_phys2(sys_table->boottime->exit_boot_services, | 536 | data = (struct setup_data *)(unsigned long)data->next; |
1033 | handle, key); | ||
1034 | if (status != EFI_SUCCESS) { | ||
1035 | /* | ||
1036 | * ExitBootServices() will fail if any of the event | ||
1037 | * handlers change the memory map. In which case, we | ||
1038 | * must be prepared to retry, but only once so that | ||
1039 | * we're guaranteed to exit on repeated failures instead | ||
1040 | * of spinning forever. | ||
1041 | */ | ||
1042 | if (called_exit) | ||
1043 | goto free_mem_map; | ||
1044 | 537 | ||
1045 | called_exit = true; | 538 | if (data) |
1046 | goto get_map; | 539 | data->next = (unsigned long)e820ext; |
1047 | } | 540 | else |
541 | params->hdr.setup_data = (unsigned long)e820ext; | ||
542 | } | ||
1048 | 543 | ||
1049 | /* Historic? */ | 544 | static efi_status_t setup_e820(struct boot_params *params, |
1050 | boot_params->alt_mem_k = 32 * 1024; | 545 | struct setup_data *e820ext, u32 e820ext_size) |
546 | { | ||
547 | struct e820entry *e820_map = ¶ms->e820_map[0]; | ||
548 | struct efi_info *efi = ¶ms->efi_info; | ||
549 | struct e820entry *prev = NULL; | ||
550 | u32 nr_entries; | ||
551 | u32 nr_desc; | ||
552 | int i; | ||
1051 | 553 | ||
1052 | /* | ||
1053 | * Convert the EFI memory map to E820. | ||
1054 | */ | ||
1055 | nr_entries = 0; | 554 | nr_entries = 0; |
1056 | for (i = 0; i < size / desc_size; i++) { | 555 | nr_desc = efi->efi_memmap_size / efi->efi_memdesc_size; |
556 | |||
557 | for (i = 0; i < nr_desc; i++) { | ||
1057 | efi_memory_desc_t *d; | 558 | efi_memory_desc_t *d; |
1058 | unsigned int e820_type = 0; | 559 | unsigned int e820_type = 0; |
1059 | unsigned long m = (unsigned long)mem_map; | 560 | unsigned long m = efi->efi_memmap; |
1060 | 561 | ||
1061 | d = (efi_memory_desc_t *)(m + (i * desc_size)); | 562 | d = (efi_memory_desc_t *)(m + (i * efi->efi_memdesc_size)); |
1062 | switch (d->type) { | 563 | switch (d->type) { |
1063 | case EFI_RESERVED_TYPE: | 564 | case EFI_RESERVED_TYPE: |
1064 | case EFI_RUNTIME_SERVICES_CODE: | 565 | case EFI_RUNTIME_SERVICES_CODE: |
@@ -1095,61 +596,151 @@ get_map: | |||
1095 | 596 | ||
1096 | /* Merge adjacent mappings */ | 597 | /* Merge adjacent mappings */ |
1097 | if (prev && prev->type == e820_type && | 598 | if (prev && prev->type == e820_type && |
1098 | (prev->addr + prev->size) == d->phys_addr) | 599 | (prev->addr + prev->size) == d->phys_addr) { |
1099 | prev->size += d->num_pages << 12; | 600 | prev->size += d->num_pages << 12; |
1100 | else { | 601 | continue; |
1101 | e820_map->addr = d->phys_addr; | 602 | } |
1102 | e820_map->size = d->num_pages << 12; | 603 | |
1103 | e820_map->type = e820_type; | 604 | if (nr_entries == ARRAY_SIZE(params->e820_map)) { |
1104 | prev = e820_map++; | 605 | u32 need = (nr_desc - i) * sizeof(struct e820entry) + |
1105 | nr_entries++; | 606 | sizeof(struct setup_data); |
607 | |||
608 | if (!e820ext || e820ext_size < need) | ||
609 | return EFI_BUFFER_TOO_SMALL; | ||
610 | |||
611 | /* boot_params map full, switch to e820 extended */ | ||
612 | e820_map = (struct e820entry *)e820ext->data; | ||
1106 | } | 613 | } |
614 | |||
615 | e820_map->addr = d->phys_addr; | ||
616 | e820_map->size = d->num_pages << PAGE_SHIFT; | ||
617 | e820_map->type = e820_type; | ||
618 | prev = e820_map++; | ||
619 | nr_entries++; | ||
1107 | } | 620 | } |
1108 | 621 | ||
1109 | boot_params->e820_entries = nr_entries; | 622 | if (nr_entries > ARRAY_SIZE(params->e820_map)) { |
623 | u32 nr_e820ext = nr_entries - ARRAY_SIZE(params->e820_map); | ||
624 | |||
625 | add_e820ext(params, e820ext, nr_e820ext); | ||
626 | nr_entries -= nr_e820ext; | ||
627 | } | ||
628 | |||
629 | params->e820_entries = (u8)nr_entries; | ||
1110 | 630 | ||
1111 | return EFI_SUCCESS; | 631 | return EFI_SUCCESS; |
632 | } | ||
633 | |||
634 | static efi_status_t alloc_e820ext(u32 nr_desc, struct setup_data **e820ext, | ||
635 | u32 *e820ext_size) | ||
636 | { | ||
637 | efi_status_t status; | ||
638 | unsigned long size; | ||
639 | |||
640 | size = sizeof(struct setup_data) + | ||
641 | sizeof(struct e820entry) * nr_desc; | ||
642 | |||
643 | if (*e820ext) { | ||
644 | efi_call_phys1(sys_table->boottime->free_pool, *e820ext); | ||
645 | *e820ext = NULL; | ||
646 | *e820ext_size = 0; | ||
647 | } | ||
648 | |||
649 | status = efi_call_phys3(sys_table->boottime->allocate_pool, | ||
650 | EFI_LOADER_DATA, size, e820ext); | ||
651 | |||
652 | if (status == EFI_SUCCESS) | ||
653 | *e820ext_size = size; | ||
1112 | 654 | ||
1113 | free_mem_map: | ||
1114 | low_free(_size, (unsigned long)mem_map); | ||
1115 | return status; | 655 | return status; |
1116 | } | 656 | } |
1117 | 657 | ||
1118 | static efi_status_t relocate_kernel(struct setup_header *hdr) | 658 | static efi_status_t exit_boot(struct boot_params *boot_params, |
659 | void *handle) | ||
1119 | { | 660 | { |
1120 | unsigned long start, nr_pages; | 661 | struct efi_info *efi = &boot_params->efi_info; |
662 | unsigned long map_sz, key, desc_size; | ||
663 | efi_memory_desc_t *mem_map; | ||
664 | struct setup_data *e820ext; | ||
665 | __u32 e820ext_size; | ||
666 | __u32 nr_desc, prev_nr_desc; | ||
1121 | efi_status_t status; | 667 | efi_status_t status; |
668 | __u32 desc_version; | ||
669 | bool called_exit = false; | ||
670 | u8 nr_entries; | ||
671 | int i; | ||
1122 | 672 | ||
1123 | /* | 673 | nr_desc = 0; |
1124 | * The EFI firmware loader could have placed the kernel image | 674 | e820ext = NULL; |
1125 | * anywhere in memory, but the kernel has various restrictions | 675 | e820ext_size = 0; |
1126 | * on the max physical address it can run at. Attempt to move | ||
1127 | * the kernel to boot_params.pref_address, or as low as | ||
1128 | * possible. | ||
1129 | */ | ||
1130 | start = hdr->pref_address; | ||
1131 | nr_pages = round_up(hdr->init_size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; | ||
1132 | 676 | ||
1133 | status = efi_call_phys4(sys_table->boottime->allocate_pages, | 677 | get_map: |
1134 | EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA, | 678 | status = efi_get_memory_map(sys_table, &mem_map, &map_sz, &desc_size, |
1135 | nr_pages, &start); | 679 | &desc_version, &key); |
1136 | if (status != EFI_SUCCESS) { | 680 | |
1137 | status = low_alloc(hdr->init_size, hdr->kernel_alignment, | 681 | if (status != EFI_SUCCESS) |
1138 | &start); | 682 | return status; |
683 | |||
684 | prev_nr_desc = nr_desc; | ||
685 | nr_desc = map_sz / desc_size; | ||
686 | if (nr_desc > prev_nr_desc && | ||
687 | nr_desc > ARRAY_SIZE(boot_params->e820_map)) { | ||
688 | u32 nr_e820ext = nr_desc - ARRAY_SIZE(boot_params->e820_map); | ||
689 | |||
690 | status = alloc_e820ext(nr_e820ext, &e820ext, &e820ext_size); | ||
1139 | if (status != EFI_SUCCESS) | 691 | if (status != EFI_SUCCESS) |
1140 | efi_printk("Failed to alloc mem for kernel\n"); | 692 | goto free_mem_map; |
693 | |||
694 | efi_call_phys1(sys_table->boottime->free_pool, mem_map); | ||
695 | goto get_map; /* Allocated memory, get map again */ | ||
1141 | } | 696 | } |
1142 | 697 | ||
1143 | if (status == EFI_SUCCESS) | 698 | memcpy(&efi->efi_loader_signature, EFI_LOADER_SIGNATURE, sizeof(__u32)); |
1144 | memcpy((void *)start, (void *)(unsigned long)hdr->code32_start, | 699 | efi->efi_systab = (unsigned long)sys_table; |
1145 | hdr->init_size); | 700 | efi->efi_memdesc_size = desc_size; |
701 | efi->efi_memdesc_version = desc_version; | ||
702 | efi->efi_memmap = (unsigned long)mem_map; | ||
703 | efi->efi_memmap_size = map_sz; | ||
704 | |||
705 | #ifdef CONFIG_X86_64 | ||
706 | efi->efi_systab_hi = (unsigned long)sys_table >> 32; | ||
707 | efi->efi_memmap_hi = (unsigned long)mem_map >> 32; | ||
708 | #endif | ||
1146 | 709 | ||
1147 | hdr->pref_address = hdr->code32_start; | 710 | /* Might as well exit boot services now */ |
1148 | hdr->code32_start = (__u32)start; | 711 | status = efi_call_phys2(sys_table->boottime->exit_boot_services, |
712 | handle, key); | ||
713 | if (status != EFI_SUCCESS) { | ||
714 | /* | ||
715 | * ExitBootServices() will fail if any of the event | ||
716 | * handlers change the memory map. In which case, we | ||
717 | * must be prepared to retry, but only once so that | ||
718 | * we're guaranteed to exit on repeated failures instead | ||
719 | * of spinning forever. | ||
720 | */ | ||
721 | if (called_exit) | ||
722 | goto free_mem_map; | ||
1149 | 723 | ||
724 | called_exit = true; | ||
725 | efi_call_phys1(sys_table->boottime->free_pool, mem_map); | ||
726 | goto get_map; | ||
727 | } | ||
728 | |||
729 | /* Historic? */ | ||
730 | boot_params->alt_mem_k = 32 * 1024; | ||
731 | |||
732 | status = setup_e820(boot_params, e820ext, e820ext_size); | ||
733 | if (status != EFI_SUCCESS) | ||
734 | return status; | ||
735 | |||
736 | return EFI_SUCCESS; | ||
737 | |||
738 | free_mem_map: | ||
739 | efi_call_phys1(sys_table->boottime->free_pool, mem_map); | ||
1150 | return status; | 740 | return status; |
1151 | } | 741 | } |
1152 | 742 | ||
743 | |||
1153 | /* | 744 | /* |
1154 | * On success we return a pointer to a boot_params structure, and NULL | 745 | * On success we return a pointer to a boot_params structure, and NULL |
1155 | * on failure. | 746 | * on failure. |
@@ -1157,7 +748,7 @@ static efi_status_t relocate_kernel(struct setup_header *hdr) | |||
1157 | struct boot_params *efi_main(void *handle, efi_system_table_t *_table, | 748 | struct boot_params *efi_main(void *handle, efi_system_table_t *_table, |
1158 | struct boot_params *boot_params) | 749 | struct boot_params *boot_params) |
1159 | { | 750 | { |
1160 | struct desc_ptr *gdt, *idt; | 751 | struct desc_ptr *gdt; |
1161 | efi_loaded_image_t *image; | 752 | efi_loaded_image_t *image; |
1162 | struct setup_header *hdr = &boot_params->hdr; | 753 | struct setup_header *hdr = &boot_params->hdr; |
1163 | efi_status_t status; | 754 | efi_status_t status; |
@@ -1177,37 +768,33 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table, | |||
1177 | EFI_LOADER_DATA, sizeof(*gdt), | 768 | EFI_LOADER_DATA, sizeof(*gdt), |
1178 | (void **)&gdt); | 769 | (void **)&gdt); |
1179 | if (status != EFI_SUCCESS) { | 770 | if (status != EFI_SUCCESS) { |
1180 | efi_printk("Failed to alloc mem for gdt structure\n"); | 771 | efi_printk(sys_table, "Failed to alloc mem for gdt structure\n"); |
1181 | goto fail; | 772 | goto fail; |
1182 | } | 773 | } |
1183 | 774 | ||
1184 | gdt->size = 0x800; | 775 | gdt->size = 0x800; |
1185 | status = low_alloc(gdt->size, 8, (unsigned long *)&gdt->address); | 776 | status = efi_low_alloc(sys_table, gdt->size, 8, |
1186 | if (status != EFI_SUCCESS) { | 777 | (unsigned long *)&gdt->address); |
1187 | efi_printk("Failed to alloc mem for gdt\n"); | ||
1188 | goto fail; | ||
1189 | } | ||
1190 | |||
1191 | status = efi_call_phys3(sys_table->boottime->allocate_pool, | ||
1192 | EFI_LOADER_DATA, sizeof(*idt), | ||
1193 | (void **)&idt); | ||
1194 | if (status != EFI_SUCCESS) { | 778 | if (status != EFI_SUCCESS) { |
1195 | efi_printk("Failed to alloc mem for idt structure\n"); | 779 | efi_printk(sys_table, "Failed to alloc mem for gdt\n"); |
1196 | goto fail; | 780 | goto fail; |
1197 | } | 781 | } |
1198 | 782 | ||
1199 | idt->size = 0; | ||
1200 | idt->address = 0; | ||
1201 | |||
1202 | /* | 783 | /* |
1203 | * If the kernel isn't already loaded at the preferred load | 784 | * If the kernel isn't already loaded at the preferred load |
1204 | * address, relocate it. | 785 | * address, relocate it. |
1205 | */ | 786 | */ |
1206 | if (hdr->pref_address != hdr->code32_start) { | 787 | if (hdr->pref_address != hdr->code32_start) { |
1207 | status = relocate_kernel(hdr); | 788 | unsigned long bzimage_addr = hdr->code32_start; |
1208 | 789 | status = efi_relocate_kernel(sys_table, &bzimage_addr, | |
790 | hdr->init_size, hdr->init_size, | ||
791 | hdr->pref_address, | ||
792 | hdr->kernel_alignment); | ||
1209 | if (status != EFI_SUCCESS) | 793 | if (status != EFI_SUCCESS) |
1210 | goto fail; | 794 | goto fail; |
795 | |||
796 | hdr->pref_address = hdr->code32_start; | ||
797 | hdr->code32_start = bzimage_addr; | ||
1211 | } | 798 | } |
1212 | 799 | ||
1213 | status = exit_boot(boot_params, handle); | 800 | status = exit_boot(boot_params, handle); |
@@ -1267,10 +854,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table, | |||
1267 | desc->base2 = 0x00; | 854 | desc->base2 = 0x00; |
1268 | #endif /* CONFIG_X86_64 */ | 855 | #endif /* CONFIG_X86_64 */ |
1269 | 856 | ||
1270 | asm volatile ("lidt %0" : : "m" (*idt)); | ||
1271 | asm volatile ("lgdt %0" : : "m" (*gdt)); | ||
1272 | |||
1273 | asm volatile("cli"); | 857 | asm volatile("cli"); |
858 | asm volatile ("lgdt %0" : : "m" (*gdt)); | ||
1274 | 859 | ||
1275 | return boot_params; | 860 | return boot_params; |
1276 | fail: | 861 | fail: |
diff --git a/arch/x86/boot/compressed/eboot.h b/arch/x86/boot/compressed/eboot.h index e5b0a8f91c5f..81b6b652b46a 100644 --- a/arch/x86/boot/compressed/eboot.h +++ b/arch/x86/boot/compressed/eboot.h | |||
@@ -11,9 +11,6 @@ | |||
11 | 11 | ||
12 | #define DESC_TYPE_CODE_DATA (1 << 0) | 12 | #define DESC_TYPE_CODE_DATA (1 << 0) |
13 | 13 | ||
14 | #define EFI_PAGE_SIZE (1UL << EFI_PAGE_SHIFT) | ||
15 | #define EFI_READ_CHUNK_SIZE (1024 * 1024) | ||
16 | |||
17 | #define EFI_CONSOLE_OUT_DEVICE_GUID \ | 14 | #define EFI_CONSOLE_OUT_DEVICE_GUID \ |
18 | EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x0, 0x90, 0x27, \ | 15 | EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x0, 0x90, 0x27, \ |
19 | 0x3f, 0xc1, 0x4d) | 16 | 0x3f, 0xc1, 0x4d) |
@@ -62,10 +59,4 @@ struct efi_uga_draw_protocol { | |||
62 | void *blt; | 59 | void *blt; |
63 | }; | 60 | }; |
64 | 61 | ||
65 | struct efi_simple_text_output_protocol { | ||
66 | void *reset; | ||
67 | void *output_string; | ||
68 | void *test_string; | ||
69 | }; | ||
70 | |||
71 | #endif /* BOOT_COMPRESSED_EBOOT_H */ | 62 | #endif /* BOOT_COMPRESSED_EBOOT_H */ |
diff --git a/arch/x86/boot/compressed/mkpiggy.c b/arch/x86/boot/compressed/mkpiggy.c index 958a641483dd..b669ab65bf6c 100644 --- a/arch/x86/boot/compressed/mkpiggy.c +++ b/arch/x86/boot/compressed/mkpiggy.c | |||
@@ -36,11 +36,12 @@ int main(int argc, char *argv[]) | |||
36 | uint32_t olen; | 36 | uint32_t olen; |
37 | long ilen; | 37 | long ilen; |
38 | unsigned long offs; | 38 | unsigned long offs; |
39 | FILE *f; | 39 | FILE *f = NULL; |
40 | int retval = 1; | ||
40 | 41 | ||
41 | if (argc < 2) { | 42 | if (argc < 2) { |
42 | fprintf(stderr, "Usage: %s compressed_file\n", argv[0]); | 43 | fprintf(stderr, "Usage: %s compressed_file\n", argv[0]); |
43 | return 1; | 44 | goto bail; |
44 | } | 45 | } |
45 | 46 | ||
46 | /* Get the information for the compressed kernel image first */ | 47 | /* Get the information for the compressed kernel image first */ |
@@ -48,7 +49,7 @@ int main(int argc, char *argv[]) | |||
48 | f = fopen(argv[1], "r"); | 49 | f = fopen(argv[1], "r"); |
49 | if (!f) { | 50 | if (!f) { |
50 | perror(argv[1]); | 51 | perror(argv[1]); |
51 | return 1; | 52 | goto bail; |
52 | } | 53 | } |
53 | 54 | ||
54 | 55 | ||
@@ -58,12 +59,11 @@ int main(int argc, char *argv[]) | |||
58 | 59 | ||
59 | if (fread(&olen, sizeof(olen), 1, f) != 1) { | 60 | if (fread(&olen, sizeof(olen), 1, f) != 1) { |
60 | perror(argv[1]); | 61 | perror(argv[1]); |
61 | return 1; | 62 | goto bail; |
62 | } | 63 | } |
63 | 64 | ||
64 | ilen = ftell(f); | 65 | ilen = ftell(f); |
65 | olen = get_unaligned_le32(&olen); | 66 | olen = get_unaligned_le32(&olen); |
66 | fclose(f); | ||
67 | 67 | ||
68 | /* | 68 | /* |
69 | * Now we have the input (compressed) and output (uncompressed) | 69 | * Now we have the input (compressed) and output (uncompressed) |
@@ -91,5 +91,9 @@ int main(int argc, char *argv[]) | |||
91 | printf(".incbin \"%s\"\n", argv[1]); | 91 | printf(".incbin \"%s\"\n", argv[1]); |
92 | printf("input_data_end:\n"); | 92 | printf("input_data_end:\n"); |
93 | 93 | ||
94 | return 0; | 94 | retval = 0; |
95 | bail: | ||
96 | if (f) | ||
97 | fclose(f); | ||
98 | return retval; | ||
95 | } | 99 | } |
diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c index c941d6a8887f..8e15b22391fc 100644 --- a/arch/x86/boot/tools/build.c +++ b/arch/x86/boot/tools/build.c | |||
@@ -5,14 +5,15 @@ | |||
5 | */ | 5 | */ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * This file builds a disk-image from two different files: | 8 | * This file builds a disk-image from three different files: |
9 | * | 9 | * |
10 | * - setup: 8086 machine code, sets up system parm | 10 | * - setup: 8086 machine code, sets up system parm |
11 | * - system: 80386 code for actual system | 11 | * - system: 80386 code for actual system |
12 | * - zoffset.h: header with ZO_* defines | ||
12 | * | 13 | * |
13 | * It does some checking that all files are of the correct type, and | 14 | * It does some checking that all files are of the correct type, and writes |
14 | * just writes the result to stdout, removing headers and padding to | 15 | * the result to the specified destination, removing headers and padding to |
15 | * the right amount. It also writes some system data to stderr. | 16 | * the right amount. It also writes some system data to stdout. |
16 | */ | 17 | */ |
17 | 18 | ||
18 | /* | 19 | /* |
@@ -136,7 +137,7 @@ static void die(const char * str, ...) | |||
136 | 137 | ||
137 | static void usage(void) | 138 | static void usage(void) |
138 | { | 139 | { |
139 | die("Usage: build setup system [zoffset.h] [> image]"); | 140 | die("Usage: build setup system zoffset.h image"); |
140 | } | 141 | } |
141 | 142 | ||
142 | #ifdef CONFIG_EFI_STUB | 143 | #ifdef CONFIG_EFI_STUB |
@@ -265,7 +266,7 @@ int main(int argc, char ** argv) | |||
265 | int c; | 266 | int c; |
266 | u32 sys_size; | 267 | u32 sys_size; |
267 | struct stat sb; | 268 | struct stat sb; |
268 | FILE *file; | 269 | FILE *file, *dest; |
269 | int fd; | 270 | int fd; |
270 | void *kernel; | 271 | void *kernel; |
271 | u32 crc = 0xffffffffUL; | 272 | u32 crc = 0xffffffffUL; |
@@ -280,10 +281,13 @@ int main(int argc, char ** argv) | |||
280 | startup_64 = 0x200; | 281 | startup_64 = 0x200; |
281 | #endif | 282 | #endif |
282 | 283 | ||
283 | if (argc == 4) | 284 | if (argc != 5) |
284 | parse_zoffset(argv[3]); | ||
285 | else if (argc != 3) | ||
286 | usage(); | 285 | usage(); |
286 | parse_zoffset(argv[3]); | ||
287 | |||
288 | dest = fopen(argv[4], "w"); | ||
289 | if (!dest) | ||
290 | die("Unable to write `%s': %m", argv[4]); | ||
287 | 291 | ||
288 | /* Copy the setup code */ | 292 | /* Copy the setup code */ |
289 | file = fopen(argv[1], "r"); | 293 | file = fopen(argv[1], "r"); |
@@ -318,7 +322,7 @@ int main(int argc, char ** argv) | |||
318 | /* Set the default root device */ | 322 | /* Set the default root device */ |
319 | put_unaligned_le16(DEFAULT_ROOT_DEV, &buf[508]); | 323 | put_unaligned_le16(DEFAULT_ROOT_DEV, &buf[508]); |
320 | 324 | ||
321 | fprintf(stderr, "Setup is %d bytes (padded to %d bytes).\n", c, i); | 325 | printf("Setup is %d bytes (padded to %d bytes).\n", c, i); |
322 | 326 | ||
323 | /* Open and stat the kernel file */ | 327 | /* Open and stat the kernel file */ |
324 | fd = open(argv[2], O_RDONLY); | 328 | fd = open(argv[2], O_RDONLY); |
@@ -327,7 +331,7 @@ int main(int argc, char ** argv) | |||
327 | if (fstat(fd, &sb)) | 331 | if (fstat(fd, &sb)) |
328 | die("Unable to stat `%s': %m", argv[2]); | 332 | die("Unable to stat `%s': %m", argv[2]); |
329 | sz = sb.st_size; | 333 | sz = sb.st_size; |
330 | fprintf (stderr, "System is %d kB\n", (sz+1023)/1024); | 334 | printf("System is %d kB\n", (sz+1023)/1024); |
331 | kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0); | 335 | kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0); |
332 | if (kernel == MAP_FAILED) | 336 | if (kernel == MAP_FAILED) |
333 | die("Unable to mmap '%s': %m", argv[2]); | 337 | die("Unable to mmap '%s': %m", argv[2]); |
@@ -348,27 +352,31 @@ int main(int argc, char ** argv) | |||
348 | #endif | 352 | #endif |
349 | 353 | ||
350 | crc = partial_crc32(buf, i, crc); | 354 | crc = partial_crc32(buf, i, crc); |
351 | if (fwrite(buf, 1, i, stdout) != i) | 355 | if (fwrite(buf, 1, i, dest) != i) |
352 | die("Writing setup failed"); | 356 | die("Writing setup failed"); |
353 | 357 | ||
354 | /* Copy the kernel code */ | 358 | /* Copy the kernel code */ |
355 | crc = partial_crc32(kernel, sz, crc); | 359 | crc = partial_crc32(kernel, sz, crc); |
356 | if (fwrite(kernel, 1, sz, stdout) != sz) | 360 | if (fwrite(kernel, 1, sz, dest) != sz) |
357 | die("Writing kernel failed"); | 361 | die("Writing kernel failed"); |
358 | 362 | ||
359 | /* Add padding leaving 4 bytes for the checksum */ | 363 | /* Add padding leaving 4 bytes for the checksum */ |
360 | while (sz++ < (sys_size*16) - 4) { | 364 | while (sz++ < (sys_size*16) - 4) { |
361 | crc = partial_crc32_one('\0', crc); | 365 | crc = partial_crc32_one('\0', crc); |
362 | if (fwrite("\0", 1, 1, stdout) != 1) | 366 | if (fwrite("\0", 1, 1, dest) != 1) |
363 | die("Writing padding failed"); | 367 | die("Writing padding failed"); |
364 | } | 368 | } |
365 | 369 | ||
366 | /* Write the CRC */ | 370 | /* Write the CRC */ |
367 | fprintf(stderr, "CRC %x\n", crc); | 371 | printf("CRC %x\n", crc); |
368 | put_unaligned_le32(crc, buf); | 372 | put_unaligned_le32(crc, buf); |
369 | if (fwrite(buf, 1, 4, stdout) != 4) | 373 | if (fwrite(buf, 1, 4, dest) != 4) |
370 | die("Writing CRC failed"); | 374 | die("Writing CRC failed"); |
371 | 375 | ||
376 | /* Catch any delayed write failures */ | ||
377 | if (fclose(dest)) | ||
378 | die("Writing image failed"); | ||
379 | |||
372 | close(fd); | 380 | close(fd); |
373 | 381 | ||
374 | /* Everything is OK */ | 382 | /* Everything is OK */ |
diff --git a/arch/x86/configs/i386_defconfig b/arch/x86/configs/i386_defconfig index 94447086e551..a7fef2621cc9 100644 --- a/arch/x86/configs/i386_defconfig +++ b/arch/x86/configs/i386_defconfig | |||
@@ -142,6 +142,8 @@ CONFIG_MAC80211=y | |||
142 | CONFIG_MAC80211_LEDS=y | 142 | CONFIG_MAC80211_LEDS=y |
143 | CONFIG_RFKILL=y | 143 | CONFIG_RFKILL=y |
144 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | 144 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" |
145 | CONFIG_DEVTMPFS=y | ||
146 | CONFIG_DEVTMPFS_MOUNT=y | ||
145 | CONFIG_DEBUG_DEVRES=y | 147 | CONFIG_DEBUG_DEVRES=y |
146 | CONFIG_CONNECTOR=y | 148 | CONFIG_CONNECTOR=y |
147 | CONFIG_BLK_DEV_LOOP=y | 149 | CONFIG_BLK_DEV_LOOP=y |
diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig index 671524d0f6c0..c1119d4c1281 100644 --- a/arch/x86/configs/x86_64_defconfig +++ b/arch/x86/configs/x86_64_defconfig | |||
@@ -141,6 +141,8 @@ CONFIG_MAC80211=y | |||
141 | CONFIG_MAC80211_LEDS=y | 141 | CONFIG_MAC80211_LEDS=y |
142 | CONFIG_RFKILL=y | 142 | CONFIG_RFKILL=y |
143 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | 143 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" |
144 | CONFIG_DEVTMPFS=y | ||
145 | CONFIG_DEVTMPFS_MOUNT=y | ||
144 | CONFIG_DEBUG_DEVRES=y | 146 | CONFIG_DEBUG_DEVRES=y |
145 | CONFIG_CONNECTOR=y | 147 | CONFIG_CONNECTOR=y |
146 | CONFIG_BLK_DEV_LOOP=y | 148 | CONFIG_BLK_DEV_LOOP=y |
diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c index bae3aba95b15..d21ff89207cd 100644 --- a/arch/x86/ia32/ia32_aout.c +++ b/arch/x86/ia32/ia32_aout.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/personality.h> | 25 | #include <linux/personality.h> |
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/jiffies.h> | 27 | #include <linux/jiffies.h> |
28 | #include <linux/perf_event.h> | ||
28 | 29 | ||
29 | #include <asm/uaccess.h> | 30 | #include <asm/uaccess.h> |
30 | #include <asm/pgalloc.h> | 31 | #include <asm/pgalloc.h> |
@@ -33,14 +34,18 @@ | |||
33 | #include <asm/ia32.h> | 34 | #include <asm/ia32.h> |
34 | 35 | ||
35 | #undef WARN_OLD | 36 | #undef WARN_OLD |
36 | #undef CORE_DUMP /* definitely broken */ | ||
37 | 37 | ||
38 | static int load_aout_binary(struct linux_binprm *); | 38 | static int load_aout_binary(struct linux_binprm *); |
39 | static int load_aout_library(struct file *); | 39 | static int load_aout_library(struct file *); |
40 | 40 | ||
41 | #ifdef CORE_DUMP | 41 | #ifdef CONFIG_COREDUMP |
42 | static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, | 42 | static int aout_core_dump(struct coredump_params *); |
43 | unsigned long limit); | 43 | |
44 | static unsigned long get_dr(int n) | ||
45 | { | ||
46 | struct perf_event *bp = current->thread.ptrace_bps[n]; | ||
47 | return bp ? bp->hw.info.address : 0; | ||
48 | } | ||
44 | 49 | ||
45 | /* | 50 | /* |
46 | * fill in the user structure for a core dump.. | 51 | * fill in the user structure for a core dump.. |
@@ -48,6 +53,7 @@ static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, | |||
48 | static void dump_thread32(struct pt_regs *regs, struct user32 *dump) | 53 | static void dump_thread32(struct pt_regs *regs, struct user32 *dump) |
49 | { | 54 | { |
50 | u32 fs, gs; | 55 | u32 fs, gs; |
56 | memset(dump, 0, sizeof(*dump)); | ||
51 | 57 | ||
52 | /* changed the size calculations - should hopefully work better. lbt */ | 58 | /* changed the size calculations - should hopefully work better. lbt */ |
53 | dump->magic = CMAGIC; | 59 | dump->magic = CMAGIC; |
@@ -57,15 +63,12 @@ static void dump_thread32(struct pt_regs *regs, struct user32 *dump) | |||
57 | dump->u_dsize = ((unsigned long) | 63 | dump->u_dsize = ((unsigned long) |
58 | (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT; | 64 | (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT; |
59 | dump->u_dsize -= dump->u_tsize; | 65 | dump->u_dsize -= dump->u_tsize; |
60 | dump->u_ssize = 0; | 66 | dump->u_debugreg[0] = get_dr(0); |
61 | dump->u_debugreg[0] = current->thread.debugreg0; | 67 | dump->u_debugreg[1] = get_dr(1); |
62 | dump->u_debugreg[1] = current->thread.debugreg1; | 68 | dump->u_debugreg[2] = get_dr(2); |
63 | dump->u_debugreg[2] = current->thread.debugreg2; | 69 | dump->u_debugreg[3] = get_dr(3); |
64 | dump->u_debugreg[3] = current->thread.debugreg3; | ||
65 | dump->u_debugreg[4] = 0; | ||
66 | dump->u_debugreg[5] = 0; | ||
67 | dump->u_debugreg[6] = current->thread.debugreg6; | 70 | dump->u_debugreg[6] = current->thread.debugreg6; |
68 | dump->u_debugreg[7] = current->thread.debugreg7; | 71 | dump->u_debugreg[7] = current->thread.ptrace_dr7; |
69 | 72 | ||
70 | if (dump->start_stack < 0xc0000000) { | 73 | if (dump->start_stack < 0xc0000000) { |
71 | unsigned long tmp; | 74 | unsigned long tmp; |
@@ -74,24 +77,24 @@ static void dump_thread32(struct pt_regs *regs, struct user32 *dump) | |||
74 | dump->u_ssize = tmp >> PAGE_SHIFT; | 77 | dump->u_ssize = tmp >> PAGE_SHIFT; |
75 | } | 78 | } |
76 | 79 | ||
77 | dump->regs.bx = regs->bx; | 80 | dump->regs.ebx = regs->bx; |
78 | dump->regs.cx = regs->cx; | 81 | dump->regs.ecx = regs->cx; |
79 | dump->regs.dx = regs->dx; | 82 | dump->regs.edx = regs->dx; |
80 | dump->regs.si = regs->si; | 83 | dump->regs.esi = regs->si; |
81 | dump->regs.di = regs->di; | 84 | dump->regs.edi = regs->di; |
82 | dump->regs.bp = regs->bp; | 85 | dump->regs.ebp = regs->bp; |
83 | dump->regs.ax = regs->ax; | 86 | dump->regs.eax = regs->ax; |
84 | dump->regs.ds = current->thread.ds; | 87 | dump->regs.ds = current->thread.ds; |
85 | dump->regs.es = current->thread.es; | 88 | dump->regs.es = current->thread.es; |
86 | savesegment(fs, fs); | 89 | savesegment(fs, fs); |
87 | dump->regs.fs = fs; | 90 | dump->regs.fs = fs; |
88 | savesegment(gs, gs); | 91 | savesegment(gs, gs); |
89 | dump->regs.gs = gs; | 92 | dump->regs.gs = gs; |
90 | dump->regs.orig_ax = regs->orig_ax; | 93 | dump->regs.orig_eax = regs->orig_ax; |
91 | dump->regs.ip = regs->ip; | 94 | dump->regs.eip = regs->ip; |
92 | dump->regs.cs = regs->cs; | 95 | dump->regs.cs = regs->cs; |
93 | dump->regs.flags = regs->flags; | 96 | dump->regs.eflags = regs->flags; |
94 | dump->regs.sp = regs->sp; | 97 | dump->regs.esp = regs->sp; |
95 | dump->regs.ss = regs->ss; | 98 | dump->regs.ss = regs->ss; |
96 | 99 | ||
97 | #if 1 /* FIXME */ | 100 | #if 1 /* FIXME */ |
@@ -107,7 +110,7 @@ static struct linux_binfmt aout_format = { | |||
107 | .module = THIS_MODULE, | 110 | .module = THIS_MODULE, |
108 | .load_binary = load_aout_binary, | 111 | .load_binary = load_aout_binary, |
109 | .load_shlib = load_aout_library, | 112 | .load_shlib = load_aout_library, |
110 | #ifdef CORE_DUMP | 113 | #ifdef CONFIG_COREDUMP |
111 | .core_dump = aout_core_dump, | 114 | .core_dump = aout_core_dump, |
112 | #endif | 115 | #endif |
113 | .min_coredump = PAGE_SIZE | 116 | .min_coredump = PAGE_SIZE |
@@ -122,7 +125,7 @@ static void set_brk(unsigned long start, unsigned long end) | |||
122 | vm_brk(start, end - start); | 125 | vm_brk(start, end - start); |
123 | } | 126 | } |
124 | 127 | ||
125 | #ifdef CORE_DUMP | 128 | #ifdef CONFIG_COREDUMP |
126 | /* | 129 | /* |
127 | * These are the only things you should do on a core-file: use only these | 130 | * These are the only things you should do on a core-file: use only these |
128 | * macros to write out all the necessary info. | 131 | * macros to write out all the necessary info. |
@@ -130,15 +133,7 @@ static void set_brk(unsigned long start, unsigned long end) | |||
130 | 133 | ||
131 | #include <linux/coredump.h> | 134 | #include <linux/coredump.h> |
132 | 135 | ||
133 | #define DUMP_WRITE(addr, nr) \ | 136 | #define START_DATA(u) (u.u_tsize << PAGE_SHIFT) |
134 | if (!dump_write(file, (void *)(addr), (nr))) \ | ||
135 | goto end_coredump; | ||
136 | |||
137 | #define DUMP_SEEK(offset) \ | ||
138 | if (!dump_seek(file, offset)) \ | ||
139 | goto end_coredump; | ||
140 | |||
141 | #define START_DATA() (u.u_tsize << PAGE_SHIFT) | ||
142 | #define START_STACK(u) (u.start_stack) | 137 | #define START_STACK(u) (u.start_stack) |
143 | 138 | ||
144 | /* | 139 | /* |
@@ -151,8 +146,7 @@ static void set_brk(unsigned long start, unsigned long end) | |||
151 | * dumping of the process results in another error.. | 146 | * dumping of the process results in another error.. |
152 | */ | 147 | */ |
153 | 148 | ||
154 | static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, | 149 | static int aout_core_dump(struct coredump_params *cprm) |
155 | unsigned long limit) | ||
156 | { | 150 | { |
157 | mm_segment_t fs; | 151 | mm_segment_t fs; |
158 | int has_dumped = 0; | 152 | int has_dumped = 0; |
@@ -164,19 +158,19 @@ static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, | |||
164 | has_dumped = 1; | 158 | has_dumped = 1; |
165 | strncpy(dump.u_comm, current->comm, sizeof(current->comm)); | 159 | strncpy(dump.u_comm, current->comm, sizeof(current->comm)); |
166 | dump.u_ar0 = offsetof(struct user32, regs); | 160 | dump.u_ar0 = offsetof(struct user32, regs); |
167 | dump.signal = signr; | 161 | dump.signal = cprm->siginfo->si_signo; |
168 | dump_thread32(regs, &dump); | 162 | dump_thread32(cprm->regs, &dump); |
169 | 163 | ||
170 | /* | 164 | /* |
171 | * If the size of the dump file exceeds the rlimit, then see | 165 | * If the size of the dump file exceeds the rlimit, then see |
172 | * what would happen if we wrote the stack, but not the data | 166 | * what would happen if we wrote the stack, but not the data |
173 | * area. | 167 | * area. |
174 | */ | 168 | */ |
175 | if ((dump.u_dsize + dump.u_ssize + 1) * PAGE_SIZE > limit) | 169 | if ((dump.u_dsize + dump.u_ssize + 1) * PAGE_SIZE > cprm->limit) |
176 | dump.u_dsize = 0; | 170 | dump.u_dsize = 0; |
177 | 171 | ||
178 | /* Make sure we have enough room to write the stack and data areas. */ | 172 | /* Make sure we have enough room to write the stack and data areas. */ |
179 | if ((dump.u_ssize + 1) * PAGE_SIZE > limit) | 173 | if ((dump.u_ssize + 1) * PAGE_SIZE > cprm->limit) |
180 | dump.u_ssize = 0; | 174 | dump.u_ssize = 0; |
181 | 175 | ||
182 | /* make sure we actually have a data and stack area to dump */ | 176 | /* make sure we actually have a data and stack area to dump */ |
@@ -190,22 +184,26 @@ static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, | |||
190 | 184 | ||
191 | set_fs(KERNEL_DS); | 185 | set_fs(KERNEL_DS); |
192 | /* struct user */ | 186 | /* struct user */ |
193 | DUMP_WRITE(&dump, sizeof(dump)); | 187 | if (!dump_emit(cprm, &dump, sizeof(dump))) |
188 | goto end_coredump; | ||
194 | /* Now dump all of the user data. Include malloced stuff as well */ | 189 | /* Now dump all of the user data. Include malloced stuff as well */ |
195 | DUMP_SEEK(PAGE_SIZE - sizeof(dump)); | 190 | if (!dump_skip(cprm, PAGE_SIZE - sizeof(dump))) |
191 | goto end_coredump; | ||
196 | /* now we start writing out the user space info */ | 192 | /* now we start writing out the user space info */ |
197 | set_fs(USER_DS); | 193 | set_fs(USER_DS); |
198 | /* Dump the data area */ | 194 | /* Dump the data area */ |
199 | if (dump.u_dsize != 0) { | 195 | if (dump.u_dsize != 0) { |
200 | dump_start = START_DATA(dump); | 196 | dump_start = START_DATA(dump); |
201 | dump_size = dump.u_dsize << PAGE_SHIFT; | 197 | dump_size = dump.u_dsize << PAGE_SHIFT; |
202 | DUMP_WRITE(dump_start, dump_size); | 198 | if (!dump_emit(cprm, (void *)dump_start, dump_size)) |
199 | goto end_coredump; | ||
203 | } | 200 | } |
204 | /* Now prepare to dump the stack area */ | 201 | /* Now prepare to dump the stack area */ |
205 | if (dump.u_ssize != 0) { | 202 | if (dump.u_ssize != 0) { |
206 | dump_start = START_STACK(dump); | 203 | dump_start = START_STACK(dump); |
207 | dump_size = dump.u_ssize << PAGE_SHIFT; | 204 | dump_size = dump.u_ssize << PAGE_SHIFT; |
208 | DUMP_WRITE(dump_start, dump_size); | 205 | if (!dump_emit(cprm, (void *)dump_start, dump_size)) |
206 | goto end_coredump; | ||
209 | } | 207 | } |
210 | end_coredump: | 208 | end_coredump: |
211 | set_fs(fs); | 209 | set_fs(fs); |
diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index 665a730307f2..220675795e08 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c | |||
@@ -34,7 +34,7 @@ | |||
34 | #include <asm/sys_ia32.h> | 34 | #include <asm/sys_ia32.h> |
35 | #include <asm/smap.h> | 35 | #include <asm/smap.h> |
36 | 36 | ||
37 | int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) | 37 | int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from) |
38 | { | 38 | { |
39 | int err = 0; | 39 | int err = 0; |
40 | bool ia32 = test_thread_flag(TIF_IA32); | 40 | bool ia32 = test_thread_flag(TIF_IA32); |
diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h index b1977bad5435..c8c1e700c26e 100644 --- a/arch/x86/include/asm/acpi.h +++ b/arch/x86/include/asm/acpi.h | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <acpi/pdc_intel.h> | 26 | #include <acpi/pdc_intel.h> |
27 | 27 | ||
28 | #include <asm/numa.h> | 28 | #include <asm/numa.h> |
29 | #include <asm/fixmap.h> | ||
29 | #include <asm/processor.h> | 30 | #include <asm/processor.h> |
30 | #include <asm/mmu.h> | 31 | #include <asm/mmu.h> |
31 | #include <asm/mpspec.h> | 32 | #include <asm/mpspec.h> |
diff --git a/arch/x86/include/asm/atomic.h b/arch/x86/include/asm/atomic.h index 722aa3b04624..da31c8b8a92d 100644 --- a/arch/x86/include/asm/atomic.h +++ b/arch/x86/include/asm/atomic.h | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <asm/processor.h> | 6 | #include <asm/processor.h> |
7 | #include <asm/alternative.h> | 7 | #include <asm/alternative.h> |
8 | #include <asm/cmpxchg.h> | 8 | #include <asm/cmpxchg.h> |
9 | #include <asm/rmwcc.h> | ||
9 | 10 | ||
10 | /* | 11 | /* |
11 | * Atomic operations that C can't guarantee us. Useful for | 12 | * Atomic operations that C can't guarantee us. Useful for |
@@ -76,12 +77,7 @@ static inline void atomic_sub(int i, atomic_t *v) | |||
76 | */ | 77 | */ |
77 | static inline int atomic_sub_and_test(int i, atomic_t *v) | 78 | static inline int atomic_sub_and_test(int i, atomic_t *v) |
78 | { | 79 | { |
79 | unsigned char c; | 80 | GEN_BINARY_RMWcc(LOCK_PREFIX "subl", v->counter, i, "%0", "e"); |
80 | |||
81 | asm volatile(LOCK_PREFIX "subl %2,%0; sete %1" | ||
82 | : "+m" (v->counter), "=qm" (c) | ||
83 | : "ir" (i) : "memory"); | ||
84 | return c; | ||
85 | } | 81 | } |
86 | 82 | ||
87 | /** | 83 | /** |
@@ -118,12 +114,7 @@ static inline void atomic_dec(atomic_t *v) | |||
118 | */ | 114 | */ |
119 | static inline int atomic_dec_and_test(atomic_t *v) | 115 | static inline int atomic_dec_and_test(atomic_t *v) |
120 | { | 116 | { |
121 | unsigned char c; | 117 | GEN_UNARY_RMWcc(LOCK_PREFIX "decl", v->counter, "%0", "e"); |
122 | |||
123 | asm volatile(LOCK_PREFIX "decl %0; sete %1" | ||
124 | : "+m" (v->counter), "=qm" (c) | ||
125 | : : "memory"); | ||
126 | return c != 0; | ||
127 | } | 118 | } |
128 | 119 | ||
129 | /** | 120 | /** |
@@ -136,12 +127,7 @@ static inline int atomic_dec_and_test(atomic_t *v) | |||
136 | */ | 127 | */ |
137 | static inline int atomic_inc_and_test(atomic_t *v) | 128 | static inline int atomic_inc_and_test(atomic_t *v) |
138 | { | 129 | { |
139 | unsigned char c; | 130 | GEN_UNARY_RMWcc(LOCK_PREFIX "incl", v->counter, "%0", "e"); |
140 | |||
141 | asm volatile(LOCK_PREFIX "incl %0; sete %1" | ||
142 | : "+m" (v->counter), "=qm" (c) | ||
143 | : : "memory"); | ||
144 | return c != 0; | ||
145 | } | 131 | } |
146 | 132 | ||
147 | /** | 133 | /** |
@@ -155,12 +141,7 @@ static inline int atomic_inc_and_test(atomic_t *v) | |||
155 | */ | 141 | */ |
156 | static inline int atomic_add_negative(int i, atomic_t *v) | 142 | static inline int atomic_add_negative(int i, atomic_t *v) |
157 | { | 143 | { |
158 | unsigned char c; | 144 | GEN_BINARY_RMWcc(LOCK_PREFIX "addl", v->counter, i, "%0", "s"); |
159 | |||
160 | asm volatile(LOCK_PREFIX "addl %2,%0; sets %1" | ||
161 | : "+m" (v->counter), "=qm" (c) | ||
162 | : "ir" (i) : "memory"); | ||
163 | return c; | ||
164 | } | 145 | } |
165 | 146 | ||
166 | /** | 147 | /** |
diff --git a/arch/x86/include/asm/atomic64_64.h b/arch/x86/include/asm/atomic64_64.h index 0e1cbfc8ee06..3f065c985aee 100644 --- a/arch/x86/include/asm/atomic64_64.h +++ b/arch/x86/include/asm/atomic64_64.h | |||
@@ -72,12 +72,7 @@ static inline void atomic64_sub(long i, atomic64_t *v) | |||
72 | */ | 72 | */ |
73 | static inline int atomic64_sub_and_test(long i, atomic64_t *v) | 73 | static inline int atomic64_sub_and_test(long i, atomic64_t *v) |
74 | { | 74 | { |
75 | unsigned char c; | 75 | GEN_BINARY_RMWcc(LOCK_PREFIX "subq", v->counter, i, "%0", "e"); |
76 | |||
77 | asm volatile(LOCK_PREFIX "subq %2,%0; sete %1" | ||
78 | : "=m" (v->counter), "=qm" (c) | ||
79 | : "er" (i), "m" (v->counter) : "memory"); | ||
80 | return c; | ||
81 | } | 76 | } |
82 | 77 | ||
83 | /** | 78 | /** |
@@ -116,12 +111,7 @@ static inline void atomic64_dec(atomic64_t *v) | |||
116 | */ | 111 | */ |
117 | static inline int atomic64_dec_and_test(atomic64_t *v) | 112 | static inline int atomic64_dec_and_test(atomic64_t *v) |
118 | { | 113 | { |
119 | unsigned char c; | 114 | GEN_UNARY_RMWcc(LOCK_PREFIX "decq", v->counter, "%0", "e"); |
120 | |||
121 | asm volatile(LOCK_PREFIX "decq %0; sete %1" | ||
122 | : "=m" (v->counter), "=qm" (c) | ||
123 | : "m" (v->counter) : "memory"); | ||
124 | return c != 0; | ||
125 | } | 115 | } |
126 | 116 | ||
127 | /** | 117 | /** |
@@ -134,12 +124,7 @@ static inline int atomic64_dec_and_test(atomic64_t *v) | |||
134 | */ | 124 | */ |
135 | static inline int atomic64_inc_and_test(atomic64_t *v) | 125 | static inline int atomic64_inc_and_test(atomic64_t *v) |
136 | { | 126 | { |
137 | unsigned char c; | 127 | GEN_UNARY_RMWcc(LOCK_PREFIX "incq", v->counter, "%0", "e"); |
138 | |||
139 | asm volatile(LOCK_PREFIX "incq %0; sete %1" | ||
140 | : "=m" (v->counter), "=qm" (c) | ||
141 | : "m" (v->counter) : "memory"); | ||
142 | return c != 0; | ||
143 | } | 128 | } |
144 | 129 | ||
145 | /** | 130 | /** |
@@ -153,12 +138,7 @@ static inline int atomic64_inc_and_test(atomic64_t *v) | |||
153 | */ | 138 | */ |
154 | static inline int atomic64_add_negative(long i, atomic64_t *v) | 139 | static inline int atomic64_add_negative(long i, atomic64_t *v) |
155 | { | 140 | { |
156 | unsigned char c; | 141 | GEN_BINARY_RMWcc(LOCK_PREFIX "addq", v->counter, i, "%0", "s"); |
157 | |||
158 | asm volatile(LOCK_PREFIX "addq %2,%0; sets %1" | ||
159 | : "=m" (v->counter), "=qm" (c) | ||
160 | : "er" (i), "m" (v->counter) : "memory"); | ||
161 | return c; | ||
162 | } | 142 | } |
163 | 143 | ||
164 | /** | 144 | /** |
diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h index 41639ce8fd63..6d76d0935989 100644 --- a/arch/x86/include/asm/bitops.h +++ b/arch/x86/include/asm/bitops.h | |||
@@ -14,6 +14,7 @@ | |||
14 | 14 | ||
15 | #include <linux/compiler.h> | 15 | #include <linux/compiler.h> |
16 | #include <asm/alternative.h> | 16 | #include <asm/alternative.h> |
17 | #include <asm/rmwcc.h> | ||
17 | 18 | ||
18 | #if BITS_PER_LONG == 32 | 19 | #if BITS_PER_LONG == 32 |
19 | # define _BITOPS_LONG_SHIFT 5 | 20 | # define _BITOPS_LONG_SHIFT 5 |
@@ -204,12 +205,7 @@ static inline void change_bit(long nr, volatile unsigned long *addr) | |||
204 | */ | 205 | */ |
205 | static inline int test_and_set_bit(long nr, volatile unsigned long *addr) | 206 | static inline int test_and_set_bit(long nr, volatile unsigned long *addr) |
206 | { | 207 | { |
207 | int oldbit; | 208 | GEN_BINARY_RMWcc(LOCK_PREFIX "bts", *addr, nr, "%0", "c"); |
208 | |||
209 | asm volatile(LOCK_PREFIX "bts %2,%1\n\t" | ||
210 | "sbb %0,%0" : "=r" (oldbit), ADDR : "Ir" (nr) : "memory"); | ||
211 | |||
212 | return oldbit; | ||
213 | } | 209 | } |
214 | 210 | ||
215 | /** | 211 | /** |
@@ -255,13 +251,7 @@ static inline int __test_and_set_bit(long nr, volatile unsigned long *addr) | |||
255 | */ | 251 | */ |
256 | static inline int test_and_clear_bit(long nr, volatile unsigned long *addr) | 252 | static inline int test_and_clear_bit(long nr, volatile unsigned long *addr) |
257 | { | 253 | { |
258 | int oldbit; | 254 | GEN_BINARY_RMWcc(LOCK_PREFIX "btr", *addr, nr, "%0", "c"); |
259 | |||
260 | asm volatile(LOCK_PREFIX "btr %2,%1\n\t" | ||
261 | "sbb %0,%0" | ||
262 | : "=r" (oldbit), ADDR : "Ir" (nr) : "memory"); | ||
263 | |||
264 | return oldbit; | ||
265 | } | 255 | } |
266 | 256 | ||
267 | /** | 257 | /** |
@@ -314,13 +304,7 @@ static inline int __test_and_change_bit(long nr, volatile unsigned long *addr) | |||
314 | */ | 304 | */ |
315 | static inline int test_and_change_bit(long nr, volatile unsigned long *addr) | 305 | static inline int test_and_change_bit(long nr, volatile unsigned long *addr) |
316 | { | 306 | { |
317 | int oldbit; | 307 | GEN_BINARY_RMWcc(LOCK_PREFIX "btc", *addr, nr, "%0", "c"); |
318 | |||
319 | asm volatile(LOCK_PREFIX "btc %2,%1\n\t" | ||
320 | "sbb %0,%0" | ||
321 | : "=r" (oldbit), ADDR : "Ir" (nr) : "memory"); | ||
322 | |||
323 | return oldbit; | ||
324 | } | 308 | } |
325 | 309 | ||
326 | static __always_inline int constant_test_bit(long nr, const volatile unsigned long *addr) | 310 | static __always_inline int constant_test_bit(long nr, const volatile unsigned long *addr) |
diff --git a/arch/x86/include/asm/calling.h b/arch/x86/include/asm/calling.h index 0fa675033912..cb4c73bfeb48 100644 --- a/arch/x86/include/asm/calling.h +++ b/arch/x86/include/asm/calling.h | |||
@@ -48,6 +48,8 @@ For 32-bit we have the following conventions - kernel is built with | |||
48 | 48 | ||
49 | #include <asm/dwarf2.h> | 49 | #include <asm/dwarf2.h> |
50 | 50 | ||
51 | #ifdef CONFIG_X86_64 | ||
52 | |||
51 | /* | 53 | /* |
52 | * 64-bit system call stack frame layout defines and helpers, | 54 | * 64-bit system call stack frame layout defines and helpers, |
53 | * for assembly code: | 55 | * for assembly code: |
@@ -192,3 +194,51 @@ For 32-bit we have the following conventions - kernel is built with | |||
192 | .macro icebp | 194 | .macro icebp |
193 | .byte 0xf1 | 195 | .byte 0xf1 |
194 | .endm | 196 | .endm |
197 | |||
198 | #else /* CONFIG_X86_64 */ | ||
199 | |||
200 | /* | ||
201 | * For 32bit only simplified versions of SAVE_ALL/RESTORE_ALL. These | ||
202 | * are different from the entry_32.S versions in not changing the segment | ||
203 | * registers. So only suitable for in kernel use, not when transitioning | ||
204 | * from or to user space. The resulting stack frame is not a standard | ||
205 | * pt_regs frame. The main use case is calling C code from assembler | ||
206 | * when all the registers need to be preserved. | ||
207 | */ | ||
208 | |||
209 | .macro SAVE_ALL | ||
210 | pushl_cfi %eax | ||
211 | CFI_REL_OFFSET eax, 0 | ||
212 | pushl_cfi %ebp | ||
213 | CFI_REL_OFFSET ebp, 0 | ||
214 | pushl_cfi %edi | ||
215 | CFI_REL_OFFSET edi, 0 | ||
216 | pushl_cfi %esi | ||
217 | CFI_REL_OFFSET esi, 0 | ||
218 | pushl_cfi %edx | ||
219 | CFI_REL_OFFSET edx, 0 | ||
220 | pushl_cfi %ecx | ||
221 | CFI_REL_OFFSET ecx, 0 | ||
222 | pushl_cfi %ebx | ||
223 | CFI_REL_OFFSET ebx, 0 | ||
224 | .endm | ||
225 | |||
226 | .macro RESTORE_ALL | ||
227 | popl_cfi %ebx | ||
228 | CFI_RESTORE ebx | ||
229 | popl_cfi %ecx | ||
230 | CFI_RESTORE ecx | ||
231 | popl_cfi %edx | ||
232 | CFI_RESTORE edx | ||
233 | popl_cfi %esi | ||
234 | CFI_RESTORE esi | ||
235 | popl_cfi %edi | ||
236 | CFI_RESTORE edi | ||
237 | popl_cfi %ebp | ||
238 | CFI_RESTORE ebp | ||
239 | popl_cfi %eax | ||
240 | CFI_RESTORE eax | ||
241 | .endm | ||
242 | |||
243 | #endif /* CONFIG_X86_64 */ | ||
244 | |||
diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h index b90e5dfeee46..50d033a8947d 100644 --- a/arch/x86/include/asm/desc.h +++ b/arch/x86/include/asm/desc.h | |||
@@ -327,10 +327,25 @@ static inline void write_trace_idt_entry(int entry, const gate_desc *gate) | |||
327 | { | 327 | { |
328 | write_idt_entry(trace_idt_table, entry, gate); | 328 | write_idt_entry(trace_idt_table, entry, gate); |
329 | } | 329 | } |
330 | |||
331 | static inline void _trace_set_gate(int gate, unsigned type, void *addr, | ||
332 | unsigned dpl, unsigned ist, unsigned seg) | ||
333 | { | ||
334 | gate_desc s; | ||
335 | |||
336 | pack_gate(&s, type, (unsigned long)addr, dpl, ist, seg); | ||
337 | /* | ||
338 | * does not need to be atomic because it is only done once at | ||
339 | * setup time | ||
340 | */ | ||
341 | write_trace_idt_entry(gate, &s); | ||
342 | } | ||
330 | #else | 343 | #else |
331 | static inline void write_trace_idt_entry(int entry, const gate_desc *gate) | 344 | static inline void write_trace_idt_entry(int entry, const gate_desc *gate) |
332 | { | 345 | { |
333 | } | 346 | } |
347 | |||
348 | #define _trace_set_gate(gate, type, addr, dpl, ist, seg) | ||
334 | #endif | 349 | #endif |
335 | 350 | ||
336 | static inline void _set_gate(int gate, unsigned type, void *addr, | 351 | static inline void _set_gate(int gate, unsigned type, void *addr, |
@@ -353,11 +368,14 @@ static inline void _set_gate(int gate, unsigned type, void *addr, | |||
353 | * Pentium F0 0F bugfix can have resulted in the mapped | 368 | * Pentium F0 0F bugfix can have resulted in the mapped |
354 | * IDT being write-protected. | 369 | * IDT being write-protected. |
355 | */ | 370 | */ |
356 | static inline void set_intr_gate(unsigned int n, void *addr) | 371 | #define set_intr_gate(n, addr) \ |
357 | { | 372 | do { \ |
358 | BUG_ON((unsigned)n > 0xFF); | 373 | BUG_ON((unsigned)n > 0xFF); \ |
359 | _set_gate(n, GATE_INTERRUPT, addr, 0, 0, __KERNEL_CS); | 374 | _set_gate(n, GATE_INTERRUPT, (void *)addr, 0, 0, \ |
360 | } | 375 | __KERNEL_CS); \ |
376 | _trace_set_gate(n, GATE_INTERRUPT, (void *)trace_##addr,\ | ||
377 | 0, 0, __KERNEL_CS); \ | ||
378 | } while (0) | ||
361 | 379 | ||
362 | extern int first_system_vector; | 380 | extern int first_system_vector; |
363 | /* used_vectors is BITMAP for irq is not managed by percpu vector_irq */ | 381 | /* used_vectors is BITMAP for irq is not managed by percpu vector_irq */ |
@@ -374,37 +392,10 @@ static inline void alloc_system_vector(int vector) | |||
374 | } | 392 | } |
375 | } | 393 | } |
376 | 394 | ||
377 | #ifdef CONFIG_TRACING | ||
378 | static inline void trace_set_intr_gate(unsigned int gate, void *addr) | ||
379 | { | ||
380 | gate_desc s; | ||
381 | |||
382 | pack_gate(&s, GATE_INTERRUPT, (unsigned long)addr, 0, 0, __KERNEL_CS); | ||
383 | write_idt_entry(trace_idt_table, gate, &s); | ||
384 | } | ||
385 | |||
386 | static inline void __trace_alloc_intr_gate(unsigned int n, void *addr) | ||
387 | { | ||
388 | trace_set_intr_gate(n, addr); | ||
389 | } | ||
390 | #else | ||
391 | static inline void trace_set_intr_gate(unsigned int gate, void *addr) | ||
392 | { | ||
393 | } | ||
394 | |||
395 | #define __trace_alloc_intr_gate(n, addr) | ||
396 | #endif | ||
397 | |||
398 | static inline void __alloc_intr_gate(unsigned int n, void *addr) | ||
399 | { | ||
400 | set_intr_gate(n, addr); | ||
401 | } | ||
402 | |||
403 | #define alloc_intr_gate(n, addr) \ | 395 | #define alloc_intr_gate(n, addr) \ |
404 | do { \ | 396 | do { \ |
405 | alloc_system_vector(n); \ | 397 | alloc_system_vector(n); \ |
406 | __alloc_intr_gate(n, addr); \ | 398 | set_intr_gate(n, addr); \ |
407 | __trace_alloc_intr_gate(n, trace_##addr); \ | ||
408 | } while (0) | 399 | } while (0) |
409 | 400 | ||
410 | /* | 401 | /* |
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 0062a0125041..65c6e6e3a552 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h | |||
@@ -109,6 +109,8 @@ static inline bool efi_is_native(void) | |||
109 | return IS_ENABLED(CONFIG_X86_64) == efi_enabled(EFI_64BIT); | 109 | return IS_ENABLED(CONFIG_X86_64) == efi_enabled(EFI_64BIT); |
110 | } | 110 | } |
111 | 111 | ||
112 | extern struct console early_efi_console; | ||
113 | |||
112 | #else | 114 | #else |
113 | /* | 115 | /* |
114 | * IF EFI is not configured, have the EFI calls return -ENOSYS. | 116 | * IF EFI is not configured, have the EFI calls return -ENOSYS. |
diff --git a/arch/x86/include/asm/fpu-internal.h b/arch/x86/include/asm/fpu-internal.h index 4d0bda7b11e3..c49a613c6452 100644 --- a/arch/x86/include/asm/fpu-internal.h +++ b/arch/x86/include/asm/fpu-internal.h | |||
@@ -365,7 +365,7 @@ static inline void drop_fpu(struct task_struct *tsk) | |||
365 | * Forget coprocessor state.. | 365 | * Forget coprocessor state.. |
366 | */ | 366 | */ |
367 | preempt_disable(); | 367 | preempt_disable(); |
368 | tsk->fpu_counter = 0; | 368 | tsk->thread.fpu_counter = 0; |
369 | __drop_fpu(tsk); | 369 | __drop_fpu(tsk); |
370 | clear_used_math(); | 370 | clear_used_math(); |
371 | preempt_enable(); | 371 | preempt_enable(); |
@@ -424,7 +424,7 @@ static inline fpu_switch_t switch_fpu_prepare(struct task_struct *old, struct ta | |||
424 | * or if the past 5 consecutive context-switches used math. | 424 | * or if the past 5 consecutive context-switches used math. |
425 | */ | 425 | */ |
426 | fpu.preload = tsk_used_math(new) && (use_eager_fpu() || | 426 | fpu.preload = tsk_used_math(new) && (use_eager_fpu() || |
427 | new->fpu_counter > 5); | 427 | new->thread.fpu_counter > 5); |
428 | if (__thread_has_fpu(old)) { | 428 | if (__thread_has_fpu(old)) { |
429 | if (!__save_init_fpu(old)) | 429 | if (!__save_init_fpu(old)) |
430 | cpu = ~0; | 430 | cpu = ~0; |
@@ -433,16 +433,16 @@ static inline fpu_switch_t switch_fpu_prepare(struct task_struct *old, struct ta | |||
433 | 433 | ||
434 | /* Don't change CR0.TS if we just switch! */ | 434 | /* Don't change CR0.TS if we just switch! */ |
435 | if (fpu.preload) { | 435 | if (fpu.preload) { |
436 | new->fpu_counter++; | 436 | new->thread.fpu_counter++; |
437 | __thread_set_has_fpu(new); | 437 | __thread_set_has_fpu(new); |
438 | prefetch(new->thread.fpu.state); | 438 | prefetch(new->thread.fpu.state); |
439 | } else if (!use_eager_fpu()) | 439 | } else if (!use_eager_fpu()) |
440 | stts(); | 440 | stts(); |
441 | } else { | 441 | } else { |
442 | old->fpu_counter = 0; | 442 | old->thread.fpu_counter = 0; |
443 | old->thread.fpu.last_cpu = ~0; | 443 | old->thread.fpu.last_cpu = ~0; |
444 | if (fpu.preload) { | 444 | if (fpu.preload) { |
445 | new->fpu_counter++; | 445 | new->thread.fpu_counter++; |
446 | if (!use_eager_fpu() && fpu_lazy_restore(new, cpu)) | 446 | if (!use_eager_fpu() && fpu_lazy_restore(new, cpu)) |
447 | fpu.preload = 0; | 447 | fpu.preload = 0; |
448 | else | 448 | else |
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h index 92b3bae08b74..cba45d99ac1a 100644 --- a/arch/x86/include/asm/hw_irq.h +++ b/arch/x86/include/asm/hw_irq.h | |||
@@ -187,6 +187,9 @@ extern __visible void smp_invalidate_interrupt(struct pt_regs *); | |||
187 | #endif | 187 | #endif |
188 | 188 | ||
189 | extern void (*__initconst interrupt[NR_VECTORS-FIRST_EXTERNAL_VECTOR])(void); | 189 | extern void (*__initconst interrupt[NR_VECTORS-FIRST_EXTERNAL_VECTOR])(void); |
190 | #ifdef CONFIG_TRACING | ||
191 | #define trace_interrupt interrupt | ||
192 | #endif | ||
190 | 193 | ||
191 | typedef int vector_irq_t[NR_VECTORS]; | 194 | typedef int vector_irq_t[NR_VECTORS]; |
192 | DECLARE_PER_CPU(vector_irq_t, vector_irq); | 195 | DECLARE_PER_CPU(vector_irq_t, vector_irq); |
diff --git a/arch/x86/include/asm/intel-mid.h b/arch/x86/include/asm/intel-mid.h new file mode 100644 index 000000000000..459769d39263 --- /dev/null +++ b/arch/x86/include/asm/intel-mid.h | |||
@@ -0,0 +1,113 @@ | |||
1 | /* | ||
2 | * intel-mid.h: Intel MID specific setup code | ||
3 | * | ||
4 | * (C) Copyright 2009 Intel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; version 2 | ||
9 | * of the License. | ||
10 | */ | ||
11 | #ifndef _ASM_X86_INTEL_MID_H | ||
12 | #define _ASM_X86_INTEL_MID_H | ||
13 | |||
14 | #include <linux/sfi.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | |||
17 | extern int intel_mid_pci_init(void); | ||
18 | extern int get_gpio_by_name(const char *name); | ||
19 | extern void intel_scu_device_register(struct platform_device *pdev); | ||
20 | extern int __init sfi_parse_mrtc(struct sfi_table_header *table); | ||
21 | extern int __init sfi_parse_mtmr(struct sfi_table_header *table); | ||
22 | extern int sfi_mrtc_num; | ||
23 | extern struct sfi_rtc_table_entry sfi_mrtc_array[]; | ||
24 | |||
25 | /* | ||
26 | * Here defines the array of devices platform data that IAFW would export | ||
27 | * through SFI "DEVS" table, we use name and type to match the device and | ||
28 | * its platform data. | ||
29 | */ | ||
30 | struct devs_id { | ||
31 | char name[SFI_NAME_LEN + 1]; | ||
32 | u8 type; | ||
33 | u8 delay; | ||
34 | void *(*get_platform_data)(void *info); | ||
35 | /* Custom handler for devices */ | ||
36 | void (*device_handler)(struct sfi_device_table_entry *pentry, | ||
37 | struct devs_id *dev); | ||
38 | }; | ||
39 | |||
40 | #define sfi_device(i) \ | ||
41 | static const struct devs_id *const __intel_mid_sfi_##i##_dev __used \ | ||
42 | __attribute__((__section__(".x86_intel_mid_dev.init"))) = &i | ||
43 | |||
44 | /* | ||
45 | * Medfield is the follow-up of Moorestown, it combines two chip solution into | ||
46 | * one. Other than that it also added always-on and constant tsc and lapic | ||
47 | * timers. Medfield is the platform name, and the chip name is called Penwell | ||
48 | * we treat Medfield/Penwell as a variant of Moorestown. Penwell can be | ||
49 | * identified via MSRs. | ||
50 | */ | ||
51 | enum intel_mid_cpu_type { | ||
52 | /* 1 was Moorestown */ | ||
53 | INTEL_MID_CPU_CHIP_PENWELL = 2, | ||
54 | }; | ||
55 | |||
56 | extern enum intel_mid_cpu_type __intel_mid_cpu_chip; | ||
57 | |||
58 | #ifdef CONFIG_X86_INTEL_MID | ||
59 | |||
60 | static inline enum intel_mid_cpu_type intel_mid_identify_cpu(void) | ||
61 | { | ||
62 | return __intel_mid_cpu_chip; | ||
63 | } | ||
64 | |||
65 | static inline bool intel_mid_has_msic(void) | ||
66 | { | ||
67 | return (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_PENWELL); | ||
68 | } | ||
69 | |||
70 | #else /* !CONFIG_X86_INTEL_MID */ | ||
71 | |||
72 | #define intel_mid_identify_cpu() (0) | ||
73 | #define intel_mid_has_msic() (0) | ||
74 | |||
75 | #endif /* !CONFIG_X86_INTEL_MID */ | ||
76 | |||
77 | enum intel_mid_timer_options { | ||
78 | INTEL_MID_TIMER_DEFAULT, | ||
79 | INTEL_MID_TIMER_APBT_ONLY, | ||
80 | INTEL_MID_TIMER_LAPIC_APBT, | ||
81 | }; | ||
82 | |||
83 | extern enum intel_mid_timer_options intel_mid_timer_options; | ||
84 | |||
85 | /* | ||
86 | * Penwell uses spread spectrum clock, so the freq number is not exactly | ||
87 | * the same as reported by MSR based on SDM. | ||
88 | */ | ||
89 | #define PENWELL_FSB_FREQ_83SKU 83200 | ||
90 | #define PENWELL_FSB_FREQ_100SKU 99840 | ||
91 | |||
92 | #define SFI_MTMR_MAX_NUM 8 | ||
93 | #define SFI_MRTC_MAX 8 | ||
94 | |||
95 | extern struct console early_mrst_console; | ||
96 | extern void mrst_early_console_init(void); | ||
97 | |||
98 | extern struct console early_hsu_console; | ||
99 | extern void hsu_early_console_init(const char *); | ||
100 | |||
101 | extern void intel_scu_devices_create(void); | ||
102 | extern void intel_scu_devices_destroy(void); | ||
103 | |||
104 | /* VRTC timer */ | ||
105 | #define MRST_VRTC_MAP_SZ (1024) | ||
106 | /*#define MRST_VRTC_PGOFFSET (0xc00) */ | ||
107 | |||
108 | extern void intel_mid_rtc_init(void); | ||
109 | |||
110 | /* the offset for the mapping of global gpio pin to irq */ | ||
111 | #define INTEL_MID_IRQ_OFFSET 0x100 | ||
112 | |||
113 | #endif /* _ASM_X86_INTEL_MID_H */ | ||
diff --git a/arch/x86/include/asm/mrst-vrtc.h b/arch/x86/include/asm/intel_mid_vrtc.h index 1e69a75412a4..86ff4685c409 100644 --- a/arch/x86/include/asm/mrst-vrtc.h +++ b/arch/x86/include/asm/intel_mid_vrtc.h | |||
@@ -1,5 +1,5 @@ | |||
1 | #ifndef _MRST_VRTC_H | 1 | #ifndef _INTEL_MID_VRTC_H |
2 | #define _MRST_VRTC_H | 2 | #define _INTEL_MID_VRTC_H |
3 | 3 | ||
4 | extern unsigned char vrtc_cmos_read(unsigned char reg); | 4 | extern unsigned char vrtc_cmos_read(unsigned char reg); |
5 | extern void vrtc_cmos_write(unsigned char val, unsigned char reg); | 5 | extern void vrtc_cmos_write(unsigned char val, unsigned char reg); |
diff --git a/arch/x86/include/asm/kdebug.h b/arch/x86/include/asm/kdebug.h index 2c37aadcbc35..32ce71375b21 100644 --- a/arch/x86/include/asm/kdebug.h +++ b/arch/x86/include/asm/kdebug.h | |||
@@ -21,7 +21,7 @@ enum die_val { | |||
21 | DIE_NMIUNKNOWN, | 21 | DIE_NMIUNKNOWN, |
22 | }; | 22 | }; |
23 | 23 | ||
24 | extern void printk_address(unsigned long address, int reliable); | 24 | extern void printk_address(unsigned long address); |
25 | extern void die(const char *, struct pt_regs *,long); | 25 | extern void die(const char *, struct pt_regs *,long); |
26 | extern int __must_check __die(const char *, struct pt_regs *, long); | 26 | extern int __must_check __die(const char *, struct pt_regs *, long); |
27 | extern void show_trace(struct task_struct *t, struct pt_regs *regs, | 27 | extern void show_trace(struct task_struct *t, struct pt_regs *regs, |
diff --git a/arch/x86/include/asm/local.h b/arch/x86/include/asm/local.h index 2d89e3980cbd..5b23e605e707 100644 --- a/arch/x86/include/asm/local.h +++ b/arch/x86/include/asm/local.h | |||
@@ -52,12 +52,7 @@ static inline void local_sub(long i, local_t *l) | |||
52 | */ | 52 | */ |
53 | static inline int local_sub_and_test(long i, local_t *l) | 53 | static inline int local_sub_and_test(long i, local_t *l) |
54 | { | 54 | { |
55 | unsigned char c; | 55 | GEN_BINARY_RMWcc(_ASM_SUB, l->a.counter, i, "%0", "e"); |
56 | |||
57 | asm volatile(_ASM_SUB "%2,%0; sete %1" | ||
58 | : "+m" (l->a.counter), "=qm" (c) | ||
59 | : "ir" (i) : "memory"); | ||
60 | return c; | ||
61 | } | 56 | } |
62 | 57 | ||
63 | /** | 58 | /** |
@@ -70,12 +65,7 @@ static inline int local_sub_and_test(long i, local_t *l) | |||
70 | */ | 65 | */ |
71 | static inline int local_dec_and_test(local_t *l) | 66 | static inline int local_dec_and_test(local_t *l) |
72 | { | 67 | { |
73 | unsigned char c; | 68 | GEN_UNARY_RMWcc(_ASM_DEC, l->a.counter, "%0", "e"); |
74 | |||
75 | asm volatile(_ASM_DEC "%0; sete %1" | ||
76 | : "+m" (l->a.counter), "=qm" (c) | ||
77 | : : "memory"); | ||
78 | return c != 0; | ||
79 | } | 69 | } |
80 | 70 | ||
81 | /** | 71 | /** |
@@ -88,12 +78,7 @@ static inline int local_dec_and_test(local_t *l) | |||
88 | */ | 78 | */ |
89 | static inline int local_inc_and_test(local_t *l) | 79 | static inline int local_inc_and_test(local_t *l) |
90 | { | 80 | { |
91 | unsigned char c; | 81 | GEN_UNARY_RMWcc(_ASM_INC, l->a.counter, "%0", "e"); |
92 | |||
93 | asm volatile(_ASM_INC "%0; sete %1" | ||
94 | : "+m" (l->a.counter), "=qm" (c) | ||
95 | : : "memory"); | ||
96 | return c != 0; | ||
97 | } | 82 | } |
98 | 83 | ||
99 | /** | 84 | /** |
@@ -107,12 +92,7 @@ static inline int local_inc_and_test(local_t *l) | |||
107 | */ | 92 | */ |
108 | static inline int local_add_negative(long i, local_t *l) | 93 | static inline int local_add_negative(long i, local_t *l) |
109 | { | 94 | { |
110 | unsigned char c; | 95 | GEN_BINARY_RMWcc(_ASM_ADD, l->a.counter, i, "%0", "s"); |
111 | |||
112 | asm volatile(_ASM_ADD "%2,%0; sets %1" | ||
113 | : "+m" (l->a.counter), "=qm" (c) | ||
114 | : "ir" (i) : "memory"); | ||
115 | return c; | ||
116 | } | 96 | } |
117 | 97 | ||
118 | /** | 98 | /** |
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h index cbe6b9e404ce..c696a8687567 100644 --- a/arch/x86/include/asm/mce.h +++ b/arch/x86/include/asm/mce.h | |||
@@ -16,6 +16,7 @@ | |||
16 | #define MCG_EXT_CNT_SHIFT 16 | 16 | #define MCG_EXT_CNT_SHIFT 16 |
17 | #define MCG_EXT_CNT(c) (((c) & MCG_EXT_CNT_MASK) >> MCG_EXT_CNT_SHIFT) | 17 | #define MCG_EXT_CNT(c) (((c) & MCG_EXT_CNT_MASK) >> MCG_EXT_CNT_SHIFT) |
18 | #define MCG_SER_P (1ULL<<24) /* MCA recovery/new status bits */ | 18 | #define MCG_SER_P (1ULL<<24) /* MCA recovery/new status bits */ |
19 | #define MCG_ELOG_P (1ULL<<26) /* Extended error log supported */ | ||
19 | 20 | ||
20 | /* MCG_STATUS register defines */ | 21 | /* MCG_STATUS register defines */ |
21 | #define MCG_STATUS_RIPV (1ULL<<0) /* restart ip valid */ | 22 | #define MCG_STATUS_RIPV (1ULL<<0) /* restart ip valid */ |
diff --git a/arch/x86/include/asm/misc.h b/arch/x86/include/asm/misc.h new file mode 100644 index 000000000000..475f5bbc7f53 --- /dev/null +++ b/arch/x86/include/asm/misc.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_X86_MISC_H | ||
2 | #define _ASM_X86_MISC_H | ||
3 | |||
4 | int num_digits(int val); | ||
5 | |||
6 | #endif /* _ASM_X86_MISC_H */ | ||
diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h index 626cf70082d7..3142a94c7b4b 100644 --- a/arch/x86/include/asm/mpspec.h +++ b/arch/x86/include/asm/mpspec.h | |||
@@ -94,7 +94,7 @@ static inline void early_reserve_e820_mpc_new(void) { } | |||
94 | #define default_get_smp_config x86_init_uint_noop | 94 | #define default_get_smp_config x86_init_uint_noop |
95 | #endif | 95 | #endif |
96 | 96 | ||
97 | void generic_processor_info(int apicid, int version); | 97 | int generic_processor_info(int apicid, int version); |
98 | #ifdef CONFIG_ACPI | 98 | #ifdef CONFIG_ACPI |
99 | extern void mp_register_ioapic(int id, u32 address, u32 gsi_base); | 99 | extern void mp_register_ioapic(int id, u32 address, u32 gsi_base); |
100 | extern void mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, | 100 | extern void mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, |
diff --git a/arch/x86/include/asm/mrst.h b/arch/x86/include/asm/mrst.h deleted file mode 100644 index fc18bf3ce7c8..000000000000 --- a/arch/x86/include/asm/mrst.h +++ /dev/null | |||
@@ -1,81 +0,0 @@ | |||
1 | /* | ||
2 | * mrst.h: Intel Moorestown platform specific setup code | ||
3 | * | ||
4 | * (C) Copyright 2009 Intel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; version 2 | ||
9 | * of the License. | ||
10 | */ | ||
11 | #ifndef _ASM_X86_MRST_H | ||
12 | #define _ASM_X86_MRST_H | ||
13 | |||
14 | #include <linux/sfi.h> | ||
15 | |||
16 | extern int pci_mrst_init(void); | ||
17 | extern int __init sfi_parse_mrtc(struct sfi_table_header *table); | ||
18 | extern int sfi_mrtc_num; | ||
19 | extern struct sfi_rtc_table_entry sfi_mrtc_array[]; | ||
20 | |||
21 | /* | ||
22 | * Medfield is the follow-up of Moorestown, it combines two chip solution into | ||
23 | * one. Other than that it also added always-on and constant tsc and lapic | ||
24 | * timers. Medfield is the platform name, and the chip name is called Penwell | ||
25 | * we treat Medfield/Penwell as a variant of Moorestown. Penwell can be | ||
26 | * identified via MSRs. | ||
27 | */ | ||
28 | enum mrst_cpu_type { | ||
29 | /* 1 was Moorestown */ | ||
30 | MRST_CPU_CHIP_PENWELL = 2, | ||
31 | }; | ||
32 | |||
33 | extern enum mrst_cpu_type __mrst_cpu_chip; | ||
34 | |||
35 | #ifdef CONFIG_X86_INTEL_MID | ||
36 | |||
37 | static inline enum mrst_cpu_type mrst_identify_cpu(void) | ||
38 | { | ||
39 | return __mrst_cpu_chip; | ||
40 | } | ||
41 | |||
42 | #else /* !CONFIG_X86_INTEL_MID */ | ||
43 | |||
44 | #define mrst_identify_cpu() (0) | ||
45 | |||
46 | #endif /* !CONFIG_X86_INTEL_MID */ | ||
47 | |||
48 | enum mrst_timer_options { | ||
49 | MRST_TIMER_DEFAULT, | ||
50 | MRST_TIMER_APBT_ONLY, | ||
51 | MRST_TIMER_LAPIC_APBT, | ||
52 | }; | ||
53 | |||
54 | extern enum mrst_timer_options mrst_timer_options; | ||
55 | |||
56 | /* | ||
57 | * Penwell uses spread spectrum clock, so the freq number is not exactly | ||
58 | * the same as reported by MSR based on SDM. | ||
59 | */ | ||
60 | #define PENWELL_FSB_FREQ_83SKU 83200 | ||
61 | #define PENWELL_FSB_FREQ_100SKU 99840 | ||
62 | |||
63 | #define SFI_MTMR_MAX_NUM 8 | ||
64 | #define SFI_MRTC_MAX 8 | ||
65 | |||
66 | extern struct console early_mrst_console; | ||
67 | extern void mrst_early_console_init(void); | ||
68 | |||
69 | extern struct console early_hsu_console; | ||
70 | extern void hsu_early_console_init(const char *); | ||
71 | |||
72 | extern void intel_scu_devices_create(void); | ||
73 | extern void intel_scu_devices_destroy(void); | ||
74 | |||
75 | /* VRTC timer */ | ||
76 | #define MRST_VRTC_MAP_SZ (1024) | ||
77 | /*#define MRST_VRTC_PGOFFSET (0xc00) */ | ||
78 | |||
79 | extern void mrst_rtc_init(void); | ||
80 | |||
81 | #endif /* _ASM_X86_MRST_H */ | ||
diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h index cb7502852acb..e139b13f2a33 100644 --- a/arch/x86/include/asm/msr.h +++ b/arch/x86/include/asm/msr.h | |||
@@ -218,10 +218,14 @@ void msrs_free(struct msr *msrs); | |||
218 | #ifdef CONFIG_SMP | 218 | #ifdef CONFIG_SMP |
219 | int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); | 219 | int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); |
220 | int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); | 220 | int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); |
221 | int rdmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 *q); | ||
222 | int wrmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 q); | ||
221 | void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs); | 223 | void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs); |
222 | void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs); | 224 | void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs); |
223 | int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); | 225 | int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); |
224 | int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); | 226 | int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); |
227 | int rdmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 *q); | ||
228 | int wrmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 q); | ||
225 | int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]); | 229 | int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]); |
226 | int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]); | 230 | int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]); |
227 | #else /* CONFIG_SMP */ | 231 | #else /* CONFIG_SMP */ |
@@ -235,6 +239,16 @@ static inline int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) | |||
235 | wrmsr(msr_no, l, h); | 239 | wrmsr(msr_no, l, h); |
236 | return 0; | 240 | return 0; |
237 | } | 241 | } |
242 | static inline int rdmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 *q) | ||
243 | { | ||
244 | rdmsrl(msr_no, *q); | ||
245 | return 0; | ||
246 | } | ||
247 | static inline int wrmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 q) | ||
248 | { | ||
249 | wrmsrl(msr_no, q); | ||
250 | return 0; | ||
251 | } | ||
238 | static inline void rdmsr_on_cpus(const struct cpumask *m, u32 msr_no, | 252 | static inline void rdmsr_on_cpus(const struct cpumask *m, u32 msr_no, |
239 | struct msr *msrs) | 253 | struct msr *msrs) |
240 | { | 254 | { |
@@ -254,6 +268,14 @@ static inline int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) | |||
254 | { | 268 | { |
255 | return wrmsr_safe(msr_no, l, h); | 269 | return wrmsr_safe(msr_no, l, h); |
256 | } | 270 | } |
271 | static inline int rdmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 *q) | ||
272 | { | ||
273 | return rdmsrl_safe(msr_no, q); | ||
274 | } | ||
275 | static inline int wrmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 q) | ||
276 | { | ||
277 | return wrmsrl_safe(msr_no, q); | ||
278 | } | ||
257 | static inline int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]) | 279 | static inline int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]) |
258 | { | 280 | { |
259 | return rdmsr_safe_regs(regs); | 281 | return rdmsr_safe_regs(regs); |
diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h index 0da5200ee79d..94220d14d5cc 100644 --- a/arch/x86/include/asm/percpu.h +++ b/arch/x86/include/asm/percpu.h | |||
@@ -128,7 +128,8 @@ do { \ | |||
128 | do { \ | 128 | do { \ |
129 | typedef typeof(var) pao_T__; \ | 129 | typedef typeof(var) pao_T__; \ |
130 | const int pao_ID__ = (__builtin_constant_p(val) && \ | 130 | const int pao_ID__ = (__builtin_constant_p(val) && \ |
131 | ((val) == 1 || (val) == -1)) ? (val) : 0; \ | 131 | ((val) == 1 || (val) == -1)) ? \ |
132 | (int)(val) : 0; \ | ||
132 | if (0) { \ | 133 | if (0) { \ |
133 | pao_T__ pao_tmp__; \ | 134 | pao_T__ pao_tmp__; \ |
134 | pao_tmp__ = (val); \ | 135 | pao_tmp__ = (val); \ |
@@ -377,9 +378,6 @@ do { \ | |||
377 | #define __this_cpu_or_1(pcp, val) percpu_to_op("or", (pcp), val) | 378 | #define __this_cpu_or_1(pcp, val) percpu_to_op("or", (pcp), val) |
378 | #define __this_cpu_or_2(pcp, val) percpu_to_op("or", (pcp), val) | 379 | #define __this_cpu_or_2(pcp, val) percpu_to_op("or", (pcp), val) |
379 | #define __this_cpu_or_4(pcp, val) percpu_to_op("or", (pcp), val) | 380 | #define __this_cpu_or_4(pcp, val) percpu_to_op("or", (pcp), val) |
380 | #define __this_cpu_xor_1(pcp, val) percpu_to_op("xor", (pcp), val) | ||
381 | #define __this_cpu_xor_2(pcp, val) percpu_to_op("xor", (pcp), val) | ||
382 | #define __this_cpu_xor_4(pcp, val) percpu_to_op("xor", (pcp), val) | ||
383 | #define __this_cpu_xchg_1(pcp, val) percpu_xchg_op(pcp, val) | 381 | #define __this_cpu_xchg_1(pcp, val) percpu_xchg_op(pcp, val) |
384 | #define __this_cpu_xchg_2(pcp, val) percpu_xchg_op(pcp, val) | 382 | #define __this_cpu_xchg_2(pcp, val) percpu_xchg_op(pcp, val) |
385 | #define __this_cpu_xchg_4(pcp, val) percpu_xchg_op(pcp, val) | 383 | #define __this_cpu_xchg_4(pcp, val) percpu_xchg_op(pcp, val) |
@@ -399,9 +397,6 @@ do { \ | |||
399 | #define this_cpu_or_1(pcp, val) percpu_to_op("or", (pcp), val) | 397 | #define this_cpu_or_1(pcp, val) percpu_to_op("or", (pcp), val) |
400 | #define this_cpu_or_2(pcp, val) percpu_to_op("or", (pcp), val) | 398 | #define this_cpu_or_2(pcp, val) percpu_to_op("or", (pcp), val) |
401 | #define this_cpu_or_4(pcp, val) percpu_to_op("or", (pcp), val) | 399 | #define this_cpu_or_4(pcp, val) percpu_to_op("or", (pcp), val) |
402 | #define this_cpu_xor_1(pcp, val) percpu_to_op("xor", (pcp), val) | ||
403 | #define this_cpu_xor_2(pcp, val) percpu_to_op("xor", (pcp), val) | ||
404 | #define this_cpu_xor_4(pcp, val) percpu_to_op("xor", (pcp), val) | ||
405 | #define this_cpu_xchg_1(pcp, nval) percpu_xchg_op(pcp, nval) | 400 | #define this_cpu_xchg_1(pcp, nval) percpu_xchg_op(pcp, nval) |
406 | #define this_cpu_xchg_2(pcp, nval) percpu_xchg_op(pcp, nval) | 401 | #define this_cpu_xchg_2(pcp, nval) percpu_xchg_op(pcp, nval) |
407 | #define this_cpu_xchg_4(pcp, nval) percpu_xchg_op(pcp, nval) | 402 | #define this_cpu_xchg_4(pcp, nval) percpu_xchg_op(pcp, nval) |
@@ -446,7 +441,6 @@ do { \ | |||
446 | #define __this_cpu_add_8(pcp, val) percpu_add_op((pcp), val) | 441 | #define __this_cpu_add_8(pcp, val) percpu_add_op((pcp), val) |
447 | #define __this_cpu_and_8(pcp, val) percpu_to_op("and", (pcp), val) | 442 | #define __this_cpu_and_8(pcp, val) percpu_to_op("and", (pcp), val) |
448 | #define __this_cpu_or_8(pcp, val) percpu_to_op("or", (pcp), val) | 443 | #define __this_cpu_or_8(pcp, val) percpu_to_op("or", (pcp), val) |
449 | #define __this_cpu_xor_8(pcp, val) percpu_to_op("xor", (pcp), val) | ||
450 | #define __this_cpu_add_return_8(pcp, val) percpu_add_return_op(pcp, val) | 444 | #define __this_cpu_add_return_8(pcp, val) percpu_add_return_op(pcp, val) |
451 | #define __this_cpu_xchg_8(pcp, nval) percpu_xchg_op(pcp, nval) | 445 | #define __this_cpu_xchg_8(pcp, nval) percpu_xchg_op(pcp, nval) |
452 | #define __this_cpu_cmpxchg_8(pcp, oval, nval) percpu_cmpxchg_op(pcp, oval, nval) | 446 | #define __this_cpu_cmpxchg_8(pcp, oval, nval) percpu_cmpxchg_op(pcp, oval, nval) |
@@ -456,7 +450,6 @@ do { \ | |||
456 | #define this_cpu_add_8(pcp, val) percpu_add_op((pcp), val) | 450 | #define this_cpu_add_8(pcp, val) percpu_add_op((pcp), val) |
457 | #define this_cpu_and_8(pcp, val) percpu_to_op("and", (pcp), val) | 451 | #define this_cpu_and_8(pcp, val) percpu_to_op("and", (pcp), val) |
458 | #define this_cpu_or_8(pcp, val) percpu_to_op("or", (pcp), val) | 452 | #define this_cpu_or_8(pcp, val) percpu_to_op("or", (pcp), val) |
459 | #define this_cpu_xor_8(pcp, val) percpu_to_op("xor", (pcp), val) | ||
460 | #define this_cpu_add_return_8(pcp, val) percpu_add_return_op(pcp, val) | 453 | #define this_cpu_add_return_8(pcp, val) percpu_add_return_op(pcp, val) |
461 | #define this_cpu_xchg_8(pcp, nval) percpu_xchg_op(pcp, nval) | 454 | #define this_cpu_xchg_8(pcp, nval) percpu_xchg_op(pcp, nval) |
462 | #define this_cpu_cmpxchg_8(pcp, oval, nval) percpu_cmpxchg_op(pcp, oval, nval) | 455 | #define this_cpu_cmpxchg_8(pcp, oval, nval) percpu_cmpxchg_op(pcp, oval, nval) |
diff --git a/arch/x86/include/asm/pgalloc.h b/arch/x86/include/asm/pgalloc.h index b4389a468fb6..c4412e972bbd 100644 --- a/arch/x86/include/asm/pgalloc.h +++ b/arch/x86/include/asm/pgalloc.h | |||
@@ -80,12 +80,21 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, | |||
80 | #if PAGETABLE_LEVELS > 2 | 80 | #if PAGETABLE_LEVELS > 2 |
81 | static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) | 81 | static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) |
82 | { | 82 | { |
83 | return (pmd_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT); | 83 | struct page *page; |
84 | page = alloc_pages(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO, 0); | ||
85 | if (!page) | ||
86 | return NULL; | ||
87 | if (!pgtable_pmd_page_ctor(page)) { | ||
88 | __free_pages(page, 0); | ||
89 | return NULL; | ||
90 | } | ||
91 | return (pmd_t *)page_address(page); | ||
84 | } | 92 | } |
85 | 93 | ||
86 | static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) | 94 | static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) |
87 | { | 95 | { |
88 | BUG_ON((unsigned long)pmd & (PAGE_SIZE-1)); | 96 | BUG_ON((unsigned long)pmd & (PAGE_SIZE-1)); |
97 | pgtable_pmd_page_dtor(virt_to_page(pmd)); | ||
89 | free_page((unsigned long)pmd); | 98 | free_page((unsigned long)pmd); |
90 | } | 99 | } |
91 | 100 | ||
diff --git a/arch/x86/include/asm/preempt.h b/arch/x86/include/asm/preempt.h new file mode 100644 index 000000000000..8729723636fd --- /dev/null +++ b/arch/x86/include/asm/preempt.h | |||
@@ -0,0 +1,100 @@ | |||
1 | #ifndef __ASM_PREEMPT_H | ||
2 | #define __ASM_PREEMPT_H | ||
3 | |||
4 | #include <asm/rmwcc.h> | ||
5 | #include <asm/percpu.h> | ||
6 | #include <linux/thread_info.h> | ||
7 | |||
8 | DECLARE_PER_CPU(int, __preempt_count); | ||
9 | |||
10 | /* | ||
11 | * We mask the PREEMPT_NEED_RESCHED bit so as not to confuse all current users | ||
12 | * that think a non-zero value indicates we cannot preempt. | ||
13 | */ | ||
14 | static __always_inline int preempt_count(void) | ||
15 | { | ||
16 | return __this_cpu_read_4(__preempt_count) & ~PREEMPT_NEED_RESCHED; | ||
17 | } | ||
18 | |||
19 | static __always_inline void preempt_count_set(int pc) | ||
20 | { | ||
21 | __this_cpu_write_4(__preempt_count, pc); | ||
22 | } | ||
23 | |||
24 | /* | ||
25 | * must be macros to avoid header recursion hell | ||
26 | */ | ||
27 | #define task_preempt_count(p) \ | ||
28 | (task_thread_info(p)->saved_preempt_count & ~PREEMPT_NEED_RESCHED) | ||
29 | |||
30 | #define init_task_preempt_count(p) do { \ | ||
31 | task_thread_info(p)->saved_preempt_count = PREEMPT_DISABLED; \ | ||
32 | } while (0) | ||
33 | |||
34 | #define init_idle_preempt_count(p, cpu) do { \ | ||
35 | task_thread_info(p)->saved_preempt_count = PREEMPT_ENABLED; \ | ||
36 | per_cpu(__preempt_count, (cpu)) = PREEMPT_ENABLED; \ | ||
37 | } while (0) | ||
38 | |||
39 | /* | ||
40 | * We fold the NEED_RESCHED bit into the preempt count such that | ||
41 | * preempt_enable() can decrement and test for needing to reschedule with a | ||
42 | * single instruction. | ||
43 | * | ||
44 | * We invert the actual bit, so that when the decrement hits 0 we know we both | ||
45 | * need to resched (the bit is cleared) and can resched (no preempt count). | ||
46 | */ | ||
47 | |||
48 | static __always_inline void set_preempt_need_resched(void) | ||
49 | { | ||
50 | __this_cpu_and_4(__preempt_count, ~PREEMPT_NEED_RESCHED); | ||
51 | } | ||
52 | |||
53 | static __always_inline void clear_preempt_need_resched(void) | ||
54 | { | ||
55 | __this_cpu_or_4(__preempt_count, PREEMPT_NEED_RESCHED); | ||
56 | } | ||
57 | |||
58 | static __always_inline bool test_preempt_need_resched(void) | ||
59 | { | ||
60 | return !(__this_cpu_read_4(__preempt_count) & PREEMPT_NEED_RESCHED); | ||
61 | } | ||
62 | |||
63 | /* | ||
64 | * The various preempt_count add/sub methods | ||
65 | */ | ||
66 | |||
67 | static __always_inline void __preempt_count_add(int val) | ||
68 | { | ||
69 | __this_cpu_add_4(__preempt_count, val); | ||
70 | } | ||
71 | |||
72 | static __always_inline void __preempt_count_sub(int val) | ||
73 | { | ||
74 | __this_cpu_add_4(__preempt_count, -val); | ||
75 | } | ||
76 | |||
77 | static __always_inline bool __preempt_count_dec_and_test(void) | ||
78 | { | ||
79 | GEN_UNARY_RMWcc("decl", __preempt_count, __percpu_arg(0), "e"); | ||
80 | } | ||
81 | |||
82 | /* | ||
83 | * Returns true when we need to resched and can (barring IRQ state). | ||
84 | */ | ||
85 | static __always_inline bool should_resched(void) | ||
86 | { | ||
87 | return unlikely(!__this_cpu_read_4(__preempt_count)); | ||
88 | } | ||
89 | |||
90 | #ifdef CONFIG_PREEMPT | ||
91 | extern asmlinkage void ___preempt_schedule(void); | ||
92 | # define __preempt_schedule() asm ("call ___preempt_schedule") | ||
93 | extern asmlinkage void preempt_schedule(void); | ||
94 | # ifdef CONFIG_CONTEXT_TRACKING | ||
95 | extern asmlinkage void ___preempt_schedule_context(void); | ||
96 | # define __preempt_schedule_context() asm ("call ___preempt_schedule_context") | ||
97 | # endif | ||
98 | #endif | ||
99 | |||
100 | #endif /* __ASM_PREEMPT_H */ | ||
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 987c75ecc334..7b034a4057f9 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h | |||
@@ -488,6 +488,15 @@ struct thread_struct { | |||
488 | unsigned long iopl; | 488 | unsigned long iopl; |
489 | /* Max allowed port in the bitmap, in bytes: */ | 489 | /* Max allowed port in the bitmap, in bytes: */ |
490 | unsigned io_bitmap_max; | 490 | unsigned io_bitmap_max; |
491 | /* | ||
492 | * fpu_counter contains the number of consecutive context switches | ||
493 | * that the FPU is used. If this is over a threshold, the lazy fpu | ||
494 | * saving becomes unlazy to save the trap. This is an unsigned char | ||
495 | * so that after 256 times the counter wraps and the behavior turns | ||
496 | * lazy again; this to deal with bursty apps that only use FPU for | ||
497 | * a short time | ||
498 | */ | ||
499 | unsigned char fpu_counter; | ||
491 | }; | 500 | }; |
492 | 501 | ||
493 | /* | 502 | /* |
diff --git a/arch/x86/include/asm/prom.h b/arch/x86/include/asm/prom.h index bade6ac3b14f..fbeb06ed0eaa 100644 --- a/arch/x86/include/asm/prom.h +++ b/arch/x86/include/asm/prom.h | |||
@@ -39,10 +39,5 @@ static inline void x86_dtb_init(void) { } | |||
39 | 39 | ||
40 | extern char cmd_line[COMMAND_LINE_SIZE]; | 40 | extern char cmd_line[COMMAND_LINE_SIZE]; |
41 | 41 | ||
42 | #define pci_address_to_pio pci_address_to_pio | ||
43 | unsigned long pci_address_to_pio(phys_addr_t addr); | ||
44 | |||
45 | #define HAVE_ARCH_DEVTREE_FIXUPS | ||
46 | |||
47 | #endif /* __ASSEMBLY__ */ | 42 | #endif /* __ASSEMBLY__ */ |
48 | #endif | 43 | #endif |
diff --git a/arch/x86/include/asm/rmwcc.h b/arch/x86/include/asm/rmwcc.h new file mode 100644 index 000000000000..1ff990f1de8e --- /dev/null +++ b/arch/x86/include/asm/rmwcc.h | |||
@@ -0,0 +1,41 @@ | |||
1 | #ifndef _ASM_X86_RMWcc | ||
2 | #define _ASM_X86_RMWcc | ||
3 | |||
4 | #ifdef CC_HAVE_ASM_GOTO | ||
5 | |||
6 | #define __GEN_RMWcc(fullop, var, cc, ...) \ | ||
7 | do { \ | ||
8 | asm_volatile_goto (fullop "; j" cc " %l[cc_label]" \ | ||
9 | : : "m" (var), ## __VA_ARGS__ \ | ||
10 | : "memory" : cc_label); \ | ||
11 | return 0; \ | ||
12 | cc_label: \ | ||
13 | return 1; \ | ||
14 | } while (0) | ||
15 | |||
16 | #define GEN_UNARY_RMWcc(op, var, arg0, cc) \ | ||
17 | __GEN_RMWcc(op " " arg0, var, cc) | ||
18 | |||
19 | #define GEN_BINARY_RMWcc(op, var, val, arg0, cc) \ | ||
20 | __GEN_RMWcc(op " %1, " arg0, var, cc, "er" (val)) | ||
21 | |||
22 | #else /* !CC_HAVE_ASM_GOTO */ | ||
23 | |||
24 | #define __GEN_RMWcc(fullop, var, cc, ...) \ | ||
25 | do { \ | ||
26 | char c; \ | ||
27 | asm volatile (fullop "; set" cc " %1" \ | ||
28 | : "+m" (var), "=qm" (c) \ | ||
29 | : __VA_ARGS__ : "memory"); \ | ||
30 | return c != 0; \ | ||
31 | } while (0) | ||
32 | |||
33 | #define GEN_UNARY_RMWcc(op, var, arg0, cc) \ | ||
34 | __GEN_RMWcc(op " " arg0, var, cc) | ||
35 | |||
36 | #define GEN_BINARY_RMWcc(op, var, val, arg0, cc) \ | ||
37 | __GEN_RMWcc(op " %2, " arg0, var, cc, "er" (val)) | ||
38 | |||
39 | #endif /* CC_HAVE_ASM_GOTO */ | ||
40 | |||
41 | #endif /* _ASM_X86_RMWcc */ | ||
diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h index c48a95035a77..6f1c3a8a33ab 100644 --- a/arch/x86/include/asm/segment.h +++ b/arch/x86/include/asm/segment.h | |||
@@ -214,6 +214,9 @@ | |||
214 | #ifdef __KERNEL__ | 214 | #ifdef __KERNEL__ |
215 | #ifndef __ASSEMBLY__ | 215 | #ifndef __ASSEMBLY__ |
216 | extern const char early_idt_handlers[NUM_EXCEPTION_VECTORS][2+2+5]; | 216 | extern const char early_idt_handlers[NUM_EXCEPTION_VECTORS][2+2+5]; |
217 | #ifdef CONFIG_TRACING | ||
218 | #define trace_early_idt_handlers early_idt_handlers | ||
219 | #endif | ||
217 | 220 | ||
218 | /* | 221 | /* |
219 | * Load a segment. Fall back on loading the zero | 222 | * Load a segment. Fall back on loading the zero |
diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h index 347555492dad..59bcf4e22418 100644 --- a/arch/x86/include/asm/setup.h +++ b/arch/x86/include/asm/setup.h | |||
@@ -51,9 +51,9 @@ extern void i386_reserve_resources(void); | |||
51 | extern void setup_default_timer_irq(void); | 51 | extern void setup_default_timer_irq(void); |
52 | 52 | ||
53 | #ifdef CONFIG_X86_INTEL_MID | 53 | #ifdef CONFIG_X86_INTEL_MID |
54 | extern void x86_mrst_early_setup(void); | 54 | extern void x86_intel_mid_early_setup(void); |
55 | #else | 55 | #else |
56 | static inline void x86_mrst_early_setup(void) { } | 56 | static inline void x86_intel_mid_early_setup(void) { } |
57 | #endif | 57 | #endif |
58 | 58 | ||
59 | #ifdef CONFIG_X86_INTEL_CE | 59 | #ifdef CONFIG_X86_INTEL_CE |
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index 27811190cbd7..c46a46be1ec6 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h | |||
@@ -28,8 +28,7 @@ struct thread_info { | |||
28 | __u32 flags; /* low level flags */ | 28 | __u32 flags; /* low level flags */ |
29 | __u32 status; /* thread synchronous flags */ | 29 | __u32 status; /* thread synchronous flags */ |
30 | __u32 cpu; /* current CPU */ | 30 | __u32 cpu; /* current CPU */ |
31 | int preempt_count; /* 0 => preemptable, | 31 | int saved_preempt_count; |
32 | <0 => BUG */ | ||
33 | mm_segment_t addr_limit; | 32 | mm_segment_t addr_limit; |
34 | struct restart_block restart_block; | 33 | struct restart_block restart_block; |
35 | void __user *sysenter_return; | 34 | void __user *sysenter_return; |
@@ -49,7 +48,7 @@ struct thread_info { | |||
49 | .exec_domain = &default_exec_domain, \ | 48 | .exec_domain = &default_exec_domain, \ |
50 | .flags = 0, \ | 49 | .flags = 0, \ |
51 | .cpu = 0, \ | 50 | .cpu = 0, \ |
52 | .preempt_count = INIT_PREEMPT_COUNT, \ | 51 | .saved_preempt_count = INIT_PREEMPT_COUNT, \ |
53 | .addr_limit = KERNEL_DS, \ | 52 | .addr_limit = KERNEL_DS, \ |
54 | .restart_block = { \ | 53 | .restart_block = { \ |
55 | .fn = do_no_restart_syscall, \ | 54 | .fn = do_no_restart_syscall, \ |
diff --git a/arch/x86/include/asm/trace/exceptions.h b/arch/x86/include/asm/trace/exceptions.h new file mode 100644 index 000000000000..2fbc66c7885b --- /dev/null +++ b/arch/x86/include/asm/trace/exceptions.h | |||
@@ -0,0 +1,52 @@ | |||
1 | #undef TRACE_SYSTEM | ||
2 | #define TRACE_SYSTEM exceptions | ||
3 | |||
4 | #if !defined(_TRACE_PAGE_FAULT_H) || defined(TRACE_HEADER_MULTI_READ) | ||
5 | #define _TRACE_PAGE_FAULT_H | ||
6 | |||
7 | #include <linux/tracepoint.h> | ||
8 | |||
9 | extern void trace_irq_vector_regfunc(void); | ||
10 | extern void trace_irq_vector_unregfunc(void); | ||
11 | |||
12 | DECLARE_EVENT_CLASS(x86_exceptions, | ||
13 | |||
14 | TP_PROTO(unsigned long address, struct pt_regs *regs, | ||
15 | unsigned long error_code), | ||
16 | |||
17 | TP_ARGS(address, regs, error_code), | ||
18 | |||
19 | TP_STRUCT__entry( | ||
20 | __field( unsigned long, address ) | ||
21 | __field( unsigned long, ip ) | ||
22 | __field( unsigned long, error_code ) | ||
23 | ), | ||
24 | |||
25 | TP_fast_assign( | ||
26 | __entry->address = address; | ||
27 | __entry->ip = regs->ip; | ||
28 | __entry->error_code = error_code; | ||
29 | ), | ||
30 | |||
31 | TP_printk("address=%pf ip=%pf error_code=0x%lx", | ||
32 | (void *)__entry->address, (void *)__entry->ip, | ||
33 | __entry->error_code) ); | ||
34 | |||
35 | #define DEFINE_PAGE_FAULT_EVENT(name) \ | ||
36 | DEFINE_EVENT_FN(x86_exceptions, name, \ | ||
37 | TP_PROTO(unsigned long address, struct pt_regs *regs, \ | ||
38 | unsigned long error_code), \ | ||
39 | TP_ARGS(address, regs, error_code), \ | ||
40 | trace_irq_vector_regfunc, \ | ||
41 | trace_irq_vector_unregfunc); | ||
42 | |||
43 | DEFINE_PAGE_FAULT_EVENT(page_fault_user); | ||
44 | DEFINE_PAGE_FAULT_EVENT(page_fault_kernel); | ||
45 | |||
46 | #undef TRACE_INCLUDE_PATH | ||
47 | #define TRACE_INCLUDE_PATH . | ||
48 | #define TRACE_INCLUDE_FILE exceptions | ||
49 | #endif /* _TRACE_PAGE_FAULT_H */ | ||
50 | |||
51 | /* This part must be outside protection */ | ||
52 | #include <trace/define_trace.h> | ||
diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h index 7036cb60cd87..58d66fe06b61 100644 --- a/arch/x86/include/asm/traps.h +++ b/arch/x86/include/asm/traps.h | |||
@@ -37,6 +37,23 @@ asmlinkage void machine_check(void); | |||
37 | #endif /* CONFIG_X86_MCE */ | 37 | #endif /* CONFIG_X86_MCE */ |
38 | asmlinkage void simd_coprocessor_error(void); | 38 | asmlinkage void simd_coprocessor_error(void); |
39 | 39 | ||
40 | #ifdef CONFIG_TRACING | ||
41 | asmlinkage void trace_page_fault(void); | ||
42 | #define trace_divide_error divide_error | ||
43 | #define trace_bounds bounds | ||
44 | #define trace_invalid_op invalid_op | ||
45 | #define trace_device_not_available device_not_available | ||
46 | #define trace_coprocessor_segment_overrun coprocessor_segment_overrun | ||
47 | #define trace_invalid_TSS invalid_TSS | ||
48 | #define trace_segment_not_present segment_not_present | ||
49 | #define trace_general_protection general_protection | ||
50 | #define trace_spurious_interrupt_bug spurious_interrupt_bug | ||
51 | #define trace_coprocessor_error coprocessor_error | ||
52 | #define trace_alignment_check alignment_check | ||
53 | #define trace_simd_coprocessor_error simd_coprocessor_error | ||
54 | #define trace_async_page_fault async_page_fault | ||
55 | #endif | ||
56 | |||
40 | dotraplinkage void do_divide_error(struct pt_regs *, long); | 57 | dotraplinkage void do_divide_error(struct pt_regs *, long); |
41 | dotraplinkage void do_debug(struct pt_regs *, long); | 58 | dotraplinkage void do_debug(struct pt_regs *, long); |
42 | dotraplinkage void do_nmi(struct pt_regs *, long); | 59 | dotraplinkage void do_nmi(struct pt_regs *, long); |
@@ -55,6 +72,9 @@ asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *); | |||
55 | #endif | 72 | #endif |
56 | dotraplinkage void do_general_protection(struct pt_regs *, long); | 73 | dotraplinkage void do_general_protection(struct pt_regs *, long); |
57 | dotraplinkage void do_page_fault(struct pt_regs *, unsigned long); | 74 | dotraplinkage void do_page_fault(struct pt_regs *, unsigned long); |
75 | #ifdef CONFIG_TRACING | ||
76 | dotraplinkage void trace_do_page_fault(struct pt_regs *, unsigned long); | ||
77 | #endif | ||
58 | dotraplinkage void do_spurious_interrupt_bug(struct pt_regs *, long); | 78 | dotraplinkage void do_spurious_interrupt_bug(struct pt_regs *, long); |
59 | dotraplinkage void do_coprocessor_error(struct pt_regs *, long); | 79 | dotraplinkage void do_coprocessor_error(struct pt_regs *, long); |
60 | dotraplinkage void do_alignment_check(struct pt_regs *, long); | 80 | dotraplinkage void do_alignment_check(struct pt_regs *, long); |
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index 5838fa911aa0..8ec57c07b125 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h | |||
@@ -542,5 +542,103 @@ extern struct movsl_mask { | |||
542 | # include <asm/uaccess_64.h> | 542 | # include <asm/uaccess_64.h> |
543 | #endif | 543 | #endif |
544 | 544 | ||
545 | unsigned long __must_check _copy_from_user(void *to, const void __user *from, | ||
546 | unsigned n); | ||
547 | unsigned long __must_check _copy_to_user(void __user *to, const void *from, | ||
548 | unsigned n); | ||
549 | |||
550 | #ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS | ||
551 | # define copy_user_diag __compiletime_error | ||
552 | #else | ||
553 | # define copy_user_diag __compiletime_warning | ||
554 | #endif | ||
555 | |||
556 | extern void copy_user_diag("copy_from_user() buffer size is too small") | ||
557 | copy_from_user_overflow(void); | ||
558 | extern void copy_user_diag("copy_to_user() buffer size is too small") | ||
559 | copy_to_user_overflow(void) __asm__("copy_from_user_overflow"); | ||
560 | |||
561 | #undef copy_user_diag | ||
562 | |||
563 | #ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS | ||
564 | |||
565 | extern void | ||
566 | __compiletime_warning("copy_from_user() buffer size is not provably correct") | ||
567 | __copy_from_user_overflow(void) __asm__("copy_from_user_overflow"); | ||
568 | #define __copy_from_user_overflow(size, count) __copy_from_user_overflow() | ||
569 | |||
570 | extern void | ||
571 | __compiletime_warning("copy_to_user() buffer size is not provably correct") | ||
572 | __copy_to_user_overflow(void) __asm__("copy_from_user_overflow"); | ||
573 | #define __copy_to_user_overflow(size, count) __copy_to_user_overflow() | ||
574 | |||
575 | #else | ||
576 | |||
577 | static inline void | ||
578 | __copy_from_user_overflow(int size, unsigned long count) | ||
579 | { | ||
580 | WARN(1, "Buffer overflow detected (%d < %lu)!\n", size, count); | ||
581 | } | ||
582 | |||
583 | #define __copy_to_user_overflow __copy_from_user_overflow | ||
584 | |||
585 | #endif | ||
586 | |||
587 | static inline unsigned long __must_check | ||
588 | copy_from_user(void *to, const void __user *from, unsigned long n) | ||
589 | { | ||
590 | int sz = __compiletime_object_size(to); | ||
591 | |||
592 | might_fault(); | ||
593 | |||
594 | /* | ||
595 | * While we would like to have the compiler do the checking for us | ||
596 | * even in the non-constant size case, any false positives there are | ||
597 | * a problem (especially when DEBUG_STRICT_USER_COPY_CHECKS, but even | ||
598 | * without - the [hopefully] dangerous looking nature of the warning | ||
599 | * would make people go look at the respecitive call sites over and | ||
600 | * over again just to find that there's no problem). | ||
601 | * | ||
602 | * And there are cases where it's just not realistic for the compiler | ||
603 | * to prove the count to be in range. For example when multiple call | ||
604 | * sites of a helper function - perhaps in different source files - | ||
605 | * all doing proper range checking, yet the helper function not doing | ||
606 | * so again. | ||
607 | * | ||
608 | * Therefore limit the compile time checking to the constant size | ||
609 | * case, and do only runtime checking for non-constant sizes. | ||
610 | */ | ||
611 | |||
612 | if (likely(sz < 0 || sz >= n)) | ||
613 | n = _copy_from_user(to, from, n); | ||
614 | else if(__builtin_constant_p(n)) | ||
615 | copy_from_user_overflow(); | ||
616 | else | ||
617 | __copy_from_user_overflow(sz, n); | ||
618 | |||
619 | return n; | ||
620 | } | ||
621 | |||
622 | static inline unsigned long __must_check | ||
623 | copy_to_user(void __user *to, const void *from, unsigned long n) | ||
624 | { | ||
625 | int sz = __compiletime_object_size(from); | ||
626 | |||
627 | might_fault(); | ||
628 | |||
629 | /* See the comment in copy_from_user() above. */ | ||
630 | if (likely(sz < 0 || sz >= n)) | ||
631 | n = _copy_to_user(to, from, n); | ||
632 | else if(__builtin_constant_p(n)) | ||
633 | copy_to_user_overflow(); | ||
634 | else | ||
635 | __copy_to_user_overflow(sz, n); | ||
636 | |||
637 | return n; | ||
638 | } | ||
639 | |||
640 | #undef __copy_from_user_overflow | ||
641 | #undef __copy_to_user_overflow | ||
642 | |||
545 | #endif /* _ASM_X86_UACCESS_H */ | 643 | #endif /* _ASM_X86_UACCESS_H */ |
546 | 644 | ||
diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h index 7f760a9f1f61..3c03a5de64d3 100644 --- a/arch/x86/include/asm/uaccess_32.h +++ b/arch/x86/include/asm/uaccess_32.h | |||
@@ -184,33 +184,4 @@ __copy_from_user_inatomic_nocache(void *to, const void __user *from, | |||
184 | return __copy_from_user_ll_nocache_nozero(to, from, n); | 184 | return __copy_from_user_ll_nocache_nozero(to, from, n); |
185 | } | 185 | } |
186 | 186 | ||
187 | unsigned long __must_check copy_to_user(void __user *to, | ||
188 | const void *from, unsigned long n); | ||
189 | unsigned long __must_check _copy_from_user(void *to, | ||
190 | const void __user *from, | ||
191 | unsigned long n); | ||
192 | |||
193 | |||
194 | extern void copy_from_user_overflow(void) | ||
195 | #ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS | ||
196 | __compiletime_error("copy_from_user() buffer size is not provably correct") | ||
197 | #else | ||
198 | __compiletime_warning("copy_from_user() buffer size is not provably correct") | ||
199 | #endif | ||
200 | ; | ||
201 | |||
202 | static inline unsigned long __must_check copy_from_user(void *to, | ||
203 | const void __user *from, | ||
204 | unsigned long n) | ||
205 | { | ||
206 | int sz = __compiletime_object_size(to); | ||
207 | |||
208 | if (likely(sz == -1 || sz >= n)) | ||
209 | n = _copy_from_user(to, from, n); | ||
210 | else | ||
211 | copy_from_user_overflow(); | ||
212 | |||
213 | return n; | ||
214 | } | ||
215 | |||
216 | #endif /* _ASM_X86_UACCESS_32_H */ | 187 | #endif /* _ASM_X86_UACCESS_32_H */ |
diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h index 4f7923dd0007..190413d0de57 100644 --- a/arch/x86/include/asm/uaccess_64.h +++ b/arch/x86/include/asm/uaccess_64.h | |||
@@ -46,42 +46,13 @@ copy_user_generic(void *to, const void *from, unsigned len) | |||
46 | } | 46 | } |
47 | 47 | ||
48 | __must_check unsigned long | 48 | __must_check unsigned long |
49 | _copy_to_user(void __user *to, const void *from, unsigned len); | ||
50 | __must_check unsigned long | ||
51 | _copy_from_user(void *to, const void __user *from, unsigned len); | ||
52 | __must_check unsigned long | ||
53 | copy_in_user(void __user *to, const void __user *from, unsigned len); | 49 | copy_in_user(void __user *to, const void __user *from, unsigned len); |
54 | 50 | ||
55 | static inline unsigned long __must_check copy_from_user(void *to, | ||
56 | const void __user *from, | ||
57 | unsigned long n) | ||
58 | { | ||
59 | int sz = __compiletime_object_size(to); | ||
60 | |||
61 | might_fault(); | ||
62 | if (likely(sz == -1 || sz >= n)) | ||
63 | n = _copy_from_user(to, from, n); | ||
64 | #ifdef CONFIG_DEBUG_VM | ||
65 | else | ||
66 | WARN(1, "Buffer overflow detected!\n"); | ||
67 | #endif | ||
68 | return n; | ||
69 | } | ||
70 | |||
71 | static __always_inline __must_check | 51 | static __always_inline __must_check |
72 | int copy_to_user(void __user *dst, const void *src, unsigned size) | 52 | int __copy_from_user_nocheck(void *dst, const void __user *src, unsigned size) |
73 | { | ||
74 | might_fault(); | ||
75 | |||
76 | return _copy_to_user(dst, src, size); | ||
77 | } | ||
78 | |||
79 | static __always_inline __must_check | ||
80 | int __copy_from_user(void *dst, const void __user *src, unsigned size) | ||
81 | { | 53 | { |
82 | int ret = 0; | 54 | int ret = 0; |
83 | 55 | ||
84 | might_fault(); | ||
85 | if (!__builtin_constant_p(size)) | 56 | if (!__builtin_constant_p(size)) |
86 | return copy_user_generic(dst, (__force void *)src, size); | 57 | return copy_user_generic(dst, (__force void *)src, size); |
87 | switch (size) { | 58 | switch (size) { |
@@ -121,11 +92,17 @@ int __copy_from_user(void *dst, const void __user *src, unsigned size) | |||
121 | } | 92 | } |
122 | 93 | ||
123 | static __always_inline __must_check | 94 | static __always_inline __must_check |
124 | int __copy_to_user(void __user *dst, const void *src, unsigned size) | 95 | int __copy_from_user(void *dst, const void __user *src, unsigned size) |
96 | { | ||
97 | might_fault(); | ||
98 | return __copy_from_user_nocheck(dst, src, size); | ||
99 | } | ||
100 | |||
101 | static __always_inline __must_check | ||
102 | int __copy_to_user_nocheck(void __user *dst, const void *src, unsigned size) | ||
125 | { | 103 | { |
126 | int ret = 0; | 104 | int ret = 0; |
127 | 105 | ||
128 | might_fault(); | ||
129 | if (!__builtin_constant_p(size)) | 106 | if (!__builtin_constant_p(size)) |
130 | return copy_user_generic((__force void *)dst, src, size); | 107 | return copy_user_generic((__force void *)dst, src, size); |
131 | switch (size) { | 108 | switch (size) { |
@@ -165,6 +142,13 @@ int __copy_to_user(void __user *dst, const void *src, unsigned size) | |||
165 | } | 142 | } |
166 | 143 | ||
167 | static __always_inline __must_check | 144 | static __always_inline __must_check |
145 | int __copy_to_user(void __user *dst, const void *src, unsigned size) | ||
146 | { | ||
147 | might_fault(); | ||
148 | return __copy_to_user_nocheck(dst, src, size); | ||
149 | } | ||
150 | |||
151 | static __always_inline __must_check | ||
168 | int __copy_in_user(void __user *dst, const void __user *src, unsigned size) | 152 | int __copy_in_user(void __user *dst, const void __user *src, unsigned size) |
169 | { | 153 | { |
170 | int ret = 0; | 154 | int ret = 0; |
@@ -220,13 +204,13 @@ int __copy_in_user(void __user *dst, const void __user *src, unsigned size) | |||
220 | static __must_check __always_inline int | 204 | static __must_check __always_inline int |
221 | __copy_from_user_inatomic(void *dst, const void __user *src, unsigned size) | 205 | __copy_from_user_inatomic(void *dst, const void __user *src, unsigned size) |
222 | { | 206 | { |
223 | return copy_user_generic(dst, (__force const void *)src, size); | 207 | return __copy_from_user_nocheck(dst, (__force const void *)src, size); |
224 | } | 208 | } |
225 | 209 | ||
226 | static __must_check __always_inline int | 210 | static __must_check __always_inline int |
227 | __copy_to_user_inatomic(void __user *dst, const void *src, unsigned size) | 211 | __copy_to_user_inatomic(void __user *dst, const void *src, unsigned size) |
228 | { | 212 | { |
229 | return copy_user_generic((__force void *)dst, src, size); | 213 | return __copy_to_user_nocheck((__force void *)dst, src, size); |
230 | } | 214 | } |
231 | 215 | ||
232 | extern long __copy_user_nocache(void *dst, const void __user *src, | 216 | extern long __copy_user_nocache(void *dst, const void __user *src, |
diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h index 6e5197910fd8..3087ea9c5f2e 100644 --- a/arch/x86/include/asm/uprobes.h +++ b/arch/x86/include/asm/uprobes.h | |||
@@ -35,7 +35,10 @@ typedef u8 uprobe_opcode_t; | |||
35 | 35 | ||
36 | struct arch_uprobe { | 36 | struct arch_uprobe { |
37 | u16 fixups; | 37 | u16 fixups; |
38 | u8 insn[MAX_UINSN_BYTES]; | 38 | union { |
39 | u8 insn[MAX_UINSN_BYTES]; | ||
40 | u8 ixol[MAX_UINSN_BYTES]; | ||
41 | }; | ||
39 | #ifdef CONFIG_X86_64 | 42 | #ifdef CONFIG_X86_64 |
40 | unsigned long rip_rela_target_address; | 43 | unsigned long rip_rela_target_address; |
41 | #endif | 44 | #endif |
@@ -49,11 +52,4 @@ struct arch_uprobe_task { | |||
49 | unsigned int saved_tf; | 52 | unsigned int saved_tf; |
50 | }; | 53 | }; |
51 | 54 | ||
52 | extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr); | ||
53 | extern int arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs); | ||
54 | extern int arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs); | ||
55 | extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk); | ||
56 | extern int arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data); | ||
57 | extern void arch_uprobe_abort_xol(struct arch_uprobe *aup, struct pt_regs *regs); | ||
58 | extern unsigned long arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs *regs); | ||
59 | #endif /* _ASM_UPROBES_H */ | 55 | #endif /* _ASM_UPROBES_H */ |
diff --git a/arch/x86/include/asm/uv/uv.h b/arch/x86/include/asm/uv/uv.h index 062921ef34e9..6b964a0b86d1 100644 --- a/arch/x86/include/asm/uv/uv.h +++ b/arch/x86/include/asm/uv/uv.h | |||
@@ -12,6 +12,7 @@ extern enum uv_system_type get_uv_system_type(void); | |||
12 | extern int is_uv_system(void); | 12 | extern int is_uv_system(void); |
13 | extern void uv_cpu_init(void); | 13 | extern void uv_cpu_init(void); |
14 | extern void uv_nmi_init(void); | 14 | extern void uv_nmi_init(void); |
15 | extern void uv_register_nmi_notifier(void); | ||
15 | extern void uv_system_init(void); | 16 | extern void uv_system_init(void); |
16 | extern const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, | 17 | extern const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, |
17 | struct mm_struct *mm, | 18 | struct mm_struct *mm, |
@@ -25,6 +26,7 @@ static inline enum uv_system_type get_uv_system_type(void) { return UV_NONE; } | |||
25 | static inline int is_uv_system(void) { return 0; } | 26 | static inline int is_uv_system(void) { return 0; } |
26 | static inline void uv_cpu_init(void) { } | 27 | static inline void uv_cpu_init(void) { } |
27 | static inline void uv_system_init(void) { } | 28 | static inline void uv_system_init(void) { } |
29 | static inline void uv_register_nmi_notifier(void) { } | ||
28 | static inline const struct cpumask * | 30 | static inline const struct cpumask * |
29 | uv_flush_tlb_others(const struct cpumask *cpumask, struct mm_struct *mm, | 31 | uv_flush_tlb_others(const struct cpumask *cpumask, struct mm_struct *mm, |
30 | unsigned long start, unsigned long end, unsigned int cpu) | 32 | unsigned long start, unsigned long end, unsigned int cpu) |
diff --git a/arch/x86/include/asm/uv/uv_hub.h b/arch/x86/include/asm/uv/uv_hub.h index 2c32df95bb78..a30836c8ac4d 100644 --- a/arch/x86/include/asm/uv/uv_hub.h +++ b/arch/x86/include/asm/uv/uv_hub.h | |||
@@ -502,8 +502,8 @@ struct uv_blade_info { | |||
502 | unsigned short nr_online_cpus; | 502 | unsigned short nr_online_cpus; |
503 | unsigned short pnode; | 503 | unsigned short pnode; |
504 | short memory_nid; | 504 | short memory_nid; |
505 | spinlock_t nmi_lock; | 505 | spinlock_t nmi_lock; /* obsolete, see uv_hub_nmi */ |
506 | unsigned long nmi_count; | 506 | unsigned long nmi_count; /* obsolete, see uv_hub_nmi */ |
507 | }; | 507 | }; |
508 | extern struct uv_blade_info *uv_blade_info; | 508 | extern struct uv_blade_info *uv_blade_info; |
509 | extern short *uv_node_to_blade; | 509 | extern short *uv_node_to_blade; |
@@ -576,6 +576,59 @@ static inline int uv_num_possible_blades(void) | |||
576 | return uv_possible_blades; | 576 | return uv_possible_blades; |
577 | } | 577 | } |
578 | 578 | ||
579 | /* Per Hub NMI support */ | ||
580 | extern void uv_nmi_setup(void); | ||
581 | |||
582 | /* BMC sets a bit this MMR non-zero before sending an NMI */ | ||
583 | #define UVH_NMI_MMR UVH_SCRATCH5 | ||
584 | #define UVH_NMI_MMR_CLEAR UVH_SCRATCH5_ALIAS | ||
585 | #define UVH_NMI_MMR_SHIFT 63 | ||
586 | #define UVH_NMI_MMR_TYPE "SCRATCH5" | ||
587 | |||
588 | /* Newer SMM NMI handler, not present in all systems */ | ||
589 | #define UVH_NMI_MMRX UVH_EVENT_OCCURRED0 | ||
590 | #define UVH_NMI_MMRX_CLEAR UVH_EVENT_OCCURRED0_ALIAS | ||
591 | #define UVH_NMI_MMRX_SHIFT (is_uv1_hub() ? \ | ||
592 | UV1H_EVENT_OCCURRED0_EXTIO_INT0_SHFT :\ | ||
593 | UVXH_EVENT_OCCURRED0_EXTIO_INT0_SHFT) | ||
594 | #define UVH_NMI_MMRX_TYPE "EXTIO_INT0" | ||
595 | |||
596 | /* Non-zero indicates newer SMM NMI handler present */ | ||
597 | #define UVH_NMI_MMRX_SUPPORTED UVH_EXTIO_INT0_BROADCAST | ||
598 | |||
599 | /* Indicates to BIOS that we want to use the newer SMM NMI handler */ | ||
600 | #define UVH_NMI_MMRX_REQ UVH_SCRATCH5_ALIAS_2 | ||
601 | #define UVH_NMI_MMRX_REQ_SHIFT 62 | ||
602 | |||
603 | struct uv_hub_nmi_s { | ||
604 | raw_spinlock_t nmi_lock; | ||
605 | atomic_t in_nmi; /* flag this node in UV NMI IRQ */ | ||
606 | atomic_t cpu_owner; /* last locker of this struct */ | ||
607 | atomic_t read_mmr_count; /* count of MMR reads */ | ||
608 | atomic_t nmi_count; /* count of true UV NMIs */ | ||
609 | unsigned long nmi_value; /* last value read from NMI MMR */ | ||
610 | }; | ||
611 | |||
612 | struct uv_cpu_nmi_s { | ||
613 | struct uv_hub_nmi_s *hub; | ||
614 | atomic_t state; | ||
615 | atomic_t pinging; | ||
616 | int queries; | ||
617 | int pings; | ||
618 | }; | ||
619 | |||
620 | DECLARE_PER_CPU(struct uv_cpu_nmi_s, __uv_cpu_nmi); | ||
621 | #define uv_cpu_nmi (__get_cpu_var(__uv_cpu_nmi)) | ||
622 | #define uv_hub_nmi (uv_cpu_nmi.hub) | ||
623 | #define uv_cpu_nmi_per(cpu) (per_cpu(__uv_cpu_nmi, cpu)) | ||
624 | #define uv_hub_nmi_per(cpu) (uv_cpu_nmi_per(cpu).hub) | ||
625 | |||
626 | /* uv_cpu_nmi_states */ | ||
627 | #define UV_NMI_STATE_OUT 0 | ||
628 | #define UV_NMI_STATE_IN 1 | ||
629 | #define UV_NMI_STATE_DUMP 2 | ||
630 | #define UV_NMI_STATE_DUMP_DONE 3 | ||
631 | |||
579 | /* Update SCIR state */ | 632 | /* Update SCIR state */ |
580 | static inline void uv_set_scir_bits(unsigned char value) | 633 | static inline void uv_set_scir_bits(unsigned char value) |
581 | { | 634 | { |
diff --git a/arch/x86/include/asm/uv/uv_mmrs.h b/arch/x86/include/asm/uv/uv_mmrs.h index bd5f80e58a23..e42249bcf7e1 100644 --- a/arch/x86/include/asm/uv/uv_mmrs.h +++ b/arch/x86/include/asm/uv/uv_mmrs.h | |||
@@ -461,6 +461,23 @@ union uvh_event_occurred0_u { | |||
461 | 461 | ||
462 | 462 | ||
463 | /* ========================================================================= */ | 463 | /* ========================================================================= */ |
464 | /* UVH_EXTIO_INT0_BROADCAST */ | ||
465 | /* ========================================================================= */ | ||
466 | #define UVH_EXTIO_INT0_BROADCAST 0x61448UL | ||
467 | #define UVH_EXTIO_INT0_BROADCAST_32 0x3f0 | ||
468 | |||
469 | #define UVH_EXTIO_INT0_BROADCAST_ENABLE_SHFT 0 | ||
470 | #define UVH_EXTIO_INT0_BROADCAST_ENABLE_MASK 0x0000000000000001UL | ||
471 | |||
472 | union uvh_extio_int0_broadcast_u { | ||
473 | unsigned long v; | ||
474 | struct uvh_extio_int0_broadcast_s { | ||
475 | unsigned long enable:1; /* RW */ | ||
476 | unsigned long rsvd_1_63:63; | ||
477 | } s; | ||
478 | }; | ||
479 | |||
480 | /* ========================================================================= */ | ||
464 | /* UVH_GR0_TLB_INT0_CONFIG */ | 481 | /* UVH_GR0_TLB_INT0_CONFIG */ |
465 | /* ========================================================================= */ | 482 | /* ========================================================================= */ |
466 | #define UVH_GR0_TLB_INT0_CONFIG 0x61b00UL | 483 | #define UVH_GR0_TLB_INT0_CONFIG 0x61b00UL |
@@ -2606,6 +2623,20 @@ union uvh_scratch5_u { | |||
2606 | }; | 2623 | }; |
2607 | 2624 | ||
2608 | /* ========================================================================= */ | 2625 | /* ========================================================================= */ |
2626 | /* UVH_SCRATCH5_ALIAS */ | ||
2627 | /* ========================================================================= */ | ||
2628 | #define UVH_SCRATCH5_ALIAS 0x2d0208UL | ||
2629 | #define UVH_SCRATCH5_ALIAS_32 0x780 | ||
2630 | |||
2631 | |||
2632 | /* ========================================================================= */ | ||
2633 | /* UVH_SCRATCH5_ALIAS_2 */ | ||
2634 | /* ========================================================================= */ | ||
2635 | #define UVH_SCRATCH5_ALIAS_2 0x2d0210UL | ||
2636 | #define UVH_SCRATCH5_ALIAS_2_32 0x788 | ||
2637 | |||
2638 | |||
2639 | /* ========================================================================= */ | ||
2609 | /* UVXH_EVENT_OCCURRED2 */ | 2640 | /* UVXH_EVENT_OCCURRED2 */ |
2610 | /* ========================================================================= */ | 2641 | /* ========================================================================= */ |
2611 | #define UVXH_EVENT_OCCURRED2 0x70100UL | 2642 | #define UVXH_EVENT_OCCURRED2 0x70100UL |
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h index 828a1565ba57..0f1be11e43d2 100644 --- a/arch/x86/include/asm/x86_init.h +++ b/arch/x86/include/asm/x86_init.h | |||
@@ -172,6 +172,7 @@ struct x86_platform_ops { | |||
172 | 172 | ||
173 | struct pci_dev; | 173 | struct pci_dev; |
174 | struct msi_msg; | 174 | struct msi_msg; |
175 | struct msi_desc; | ||
175 | 176 | ||
176 | struct x86_msi_ops { | 177 | struct x86_msi_ops { |
177 | int (*setup_msi_irqs)(struct pci_dev *dev, int nvec, int type); | 178 | int (*setup_msi_irqs)(struct pci_dev *dev, int nvec, int type); |
@@ -182,6 +183,8 @@ struct x86_msi_ops { | |||
182 | void (*teardown_msi_irqs)(struct pci_dev *dev); | 183 | void (*teardown_msi_irqs)(struct pci_dev *dev); |
183 | void (*restore_msi_irqs)(struct pci_dev *dev, int irq); | 184 | void (*restore_msi_irqs)(struct pci_dev *dev, int irq); |
184 | int (*setup_hpet_msi)(unsigned int irq, unsigned int id); | 185 | int (*setup_hpet_msi)(unsigned int irq, unsigned int id); |
186 | u32 (*msi_mask_irq)(struct msi_desc *desc, u32 mask, u32 flag); | ||
187 | u32 (*msix_mask_irq)(struct msi_desc *desc, u32 flag); | ||
185 | }; | 188 | }; |
186 | 189 | ||
187 | struct IO_APIC_route_entry; | 190 | struct IO_APIC_route_entry; |
diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h index c15ddaf90710..9c3733c5f8f7 100644 --- a/arch/x86/include/uapi/asm/bootparam.h +++ b/arch/x86/include/uapi/asm/bootparam.h | |||
@@ -158,7 +158,7 @@ enum { | |||
158 | X86_SUBARCH_PC = 0, | 158 | X86_SUBARCH_PC = 0, |
159 | X86_SUBARCH_LGUEST, | 159 | X86_SUBARCH_LGUEST, |
160 | X86_SUBARCH_XEN, | 160 | X86_SUBARCH_XEN, |
161 | X86_SUBARCH_MRST, | 161 | X86_SUBARCH_INTEL_MID, |
162 | X86_SUBARCH_CE4100, | 162 | X86_SUBARCH_CE4100, |
163 | X86_NR_SUBARCHS, | 163 | X86_NR_SUBARCHS, |
164 | }; | 164 | }; |
diff --git a/arch/x86/include/uapi/asm/hyperv.h b/arch/x86/include/uapi/asm/hyperv.h index b80420bcd09d..b8f1c0176cbc 100644 --- a/arch/x86/include/uapi/asm/hyperv.h +++ b/arch/x86/include/uapi/asm/hyperv.h | |||
@@ -27,6 +27,19 @@ | |||
27 | #define HV_X64_MSR_VP_RUNTIME_AVAILABLE (1 << 0) | 27 | #define HV_X64_MSR_VP_RUNTIME_AVAILABLE (1 << 0) |
28 | /* Partition Reference Counter (HV_X64_MSR_TIME_REF_COUNT) available*/ | 28 | /* Partition Reference Counter (HV_X64_MSR_TIME_REF_COUNT) available*/ |
29 | #define HV_X64_MSR_TIME_REF_COUNT_AVAILABLE (1 << 1) | 29 | #define HV_X64_MSR_TIME_REF_COUNT_AVAILABLE (1 << 1) |
30 | |||
31 | /* | ||
32 | * There is a single feature flag that signifies the presence of the MSR | ||
33 | * that can be used to retrieve both the local APIC Timer frequency as | ||
34 | * well as the TSC frequency. | ||
35 | */ | ||
36 | |||
37 | /* Local APIC timer frequency MSR (HV_X64_MSR_APIC_FREQUENCY) is available */ | ||
38 | #define HV_X64_MSR_APIC_FREQUENCY_AVAILABLE (1 << 11) | ||
39 | |||
40 | /* TSC frequency MSR (HV_X64_MSR_TSC_FREQUENCY) is available */ | ||
41 | #define HV_X64_MSR_TSC_FREQUENCY_AVAILABLE (1 << 11) | ||
42 | |||
30 | /* | 43 | /* |
31 | * Basic SynIC MSRs (HV_X64_MSR_SCONTROL through HV_X64_MSR_EOM | 44 | * Basic SynIC MSRs (HV_X64_MSR_SCONTROL through HV_X64_MSR_EOM |
32 | * and HV_X64_MSR_SINT0 through HV_X64_MSR_SINT15) available | 45 | * and HV_X64_MSR_SINT0 through HV_X64_MSR_SINT15) available |
@@ -136,6 +149,12 @@ | |||
136 | /* MSR used to read the per-partition time reference counter */ | 149 | /* MSR used to read the per-partition time reference counter */ |
137 | #define HV_X64_MSR_TIME_REF_COUNT 0x40000020 | 150 | #define HV_X64_MSR_TIME_REF_COUNT 0x40000020 |
138 | 151 | ||
152 | /* MSR used to retrieve the TSC frequency */ | ||
153 | #define HV_X64_MSR_TSC_FREQUENCY 0x40000022 | ||
154 | |||
155 | /* MSR used to retrieve the local APIC timer frequency */ | ||
156 | #define HV_X64_MSR_APIC_FREQUENCY 0x40000023 | ||
157 | |||
139 | /* Define the virtual APIC registers */ | 158 | /* Define the virtual APIC registers */ |
140 | #define HV_X64_MSR_EOI 0x40000070 | 159 | #define HV_X64_MSR_EOI 0x40000070 |
141 | #define HV_X64_MSR_ICR 0x40000071 | 160 | #define HV_X64_MSR_ICR 0x40000071 |
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index a5408b965c9d..9b0a34e2cd79 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile | |||
@@ -36,6 +36,8 @@ obj-y += tsc.o io_delay.o rtc.o | |||
36 | obj-y += pci-iommu_table.o | 36 | obj-y += pci-iommu_table.o |
37 | obj-y += resource.o | 37 | obj-y += resource.o |
38 | 38 | ||
39 | obj-$(CONFIG_PREEMPT) += preempt.o | ||
40 | |||
39 | obj-y += process.o | 41 | obj-y += process.o |
40 | obj-y += i387.o xsave.o | 42 | obj-y += i387.o xsave.o |
41 | obj-y += ptrace.o | 43 | obj-y += ptrace.o |
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 40c76604199f..6c0b43bd024b 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
@@ -189,24 +189,31 @@ static int __init acpi_parse_madt(struct acpi_table_header *table) | |||
189 | return 0; | 189 | return 0; |
190 | } | 190 | } |
191 | 191 | ||
192 | static void acpi_register_lapic(int id, u8 enabled) | 192 | /** |
193 | * acpi_register_lapic - register a local apic and generates a logic cpu number | ||
194 | * @id: local apic id to register | ||
195 | * @enabled: this cpu is enabled or not | ||
196 | * | ||
197 | * Returns the logic cpu number which maps to the local apic | ||
198 | */ | ||
199 | static int acpi_register_lapic(int id, u8 enabled) | ||
193 | { | 200 | { |
194 | unsigned int ver = 0; | 201 | unsigned int ver = 0; |
195 | 202 | ||
196 | if (id >= MAX_LOCAL_APIC) { | 203 | if (id >= MAX_LOCAL_APIC) { |
197 | printk(KERN_INFO PREFIX "skipped apicid that is too big\n"); | 204 | printk(KERN_INFO PREFIX "skipped apicid that is too big\n"); |
198 | return; | 205 | return -EINVAL; |
199 | } | 206 | } |
200 | 207 | ||
201 | if (!enabled) { | 208 | if (!enabled) { |
202 | ++disabled_cpus; | 209 | ++disabled_cpus; |
203 | return; | 210 | return -EINVAL; |
204 | } | 211 | } |
205 | 212 | ||
206 | if (boot_cpu_physical_apicid != -1U) | 213 | if (boot_cpu_physical_apicid != -1U) |
207 | ver = apic_version[boot_cpu_physical_apicid]; | 214 | ver = apic_version[boot_cpu_physical_apicid]; |
208 | 215 | ||
209 | generic_processor_info(id, ver); | 216 | return generic_processor_info(id, ver); |
210 | } | 217 | } |
211 | 218 | ||
212 | static int __init | 219 | static int __init |
@@ -614,84 +621,27 @@ static void acpi_map_cpu2node(acpi_handle handle, int cpu, int physid) | |||
614 | #endif | 621 | #endif |
615 | } | 622 | } |
616 | 623 | ||
617 | static int _acpi_map_lsapic(acpi_handle handle, int *pcpu) | 624 | static int _acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu) |
618 | { | 625 | { |
619 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
620 | union acpi_object *obj; | ||
621 | struct acpi_madt_local_apic *lapic; | ||
622 | cpumask_var_t tmp_map, new_map; | ||
623 | u8 physid; | ||
624 | int cpu; | 626 | int cpu; |
625 | int retval = -ENOMEM; | ||
626 | |||
627 | if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer))) | ||
628 | return -EINVAL; | ||
629 | |||
630 | if (!buffer.length || !buffer.pointer) | ||
631 | return -EINVAL; | ||
632 | |||
633 | obj = buffer.pointer; | ||
634 | if (obj->type != ACPI_TYPE_BUFFER || | ||
635 | obj->buffer.length < sizeof(*lapic)) { | ||
636 | kfree(buffer.pointer); | ||
637 | return -EINVAL; | ||
638 | } | ||
639 | 627 | ||
640 | lapic = (struct acpi_madt_local_apic *)obj->buffer.pointer; | 628 | cpu = acpi_register_lapic(physid, ACPI_MADT_ENABLED); |
641 | 629 | if (cpu < 0) { | |
642 | if (lapic->header.type != ACPI_MADT_TYPE_LOCAL_APIC || | 630 | pr_info(PREFIX "Unable to map lapic to logical cpu number\n"); |
643 | !(lapic->lapic_flags & ACPI_MADT_ENABLED)) { | 631 | return cpu; |
644 | kfree(buffer.pointer); | ||
645 | return -EINVAL; | ||
646 | } | ||
647 | |||
648 | physid = lapic->id; | ||
649 | |||
650 | kfree(buffer.pointer); | ||
651 | buffer.length = ACPI_ALLOCATE_BUFFER; | ||
652 | buffer.pointer = NULL; | ||
653 | lapic = NULL; | ||
654 | |||
655 | if (!alloc_cpumask_var(&tmp_map, GFP_KERNEL)) | ||
656 | goto out; | ||
657 | |||
658 | if (!alloc_cpumask_var(&new_map, GFP_KERNEL)) | ||
659 | goto free_tmp_map; | ||
660 | |||
661 | cpumask_copy(tmp_map, cpu_present_mask); | ||
662 | acpi_register_lapic(physid, ACPI_MADT_ENABLED); | ||
663 | |||
664 | /* | ||
665 | * If acpi_register_lapic successfully generates a new logical cpu | ||
666 | * number, then the following will get us exactly what was mapped | ||
667 | */ | ||
668 | cpumask_andnot(new_map, cpu_present_mask, tmp_map); | ||
669 | if (cpumask_empty(new_map)) { | ||
670 | printk ("Unable to map lapic to logical cpu number\n"); | ||
671 | retval = -EINVAL; | ||
672 | goto free_new_map; | ||
673 | } | 632 | } |
674 | 633 | ||
675 | acpi_processor_set_pdc(handle); | 634 | acpi_processor_set_pdc(handle); |
676 | |||
677 | cpu = cpumask_first(new_map); | ||
678 | acpi_map_cpu2node(handle, cpu, physid); | 635 | acpi_map_cpu2node(handle, cpu, physid); |
679 | 636 | ||
680 | *pcpu = cpu; | 637 | *pcpu = cpu; |
681 | retval = 0; | 638 | return 0; |
682 | |||
683 | free_new_map: | ||
684 | free_cpumask_var(new_map); | ||
685 | free_tmp_map: | ||
686 | free_cpumask_var(tmp_map); | ||
687 | out: | ||
688 | return retval; | ||
689 | } | 639 | } |
690 | 640 | ||
691 | /* wrapper to silence section mismatch warning */ | 641 | /* wrapper to silence section mismatch warning */ |
692 | int __ref acpi_map_lsapic(acpi_handle handle, int *pcpu) | 642 | int __ref acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu) |
693 | { | 643 | { |
694 | return _acpi_map_lsapic(handle, pcpu); | 644 | return _acpi_map_lsapic(handle, physid, pcpu); |
695 | } | 645 | } |
696 | EXPORT_SYMBOL(acpi_map_lsapic); | 646 | EXPORT_SYMBOL(acpi_map_lsapic); |
697 | 647 | ||
@@ -745,7 +695,7 @@ static int __init acpi_parse_sbf(struct acpi_table_header *table) | |||
745 | #ifdef CONFIG_HPET_TIMER | 695 | #ifdef CONFIG_HPET_TIMER |
746 | #include <asm/hpet.h> | 696 | #include <asm/hpet.h> |
747 | 697 | ||
748 | static struct __initdata resource *hpet_res; | 698 | static struct resource *hpet_res __initdata; |
749 | 699 | ||
750 | static int __init acpi_parse_hpet(struct acpi_table_header *table) | 700 | static int __init acpi_parse_hpet(struct acpi_table_header *table) |
751 | { | 701 | { |
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index 33120100ff5e..3a2ae4c88948 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c | |||
@@ -26,6 +26,17 @@ static char temp_stack[4096]; | |||
26 | #endif | 26 | #endif |
27 | 27 | ||
28 | /** | 28 | /** |
29 | * x86_acpi_enter_sleep_state - enter sleep state | ||
30 | * @state: Sleep state to enter. | ||
31 | * | ||
32 | * Wrapper around acpi_enter_sleep_state() to be called by assmebly. | ||
33 | */ | ||
34 | acpi_status asmlinkage x86_acpi_enter_sleep_state(u8 state) | ||
35 | { | ||
36 | return acpi_enter_sleep_state(state); | ||
37 | } | ||
38 | |||
39 | /** | ||
29 | * x86_acpi_suspend_lowlevel - save kernel state | 40 | * x86_acpi_suspend_lowlevel - save kernel state |
30 | * | 41 | * |
31 | * Create an identity mapped page table and copy the wakeup routine to | 42 | * Create an identity mapped page table and copy the wakeup routine to |
diff --git a/arch/x86/kernel/acpi/sleep.h b/arch/x86/kernel/acpi/sleep.h index c9c2c982d5e4..65c7b606b606 100644 --- a/arch/x86/kernel/acpi/sleep.h +++ b/arch/x86/kernel/acpi/sleep.h | |||
@@ -17,3 +17,5 @@ extern void wakeup_long64(void); | |||
17 | extern void do_suspend_lowlevel(void); | 17 | extern void do_suspend_lowlevel(void); |
18 | 18 | ||
19 | extern int x86_acpi_suspend_lowlevel(void); | 19 | extern int x86_acpi_suspend_lowlevel(void); |
20 | |||
21 | acpi_status asmlinkage x86_acpi_enter_sleep_state(u8 state); | ||
diff --git a/arch/x86/kernel/acpi/wakeup_32.S b/arch/x86/kernel/acpi/wakeup_32.S index d1daa66ab162..665c6b7d2ea9 100644 --- a/arch/x86/kernel/acpi/wakeup_32.S +++ b/arch/x86/kernel/acpi/wakeup_32.S | |||
@@ -73,7 +73,7 @@ ENTRY(do_suspend_lowlevel) | |||
73 | call save_processor_state | 73 | call save_processor_state |
74 | call save_registers | 74 | call save_registers |
75 | pushl $3 | 75 | pushl $3 |
76 | call acpi_enter_sleep_state | 76 | call x86_acpi_enter_sleep_state |
77 | addl $4, %esp | 77 | addl $4, %esp |
78 | 78 | ||
79 | # In case of S3 failure, we'll emerge here. Jump | 79 | # In case of S3 failure, we'll emerge here. Jump |
diff --git a/arch/x86/kernel/acpi/wakeup_64.S b/arch/x86/kernel/acpi/wakeup_64.S index 8ea5164cbd04..ae693b51ed8e 100644 --- a/arch/x86/kernel/acpi/wakeup_64.S +++ b/arch/x86/kernel/acpi/wakeup_64.S | |||
@@ -73,7 +73,7 @@ ENTRY(do_suspend_lowlevel) | |||
73 | addq $8, %rsp | 73 | addq $8, %rsp |
74 | movl $3, %edi | 74 | movl $3, %edi |
75 | xorl %eax, %eax | 75 | xorl %eax, %eax |
76 | call acpi_enter_sleep_state | 76 | call x86_acpi_enter_sleep_state |
77 | /* in case something went wrong, restore the machine status and go on */ | 77 | /* in case something went wrong, restore the machine status and go on */ |
78 | jmp resume_point | 78 | jmp resume_point |
79 | 79 | ||
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 15e8563e5c24..df94598ad05a 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c | |||
@@ -402,17 +402,6 @@ void alternatives_enable_smp(void) | |||
402 | { | 402 | { |
403 | struct smp_alt_module *mod; | 403 | struct smp_alt_module *mod; |
404 | 404 | ||
405 | #ifdef CONFIG_LOCKDEP | ||
406 | /* | ||
407 | * Older binutils section handling bug prevented | ||
408 | * alternatives-replacement from working reliably. | ||
409 | * | ||
410 | * If this still occurs then you should see a hang | ||
411 | * or crash shortly after this line: | ||
412 | */ | ||
413 | pr_info("lockdep: fixing up alternatives\n"); | ||
414 | #endif | ||
415 | |||
416 | /* Why bother if there are no other CPUs? */ | 405 | /* Why bother if there are no other CPUs? */ |
417 | BUG_ON(num_possible_cpus() == 1); | 406 | BUG_ON(num_possible_cpus() == 1); |
418 | 407 | ||
diff --git a/arch/x86/kernel/apb_timer.c b/arch/x86/kernel/apb_timer.c index c9876efecafb..af5b08ab3b71 100644 --- a/arch/x86/kernel/apb_timer.c +++ b/arch/x86/kernel/apb_timer.c | |||
@@ -40,7 +40,7 @@ | |||
40 | 40 | ||
41 | #include <asm/fixmap.h> | 41 | #include <asm/fixmap.h> |
42 | #include <asm/apb_timer.h> | 42 | #include <asm/apb_timer.h> |
43 | #include <asm/mrst.h> | 43 | #include <asm/intel-mid.h> |
44 | #include <asm/time.h> | 44 | #include <asm/time.h> |
45 | 45 | ||
46 | #define APBT_CLOCKEVENT_RATING 110 | 46 | #define APBT_CLOCKEVENT_RATING 110 |
@@ -157,13 +157,13 @@ static int __init apbt_clockevent_register(void) | |||
157 | 157 | ||
158 | adev->num = smp_processor_id(); | 158 | adev->num = smp_processor_id(); |
159 | adev->timer = dw_apb_clockevent_init(smp_processor_id(), "apbt0", | 159 | adev->timer = dw_apb_clockevent_init(smp_processor_id(), "apbt0", |
160 | mrst_timer_options == MRST_TIMER_LAPIC_APBT ? | 160 | intel_mid_timer_options == INTEL_MID_TIMER_LAPIC_APBT ? |
161 | APBT_CLOCKEVENT_RATING - 100 : APBT_CLOCKEVENT_RATING, | 161 | APBT_CLOCKEVENT_RATING - 100 : APBT_CLOCKEVENT_RATING, |
162 | adev_virt_addr(adev), 0, apbt_freq); | 162 | adev_virt_addr(adev), 0, apbt_freq); |
163 | /* Firmware does EOI handling for us. */ | 163 | /* Firmware does EOI handling for us. */ |
164 | adev->timer->eoi = NULL; | 164 | adev->timer->eoi = NULL; |
165 | 165 | ||
166 | if (mrst_timer_options == MRST_TIMER_LAPIC_APBT) { | 166 | if (intel_mid_timer_options == INTEL_MID_TIMER_LAPIC_APBT) { |
167 | global_clock_event = &adev->timer->ced; | 167 | global_clock_event = &adev->timer->ced; |
168 | printk(KERN_DEBUG "%s clockevent registered as global\n", | 168 | printk(KERN_DEBUG "%s clockevent registered as global\n", |
169 | global_clock_event->name); | 169 | global_clock_event->name); |
@@ -253,7 +253,7 @@ static int apbt_cpuhp_notify(struct notifier_block *n, | |||
253 | 253 | ||
254 | static __init int apbt_late_init(void) | 254 | static __init int apbt_late_init(void) |
255 | { | 255 | { |
256 | if (mrst_timer_options == MRST_TIMER_LAPIC_APBT || | 256 | if (intel_mid_timer_options == INTEL_MID_TIMER_LAPIC_APBT || |
257 | !apb_timer_block_enabled) | 257 | !apb_timer_block_enabled) |
258 | return 0; | 258 | return 0; |
259 | /* This notifier should be called after workqueue is ready */ | 259 | /* This notifier should be called after workqueue is ready */ |
@@ -340,7 +340,7 @@ void __init apbt_time_init(void) | |||
340 | } | 340 | } |
341 | #ifdef CONFIG_SMP | 341 | #ifdef CONFIG_SMP |
342 | /* kernel cmdline disable apb timer, so we will use lapic timers */ | 342 | /* kernel cmdline disable apb timer, so we will use lapic timers */ |
343 | if (mrst_timer_options == MRST_TIMER_LAPIC_APBT) { | 343 | if (intel_mid_timer_options == INTEL_MID_TIMER_LAPIC_APBT) { |
344 | printk(KERN_INFO "apbt: disabled per cpu timer\n"); | 344 | printk(KERN_INFO "apbt: disabled per cpu timer\n"); |
345 | return; | 345 | return; |
346 | } | 346 | } |
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index a7eb82d9b012..ed165d657380 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
@@ -2107,7 +2107,7 @@ void disconnect_bsp_APIC(int virt_wire_setup) | |||
2107 | apic_write(APIC_LVT1, value); | 2107 | apic_write(APIC_LVT1, value); |
2108 | } | 2108 | } |
2109 | 2109 | ||
2110 | void generic_processor_info(int apicid, int version) | 2110 | int generic_processor_info(int apicid, int version) |
2111 | { | 2111 | { |
2112 | int cpu, max = nr_cpu_ids; | 2112 | int cpu, max = nr_cpu_ids; |
2113 | bool boot_cpu_detected = physid_isset(boot_cpu_physical_apicid, | 2113 | bool boot_cpu_detected = physid_isset(boot_cpu_physical_apicid, |
@@ -2127,7 +2127,7 @@ void generic_processor_info(int apicid, int version) | |||
2127 | " Processor %d/0x%x ignored.\n", max, thiscpu, apicid); | 2127 | " Processor %d/0x%x ignored.\n", max, thiscpu, apicid); |
2128 | 2128 | ||
2129 | disabled_cpus++; | 2129 | disabled_cpus++; |
2130 | return; | 2130 | return -ENODEV; |
2131 | } | 2131 | } |
2132 | 2132 | ||
2133 | if (num_processors >= nr_cpu_ids) { | 2133 | if (num_processors >= nr_cpu_ids) { |
@@ -2138,7 +2138,7 @@ void generic_processor_info(int apicid, int version) | |||
2138 | " Processor %d/0x%x ignored.\n", max, thiscpu, apicid); | 2138 | " Processor %d/0x%x ignored.\n", max, thiscpu, apicid); |
2139 | 2139 | ||
2140 | disabled_cpus++; | 2140 | disabled_cpus++; |
2141 | return; | 2141 | return -EINVAL; |
2142 | } | 2142 | } |
2143 | 2143 | ||
2144 | num_processors++; | 2144 | num_processors++; |
@@ -2183,6 +2183,8 @@ void generic_processor_info(int apicid, int version) | |||
2183 | #endif | 2183 | #endif |
2184 | set_cpu_possible(cpu, true); | 2184 | set_cpu_possible(cpu, true); |
2185 | set_cpu_present(cpu, true); | 2185 | set_cpu_present(cpu, true); |
2186 | |||
2187 | return cpu; | ||
2186 | } | 2188 | } |
2187 | 2189 | ||
2188 | int hard_smp_processor_id(void) | 2190 | int hard_smp_processor_id(void) |
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index 1191ac1c9d25..ad0dc0428baf 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c | |||
@@ -39,12 +39,6 @@ | |||
39 | #include <asm/x86_init.h> | 39 | #include <asm/x86_init.h> |
40 | #include <asm/nmi.h> | 40 | #include <asm/nmi.h> |
41 | 41 | ||
42 | /* BMC sets a bit this MMR non-zero before sending an NMI */ | ||
43 | #define UVH_NMI_MMR UVH_SCRATCH5 | ||
44 | #define UVH_NMI_MMR_CLEAR (UVH_NMI_MMR + 8) | ||
45 | #define UV_NMI_PENDING_MASK (1UL << 63) | ||
46 | DEFINE_PER_CPU(unsigned long, cpu_last_nmi_count); | ||
47 | |||
48 | DEFINE_PER_CPU(int, x2apic_extra_bits); | 42 | DEFINE_PER_CPU(int, x2apic_extra_bits); |
49 | 43 | ||
50 | #define PR_DEVEL(fmt, args...) pr_devel("%s: " fmt, __func__, args) | 44 | #define PR_DEVEL(fmt, args...) pr_devel("%s: " fmt, __func__, args) |
@@ -58,7 +52,6 @@ int uv_min_hub_revision_id; | |||
58 | EXPORT_SYMBOL_GPL(uv_min_hub_revision_id); | 52 | EXPORT_SYMBOL_GPL(uv_min_hub_revision_id); |
59 | unsigned int uv_apicid_hibits; | 53 | unsigned int uv_apicid_hibits; |
60 | EXPORT_SYMBOL_GPL(uv_apicid_hibits); | 54 | EXPORT_SYMBOL_GPL(uv_apicid_hibits); |
61 | static DEFINE_SPINLOCK(uv_nmi_lock); | ||
62 | 55 | ||
63 | static struct apic apic_x2apic_uv_x; | 56 | static struct apic apic_x2apic_uv_x; |
64 | 57 | ||
@@ -113,7 +106,7 @@ static int __init early_get_pnodeid(void) | |||
113 | break; | 106 | break; |
114 | case UV3_HUB_PART_NUMBER: | 107 | case UV3_HUB_PART_NUMBER: |
115 | case UV3_HUB_PART_NUMBER_X: | 108 | case UV3_HUB_PART_NUMBER_X: |
116 | uv_min_hub_revision_id += UV3_HUB_REVISION_BASE - 1; | 109 | uv_min_hub_revision_id += UV3_HUB_REVISION_BASE; |
117 | break; | 110 | break; |
118 | } | 111 | } |
119 | 112 | ||
@@ -847,68 +840,6 @@ void uv_cpu_init(void) | |||
847 | set_x2apic_extra_bits(uv_hub_info->pnode); | 840 | set_x2apic_extra_bits(uv_hub_info->pnode); |
848 | } | 841 | } |
849 | 842 | ||
850 | /* | ||
851 | * When NMI is received, print a stack trace. | ||
852 | */ | ||
853 | int uv_handle_nmi(unsigned int reason, struct pt_regs *regs) | ||
854 | { | ||
855 | unsigned long real_uv_nmi; | ||
856 | int bid; | ||
857 | |||
858 | /* | ||
859 | * Each blade has an MMR that indicates when an NMI has been sent | ||
860 | * to cpus on the blade. If an NMI is detected, atomically | ||
861 | * clear the MMR and update a per-blade NMI count used to | ||
862 | * cause each cpu on the blade to notice a new NMI. | ||
863 | */ | ||
864 | bid = uv_numa_blade_id(); | ||
865 | real_uv_nmi = (uv_read_local_mmr(UVH_NMI_MMR) & UV_NMI_PENDING_MASK); | ||
866 | |||
867 | if (unlikely(real_uv_nmi)) { | ||
868 | spin_lock(&uv_blade_info[bid].nmi_lock); | ||
869 | real_uv_nmi = (uv_read_local_mmr(UVH_NMI_MMR) & UV_NMI_PENDING_MASK); | ||
870 | if (real_uv_nmi) { | ||
871 | uv_blade_info[bid].nmi_count++; | ||
872 | uv_write_local_mmr(UVH_NMI_MMR_CLEAR, UV_NMI_PENDING_MASK); | ||
873 | } | ||
874 | spin_unlock(&uv_blade_info[bid].nmi_lock); | ||
875 | } | ||
876 | |||
877 | if (likely(__get_cpu_var(cpu_last_nmi_count) == uv_blade_info[bid].nmi_count)) | ||
878 | return NMI_DONE; | ||
879 | |||
880 | __get_cpu_var(cpu_last_nmi_count) = uv_blade_info[bid].nmi_count; | ||
881 | |||
882 | /* | ||
883 | * Use a lock so only one cpu prints at a time. | ||
884 | * This prevents intermixed output. | ||
885 | */ | ||
886 | spin_lock(&uv_nmi_lock); | ||
887 | pr_info("UV NMI stack dump cpu %u:\n", smp_processor_id()); | ||
888 | dump_stack(); | ||
889 | spin_unlock(&uv_nmi_lock); | ||
890 | |||
891 | return NMI_HANDLED; | ||
892 | } | ||
893 | |||
894 | void uv_register_nmi_notifier(void) | ||
895 | { | ||
896 | if (register_nmi_handler(NMI_UNKNOWN, uv_handle_nmi, 0, "uv")) | ||
897 | printk(KERN_WARNING "UV NMI handler failed to register\n"); | ||
898 | } | ||
899 | |||
900 | void uv_nmi_init(void) | ||
901 | { | ||
902 | unsigned int value; | ||
903 | |||
904 | /* | ||
905 | * Unmask NMI on all cpus | ||
906 | */ | ||
907 | value = apic_read(APIC_LVT1) | APIC_DM_NMI; | ||
908 | value &= ~APIC_LVT_MASKED; | ||
909 | apic_write(APIC_LVT1, value); | ||
910 | } | ||
911 | |||
912 | void __init uv_system_init(void) | 843 | void __init uv_system_init(void) |
913 | { | 844 | { |
914 | union uvh_rh_gam_config_mmr_u m_n_config; | 845 | union uvh_rh_gam_config_mmr_u m_n_config; |
@@ -1046,6 +977,7 @@ void __init uv_system_init(void) | |||
1046 | map_mmr_high(max_pnode); | 977 | map_mmr_high(max_pnode); |
1047 | map_mmioh_high(min_pnode, max_pnode); | 978 | map_mmioh_high(min_pnode, max_pnode); |
1048 | 979 | ||
980 | uv_nmi_setup(); | ||
1049 | uv_cpu_init(); | 981 | uv_cpu_init(); |
1050 | uv_scir_register_cpu_notifier(); | 982 | uv_scir_register_cpu_notifier(); |
1051 | uv_register_nmi_notifier(); | 983 | uv_register_nmi_notifier(); |
diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c index 28610822fb3c..9f6b9341950f 100644 --- a/arch/x86/kernel/asm-offsets.c +++ b/arch/x86/kernel/asm-offsets.c | |||
@@ -32,7 +32,6 @@ void common(void) { | |||
32 | OFFSET(TI_flags, thread_info, flags); | 32 | OFFSET(TI_flags, thread_info, flags); |
33 | OFFSET(TI_status, thread_info, status); | 33 | OFFSET(TI_status, thread_info, status); |
34 | OFFSET(TI_addr_limit, thread_info, addr_limit); | 34 | OFFSET(TI_addr_limit, thread_info, addr_limit); |
35 | OFFSET(TI_preempt_count, thread_info, preempt_count); | ||
36 | 35 | ||
37 | BLANK(); | 36 | BLANK(); |
38 | OFFSET(crypto_tfm_ctx_offset, crypto_tfm, __crt_ctx); | 37 | OFFSET(crypto_tfm_ctx_offset, crypto_tfm, __crt_ctx); |
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 903a264af981..3daece79a142 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c | |||
@@ -823,8 +823,8 @@ static const struct cpu_dev amd_cpu_dev = { | |||
823 | .c_vendor = "AMD", | 823 | .c_vendor = "AMD", |
824 | .c_ident = { "AuthenticAMD" }, | 824 | .c_ident = { "AuthenticAMD" }, |
825 | #ifdef CONFIG_X86_32 | 825 | #ifdef CONFIG_X86_32 |
826 | .c_models = { | 826 | .legacy_models = { |
827 | { .vendor = X86_VENDOR_AMD, .family = 4, .model_names = | 827 | { .family = 4, .model_names = |
828 | { | 828 | { |
829 | [3] = "486 DX/2", | 829 | [3] = "486 DX/2", |
830 | [7] = "486 DX/2-WB", | 830 | [7] = "486 DX/2-WB", |
@@ -835,7 +835,7 @@ static const struct cpu_dev amd_cpu_dev = { | |||
835 | } | 835 | } |
836 | }, | 836 | }, |
837 | }, | 837 | }, |
838 | .c_size_cache = amd_size_cache, | 838 | .legacy_cache_size = amd_size_cache, |
839 | #endif | 839 | #endif |
840 | .c_early_init = early_init_amd, | 840 | .c_early_init = early_init_amd, |
841 | .c_detect_tlb = cpu_detect_tlb_amd, | 841 | .c_detect_tlb = cpu_detect_tlb_amd, |
diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c index fbf6c3bc2400..8d5652dc99dd 100644 --- a/arch/x86/kernel/cpu/centaur.c +++ b/arch/x86/kernel/cpu/centaur.c | |||
@@ -468,10 +468,10 @@ static void init_centaur(struct cpuinfo_x86 *c) | |||
468 | #endif | 468 | #endif |
469 | } | 469 | } |
470 | 470 | ||
471 | #ifdef CONFIG_X86_32 | ||
471 | static unsigned int | 472 | static unsigned int |
472 | centaur_size_cache(struct cpuinfo_x86 *c, unsigned int size) | 473 | centaur_size_cache(struct cpuinfo_x86 *c, unsigned int size) |
473 | { | 474 | { |
474 | #ifdef CONFIG_X86_32 | ||
475 | /* VIA C3 CPUs (670-68F) need further shifting. */ | 475 | /* VIA C3 CPUs (670-68F) need further shifting. */ |
476 | if ((c->x86 == 6) && ((c->x86_model == 7) || (c->x86_model == 8))) | 476 | if ((c->x86 == 6) && ((c->x86_model == 7) || (c->x86_model == 8))) |
477 | size >>= 8; | 477 | size >>= 8; |
@@ -484,16 +484,18 @@ centaur_size_cache(struct cpuinfo_x86 *c, unsigned int size) | |||
484 | if ((c->x86 == 6) && (c->x86_model == 9) && | 484 | if ((c->x86 == 6) && (c->x86_model == 9) && |
485 | (c->x86_mask == 1) && (size == 65)) | 485 | (c->x86_mask == 1) && (size == 65)) |
486 | size -= 1; | 486 | size -= 1; |
487 | #endif | ||
488 | return size; | 487 | return size; |
489 | } | 488 | } |
489 | #endif | ||
490 | 490 | ||
491 | static const struct cpu_dev centaur_cpu_dev = { | 491 | static const struct cpu_dev centaur_cpu_dev = { |
492 | .c_vendor = "Centaur", | 492 | .c_vendor = "Centaur", |
493 | .c_ident = { "CentaurHauls" }, | 493 | .c_ident = { "CentaurHauls" }, |
494 | .c_early_init = early_init_centaur, | 494 | .c_early_init = early_init_centaur, |
495 | .c_init = init_centaur, | 495 | .c_init = init_centaur, |
496 | .c_size_cache = centaur_size_cache, | 496 | #ifdef CONFIG_X86_32 |
497 | .legacy_cache_size = centaur_size_cache, | ||
498 | #endif | ||
497 | .c_x86_vendor = X86_VENDOR_CENTAUR, | 499 | .c_x86_vendor = X86_VENDOR_CENTAUR, |
498 | }; | 500 | }; |
499 | 501 | ||
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 2793d1f095a2..6abc172b8258 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
@@ -346,7 +346,8 @@ static void filter_cpuid_features(struct cpuinfo_x86 *c, bool warn) | |||
346 | /* Look up CPU names by table lookup. */ | 346 | /* Look up CPU names by table lookup. */ |
347 | static const char *table_lookup_model(struct cpuinfo_x86 *c) | 347 | static const char *table_lookup_model(struct cpuinfo_x86 *c) |
348 | { | 348 | { |
349 | const struct cpu_model_info *info; | 349 | #ifdef CONFIG_X86_32 |
350 | const struct legacy_cpu_model_info *info; | ||
350 | 351 | ||
351 | if (c->x86_model >= 16) | 352 | if (c->x86_model >= 16) |
352 | return NULL; /* Range check */ | 353 | return NULL; /* Range check */ |
@@ -354,13 +355,14 @@ static const char *table_lookup_model(struct cpuinfo_x86 *c) | |||
354 | if (!this_cpu) | 355 | if (!this_cpu) |
355 | return NULL; | 356 | return NULL; |
356 | 357 | ||
357 | info = this_cpu->c_models; | 358 | info = this_cpu->legacy_models; |
358 | 359 | ||
359 | while (info && info->family) { | 360 | while (info->family) { |
360 | if (info->family == c->x86) | 361 | if (info->family == c->x86) |
361 | return info->model_names[c->x86_model]; | 362 | return info->model_names[c->x86_model]; |
362 | info++; | 363 | info++; |
363 | } | 364 | } |
365 | #endif | ||
364 | return NULL; /* Not found */ | 366 | return NULL; /* Not found */ |
365 | } | 367 | } |
366 | 368 | ||
@@ -450,8 +452,8 @@ void cpu_detect_cache_sizes(struct cpuinfo_x86 *c) | |||
450 | c->x86_tlbsize += ((ebx >> 16) & 0xfff) + (ebx & 0xfff); | 452 | c->x86_tlbsize += ((ebx >> 16) & 0xfff) + (ebx & 0xfff); |
451 | #else | 453 | #else |
452 | /* do processor-specific cache resizing */ | 454 | /* do processor-specific cache resizing */ |
453 | if (this_cpu->c_size_cache) | 455 | if (this_cpu->legacy_cache_size) |
454 | l2size = this_cpu->c_size_cache(c, l2size); | 456 | l2size = this_cpu->legacy_cache_size(c, l2size); |
455 | 457 | ||
456 | /* Allow user to override all this if necessary. */ | 458 | /* Allow user to override all this if necessary. */ |
457 | if (cachesize_override != -1) | 459 | if (cachesize_override != -1) |
@@ -1095,6 +1097,9 @@ DEFINE_PER_CPU(char *, irq_stack_ptr) = | |||
1095 | 1097 | ||
1096 | DEFINE_PER_CPU(unsigned int, irq_count) __visible = -1; | 1098 | DEFINE_PER_CPU(unsigned int, irq_count) __visible = -1; |
1097 | 1099 | ||
1100 | DEFINE_PER_CPU(int, __preempt_count) = INIT_PREEMPT_COUNT; | ||
1101 | EXPORT_PER_CPU_SYMBOL(__preempt_count); | ||
1102 | |||
1098 | DEFINE_PER_CPU(struct task_struct *, fpu_owner_task); | 1103 | DEFINE_PER_CPU(struct task_struct *, fpu_owner_task); |
1099 | 1104 | ||
1100 | /* | 1105 | /* |
@@ -1169,6 +1174,8 @@ void debug_stack_reset(void) | |||
1169 | 1174 | ||
1170 | DEFINE_PER_CPU(struct task_struct *, current_task) = &init_task; | 1175 | DEFINE_PER_CPU(struct task_struct *, current_task) = &init_task; |
1171 | EXPORT_PER_CPU_SYMBOL(current_task); | 1176 | EXPORT_PER_CPU_SYMBOL(current_task); |
1177 | DEFINE_PER_CPU(int, __preempt_count) = INIT_PREEMPT_COUNT; | ||
1178 | EXPORT_PER_CPU_SYMBOL(__preempt_count); | ||
1172 | DEFINE_PER_CPU(struct task_struct *, fpu_owner_task); | 1179 | DEFINE_PER_CPU(struct task_struct *, fpu_owner_task); |
1173 | 1180 | ||
1174 | #ifdef CONFIG_CC_STACKPROTECTOR | 1181 | #ifdef CONFIG_CC_STACKPROTECTOR |
diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h index 4041c24ae7db..c37dc37e8317 100644 --- a/arch/x86/kernel/cpu/cpu.h +++ b/arch/x86/kernel/cpu/cpu.h | |||
@@ -1,12 +1,6 @@ | |||
1 | #ifndef ARCH_X86_CPU_H | 1 | #ifndef ARCH_X86_CPU_H |
2 | #define ARCH_X86_CPU_H | 2 | #define ARCH_X86_CPU_H |
3 | 3 | ||
4 | struct cpu_model_info { | ||
5 | int vendor; | ||
6 | int family; | ||
7 | const char *model_names[16]; | ||
8 | }; | ||
9 | |||
10 | /* attempt to consolidate cpu attributes */ | 4 | /* attempt to consolidate cpu attributes */ |
11 | struct cpu_dev { | 5 | struct cpu_dev { |
12 | const char *c_vendor; | 6 | const char *c_vendor; |
@@ -14,15 +8,23 @@ struct cpu_dev { | |||
14 | /* some have two possibilities for cpuid string */ | 8 | /* some have two possibilities for cpuid string */ |
15 | const char *c_ident[2]; | 9 | const char *c_ident[2]; |
16 | 10 | ||
17 | struct cpu_model_info c_models[4]; | ||
18 | |||
19 | void (*c_early_init)(struct cpuinfo_x86 *); | 11 | void (*c_early_init)(struct cpuinfo_x86 *); |
20 | void (*c_bsp_init)(struct cpuinfo_x86 *); | 12 | void (*c_bsp_init)(struct cpuinfo_x86 *); |
21 | void (*c_init)(struct cpuinfo_x86 *); | 13 | void (*c_init)(struct cpuinfo_x86 *); |
22 | void (*c_identify)(struct cpuinfo_x86 *); | 14 | void (*c_identify)(struct cpuinfo_x86 *); |
23 | void (*c_detect_tlb)(struct cpuinfo_x86 *); | 15 | void (*c_detect_tlb)(struct cpuinfo_x86 *); |
24 | unsigned int (*c_size_cache)(struct cpuinfo_x86 *, unsigned int); | ||
25 | int c_x86_vendor; | 16 | int c_x86_vendor; |
17 | #ifdef CONFIG_X86_32 | ||
18 | /* Optional vendor specific routine to obtain the cache size. */ | ||
19 | unsigned int (*legacy_cache_size)(struct cpuinfo_x86 *, | ||
20 | unsigned int); | ||
21 | |||
22 | /* Family/stepping-based lookup table for model names. */ | ||
23 | struct legacy_cpu_model_info { | ||
24 | int family; | ||
25 | const char *model_names[16]; | ||
26 | } legacy_models[5]; | ||
27 | #endif | ||
26 | }; | 28 | }; |
27 | 29 | ||
28 | struct _tlb_table { | 30 | struct _tlb_table { |
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index ec7299566f79..dc1ec0dff939 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c | |||
@@ -665,8 +665,8 @@ static const struct cpu_dev intel_cpu_dev = { | |||
665 | .c_vendor = "Intel", | 665 | .c_vendor = "Intel", |
666 | .c_ident = { "GenuineIntel" }, | 666 | .c_ident = { "GenuineIntel" }, |
667 | #ifdef CONFIG_X86_32 | 667 | #ifdef CONFIG_X86_32 |
668 | .c_models = { | 668 | .legacy_models = { |
669 | { .vendor = X86_VENDOR_INTEL, .family = 4, .model_names = | 669 | { .family = 4, .model_names = |
670 | { | 670 | { |
671 | [0] = "486 DX-25/33", | 671 | [0] = "486 DX-25/33", |
672 | [1] = "486 DX-50", | 672 | [1] = "486 DX-50", |
@@ -679,7 +679,7 @@ static const struct cpu_dev intel_cpu_dev = { | |||
679 | [9] = "486 DX/4-WB" | 679 | [9] = "486 DX/4-WB" |
680 | } | 680 | } |
681 | }, | 681 | }, |
682 | { .vendor = X86_VENDOR_INTEL, .family = 5, .model_names = | 682 | { .family = 5, .model_names = |
683 | { | 683 | { |
684 | [0] = "Pentium 60/66 A-step", | 684 | [0] = "Pentium 60/66 A-step", |
685 | [1] = "Pentium 60/66", | 685 | [1] = "Pentium 60/66", |
@@ -690,7 +690,7 @@ static const struct cpu_dev intel_cpu_dev = { | |||
690 | [8] = "Mobile Pentium MMX" | 690 | [8] = "Mobile Pentium MMX" |
691 | } | 691 | } |
692 | }, | 692 | }, |
693 | { .vendor = X86_VENDOR_INTEL, .family = 6, .model_names = | 693 | { .family = 6, .model_names = |
694 | { | 694 | { |
695 | [0] = "Pentium Pro A-step", | 695 | [0] = "Pentium Pro A-step", |
696 | [1] = "Pentium Pro", | 696 | [1] = "Pentium Pro", |
@@ -704,7 +704,7 @@ static const struct cpu_dev intel_cpu_dev = { | |||
704 | [11] = "Pentium III (Tualatin)", | 704 | [11] = "Pentium III (Tualatin)", |
705 | } | 705 | } |
706 | }, | 706 | }, |
707 | { .vendor = X86_VENDOR_INTEL, .family = 15, .model_names = | 707 | { .family = 15, .model_names = |
708 | { | 708 | { |
709 | [0] = "Pentium 4 (Unknown)", | 709 | [0] = "Pentium 4 (Unknown)", |
710 | [1] = "Pentium 4 (Willamette)", | 710 | [1] = "Pentium 4 (Willamette)", |
@@ -714,7 +714,7 @@ static const struct cpu_dev intel_cpu_dev = { | |||
714 | } | 714 | } |
715 | }, | 715 | }, |
716 | }, | 716 | }, |
717 | .c_size_cache = intel_size_cache, | 717 | .legacy_cache_size = intel_size_cache, |
718 | #endif | 718 | #endif |
719 | .c_detect_tlb = intel_detect_tlb, | 719 | .c_detect_tlb = intel_detect_tlb, |
720 | .c_early_init = early_init_intel, | 720 | .c_early_init = early_init_intel, |
diff --git a/arch/x86/kernel/cpu/mcheck/mce-apei.c b/arch/x86/kernel/cpu/mcheck/mce-apei.c index cd8b166a1735..de8b60a53f69 100644 --- a/arch/x86/kernel/cpu/mcheck/mce-apei.c +++ b/arch/x86/kernel/cpu/mcheck/mce-apei.c | |||
@@ -42,8 +42,7 @@ void apei_mce_report_mem_error(int corrected, struct cper_sec_mem_err *mem_err) | |||
42 | struct mce m; | 42 | struct mce m; |
43 | 43 | ||
44 | /* Only corrected MC is reported */ | 44 | /* Only corrected MC is reported */ |
45 | if (!corrected || !(mem_err->validation_bits & | 45 | if (!corrected || !(mem_err->validation_bits & CPER_MEM_VALID_PA)) |
46 | CPER_MEM_VALID_PHYSICAL_ADDRESS)) | ||
47 | return; | 46 | return; |
48 | 47 | ||
49 | mce_setup(&m); | 48 | mce_setup(&m); |
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index 71a39f3621ba..9f7ca266864a 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/clocksource.h> | 15 | #include <linux/clocksource.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/hardirq.h> | 17 | #include <linux/hardirq.h> |
18 | #include <linux/efi.h> | ||
18 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
19 | #include <asm/processor.h> | 20 | #include <asm/processor.h> |
20 | #include <asm/hypervisor.h> | 21 | #include <asm/hypervisor.h> |
@@ -23,6 +24,8 @@ | |||
23 | #include <asm/desc.h> | 24 | #include <asm/desc.h> |
24 | #include <asm/idle.h> | 25 | #include <asm/idle.h> |
25 | #include <asm/irq_regs.h> | 26 | #include <asm/irq_regs.h> |
27 | #include <asm/i8259.h> | ||
28 | #include <asm/apic.h> | ||
26 | 29 | ||
27 | struct ms_hyperv_info ms_hyperv; | 30 | struct ms_hyperv_info ms_hyperv; |
28 | EXPORT_SYMBOL_GPL(ms_hyperv); | 31 | EXPORT_SYMBOL_GPL(ms_hyperv); |
@@ -76,6 +79,30 @@ static void __init ms_hyperv_init_platform(void) | |||
76 | printk(KERN_INFO "HyperV: features 0x%x, hints 0x%x\n", | 79 | printk(KERN_INFO "HyperV: features 0x%x, hints 0x%x\n", |
77 | ms_hyperv.features, ms_hyperv.hints); | 80 | ms_hyperv.features, ms_hyperv.hints); |
78 | 81 | ||
82 | #ifdef CONFIG_X86_LOCAL_APIC | ||
83 | if (ms_hyperv.features & HV_X64_MSR_APIC_FREQUENCY_AVAILABLE) { | ||
84 | /* | ||
85 | * Get the APIC frequency. | ||
86 | */ | ||
87 | u64 hv_lapic_frequency; | ||
88 | |||
89 | rdmsrl(HV_X64_MSR_APIC_FREQUENCY, hv_lapic_frequency); | ||
90 | hv_lapic_frequency = div_u64(hv_lapic_frequency, HZ); | ||
91 | lapic_timer_frequency = hv_lapic_frequency; | ||
92 | printk(KERN_INFO "HyperV: LAPIC Timer Frequency: %#x\n", | ||
93 | lapic_timer_frequency); | ||
94 | |||
95 | /* | ||
96 | * On Hyper-V, when we are booting off an EFI firmware stack, | ||
97 | * we do not have many legacy devices including PIC, PIT etc. | ||
98 | */ | ||
99 | if (efi_enabled(EFI_BOOT)) { | ||
100 | printk(KERN_INFO "HyperV: Using null_legacy_pic\n"); | ||
101 | legacy_pic = &null_legacy_pic; | ||
102 | } | ||
103 | } | ||
104 | #endif | ||
105 | |||
79 | if (ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE) | 106 | if (ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE) |
80 | clocksource_register_hz(&hyperv_cs, NSEC_PER_SEC/100); | 107 | clocksource_register_hz(&hyperv_cs, NSEC_PER_SEC/100); |
81 | } | 108 | } |
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 9d8449158cf9..8e132931614d 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
@@ -1276,16 +1276,16 @@ void perf_events_lapic_init(void) | |||
1276 | static int __kprobes | 1276 | static int __kprobes |
1277 | perf_event_nmi_handler(unsigned int cmd, struct pt_regs *regs) | 1277 | perf_event_nmi_handler(unsigned int cmd, struct pt_regs *regs) |
1278 | { | 1278 | { |
1279 | int ret; | ||
1280 | u64 start_clock; | 1279 | u64 start_clock; |
1281 | u64 finish_clock; | 1280 | u64 finish_clock; |
1281 | int ret; | ||
1282 | 1282 | ||
1283 | if (!atomic_read(&active_events)) | 1283 | if (!atomic_read(&active_events)) |
1284 | return NMI_DONE; | 1284 | return NMI_DONE; |
1285 | 1285 | ||
1286 | start_clock = local_clock(); | 1286 | start_clock = sched_clock(); |
1287 | ret = x86_pmu.handle_irq(regs); | 1287 | ret = x86_pmu.handle_irq(regs); |
1288 | finish_clock = local_clock(); | 1288 | finish_clock = sched_clock(); |
1289 | 1289 | ||
1290 | perf_sample_event_took(finish_clock - start_clock); | 1290 | perf_sample_event_took(finish_clock - start_clock); |
1291 | 1291 | ||
@@ -1989,7 +1989,7 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry) | |||
1989 | frame.return_address = 0; | 1989 | frame.return_address = 0; |
1990 | 1990 | ||
1991 | bytes = copy_from_user_nmi(&frame, fp, sizeof(frame)); | 1991 | bytes = copy_from_user_nmi(&frame, fp, sizeof(frame)); |
1992 | if (bytes != sizeof(frame)) | 1992 | if (bytes != 0) |
1993 | break; | 1993 | break; |
1994 | 1994 | ||
1995 | if (!valid_user_frame(fp, sizeof(frame))) | 1995 | if (!valid_user_frame(fp, sizeof(frame))) |
@@ -2041,7 +2041,7 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) | |||
2041 | frame.return_address = 0; | 2041 | frame.return_address = 0; |
2042 | 2042 | ||
2043 | bytes = copy_from_user_nmi(&frame, fp, sizeof(frame)); | 2043 | bytes = copy_from_user_nmi(&frame, fp, sizeof(frame)); |
2044 | if (bytes != sizeof(frame)) | 2044 | if (bytes != 0) |
2045 | break; | 2045 | break; |
2046 | 2046 | ||
2047 | if (!valid_user_frame(fp, sizeof(frame))) | 2047 | if (!valid_user_frame(fp, sizeof(frame))) |
diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h index cc16faae0538..fd00bb29425d 100644 --- a/arch/x86/kernel/cpu/perf_event.h +++ b/arch/x86/kernel/cpu/perf_event.h | |||
@@ -164,6 +164,11 @@ struct cpu_hw_events { | |||
164 | struct perf_guest_switch_msr guest_switch_msrs[X86_PMC_IDX_MAX]; | 164 | struct perf_guest_switch_msr guest_switch_msrs[X86_PMC_IDX_MAX]; |
165 | 165 | ||
166 | /* | 166 | /* |
167 | * Intel checkpoint mask | ||
168 | */ | ||
169 | u64 intel_cp_status; | ||
170 | |||
171 | /* | ||
167 | * manage shared (per-core, per-cpu) registers | 172 | * manage shared (per-core, per-cpu) registers |
168 | * used on Intel NHM/WSM/SNB | 173 | * used on Intel NHM/WSM/SNB |
169 | */ | 174 | */ |
@@ -440,6 +445,7 @@ struct x86_pmu { | |||
440 | int lbr_nr; /* hardware stack size */ | 445 | int lbr_nr; /* hardware stack size */ |
441 | u64 lbr_sel_mask; /* LBR_SELECT valid bits */ | 446 | u64 lbr_sel_mask; /* LBR_SELECT valid bits */ |
442 | const int *lbr_sel_map; /* lbr_select mappings */ | 447 | const int *lbr_sel_map; /* lbr_select mappings */ |
448 | bool lbr_double_abort; /* duplicated lbr aborts */ | ||
443 | 449 | ||
444 | /* | 450 | /* |
445 | * Extra registers for events | 451 | * Extra registers for events |
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index f31a1655d1ff..0fa4f242f050 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c | |||
@@ -190,9 +190,9 @@ static struct extra_reg intel_snbep_extra_regs[] __read_mostly = { | |||
190 | EVENT_EXTRA_END | 190 | EVENT_EXTRA_END |
191 | }; | 191 | }; |
192 | 192 | ||
193 | EVENT_ATTR_STR(mem-loads, mem_ld_nhm, "event=0x0b,umask=0x10,ldlat=3"); | 193 | EVENT_ATTR_STR(mem-loads, mem_ld_nhm, "event=0x0b,umask=0x10,ldlat=3"); |
194 | EVENT_ATTR_STR(mem-loads, mem_ld_snb, "event=0xcd,umask=0x1,ldlat=3"); | 194 | EVENT_ATTR_STR(mem-loads, mem_ld_snb, "event=0xcd,umask=0x1,ldlat=3"); |
195 | EVENT_ATTR_STR(mem-stores, mem_st_snb, "event=0xcd,umask=0x2"); | 195 | EVENT_ATTR_STR(mem-stores, mem_st_snb, "event=0xcd,umask=0x2"); |
196 | 196 | ||
197 | struct attribute *nhm_events_attrs[] = { | 197 | struct attribute *nhm_events_attrs[] = { |
198 | EVENT_PTR(mem_ld_nhm), | 198 | EVENT_PTR(mem_ld_nhm), |
@@ -1184,6 +1184,11 @@ static void intel_pmu_disable_fixed(struct hw_perf_event *hwc) | |||
1184 | wrmsrl(hwc->config_base, ctrl_val); | 1184 | wrmsrl(hwc->config_base, ctrl_val); |
1185 | } | 1185 | } |
1186 | 1186 | ||
1187 | static inline bool event_is_checkpointed(struct perf_event *event) | ||
1188 | { | ||
1189 | return (event->hw.config & HSW_IN_TX_CHECKPOINTED) != 0; | ||
1190 | } | ||
1191 | |||
1187 | static void intel_pmu_disable_event(struct perf_event *event) | 1192 | static void intel_pmu_disable_event(struct perf_event *event) |
1188 | { | 1193 | { |
1189 | struct hw_perf_event *hwc = &event->hw; | 1194 | struct hw_perf_event *hwc = &event->hw; |
@@ -1197,6 +1202,7 @@ static void intel_pmu_disable_event(struct perf_event *event) | |||
1197 | 1202 | ||
1198 | cpuc->intel_ctrl_guest_mask &= ~(1ull << hwc->idx); | 1203 | cpuc->intel_ctrl_guest_mask &= ~(1ull << hwc->idx); |
1199 | cpuc->intel_ctrl_host_mask &= ~(1ull << hwc->idx); | 1204 | cpuc->intel_ctrl_host_mask &= ~(1ull << hwc->idx); |
1205 | cpuc->intel_cp_status &= ~(1ull << hwc->idx); | ||
1200 | 1206 | ||
1201 | /* | 1207 | /* |
1202 | * must disable before any actual event | 1208 | * must disable before any actual event |
@@ -1271,6 +1277,9 @@ static void intel_pmu_enable_event(struct perf_event *event) | |||
1271 | if (event->attr.exclude_guest) | 1277 | if (event->attr.exclude_guest) |
1272 | cpuc->intel_ctrl_host_mask |= (1ull << hwc->idx); | 1278 | cpuc->intel_ctrl_host_mask |= (1ull << hwc->idx); |
1273 | 1279 | ||
1280 | if (unlikely(event_is_checkpointed(event))) | ||
1281 | cpuc->intel_cp_status |= (1ull << hwc->idx); | ||
1282 | |||
1274 | if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { | 1283 | if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { |
1275 | intel_pmu_enable_fixed(hwc); | 1284 | intel_pmu_enable_fixed(hwc); |
1276 | return; | 1285 | return; |
@@ -1289,6 +1298,17 @@ static void intel_pmu_enable_event(struct perf_event *event) | |||
1289 | int intel_pmu_save_and_restart(struct perf_event *event) | 1298 | int intel_pmu_save_and_restart(struct perf_event *event) |
1290 | { | 1299 | { |
1291 | x86_perf_event_update(event); | 1300 | x86_perf_event_update(event); |
1301 | /* | ||
1302 | * For a checkpointed counter always reset back to 0. This | ||
1303 | * avoids a situation where the counter overflows, aborts the | ||
1304 | * transaction and is then set back to shortly before the | ||
1305 | * overflow, and overflows and aborts again. | ||
1306 | */ | ||
1307 | if (unlikely(event_is_checkpointed(event))) { | ||
1308 | /* No race with NMIs because the counter should not be armed */ | ||
1309 | wrmsrl(event->hw.event_base, 0); | ||
1310 | local64_set(&event->hw.prev_count, 0); | ||
1311 | } | ||
1292 | return x86_perf_event_set_period(event); | 1312 | return x86_perf_event_set_period(event); |
1293 | } | 1313 | } |
1294 | 1314 | ||
@@ -1372,6 +1392,13 @@ again: | |||
1372 | x86_pmu.drain_pebs(regs); | 1392 | x86_pmu.drain_pebs(regs); |
1373 | } | 1393 | } |
1374 | 1394 | ||
1395 | /* | ||
1396 | * Checkpointed counters can lead to 'spurious' PMIs because the | ||
1397 | * rollback caused by the PMI will have cleared the overflow status | ||
1398 | * bit. Therefore always force probe these counters. | ||
1399 | */ | ||
1400 | status |= cpuc->intel_cp_status; | ||
1401 | |||
1375 | for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) { | 1402 | for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) { |
1376 | struct perf_event *event = cpuc->events[bit]; | 1403 | struct perf_event *event = cpuc->events[bit]; |
1377 | 1404 | ||
@@ -1837,6 +1864,20 @@ static int hsw_hw_config(struct perf_event *event) | |||
1837 | event->attr.precise_ip > 0)) | 1864 | event->attr.precise_ip > 0)) |
1838 | return -EOPNOTSUPP; | 1865 | return -EOPNOTSUPP; |
1839 | 1866 | ||
1867 | if (event_is_checkpointed(event)) { | ||
1868 | /* | ||
1869 | * Sampling of checkpointed events can cause situations where | ||
1870 | * the CPU constantly aborts because of a overflow, which is | ||
1871 | * then checkpointed back and ignored. Forbid checkpointing | ||
1872 | * for sampling. | ||
1873 | * | ||
1874 | * But still allow a long sampling period, so that perf stat | ||
1875 | * from KVM works. | ||
1876 | */ | ||
1877 | if (event->attr.sample_period > 0 && | ||
1878 | event->attr.sample_period < 0x7fffffff) | ||
1879 | return -EOPNOTSUPP; | ||
1880 | } | ||
1840 | return 0; | 1881 | return 0; |
1841 | } | 1882 | } |
1842 | 1883 | ||
@@ -2182,10 +2223,36 @@ static __init void intel_nehalem_quirk(void) | |||
2182 | } | 2223 | } |
2183 | } | 2224 | } |
2184 | 2225 | ||
2185 | EVENT_ATTR_STR(mem-loads, mem_ld_hsw, "event=0xcd,umask=0x1,ldlat=3"); | 2226 | EVENT_ATTR_STR(mem-loads, mem_ld_hsw, "event=0xcd,umask=0x1,ldlat=3"); |
2186 | EVENT_ATTR_STR(mem-stores, mem_st_hsw, "event=0xd0,umask=0x82") | 2227 | EVENT_ATTR_STR(mem-stores, mem_st_hsw, "event=0xd0,umask=0x82") |
2228 | |||
2229 | /* Haswell special events */ | ||
2230 | EVENT_ATTR_STR(tx-start, tx_start, "event=0xc9,umask=0x1"); | ||
2231 | EVENT_ATTR_STR(tx-commit, tx_commit, "event=0xc9,umask=0x2"); | ||
2232 | EVENT_ATTR_STR(tx-abort, tx_abort, "event=0xc9,umask=0x4"); | ||
2233 | EVENT_ATTR_STR(tx-capacity, tx_capacity, "event=0x54,umask=0x2"); | ||
2234 | EVENT_ATTR_STR(tx-conflict, tx_conflict, "event=0x54,umask=0x1"); | ||
2235 | EVENT_ATTR_STR(el-start, el_start, "event=0xc8,umask=0x1"); | ||
2236 | EVENT_ATTR_STR(el-commit, el_commit, "event=0xc8,umask=0x2"); | ||
2237 | EVENT_ATTR_STR(el-abort, el_abort, "event=0xc8,umask=0x4"); | ||
2238 | EVENT_ATTR_STR(el-capacity, el_capacity, "event=0x54,umask=0x2"); | ||
2239 | EVENT_ATTR_STR(el-conflict, el_conflict, "event=0x54,umask=0x1"); | ||
2240 | EVENT_ATTR_STR(cycles-t, cycles_t, "event=0x3c,in_tx=1"); | ||
2241 | EVENT_ATTR_STR(cycles-ct, cycles_ct, "event=0x3c,in_tx=1,in_tx_cp=1"); | ||
2187 | 2242 | ||
2188 | static struct attribute *hsw_events_attrs[] = { | 2243 | static struct attribute *hsw_events_attrs[] = { |
2244 | EVENT_PTR(tx_start), | ||
2245 | EVENT_PTR(tx_commit), | ||
2246 | EVENT_PTR(tx_abort), | ||
2247 | EVENT_PTR(tx_capacity), | ||
2248 | EVENT_PTR(tx_conflict), | ||
2249 | EVENT_PTR(el_start), | ||
2250 | EVENT_PTR(el_commit), | ||
2251 | EVENT_PTR(el_abort), | ||
2252 | EVENT_PTR(el_capacity), | ||
2253 | EVENT_PTR(el_conflict), | ||
2254 | EVENT_PTR(cycles_t), | ||
2255 | EVENT_PTR(cycles_ct), | ||
2189 | EVENT_PTR(mem_ld_hsw), | 2256 | EVENT_PTR(mem_ld_hsw), |
2190 | EVENT_PTR(mem_st_hsw), | 2257 | EVENT_PTR(mem_st_hsw), |
2191 | NULL | 2258 | NULL |
@@ -2452,6 +2519,7 @@ __init int intel_pmu_init(void) | |||
2452 | x86_pmu.hw_config = hsw_hw_config; | 2519 | x86_pmu.hw_config = hsw_hw_config; |
2453 | x86_pmu.get_event_constraints = hsw_get_event_constraints; | 2520 | x86_pmu.get_event_constraints = hsw_get_event_constraints; |
2454 | x86_pmu.cpu_events = hsw_events_attrs; | 2521 | x86_pmu.cpu_events = hsw_events_attrs; |
2522 | x86_pmu.lbr_double_abort = true; | ||
2455 | pr_cont("Haswell events, "); | 2523 | pr_cont("Haswell events, "); |
2456 | break; | 2524 | break; |
2457 | 2525 | ||
diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index ab3ba1c1b7dd..ae96cfa5eddd 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c | |||
@@ -12,6 +12,7 @@ | |||
12 | 12 | ||
13 | #define BTS_BUFFER_SIZE (PAGE_SIZE << 4) | 13 | #define BTS_BUFFER_SIZE (PAGE_SIZE << 4) |
14 | #define PEBS_BUFFER_SIZE PAGE_SIZE | 14 | #define PEBS_BUFFER_SIZE PAGE_SIZE |
15 | #define PEBS_FIXUP_SIZE PAGE_SIZE | ||
15 | 16 | ||
16 | /* | 17 | /* |
17 | * pebs_record_32 for p4 and core not supported | 18 | * pebs_record_32 for p4 and core not supported |
@@ -182,18 +183,32 @@ struct pebs_record_nhm { | |||
182 | * Same as pebs_record_nhm, with two additional fields. | 183 | * Same as pebs_record_nhm, with two additional fields. |
183 | */ | 184 | */ |
184 | struct pebs_record_hsw { | 185 | struct pebs_record_hsw { |
185 | struct pebs_record_nhm nhm; | 186 | u64 flags, ip; |
186 | /* | 187 | u64 ax, bx, cx, dx; |
187 | * Real IP of the event. In the Intel documentation this | 188 | u64 si, di, bp, sp; |
188 | * is called eventingrip. | 189 | u64 r8, r9, r10, r11; |
189 | */ | 190 | u64 r12, r13, r14, r15; |
190 | u64 real_ip; | 191 | u64 status, dla, dse, lat; |
191 | /* | 192 | u64 real_ip, tsx_tuning; |
192 | * TSX tuning information field: abort cycles and abort flags. | 193 | }; |
193 | */ | 194 | |
194 | u64 tsx_tuning; | 195 | union hsw_tsx_tuning { |
196 | struct { | ||
197 | u32 cycles_last_block : 32, | ||
198 | hle_abort : 1, | ||
199 | rtm_abort : 1, | ||
200 | instruction_abort : 1, | ||
201 | non_instruction_abort : 1, | ||
202 | retry : 1, | ||
203 | data_conflict : 1, | ||
204 | capacity_writes : 1, | ||
205 | capacity_reads : 1; | ||
206 | }; | ||
207 | u64 value; | ||
195 | }; | 208 | }; |
196 | 209 | ||
210 | #define PEBS_HSW_TSX_FLAGS 0xff00000000ULL | ||
211 | |||
197 | void init_debug_store_on_cpu(int cpu) | 212 | void init_debug_store_on_cpu(int cpu) |
198 | { | 213 | { |
199 | struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds; | 214 | struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds; |
@@ -214,12 +229,14 @@ void fini_debug_store_on_cpu(int cpu) | |||
214 | wrmsr_on_cpu(cpu, MSR_IA32_DS_AREA, 0, 0); | 229 | wrmsr_on_cpu(cpu, MSR_IA32_DS_AREA, 0, 0); |
215 | } | 230 | } |
216 | 231 | ||
232 | static DEFINE_PER_CPU(void *, insn_buffer); | ||
233 | |||
217 | static int alloc_pebs_buffer(int cpu) | 234 | static int alloc_pebs_buffer(int cpu) |
218 | { | 235 | { |
219 | struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds; | 236 | struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds; |
220 | int node = cpu_to_node(cpu); | 237 | int node = cpu_to_node(cpu); |
221 | int max, thresh = 1; /* always use a single PEBS record */ | 238 | int max, thresh = 1; /* always use a single PEBS record */ |
222 | void *buffer; | 239 | void *buffer, *ibuffer; |
223 | 240 | ||
224 | if (!x86_pmu.pebs) | 241 | if (!x86_pmu.pebs) |
225 | return 0; | 242 | return 0; |
@@ -228,6 +245,19 @@ static int alloc_pebs_buffer(int cpu) | |||
228 | if (unlikely(!buffer)) | 245 | if (unlikely(!buffer)) |
229 | return -ENOMEM; | 246 | return -ENOMEM; |
230 | 247 | ||
248 | /* | ||
249 | * HSW+ already provides us the eventing ip; no need to allocate this | ||
250 | * buffer then. | ||
251 | */ | ||
252 | if (x86_pmu.intel_cap.pebs_format < 2) { | ||
253 | ibuffer = kzalloc_node(PEBS_FIXUP_SIZE, GFP_KERNEL, node); | ||
254 | if (!ibuffer) { | ||
255 | kfree(buffer); | ||
256 | return -ENOMEM; | ||
257 | } | ||
258 | per_cpu(insn_buffer, cpu) = ibuffer; | ||
259 | } | ||
260 | |||
231 | max = PEBS_BUFFER_SIZE / x86_pmu.pebs_record_size; | 261 | max = PEBS_BUFFER_SIZE / x86_pmu.pebs_record_size; |
232 | 262 | ||
233 | ds->pebs_buffer_base = (u64)(unsigned long)buffer; | 263 | ds->pebs_buffer_base = (u64)(unsigned long)buffer; |
@@ -248,6 +278,9 @@ static void release_pebs_buffer(int cpu) | |||
248 | if (!ds || !x86_pmu.pebs) | 278 | if (!ds || !x86_pmu.pebs) |
249 | return; | 279 | return; |
250 | 280 | ||
281 | kfree(per_cpu(insn_buffer, cpu)); | ||
282 | per_cpu(insn_buffer, cpu) = NULL; | ||
283 | |||
251 | kfree((void *)(unsigned long)ds->pebs_buffer_base); | 284 | kfree((void *)(unsigned long)ds->pebs_buffer_base); |
252 | ds->pebs_buffer_base = 0; | 285 | ds->pebs_buffer_base = 0; |
253 | } | 286 | } |
@@ -715,6 +748,7 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs) | |||
715 | unsigned long old_to, to = cpuc->lbr_entries[0].to; | 748 | unsigned long old_to, to = cpuc->lbr_entries[0].to; |
716 | unsigned long ip = regs->ip; | 749 | unsigned long ip = regs->ip; |
717 | int is_64bit = 0; | 750 | int is_64bit = 0; |
751 | void *kaddr; | ||
718 | 752 | ||
719 | /* | 753 | /* |
720 | * We don't need to fixup if the PEBS assist is fault like | 754 | * We don't need to fixup if the PEBS assist is fault like |
@@ -738,7 +772,7 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs) | |||
738 | * unsigned math, either ip is before the start (impossible) or | 772 | * unsigned math, either ip is before the start (impossible) or |
739 | * the basic block is larger than 1 page (sanity) | 773 | * the basic block is larger than 1 page (sanity) |
740 | */ | 774 | */ |
741 | if ((ip - to) > PAGE_SIZE) | 775 | if ((ip - to) > PEBS_FIXUP_SIZE) |
742 | return 0; | 776 | return 0; |
743 | 777 | ||
744 | /* | 778 | /* |
@@ -749,29 +783,33 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs) | |||
749 | return 1; | 783 | return 1; |
750 | } | 784 | } |
751 | 785 | ||
786 | if (!kernel_ip(ip)) { | ||
787 | int size, bytes; | ||
788 | u8 *buf = this_cpu_read(insn_buffer); | ||
789 | |||
790 | size = ip - to; /* Must fit our buffer, see above */ | ||
791 | bytes = copy_from_user_nmi(buf, (void __user *)to, size); | ||
792 | if (bytes != 0) | ||
793 | return 0; | ||
794 | |||
795 | kaddr = buf; | ||
796 | } else { | ||
797 | kaddr = (void *)to; | ||
798 | } | ||
799 | |||
752 | do { | 800 | do { |
753 | struct insn insn; | 801 | struct insn insn; |
754 | u8 buf[MAX_INSN_SIZE]; | ||
755 | void *kaddr; | ||
756 | 802 | ||
757 | old_to = to; | 803 | old_to = to; |
758 | if (!kernel_ip(ip)) { | ||
759 | int bytes, size = MAX_INSN_SIZE; | ||
760 | |||
761 | bytes = copy_from_user_nmi(buf, (void __user *)to, size); | ||
762 | if (bytes != size) | ||
763 | return 0; | ||
764 | |||
765 | kaddr = buf; | ||
766 | } else | ||
767 | kaddr = (void *)to; | ||
768 | 804 | ||
769 | #ifdef CONFIG_X86_64 | 805 | #ifdef CONFIG_X86_64 |
770 | is_64bit = kernel_ip(to) || !test_thread_flag(TIF_IA32); | 806 | is_64bit = kernel_ip(to) || !test_thread_flag(TIF_IA32); |
771 | #endif | 807 | #endif |
772 | insn_init(&insn, kaddr, is_64bit); | 808 | insn_init(&insn, kaddr, is_64bit); |
773 | insn_get_length(&insn); | 809 | insn_get_length(&insn); |
810 | |||
774 | to += insn.length; | 811 | to += insn.length; |
812 | kaddr += insn.length; | ||
775 | } while (to < ip); | 813 | } while (to < ip); |
776 | 814 | ||
777 | if (to == ip) { | 815 | if (to == ip) { |
@@ -786,16 +824,34 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs) | |||
786 | return 0; | 824 | return 0; |
787 | } | 825 | } |
788 | 826 | ||
827 | static inline u64 intel_hsw_weight(struct pebs_record_hsw *pebs) | ||
828 | { | ||
829 | if (pebs->tsx_tuning) { | ||
830 | union hsw_tsx_tuning tsx = { .value = pebs->tsx_tuning }; | ||
831 | return tsx.cycles_last_block; | ||
832 | } | ||
833 | return 0; | ||
834 | } | ||
835 | |||
836 | static inline u64 intel_hsw_transaction(struct pebs_record_hsw *pebs) | ||
837 | { | ||
838 | u64 txn = (pebs->tsx_tuning & PEBS_HSW_TSX_FLAGS) >> 32; | ||
839 | |||
840 | /* For RTM XABORTs also log the abort code from AX */ | ||
841 | if ((txn & PERF_TXN_TRANSACTION) && (pebs->ax & 1)) | ||
842 | txn |= ((pebs->ax >> 24) & 0xff) << PERF_TXN_ABORT_SHIFT; | ||
843 | return txn; | ||
844 | } | ||
845 | |||
789 | static void __intel_pmu_pebs_event(struct perf_event *event, | 846 | static void __intel_pmu_pebs_event(struct perf_event *event, |
790 | struct pt_regs *iregs, void *__pebs) | 847 | struct pt_regs *iregs, void *__pebs) |
791 | { | 848 | { |
792 | /* | 849 | /* |
793 | * We cast to pebs_record_nhm to get the load latency data | 850 | * We cast to the biggest pebs_record but are careful not to |
794 | * if extra_reg MSR_PEBS_LD_LAT_THRESHOLD used | 851 | * unconditionally access the 'extra' entries. |
795 | */ | 852 | */ |
796 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 853 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
797 | struct pebs_record_nhm *pebs = __pebs; | 854 | struct pebs_record_hsw *pebs = __pebs; |
798 | struct pebs_record_hsw *pebs_hsw = __pebs; | ||
799 | struct perf_sample_data data; | 855 | struct perf_sample_data data; |
800 | struct pt_regs regs; | 856 | struct pt_regs regs; |
801 | u64 sample_type; | 857 | u64 sample_type; |
@@ -854,7 +910,7 @@ static void __intel_pmu_pebs_event(struct perf_event *event, | |||
854 | regs.sp = pebs->sp; | 910 | regs.sp = pebs->sp; |
855 | 911 | ||
856 | if (event->attr.precise_ip > 1 && x86_pmu.intel_cap.pebs_format >= 2) { | 912 | if (event->attr.precise_ip > 1 && x86_pmu.intel_cap.pebs_format >= 2) { |
857 | regs.ip = pebs_hsw->real_ip; | 913 | regs.ip = pebs->real_ip; |
858 | regs.flags |= PERF_EFLAGS_EXACT; | 914 | regs.flags |= PERF_EFLAGS_EXACT; |
859 | } else if (event->attr.precise_ip > 1 && intel_pmu_pebs_fixup_ip(®s)) | 915 | } else if (event->attr.precise_ip > 1 && intel_pmu_pebs_fixup_ip(®s)) |
860 | regs.flags |= PERF_EFLAGS_EXACT; | 916 | regs.flags |= PERF_EFLAGS_EXACT; |
@@ -862,9 +918,18 @@ static void __intel_pmu_pebs_event(struct perf_event *event, | |||
862 | regs.flags &= ~PERF_EFLAGS_EXACT; | 918 | regs.flags &= ~PERF_EFLAGS_EXACT; |
863 | 919 | ||
864 | if ((event->attr.sample_type & PERF_SAMPLE_ADDR) && | 920 | if ((event->attr.sample_type & PERF_SAMPLE_ADDR) && |
865 | x86_pmu.intel_cap.pebs_format >= 1) | 921 | x86_pmu.intel_cap.pebs_format >= 1) |
866 | data.addr = pebs->dla; | 922 | data.addr = pebs->dla; |
867 | 923 | ||
924 | if (x86_pmu.intel_cap.pebs_format >= 2) { | ||
925 | /* Only set the TSX weight when no memory weight. */ | ||
926 | if ((event->attr.sample_type & PERF_SAMPLE_WEIGHT) && !fll) | ||
927 | data.weight = intel_hsw_weight(pebs); | ||
928 | |||
929 | if (event->attr.sample_type & PERF_SAMPLE_TRANSACTION) | ||
930 | data.txn = intel_hsw_transaction(pebs); | ||
931 | } | ||
932 | |||
868 | if (has_branch_stack(event)) | 933 | if (has_branch_stack(event)) |
869 | data.br_stack = &cpuc->lbr_stack; | 934 | data.br_stack = &cpuc->lbr_stack; |
870 | 935 | ||
@@ -913,17 +978,34 @@ static void intel_pmu_drain_pebs_core(struct pt_regs *iregs) | |||
913 | __intel_pmu_pebs_event(event, iregs, at); | 978 | __intel_pmu_pebs_event(event, iregs, at); |
914 | } | 979 | } |
915 | 980 | ||
916 | static void __intel_pmu_drain_pebs_nhm(struct pt_regs *iregs, void *at, | 981 | static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs) |
917 | void *top) | ||
918 | { | 982 | { |
919 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 983 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
920 | struct debug_store *ds = cpuc->ds; | 984 | struct debug_store *ds = cpuc->ds; |
921 | struct perf_event *event = NULL; | 985 | struct perf_event *event = NULL; |
986 | void *at, *top; | ||
922 | u64 status = 0; | 987 | u64 status = 0; |
923 | int bit; | 988 | int bit; |
924 | 989 | ||
990 | if (!x86_pmu.pebs_active) | ||
991 | return; | ||
992 | |||
993 | at = (struct pebs_record_nhm *)(unsigned long)ds->pebs_buffer_base; | ||
994 | top = (struct pebs_record_nhm *)(unsigned long)ds->pebs_index; | ||
995 | |||
925 | ds->pebs_index = ds->pebs_buffer_base; | 996 | ds->pebs_index = ds->pebs_buffer_base; |
926 | 997 | ||
998 | if (unlikely(at > top)) | ||
999 | return; | ||
1000 | |||
1001 | /* | ||
1002 | * Should not happen, we program the threshold at 1 and do not | ||
1003 | * set a reset value. | ||
1004 | */ | ||
1005 | WARN_ONCE(top - at > x86_pmu.max_pebs_events * x86_pmu.pebs_record_size, | ||
1006 | "Unexpected number of pebs records %ld\n", | ||
1007 | (long)(top - at) / x86_pmu.pebs_record_size); | ||
1008 | |||
927 | for (; at < top; at += x86_pmu.pebs_record_size) { | 1009 | for (; at < top; at += x86_pmu.pebs_record_size) { |
928 | struct pebs_record_nhm *p = at; | 1010 | struct pebs_record_nhm *p = at; |
929 | 1011 | ||
@@ -951,61 +1033,6 @@ static void __intel_pmu_drain_pebs_nhm(struct pt_regs *iregs, void *at, | |||
951 | } | 1033 | } |
952 | } | 1034 | } |
953 | 1035 | ||
954 | static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs) | ||
955 | { | ||
956 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
957 | struct debug_store *ds = cpuc->ds; | ||
958 | struct pebs_record_nhm *at, *top; | ||
959 | int n; | ||
960 | |||
961 | if (!x86_pmu.pebs_active) | ||
962 | return; | ||
963 | |||
964 | at = (struct pebs_record_nhm *)(unsigned long)ds->pebs_buffer_base; | ||
965 | top = (struct pebs_record_nhm *)(unsigned long)ds->pebs_index; | ||
966 | |||
967 | ds->pebs_index = ds->pebs_buffer_base; | ||
968 | |||
969 | n = top - at; | ||
970 | if (n <= 0) | ||
971 | return; | ||
972 | |||
973 | /* | ||
974 | * Should not happen, we program the threshold at 1 and do not | ||
975 | * set a reset value. | ||
976 | */ | ||
977 | WARN_ONCE(n > x86_pmu.max_pebs_events, | ||
978 | "Unexpected number of pebs records %d\n", n); | ||
979 | |||
980 | return __intel_pmu_drain_pebs_nhm(iregs, at, top); | ||
981 | } | ||
982 | |||
983 | static void intel_pmu_drain_pebs_hsw(struct pt_regs *iregs) | ||
984 | { | ||
985 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
986 | struct debug_store *ds = cpuc->ds; | ||
987 | struct pebs_record_hsw *at, *top; | ||
988 | int n; | ||
989 | |||
990 | if (!x86_pmu.pebs_active) | ||
991 | return; | ||
992 | |||
993 | at = (struct pebs_record_hsw *)(unsigned long)ds->pebs_buffer_base; | ||
994 | top = (struct pebs_record_hsw *)(unsigned long)ds->pebs_index; | ||
995 | |||
996 | n = top - at; | ||
997 | if (n <= 0) | ||
998 | return; | ||
999 | /* | ||
1000 | * Should not happen, we program the threshold at 1 and do not | ||
1001 | * set a reset value. | ||
1002 | */ | ||
1003 | WARN_ONCE(n > x86_pmu.max_pebs_events, | ||
1004 | "Unexpected number of pebs records %d\n", n); | ||
1005 | |||
1006 | return __intel_pmu_drain_pebs_nhm(iregs, at, top); | ||
1007 | } | ||
1008 | |||
1009 | /* | 1036 | /* |
1010 | * BTS, PEBS probe and setup | 1037 | * BTS, PEBS probe and setup |
1011 | */ | 1038 | */ |
@@ -1040,7 +1067,7 @@ void intel_ds_init(void) | |||
1040 | case 2: | 1067 | case 2: |
1041 | pr_cont("PEBS fmt2%c, ", pebs_type); | 1068 | pr_cont("PEBS fmt2%c, ", pebs_type); |
1042 | x86_pmu.pebs_record_size = sizeof(struct pebs_record_hsw); | 1069 | x86_pmu.pebs_record_size = sizeof(struct pebs_record_hsw); |
1043 | x86_pmu.drain_pebs = intel_pmu_drain_pebs_hsw; | 1070 | x86_pmu.drain_pebs = intel_pmu_drain_pebs_nhm; |
1044 | break; | 1071 | break; |
1045 | 1072 | ||
1046 | default: | 1073 | default: |
diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/arch/x86/kernel/cpu/perf_event_intel_lbr.c index d5be06a5005e..d82d155aca8c 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_lbr.c +++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c | |||
@@ -284,6 +284,7 @@ static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc) | |||
284 | int lbr_format = x86_pmu.intel_cap.lbr_format; | 284 | int lbr_format = x86_pmu.intel_cap.lbr_format; |
285 | u64 tos = intel_pmu_lbr_tos(); | 285 | u64 tos = intel_pmu_lbr_tos(); |
286 | int i; | 286 | int i; |
287 | int out = 0; | ||
287 | 288 | ||
288 | for (i = 0; i < x86_pmu.lbr_nr; i++) { | 289 | for (i = 0; i < x86_pmu.lbr_nr; i++) { |
289 | unsigned long lbr_idx = (tos - i) & mask; | 290 | unsigned long lbr_idx = (tos - i) & mask; |
@@ -306,15 +307,27 @@ static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc) | |||
306 | } | 307 | } |
307 | from = (u64)((((s64)from) << skip) >> skip); | 308 | from = (u64)((((s64)from) << skip) >> skip); |
308 | 309 | ||
309 | cpuc->lbr_entries[i].from = from; | 310 | /* |
310 | cpuc->lbr_entries[i].to = to; | 311 | * Some CPUs report duplicated abort records, |
311 | cpuc->lbr_entries[i].mispred = mis; | 312 | * with the second entry not having an abort bit set. |
312 | cpuc->lbr_entries[i].predicted = pred; | 313 | * Skip them here. This loop runs backwards, |
313 | cpuc->lbr_entries[i].in_tx = in_tx; | 314 | * so we need to undo the previous record. |
314 | cpuc->lbr_entries[i].abort = abort; | 315 | * If the abort just happened outside the window |
315 | cpuc->lbr_entries[i].reserved = 0; | 316 | * the extra entry cannot be removed. |
317 | */ | ||
318 | if (abort && x86_pmu.lbr_double_abort && out > 0) | ||
319 | out--; | ||
320 | |||
321 | cpuc->lbr_entries[out].from = from; | ||
322 | cpuc->lbr_entries[out].to = to; | ||
323 | cpuc->lbr_entries[out].mispred = mis; | ||
324 | cpuc->lbr_entries[out].predicted = pred; | ||
325 | cpuc->lbr_entries[out].in_tx = in_tx; | ||
326 | cpuc->lbr_entries[out].abort = abort; | ||
327 | cpuc->lbr_entries[out].reserved = 0; | ||
328 | out++; | ||
316 | } | 329 | } |
317 | cpuc->lbr_stack.nr = i; | 330 | cpuc->lbr_stack.nr = out; |
318 | } | 331 | } |
319 | 332 | ||
320 | void intel_pmu_lbr_read(void) | 333 | void intel_pmu_lbr_read(void) |
@@ -478,7 +491,7 @@ static int branch_type(unsigned long from, unsigned long to, int abort) | |||
478 | 491 | ||
479 | /* may fail if text not present */ | 492 | /* may fail if text not present */ |
480 | bytes = copy_from_user_nmi(buf, (void __user *)from, size); | 493 | bytes = copy_from_user_nmi(buf, (void __user *)from, size); |
481 | if (bytes != size) | 494 | if (bytes != 0) |
482 | return X86_BR_NONE; | 495 | return X86_BR_NONE; |
483 | 496 | ||
484 | addr = buf; | 497 | addr = buf; |
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c index 4118f9f68315..29c248799ced 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c | |||
@@ -997,6 +997,20 @@ static int snbep_pci2phy_map_init(int devid) | |||
997 | } | 997 | } |
998 | } | 998 | } |
999 | 999 | ||
1000 | if (!err) { | ||
1001 | /* | ||
1002 | * For PCI bus with no UBOX device, find the next bus | ||
1003 | * that has UBOX device and use its mapping. | ||
1004 | */ | ||
1005 | i = -1; | ||
1006 | for (bus = 255; bus >= 0; bus--) { | ||
1007 | if (pcibus_to_physid[bus] >= 0) | ||
1008 | i = pcibus_to_physid[bus]; | ||
1009 | else | ||
1010 | pcibus_to_physid[bus] = i; | ||
1011 | } | ||
1012 | } | ||
1013 | |||
1000 | if (ubox_dev) | 1014 | if (ubox_dev) |
1001 | pci_dev_put(ubox_dev); | 1015 | pci_dev_put(ubox_dev); |
1002 | 1016 | ||
@@ -1099,6 +1113,24 @@ static struct attribute *ivt_uncore_qpi_formats_attr[] = { | |||
1099 | &format_attr_umask.attr, | 1113 | &format_attr_umask.attr, |
1100 | &format_attr_edge.attr, | 1114 | &format_attr_edge.attr, |
1101 | &format_attr_thresh8.attr, | 1115 | &format_attr_thresh8.attr, |
1116 | &format_attr_match_rds.attr, | ||
1117 | &format_attr_match_rnid30.attr, | ||
1118 | &format_attr_match_rnid4.attr, | ||
1119 | &format_attr_match_dnid.attr, | ||
1120 | &format_attr_match_mc.attr, | ||
1121 | &format_attr_match_opc.attr, | ||
1122 | &format_attr_match_vnw.attr, | ||
1123 | &format_attr_match0.attr, | ||
1124 | &format_attr_match1.attr, | ||
1125 | &format_attr_mask_rds.attr, | ||
1126 | &format_attr_mask_rnid30.attr, | ||
1127 | &format_attr_mask_rnid4.attr, | ||
1128 | &format_attr_mask_dnid.attr, | ||
1129 | &format_attr_mask_mc.attr, | ||
1130 | &format_attr_mask_opc.attr, | ||
1131 | &format_attr_mask_vnw.attr, | ||
1132 | &format_attr_mask0.attr, | ||
1133 | &format_attr_mask1.attr, | ||
1102 | NULL, | 1134 | NULL, |
1103 | }; | 1135 | }; |
1104 | 1136 | ||
@@ -1312,17 +1344,83 @@ static struct intel_uncore_type ivt_uncore_imc = { | |||
1312 | IVT_UNCORE_PCI_COMMON_INIT(), | 1344 | IVT_UNCORE_PCI_COMMON_INIT(), |
1313 | }; | 1345 | }; |
1314 | 1346 | ||
1347 | /* registers in IRP boxes are not properly aligned */ | ||
1348 | static unsigned ivt_uncore_irp_ctls[] = {0xd8, 0xdc, 0xe0, 0xe4}; | ||
1349 | static unsigned ivt_uncore_irp_ctrs[] = {0xa0, 0xb0, 0xb8, 0xc0}; | ||
1350 | |||
1351 | static void ivt_uncore_irp_enable_event(struct intel_uncore_box *box, struct perf_event *event) | ||
1352 | { | ||
1353 | struct pci_dev *pdev = box->pci_dev; | ||
1354 | struct hw_perf_event *hwc = &event->hw; | ||
1355 | |||
1356 | pci_write_config_dword(pdev, ivt_uncore_irp_ctls[hwc->idx], | ||
1357 | hwc->config | SNBEP_PMON_CTL_EN); | ||
1358 | } | ||
1359 | |||
1360 | static void ivt_uncore_irp_disable_event(struct intel_uncore_box *box, struct perf_event *event) | ||
1361 | { | ||
1362 | struct pci_dev *pdev = box->pci_dev; | ||
1363 | struct hw_perf_event *hwc = &event->hw; | ||
1364 | |||
1365 | pci_write_config_dword(pdev, ivt_uncore_irp_ctls[hwc->idx], hwc->config); | ||
1366 | } | ||
1367 | |||
1368 | static u64 ivt_uncore_irp_read_counter(struct intel_uncore_box *box, struct perf_event *event) | ||
1369 | { | ||
1370 | struct pci_dev *pdev = box->pci_dev; | ||
1371 | struct hw_perf_event *hwc = &event->hw; | ||
1372 | u64 count = 0; | ||
1373 | |||
1374 | pci_read_config_dword(pdev, ivt_uncore_irp_ctrs[hwc->idx], (u32 *)&count); | ||
1375 | pci_read_config_dword(pdev, ivt_uncore_irp_ctrs[hwc->idx] + 4, (u32 *)&count + 1); | ||
1376 | |||
1377 | return count; | ||
1378 | } | ||
1379 | |||
1380 | static struct intel_uncore_ops ivt_uncore_irp_ops = { | ||
1381 | .init_box = ivt_uncore_pci_init_box, | ||
1382 | .disable_box = snbep_uncore_pci_disable_box, | ||
1383 | .enable_box = snbep_uncore_pci_enable_box, | ||
1384 | .disable_event = ivt_uncore_irp_disable_event, | ||
1385 | .enable_event = ivt_uncore_irp_enable_event, | ||
1386 | .read_counter = ivt_uncore_irp_read_counter, | ||
1387 | }; | ||
1388 | |||
1389 | static struct intel_uncore_type ivt_uncore_irp = { | ||
1390 | .name = "irp", | ||
1391 | .num_counters = 4, | ||
1392 | .num_boxes = 1, | ||
1393 | .perf_ctr_bits = 48, | ||
1394 | .event_mask = IVT_PMON_RAW_EVENT_MASK, | ||
1395 | .box_ctl = SNBEP_PCI_PMON_BOX_CTL, | ||
1396 | .ops = &ivt_uncore_irp_ops, | ||
1397 | .format_group = &ivt_uncore_format_group, | ||
1398 | }; | ||
1399 | |||
1400 | static struct intel_uncore_ops ivt_uncore_qpi_ops = { | ||
1401 | .init_box = ivt_uncore_pci_init_box, | ||
1402 | .disable_box = snbep_uncore_pci_disable_box, | ||
1403 | .enable_box = snbep_uncore_pci_enable_box, | ||
1404 | .disable_event = snbep_uncore_pci_disable_event, | ||
1405 | .enable_event = snbep_qpi_enable_event, | ||
1406 | .read_counter = snbep_uncore_pci_read_counter, | ||
1407 | .hw_config = snbep_qpi_hw_config, | ||
1408 | .get_constraint = uncore_get_constraint, | ||
1409 | .put_constraint = uncore_put_constraint, | ||
1410 | }; | ||
1411 | |||
1315 | static struct intel_uncore_type ivt_uncore_qpi = { | 1412 | static struct intel_uncore_type ivt_uncore_qpi = { |
1316 | .name = "qpi", | 1413 | .name = "qpi", |
1317 | .num_counters = 4, | 1414 | .num_counters = 4, |
1318 | .num_boxes = 3, | 1415 | .num_boxes = 3, |
1319 | .perf_ctr_bits = 48, | 1416 | .perf_ctr_bits = 48, |
1320 | .perf_ctr = SNBEP_PCI_PMON_CTR0, | 1417 | .perf_ctr = SNBEP_PCI_PMON_CTR0, |
1321 | .event_ctl = SNBEP_PCI_PMON_CTL0, | 1418 | .event_ctl = SNBEP_PCI_PMON_CTL0, |
1322 | .event_mask = IVT_QPI_PCI_PMON_RAW_EVENT_MASK, | 1419 | .event_mask = IVT_QPI_PCI_PMON_RAW_EVENT_MASK, |
1323 | .box_ctl = SNBEP_PCI_PMON_BOX_CTL, | 1420 | .box_ctl = SNBEP_PCI_PMON_BOX_CTL, |
1324 | .ops = &ivt_uncore_pci_ops, | 1421 | .num_shared_regs = 1, |
1325 | .format_group = &ivt_uncore_qpi_format_group, | 1422 | .ops = &ivt_uncore_qpi_ops, |
1423 | .format_group = &ivt_uncore_qpi_format_group, | ||
1326 | }; | 1424 | }; |
1327 | 1425 | ||
1328 | static struct intel_uncore_type ivt_uncore_r2pcie = { | 1426 | static struct intel_uncore_type ivt_uncore_r2pcie = { |
@@ -1346,6 +1444,7 @@ static struct intel_uncore_type ivt_uncore_r3qpi = { | |||
1346 | enum { | 1444 | enum { |
1347 | IVT_PCI_UNCORE_HA, | 1445 | IVT_PCI_UNCORE_HA, |
1348 | IVT_PCI_UNCORE_IMC, | 1446 | IVT_PCI_UNCORE_IMC, |
1447 | IVT_PCI_UNCORE_IRP, | ||
1349 | IVT_PCI_UNCORE_QPI, | 1448 | IVT_PCI_UNCORE_QPI, |
1350 | IVT_PCI_UNCORE_R2PCIE, | 1449 | IVT_PCI_UNCORE_R2PCIE, |
1351 | IVT_PCI_UNCORE_R3QPI, | 1450 | IVT_PCI_UNCORE_R3QPI, |
@@ -1354,6 +1453,7 @@ enum { | |||
1354 | static struct intel_uncore_type *ivt_pci_uncores[] = { | 1453 | static struct intel_uncore_type *ivt_pci_uncores[] = { |
1355 | [IVT_PCI_UNCORE_HA] = &ivt_uncore_ha, | 1454 | [IVT_PCI_UNCORE_HA] = &ivt_uncore_ha, |
1356 | [IVT_PCI_UNCORE_IMC] = &ivt_uncore_imc, | 1455 | [IVT_PCI_UNCORE_IMC] = &ivt_uncore_imc, |
1456 | [IVT_PCI_UNCORE_IRP] = &ivt_uncore_irp, | ||
1357 | [IVT_PCI_UNCORE_QPI] = &ivt_uncore_qpi, | 1457 | [IVT_PCI_UNCORE_QPI] = &ivt_uncore_qpi, |
1358 | [IVT_PCI_UNCORE_R2PCIE] = &ivt_uncore_r2pcie, | 1458 | [IVT_PCI_UNCORE_R2PCIE] = &ivt_uncore_r2pcie, |
1359 | [IVT_PCI_UNCORE_R3QPI] = &ivt_uncore_r3qpi, | 1459 | [IVT_PCI_UNCORE_R3QPI] = &ivt_uncore_r3qpi, |
@@ -1401,6 +1501,10 @@ static DEFINE_PCI_DEVICE_TABLE(ivt_uncore_pci_ids) = { | |||
1401 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xef1), | 1501 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xef1), |
1402 | .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_IMC, 7), | 1502 | .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_IMC, 7), |
1403 | }, | 1503 | }, |
1504 | { /* IRP */ | ||
1505 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe39), | ||
1506 | .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_IRP, 0), | ||
1507 | }, | ||
1404 | { /* QPI0 Port 0 */ | 1508 | { /* QPI0 Port 0 */ |
1405 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe32), | 1509 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe32), |
1406 | .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_QPI, 0), | 1510 | .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_QPI, 0), |
@@ -1429,6 +1533,16 @@ static DEFINE_PCI_DEVICE_TABLE(ivt_uncore_pci_ids) = { | |||
1429 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe3e), | 1533 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe3e), |
1430 | .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_R3QPI, 2), | 1534 | .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_R3QPI, 2), |
1431 | }, | 1535 | }, |
1536 | { /* QPI Port 0 filter */ | ||
1537 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe86), | ||
1538 | .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV, | ||
1539 | SNBEP_PCI_QPI_PORT0_FILTER), | ||
1540 | }, | ||
1541 | { /* QPI Port 0 filter */ | ||
1542 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe96), | ||
1543 | .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV, | ||
1544 | SNBEP_PCI_QPI_PORT1_FILTER), | ||
1545 | }, | ||
1432 | { /* end: all zeroes */ } | 1546 | { /* end: all zeroes */ } |
1433 | }; | 1547 | }; |
1434 | 1548 | ||
diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c index aee6317b902f..06fe3ed8b851 100644 --- a/arch/x86/kernel/cpu/proc.c +++ b/arch/x86/kernel/cpu/proc.c | |||
@@ -11,15 +11,12 @@ static void show_cpuinfo_core(struct seq_file *m, struct cpuinfo_x86 *c, | |||
11 | unsigned int cpu) | 11 | unsigned int cpu) |
12 | { | 12 | { |
13 | #ifdef CONFIG_SMP | 13 | #ifdef CONFIG_SMP |
14 | if (c->x86_max_cores * smp_num_siblings > 1) { | 14 | seq_printf(m, "physical id\t: %d\n", c->phys_proc_id); |
15 | seq_printf(m, "physical id\t: %d\n", c->phys_proc_id); | 15 | seq_printf(m, "siblings\t: %d\n", cpumask_weight(cpu_core_mask(cpu))); |
16 | seq_printf(m, "siblings\t: %d\n", | 16 | seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id); |
17 | cpumask_weight(cpu_core_mask(cpu))); | 17 | seq_printf(m, "cpu cores\t: %d\n", c->booted_cores); |
18 | seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id); | 18 | seq_printf(m, "apicid\t\t: %d\n", c->apicid); |
19 | seq_printf(m, "cpu cores\t: %d\n", c->booted_cores); | 19 | seq_printf(m, "initial apicid\t: %d\n", c->initial_apicid); |
20 | seq_printf(m, "apicid\t\t: %d\n", c->apicid); | ||
21 | seq_printf(m, "initial apicid\t: %d\n", c->initial_apicid); | ||
22 | } | ||
23 | #endif | 20 | #endif |
24 | } | 21 | } |
25 | 22 | ||
diff --git a/arch/x86/kernel/cpu/umc.c b/arch/x86/kernel/cpu/umc.c index 202759a14121..75c5ad5d35cc 100644 --- a/arch/x86/kernel/cpu/umc.c +++ b/arch/x86/kernel/cpu/umc.c | |||
@@ -11,8 +11,8 @@ | |||
11 | static const struct cpu_dev umc_cpu_dev = { | 11 | static const struct cpu_dev umc_cpu_dev = { |
12 | .c_vendor = "UMC", | 12 | .c_vendor = "UMC", |
13 | .c_ident = { "UMC UMC UMC" }, | 13 | .c_ident = { "UMC UMC UMC" }, |
14 | .c_models = { | 14 | .legacy_models = { |
15 | { .vendor = X86_VENDOR_UMC, .family = 4, .model_names = | 15 | { .family = 4, .model_names = |
16 | { | 16 | { |
17 | [1] = "U5D", | 17 | [1] = "U5D", |
18 | [2] = "U5S", | 18 | [2] = "U5S", |
diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c index e0e0841eef45..18677a90d6a3 100644 --- a/arch/x86/kernel/crash.c +++ b/arch/x86/kernel/crash.c | |||
@@ -127,12 +127,12 @@ void native_machine_crash_shutdown(struct pt_regs *regs) | |||
127 | cpu_emergency_vmxoff(); | 127 | cpu_emergency_vmxoff(); |
128 | cpu_emergency_svm_disable(); | 128 | cpu_emergency_svm_disable(); |
129 | 129 | ||
130 | lapic_shutdown(); | ||
131 | #ifdef CONFIG_X86_IO_APIC | 130 | #ifdef CONFIG_X86_IO_APIC |
132 | /* Prevent crash_kexec() from deadlocking on ioapic_lock. */ | 131 | /* Prevent crash_kexec() from deadlocking on ioapic_lock. */ |
133 | ioapic_zap_locks(); | 132 | ioapic_zap_locks(); |
134 | disable_IO_APIC(); | 133 | disable_IO_APIC(); |
135 | #endif | 134 | #endif |
135 | lapic_shutdown(); | ||
136 | #ifdef CONFIG_HPET_TIMER | 136 | #ifdef CONFIG_HPET_TIMER |
137 | hpet_disable(); | 137 | hpet_disable(); |
138 | #endif | 138 | #endif |
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c index 376dc7873447..d35078ea1446 100644 --- a/arch/x86/kernel/devicetree.c +++ b/arch/x86/kernel/devicetree.c | |||
@@ -20,22 +20,13 @@ | |||
20 | #include <asm/hpet.h> | 20 | #include <asm/hpet.h> |
21 | #include <asm/apic.h> | 21 | #include <asm/apic.h> |
22 | #include <asm/pci_x86.h> | 22 | #include <asm/pci_x86.h> |
23 | #include <asm/setup.h> | ||
23 | 24 | ||
24 | __initdata u64 initial_dtb; | 25 | __initdata u64 initial_dtb; |
25 | char __initdata cmd_line[COMMAND_LINE_SIZE]; | 26 | char __initdata cmd_line[COMMAND_LINE_SIZE]; |
26 | 27 | ||
27 | int __initdata of_ioapic; | 28 | int __initdata of_ioapic; |
28 | 29 | ||
29 | unsigned long pci_address_to_pio(phys_addr_t address) | ||
30 | { | ||
31 | /* | ||
32 | * The ioport address can be directly used by inX / outX | ||
33 | */ | ||
34 | BUG_ON(address >= (1 << 16)); | ||
35 | return (unsigned long)address; | ||
36 | } | ||
37 | EXPORT_SYMBOL_GPL(pci_address_to_pio); | ||
38 | |||
39 | void __init early_init_dt_scan_chosen_arch(unsigned long node) | 30 | void __init early_init_dt_scan_chosen_arch(unsigned long node) |
40 | { | 31 | { |
41 | BUG(); | 32 | BUG(); |
@@ -51,15 +42,6 @@ void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) | |||
51 | return __alloc_bootmem(size, align, __pa(MAX_DMA_ADDRESS)); | 42 | return __alloc_bootmem(size, align, __pa(MAX_DMA_ADDRESS)); |
52 | } | 43 | } |
53 | 44 | ||
54 | #ifdef CONFIG_BLK_DEV_INITRD | ||
55 | void __init early_init_dt_setup_initrd_arch(u64 start, u64 end) | ||
56 | { | ||
57 | initrd_start = (unsigned long)__va(start); | ||
58 | initrd_end = (unsigned long)__va(end); | ||
59 | initrd_below_start_ok = 1; | ||
60 | } | ||
61 | #endif | ||
62 | |||
63 | void __init add_dtb(u64 data) | 45 | void __init add_dtb(u64 data) |
64 | { | 46 | { |
65 | initial_dtb = data + offsetof(struct setup_data, data); | 47 | initial_dtb = data + offsetof(struct setup_data, data); |
@@ -105,7 +87,6 @@ struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus) | |||
105 | 87 | ||
106 | static int x86_of_pci_irq_enable(struct pci_dev *dev) | 88 | static int x86_of_pci_irq_enable(struct pci_dev *dev) |
107 | { | 89 | { |
108 | struct of_irq oirq; | ||
109 | u32 virq; | 90 | u32 virq; |
110 | int ret; | 91 | int ret; |
111 | u8 pin; | 92 | u8 pin; |
@@ -116,12 +97,7 @@ static int x86_of_pci_irq_enable(struct pci_dev *dev) | |||
116 | if (!pin) | 97 | if (!pin) |
117 | return 0; | 98 | return 0; |
118 | 99 | ||
119 | ret = of_irq_map_pci(dev, &oirq); | 100 | virq = of_irq_parse_and_map_pci(dev, 0, 0); |
120 | if (ret) | ||
121 | return ret; | ||
122 | |||
123 | virq = irq_create_of_mapping(oirq.controller, oirq.specifier, | ||
124 | oirq.size); | ||
125 | if (virq == 0) | 101 | if (virq == 0) |
126 | return -EINVAL; | 102 | return -EINVAL; |
127 | dev->irq = virq; | 103 | dev->irq = virq; |
@@ -230,7 +206,7 @@ static void __init dtb_apic_setup(void) | |||
230 | static void __init x86_flattree_get_config(void) | 206 | static void __init x86_flattree_get_config(void) |
231 | { | 207 | { |
232 | u32 size, map_len; | 208 | u32 size, map_len; |
233 | void *new_dtb; | 209 | struct boot_param_header *dt; |
234 | 210 | ||
235 | if (!initial_dtb) | 211 | if (!initial_dtb) |
236 | return; | 212 | return; |
@@ -238,24 +214,17 @@ static void __init x86_flattree_get_config(void) | |||
238 | map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK), | 214 | map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK), |
239 | (u64)sizeof(struct boot_param_header)); | 215 | (u64)sizeof(struct boot_param_header)); |
240 | 216 | ||
241 | initial_boot_params = early_memremap(initial_dtb, map_len); | 217 | dt = early_memremap(initial_dtb, map_len); |
242 | size = be32_to_cpu(initial_boot_params->totalsize); | 218 | size = be32_to_cpu(dt->totalsize); |
243 | if (map_len < size) { | 219 | if (map_len < size) { |
244 | early_iounmap(initial_boot_params, map_len); | 220 | early_iounmap(dt, map_len); |
245 | initial_boot_params = early_memremap(initial_dtb, size); | 221 | dt = early_memremap(initial_dtb, size); |
246 | map_len = size; | 222 | map_len = size; |
247 | } | 223 | } |
248 | 224 | ||
249 | new_dtb = alloc_bootmem(size); | 225 | initial_boot_params = dt; |
250 | memcpy(new_dtb, initial_boot_params, size); | 226 | unflatten_and_copy_device_tree(); |
251 | early_iounmap(initial_boot_params, map_len); | 227 | early_iounmap(dt, map_len); |
252 | |||
253 | initial_boot_params = new_dtb; | ||
254 | |||
255 | /* root level address cells */ | ||
256 | of_scan_flat_dt(early_init_dt_scan_root, NULL); | ||
257 | |||
258 | unflatten_device_tree(); | ||
259 | } | 228 | } |
260 | #else | 229 | #else |
261 | static inline void x86_flattree_get_config(void) { } | 230 | static inline void x86_flattree_get_config(void) { } |
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c index deb6421c9e69..d9c12d3022a7 100644 --- a/arch/x86/kernel/dumpstack.c +++ b/arch/x86/kernel/dumpstack.c | |||
@@ -25,12 +25,17 @@ unsigned int code_bytes = 64; | |||
25 | int kstack_depth_to_print = 3 * STACKSLOTS_PER_LINE; | 25 | int kstack_depth_to_print = 3 * STACKSLOTS_PER_LINE; |
26 | static int die_counter; | 26 | static int die_counter; |
27 | 27 | ||
28 | void printk_address(unsigned long address, int reliable) | 28 | static void printk_stack_address(unsigned long address, int reliable) |
29 | { | 29 | { |
30 | pr_cont(" [<%p>] %s%pB\n", | 30 | pr_cont(" [<%p>] %s%pB\n", |
31 | (void *)address, reliable ? "" : "? ", (void *)address); | 31 | (void *)address, reliable ? "" : "? ", (void *)address); |
32 | } | 32 | } |
33 | 33 | ||
34 | void printk_address(unsigned long address) | ||
35 | { | ||
36 | pr_cont(" [<%p>] %pS\n", (void *)address, (void *)address); | ||
37 | } | ||
38 | |||
34 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 39 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
35 | static void | 40 | static void |
36 | print_ftrace_graph_addr(unsigned long addr, void *data, | 41 | print_ftrace_graph_addr(unsigned long addr, void *data, |
@@ -151,7 +156,7 @@ static void print_trace_address(void *data, unsigned long addr, int reliable) | |||
151 | { | 156 | { |
152 | touch_nmi_watchdog(); | 157 | touch_nmi_watchdog(); |
153 | printk(data); | 158 | printk(data); |
154 | printk_address(addr, reliable); | 159 | printk_stack_address(addr, reliable); |
155 | } | 160 | } |
156 | 161 | ||
157 | static const struct stacktrace_ops print_trace_ops = { | 162 | static const struct stacktrace_ops print_trace_ops = { |
@@ -281,7 +286,7 @@ int __kprobes __die(const char *str, struct pt_regs *regs, long err) | |||
281 | #else | 286 | #else |
282 | /* Executive summary in case the oops scrolled away */ | 287 | /* Executive summary in case the oops scrolled away */ |
283 | printk(KERN_ALERT "RIP "); | 288 | printk(KERN_ALERT "RIP "); |
284 | printk_address(regs->ip, 1); | 289 | printk_address(regs->ip); |
285 | printk(" RSP <%016lx>\n", regs->sp); | 290 | printk(" RSP <%016lx>\n", regs->sp); |
286 | #endif | 291 | #endif |
287 | return 0; | 292 | return 0; |
diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c index d15f575a861b..01d1c187c9f9 100644 --- a/arch/x86/kernel/early_printk.c +++ b/arch/x86/kernel/early_printk.c | |||
@@ -14,9 +14,11 @@ | |||
14 | #include <xen/hvc-console.h> | 14 | #include <xen/hvc-console.h> |
15 | #include <asm/pci-direct.h> | 15 | #include <asm/pci-direct.h> |
16 | #include <asm/fixmap.h> | 16 | #include <asm/fixmap.h> |
17 | #include <asm/mrst.h> | 17 | #include <asm/intel-mid.h> |
18 | #include <asm/pgtable.h> | 18 | #include <asm/pgtable.h> |
19 | #include <linux/usb/ehci_def.h> | 19 | #include <linux/usb/ehci_def.h> |
20 | #include <linux/efi.h> | ||
21 | #include <asm/efi.h> | ||
20 | 22 | ||
21 | /* Simple VGA output */ | 23 | /* Simple VGA output */ |
22 | #define VGABASE (__ISA_IO_base + 0xb8000) | 24 | #define VGABASE (__ISA_IO_base + 0xb8000) |
@@ -234,6 +236,11 @@ static int __init setup_early_printk(char *buf) | |||
234 | early_console_register(&early_hsu_console, keep); | 236 | early_console_register(&early_hsu_console, keep); |
235 | } | 237 | } |
236 | #endif | 238 | #endif |
239 | #ifdef CONFIG_EARLY_PRINTK_EFI | ||
240 | if (!strncmp(buf, "efi", 3)) | ||
241 | early_console_register(&early_efi_console, keep); | ||
242 | #endif | ||
243 | |||
237 | buf++; | 244 | buf++; |
238 | } | 245 | } |
239 | return 0; | 246 | return 0; |
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index f0dcb0ceb6a2..51e2988c5728 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S | |||
@@ -362,12 +362,9 @@ END(ret_from_exception) | |||
362 | #ifdef CONFIG_PREEMPT | 362 | #ifdef CONFIG_PREEMPT |
363 | ENTRY(resume_kernel) | 363 | ENTRY(resume_kernel) |
364 | DISABLE_INTERRUPTS(CLBR_ANY) | 364 | DISABLE_INTERRUPTS(CLBR_ANY) |
365 | cmpl $0,TI_preempt_count(%ebp) # non-zero preempt_count ? | ||
366 | jnz restore_all | ||
367 | need_resched: | 365 | need_resched: |
368 | movl TI_flags(%ebp), %ecx # need_resched set ? | 366 | cmpl $0,PER_CPU_VAR(__preempt_count) |
369 | testb $_TIF_NEED_RESCHED, %cl | 367 | jnz restore_all |
370 | jz restore_all | ||
371 | testl $X86_EFLAGS_IF,PT_EFLAGS(%esp) # interrupts off (exception path) ? | 368 | testl $X86_EFLAGS_IF,PT_EFLAGS(%esp) # interrupts off (exception path) ? |
372 | jz restore_all | 369 | jz restore_all |
373 | call preempt_schedule_irq | 370 | call preempt_schedule_irq |
@@ -1247,6 +1244,16 @@ return_to_handler: | |||
1247 | */ | 1244 | */ |
1248 | .pushsection .kprobes.text, "ax" | 1245 | .pushsection .kprobes.text, "ax" |
1249 | 1246 | ||
1247 | #ifdef CONFIG_TRACING | ||
1248 | ENTRY(trace_page_fault) | ||
1249 | RING0_EC_FRAME | ||
1250 | ASM_CLAC | ||
1251 | pushl_cfi $trace_do_page_fault | ||
1252 | jmp error_code | ||
1253 | CFI_ENDPROC | ||
1254 | END(trace_page_fault) | ||
1255 | #endif | ||
1256 | |||
1250 | ENTRY(page_fault) | 1257 | ENTRY(page_fault) |
1251 | RING0_EC_FRAME | 1258 | RING0_EC_FRAME |
1252 | ASM_CLAC | 1259 | ASM_CLAC |
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index b077f4cc225a..e21b0785a85b 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
@@ -1103,10 +1103,8 @@ retint_signal: | |||
1103 | /* Returning to kernel space. Check if we need preemption */ | 1103 | /* Returning to kernel space. Check if we need preemption */ |
1104 | /* rcx: threadinfo. interrupts off. */ | 1104 | /* rcx: threadinfo. interrupts off. */ |
1105 | ENTRY(retint_kernel) | 1105 | ENTRY(retint_kernel) |
1106 | cmpl $0,TI_preempt_count(%rcx) | 1106 | cmpl $0,PER_CPU_VAR(__preempt_count) |
1107 | jnz retint_restore_args | 1107 | jnz retint_restore_args |
1108 | bt $TIF_NEED_RESCHED,TI_flags(%rcx) | ||
1109 | jnc retint_restore_args | ||
1110 | bt $9,EFLAGS-ARGOFFSET(%rsp) /* interrupts off? */ | 1108 | bt $9,EFLAGS-ARGOFFSET(%rsp) /* interrupts off? */ |
1111 | jnc retint_restore_args | 1109 | jnc retint_restore_args |
1112 | call preempt_schedule_irq | 1110 | call preempt_schedule_irq |
@@ -1280,6 +1278,17 @@ ENTRY(\sym) | |||
1280 | END(\sym) | 1278 | END(\sym) |
1281 | .endm | 1279 | .endm |
1282 | 1280 | ||
1281 | #ifdef CONFIG_TRACING | ||
1282 | .macro trace_errorentry sym do_sym | ||
1283 | errorentry trace(\sym) trace(\do_sym) | ||
1284 | errorentry \sym \do_sym | ||
1285 | .endm | ||
1286 | #else | ||
1287 | .macro trace_errorentry sym do_sym | ||
1288 | errorentry \sym \do_sym | ||
1289 | .endm | ||
1290 | #endif | ||
1291 | |||
1283 | /* error code is on the stack already */ | 1292 | /* error code is on the stack already */ |
1284 | .macro paranoiderrorentry sym do_sym | 1293 | .macro paranoiderrorentry sym do_sym |
1285 | ENTRY(\sym) | 1294 | ENTRY(\sym) |
@@ -1342,7 +1351,7 @@ bad_gs: | |||
1342 | .previous | 1351 | .previous |
1343 | 1352 | ||
1344 | /* Call softirq on interrupt stack. Interrupts are off. */ | 1353 | /* Call softirq on interrupt stack. Interrupts are off. */ |
1345 | ENTRY(call_softirq) | 1354 | ENTRY(do_softirq_own_stack) |
1346 | CFI_STARTPROC | 1355 | CFI_STARTPROC |
1347 | pushq_cfi %rbp | 1356 | pushq_cfi %rbp |
1348 | CFI_REL_OFFSET rbp,0 | 1357 | CFI_REL_OFFSET rbp,0 |
@@ -1359,7 +1368,7 @@ ENTRY(call_softirq) | |||
1359 | decl PER_CPU_VAR(irq_count) | 1368 | decl PER_CPU_VAR(irq_count) |
1360 | ret | 1369 | ret |
1361 | CFI_ENDPROC | 1370 | CFI_ENDPROC |
1362 | END(call_softirq) | 1371 | END(do_softirq_own_stack) |
1363 | 1372 | ||
1364 | #ifdef CONFIG_XEN | 1373 | #ifdef CONFIG_XEN |
1365 | zeroentry xen_hypervisor_callback xen_do_hypervisor_callback | 1374 | zeroentry xen_hypervisor_callback xen_do_hypervisor_callback |
@@ -1482,7 +1491,7 @@ zeroentry xen_int3 do_int3 | |||
1482 | errorentry xen_stack_segment do_stack_segment | 1491 | errorentry xen_stack_segment do_stack_segment |
1483 | #endif | 1492 | #endif |
1484 | errorentry general_protection do_general_protection | 1493 | errorentry general_protection do_general_protection |
1485 | errorentry page_fault do_page_fault | 1494 | trace_errorentry page_fault do_page_fault |
1486 | #ifdef CONFIG_KVM_GUEST | 1495 | #ifdef CONFIG_KVM_GUEST |
1487 | errorentry async_page_fault do_async_page_fault | 1496 | errorentry async_page_fault do_async_page_fault |
1488 | #endif | 1497 | #endif |
diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c index 06f87bece92a..c61a14a4a310 100644 --- a/arch/x86/kernel/head32.c +++ b/arch/x86/kernel/head32.c | |||
@@ -35,8 +35,8 @@ asmlinkage void __init i386_start_kernel(void) | |||
35 | 35 | ||
36 | /* Call the subarch specific early setup function */ | 36 | /* Call the subarch specific early setup function */ |
37 | switch (boot_params.hdr.hardware_subarch) { | 37 | switch (boot_params.hdr.hardware_subarch) { |
38 | case X86_SUBARCH_MRST: | 38 | case X86_SUBARCH_INTEL_MID: |
39 | x86_mrst_early_setup(); | 39 | x86_intel_mid_early_setup(); |
40 | break; | 40 | break; |
41 | case X86_SUBARCH_CE4100: | 41 | case X86_SUBARCH_CE4100: |
42 | x86_ce4100_early_setup(); | 42 | x86_ce4100_early_setup(); |
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index 1be8e43b669e..85126ccbdf6b 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c | |||
@@ -162,7 +162,7 @@ asmlinkage void __init x86_64_start_kernel(char * real_mode_data) | |||
162 | clear_bss(); | 162 | clear_bss(); |
163 | 163 | ||
164 | for (i = 0; i < NUM_EXCEPTION_VECTORS; i++) | 164 | for (i = 0; i < NUM_EXCEPTION_VECTORS; i++) |
165 | set_intr_gate(i, &early_idt_handlers[i]); | 165 | set_intr_gate(i, early_idt_handlers[i]); |
166 | load_idt((const struct desc_ptr *)&idt_descr); | 166 | load_idt((const struct desc_ptr *)&idt_descr); |
167 | 167 | ||
168 | copy_bootdata(__va(real_mode_data)); | 168 | copy_bootdata(__va(real_mode_data)); |
diff --git a/arch/x86/kernel/i386_ksyms_32.c b/arch/x86/kernel/i386_ksyms_32.c index 0fa69127209a..05fd74f537d6 100644 --- a/arch/x86/kernel/i386_ksyms_32.c +++ b/arch/x86/kernel/i386_ksyms_32.c | |||
@@ -37,3 +37,10 @@ EXPORT_SYMBOL(strstr); | |||
37 | 37 | ||
38 | EXPORT_SYMBOL(csum_partial); | 38 | EXPORT_SYMBOL(csum_partial); |
39 | EXPORT_SYMBOL(empty_zero_page); | 39 | EXPORT_SYMBOL(empty_zero_page); |
40 | |||
41 | #ifdef CONFIG_PREEMPT | ||
42 | EXPORT_SYMBOL(___preempt_schedule); | ||
43 | #ifdef CONFIG_CONTEXT_TRACKING | ||
44 | EXPORT_SYMBOL(___preempt_schedule_context); | ||
45 | #endif | ||
46 | #endif | ||
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index 5d576ab34403..e8368c6dd2a2 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c | |||
@@ -100,7 +100,7 @@ void unlazy_fpu(struct task_struct *tsk) | |||
100 | __save_init_fpu(tsk); | 100 | __save_init_fpu(tsk); |
101 | __thread_fpu_end(tsk); | 101 | __thread_fpu_end(tsk); |
102 | } else | 102 | } else |
103 | tsk->fpu_counter = 0; | 103 | tsk->thread.fpu_counter = 0; |
104 | preempt_enable(); | 104 | preempt_enable(); |
105 | } | 105 | } |
106 | EXPORT_SYMBOL(unlazy_fpu); | 106 | EXPORT_SYMBOL(unlazy_fpu); |
diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c index 9a5c460404dc..2e977b5d61dd 100644 --- a/arch/x86/kernel/i8259.c +++ b/arch/x86/kernel/i8259.c | |||
@@ -312,8 +312,7 @@ static void init_8259A(int auto_eoi) | |||
312 | */ | 312 | */ |
313 | outb_pic(0x11, PIC_MASTER_CMD); /* ICW1: select 8259A-1 init */ | 313 | outb_pic(0x11, PIC_MASTER_CMD); /* ICW1: select 8259A-1 init */ |
314 | 314 | ||
315 | /* ICW2: 8259A-1 IR0-7 mapped to 0x30-0x37 on x86-64, | 315 | /* ICW2: 8259A-1 IR0-7 mapped to 0x30-0x37 */ |
316 | to 0x20-0x27 on i386 */ | ||
317 | outb_pic(IRQ0_VECTOR, PIC_MASTER_IMR); | 316 | outb_pic(IRQ0_VECTOR, PIC_MASTER_IMR); |
318 | 317 | ||
319 | /* 8259A-1 (the master) has a slave on IR2 */ | 318 | /* 8259A-1 (the master) has a slave on IR2 */ |
diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c index 4186755f1d7c..d7fcbedc9c43 100644 --- a/arch/x86/kernel/irq_32.c +++ b/arch/x86/kernel/irq_32.c | |||
@@ -100,9 +100,6 @@ execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq) | |||
100 | irqctx->tinfo.task = curctx->tinfo.task; | 100 | irqctx->tinfo.task = curctx->tinfo.task; |
101 | irqctx->tinfo.previous_esp = current_stack_pointer; | 101 | irqctx->tinfo.previous_esp = current_stack_pointer; |
102 | 102 | ||
103 | /* Copy the preempt_count so that the [soft]irq checks work. */ | ||
104 | irqctx->tinfo.preempt_count = curctx->tinfo.preempt_count; | ||
105 | |||
106 | if (unlikely(overflow)) | 103 | if (unlikely(overflow)) |
107 | call_on_stack(print_stack_overflow, isp); | 104 | call_on_stack(print_stack_overflow, isp); |
108 | 105 | ||
@@ -131,7 +128,6 @@ void irq_ctx_init(int cpu) | |||
131 | THREAD_SIZE_ORDER)); | 128 | THREAD_SIZE_ORDER)); |
132 | memset(&irqctx->tinfo, 0, sizeof(struct thread_info)); | 129 | memset(&irqctx->tinfo, 0, sizeof(struct thread_info)); |
133 | irqctx->tinfo.cpu = cpu; | 130 | irqctx->tinfo.cpu = cpu; |
134 | irqctx->tinfo.preempt_count = HARDIRQ_OFFSET; | ||
135 | irqctx->tinfo.addr_limit = MAKE_MM_SEG(0); | 131 | irqctx->tinfo.addr_limit = MAKE_MM_SEG(0); |
136 | 132 | ||
137 | per_cpu(hardirq_ctx, cpu) = irqctx; | 133 | per_cpu(hardirq_ctx, cpu) = irqctx; |
@@ -149,35 +145,21 @@ void irq_ctx_init(int cpu) | |||
149 | cpu, per_cpu(hardirq_ctx, cpu), per_cpu(softirq_ctx, cpu)); | 145 | cpu, per_cpu(hardirq_ctx, cpu), per_cpu(softirq_ctx, cpu)); |
150 | } | 146 | } |
151 | 147 | ||
152 | asmlinkage void do_softirq(void) | 148 | void do_softirq_own_stack(void) |
153 | { | 149 | { |
154 | unsigned long flags; | ||
155 | struct thread_info *curctx; | 150 | struct thread_info *curctx; |
156 | union irq_ctx *irqctx; | 151 | union irq_ctx *irqctx; |
157 | u32 *isp; | 152 | u32 *isp; |
158 | 153 | ||
159 | if (in_interrupt()) | 154 | curctx = current_thread_info(); |
160 | return; | 155 | irqctx = __this_cpu_read(softirq_ctx); |
161 | 156 | irqctx->tinfo.task = curctx->task; | |
162 | local_irq_save(flags); | 157 | irqctx->tinfo.previous_esp = current_stack_pointer; |
163 | |||
164 | if (local_softirq_pending()) { | ||
165 | curctx = current_thread_info(); | ||
166 | irqctx = __this_cpu_read(softirq_ctx); | ||
167 | irqctx->tinfo.task = curctx->task; | ||
168 | irqctx->tinfo.previous_esp = current_stack_pointer; | ||
169 | |||
170 | /* build the stack frame on the softirq stack */ | ||
171 | isp = (u32 *) ((char *)irqctx + sizeof(*irqctx)); | ||
172 | 158 | ||
173 | call_on_stack(__do_softirq, isp); | 159 | /* build the stack frame on the softirq stack */ |
174 | /* | 160 | isp = (u32 *) ((char *)irqctx + sizeof(*irqctx)); |
175 | * Shouldn't happen, we returned above if in_interrupt(): | ||
176 | */ | ||
177 | WARN_ON_ONCE(softirq_count()); | ||
178 | } | ||
179 | 161 | ||
180 | local_irq_restore(flags); | 162 | call_on_stack(__do_softirq, isp); |
181 | } | 163 | } |
182 | 164 | ||
183 | bool handle_irq(unsigned irq, struct pt_regs *regs) | 165 | bool handle_irq(unsigned irq, struct pt_regs *regs) |
diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c index d04d3ecded62..4d1c746892eb 100644 --- a/arch/x86/kernel/irq_64.c +++ b/arch/x86/kernel/irq_64.c | |||
@@ -87,24 +87,3 @@ bool handle_irq(unsigned irq, struct pt_regs *regs) | |||
87 | generic_handle_irq_desc(irq, desc); | 87 | generic_handle_irq_desc(irq, desc); |
88 | return true; | 88 | return true; |
89 | } | 89 | } |
90 | |||
91 | |||
92 | extern void call_softirq(void); | ||
93 | |||
94 | asmlinkage void do_softirq(void) | ||
95 | { | ||
96 | __u32 pending; | ||
97 | unsigned long flags; | ||
98 | |||
99 | if (in_interrupt()) | ||
100 | return; | ||
101 | |||
102 | local_irq_save(flags); | ||
103 | pending = local_softirq_pending(); | ||
104 | /* Switch to interrupt stack */ | ||
105 | if (pending) { | ||
106 | call_softirq(); | ||
107 | WARN_ON_ONCE(softirq_count()); | ||
108 | } | ||
109 | local_irq_restore(flags); | ||
110 | } | ||
diff --git a/arch/x86/kernel/jump_label.c b/arch/x86/kernel/jump_label.c index ee11b7dfbfbb..26d5a55a2736 100644 --- a/arch/x86/kernel/jump_label.c +++ b/arch/x86/kernel/jump_label.c | |||
@@ -42,15 +42,27 @@ static void __jump_label_transform(struct jump_entry *entry, | |||
42 | int init) | 42 | int init) |
43 | { | 43 | { |
44 | union jump_code_union code; | 44 | union jump_code_union code; |
45 | const unsigned char default_nop[] = { STATIC_KEY_INIT_NOP }; | ||
45 | const unsigned char *ideal_nop = ideal_nops[NOP_ATOMIC5]; | 46 | const unsigned char *ideal_nop = ideal_nops[NOP_ATOMIC5]; |
46 | 47 | ||
47 | if (type == JUMP_LABEL_ENABLE) { | 48 | if (type == JUMP_LABEL_ENABLE) { |
48 | /* | 49 | if (init) { |
49 | * We are enabling this jump label. If it is not a nop | 50 | /* |
50 | * then something must have gone wrong. | 51 | * Jump label is enabled for the first time. |
51 | */ | 52 | * So we expect a default_nop... |
52 | if (unlikely(memcmp((void *)entry->code, ideal_nop, 5) != 0)) | 53 | */ |
53 | bug_at((void *)entry->code, __LINE__); | 54 | if (unlikely(memcmp((void *)entry->code, default_nop, 5) |
55 | != 0)) | ||
56 | bug_at((void *)entry->code, __LINE__); | ||
57 | } else { | ||
58 | /* | ||
59 | * ...otherwise expect an ideal_nop. Otherwise | ||
60 | * something went horribly wrong. | ||
61 | */ | ||
62 | if (unlikely(memcmp((void *)entry->code, ideal_nop, 5) | ||
63 | != 0)) | ||
64 | bug_at((void *)entry->code, __LINE__); | ||
65 | } | ||
54 | 66 | ||
55 | code.jump = 0xe9; | 67 | code.jump = 0xe9; |
56 | code.offset = entry->target - | 68 | code.offset = entry->target - |
@@ -63,7 +75,6 @@ static void __jump_label_transform(struct jump_entry *entry, | |||
63 | * are converting the default nop to the ideal nop. | 75 | * are converting the default nop to the ideal nop. |
64 | */ | 76 | */ |
65 | if (init) { | 77 | if (init) { |
66 | const unsigned char default_nop[] = { STATIC_KEY_INIT_NOP }; | ||
67 | if (unlikely(memcmp((void *)entry->code, default_nop, 5) != 0)) | 78 | if (unlikely(memcmp((void *)entry->code, default_nop, 5) != 0)) |
68 | bug_at((void *)entry->code, __LINE__); | 79 | bug_at((void *)entry->code, __LINE__); |
69 | } else { | 80 | } else { |
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index 697b93af02dd..6dd802c6d780 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c | |||
@@ -464,7 +464,7 @@ static struct notifier_block kvm_cpu_notifier = { | |||
464 | 464 | ||
465 | static void __init kvm_apf_trap_init(void) | 465 | static void __init kvm_apf_trap_init(void) |
466 | { | 466 | { |
467 | set_intr_gate(14, &async_page_fault); | 467 | set_intr_gate(14, async_page_fault); |
468 | } | 468 | } |
469 | 469 | ||
470 | void __init kvm_guest_init(void) | 470 | void __init kvm_guest_init(void) |
@@ -609,7 +609,7 @@ static struct dentry *d_kvm_debug; | |||
609 | 609 | ||
610 | struct dentry *kvm_init_debugfs(void) | 610 | struct dentry *kvm_init_debugfs(void) |
611 | { | 611 | { |
612 | d_kvm_debug = debugfs_create_dir("kvm", NULL); | 612 | d_kvm_debug = debugfs_create_dir("kvm-guest", NULL); |
613 | if (!d_kvm_debug) | 613 | if (!d_kvm_debug) |
614 | printk(KERN_WARNING "Could not create 'kvm' debugfs directory\n"); | 614 | printk(KERN_WARNING "Could not create 'kvm' debugfs directory\n"); |
615 | 615 | ||
@@ -775,11 +775,22 @@ void __init kvm_spinlock_init(void) | |||
775 | if (!kvm_para_has_feature(KVM_FEATURE_PV_UNHALT)) | 775 | if (!kvm_para_has_feature(KVM_FEATURE_PV_UNHALT)) |
776 | return; | 776 | return; |
777 | 777 | ||
778 | printk(KERN_INFO "KVM setup paravirtual spinlock\n"); | 778 | pv_lock_ops.lock_spinning = PV_CALLEE_SAVE(kvm_lock_spinning); |
779 | pv_lock_ops.unlock_kick = kvm_unlock_kick; | ||
780 | } | ||
781 | |||
782 | static __init int kvm_spinlock_init_jump(void) | ||
783 | { | ||
784 | if (!kvm_para_available()) | ||
785 | return 0; | ||
786 | if (!kvm_para_has_feature(KVM_FEATURE_PV_UNHALT)) | ||
787 | return 0; | ||
779 | 788 | ||
780 | static_key_slow_inc(¶virt_ticketlocks_enabled); | 789 | static_key_slow_inc(¶virt_ticketlocks_enabled); |
790 | printk(KERN_INFO "KVM setup paravirtual spinlock\n"); | ||
781 | 791 | ||
782 | pv_lock_ops.lock_spinning = PV_CALLEE_SAVE(kvm_lock_spinning); | 792 | return 0; |
783 | pv_lock_ops.unlock_kick = kvm_unlock_kick; | ||
784 | } | 793 | } |
794 | early_initcall(kvm_spinlock_init_jump); | ||
795 | |||
785 | #endif /* CONFIG_PARAVIRT_SPINLOCKS */ | 796 | #endif /* CONFIG_PARAVIRT_SPINLOCKS */ |
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index af99f71aeb7f..c3d4cc972eca 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c | |||
@@ -431,7 +431,7 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device, | |||
431 | snprintf(fw_name, sizeof(fw_name), "amd-ucode/microcode_amd_fam%.2xh.bin", c->x86); | 431 | snprintf(fw_name, sizeof(fw_name), "amd-ucode/microcode_amd_fam%.2xh.bin", c->x86); |
432 | 432 | ||
433 | if (request_firmware(&fw, (const char *)fw_name, device)) { | 433 | if (request_firmware(&fw, (const char *)fw_name, device)) { |
434 | pr_err("failed to load file %s\n", fw_name); | 434 | pr_debug("failed to load file %s\n", fw_name); |
435 | goto out; | 435 | goto out; |
436 | } | 436 | } |
437 | 437 | ||
diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c index 216a4d754b0c..18be189368bb 100644 --- a/arch/x86/kernel/module.c +++ b/arch/x86/kernel/module.c | |||
@@ -49,7 +49,7 @@ void *module_alloc(unsigned long size) | |||
49 | return NULL; | 49 | return NULL; |
50 | return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END, | 50 | return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END, |
51 | GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL_EXEC, | 51 | GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL_EXEC, |
52 | -1, __builtin_return_address(0)); | 52 | NUMA_NO_NODE, __builtin_return_address(0)); |
53 | } | 53 | } |
54 | 54 | ||
55 | #ifdef CONFIG_X86_32 | 55 | #ifdef CONFIG_X86_32 |
diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c index 88458faea2f8..05266b5aae22 100644 --- a/arch/x86/kernel/msr.c +++ b/arch/x86/kernel/msr.c | |||
@@ -46,7 +46,7 @@ static struct class *msr_class; | |||
46 | static loff_t msr_seek(struct file *file, loff_t offset, int orig) | 46 | static loff_t msr_seek(struct file *file, loff_t offset, int orig) |
47 | { | 47 | { |
48 | loff_t ret; | 48 | loff_t ret; |
49 | struct inode *inode = file->f_mapping->host; | 49 | struct inode *inode = file_inode(file); |
50 | 50 | ||
51 | mutex_lock(&inode->i_mutex); | 51 | mutex_lock(&inode->i_mutex); |
52 | switch (orig) { | 52 | switch (orig) { |
diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c index ba77ebc2c353..6fcb49ce50a1 100644 --- a/arch/x86/kernel/nmi.c +++ b/arch/x86/kernel/nmi.c | |||
@@ -113,10 +113,10 @@ static int __kprobes nmi_handle(unsigned int type, struct pt_regs *regs, bool b2 | |||
113 | u64 before, delta, whole_msecs; | 113 | u64 before, delta, whole_msecs; |
114 | int remainder_ns, decimal_msecs, thishandled; | 114 | int remainder_ns, decimal_msecs, thishandled; |
115 | 115 | ||
116 | before = local_clock(); | 116 | before = sched_clock(); |
117 | thishandled = a->handler(type, regs); | 117 | thishandled = a->handler(type, regs); |
118 | handled += thishandled; | 118 | handled += thishandled; |
119 | delta = local_clock() - before; | 119 | delta = sched_clock() - before; |
120 | trace_nmi_handler(a->handler, (int)delta, thishandled); | 120 | trace_nmi_handler(a->handler, (int)delta, thishandled); |
121 | 121 | ||
122 | if (delta < nmi_longest_ns) | 122 | if (delta < nmi_longest_ns) |
diff --git a/arch/x86/kernel/preempt.S b/arch/x86/kernel/preempt.S new file mode 100644 index 000000000000..ca7f0d58a87d --- /dev/null +++ b/arch/x86/kernel/preempt.S | |||
@@ -0,0 +1,25 @@ | |||
1 | |||
2 | #include <linux/linkage.h> | ||
3 | #include <asm/dwarf2.h> | ||
4 | #include <asm/asm.h> | ||
5 | #include <asm/calling.h> | ||
6 | |||
7 | ENTRY(___preempt_schedule) | ||
8 | CFI_STARTPROC | ||
9 | SAVE_ALL | ||
10 | call preempt_schedule | ||
11 | RESTORE_ALL | ||
12 | ret | ||
13 | CFI_ENDPROC | ||
14 | |||
15 | #ifdef CONFIG_CONTEXT_TRACKING | ||
16 | |||
17 | ENTRY(___preempt_schedule_context) | ||
18 | CFI_STARTPROC | ||
19 | SAVE_ALL | ||
20 | call preempt_schedule_context | ||
21 | RESTORE_ALL | ||
22 | ret | ||
23 | CFI_ENDPROC | ||
24 | |||
25 | #endif | ||
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index c83516be1052..3fb8d95ab8b5 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c | |||
@@ -391,9 +391,9 @@ static void amd_e400_idle(void) | |||
391 | * The switch back from broadcast mode needs to be | 391 | * The switch back from broadcast mode needs to be |
392 | * called with interrupts disabled. | 392 | * called with interrupts disabled. |
393 | */ | 393 | */ |
394 | local_irq_disable(); | 394 | local_irq_disable(); |
395 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu); | 395 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu); |
396 | local_irq_enable(); | 396 | local_irq_enable(); |
397 | } else | 397 | } else |
398 | default_idle(); | 398 | default_idle(); |
399 | } | 399 | } |
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 884f98f69354..6f1236c29c4b 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c | |||
@@ -153,7 +153,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
153 | childregs->orig_ax = -1; | 153 | childregs->orig_ax = -1; |
154 | childregs->cs = __KERNEL_CS | get_kernel_rpl(); | 154 | childregs->cs = __KERNEL_CS | get_kernel_rpl(); |
155 | childregs->flags = X86_EFLAGS_IF | X86_EFLAGS_FIXED; | 155 | childregs->flags = X86_EFLAGS_IF | X86_EFLAGS_FIXED; |
156 | p->fpu_counter = 0; | 156 | p->thread.fpu_counter = 0; |
157 | p->thread.io_bitmap_ptr = NULL; | 157 | p->thread.io_bitmap_ptr = NULL; |
158 | memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); | 158 | memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); |
159 | return 0; | 159 | return 0; |
@@ -166,7 +166,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
166 | p->thread.ip = (unsigned long) ret_from_fork; | 166 | p->thread.ip = (unsigned long) ret_from_fork; |
167 | task_user_gs(p) = get_user_gs(current_pt_regs()); | 167 | task_user_gs(p) = get_user_gs(current_pt_regs()); |
168 | 168 | ||
169 | p->fpu_counter = 0; | 169 | p->thread.fpu_counter = 0; |
170 | p->thread.io_bitmap_ptr = NULL; | 170 | p->thread.io_bitmap_ptr = NULL; |
171 | tsk = current; | 171 | tsk = current; |
172 | err = -ENOMEM; | 172 | err = -ENOMEM; |
@@ -292,6 +292,14 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) | |||
292 | set_iopl_mask(next->iopl); | 292 | set_iopl_mask(next->iopl); |
293 | 293 | ||
294 | /* | 294 | /* |
295 | * If it were not for PREEMPT_ACTIVE we could guarantee that the | ||
296 | * preempt_count of all tasks was equal here and this would not be | ||
297 | * needed. | ||
298 | */ | ||
299 | task_thread_info(prev_p)->saved_preempt_count = this_cpu_read(__preempt_count); | ||
300 | this_cpu_write(__preempt_count, task_thread_info(next_p)->saved_preempt_count); | ||
301 | |||
302 | /* | ||
295 | * Now maybe handle debug registers and/or IO bitmaps | 303 | * Now maybe handle debug registers and/or IO bitmaps |
296 | */ | 304 | */ |
297 | if (unlikely(task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV || | 305 | if (unlikely(task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV || |
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index bb1dc51bab05..9c0280f93d05 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
@@ -63,7 +63,7 @@ void __show_regs(struct pt_regs *regs, int all) | |||
63 | unsigned int ds, cs, es; | 63 | unsigned int ds, cs, es; |
64 | 64 | ||
65 | printk(KERN_DEFAULT "RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip); | 65 | printk(KERN_DEFAULT "RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip); |
66 | printk_address(regs->ip, 1); | 66 | printk_address(regs->ip); |
67 | printk(KERN_DEFAULT "RSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss, | 67 | printk(KERN_DEFAULT "RSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss, |
68 | regs->sp, regs->flags); | 68 | regs->sp, regs->flags); |
69 | printk(KERN_DEFAULT "RAX: %016lx RBX: %016lx RCX: %016lx\n", | 69 | printk(KERN_DEFAULT "RAX: %016lx RBX: %016lx RCX: %016lx\n", |
@@ -163,7 +163,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
163 | p->thread.sp = (unsigned long) childregs; | 163 | p->thread.sp = (unsigned long) childregs; |
164 | p->thread.usersp = me->thread.usersp; | 164 | p->thread.usersp = me->thread.usersp; |
165 | set_tsk_thread_flag(p, TIF_FORK); | 165 | set_tsk_thread_flag(p, TIF_FORK); |
166 | p->fpu_counter = 0; | 166 | p->thread.fpu_counter = 0; |
167 | p->thread.io_bitmap_ptr = NULL; | 167 | p->thread.io_bitmap_ptr = NULL; |
168 | 168 | ||
169 | savesegment(gs, p->thread.gsindex); | 169 | savesegment(gs, p->thread.gsindex); |
@@ -363,6 +363,14 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) | |||
363 | this_cpu_write(old_rsp, next->usersp); | 363 | this_cpu_write(old_rsp, next->usersp); |
364 | this_cpu_write(current_task, next_p); | 364 | this_cpu_write(current_task, next_p); |
365 | 365 | ||
366 | /* | ||
367 | * If it were not for PREEMPT_ACTIVE we could guarantee that the | ||
368 | * preempt_count of all tasks was equal here and this would not be | ||
369 | * needed. | ||
370 | */ | ||
371 | task_thread_info(prev_p)->saved_preempt_count = this_cpu_read(__preempt_count); | ||
372 | this_cpu_write(__preempt_count, task_thread_info(next_p)->saved_preempt_count); | ||
373 | |||
366 | this_cpu_write(kernel_stack, | 374 | this_cpu_write(kernel_stack, |
367 | (unsigned long)task_stack_page(next_p) + | 375 | (unsigned long)task_stack_page(next_p) + |
368 | THREAD_SIZE - KERNEL_STACK_OFFSET); | 376 | THREAD_SIZE - KERNEL_STACK_OFFSET); |
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 7e920bff99a3..da3c599584a3 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c | |||
@@ -61,7 +61,7 @@ static int __init set_bios_reboot(const struct dmi_system_id *d) | |||
61 | if (reboot_type != BOOT_BIOS) { | 61 | if (reboot_type != BOOT_BIOS) { |
62 | reboot_type = BOOT_BIOS; | 62 | reboot_type = BOOT_BIOS; |
63 | pr_info("%s series board detected. Selecting %s-method for reboots.\n", | 63 | pr_info("%s series board detected. Selecting %s-method for reboots.\n", |
64 | "BIOS", d->ident); | 64 | d->ident, "BIOS"); |
65 | } | 65 | } |
66 | return 0; | 66 | return 0; |
67 | } | 67 | } |
@@ -117,7 +117,7 @@ static int __init set_pci_reboot(const struct dmi_system_id *d) | |||
117 | if (reboot_type != BOOT_CF9) { | 117 | if (reboot_type != BOOT_CF9) { |
118 | reboot_type = BOOT_CF9; | 118 | reboot_type = BOOT_CF9; |
119 | pr_info("%s series board detected. Selecting %s-method for reboots.\n", | 119 | pr_info("%s series board detected. Selecting %s-method for reboots.\n", |
120 | "PCI", d->ident); | 120 | d->ident, "PCI"); |
121 | } | 121 | } |
122 | return 0; | 122 | return 0; |
123 | } | 123 | } |
@@ -127,7 +127,7 @@ static int __init set_kbd_reboot(const struct dmi_system_id *d) | |||
127 | if (reboot_type != BOOT_KBD) { | 127 | if (reboot_type != BOOT_KBD) { |
128 | reboot_type = BOOT_KBD; | 128 | reboot_type = BOOT_KBD; |
129 | pr_info("%s series board detected. Selecting %s-method for reboot.\n", | 129 | pr_info("%s series board detected. Selecting %s-method for reboot.\n", |
130 | "KBD", d->ident); | 130 | d->ident, "KBD"); |
131 | } | 131 | } |
132 | return 0; | 132 | return 0; |
133 | } | 133 | } |
@@ -136,252 +136,256 @@ static int __init set_kbd_reboot(const struct dmi_system_id *d) | |||
136 | * This is a single dmi_table handling all reboot quirks. | 136 | * This is a single dmi_table handling all reboot quirks. |
137 | */ | 137 | */ |
138 | static struct dmi_system_id __initdata reboot_dmi_table[] = { | 138 | static struct dmi_system_id __initdata reboot_dmi_table[] = { |
139 | { /* Handle problems with rebooting on Dell E520's */ | 139 | |
140 | .callback = set_bios_reboot, | 140 | /* Acer */ |
141 | .ident = "Dell E520", | 141 | { /* Handle reboot issue on Acer Aspire one */ |
142 | .callback = set_kbd_reboot, | ||
143 | .ident = "Acer Aspire One A110", | ||
142 | .matches = { | 144 | .matches = { |
143 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | 145 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
144 | DMI_MATCH(DMI_PRODUCT_NAME, "Dell DM061"), | 146 | DMI_MATCH(DMI_PRODUCT_NAME, "AOA110"), |
145 | }, | 147 | }, |
146 | }, | 148 | }, |
147 | { /* Handle problems with rebooting on Dell 1300's */ | 149 | |
148 | .callback = set_bios_reboot, | 150 | /* Apple */ |
149 | .ident = "Dell PowerEdge 1300", | 151 | { /* Handle problems with rebooting on Apple MacBook5 */ |
152 | .callback = set_pci_reboot, | ||
153 | .ident = "Apple MacBook5", | ||
150 | .matches = { | 154 | .matches = { |
151 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), | 155 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), |
152 | DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1300/"), | 156 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5"), |
153 | }, | 157 | }, |
154 | }, | 158 | }, |
155 | { /* Handle problems with rebooting on Dell 300's */ | 159 | { /* Handle problems with rebooting on Apple MacBookPro5 */ |
156 | .callback = set_bios_reboot, | 160 | .callback = set_pci_reboot, |
157 | .ident = "Dell PowerEdge 300", | 161 | .ident = "Apple MacBookPro5", |
158 | .matches = { | 162 | .matches = { |
159 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), | 163 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), |
160 | DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 300/"), | 164 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5"), |
161 | }, | 165 | }, |
162 | }, | 166 | }, |
163 | { /* Handle problems with rebooting on Dell Optiplex 745's SFF */ | 167 | { /* Handle problems with rebooting on Apple Macmini3,1 */ |
164 | .callback = set_bios_reboot, | 168 | .callback = set_pci_reboot, |
165 | .ident = "Dell OptiPlex 745", | 169 | .ident = "Apple Macmini3,1", |
166 | .matches = { | 170 | .matches = { |
167 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | 171 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), |
168 | DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"), | 172 | DMI_MATCH(DMI_PRODUCT_NAME, "Macmini3,1"), |
169 | }, | 173 | }, |
170 | }, | 174 | }, |
171 | { /* Handle problems with rebooting on Dell Optiplex 745's DFF */ | 175 | { /* Handle problems with rebooting on the iMac9,1. */ |
172 | .callback = set_bios_reboot, | 176 | .callback = set_pci_reboot, |
173 | .ident = "Dell OptiPlex 745", | 177 | .ident = "Apple iMac9,1", |
174 | .matches = { | 178 | .matches = { |
175 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | 179 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), |
176 | DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"), | 180 | DMI_MATCH(DMI_PRODUCT_NAME, "iMac9,1"), |
177 | DMI_MATCH(DMI_BOARD_NAME, "0MM599"), | ||
178 | }, | 181 | }, |
179 | }, | 182 | }, |
180 | { /* Handle problems with rebooting on Dell Optiplex 745 with 0KW626 */ | 183 | |
184 | /* ASUS */ | ||
185 | { /* Handle problems with rebooting on ASUS P4S800 */ | ||
181 | .callback = set_bios_reboot, | 186 | .callback = set_bios_reboot, |
182 | .ident = "Dell OptiPlex 745", | 187 | .ident = "ASUS P4S800", |
183 | .matches = { | 188 | .matches = { |
184 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | 189 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), |
185 | DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"), | 190 | DMI_MATCH(DMI_BOARD_NAME, "P4S800"), |
186 | DMI_MATCH(DMI_BOARD_NAME, "0KW626"), | ||
187 | }, | 191 | }, |
188 | }, | 192 | }, |
189 | { /* Handle problems with rebooting on Dell Optiplex 330 with 0KP561 */ | 193 | |
194 | /* Dell */ | ||
195 | { /* Handle problems with rebooting on Dell DXP061 */ | ||
190 | .callback = set_bios_reboot, | 196 | .callback = set_bios_reboot, |
191 | .ident = "Dell OptiPlex 330", | 197 | .ident = "Dell DXP061", |
192 | .matches = { | 198 | .matches = { |
193 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | 199 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
194 | DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 330"), | 200 | DMI_MATCH(DMI_PRODUCT_NAME, "Dell DXP061"), |
195 | DMI_MATCH(DMI_BOARD_NAME, "0KP561"), | ||
196 | }, | 201 | }, |
197 | }, | 202 | }, |
198 | { /* Handle problems with rebooting on Dell Optiplex 360 with 0T656F */ | 203 | { /* Handle problems with rebooting on Dell E520's */ |
199 | .callback = set_bios_reboot, | 204 | .callback = set_bios_reboot, |
200 | .ident = "Dell OptiPlex 360", | 205 | .ident = "Dell E520", |
201 | .matches = { | 206 | .matches = { |
202 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | 207 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
203 | DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 360"), | 208 | DMI_MATCH(DMI_PRODUCT_NAME, "Dell DM061"), |
204 | DMI_MATCH(DMI_BOARD_NAME, "0T656F"), | ||
205 | }, | 209 | }, |
206 | }, | 210 | }, |
207 | { /* Handle problems with rebooting on Dell OptiPlex 760 with 0G919G */ | 211 | { /* Handle problems with rebooting on the Latitude E5410. */ |
208 | .callback = set_bios_reboot, | 212 | .callback = set_pci_reboot, |
209 | .ident = "Dell OptiPlex 760", | 213 | .ident = "Dell Latitude E5410", |
210 | .matches = { | 214 | .matches = { |
211 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | 215 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
212 | DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 760"), | 216 | DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E5410"), |
213 | DMI_MATCH(DMI_BOARD_NAME, "0G919G"), | ||
214 | }, | 217 | }, |
215 | }, | 218 | }, |
216 | { /* Handle problems with rebooting on Dell 2400's */ | 219 | { /* Handle problems with rebooting on the Latitude E5420. */ |
217 | .callback = set_bios_reboot, | 220 | .callback = set_pci_reboot, |
218 | .ident = "Dell PowerEdge 2400", | 221 | .ident = "Dell Latitude E5420", |
219 | .matches = { | 222 | .matches = { |
220 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), | 223 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
221 | DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"), | 224 | DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E5420"), |
222 | }, | 225 | }, |
223 | }, | 226 | }, |
224 | { /* Handle problems with rebooting on Dell T5400's */ | 227 | { /* Handle problems with rebooting on the Latitude E6320. */ |
225 | .callback = set_bios_reboot, | 228 | .callback = set_pci_reboot, |
226 | .ident = "Dell Precision T5400", | 229 | .ident = "Dell Latitude E6320", |
227 | .matches = { | 230 | .matches = { |
228 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | 231 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
229 | DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation T5400"), | 232 | DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6320"), |
230 | }, | 233 | }, |
231 | }, | 234 | }, |
232 | { /* Handle problems with rebooting on Dell T7400's */ | 235 | { /* Handle problems with rebooting on the Latitude E6420. */ |
233 | .callback = set_bios_reboot, | 236 | .callback = set_pci_reboot, |
234 | .ident = "Dell Precision T7400", | 237 | .ident = "Dell Latitude E6420", |
235 | .matches = { | 238 | .matches = { |
236 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | 239 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
237 | DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation T7400"), | 240 | DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6420"), |
238 | }, | 241 | }, |
239 | }, | 242 | }, |
240 | { /* Handle problems with rebooting on HP laptops */ | 243 | { /* Handle problems with rebooting on Dell Optiplex 330 with 0KP561 */ |
241 | .callback = set_bios_reboot, | 244 | .callback = set_bios_reboot, |
242 | .ident = "HP Compaq Laptop", | 245 | .ident = "Dell OptiPlex 330", |
243 | .matches = { | 246 | .matches = { |
244 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | 247 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
245 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq"), | 248 | DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 330"), |
249 | DMI_MATCH(DMI_BOARD_NAME, "0KP561"), | ||
246 | }, | 250 | }, |
247 | }, | 251 | }, |
248 | { /* Handle problems with rebooting on Dell XPS710 */ | 252 | { /* Handle problems with rebooting on Dell Optiplex 360 with 0T656F */ |
249 | .callback = set_bios_reboot, | 253 | .callback = set_bios_reboot, |
250 | .ident = "Dell XPS710", | 254 | .ident = "Dell OptiPlex 360", |
251 | .matches = { | 255 | .matches = { |
252 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | 256 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
253 | DMI_MATCH(DMI_PRODUCT_NAME, "Dell XPS710"), | 257 | DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 360"), |
258 | DMI_MATCH(DMI_BOARD_NAME, "0T656F"), | ||
254 | }, | 259 | }, |
255 | }, | 260 | }, |
256 | { /* Handle problems with rebooting on Dell DXP061 */ | 261 | { /* Handle problems with rebooting on Dell Optiplex 745's SFF */ |
257 | .callback = set_bios_reboot, | 262 | .callback = set_bios_reboot, |
258 | .ident = "Dell DXP061", | 263 | .ident = "Dell OptiPlex 745", |
259 | .matches = { | 264 | .matches = { |
260 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | 265 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
261 | DMI_MATCH(DMI_PRODUCT_NAME, "Dell DXP061"), | 266 | DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"), |
262 | }, | 267 | }, |
263 | }, | 268 | }, |
264 | { /* Handle problems with rebooting on Sony VGN-Z540N */ | 269 | { /* Handle problems with rebooting on Dell Optiplex 745's DFF */ |
265 | .callback = set_bios_reboot, | 270 | .callback = set_bios_reboot, |
266 | .ident = "Sony VGN-Z540N", | 271 | .ident = "Dell OptiPlex 745", |
267 | .matches = { | 272 | .matches = { |
268 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | 273 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
269 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-Z540N"), | 274 | DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"), |
275 | DMI_MATCH(DMI_BOARD_NAME, "0MM599"), | ||
270 | }, | 276 | }, |
271 | }, | 277 | }, |
272 | { /* Handle problems with rebooting on ASUS P4S800 */ | 278 | { /* Handle problems with rebooting on Dell Optiplex 745 with 0KW626 */ |
273 | .callback = set_bios_reboot, | 279 | .callback = set_bios_reboot, |
274 | .ident = "ASUS P4S800", | 280 | .ident = "Dell OptiPlex 745", |
275 | .matches = { | ||
276 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), | ||
277 | DMI_MATCH(DMI_BOARD_NAME, "P4S800"), | ||
278 | }, | ||
279 | }, | ||
280 | |||
281 | { /* Handle reboot issue on Acer Aspire one */ | ||
282 | .callback = set_kbd_reboot, | ||
283 | .ident = "Acer Aspire One A110", | ||
284 | .matches = { | 281 | .matches = { |
285 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 282 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
286 | DMI_MATCH(DMI_PRODUCT_NAME, "AOA110"), | 283 | DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"), |
284 | DMI_MATCH(DMI_BOARD_NAME, "0KW626"), | ||
287 | }, | 285 | }, |
288 | }, | 286 | }, |
289 | { /* Handle problems with rebooting on Apple MacBook5 */ | 287 | { /* Handle problems with rebooting on Dell OptiPlex 760 with 0G919G */ |
290 | .callback = set_pci_reboot, | 288 | .callback = set_bios_reboot, |
291 | .ident = "Apple MacBook5", | 289 | .ident = "Dell OptiPlex 760", |
292 | .matches = { | 290 | .matches = { |
293 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), | 291 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
294 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5"), | 292 | DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 760"), |
293 | DMI_MATCH(DMI_BOARD_NAME, "0G919G"), | ||
295 | }, | 294 | }, |
296 | }, | 295 | }, |
297 | { /* Handle problems with rebooting on Apple MacBookPro5 */ | 296 | { /* Handle problems with rebooting on the OptiPlex 990. */ |
298 | .callback = set_pci_reboot, | 297 | .callback = set_pci_reboot, |
299 | .ident = "Apple MacBookPro5", | 298 | .ident = "Dell OptiPlex 990", |
300 | .matches = { | 299 | .matches = { |
301 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), | 300 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
302 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5"), | 301 | DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 990"), |
303 | }, | 302 | }, |
304 | }, | 303 | }, |
305 | { /* Handle problems with rebooting on Apple Macmini3,1 */ | 304 | { /* Handle problems with rebooting on Dell 300's */ |
306 | .callback = set_pci_reboot, | 305 | .callback = set_bios_reboot, |
307 | .ident = "Apple Macmini3,1", | 306 | .ident = "Dell PowerEdge 300", |
308 | .matches = { | 307 | .matches = { |
309 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), | 308 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), |
310 | DMI_MATCH(DMI_PRODUCT_NAME, "Macmini3,1"), | 309 | DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 300/"), |
311 | }, | 310 | }, |
312 | }, | 311 | }, |
313 | { /* Handle problems with rebooting on the iMac9,1. */ | 312 | { /* Handle problems with rebooting on Dell 1300's */ |
314 | .callback = set_pci_reboot, | 313 | .callback = set_bios_reboot, |
315 | .ident = "Apple iMac9,1", | 314 | .ident = "Dell PowerEdge 1300", |
316 | .matches = { | 315 | .matches = { |
317 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), | 316 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), |
318 | DMI_MATCH(DMI_PRODUCT_NAME, "iMac9,1"), | 317 | DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1300/"), |
319 | }, | 318 | }, |
320 | }, | 319 | }, |
321 | { /* Handle problems with rebooting on the Latitude E6320. */ | 320 | { /* Handle problems with rebooting on Dell 2400's */ |
322 | .callback = set_pci_reboot, | 321 | .callback = set_bios_reboot, |
323 | .ident = "Dell Latitude E6320", | 322 | .ident = "Dell PowerEdge 2400", |
324 | .matches = { | 323 | .matches = { |
325 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | 324 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), |
326 | DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6320"), | 325 | DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"), |
327 | }, | 326 | }, |
328 | }, | 327 | }, |
329 | { /* Handle problems with rebooting on the Latitude E5410. */ | 328 | { /* Handle problems with rebooting on the Dell PowerEdge C6100. */ |
330 | .callback = set_pci_reboot, | 329 | .callback = set_pci_reboot, |
331 | .ident = "Dell Latitude E5410", | 330 | .ident = "Dell PowerEdge C6100", |
332 | .matches = { | 331 | .matches = { |
333 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | 332 | DMI_MATCH(DMI_SYS_VENDOR, "Dell"), |
334 | DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E5410"), | 333 | DMI_MATCH(DMI_PRODUCT_NAME, "C6100"), |
335 | }, | 334 | }, |
336 | }, | 335 | }, |
337 | { /* Handle problems with rebooting on the Latitude E5420. */ | 336 | { /* Handle problems with rebooting on the Precision M6600. */ |
338 | .callback = set_pci_reboot, | 337 | .callback = set_pci_reboot, |
339 | .ident = "Dell Latitude E5420", | 338 | .ident = "Dell Precision M6600", |
340 | .matches = { | 339 | .matches = { |
341 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | 340 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
342 | DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E5420"), | 341 | DMI_MATCH(DMI_PRODUCT_NAME, "Precision M6600"), |
343 | }, | 342 | }, |
344 | }, | 343 | }, |
345 | { /* Handle problems with rebooting on the Latitude E6420. */ | 344 | { /* Handle problems with rebooting on Dell T5400's */ |
346 | .callback = set_pci_reboot, | 345 | .callback = set_bios_reboot, |
347 | .ident = "Dell Latitude E6420", | 346 | .ident = "Dell Precision T5400", |
348 | .matches = { | 347 | .matches = { |
349 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | 348 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
350 | DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6420"), | 349 | DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation T5400"), |
351 | }, | 350 | }, |
352 | }, | 351 | }, |
353 | { /* Handle problems with rebooting on the OptiPlex 990. */ | 352 | { /* Handle problems with rebooting on Dell T7400's */ |
354 | .callback = set_pci_reboot, | 353 | .callback = set_bios_reboot, |
355 | .ident = "Dell OptiPlex 990", | 354 | .ident = "Dell Precision T7400", |
356 | .matches = { | 355 | .matches = { |
357 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | 356 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
358 | DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 990"), | 357 | DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation T7400"), |
359 | }, | 358 | }, |
360 | }, | 359 | }, |
361 | { /* Handle problems with rebooting on the Precision M6600. */ | 360 | { /* Handle problems with rebooting on Dell XPS710 */ |
362 | .callback = set_pci_reboot, | 361 | .callback = set_bios_reboot, |
363 | .ident = "Dell Precision M6600", | 362 | .ident = "Dell XPS710", |
364 | .matches = { | 363 | .matches = { |
365 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | 364 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
366 | DMI_MATCH(DMI_PRODUCT_NAME, "Precision M6600"), | 365 | DMI_MATCH(DMI_PRODUCT_NAME, "Dell XPS710"), |
367 | }, | 366 | }, |
368 | }, | 367 | }, |
369 | { /* Handle problems with rebooting on the Dell PowerEdge C6100. */ | 368 | |
370 | .callback = set_pci_reboot, | 369 | /* Hewlett-Packard */ |
371 | .ident = "Dell PowerEdge C6100", | 370 | { /* Handle problems with rebooting on HP laptops */ |
371 | .callback = set_bios_reboot, | ||
372 | .ident = "HP Compaq Laptop", | ||
372 | .matches = { | 373 | .matches = { |
373 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | 374 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), |
374 | DMI_MATCH(DMI_PRODUCT_NAME, "C6100"), | 375 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq"), |
375 | }, | 376 | }, |
376 | }, | 377 | }, |
377 | { /* Some C6100 machines were shipped with vendor being 'Dell'. */ | 378 | |
378 | .callback = set_pci_reboot, | 379 | /* Sony */ |
379 | .ident = "Dell PowerEdge C6100", | 380 | { /* Handle problems with rebooting on Sony VGN-Z540N */ |
381 | .callback = set_bios_reboot, | ||
382 | .ident = "Sony VGN-Z540N", | ||
380 | .matches = { | 383 | .matches = { |
381 | DMI_MATCH(DMI_SYS_VENDOR, "Dell"), | 384 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), |
382 | DMI_MATCH(DMI_PRODUCT_NAME, "C6100"), | 385 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-Z540N"), |
383 | }, | 386 | }, |
384 | }, | 387 | }, |
388 | |||
385 | { } | 389 | { } |
386 | }; | 390 | }; |
387 | 391 | ||
@@ -535,10 +539,13 @@ static void native_machine_emergency_restart(void) | |||
535 | 539 | ||
536 | case BOOT_CF9_COND: | 540 | case BOOT_CF9_COND: |
537 | if (port_cf9_safe) { | 541 | if (port_cf9_safe) { |
538 | u8 cf9 = inb(0xcf9) & ~6; | 542 | u8 reboot_code = reboot_mode == REBOOT_WARM ? |
543 | 0x06 : 0x0E; | ||
544 | u8 cf9 = inb(0xcf9) & ~reboot_code; | ||
539 | outb(cf9|2, 0xcf9); /* Request hard reset */ | 545 | outb(cf9|2, 0xcf9); /* Request hard reset */ |
540 | udelay(50); | 546 | udelay(50); |
541 | outb(cf9|6, 0xcf9); /* Actually do the reset */ | 547 | /* Actually do the reset */ |
548 | outb(cf9|reboot_code, 0xcf9); | ||
542 | udelay(50); | 549 | udelay(50); |
543 | } | 550 | } |
544 | reboot_type = BOOT_KBD; | 551 | reboot_type = BOOT_KBD; |
@@ -550,6 +557,10 @@ static void native_machine_emergency_restart(void) | |||
550 | void native_machine_shutdown(void) | 557 | void native_machine_shutdown(void) |
551 | { | 558 | { |
552 | /* Stop the cpus and apics */ | 559 | /* Stop the cpus and apics */ |
560 | #ifdef CONFIG_X86_IO_APIC | ||
561 | disable_IO_APIC(); | ||
562 | #endif | ||
563 | |||
553 | #ifdef CONFIG_SMP | 564 | #ifdef CONFIG_SMP |
554 | /* | 565 | /* |
555 | * Stop all of the others. Also disable the local irq to | 566 | * Stop all of the others. Also disable the local irq to |
@@ -562,10 +573,6 @@ void native_machine_shutdown(void) | |||
562 | 573 | ||
563 | lapic_shutdown(); | 574 | lapic_shutdown(); |
564 | 575 | ||
565 | #ifdef CONFIG_X86_IO_APIC | ||
566 | disable_IO_APIC(); | ||
567 | #endif | ||
568 | |||
569 | #ifdef CONFIG_HPET_TIMER | 576 | #ifdef CONFIG_HPET_TIMER |
570 | hpet_disable(); | 577 | hpet_disable(); |
571 | #endif | 578 | #endif |
diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c index 0aa29394ed6f..ca9622a25e95 100644 --- a/arch/x86/kernel/rtc.c +++ b/arch/x86/kernel/rtc.c | |||
@@ -12,7 +12,7 @@ | |||
12 | #include <asm/vsyscall.h> | 12 | #include <asm/vsyscall.h> |
13 | #include <asm/x86_init.h> | 13 | #include <asm/x86_init.h> |
14 | #include <asm/time.h> | 14 | #include <asm/time.h> |
15 | #include <asm/mrst.h> | 15 | #include <asm/intel-mid.h> |
16 | #include <asm/rtc.h> | 16 | #include <asm/rtc.h> |
17 | 17 | ||
18 | #ifdef CONFIG_X86_32 | 18 | #ifdef CONFIG_X86_32 |
@@ -189,9 +189,17 @@ static __init int add_rtc_cmos(void) | |||
189 | return 0; | 189 | return 0; |
190 | 190 | ||
191 | /* Intel MID platforms don't have ioport rtc */ | 191 | /* Intel MID platforms don't have ioport rtc */ |
192 | if (mrst_identify_cpu()) | 192 | if (intel_mid_identify_cpu()) |
193 | return -ENODEV; | 193 | return -ENODEV; |
194 | 194 | ||
195 | #ifdef CONFIG_ACPI | ||
196 | if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_CMOS_RTC) { | ||
197 | /* This warning can likely go away again in a year or two. */ | ||
198 | pr_info("ACPI: not registering RTC platform device\n"); | ||
199 | return -ENODEV; | ||
200 | } | ||
201 | #endif | ||
202 | |||
195 | platform_device_register(&rtc_device); | 203 | platform_device_register(&rtc_device); |
196 | dev_info(&rtc_device.dev, | 204 | dev_info(&rtc_device.dev, |
197 | "registered platform RTC device (no PNP device found)\n"); | 205 | "registered platform RTC device (no PNP device found)\n"); |
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index f0de6294b955..cb233bc9dee3 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -993,6 +993,7 @@ void __init setup_arch(char **cmdline_p) | |||
993 | efi_init(); | 993 | efi_init(); |
994 | 994 | ||
995 | dmi_scan_machine(); | 995 | dmi_scan_machine(); |
996 | dmi_memdev_walk(); | ||
996 | dmi_set_dump_stack_arch_desc(); | 997 | dmi_set_dump_stack_arch_desc(); |
997 | 998 | ||
998 | /* | 999 | /* |
@@ -1120,8 +1121,6 @@ void __init setup_arch(char **cmdline_p) | |||
1120 | acpi_initrd_override((void *)initrd_start, initrd_end - initrd_start); | 1121 | acpi_initrd_override((void *)initrd_start, initrd_end - initrd_start); |
1121 | #endif | 1122 | #endif |
1122 | 1123 | ||
1123 | reserve_crashkernel(); | ||
1124 | |||
1125 | vsmp_init(); | 1124 | vsmp_init(); |
1126 | 1125 | ||
1127 | io_delay_init(); | 1126 | io_delay_init(); |
@@ -1134,6 +1133,13 @@ void __init setup_arch(char **cmdline_p) | |||
1134 | early_acpi_boot_init(); | 1133 | early_acpi_boot_init(); |
1135 | 1134 | ||
1136 | initmem_init(); | 1135 | initmem_init(); |
1136 | |||
1137 | /* | ||
1138 | * Reserve memory for crash kernel after SRAT is parsed so that it | ||
1139 | * won't consume hotpluggable memory. | ||
1140 | */ | ||
1141 | reserve_crashkernel(); | ||
1142 | |||
1137 | memblock_find_dma_reserve(); | 1143 | memblock_find_dma_reserve(); |
1138 | 1144 | ||
1139 | #ifdef CONFIG_KVM_GUEST | 1145 | #ifdef CONFIG_KVM_GUEST |
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 6cacab671f9b..85dc05a3aa02 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
@@ -73,36 +73,14 @@ | |||
73 | #include <asm/setup.h> | 73 | #include <asm/setup.h> |
74 | #include <asm/uv/uv.h> | 74 | #include <asm/uv/uv.h> |
75 | #include <linux/mc146818rtc.h> | 75 | #include <linux/mc146818rtc.h> |
76 | |||
77 | #include <asm/smpboot_hooks.h> | 76 | #include <asm/smpboot_hooks.h> |
78 | #include <asm/i8259.h> | 77 | #include <asm/i8259.h> |
79 | |||
80 | #include <asm/realmode.h> | 78 | #include <asm/realmode.h> |
79 | #include <asm/misc.h> | ||
81 | 80 | ||
82 | /* State of each CPU */ | 81 | /* State of each CPU */ |
83 | DEFINE_PER_CPU(int, cpu_state) = { 0 }; | 82 | DEFINE_PER_CPU(int, cpu_state) = { 0 }; |
84 | 83 | ||
85 | #ifdef CONFIG_HOTPLUG_CPU | ||
86 | /* | ||
87 | * We need this for trampoline_base protection from concurrent accesses when | ||
88 | * off- and onlining cores wildly. | ||
89 | */ | ||
90 | static DEFINE_MUTEX(x86_cpu_hotplug_driver_mutex); | ||
91 | |||
92 | void cpu_hotplug_driver_lock(void) | ||
93 | { | ||
94 | mutex_lock(&x86_cpu_hotplug_driver_mutex); | ||
95 | } | ||
96 | |||
97 | void cpu_hotplug_driver_unlock(void) | ||
98 | { | ||
99 | mutex_unlock(&x86_cpu_hotplug_driver_mutex); | ||
100 | } | ||
101 | |||
102 | ssize_t arch_cpu_probe(const char *buf, size_t count) { return -1; } | ||
103 | ssize_t arch_cpu_release(const char *buf, size_t count) { return -1; } | ||
104 | #endif | ||
105 | |||
106 | /* Number of siblings per CPU package */ | 84 | /* Number of siblings per CPU package */ |
107 | int smp_num_siblings = 1; | 85 | int smp_num_siblings = 1; |
108 | EXPORT_SYMBOL(smp_num_siblings); | 86 | EXPORT_SYMBOL(smp_num_siblings); |
@@ -648,22 +626,46 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip) | |||
648 | return (send_status | accept_status); | 626 | return (send_status | accept_status); |
649 | } | 627 | } |
650 | 628 | ||
629 | void smp_announce(void) | ||
630 | { | ||
631 | int num_nodes = num_online_nodes(); | ||
632 | |||
633 | printk(KERN_INFO "x86: Booted up %d node%s, %d CPUs\n", | ||
634 | num_nodes, (num_nodes > 1 ? "s" : ""), num_online_cpus()); | ||
635 | } | ||
636 | |||
651 | /* reduce the number of lines printed when booting a large cpu count system */ | 637 | /* reduce the number of lines printed when booting a large cpu count system */ |
652 | static void announce_cpu(int cpu, int apicid) | 638 | static void announce_cpu(int cpu, int apicid) |
653 | { | 639 | { |
654 | static int current_node = -1; | 640 | static int current_node = -1; |
655 | int node = early_cpu_to_node(cpu); | 641 | int node = early_cpu_to_node(cpu); |
656 | int max_cpu_present = find_last_bit(cpumask_bits(cpu_present_mask), NR_CPUS); | 642 | static int width, node_width; |
643 | |||
644 | if (!width) | ||
645 | width = num_digits(num_possible_cpus()) + 1; /* + '#' sign */ | ||
646 | |||
647 | if (!node_width) | ||
648 | node_width = num_digits(num_possible_nodes()) + 1; /* + '#' */ | ||
649 | |||
650 | if (cpu == 1) | ||
651 | printk(KERN_INFO "x86: Booting SMP configuration:\n"); | ||
657 | 652 | ||
658 | if (system_state == SYSTEM_BOOTING) { | 653 | if (system_state == SYSTEM_BOOTING) { |
659 | if (node != current_node) { | 654 | if (node != current_node) { |
660 | if (current_node > (-1)) | 655 | if (current_node > (-1)) |
661 | pr_cont(" OK\n"); | 656 | pr_cont("\n"); |
662 | current_node = node; | 657 | current_node = node; |
663 | pr_info("Booting Node %3d, Processors ", node); | 658 | |
659 | printk(KERN_INFO ".... node %*s#%d, CPUs: ", | ||
660 | node_width - num_digits(node), " ", node); | ||
664 | } | 661 | } |
665 | pr_cont(" #%4d%s", cpu, cpu == max_cpu_present ? " OK\n" : ""); | 662 | |
666 | return; | 663 | /* Add padding for the BSP */ |
664 | if (cpu == 1) | ||
665 | pr_cont("%*s", width + 1, " "); | ||
666 | |||
667 | pr_cont("%*s#%d", width - num_digits(cpu), " ", cpu); | ||
668 | |||
667 | } else | 669 | } else |
668 | pr_info("Booting Node %d Processor %d APIC 0x%x\n", | 670 | pr_info("Booting Node %d Processor %d APIC 0x%x\n", |
669 | node, cpu, apicid); | 671 | node, cpu, apicid); |
diff --git a/arch/x86/kernel/topology.c b/arch/x86/kernel/topology.c index 6e60b5fe2244..649b010da00b 100644 --- a/arch/x86/kernel/topology.c +++ b/arch/x86/kernel/topology.c | |||
@@ -65,29 +65,32 @@ int __ref _debug_hotplug_cpu(int cpu, int action) | |||
65 | if (!cpu_is_hotpluggable(cpu)) | 65 | if (!cpu_is_hotpluggable(cpu)) |
66 | return -EINVAL; | 66 | return -EINVAL; |
67 | 67 | ||
68 | cpu_hotplug_driver_lock(); | 68 | lock_device_hotplug(); |
69 | 69 | ||
70 | switch (action) { | 70 | switch (action) { |
71 | case 0: | 71 | case 0: |
72 | ret = cpu_down(cpu); | 72 | ret = cpu_down(cpu); |
73 | if (!ret) { | 73 | if (!ret) { |
74 | pr_info("CPU %u is now offline\n", cpu); | 74 | pr_info("CPU %u is now offline\n", cpu); |
75 | dev->offline = true; | ||
75 | kobject_uevent(&dev->kobj, KOBJ_OFFLINE); | 76 | kobject_uevent(&dev->kobj, KOBJ_OFFLINE); |
76 | } else | 77 | } else |
77 | pr_debug("Can't offline CPU%d.\n", cpu); | 78 | pr_debug("Can't offline CPU%d.\n", cpu); |
78 | break; | 79 | break; |
79 | case 1: | 80 | case 1: |
80 | ret = cpu_up(cpu); | 81 | ret = cpu_up(cpu); |
81 | if (!ret) | 82 | if (!ret) { |
83 | dev->offline = false; | ||
82 | kobject_uevent(&dev->kobj, KOBJ_ONLINE); | 84 | kobject_uevent(&dev->kobj, KOBJ_ONLINE); |
83 | else | 85 | } else { |
84 | pr_debug("Can't online CPU%d.\n", cpu); | 86 | pr_debug("Can't online CPU%d.\n", cpu); |
87 | } | ||
85 | break; | 88 | break; |
86 | default: | 89 | default: |
87 | ret = -EINVAL; | 90 | ret = -EINVAL; |
88 | } | 91 | } |
89 | 92 | ||
90 | cpu_hotplug_driver_unlock(); | 93 | unlock_device_hotplug(); |
91 | 94 | ||
92 | return ret; | 95 | return ret; |
93 | } | 96 | } |
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 8c8093b146ca..b857ed890b4c 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c | |||
@@ -88,7 +88,7 @@ static inline void conditional_sti(struct pt_regs *regs) | |||
88 | 88 | ||
89 | static inline void preempt_conditional_sti(struct pt_regs *regs) | 89 | static inline void preempt_conditional_sti(struct pt_regs *regs) |
90 | { | 90 | { |
91 | inc_preempt_count(); | 91 | preempt_count_inc(); |
92 | if (regs->flags & X86_EFLAGS_IF) | 92 | if (regs->flags & X86_EFLAGS_IF) |
93 | local_irq_enable(); | 93 | local_irq_enable(); |
94 | } | 94 | } |
@@ -103,7 +103,7 @@ static inline void preempt_conditional_cli(struct pt_regs *regs) | |||
103 | { | 103 | { |
104 | if (regs->flags & X86_EFLAGS_IF) | 104 | if (regs->flags & X86_EFLAGS_IF) |
105 | local_irq_disable(); | 105 | local_irq_disable(); |
106 | dec_preempt_count(); | 106 | preempt_count_dec(); |
107 | } | 107 | } |
108 | 108 | ||
109 | static int __kprobes | 109 | static int __kprobes |
@@ -653,7 +653,7 @@ void math_state_restore(void) | |||
653 | return; | 653 | return; |
654 | } | 654 | } |
655 | 655 | ||
656 | tsk->fpu_counter++; | 656 | tsk->thread.fpu_counter++; |
657 | } | 657 | } |
658 | EXPORT_SYMBOL_GPL(math_state_restore); | 658 | EXPORT_SYMBOL_GPL(math_state_restore); |
659 | 659 | ||
@@ -713,7 +713,7 @@ void __init early_trap_init(void) | |||
713 | /* int3 can be called from all */ | 713 | /* int3 can be called from all */ |
714 | set_system_intr_gate_ist(X86_TRAP_BP, &int3, DEBUG_STACK); | 714 | set_system_intr_gate_ist(X86_TRAP_BP, &int3, DEBUG_STACK); |
715 | #ifdef CONFIG_X86_32 | 715 | #ifdef CONFIG_X86_32 |
716 | set_intr_gate(X86_TRAP_PF, &page_fault); | 716 | set_intr_gate(X86_TRAP_PF, page_fault); |
717 | #endif | 717 | #endif |
718 | load_idt(&idt_descr); | 718 | load_idt(&idt_descr); |
719 | } | 719 | } |
@@ -721,7 +721,7 @@ void __init early_trap_init(void) | |||
721 | void __init early_trap_pf_init(void) | 721 | void __init early_trap_pf_init(void) |
722 | { | 722 | { |
723 | #ifdef CONFIG_X86_64 | 723 | #ifdef CONFIG_X86_64 |
724 | set_intr_gate(X86_TRAP_PF, &page_fault); | 724 | set_intr_gate(X86_TRAP_PF, page_fault); |
725 | #endif | 725 | #endif |
726 | } | 726 | } |
727 | 727 | ||
@@ -737,30 +737,30 @@ void __init trap_init(void) | |||
737 | early_iounmap(p, 4); | 737 | early_iounmap(p, 4); |
738 | #endif | 738 | #endif |
739 | 739 | ||
740 | set_intr_gate(X86_TRAP_DE, ÷_error); | 740 | set_intr_gate(X86_TRAP_DE, divide_error); |
741 | set_intr_gate_ist(X86_TRAP_NMI, &nmi, NMI_STACK); | 741 | set_intr_gate_ist(X86_TRAP_NMI, &nmi, NMI_STACK); |
742 | /* int4 can be called from all */ | 742 | /* int4 can be called from all */ |
743 | set_system_intr_gate(X86_TRAP_OF, &overflow); | 743 | set_system_intr_gate(X86_TRAP_OF, &overflow); |
744 | set_intr_gate(X86_TRAP_BR, &bounds); | 744 | set_intr_gate(X86_TRAP_BR, bounds); |
745 | set_intr_gate(X86_TRAP_UD, &invalid_op); | 745 | set_intr_gate(X86_TRAP_UD, invalid_op); |
746 | set_intr_gate(X86_TRAP_NM, &device_not_available); | 746 | set_intr_gate(X86_TRAP_NM, device_not_available); |
747 | #ifdef CONFIG_X86_32 | 747 | #ifdef CONFIG_X86_32 |
748 | set_task_gate(X86_TRAP_DF, GDT_ENTRY_DOUBLEFAULT_TSS); | 748 | set_task_gate(X86_TRAP_DF, GDT_ENTRY_DOUBLEFAULT_TSS); |
749 | #else | 749 | #else |
750 | set_intr_gate_ist(X86_TRAP_DF, &double_fault, DOUBLEFAULT_STACK); | 750 | set_intr_gate_ist(X86_TRAP_DF, &double_fault, DOUBLEFAULT_STACK); |
751 | #endif | 751 | #endif |
752 | set_intr_gate(X86_TRAP_OLD_MF, &coprocessor_segment_overrun); | 752 | set_intr_gate(X86_TRAP_OLD_MF, coprocessor_segment_overrun); |
753 | set_intr_gate(X86_TRAP_TS, &invalid_TSS); | 753 | set_intr_gate(X86_TRAP_TS, invalid_TSS); |
754 | set_intr_gate(X86_TRAP_NP, &segment_not_present); | 754 | set_intr_gate(X86_TRAP_NP, segment_not_present); |
755 | set_intr_gate_ist(X86_TRAP_SS, &stack_segment, STACKFAULT_STACK); | 755 | set_intr_gate_ist(X86_TRAP_SS, &stack_segment, STACKFAULT_STACK); |
756 | set_intr_gate(X86_TRAP_GP, &general_protection); | 756 | set_intr_gate(X86_TRAP_GP, general_protection); |
757 | set_intr_gate(X86_TRAP_SPURIOUS, &spurious_interrupt_bug); | 757 | set_intr_gate(X86_TRAP_SPURIOUS, spurious_interrupt_bug); |
758 | set_intr_gate(X86_TRAP_MF, &coprocessor_error); | 758 | set_intr_gate(X86_TRAP_MF, coprocessor_error); |
759 | set_intr_gate(X86_TRAP_AC, &alignment_check); | 759 | set_intr_gate(X86_TRAP_AC, alignment_check); |
760 | #ifdef CONFIG_X86_MCE | 760 | #ifdef CONFIG_X86_MCE |
761 | set_intr_gate_ist(X86_TRAP_MC, &machine_check, MCE_STACK); | 761 | set_intr_gate_ist(X86_TRAP_MC, &machine_check, MCE_STACK); |
762 | #endif | 762 | #endif |
763 | set_intr_gate(X86_TRAP_XF, &simd_coprocessor_error); | 763 | set_intr_gate(X86_TRAP_XF, simd_coprocessor_error); |
764 | 764 | ||
765 | /* Reserve all the builtin and the syscall vector: */ | 765 | /* Reserve all the builtin and the syscall vector: */ |
766 | for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++) | 766 | for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++) |
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index 10c4f3006afd..da6b35a98260 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S | |||
@@ -199,6 +199,15 @@ SECTIONS | |||
199 | __x86_cpu_dev_end = .; | 199 | __x86_cpu_dev_end = .; |
200 | } | 200 | } |
201 | 201 | ||
202 | #ifdef CONFIG_X86_INTEL_MID | ||
203 | .x86_intel_mid_dev.init : AT(ADDR(.x86_intel_mid_dev.init) - \ | ||
204 | LOAD_OFFSET) { | ||
205 | __x86_intel_mid_dev_start = .; | ||
206 | *(.x86_intel_mid_dev.init) | ||
207 | __x86_intel_mid_dev_end = .; | ||
208 | } | ||
209 | #endif | ||
210 | |||
202 | /* | 211 | /* |
203 | * start address and size of operations which during runtime | 212 | * start address and size of operations which during runtime |
204 | * can be patched with virtualization friendly instructions or | 213 | * can be patched with virtualization friendly instructions or |
diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c index b014d9414d08..040681928e9d 100644 --- a/arch/x86/kernel/x8664_ksyms_64.c +++ b/arch/x86/kernel/x8664_ksyms_64.c | |||
@@ -66,3 +66,10 @@ EXPORT_SYMBOL(empty_zero_page); | |||
66 | #ifndef CONFIG_PARAVIRT | 66 | #ifndef CONFIG_PARAVIRT |
67 | EXPORT_SYMBOL(native_load_gs_index); | 67 | EXPORT_SYMBOL(native_load_gs_index); |
68 | #endif | 68 | #endif |
69 | |||
70 | #ifdef CONFIG_PREEMPT | ||
71 | EXPORT_SYMBOL(___preempt_schedule); | ||
72 | #ifdef CONFIG_CONTEXT_TRACKING | ||
73 | EXPORT_SYMBOL(___preempt_schedule_context); | ||
74 | #endif | ||
75 | #endif | ||
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c index 8ce0072cd700..021783b1f46a 100644 --- a/arch/x86/kernel/x86_init.c +++ b/arch/x86/kernel/x86_init.c | |||
@@ -116,6 +116,8 @@ struct x86_msi_ops x86_msi = { | |||
116 | .teardown_msi_irqs = default_teardown_msi_irqs, | 116 | .teardown_msi_irqs = default_teardown_msi_irqs, |
117 | .restore_msi_irqs = default_restore_msi_irqs, | 117 | .restore_msi_irqs = default_restore_msi_irqs, |
118 | .setup_hpet_msi = default_setup_hpet_msi, | 118 | .setup_hpet_msi = default_setup_hpet_msi, |
119 | .msi_mask_irq = default_msi_mask_irq, | ||
120 | .msix_mask_irq = default_msix_mask_irq, | ||
119 | }; | 121 | }; |
120 | 122 | ||
121 | /* MSI arch specific hooks */ | 123 | /* MSI arch specific hooks */ |
@@ -138,6 +140,14 @@ void arch_restore_msi_irqs(struct pci_dev *dev, int irq) | |||
138 | { | 140 | { |
139 | x86_msi.restore_msi_irqs(dev, irq); | 141 | x86_msi.restore_msi_irqs(dev, irq); |
140 | } | 142 | } |
143 | u32 arch_msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) | ||
144 | { | ||
145 | return x86_msi.msi_mask_irq(desc, mask, flag); | ||
146 | } | ||
147 | u32 arch_msix_mask_irq(struct msi_desc *desc, u32 flag) | ||
148 | { | ||
149 | return x86_msi.msix_mask_irq(desc, flag); | ||
150 | } | ||
141 | #endif | 151 | #endif |
142 | 152 | ||
143 | struct x86_io_apic_ops x86_io_apic_ops = { | 153 | struct x86_io_apic_ops x86_io_apic_ops = { |
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 96b2c6697c9d..992d63bb154f 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile | |||
@@ -16,7 +16,7 @@ clean-files := inat-tables.c | |||
16 | 16 | ||
17 | obj-$(CONFIG_SMP) += msr-smp.o cache-smp.o | 17 | obj-$(CONFIG_SMP) += msr-smp.o cache-smp.o |
18 | 18 | ||
19 | lib-y := delay.o | 19 | lib-y := delay.o misc.o |
20 | lib-y += thunk_$(BITS).o | 20 | lib-y += thunk_$(BITS).o |
21 | lib-y += usercopy_$(BITS).o usercopy.o getuser.o putuser.o | 21 | lib-y += usercopy_$(BITS).o usercopy.o getuser.o putuser.o |
22 | lib-y += memcpy_$(BITS).o | 22 | lib-y += memcpy_$(BITS).o |
diff --git a/arch/x86/lib/misc.c b/arch/x86/lib/misc.c new file mode 100644 index 000000000000..76b373af03f0 --- /dev/null +++ b/arch/x86/lib/misc.c | |||
@@ -0,0 +1,21 @@ | |||
1 | /* | ||
2 | * Count the digits of @val including a possible sign. | ||
3 | * | ||
4 | * (Typed on and submitted from hpa's mobile phone.) | ||
5 | */ | ||
6 | int num_digits(int val) | ||
7 | { | ||
8 | int m = 10; | ||
9 | int d = 1; | ||
10 | |||
11 | if (val < 0) { | ||
12 | d++; | ||
13 | val = -val; | ||
14 | } | ||
15 | |||
16 | while (val >= m) { | ||
17 | m *= 10; | ||
18 | d++; | ||
19 | } | ||
20 | return d; | ||
21 | } | ||
diff --git a/arch/x86/lib/msr-smp.c b/arch/x86/lib/msr-smp.c index a6b1b86d2253..518532e6a3fa 100644 --- a/arch/x86/lib/msr-smp.c +++ b/arch/x86/lib/msr-smp.c | |||
@@ -47,6 +47,21 @@ int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) | |||
47 | } | 47 | } |
48 | EXPORT_SYMBOL(rdmsr_on_cpu); | 48 | EXPORT_SYMBOL(rdmsr_on_cpu); |
49 | 49 | ||
50 | int rdmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 *q) | ||
51 | { | ||
52 | int err; | ||
53 | struct msr_info rv; | ||
54 | |||
55 | memset(&rv, 0, sizeof(rv)); | ||
56 | |||
57 | rv.msr_no = msr_no; | ||
58 | err = smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 1); | ||
59 | *q = rv.reg.q; | ||
60 | |||
61 | return err; | ||
62 | } | ||
63 | EXPORT_SYMBOL(rdmsrl_on_cpu); | ||
64 | |||
50 | int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) | 65 | int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) |
51 | { | 66 | { |
52 | int err; | 67 | int err; |
@@ -63,6 +78,22 @@ int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) | |||
63 | } | 78 | } |
64 | EXPORT_SYMBOL(wrmsr_on_cpu); | 79 | EXPORT_SYMBOL(wrmsr_on_cpu); |
65 | 80 | ||
81 | int wrmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 q) | ||
82 | { | ||
83 | int err; | ||
84 | struct msr_info rv; | ||
85 | |||
86 | memset(&rv, 0, sizeof(rv)); | ||
87 | |||
88 | rv.msr_no = msr_no; | ||
89 | rv.reg.q = q; | ||
90 | |||
91 | err = smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 1); | ||
92 | |||
93 | return err; | ||
94 | } | ||
95 | EXPORT_SYMBOL(wrmsrl_on_cpu); | ||
96 | |||
66 | static void __rwmsr_on_cpus(const struct cpumask *mask, u32 msr_no, | 97 | static void __rwmsr_on_cpus(const struct cpumask *mask, u32 msr_no, |
67 | struct msr *msrs, | 98 | struct msr *msrs, |
68 | void (*msr_func) (void *info)) | 99 | void (*msr_func) (void *info)) |
@@ -159,6 +190,37 @@ int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) | |||
159 | } | 190 | } |
160 | EXPORT_SYMBOL(wrmsr_safe_on_cpu); | 191 | EXPORT_SYMBOL(wrmsr_safe_on_cpu); |
161 | 192 | ||
193 | int wrmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 q) | ||
194 | { | ||
195 | int err; | ||
196 | struct msr_info rv; | ||
197 | |||
198 | memset(&rv, 0, sizeof(rv)); | ||
199 | |||
200 | rv.msr_no = msr_no; | ||
201 | rv.reg.q = q; | ||
202 | |||
203 | err = smp_call_function_single(cpu, __wrmsr_safe_on_cpu, &rv, 1); | ||
204 | |||
205 | return err ? err : rv.err; | ||
206 | } | ||
207 | EXPORT_SYMBOL(wrmsrl_safe_on_cpu); | ||
208 | |||
209 | int rdmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 *q) | ||
210 | { | ||
211 | int err; | ||
212 | struct msr_info rv; | ||
213 | |||
214 | memset(&rv, 0, sizeof(rv)); | ||
215 | |||
216 | rv.msr_no = msr_no; | ||
217 | err = smp_call_function_single(cpu, __rdmsr_safe_on_cpu, &rv, 1); | ||
218 | *q = rv.reg.q; | ||
219 | |||
220 | return err ? err : rv.err; | ||
221 | } | ||
222 | EXPORT_SYMBOL(rdmsrl_safe_on_cpu); | ||
223 | |||
162 | /* | 224 | /* |
163 | * These variants are significantly slower, but allows control over | 225 | * These variants are significantly slower, but allows control over |
164 | * the entire 32-bit GPR set. | 226 | * the entire 32-bit GPR set. |
diff --git a/arch/x86/lib/usercopy.c b/arch/x86/lib/usercopy.c index 4f74d94c8d97..ddf9ecb53cc3 100644 --- a/arch/x86/lib/usercopy.c +++ b/arch/x86/lib/usercopy.c | |||
@@ -11,39 +11,26 @@ | |||
11 | #include <linux/sched.h> | 11 | #include <linux/sched.h> |
12 | 12 | ||
13 | /* | 13 | /* |
14 | * best effort, GUP based copy_from_user() that is NMI-safe | 14 | * We rely on the nested NMI work to allow atomic faults from the NMI path; the |
15 | * nested NMI paths are careful to preserve CR2. | ||
15 | */ | 16 | */ |
16 | unsigned long | 17 | unsigned long |
17 | copy_from_user_nmi(void *to, const void __user *from, unsigned long n) | 18 | copy_from_user_nmi(void *to, const void __user *from, unsigned long n) |
18 | { | 19 | { |
19 | unsigned long offset, addr = (unsigned long)from; | 20 | unsigned long ret; |
20 | unsigned long size, len = 0; | ||
21 | struct page *page; | ||
22 | void *map; | ||
23 | int ret; | ||
24 | 21 | ||
25 | if (__range_not_ok(from, n, TASK_SIZE)) | 22 | if (__range_not_ok(from, n, TASK_SIZE)) |
26 | return len; | 23 | return 0; |
27 | 24 | ||
28 | do { | 25 | /* |
29 | ret = __get_user_pages_fast(addr, 1, 0, &page); | 26 | * Even though this function is typically called from NMI/IRQ context |
30 | if (!ret) | 27 | * disable pagefaults so that its behaviour is consistent even when |
31 | break; | 28 | * called form other contexts. |
32 | 29 | */ | |
33 | offset = addr & (PAGE_SIZE - 1); | 30 | pagefault_disable(); |
34 | size = min(PAGE_SIZE - offset, n - len); | 31 | ret = __copy_from_user_inatomic(to, from, n); |
35 | 32 | pagefault_enable(); | |
36 | map = kmap_atomic(page); | 33 | |
37 | memcpy(to, map+offset, size); | 34 | return ret; |
38 | kunmap_atomic(map); | ||
39 | put_page(page); | ||
40 | |||
41 | len += size; | ||
42 | to += size; | ||
43 | addr += size; | ||
44 | |||
45 | } while (len < n); | ||
46 | |||
47 | return len; | ||
48 | } | 35 | } |
49 | EXPORT_SYMBOL_GPL(copy_from_user_nmi); | 36 | EXPORT_SYMBOL_GPL(copy_from_user_nmi); |
diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c index 3eb18acd0e40..e2f5e21c03b3 100644 --- a/arch/x86/lib/usercopy_32.c +++ b/arch/x86/lib/usercopy_32.c | |||
@@ -654,14 +654,13 @@ EXPORT_SYMBOL(__copy_from_user_ll_nocache_nozero); | |||
654 | * Returns number of bytes that could not be copied. | 654 | * Returns number of bytes that could not be copied. |
655 | * On success, this will be zero. | 655 | * On success, this will be zero. |
656 | */ | 656 | */ |
657 | unsigned long | 657 | unsigned long _copy_to_user(void __user *to, const void *from, unsigned n) |
658 | copy_to_user(void __user *to, const void *from, unsigned long n) | ||
659 | { | 658 | { |
660 | if (access_ok(VERIFY_WRITE, to, n)) | 659 | if (access_ok(VERIFY_WRITE, to, n)) |
661 | n = __copy_to_user(to, from, n); | 660 | n = __copy_to_user(to, from, n); |
662 | return n; | 661 | return n; |
663 | } | 662 | } |
664 | EXPORT_SYMBOL(copy_to_user); | 663 | EXPORT_SYMBOL(_copy_to_user); |
665 | 664 | ||
666 | /** | 665 | /** |
667 | * copy_from_user: - Copy a block of data from user space. | 666 | * copy_from_user: - Copy a block of data from user space. |
@@ -679,8 +678,7 @@ EXPORT_SYMBOL(copy_to_user); | |||
679 | * If some data could not be copied, this function will pad the copied | 678 | * If some data could not be copied, this function will pad the copied |
680 | * data to the requested size using zero bytes. | 679 | * data to the requested size using zero bytes. |
681 | */ | 680 | */ |
682 | unsigned long | 681 | unsigned long _copy_from_user(void *to, const void __user *from, unsigned n) |
683 | _copy_from_user(void *to, const void __user *from, unsigned long n) | ||
684 | { | 682 | { |
685 | if (access_ok(VERIFY_READ, from, n)) | 683 | if (access_ok(VERIFY_READ, from, n)) |
686 | n = __copy_from_user(to, from, n); | 684 | n = __copy_from_user(to, from, n); |
diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile index 23d8e5fecf76..6a19ad9f370d 100644 --- a/arch/x86/mm/Makefile +++ b/arch/x86/mm/Makefile | |||
@@ -6,6 +6,8 @@ nostackp := $(call cc-option, -fno-stack-protector) | |||
6 | CFLAGS_physaddr.o := $(nostackp) | 6 | CFLAGS_physaddr.o := $(nostackp) |
7 | CFLAGS_setup_nx.o := $(nostackp) | 7 | CFLAGS_setup_nx.o := $(nostackp) |
8 | 8 | ||
9 | CFLAGS_fault.o := -I$(src)/../include/asm/trace | ||
10 | |||
9 | obj-$(CONFIG_X86_PAT) += pat_rbtree.o | 11 | obj-$(CONFIG_X86_PAT) += pat_rbtree.o |
10 | obj-$(CONFIG_SMP) += tlb.o | 12 | obj-$(CONFIG_SMP) += tlb.o |
11 | 13 | ||
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 3aaeffcfd67a..9ff85bb8dd69 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c | |||
@@ -20,6 +20,9 @@ | |||
20 | #include <asm/kmemcheck.h> /* kmemcheck_*(), ... */ | 20 | #include <asm/kmemcheck.h> /* kmemcheck_*(), ... */ |
21 | #include <asm/fixmap.h> /* VSYSCALL_START */ | 21 | #include <asm/fixmap.h> /* VSYSCALL_START */ |
22 | 22 | ||
23 | #define CREATE_TRACE_POINTS | ||
24 | #include <asm/trace/exceptions.h> | ||
25 | |||
23 | /* | 26 | /* |
24 | * Page fault error code bits: | 27 | * Page fault error code bits: |
25 | * | 28 | * |
@@ -51,7 +54,7 @@ kmmio_fault(struct pt_regs *regs, unsigned long addr) | |||
51 | return 0; | 54 | return 0; |
52 | } | 55 | } |
53 | 56 | ||
54 | static inline int __kprobes notify_page_fault(struct pt_regs *regs) | 57 | static inline int __kprobes kprobes_fault(struct pt_regs *regs) |
55 | { | 58 | { |
56 | int ret = 0; | 59 | int ret = 0; |
57 | 60 | ||
@@ -596,7 +599,7 @@ show_fault_oops(struct pt_regs *regs, unsigned long error_code, | |||
596 | 599 | ||
597 | printk(KERN_CONT " at %p\n", (void *) address); | 600 | printk(KERN_CONT " at %p\n", (void *) address); |
598 | printk(KERN_ALERT "IP:"); | 601 | printk(KERN_ALERT "IP:"); |
599 | printk_address(regs->ip, 1); | 602 | printk_address(regs->ip); |
600 | 603 | ||
601 | dump_pagetable(address); | 604 | dump_pagetable(address); |
602 | } | 605 | } |
@@ -1048,7 +1051,7 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code) | |||
1048 | return; | 1051 | return; |
1049 | 1052 | ||
1050 | /* kprobes don't want to hook the spurious faults: */ | 1053 | /* kprobes don't want to hook the spurious faults: */ |
1051 | if (notify_page_fault(regs)) | 1054 | if (kprobes_fault(regs)) |
1052 | return; | 1055 | return; |
1053 | /* | 1056 | /* |
1054 | * Don't take the mm semaphore here. If we fixup a prefetch | 1057 | * Don't take the mm semaphore here. If we fixup a prefetch |
@@ -1060,23 +1063,8 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code) | |||
1060 | } | 1063 | } |
1061 | 1064 | ||
1062 | /* kprobes don't want to hook the spurious faults: */ | 1065 | /* kprobes don't want to hook the spurious faults: */ |
1063 | if (unlikely(notify_page_fault(regs))) | 1066 | if (unlikely(kprobes_fault(regs))) |
1064 | return; | 1067 | return; |
1065 | /* | ||
1066 | * It's safe to allow irq's after cr2 has been saved and the | ||
1067 | * vmalloc fault has been handled. | ||
1068 | * | ||
1069 | * User-mode registers count as a user access even for any | ||
1070 | * potential system fault or CPU buglet: | ||
1071 | */ | ||
1072 | if (user_mode_vm(regs)) { | ||
1073 | local_irq_enable(); | ||
1074 | error_code |= PF_USER; | ||
1075 | flags |= FAULT_FLAG_USER; | ||
1076 | } else { | ||
1077 | if (regs->flags & X86_EFLAGS_IF) | ||
1078 | local_irq_enable(); | ||
1079 | } | ||
1080 | 1068 | ||
1081 | if (unlikely(error_code & PF_RSVD)) | 1069 | if (unlikely(error_code & PF_RSVD)) |
1082 | pgtable_bad(regs, error_code, address); | 1070 | pgtable_bad(regs, error_code, address); |
@@ -1088,8 +1076,6 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code) | |||
1088 | } | 1076 | } |
1089 | } | 1077 | } |
1090 | 1078 | ||
1091 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); | ||
1092 | |||
1093 | /* | 1079 | /* |
1094 | * If we're in an interrupt, have no user context or are running | 1080 | * If we're in an interrupt, have no user context or are running |
1095 | * in an atomic region then we must not take the fault: | 1081 | * in an atomic region then we must not take the fault: |
@@ -1099,6 +1085,24 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code) | |||
1099 | return; | 1085 | return; |
1100 | } | 1086 | } |
1101 | 1087 | ||
1088 | /* | ||
1089 | * It's safe to allow irq's after cr2 has been saved and the | ||
1090 | * vmalloc fault has been handled. | ||
1091 | * | ||
1092 | * User-mode registers count as a user access even for any | ||
1093 | * potential system fault or CPU buglet: | ||
1094 | */ | ||
1095 | if (user_mode_vm(regs)) { | ||
1096 | local_irq_enable(); | ||
1097 | error_code |= PF_USER; | ||
1098 | flags |= FAULT_FLAG_USER; | ||
1099 | } else { | ||
1100 | if (regs->flags & X86_EFLAGS_IF) | ||
1101 | local_irq_enable(); | ||
1102 | } | ||
1103 | |||
1104 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); | ||
1105 | |||
1102 | if (error_code & PF_WRITE) | 1106 | if (error_code & PF_WRITE) |
1103 | flags |= FAULT_FLAG_WRITE; | 1107 | flags |= FAULT_FLAG_WRITE; |
1104 | 1108 | ||
@@ -1231,3 +1235,23 @@ do_page_fault(struct pt_regs *regs, unsigned long error_code) | |||
1231 | __do_page_fault(regs, error_code); | 1235 | __do_page_fault(regs, error_code); |
1232 | exception_exit(prev_state); | 1236 | exception_exit(prev_state); |
1233 | } | 1237 | } |
1238 | |||
1239 | static void trace_page_fault_entries(struct pt_regs *regs, | ||
1240 | unsigned long error_code) | ||
1241 | { | ||
1242 | if (user_mode(regs)) | ||
1243 | trace_page_fault_user(read_cr2(), regs, error_code); | ||
1244 | else | ||
1245 | trace_page_fault_kernel(read_cr2(), regs, error_code); | ||
1246 | } | ||
1247 | |||
1248 | dotraplinkage void __kprobes | ||
1249 | trace_do_page_fault(struct pt_regs *regs, unsigned long error_code) | ||
1250 | { | ||
1251 | enum ctx_state prev_state; | ||
1252 | |||
1253 | prev_state = exception_enter(); | ||
1254 | trace_page_fault_entries(regs, error_code); | ||
1255 | __do_page_fault(regs, error_code); | ||
1256 | exception_exit(prev_state); | ||
1257 | } | ||
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index 04664cdb7fda..f97130618113 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c | |||
@@ -53,12 +53,12 @@ __ref void *alloc_low_pages(unsigned int num) | |||
53 | if ((pgt_buf_end + num) > pgt_buf_top || !can_use_brk_pgt) { | 53 | if ((pgt_buf_end + num) > pgt_buf_top || !can_use_brk_pgt) { |
54 | unsigned long ret; | 54 | unsigned long ret; |
55 | if (min_pfn_mapped >= max_pfn_mapped) | 55 | if (min_pfn_mapped >= max_pfn_mapped) |
56 | panic("alloc_low_page: ran out of memory"); | 56 | panic("alloc_low_pages: ran out of memory"); |
57 | ret = memblock_find_in_range(min_pfn_mapped << PAGE_SHIFT, | 57 | ret = memblock_find_in_range(min_pfn_mapped << PAGE_SHIFT, |
58 | max_pfn_mapped << PAGE_SHIFT, | 58 | max_pfn_mapped << PAGE_SHIFT, |
59 | PAGE_SIZE * num , PAGE_SIZE); | 59 | PAGE_SIZE * num , PAGE_SIZE); |
60 | if (!ret) | 60 | if (!ret) |
61 | panic("alloc_low_page: can not alloc memory"); | 61 | panic("alloc_low_pages: can not alloc memory"); |
62 | memblock_reserve(ret, PAGE_SIZE * num); | 62 | memblock_reserve(ret, PAGE_SIZE * num); |
63 | pfn = ret >> PAGE_SHIFT; | 63 | pfn = ret >> PAGE_SHIFT; |
64 | } else { | 64 | } else { |
@@ -399,29 +399,46 @@ static unsigned long __init init_range_memory_mapping( | |||
399 | return mapped_ram_size; | 399 | return mapped_ram_size; |
400 | } | 400 | } |
401 | 401 | ||
402 | /* (PUD_SHIFT-PMD_SHIFT)/2 */ | 402 | static unsigned long __init get_new_step_size(unsigned long step_size) |
403 | #define STEP_SIZE_SHIFT 5 | 403 | { |
404 | void __init init_mem_mapping(void) | 404 | /* |
405 | * Explain why we shift by 5 and why we don't have to worry about | ||
406 | * 'step_size << 5' overflowing: | ||
407 | * | ||
408 | * initial mapped size is PMD_SIZE (2M). | ||
409 | * We can not set step_size to be PUD_SIZE (1G) yet. | ||
410 | * In worse case, when we cross the 1G boundary, and | ||
411 | * PG_LEVEL_2M is not set, we will need 1+1+512 pages (2M + 8k) | ||
412 | * to map 1G range with PTE. Use 5 as shift for now. | ||
413 | * | ||
414 | * Don't need to worry about overflow, on 32bit, when step_size | ||
415 | * is 0, round_down() returns 0 for start, and that turns it | ||
416 | * into 0x100000000ULL. | ||
417 | */ | ||
418 | return step_size << 5; | ||
419 | } | ||
420 | |||
421 | /** | ||
422 | * memory_map_top_down - Map [map_start, map_end) top down | ||
423 | * @map_start: start address of the target memory range | ||
424 | * @map_end: end address of the target memory range | ||
425 | * | ||
426 | * This function will setup direct mapping for memory range | ||
427 | * [map_start, map_end) in top-down. That said, the page tables | ||
428 | * will be allocated at the end of the memory, and we map the | ||
429 | * memory in top-down. | ||
430 | */ | ||
431 | static void __init memory_map_top_down(unsigned long map_start, | ||
432 | unsigned long map_end) | ||
405 | { | 433 | { |
406 | unsigned long end, real_end, start, last_start; | 434 | unsigned long real_end, start, last_start; |
407 | unsigned long step_size; | 435 | unsigned long step_size; |
408 | unsigned long addr; | 436 | unsigned long addr; |
409 | unsigned long mapped_ram_size = 0; | 437 | unsigned long mapped_ram_size = 0; |
410 | unsigned long new_mapped_ram_size; | 438 | unsigned long new_mapped_ram_size; |
411 | 439 | ||
412 | probe_page_size_mask(); | ||
413 | |||
414 | #ifdef CONFIG_X86_64 | ||
415 | end = max_pfn << PAGE_SHIFT; | ||
416 | #else | ||
417 | end = max_low_pfn << PAGE_SHIFT; | ||
418 | #endif | ||
419 | |||
420 | /* the ISA range is always mapped regardless of memory holes */ | ||
421 | init_memory_mapping(0, ISA_END_ADDRESS); | ||
422 | |||
423 | /* xen has big range in reserved near end of ram, skip it at first.*/ | 440 | /* xen has big range in reserved near end of ram, skip it at first.*/ |
424 | addr = memblock_find_in_range(ISA_END_ADDRESS, end, PMD_SIZE, PMD_SIZE); | 441 | addr = memblock_find_in_range(map_start, map_end, PMD_SIZE, PMD_SIZE); |
425 | real_end = addr + PMD_SIZE; | 442 | real_end = addr + PMD_SIZE; |
426 | 443 | ||
427 | /* step_size need to be small so pgt_buf from BRK could cover it */ | 444 | /* step_size need to be small so pgt_buf from BRK could cover it */ |
@@ -436,25 +453,106 @@ void __init init_mem_mapping(void) | |||
436 | * end of RAM in [min_pfn_mapped, max_pfn_mapped) used as new pages | 453 | * end of RAM in [min_pfn_mapped, max_pfn_mapped) used as new pages |
437 | * for page table. | 454 | * for page table. |
438 | */ | 455 | */ |
439 | while (last_start > ISA_END_ADDRESS) { | 456 | while (last_start > map_start) { |
440 | if (last_start > step_size) { | 457 | if (last_start > step_size) { |
441 | start = round_down(last_start - 1, step_size); | 458 | start = round_down(last_start - 1, step_size); |
442 | if (start < ISA_END_ADDRESS) | 459 | if (start < map_start) |
443 | start = ISA_END_ADDRESS; | 460 | start = map_start; |
444 | } else | 461 | } else |
445 | start = ISA_END_ADDRESS; | 462 | start = map_start; |
446 | new_mapped_ram_size = init_range_memory_mapping(start, | 463 | new_mapped_ram_size = init_range_memory_mapping(start, |
447 | last_start); | 464 | last_start); |
448 | last_start = start; | 465 | last_start = start; |
449 | min_pfn_mapped = last_start >> PAGE_SHIFT; | 466 | min_pfn_mapped = last_start >> PAGE_SHIFT; |
450 | /* only increase step_size after big range get mapped */ | 467 | /* only increase step_size after big range get mapped */ |
451 | if (new_mapped_ram_size > mapped_ram_size) | 468 | if (new_mapped_ram_size > mapped_ram_size) |
452 | step_size <<= STEP_SIZE_SHIFT; | 469 | step_size = get_new_step_size(step_size); |
453 | mapped_ram_size += new_mapped_ram_size; | 470 | mapped_ram_size += new_mapped_ram_size; |
454 | } | 471 | } |
455 | 472 | ||
456 | if (real_end < end) | 473 | if (real_end < map_end) |
457 | init_range_memory_mapping(real_end, end); | 474 | init_range_memory_mapping(real_end, map_end); |
475 | } | ||
476 | |||
477 | /** | ||
478 | * memory_map_bottom_up - Map [map_start, map_end) bottom up | ||
479 | * @map_start: start address of the target memory range | ||
480 | * @map_end: end address of the target memory range | ||
481 | * | ||
482 | * This function will setup direct mapping for memory range | ||
483 | * [map_start, map_end) in bottom-up. Since we have limited the | ||
484 | * bottom-up allocation above the kernel, the page tables will | ||
485 | * be allocated just above the kernel and we map the memory | ||
486 | * in [map_start, map_end) in bottom-up. | ||
487 | */ | ||
488 | static void __init memory_map_bottom_up(unsigned long map_start, | ||
489 | unsigned long map_end) | ||
490 | { | ||
491 | unsigned long next, new_mapped_ram_size, start; | ||
492 | unsigned long mapped_ram_size = 0; | ||
493 | /* step_size need to be small so pgt_buf from BRK could cover it */ | ||
494 | unsigned long step_size = PMD_SIZE; | ||
495 | |||
496 | start = map_start; | ||
497 | min_pfn_mapped = start >> PAGE_SHIFT; | ||
498 | |||
499 | /* | ||
500 | * We start from the bottom (@map_start) and go to the top (@map_end). | ||
501 | * The memblock_find_in_range() gets us a block of RAM from the | ||
502 | * end of RAM in [min_pfn_mapped, max_pfn_mapped) used as new pages | ||
503 | * for page table. | ||
504 | */ | ||
505 | while (start < map_end) { | ||
506 | if (map_end - start > step_size) { | ||
507 | next = round_up(start + 1, step_size); | ||
508 | if (next > map_end) | ||
509 | next = map_end; | ||
510 | } else | ||
511 | next = map_end; | ||
512 | |||
513 | new_mapped_ram_size = init_range_memory_mapping(start, next); | ||
514 | start = next; | ||
515 | |||
516 | if (new_mapped_ram_size > mapped_ram_size) | ||
517 | step_size = get_new_step_size(step_size); | ||
518 | mapped_ram_size += new_mapped_ram_size; | ||
519 | } | ||
520 | } | ||
521 | |||
522 | void __init init_mem_mapping(void) | ||
523 | { | ||
524 | unsigned long end; | ||
525 | |||
526 | probe_page_size_mask(); | ||
527 | |||
528 | #ifdef CONFIG_X86_64 | ||
529 | end = max_pfn << PAGE_SHIFT; | ||
530 | #else | ||
531 | end = max_low_pfn << PAGE_SHIFT; | ||
532 | #endif | ||
533 | |||
534 | /* the ISA range is always mapped regardless of memory holes */ | ||
535 | init_memory_mapping(0, ISA_END_ADDRESS); | ||
536 | |||
537 | /* | ||
538 | * If the allocation is in bottom-up direction, we setup direct mapping | ||
539 | * in bottom-up, otherwise we setup direct mapping in top-down. | ||
540 | */ | ||
541 | if (memblock_bottom_up()) { | ||
542 | unsigned long kernel_end = __pa_symbol(_end); | ||
543 | |||
544 | /* | ||
545 | * we need two separate calls here. This is because we want to | ||
546 | * allocate page tables above the kernel. So we first map | ||
547 | * [kernel_end, end) to make memory above the kernel be mapped | ||
548 | * as soon as possible. And then use page tables allocated above | ||
549 | * the kernel to map [ISA_END_ADDRESS, kernel_end). | ||
550 | */ | ||
551 | memory_map_bottom_up(kernel_end, end); | ||
552 | memory_map_bottom_up(ISA_END_ADDRESS, kernel_end); | ||
553 | } else { | ||
554 | memory_map_top_down(ISA_END_ADDRESS, end); | ||
555 | } | ||
458 | 556 | ||
459 | #ifdef CONFIG_X86_64 | 557 | #ifdef CONFIG_X86_64 |
460 | if (max_pfn > max_low_pfn) { | 558 | if (max_pfn > max_low_pfn) { |
diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c index 8bf93bae1f13..24aec58d6afd 100644 --- a/arch/x86/mm/numa.c +++ b/arch/x86/mm/numa.c | |||
@@ -567,6 +567,17 @@ static int __init numa_init(int (*init_func)(void)) | |||
567 | ret = init_func(); | 567 | ret = init_func(); |
568 | if (ret < 0) | 568 | if (ret < 0) |
569 | return ret; | 569 | return ret; |
570 | |||
571 | /* | ||
572 | * We reset memblock back to the top-down direction | ||
573 | * here because if we configured ACPI_NUMA, we have | ||
574 | * parsed SRAT in init_func(). It is ok to have the | ||
575 | * reset here even if we did't configure ACPI_NUMA | ||
576 | * or acpi numa init fails and fallbacks to dummy | ||
577 | * numa init. | ||
578 | */ | ||
579 | memblock_set_bottom_up(false); | ||
580 | |||
570 | ret = numa_cleanup_meminfo(&numa_meminfo); | 581 | ret = numa_cleanup_meminfo(&numa_meminfo); |
571 | if (ret < 0) | 582 | if (ret < 0) |
572 | return ret; | 583 | return ret; |
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c index dfa537a03be1..a7cccb6d7fec 100644 --- a/arch/x86/mm/pgtable.c +++ b/arch/x86/mm/pgtable.c | |||
@@ -25,8 +25,12 @@ pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address) | |||
25 | struct page *pte; | 25 | struct page *pte; |
26 | 26 | ||
27 | pte = alloc_pages(__userpte_alloc_gfp, 0); | 27 | pte = alloc_pages(__userpte_alloc_gfp, 0); |
28 | if (pte) | 28 | if (!pte) |
29 | pgtable_page_ctor(pte); | 29 | return NULL; |
30 | if (!pgtable_page_ctor(pte)) { | ||
31 | __free_page(pte); | ||
32 | return NULL; | ||
33 | } | ||
30 | return pte; | 34 | return pte; |
31 | } | 35 | } |
32 | 36 | ||
@@ -189,8 +193,10 @@ static void free_pmds(pmd_t *pmds[]) | |||
189 | int i; | 193 | int i; |
190 | 194 | ||
191 | for(i = 0; i < PREALLOCATED_PMDS; i++) | 195 | for(i = 0; i < PREALLOCATED_PMDS; i++) |
192 | if (pmds[i]) | 196 | if (pmds[i]) { |
197 | pgtable_pmd_page_dtor(virt_to_page(pmds[i])); | ||
193 | free_page((unsigned long)pmds[i]); | 198 | free_page((unsigned long)pmds[i]); |
199 | } | ||
194 | } | 200 | } |
195 | 201 | ||
196 | static int preallocate_pmds(pmd_t *pmds[]) | 202 | static int preallocate_pmds(pmd_t *pmds[]) |
@@ -200,8 +206,13 @@ static int preallocate_pmds(pmd_t *pmds[]) | |||
200 | 206 | ||
201 | for(i = 0; i < PREALLOCATED_PMDS; i++) { | 207 | for(i = 0; i < PREALLOCATED_PMDS; i++) { |
202 | pmd_t *pmd = (pmd_t *)__get_free_page(PGALLOC_GFP); | 208 | pmd_t *pmd = (pmd_t *)__get_free_page(PGALLOC_GFP); |
203 | if (pmd == NULL) | 209 | if (!pmd) |
204 | failed = true; | 210 | failed = true; |
211 | if (pmd && !pgtable_pmd_page_ctor(virt_to_page(pmd))) { | ||
212 | free_page((unsigned long)pmds[i]); | ||
213 | pmd = NULL; | ||
214 | failed = true; | ||
215 | } | ||
205 | pmds[i] = pmd; | 216 | pmds[i] = pmd; |
206 | } | 217 | } |
207 | 218 | ||
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index 79c216aa0e2b..26328e800869 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c | |||
@@ -772,13 +772,23 @@ out: | |||
772 | return; | 772 | return; |
773 | } | 773 | } |
774 | 774 | ||
775 | static void bpf_jit_free_deferred(struct work_struct *work) | ||
776 | { | ||
777 | struct sk_filter *fp = container_of(work, struct sk_filter, work); | ||
778 | unsigned long addr = (unsigned long)fp->bpf_func & PAGE_MASK; | ||
779 | struct bpf_binary_header *header = (void *)addr; | ||
780 | |||
781 | set_memory_rw(addr, header->pages); | ||
782 | module_free(NULL, header); | ||
783 | kfree(fp); | ||
784 | } | ||
785 | |||
775 | void bpf_jit_free(struct sk_filter *fp) | 786 | void bpf_jit_free(struct sk_filter *fp) |
776 | { | 787 | { |
777 | if (fp->bpf_func != sk_run_filter) { | 788 | if (fp->bpf_func != sk_run_filter) { |
778 | unsigned long addr = (unsigned long)fp->bpf_func & PAGE_MASK; | 789 | INIT_WORK(&fp->work, bpf_jit_free_deferred); |
779 | struct bpf_binary_header *header = (void *)addr; | 790 | schedule_work(&fp->work); |
780 | 791 | } else { | |
781 | set_memory_rw(addr, header->pages); | 792 | kfree(fp); |
782 | module_free(NULL, header); | ||
783 | } | 793 | } |
784 | } | 794 | } |
diff --git a/arch/x86/oprofile/backtrace.c b/arch/x86/oprofile/backtrace.c index d6aa6e8315d1..5d04be5efb64 100644 --- a/arch/x86/oprofile/backtrace.c +++ b/arch/x86/oprofile/backtrace.c | |||
@@ -47,7 +47,7 @@ dump_user_backtrace_32(struct stack_frame_ia32 *head) | |||
47 | unsigned long bytes; | 47 | unsigned long bytes; |
48 | 48 | ||
49 | bytes = copy_from_user_nmi(bufhead, head, sizeof(bufhead)); | 49 | bytes = copy_from_user_nmi(bufhead, head, sizeof(bufhead)); |
50 | if (bytes != sizeof(bufhead)) | 50 | if (bytes != 0) |
51 | return NULL; | 51 | return NULL; |
52 | 52 | ||
53 | fp = (struct stack_frame_ia32 *) compat_ptr(bufhead[0].next_frame); | 53 | fp = (struct stack_frame_ia32 *) compat_ptr(bufhead[0].next_frame); |
@@ -93,7 +93,7 @@ static struct stack_frame *dump_user_backtrace(struct stack_frame *head) | |||
93 | unsigned long bytes; | 93 | unsigned long bytes; |
94 | 94 | ||
95 | bytes = copy_from_user_nmi(bufhead, head, sizeof(bufhead)); | 95 | bytes = copy_from_user_nmi(bufhead, head, sizeof(bufhead)); |
96 | if (bytes != sizeof(bufhead)) | 96 | if (bytes != 0) |
97 | return NULL; | 97 | return NULL; |
98 | 98 | ||
99 | oprofile_add_trace(bufhead[0].return_address); | 99 | oprofile_add_trace(bufhead[0].return_address); |
diff --git a/arch/x86/pci/Makefile b/arch/x86/pci/Makefile index ee0af58ca5bd..e063eed0f912 100644 --- a/arch/x86/pci/Makefile +++ b/arch/x86/pci/Makefile | |||
@@ -18,7 +18,7 @@ obj-$(CONFIG_X86_VISWS) += visws.o | |||
18 | obj-$(CONFIG_X86_NUMAQ) += numaq_32.o | 18 | obj-$(CONFIG_X86_NUMAQ) += numaq_32.o |
19 | obj-$(CONFIG_X86_NUMACHIP) += numachip.o | 19 | obj-$(CONFIG_X86_NUMACHIP) += numachip.o |
20 | 20 | ||
21 | obj-$(CONFIG_X86_INTEL_MID) += mrst.o | 21 | obj-$(CONFIG_X86_INTEL_MID) += intel_mid_pci.o |
22 | 22 | ||
23 | obj-y += common.o early.o | 23 | obj-y += common.o early.o |
24 | obj-y += bus_numa.o | 24 | obj-y += bus_numa.o |
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index b30e937689d6..7fb24e53d4c8 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c | |||
@@ -354,12 +354,12 @@ static void coalesce_windows(struct pci_root_info *info, unsigned long type) | |||
354 | * the kernel resource tree doesn't allow overlaps. | 354 | * the kernel resource tree doesn't allow overlaps. |
355 | */ | 355 | */ |
356 | if (resource_overlaps(res1, res2)) { | 356 | if (resource_overlaps(res1, res2)) { |
357 | res1->start = min(res1->start, res2->start); | 357 | res2->start = min(res1->start, res2->start); |
358 | res1->end = max(res1->end, res2->end); | 358 | res2->end = max(res1->end, res2->end); |
359 | dev_info(&info->bridge->dev, | 359 | dev_info(&info->bridge->dev, |
360 | "host bridge window expanded to %pR; %pR ignored\n", | 360 | "host bridge window expanded to %pR; %pR ignored\n", |
361 | res1, res2); | 361 | res2, res1); |
362 | res2->flags = 0; | 362 | res1->flags = 0; |
363 | } | 363 | } |
364 | } | 364 | } |
365 | } | 365 | } |
diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c index f5809fa2753e..b046e070e088 100644 --- a/arch/x86/pci/fixup.c +++ b/arch/x86/pci/fixup.c | |||
@@ -231,7 +231,7 @@ static int quirk_pcie_aspm_write(struct pci_bus *bus, unsigned int devfn, int wh | |||
231 | offset = quirk_aspm_offset[GET_INDEX(bus->self->device, devfn)]; | 231 | offset = quirk_aspm_offset[GET_INDEX(bus->self->device, devfn)]; |
232 | 232 | ||
233 | if ((offset) && (where == offset)) | 233 | if ((offset) && (where == offset)) |
234 | value = value & 0xfffffffc; | 234 | value = value & ~PCI_EXP_LNKCTL_ASPMC; |
235 | 235 | ||
236 | return raw_pci_write(pci_domain_nr(bus), bus->number, | 236 | return raw_pci_write(pci_domain_nr(bus), bus->number, |
237 | devfn, where, size, value); | 237 | devfn, where, size, value); |
@@ -252,7 +252,7 @@ static struct pci_ops quirk_pcie_aspm_ops = { | |||
252 | */ | 252 | */ |
253 | static void pcie_rootport_aspm_quirk(struct pci_dev *pdev) | 253 | static void pcie_rootport_aspm_quirk(struct pci_dev *pdev) |
254 | { | 254 | { |
255 | int cap_base, i; | 255 | int i; |
256 | struct pci_bus *pbus; | 256 | struct pci_bus *pbus; |
257 | struct pci_dev *dev; | 257 | struct pci_dev *dev; |
258 | 258 | ||
@@ -278,7 +278,7 @@ static void pcie_rootport_aspm_quirk(struct pci_dev *pdev) | |||
278 | for (i = GET_INDEX(pdev->device, 0); i <= GET_INDEX(pdev->device, 7); ++i) | 278 | for (i = GET_INDEX(pdev->device, 0); i <= GET_INDEX(pdev->device, 7); ++i) |
279 | quirk_aspm_offset[i] = 0; | 279 | quirk_aspm_offset[i] = 0; |
280 | 280 | ||
281 | pbus->ops = pbus->parent->ops; | 281 | pci_bus_set_ops(pbus, pbus->parent->ops); |
282 | } else { | 282 | } else { |
283 | /* | 283 | /* |
284 | * If devices are attached to the root port at power-up or | 284 | * If devices are attached to the root port at power-up or |
@@ -286,13 +286,15 @@ static void pcie_rootport_aspm_quirk(struct pci_dev *pdev) | |||
286 | * each root port to save the register offsets and replace the | 286 | * each root port to save the register offsets and replace the |
287 | * bus ops. | 287 | * bus ops. |
288 | */ | 288 | */ |
289 | list_for_each_entry(dev, &pbus->devices, bus_list) { | 289 | list_for_each_entry(dev, &pbus->devices, bus_list) |
290 | /* There are 0 to 8 devices attached to this bus */ | 290 | /* There are 0 to 8 devices attached to this bus */ |
291 | cap_base = pci_find_capability(dev, PCI_CAP_ID_EXP); | 291 | quirk_aspm_offset[GET_INDEX(pdev->device, dev->devfn)] = |
292 | quirk_aspm_offset[GET_INDEX(pdev->device, dev->devfn)] = cap_base + 0x10; | 292 | dev->pcie_cap + PCI_EXP_LNKCTL; |
293 | } | 293 | |
294 | pbus->ops = &quirk_pcie_aspm_ops; | 294 | pci_bus_set_ops(pbus, &quirk_pcie_aspm_ops); |
295 | dev_info(&pbus->dev, "writes to ASPM control bits will be ignored\n"); | ||
295 | } | 296 | } |
297 | |||
296 | } | 298 | } |
297 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PA, pcie_rootport_aspm_quirk); | 299 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PA, pcie_rootport_aspm_quirk); |
298 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PA1, pcie_rootport_aspm_quirk); | 300 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PA1, pcie_rootport_aspm_quirk); |
diff --git a/arch/x86/pci/mrst.c b/arch/x86/pci/intel_mid_pci.c index 903fded50786..51384ca727ad 100644 --- a/arch/x86/pci/mrst.c +++ b/arch/x86/pci/intel_mid_pci.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Moorestown PCI support | 2 | * Intel MID PCI support |
3 | * Copyright (c) 2008 Intel Corporation | 3 | * Copyright (c) 2008 Intel Corporation |
4 | * Jesse Barnes <jesse.barnes@intel.com> | 4 | * Jesse Barnes <jesse.barnes@intel.com> |
5 | * | 5 | * |
@@ -150,12 +150,12 @@ static bool type1_access_ok(unsigned int bus, unsigned int devfn, int reg) | |||
150 | * shim. Therefore, use the header type in shim instead. | 150 | * shim. Therefore, use the header type in shim instead. |
151 | */ | 151 | */ |
152 | if (reg >= 0x100 || reg == PCI_STATUS || reg == PCI_HEADER_TYPE) | 152 | if (reg >= 0x100 || reg == PCI_STATUS || reg == PCI_HEADER_TYPE) |
153 | return 0; | 153 | return false; |
154 | if (bus == 0 && (devfn == PCI_DEVFN(2, 0) | 154 | if (bus == 0 && (devfn == PCI_DEVFN(2, 0) |
155 | || devfn == PCI_DEVFN(0, 0) | 155 | || devfn == PCI_DEVFN(0, 0) |
156 | || devfn == PCI_DEVFN(3, 0))) | 156 | || devfn == PCI_DEVFN(3, 0))) |
157 | return 1; | 157 | return true; |
158 | return 0; /* Langwell on others */ | 158 | return false; /* Langwell on others */ |
159 | } | 159 | } |
160 | 160 | ||
161 | static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, | 161 | static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, |
@@ -205,7 +205,7 @@ static int pci_write(struct pci_bus *bus, unsigned int devfn, int where, | |||
205 | where, size, value); | 205 | where, size, value); |
206 | } | 206 | } |
207 | 207 | ||
208 | static int mrst_pci_irq_enable(struct pci_dev *dev) | 208 | static int intel_mid_pci_irq_enable(struct pci_dev *dev) |
209 | { | 209 | { |
210 | u8 pin; | 210 | u8 pin; |
211 | struct io_apic_irq_attr irq_attr; | 211 | struct io_apic_irq_attr irq_attr; |
@@ -225,23 +225,23 @@ static int mrst_pci_irq_enable(struct pci_dev *dev) | |||
225 | return 0; | 225 | return 0; |
226 | } | 226 | } |
227 | 227 | ||
228 | struct pci_ops pci_mrst_ops = { | 228 | struct pci_ops intel_mid_pci_ops = { |
229 | .read = pci_read, | 229 | .read = pci_read, |
230 | .write = pci_write, | 230 | .write = pci_write, |
231 | }; | 231 | }; |
232 | 232 | ||
233 | /** | 233 | /** |
234 | * pci_mrst_init - installs pci_mrst_ops | 234 | * intel_mid_pci_init - installs intel_mid_pci_ops |
235 | * | 235 | * |
236 | * Moorestown has an interesting PCI implementation (see above). | 236 | * Moorestown has an interesting PCI implementation (see above). |
237 | * Called when the early platform detection installs it. | 237 | * Called when the early platform detection installs it. |
238 | */ | 238 | */ |
239 | int __init pci_mrst_init(void) | 239 | int __init intel_mid_pci_init(void) |
240 | { | 240 | { |
241 | pr_info("Intel MID platform detected, using MID PCI ops\n"); | 241 | pr_info("Intel MID platform detected, using MID PCI ops\n"); |
242 | pci_mmcfg_late_init(); | 242 | pci_mmcfg_late_init(); |
243 | pcibios_enable_irq = mrst_pci_irq_enable; | 243 | pcibios_enable_irq = intel_mid_pci_irq_enable; |
244 | pci_root_ops = pci_mrst_ops; | 244 | pci_root_ops = intel_mid_pci_ops; |
245 | pci_soc_mode = 1; | 245 | pci_soc_mode = 1; |
246 | /* Continue with standard init */ | 246 | /* Continue with standard init */ |
247 | return 1; | 247 | return 1; |
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index 48e8461057ba..5eee4959785d 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c | |||
@@ -382,7 +382,14 @@ static void xen_teardown_msi_irq(unsigned int irq) | |||
382 | { | 382 | { |
383 | xen_destroy_irq(irq); | 383 | xen_destroy_irq(irq); |
384 | } | 384 | } |
385 | 385 | static u32 xen_nop_msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) | |
386 | { | ||
387 | return 0; | ||
388 | } | ||
389 | static u32 xen_nop_msix_mask_irq(struct msi_desc *desc, u32 flag) | ||
390 | { | ||
391 | return 0; | ||
392 | } | ||
386 | #endif | 393 | #endif |
387 | 394 | ||
388 | int __init pci_xen_init(void) | 395 | int __init pci_xen_init(void) |
@@ -406,6 +413,8 @@ int __init pci_xen_init(void) | |||
406 | x86_msi.setup_msi_irqs = xen_setup_msi_irqs; | 413 | x86_msi.setup_msi_irqs = xen_setup_msi_irqs; |
407 | x86_msi.teardown_msi_irq = xen_teardown_msi_irq; | 414 | x86_msi.teardown_msi_irq = xen_teardown_msi_irq; |
408 | x86_msi.teardown_msi_irqs = xen_teardown_msi_irqs; | 415 | x86_msi.teardown_msi_irqs = xen_teardown_msi_irqs; |
416 | x86_msi.msi_mask_irq = xen_nop_msi_mask_irq; | ||
417 | x86_msi.msix_mask_irq = xen_nop_msix_mask_irq; | ||
409 | #endif | 418 | #endif |
410 | return 0; | 419 | return 0; |
411 | } | 420 | } |
@@ -485,6 +494,8 @@ int __init pci_xen_initial_domain(void) | |||
485 | x86_msi.setup_msi_irqs = xen_initdom_setup_msi_irqs; | 494 | x86_msi.setup_msi_irqs = xen_initdom_setup_msi_irqs; |
486 | x86_msi.teardown_msi_irq = xen_teardown_msi_irq; | 495 | x86_msi.teardown_msi_irq = xen_teardown_msi_irq; |
487 | x86_msi.restore_msi_irqs = xen_initdom_restore_msi_irqs; | 496 | x86_msi.restore_msi_irqs = xen_initdom_restore_msi_irqs; |
497 | x86_msi.msi_mask_irq = xen_nop_msi_mask_irq; | ||
498 | x86_msi.msix_mask_irq = xen_nop_msix_mask_irq; | ||
488 | #endif | 499 | #endif |
489 | xen_setup_acpi_sci(); | 500 | xen_setup_acpi_sci(); |
490 | __acpi_register_gsi = acpi_register_gsi_xen; | 501 | __acpi_register_gsi = acpi_register_gsi_xen; |
diff --git a/arch/x86/platform/Makefile b/arch/x86/platform/Makefile index 01e0231a113e..20342d4c82ce 100644 --- a/arch/x86/platform/Makefile +++ b/arch/x86/platform/Makefile | |||
@@ -4,7 +4,7 @@ obj-y += efi/ | |||
4 | obj-y += geode/ | 4 | obj-y += geode/ |
5 | obj-y += goldfish/ | 5 | obj-y += goldfish/ |
6 | obj-y += iris/ | 6 | obj-y += iris/ |
7 | obj-y += mrst/ | 7 | obj-y += intel-mid/ |
8 | obj-y += olpc/ | 8 | obj-y += olpc/ |
9 | obj-y += scx200/ | 9 | obj-y += scx200/ |
10 | obj-y += sfi/ | 10 | obj-y += sfi/ |
diff --git a/arch/x86/platform/efi/Makefile b/arch/x86/platform/efi/Makefile index 6db1cc4c7534..b7b0b35c1981 100644 --- a/arch/x86/platform/efi/Makefile +++ b/arch/x86/platform/efi/Makefile | |||
@@ -1,2 +1,3 @@ | |||
1 | obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o | 1 | obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o |
2 | obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o | 2 | obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o |
3 | obj-$(CONFIG_EARLY_PRINTK_EFI) += early_printk.o | ||
diff --git a/arch/x86/platform/efi/early_printk.c b/arch/x86/platform/efi/early_printk.c new file mode 100644 index 000000000000..6599a0027b76 --- /dev/null +++ b/arch/x86/platform/efi/early_printk.c | |||
@@ -0,0 +1,191 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013 Intel Corporation; author Matt Fleming | ||
3 | * | ||
4 | * This file is part of the Linux kernel, and is made available under | ||
5 | * the terms of the GNU General Public License version 2. | ||
6 | */ | ||
7 | |||
8 | #include <linux/console.h> | ||
9 | #include <linux/efi.h> | ||
10 | #include <linux/font.h> | ||
11 | #include <linux/io.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <asm/setup.h> | ||
14 | |||
15 | static const struct font_desc *font; | ||
16 | static u32 efi_x, efi_y; | ||
17 | |||
18 | static __init void early_efi_clear_scanline(unsigned int y) | ||
19 | { | ||
20 | unsigned long base, *dst; | ||
21 | u16 len; | ||
22 | |||
23 | base = boot_params.screen_info.lfb_base; | ||
24 | len = boot_params.screen_info.lfb_linelength; | ||
25 | |||
26 | dst = early_ioremap(base + y*len, len); | ||
27 | if (!dst) | ||
28 | return; | ||
29 | |||
30 | memset(dst, 0, len); | ||
31 | early_iounmap(dst, len); | ||
32 | } | ||
33 | |||
34 | static __init void early_efi_scroll_up(void) | ||
35 | { | ||
36 | unsigned long base, *dst, *src; | ||
37 | u16 len; | ||
38 | u32 i, height; | ||
39 | |||
40 | base = boot_params.screen_info.lfb_base; | ||
41 | len = boot_params.screen_info.lfb_linelength; | ||
42 | height = boot_params.screen_info.lfb_height; | ||
43 | |||
44 | for (i = 0; i < height - font->height; i++) { | ||
45 | dst = early_ioremap(base + i*len, len); | ||
46 | if (!dst) | ||
47 | return; | ||
48 | |||
49 | src = early_ioremap(base + (i + font->height) * len, len); | ||
50 | if (!src) { | ||
51 | early_iounmap(dst, len); | ||
52 | return; | ||
53 | } | ||
54 | |||
55 | memmove(dst, src, len); | ||
56 | |||
57 | early_iounmap(src, len); | ||
58 | early_iounmap(dst, len); | ||
59 | } | ||
60 | } | ||
61 | |||
62 | static void early_efi_write_char(u32 *dst, unsigned char c, unsigned int h) | ||
63 | { | ||
64 | const u32 color_black = 0x00000000; | ||
65 | const u32 color_white = 0x00ffffff; | ||
66 | const u8 *src; | ||
67 | u8 s8; | ||
68 | int m; | ||
69 | |||
70 | src = font->data + c * font->height; | ||
71 | s8 = *(src + h); | ||
72 | |||
73 | for (m = 0; m < 8; m++) { | ||
74 | if ((s8 >> (7 - m)) & 1) | ||
75 | *dst = color_white; | ||
76 | else | ||
77 | *dst = color_black; | ||
78 | dst++; | ||
79 | } | ||
80 | } | ||
81 | |||
82 | static __init void | ||
83 | early_efi_write(struct console *con, const char *str, unsigned int num) | ||
84 | { | ||
85 | struct screen_info *si; | ||
86 | unsigned long base; | ||
87 | unsigned int len; | ||
88 | const char *s; | ||
89 | void *dst; | ||
90 | |||
91 | base = boot_params.screen_info.lfb_base; | ||
92 | si = &boot_params.screen_info; | ||
93 | len = si->lfb_linelength; | ||
94 | |||
95 | while (num) { | ||
96 | unsigned int linemax; | ||
97 | unsigned int h, count = 0; | ||
98 | |||
99 | for (s = str; *s && *s != '\n'; s++) { | ||
100 | if (count == num) | ||
101 | break; | ||
102 | count++; | ||
103 | } | ||
104 | |||
105 | linemax = (si->lfb_width - efi_x) / font->width; | ||
106 | if (count > linemax) | ||
107 | count = linemax; | ||
108 | |||
109 | for (h = 0; h < font->height; h++) { | ||
110 | unsigned int n, x; | ||
111 | |||
112 | dst = early_ioremap(base + (efi_y + h) * len, len); | ||
113 | if (!dst) | ||
114 | return; | ||
115 | |||
116 | s = str; | ||
117 | n = count; | ||
118 | x = efi_x; | ||
119 | |||
120 | while (n-- > 0) { | ||
121 | early_efi_write_char(dst + x*4, *s, h); | ||
122 | x += font->width; | ||
123 | s++; | ||
124 | } | ||
125 | |||
126 | early_iounmap(dst, len); | ||
127 | } | ||
128 | |||
129 | num -= count; | ||
130 | efi_x += count * font->width; | ||
131 | str += count; | ||
132 | |||
133 | if (num > 0 && *s == '\n') { | ||
134 | efi_x = 0; | ||
135 | efi_y += font->height; | ||
136 | str++; | ||
137 | num--; | ||
138 | } | ||
139 | |||
140 | if (efi_x >= si->lfb_width) { | ||
141 | efi_x = 0; | ||
142 | efi_y += font->height; | ||
143 | } | ||
144 | |||
145 | if (efi_y + font->height >= si->lfb_height) { | ||
146 | u32 i; | ||
147 | |||
148 | efi_y -= font->height; | ||
149 | early_efi_scroll_up(); | ||
150 | |||
151 | for (i = 0; i < font->height; i++) | ||
152 | early_efi_clear_scanline(efi_y + i); | ||
153 | } | ||
154 | } | ||
155 | } | ||
156 | |||
157 | static __init int early_efi_setup(struct console *con, char *options) | ||
158 | { | ||
159 | struct screen_info *si; | ||
160 | u16 xres, yres; | ||
161 | u32 i; | ||
162 | |||
163 | si = &boot_params.screen_info; | ||
164 | xres = si->lfb_width; | ||
165 | yres = si->lfb_height; | ||
166 | |||
167 | /* | ||
168 | * early_efi_write_char() implicitly assumes a framebuffer with | ||
169 | * 32-bits per pixel. | ||
170 | */ | ||
171 | if (si->lfb_depth != 32) | ||
172 | return -ENODEV; | ||
173 | |||
174 | font = get_default_font(xres, yres, -1, -1); | ||
175 | if (!font) | ||
176 | return -ENODEV; | ||
177 | |||
178 | efi_y = rounddown(yres, font->height) - font->height; | ||
179 | for (i = 0; i < (yres - efi_y) / font->height; i++) | ||
180 | early_efi_scroll_up(); | ||
181 | |||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | struct console early_efi_console = { | ||
186 | .name = "earlyefi", | ||
187 | .write = early_efi_write, | ||
188 | .setup = early_efi_setup, | ||
189 | .flags = CON_PRINTBUFFER, | ||
190 | .index = -1, | ||
191 | }; | ||
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index c7e22ab29a5a..92c02344a060 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c | |||
@@ -60,19 +60,6 @@ | |||
60 | 60 | ||
61 | static efi_char16_t efi_dummy_name[6] = { 'D', 'U', 'M', 'M', 'Y', 0 }; | 61 | static efi_char16_t efi_dummy_name[6] = { 'D', 'U', 'M', 'M', 'Y', 0 }; |
62 | 62 | ||
63 | struct efi __read_mostly efi = { | ||
64 | .mps = EFI_INVALID_TABLE_ADDR, | ||
65 | .acpi = EFI_INVALID_TABLE_ADDR, | ||
66 | .acpi20 = EFI_INVALID_TABLE_ADDR, | ||
67 | .smbios = EFI_INVALID_TABLE_ADDR, | ||
68 | .sal_systab = EFI_INVALID_TABLE_ADDR, | ||
69 | .boot_info = EFI_INVALID_TABLE_ADDR, | ||
70 | .hcdp = EFI_INVALID_TABLE_ADDR, | ||
71 | .uga = EFI_INVALID_TABLE_ADDR, | ||
72 | .uv_systab = EFI_INVALID_TABLE_ADDR, | ||
73 | }; | ||
74 | EXPORT_SYMBOL(efi); | ||
75 | |||
76 | struct efi_memory_map memmap; | 63 | struct efi_memory_map memmap; |
77 | 64 | ||
78 | static struct efi efi_phys __initdata; | 65 | static struct efi efi_phys __initdata; |
@@ -80,6 +67,13 @@ static efi_system_table_t efi_systab __initdata; | |||
80 | 67 | ||
81 | unsigned long x86_efi_facility; | 68 | unsigned long x86_efi_facility; |
82 | 69 | ||
70 | static __initdata efi_config_table_type_t arch_tables[] = { | ||
71 | #ifdef CONFIG_X86_UV | ||
72 | {UV_SYSTEM_TABLE_GUID, "UVsystab", &efi.uv_systab}, | ||
73 | #endif | ||
74 | {NULL_GUID, NULL, NULL}, | ||
75 | }; | ||
76 | |||
83 | /* | 77 | /* |
84 | * Returns 1 if 'facility' is enabled, 0 otherwise. | 78 | * Returns 1 if 'facility' is enabled, 0 otherwise. |
85 | */ | 79 | */ |
@@ -399,6 +393,8 @@ int __init efi_memblock_x86_reserve_range(void) | |||
399 | 393 | ||
400 | memblock_reserve(pmap, memmap.nr_map * memmap.desc_size); | 394 | memblock_reserve(pmap, memmap.nr_map * memmap.desc_size); |
401 | 395 | ||
396 | efi.memmap = &memmap; | ||
397 | |||
402 | return 0; | 398 | return 0; |
403 | } | 399 | } |
404 | 400 | ||
@@ -578,80 +574,6 @@ static int __init efi_systab_init(void *phys) | |||
578 | return 0; | 574 | return 0; |
579 | } | 575 | } |
580 | 576 | ||
581 | static int __init efi_config_init(u64 tables, int nr_tables) | ||
582 | { | ||
583 | void *config_tables, *tablep; | ||
584 | int i, sz; | ||
585 | |||
586 | if (efi_enabled(EFI_64BIT)) | ||
587 | sz = sizeof(efi_config_table_64_t); | ||
588 | else | ||
589 | sz = sizeof(efi_config_table_32_t); | ||
590 | |||
591 | /* | ||
592 | * Let's see what config tables the firmware passed to us. | ||
593 | */ | ||
594 | config_tables = early_ioremap(tables, nr_tables * sz); | ||
595 | if (config_tables == NULL) { | ||
596 | pr_err("Could not map Configuration table!\n"); | ||
597 | return -ENOMEM; | ||
598 | } | ||
599 | |||
600 | tablep = config_tables; | ||
601 | pr_info(""); | ||
602 | for (i = 0; i < efi.systab->nr_tables; i++) { | ||
603 | efi_guid_t guid; | ||
604 | unsigned long table; | ||
605 | |||
606 | if (efi_enabled(EFI_64BIT)) { | ||
607 | u64 table64; | ||
608 | guid = ((efi_config_table_64_t *)tablep)->guid; | ||
609 | table64 = ((efi_config_table_64_t *)tablep)->table; | ||
610 | table = table64; | ||
611 | #ifdef CONFIG_X86_32 | ||
612 | if (table64 >> 32) { | ||
613 | pr_cont("\n"); | ||
614 | pr_err("Table located above 4GB, disabling EFI.\n"); | ||
615 | early_iounmap(config_tables, | ||
616 | efi.systab->nr_tables * sz); | ||
617 | return -EINVAL; | ||
618 | } | ||
619 | #endif | ||
620 | } else { | ||
621 | guid = ((efi_config_table_32_t *)tablep)->guid; | ||
622 | table = ((efi_config_table_32_t *)tablep)->table; | ||
623 | } | ||
624 | if (!efi_guidcmp(guid, MPS_TABLE_GUID)) { | ||
625 | efi.mps = table; | ||
626 | pr_cont(" MPS=0x%lx ", table); | ||
627 | } else if (!efi_guidcmp(guid, ACPI_20_TABLE_GUID)) { | ||
628 | efi.acpi20 = table; | ||
629 | pr_cont(" ACPI 2.0=0x%lx ", table); | ||
630 | } else if (!efi_guidcmp(guid, ACPI_TABLE_GUID)) { | ||
631 | efi.acpi = table; | ||
632 | pr_cont(" ACPI=0x%lx ", table); | ||
633 | } else if (!efi_guidcmp(guid, SMBIOS_TABLE_GUID)) { | ||
634 | efi.smbios = table; | ||
635 | pr_cont(" SMBIOS=0x%lx ", table); | ||
636 | #ifdef CONFIG_X86_UV | ||
637 | } else if (!efi_guidcmp(guid, UV_SYSTEM_TABLE_GUID)) { | ||
638 | efi.uv_systab = table; | ||
639 | pr_cont(" UVsystab=0x%lx ", table); | ||
640 | #endif | ||
641 | } else if (!efi_guidcmp(guid, HCDP_TABLE_GUID)) { | ||
642 | efi.hcdp = table; | ||
643 | pr_cont(" HCDP=0x%lx ", table); | ||
644 | } else if (!efi_guidcmp(guid, UGA_IO_PROTOCOL_GUID)) { | ||
645 | efi.uga = table; | ||
646 | pr_cont(" UGA=0x%lx ", table); | ||
647 | } | ||
648 | tablep += sz; | ||
649 | } | ||
650 | pr_cont("\n"); | ||
651 | early_iounmap(config_tables, efi.systab->nr_tables * sz); | ||
652 | return 0; | ||
653 | } | ||
654 | |||
655 | static int __init efi_runtime_init(void) | 577 | static int __init efi_runtime_init(void) |
656 | { | 578 | { |
657 | efi_runtime_services_t *runtime; | 579 | efi_runtime_services_t *runtime; |
@@ -745,7 +667,7 @@ void __init efi_init(void) | |||
745 | efi.systab->hdr.revision >> 16, | 667 | efi.systab->hdr.revision >> 16, |
746 | efi.systab->hdr.revision & 0xffff, vendor); | 668 | efi.systab->hdr.revision & 0xffff, vendor); |
747 | 669 | ||
748 | if (efi_config_init(efi.systab->tables, efi.systab->nr_tables)) | 670 | if (efi_config_init(arch_tables)) |
749 | return; | 671 | return; |
750 | 672 | ||
751 | set_bit(EFI_CONFIG_TABLES, &x86_efi_facility); | 673 | set_bit(EFI_CONFIG_TABLES, &x86_efi_facility); |
@@ -816,34 +738,6 @@ static void __init runtime_code_page_mkexec(void) | |||
816 | } | 738 | } |
817 | } | 739 | } |
818 | 740 | ||
819 | /* | ||
820 | * We can't ioremap data in EFI boot services RAM, because we've already mapped | ||
821 | * it as RAM. So, look it up in the existing EFI memory map instead. Only | ||
822 | * callable after efi_enter_virtual_mode and before efi_free_boot_services. | ||
823 | */ | ||
824 | void __iomem *efi_lookup_mapped_addr(u64 phys_addr) | ||
825 | { | ||
826 | void *p; | ||
827 | if (WARN_ON(!memmap.map)) | ||
828 | return NULL; | ||
829 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | ||
830 | efi_memory_desc_t *md = p; | ||
831 | u64 size = md->num_pages << EFI_PAGE_SHIFT; | ||
832 | u64 end = md->phys_addr + size; | ||
833 | if (!(md->attribute & EFI_MEMORY_RUNTIME) && | ||
834 | md->type != EFI_BOOT_SERVICES_CODE && | ||
835 | md->type != EFI_BOOT_SERVICES_DATA) | ||
836 | continue; | ||
837 | if (!md->virt_addr) | ||
838 | continue; | ||
839 | if (phys_addr >= md->phys_addr && phys_addr < end) { | ||
840 | phys_addr += md->virt_addr - md->phys_addr; | ||
841 | return (__force void __iomem *)(unsigned long)phys_addr; | ||
842 | } | ||
843 | } | ||
844 | return NULL; | ||
845 | } | ||
846 | |||
847 | void efi_memory_uc(u64 addr, unsigned long size) | 741 | void efi_memory_uc(u64 addr, unsigned long size) |
848 | { | 742 | { |
849 | unsigned long page_shift = 1UL << EFI_PAGE_SHIFT; | 743 | unsigned long page_shift = 1UL << EFI_PAGE_SHIFT; |
diff --git a/arch/x86/platform/geode/alix.c b/arch/x86/platform/geode/alix.c index 90e23e7679a5..76b6632d3143 100644 --- a/arch/x86/platform/geode/alix.c +++ b/arch/x86/platform/geode/alix.c | |||
@@ -98,7 +98,7 @@ static struct platform_device alix_leds_dev = { | |||
98 | .dev.platform_data = &alix_leds_data, | 98 | .dev.platform_data = &alix_leds_data, |
99 | }; | 99 | }; |
100 | 100 | ||
101 | static struct __initdata platform_device *alix_devs[] = { | 101 | static struct platform_device *alix_devs[] __initdata = { |
102 | &alix_buttons_dev, | 102 | &alix_buttons_dev, |
103 | &alix_leds_dev, | 103 | &alix_leds_dev, |
104 | }; | 104 | }; |
diff --git a/arch/x86/platform/geode/geos.c b/arch/x86/platform/geode/geos.c index c2e6d53558be..aa733fba2471 100644 --- a/arch/x86/platform/geode/geos.c +++ b/arch/x86/platform/geode/geos.c | |||
@@ -87,7 +87,7 @@ static struct platform_device geos_leds_dev = { | |||
87 | .dev.platform_data = &geos_leds_data, | 87 | .dev.platform_data = &geos_leds_data, |
88 | }; | 88 | }; |
89 | 89 | ||
90 | static struct __initdata platform_device *geos_devs[] = { | 90 | static struct platform_device *geos_devs[] __initdata = { |
91 | &geos_buttons_dev, | 91 | &geos_buttons_dev, |
92 | &geos_leds_dev, | 92 | &geos_leds_dev, |
93 | }; | 93 | }; |
diff --git a/arch/x86/platform/geode/net5501.c b/arch/x86/platform/geode/net5501.c index 646e3b5b4bb6..927e38c0089f 100644 --- a/arch/x86/platform/geode/net5501.c +++ b/arch/x86/platform/geode/net5501.c | |||
@@ -78,7 +78,7 @@ static struct platform_device net5501_leds_dev = { | |||
78 | .dev.platform_data = &net5501_leds_data, | 78 | .dev.platform_data = &net5501_leds_data, |
79 | }; | 79 | }; |
80 | 80 | ||
81 | static struct __initdata platform_device *net5501_devs[] = { | 81 | static struct platform_device *net5501_devs[] __initdata = { |
82 | &net5501_buttons_dev, | 82 | &net5501_buttons_dev, |
83 | &net5501_leds_dev, | 83 | &net5501_leds_dev, |
84 | }; | 84 | }; |
diff --git a/arch/x86/platform/intel-mid/Makefile b/arch/x86/platform/intel-mid/Makefile new file mode 100644 index 000000000000..01cc29ea5ff7 --- /dev/null +++ b/arch/x86/platform/intel-mid/Makefile | |||
@@ -0,0 +1,7 @@ | |||
1 | obj-$(CONFIG_X86_INTEL_MID) += intel-mid.o | ||
2 | obj-$(CONFIG_X86_INTEL_MID) += intel_mid_vrtc.o | ||
3 | obj-$(CONFIG_EARLY_PRINTK_INTEL_MID) += early_printk_intel_mid.o | ||
4 | # SFI specific code | ||
5 | ifdef CONFIG_X86_INTEL_MID | ||
6 | obj-$(CONFIG_SFI) += sfi.o device_libs/ | ||
7 | endif | ||
diff --git a/arch/x86/platform/intel-mid/device_libs/Makefile b/arch/x86/platform/intel-mid/device_libs/Makefile new file mode 100644 index 000000000000..097e7a7940d8 --- /dev/null +++ b/arch/x86/platform/intel-mid/device_libs/Makefile | |||
@@ -0,0 +1,22 @@ | |||
1 | # IPC Devices | ||
2 | obj-y += platform_ipc.o | ||
3 | obj-$(subst m,y,$(CONFIG_MFD_INTEL_MSIC)) += platform_msic.o | ||
4 | obj-$(subst m,y,$(CONFIG_SND_MFLD_MACHINE)) += platform_msic_audio.o | ||
5 | obj-$(subst m,y,$(CONFIG_GPIO_MSIC)) += platform_msic_gpio.o | ||
6 | obj-$(subst m,y,$(CONFIG_MFD_INTEL_MSIC)) += platform_msic_ocd.o | ||
7 | obj-$(subst m,y,$(CONFIG_MFD_INTEL_MSIC)) += platform_msic_battery.o | ||
8 | obj-$(subst m,y,$(CONFIG_INTEL_MID_POWER_BUTTON)) += platform_msic_power_btn.o | ||
9 | obj-$(subst m,y,$(CONFIG_GPIO_INTEL_PMIC)) += platform_pmic_gpio.o | ||
10 | obj-$(subst m,y,$(CONFIG_INTEL_MFLD_THERMAL)) += platform_msic_thermal.o | ||
11 | # I2C Devices | ||
12 | obj-$(subst m,y,$(CONFIG_SENSORS_EMC1403)) += platform_emc1403.o | ||
13 | obj-$(subst m,y,$(CONFIG_SENSORS_LIS3LV02D)) += platform_lis331.o | ||
14 | obj-$(subst m,y,$(CONFIG_GPIO_PCA953X)) += platform_max7315.o | ||
15 | obj-$(subst m,y,$(CONFIG_INPUT_MPU3050)) += platform_mpu3050.o | ||
16 | obj-$(subst m,y,$(CONFIG_INPUT_BMA150)) += platform_bma023.o | ||
17 | obj-$(subst m,y,$(CONFIG_GPIO_PCA953X)) += platform_tca6416.o | ||
18 | obj-$(subst m,y,$(CONFIG_DRM_MEDFIELD)) += platform_tc35876x.o | ||
19 | # SPI Devices | ||
20 | obj-$(subst m,y,$(CONFIG_SERIAL_MRST_MAX3110)) += platform_max3111.o | ||
21 | # MISC Devices | ||
22 | obj-$(subst m,y,$(CONFIG_KEYBOARD_GPIO)) += platform_gpio_keys.o | ||
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_bma023.c b/arch/x86/platform/intel-mid/device_libs/platform_bma023.c new file mode 100644 index 000000000000..0ae7f2ae2296 --- /dev/null +++ b/arch/x86/platform/intel-mid/device_libs/platform_bma023.c | |||
@@ -0,0 +1,20 @@ | |||
1 | /* | ||
2 | * platform_bma023.c: bma023 platform data initilization file | ||
3 | * | ||
4 | * (C) Copyright 2013 Intel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; version 2 | ||
9 | * of the License. | ||
10 | */ | ||
11 | |||
12 | #include <asm/intel-mid.h> | ||
13 | |||
14 | static const struct devs_id bma023_dev_id __initconst = { | ||
15 | .name = "bma023", | ||
16 | .type = SFI_DEV_TYPE_I2C, | ||
17 | .delay = 1, | ||
18 | }; | ||
19 | |||
20 | sfi_device(bma023_dev_id); | ||
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_emc1403.c b/arch/x86/platform/intel-mid/device_libs/platform_emc1403.c new file mode 100644 index 000000000000..0d942c1d26d5 --- /dev/null +++ b/arch/x86/platform/intel-mid/device_libs/platform_emc1403.c | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | * platform_emc1403.c: emc1403 platform data initilization file | ||
3 | * | ||
4 | * (C) Copyright 2013 Intel Corporation | ||
5 | * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; version 2 | ||
10 | * of the License. | ||
11 | */ | ||
12 | |||
13 | #include <linux/init.h> | ||
14 | #include <linux/gpio.h> | ||
15 | #include <linux/i2c.h> | ||
16 | #include <asm/intel-mid.h> | ||
17 | |||
18 | static void __init *emc1403_platform_data(void *info) | ||
19 | { | ||
20 | static short intr2nd_pdata; | ||
21 | struct i2c_board_info *i2c_info = info; | ||
22 | int intr = get_gpio_by_name("thermal_int"); | ||
23 | int intr2nd = get_gpio_by_name("thermal_alert"); | ||
24 | |||
25 | if (intr == -1 || intr2nd == -1) | ||
26 | return NULL; | ||
27 | |||
28 | i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET; | ||
29 | intr2nd_pdata = intr2nd + INTEL_MID_IRQ_OFFSET; | ||
30 | |||
31 | return &intr2nd_pdata; | ||
32 | } | ||
33 | |||
34 | static const struct devs_id emc1403_dev_id __initconst = { | ||
35 | .name = "emc1403", | ||
36 | .type = SFI_DEV_TYPE_I2C, | ||
37 | .delay = 1, | ||
38 | .get_platform_data = &emc1403_platform_data, | ||
39 | }; | ||
40 | |||
41 | sfi_device(emc1403_dev_id); | ||
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_gpio_keys.c b/arch/x86/platform/intel-mid/device_libs/platform_gpio_keys.c new file mode 100644 index 000000000000..a013a4834bbe --- /dev/null +++ b/arch/x86/platform/intel-mid/device_libs/platform_gpio_keys.c | |||
@@ -0,0 +1,83 @@ | |||
1 | /* | ||
2 | * platform_gpio_keys.c: gpio_keys platform data initilization file | ||
3 | * | ||
4 | * (C) Copyright 2013 Intel Corporation | ||
5 | * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; version 2 | ||
10 | * of the License. | ||
11 | */ | ||
12 | |||
13 | #include <linux/input.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/gpio.h> | ||
17 | #include <linux/gpio_keys.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <asm/intel-mid.h> | ||
20 | |||
21 | #define DEVICE_NAME "gpio-keys" | ||
22 | |||
23 | /* | ||
24 | * we will search these buttons in SFI GPIO table (by name) | ||
25 | * and register them dynamically. Please add all possible | ||
26 | * buttons here, we will shrink them if no GPIO found. | ||
27 | */ | ||
28 | static struct gpio_keys_button gpio_button[] = { | ||
29 | {KEY_POWER, -1, 1, "power_btn", EV_KEY, 0, 3000}, | ||
30 | {KEY_PROG1, -1, 1, "prog_btn1", EV_KEY, 0, 20}, | ||
31 | {KEY_PROG2, -1, 1, "prog_btn2", EV_KEY, 0, 20}, | ||
32 | {SW_LID, -1, 1, "lid_switch", EV_SW, 0, 20}, | ||
33 | {KEY_VOLUMEUP, -1, 1, "vol_up", EV_KEY, 0, 20}, | ||
34 | {KEY_VOLUMEDOWN, -1, 1, "vol_down", EV_KEY, 0, 20}, | ||
35 | {KEY_CAMERA, -1, 1, "camera_full", EV_KEY, 0, 20}, | ||
36 | {KEY_CAMERA_FOCUS, -1, 1, "camera_half", EV_KEY, 0, 20}, | ||
37 | {SW_KEYPAD_SLIDE, -1, 1, "MagSw1", EV_SW, 0, 20}, | ||
38 | {SW_KEYPAD_SLIDE, -1, 1, "MagSw2", EV_SW, 0, 20}, | ||
39 | }; | ||
40 | |||
41 | static struct gpio_keys_platform_data gpio_keys = { | ||
42 | .buttons = gpio_button, | ||
43 | .rep = 1, | ||
44 | .nbuttons = -1, /* will fill it after search */ | ||
45 | }; | ||
46 | |||
47 | static struct platform_device pb_device = { | ||
48 | .name = DEVICE_NAME, | ||
49 | .id = -1, | ||
50 | .dev = { | ||
51 | .platform_data = &gpio_keys, | ||
52 | }, | ||
53 | }; | ||
54 | |||
55 | /* | ||
56 | * Shrink the non-existent buttons, register the gpio button | ||
57 | * device if there is some | ||
58 | */ | ||
59 | static int __init pb_keys_init(void) | ||
60 | { | ||
61 | struct gpio_keys_button *gb = gpio_button; | ||
62 | int i, num, good = 0; | ||
63 | |||
64 | num = sizeof(gpio_button) / sizeof(struct gpio_keys_button); | ||
65 | for (i = 0; i < num; i++) { | ||
66 | gb[i].gpio = get_gpio_by_name(gb[i].desc); | ||
67 | pr_debug("info[%2d]: name = %s, gpio = %d\n", i, gb[i].desc, | ||
68 | gb[i].gpio); | ||
69 | if (gb[i].gpio == -1) | ||
70 | continue; | ||
71 | |||
72 | if (i != good) | ||
73 | gb[good] = gb[i]; | ||
74 | good++; | ||
75 | } | ||
76 | |||
77 | if (good) { | ||
78 | gpio_keys.nbuttons = good; | ||
79 | return platform_device_register(&pb_device); | ||
80 | } | ||
81 | return 0; | ||
82 | } | ||
83 | late_initcall(pb_keys_init); | ||
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_ipc.c b/arch/x86/platform/intel-mid/device_libs/platform_ipc.c new file mode 100644 index 000000000000..a84b73d6c4a0 --- /dev/null +++ b/arch/x86/platform/intel-mid/device_libs/platform_ipc.c | |||
@@ -0,0 +1,68 @@ | |||
1 | /* | ||
2 | * platform_ipc.c: IPC platform library file | ||
3 | * | ||
4 | * (C) Copyright 2013 Intel Corporation | ||
5 | * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; version 2 | ||
10 | * of the License. | ||
11 | */ | ||
12 | |||
13 | #include <linux/init.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/sfi.h> | ||
17 | #include <linux/gpio.h> | ||
18 | #include <asm/intel-mid.h> | ||
19 | #include "platform_ipc.h" | ||
20 | |||
21 | void __init ipc_device_handler(struct sfi_device_table_entry *pentry, | ||
22 | struct devs_id *dev) | ||
23 | { | ||
24 | struct platform_device *pdev; | ||
25 | void *pdata = NULL; | ||
26 | static struct resource res __initdata = { | ||
27 | .name = "IRQ", | ||
28 | .flags = IORESOURCE_IRQ, | ||
29 | }; | ||
30 | |||
31 | pr_debug("IPC bus, name = %16.16s, irq = 0x%2x\n", | ||
32 | pentry->name, pentry->irq); | ||
33 | |||
34 | /* | ||
35 | * We need to call platform init of IPC devices to fill misc_pdata | ||
36 | * structure. It will be used in msic_init for initialization. | ||
37 | */ | ||
38 | if (dev != NULL) | ||
39 | pdata = dev->get_platform_data(pentry); | ||
40 | |||
41 | /* | ||
42 | * On Medfield the platform device creation is handled by the MSIC | ||
43 | * MFD driver so we don't need to do it here. | ||
44 | */ | ||
45 | if (intel_mid_has_msic()) | ||
46 | return; | ||
47 | |||
48 | pdev = platform_device_alloc(pentry->name, 0); | ||
49 | if (pdev == NULL) { | ||
50 | pr_err("out of memory for SFI platform device '%s'.\n", | ||
51 | pentry->name); | ||
52 | return; | ||
53 | } | ||
54 | res.start = pentry->irq; | ||
55 | platform_device_add_resources(pdev, &res, 1); | ||
56 | |||
57 | pdev->dev.platform_data = pdata; | ||
58 | intel_scu_device_register(pdev); | ||
59 | } | ||
60 | |||
61 | static const struct devs_id pmic_audio_dev_id __initconst = { | ||
62 | .name = "pmic_audio", | ||
63 | .type = SFI_DEV_TYPE_IPC, | ||
64 | .delay = 1, | ||
65 | .device_handler = &ipc_device_handler, | ||
66 | }; | ||
67 | |||
68 | sfi_device(pmic_audio_dev_id); | ||
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_ipc.h b/arch/x86/platform/intel-mid/device_libs/platform_ipc.h new file mode 100644 index 000000000000..8f568dd79605 --- /dev/null +++ b/arch/x86/platform/intel-mid/device_libs/platform_ipc.h | |||
@@ -0,0 +1,17 @@ | |||
1 | /* | ||
2 | * platform_ipc.h: IPC platform library header file | ||
3 | * | ||
4 | * (C) Copyright 2013 Intel Corporation | ||
5 | * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; version 2 | ||
10 | * of the License. | ||
11 | */ | ||
12 | #ifndef _PLATFORM_IPC_H_ | ||
13 | #define _PLATFORM_IPC_H_ | ||
14 | |||
15 | extern void __init ipc_device_handler(struct sfi_device_table_entry *pentry, | ||
16 | struct devs_id *dev) __attribute__((weak)); | ||
17 | #endif | ||
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_lis331.c b/arch/x86/platform/intel-mid/device_libs/platform_lis331.c new file mode 100644 index 000000000000..15278c11f714 --- /dev/null +++ b/arch/x86/platform/intel-mid/device_libs/platform_lis331.c | |||
@@ -0,0 +1,39 @@ | |||
1 | /* | ||
2 | * platform_lis331.c: lis331 platform data initilization file | ||
3 | * | ||
4 | * (C) Copyright 2013 Intel Corporation | ||
5 | * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; version 2 | ||
10 | * of the License. | ||
11 | */ | ||
12 | |||
13 | #include <linux/i2c.h> | ||
14 | #include <linux/gpio.h> | ||
15 | #include <asm/intel-mid.h> | ||
16 | |||
17 | static void __init *lis331dl_platform_data(void *info) | ||
18 | { | ||
19 | static short intr2nd_pdata; | ||
20 | struct i2c_board_info *i2c_info = info; | ||
21 | int intr = get_gpio_by_name("accel_int"); | ||
22 | int intr2nd = get_gpio_by_name("accel_2"); | ||
23 | |||
24 | if (intr == -1 || intr2nd == -1) | ||
25 | return NULL; | ||
26 | |||
27 | i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET; | ||
28 | intr2nd_pdata = intr2nd + INTEL_MID_IRQ_OFFSET; | ||
29 | |||
30 | return &intr2nd_pdata; | ||
31 | } | ||
32 | |||
33 | static const struct devs_id lis331dl_dev_id __initconst = { | ||
34 | .name = "i2c_accel", | ||
35 | .type = SFI_DEV_TYPE_I2C, | ||
36 | .get_platform_data = &lis331dl_platform_data, | ||
37 | }; | ||
38 | |||
39 | sfi_device(lis331dl_dev_id); | ||
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_max3111.c b/arch/x86/platform/intel-mid/device_libs/platform_max3111.c new file mode 100644 index 000000000000..afd1df94e0e5 --- /dev/null +++ b/arch/x86/platform/intel-mid/device_libs/platform_max3111.c | |||
@@ -0,0 +1,35 @@ | |||
1 | /* | ||
2 | * platform_max3111.c: max3111 platform data initilization file | ||
3 | * | ||
4 | * (C) Copyright 2013 Intel Corporation | ||
5 | * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; version 2 | ||
10 | * of the License. | ||
11 | */ | ||
12 | |||
13 | #include <linux/gpio.h> | ||
14 | #include <linux/spi/spi.h> | ||
15 | #include <asm/intel-mid.h> | ||
16 | |||
17 | static void __init *max3111_platform_data(void *info) | ||
18 | { | ||
19 | struct spi_board_info *spi_info = info; | ||
20 | int intr = get_gpio_by_name("max3111_int"); | ||
21 | |||
22 | spi_info->mode = SPI_MODE_0; | ||
23 | if (intr == -1) | ||
24 | return NULL; | ||
25 | spi_info->irq = intr + INTEL_MID_IRQ_OFFSET; | ||
26 | return NULL; | ||
27 | } | ||
28 | |||
29 | static const struct devs_id max3111_dev_id __initconst = { | ||
30 | .name = "spi_max3111", | ||
31 | .type = SFI_DEV_TYPE_SPI, | ||
32 | .get_platform_data = &max3111_platform_data, | ||
33 | }; | ||
34 | |||
35 | sfi_device(max3111_dev_id); | ||
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_max7315.c b/arch/x86/platform/intel-mid/device_libs/platform_max7315.c new file mode 100644 index 000000000000..94ade10024ae --- /dev/null +++ b/arch/x86/platform/intel-mid/device_libs/platform_max7315.c | |||
@@ -0,0 +1,79 @@ | |||
1 | /* | ||
2 | * platform_max7315.c: max7315 platform data initilization file | ||
3 | * | ||
4 | * (C) Copyright 2013 Intel Corporation | ||
5 | * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; version 2 | ||
10 | * of the License. | ||
11 | */ | ||
12 | |||
13 | #include <linux/init.h> | ||
14 | #include <linux/gpio.h> | ||
15 | #include <linux/i2c.h> | ||
16 | #include <linux/platform_data/pca953x.h> | ||
17 | #include <asm/intel-mid.h> | ||
18 | |||
19 | #define MAX7315_NUM 2 | ||
20 | |||
21 | static void __init *max7315_platform_data(void *info) | ||
22 | { | ||
23 | static struct pca953x_platform_data max7315_pdata[MAX7315_NUM]; | ||
24 | static int nr; | ||
25 | struct pca953x_platform_data *max7315 = &max7315_pdata[nr]; | ||
26 | struct i2c_board_info *i2c_info = info; | ||
27 | int gpio_base, intr; | ||
28 | char base_pin_name[SFI_NAME_LEN + 1]; | ||
29 | char intr_pin_name[SFI_NAME_LEN + 1]; | ||
30 | |||
31 | if (nr == MAX7315_NUM) { | ||
32 | pr_err("too many max7315s, we only support %d\n", | ||
33 | MAX7315_NUM); | ||
34 | return NULL; | ||
35 | } | ||
36 | /* we have several max7315 on the board, we only need load several | ||
37 | * instances of the same pca953x driver to cover them | ||
38 | */ | ||
39 | strcpy(i2c_info->type, "max7315"); | ||
40 | if (nr++) { | ||
41 | sprintf(base_pin_name, "max7315_%d_base", nr); | ||
42 | sprintf(intr_pin_name, "max7315_%d_int", nr); | ||
43 | } else { | ||
44 | strcpy(base_pin_name, "max7315_base"); | ||
45 | strcpy(intr_pin_name, "max7315_int"); | ||
46 | } | ||
47 | |||
48 | gpio_base = get_gpio_by_name(base_pin_name); | ||
49 | intr = get_gpio_by_name(intr_pin_name); | ||
50 | |||
51 | if (gpio_base == -1) | ||
52 | return NULL; | ||
53 | max7315->gpio_base = gpio_base; | ||
54 | if (intr != -1) { | ||
55 | i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET; | ||
56 | max7315->irq_base = gpio_base + INTEL_MID_IRQ_OFFSET; | ||
57 | } else { | ||
58 | i2c_info->irq = -1; | ||
59 | max7315->irq_base = -1; | ||
60 | } | ||
61 | return max7315; | ||
62 | } | ||
63 | |||
64 | static const struct devs_id max7315_dev_id __initconst = { | ||
65 | .name = "i2c_max7315", | ||
66 | .type = SFI_DEV_TYPE_I2C, | ||
67 | .delay = 1, | ||
68 | .get_platform_data = &max7315_platform_data, | ||
69 | }; | ||
70 | |||
71 | static const struct devs_id max7315_2_dev_id __initconst = { | ||
72 | .name = "i2c_max7315_2", | ||
73 | .type = SFI_DEV_TYPE_I2C, | ||
74 | .delay = 1, | ||
75 | .get_platform_data = &max7315_platform_data, | ||
76 | }; | ||
77 | |||
78 | sfi_device(max7315_dev_id); | ||
79 | sfi_device(max7315_2_dev_id); | ||
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_mpu3050.c b/arch/x86/platform/intel-mid/device_libs/platform_mpu3050.c new file mode 100644 index 000000000000..dd28d63c84fb --- /dev/null +++ b/arch/x86/platform/intel-mid/device_libs/platform_mpu3050.c | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * platform_mpu3050.c: mpu3050 platform data initilization file | ||
3 | * | ||
4 | * (C) Copyright 2013 Intel Corporation | ||
5 | * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; version 2 | ||
10 | * of the License. | ||
11 | */ | ||
12 | |||
13 | #include <linux/gpio.h> | ||
14 | #include <linux/i2c.h> | ||
15 | #include <asm/intel-mid.h> | ||
16 | |||
17 | static void *mpu3050_platform_data(void *info) | ||
18 | { | ||
19 | struct i2c_board_info *i2c_info = info; | ||
20 | int intr = get_gpio_by_name("mpu3050_int"); | ||
21 | |||
22 | if (intr == -1) | ||
23 | return NULL; | ||
24 | |||
25 | i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET; | ||
26 | return NULL; | ||
27 | } | ||
28 | |||
29 | static const struct devs_id mpu3050_dev_id __initconst = { | ||
30 | .name = "mpu3050", | ||
31 | .type = SFI_DEV_TYPE_I2C, | ||
32 | .delay = 1, | ||
33 | .get_platform_data = &mpu3050_platform_data, | ||
34 | }; | ||
35 | |||
36 | sfi_device(mpu3050_dev_id); | ||
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_msic.c b/arch/x86/platform/intel-mid/device_libs/platform_msic.c new file mode 100644 index 000000000000..9f4a775a69d6 --- /dev/null +++ b/arch/x86/platform/intel-mid/device_libs/platform_msic.c | |||
@@ -0,0 +1,87 @@ | |||
1 | /* | ||
2 | * platform_msic.c: MSIC platform data initilization file | ||
3 | * | ||
4 | * (C) Copyright 2013 Intel Corporation | ||
5 | * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; version 2 | ||
10 | * of the License. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/scatterlist.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/sfi.h> | ||
18 | #include <linux/mfd/intel_msic.h> | ||
19 | #include <asm/intel_scu_ipc.h> | ||
20 | #include <asm/intel-mid.h> | ||
21 | #include "platform_msic.h" | ||
22 | |||
23 | struct intel_msic_platform_data msic_pdata; | ||
24 | |||
25 | static struct resource msic_resources[] = { | ||
26 | { | ||
27 | .start = INTEL_MSIC_IRQ_PHYS_BASE, | ||
28 | .end = INTEL_MSIC_IRQ_PHYS_BASE + 64 - 1, | ||
29 | .flags = IORESOURCE_MEM, | ||
30 | }, | ||
31 | }; | ||
32 | |||
33 | static struct platform_device msic_device = { | ||
34 | .name = "intel_msic", | ||
35 | .id = -1, | ||
36 | .dev = { | ||
37 | .platform_data = &msic_pdata, | ||
38 | }, | ||
39 | .num_resources = ARRAY_SIZE(msic_resources), | ||
40 | .resource = msic_resources, | ||
41 | }; | ||
42 | |||
43 | static int msic_scu_status_change(struct notifier_block *nb, | ||
44 | unsigned long code, void *data) | ||
45 | { | ||
46 | if (code == SCU_DOWN) { | ||
47 | platform_device_unregister(&msic_device); | ||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | return platform_device_register(&msic_device); | ||
52 | } | ||
53 | |||
54 | static int __init msic_init(void) | ||
55 | { | ||
56 | static struct notifier_block msic_scu_notifier = { | ||
57 | .notifier_call = msic_scu_status_change, | ||
58 | }; | ||
59 | |||
60 | /* | ||
61 | * We need to be sure that the SCU IPC is ready before MSIC device | ||
62 | * can be registered. | ||
63 | */ | ||
64 | if (intel_mid_has_msic()) | ||
65 | intel_scu_notifier_add(&msic_scu_notifier); | ||
66 | |||
67 | return 0; | ||
68 | } | ||
69 | arch_initcall(msic_init); | ||
70 | |||
71 | /* | ||
72 | * msic_generic_platform_data - sets generic platform data for the block | ||
73 | * @info: pointer to the SFI device table entry for this block | ||
74 | * @block: MSIC block | ||
75 | * | ||
76 | * Function sets IRQ number from the SFI table entry for given device to | ||
77 | * the MSIC platform data. | ||
78 | */ | ||
79 | void *msic_generic_platform_data(void *info, enum intel_msic_block block) | ||
80 | { | ||
81 | struct sfi_device_table_entry *entry = info; | ||
82 | |||
83 | BUG_ON(block < 0 || block >= INTEL_MSIC_BLOCK_LAST); | ||
84 | msic_pdata.irq[block] = entry->irq; | ||
85 | |||
86 | return NULL; | ||
87 | } | ||
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_msic.h b/arch/x86/platform/intel-mid/device_libs/platform_msic.h new file mode 100644 index 000000000000..917eb56d77da --- /dev/null +++ b/arch/x86/platform/intel-mid/device_libs/platform_msic.h | |||
@@ -0,0 +1,19 @@ | |||
1 | /* | ||
2 | * platform_msic.h: MSIC platform data header file | ||
3 | * | ||
4 | * (C) Copyright 2013 Intel Corporation | ||
5 | * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; version 2 | ||
10 | * of the License. | ||
11 | */ | ||
12 | #ifndef _PLATFORM_MSIC_H_ | ||
13 | #define _PLATFORM_MSIC_H_ | ||
14 | |||
15 | extern struct intel_msic_platform_data msic_pdata; | ||
16 | |||
17 | extern void *msic_generic_platform_data(void *info, | ||
18 | enum intel_msic_block block) __attribute__((weak)); | ||
19 | #endif | ||
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_msic_audio.c b/arch/x86/platform/intel-mid/device_libs/platform_msic_audio.c new file mode 100644 index 000000000000..29629397d2b3 --- /dev/null +++ b/arch/x86/platform/intel-mid/device_libs/platform_msic_audio.c | |||
@@ -0,0 +1,47 @@ | |||
1 | /* | ||
2 | * platform_msic_audio.c: MSIC audio platform data initilization file | ||
3 | * | ||
4 | * (C) Copyright 2013 Intel Corporation | ||
5 | * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; version 2 | ||
10 | * of the License. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/scatterlist.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/sfi.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/mfd/intel_msic.h> | ||
20 | #include <asm/intel-mid.h> | ||
21 | |||
22 | #include "platform_msic.h" | ||
23 | #include "platform_ipc.h" | ||
24 | |||
25 | static void *msic_audio_platform_data(void *info) | ||
26 | { | ||
27 | struct platform_device *pdev; | ||
28 | |||
29 | pdev = platform_device_register_simple("sst-platform", -1, NULL, 0); | ||
30 | |||
31 | if (IS_ERR(pdev)) { | ||
32 | pr_err("failed to create audio platform device\n"); | ||
33 | return NULL; | ||
34 | } | ||
35 | |||
36 | return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_AUDIO); | ||
37 | } | ||
38 | |||
39 | static const struct devs_id msic_audio_dev_id __initconst = { | ||
40 | .name = "msic_audio", | ||
41 | .type = SFI_DEV_TYPE_IPC, | ||
42 | .delay = 1, | ||
43 | .get_platform_data = &msic_audio_platform_data, | ||
44 | .device_handler = &ipc_device_handler, | ||
45 | }; | ||
46 | |||
47 | sfi_device(msic_audio_dev_id); | ||
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_msic_battery.c b/arch/x86/platform/intel-mid/device_libs/platform_msic_battery.c new file mode 100644 index 000000000000..f446c33df1a8 --- /dev/null +++ b/arch/x86/platform/intel-mid/device_libs/platform_msic_battery.c | |||
@@ -0,0 +1,37 @@ | |||
1 | /* | ||
2 | * platform_msic_battery.c: MSIC battery platform data initilization file | ||
3 | * | ||
4 | * (C) Copyright 2013 Intel Corporation | ||
5 | * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; version 2 | ||
10 | * of the License. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/scatterlist.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/sfi.h> | ||
18 | #include <linux/mfd/intel_msic.h> | ||
19 | #include <asm/intel-mid.h> | ||
20 | |||
21 | #include "platform_msic.h" | ||
22 | #include "platform_ipc.h" | ||
23 | |||
24 | static void __init *msic_battery_platform_data(void *info) | ||
25 | { | ||
26 | return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_BATTERY); | ||
27 | } | ||
28 | |||
29 | static const struct devs_id msic_battery_dev_id __initconst = { | ||
30 | .name = "msic_battery", | ||
31 | .type = SFI_DEV_TYPE_IPC, | ||
32 | .delay = 1, | ||
33 | .get_platform_data = &msic_battery_platform_data, | ||
34 | .device_handler = &ipc_device_handler, | ||
35 | }; | ||
36 | |||
37 | sfi_device(msic_battery_dev_id); | ||
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_msic_gpio.c b/arch/x86/platform/intel-mid/device_libs/platform_msic_gpio.c new file mode 100644 index 000000000000..2a4f7b1dd917 --- /dev/null +++ b/arch/x86/platform/intel-mid/device_libs/platform_msic_gpio.c | |||
@@ -0,0 +1,48 @@ | |||
1 | /* | ||
2 | * platform_msic_gpio.c: MSIC GPIO platform data initilization file | ||
3 | * | ||
4 | * (C) Copyright 2013 Intel Corporation | ||
5 | * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; version 2 | ||
10 | * of the License. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/scatterlist.h> | ||
16 | #include <linux/sfi.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/gpio.h> | ||
19 | #include <linux/mfd/intel_msic.h> | ||
20 | #include <asm/intel-mid.h> | ||
21 | |||
22 | #include "platform_msic.h" | ||
23 | #include "platform_ipc.h" | ||
24 | |||
25 | static void __init *msic_gpio_platform_data(void *info) | ||
26 | { | ||
27 | static struct intel_msic_gpio_pdata msic_gpio_pdata; | ||
28 | |||
29 | int gpio = get_gpio_by_name("msic_gpio_base"); | ||
30 | |||
31 | if (gpio < 0) | ||
32 | return NULL; | ||
33 | |||
34 | msic_gpio_pdata.gpio_base = gpio; | ||
35 | msic_pdata.gpio = &msic_gpio_pdata; | ||
36 | |||
37 | return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_GPIO); | ||
38 | } | ||
39 | |||
40 | static const struct devs_id msic_gpio_dev_id __initconst = { | ||
41 | .name = "msic_gpio", | ||
42 | .type = SFI_DEV_TYPE_IPC, | ||
43 | .delay = 1, | ||
44 | .get_platform_data = &msic_gpio_platform_data, | ||
45 | .device_handler = &ipc_device_handler, | ||
46 | }; | ||
47 | |||
48 | sfi_device(msic_gpio_dev_id); | ||
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_msic_ocd.c b/arch/x86/platform/intel-mid/device_libs/platform_msic_ocd.c new file mode 100644 index 000000000000..6497111ddb54 --- /dev/null +++ b/arch/x86/platform/intel-mid/device_libs/platform_msic_ocd.c | |||
@@ -0,0 +1,49 @@ | |||
1 | /* | ||
2 | * platform_msic_ocd.c: MSIC OCD platform data initilization file | ||
3 | * | ||
4 | * (C) Copyright 2013 Intel Corporation | ||
5 | * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; version 2 | ||
10 | * of the License. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/scatterlist.h> | ||
16 | #include <linux/sfi.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/gpio.h> | ||
19 | #include <linux/mfd/intel_msic.h> | ||
20 | #include <asm/intel-mid.h> | ||
21 | |||
22 | #include "platform_msic.h" | ||
23 | #include "platform_ipc.h" | ||
24 | |||
25 | static void __init *msic_ocd_platform_data(void *info) | ||
26 | { | ||
27 | static struct intel_msic_ocd_pdata msic_ocd_pdata; | ||
28 | int gpio; | ||
29 | |||
30 | gpio = get_gpio_by_name("ocd_gpio"); | ||
31 | |||
32 | if (gpio < 0) | ||
33 | return NULL; | ||
34 | |||
35 | msic_ocd_pdata.gpio = gpio; | ||
36 | msic_pdata.ocd = &msic_ocd_pdata; | ||
37 | |||
38 | return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_OCD); | ||
39 | } | ||
40 | |||
41 | static const struct devs_id msic_ocd_dev_id __initconst = { | ||
42 | .name = "msic_ocd", | ||
43 | .type = SFI_DEV_TYPE_IPC, | ||
44 | .delay = 1, | ||
45 | .get_platform_data = &msic_ocd_platform_data, | ||
46 | .device_handler = &ipc_device_handler, | ||
47 | }; | ||
48 | |||
49 | sfi_device(msic_ocd_dev_id); | ||
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_msic_power_btn.c b/arch/x86/platform/intel-mid/device_libs/platform_msic_power_btn.c new file mode 100644 index 000000000000..83a3459bc337 --- /dev/null +++ b/arch/x86/platform/intel-mid/device_libs/platform_msic_power_btn.c | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * platform_msic_power_btn.c: MSIC power btn platform data initilization file | ||
3 | * | ||
4 | * (C) Copyright 2013 Intel Corporation | ||
5 | * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; version 2 | ||
10 | * of the License. | ||
11 | */ | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/interrupt.h> | ||
14 | #include <linux/scatterlist.h> | ||
15 | #include <linux/sfi.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/mfd/intel_msic.h> | ||
18 | #include <asm/intel-mid.h> | ||
19 | |||
20 | #include "platform_msic.h" | ||
21 | #include "platform_ipc.h" | ||
22 | |||
23 | static void __init *msic_power_btn_platform_data(void *info) | ||
24 | { | ||
25 | return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_POWER_BTN); | ||
26 | } | ||
27 | |||
28 | static const struct devs_id msic_power_btn_dev_id __initconst = { | ||
29 | .name = "msic_power_btn", | ||
30 | .type = SFI_DEV_TYPE_IPC, | ||
31 | .delay = 1, | ||
32 | .get_platform_data = &msic_power_btn_platform_data, | ||
33 | .device_handler = &ipc_device_handler, | ||
34 | }; | ||
35 | |||
36 | sfi_device(msic_power_btn_dev_id); | ||
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_msic_thermal.c b/arch/x86/platform/intel-mid/device_libs/platform_msic_thermal.c new file mode 100644 index 000000000000..a351878b96bc --- /dev/null +++ b/arch/x86/platform/intel-mid/device_libs/platform_msic_thermal.c | |||
@@ -0,0 +1,37 @@ | |||
1 | /* | ||
2 | * platform_msic_thermal.c: msic_thermal platform data initilization file | ||
3 | * | ||
4 | * (C) Copyright 2013 Intel Corporation | ||
5 | * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; version 2 | ||
10 | * of the License. | ||
11 | */ | ||
12 | |||
13 | #include <linux/input.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/gpio.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/mfd/intel_msic.h> | ||
19 | #include <asm/intel-mid.h> | ||
20 | |||
21 | #include "platform_msic.h" | ||
22 | #include "platform_ipc.h" | ||
23 | |||
24 | static void __init *msic_thermal_platform_data(void *info) | ||
25 | { | ||
26 | return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_THERMAL); | ||
27 | } | ||
28 | |||
29 | static const struct devs_id msic_thermal_dev_id __initconst = { | ||
30 | .name = "msic_thermal", | ||
31 | .type = SFI_DEV_TYPE_IPC, | ||
32 | .delay = 1, | ||
33 | .get_platform_data = &msic_thermal_platform_data, | ||
34 | .device_handler = &ipc_device_handler, | ||
35 | }; | ||
36 | |||
37 | sfi_device(msic_thermal_dev_id); | ||
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_pmic_gpio.c b/arch/x86/platform/intel-mid/device_libs/platform_pmic_gpio.c new file mode 100644 index 000000000000..d87182a09263 --- /dev/null +++ b/arch/x86/platform/intel-mid/device_libs/platform_pmic_gpio.c | |||
@@ -0,0 +1,54 @@ | |||
1 | /* | ||
2 | * platform_pmic_gpio.c: PMIC GPIO platform data initilization file | ||
3 | * | ||
4 | * (C) Copyright 2013 Intel Corporation | ||
5 | * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; version 2 | ||
10 | * of the License. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/scatterlist.h> | ||
16 | #include <linux/gpio.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/sfi.h> | ||
19 | #include <linux/intel_pmic_gpio.h> | ||
20 | #include <asm/intel-mid.h> | ||
21 | |||
22 | #include "platform_ipc.h" | ||
23 | |||
24 | static void __init *pmic_gpio_platform_data(void *info) | ||
25 | { | ||
26 | static struct intel_pmic_gpio_platform_data pmic_gpio_pdata; | ||
27 | int gpio_base = get_gpio_by_name("pmic_gpio_base"); | ||
28 | |||
29 | if (gpio_base == -1) | ||
30 | gpio_base = 64; | ||
31 | pmic_gpio_pdata.gpio_base = gpio_base; | ||
32 | pmic_gpio_pdata.irq_base = gpio_base + INTEL_MID_IRQ_OFFSET; | ||
33 | pmic_gpio_pdata.gpiointr = 0xffffeff8; | ||
34 | |||
35 | return &pmic_gpio_pdata; | ||
36 | } | ||
37 | |||
38 | static const struct devs_id pmic_gpio_spi_dev_id __initconst = { | ||
39 | .name = "pmic_gpio", | ||
40 | .type = SFI_DEV_TYPE_SPI, | ||
41 | .delay = 1, | ||
42 | .get_platform_data = &pmic_gpio_platform_data, | ||
43 | }; | ||
44 | |||
45 | static const struct devs_id pmic_gpio_ipc_dev_id __initconst = { | ||
46 | .name = "pmic_gpio", | ||
47 | .type = SFI_DEV_TYPE_IPC, | ||
48 | .delay = 1, | ||
49 | .get_platform_data = &pmic_gpio_platform_data, | ||
50 | .device_handler = &ipc_device_handler | ||
51 | }; | ||
52 | |||
53 | sfi_device(pmic_gpio_spi_dev_id); | ||
54 | sfi_device(pmic_gpio_ipc_dev_id); | ||
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_tc35876x.c b/arch/x86/platform/intel-mid/device_libs/platform_tc35876x.c new file mode 100644 index 000000000000..740fc757050c --- /dev/null +++ b/arch/x86/platform/intel-mid/device_libs/platform_tc35876x.c | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * platform_tc35876x.c: tc35876x platform data initilization file | ||
3 | * | ||
4 | * (C) Copyright 2013 Intel Corporation | ||
5 | * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; version 2 | ||
10 | * of the License. | ||
11 | */ | ||
12 | |||
13 | #include <linux/gpio.h> | ||
14 | #include <linux/i2c/tc35876x.h> | ||
15 | #include <asm/intel-mid.h> | ||
16 | |||
17 | /*tc35876x DSI_LVDS bridge chip and panel platform data*/ | ||
18 | static void *tc35876x_platform_data(void *data) | ||
19 | { | ||
20 | static struct tc35876x_platform_data pdata; | ||
21 | |||
22 | /* gpio pins set to -1 will not be used by the driver */ | ||
23 | pdata.gpio_bridge_reset = get_gpio_by_name("LCMB_RXEN"); | ||
24 | pdata.gpio_panel_bl_en = get_gpio_by_name("6S6P_BL_EN"); | ||
25 | pdata.gpio_panel_vadd = get_gpio_by_name("EN_VREG_LCD_V3P3"); | ||
26 | |||
27 | return &pdata; | ||
28 | } | ||
29 | |||
30 | static const struct devs_id tc35876x_dev_id __initconst = { | ||
31 | .name = "i2c_disp_brig", | ||
32 | .type = SFI_DEV_TYPE_I2C, | ||
33 | .get_platform_data = &tc35876x_platform_data, | ||
34 | }; | ||
35 | |||
36 | sfi_device(tc35876x_dev_id); | ||
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_tca6416.c b/arch/x86/platform/intel-mid/device_libs/platform_tca6416.c new file mode 100644 index 000000000000..22881c9a6737 --- /dev/null +++ b/arch/x86/platform/intel-mid/device_libs/platform_tca6416.c | |||
@@ -0,0 +1,57 @@ | |||
1 | /* | ||
2 | * platform_tca6416.c: tca6416 platform data initilization file | ||
3 | * | ||
4 | * (C) Copyright 2013 Intel Corporation | ||
5 | * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; version 2 | ||
10 | * of the License. | ||
11 | */ | ||
12 | |||
13 | #include <linux/platform_data/pca953x.h> | ||
14 | #include <linux/i2c.h> | ||
15 | #include <linux/gpio.h> | ||
16 | #include <asm/intel-mid.h> | ||
17 | |||
18 | #define TCA6416_NAME "tca6416" | ||
19 | #define TCA6416_BASE "tca6416_base" | ||
20 | #define TCA6416_INTR "tca6416_int" | ||
21 | |||
22 | static void *tca6416_platform_data(void *info) | ||
23 | { | ||
24 | static struct pca953x_platform_data tca6416; | ||
25 | struct i2c_board_info *i2c_info = info; | ||
26 | int gpio_base, intr; | ||
27 | char base_pin_name[SFI_NAME_LEN + 1]; | ||
28 | char intr_pin_name[SFI_NAME_LEN + 1]; | ||
29 | |||
30 | strcpy(i2c_info->type, TCA6416_NAME); | ||
31 | strcpy(base_pin_name, TCA6416_BASE); | ||
32 | strcpy(intr_pin_name, TCA6416_INTR); | ||
33 | |||
34 | gpio_base = get_gpio_by_name(base_pin_name); | ||
35 | intr = get_gpio_by_name(intr_pin_name); | ||
36 | |||
37 | if (gpio_base == -1) | ||
38 | return NULL; | ||
39 | tca6416.gpio_base = gpio_base; | ||
40 | if (intr != -1) { | ||
41 | i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET; | ||
42 | tca6416.irq_base = gpio_base + INTEL_MID_IRQ_OFFSET; | ||
43 | } else { | ||
44 | i2c_info->irq = -1; | ||
45 | tca6416.irq_base = -1; | ||
46 | } | ||
47 | return &tca6416; | ||
48 | } | ||
49 | |||
50 | static const struct devs_id tca6416_dev_id __initconst = { | ||
51 | .name = "tca6416", | ||
52 | .type = SFI_DEV_TYPE_I2C, | ||
53 | .delay = 1, | ||
54 | .get_platform_data = &tca6416_platform_data, | ||
55 | }; | ||
56 | |||
57 | sfi_device(tca6416_dev_id); | ||
diff --git a/arch/x86/platform/mrst/early_printk_mrst.c b/arch/x86/platform/intel-mid/early_printk_intel_mid.c index 028454f0c3a5..4f702f554f6e 100644 --- a/arch/x86/platform/mrst/early_printk_mrst.c +++ b/arch/x86/platform/intel-mid/early_printk_intel_mid.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * early_printk_mrst.c - early consoles for Intel MID platforms | 2 | * early_printk_intel_mid.c - early consoles for Intel MID platforms |
3 | * | 3 | * |
4 | * Copyright (c) 2008-2010, Intel Corporation | 4 | * Copyright (c) 2008-2010, Intel Corporation |
5 | * | 5 | * |
@@ -27,7 +27,7 @@ | |||
27 | 27 | ||
28 | #include <asm/fixmap.h> | 28 | #include <asm/fixmap.h> |
29 | #include <asm/pgtable.h> | 29 | #include <asm/pgtable.h> |
30 | #include <asm/mrst.h> | 30 | #include <asm/intel-mid.h> |
31 | 31 | ||
32 | #define MRST_SPI_TIMEOUT 0x200000 | 32 | #define MRST_SPI_TIMEOUT 0x200000 |
33 | #define MRST_REGBASE_SPI0 0xff128000 | 33 | #define MRST_REGBASE_SPI0 0xff128000 |
@@ -152,7 +152,7 @@ void mrst_early_console_init(void) | |||
152 | spi0_cdiv = ((*pclk_spi0) & 0xe00) >> 9; | 152 | spi0_cdiv = ((*pclk_spi0) & 0xe00) >> 9; |
153 | freq = 100000000 / (spi0_cdiv + 1); | 153 | freq = 100000000 / (spi0_cdiv + 1); |
154 | 154 | ||
155 | if (mrst_identify_cpu() == MRST_CPU_CHIP_PENWELL) | 155 | if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_PENWELL) |
156 | mrst_spi_paddr = MRST_REGBASE_SPI1; | 156 | mrst_spi_paddr = MRST_REGBASE_SPI1; |
157 | 157 | ||
158 | pspi = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE, | 158 | pspi = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE, |
@@ -213,13 +213,14 @@ static void early_mrst_spi_putc(char c) | |||
213 | } | 213 | } |
214 | 214 | ||
215 | if (!timeout) | 215 | if (!timeout) |
216 | pr_warning("MRST earlycon: timed out\n"); | 216 | pr_warn("MRST earlycon: timed out\n"); |
217 | else | 217 | else |
218 | max3110_write_data(c); | 218 | max3110_write_data(c); |
219 | } | 219 | } |
220 | 220 | ||
221 | /* Early SPI only uses polling mode */ | 221 | /* Early SPI only uses polling mode */ |
222 | static void early_mrst_spi_write(struct console *con, const char *str, unsigned n) | 222 | static void early_mrst_spi_write(struct console *con, const char *str, |
223 | unsigned n) | ||
223 | { | 224 | { |
224 | int i; | 225 | int i; |
225 | 226 | ||
diff --git a/arch/x86/platform/intel-mid/intel-mid.c b/arch/x86/platform/intel-mid/intel-mid.c new file mode 100644 index 000000000000..f90e290f689f --- /dev/null +++ b/arch/x86/platform/intel-mid/intel-mid.c | |||
@@ -0,0 +1,213 @@ | |||
1 | /* | ||
2 | * intel-mid.c: Intel MID platform setup code | ||
3 | * | ||
4 | * (C) Copyright 2008, 2012 Intel Corporation | ||
5 | * Author: Jacob Pan (jacob.jun.pan@intel.com) | ||
6 | * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; version 2 | ||
11 | * of the License. | ||
12 | */ | ||
13 | |||
14 | #define pr_fmt(fmt) "intel_mid: " fmt | ||
15 | |||
16 | #include <linux/init.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/scatterlist.h> | ||
20 | #include <linux/sfi.h> | ||
21 | #include <linux/irq.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/notifier.h> | ||
24 | |||
25 | #include <asm/setup.h> | ||
26 | #include <asm/mpspec_def.h> | ||
27 | #include <asm/hw_irq.h> | ||
28 | #include <asm/apic.h> | ||
29 | #include <asm/io_apic.h> | ||
30 | #include <asm/intel-mid.h> | ||
31 | #include <asm/intel_mid_vrtc.h> | ||
32 | #include <asm/io.h> | ||
33 | #include <asm/i8259.h> | ||
34 | #include <asm/intel_scu_ipc.h> | ||
35 | #include <asm/apb_timer.h> | ||
36 | #include <asm/reboot.h> | ||
37 | |||
38 | /* | ||
39 | * the clockevent devices on Moorestown/Medfield can be APBT or LAPIC clock, | ||
40 | * cmdline option x86_intel_mid_timer can be used to override the configuration | ||
41 | * to prefer one or the other. | ||
42 | * at runtime, there are basically three timer configurations: | ||
43 | * 1. per cpu apbt clock only | ||
44 | * 2. per cpu always-on lapic clocks only, this is Penwell/Medfield only | ||
45 | * 3. per cpu lapic clock (C3STOP) and one apbt clock, with broadcast. | ||
46 | * | ||
47 | * by default (without cmdline option), platform code first detects cpu type | ||
48 | * to see if we are on lincroft or penwell, then set up both lapic or apbt | ||
49 | * clocks accordingly. | ||
50 | * i.e. by default, medfield uses configuration #2, moorestown uses #1. | ||
51 | * config #3 is supported but not recommended on medfield. | ||
52 | * | ||
53 | * rating and feature summary: | ||
54 | * lapic (with C3STOP) --------- 100 | ||
55 | * apbt (always-on) ------------ 110 | ||
56 | * lapic (always-on,ARAT) ------ 150 | ||
57 | */ | ||
58 | |||
59 | enum intel_mid_timer_options intel_mid_timer_options; | ||
60 | |||
61 | enum intel_mid_cpu_type __intel_mid_cpu_chip; | ||
62 | EXPORT_SYMBOL_GPL(__intel_mid_cpu_chip); | ||
63 | |||
64 | static void intel_mid_power_off(void) | ||
65 | { | ||
66 | } | ||
67 | |||
68 | static void intel_mid_reboot(void) | ||
69 | { | ||
70 | intel_scu_ipc_simple_command(IPCMSG_COLD_BOOT, 0); | ||
71 | } | ||
72 | |||
73 | static unsigned long __init intel_mid_calibrate_tsc(void) | ||
74 | { | ||
75 | unsigned long fast_calibrate; | ||
76 | u32 lo, hi, ratio, fsb; | ||
77 | |||
78 | rdmsr(MSR_IA32_PERF_STATUS, lo, hi); | ||
79 | pr_debug("IA32 perf status is 0x%x, 0x%0x\n", lo, hi); | ||
80 | ratio = (hi >> 8) & 0x1f; | ||
81 | pr_debug("ratio is %d\n", ratio); | ||
82 | if (!ratio) { | ||
83 | pr_err("read a zero ratio, should be incorrect!\n"); | ||
84 | pr_err("force tsc ratio to 16 ...\n"); | ||
85 | ratio = 16; | ||
86 | } | ||
87 | rdmsr(MSR_FSB_FREQ, lo, hi); | ||
88 | if ((lo & 0x7) == 0x7) | ||
89 | fsb = PENWELL_FSB_FREQ_83SKU; | ||
90 | else | ||
91 | fsb = PENWELL_FSB_FREQ_100SKU; | ||
92 | fast_calibrate = ratio * fsb; | ||
93 | pr_debug("read penwell tsc %lu khz\n", fast_calibrate); | ||
94 | lapic_timer_frequency = fsb * 1000 / HZ; | ||
95 | /* mark tsc clocksource as reliable */ | ||
96 | set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE); | ||
97 | |||
98 | if (fast_calibrate) | ||
99 | return fast_calibrate; | ||
100 | |||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | static void __init intel_mid_time_init(void) | ||
105 | { | ||
106 | sfi_table_parse(SFI_SIG_MTMR, NULL, NULL, sfi_parse_mtmr); | ||
107 | switch (intel_mid_timer_options) { | ||
108 | case INTEL_MID_TIMER_APBT_ONLY: | ||
109 | break; | ||
110 | case INTEL_MID_TIMER_LAPIC_APBT: | ||
111 | x86_init.timers.setup_percpu_clockev = setup_boot_APIC_clock; | ||
112 | x86_cpuinit.setup_percpu_clockev = setup_secondary_APIC_clock; | ||
113 | break; | ||
114 | default: | ||
115 | if (!boot_cpu_has(X86_FEATURE_ARAT)) | ||
116 | break; | ||
117 | x86_init.timers.setup_percpu_clockev = setup_boot_APIC_clock; | ||
118 | x86_cpuinit.setup_percpu_clockev = setup_secondary_APIC_clock; | ||
119 | return; | ||
120 | } | ||
121 | /* we need at least one APB timer */ | ||
122 | pre_init_apic_IRQ0(); | ||
123 | apbt_time_init(); | ||
124 | } | ||
125 | |||
126 | static void intel_mid_arch_setup(void) | ||
127 | { | ||
128 | if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 0x27) | ||
129 | __intel_mid_cpu_chip = INTEL_MID_CPU_CHIP_PENWELL; | ||
130 | else { | ||
131 | pr_err("Unknown Intel MID CPU (%d:%d), default to Penwell\n", | ||
132 | boot_cpu_data.x86, boot_cpu_data.x86_model); | ||
133 | __intel_mid_cpu_chip = INTEL_MID_CPU_CHIP_PENWELL; | ||
134 | } | ||
135 | } | ||
136 | |||
137 | /* MID systems don't have i8042 controller */ | ||
138 | static int intel_mid_i8042_detect(void) | ||
139 | { | ||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | /* | ||
144 | * Moorestown does not have external NMI source nor port 0x61 to report | ||
145 | * NMI status. The possible NMI sources are from pmu as a result of NMI | ||
146 | * watchdog or lock debug. Reading io port 0x61 results in 0xff which | ||
147 | * misled NMI handler. | ||
148 | */ | ||
149 | static unsigned char intel_mid_get_nmi_reason(void) | ||
150 | { | ||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | /* | ||
155 | * Moorestown specific x86_init function overrides and early setup | ||
156 | * calls. | ||
157 | */ | ||
158 | void __init x86_intel_mid_early_setup(void) | ||
159 | { | ||
160 | x86_init.resources.probe_roms = x86_init_noop; | ||
161 | x86_init.resources.reserve_resources = x86_init_noop; | ||
162 | |||
163 | x86_init.timers.timer_init = intel_mid_time_init; | ||
164 | x86_init.timers.setup_percpu_clockev = x86_init_noop; | ||
165 | |||
166 | x86_init.irqs.pre_vector_init = x86_init_noop; | ||
167 | |||
168 | x86_init.oem.arch_setup = intel_mid_arch_setup; | ||
169 | |||
170 | x86_cpuinit.setup_percpu_clockev = apbt_setup_secondary_clock; | ||
171 | |||
172 | x86_platform.calibrate_tsc = intel_mid_calibrate_tsc; | ||
173 | x86_platform.i8042_detect = intel_mid_i8042_detect; | ||
174 | x86_init.timers.wallclock_init = intel_mid_rtc_init; | ||
175 | x86_platform.get_nmi_reason = intel_mid_get_nmi_reason; | ||
176 | |||
177 | x86_init.pci.init = intel_mid_pci_init; | ||
178 | x86_init.pci.fixup_irqs = x86_init_noop; | ||
179 | |||
180 | legacy_pic = &null_legacy_pic; | ||
181 | |||
182 | pm_power_off = intel_mid_power_off; | ||
183 | machine_ops.emergency_restart = intel_mid_reboot; | ||
184 | |||
185 | /* Avoid searching for BIOS MP tables */ | ||
186 | x86_init.mpparse.find_smp_config = x86_init_noop; | ||
187 | x86_init.mpparse.get_smp_config = x86_init_uint_noop; | ||
188 | set_bit(MP_BUS_ISA, mp_bus_not_pci); | ||
189 | } | ||
190 | |||
191 | /* | ||
192 | * if user does not want to use per CPU apb timer, just give it a lower rating | ||
193 | * than local apic timer and skip the late per cpu timer init. | ||
194 | */ | ||
195 | static inline int __init setup_x86_intel_mid_timer(char *arg) | ||
196 | { | ||
197 | if (!arg) | ||
198 | return -EINVAL; | ||
199 | |||
200 | if (strcmp("apbt_only", arg) == 0) | ||
201 | intel_mid_timer_options = INTEL_MID_TIMER_APBT_ONLY; | ||
202 | else if (strcmp("lapic_and_apbt", arg) == 0) | ||
203 | intel_mid_timer_options = INTEL_MID_TIMER_LAPIC_APBT; | ||
204 | else { | ||
205 | pr_warn("X86 INTEL_MID timer option %s not recognised" | ||
206 | " use x86_intel_mid_timer=apbt_only or lapic_and_apbt\n", | ||
207 | arg); | ||
208 | return -EINVAL; | ||
209 | } | ||
210 | return 0; | ||
211 | } | ||
212 | __setup("x86_intel_mid_timer=", setup_x86_intel_mid_timer); | ||
213 | |||
diff --git a/arch/x86/platform/mrst/vrtc.c b/arch/x86/platform/intel-mid/intel_mid_vrtc.c index 5e355b134ba4..4762cff7facd 100644 --- a/arch/x86/platform/mrst/vrtc.c +++ b/arch/x86/platform/intel-mid/intel_mid_vrtc.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * vrtc.c: Driver for virtual RTC device on Intel MID platform | 2 | * intel_mid_vrtc.c: Driver for virtual RTC device on Intel MID platform |
3 | * | 3 | * |
4 | * (C) Copyright 2009 Intel Corporation | 4 | * (C) Copyright 2009 Intel Corporation |
5 | * | 5 | * |
@@ -23,8 +23,8 @@ | |||
23 | #include <linux/sfi.h> | 23 | #include <linux/sfi.h> |
24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
25 | 25 | ||
26 | #include <asm/mrst.h> | 26 | #include <asm/intel-mid.h> |
27 | #include <asm/mrst-vrtc.h> | 27 | #include <asm/intel_mid_vrtc.h> |
28 | #include <asm/time.h> | 28 | #include <asm/time.h> |
29 | #include <asm/fixmap.h> | 29 | #include <asm/fixmap.h> |
30 | 30 | ||
@@ -79,7 +79,7 @@ void vrtc_get_time(struct timespec *now) | |||
79 | /* vRTC YEAR reg contains the offset to 1972 */ | 79 | /* vRTC YEAR reg contains the offset to 1972 */ |
80 | year += 1972; | 80 | year += 1972; |
81 | 81 | ||
82 | printk(KERN_INFO "vRTC: sec: %d min: %d hour: %d day: %d " | 82 | pr_info("vRTC: sec: %d min: %d hour: %d day: %d " |
83 | "mon: %d year: %d\n", sec, min, hour, mday, mon, year); | 83 | "mon: %d year: %d\n", sec, min, hour, mday, mon, year); |
84 | 84 | ||
85 | now->tv_sec = mktime(year, mon, mday, hour, min, sec); | 85 | now->tv_sec = mktime(year, mon, mday, hour, min, sec); |
@@ -109,15 +109,14 @@ int vrtc_set_mmss(const struct timespec *now) | |||
109 | vrtc_cmos_write(tm.tm_sec, RTC_SECONDS); | 109 | vrtc_cmos_write(tm.tm_sec, RTC_SECONDS); |
110 | spin_unlock_irqrestore(&rtc_lock, flags); | 110 | spin_unlock_irqrestore(&rtc_lock, flags); |
111 | } else { | 111 | } else { |
112 | printk(KERN_ERR | 112 | pr_err("%s: Invalid vRTC value: write of %lx to vRTC failed\n", |
113 | "%s: Invalid vRTC value: write of %lx to vRTC failed\n", | ||
114 | __FUNCTION__, now->tv_sec); | 113 | __FUNCTION__, now->tv_sec); |
115 | retval = -EINVAL; | 114 | retval = -EINVAL; |
116 | } | 115 | } |
117 | return retval; | 116 | return retval; |
118 | } | 117 | } |
119 | 118 | ||
120 | void __init mrst_rtc_init(void) | 119 | void __init intel_mid_rtc_init(void) |
121 | { | 120 | { |
122 | unsigned long vrtc_paddr; | 121 | unsigned long vrtc_paddr; |
123 | 122 | ||
@@ -155,10 +154,10 @@ static struct platform_device vrtc_device = { | |||
155 | }; | 154 | }; |
156 | 155 | ||
157 | /* Register the RTC device if appropriate */ | 156 | /* Register the RTC device if appropriate */ |
158 | static int __init mrst_device_create(void) | 157 | static int __init intel_mid_device_create(void) |
159 | { | 158 | { |
160 | /* No Moorestown, no device */ | 159 | /* No Moorestown, no device */ |
161 | if (!mrst_identify_cpu()) | 160 | if (!intel_mid_identify_cpu()) |
162 | return -ENODEV; | 161 | return -ENODEV; |
163 | /* No timer, no device */ | 162 | /* No timer, no device */ |
164 | if (!sfi_mrtc_num) | 163 | if (!sfi_mrtc_num) |
@@ -175,4 +174,4 @@ static int __init mrst_device_create(void) | |||
175 | return platform_device_register(&vrtc_device); | 174 | return platform_device_register(&vrtc_device); |
176 | } | 175 | } |
177 | 176 | ||
178 | module_init(mrst_device_create); | 177 | module_init(intel_mid_device_create); |
diff --git a/arch/x86/platform/intel-mid/sfi.c b/arch/x86/platform/intel-mid/sfi.c new file mode 100644 index 000000000000..c84c1ca396bf --- /dev/null +++ b/arch/x86/platform/intel-mid/sfi.c | |||
@@ -0,0 +1,488 @@ | |||
1 | /* | ||
2 | * intel_mid_sfi.c: Intel MID SFI initialization code | ||
3 | * | ||
4 | * (C) Copyright 2013 Intel Corporation | ||
5 | * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; version 2 | ||
10 | * of the License. | ||
11 | */ | ||
12 | |||
13 | #include <linux/init.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/scatterlist.h> | ||
17 | #include <linux/sfi.h> | ||
18 | #include <linux/intel_pmic_gpio.h> | ||
19 | #include <linux/spi/spi.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <linux/skbuff.h> | ||
22 | #include <linux/gpio.h> | ||
23 | #include <linux/gpio_keys.h> | ||
24 | #include <linux/input.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/irq.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/notifier.h> | ||
29 | #include <linux/mmc/core.h> | ||
30 | #include <linux/mmc/card.h> | ||
31 | #include <linux/blkdev.h> | ||
32 | |||
33 | #include <asm/setup.h> | ||
34 | #include <asm/mpspec_def.h> | ||
35 | #include <asm/hw_irq.h> | ||
36 | #include <asm/apic.h> | ||
37 | #include <asm/io_apic.h> | ||
38 | #include <asm/intel-mid.h> | ||
39 | #include <asm/intel_mid_vrtc.h> | ||
40 | #include <asm/io.h> | ||
41 | #include <asm/i8259.h> | ||
42 | #include <asm/intel_scu_ipc.h> | ||
43 | #include <asm/apb_timer.h> | ||
44 | #include <asm/reboot.h> | ||
45 | |||
46 | #define SFI_SIG_OEM0 "OEM0" | ||
47 | #define MAX_IPCDEVS 24 | ||
48 | #define MAX_SCU_SPI 24 | ||
49 | #define MAX_SCU_I2C 24 | ||
50 | |||
51 | static struct platform_device *ipc_devs[MAX_IPCDEVS]; | ||
52 | static struct spi_board_info *spi_devs[MAX_SCU_SPI]; | ||
53 | static struct i2c_board_info *i2c_devs[MAX_SCU_I2C]; | ||
54 | static struct sfi_gpio_table_entry *gpio_table; | ||
55 | static struct sfi_timer_table_entry sfi_mtimer_array[SFI_MTMR_MAX_NUM]; | ||
56 | static int ipc_next_dev; | ||
57 | static int spi_next_dev; | ||
58 | static int i2c_next_dev; | ||
59 | static int i2c_bus[MAX_SCU_I2C]; | ||
60 | static int gpio_num_entry; | ||
61 | static u32 sfi_mtimer_usage[SFI_MTMR_MAX_NUM]; | ||
62 | int sfi_mrtc_num; | ||
63 | int sfi_mtimer_num; | ||
64 | |||
65 | struct sfi_rtc_table_entry sfi_mrtc_array[SFI_MRTC_MAX]; | ||
66 | EXPORT_SYMBOL_GPL(sfi_mrtc_array); | ||
67 | |||
68 | struct blocking_notifier_head intel_scu_notifier = | ||
69 | BLOCKING_NOTIFIER_INIT(intel_scu_notifier); | ||
70 | EXPORT_SYMBOL_GPL(intel_scu_notifier); | ||
71 | |||
72 | #define intel_mid_sfi_get_pdata(dev, priv) \ | ||
73 | ((dev)->get_platform_data ? (dev)->get_platform_data(priv) : NULL) | ||
74 | |||
75 | /* parse all the mtimer info to a static mtimer array */ | ||
76 | int __init sfi_parse_mtmr(struct sfi_table_header *table) | ||
77 | { | ||
78 | struct sfi_table_simple *sb; | ||
79 | struct sfi_timer_table_entry *pentry; | ||
80 | struct mpc_intsrc mp_irq; | ||
81 | int totallen; | ||
82 | |||
83 | sb = (struct sfi_table_simple *)table; | ||
84 | if (!sfi_mtimer_num) { | ||
85 | sfi_mtimer_num = SFI_GET_NUM_ENTRIES(sb, | ||
86 | struct sfi_timer_table_entry); | ||
87 | pentry = (struct sfi_timer_table_entry *) sb->pentry; | ||
88 | totallen = sfi_mtimer_num * sizeof(*pentry); | ||
89 | memcpy(sfi_mtimer_array, pentry, totallen); | ||
90 | } | ||
91 | |||
92 | pr_debug("SFI MTIMER info (num = %d):\n", sfi_mtimer_num); | ||
93 | pentry = sfi_mtimer_array; | ||
94 | for (totallen = 0; totallen < sfi_mtimer_num; totallen++, pentry++) { | ||
95 | pr_debug("timer[%d]: paddr = 0x%08x, freq = %dHz, irq = %d\n", | ||
96 | totallen, (u32)pentry->phys_addr, | ||
97 | pentry->freq_hz, pentry->irq); | ||
98 | if (!pentry->irq) | ||
99 | continue; | ||
100 | mp_irq.type = MP_INTSRC; | ||
101 | mp_irq.irqtype = mp_INT; | ||
102 | /* triggering mode edge bit 2-3, active high polarity bit 0-1 */ | ||
103 | mp_irq.irqflag = 5; | ||
104 | mp_irq.srcbus = MP_BUS_ISA; | ||
105 | mp_irq.srcbusirq = pentry->irq; /* IRQ */ | ||
106 | mp_irq.dstapic = MP_APIC_ALL; | ||
107 | mp_irq.dstirq = pentry->irq; | ||
108 | mp_save_irq(&mp_irq); | ||
109 | } | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | struct sfi_timer_table_entry *sfi_get_mtmr(int hint) | ||
115 | { | ||
116 | int i; | ||
117 | if (hint < sfi_mtimer_num) { | ||
118 | if (!sfi_mtimer_usage[hint]) { | ||
119 | pr_debug("hint taken for timer %d irq %d\n", | ||
120 | hint, sfi_mtimer_array[hint].irq); | ||
121 | sfi_mtimer_usage[hint] = 1; | ||
122 | return &sfi_mtimer_array[hint]; | ||
123 | } | ||
124 | } | ||
125 | /* take the first timer available */ | ||
126 | for (i = 0; i < sfi_mtimer_num;) { | ||
127 | if (!sfi_mtimer_usage[i]) { | ||
128 | sfi_mtimer_usage[i] = 1; | ||
129 | return &sfi_mtimer_array[i]; | ||
130 | } | ||
131 | i++; | ||
132 | } | ||
133 | return NULL; | ||
134 | } | ||
135 | |||
136 | void sfi_free_mtmr(struct sfi_timer_table_entry *mtmr) | ||
137 | { | ||
138 | int i; | ||
139 | for (i = 0; i < sfi_mtimer_num;) { | ||
140 | if (mtmr->irq == sfi_mtimer_array[i].irq) { | ||
141 | sfi_mtimer_usage[i] = 0; | ||
142 | return; | ||
143 | } | ||
144 | i++; | ||
145 | } | ||
146 | } | ||
147 | |||
148 | /* parse all the mrtc info to a global mrtc array */ | ||
149 | int __init sfi_parse_mrtc(struct sfi_table_header *table) | ||
150 | { | ||
151 | struct sfi_table_simple *sb; | ||
152 | struct sfi_rtc_table_entry *pentry; | ||
153 | struct mpc_intsrc mp_irq; | ||
154 | |||
155 | int totallen; | ||
156 | |||
157 | sb = (struct sfi_table_simple *)table; | ||
158 | if (!sfi_mrtc_num) { | ||
159 | sfi_mrtc_num = SFI_GET_NUM_ENTRIES(sb, | ||
160 | struct sfi_rtc_table_entry); | ||
161 | pentry = (struct sfi_rtc_table_entry *)sb->pentry; | ||
162 | totallen = sfi_mrtc_num * sizeof(*pentry); | ||
163 | memcpy(sfi_mrtc_array, pentry, totallen); | ||
164 | } | ||
165 | |||
166 | pr_debug("SFI RTC info (num = %d):\n", sfi_mrtc_num); | ||
167 | pentry = sfi_mrtc_array; | ||
168 | for (totallen = 0; totallen < sfi_mrtc_num; totallen++, pentry++) { | ||
169 | pr_debug("RTC[%d]: paddr = 0x%08x, irq = %d\n", | ||
170 | totallen, (u32)pentry->phys_addr, pentry->irq); | ||
171 | mp_irq.type = MP_INTSRC; | ||
172 | mp_irq.irqtype = mp_INT; | ||
173 | mp_irq.irqflag = 0xf; /* level trigger and active low */ | ||
174 | mp_irq.srcbus = MP_BUS_ISA; | ||
175 | mp_irq.srcbusirq = pentry->irq; /* IRQ */ | ||
176 | mp_irq.dstapic = MP_APIC_ALL; | ||
177 | mp_irq.dstirq = pentry->irq; | ||
178 | mp_save_irq(&mp_irq); | ||
179 | } | ||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | |||
184 | /* | ||
185 | * Parsing GPIO table first, since the DEVS table will need this table | ||
186 | * to map the pin name to the actual pin. | ||
187 | */ | ||
188 | static int __init sfi_parse_gpio(struct sfi_table_header *table) | ||
189 | { | ||
190 | struct sfi_table_simple *sb; | ||
191 | struct sfi_gpio_table_entry *pentry; | ||
192 | int num, i; | ||
193 | |||
194 | if (gpio_table) | ||
195 | return 0; | ||
196 | sb = (struct sfi_table_simple *)table; | ||
197 | num = SFI_GET_NUM_ENTRIES(sb, struct sfi_gpio_table_entry); | ||
198 | pentry = (struct sfi_gpio_table_entry *)sb->pentry; | ||
199 | |||
200 | gpio_table = kmalloc(num * sizeof(*pentry), GFP_KERNEL); | ||
201 | if (!gpio_table) | ||
202 | return -1; | ||
203 | memcpy(gpio_table, pentry, num * sizeof(*pentry)); | ||
204 | gpio_num_entry = num; | ||
205 | |||
206 | pr_debug("GPIO pin info:\n"); | ||
207 | for (i = 0; i < num; i++, pentry++) | ||
208 | pr_debug("info[%2d]: controller = %16.16s, pin_name = %16.16s," | ||
209 | " pin = %d\n", i, | ||
210 | pentry->controller_name, | ||
211 | pentry->pin_name, | ||
212 | pentry->pin_no); | ||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | int get_gpio_by_name(const char *name) | ||
217 | { | ||
218 | struct sfi_gpio_table_entry *pentry = gpio_table; | ||
219 | int i; | ||
220 | |||
221 | if (!pentry) | ||
222 | return -1; | ||
223 | for (i = 0; i < gpio_num_entry; i++, pentry++) { | ||
224 | if (!strncmp(name, pentry->pin_name, SFI_NAME_LEN)) | ||
225 | return pentry->pin_no; | ||
226 | } | ||
227 | return -1; | ||
228 | } | ||
229 | |||
230 | void __init intel_scu_device_register(struct platform_device *pdev) | ||
231 | { | ||
232 | if (ipc_next_dev == MAX_IPCDEVS) | ||
233 | pr_err("too many SCU IPC devices"); | ||
234 | else | ||
235 | ipc_devs[ipc_next_dev++] = pdev; | ||
236 | } | ||
237 | |||
238 | static void __init intel_scu_spi_device_register(struct spi_board_info *sdev) | ||
239 | { | ||
240 | struct spi_board_info *new_dev; | ||
241 | |||
242 | if (spi_next_dev == MAX_SCU_SPI) { | ||
243 | pr_err("too many SCU SPI devices"); | ||
244 | return; | ||
245 | } | ||
246 | |||
247 | new_dev = kzalloc(sizeof(*sdev), GFP_KERNEL); | ||
248 | if (!new_dev) { | ||
249 | pr_err("failed to alloc mem for delayed spi dev %s\n", | ||
250 | sdev->modalias); | ||
251 | return; | ||
252 | } | ||
253 | memcpy(new_dev, sdev, sizeof(*sdev)); | ||
254 | |||
255 | spi_devs[spi_next_dev++] = new_dev; | ||
256 | } | ||
257 | |||
258 | static void __init intel_scu_i2c_device_register(int bus, | ||
259 | struct i2c_board_info *idev) | ||
260 | { | ||
261 | struct i2c_board_info *new_dev; | ||
262 | |||
263 | if (i2c_next_dev == MAX_SCU_I2C) { | ||
264 | pr_err("too many SCU I2C devices"); | ||
265 | return; | ||
266 | } | ||
267 | |||
268 | new_dev = kzalloc(sizeof(*idev), GFP_KERNEL); | ||
269 | if (!new_dev) { | ||
270 | pr_err("failed to alloc mem for delayed i2c dev %s\n", | ||
271 | idev->type); | ||
272 | return; | ||
273 | } | ||
274 | memcpy(new_dev, idev, sizeof(*idev)); | ||
275 | |||
276 | i2c_bus[i2c_next_dev] = bus; | ||
277 | i2c_devs[i2c_next_dev++] = new_dev; | ||
278 | } | ||
279 | |||
280 | /* Called by IPC driver */ | ||
281 | void intel_scu_devices_create(void) | ||
282 | { | ||
283 | int i; | ||
284 | |||
285 | for (i = 0; i < ipc_next_dev; i++) | ||
286 | platform_device_add(ipc_devs[i]); | ||
287 | |||
288 | for (i = 0; i < spi_next_dev; i++) | ||
289 | spi_register_board_info(spi_devs[i], 1); | ||
290 | |||
291 | for (i = 0; i < i2c_next_dev; i++) { | ||
292 | struct i2c_adapter *adapter; | ||
293 | struct i2c_client *client; | ||
294 | |||
295 | adapter = i2c_get_adapter(i2c_bus[i]); | ||
296 | if (adapter) { | ||
297 | client = i2c_new_device(adapter, i2c_devs[i]); | ||
298 | if (!client) | ||
299 | pr_err("can't create i2c device %s\n", | ||
300 | i2c_devs[i]->type); | ||
301 | } else | ||
302 | i2c_register_board_info(i2c_bus[i], i2c_devs[i], 1); | ||
303 | } | ||
304 | intel_scu_notifier_post(SCU_AVAILABLE, NULL); | ||
305 | } | ||
306 | EXPORT_SYMBOL_GPL(intel_scu_devices_create); | ||
307 | |||
308 | /* Called by IPC driver */ | ||
309 | void intel_scu_devices_destroy(void) | ||
310 | { | ||
311 | int i; | ||
312 | |||
313 | intel_scu_notifier_post(SCU_DOWN, NULL); | ||
314 | |||
315 | for (i = 0; i < ipc_next_dev; i++) | ||
316 | platform_device_del(ipc_devs[i]); | ||
317 | } | ||
318 | EXPORT_SYMBOL_GPL(intel_scu_devices_destroy); | ||
319 | |||
320 | static void __init install_irq_resource(struct platform_device *pdev, int irq) | ||
321 | { | ||
322 | /* Single threaded */ | ||
323 | static struct resource res __initdata = { | ||
324 | .name = "IRQ", | ||
325 | .flags = IORESOURCE_IRQ, | ||
326 | }; | ||
327 | res.start = irq; | ||
328 | platform_device_add_resources(pdev, &res, 1); | ||
329 | } | ||
330 | |||
331 | static void __init sfi_handle_ipc_dev(struct sfi_device_table_entry *pentry, | ||
332 | struct devs_id *dev) | ||
333 | { | ||
334 | struct platform_device *pdev; | ||
335 | void *pdata = NULL; | ||
336 | |||
337 | pr_debug("IPC bus, name = %16.16s, irq = 0x%2x\n", | ||
338 | pentry->name, pentry->irq); | ||
339 | pdata = intel_mid_sfi_get_pdata(dev, pentry); | ||
340 | |||
341 | pdev = platform_device_alloc(pentry->name, 0); | ||
342 | if (pdev == NULL) { | ||
343 | pr_err("out of memory for SFI platform device '%s'.\n", | ||
344 | pentry->name); | ||
345 | return; | ||
346 | } | ||
347 | install_irq_resource(pdev, pentry->irq); | ||
348 | |||
349 | pdev->dev.platform_data = pdata; | ||
350 | platform_device_add(pdev); | ||
351 | } | ||
352 | |||
353 | static void __init sfi_handle_spi_dev(struct sfi_device_table_entry *pentry, | ||
354 | struct devs_id *dev) | ||
355 | { | ||
356 | struct spi_board_info spi_info; | ||
357 | void *pdata = NULL; | ||
358 | |||
359 | memset(&spi_info, 0, sizeof(spi_info)); | ||
360 | strncpy(spi_info.modalias, pentry->name, SFI_NAME_LEN); | ||
361 | spi_info.irq = ((pentry->irq == (u8)0xff) ? 0 : pentry->irq); | ||
362 | spi_info.bus_num = pentry->host_num; | ||
363 | spi_info.chip_select = pentry->addr; | ||
364 | spi_info.max_speed_hz = pentry->max_freq; | ||
365 | pr_debug("SPI bus=%d, name=%16.16s, irq=0x%2x, max_freq=%d, cs=%d\n", | ||
366 | spi_info.bus_num, | ||
367 | spi_info.modalias, | ||
368 | spi_info.irq, | ||
369 | spi_info.max_speed_hz, | ||
370 | spi_info.chip_select); | ||
371 | |||
372 | pdata = intel_mid_sfi_get_pdata(dev, &spi_info); | ||
373 | |||
374 | spi_info.platform_data = pdata; | ||
375 | if (dev->delay) | ||
376 | intel_scu_spi_device_register(&spi_info); | ||
377 | else | ||
378 | spi_register_board_info(&spi_info, 1); | ||
379 | } | ||
380 | |||
381 | static void __init sfi_handle_i2c_dev(struct sfi_device_table_entry *pentry, | ||
382 | struct devs_id *dev) | ||
383 | { | ||
384 | struct i2c_board_info i2c_info; | ||
385 | void *pdata = NULL; | ||
386 | |||
387 | memset(&i2c_info, 0, sizeof(i2c_info)); | ||
388 | strncpy(i2c_info.type, pentry->name, SFI_NAME_LEN); | ||
389 | i2c_info.irq = ((pentry->irq == (u8)0xff) ? 0 : pentry->irq); | ||
390 | i2c_info.addr = pentry->addr; | ||
391 | pr_debug("I2C bus = %d, name = %16.16s, irq = 0x%2x, addr = 0x%x\n", | ||
392 | pentry->host_num, | ||
393 | i2c_info.type, | ||
394 | i2c_info.irq, | ||
395 | i2c_info.addr); | ||
396 | pdata = intel_mid_sfi_get_pdata(dev, &i2c_info); | ||
397 | i2c_info.platform_data = pdata; | ||
398 | |||
399 | if (dev->delay) | ||
400 | intel_scu_i2c_device_register(pentry->host_num, &i2c_info); | ||
401 | else | ||
402 | i2c_register_board_info(pentry->host_num, &i2c_info, 1); | ||
403 | } | ||
404 | |||
405 | extern struct devs_id *const __x86_intel_mid_dev_start[], | ||
406 | *const __x86_intel_mid_dev_end[]; | ||
407 | |||
408 | static struct devs_id __init *get_device_id(u8 type, char *name) | ||
409 | { | ||
410 | struct devs_id *const *dev_table; | ||
411 | |||
412 | for (dev_table = __x86_intel_mid_dev_start; | ||
413 | dev_table < __x86_intel_mid_dev_end; dev_table++) { | ||
414 | struct devs_id *dev = *dev_table; | ||
415 | if (dev->type == type && | ||
416 | !strncmp(dev->name, name, SFI_NAME_LEN)) { | ||
417 | return dev; | ||
418 | } | ||
419 | } | ||
420 | |||
421 | return NULL; | ||
422 | } | ||
423 | |||
424 | static int __init sfi_parse_devs(struct sfi_table_header *table) | ||
425 | { | ||
426 | struct sfi_table_simple *sb; | ||
427 | struct sfi_device_table_entry *pentry; | ||
428 | struct devs_id *dev = NULL; | ||
429 | int num, i; | ||
430 | int ioapic; | ||
431 | struct io_apic_irq_attr irq_attr; | ||
432 | |||
433 | sb = (struct sfi_table_simple *)table; | ||
434 | num = SFI_GET_NUM_ENTRIES(sb, struct sfi_device_table_entry); | ||
435 | pentry = (struct sfi_device_table_entry *)sb->pentry; | ||
436 | |||
437 | for (i = 0; i < num; i++, pentry++) { | ||
438 | int irq = pentry->irq; | ||
439 | |||
440 | if (irq != (u8)0xff) { /* native RTE case */ | ||
441 | /* these SPI2 devices are not exposed to system as PCI | ||
442 | * devices, but they have separate RTE entry in IOAPIC | ||
443 | * so we have to enable them one by one here | ||
444 | */ | ||
445 | ioapic = mp_find_ioapic(irq); | ||
446 | irq_attr.ioapic = ioapic; | ||
447 | irq_attr.ioapic_pin = irq; | ||
448 | irq_attr.trigger = 1; | ||
449 | irq_attr.polarity = 1; | ||
450 | io_apic_set_pci_routing(NULL, irq, &irq_attr); | ||
451 | } else | ||
452 | irq = 0; /* No irq */ | ||
453 | |||
454 | dev = get_device_id(pentry->type, pentry->name); | ||
455 | |||
456 | if (!dev) | ||
457 | continue; | ||
458 | |||
459 | if (dev->device_handler) { | ||
460 | dev->device_handler(pentry, dev); | ||
461 | } else { | ||
462 | switch (pentry->type) { | ||
463 | case SFI_DEV_TYPE_IPC: | ||
464 | sfi_handle_ipc_dev(pentry, dev); | ||
465 | break; | ||
466 | case SFI_DEV_TYPE_SPI: | ||
467 | sfi_handle_spi_dev(pentry, dev); | ||
468 | break; | ||
469 | case SFI_DEV_TYPE_I2C: | ||
470 | sfi_handle_i2c_dev(pentry, dev); | ||
471 | break; | ||
472 | case SFI_DEV_TYPE_UART: | ||
473 | case SFI_DEV_TYPE_HSI: | ||
474 | default: | ||
475 | break; | ||
476 | } | ||
477 | } | ||
478 | } | ||
479 | return 0; | ||
480 | } | ||
481 | |||
482 | static int __init intel_mid_platform_init(void) | ||
483 | { | ||
484 | sfi_table_parse(SFI_SIG_GPIO, NULL, NULL, sfi_parse_gpio); | ||
485 | sfi_table_parse(SFI_SIG_DEVS, NULL, NULL, sfi_parse_devs); | ||
486 | return 0; | ||
487 | } | ||
488 | arch_initcall(intel_mid_platform_init); | ||
diff --git a/arch/x86/platform/mrst/Makefile b/arch/x86/platform/mrst/Makefile deleted file mode 100644 index af1da7e623f9..000000000000 --- a/arch/x86/platform/mrst/Makefile +++ /dev/null | |||
@@ -1,3 +0,0 @@ | |||
1 | obj-$(CONFIG_X86_INTEL_MID) += mrst.o | ||
2 | obj-$(CONFIG_X86_INTEL_MID) += vrtc.o | ||
3 | obj-$(CONFIG_EARLY_PRINTK_INTEL_MID) += early_printk_mrst.o | ||
diff --git a/arch/x86/platform/mrst/mrst.c b/arch/x86/platform/mrst/mrst.c deleted file mode 100644 index 3ca5957b7a34..000000000000 --- a/arch/x86/platform/mrst/mrst.c +++ /dev/null | |||
@@ -1,1052 +0,0 @@ | |||
1 | /* | ||
2 | * mrst.c: Intel Moorestown platform specific setup code | ||
3 | * | ||
4 | * (C) Copyright 2008 Intel Corporation | ||
5 | * Author: Jacob Pan (jacob.jun.pan@intel.com) | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; version 2 | ||
10 | * of the License. | ||
11 | */ | ||
12 | |||
13 | #define pr_fmt(fmt) "mrst: " fmt | ||
14 | |||
15 | #include <linux/init.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/scatterlist.h> | ||
19 | #include <linux/sfi.h> | ||
20 | #include <linux/intel_pmic_gpio.h> | ||
21 | #include <linux/spi/spi.h> | ||
22 | #include <linux/i2c.h> | ||
23 | #include <linux/platform_data/pca953x.h> | ||
24 | #include <linux/gpio_keys.h> | ||
25 | #include <linux/input.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | #include <linux/irq.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/notifier.h> | ||
30 | #include <linux/mfd/intel_msic.h> | ||
31 | #include <linux/gpio.h> | ||
32 | #include <linux/i2c/tc35876x.h> | ||
33 | |||
34 | #include <asm/setup.h> | ||
35 | #include <asm/mpspec_def.h> | ||
36 | #include <asm/hw_irq.h> | ||
37 | #include <asm/apic.h> | ||
38 | #include <asm/io_apic.h> | ||
39 | #include <asm/mrst.h> | ||
40 | #include <asm/mrst-vrtc.h> | ||
41 | #include <asm/io.h> | ||
42 | #include <asm/i8259.h> | ||
43 | #include <asm/intel_scu_ipc.h> | ||
44 | #include <asm/apb_timer.h> | ||
45 | #include <asm/reboot.h> | ||
46 | |||
47 | /* | ||
48 | * the clockevent devices on Moorestown/Medfield can be APBT or LAPIC clock, | ||
49 | * cmdline option x86_mrst_timer can be used to override the configuration | ||
50 | * to prefer one or the other. | ||
51 | * at runtime, there are basically three timer configurations: | ||
52 | * 1. per cpu apbt clock only | ||
53 | * 2. per cpu always-on lapic clocks only, this is Penwell/Medfield only | ||
54 | * 3. per cpu lapic clock (C3STOP) and one apbt clock, with broadcast. | ||
55 | * | ||
56 | * by default (without cmdline option), platform code first detects cpu type | ||
57 | * to see if we are on lincroft or penwell, then set up both lapic or apbt | ||
58 | * clocks accordingly. | ||
59 | * i.e. by default, medfield uses configuration #2, moorestown uses #1. | ||
60 | * config #3 is supported but not recommended on medfield. | ||
61 | * | ||
62 | * rating and feature summary: | ||
63 | * lapic (with C3STOP) --------- 100 | ||
64 | * apbt (always-on) ------------ 110 | ||
65 | * lapic (always-on,ARAT) ------ 150 | ||
66 | */ | ||
67 | |||
68 | enum mrst_timer_options mrst_timer_options; | ||
69 | |||
70 | static u32 sfi_mtimer_usage[SFI_MTMR_MAX_NUM]; | ||
71 | static struct sfi_timer_table_entry sfi_mtimer_array[SFI_MTMR_MAX_NUM]; | ||
72 | enum mrst_cpu_type __mrst_cpu_chip; | ||
73 | EXPORT_SYMBOL_GPL(__mrst_cpu_chip); | ||
74 | |||
75 | int sfi_mtimer_num; | ||
76 | |||
77 | struct sfi_rtc_table_entry sfi_mrtc_array[SFI_MRTC_MAX]; | ||
78 | EXPORT_SYMBOL_GPL(sfi_mrtc_array); | ||
79 | int sfi_mrtc_num; | ||
80 | |||
81 | static void mrst_power_off(void) | ||
82 | { | ||
83 | } | ||
84 | |||
85 | static void mrst_reboot(void) | ||
86 | { | ||
87 | intel_scu_ipc_simple_command(IPCMSG_COLD_BOOT, 0); | ||
88 | } | ||
89 | |||
90 | /* parse all the mtimer info to a static mtimer array */ | ||
91 | static int __init sfi_parse_mtmr(struct sfi_table_header *table) | ||
92 | { | ||
93 | struct sfi_table_simple *sb; | ||
94 | struct sfi_timer_table_entry *pentry; | ||
95 | struct mpc_intsrc mp_irq; | ||
96 | int totallen; | ||
97 | |||
98 | sb = (struct sfi_table_simple *)table; | ||
99 | if (!sfi_mtimer_num) { | ||
100 | sfi_mtimer_num = SFI_GET_NUM_ENTRIES(sb, | ||
101 | struct sfi_timer_table_entry); | ||
102 | pentry = (struct sfi_timer_table_entry *) sb->pentry; | ||
103 | totallen = sfi_mtimer_num * sizeof(*pentry); | ||
104 | memcpy(sfi_mtimer_array, pentry, totallen); | ||
105 | } | ||
106 | |||
107 | pr_debug("SFI MTIMER info (num = %d):\n", sfi_mtimer_num); | ||
108 | pentry = sfi_mtimer_array; | ||
109 | for (totallen = 0; totallen < sfi_mtimer_num; totallen++, pentry++) { | ||
110 | pr_debug("timer[%d]: paddr = 0x%08x, freq = %dHz," | ||
111 | " irq = %d\n", totallen, (u32)pentry->phys_addr, | ||
112 | pentry->freq_hz, pentry->irq); | ||
113 | if (!pentry->irq) | ||
114 | continue; | ||
115 | mp_irq.type = MP_INTSRC; | ||
116 | mp_irq.irqtype = mp_INT; | ||
117 | /* triggering mode edge bit 2-3, active high polarity bit 0-1 */ | ||
118 | mp_irq.irqflag = 5; | ||
119 | mp_irq.srcbus = MP_BUS_ISA; | ||
120 | mp_irq.srcbusirq = pentry->irq; /* IRQ */ | ||
121 | mp_irq.dstapic = MP_APIC_ALL; | ||
122 | mp_irq.dstirq = pentry->irq; | ||
123 | mp_save_irq(&mp_irq); | ||
124 | } | ||
125 | |||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | struct sfi_timer_table_entry *sfi_get_mtmr(int hint) | ||
130 | { | ||
131 | int i; | ||
132 | if (hint < sfi_mtimer_num) { | ||
133 | if (!sfi_mtimer_usage[hint]) { | ||
134 | pr_debug("hint taken for timer %d irq %d\n",\ | ||
135 | hint, sfi_mtimer_array[hint].irq); | ||
136 | sfi_mtimer_usage[hint] = 1; | ||
137 | return &sfi_mtimer_array[hint]; | ||
138 | } | ||
139 | } | ||
140 | /* take the first timer available */ | ||
141 | for (i = 0; i < sfi_mtimer_num;) { | ||
142 | if (!sfi_mtimer_usage[i]) { | ||
143 | sfi_mtimer_usage[i] = 1; | ||
144 | return &sfi_mtimer_array[i]; | ||
145 | } | ||
146 | i++; | ||
147 | } | ||
148 | return NULL; | ||
149 | } | ||
150 | |||
151 | void sfi_free_mtmr(struct sfi_timer_table_entry *mtmr) | ||
152 | { | ||
153 | int i; | ||
154 | for (i = 0; i < sfi_mtimer_num;) { | ||
155 | if (mtmr->irq == sfi_mtimer_array[i].irq) { | ||
156 | sfi_mtimer_usage[i] = 0; | ||
157 | return; | ||
158 | } | ||
159 | i++; | ||
160 | } | ||
161 | } | ||
162 | |||
163 | /* parse all the mrtc info to a global mrtc array */ | ||
164 | int __init sfi_parse_mrtc(struct sfi_table_header *table) | ||
165 | { | ||
166 | struct sfi_table_simple *sb; | ||
167 | struct sfi_rtc_table_entry *pentry; | ||
168 | struct mpc_intsrc mp_irq; | ||
169 | |||
170 | int totallen; | ||
171 | |||
172 | sb = (struct sfi_table_simple *)table; | ||
173 | if (!sfi_mrtc_num) { | ||
174 | sfi_mrtc_num = SFI_GET_NUM_ENTRIES(sb, | ||
175 | struct sfi_rtc_table_entry); | ||
176 | pentry = (struct sfi_rtc_table_entry *)sb->pentry; | ||
177 | totallen = sfi_mrtc_num * sizeof(*pentry); | ||
178 | memcpy(sfi_mrtc_array, pentry, totallen); | ||
179 | } | ||
180 | |||
181 | pr_debug("SFI RTC info (num = %d):\n", sfi_mrtc_num); | ||
182 | pentry = sfi_mrtc_array; | ||
183 | for (totallen = 0; totallen < sfi_mrtc_num; totallen++, pentry++) { | ||
184 | pr_debug("RTC[%d]: paddr = 0x%08x, irq = %d\n", | ||
185 | totallen, (u32)pentry->phys_addr, pentry->irq); | ||
186 | mp_irq.type = MP_INTSRC; | ||
187 | mp_irq.irqtype = mp_INT; | ||
188 | mp_irq.irqflag = 0xf; /* level trigger and active low */ | ||
189 | mp_irq.srcbus = MP_BUS_ISA; | ||
190 | mp_irq.srcbusirq = pentry->irq; /* IRQ */ | ||
191 | mp_irq.dstapic = MP_APIC_ALL; | ||
192 | mp_irq.dstirq = pentry->irq; | ||
193 | mp_save_irq(&mp_irq); | ||
194 | } | ||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | static unsigned long __init mrst_calibrate_tsc(void) | ||
199 | { | ||
200 | unsigned long fast_calibrate; | ||
201 | u32 lo, hi, ratio, fsb; | ||
202 | |||
203 | rdmsr(MSR_IA32_PERF_STATUS, lo, hi); | ||
204 | pr_debug("IA32 perf status is 0x%x, 0x%0x\n", lo, hi); | ||
205 | ratio = (hi >> 8) & 0x1f; | ||
206 | pr_debug("ratio is %d\n", ratio); | ||
207 | if (!ratio) { | ||
208 | pr_err("read a zero ratio, should be incorrect!\n"); | ||
209 | pr_err("force tsc ratio to 16 ...\n"); | ||
210 | ratio = 16; | ||
211 | } | ||
212 | rdmsr(MSR_FSB_FREQ, lo, hi); | ||
213 | if ((lo & 0x7) == 0x7) | ||
214 | fsb = PENWELL_FSB_FREQ_83SKU; | ||
215 | else | ||
216 | fsb = PENWELL_FSB_FREQ_100SKU; | ||
217 | fast_calibrate = ratio * fsb; | ||
218 | pr_debug("read penwell tsc %lu khz\n", fast_calibrate); | ||
219 | lapic_timer_frequency = fsb * 1000 / HZ; | ||
220 | /* mark tsc clocksource as reliable */ | ||
221 | set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE); | ||
222 | |||
223 | if (fast_calibrate) | ||
224 | return fast_calibrate; | ||
225 | |||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | static void __init mrst_time_init(void) | ||
230 | { | ||
231 | sfi_table_parse(SFI_SIG_MTMR, NULL, NULL, sfi_parse_mtmr); | ||
232 | switch (mrst_timer_options) { | ||
233 | case MRST_TIMER_APBT_ONLY: | ||
234 | break; | ||
235 | case MRST_TIMER_LAPIC_APBT: | ||
236 | x86_init.timers.setup_percpu_clockev = setup_boot_APIC_clock; | ||
237 | x86_cpuinit.setup_percpu_clockev = setup_secondary_APIC_clock; | ||
238 | break; | ||
239 | default: | ||
240 | if (!boot_cpu_has(X86_FEATURE_ARAT)) | ||
241 | break; | ||
242 | x86_init.timers.setup_percpu_clockev = setup_boot_APIC_clock; | ||
243 | x86_cpuinit.setup_percpu_clockev = setup_secondary_APIC_clock; | ||
244 | return; | ||
245 | } | ||
246 | /* we need at least one APB timer */ | ||
247 | pre_init_apic_IRQ0(); | ||
248 | apbt_time_init(); | ||
249 | } | ||
250 | |||
251 | static void mrst_arch_setup(void) | ||
252 | { | ||
253 | if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 0x27) | ||
254 | __mrst_cpu_chip = MRST_CPU_CHIP_PENWELL; | ||
255 | else { | ||
256 | pr_err("Unknown Intel MID CPU (%d:%d), default to Penwell\n", | ||
257 | boot_cpu_data.x86, boot_cpu_data.x86_model); | ||
258 | __mrst_cpu_chip = MRST_CPU_CHIP_PENWELL; | ||
259 | } | ||
260 | } | ||
261 | |||
262 | /* MID systems don't have i8042 controller */ | ||
263 | static int mrst_i8042_detect(void) | ||
264 | { | ||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | /* | ||
269 | * Moorestown does not have external NMI source nor port 0x61 to report | ||
270 | * NMI status. The possible NMI sources are from pmu as a result of NMI | ||
271 | * watchdog or lock debug. Reading io port 0x61 results in 0xff which | ||
272 | * misled NMI handler. | ||
273 | */ | ||
274 | static unsigned char mrst_get_nmi_reason(void) | ||
275 | { | ||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | /* | ||
280 | * Moorestown specific x86_init function overrides and early setup | ||
281 | * calls. | ||
282 | */ | ||
283 | void __init x86_mrst_early_setup(void) | ||
284 | { | ||
285 | x86_init.resources.probe_roms = x86_init_noop; | ||
286 | x86_init.resources.reserve_resources = x86_init_noop; | ||
287 | |||
288 | x86_init.timers.timer_init = mrst_time_init; | ||
289 | x86_init.timers.setup_percpu_clockev = x86_init_noop; | ||
290 | |||
291 | x86_init.irqs.pre_vector_init = x86_init_noop; | ||
292 | |||
293 | x86_init.oem.arch_setup = mrst_arch_setup; | ||
294 | |||
295 | x86_cpuinit.setup_percpu_clockev = apbt_setup_secondary_clock; | ||
296 | |||
297 | x86_platform.calibrate_tsc = mrst_calibrate_tsc; | ||
298 | x86_platform.i8042_detect = mrst_i8042_detect; | ||
299 | x86_init.timers.wallclock_init = mrst_rtc_init; | ||
300 | x86_platform.get_nmi_reason = mrst_get_nmi_reason; | ||
301 | |||
302 | x86_init.pci.init = pci_mrst_init; | ||
303 | x86_init.pci.fixup_irqs = x86_init_noop; | ||
304 | |||
305 | legacy_pic = &null_legacy_pic; | ||
306 | |||
307 | /* Moorestown specific power_off/restart method */ | ||
308 | pm_power_off = mrst_power_off; | ||
309 | machine_ops.emergency_restart = mrst_reboot; | ||
310 | |||
311 | /* Avoid searching for BIOS MP tables */ | ||
312 | x86_init.mpparse.find_smp_config = x86_init_noop; | ||
313 | x86_init.mpparse.get_smp_config = x86_init_uint_noop; | ||
314 | set_bit(MP_BUS_ISA, mp_bus_not_pci); | ||
315 | } | ||
316 | |||
317 | /* | ||
318 | * if user does not want to use per CPU apb timer, just give it a lower rating | ||
319 | * than local apic timer and skip the late per cpu timer init. | ||
320 | */ | ||
321 | static inline int __init setup_x86_mrst_timer(char *arg) | ||
322 | { | ||
323 | if (!arg) | ||
324 | return -EINVAL; | ||
325 | |||
326 | if (strcmp("apbt_only", arg) == 0) | ||
327 | mrst_timer_options = MRST_TIMER_APBT_ONLY; | ||
328 | else if (strcmp("lapic_and_apbt", arg) == 0) | ||
329 | mrst_timer_options = MRST_TIMER_LAPIC_APBT; | ||
330 | else { | ||
331 | pr_warning("X86 MRST timer option %s not recognised" | ||
332 | " use x86_mrst_timer=apbt_only or lapic_and_apbt\n", | ||
333 | arg); | ||
334 | return -EINVAL; | ||
335 | } | ||
336 | return 0; | ||
337 | } | ||
338 | __setup("x86_mrst_timer=", setup_x86_mrst_timer); | ||
339 | |||
340 | /* | ||
341 | * Parsing GPIO table first, since the DEVS table will need this table | ||
342 | * to map the pin name to the actual pin. | ||
343 | */ | ||
344 | static struct sfi_gpio_table_entry *gpio_table; | ||
345 | static int gpio_num_entry; | ||
346 | |||
347 | static int __init sfi_parse_gpio(struct sfi_table_header *table) | ||
348 | { | ||
349 | struct sfi_table_simple *sb; | ||
350 | struct sfi_gpio_table_entry *pentry; | ||
351 | int num, i; | ||
352 | |||
353 | if (gpio_table) | ||
354 | return 0; | ||
355 | sb = (struct sfi_table_simple *)table; | ||
356 | num = SFI_GET_NUM_ENTRIES(sb, struct sfi_gpio_table_entry); | ||
357 | pentry = (struct sfi_gpio_table_entry *)sb->pentry; | ||
358 | |||
359 | gpio_table = kmalloc(num * sizeof(*pentry), GFP_KERNEL); | ||
360 | if (!gpio_table) | ||
361 | return -1; | ||
362 | memcpy(gpio_table, pentry, num * sizeof(*pentry)); | ||
363 | gpio_num_entry = num; | ||
364 | |||
365 | pr_debug("GPIO pin info:\n"); | ||
366 | for (i = 0; i < num; i++, pentry++) | ||
367 | pr_debug("info[%2d]: controller = %16.16s, pin_name = %16.16s," | ||
368 | " pin = %d\n", i, | ||
369 | pentry->controller_name, | ||
370 | pentry->pin_name, | ||
371 | pentry->pin_no); | ||
372 | return 0; | ||
373 | } | ||
374 | |||
375 | static int get_gpio_by_name(const char *name) | ||
376 | { | ||
377 | struct sfi_gpio_table_entry *pentry = gpio_table; | ||
378 | int i; | ||
379 | |||
380 | if (!pentry) | ||
381 | return -1; | ||
382 | for (i = 0; i < gpio_num_entry; i++, pentry++) { | ||
383 | if (!strncmp(name, pentry->pin_name, SFI_NAME_LEN)) | ||
384 | return pentry->pin_no; | ||
385 | } | ||
386 | return -1; | ||
387 | } | ||
388 | |||
389 | /* | ||
390 | * Here defines the array of devices platform data that IAFW would export | ||
391 | * through SFI "DEVS" table, we use name and type to match the device and | ||
392 | * its platform data. | ||
393 | */ | ||
394 | struct devs_id { | ||
395 | char name[SFI_NAME_LEN + 1]; | ||
396 | u8 type; | ||
397 | u8 delay; | ||
398 | void *(*get_platform_data)(void *info); | ||
399 | }; | ||
400 | |||
401 | /* the offset for the mapping of global gpio pin to irq */ | ||
402 | #define MRST_IRQ_OFFSET 0x100 | ||
403 | |||
404 | static void __init *pmic_gpio_platform_data(void *info) | ||
405 | { | ||
406 | static struct intel_pmic_gpio_platform_data pmic_gpio_pdata; | ||
407 | int gpio_base = get_gpio_by_name("pmic_gpio_base"); | ||
408 | |||
409 | if (gpio_base == -1) | ||
410 | gpio_base = 64; | ||
411 | pmic_gpio_pdata.gpio_base = gpio_base; | ||
412 | pmic_gpio_pdata.irq_base = gpio_base + MRST_IRQ_OFFSET; | ||
413 | pmic_gpio_pdata.gpiointr = 0xffffeff8; | ||
414 | |||
415 | return &pmic_gpio_pdata; | ||
416 | } | ||
417 | |||
418 | static void __init *max3111_platform_data(void *info) | ||
419 | { | ||
420 | struct spi_board_info *spi_info = info; | ||
421 | int intr = get_gpio_by_name("max3111_int"); | ||
422 | |||
423 | spi_info->mode = SPI_MODE_0; | ||
424 | if (intr == -1) | ||
425 | return NULL; | ||
426 | spi_info->irq = intr + MRST_IRQ_OFFSET; | ||
427 | return NULL; | ||
428 | } | ||
429 | |||
430 | /* we have multiple max7315 on the board ... */ | ||
431 | #define MAX7315_NUM 2 | ||
432 | static void __init *max7315_platform_data(void *info) | ||
433 | { | ||
434 | static struct pca953x_platform_data max7315_pdata[MAX7315_NUM]; | ||
435 | static int nr; | ||
436 | struct pca953x_platform_data *max7315 = &max7315_pdata[nr]; | ||
437 | struct i2c_board_info *i2c_info = info; | ||
438 | int gpio_base, intr; | ||
439 | char base_pin_name[SFI_NAME_LEN + 1]; | ||
440 | char intr_pin_name[SFI_NAME_LEN + 1]; | ||
441 | |||
442 | if (nr == MAX7315_NUM) { | ||
443 | pr_err("too many max7315s, we only support %d\n", | ||
444 | MAX7315_NUM); | ||
445 | return NULL; | ||
446 | } | ||
447 | /* we have several max7315 on the board, we only need load several | ||
448 | * instances of the same pca953x driver to cover them | ||
449 | */ | ||
450 | strcpy(i2c_info->type, "max7315"); | ||
451 | if (nr++) { | ||
452 | sprintf(base_pin_name, "max7315_%d_base", nr); | ||
453 | sprintf(intr_pin_name, "max7315_%d_int", nr); | ||
454 | } else { | ||
455 | strcpy(base_pin_name, "max7315_base"); | ||
456 | strcpy(intr_pin_name, "max7315_int"); | ||
457 | } | ||
458 | |||
459 | gpio_base = get_gpio_by_name(base_pin_name); | ||
460 | intr = get_gpio_by_name(intr_pin_name); | ||
461 | |||
462 | if (gpio_base == -1) | ||
463 | return NULL; | ||
464 | max7315->gpio_base = gpio_base; | ||
465 | if (intr != -1) { | ||
466 | i2c_info->irq = intr + MRST_IRQ_OFFSET; | ||
467 | max7315->irq_base = gpio_base + MRST_IRQ_OFFSET; | ||
468 | } else { | ||
469 | i2c_info->irq = -1; | ||
470 | max7315->irq_base = -1; | ||
471 | } | ||
472 | return max7315; | ||
473 | } | ||
474 | |||
475 | static void *tca6416_platform_data(void *info) | ||
476 | { | ||
477 | static struct pca953x_platform_data tca6416; | ||
478 | struct i2c_board_info *i2c_info = info; | ||
479 | int gpio_base, intr; | ||
480 | char base_pin_name[SFI_NAME_LEN + 1]; | ||
481 | char intr_pin_name[SFI_NAME_LEN + 1]; | ||
482 | |||
483 | strcpy(i2c_info->type, "tca6416"); | ||
484 | strcpy(base_pin_name, "tca6416_base"); | ||
485 | strcpy(intr_pin_name, "tca6416_int"); | ||
486 | |||
487 | gpio_base = get_gpio_by_name(base_pin_name); | ||
488 | intr = get_gpio_by_name(intr_pin_name); | ||
489 | |||
490 | if (gpio_base == -1) | ||
491 | return NULL; | ||
492 | tca6416.gpio_base = gpio_base; | ||
493 | if (intr != -1) { | ||
494 | i2c_info->irq = intr + MRST_IRQ_OFFSET; | ||
495 | tca6416.irq_base = gpio_base + MRST_IRQ_OFFSET; | ||
496 | } else { | ||
497 | i2c_info->irq = -1; | ||
498 | tca6416.irq_base = -1; | ||
499 | } | ||
500 | return &tca6416; | ||
501 | } | ||
502 | |||
503 | static void *mpu3050_platform_data(void *info) | ||
504 | { | ||
505 | struct i2c_board_info *i2c_info = info; | ||
506 | int intr = get_gpio_by_name("mpu3050_int"); | ||
507 | |||
508 | if (intr == -1) | ||
509 | return NULL; | ||
510 | |||
511 | i2c_info->irq = intr + MRST_IRQ_OFFSET; | ||
512 | return NULL; | ||
513 | } | ||
514 | |||
515 | static void __init *emc1403_platform_data(void *info) | ||
516 | { | ||
517 | static short intr2nd_pdata; | ||
518 | struct i2c_board_info *i2c_info = info; | ||
519 | int intr = get_gpio_by_name("thermal_int"); | ||
520 | int intr2nd = get_gpio_by_name("thermal_alert"); | ||
521 | |||
522 | if (intr == -1 || intr2nd == -1) | ||
523 | return NULL; | ||
524 | |||
525 | i2c_info->irq = intr + MRST_IRQ_OFFSET; | ||
526 | intr2nd_pdata = intr2nd + MRST_IRQ_OFFSET; | ||
527 | |||
528 | return &intr2nd_pdata; | ||
529 | } | ||
530 | |||
531 | static void __init *lis331dl_platform_data(void *info) | ||
532 | { | ||
533 | static short intr2nd_pdata; | ||
534 | struct i2c_board_info *i2c_info = info; | ||
535 | int intr = get_gpio_by_name("accel_int"); | ||
536 | int intr2nd = get_gpio_by_name("accel_2"); | ||
537 | |||
538 | if (intr == -1 || intr2nd == -1) | ||
539 | return NULL; | ||
540 | |||
541 | i2c_info->irq = intr + MRST_IRQ_OFFSET; | ||
542 | intr2nd_pdata = intr2nd + MRST_IRQ_OFFSET; | ||
543 | |||
544 | return &intr2nd_pdata; | ||
545 | } | ||
546 | |||
547 | static void __init *no_platform_data(void *info) | ||
548 | { | ||
549 | return NULL; | ||
550 | } | ||
551 | |||
552 | static struct resource msic_resources[] = { | ||
553 | { | ||
554 | .start = INTEL_MSIC_IRQ_PHYS_BASE, | ||
555 | .end = INTEL_MSIC_IRQ_PHYS_BASE + 64 - 1, | ||
556 | .flags = IORESOURCE_MEM, | ||
557 | }, | ||
558 | }; | ||
559 | |||
560 | static struct intel_msic_platform_data msic_pdata; | ||
561 | |||
562 | static struct platform_device msic_device = { | ||
563 | .name = "intel_msic", | ||
564 | .id = -1, | ||
565 | .dev = { | ||
566 | .platform_data = &msic_pdata, | ||
567 | }, | ||
568 | .num_resources = ARRAY_SIZE(msic_resources), | ||
569 | .resource = msic_resources, | ||
570 | }; | ||
571 | |||
572 | static inline bool mrst_has_msic(void) | ||
573 | { | ||
574 | return mrst_identify_cpu() == MRST_CPU_CHIP_PENWELL; | ||
575 | } | ||
576 | |||
577 | static int msic_scu_status_change(struct notifier_block *nb, | ||
578 | unsigned long code, void *data) | ||
579 | { | ||
580 | if (code == SCU_DOWN) { | ||
581 | platform_device_unregister(&msic_device); | ||
582 | return 0; | ||
583 | } | ||
584 | |||
585 | return platform_device_register(&msic_device); | ||
586 | } | ||
587 | |||
588 | static int __init msic_init(void) | ||
589 | { | ||
590 | static struct notifier_block msic_scu_notifier = { | ||
591 | .notifier_call = msic_scu_status_change, | ||
592 | }; | ||
593 | |||
594 | /* | ||
595 | * We need to be sure that the SCU IPC is ready before MSIC device | ||
596 | * can be registered. | ||
597 | */ | ||
598 | if (mrst_has_msic()) | ||
599 | intel_scu_notifier_add(&msic_scu_notifier); | ||
600 | |||
601 | return 0; | ||
602 | } | ||
603 | arch_initcall(msic_init); | ||
604 | |||
605 | /* | ||
606 | * msic_generic_platform_data - sets generic platform data for the block | ||
607 | * @info: pointer to the SFI device table entry for this block | ||
608 | * @block: MSIC block | ||
609 | * | ||
610 | * Function sets IRQ number from the SFI table entry for given device to | ||
611 | * the MSIC platform data. | ||
612 | */ | ||
613 | static void *msic_generic_platform_data(void *info, enum intel_msic_block block) | ||
614 | { | ||
615 | struct sfi_device_table_entry *entry = info; | ||
616 | |||
617 | BUG_ON(block < 0 || block >= INTEL_MSIC_BLOCK_LAST); | ||
618 | msic_pdata.irq[block] = entry->irq; | ||
619 | |||
620 | return no_platform_data(info); | ||
621 | } | ||
622 | |||
623 | static void *msic_battery_platform_data(void *info) | ||
624 | { | ||
625 | return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_BATTERY); | ||
626 | } | ||
627 | |||
628 | static void *msic_gpio_platform_data(void *info) | ||
629 | { | ||
630 | static struct intel_msic_gpio_pdata pdata; | ||
631 | int gpio = get_gpio_by_name("msic_gpio_base"); | ||
632 | |||
633 | if (gpio < 0) | ||
634 | return NULL; | ||
635 | |||
636 | pdata.gpio_base = gpio; | ||
637 | msic_pdata.gpio = &pdata; | ||
638 | |||
639 | return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_GPIO); | ||
640 | } | ||
641 | |||
642 | static void *msic_audio_platform_data(void *info) | ||
643 | { | ||
644 | struct platform_device *pdev; | ||
645 | |||
646 | pdev = platform_device_register_simple("sst-platform", -1, NULL, 0); | ||
647 | if (IS_ERR(pdev)) { | ||
648 | pr_err("failed to create audio platform device\n"); | ||
649 | return NULL; | ||
650 | } | ||
651 | |||
652 | return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_AUDIO); | ||
653 | } | ||
654 | |||
655 | static void *msic_power_btn_platform_data(void *info) | ||
656 | { | ||
657 | return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_POWER_BTN); | ||
658 | } | ||
659 | |||
660 | static void *msic_ocd_platform_data(void *info) | ||
661 | { | ||
662 | static struct intel_msic_ocd_pdata pdata; | ||
663 | int gpio = get_gpio_by_name("ocd_gpio"); | ||
664 | |||
665 | if (gpio < 0) | ||
666 | return NULL; | ||
667 | |||
668 | pdata.gpio = gpio; | ||
669 | msic_pdata.ocd = &pdata; | ||
670 | |||
671 | return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_OCD); | ||
672 | } | ||
673 | |||
674 | static void *msic_thermal_platform_data(void *info) | ||
675 | { | ||
676 | return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_THERMAL); | ||
677 | } | ||
678 | |||
679 | /* tc35876x DSI-LVDS bridge chip and panel platform data */ | ||
680 | static void *tc35876x_platform_data(void *data) | ||
681 | { | ||
682 | static struct tc35876x_platform_data pdata; | ||
683 | |||
684 | /* gpio pins set to -1 will not be used by the driver */ | ||
685 | pdata.gpio_bridge_reset = get_gpio_by_name("LCMB_RXEN"); | ||
686 | pdata.gpio_panel_bl_en = get_gpio_by_name("6S6P_BL_EN"); | ||
687 | pdata.gpio_panel_vadd = get_gpio_by_name("EN_VREG_LCD_V3P3"); | ||
688 | |||
689 | return &pdata; | ||
690 | } | ||
691 | |||
692 | static const struct devs_id __initconst device_ids[] = { | ||
693 | {"bma023", SFI_DEV_TYPE_I2C, 1, &no_platform_data}, | ||
694 | {"pmic_gpio", SFI_DEV_TYPE_SPI, 1, &pmic_gpio_platform_data}, | ||
695 | {"pmic_gpio", SFI_DEV_TYPE_IPC, 1, &pmic_gpio_platform_data}, | ||
696 | {"spi_max3111", SFI_DEV_TYPE_SPI, 0, &max3111_platform_data}, | ||
697 | {"i2c_max7315", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data}, | ||
698 | {"i2c_max7315_2", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data}, | ||
699 | {"tca6416", SFI_DEV_TYPE_I2C, 1, &tca6416_platform_data}, | ||
700 | {"emc1403", SFI_DEV_TYPE_I2C, 1, &emc1403_platform_data}, | ||
701 | {"i2c_accel", SFI_DEV_TYPE_I2C, 0, &lis331dl_platform_data}, | ||
702 | {"pmic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data}, | ||
703 | {"mpu3050", SFI_DEV_TYPE_I2C, 1, &mpu3050_platform_data}, | ||
704 | {"i2c_disp_brig", SFI_DEV_TYPE_I2C, 0, &tc35876x_platform_data}, | ||
705 | |||
706 | /* MSIC subdevices */ | ||
707 | {"msic_battery", SFI_DEV_TYPE_IPC, 1, &msic_battery_platform_data}, | ||
708 | {"msic_gpio", SFI_DEV_TYPE_IPC, 1, &msic_gpio_platform_data}, | ||
709 | {"msic_audio", SFI_DEV_TYPE_IPC, 1, &msic_audio_platform_data}, | ||
710 | {"msic_power_btn", SFI_DEV_TYPE_IPC, 1, &msic_power_btn_platform_data}, | ||
711 | {"msic_ocd", SFI_DEV_TYPE_IPC, 1, &msic_ocd_platform_data}, | ||
712 | {"msic_thermal", SFI_DEV_TYPE_IPC, 1, &msic_thermal_platform_data}, | ||
713 | |||
714 | {}, | ||
715 | }; | ||
716 | |||
717 | #define MAX_IPCDEVS 24 | ||
718 | static struct platform_device *ipc_devs[MAX_IPCDEVS]; | ||
719 | static int ipc_next_dev; | ||
720 | |||
721 | #define MAX_SCU_SPI 24 | ||
722 | static struct spi_board_info *spi_devs[MAX_SCU_SPI]; | ||
723 | static int spi_next_dev; | ||
724 | |||
725 | #define MAX_SCU_I2C 24 | ||
726 | static struct i2c_board_info *i2c_devs[MAX_SCU_I2C]; | ||
727 | static int i2c_bus[MAX_SCU_I2C]; | ||
728 | static int i2c_next_dev; | ||
729 | |||
730 | static void __init intel_scu_device_register(struct platform_device *pdev) | ||
731 | { | ||
732 | if(ipc_next_dev == MAX_IPCDEVS) | ||
733 | pr_err("too many SCU IPC devices"); | ||
734 | else | ||
735 | ipc_devs[ipc_next_dev++] = pdev; | ||
736 | } | ||
737 | |||
738 | static void __init intel_scu_spi_device_register(struct spi_board_info *sdev) | ||
739 | { | ||
740 | struct spi_board_info *new_dev; | ||
741 | |||
742 | if (spi_next_dev == MAX_SCU_SPI) { | ||
743 | pr_err("too many SCU SPI devices"); | ||
744 | return; | ||
745 | } | ||
746 | |||
747 | new_dev = kzalloc(sizeof(*sdev), GFP_KERNEL); | ||
748 | if (!new_dev) { | ||
749 | pr_err("failed to alloc mem for delayed spi dev %s\n", | ||
750 | sdev->modalias); | ||
751 | return; | ||
752 | } | ||
753 | memcpy(new_dev, sdev, sizeof(*sdev)); | ||
754 | |||
755 | spi_devs[spi_next_dev++] = new_dev; | ||
756 | } | ||
757 | |||
758 | static void __init intel_scu_i2c_device_register(int bus, | ||
759 | struct i2c_board_info *idev) | ||
760 | { | ||
761 | struct i2c_board_info *new_dev; | ||
762 | |||
763 | if (i2c_next_dev == MAX_SCU_I2C) { | ||
764 | pr_err("too many SCU I2C devices"); | ||
765 | return; | ||
766 | } | ||
767 | |||
768 | new_dev = kzalloc(sizeof(*idev), GFP_KERNEL); | ||
769 | if (!new_dev) { | ||
770 | pr_err("failed to alloc mem for delayed i2c dev %s\n", | ||
771 | idev->type); | ||
772 | return; | ||
773 | } | ||
774 | memcpy(new_dev, idev, sizeof(*idev)); | ||
775 | |||
776 | i2c_bus[i2c_next_dev] = bus; | ||
777 | i2c_devs[i2c_next_dev++] = new_dev; | ||
778 | } | ||
779 | |||
780 | BLOCKING_NOTIFIER_HEAD(intel_scu_notifier); | ||
781 | EXPORT_SYMBOL_GPL(intel_scu_notifier); | ||
782 | |||
783 | /* Called by IPC driver */ | ||
784 | void intel_scu_devices_create(void) | ||
785 | { | ||
786 | int i; | ||
787 | |||
788 | for (i = 0; i < ipc_next_dev; i++) | ||
789 | platform_device_add(ipc_devs[i]); | ||
790 | |||
791 | for (i = 0; i < spi_next_dev; i++) | ||
792 | spi_register_board_info(spi_devs[i], 1); | ||
793 | |||
794 | for (i = 0; i < i2c_next_dev; i++) { | ||
795 | struct i2c_adapter *adapter; | ||
796 | struct i2c_client *client; | ||
797 | |||
798 | adapter = i2c_get_adapter(i2c_bus[i]); | ||
799 | if (adapter) { | ||
800 | client = i2c_new_device(adapter, i2c_devs[i]); | ||
801 | if (!client) | ||
802 | pr_err("can't create i2c device %s\n", | ||
803 | i2c_devs[i]->type); | ||
804 | } else | ||
805 | i2c_register_board_info(i2c_bus[i], i2c_devs[i], 1); | ||
806 | } | ||
807 | intel_scu_notifier_post(SCU_AVAILABLE, NULL); | ||
808 | } | ||
809 | EXPORT_SYMBOL_GPL(intel_scu_devices_create); | ||
810 | |||
811 | /* Called by IPC driver */ | ||
812 | void intel_scu_devices_destroy(void) | ||
813 | { | ||
814 | int i; | ||
815 | |||
816 | intel_scu_notifier_post(SCU_DOWN, NULL); | ||
817 | |||
818 | for (i = 0; i < ipc_next_dev; i++) | ||
819 | platform_device_del(ipc_devs[i]); | ||
820 | } | ||
821 | EXPORT_SYMBOL_GPL(intel_scu_devices_destroy); | ||
822 | |||
823 | static void __init install_irq_resource(struct platform_device *pdev, int irq) | ||
824 | { | ||
825 | /* Single threaded */ | ||
826 | static struct resource __initdata res = { | ||
827 | .name = "IRQ", | ||
828 | .flags = IORESOURCE_IRQ, | ||
829 | }; | ||
830 | res.start = irq; | ||
831 | platform_device_add_resources(pdev, &res, 1); | ||
832 | } | ||
833 | |||
834 | static void __init sfi_handle_ipc_dev(struct sfi_device_table_entry *entry) | ||
835 | { | ||
836 | const struct devs_id *dev = device_ids; | ||
837 | struct platform_device *pdev; | ||
838 | void *pdata = NULL; | ||
839 | |||
840 | while (dev->name[0]) { | ||
841 | if (dev->type == SFI_DEV_TYPE_IPC && | ||
842 | !strncmp(dev->name, entry->name, SFI_NAME_LEN)) { | ||
843 | pdata = dev->get_platform_data(entry); | ||
844 | break; | ||
845 | } | ||
846 | dev++; | ||
847 | } | ||
848 | |||
849 | /* | ||
850 | * On Medfield the platform device creation is handled by the MSIC | ||
851 | * MFD driver so we don't need to do it here. | ||
852 | */ | ||
853 | if (mrst_has_msic()) | ||
854 | return; | ||
855 | |||
856 | pdev = platform_device_alloc(entry->name, 0); | ||
857 | if (pdev == NULL) { | ||
858 | pr_err("out of memory for SFI platform device '%s'.\n", | ||
859 | entry->name); | ||
860 | return; | ||
861 | } | ||
862 | install_irq_resource(pdev, entry->irq); | ||
863 | |||
864 | pdev->dev.platform_data = pdata; | ||
865 | intel_scu_device_register(pdev); | ||
866 | } | ||
867 | |||
868 | static void __init sfi_handle_spi_dev(struct spi_board_info *spi_info) | ||
869 | { | ||
870 | const struct devs_id *dev = device_ids; | ||
871 | void *pdata = NULL; | ||
872 | |||
873 | while (dev->name[0]) { | ||
874 | if (dev->type == SFI_DEV_TYPE_SPI && | ||
875 | !strncmp(dev->name, spi_info->modalias, SFI_NAME_LEN)) { | ||
876 | pdata = dev->get_platform_data(spi_info); | ||
877 | break; | ||
878 | } | ||
879 | dev++; | ||
880 | } | ||
881 | spi_info->platform_data = pdata; | ||
882 | if (dev->delay) | ||
883 | intel_scu_spi_device_register(spi_info); | ||
884 | else | ||
885 | spi_register_board_info(spi_info, 1); | ||
886 | } | ||
887 | |||
888 | static void __init sfi_handle_i2c_dev(int bus, struct i2c_board_info *i2c_info) | ||
889 | { | ||
890 | const struct devs_id *dev = device_ids; | ||
891 | void *pdata = NULL; | ||
892 | |||
893 | while (dev->name[0]) { | ||
894 | if (dev->type == SFI_DEV_TYPE_I2C && | ||
895 | !strncmp(dev->name, i2c_info->type, SFI_NAME_LEN)) { | ||
896 | pdata = dev->get_platform_data(i2c_info); | ||
897 | break; | ||
898 | } | ||
899 | dev++; | ||
900 | } | ||
901 | i2c_info->platform_data = pdata; | ||
902 | |||
903 | if (dev->delay) | ||
904 | intel_scu_i2c_device_register(bus, i2c_info); | ||
905 | else | ||
906 | i2c_register_board_info(bus, i2c_info, 1); | ||
907 | } | ||
908 | |||
909 | |||
910 | static int __init sfi_parse_devs(struct sfi_table_header *table) | ||
911 | { | ||
912 | struct sfi_table_simple *sb; | ||
913 | struct sfi_device_table_entry *pentry; | ||
914 | struct spi_board_info spi_info; | ||
915 | struct i2c_board_info i2c_info; | ||
916 | int num, i, bus; | ||
917 | int ioapic; | ||
918 | struct io_apic_irq_attr irq_attr; | ||
919 | |||
920 | sb = (struct sfi_table_simple *)table; | ||
921 | num = SFI_GET_NUM_ENTRIES(sb, struct sfi_device_table_entry); | ||
922 | pentry = (struct sfi_device_table_entry *)sb->pentry; | ||
923 | |||
924 | for (i = 0; i < num; i++, pentry++) { | ||
925 | int irq = pentry->irq; | ||
926 | |||
927 | if (irq != (u8)0xff) { /* native RTE case */ | ||
928 | /* these SPI2 devices are not exposed to system as PCI | ||
929 | * devices, but they have separate RTE entry in IOAPIC | ||
930 | * so we have to enable them one by one here | ||
931 | */ | ||
932 | ioapic = mp_find_ioapic(irq); | ||
933 | irq_attr.ioapic = ioapic; | ||
934 | irq_attr.ioapic_pin = irq; | ||
935 | irq_attr.trigger = 1; | ||
936 | irq_attr.polarity = 1; | ||
937 | io_apic_set_pci_routing(NULL, irq, &irq_attr); | ||
938 | } else | ||
939 | irq = 0; /* No irq */ | ||
940 | |||
941 | switch (pentry->type) { | ||
942 | case SFI_DEV_TYPE_IPC: | ||
943 | pr_debug("info[%2d]: IPC bus, name = %16.16s, " | ||
944 | "irq = 0x%2x\n", i, pentry->name, pentry->irq); | ||
945 | sfi_handle_ipc_dev(pentry); | ||
946 | break; | ||
947 | case SFI_DEV_TYPE_SPI: | ||
948 | memset(&spi_info, 0, sizeof(spi_info)); | ||
949 | strncpy(spi_info.modalias, pentry->name, SFI_NAME_LEN); | ||
950 | spi_info.irq = irq; | ||
951 | spi_info.bus_num = pentry->host_num; | ||
952 | spi_info.chip_select = pentry->addr; | ||
953 | spi_info.max_speed_hz = pentry->max_freq; | ||
954 | pr_debug("info[%2d]: SPI bus = %d, name = %16.16s, " | ||
955 | "irq = 0x%2x, max_freq = %d, cs = %d\n", i, | ||
956 | spi_info.bus_num, | ||
957 | spi_info.modalias, | ||
958 | spi_info.irq, | ||
959 | spi_info.max_speed_hz, | ||
960 | spi_info.chip_select); | ||
961 | sfi_handle_spi_dev(&spi_info); | ||
962 | break; | ||
963 | case SFI_DEV_TYPE_I2C: | ||
964 | memset(&i2c_info, 0, sizeof(i2c_info)); | ||
965 | bus = pentry->host_num; | ||
966 | strncpy(i2c_info.type, pentry->name, SFI_NAME_LEN); | ||
967 | i2c_info.irq = irq; | ||
968 | i2c_info.addr = pentry->addr; | ||
969 | pr_debug("info[%2d]: I2C bus = %d, name = %16.16s, " | ||
970 | "irq = 0x%2x, addr = 0x%x\n", i, bus, | ||
971 | i2c_info.type, | ||
972 | i2c_info.irq, | ||
973 | i2c_info.addr); | ||
974 | sfi_handle_i2c_dev(bus, &i2c_info); | ||
975 | break; | ||
976 | case SFI_DEV_TYPE_UART: | ||
977 | case SFI_DEV_TYPE_HSI: | ||
978 | default: | ||
979 | ; | ||
980 | } | ||
981 | } | ||
982 | return 0; | ||
983 | } | ||
984 | |||
985 | static int __init mrst_platform_init(void) | ||
986 | { | ||
987 | sfi_table_parse(SFI_SIG_GPIO, NULL, NULL, sfi_parse_gpio); | ||
988 | sfi_table_parse(SFI_SIG_DEVS, NULL, NULL, sfi_parse_devs); | ||
989 | return 0; | ||
990 | } | ||
991 | arch_initcall(mrst_platform_init); | ||
992 | |||
993 | /* | ||
994 | * we will search these buttons in SFI GPIO table (by name) | ||
995 | * and register them dynamically. Please add all possible | ||
996 | * buttons here, we will shrink them if no GPIO found. | ||
997 | */ | ||
998 | static struct gpio_keys_button gpio_button[] = { | ||
999 | {KEY_POWER, -1, 1, "power_btn", EV_KEY, 0, 3000}, | ||
1000 | {KEY_PROG1, -1, 1, "prog_btn1", EV_KEY, 0, 20}, | ||
1001 | {KEY_PROG2, -1, 1, "prog_btn2", EV_KEY, 0, 20}, | ||
1002 | {SW_LID, -1, 1, "lid_switch", EV_SW, 0, 20}, | ||
1003 | {KEY_VOLUMEUP, -1, 1, "vol_up", EV_KEY, 0, 20}, | ||
1004 | {KEY_VOLUMEDOWN, -1, 1, "vol_down", EV_KEY, 0, 20}, | ||
1005 | {KEY_CAMERA, -1, 1, "camera_full", EV_KEY, 0, 20}, | ||
1006 | {KEY_CAMERA_FOCUS, -1, 1, "camera_half", EV_KEY, 0, 20}, | ||
1007 | {SW_KEYPAD_SLIDE, -1, 1, "MagSw1", EV_SW, 0, 20}, | ||
1008 | {SW_KEYPAD_SLIDE, -1, 1, "MagSw2", EV_SW, 0, 20}, | ||
1009 | }; | ||
1010 | |||
1011 | static struct gpio_keys_platform_data mrst_gpio_keys = { | ||
1012 | .buttons = gpio_button, | ||
1013 | .rep = 1, | ||
1014 | .nbuttons = -1, /* will fill it after search */ | ||
1015 | }; | ||
1016 | |||
1017 | static struct platform_device pb_device = { | ||
1018 | .name = "gpio-keys", | ||
1019 | .id = -1, | ||
1020 | .dev = { | ||
1021 | .platform_data = &mrst_gpio_keys, | ||
1022 | }, | ||
1023 | }; | ||
1024 | |||
1025 | /* | ||
1026 | * Shrink the non-existent buttons, register the gpio button | ||
1027 | * device if there is some | ||
1028 | */ | ||
1029 | static int __init pb_keys_init(void) | ||
1030 | { | ||
1031 | struct gpio_keys_button *gb = gpio_button; | ||
1032 | int i, num, good = 0; | ||
1033 | |||
1034 | num = sizeof(gpio_button) / sizeof(struct gpio_keys_button); | ||
1035 | for (i = 0; i < num; i++) { | ||
1036 | gb[i].gpio = get_gpio_by_name(gb[i].desc); | ||
1037 | pr_debug("info[%2d]: name = %s, gpio = %d\n", i, gb[i].desc, gb[i].gpio); | ||
1038 | if (gb[i].gpio == -1) | ||
1039 | continue; | ||
1040 | |||
1041 | if (i != good) | ||
1042 | gb[good] = gb[i]; | ||
1043 | good++; | ||
1044 | } | ||
1045 | |||
1046 | if (good) { | ||
1047 | mrst_gpio_keys.nbuttons = good; | ||
1048 | return platform_device_register(&pb_device); | ||
1049 | } | ||
1050 | return 0; | ||
1051 | } | ||
1052 | late_initcall(pb_keys_init); | ||
diff --git a/arch/x86/platform/olpc/olpc-xo15-sci.c b/arch/x86/platform/olpc/olpc-xo15-sci.c index fef7d0ba7e3a..649a12befba9 100644 --- a/arch/x86/platform/olpc/olpc-xo15-sci.c +++ b/arch/x86/platform/olpc/olpc-xo15-sci.c | |||
@@ -40,16 +40,9 @@ static bool lid_wake_on_close; | |||
40 | */ | 40 | */ |
41 | static int set_lid_wake_behavior(bool wake_on_close) | 41 | static int set_lid_wake_behavior(bool wake_on_close) |
42 | { | 42 | { |
43 | struct acpi_object_list arg_list; | ||
44 | union acpi_object arg; | ||
45 | acpi_status status; | 43 | acpi_status status; |
46 | 44 | ||
47 | arg_list.count = 1; | 45 | status = acpi_execute_simple_method(NULL, "\\_SB.PCI0.LID.LIDW", wake_on_close); |
48 | arg_list.pointer = &arg; | ||
49 | arg.type = ACPI_TYPE_INTEGER; | ||
50 | arg.integer.value = wake_on_close; | ||
51 | |||
52 | status = acpi_evaluate_object(NULL, "\\_SB.PCI0.LID.LIDW", &arg_list, NULL); | ||
53 | if (ACPI_FAILURE(status)) { | 46 | if (ACPI_FAILURE(status)) { |
54 | pr_warning(PFX "failed to set lid behavior\n"); | 47 | pr_warning(PFX "failed to set lid behavior\n"); |
55 | return 1; | 48 | return 1; |
diff --git a/arch/x86/platform/uv/Makefile b/arch/x86/platform/uv/Makefile index 6c40995fefb8..52079bebd014 100644 --- a/arch/x86/platform/uv/Makefile +++ b/arch/x86/platform/uv/Makefile | |||
@@ -1 +1 @@ | |||
obj-$(CONFIG_X86_UV) += tlb_uv.o bios_uv.o uv_irq.o uv_sysfs.o uv_time.o | obj-$(CONFIG_X86_UV) += tlb_uv.o bios_uv.o uv_irq.o uv_sysfs.o uv_time.o uv_nmi.o | ||
diff --git a/arch/x86/platform/uv/uv_nmi.c b/arch/x86/platform/uv/uv_nmi.c new file mode 100644 index 000000000000..8eeccba73130 --- /dev/null +++ b/arch/x86/platform/uv/uv_nmi.c | |||
@@ -0,0 +1,700 @@ | |||
1 | /* | ||
2 | * SGI NMI support routines | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | * | ||
18 | * Copyright (c) 2009-2013 Silicon Graphics, Inc. All Rights Reserved. | ||
19 | * Copyright (c) Mike Travis | ||
20 | */ | ||
21 | |||
22 | #include <linux/cpu.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/kdb.h> | ||
25 | #include <linux/kexec.h> | ||
26 | #include <linux/kgdb.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/nmi.h> | ||
29 | #include <linux/sched.h> | ||
30 | #include <linux/slab.h> | ||
31 | |||
32 | #include <asm/apic.h> | ||
33 | #include <asm/current.h> | ||
34 | #include <asm/kdebug.h> | ||
35 | #include <asm/local64.h> | ||
36 | #include <asm/nmi.h> | ||
37 | #include <asm/traps.h> | ||
38 | #include <asm/uv/uv.h> | ||
39 | #include <asm/uv/uv_hub.h> | ||
40 | #include <asm/uv/uv_mmrs.h> | ||
41 | |||
42 | /* | ||
43 | * UV handler for NMI | ||
44 | * | ||
45 | * Handle system-wide NMI events generated by the global 'power nmi' command. | ||
46 | * | ||
47 | * Basic operation is to field the NMI interrupt on each cpu and wait | ||
48 | * until all cpus have arrived into the nmi handler. If some cpus do not | ||
49 | * make it into the handler, try and force them in with the IPI(NMI) signal. | ||
50 | * | ||
51 | * We also have to lessen UV Hub MMR accesses as much as possible as this | ||
52 | * disrupts the UV Hub's primary mission of directing NumaLink traffic and | ||
53 | * can cause system problems to occur. | ||
54 | * | ||
55 | * To do this we register our primary NMI notifier on the NMI_UNKNOWN | ||
56 | * chain. This reduces the number of false NMI calls when the perf | ||
57 | * tools are running which generate an enormous number of NMIs per | ||
58 | * second (~4M/s for 1024 cpu threads). Our secondary NMI handler is | ||
59 | * very short as it only checks that if it has been "pinged" with the | ||
60 | * IPI(NMI) signal as mentioned above, and does not read the UV Hub's MMR. | ||
61 | * | ||
62 | */ | ||
63 | |||
64 | static struct uv_hub_nmi_s **uv_hub_nmi_list; | ||
65 | |||
66 | DEFINE_PER_CPU(struct uv_cpu_nmi_s, __uv_cpu_nmi); | ||
67 | EXPORT_PER_CPU_SYMBOL_GPL(__uv_cpu_nmi); | ||
68 | |||
69 | static unsigned long nmi_mmr; | ||
70 | static unsigned long nmi_mmr_clear; | ||
71 | static unsigned long nmi_mmr_pending; | ||
72 | |||
73 | static atomic_t uv_in_nmi; | ||
74 | static atomic_t uv_nmi_cpu = ATOMIC_INIT(-1); | ||
75 | static atomic_t uv_nmi_cpus_in_nmi = ATOMIC_INIT(-1); | ||
76 | static atomic_t uv_nmi_slave_continue; | ||
77 | static atomic_t uv_nmi_kexec_failed; | ||
78 | static cpumask_var_t uv_nmi_cpu_mask; | ||
79 | |||
80 | /* Values for uv_nmi_slave_continue */ | ||
81 | #define SLAVE_CLEAR 0 | ||
82 | #define SLAVE_CONTINUE 1 | ||
83 | #define SLAVE_EXIT 2 | ||
84 | |||
85 | /* | ||
86 | * Default is all stack dumps go to the console and buffer. | ||
87 | * Lower level to send to log buffer only. | ||
88 | */ | ||
89 | static int uv_nmi_loglevel = 7; | ||
90 | module_param_named(dump_loglevel, uv_nmi_loglevel, int, 0644); | ||
91 | |||
92 | /* | ||
93 | * The following values show statistics on how perf events are affecting | ||
94 | * this system. | ||
95 | */ | ||
96 | static int param_get_local64(char *buffer, const struct kernel_param *kp) | ||
97 | { | ||
98 | return sprintf(buffer, "%lu\n", local64_read((local64_t *)kp->arg)); | ||
99 | } | ||
100 | |||
101 | static int param_set_local64(const char *val, const struct kernel_param *kp) | ||
102 | { | ||
103 | /* clear on any write */ | ||
104 | local64_set((local64_t *)kp->arg, 0); | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static struct kernel_param_ops param_ops_local64 = { | ||
109 | .get = param_get_local64, | ||
110 | .set = param_set_local64, | ||
111 | }; | ||
112 | #define param_check_local64(name, p) __param_check(name, p, local64_t) | ||
113 | |||
114 | static local64_t uv_nmi_count; | ||
115 | module_param_named(nmi_count, uv_nmi_count, local64, 0644); | ||
116 | |||
117 | static local64_t uv_nmi_misses; | ||
118 | module_param_named(nmi_misses, uv_nmi_misses, local64, 0644); | ||
119 | |||
120 | static local64_t uv_nmi_ping_count; | ||
121 | module_param_named(ping_count, uv_nmi_ping_count, local64, 0644); | ||
122 | |||
123 | static local64_t uv_nmi_ping_misses; | ||
124 | module_param_named(ping_misses, uv_nmi_ping_misses, local64, 0644); | ||
125 | |||
126 | /* | ||
127 | * Following values allow tuning for large systems under heavy loading | ||
128 | */ | ||
129 | static int uv_nmi_initial_delay = 100; | ||
130 | module_param_named(initial_delay, uv_nmi_initial_delay, int, 0644); | ||
131 | |||
132 | static int uv_nmi_slave_delay = 100; | ||
133 | module_param_named(slave_delay, uv_nmi_slave_delay, int, 0644); | ||
134 | |||
135 | static int uv_nmi_loop_delay = 100; | ||
136 | module_param_named(loop_delay, uv_nmi_loop_delay, int, 0644); | ||
137 | |||
138 | static int uv_nmi_trigger_delay = 10000; | ||
139 | module_param_named(trigger_delay, uv_nmi_trigger_delay, int, 0644); | ||
140 | |||
141 | static int uv_nmi_wait_count = 100; | ||
142 | module_param_named(wait_count, uv_nmi_wait_count, int, 0644); | ||
143 | |||
144 | static int uv_nmi_retry_count = 500; | ||
145 | module_param_named(retry_count, uv_nmi_retry_count, int, 0644); | ||
146 | |||
147 | /* | ||
148 | * Valid NMI Actions: | ||
149 | * "dump" - dump process stack for each cpu | ||
150 | * "ips" - dump IP info for each cpu | ||
151 | * "kdump" - do crash dump | ||
152 | * "kdb" - enter KDB/KGDB (default) | ||
153 | */ | ||
154 | static char uv_nmi_action[8] = "kdb"; | ||
155 | module_param_string(action, uv_nmi_action, sizeof(uv_nmi_action), 0644); | ||
156 | |||
157 | static inline bool uv_nmi_action_is(const char *action) | ||
158 | { | ||
159 | return (strncmp(uv_nmi_action, action, strlen(action)) == 0); | ||
160 | } | ||
161 | |||
162 | /* Setup which NMI support is present in system */ | ||
163 | static void uv_nmi_setup_mmrs(void) | ||
164 | { | ||
165 | if (uv_read_local_mmr(UVH_NMI_MMRX_SUPPORTED)) { | ||
166 | uv_write_local_mmr(UVH_NMI_MMRX_REQ, | ||
167 | 1UL << UVH_NMI_MMRX_REQ_SHIFT); | ||
168 | nmi_mmr = UVH_NMI_MMRX; | ||
169 | nmi_mmr_clear = UVH_NMI_MMRX_CLEAR; | ||
170 | nmi_mmr_pending = 1UL << UVH_NMI_MMRX_SHIFT; | ||
171 | pr_info("UV: SMI NMI support: %s\n", UVH_NMI_MMRX_TYPE); | ||
172 | } else { | ||
173 | nmi_mmr = UVH_NMI_MMR; | ||
174 | nmi_mmr_clear = UVH_NMI_MMR_CLEAR; | ||
175 | nmi_mmr_pending = 1UL << UVH_NMI_MMR_SHIFT; | ||
176 | pr_info("UV: SMI NMI support: %s\n", UVH_NMI_MMR_TYPE); | ||
177 | } | ||
178 | } | ||
179 | |||
180 | /* Read NMI MMR and check if NMI flag was set by BMC. */ | ||
181 | static inline int uv_nmi_test_mmr(struct uv_hub_nmi_s *hub_nmi) | ||
182 | { | ||
183 | hub_nmi->nmi_value = uv_read_local_mmr(nmi_mmr); | ||
184 | atomic_inc(&hub_nmi->read_mmr_count); | ||
185 | return !!(hub_nmi->nmi_value & nmi_mmr_pending); | ||
186 | } | ||
187 | |||
188 | static inline void uv_local_mmr_clear_nmi(void) | ||
189 | { | ||
190 | uv_write_local_mmr(nmi_mmr_clear, nmi_mmr_pending); | ||
191 | } | ||
192 | |||
193 | /* | ||
194 | * If first cpu in on this hub, set hub_nmi "in_nmi" and "owner" values and | ||
195 | * return true. If first cpu in on the system, set global "in_nmi" flag. | ||
196 | */ | ||
197 | static int uv_set_in_nmi(int cpu, struct uv_hub_nmi_s *hub_nmi) | ||
198 | { | ||
199 | int first = atomic_add_unless(&hub_nmi->in_nmi, 1, 1); | ||
200 | |||
201 | if (first) { | ||
202 | atomic_set(&hub_nmi->cpu_owner, cpu); | ||
203 | if (atomic_add_unless(&uv_in_nmi, 1, 1)) | ||
204 | atomic_set(&uv_nmi_cpu, cpu); | ||
205 | |||
206 | atomic_inc(&hub_nmi->nmi_count); | ||
207 | } | ||
208 | return first; | ||
209 | } | ||
210 | |||
211 | /* Check if this is a system NMI event */ | ||
212 | static int uv_check_nmi(struct uv_hub_nmi_s *hub_nmi) | ||
213 | { | ||
214 | int cpu = smp_processor_id(); | ||
215 | int nmi = 0; | ||
216 | |||
217 | local64_inc(&uv_nmi_count); | ||
218 | uv_cpu_nmi.queries++; | ||
219 | |||
220 | do { | ||
221 | nmi = atomic_read(&hub_nmi->in_nmi); | ||
222 | if (nmi) | ||
223 | break; | ||
224 | |||
225 | if (raw_spin_trylock(&hub_nmi->nmi_lock)) { | ||
226 | |||
227 | /* check hub MMR NMI flag */ | ||
228 | if (uv_nmi_test_mmr(hub_nmi)) { | ||
229 | uv_set_in_nmi(cpu, hub_nmi); | ||
230 | nmi = 1; | ||
231 | break; | ||
232 | } | ||
233 | |||
234 | /* MMR NMI flag is clear */ | ||
235 | raw_spin_unlock(&hub_nmi->nmi_lock); | ||
236 | |||
237 | } else { | ||
238 | /* wait a moment for the hub nmi locker to set flag */ | ||
239 | cpu_relax(); | ||
240 | udelay(uv_nmi_slave_delay); | ||
241 | |||
242 | /* re-check hub in_nmi flag */ | ||
243 | nmi = atomic_read(&hub_nmi->in_nmi); | ||
244 | if (nmi) | ||
245 | break; | ||
246 | } | ||
247 | |||
248 | /* check if this BMC missed setting the MMR NMI flag */ | ||
249 | if (!nmi) { | ||
250 | nmi = atomic_read(&uv_in_nmi); | ||
251 | if (nmi) | ||
252 | uv_set_in_nmi(cpu, hub_nmi); | ||
253 | } | ||
254 | |||
255 | } while (0); | ||
256 | |||
257 | if (!nmi) | ||
258 | local64_inc(&uv_nmi_misses); | ||
259 | |||
260 | return nmi; | ||
261 | } | ||
262 | |||
263 | /* Need to reset the NMI MMR register, but only once per hub. */ | ||
264 | static inline void uv_clear_nmi(int cpu) | ||
265 | { | ||
266 | struct uv_hub_nmi_s *hub_nmi = uv_hub_nmi; | ||
267 | |||
268 | if (cpu == atomic_read(&hub_nmi->cpu_owner)) { | ||
269 | atomic_set(&hub_nmi->cpu_owner, -1); | ||
270 | atomic_set(&hub_nmi->in_nmi, 0); | ||
271 | uv_local_mmr_clear_nmi(); | ||
272 | raw_spin_unlock(&hub_nmi->nmi_lock); | ||
273 | } | ||
274 | } | ||
275 | |||
276 | /* Print non-responding cpus */ | ||
277 | static void uv_nmi_nr_cpus_pr(char *fmt) | ||
278 | { | ||
279 | static char cpu_list[1024]; | ||
280 | int len = sizeof(cpu_list); | ||
281 | int c = cpumask_weight(uv_nmi_cpu_mask); | ||
282 | int n = cpulist_scnprintf(cpu_list, len, uv_nmi_cpu_mask); | ||
283 | |||
284 | if (n >= len-1) | ||
285 | strcpy(&cpu_list[len - 6], "...\n"); | ||
286 | |||
287 | printk(fmt, c, cpu_list); | ||
288 | } | ||
289 | |||
290 | /* Ping non-responding cpus attemping to force them into the NMI handler */ | ||
291 | static void uv_nmi_nr_cpus_ping(void) | ||
292 | { | ||
293 | int cpu; | ||
294 | |||
295 | for_each_cpu(cpu, uv_nmi_cpu_mask) | ||
296 | atomic_set(&uv_cpu_nmi_per(cpu).pinging, 1); | ||
297 | |||
298 | apic->send_IPI_mask(uv_nmi_cpu_mask, APIC_DM_NMI); | ||
299 | } | ||
300 | |||
301 | /* Clean up flags for cpus that ignored both NMI and ping */ | ||
302 | static void uv_nmi_cleanup_mask(void) | ||
303 | { | ||
304 | int cpu; | ||
305 | |||
306 | for_each_cpu(cpu, uv_nmi_cpu_mask) { | ||
307 | atomic_set(&uv_cpu_nmi_per(cpu).pinging, 0); | ||
308 | atomic_set(&uv_cpu_nmi_per(cpu).state, UV_NMI_STATE_OUT); | ||
309 | cpumask_clear_cpu(cpu, uv_nmi_cpu_mask); | ||
310 | } | ||
311 | } | ||
312 | |||
313 | /* Loop waiting as cpus enter nmi handler */ | ||
314 | static int uv_nmi_wait_cpus(int first) | ||
315 | { | ||
316 | int i, j, k, n = num_online_cpus(); | ||
317 | int last_k = 0, waiting = 0; | ||
318 | |||
319 | if (first) { | ||
320 | cpumask_copy(uv_nmi_cpu_mask, cpu_online_mask); | ||
321 | k = 0; | ||
322 | } else { | ||
323 | k = n - cpumask_weight(uv_nmi_cpu_mask); | ||
324 | } | ||
325 | |||
326 | udelay(uv_nmi_initial_delay); | ||
327 | for (i = 0; i < uv_nmi_retry_count; i++) { | ||
328 | int loop_delay = uv_nmi_loop_delay; | ||
329 | |||
330 | for_each_cpu(j, uv_nmi_cpu_mask) { | ||
331 | if (atomic_read(&uv_cpu_nmi_per(j).state)) { | ||
332 | cpumask_clear_cpu(j, uv_nmi_cpu_mask); | ||
333 | if (++k >= n) | ||
334 | break; | ||
335 | } | ||
336 | } | ||
337 | if (k >= n) { /* all in? */ | ||
338 | k = n; | ||
339 | break; | ||
340 | } | ||
341 | if (last_k != k) { /* abort if no new cpus coming in */ | ||
342 | last_k = k; | ||
343 | waiting = 0; | ||
344 | } else if (++waiting > uv_nmi_wait_count) | ||
345 | break; | ||
346 | |||
347 | /* extend delay if waiting only for cpu 0 */ | ||
348 | if (waiting && (n - k) == 1 && | ||
349 | cpumask_test_cpu(0, uv_nmi_cpu_mask)) | ||
350 | loop_delay *= 100; | ||
351 | |||
352 | udelay(loop_delay); | ||
353 | } | ||
354 | atomic_set(&uv_nmi_cpus_in_nmi, k); | ||
355 | return n - k; | ||
356 | } | ||
357 | |||
358 | /* Wait until all slave cpus have entered UV NMI handler */ | ||
359 | static void uv_nmi_wait(int master) | ||
360 | { | ||
361 | /* indicate this cpu is in */ | ||
362 | atomic_set(&uv_cpu_nmi.state, UV_NMI_STATE_IN); | ||
363 | |||
364 | /* if not the first cpu in (the master), then we are a slave cpu */ | ||
365 | if (!master) | ||
366 | return; | ||
367 | |||
368 | do { | ||
369 | /* wait for all other cpus to gather here */ | ||
370 | if (!uv_nmi_wait_cpus(1)) | ||
371 | break; | ||
372 | |||
373 | /* if not all made it in, send IPI NMI to them */ | ||
374 | uv_nmi_nr_cpus_pr(KERN_ALERT | ||
375 | "UV: Sending NMI IPI to %d non-responding CPUs: %s\n"); | ||
376 | uv_nmi_nr_cpus_ping(); | ||
377 | |||
378 | /* if all cpus are in, then done */ | ||
379 | if (!uv_nmi_wait_cpus(0)) | ||
380 | break; | ||
381 | |||
382 | uv_nmi_nr_cpus_pr(KERN_ALERT | ||
383 | "UV: %d CPUs not in NMI loop: %s\n"); | ||
384 | } while (0); | ||
385 | |||
386 | pr_alert("UV: %d of %d CPUs in NMI\n", | ||
387 | atomic_read(&uv_nmi_cpus_in_nmi), num_online_cpus()); | ||
388 | } | ||
389 | |||
390 | static void uv_nmi_dump_cpu_ip_hdr(void) | ||
391 | { | ||
392 | printk(KERN_DEFAULT | ||
393 | "\nUV: %4s %6s %-32s %s (Note: PID 0 not listed)\n", | ||
394 | "CPU", "PID", "COMMAND", "IP"); | ||
395 | } | ||
396 | |||
397 | static void uv_nmi_dump_cpu_ip(int cpu, struct pt_regs *regs) | ||
398 | { | ||
399 | printk(KERN_DEFAULT "UV: %4d %6d %-32.32s ", | ||
400 | cpu, current->pid, current->comm); | ||
401 | |||
402 | printk_address(regs->ip); | ||
403 | } | ||
404 | |||
405 | /* Dump this cpu's state */ | ||
406 | static void uv_nmi_dump_state_cpu(int cpu, struct pt_regs *regs) | ||
407 | { | ||
408 | const char *dots = " ................................. "; | ||
409 | |||
410 | if (uv_nmi_action_is("ips")) { | ||
411 | if (cpu == 0) | ||
412 | uv_nmi_dump_cpu_ip_hdr(); | ||
413 | |||
414 | if (current->pid != 0) | ||
415 | uv_nmi_dump_cpu_ip(cpu, regs); | ||
416 | |||
417 | } else if (uv_nmi_action_is("dump")) { | ||
418 | printk(KERN_DEFAULT | ||
419 | "UV:%sNMI process trace for CPU %d\n", dots, cpu); | ||
420 | show_regs(regs); | ||
421 | } | ||
422 | atomic_set(&uv_cpu_nmi.state, UV_NMI_STATE_DUMP_DONE); | ||
423 | } | ||
424 | |||
425 | /* Trigger a slave cpu to dump it's state */ | ||
426 | static void uv_nmi_trigger_dump(int cpu) | ||
427 | { | ||
428 | int retry = uv_nmi_trigger_delay; | ||
429 | |||
430 | if (atomic_read(&uv_cpu_nmi_per(cpu).state) != UV_NMI_STATE_IN) | ||
431 | return; | ||
432 | |||
433 | atomic_set(&uv_cpu_nmi_per(cpu).state, UV_NMI_STATE_DUMP); | ||
434 | do { | ||
435 | cpu_relax(); | ||
436 | udelay(10); | ||
437 | if (atomic_read(&uv_cpu_nmi_per(cpu).state) | ||
438 | != UV_NMI_STATE_DUMP) | ||
439 | return; | ||
440 | } while (--retry > 0); | ||
441 | |||
442 | pr_crit("UV: CPU %d stuck in process dump function\n", cpu); | ||
443 | atomic_set(&uv_cpu_nmi_per(cpu).state, UV_NMI_STATE_DUMP_DONE); | ||
444 | } | ||
445 | |||
446 | /* Wait until all cpus ready to exit */ | ||
447 | static void uv_nmi_sync_exit(int master) | ||
448 | { | ||
449 | atomic_dec(&uv_nmi_cpus_in_nmi); | ||
450 | if (master) { | ||
451 | while (atomic_read(&uv_nmi_cpus_in_nmi) > 0) | ||
452 | cpu_relax(); | ||
453 | atomic_set(&uv_nmi_slave_continue, SLAVE_CLEAR); | ||
454 | } else { | ||
455 | while (atomic_read(&uv_nmi_slave_continue)) | ||
456 | cpu_relax(); | ||
457 | } | ||
458 | } | ||
459 | |||
460 | /* Walk through cpu list and dump state of each */ | ||
461 | static void uv_nmi_dump_state(int cpu, struct pt_regs *regs, int master) | ||
462 | { | ||
463 | if (master) { | ||
464 | int tcpu; | ||
465 | int ignored = 0; | ||
466 | int saved_console_loglevel = console_loglevel; | ||
467 | |||
468 | pr_alert("UV: tracing %s for %d CPUs from CPU %d\n", | ||
469 | uv_nmi_action_is("ips") ? "IPs" : "processes", | ||
470 | atomic_read(&uv_nmi_cpus_in_nmi), cpu); | ||
471 | |||
472 | console_loglevel = uv_nmi_loglevel; | ||
473 | atomic_set(&uv_nmi_slave_continue, SLAVE_EXIT); | ||
474 | for_each_online_cpu(tcpu) { | ||
475 | if (cpumask_test_cpu(tcpu, uv_nmi_cpu_mask)) | ||
476 | ignored++; | ||
477 | else if (tcpu == cpu) | ||
478 | uv_nmi_dump_state_cpu(tcpu, regs); | ||
479 | else | ||
480 | uv_nmi_trigger_dump(tcpu); | ||
481 | } | ||
482 | if (ignored) | ||
483 | printk(KERN_DEFAULT "UV: %d CPUs ignored NMI\n", | ||
484 | ignored); | ||
485 | |||
486 | console_loglevel = saved_console_loglevel; | ||
487 | pr_alert("UV: process trace complete\n"); | ||
488 | } else { | ||
489 | while (!atomic_read(&uv_nmi_slave_continue)) | ||
490 | cpu_relax(); | ||
491 | while (atomic_read(&uv_cpu_nmi.state) != UV_NMI_STATE_DUMP) | ||
492 | cpu_relax(); | ||
493 | uv_nmi_dump_state_cpu(cpu, regs); | ||
494 | } | ||
495 | uv_nmi_sync_exit(master); | ||
496 | } | ||
497 | |||
498 | static void uv_nmi_touch_watchdogs(void) | ||
499 | { | ||
500 | touch_softlockup_watchdog_sync(); | ||
501 | clocksource_touch_watchdog(); | ||
502 | rcu_cpu_stall_reset(); | ||
503 | touch_nmi_watchdog(); | ||
504 | } | ||
505 | |||
506 | #if defined(CONFIG_KEXEC) | ||
507 | static void uv_nmi_kdump(int cpu, int master, struct pt_regs *regs) | ||
508 | { | ||
509 | /* Call crash to dump system state */ | ||
510 | if (master) { | ||
511 | pr_emerg("UV: NMI executing crash_kexec on CPU%d\n", cpu); | ||
512 | crash_kexec(regs); | ||
513 | |||
514 | pr_emerg("UV: crash_kexec unexpectedly returned, "); | ||
515 | if (!kexec_crash_image) { | ||
516 | pr_cont("crash kernel not loaded\n"); | ||
517 | atomic_set(&uv_nmi_kexec_failed, 1); | ||
518 | uv_nmi_sync_exit(1); | ||
519 | return; | ||
520 | } | ||
521 | pr_cont("kexec busy, stalling cpus while waiting\n"); | ||
522 | } | ||
523 | |||
524 | /* If crash exec fails the slaves should return, otherwise stall */ | ||
525 | while (atomic_read(&uv_nmi_kexec_failed) == 0) | ||
526 | mdelay(10); | ||
527 | |||
528 | /* Crash kernel most likely not loaded, return in an orderly fashion */ | ||
529 | uv_nmi_sync_exit(0); | ||
530 | } | ||
531 | |||
532 | #else /* !CONFIG_KEXEC */ | ||
533 | static inline void uv_nmi_kdump(int cpu, int master, struct pt_regs *regs) | ||
534 | { | ||
535 | if (master) | ||
536 | pr_err("UV: NMI kdump: KEXEC not supported in this kernel\n"); | ||
537 | } | ||
538 | #endif /* !CONFIG_KEXEC */ | ||
539 | |||
540 | #ifdef CONFIG_KGDB_KDB | ||
541 | /* Call KDB from NMI handler */ | ||
542 | static void uv_call_kdb(int cpu, struct pt_regs *regs, int master) | ||
543 | { | ||
544 | int ret; | ||
545 | |||
546 | if (master) { | ||
547 | /* call KGDB NMI handler as MASTER */ | ||
548 | ret = kgdb_nmicallin(cpu, X86_TRAP_NMI, regs, | ||
549 | &uv_nmi_slave_continue); | ||
550 | if (ret) { | ||
551 | pr_alert("KDB returned error, is kgdboc set?\n"); | ||
552 | atomic_set(&uv_nmi_slave_continue, SLAVE_EXIT); | ||
553 | } | ||
554 | } else { | ||
555 | /* wait for KGDB signal that it's ready for slaves to enter */ | ||
556 | int sig; | ||
557 | |||
558 | do { | ||
559 | cpu_relax(); | ||
560 | sig = atomic_read(&uv_nmi_slave_continue); | ||
561 | } while (!sig); | ||
562 | |||
563 | /* call KGDB as slave */ | ||
564 | if (sig == SLAVE_CONTINUE) | ||
565 | kgdb_nmicallback(cpu, regs); | ||
566 | } | ||
567 | uv_nmi_sync_exit(master); | ||
568 | } | ||
569 | |||
570 | #else /* !CONFIG_KGDB_KDB */ | ||
571 | static inline void uv_call_kdb(int cpu, struct pt_regs *regs, int master) | ||
572 | { | ||
573 | pr_err("UV: NMI error: KGDB/KDB is not enabled in this kernel\n"); | ||
574 | } | ||
575 | #endif /* !CONFIG_KGDB_KDB */ | ||
576 | |||
577 | /* | ||
578 | * UV NMI handler | ||
579 | */ | ||
580 | int uv_handle_nmi(unsigned int reason, struct pt_regs *regs) | ||
581 | { | ||
582 | struct uv_hub_nmi_s *hub_nmi = uv_hub_nmi; | ||
583 | int cpu = smp_processor_id(); | ||
584 | int master = 0; | ||
585 | unsigned long flags; | ||
586 | |||
587 | local_irq_save(flags); | ||
588 | |||
589 | /* If not a UV System NMI, ignore */ | ||
590 | if (!atomic_read(&uv_cpu_nmi.pinging) && !uv_check_nmi(hub_nmi)) { | ||
591 | local_irq_restore(flags); | ||
592 | return NMI_DONE; | ||
593 | } | ||
594 | |||
595 | /* Indicate we are the first CPU into the NMI handler */ | ||
596 | master = (atomic_read(&uv_nmi_cpu) == cpu); | ||
597 | |||
598 | /* If NMI action is "kdump", then attempt to do it */ | ||
599 | if (uv_nmi_action_is("kdump")) | ||
600 | uv_nmi_kdump(cpu, master, regs); | ||
601 | |||
602 | /* Pause as all cpus enter the NMI handler */ | ||
603 | uv_nmi_wait(master); | ||
604 | |||
605 | /* Dump state of each cpu */ | ||
606 | if (uv_nmi_action_is("ips") || uv_nmi_action_is("dump")) | ||
607 | uv_nmi_dump_state(cpu, regs, master); | ||
608 | |||
609 | /* Call KDB if enabled */ | ||
610 | else if (uv_nmi_action_is("kdb")) | ||
611 | uv_call_kdb(cpu, regs, master); | ||
612 | |||
613 | /* Clear per_cpu "in nmi" flag */ | ||
614 | atomic_set(&uv_cpu_nmi.state, UV_NMI_STATE_OUT); | ||
615 | |||
616 | /* Clear MMR NMI flag on each hub */ | ||
617 | uv_clear_nmi(cpu); | ||
618 | |||
619 | /* Clear global flags */ | ||
620 | if (master) { | ||
621 | if (cpumask_weight(uv_nmi_cpu_mask)) | ||
622 | uv_nmi_cleanup_mask(); | ||
623 | atomic_set(&uv_nmi_cpus_in_nmi, -1); | ||
624 | atomic_set(&uv_nmi_cpu, -1); | ||
625 | atomic_set(&uv_in_nmi, 0); | ||
626 | } | ||
627 | |||
628 | uv_nmi_touch_watchdogs(); | ||
629 | local_irq_restore(flags); | ||
630 | |||
631 | return NMI_HANDLED; | ||
632 | } | ||
633 | |||
634 | /* | ||
635 | * NMI handler for pulling in CPUs when perf events are grabbing our NMI | ||
636 | */ | ||
637 | int uv_handle_nmi_ping(unsigned int reason, struct pt_regs *regs) | ||
638 | { | ||
639 | int ret; | ||
640 | |||
641 | uv_cpu_nmi.queries++; | ||
642 | if (!atomic_read(&uv_cpu_nmi.pinging)) { | ||
643 | local64_inc(&uv_nmi_ping_misses); | ||
644 | return NMI_DONE; | ||
645 | } | ||
646 | |||
647 | uv_cpu_nmi.pings++; | ||
648 | local64_inc(&uv_nmi_ping_count); | ||
649 | ret = uv_handle_nmi(reason, regs); | ||
650 | atomic_set(&uv_cpu_nmi.pinging, 0); | ||
651 | return ret; | ||
652 | } | ||
653 | |||
654 | void uv_register_nmi_notifier(void) | ||
655 | { | ||
656 | if (register_nmi_handler(NMI_UNKNOWN, uv_handle_nmi, 0, "uv")) | ||
657 | pr_warn("UV: NMI handler failed to register\n"); | ||
658 | |||
659 | if (register_nmi_handler(NMI_LOCAL, uv_handle_nmi_ping, 0, "uvping")) | ||
660 | pr_warn("UV: PING NMI handler failed to register\n"); | ||
661 | } | ||
662 | |||
663 | void uv_nmi_init(void) | ||
664 | { | ||
665 | unsigned int value; | ||
666 | |||
667 | /* | ||
668 | * Unmask NMI on all cpus | ||
669 | */ | ||
670 | value = apic_read(APIC_LVT1) | APIC_DM_NMI; | ||
671 | value &= ~APIC_LVT_MASKED; | ||
672 | apic_write(APIC_LVT1, value); | ||
673 | } | ||
674 | |||
675 | void uv_nmi_setup(void) | ||
676 | { | ||
677 | int size = sizeof(void *) * (1 << NODES_SHIFT); | ||
678 | int cpu, nid; | ||
679 | |||
680 | /* Setup hub nmi info */ | ||
681 | uv_nmi_setup_mmrs(); | ||
682 | uv_hub_nmi_list = kzalloc(size, GFP_KERNEL); | ||
683 | pr_info("UV: NMI hub list @ 0x%p (%d)\n", uv_hub_nmi_list, size); | ||
684 | BUG_ON(!uv_hub_nmi_list); | ||
685 | size = sizeof(struct uv_hub_nmi_s); | ||
686 | for_each_present_cpu(cpu) { | ||
687 | nid = cpu_to_node(cpu); | ||
688 | if (uv_hub_nmi_list[nid] == NULL) { | ||
689 | uv_hub_nmi_list[nid] = kzalloc_node(size, | ||
690 | GFP_KERNEL, nid); | ||
691 | BUG_ON(!uv_hub_nmi_list[nid]); | ||
692 | raw_spin_lock_init(&(uv_hub_nmi_list[nid]->nmi_lock)); | ||
693 | atomic_set(&uv_hub_nmi_list[nid]->cpu_owner, -1); | ||
694 | } | ||
695 | uv_hub_nmi_per(cpu) = uv_hub_nmi_list[nid]; | ||
696 | } | ||
697 | BUG_ON(!alloc_cpumask_var(&uv_nmi_cpu_mask, GFP_KERNEL)); | ||
698 | } | ||
699 | |||
700 | |||
diff --git a/arch/x86/um/elfcore.c b/arch/x86/um/elfcore.c index 6bb49b687c97..7bb89a27a5e4 100644 --- a/arch/x86/um/elfcore.c +++ b/arch/x86/um/elfcore.c | |||
@@ -11,8 +11,7 @@ Elf32_Half elf_core_extra_phdrs(void) | |||
11 | return vsyscall_ehdr ? (((struct elfhdr *)vsyscall_ehdr)->e_phnum) : 0; | 11 | return vsyscall_ehdr ? (((struct elfhdr *)vsyscall_ehdr)->e_phnum) : 0; |
12 | } | 12 | } |
13 | 13 | ||
14 | int elf_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size, | 14 | int elf_core_write_extra_phdrs(struct coredump_params *cprm, loff_t offset) |
15 | unsigned long limit) | ||
16 | { | 15 | { |
17 | if ( vsyscall_ehdr ) { | 16 | if ( vsyscall_ehdr ) { |
18 | const struct elfhdr *const ehdrp = | 17 | const struct elfhdr *const ehdrp = |
@@ -32,17 +31,14 @@ int elf_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size, | |||
32 | phdr.p_offset += ofs; | 31 | phdr.p_offset += ofs; |
33 | } | 32 | } |
34 | phdr.p_paddr = 0; /* match other core phdrs */ | 33 | phdr.p_paddr = 0; /* match other core phdrs */ |
35 | *size += sizeof(phdr); | 34 | if (!dump_emit(cprm, &phdr, sizeof(phdr))) |
36 | if (*size > limit | ||
37 | || !dump_write(file, &phdr, sizeof(phdr))) | ||
38 | return 0; | 35 | return 0; |
39 | } | 36 | } |
40 | } | 37 | } |
41 | return 1; | 38 | return 1; |
42 | } | 39 | } |
43 | 40 | ||
44 | int elf_core_write_extra_data(struct file *file, size_t *size, | 41 | int elf_core_write_extra_data(struct coredump_params *cprm) |
45 | unsigned long limit) | ||
46 | { | 42 | { |
47 | if ( vsyscall_ehdr ) { | 43 | if ( vsyscall_ehdr ) { |
48 | const struct elfhdr *const ehdrp = | 44 | const struct elfhdr *const ehdrp = |
@@ -55,10 +51,7 @@ int elf_core_write_extra_data(struct file *file, size_t *size, | |||
55 | if (phdrp[i].p_type == PT_LOAD) { | 51 | if (phdrp[i].p_type == PT_LOAD) { |
56 | void *addr = (void *) phdrp[i].p_vaddr; | 52 | void *addr = (void *) phdrp[i].p_vaddr; |
57 | size_t filesz = phdrp[i].p_filesz; | 53 | size_t filesz = phdrp[i].p_filesz; |
58 | 54 | if (!dump_emit(cprm, addr, filesz)) | |
59 | *size += filesz; | ||
60 | if (*size > limit | ||
61 | || !dump_write(file, addr, filesz)) | ||
62 | return 0; | 55 | return 0; |
63 | } | 56 | } |
64 | } | 57 | } |
diff --git a/arch/x86/vdso/vclock_gettime.c b/arch/x86/vdso/vclock_gettime.c index 72074d528400..2ada505067cc 100644 --- a/arch/x86/vdso/vclock_gettime.c +++ b/arch/x86/vdso/vclock_gettime.c | |||
@@ -178,7 +178,7 @@ notrace static int __always_inline do_realtime(struct timespec *ts) | |||
178 | 178 | ||
179 | ts->tv_nsec = 0; | 179 | ts->tv_nsec = 0; |
180 | do { | 180 | do { |
181 | seq = read_seqcount_begin(>od->seq); | 181 | seq = read_seqcount_begin_no_lockdep(>od->seq); |
182 | mode = gtod->clock.vclock_mode; | 182 | mode = gtod->clock.vclock_mode; |
183 | ts->tv_sec = gtod->wall_time_sec; | 183 | ts->tv_sec = gtod->wall_time_sec; |
184 | ns = gtod->wall_time_snsec; | 184 | ns = gtod->wall_time_snsec; |
@@ -198,7 +198,7 @@ notrace static int do_monotonic(struct timespec *ts) | |||
198 | 198 | ||
199 | ts->tv_nsec = 0; | 199 | ts->tv_nsec = 0; |
200 | do { | 200 | do { |
201 | seq = read_seqcount_begin(>od->seq); | 201 | seq = read_seqcount_begin_no_lockdep(>od->seq); |
202 | mode = gtod->clock.vclock_mode; | 202 | mode = gtod->clock.vclock_mode; |
203 | ts->tv_sec = gtod->monotonic_time_sec; | 203 | ts->tv_sec = gtod->monotonic_time_sec; |
204 | ns = gtod->monotonic_time_snsec; | 204 | ns = gtod->monotonic_time_snsec; |
@@ -214,7 +214,7 @@ notrace static int do_realtime_coarse(struct timespec *ts) | |||
214 | { | 214 | { |
215 | unsigned long seq; | 215 | unsigned long seq; |
216 | do { | 216 | do { |
217 | seq = read_seqcount_begin(>od->seq); | 217 | seq = read_seqcount_begin_no_lockdep(>od->seq); |
218 | ts->tv_sec = gtod->wall_time_coarse.tv_sec; | 218 | ts->tv_sec = gtod->wall_time_coarse.tv_sec; |
219 | ts->tv_nsec = gtod->wall_time_coarse.tv_nsec; | 219 | ts->tv_nsec = gtod->wall_time_coarse.tv_nsec; |
220 | } while (unlikely(read_seqcount_retry(>od->seq, seq))); | 220 | } while (unlikely(read_seqcount_retry(>od->seq, seq))); |
@@ -225,7 +225,7 @@ notrace static int do_monotonic_coarse(struct timespec *ts) | |||
225 | { | 225 | { |
226 | unsigned long seq; | 226 | unsigned long seq; |
227 | do { | 227 | do { |
228 | seq = read_seqcount_begin(>od->seq); | 228 | seq = read_seqcount_begin_no_lockdep(>od->seq); |
229 | ts->tv_sec = gtod->monotonic_time_coarse.tv_sec; | 229 | ts->tv_sec = gtod->monotonic_time_coarse.tv_sec; |
230 | ts->tv_nsec = gtod->monotonic_time_coarse.tv_nsec; | 230 | ts->tv_nsec = gtod->monotonic_time_coarse.tv_nsec; |
231 | } while (unlikely(read_seqcount_retry(>od->seq, seq))); | 231 | } while (unlikely(read_seqcount_retry(>od->seq, seq))); |
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index b3f36369e667..ce563be09cc1 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c | |||
@@ -796,8 +796,8 @@ static spinlock_t *xen_pte_lock(struct page *page, struct mm_struct *mm) | |||
796 | { | 796 | { |
797 | spinlock_t *ptl = NULL; | 797 | spinlock_t *ptl = NULL; |
798 | 798 | ||
799 | #if USE_SPLIT_PTLOCKS | 799 | #if USE_SPLIT_PTE_PTLOCKS |
800 | ptl = __pte_lockptr(page); | 800 | ptl = ptlock_ptr(page); |
801 | spin_lock_nest_lock(ptl, &mm->page_table_lock); | 801 | spin_lock_nest_lock(ptl, &mm->page_table_lock); |
802 | #endif | 802 | #endif |
803 | 803 | ||
@@ -1637,7 +1637,7 @@ static inline void xen_alloc_ptpage(struct mm_struct *mm, unsigned long pfn, | |||
1637 | 1637 | ||
1638 | __set_pfn_prot(pfn, PAGE_KERNEL_RO); | 1638 | __set_pfn_prot(pfn, PAGE_KERNEL_RO); |
1639 | 1639 | ||
1640 | if (level == PT_PTE && USE_SPLIT_PTLOCKS) | 1640 | if (level == PT_PTE && USE_SPLIT_PTE_PTLOCKS) |
1641 | __pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn); | 1641 | __pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn); |
1642 | 1642 | ||
1643 | xen_mc_issue(PARAVIRT_LAZY_MMU); | 1643 | xen_mc_issue(PARAVIRT_LAZY_MMU); |
@@ -1671,7 +1671,7 @@ static inline void xen_release_ptpage(unsigned long pfn, unsigned level) | |||
1671 | if (!PageHighMem(page)) { | 1671 | if (!PageHighMem(page)) { |
1672 | xen_mc_batch(); | 1672 | xen_mc_batch(); |
1673 | 1673 | ||
1674 | if (level == PT_PTE && USE_SPLIT_PTLOCKS) | 1674 | if (level == PT_PTE && USE_SPLIT_PTE_PTLOCKS) |
1675 | __pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, pfn); | 1675 | __pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, pfn); |
1676 | 1676 | ||
1677 | __set_pfn_prot(pfn, PAGE_KERNEL); | 1677 | __set_pfn_prot(pfn, PAGE_KERNEL); |
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 48b57182dbb6..c36b325abd83 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c | |||
@@ -278,6 +278,15 @@ static void __init xen_smp_prepare_boot_cpu(void) | |||
278 | old memory can be recycled */ | 278 | old memory can be recycled */ |
279 | make_lowmem_page_readwrite(xen_initial_gdt); | 279 | make_lowmem_page_readwrite(xen_initial_gdt); |
280 | 280 | ||
281 | #ifdef CONFIG_X86_32 | ||
282 | /* | ||
283 | * Xen starts us with XEN_FLAT_RING1_DS, but linux code | ||
284 | * expects __USER_DS | ||
285 | */ | ||
286 | loadsegment(ds, __USER_DS); | ||
287 | loadsegment(es, __USER_DS); | ||
288 | #endif | ||
289 | |||
281 | xen_filter_cpu_maps(); | 290 | xen_filter_cpu_maps(); |
282 | xen_setup_vcpu_info_placement(); | 291 | xen_setup_vcpu_info_placement(); |
283 | } | 292 | } |