LCOV - code coverage report
Current view: top level - arch/x86/kernel/cpu - topology.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 48 0.0 %
Date: 2022-03-28 13:20:08 Functions: 0 2 0.0 %
Branches: 0 10 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : /*
       3                 :            :  * Check for extended topology enumeration cpuid leaf 0xb and if it
       4                 :            :  * exists, use it for populating initial_apicid and cpu topology
       5                 :            :  * detection.
       6                 :            :  */
       7                 :            : 
       8                 :            : #include <linux/cpu.h>
       9                 :            : #include <asm/apic.h>
      10                 :            : #include <asm/memtype.h>
      11                 :            : #include <asm/processor.h>
      12                 :            : 
      13                 :            : #include "cpu.h"
      14                 :            : 
      15                 :            : /* leaf 0xb SMT level */
      16                 :            : #define SMT_LEVEL       0
      17                 :            : 
      18                 :            : /* extended topology sub-leaf types */
      19                 :            : #define INVALID_TYPE    0
      20                 :            : #define SMT_TYPE        1
      21                 :            : #define CORE_TYPE       2
      22                 :            : #define DIE_TYPE        5
      23                 :            : 
      24                 :            : #define LEAFB_SUBTYPE(ecx)              (((ecx) >> 8) & 0xff)
      25                 :            : #define BITS_SHIFT_NEXT_LEVEL(eax)      ((eax) & 0x1f)
      26                 :            : #define LEVEL_MAX_SIBLINGS(ebx)         ((ebx) & 0xffff)
      27                 :            : 
      28                 :            : #ifdef CONFIG_SMP
      29                 :            : unsigned int __max_die_per_package __read_mostly = 1;
      30                 :            : EXPORT_SYMBOL(__max_die_per_package);
      31                 :            : 
      32                 :            : /*
      33                 :            :  * Check if given CPUID extended toplogy "leaf" is implemented
      34                 :            :  */
      35                 :            : static int check_extended_topology_leaf(int leaf)
      36                 :            : {
      37                 :            :         unsigned int eax, ebx, ecx, edx;
      38                 :            : 
      39                 :            :         cpuid_count(leaf, SMT_LEVEL, &eax, &ebx, &ecx, &edx);
      40                 :            : 
      41                 :            :         if (ebx == 0 || (LEAFB_SUBTYPE(ecx) != SMT_TYPE))
      42                 :            :                 return -1;
      43                 :            : 
      44                 :            :         return 0;
      45                 :            : }
      46                 :            : /*
      47                 :            :  * Return best CPUID Extended Toplogy Leaf supported
      48                 :            :  */
      49                 :            : static int detect_extended_topology_leaf(struct cpuinfo_x86 *c)
      50                 :            : {
      51                 :            :         if (c->cpuid_level >= 0x1f) {
      52                 :            :                 if (check_extended_topology_leaf(0x1f) == 0)
      53                 :            :                         return 0x1f;
      54                 :            :         }
      55                 :            : 
      56                 :            :         if (c->cpuid_level >= 0xb) {
      57                 :            :                 if (check_extended_topology_leaf(0xb) == 0)
      58                 :            :                         return 0xb;
      59                 :            :         }
      60                 :            : 
      61                 :            :         return -1;
      62                 :            : }
      63                 :            : #endif
      64                 :            : 
      65                 :          0 : int detect_extended_topology_early(struct cpuinfo_x86 *c)
      66                 :            : {
      67                 :            : #ifdef CONFIG_SMP
      68                 :          0 :         unsigned int eax, ebx, ecx, edx;
      69                 :          0 :         int leaf;
      70                 :            : 
      71                 :          0 :         leaf = detect_extended_topology_leaf(c);
      72         [ #  # ]:          0 :         if (leaf < 0)
      73                 :            :                 return -1;
      74                 :            : 
      75                 :          0 :         set_cpu_cap(c, X86_FEATURE_XTOPOLOGY);
      76                 :            : 
      77                 :          0 :         cpuid_count(leaf, SMT_LEVEL, &eax, &ebx, &ecx, &edx);
      78                 :            :         /*
      79                 :            :          * initial apic id, which also represents 32-bit extended x2apic id.
      80                 :            :          */
      81                 :          0 :         c->initial_apicid = edx;
      82                 :          0 :         smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx);
      83                 :            : #endif
      84                 :          0 :         return 0;
      85                 :            : }
      86                 :            : 
      87                 :            : /*
      88                 :            :  * Check for extended topology enumeration cpuid leaf, and if it
      89                 :            :  * exists, use it for populating initial_apicid and cpu topology
      90                 :            :  * detection.
      91                 :            :  */
      92                 :          0 : int detect_extended_topology(struct cpuinfo_x86 *c)
      93                 :            : {
      94                 :            : #ifdef CONFIG_SMP
      95                 :          0 :         unsigned int eax, ebx, ecx, edx, sub_index;
      96                 :          0 :         unsigned int ht_mask_width, core_plus_mask_width, die_plus_mask_width;
      97                 :          0 :         unsigned int core_select_mask, core_level_siblings;
      98                 :          0 :         unsigned int die_select_mask, die_level_siblings;
      99                 :          0 :         int leaf;
     100                 :            : 
     101                 :          0 :         leaf = detect_extended_topology_leaf(c);
     102         [ #  # ]:          0 :         if (leaf < 0)
     103                 :            :                 return -1;
     104                 :            : 
     105                 :            :         /*
     106                 :            :          * Populate HT related information from sub-leaf level 0.
     107                 :            :          */
     108                 :          0 :         cpuid_count(leaf, SMT_LEVEL, &eax, &ebx, &ecx, &edx);
     109                 :          0 :         c->initial_apicid = edx;
     110                 :          0 :         core_level_siblings = smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx);
     111                 :          0 :         core_plus_mask_width = ht_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
     112                 :          0 :         die_level_siblings = LEVEL_MAX_SIBLINGS(ebx);
     113                 :          0 :         die_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
     114                 :            : 
     115                 :          0 :         sub_index = 1;
     116                 :          0 :         do {
     117                 :          0 :                 cpuid_count(leaf, sub_index, &eax, &ebx, &ecx, &edx);
     118                 :            : 
     119                 :            :                 /*
     120                 :            :                  * Check for the Core type in the implemented sub leaves.
     121                 :            :                  */
     122         [ #  # ]:          0 :                 if (LEAFB_SUBTYPE(ecx) == CORE_TYPE) {
     123                 :          0 :                         core_level_siblings = LEVEL_MAX_SIBLINGS(ebx);
     124                 :          0 :                         core_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
     125                 :          0 :                         die_level_siblings = core_level_siblings;
     126                 :          0 :                         die_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
     127                 :            :                 }
     128         [ #  # ]:          0 :                 if (LEAFB_SUBTYPE(ecx) == DIE_TYPE) {
     129                 :          0 :                         die_level_siblings = LEVEL_MAX_SIBLINGS(ebx);
     130                 :          0 :                         die_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
     131                 :            :                 }
     132                 :            : 
     133                 :          0 :                 sub_index++;
     134         [ #  # ]:          0 :         } while (LEAFB_SUBTYPE(ecx) != INVALID_TYPE);
     135                 :            : 
     136                 :          0 :         core_select_mask = (~(-1 << core_plus_mask_width)) >> ht_mask_width;
     137                 :          0 :         die_select_mask = (~(-1 << die_plus_mask_width)) >>
     138                 :            :                                 core_plus_mask_width;
     139                 :            : 
     140                 :          0 :         c->cpu_core_id = apic->phys_pkg_id(c->initial_apicid,
     141                 :          0 :                                 ht_mask_width) & core_select_mask;
     142                 :          0 :         c->cpu_die_id = apic->phys_pkg_id(c->initial_apicid,
     143                 :          0 :                                 core_plus_mask_width) & die_select_mask;
     144                 :          0 :         c->phys_proc_id = apic->phys_pkg_id(c->initial_apicid,
     145                 :            :                                 die_plus_mask_width);
     146                 :            :         /*
     147                 :            :          * Reinit the apicid, now that we have extended initial_apicid.
     148                 :            :          */
     149                 :          0 :         c->apicid = apic->phys_pkg_id(c->initial_apicid, 0);
     150                 :            : 
     151                 :          0 :         c->x86_max_cores = (core_level_siblings / smp_num_siblings);
     152                 :          0 :         __max_die_per_package = (die_level_siblings / core_level_siblings);
     153                 :            : #endif
     154                 :          0 :         return 0;
     155                 :            : }

Generated by: LCOV version 1.14