On 08/01/06 14:10, Dave Anderson wrote: > The only issues I see is that the read_config() and read_config_err() > should probably go into a common file in case we ever need them for > other configuration-related stuff in the future. OK, I'll let you decide where they should land, I try not to venture to far out of the arch specific areas :-). > and couple of the malloc() error messages in read_config() are > cut-and-pasted and refer to "ia64_memmap". Doah.. OK, I have attached a fixed version. I have also dome some extra housekeeping in the read_config function. > I'll give it a run against a 3 leveler to make sure nothing breaks. Excellent. I tested it on both so everything should be fine. Thanks! Troy
diff -urpN -urN -X /root/dontdiff orig/defs.h crash-4.0-2.33/defs.h --- orig/defs.h 2006-07-13 12:51:50.000000000 -0600 +++ crash-4.0-2.33/defs.h 2006-08-01 09:04:01.000000000 -0600 @@ -701,9 +701,11 @@ struct machdep_table { char **file; } *line_number_hooks; ulong last_pgd_read; + ulong last_pud_read; ulong last_pmd_read; ulong last_ptbl_read; char *pgd; + char *pud; char *pmd; char *ptbl; int ptrs_per_pgd; @@ -717,6 +719,7 @@ struct machdep_table { void (*get_xendump_regs)(struct xendump_data *, struct bt_info *, ulong *, ulong *); void (*clear_machdep_cache)(void); int (*xen_kdump_p2m_create)(struct xen_kdump_data *); + int nr_cpus; }; /* @@ -735,6 +738,7 @@ extern struct machdep_table *machdep; #define IS_LAST_PGD_READ(pgd) ((ulong)(pgd) == machdep->last_pgd_read) #define IS_LAST_PMD_READ(pmd) ((ulong)(pmd) == machdep->last_pmd_read) #define IS_LAST_PTBL_READ(ptbl) ((ulong)(ptbl) == machdep->last_ptbl_read) +#define IS_LAST_PUD_READ(pud) ((ulong)(pud) == machdep->last_pud_read) #define FILL_PGD(PGD, TYPE, SIZE) \ if (!IS_LAST_PGD_READ(PGD)) { \ @@ -743,6 +747,13 @@ extern struct machdep_table *machdep; machdep->last_pgd_read = (ulong)(PGD); \ } +#define FILL_PUD(PUD, TYPE, SIZE) \ + if (!IS_LAST_PUD_READ(PUD)) { \ + readmem((ulonglong)((ulong)(PUD)), TYPE, machdep->pud, \ + SIZE, "pud page", FAULT_ON_ERROR); \ + machdep->last_pud_read = (ulong)(PUD); \ + } + #define FILL_PMD(PMD, TYPE, SIZE) \ if (!IS_LAST_PMD_READ(PMD)) { \ readmem((ulonglong)(PMD), TYPE, machdep->pmd, \ @@ -2117,16 +2128,57 @@ struct load_module { #define SWITCH_STACK_ADDR(X) (ia64_get_switch_stack((ulong)(X))) -#define PGDIR_SHIFT (PAGESHIFT() + 2*(PAGESHIFT()-3)) -#define PMD_SHIFT (PAGESHIFT() + (PAGESHIFT()-3)) -#define PTRS_PER_PGD (((ulong)(1)) << (PAGESHIFT()-3)) -#define PTRS_PER_PMD (((ulong)(1)) << (PAGESHIFT()-3)) -#define PTRS_PER_PTE (((ulong)(1)) << (PAGESHIFT()-3)) -#define PTRS_PER_PAGE (((ulong)(1)) << (PAGESHIFT()-3)) #define __IA64_UL(x) ((unsigned long)(x)) #define IA64_MAX_PHYS_BITS (50) /* max # of phys address bits (architected) */ /* + * How many pointers will a page table level hold expressed in shift + */ +#define PTRS_PER_PTD_SHIFT (PAGESHIFT()-3) + +/* + * Definitions for fourth level: + */ +#define PTRS_PER_PTE (__IA64_UL(1) << (PTRS_PER_PTD_SHIFT)) + +/* + * Definitions for third level: + * + * PMD_SHIFT determines the size of the area a third-level page table + * can map. + */ +#define PMD_SHIFT (PAGESHIFT() + (PTRS_PER_PTD_SHIFT)) +#define PMD_SIZE (1UL << PMD_SHIFT) +#define PMD_MASK (~(PMD_SIZE-1)) +#define PTRS_PER_PMD (1UL << (PTRS_PER_PTD_SHIFT)) + +/* + * PUD_SHIFT determines the size of the area a second-level page table + * can map + */ +#define PUD_SHIFT (PMD_SHIFT + (PTRS_PER_PTD_SHIFT)) +#define PUD_SIZE (1UL << PUD_SHIFT) +#define PUD_MASK (~(PUD_SIZE-1)) +#define PTRS_PER_PUD (1UL << (PTRS_PER_PTD_SHIFT)) + +/* + * Definitions for first level: + * + * PGDIR_SHIFT determines what a first-level page table entry can map. + */ + +#define PGDIR_SHIFT_4L (PUD_SHIFT + (PTRS_PER_PTD_SHIFT)) +#define PGDIR_SHIFT_3L (PMD_SHIFT + (PTRS_PER_PTD_SHIFT)) +/* Turns out 4L & 3L PGDIR_SHIFT are the same (for now) */ +#define PGDIR_SHIFT PGDIR_SHIFT_4L +#define PGDIR_SIZE (__IA64_UL(1) << PGDIR_SHIFT) +#define PGDIR_MASK (~(PGDIR_SIZE-1)) +#define PTRS_PER_PGD_SHIFT PTRS_PER_PTD_SHIFT +#define PTRS_PER_PGD (1UL << PTRS_PER_PGD_SHIFT) +#define USER_PTRS_PER_PGD (5*PTRS_PER_PGD/8) /* regions 0-4 are user regions */ +#define FIRST_USER_ADDRESS 0 + +/* * First, define the various bits in a PTE. Note that the PTE format * matches the VHPT short format, the firt doubleword of the VHPD long * format, and the first doubleword of the TLB insertion format. @@ -2178,6 +2230,9 @@ struct load_module { #define __DIRTY_BITS _PAGE_ED | __DIRTY_BITS_NO_ED #define EFI_PAGE_SHIFT (12) + +#define VM_4_LEVEL (0x4) + /* * NOTE: #include'ing <asm/efi.h> creates too many compiler problems, so * this stuff is hardwired here; it's probably etched in stone somewhere. @@ -3588,6 +3643,12 @@ int ia64_in_init_stack(ulong addr); #define IA64_RBS_OFFSET ((SIZE(task_struct) + 15) & ~15) #define IA64_STK_OFFSET (STACKSIZE()) +#define MAGIC_START "IKCFG_ST" +#define MAGIC_END "IKCFG_ED" +#define MAGIC_SIZE (sizeof(MAGIC_START) - 1) +#define LIST_SIZE 2 + + struct machine_specific { ulong cpu_data_address; ulong unimpl_va_mask; diff -urpN -urN -X /root/dontdiff orig/ia64.c crash-4.0-2.33/ia64.c --- orig/ia64.c 2006-07-13 12:51:50.000000000 -0600 +++ crash-4.0-2.33/ia64.c 2006-08-01 12:44:24.000000000 -0600 @@ -25,6 +25,8 @@ static void ia64_old_unwind_init(void); static void try_old_unwind(struct bt_info *); static void ia64_dump_irq(int); static ulong ia64_processor_speed(void); +static int ia64_vtop_4l(ulong vaddr, physaddr_t *paddr, ulong *pgd, int verbose, int usr); +static int ia64_vtop(ulong vaddr, physaddr_t *paddr, ulong *pgd, int verbose, int usr); static int ia64_uvtop(struct task_context *, ulong, physaddr_t *, int); static int ia64_kvtop(struct task_context *, ulong, physaddr_t *, int); static ulong ia64_get_task_pgd(ulong); @@ -63,6 +65,9 @@ static ulong rse_read_reg(struct unw_fra static void rse_function_params(struct unw_frame_info *, char *); +static void read_config(void); +static void read_config_err(int e, char *msg); + struct machine_specific ia64_machine_specific = { 0 }; void @@ -101,11 +106,14 @@ ia64_init(int when) } if ((machdep->pgd = (char *)malloc(PAGESIZE())) == NULL) error(FATAL, "cannot malloc pgd space."); + if ((machdep->pud = (char *)malloc(PAGESIZE())) == NULL) + error(FATAL, "cannot malloc pud space."); if ((machdep->pmd = (char *)malloc(PAGESIZE())) == NULL) error(FATAL, "cannot malloc pmd space."); if ((machdep->ptbl = (char *)malloc(PAGESIZE())) == NULL) error(FATAL, "cannot malloc ptbl space."); machdep->last_pgd_read = 0; + machdep->last_pud_read = 0; machdep->last_pmd_read = 0; machdep->last_ptbl_read = 0; machdep->verify_paddr = ia64_verify_paddr; @@ -118,14 +126,17 @@ ia64_init(int when) break; case PRE_GDB: + if (pc->flags & KERNEL_DEBUG_QUERY) return; + /* * Until the kernel core dump and va_server library code * do the right thing with respect to the configured page size, * try to recognize a fatal inequity between the compiled-in * page size and the page size used by the kernel. */ + if ((sp = symbol_search("empty_zero_page")) && (spn = next_symbol(NULL, sp)) && @@ -179,6 +190,7 @@ ia64_init(int when) break; case POST_GDB: + read_config(); STRUCT_SIZE_INIT(cpuinfo_ia64, "cpuinfo_ia64"); STRUCT_SIZE_INIT(switch_stack, "switch_stack"); MEMBER_OFFSET_INIT(thread_struct_fph, "thread_struct", "fph"); @@ -215,6 +227,237 @@ ia64_init(int when) } } +void +read_config_err(int e, char *msg) +{ + error(WARNING, "zlib could not %s\n", msg); + switch (e) { + case Z_OK: + fprintf(fp, "Z_OK\n"); + break; + + case Z_STREAM_END: + fprintf(fp, "Z_STREAM_END\n"); + break; + + case Z_NEED_DICT: + fprintf(fp, "Z_NEED_DICT\n"); + break; + + case Z_ERRNO: + fprintf(fp, "Z_ERNO\n"); + break; + + case Z_STREAM_ERROR: + fprintf(fp, "Z_STREAM\n"); + break; + + case Z_DATA_ERROR: + fprintf(fp, "Z_DATA_ERROR\n"); + break; + + case Z_MEM_ERROR: /* out of memory */ + fprintf(fp, "Z_MEM_ERROR\n"); + break; + + case Z_BUF_ERROR: /* not enough room in output buf */ + fprintf(fp, "Z_BUF_ERROR\n"); + break; + + case Z_VERSION_ERROR: + fprintf(fp, "Z_VERSION_ERROR\n"); + break; + + default: + fprintf(fp, "UNKNOWN ERROR: %d\n", e); + break; + } +} + +void +read_config(void) +{ + struct syment *sp; + ulong kr; + int ii, jj, ret, end, found=0; + unsigned long size, bufsz; + char *pos, *ln, *buf, *head, *tail, *val, *uncomp; + char line[512]; + z_stream stream; + + if (!symbol_exists("kernel_config_data")) + return; + + if ((sp = symbol_search("kernel_config_data")) != NULL) + kr = sp->value; + else + return; + + error(NOTE, "Using IKCONFIG (In Kernel Config)\n"); + + /* we don't know how large IKCONFIG is, so we start with + * 32k, if we can't find MAGIC_END assume we didn't read + * enough, double it and try again + */ + ii = 32; + +again: + size = ii * 1024; + + if ((buf = (char *)malloc(size)) == NULL){ + error(WARNING, "cannot malloc IKCONFIG input buffer\n"); + return; + } + + readmem(kr, KVADDR, buf, size, + "kernel_config_data", RETURN_ON_ERROR); + + /* Find the start */ + if (strstr(buf, MAGIC_START)) + head = buf + MAGIC_SIZE + 10; /* skip past MAGIC_START and gzip header */ + else{ + error(WARNING, "could not find MAGIC_START!\n"); + goto out2; + } + + tail = head; + + end = strlen(MAGIC_END); + + /* Find the end*/ + while(tail < (buf + (size - 1))){ + + if (strncmp(tail, MAGIC_END, end)==0){ + found = 1; + break; + } + tail++; + } + + if (found){ + bufsz = tail - head; + size = 10 * bufsz; + if ((uncomp = (char *)malloc(size)) == NULL){ + error(WARNING, "cannot malloc IKCONFIG output buffer\n"); + goto out2; + } + } else { + if (ii > 512){ + error(WARNING, "could not find MAGIC_END!\n"); + goto out2; + } else { + free(buf); + ii *= 2; + goto again; + } + } + + + /* initialize zlib */ + stream.next_in = (Bytef*)head; + stream.avail_in = (uInt) bufsz; + + stream.next_out = uncomp; + stream.avail_out = (uInt) size; + + stream.zalloc = NULL; + stream.zfree = NULL; + stream.opaque = NULL; + + ret = inflateInit2(&stream, -MAX_WBITS); + if (ret != Z_OK){ + read_config_err(ret, "initialize"); + goto out1; + } + + ret = inflate(&stream, Z_FINISH); + + if (ret != Z_STREAM_END) { + inflateEnd(&stream); + if (ret == Z_NEED_DICT || + (ret == Z_BUF_ERROR && stream.avail_in == 0)){ + read_config_err(Z_DATA_ERROR, "uncompress"); + goto out1; + } + read_config_err(ret, "uncompress"); + goto out1; + } + size = stream.total_out; + + ret = inflateEnd(&stream); + + pos = uncomp; + + do{ + ret = sscanf(pos, "%511[^\n]\n%n", line, &ii); + if (ret > 0){ + pos += ii; + + ln = line; + + /* skip leading whitespace */ + while(isblank(*ln)) + ln++; + + /* skip comments */ + if (*ln == '#') + continue; + + /* Find '=' */ + if ((head = strchr(ln, '=')) != NULL){ + *head = '\0'; + val = head + 1; + + head--; + + /* skip trailing whitespace */ + while(isblank(*head)){ + *head = '\0'; + head--; + } + + /* skip whitespace */ + while(isblank(*val)) + val++; + + } else /* Bad line, skip it */ + continue; + + for (jj=0; jj < LIST_SIZE; jj++){ + /* keep the parse list here to make it obvious */ + char *parse[LIST_SIZE] = {"CONFIG_NR_CPUS", + "CONFIG_PGTABLE_4" + }; + + if (strcmp(ln, parse[jj])==0){ + switch (jj) + { + /* FIXME: nr_cpus currently + * unused, it would be nice to + * use the real config value + */ + case 0: /* CONFIG_NR_CPUS */ + machdep->nr_cpus = atoi(val); + break; + case 1: /* CONFIG_PGTABLE_4 */ + machdep->flags |= VM_4_LEVEL; + break; + } + } + } + + } + + } while (ret > 0); + +out1: + free(uncomp); +out2: + free(buf); + return; + +} + /* * --machdep <addr> defaults to the physical start location. * @@ -287,11 +530,34 @@ parse_cmdline_arg(void) continue; } } + } else if (STRNEQ(arglist[i], "vm=")) { + p = arglist[i] + strlen("vm="); + if (strlen(p)) { + if (STREQ(p, "4l")) { + machdep->flags |= VM_4_LEVEL; + continue; + } + } } error(WARNING, "ignoring --machdep option: %s\n", arglist[i]); } + switch (machdep->flags & (VM_4_LEVEL)) + { + case VM_4_LEVEL: + error(NOTE, "using 4-level pagetable\n"); + c++; + break; + + default: + error(WARNING, "Invalid vm= option\n"); + c++; + machdep->flags &= ~(VM_4_LEVEL); + break; + } + + if (c) fprintf(fp, "\n"); } @@ -451,6 +717,7 @@ ia64_dump_machdep_table(ulong arg) fprintf(fp, " value_to_symbol: generic_machdep_value_to_symbol()\n"); fprintf(fp, " line_number_hooks: ia64_line_number_hooks\n"); fprintf(fp, " last_pgd_read: %lx\n", machdep->last_pgd_read); + fprintf(fp, " last_pud_read: %lx\n", machdep->last_pud_read); fprintf(fp, " last_pmd_read: %lx\n", machdep->last_pmd_read); fprintf(fp, " last_ptbl_read: %lx\n", machdep->last_ptbl_read); fprintf(fp, " pgd: %lx\n", (ulong)machdep->pgd); @@ -667,75 +934,152 @@ ia64_processor_speed(void) return (machdep->mhz = mhz); } - - -/* - * Translates a user virtual address to its physical address. cmd_vtop() - * sets the verbose flag so that the pte translation gets displayed; all - * other callers quietly accept the translation. - * - * This routine can also take mapped kernel virtual addresses if the -u flag - * was passed to cmd_vtop(). If so, it makes the translation using the - * swapper_pg_dir, making it irrelevant in this processor's case. +/* Generic abstraction to translate user or kernel virtual + * addresses to physical using a 4 level page table. */ static int -ia64_uvtop(struct task_context *tc, ulong uvaddr, physaddr_t *paddr, int verbose) +ia64_vtop_4l(ulong vaddr, physaddr_t *paddr, ulong *pgd, int verbose, int usr) { - ulong mm; - ulong *pgd; ulong *page_dir; + ulong *page_upper; ulong *page_middle; ulong *page_table; ulong pgd_pte; + ulong pud_pte; ulong pmd_pte; ulong pte; ulong region, offset; - if (!tc) - error(FATAL, "current context invalid\n"); - - *paddr = 0; - region = VADDR_REGION(uvaddr); + if(usr){ + region = VADDR_REGION(vaddr); + offset = (vaddr >> PGDIR_SHIFT) & ((PTRS_PER_PGD >> 3) - 1); + offset |= (region << (PAGESHIFT() - 6)); + page_dir = pgd + offset; + }else{ + pgd = (ulong *)vt->kernel_pgd[0]; + page_dir = pgd + ((vaddr >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)); + } - if (IS_KVADDR(uvaddr)) - return ia64_kvtop(tc, uvaddr, paddr, verbose); + if (verbose) + fprintf(fp, "PAGE DIRECTORY: %lx\n", (ulong)pgd); - if ((mm = task_mm(tc->task, TRUE))) - pgd = ULONG_PTR(tt->mm_struct + OFFSET(mm_struct_pgd)); - else - readmem(tc->mm_struct + OFFSET(mm_struct_pgd), KVADDR, &pgd, - sizeof(long), "mm_struct pgd", FAULT_ON_ERROR); + FILL_PGD(PAGEBASE(pgd), KVADDR, PAGESIZE()); + pgd_pte = ULONG(machdep->pgd + PAGEOFFSET(page_dir)); + + if (verbose) + fprintf(fp, " PGD: %lx => %lx\n", (ulong)page_dir, pgd_pte); + if (!(pgd_pte)) + return FALSE; + + offset = (vaddr >> PUD_SHIFT) & (PTRS_PER_PUD - 1); + page_upper = (ulong *)(PTOV(pgd_pte & _PFN_MASK)) + offset; + + FILL_PUD(PAGEBASE(page_upper), KVADDR, PAGESIZE()); + pud_pte = ULONG(machdep->pud + PAGEOFFSET(page_upper)); + if (verbose) + fprintf(fp, " PUD: %lx => %lx\n", (ulong)page_upper, pud_pte); + + if (!(pud_pte)) + return FALSE; + + offset = (vaddr >> PMD_SHIFT) & (PTRS_PER_PMD - 1); + page_middle = (ulong *)(PTOV(pud_pte & _PFN_MASK)) + offset; + + FILL_PMD(PAGEBASE(page_middle), KVADDR, PAGESIZE()); + pmd_pte = ULONG(machdep->pmd + PAGEOFFSET(page_middle)); + + if (verbose) + fprintf(fp, " PMD: %lx => %lx\n", (ulong)page_middle, pmd_pte); + + if (!(pmd_pte)) + return FALSE; + + offset = (vaddr >> PAGESHIFT()) & (PTRS_PER_PTE - 1); + page_table = (ulong *)(PTOV(pmd_pte & _PFN_MASK)) + offset; + + FILL_PTBL(PAGEBASE(page_table), KVADDR, PAGESIZE()); + pte = ULONG(machdep->ptbl + PAGEOFFSET(page_table)); + + if (verbose) + fprintf(fp, " PTE: %lx => %lx\n", (ulong)page_table, pte); + + if (!(pte & (_PAGE_P))) { + if(usr) + *paddr = pte; + if (pte && verbose) { + fprintf(fp, "\n"); + ia64_translate_pte(pte, 0, 0); + } + return FALSE; + } + + *paddr = (pte & _PFN_MASK) + PAGEOFFSET(vaddr); + + if (verbose) { + fprintf(fp, " PAGE: %lx\n\n", PAGEBASE(*paddr)); + ia64_translate_pte(pte, 0, 0); + } + + return TRUE; + + + +} + +/* Generic abstraction to translate user or kernel virtual + * addresses to physical using a 3 level page table. + */ +static int +ia64_vtop(ulong vaddr, physaddr_t *paddr, ulong *pgd, int verbose, int usr) +{ + ulong *page_dir; + ulong *page_middle; + ulong *page_table; + ulong pgd_pte; + ulong pmd_pte; + ulong pte; + ulong region, offset; + + if(usr){ + region = VADDR_REGION(vaddr); + offset = (vaddr >> PGDIR_SHIFT) & ((PTRS_PER_PGD >> 3) - 1); + offset |= (region << (PAGESHIFT() - 6)); + page_dir = pgd + offset; + }else{ + pgd = (ulong *)vt->kernel_pgd[0]; + page_dir = pgd + ((vaddr >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)); + } + + if (verbose) fprintf(fp, "PAGE DIRECTORY: %lx\n", (ulong)pgd); + - offset = (uvaddr >> PGDIR_SHIFT) & ((PTRS_PER_PGD >> 3) - 1); - offset |= (region << (PAGESHIFT() - 6)); - page_dir = pgd + offset; FILL_PGD(PAGEBASE(pgd), KVADDR, PAGESIZE()); pgd_pte = ULONG(machdep->pgd + PAGEOFFSET(page_dir)); - if (verbose) { + if (verbose) fprintf(fp, " PGD: %lx => %lx\n", (ulong)page_dir, pgd_pte); - } + if (!(pgd_pte)) - goto no_upage; + return FALSE; - offset = (uvaddr >> PMD_SHIFT) & (PTRS_PER_PMD - 1); + offset = (vaddr >> PMD_SHIFT) & (PTRS_PER_PMD - 1); page_middle = (ulong *)(PTOV(pgd_pte & _PFN_MASK)) + offset; FILL_PMD(PAGEBASE(page_middle), KVADDR, PAGESIZE()); pmd_pte = ULONG(machdep->pmd + PAGEOFFSET(page_middle)); if (verbose) - fprintf(fp, " PMD: %lx => %lx\n", (ulong)page_middle,pmd_pte); + fprintf(fp, " PMD: %lx => %lx\n", (ulong)page_middle, pmd_pte); if (!(pmd_pte)) - goto no_upage; + return FALSE; - offset = (uvaddr >> PAGESHIFT()) & (PTRS_PER_PTE - 1); + offset = (vaddr >> PAGESHIFT()) & (PTRS_PER_PTE - 1); page_table = (ulong *)(PTOV(pmd_pte & _PFN_MASK)) + offset; FILL_PTBL(PAGEBASE(page_table), KVADDR, PAGESIZE()); @@ -745,15 +1089,16 @@ ia64_uvtop(struct task_context *tc, ulon fprintf(fp, " PTE: %lx => %lx\n", (ulong)page_table, pte); if (!(pte & (_PAGE_P))) { - *paddr = pte; + if(usr) + *paddr = pte; if (pte && verbose) { fprintf(fp, "\n"); ia64_translate_pte(pte, 0, 0); } - goto no_upage; + return FALSE; } - *paddr = (pte & _PFN_MASK) + PAGEOFFSET(uvaddr); + *paddr = (pte & _PFN_MASK) + PAGEOFFSET(vaddr); if (verbose) { fprintf(fp, " PAGE: %lx\n\n", PAGEBASE(*paddr)); @@ -762,9 +1107,50 @@ ia64_uvtop(struct task_context *tc, ulon return TRUE; -no_upage: +} - return FALSE; + +/* + * Translates a user virtual address to its physical address. cmd_vtop() + * sets the verbose flag so that the pte translation gets displayed; all + * other callers quietly accept the translation. + * + * This routine can also take mapped kernel virtual addresses if the -u flag + * was passed to cmd_vtop(). If so, it makes the translation using the + * swapper_pg_dir, making it irrelevant in this processor's case. + */ +static int +ia64_uvtop(struct task_context *tc, ulong uvaddr, physaddr_t *paddr, int verbose) +{ + ulong mm; + ulong *pgd; + ulong *page_dir; + ulong *page_middle; + ulong *page_table; + ulong pgd_pte; + ulong pmd_pte; + ulong pte; + ulong offset; + + if (!tc) + error(FATAL, "current context invalid\n"); + + *paddr = 0; + + if (IS_KVADDR(uvaddr)) + return ia64_kvtop(tc, uvaddr, paddr, verbose); + + if ((mm = task_mm(tc->task, TRUE))) + pgd = ULONG_PTR(tt->mm_struct + OFFSET(mm_struct_pgd)); + else + readmem(tc->mm_struct + OFFSET(mm_struct_pgd), KVADDR, &pgd, + sizeof(long), "mm_struct pgd", FAULT_ON_ERROR); + + if (machdep->flags & VM_4_LEVEL) + return ia64_vtop_4l(uvaddr, paddr, pgd, verbose, 1); + else + return ia64_vtop(uvaddr, paddr, pgd, verbose, 1); + } @@ -818,64 +1204,11 @@ ia64_kvtop(struct task_context *tc, ulon pgd = (ulong *)vt->kernel_pgd[0]; - if (verbose) { - fprintf(fp, "PAGE DIRECTORY: %lx\n", (ulong)pgd); - } - - page_dir = pgd + ((kvaddr >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)); - - FILL_PGD(PAGEBASE(pgd), KVADDR, PAGESIZE()); - pgd_pte = ULONG(machdep->pgd + PAGEOFFSET(page_dir)); - - if (verbose) { - fprintf(fp, " PGD: %lx => %lx\n", (ulong)page_dir, pgd_pte); - } - - if (!(pgd_pte)) - goto no_kpage; - - offset = (kvaddr >> PMD_SHIFT) & (PTRS_PER_PMD - 1); - page_middle = (ulong *)(PTOV(pgd_pte & _PFN_MASK)) + offset; - - FILL_PMD(PAGEBASE(page_middle), KVADDR, PAGESIZE()); - pmd_pte = ULONG(machdep->pmd + PAGEOFFSET(page_middle)); - - if (verbose) - fprintf(fp, " PMD: %lx => %lx\n", (ulong)page_middle, - pmd_pte); - - if (!(pmd_pte)) - goto no_kpage; - - offset = (kvaddr >> PAGESHIFT()) & (PTRS_PER_PTE - 1); - page_table = (ulong *)(PTOV(pmd_pte & _PFN_MASK)) + offset; - - FILL_PTBL(PAGEBASE(page_table), KVADDR, PAGESIZE()); - pte = ULONG(machdep->ptbl + PAGEOFFSET(page_table)); - - if (verbose) - fprintf(fp, " PTE: %lx => %lx\n", (ulong)page_table, pte); - - if (!(pte & (_PAGE_P))) { - if (pte && verbose) { - fprintf(fp, "\n"); - ia64_translate_pte(pte, 0, 0); - } - goto no_kpage; - } - - *paddr = (pte & _PFN_MASK) + PAGEOFFSET(kvaddr); - - if (verbose) { - fprintf(fp, " PAGE: %lx\n\n", PAGEBASE(*paddr)); - ia64_translate_pte(pte, 0, 0); - } - - return TRUE; - -no_kpage: + if (machdep->flags & VM_4_LEVEL) + return ia64_vtop_4l(kvaddr, paddr, pgd, verbose, 0); + else + return ia64_vtop(kvaddr, paddr, pgd, verbose, 0); - return FALSE; } /*
-- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility