On Fri, 2022-06-10 at 17:35 +0300, Kirill A. Shutemov wrote: > +#ifdef CONFIG_X86_64 > +/* > + * Mask out tag bits from the address. > + * > + * Magic with the 'sign' allows to untag userspace pointer without > any branches > + * while leaving kernel addresses intact. Trying to understand the magic part here. I guess how it works is, when the high bit is set, it does the opposite of untagging the addresses by setting the tag bits instead of clearing them. So: - For proper canonical kernel addresses (with U57) it leaves them intact since the tag bits were already set. - For non-canonical kernel-half addresses, it fixes them up. (0xeffffff000000840->0xfffffff000000840) - For U48 and 5 level paging, it corrupts some normal kernel addresses. (0xff90ffffffffffff->0xffffffffffffffff) I just ported this to userspace and threw some addresses at it to see what happened, so hopefully I got that right. Is this special kernel address handling only needed because copy_to_kernel_nofault(), etc call the user helpers? > + */ > +#define untagged_addr(mm, > addr) ({ \ > + u64 __addr = (__force > u64)(addr); \ > + s64 sign = (s64)__addr >> > 63; \ > + __addr ^= > sign; \ > + __addr &= (mm)- > >context.untag_mask; \ > + __addr ^= > sign; \ > + (__force > __typeof__(addr))__addr; \ > +})