@ -61,8 +61,9 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong ptel = args [ 3 ] ;
target_ulong page_shift = 12 ;
target_ulong raddr ;
target_ulong i ;
target_ulong index ;
hwaddr hpte ;
uint64_t token ;
/* only handle 4k and 16M pages for now */
if ( pteh & HPTE64_V_LARGE ) {
@ -105,30 +106,37 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr,
if ( ! valid_pte_index ( env , pte_index ) ) {
return H_PARAMETER ;
}
index = 0 ;
hpte = pte_index * HASH_PTE_SIZE_64 ;
if ( likely ( ( flags & H_EXACT ) = = 0 ) ) {
pte_index & = ~ 7ULL ;
hpte = pte_index * HASH_PTE_SIZE_64 ;
for ( i = 0 ; ; + + i ) {
if ( i = = 8 ) {
token = ppc_hash64_start_access ( cpu , pte_index ) ;
do {
if ( index = = 8 ) {
ppc_hash64_stop_access ( token ) ;
return H_PTEG_FULL ;
}
if ( ( ppc_hash64_load_hpte0 ( env , hp te) & HPTE64_V_VALID ) = = 0 ) {
if ( ( ppc_hash64_load_hpte0 ( env , tok en , index ) & HPTE64_V_VALID ) = = 0 ) {
break ;
}
hpte + = HASH_PTE_SIZE_64 ;
}
} while ( index + + ) ;
ppc_hash64_stop_access ( token ) ;
} else {
i = 0 ;
hpte = pte_index * HASH_PTE_SIZE_64 ;
if ( ppc_hash64_load_hpte0 ( env , hpte ) & HPTE64_V_VALID ) {
token = ppc_hash64_start_access ( cpu , pte_index ) ;
if ( ppc_hash64_load_hpte0 ( env , token , 0 ) & HPTE64_V_VALID ) {
ppc_hash64_stop_access ( token ) ;
return H_PTEG_FULL ;
}
ppc_hash64_stop_access ( token ) ;
}
hpte + = index * HASH_PTE_SIZE_64 ;
ppc_hash64_store_hpte1 ( env , hpte , ptel ) ;
/* eieio(); FIXME: need some sort of barrier for smp? */
ppc_hash64_store_hpte0 ( env , hpte , pteh | HPTE64_V_HPTE_DIRTY ) ;
args [ 0 ] = pte_index + i ;
args [ 0 ] = pte_index + index ;
return H_SUCCESS ;
}
@ -145,16 +153,17 @@ static RemoveResult remove_hpte(CPUPPCState *env, target_ulong ptex,
target_ulong * vp , target_ulong * rp )
{
hwaddr hpte ;
uint64_t token ;
target_ulong v , r , rb ;
if ( ! valid_pte_index ( env , ptex ) ) {
return REMOVE_PARM ;
}
hp te = ptex * HASH_PTE_SIZE_64 ;
v = ppc_hash64_load_hpte0 ( env , hp te) ;
r = ppc_hash64_load_hpte1 ( env , hpte ) ;
tok en = ppc_hash64_start_access ( ppc_env_get_cpu ( env ) , ptex ) ;
v = ppc_hash64_load_hpte0 ( env , token , 0 ) ;
r = ppc_hash64_load_hpte1 ( env , tok en , 0 ) ;
ppc_hash64_stop_access ( token ) ;
if ( ( v & HPTE64_V_VALID ) = = 0 | |
( ( flags & H_AVPN ) & & ( v & ~ 0x7fULL ) ! = avpn ) | |
@ -163,6 +172,7 @@ static RemoveResult remove_hpte(CPUPPCState *env, target_ulong ptex,
}
* vp = v ;
* rp = r ;
hpte = ptex * HASH_PTE_SIZE_64 ;
ppc_hash64_store_hpte0 ( env , hpte , HPTE64_V_HPTE_DIRTY ) ;
rb = compute_tlbie_rb ( v , r , ptex ) ;
ppc_tlb_invalidate_one ( env , rb ) ;
@ -271,16 +281,17 @@ static target_ulong h_protect(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong pte_index = args [ 1 ] ;
target_ulong avpn = args [ 2 ] ;
hwaddr hpte ;
uint64_t token ;
target_ulong v , r , rb ;
if ( ! valid_pte_index ( env , pte_index ) ) {
return H_PARAMETER ;
}
hp te = pte_index * HASH_PTE_SIZE_64 ;
v = ppc_hash64_load_hpte0 ( env , hp te) ;
r = ppc_hash64_load_hpte1 ( env , hpte ) ;
tok en = ppc_hash64_start_access ( cpu , pte_index ) ;
v = ppc_hash64_load_hpte0 ( env , token , 0 ) ;
r = ppc_hash64_load_hpte1 ( env , tok en , 0 ) ;
ppc_hash64_stop_access ( token ) ;
if ( ( v & HPTE64_V_VALID ) = = 0 | |
( ( flags & H_AVPN ) & & ( v & ~ 0x7fULL ) ! = avpn ) ) {
@ -293,6 +304,7 @@ static target_ulong h_protect(PowerPCCPU *cpu, sPAPREnvironment *spapr,
r | = ( flags < < 48 ) & HPTE64_R_KEY_HI ;
r | = flags & ( HPTE64_R_PP | HPTE64_R_N | HPTE64_R_KEY_LO ) ;
rb = compute_tlbie_rb ( v , r , pte_index ) ;
hpte = pte_index * HASH_PTE_SIZE_64 ;
ppc_hash64_store_hpte0 ( env , hpte , ( v & ~ HPTE64_V_VALID ) | HPTE64_V_HPTE_DIRTY ) ;
ppc_tlb_invalidate_one ( env , rb ) ;
ppc_hash64_store_hpte1 ( env , hpte , r ) ;