aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pseries/lpar.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/pseries/lpar.c')
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c33
1 files changed, 20 insertions, 13 deletions
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 0707653612ba..cf79b46d8f88 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -367,21 +367,28 @@ static void pSeries_lpar_hptab_clear(void)
367{ 367{
368 unsigned long size_bytes = 1UL << ppc64_pft_size; 368 unsigned long size_bytes = 1UL << ppc64_pft_size;
369 unsigned long hpte_count = size_bytes >> 4; 369 unsigned long hpte_count = size_bytes >> 4;
370 unsigned long dummy1, dummy2, dword0; 370 struct {
371 unsigned long pteh;
372 unsigned long ptel;
373 } ptes[4];
371 long lpar_rc; 374 long lpar_rc;
372 int i; 375 int i, j;
373 376
374 /* TODO: Use bulk call */ 377 /* Read in batches of 4,
375 for (i = 0; i < hpte_count; i++) { 378 * invalidate only valid entries not in the VRMA
376 /* dont remove HPTEs with VRMA mappings */ 379 * hpte_count will be a multiple of 4
377 lpar_rc = plpar_pte_remove_raw(H_ANDCOND, i, HPTE_V_1TB_SEG, 380 */
378 &dummy1, &dummy2); 381 for (i = 0; i < hpte_count; i += 4) {
379 if (lpar_rc == H_NOT_FOUND) { 382 lpar_rc = plpar_pte_read_4_raw(0, i, (void *)ptes);
380 lpar_rc = plpar_pte_read_raw(0, i, &dword0, &dummy1); 383 if (lpar_rc != H_SUCCESS)
381 if (!lpar_rc && ((dword0 & HPTE_V_VRMA_MASK) 384 continue;
382 != HPTE_V_VRMA_MASK)) 385 for (j = 0; j < 4; j++){
383 /* Can be hpte for 1TB Seg. So remove it */ 386 if ((ptes[j].pteh & HPTE_V_VRMA_MASK) ==
384 plpar_pte_remove_raw(0, i, 0, &dummy1, &dummy2); 387 HPTE_V_VRMA_MASK)
388 continue;
389 if (ptes[j].pteh & HPTE_V_VALID)
390 plpar_pte_remove_raw(0, i + j, 0,
391 &(ptes[j].pteh), &(ptes[j].ptel));
385 } 392 }
386 } 393 }
387} 394}