Skip to content

Commit 1dbc0a9

Browse files
committed
x86: mm: remove 'sign' games from LAM untagged_addr*() macros
The intent of the sign games was to not modify kernel addresses when untagging them. However, that had two issues: (a) it didn't actually work as intended, since the mask was calculated as 'addr >> 63' on an _unsigned_ address. So instead of getting a mask of all ones for kernel addresses, you just got '1'. (b) untagging a kernel address isn't actually a valid operation anyway. Now, (a) had originally been true for both 'untagged_addr()' and the remote version of it, but had accidentally been fixed for the regular version of untagged_addr() by commit e0bddc1 ("x86/mm: Reduce untagged_addr() overhead for systems without LAM"). That one rewrote the shift to be part of the alternative asm code, and in the process changed the unsigned shift into a signed 'sar' instruction. And while it is true that we don't want to turn what looks like a kernel address into a user address by masking off the high bit, that doesn't need these sign masking games - all it needs is that the mm context 'untag_mask' value has the high bit set. Which it always does. So simplify the code by just removing the superfluous (and in the case of untagged_addr_remote(), still buggy) sign bit games in the address masking. Acked-by: Dave Hansen <dave.hansen@intel.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent b9bd9f6 commit 1dbc0a9

1 file changed

Lines changed: 3 additions & 15 deletions

File tree

arch/x86/include/asm/uaccess_64.h

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,17 @@
1515
#ifdef CONFIG_ADDRESS_MASKING
1616
/*
1717
* Mask out tag bits from the address.
18-
*
19-
* Magic with the 'sign' allows to untag userspace pointer without any branches
20-
* while leaving kernel addresses intact.
2118
*/
2219
static inline unsigned long __untagged_addr(unsigned long addr)
2320
{
24-
long sign;
25-
2621
/*
2722
* Refer tlbstate_untag_mask directly to avoid RIP-relative relocation
2823
* in alternative instructions. The relocation gets wrong when gets
2924
* copied to the target place.
3025
*/
3126
asm (ALTERNATIVE("",
32-
"sar $63, %[sign]\n\t" /* user_ptr ? 0 : -1UL */
33-
"or %%gs:tlbstate_untag_mask, %[sign]\n\t"
34-
"and %[sign], %[addr]\n\t", X86_FEATURE_LAM)
35-
: [addr] "+r" (addr), [sign] "=r" (sign)
36-
: "m" (tlbstate_untag_mask), "[sign]" (addr));
27+
"and %%gs:tlbstate_untag_mask, %[addr]\n\t", X86_FEATURE_LAM)
28+
: [addr] "+r" (addr) : "m" (tlbstate_untag_mask));
3729

3830
return addr;
3931
}
@@ -46,12 +38,8 @@ static inline unsigned long __untagged_addr(unsigned long addr)
4638
static inline unsigned long __untagged_addr_remote(struct mm_struct *mm,
4739
unsigned long addr)
4840
{
49-
long sign = addr >> 63;
50-
5141
mmap_assert_locked(mm);
52-
addr &= (mm)->context.untag_mask | sign;
53-
54-
return addr;
42+
return addr & (mm)->context.untag_mask;
5543
}
5644

5745
#define untagged_addr_remote(mm, addr) ({ \

0 commit comments

Comments
 (0)