--- a/src/sh4/mmu.c Sat Jan 03 03:30:26 2009 +0000 +++ b/src/sh4/mmu.c Mon Jan 05 04:16:28 2009 +0000 @@ -79,7 +79,8 @@ static void mmu_set_tlb_asid( uint32_t asid ); static void mmu_set_storequeue_protected( int protected ); static gboolean mmu_utlb_map_pages( mem_region_fn_t priv_page, mem_region_fn_t user_page, sh4addr_t start_addr, int npages ); -static gboolean mmu_utlb_unmap_pages( gboolean unmap_user, sh4addr_t start_addr, int npages ); +static void mmu_utlb_remap_pages( gboolean remap_priv, gboolean remap_user, int entryNo ); +static gboolean mmu_utlb_unmap_pages( gboolean unmap_priv, gboolean unmap_user, sh4addr_t start_addr, int npages ); static gboolean mmu_ext_page_remapped( sh4addr_t page, mem_region_fn_t fn, void *user_data ); static void mmu_utlb_1k_init(); static struct utlb_1k_entry *mmu_utlb_1k_alloc(); @@ -420,13 +421,13 @@ /* Scan for pages that need to be remapped */ int i; if( IS_SV_ENABLED() ) { - // FIXME: Priv pages don't change - only user pages are mapped in/out for( i=0; i= mask ) { + /* entry is no larger than the area we're replacing - map completely */ + start_addr = mmu_utlb[i].vpn & mmu_utlb[i].mask; + npages = get_tlb_size_pages( mmu_utlb[i].flags ); + } else { + /* Otherwise map subset - region covered by removed page */ + start_addr = remap_addr; + npages = get_tlb_size_pages( mmu_utlb[entryNo].flags ); + } + + if( (mmu_utlb[i].flags & TLB_SHARE) || mmu_utlb[i].asid == mmu_asid ) { + mmu_utlb_map_pages( priv_page, user_page, start_addr, npages ); + } else if( IS_SV_ENABLED() ) { + mmu_utlb_map_pages( priv_page, NULL, start_addr, npages ); + } + + } + } +} + +/** * Remove a previous TLB mapping (replacing them with the TLB miss region). * @return FALSE if any pages were previously mapped to the TLB multihit page, * otherwise TRUE. In either case, all pages in the region are cleared to TLB miss. */ -static gboolean mmu_utlb_unmap_pages( gboolean unmap_user, sh4addr_t start_addr, int npages ) +static gboolean mmu_utlb_unmap_pages( gboolean unmap_priv, gboolean unmap_user, sh4addr_t start_addr, int npages ) { mem_region_fn_t *ptr = &sh4_address_space[start_addr >> 12]; mem_region_fn_t *uptr = &sh4_user_address_space[start_addr >> 12]; @@ -599,8 +641,10 @@ if( ent->subpages[idx] == &mem_region_tlb_multihit ) { unmapping_ok = FALSE; } - ent->subpages[idx] = &mem_region_tlb_miss; - ent->user_subpages[idx] = &mem_region_tlb_miss; + if( unmap_priv ) + ent->subpages[idx] = &mem_region_tlb_miss; + if( unmap_user ) + ent->user_subpages[idx] = &mem_region_tlb_miss; /* If all 4 subpages have the same content, merge them together and * release the 1K entry @@ -619,24 +663,35 @@ *uptr = user_page; } } else { - if( !unmap_user ) { - /* Privileged (un)mapping only */ + if( unmap_priv ) { + if( unmap_user ) { + for( i=0; imask); - if( j != entry && (start_addr & mask) == (mmu_utlb[j].vpn & mask) ) { - - } - } + mmu_utlb_remap_pages( TRUE, unmap_user, entry ); } }