2 * Copyright (c) 2006 Peter Wemm
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
30 * AMD64 machine dependent routines for kvm and minidumps.
33 #include <sys/param.h>
38 #include <sys/fnv_hash.h>
46 #include <vm/vm_param.h>
48 #include <machine/elf.h>
49 #include <machine/cpufunc.h>
50 #include <machine/minidump.h>
54 #include "kvm_private.h"
64 /* minidump must be the first item! */
66 int minidump
; /* 1 = minidump mode */
67 struct minidumphdr hdr
;
68 void *hpt_head
[HPT_SIZE
];
74 hpt_insert(kvm_t
*kd
, vm_paddr_t pa
, int64_t off
)
77 uint32_t fnv
= FNV1_32_INIT
;
79 fnv
= fnv_32_buf(&pa
, sizeof(pa
), fnv
);
80 fnv
&= (HPT_SIZE
- 1);
81 hpte
= malloc(sizeof(*hpte
));
84 hpte
->next
= kd
->vmst
->hpt_head
[fnv
];
85 kd
->vmst
->hpt_head
[fnv
] = hpte
;
89 hpt_find(kvm_t
*kd
, vm_paddr_t pa
)
92 uint32_t fnv
= FNV1_32_INIT
;
94 fnv
= fnv_32_buf(&pa
, sizeof(pa
), fnv
);
95 fnv
&= (HPT_SIZE
- 1);
96 for (hpte
= kd
->vmst
->hpt_head
[fnv
]; hpte
!= NULL
; hpte
= hpte
->next
) {
104 inithash(kvm_t
*kd
, uint64_t *base
, int len
, off_t off
)
110 for (idx
= 0; idx
< len
/ sizeof(*base
); idx
++) {
114 bits
&= ~(1ul << bit
);
115 pa
= (idx
* sizeof(*base
) * NBBY
+ bit
) * PAGE_SIZE
;
116 hpt_insert(kd
, pa
, off
);
124 _kvm_minidump_freevtop(kvm_t
*kd
)
126 struct vmstate
*vm
= kd
->vmst
;
137 _kvm_minidump_initvtop(kvm_t
*kd
)
140 struct vmstate
*vmst
;
143 vmst
= _kvm_malloc(kd
, sizeof(*vmst
));
145 _kvm_err(kd
, kd
->program
, "cannot allocate vm");
149 bzero(vmst
, sizeof(*vmst
));
151 if (pread(kd
->pmfd
, &vmst
->hdr
, sizeof(vmst
->hdr
), 0) !=
153 _kvm_err(kd
, kd
->program
, "cannot read dump header");
156 if (strncmp(MINIDUMP_MAGIC
, vmst
->hdr
.magic
, sizeof(vmst
->hdr
.magic
)) != 0) {
157 _kvm_err(kd
, kd
->program
, "not a minidump for this platform");
160 if (vmst
->hdr
.version
!= MINIDUMP_VERSION
) {
161 _kvm_err(kd
, kd
->program
, "wrong minidump version. expected %d got %d",
162 MINIDUMP_VERSION
, vmst
->hdr
.version
);
166 /* Skip header and msgbuf */
167 off
= PAGE_SIZE
+ round_page(vmst
->hdr
.msgbufsize
);
169 vmst
->bitmap
= _kvm_malloc(kd
, vmst
->hdr
.bitmapsize
);
170 if (vmst
->bitmap
== NULL
) {
171 _kvm_err(kd
, kd
->program
, "cannot allocate %d bytes for bitmap", vmst
->hdr
.bitmapsize
);
174 if (pread(kd
->pmfd
, vmst
->bitmap
, vmst
->hdr
.bitmapsize
, off
) !=
175 vmst
->hdr
.bitmapsize
) {
176 _kvm_err(kd
, kd
->program
, "cannot read %d bytes for page bitmap", vmst
->hdr
.bitmapsize
);
179 off
+= round_page(vmst
->hdr
.bitmapsize
);
181 vmst
->ptemap
= _kvm_malloc(kd
, vmst
->hdr
.ptesize
);
182 if (vmst
->ptemap
== NULL
) {
183 _kvm_err(kd
, kd
->program
, "cannot allocate %d bytes for ptemap", vmst
->hdr
.ptesize
);
186 if (pread(kd
->pmfd
, vmst
->ptemap
, vmst
->hdr
.ptesize
, off
) !=
188 _kvm_err(kd
, kd
->program
, "cannot read %d bytes for ptemap", vmst
->hdr
.ptesize
);
191 off
+= vmst
->hdr
.ptesize
;
193 /* build physical address hash table for sparse pages */
194 inithash(kd
, vmst
->bitmap
, vmst
->hdr
.bitmapsize
, off
);
200 _kvm_minidump_vatop(kvm_t
*kd
, u_long va
, off_t
*pa
)
211 offset
= va
& (PAGE_SIZE
- 1);
213 if (va
>= vm
->hdr
.kernbase
) {
214 pteindex
= (va
- vm
->hdr
.kernbase
) >> PAGE_SHIFT
;
215 pte
= vm
->ptemap
[pteindex
];
216 if (((u_long
)pte
& PG_V
) == 0) {
217 _kvm_err(kd
, kd
->program
, "_kvm_vatop: pte not valid");
221 ofs
= hpt_find(kd
, a
);
223 _kvm_err(kd
, kd
->program
, "_kvm_vatop: physical address 0x%lx not in minidump", a
);
227 return (PAGE_SIZE
- offset
);
228 } else if (va
>= vm
->hdr
.dmapbase
&& va
< vm
->hdr
.dmapend
) {
229 a
= (va
- vm
->hdr
.dmapbase
) & ~PAGE_MASK
;
230 ofs
= hpt_find(kd
, a
);
232 _kvm_err(kd
, kd
->program
, "_kvm_vatop: direct map address 0x%lx not in minidump", va
);
236 return (PAGE_SIZE
- offset
);
238 _kvm_err(kd
, kd
->program
, "_kvm_vatop: virtual address 0x%lx not minidumped", va
);
243 _kvm_err(kd
, 0, "invalid address (0x%lx)", va
);
248 _kvm_minidump_kvatop(kvm_t
*kd
, u_long va
, off_t
*pa
)
252 _kvm_err(kd
, 0, "kvm_kvatop called in live kernel!");
255 return (_kvm_minidump_vatop(kd
, va
, pa
));