1 /* $NetBSD: kvm_aarch64.c,v 1.1 2014/08/10 05:47:37 matt Exp $ */
4 * Copyright (c) 2014 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Matt Thomas of 3am Software Foundry.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/param.h>
36 #include <sys/kcore.h>
37 #include <sys/types.h>
42 #include <machine/kcore.h>
43 #include <machine/pte.h>
44 #include <machine/vmparam.h>
50 #include "kvm_private.h"
52 __RCSID("$NetBSD: kvm_aarch64.c,v 1.1 2014/08/10 05:47:37 matt Exp $");
56 _kvm_freevtop(kvm_t
*kd
)
63 _kvm_initvtop(kvm_t
*kd
)
69 _kvm_kvatop(kvm_t
*kd
, vaddr_t va
, paddr_t
*pa
)
72 _kvm_err(kd
, 0, "vatop called in live kernel!");
76 if ((va
& AARCH64_KSEG_MASK
) != AARCH64_KSEG_START
) {
78 * Bogus address (not in KV space): punt.
80 _kvm_err(kd
, 0, "invalid kernel virtual address");
86 const cpu_kcore_hdr_t
* const cpu_kh
= kd
->cpu_data
;
87 const u_int tg1
=__SHIFTOUT(cpu_kh
->kh_tcr1
, TCR_TG1
);
88 const u_int t1siz
= __SHIFTOUT(cpu_kh
->kh_tcr1
, TCR_T1SZ
);
91 * Real kernel virtual address: do the translation.
107 va_bits
= t1siz
+ 38;
114 const size_t page_size
= 1 << page_shift
;
115 const uint64_t page_mask
= (page_size
- 1);
116 const uint64_t page_addr
= __BITS(47, 0) & ~page_mask
;
117 const uint64_t pte_mask
= page_mask
>> 3;
118 const u_int pte_shift
= page_shift
- 3;
120 /* how many level of page tables do we have? */
121 u_int level
= (48 + page_shift
- 1) / page_shift
;
123 /* restrict va to the valid VA bits */
124 va
&= (1LL << va_bits
) - 1;
126 u_int addr_shift
= page_shift
+ (level
- 1) * pte_shift
;
128 /* clear out the unused low bits of the table address */
129 paddr_t pte_addr
= (cpu_kh
->kh_ttbr1
& TTBR_BADDR
);
130 pte_addr
&= ~((8L << (va_bits
- addr_shift
)) - 1);
135 /* now index into the pte table */
136 pte_addr
+= 8 * ((va
>> addr_shift
) & pte_mask
);
138 /* Find and read the PTE. */
139 if (_kvm_pread(kd
, kd
->pmfd
, &pte
, sizeof(pte
),
140 _kvm_pa2off(kd
, pte_addr
)) != sizeof(pte
)) {
141 _kvm_syserr(kd
, 0, "could not read pte");
145 /* Find and read the L2 PTE. */
146 if ((pte
& LX_VALID
) == 0) {
147 _kvm_err(kd
, 0, "invalid translation (invalid pte)");
151 if ((pte
& LX_TYPE
) == LX_TYPE_BLK
) {
152 const paddr_t blk_mask
= ((1L << addr_shift
) - 1);
154 *pa
= (pte
& page_addr
& ~blk_mask
) | (va
& blk_mask
);
158 if (level
== page_shift
) {
159 *pa
= (pte
& page_addr
) | (va
& page_mask
);
164 * Read next level of page table
167 pte_addr
= pte
& page_addr
;
168 addr_shift
-= pte_shift
;
173 * Translate a physical address to a file-offset in the crash dump.
176 _kvm_pa2off(kvm_t
*kd
, paddr_t pa
)
178 const cpu_kcore_hdr_t
* const cpu_kh
= kd
->cpu_data
;
181 for (const phys_ram_seg_t
*ramsegs
= cpu_kh
->kh_ramsegs
;
182 ramsegs
->size
!= 0; ramsegs
++) {
183 if (pa
>= ramsegs
->start
184 && pa
< ramsegs
->start
+ ramsegs
->size
) {
185 off
+= pa
- ramsegs
->start
;
188 off
+= ramsegs
->size
;
191 return kd
->dump_off
+ off
;
195 * Machine-dependent initialization for ALL open kvm descriptors,
196 * not just those for a kernel crash dump. Some architectures
197 * have to deal with these NOT being constants! (i.e. m68k)
200 _kvm_mdopen(kvm_t
*kd
)
203 kd
->usrstack
= USRSTACK
;
204 kd
->min_uva
= VM_MIN_ADDRESS
;
205 kd
->max_uva
= VM_MAXUSER_ADDRESS
;