LCOV - code coverage report
Current view: top level - drivers/base - cpu.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 78 181 43.1 %
Date: 2022-03-28 13:20:08 Functions: 10 29 34.5 %
Branches: 18 66 27.3 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : /*
       3                 :            :  * CPU subsystem support
       4                 :            :  */
       5                 :            : 
       6                 :            : #include <linux/kernel.h>
       7                 :            : #include <linux/module.h>
       8                 :            : #include <linux/init.h>
       9                 :            : #include <linux/sched.h>
      10                 :            : #include <linux/cpu.h>
      11                 :            : #include <linux/topology.h>
      12                 :            : #include <linux/device.h>
      13                 :            : #include <linux/node.h>
      14                 :            : #include <linux/gfp.h>
      15                 :            : #include <linux/slab.h>
      16                 :            : #include <linux/percpu.h>
      17                 :            : #include <linux/acpi.h>
      18                 :            : #include <linux/of.h>
      19                 :            : #include <linux/cpufeature.h>
      20                 :            : #include <linux/tick.h>
      21                 :            : #include <linux/pm_qos.h>
      22                 :            : #include <linux/sched/isolation.h>
      23                 :            : 
      24                 :            : #include "base.h"
      25                 :            : 
      26                 :            : static DEFINE_PER_CPU(struct device *, cpu_sys_devices);
      27                 :            : 
      28                 :         30 : static int cpu_subsys_match(struct device *dev, struct device_driver *drv)
      29                 :            : {
      30                 :            :         /* ACPI style match is the only one that may succeed. */
      31         [ +  - ]:         30 :         if (acpi_driver_match_device(dev, drv))
      32                 :         30 :                 return 1;
      33                 :            : 
      34                 :            :         return 0;
      35                 :            : }
      36                 :            : 
      37                 :            : #ifdef CONFIG_HOTPLUG_CPU
      38                 :          0 : static void change_cpu_under_node(struct cpu *cpu,
      39                 :            :                         unsigned int from_nid, unsigned int to_nid)
      40                 :            : {
      41                 :          0 :         int cpuid = cpu->dev.id;
      42                 :          0 :         unregister_cpu_under_node(cpuid, from_nid);
      43                 :          0 :         register_cpu_under_node(cpuid, to_nid);
      44                 :          0 :         cpu->node_id = to_nid;
      45                 :          0 : }
      46                 :            : 
      47                 :          0 : static int cpu_subsys_online(struct device *dev)
      48                 :            : {
      49                 :          0 :         struct cpu *cpu = container_of(dev, struct cpu, dev);
      50                 :          0 :         int cpuid = dev->id;
      51                 :          0 :         int from_nid, to_nid;
      52                 :          0 :         int ret;
      53                 :            : 
      54         [ #  # ]:          0 :         from_nid = cpu_to_node(cpuid);
      55         [ #  # ]:          0 :         if (from_nid == NUMA_NO_NODE)
      56                 :            :                 return -ENODEV;
      57                 :            : 
      58                 :          0 :         ret = cpu_up(cpuid);
      59                 :            :         /*
      60                 :            :          * When hot adding memory to memoryless node and enabling a cpu
      61                 :            :          * on the node, node number of the cpu may internally change.
      62                 :            :          */
      63         [ #  # ]:          0 :         to_nid = cpu_to_node(cpuid);
      64         [ #  # ]:          0 :         if (from_nid != to_nid)
      65                 :          0 :                 change_cpu_under_node(cpu, from_nid, to_nid);
      66                 :            : 
      67                 :            :         return ret;
      68                 :            : }
      69                 :            : 
      70                 :          0 : static int cpu_subsys_offline(struct device *dev)
      71                 :            : {
      72                 :          0 :         return cpu_down(dev->id);
      73                 :            : }
      74                 :            : 
      75                 :          0 : void unregister_cpu(struct cpu *cpu)
      76                 :            : {
      77                 :          0 :         int logical_cpu = cpu->dev.id;
      78                 :            : 
      79                 :          0 :         unregister_cpu_under_node(logical_cpu, cpu_to_node(logical_cpu));
      80                 :            : 
      81                 :          0 :         device_unregister(&cpu->dev);
      82                 :          0 :         per_cpu(cpu_sys_devices, logical_cpu) = NULL;
      83                 :          0 :         return;
      84                 :            : }
      85                 :            : 
      86                 :            : #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
      87                 :            : static ssize_t cpu_probe_store(struct device *dev,
      88                 :            :                                struct device_attribute *attr,
      89                 :            :                                const char *buf,
      90                 :            :                                size_t count)
      91                 :            : {
      92                 :            :         ssize_t cnt;
      93                 :            :         int ret;
      94                 :            : 
      95                 :            :         ret = lock_device_hotplug_sysfs();
      96                 :            :         if (ret)
      97                 :            :                 return ret;
      98                 :            : 
      99                 :            :         cnt = arch_cpu_probe(buf, count);
     100                 :            : 
     101                 :            :         unlock_device_hotplug();
     102                 :            :         return cnt;
     103                 :            : }
     104                 :            : 
     105                 :            : static ssize_t cpu_release_store(struct device *dev,
     106                 :            :                                  struct device_attribute *attr,
     107                 :            :                                  const char *buf,
     108                 :            :                                  size_t count)
     109                 :            : {
     110                 :            :         ssize_t cnt;
     111                 :            :         int ret;
     112                 :            : 
     113                 :            :         ret = lock_device_hotplug_sysfs();
     114                 :            :         if (ret)
     115                 :            :                 return ret;
     116                 :            : 
     117                 :            :         cnt = arch_cpu_release(buf, count);
     118                 :            : 
     119                 :            :         unlock_device_hotplug();
     120                 :            :         return cnt;
     121                 :            : }
     122                 :            : 
     123                 :            : static DEVICE_ATTR(probe, S_IWUSR, NULL, cpu_probe_store);
     124                 :            : static DEVICE_ATTR(release, S_IWUSR, NULL, cpu_release_store);
     125                 :            : #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */
     126                 :            : #endif /* CONFIG_HOTPLUG_CPU */
     127                 :            : 
     128                 :            : struct bus_type cpu_subsys = {
     129                 :            :         .name = "cpu",
     130                 :            :         .dev_name = "cpu",
     131                 :            :         .match = cpu_subsys_match,
     132                 :            : #ifdef CONFIG_HOTPLUG_CPU
     133                 :            :         .online = cpu_subsys_online,
     134                 :            :         .offline = cpu_subsys_offline,
     135                 :            : #endif
     136                 :            : };
     137                 :            : EXPORT_SYMBOL_GPL(cpu_subsys);
     138                 :            : 
     139                 :            : #ifdef CONFIG_KEXEC
     140                 :            : #include <linux/kexec.h>
     141                 :            : 
     142                 :          0 : static ssize_t show_crash_notes(struct device *dev, struct device_attribute *attr,
     143                 :            :                                 char *buf)
     144                 :            : {
     145                 :          0 :         struct cpu *cpu = container_of(dev, struct cpu, dev);
     146                 :          0 :         ssize_t rc;
     147                 :          0 :         unsigned long long addr;
     148                 :          0 :         int cpunum;
     149                 :            : 
     150                 :          0 :         cpunum = cpu->dev.id;
     151                 :            : 
     152                 :            :         /*
     153                 :            :          * Might be reading other cpu's data based on which cpu read thread
     154                 :            :          * has been scheduled. But cpu data (memory) is allocated once during
     155                 :            :          * boot up and this data does not change there after. Hence this
     156                 :            :          * operation should be safe. No locking required.
     157                 :            :          */
     158                 :          0 :         addr = per_cpu_ptr_to_phys(per_cpu_ptr(crash_notes, cpunum));
     159                 :          0 :         rc = sprintf(buf, "%Lx\n", addr);
     160                 :          0 :         return rc;
     161                 :            : }
     162                 :            : static DEVICE_ATTR(crash_notes, 0400, show_crash_notes, NULL);
     163                 :            : 
     164                 :          0 : static ssize_t show_crash_notes_size(struct device *dev,
     165                 :            :                                      struct device_attribute *attr,
     166                 :            :                                      char *buf)
     167                 :            : {
     168                 :          0 :         ssize_t rc;
     169                 :            : 
     170                 :          0 :         rc = sprintf(buf, "%zu\n", sizeof(note_buf_t));
     171                 :          0 :         return rc;
     172                 :            : }
     173                 :            : static DEVICE_ATTR(crash_notes_size, 0400, show_crash_notes_size, NULL);
     174                 :            : 
     175                 :            : static struct attribute *crash_note_cpu_attrs[] = {
     176                 :            :         &dev_attr_crash_notes.attr,
     177                 :            :         &dev_attr_crash_notes_size.attr,
     178                 :            :         NULL
     179                 :            : };
     180                 :            : 
     181                 :            : static struct attribute_group crash_note_cpu_attr_group = {
     182                 :            :         .attrs = crash_note_cpu_attrs,
     183                 :            : };
     184                 :            : #endif
     185                 :            : 
     186                 :            : static const struct attribute_group *common_cpu_attr_groups[] = {
     187                 :            : #ifdef CONFIG_KEXEC
     188                 :            :         &crash_note_cpu_attr_group,
     189                 :            : #endif
     190                 :            :         NULL
     191                 :            : };
     192                 :            : 
     193                 :            : static const struct attribute_group *hotplugable_cpu_attr_groups[] = {
     194                 :            : #ifdef CONFIG_KEXEC
     195                 :            :         &crash_note_cpu_attr_group,
     196                 :            : #endif
     197                 :            :         NULL
     198                 :            : };
     199                 :            : 
     200                 :            : /*
     201                 :            :  * Print cpu online, possible, present, and system maps
     202                 :            :  */
     203                 :            : 
     204                 :            : struct cpu_attr {
     205                 :            :         struct device_attribute attr;
     206                 :            :         const struct cpumask *const map;
     207                 :            : };
     208                 :            : 
     209                 :         60 : static ssize_t show_cpus_attr(struct device *dev,
     210                 :            :                               struct device_attribute *attr,
     211                 :            :                               char *buf)
     212                 :            : {
     213                 :         60 :         struct cpu_attr *ca = container_of(attr, struct cpu_attr, attr);
     214                 :            : 
     215                 :         60 :         return cpumap_print_to_pagebuf(true, buf, ca->map);
     216                 :            : }
     217                 :            : 
     218                 :            : #define _CPU_ATTR(name, map) \
     219                 :            :         { __ATTR(name, 0444, show_cpus_attr, NULL), map }
     220                 :            : 
     221                 :            : /* Keep in sync with cpu_subsys_attrs */
     222                 :            : static struct cpu_attr cpu_attrs[] = {
     223                 :            :         _CPU_ATTR(online, &__cpu_online_mask),
     224                 :            :         _CPU_ATTR(possible, &__cpu_possible_mask),
     225                 :            :         _CPU_ATTR(present, &__cpu_present_mask),
     226                 :            : };
     227                 :            : 
     228                 :            : /*
     229                 :            :  * Print values for NR_CPUS and offlined cpus
     230                 :            :  */
     231                 :          0 : static ssize_t print_cpus_kernel_max(struct device *dev,
     232                 :            :                                      struct device_attribute *attr, char *buf)
     233                 :            : {
     234                 :          0 :         int n = snprintf(buf, PAGE_SIZE-2, "%d\n", NR_CPUS - 1);
     235                 :          0 :         return n;
     236                 :            : }
     237                 :            : static DEVICE_ATTR(kernel_max, 0444, print_cpus_kernel_max, NULL);
     238                 :            : 
     239                 :            : /* arch-optional setting to enable display of offline cpus >= nr_cpu_ids */
     240                 :            : unsigned int total_cpus;
     241                 :            : 
     242                 :          0 : static ssize_t print_cpus_offline(struct device *dev,
     243                 :            :                                   struct device_attribute *attr, char *buf)
     244                 :            : {
     245                 :          0 :         int n = 0, len = PAGE_SIZE-2;
     246                 :          0 :         cpumask_var_t offline;
     247                 :            : 
     248                 :            :         /* display offline cpus < nr_cpu_ids */
     249                 :          0 :         if (!alloc_cpumask_var(&offline, GFP_KERNEL))
     250                 :            :                 return -ENOMEM;
     251                 :          0 :         cpumask_andnot(offline, cpu_possible_mask, cpu_online_mask);
     252                 :          0 :         n = scnprintf(buf, len, "%*pbl", cpumask_pr_args(offline));
     253         [ #  # ]:          0 :         free_cpumask_var(offline);
     254                 :            : 
     255                 :            :         /* display offline cpus >= nr_cpu_ids */
     256   [ #  #  #  # ]:          0 :         if (total_cpus && nr_cpu_ids < total_cpus) {
     257         [ #  # ]:          0 :                 if (n && n < len)
     258                 :          0 :                         buf[n++] = ',';
     259                 :            : 
     260         [ #  # ]:          0 :                 if (nr_cpu_ids == total_cpus-1)
     261                 :          0 :                         n += snprintf(&buf[n], len - n, "%u", nr_cpu_ids);
     262                 :            :                 else
     263                 :          0 :                         n += snprintf(&buf[n], len - n, "%u-%d",
     264                 :            :                                                       nr_cpu_ids, total_cpus-1);
     265                 :            :         }
     266                 :            : 
     267                 :          0 :         n += snprintf(&buf[n], len - n, "\n");
     268                 :          0 :         return n;
     269                 :            : }
     270                 :            : static DEVICE_ATTR(offline, 0444, print_cpus_offline, NULL);
     271                 :            : 
     272                 :          0 : static ssize_t print_cpus_isolated(struct device *dev,
     273                 :            :                                   struct device_attribute *attr, char *buf)
     274                 :            : {
     275                 :          0 :         int n = 0, len = PAGE_SIZE-2;
     276                 :          0 :         cpumask_var_t isolated;
     277                 :            : 
     278                 :          0 :         if (!alloc_cpumask_var(&isolated, GFP_KERNEL))
     279                 :            :                 return -ENOMEM;
     280                 :            : 
     281                 :          0 :         cpumask_andnot(isolated, cpu_possible_mask,
     282                 :            :                        housekeeping_cpumask(HK_FLAG_DOMAIN));
     283                 :          0 :         n = scnprintf(buf, len, "%*pbl\n", cpumask_pr_args(isolated));
     284                 :            : 
     285                 :          0 :         free_cpumask_var(isolated);
     286                 :            : 
     287                 :          0 :         return n;
     288                 :            : }
     289                 :            : static DEVICE_ATTR(isolated, 0444, print_cpus_isolated, NULL);
     290                 :            : 
     291                 :            : #ifdef CONFIG_NO_HZ_FULL
     292                 :            : static ssize_t print_cpus_nohz_full(struct device *dev,
     293                 :            :                                   struct device_attribute *attr, char *buf)
     294                 :            : {
     295                 :            :         int n = 0, len = PAGE_SIZE-2;
     296                 :            : 
     297                 :            :         n = scnprintf(buf, len, "%*pbl\n", cpumask_pr_args(tick_nohz_full_mask));
     298                 :            : 
     299                 :            :         return n;
     300                 :            : }
     301                 :            : static DEVICE_ATTR(nohz_full, 0444, print_cpus_nohz_full, NULL);
     302                 :            : #endif
     303                 :            : 
     304                 :          0 : static void cpu_device_release(struct device *dev)
     305                 :            : {
     306                 :            :         /*
     307                 :            :          * This is an empty function to prevent the driver core from spitting a
     308                 :            :          * warning at us.  Yes, I know this is directly opposite of what the
     309                 :            :          * documentation for the driver core and kobjects say, and the author
     310                 :            :          * of this code has already been publically ridiculed for doing
     311                 :            :          * something as foolish as this.  However, at this point in time, it is
     312                 :            :          * the only way to handle the issue of statically allocated cpu
     313                 :            :          * devices.  The different architectures will have their cpu device
     314                 :            :          * code reworked to properly handle this in the near future, so this
     315                 :            :          * function will then be changed to correctly free up the memory held
     316                 :            :          * by the cpu device.
     317                 :            :          *
     318                 :            :          * Never copy this way of doing things, or you too will be made fun of
     319                 :            :          * on the linux-kernel list, you have been warned.
     320                 :            :          */
     321                 :          0 : }
     322                 :            : 
     323                 :            : #ifdef CONFIG_GENERIC_CPU_AUTOPROBE
     324                 :        150 : static ssize_t print_cpu_modalias(struct device *dev,
     325                 :            :                                   struct device_attribute *attr,
     326                 :            :                                   char *buf)
     327                 :            : {
     328                 :        150 :         ssize_t n;
     329                 :        150 :         u32 i;
     330                 :            : 
     331                 :        150 :         n = sprintf(buf, "cpu:type:" CPU_FEATURE_TYPEFMT ":feature:",
     332                 :        150 :                     CPU_FEATURE_TYPEVAL);
     333                 :            : 
     334         [ +  + ]:      91350 :         for (i = 0; i < MAX_CPU_FEATURES; i++)
     335   [ -  +  -  -  :      91200 :                 if (cpu_have_feature(i)) {
          -  -  -  -  -  
          -  -  -  -  -  
                   +  + ]
     336         [ -  + ]:       8550 :                         if (PAGE_SIZE < n + sizeof(",XXXX\n")) {
     337                 :          0 :                                 WARN(1, "CPU features overflow page\n");
     338                 :          0 :                                 break;
     339                 :            :                         }
     340                 :       8550 :                         n += sprintf(&buf[n], ",%04X", i);
     341                 :            :                 }
     342                 :        150 :         buf[n++] = '\n';
     343                 :        150 :         return n;
     344                 :            : }
     345                 :            : 
     346                 :        150 : static int cpu_uevent(struct device *dev, struct kobj_uevent_env *env)
     347                 :            : {
     348                 :        150 :         char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
     349         [ +  - ]:        150 :         if (buf) {
     350                 :        150 :                 print_cpu_modalias(NULL, NULL, buf);
     351                 :        150 :                 add_uevent_var(env, "MODALIAS=%s", buf);
     352                 :        150 :                 kfree(buf);
     353                 :            :         }
     354                 :        150 :         return 0;
     355                 :            : }
     356                 :            : #endif
     357                 :            : 
     358                 :            : /*
     359                 :            :  * register_cpu - Setup a sysfs device for a CPU.
     360                 :            :  * @cpu - cpu->hotpluggable field set to 1 will generate a control file in
     361                 :            :  *        sysfs for this CPU.
     362                 :            :  * @num - CPU number to use when creating the device.
     363                 :            :  *
     364                 :            :  * Initialize and register the CPU device.
     365                 :            :  */
     366                 :         30 : int register_cpu(struct cpu *cpu, int num)
     367                 :            : {
     368                 :         30 :         int error;
     369                 :            : 
     370                 :         30 :         cpu->node_id = cpu_to_node(num);
     371                 :         30 :         memset(&cpu->dev, 0x00, sizeof(struct device));
     372                 :         30 :         cpu->dev.id = num;
     373                 :         30 :         cpu->dev.bus = &cpu_subsys;
     374                 :         30 :         cpu->dev.release = cpu_device_release;
     375                 :         30 :         cpu->dev.offline_disabled = !cpu->hotpluggable;
     376                 :         30 :         cpu->dev.offline = !cpu_online(num);
     377         [ -  + ]:         30 :         cpu->dev.of_node = of_get_cpu_node(num, NULL);
     378                 :            : #ifdef CONFIG_GENERIC_CPU_AUTOPROBE
     379                 :         30 :         cpu->dev.bus->uevent = cpu_uevent;
     380                 :            : #endif
     381                 :         30 :         cpu->dev.groups = common_cpu_attr_groups;
     382         [ -  + ]:         30 :         if (cpu->hotpluggable)
     383                 :          0 :                 cpu->dev.groups = hotplugable_cpu_attr_groups;
     384                 :         30 :         error = device_register(&cpu->dev);
     385         [ -  + ]:         30 :         if (error) {
     386                 :          0 :                 put_device(&cpu->dev);
     387                 :          0 :                 return error;
     388                 :            :         }
     389                 :            : 
     390                 :         30 :         per_cpu(cpu_sys_devices, num) = &cpu->dev;
     391                 :         30 :         register_cpu_under_node(num, cpu_to_node(num));
     392                 :         30 :         dev_pm_qos_expose_latency_limit(&cpu->dev,
     393                 :            :                                         PM_QOS_RESUME_LATENCY_NO_CONSTRAINT);
     394                 :            : 
     395                 :         30 :         return 0;
     396                 :            : }
     397                 :            : 
     398                 :        240 : struct device *get_cpu_device(unsigned cpu)
     399                 :            : {
     400   [ +  -  +  - ]:        480 :         if (cpu < nr_cpu_ids && cpu_possible(cpu))
     401                 :        240 :                 return per_cpu(cpu_sys_devices, cpu);
     402                 :            :         else
     403                 :          0 :                 return NULL;
     404                 :            : }
     405                 :            : EXPORT_SYMBOL_GPL(get_cpu_device);
     406                 :            : 
     407                 :          0 : static void device_create_release(struct device *dev)
     408                 :            : {
     409                 :          0 :         kfree(dev);
     410                 :          0 : }
     411                 :            : 
     412                 :            : __printf(4, 0)
     413                 :            : static struct device *
     414                 :        150 : __cpu_device_create(struct device *parent, void *drvdata,
     415                 :            :                     const struct attribute_group **groups,
     416                 :            :                     const char *fmt, va_list args)
     417                 :            : {
     418                 :        150 :         struct device *dev = NULL;
     419                 :        150 :         int retval = -ENODEV;
     420                 :            : 
     421                 :        150 :         dev = kzalloc(sizeof(*dev), GFP_KERNEL);
     422         [ -  + ]:        150 :         if (!dev) {
     423                 :          0 :                 retval = -ENOMEM;
     424                 :          0 :                 goto error;
     425                 :            :         }
     426                 :            : 
     427                 :        150 :         device_initialize(dev);
     428                 :        150 :         dev->parent = parent;
     429                 :        150 :         dev->groups = groups;
     430                 :        150 :         dev->release = device_create_release;
     431                 :        150 :         device_set_pm_not_required(dev);
     432                 :        150 :         dev_set_drvdata(dev, drvdata);
     433                 :            : 
     434                 :        150 :         retval = kobject_set_name_vargs(&dev->kobj, fmt, args);
     435         [ -  + ]:        150 :         if (retval)
     436                 :          0 :                 goto error;
     437                 :            : 
     438                 :        150 :         retval = device_add(dev);
     439         [ -  + ]:        150 :         if (retval)
     440                 :          0 :                 goto error;
     441                 :            : 
     442                 :            :         return dev;
     443                 :            : 
     444                 :          0 : error:
     445                 :          0 :         put_device(dev);
     446                 :          0 :         return ERR_PTR(retval);
     447                 :            : }
     448                 :            : 
     449                 :        150 : struct device *cpu_device_create(struct device *parent, void *drvdata,
     450                 :            :                                  const struct attribute_group **groups,
     451                 :            :                                  const char *fmt, ...)
     452                 :            : {
     453                 :        150 :         va_list vargs;
     454                 :        150 :         struct device *dev;
     455                 :            : 
     456                 :        150 :         va_start(vargs, fmt);
     457                 :        150 :         dev = __cpu_device_create(parent, drvdata, groups, fmt, vargs);
     458                 :        150 :         va_end(vargs);
     459                 :        150 :         return dev;
     460                 :            : }
     461                 :            : EXPORT_SYMBOL_GPL(cpu_device_create);
     462                 :            : 
     463                 :            : #ifdef CONFIG_GENERIC_CPU_AUTOPROBE
     464                 :            : static DEVICE_ATTR(modalias, 0444, print_cpu_modalias, NULL);
     465                 :            : #endif
     466                 :            : 
     467                 :            : static struct attribute *cpu_root_attrs[] = {
     468                 :            : #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
     469                 :            :         &dev_attr_probe.attr,
     470                 :            :         &dev_attr_release.attr,
     471                 :            : #endif
     472                 :            :         &cpu_attrs[0].attr.attr,
     473                 :            :         &cpu_attrs[1].attr.attr,
     474                 :            :         &cpu_attrs[2].attr.attr,
     475                 :            :         &dev_attr_kernel_max.attr,
     476                 :            :         &dev_attr_offline.attr,
     477                 :            :         &dev_attr_isolated.attr,
     478                 :            : #ifdef CONFIG_NO_HZ_FULL
     479                 :            :         &dev_attr_nohz_full.attr,
     480                 :            : #endif
     481                 :            : #ifdef CONFIG_GENERIC_CPU_AUTOPROBE
     482                 :            :         &dev_attr_modalias.attr,
     483                 :            : #endif
     484                 :            :         NULL
     485                 :            : };
     486                 :            : 
     487                 :            : static struct attribute_group cpu_root_attr_group = {
     488                 :            :         .attrs = cpu_root_attrs,
     489                 :            : };
     490                 :            : 
     491                 :            : static const struct attribute_group *cpu_root_attr_groups[] = {
     492                 :            :         &cpu_root_attr_group,
     493                 :            :         NULL,
     494                 :            : };
     495                 :            : 
     496                 :          0 : bool cpu_is_hotpluggable(unsigned cpu)
     497                 :            : {
     498                 :          0 :         struct device *dev = get_cpu_device(cpu);
     499   [ #  #  #  # ]:          0 :         return dev && container_of(dev, struct cpu, dev)->hotpluggable;
     500                 :            : }
     501                 :            : EXPORT_SYMBOL_GPL(cpu_is_hotpluggable);
     502                 :            : 
     503                 :            : #ifdef CONFIG_GENERIC_CPU_DEVICES
     504                 :            : static DEFINE_PER_CPU(struct cpu, cpu_devices);
     505                 :            : #endif
     506                 :            : 
     507                 :         30 : static void __init cpu_dev_register_generic(void)
     508                 :            : {
     509                 :            : #ifdef CONFIG_GENERIC_CPU_DEVICES
     510                 :            :         int i;
     511                 :            : 
     512                 :            :         for_each_possible_cpu(i) {
     513                 :            :                 if (register_cpu(&per_cpu(cpu_devices, i), i))
     514                 :            :                         panic("Failed to register CPU device");
     515                 :            :         }
     516                 :            : #endif
     517                 :         30 : }
     518                 :            : 
     519                 :            : #ifdef CONFIG_GENERIC_CPU_VULNERABILITIES
     520                 :            : 
     521                 :          0 : ssize_t __weak cpu_show_meltdown(struct device *dev,
     522                 :            :                                  struct device_attribute *attr, char *buf)
     523                 :            : {
     524                 :          0 :         return sprintf(buf, "Not affected\n");
     525                 :            : }
     526                 :            : 
     527                 :          0 : ssize_t __weak cpu_show_spectre_v1(struct device *dev,
     528                 :            :                                    struct device_attribute *attr, char *buf)
     529                 :            : {
     530                 :          0 :         return sprintf(buf, "Not affected\n");
     531                 :            : }
     532                 :            : 
     533                 :          0 : ssize_t __weak cpu_show_spectre_v2(struct device *dev,
     534                 :            :                                    struct device_attribute *attr, char *buf)
     535                 :            : {
     536                 :          0 :         return sprintf(buf, "Not affected\n");
     537                 :            : }
     538                 :            : 
     539                 :          0 : ssize_t __weak cpu_show_spec_store_bypass(struct device *dev,
     540                 :            :                                           struct device_attribute *attr, char *buf)
     541                 :            : {
     542                 :          0 :         return sprintf(buf, "Not affected\n");
     543                 :            : }
     544                 :            : 
     545                 :          0 : ssize_t __weak cpu_show_l1tf(struct device *dev,
     546                 :            :                              struct device_attribute *attr, char *buf)
     547                 :            : {
     548                 :          0 :         return sprintf(buf, "Not affected\n");
     549                 :            : }
     550                 :            : 
     551                 :          0 : ssize_t __weak cpu_show_mds(struct device *dev,
     552                 :            :                             struct device_attribute *attr, char *buf)
     553                 :            : {
     554                 :          0 :         return sprintf(buf, "Not affected\n");
     555                 :            : }
     556                 :            : 
     557                 :          0 : ssize_t __weak cpu_show_tsx_async_abort(struct device *dev,
     558                 :            :                                         struct device_attribute *attr,
     559                 :            :                                         char *buf)
     560                 :            : {
     561                 :          0 :         return sprintf(buf, "Not affected\n");
     562                 :            : }
     563                 :            : 
     564                 :          0 : ssize_t __weak cpu_show_itlb_multihit(struct device *dev,
     565                 :            :                             struct device_attribute *attr, char *buf)
     566                 :            : {
     567                 :          0 :         return sprintf(buf, "Not affected\n");
     568                 :            : }
     569                 :            : 
     570                 :            : static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL);
     571                 :            : static DEVICE_ATTR(spectre_v1, 0444, cpu_show_spectre_v1, NULL);
     572                 :            : static DEVICE_ATTR(spectre_v2, 0444, cpu_show_spectre_v2, NULL);
     573                 :            : static DEVICE_ATTR(spec_store_bypass, 0444, cpu_show_spec_store_bypass, NULL);
     574                 :            : static DEVICE_ATTR(l1tf, 0444, cpu_show_l1tf, NULL);
     575                 :            : static DEVICE_ATTR(mds, 0444, cpu_show_mds, NULL);
     576                 :            : static DEVICE_ATTR(tsx_async_abort, 0444, cpu_show_tsx_async_abort, NULL);
     577                 :            : static DEVICE_ATTR(itlb_multihit, 0444, cpu_show_itlb_multihit, NULL);
     578                 :            : 
     579                 :            : static struct attribute *cpu_root_vulnerabilities_attrs[] = {
     580                 :            :         &dev_attr_meltdown.attr,
     581                 :            :         &dev_attr_spectre_v1.attr,
     582                 :            :         &dev_attr_spectre_v2.attr,
     583                 :            :         &dev_attr_spec_store_bypass.attr,
     584                 :            :         &dev_attr_l1tf.attr,
     585                 :            :         &dev_attr_mds.attr,
     586                 :            :         &dev_attr_tsx_async_abort.attr,
     587                 :            :         &dev_attr_itlb_multihit.attr,
     588                 :            :         NULL
     589                 :            : };
     590                 :            : 
     591                 :            : static const struct attribute_group cpu_root_vulnerabilities_group = {
     592                 :            :         .name  = "vulnerabilities",
     593                 :            :         .attrs = cpu_root_vulnerabilities_attrs,
     594                 :            : };
     595                 :            : 
     596                 :         30 : static void __init cpu_register_vulnerabilities(void)
     597                 :            : {
     598         [ -  + ]:         30 :         if (sysfs_create_group(&cpu_subsys.dev_root->kobj,
     599                 :            :                                &cpu_root_vulnerabilities_group))
     600                 :          0 :                 pr_err("Unable to register CPU vulnerabilities\n");
     601                 :         30 : }
     602                 :            : 
     603                 :            : #else
     604                 :            : static inline void cpu_register_vulnerabilities(void) { }
     605                 :            : #endif
     606                 :            : 
     607                 :         30 : void __init cpu_dev_init(void)
     608                 :            : {
     609         [ -  + ]:         30 :         if (subsys_system_register(&cpu_subsys, cpu_root_attr_groups))
     610                 :          0 :                 panic("Failed to register CPU subsystem");
     611                 :            : 
     612                 :         30 :         cpu_dev_register_generic();
     613                 :         30 :         cpu_register_vulnerabilities();
     614                 :         30 : }

Generated by: LCOV version 1.14