Skip to content

Commit 579d1b3

Browse files
lukenelswilldeacon
authored andcommitted
arm64: insn: Fix two bugs in encoding 32-bit logical immediates
This patch fixes two issues present in the current function for encoding arm64 logical immediates when using the 32-bit variants of instructions. First, the code does not correctly reject an all-ones 32-bit immediate, and returns an undefined instruction encoding. Second, the code incorrectly rejects some 32-bit immediates that are actually encodable as logical immediates. The root cause is that the code uses a default mask of 64-bit all-ones, even for 32-bit immediates. This causes an issue later on when the default mask is used to fill the top bits of the immediate with ones, shown here: /* * Pattern: 0..01..10..01..1 * * Fill the unused top bits with ones, and check if * the result is a valid immediate (all ones with a * contiguous ranges of zeroes). */ imm |= ~mask; if (!range_of_ones(~imm)) return AARCH64_BREAK_FAULT; To see the problem, consider an immediate of the form 0..01..10..01..1, where the upper 32 bits are zero, such as 0x80000001. The code checks if ~(imm | ~mask) contains a range of ones: the incorrect mask yields 1..10..01..10..0, which fails the check; the correct mask yields 0..01..10..0, which succeeds. The fix for both issues is to generate a correct mask based on the instruction immediate size, and use the mask to check for all-ones, all-zeroes, and values wider than the mask. Currently, arch/arm64/kvm/va_layout.c is the only user of this function, which uses 64-bit immediates and therefore won't trigger these bugs. We tested the new code against llvm-mc with all 1,302 encodable 32-bit logical immediates and all 5,334 encodable 64-bit logical immediates. Fixes: ef3935e ("arm64: insn: Add encoder for bitwise operations using literals") Suggested-by: Will Deacon <[email protected]> Co-developed-by: Xi Wang <[email protected]> Signed-off-by: Xi Wang <[email protected]> Signed-off-by: Luke Nelson <[email protected]> Reviewed-by: Marc Zyngier <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent 6a8b55e commit 579d1b3

File tree

1 file changed

+7
-7
lines changed

1 file changed

+7
-7
lines changed

arch/arm64/kernel/insn.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1535,16 +1535,10 @@ static u32 aarch64_encode_immediate(u64 imm,
15351535
u32 insn)
15361536
{
15371537
unsigned int immr, imms, n, ones, ror, esz, tmp;
1538-
u64 mask = ~0UL;
1539-
1540-
/* Can't encode full zeroes or full ones */
1541-
if (!imm || !~imm)
1542-
return AARCH64_BREAK_FAULT;
1538+
u64 mask;
15431539

15441540
switch (variant) {
15451541
case AARCH64_INSN_VARIANT_32BIT:
1546-
if (upper_32_bits(imm))
1547-
return AARCH64_BREAK_FAULT;
15481542
esz = 32;
15491543
break;
15501544
case AARCH64_INSN_VARIANT_64BIT:
@@ -1556,6 +1550,12 @@ static u32 aarch64_encode_immediate(u64 imm,
15561550
return AARCH64_BREAK_FAULT;
15571551
}
15581552

1553+
mask = GENMASK(esz - 1, 0);
1554+
1555+
/* Can't encode full zeroes, full ones, or value wider than the mask */
1556+
if (!imm || imm == mask || imm & ~mask)
1557+
return AARCH64_BREAK_FAULT;
1558+
15591559
/*
15601560
* Inverse of Replicate(). Try to spot a repeating pattern
15611561
* with a pow2 stride.

0 commit comments

Comments
 (0)