FAQ Search Today's Posts Mark Forums Read
» Video Reviews

» Linux Archive

Linux-archive is a website aiming to archive linux email lists and to make them easily accessible for linux users/developers.


» Sponsor

» Partners

» Sponsor

Go Back   Linux Archive > Redhat > Crash Utility

 
 
LinkBack Thread Tools
 
Old 02-02-2012, 07:45 AM
"Suzuki K. Poulose"
 
Default Support for platform based Virtual address translation

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 the PGDIRSHIT, PTRS_PER_PTE and the size of a
physical address.

I have not modified the size of the machdep->pgd allocation. Instead,
we always read a PAGESIZE() which contains the entry.

Signed-off-by: Suzuki K. Poulose <suzuki@in.ibm.com>
---

defs.h | 14 +++++++++--
ppc.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++------
2 files changed, 83 insertions(+), 11 deletions(-)

diff --git a/defs.h b/defs.h
index 82d51e5..aba13ea 100755
--- a/defs.h
+++ b/defs.h
@@ -2603,9 +2603,17 @@ struct load_module {
#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)
+/* Default values for PPC */
+#define DEFAULT_PGDIR_SHIFT (22)
+#define DEFAULT_PTRS_PER_PTE (1024)
+#define DEFAULT_PTRS_PER_PGD (1024)
+#define DEFAULT_PTE_SIZE sizeof(ulong)
+
+
+#define PGDIR_SHIFT (base_platform->pgdir_shift)
+#define PTRS_PER_PTE (base_platform->ptrs_per_pte)
+#define PTRS_PER_PGD (base_platform->ptrs_per_pgd)
+#define PTE_SIZE (base_platform->pte_size)

#define _PAGE_PRESENT 0x001 /* software: pte contains a translation */
#define _PAGE_USER 0x002 /* matches one of the PP bits */
diff --git a/ppc.c b/ppc.c
index cfa3f5f..600df34 100755
--- a/ppc.c
+++ b/ppc.c
@@ -67,10 +67,59 @@ static void ppc_display_machine_stats(void);
static void ppc_dump_line_number(ulong);
static struct line_number_hook ppc_line_number_hooks[];

+struct platform {
+ char *name;
+ int pgdir_shift;
+ int ptrs_per_pgd;
+ int ptrs_per_pte;
+ int pte_size;
+} ppc_boards[] = {
+ {
+ /* Always keep the default as the first entry */
+ .name = "default",
+ .pgdir_shift = DEFAULT_PGDIR_SHIFT,
+ .ptrs_per_pgd = DEFAULT_PTRS_PER_PGD,
+ .ptrs_per_pte = DEFAULT_PTRS_PER_PTE,
+ .pte_size = DEFAULT_PTE_SIZE,
+ },
+ {
+ /* Keep this at the end */
+ .name = NULL,
+ }
+};
+
+struct platform *base_platform;
+static struct platform *ppc_get_base_platform(void);
+
/* Defined in diskdump.c */
extern void process_elf32_notes(void *, ulong);

/*
+ * Find the platform of the crashing system and set the
+ * base_platform accordingly.
+ */
+struct platform*
+ppc_get_base_platform(void)
+{
+ char platform[32];
+ struct platform *tmp = &ppc_boards[1]; /* start at 1 */
+ ulong ppc_platform;
+
+ if(!try_get_symbol_data("powerpc_base_platform", sizeof(ulong), &ppc_platform))
+ return &ppc_boards[0];
+
+ if (read_string(ppc_platform, platform, 31) == 0)
+ return &ppc_boards[0];
+
+ for (; tmp->name!= NULL; tmp++)
+ if (!strcmp(tmp->name, platform))
+ return tmp;
+
+ /* Use default definitions */
+ return &ppc_boards[0];
+}
+
+/*
* Do all necessary machine-specific setup here. This is called twice,
* before and after GDB has been initialized.
*/
@@ -104,7 +153,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:
@@ -130,6 +178,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 */
+ base_platform = ppc_get_base_platform();
+
+ machdep->ptrs_per_pgd = PTRS_PER_PGD;
+
break;

case POST_GDB:
@@ -269,14 +322,21 @@ ppc_pgd_vtop(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
ulong *page_middle;
ulong *page_table;
ulong pgd_pte;
- ulong pte;
+ unsigned long long pte;

- if (verbose)
+ if (verbose) {
+ fprintf(fp, "Using %s board definitions:
", base_platform->name);
fprintf(fp, "PAGE DIRECTORY: %lx
", (ulong)pgd);
+ }

page_dir = pgd + (vaddr >> PGDIR_SHIFT);

- FILL_PGD(PAGEBASE(pgd), KVADDR, PAGESIZE());
+ /*
+ * 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(page_dir), KVADDR, PAGESIZE());
pgd_pte = ULONG(machdep->pgd + PAGEOFFSET(page_dir));

if (verbose)
@@ -288,10 +348,10 @@ 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)
@@ -299,10 +359,14 @@ ppc_pgd_vtop(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
(ulong)page_table);

FILL_PTBL(PAGEBASE(page_table), KVADDR, PAGESIZE());
- pte = ULONG(machdep->ptbl + PAGEOFFSET(page_table));
+ if (PTE_SIZE == sizeof(unsigned long long))
+ pte = ULONGLONG(machdep->ptbl + PAGEOFFSET(page_table));
+
+ else /* Defaults to ulong */
+ pte = ULONG(machdep->ptbl + PAGEOFFSET(page_table));

if (verbose)
- fprintf(fp, " PTE: %lx => %lx
", (ulong)page_table, pte);
+ fprintf(fp, " PTE: %lx => %llx
", (ulong)page_table, pte);

if (!(pte & _PAGE_PRESENT)) {
if (pte && verbose) {

--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
 
Old 02-03-2012, 04:16 AM
Toshikazu Nakayama
 
Default Support for platform based Virtual address translation

(2012/02/02 17:45), 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 the PGDIRSHIT, PTRS_PER_PTE and the size of a
> physical address.
>
> I have not modified the size of the machdep->pgd allocation. Instead,
> we always read a PAGESIZE() which contains the entry.

This way is very effectual in several angles, I like it
in addtion to your first integration work.

> Signed-off-by: Suzuki K. Poulose<suzuki@in.ibm.com>
> ---
>
> defs.h | 14 +++++++++--
> ppc.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++------
> 2 files changed, 83 insertions(+), 11 deletions(-)
>
> diff --git a/defs.h b/defs.h
> index 82d51e5..aba13ea 100755
> --- a/defs.h
> +++ b/defs.h
> @@ -2603,9 +2603,17 @@ struct load_module {
> #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)
> +/* Default values for PPC */
> +#define DEFAULT_PGDIR_SHIFT (22)
> +#define DEFAULT_PTRS_PER_PTE (1024)
> +#define DEFAULT_PTRS_PER_PGD (1024)
> +#define DEFAULT_PTE_SIZE sizeof(ulong)
> +
> +
> +#define PGDIR_SHIFT (base_platform->pgdir_shift)
> +#define PTRS_PER_PTE (base_platform->ptrs_per_pte)
> +#define PTRS_PER_PGD (base_platform->ptrs_per_pgd)
> +#define PTE_SIZE (base_platform->pte_size)
>
> #define _PAGE_PRESENT 0x001 /* software: pte contains a translation */
> #define _PAGE_USER 0x002 /* matches one of the PP bits */
> diff --git a/ppc.c b/ppc.c
> index cfa3f5f..600df34 100755
> --- a/ppc.c
> +++ b/ppc.c
> @@ -67,10 +67,59 @@ static void ppc_display_machine_stats(void);
> static void ppc_dump_line_number(ulong);
> static struct line_number_hook ppc_line_number_hooks[];
>
> +struct platform {
> + char *name;

const char *name is better?

> + int pgdir_shift;
> + int ptrs_per_pgd;
> + int ptrs_per_pte;
> + int pte_size;
> +} ppc_boards[] = {
> + {
> + /* Always keep the default as the first entry */
> + .name = "default",
> + .pgdir_shift = DEFAULT_PGDIR_SHIFT,
> + .ptrs_per_pgd = DEFAULT_PTRS_PER_PGD,
> + .ptrs_per_pte = DEFAULT_PTRS_PER_PTE,
> + .pte_size = DEFAULT_PTE_SIZE,
> + },
> + {
> + /* Keep this at the end */
> + .name = NULL,
> + }
> +};
> +
> +struct platform *base_platform;
> +static struct platform *ppc_get_base_platform(void);
> +
> /* Defined in diskdump.c */
> extern void process_elf32_notes(void *, ulong);
>
> /*
> + * Find the platform of the crashing system and set the
> + * base_platform accordingly.
> + */
> +struct platform*
> +ppc_get_base_platform(void)
> +{
> + char platform[32];
> + struct platform *tmp =&ppc_boards[1]; /* start at 1 */
> + ulong ppc_platform;
> +
> + if(!try_get_symbol_data("powerpc_base_platform", sizeof(ulong),&ppc_platform))
> + return&ppc_boards[0];
> +
> + if (read_string(ppc_platform, platform, 31) == 0)
> + return&ppc_boards[0];
> +
> + for (; tmp->name!= NULL; tmp++)
> + if (!strcmp(tmp->name, platform))
> + return tmp;

Is there any reasons to distinct "ppc440gp"?

Since I see that there are no "ppc440" prefix platform other than PPC40
in latest cpu_specs[], and all of ppc440gp's values in ppc_boards[] are the
same as ppc440.
Can it be summarized by using STRNEQ("ppc440") or strncmp("ppc440")?

And I often see similar comparisons as SRTEQ() in crash code,
also "unsigned long long" is "ulonglong".
Although I wonder whether they are unspoken rules or not,
I think it is better to use familiarity STREQ() and ulonglong.

Thanks,
Toshi

> +
> + /* Use default definitions */
> + return&ppc_boards[0];
> +}
> +
> +/*
> * Do all necessary machine-specific setup here. This is called twice,
> * before and after GDB has been initialized.
> */
> @@ -104,7 +153,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:
> @@ -130,6 +178,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 */
> + base_platform = ppc_get_base_platform();
> +
> + machdep->ptrs_per_pgd = PTRS_PER_PGD;
> +
> break;
>
> case POST_GDB:
> @@ -269,14 +322,21 @@ ppc_pgd_vtop(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
> ulong *page_middle;
> ulong *page_table;
> ulong pgd_pte;
> - ulong pte;
> + unsigned long long pte;
>
> - if (verbose)
> + if (verbose) {
> + fprintf(fp, "Using %s board definitions:
", base_platform->name);
> fprintf(fp, "PAGE DIRECTORY: %lx
", (ulong)pgd);
> + }
>
> page_dir = pgd + (vaddr>> PGDIR_SHIFT);
>
> - FILL_PGD(PAGEBASE(pgd), KVADDR, PAGESIZE());
> + /*
> + * 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(page_dir), KVADDR, PAGESIZE());
> pgd_pte = ULONG(machdep->pgd + PAGEOFFSET(page_dir));
>
> if (verbose)
> @@ -288,10 +348,10 @@ 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)
> @@ -299,10 +359,14 @@ ppc_pgd_vtop(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
> (ulong)page_table);
>
> FILL_PTBL(PAGEBASE(page_table), KVADDR, PAGESIZE());
> - pte = ULONG(machdep->ptbl + PAGEOFFSET(page_table));
> + if (PTE_SIZE == sizeof(unsigned long long))
> + pte = ULONGLONG(machdep->ptbl + PAGEOFFSET(page_table));
> +
> + else /* Defaults to ulong */
> + pte = ULONG(machdep->ptbl + PAGEOFFSET(page_table));
>
> if (verbose)
> - fprintf(fp, " PTE: %lx => %lx
", (ulong)page_table, pte);
> + fprintf(fp, " PTE: %lx => %llx
", (ulong)page_table, pte);
>
> if (!(pte& _PAGE_PRESENT)) {
> if (pte&& verbose) {
>
>

--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
 
Old 02-04-2012, 04:08 AM
"Suzuki K. Poulose"
 
Default Support for platform based Virtual address translation

Nakayama-San,

>> 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 the PGDIRSHIT, PTRS_PER_PTE and the size of a
>> physical address.
>>
>> I have not modified the size of the machdep->pgd allocation. Instead,
>> we always read a PAGESIZE() which contains the entry.
>
> This way is very effectual in several angles, I like it
> in addtion to your first integration work.
>
>> Signed-off-by: Suzuki K. Poulose<suzuki@in.ibm.com>

>> --- a/ppc.c
>> +++ b/ppc.c
>> @@ -67,10 +67,59 @@ static void ppc_display_machine_stats(void);
>> static void ppc_dump_line_number(ulong);
>> static struct line_number_hook ppc_line_number_hooks[];
>>
>> +struct platform {
>> + char *name;
>
> const char *name is better?
Yes, will do that.

>
>> + int pgdir_shift;
>> + int ptrs_per_pgd;
>> + int ptrs_per_pte;
>> + int pte_size;
>> +} ppc_boards[] = {
>> + {
>> + /* Always keep the default as the first entry */
>> + .name = "default",
>> + .pgdir_shift = DEFAULT_PGDIR_SHIFT,
>> + .ptrs_per_pgd = DEFAULT_PTRS_PER_PGD,
>> + .ptrs_per_pte = DEFAULT_PTRS_PER_PTE,
>> + .pte_size = DEFAULT_PTE_SIZE,
>> + },
>> + {
>> + /* Keep this at the end */
>> + .name = NULL,
>> + }
>> +};
>> +
>> +struct platform *base_platform;
>> +static struct platform *ppc_get_base_platform(void);
>> +
>> /* Defined in diskdump.c */
>> extern void process_elf32_notes(void *, ulong);
>>
>> /*
>> + * Find the platform of the crashing system and set the
>> + * base_platform accordingly.
>> + */
>> +struct platform*
>> +ppc_get_base_platform(void)
>> +{
>> + char platform[32];
>> + struct platform *tmp =&ppc_boards[1]; /* start at 1 */
>> + ulong ppc_platform;
>> +
>> + if(!try_get_symbol_data("powerpc_base_platform", sizeof(ulong),&ppc_platform))
>> + return&ppc_boards[0];
>> +
>> + if (read_string(ppc_platform, platform, 31) == 0)
>> + return&ppc_boards[0];
>> +
>> + for (; tmp->name!= NULL; tmp++)
>> + if (!strcmp(tmp->name, platform))
>> + return tmp;
>
> Is there any reasons to distinct "ppc440gp"?
>
No specific reasons, apart from just the name difference.

> Since I see that there are no "ppc440" prefix platform other than PPC40
> in latest cpu_specs[], and all of ppc440gp's values in ppc_boards[] are the
> same as ppc440.
> Can it be summarized by using STRNEQ("ppc440") or strncmp("ppc440")?
The problem is, this is generic code. And there could be a different platforms
which start with the same prefix and having different settings for the page
bits, (e.g, freescale processors). So generalizing this would be a problem.

One option I could think of is defining a function rather than a 'name' for each
platform to identify the 'running platform' as its variant.

i.e,

struct platform {
int (*check_platform) (char *s);
const char *name;
...
}

Where we could invoke the check_platform() for each platform, instead of
doing a check ourselves. The check_platform() could be implemented by each
distinct platforms and could use one board definition for multiple platform
values. This would also help us to reduce the 'platform' definitions as different
non-related platforms may also have the same set of definitions.

So the loop would look like :

for (; tmp->name!= NULL; tmp++)
if (tmpe->check_platform(platform))
return tmp;

What do you think about this approach ?

> And I often see similar comparisons as SRTEQ() in crash code,
> also "unsigned long long" is "ulonglong".
I will switch to ulonglong.

Thank you, for the review !

Suzuki

--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
 
Old 02-06-2012, 01:51 AM
Toshikazu Nakayama
 
Default Support for platform based Virtual address translation

Suzuki-San,

>>> + for (; tmp->name!= NULL; tmp++)
>>> + if (!strcmp(tmp->name, platform))
>>> + return tmp;
>>
>> Is there any reasons to distinct "ppc440gp"?
>>
> No specific reasons, apart from just the name difference.
>
>> Since I see that there are no "ppc440" prefix platform other than PPC40
>> in latest cpu_specs[], and all of ppc440gp's values in ppc_boards[] are the
>> same as ppc440.
>> Can it be summarized by using STRNEQ("ppc440") or strncmp("ppc440")?
> The problem is, this is generic code. And there could be a different platforms
> which start with the same prefix and having different settings for the page
> bits, (e.g, freescale processors). So generalizing this would be a problem.

I can understand your careful thought, thanks.

> One option I could think of is defining a function rather than a 'name' for each
> platform to identify the 'running platform' as its variant.
>
> i.e,
>
> struct platform {
> int (*check_platform) (char *s);
> const char *name;
> ...
> }
>
> Where we could invoke the check_platform() for each platform, instead of
> doing a check ourselves. The check_platform() could be implemented by each
> distinct platforms and could use one board definition for multiple platform
> values. This would also help us to reduce the 'platform' definitions as different
> non-related platforms may also have the same set of definitions.
>
> So the loop would look like :
>
> for (; tmp->name!= NULL; tmp++)
> if (tmpe->check_platform(platform))
> return tmp;
>
> What do you think about this approach ?

I can imagine that ppc_boards[] own least entries "default", "ppc440", "ppc??",
(or declare as "ibm", "freescale", ..)
and call check_ppc440_platform("platform"), check_ppc??_platform("platform")
to check or update page bits.

The check_ppc440_platform() can do with SRTEQ("platform", "ppc440(gp)") easily
but check_ppc??_platform() has to check more conditions if prefixed name
has different settings for the page bits.
Finaly check_platform sometimes update page talbe bit members in struct platform.

This is interesting so I wait for your updates
even though my imagination is different from yours.

Thanks,
Toshi

--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
 
Old 02-07-2012, 09:46 AM
"Suzuki K. Poulose"
 
Default Support for platform based Virtual address translation

On 02/06/2012 08:21 AM, Toshikazu Nakayama wrote:
> Suzuki-San,
>
>>>> + for (; tmp->name!= NULL; tmp++)
>>>> + if (!strcmp(tmp->name, platform))
>>>> + return tmp;
>>>
>>> Is there any reasons to distinct "ppc440gp"?
>>>
>> No specific reasons, apart from just the name difference.
>>
>>> Since I see that there are no "ppc440" prefix platform other than PPC40
>>> in latest cpu_specs[], and all of ppc440gp's values in ppc_boards[] are the
>>> same as ppc440.
>>> Can it be summarized by using STRNEQ("ppc440") or strncmp("ppc440")?
>> The problem is, this is generic code. And there could be a different platforms
>> which start with the same prefix and having different settings for the page
>> bits, (e.g, freescale processors). So generalizing this would be a problem.
>
> I can understand your careful thought, thanks.
>
>> One option I could think of is defining a function rather than a 'name' for each
>> platform to identify the 'running platform' as its variant.
>>
>> i.e,
>>
>> struct platform {
>> int (*check_platform) (char *s);
>> const char *name;
>> ...
>> }
>>
>> Where we could invoke the check_platform() for each platform, instead of
>> doing a check ourselves. The check_platform() could be implemented by each
>> distinct platforms and could use one board definition for multiple platform
>> values. This would also help us to reduce the 'platform' definitions as different
>> non-related platforms may also have the same set of definitions.
>>
>> So the loop would look like :
>>
>> for (; tmp->name!= NULL; tmp++)
>> if (tmpe->check_platform(platform))
>> return tmp;
>>
>> What do you think about this approach ?
>
> I can imagine that ppc_boards[] own least entries "default", "ppc440", "ppc??",
> (or declare as "ibm", "freescale", ..)
> and call check_ppc440_platform("platform"), check_ppc??_platform("platform")
> to check or update page bits.
>
> The check_ppc440_platform() can do with SRTEQ("platform", "ppc440(gp)") easily
> but check_ppc??_platform() has to check more conditions if prefixed name
> has different settings for the page bits.
> Finaly check_platform sometimes update page talbe bit members in struct platform.
>
> This is interesting so I wait for your updates
> even though my imagination is different from yours.

Sounds good. I will spin a new version with these changes.

Thanks
Suzuki

--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
 
Old 02-13-2012, 05:55 AM
"Suzuki K. Poulose"
 
Default Support for platform based Virtual address translation

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 and the size of a PTE.

The patch also adds support 64bit ptes.

Signed-off-by: Suzuki K. Poulose <suzuki@in.ibm.com>
---

defs.h | 14 ++++++++--
ppc.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++------
2 files changed, 96 insertions(+), 11 deletions(-)

diff --git a/defs.h b/defs.h
index a942dbb..603a583 100755
--- a/defs.h
+++ b/defs.h
@@ -2641,9 +2641,17 @@ struct load_module {
#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)
+/* Default values for PPC */
+#define DEFAULT_PGDIR_SHIFT (22)
+#define DEFAULT_PTRS_PER_PTE (1024)
+#define DEFAULT_PTRS_PER_PGD (1024)
+#define DEFAULT_PTE_SIZE sizeof(ulong)
+
+
+#define PGDIR_SHIFT (base_platform.pgdir_shift)
+#define PTRS_PER_PTE (base_platform.ptrs_per_pte)
+#define PTRS_PER_PGD (base_platform.ptrs_per_pgd)
+#define PTE_SIZE (base_platform.pte_size)

#define _PAGE_PRESENT 0x001 /* software: pte contains a translation */
#define _PAGE_USER 0x002 /* matches one of the PP bits */
diff --git a/ppc.c b/ppc.c
index 3834e7f..0e934ca 100755
--- a/ppc.c
+++ b/ppc.c
@@ -17,6 +17,21 @@
#ifdef PPC
#include "defs.h"

+
+#define MAX_PLATFORM_LEN 32 /* length for platform string */
+
+/*
+ * The following struct would hold the page translation information
+ * for the platform determined at runtime by ppc_probe_base_platform().
+ */
+struct platform {
+ char *name;
+ int pgdir_shift;
+ int ptrs_per_pgd;
+ int ptrs_per_pte;
+ int pte_size;
+} base_platform;
+
/*
* This structure was copied from kernel source
* in include/asm-ppc/ptrace.h
@@ -67,6 +82,53 @@ static void ppc_display_machine_stats(void);
static void ppc_dump_line_number(ulong);
static struct line_number_hook ppc_line_number_hooks[];

+static int probe_default_platform(char *, struct platform *);
+static void ppc_probe_base_platform(void);
+
+typedef int (*probe_func_t) (char *, struct platform *);
+
+probe_func_t probe_platforms[] = {
+ probe_default_platform, /* This should be at the end */
+ NULL
+};
+
+static int
+probe_default_platform(char *name, struct platform *p)
+{
+ /* Use the default definitions */
+ p->pgdir_shift = DEFAULT_PGDIR_SHIFT;
+ p->ptrs_per_pgd = DEFAULT_PTRS_PER_PGD;
+ p->ptrs_per_pte = DEFAULT_PTRS_PER_PTE;
+ p->pte_size = DEFAULT_PTE_SIZE;
+ p->name = strdup("default");
+
+ 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] = '';
+
+ for (i = 0; probe_platforms[i] != NULL; i++) {
+ probe = probe_platforms[i];
+ if (probe(platform_name, &base_platform))
+ break;
+ }
+}
+
/*
* Do all necessary machine-specific setup here. This is called twice,
* before and after GDB has been initialized.
@@ -101,7 +163,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 +188,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:
@@ -266,14 +332,21 @@ 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, "Using %s board definitions:
", base_platform.name);
fprintf(fp, "PAGE DIRECTORY: %lx
", (ulong)pgd);
+ }

page_dir = pgd + (vaddr >> PGDIR_SHIFT);

- FILL_PGD(PAGEBASE(pgd), KVADDR, PAGESIZE());
+ /*
+ * 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(page_dir), KVADDR, PAGESIZE());
pgd_pte = ULONG(machdep->pgd + PAGEOFFSET(page_dir));

if (verbose)
@@ -285,10 +358,10 @@ 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)
@@ -296,10 +369,14 @@ ppc_pgd_vtop(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
(ulong)page_table);

FILL_PTBL(PAGEBASE(page_table), KVADDR, PAGESIZE());
- pte = ULONG(machdep->ptbl + PAGEOFFSET(page_table));
+ if (PTE_SIZE == sizeof(ulonglong))
+ pte = ULONGLONG(machdep->ptbl + PAGEOFFSET(page_table));
+
+ else /* Defaults to ulong */
+ pte = ULONG(machdep->ptbl + PAGEOFFSET(page_table));

if (verbose)
- fprintf(fp, " PTE: %lx => %lx
", (ulong)page_table, pte);
+ fprintf(fp, " PTE: %lx => %llx
", (ulong)page_table, pte);

if (!(pte & _PAGE_PRESENT)) {
if (pte && verbose) {

--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
 
Old 02-20-2012, 10:06 AM
"Suzuki K. Poulose"
 
Default Support for platform based Virtual address translation

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@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] = '';
+
+ 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
", 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
", machdep->pageshift);
fprintf(fp, " pagemask: %llx
", machdep->pagemask);
fprintf(fp, " pageoffset: %lx
", machdep->pageoffset);
+ fprintf(fp, " pgdir_shift: %d
", PGDIR_SHIFT);
+ fprintf(fp, " ptrs_per_pgd: %d
", PTRS_PER_PGD);
+ fprintf(fp, " ptrs_per_pte: %d
", PTRS_PER_PTE);
+ fprintf(fp, " pte_size: %d
", PTE_SIZE);
fprintf(fp, " stacksize: %ld
", machdep->stacksize);
fprintf(fp, " hz: %d
", machdep->hz);
fprintf(fp, " mhz: %ld
", machdep->mhz);
@@ -252,7 +330,6 @@ ppc_dump_machdep_table(ulong arg)
fprintf(fp, " pgd: %lx
", (ulong)machdep->pgd);
fprintf(fp, " pmd: %lx
", (ulong)machdep->pmd);
fprintf(fp, " ptbl: %lx
", (ulong)machdep->ptbl);
- fprintf(fp, " ptrs_per_pgd: %d
", machdep->ptrs_per_pgd);
fprintf(fp, " section_size_bits: %ld
", machdep->section_size_bits);
fprintf(fp, " max_physmem_bits: %ld
", machdep->max_physmem_bits);
fprintf(fp, " sections_per_root: %ld
", 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
", (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
", (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
", (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
", (ulong)page_table, pte);
+ fprintf(fp, " PTE: %lx => %llx
", (ulong)page_table, pte);

if (!(pte & _PAGE_PRESENT)) {
if (pte && verbose) {
fprintf(fp, "
");
- ppc_translate_pte(pte, 0, 0);
+ ppc_translate_pte(0, 0, pte);
}
goto no_page;
}

if (verbose) {
- fprintf(fp, " PAGE: %lx

", PAGEBASE(pte));
- ppc_translate_pte(pte, 0, 0);
+ fprintf(fp, " PAGE: %llx

", 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)
{
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
", uts->machine);
+ fprintf(fp, " PLATFORM: %s
", PPC_PLATFORM);
fprintf(fp, " MEMORY SIZE: %s
", get_memory_size(buf));
fprintf(fp, " CPUS: %d
", kt->cpus);
fprintf(fp, " PROCESSOR SPEED: ");

--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
 
Old 02-21-2012, 12:31 AM
Toshikazu Nakayama
 
Default Support for platform based Virtual address translation

(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@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] = '';

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
", 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
", machdep->pageshift);
> fprintf(fp, " pagemask: %llx
", machdep->pagemask);
> fprintf(fp, " pageoffset: %lx
", machdep->pageoffset);
> + fprintf(fp, " pgdir_shift: %d
", PGDIR_SHIFT);
> + fprintf(fp, " ptrs_per_pgd: %d
", PTRS_PER_PGD);
> + fprintf(fp, " ptrs_per_pte: %d
", PTRS_PER_PTE);
> + fprintf(fp, " pte_size: %d
", PTE_SIZE);
> fprintf(fp, " stacksize: %ld
", machdep->stacksize);
> fprintf(fp, " hz: %d
", machdep->hz);
> fprintf(fp, " mhz: %ld
", machdep->mhz);
> @@ -252,7 +330,6 @@ ppc_dump_machdep_table(ulong arg)
> fprintf(fp, " pgd: %lx
", (ulong)machdep->pgd);
> fprintf(fp, " pmd: %lx
", (ulong)machdep->pmd);
> fprintf(fp, " ptbl: %lx
", (ulong)machdep->ptbl);
> - fprintf(fp, " ptrs_per_pgd: %d
", machdep->ptrs_per_pgd);
> fprintf(fp, " section_size_bits: %ld
", machdep->section_size_bits);
> fprintf(fp, " max_physmem_bits: %ld
", machdep->max_physmem_bits);
> fprintf(fp, " sections_per_root: %ld
", 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
", (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
", (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
", (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
", (ulong)page_table, pte);
> + fprintf(fp, " PTE: %lx => %llx
", (ulong)page_table, pte);
>
> if (!(pte& _PAGE_PRESENT)) {
> if (pte&& verbose) {
> fprintf(fp, "
");
> - ppc_translate_pte(pte, 0, 0);
> + ppc_translate_pte(0, 0, pte);
> }
> goto no_page;
> }
>
> if (verbose) {
> - fprintf(fp, " PAGE: %lx

", PAGEBASE(pte));
> - ppc_translate_pte(pte, 0, 0);
> + fprintf(fp, " PAGE: %llx

", 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
", uts->machine);
> + fprintf(fp, " PLATFORM: %s
", PPC_PLATFORM);
> fprintf(fp, " MEMORY SIZE: %s
", get_memory_size(buf));
> fprintf(fp, " CPUS: %d
", kt->cpus);
> fprintf(fp, " PROCESSOR SPEED: ");
>
>

--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
 
Old 02-21-2012, 05:14 AM
"Suzuki K. Poulose"
 
Default Support for platform based Virtual address translation

On 02/21/2012 07:01 AM, Toshikazu Nakayama wrote:
> (2012/02/20 20:06), Suzuki K. Poulose wrote:
[...]
>> + * 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] = '';
>
> Could you give some fallback message at PLATFORM: via 'mach' command
> like "undetectable" or any good phrase?

Yep, makes sense. I will make it '(unknown)'.


>>
>> *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.

Makes sense. I will respin this with the changes. Thank you very much for the
suggestions.

Suzuki

--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
 
Old 02-21-2012, 11:19 AM
"Suzuki K. Poulose"
 
Default Support for platform based Virtual address translation

Here is the updated version with the following changes :

* ppc_translate_pte(ulong pte32, void *physaddr, ulonglong pte64);
* Updates the machdep->flags with PAE flag to indicate we have a 64bit
PTE.
* Sets the platform string to '(unknown)' if we are unable to read the
string from the kernel.


---
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@in.ibm.com>
---

defs.h | 82 +++++++++++++++++++++++++++------
ppc.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++++++ +-------------
2 files changed, 192 insertions(+), 49 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..64fa4db 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 */
+ strcpy(platform_name, "(unknown)");
+
+ 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,14 @@ 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;
+ /* Check if we have 64bit PTE on 32bit system */
+ if (PTE_SIZE == sizeof(ulonglong))
+ machdep->flags |= PAE;
+
break;

case POST_GDB:
@@ -201,6 +277,7 @@ ppc_dump_machdep_table(ulong arg)
int others;

others = 0;
+ fprintf(fp, " platform: %s
", PPC_PLATFORM);
fprintf(fp, " flags: %lx (", machdep->flags);
if (machdep->flags & KSYMS_START)
fprintf(fp, "%sKSYMS_START", others++ ? "|" : "");
@@ -212,6 +289,10 @@ ppc_dump_machdep_table(ulong arg)
fprintf(fp, " pageshift: %d
", machdep->pageshift);
fprintf(fp, " pagemask: %llx
", machdep->pagemask);
fprintf(fp, " pageoffset: %lx
", machdep->pageoffset);
+ fprintf(fp, " pgdir_shift: %d
", PGDIR_SHIFT);
+ fprintf(fp, " ptrs_per_pgd: %d
", PTRS_PER_PGD);
+ fprintf(fp, " ptrs_per_pte: %d
", PTRS_PER_PTE);
+ fprintf(fp, " pte_size: %d
", PTE_SIZE);
fprintf(fp, " stacksize: %ld
", machdep->stacksize);
fprintf(fp, " hz: %d
", machdep->hz);
fprintf(fp, " mhz: %ld
", machdep->mhz);
@@ -252,7 +333,6 @@ ppc_dump_machdep_table(ulong arg)
fprintf(fp, " pgd: %lx
", (ulong)machdep->pgd);
fprintf(fp, " pmd: %lx
", (ulong)machdep->pmd);
fprintf(fp, " ptbl: %lx
", (ulong)machdep->ptbl);
- fprintf(fp, " ptrs_per_pgd: %d
", machdep->ptrs_per_pgd);
fprintf(fp, " section_size_bits: %ld
", machdep->section_size_bits);
fprintf(fp, " max_physmem_bits: %ld
", machdep->max_physmem_bits);
fprintf(fp, " sections_per_root: %ld
", machdep->sections_per_root);
@@ -266,15 +346,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
", (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
", (ulong)page_dir, pgd_pte);
@@ -285,33 +370,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
", (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
", (ulong)page_table, pte);
+ fprintf(fp, " PTE: %lx => %llx
", (ulong)page_table, pte);

if (!(pte & _PAGE_PRESENT)) {
if (pte && verbose) {
fprintf(fp, "
");
- ppc_translate_pte(pte, 0, 0);
+ ppc_translate_pte((ulong)pte, 0, pte);
}
goto no_page;
}

if (verbose) {
- fprintf(fp, " PAGE: %lx

", PAGEBASE(pte));
- ppc_translate_pte(pte, 0, 0);
+ fprintf(fp, " PAGE: %llx

", PAGEBASE(pte));
+ ppc_translate_pte((ulong)pte, 0, pte);
}

*paddr = PAGEBASE(pte) + PAGEOFFSET(vaddr);
@@ -623,7 +712,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 pte32, void *physaddr, ulonglong pte64)
{
int c, len1, len2, len3, others, page_present;
char buf[BUFSIZE];
@@ -632,22 +721,25 @@ ppc_translate_pte(ulong pte, void *physaddr, ulonglong unused)
char ptebuf[BUFSIZE];
char physbuf[BUFSIZE];
char *arglist[MAXARGS];
- ulong paddr;
+ ulonglong paddr;
+
+ if (!(machdep->flags & PAE))
+ pte64 = pte32;

- paddr = PAGEBASE(pte);
- page_present = (pte & _PAGE_PRESENT);
+ paddr = PAGEBASE(pte64);
+ page_present = (pte64 & _PAGE_PRESENT);

if (physaddr) {
*((ulong *)physaddr) = paddr;
return page_present;
}

- sprintf(ptebuf, "%lx", pte);
+ sprintf(ptebuf, "%llx", pte64);
len1 = MAX(strlen(ptebuf), strlen("PTE"));
fprintf(fp, "%s ", mkstring(buf, len1, CENTER|LJUST, "PTE"));

- if (!page_present && pte) {
- swap_location(pte, buf);
+ if (!page_present && pte64) {
+ swap_location(pte64, buf);
if ((c = parse_line(buf, arglist)) != 3)
error(FATAL, "cannot determine swap location
");

@@ -668,7 +760,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"));

@@ -680,26 +772,26 @@ ppc_translate_pte(ulong pte, void *physaddr, ulonglong unused)
fprintf(fp, "(");
others = 0;

- if (pte) {
- if (pte & _PAGE_PRESENT)
+ if (pte64) {
+ if (pte64 & _PAGE_PRESENT)
fprintf(fp, "%sPRESENT", others++ ? "|" : "");
- if (pte & _PAGE_USER)
+ if (pte64 & _PAGE_USER)
fprintf(fp, "%sUSER", others++ ? "|" : "");
- if (pte & _PAGE_RW)
+ if (pte64 & _PAGE_RW)
fprintf(fp, "%sRW", others++ ? "|" : "");
- if (pte & _PAGE_GUARDED)
+ if (pte64 & _PAGE_GUARDED)
fprintf(fp, "%sGUARDED", others++ ? "|" : "");
- if (pte & _PAGE_COHERENT)
+ if (pte64 & _PAGE_COHERENT)
fprintf(fp, "%sCOHERENT", others++ ? "|" : "");
- if (pte & _PAGE_NO_CACHE)
+ if (pte64 & _PAGE_NO_CACHE)
fprintf(fp, "%sNO_CACHE", others++ ? "|" : "");
- if (pte & _PAGE_WRITETHRU)
+ if (pte64 & _PAGE_WRITETHRU)
fprintf(fp, "%sWRITETHRU", others++ ? "|" : "");
- if (pte & _PAGE_DIRTY)
+ if (pte64 & _PAGE_DIRTY)
fprintf(fp, "%sDIRTY", others++ ? "|" : "");
- if (pte & _PAGE_ACCESSED)
+ if (pte64 & _PAGE_ACCESSED)
fprintf(fp, "%sACCESSED", others++ ? "|" : "");
- if (pte & _PAGE_HWWRITE)
+ if (pte64 & _PAGE_HWWRITE)
fprintf(fp, "%sHWWRITE", others++ ? "|" : "");
} else
fprintf(fp, "no mapping");
@@ -1509,6 +1601,7 @@ ppc_display_machine_stats(void)
uts = &kt->utsname;

fprintf(fp, " MACHINE TYPE: %s
", uts->machine);
+ fprintf(fp, " PLATFORM: %s
", PPC_PLATFORM);
fprintf(fp, " MEMORY SIZE: %s
", get_memory_size(buf));
fprintf(fp, " CPUS: %d
", kt->cpus);
fprintf(fp, " PROCESSOR SPEED: ");

--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
 

Thread Tools




All times are GMT. The time now is 05:06 PM.

VBulletin, Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO ©2007, Crawlability, Inc.
Copyright 2007 - 2008, www.linux-archive.org