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

sysfs.c (8448B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * RTC subsystem, sysfs interface
      4 *
      5 * Copyright (C) 2005 Tower Technologies
      6 * Author: Alessandro Zummo <a.zummo@towertech.it>
      7 */
      8
      9#include <linux/module.h>
     10#include <linux/rtc.h>
     11
     12#include "rtc-core.h"
     13
     14/* device attributes */
     15
     16/*
     17 * NOTE:  RTC times displayed in sysfs use the RTC's timezone.  That's
     18 * ideally UTC.  However, PCs that also boot to MS-Windows normally use
     19 * the local time and change to match daylight savings time.  That affects
     20 * attributes including date, time, since_epoch, and wakealarm.
     21 */
     22
     23static ssize_t
     24name_show(struct device *dev, struct device_attribute *attr, char *buf)
     25{
     26	return sprintf(buf, "%s %s\n", dev_driver_string(dev->parent),
     27		       dev_name(dev->parent));
     28}
     29static DEVICE_ATTR_RO(name);
     30
     31static ssize_t
     32date_show(struct device *dev, struct device_attribute *attr, char *buf)
     33{
     34	ssize_t retval;
     35	struct rtc_time tm;
     36
     37	retval = rtc_read_time(to_rtc_device(dev), &tm);
     38	if (retval)
     39		return retval;
     40
     41	return sprintf(buf, "%ptRd\n", &tm);
     42}
     43static DEVICE_ATTR_RO(date);
     44
     45static ssize_t
     46time_show(struct device *dev, struct device_attribute *attr, char *buf)
     47{
     48	ssize_t retval;
     49	struct rtc_time tm;
     50
     51	retval = rtc_read_time(to_rtc_device(dev), &tm);
     52	if (retval)
     53		return retval;
     54
     55	return sprintf(buf, "%ptRt\n", &tm);
     56}
     57static DEVICE_ATTR_RO(time);
     58
     59static ssize_t
     60since_epoch_show(struct device *dev, struct device_attribute *attr, char *buf)
     61{
     62	ssize_t retval;
     63	struct rtc_time tm;
     64
     65	retval = rtc_read_time(to_rtc_device(dev), &tm);
     66	if (retval == 0) {
     67		time64_t time;
     68
     69		time = rtc_tm_to_time64(&tm);
     70		retval = sprintf(buf, "%lld\n", time);
     71	}
     72
     73	return retval;
     74}
     75static DEVICE_ATTR_RO(since_epoch);
     76
     77static ssize_t
     78max_user_freq_show(struct device *dev, struct device_attribute *attr, char *buf)
     79{
     80	return sprintf(buf, "%d\n", to_rtc_device(dev)->max_user_freq);
     81}
     82
     83static ssize_t
     84max_user_freq_store(struct device *dev, struct device_attribute *attr,
     85		    const char *buf, size_t n)
     86{
     87	struct rtc_device *rtc = to_rtc_device(dev);
     88	unsigned long val;
     89	int err;
     90
     91	err = kstrtoul(buf, 0, &val);
     92	if (err)
     93		return err;
     94
     95	if (val >= 4096 || val == 0)
     96		return -EINVAL;
     97
     98	rtc->max_user_freq = (int)val;
     99
    100	return n;
    101}
    102static DEVICE_ATTR_RW(max_user_freq);
    103
    104/**
    105 * hctosys_show - indicate if the given RTC set the system time
    106 * @dev: The device that the attribute belongs to.
    107 * @attr: The attribute being read.
    108 * @buf: The result buffer.
    109 *
    110 * buf is "1" if the system clock was set by this RTC at the last
    111 * boot or resume event.
    112 */
    113static ssize_t
    114hctosys_show(struct device *dev, struct device_attribute *attr, char *buf)
    115{
    116#ifdef CONFIG_RTC_HCTOSYS_DEVICE
    117	if (rtc_hctosys_ret == 0 &&
    118	    strcmp(dev_name(&to_rtc_device(dev)->dev),
    119		   CONFIG_RTC_HCTOSYS_DEVICE) == 0)
    120		return sprintf(buf, "1\n");
    121#endif
    122	return sprintf(buf, "0\n");
    123}
    124static DEVICE_ATTR_RO(hctosys);
    125
    126static ssize_t
    127wakealarm_show(struct device *dev, struct device_attribute *attr, char *buf)
    128{
    129	ssize_t retval;
    130	time64_t alarm;
    131	struct rtc_wkalrm alm;
    132
    133	/* Don't show disabled alarms.  For uniformity, RTC alarms are
    134	 * conceptually one-shot, even though some common RTCs (on PCs)
    135	 * don't actually work that way.
    136	 *
    137	 * NOTE: RTC implementations where the alarm doesn't match an
    138	 * exact YYYY-MM-DD HH:MM[:SS] date *must* disable their RTC
    139	 * alarms after they trigger, to ensure one-shot semantics.
    140	 */
    141	retval = rtc_read_alarm(to_rtc_device(dev), &alm);
    142	if (retval == 0 && alm.enabled) {
    143		alarm = rtc_tm_to_time64(&alm.time);
    144		retval = sprintf(buf, "%lld\n", alarm);
    145	}
    146
    147	return retval;
    148}
    149
    150static ssize_t
    151wakealarm_store(struct device *dev, struct device_attribute *attr,
    152		const char *buf, size_t n)
    153{
    154	ssize_t retval;
    155	time64_t now, alarm;
    156	time64_t push = 0;
    157	struct rtc_wkalrm alm;
    158	struct rtc_device *rtc = to_rtc_device(dev);
    159	const char *buf_ptr;
    160	int adjust = 0;
    161
    162	/* Only request alarms that trigger in the future.  Disable them
    163	 * by writing another time, e.g. 0 meaning Jan 1 1970 UTC.
    164	 */
    165	retval = rtc_read_time(rtc, &alm.time);
    166	if (retval < 0)
    167		return retval;
    168	now = rtc_tm_to_time64(&alm.time);
    169
    170	buf_ptr = buf;
    171	if (*buf_ptr == '+') {
    172		buf_ptr++;
    173		if (*buf_ptr == '=') {
    174			buf_ptr++;
    175			push = 1;
    176		} else {
    177			adjust = 1;
    178		}
    179	}
    180	retval = kstrtos64(buf_ptr, 0, &alarm);
    181	if (retval)
    182		return retval;
    183	if (adjust)
    184		alarm += now;
    185	if (alarm > now || push) {
    186		/* Avoid accidentally clobbering active alarms; we can't
    187		 * entirely prevent that here, without even the minimal
    188		 * locking from the /dev/rtcN api.
    189		 */
    190		retval = rtc_read_alarm(rtc, &alm);
    191		if (retval < 0)
    192			return retval;
    193		if (alm.enabled) {
    194			if (push) {
    195				push = rtc_tm_to_time64(&alm.time);
    196				alarm += push;
    197			} else
    198				return -EBUSY;
    199		} else if (push)
    200			return -EINVAL;
    201		alm.enabled = 1;
    202	} else {
    203		alm.enabled = 0;
    204
    205		/* Provide a valid future alarm time.  Linux isn't EFI,
    206		 * this time won't be ignored when disabling the alarm.
    207		 */
    208		alarm = now + 300;
    209	}
    210	rtc_time64_to_tm(alarm, &alm.time);
    211
    212	retval = rtc_set_alarm(rtc, &alm);
    213	return (retval < 0) ? retval : n;
    214}
    215static DEVICE_ATTR_RW(wakealarm);
    216
    217static ssize_t
    218offset_show(struct device *dev, struct device_attribute *attr, char *buf)
    219{
    220	ssize_t retval;
    221	long offset;
    222
    223	retval = rtc_read_offset(to_rtc_device(dev), &offset);
    224	if (retval == 0)
    225		retval = sprintf(buf, "%ld\n", offset);
    226
    227	return retval;
    228}
    229
    230static ssize_t
    231offset_store(struct device *dev, struct device_attribute *attr,
    232	     const char *buf, size_t n)
    233{
    234	ssize_t retval;
    235	long offset;
    236
    237	retval = kstrtol(buf, 10, &offset);
    238	if (retval == 0)
    239		retval = rtc_set_offset(to_rtc_device(dev), offset);
    240
    241	return (retval < 0) ? retval : n;
    242}
    243static DEVICE_ATTR_RW(offset);
    244
    245static ssize_t
    246range_show(struct device *dev, struct device_attribute *attr, char *buf)
    247{
    248	return sprintf(buf, "[%lld,%llu]\n", to_rtc_device(dev)->range_min,
    249		       to_rtc_device(dev)->range_max);
    250}
    251static DEVICE_ATTR_RO(range);
    252
    253static struct attribute *rtc_attrs[] = {
    254	&dev_attr_name.attr,
    255	&dev_attr_date.attr,
    256	&dev_attr_time.attr,
    257	&dev_attr_since_epoch.attr,
    258	&dev_attr_max_user_freq.attr,
    259	&dev_attr_hctosys.attr,
    260	&dev_attr_wakealarm.attr,
    261	&dev_attr_offset.attr,
    262	&dev_attr_range.attr,
    263	NULL,
    264};
    265
    266/* The reason to trigger an alarm with no process watching it (via sysfs)
    267 * is its side effect:  waking from a system state like suspend-to-RAM or
    268 * suspend-to-disk.  So: no attribute unless that side effect is possible.
    269 * (Userspace may disable that mechanism later.)
    270 */
    271static bool rtc_does_wakealarm(struct rtc_device *rtc)
    272{
    273	if (!device_can_wakeup(rtc->dev.parent))
    274		return false;
    275
    276	return !!test_bit(RTC_FEATURE_ALARM, rtc->features);
    277}
    278
    279static umode_t rtc_attr_is_visible(struct kobject *kobj,
    280				   struct attribute *attr, int n)
    281{
    282	struct device *dev = kobj_to_dev(kobj);
    283	struct rtc_device *rtc = to_rtc_device(dev);
    284	umode_t mode = attr->mode;
    285
    286	if (attr == &dev_attr_wakealarm.attr) {
    287		if (!rtc_does_wakealarm(rtc))
    288			mode = 0;
    289	} else if (attr == &dev_attr_offset.attr) {
    290		if (!rtc->ops->set_offset)
    291			mode = 0;
    292	} else if (attr == &dev_attr_range.attr) {
    293		if (!(rtc->range_max - rtc->range_min))
    294			mode = 0;
    295	}
    296
    297	return mode;
    298}
    299
    300static struct attribute_group rtc_attr_group = {
    301	.is_visible	= rtc_attr_is_visible,
    302	.attrs		= rtc_attrs,
    303};
    304
    305static const struct attribute_group *rtc_attr_groups[] = {
    306	&rtc_attr_group,
    307	NULL
    308};
    309
    310const struct attribute_group **rtc_get_dev_attribute_groups(void)
    311{
    312	return rtc_attr_groups;
    313}
    314
    315int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps)
    316{
    317	size_t old_cnt = 0, add_cnt = 0, new_cnt;
    318	const struct attribute_group **groups, **old;
    319
    320	if (!grps)
    321		return -EINVAL;
    322
    323	groups = rtc->dev.groups;
    324	if (groups)
    325		for (; *groups; groups++)
    326			old_cnt++;
    327
    328	for (groups = grps; *groups; groups++)
    329		add_cnt++;
    330
    331	new_cnt = old_cnt + add_cnt + 1;
    332	groups = devm_kcalloc(&rtc->dev, new_cnt, sizeof(*groups), GFP_KERNEL);
    333	if (!groups)
    334		return -ENOMEM;
    335	memcpy(groups, rtc->dev.groups, old_cnt * sizeof(*groups));
    336	memcpy(groups + old_cnt, grps, add_cnt * sizeof(*groups));
    337	groups[old_cnt + add_cnt] = NULL;
    338
    339	old = rtc->dev.groups;
    340	rtc->dev.groups = groups;
    341	if (old && old != rtc_attr_groups)
    342		devm_kfree(&rtc->dev, old);
    343
    344	return 0;
    345}
    346EXPORT_SYMBOL(rtc_add_groups);
    347
    348int rtc_add_group(struct rtc_device *rtc, const struct attribute_group *grp)
    349{
    350	const struct attribute_group *groups[] = { grp, NULL };
    351
    352	return rtc_add_groups(rtc, groups);
    353}
    354EXPORT_SYMBOL(rtc_add_group);