translate_virtual-irix6.x.tcl
6.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
#
# Copyright (C) 1996-1998 by the Board of Trustees
# of Leland Stanford Junior University.
#
# This file is part of the SimOS distribution.
# See LICENSE file for terms of the license.
#
##
## assumes kernel has been defined
##
set mainStart [symbol read kernel::main:START]
if {$mainStart < 0xa800000000000000} {
console "This doesn't look like a irix64 kernel!!\n"
exit
}
set PNUM_SHIFT 14
set PNUM_MASK 0x3fff
set SEG_MASK 0x3FFFFFFF
if ![info exists irix_moose] {
set irix_moose 0
}
if {$irix_moose} {
set U_ADDR 0x400002ffffff8000
set PDA_ADDR 0x400002ffffffc000
set K0BASE 0x4000000000000000
set K2BASE 0x4000020000000000
set KS0BASE 0x4000000000000000
set KS2BASE 0x4000020000000000
set MOOSE_PDA_PAGE 0xffffffffffffc000
} else {
set U_ADDR 0xffffffffffff8000
set PDA_ADDR 0xffffffffffffc000
set K0BASE 0xa800000000000000
set K2BASE 0xc000000000000000
}
set UPAGENUM [expr $U_ADDR >> $PNUM_SHIFT]
set PDAPAGENUM [expr $PDA_ADDR >> $PNUM_SHIFT]
set private "(*(struct pda_s*)$PDA_ADDR)"
set u "(*(struct user*)$U_ADDR)"
set PTE_VPNMASK 0xFFFFFE00
set PTE_VPNSHIFT 3
set PTE_VBITMASK 0x00000001
set PR_SADDR 0x00000040
set SHRD_SENTINEL 0x00000200
set upg_isa_structure 1
set mod_by_cell 0
if {$irix_moose} {
proc TclTranslateVirtual {cpunum vaddr} {
global MOOSE_PDA_PAGE PAGE_SHIFT KS0BASE KS2BASE K2BASE OS VCPU
global OFFSET_MASK
#console "Translating virtual: cpunum=$cpunum vaddr=$vaddr\n"
if {($vaddr >= $KS0BASE) && ($vaddr < $KS2BASE)} {
# ks0seg addr
return [TranslatePhysical $cpunum [expr $vaddr - $KS0BASE]]
}
console "Translating virtual: cpunum=$cpunum vaddr=$vaddr\n"
debug
}
set SEG_SHIFT 19
set PTE_SHIFT 12
set PTE_MASK 0x7f
set PTE_VALID 0x2
set PTE_PFNSHIFT 6
set MOOSE_PAGE_SHIFT 12
set MOOSE_PAGE_MASK 0xfff
proc TranslatePhysical {cpunum paddr} {
global SEG_SHIFT PTE_MASK PTE_SHIFT PTE_VALID PTE_PFNSHIFT MOOSE_PAGE_SHIFT MOOSE_PAGE_MASK MEMORY
#console "Translating physical: cpunum=$cpunum paddr=[hex $paddr]\n"
set pmap [symbol read monitor::PDAs<$cpunum>->vcpu_pmap]
set segnum [expr $paddr >> $SEG_SHIFT]
set indx [expr ($paddr >> $PTE_SHIFT) & $PTE_MASK]
set segment [symbol read monitor::((long**)$pmap)<$segnum>]
set pte [symbol read "monitor::((struct PageMapEntry*)$segment)<$indx>.pte"]
if {$pte & $PTE_VALID} {
set pgoff [expr $paddr & $MOOSE_PAGE_MASK]
return [expr (($pte >> $PTE_PFNSHIFT) << $MOOSE_PAGE_SHIFT) | $pgoff]
} else {
console "TP failed: pmap=$pmap segment=$segment pte=[hex $pte]\n"
console "TP failed: segnum=[hex $segnum] indx=[hex $indx]\n"
debug
}
}
} else {
set SEG_SHIFT 19
set PTE_SHIFT 12
set PTE_MASK 0x7f
set PTE_VALID 0x2
set PTE_PFNSHIFT 6
set PAGE_SHIFT 12
set PAGE_MASK 0xfff
proc TclTranslateVirtual {cpunum vaddr} {
global UPAGENUM PDAPAGENUM K0BASE K2BASE REGISTER SHRD_SENTINEL PR_SADDR
global cpusPerCell upg_isa_structure mod_by_cell
global PTE_VPNMASK PTE_VPNSHIFT PTE_VBITMASK MCPU PNUM_SHIFT PNUM_MASK SEG_MASK
console "Translating 64-bit virtual - beware: CPU=$cpunum vaddr=$vaddr\n"
set pdaindx $MCPU($cpunum)
if ![symbol read kernel::pdaindr<$pdaindx>.pda] {
console "TV.TCL: pdaindr read of $pdaindx failed \n"
# during boot
return 0
}
set vpn [expr ($vaddr >> $PNUM_SHIFT) & $SEG_MASK]
set pgoff [expr $vaddr & $PNUM_MASK]
console "vpn $vpn, off: $pgoff\n"
if {$vpn == $UPAGENUM} {
if {$upg_isa_structure} {
set upte [symbol read kernel::pdaindr<$pdaindx>.pda->p_upglo.pgi]
} else {
set upte [symbol read kernel::pdaindr<$pdaindx>.pda->p_upglo]
}
return [expr (($upte & $PTE_VPNMASK)<<$PTE_VPNSHIFT) | $pgoff]
}
if {$vpn == $PDAPAGENUM} {
set pdap [symbol read kernel::pdaindr<$pdaindx>.pda]
assert {!($pdap & $PNUM_MASK)}
return [expr ($pdap - $K0BASE) | $pgoff]
}
set firstK2Page [expr $K2BASE >> $PNUM_SHIFT]
if {$vpn >= $firstK2Page} {
# kernel virtual address
set lastK2Page [expr $firstK2Page + [symbol read kernel::v.v_syssegsz]]
if {$vpn < $lastK2Page} {
set kpte [symbol read kernel::kptbl<[expr $vpn - $firstK2Page]>.pgi]
return [expr (($kpte & $PTE_VPNMASK)<<$PTE_VPNSHIFT) | $pgoff]
}
return 0
}
if {$vpn < ($K0BASE >> $PNUM_SHIFT)} {
# user virtual address
console "TV.TCL: user virtual address\n"
if {$upg_isa_structure} {
set upte [symbol read kernel::pdaindr<$pdaindx>.pda->p_upglo.pgi]
} else {
set upte [symbol read kernel::pdaindr<$pdaindx>.pda->p_upglo]
}
set uarea [expr (($upte & $PTE_VPNMASK)<<$PTE_VPNSHIFT) + $K0BASE]
set procp [symbol read kernel:user.h:((user_t*)$uarea)->u_procp]
set pmap [symbol read kernel:proc.h:((proc_t*)$procp)->p_pmap]
if {!$pmap} {
# should get here only if idle, in which case why are
# we translating a user virtual address? Anyway, ignore
# it and go one. The following warning used to be an
# assertion but seems to happen occasionally when the
# debugger is operating, and we don't want to fail in that
# case.
if {[symbol read kernel::pdaindr<$pdaindx>.pda->p_curproc]} {
console "TclTranslateVirtual: pda says a proc is active but pmap is null\n"
}
return 0
}
set pte [pmapProbe $pmap $vaddr]
if {!$pte || ($pte == $SHRD_SENTINEL)} {
if {[symbol read kernel:proc.h:((proc_t*)$procp)->p_shmask] & $PR_SADDR} {
set pmap [symbol read kernel:proc.h:((proc_t*)$procp)->p_shaddr->s_pmap]
set pte [pmapProbe $pmap $vaddr]
}
}
if {$pte} {
assert {$pte != $SHRD_SENTINEL}
return [expr (($pte & $PTE_VPNMASK)<<$PTE_VPNSHIFT) | $pgoff]
}
}
return 0
}
proc pmapProbe {pmap vaddr} {
global PTE_VBITMASK
console "pmapProbe $pmap $vaddr, pc=$pc, ra=$ra\n"
debug
set segment [expr ($vaddr >> 22) & 0x03FF]
set segptr [symbol read kernel:pmap.c:((pseg_t*)$pmap)->pseg_segptr<$segment>]
if {!$segptr} {
# console "no seg pointer\n"
return 0
}
set segoff [expr ($vaddr >> 12) & 0x03FF]
set pte [symbol read kernel:pmap.c:((int*)$segptr)<$segoff>]
if {!($pte & $PTE_VBITMASK)} {
# console "TclTranslateVirtual: pte not valid = [hex $pte]\n"
return 0
}
return $pte
}
}