aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/Kconfig1
-rw-r--r--arch/x86/Makefile4
-rw-r--r--arch/x86/events/intel/uncore.h33
-rw-r--r--arch/x86/events/intel/uncore_snb.c121
-rw-r--r--arch/x86/include/asm/mce.h2
-rw-r--r--arch/x86/include/asm/mshyperv.h2
-rw-r--r--arch/x86/include/asm/page_64_types.h12
-rw-r--r--arch/x86/include/asm/pgtable_64_types.h4
-rw-r--r--arch/x86/include/asm/qspinlock.h13
-rw-r--r--arch/x86/include/asm/xen/page.h35
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce.c6
-rw-r--r--arch/x86/kernel/cpu/mshyperv.c11
-rw-r--r--arch/x86/kernel/cpu/vmware.c2
-rw-r--r--arch/x86/kernel/ldt.c59
-rw-r--r--arch/x86/kernel/vsmp_64.c84
-rw-r--r--arch/x86/xen/mmu_pv.c6
-rw-r--r--arch/x86/xen/p2m.c3
-rw-r--r--arch/x86/xen/spinlock.c14
18 files changed, 268 insertions, 144 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index ba7e3464ee92..9d734f3c8234 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -525,7 +525,6 @@ config X86_VSMP
525 bool "ScaleMP vSMP" 525 bool "ScaleMP vSMP"
526 select HYPERVISOR_GUEST 526 select HYPERVISOR_GUEST
527 select PARAVIRT 527 select PARAVIRT
528 select PARAVIRT_XXL
529 depends on X86_64 && PCI 528 depends on X86_64 && PCI
530 depends on X86_EXTENDED_PLATFORM 529 depends on X86_EXTENDED_PLATFORM
531 depends on SMP 530 depends on SMP
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 5b562e464009..88398fdf8129 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -213,8 +213,6 @@ ifdef CONFIG_X86_64
213KBUILD_LDFLAGS += $(call ld-option, -z max-page-size=0x200000) 213KBUILD_LDFLAGS += $(call ld-option, -z max-page-size=0x200000)
214endif 214endif
215 215
216# Speed up the build
217KBUILD_CFLAGS += -pipe
218# Workaround for a gcc prelease that unfortunately was shipped in a suse release 216# Workaround for a gcc prelease that unfortunately was shipped in a suse release
219KBUILD_CFLAGS += -Wno-sign-compare 217KBUILD_CFLAGS += -Wno-sign-compare
220# 218#
@@ -239,7 +237,7 @@ archheaders:
239archmacros: 237archmacros:
240 $(Q)$(MAKE) $(build)=arch/x86/kernel arch/x86/kernel/macros.s 238 $(Q)$(MAKE) $(build)=arch/x86/kernel arch/x86/kernel/macros.s
241 239
242ASM_MACRO_FLAGS = -Wa,arch/x86/kernel/macros.s -Wa,- 240ASM_MACRO_FLAGS = -Wa,arch/x86/kernel/macros.s
243export ASM_MACRO_FLAGS 241export ASM_MACRO_FLAGS
244KBUILD_CFLAGS += $(ASM_MACRO_FLAGS) 242KBUILD_CFLAGS += $(ASM_MACRO_FLAGS)
245 243
diff --git a/arch/x86/events/intel/uncore.h b/arch/x86/events/intel/uncore.h
index e17ab885b1e9..cb46d602a6b8 100644
--- a/arch/x86/events/intel/uncore.h
+++ b/arch/x86/events/intel/uncore.h
@@ -129,8 +129,15 @@ struct intel_uncore_box {
129 struct intel_uncore_extra_reg shared_regs[0]; 129 struct intel_uncore_extra_reg shared_regs[0];
130}; 130};
131 131
132#define UNCORE_BOX_FLAG_INITIATED 0 132/* CFL uncore 8th cbox MSRs */
133#define UNCORE_BOX_FLAG_CTL_OFFS8 1 /* event config registers are 8-byte apart */ 133#define CFL_UNC_CBO_7_PERFEVTSEL0 0xf70
134#define CFL_UNC_CBO_7_PER_CTR0 0xf76
135
136#define UNCORE_BOX_FLAG_INITIATED 0
137/* event config registers are 8-byte apart */
138#define UNCORE_BOX_FLAG_CTL_OFFS8 1
139/* CFL 8th CBOX has different MSR space */
140#define UNCORE_BOX_FLAG_CFL8_CBOX_MSR_OFFS 2
134 141
135struct uncore_event_desc { 142struct uncore_event_desc {
136 struct kobj_attribute attr; 143 struct kobj_attribute attr;
@@ -297,17 +304,27 @@ unsigned int uncore_freerunning_counter(struct intel_uncore_box *box,
297static inline 304static inline
298unsigned uncore_msr_event_ctl(struct intel_uncore_box *box, int idx) 305unsigned uncore_msr_event_ctl(struct intel_uncore_box *box, int idx)
299{ 306{
300 return box->pmu->type->event_ctl + 307 if (test_bit(UNCORE_BOX_FLAG_CFL8_CBOX_MSR_OFFS, &box->flags)) {
301 (box->pmu->type->pair_ctr_ctl ? 2 * idx : idx) + 308 return CFL_UNC_CBO_7_PERFEVTSEL0 +
302 uncore_msr_box_offset(box); 309 (box->pmu->type->pair_ctr_ctl ? 2 * idx : idx);
310 } else {
311 return box->pmu->type->event_ctl +
312 (box->pmu->type->pair_ctr_ctl ? 2 * idx : idx) +
313 uncore_msr_box_offset(box);
314 }
303} 315}
304 316
305static inline 317static inline
306unsigned uncore_msr_perf_ctr(struct intel_uncore_box *box, int idx) 318unsigned uncore_msr_perf_ctr(struct intel_uncore_box *box, int idx)
307{ 319{
308 return box->pmu->type->perf_ctr + 320 if (test_bit(UNCORE_BOX_FLAG_CFL8_CBOX_MSR_OFFS, &box->flags)) {
309 (box->pmu->type->pair_ctr_ctl ? 2 * idx : idx) + 321 return CFL_UNC_CBO_7_PER_CTR0 +
310 uncore_msr_box_offset(box); 322 (box->pmu->type->pair_ctr_ctl ? 2 * idx : idx);
323 } else {
324 return box->pmu->type->perf_ctr +
325 (box->pmu->type->pair_ctr_ctl ? 2 * idx : idx) +
326 uncore_msr_box_offset(box);
327 }
311} 328}
312 329
313static inline 330static inline
diff --git a/arch/x86/events/intel/uncore_snb.c b/arch/x86/events/intel/uncore_snb.c
index 8527c3e1038b..2593b0d7aeee 100644
--- a/arch/x86/events/intel/uncore_snb.c
+++ b/arch/x86/events/intel/uncore_snb.c
@@ -15,6 +15,25 @@
15#define PCI_DEVICE_ID_INTEL_SKL_HQ_IMC 0x1910 15#define PCI_DEVICE_ID_INTEL_SKL_HQ_IMC 0x1910
16#define PCI_DEVICE_ID_INTEL_SKL_SD_IMC 0x190f 16#define PCI_DEVICE_ID_INTEL_SKL_SD_IMC 0x190f
17#define PCI_DEVICE_ID_INTEL_SKL_SQ_IMC 0x191f 17#define PCI_DEVICE_ID_INTEL_SKL_SQ_IMC 0x191f
18#define PCI_DEVICE_ID_INTEL_KBL_Y_IMC 0x590c
19#define PCI_DEVICE_ID_INTEL_KBL_U_IMC 0x5904
20#define PCI_DEVICE_ID_INTEL_KBL_UQ_IMC 0x5914
21#define PCI_DEVICE_ID_INTEL_KBL_SD_IMC 0x590f
22#define PCI_DEVICE_ID_INTEL_KBL_SQ_IMC 0x591f
23#define PCI_DEVICE_ID_INTEL_CFL_2U_IMC 0x3ecc
24#define PCI_DEVICE_ID_INTEL_CFL_4U_IMC 0x3ed0
25#define PCI_DEVICE_ID_INTEL_CFL_4H_IMC 0x3e10
26#define PCI_DEVICE_ID_INTEL_CFL_6H_IMC 0x3ec4
27#define PCI_DEVICE_ID_INTEL_CFL_2S_D_IMC 0x3e0f
28#define PCI_DEVICE_ID_INTEL_CFL_4S_D_IMC 0x3e1f
29#define PCI_DEVICE_ID_INTEL_CFL_6S_D_IMC 0x3ec2
30#define PCI_DEVICE_ID_INTEL_CFL_8S_D_IMC 0x3e30
31#define PCI_DEVICE_ID_INTEL_CFL_4S_W_IMC 0x3e18
32#define PCI_DEVICE_ID_INTEL_CFL_6S_W_IMC 0x3ec6
33#define PCI_DEVICE_ID_INTEL_CFL_8S_W_IMC 0x3e31
34#define PCI_DEVICE_ID_INTEL_CFL_4S_S_IMC 0x3e33
35#define PCI_DEVICE_ID_INTEL_CFL_6S_S_IMC 0x3eca
36#define PCI_DEVICE_ID_INTEL_CFL_8S_S_IMC 0x3e32
18 37
19/* SNB event control */ 38/* SNB event control */
20#define SNB_UNC_CTL_EV_SEL_MASK 0x000000ff 39#define SNB_UNC_CTL_EV_SEL_MASK 0x000000ff
@@ -202,6 +221,10 @@ static void skl_uncore_msr_init_box(struct intel_uncore_box *box)
202 wrmsrl(SKL_UNC_PERF_GLOBAL_CTL, 221 wrmsrl(SKL_UNC_PERF_GLOBAL_CTL,
203 SNB_UNC_GLOBAL_CTL_EN | SKL_UNC_GLOBAL_CTL_CORE_ALL); 222 SNB_UNC_GLOBAL_CTL_EN | SKL_UNC_GLOBAL_CTL_CORE_ALL);
204 } 223 }
224
225 /* The 8th CBOX has different MSR space */
226 if (box->pmu->pmu_idx == 7)
227 __set_bit(UNCORE_BOX_FLAG_CFL8_CBOX_MSR_OFFS, &box->flags);
205} 228}
206 229
207static void skl_uncore_msr_enable_box(struct intel_uncore_box *box) 230static void skl_uncore_msr_enable_box(struct intel_uncore_box *box)
@@ -228,7 +251,7 @@ static struct intel_uncore_ops skl_uncore_msr_ops = {
228static struct intel_uncore_type skl_uncore_cbox = { 251static struct intel_uncore_type skl_uncore_cbox = {
229 .name = "cbox", 252 .name = "cbox",
230 .num_counters = 4, 253 .num_counters = 4,
231 .num_boxes = 5, 254 .num_boxes = 8,
232 .perf_ctr_bits = 44, 255 .perf_ctr_bits = 44,
233 .fixed_ctr_bits = 48, 256 .fixed_ctr_bits = 48,
234 .perf_ctr = SNB_UNC_CBO_0_PER_CTR0, 257 .perf_ctr = SNB_UNC_CBO_0_PER_CTR0,
@@ -569,7 +592,82 @@ static const struct pci_device_id skl_uncore_pci_ids[] = {
569 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SKL_SQ_IMC), 592 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SKL_SQ_IMC),
570 .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0), 593 .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
571 }, 594 },
572 595 { /* IMC */
596 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KBL_Y_IMC),
597 .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
598 },
599 { /* IMC */
600 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KBL_U_IMC),
601 .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
602 },
603 { /* IMC */
604 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KBL_UQ_IMC),
605 .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
606 },
607 { /* IMC */
608 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KBL_SD_IMC),
609 .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
610 },
611 { /* IMC */
612 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KBL_SQ_IMC),
613 .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
614 },
615 { /* IMC */
616 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CFL_2U_IMC),
617 .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
618 },
619 { /* IMC */
620 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CFL_4U_IMC),
621 .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
622 },
623 { /* IMC */
624 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CFL_4H_IMC),
625 .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
626 },
627 { /* IMC */
628 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CFL_6H_IMC),
629 .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
630 },
631 { /* IMC */
632 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CFL_2S_D_IMC),
633 .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
634 },
635 { /* IMC */
636 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CFL_4S_D_IMC),
637 .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
638 },
639 { /* IMC */
640 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CFL_6S_D_IMC),
641 .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
642 },
643 { /* IMC */
644 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CFL_8S_D_IMC),
645 .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
646 },
647 { /* IMC */
648 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CFL_4S_W_IMC),
649 .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
650 },
651 { /* IMC */
652 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CFL_6S_W_IMC),
653 .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
654 },
655 { /* IMC */
656 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CFL_8S_W_IMC),
657 .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
658 },
659 { /* IMC */
660 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CFL_4S_S_IMC),
661 .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
662 },
663 { /* IMC */
664 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CFL_6S_S_IMC),
665 .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
666 },
667 { /* IMC */
668 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CFL_8S_S_IMC),
669 .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
670 },
573 { /* end: all zeroes */ }, 671 { /* end: all zeroes */ },
574}; 672};
575 673
@@ -618,6 +716,25 @@ static const struct imc_uncore_pci_dev desktop_imc_pci_ids[] = {
618 IMC_DEV(SKL_HQ_IMC, &skl_uncore_pci_driver), /* 6th Gen Core H Quad Core */ 716 IMC_DEV(SKL_HQ_IMC, &skl_uncore_pci_driver), /* 6th Gen Core H Quad Core */
619 IMC_DEV(SKL_SD_IMC, &skl_uncore_pci_driver), /* 6th Gen Core S Dual Core */ 717 IMC_DEV(SKL_SD_IMC, &skl_uncore_pci_driver), /* 6th Gen Core S Dual Core */
620 IMC_DEV(SKL_SQ_IMC, &skl_uncore_pci_driver), /* 6th Gen Core S Quad Core */ 718 IMC_DEV(SKL_SQ_IMC, &skl_uncore_pci_driver), /* 6th Gen Core S Quad Core */
719 IMC_DEV(KBL_Y_IMC, &skl_uncore_pci_driver), /* 7th Gen Core Y */
720 IMC_DEV(KBL_U_IMC, &skl_uncore_pci_driver), /* 7th Gen Core U */
721 IMC_DEV(KBL_UQ_IMC, &skl_uncore_pci_driver), /* 7th Gen Core U Quad Core */
722 IMC_DEV(KBL_SD_IMC, &skl_uncore_pci_driver), /* 7th Gen Core S Dual Core */
723 IMC_DEV(KBL_SQ_IMC, &skl_uncore_pci_driver), /* 7th Gen Core S Quad Core */
724 IMC_DEV(CFL_2U_IMC, &skl_uncore_pci_driver), /* 8th Gen Core U 2 Cores */
725 IMC_DEV(CFL_4U_IMC, &skl_uncore_pci_driver), /* 8th Gen Core U 4 Cores */
726 IMC_DEV(CFL_4H_IMC, &skl_uncore_pci_driver), /* 8th Gen Core H 4 Cores */
727 IMC_DEV(CFL_6H_IMC, &skl_uncore_pci_driver), /* 8th Gen Core H 6 Cores */
728 IMC_DEV(CFL_2S_D_IMC, &skl_uncore_pci_driver), /* 8th Gen Core S 2 Cores Desktop */
729 IMC_DEV(CFL_4S_D_IMC, &skl_uncore_pci_driver), /* 8th Gen Core S 4 Cores Desktop */
730 IMC_DEV(CFL_6S_D_IMC, &skl_uncore_pci_driver), /* 8th Gen Core S 6 Cores Desktop */
731 IMC_DEV(CFL_8S_D_IMC, &skl_uncore_pci_driver), /* 8th Gen Core S 8 Cores Desktop */
732 IMC_DEV(CFL_4S_W_IMC, &skl_uncore_pci_driver), /* 8th Gen Core S 4 Cores Work Station */
733 IMC_DEV(CFL_6S_W_IMC, &skl_uncore_pci_driver), /* 8th Gen Core S 6 Cores Work Station */
734 IMC_DEV(CFL_8S_W_IMC, &skl_uncore_pci_driver), /* 8th Gen Core S 8 Cores Work Station */
735 IMC_DEV(CFL_4S_S_IMC, &skl_uncore_pci_driver), /* 8th Gen Core S 4 Cores Server */
736 IMC_DEV(CFL_6S_S_IMC, &skl_uncore_pci_driver), /* 8th Gen Core S 6 Cores Server */
737 IMC_DEV(CFL_8S_S_IMC, &skl_uncore_pci_driver), /* 8th Gen Core S 8 Cores Server */
621 { /* end marker */ } 738 { /* end marker */ }
622}; 739};
623 740
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index 4da9b1c58d28..c1a812bd5a27 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -221,6 +221,8 @@ static inline void mce_hygon_feature_init(struct cpuinfo_x86 *c) { return mce_am
221 221
222int mce_available(struct cpuinfo_x86 *c); 222int mce_available(struct cpuinfo_x86 *c);
223bool mce_is_memory_error(struct mce *m); 223bool mce_is_memory_error(struct mce *m);
224bool mce_is_correctable(struct mce *m);
225int mce_usable_address(struct mce *m);
224 226
225DECLARE_PER_CPU(unsigned, mce_exception_count); 227DECLARE_PER_CPU(unsigned, mce_exception_count);
226DECLARE_PER_CPU(unsigned, mce_poll_count); 228DECLARE_PER_CPU(unsigned, mce_poll_count);
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 0d6271cce198..1d0a7778e163 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -232,7 +232,7 @@ static inline u64 hv_do_fast_hypercall16(u16 code, u64 input1, u64 input2)
232 : "cc"); 232 : "cc");
233 } 233 }
234#endif 234#endif
235 return hv_status; 235 return hv_status;
236} 236}
237 237
238/* 238/*
diff --git a/arch/x86/include/asm/page_64_types.h b/arch/x86/include/asm/page_64_types.h
index cd0cf1c568b4..8f657286d599 100644
--- a/arch/x86/include/asm/page_64_types.h
+++ b/arch/x86/include/asm/page_64_types.h
@@ -33,12 +33,14 @@
33 33
34/* 34/*
35 * Set __PAGE_OFFSET to the most negative possible address + 35 * Set __PAGE_OFFSET to the most negative possible address +
36 * PGDIR_SIZE*16 (pgd slot 272). The gap is to allow a space for a 36 * PGDIR_SIZE*17 (pgd slot 273).
37 * hypervisor to fit. Choosing 16 slots here is arbitrary, but it's 37 *
38 * what Xen requires. 38 * The gap is to allow a space for LDT remap for PTI (1 pgd slot) and space for
39 * a hypervisor (16 slots). Choosing 16 slots for a hypervisor is arbitrary,
40 * but it's what Xen requires.
39 */ 41 */
40#define __PAGE_OFFSET_BASE_L5 _AC(0xff10000000000000, UL) 42#define __PAGE_OFFSET_BASE_L5 _AC(0xff11000000000000, UL)
41#define __PAGE_OFFSET_BASE_L4 _AC(0xffff880000000000, UL) 43#define __PAGE_OFFSET_BASE_L4 _AC(0xffff888000000000, UL)
42 44
43#ifdef CONFIG_DYNAMIC_MEMORY_LAYOUT 45#ifdef CONFIG_DYNAMIC_MEMORY_LAYOUT
44#define __PAGE_OFFSET page_offset_base 46#define __PAGE_OFFSET page_offset_base
diff --git a/arch/x86/include/asm/pgtable_64_types.h b/arch/x86/include/asm/pgtable_64_types.h
index 04edd2d58211..84bd9bdc1987 100644
--- a/arch/x86/include/asm/pgtable_64_types.h
+++ b/arch/x86/include/asm/pgtable_64_types.h
@@ -111,9 +111,7 @@ extern unsigned int ptrs_per_p4d;
111 */ 111 */
112#define MAXMEM (1UL << MAX_PHYSMEM_BITS) 112#define MAXMEM (1UL << MAX_PHYSMEM_BITS)
113 113
114#define LDT_PGD_ENTRY_L4 -3UL 114#define LDT_PGD_ENTRY -240UL
115#define LDT_PGD_ENTRY_L5 -112UL
116#define LDT_PGD_ENTRY (pgtable_l5_enabled() ? LDT_PGD_ENTRY_L5 : LDT_PGD_ENTRY_L4)
117#define LDT_BASE_ADDR (LDT_PGD_ENTRY << PGDIR_SHIFT) 115#define LDT_BASE_ADDR (LDT_PGD_ENTRY << PGDIR_SHIFT)
118#define LDT_END_ADDR (LDT_BASE_ADDR + PGDIR_SIZE) 116#define LDT_END_ADDR (LDT_BASE_ADDR + PGDIR_SIZE)
119 117
diff --git a/arch/x86/include/asm/qspinlock.h b/arch/x86/include/asm/qspinlock.h
index 87623c6b13db..bd5ac6cc37db 100644
--- a/arch/x86/include/asm/qspinlock.h
+++ b/arch/x86/include/asm/qspinlock.h
@@ -13,12 +13,15 @@
13#define queued_fetch_set_pending_acquire queued_fetch_set_pending_acquire 13#define queued_fetch_set_pending_acquire queued_fetch_set_pending_acquire
14static __always_inline u32 queued_fetch_set_pending_acquire(struct qspinlock *lock) 14static __always_inline u32 queued_fetch_set_pending_acquire(struct qspinlock *lock)
15{ 15{
16 u32 val = 0; 16 u32 val;
17
18 if (GEN_BINARY_RMWcc(LOCK_PREFIX "btsl", lock->val.counter, c,
19 "I", _Q_PENDING_OFFSET))
20 val |= _Q_PENDING_VAL;
21 17
18 /*
19 * We can't use GEN_BINARY_RMWcc() inside an if() stmt because asm goto
20 * and CONFIG_PROFILE_ALL_BRANCHES=y results in a label inside a
21 * statement expression, which GCC doesn't like.
22 */
23 val = GEN_BINARY_RMWcc(LOCK_PREFIX "btsl", lock->val.counter, c,
24 "I", _Q_PENDING_OFFSET) * _Q_PENDING_VAL;
22 val |= atomic_read(&lock->val) & ~_Q_PENDING_MASK; 25 val |= atomic_read(&lock->val) & ~_Q_PENDING_MASK;
23 26
24 return val; 27 return val;
diff --git a/arch/x86/include/asm/xen/page.h b/arch/x86/include/asm/xen/page.h
index 123e669bf363..790ce08e41f2 100644
--- a/arch/x86/include/asm/xen/page.h
+++ b/arch/x86/include/asm/xen/page.h
@@ -9,7 +9,7 @@
9#include <linux/mm.h> 9#include <linux/mm.h>
10#include <linux/device.h> 10#include <linux/device.h>
11 11
12#include <linux/uaccess.h> 12#include <asm/extable.h>
13#include <asm/page.h> 13#include <asm/page.h>
14#include <asm/pgtable.h> 14#include <asm/pgtable.h>
15 15
@@ -93,12 +93,39 @@ clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops,
93 */ 93 */
94static inline int xen_safe_write_ulong(unsigned long *addr, unsigned long val) 94static inline int xen_safe_write_ulong(unsigned long *addr, unsigned long val)
95{ 95{
96 return __put_user(val, (unsigned long __user *)addr); 96 int ret = 0;
97
98 asm volatile("1: mov %[val], %[ptr]\n"
99 "2:\n"
100 ".section .fixup, \"ax\"\n"
101 "3: sub $1, %[ret]\n"
102 " jmp 2b\n"
103 ".previous\n"
104 _ASM_EXTABLE(1b, 3b)
105 : [ret] "+r" (ret), [ptr] "=m" (*addr)
106 : [val] "r" (val));
107
108 return ret;
97} 109}
98 110
99static inline int xen_safe_read_ulong(unsigned long *addr, unsigned long *val) 111static inline int xen_safe_read_ulong(const unsigned long *addr,
112 unsigned long *val)
100{ 113{
101 return __get_user(*val, (unsigned long __user *)addr); 114 int ret = 0;
115 unsigned long rval = ~0ul;
116
117 asm volatile("1: mov %[ptr], %[rval]\n"
118 "2:\n"
119 ".section .fixup, \"ax\"\n"
120 "3: sub $1, %[ret]\n"
121 " jmp 2b\n"
122 ".previous\n"
123 _ASM_EXTABLE(1b, 3b)
124 : [ret] "+r" (ret), [rval] "+r" (rval)
125 : [ptr] "m" (*addr));
126 *val = rval;
127
128 return ret;
102} 129}
103 130
104#ifdef CONFIG_XEN_PV 131#ifdef CONFIG_XEN_PV
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 8c66d2fc8f81..36d2696c9563 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -485,7 +485,7 @@ static void mce_report_event(struct pt_regs *regs)
485 * be somewhat complicated (e.g. segment offset would require an instruction 485 * be somewhat complicated (e.g. segment offset would require an instruction
486 * parser). So only support physical addresses up to page granuality for now. 486 * parser). So only support physical addresses up to page granuality for now.
487 */ 487 */
488static int mce_usable_address(struct mce *m) 488int mce_usable_address(struct mce *m)
489{ 489{
490 if (!(m->status & MCI_STATUS_ADDRV)) 490 if (!(m->status & MCI_STATUS_ADDRV))
491 return 0; 491 return 0;
@@ -505,6 +505,7 @@ static int mce_usable_address(struct mce *m)
505 505
506 return 1; 506 return 1;
507} 507}
508EXPORT_SYMBOL_GPL(mce_usable_address);
508 509
509bool mce_is_memory_error(struct mce *m) 510bool mce_is_memory_error(struct mce *m)
510{ 511{
@@ -534,7 +535,7 @@ bool mce_is_memory_error(struct mce *m)
534} 535}
535EXPORT_SYMBOL_GPL(mce_is_memory_error); 536EXPORT_SYMBOL_GPL(mce_is_memory_error);
536 537
537static bool mce_is_correctable(struct mce *m) 538bool mce_is_correctable(struct mce *m)
538{ 539{
539 if (m->cpuvendor == X86_VENDOR_AMD && m->status & MCI_STATUS_DEFERRED) 540 if (m->cpuvendor == X86_VENDOR_AMD && m->status & MCI_STATUS_DEFERRED)
540 return false; 541 return false;
@@ -547,6 +548,7 @@ static bool mce_is_correctable(struct mce *m)
547 548
548 return true; 549 return true;
549} 550}
551EXPORT_SYMBOL_GPL(mce_is_correctable);
550 552
551static bool cec_add_mce(struct mce *m) 553static bool cec_add_mce(struct mce *m)
552{ 554{
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index 1c72f3819eb1..e81a2db42df7 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -20,6 +20,7 @@
20#include <linux/interrupt.h> 20#include <linux/interrupt.h>
21#include <linux/irq.h> 21#include <linux/irq.h>
22#include <linux/kexec.h> 22#include <linux/kexec.h>
23#include <linux/i8253.h>
23#include <asm/processor.h> 24#include <asm/processor.h>
24#include <asm/hypervisor.h> 25#include <asm/hypervisor.h>
25#include <asm/hyperv-tlfs.h> 26#include <asm/hyperv-tlfs.h>
@@ -295,6 +296,16 @@ static void __init ms_hyperv_init_platform(void)
295 if (efi_enabled(EFI_BOOT)) 296 if (efi_enabled(EFI_BOOT))
296 x86_platform.get_nmi_reason = hv_get_nmi_reason; 297 x86_platform.get_nmi_reason = hv_get_nmi_reason;
297 298
299 /*
300 * Hyper-V VMs have a PIT emulation quirk such that zeroing the
301 * counter register during PIT shutdown restarts the PIT. So it
302 * continues to interrupt @18.2 HZ. Setting i8253_clear_counter
303 * to false tells pit_shutdown() not to zero the counter so that
304 * the PIT really is shutdown. Generation 2 VMs don't have a PIT,
305 * and setting this value has no effect.
306 */
307 i8253_clear_counter_on_shutdown = false;
308
298#if IS_ENABLED(CONFIG_HYPERV) 309#if IS_ENABLED(CONFIG_HYPERV)
299 /* 310 /*
300 * Setup the hook to get control post apic initialization. 311 * Setup the hook to get control post apic initialization.
diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c
index d9ab49bed8af..0eda91f8eeac 100644
--- a/arch/x86/kernel/cpu/vmware.c
+++ b/arch/x86/kernel/cpu/vmware.c
@@ -77,7 +77,7 @@ static __init int setup_vmw_sched_clock(char *s)
77} 77}
78early_param("no-vmw-sched-clock", setup_vmw_sched_clock); 78early_param("no-vmw-sched-clock", setup_vmw_sched_clock);
79 79
80static unsigned long long vmware_sched_clock(void) 80static unsigned long long notrace vmware_sched_clock(void)
81{ 81{
82 unsigned long long ns; 82 unsigned long long ns;
83 83
diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c
index ab18e0884dc6..6135ae8ce036 100644
--- a/arch/x86/kernel/ldt.c
+++ b/arch/x86/kernel/ldt.c
@@ -199,14 +199,6 @@ static void sanity_check_ldt_mapping(struct mm_struct *mm)
199/* 199/*
200 * If PTI is enabled, this maps the LDT into the kernelmode and 200 * If PTI is enabled, this maps the LDT into the kernelmode and
201 * usermode tables for the given mm. 201 * usermode tables for the given mm.
202 *
203 * There is no corresponding unmap function. Even if the LDT is freed, we
204 * leave the PTEs around until the slot is reused or the mm is destroyed.
205 * This is harmless: the LDT is always in ordinary memory, and no one will
206 * access the freed slot.
207 *
208 * If we wanted to unmap freed LDTs, we'd also need to do a flush to make
209 * it useful, and the flush would slow down modify_ldt().
210 */ 202 */
211static int 203static int
212map_ldt_struct(struct mm_struct *mm, struct ldt_struct *ldt, int slot) 204map_ldt_struct(struct mm_struct *mm, struct ldt_struct *ldt, int slot)
@@ -214,8 +206,7 @@ map_ldt_struct(struct mm_struct *mm, struct ldt_struct *ldt, int slot)
214 unsigned long va; 206 unsigned long va;
215 bool is_vmalloc; 207 bool is_vmalloc;
216 spinlock_t *ptl; 208 spinlock_t *ptl;
217 pgd_t *pgd; 209 int i, nr_pages;
218 int i;
219 210
220 if (!static_cpu_has(X86_FEATURE_PTI)) 211 if (!static_cpu_has(X86_FEATURE_PTI))
221 return 0; 212 return 0;
@@ -229,16 +220,11 @@ map_ldt_struct(struct mm_struct *mm, struct ldt_struct *ldt, int slot)
229 /* Check if the current mappings are sane */ 220 /* Check if the current mappings are sane */
230 sanity_check_ldt_mapping(mm); 221 sanity_check_ldt_mapping(mm);
231 222
232 /*
233 * Did we already have the top level entry allocated? We can't
234 * use pgd_none() for this because it doens't do anything on
235 * 4-level page table kernels.
236 */
237 pgd = pgd_offset(mm, LDT_BASE_ADDR);
238
239 is_vmalloc = is_vmalloc_addr(ldt->entries); 223 is_vmalloc = is_vmalloc_addr(ldt->entries);
240 224
241 for (i = 0; i * PAGE_SIZE < ldt->nr_entries * LDT_ENTRY_SIZE; i++) { 225 nr_pages = DIV_ROUND_UP(ldt->nr_entries * LDT_ENTRY_SIZE, PAGE_SIZE);
226
227 for (i = 0; i < nr_pages; i++) {
242 unsigned long offset = i << PAGE_SHIFT; 228 unsigned long offset = i << PAGE_SHIFT;
243 const void *src = (char *)ldt->entries + offset; 229 const void *src = (char *)ldt->entries + offset;
244 unsigned long pfn; 230 unsigned long pfn;
@@ -272,13 +258,39 @@ map_ldt_struct(struct mm_struct *mm, struct ldt_struct *ldt, int slot)
272 /* Propagate LDT mapping to the user page-table */ 258 /* Propagate LDT mapping to the user page-table */
273 map_ldt_struct_to_user(mm); 259 map_ldt_struct_to_user(mm);
274 260
275 va = (unsigned long)ldt_slot_va(slot);
276 flush_tlb_mm_range(mm, va, va + LDT_SLOT_STRIDE, PAGE_SHIFT, false);
277
278 ldt->slot = slot; 261 ldt->slot = slot;
279 return 0; 262 return 0;
280} 263}
281 264
265static void unmap_ldt_struct(struct mm_struct *mm, struct ldt_struct *ldt)
266{
267 unsigned long va;
268 int i, nr_pages;
269
270 if (!ldt)
271 return;
272
273 /* LDT map/unmap is only required for PTI */
274 if (!static_cpu_has(X86_FEATURE_PTI))
275 return;
276
277 nr_pages = DIV_ROUND_UP(ldt->nr_entries * LDT_ENTRY_SIZE, PAGE_SIZE);
278
279 for (i = 0; i < nr_pages; i++) {
280 unsigned long offset = i << PAGE_SHIFT;
281 spinlock_t *ptl;
282 pte_t *ptep;
283
284 va = (unsigned long)ldt_slot_va(ldt->slot) + offset;
285 ptep = get_locked_pte(mm, va, &ptl);
286 pte_clear(mm, va, ptep);
287 pte_unmap_unlock(ptep, ptl);
288 }
289
290 va = (unsigned long)ldt_slot_va(ldt->slot);
291 flush_tlb_mm_range(mm, va, va + nr_pages * PAGE_SIZE, PAGE_SHIFT, false);
292}
293
282#else /* !CONFIG_PAGE_TABLE_ISOLATION */ 294#else /* !CONFIG_PAGE_TABLE_ISOLATION */
283 295
284static int 296static int
@@ -286,6 +298,10 @@ map_ldt_struct(struct mm_struct *mm, struct ldt_struct *ldt, int slot)
286{ 298{
287 return 0; 299 return 0;
288} 300}
301
302static void unmap_ldt_struct(struct mm_struct *mm, struct ldt_struct *ldt)
303{
304}
289#endif /* CONFIG_PAGE_TABLE_ISOLATION */ 305#endif /* CONFIG_PAGE_TABLE_ISOLATION */
290 306
291static void free_ldt_pgtables(struct mm_struct *mm) 307static void free_ldt_pgtables(struct mm_struct *mm)
@@ -524,6 +540,7 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
524 } 540 }
525 541
526 install_ldt(mm, new_ldt); 542 install_ldt(mm, new_ldt);
543 unmap_ldt_struct(mm, old_ldt);
527 free_ldt_struct(old_ldt); 544 free_ldt_struct(old_ldt);
528 error = 0; 545 error = 0;
529 546
diff --git a/arch/x86/kernel/vsmp_64.c b/arch/x86/kernel/vsmp_64.c
index 1eae5af491c2..891a75dbc131 100644
--- a/arch/x86/kernel/vsmp_64.c
+++ b/arch/x86/kernel/vsmp_64.c
@@ -26,65 +26,8 @@
26 26
27#define TOPOLOGY_REGISTER_OFFSET 0x10 27#define TOPOLOGY_REGISTER_OFFSET 0x10
28 28
29#if defined CONFIG_PCI && defined CONFIG_PARAVIRT_XXL 29#ifdef CONFIG_PCI
30/* 30static void __init set_vsmp_ctl(void)
31 * Interrupt control on vSMPowered systems:
32 * ~AC is a shadow of IF. If IF is 'on' AC should be 'off'
33 * and vice versa.
34 */
35
36asmlinkage __visible unsigned long vsmp_save_fl(void)
37{
38 unsigned long flags = native_save_fl();
39
40 if (!(flags & X86_EFLAGS_IF) || (flags & X86_EFLAGS_AC))
41 flags &= ~X86_EFLAGS_IF;
42 return flags;
43}
44PV_CALLEE_SAVE_REGS_THUNK(vsmp_save_fl);
45
46__visible void vsmp_restore_fl(unsigned long flags)
47{
48 if (flags & X86_EFLAGS_IF)
49 flags &= ~X86_EFLAGS_AC;
50 else
51 flags |= X86_EFLAGS_AC;
52 native_restore_fl(flags);
53}
54PV_CALLEE_SAVE_REGS_THUNK(vsmp_restore_fl);
55
56asmlinkage __visible void vsmp_irq_disable(void)
57{
58 unsigned long flags = native_save_fl();
59
60 native_restore_fl((flags & ~X86_EFLAGS_IF) | X86_EFLAGS_AC);
61}
62PV_CALLEE_SAVE_REGS_THUNK(vsmp_irq_disable);
63
64asmlinkage __visible void vsmp_irq_enable(void)
65{
66 unsigned long flags = native_save_fl();
67
68 native_restore_fl((flags | X86_EFLAGS_IF) & (~X86_EFLAGS_AC));
69}
70PV_CALLEE_SAVE_REGS_THUNK(vsmp_irq_enable);
71
72static unsigned __init vsmp_patch(u8 type, void *ibuf,
73 unsigned long addr, unsigned len)
74{
75 switch (type) {
76 case PARAVIRT_PATCH(irq.irq_enable):
77 case PARAVIRT_PATCH(irq.irq_disable):
78 case PARAVIRT_PATCH(irq.save_fl):
79 case PARAVIRT_PATCH(irq.restore_fl):
80 return paravirt_patch_default(type, ibuf, addr, len);
81 default:
82 return native_patch(type, ibuf, addr, len);
83 }
84
85}
86
87static void __init set_vsmp_pv_ops(void)
88{ 31{
89 void __iomem *address; 32 void __iomem *address;
90 unsigned int cap, ctl, cfg; 33 unsigned int cap, ctl, cfg;
@@ -109,28 +52,12 @@ static void __init set_vsmp_pv_ops(void)
109 } 52 }
110#endif 53#endif
111 54
112 if (cap & ctl & (1 << 4)) {
113 /* Setup irq ops and turn on vSMP IRQ fastpath handling */
114 pv_ops.irq.irq_disable = PV_CALLEE_SAVE(vsmp_irq_disable);
115 pv_ops.irq.irq_enable = PV_CALLEE_SAVE(vsmp_irq_enable);
116 pv_ops.irq.save_fl = PV_CALLEE_SAVE(vsmp_save_fl);
117 pv_ops.irq.restore_fl = PV_CALLEE_SAVE(vsmp_restore_fl);
118 pv_ops.init.patch = vsmp_patch;
119 ctl &= ~(1 << 4);
120 }
121 writel(ctl, address + 4); 55 writel(ctl, address + 4);
122 ctl = readl(address + 4); 56 ctl = readl(address + 4);
123 pr_info("vSMP CTL: control set to:0x%08x\n", ctl); 57 pr_info("vSMP CTL: control set to:0x%08x\n", ctl);
124 58
125 early_iounmap(address, 8); 59 early_iounmap(address, 8);
126} 60}
127#else
128static void __init set_vsmp_pv_ops(void)
129{
130}
131#endif
132
133#ifdef CONFIG_PCI
134static int is_vsmp = -1; 61static int is_vsmp = -1;
135 62
136static void __init detect_vsmp_box(void) 63static void __init detect_vsmp_box(void)
@@ -164,11 +91,14 @@ static int is_vsmp_box(void)
164{ 91{
165 return 0; 92 return 0;
166} 93}
94static void __init set_vsmp_ctl(void)
95{
96}
167#endif 97#endif
168 98
169static void __init vsmp_cap_cpus(void) 99static void __init vsmp_cap_cpus(void)
170{ 100{
171#if !defined(CONFIG_X86_VSMP) && defined(CONFIG_SMP) 101#if !defined(CONFIG_X86_VSMP) && defined(CONFIG_SMP) && defined(CONFIG_PCI)
172 void __iomem *address; 102 void __iomem *address;
173 unsigned int cfg, topology, node_shift, maxcpus; 103 unsigned int cfg, topology, node_shift, maxcpus;
174 104
@@ -221,6 +151,6 @@ void __init vsmp_init(void)
221 151
222 vsmp_cap_cpus(); 152 vsmp_cap_cpus();
223 153
224 set_vsmp_pv_ops(); 154 set_vsmp_ctl();
225 return; 155 return;
226} 156}
diff --git a/arch/x86/xen/mmu_pv.c b/arch/x86/xen/mmu_pv.c
index 0d7b3ae4960b..a5d7ed125337 100644
--- a/arch/x86/xen/mmu_pv.c
+++ b/arch/x86/xen/mmu_pv.c
@@ -1905,7 +1905,7 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
1905 init_top_pgt[0] = __pgd(0); 1905 init_top_pgt[0] = __pgd(0);
1906 1906
1907 /* Pre-constructed entries are in pfn, so convert to mfn */ 1907 /* Pre-constructed entries are in pfn, so convert to mfn */
1908 /* L4[272] -> level3_ident_pgt */ 1908 /* L4[273] -> level3_ident_pgt */
1909 /* L4[511] -> level3_kernel_pgt */ 1909 /* L4[511] -> level3_kernel_pgt */
1910 convert_pfn_mfn(init_top_pgt); 1910 convert_pfn_mfn(init_top_pgt);
1911 1911
@@ -1925,8 +1925,8 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
1925 addr[0] = (unsigned long)pgd; 1925 addr[0] = (unsigned long)pgd;
1926 addr[1] = (unsigned long)l3; 1926 addr[1] = (unsigned long)l3;
1927 addr[2] = (unsigned long)l2; 1927 addr[2] = (unsigned long)l2;
1928 /* Graft it onto L4[272][0]. Note that we creating an aliasing problem: 1928 /* Graft it onto L4[273][0]. Note that we creating an aliasing problem:
1929 * Both L4[272][0] and L4[511][510] have entries that point to the same 1929 * Both L4[273][0] and L4[511][510] have entries that point to the same
1930 * L2 (PMD) tables. Meaning that if you modify it in __va space 1930 * L2 (PMD) tables. Meaning that if you modify it in __va space
1931 * it will be also modified in the __ka space! (But if you just 1931 * it will be also modified in the __ka space! (But if you just
1932 * modify the PMD table to point to other PTE's or none, then you 1932 * modify the PMD table to point to other PTE's or none, then you
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c
index b06731705529..055e37e43541 100644
--- a/arch/x86/xen/p2m.c
+++ b/arch/x86/xen/p2m.c
@@ -656,8 +656,7 @@ bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
656 656
657 /* 657 /*
658 * The interface requires atomic updates on p2m elements. 658 * The interface requires atomic updates on p2m elements.
659 * xen_safe_write_ulong() is using __put_user which does an atomic 659 * xen_safe_write_ulong() is using an atomic store via asm().
660 * store via asm().
661 */ 660 */
662 if (likely(!xen_safe_write_ulong(xen_p2m_addr + pfn, mfn))) 661 if (likely(!xen_safe_write_ulong(xen_p2m_addr + pfn, mfn)))
663 return true; 662 return true;
diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c
index 441c88262169..1c8a8816a402 100644
--- a/arch/x86/xen/spinlock.c
+++ b/arch/x86/xen/spinlock.c
@@ -9,6 +9,7 @@
9#include <linux/log2.h> 9#include <linux/log2.h>
10#include <linux/gfp.h> 10#include <linux/gfp.h>
11#include <linux/slab.h> 11#include <linux/slab.h>
12#include <linux/atomic.h>
12 13
13#include <asm/paravirt.h> 14#include <asm/paravirt.h>
14#include <asm/qspinlock.h> 15#include <asm/qspinlock.h>
@@ -21,6 +22,7 @@
21 22
22static DEFINE_PER_CPU(int, lock_kicker_irq) = -1; 23static DEFINE_PER_CPU(int, lock_kicker_irq) = -1;
23static DEFINE_PER_CPU(char *, irq_name); 24static DEFINE_PER_CPU(char *, irq_name);
25static DEFINE_PER_CPU(atomic_t, xen_qlock_wait_nest);
24static bool xen_pvspin = true; 26static bool xen_pvspin = true;
25 27
26static void xen_qlock_kick(int cpu) 28static void xen_qlock_kick(int cpu)
@@ -39,25 +41,25 @@ static void xen_qlock_kick(int cpu)
39 */ 41 */
40static void xen_qlock_wait(u8 *byte, u8 val) 42static void xen_qlock_wait(u8 *byte, u8 val)
41{ 43{
42 unsigned long flags;
43 int irq = __this_cpu_read(lock_kicker_irq); 44 int irq = __this_cpu_read(lock_kicker_irq);
45 atomic_t *nest_cnt = this_cpu_ptr(&xen_qlock_wait_nest);
44 46
45 /* If kicker interrupts not initialized yet, just spin */ 47 /* If kicker interrupts not initialized yet, just spin */
46 if (irq == -1 || in_nmi()) 48 if (irq == -1 || in_nmi())
47 return; 49 return;
48 50
49 /* Guard against reentry. */ 51 /* Detect reentry. */
50 local_irq_save(flags); 52 atomic_inc(nest_cnt);
51 53
52 /* If irq pending already clear it. */ 54 /* If irq pending already and no nested call clear it. */
53 if (xen_test_irq_pending(irq)) { 55 if (atomic_read(nest_cnt) == 1 && xen_test_irq_pending(irq)) {
54 xen_clear_irq_pending(irq); 56 xen_clear_irq_pending(irq);
55 } else if (READ_ONCE(*byte) == val) { 57 } else if (READ_ONCE(*byte) == val) {
56 /* Block until irq becomes pending (or a spurious wakeup) */ 58 /* Block until irq becomes pending (or a spurious wakeup) */
57 xen_poll_irq(irq); 59 xen_poll_irq(irq);
58 } 60 }
59 61
60 local_irq_restore(flags); 62 atomic_dec(nest_cnt);
61} 63}
62 64
63static irqreturn_t dummy_handler(int irq, void *dev_id) 65static irqreturn_t dummy_handler(int irq, void *dev_id)