Skip to content

Commit 812ad49

Browse files
committed
Merge tag 'riscv/for-v5.4-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux
Pull RISC-V fixes from Paul Walmsley: - Ensure that exclusive-load reservations are terminated after system call or exception handling. This primarily affects QEMU, which does not expire load reservations. - Fix an issue primarily affecting RV32 platforms that can cause the DT header to be corrupted, causing boot failures. * tag 'riscv/for-v5.4-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux: riscv: Fix memblock reservation for device tree blob RISC-V: Clear load reservations while restoring hart contexts
2 parents a4ad51e + 922b037 commit 812ad49

File tree

3 files changed

+32
-2
lines changed

3 files changed

+32
-2
lines changed

arch/riscv/include/asm/asm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#define REG_L __REG_SEL(ld, lw)
2424
#define REG_S __REG_SEL(sd, sw)
25+
#define REG_SC __REG_SEL(sc.d, sc.w)
2526
#define SZREG __REG_SEL(8, 4)
2627
#define LGREG __REG_SEL(3, 2)
2728

arch/riscv/kernel/entry.S

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,26 @@ _save_context:
9898
*/
9999
.macro RESTORE_ALL
100100
REG_L a0, PT_SSTATUS(sp)
101-
REG_L a2, PT_SEPC(sp)
101+
/*
102+
* The current load reservation is effectively part of the processor's
103+
* state, in the sense that load reservations cannot be shared between
104+
* different hart contexts. We can't actually save and restore a load
105+
* reservation, so instead here we clear any existing reservation --
106+
* it's always legal for implementations to clear load reservations at
107+
* any point (as long as the forward progress guarantee is kept, but
108+
* we'll ignore that here).
109+
*
110+
* Dangling load reservations can be the result of taking a trap in the
111+
* middle of an LR/SC sequence, but can also be the result of a taken
112+
* forward branch around an SC -- which is how we implement CAS. As a
113+
* result we need to clear reservations between the last CAS and the
114+
* jump back to the new context. While it is unlikely the store
115+
* completes, implementations are allowed to expand reservations to be
116+
* arbitrarily large.
117+
*/
118+
REG_L a2, PT_SEPC(sp)
119+
REG_SC x0, a2, PT_SEPC(sp)
120+
102121
csrw CSR_SSTATUS, a0
103122
csrw CSR_SEPC, a2
104123

arch/riscv/mm/init.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <linux/swap.h>
1212
#include <linux/sizes.h>
1313
#include <linux/of_fdt.h>
14+
#include <linux/libfdt.h>
1415

1516
#include <asm/fixmap.h>
1617
#include <asm/tlbflush.h>
@@ -82,6 +83,8 @@ static void __init setup_initrd(void)
8283
}
8384
#endif /* CONFIG_BLK_DEV_INITRD */
8485

86+
static phys_addr_t dtb_early_pa __initdata;
87+
8588
void __init setup_bootmem(void)
8689
{
8790
struct memblock_region *reg;
@@ -117,7 +120,12 @@ void __init setup_bootmem(void)
117120
setup_initrd();
118121
#endif /* CONFIG_BLK_DEV_INITRD */
119122

120-
early_init_fdt_reserve_self();
123+
/*
124+
* Avoid using early_init_fdt_reserve_self() since __pa() does
125+
* not work for DTB pointers that are fixmap addresses
126+
*/
127+
memblock_reserve(dtb_early_pa, fdt_totalsize(dtb_early_va));
128+
121129
early_init_fdt_scan_reserved_mem();
122130
memblock_allow_resize();
123131
memblock_dump_all();
@@ -393,6 +401,8 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
393401

394402
/* Save pointer to DTB for early FDT parsing */
395403
dtb_early_va = (void *)fix_to_virt(FIX_FDT) + (dtb_pa & ~PAGE_MASK);
404+
/* Save physical address for memblock reservation */
405+
dtb_early_pa = dtb_pa;
396406
}
397407

398408
static void __init setup_vm_final(void)

0 commit comments

Comments
 (0)