Patch "clocksource/drivers/arm_arch_timer: Fix XGene-1 TVAL register math error" has been added to the 6.0-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    clocksource/drivers/arm_arch_timer: Fix XGene-1 TVAL register math error

to the 6.0-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     clocksource-drivers-arm_arch_timer-fix-xgene-1-tval-.patch
and it can be found in the queue-6.0 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 37b5ba5713be78835b7b623ad1f3b89acf51d6d8
Author: Joe Korty <joe.korty@xxxxxxxxxxxxxxxxx>
Date:   Mon Nov 21 14:53:43 2022 +0000

    clocksource/drivers/arm_arch_timer: Fix XGene-1 TVAL register math error
    
    [ Upstream commit 839a973988a94c15002cbd81536e4af6ced2bd30 ]
    
    The TVAL register is 32 bit signed.  Thus only the lower 31 bits are
    available to specify when an interrupt is to occur at some time in the
    near future.  Attempting to specify a larger interval with TVAL results
    in a negative time delta which means the timer fires immediately upon
    being programmed, rather than firing at that expected future time.
    
    The solution is for Linux to declare that TVAL is a 31 bit register rather
    than give its true size of 32 bits.  This prevents Linux from programming
    TVAL with a too-large value.  Note that, prior to 5.16, this little trick
    was the standard way to handle TVAL in Linux, so there is nothing new
    happening here on that front.
    
    The softlockup detector hides the issue, because it keeps generating
    short timer deadlines that are within the scope of the broken timer.
    
    Disabling it, it starts using NO_HZ with much longer timer deadlines, which
    turns into an interrupt flood:
    
     11: 1124855130  949168462  758009394   76417474  104782230   30210281
             310890 1734323687     GICv2  29 Level     arch_timer
    
    And "much longer" isn't that long: it takes less than 43s to underflow
    TVAL at 50MHz (the frequency of the counter on XGene-1).
    
    Some comments on the v1 version of this patch by Marc Zyngier:
    
      XGene implements CVAL (a 64bit comparator) in terms of TVAL (a countdown
      register) instead of the other way around. TVAL being a 32bit register,
      the width of the counter should equally be 32.  However, TVAL is a
      *signed* value, and keeps counting down in the negative range once the
      timer fires.
    
      It means that any TVAL value with bit 31 set will fire immediately,
      as it cannot be distinguished from an already expired timer. Reducing
      the timer range back to a paltry 31 bits papers over the issue.
    
      Another problem cannot be fixed though, which is that the timer interrupt
      *must* be handled within the negative countdown period, or the interrupt
      will be lost (TVAL will rollover to a positive value, indicative of a
      new timer deadline).
    
    Fixes: 012f18850452 ("clocksource/drivers/arm_arch_timer: Work around broken CVAL implementations")
    Signed-off-by: Joe Korty <joe.korty@xxxxxxxxxxxxxxxxx>
    Signed-off-by: Marc Zyngier <maz@xxxxxxxxxx>
    Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
    Reviewed-by: Marc Zyngier <maz@xxxxxxxxxx>
    Link: https://lore.kernel.org/r/20221024165422.GA51107@xxxxxxxxxxxxxxxxxxxxxxxx
    Link: https://lore.kernel.org/r/20221121145343.896018-1-maz@xxxxxxxxxx
    
    [maz: revamped the commit message]
    
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index a7ff77550e17..933bb960490d 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -806,6 +806,9 @@ static u64 __arch_timer_check_delta(void)
 		/*
 		 * XGene-1 implements CVAL in terms of TVAL, meaning
 		 * that the maximum timer range is 32bit. Shame on them.
+		 *
+		 * Note that TVAL is signed, thus has only 31 of its
+		 * 32 bits to express magnitude.
 		 */
 		MIDR_ALL_VERSIONS(MIDR_CPU_MODEL(ARM_CPU_IMP_APM,
 						 APM_CPU_PART_POTENZA)),
@@ -813,8 +816,8 @@ static u64 __arch_timer_check_delta(void)
 	};
 
 	if (is_midr_in_range_list(read_cpuid_id(), broken_cval_midrs)) {
-		pr_warn_once("Broken CNTx_CVAL_EL1, limiting width to 32bits");
-		return CLOCKSOURCE_MASK(32);
+		pr_warn_once("Broken CNTx_CVAL_EL1, using 31 bit TVAL instead.\n");
+		return CLOCKSOURCE_MASK(31);
 	}
 #endif
 	return CLOCKSOURCE_MASK(arch_counter_get_width());



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux