]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
LoongArch: Adjust time routines for 32BIT/64BIT
authorHuacai Chen <chenhuacai@loongson.cn>
Mon, 8 Dec 2025 10:09:17 +0000 (18:09 +0800)
committerHuacai Chen <chenhuacai@loongson.cn>
Mon, 8 Dec 2025 10:09:17 +0000 (18:09 +0800)
Adjust time routines for both 32BIT and 64BIT, including: rdtime_h() /
rdtime_l() definitions for 32BIT and rdtime_d() definition for 64BIT,
get_cycles() and get_cycles64() definitions for 32BIT/64BIT, show time
frequency info ("CPU MHz" and "BogoMIPS") in /proc/cpuinfo, etc.

Use do_div() for division which works on both 32BIT and 64BIT platforms.

Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
arch/loongarch/include/asm/loongarch.h
arch/loongarch/include/asm/timex.h
arch/loongarch/kernel/proc.c
arch/loongarch/kernel/syscall.c
arch/loongarch/kernel/time.c
arch/loongarch/kvm/vcpu.c

index 804341bd8d2ebadddb525f71a75349d8b698b331..19e3f2c183fea2c180f9e41349365a604b329999 100644 (file)
 
 #ifndef __ASSEMBLER__
 
-static __always_inline u64 drdtime(void)
+#ifdef CONFIG_32BIT
+
+static __always_inline u32 rdtime_h(void)
+{
+       u32 val = 0;
+
+       __asm__ __volatile__(
+               "rdtimeh.w %0, $zero\n\t"
+               : "=r"(val)
+               :
+               );
+       return val;
+}
+
+static __always_inline u32 rdtime_l(void)
+{
+       u32 val = 0;
+
+       __asm__ __volatile__(
+               "rdtimel.w %0, $zero\n\t"
+               : "=r"(val)
+               :
+               );
+       return val;
+}
+
+#else
+
+static __always_inline u64 rdtime_d(void)
 {
        u64 val = 0;
 
@@ -1250,6 +1278,8 @@ static __always_inline u64 drdtime(void)
        return val;
 }
 
+#endif
+
 static inline unsigned int get_csr_cpuid(void)
 {
        return csr_read32(LOONGARCH_CSR_CPUID);
index fb41e9e7a222cb9570adc6b3909391bfed50d82d..9ea52fad969039447f2fc9bb70e3bc6c3eef94a5 100644 (file)
@@ -18,7 +18,38 @@ typedef unsigned long cycles_t;
 
 static inline cycles_t get_cycles(void)
 {
-       return drdtime();
+#ifdef CONFIG_32BIT
+       return rdtime_l();
+#else
+       return rdtime_d();
+#endif
+}
+
+#ifdef CONFIG_32BIT
+
+#define get_cycles_hi get_cycles_hi
+
+static inline cycles_t get_cycles_hi(void)
+{
+       return rdtime_h();
+}
+
+#endif
+
+static inline u64 get_cycles64(void)
+{
+#ifdef CONFIG_32BIT
+       u32 hi, lo;
+
+       do {
+               hi = rdtime_h();
+               lo = rdtime_l();
+       } while (hi != rdtime_h());
+
+       return ((u64)hi << 32) | lo;
+#else
+       return rdtime_d();
+#endif
 }
 
 #endif /* __KERNEL__ */
index 63d2b7e7e844b0647a3e0d988ec2adb6c77b9b14..a8800d20e11bd5ae5a00ed9eb52d7491cb1ec71b 100644 (file)
@@ -20,11 +20,14 @@ static int show_cpuinfo(struct seq_file *m, void *v)
        unsigned int prid = cpu_data[n].processor_id;
        unsigned int version = cpu_data[n].processor_id & 0xff;
        unsigned int fp_version = cpu_data[n].fpu_vers;
+       u64 freq = cpu_clock_freq, bogomips = lpj_fine * cpu_clock_freq;
 
 #ifdef CONFIG_SMP
        if (!cpu_online(n))
                return 0;
 #endif
+       do_div(freq, 10000);
+       do_div(bogomips, const_clock_freq * (5000/HZ));
 
        /*
         * For the first processor also print the system type
@@ -41,11 +44,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
        seq_printf(m, "PRID\t\t\t: %s (%08x)\n", id_to_core_name(prid), prid);
        seq_printf(m, "CPU Revision\t\t: 0x%02x\n", version);
        seq_printf(m, "FPU Revision\t\t: 0x%02x\n", fp_version);
-       seq_printf(m, "CPU MHz\t\t\t: %llu.%02llu\n",
-                     cpu_clock_freq / 1000000, (cpu_clock_freq / 10000) % 100);
-       seq_printf(m, "BogoMIPS\t\t: %llu.%02llu\n",
-                     (lpj_fine * cpu_clock_freq / const_clock_freq) / (500000/HZ),
-                     ((lpj_fine * cpu_clock_freq / const_clock_freq) / (5000/HZ)) % 100);
+       seq_printf(m, "CPU MHz\t\t\t: %u.%02u\n", (u32)freq / 100, (u32)freq % 100);
+       seq_printf(m, "BogoMIPS\t\t: %u.%02u\n", (u32)bogomips / 100, (u32)bogomips % 100);
        seq_printf(m, "TLB Entries\t\t: %d\n", cpu_data[n].tlbsize);
        seq_printf(m, "Address Sizes\t\t: %d bits physical, %d bits virtual\n",
                      cpu_pabits + 1, cpu_vabits + 1);
index 168bd97540f8cfc9be26d75843c5066c6630a0d2..ab94eb5ce039137ee7d13675412bf5a33f481e2b 100644 (file)
@@ -75,7 +75,7 @@ void noinstr __no_stack_protector do_syscall(struct pt_regs *regs)
         *
         * The resulting 6 bits of entropy is seen in SP[9:4].
         */
-       choose_random_kstack_offset(drdtime());
+       choose_random_kstack_offset(get_cycles());
 
        syscall_exit_to_user_mode(regs);
 }
