cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

msi_ia64.c (4324B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * MSI hooks for standard x86 apic
      4 */
      5
      6#include <linux/pci.h>
      7#include <linux/irq.h>
      8#include <linux/msi.h>
      9#include <linux/dmar.h>
     10#include <asm/smp.h>
     11#include <asm/msidef.h>
     12
     13static struct irq_chip	ia64_msi_chip;
     14
     15#ifdef CONFIG_SMP
     16static int ia64_set_msi_irq_affinity(struct irq_data *idata,
     17				     const cpumask_t *cpu_mask, bool force)
     18{
     19	struct msi_msg msg;
     20	u32 addr, data;
     21	int cpu = cpumask_first_and(cpu_mask, cpu_online_mask);
     22	unsigned int irq = idata->irq;
     23
     24	if (irq_prepare_move(irq, cpu))
     25		return -1;
     26
     27	__get_cached_msi_msg(irq_data_get_msi_desc(idata), &msg);
     28
     29	addr = msg.address_lo;
     30	addr &= MSI_ADDR_DEST_ID_MASK;
     31	addr |= MSI_ADDR_DEST_ID_CPU(cpu_physical_id(cpu));
     32	msg.address_lo = addr;
     33
     34	data = msg.data;
     35	data &= MSI_DATA_VECTOR_MASK;
     36	data |= MSI_DATA_VECTOR(irq_to_vector(irq));
     37	msg.data = data;
     38
     39	pci_write_msi_msg(irq, &msg);
     40	cpumask_copy(irq_data_get_affinity_mask(idata), cpumask_of(cpu));
     41
     42	return 0;
     43}
     44#endif /* CONFIG_SMP */
     45
     46int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
     47{
     48	struct msi_msg	msg;
     49	unsigned long	dest_phys_id;
     50	int	irq, vector;
     51
     52	irq = create_irq();
     53	if (irq < 0)
     54		return irq;
     55
     56	irq_set_msi_desc(irq, desc);
     57	dest_phys_id = cpu_physical_id(cpumask_any_and(&(irq_to_domain(irq)),
     58						       cpu_online_mask));
     59	vector = irq_to_vector(irq);
     60
     61	msg.address_hi = 0;
     62	msg.address_lo =
     63		MSI_ADDR_HEADER |
     64		MSI_ADDR_DEST_MODE_PHYS |
     65		MSI_ADDR_REDIRECTION_CPU |
     66		MSI_ADDR_DEST_ID_CPU(dest_phys_id);
     67
     68	msg.data =
     69		MSI_DATA_TRIGGER_EDGE |
     70		MSI_DATA_LEVEL_ASSERT |
     71		MSI_DATA_DELIVERY_FIXED |
     72		MSI_DATA_VECTOR(vector);
     73
     74	pci_write_msi_msg(irq, &msg);
     75	irq_set_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq);
     76
     77	return 0;
     78}
     79
     80void arch_teardown_msi_irq(unsigned int irq)
     81{
     82	destroy_irq(irq);
     83}
     84
     85static void ia64_ack_msi_irq(struct irq_data *data)
     86{
     87	irq_complete_move(data->irq);
     88	irq_move_irq(data);
     89	ia64_eoi();
     90}
     91
     92static int ia64_msi_retrigger_irq(struct irq_data *data)
     93{
     94	unsigned int vector = irq_to_vector(data->irq);
     95	ia64_resend_irq(vector);
     96
     97	return 1;
     98}
     99
    100/*
    101 * Generic ops used on most IA64 platforms.
    102 */
    103static struct irq_chip ia64_msi_chip = {
    104	.name			= "PCI-MSI",
    105	.irq_mask		= pci_msi_mask_irq,
    106	.irq_unmask		= pci_msi_unmask_irq,
    107	.irq_ack		= ia64_ack_msi_irq,
    108#ifdef CONFIG_SMP
    109	.irq_set_affinity	= ia64_set_msi_irq_affinity,
    110#endif
    111	.irq_retrigger		= ia64_msi_retrigger_irq,
    112};
    113
    114#ifdef CONFIG_INTEL_IOMMU
    115#ifdef CONFIG_SMP
    116static int dmar_msi_set_affinity(struct irq_data *data,
    117				 const struct cpumask *mask, bool force)
    118{
    119	unsigned int irq = data->irq;
    120	struct irq_cfg *cfg = irq_cfg + irq;
    121	struct msi_msg msg;
    122	int cpu = cpumask_first_and(mask, cpu_online_mask);
    123
    124	if (irq_prepare_move(irq, cpu))
    125		return -1;
    126
    127	dmar_msi_read(irq, &msg);
    128
    129	msg.data &= ~MSI_DATA_VECTOR_MASK;
    130	msg.data |= MSI_DATA_VECTOR(cfg->vector);
    131	msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
    132	msg.address_lo |= MSI_ADDR_DEST_ID_CPU(cpu_physical_id(cpu));
    133
    134	dmar_msi_write(irq, &msg);
    135	cpumask_copy(irq_data_get_affinity_mask(data), mask);
    136
    137	return 0;
    138}
    139#endif /* CONFIG_SMP */
    140
    141static struct irq_chip dmar_msi_type = {
    142	.name = "DMAR_MSI",
    143	.irq_unmask = dmar_msi_unmask,
    144	.irq_mask = dmar_msi_mask,
    145	.irq_ack = ia64_ack_msi_irq,
    146#ifdef CONFIG_SMP
    147	.irq_set_affinity = dmar_msi_set_affinity,
    148#endif
    149	.irq_retrigger = ia64_msi_retrigger_irq,
    150};
    151
    152static void
    153msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
    154{
    155	struct irq_cfg *cfg = irq_cfg + irq;
    156	unsigned dest;
    157
    158	dest = cpu_physical_id(cpumask_first_and(&(irq_to_domain(irq)),
    159						 cpu_online_mask));
    160
    161	msg->address_hi = 0;
    162	msg->address_lo =
    163		MSI_ADDR_HEADER |
    164		MSI_ADDR_DEST_MODE_PHYS |
    165		MSI_ADDR_REDIRECTION_CPU |
    166		MSI_ADDR_DEST_ID_CPU(dest);
    167
    168	msg->data =
    169		MSI_DATA_TRIGGER_EDGE |
    170		MSI_DATA_LEVEL_ASSERT |
    171		MSI_DATA_DELIVERY_FIXED |
    172		MSI_DATA_VECTOR(cfg->vector);
    173}
    174
    175int dmar_alloc_hwirq(int id, int node, void *arg)
    176{
    177	int irq;
    178	struct msi_msg msg;
    179
    180	irq = create_irq();
    181	if (irq > 0) {
    182		irq_set_handler_data(irq, arg);
    183		irq_set_chip_and_handler_name(irq, &dmar_msi_type,
    184					      handle_edge_irq, "edge");
    185		msi_compose_msg(NULL, irq, &msg);
    186		dmar_msi_write(irq, &msg);
    187	}
    188
    189	return irq;
    190}
    191
    192void dmar_free_hwirq(int irq)
    193{
    194	irq_set_handler_data(irq, NULL);
    195	destroy_irq(irq);
    196}
    197#endif /* CONFIG_INTEL_IOMMU */
    198