diff options
-rw-r--r-- | arch/x86/Makefile | 1 | ||||
-rw-r--r-- | arch/x86/boot/compressed/pgtable_64.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/apic/apic.c | 4 | ||||
-rw-r--r-- | arch/x86/kernel/apic/bigsmp_32.c | 24 | ||||
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 8 | ||||
-rw-r--r-- | arch/x86/kernel/uprobes.c | 17 | ||||
-rw-r--r-- | arch/x86/mm/pageattr.c | 26 |
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 | ||
39 | REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), -ffreestanding) | 39 | REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), -ffreestanding) |
40 | REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), -fno-stack-protector) | 40 | REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), -fno-stack-protector) |
41 | REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), -Wno-address-of-packed-member) | ||
41 | REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), $(cc_stack_align4)) | 42 | REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), $(cc_stack_align4)) |
42 | export REALMODE_CFLAGS | 43 | export 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 | ||
41 | static 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 | */ |
59 | static void bigsmp_init_apic_ldr(void) | 45 | static 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 | ||
69 | static void bigsmp_setup_apic_routing(void) | 49 | static 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 | ||
511 | static inline int sizeof_long(void) | 511 | static 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 | ||
516 | static int default_pre_xol_op(struct arch_uprobe *auprobe, struct pt_regs *regs) | 519 | static 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 | ||
522 | static int emulate_push_stack(struct pt_regs *regs, unsigned long val) | 525 | static 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) | |||
1056 | unsigned long | 1059 | unsigned long |
1057 | arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs *regs) | 1060 | arch_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 | */ |
517 | static inline pgprot_t static_protections(pgprot_t prot, unsigned long start, | 517 | static 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); |