aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--arch/riscv/kvm/nacl.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/arch/riscv/kvm/nacl.c b/arch/riscv/kvm/nacl.c
index 9aff03c4f667..a5cda9a65156 100644
--- a/arch/riscv/kvm/nacl.c
+++ b/arch/riscv/kvm/nacl.c
@@ -42,12 +42,24 @@ again:
}
}
- entp = shmem + SBI_NACL_SHMEM_HFENCE_ENTRY_CONFIG(i);
- *entp = cpu_to_lelong(control);
+ /*
+ * Per SBI v3.0 section 15.1.2, the Page_Number and Page_Count
+ * words must be updated before the Config word with its Pending
+ * bit set. WRITE_ONCE() stops the compiler from reordering the
+ * stores and smp_wmb() makes the parameter words globally
+ * visible to the SBI implementation (or NACL hardware) before
+ * the Pending bit is set.
+ */
entp = shmem + SBI_NACL_SHMEM_HFENCE_ENTRY_PNUM(i);
- *entp = cpu_to_lelong(page_num);
+ WRITE_ONCE(*entp, cpu_to_lelong(page_num));
entp = shmem + SBI_NACL_SHMEM_HFENCE_ENTRY_PCOUNT(i);
- *entp = cpu_to_lelong(page_count);
+ WRITE_ONCE(*entp, cpu_to_lelong(page_count));
+
+ /* Ensure the parameter words are visible before the Pending bit */
+ smp_wmb();
+
+ entp = shmem + SBI_NACL_SHMEM_HFENCE_ENTRY_CONFIG(i);
+ WRITE_ONCE(*entp, cpu_to_lelong(control));
}
int kvm_riscv_nacl_enable(void)