diff mbox series

lib: sbi: Refine the settings for switching to Virtual Supervisor Mode.

Message ID 20240409022410.1866-1-popeblei@gmail.com
State Superseded
Headers show
Series lib: sbi: Refine the settings for switching to Virtual Supervisor Mode. | expand

Commit Message

Pope B.Lei April 9, 2024, 2:24 a.m. UTC
Although Mstatus.MPV is set, before executing mret, access to VS mode
registers should use the actual register addresses, not the pseudonyms
of S registers.

Signed-off-by: Pope B.Lei <popeblei@gmail.com>
---
 lib/sbi/sbi_hart.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

Comments

Pope B.Lei April 9, 2024, 2:27 a.m. UTC | #1
Dear All:
     I discovered a subtle bug during the process of switching to VS
mode. The issue arises because, even though Mstatus.MPV is set, before
executing mret, one should access the VS mode registers using their
actual addresses, rather than using the pseudonyms of the S registers.

Best Regards!

Boswell Lei

On Tue, Apr 9, 2024 at 10:24 AM Pope B.Lei <popeblei@gmail.com> wrote:
>
> Although Mstatus.MPV is set, before executing mret, access to VS mode
> registers should use the actual register addresses, not the pseudonyms
> of S registers.
>
> Signed-off-by: Pope B.Lei <popeblei@gmail.com>
> ---
>  lib/sbi/sbi_hart.c | 15 +++++++++++----
>  1 file changed, 11 insertions(+), 4 deletions(-)
>
> diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c
> index 3d13694..e145cdc 100644
> --- a/lib/sbi/sbi_hart.c
> +++ b/lib/sbi/sbi_hart.c
> @@ -1041,10 +1041,17 @@ sbi_hart_switch_mode(unsigned long arg0, unsigned long arg1,
>         csr_write(CSR_MEPC, next_addr);
>
>         if (next_mode == PRV_S) {
> -               csr_write(CSR_STVEC, next_addr);
> -               csr_write(CSR_SSCRATCH, 0);
> -               csr_write(CSR_SIE, 0);
> -               csr_write(CSR_SATP, 0);
> +               if (true == next_virt){
> +                   csr_write(CSR_VSTVEC, next_addr);
> +                   csr_write(CSR_VSSCRATCH, 0);
> +                   csr_write(CSR_VSIE, 0);
> +                   csr_write(CSR_VSATP, 0);
> +               } else if (false == next_virt){
> +                   csr_write(CSR_STVEC, next_addr);
> +                   csr_write(CSR_SSCRATCH, 0);
> +                   csr_write(CSR_SIE, 0);
> +                   csr_write(CSR_SATP, 0);
> +               }
>         } else if (next_mode == PRV_U) {
>                 if (misa_extension('N')) {
>                         csr_write(CSR_UTVEC, next_addr);
> --
> 2.35.2.windows.1
>
Andreas Schwab April 9, 2024, 7:44 a.m. UTC | #2
On Apr 09 2024, Pope B.Lei wrote:

> diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c
> index 3d13694..e145cdc 100644
> --- a/lib/sbi/sbi_hart.c
> +++ b/lib/sbi/sbi_hart.c
> @@ -1041,10 +1041,17 @@ sbi_hart_switch_mode(unsigned long arg0, unsigned long arg1,
>  	csr_write(CSR_MEPC, next_addr);
>  
>  	if (next_mode == PRV_S) {
> -		csr_write(CSR_STVEC, next_addr);
> -		csr_write(CSR_SSCRATCH, 0);
> -		csr_write(CSR_SIE, 0);
> -		csr_write(CSR_SATP, 0);
> +		if (true == next_virt){

Never compare a boolean with a constant.

> +		    csr_write(CSR_VSTVEC, next_addr);
> +		    csr_write(CSR_VSSCRATCH, 0);
> +		    csr_write(CSR_VSIE, 0);
> +		    csr_write(CSR_VSATP, 0);
> +		} else if (false == next_virt){

This condition is obviously redundant.
diff mbox series

Patch

diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c
index 3d13694..e145cdc 100644
--- a/lib/sbi/sbi_hart.c
+++ b/lib/sbi/sbi_hart.c
@@ -1041,10 +1041,17 @@  sbi_hart_switch_mode(unsigned long arg0, unsigned long arg1,
 	csr_write(CSR_MEPC, next_addr);
 
 	if (next_mode == PRV_S) {
-		csr_write(CSR_STVEC, next_addr);
-		csr_write(CSR_SSCRATCH, 0);
-		csr_write(CSR_SIE, 0);
-		csr_write(CSR_SATP, 0);
+		if (true == next_virt){
+		    csr_write(CSR_VSTVEC, next_addr);
+		    csr_write(CSR_VSSCRATCH, 0);
+		    csr_write(CSR_VSIE, 0);
+		    csr_write(CSR_VSATP, 0);
+		} else if (false == next_virt){
+		    csr_write(CSR_STVEC, next_addr);
+		    csr_write(CSR_SSCRATCH, 0);
+		    csr_write(CSR_SIE, 0);
+		    csr_write(CSR_SATP, 0);
+		}
 	} else if (next_mode == PRV_U) {
 		if (misa_extension('N')) {
 			csr_write(CSR_UTVEC, next_addr);