^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/regset.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <asm/switch_to.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include "ptrace-decl.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * For get_evrregs/set_evrregs functions 'data' has the following layout:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * u32 evr[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * u64 acc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * u32 spefscr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) int evr_active(struct task_struct *target, const struct user_regset *regset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) flush_spe_to_thread(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) return target->thread.used_spe ? regset->n : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) int evr_get(struct task_struct *target, const struct user_regset *regset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct membuf to)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) flush_spe_to_thread(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) membuf_write(&to, &target->thread.evr, sizeof(target->thread.evr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) BUILD_BUG_ON(offsetof(struct thread_struct, acc) + sizeof(u64) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) offsetof(struct thread_struct, spefscr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) return membuf_write(&to, &target->thread.acc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) sizeof(u64) + sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) int evr_set(struct task_struct *target, const struct user_regset *regset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) unsigned int pos, unsigned int count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) const void *kbuf, const void __user *ubuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) flush_spe_to_thread(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) &target->thread.evr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) 0, sizeof(target->thread.evr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) BUILD_BUG_ON(offsetof(struct thread_struct, acc) + sizeof(u64) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) offsetof(struct thread_struct, spefscr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) &target->thread.acc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) sizeof(target->thread.evr), -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }