diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/conf/files.mips | 1 | ||||
-rw-r--r-- | sys/mips/include/smp.h | 3 | ||||
-rw-r--r-- | sys/mips/mips/machdep.c | 2 | ||||
-rw-r--r-- | sys/mips/mips/mp_machdep.c | 23 | ||||
-rw-r--r-- | sys/mips/mips/tick.c | 228 | ||||
-rw-r--r-- | sys/mips/rmi/tick.c | 14 |
6 files changed, 140 insertions, 131 deletions
diff --git a/sys/conf/files.mips b/sys/conf/files.mips index 0bec97b..c33fa9a 100644 --- a/sys/conf/files.mips +++ b/sys/conf/files.mips @@ -88,6 +88,7 @@ libkern/umoddi3.c optional isa_mips32 #libkern/mips/strcmp.S standard #libkern/mips/strncmp.S standard +kern/kern_clocksource.c standard kern/link_elf_obj.c standard dev/cfe/cfe_api.c optional cfe diff --git a/sys/mips/include/smp.h b/sys/mips/include/smp.h index 216b9e7..cf2261c 100644 --- a/sys/mips/include/smp.h +++ b/sys/mips/include/smp.h @@ -27,9 +27,12 @@ #define IPI_STOP 0x0008 #define IPI_STOP_HARD 0x0008 #define IPI_PREEMPT 0x0010 +#define IPI_HARDCLOCK 0x0020 +#define IPI_STATCLOCK 0x0040 #ifndef LOCORE +void ipi_all_but_self(int ipi); void ipi_selected(cpumask_t cpus, int ipi); void smp_init_secondary(u_int32_t cpuid); void mpentry(void); diff --git a/sys/mips/mips/machdep.c b/sys/mips/mips/machdep.c index eede505..060e101 100644 --- a/sys/mips/mips/machdep.c +++ b/sys/mips/mips/machdep.c @@ -307,7 +307,9 @@ mips_proc0_init(void) void cpu_initclocks(void) { + platform_initclocks(); + cpu_initclocks_bsp(); } struct msgbuf *msgbufp=0; diff --git a/sys/mips/mips/mp_machdep.c b/sys/mips/mips/mp_machdep.c index 00a91fb..5764326 100644 --- a/sys/mips/mips/mp_machdep.c +++ b/sys/mips/mips/mp_machdep.c @@ -71,6 +71,13 @@ ipi_send(struct pcpu *pc, int ipi) CTR1(KTR_SMP, "%s: sent", __func__); } +void +ipi_all_but_self(int ipi) +{ + + ipi_selected(PCPU_GET(other_cpus), ipi); +} + /* Send an IPI to a set of cpus. */ void ipi_selected(cpumask_t cpus, int ipi) @@ -146,6 +153,14 @@ mips_ipi_handler(void *arg) CTR1(KTR_SMP, "%s: IPI_PREEMPT", __func__); sched_preempt(curthread); break; + case IPI_HARDCLOCK: + CTR1(KTR_SMP, "%s: IPI_HARDCLOCK", __func__); + hardclockintr(arg);; + break; + case IPI_STATCLOCK: + CTR1(KTR_SMP, "%s: IPI_STATCLOCK", __func__); + statclockintr(arg);; + break; default: panic("Unknown IPI 0x%0x on cpu %d", ipi, curcpu); } @@ -290,13 +305,11 @@ smp_init_secondary(u_int32_t cpuid) while (smp_started == 0) ; /* nothing */ - /* - * Bootstrap the compare register. - */ - mips_wr_compare(mips_rd_count() + counter_freq / hz); - intr_enable(); + /* Start per-CPU event timers. */ + cpu_initclocks_ap(); + /* enter the scheduler */ sched_throw(NULL); diff --git a/sys/mips/mips/tick.c b/sys/mips/mips/tick.c index 5432c42..06c9aa7 100644 --- a/sys/mips/mips/tick.c +++ b/sys/mips/mips/tick.c @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include <sys/power.h> #include <sys/smp.h> #include <sys/time.h> +#include <sys/timeet.h> #include <sys/timetc.h> #include <machine/hwfunc.h> @@ -56,8 +57,8 @@ uint64_t counter_freq; struct timecounter *platform_timecounter; -static uint64_t cycles_per_tick; -static uint64_t cycles_per_usec; +static DPCPU_DEFINE(uint32_t, cycles_per_tick); +static uint32_t cycles_per_usec; static u_int32_t counter_upper = 0; static u_int32_t counter_lower_last = 0; @@ -65,6 +66,15 @@ static u_int32_t counter_lower_last = 0; static DPCPU_DEFINE(uint32_t, compare_ticks); static DPCPU_DEFINE(uint32_t, lost_ticks); +struct clock_softc { + int intr_rid; + struct resource *intr_res; + void *intr_handler; + struct timecounter tc; + struct eventtimer et; +}; +static struct clock_softc *softc; + /* * Device methods */ @@ -73,15 +83,6 @@ static void clock_identify(driver_t *, device_t); static int clock_attach(device_t); static unsigned counter_get_timecount(struct timecounter *tc); -static struct timecounter counter_timecounter = { - counter_get_timecount, /* get_timecount */ - 0, /* no poll_pps */ - 0xffffffffu, /* counter_mask */ - 0, /* frequency */ - "MIPS32", /* name */ - 800, /* quality (adjusted in code) */ -}; - void mips_timer_early_init(uint64_t clock_hz) { @@ -94,8 +95,6 @@ void platform_initclocks(void) { - tc_init(&counter_timecounter); - if (platform_timecounter != NULL) tc_init(platform_timecounter); } @@ -140,40 +139,7 @@ mips_timer_init_params(uint64_t platform_counter_freq, int double_count) if (double_count != 0) counter_freq /= 2; - /* - * We want to run stathz in the neighborhood of 128hz. We would - * like profhz to run as often as possible, so we let it run on - * each clock tick. We try to honor the requested 'hz' value as - * much as possible. - * - * If 'hz' is above 1500, then we just let the timer - * (and profhz) run at hz. If 'hz' is below 1500 but above - * 750, then we let the timer run at 2 * 'hz'. If 'hz' - * is below 750 then we let the timer run at 4 * 'hz'. - */ - if (hz >= 1500) - timer1hz = hz; - else if (hz >= 750) - timer1hz = hz * 2; - else - timer1hz = hz * 4; - - if (timer1hz < 128) - stathz = timer1hz; - else - stathz = timer1hz / (timer1hz / 128); - profhz = timer1hz; - - cycles_per_tick = counter_freq / timer1hz; cycles_per_usec = counter_freq / (1 * 1000 * 1000); - - counter_timecounter.tc_frequency = counter_freq; - printf("hz=%d timer1hz:%d cyl_per_tick:%jd cyl_per_usec:%jd freq:%jd\n", - hz, - timer1hz, - cycles_per_tick, - cycles_per_usec, - counter_freq); set_cputicker(tick_ticker, counter_freq, 1); } @@ -183,13 +149,14 @@ sysctl_machdep_counter_freq(SYSCTL_HANDLER_ARGS) int error; uint64_t freq; - if (counter_timecounter.tc_frequency == 0) + if (softc == NULL) return (EOPNOTSUPP); freq = counter_freq; error = sysctl_handle_int(oidp, &freq, sizeof(freq), req); if (error == 0 && req->newptr != NULL) { counter_freq = freq; - counter_timecounter.tc_frequency = counter_freq; + softc->et.et_frequency = counter_freq; + softc->tc.tc_frequency = counter_freq; } return (error); } @@ -205,19 +172,6 @@ counter_get_timecount(struct timecounter *tc) return (mips_rd_count()); } - -void -cpu_startprofclock(void) -{ - /* nothing to do */ -} - -void -cpu_stopprofclock(void) -{ - /* nothing to do */ -} - /* * Wait for about n microseconds (at least!). */ @@ -251,23 +205,62 @@ DELAY(int n) } } +static int +clock_start(struct eventtimer *et, + struct bintime *first, struct bintime *period) +{ + uint32_t fdiv, div, next; + + if (period != NULL) { + div = (et->et_frequency * (period->frac >> 32)) >> 32; + if (period->sec != 0) + div += et->et_frequency * period->sec; + } else + div = 0; + if (first != NULL) { + fdiv = (et->et_frequency * (first->frac >> 32)) >> 32; + if (first->sec != 0) + fdiv += et->et_frequency * first->sec; + } else + fdiv = div; + DPCPU_SET(cycles_per_tick, div); + next = mips_rd_count() + fdiv; + DPCPU_SET(compare_ticks, next); + mips_wr_compare(next); + return (0); +} + +static int +clock_stop(struct eventtimer *et) +{ + + DPCPU_SET(cycles_per_tick, 0); + mips_wr_compare(0xffffffff); + return (0); +} + /* * Device section of file below */ static int clock_intr(void *arg) { - struct trapframe *tf; + struct clock_softc *sc = (struct clock_softc *)arg; + uint32_t cycles_per_tick; uint32_t count, compare_last, compare_next, lost_ticks; + cycles_per_tick = DPCPU_GET(cycles_per_tick); /* * Set next clock edge. */ count = mips_rd_count(); compare_last = DPCPU_GET(compare_ticks); - compare_next = count + cycles_per_tick; - DPCPU_SET(compare_ticks, compare_next); - mips_wr_compare(compare_next); + if (cycles_per_tick > 0) { + compare_next = count + cycles_per_tick; + DPCPU_SET(compare_ticks, compare_next); + mips_wr_compare(compare_next); + } else + mips_wr_compare(0xffffffff); critical_enter(); if (count < counter_lower_last) { @@ -275,45 +268,34 @@ clock_intr(void *arg) counter_lower_last = count; } - /* - * Magic. Setting up with an arg of NULL means we get passed tf. - */ - tf = (struct trapframe *)arg; + if (cycles_per_tick > 0) { - /* - * Account for the "lost time" between when the timer interrupt fired - * and when 'clock_intr' actually started executing. - */ - lost_ticks = DPCPU_GET(lost_ticks); - lost_ticks += count - compare_last; - - /* - * If the COUNT and COMPARE registers are no longer in sync then make - * up some reasonable value for the 'lost_ticks'. - * - * This could happen, for e.g., after we resume normal operations after - * exiting the debugger. - */ - if (lost_ticks > 2 * cycles_per_tick) - lost_ticks = cycles_per_tick; - - while (lost_ticks >= cycles_per_tick) { - timer1clock(TRAPF_USERMODE(tf), tf->pc); - lost_ticks -= cycles_per_tick; + /* + * Account for the "lost time" between when the timer interrupt + * fired and when 'clock_intr' actually started executing. + */ + lost_ticks = DPCPU_GET(lost_ticks); + lost_ticks += count - compare_last; + + /* + * If the COUNT and COMPARE registers are no longer in sync + * then make up some reasonable value for the 'lost_ticks'. + * + * This could happen, for e.g., after we resume normal + * operations after exiting the debugger. + */ + if (lost_ticks > 2 * cycles_per_tick) + lost_ticks = cycles_per_tick; + + while (lost_ticks >= cycles_per_tick) { + if (sc->et.et_active) + sc->et.et_event_cb(&sc->et, sc->et.et_arg); + lost_ticks -= cycles_per_tick; + } + DPCPU_SET(lost_ticks, lost_ticks); } - DPCPU_SET(lost_ticks, lost_ticks); - -#ifdef KDTRACE_HOOKS - /* - * If the DTrace hooks are configured and a callback function - * has been registered, then call it to process the high speed - * timers. - */ - int cpu = PCPU_GET(cpuid); - if (cyclic_clock_func[cpu] != NULL) - (*cyclic_clock_func[cpu])(tf); -#endif - timer1clock(TRAPF_USERMODE(tf), tf->pc); + if (sc->et.et_active) + sc->et.et_event_cb(&sc->et, sc->et.et_arg); critical_exit(); return (FILTER_HANDLED); } @@ -339,25 +321,45 @@ clock_identify(driver_t * drv, device_t parent) static int clock_attach(device_t dev) { - struct resource *irq; + struct clock_softc *sc; int error; - int rid; - rid = 0; - irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 5, 5, 1, RF_ACTIVE); - if (irq == NULL) { + softc = sc = device_get_softc(dev); + sc->intr_rid = 0; + sc->intr_res = bus_alloc_resource(dev, + SYS_RES_IRQ, &sc->intr_rid, 5, 5, 1, RF_ACTIVE); + if (sc->intr_res == NULL) { device_printf(dev, "failed to allocate irq\n"); return (ENXIO); } - error = bus_setup_intr(dev, irq, INTR_TYPE_CLK, clock_intr, NULL, - NULL, NULL); - + error = bus_setup_intr(dev, sc->intr_res, INTR_TYPE_CLK, + clock_intr, NULL, sc, &sc->intr_handler); if (error != 0) { device_printf(dev, "bus_setup_intr returned %d\n", error); return (error); } - mips_wr_compare(mips_rd_count() + counter_freq / hz); + sc->tc.tc_get_timecount = counter_get_timecount; + sc->tc.tc_counter_mask = 0xffffffff; + sc->tc.tc_frequency = counter_freq; + sc->tc.tc_name = "MIPS32"; + sc->tc.tc_quality = 800; + sc->tc.tc_priv = sc; + tc_init(&sc->tc); + sc->et.et_name = "MIPS32"; + sc->et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT | + ET_FLAGS_PERCPU; + sc->et.et_quality = 800; + sc->et.et_frequency = counter_freq; + sc->et.et_min_period.sec = 0; + sc->et.et_min_period.frac = 0x00004000LLU << 32; + sc->et.et_max_period.sec = 0xfffffffeU / sc->et.et_frequency; + sc->et.et_max_period.frac = + ((0xfffffffeLLU << 32) / sc->et.et_frequency) << 32; + sc->et.et_start = clock_start; + sc->et.et_stop = clock_stop; + sc->et.et_priv = sc; + et_register(&sc->et); return (0); } @@ -373,7 +375,9 @@ static device_method_t clock_methods[] = { }; static driver_t clock_driver = { - "clock", clock_methods, 32 + "clock", + clock_methods, + sizeof(struct clock_softc), }; static devclass_t clock_devclass; diff --git a/sys/mips/rmi/tick.c b/sys/mips/rmi/tick.c index aaeb0e9..08dc4ad 100644 --- a/sys/mips/rmi/tick.c +++ b/sys/mips/rmi/tick.c @@ -72,20 +72,6 @@ tick_init(void) tc_init(&counter_timecounter); } - -void -cpu_startprofclock(void) -{ - /* nothing to do */ -} - -void -cpu_stopprofclock(void) -{ - /* nothing to do */ -} - - static int sysctl_machdep_counter_freq(SYSCTL_HANDLER_ARGS) { |