LCOV - code coverage report
Current view: top level - arch/x86/kernel/apic - apic_flat_64.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 22 48 45.8 %
Date: 2021-04-22 12:43:58 Functions: 6 13 46.2 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-only
       2             : /*
       3             :  * Copyright 2004 James Cleverdon, IBM.
       4             :  *
       5             :  * Flat APIC subarch code.
       6             :  *
       7             :  * Hacked for x86-64 by James Cleverdon from i386 architecture code by
       8             :  * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
       9             :  * James Cleverdon.
      10             :  */
      11             : #include <linux/cpumask.h>
      12             : #include <linux/export.h>
      13             : #include <linux/acpi.h>
      14             : 
      15             : #include <asm/jailhouse_para.h>
      16             : #include <asm/apic.h>
      17             : 
      18             : #include "local.h"
      19             : 
      20             : static struct apic apic_physflat;
      21             : static struct apic apic_flat;
      22             : 
      23             : struct apic *apic __ro_after_init = &apic_flat;
      24             : EXPORT_SYMBOL_GPL(apic);
      25             : 
      26           0 : static int flat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
      27             : {
      28           0 :         return 1;
      29             : }
      30             : 
      31             : /*
      32             :  * Set up the logical destination ID.
      33             :  *
      34             :  * Intel recommends to set DFR, LDR and TPR before enabling
      35             :  * an APIC.  See e.g. "AP-388 82489DX User's Manual" (Intel
      36             :  * document number 292116).  So here it goes...
      37             :  */
      38           4 : void flat_init_apic_ldr(void)
      39             : {
      40           4 :         unsigned long val;
      41           4 :         unsigned long num, id;
      42             : 
      43           4 :         num = smp_processor_id();
      44           4 :         id = 1UL << num;
      45           4 :         apic_write(APIC_DFR, APIC_DFR_FLAT);
      46           4 :         val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
      47           4 :         val |= SET_APIC_LOGICAL_ID(id);
      48           4 :         apic_write(APIC_LDR, val);
      49           4 : }
      50             : 
      51           0 : static void _flat_send_IPI_mask(unsigned long mask, int vector)
      52             : {
      53           0 :         unsigned long flags;
      54             : 
      55           0 :         local_irq_save(flags);
      56           0 :         __default_send_IPI_dest_field(mask, vector, APIC_DEST_LOGICAL);
      57           0 :         local_irq_restore(flags);
      58           0 : }
      59             : 
      60           0 : static void flat_send_IPI_mask(const struct cpumask *cpumask, int vector)
      61             : {
      62           0 :         unsigned long mask = cpumask_bits(cpumask)[0];
      63             : 
      64           0 :         _flat_send_IPI_mask(mask, vector);
      65           0 : }
      66             : 
      67             : static void
      68           0 : flat_send_IPI_mask_allbutself(const struct cpumask *cpumask, int vector)
      69             : {
      70           0 :         unsigned long mask = cpumask_bits(cpumask)[0];
      71           0 :         int cpu = smp_processor_id();
      72             : 
      73           0 :         if (cpu < BITS_PER_LONG)
      74           0 :                 __clear_bit(cpu, &mask);
      75             : 
      76           0 :         _flat_send_IPI_mask(mask, vector);
      77           0 : }
      78             : 
      79           8 : static unsigned int flat_get_apic_id(unsigned long x)
      80             : {
      81           8 :         return (x >> 24) & 0xFF;
      82             : }
      83             : 
      84           0 : static u32 set_apic_id(unsigned int id)
      85             : {
      86           0 :         return (id & 0xFF) << 24;
      87             : }
      88             : 
      89           4 : static unsigned int read_xapic_id(void)
      90             : {
      91           8 :         return flat_get_apic_id(apic_read(APIC_ID));
      92             : }
      93             : 
      94           4 : static int flat_apic_id_registered(void)
      95             : {
      96           4 :         return physid_isset(read_xapic_id(), phys_cpu_present_map);
      97             : }
      98             : 
      99          16 : static int flat_phys_pkg_id(int initial_apic_id, int index_msb)
     100             : {
     101          16 :         return initial_apic_id >> index_msb;
     102             : }
     103             : 
     104           1 : static int flat_probe(void)
     105             : {
     106           1 :         return 1;
     107             : }
     108             : 
     109             : static struct apic apic_flat __ro_after_init = {
     110             :         .name                           = "flat",
     111             :         .probe                          = flat_probe,
     112             :         .acpi_madt_oem_check            = flat_acpi_madt_oem_check,
     113             :         .apic_id_valid                  = default_apic_id_valid,
     114             :         .apic_id_registered             = flat_apic_id_registered,
     115             : 
     116             :         .delivery_mode                  = APIC_DELIVERY_MODE_FIXED,
     117             :         .dest_mode_logical              = true,
     118             : 
     119             :         .disable_esr                    = 0,
     120             : 
     121             :         .check_apicid_used              = NULL,
     122             :         .init_apic_ldr                  = flat_init_apic_ldr,
     123             :         .ioapic_phys_id_map             = NULL,
     124             :         .setup_apic_routing             = NULL,
     125             :         .cpu_present_to_apicid          = default_cpu_present_to_apicid,
     126             :         .apicid_to_cpu_present          = NULL,
     127             :         .check_phys_apicid_present      = default_check_phys_apicid_present,
     128             :         .phys_pkg_id                    = flat_phys_pkg_id,
     129             : 
     130             :         .get_apic_id                    = flat_get_apic_id,
     131             :         .set_apic_id                    = set_apic_id,
     132             : 
     133             :         .calc_dest_apicid               = apic_flat_calc_apicid,
     134             : 
     135             :         .send_IPI                       = default_send_IPI_single,
     136             :         .send_IPI_mask                  = flat_send_IPI_mask,
     137             :         .send_IPI_mask_allbutself       = flat_send_IPI_mask_allbutself,
     138             :         .send_IPI_allbutself            = default_send_IPI_allbutself,
     139             :         .send_IPI_all                   = default_send_IPI_all,
     140             :         .send_IPI_self                  = default_send_IPI_self,
     141             : 
     142             :         .inquire_remote_apic            = default_inquire_remote_apic,
     143             : 
     144             :         .read                           = native_apic_mem_read,
     145             :         .write                          = native_apic_mem_write,
     146             :         .eoi_write                      = native_apic_mem_write,
     147             :         .icr_read                       = native_apic_icr_read,
     148             :         .icr_write                      = native_apic_icr_write,
     149             :         .wait_icr_idle                  = native_apic_wait_icr_idle,
     150             :         .safe_wait_icr_idle             = native_safe_apic_wait_icr_idle,
     151             : };
     152             : 
     153             : /*
     154             :  * Physflat mode is used when there are more than 8 CPUs on a system.
     155             :  * We cannot use logical delivery in this case because the mask
     156             :  * overflows, so use physical mode.
     157             :  */
     158           0 : static int physflat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
     159             : {
     160             : #ifdef CONFIG_ACPI
     161             :         /*
     162             :          * Quirk: some x86_64 machines can only use physical APIC mode
     163             :          * regardless of how many processors are present (x86_64 ES7000
     164             :          * is an example).
     165             :          */
     166             :         if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
     167             :                 (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL)) {
     168             :                 printk(KERN_DEBUG "system APIC only can use physical flat");
     169             :                 return 1;
     170             :         }
     171             : 
     172             :         if (!strncmp(oem_id, "IBM", 3) && !strncmp(oem_table_id, "EXA", 3)) {
     173             :                 printk(KERN_DEBUG "IBM Summit detected, will use apic physical");
     174             :                 return 1;
     175             :         }
     176             : #endif
     177             : 
     178           0 :         return 0;
     179             : }
     180             : 
     181           0 : static void physflat_init_apic_ldr(void)
     182             : {
     183             :         /*
     184             :          * LDR and DFR are not involved in physflat mode, rather:
     185             :          * "In physical destination mode, the destination processor is
     186             :          * specified by its local APIC ID [...]." (Intel SDM, 10.6.2.1)
     187             :          */
     188           0 : }
     189             : 
     190           1 : static int physflat_probe(void)
     191             : {
     192           1 :         if (apic == &apic_physflat || num_possible_cpus() > 8 ||
     193             :             jailhouse_paravirt())
     194           0 :                 return 1;
     195             : 
     196             :         return 0;
     197             : }
     198             : 
     199             : static struct apic apic_physflat __ro_after_init = {
     200             : 
     201             :         .name                           = "physical flat",
     202             :         .probe                          = physflat_probe,
     203             :         .acpi_madt_oem_check            = physflat_acpi_madt_oem_check,
     204             :         .apic_id_valid                  = default_apic_id_valid,
     205             :         .apic_id_registered             = flat_apic_id_registered,
     206             : 
     207             :         .delivery_mode                  = APIC_DELIVERY_MODE_FIXED,
     208             :         .dest_mode_logical              = false,
     209             : 
     210             :         .disable_esr                    = 0,
     211             : 
     212             :         .check_apicid_used              = NULL,
     213             :         .init_apic_ldr                  = physflat_init_apic_ldr,
     214             :         .ioapic_phys_id_map             = NULL,
     215             :         .setup_apic_routing             = NULL,
     216             :         .cpu_present_to_apicid          = default_cpu_present_to_apicid,
     217             :         .apicid_to_cpu_present          = NULL,
     218             :         .check_phys_apicid_present      = default_check_phys_apicid_present,
     219             :         .phys_pkg_id                    = flat_phys_pkg_id,
     220             : 
     221             :         .get_apic_id                    = flat_get_apic_id,
     222             :         .set_apic_id                    = set_apic_id,
     223             : 
     224             :         .calc_dest_apicid               = apic_default_calc_apicid,
     225             : 
     226             :         .send_IPI                       = default_send_IPI_single_phys,
     227             :         .send_IPI_mask                  = default_send_IPI_mask_sequence_phys,
     228             :         .send_IPI_mask_allbutself       = default_send_IPI_mask_allbutself_phys,
     229             :         .send_IPI_allbutself            = default_send_IPI_allbutself,
     230             :         .send_IPI_all                   = default_send_IPI_all,
     231             :         .send_IPI_self                  = default_send_IPI_self,
     232             : 
     233             :         .inquire_remote_apic            = default_inquire_remote_apic,
     234             : 
     235             :         .read                           = native_apic_mem_read,
     236             :         .write                          = native_apic_mem_write,
     237             :         .eoi_write                      = native_apic_mem_write,
     238             :         .icr_read                       = native_apic_icr_read,
     239             :         .icr_write                      = native_apic_icr_write,
     240             :         .wait_icr_idle                  = native_apic_wait_icr_idle,
     241             :         .safe_wait_icr_idle             = native_safe_apic_wait_icr_idle,
     242             : };
     243             : 
     244             : /*
     245             :  * We need to check for physflat first, so this order is important.
     246             :  */
     247             : apic_drivers(apic_physflat, apic_flat);

Generated by: LCOV version 1.14