LoongArch: Adjust time routines for 32BIT/64BIT

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>
pull/1354/merge
Huacai Chen 2025-12-08 18:09:17 +08:00
parent 4ad04e7c7e
commit ced7814d3a
6 changed files with 80 additions and 17 deletions

View File

@ -1238,7 +1238,35 @@
#ifndef __ASSEMBLER__ #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; u64 val = 0;
@ -1250,6 +1278,8 @@ static __always_inline u64 drdtime(void)
return val; return val;
} }
#endif
static inline unsigned int get_csr_cpuid(void) static inline unsigned int get_csr_cpuid(void)
{ {
return csr_read32(LOONGARCH_CSR_CPUID); return csr_read32(LOONGARCH_CSR_CPUID);

View File

@ -18,7 +18,38 @@ typedef unsigned long cycles_t;
static inline cycles_t get_cycles(void) 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__ */ #endif /* __KERNEL__ */

View 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 prid = cpu_data[n].processor_id;
unsigned int version = cpu_data[n].processor_id & 0xff; unsigned int version = cpu_data[n].processor_id & 0xff;
unsigned int fp_version = cpu_data[n].fpu_vers; unsigned int fp_version = cpu_data[n].fpu_vers;
u64 freq = cpu_clock_freq, bogomips = lpj_fine * cpu_clock_freq;
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
if (!cpu_online(n)) if (!cpu_online(n))
return 0; return 0;
#endif #endif
do_div(freq, 10000);
do_div(bogomips, const_clock_freq * (5000/HZ));
/* /*
* For the first processor also print the system type * 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, "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, "CPU Revision\t\t: 0x%02x\n", version);
seq_printf(m, "FPU Revision\t\t: 0x%02x\n", fp_version); seq_printf(m, "FPU Revision\t\t: 0x%02x\n", fp_version);
seq_printf(m, "CPU MHz\t\t\t: %llu.%02llu\n", seq_printf(m, "CPU MHz\t\t\t: %u.%02u\n", (u32)freq / 100, (u32)freq % 100);
cpu_clock_freq / 1000000, (cpu_clock_freq / 10000) % 100); seq_printf(m, "BogoMIPS\t\t: %u.%02u\n", (u32)bogomips / 100, (u32)bogomips % 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, "TLB Entries\t\t: %d\n", cpu_data[n].tlbsize); 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", seq_printf(m, "Address Sizes\t\t: %d bits physical, %d bits virtual\n",
cpu_pabits + 1, cpu_vabits + 1); cpu_pabits + 1, cpu_vabits + 1);

View 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]. * 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); syscall_exit_to_user_mode(regs);
} }

View File

@ -18,6 +18,7 @@
#include <asm/loongarch.h> #include <asm/loongarch.h>
#include <asm/paravirt.h> #include <asm/paravirt.h>
#include <asm/time.h> #include <asm/time.h>
#include <asm/timex.h>
u64 cpu_clock_freq; u64 cpu_clock_freq;
EXPORT_SYMBOL(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) static int constant_set_state_periodic(struct clock_event_device *evt)
{ {
unsigned long period;
unsigned long timer_config; unsigned long timer_config;
u64 period = const_clock_freq;
raw_spin_lock(&state_lock); raw_spin_lock(&state_lock);
period = const_clock_freq / HZ; do_div(period, HZ);
timer_config = period & CSR_TCFG_VAL; timer_config = period & CSR_TCFG_VAL;
timer_config |= (CSR_TCFG_PERIOD | CSR_TCFG_EN); timer_config |= (CSR_TCFG_PERIOD | CSR_TCFG_EN);
csr_write(timer_config, LOONGARCH_CSR_TCFG); 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) 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); do_div(lpj, HZ);
@ -131,7 +132,7 @@ static long init_offset;
void save_counter(void) void save_counter(void)
{ {
init_offset = drdtime(); init_offset = get_cycles();
} }
void sync_counter(void) void sync_counter(void)
@ -197,12 +198,12 @@ int constant_clockevent_init(void)
static u64 read_const_counter(struct clocksource *clk) static u64 read_const_counter(struct clocksource *clk)
{ {
return drdtime(); return get_cycles64();
} }
static noinstr u64 sched_clock_read(void) static noinstr u64 sched_clock_read(void)
{ {
return drdtime(); return get_cycles64();
} }
static struct clocksource clocksource_const = { static struct clocksource clocksource_const = {
@ -235,7 +236,7 @@ void __init time_init(void)
else else
const_clock_freq = calc_const_freq(); 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_clockevent_init();
constant_clocksource_init(); constant_clocksource_init();

View File

@ -9,6 +9,7 @@
#include <asm/loongarch.h> #include <asm/loongarch.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/time.h> #include <asm/time.h>
#include <asm/timex.h>
#define CREATE_TRACE_POINTS #define CREATE_TRACE_POINTS
#include "trace.h" #include "trace.h"
@ -811,7 +812,7 @@ static int kvm_get_one_reg(struct kvm_vcpu *vcpu,
case KVM_REG_LOONGARCH_KVM: case KVM_REG_LOONGARCH_KVM:
switch (reg->id) { switch (reg->id) {
case KVM_REG_LOONGARCH_COUNTER: case KVM_REG_LOONGARCH_COUNTER:
*v = drdtime() + vcpu->kvm->arch.time_offset; *v = get_cycles() + vcpu->kvm->arch.time_offset;
break; break;
case KVM_REG_LOONGARCH_DEBUG_INST: case KVM_REG_LOONGARCH_DEBUG_INST:
*v = INSN_HVCL | KVM_HCALL_SWDBG; *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 * only set for the first time for smp system
*/ */
if (vcpu->vcpu_id == 0) 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; break;
case KVM_REG_LOONGARCH_VCPU_RESET: case KVM_REG_LOONGARCH_VCPU_RESET:
vcpu->arch.st.guest_addr = 0; vcpu->arch.st.guest_addr = 0;