Skip to content
  • Philippe Mathieu-Daudé's avatar
    98f52cdb
    memory: Fix access_with_adjusted_size(small size) on big-endian memory regions · 98f52cdb
    Philippe Mathieu-Daudé authored
    
    
    Memory regions configured as DEVICE_BIG_ENDIAN (or DEVICE_NATIVE_ENDIAN on
    big-endian guest) behave incorrectly when the memory access 'size' is smaller
    than the implementation 'access_size'.
    
    In the following code segment from access_with_adjusted_size():
    
        if (memory_region_big_endian(mr)) {
            for (i = 0; i < size; i += access_size) {
                r |= access_fn(mr, addr + i, value, access_size,
                            (size - access_size - i) * 8, access_mask, attrs);
            }
    
    (size - access_size - i) * 8 is the number of bits that will arithmetic
    shift the current value.
    
    Currently we can only 'left' shift a read() access, and 'right' shift a write().
    
    When the access 'size' is smaller than the implementation, we get a negative
    number of bits to shift.
    
    For the read() case, a negative 'left' shift is a 'right' shift :)
    However since the 'shift' type is unsigned, there is currently no way to
    right shift.
    
    Fix this by changing the access_fn() prototype to handle signed shift values,
    and modify the memory_region_shift_read|write_access() helpers to correctly
    arithmetic shift the opposite direction when the 'shift' value is negative.
    
    Signed-off-by: default avatarPhilippe Mathieu-Daudé <f4bug@amsat.org>
    Message-Id: <20180927002416.1781-4-f4bug@amsat.org>
    Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
    98f52cdb
    memory: Fix access_with_adjusted_size(small size) on big-endian memory regions
    Philippe Mathieu-Daudé authored
    
    
    Memory regions configured as DEVICE_BIG_ENDIAN (or DEVICE_NATIVE_ENDIAN on
    big-endian guest) behave incorrectly when the memory access 'size' is smaller
    than the implementation 'access_size'.
    
    In the following code segment from access_with_adjusted_size():
    
        if (memory_region_big_endian(mr)) {
            for (i = 0; i < size; i += access_size) {
                r |= access_fn(mr, addr + i, value, access_size,
                            (size - access_size - i) * 8, access_mask, attrs);
            }
    
    (size - access_size - i) * 8 is the number of bits that will arithmetic
    shift the current value.
    
    Currently we can only 'left' shift a read() access, and 'right' shift a write().
    
    When the access 'size' is smaller than the implementation, we get a negative
    number of bits to shift.
    
    For the read() case, a negative 'left' shift is a 'right' shift :)
    However since the 'shift' type is unsigned, there is currently no way to
    right shift.
    
    Fix this by changing the access_fn() prototype to handle signed shift values,
    and modify the memory_region_shift_read|write_access() helpers to correctly
    arithmetic shift the opposite direction when the 'shift' value is negative.
    
    Signed-off-by: default avatarPhilippe Mathieu-Daudé <f4bug@amsat.org>
    Message-Id: <20180927002416.1781-4-f4bug@amsat.org>
    Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
Loading