diff mbox series

[2/4] target/arm: Fixup contiguous first-fault and no-fault loads

Message ID 20201207044655.2312-3-zhiwei_liu@c-sky.com
State New
Headers show
Series target/arm bug fix | expand

Commit Message

LIU Zhiwei Dec. 7, 2020, 4:46 a.m. UTC
First-fault or no-fault doesn't mean only access one page.

When cross pages, for first-fault, if there is no fault in the first access,
the second page should be accessed. And for no-fault, the second page
should always be accessed.

Signed-off-by: LIU Zhiwei <zhiwei_liu@c-sky.com>
---
 target/arm/sve_helper.c | 35 ++++++++++++++++++++++++-----------
 1 file changed, 24 insertions(+), 11 deletions(-)

Comments

Richard Henderson Dec. 8, 2020, 8:16 p.m. UTC | #1
On 12/6/20 10:46 PM, LIU Zhiwei wrote:
> First-fault or no-fault doesn't mean only access one page.

But the implementation is *allowed* to access only one page.
Thus the comment:

> -    /*
> -     * MemSingleNF is allowed to fail for any reason.  We have special
> -     * code above to handle the first element crossing a page boundary.
> -     * As an implementation choice, decline to handle a cross-page element
> -     * in any other position.
> -     */


r~
LIU Zhiwei Dec. 10, 2020, 11:54 a.m. UTC | #2
On 2020/12/9 4:16, Richard Henderson wrote:
> On 12/6/20 10:46 PM, LIU Zhiwei wrote:
>> First-fault or no-fault doesn't mean only access one page.
> But the implementation is *allowed* to access only one page.
> Thus the comment:
>
>> -    /*
>> -     * MemSingleNF is allowed to fail for any reason.  We have special
>> -     * code above to handle the first element crossing a page boundary.
>> -     * As an implementation choice, decline to handle a cross-page element
>> -     * in any other position.
>> -     */
 From the pseudo code,  I see  that we should handle the first element 
in first-fault follow Mem. And the other elements in this function 
should follow  MemNF.

I have some questions here:

1. Why  do special process to the first element if it crosses pages in 
no-fault? Because it's not aligned?

// MemNF[] - non-assignment form

// =============================

(bits(8*size), boolean) MemNF[bits(64) address, integer size, AccType 
acctype]

    assert size IN {1, 2, 4, 8, 16};

    bits(8*size) value;

    aligned = (address == Align(address, size));

    A = SCTLR[].A;

    if !aligned && (A == '1') then

         return (bits(8*size) UNKNOWN, TRUE);

    atomic = aligned || size == 1;

    if !atomic then

         (value<7:0>, bad) = MemSingleNF[address, 1, acctype, aligned];

         if bad then

             return (bits(8*size) UNKNOWN, TRUE);

         // For subsequent bytes it is CONSTRAINED UNPREDICTABLE whether
    an unaligned Device memory

         // access will generate an Alignment Fault, as to get this far
    means the first byte did

         // not, so we must be changing to a new translation page.

         if !aligned then

         c = ConstrainUnpredictable(Unpredictable_DEVPAGE2);

         assert c IN {Constraint_FAULT, Constraint_NONE};

         if c == Constraint_NONE then aligned = TRUE;

         for i = 1 to size-1

             (value<8*i+7:8*i>, bad) = MemSingleNF[address+i, 1,
    acctype, aligned];

         if bad then

             return (bits(8*size) UNKNOWN, TRUE);

    else

         (value, bad) = MemSingleNF[address, size, acctype, aligned];

         if bad then

             return (bits(8*size) UNKNOWN, TRUE);

    return (value, FALSE);



2.  Why it doesn't access the second page like the first page? I think 
they should obey the same MemSingleNF implementation.

> r~
diff mbox series

Patch

diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
index 91d1d24725..700a8a7585 100644
--- a/target/arm/sve_helper.c
+++ b/target/arm/sve_helper.c
@@ -4916,17 +4916,6 @@  void sve_ldnfff1_r(CPUARMState *env, void *vg, const target_ulong addr,
         } while (reg_off <= reg_last && (reg_off & 63));
     } while (reg_off <= reg_last);
 
-    /*
-     * MemSingleNF is allowed to fail for any reason.  We have special
-     * code above to handle the first element crossing a page boundary.
-     * As an implementation choice, decline to handle a cross-page element
-     * in any other position.
-     */
-    reg_off = info.reg_off_split;
-    if (reg_off >= 0) {
-        goto do_fault;
-    }
-
  second_page:
     reg_off = info.reg_off_first[1];
     if (likely(reg_off < 0)) {
@@ -4934,6 +4923,30 @@  void sve_ldnfff1_r(CPUARMState *env, void *vg, const target_ulong addr,
         return;
     }
 
+    mem_off = info.mem_off_first[1];
+    reg_last = info.reg_off_last[1];
+    host = info.page[1].host;
+
+    do {
+        uint64_t pg = *(uint64_t *)(vg + (reg_off >> 3));
+        do {
+            if ((pg >> (reg_off & 63)) & 1) {
+                if (unlikely(flags & TLB_WATCHPOINT) &&
+                    (cpu_watchpoint_address_matches
+                     (env_cpu(env), addr + mem_off, 1 << msz)
+                     & BP_MEM_READ)) {
+                    goto do_fault;
+                }
+                if (mtedesc && !mte_probe1(env, mtedesc, addr + mem_off)) {
+                    goto do_fault;
+                }
+                host_fn(vd, reg_off, host + mem_off);
+            }
+            reg_off += 1 << esz;
+            mem_off += 1 << msz;
+        } while (reg_off <= reg_last && (reg_off & 63));
+    } while (reg_off <= reg_last);
+
     /*
      * MemSingleNF is allowed to fail for any reason.  As an implementation
      * choice, decline to handle elements on the second page.  This should