diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-26 17:11:54 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-26 17:11:54 -0500 |
| commit | 02fc87b117a9b9ec325089d098fce86ed11966bd (patch) | |
| tree | 537176c1c32b25c781bf8974af854a4ee4dbc77a | |
| parent | 6830c8db58c2616d8ba2bf45e7d98dca5f69b07f (diff) | |
| parent | 12a78d43de767eaf8fb272facb7a7b6f2dc6a9df (diff) | |
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull misc x86 fixes from Ingo Molnar:
- topology enumeration fixes
- KASAN fix
- two entry fixes (not yet the big series related to KASLR)
- remove obsolete code
- instruction decoder fix
- better /dev/mem sanity checks, hopefully working better this time
- pkeys fixes
- two ACPI fixes
- 5-level paging related fixes
- UMIP fixes that should make application visible faults more debuggable
- boot fix for weird virtualization environment
* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (24 commits)
x86/decoder: Add new TEST instruction pattern
x86/PCI: Remove unused HyperTransport interrupt support
x86/umip: Fix insn_get_code_seg_params()'s return value
x86/boot/KASLR: Remove unused variable
x86/entry/64: Add missing irqflags tracing to native_load_gs_index()
x86/mm/kasan: Don't use vmemmap_populate() to initialize shadow
x86/entry/64: Fix entry_SYSCALL_64_after_hwframe() IRQ tracing
x86/pkeys/selftests: Fix protection keys write() warning
x86/pkeys/selftests: Rename 'si_pkey' to 'siginfo_pkey'
x86/mpx/selftests: Fix up weird arrays
x86/pkeys: Update documentation about availability
x86/umip: Print a warning into the syslog if UMIP-protected instructions are used
x86/smpboot: Fix __max_logical_packages estimate
x86/topology: Avoid wasting 128k for package id array
perf/x86/intel/uncore: Cache logical pkg id in uncore driver
x86/acpi: Reduce code duplication in mp_override_legacy_irq()
x86/acpi: Handle SCI interrupts above legacy space gracefully
x86/boot: Fix boot failure when SMP MP-table is based at 0
x86/mm: Limit mmap() of /dev/mem to valid physical addresses
x86/selftests: Add test for mapping placement for 5-level paging
...
38 files changed, 472 insertions, 616 deletions
diff --git a/Documentation/x86/protection-keys.txt b/Documentation/x86/protection-keys.txt index fa46dcb347bc..ecb0d2dadfb7 100644 --- a/Documentation/x86/protection-keys.txt +++ b/Documentation/x86/protection-keys.txt | |||
| @@ -1,5 +1,10 @@ | |||
| 1 | Memory Protection Keys for Userspace (PKU aka PKEYs) is a CPU feature | 1 | Memory Protection Keys for Userspace (PKU aka PKEYs) is a feature |
| 2 | which will be found on future Intel CPUs. | 2 | which is found on Intel's Skylake "Scalable Processor" Server CPUs. |
| 3 | It will be avalable in future non-server parts. | ||
| 4 | |||
| 5 | For anyone wishing to test or use this feature, it is available in | ||
| 6 | Amazon's EC2 C5 instances and is known to work there using an Ubuntu | ||
| 7 | 17.04 image. | ||
| 3 | 8 | ||
| 4 | Memory Protection Keys provides a mechanism for enforcing page-based | 9 | Memory Protection Keys provides a mechanism for enforcing page-based |
| 5 | protections, but without requiring modification of the page tables | 10 | protections, but without requiring modification of the page tables |
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index df3276d6bfe3..8eed3f94bfc7 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
| @@ -1804,14 +1804,20 @@ config X86_SMAP | |||
| 1804 | If unsure, say Y. | 1804 | If unsure, say Y. |
| 1805 | 1805 | ||
| 1806 | config X86_INTEL_UMIP | 1806 | config X86_INTEL_UMIP |
| 1807 | def_bool n | 1807 | def_bool y |
| 1808 | depends on CPU_SUP_INTEL | 1808 | depends on CPU_SUP_INTEL |
| 1809 | prompt "Intel User Mode Instruction Prevention" if EXPERT | 1809 | prompt "Intel User Mode Instruction Prevention" if EXPERT |
| 1810 | ---help--- | 1810 | ---help--- |
| 1811 | The User Mode Instruction Prevention (UMIP) is a security | 1811 | The User Mode Instruction Prevention (UMIP) is a security |
| 1812 | feature in newer Intel processors. If enabled, a general | 1812 | feature in newer Intel processors. If enabled, a general |
| 1813 | protection fault is issued if the instructions SGDT, SLDT, | 1813 | protection fault is issued if the SGDT, SLDT, SIDT, SMSW |
| 1814 | SIDT, SMSW and STR are executed in user mode. | 1814 | or STR instructions are executed in user mode. These instructions |
| 1815 | unnecessarily expose information about the hardware state. | ||
| 1816 | |||
| 1817 | The vast majority of applications do not use these instructions. | ||
| 1818 | For the very few that do, software emulation is provided in | ||
| 1819 | specific cases in protected and virtual-8086 modes. Emulated | ||
| 1820 | results are dummy. | ||
| 1815 | 1821 | ||
| 1816 | config X86_INTEL_MPX | 1822 | config X86_INTEL_MPX |
| 1817 | prompt "Intel MPX (Memory Protection Extensions)" | 1823 | prompt "Intel MPX (Memory Protection Extensions)" |
diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c index a63fbc25ce84..8199a6187251 100644 --- a/arch/x86/boot/compressed/kaslr.c +++ b/arch/x86/boot/compressed/kaslr.c | |||
| @@ -171,7 +171,6 @@ parse_memmap(char *p, unsigned long long *start, unsigned long long *size) | |||
| 171 | static void mem_avoid_memmap(char *str) | 171 | static void mem_avoid_memmap(char *str) |
| 172 | { | 172 | { |
| 173 | static int i; | 173 | static int i; |
| 174 | int rc; | ||
| 175 | 174 | ||
| 176 | if (i >= MAX_MEMMAP_REGIONS) | 175 | if (i >= MAX_MEMMAP_REGIONS) |
| 177 | return; | 176 | return; |
| @@ -219,7 +218,7 @@ static int handle_mem_memmap(void) | |||
| 219 | return 0; | 218 | return 0; |
| 220 | 219 | ||
| 221 | tmp_cmdline = malloc(len + 1); | 220 | tmp_cmdline = malloc(len + 1); |
| 222 | if (!tmp_cmdline ) | 221 | if (!tmp_cmdline) |
| 223 | error("Failed to allocate space for tmp_cmdline"); | 222 | error("Failed to allocate space for tmp_cmdline"); |
| 224 | 223 | ||
| 225 | memcpy(tmp_cmdline, args, len); | 224 | memcpy(tmp_cmdline, args, len); |
| @@ -363,7 +362,7 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size, | |||
| 363 | cmd_line |= boot_params->hdr.cmd_line_ptr; | 362 | cmd_line |= boot_params->hdr.cmd_line_ptr; |
| 364 | /* Calculate size of cmd_line. */ | 363 | /* Calculate size of cmd_line. */ |
| 365 | ptr = (char *)(unsigned long)cmd_line; | 364 | ptr = (char *)(unsigned long)cmd_line; |
| 366 | for (cmd_line_size = 0; ptr[cmd_line_size++]; ) | 365 | for (cmd_line_size = 0; ptr[cmd_line_size++];) |
| 367 | ; | 366 | ; |
| 368 | mem_avoid[MEM_AVOID_CMDLINE].start = cmd_line; | 367 | mem_avoid[MEM_AVOID_CMDLINE].start = cmd_line; |
| 369 | mem_avoid[MEM_AVOID_CMDLINE].size = cmd_line_size; | 368 | mem_avoid[MEM_AVOID_CMDLINE].size = cmd_line_size; |
diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index a2b30ec69497..f81d50d7ceac 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S | |||
| @@ -51,15 +51,19 @@ ENTRY(native_usergs_sysret64) | |||
| 51 | END(native_usergs_sysret64) | 51 | END(native_usergs_sysret64) |
| 52 | #endif /* CONFIG_PARAVIRT */ | 52 | #endif /* CONFIG_PARAVIRT */ |
| 53 | 53 | ||
| 54 | .macro TRACE_IRQS_IRETQ | 54 | .macro TRACE_IRQS_FLAGS flags:req |
| 55 | #ifdef CONFIG_TRACE_IRQFLAGS | 55 | #ifdef CONFIG_TRACE_IRQFLAGS |
| 56 | bt $9, EFLAGS(%rsp) /* interrupts off? */ | 56 | bt $9, \flags /* interrupts off? */ |
| 57 | jnc 1f | 57 | jnc 1f |
| 58 | TRACE_IRQS_ON | 58 | TRACE_IRQS_ON |
| 59 | 1: | 59 | 1: |
| 60 | #endif | 60 | #endif |
| 61 | .endm | 61 | .endm |
| 62 | 62 | ||
| 63 | .macro TRACE_IRQS_IRETQ | ||
| 64 | TRACE_IRQS_FLAGS EFLAGS(%rsp) | ||
| 65 | .endm | ||
| 66 | |||
| 63 | /* | 67 | /* |
| 64 | * When dynamic function tracer is enabled it will add a breakpoint | 68 | * When dynamic function tracer is enabled it will add a breakpoint |
| 65 | * to all locations that it is about to modify, sync CPUs, update | 69 | * to all locations that it is about to modify, sync CPUs, update |
| @@ -148,8 +152,6 @@ ENTRY(entry_SYSCALL_64) | |||
| 148 | movq %rsp, PER_CPU_VAR(rsp_scratch) | 152 | movq %rsp, PER_CPU_VAR(rsp_scratch) |
| 149 | movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp | 153 | movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp |
| 150 | 154 | ||
| 151 | TRACE_IRQS_OFF | ||
| 152 | |||
| 153 | /* Construct struct pt_regs on stack */ | 155 | /* Construct struct pt_regs on stack */ |
| 154 | pushq $__USER_DS /* pt_regs->ss */ | 156 | pushq $__USER_DS /* pt_regs->ss */ |
| 155 | pushq PER_CPU_VAR(rsp_scratch) /* pt_regs->sp */ | 157 | pushq PER_CPU_VAR(rsp_scratch) /* pt_regs->sp */ |
| @@ -170,6 +172,8 @@ GLOBAL(entry_SYSCALL_64_after_hwframe) | |||
| 170 | sub $(6*8), %rsp /* pt_regs->bp, bx, r12-15 not saved */ | 172 | sub $(6*8), %rsp /* pt_regs->bp, bx, r12-15 not saved */ |
| 171 | UNWIND_HINT_REGS extra=0 | 173 | UNWIND_HINT_REGS extra=0 |
| 172 | 174 | ||
| 175 | TRACE_IRQS_OFF | ||
| 176 | |||
| 173 | /* | 177 | /* |
| 174 | * If we need to do entry work or if we guess we'll need to do | 178 | * If we need to do entry work or if we guess we'll need to do |
| 175 | * exit work, go straight to the slow path. | 179 | * exit work, go straight to the slow path. |
| @@ -943,11 +947,13 @@ ENTRY(native_load_gs_index) | |||
| 943 | FRAME_BEGIN | 947 | FRAME_BEGIN |
| 944 | pushfq | 948 | pushfq |
| 945 | DISABLE_INTERRUPTS(CLBR_ANY & ~CLBR_RDI) | 949 | DISABLE_INTERRUPTS(CLBR_ANY & ~CLBR_RDI) |
| 950 | TRACE_IRQS_OFF | ||
| 946 | SWAPGS | 951 | SWAPGS |
| 947 | .Lgs_change: | 952 | .Lgs_change: |
| 948 | movl %edi, %gs | 953 | movl %edi, %gs |
| 949 | 2: ALTERNATIVE "", "mfence", X86_BUG_SWAPGS_FENCE | 954 | 2: ALTERNATIVE "", "mfence", X86_BUG_SWAPGS_FENCE |
| 950 | SWAPGS | 955 | SWAPGS |
| 956 | TRACE_IRQS_FLAGS (%rsp) | ||
| 951 | popfq | 957 | popfq |
| 952 | FRAME_END | 958 | FRAME_END |
| 953 | ret | 959 | ret |
diff --git a/arch/x86/events/intel/uncore.c b/arch/x86/events/intel/uncore.c index d45e06346f14..7874c980d569 100644 --- a/arch/x86/events/intel/uncore.c +++ b/arch/x86/events/intel/uncore.c | |||
| @@ -975,10 +975,10 @@ static void uncore_pci_remove(struct pci_dev *pdev) | |||
| 975 | int i, phys_id, pkg; | 975 | int i, phys_id, pkg; |
| 976 | 976 | ||
| 977 | phys_id = uncore_pcibus_to_physid(pdev->bus); | 977 | phys_id = uncore_pcibus_to_physid(pdev->bus); |
| 978 | pkg = topology_phys_to_logical_pkg(phys_id); | ||
| 979 | 978 | ||
| 980 | box = pci_get_drvdata(pdev); | 979 | box = pci_get_drvdata(pdev); |
| 981 | if (!box) { | 980 | if (!box) { |
| 981 | pkg = topology_phys_to_logical_pkg(phys_id); | ||
| 982 | for (i = 0; i < UNCORE_EXTRA_PCI_DEV_MAX; i++) { | 982 | for (i = 0; i < UNCORE_EXTRA_PCI_DEV_MAX; i++) { |
| 983 | if (uncore_extra_pci_dev[pkg].dev[i] == pdev) { | 983 | if (uncore_extra_pci_dev[pkg].dev[i] == pdev) { |
| 984 | uncore_extra_pci_dev[pkg].dev[i] = NULL; | 984 | uncore_extra_pci_dev[pkg].dev[i] = NULL; |
| @@ -994,7 +994,7 @@ static void uncore_pci_remove(struct pci_dev *pdev) | |||
| 994 | return; | 994 | return; |
| 995 | 995 | ||
| 996 | pci_set_drvdata(pdev, NULL); | 996 | pci_set_drvdata(pdev, NULL); |
| 997 | pmu->boxes[pkg] = NULL; | 997 | pmu->boxes[box->pkgid] = NULL; |
| 998 | if (atomic_dec_return(&pmu->activeboxes) == 0) | 998 | if (atomic_dec_return(&pmu->activeboxes) == 0) |
| 999 | uncore_pmu_unregister(pmu); | 999 | uncore_pmu_unregister(pmu); |
| 1000 | uncore_box_exit(box); | 1000 | uncore_box_exit(box); |
diff --git a/arch/x86/events/intel/uncore.h b/arch/x86/events/intel/uncore.h index 4364191e7c6b..414dc7e7c950 100644 --- a/arch/x86/events/intel/uncore.h +++ b/arch/x86/events/intel/uncore.h | |||
| @@ -100,7 +100,7 @@ struct intel_uncore_extra_reg { | |||
| 100 | 100 | ||
| 101 | struct intel_uncore_box { | 101 | struct intel_uncore_box { |
| 102 | int pci_phys_id; | 102 | int pci_phys_id; |
| 103 | int pkgid; | 103 | int pkgid; /* Logical package ID */ |
| 104 | int n_active; /* number of active events */ | 104 | int n_active; /* number of active events */ |
| 105 | int n_events; | 105 | int n_events; |
| 106 | int cpu; /* cpu to collect events */ | 106 | int cpu; /* cpu to collect events */ |
diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c index f4e4168455a8..6d8044ab1060 100644 --- a/arch/x86/events/intel/uncore_snbep.c +++ b/arch/x86/events/intel/uncore_snbep.c | |||
| @@ -1057,7 +1057,7 @@ static void snbep_qpi_enable_event(struct intel_uncore_box *box, struct perf_eve | |||
| 1057 | 1057 | ||
| 1058 | if (reg1->idx != EXTRA_REG_NONE) { | 1058 | if (reg1->idx != EXTRA_REG_NONE) { |
| 1059 | int idx = box->pmu->pmu_idx + SNBEP_PCI_QPI_PORT0_FILTER; | 1059 | int idx = box->pmu->pmu_idx + SNBEP_PCI_QPI_PORT0_FILTER; |
| 1060 | int pkg = topology_phys_to_logical_pkg(box->pci_phys_id); | 1060 | int pkg = box->pkgid; |
| 1061 | struct pci_dev *filter_pdev = uncore_extra_pci_dev[pkg].dev[idx]; | 1061 | struct pci_dev *filter_pdev = uncore_extra_pci_dev[pkg].dev[idx]; |
| 1062 | 1062 | ||
| 1063 | if (filter_pdev) { | 1063 | if (filter_pdev) { |
diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h index 3a091cea36c5..0d157d2a1e2a 100644 --- a/arch/x86/include/asm/elf.h +++ b/arch/x86/include/asm/elf.h | |||
| @@ -309,6 +309,7 @@ static inline int mmap_is_ia32(void) | |||
| 309 | extern unsigned long task_size_32bit(void); | 309 | extern unsigned long task_size_32bit(void); |
| 310 | extern unsigned long task_size_64bit(int full_addr_space); | 310 | extern unsigned long task_size_64bit(int full_addr_space); |
| 311 | extern unsigned long get_mmap_base(int is_legacy); | 311 | extern unsigned long get_mmap_base(int is_legacy); |
| 312 | extern bool mmap_address_hint_valid(unsigned long addr, unsigned long len); | ||
| 312 | 313 | ||
| 313 | #ifdef CONFIG_X86_32 | 314 | #ifdef CONFIG_X86_32 |
| 314 | 315 | ||
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h index b80e46733909..2851077b6051 100644 --- a/arch/x86/include/asm/hw_irq.h +++ b/arch/x86/include/asm/hw_irq.h | |||
| @@ -99,14 +99,6 @@ struct irq_alloc_info { | |||
| 99 | void *dmar_data; | 99 | void *dmar_data; |
| 100 | }; | 100 | }; |
| 101 | #endif | 101 | #endif |
| 102 | #ifdef CONFIG_HT_IRQ | ||
| 103 | struct { | ||
| 104 | int ht_pos; | ||
| 105 | int ht_idx; | ||
| 106 | struct pci_dev *ht_dev; | ||
| 107 | void *ht_update; | ||
| 108 | }; | ||
| 109 | #endif | ||
| 110 | #ifdef CONFIG_X86_UV | 102 | #ifdef CONFIG_X86_UV |
| 111 | struct { | 103 | struct { |
| 112 | int uv_limit; | 104 | int uv_limit; |
diff --git a/arch/x86/include/asm/hypertransport.h b/arch/x86/include/asm/hypertransport.h deleted file mode 100644 index 5d55df352879..000000000000 --- a/arch/x86/include/asm/hypertransport.h +++ /dev/null | |||
| @@ -1,46 +0,0 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | #ifndef _ASM_X86_HYPERTRANSPORT_H | ||
| 3 | #define _ASM_X86_HYPERTRANSPORT_H | ||
| 4 | |||
| 5 | /* | ||
| 6 | * Constants for x86 Hypertransport Interrupts. | ||
| 7 | */ | ||
| 8 | |||
| 9 | #define HT_IRQ_LOW_BASE 0xf8000000 | ||
| 10 | |||
| 11 | #define HT_IRQ_LOW_VECTOR_SHIFT 16 | ||
| 12 | #define HT_IRQ_LOW_VECTOR_MASK 0x00ff0000 | ||
| 13 | #define HT_IRQ_LOW_VECTOR(v) \ | ||
| 14 | (((v) << HT_IRQ_LOW_VECTOR_SHIFT) & HT_IRQ_LOW_VECTOR_MASK) | ||
| 15 | |||
| 16 | #define HT_IRQ_LOW_DEST_ID_SHIFT 8 | ||
| 17 | #define HT_IRQ_LOW_DEST_ID_MASK 0x0000ff00 | ||
| 18 | #define HT_IRQ_LOW_DEST_ID(v) \ | ||
| 19 | (((v) << HT_IRQ_LOW_DEST_ID_SHIFT) & HT_IRQ_LOW_DEST_ID_MASK) | ||
| 20 | |||
| 21 | #define HT_IRQ_LOW_DM_PHYSICAL 0x0000000 | ||
| 22 | #define HT_IRQ_LOW_DM_LOGICAL 0x0000040 | ||
| 23 | |||
| 24 | #define HT_IRQ_LOW_RQEOI_EDGE 0x0000000 | ||
| 25 | #define HT_IRQ_LOW_RQEOI_LEVEL 0x0000020 | ||
| 26 | |||
| 27 | |||
| 28 | #define HT_IRQ_LOW_MT_FIXED 0x0000000 | ||
| 29 | #define HT_IRQ_LOW_MT_ARBITRATED 0x0000004 | ||
| 30 | #define HT_IRQ_LOW_MT_SMI 0x0000008 | ||
| 31 | #define HT_IRQ_LOW_MT_NMI 0x000000c | ||
| 32 | #define HT_IRQ_LOW_MT_INIT 0x0000010 | ||
| 33 | #define HT_IRQ_LOW_MT_STARTUP 0x0000014 | ||
| 34 | #define HT_IRQ_LOW_MT_EXTINT 0x0000018 | ||
| 35 | #define HT_IRQ_LOW_MT_LINT1 0x000008c | ||
| 36 | #define HT_IRQ_LOW_MT_LINT0 0x0000098 | ||
| 37 | |||
| 38 | #define HT_IRQ_LOW_IRQ_MASKED 0x0000001 | ||
| 39 | |||
| 40 | |||
| 41 | #define HT_IRQ_HIGH_DEST_ID_SHIFT 0 | ||
| 42 | #define HT_IRQ_HIGH_DEST_ID_MASK 0x00ffffff | ||
| 43 | #define HT_IRQ_HIGH_DEST_ID(v) \ | ||
| 44 | ((((v) >> 8) << HT_IRQ_HIGH_DEST_ID_SHIFT) & HT_IRQ_HIGH_DEST_ID_MASK) | ||
| 45 | |||
| 46 | #endif /* _ASM_X86_HYPERTRANSPORT_H */ | ||
diff --git a/arch/x86/include/asm/insn-eval.h b/arch/x86/include/asm/insn-eval.h index e1d3b4ce8a92..2b6ccf2c49f1 100644 --- a/arch/x86/include/asm/insn-eval.h +++ b/arch/x86/include/asm/insn-eval.h | |||
| @@ -18,6 +18,6 @@ | |||
| 18 | void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs); | 18 | void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs); |
| 19 | int insn_get_modrm_rm_off(struct insn *insn, struct pt_regs *regs); | 19 | int insn_get_modrm_rm_off(struct insn *insn, struct pt_regs *regs); |
| 20 | unsigned long insn_get_seg_base(struct pt_regs *regs, int seg_reg_idx); | 20 | unsigned long insn_get_seg_base(struct pt_regs *regs, int seg_reg_idx); |
| 21 | char insn_get_code_seg_params(struct pt_regs *regs); | 21 | int insn_get_code_seg_params(struct pt_regs *regs); |
| 22 | 22 | ||
| 23 | #endif /* _ASM_X86_INSN_EVAL_H */ | 23 | #endif /* _ASM_X86_INSN_EVAL_H */ |
diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h index 93ae8aee1780..95e948627fd0 100644 --- a/arch/x86/include/asm/io.h +++ b/arch/x86/include/asm/io.h | |||
| @@ -111,6 +111,10 @@ build_mmio_write(__writeq, "q", unsigned long, "r", ) | |||
| 111 | 111 | ||
| 112 | #endif | 112 | #endif |
| 113 | 113 | ||
| 114 | #define ARCH_HAS_VALID_PHYS_ADDR_RANGE | ||
| 115 | extern int valid_phys_addr_range(phys_addr_t addr, size_t size); | ||
| 116 | extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size); | ||
| 117 | |||
| 114 | /** | 118 | /** |
| 115 | * virt_to_phys - map virtual addresses to physical | 119 | * virt_to_phys - map virtual addresses to physical |
| 116 | * @address: address to remap | 120 | * @address: address to remap |
diff --git a/arch/x86/include/asm/irqdomain.h b/arch/x86/include/asm/irqdomain.h index f695cc6b8e1f..139feef467f7 100644 --- a/arch/x86/include/asm/irqdomain.h +++ b/arch/x86/include/asm/irqdomain.h | |||
| @@ -56,10 +56,4 @@ extern void arch_init_msi_domain(struct irq_domain *domain); | |||
| 56 | static inline void arch_init_msi_domain(struct irq_domain *domain) { } | 56 | static inline void arch_init_msi_domain(struct irq_domain *domain) { } |
| 57 | #endif | 57 | #endif |
| 58 | 58 | ||
| 59 | #ifdef CONFIG_HT_IRQ | ||
| 60 | extern void arch_init_htirq_domain(struct irq_domain *domain); | ||
| 61 | #else | ||
| 62 | static inline void arch_init_htirq_domain(struct irq_domain *domain) { } | ||
| 63 | #endif | ||
| 64 | |||
| 65 | #endif | 59 | #endif |
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 2db7cf720b04..cc16fa882e3e 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h | |||
| @@ -132,6 +132,7 @@ struct cpuinfo_x86 { | |||
| 132 | /* Index into per_cpu list: */ | 132 | /* Index into per_cpu list: */ |
| 133 | u16 cpu_index; | 133 | u16 cpu_index; |
| 134 | u32 microcode; | 134 | u32 microcode; |
| 135 | unsigned initialized : 1; | ||
| 135 | } __randomize_layout; | 136 | } __randomize_layout; |
| 136 | 137 | ||
| 137 | struct cpuid_regs { | 138 | struct cpuid_regs { |
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index ef9e02e614d0..f4c463df8b08 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
| @@ -342,13 +342,12 @@ acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long e | |||
| 342 | #ifdef CONFIG_X86_IO_APIC | 342 | #ifdef CONFIG_X86_IO_APIC |
| 343 | #define MP_ISA_BUS 0 | 343 | #define MP_ISA_BUS 0 |
| 344 | 344 | ||
| 345 | static int __init mp_register_ioapic_irq(u8 bus_irq, u8 polarity, | ||
| 346 | u8 trigger, u32 gsi); | ||
| 347 | |||
| 345 | static void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, | 348 | static void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, |
| 346 | u32 gsi) | 349 | u32 gsi) |
| 347 | { | 350 | { |
| 348 | int ioapic; | ||
| 349 | int pin; | ||
| 350 | struct mpc_intsrc mp_irq; | ||
| 351 | |||
| 352 | /* | 351 | /* |
| 353 | * Check bus_irq boundary. | 352 | * Check bus_irq boundary. |
| 354 | */ | 353 | */ |
| @@ -358,14 +357,6 @@ static void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, | |||
| 358 | } | 357 | } |
| 359 | 358 | ||
| 360 | /* | 359 | /* |
| 361 | * Convert 'gsi' to 'ioapic.pin'. | ||
| 362 | */ | ||
| 363 | ioapic = mp_find_ioapic(gsi); | ||
| 364 | if (ioapic < 0) | ||
| 365 | return; | ||
| 366 | pin = mp_find_ioapic_pin(ioapic, gsi); | ||
| 367 | |||
| 368 | /* | ||
| 369 | * TBD: This check is for faulty timer entries, where the override | 360 | * TBD: This check is for faulty timer entries, where the override |
| 370 | * erroneously sets the trigger to level, resulting in a HUGE | 361 | * erroneously sets the trigger to level, resulting in a HUGE |
| 371 | * increase of timer interrupts! | 362 | * increase of timer interrupts! |
| @@ -373,16 +364,8 @@ static void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, | |||
| 373 | if ((bus_irq == 0) && (trigger == 3)) | 364 | if ((bus_irq == 0) && (trigger == 3)) |
| 374 | trigger = 1; | 365 | trigger = 1; |
| 375 | 366 | ||
| 376 | mp_irq.type = MP_INTSRC; | 367 | if (mp_register_ioapic_irq(bus_irq, polarity, trigger, gsi) < 0) |
| 377 | mp_irq.irqtype = mp_INT; | 368 | return; |
| 378 | mp_irq.irqflag = (trigger << 2) | polarity; | ||
| 379 | mp_irq.srcbus = MP_ISA_BUS; | ||
| 380 | mp_irq.srcbusirq = bus_irq; /* IRQ */ | ||
| 381 | mp_irq.dstapic = mpc_ioapic_id(ioapic); /* APIC ID */ | ||
| 382 | mp_irq.dstirq = pin; /* INTIN# */ | ||
| 383 | |||
| 384 | mp_save_irq(&mp_irq); | ||
| 385 | |||
| 386 | /* | 369 | /* |
| 387 | * Reset default identity mapping if gsi is also an legacy IRQ, | 370 | * Reset default identity mapping if gsi is also an legacy IRQ, |
| 388 | * otherwise there will be more than one entry with the same GSI | 371 | * otherwise there will be more than one entry with the same GSI |
| @@ -429,6 +412,34 @@ static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger, | |||
| 429 | return 0; | 412 | return 0; |
| 430 | } | 413 | } |
| 431 | 414 | ||
| 415 | static int __init mp_register_ioapic_irq(u8 bus_irq, u8 polarity, | ||
| 416 | u8 trigger, u32 gsi) | ||
| 417 | { | ||
| 418 | struct mpc_intsrc mp_irq; | ||
| 419 | int ioapic, pin; | ||
| 420 | |||
| 421 | /* Convert 'gsi' to 'ioapic.pin'(INTIN#) */ | ||
| 422 | ioapic = mp_find_ioapic(gsi); | ||
| 423 | if (ioapic < 0) { | ||
| 424 | pr_warn("Failed to find ioapic for gsi : %u\n", gsi); | ||
| 425 | return ioapic; | ||
| 426 | } | ||
| 427 | |||
| 428 | pin = mp_find_ioapic_pin(ioapic, gsi); | ||
| 429 | |||
| 430 | mp_irq.type = MP_INTSRC; | ||
| 431 | mp_irq.irqtype = mp_INT; | ||
| 432 | mp_irq.irqflag = (trigger << 2) | polarity; | ||
| 433 | mp_irq.srcbus = MP_ISA_BUS; | ||
| 434 | mp_irq.srcbusirq = bus_irq; | ||
| 435 | mp_irq.dstapic = mpc_ioapic_id(ioapic); | ||
| 436 | mp_irq.dstirq = pin; | ||
| 437 | |||
| 438 | mp_save_irq(&mp_irq); | ||
| 439 | |||
| 440 | return 0; | ||
| 441 | } | ||
| 442 | |||
| 432 | static int __init | 443 | static int __init |
| 433 | acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end) | 444 | acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end) |
| 434 | { | 445 | { |
| @@ -473,7 +484,11 @@ static void __init acpi_sci_ioapic_setup(u8 bus_irq, u16 polarity, u16 trigger, | |||
| 473 | if (acpi_sci_flags & ACPI_MADT_POLARITY_MASK) | 484 | if (acpi_sci_flags & ACPI_MADT_POLARITY_MASK) |
| 474 | polarity = acpi_sci_flags & ACPI_MADT_POLARITY_MASK; | 485 | polarity = acpi_sci_flags & ACPI_MADT_POLARITY_MASK; |
| 475 | 486 | ||
| 476 | mp_override_legacy_irq(bus_irq, polarity, trigger, gsi); | 487 | if (bus_irq < NR_IRQS_LEGACY) |
| 488 | mp_override_legacy_irq(bus_irq, polarity, trigger, gsi); | ||
| 489 | else | ||
| 490 | mp_register_ioapic_irq(bus_irq, polarity, trigger, gsi); | ||
| 491 | |||
| 477 | acpi_penalize_sci_irq(bus_irq, trigger, polarity); | 492 | acpi_penalize_sci_irq(bus_irq, trigger, polarity); |
| 478 | 493 | ||
| 479 | /* | 494 | /* |
diff --git a/arch/x86/kernel/apic/Makefile b/arch/x86/kernel/apic/Makefile index a9e08924927e..a6fcaf16cdbf 100644 --- a/arch/x86/kernel/apic/Makefile +++ b/arch/x86/kernel/apic/Makefile | |||
| @@ -12,7 +12,6 @@ obj-y += hw_nmi.o | |||
| 12 | 12 | ||
| 13 | obj-$(CONFIG_X86_IO_APIC) += io_apic.o | 13 | obj-$(CONFIG_X86_IO_APIC) += io_apic.o |
| 14 | obj-$(CONFIG_PCI_MSI) += msi.o | 14 | obj-$(CONFIG_PCI_MSI) += msi.o |
| 15 | obj-$(CONFIG_HT_IRQ) += htirq.o | ||
| 16 | obj-$(CONFIG_SMP) += ipi.o | 15 | obj-$(CONFIG_SMP) += ipi.o |
| 17 | 16 | ||
| 18 | ifeq ($(CONFIG_X86_64),y) | 17 | ifeq ($(CONFIG_X86_64),y) |
diff --git a/arch/x86/kernel/apic/htirq.c b/arch/x86/kernel/apic/htirq.c deleted file mode 100644 index b07075dce8b7..000000000000 --- a/arch/x86/kernel/apic/htirq.c +++ /dev/null | |||
| @@ -1,198 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Support Hypertransport IRQ | ||
| 3 | * | ||
| 4 | * Copyright (C) 1997, 1998, 1999, 2000, 2009 Ingo Molnar, Hajnalka Szabo | ||
| 5 | * Moved from arch/x86/kernel/apic/io_apic.c. | ||
| 6 | * Jiang Liu <jiang.liu@linux.intel.com> | ||
| 7 | * Add support of hierarchical irqdomain | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License version 2 as | ||
| 11 | * published by the Free Software Foundation. | ||
| 12 | */ | ||
| 13 | #include <linux/mm.h> | ||
| 14 | #include <linux/interrupt.h> | ||
| 15 | #include <linux/init.h> | ||
| 16 | #include <linux/device.h> | ||
| 17 | #include <linux/pci.h> | ||
| 18 | #include <linux/htirq.h> | ||
| 19 | #include <asm/irqdomain.h> | ||
| 20 | #include <asm/hw_irq.h> | ||
| 21 | #include <asm/apic.h> | ||
| 22 | #include <asm/hypertransport.h> | ||
| 23 | |||
| 24 | static struct irq_domain *htirq_domain; | ||
| 25 | |||
| 26 | /* | ||
| 27 | * Hypertransport interrupt support | ||
| 28 | */ | ||
| 29 | static int | ||
| 30 | ht_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force) | ||
| 31 | { | ||
| 32 | struct irq_data *parent = data->parent_data; | ||
| 33 | int ret; | ||
| 34 | |||
| 35 | ret = parent->chip->irq_set_affinity(parent, mask, force); | ||
| 36 | if (ret >= 0) { | ||
| 37 | struct ht_irq_msg msg; | ||
| 38 | struct irq_cfg *cfg = irqd_cfg(data); | ||
| 39 | |||
| 40 | fetch_ht_irq_msg(data->irq, &msg); | ||
| 41 | msg.address_lo &= ~(HT_IRQ_LOW_VECTOR_MASK | | ||
| 42 | HT_IRQ_LOW_DEST_ID_MASK); | ||
| 43 | msg.address_lo |= HT_IRQ_LOW_VECTOR(cfg->vector) | | ||
| 44 | HT_IRQ_LOW_DEST_ID(cfg->dest_apicid); | ||
| 45 | msg.address_hi &= ~(HT_IRQ_HIGH_DEST_ID_MASK); | ||
| 46 | msg.address_hi |= HT_IRQ_HIGH_DEST_ID(cfg->dest_apicid); | ||
| 47 | write_ht_irq_msg(data->irq, &msg); | ||
| 48 | } | ||
| 49 | |||
| 50 | return ret; | ||
| 51 | } | ||
| 52 | |||
| 53 | static struct irq_chip ht_irq_chip = { | ||
| 54 | .name = "PCI-HT", | ||
| 55 | .irq_mask = mask_ht_irq, | ||
| 56 | .irq_unmask = unmask_ht_irq, | ||
| 57 | .irq_ack = irq_chip_ack_parent, | ||
| 58 | .irq_set_affinity = ht_set_affinity, | ||
| 59 | .irq_retrigger = irq_chip_retrigger_hierarchy, | ||
| 60 | .flags = IRQCHIP_SKIP_SET_WAKE, | ||
| 61 | }; | ||
| 62 | |||
| 63 | static int htirq_domain_alloc(struct irq_domain *domain, unsigned int virq, | ||
| 64 | unsigned int nr_irqs, void *arg) | ||
| 65 | { | ||
| 66 | struct ht_irq_cfg *ht_cfg; | ||
| 67 | struct irq_alloc_info *info = arg; | ||
| 68 | struct pci_dev *dev; | ||
| 69 | irq_hw_number_t hwirq; | ||
| 70 | int ret; | ||
| 71 | |||
| 72 | if (nr_irqs > 1 || !info) | ||
| 73 | return -EINVAL; | ||
| 74 | |||
| 75 | dev = info->ht_dev; | ||
| 76 | hwirq = (info->ht_idx & 0xFF) | | ||
| 77 | PCI_DEVID(dev->bus->number, dev->devfn) << 8 | | ||
| 78 | (pci_domain_nr(dev->bus) & 0xFFFFFFFF) << 24; | ||
| 79 | if (irq_find_mapping(domain, hwirq) > 0) | ||
| 80 | return -EEXIST; | ||
| 81 | |||
| 82 | ht_cfg = kmalloc(sizeof(*ht_cfg), GFP_KERNEL); | ||
| 83 | if (!ht_cfg) | ||
| 84 | return -ENOMEM; | ||
| 85 | |||
| 86 | ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, info); | ||
| 87 | if (ret < 0) { | ||
| 88 | kfree(ht_cfg); | ||
| 89 | return ret; | ||
| 90 | } | ||
| 91 | |||
| 92 | /* Initialize msg to a value that will never match the first write. */ | ||
| 93 | ht_cfg->msg.address_lo = 0xffffffff; | ||
| 94 | ht_cfg->msg.address_hi = 0xffffffff; | ||
| 95 | ht_cfg->dev = info->ht_dev; | ||
| 96 | ht_cfg->update = info->ht_update; | ||
| 97 | ht_cfg->pos = info->ht_pos; | ||
| 98 | ht_cfg->idx = 0x10 + (info->ht_idx * 2); | ||
| 99 | irq_domain_set_info(domain, virq, hwirq, &ht_irq_chip, ht_cfg, | ||
| 100 | handle_edge_irq, ht_cfg, "edge"); | ||
| 101 | |||
| 102 | return 0; | ||
| 103 | } | ||
| 104 | |||
| 105 | static void htirq_domain_free(struct irq_domain *domain, unsigned int virq, | ||
| 106 | unsigned int nr_irqs) | ||
| 107 | { | ||
| 108 | struct irq_data *irq_data = irq_domain_get_irq_data(domain, virq); | ||
| 109 | |||
| 110 | BUG_ON(nr_irqs != 1); | ||
| 111 | kfree(irq_data->chip_data); | ||
| 112 | irq_domain_free_irqs_top(domain, virq, nr_irqs); | ||
| 113 | } | ||
| 114 | |||
| 115 | static int htirq_domain_activate(struct irq_domain *domain, | ||
| 116 | struct irq_data *irq_data, bool early) | ||
| 117 | { | ||
| 118 | struct ht_irq_msg msg; | ||
| 119 | struct irq_cfg *cfg = irqd_cfg(irq_data); | ||
| 120 | |||
| 121 | msg.address_hi = HT_IRQ_HIGH_DEST_ID(cfg->dest_apicid); | ||
| 122 | msg.address_lo = | ||
| 123 | HT_IRQ_LOW_BASE | | ||
| 124 | HT_IRQ_LOW_DEST_ID(cfg->dest_apicid) | | ||
| 125 | HT_IRQ_LOW_VECTOR(cfg->vector) | | ||
| 126 | ((apic->irq_dest_mode == 0) ? | ||
| 127 | HT_IRQ_LOW_DM_PHYSICAL : | ||
| 128 | HT_IRQ_LOW_DM_LOGICAL) | | ||
| 129 | HT_IRQ_LOW_RQEOI_EDGE | | ||
| 130 | ((apic->irq_delivery_mode != dest_LowestPrio) ? | ||
| 131 | HT_IRQ_LOW_MT_FIXED : | ||
| 132 | HT_IRQ_LOW_MT_ARBITRATED) | | ||
| 133 | HT_IRQ_LOW_IRQ_MASKED; | ||
| 134 | write_ht_irq_msg(irq_data->irq, &msg); | ||
| 135 | return 0; | ||
| 136 | } | ||
| 137 | |||
| 138 | static void htirq_domain_deactivate(struct irq_domain *domain, | ||
| 139 | struct irq_data *irq_data) | ||
| 140 | { | ||
| 141 | struct ht_irq_msg msg; | ||
| 142 | |||
| 143 | memset(&msg, 0, sizeof(msg)); | ||
| 144 | write_ht_irq_msg(irq_data->irq, &msg); | ||
| 145 | } | ||
| 146 | |||
| 147 | static const struct irq_domain_ops htirq_domain_ops = { | ||
| 148 | .alloc = htirq_domain_alloc, | ||
| 149 | .free = htirq_domain_free, | ||
| 150 | .activate = htirq_domain_activate, | ||
| 151 | .deactivate = htirq_domain_deactivate, | ||
| 152 | }; | ||
| 153 | |||
| 154 | void __init arch_init_htirq_domain(struct irq_domain *parent) | ||
| 155 | { | ||
| 156 | struct fwnode_handle *fn; | ||
| 157 | |||
| 158 | if (disable_apic) | ||
| 159 | return; | ||
| 160 | |||
| 161 | fn = irq_domain_alloc_named_fwnode("PCI-HT"); | ||
| 162 | if (!fn) | ||
| 163 | goto warn; | ||
| 164 | |||
| 165 | htirq_domain = irq_domain_create_tree(fn, &htirq_domain_ops, NULL); | ||
| 166 | irq_domain_free_fwnode(fn); | ||
| 167 | if (!htirq_domain) | ||
| 168 | goto warn; | ||
| 169 | |||
| 170 | htirq_domain->parent = parent; | ||
| 171 | return; | ||
| 172 | |||
| 173 | warn: | ||
| 174 | pr_warn("Failed to initialize irqdomain for HTIRQ.\n"); | ||
| 175 | } | ||
| 176 | |||
| 177 | int arch_setup_ht_irq(int idx, int pos, struct pci_dev *dev, | ||
| 178 | ht_irq_update_t *update) | ||
| 179 | { | ||
| 180 | struct irq_alloc_info info; | ||
| 181 | |||
| 182 | if (!htirq_domain) | ||
| 183 | return -ENOSYS; | ||
| 184 | |||
| 185 | init_irq_alloc_info(&info, NULL); | ||
| 186 | info.ht_idx = idx; | ||
| 187 | info.ht_pos = pos; | ||
| 188 | info.ht_dev = dev; | ||
| 189 | info.ht_update = update; | ||
| 190 | |||
| 191 | return irq_domain_alloc_irqs(htirq_domain, 1, dev_to_node(&dev->dev), | ||
| 192 | &info); | ||
| 193 | } | ||
| 194 | |||
| 195 | void arch_teardown_ht_irq(unsigned int irq) | ||
| 196 | { | ||
| 197 | irq_domain_free_irqs(irq, 1); | ||
| 198 | } | ||
diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c index 05c85e693a5d..6a823a25eaff 100644 --- a/arch/x86/kernel/apic/vector.c +++ b/arch/x86/kernel/apic/vector.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Local APIC related interfaces to support IOAPIC, MSI, HT_IRQ etc. | 2 | * Local APIC related interfaces to support IOAPIC, MSI, etc. |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 1997, 1998, 1999, 2000, 2009 Ingo Molnar, Hajnalka Szabo | 4 | * Copyright (C) 1997, 1998, 1999, 2000, 2009 Ingo Molnar, Hajnalka Szabo |
| 5 | * Moved from arch/x86/kernel/apic/io_apic.c. | 5 | * Moved from arch/x86/kernel/apic/io_apic.c. |
| @@ -601,7 +601,7 @@ int __init arch_probe_nr_irqs(void) | |||
| 601 | nr_irqs = NR_VECTORS * nr_cpu_ids; | 601 | nr_irqs = NR_VECTORS * nr_cpu_ids; |
| 602 | 602 | ||
| 603 | nr = (gsi_top + nr_legacy_irqs()) + 8 * nr_cpu_ids; | 603 | nr = (gsi_top + nr_legacy_irqs()) + 8 * nr_cpu_ids; |
| 604 | #if defined(CONFIG_PCI_MSI) || defined(CONFIG_HT_IRQ) | 604 | #if defined(CONFIG_PCI_MSI) |
| 605 | /* | 605 | /* |
| 606 | * for MSI and HT dyn irq | 606 | * for MSI and HT dyn irq |
| 607 | */ | 607 | */ |
| @@ -663,7 +663,6 @@ int __init arch_early_irq_init(void) | |||
| 663 | irq_set_default_host(x86_vector_domain); | 663 | irq_set_default_host(x86_vector_domain); |
| 664 | 664 | ||
| 665 | arch_init_msi_domain(x86_vector_domain); | 665 | arch_init_msi_domain(x86_vector_domain); |
| 666 | arch_init_htirq_domain(x86_vector_domain); | ||
| 667 | 666 | ||
| 668 | BUG_ON(!alloc_cpumask_var(&vector_searchmask, GFP_KERNEL)); | 667 | BUG_ON(!alloc_cpumask_var(&vector_searchmask, GFP_KERNEL)); |
| 669 | 668 | ||
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 13ae9e5eec2f..fa998ca8aa5a 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
| @@ -341,6 +341,8 @@ static __always_inline void setup_umip(struct cpuinfo_x86 *c) | |||
| 341 | 341 | ||
| 342 | cr4_set_bits(X86_CR4_UMIP); | 342 | cr4_set_bits(X86_CR4_UMIP); |
| 343 | 343 | ||
| 344 | pr_info("x86/cpu: Activated the Intel User Mode Instruction Prevention (UMIP) CPU feature\n"); | ||
| 345 | |||
| 344 | return; | 346 | return; |
| 345 | 347 | ||
| 346 | out: | 348 | out: |
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index 410c5dadcee3..3a4b12809ab5 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c | |||
| @@ -431,6 +431,7 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type) | |||
| 431 | } | 431 | } |
| 432 | 432 | ||
| 433 | static unsigned long mpf_base; | 433 | static unsigned long mpf_base; |
| 434 | static bool mpf_found; | ||
| 434 | 435 | ||
| 435 | static unsigned long __init get_mpc_size(unsigned long physptr) | 436 | static unsigned long __init get_mpc_size(unsigned long physptr) |
| 436 | { | 437 | { |
| @@ -504,7 +505,7 @@ void __init default_get_smp_config(unsigned int early) | |||
| 504 | if (!smp_found_config) | 505 | if (!smp_found_config) |
| 505 | return; | 506 | return; |
| 506 | 507 | ||
| 507 | if (!mpf_base) | 508 | if (!mpf_found) |
| 508 | return; | 509 | return; |
| 509 | 510 | ||
| 510 | if (acpi_lapic && early) | 511 | if (acpi_lapic && early) |
| @@ -593,6 +594,7 @@ static int __init smp_scan_config(unsigned long base, unsigned long length) | |||
| 593 | smp_found_config = 1; | 594 | smp_found_config = 1; |
| 594 | #endif | 595 | #endif |
| 595 | mpf_base = base; | 596 | mpf_base = base; |
| 597 | mpf_found = true; | ||
| 596 | 598 | ||
| 597 | pr_info("found SMP MP-table at [mem %#010lx-%#010lx] mapped at [%p]\n", | 599 | pr_info("found SMP MP-table at [mem %#010lx-%#010lx] mapped at [%p]\n", |
| 598 | base, base + sizeof(*mpf) - 1, mpf); | 600 | base, base + sizeof(*mpf) - 1, mpf); |
| @@ -858,7 +860,7 @@ static int __init update_mp_table(void) | |||
| 858 | if (!enable_update_mptable) | 860 | if (!enable_update_mptable) |
| 859 | return 0; | 861 | return 0; |
| 860 | 862 | ||
| 861 | if (!mpf_base) | 863 | if (!mpf_found) |
| 862 | return 0; | 864 | return 0; |
| 863 | 865 | ||
| 864 | mpf = early_memremap(mpf_base, sizeof(*mpf)); | 866 | mpf = early_memremap(mpf_base, sizeof(*mpf)); |
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 5f59e6bee123..3d01df7d7cf6 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
| @@ -101,9 +101,6 @@ DEFINE_PER_CPU_READ_MOSTLY(struct cpuinfo_x86, cpu_info); | |||
| 101 | EXPORT_PER_CPU_SYMBOL(cpu_info); | 101 | EXPORT_PER_CPU_SYMBOL(cpu_info); |
| 102 | 102 | ||
| 103 | /* Logical package management. We might want to allocate that dynamically */ | 103 | /* Logical package management. We might want to allocate that dynamically */ |
| 104 | static int *physical_to_logical_pkg __read_mostly; | ||
| 105 | static unsigned long *physical_package_map __read_mostly;; | ||
| 106 | static unsigned int max_physical_pkg_id __read_mostly; | ||
| 107 | unsigned int __max_logical_packages __read_mostly; | 104 | unsigned int __max_logical_packages __read_mostly; |
| 108 | EXPORT_SYMBOL(__max_logical_packages); | 105 | EXPORT_SYMBOL(__max_logical_packages); |
| 109 | static unsigned int logical_packages __read_mostly; | 106 | static unsigned int logical_packages __read_mostly; |
| @@ -281,108 +278,48 @@ static void notrace start_secondary(void *unused) | |||
| 281 | } | 278 | } |
| 282 | 279 | ||
| 283 | /** | 280 | /** |
| 281 | * topology_phys_to_logical_pkg - Map a physical package id to a logical | ||
| 282 | * | ||
| 283 | * Returns logical package id or -1 if not found | ||
| 284 | */ | ||
| 285 | int topology_phys_to_logical_pkg(unsigned int phys_pkg) | ||
| 286 | { | ||
| 287 | int cpu; | ||
| 288 | |||
| 289 | for_each_possible_cpu(cpu) { | ||
| 290 | struct cpuinfo_x86 *c = &cpu_data(cpu); | ||
| 291 | |||
| 292 | if (c->initialized && c->phys_proc_id == phys_pkg) | ||
| 293 | return c->logical_proc_id; | ||
| 294 | } | ||
| 295 | return -1; | ||
| 296 | } | ||
| 297 | EXPORT_SYMBOL(topology_phys_to_logical_pkg); | ||
| 298 | |||
| 299 | /** | ||
| 284 | * topology_update_package_map - Update the physical to logical package map | 300 | * topology_update_package_map - Update the physical to logical package map |
| 285 | * @pkg: The physical package id as retrieved via CPUID | 301 | * @pkg: The physical package id as retrieved via CPUID |
| 286 | * @cpu: The cpu for which this is updated | 302 | * @cpu: The cpu for which this is updated |
| 287 | */ | 303 | */ |
| 288 | int topology_update_package_map(unsigned int pkg, unsigned int cpu) | 304 | int topology_update_package_map(unsigned int pkg, unsigned int cpu) |
| 289 | { | 305 | { |
| 290 | unsigned int new; | 306 | int new; |
| 291 | 307 | ||
| 292 | /* Called from early boot ? */ | 308 | /* Already available somewhere? */ |
| 293 | if (!physical_package_map) | 309 | new = topology_phys_to_logical_pkg(pkg); |
| 294 | return 0; | 310 | if (new >= 0) |
| 295 | |||
| 296 | if (pkg >= max_physical_pkg_id) | ||
| 297 | return -EINVAL; | ||
| 298 | |||
| 299 | /* Set the logical package id */ | ||
| 300 | if (test_and_set_bit(pkg, physical_package_map)) | ||
| 301 | goto found; | 311 | goto found; |
| 302 | 312 | ||
| 303 | if (logical_packages >= __max_logical_packages) { | ||
| 304 | pr_warn("Package %u of CPU %u exceeds BIOS package data %u.\n", | ||
| 305 | logical_packages, cpu, __max_logical_packages); | ||
| 306 | return -ENOSPC; | ||
| 307 | } | ||
| 308 | |||
| 309 | new = logical_packages++; | 313 | new = logical_packages++; |
| 310 | if (new != pkg) { | 314 | if (new != pkg) { |
| 311 | pr_info("CPU %u Converting physical %u to logical package %u\n", | 315 | pr_info("CPU %u Converting physical %u to logical package %u\n", |
| 312 | cpu, pkg, new); | 316 | cpu, pkg, new); |
| 313 | } | 317 | } |
| 314 | physical_to_logical_pkg[pkg] = new; | ||
| 315 | |||
| 316 | found: | 318 | found: |
| 317 | cpu_data(cpu).logical_proc_id = physical_to_logical_pkg[pkg]; | 319 | cpu_data(cpu).logical_proc_id = new; |
| 318 | return 0; | 320 | return 0; |
| 319 | } | 321 | } |
| 320 | 322 | ||
| 321 | /** | ||
| 322 | * topology_phys_to_logical_pkg - Map a physical package id to a logical | ||
| 323 | * | ||
| 324 | * Returns logical package id or -1 if not found | ||
| 325 | */ | ||
| 326 | int topology_phys_to_logical_pkg(unsigned int phys_pkg) | ||
| 327 | { | ||
| 328 | if (phys_pkg >= max_physical_pkg_id) | ||
| 329 | return -1; | ||
| 330 | return physical_to_logical_pkg[phys_pkg]; | ||
| 331 | } | ||
| 332 | EXPORT_SYMBOL(topology_phys_to_logical_pkg); | ||
| 333 | |||
| 334 | static void __init smp_init_package_map(struct cpuinfo_x86 *c, unsigned int cpu) | ||
| 335 | { | ||
| 336 | unsigned int ncpus; | ||
| 337 | size_t size; | ||
| 338 | |||
| 339 | /* | ||
| 340 | * Today neither Intel nor AMD support heterogenous systems. That | ||
| 341 | * might change in the future.... | ||
| 342 | * | ||
| 343 | * While ideally we'd want '* smp_num_siblings' in the below @ncpus | ||
| 344 | * computation, this won't actually work since some Intel BIOSes | ||
| 345 | * report inconsistent HT data when they disable HT. | ||
| 346 | * | ||
| 347 | * In particular, they reduce the APIC-IDs to only include the cores, | ||
| 348 | * but leave the CPUID topology to say there are (2) siblings. | ||
| 349 | * This means we don't know how many threads there will be until | ||
| 350 | * after the APIC enumeration. | ||
| 351 | * | ||
| 352 | * By not including this we'll sometimes over-estimate the number of | ||
| 353 | * logical packages by the amount of !present siblings, but this is | ||
| 354 | * still better than MAX_LOCAL_APIC. | ||
| 355 | * | ||
| 356 | * We use total_cpus not nr_cpu_ids because nr_cpu_ids can be limited | ||
| 357 | * on the command line leading to a similar issue as the HT disable | ||
| 358 | * problem because the hyperthreads are usually enumerated after the | ||
| 359 | * primary cores. | ||
| 360 | */ | ||
| 361 | ncpus = boot_cpu_data.x86_max_cores; | ||
| 362 | if (!ncpus) { | ||
| 363 | pr_warn("x86_max_cores == zero !?!?"); | ||
| 364 | ncpus = 1; | ||
| 365 | } | ||
| 366 | |||
| 367 | __max_logical_packages = DIV_ROUND_UP(total_cpus, ncpus); | ||
| 368 | logical_packages = 0; | ||
| 369 | |||
| 370 | /* | ||
| 371 | * Possibly larger than what we need as the number of apic ids per | ||
| 372 | * package can be smaller than the actual used apic ids. | ||
| 373 | */ | ||
| 374 | max_physical_pkg_id = DIV_ROUND_UP(MAX_LOCAL_APIC, ncpus); | ||
| 375 | size = max_physical_pkg_id * sizeof(unsigned int); | ||
| 376 | physical_to_logical_pkg = kmalloc(size, GFP_KERNEL); | ||
| 377 | memset(physical_to_logical_pkg, 0xff, size); | ||
| 378 | size = BITS_TO_LONGS(max_physical_pkg_id) * sizeof(unsigned long); | ||
| 379 | physical_package_map = kzalloc(size, GFP_KERNEL); | ||
| 380 | |||
| 381 | pr_info("Max logical packages: %u\n", __max_logical_packages); | ||
| 382 | |||
| 383 | topology_update_package_map(c->phys_proc_id, cpu); | ||
| 384 | } | ||
| 385 | |||
| 386 | void __init smp_store_boot_cpu_info(void) | 323 | void __init smp_store_boot_cpu_info(void) |
| 387 | { | 324 | { |
| 388 | int id = 0; /* CPU 0 */ | 325 | int id = 0; /* CPU 0 */ |
| @@ -390,7 +327,8 @@ void __init smp_store_boot_cpu_info(void) | |||
| 390 | 327 | ||
| 391 | *c = boot_cpu_data; | 328 | *c = boot_cpu_data; |
| 392 | c->cpu_index = id; | 329 | c->cpu_index = id; |
| 393 | smp_init_package_map(c, id); | 330 | topology_update_package_map(c->phys_proc_id, id); |
| 331 | c->initialized = true; | ||
| 394 | } | 332 | } |
| 395 | 333 | ||
| 396 | /* | 334 | /* |
| @@ -401,13 +339,16 @@ void smp_store_cpu_info(int id) | |||
| 401 | { | 339 | { |
| 402 | struct cpuinfo_x86 *c = &cpu_data(id); | 340 | struct cpuinfo_x86 *c = &cpu_data(id); |
| 403 | 341 | ||
| 404 | *c = boot_cpu_data; | 342 | /* Copy boot_cpu_data only on the first bringup */ |
| 343 | if (!c->initialized) | ||
| 344 | *c = boot_cpu_data; | ||
| 405 | c->cpu_index = id; | 345 | c->cpu_index = id; |
| 406 | /* | 346 | /* |
| 407 | * During boot time, CPU0 has this setup already. Save the info when | 347 | * During boot time, CPU0 has this setup already. Save the info when |
| 408 | * bringing up AP or offlined CPU0. | 348 | * bringing up AP or offlined CPU0. |
| 409 | */ | 349 | */ |
| 410 | identify_secondary_cpu(c); | 350 | identify_secondary_cpu(c); |
| 351 | c->initialized = true; | ||
| 411 | } | 352 | } |
| 412 | 353 | ||
| 413 | static bool | 354 | static bool |
| @@ -1356,7 +1297,16 @@ void __init native_smp_prepare_boot_cpu(void) | |||
| 1356 | 1297 | ||
| 1357 | void __init native_smp_cpus_done(unsigned int max_cpus) | 1298 | void __init native_smp_cpus_done(unsigned int max_cpus) |
| 1358 | { | 1299 | { |
| 1300 | int ncpus; | ||
| 1301 | |||
| 1359 | pr_debug("Boot done\n"); | 1302 | pr_debug("Boot done\n"); |
| 1303 | /* | ||
| 1304 | * Today neither Intel nor AMD support heterogenous systems so | ||
| 1305 | * extrapolate the boot cpu's data to all packages. | ||
| 1306 | */ | ||
| 1307 | ncpus = cpu_data(0).booted_cores * smp_num_siblings; | ||
| 1308 | __max_logical_packages = DIV_ROUND_UP(nr_cpu_ids, ncpus); | ||
| 1309 | pr_info("Max logical packages: %u\n", __max_logical_packages); | ||
| 1360 | 1310 | ||
| 1361 | if (x86_has_numa_in_package) | 1311 | if (x86_has_numa_in_package) |
| 1362 | set_sched_topology(x86_numa_in_package_topology); | 1312 | set_sched_topology(x86_numa_in_package_topology); |
diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c index a63fe77b3217..676774b9bb8d 100644 --- a/arch/x86/kernel/sys_x86_64.c +++ b/arch/x86/kernel/sys_x86_64.c | |||
| @@ -188,6 +188,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, | |||
| 188 | if (len > TASK_SIZE) | 188 | if (len > TASK_SIZE) |
| 189 | return -ENOMEM; | 189 | return -ENOMEM; |
| 190 | 190 | ||
| 191 | /* No address checking. See comment at mmap_address_hint_valid() */ | ||
| 191 | if (flags & MAP_FIXED) | 192 | if (flags & MAP_FIXED) |
| 192 | return addr; | 193 | return addr; |
| 193 | 194 | ||
| @@ -197,12 +198,15 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, | |||
| 197 | 198 | ||
| 198 | /* requesting a specific address */ | 199 | /* requesting a specific address */ |
| 199 | if (addr) { | 200 | if (addr) { |
| 200 | addr = PAGE_ALIGN(addr); | 201 | addr &= PAGE_MASK; |
| 202 | if (!mmap_address_hint_valid(addr, len)) | ||
| 203 | goto get_unmapped_area; | ||
| 204 | |||
| 201 | vma = find_vma(mm, addr); | 205 | vma = find_vma(mm, addr); |
| 202 | if (TASK_SIZE - len >= addr && | 206 | if (!vma || addr + len <= vm_start_gap(vma)) |
| 203 | (!vma || addr + len <= vm_start_gap(vma))) | ||
| 204 | return addr; | 207 | return addr; |
| 205 | } | 208 | } |
| 209 | get_unmapped_area: | ||
| 206 | 210 | ||
| 207 | info.flags = VM_UNMAPPED_AREA_TOPDOWN; | 211 | info.flags = VM_UNMAPPED_AREA_TOPDOWN; |
| 208 | info.length = len; | 212 | info.length = len; |
diff --git a/arch/x86/kernel/umip.c b/arch/x86/kernel/umip.c index 6ba82be68cff..f44ce0fb3583 100644 --- a/arch/x86/kernel/umip.c +++ b/arch/x86/kernel/umip.c | |||
| @@ -78,7 +78,60 @@ | |||
| 78 | 78 | ||
| 79 | #define UMIP_INST_SGDT 0 /* 0F 01 /0 */ | 79 | #define UMIP_INST_SGDT 0 /* 0F 01 /0 */ |
| 80 | #define UMIP_INST_SIDT 1 /* 0F 01 /1 */ | 80 | #define UMIP_INST_SIDT 1 /* 0F 01 /1 */ |
| 81 | #define UMIP_INST_SMSW 3 /* 0F 01 /4 */ | 81 | #define UMIP_INST_SMSW 2 /* 0F 01 /4 */ |
| 82 | #define UMIP_INST_SLDT 3 /* 0F 00 /0 */ | ||
| 83 | #define UMIP_INST_STR 4 /* 0F 00 /1 */ | ||
| 84 | |||
| 85 | const char * const umip_insns[5] = { | ||
| 86 | [UMIP_INST_SGDT] = "SGDT", | ||
| 87 | [UMIP_INST_SIDT] = "SIDT", | ||
| 88 | [UMIP_INST_SMSW] = "SMSW", | ||
| 89 | [UMIP_INST_SLDT] = "SLDT", | ||
| 90 | [UMIP_INST_STR] = "STR", | ||
| 91 | }; | ||
| 92 | |||
| 93 | #define umip_pr_err(regs, fmt, ...) \ | ||
| 94 | umip_printk(regs, KERN_ERR, fmt, ##__VA_ARGS__) | ||
| 95 | #define umip_pr_warning(regs, fmt, ...) \ | ||
| 96 | umip_printk(regs, KERN_WARNING, fmt, ##__VA_ARGS__) | ||
| 97 | |||
| 98 | /** | ||
| 99 | * umip_printk() - Print a rate-limited message | ||
| 100 | * @regs: Register set with the context in which the warning is printed | ||
| 101 | * @log_level: Kernel log level to print the message | ||
| 102 | * @fmt: The text string to print | ||
| 103 | * | ||
| 104 | * Print the text contained in @fmt. The print rate is limited to bursts of 5 | ||
| 105 | * messages every two minutes. The purpose of this customized version of | ||
| 106 | * printk() is to print messages when user space processes use any of the | ||
| 107 | * UMIP-protected instructions. Thus, the printed text is prepended with the | ||
| 108 | * task name and process ID number of the current task as well as the | ||
| 109 | * instruction and stack pointers in @regs as seen when entering kernel mode. | ||
| 110 | * | ||
| 111 | * Returns: | ||
| 112 | * | ||
| 113 | * None. | ||
| 114 | */ | ||
| 115 | static __printf(3, 4) | ||
| 116 | void umip_printk(const struct pt_regs *regs, const char *log_level, | ||
| 117 | const char *fmt, ...) | ||
| 118 | { | ||
| 119 | /* Bursts of 5 messages every two minutes */ | ||
| 120 | static DEFINE_RATELIMIT_STATE(ratelimit, 2 * 60 * HZ, 5); | ||
| 121 | struct task_struct *tsk = current; | ||
| 122 | struct va_format vaf; | ||
| 123 | va_list args; | ||
| 124 | |||
| 125 | if (!__ratelimit(&ratelimit)) | ||
| 126 | return; | ||
| 127 | |||
| 128 | va_start(args, fmt); | ||
| 129 | vaf.fmt = fmt; | ||
| 130 | vaf.va = &args; | ||
| 131 | printk("%s" pr_fmt("%s[%d] ip:%lx sp:%lx: %pV"), log_level, tsk->comm, | ||
| 132 | task_pid_nr(tsk), regs->ip, regs->sp, &vaf); | ||
| 133 | va_end(args); | ||
| 134 | } | ||
| 82 | 135 | ||
| 83 | /** | 136 | /** |
| 84 | * identify_insn() - Identify a UMIP-protected instruction | 137 | * identify_insn() - Identify a UMIP-protected instruction |
| @@ -118,10 +171,16 @@ static int identify_insn(struct insn *insn) | |||
| 118 | default: | 171 | default: |
| 119 | return -EINVAL; | 172 | return -EINVAL; |
| 120 | } | 173 | } |
| 174 | } else if (insn->opcode.bytes[1] == 0x0) { | ||
| 175 | if (X86_MODRM_REG(insn->modrm.value) == 0) | ||
| 176 | return UMIP_INST_SLDT; | ||
| 177 | else if (X86_MODRM_REG(insn->modrm.value) == 1) | ||
| 178 | return UMIP_INST_STR; | ||
| 179 | else | ||
| 180 | return -EINVAL; | ||
| 181 | } else { | ||
| 182 | return -EINVAL; | ||
| 121 | } | 183 | } |
| 122 | |||
| 123 | /* SLDT AND STR are not emulated */ | ||
| 124 | return -EINVAL; | ||
| 125 | } | 184 | } |
| 126 | 185 | ||
| 127 | /** | 186 | /** |
| @@ -228,10 +287,8 @@ static void force_sig_info_umip_fault(void __user *addr, struct pt_regs *regs) | |||
| 228 | if (!(show_unhandled_signals && unhandled_signal(tsk, SIGSEGV))) | 287 | if (!(show_unhandled_signals && unhandled_signal(tsk, SIGSEGV))) |
| 229 | return; | 288 | return; |
| 230 | 289 | ||
| 231 | pr_err_ratelimited("%s[%d] umip emulation segfault ip:%lx sp:%lx error:%x in %lx\n", | 290 | umip_pr_err(regs, "segfault in emulation. error%x\n", |
| 232 | tsk->comm, task_pid_nr(tsk), regs->ip, | 291 | X86_PF_USER | X86_PF_WRITE); |
| 233 | regs->sp, X86_PF_USER | X86_PF_WRITE, | ||
| 234 | regs->ip); | ||
| 235 | } | 292 | } |
| 236 | 293 | ||
| 237 | /** | 294 | /** |
| @@ -262,15 +319,11 @@ bool fixup_umip_exception(struct pt_regs *regs) | |||
| 262 | unsigned char buf[MAX_INSN_SIZE]; | 319 | unsigned char buf[MAX_INSN_SIZE]; |
| 263 | void __user *uaddr; | 320 | void __user *uaddr; |
| 264 | struct insn insn; | 321 | struct insn insn; |
| 265 | char seg_defs; | 322 | int seg_defs; |
| 266 | 323 | ||
| 267 | if (!regs) | 324 | if (!regs) |
| 268 | return false; | 325 | return false; |
| 269 | 326 | ||
| 270 | /* Do not emulate 64-bit processes. */ | ||
| 271 | if (user_64bit_mode(regs)) | ||
| 272 | return false; | ||
| 273 | |||
| 274 | /* | 327 | /* |
| 275 | * If not in user-space long mode, a custom code segment could be in | 328 | * If not in user-space long mode, a custom code segment could be in |
| 276 | * use. This is true in protected mode (if the process defined a local | 329 | * use. This is true in protected mode (if the process defined a local |
| @@ -322,6 +375,15 @@ bool fixup_umip_exception(struct pt_regs *regs) | |||
| 322 | if (umip_inst < 0) | 375 | if (umip_inst < 0) |
| 323 | return false; | 376 | return false; |
| 324 | 377 | ||
| 378 | umip_pr_warning(regs, "%s instruction cannot be used by applications.\n", | ||
| 379 | umip_insns[umip_inst]); | ||
| 380 | |||
| 381 | /* Do not emulate SLDT, STR or user long mode processes. */ | ||
| 382 | if (umip_inst == UMIP_INST_STR || umip_inst == UMIP_INST_SLDT || user_64bit_mode(regs)) | ||
| 383 | return false; | ||
| 384 | |||
| 385 | umip_pr_warning(regs, "For now, expensive software emulation returns the result.\n"); | ||
| 386 | |||
| 325 | if (emulate_umip_insn(&insn, umip_inst, dummy_data, &dummy_data_size)) | 387 | if (emulate_umip_insn(&insn, umip_inst, dummy_data, &dummy_data_size)) |
| 326 | return false; | 388 | return false; |
| 327 | 389 | ||
diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c index 35625d279458..9119d8e41f1f 100644 --- a/arch/x86/lib/insn-eval.c +++ b/arch/x86/lib/insn-eval.c | |||
| @@ -733,11 +733,11 @@ static unsigned long get_seg_limit(struct pt_regs *regs, int seg_reg_idx) | |||
| 733 | * | 733 | * |
| 734 | * Returns: | 734 | * Returns: |
| 735 | * | 735 | * |
| 736 | * A signed 8-bit value containing the default parameters on success. | 736 | * An int containing ORed-in default parameters on success. |
| 737 | * | 737 | * |
| 738 | * -EINVAL on error. | 738 | * -EINVAL on error. |
| 739 | */ | 739 | */ |
| 740 | char insn_get_code_seg_params(struct pt_regs *regs) | 740 | int insn_get_code_seg_params(struct pt_regs *regs) |
| 741 | { | 741 | { |
| 742 | struct desc_struct *desc; | 742 | struct desc_struct *desc; |
| 743 | short sel; | 743 | short sel; |
diff --git a/arch/x86/lib/x86-opcode-map.txt b/arch/x86/lib/x86-opcode-map.txt index 12e377184ee4..c4d55919fac1 100644 --- a/arch/x86/lib/x86-opcode-map.txt +++ b/arch/x86/lib/x86-opcode-map.txt | |||
| @@ -896,7 +896,7 @@ EndTable | |||
| 896 | 896 | ||
| 897 | GrpTable: Grp3_1 | 897 | GrpTable: Grp3_1 |
| 898 | 0: TEST Eb,Ib | 898 | 0: TEST Eb,Ib |
| 899 | 1: | 899 | 1: TEST Eb,Ib |
| 900 | 2: NOT Eb | 900 | 2: NOT Eb |
| 901 | 3: NEG Eb | 901 | 3: NEG Eb |
| 902 | 4: MUL AL,Eb | 902 | 4: MUL AL,Eb |
diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c index 8ae0000cbdb3..00b296617ca4 100644 --- a/arch/x86/mm/hugetlbpage.c +++ b/arch/x86/mm/hugetlbpage.c | |||
| @@ -158,6 +158,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, | |||
| 158 | if (len > TASK_SIZE) | 158 | if (len > TASK_SIZE) |
| 159 | return -ENOMEM; | 159 | return -ENOMEM; |
| 160 | 160 | ||
| 161 | /* No address checking. See comment at mmap_address_hint_valid() */ | ||
| 161 | if (flags & MAP_FIXED) { | 162 | if (flags & MAP_FIXED) { |
| 162 | if (prepare_hugepage_range(file, addr, len)) | 163 | if (prepare_hugepage_range(file, addr, len)) |
| 163 | return -EINVAL; | 164 | return -EINVAL; |
| @@ -165,12 +166,16 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, | |||
| 165 | } | 166 | } |
| 166 | 167 | ||
| 167 | if (addr) { | 168 | if (addr) { |
| 168 | addr = ALIGN(addr, huge_page_size(h)); | 169 | addr &= huge_page_mask(h); |
| 170 | if (!mmap_address_hint_valid(addr, len)) | ||
| 171 | goto get_unmapped_area; | ||
| 172 | |||
| 169 | vma = find_vma(mm, addr); | 173 | vma = find_vma(mm, addr); |
| 170 | if (TASK_SIZE - len >= addr && | 174 | if (!vma || addr + len <= vm_start_gap(vma)) |
| 171 | (!vma || addr + len <= vm_start_gap(vma))) | ||
| 172 | return addr; | 175 | return addr; |
| 173 | } | 176 | } |
| 177 | |||
| 178 | get_unmapped_area: | ||
| 174 | if (mm->get_unmapped_area == arch_get_unmapped_area) | 179 | if (mm->get_unmapped_area == arch_get_unmapped_area) |
| 175 | return hugetlb_get_unmapped_area_bottomup(file, addr, len, | 180 | return hugetlb_get_unmapped_area_bottomup(file, addr, len, |
| 176 | pgoff, flags); | 181 | pgoff, flags); |
diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c index a99679826846..155ecbac9e28 100644 --- a/arch/x86/mm/mmap.c +++ b/arch/x86/mm/mmap.c | |||
| @@ -33,6 +33,8 @@ | |||
| 33 | #include <linux/compat.h> | 33 | #include <linux/compat.h> |
| 34 | #include <asm/elf.h> | 34 | #include <asm/elf.h> |
| 35 | 35 | ||
| 36 | #include "physaddr.h" | ||
| 37 | |||
| 36 | struct va_alignment __read_mostly va_align = { | 38 | struct va_alignment __read_mostly va_align = { |
| 37 | .flags = -1, | 39 | .flags = -1, |
| 38 | }; | 40 | }; |
| @@ -174,3 +176,63 @@ const char *arch_vma_name(struct vm_area_struct *vma) | |||
| 174 | return "[mpx]"; | 176 | return "[mpx]"; |
| 175 | return NULL; | 177 | return NULL; |
| 176 | } | 178 | } |
| 179 | |||
| 180 | /** | ||
| 181 | * mmap_address_hint_valid - Validate the address hint of mmap | ||
| 182 | * @addr: Address hint | ||
| 183 | * @len: Mapping length | ||
| 184 | * | ||
| 185 | * Check whether @addr and @addr + @len result in a valid mapping. | ||
| 186 | * | ||
| 187 | * On 32bit this only checks whether @addr + @len is <= TASK_SIZE. | ||
| 188 | * | ||
| 189 | * On 64bit with 5-level page tables another sanity check is required | ||
| 190 | * because mappings requested by mmap(@addr, 0) which cross the 47-bit | ||
| 191 | * virtual address boundary can cause the following theoretical issue: | ||
| 192 | * | ||
| 193 | * An application calls mmap(addr, 0), i.e. without MAP_FIXED, where @addr | ||
| 194 | * is below the border of the 47-bit address space and @addr + @len is | ||
| 195 | * above the border. | ||
| 196 | * | ||
| 197 | * With 4-level paging this request succeeds, but the resulting mapping | ||
| 198 | * address will always be within the 47-bit virtual address space, because | ||
| 199 | * the hint address does not result in a valid mapping and is | ||
| 200 | * ignored. Hence applications which are not prepared to handle virtual | ||
| 201 | * addresses above 47-bit work correctly. | ||
| 202 | * | ||
| 203 | * With 5-level paging this request would be granted and result in a | ||
| 204 | * mapping which crosses the border of the 47-bit virtual address | ||
| 205 | * space. If the application cannot handle addresses above 47-bit this | ||
| 206 | * will lead to misbehaviour and hard to diagnose failures. | ||
| 207 | * | ||
| 208 | * Therefore ignore address hints which would result in a mapping crossing | ||
| 209 | * the 47-bit virtual address boundary. | ||
| 210 | * | ||
| 211 | * Note, that in the same scenario with MAP_FIXED the behaviour is | ||
| 212 | * different. The request with @addr < 47-bit and @addr + @len > 47-bit | ||
| 213 | * fails on a 4-level paging machine but succeeds on a 5-level paging | ||
| 214 | * machine. It is reasonable to expect that an application does not rely on | ||
| 215 | * the failure of such a fixed mapping request, so the restriction is not | ||
| 216 | * applied. | ||
| 217 | */ | ||
| 218 | bool mmap_address_hint_valid(unsigned long addr, unsigned long len) | ||
| 219 | { | ||
| 220 | if (TASK_SIZE - len < addr) | ||
| 221 | return false; | ||
| 222 | |||
| 223 | return (addr > DEFAULT_MAP_WINDOW) == (addr + len > DEFAULT_MAP_WINDOW); | ||
| 224 | } | ||
| 225 | |||
| 226 | /* Can we access it for direct reading/writing? Must be RAM: */ | ||
| 227 | int valid_phys_addr_range(phys_addr_t addr, size_t count) | ||
| 228 | { | ||
| 229 | return addr + count <= __pa(high_memory); | ||
| 230 | } | ||
| 231 | |||
| 232 | /* Can we access it through mmap? Must be a valid physical address: */ | ||
| 233 | int valid_mmap_phys_addr_range(unsigned long pfn, size_t count) | ||
| 234 | { | ||
| 235 | phys_addr_t addr = (phys_addr_t)pfn << PAGE_SHIFT; | ||
| 236 | |||
| 237 | return phys_addr_valid(addr + count - 1); | ||
| 238 | } | ||
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 970e1242a282..6aefe5370e5b 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
| @@ -343,6 +343,10 @@ static int mmap_mem(struct file *file, struct vm_area_struct *vma) | |||
| 343 | size_t size = vma->vm_end - vma->vm_start; | 343 | size_t size = vma->vm_end - vma->vm_start; |
| 344 | phys_addr_t offset = (phys_addr_t)vma->vm_pgoff << PAGE_SHIFT; | 344 | phys_addr_t offset = (phys_addr_t)vma->vm_pgoff << PAGE_SHIFT; |
| 345 | 345 | ||
| 346 | /* Does it even fit in phys_addr_t? */ | ||
| 347 | if (offset >> PAGE_SHIFT != vma->vm_pgoff) | ||
| 348 | return -EINVAL; | ||
| 349 | |||
| 346 | /* It's illegal to wrap around the end of the physical address space. */ | 350 | /* It's illegal to wrap around the end of the physical address space. */ |
| 347 | if (offset + (phys_addr_t)size - 1 < offset) | 351 | if (offset + (phys_addr_t)size - 1 < offset) |
| 348 | return -EINVAL; | 352 | return -EINVAL; |
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 90944667ccea..bda151788f3f 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig | |||
| @@ -80,15 +80,6 @@ config XEN_PCIDEV_FRONTEND | |||
| 80 | The PCI device frontend driver allows the kernel to import arbitrary | 80 | The PCI device frontend driver allows the kernel to import arbitrary |
| 81 | PCI devices from a PCI backend to support PCI driver domains. | 81 | PCI devices from a PCI backend to support PCI driver domains. |
| 82 | 82 | ||
| 83 | config HT_IRQ | ||
| 84 | bool "Interrupts on hypertransport devices" | ||
| 85 | default y | ||
| 86 | depends on PCI && X86_LOCAL_APIC | ||
| 87 | help | ||
| 88 | This allows native hypertransport devices to use interrupts. | ||
| 89 | |||
| 90 | If unsure say Y. | ||
| 91 | |||
| 92 | config PCI_ATS | 83 | config PCI_ATS |
| 93 | bool | 84 | bool |
| 94 | 85 | ||
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 3d5e047f0a32..c7819b973df7 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile | |||
| @@ -21,9 +21,6 @@ obj-$(CONFIG_HOTPLUG_PCI) += hotplug/ | |||
| 21 | # Build the PCI MSI interrupt support | 21 | # Build the PCI MSI interrupt support |
| 22 | obj-$(CONFIG_PCI_MSI) += msi.o | 22 | obj-$(CONFIG_PCI_MSI) += msi.o |
| 23 | 23 | ||
| 24 | # Build the Hypertransport interrupt support | ||
| 25 | obj-$(CONFIG_HT_IRQ) += htirq.o | ||
| 26 | |||
| 27 | obj-$(CONFIG_PCI_ATS) += ats.o | 24 | obj-$(CONFIG_PCI_ATS) += ats.o |
| 28 | obj-$(CONFIG_PCI_IOV) += iov.o | 25 | obj-$(CONFIG_PCI_IOV) += iov.o |
| 29 | 26 | ||
diff --git a/drivers/pci/htirq.c b/drivers/pci/htirq.c deleted file mode 100644 index bb88c26f5144..000000000000 --- a/drivers/pci/htirq.c +++ /dev/null | |||
| @@ -1,135 +0,0 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * File: htirq.c | ||
| 4 | * Purpose: Hypertransport Interrupt Capability | ||
| 5 | * | ||
| 6 | * Copyright (C) 2006 Linux Networx | ||
| 7 | * Copyright (C) Eric Biederman <ebiederman@lnxi.com> | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/irq.h> | ||
| 11 | #include <linux/pci.h> | ||
| 12 | #include <linux/spinlock.h> | ||
| 13 | #include <linux/export.h> | ||
| 14 | #include <linux/slab.h> | ||
| 15 | #include <linux/htirq.h> | ||
| 16 | |||
| 17 | /* Global ht irq lock. | ||
| 18 | * | ||
| 19 | * This is needed to serialize access to the data port in hypertransport | ||
| 20 | * irq capability. | ||
| 21 | * | ||
| 22 | * With multiple simultaneous hypertransport irq devices it might pay | ||
| 23 | * to make this more fine grained. But start with simple, stupid, and correct. | ||
| 24 | */ | ||
| 25 | static DEFINE_SPINLOCK(ht_irq_lock); | ||
| 26 | |||
| 27 | void write_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg) | ||
| 28 | { | ||
| 29 | struct ht_irq_cfg *cfg = irq_get_handler_data(irq); | ||
| 30 | unsigned long flags; | ||
| 31 | |||
| 32 | spin_lock_irqsave(&ht_irq_lock, flags); | ||
| 33 | if (cfg->msg.address_lo != msg->address_lo) { | ||
| 34 | pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx); | ||
| 35 | pci_write_config_dword(cfg->dev, cfg->pos + 4, msg->address_lo); | ||
| 36 | } | ||
| 37 | if (cfg->msg.address_hi != msg->address_hi) { | ||
| 38 | pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx + 1); | ||
| 39 | pci_write_config_dword(cfg->dev, cfg->pos + 4, msg->address_hi); | ||
| 40 | } | ||
| 41 | if (cfg->update) | ||
| 42 | cfg->update(cfg->dev, irq, msg); | ||
| 43 | spin_unlock_irqrestore(&ht_irq_lock, flags); | ||
| 44 | cfg->msg = *msg; | ||
| 45 | } | ||
| 46 | |||
| 47 | void fetch_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg) | ||
| 48 | { | ||
| 49 | struct ht_irq_cfg *cfg = irq_get_handler_data(irq); | ||
| 50 | |||
| 51 | *msg = cfg->msg; | ||
| 52 | } | ||
| 53 | |||
| 54 | void mask_ht_irq(struct irq_data *data) | ||
| 55 | { | ||
| 56 | struct ht_irq_cfg *cfg = irq_data_get_irq_handler_data(data); | ||
| 57 | struct ht_irq_msg msg = cfg->msg; | ||
| 58 | |||
| 59 | msg.address_lo |= 1; | ||
| 60 | write_ht_irq_msg(data->irq, &msg); | ||
| 61 | } | ||
| 62 | |||
| 63 | void unmask_ht_irq(struct irq_data *data) | ||
| 64 | { | ||
| 65 | struct ht_irq_cfg *cfg = irq_data_get_irq_handler_data(data); | ||
| 66 | struct ht_irq_msg msg = cfg->msg; | ||
| 67 | |||
| 68 | msg.address_lo &= ~1; | ||
| 69 | write_ht_irq_msg(data->irq, &msg); | ||
| 70 | } | ||
| 71 | |||
| 72 | /** | ||
| 73 | * __ht_create_irq - create an irq and attach it to a device. | ||
| 74 | * @dev: The hypertransport device to find the irq capability on. | ||
| 75 | * @idx: Which of the possible irqs to attach to. | ||
| 76 | * @update: Function to be called when changing the htirq message | ||
| 77 | * | ||
| 78 | * The irq number of the new irq or a negative error value is returned. | ||
| 79 | */ | ||
| 80 | int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update) | ||
| 81 | { | ||
| 82 | int max_irq, pos, irq; | ||
| 83 | unsigned long flags; | ||
| 84 | u32 data; | ||
| 85 | |||
| 86 | pos = pci_find_ht_capability(dev, HT_CAPTYPE_IRQ); | ||
| 87 | if (!pos) | ||
| 88 | return -EINVAL; | ||
| 89 | |||
| 90 | /* Verify the idx I want to use is in range */ | ||
| 91 | spin_lock_irqsave(&ht_irq_lock, flags); | ||
| 92 | pci_write_config_byte(dev, pos + 2, 1); | ||
| 93 | pci_read_config_dword(dev, pos + 4, &data); | ||
| 94 | spin_unlock_irqrestore(&ht_irq_lock, flags); | ||
| 95 | |||
| 96 | max_irq = (data >> 16) & 0xff; | ||
| 97 | if (idx > max_irq) | ||
| 98 | return -EINVAL; | ||
| 99 | |||
| 100 | irq = arch_setup_ht_irq(idx, pos, dev, update); | ||
| 101 | if (irq > 0) | ||
| 102 | dev_dbg(&dev->dev, "irq %d for HT\n", irq); | ||
| 103 | |||
| 104 | return irq; | ||
| 105 | } | ||
| 106 | EXPORT_SYMBOL(__ht_create_irq); | ||
| 107 | |||
| 108 | /** | ||
| 109 | * ht_create_irq - create an irq and attach it to a device. | ||
| 110 | * @dev: The hypertransport device to find the irq capability on. | ||
| 111 | * @idx: Which of the possible irqs to attach to. | ||
| 112 | * | ||
| 113 | * ht_create_irq needs to be called for all hypertransport devices | ||
| 114 | * that generate irqs. | ||
| 115 | * | ||
| 116 | * The irq number of the new irq or a negative error value is returned. | ||
| 117 | */ | ||
| 118 | int ht_create_irq(struct pci_dev *dev, int idx) | ||
| 119 | { | ||
| 120 | return __ht_create_irq(dev, idx, NULL); | ||
| 121 | } | ||
| 122 | EXPORT_SYMBOL(ht_create_irq); | ||
| 123 | |||
| 124 | /** | ||
| 125 | * ht_destroy_irq - destroy an irq created with ht_create_irq | ||
| 126 | * @irq: irq to be destroyed | ||
| 127 | * | ||
| 128 | * This reverses ht_create_irq removing the specified irq from | ||
| 129 | * existence. The irq should be free before this happens. | ||
| 130 | */ | ||
| 131 | void ht_destroy_irq(unsigned int irq) | ||
| 132 | { | ||
| 133 | arch_teardown_ht_irq(irq); | ||
| 134 | } | ||
| 135 | EXPORT_SYMBOL(ht_destroy_irq); | ||
diff --git a/include/linux/htirq.h b/include/linux/htirq.h deleted file mode 100644 index 127c39d815ba..000000000000 --- a/include/linux/htirq.h +++ /dev/null | |||
| @@ -1,39 +0,0 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | #ifndef LINUX_HTIRQ_H | ||
| 3 | #define LINUX_HTIRQ_H | ||
| 4 | |||
| 5 | struct pci_dev; | ||
| 6 | struct irq_data; | ||
| 7 | |||
| 8 | struct ht_irq_msg { | ||
| 9 | u32 address_lo; /* low 32 bits of the ht irq message */ | ||
| 10 | u32 address_hi; /* high 32 bits of the it irq message */ | ||
| 11 | }; | ||
| 12 | |||
| 13 | typedef void (ht_irq_update_t)(struct pci_dev *dev, int irq, | ||
| 14 | struct ht_irq_msg *msg); | ||
| 15 | |||
| 16 | struct ht_irq_cfg { | ||
| 17 | struct pci_dev *dev; | ||
| 18 | /* Update callback used to cope with buggy hardware */ | ||
| 19 | ht_irq_update_t *update; | ||
| 20 | unsigned pos; | ||
| 21 | unsigned idx; | ||
| 22 | struct ht_irq_msg msg; | ||
| 23 | }; | ||
| 24 | |||
| 25 | /* Helper functions.. */ | ||
| 26 | void fetch_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg); | ||
| 27 | void write_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg); | ||
| 28 | void mask_ht_irq(struct irq_data *data); | ||
| 29 | void unmask_ht_irq(struct irq_data *data); | ||
| 30 | |||
| 31 | /* The arch hook for getting things started */ | ||
| 32 | int arch_setup_ht_irq(int idx, int pos, struct pci_dev *dev, | ||
| 33 | ht_irq_update_t *update); | ||
| 34 | void arch_teardown_ht_irq(unsigned int irq); | ||
| 35 | |||
| 36 | /* For drivers of buggy hardware */ | ||
| 37 | int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update); | ||
| 38 | |||
| 39 | #endif /* LINUX_HTIRQ_H */ | ||
diff --git a/include/linux/pci.h b/include/linux/pci.h index 96c94980d1ff..0403894147a3 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
| @@ -1485,12 +1485,6 @@ static inline void pcie_set_ecrc_checking(struct pci_dev *dev) { } | |||
| 1485 | static inline void pcie_ecrc_get_policy(char *str) { } | 1485 | static inline void pcie_ecrc_get_policy(char *str) { } |
| 1486 | #endif | 1486 | #endif |
| 1487 | 1487 | ||
| 1488 | #ifdef CONFIG_HT_IRQ | ||
| 1489 | /* The functions a driver should call */ | ||
| 1490 | int ht_create_irq(struct pci_dev *dev, int idx); | ||
| 1491 | void ht_destroy_irq(unsigned int irq); | ||
| 1492 | #endif /* CONFIG_HT_IRQ */ | ||
| 1493 | |||
| 1494 | #ifdef CONFIG_PCI_ATS | 1488 | #ifdef CONFIG_PCI_ATS |
| 1495 | /* Address Translation Service */ | 1489 | /* Address Translation Service */ |
| 1496 | void pci_ats_init(struct pci_dev *dev); | 1490 | void pci_ats_init(struct pci_dev *dev); |
diff --git a/tools/testing/selftests/x86/5lvl.c b/tools/testing/selftests/x86/5lvl.c new file mode 100644 index 000000000000..2eafdcd4c2b3 --- /dev/null +++ b/tools/testing/selftests/x86/5lvl.c | |||
| @@ -0,0 +1,177 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include <sys/mman.h> | ||
| 3 | |||
| 4 | #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) | ||
| 5 | |||
| 6 | #define PAGE_SIZE 4096 | ||
| 7 | #define LOW_ADDR ((void *) (1UL << 30)) | ||
| 8 | #define HIGH_ADDR ((void *) (1UL << 50)) | ||
| 9 | |||
| 10 | struct testcase { | ||
| 11 | void *addr; | ||
| 12 | unsigned long size; | ||
| 13 | unsigned long flags; | ||
| 14 | const char *msg; | ||
| 15 | unsigned int low_addr_required:1; | ||
| 16 | unsigned int keep_mapped:1; | ||
| 17 | }; | ||
| 18 | |||
| 19 | static struct testcase testcases[] = { | ||
| 20 | { | ||
| 21 | .addr = NULL, | ||
| 22 | .size = 2 * PAGE_SIZE, | ||
| 23 | .flags = MAP_PRIVATE | MAP_ANONYMOUS, | ||
| 24 | .msg = "mmap(NULL)", | ||
| 25 | .low_addr_required = 1, | ||
| 26 | }, | ||
| 27 | { | ||
| 28 | .addr = LOW_ADDR, | ||
| 29 | .size = 2 * PAGE_SIZE, | ||
| 30 | .flags = MAP_PRIVATE | MAP_ANONYMOUS, | ||
| 31 | .msg = "mmap(LOW_ADDR)", | ||
| 32 | .low_addr_required = 1, | ||
| 33 | }, | ||
| 34 | { | ||
| 35 | .addr = HIGH_ADDR, | ||
| 36 | .size = 2 * PAGE_SIZE, | ||
| 37 | .flags = MAP_PRIVATE | MAP_ANONYMOUS, | ||
| 38 | .msg = "mmap(HIGH_ADDR)", | ||
| 39 | .keep_mapped = 1, | ||
| 40 | }, | ||
| 41 | { | ||
| 42 | .addr = HIGH_ADDR, | ||
| 43 | .size = 2 * PAGE_SIZE, | ||
| 44 | .flags = MAP_PRIVATE | MAP_ANONYMOUS, | ||
| 45 | .msg = "mmap(HIGH_ADDR) again", | ||
| 46 | .keep_mapped = 1, | ||
| 47 | }, | ||
| 48 | { | ||
| 49 | .addr = HIGH_ADDR, | ||
| 50 | .size = 2 * PAGE_SIZE, | ||
| 51 | .flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, | ||
| 52 | .msg = "mmap(HIGH_ADDR, MAP_FIXED)", | ||
| 53 | }, | ||
| 54 | { | ||
| 55 | .addr = (void*) -1, | ||
| 56 | .size = 2 * PAGE_SIZE, | ||
| 57 | .flags = MAP_PRIVATE | MAP_ANONYMOUS, | ||
| 58 | .msg = "mmap(-1)", | ||
| 59 | .keep_mapped = 1, | ||
| 60 | }, | ||
| 61 | { | ||
| 62 | .addr = (void*) -1, | ||
| 63 | .size = 2 * PAGE_SIZE, | ||
| 64 | .flags = MAP_PRIVATE | MAP_ANONYMOUS, | ||
| 65 | .msg = "mmap(-1) again", | ||
| 66 | }, | ||
| 67 | { | ||
| 68 | .addr = (void *)((1UL << 47) - PAGE_SIZE), | ||
| 69 | .size = 2 * PAGE_SIZE, | ||
| 70 | .flags = MAP_PRIVATE | MAP_ANONYMOUS, | ||
| 71 | .msg = "mmap((1UL << 47), 2 * PAGE_SIZE)", | ||
| 72 | .low_addr_required = 1, | ||
| 73 | .keep_mapped = 1, | ||
| 74 | }, | ||
| 75 | { | ||
| 76 | .addr = (void *)((1UL << 47) - PAGE_SIZE / 2), | ||
| 77 | .size = 2 * PAGE_SIZE, | ||
| 78 | .flags = MAP_PRIVATE | MAP_ANONYMOUS, | ||
| 79 | .msg = "mmap((1UL << 47), 2 * PAGE_SIZE / 2)", | ||
| 80 | .low_addr_required = 1, | ||
| 81 | .keep_mapped = 1, | ||
| 82 | }, | ||
| 83 | { | ||
| 84 | .addr = (void *)((1UL << 47) - PAGE_SIZE), | ||
| 85 | .size = 2 * PAGE_SIZE, | ||
| 86 | .flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, | ||
| 87 | .msg = "mmap((1UL << 47) - PAGE_SIZE, 2 * PAGE_SIZE, MAP_FIXED)", | ||
| 88 | }, | ||
| 89 | { | ||
| 90 | .addr = NULL, | ||
| 91 | .size = 2UL << 20, | ||
| 92 | .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS, | ||
| 93 | .msg = "mmap(NULL, MAP_HUGETLB)", | ||
| 94 | .low_addr_required = 1, | ||
| 95 | }, | ||
| 96 | { | ||
| 97 | .addr = LOW_ADDR, | ||
| 98 | .size = 2UL << 20, | ||
| 99 | .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS, | ||
| 100 | .msg = "mmap(LOW_ADDR, MAP_HUGETLB)", | ||
| 101 | .low_addr_required = 1, | ||
| 102 | }, | ||
| 103 | { | ||
| 104 | .addr = HIGH_ADDR, | ||
| 105 | .size = 2UL << 20, | ||
| 106 | .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS, | ||
| 107 | .msg = "mmap(HIGH_ADDR, MAP_HUGETLB)", | ||
| 108 | .keep_mapped = 1, | ||
| 109 | }, | ||
| 110 | { | ||
| 111 | .addr = HIGH_ADDR, | ||
| 112 | .size = 2UL << 20, | ||
| 113 | .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS, | ||
| 114 | .msg = "mmap(HIGH_ADDR, MAP_HUGETLB) again", | ||
| 115 | .keep_mapped = 1, | ||
| 116 | }, | ||
| 117 | { | ||
| 118 | .addr = HIGH_ADDR, | ||
| 119 | .size = 2UL << 20, | ||
| 120 | .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, | ||
| 121 | .msg = "mmap(HIGH_ADDR, MAP_FIXED | MAP_HUGETLB)", | ||
| 122 | }, | ||
| 123 | { | ||
| 124 | .addr = (void*) -1, | ||
| 125 | .size = 2UL << 20, | ||
| 126 | .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS, | ||
| 127 | .msg = "mmap(-1, MAP_HUGETLB)", | ||
| 128 | .keep_mapped = 1, | ||
| 129 | }, | ||
| 130 | { | ||
| 131 | .addr = (void*) -1, | ||
| 132 | .size = 2UL << 20, | ||
| 133 | .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS, | ||
| 134 | .msg = "mmap(-1, MAP_HUGETLB) again", | ||
| 135 | }, | ||
| 136 | { | ||
| 137 | .addr = (void *)((1UL << 47) - PAGE_SIZE), | ||
| 138 | .size = 4UL << 20, | ||
| 139 | .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS, | ||
| 140 | .msg = "mmap((1UL << 47), 4UL << 20, MAP_HUGETLB)", | ||
| 141 | .low_addr_required = 1, | ||
| 142 | .keep_mapped = 1, | ||
| 143 | }, | ||
| 144 | { | ||
| 145 | .addr = (void *)((1UL << 47) - (2UL << 20)), | ||
| 146 | .size = 4UL << 20, | ||
| 147 | .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, | ||
| 148 | .msg = "mmap((1UL << 47) - (2UL << 20), 4UL << 20, MAP_FIXED | MAP_HUGETLB)", | ||
| 149 | }, | ||
| 150 | }; | ||
| 151 | |||
| 152 | int main(int argc, char **argv) | ||
| 153 | { | ||
| 154 | int i; | ||
| 155 | void *p; | ||
| 156 | |||
| 157 | for (i = 0; i < ARRAY_SIZE(testcases); i++) { | ||
| 158 | struct testcase *t = testcases + i; | ||
| 159 | |||
| 160 | p = mmap(t->addr, t->size, PROT_NONE, t->flags, -1, 0); | ||
| 161 | |||
| 162 | printf("%s: %p - ", t->msg, p); | ||
| 163 | |||
| 164 | if (p == MAP_FAILED) { | ||
| 165 | printf("FAILED\n"); | ||
| 166 | continue; | ||
| 167 | } | ||
| 168 | |||
| 169 | if (t->low_addr_required && p >= (void *)(1UL << 47)) | ||
| 170 | printf("FAILED\n"); | ||
| 171 | else | ||
| 172 | printf("OK\n"); | ||
| 173 | if (!t->keep_mapped) | ||
| 174 | munmap(p, t->size); | ||
| 175 | } | ||
| 176 | return 0; | ||
| 177 | } | ||
diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile index 7b1adeee4b0f..939a337128db 100644 --- a/tools/testing/selftests/x86/Makefile +++ b/tools/testing/selftests/x86/Makefile | |||
| @@ -11,7 +11,7 @@ TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt ptrace_sysc | |||
| 11 | TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault test_syscall_vdso unwind_vdso \ | 11 | TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault test_syscall_vdso unwind_vdso \ |
| 12 | test_FCMOV test_FCOMI test_FISTTP \ | 12 | test_FCMOV test_FCOMI test_FISTTP \ |
| 13 | vdso_restorer | 13 | vdso_restorer |
| 14 | TARGETS_C_64BIT_ONLY := fsgsbase sysret_rip | 14 | TARGETS_C_64BIT_ONLY := fsgsbase sysret_rip 5lvl |
| 15 | 15 | ||
| 16 | TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY) | 16 | TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY) |
| 17 | TARGETS_C_64BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_64BIT_ONLY) | 17 | TARGETS_C_64BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_64BIT_ONLY) |
diff --git a/tools/testing/selftests/x86/mpx-hw.h b/tools/testing/selftests/x86/mpx-hw.h index 3f0093911f03..d1b61ab870f8 100644 --- a/tools/testing/selftests/x86/mpx-hw.h +++ b/tools/testing/selftests/x86/mpx-hw.h | |||
| @@ -52,14 +52,14 @@ | |||
| 52 | struct mpx_bd_entry { | 52 | struct mpx_bd_entry { |
| 53 | union { | 53 | union { |
| 54 | char x[MPX_BOUNDS_DIR_ENTRY_SIZE_BYTES]; | 54 | char x[MPX_BOUNDS_DIR_ENTRY_SIZE_BYTES]; |
| 55 | void *contents[1]; | 55 | void *contents[0]; |
| 56 | }; | 56 | }; |
| 57 | } __attribute__((packed)); | 57 | } __attribute__((packed)); |
| 58 | 58 | ||
| 59 | struct mpx_bt_entry { | 59 | struct mpx_bt_entry { |
| 60 | union { | 60 | union { |
| 61 | char x[MPX_BOUNDS_TABLE_ENTRY_SIZE_BYTES]; | 61 | char x[MPX_BOUNDS_TABLE_ENTRY_SIZE_BYTES]; |
| 62 | unsigned long contents[1]; | 62 | unsigned long contents[0]; |
| 63 | }; | 63 | }; |
| 64 | } __attribute__((packed)); | 64 | } __attribute__((packed)); |
| 65 | 65 | ||
diff --git a/tools/testing/selftests/x86/pkey-helpers.h b/tools/testing/selftests/x86/pkey-helpers.h index 3818f25391c2..b3cb7670e026 100644 --- a/tools/testing/selftests/x86/pkey-helpers.h +++ b/tools/testing/selftests/x86/pkey-helpers.h | |||
| @@ -30,6 +30,7 @@ static inline void sigsafe_printf(const char *format, ...) | |||
| 30 | if (!dprint_in_signal) { | 30 | if (!dprint_in_signal) { |
| 31 | vprintf(format, ap); | 31 | vprintf(format, ap); |
| 32 | } else { | 32 | } else { |
| 33 | int ret; | ||
| 33 | int len = vsnprintf(dprint_in_signal_buffer, | 34 | int len = vsnprintf(dprint_in_signal_buffer, |
| 34 | DPRINT_IN_SIGNAL_BUF_SIZE, | 35 | DPRINT_IN_SIGNAL_BUF_SIZE, |
| 35 | format, ap); | 36 | format, ap); |
| @@ -39,7 +40,9 @@ static inline void sigsafe_printf(const char *format, ...) | |||
| 39 | */ | 40 | */ |
| 40 | if (len > DPRINT_IN_SIGNAL_BUF_SIZE) | 41 | if (len > DPRINT_IN_SIGNAL_BUF_SIZE) |
| 41 | len = DPRINT_IN_SIGNAL_BUF_SIZE; | 42 | len = DPRINT_IN_SIGNAL_BUF_SIZE; |
| 42 | write(1, dprint_in_signal_buffer, len); | 43 | ret = write(1, dprint_in_signal_buffer, len); |
| 44 | if (ret < 0) | ||
| 45 | abort(); | ||
| 43 | } | 46 | } |
| 44 | va_end(ap); | 47 | va_end(ap); |
| 45 | } | 48 | } |
diff --git a/tools/testing/selftests/x86/protection_keys.c b/tools/testing/selftests/x86/protection_keys.c index 7a1cc0e56d2d..bc1b0735bb50 100644 --- a/tools/testing/selftests/x86/protection_keys.c +++ b/tools/testing/selftests/x86/protection_keys.c | |||
| @@ -250,7 +250,7 @@ void signal_handler(int signum, siginfo_t *si, void *vucontext) | |||
| 250 | unsigned long ip; | 250 | unsigned long ip; |
| 251 | char *fpregs; | 251 | char *fpregs; |
| 252 | u32 *pkru_ptr; | 252 | u32 *pkru_ptr; |
| 253 | u64 si_pkey; | 253 | u64 siginfo_pkey; |
| 254 | u32 *si_pkey_ptr; | 254 | u32 *si_pkey_ptr; |
| 255 | int pkru_offset; | 255 | int pkru_offset; |
| 256 | fpregset_t fpregset; | 256 | fpregset_t fpregset; |
| @@ -292,9 +292,9 @@ void signal_handler(int signum, siginfo_t *si, void *vucontext) | |||
| 292 | si_pkey_ptr = (u32 *)(((u8 *)si) + si_pkey_offset); | 292 | si_pkey_ptr = (u32 *)(((u8 *)si) + si_pkey_offset); |
| 293 | dprintf1("si_pkey_ptr: %p\n", si_pkey_ptr); | 293 | dprintf1("si_pkey_ptr: %p\n", si_pkey_ptr); |
| 294 | dump_mem(si_pkey_ptr - 8, 24); | 294 | dump_mem(si_pkey_ptr - 8, 24); |
| 295 | si_pkey = *si_pkey_ptr; | 295 | siginfo_pkey = *si_pkey_ptr; |
| 296 | pkey_assert(si_pkey < NR_PKEYS); | 296 | pkey_assert(siginfo_pkey < NR_PKEYS); |
| 297 | last_si_pkey = si_pkey; | 297 | last_si_pkey = siginfo_pkey; |
| 298 | 298 | ||
| 299 | if ((si->si_code == SEGV_MAPERR) || | 299 | if ((si->si_code == SEGV_MAPERR) || |
| 300 | (si->si_code == SEGV_ACCERR) || | 300 | (si->si_code == SEGV_ACCERR) || |
| @@ -306,7 +306,7 @@ void signal_handler(int signum, siginfo_t *si, void *vucontext) | |||
| 306 | dprintf1("signal pkru from xsave: %08x\n", *pkru_ptr); | 306 | dprintf1("signal pkru from xsave: %08x\n", *pkru_ptr); |
| 307 | /* need __rdpkru() version so we do not do shadow_pkru checking */ | 307 | /* need __rdpkru() version so we do not do shadow_pkru checking */ |
| 308 | dprintf1("signal pkru from pkru: %08x\n", __rdpkru()); | 308 | dprintf1("signal pkru from pkru: %08x\n", __rdpkru()); |
| 309 | dprintf1("si_pkey from siginfo: %jx\n", si_pkey); | 309 | dprintf1("pkey from siginfo: %jx\n", siginfo_pkey); |
| 310 | *(u64 *)pkru_ptr = 0x00000000; | 310 | *(u64 *)pkru_ptr = 0x00000000; |
| 311 | dprintf1("WARNING: set PRKU=0 to allow faulting instruction to continue\n"); | 311 | dprintf1("WARNING: set PRKU=0 to allow faulting instruction to continue\n"); |
| 312 | pkru_faults++; | 312 | pkru_faults++; |
