diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/rseq.c | 119 |
1 files changed, 59 insertions, 60 deletions
diff --git a/kernel/rseq.c b/kernel/rseq.c index 246319d7cb0c..51fafc4528b0 100644 --- a/kernel/rseq.c +++ b/kernel/rseq.c @@ -8,6 +8,65 @@ * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> */ +/* + * Restartable sequences are a lightweight interface that allows + * user-level code to be executed atomically relative to scheduler + * preemption and signal delivery. Typically used for implementing + * per-cpu operations. + * + * It allows user-space to perform update operations on per-cpu data + * without requiring heavy-weight atomic operations. + * + * Detailed algorithm of rseq user-space assembly sequences: + * + * init(rseq_cs) + * cpu = TLS->rseq::cpu_id_start + * [1] TLS->rseq::rseq_cs = rseq_cs + * [start_ip] ---------------------------- + * [2] if (cpu != TLS->rseq::cpu_id) + * goto abort_ip; + * [3] <last_instruction_in_cs> + * [post_commit_ip] ---------------------------- + * + * The address of jump target abort_ip must be outside the critical + * region, i.e.: + * + * [abort_ip] < [start_ip] || [abort_ip] >= [post_commit_ip] + * + * Steps [2]-[3] (inclusive) need to be a sequence of instructions in + * userspace that can handle being interrupted between any of those + * instructions, and then resumed to the abort_ip. + * + * 1. Userspace stores the address of the struct rseq_cs assembly + * block descriptor into the rseq_cs field of the registered + * struct rseq TLS area. This update is performed through a single + * store within the inline assembly instruction sequence. + * [start_ip] + * + * 2. Userspace tests to check whether the current cpu_id field match + * the cpu number loaded before start_ip, branching to abort_ip + * in case of a mismatch. + * + * If the sequence is preempted or interrupted by a signal + * at or after start_ip and before post_commit_ip, then the kernel + * clears TLS->__rseq_abi::rseq_cs, and sets the user-space return + * ip to abort_ip before returning to user-space, so the preempted + * execution resumes at abort_ip. + * + * 3. Userspace critical section final instruction before + * post_commit_ip is the commit. The critical section is + * self-terminating. + * [post_commit_ip] + * + * 4. <success> + * + * On failure at [2], or if interrupted by preempt or signal delivery + * between [1] and [3]: + * + * [abort_ip] + * F1. <failure> + */ + #include <linux/sched.h> #include <linux/uaccess.h> #include <linux/syscalls.h> @@ -98,66 +157,6 @@ static int rseq_validate_ro_fields(struct task_struct *t) unsafe_put_user(value, &t->rseq->field, error_label) #endif -/* - * - * Restartable sequences are a lightweight interface that allows - * user-level code to be executed atomically relative to scheduler - * preemption and signal delivery. Typically used for implementing - * per-cpu operations. - * - * It allows user-space to perform update operations on per-cpu data - * without requiring heavy-weight atomic operations. - * - * Detailed algorithm of rseq user-space assembly sequences: - * - * init(rseq_cs) - * cpu = TLS->rseq::cpu_id_start - * [1] TLS->rseq::rseq_cs = rseq_cs - * [start_ip] ---------------------------- - * [2] if (cpu != TLS->rseq::cpu_id) - * goto abort_ip; - * [3] <last_instruction_in_cs> - * [post_commit_ip] ---------------------------- - * - * The address of jump target abort_ip must be outside the critical - * region, i.e.: - * - * [abort_ip] < [start_ip] || [abort_ip] >= [post_commit_ip] - * - * Steps [2]-[3] (inclusive) need to be a sequence of instructions in - * userspace that can handle being interrupted between any of those - * instructions, and then resumed to the abort_ip. - * - * 1. Userspace stores the address of the struct rseq_cs assembly - * block descriptor into the rseq_cs field of the registered - * struct rseq TLS area. This update is performed through a single - * store within the inline assembly instruction sequence. - * [start_ip] - * - * 2. Userspace tests to check whether the current cpu_id field match - * the cpu number loaded before start_ip, branching to abort_ip - * in case of a mismatch. - * - * If the sequence is preempted or interrupted by a signal - * at or after start_ip and before post_commit_ip, then the kernel - * clears TLS->__rseq_abi::rseq_cs, and sets the user-space return - * ip to abort_ip before returning to user-space, so the preempted - * execution resumes at abort_ip. - * - * 3. Userspace critical section final instruction before - * post_commit_ip is the commit. The critical section is - * self-terminating. - * [post_commit_ip] - * - * 4. <success> - * - * On failure at [2], or if interrupted by preempt or signal delivery - * between [1] and [3]: - * - * [abort_ip] - * F1. <failure> - */ - static int rseq_update_cpu_node_id(struct task_struct *t) { struct rseq __user *rseq = t->rseq; |
