[PATCH 8/8] ppc64: enable address translation support for radix mmu
Hari Bathini
hbathini at linux.vnet.ibm.com
Tue Sep 27 13:24:48 PDT 2016
As both radix and hash MMU are supported in a single kernel on
Power ISA 3.0 based server processors, identify the current MMU
type and set page table index values accordingly.
Signed-off-by: Hari Bathini <hbathini at linux.vnet.ibm.com>
---
arch/ppc64.c | 47 +++++++++++++++++++++++++++++++++++++++++------
makedumpfile.c | 11 +++++++++++
makedumpfile.h | 39 ++++++++++++++++++++++++++++++---------
3 files changed, 82 insertions(+), 15 deletions(-)
diff --git a/arch/ppc64.c b/arch/ppc64.c
index 40076eb..6aeab7e 100644
--- a/arch/ppc64.c
+++ b/arch/ppc64.c
@@ -237,7 +237,13 @@ ppc64_vmalloc_init(void)
/*
* 64K pagesize
*/
- if (info->kernel_version >= KERNEL_VERSION(4, 6, 0)) {
+ if (info->cur_mmu_type & RADIX_MMU) {
+ info->l1_index_size = PTE_INDEX_SIZE_RADIX_64K;
+ info->l2_index_size = PMD_INDEX_SIZE_RADIX_64K;
+ info->l3_index_size = PUD_INDEX_SIZE_RADIX_64K;
+ info->l4_index_size = PGD_INDEX_SIZE_RADIX_64K;
+
+ } else if (info->kernel_version >= KERNEL_VERSION(4, 6, 0)) {
info->l1_index_size = PTE_INDEX_SIZE_L4_64K_3_10;
info->l2_index_size = PMD_INDEX_SIZE_L4_64K_4_6;
info->l3_index_size = PUD_INDEX_SIZE_L4_64K_4_6;
@@ -272,11 +278,19 @@ ppc64_vmalloc_init(void)
/*
* 4K pagesize
*/
- info->l1_index_size = PTE_INDEX_SIZE_L4_4K;
- info->l2_index_size = PMD_INDEX_SIZE_L4_4K;
- info->l3_index_size = (info->kernel_version >= KERNEL_VERSION(3, 7, 0) ?
- PUD_INDEX_SIZE_L4_4K_3_7 : PUD_INDEX_SIZE_L4_4K);
- info->l4_index_size = PGD_INDEX_SIZE_L4_4K;
+ if (info->cur_mmu_type & RADIX_MMU) {
+ info->l1_index_size = PTE_INDEX_SIZE_RADIX_4K;
+ info->l2_index_size = PMD_INDEX_SIZE_RADIX_4K;
+ info->l3_index_size = PUD_INDEX_SIZE_RADIX_4K;
+ info->l4_index_size = PGD_INDEX_SIZE_RADIX_4K;
+
+ } else {
+ info->l1_index_size = PTE_INDEX_SIZE_L4_4K;
+ info->l2_index_size = PMD_INDEX_SIZE_L4_4K;
+ info->l3_index_size = (info->kernel_version >= KERNEL_VERSION(3, 7, 0) ?
+ PUD_INDEX_SIZE_L4_4K_3_7 : PUD_INDEX_SIZE_L4_4K);
+ info->l4_index_size = PGD_INDEX_SIZE_L4_4K;
+ }
info->pte_rpn_shift = (info->kernel_version >= KERNEL_VERSION(4, 5, 0) ?
PTE_RPN_SHIFT_L4_4K_4_5 : PTE_RPN_SHIFT_L4_4K);
@@ -537,6 +551,27 @@ get_machdep_info_ppc64(void)
int
get_versiondep_info_ppc64()
{
+ unsigned long cur_cpu_spec;
+ uint mmu_features;
+
+ /*
+ * On PowerISA 3.0 based server processors, a kernel can run with
+ * radix MMU or standard MMU. Get the current MMU type.
+ */
+ info->cur_mmu_type = STD_MMU;
+ if ((SYMBOL(cur_cpu_spec) != NOT_FOUND_SYMBOL)
+ && (OFFSET(cpu_spec.mmu_features) != NOT_FOUND_STRUCTURE)) {
+ if (readmem(VADDR, SYMBOL(cur_cpu_spec), &cur_cpu_spec,
+ sizeof(cur_cpu_spec))) {
+ if (readmem(VADDR, cur_cpu_spec + OFFSET(cpu_spec.mmu_features),
+ &mmu_features, sizeof(mmu_features)))
+ info->cur_mmu_type = mmu_features & RADIX_MMU;
+ }
+ }
+
+ /*
+ * Initialize Linux page table info
+ */
if (ppc64_vmalloc_init() == FALSE) {
ERRMSG("Can't initialize for vmalloc translation\n");
return FALSE;
diff --git a/makedumpfile.c b/makedumpfile.c
index d168dfd..c4b3c62 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -1567,6 +1567,7 @@ get_symbol_info(void)
SYMBOL_INIT(cpu_pgd, "cpu_pgd");
SYMBOL_INIT(demote_segment_4k, "demote_segment_4k");
+ SYMBOL_INIT(cur_cpu_spec, "cur_cpu_spec");
return TRUE;
}
@@ -1949,6 +1950,12 @@ get_structure_info(void)
SIZE_INIT(mmu_psize_def, "mmu_psize_def");
OFFSET_INIT(mmu_psize_def.shift, "mmu_psize_def", "shift");
+ /*
+ * Get offsets of the cpu_spec's members.
+ */
+ SIZE_INIT(cpu_spec, "cpu_spec");
+ OFFSET_INIT(cpu_spec.mmu_features, "cpu_spec", "mmu_features");
+
return TRUE;
}
@@ -2151,6 +2158,7 @@ write_vmcoreinfo_data(void)
WRITE_SYMBOL("mmu_vmemmap_psize", mmu_vmemmap_psize);
WRITE_SYMBOL("cpu_pgd", cpu_pgd);
WRITE_SYMBOL("demote_segment_4k", demote_segment_4k);
+ WRITE_SYMBOL("cur_cpu_spec", cur_cpu_spec);
WRITE_SYMBOL("free_huge_page", free_huge_page);
/*
@@ -2226,6 +2234,7 @@ write_vmcoreinfo_data(void)
vmemmap_backing.virt_addr);
WRITE_MEMBER_OFFSET("vmemmap_backing.list", vmemmap_backing.list);
WRITE_MEMBER_OFFSET("mmu_psize_def.shift", mmu_psize_def.shift);
+ WRITE_MEMBER_OFFSET("cpu_spec.mmu_features", cpu_spec.mmu_features);
if (SYMBOL(node_data) != NOT_FOUND_SYMBOL)
WRITE_ARRAY_LENGTH("node_data", node_data);
@@ -2503,6 +2512,7 @@ read_vmcoreinfo(void)
READ_SYMBOL("mmu_vmemmap_psize", mmu_vmemmap_psize);
READ_SYMBOL("cpu_pgd", cpu_pgd);
READ_SYMBOL("demote_segment_4k", demote_segment_4k);
+ READ_SYMBOL("cur_cpu_spec", cur_cpu_spec);
READ_SYMBOL("free_huge_page", free_huge_page);
READ_STRUCTURE_SIZE("page", page);
@@ -2561,6 +2571,7 @@ read_vmcoreinfo(void)
vmemmap_backing.virt_addr);
READ_MEMBER_OFFSET("vmemmap_backing.list", vmemmap_backing.list);
READ_MEMBER_OFFSET("mmu_psize_def.shift", mmu_psize_def.shift);
+ READ_MEMBER_OFFSET("cpu_spec.mmu_features", cpu_spec.mmu_features);
READ_STRUCTURE_SIZE("printk_log", printk_log);
if (SIZE(printk_log) != NOT_FOUND_STRUCTURE) {
diff --git a/makedumpfile.h b/makedumpfile.h
index 69747c0..a5955ff 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -633,6 +633,10 @@ int get_va_bits_arm64(void);
#define PUD_INDEX_SIZE_L4_4K 7
#define PGD_INDEX_SIZE_L4_4K 9
#define PUD_INDEX_SIZE_L4_4K_3_7 9
+#define PTE_INDEX_SIZE_RADIX_4K 9
+#define PMD_INDEX_SIZE_RADIX_4K 9
+#define PUD_INDEX_SIZE_RADIX_4K 9
+#define PGD_INDEX_SIZE_RADIX_4K 13
#define PTE_RPN_SHIFT_L4_4K 17
#define PTE_RPN_SHIFT_L4_4K_4_5 18
#define PGD_MASKED_BITS_4K 0
@@ -649,6 +653,10 @@ int get_va_bits_arm64(void);
#define PGD_INDEX_SIZE_L4_64K_3_10 12
#define PMD_INDEX_SIZE_L4_64K_4_6 5
#define PUD_INDEX_SIZE_L4_64K_4_6 5
+#define PTE_INDEX_SIZE_RADIX_64K 5
+#define PMD_INDEX_SIZE_RADIX_64K 9
+#define PUD_INDEX_SIZE_RADIX_64K 9
+#define PGD_INDEX_SIZE_RADIX_64K 13
#define PTE_RPN_SHIFT_L4_64K_V1 32
#define PTE_RPN_SHIFT_L4_64K_V2 30
#define PGD_MASKED_BITS_64K 0
@@ -668,6 +676,17 @@ int get_va_bits_arm64(void);
#define PUD_MASKED_BITS_4_7 0xc0000000000000ffUL
#define PMD_MASKED_BITS_4_7 0xc0000000000000ffUL
+/*
+ * Supported MMU types
+ */
+#define STD_MMU 0x0
+/*
+ * The flag bit for radix MMU in cpu_spec.mmu_features
+ * in the kernel. Use the same flag here.
+ */
+#define RADIX_MMU 0x40
+
+
#define PGD_MASK_L4 \
(info->kernel_version >= KERNEL_VERSION(3, 10, 0) ? (info->ptrs_per_pgd - 1) : 0x1ff)
#define PGD_OFFSET_L4(vaddr) ((vaddr >> (info->l4_shift)) & PGD_MASK_L4)
@@ -1129,6 +1148,7 @@ struct DumpInfo {
/*
* page table info for ppc64
*/
+ int cur_mmu_type;
int ptrs_per_pgd;
uint l4_index_size;
uint l3_index_size;
@@ -1438,17 +1458,14 @@ struct symbol_table {
unsigned long long kexec_crash_image;
/*
- * vmemmap symbols on ppc64 arch
+ * symbols on ppc64 arch
*/
unsigned long long vmemmap_list;
unsigned long long mmu_vmemmap_psize;
unsigned long long mmu_psize_defs;
-
- /*
- * vm related symbols for ppc64 arch
- */
unsigned long long cpu_pgd;
unsigned long long demote_segment_4k;
+ unsigned long long cur_cpu_spec;
};
struct size_table {
@@ -1485,10 +1502,11 @@ struct size_table {
long elf64_hdr;
/*
- * vmemmap symbols on ppc64 arch
+ * symbols on ppc64 arch
*/
long vmemmap_backing;
long mmu_psize_def;
+ long cpu_spec;
long pageflags;
};
@@ -1637,18 +1655,21 @@ struct offset_table {
} printk_log;
/*
- * vmemmap symbols on ppc64 arch
+ * symbols on ppc64 arch
*/
- struct mmu_psize_def {
+ struct mmu_psize_def_s {
long shift;
} mmu_psize_def;
- struct vmemmap_backing {
+ struct vmemmap_backing_s {
long phys;
long virt_addr;
long list;
} vmemmap_backing;
+ struct cpu_spec_s {
+ long mmu_features;
+ } cpu_spec;
};
/*
More information about the kexec
mailing list