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

ptp_clock.c (11643B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * PTP 1588 clock support
      4 *
      5 * Copyright (C) 2010 OMICRON electronics GmbH
      6 */
      7#include <linux/idr.h>
      8#include <linux/device.h>
      9#include <linux/err.h>
     10#include <linux/init.h>
     11#include <linux/kernel.h>
     12#include <linux/module.h>
     13#include <linux/posix-clock.h>
     14#include <linux/pps_kernel.h>
     15#include <linux/slab.h>
     16#include <linux/syscalls.h>
     17#include <linux/uaccess.h>
     18#include <uapi/linux/sched/types.h>
     19
     20#include "ptp_private.h"
     21
     22#define PTP_MAX_ALARMS 4
     23#define PTP_PPS_DEFAULTS (PPS_CAPTUREASSERT | PPS_OFFSETASSERT)
     24#define PTP_PPS_EVENT PPS_CAPTUREASSERT
     25#define PTP_PPS_MODE (PTP_PPS_DEFAULTS | PPS_CANWAIT | PPS_TSFMT_TSPEC)
     26
     27struct class *ptp_class;
     28
     29/* private globals */
     30
     31static dev_t ptp_devt;
     32
     33static DEFINE_IDA(ptp_clocks_map);
     34
     35/* time stamp event queue operations */
     36
     37static inline int queue_free(struct timestamp_event_queue *q)
     38{
     39	return PTP_MAX_TIMESTAMPS - queue_cnt(q) - 1;
     40}
     41
     42static void enqueue_external_timestamp(struct timestamp_event_queue *queue,
     43				       struct ptp_clock_event *src)
     44{
     45	struct ptp_extts_event *dst;
     46	unsigned long flags;
     47	s64 seconds;
     48	u32 remainder;
     49
     50	seconds = div_u64_rem(src->timestamp, 1000000000, &remainder);
     51
     52	spin_lock_irqsave(&queue->lock, flags);
     53
     54	dst = &queue->buf[queue->tail];
     55	dst->index = src->index;
     56	dst->t.sec = seconds;
     57	dst->t.nsec = remainder;
     58
     59	if (!queue_free(queue))
     60		queue->head = (queue->head + 1) % PTP_MAX_TIMESTAMPS;
     61
     62	queue->tail = (queue->tail + 1) % PTP_MAX_TIMESTAMPS;
     63
     64	spin_unlock_irqrestore(&queue->lock, flags);
     65}
     66
     67/* posix clock implementation */
     68
     69static int ptp_clock_getres(struct posix_clock *pc, struct timespec64 *tp)
     70{
     71	tp->tv_sec = 0;
     72	tp->tv_nsec = 1;
     73	return 0;
     74}
     75
     76static int ptp_clock_settime(struct posix_clock *pc, const struct timespec64 *tp)
     77{
     78	struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
     79
     80	if (ptp_clock_freerun(ptp)) {
     81		pr_err("ptp: physical clock is free running\n");
     82		return -EBUSY;
     83	}
     84
     85	return  ptp->info->settime64(ptp->info, tp);
     86}
     87
     88static int ptp_clock_gettime(struct posix_clock *pc, struct timespec64 *tp)
     89{
     90	struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
     91	int err;
     92
     93	if (ptp->info->gettimex64)
     94		err = ptp->info->gettimex64(ptp->info, tp, NULL);
     95	else
     96		err = ptp->info->gettime64(ptp->info, tp);
     97	return err;
     98}
     99
    100static int ptp_clock_adjtime(struct posix_clock *pc, struct __kernel_timex *tx)
    101{
    102	struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
    103	struct ptp_clock_info *ops;
    104	int err = -EOPNOTSUPP;
    105
    106	if (ptp_clock_freerun(ptp)) {
    107		pr_err("ptp: physical clock is free running\n");
    108		return -EBUSY;
    109	}
    110
    111	ops = ptp->info;
    112
    113	if (tx->modes & ADJ_SETOFFSET) {
    114		struct timespec64 ts;
    115		ktime_t kt;
    116		s64 delta;
    117
    118		ts.tv_sec  = tx->time.tv_sec;
    119		ts.tv_nsec = tx->time.tv_usec;
    120
    121		if (!(tx->modes & ADJ_NANO))
    122			ts.tv_nsec *= 1000;
    123
    124		if ((unsigned long) ts.tv_nsec >= NSEC_PER_SEC)
    125			return -EINVAL;
    126
    127		kt = timespec64_to_ktime(ts);
    128		delta = ktime_to_ns(kt);
    129		err = ops->adjtime(ops, delta);
    130	} else if (tx->modes & ADJ_FREQUENCY) {
    131		long ppb = scaled_ppm_to_ppb(tx->freq);
    132		if (ppb > ops->max_adj || ppb < -ops->max_adj)
    133			return -ERANGE;
    134		if (ops->adjfine)
    135			err = ops->adjfine(ops, tx->freq);
    136		else
    137			err = ops->adjfreq(ops, ppb);
    138		ptp->dialed_frequency = tx->freq;
    139	} else if (tx->modes & ADJ_OFFSET) {
    140		if (ops->adjphase) {
    141			s32 offset = tx->offset;
    142
    143			if (!(tx->modes & ADJ_NANO))
    144				offset *= NSEC_PER_USEC;
    145
    146			err = ops->adjphase(ops, offset);
    147		}
    148	} else if (tx->modes == 0) {
    149		tx->freq = ptp->dialed_frequency;
    150		err = 0;
    151	}
    152
    153	return err;
    154}
    155
    156static struct posix_clock_operations ptp_clock_ops = {
    157	.owner		= THIS_MODULE,
    158	.clock_adjtime	= ptp_clock_adjtime,
    159	.clock_gettime	= ptp_clock_gettime,
    160	.clock_getres	= ptp_clock_getres,
    161	.clock_settime	= ptp_clock_settime,
    162	.ioctl		= ptp_ioctl,
    163	.open		= ptp_open,
    164	.poll		= ptp_poll,
    165	.read		= ptp_read,
    166};
    167
    168static void ptp_clock_release(struct device *dev)
    169{
    170	struct ptp_clock *ptp = container_of(dev, struct ptp_clock, dev);
    171
    172	ptp_cleanup_pin_groups(ptp);
    173	kfree(ptp->vclock_index);
    174	mutex_destroy(&ptp->tsevq_mux);
    175	mutex_destroy(&ptp->pincfg_mux);
    176	mutex_destroy(&ptp->n_vclocks_mux);
    177	ida_simple_remove(&ptp_clocks_map, ptp->index);
    178	kfree(ptp);
    179}
    180
    181static int ptp_getcycles64(struct ptp_clock_info *info, struct timespec64 *ts)
    182{
    183	if (info->getcyclesx64)
    184		return info->getcyclesx64(info, ts, NULL);
    185	else
    186		return info->gettime64(info, ts);
    187}
    188
    189static void ptp_aux_kworker(struct kthread_work *work)
    190{
    191	struct ptp_clock *ptp = container_of(work, struct ptp_clock,
    192					     aux_work.work);
    193	struct ptp_clock_info *info = ptp->info;
    194	long delay;
    195
    196	delay = info->do_aux_work(info);
    197
    198	if (delay >= 0)
    199		kthread_queue_delayed_work(ptp->kworker, &ptp->aux_work, delay);
    200}
    201
    202/* public interface */
    203
    204struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
    205				     struct device *parent)
    206{
    207	struct ptp_clock *ptp;
    208	int err = 0, index, major = MAJOR(ptp_devt);
    209	size_t size;
    210
    211	if (info->n_alarm > PTP_MAX_ALARMS)
    212		return ERR_PTR(-EINVAL);
    213
    214	/* Initialize a clock structure. */
    215	err = -ENOMEM;
    216	ptp = kzalloc(sizeof(struct ptp_clock), GFP_KERNEL);
    217	if (ptp == NULL)
    218		goto no_memory;
    219
    220	index = ida_simple_get(&ptp_clocks_map, 0, MINORMASK + 1, GFP_KERNEL);
    221	if (index < 0) {
    222		err = index;
    223		goto no_slot;
    224	}
    225
    226	ptp->clock.ops = ptp_clock_ops;
    227	ptp->info = info;
    228	ptp->devid = MKDEV(major, index);
    229	ptp->index = index;
    230	spin_lock_init(&ptp->tsevq.lock);
    231	mutex_init(&ptp->tsevq_mux);
    232	mutex_init(&ptp->pincfg_mux);
    233	mutex_init(&ptp->n_vclocks_mux);
    234	init_waitqueue_head(&ptp->tsev_wq);
    235
    236	if (ptp->info->getcycles64 || ptp->info->getcyclesx64) {
    237		ptp->has_cycles = true;
    238		if (!ptp->info->getcycles64 && ptp->info->getcyclesx64)
    239			ptp->info->getcycles64 = ptp_getcycles64;
    240	} else {
    241		/* Free running cycle counter not supported, use time. */
    242		ptp->info->getcycles64 = ptp_getcycles64;
    243
    244		if (ptp->info->gettimex64)
    245			ptp->info->getcyclesx64 = ptp->info->gettimex64;
    246
    247		if (ptp->info->getcrosststamp)
    248			ptp->info->getcrosscycles = ptp->info->getcrosststamp;
    249	}
    250
    251	if (ptp->info->do_aux_work) {
    252		kthread_init_delayed_work(&ptp->aux_work, ptp_aux_kworker);
    253		ptp->kworker = kthread_create_worker(0, "ptp%d", ptp->index);
    254		if (IS_ERR(ptp->kworker)) {
    255			err = PTR_ERR(ptp->kworker);
    256			pr_err("failed to create ptp aux_worker %d\n", err);
    257			goto kworker_err;
    258		}
    259	}
    260
    261	/* PTP virtual clock is being registered under physical clock */
    262	if (parent && parent->class && parent->class->name &&
    263	    strcmp(parent->class->name, "ptp") == 0)
    264		ptp->is_virtual_clock = true;
    265
    266	if (!ptp->is_virtual_clock) {
    267		ptp->max_vclocks = PTP_DEFAULT_MAX_VCLOCKS;
    268
    269		size = sizeof(int) * ptp->max_vclocks;
    270		ptp->vclock_index = kzalloc(size, GFP_KERNEL);
    271		if (!ptp->vclock_index) {
    272			err = -ENOMEM;
    273			goto no_mem_for_vclocks;
    274		}
    275	}
    276
    277	err = ptp_populate_pin_groups(ptp);
    278	if (err)
    279		goto no_pin_groups;
    280
    281	/* Register a new PPS source. */
    282	if (info->pps) {
    283		struct pps_source_info pps;
    284		memset(&pps, 0, sizeof(pps));
    285		snprintf(pps.name, PPS_MAX_NAME_LEN, "ptp%d", index);
    286		pps.mode = PTP_PPS_MODE;
    287		pps.owner = info->owner;
    288		ptp->pps_source = pps_register_source(&pps, PTP_PPS_DEFAULTS);
    289		if (IS_ERR(ptp->pps_source)) {
    290			err = PTR_ERR(ptp->pps_source);
    291			pr_err("failed to register pps source\n");
    292			goto no_pps;
    293		}
    294		ptp->pps_source->lookup_cookie = ptp;
    295	}
    296
    297	/* Initialize a new device of our class in our clock structure. */
    298	device_initialize(&ptp->dev);
    299	ptp->dev.devt = ptp->devid;
    300	ptp->dev.class = ptp_class;
    301	ptp->dev.parent = parent;
    302	ptp->dev.groups = ptp->pin_attr_groups;
    303	ptp->dev.release = ptp_clock_release;
    304	dev_set_drvdata(&ptp->dev, ptp);
    305	dev_set_name(&ptp->dev, "ptp%d", ptp->index);
    306
    307	/* Create a posix clock and link it to the device. */
    308	err = posix_clock_register(&ptp->clock, &ptp->dev);
    309	if (err) {
    310		if (ptp->pps_source)
    311			pps_unregister_source(ptp->pps_source);
    312
    313		if (ptp->kworker)
    314			kthread_destroy_worker(ptp->kworker);
    315
    316		put_device(&ptp->dev);
    317
    318		pr_err("failed to create posix clock\n");
    319		return ERR_PTR(err);
    320	}
    321
    322	return ptp;
    323
    324no_pps:
    325	ptp_cleanup_pin_groups(ptp);
    326no_pin_groups:
    327	kfree(ptp->vclock_index);
    328no_mem_for_vclocks:
    329	if (ptp->kworker)
    330		kthread_destroy_worker(ptp->kworker);
    331kworker_err:
    332	mutex_destroy(&ptp->tsevq_mux);
    333	mutex_destroy(&ptp->pincfg_mux);
    334	mutex_destroy(&ptp->n_vclocks_mux);
    335	ida_simple_remove(&ptp_clocks_map, index);
    336no_slot:
    337	kfree(ptp);
    338no_memory:
    339	return ERR_PTR(err);
    340}
    341EXPORT_SYMBOL(ptp_clock_register);
    342
    343static int unregister_vclock(struct device *dev, void *data)
    344{
    345	struct ptp_clock *ptp = dev_get_drvdata(dev);
    346
    347	ptp_vclock_unregister(info_to_vclock(ptp->info));
    348	return 0;
    349}
    350
    351int ptp_clock_unregister(struct ptp_clock *ptp)
    352{
    353	if (ptp_vclock_in_use(ptp)) {
    354		device_for_each_child(&ptp->dev, NULL, unregister_vclock);
    355	}
    356
    357	ptp->defunct = 1;
    358	wake_up_interruptible(&ptp->tsev_wq);
    359
    360	if (ptp->kworker) {
    361		kthread_cancel_delayed_work_sync(&ptp->aux_work);
    362		kthread_destroy_worker(ptp->kworker);
    363	}
    364
    365	/* Release the clock's resources. */
    366	if (ptp->pps_source)
    367		pps_unregister_source(ptp->pps_source);
    368
    369	posix_clock_unregister(&ptp->clock);
    370
    371	return 0;
    372}
    373EXPORT_SYMBOL(ptp_clock_unregister);
    374
    375void ptp_clock_event(struct ptp_clock *ptp, struct ptp_clock_event *event)
    376{
    377	struct pps_event_time evt;
    378
    379	switch (event->type) {
    380
    381	case PTP_CLOCK_ALARM:
    382		break;
    383
    384	case PTP_CLOCK_EXTTS:
    385		enqueue_external_timestamp(&ptp->tsevq, event);
    386		wake_up_interruptible(&ptp->tsev_wq);
    387		break;
    388
    389	case PTP_CLOCK_PPS:
    390		pps_get_ts(&evt);
    391		pps_event(ptp->pps_source, &evt, PTP_PPS_EVENT, NULL);
    392		break;
    393
    394	case PTP_CLOCK_PPSUSR:
    395		pps_event(ptp->pps_source, &event->pps_times,
    396			  PTP_PPS_EVENT, NULL);
    397		break;
    398	}
    399}
    400EXPORT_SYMBOL(ptp_clock_event);
    401
    402int ptp_clock_index(struct ptp_clock *ptp)
    403{
    404	return ptp->index;
    405}
    406EXPORT_SYMBOL(ptp_clock_index);
    407
    408int ptp_find_pin(struct ptp_clock *ptp,
    409		 enum ptp_pin_function func, unsigned int chan)
    410{
    411	struct ptp_pin_desc *pin = NULL;
    412	int i;
    413
    414	for (i = 0; i < ptp->info->n_pins; i++) {
    415		if (ptp->info->pin_config[i].func == func &&
    416		    ptp->info->pin_config[i].chan == chan) {
    417			pin = &ptp->info->pin_config[i];
    418			break;
    419		}
    420	}
    421
    422	return pin ? i : -1;
    423}
    424EXPORT_SYMBOL(ptp_find_pin);
    425
    426int ptp_find_pin_unlocked(struct ptp_clock *ptp,
    427			  enum ptp_pin_function func, unsigned int chan)
    428{
    429	int result;
    430
    431	mutex_lock(&ptp->pincfg_mux);
    432
    433	result = ptp_find_pin(ptp, func, chan);
    434
    435	mutex_unlock(&ptp->pincfg_mux);
    436
    437	return result;
    438}
    439EXPORT_SYMBOL(ptp_find_pin_unlocked);
    440
    441int ptp_schedule_worker(struct ptp_clock *ptp, unsigned long delay)
    442{
    443	return kthread_mod_delayed_work(ptp->kworker, &ptp->aux_work, delay);
    444}
    445EXPORT_SYMBOL(ptp_schedule_worker);
    446
    447void ptp_cancel_worker_sync(struct ptp_clock *ptp)
    448{
    449	kthread_cancel_delayed_work_sync(&ptp->aux_work);
    450}
    451EXPORT_SYMBOL(ptp_cancel_worker_sync);
    452
    453/* module operations */
    454
    455static void __exit ptp_exit(void)
    456{
    457	class_destroy(ptp_class);
    458	unregister_chrdev_region(ptp_devt, MINORMASK + 1);
    459	ida_destroy(&ptp_clocks_map);
    460}
    461
    462static int __init ptp_init(void)
    463{
    464	int err;
    465
    466	ptp_class = class_create(THIS_MODULE, "ptp");
    467	if (IS_ERR(ptp_class)) {
    468		pr_err("ptp: failed to allocate class\n");
    469		return PTR_ERR(ptp_class);
    470	}
    471
    472	err = alloc_chrdev_region(&ptp_devt, 0, MINORMASK + 1, "ptp");
    473	if (err < 0) {
    474		pr_err("ptp: failed to allocate device region\n");
    475		goto no_region;
    476	}
    477
    478	ptp_class->dev_groups = ptp_groups;
    479	pr_info("PTP clock support registered\n");
    480	return 0;
    481
    482no_region:
    483	class_destroy(ptp_class);
    484	return err;
    485}
    486
    487subsys_initcall(ptp_init);
    488module_exit(ptp_exit);
    489
    490MODULE_AUTHOR("Richard Cochran <richardcochran@gmail.com>");
    491MODULE_DESCRIPTION("PTP clocks support");
    492MODULE_LICENSE("GPL");