@ -151,6 +151,7 @@ void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque)
}
static void xen_remap_bucket ( MapCacheEntry * entry ,
void * vaddr ,
hwaddr size ,
hwaddr address_index ,
bool dummy )
@ -167,7 +168,9 @@ static void xen_remap_bucket(MapCacheEntry *entry,
err = g_malloc0 ( nb_pfn * sizeof ( int ) ) ;
if ( entry - > vaddr_base ! = NULL ) {
ram_block_notify_remove ( entry - > vaddr_base , entry - > size ) ;
if ( ! ( entry - > flags & XEN_MAPCACHE_ENTRY_DUMMY ) ) {
ram_block_notify_remove ( entry - > vaddr_base , entry - > size ) ;
}
if ( munmap ( entry - > vaddr_base , entry - > size ) ! = 0 ) {
perror ( " unmap fails " ) ;
exit ( - 1 ) ;
@ -181,11 +184,11 @@ static void xen_remap_bucket(MapCacheEntry *entry,
}
if ( ! dummy ) {
vaddr_base = xenforeignmemory_map ( xen_fmem , xen_domid ,
PROT_READ | PROT_WRITE ,
vaddr_base = xenforeignmemory_map2 ( xen_fmem , xen_domid , vaddr ,
PROT_READ | PROT_WRITE , 0 ,
nb_pfn , pfns , err ) ;
if ( vaddr_base = = NULL ) {
perror ( " xenforeignmemory_map " ) ;
perror ( " xenforeignmemory_map2 " ) ;
exit ( - 1 ) ;
}
} else {
@ -193,7 +196,7 @@ static void xen_remap_bucket(MapCacheEntry *entry,
* We create dummy mappings where we are unable to create a foreign
* mapping immediately due to certain circumstances ( i . e . on resume now )
*/
vaddr_base = mmap ( NULL , size , PROT_READ | PROT_WRITE ,
vaddr_base = mmap ( vaddr , size , PROT_READ | PROT_WRITE ,
MAP_ANON | MAP_SHARED , - 1 , 0 ) ;
if ( vaddr_base = = NULL ) {
perror ( " mmap " ) ;
@ -201,6 +204,10 @@ static void xen_remap_bucket(MapCacheEntry *entry,
}
}
if ( ! ( entry - > flags & XEN_MAPCACHE_ENTRY_DUMMY ) ) {
ram_block_notify_add ( vaddr_base , size ) ;
}
entry - > vaddr_base = vaddr_base ;
entry - > paddr_index = address_index ;
entry - > size = size ;
@ -213,7 +220,6 @@ static void xen_remap_bucket(MapCacheEntry *entry,
entry - > flags & = ~ ( XEN_MAPCACHE_ENTRY_DUMMY ) ;
}
ram_block_notify_add ( entry - > vaddr_base , entry - > size ) ;
bitmap_zero ( entry - > valid_mapping , nb_pfn ) ;
for ( i = 0 ; i < nb_pfn ; i + + ) {
if ( ! err [ i ] ) {
@ -286,14 +292,14 @@ tryagain:
if ( ! entry ) {
entry = g_malloc0 ( sizeof ( MapCacheEntry ) ) ;
pentry - > next = entry ;
xen_remap_bucket ( entry , cache_size , address_index , dummy ) ;
xen_remap_bucket ( entry , NULL , cache_size , address_index , dummy ) ;
} else if ( ! entry - > lock ) {
if ( ! entry - > vaddr_base | | entry - > paddr_index ! = address_index | |
entry - > size ! = cache_size | |
! test_bits ( address_offset > > XC_PAGE_SHIFT ,
test_bit_size > > XC_PAGE_SHIFT ,
entry - > valid_mapping ) ) {
xen_remap_bucket ( entry , cache_size , address_index , dummy ) ;
xen_remap_bucket ( entry , NULL , cache_size , address_index , dummy ) ;
}
}
@ -490,3 +496,66 @@ void xen_invalidate_map_cache(void)
mapcache_unlock ( ) ;
}
static uint8_t * xen_replace_cache_entry_unlocked ( hwaddr old_phys_addr ,
hwaddr new_phys_addr ,
hwaddr size )
{
MapCacheEntry * entry ;
hwaddr address_index , address_offset ;
hwaddr test_bit_size , cache_size = size ;
address_index = old_phys_addr > > MCACHE_BUCKET_SHIFT ;
address_offset = old_phys_addr & ( MCACHE_BUCKET_SIZE - 1 ) ;
assert ( size ) ;
/* test_bit_size is always a multiple of XC_PAGE_SIZE */
test_bit_size = size + ( old_phys_addr & ( XC_PAGE_SIZE - 1 ) ) ;
if ( test_bit_size % XC_PAGE_SIZE ) {
test_bit_size + = XC_PAGE_SIZE - ( test_bit_size % XC_PAGE_SIZE ) ;
}
cache_size = size + address_offset ;
if ( cache_size % MCACHE_BUCKET_SIZE ) {
cache_size + = MCACHE_BUCKET_SIZE - ( cache_size % MCACHE_BUCKET_SIZE ) ;
}
entry = & mapcache - > entry [ address_index % mapcache - > nr_buckets ] ;
while ( entry & & ! ( entry - > paddr_index = = address_index & &
entry - > size = = cache_size ) ) {
entry = entry - > next ;
}
if ( ! entry ) {
DPRINTF ( " Trying to update an entry for %lx " \
" that is not in the mapcache! \n " , old_phys_addr ) ;
return NULL ;
}
address_index = new_phys_addr > > MCACHE_BUCKET_SHIFT ;
address_offset = new_phys_addr & ( MCACHE_BUCKET_SIZE - 1 ) ;
fprintf ( stderr , " Replacing a dummy mapcache entry for %lx with %lx \n " ,
old_phys_addr , new_phys_addr ) ;
xen_remap_bucket ( entry , entry - > vaddr_base ,
cache_size , address_index , false ) ;
if ( ! test_bits ( address_offset > > XC_PAGE_SHIFT ,
test_bit_size > > XC_PAGE_SHIFT ,
entry - > valid_mapping ) ) {
DPRINTF ( " Unable to update a mapcache entry for %lx! \n " , old_phys_addr ) ;
return NULL ;
}
return entry - > vaddr_base + address_offset ;
}
uint8_t * xen_replace_cache_entry ( hwaddr old_phys_addr ,
hwaddr new_phys_addr ,
hwaddr size )
{
uint8_t * p ;
mapcache_lock ( ) ;
p = xen_replace_cache_entry_unlocked ( old_phys_addr , new_phys_addr , size ) ;
mapcache_unlock ( ) ;
return p ;
}