4
* Created by: Mika Westerberg <ext-mika.1.westerberg@nokia.com>
5
* Copyright (C) 2010 Nokia Corporation
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
19
#include "makedumpfile.h"
21
#define PMD_TYPE_MASK 3
22
#define PMD_TYPE_SECT 2
23
#define PMD_TYPE_TABLE 1
25
#define pgd_index(vaddr) ((vaddr) >> PGDIR_SHIFT)
26
#define pte_index(vaddr) ((vaddr >> PAGESHIFT()) & (PTRS_PER_PTE - 1))
28
#define pgd_offset(pgdir, vaddr) \
29
((pgdir) + pgd_index(vaddr) * 2 * sizeof(unsigned long))
30
#define pmd_offset(dir, vaddr) (dir)
31
#define pte_offset(pmd, vaddr) \
32
(pmd_page_vaddr(pmd) + pte_index(vaddr) * sizeof(unsigned long))
35
* These only work for kernel directly mapped addresses.
37
#define __va(paddr) ((paddr) - info->phys_base + info->page_offset)
38
#define __pa(vaddr) ((vaddr) - info->page_offset + info->phys_base)
40
static inline unsigned long
41
pmd_page_vaddr(unsigned long pmd)
45
ptr = pmd & ~(PTRS_PER_PTE * sizeof(void *) - 1);
46
ptr += PTRS_PER_PTE * sizeof(void *);
52
get_phys_base_arm(void)
54
unsigned long phys_base = ULONG_MAX;
58
* We resolve phys_base from PT_LOAD segments. LMA contains physical
59
* address of the segment, and we use the first one.
61
for (i = 0; i < info->num_load_memory; i++) {
62
const struct pt_load_segment *pls = &info->pt_load_segments[i];
64
if (pls->phys_start < phys_base)
65
phys_base = pls->phys_start;
68
if (phys_base == ULONG_MAX) {
69
ERRMSG("Can't determine phys_base.\n");
73
info->phys_base = phys_base;
74
DEBUG_MSG("phys_base : %lx\n", phys_base);
80
get_machdep_info_arm(void)
82
info->page_offset = SYMBOL(_stext) & 0xffff0000UL;
83
info->max_physmem_bits = _MAX_PHYSMEM_BITS;
84
info->kernel_start = SYMBOL(_stext);
85
info->section_size_bits = _SECTION_SIZE_BITS;
87
DEBUG_MSG("page_offset : %lx\n", info->page_offset);
88
DEBUG_MSG("kernel_start : %lx\n", info->kernel_start);
94
* vtop_arm() - translate arbitrary virtual address to physical
95
* @vaddr: virtual address to translate
97
* Function translates @vaddr into physical address using page tables. This
98
* address can be any virtual address. Returns physical address of the
99
* corresponding virtual address or %NOT_PADDR when there is no translation.
101
static unsigned long long
102
vtop_arm(unsigned long vaddr)
104
unsigned long long paddr = NOT_PADDR;
105
unsigned long ptr, pgd, pte, pmd;
107
if (SYMBOL(swapper_pg_dir) == NOT_FOUND_SYMBOL) {
108
ERRMSG("Can't get the symbol of swapper_pg_dir.\n");
112
ptr = pgd_offset(SYMBOL(swapper_pg_dir), vaddr);
113
if (!readmem(VADDR, ptr, &pgd, sizeof(pmd))) {
114
ERRMSG("Can't read pgd\n");
118
if (info->vaddr_for_vtop == vaddr)
119
MSG(" PGD : %08lx => %08lx\n", ptr, pgd);
121
pmd = pmd_offset(pgd, vaddr);
123
switch (pmd & PMD_TYPE_MASK) {
124
case PMD_TYPE_TABLE: {
126
ptr = pte_offset(pmd, vaddr);
127
if (!readmem(VADDR, ptr, &pte, sizeof(pte))) {
128
ERRMSG("Can't read pte\n");
132
if (info->vaddr_for_vtop == vaddr)
133
MSG(" PTE : %08lx => %08lx\n", ptr, pte);
135
if (!(pte & _PAGE_PRESENT)) {
136
ERRMSG("Can't get a valid pte.\n");
140
paddr = PAGEBASE(pte) + (vaddr & (PAGESIZE() - 1));
146
pte = pmd & PMD_MASK;
147
paddr = pte + (vaddr & (PMD_SIZE - 1));
155
vaddr_to_paddr_arm(unsigned long vaddr)
158
* Only use translation tables when user has explicitly requested us to
159
* perform translation for a given address. Otherwise we assume that the
160
* translation is done within the kernel direct mapped region.
162
if (info->vaddr_for_vtop == vaddr)
163
return vtop_arm(vaddr);