2 * HPPA interrupt helper routines
4 * Copyright (c) 2017 Richard Henderson
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 #include "qemu/osdep.h"
22 #include "migration/cpu.h"
25 static int get_psw(QEMUFile
*f
, void *opaque
, size_t size
,
26 const VMStateField
*field
)
28 CPUHPPAState
*env
= opaque
;
29 cpu_hppa_put_psw(env
, qemu_get_be64(f
));
33 static int put_psw(QEMUFile
*f
, void *opaque
, size_t size
,
34 const VMStateField
*field
, JSONWriter
*vmdesc
)
36 CPUHPPAState
*env
= opaque
;
37 qemu_put_be64(f
, cpu_hppa_get_psw(env
));
41 static const VMStateInfo vmstate_psw
= {
47 static int get_tlb(QEMUFile
*f
, void *opaque
, size_t size
,
48 const VMStateField
*field
)
50 HPPATLBEntry
*ent
= opaque
;
53 ent
->itree
.start
= qemu_get_be64(f
);
54 ent
->itree
.last
= qemu_get_be64(f
);
55 ent
->pa
= qemu_get_be64(f
);
56 val
= qemu_get_be64(f
);
59 ent
->t
= extract64(val
, 61, 1);
60 ent
->d
= extract64(val
, 60, 1);
61 ent
->b
= extract64(val
, 59, 1);
62 ent
->ar_type
= extract64(val
, 56, 3);
63 ent
->ar_pl1
= extract64(val
, 54, 2);
64 ent
->ar_pl2
= extract64(val
, 52, 2);
65 ent
->u
= extract64(val
, 51, 1);
68 ent
->access_id
= extract64(val
, 1, 31);
74 static int put_tlb(QEMUFile
*f
, void *opaque
, size_t size
,
75 const VMStateField
*field
, JSONWriter
*vmdesc
)
77 HPPATLBEntry
*ent
= opaque
;
80 if (ent
->entry_valid
) {
82 val
= deposit64(val
, 61, 1, ent
->t
);
83 val
= deposit64(val
, 60, 1, ent
->d
);
84 val
= deposit64(val
, 59, 1, ent
->b
);
85 val
= deposit64(val
, 56, 3, ent
->ar_type
);
86 val
= deposit64(val
, 54, 2, ent
->ar_pl1
);
87 val
= deposit64(val
, 52, 2, ent
->ar_pl2
);
88 val
= deposit64(val
, 51, 1, ent
->u
);
91 val
= deposit64(val
, 1, 31, ent
->access_id
);
94 qemu_put_be64(f
, ent
->itree
.start
);
95 qemu_put_be64(f
, ent
->itree
.last
);
96 qemu_put_be64(f
, ent
->pa
);
97 qemu_put_be64(f
, val
);
101 static const VMStateInfo vmstate_tlb_entry
= {
107 static int tlb_pre_load(void *opaque
)
109 CPUHPPAState
*env
= opaque
;
112 * Zap the entire tlb, on-the-side data structures and all.
113 * Each tlb entry will have data re-filled by put_tlb.
115 memset(env
->tlb
, 0, sizeof(env
->tlb
));
116 memset(&env
->tlb_root
, 0, sizeof(env
->tlb_root
));
117 env
->tlb_unused
= NULL
;
118 env
->tlb_partial
= NULL
;
123 static int tlb_post_load(void *opaque
, int version_id
)
125 CPUHPPAState
*env
= opaque
;
126 uint32_t btlb_entries
= HPPA_BTLB_ENTRIES(env
);
127 HPPATLBEntry
**unused
= &env
->tlb_unused
;
128 HPPATLBEntry
*partial
= NULL
;
131 * Re-create the interval tree from the valid entries.
132 * Truly invalid entries should have start == end == 0.
133 * Otherwise it should be the in-flight tlb_partial entry.
135 for (uint32_t i
= 0; i
< ARRAY_SIZE(env
->tlb
); ++i
) {
136 HPPATLBEntry
*e
= &env
->tlb
[i
];
138 if (e
->entry_valid
) {
139 interval_tree_insert(&e
->itree
, &env
->tlb_root
);
140 } else if (i
< btlb_entries
) {
141 /* btlb not in unused list */
142 } else if (partial
== NULL
&& e
->itree
.start
< e
->itree
.last
) {
146 unused
= &e
->unused_next
;
149 env
->tlb_partial
= partial
;
155 static const VMStateField vmstate_tlb_fields
[] = {
156 VMSTATE_ARRAY(tlb
, CPUHPPAState
,
157 ARRAY_SIZE(((CPUHPPAState
*)0)->tlb
),
158 0, vmstate_tlb_entry
, HPPATLBEntry
),
159 VMSTATE_UINT32(tlb_last
, CPUHPPAState
),
160 VMSTATE_END_OF_LIST()
163 static const VMStateDescription vmstate_tlb
= {
166 .minimum_version_id
= 1,
167 .fields
= vmstate_tlb_fields
,
168 .pre_load
= tlb_pre_load
,
169 .post_load
= tlb_post_load
,
172 static const VMStateField vmstate_env_fields
[] = {
173 VMSTATE_UINT64_ARRAY(gr
, CPUHPPAState
, 32),
174 VMSTATE_UINT64_ARRAY(fr
, CPUHPPAState
, 32),
175 VMSTATE_UINT64_ARRAY(sr
, CPUHPPAState
, 8),
176 VMSTATE_UINT64_ARRAY(cr
, CPUHPPAState
, 32),
177 VMSTATE_UINT64_ARRAY(cr_back
, CPUHPPAState
, 2),
178 VMSTATE_UINT64_ARRAY(shadow
, CPUHPPAState
, 7),
180 /* Save the architecture value of the psw, not the internally
181 expanded version. Since this architecture value does not
182 exist in memory to be stored, this requires a but of hoop
183 jumping. We want OFFSET=0 so that we effectively pass ENV
184 to the helper functions, and we need to fill in the name by
185 hand since there's no field of that name. */
189 .size
= sizeof(uint64_t),
190 .info
= &vmstate_psw
,
195 VMSTATE_UINT64(iaoq_f
, CPUHPPAState
),
196 VMSTATE_UINT64(iaoq_b
, CPUHPPAState
),
197 VMSTATE_UINT64(iasq_f
, CPUHPPAState
),
198 VMSTATE_UINT64(iasq_b
, CPUHPPAState
),
200 VMSTATE_UINT32(fr0_shadow
, CPUHPPAState
),
201 VMSTATE_END_OF_LIST()
204 static const VMStateDescription
* const vmstate_env_subsections
[] = {
209 static const VMStateDescription vmstate_env
= {
212 .minimum_version_id
= 3,
213 .fields
= vmstate_env_fields
,
214 .subsections
= vmstate_env_subsections
,
217 static const VMStateField vmstate_cpu_fields
[] = {
219 VMSTATE_STRUCT(env
, HPPACPU
, 1, vmstate_env
, CPUHPPAState
),
220 VMSTATE_END_OF_LIST()
223 const VMStateDescription vmstate_hppa_cpu
= {
226 .minimum_version_id
= 1,
227 .fields
= vmstate_cpu_fields
,