aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnup Patel <anup.patel@wdc.com>2019-04-05 14:08:57 +0530
committerAnup Patel <anup@brainfault.org>2019-09-30 15:18:06 +0530
commit1a5614e971cf44e08342c2b1639fa3be544b0202 (patch)
tree0afa5525ef174e565eec10f73a4a64a58dc31c72
parent0089897d41b5b2382acba1c2c9f9386edad75228 (diff)
lib: Extend sbi_hart_switch_mode() to support hypervisor extension
This patch extends sbi_hart_switch_mode() to support entering VS/VU modes when hypervisor extension is available. Signed-off-by: Anup Patel <anup.patel@wdc.com>
-rw-r--r--include/sbi/riscv_encoding.h14
-rw-r--r--include/sbi/sbi_hart.h3
-rw-r--r--lib/sbi/sbi_hart.c27
-rw-r--r--lib/sbi/sbi_init.c5
4 files changed, 44 insertions, 5 deletions
diff --git a/include/sbi/riscv_encoding.h b/include/sbi/riscv_encoding.h
index 5a5086a..dace9e6 100644
--- a/include/sbi/riscv_encoding.h
+++ b/include/sbi/riscv_encoding.h
@@ -38,8 +38,21 @@
#define MSTATUS_TW 0x00200000
#define MSTATUS_TSR 0x00400000
#define MSTATUS32_SD 0x80000000
+#if __riscv_xlen == 64
#define MSTATUS_UXL 0x0000000300000000
#define MSTATUS_SXL 0x0000000C00000000
+#define MSTATUS_MTL 0x0000004000000000
+#define MSTATUS_MTL_SHIFT 38
+#define MSTATUS_MPV 0x0000008000000000
+#define MSTATUS_MPV_HIFT 39
+#else
+#define MSTATUSH_UXL 0x00000003
+#define MSTATUSH_SXL 0x0000000C
+#define MSTATUSH_MTL 0x00000040
+#define MSTATUSH_MTL_SHIFT 6
+#define MSTATUSH_MPV 0x00000080
+#define MSTATUSH_MPV_HIFT 7
+#endif
#define MSTATUS64_SD 0x8000000000000000
#define SSTATUS_UIE 0x00000001
@@ -256,6 +269,7 @@
#define CSR_MIE 0x304
#define CSR_MTVEC 0x305
#define CSR_MCOUNTEREN 0x306
+#define CSR_MSTATUSH 0x310
#define CSR_MSCRATCH 0x340
#define CSR_MEPC 0x341
#define CSR_MCAUSE 0x342
diff --git a/include/sbi/sbi_hart.h b/include/sbi/sbi_hart.h
index 4aa4a5c..0762f95 100644
--- a/include/sbi/sbi_hart.h
+++ b/include/sbi/sbi_hart.h
@@ -26,7 +26,8 @@ void __attribute__((noreturn)) sbi_hart_hang(void);
void __attribute__((noreturn))
sbi_hart_switch_mode(unsigned long arg0, unsigned long arg1,
- unsigned long next_addr, unsigned long next_mode);
+ unsigned long next_addr, unsigned long next_mode,
+ bool next_virt);
void sbi_hart_mark_available(u32 hartid);
diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c
index 6dac84b..b0c087a 100644
--- a/lib/sbi/sbi_hart.c
+++ b/lib/sbi/sbi_hart.c
@@ -241,9 +241,14 @@ void __attribute__((noreturn)) sbi_hart_hang(void)
void __attribute__((noreturn))
sbi_hart_switch_mode(unsigned long arg0, unsigned long arg1,
- unsigned long next_addr, unsigned long next_mode)
+ unsigned long next_addr, unsigned long next_mode,
+ bool next_virt)
{
+#if __riscv_xlen == 32
+ unsigned long val, valH;
+#else
unsigned long val;
+#endif
switch (next_mode) {
case PRV_M:
@@ -263,7 +268,25 @@ sbi_hart_switch_mode(unsigned long arg0, unsigned long arg1,
val = csr_read(CSR_MSTATUS);
val = INSERT_FIELD(val, MSTATUS_MPP, next_mode);
val = INSERT_FIELD(val, MSTATUS_MPIE, 0);
-
+#if __riscv_xlen == 32
+ if (misa_extension('H')) {
+ valH = csr_read(CSR_MSTATUSH);
+ valH = INSERT_FIELD(valH, MSTATUSH_MTL, 0);
+ if (next_virt)
+ valH = INSERT_FIELD(valH, MSTATUSH_MPV, 1);
+ else
+ valH = INSERT_FIELD(valH, MSTATUSH_MPV, 0);
+ csr_write(CSR_MSTATUSH, valH);
+ }
+#else
+ if (misa_extension('H')) {
+ val = INSERT_FIELD(val, MSTATUS_MTL, 0);
+ if (next_virt)
+ val = INSERT_FIELD(val, MSTATUS_MPV, 1);
+ else
+ val = INSERT_FIELD(val, MSTATUS_MPV, 0);
+ }
+#endif
csr_write(CSR_MSTATUS, val);
csr_write(CSR_MEPC, next_addr);
diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
index 4663a30..e1acb57 100644
--- a/lib/sbi/sbi_init.c
+++ b/lib/sbi/sbi_init.c
@@ -102,7 +102,7 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
sbi_hart_wake_coldboot_harts(scratch, hartid);
sbi_hart_mark_available(hartid);
sbi_hart_switch_mode(hartid, scratch->next_arg1, scratch->next_addr,
- scratch->next_mode);
+ scratch->next_mode, FALSE);
}
static void __noreturn init_warmboot(struct sbi_scratch *scratch, u32 hartid)
@@ -147,7 +147,8 @@ static void __noreturn init_warmboot(struct sbi_scratch *scratch, u32 hartid)
sbi_hart_hang();
else
sbi_hart_switch_mode(hartid, scratch->next_arg1,
- scratch->next_addr, scratch->next_mode);
+ scratch->next_addr,
+ scratch->next_mode, FALSE);
}
static atomic_t coldboot_lottery = ATOMIC_INITIALIZER(0);