diff mbox series

[v2,09/28] s390x/tcg: MVCLU/MVCLE: Process max 4k bytes at a time

Message ID 20190906075750.14791-10-david@redhat.com (mailing list archive)
State New, archived
Headers show
Series s390x/tcg: mem_helper: Fault-safe handling | expand

Commit Message

David Hildenbrand Sept. 6, 2019, 7:57 a.m. UTC
... and indicate cc=3 in case there is work remaining. Keep unicode
padding simple.

While reworking, properly wrap the addresses.

Signed-off-by: David Hildenbrand <david@redhat.com>
---
 target/s390x/mem_helper.c | 54 ++++++++++++++++++++++-----------------
 1 file changed, 31 insertions(+), 23 deletions(-)

Comments

Richard Henderson Sept. 11, 2019, 3:05 p.m. UTC | #1
On 9/6/19 3:57 AM, David Hildenbrand wrote:
> +    if (*srclen) {
> +        /* Copy the src array */
> +        len = MIN(len, *srclen);
> +        *destlen -= len;
> +        *srclen -= len;
> +        fast_memmove(env, *dest, *src, len, ra);
> +        *src = wrap_address(env, *src + len);
> +        *dest = wrap_address(env, *dest + len);
> +    } else if (wordsize == 1) {
> +        /* Pad the remaining area */
> +        *destlen -= len;
> +        fast_memset(env, *dest, pad, len, ra);
> +        *dest = wrap_address(env, *dest + len);

Again, I'm not sure fast_memmove actually handles wrap, yet.
Would it be easier to split at page boundaries rather than a
fixed 4k length?


r~
David Hildenbrand Sept. 11, 2019, 4:14 p.m. UTC | #2
On 11.09.19 17:05, Richard Henderson wrote:
> On 9/6/19 3:57 AM, David Hildenbrand wrote:
>> +    if (*srclen) {
>> +        /* Copy the src array */
>> +        len = MIN(len, *srclen);
>> +        *destlen -= len;
>> +        *srclen -= len;
>> +        fast_memmove(env, *dest, *src, len, ra);
>> +        *src = wrap_address(env, *src + len);
>> +        *dest = wrap_address(env, *dest + len);
>> +    } else if (wordsize == 1) {
>> +        /* Pad the remaining area */
>> +        *destlen -= len;
>> +        fast_memset(env, *dest, pad, len, ra);
>> +        *dest = wrap_address(env, *dest + len);
> 
> Again, I'm not sure fast_memmove actually handles wrap, yet.

Similarly, fixed by access_prepare(), access_memmove().

> Would it be easier to split at page boundaries rather than a
> fixed 4k length?

Also had that already, can do.
diff mbox series

Patch

diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index 947a4277f0..6d8ebd18fa 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -769,8 +769,8 @@  static inline uint32_t do_mvcl(CPUS390XState *env,
                                uint64_t *src, uint64_t *srclen,
                                uint16_t pad, int wordsize, uintptr_t ra)
 {
-    uint64_t len = MIN(*srclen, *destlen);
-    uint32_t cc;
+    int len = MIN(*destlen, TARGET_PAGE_SIZE);
+    int i, cc;
 
     if (*destlen == *srclen) {
         cc = 0;
@@ -780,32 +780,40 @@  static inline uint32_t do_mvcl(CPUS390XState *env,
         cc = 2;
     }
 
-    /* Copy the src array */
-    fast_memmove(env, *dest, *src, len, ra);
-    *src += len;
-    *srclen -= len;
-    *dest += len;
-    *destlen -= len;
+    if (!*destlen) {
+        return cc;
+    }
 
-    /* Pad the remaining area */
-    if (wordsize == 1) {
-        fast_memset(env, *dest, pad, *destlen, ra);
-        *dest += *destlen;
-        *destlen = 0;
+    /*
+     * Only perform one type of type of operation (move/pad) at a time.
+     * Process up to 4k bytes.
+     */
+    if (*srclen) {
+        /* Copy the src array */
+        len = MIN(len, *srclen);
+        *destlen -= len;
+        *srclen -= len;
+        fast_memmove(env, *dest, *src, len, ra);
+        *src = wrap_address(env, *src + len);
+        *dest = wrap_address(env, *dest + len);
+    } else if (wordsize == 1) {
+        /* Pad the remaining area */
+        *destlen -= len;
+        fast_memset(env, *dest, pad, len, ra);
+        *dest = wrap_address(env, *dest + len);
     } else {
-        /* If remaining length is odd, pad with odd byte first.  */
-        if (*destlen & 1) {
-            cpu_stb_data_ra(env, *dest, pad & 0xff, ra);
-            *dest += 1;
-            *destlen -= 1;
-        }
-        /* The remaining length is even, pad using words.  */
-        for (; *destlen; *dest += 2, *destlen -= 2) {
-            cpu_stw_data_ra(env, *dest, pad, ra);
+        /* The remaining length selects the padding byte. */
+        for (i = 0; i < len; (*destlen)--, i++) {
+            if (*destlen & 1) {
+                cpu_stb_data_ra(env, *dest, pad, ra);
+            } else {
+                cpu_stb_data_ra(env, *dest, pad >> 8, ra);
+            }
+            *dest = wrap_address(env, *dest + 1);
         }
     }
 
-    return cc;
+    return *destlen ? 3 : cc;
 }
 
 /* move long */