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
parent
4ad04e7c7e
commit
ced7814d3a
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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__ */
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue