summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-09-01 14:21:57 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-09-01 14:21:57 -0400
commit9f159ae07f07fc540290f21937231034f554bdd7 (patch)
treef343157aefa90c11e1e136514e2222e8cba0dc33
parent5fb181cba01088924a68441753843e5acfd012ff (diff)
parent7af0145067bc429a09ac4047b167c0971c9f0dc7 (diff)
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fixes from Thomas Gleixner: "A set of fixes for x86: - Fix the bogus detection of 32bit user mode for uretprobes which caused corruption of the user return address resulting in application crashes. In the uprobes handler in_ia32_syscall() is obviously always returning false on a 64bit kernel. Use user_64bit_mode() instead which works correctly. - Prevent large page splitting when ftrace flips RW/RO on the kernel text which caused iTLB performance issues. Ftrace wants to be converted to text_poke() which avoids the problem, but for now allow large page preservation in the static protections check when the change request spawns a full large page. - Prevent arch_dynirq_lower_bound() from returning 0 when the IOAPIC is configured via device tree. In the device tree case the GSI 1:1 mapping is meaningless therefore the lower bound which protects the GSI range on ACPI machines is irrelevant. Return the lower bound which the core hands to the function instead of blindly returning 0 which causes the core to allocate the invalid virtual interupt number 0 which in turn prevents all drivers from allocating and requesting an interrupt. - Remove the bogus initialization of LDR and DFR in the 32bit bigsmp APIC driver. That uses physical destination mode where LDR/DFR are ignored, but the initialization and the missing clear of LDR caused the APIC to be left in a inconsistent state on kexec/reboot. - Clear LDR when clearing the APIC registers so the APIC is in a well defined state. - Initialize variables proper in the find_trampoline_placement() code. - Silence GCC( build warning for the real mode part of the build" * 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/mm/cpa: Prevent large page split when ftrace flips RW on kernel text x86/build: Add -Wnoaddress-of-packed-member to REALMODE_CFLAGS, to silence GCC9 build warning x86/boot/compressed/64: Fix missing initialization in find_trampoline_placement() x86/apic: Include the LDR when clearing out APIC registers x86/apic: Do not initialize LDR and DFR for bigsmp uprobes/x86: Fix detection of 32-bit user mode x86/apic: Fix arch_dynirq_lower_bound() bug for DT enabled machines
-rw-r--r--arch/x86/Makefile1
-rw-r--r--arch/x86/boot/compressed/pgtable_64.c2
-rw-r--r--arch/x86/kernel/apic/apic.c4
-rw-r--r--arch/x86/kernel/apic/bigsmp_32.c24
-rw-r--r--arch/x86/kernel/apic/io_apic.c8
-rw-r--r--arch/x86/kernel/uprobes.c17
-rw-r--r--arch/x86/mm/pageattr.c26
7 files changed, 43 insertions, 39 deletions
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 56e748a7679f..94df0868804b 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -38,6 +38,7 @@ REALMODE_CFLAGS := $(M16_CFLAGS) -g -Os -DDISABLE_BRANCH_PROFILING \
38 38
39REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), -ffreestanding) 39REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), -ffreestanding)
40REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), -fno-stack-protector) 40REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), -fno-stack-protector)
41REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), -Wno-address-of-packed-member)
41REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), $(cc_stack_align4)) 42REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), $(cc_stack_align4))
42export REALMODE_CFLAGS 43export REALMODE_CFLAGS
43 44
diff --git a/arch/x86/boot/compressed/pgtable_64.c b/arch/x86/boot/compressed/pgtable_64.c
index 2faddeb0398a..c8862696a47b 100644
--- a/arch/x86/boot/compressed/pgtable_64.c
+++ b/arch/x86/boot/compressed/pgtable_64.c
@@ -72,7 +72,7 @@ static unsigned long find_trampoline_placement(void)
72 72
73 /* Find the first usable memory region under bios_start. */ 73 /* Find the first usable memory region under bios_start. */
74 for (i = boot_params->e820_entries - 1; i >= 0; i--) { 74 for (i = boot_params->e820_entries - 1; i >= 0; i--) {
75 unsigned long new; 75 unsigned long new = bios_start;
76 76
77 entry = &boot_params->e820_table[i]; 77 entry = &boot_params->e820_table[i];
78 78
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index aa5495d0f478..dba2828b779a 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1179,6 +1179,10 @@ void clear_local_APIC(void)
1179 apic_write(APIC_LVT0, v | APIC_LVT_MASKED); 1179 apic_write(APIC_LVT0, v | APIC_LVT_MASKED);
1180 v = apic_read(APIC_LVT1); 1180 v = apic_read(APIC_LVT1);
1181 apic_write(APIC_LVT1, v | APIC_LVT_MASKED); 1181 apic_write(APIC_LVT1, v | APIC_LVT_MASKED);
1182 if (!x2apic_enabled()) {
1183 v = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
1184 apic_write(APIC_LDR, v);
1185 }
1182 if (maxlvt >= 4) { 1186 if (maxlvt >= 4) {
1183 v = apic_read(APIC_LVTPC); 1187 v = apic_read(APIC_LVTPC);
1184 apic_write(APIC_LVTPC, v | APIC_LVT_MASKED); 1188 apic_write(APIC_LVTPC, v | APIC_LVT_MASKED);
diff --git a/arch/x86/kernel/apic/bigsmp_32.c b/arch/x86/kernel/apic/bigsmp_32.c
index afee386ff711..caedd8d60d36 100644
--- a/arch/x86/kernel/apic/bigsmp_32.c
+++ b/arch/x86/kernel/apic/bigsmp_32.c
@@ -38,32 +38,12 @@ static int bigsmp_early_logical_apicid(int cpu)
38 return early_per_cpu(x86_cpu_to_apicid, cpu); 38 return early_per_cpu(x86_cpu_to_apicid, cpu);
39} 39}
40 40
41static inline unsigned long calculate_ldr(int cpu)
42{
43 unsigned long val, id;
44
45 val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
46 id = per_cpu(x86_bios_cpu_apicid, cpu);
47 val |= SET_APIC_LOGICAL_ID(id);
48
49 return val;
50}
51
52/* 41/*
53 * Set up the logical destination ID. 42 * bigsmp enables physical destination mode
54 * 43 * and doesn't use LDR and DFR
55 * Intel recommends to set DFR, LDR and TPR before enabling
56 * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel
57 * document number 292116). So here it goes...
58 */ 44 */
59static void bigsmp_init_apic_ldr(void) 45static void bigsmp_init_apic_ldr(void)
60{ 46{
61 unsigned long val;
62 int cpu = smp_processor_id();
63
64 apic_write(APIC_DFR, APIC_DFR_FLAT);
65 val = calculate_ldr(cpu);
66 apic_write(APIC_LDR, val);
67} 47}
68 48
69static void bigsmp_setup_apic_routing(void) 49static void bigsmp_setup_apic_routing(void)
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index c7bb6c69f21c..d6af97fd170a 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -2438,7 +2438,13 @@ unsigned int arch_dynirq_lower_bound(unsigned int from)
2438 * dmar_alloc_hwirq() may be called before setup_IO_APIC(), so use 2438 * dmar_alloc_hwirq() may be called before setup_IO_APIC(), so use
2439 * gsi_top if ioapic_dynirq_base hasn't been initialized yet. 2439 * gsi_top if ioapic_dynirq_base hasn't been initialized yet.
2440 */ 2440 */
2441 return ioapic_initialized ? ioapic_dynirq_base : gsi_top; 2441 if (!ioapic_initialized)
2442 return gsi_top;
2443 /*
2444 * For DT enabled machines ioapic_dynirq_base is irrelevant and not
2445 * updated. So simply return @from if ioapic_dynirq_base == 0.
2446 */
2447 return ioapic_dynirq_base ? : from;
2442} 2448}
2443 2449
2444#ifdef CONFIG_X86_32 2450#ifdef CONFIG_X86_32
diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c
index d8359ebeea70..8cd745ef8c7b 100644
--- a/arch/x86/kernel/uprobes.c
+++ b/arch/x86/kernel/uprobes.c
@@ -508,9 +508,12 @@ struct uprobe_xol_ops {
508 void (*abort)(struct arch_uprobe *, struct pt_regs *); 508 void (*abort)(struct arch_uprobe *, struct pt_regs *);
509}; 509};
510 510
511static inline int sizeof_long(void) 511static inline int sizeof_long(struct pt_regs *regs)
512{ 512{
513 return in_ia32_syscall() ? 4 : 8; 513 /*
514 * Check registers for mode as in_xxx_syscall() does not apply here.
515 */
516 return user_64bit_mode(regs) ? 8 : 4;
514} 517}
515 518
516static int default_pre_xol_op(struct arch_uprobe *auprobe, struct pt_regs *regs) 519static int default_pre_xol_op(struct arch_uprobe *auprobe, struct pt_regs *regs)
@@ -521,9 +524,9 @@ static int default_pre_xol_op(struct arch_uprobe *auprobe, struct pt_regs *regs)
521 524
522static int emulate_push_stack(struct pt_regs *regs, unsigned long val) 525static int emulate_push_stack(struct pt_regs *regs, unsigned long val)
523{ 526{
524 unsigned long new_sp = regs->sp - sizeof_long(); 527 unsigned long new_sp = regs->sp - sizeof_long(regs);
525 528
526 if (copy_to_user((void __user *)new_sp, &val, sizeof_long())) 529 if (copy_to_user((void __user *)new_sp, &val, sizeof_long(regs)))
527 return -EFAULT; 530 return -EFAULT;
528 531
529 regs->sp = new_sp; 532 regs->sp = new_sp;
@@ -556,7 +559,7 @@ static int default_post_xol_op(struct arch_uprobe *auprobe, struct pt_regs *regs
556 long correction = utask->vaddr - utask->xol_vaddr; 559 long correction = utask->vaddr - utask->xol_vaddr;
557 regs->ip += correction; 560 regs->ip += correction;
558 } else if (auprobe->defparam.fixups & UPROBE_FIX_CALL) { 561 } else if (auprobe->defparam.fixups & UPROBE_FIX_CALL) {
559 regs->sp += sizeof_long(); /* Pop incorrect return address */ 562 regs->sp += sizeof_long(regs); /* Pop incorrect return address */
560 if (emulate_push_stack(regs, utask->vaddr + auprobe->defparam.ilen)) 563 if (emulate_push_stack(regs, utask->vaddr + auprobe->defparam.ilen))
561 return -ERESTART; 564 return -ERESTART;
562 } 565 }
@@ -675,7 +678,7 @@ static int branch_post_xol_op(struct arch_uprobe *auprobe, struct pt_regs *regs)
675 * "call" insn was executed out-of-line. Just restore ->sp and restart. 678 * "call" insn was executed out-of-line. Just restore ->sp and restart.
676 * We could also restore ->ip and try to call branch_emulate_op() again. 679 * We could also restore ->ip and try to call branch_emulate_op() again.
677 */ 680 */
678 regs->sp += sizeof_long(); 681 regs->sp += sizeof_long(regs);
679 return -ERESTART; 682 return -ERESTART;
680} 683}
681 684
@@ -1056,7 +1059,7 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
1056unsigned long 1059unsigned long
1057arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs *regs) 1060arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs *regs)
1058{ 1061{
1059 int rasize = sizeof_long(), nleft; 1062 int rasize = sizeof_long(regs), nleft;
1060 unsigned long orig_ret_vaddr = 0; /* clear high bits for 32-bit apps */ 1063 unsigned long orig_ret_vaddr = 0; /* clear high bits for 32-bit apps */
1061 1064
1062 if (copy_from_user(&orig_ret_vaddr, (void __user *)regs->sp, rasize)) 1065 if (copy_from_user(&orig_ret_vaddr, (void __user *)regs->sp, rasize))
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 6a9a77a403c9..e14e95ea7338 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -516,7 +516,7 @@ static inline void check_conflict(int warnlvl, pgprot_t prot, pgprotval_t val,
516 */ 516 */
517static inline pgprot_t static_protections(pgprot_t prot, unsigned long start, 517static inline pgprot_t static_protections(pgprot_t prot, unsigned long start,
518 unsigned long pfn, unsigned long npg, 518 unsigned long pfn, unsigned long npg,
519 int warnlvl) 519 unsigned long lpsize, int warnlvl)
520{ 520{
521 pgprotval_t forbidden, res; 521 pgprotval_t forbidden, res;
522 unsigned long end; 522 unsigned long end;
@@ -535,9 +535,17 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long start,
535 check_conflict(warnlvl, prot, res, start, end, pfn, "Text NX"); 535 check_conflict(warnlvl, prot, res, start, end, pfn, "Text NX");
536 forbidden = res; 536 forbidden = res;
537 537
538 res = protect_kernel_text_ro(start, end); 538 /*
539 check_conflict(warnlvl, prot, res, start, end, pfn, "Text RO"); 539 * Special case to preserve a large page. If the change spawns the
540 forbidden |= res; 540 * full large page mapping then there is no point to split it
541 * up. Happens with ftrace and is going to be removed once ftrace
542 * switched to text_poke().
543 */
544 if (lpsize != (npg * PAGE_SIZE) || (start & (lpsize - 1))) {
545 res = protect_kernel_text_ro(start, end);
546 check_conflict(warnlvl, prot, res, start, end, pfn, "Text RO");
547 forbidden |= res;
548 }
541 549
542 /* Check the PFN directly */ 550 /* Check the PFN directly */
543 res = protect_pci_bios(pfn, pfn + npg - 1); 551 res = protect_pci_bios(pfn, pfn + npg - 1);
@@ -819,7 +827,7 @@ static int __should_split_large_page(pte_t *kpte, unsigned long address,
819 * extra conditional required here. 827 * extra conditional required here.
820 */ 828 */
821 chk_prot = static_protections(old_prot, lpaddr, old_pfn, numpages, 829 chk_prot = static_protections(old_prot, lpaddr, old_pfn, numpages,
822 CPA_CONFLICT); 830 psize, CPA_CONFLICT);
823 831
824 if (WARN_ON_ONCE(pgprot_val(chk_prot) != pgprot_val(old_prot))) { 832 if (WARN_ON_ONCE(pgprot_val(chk_prot) != pgprot_val(old_prot))) {
825 /* 833 /*
@@ -855,7 +863,7 @@ static int __should_split_large_page(pte_t *kpte, unsigned long address,
855 * protection requirement in the large page. 863 * protection requirement in the large page.
856 */ 864 */
857 new_prot = static_protections(req_prot, lpaddr, old_pfn, numpages, 865 new_prot = static_protections(req_prot, lpaddr, old_pfn, numpages,
858 CPA_DETECT); 866 psize, CPA_DETECT);
859 867
860 /* 868 /*
861 * If there is a conflict, split the large page. 869 * If there is a conflict, split the large page.
@@ -906,7 +914,8 @@ static void split_set_pte(struct cpa_data *cpa, pte_t *pte, unsigned long pfn,
906 if (!cpa->force_static_prot) 914 if (!cpa->force_static_prot)
907 goto set; 915 goto set;
908 916
909 prot = static_protections(ref_prot, address, pfn, npg, CPA_PROTECT); 917 /* Hand in lpsize = 0 to enforce the protection mechanism */
918 prot = static_protections(ref_prot, address, pfn, npg, 0, CPA_PROTECT);
910 919
911 if (pgprot_val(prot) == pgprot_val(ref_prot)) 920 if (pgprot_val(prot) == pgprot_val(ref_prot))
912 goto set; 921 goto set;
@@ -1503,7 +1512,8 @@ repeat:
1503 pgprot_val(new_prot) |= pgprot_val(cpa->mask_set); 1512 pgprot_val(new_prot) |= pgprot_val(cpa->mask_set);
1504 1513
1505 cpa_inc_4k_install(); 1514 cpa_inc_4k_install();
1506 new_prot = static_protections(new_prot, address, pfn, 1, 1515 /* Hand in lpsize = 0 to enforce the protection mechanism */
1516 new_prot = static_protections(new_prot, address, pfn, 1, 0,
1507 CPA_PROTECT); 1517 CPA_PROTECT);
1508 1518
1509 new_prot = pgprot_clear_protnone_bits(new_prot); 1519 new_prot = pgprot_clear_protnone_bits(new_prot);