diff options
author | David S. Miller <davem@davemloft.net> | 2019-10-05 13:37:23 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-10-05 13:37:23 -0700 |
commit | 6f4c930e02355664d89c976eccea5d999a90de16 (patch) | |
tree | bc08932fbf43b9560ba5bde3284674054e3b56eb /arch/riscv/kernel/entry.S | |
parent | 26e0105550862a137eba701e2f4e3eeb343759e9 (diff) | |
parent | 2d00aee21a5d4966e086d98f9d710afb92fb14e8 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Diffstat (limited to 'arch/riscv/kernel/entry.S')
-rw-r--r-- | arch/riscv/kernel/entry.S | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S index da7aa88113c2..2d592da1e776 100644 --- a/arch/riscv/kernel/entry.S +++ b/arch/riscv/kernel/entry.S @@ -98,7 +98,26 @@ _save_context: */ .macro RESTORE_ALL REG_L a0, PT_SSTATUS(sp) - REG_L a2, PT_SEPC(sp) + /* + * The current load reservation is effectively part of the processor's + * state, in the sense that load reservations cannot be shared between + * different hart contexts. We can't actually save and restore a load + * reservation, so instead here we clear any existing reservation -- + * it's always legal for implementations to clear load reservations at + * any point (as long as the forward progress guarantee is kept, but + * we'll ignore that here). + * + * Dangling load reservations can be the result of taking a trap in the + * middle of an LR/SC sequence, but can also be the result of a taken + * forward branch around an SC -- which is how we implement CAS. As a + * result we need to clear reservations between the last CAS and the + * jump back to the new context. While it is unlikely the store + * completes, implementations are allowed to expand reservations to be + * arbitrarily large. + */ + REG_L a2, PT_SEPC(sp) + REG_SC x0, a2, PT_SEPC(sp) + csrw CSR_SSTATUS, a0 csrw CSR_SEPC, a2 |