This patch introduces the 'platform' descriptor and an infrastructure to dynamically probe the platform where the core was generated. struct platform { char *name; /* name of the platform */ int pgdir_shift; int ptrs_per_pte; int pte_size; /* size of a pte (32/64) */ } base_platform; The above structure would hold the definitions for page translation for the platform where the core was generated. We maintain a list of probe functions, defined for each platform, which can check if the 'platform string' (obtained by reading the kernel variable 'powerpc_base_platform') matches one of its variants and update the descriptor with the specific values. There is a default probe function -at the end of the list - which would set the default values for the translation. get_machdep_info_ppc() will call ppc_probe_base_platform() to scan through the list of known platform probes to identify the running platform and update the descriptor accordingly. This infrastructure will be used for the vmalloc translation for PPC. Since there are a variety of platforms out there with different translation schemes, this infrastructure would help us to support all of them with very little overhead. Signed-off-by: Suzuki K. Poulose <suzuki at in.ibm.com> --- arch/ppc.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ makedumpfile.c | 2 ++ makedumpfile.h | 16 +++++++++++++--- 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/arch/ppc.c b/arch/ppc.c index 2ca0dc5..0ad2cf4 100644 --- a/arch/ppc.c +++ b/arch/ppc.c @@ -25,6 +25,56 @@ #include "../elf_info.h" #include "../makedumpfile.h" +#define MAX_PLATFORM_LEN 64 /* length of platform string */ + +struct platform { + char *name; + int pgdir_shift; + int ptrs_per_pte; + int pte_size; +} base_platform; + +typedef int (*probe_func_t)(char *, struct platform *); + +static int probe_default_platform(char *, struct platform*); + +probe_func_t probe_platforms[] = { + probe_default_platform, /* This should be at the end of the list */ + NULL +}; + +static int probe_default_platform(char *s, struct platform *p) +{ + /* Accept as the default platform */ + p->name = strdup(s); + p->pgdir_shift = DEFAULT_PGDIR_SHIFT; + p->ptrs_per_pte = DEFAULT_PTRS_PER_PTE; + p->pte_size = DEFAULT_PTE_SIZE; + + return TRUE; +} + +static void +ppc_probe_base_platform(void) +{ + unsigned long ptr; + char ppc_platform[MAX_PLATFORM_LEN]; + int i; + + + if (SYMBOL(powerpc_base_platform) == NOT_FOUND_SYMBOL || + !readmem(VADDR, SYMBOL(powerpc_base_platform), &ptr, sizeof(ptr)) || + !read_string(VADDR, ptr, ppc_platform, MAX_PLATFORM_LEN - 1)) + /* lets fallback to default if we couldn't find the platform */ + ppc_platform[0] = '\0'; + + for(i = 0; probe_platforms[i] != NULL; i++) { + probe_func_t probe = probe_platforms[i]; + if(probe(ppc_platform, &base_platform)) + break; + } +} + int get_machdep_info_ppc(void) { @@ -63,6 +113,9 @@ get_machdep_info_ppc(void) info->vmalloc_start = vmalloc_start; DEBUG_MSG("vmalloc_start: %lx\n", vmalloc_start); + ppc_probe_base_platform(); + DEBUG_MSG("Using '%s' platform VM definitions\n", base_platform.name); + return TRUE; } diff --git a/makedumpfile.c b/makedumpfile.c index e978e1c..2550edc 100644 --- a/makedumpfile.c +++ b/makedumpfile.c @@ -855,6 +855,8 @@ get_symbol_info(void) if (SYMBOL(__per_cpu_offset) != NOT_FOUND_SYMBOL) SYMBOL_ARRAY_LENGTH_INIT(__per_cpu_offset, "__per_cpu_offset"); + SYMBOL_INIT(powerpc_base_platform, "powerpc_base_platform"); + return TRUE; } diff --git a/makedumpfile.h b/makedumpfile.h index f7603d7..3a5152c 100644 --- a/makedumpfile.h +++ b/makedumpfile.h @@ -539,9 +539,13 @@ do { \ #define _SECTION_SIZE_BITS (24) #define _MAX_PHYSMEM_BITS (44) -#define PGDIR_SHIFT (22) -#define PTRS_PER_PTE (1024) -#define PTE_SIZE (sizeof(unsigned long)) +#define DEFAULT_PGDIR_SHIFT (22) +#define DEFAULT_PTRS_PER_PTE (1024) +#define DEFAULT_PTE_SIZE (sizeof(unsigned long)) + +#define PGDIR_SHIFT (base_platform.pgdir_shift) +#define PTRS_PER_PTE (base_platform.ptrs_per_pte) +#define PTE_SIZE (base_platform.pte_size) #define _PAGE_PRESENT (0x1) @@ -1018,6 +1022,12 @@ struct symbol_table { unsigned long long high_memory; /* + * PPC platform string pointer. Used for + * vmalloc translation. + */ + unsigned long long powerpc_base_platform; + + /* * for sadump */ unsigned long long linux_banner;