aboutsummaryrefslogtreecommitdiff
path: root/machine/mtrap.c
diff options
context:
space:
mode:
authorAndrew Waterman <andrew@sifive.com>2016-11-04 13:51:10 -0700
committerAndrew Waterman <andrew@sifive.com>2016-11-04 13:51:10 -0700
commit7a7106885367201ffbfd6f5568d8c5262dbb766d (patch)
tree0fa630df2623f1331b44acaefc4e48ab7ddb215c /machine/mtrap.c
parentd5e3e0d86a4ff7034c3dfab172747e8d74063a42 (diff)
downloadriscv-pk-7a7106885367201ffbfd6f5568d8c5262dbb766d.zip
riscv-pk-7a7106885367201ffbfd6f5568d8c5262dbb766d.tar.gz
riscv-pk-7a7106885367201ffbfd6f5568d8c5262dbb766d.tar.bz2
Acquire lock before attempting tohost/fromhost sequences
Diffstat (limited to 'machine/mtrap.c')
-rw-r--r--machine/mtrap.c35
1 files changed, 23 insertions, 12 deletions
diff --git a/machine/mtrap.c b/machine/mtrap.c
index a68c0d9..d2cbcd2 100644
--- a/machine/mtrap.c
+++ b/machine/mtrap.c
@@ -9,6 +9,7 @@
volatile uint64_t tohost __attribute__((aligned(64))) __attribute__((section("htif")));
volatile uint64_t fromhost __attribute__((aligned(64))) __attribute__((section("htif")));
+static spinlock_t htif_lock = SPINLOCK_INIT;
void __attribute__((noreturn)) bad_trap()
{
@@ -26,7 +27,7 @@ static void request_htif_keyboard_interrupt()
tohost = TOHOST_CMD(1, 0, 0);
}
-static void htif_interrupt()
+static void __htif_interrupt()
{
// we should only be interrupted by keypresses
uint64_t fh = fromhost;
@@ -41,19 +42,29 @@ static void htif_interrupt()
static void do_tohost_fromhost(uintptr_t dev, uintptr_t cmd, uintptr_t data)
{
- while (tohost)
- htif_interrupt();
- tohost = TOHOST_CMD(dev, cmd, data);
-
- while (1) {
- uint64_t fh = fromhost;
- if (fh) {
- if (FROMHOST_DEV(fh) == dev && FROMHOST_CMD(fh) == cmd) {
- fromhost = 0;
- break;
+ spinlock_lock(&htif_lock);
+ while (tohost)
+ __htif_interrupt();
+ tohost = TOHOST_CMD(dev, cmd, data);
+
+ while (1) {
+ uint64_t fh = fromhost;
+ if (fh) {
+ if (FROMHOST_DEV(fh) == dev && FROMHOST_CMD(fh) == cmd) {
+ fromhost = 0;
+ break;
+ }
+ __htif_interrupt();
}
- htif_interrupt();
}
+ spinlock_unlock(&htif_lock);
+}
+
+static void htif_interrupt()
+{
+ if (spinlock_trylock(&htif_lock) == 0) {
+ __htif_interrupt();
+ spinlock_unlock(&htif_lock);
}
}