qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

address_space_read: address_space_to_flatview needs RCU lock

address_space_read is calling address_space_to_flatview but it can
be called outside the RCU lock. To fix it, push the rcu_read_lock/unlock
pair up from flatview_read_full to address_space_read's constant size
fast path and address_space_read_full.

Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

+35 -28
+25 -13
exec.c
··· 2616 2616 }, 2617 2617 }; 2618 2618 2619 + static MemTxResult flatview_read(FlatView *fv, hwaddr addr, 2620 + MemTxAttrs attrs, uint8_t *buf, int len); 2619 2621 static MemTxResult flatview_write(FlatView *fv, hwaddr addr, MemTxAttrs attrs, 2620 2622 const uint8_t *buf, int len); 2621 2623 static bool flatview_access_valid(FlatView *fv, hwaddr addr, int len, ··· 3165 3167 return result; 3166 3168 } 3167 3169 3168 - MemTxResult flatview_read_full(FlatView *fv, hwaddr addr, 3169 - MemTxAttrs attrs, uint8_t *buf, int len) 3170 + /* Called from RCU critical section. */ 3171 + static MemTxResult flatview_read(FlatView *fv, hwaddr addr, 3172 + MemTxAttrs attrs, uint8_t *buf, int len) 3170 3173 { 3171 3174 hwaddr l; 3172 3175 hwaddr addr1; 3173 3176 MemoryRegion *mr; 3174 - MemTxResult result = MEMTX_OK; 3175 3177 3176 - if (len > 0) { 3177 - rcu_read_lock(); 3178 - l = len; 3179 - mr = flatview_translate(fv, addr, &addr1, &l, false); 3180 - result = flatview_read_continue(fv, addr, attrs, buf, len, 3181 - addr1, l, mr); 3182 - rcu_read_unlock(); 3183 - } 3184 - 3185 - return result; 3178 + l = len; 3179 + mr = flatview_translate(fv, addr, &addr1, &l, false); 3180 + return flatview_read_continue(fv, addr, attrs, buf, len, 3181 + addr1, l, mr); 3186 3182 } 3187 3183 3188 3184 static MemTxResult flatview_rw(FlatView *fv, hwaddr addr, MemTxAttrs attrs, ··· 3201 3197 { 3202 3198 return flatview_rw(address_space_to_flatview(as), 3203 3199 addr, attrs, buf, len, is_write); 3200 + } 3201 + 3202 + MemTxResult address_space_read_full(AddressSpace *as, hwaddr addr, 3203 + MemTxAttrs attrs, uint8_t *buf, int len) 3204 + { 3205 + MemTxResult result = MEMTX_OK; 3206 + FlatView *fv; 3207 + 3208 + if (len > 0) { 3209 + rcu_read_lock(); 3210 + fv = address_space_to_flatview(as); 3211 + result = flatview_read(fv, addr, attrs, buf, len); 3212 + rcu_read_unlock(); 3213 + } 3214 + 3215 + return result; 3204 3216 } 3205 3217 3206 3218 MemTxResult address_space_write(AddressSpace *as, hwaddr addr,
+10 -15
include/exec/memory.h
··· 1917 1917 1918 1918 1919 1919 /* Internal functions, part of the implementation of address_space_read. */ 1920 + MemTxResult address_space_read_full(AddressSpace *as, hwaddr addr, 1921 + MemTxAttrs attrs, uint8_t *buf, int len); 1920 1922 MemTxResult flatview_read_continue(FlatView *fv, hwaddr addr, 1921 1923 MemTxAttrs attrs, uint8_t *buf, 1922 1924 int len, hwaddr addr1, hwaddr l, 1923 1925 MemoryRegion *mr); 1924 - 1925 - MemTxResult flatview_read_full(FlatView *fv, hwaddr addr, 1926 - MemTxAttrs attrs, uint8_t *buf, int len); 1927 1926 void *qemu_map_ram_ptr(RAMBlock *ram_block, ram_addr_t addr); 1928 1927 1929 1928 static inline bool memory_access_is_direct(MemoryRegion *mr, bool is_write) ··· 1942 1941 * 1943 1942 * Return a MemTxResult indicating whether the operation succeeded 1944 1943 * or failed (eg unassigned memory, device rejected the transaction, 1945 - * IOMMU fault). 1944 + * IOMMU fault). Called within RCU critical section. 1946 1945 * 1947 - * @fv: #FlatView to be accessed 1946 + * @as: #AddressSpace to be accessed 1948 1947 * @addr: address within that address space 1949 1948 * @attrs: memory transaction attributes 1950 1949 * @buf: buffer with the data transferred 1951 1950 */ 1952 1951 static inline __attribute__((__always_inline__)) 1953 - MemTxResult flatview_read(FlatView *fv, hwaddr addr, MemTxAttrs attrs, 1954 - uint8_t *buf, int len) 1952 + MemTxResult address_space_read(AddressSpace *as, hwaddr addr, 1953 + MemTxAttrs attrs, uint8_t *buf, 1954 + int len) 1955 1955 { 1956 1956 MemTxResult result = MEMTX_OK; 1957 1957 hwaddr l, addr1; 1958 1958 void *ptr; 1959 1959 MemoryRegion *mr; 1960 + FlatView *fv; 1960 1961 1961 1962 if (__builtin_constant_p(len)) { 1962 1963 if (len) { 1963 1964 rcu_read_lock(); 1965 + fv = address_space_to_flatview(as); 1964 1966 l = len; 1965 1967 mr = flatview_translate(fv, addr, &addr1, &l, false); 1966 1968 if (len == l && memory_access_is_direct(mr, false)) { ··· 1973 1975 rcu_read_unlock(); 1974 1976 } 1975 1977 } else { 1976 - result = flatview_read_full(fv, addr, attrs, buf, len); 1978 + result = address_space_read_full(as, addr, attrs, buf, len); 1977 1979 } 1978 1980 return result; 1979 - } 1980 - 1981 - static inline MemTxResult address_space_read(AddressSpace *as, hwaddr addr, 1982 - MemTxAttrs attrs, uint8_t *buf, 1983 - int len) 1984 - { 1985 - return flatview_read(address_space_to_flatview(as), addr, attrs, buf, len); 1986 1981 } 1987 1982 1988 1983 /**