mirror of
https://github.com/a52xq-dev/kernel.git
synced 2026-10-18 21:58:11 +07:00
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 ...
This commit is contained in:
commit
02fc87b117
38 changed files with 472 additions and 616 deletions
|
|
@ -1,5 +1,10 @@
|
|||
Memory Protection Keys for Userspace (PKU aka PKEYs) is a CPU feature
|
||||
which will be found on future Intel CPUs.
|
||||
Memory Protection Keys for Userspace (PKU aka PKEYs) is a feature
|
||||
which is found on Intel's Skylake "Scalable Processor" Server CPUs.
|
||||
It will be avalable in future non-server parts.
|
||||
|
||||
For anyone wishing to test or use this feature, it is available in
|
||||
Amazon's EC2 C5 instances and is known to work there using an Ubuntu
|
||||
17.04 image.
|
||||
|
||||
Memory Protection Keys provides a mechanism for enforcing page-based
|
||||
protections, but without requiring modification of the page tables
|
||||
|
|
|
|||
|
|
@ -1804,14 +1804,20 @@ config X86_SMAP
|
|||
If unsure, say Y.
|
||||
|
||||
config X86_INTEL_UMIP
|
||||
def_bool n
|
||||
def_bool y
|
||||
depends on CPU_SUP_INTEL
|
||||
prompt "Intel User Mode Instruction Prevention" if EXPERT
|
||||
---help---
|
||||
The User Mode Instruction Prevention (UMIP) is a security
|
||||
feature in newer Intel processors. If enabled, a general
|
||||
protection fault is issued if the instructions SGDT, SLDT,
|
||||
SIDT, SMSW and STR are executed in user mode.
|
||||
protection fault is issued if the SGDT, SLDT, SIDT, SMSW
|
||||
or STR instructions are executed in user mode. These instructions
|
||||
unnecessarily expose information about the hardware state.
|
||||
|
||||
The vast majority of applications do not use these instructions.
|
||||
For the very few that do, software emulation is provided in
|
||||
specific cases in protected and virtual-8086 modes. Emulated
|
||||
results are dummy.
|
||||
|
||||
config X86_INTEL_MPX
|
||||
prompt "Intel MPX (Memory Protection Extensions)"
|
||||
|
|
|
|||
|
|
@ -171,7 +171,6 @@ parse_memmap(char *p, unsigned long long *start, unsigned long long *size)
|
|||
static void mem_avoid_memmap(char *str)
|
||||
{
|
||||
static int i;
|
||||
int rc;
|
||||
|
||||
if (i >= MAX_MEMMAP_REGIONS)
|
||||
return;
|
||||
|
|
@ -219,7 +218,7 @@ static int handle_mem_memmap(void)
|
|||
return 0;
|
||||
|
||||
tmp_cmdline = malloc(len + 1);
|
||||
if (!tmp_cmdline )
|
||||
if (!tmp_cmdline)
|
||||
error("Failed to allocate space for tmp_cmdline");
|
||||
|
||||
memcpy(tmp_cmdline, args, len);
|
||||
|
|
@ -363,7 +362,7 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size,
|
|||
cmd_line |= boot_params->hdr.cmd_line_ptr;
|
||||
/* Calculate size of cmd_line. */
|
||||
ptr = (char *)(unsigned long)cmd_line;
|
||||
for (cmd_line_size = 0; ptr[cmd_line_size++]; )
|
||||
for (cmd_line_size = 0; ptr[cmd_line_size++];)
|
||||
;
|
||||
mem_avoid[MEM_AVOID_CMDLINE].start = cmd_line;
|
||||
mem_avoid[MEM_AVOID_CMDLINE].size = cmd_line_size;
|
||||
|
|
|
|||
|
|
@ -51,15 +51,19 @@ ENTRY(native_usergs_sysret64)
|
|||
END(native_usergs_sysret64)
|
||||
#endif /* CONFIG_PARAVIRT */
|
||||
|
||||
.macro TRACE_IRQS_IRETQ
|
||||
.macro TRACE_IRQS_FLAGS flags:req
|
||||
#ifdef CONFIG_TRACE_IRQFLAGS
|
||||
bt $9, EFLAGS(%rsp) /* interrupts off? */
|
||||
bt $9, \flags /* interrupts off? */
|
||||
jnc 1f
|
||||
TRACE_IRQS_ON
|
||||
1:
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro TRACE_IRQS_IRETQ
|
||||
TRACE_IRQS_FLAGS EFLAGS(%rsp)
|
||||
.endm
|
||||
|
||||
/*
|
||||
* When dynamic function tracer is enabled it will add a breakpoint
|
||||
* to all locations that it is about to modify, sync CPUs, update
|
||||
|
|
@ -148,8 +152,6 @@ ENTRY(entry_SYSCALL_64)
|
|||
movq %rsp, PER_CPU_VAR(rsp_scratch)
|
||||
movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
|
||||
|
||||
TRACE_IRQS_OFF
|
||||
|
||||
/* Construct struct pt_regs on stack */
|
||||
pushq $__USER_DS /* pt_regs->ss */
|
||||
pushq PER_CPU_VAR(rsp_scratch) /* pt_regs->sp */
|
||||
|
|
@ -170,6 +172,8 @@ GLOBAL(entry_SYSCALL_64_after_hwframe)
|
|||
sub $(6*8), %rsp /* pt_regs->bp, bx, r12-15 not saved */
|
||||
UNWIND_HINT_REGS extra=0
|
||||
|
||||
TRACE_IRQS_OFF
|
||||
|
||||
/*
|
||||
* If we need to do entry work or if we guess we'll need to do
|
||||
* exit work, go straight to the slow path.
|
||||
|
|
@ -943,11 +947,13 @@ ENTRY(native_load_gs_index)
|
|||
FRAME_BEGIN
|
||||
pushfq
|
||||
DISABLE_INTERRUPTS(CLBR_ANY & ~CLBR_RDI)
|
||||
TRACE_IRQS_OFF
|
||||
SWAPGS
|
||||
.Lgs_change:
|
||||
movl %edi, %gs
|
||||
2: ALTERNATIVE "", "mfence", X86_BUG_SWAPGS_FENCE
|
||||
SWAPGS
|
||||
TRACE_IRQS_FLAGS (%rsp)
|
||||
popfq
|
||||
FRAME_END
|
||||
ret
|
||||
|
|
|
|||
|
|
@ -975,10 +975,10 @@ static void uncore_pci_remove(struct pci_dev *pdev)
|
|||
int i, phys_id, pkg;
|
||||
|
||||
phys_id = uncore_pcibus_to_physid(pdev->bus);
|
||||
pkg = topology_phys_to_logical_pkg(phys_id);
|
||||
|
||||
box = pci_get_drvdata(pdev);
|
||||
if (!box) {
|
||||
pkg = topology_phys_to_logical_pkg(phys_id);
|
||||
for (i = 0; i < UNCORE_EXTRA_PCI_DEV_MAX; i++) {
|
||||
if (uncore_extra_pci_dev[pkg].dev[i] == pdev) {
|
||||
uncore_extra_pci_dev[pkg].dev[i] = NULL;
|
||||
|
|
@ -994,7 +994,7 @@ static void uncore_pci_remove(struct pci_dev *pdev)
|
|||
return;
|
||||
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
pmu->boxes[pkg] = NULL;
|
||||
pmu->boxes[box->pkgid] = NULL;
|
||||
if (atomic_dec_return(&pmu->activeboxes) == 0)
|
||||
uncore_pmu_unregister(pmu);
|
||||
uncore_box_exit(box);
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ struct intel_uncore_extra_reg {
|
|||
|
||||
struct intel_uncore_box {
|
||||
int pci_phys_id;
|
||||
int pkgid;
|
||||
int pkgid; /* Logical package ID */
|
||||
int n_active; /* number of active events */
|
||||
int n_events;
|
||||
int cpu; /* cpu to collect events */
|
||||
|
|
|
|||
|
|
@ -1057,7 +1057,7 @@ static void snbep_qpi_enable_event(struct intel_uncore_box *box, struct perf_eve
|
|||
|
||||
if (reg1->idx != EXTRA_REG_NONE) {
|
||||
int idx = box->pmu->pmu_idx + SNBEP_PCI_QPI_PORT0_FILTER;
|
||||
int pkg = topology_phys_to_logical_pkg(box->pci_phys_id);
|
||||
int pkg = box->pkgid;
|
||||
struct pci_dev *filter_pdev = uncore_extra_pci_dev[pkg].dev[idx];
|
||||
|
||||
if (filter_pdev) {
|
||||
|
|
|
|||
|
|
@ -309,6 +309,7 @@ static inline int mmap_is_ia32(void)
|
|||
extern unsigned long task_size_32bit(void);
|
||||
extern unsigned long task_size_64bit(int full_addr_space);
|
||||
extern unsigned long get_mmap_base(int is_legacy);
|
||||
extern bool mmap_address_hint_valid(unsigned long addr, unsigned long len);
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
|
||||
|
|
|
|||
|
|
@ -99,14 +99,6 @@ struct irq_alloc_info {
|
|||
void *dmar_data;
|
||||
};
|
||||
#endif
|
||||
#ifdef CONFIG_HT_IRQ
|
||||
struct {
|
||||
int ht_pos;
|
||||
int ht_idx;
|
||||
struct pci_dev *ht_dev;
|
||||
void *ht_update;
|
||||
};
|
||||
#endif
|
||||
#ifdef CONFIG_X86_UV
|
||||
struct {
|
||||
int uv_limit;
|
||||
|
|
|
|||
|
|
@ -1,46 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ASM_X86_HYPERTRANSPORT_H
|
||||
#define _ASM_X86_HYPERTRANSPORT_H
|
||||
|
||||
/*
|
||||
* Constants for x86 Hypertransport Interrupts.
|
||||
*/
|
||||
|
||||
#define HT_IRQ_LOW_BASE 0xf8000000
|
||||
|
||||
#define HT_IRQ_LOW_VECTOR_SHIFT 16
|
||||
#define HT_IRQ_LOW_VECTOR_MASK 0x00ff0000
|
||||
#define HT_IRQ_LOW_VECTOR(v) \
|
||||
(((v) << HT_IRQ_LOW_VECTOR_SHIFT) & HT_IRQ_LOW_VECTOR_MASK)
|
||||
|
||||
#define HT_IRQ_LOW_DEST_ID_SHIFT 8
|
||||
#define HT_IRQ_LOW_DEST_ID_MASK 0x0000ff00
|
||||
#define HT_IRQ_LOW_DEST_ID(v) \
|
||||
(((v) << HT_IRQ_LOW_DEST_ID_SHIFT) & HT_IRQ_LOW_DEST_ID_MASK)
|
||||
|
||||
#define HT_IRQ_LOW_DM_PHYSICAL 0x0000000
|
||||
#define HT_IRQ_LOW_DM_LOGICAL 0x0000040
|
||||
|
||||
#define HT_IRQ_LOW_RQEOI_EDGE 0x0000000
|
||||
#define HT_IRQ_LOW_RQEOI_LEVEL 0x0000020
|
||||
|
||||
|
||||
#define HT_IRQ_LOW_MT_FIXED 0x0000000
|
||||
#define HT_IRQ_LOW_MT_ARBITRATED 0x0000004
|
||||
#define HT_IRQ_LOW_MT_SMI 0x0000008
|
||||
#define HT_IRQ_LOW_MT_NMI 0x000000c
|
||||
#define HT_IRQ_LOW_MT_INIT 0x0000010
|
||||
#define HT_IRQ_LOW_MT_STARTUP 0x0000014
|
||||
#define HT_IRQ_LOW_MT_EXTINT 0x0000018
|
||||
#define HT_IRQ_LOW_MT_LINT1 0x000008c
|
||||
#define HT_IRQ_LOW_MT_LINT0 0x0000098
|
||||
|
||||
#define HT_IRQ_LOW_IRQ_MASKED 0x0000001
|
||||
|
||||
|
||||
#define HT_IRQ_HIGH_DEST_ID_SHIFT 0
|
||||
#define HT_IRQ_HIGH_DEST_ID_MASK 0x00ffffff
|
||||
#define HT_IRQ_HIGH_DEST_ID(v) \
|
||||
((((v) >> 8) << HT_IRQ_HIGH_DEST_ID_SHIFT) & HT_IRQ_HIGH_DEST_ID_MASK)
|
||||
|
||||
#endif /* _ASM_X86_HYPERTRANSPORT_H */
|
||||
|
|
@ -18,6 +18,6 @@
|
|||
void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs);
|
||||
int insn_get_modrm_rm_off(struct insn *insn, struct pt_regs *regs);
|
||||
unsigned long insn_get_seg_base(struct pt_regs *regs, int seg_reg_idx);
|
||||
char insn_get_code_seg_params(struct pt_regs *regs);
|
||||
int insn_get_code_seg_params(struct pt_regs *regs);
|
||||
|
||||
#endif /* _ASM_X86_INSN_EVAL_H */
|
||||
|
|
|
|||
|
|
@ -111,6 +111,10 @@ build_mmio_write(__writeq, "q", unsigned long, "r", )
|
|||
|
||||
#endif
|
||||
|
||||
#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
|
||||
extern int valid_phys_addr_range(phys_addr_t addr, size_t size);
|
||||
extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
|
||||
|
||||
/**
|
||||
* virt_to_phys - map virtual addresses to physical
|
||||
* @address: address to remap
|
||||
|
|
|
|||
|
|
@ -56,10 +56,4 @@ extern void arch_init_msi_domain(struct irq_domain *domain);
|
|||
static inline void arch_init_msi_domain(struct irq_domain *domain) { }
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HT_IRQ
|
||||
extern void arch_init_htirq_domain(struct irq_domain *domain);
|
||||
#else
|
||||
static inline void arch_init_htirq_domain(struct irq_domain *domain) { }
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -132,6 +132,7 @@ struct cpuinfo_x86 {
|
|||
/* Index into per_cpu list: */
|
||||
u16 cpu_index;
|
||||
u32 microcode;
|
||||
unsigned initialized : 1;
|
||||
} __randomize_layout;
|
||||
|
||||
struct cpuid_regs {
|
||||
|
|
|
|||
|
|
@ -342,13 +342,12 @@ acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long e
|
|||
#ifdef CONFIG_X86_IO_APIC
|
||||
#define MP_ISA_BUS 0
|
||||
|
||||
static int __init mp_register_ioapic_irq(u8 bus_irq, u8 polarity,
|
||||
u8 trigger, u32 gsi);
|
||||
|
||||
static void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
|
||||
u32 gsi)
|
||||
{
|
||||
int ioapic;
|
||||
int pin;
|
||||
struct mpc_intsrc mp_irq;
|
||||
|
||||
/*
|
||||
* Check bus_irq boundary.
|
||||
*/
|
||||
|
|
@ -357,14 +356,6 @@ static void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
|
|||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert 'gsi' to 'ioapic.pin'.
|
||||
*/
|
||||
ioapic = mp_find_ioapic(gsi);
|
||||
if (ioapic < 0)
|
||||
return;
|
||||
pin = mp_find_ioapic_pin(ioapic, gsi);
|
||||
|
||||
/*
|
||||
* TBD: This check is for faulty timer entries, where the override
|
||||
* erroneously sets the trigger to level, resulting in a HUGE
|
||||
|
|
@ -373,16 +364,8 @@ static void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
|
|||
if ((bus_irq == 0) && (trigger == 3))
|
||||
trigger = 1;
|
||||
|
||||
mp_irq.type = MP_INTSRC;
|
||||
mp_irq.irqtype = mp_INT;
|
||||
mp_irq.irqflag = (trigger << 2) | polarity;
|
||||
mp_irq.srcbus = MP_ISA_BUS;
|
||||
mp_irq.srcbusirq = bus_irq; /* IRQ */
|
||||
mp_irq.dstapic = mpc_ioapic_id(ioapic); /* APIC ID */
|
||||
mp_irq.dstirq = pin; /* INTIN# */
|
||||
|
||||
mp_save_irq(&mp_irq);
|
||||
|
||||
if (mp_register_ioapic_irq(bus_irq, polarity, trigger, gsi) < 0)
|
||||
return;
|
||||
/*
|
||||
* Reset default identity mapping if gsi is also an legacy IRQ,
|
||||
* 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,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __init mp_register_ioapic_irq(u8 bus_irq, u8 polarity,
|
||||
u8 trigger, u32 gsi)
|
||||
{
|
||||
struct mpc_intsrc mp_irq;
|
||||
int ioapic, pin;
|
||||
|
||||
/* Convert 'gsi' to 'ioapic.pin'(INTIN#) */
|
||||
ioapic = mp_find_ioapic(gsi);
|
||||
if (ioapic < 0) {
|
||||
pr_warn("Failed to find ioapic for gsi : %u\n", gsi);
|
||||
return ioapic;
|
||||
}
|
||||
|
||||
pin = mp_find_ioapic_pin(ioapic, gsi);
|
||||
|
||||
mp_irq.type = MP_INTSRC;
|
||||
mp_irq.irqtype = mp_INT;
|
||||
mp_irq.irqflag = (trigger << 2) | polarity;
|
||||
mp_irq.srcbus = MP_ISA_BUS;
|
||||
mp_irq.srcbusirq = bus_irq;
|
||||
mp_irq.dstapic = mpc_ioapic_id(ioapic);
|
||||
mp_irq.dstirq = pin;
|
||||
|
||||
mp_save_irq(&mp_irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init
|
||||
acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
|
||||
{
|
||||
|
|
@ -473,7 +484,11 @@ static void __init acpi_sci_ioapic_setup(u8 bus_irq, u16 polarity, u16 trigger,
|
|||
if (acpi_sci_flags & ACPI_MADT_POLARITY_MASK)
|
||||
polarity = acpi_sci_flags & ACPI_MADT_POLARITY_MASK;
|
||||
|
||||
mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);
|
||||
if (bus_irq < NR_IRQS_LEGACY)
|
||||
mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);
|
||||
else
|
||||
mp_register_ioapic_irq(bus_irq, polarity, trigger, gsi);
|
||||
|
||||
acpi_penalize_sci_irq(bus_irq, trigger, polarity);
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ obj-y += hw_nmi.o
|
|||
|
||||
obj-$(CONFIG_X86_IO_APIC) += io_apic.o
|
||||
obj-$(CONFIG_PCI_MSI) += msi.o
|
||||
obj-$(CONFIG_HT_IRQ) += htirq.o
|
||||
obj-$(CONFIG_SMP) += ipi.o
|
||||
|
||||
ifeq ($(CONFIG_X86_64),y)
|
||||
|
|
|
|||
|
|
@ -1,198 +0,0 @@
|
|||
/*
|
||||
* Support Hypertransport IRQ
|
||||
*
|
||||
* Copyright (C) 1997, 1998, 1999, 2000, 2009 Ingo Molnar, Hajnalka Szabo
|
||||
* Moved from arch/x86/kernel/apic/io_apic.c.
|
||||
* Jiang Liu <jiang.liu@linux.intel.com>
|
||||
* Add support of hierarchical irqdomain
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/mm.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/htirq.h>
|
||||
#include <asm/irqdomain.h>
|
||||
#include <asm/hw_irq.h>
|
||||
#include <asm/apic.h>
|
||||
#include <asm/hypertransport.h>
|
||||
|
||||
static struct irq_domain *htirq_domain;
|
||||
|
||||
/*
|
||||
* Hypertransport interrupt support
|
||||
*/
|
||||
static int
|
||||
ht_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force)
|
||||
{
|
||||
struct irq_data *parent = data->parent_data;
|
||||
int ret;
|
||||
|
||||
ret = parent->chip->irq_set_affinity(parent, mask, force);
|
||||
if (ret >= 0) {
|
||||
struct ht_irq_msg msg;
|
||||
struct irq_cfg *cfg = irqd_cfg(data);
|
||||
|
||||
fetch_ht_irq_msg(data->irq, &msg);
|
||||
msg.address_lo &= ~(HT_IRQ_LOW_VECTOR_MASK |
|
||||
HT_IRQ_LOW_DEST_ID_MASK);
|
||||
msg.address_lo |= HT_IRQ_LOW_VECTOR(cfg->vector) |
|
||||
HT_IRQ_LOW_DEST_ID(cfg->dest_apicid);
|
||||
msg.address_hi &= ~(HT_IRQ_HIGH_DEST_ID_MASK);
|
||||
msg.address_hi |= HT_IRQ_HIGH_DEST_ID(cfg->dest_apicid);
|
||||
write_ht_irq_msg(data->irq, &msg);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct irq_chip ht_irq_chip = {
|
||||
.name = "PCI-HT",
|
||||
.irq_mask = mask_ht_irq,
|
||||
.irq_unmask = unmask_ht_irq,
|
||||
.irq_ack = irq_chip_ack_parent,
|
||||
.irq_set_affinity = ht_set_affinity,
|
||||
.irq_retrigger = irq_chip_retrigger_hierarchy,
|
||||
.flags = IRQCHIP_SKIP_SET_WAKE,
|
||||
};
|
||||
|
||||
static int htirq_domain_alloc(struct irq_domain *domain, unsigned int virq,
|
||||
unsigned int nr_irqs, void *arg)
|
||||
{
|
||||
struct ht_irq_cfg *ht_cfg;
|
||||
struct irq_alloc_info *info = arg;
|
||||
struct pci_dev *dev;
|
||||
irq_hw_number_t hwirq;
|
||||
int ret;
|
||||
|
||||
if (nr_irqs > 1 || !info)
|
||||
return -EINVAL;
|
||||
|
||||
dev = info->ht_dev;
|
||||
hwirq = (info->ht_idx & 0xFF) |
|
||||
PCI_DEVID(dev->bus->number, dev->devfn) << 8 |
|
||||
(pci_domain_nr(dev->bus) & 0xFFFFFFFF) << 24;
|
||||
if (irq_find_mapping(domain, hwirq) > 0)
|
||||
return -EEXIST;
|
||||
|
||||
ht_cfg = kmalloc(sizeof(*ht_cfg), GFP_KERNEL);
|
||||
if (!ht_cfg)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, info);
|
||||
if (ret < 0) {
|
||||
kfree(ht_cfg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Initialize msg to a value that will never match the first write. */
|
||||
ht_cfg->msg.address_lo = 0xffffffff;
|
||||
ht_cfg->msg.address_hi = 0xffffffff;
|
||||
ht_cfg->dev = info->ht_dev;
|
||||
ht_cfg->update = info->ht_update;
|
||||
ht_cfg->pos = info->ht_pos;
|
||||
ht_cfg->idx = 0x10 + (info->ht_idx * 2);
|
||||
irq_domain_set_info(domain, virq, hwirq, &ht_irq_chip, ht_cfg,
|
||||
handle_edge_irq, ht_cfg, "edge");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void htirq_domain_free(struct irq_domain *domain, unsigned int virq,
|
||||
unsigned int nr_irqs)
|
||||
{
|
||||
struct irq_data *irq_data = irq_domain_get_irq_data(domain, virq);
|
||||
|
||||
BUG_ON(nr_irqs != 1);
|
||||
kfree(irq_data->chip_data);
|
||||
irq_domain_free_irqs_top(domain, virq, nr_irqs);
|
||||
}
|
||||
|
||||
static int htirq_domain_activate(struct irq_domain *domain,
|
||||
struct irq_data *irq_data, bool early)
|
||||
{
|
||||
struct ht_irq_msg msg;
|
||||
struct irq_cfg *cfg = irqd_cfg(irq_data);
|
||||
|
||||
msg.address_hi = HT_IRQ_HIGH_DEST_ID(cfg->dest_apicid);
|
||||
msg.address_lo =
|
||||
HT_IRQ_LOW_BASE |
|
||||
HT_IRQ_LOW_DEST_ID(cfg->dest_apicid) |
|
||||
HT_IRQ_LOW_VECTOR(cfg->vector) |
|
||||
((apic->irq_dest_mode == 0) ?
|
||||
HT_IRQ_LOW_DM_PHYSICAL :
|
||||
HT_IRQ_LOW_DM_LOGICAL) |
|
||||
HT_IRQ_LOW_RQEOI_EDGE |
|
||||
((apic->irq_delivery_mode != dest_LowestPrio) ?
|
||||
HT_IRQ_LOW_MT_FIXED :
|
||||
HT_IRQ_LOW_MT_ARBITRATED) |
|
||||
HT_IRQ_LOW_IRQ_MASKED;
|
||||
write_ht_irq_msg(irq_data->irq, &msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void htirq_domain_deactivate(struct irq_domain *domain,
|
||||
struct irq_data *irq_data)
|
||||
{
|
||||
struct ht_irq_msg msg;
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
write_ht_irq_msg(irq_data->irq, &msg);
|
||||
}
|
||||
|
||||
static const struct irq_domain_ops htirq_domain_ops = {
|
||||
.alloc = htirq_domain_alloc,
|
||||
.free = htirq_domain_free,
|
||||
.activate = htirq_domain_activate,
|
||||
.deactivate = htirq_domain_deactivate,
|
||||
};
|
||||
|
||||
void __init arch_init_htirq_domain(struct irq_domain *parent)
|
||||
{
|
||||
struct fwnode_handle *fn;
|
||||
|
||||
if (disable_apic)
|
||||
return;
|
||||
|
||||
fn = irq_domain_alloc_named_fwnode("PCI-HT");
|
||||
if (!fn)
|
||||
goto warn;
|
||||
|
||||
htirq_domain = irq_domain_create_tree(fn, &htirq_domain_ops, NULL);
|
||||
irq_domain_free_fwnode(fn);
|
||||
if (!htirq_domain)
|
||||
goto warn;
|
||||
|
||||
htirq_domain->parent = parent;
|
||||
return;
|
||||
|
||||
warn:
|
||||
pr_warn("Failed to initialize irqdomain for HTIRQ.\n");
|
||||
}
|
||||
|
||||
int arch_setup_ht_irq(int idx, int pos, struct pci_dev *dev,
|
||||
ht_irq_update_t *update)
|
||||
{
|
||||
struct irq_alloc_info info;
|
||||
|
||||
if (!htirq_domain)
|
||||
return -ENOSYS;
|
||||
|
||||
init_irq_alloc_info(&info, NULL);
|
||||
info.ht_idx = idx;
|
||||
info.ht_pos = pos;
|
||||
info.ht_dev = dev;
|
||||
info.ht_update = update;
|
||||
|
||||
return irq_domain_alloc_irqs(htirq_domain, 1, dev_to_node(&dev->dev),
|
||||
&info);
|
||||
}
|
||||
|
||||
void arch_teardown_ht_irq(unsigned int irq)
|
||||
{
|
||||
irq_domain_free_irqs(irq, 1);
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Local APIC related interfaces to support IOAPIC, MSI, HT_IRQ etc.
|
||||
* Local APIC related interfaces to support IOAPIC, MSI, etc.
|
||||
*
|
||||
* Copyright (C) 1997, 1998, 1999, 2000, 2009 Ingo Molnar, Hajnalka Szabo
|
||||
* Moved from arch/x86/kernel/apic/io_apic.c.
|
||||
|
|
@ -601,7 +601,7 @@ int __init arch_probe_nr_irqs(void)
|
|||
nr_irqs = NR_VECTORS * nr_cpu_ids;
|
||||
|
||||
nr = (gsi_top + nr_legacy_irqs()) + 8 * nr_cpu_ids;
|
||||
#if defined(CONFIG_PCI_MSI) || defined(CONFIG_HT_IRQ)
|
||||
#if defined(CONFIG_PCI_MSI)
|
||||
/*
|
||||
* for MSI and HT dyn irq
|
||||
*/
|
||||
|
|
@ -663,7 +663,6 @@ int __init arch_early_irq_init(void)
|
|||
irq_set_default_host(x86_vector_domain);
|
||||
|
||||
arch_init_msi_domain(x86_vector_domain);
|
||||
arch_init_htirq_domain(x86_vector_domain);
|
||||
|
||||
BUG_ON(!alloc_cpumask_var(&vector_searchmask, GFP_KERNEL));
|
||||
|
||||
|
|
|
|||
|
|
@ -341,6 +341,8 @@ static __always_inline void setup_umip(struct cpuinfo_x86 *c)
|
|||
|
||||
cr4_set_bits(X86_CR4_UMIP);
|
||||
|
||||
pr_info("x86/cpu: Activated the Intel User Mode Instruction Prevention (UMIP) CPU feature\n");
|
||||
|
||||
return;
|
||||
|
||||
out:
|
||||
|
|
|
|||
|
|
@ -431,6 +431,7 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type)
|
|||
}
|
||||
|
||||
static unsigned long mpf_base;
|
||||
static bool mpf_found;
|
||||
|
||||
static unsigned long __init get_mpc_size(unsigned long physptr)
|
||||
{
|
||||
|
|
@ -504,7 +505,7 @@ void __init default_get_smp_config(unsigned int early)
|
|||
if (!smp_found_config)
|
||||
return;
|
||||
|
||||
if (!mpf_base)
|
||||
if (!mpf_found)
|
||||
return;
|
||||
|
||||
if (acpi_lapic && early)
|
||||
|
|
@ -593,6 +594,7 @@ static int __init smp_scan_config(unsigned long base, unsigned long length)
|
|||
smp_found_config = 1;
|
||||
#endif
|
||||
mpf_base = base;
|
||||
mpf_found = true;
|
||||
|
||||
pr_info("found SMP MP-table at [mem %#010lx-%#010lx] mapped at [%p]\n",
|
||||
base, base + sizeof(*mpf) - 1, mpf);
|
||||
|
|
@ -858,7 +860,7 @@ static int __init update_mp_table(void)
|
|||
if (!enable_update_mptable)
|
||||
return 0;
|
||||
|
||||
if (!mpf_base)
|
||||
if (!mpf_found)
|
||||
return 0;
|
||||
|
||||
mpf = early_memremap(mpf_base, sizeof(*mpf));
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue