diff options
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/boot/Makefile | 1 | ||||
-rw-r--r-- | arch/x86/crypto/Makefile | 2 | ||||
-rw-r--r-- | arch/x86/crypto/aes_ctrby8_avx-x86_64.S | 46 | ||||
-rw-r--r-- | arch/x86/include/asm/vgtod.h | 6 | ||||
-rw-r--r-- | arch/x86/kernel/acpi/boot.c | 9 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/Makefile | 1 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mkcapflags.sh | 2 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel_ds.c | 4 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel_rapl.c | 44 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel_uncore.h | 2 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel_uncore_snbep.c | 17 | ||||
-rw-r--r-- | arch/x86/kernel/kprobes/core.c | 20 | ||||
-rw-r--r-- | arch/x86/kernel/perf_regs.c | 90 | ||||
-rw-r--r-- | arch/x86/lib/insn.c | 2 | ||||
-rw-r--r-- | arch/x86/mm/init.c | 37 | ||||
-rw-r--r-- | arch/x86/vdso/vma.c | 45 | ||||
-rw-r--r-- | arch/x86/xen/enlighten.c | 22 | ||||
-rw-r--r-- | arch/x86/xen/p2m.c | 20 | ||||
-rw-r--r-- | arch/x86/xen/setup.c | 42 | ||||
-rw-r--r-- | arch/x86/xen/time.c | 18 |
20 files changed, 307 insertions, 123 deletions
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile index 5b016e2498f3..3db07f30636f 100644 --- a/arch/x86/boot/Makefile +++ b/arch/x86/boot/Makefile | |||
@@ -51,6 +51,7 @@ targets += cpustr.h | |||
51 | $(obj)/cpustr.h: $(obj)/mkcpustr FORCE | 51 | $(obj)/cpustr.h: $(obj)/mkcpustr FORCE |
52 | $(call if_changed,cpustr) | 52 | $(call if_changed,cpustr) |
53 | endif | 53 | endif |
54 | clean-files += cpustr.h | ||
54 | 55 | ||
55 | # --------------------------------------------------------------------------- | 56 | # --------------------------------------------------------------------------- |
56 | 57 | ||
diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile index fd0f848938cc..5a4a089e8b1f 100644 --- a/arch/x86/crypto/Makefile +++ b/arch/x86/crypto/Makefile | |||
@@ -26,7 +26,6 @@ obj-$(CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL) += ghash-clmulni-intel.o | |||
26 | 26 | ||
27 | obj-$(CONFIG_CRYPTO_CRC32C_INTEL) += crc32c-intel.o | 27 | obj-$(CONFIG_CRYPTO_CRC32C_INTEL) += crc32c-intel.o |
28 | obj-$(CONFIG_CRYPTO_SHA1_SSSE3) += sha1-ssse3.o | 28 | obj-$(CONFIG_CRYPTO_SHA1_SSSE3) += sha1-ssse3.o |
29 | obj-$(CONFIG_CRYPTO_SHA1_MB) += sha-mb/ | ||
30 | obj-$(CONFIG_CRYPTO_CRC32_PCLMUL) += crc32-pclmul.o | 29 | obj-$(CONFIG_CRYPTO_CRC32_PCLMUL) += crc32-pclmul.o |
31 | obj-$(CONFIG_CRYPTO_SHA256_SSSE3) += sha256-ssse3.o | 30 | obj-$(CONFIG_CRYPTO_SHA256_SSSE3) += sha256-ssse3.o |
32 | obj-$(CONFIG_CRYPTO_SHA512_SSSE3) += sha512-ssse3.o | 31 | obj-$(CONFIG_CRYPTO_SHA512_SSSE3) += sha512-ssse3.o |
@@ -46,6 +45,7 @@ endif | |||
46 | ifeq ($(avx2_supported),yes) | 45 | ifeq ($(avx2_supported),yes) |
47 | obj-$(CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64) += camellia-aesni-avx2.o | 46 | obj-$(CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64) += camellia-aesni-avx2.o |
48 | obj-$(CONFIG_CRYPTO_SERPENT_AVX2_X86_64) += serpent-avx2.o | 47 | obj-$(CONFIG_CRYPTO_SERPENT_AVX2_X86_64) += serpent-avx2.o |
48 | obj-$(CONFIG_CRYPTO_SHA1_MB) += sha-mb/ | ||
49 | endif | 49 | endif |
50 | 50 | ||
51 | aes-i586-y := aes-i586-asm_32.o aes_glue.o | 51 | aes-i586-y := aes-i586-asm_32.o aes_glue.o |
diff --git a/arch/x86/crypto/aes_ctrby8_avx-x86_64.S b/arch/x86/crypto/aes_ctrby8_avx-x86_64.S index 2df2a0298f5a..a916c4a61165 100644 --- a/arch/x86/crypto/aes_ctrby8_avx-x86_64.S +++ b/arch/x86/crypto/aes_ctrby8_avx-x86_64.S | |||
@@ -208,7 +208,7 @@ ddq_add_8: | |||
208 | 208 | ||
209 | .if (klen == KEY_128) | 209 | .if (klen == KEY_128) |
210 | .if (load_keys) | 210 | .if (load_keys) |
211 | vmovdqa 3*16(p_keys), xkeyA | 211 | vmovdqa 3*16(p_keys), xkey4 |
212 | .endif | 212 | .endif |
213 | .else | 213 | .else |
214 | vmovdqa 3*16(p_keys), xkeyA | 214 | vmovdqa 3*16(p_keys), xkeyA |
@@ -224,7 +224,7 @@ ddq_add_8: | |||
224 | add $(16*by), p_in | 224 | add $(16*by), p_in |
225 | 225 | ||
226 | .if (klen == KEY_128) | 226 | .if (klen == KEY_128) |
227 | vmovdqa 4*16(p_keys), xkey4 | 227 | vmovdqa 4*16(p_keys), xkeyB |
228 | .else | 228 | .else |
229 | .if (load_keys) | 229 | .if (load_keys) |
230 | vmovdqa 4*16(p_keys), xkey4 | 230 | vmovdqa 4*16(p_keys), xkey4 |
@@ -234,7 +234,12 @@ ddq_add_8: | |||
234 | .set i, 0 | 234 | .set i, 0 |
235 | .rept by | 235 | .rept by |
236 | club XDATA, i | 236 | club XDATA, i |
237 | vaesenc xkeyA, var_xdata, var_xdata /* key 3 */ | 237 | /* key 3 */ |
238 | .if (klen == KEY_128) | ||
239 | vaesenc xkey4, var_xdata, var_xdata | ||
240 | .else | ||
241 | vaesenc xkeyA, var_xdata, var_xdata | ||
242 | .endif | ||
238 | .set i, (i +1) | 243 | .set i, (i +1) |
239 | .endr | 244 | .endr |
240 | 245 | ||
@@ -243,13 +248,18 @@ ddq_add_8: | |||
243 | .set i, 0 | 248 | .set i, 0 |
244 | .rept by | 249 | .rept by |
245 | club XDATA, i | 250 | club XDATA, i |
246 | vaesenc xkey4, var_xdata, var_xdata /* key 4 */ | 251 | /* key 4 */ |
252 | .if (klen == KEY_128) | ||
253 | vaesenc xkeyB, var_xdata, var_xdata | ||
254 | .else | ||
255 | vaesenc xkey4, var_xdata, var_xdata | ||
256 | .endif | ||
247 | .set i, (i +1) | 257 | .set i, (i +1) |
248 | .endr | 258 | .endr |
249 | 259 | ||
250 | .if (klen == KEY_128) | 260 | .if (klen == KEY_128) |
251 | .if (load_keys) | 261 | .if (load_keys) |
252 | vmovdqa 6*16(p_keys), xkeyB | 262 | vmovdqa 6*16(p_keys), xkey8 |
253 | .endif | 263 | .endif |
254 | .else | 264 | .else |
255 | vmovdqa 6*16(p_keys), xkeyB | 265 | vmovdqa 6*16(p_keys), xkeyB |
@@ -267,12 +277,17 @@ ddq_add_8: | |||
267 | .set i, 0 | 277 | .set i, 0 |
268 | .rept by | 278 | .rept by |
269 | club XDATA, i | 279 | club XDATA, i |
270 | vaesenc xkeyB, var_xdata, var_xdata /* key 6 */ | 280 | /* key 6 */ |
281 | .if (klen == KEY_128) | ||
282 | vaesenc xkey8, var_xdata, var_xdata | ||
283 | .else | ||
284 | vaesenc xkeyB, var_xdata, var_xdata | ||
285 | .endif | ||
271 | .set i, (i +1) | 286 | .set i, (i +1) |
272 | .endr | 287 | .endr |
273 | 288 | ||
274 | .if (klen == KEY_128) | 289 | .if (klen == KEY_128) |
275 | vmovdqa 8*16(p_keys), xkey8 | 290 | vmovdqa 8*16(p_keys), xkeyB |
276 | .else | 291 | .else |
277 | .if (load_keys) | 292 | .if (load_keys) |
278 | vmovdqa 8*16(p_keys), xkey8 | 293 | vmovdqa 8*16(p_keys), xkey8 |
@@ -288,7 +303,7 @@ ddq_add_8: | |||
288 | 303 | ||
289 | .if (klen == KEY_128) | 304 | .if (klen == KEY_128) |
290 | .if (load_keys) | 305 | .if (load_keys) |
291 | vmovdqa 9*16(p_keys), xkeyA | 306 | vmovdqa 9*16(p_keys), xkey12 |
292 | .endif | 307 | .endif |
293 | .else | 308 | .else |
294 | vmovdqa 9*16(p_keys), xkeyA | 309 | vmovdqa 9*16(p_keys), xkeyA |
@@ -297,7 +312,12 @@ ddq_add_8: | |||
297 | .set i, 0 | 312 | .set i, 0 |
298 | .rept by | 313 | .rept by |
299 | club XDATA, i | 314 | club XDATA, i |
300 | vaesenc xkey8, var_xdata, var_xdata /* key 8 */ | 315 | /* key 8 */ |
316 | .if (klen == KEY_128) | ||
317 | vaesenc xkeyB, var_xdata, var_xdata | ||
318 | .else | ||
319 | vaesenc xkey8, var_xdata, var_xdata | ||
320 | .endif | ||
301 | .set i, (i +1) | 321 | .set i, (i +1) |
302 | .endr | 322 | .endr |
303 | 323 | ||
@@ -306,7 +326,12 @@ ddq_add_8: | |||
306 | .set i, 0 | 326 | .set i, 0 |
307 | .rept by | 327 | .rept by |
308 | club XDATA, i | 328 | club XDATA, i |
309 | vaesenc xkeyA, var_xdata, var_xdata /* key 9 */ | 329 | /* key 9 */ |
330 | .if (klen == KEY_128) | ||
331 | vaesenc xkey12, var_xdata, var_xdata | ||
332 | .else | ||
333 | vaesenc xkeyA, var_xdata, var_xdata | ||
334 | .endif | ||
310 | .set i, (i +1) | 335 | .set i, (i +1) |
311 | .endr | 336 | .endr |
312 | 337 | ||
@@ -412,7 +437,6 @@ ddq_add_8: | |||
412 | /* main body of aes ctr load */ | 437 | /* main body of aes ctr load */ |
413 | 438 | ||
414 | .macro do_aes_ctrmain key_len | 439 | .macro do_aes_ctrmain key_len |
415 | |||
416 | cmp $16, num_bytes | 440 | cmp $16, num_bytes |
417 | jb .Ldo_return2\key_len | 441 | jb .Ldo_return2\key_len |
418 | 442 | ||
diff --git a/arch/x86/include/asm/vgtod.h b/arch/x86/include/asm/vgtod.h index e7e9682a33e9..f556c4843aa1 100644 --- a/arch/x86/include/asm/vgtod.h +++ b/arch/x86/include/asm/vgtod.h | |||
@@ -80,9 +80,11 @@ static inline unsigned int __getcpu(void) | |||
80 | 80 | ||
81 | /* | 81 | /* |
82 | * Load per CPU data from GDT. LSL is faster than RDTSCP and | 82 | * Load per CPU data from GDT. LSL is faster than RDTSCP and |
83 | * works on all CPUs. | 83 | * works on all CPUs. This is volatile so that it orders |
84 | * correctly wrt barrier() and to keep gcc from cleverly | ||
85 | * hoisting it out of the calling function. | ||
84 | */ | 86 | */ |
85 | asm("lsl %1,%0" : "=r" (p) : "r" (__PER_CPU_SEG)); | 87 | asm volatile ("lsl %1,%0" : "=r" (p) : "r" (__PER_CPU_SEG)); |
86 | 88 | ||
87 | return p; | 89 | return p; |
88 | } | 90 | } |
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 4433a4be8171..d1626364a28a 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
@@ -750,13 +750,13 @@ static int _acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu) | |||
750 | } | 750 | } |
751 | 751 | ||
752 | /* wrapper to silence section mismatch warning */ | 752 | /* wrapper to silence section mismatch warning */ |
753 | int __ref acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu) | 753 | int __ref acpi_map_cpu(acpi_handle handle, int physid, int *pcpu) |
754 | { | 754 | { |
755 | return _acpi_map_lsapic(handle, physid, pcpu); | 755 | return _acpi_map_lsapic(handle, physid, pcpu); |
756 | } | 756 | } |
757 | EXPORT_SYMBOL(acpi_map_lsapic); | 757 | EXPORT_SYMBOL(acpi_map_cpu); |
758 | 758 | ||
759 | int acpi_unmap_lsapic(int cpu) | 759 | int acpi_unmap_cpu(int cpu) |
760 | { | 760 | { |
761 | #ifdef CONFIG_ACPI_NUMA | 761 | #ifdef CONFIG_ACPI_NUMA |
762 | set_apicid_to_node(per_cpu(x86_cpu_to_apicid, cpu), NUMA_NO_NODE); | 762 | set_apicid_to_node(per_cpu(x86_cpu_to_apicid, cpu), NUMA_NO_NODE); |
@@ -768,8 +768,7 @@ int acpi_unmap_lsapic(int cpu) | |||
768 | 768 | ||
769 | return (0); | 769 | return (0); |
770 | } | 770 | } |
771 | 771 | EXPORT_SYMBOL(acpi_unmap_cpu); | |
772 | EXPORT_SYMBOL(acpi_unmap_lsapic); | ||
773 | #endif /* CONFIG_ACPI_HOTPLUG_CPU */ | 772 | #endif /* CONFIG_ACPI_HOTPLUG_CPU */ |
774 | 773 | ||
775 | int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base) | 774 | int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base) |
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index e27b49d7c922..80091ae54c2b 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile | |||
@@ -66,3 +66,4 @@ targets += capflags.c | |||
66 | $(obj)/capflags.c: $(cpufeature) $(src)/mkcapflags.sh FORCE | 66 | $(obj)/capflags.c: $(cpufeature) $(src)/mkcapflags.sh FORCE |
67 | $(call if_changed,mkcapflags) | 67 | $(call if_changed,mkcapflags) |
68 | endif | 68 | endif |
69 | clean-files += capflags.c | ||
diff --git a/arch/x86/kernel/cpu/mkcapflags.sh b/arch/x86/kernel/cpu/mkcapflags.sh index e2b22df964cd..36d99a337b49 100644 --- a/arch/x86/kernel/cpu/mkcapflags.sh +++ b/arch/x86/kernel/cpu/mkcapflags.sh | |||
@@ -28,7 +28,7 @@ function dump_array() | |||
28 | # If the /* comment */ starts with a quote string, grab that. | 28 | # If the /* comment */ starts with a quote string, grab that. |
29 | VALUE="$(echo "$i" | sed -n 's@.*/\* *\("[^"]*"\).*\*/@\1@p')" | 29 | VALUE="$(echo "$i" | sed -n 's@.*/\* *\("[^"]*"\).*\*/@\1@p')" |
30 | [ -z "$VALUE" ] && VALUE="\"$NAME\"" | 30 | [ -z "$VALUE" ] && VALUE="\"$NAME\"" |
31 | [ "$VALUE" == '""' ] && continue | 31 | [ "$VALUE" = '""' ] && continue |
32 | 32 | ||
33 | # Name is uppercase, VALUE is all lowercase | 33 | # Name is uppercase, VALUE is all lowercase |
34 | VALUE="$(echo "$VALUE" | tr A-Z a-z)" | 34 | VALUE="$(echo "$VALUE" | tr A-Z a-z)" |
diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index 3c895d480cd7..073983398364 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c | |||
@@ -568,8 +568,8 @@ struct event_constraint intel_atom_pebs_event_constraints[] = { | |||
568 | }; | 568 | }; |
569 | 569 | ||
570 | struct event_constraint intel_slm_pebs_event_constraints[] = { | 570 | struct event_constraint intel_slm_pebs_event_constraints[] = { |
571 | /* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */ | 571 | /* INST_RETIRED.ANY_P, inv=1, cmask=16 (cycles:p). */ |
572 | INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c2, 0xf), | 572 | INTEL_FLAGS_EVENT_CONSTRAINT(0x108000c0, 0x1), |
573 | /* Allow all events as PEBS with no flags */ | 573 | /* Allow all events as PEBS with no flags */ |
574 | INTEL_ALL_EVENT_CONSTRAINT(0, 0x1), | 574 | INTEL_ALL_EVENT_CONSTRAINT(0, 0x1), |
575 | EVENT_CONSTRAINT_END | 575 | EVENT_CONSTRAINT_END |
diff --git a/arch/x86/kernel/cpu/perf_event_intel_rapl.c b/arch/x86/kernel/cpu/perf_event_intel_rapl.c index 673f930c700f..6e434f8e5fc8 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_rapl.c +++ b/arch/x86/kernel/cpu/perf_event_intel_rapl.c | |||
@@ -103,6 +103,13 @@ static struct kobj_attribute format_attr_##_var = \ | |||
103 | 103 | ||
104 | #define RAPL_CNTR_WIDTH 32 /* 32-bit rapl counters */ | 104 | #define RAPL_CNTR_WIDTH 32 /* 32-bit rapl counters */ |
105 | 105 | ||
106 | #define RAPL_EVENT_ATTR_STR(_name, v, str) \ | ||
107 | static struct perf_pmu_events_attr event_attr_##v = { \ | ||
108 | .attr = __ATTR(_name, 0444, rapl_sysfs_show, NULL), \ | ||
109 | .id = 0, \ | ||
110 | .event_str = str, \ | ||
111 | }; | ||
112 | |||
106 | struct rapl_pmu { | 113 | struct rapl_pmu { |
107 | spinlock_t lock; | 114 | spinlock_t lock; |
108 | int hw_unit; /* 1/2^hw_unit Joule */ | 115 | int hw_unit; /* 1/2^hw_unit Joule */ |
@@ -379,23 +386,36 @@ static struct attribute_group rapl_pmu_attr_group = { | |||
379 | .attrs = rapl_pmu_attrs, | 386 | .attrs = rapl_pmu_attrs, |
380 | }; | 387 | }; |
381 | 388 | ||
382 | EVENT_ATTR_STR(energy-cores, rapl_cores, "event=0x01"); | 389 | static ssize_t rapl_sysfs_show(struct device *dev, |
383 | EVENT_ATTR_STR(energy-pkg , rapl_pkg, "event=0x02"); | 390 | struct device_attribute *attr, |
384 | EVENT_ATTR_STR(energy-ram , rapl_ram, "event=0x03"); | 391 | char *page) |
385 | EVENT_ATTR_STR(energy-gpu , rapl_gpu, "event=0x04"); | 392 | { |
393 | struct perf_pmu_events_attr *pmu_attr = \ | ||
394 | container_of(attr, struct perf_pmu_events_attr, attr); | ||
395 | |||
396 | if (pmu_attr->event_str) | ||
397 | return sprintf(page, "%s", pmu_attr->event_str); | ||
398 | |||
399 | return 0; | ||
400 | } | ||
401 | |||
402 | RAPL_EVENT_ATTR_STR(energy-cores, rapl_cores, "event=0x01"); | ||
403 | RAPL_EVENT_ATTR_STR(energy-pkg , rapl_pkg, "event=0x02"); | ||
404 | RAPL_EVENT_ATTR_STR(energy-ram , rapl_ram, "event=0x03"); | ||
405 | RAPL_EVENT_ATTR_STR(energy-gpu , rapl_gpu, "event=0x04"); | ||
386 | 406 | ||
387 | EVENT_ATTR_STR(energy-cores.unit, rapl_cores_unit, "Joules"); | 407 | RAPL_EVENT_ATTR_STR(energy-cores.unit, rapl_cores_unit, "Joules"); |
388 | EVENT_ATTR_STR(energy-pkg.unit , rapl_pkg_unit, "Joules"); | 408 | RAPL_EVENT_ATTR_STR(energy-pkg.unit , rapl_pkg_unit, "Joules"); |
389 | EVENT_ATTR_STR(energy-ram.unit , rapl_ram_unit, "Joules"); | 409 | RAPL_EVENT_ATTR_STR(energy-ram.unit , rapl_ram_unit, "Joules"); |
390 | EVENT_ATTR_STR(energy-gpu.unit , rapl_gpu_unit, "Joules"); | 410 | RAPL_EVENT_ATTR_STR(energy-gpu.unit , rapl_gpu_unit, "Joules"); |
391 | 411 | ||
392 | /* | 412 | /* |
393 | * we compute in 0.23 nJ increments regardless of MSR | 413 | * we compute in 0.23 nJ increments regardless of MSR |
394 | */ | 414 | */ |
395 | EVENT_ATTR_STR(energy-cores.scale, rapl_cores_scale, "2.3283064365386962890625e-10"); | 415 | RAPL_EVENT_ATTR_STR(energy-cores.scale, rapl_cores_scale, "2.3283064365386962890625e-10"); |
396 | EVENT_ATTR_STR(energy-pkg.scale, rapl_pkg_scale, "2.3283064365386962890625e-10"); | 416 | RAPL_EVENT_ATTR_STR(energy-pkg.scale, rapl_pkg_scale, "2.3283064365386962890625e-10"); |
397 | EVENT_ATTR_STR(energy-ram.scale, rapl_ram_scale, "2.3283064365386962890625e-10"); | 417 | RAPL_EVENT_ATTR_STR(energy-ram.scale, rapl_ram_scale, "2.3283064365386962890625e-10"); |
398 | EVENT_ATTR_STR(energy-gpu.scale, rapl_gpu_scale, "2.3283064365386962890625e-10"); | 418 | RAPL_EVENT_ATTR_STR(energy-gpu.scale, rapl_gpu_scale, "2.3283064365386962890625e-10"); |
399 | 419 | ||
400 | static struct attribute *rapl_events_srv_attr[] = { | 420 | static struct attribute *rapl_events_srv_attr[] = { |
401 | EVENT_PTR(rapl_cores), | 421 | EVENT_PTR(rapl_cores), |
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.h b/arch/x86/kernel/cpu/perf_event_intel_uncore.h index 18eb78bbdd10..863d9b02563e 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.h +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.h | |||
@@ -17,7 +17,7 @@ | |||
17 | #define UNCORE_PCI_DEV_TYPE(data) ((data >> 8) & 0xff) | 17 | #define UNCORE_PCI_DEV_TYPE(data) ((data >> 8) & 0xff) |
18 | #define UNCORE_PCI_DEV_IDX(data) (data & 0xff) | 18 | #define UNCORE_PCI_DEV_IDX(data) (data & 0xff) |
19 | #define UNCORE_EXTRA_PCI_DEV 0xff | 19 | #define UNCORE_EXTRA_PCI_DEV 0xff |
20 | #define UNCORE_EXTRA_PCI_DEV_MAX 2 | 20 | #define UNCORE_EXTRA_PCI_DEV_MAX 3 |
21 | 21 | ||
22 | /* support up to 8 sockets */ | 22 | /* support up to 8 sockets */ |
23 | #define UNCORE_SOCKET_MAX 8 | 23 | #define UNCORE_SOCKET_MAX 8 |
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore_snbep.c b/arch/x86/kernel/cpu/perf_event_intel_uncore_snbep.c index 745b158e9a65..21af6149edf2 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore_snbep.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore_snbep.c | |||
@@ -891,6 +891,7 @@ void snbep_uncore_cpu_init(void) | |||
891 | enum { | 891 | enum { |
892 | SNBEP_PCI_QPI_PORT0_FILTER, | 892 | SNBEP_PCI_QPI_PORT0_FILTER, |
893 | SNBEP_PCI_QPI_PORT1_FILTER, | 893 | SNBEP_PCI_QPI_PORT1_FILTER, |
894 | HSWEP_PCI_PCU_3, | ||
894 | }; | 895 | }; |
895 | 896 | ||
896 | static int snbep_qpi_hw_config(struct intel_uncore_box *box, struct perf_event *event) | 897 | static int snbep_qpi_hw_config(struct intel_uncore_box *box, struct perf_event *event) |
@@ -2026,6 +2027,17 @@ void hswep_uncore_cpu_init(void) | |||
2026 | { | 2027 | { |
2027 | if (hswep_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores) | 2028 | if (hswep_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores) |
2028 | hswep_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores; | 2029 | hswep_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores; |
2030 | |||
2031 | /* Detect 6-8 core systems with only two SBOXes */ | ||
2032 | if (uncore_extra_pci_dev[0][HSWEP_PCI_PCU_3]) { | ||
2033 | u32 capid4; | ||
2034 | |||
2035 | pci_read_config_dword(uncore_extra_pci_dev[0][HSWEP_PCI_PCU_3], | ||
2036 | 0x94, &capid4); | ||
2037 | if (((capid4 >> 6) & 0x3) == 0) | ||
2038 | hswep_uncore_sbox.num_boxes = 2; | ||
2039 | } | ||
2040 | |||
2029 | uncore_msr_uncores = hswep_msr_uncores; | 2041 | uncore_msr_uncores = hswep_msr_uncores; |
2030 | } | 2042 | } |
2031 | 2043 | ||
@@ -2287,6 +2299,11 @@ static DEFINE_PCI_DEVICE_TABLE(hswep_uncore_pci_ids) = { | |||
2287 | .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV, | 2299 | .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV, |
2288 | SNBEP_PCI_QPI_PORT1_FILTER), | 2300 | SNBEP_PCI_QPI_PORT1_FILTER), |
2289 | }, | 2301 | }, |
2302 | { /* PCU.3 (for Capability registers) */ | ||
2303 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2fc0), | ||
2304 | .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV, | ||
2305 | HSWEP_PCI_PCU_3), | ||
2306 | }, | ||
2290 | { /* end: all zeroes */ } | 2307 | { /* end: all zeroes */ } |
2291 | }; | 2308 | }; |
2292 | 2309 | ||
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c index f7e3cd50ece0..98f654d466e5 100644 --- a/arch/x86/kernel/kprobes/core.c +++ b/arch/x86/kernel/kprobes/core.c | |||
@@ -1020,6 +1020,15 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | |||
1020 | regs->flags &= ~X86_EFLAGS_IF; | 1020 | regs->flags &= ~X86_EFLAGS_IF; |
1021 | trace_hardirqs_off(); | 1021 | trace_hardirqs_off(); |
1022 | regs->ip = (unsigned long)(jp->entry); | 1022 | regs->ip = (unsigned long)(jp->entry); |
1023 | |||
1024 | /* | ||
1025 | * jprobes use jprobe_return() which skips the normal return | ||
1026 | * path of the function, and this messes up the accounting of the | ||
1027 | * function graph tracer to get messed up. | ||
1028 | * | ||
1029 | * Pause function graph tracing while performing the jprobe function. | ||
1030 | */ | ||
1031 | pause_graph_tracing(); | ||
1023 | return 1; | 1032 | return 1; |
1024 | } | 1033 | } |
1025 | NOKPROBE_SYMBOL(setjmp_pre_handler); | 1034 | NOKPROBE_SYMBOL(setjmp_pre_handler); |
@@ -1048,24 +1057,25 @@ int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) | |||
1048 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 1057 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
1049 | u8 *addr = (u8 *) (regs->ip - 1); | 1058 | u8 *addr = (u8 *) (regs->ip - 1); |
1050 | struct jprobe *jp = container_of(p, struct jprobe, kp); | 1059 | struct jprobe *jp = container_of(p, struct jprobe, kp); |
1060 | void *saved_sp = kcb->jprobe_saved_sp; | ||
1051 | 1061 | ||
1052 | if ((addr > (u8 *) jprobe_return) && | 1062 | if ((addr > (u8 *) jprobe_return) && |
1053 | (addr < (u8 *) jprobe_return_end)) { | 1063 | (addr < (u8 *) jprobe_return_end)) { |
1054 | if (stack_addr(regs) != kcb->jprobe_saved_sp) { | 1064 | if (stack_addr(regs) != saved_sp) { |
1055 | struct pt_regs *saved_regs = &kcb->jprobe_saved_regs; | 1065 | struct pt_regs *saved_regs = &kcb->jprobe_saved_regs; |
1056 | printk(KERN_ERR | 1066 | printk(KERN_ERR |
1057 | "current sp %p does not match saved sp %p\n", | 1067 | "current sp %p does not match saved sp %p\n", |
1058 | stack_addr(regs), kcb->jprobe_saved_sp); | 1068 | stack_addr(regs), saved_sp); |
1059 | printk(KERN_ERR "Saved registers for jprobe %p\n", jp); | 1069 | printk(KERN_ERR "Saved registers for jprobe %p\n", jp); |
1060 | show_regs(saved_regs); | 1070 | show_regs(saved_regs); |
1061 | printk(KERN_ERR "Current registers\n"); | 1071 | printk(KERN_ERR "Current registers\n"); |
1062 | show_regs(regs); | 1072 | show_regs(regs); |
1063 | BUG(); | 1073 | BUG(); |
1064 | } | 1074 | } |
1075 | /* It's OK to start function graph tracing again */ | ||
1076 | unpause_graph_tracing(); | ||
1065 | *regs = kcb->jprobe_saved_regs; | 1077 | *regs = kcb->jprobe_saved_regs; |
1066 | memcpy((kprobe_opcode_t *)(kcb->jprobe_saved_sp), | 1078 | memcpy(saved_sp, kcb->jprobes_stack, MIN_STACK_SIZE(saved_sp)); |
1067 | kcb->jprobes_stack, | ||
1068 | MIN_STACK_SIZE(kcb->jprobe_saved_sp)); | ||
1069 | preempt_enable_no_resched(); | 1079 | preempt_enable_no_resched(); |
1070 | return 1; | 1080 | return 1; |
1071 | } | 1081 | } |
diff --git a/arch/x86/kernel/perf_regs.c b/arch/x86/kernel/perf_regs.c index e309cc5c276e..781861cc5ee8 100644 --- a/arch/x86/kernel/perf_regs.c +++ b/arch/x86/kernel/perf_regs.c | |||
@@ -78,6 +78,14 @@ u64 perf_reg_abi(struct task_struct *task) | |||
78 | { | 78 | { |
79 | return PERF_SAMPLE_REGS_ABI_32; | 79 | return PERF_SAMPLE_REGS_ABI_32; |
80 | } | 80 | } |
81 | |||
82 | void perf_get_regs_user(struct perf_regs *regs_user, | ||
83 | struct pt_regs *regs, | ||
84 | struct pt_regs *regs_user_copy) | ||
85 | { | ||
86 | regs_user->regs = task_pt_regs(current); | ||
87 | regs_user->abi = perf_reg_abi(current); | ||
88 | } | ||
81 | #else /* CONFIG_X86_64 */ | 89 | #else /* CONFIG_X86_64 */ |
82 | #define REG_NOSUPPORT ((1ULL << PERF_REG_X86_DS) | \ | 90 | #define REG_NOSUPPORT ((1ULL << PERF_REG_X86_DS) | \ |
83 | (1ULL << PERF_REG_X86_ES) | \ | 91 | (1ULL << PERF_REG_X86_ES) | \ |
@@ -102,4 +110,86 @@ u64 perf_reg_abi(struct task_struct *task) | |||
102 | else | 110 | else |
103 | return PERF_SAMPLE_REGS_ABI_64; | 111 | return PERF_SAMPLE_REGS_ABI_64; |
104 | } | 112 | } |
113 | |||
114 | void perf_get_regs_user(struct perf_regs *regs_user, | ||
115 | struct pt_regs *regs, | ||
116 | struct pt_regs *regs_user_copy) | ||
117 | { | ||
118 | struct pt_regs *user_regs = task_pt_regs(current); | ||
119 | |||
120 | /* | ||
121 | * If we're in an NMI that interrupted task_pt_regs setup, then | ||
122 | * we can't sample user regs at all. This check isn't really | ||
123 | * sufficient, though, as we could be in an NMI inside an interrupt | ||
124 | * that happened during task_pt_regs setup. | ||
125 | */ | ||
126 | if (regs->sp > (unsigned long)&user_regs->r11 && | ||
127 | regs->sp <= (unsigned long)(user_regs + 1)) { | ||
128 | regs_user->abi = PERF_SAMPLE_REGS_ABI_NONE; | ||
129 | regs_user->regs = NULL; | ||
130 | return; | ||
131 | } | ||
132 | |||
133 | /* | ||
134 | * RIP, flags, and the argument registers are usually saved. | ||
135 | * orig_ax is probably okay, too. | ||
136 | */ | ||
137 | regs_user_copy->ip = user_regs->ip; | ||
138 | regs_user_copy->cx = user_regs->cx; | ||
139 | regs_user_copy->dx = user_regs->dx; | ||
140 | regs_user_copy->si = user_regs->si; | ||
141 | regs_user_copy->di = user_regs->di; | ||
142 | regs_user_copy->r8 = user_regs->r8; | ||
143 | regs_user_copy->r9 = user_regs->r9; | ||
144 | regs_user_copy->r10 = user_regs->r10; | ||
145 | regs_user_copy->r11 = user_regs->r11; | ||
146 | regs_user_copy->orig_ax = user_regs->orig_ax; | ||
147 | regs_user_copy->flags = user_regs->flags; | ||
148 | |||
149 | /* | ||
150 | * Don't even try to report the "rest" regs. | ||
151 | */ | ||
152 | regs_user_copy->bx = -1; | ||
153 | regs_user_copy->bp = -1; | ||
154 | regs_user_copy->r12 = -1; | ||
155 | regs_user_copy->r13 = -1; | ||
156 | regs_user_copy->r14 = -1; | ||
157 | regs_user_copy->r15 = -1; | ||
158 | |||
159 | /* | ||
160 | * For this to be at all useful, we need a reasonable guess for | ||
161 | * sp and the ABI. Be careful: we're in NMI context, and we're | ||
162 | * considering current to be the current task, so we should | ||
163 | * be careful not to look at any other percpu variables that might | ||
164 | * change during context switches. | ||
165 | */ | ||
166 | if (IS_ENABLED(CONFIG_IA32_EMULATION) && | ||
167 | task_thread_info(current)->status & TS_COMPAT) { | ||
168 | /* Easy case: we're in a compat syscall. */ | ||
169 | regs_user->abi = PERF_SAMPLE_REGS_ABI_32; | ||
170 | regs_user_copy->sp = user_regs->sp; | ||
171 | regs_user_copy->cs = user_regs->cs; | ||
172 | regs_user_copy->ss = user_regs->ss; | ||
173 | } else if (user_regs->orig_ax != -1) { | ||
174 | /* | ||
175 | * We're probably in a 64-bit syscall. | ||
176 | * Warning: this code is severely racy. At least it's better | ||
177 | * than just blindly copying user_regs. | ||
178 | */ | ||
179 | regs_user->abi = PERF_SAMPLE_REGS_ABI_64; | ||
180 | regs_user_copy->sp = this_cpu_read(old_rsp); | ||
181 | regs_user_copy->cs = __USER_CS; | ||
182 | regs_user_copy->ss = __USER_DS; | ||
183 | regs_user_copy->cx = -1; /* usually contains garbage */ | ||
184 | } else { | ||
185 | /* We're probably in an interrupt or exception. */ | ||
186 | regs_user->abi = user_64bit_mode(user_regs) ? | ||
187 | PERF_SAMPLE_REGS_ABI_64 : PERF_SAMPLE_REGS_ABI_32; | ||
188 | regs_user_copy->sp = user_regs->sp; | ||
189 | regs_user_copy->cs = user_regs->cs; | ||
190 | regs_user_copy->ss = user_regs->ss; | ||
191 | } | ||
192 | |||
193 | regs_user->regs = regs_user_copy; | ||
194 | } | ||
105 | #endif /* CONFIG_X86_32 */ | 195 | #endif /* CONFIG_X86_32 */ |
diff --git a/arch/x86/lib/insn.c b/arch/x86/lib/insn.c index 2480978b31cc..1313ae6b478b 100644 --- a/arch/x86/lib/insn.c +++ b/arch/x86/lib/insn.c | |||
@@ -28,7 +28,7 @@ | |||
28 | 28 | ||
29 | /* Verify next sizeof(t) bytes can be on the same instruction */ | 29 | /* Verify next sizeof(t) bytes can be on the same instruction */ |
30 | #define validate_next(t, insn, n) \ | 30 | #define validate_next(t, insn, n) \ |
31 | ((insn)->next_byte + sizeof(t) + n < (insn)->end_kaddr) | 31 | ((insn)->next_byte + sizeof(t) + n <= (insn)->end_kaddr) |
32 | 32 | ||
33 | #define __get_next(t, insn) \ | 33 | #define __get_next(t, insn) \ |
34 | ({ t r = *(t*)insn->next_byte; insn->next_byte += sizeof(t); r; }) | 34 | ({ t r = *(t*)insn->next_byte; insn->next_byte += sizeof(t); r; }) |
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index a97ee0801475..08a7d313538a 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c | |||
@@ -438,20 +438,20 @@ static unsigned long __init init_range_memory_mapping( | |||
438 | static unsigned long __init get_new_step_size(unsigned long step_size) | 438 | static unsigned long __init get_new_step_size(unsigned long step_size) |
439 | { | 439 | { |
440 | /* | 440 | /* |
441 | * Explain why we shift by 5 and why we don't have to worry about | 441 | * Initial mapped size is PMD_SIZE (2M). |
442 | * 'step_size << 5' overflowing: | ||
443 | * | ||
444 | * initial mapped size is PMD_SIZE (2M). | ||
445 | * We can not set step_size to be PUD_SIZE (1G) yet. | 442 | * We can not set step_size to be PUD_SIZE (1G) yet. |
446 | * In worse case, when we cross the 1G boundary, and | 443 | * In worse case, when we cross the 1G boundary, and |
447 | * PG_LEVEL_2M is not set, we will need 1+1+512 pages (2M + 8k) | 444 | * PG_LEVEL_2M is not set, we will need 1+1+512 pages (2M + 8k) |
448 | * to map 1G range with PTE. Use 5 as shift for now. | 445 | * to map 1G range with PTE. Hence we use one less than the |
446 | * difference of page table level shifts. | ||
449 | * | 447 | * |
450 | * Don't need to worry about overflow, on 32bit, when step_size | 448 | * Don't need to worry about overflow in the top-down case, on 32bit, |
451 | * is 0, round_down() returns 0 for start, and that turns it | 449 | * when step_size is 0, round_down() returns 0 for start, and that |
452 | * into 0x100000000ULL. | 450 | * turns it into 0x100000000ULL. |
451 | * In the bottom-up case, round_up(x, 0) returns 0 though too, which | ||
452 | * needs to be taken into consideration by the code below. | ||
453 | */ | 453 | */ |
454 | return step_size << 5; | 454 | return step_size << (PMD_SHIFT - PAGE_SHIFT - 1); |
455 | } | 455 | } |
456 | 456 | ||
457 | /** | 457 | /** |
@@ -471,7 +471,6 @@ static void __init memory_map_top_down(unsigned long map_start, | |||
471 | unsigned long step_size; | 471 | unsigned long step_size; |
472 | unsigned long addr; | 472 | unsigned long addr; |
473 | unsigned long mapped_ram_size = 0; | 473 | unsigned long mapped_ram_size = 0; |
474 | unsigned long new_mapped_ram_size; | ||
475 | 474 | ||
476 | /* xen has big range in reserved near end of ram, skip it at first.*/ | 475 | /* xen has big range in reserved near end of ram, skip it at first.*/ |
477 | addr = memblock_find_in_range(map_start, map_end, PMD_SIZE, PMD_SIZE); | 476 | addr = memblock_find_in_range(map_start, map_end, PMD_SIZE, PMD_SIZE); |
@@ -496,14 +495,12 @@ static void __init memory_map_top_down(unsigned long map_start, | |||
496 | start = map_start; | 495 | start = map_start; |
497 | } else | 496 | } else |
498 | start = map_start; | 497 | start = map_start; |
499 | new_mapped_ram_size = init_range_memory_mapping(start, | 498 | mapped_ram_size += init_range_memory_mapping(start, |
500 | last_start); | 499 | last_start); |
501 | last_start = start; | 500 | last_start = start; |
502 | min_pfn_mapped = last_start >> PAGE_SHIFT; | 501 | min_pfn_mapped = last_start >> PAGE_SHIFT; |
503 | /* only increase step_size after big range get mapped */ | 502 | if (mapped_ram_size >= step_size) |
504 | if (new_mapped_ram_size > mapped_ram_size) | ||
505 | step_size = get_new_step_size(step_size); | 503 | step_size = get_new_step_size(step_size); |
506 | mapped_ram_size += new_mapped_ram_size; | ||
507 | } | 504 | } |
508 | 505 | ||
509 | if (real_end < map_end) | 506 | if (real_end < map_end) |
@@ -524,7 +521,7 @@ static void __init memory_map_top_down(unsigned long map_start, | |||
524 | static void __init memory_map_bottom_up(unsigned long map_start, | 521 | static void __init memory_map_bottom_up(unsigned long map_start, |
525 | unsigned long map_end) | 522 | unsigned long map_end) |
526 | { | 523 | { |
527 | unsigned long next, new_mapped_ram_size, start; | 524 | unsigned long next, start; |
528 | unsigned long mapped_ram_size = 0; | 525 | unsigned long mapped_ram_size = 0; |
529 | /* step_size need to be small so pgt_buf from BRK could cover it */ | 526 | /* step_size need to be small so pgt_buf from BRK could cover it */ |
530 | unsigned long step_size = PMD_SIZE; | 527 | unsigned long step_size = PMD_SIZE; |
@@ -539,19 +536,19 @@ static void __init memory_map_bottom_up(unsigned long map_start, | |||
539 | * for page table. | 536 | * for page table. |
540 | */ | 537 | */ |
541 | while (start < map_end) { | 538 | while (start < map_end) { |
542 | if (map_end - start > step_size) { | 539 | if (step_size && map_end - start > step_size) { |
543 | next = round_up(start + 1, step_size); | 540 | next = round_up(start + 1, step_size); |
544 | if (next > map_end) | 541 | if (next > map_end) |
545 | next = map_end; | 542 | next = map_end; |
546 | } else | 543 | } else { |
547 | next = map_end; | 544 | next = map_end; |
545 | } | ||
548 | 546 | ||
549 | new_mapped_ram_size = init_range_memory_mapping(start, next); | 547 | mapped_ram_size += init_range_memory_mapping(start, next); |
550 | start = next; | 548 | start = next; |
551 | 549 | ||
552 | if (new_mapped_ram_size > mapped_ram_size) | 550 | if (mapped_ram_size >= step_size) |
553 | step_size = get_new_step_size(step_size); | 551 | step_size = get_new_step_size(step_size); |
554 | mapped_ram_size += new_mapped_ram_size; | ||
555 | } | 552 | } |
556 | } | 553 | } |
557 | 554 | ||
diff --git a/arch/x86/vdso/vma.c b/arch/x86/vdso/vma.c index 009495b9ab4b..1c9f750c3859 100644 --- a/arch/x86/vdso/vma.c +++ b/arch/x86/vdso/vma.c | |||
@@ -41,12 +41,17 @@ void __init init_vdso_image(const struct vdso_image *image) | |||
41 | 41 | ||
42 | struct linux_binprm; | 42 | struct linux_binprm; |
43 | 43 | ||
44 | /* Put the vdso above the (randomized) stack with another randomized offset. | 44 | /* |
45 | This way there is no hole in the middle of address space. | 45 | * Put the vdso above the (randomized) stack with another randomized |
46 | To save memory make sure it is still in the same PTE as the stack top. | 46 | * offset. This way there is no hole in the middle of address space. |
47 | This doesn't give that many random bits. | 47 | * To save memory make sure it is still in the same PTE as the stack |
48 | 48 | * top. This doesn't give that many random bits. | |
49 | Only used for the 64-bit and x32 vdsos. */ | 49 | * |
50 | * Note that this algorithm is imperfect: the distribution of the vdso | ||
51 | * start address within a PMD is biased toward the end. | ||
52 | * | ||
53 | * Only used for the 64-bit and x32 vdsos. | ||
54 | */ | ||
50 | static unsigned long vdso_addr(unsigned long start, unsigned len) | 55 | static unsigned long vdso_addr(unsigned long start, unsigned len) |
51 | { | 56 | { |
52 | #ifdef CONFIG_X86_32 | 57 | #ifdef CONFIG_X86_32 |
@@ -54,22 +59,30 @@ static unsigned long vdso_addr(unsigned long start, unsigned len) | |||
54 | #else | 59 | #else |
55 | unsigned long addr, end; | 60 | unsigned long addr, end; |
56 | unsigned offset; | 61 | unsigned offset; |
57 | end = (start + PMD_SIZE - 1) & PMD_MASK; | 62 | |
63 | /* | ||
64 | * Round up the start address. It can start out unaligned as a result | ||
65 | * of stack start randomization. | ||
66 | */ | ||
67 | start = PAGE_ALIGN(start); | ||
68 | |||
69 | /* Round the lowest possible end address up to a PMD boundary. */ | ||
70 | end = (start + len + PMD_SIZE - 1) & PMD_MASK; | ||
58 | if (end >= TASK_SIZE_MAX) | 71 | if (end >= TASK_SIZE_MAX) |
59 | end = TASK_SIZE_MAX; | 72 | end = TASK_SIZE_MAX; |
60 | end -= len; | 73 | end -= len; |
61 | /* This loses some more bits than a modulo, but is cheaper */ | 74 | |
62 | offset = get_random_int() & (PTRS_PER_PTE - 1); | 75 | if (end > start) { |
63 | addr = start + (offset << PAGE_SHIFT); | 76 | offset = get_random_int() % (((end - start) >> PAGE_SHIFT) + 1); |
64 | if (addr >= end) | 77 | addr = start + (offset << PAGE_SHIFT); |
65 | addr = end; | 78 | } else { |
79 | addr = start; | ||
80 | } | ||
66 | 81 | ||
67 | /* | 82 | /* |
68 | * page-align it here so that get_unmapped_area doesn't | 83 | * Forcibly align the final address in case we have a hardware |
69 | * align it wrongfully again to the next page. addr can come in 4K | 84 | * issue that requires alignment for performance reasons. |
70 | * unaligned here as a result of stack start randomization. | ||
71 | */ | 85 | */ |
72 | addr = PAGE_ALIGN(addr); | ||
73 | addr = align_vdso_addr(addr); | 86 | addr = align_vdso_addr(addr); |
74 | 87 | ||
75 | return addr; | 88 | return addr; |
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 6bf3a13e3e0f..78a881b7fc41 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <xen/interface/physdev.h> | 40 | #include <xen/interface/physdev.h> |
41 | #include <xen/interface/vcpu.h> | 41 | #include <xen/interface/vcpu.h> |
42 | #include <xen/interface/memory.h> | 42 | #include <xen/interface/memory.h> |
43 | #include <xen/interface/nmi.h> | ||
43 | #include <xen/interface/xen-mca.h> | 44 | #include <xen/interface/xen-mca.h> |
44 | #include <xen/features.h> | 45 | #include <xen/features.h> |
45 | #include <xen/page.h> | 46 | #include <xen/page.h> |
@@ -66,6 +67,7 @@ | |||
66 | #include <asm/reboot.h> | 67 | #include <asm/reboot.h> |
67 | #include <asm/stackprotector.h> | 68 | #include <asm/stackprotector.h> |
68 | #include <asm/hypervisor.h> | 69 | #include <asm/hypervisor.h> |
70 | #include <asm/mach_traps.h> | ||
69 | #include <asm/mwait.h> | 71 | #include <asm/mwait.h> |
70 | #include <asm/pci_x86.h> | 72 | #include <asm/pci_x86.h> |
71 | #include <asm/pat.h> | 73 | #include <asm/pat.h> |
@@ -1351,6 +1353,21 @@ static const struct machine_ops xen_machine_ops __initconst = { | |||
1351 | .emergency_restart = xen_emergency_restart, | 1353 | .emergency_restart = xen_emergency_restart, |
1352 | }; | 1354 | }; |
1353 | 1355 | ||
1356 | static unsigned char xen_get_nmi_reason(void) | ||
1357 | { | ||
1358 | unsigned char reason = 0; | ||
1359 | |||
1360 | /* Construct a value which looks like it came from port 0x61. */ | ||
1361 | if (test_bit(_XEN_NMIREASON_io_error, | ||
1362 | &HYPERVISOR_shared_info->arch.nmi_reason)) | ||
1363 | reason |= NMI_REASON_IOCHK; | ||
1364 | if (test_bit(_XEN_NMIREASON_pci_serr, | ||
1365 | &HYPERVISOR_shared_info->arch.nmi_reason)) | ||
1366 | reason |= NMI_REASON_SERR; | ||
1367 | |||
1368 | return reason; | ||
1369 | } | ||
1370 | |||
1354 | static void __init xen_boot_params_init_edd(void) | 1371 | static void __init xen_boot_params_init_edd(void) |
1355 | { | 1372 | { |
1356 | #if IS_ENABLED(CONFIG_EDD) | 1373 | #if IS_ENABLED(CONFIG_EDD) |
@@ -1535,9 +1552,12 @@ asmlinkage __visible void __init xen_start_kernel(void) | |||
1535 | pv_info = xen_info; | 1552 | pv_info = xen_info; |
1536 | pv_init_ops = xen_init_ops; | 1553 | pv_init_ops = xen_init_ops; |
1537 | pv_apic_ops = xen_apic_ops; | 1554 | pv_apic_ops = xen_apic_ops; |
1538 | if (!xen_pvh_domain()) | 1555 | if (!xen_pvh_domain()) { |
1539 | pv_cpu_ops = xen_cpu_ops; | 1556 | pv_cpu_ops = xen_cpu_ops; |
1540 | 1557 | ||
1558 | x86_platform.get_nmi_reason = xen_get_nmi_reason; | ||
1559 | } | ||
1560 | |||
1541 | if (xen_feature(XENFEAT_auto_translated_physmap)) | 1561 | if (xen_feature(XENFEAT_auto_translated_physmap)) |
1542 | x86_init.resources.memory_setup = xen_auto_xlated_memory_setup; | 1562 | x86_init.resources.memory_setup = xen_auto_xlated_memory_setup; |
1543 | else | 1563 | else |
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c index edbc7a63fd73..70fb5075c901 100644 --- a/arch/x86/xen/p2m.c +++ b/arch/x86/xen/p2m.c | |||
@@ -167,10 +167,13 @@ static void * __ref alloc_p2m_page(void) | |||
167 | return (void *)__get_free_page(GFP_KERNEL | __GFP_REPEAT); | 167 | return (void *)__get_free_page(GFP_KERNEL | __GFP_REPEAT); |
168 | } | 168 | } |
169 | 169 | ||
170 | /* Only to be called in case of a race for a page just allocated! */ | 170 | static void __ref free_p2m_page(void *p) |
171 | static void free_p2m_page(void *p) | ||
172 | { | 171 | { |
173 | BUG_ON(!slab_is_available()); | 172 | if (unlikely(!slab_is_available())) { |
173 | free_bootmem((unsigned long)p, PAGE_SIZE); | ||
174 | return; | ||
175 | } | ||
176 | |||
174 | free_page((unsigned long)p); | 177 | free_page((unsigned long)p); |
175 | } | 178 | } |
176 | 179 | ||
@@ -375,7 +378,7 @@ static void __init xen_rebuild_p2m_list(unsigned long *p2m) | |||
375 | p2m_missing_pte : p2m_identity_pte; | 378 | p2m_missing_pte : p2m_identity_pte; |
376 | for (i = 0; i < PMDS_PER_MID_PAGE; i++) { | 379 | for (i = 0; i < PMDS_PER_MID_PAGE; i++) { |
377 | pmdp = populate_extra_pmd( | 380 | pmdp = populate_extra_pmd( |
378 | (unsigned long)(p2m + pfn + i * PTRS_PER_PTE)); | 381 | (unsigned long)(p2m + pfn) + i * PMD_SIZE); |
379 | set_pmd(pmdp, __pmd(__pa(ptep) | _KERNPG_TABLE)); | 382 | set_pmd(pmdp, __pmd(__pa(ptep) | _KERNPG_TABLE)); |
380 | } | 383 | } |
381 | } | 384 | } |
@@ -436,10 +439,9 @@ EXPORT_SYMBOL_GPL(get_phys_to_machine); | |||
436 | * a new pmd is to replace p2m_missing_pte or p2m_identity_pte by a individual | 439 | * a new pmd is to replace p2m_missing_pte or p2m_identity_pte by a individual |
437 | * pmd. In case of PAE/x86-32 there are multiple pmds to allocate! | 440 | * pmd. In case of PAE/x86-32 there are multiple pmds to allocate! |
438 | */ | 441 | */ |
439 | static pte_t *alloc_p2m_pmd(unsigned long addr, pte_t *ptep, pte_t *pte_pg) | 442 | static pte_t *alloc_p2m_pmd(unsigned long addr, pte_t *pte_pg) |
440 | { | 443 | { |
441 | pte_t *ptechk; | 444 | pte_t *ptechk; |
442 | pte_t *pteret = ptep; | ||
443 | pte_t *pte_newpg[PMDS_PER_MID_PAGE]; | 445 | pte_t *pte_newpg[PMDS_PER_MID_PAGE]; |
444 | pmd_t *pmdp; | 446 | pmd_t *pmdp; |
445 | unsigned int level; | 447 | unsigned int level; |
@@ -473,8 +475,6 @@ static pte_t *alloc_p2m_pmd(unsigned long addr, pte_t *ptep, pte_t *pte_pg) | |||
473 | if (ptechk == pte_pg) { | 475 | if (ptechk == pte_pg) { |
474 | set_pmd(pmdp, | 476 | set_pmd(pmdp, |
475 | __pmd(__pa(pte_newpg[i]) | _KERNPG_TABLE)); | 477 | __pmd(__pa(pte_newpg[i]) | _KERNPG_TABLE)); |
476 | if (vaddr == (addr & ~(PMD_SIZE - 1))) | ||
477 | pteret = pte_offset_kernel(pmdp, addr); | ||
478 | pte_newpg[i] = NULL; | 478 | pte_newpg[i] = NULL; |
479 | } | 479 | } |
480 | 480 | ||
@@ -488,7 +488,7 @@ static pte_t *alloc_p2m_pmd(unsigned long addr, pte_t *ptep, pte_t *pte_pg) | |||
488 | vaddr += PMD_SIZE; | 488 | vaddr += PMD_SIZE; |
489 | } | 489 | } |
490 | 490 | ||
491 | return pteret; | 491 | return lookup_address(addr, &level); |
492 | } | 492 | } |
493 | 493 | ||
494 | /* | 494 | /* |
@@ -517,7 +517,7 @@ static bool alloc_p2m(unsigned long pfn) | |||
517 | 517 | ||
518 | if (pte_pg == p2m_missing_pte || pte_pg == p2m_identity_pte) { | 518 | if (pte_pg == p2m_missing_pte || pte_pg == p2m_identity_pte) { |
519 | /* PMD level is missing, allocate a new one */ | 519 | /* PMD level is missing, allocate a new one */ |
520 | ptep = alloc_p2m_pmd(addr, ptep, pte_pg); | 520 | ptep = alloc_p2m_pmd(addr, pte_pg); |
521 | if (!ptep) | 521 | if (!ptep) |
522 | return false; | 522 | return false; |
523 | } | 523 | } |
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index dfd77dec8e2b..865e56cea7a0 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c | |||
@@ -140,7 +140,7 @@ static void __init xen_del_extra_mem(u64 start, u64 size) | |||
140 | unsigned long __ref xen_chk_extra_mem(unsigned long pfn) | 140 | unsigned long __ref xen_chk_extra_mem(unsigned long pfn) |
141 | { | 141 | { |
142 | int i; | 142 | int i; |
143 | unsigned long addr = PFN_PHYS(pfn); | 143 | phys_addr_t addr = PFN_PHYS(pfn); |
144 | 144 | ||
145 | for (i = 0; i < XEN_EXTRA_MEM_MAX_REGIONS; i++) { | 145 | for (i = 0; i < XEN_EXTRA_MEM_MAX_REGIONS; i++) { |
146 | if (addr >= xen_extra_mem[i].start && | 146 | if (addr >= xen_extra_mem[i].start && |
@@ -160,6 +160,8 @@ void __init xen_inv_extra_mem(void) | |||
160 | int i; | 160 | int i; |
161 | 161 | ||
162 | for (i = 0; i < XEN_EXTRA_MEM_MAX_REGIONS; i++) { | 162 | for (i = 0; i < XEN_EXTRA_MEM_MAX_REGIONS; i++) { |
163 | if (!xen_extra_mem[i].size) | ||
164 | continue; | ||
163 | pfn_s = PFN_DOWN(xen_extra_mem[i].start); | 165 | pfn_s = PFN_DOWN(xen_extra_mem[i].start); |
164 | pfn_e = PFN_UP(xen_extra_mem[i].start + xen_extra_mem[i].size); | 166 | pfn_e = PFN_UP(xen_extra_mem[i].start + xen_extra_mem[i].size); |
165 | for (pfn = pfn_s; pfn < pfn_e; pfn++) | 167 | for (pfn = pfn_s; pfn < pfn_e; pfn++) |
@@ -229,15 +231,14 @@ static int __init xen_free_mfn(unsigned long mfn) | |||
229 | * as a fallback if the remapping fails. | 231 | * as a fallback if the remapping fails. |
230 | */ | 232 | */ |
231 | static void __init xen_set_identity_and_release_chunk(unsigned long start_pfn, | 233 | static void __init xen_set_identity_and_release_chunk(unsigned long start_pfn, |
232 | unsigned long end_pfn, unsigned long nr_pages, unsigned long *identity, | 234 | unsigned long end_pfn, unsigned long nr_pages, unsigned long *released) |
233 | unsigned long *released) | ||
234 | { | 235 | { |
235 | unsigned long len = 0; | ||
236 | unsigned long pfn, end; | 236 | unsigned long pfn, end; |
237 | int ret; | 237 | int ret; |
238 | 238 | ||
239 | WARN_ON(start_pfn > end_pfn); | 239 | WARN_ON(start_pfn > end_pfn); |
240 | 240 | ||
241 | /* Release pages first. */ | ||
241 | end = min(end_pfn, nr_pages); | 242 | end = min(end_pfn, nr_pages); |
242 | for (pfn = start_pfn; pfn < end; pfn++) { | 243 | for (pfn = start_pfn; pfn < end; pfn++) { |
243 | unsigned long mfn = pfn_to_mfn(pfn); | 244 | unsigned long mfn = pfn_to_mfn(pfn); |
@@ -250,16 +251,14 @@ static void __init xen_set_identity_and_release_chunk(unsigned long start_pfn, | |||
250 | WARN(ret != 1, "Failed to release pfn %lx err=%d\n", pfn, ret); | 251 | WARN(ret != 1, "Failed to release pfn %lx err=%d\n", pfn, ret); |
251 | 252 | ||
252 | if (ret == 1) { | 253 | if (ret == 1) { |
254 | (*released)++; | ||
253 | if (!__set_phys_to_machine(pfn, INVALID_P2M_ENTRY)) | 255 | if (!__set_phys_to_machine(pfn, INVALID_P2M_ENTRY)) |
254 | break; | 256 | break; |
255 | len++; | ||
256 | } else | 257 | } else |
257 | break; | 258 | break; |
258 | } | 259 | } |
259 | 260 | ||
260 | /* Need to release pages first */ | 261 | set_phys_range_identity(start_pfn, end_pfn); |
261 | *released += len; | ||
262 | *identity += set_phys_range_identity(start_pfn, end_pfn); | ||
263 | } | 262 | } |
264 | 263 | ||
265 | /* | 264 | /* |
@@ -287,7 +286,7 @@ static void __init xen_update_mem_tables(unsigned long pfn, unsigned long mfn) | |||
287 | } | 286 | } |
288 | 287 | ||
289 | /* Update kernel mapping, but not for highmem. */ | 288 | /* Update kernel mapping, but not for highmem. */ |
290 | if ((pfn << PAGE_SHIFT) >= __pa(high_memory)) | 289 | if (pfn >= PFN_UP(__pa(high_memory - 1))) |
291 | return; | 290 | return; |
292 | 291 | ||
293 | if (HYPERVISOR_update_va_mapping((unsigned long)__va(pfn << PAGE_SHIFT), | 292 | if (HYPERVISOR_update_va_mapping((unsigned long)__va(pfn << PAGE_SHIFT), |
@@ -318,7 +317,6 @@ static void __init xen_do_set_identity_and_remap_chunk( | |||
318 | unsigned long ident_pfn_iter, remap_pfn_iter; | 317 | unsigned long ident_pfn_iter, remap_pfn_iter; |
319 | unsigned long ident_end_pfn = start_pfn + size; | 318 | unsigned long ident_end_pfn = start_pfn + size; |
320 | unsigned long left = size; | 319 | unsigned long left = size; |
321 | unsigned long ident_cnt = 0; | ||
322 | unsigned int i, chunk; | 320 | unsigned int i, chunk; |
323 | 321 | ||
324 | WARN_ON(size == 0); | 322 | WARN_ON(size == 0); |
@@ -347,8 +345,7 @@ static void __init xen_do_set_identity_and_remap_chunk( | |||
347 | xen_remap_mfn = mfn; | 345 | xen_remap_mfn = mfn; |
348 | 346 | ||
349 | /* Set identity map */ | 347 | /* Set identity map */ |
350 | ident_cnt += set_phys_range_identity(ident_pfn_iter, | 348 | set_phys_range_identity(ident_pfn_iter, ident_pfn_iter + chunk); |
351 | ident_pfn_iter + chunk); | ||
352 | 349 | ||
353 | left -= chunk; | 350 | left -= chunk; |
354 | } | 351 | } |
@@ -371,7 +368,7 @@ static void __init xen_do_set_identity_and_remap_chunk( | |||
371 | static unsigned long __init xen_set_identity_and_remap_chunk( | 368 | static unsigned long __init xen_set_identity_and_remap_chunk( |
372 | const struct e820entry *list, size_t map_size, unsigned long start_pfn, | 369 | const struct e820entry *list, size_t map_size, unsigned long start_pfn, |
373 | unsigned long end_pfn, unsigned long nr_pages, unsigned long remap_pfn, | 370 | unsigned long end_pfn, unsigned long nr_pages, unsigned long remap_pfn, |
374 | unsigned long *identity, unsigned long *released) | 371 | unsigned long *released, unsigned long *remapped) |
375 | { | 372 | { |
376 | unsigned long pfn; | 373 | unsigned long pfn; |
377 | unsigned long i = 0; | 374 | unsigned long i = 0; |
@@ -386,8 +383,7 @@ static unsigned long __init xen_set_identity_and_remap_chunk( | |||
386 | /* Do not remap pages beyond the current allocation */ | 383 | /* Do not remap pages beyond the current allocation */ |
387 | if (cur_pfn >= nr_pages) { | 384 | if (cur_pfn >= nr_pages) { |
388 | /* Identity map remaining pages */ | 385 | /* Identity map remaining pages */ |
389 | *identity += set_phys_range_identity(cur_pfn, | 386 | set_phys_range_identity(cur_pfn, cur_pfn + size); |
390 | cur_pfn + size); | ||
391 | break; | 387 | break; |
392 | } | 388 | } |
393 | if (cur_pfn + size > nr_pages) | 389 | if (cur_pfn + size > nr_pages) |
@@ -398,7 +394,7 @@ static unsigned long __init xen_set_identity_and_remap_chunk( | |||
398 | if (!remap_range_size) { | 394 | if (!remap_range_size) { |
399 | pr_warning("Unable to find available pfn range, not remapping identity pages\n"); | 395 | pr_warning("Unable to find available pfn range, not remapping identity pages\n"); |
400 | xen_set_identity_and_release_chunk(cur_pfn, | 396 | xen_set_identity_and_release_chunk(cur_pfn, |
401 | cur_pfn + left, nr_pages, identity, released); | 397 | cur_pfn + left, nr_pages, released); |
402 | break; | 398 | break; |
403 | } | 399 | } |
404 | /* Adjust size to fit in current e820 RAM region */ | 400 | /* Adjust size to fit in current e820 RAM region */ |
@@ -410,7 +406,7 @@ static unsigned long __init xen_set_identity_and_remap_chunk( | |||
410 | /* Update variables to reflect new mappings. */ | 406 | /* Update variables to reflect new mappings. */ |
411 | i += size; | 407 | i += size; |
412 | remap_pfn += size; | 408 | remap_pfn += size; |
413 | *identity += size; | 409 | *remapped += size; |
414 | } | 410 | } |
415 | 411 | ||
416 | /* | 412 | /* |
@@ -427,13 +423,13 @@ static unsigned long __init xen_set_identity_and_remap_chunk( | |||
427 | 423 | ||
428 | static void __init xen_set_identity_and_remap( | 424 | static void __init xen_set_identity_and_remap( |
429 | const struct e820entry *list, size_t map_size, unsigned long nr_pages, | 425 | const struct e820entry *list, size_t map_size, unsigned long nr_pages, |
430 | unsigned long *released) | 426 | unsigned long *released, unsigned long *remapped) |
431 | { | 427 | { |
432 | phys_addr_t start = 0; | 428 | phys_addr_t start = 0; |
433 | unsigned long identity = 0; | ||
434 | unsigned long last_pfn = nr_pages; | 429 | unsigned long last_pfn = nr_pages; |
435 | const struct e820entry *entry; | 430 | const struct e820entry *entry; |
436 | unsigned long num_released = 0; | 431 | unsigned long num_released = 0; |
432 | unsigned long num_remapped = 0; | ||
437 | int i; | 433 | int i; |
438 | 434 | ||
439 | /* | 435 | /* |
@@ -460,14 +456,14 @@ static void __init xen_set_identity_and_remap( | |||
460 | last_pfn = xen_set_identity_and_remap_chunk( | 456 | last_pfn = xen_set_identity_and_remap_chunk( |
461 | list, map_size, start_pfn, | 457 | list, map_size, start_pfn, |
462 | end_pfn, nr_pages, last_pfn, | 458 | end_pfn, nr_pages, last_pfn, |
463 | &identity, &num_released); | 459 | &num_released, &num_remapped); |
464 | start = end; | 460 | start = end; |
465 | } | 461 | } |
466 | } | 462 | } |
467 | 463 | ||
468 | *released = num_released; | 464 | *released = num_released; |
465 | *remapped = num_remapped; | ||
469 | 466 | ||
470 | pr_info("Set %ld page(s) to 1-1 mapping\n", identity); | ||
471 | pr_info("Released %ld page(s)\n", num_released); | 467 | pr_info("Released %ld page(s)\n", num_released); |
472 | } | 468 | } |
473 | 469 | ||
@@ -586,6 +582,7 @@ char * __init xen_memory_setup(void) | |||
586 | struct xen_memory_map memmap; | 582 | struct xen_memory_map memmap; |
587 | unsigned long max_pages; | 583 | unsigned long max_pages; |
588 | unsigned long extra_pages = 0; | 584 | unsigned long extra_pages = 0; |
585 | unsigned long remapped_pages; | ||
589 | int i; | 586 | int i; |
590 | int op; | 587 | int op; |
591 | 588 | ||
@@ -635,9 +632,10 @@ char * __init xen_memory_setup(void) | |||
635 | * underlying RAM. | 632 | * underlying RAM. |
636 | */ | 633 | */ |
637 | xen_set_identity_and_remap(map, memmap.nr_entries, max_pfn, | 634 | xen_set_identity_and_remap(map, memmap.nr_entries, max_pfn, |
638 | &xen_released_pages); | 635 | &xen_released_pages, &remapped_pages); |
639 | 636 | ||
640 | extra_pages += xen_released_pages; | 637 | extra_pages += xen_released_pages; |
638 | extra_pages += remapped_pages; | ||
641 | 639 | ||
642 | /* | 640 | /* |
643 | * Clamp the amount of extra memory to a EXTRA_MEM_RATIO | 641 | * Clamp the amount of extra memory to a EXTRA_MEM_RATIO |
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index f473d268d387..69087341d9ae 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c | |||
@@ -391,7 +391,7 @@ static const struct clock_event_device *xen_clockevent = | |||
391 | 391 | ||
392 | struct xen_clock_event_device { | 392 | struct xen_clock_event_device { |
393 | struct clock_event_device evt; | 393 | struct clock_event_device evt; |
394 | char *name; | 394 | char name[16]; |
395 | }; | 395 | }; |
396 | static DEFINE_PER_CPU(struct xen_clock_event_device, xen_clock_events) = { .evt.irq = -1 }; | 396 | static DEFINE_PER_CPU(struct xen_clock_event_device, xen_clock_events) = { .evt.irq = -1 }; |
397 | 397 | ||
@@ -420,46 +420,38 @@ void xen_teardown_timer(int cpu) | |||
420 | if (evt->irq >= 0) { | 420 | if (evt->irq >= 0) { |
421 | unbind_from_irqhandler(evt->irq, NULL); | 421 | unbind_from_irqhandler(evt->irq, NULL); |
422 | evt->irq = -1; | 422 | evt->irq = -1; |
423 | kfree(per_cpu(xen_clock_events, cpu).name); | ||
424 | per_cpu(xen_clock_events, cpu).name = NULL; | ||
425 | } | 423 | } |
426 | } | 424 | } |
427 | 425 | ||
428 | void xen_setup_timer(int cpu) | 426 | void xen_setup_timer(int cpu) |
429 | { | 427 | { |
430 | char *name; | 428 | struct xen_clock_event_device *xevt = &per_cpu(xen_clock_events, cpu); |
431 | struct clock_event_device *evt; | 429 | struct clock_event_device *evt = &xevt->evt; |
432 | int irq; | 430 | int irq; |
433 | 431 | ||
434 | evt = &per_cpu(xen_clock_events, cpu).evt; | ||
435 | WARN(evt->irq >= 0, "IRQ%d for CPU%d is already allocated\n", evt->irq, cpu); | 432 | WARN(evt->irq >= 0, "IRQ%d for CPU%d is already allocated\n", evt->irq, cpu); |
436 | if (evt->irq >= 0) | 433 | if (evt->irq >= 0) |
437 | xen_teardown_timer(cpu); | 434 | xen_teardown_timer(cpu); |
438 | 435 | ||
439 | printk(KERN_INFO "installing Xen timer for CPU %d\n", cpu); | 436 | printk(KERN_INFO "installing Xen timer for CPU %d\n", cpu); |
440 | 437 | ||
441 | name = kasprintf(GFP_KERNEL, "timer%d", cpu); | 438 | snprintf(xevt->name, sizeof(xevt->name), "timer%d", cpu); |
442 | if (!name) | ||
443 | name = "<timer kasprintf failed>"; | ||
444 | 439 | ||
445 | irq = bind_virq_to_irqhandler(VIRQ_TIMER, cpu, xen_timer_interrupt, | 440 | irq = bind_virq_to_irqhandler(VIRQ_TIMER, cpu, xen_timer_interrupt, |
446 | IRQF_PERCPU|IRQF_NOBALANCING|IRQF_TIMER| | 441 | IRQF_PERCPU|IRQF_NOBALANCING|IRQF_TIMER| |
447 | IRQF_FORCE_RESUME|IRQF_EARLY_RESUME, | 442 | IRQF_FORCE_RESUME|IRQF_EARLY_RESUME, |
448 | name, NULL); | 443 | xevt->name, NULL); |
449 | (void)xen_set_irq_priority(irq, XEN_IRQ_PRIORITY_MAX); | 444 | (void)xen_set_irq_priority(irq, XEN_IRQ_PRIORITY_MAX); |
450 | 445 | ||
451 | memcpy(evt, xen_clockevent, sizeof(*evt)); | 446 | memcpy(evt, xen_clockevent, sizeof(*evt)); |
452 | 447 | ||
453 | evt->cpumask = cpumask_of(cpu); | 448 | evt->cpumask = cpumask_of(cpu); |
454 | evt->irq = irq; | 449 | evt->irq = irq; |
455 | per_cpu(xen_clock_events, cpu).name = name; | ||
456 | } | 450 | } |
457 | 451 | ||
458 | 452 | ||
459 | void xen_setup_cpu_clockevents(void) | 453 | void xen_setup_cpu_clockevents(void) |
460 | { | 454 | { |
461 | BUG_ON(preemptible()); | ||
462 | |||
463 | clockevents_register_device(this_cpu_ptr(&xen_clock_events.evt)); | 455 | clockevents_register_device(this_cpu_ptr(&xen_clock_events.evt)); |
464 | } | 456 | } |
465 | 457 | ||