cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

wakeup_stats.c (5464B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Wakeup statistics in sysfs
      4 *
      5 * Copyright (c) 2019 Linux Foundation
      6 * Copyright (c) 2019 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
      7 * Copyright (c) 2019 Google Inc.
      8 */
      9
     10#include <linux/device.h>
     11#include <linux/idr.h>
     12#include <linux/init.h>
     13#include <linux/kdev_t.h>
     14#include <linux/kernel.h>
     15#include <linux/kobject.h>
     16#include <linux/slab.h>
     17#include <linux/timekeeping.h>
     18
     19#include "power.h"
     20
     21static struct class *wakeup_class;
     22
     23#define wakeup_attr(_name)						\
     24static ssize_t _name##_show(struct device *dev,				\
     25			    struct device_attribute *attr, char *buf)	\
     26{									\
     27	struct wakeup_source *ws = dev_get_drvdata(dev);		\
     28									\
     29	return sysfs_emit(buf, "%lu\n", ws->_name);			\
     30}									\
     31static DEVICE_ATTR_RO(_name)
     32
     33wakeup_attr(active_count);
     34wakeup_attr(event_count);
     35wakeup_attr(wakeup_count);
     36wakeup_attr(expire_count);
     37
     38static ssize_t active_time_ms_show(struct device *dev,
     39				   struct device_attribute *attr, char *buf)
     40{
     41	struct wakeup_source *ws = dev_get_drvdata(dev);
     42	ktime_t active_time =
     43		ws->active ? ktime_sub(ktime_get(), ws->last_time) : 0;
     44
     45	return sysfs_emit(buf, "%lld\n", ktime_to_ms(active_time));
     46}
     47static DEVICE_ATTR_RO(active_time_ms);
     48
     49static ssize_t total_time_ms_show(struct device *dev,
     50				  struct device_attribute *attr, char *buf)
     51{
     52	struct wakeup_source *ws = dev_get_drvdata(dev);
     53	ktime_t active_time;
     54	ktime_t total_time = ws->total_time;
     55
     56	if (ws->active) {
     57		active_time = ktime_sub(ktime_get(), ws->last_time);
     58		total_time = ktime_add(total_time, active_time);
     59	}
     60
     61	return sysfs_emit(buf, "%lld\n", ktime_to_ms(total_time));
     62}
     63static DEVICE_ATTR_RO(total_time_ms);
     64
     65static ssize_t max_time_ms_show(struct device *dev,
     66				struct device_attribute *attr, char *buf)
     67{
     68	struct wakeup_source *ws = dev_get_drvdata(dev);
     69	ktime_t active_time;
     70	ktime_t max_time = ws->max_time;
     71
     72	if (ws->active) {
     73		active_time = ktime_sub(ktime_get(), ws->last_time);
     74		if (active_time > max_time)
     75			max_time = active_time;
     76	}
     77
     78	return sysfs_emit(buf, "%lld\n", ktime_to_ms(max_time));
     79}
     80static DEVICE_ATTR_RO(max_time_ms);
     81
     82static ssize_t last_change_ms_show(struct device *dev,
     83				   struct device_attribute *attr, char *buf)
     84{
     85	struct wakeup_source *ws = dev_get_drvdata(dev);
     86
     87	return sysfs_emit(buf, "%lld\n", ktime_to_ms(ws->last_time));
     88}
     89static DEVICE_ATTR_RO(last_change_ms);
     90
     91static ssize_t name_show(struct device *dev, struct device_attribute *attr,
     92			 char *buf)
     93{
     94	struct wakeup_source *ws = dev_get_drvdata(dev);
     95
     96	return sysfs_emit(buf, "%s\n", ws->name);
     97}
     98static DEVICE_ATTR_RO(name);
     99
    100static ssize_t prevent_suspend_time_ms_show(struct device *dev,
    101					    struct device_attribute *attr,
    102					    char *buf)
    103{
    104	struct wakeup_source *ws = dev_get_drvdata(dev);
    105	ktime_t prevent_sleep_time = ws->prevent_sleep_time;
    106
    107	if (ws->active && ws->autosleep_enabled) {
    108		prevent_sleep_time = ktime_add(prevent_sleep_time,
    109			ktime_sub(ktime_get(), ws->start_prevent_time));
    110	}
    111
    112	return sysfs_emit(buf, "%lld\n", ktime_to_ms(prevent_sleep_time));
    113}
    114static DEVICE_ATTR_RO(prevent_suspend_time_ms);
    115
    116static struct attribute *wakeup_source_attrs[] = {
    117	&dev_attr_name.attr,
    118	&dev_attr_active_count.attr,
    119	&dev_attr_event_count.attr,
    120	&dev_attr_wakeup_count.attr,
    121	&dev_attr_expire_count.attr,
    122	&dev_attr_active_time_ms.attr,
    123	&dev_attr_total_time_ms.attr,
    124	&dev_attr_max_time_ms.attr,
    125	&dev_attr_last_change_ms.attr,
    126	&dev_attr_prevent_suspend_time_ms.attr,
    127	NULL,
    128};
    129ATTRIBUTE_GROUPS(wakeup_source);
    130
    131static void device_create_release(struct device *dev)
    132{
    133	kfree(dev);
    134}
    135
    136static struct device *wakeup_source_device_create(struct device *parent,
    137						  struct wakeup_source *ws)
    138{
    139	struct device *dev = NULL;
    140	int retval;
    141
    142	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
    143	if (!dev) {
    144		retval = -ENOMEM;
    145		goto error;
    146	}
    147
    148	device_initialize(dev);
    149	dev->devt = MKDEV(0, 0);
    150	dev->class = wakeup_class;
    151	dev->parent = parent;
    152	dev->groups = wakeup_source_groups;
    153	dev->release = device_create_release;
    154	dev_set_drvdata(dev, ws);
    155	device_set_pm_not_required(dev);
    156
    157	retval = dev_set_name(dev, "wakeup%d", ws->id);
    158	if (retval)
    159		goto error;
    160
    161	retval = device_add(dev);
    162	if (retval)
    163		goto error;
    164
    165	return dev;
    166
    167error:
    168	put_device(dev);
    169	return ERR_PTR(retval);
    170}
    171
    172/**
    173 * wakeup_source_sysfs_add - Add wakeup_source attributes to sysfs.
    174 * @parent: Device given wakeup source is associated with (or NULL if virtual).
    175 * @ws: Wakeup source to be added in sysfs.
    176 */
    177int wakeup_source_sysfs_add(struct device *parent, struct wakeup_source *ws)
    178{
    179	struct device *dev;
    180
    181	dev = wakeup_source_device_create(parent, ws);
    182	if (IS_ERR(dev))
    183		return PTR_ERR(dev);
    184	ws->dev = dev;
    185
    186	return 0;
    187}
    188
    189/**
    190 * pm_wakeup_source_sysfs_add - Add wakeup_source attributes to sysfs
    191 * for a device if they're missing.
    192 * @parent: Device given wakeup source is associated with
    193 */
    194int pm_wakeup_source_sysfs_add(struct device *parent)
    195{
    196	if (!parent->power.wakeup || parent->power.wakeup->dev)
    197		return 0;
    198
    199	return wakeup_source_sysfs_add(parent, parent->power.wakeup);
    200}
    201
    202/**
    203 * wakeup_source_sysfs_remove - Remove wakeup_source attributes from sysfs.
    204 * @ws: Wakeup source to be removed from sysfs.
    205 */
    206void wakeup_source_sysfs_remove(struct wakeup_source *ws)
    207{
    208	device_unregister(ws->dev);
    209}
    210
    211static int __init wakeup_sources_sysfs_init(void)
    212{
    213	wakeup_class = class_create(THIS_MODULE, "wakeup");
    214
    215	return PTR_ERR_OR_ZERO(wakeup_class);
    216}
    217postcore_initcall(wakeup_sources_sysfs_init);