diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-31 19:17:19 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-31 19:17:19 -0500 |
| commit | d517be5fcf1a7feb06ce3d5f28055ad1ce17030b (patch) | |
| tree | aa3974eaaa147425aa4cb96c865dc2683eaa3d3a | |
| parent | dc799d0179baa7f62d2e73a8217a273ca82adbdf (diff) | |
| parent | 742563777e8da62197d6cb4b99f4027f59454735 (diff) | |
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fixes from Thomas Gleixner:
"A bit on the largish side due to a series of fixes for a regression in
the x86 vector management which was introduced in 4.3. This work was
started in December already, but it took some time to fix all corner
cases and a couple of older bugs in that area which were detected
while at it
Aside of that a few platform updates for intel-mid, quark and UV and
two fixes for in the mm code:
- Use proper types for pgprot values to avoid truncation
- Prevent a size truncation in the pageattr code when setting page
attributes for large mappings"
* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (21 commits)
x86/mm/pat: Avoid truncation when converting cpa->numpages to address
x86/mm: Fix types used in pgprot cacheability flags translations
x86/platform/quark: Print boundaries correctly
x86/platform/UV: Remove EFI memmap quirk for UV2+
x86/platform/intel-mid: Join string and fix SoC name
x86/platform/intel-mid: Enable 64-bit build
x86/irq: Plug vector cleanup race
x86/irq: Call irq_force_move_complete with irq descriptor
x86/irq: Remove outgoing CPU from vector cleanup mask
x86/irq: Remove the cpumask allocation from send_cleanup_vector()
x86/irq: Clear move_in_progress before sending cleanup IPI
x86/irq: Remove offline cpus from vector cleanup
x86/irq: Get rid of code duplication
x86/irq: Copy vectormask instead of an AND operation
x86/irq: Check vector allocation early
x86/irq: Reorganize the search in assign_irq_vector
x86/irq: Reorganize the return path in assign_irq_vector
x86/irq: Do not use apic_chip_data.old_domain as temporary buffer
x86/irq: Validate that irq descriptor is still active
x86/irq: Fix a race in x86_vector_free_irqs()
...
| -rw-r--r-- | arch/x86/Kconfig | 3 | ||||
| -rw-r--r-- | arch/x86/include/asm/irq.h | 5 | ||||
| -rw-r--r-- | arch/x86/include/asm/pgtable_types.h | 6 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 6 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/vector.c | 221 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/x2apic_uv_x.c | 5 | ||||
| -rw-r--r-- | arch/x86/kernel/head64.c | 8 | ||||
| -rw-r--r-- | arch/x86/kernel/irq.c | 11 | ||||
| -rw-r--r-- | arch/x86/mm/pageattr.c | 4 | ||||
| -rw-r--r-- | arch/x86/platform/efi/quirks.c | 17 | ||||
| -rw-r--r-- | arch/x86/platform/intel-mid/intel-mid.c | 8 | ||||
| -rw-r--r-- | arch/x86/platform/intel-quark/imr.c | 18 |
12 files changed, 209 insertions, 103 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 330e738ccfc1..9af2e6338400 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
| @@ -509,11 +509,10 @@ config X86_INTEL_CE | |||
| 509 | 509 | ||
| 510 | config X86_INTEL_MID | 510 | config X86_INTEL_MID |
| 511 | bool "Intel MID platform support" | 511 | bool "Intel MID platform support" |
| 512 | depends on X86_32 | ||
| 513 | depends on X86_EXTENDED_PLATFORM | 512 | depends on X86_EXTENDED_PLATFORM |
| 514 | depends on X86_PLATFORM_DEVICES | 513 | depends on X86_PLATFORM_DEVICES |
| 515 | depends on PCI | 514 | depends on PCI |
| 516 | depends on PCI_GOANY | 515 | depends on X86_64 || (PCI_GOANY && X86_32) |
| 517 | depends on X86_IO_APIC | 516 | depends on X86_IO_APIC |
| 518 | select SFI | 517 | select SFI |
| 519 | select I2C | 518 | select I2C |
diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h index 881b4768644a..e7de5c9a4fbd 100644 --- a/arch/x86/include/asm/irq.h +++ b/arch/x86/include/asm/irq.h | |||
| @@ -23,11 +23,13 @@ extern void irq_ctx_init(int cpu); | |||
| 23 | 23 | ||
| 24 | #define __ARCH_HAS_DO_SOFTIRQ | 24 | #define __ARCH_HAS_DO_SOFTIRQ |
| 25 | 25 | ||
| 26 | struct irq_desc; | ||
| 27 | |||
| 26 | #ifdef CONFIG_HOTPLUG_CPU | 28 | #ifdef CONFIG_HOTPLUG_CPU |
| 27 | #include <linux/cpumask.h> | 29 | #include <linux/cpumask.h> |
| 28 | extern int check_irq_vectors_for_cpu_disable(void); | 30 | extern int check_irq_vectors_for_cpu_disable(void); |
| 29 | extern void fixup_irqs(void); | 31 | extern void fixup_irqs(void); |
| 30 | extern void irq_force_complete_move(int); | 32 | extern void irq_force_complete_move(struct irq_desc *desc); |
| 31 | #endif | 33 | #endif |
| 32 | 34 | ||
| 33 | #ifdef CONFIG_HAVE_KVM | 35 | #ifdef CONFIG_HAVE_KVM |
| @@ -37,7 +39,6 @@ extern void kvm_set_posted_intr_wakeup_handler(void (*handler)(void)); | |||
| 37 | extern void (*x86_platform_ipi_callback)(void); | 39 | extern void (*x86_platform_ipi_callback)(void); |
| 38 | extern void native_init_IRQ(void); | 40 | extern void native_init_IRQ(void); |
| 39 | 41 | ||
| 40 | struct irq_desc; | ||
| 41 | extern bool handle_irq(struct irq_desc *desc, struct pt_regs *regs); | 42 | extern bool handle_irq(struct irq_desc *desc, struct pt_regs *regs); |
| 42 | 43 | ||
| 43 | extern __visible unsigned int do_IRQ(struct pt_regs *regs); | 44 | extern __visible unsigned int do_IRQ(struct pt_regs *regs); |
diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h index 04c27a013165..4432ab7f407c 100644 --- a/arch/x86/include/asm/pgtable_types.h +++ b/arch/x86/include/asm/pgtable_types.h | |||
| @@ -366,20 +366,18 @@ static inline enum page_cache_mode pgprot2cachemode(pgprot_t pgprot) | |||
| 366 | } | 366 | } |
| 367 | static inline pgprot_t pgprot_4k_2_large(pgprot_t pgprot) | 367 | static inline pgprot_t pgprot_4k_2_large(pgprot_t pgprot) |
| 368 | { | 368 | { |
| 369 | pgprotval_t val = pgprot_val(pgprot); | ||
| 369 | pgprot_t new; | 370 | pgprot_t new; |
| 370 | unsigned long val; | ||
| 371 | 371 | ||
| 372 | val = pgprot_val(pgprot); | ||
| 373 | pgprot_val(new) = (val & ~(_PAGE_PAT | _PAGE_PAT_LARGE)) | | 372 | pgprot_val(new) = (val & ~(_PAGE_PAT | _PAGE_PAT_LARGE)) | |
| 374 | ((val & _PAGE_PAT) << (_PAGE_BIT_PAT_LARGE - _PAGE_BIT_PAT)); | 373 | ((val & _PAGE_PAT) << (_PAGE_BIT_PAT_LARGE - _PAGE_BIT_PAT)); |
| 375 | return new; | 374 | return new; |
| 376 | } | 375 | } |
| 377 | static inline pgprot_t pgprot_large_2_4k(pgprot_t pgprot) | 376 | static inline pgprot_t pgprot_large_2_4k(pgprot_t pgprot) |
| 378 | { | 377 | { |
| 378 | pgprotval_t val = pgprot_val(pgprot); | ||
| 379 | pgprot_t new; | 379 | pgprot_t new; |
| 380 | unsigned long val; | ||
| 381 | 380 | ||
| 382 | val = pgprot_val(pgprot); | ||
| 383 | pgprot_val(new) = (val & ~(_PAGE_PAT | _PAGE_PAT_LARGE)) | | 381 | pgprot_val(new) = (val & ~(_PAGE_PAT | _PAGE_PAT_LARGE)) | |
| 384 | ((val & _PAGE_PAT_LARGE) >> | 382 | ((val & _PAGE_PAT_LARGE) >> |
| 385 | (_PAGE_BIT_PAT_LARGE - _PAGE_BIT_PAT)); | 383 | (_PAGE_BIT_PAT_LARGE - _PAGE_BIT_PAT)); |
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index f25321894ad2..fdb0fbfb1197 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
| @@ -2521,6 +2521,7 @@ void __init setup_ioapic_dest(void) | |||
| 2521 | { | 2521 | { |
| 2522 | int pin, ioapic, irq, irq_entry; | 2522 | int pin, ioapic, irq, irq_entry; |
| 2523 | const struct cpumask *mask; | 2523 | const struct cpumask *mask; |
| 2524 | struct irq_desc *desc; | ||
| 2524 | struct irq_data *idata; | 2525 | struct irq_data *idata; |
| 2525 | struct irq_chip *chip; | 2526 | struct irq_chip *chip; |
| 2526 | 2527 | ||
| @@ -2536,7 +2537,9 @@ void __init setup_ioapic_dest(void) | |||
| 2536 | if (irq < 0 || !mp_init_irq_at_boot(ioapic, irq)) | 2537 | if (irq < 0 || !mp_init_irq_at_boot(ioapic, irq)) |
| 2537 | continue; | 2538 | continue; |
| 2538 | 2539 | ||
| 2539 | idata = irq_get_irq_data(irq); | 2540 | desc = irq_to_desc(irq); |
| 2541 | raw_spin_lock_irq(&desc->lock); | ||
| 2542 | idata = irq_desc_get_irq_data(desc); | ||
| 2540 | 2543 | ||
| 2541 | /* | 2544 | /* |
| 2542 | * Honour affinities which have been set in early boot | 2545 | * Honour affinities which have been set in early boot |
| @@ -2550,6 +2553,7 @@ void __init setup_ioapic_dest(void) | |||
| 2550 | /* Might be lapic_chip for irq 0 */ | 2553 | /* Might be lapic_chip for irq 0 */ |
| 2551 | if (chip->irq_set_affinity) | 2554 | if (chip->irq_set_affinity) |
| 2552 | chip->irq_set_affinity(idata, mask, false); | 2555 | chip->irq_set_affinity(idata, mask, false); |
| 2556 | raw_spin_unlock_irq(&desc->lock); | ||
| 2553 | } | 2557 | } |
| 2554 | } | 2558 | } |
| 2555 | #endif | 2559 | #endif |
diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c index 908cb37da171..3b670df4ba7b 100644 --- a/arch/x86/kernel/apic/vector.c +++ b/arch/x86/kernel/apic/vector.c | |||
| @@ -31,7 +31,7 @@ struct apic_chip_data { | |||
| 31 | struct irq_domain *x86_vector_domain; | 31 | struct irq_domain *x86_vector_domain; |
| 32 | EXPORT_SYMBOL_GPL(x86_vector_domain); | 32 | EXPORT_SYMBOL_GPL(x86_vector_domain); |
| 33 | static DEFINE_RAW_SPINLOCK(vector_lock); | 33 | static DEFINE_RAW_SPINLOCK(vector_lock); |
| 34 | static cpumask_var_t vector_cpumask; | 34 | static cpumask_var_t vector_cpumask, vector_searchmask, searched_cpumask; |
| 35 | static struct irq_chip lapic_controller; | 35 | static struct irq_chip lapic_controller; |
| 36 | #ifdef CONFIG_X86_IO_APIC | 36 | #ifdef CONFIG_X86_IO_APIC |
| 37 | static struct apic_chip_data *legacy_irq_data[NR_IRQS_LEGACY]; | 37 | static struct apic_chip_data *legacy_irq_data[NR_IRQS_LEGACY]; |
| @@ -118,35 +118,47 @@ static int __assign_irq_vector(int irq, struct apic_chip_data *d, | |||
| 118 | */ | 118 | */ |
| 119 | static int current_vector = FIRST_EXTERNAL_VECTOR + VECTOR_OFFSET_START; | 119 | static int current_vector = FIRST_EXTERNAL_VECTOR + VECTOR_OFFSET_START; |
| 120 | static int current_offset = VECTOR_OFFSET_START % 16; | 120 | static int current_offset = VECTOR_OFFSET_START % 16; |
| 121 | int cpu, err; | 121 | int cpu, vector; |
| 122 | 122 | ||
| 123 | if (d->move_in_progress) | 123 | /* |
| 124 | * If there is still a move in progress or the previous move has not | ||
| 125 | * been cleaned up completely, tell the caller to come back later. | ||
| 126 | */ | ||
| 127 | if (d->move_in_progress || | ||
| 128 | cpumask_intersects(d->old_domain, cpu_online_mask)) | ||
| 124 | return -EBUSY; | 129 | return -EBUSY; |
| 125 | 130 | ||
| 126 | /* Only try and allocate irqs on cpus that are present */ | 131 | /* Only try and allocate irqs on cpus that are present */ |
| 127 | err = -ENOSPC; | ||
| 128 | cpumask_clear(d->old_domain); | 132 | cpumask_clear(d->old_domain); |
| 133 | cpumask_clear(searched_cpumask); | ||
| 129 | cpu = cpumask_first_and(mask, cpu_online_mask); | 134 | cpu = cpumask_first_and(mask, cpu_online_mask); |
| 130 | while (cpu < nr_cpu_ids) { | 135 | while (cpu < nr_cpu_ids) { |
| 131 | int new_cpu, vector, offset; | 136 | int new_cpu, offset; |
| 132 | 137 | ||
| 138 | /* Get the possible target cpus for @mask/@cpu from the apic */ | ||
| 133 | apic->vector_allocation_domain(cpu, vector_cpumask, mask); | 139 | apic->vector_allocation_domain(cpu, vector_cpumask, mask); |
| 134 | 140 | ||
| 141 | /* | ||
| 142 | * Clear the offline cpus from @vector_cpumask for searching | ||
| 143 | * and verify whether the result overlaps with @mask. If true, | ||
| 144 | * then the call to apic->cpu_mask_to_apicid_and() will | ||
| 145 | * succeed as well. If not, no point in trying to find a | ||
| 146 | * vector in this mask. | ||
| 147 | */ | ||
| 148 | cpumask_and(vector_searchmask, vector_cpumask, cpu_online_mask); | ||
| 149 | if (!cpumask_intersects(vector_searchmask, mask)) | ||
| 150 | goto next_cpu; | ||
| 151 | |||
| 135 | if (cpumask_subset(vector_cpumask, d->domain)) { | 152 | if (cpumask_subset(vector_cpumask, d->domain)) { |
