LCOV - code coverage report
Current view: top level - arch/x86/kernel/apic - apic_flat_64.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 27 54 50.0 %
Date: 2022-03-28 15:32:58 Functions: 8 13 61.5 %
Branches: 4 16 25.0 %

           Branch data     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                 :         56 : static int flat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
      27                 :            : {
      28                 :         56 :         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                 :         28 : void flat_init_apic_ldr(void)
      39                 :            : {
      40                 :         28 :         unsigned long val;
      41                 :         28 :         unsigned long num, id;
      42                 :            : 
      43                 :         28 :         num = smp_processor_id();
      44                 :         28 :         id = 1UL << num;
      45                 :         28 :         apic_write(APIC_DFR, APIC_DFR_FLAT);
      46                 :         28 :         val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
      47                 :         28 :         val |= SET_APIC_LOGICAL_ID(id);
      48                 :         28 :         apic_write(APIC_LDR, val);
      49                 :         28 : }
      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                 :        168 : static unsigned int flat_get_apic_id(unsigned long x)
      80                 :            : {
      81                 :        168 :         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                 :         28 : static unsigned int read_xapic_id(void)
      90                 :            : {
      91                 :         56 :         return flat_get_apic_id(apic_read(APIC_ID));
      92                 :            : }
      93                 :            : 
      94                 :         28 : static int flat_apic_id_registered(void)
      95                 :            : {
      96                 :         28 :         return physid_isset(read_xapic_id(), phys_cpu_present_map);
      97                 :            : }
      98                 :            : 
      99                 :         28 : static int flat_phys_pkg_id(int initial_apic_id, int index_msb)
     100                 :            : {
     101                 :         28 :         return initial_apic_id >> index_msb;
     102                 :            : }
     103                 :            : 
     104                 :         28 : static int flat_probe(void)
     105                 :            : {
     106                 :         28 :         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                 :            :         .irq_delivery_mode              = dest_Fixed,
     117                 :            :         .irq_dest_mode                  = 1, /* logical */
     118                 :            : 
     119                 :            :         .disable_esr                    = 0,
     120                 :            :         .dest_logical                   = APIC_DEST_LOGICAL,
     121                 :            :         .check_apicid_used              = NULL,
     122                 :            : 
     123                 :            :         .init_apic_ldr                  = flat_init_apic_ldr,
     124                 :            : 
     125                 :            :         .ioapic_phys_id_map             = NULL,
     126                 :            :         .setup_apic_routing             = NULL,
     127                 :            :         .cpu_present_to_apicid          = default_cpu_present_to_apicid,
     128                 :            :         .apicid_to_cpu_present          = NULL,
     129                 :            :         .check_phys_apicid_present      = default_check_phys_apicid_present,
     130                 :            :         .phys_pkg_id                    = flat_phys_pkg_id,
     131                 :            : 
     132                 :            :         .get_apic_id                    = flat_get_apic_id,
     133                 :            :         .set_apic_id                    = set_apic_id,
     134                 :            : 
     135                 :            :         .calc_dest_apicid               = apic_flat_calc_apicid,
     136                 :            : 
     137                 :            :         .send_IPI                       = default_send_IPI_single,
     138                 :            :         .send_IPI_mask                  = flat_send_IPI_mask,
     139                 :            :         .send_IPI_mask_allbutself       = flat_send_IPI_mask_allbutself,
     140                 :            :         .send_IPI_allbutself            = default_send_IPI_allbutself,
     141                 :            :         .send_IPI_all                   = default_send_IPI_all,
     142                 :            :         .send_IPI_self                  = default_send_IPI_self,
     143                 :            : 
     144                 :            :         .inquire_remote_apic            = default_inquire_remote_apic,
     145                 :            : 
     146                 :            :         .read                           = native_apic_mem_read,
     147                 :            :         .write                          = native_apic_mem_write,
     148                 :            :         .eoi_write                      = native_apic_mem_write,
     149                 :            :         .icr_read                       = native_apic_icr_read,
     150                 :            :         .icr_write                      = native_apic_icr_write,
     151                 :            :         .wait_icr_idle                  = native_apic_wait_icr_idle,
     152                 :            :         .safe_wait_icr_idle             = native_safe_apic_wait_icr_idle,
     153                 :            : };
     154                 :            : 
     155                 :            : /*
     156                 :            :  * Physflat mode is used when there are more than 8 CPUs on a system.
     157                 :            :  * We cannot use logical delivery in this case because the mask
     158                 :            :  * overflows, so use physical mode.
     159                 :            :  */
     160                 :         56 : static int physflat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
     161                 :            : {
     162                 :            : #ifdef CONFIG_ACPI
     163                 :            :         /*
     164                 :            :          * Quirk: some x86_64 machines can only use physical APIC mode
     165                 :            :          * regardless of how many processors are present (x86_64 ES7000
     166                 :            :          * is an example).
     167                 :            :          */
     168         [ -  + ]:         56 :         if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
     169         [ #  # ]:          0 :                 (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL)) {
     170                 :          0 :                 printk(KERN_DEBUG "system APIC only can use physical flat");
     171                 :          0 :                 return 1;
     172                 :            :         }
     173                 :            : 
     174   [ -  +  -  - ]:         56 :         if (!strncmp(oem_id, "IBM", 3) && !strncmp(oem_table_id, "EXA", 3)) {
     175                 :          0 :                 printk(KERN_DEBUG "IBM Summit detected, will use apic physical");
     176                 :          0 :                 return 1;
     177                 :            :         }
     178                 :            : #endif
     179                 :            : 
     180                 :            :         return 0;
     181                 :            : }
     182                 :            : 
     183                 :          0 : static void physflat_init_apic_ldr(void)
     184                 :            : {
     185                 :            :         /*
     186                 :            :          * LDR and DFR are not involved in physflat mode, rather:
     187                 :            :          * "In physical destination mode, the destination processor is
     188                 :            :          * specified by its local APIC ID [...]." (Intel SDM, 10.6.2.1)
     189                 :            :          */
     190                 :          0 : }
     191                 :            : 
     192                 :         28 : static int physflat_probe(void)
     193                 :            : {
     194   [ +  -  -  + ]:         28 :         if (apic == &apic_physflat || num_possible_cpus() > 8 ||
     195                 :            :             jailhouse_paravirt())
     196                 :          0 :                 return 1;
     197                 :            : 
     198                 :            :         return 0;
     199                 :            : }
     200                 :            : 
     201                 :            : static struct apic apic_physflat __ro_after_init = {
     202                 :            : 
     203                 :            :         .name                           = "physical flat",
     204                 :            :         .probe                          = physflat_probe,
     205                 :            :         .acpi_madt_oem_check            = physflat_acpi_madt_oem_check,
     206                 :            :         .apic_id_valid                  = default_apic_id_valid,
     207                 :            :         .apic_id_registered             = flat_apic_id_registered,
     208                 :            : 
     209                 :            :         .irq_delivery_mode              = dest_Fixed,
     210                 :            :         .irq_dest_mode                  = 0, /* physical */
     211                 :            : 
     212                 :            :         .disable_esr                    = 0,
     213                 :            :         .dest_logical                   = 0,
     214                 :            :         .check_apicid_used              = NULL,
     215                 :            : 
     216                 :            :         .init_apic_ldr                  = physflat_init_apic_ldr,
     217                 :            : 
     218                 :            :         .ioapic_phys_id_map             = NULL,
     219                 :            :         .setup_apic_routing             = NULL,
     220                 :            :         .cpu_present_to_apicid          = default_cpu_present_to_apicid,
     221                 :            :         .apicid_to_cpu_present          = NULL,
     222                 :            :         .check_phys_apicid_present      = default_check_phys_apicid_present,
     223                 :            :         .phys_pkg_id                    = flat_phys_pkg_id,
     224                 :            : 
     225                 :            :         .get_apic_id                    = flat_get_apic_id,
     226                 :            :         .set_apic_id                    = set_apic_id,
     227                 :            : 
     228                 :            :         .calc_dest_apicid               = apic_default_calc_apicid,
     229                 :            : 
     230                 :            :         .send_IPI                       = default_send_IPI_single_phys,
     231                 :            :         .send_IPI_mask                  = default_send_IPI_mask_sequence_phys,
     232                 :            :         .send_IPI_mask_allbutself       = default_send_IPI_mask_allbutself_phys,
     233                 :            :         .send_IPI_allbutself            = default_send_IPI_allbutself,
     234                 :            :         .send_IPI_all                   = default_send_IPI_all,
     235                 :            :         .send_IPI_self                  = default_send_IPI_self,
     236                 :            : 
     237                 :            :         .inquire_remote_apic            = default_inquire_remote_apic,
     238                 :            : 
     239                 :            :         .read                           = native_apic_mem_read,
     240                 :            :         .write                          = native_apic_mem_write,
     241                 :            :         .eoi_write                      = native_apic_mem_write,
     242                 :            :         .icr_read                       = native_apic_icr_read,
     243                 :            :         .icr_write                      = native_apic_icr_write,
     244                 :            :         .wait_icr_idle                  = native_apic_wait_icr_idle,
     245                 :            :         .safe_wait_icr_idle             = native_safe_apic_wait_icr_idle,
     246                 :            : };
     247                 :            : 
     248                 :            : /*
     249                 :            :  * We need to check for physflat first, so this order is important.
     250                 :            :  */
     251                 :            : apic_drivers(apic_physflat, apic_flat);

Generated by: LCOV version 1.14