Commit 5246adec authored by Anton Blanchard's avatar Anton Blanchard Committed by Michael Ellerman
Browse files

powerpc/pseries: Use H_CLEAR_HPT to clear MMU hash table during kexec



An hcall was recently added that does exactly what we need during kexec
- it clears the entire MMU hash table, ignoring any VRMA mappings.

Try it and fall back to the old method if we get a failure.

On a POWER8 box with 5TB of memory, this reduces the time it takes to
kexec a new kernel from from 4 minutes to 1 minute.

Signed-off-by: default avatarAnton Blanchard <anton@samba.org>
Tested-by: default avatarMahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
[mpe: Split into separate functions and tweak function naming]
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 9e607f72
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -275,7 +275,8 @@
#define H_COP			0x304
#define H_GET_MPP_X		0x314
#define H_SET_MODE		0x31C
#define MAX_HCALL_OPCODE	H_SET_MODE
#define H_CLEAR_HPT		0x358
#define MAX_HCALL_OPCODE	H_CLEAR_HPT

/* H_VIOCTL functions */
#define H_GET_VIOA_DUMP_SIZE	0x01
+22 −2
Original line number Diff line number Diff line
@@ -221,7 +221,7 @@ static long pSeries_lpar_hpte_remove(unsigned long hpte_group)
	return -1;
}

static void pSeries_lpar_hptab_clear(void)
static void manual_hpte_clear_all(void)
{
	unsigned long size_bytes = 1UL << ppc64_pft_size;
	unsigned long hpte_count = size_bytes >> 4;
@@ -249,6 +249,26 @@ static void pSeries_lpar_hptab_clear(void)
					&(ptes[j].pteh), &(ptes[j].ptel));
		}
	}
}

static int hcall_hpte_clear_all(void)
{
	int rc;

	do {
		rc = plpar_hcall_norets(H_CLEAR_HPT);
	} while (rc == H_CONTINUE);

	return rc;
}

static void pseries_hpte_clear_all(void)
{
	int rc;

	rc = hcall_hpte_clear_all();
	if (rc != H_SUCCESS)
		manual_hpte_clear_all();

#ifdef __LITTLE_ENDIAN__
	/*
@@ -598,7 +618,7 @@ void __init hpte_init_pseries(void)
	mmu_hash_ops.hpte_remove	 = pSeries_lpar_hpte_remove;
	mmu_hash_ops.hpte_removebolted   = pSeries_lpar_hpte_removebolted;
	mmu_hash_ops.flush_hash_range	 = pSeries_lpar_flush_hash_range;
	mmu_hash_ops.hpte_clear_all      = pSeries_lpar_hptab_clear;
	mmu_hash_ops.hpte_clear_all      = pseries_hpte_clear_all;
	mmu_hash_ops.hugepage_invalidate = pSeries_lpar_hugepage_invalidate;
}