[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v1 11/22] RISC-V: Improve page table walker spec
From: |
Michael Clark |
Subject: |
Re: [Qemu-devel] [PATCH v1 11/22] RISC-V: Improve page table walker spec compliance |
Date: |
Fri, 9 Mar 2018 16:54:33 +1300 |
On Wed, Mar 7, 2018 at 9:43 AM, Michael Clark <address@hidden> wrote:
> - Inline PTE_TABLE check for better readability
> - Improve readibility of User page U mode and SUM test
> - Disallow non U mode from fetching from User pages
> - Add reserved PTE flag check: W or W|X
> - Add misaligned PPN check
> - Change access checks from ternary operator to if statements
> - Improves page walker comments
> - No measurable performance impact on dd test
>
> Signed-off-by: Michael Clark <address@hidden>
> Signed-off-by: Palmer Dabbelt <address@hidden>
> ---
> target/riscv/cpu_bits.h | 2 --
> target/riscv/helper.c | 57 ++++++++++++++++++++++++++++++
> ++++---------------
> 2 files changed, 40 insertions(+), 19 deletions(-)
>
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index 64aa097..12b4757 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -407,5 +407,3 @@
> #define PTE_SOFT 0x300 /* Reserved for Software */
>
> #define PTE_PPN_SHIFT 10
> -
> -#define PTE_TABLE(PTE) (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) ==
> PTE_V)
> diff --git a/target/riscv/helper.c b/target/riscv/helper.c
> index 228933c..2165ecb 100644
> --- a/target/riscv/helper.c
> +++ b/target/riscv/helper.c
> @@ -185,16 +185,36 @@ restart:
> #endif
> target_ulong ppn = pte >> PTE_PPN_SHIFT;
>
> - if (PTE_TABLE(pte)) { /* next level of page table */
> + if (!(pte & PTE_V)) {
> + /* Invalid PTE */
> + return TRANSLATE_FAIL;
> + } else if (!(pte & (PTE_R | PTE_W | PTE_X))) {
> + /* Inner PTE, continue walking */
> base = ppn << PGSHIFT;
> - } else if ((pte & PTE_U) ? (mode == PRV_S) && !sum : !(mode ==
> PRV_S)) {
> - break;
> - } else if (!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) {
> - break;
> - } else if (access_type == MMU_INST_FETCH ? !(pte & PTE_X) :
> - access_type == MMU_DATA_LOAD ? !(pte & PTE_R) &&
> - !(mxr && (pte & PTE_X)) : !((pte & PTE_R) && (pte &
> PTE_W))) {
> - break;
> + } else if ((pte & (PTE_R | PTE_W | PTE_X)) == PTE_W) {
> + /* Reserved leaf PTE flags: PTE_W */
> + return TRANSLATE_FAIL;
> + } else if ((pte & (PTE_R | PTE_W | PTE_X)) == (PTE_W | PTE_X)) {
> + /* Reserved leaf PTE flags: PTE_W + PTE_X */
> + return TRANSLATE_FAIL;
> + } else if ((pte & PTE_U) && ((mode != PRV_U) &&
> + (!sum || access_type == MMU_INST_FETCH))) {
> + /* User PTE flags when not U mode and mstats.SUM is not set,
> + or the access type is an instruction fetch */
> + return TRANSLATE_FAIL;
> + } else if (ppn & ((1ULL << ptshift) - 1)) {
> + /* Misasligned PPN */
> + return TRANSLATE_FAIL;
> + } else if (access_type == MMU_DATA_LOAD && !((pte & PTE_R) ||
> + ((pte & PTE_X) && mxr))) {
>
This should only honor the mstatus.MXR flags if mode != PRV_U
+ /* Read access check failed */
> + return TRANSLATE_FAIL;
> + } else if (access_type == MMU_DATA_STORE && !(pte & PTE_W)) {
> + /* Write access check failed */
> + return TRANSLATE_FAIL;
> + } else if (access_type == MMU_INST_FETCH && !(pte & PTE_X)) {
> + /* Fetch access check failed */
> + return TRANSLATE_FAIL;
> } else {
> /* if necessary, set accessed and dirty bits. */
> target_ulong updated_pte = pte | PTE_A |
> @@ -202,11 +222,14 @@ restart:
>
> /* Page table updates need to be atomic with MTTCG enabled */
> if (updated_pte != pte) {
> - /* if accessed or dirty bits need updating, and the PTE is
> - * in RAM, then we do so atomically with a compare and
> swap.
> - * if the PTE is in IO space, then it can't be updated.
> - * if the PTE changed, then we must re-walk the page table
> - as the PTE is no longer valid */
> + /*
> + * - if accessed or dirty bits need updating, and the PTE
> is
> + * in RAM, then we do so atomically with a compare and
> swap.
> + * - if the PTE is in IO space or ROM, then it can't be
> updated
> + * and we return TRANSLATE_FAIL.
> + * - if the PTE changed by the time we went to update it,
> then
> + * it is no longer valid and we must re-walk the page
> table.
> + */
> MemoryRegion *mr;
> hwaddr l = sizeof(target_ulong), addr1;
> rcu_read_lock();
> @@ -243,15 +266,15 @@ restart:
> target_ulong vpn = addr >> PGSHIFT;
> *physical = (ppn | (vpn & ((1L << ptshift) - 1))) << PGSHIFT;
>
> + /* set permissions on the TLB entry */
> if ((pte & PTE_R)) {
> *prot |= PAGE_READ;
> }
>
There is a logic bug here, but it is pre-existing. If mxr and mode is not
U, the X flag needs to make the page readable i.e. (MXR) Make eXecute
Readable.
> if ((pte & PTE_X)) {
> *prot |= PAGE_EXEC;
> }
> - /* only add write permission on stores or if the page
> - is already dirty, so that we don't miss further
> - page table walks to update the dirty bit */
> + /* add write permission on stores or if the page is already
> dirty,
> + so that we TLB miss on later writes to update the dirty
> bit */
> if ((pte & PTE_W) &&
> (access_type == MMU_DATA_STORE || (pte & PTE_D))) {
> *prot |= PAGE_WRITE;
> --
> 2.7.0
>
>
- Re: [Qemu-devel] [PATCH v1 05/22] RISC-V: Remove redundant identity_translate from, (continued)
- [Qemu-devel] [PATCH v1 08/22] RISC-V: Make sure the emulated rom has space for, Michael Clark, 2018/03/06
- [Qemu-devel] [PATCH v1 09/22] RISC-V: Include hexidecimal instruction in, Michael Clark, 2018/03/06
- [Qemu-devel] [PATCH v1 11/22] RISC-V: Improve page table walker spec compliance, Michael Clark, 2018/03/06
- Re: [Qemu-devel] [PATCH v1 11/22] RISC-V: Improve page table walker spec compliance,
Michael Clark <=
- [Qemu-devel] [PATCH v1 10/22] RISC-V: Hold rcu_read_lock when accessing memory, Michael Clark, 2018/03/06
- [Qemu-devel] [PATCH v1 12/22] RISC-V: Update E order and I extension order, Michael Clark, 2018/03/06
- [Qemu-devel] [PATCH v1 13/22] RISC-V: Make spike and virt header guards more, Michael Clark, 2018/03/06
- [Qemu-devel] [PATCH v1 15/22] RISC-V: Use memory_region_is_ram in atomic pte, Michael Clark, 2018/03/06
- [Qemu-devel] [PATCH v1 14/22] RISC-V: Make virt header comment title consistent, Michael Clark, 2018/03/06
- [Qemu-devel] [PATCH v1 16/22] RISC-V: Remove EM_RISCV ELF_MACHINE indirection from, Michael Clark, 2018/03/06
- [Qemu-devel] [PATCH v1 18/22] RISC-V: Remove braces from satp case statement with, Michael Clark, 2018/03/06
- [Qemu-devel] [PATCH v1 17/22] RISC-V: Ingore satp writes and return 0 for reads, Michael Clark, 2018/03/06
- [Qemu-devel] [PATCH v1 19/22] RISC-V: riscv-qemu port supports sv39 and sv48, Michael Clark, 2018/03/06