[Crash-utility] [PATCH v4 2/4] [ppc] Support for platform based Virtual address translation
Toshikazu Nakayama
nakayama.ts at ncos.nec.co.jp
Tue Feb 21 01:31:04 UTC 2012
(2012/02/20 20:06), Suzuki K. Poulose wrote:
> This patch adds infrastructure for defining Virtual address translation bits
> for each platform and use the specific definition for the platform depending on
> the 'powerpc_base_platform' variable. If a matching platform is not found,
> fallbacks to the default definition.
>
> Each platform can define a probe function which can identify the 'kernel
> platform string' to one of its variant. It can then update PGDIR_SHIFT,
> PTRS_PER_PGD, PTRS_PER_PTE, the size of a PTE and also the various Page flags.
>
> This patch also changes the pte to ulonglong type.
>
> mach command now displays the platform string read from the kernel.
>
> crash> mach
> MACHINE TYPE: ppc
> PLATFORM: ppc440gp
> MEMORY SIZE: 128 MB
> ...
>
> Signed-off-by: Suzuki K. Poulose<suzuki at in.ibm.com>
> ---
>
> defs.h | 82 ++++++++++++++++++++++++++++++++++---------
> ppc.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
> 2 files changed, 171 insertions(+), 34 deletions(-)
>
> diff --git a/defs.h b/defs.h
> index a942dbb..0c5558e 100755
> --- a/defs.h
> +++ b/defs.h
> @@ -2635,27 +2635,50 @@ struct load_module {
> #define _32BIT_
> #define MACHINE_TYPE "PPC"
>
> -#define PAGEBASE(X) (((ulong)(X))& (ulong)machdep->pagemask)
> +#define PAGEBASE(X) ((X)& machdep->pagemask)
>
> #define PTOV(X) ((unsigned long)(X)+(machdep->kvbase))
> #define VTOP(X) ((unsigned long)(X)-(machdep->kvbase))
> #define IS_VMALLOC_ADDR(X) (vt->vmalloc_start&& (ulong)(X)>= vt->vmalloc_start)
>
> -#define PGDIR_SHIFT (22)
> -#define PTRS_PER_PTE (1024)
> -#define PTRS_PER_PGD (1024)
> -
> -#define _PAGE_PRESENT 0x001 /* software: pte contains a translation */
> -#define _PAGE_USER 0x002 /* matches one of the PP bits */
> -#define _PAGE_RW 0x004 /* software: user write access allowed */
> -#define _PAGE_GUARDED 0x008
> -#define _PAGE_COHERENT 0x010 /* M: enforce memory coherence (SMP systems) */
> -#define _PAGE_NO_CACHE 0x020 /* I: cache inhibit */
> -#define _PAGE_WRITETHRU 0x040 /* W: cache write-through */
> -#define _PAGE_DIRTY 0x080 /* C: page changed */
> -#define _PAGE_ACCESSED 0x100 /* R: page referenced */
> -#define _PAGE_HWWRITE 0x200 /* software: _PAGE_RW& _PAGE_DIRTY */
> -#define _PAGE_SHARED 0
> +/* Page translation bits */
> +#define PPC_PLATFORM (machdep->machspec->platform)
> +#define PGDIR_SHIFT (machdep->machspec->pgdir_shift)
> +#define PTRS_PER_PTE (machdep->machspec->ptrs_per_pte)
> +#define PTRS_PER_PGD (machdep->machspec->ptrs_per_pgd)
> +#define PTE_SIZE (machdep->machspec->pte_size)
> +
> +/* Default values for Page translation */
> +#define DEFAULT_PGDIR_SHIFT (22)
> +#define DEFAULT_PTRS_PER_PTE (1024)
> +#define DEFAULT_PTRS_PER_PGD (1024)
> +#define DEFAULT_PTE_SIZE sizeof(ulong)
> +
> +/* PAGE flags */
> +#define _PAGE_PRESENT (machdep->machspec->_page_present) /* software: pte contains a translation */
> +#define _PAGE_USER (machdep->machspec->_page_user) /* matches one of the PP bits */
> +#define _PAGE_RW (machdep->machspec->_page_rw) /* software: user write access allowed */
> +#define _PAGE_GUARDED (machdep->machspec->_page_guarded)
> +#define _PAGE_COHERENT (machdep->machspec->_page_coherent /* M: enforce memory coherence (SMP systems) */)
> +#define _PAGE_NO_CACHE (machdep->machspec->_page_no_cache) /* I: cache inhibit */
> +#define _PAGE_WRITETHRU (machdep->machspec->_page_writethru) /* W: cache write-through */
> +#define _PAGE_DIRTY (machdep->machspec->_page_dirty) /* C: page changed */
> +#define _PAGE_ACCESSED (machdep->machspec->_page_accessed) /* R: page referenced */
> +#define _PAGE_HWWRITE (machdep->machspec->_page_hwwrite) /* software: _PAGE_RW& _PAGE_DIRTY */
> +#define _PAGE_SHARED (machdep->machspec->_page_shared)
> +
> +/* Default values for PAGE flags */
> +#define DEFAULT_PAGE_PRESENT 0x001
> +#define DEFAULT_PAGE_USER 0x002
> +#define DEFAULT_PAGE_RW 0x004
> +#define DEFAULT_PAGE_GUARDED 0x008
> +#define DEFAULT_PAGE_COHERENT 0x010
> +#define DEFAULT_PAGE_NO_CACHE 0x020
> +#define DEFAULT_PAGE_WRITETHRU 0x040
> +#define DEFAULT_PAGE_DIRTY 0x080
> +#define DEFAULT_PAGE_ACCESSED 0x100
> +#define DEFAULT_PAGE_HWWRITE 0x200
> +#define DEFAULT_PAGE_SHARED 0
>
> #define SWP_TYPE(entry) (((entry)>> 1)& 0x7f)
> #define SWP_OFFSET(entry) ((entry)>> 8)
> @@ -4533,6 +4556,33 @@ void ppc64_dump_machdep_table(ulong);
> * ppc.c
> */
> #ifdef PPC
> +
> +/* Holds the platform specific info for page translation */
> +struct machine_specific {
> +
> + char *platform;
> +
> + /* page address translation bits */
> + int pgdir_shift;
> + int ptrs_per_pgd;
> + int ptrs_per_pte;
> + int pte_size;
> +
> + /* page flags */
> + ulong _page_present;
> + ulong _page_user;
> + ulong _page_rw;
> + ulong _page_guarded;
> + ulong _page_coherent;
> + ulong _page_no_cache;
> + ulong _page_writethru;
> + ulong _page_dirty;
> + ulong _page_accessed;
> + ulong _page_hwwrite;
> + ulong _page_shared;
> +
> +};
> +
> void ppc_init(int);
> void ppc_dump_machdep_table(ulong);
> #define display_idt_table() \
> diff --git a/ppc.c b/ppc.c
> index 3834e7f..9f765b6 100755
> --- a/ppc.c
> +++ b/ppc.c
> @@ -17,6 +17,9 @@
> #ifdef PPC
> #include "defs.h"
>
> +
> +#define MAX_PLATFORM_LEN 32 /* length for platform string */
> +
> /*
> * This structure was copied from kernel source
> * in include/asm-ppc/ptrace.h
> @@ -67,6 +70,71 @@ static void ppc_display_machine_stats(void);
> static void ppc_dump_line_number(ulong);
> static struct line_number_hook ppc_line_number_hooks[];
>
> +
> +static struct machine_specific ppc_machine_specific = { 0 };
> +static int probe_default_platform(char *);
> +static void ppc_probe_base_platform(void);
> +
> +typedef int (*probe_func_t) (char *);
> +
> +probe_func_t probe_platforms[] = {
> + probe_default_platform, /* This should be at the end */
> + NULL
> +};
> +
> +static int
> +probe_default_platform(char *name)
> +{
> + struct machine_specific *machspec = machdep->machspec;
> +
> + /* Use the default definitions */
> + machspec->platform = strdup(name);
> +
> + machspec->pgdir_shift = DEFAULT_PGDIR_SHIFT;
> + machspec->ptrs_per_pgd = DEFAULT_PTRS_PER_PGD;
> + machspec->ptrs_per_pte = DEFAULT_PTRS_PER_PTE;
> + machspec->pte_size = DEFAULT_PTE_SIZE;
> +
> + machspec->_page_present = DEFAULT_PAGE_PRESENT;
> + machspec->_page_user = DEFAULT_PAGE_USER;
> + machspec->_page_rw = DEFAULT_PAGE_RW;
> + machspec->_page_guarded = DEFAULT_PAGE_GUARDED;
> + machspec->_page_coherent = DEFAULT_PAGE_COHERENT;
> + machspec->_page_no_cache = DEFAULT_PAGE_NO_CACHE;
> + machspec->_page_writethru = DEFAULT_PAGE_WRITETHRU;
> + machspec->_page_dirty = DEFAULT_PAGE_DIRTY;
> + machspec->_page_accessed = DEFAULT_PAGE_ACCESSED;
> + machspec->_page_hwwrite = DEFAULT_PAGE_HWWRITE;
> + machspec->_page_shared = DEFAULT_PAGE_SHARED;
> +
> +
> + return TRUE;
> +}
> +
> +/*
> + * Find the platform of the crashing system and set the
> + * base_platform accordingly.
> + */
> +void
> +ppc_probe_base_platform(void)
> +{
> + probe_func_t probe;
> + char platform_name[MAX_PLATFORM_LEN];
> + ulong ptr;
> + int i;
> +
> + if(!try_get_symbol_data("powerpc_base_platform", sizeof(ulong),&ptr) ||
> + read_string(ptr, platform_name, MAX_PLATFORM_LEN - 1) == 0)
> + /* Let us fallback to default definitions */
> + platform_name[0] = '\0';
Could you give some fallback message at PLATFORM: via 'mach' command
like "undetectable" or any good phrase?
> + for (i = 0; probe_platforms[i] != NULL; i++) {
> + probe = probe_platforms[i];
> + if (probe(platform_name))
> + break;
> + }
> +}
> +
> /*
> * Do all necessary machine-specific setup here. This is called twice,
> * before and after GDB has been initialized.
> @@ -80,6 +148,7 @@ ppc_init(int when)
> switch (when)
> {
> case SETUP_ENV:
> + machdep->machspec =&ppc_machine_specific;
> machdep->process_elf_notes = process_elf32_notes;
> break;
>
> @@ -101,7 +170,6 @@ ppc_init(int when)
> machdep->last_pmd_read = 0;
> machdep->last_ptbl_read = 0;
> machdep->verify_paddr = generic_verify_paddr;
> - machdep->ptrs_per_pgd = PTRS_PER_PGD;
> break;
>
> case PRE_GDB:
> @@ -127,6 +195,11 @@ ppc_init(int when)
> machdep->line_number_hooks = ppc_line_number_hooks;
> machdep->value_to_symbol = generic_machdep_value_to_symbol;
> machdep->init_kernel_pgd = NULL;
> +
> + /* Find the platform where we crashed */
> + ppc_probe_base_platform();
> + machdep->ptrs_per_pgd = PTRS_PER_PGD;
> +
> break;
>
> case POST_GDB:
> @@ -201,6 +274,7 @@ ppc_dump_machdep_table(ulong arg)
> int others;
>
> others = 0;
> + fprintf(fp, " platform: %s\n", PPC_PLATFORM);
> fprintf(fp, " flags: %lx (", machdep->flags);
> if (machdep->flags& KSYMS_START)
> fprintf(fp, "%sKSYMS_START", others++ ? "|" : "");
> @@ -212,6 +286,10 @@ ppc_dump_machdep_table(ulong arg)
> fprintf(fp, " pageshift: %d\n", machdep->pageshift);
> fprintf(fp, " pagemask: %llx\n", machdep->pagemask);
> fprintf(fp, " pageoffset: %lx\n", machdep->pageoffset);
> + fprintf(fp, " pgdir_shift: %d\n", PGDIR_SHIFT);
> + fprintf(fp, " ptrs_per_pgd: %d\n", PTRS_PER_PGD);
> + fprintf(fp, " ptrs_per_pte: %d\n", PTRS_PER_PTE);
> + fprintf(fp, " pte_size: %d\n", PTE_SIZE);
> fprintf(fp, " stacksize: %ld\n", machdep->stacksize);
> fprintf(fp, " hz: %d\n", machdep->hz);
> fprintf(fp, " mhz: %ld\n", machdep->mhz);
> @@ -252,7 +330,6 @@ ppc_dump_machdep_table(ulong arg)
> fprintf(fp, " pgd: %lx\n", (ulong)machdep->pgd);
> fprintf(fp, " pmd: %lx\n", (ulong)machdep->pmd);
> fprintf(fp, " ptbl: %lx\n", (ulong)machdep->ptbl);
> - fprintf(fp, " ptrs_per_pgd: %d\n", machdep->ptrs_per_pgd);
> fprintf(fp, " section_size_bits: %ld\n", machdep->section_size_bits);
> fprintf(fp, " max_physmem_bits: %ld\n", machdep->max_physmem_bits);
> fprintf(fp, " sections_per_root: %ld\n", machdep->sections_per_root);
> @@ -266,15 +343,20 @@ ppc_pgd_vtop(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
> ulong *page_middle;
> ulong *page_table;
> ulong pgd_pte;
> - ulong pte;
> + ulonglong pte;
>
> - if (verbose)
> + if (verbose)
> fprintf(fp, "PAGE DIRECTORY: %lx\n", (ulong)pgd);
>
> page_dir = pgd + (vaddr>> PGDIR_SHIFT);
>
> - FILL_PGD(PAGEBASE(pgd), KVADDR, PAGESIZE());
> - pgd_pte = ULONG(machdep->pgd + PAGEOFFSET(page_dir));
> + /*
> + * Size of a pgd could be more than a PAGE.
> + * So use PAGEBASE(page_dir), instead of
> + * PAGEBASE(pgd) for FILL_PGD()
> + */
> + FILL_PGD(PAGEBASE((ulong)page_dir), KVADDR, PAGESIZE());
> + pgd_pte = ULONG(machdep->pgd + PAGEOFFSET((ulong)page_dir));
>
> if (verbose)
> fprintf(fp, " PGD: %lx => %lx\n", (ulong)page_dir, pgd_pte);
> @@ -285,33 +367,37 @@ ppc_pgd_vtop(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
> page_middle = (ulong *)pgd_pte;
>
> if (machdep->flags& CPU_BOOKE)
> - page_table = page_middle + (BTOP(vaddr)& (PTRS_PER_PTE - 1));
> + page_table = (ulong *)((ulong)page_middle + ((ulong)BTOP(vaddr)& (PTRS_PER_PTE - 1)) * PTE_SIZE);
> else {
> page_table = (ulong *)((pgd_pte& (ulong)machdep->pagemask) + machdep->kvbase);
> - page_table += ((ulong)BTOP(vaddr)& (PTRS_PER_PTE-1));
> + page_table = (ulong *)((ulong)page_table + ((ulong)BTOP(vaddr)& (PTRS_PER_PTE-1)) * PTE_SIZE);
> }
>
> if (verbose)
> fprintf(fp, " PMD: %lx => %lx\n", (ulong)page_middle,
> (ulong)page_table);
>
> - FILL_PTBL(PAGEBASE(page_table), KVADDR, PAGESIZE());
> - pte = ULONG(machdep->ptbl + PAGEOFFSET(page_table));
> + FILL_PTBL(PAGEBASE((ulong)page_table), KVADDR, PAGESIZE());
> + if (PTE_SIZE == sizeof(ulonglong))
> + pte = ULONGLONG(machdep->ptbl + PAGEOFFSET((ulong)page_table));
> +
> + else /* Defaults to ulong */
> + pte = ULONG(machdep->ptbl + PAGEOFFSET((ulong)page_table));
>
> if (verbose)
> - fprintf(fp, " PTE: %lx => %lx\n", (ulong)page_table, pte);
> + fprintf(fp, " PTE: %lx => %llx\n", (ulong)page_table, pte);
>
> if (!(pte& _PAGE_PRESENT)) {
> if (pte&& verbose) {
> fprintf(fp, "\n");
> - ppc_translate_pte(pte, 0, 0);
> + ppc_translate_pte(0, 0, pte);
> }
> goto no_page;
> }
>
> if (verbose) {
> - fprintf(fp, " PAGE: %lx\n\n", PAGEBASE(pte));
> - ppc_translate_pte(pte, 0, 0);
> + fprintf(fp, " PAGE: %llx\n\n", PAGEBASE(pte));
> + ppc_translate_pte(0, 0, pte);
> }
>
> *paddr = PAGEBASE(pte) + PAGEOFFSET(vaddr);
> @@ -623,7 +709,7 @@ ppc_get_task_pgd(ulong task)
> * If a physaddr pointer is passed in, don't print anything.
> */
> static int
> -ppc_translate_pte(ulong pte, void *physaddr, ulonglong unused)
> +ppc_translate_pte(ulong unused, void *physaddr, ulonglong pte)
This change may gives impacts for existing machdep->translate_pte() users
whose external modules are possible to call with legacy prototype
machdep->translate_pte(pte, physaddr, unused) for 32bit pte.
A "unused" should be used for extended 64bit pte support in addition to
first 32bit pte support.
I think it is better for everyone to mark machdep->flags with PAE at PATCH3/4.
Maybe PAE is named for x86 but there are no differences in terms of flag
handling.
Then declare ppc_translate_pte(ulong pte32, void *physaddr, ulonglong pte64)
so that ppc_pgd_vtop() can call with ppc_translate_pte((ulong)pte, NULL, pte)
and external users can also select similar way.
Thanks,
Toshi
> {
> int c, len1, len2, len3, others, page_present;
> char buf[BUFSIZE];
> @@ -632,7 +718,7 @@ ppc_translate_pte(ulong pte, void *physaddr, ulonglong unused)
> char ptebuf[BUFSIZE];
> char physbuf[BUFSIZE];
> char *arglist[MAXARGS];
> - ulong paddr;
> + ulonglong paddr;
>
> paddr = PAGEBASE(pte);
> page_present = (pte& _PAGE_PRESENT);
> @@ -642,7 +728,7 @@ ppc_translate_pte(ulong pte, void *physaddr, ulonglong unused)
> return page_present;
> }
>
> - sprintf(ptebuf, "%lx", pte);
> + sprintf(ptebuf, "%llx", pte);
> len1 = MAX(strlen(ptebuf), strlen("PTE"));
> fprintf(fp, "%s ", mkstring(buf, len1, CENTER|LJUST, "PTE"));
>
> @@ -668,7 +754,7 @@ ppc_translate_pte(ulong pte, void *physaddr, ulonglong unused)
> return page_present;
> }
>
> - sprintf(physbuf, "%lx", paddr);
> + sprintf(physbuf, "%llx", paddr);
> len2 = MAX(strlen(physbuf), strlen("PHYSICAL"));
> fprintf(fp, "%s ", mkstring(buf, len2, CENTER|LJUST, "PHYSICAL"));
>
> @@ -1509,6 +1595,7 @@ ppc_display_machine_stats(void)
> uts =&kt->utsname;
>
> fprintf(fp, " MACHINE TYPE: %s\n", uts->machine);
> + fprintf(fp, " PLATFORM: %s\n", PPC_PLATFORM);
> fprintf(fp, " MEMORY SIZE: %s\n", get_memory_size(buf));
> fprintf(fp, " CPUS: %d\n", kt->cpus);
> fprintf(fp, " PROCESSOR SPEED: ");
>
>
More information about the Crash-utility
mailing list