Sibyte provides a 64-bit read-only counter that counts at half the processor
frequency. This counter can be accessed coherently from both cores. Use this as the preferred timecounter for the SWARM kernels. The CP0 COUNT register is unusable as the timecounter on SMP platforms because the COUNT registers on different CPUs are not guaranteed to be in sync.
This commit is contained in:
parent
293f20dffb
commit
69a5a0bfea
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=205364
@ -34,6 +34,14 @@ void mips_timer_init_params(uint64_t, int);
|
||||
extern uint64_t counter_freq;
|
||||
extern int clocks_running;
|
||||
|
||||
/*
|
||||
* The 'platform_timecounter' pointer may be used to register a
|
||||
* platform-specific timecounter.
|
||||
*
|
||||
* A default timecounter based on the CP0 COUNT register is always registered.
|
||||
*/
|
||||
extern struct timecounter *platform_timecounter;
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* !_MACHINE_CLOCK_H_ */
|
||||
|
@ -54,6 +54,8 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
uint64_t counter_freq;
|
||||
|
||||
struct timecounter *platform_timecounter;
|
||||
|
||||
static uint64_t cycles_per_tick;
|
||||
static uint64_t cycles_per_usec;
|
||||
static uint64_t cycles_per_hz, cycles_per_stathz, cycles_per_profhz;
|
||||
@ -103,6 +105,9 @@ platform_initclocks(void)
|
||||
{
|
||||
|
||||
tc_init(&counter_timecounter);
|
||||
|
||||
if (platform_timecounter != NULL)
|
||||
tc_init(platform_timecounter);
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
|
@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/sysent.h>
|
||||
#include <sys/sysproto.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/timetc.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_object.h>
|
||||
@ -364,6 +365,32 @@ platform_start_ap(int cpuid)
|
||||
}
|
||||
#endif /* SMP */
|
||||
|
||||
static u_int
|
||||
sb_get_timecount(struct timecounter *tc)
|
||||
{
|
||||
|
||||
return ((u_int)sb_zbbus_cycle_count());
|
||||
}
|
||||
|
||||
static void
|
||||
sb_timecounter_init(void)
|
||||
{
|
||||
static struct timecounter sb_timecounter = {
|
||||
sb_get_timecount,
|
||||
NULL,
|
||||
~0u,
|
||||
0,
|
||||
"sibyte_zbbus_counter",
|
||||
2000
|
||||
};
|
||||
|
||||
/*
|
||||
* The ZBbus cycle counter runs at half the cpu frequency.
|
||||
*/
|
||||
sb_timecounter.tc_frequency = sb_cpu_speed() / 2;
|
||||
platform_timecounter = &sb_timecounter;
|
||||
}
|
||||
|
||||
void
|
||||
platform_start(__register_t a0, __register_t a1, __register_t a2,
|
||||
__register_t a3)
|
||||
@ -378,6 +405,7 @@ platform_start(__register_t a0, __register_t a1, __register_t a2,
|
||||
mips_postboot_fixup();
|
||||
|
||||
sb_intr_init(0);
|
||||
sb_timecounter_init();
|
||||
|
||||
/* Initialize pcpu stuff */
|
||||
mips_pcpu0_init();
|
||||
@ -400,4 +428,6 @@ platform_start(__register_t a0, __register_t a1, __register_t a2,
|
||||
mips_init();
|
||||
|
||||
mips_timer_init_params(sb_cpu_speed(), 0);
|
||||
|
||||
set_cputicker(sb_zbbus_cycle_count, sb_cpu_speed() / 2, 1);
|
||||
}
|
||||
|
@ -56,6 +56,8 @@ extern uint64_t sb_load64(uint32_t addr);
|
||||
#define SYSCFG_ADDR MIPS_PHYS_TO_KSEG1(0x10020008)
|
||||
#define SYSCFG_PLLDIV(x) GET_VAL_64((x), 7, 5)
|
||||
|
||||
#define ZBBUS_CYCLE_COUNT_ADDR MIPS_PHYS_TO_KSEG1(0x10030000)
|
||||
|
||||
#define INTSRC_MASK_ADDR(cpu) \
|
||||
(MIPS_PHYS_TO_KSEG1(0x10020028) | ((cpu) << 13))
|
||||
|
||||
@ -82,6 +84,13 @@ sb_write_syscfg(uint64_t val)
|
||||
sb_store64(SYSCFG_ADDR, val);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
sb_zbbus_cycle_count(void)
|
||||
{
|
||||
|
||||
return (sb_load64(ZBBUS_CYCLE_COUNT_ADDR));
|
||||
}
|
||||
|
||||
uint64_t
|
||||
sb_cpu_speed(void)
|
||||
{
|
||||
|
@ -31,6 +31,7 @@
|
||||
|
||||
#define NUM_INTSRC 64 /* total number of interrupt sources */
|
||||
|
||||
uint64_t sb_zbbus_cycle_count(void);
|
||||
uint64_t sb_cpu_speed(void);
|
||||
void sb_system_reset(void);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user