LCOV - code coverage report
Current view: top level - arch/x86/kernel/apic - vector.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 246 585 42.1 %
Date: 2021-04-22 12:43:58 Functions: 32 56 57.1 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-only
       2             : /*
       3             :  * Local APIC related interfaces to support IOAPIC, MSI, etc.
       4             :  *
       5             :  * Copyright (C) 1997, 1998, 1999, 2000, 2009 Ingo Molnar, Hajnalka Szabo
       6             :  *      Moved from arch/x86/kernel/apic/io_apic.c.
       7             :  * Jiang Liu <jiang.liu@linux.intel.com>
       8             :  *      Enable support of hierarchical irqdomains
       9             :  */
      10             : #include <linux/interrupt.h>
      11             : #include <linux/irq.h>
      12             : #include <linux/seq_file.h>
      13             : #include <linux/init.h>
      14             : #include <linux/compiler.h>
      15             : #include <linux/slab.h>
      16             : #include <asm/irqdomain.h>
      17             : #include <asm/hw_irq.h>
      18             : #include <asm/traps.h>
      19             : #include <asm/apic.h>
      20             : #include <asm/i8259.h>
      21             : #include <asm/desc.h>
      22             : #include <asm/irq_remapping.h>
      23             : 
      24             : #include <asm/trace/irq_vectors.h>
      25             : 
      26             : struct apic_chip_data {
      27             :         struct irq_cfg          hw_irq_cfg;
      28             :         unsigned int            vector;
      29             :         unsigned int            prev_vector;
      30             :         unsigned int            cpu;
      31             :         unsigned int            prev_cpu;
      32             :         unsigned int            irq;
      33             :         struct hlist_node       clist;
      34             :         unsigned int            move_in_progress        : 1,
      35             :                                 is_managed              : 1,
      36             :                                 can_reserve             : 1,
      37             :                                 has_reserved            : 1;
      38             : };
      39             : 
      40             : struct irq_domain *x86_vector_domain;
      41             : EXPORT_SYMBOL_GPL(x86_vector_domain);
      42             : static DEFINE_RAW_SPINLOCK(vector_lock);
      43             : static cpumask_var_t vector_searchmask;
      44             : static struct irq_chip lapic_controller;
      45             : static struct irq_matrix *vector_matrix;
      46             : #ifdef CONFIG_SMP
      47             : static DEFINE_PER_CPU(struct hlist_head, cleanup_list);
      48             : #endif
      49             : 
      50           3 : void lock_vector_lock(void)
      51             : {
      52             :         /* Used to the online set of cpus does not change
      53             :          * during assign_irq_vector.
      54             :          */
      55           3 :         raw_spin_lock(&vector_lock);
      56           3 : }
      57             : 
      58           3 : void unlock_vector_lock(void)
      59             : {
      60           3 :         raw_spin_unlock(&vector_lock);
      61           3 : }
      62             : 
      63           0 : void init_irq_alloc_info(struct irq_alloc_info *info,
      64             :                          const struct cpumask *mask)
      65             : {
      66           0 :         memset(info, 0, sizeof(*info));
      67           0 :         info->mask = mask;
      68           0 : }
      69             : 
      70          15 : void copy_irq_alloc_info(struct irq_alloc_info *dst, struct irq_alloc_info *src)
      71             : {
      72          15 :         if (src)
      73           0 :                 *dst = *src;
      74             :         else
      75          15 :                 memset(dst, 0, sizeof(*dst));
      76          15 : }
      77             : 
      78        3814 : static struct apic_chip_data *apic_chip_data(struct irq_data *irqd)
      79             : {
      80        3814 :         if (!irqd)
      81             :                 return NULL;
      82             : 
      83        3830 :         while (irqd->parent_data)
      84             :                 irqd = irqd->parent_data;
      85             : 
      86          63 :         return irqd->chip_data;
      87             : }
      88             : 
      89        3751 : struct irq_cfg *irqd_cfg(struct irq_data *irqd)
      90             : {
      91           1 :         struct apic_chip_data *apicd = apic_chip_data(irqd);
      92             : 
      93        3751 :         return apicd ? &apicd->hw_irq_cfg : NULL;
      94             : }
      95             : EXPORT_SYMBOL_GPL(irqd_cfg);
      96             : 
      97          16 : struct irq_cfg *irq_cfg(unsigned int irq)
      98             : {
      99          16 :         return irqd_cfg(irq_get_irq_data(irq));
     100             : }
     101             : 
     102          15 : static struct apic_chip_data *alloc_apic_chip_data(int node)
     103             : {
     104          15 :         struct apic_chip_data *apicd;
     105             : 
     106          15 :         apicd = kzalloc_node(sizeof(*apicd), GFP_KERNEL, node);
     107          15 :         if (apicd)
     108          15 :                 INIT_HLIST_NODE(&apicd->clist);
     109          15 :         return apicd;
     110             : }
     111             : 
     112           0 : static void free_apic_chip_data(struct apic_chip_data *apicd)
     113             : {
     114           0 :         kfree(apicd);
     115           0 : }
     116             : 
     117          18 : static void apic_update_irq_cfg(struct irq_data *irqd, unsigned int vector,
     118             :                                 unsigned int cpu)
     119             : {
     120          18 :         struct apic_chip_data *apicd = apic_chip_data(irqd);
     121             : 
     122          54 :         lockdep_assert_held(&vector_lock);
     123             : 
     124          18 :         apicd->hw_irq_cfg.vector = vector;
     125          18 :         apicd->hw_irq_cfg.dest_apicid = apic->calc_dest_apicid(cpu);
     126          18 :         irq_data_update_effective_affinity(irqd, cpumask_of(cpu));
     127          18 :         trace_vector_config(irqd->irq, vector, cpu,
     128             :                             apicd->hw_irq_cfg.dest_apicid);
     129          18 : }
     130             : 
     131           3 : static void apic_update_vector(struct irq_data *irqd, unsigned int newvec,
     132             :                                unsigned int newcpu)
     133             : {
     134           3 :         struct apic_chip_data *apicd = apic_chip_data(irqd);
     135           3 :         struct irq_desc *desc = irq_data_to_desc(irqd);
     136           3 :         bool managed = irqd_affinity_is_managed(irqd);
     137             : 
     138           9 :         lockdep_assert_held(&vector_lock);
     139             : 
     140           3 :         trace_vector_update(irqd->irq, newvec, newcpu, apicd->vector,
     141             :                             apicd->cpu);
     142             : 
     143             :         /*
     144             :          * If there is no vector associated or if the associated vector is
     145             :          * the shutdown vector, which is associated to make PCI/MSI
     146             :          * shutdown mode work, then there is nothing to release. Clear out
     147             :          * prev_vector for this and the offlined target case.
     148             :          */
     149           3 :         apicd->prev_vector = 0;
     150           3 :         if (!apicd->vector || apicd->vector == MANAGED_IRQ_SHUTDOWN_VECTOR)
     151           3 :                 goto setnew;
     152             :         /*
     153             :          * If the target CPU of the previous vector is online, then mark
     154             :          * the vector as move in progress and store it for cleanup when the
     155             :          * first interrupt on the new vector arrives. If the target CPU is
     156             :          * offline then the regular release mechanism via the cleanup
     157             :          * vector is not possible and the vector can be immediately freed
     158             :          * in the underlying matrix allocator.
     159             :          */
     160           0 :         if (cpu_online(apicd->cpu)) {
     161           0 :                 apicd->move_in_progress = true;
     162           0 :                 apicd->prev_vector = apicd->vector;
     163           0 :                 apicd->prev_cpu = apicd->cpu;
     164           0 :                 WARN_ON_ONCE(apicd->cpu == newcpu);
     165             :         } else {
     166           0 :                 irq_matrix_free(vector_matrix, apicd->cpu, apicd->vector,
     167             :                                 managed);
     168             :         }
     169             : 
     170           3 : setnew:
     171           3 :         apicd->vector = newvec;
     172           3 :         apicd->cpu = newcpu;
     173           3 :         BUG_ON(!IS_ERR_OR_NULL(per_cpu(vector_irq, newcpu)[newvec]));
     174           3 :         per_cpu(vector_irq, newcpu)[newvec] = desc;
     175           3 : }
     176             : 
     177          15 : static void vector_assign_managed_shutdown(struct irq_data *irqd)
     178             : {
     179          15 :         unsigned int cpu = cpumask_first(cpu_online_mask);
     180             : 
     181          15 :         apic_update_irq_cfg(irqd, MANAGED_IRQ_SHUTDOWN_VECTOR, cpu);
     182          15 : }
     183             : 
     184           0 : static int reserve_managed_vector(struct irq_data *irqd)
     185             : {
     186           0 :         const struct cpumask *affmsk = irq_data_get_affinity_mask(irqd);
     187           0 :         struct apic_chip_data *apicd = apic_chip_data(irqd);
     188           0 :         unsigned long flags;
     189           0 :         int ret;
     190             : 
     191           0 :         raw_spin_lock_irqsave(&vector_lock, flags);
     192           0 :         apicd->is_managed = true;
     193           0 :         ret = irq_matrix_reserve_managed(vector_matrix, affmsk);
     194           0 :         raw_spin_unlock_irqrestore(&vector_lock, flags);
     195           0 :         trace_vector_reserve_managed(irqd->irq, ret);
     196           0 :         return ret;
     197             : }
     198             : 
     199          15 : static void reserve_irq_vector_locked(struct irq_data *irqd)
     200             : {
     201          15 :         struct apic_chip_data *apicd = apic_chip_data(irqd);
     202             : 
     203          15 :         irq_matrix_reserve(vector_matrix);
     204          15 :         apicd->can_reserve = true;
     205          15 :         apicd->has_reserved = true;
     206          15 :         irqd_set_can_reserve(irqd);
     207          15 :         trace_vector_reserve(irqd->irq, 0);
     208          15 :         vector_assign_managed_shutdown(irqd);
     209          15 : }
     210             : 
     211          15 : static int reserve_irq_vector(struct irq_data *irqd)
     212             : {
     213          15 :         unsigned long flags;
     214             : 
     215          15 :         raw_spin_lock_irqsave(&vector_lock, flags);
     216          15 :         reserve_irq_vector_locked(irqd);
     217          15 :         raw_spin_unlock_irqrestore(&vector_lock, flags);
     218          15 :         return 0;
     219             : }
     220             : 
     221             : static int
     222           6 : assign_vector_locked(struct irq_data *irqd, const struct cpumask *dest)
     223             : {
     224           6 :         struct apic_chip_data *apicd = apic_chip_data(irqd);
     225           6 :         bool resvd = apicd->has_reserved;
     226           6 :         unsigned int cpu = apicd->cpu;
     227           6 :         int vector = apicd->vector;
     228             : 
     229          18 :         lockdep_assert_held(&vector_lock);
     230             : 
     231             :         /*
     232             :          * If the current target CPU is online and in the new requested
     233             :          * affinity mask, there is no point in moving the interrupt from
     234             :          * one CPU to another.
     235             :          */
     236           6 :         if (vector && cpu_online(cpu) && cpumask_test_cpu(cpu, dest))
     237             :                 return 0;
     238             : 
     239             :         /*
     240             :          * Careful here. @apicd might either have move_in_progress set or
     241             :          * be enqueued for cleanup. Assigning a new vector would either
     242             :          * leave a stale vector on some CPU around or in case of a pending
     243             :          * cleanup corrupt the hlist.
     244             :          */
     245           3 :         if (apicd->move_in_progress || !hlist_unhashed(&apicd->clist))
     246             :                 return -EBUSY;
     247             : 
     248           3 :         vector = irq_matrix_alloc(vector_matrix, dest, resvd, &cpu);
     249           3 :         trace_vector_alloc(irqd->irq, vector, resvd, vector);
     250           3 :         if (vector < 0)
     251             :                 return vector;
     252           3 :         apic_update_vector(irqd, vector, cpu);
     253           3 :         apic_update_irq_cfg(irqd, vector, cpu);
     254             : 
     255           3 :         return 0;
     256             : }
     257             : 
     258           0 : static int assign_irq_vector(struct irq_data *irqd, const struct cpumask *dest)
     259             : {
     260           0 :         unsigned long flags;
     261           0 :         int ret;
     262             : 
     263           0 :         raw_spin_lock_irqsave(&vector_lock, flags);
     264           0 :         cpumask_and(vector_searchmask, dest, cpu_online_mask);
     265           0 :         ret = assign_vector_locked(irqd, vector_searchmask);
     266           0 :         raw_spin_unlock_irqrestore(&vector_lock, flags);
     267           0 :         return ret;
     268             : }
     269             : 
     270           3 : static int assign_irq_vector_any_locked(struct irq_data *irqd)
     271             : {
     272             :         /* Get the affinity mask - either irq_default_affinity or (user) set */
     273           3 :         const struct cpumask *affmsk = irq_data_get_affinity_mask(irqd);
     274           3 :         int node = irq_data_get_node(irqd);
     275             : 
     276           3 :         if (node != NUMA_NO_NODE) {
     277             :                 /* Try the intersection of @affmsk and node mask */
     278           3 :                 cpumask_and(vector_searchmask, cpumask_of_node(node), affmsk);
     279           3 :                 if (!assign_vector_locked(irqd, vector_searchmask))
     280             :                         return 0;
     281             :         }
     282             : 
     283             :         /* Try the full affinity mask */
     284           0 :         cpumask_and(vector_searchmask, affmsk, cpu_online_mask);
     285           0 :         if (!assign_vector_locked(irqd, vector_searchmask))
     286             :                 return 0;
     287             : 
     288           0 :         if (node != NUMA_NO_NODE) {
     289             :                 /* Try the node mask */
     290           0 :                 if (!assign_vector_locked(irqd, cpumask_of_node(node)))
     291             :                         return 0;
     292             :         }
     293             : 
     294             :         /* Try the full online mask */
     295           0 :         return assign_vector_locked(irqd, cpu_online_mask);
     296             : }
     297             : 
     298             : static int
     299          15 : assign_irq_vector_policy(struct irq_data *irqd, struct irq_alloc_info *info)
     300             : {
     301          15 :         if (irqd_affinity_is_managed(irqd))
     302           0 :                 return reserve_managed_vector(irqd);
     303          15 :         if (info->mask)
     304           0 :                 return assign_irq_vector(irqd, info->mask);
     305             :         /*
     306             :          * Make only a global reservation with no guarantee. A real vector
     307             :          * is associated at activation time.
     308             :          */
     309          15 :         return reserve_irq_vector(irqd);
     310             : }
     311             : 
     312             : static int
     313           0 : assign_managed_vector(struct irq_data *irqd, const struct cpumask *dest)
     314             : {
     315           0 :         const struct cpumask *affmsk = irq_data_get_affinity_mask(irqd);
     316           0 :         struct apic_chip_data *apicd = apic_chip_data(irqd);
     317           0 :         int vector, cpu;
     318             : 
     319           0 :         cpumask_and(vector_searchmask, dest, affmsk);
     320             : 
     321             :         /* set_affinity might call here for nothing */
     322           0 :         if (apicd->vector && cpumask_test_cpu(apicd->cpu, vector_searchmask))
     323             :                 return 0;
     324           0 :         vector = irq_matrix_alloc_managed(vector_matrix, vector_searchmask,
     325             :                                           &cpu);
     326           0 :         trace_vector_alloc_managed(irqd->irq, vector, vector);
     327           0 :         if (vector < 0)
     328             :                 return vector;
     329           0 :         apic_update_vector(irqd, vector, cpu);
     330           0 :         apic_update_irq_cfg(irqd, vector, cpu);
     331           0 :         return 0;
     332             : }
     333             : 
     334          15 : static void clear_irq_vector(struct irq_data *irqd)
     335             : {
     336          15 :         struct apic_chip_data *apicd = apic_chip_data(irqd);
     337          15 :         bool managed = irqd_affinity_is_managed(irqd);
     338          15 :         unsigned int vector = apicd->vector;
     339             : 
     340          45 :         lockdep_assert_held(&vector_lock);
     341             : 
     342          15 :         if (!vector)
     343             :                 return;
     344             : 
     345          15 :         trace_vector_clear(irqd->irq, vector, apicd->cpu, apicd->prev_vector,
     346             :                            apicd->prev_cpu);
     347             : 
     348          15 :         per_cpu(vector_irq, apicd->cpu)[vector] = VECTOR_SHUTDOWN;
     349          15 :         irq_matrix_free(vector_matrix, apicd->cpu, vector, managed);
     350          15 :         apicd->vector = 0;
     351             : 
     352             :         /* Clean up move in progress */
     353          15 :         vector = apicd->prev_vector;
     354          15 :         if (!vector)
     355             :                 return;
     356             : 
     357           0 :         per_cpu(vector_irq, apicd->prev_cpu)[vector] = VECTOR_SHUTDOWN;
     358           0 :         irq_matrix_free(vector_matrix, apicd->prev_cpu, vector, managed);
     359           0 :         apicd->prev_vector = 0;
     360           0 :         apicd->move_in_progress = 0;
     361           0 :         hlist_del_init(&apicd->clist);
     362             : }
     363             : 
     364           0 : static void x86_vector_deactivate(struct irq_domain *dom, struct irq_data *irqd)
     365             : {
     366           0 :         struct apic_chip_data *apicd = apic_chip_data(irqd);
     367           0 :         unsigned long flags;
     368             : 
     369           0 :         trace_vector_deactivate(irqd->irq, apicd->is_managed,
     370           0 :                                 apicd->can_reserve, false);
     371             : 
     372             :         /* Regular fixed assigned interrupt */
     373           0 :         if (!apicd->is_managed && !apicd->can_reserve)
     374             :                 return;
     375             :         /* If the interrupt has a global reservation, nothing to do */
     376           0 :         if (apicd->has_reserved)
     377             :                 return;
     378             : 
     379           0 :         raw_spin_lock_irqsave(&vector_lock, flags);
     380           0 :         clear_irq_vector(irqd);
     381           0 :         if (apicd->can_reserve)
     382           0 :                 reserve_irq_vector_locked(irqd);
     383             :         else
     384           0 :                 vector_assign_managed_shutdown(irqd);
     385           0 :         raw_spin_unlock_irqrestore(&vector_lock, flags);
     386             : }
     387             : 
     388           3 : static int activate_reserved(struct irq_data *irqd)
     389             : {
     390           3 :         struct apic_chip_data *apicd = apic_chip_data(irqd);
     391           3 :         int ret;
     392             : 
     393           3 :         ret = assign_irq_vector_any_locked(irqd);
     394           3 :         if (!ret) {
     395           3 :                 apicd->has_reserved = false;
     396             :                 /*
     397             :                  * Core might have disabled reservation mode after
     398             :                  * allocating the irq descriptor. Ideally this should
     399             :                  * happen before allocation time, but that would require
     400             :                  * completely convoluted ways of transporting that
     401             :                  * information.
     402             :                  */
     403           3 :                 if (!irqd_can_reserve(irqd))
     404           0 :                         apicd->can_reserve = false;
     405             :         }
     406             : 
     407             :         /*
     408             :          * Check to ensure that the effective affinity mask is a subset
     409             :          * the user supplied affinity mask, and warn the user if it is not
     410             :          */
     411           3 :         if (!cpumask_subset(irq_data_get_effective_affinity_mask(irqd),
     412           3 :                             irq_data_get_affinity_mask(irqd))) {
     413           0 :                 pr_warn("irq %u: Affinity broken due to vector space exhaustion.\n",
     414             :                         irqd->irq);
     415             :         }
     416             : 
     417           3 :         return ret;
     418             : }
     419             : 
     420           0 : static int activate_managed(struct irq_data *irqd)
     421             : {
     422           0 :         const struct cpumask *dest = irq_data_get_affinity_mask(irqd);
     423           0 :         int ret;
     424             : 
     425           0 :         cpumask_and(vector_searchmask, dest, cpu_online_mask);
     426           0 :         if (WARN_ON_ONCE(cpumask_empty(vector_searchmask))) {
     427             :                 /* Something in the core code broke! Survive gracefully */
     428           0 :                 pr_err("Managed startup for irq %u, but no CPU\n", irqd->irq);
     429           0 :                 return -EINVAL;
     430             :         }
     431             : 
     432           0 :         ret = assign_managed_vector(irqd, vector_searchmask);
     433             :         /*
     434             :          * This should not happen. The vector reservation got buggered.  Handle
     435             :          * it gracefully.
     436             :          */
     437           0 :         if (WARN_ON_ONCE(ret < 0)) {
     438           0 :                 pr_err("Managed startup irq %u, no vector available\n",
     439             :                        irqd->irq);
     440             :         }
     441             :         return ret;
     442             : }
     443             : 
     444           3 : static int x86_vector_activate(struct irq_domain *dom, struct irq_data *irqd,
     445             :                                bool reserve)
     446             : {
     447           3 :         struct apic_chip_data *apicd = apic_chip_data(irqd);
     448           3 :         unsigned long flags;
     449           3 :         int ret = 0;
     450             : 
     451           3 :         trace_vector_activate(irqd->irq, apicd->is_managed,
     452           3 :                               apicd->can_reserve, reserve);
     453             : 
     454           3 :         raw_spin_lock_irqsave(&vector_lock, flags);
     455           3 :         if (!apicd->can_reserve && !apicd->is_managed)
     456           0 :                 assign_irq_vector_any_locked(irqd);
     457           3 :         else if (reserve || irqd_is_managed_and_shutdown(irqd))
     458           0 :                 vector_assign_managed_shutdown(irqd);
     459           3 :         else if (apicd->is_managed)
     460           0 :                 ret = activate_managed(irqd);
     461           3 :         else if (apicd->has_reserved)
     462           3 :                 ret = activate_reserved(irqd);
     463           3 :         raw_spin_unlock_irqrestore(&vector_lock, flags);
     464           3 :         return ret;
     465             : }
     466             : 
     467           0 : static void vector_free_reserved_and_managed(struct irq_data *irqd)
     468             : {
     469           0 :         const struct cpumask *dest = irq_data_get_affinity_mask(irqd);
     470           0 :         struct apic_chip_data *apicd = apic_chip_data(irqd);
     471             : 
     472           0 :         trace_vector_teardown(irqd->irq, apicd->is_managed,
     473           0 :                               apicd->has_reserved);
     474             : 
     475           0 :         if (apicd->has_reserved)
     476           0 :                 irq_matrix_remove_reserved(vector_matrix);
     477           0 :         if (apicd->is_managed)
     478           0 :                 irq_matrix_remove_managed(vector_matrix, dest);
     479           0 : }
     480             : 
     481           0 : static void x86_vector_free_irqs(struct irq_domain *domain,
     482             :                                  unsigned int virq, unsigned int nr_irqs)
     483             : {
     484           0 :         struct apic_chip_data *apicd;
     485           0 :         struct irq_data *irqd;
     486           0 :         unsigned long flags;
     487           0 :         int i;
     488             : 
     489           0 :         for (i = 0; i < nr_irqs; i++) {
     490           0 :                 irqd = irq_domain_get_irq_data(x86_vector_domain, virq + i);
     491           0 :                 if (irqd && irqd->chip_data) {
     492           0 :                         raw_spin_lock_irqsave(&vector_lock, flags);
     493           0 :                         clear_irq_vector(irqd);
     494           0 :                         vector_free_reserved_and_managed(irqd);
     495           0 :                         apicd = irqd->chip_data;
     496           0 :                         irq_domain_reset_irq_data(irqd);
     497           0 :                         raw_spin_unlock_irqrestore(&vector_lock, flags);
     498           0 :                         free_apic_chip_data(apicd);
     499             :                 }
     500             :         }
     501           0 : }
     502             : 
     503          15 : static bool vector_configure_legacy(unsigned int virq, struct irq_data *irqd,
     504             :                                     struct apic_chip_data *apicd)
     505             : {
     506          15 :         unsigned long flags;
     507          15 :         bool realloc = false;
     508             : 
     509          15 :         apicd->vector = ISA_IRQ_VECTOR(virq);
     510          15 :         apicd->cpu = 0;
     511             : 
     512          15 :         raw_spin_lock_irqsave(&vector_lock, flags);
     513             :         /*
     514             :          * If the interrupt is activated, then it must stay at this vector
     515             :          * position. That's usually the timer interrupt (0).
     516             :          */
     517          15 :         if (irqd_is_activated(irqd)) {
     518           0 :                 trace_vector_setup(virq, true, 0);
     519           0 :                 apic_update_irq_cfg(irqd, apicd->vector, apicd->cpu);
     520             :         } else {
     521             :                 /* Release the vector */
     522          15 :                 apicd->can_reserve = true;
     523          15 :                 irqd_set_can_reserve(irqd);
     524          15 :                 clear_irq_vector(irqd);
     525          15 :                 realloc = true;
     526             :         }
     527          15 :         raw_spin_unlock_irqrestore(&vector_lock, flags);
     528          15 :         return realloc;
     529             : }
     530             : 
     531          15 : static int x86_vector_alloc_irqs(struct irq_domain *domain, unsigned int virq,
     532             :                                  unsigned int nr_irqs, void *arg)
     533             : {
     534          15 :         struct irq_alloc_info *info = arg;
     535          15 :         struct apic_chip_data *apicd;
     536          15 :         struct irq_data *irqd;
     537          15 :         int i, err, node;
     538             : 
     539          15 :         if (disable_apic)
     540             :                 return -ENXIO;
     541             : 
     542             :         /* Currently vector allocator can't guarantee contiguous allocations */
     543          15 :         if ((info->flags & X86_IRQ_ALLOC_CONTIGUOUS_VECTORS) && nr_irqs > 1)
     544             :                 return -ENOSYS;
     545             : 
     546          30 :         for (i = 0; i < nr_irqs; i++) {
     547          15 :                 irqd = irq_domain_get_irq_data(domain, virq + i);
     548          15 :                 BUG_ON(!irqd);
     549          15 :                 node = irq_data_get_node(irqd);
     550          15 :                 WARN_ON_ONCE(irqd->chip_data);
     551          15 :                 apicd = alloc_apic_chip_data(node);
     552          15 :                 if (!apicd) {
     553           0 :                         err = -ENOMEM;
     554           0 :                         goto error;
     555             :                 }
     556             : 
     557          15 :                 apicd->irq = virq + i;
     558          15 :                 irqd->chip = &lapic_controller;
     559          15 :                 irqd->chip_data = apicd;
     560          15 :                 irqd->hwirq = virq + i;
     561          15 :                 irqd_set_single_target(irqd);
     562             :                 /*
     563             :                  * Prevent that any of these interrupts is invoked in
     564             :                  * non interrupt context via e.g. generic_handle_irq()
     565             :                  * as that can corrupt the affinity move state.
     566             :                  */
     567          15 :                 irqd_set_handle_enforce_irqctx(irqd);
     568             : 
     569             :                 /* Don't invoke affinity setter on deactivated interrupts */
     570          15 :                 irqd_set_affinity_on_activate(irqd);
     571             : 
     572             :                 /*
     573             :                  * Legacy vectors are already assigned when the IOAPIC
     574             :                  * takes them over. They stay on the same vector. This is
     575             :                  * required for check_timer() to work correctly as it might
     576             :                  * switch back to legacy mode. Only update the hardware
     577             :                  * config.
     578             :                  */
     579          15 :                 if (info->flags & X86_IRQ_ALLOC_LEGACY) {
     580          15 :                         if (!vector_configure_legacy(virq + i, irqd, apicd))
     581           0 :                                 continue;
     582             :                 }
     583             : 
     584          15 :                 err = assign_irq_vector_policy(irqd, info);
     585          15 :                 trace_vector_setup(virq + i, false, err);
     586          15 :                 if (err) {
     587           0 :                         irqd->chip_data = NULL;
     588           0 :                         free_apic_chip_data(apicd);
     589           0 :                         goto error;
     590             :                 }
     591             :         }
     592             : 
     593             :         return 0;
     594             : 
     595           0 : error:
     596           0 :         x86_vector_free_irqs(domain, virq, i);
     597           0 :         return err;
     598             : }
     599             : 
     600             : #ifdef CONFIG_GENERIC_IRQ_DEBUGFS
     601             : static void x86_vector_debug_show(struct seq_file *m, struct irq_domain *d,
     602             :                                   struct irq_data *irqd, int ind)
     603             : {
     604             :         struct apic_chip_data apicd;
     605             :         unsigned long flags;
     606             :         int irq;
     607             : 
     608             :         if (!irqd) {
     609             :                 irq_matrix_debug_show(m, vector_matrix, ind);
     610             :                 return;
     611             :         }
     612             : 
     613             :         irq = irqd->irq;
     614             :         if (irq < nr_legacy_irqs() && !test_bit(irq, &io_apic_irqs)) {
     615             :                 seq_printf(m, "%*sVector: %5d\n", ind, "", ISA_IRQ_VECTOR(irq));
     616             :                 seq_printf(m, "%*sTarget: Legacy PIC all CPUs\n", ind, "");
     617             :                 return;
     618             :         }
     619             : 
     620             :         if (!irqd->chip_data) {
     621             :                 seq_printf(m, "%*sVector: Not assigned\n", ind, "");
     622             :                 return;
     623             :         }
     624             : 
     625             :         raw_spin_lock_irqsave(&vector_lock, flags);
     626             :         memcpy(&apicd, irqd->chip_data, sizeof(apicd));
     627             :         raw_spin_unlock_irqrestore(&vector_lock, flags);
     628             : 
     629             :         seq_printf(m, "%*sVector: %5u\n", ind, "", apicd.vector);
     630             :         seq_printf(m, "%*sTarget: %5u\n", ind, "", apicd.cpu);
     631             :         if (apicd.prev_vector) {
     632             :                 seq_printf(m, "%*sPrevious vector: %5u\n", ind, "", apicd.prev_vector);
     633             :                 seq_printf(m, "%*sPrevious target: %5u\n", ind, "", apicd.prev_cpu);
     634             :         }
     635             :         seq_printf(m, "%*smove_in_progress: %u\n", ind, "", apicd.move_in_progress ? 1 : 0);
     636             :         seq_printf(m, "%*sis_managed:       %u\n", ind, "", apicd.is_managed ? 1 : 0);
     637             :         seq_printf(m, "%*scan_reserve:      %u\n", ind, "", apicd.can_reserve ? 1 : 0);
     638             :         seq_printf(m, "%*shas_reserved:     %u\n", ind, "", apicd.has_reserved ? 1 : 0);
     639             :         seq_printf(m, "%*scleanup_pending:  %u\n", ind, "", !hlist_unhashed(&apicd.clist));
     640             : }
     641             : #endif
     642             : 
     643           1 : int x86_fwspec_is_ioapic(struct irq_fwspec *fwspec)
     644             : {
     645           1 :         if (fwspec->param_count != 1)
     646             :                 return 0;
     647             : 
     648           2 :         if (is_fwnode_irqchip(fwspec->fwnode)) {
     649           1 :                 const char *fwname = fwnode_get_name(fwspec->fwnode);
     650           1 :                 return fwname && !strncmp(fwname, "IO-APIC-", 8) &&
     651           1 :                         simple_strtol(fwname+8, NULL, 10) == fwspec->param[0];
     652             :         }
     653           1 :         return to_of_node(fwspec->fwnode) &&
     654             :                 of_device_is_compatible(to_of_node(fwspec->fwnode),
     655             :                                         "intel,ce4100-ioapic");
     656             : }
     657             : 
     658           0 : int x86_fwspec_is_hpet(struct irq_fwspec *fwspec)
     659             : {
     660           0 :         if (fwspec->param_count != 1)
     661             :                 return 0;
     662             : 
     663           0 :         if (is_fwnode_irqchip(fwspec->fwnode)) {
     664           0 :                 const char *fwname = fwnode_get_name(fwspec->fwnode);
     665           0 :                 return fwname && !strncmp(fwname, "HPET-MSI-", 9) &&
     666           0 :                         simple_strtol(fwname+9, NULL, 10) == fwspec->param[0];
     667             :         }
     668             :         return 0;
     669             : }
     670             : 
     671           1 : static int x86_vector_select(struct irq_domain *d, struct irq_fwspec *fwspec,
     672             :                              enum irq_domain_bus_token bus_token)
     673             : {
     674             :         /*
     675             :          * HPET and I/OAPIC cannot be parented in the vector domain
     676             :          * if IRQ remapping is enabled. APIC IDs above 15 bits are
     677             :          * only permitted if IRQ remapping is enabled, so check that.
     678             :          */
     679           1 :         if (apic->apic_id_valid(32768))
     680             :                 return 0;
     681             : 
     682           1 :         return x86_fwspec_is_ioapic(fwspec) || x86_fwspec_is_hpet(fwspec);
     683             : }
     684             : 
     685             : static const struct irq_domain_ops x86_vector_domain_ops = {
     686             :         .select         = x86_vector_select,
     687             :         .alloc          = x86_vector_alloc_irqs,
     688             :         .free           = x86_vector_free_irqs,
     689             :         .activate       = x86_vector_activate,
     690             :         .deactivate     = x86_vector_deactivate,
     691             : #ifdef CONFIG_GENERIC_IRQ_DEBUGFS
     692             :         .debug_show     = x86_vector_debug_show,
     693             : #endif
     694             : };
     695             : 
     696           1 : int __init arch_probe_nr_irqs(void)
     697             : {
     698           1 :         int nr;
     699             : 
     700           1 :         if (nr_irqs > (NR_VECTORS * nr_cpu_ids))
     701           1 :                 nr_irqs = NR_VECTORS * nr_cpu_ids;
     702             : 
     703           1 :         nr = (gsi_top + nr_legacy_irqs()) + 8 * nr_cpu_ids;
     704             : #if defined(CONFIG_PCI_MSI)
     705             :         /*
     706             :          * for MSI and HT dyn irq
     707             :          */
     708             :         if (gsi_top <= NR_IRQS_LEGACY)
     709             :                 nr +=  8 * nr_cpu_ids;
     710             :         else
     711             :                 nr += gsi_top * 16;
     712             : #endif
     713           1 :         if (nr < nr_irqs)
     714           1 :                 nr_irqs = nr;
     715             : 
     716             :         /*
     717             :          * We don't know if PIC is present at this point so we need to do
     718             :          * probe() to get the right number of legacy IRQs.
     719             :          */
     720           1 :         return legacy_pic->probe();
     721             : }
     722             : 
     723           1 : void lapic_assign_legacy_vector(unsigned int irq, bool replace)
     724             : {
     725             :         /*
     726             :          * Use assign system here so it wont get accounted as allocated
     727             :          * and moveable in the cpu hotplug check and it prevents managed
     728             :          * irq reservation from touching it.
     729             :          */
     730           0 :         irq_matrix_assign_system(vector_matrix, ISA_IRQ_VECTOR(irq), replace);
     731           1 : }
     732             : 
     733           1 : void __init lapic_assign_system_vectors(void)
     734             : {
     735           1 :         unsigned int i, vector = 0;
     736             : 
     737          34 :         for_each_set_bit_from(vector, system_vectors, NR_VECTORS)
     738          33 :                 irq_matrix_assign_system(vector_matrix, vector, false);
     739             : 
     740           1 :         if (nr_legacy_irqs() > 1)
     741           1 :                 lapic_assign_legacy_vector(PIC_CASCADE_IR, false);
     742             : 
     743             :         /* System vectors are reserved, online it */
     744           1 :         irq_matrix_online(vector_matrix);
     745             : 
     746             :         /* Mark the preallocated legacy interrupts */
     747          18 :         for (i = 0; i < nr_legacy_irqs(); i++) {
     748          16 :                 if (i != PIC_CASCADE_IR)
     749          15 :                         irq_matrix_assign(vector_matrix, ISA_IRQ_VECTOR(i));
     750             :         }
     751           1 : }
     752             : 
     753           1 : int __init arch_early_irq_init(void)
     754             : {
     755           1 :         struct fwnode_handle *fn;
     756             : 
     757           1 :         fn = irq_domain_alloc_named_fwnode("VECTOR");
     758           1 :         BUG_ON(!fn);
     759           1 :         x86_vector_domain = irq_domain_create_tree(fn, &x86_vector_domain_ops,
     760             :                                                    NULL);
     761           1 :         BUG_ON(x86_vector_domain == NULL);
     762           1 :         irq_set_default_host(x86_vector_domain);
     763             : 
     764           1 :         BUG_ON(!alloc_cpumask_var(&vector_searchmask, GFP_KERNEL));
     765             : 
     766             :         /*
     767             :          * Allocate the vector matrix allocator data structure and limit the
     768             :          * search area.
     769             :          */
     770           1 :         vector_matrix = irq_alloc_matrix(NR_VECTORS, FIRST_EXTERNAL_VECTOR,
     771             :                                          FIRST_SYSTEM_VECTOR);
     772           1 :         BUG_ON(!vector_matrix);
     773             : 
     774           1 :         return arch_early_ioapic_init();
     775             : }
     776             : 
     777             : #ifdef CONFIG_SMP
     778             : 
     779         768 : static struct irq_desc *__setup_vector_irq(int vector)
     780             : {
     781         768 :         int isairq = vector - ISA_IRQ_VECTOR(0);
     782             : 
     783             :         /* Check whether the irq is in the legacy space */
     784         768 :         if (isairq < 0 || isairq >= nr_legacy_irqs())
     785             :                 return VECTOR_UNUSED;
     786             :         /* Check whether the irq is handled by the IOAPIC */
     787          48 :         if (test_bit(isairq, &io_apic_irqs))
     788             :                 return VECTOR_UNUSED;
     789           3 :         return irq_to_desc(isairq);
     790             : }
     791             : 
     792             : /* Online the local APIC infrastructure and initialize the vectors */
     793           3 : void lapic_online(void)
     794             : {
     795           3 :         unsigned int vector;
     796             : 
     797           9 :         lockdep_assert_held(&vector_lock);
     798             : 
     799             :         /* Online the vector matrix array for this CPU */
     800           3 :         irq_matrix_online(vector_matrix);
     801             : 
     802             :         /*
     803             :          * The interrupt affinity logic never targets interrupts to offline
     804             :          * CPUs. The exception are the legacy PIC interrupts. In general
     805             :          * they are only targeted to CPU0, but depending on the platform
     806             :          * they can be distributed to any online CPU in hardware. The
     807             :          * kernel has no influence on that. So all active legacy vectors
     808             :          * must be installed on all CPUs. All non legacy interrupts can be
     809             :          * cleared.
     810             :          */
     811         774 :         for (vector = 0; vector < NR_VECTORS; vector++)
     812         768 :                 this_cpu_write(vector_irq[vector], __setup_vector_irq(vector));
     813           3 : }
     814             : 
     815           0 : void lapic_offline(void)
     816             : {
     817           0 :         lock_vector_lock();
     818           0 :         irq_matrix_offline(vector_matrix);
     819           0 :         unlock_vector_lock();
     820           0 : }
     821             : 
     822           3 : static int apic_set_affinity(struct irq_data *irqd,
     823             :                              const struct cpumask *dest, bool force)
     824             : {
     825           3 :         int err;
     826             : 
     827           3 :         if (WARN_ON_ONCE(!irqd_is_activated(irqd)))
     828             :                 return -EIO;
     829             : 
     830           3 :         raw_spin_lock(&vector_lock);
     831           3 :         cpumask_and(vector_searchmask, dest, cpu_online_mask);
     832           3 :         if (irqd_affinity_is_managed(irqd))
     833           0 :                 err = assign_managed_vector(irqd, vector_searchmask);
     834             :         else
     835           3 :                 err = assign_vector_locked(irqd, vector_searchmask);
     836           3 :         raw_spin_unlock(&vector_lock);
     837           3 :         return err ? err : IRQ_SET_MASK_OK;
     838             : }
     839             : 
     840             : #else
     841             : # define apic_set_affinity      NULL
     842             : #endif
     843             : 
     844           0 : static int apic_retrigger_irq(struct irq_data *irqd)
     845             : {
     846           0 :         struct apic_chip_data *apicd = apic_chip_data(irqd);
     847           0 :         unsigned long flags;
     848             : 
     849           0 :         raw_spin_lock_irqsave(&vector_lock, flags);
     850           0 :         apic->send_IPI(apicd->cpu, apicd->vector);
     851           0 :         raw_spin_unlock_irqrestore(&vector_lock, flags);
     852             : 
     853           0 :         return 1;
     854             : }
     855             : 
     856        3728 : void apic_ack_irq(struct irq_data *irqd)
     857             : {
     858        3728 :         irq_move_irq(irqd);
     859        3728 :         ack_APIC_irq();
     860        3728 : }
     861             : 
     862        3728 : void apic_ack_edge(struct irq_data *irqd)
     863             : {
     864        7456 :         irq_complete_move(irqd_cfg(irqd));
     865        3728 :         apic_ack_irq(irqd);
     866        3728 : }
     867             : 
     868           6 : static void x86_vector_msi_compose_msg(struct irq_data *data,
     869             :                                        struct msi_msg *msg)
     870             : {
     871          12 :        __irq_msi_compose_msg(irqd_cfg(data), msg, false);
     872           6 : }
     873             : 
     874             : static struct irq_chip lapic_controller = {
     875             :         .name                   = "APIC",
     876             :         .irq_ack                = apic_ack_edge,
     877             :         .irq_set_affinity       = apic_set_affinity,
     878             :         .irq_compose_msi_msg    = x86_vector_msi_compose_msg,
     879             :         .irq_retrigger          = apic_retrigger_irq,
     880             : };
     881             : 
     882             : #ifdef CONFIG_SMP
     883             : 
     884           0 : static void free_moved_vector(struct apic_chip_data *apicd)
     885             : {
     886           0 :         unsigned int vector = apicd->prev_vector;
     887           0 :         unsigned int cpu = apicd->prev_cpu;
     888           0 :         bool managed = apicd->is_managed;
     889             : 
     890             :         /*
     891             :          * Managed interrupts are usually not migrated away
     892             :          * from an online CPU, but CPU isolation 'managed_irq'
     893             :          * can make that happen.
     894             :          * 1) Activation does not take the isolation into account
     895             :          *    to keep the code simple
     896             :          * 2) Migration away from an isolated CPU can happen when
     897             :          *    a non-isolated CPU which is in the calculated
     898             :          *    affinity mask comes online.
     899             :          */
     900           0 :         trace_vector_free_moved(apicd->irq, cpu, vector, managed);
     901           0 :         irq_matrix_free(vector_matrix, cpu, vector, managed);
     902           0 :         per_cpu(vector_irq, cpu)[vector] = VECTOR_UNUSED;
     903           0 :         hlist_del_init(&apicd->clist);
     904           0 :         apicd->prev_vector = 0;
     905           0 :         apicd->move_in_progress = 0;
     906           0 : }
     907             : 
     908           0 : DEFINE_IDTENTRY_SYSVEC(sysvec_irq_move_cleanup)
     909             : {
     910           0 :         struct hlist_head *clhead = this_cpu_ptr(&cleanup_list);
     911           0 :         struct apic_chip_data *apicd;
     912           0 :         struct hlist_node *tmp;
     913             : 
     914           0 :         ack_APIC_irq();
     915             :         /* Prevent vectors vanishing under us */
     916           0 :         raw_spin_lock(&vector_lock);
     917             : 
     918           0 :         hlist_for_each_entry_safe(apicd, tmp, clhead, clist) {
     919           0 :                 unsigned int irr, vector = apicd->prev_vector;
     920             : 
     921             :                 /*
     922             :                  * Paranoia: Check if the vector that needs to be cleaned
     923             :                  * up is registered at the APICs IRR. If so, then this is
     924             :                  * not the best time to clean it up. Clean it up in the
     925             :                  * next attempt by sending another IRQ_MOVE_CLEANUP_VECTOR
     926             :                  * to this CPU. IRQ_MOVE_CLEANUP_VECTOR is the lowest
     927             :                  * priority external vector, so on return from this
     928             :                  * interrupt the device interrupt will happen first.
     929             :                  */
     930           0 :                 irr = apic_read(APIC_IRR + (vector / 32 * 0x10));
     931           0 :                 if (irr & (1U << (vector % 32))) {
     932           0 :                         apic->send_IPI_self(IRQ_MOVE_CLEANUP_VECTOR);
     933           0 :                         continue;
     934             :                 }
     935           0 :                 free_moved_vector(apicd);
     936             :         }
     937             : 
     938           0 :         raw_spin_unlock(&vector_lock);
     939           0 : }
     940             : 
     941           0 : static void __send_cleanup_vector(struct apic_chip_data *apicd)
     942             : {
     943           0 :         unsigned int cpu;
     944             : 
     945           0 :         raw_spin_lock(&vector_lock);
     946           0 :         apicd->move_in_progress = 0;
     947           0 :         cpu = apicd->prev_cpu;
     948           0 :         if (cpu_online(cpu)) {
     949           0 :                 hlist_add_head(&apicd->clist, per_cpu_ptr(&cleanup_list, cpu));
     950           0 :                 apic->send_IPI(cpu, IRQ_MOVE_CLEANUP_VECTOR);
     951             :         } else {
     952           0 :                 apicd->prev_vector = 0;
     953             :         }
     954           0 :         raw_spin_unlock(&vector_lock);
     955           0 : }
     956             : 
     957           0 : void send_cleanup_vector(struct irq_cfg *cfg)
     958             : {
     959           0 :         struct apic_chip_data *apicd;
     960             : 
     961           0 :         apicd = container_of(cfg, struct apic_chip_data, hw_irq_cfg);
     962           0 :         if (apicd->move_in_progress)
     963           0 :                 __send_cleanup_vector(apicd);
     964           0 : }
     965             : 
     966        3728 : void irq_complete_move(struct irq_cfg *cfg)
     967             : {
     968        3728 :         struct apic_chip_data *apicd;
     969             : 
     970        3728 :         apicd = container_of(cfg, struct apic_chip_data, hw_irq_cfg);
     971        3728 :         if (likely(!apicd->move_in_progress))
     972             :                 return;
     973             : 
     974             :         /*
     975             :          * If the interrupt arrived on the new target CPU, cleanup the
     976             :          * vector on the old target CPU. A vector check is not required
     977             :          * because an interrupt can never move from one vector to another
     978             :          * on the same CPU.
     979             :          */
     980           0 :         if (apicd->cpu == smp_processor_id())
     981           0 :                 __send_cleanup_vector(apicd);
     982             : }
     983             : 
     984             : /*
     985             :  * Called from fixup_irqs() with @desc->lock held and interrupts disabled.
     986             :  */
     987           0 : void irq_force_complete_move(struct irq_desc *desc)
     988             : {
     989           0 :         struct apic_chip_data *apicd;
     990           0 :         struct irq_data *irqd;
     991           0 :         unsigned int vector;
     992             : 
     993             :         /*
     994             :          * The function is called for all descriptors regardless of which
     995             :          * irqdomain they belong to. For example if an IRQ is provided by
     996             :          * an irq_chip as part of a GPIO driver, the chip data for that
     997             :          * descriptor is specific to the irq_chip in question.
     998             :          *
     999             :          * Check first that the chip_data is what we expect
    1000             :          * (apic_chip_data) before touching it any further.
    1001             :          */
    1002           0 :         irqd = irq_domain_get_irq_data(x86_vector_domain,
    1003             :                                        irq_desc_get_irq(desc));
    1004           0 :         if (!irqd)
    1005             :                 return;
    1006             : 
    1007           0 :         raw_spin_lock(&vector_lock);
    1008           0 :         apicd = apic_chip_data(irqd);
    1009           0 :         if (!apicd)
    1010           0 :                 goto unlock;
    1011             : 
    1012             :         /*
    1013             :          * If prev_vector is empty, no action required.
    1014             :          */
    1015           0 :         vector = apicd->prev_vector;
    1016           0 :         if (!vector)
    1017           0 :                 goto unlock;
    1018             : 
    1019             :         /*
    1020             :          * This is tricky. If the cleanup of the old vector has not been
    1021             :          * done yet, then the following setaffinity call will fail with
    1022             :          * -EBUSY. This can leave the interrupt in a stale state.
    1023             :          *
    1024             :          * All CPUs are stuck in stop machine with interrupts disabled so
    1025             :          * calling __irq_complete_move() would be completely pointless.
    1026             :          *
    1027             :          * 1) The interrupt is in move_in_progress state. That means that we
    1028             :          *    have not seen an interrupt since the io_apic was reprogrammed to
    1029             :          *    the new vector.
    1030             :          *
    1031             :          * 2) The interrupt has fired on the new vector, but the cleanup IPIs
    1032             :          *    have not been processed yet.
    1033             :          */
    1034           0 :         if (apicd->move_in_progress) {
    1035             :                 /*
    1036             :                  * In theory there is a race:
    1037             :                  *
    1038             :                  * set_ioapic(new_vector) <-- Interrupt is raised before update
    1039             :                  *                            is effective, i.e. it's raised on
    1040             :                  *                            the old vector.
    1041             :                  *
    1042             :                  * So if the target cpu cannot handle that interrupt before
    1043             :                  * the old vector is cleaned up, we get a spurious interrupt
    1044             :                  * and in the worst case the ioapic irq line becomes stale.
    1045             :                  *
    1046             :                  * But in case of cpu hotplug this should be a non issue
    1047             :                  * because if the affinity update happens right before all
    1048             :                  * cpus rendevouz in stop machine, there is no way that the
    1049             :                  * interrupt can be blocked on the target cpu because all cpus
    1050             :                  * loops first with interrupts enabled in stop machine, so the
    1051             :                  * old vector is not yet cleaned up when the interrupt fires.
    1052             :                  *
    1053             :                  * So the only way to run into this issue is if the delivery
    1054             :                  * of the interrupt on the apic/system bus would be delayed
    1055             :                  * beyond the point where the target cpu disables interrupts
    1056             :                  * in stop machine. I doubt that it can happen, but at least
    1057             :                  * there is a theroretical chance. Virtualization might be
    1058             :                  * able to expose this, but AFAICT the IOAPIC emulation is not
    1059             :                  * as stupid as the real hardware.
    1060             :                  *
    1061             :                  * Anyway, there is nothing we can do about that at this point
    1062             :                  * w/o refactoring the whole fixup_irq() business completely.
    1063             :                  * We print at least the irq number and the old vector number,
    1064             :                  * so we have the necessary information when a problem in that
    1065             :                  * area arises.
    1066             :                  */
    1067           0 :                 pr_warn("IRQ fixup: irq %d move in progress, old vector %d\n",
    1068             :                         irqd->irq, vector);
    1069             :         }
    1070           0 :         free_moved_vector(apicd);
    1071           0 : unlock:
    1072           0 :         raw_spin_unlock(&vector_lock);
    1073             : }
    1074             : 
    1075             : #ifdef CONFIG_HOTPLUG_CPU
    1076             : /*
    1077             :  * Note, this is not accurate accounting, but at least good enough to
    1078             :  * prevent that the actual interrupt move will run out of vectors.
    1079             :  */
    1080           0 : int lapic_can_unplug_cpu(void)
    1081             : {
    1082           0 :         unsigned int rsvd, avl, tomove, cpu = smp_processor_id();
    1083           0 :         int ret = 0;
    1084             : 
    1085           0 :         raw_spin_lock(&vector_lock);
    1086           0 :         tomove = irq_matrix_allocated(vector_matrix);
    1087           0 :         avl = irq_matrix_available(vector_matrix, true);
    1088           0 :         if (avl < tomove) {
    1089           0 :                 pr_warn("CPU %u has %u vectors, %u available. Cannot disable CPU\n",
    1090             :                         cpu, tomove, avl);
    1091           0 :                 ret = -ENOSPC;
    1092           0 :                 goto out;
    1093             :         }
    1094           0 :         rsvd = irq_matrix_reserved(vector_matrix);
    1095           0 :         if (avl < rsvd) {
    1096           0 :                 pr_warn("Reserved vectors %u > available %u. IRQ request may fail\n",
    1097             :                         rsvd, avl);
    1098             :         }
    1099           0 : out:
    1100           0 :         raw_spin_unlock(&vector_lock);
    1101           0 :         return ret;
    1102             : }
    1103             : #endif /* HOTPLUG_CPU */
    1104             : #endif /* SMP */
    1105             : 
    1106           0 : static void __init print_APIC_field(int base)
    1107             : {
    1108           0 :         int i;
    1109             : 
    1110           0 :         printk(KERN_DEBUG);
    1111             : 
    1112           0 :         for (i = 0; i < 8; i++)
    1113           0 :                 pr_cont("%08x", apic_read(base + i*0x10));
    1114             : 
    1115           0 :         pr_cont("\n");
    1116           0 : }
    1117             : 
    1118           0 : static void __init print_local_APIC(void *dummy)
    1119             : {
    1120           0 :         unsigned int i, v, ver, maxlvt;
    1121           0 :         u64 icr;
    1122             : 
    1123           0 :         pr_debug("printing local APIC contents on CPU#%d/%d:\n",
    1124             :                  smp_processor_id(), hard_smp_processor_id());
    1125           0 :         v = apic_read(APIC_ID);
    1126           0 :         pr_info("... APIC ID:      %08x (%01x)\n", v, read_apic_id());
    1127           0 :         v = apic_read(APIC_LVR);
    1128           0 :         pr_info("... APIC VERSION: %08x\n", v);
    1129           0 :         ver = GET_APIC_VERSION(v);
    1130           0 :         maxlvt = lapic_get_maxlvt();
    1131             : 
    1132           0 :         v = apic_read(APIC_TASKPRI);
    1133           0 :         pr_debug("... APIC TASKPRI: %08x (%02x)\n", v, v & APIC_TPRI_MASK);
    1134             : 
    1135             :         /* !82489DX */
    1136           0 :         if (APIC_INTEGRATED(ver)) {
    1137           0 :                 if (!APIC_XAPIC(ver)) {
    1138           0 :                         v = apic_read(APIC_ARBPRI);
    1139           0 :                         pr_debug("... APIC ARBPRI: %08x (%02x)\n",
    1140             :                                  v, v & APIC_ARBPRI_MASK);
    1141             :                 }
    1142           0 :                 v = apic_read(APIC_PROCPRI);
    1143           0 :                 pr_debug("... APIC PROCPRI: %08x\n", v);
    1144             :         }
    1145             : 
    1146             :         /*
    1147             :          * Remote read supported only in the 82489DX and local APIC for
    1148             :          * Pentium processors.
    1149             :          */
    1150           0 :         if (!APIC_INTEGRATED(ver) || maxlvt == 3) {
    1151           0 :                 v = apic_read(APIC_RRR);
    1152           0 :                 pr_debug("... APIC RRR: %08x\n", v);
    1153             :         }
    1154             : 
    1155           0 :         v = apic_read(APIC_LDR);
    1156           0 :         pr_debug("... APIC LDR: %08x\n", v);
    1157           0 :         if (!x2apic_enabled()) {
    1158           0 :                 v = apic_read(APIC_DFR);
    1159           0 :                 pr_debug("... APIC DFR: %08x\n", v);
    1160             :         }
    1161           0 :         v = apic_read(APIC_SPIV);
    1162           0 :         pr_debug("... APIC SPIV: %08x\n", v);
    1163             : 
    1164           0 :         pr_debug("... APIC ISR field:\n");
    1165           0 :         print_APIC_field(APIC_ISR);
    1166           0 :         pr_debug("... APIC TMR field:\n");
    1167           0 :         print_APIC_field(APIC_TMR);
    1168           0 :         pr_debug("... APIC IRR field:\n");
    1169           0 :         print_APIC_field(APIC_IRR);
    1170             : 
    1171             :         /* !82489DX */
    1172           0 :         if (APIC_INTEGRATED(ver)) {
    1173             :                 /* Due to the Pentium erratum 3AP. */
    1174           0 :                 if (maxlvt > 3)
    1175           0 :                         apic_write(APIC_ESR, 0);
    1176             : 
    1177           0 :                 v = apic_read(APIC_ESR);
    1178           0 :                 pr_debug("... APIC ESR: %08x\n", v);
    1179             :         }
    1180             : 
    1181           0 :         icr = apic_icr_read();
    1182           0 :         pr_debug("... APIC ICR: %08x\n", (u32)icr);
    1183           0 :         pr_debug("... APIC ICR2: %08x\n", (u32)(icr >> 32));
    1184             : 
    1185           0 :         v = apic_read(APIC_LVTT);
    1186           0 :         pr_debug("... APIC LVTT: %08x\n", v);
    1187             : 
    1188           0 :         if (maxlvt > 3) {
    1189             :                 /* PC is LVT#4. */
    1190           0 :                 v = apic_read(APIC_LVTPC);
    1191           0 :                 pr_debug("... APIC LVTPC: %08x\n", v);
    1192             :         }
    1193           0 :         v = apic_read(APIC_LVT0);
    1194           0 :         pr_debug("... APIC LVT0: %08x\n", v);
    1195           0 :         v = apic_read(APIC_LVT1);
    1196           0 :         pr_debug("... APIC LVT1: %08x\n", v);
    1197             : 
    1198           0 :         if (maxlvt > 2) {
    1199             :                 /* ERR is LVT#3. */
    1200           0 :                 v = apic_read(APIC_LVTERR);
    1201           0 :                 pr_debug("... APIC LVTERR: %08x\n", v);
    1202             :         }
    1203             : 
    1204           0 :         v = apic_read(APIC_TMICT);
    1205           0 :         pr_debug("... APIC TMICT: %08x\n", v);
    1206           0 :         v = apic_read(APIC_TMCCT);
    1207           0 :         pr_debug("... APIC TMCCT: %08x\n", v);
    1208           0 :         v = apic_read(APIC_TDCR);
    1209           0 :         pr_debug("... APIC TDCR: %08x\n", v);
    1210             : 
    1211           0 :         if (boot_cpu_has(X86_FEATURE_EXTAPIC)) {
    1212           0 :                 v = apic_read(APIC_EFEAT);
    1213           0 :                 maxlvt = (v >> 16) & 0xff;
    1214           0 :                 pr_debug("... APIC EFEAT: %08x\n", v);
    1215           0 :                 v = apic_read(APIC_ECTRL);
    1216           0 :                 pr_debug("... APIC ECTRL: %08x\n", v);
    1217           0 :                 for (i = 0; i < maxlvt; i++) {
    1218           0 :                         v = apic_read(APIC_EILVTn(i));
    1219           0 :                         pr_debug("... APIC EILVT%d: %08x\n", i, v);
    1220             :                 }
    1221             :         }
    1222           0 :         pr_cont("\n");
    1223           0 : }
    1224             : 
    1225           0 : static void __init print_local_APICs(int maxcpu)
    1226             : {
    1227           0 :         int cpu;
    1228             : 
    1229           0 :         if (!maxcpu)
    1230             :                 return;
    1231             : 
    1232           0 :         preempt_disable();
    1233           0 :         for_each_online_cpu(cpu) {
    1234           0 :                 if (cpu >= maxcpu)
    1235             :                         break;
    1236           0 :                 smp_call_function_single(cpu, print_local_APIC, NULL, 1);
    1237             :         }
    1238           0 :         preempt_enable();
    1239             : }
    1240             : 
    1241           0 : static void __init print_PIC(void)
    1242             : {
    1243           0 :         unsigned int v;
    1244           0 :         unsigned long flags;
    1245             : 
    1246           0 :         if (!nr_legacy_irqs())
    1247             :                 return;
    1248             : 
    1249           0 :         pr_debug("\nprinting PIC contents\n");
    1250             : 
    1251           0 :         raw_spin_lock_irqsave(&i8259A_lock, flags);
    1252             : 
    1253           0 :         v = inb(0xa1) << 8 | inb(0x21);
    1254           0 :         pr_debug("... PIC  IMR: %04x\n", v);
    1255             : 
    1256           0 :         v = inb(0xa0) << 8 | inb(0x20);
    1257           0 :         pr_debug("... PIC  IRR: %04x\n", v);
    1258             : 
    1259           0 :         outb(0x0b, 0xa0);
    1260           0 :         outb(0x0b, 0x20);
    1261           0 :         v = inb(0xa0) << 8 | inb(0x20);
    1262           0 :         outb(0x0a, 0xa0);
    1263           0 :         outb(0x0a, 0x20);
    1264             : 
    1265           0 :         raw_spin_unlock_irqrestore(&i8259A_lock, flags);
    1266             : 
    1267           0 :         pr_debug("... PIC  ISR: %04x\n", v);
    1268             : 
    1269           0 :         v = inb(0x4d1) << 8 | inb(0x4d0);
    1270           0 :         pr_debug("... PIC ELCR: %04x\n", v);
    1271             : }
    1272             : 
    1273             : static int show_lapic __initdata = 1;
    1274           0 : static __init int setup_show_lapic(char *arg)
    1275             : {
    1276           0 :         int num = -1;
    1277             : 
    1278           0 :         if (strcmp(arg, "all") == 0) {
    1279           0 :                 show_lapic = CONFIG_NR_CPUS;
    1280             :         } else {
    1281           0 :                 get_option(&arg, &num);
    1282           0 :                 if (num >= 0)
    1283           0 :                         show_lapic = num;
    1284             :         }
    1285             : 
    1286           0 :         return 1;
    1287             : }
    1288             : __setup("show_lapic=", setup_show_lapic);
    1289             : 
    1290           1 : static int __init print_ICs(void)
    1291             : {
    1292           1 :         if (apic_verbosity == APIC_QUIET)
    1293             :                 return 0;
    1294             : 
    1295           0 :         print_PIC();
    1296             : 
    1297             :         /* don't print out if apic is not there */
    1298           0 :         if (!boot_cpu_has(X86_FEATURE_APIC) && !apic_from_smp_config())
    1299             :                 return 0;
    1300             : 
    1301           0 :         print_local_APICs(show_lapic);
    1302           0 :         print_IO_APICs();
    1303             : 
    1304           0 :         return 0;
    1305             : }
    1306             : 
    1307             : late_initcall(print_ICs);

Generated by: LCOV version 1.14