On 21.08.19 19:26, Richard Henderson wrote: > On 8/21/19 2:22 AM, David Hildenbrand wrote: >> +/* >> + * Make sure the read access is permitted and TLB entries are created. In >> + * very rare cases it might happen that the actual accesses might need >> + * new MMU translations. If the page tables were changed in between, we >> + * might still trigger a fault. However, this seems to barely happen, so we >> + * can ignore this for now. >> + */ >> +void probe_read_access(CPUS390XState *env, uint64_t addr, uint64_t len, >> + uintptr_t ra) >> +{ >> +#ifdef CONFIG_USER_ONLY >> + if (!guest_addr_valid(addr) || !guest_addr_valid(addr + len - 1) || >> + page_check_range(addr, len, PAGE_READ) < 0) { >> + s390_program_interrupt(env, PGM_ADDRESSING, ILEN_AUTO, ra); >> + } >> +#else >> + while (len) { >> + const uint64_t pagelen = -(addr | -TARGET_PAGE_MASK); >> + const uint64_t curlen = MIN(pagelen, len); >> + >> + cpu_ldub_data_ra(env, addr, ra); >> + addr = wrap_address(env, addr + curlen); >> + len -= curlen; >> + } >> +#endif >> +} > > I don't think this is really the right approach, precisely because of the > comment above. > > I think we should > > (1) Modify the generic probe_write to return the host address, > akin to tlb_vaddr_to_host except it *will* fault. > > (2) Create a generic version of probe_write for CONFIG_USER_ONLY, > much like the one you have done for target/s390x. > > (3) Create generic version of probe_read that does the same. > > (4) Rewrite fast_memset and fast_memmove to fetch all of the host > addresses before doing any modifications. The functions are > currently written as if len can be very large, handling any > number of pages. Except that's not true. While there are > several kinds of users apart from MVC, two pages are sufficient > for all users. > > Well, should be. We would need to adjust do_mvcl to limit the > operation to TARGET_PAGE_SIZE (CC=3, cpu-determined number of > bytes moved without reaching end of first operand). > Which is probably a good idea anyway. System mode should not > spend forever executing one instruction, as it would if you > pass in a 64-bit length from MVCLE. >
Related to that: yes, that's what I mentioned in the cover letter, the MOVE variants are full of issues. MVCLE should be limited to 4096 bytes, and we should return cc=3. However, MVCL (which also uses do_mvcl) is also semi-broken (it's an interruptible instruction - not cc=3, we have to update the register step by step). MVCL should return cc=3 in case it's an destructive copy - also not implemented properly. mem_helpers.c is full of issues. -- Thanks, David / dhildenb