diff options
author | Andrew Waterman <andrew@sifive.com> | 2016-11-04 13:51:10 -0700 |
---|---|---|
committer | Andrew Waterman <andrew@sifive.com> | 2016-11-04 13:51:10 -0700 |
commit | 7a7106885367201ffbfd6f5568d8c5262dbb766d (patch) | |
tree | 0fa630df2623f1331b44acaefc4e48ab7ddb215c | |
parent | d5e3e0d86a4ff7034c3dfab172747e8d74063a42 (diff) | |
download | pk-7a7106885367201ffbfd6f5568d8c5262dbb766d.zip pk-7a7106885367201ffbfd6f5568d8c5262dbb766d.tar.gz pk-7a7106885367201ffbfd6f5568d8c5262dbb766d.tar.bz2 |
Acquire lock before attempting tohost/fromhost sequences
-rw-r--r-- | machine/mtrap.c | 35 |
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); } } |