@ -392,11 +392,10 @@ address_space_translate_internal(AddressSpaceDispatch *d, hwaddr addr, hwaddr *x
static inline bool memory_access_is_direct ( MemoryRegion * mr , bool is_write )
{
if ( memory_region_is_ram ( mr ) ) {
return ! ( is_write & & mr - > readonly ) ;
}
if ( memory_region_is_romd ( mr ) ) {
return ! is_write ;
if ( is_write ) {
return memory_region_is_ram ( mr ) & & ! mr - > readonly ;
} else {
return memory_region_is_ram ( mr ) | | memory_region_is_romd ( mr ) ;
}
return false ;
@ -2469,8 +2468,8 @@ static bool prepare_mmio_access(MemoryRegion *mr)
return release_lock ;
}
MemTxResult address_space_rw ( AddressSpace * as , hwaddr addr , MemTxAttrs attrs ,
uint8_t * buf , int len , bool is_write )
MemTxResult address_space_write ( AddressSpace * as , hwaddr addr , MemTxAttrs attrs ,
const uint8_t * buf , int len )
{
hwaddr l ;
uint8_t * ptr ;
@ -2483,87 +2482,47 @@ MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
rcu_read_lock ( ) ;
while ( len > 0 ) {
l = len ;
mr = address_space_translate ( as , addr , & addr1 , & l , is_writ e) ;
mr = address_space_translate ( as , addr , & addr1 , & l , tru e) ;
if ( is_write ) {
if ( ! memory_access_is_direct ( mr , is_write ) ) {
release_lock | = prepare_mmio_access ( mr ) ;
l = memory_access_size ( mr , l , addr1 ) ;
/* XXX: could force current_cpu to NULL to avoid
potential bugs */
switch ( l ) {
case 8 :
/* 64 bit write access */
val = ldq_p ( buf ) ;
result | = memory_region_dispatch_write ( mr , addr1 , val , 8 ,
attrs ) ;
break ;
case 4 :
/* 32 bit write access */
val = ldl_p ( buf ) ;
result | = memory_region_dispatch_write ( mr , addr1 , val , 4 ,
attrs ) ;
break ;
case 2 :
/* 16 bit write access */
val = lduw_p ( buf ) ;
result | = memory_region_dispatch_write ( mr , addr1 , val , 2 ,
attrs ) ;
break ;
case 1 :
/* 8 bit write access */
val = ldub_p ( buf ) ;
result | = memory_region_dispatch_write ( mr , addr1 , val , 1 ,
attrs ) ;
break ;
default :
abort ( ) ;
}
} else {
addr1 + = memory_region_get_ram_addr ( mr ) ;
/* RAM case */
ptr = qemu_get_ram_ptr ( addr1 ) ;
memcpy ( ptr , buf , l ) ;
invalidate_and_set_dirty ( mr , addr1 , l ) ;
if ( ! memory_access_is_direct ( mr , true ) ) {
release_lock | = prepare_mmio_access ( mr ) ;
l = memory_access_size ( mr , l , addr1 ) ;
/* XXX: could force current_cpu to NULL to avoid
potential bugs */
switch ( l ) {
case 8 :
/* 64 bit write access */
val = ldq_p ( buf ) ;
result | = memory_region_dispatch_write ( mr , addr1 , val , 8 ,
attrs ) ;
break ;
case 4 :
/* 32 bit write access */
val = ldl_p ( buf ) ;
result | = memory_region_dispatch_write ( mr , addr1 , val , 4 ,
attrs ) ;
break ;
case 2 :
/* 16 bit write access */
val = lduw_p ( buf ) ;
result | = memory_region_dispatch_write ( mr , addr1 , val , 2 ,
attrs ) ;
break ;
case 1 :
/* 8 bit write access */
val = ldub_p ( buf ) ;
result | = memory_region_dispatch_write ( mr , addr1 , val , 1 ,
attrs ) ;
break ;
default :
abort ( ) ;
}
} else {
if ( ! memory_access_is_direct ( mr , is_write ) ) {
/* I/O case */
release_lock | = prepare_mmio_access ( mr ) ;
l = memory_access_size ( mr , l , addr1 ) ;
switch ( l ) {
case 8 :
/* 64 bit read access */
result | = memory_region_dispatch_read ( mr , addr1 , & val , 8 ,
attrs ) ;
stq_p ( buf , val ) ;
break ;
case 4 :
/* 32 bit read access */
result | = memory_region_dispatch_read ( mr , addr1 , & val , 4 ,
attrs ) ;
stl_p ( buf , val ) ;
break ;
case 2 :
/* 16 bit read access */
result | = memory_region_dispatch_read ( mr , addr1 , & val , 2 ,
attrs ) ;
stw_p ( buf , val ) ;
break ;
case 1 :
/* 8 bit read access */
result | = memory_region_dispatch_read ( mr , addr1 , & val , 1 ,
attrs ) ;
stb_p ( buf , val ) ;
break ;
default :
abort ( ) ;
}
} else {
/* RAM case */
ptr = qemu_get_ram_ptr ( mr - > ram_addr + addr1 ) ;
memcpy ( buf , ptr , l ) ;
}
addr1 + = memory_region_get_ram_addr ( mr ) ;
/* RAM case */
ptr = qemu_get_ram_ptr ( addr1 ) ;
memcpy ( ptr , buf , l ) ;
invalidate_and_set_dirty ( mr , addr1 , l ) ;
}
if ( release_lock ) {
@ -2580,18 +2539,83 @@ MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
return result ;
}
MemTxResult address_space_write ( AddressSpace * as , hwaddr addr , MemTxAttrs attrs ,
const uint8_t * buf , int len )
{
return address_space_rw ( as , addr , attrs , ( uint8_t * ) buf , len , true ) ;
}
MemTxResult address_space_read ( AddressSpace * as , hwaddr addr , MemTxAttrs attrs ,
uint8_t * buf , int len )
{
return address_space_rw ( as , addr , attrs , buf , len , false ) ;
hwaddr l ;
uint8_t * ptr ;
uint64_t val ;
hwaddr addr1 ;
MemoryRegion * mr ;
MemTxResult result = MEMTX_OK ;
bool release_lock = false ;
rcu_read_lock ( ) ;
while ( len > 0 ) {
l = len ;
mr = address_space_translate ( as , addr , & addr1 , & l , false ) ;
if ( ! memory_access_is_direct ( mr , false ) ) {
/* I/O case */
release_lock | = prepare_mmio_access ( mr ) ;
l = memory_access_size ( mr , l , addr1 ) ;
switch ( l ) {
case 8 :
/* 64 bit read access */
result | = memory_region_dispatch_read ( mr , addr1 , & val , 8 ,
attrs ) ;
stq_p ( buf , val ) ;
break ;
case 4 :
/* 32 bit read access */
result | = memory_region_dispatch_read ( mr , addr1 , & val , 4 ,
attrs ) ;
stl_p ( buf , val ) ;
break ;
case 2 :
/* 16 bit read access */
result | = memory_region_dispatch_read ( mr , addr1 , & val , 2 ,
attrs ) ;
stw_p ( buf , val ) ;
break ;
case 1 :
/* 8 bit read access */
result | = memory_region_dispatch_read ( mr , addr1 , & val , 1 ,
attrs ) ;
stb_p ( buf , val ) ;
break ;
default :
abort ( ) ;
}
} else {
/* RAM case */
ptr = qemu_get_ram_ptr ( mr - > ram_addr + addr1 ) ;
memcpy ( buf , ptr , l ) ;
}
if ( release_lock ) {
qemu_mutex_unlock_iothread ( ) ;
release_lock = false ;
}
len - = l ;
buf + = l ;
addr + = l ;
}
rcu_read_unlock ( ) ;
return result ;
}
MemTxResult address_space_rw ( AddressSpace * as , hwaddr addr , MemTxAttrs attrs ,
uint8_t * buf , int len , bool is_write )
{
if ( is_write ) {
return address_space_write ( as , addr , attrs , ( uint8_t * ) buf , len ) ;
} else {
return address_space_read ( as , addr , attrs , ( uint8_t * ) buf , len ) ;
}
}
void cpu_physical_memory_rw ( hwaddr addr , uint8_t * buf ,
int len , int is_write )