diff options
author | 2020-06-10 19:06:53 +0000 | |
---|---|---|
committer | 2020-06-10 19:06:53 +0000 | |
commit | ff56acc25e8db3a5cb1bd6491e816eb5452e11af (patch) | |
tree | 279302e63d8ba883f51cac2bf6f50eaa853b4378 | |
parent | Allocate MSIs from the range provided by the device tree and bind them (diff) | |
download | wireguard-openbsd-ff56acc25e8db3a5cb1bd6491e816eb5452e11af.tar.xz wireguard-openbsd-ff56acc25e8db3a5cb1bd6491e816eb5452e11af.zip |
Add clock interrupt support, adapted from the randomized dual clock
implementation from Dale Rahn but relicensed (with his permission)
under our standard ISC license.
-rw-r--r-- | sys/arch/powerpc64/conf/files.powerpc64 | 3 | ||||
-rw-r--r-- | sys/arch/powerpc64/include/cpu.h | 8 | ||||
-rw-r--r-- | sys/arch/powerpc64/powerpc64/clock.c | 186 | ||||
-rw-r--r-- | sys/arch/powerpc64/powerpc64/cpu.c | 13 | ||||
-rw-r--r-- | sys/arch/powerpc64/powerpc64/machdep.c | 14 | ||||
-rw-r--r-- | sys/arch/powerpc64/powerpc64/trap.c | 13 |
6 files changed, 209 insertions, 28 deletions
diff --git a/sys/arch/powerpc64/conf/files.powerpc64 b/sys/arch/powerpc64/conf/files.powerpc64 index e54b7bd7bfa..24919fd4741 100644 --- a/sys/arch/powerpc64/conf/files.powerpc64 +++ b/sys/arch/powerpc64/conf/files.powerpc64 @@ -1,4 +1,4 @@ -# $OpenBSD: files.powerpc64,v 1.10 2020/06/10 15:10:51 kettenis Exp $ +# $OpenBSD: files.powerpc64,v 1.11 2020/06/10 19:06:53 kettenis Exp $ maxpartitions 16 maxusers 2 8 128 @@ -7,6 +7,7 @@ file arch/powerpc64/powerpc64/locore.S file arch/powerpc64/powerpc64/autoconf.c file arch/powerpc64/powerpc64/bus_dma.c file arch/powerpc64/powerpc64/bus_space.c +file arch/powerpc64/powerpc64/clock.c file arch/powerpc64/powerpc64/conf.c file arch/powerpc64/powerpc64/cpu.c file arch/powerpc64/powerpc64/db_disasm.c ddb diff --git a/sys/arch/powerpc64/include/cpu.h b/sys/arch/powerpc64/include/cpu.h index edabe01e045..51791d5fdde 100644 --- a/sys/arch/powerpc64/include/cpu.h +++ b/sys/arch/powerpc64/include/cpu.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.h,v 1.8 2020/06/09 18:58:58 kettenis Exp $ */ +/* $OpenBSD: cpu.h,v 1.9 2020/06/10 19:06:53 kettenis Exp $ */ /* * Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org> @@ -49,6 +49,12 @@ struct cpu_info { #define CPUSAVE_LEN 9 register_t ci_tempsave[CPUSAVE_LEN]; + uint64_t ci_lasttb; + uint64_t ci_nexttimerevent; + uint64_t ci_nextstatevent; + int ci_statspending; + + volatile int ci_cpl; uint32_t ci_ipending; #ifdef DIAGNOSTIC int ci_mutex_level; diff --git a/sys/arch/powerpc64/powerpc64/clock.c b/sys/arch/powerpc64/powerpc64/clock.c new file mode 100644 index 00000000000..2b1d1705972 --- /dev/null +++ b/sys/arch/powerpc64/powerpc64/clock.c @@ -0,0 +1,186 @@ +/* $OpenBSD: clock.c,v 1.1 2020/06/10 19:06:53 kettenis Exp $ */ + +/* + * Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org> + * Copyright (c) 2003 Dale Rahn <drahn@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/evcount.h> +#include <sys/timetc.h> + +#include <machine/cpufunc.h> + +extern uint64_t tb_freq; /* cpu.c */ + +uint64_t tick_increment; +uint64_t statmin; +uint32_t statvar; + +struct evcount clock_count; +struct evcount stat_count; + +u_int tb_get_timecount(struct timecounter *); + +static struct timecounter tb_timecounter = { + tb_get_timecount, NULL, 0x7fffffff, 0, "tb", 0, NULL +}; + +void cpu_startclock(void); + +u_int +tb_get_timecount(struct timecounter *tc) +{ + return mftb(); +} + +void +cpu_initclocks(void) +{ + tick_increment = tb_freq / hz; + + stathz = 100; + profhz = 1000; /* must be a multiple of stathz */ + + setstatclockrate(stathz); + + evcount_attach(&clock_count, "clock", NULL); + evcount_attach(&stat_count, "stat", NULL); + + cpu_startclock(); + + tb_timecounter.tc_frequency = tb_freq; + tc_init(&tb_timecounter); +} + +void +cpu_startclock(void) +{ + struct cpu_info *ci = curcpu(); + uint64_t nextevent; + + ci->ci_lasttb = mftb(); + ci->ci_nexttimerevent = ci->ci_lasttb + tick_increment; + nextevent = ci->ci_nextstatevent = ci->ci_nexttimerevent; + + mtdec(nextevent - ci->ci_lasttb); + intr_enable(); +} + +void +decr_intr(struct trapframe *frame) +{ + struct cpu_info *ci = curcpu(); + uint64_t tb, prevtb; + uint64_t nextevent; + uint32_t r; + int nstats; + int s; + + /* + * Based on the actual time delay since the last decrementer reload, + * we arrange for earlier interrupt next time. + */ + + tb = mftb(); + + while (ci->ci_nexttimerevent <= tb) + ci->ci_nexttimerevent += tick_increment; + + prevtb = ci->ci_nexttimerevent - tick_increment; + + for (nstats = 0; ci->ci_nextstatevent <= tb; nstats++) { + do { + r = random() & (statvar - 1); + } while (r == 0); /* random == 0 not allowed */ + ci->ci_nextstatevent += statmin + r; + } + stat_count.ec_count += nstats; + + if (ci->ci_nexttimerevent < ci->ci_nextstatevent) + nextevent = ci->ci_nexttimerevent; + else + nextevent = ci->ci_nextstatevent; + + /* + * Transition of the MSB will trigger a decrementer interrupt. + * So the next sequence is guaranteed to do the job without a + * systematic skew. + */ + mtdec(nextevent - tb); + mtdec(nextevent - mftb()); + + if (ci->ci_cpl >= IPL_CLOCK) { + ci->ci_statspending += nstats; + } else { + nstats += ci->ci_statspending; + ci->ci_statspending = 0; + + s = splclock(); + intr_enable(); + + /* + * Do standard timer interrupt stuff. + */ + while (ci->ci_lasttb < prevtb) { + ci->ci_lasttb += tick_increment; + clock_count.ec_count++; + hardclock((struct clockframe *)frame); + } + + while (nstats-- > 0) + statclock((struct clockframe *)frame); + + intr_disable(); + splx(s); + } +} + +void +setstatclockrate(int newhz) +{ + uint64_t stat_increment; + uint64_t min_increment; + uint32_t var; + u_long msr; + + msr = intr_disable(); + + stat_increment = tb_freq / newhz; + var = 0x40000000; /* really big power of two */ + /* Find largest 2^n which is nearly smaller than statint/2. */ + min_increment = stat_increment / 2 + 100; + while (var > min_increment) + var >>= 1; + + /* Not atomic, but we can probably live with that. */ + statmin = stat_increment - (var >> 1); + statvar = var; + + intr_restore(msr); +} + +void +delay(u_int us) +{ + uint64_t tb; + + tb = mftb(); + tb += (us * tb_freq + 999999) / 1000000; + while (tb > mftb()) + continue; +} diff --git a/sys/arch/powerpc64/powerpc64/cpu.c b/sys/arch/powerpc64/powerpc64/cpu.c index e768f032323..26bdf0c0c7c 100644 --- a/sys/arch/powerpc64/powerpc64/cpu.c +++ b/sys/arch/powerpc64/powerpc64/cpu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.c,v 1.5 2020/06/07 20:50:24 kettenis Exp $ */ +/* $OpenBSD: cpu.c,v 1.6 2020/06/10 19:06:53 kettenis Exp $ */ /* * Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org> @@ -77,14 +77,3 @@ cpu_attach(struct device *parent, struct device *dev, void *aux) /* Update timebase frequency to reflect reality. */ tb_freq = OF_getpropint(faa->fa_node, "timebase-frequency", tb_freq); } - -void -delay(u_int us) -{ - uint64_t tb; - - tb = mftb(); - tb += (us * tb_freq + 999999) / 1000000; - while (tb > mftb()) - continue; -} diff --git a/sys/arch/powerpc64/powerpc64/machdep.c b/sys/arch/powerpc64/powerpc64/machdep.c index 91878121606..3e086fc0af8 100644 --- a/sys/arch/powerpc64/powerpc64/machdep.c +++ b/sys/arch/powerpc64/powerpc64/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.18 2020/06/08 18:37:16 kettenis Exp $ */ +/* $OpenBSD: machdep.c,v 1.19 2020/06/10 19:06:53 kettenis Exp $ */ /* * Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org> @@ -444,18 +444,6 @@ cpu_startup(void) } void -cpu_initclocks(void) -{ - printf("%s\n", __func__); -} - -void -setstatclockrate(int new) -{ - printf("%s\n", __func__); -} - -void setregs(struct proc *p, struct exec_package *pack, u_long stack, register_t *retval) { diff --git a/sys/arch/powerpc64/powerpc64/trap.c b/sys/arch/powerpc64/powerpc64/trap.c index 7f37d556d7c..07f8020c5d7 100644 --- a/sys/arch/powerpc64/powerpc64/trap.c +++ b/sys/arch/powerpc64/powerpc64/trap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.c,v 1.3 2020/05/27 22:22:04 gkoehler Exp $ */ +/* $OpenBSD: trap.c,v 1.4 2020/06/10 19:06:53 kettenis Exp $ */ /* * Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org> @@ -24,9 +24,17 @@ #endif #include <machine/trap.h> +void decr_intr(struct trapframe *); /* clock.c */ + void trap(struct trapframe *frame) { + switch (frame->exc) { + case EXC_DECR: + decr_intr(frame); + return; + } + #ifdef DDB /* At a trap instruction, enter the debugger. */ if (frame->exc == EXC_PGM && (frame->srr1 & EXC_PGM_TRAP)) { @@ -36,5 +44,8 @@ trap(struct trapframe *frame) } #endif + if (frame->exc == EXC_DSI) + printf("dsisr %lx dar %lx\n", frame->dsisr, frame->dar); + panic("trap type %lx at lr %lx", frame->exc, frame->lr); } |