regset: new method and helpers for it
authorAl Viro <viro@zeniv.linux.org.uk>
Fri, 21 Feb 2020 01:48:16 +0000 (20:48 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Mon, 27 Jul 2020 18:31:07 +0000 (14:31 -0400)
commit7717cb9bdd0421faa432a4e0d499fdba6e2394c8
tree54088f1cad7231a96ee5c5d880f44b58686d06e9
parentdc12d7968f9c9540494deb1285854b18ca4465ec
regset: new method and helpers for it

->regset_get() takes task+regset+buffer, returns the amount of free space
left in the buffer on success and -E... on error.

buffer is represented as struct membuf - a pair of (kernel) pointer
and amount of space left

Primitives for writing to such:
* membuf_write(buf, data, size)
* membuf_zero(buf, size)
* membuf_store(buf, value)

These are implemented as inlines (in case of membuf_store - a macro).
All writes are sequential; they become no-ops when there's no space
left.  Return value of all primitives is the amount of space left
after the operation, so they can be used as return values of ->regset_get().

Example of use:

// stores pt_regs of task + 64 bytes worth of zeroes + 32bit PID of task
int foo_get(struct task_struct *task, const struct regset *regset,
    struct membuf to)
{
membuf_write(&to, task_pt_regs(task), sizeof(struct pt_regs));
membuf_zero(&to, 64);
return membuf_store(&to, (u32)task_tgid_vnr(task));
}

regset_get()/regset_get_alloc() taught to use that thing if present.
By the end of the series all users of ->get() will be converted;
then ->get() and ->get_size() can go.

Note that unlike ->get() this thing always starts at offset 0 and,
since it only writes to kernel buffer, can't fail on copyout.
It can, of course, fail for other reasons, but those tend to
be less numerous.

The caller guarantees that the buffer size won't be bigger than
regset->n * regset->size.  That simplifies life for quite a few
instances.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
include/linux/regset.h
kernel/regset.c