diff options
author | Eugene Syromyatnikov <evgsyr@gmail.com> | 2021-12-13 23:40:04 +0100 |
---|---|---|
committer | Eugene Syromyatnikov <evgsyr@gmail.com> | 2021-12-13 23:40:04 +0100 |
commit | 7e6e42c2c11d43811ca0a83b496d526bd7ef4c08 (patch) | |
tree | be1f5654efc0a7a8c21b536a91d50621ba4d7a5b | |
parent | a6a47cff55840a6dc2f1f27456c263938e877299 (diff) | |
download | strace-7e6e42c2c11d43811ca0a83b496d526bd7ef4c08.tar.gz |
Implement COUNTER_* ioctl decoding
-rw-r--r-- | bundled/Makefile.am | 1 | ||||
-rw-r--r-- | bundled/linux/include/uapi/linux/counter.h | 154 | ||||
-rw-r--r-- | src/counter_ioctl.c | 70 | ||||
-rw-r--r-- | src/defs.h | 1 | ||||
-rw-r--r-- | src/ioctl.c | 2 | ||||
-rw-r--r-- | src/xlat/counter_ioctl_component_types.in | 9 | ||||
-rw-r--r-- | src/xlat/counter_ioctl_event_types.in | 8 | ||||
-rw-r--r-- | src/xlat/counter_ioctl_scopes.in | 6 |
8 files changed, 251 insertions, 0 deletions
diff --git a/bundled/Makefile.am b/bundled/Makefile.am index aaa8942ed..7ccec1ea2 100644 --- a/bundled/Makefile.am +++ b/bundled/Makefile.am @@ -28,6 +28,7 @@ EXTRA_DIST = \ linux/include/uapi/linux/btrfs_tree.h \ linux/include/uapi/linux/close_range.h \ linux/include/uapi/linux/const.h \ + linux/include/uapi/linux/counter.h \ linux/include/uapi/linux/cryptouser.h \ linux/include/uapi/linux/dcbnl.h \ linux/include/uapi/linux/dm-ioctl.h \ diff --git a/bundled/linux/include/uapi/linux/counter.h b/bundled/linux/include/uapi/linux/counter.h new file mode 100644 index 000000000..e23962d91 --- /dev/null +++ b/bundled/linux/include/uapi/linux/counter.h @@ -0,0 +1,154 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * Userspace ABI for Counter character devices + * Copyright (C) 2020 William Breathitt Gray + */ +#ifndef _COUNTER_H_ +#define _COUNTER_H_ + +#include <linux/ioctl.h> +#include <linux/types.h> + +/* Component type definitions */ +enum counter_component_type { + COUNTER_COMPONENT_NONE, + COUNTER_COMPONENT_SIGNAL, + COUNTER_COMPONENT_COUNT, + COUNTER_COMPONENT_FUNCTION, + COUNTER_COMPONENT_SYNAPSE_ACTION, + COUNTER_COMPONENT_EXTENSION, +}; + +/* Component scope definitions */ +enum counter_scope { + COUNTER_SCOPE_DEVICE, + COUNTER_SCOPE_SIGNAL, + COUNTER_SCOPE_COUNT, +}; + +/** + * struct counter_component - Counter component identification + * @type: component type (one of enum counter_component_type) + * @scope: component scope (one of enum counter_scope) + * @parent: parent ID (matching the ID suffix of the respective parent sysfs + * path as described by the ABI documentation file + * Documentation/ABI/testing/sysfs-bus-counter) + * @id: component ID (matching the ID provided by the respective *_component_id + * sysfs attribute of the desired component) + * + * For example, if the Count 2 ceiling extension of Counter device 4 is desired, + * set type equal to COUNTER_COMPONENT_EXTENSION, scope equal to + * COUNTER_COUNT_SCOPE, parent equal to 2, and id equal to the value provided by + * the respective /sys/bus/counter/devices/counter4/count2/ceiling_component_id + * sysfs attribute. + */ +struct counter_component { + __u8 type; + __u8 scope; + __u8 parent; + __u8 id; +}; + +/* Event type definitions */ +enum counter_event_type { + /* Count value increased past ceiling */ + COUNTER_EVENT_OVERFLOW, + /* Count value decreased past floor */ + COUNTER_EVENT_UNDERFLOW, + /* Count value increased past ceiling, or decreased past floor */ + COUNTER_EVENT_OVERFLOW_UNDERFLOW, + /* Count value reached threshold */ + COUNTER_EVENT_THRESHOLD, + /* Index signal detected */ + COUNTER_EVENT_INDEX, +}; + +/** + * struct counter_watch - Counter component watch configuration + * @component: component to watch when event triggers + * @event: event that triggers (one of enum counter_event_type) + * @channel: event channel (typically 0 unless the device supports concurrent + * events of the same type) + */ +struct counter_watch { + struct counter_component component; + __u8 event; + __u8 channel; +}; + +/* + * Queues a Counter watch for the specified event. + * + * The queued watches will not be applied until COUNTER_ENABLE_EVENTS_IOCTL is + * called. + */ +#define COUNTER_ADD_WATCH_IOCTL _IOW(0x3E, 0x00, struct counter_watch) +/* + * Enables monitoring the events specified by the Counter watches that were + * queued by COUNTER_ADD_WATCH_IOCTL. + * + * If events are already enabled, the new set of watches replaces the old one. + * Calling this ioctl also has the effect of clearing the queue of watches added + * by COUNTER_ADD_WATCH_IOCTL. + */ +#define COUNTER_ENABLE_EVENTS_IOCTL _IO(0x3E, 0x01) +/* + * Stops monitoring the previously enabled events. + */ +#define COUNTER_DISABLE_EVENTS_IOCTL _IO(0x3E, 0x02) + +/** + * struct counter_event - Counter event data + * @timestamp: best estimate of time of event occurrence, in nanoseconds + * @value: component value + * @watch: component watch configuration + * @status: return status (system error number) + */ +struct counter_event { + __aligned_u64 timestamp; + __aligned_u64 value; + struct counter_watch watch; + __u8 status; +}; + +/* Count direction values */ +enum counter_count_direction { + COUNTER_COUNT_DIRECTION_FORWARD, + COUNTER_COUNT_DIRECTION_BACKWARD, +}; + +/* Count mode values */ +enum counter_count_mode { + COUNTER_COUNT_MODE_NORMAL, + COUNTER_COUNT_MODE_RANGE_LIMIT, + COUNTER_COUNT_MODE_NON_RECYCLE, + COUNTER_COUNT_MODE_MODULO_N, +}; + +/* Count function values */ +enum counter_function { + COUNTER_FUNCTION_INCREASE, + COUNTER_FUNCTION_DECREASE, + COUNTER_FUNCTION_PULSE_DIRECTION, + COUNTER_FUNCTION_QUADRATURE_X1_A, + COUNTER_FUNCTION_QUADRATURE_X1_B, + COUNTER_FUNCTION_QUADRATURE_X2_A, + COUNTER_FUNCTION_QUADRATURE_X2_B, + COUNTER_FUNCTION_QUADRATURE_X4, +}; + +/* Signal values */ +enum counter_signal_level { + COUNTER_SIGNAL_LEVEL_LOW, + COUNTER_SIGNAL_LEVEL_HIGH, +}; + +/* Action mode values */ +enum counter_synapse_action { + COUNTER_SYNAPSE_ACTION_NONE, + COUNTER_SYNAPSE_ACTION_RISING_EDGE, + COUNTER_SYNAPSE_ACTION_FALLING_EDGE, + COUNTER_SYNAPSE_ACTION_BOTH_EDGES, +}; + +#endif /* _COUNTER_H_ */ diff --git a/src/counter_ioctl.c b/src/counter_ioctl.c new file mode 100644 index 000000000..5ed2fb750 --- /dev/null +++ b/src/counter_ioctl.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2021 Eugene Syromyatnikov <evgsyr@gmail.com>. + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "defs.h" + +#include <linux/ioctl.h> +#include <linux/counter.h> + +#include "xlat/counter_ioctl_component_types.h" +#include "xlat/counter_ioctl_event_types.h" +#include "xlat/counter_ioctl_scopes.h" + + +static void +print_struct_counter_component(const struct counter_component *const cc) +{ + tprint_struct_begin(); + PRINT_FIELD_XVAL(*cc, type, counter_ioctl_component_types, + "COUNTER_COMPONENT_???"); + tprint_struct_next(); + PRINT_FIELD_XVAL(*cc, type, counter_ioctl_component_scopes, + "COUNTER_SCOPE_???"); + tprint_struct_next(); + PRINT_FIELD_U(*cc, parent); + tprint_struct_next(); + PRINT_FIELD_U(*cc, id); + tprint_struct_end(); +} + +static void +print_struct_counter_watch(struct tcb *const tcp, const kernel_ulong_t addr) +{ + CHECK_IOCTL_SIZE(COUNTER_ADD_WATCH_IOCTL, 6); + CHECK_TYPE_SIZE(struct counter_watch, 6); + struct counter_watch w; + + if (umove_or_printaddr(tcp, addr, &w)) + return; + + tprint_struct_begin(); + PRINT_FIELD_OBJ_PTR(w, component, print_struct_counter_component); + tprint_struct_next(); + PRINT_FIELD_XVAL(w, event, counter_ioctl_events, + "COUNTER_EVENT_???"); + tprint_struct_next(); + PRINT_FIELD_U(w, channel); + tprint_struct_end(); +} + +int +counter_ioctl(struct tcb *const tcp, const unsigned int code, + const kernel_ulong_t arg) +{ + switch (code) { + case COUNTER_ADD_WATCH_IOCTL: + tprint_arg_next(); + print_struct_counter_watch(tcp, arg); + + case COUNTER_ENABLE_EVENTS_IOCTL: + case COUNTER_DISABLE_EVENTS_IOCTL: + return RVAL_IOCTL_DECODED; + + default: + return RVAL_DECODED; + } +} diff --git a/src/defs.h b/src/defs.h index c454b0b09..482bc236f 100644 --- a/src/defs.h +++ b/src/defs.h @@ -1356,6 +1356,7 @@ extern int \ name ## _ioctl(struct tcb *, unsigned int request, kernel_ulong_t arg) \ /* End of DECL_IOCTL definition. */ +DECL_IOCTL(counter); DECL_IOCTL(dm); DECL_IOCTL(evdev); DECL_IOCTL(fs_0x94); diff --git a/src/ioctl.c b/src/ioctl.c index 1965af32c..d75c04829 100644 --- a/src/ioctl.c +++ b/src/ioctl.c @@ -362,6 +362,8 @@ ioctl_decode(struct tcb *tcp) return perf_ioctl(tcp, code, arg); case '=': /* 0x3d */ return ptp_ioctl(tcp, code, arg); + case '>': /* 0x3e */ + return counter_ioctl(tcp, code, arg); case 'E': return evdev_ioctl(tcp, code, arg); case 'I': diff --git a/src/xlat/counter_ioctl_component_types.in b/src/xlat/counter_ioctl_component_types.in new file mode 100644 index 000000000..a99ccb544 --- /dev/null +++ b/src/xlat/counter_ioctl_component_types.in @@ -0,0 +1,9 @@ +#enum +#value_indexed +#unconditional +COUNTER_COMPONENT_NONE 0 +COUNTER_COMPONENT_SIGNAL 1 +COUNTER_COMPONENT_COUNT 2 +COUNTER_COMPONENT_FUNCTION 3 +COUNTER_COMPONENT_SYNAPSE_ACTION 4 +COUNTER_COMPONENT_EXTENSION 5 diff --git a/src/xlat/counter_ioctl_event_types.in b/src/xlat/counter_ioctl_event_types.in new file mode 100644 index 000000000..fa5d1d406 --- /dev/null +++ b/src/xlat/counter_ioctl_event_types.in @@ -0,0 +1,8 @@ +#enum +#value_indexed +#unconditional +COUNTER_EVENT_OVERFLOW 0 +COUNTER_EVENT_UNDERFLOW 1 +COUNTER_EVENT_OVERFLOW_UNDERFLOW 2 +COUNTER_EVENT_THRESHOLD 3 +COUNTER_EVENT_INDEX 4 diff --git a/src/xlat/counter_ioctl_scopes.in b/src/xlat/counter_ioctl_scopes.in new file mode 100644 index 000000000..cd115716f --- /dev/null +++ b/src/xlat/counter_ioctl_scopes.in @@ -0,0 +1,6 @@ +#enum +#value_indexed +#unconditional +COUNTER_SCOPE_DEVICE 0 +COUNTER_SCOPE_SIGNAL 1 +COUNTER_SCOPE_COUNT 2 |