index 1c31bf3a16ed559208855a38bac81d84f6f97e49..5892f6da07a512e855230686d36ded4b7b5b6d79 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/loongarch.h>
 #include <asm/paravirt.h>
 #include <asm/time.h>
+#include <asm/timex.h>
 
 u64 cpu_clock_freq;
 EXPORT_SYMBOL(cpu_clock_freq);
@@ -62,12 +63,12 @@ static int constant_set_state_oneshot(struct clock_event_device *evt)
 
 static int constant_set_state_periodic(struct clock_event_device *evt)
 {
-       unsigned long period;
        unsigned long timer_config;
+       u64 period = const_clock_freq;
 
        raw_spin_lock(&state_lock);
 
-       period = const_clock_freq / HZ;
+       do_div(period, HZ);
        timer_config = period & CSR_TCFG_VAL;
        timer_config |= (CSR_TCFG_PERIOD | CSR_TCFG_EN);
        csr_write(timer_config, LOONGARCH_CSR_TCFG);
@@ -120,7 +121,7 @@ static int arch_timer_dying(unsigned int cpu)
 
 static unsigned long get_loops_per_jiffy(void)
 {
-       unsigned long lpj = (unsigned long)const_clock_freq;
+       u64 lpj = const_clock_freq;
 
        do_div(lpj, HZ);
 
@@ -131,7 +132,7 @@ static long init_offset;
 
 void save_counter(void)
 {
-       init_offset = drdtime();
+       init_offset = get_cycles();
 }
 
 void sync_counter(void)
@@ -197,12 +198,12 @@ int constant_clockevent_init(void)
 
 static u64 read_const_counter(struct clocksource *clk)
 {
-       return drdtime();
+       return get_cycles64();
 }
 
 static noinstr u64 sched_clock_read(void)
 {
-       return drdtime();
+       return get_cycles64();
 }
 
 static struct clocksource clocksource_const = {
@@ -235,7 +236,7 @@ void __init time_init(void)
        else
                const_clock_freq = calc_const_freq();
 
-       init_offset = -(drdtime() - csr_read(LOONGARCH_CSR_CNTC));
+       init_offset = -(get_cycles() - csr_read(LOONGARCH_CSR_CNTC));
 
        constant_clockevent_init();
        constant_clocksource_init();
index 1245a6b358966f47025cf775a2925cb31ea32bbb..803224d297eb0c8b4dc54f55d227188c3c6b473c 100644 (file)
@@ -9,6 +9,7 @@
 #include <asm/loongarch.h>
 #include <asm/setup.h>
 #include <asm/time.h>
+#include <asm/timex.h>
 
 #define CREATE_TRACE_POINTS
 #include "trace.h"
@@ -811,7 +812,7 @@ static int kvm_get_one_reg(struct kvm_vcpu *vcpu,
        case KVM_REG_LOONGARCH_KVM:
                switch (reg->id) {
                case KVM_REG_LOONGARCH_COUNTER:
-                       *v = drdtime() + vcpu->kvm->arch.time_offset;
+                       *v = get_cycles() + vcpu->kvm->arch.time_offset;
                        break;
                case KVM_REG_LOONGARCH_DEBUG_INST:
                        *v = INSN_HVCL | KVM_HCALL_SWDBG;
@@ -906,7 +907,7 @@ static int kvm_set_one_reg(struct kvm_vcpu *vcpu,
                         * only set for the first time for smp system
                         */
                        if (vcpu->vcpu_id == 0)
-                               vcpu->kvm->arch.time_offset = (signed long)(v - drdtime());
+                               vcpu->kvm->arch.time_offset = (signed long)(v - get_cycles());
                        break;
                case KVM_REG_LOONGARCH_VCPU_RESET:
                        vcpu->arch.st.guest_addr = 0;