* Re: [PATCH] bpf: fix umin/umax when lower bits fall outside u32 range
2026-03-27 19:48 [PATCH] bpf: fix umin/umax when lower bits fall outside u32 range Helen Koike
@ 2026-03-27 20:18 ` Eduard Zingerman
2026-03-27 20:46 ` Eduard Zingerman
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Eduard Zingerman @ 2026-03-27 20:18 UTC (permalink / raw)
To: Helen Koike, andrii, shung-hsi.yu, yonghong.song, ast, bpf,
linux-kernel, kernel-dev
On Fri, 2026-03-27 at 16:48 -0300, Helen Koike wrote:
[...]
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index a965b2c45bbe..ddac09c8a9e5 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -2702,9 +2702,29 @@ static void __reg_deduce_mixed_bounds(struct bpf_reg_state *reg)
> __u64 new_umin, new_umax;
> __s64 new_smin, new_smax;
>
> - /* u32 -> u64 tightening, it's always well-formed */
> - new_umin = (reg->umin_value & ~0xffffffffULL) | reg->u32_min_value;
> - new_umax = (reg->umax_value & ~0xffffffffULL) | reg->u32_max_value;
> + /*
> + * If (u32)umin > u32_max, no value in the current upper-32-bit block
> + * satisfies [u32_min, u32_max] while being >= umin; advance umin to
> + * the next block. Otherwise apply standard u32->u64 tightening.
> + */
> + if ((u32)reg->umin_value > reg->u32_max_value)
> + new_umin = (reg->umin_value & ~0xffffffffULL) + (1ULL << 32) |
> + reg->u32_min_value;
> + else
> + new_umin = (reg->umin_value & ~0xffffffffULL) |
> + reg->u32_min_value;
> +
> + /*
> + * Symmetrically, if (u32)umax < u32_min, retreat umax to the
> + * previous block. Otherwise apply standard u32->u64 tightening.
> + */
> + if ((u32)reg->umax_value < reg->u32_min_value)
> + new_umax = (reg->umax_value & ~0xffffffffULL) - (1ULL << 32) |
> + reg->u32_max_value;
> + else
> + new_umax = (reg->umax_value & ~0xffffffffULL) |
> + reg->u32_max_value;
> +
> reg->umin_value = max_t(u64, reg->umin_value, new_umin);
> reg->umax_value = min_t(u64, reg->umax_value, new_umax);
> /* u32 -> s64 tightening, u32 range embedded into s64 preserves range validity */
Looks like it is the same case I identified in RFC [1].
[1] https://lore.kernel.org/bpf/20260318-cnum-sync-bounds-v1-4-1f2e455ea711@gmail.com/
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH] bpf: fix umin/umax when lower bits fall outside u32 range
2026-03-27 19:48 [PATCH] bpf: fix umin/umax when lower bits fall outside u32 range Helen Koike
2026-03-27 20:18 ` Eduard Zingerman
@ 2026-03-27 20:46 ` Eduard Zingerman
2026-03-30 12:09 ` Helen Koike
2026-03-30 16:24 ` kernel test robot
2026-03-30 17:53 ` kernel test robot
3 siblings, 1 reply; 6+ messages in thread
From: Eduard Zingerman @ 2026-03-27 20:46 UTC (permalink / raw)
To: Helen Koike, andrii, shung-hsi.yu, yonghong.song, ast, bpf,
linux-kernel, kernel-dev
On Fri, 2026-03-27 at 16:48 -0300, Helen Koike wrote:
[...]
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index a965b2c45bbe..ddac09c8a9e5 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -2702,9 +2702,29 @@ static void __reg_deduce_mixed_bounds(struct bpf_reg_state *reg)
> __u64 new_umin, new_umax;
> __s64 new_smin, new_smax;
>
> - /* u32 -> u64 tightening, it's always well-formed */
> - new_umin = (reg->umin_value & ~0xffffffffULL) | reg->u32_min_value;
> - new_umax = (reg->umax_value & ~0xffffffffULL) | reg->u32_max_value;
> + /*
> + * If (u32)umin > u32_max, no value in the current upper-32-bit block
> + * satisfies [u32_min, u32_max] while being >= umin; advance umin to
> + * the next block. Otherwise apply standard u32->u64 tightening.
> + */
> + if ((u32)reg->umin_value > reg->u32_max_value)
> + new_umin = (reg->umin_value & ~0xffffffffULL) + (1ULL << 32) |
> + reg->u32_min_value;
> + else
> + new_umin = (reg->umin_value & ~0xffffffffULL) |
> + reg->u32_min_value;
What would happen if there is no next or previous 32-bit block?
E.g. if (reg->umin_value & ~0xffffffffULL) + (1ULL << 32) wraps around.
I guess the argument is that if this happens, there is an invariant
violation already, will the final register still bin in invariant
violation state?
Useful picture:
N*2^32 (N+1)*2^32 (N+2)*2^32 (N+3)*2^32
||----|=====|--|----------||----|=====|-------------||--|-|=====|-------------||
|< b >| | |< b >| | |< b >|
| | | |
|<---------------+- a -+---------------->|
| |
|< t >| refined r0 range
Also, as this is based solely on unsigned ranges, the following case
is not covered, right?
N*2^32 (N+1)*2^32 (N+2)*2^32 (N+3)*2^32
||===|---------|------|===||===|----------------|===||===|---------|------|===||
|b >| | |< b||b >| |< b||b >| | |< b|
| | | |
|<-----+----------------- a --------------+-------->|
| |
|<---------------- t ------------->| refined r0 range
Would it be hard to implementing something in the same line as [2] to cover it?
> +
> + /*
> + * Symmetrically, if (u32)umax < u32_min, retreat umax to the
> + * previous block. Otherwise apply standard u32->u64 tightening.
> + */
> + if ((u32)reg->umax_value < reg->u32_min_value)
> + new_umax = (reg->umax_value & ~0xffffffffULL) - (1ULL << 32) |
> + reg->u32_max_value;
> + else
> + new_umax = (reg->umax_value & ~0xffffffffULL) |
> + reg->u32_max_value;
> +
> reg->umin_value = max_t(u64, reg->umin_value, new_umin);
> reg->umax_value = min_t(u64, reg->umax_value, new_umax);
> /* u32 -> s64 tightening, u32 range embedded into s64 preserves range validity */
I think we can move forward with this, as the fate of my RFC is
uncertain. Please add some selftests, e.g. from [1].
[1] https://lore.kernel.org/bpf/20260318-cnum-sync-bounds-v1-4-1f2e455ea711@gmail.com/
[2] https://github.com/eddyz87/cnum-verif/blob/master/cnum.c#L242
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH] bpf: fix umin/umax when lower bits fall outside u32 range
2026-03-27 20:46 ` Eduard Zingerman
@ 2026-03-30 12:09 ` Helen Koike
0 siblings, 0 replies; 6+ messages in thread
From: Helen Koike @ 2026-03-30 12:09 UTC (permalink / raw)
To: Eduard Zingerman, andrii, shung-hsi.yu, yonghong.song, ast, bpf,
linux-kernel, kernel-dev
Hi Eduard,
Thanks for your replies and pointers, please see my comments below.
On 3/27/26 5:46 PM, Eduard Zingerman wrote:
> On Fri, 2026-03-27 at 16:48 -0300, Helen Koike wrote:
>
> [...]
>
>> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
>> index a965b2c45bbe..ddac09c8a9e5 100644
>> --- a/kernel/bpf/verifier.c
>> +++ b/kernel/bpf/verifier.c
>> @@ -2702,9 +2702,29 @@ static void __reg_deduce_mixed_bounds(struct bpf_reg_state *reg)
>> __u64 new_umin, new_umax;
>> __s64 new_smin, new_smax;
>>
>> - /* u32 -> u64 tightening, it's always well-formed */
>> - new_umin = (reg->umin_value & ~0xffffffffULL) | reg->u32_min_value;
>> - new_umax = (reg->umax_value & ~0xffffffffULL) | reg->u32_max_value;
>> + /*
>> + * If (u32)umin > u32_max, no value in the current upper-32-bit block
>> + * satisfies [u32_min, u32_max] while being >= umin; advance umin to
>> + * the next block. Otherwise apply standard u32->u64 tightening.
>> + */
>> + if ((u32)reg->umin_value > reg->u32_max_value)
>> + new_umin = (reg->umin_value & ~0xffffffffULL) + (1ULL << 32) |
>> + reg->u32_min_value;
>> + else
>> + new_umin = (reg->umin_value & ~0xffffffffULL) |
>> + reg->u32_min_value;
>
> What would happen if there is no next or previous 32-bit block?
> E.g. if (reg->umin_value & ~0xffffffffULL) + (1ULL << 32) wraps around.
> I guess the argument is that if this happens, there is an invariant
> violation already, will the final register still bin in invariant
> violation state?
I thought about it and my conclusion was that we would be in trouble
anyway and the error is elsewhere (unless my understanding is wrong).
We could add a check here, but I guess reg_bounds_sanity_check() already
does that.
>
> Useful picture:
>
> N*2^32 (N+1)*2^32 (N+2)*2^32 (N+3)*2^32
> ||----|=====|--|----------||----|=====|-------------||--|-|=====|-------------||
> |< b >| | |< b >| | |< b >|
> | | | |
> |<---------------+- a -+---------------->|
> | |
> |< t >| refined r0 range
>
> Also, as this is based solely on unsigned ranges, the following case
> is not covered, right?
Right, this case is not covered.
>
> N*2^32 (N+1)*2^32 (N+2)*2^32 (N+3)*2^32
> ||===|---------|------|===||===|----------------|===||===|---------|------|===||
> |b >| | |< b||b >| |< b||b >| | |< b|
> | | | |
> |<-----+----------------- a --------------+-------->|
> | |
> |<---------------- t ------------->| refined r0 range
>
> Would it be hard to implementing something in the same line as [2] to cover it?
I'll check and get back to you.
>
>> +
>> + /*
>> + * Symmetrically, if (u32)umax < u32_min, retreat umax to the
>> + * previous block. Otherwise apply standard u32->u64 tightening.
>> + */
>> + if ((u32)reg->umax_value < reg->u32_min_value)
>> + new_umax = (reg->umax_value & ~0xffffffffULL) - (1ULL << 32) |
>> + reg->u32_max_value;
>> + else
>> + new_umax = (reg->umax_value & ~0xffffffffULL) |
>> + reg->u32_max_value;
>> +
>> reg->umin_value = max_t(u64, reg->umin_value, new_umin);
>> reg->umax_value = min_t(u64, reg->umax_value, new_umax);
>> /* u32 -> s64 tightening, u32 range embedded into s64 preserves range validity */
>
> I think we can move forward with this, as the fate of my RFC is
> uncertain. Please add some selftests, e.g. from [1].
Ack, I'll check the signed case, test against your selftests and
re-submit the patches.
Thanks again!
Helen
>
> [1] https://lore.kernel.org/bpf/20260318-cnum-sync-bounds-v1-4-1f2e455ea711@gmail.com/
> [2] https://github.com/eddyz87/cnum-verif/blob/master/cnum.c#L242
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] bpf: fix umin/umax when lower bits fall outside u32 range
2026-03-27 19:48 [PATCH] bpf: fix umin/umax when lower bits fall outside u32 range Helen Koike
2026-03-27 20:18 ` Eduard Zingerman
2026-03-27 20:46 ` Eduard Zingerman
@ 2026-03-30 16:24 ` kernel test robot
2026-03-30 17:53 ` kernel test robot
3 siblings, 0 replies; 6+ messages in thread
From: kernel test robot @ 2026-03-30 16:24 UTC (permalink / raw)
To: Helen Koike, andrii, eddyz87, shung-hsi.yu, yonghong.song, ast,
bpf, linux-kernel, kernel-dev
Cc: oe-kbuild-all
Hi Helen,
kernel test robot noticed the following build warnings:
[auto build test WARNING on bpf-next/net]
[also build test WARNING on bpf-next/master bpf/master linus/master v7.0-rc6 next-20260327]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Helen-Koike/bpf-fix-umin-umax-when-lower-bits-fall-outside-u32-range/20260330-171706
base: https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git net
patch link: https://lore.kernel.org/r/20260327194849.855397-1-koike%40igalia.com
patch subject: [PATCH] bpf: fix umin/umax when lower bits fall outside u32 range
config: x86_64-rhel-9.4-ltp (https://download.01.org/0day-ci/archive/20260330/202603301811.Bddu9uxI-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260330/202603301811.Bddu9uxI-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603301811.Bddu9uxI-lkp@intel.com/
All warnings (new ones prefixed by >>):
kernel/bpf/verifier.c: In function '__reg_deduce_mixed_bounds':
>> kernel/bpf/verifier.c:2699:63: warning: suggest parentheses around arithmetic in operand of '|' [-Wparentheses]
2699 | new_umin = (reg->umin_value & ~0xffffffffULL) + (1ULL << 32) |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~
kernel/bpf/verifier.c:2710:63: warning: suggest parentheses around arithmetic in operand of '|' [-Wparentheses]
2710 | new_umax = (reg->umax_value & ~0xffffffffULL) - (1ULL << 32) |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~
vim +2699 kernel/bpf/verifier.c
2675
2676 static void __reg_deduce_mixed_bounds(struct bpf_reg_state *reg)
2677 {
2678 /* Try to tighten 64-bit bounds from 32-bit knowledge, using 32-bit
2679 * values on both sides of 64-bit range in hope to have tighter range.
2680 * E.g., if r1 is [0x1'00000000, 0x3'80000000], and we learn from
2681 * 32-bit signed > 0 operation that s32 bounds are now [1; 0x7fffffff].
2682 * With this, we can substitute 1 as low 32-bits of _low_ 64-bit bound
2683 * (0x100000000 -> 0x100000001) and 0x7fffffff as low 32-bits of
2684 * _high_ 64-bit bound (0x380000000 -> 0x37fffffff) and arrive at a
2685 * better overall bounds for r1 as [0x1'000000001; 0x3'7fffffff].
2686 * We just need to make sure that derived bounds we are intersecting
2687 * with are well-formed ranges in respective s64 or u64 domain, just
2688 * like we do with similar kinds of 32-to-64 or 64-to-32 adjustments.
2689 */
2690 __u64 new_umin, new_umax;
2691 __s64 new_smin, new_smax;
2692
2693 /*
2694 * If (u32)umin > u32_max, no value in the current upper-32-bit block
2695 * satisfies [u32_min, u32_max] while being >= umin; advance umin to
2696 * the next block. Otherwise apply standard u32->u64 tightening.
2697 */
2698 if ((u32)reg->umin_value > reg->u32_max_value)
> 2699 new_umin = (reg->umin_value & ~0xffffffffULL) + (1ULL << 32) |
2700 reg->u32_min_value;
2701 else
2702 new_umin = (reg->umin_value & ~0xffffffffULL) |
2703 reg->u32_min_value;
2704
2705 /*
2706 * Symmetrically, if (u32)umax < u32_min, retreat umax to the
2707 * previous block. Otherwise apply standard u32->u64 tightening.
2708 */
2709 if ((u32)reg->umax_value < reg->u32_min_value)
2710 new_umax = (reg->umax_value & ~0xffffffffULL) - (1ULL << 32) |
2711 reg->u32_max_value;
2712 else
2713 new_umax = (reg->umax_value & ~0xffffffffULL) |
2714 reg->u32_max_value;
2715
2716 reg->umin_value = max_t(u64, reg->umin_value, new_umin);
2717 reg->umax_value = min_t(u64, reg->umax_value, new_umax);
2718 /* u32 -> s64 tightening, u32 range embedded into s64 preserves range validity */
2719 new_smin = (reg->smin_value & ~0xffffffffULL) | reg->u32_min_value;
2720 new_smax = (reg->smax_value & ~0xffffffffULL) | reg->u32_max_value;
2721 reg->smin_value = max_t(s64, reg->smin_value, new_smin);
2722 reg->smax_value = min_t(s64, reg->smax_value, new_smax);
2723
2724 /* Here we would like to handle a special case after sign extending load,
2725 * when upper bits for a 64-bit range are all 1s or all 0s.
2726 *
2727 * Upper bits are all 1s when register is in a range:
2728 * [0xffff_ffff_0000_0000, 0xffff_ffff_ffff_ffff]
2729 * Upper bits are all 0s when register is in a range:
2730 * [0x0000_0000_0000_0000, 0x0000_0000_ffff_ffff]
2731 * Together this forms are continuous range:
2732 * [0xffff_ffff_0000_0000, 0x0000_0000_ffff_ffff]
2733 *
2734 * Now, suppose that register range is in fact tighter:
2735 * [0xffff_ffff_8000_0000, 0x0000_0000_ffff_ffff] (R)
2736 * Also suppose that it's 32-bit range is positive,
2737 * meaning that lower 32-bits of the full 64-bit register
2738 * are in the range:
2739 * [0x0000_0000, 0x7fff_ffff] (W)
2740 *
2741 * If this happens, then any value in a range:
2742 * [0xffff_ffff_0000_0000, 0xffff_ffff_7fff_ffff]
2743 * is smaller than a lowest bound of the range (R):
2744 * 0xffff_ffff_8000_0000
2745 * which means that upper bits of the full 64-bit register
2746 * can't be all 1s, when lower bits are in range (W).
2747 *
2748 * Note that:
2749 * - 0xffff_ffff_8000_0000 == (s64)S32_MIN
2750 * - 0x0000_0000_7fff_ffff == (s64)S32_MAX
2751 * These relations are used in the conditions below.
2752 */
2753 if (reg->s32_min_value >= 0 && reg->smin_value >= S32_MIN && reg->smax_value <= S32_MAX) {
2754 reg->smin_value = reg->s32_min_value;
2755 reg->smax_value = reg->s32_max_value;
2756 reg->umin_value = reg->s32_min_value;
2757 reg->umax_value = reg->s32_max_value;
2758 reg->var_off = tnum_intersect(reg->var_off,
2759 tnum_range(reg->smin_value, reg->smax_value));
2760 }
2761 }
2762
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH] bpf: fix umin/umax when lower bits fall outside u32 range
2026-03-27 19:48 [PATCH] bpf: fix umin/umax when lower bits fall outside u32 range Helen Koike
` (2 preceding siblings ...)
2026-03-30 16:24 ` kernel test robot
@ 2026-03-30 17:53 ` kernel test robot
3 siblings, 0 replies; 6+ messages in thread
From: kernel test robot @ 2026-03-30 17:53 UTC (permalink / raw)
To: Helen Koike, andrii, eddyz87, shung-hsi.yu, yonghong.song, ast,
bpf, linux-kernel, kernel-dev
Cc: oe-kbuild-all
Hi Helen,
kernel test robot noticed the following build warnings:
[auto build test WARNING on bpf-next/net]
[also build test WARNING on bpf-next/master bpf/master linus/master v7.0-rc6 next-20260327]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Helen-Koike/bpf-fix-umin-umax-when-lower-bits-fall-outside-u32-range/20260330-171706
base: https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git net
patch link: https://lore.kernel.org/r/20260327194849.855397-1-koike%40igalia.com
patch subject: [PATCH] bpf: fix umin/umax when lower bits fall outside u32 range
config: i386-randconfig-013-20260330 (https://download.01.org/0day-ci/archive/20260331/202603310103.qoJg885q-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260331/202603310103.qoJg885q-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603310103.qoJg885q-lkp@intel.com/
All warnings (new ones prefixed by >>):
kernel/bpf/verifier.c: In function '__reg_deduce_mixed_bounds':
>> kernel/bpf/verifier.c:2699:63: warning: suggest parentheses around arithmetic in operand of '|' [-Wparentheses]
2699 | new_umin = (reg->umin_value & ~0xffffffffULL) + (1ULL << 32) |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~
kernel/bpf/verifier.c:2710:63: warning: suggest parentheses around arithmetic in operand of '|' [-Wparentheses]
2710 | new_umax = (reg->umax_value & ~0xffffffffULL) - (1ULL << 32) |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~
vim +2699 kernel/bpf/verifier.c
2675
2676 static void __reg_deduce_mixed_bounds(struct bpf_reg_state *reg)
2677 {
2678 /* Try to tighten 64-bit bounds from 32-bit knowledge, using 32-bit
2679 * values on both sides of 64-bit range in hope to have tighter range.
2680 * E.g., if r1 is [0x1'00000000, 0x3'80000000], and we learn from
2681 * 32-bit signed > 0 operation that s32 bounds are now [1; 0x7fffffff].
2682 * With this, we can substitute 1 as low 32-bits of _low_ 64-bit bound
2683 * (0x100000000 -> 0x100000001) and 0x7fffffff as low 32-bits of
2684 * _high_ 64-bit bound (0x380000000 -> 0x37fffffff) and arrive at a
2685 * better overall bounds for r1 as [0x1'000000001; 0x3'7fffffff].
2686 * We just need to make sure that derived bounds we are intersecting
2687 * with are well-formed ranges in respective s64 or u64 domain, just
2688 * like we do with similar kinds of 32-to-64 or 64-to-32 adjustments.
2689 */
2690 __u64 new_umin, new_umax;
2691 __s64 new_smin, new_smax;
2692
2693 /*
2694 * If (u32)umin > u32_max, no value in the current upper-32-bit block
2695 * satisfies [u32_min, u32_max] while being >= umin; advance umin to
2696 * the next block. Otherwise apply standard u32->u64 tightening.
2697 */
2698 if ((u32)reg->umin_value > reg->u32_max_value)
> 2699 new_umin = (reg->umin_value & ~0xffffffffULL) + (1ULL << 32) |
2700 reg->u32_min_value;
2701 else
2702 new_umin = (reg->umin_value & ~0xffffffffULL) |
2703 reg->u32_min_value;
2704
2705 /*
2706 * Symmetrically, if (u32)umax < u32_min, retreat umax to the
2707 * previous block. Otherwise apply standard u32->u64 tightening.
2708 */
2709 if ((u32)reg->umax_value < reg->u32_min_value)
2710 new_umax = (reg->umax_value & ~0xffffffffULL) - (1ULL << 32) |
2711 reg->u32_max_value;
2712 else
2713 new_umax = (reg->umax_value & ~0xffffffffULL) |
2714 reg->u32_max_value;
2715
2716 reg->umin_value = max_t(u64, reg->umin_value, new_umin);
2717 reg->umax_value = min_t(u64, reg->umax_value, new_umax);
2718 /* u32 -> s64 tightening, u32 range embedded into s64 preserves range validity */
2719 new_smin = (reg->smin_value & ~0xffffffffULL) | reg->u32_min_value;
2720 new_smax = (reg->smax_value & ~0xffffffffULL) | reg->u32_max_value;
2721 reg->smin_value = max_t(s64, reg->smin_value, new_smin);
2722 reg->smax_value = min_t(s64, reg->smax_value, new_smax);
2723
2724 /* Here we would like to handle a special case after sign extending load,
2725 * when upper bits for a 64-bit range are all 1s or all 0s.
2726 *
2727 * Upper bits are all 1s when register is in a range:
2728 * [0xffff_ffff_0000_0000, 0xffff_ffff_ffff_ffff]
2729 * Upper bits are all 0s when register is in a range:
2730 * [0x0000_0000_0000_0000, 0x0000_0000_ffff_ffff]
2731 * Together this forms are continuous range:
2732 * [0xffff_ffff_0000_0000, 0x0000_0000_ffff_ffff]
2733 *
2734 * Now, suppose that register range is in fact tighter:
2735 * [0xffff_ffff_8000_0000, 0x0000_0000_ffff_ffff] (R)
2736 * Also suppose that it's 32-bit range is positive,
2737 * meaning that lower 32-bits of the full 64-bit register
2738 * are in the range:
2739 * [0x0000_0000, 0x7fff_ffff] (W)
2740 *
2741 * If this happens, then any value in a range:
2742 * [0xffff_ffff_0000_0000, 0xffff_ffff_7fff_ffff]
2743 * is smaller than a lowest bound of the range (R):
2744 * 0xffff_ffff_8000_0000
2745 * which means that upper bits of the full 64-bit register
2746 * can't be all 1s, when lower bits are in range (W).
2747 *
2748 * Note that:
2749 * - 0xffff_ffff_8000_0000 == (s64)S32_MIN
2750 * - 0x0000_0000_7fff_ffff == (s64)S32_MAX
2751 * These relations are used in the conditions below.
2752 */
2753 if (reg->s32_min_value >= 0 && reg->smin_value >= S32_MIN && reg->smax_value <= S32_MAX) {
2754 reg->smin_value = reg->s32_min_value;
2755 reg->smax_value = reg->s32_max_value;
2756 reg->umin_value = reg->s32_min_value;
2757 reg->umax_value = reg->s32_max_value;
2758 reg->var_off = tnum_intersect(reg->var_off,
2759 tnum_range(reg->smin_value, reg->smax_value));
2760 }
2761 }
2762
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 6+ messages in thread