2 * Copyright 2008 IBM Corporation
4 * Copyright 2011 Intel Corporation
5 * Copyright 2016 Veertu, Inc.
6 * Copyright 2017 The Android Open Source Project
8 * QEMU Hypervisor.framework support
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of version 2 of the GNU General Public
12 * License as published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 * This file contain code under public domain from the hvdos project:
23 * https://github.com/mist64/hvdos
25 * Parts Copyright (c) 2011 NetApp, Inc.
26 * All rights reserved.
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
37 * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
38 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
40 * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
41 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
42 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
43 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
45 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
46 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50 #include "qemu/osdep.h"
51 #include "qemu/error-report.h"
52 #include "qemu/main-loop.h"
53 #include "exec/address-spaces.h"
54 #include "exec/exec-all.h"
55 #include "gdbstub/enums.h"
56 #include "hw/boards.h"
57 #include "sysemu/cpus.h"
58 #include "sysemu/hvf.h"
59 #include "sysemu/hvf_int.h"
60 #include "sysemu/runstate.h"
61 #include "qemu/guest-random.h"
67 hvf_slot
*hvf_find_overlap_slot(uint64_t start
, uint64_t size
)
71 for (x
= 0; x
< hvf_state
->num_slots
; ++x
) {
72 slot
= &hvf_state
->slots
[x
];
73 if (slot
->size
&& start
< (slot
->start
+ slot
->size
) &&
74 (start
+ size
) > slot
->start
) {
88 struct mac_slot mac_slots
[32];
90 static int do_hvf_set_memory(hvf_slot
*slot
, hv_memory_flags_t flags
)
92 struct mac_slot
*macslot
;
95 macslot
= &mac_slots
[slot
->slot_id
];
97 if (macslot
->present
) {
98 if (macslot
->size
!= slot
->size
) {
100 ret
= hv_vm_unmap(macslot
->gpa_start
, macslot
->size
);
109 macslot
->present
= 1;
110 macslot
->gpa_start
= slot
->start
;
111 macslot
->size
= slot
->size
;
112 ret
= hv_vm_map(slot
->mem
, slot
->start
, slot
->size
, flags
);
117 static void hvf_set_phys_mem(MemoryRegionSection
*section
, bool add
)
120 MemoryRegion
*area
= section
->mr
;
121 bool writable
= !area
->readonly
&& !area
->rom_device
;
122 hv_memory_flags_t flags
;
123 uint64_t page_size
= qemu_real_host_page_size();
125 if (!memory_region_is_ram(area
)) {
128 } else if (!memory_region_is_romd(area
)) {
130 * If the memory device is not in romd_mode, then we actually want
131 * to remove the hvf memory slot so all accesses will trap.
137 if (!QEMU_IS_ALIGNED(int128_get64(section
->size
), page_size
) ||
138 !QEMU_IS_ALIGNED(section
->offset_within_address_space
, page_size
)) {
139 /* Not page aligned, so we can not map as RAM */
143 mem
= hvf_find_overlap_slot(
144 section
->offset_within_address_space
,
145 int128_get64(section
->size
));
148 if (mem
->size
== int128_get64(section
->size
) &&
149 mem
->start
== section
->offset_within_address_space
&&
150 mem
->mem
== (memory_region_get_ram_ptr(area
) +
151 section
->offset_within_region
)) {
152 return; /* Same region was attempted to register, go away. */
156 /* Region needs to be reset. set the size to 0 and remap it. */
159 if (do_hvf_set_memory(mem
, 0)) {
160 error_report("Failed to reset overlapping slot");
169 if (area
->readonly
||
170 (!memory_region_is_ram(area
) && memory_region_is_romd(area
))) {
171 flags
= HV_MEMORY_READ
| HV_MEMORY_EXEC
;
173 flags
= HV_MEMORY_READ
| HV_MEMORY_WRITE
| HV_MEMORY_EXEC
;
176 /* Now make a new slot. */
179 for (x
= 0; x
< hvf_state
->num_slots
; ++x
) {
180 mem
= &hvf_state
->slots
[x
];
186 if (x
== hvf_state
->num_slots
) {
187 error_report("No free slots");
191 mem
->size
= int128_get64(section
->size
);
192 mem
->mem
= memory_region_get_ram_ptr(area
) + section
->offset_within_region
;
193 mem
->start
= section
->offset_within_address_space
;
196 if (do_hvf_set_memory(mem
, flags
)) {
197 error_report("Error registering new memory slot");
202 static void do_hvf_cpu_synchronize_state(CPUState
*cpu
, run_on_cpu_data arg
)
204 if (!cpu
->accel
->dirty
) {
205 hvf_get_registers(cpu
);
206 cpu
->accel
->dirty
= true;
210 static void hvf_cpu_synchronize_state(CPUState
*cpu
)
212 if (!cpu
->accel
->dirty
) {
213 run_on_cpu(cpu
, do_hvf_cpu_synchronize_state
, RUN_ON_CPU_NULL
);
217 static void do_hvf_cpu_synchronize_set_dirty(CPUState
*cpu
,
220 /* QEMU state is the reference, push it to HVF now and on next entry */
221 cpu
->accel
->dirty
= true;
224 static void hvf_cpu_synchronize_post_reset(CPUState
*cpu
)
226 run_on_cpu(cpu
, do_hvf_cpu_synchronize_set_dirty
, RUN_ON_CPU_NULL
);
229 static void hvf_cpu_synchronize_post_init(CPUState
*cpu
)
231 run_on_cpu(cpu
, do_hvf_cpu_synchronize_set_dirty
, RUN_ON_CPU_NULL
);
234 static void hvf_cpu_synchronize_pre_loadvm(CPUState
*cpu
)
236 run_on_cpu(cpu
, do_hvf_cpu_synchronize_set_dirty
, RUN_ON_CPU_NULL
);
239 static void hvf_set_dirty_tracking(MemoryRegionSection
*section
, bool on
)
243 slot
= hvf_find_overlap_slot(
244 section
->offset_within_address_space
,
245 int128_get64(section
->size
));
247 /* protect region against writes; begin tracking it */
249 slot
->flags
|= HVF_SLOT_LOG
;
250 hv_vm_protect((uintptr_t)slot
->start
, (size_t)slot
->size
,
251 HV_MEMORY_READ
| HV_MEMORY_EXEC
);
252 /* stop tracking region*/
254 slot
->flags
&= ~HVF_SLOT_LOG
;
255 hv_vm_protect((uintptr_t)slot
->start
, (size_t)slot
->size
,
256 HV_MEMORY_READ
| HV_MEMORY_WRITE
| HV_MEMORY_EXEC
);
260 static void hvf_log_start(MemoryListener
*listener
,
261 MemoryRegionSection
*section
, int old
, int new)
267 hvf_set_dirty_tracking(section
, 1);
270 static void hvf_log_stop(MemoryListener
*listener
,
271 MemoryRegionSection
*section
, int old
, int new)
277 hvf_set_dirty_tracking(section
, 0);
280 static void hvf_log_sync(MemoryListener
*listener
,
281 MemoryRegionSection
*section
)
284 * sync of dirty pages is handled elsewhere; just make sure we keep
285 * tracking the region.
287 hvf_set_dirty_tracking(section
, 1);
290 static void hvf_region_add(MemoryListener
*listener
,
291 MemoryRegionSection
*section
)
293 hvf_set_phys_mem(section
, true);
296 static void hvf_region_del(MemoryListener
*listener
,
297 MemoryRegionSection
*section
)
299 hvf_set_phys_mem(section
, false);
302 static MemoryListener hvf_memory_listener
= {
304 .priority
= MEMORY_LISTENER_PRIORITY_ACCEL
,
305 .region_add
= hvf_region_add
,
306 .region_del
= hvf_region_del
,
307 .log_start
= hvf_log_start
,
308 .log_stop
= hvf_log_stop
,
309 .log_sync
= hvf_log_sync
,
312 static void dummy_signal(int sig
)
318 static int hvf_accel_init(MachineState
*ms
)
324 MachineClass
*mc
= MACHINE_GET_CLASS(ms
);
326 if (mc
->hvf_get_physical_address_range
) {
327 pa_range
= mc
->hvf_get_physical_address_range(ms
);
333 ret
= hvf_arch_vm_create(ms
, (uint32_t)pa_range
);
336 s
= g_new0(HVFState
, 1);
338 s
->num_slots
= ARRAY_SIZE(s
->slots
);
339 for (x
= 0; x
< s
->num_slots
; ++x
) {
340 s
->slots
[x
].size
= 0;
341 s
->slots
[x
].slot_id
= x
;
344 QTAILQ_INIT(&s
->hvf_sw_breakpoints
);
347 memory_listener_register(&hvf_memory_listener
, &address_space_memory
);
349 return hvf_arch_init();
352 static inline int hvf_gdbstub_sstep_flags(void)
354 return SSTEP_ENABLE
| SSTEP_NOIRQ
;
357 static void hvf_accel_class_init(ObjectClass
*oc
, void *data
)
359 AccelClass
*ac
= ACCEL_CLASS(oc
);
361 ac
->init_machine
= hvf_accel_init
;
362 ac
->allowed
= &hvf_allowed
;
363 ac
->gdbstub_supported_sstep_flags
= hvf_gdbstub_sstep_flags
;
366 static const TypeInfo hvf_accel_type
= {
367 .name
= TYPE_HVF_ACCEL
,
368 .parent
= TYPE_ACCEL
,
369 .class_init
= hvf_accel_class_init
,
372 static void hvf_type_init(void)
374 type_register_static(&hvf_accel_type
);
377 type_init(hvf_type_init
);
379 static void hvf_vcpu_destroy(CPUState
*cpu
)
381 hv_return_t ret
= hv_vcpu_destroy(cpu
->accel
->fd
);
384 hvf_arch_vcpu_destroy(cpu
);
389 static int hvf_init_vcpu(CPUState
*cpu
)
393 cpu
->accel
= g_new0(AccelCPUState
, 1);
395 /* init cpu signals */
396 struct sigaction sigact
;
398 memset(&sigact
, 0, sizeof(sigact
));
399 sigact
.sa_handler
= dummy_signal
;
400 sigaction(SIG_IPI
, &sigact
, NULL
);
402 pthread_sigmask(SIG_BLOCK
, NULL
, &cpu
->accel
->unblock_ipi_mask
);
403 sigdelset(&cpu
->accel
->unblock_ipi_mask
, SIG_IPI
);
406 r
= hv_vcpu_create(&cpu
->accel
->fd
,
407 (hv_vcpu_exit_t
**)&cpu
->accel
->exit
, NULL
);
409 r
= hv_vcpu_create(&cpu
->accel
->fd
, HV_VCPU_DEFAULT
);
411 cpu
->accel
->dirty
= true;
414 cpu
->accel
->guest_debug_enabled
= false;
416 return hvf_arch_init_vcpu(cpu
);
420 * The HVF-specific vCPU thread function. This one should only run when the host
421 * CPU supports the VMX "unrestricted guest" feature.
423 static void *hvf_cpu_thread_fn(void *arg
)
429 assert(hvf_enabled());
431 rcu_register_thread();
434 qemu_thread_get_self(cpu
->thread
);
436 cpu
->thread_id
= qemu_get_thread_id();
441 /* signal CPU creation */
442 cpu_thread_signal_created(cpu
);
443 qemu_guest_random_seed_thread_part2(cpu
->random_seed
);
446 if (cpu_can_run(cpu
)) {
447 r
= hvf_vcpu_exec(cpu
);
448 if (r
== EXCP_DEBUG
) {
449 cpu_handle_guest_debug(cpu
);
452 qemu_wait_io_event(cpu
);
453 } while (!cpu
->unplug
|| cpu_can_run(cpu
));
455 hvf_vcpu_destroy(cpu
);
456 cpu_thread_signal_destroyed(cpu
);
458 rcu_unregister_thread();
462 static void hvf_start_vcpu_thread(CPUState
*cpu
)
464 char thread_name
[VCPU_THREAD_NAME_SIZE
];
467 * HVF currently does not support TCG, and only runs in
468 * unrestricted-guest mode.
470 assert(hvf_enabled());
472 snprintf(thread_name
, VCPU_THREAD_NAME_SIZE
, "CPU %d/HVF",
474 qemu_thread_create(cpu
->thread
, thread_name
, hvf_cpu_thread_fn
,
475 cpu
, QEMU_THREAD_JOINABLE
);
478 static int hvf_insert_breakpoint(CPUState
*cpu
, int type
, vaddr addr
, vaddr len
)
480 struct hvf_sw_breakpoint
*bp
;
483 if (type
== GDB_BREAKPOINT_SW
) {
484 bp
= hvf_find_sw_breakpoint(cpu
, addr
);
490 bp
= g_new(struct hvf_sw_breakpoint
, 1);
493 err
= hvf_arch_insert_sw_breakpoint(cpu
, bp
);
499 QTAILQ_INSERT_HEAD(&hvf_state
->hvf_sw_breakpoints
, bp
, entry
);
501 err
= hvf_arch_insert_hw_breakpoint(addr
, len
, type
);
508 err
= hvf_update_guest_debug(cpu
);
516 static int hvf_remove_breakpoint(CPUState
*cpu
, int type
, vaddr addr
, vaddr len
)
518 struct hvf_sw_breakpoint
*bp
;
521 if (type
== GDB_BREAKPOINT_SW
) {
522 bp
= hvf_find_sw_breakpoint(cpu
, addr
);
527 if (bp
->use_count
> 1) {
532 err
= hvf_arch_remove_sw_breakpoint(cpu
, bp
);
537 QTAILQ_REMOVE(&hvf_state
->hvf_sw_breakpoints
, bp
, entry
);
540 err
= hvf_arch_remove_hw_breakpoint(addr
, len
, type
);
547 err
= hvf_update_guest_debug(cpu
);
555 static void hvf_remove_all_breakpoints(CPUState
*cpu
)
557 struct hvf_sw_breakpoint
*bp
, *next
;
560 QTAILQ_FOREACH_SAFE(bp
, &hvf_state
->hvf_sw_breakpoints
, entry
, next
) {
561 if (hvf_arch_remove_sw_breakpoint(cpu
, bp
) != 0) {
562 /* Try harder to find a CPU that currently sees the breakpoint. */
565 if (hvf_arch_remove_sw_breakpoint(tmpcpu
, bp
) == 0) {
570 QTAILQ_REMOVE(&hvf_state
->hvf_sw_breakpoints
, bp
, entry
);
573 hvf_arch_remove_all_hw_breakpoints();
576 hvf_update_guest_debug(cpu
);
580 static void hvf_accel_ops_class_init(ObjectClass
*oc
, void *data
)
582 AccelOpsClass
*ops
= ACCEL_OPS_CLASS(oc
);
584 ops
->create_vcpu_thread
= hvf_start_vcpu_thread
;
585 ops
->kick_vcpu_thread
= hvf_kick_vcpu_thread
;
587 ops
->synchronize_post_reset
= hvf_cpu_synchronize_post_reset
;
588 ops
->synchronize_post_init
= hvf_cpu_synchronize_post_init
;
589 ops
->synchronize_state
= hvf_cpu_synchronize_state
;
590 ops
->synchronize_pre_loadvm
= hvf_cpu_synchronize_pre_loadvm
;
592 ops
->insert_breakpoint
= hvf_insert_breakpoint
;
593 ops
->remove_breakpoint
= hvf_remove_breakpoint
;
594 ops
->remove_all_breakpoints
= hvf_remove_all_breakpoints
;
595 ops
->update_guest_debug
= hvf_update_guest_debug
;
596 ops
->supports_guest_debug
= hvf_arch_supports_guest_debug
;
598 static const TypeInfo hvf_accel_ops_type
= {
599 .name
= ACCEL_OPS_NAME("hvf"),
601 .parent
= TYPE_ACCEL_OPS
,
602 .class_init
= hvf_accel_ops_class_init
,
605 static void hvf_accel_ops_register_types(void)
607 type_register_static(&hvf_accel_ops_type
);
609 type_init(hvf_accel_ops_register_types
);