-/* $OpenBSD: plic.c,v 1.10 2022/04/06 18:59:27 naddy Exp $ */
+/* $OpenBSD: plic.c,v 1.11 2022/08/09 04:49:08 cheloha Exp $ */
/*
* Copyright (c) 2020, Mars Li <mengshi.li.mars@gmail.com>
#include <machine/bus.h>
#include <machine/fdt.h>
#include <machine/cpu.h>
+#include <machine/sbi.h>
#include "riscv64/dev/riscv_cpu_intc.h"
#include <dev/ofw/openfirm.h>
/* higher values are higher priority */
plic_set_threshold(ci->ci_cpuid, new);
+ /* trigger deferred timer interrupt if cpl is now low enough */
+ if (ci->ci_timer_deferred && new < IPL_CLOCK)
+ sbi_set_timer(0);
+
intr_restore(sie);
}
-/* $OpenBSD: cpu.h,v 1.12 2022/06/10 21:34:15 jca Exp $ */
+/* $OpenBSD: cpu.h,v 1.13 2022/08/09 04:49:08 cheloha Exp $ */
/*
* Copyright (c) 2019 Mike Larkin <mlarkin@openbsd.org>
uint64_t ci_lasttb;
uint64_t ci_nexttimerevent;
uint64_t ci_nextstatevent;
- int ci_statspending;
+ volatile int ci_timer_deferred;
uint32_t ci_cpl;
uint32_t ci_ipending;
-/* $OpenBSD: clock.c,v 1.3 2021/07/24 22:41:09 jca Exp $ */
+/* $OpenBSD: clock.c,v 1.4 2022/08/09 04:49:08 cheloha Exp $ */
/*
* Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/evcount.h>
+#include <sys/stdint.h>
#include <sys/timetc.h>
#include <machine/cpufunc.h>
int nstats;
int s;
+ /*
+ * If the clock interrupt is masked, defer all clock interrupt
+ * work until the clock interrupt is unmasked from splx(9).
+ */
+ if (ci->ci_cpl >= IPL_CLOCK) {
+ ci->ci_timer_deferred = 1;
+ sbi_set_timer(UINT64_MAX);
+ return 0;
+ }
+ ci->ci_timer_deferred = 0;
+
/*
* Based on the actual time delay since the last clock interrupt,
* we arrange for earlier interrupt next time.
sbi_set_timer(nextevent);
- 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);
+ 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);
+
return 0;
}