lib: Delegate guest page faults to HS-mode
authorAnup Patel <anup.patel@wdc.com>
Thu, 12 Dec 2019 01:30:59 +0000 (07:00 +0530)
committerAnup Patel <anup@brainfault.org>
Mon, 16 Dec 2019 09:18:16 +0000 (14:48 +0530)
As-per RISC-V hypervisor v0.5 spec, we have new guest page faults
which need to be delegated to HS-mode.

Also, we can have bits in in MIDELEG and MEDELEG hardwired to 1
which means we need to fix the sainty check on these CSRs at the
end of delegate_traps() function.

Signed-off-by: Anup Patel <anup.patel@wdc.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
lib/sbi/sbi_hart.c

index dee2e21..493e7fc 100644 (file)
@@ -88,19 +88,25 @@ static int delegate_traps(struct sbi_scratch *scratch, u32 hartid)
                              (1U << CAUSE_STORE_PAGE_FAULT);
 
        /*
-        * If hypervisor extension available then we only handle
-        * hypervisor calls (i.e. ecalls from HS-mode) and we let
-        * HS-mode handle supervisor calls (i.e. ecalls from VS-mode)
+        * If hypervisor extension available then we only handle hypervisor
+        * calls (i.e. ecalls from HS-mode) in M-mode.
+        *
+        * The HS-mode will additionally handle supervisor calls (i.e. ecalls
+        * from VS-mode), Guest page faults and Virtual interrupts.
         */
-       if (misa_extension('H'))
+       if (misa_extension('H')) {
                exceptions |= (1U << CAUSE_SUPERVISOR_ECALL);
+               exceptions |= (1U << CAUSE_FETCH_GUEST_PAGE_FAULT);
+               exceptions |= (1U << CAUSE_LOAD_GUEST_PAGE_FAULT);
+               exceptions |= (1U << CAUSE_STORE_GUEST_PAGE_FAULT);
+       }
 
        csr_write(CSR_MIDELEG, interrupts);
        csr_write(CSR_MEDELEG, exceptions);
 
-       if (csr_read(CSR_MIDELEG) != interrupts)
+       if ((csr_read(CSR_MIDELEG) & interrupts) != interrupts)
                return SBI_EFAIL;
-       if (csr_read(CSR_MEDELEG) != exceptions)
+       if ((csr_read(CSR_MEDELEG) & exceptions) != exceptions)
                return SBI_EFAIL;
 
        return 0;