diff options
Diffstat (limited to 'arch/riscv/kernel')
-rw-r--r-- | arch/riscv/kernel/entry.S | 27 | ||||
-rw-r--r-- | arch/riscv/kernel/head.S | 8 | ||||
-rw-r--r-- | arch/riscv/kernel/smp.c | 1 | ||||
-rw-r--r-- | arch/riscv/kernel/time.c | 1 |
4 files changed, 32 insertions, 5 deletions
diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S index 74ccfd464071..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 @@ -166,9 +185,13 @@ ENTRY(handle_exception) move a0, sp /* pt_regs */ tail do_IRQ 1: - /* Exceptions run with interrupts enabled */ + /* Exceptions run with interrupts enabled or disabled + depending on the state of sstatus.SR_SPIE */ + andi t0, s1, SR_SPIE + beqz t0, 1f csrs CSR_SSTATUS, SR_SIE +1: /* Handle syscalls */ li t0, EXC_SYSCALL beq s4, t0, handle_syscall diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S index 15a9189f91ad..72f89b7590dd 100644 --- a/arch/riscv/kernel/head.S +++ b/arch/riscv/kernel/head.S @@ -63,6 +63,11 @@ _start_kernel: li t0, SR_FS csrc CSR_SSTATUS, t0 +#ifdef CONFIG_SMP + li t0, CONFIG_NR_CPUS + bgeu a0, t0, .Lsecondary_park +#endif + /* Pick one hart to run the main boot sequence */ la a3, hart_lottery li a2, 1 @@ -154,9 +159,6 @@ relocate: .Lsecondary_start: #ifdef CONFIG_SMP - li a1, CONFIG_NR_CPUS - bgeu a0, a1, .Lsecondary_park - /* Set trap vector to spin forever to help debug */ la a3, .Lsecondary_park csrw CSR_STVEC, a3 diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c index 3836760d7aaf..b18cd6c8e8fb 100644 --- a/arch/riscv/kernel/smp.c +++ b/arch/riscv/kernel/smp.c @@ -206,3 +206,4 @@ void smp_send_reschedule(int cpu) { send_ipi_single(cpu, IPI_RESCHEDULE); } +EXPORT_SYMBOL_GPL(smp_send_reschedule); diff --git a/arch/riscv/kernel/time.c b/arch/riscv/kernel/time.c index 541a2b885814..9dd1f2e64db1 100644 --- a/arch/riscv/kernel/time.c +++ b/arch/riscv/kernel/time.c @@ -9,6 +9,7 @@ #include <asm/sbi.h> unsigned long riscv_timebase; +EXPORT_SYMBOL_GPL(riscv_timebase); void __init time_init(void) { |