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__
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);

View 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__ */

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 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);

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].
*/
choose_random_kstack_offset(drdtime());
choose_random_kstack_offset(get_cycles());
syscall_exit_to_user_mode(regs);
}

View 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();

View 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;