Message ID | 20201207044655.2312-3-zhiwei_liu@c-sky.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | target/arm bug fix | expand |
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~
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 --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
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(-)