mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-27 13:30:52 +00:00
* "x" monitor command fix for KVM (Christian)
* MemoryRegion name documentation (David) * mem-prealloc optimization (Jitendra) * -icount/MTTCG fixes (me) * "info mtree" niceness (Peter) * NBD drop_sync buffer overflow (Vladimir/Eric) * small cleanups and bugfixes (Li, Lin, Suramya, Thomas) * fix for "-device kvmclock" w/TCG (Eduardo) * debug output before crashing on KVM_{GET,SET}_MSRS (Eduardo) -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQExBAABCAAbBQJYx/MtFBxwYm9uemluaUByZWRoYXQuY29tAAoJEL/70l94x66D /C0IAJwQzC+pVyCDLtuuVyIxmPkJKoYTo2l5NpnkbE2yPD2GgfRS+uOoPBWaqy9I lYh1cAwsYV62zdI8DoaVfFvYoiZE36JYTQ9lEUaYLOrtuR1dBOB9f7BEmWkOxmEk SuyUKzJRhIlaTueX+HwJ/cxSR5XlqUt3Vx27rqmeNZedqRAmXF1iu5B0EKA5INvd jOLiTpQqUP9LqbjJ+cFNMT++JlaMND0T7hBFhiAFIzK3kRU1veqMUGpGye3jCBNN FKNnFYJCj/NdJu5NlfU7AR1a2iLQVRzltlMucm6e7DkYjHDA5zR+b5uosR2JiBRJ r6kMY17+aoI0Lyff53ZA4eWvD+E= =uv4K -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging * "x" monitor command fix for KVM (Christian) * MemoryRegion name documentation (David) * mem-prealloc optimization (Jitendra) * -icount/MTTCG fixes (me) * "info mtree" niceness (Peter) * NBD drop_sync buffer overflow (Vladimir/Eric) * small cleanups and bugfixes (Li, Lin, Suramya, Thomas) * fix for "-device kvmclock" w/TCG (Eduardo) * debug output before crashing on KVM_{GET,SET}_MSRS (Eduardo) # gpg: Signature made Tue 14 Mar 2017 13:42:05 GMT # gpg: using RSA key 0xBFFBD25F78C7AE83 # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * remotes/bonzini/tags/for-upstream: nbd/client: fix drop_sync [CVE-2017-2630] memory: info mtree check mr range overflow icount: process QEMU_CLOCK_VIRTUAL timers in vCPU thread main-loop: remove now unnecessary optimization cpus: define QEMUTimerListNotifyCB for QEMU system emulation qemu-timer: do not include sysemu/cpus.h from util/qemu-timer.h qemu-timer: fix off-by-one target/nios2: take BQL around interrupt check scsi: mptsas: fix the wrong reading size in fetch request util: Removed unneeded header from path.c configure: add the missing help output for optional features scripts/dump-guest-memory.py: fix int128_get64 on recent gcc kvmclock: Don't crash QEMU if KVM is disabled kvm: Print MSR information if KVM_{GET,SET}_MSRS failed exec: add cpu_synchronize_state to cpu_memory_rw_debug mem-prealloc: reduce large guest start-up and migration time. docs: Add a note about mixing bootindex with "-boot order" memory_region: Fix name comments Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
64c358a33a
@ -224,7 +224,7 @@ static void host_memory_backend_set_prealloc(Object *obj, bool value,
|
||||
void *ptr = memory_region_get_ram_ptr(&backend->mr);
|
||||
uint64_t sz = memory_region_size(&backend->mr);
|
||||
|
||||
os_mem_prealloc(fd, ptr, sz, &local_err);
|
||||
os_mem_prealloc(fd, ptr, sz, smp_cpus, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
@ -328,7 +328,7 @@ host_memory_backend_memory_complete(UserCreatable *uc, Error **errp)
|
||||
*/
|
||||
if (backend->prealloc) {
|
||||
os_mem_prealloc(memory_region_get_fd(&backend->mr), ptr, sz,
|
||||
&local_err);
|
||||
smp_cpus, &local_err);
|
||||
if (local_err) {
|
||||
goto out;
|
||||
}
|
||||
|
12
configure
vendored
12
configure
vendored
@ -1330,6 +1330,12 @@ Advanced options (experts only):
|
||||
--with-vss-sdk=SDK-path enable Windows VSS support in QEMU Guest Agent
|
||||
--with-win-sdk=SDK-path path to Windows Platform SDK (to build VSS .tlb)
|
||||
--tls-priority default TLS protocol/cipher priority string
|
||||
--enable-gprof QEMU profiling with gprof
|
||||
--enable-profiler profiler support
|
||||
--enable-xen-pv-domain-build
|
||||
xen pv domain builder
|
||||
--enable-debug-stack-usage
|
||||
track the maximum stack usage of stacks created by qemu_alloc_stack
|
||||
|
||||
Optional features, enabled with --enable-FEATURE and
|
||||
disabled with --disable-FEATURE, default is enabled if available:
|
||||
@ -1397,6 +1403,12 @@ disabled with --disable-FEATURE, default is enabled if available:
|
||||
tcmalloc tcmalloc support
|
||||
jemalloc jemalloc support
|
||||
replication replication support
|
||||
vhost-vsock virtio sockets device support
|
||||
opengl opengl support
|
||||
virglrenderer virgl rendering support
|
||||
xfsctl xfsctl support
|
||||
qom-cast-debug cast debugging support
|
||||
tools build qemu-io, qemu-nbd and qemu-image tools
|
||||
|
||||
NOTE: The object files are built at the place where configure is launched
|
||||
EOF
|
||||
|
@ -33,6 +33,7 @@
|
||||
#if defined(TARGET_I386) && !defined(CONFIG_USER_ONLY)
|
||||
#include "hw/i386/apic.h"
|
||||
#endif
|
||||
#include "sysemu/cpus.h"
|
||||
#include "sysemu/replay.h"
|
||||
|
||||
/* -icount align implementation. */
|
||||
|
31
cpus.c
31
cpus.c
@ -800,6 +800,27 @@ static void qemu_cpu_kick_rr_cpu(void)
|
||||
} while (cpu != atomic_mb_read(&tcg_current_rr_cpu));
|
||||
}
|
||||
|
||||
static void do_nothing(CPUState *cpu, run_on_cpu_data unused)
|
||||
{
|
||||
}
|
||||
|
||||
void qemu_timer_notify_cb(void *opaque, QEMUClockType type)
|
||||
{
|
||||
if (!use_icount || type != QEMU_CLOCK_VIRTUAL) {
|
||||
qemu_notify_event();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!qemu_in_vcpu_thread() && first_cpu) {
|
||||
/* qemu_cpu_kick is not enough to kick a halted CPU out of
|
||||
* qemu_tcg_wait_io_event. async_run_on_cpu, instead,
|
||||
* causes cpu_thread_is_idle to return false. This way,
|
||||
* handle_icount_deadline can run.
|
||||
*/
|
||||
async_run_on_cpu(first_cpu, do_nothing, RUN_ON_CPU_NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void kick_tcg_thread(void *opaque)
|
||||
{
|
||||
timer_mod(tcg_kick_vcpu_timer, qemu_tcg_next_kick());
|
||||
@ -1145,12 +1166,15 @@ static int64_t tcg_get_icount_limit(void)
|
||||
|
||||
static void handle_icount_deadline(void)
|
||||
{
|
||||
assert(qemu_in_vcpu_thread());
|
||||
if (use_icount) {
|
||||
int64_t deadline =
|
||||
qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
|
||||
|
||||
if (deadline == 0) {
|
||||
/* Wake up other AioContexts. */
|
||||
qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
|
||||
qemu_clock_run_timers(QEMU_CLOCK_VIRTUAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1263,6 +1287,11 @@ static void *qemu_tcg_rr_cpu_thread_fn(void *arg)
|
||||
/* Account partial waits to QEMU_CLOCK_VIRTUAL. */
|
||||
qemu_account_warp_timer();
|
||||
|
||||
/* Run the timers here. This is much more efficient than
|
||||
* waking up the I/O thread and waiting for completion.
|
||||
*/
|
||||
handle_icount_deadline();
|
||||
|
||||
if (!cpu) {
|
||||
cpu = first_cpu;
|
||||
}
|
||||
@ -1304,8 +1333,6 @@ static void *qemu_tcg_rr_cpu_thread_fn(void *arg)
|
||||
atomic_mb_set(&cpu->exit_request, 0);
|
||||
}
|
||||
|
||||
handle_icount_deadline();
|
||||
|
||||
qemu_tcg_wait_io_event(cpu ? cpu : QTAILQ_FIRST(&cpus));
|
||||
deal_with_unplugged_cpus();
|
||||
}
|
||||
|
@ -41,3 +41,12 @@ has three bootable devices target1, target3, target5 connected to it,
|
||||
the option ROM will have a boot method for each of them, but it is not
|
||||
possible to map from boot method back to a specific target. This is a
|
||||
shortcoming of the PC BIOS boot specification.
|
||||
|
||||
== Mixing bootindex and boot order parameters ==
|
||||
|
||||
Note that it does not make sense to use the bootindex property together
|
||||
with the "-boot order=..." (or "-boot once=...") parameter. The guest
|
||||
firmware implementations normally either support the one or the other,
|
||||
but not both parameters at the same time. Mixing them will result in
|
||||
undefined behavior, and thus the guest firmware will likely not boot
|
||||
from the expected devices.
|
||||
|
4
exec.c
4
exec.c
@ -43,6 +43,7 @@
|
||||
#include "exec/ioport.h"
|
||||
#include "sysemu/dma.h"
|
||||
#include "sysemu/numa.h"
|
||||
#include "sysemu/hw_accel.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "sysemu/xen-mapcache.h"
|
||||
#include "trace-root.h"
|
||||
@ -1467,7 +1468,7 @@ static void *file_ram_alloc(RAMBlock *block,
|
||||
}
|
||||
|
||||
if (mem_prealloc) {
|
||||
os_mem_prealloc(fd, area, memory, errp);
|
||||
os_mem_prealloc(fd, area, memory, smp_cpus, errp);
|
||||
if (errp && *errp) {
|
||||
goto error;
|
||||
}
|
||||
@ -3309,6 +3310,7 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
|
||||
hwaddr phys_addr;
|
||||
target_ulong page;
|
||||
|
||||
cpu_synchronize_state(cpu);
|
||||
while (len > 0) {
|
||||
int asidx;
|
||||
MemTxAttrs attrs;
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "sysemu/replay.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "block/aio.h"
|
||||
#include "sysemu/cpus.h"
|
||||
|
||||
#define DELTA_ADJUST 1
|
||||
#define DELTA_NO_ADJUST -1
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "kvm_i386.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/kvm/clock.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
#include <linux/kvm.h>
|
||||
#include <linux/kvm_para.h>
|
||||
@ -208,6 +209,11 @@ static void kvmclock_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
KVMClockState *s = KVM_CLOCK(dev);
|
||||
|
||||
if (!kvm_enabled()) {
|
||||
error_setg(errp, "kvmclock device requires KVM");
|
||||
return;
|
||||
}
|
||||
|
||||
kvm_update_clock(s);
|
||||
|
||||
qemu_add_vm_change_state_handler(kvmclock_vm_state_change, s);
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "qapi/error.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/numa.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "hw/hw.h"
|
||||
#include "target/ppc/cpu.h"
|
||||
#include "qemu/log.h"
|
||||
|
@ -756,7 +756,7 @@ static void mptsas_fetch_request(MPTSASState *s)
|
||||
|
||||
/* Read the message header from the guest first. */
|
||||
addr = s->host_mfa_high_addr | MPTSAS_FIFO_GET(s, request_post);
|
||||
pci_dma_read(pci, addr, req, sizeof(hdr));
|
||||
pci_dma_read(pci, addr, req, sizeof(*hdr));
|
||||
|
||||
if (hdr->Function < ARRAY_SIZE(mpi_request_sizes) &&
|
||||
mpi_request_sizes[hdr->Function]) {
|
||||
@ -766,8 +766,8 @@ static void mptsas_fetch_request(MPTSASState *s)
|
||||
*/
|
||||
size = mpi_request_sizes[hdr->Function];
|
||||
assert(size <= MPTSAS_MAX_REQUEST_SIZE);
|
||||
pci_dma_read(pci, addr + sizeof(hdr), &req[sizeof(hdr)],
|
||||
size - sizeof(hdr));
|
||||
pci_dma_read(pci, addr + sizeof(*hdr), &req[sizeof(*hdr)],
|
||||
size - sizeof(*hdr));
|
||||
}
|
||||
|
||||
if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
|
||||
|
@ -371,7 +371,8 @@ void memory_region_init_io(MemoryRegion *mr,
|
||||
*
|
||||
* @mr: the #MemoryRegion to be initialized.
|
||||
* @owner: the object that tracks the region's reference count
|
||||
* @name: the name of the region.
|
||||
* @name: Region name, becomes part of RAMBlock name used in migration stream
|
||||
* must be unique within any device
|
||||
* @size: size of the region.
|
||||
* @errp: pointer to Error*, to store an error if it happens.
|
||||
*/
|
||||
@ -390,7 +391,8 @@ void memory_region_init_ram(MemoryRegion *mr,
|
||||
*
|
||||
* @mr: the #MemoryRegion to be initialized.
|
||||
* @owner: the object that tracks the region's reference count
|
||||
* @name: the name of the region.
|
||||
* @name: Region name, becomes part of RAMBlock name used in migration stream
|
||||
* must be unique within any device
|
||||
* @size: used size of the region.
|
||||
* @max_size: max size of the region.
|
||||
* @resized: callback to notify owner about used size change.
|
||||
@ -412,7 +414,8 @@ void memory_region_init_resizeable_ram(MemoryRegion *mr,
|
||||
*
|
||||
* @mr: the #MemoryRegion to be initialized.
|
||||
* @owner: the object that tracks the region's reference count
|
||||
* @name: the name of the region.
|
||||
* @name: Region name, becomes part of RAMBlock name used in migration stream
|
||||
* must be unique within any device
|
||||
* @size: size of the region.
|
||||
* @share: %true if memory must be mmaped with the MAP_SHARED flag
|
||||
* @path: the path in which to allocate the RAM.
|
||||
@ -434,7 +437,8 @@ void memory_region_init_ram_from_file(MemoryRegion *mr,
|
||||
*
|
||||
* @mr: the #MemoryRegion to be initialized.
|
||||
* @owner: the object that tracks the region's reference count
|
||||
* @name: the name of the region.
|
||||
* @name: Region name, becomes part of RAMBlock name used in migration stream
|
||||
* must be unique within any device
|
||||
* @size: size of the region.
|
||||
* @ptr: memory to be mapped; must contain at least @size bytes.
|
||||
*/
|
||||
@ -496,7 +500,8 @@ void memory_region_init_alias(MemoryRegion *mr,
|
||||
*
|
||||
* @mr: the #MemoryRegion to be initialized.
|
||||
* @owner: the object that tracks the region's reference count
|
||||
* @name: the name of the region.
|
||||
* @name: Region name, becomes part of RAMBlock name used in migration stream
|
||||
* must be unique within any device
|
||||
* @size: size of the region.
|
||||
* @errp: pointer to Error*, to store an error if it happens.
|
||||
*/
|
||||
@ -513,7 +518,8 @@ void memory_region_init_rom(MemoryRegion *mr,
|
||||
* @mr: the #MemoryRegion to be initialized.
|
||||
* @owner: the object that tracks the region's reference count
|
||||
* @ops: callbacks for write access handling (must not be NULL).
|
||||
* @name: the name of the region.
|
||||
* @name: Region name, becomes part of RAMBlock name used in migration stream
|
||||
* must be unique within any device
|
||||
* @size: size of the region.
|
||||
* @errp: pointer to Error*, to store an error if it happens.
|
||||
*/
|
||||
|
@ -438,7 +438,8 @@ unsigned long qemu_getauxval(unsigned long type);
|
||||
|
||||
void qemu_set_tty_echo(int fd, bool echo);
|
||||
|
||||
void os_mem_prealloc(int fd, char *area, size_t sz, Error **errp);
|
||||
void os_mem_prealloc(int fd, char *area, size_t sz, int smp_cpus,
|
||||
Error **errp);
|
||||
|
||||
int qemu_read_password(char *buf, int buf_size);
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/notify.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "sysemu/cpus.h"
|
||||
|
||||
#define NANOSECONDS_PER_SECOND 1000000000LL
|
||||
|
||||
@ -60,7 +59,7 @@ struct QEMUTimerListGroup {
|
||||
};
|
||||
|
||||
typedef void QEMUTimerCB(void *opaque);
|
||||
typedef void QEMUTimerListNotifyCB(void *opaque);
|
||||
typedef void QEMUTimerListNotifyCB(void *opaque, QEMUClockType type);
|
||||
|
||||
struct QEMUTimer {
|
||||
int64_t expire_time; /* in nanoseconds */
|
||||
@ -534,6 +533,12 @@ static inline QEMUTimer *timer_new_tl(QEMUTimerList *timer_list,
|
||||
* Create a new timer and associate it with the default
|
||||
* timer list for the clock type @type.
|
||||
*
|
||||
* The default timer list has one special feature: in icount mode,
|
||||
* %QEMU_CLOCK_VIRTUAL timers are run in the vCPU thread. This is
|
||||
* not true of other timer lists, which are typically associated
|
||||
* with an AioContext---each of them runs its timer callbacks in its own
|
||||
* AioContext thread.
|
||||
*
|
||||
* Returns: a pointer to the timer
|
||||
*/
|
||||
static inline QEMUTimer *timer_new(QEMUClockType type, int scale,
|
||||
@ -551,6 +556,12 @@ static inline QEMUTimer *timer_new(QEMUClockType type, int scale,
|
||||
* Create a new timer with nanosecond scale on the default timer list
|
||||
* associated with the clock.
|
||||
*
|
||||
* The default timer list has one special feature: in icount mode,
|
||||
* %QEMU_CLOCK_VIRTUAL timers are run in the vCPU thread. This is
|
||||
* not true of other timer lists, which are typically associated
|
||||
* with an AioContext---each of them runs its timer callbacks in its own
|
||||
* AioContext thread.
|
||||
*
|
||||
* Returns: a pointer to the newly created timer
|
||||
*/
|
||||
static inline QEMUTimer *timer_new_ns(QEMUClockType type, QEMUTimerCB *cb,
|
||||
@ -565,6 +576,12 @@ static inline QEMUTimer *timer_new_ns(QEMUClockType type, QEMUTimerCB *cb,
|
||||
* @cb: the callback to call when the timer expires
|
||||
* @opaque: the opaque pointer to pass to the callback
|
||||
*
|
||||
* The default timer list has one special feature: in icount mode,
|
||||
* %QEMU_CLOCK_VIRTUAL timers are run in the vCPU thread. This is
|
||||
* not true of other timer lists, which are typically associated
|
||||
* with an AioContext---each of them runs its timer callbacks in its own
|
||||
* AioContext thread.
|
||||
*
|
||||
* Create a new timer with microsecond scale on the default timer list
|
||||
* associated with the clock.
|
||||
*
|
||||
@ -582,6 +599,12 @@ static inline QEMUTimer *timer_new_us(QEMUClockType type, QEMUTimerCB *cb,
|
||||
* @cb: the callback to call when the timer expires
|
||||
* @opaque: the opaque pointer to pass to the callback
|
||||
*
|
||||
* The default timer list has one special feature: in icount mode,
|
||||
* %QEMU_CLOCK_VIRTUAL timers are run in the vCPU thread. This is
|
||||
* not true of other timer lists, which are typically associated
|
||||
* with an AioContext---each of them runs its timer callbacks in its own
|
||||
* AioContext thread.
|
||||
*
|
||||
* Create a new timer with millisecond scale on the default timer list
|
||||
* associated with the clock.
|
||||
*
|
||||
@ -777,7 +800,7 @@ static inline int64_t qemu_soonest_timeout(int64_t timeout1, int64_t timeout2)
|
||||
*
|
||||
* Initialise the clock & timer infrastructure
|
||||
*/
|
||||
void init_clocks(void);
|
||||
void init_clocks(QEMUTimerListNotifyCB *notify_cb);
|
||||
|
||||
int64_t cpu_get_ticks(void);
|
||||
/* Caller must hold BQL */
|
||||
|
@ -1,6 +1,8 @@
|
||||
#ifndef QEMU_CPUS_H
|
||||
#define QEMU_CPUS_H
|
||||
|
||||
#include "qemu/timer.h"
|
||||
|
||||
/* cpus.c */
|
||||
bool qemu_in_vcpu_thread(void);
|
||||
void qemu_init_cpu_loop(void);
|
||||
@ -20,6 +22,7 @@ void dump_drift_info(FILE *f, fprintf_function cpu_fprintf);
|
||||
|
||||
/* Unblock cpu */
|
||||
void qemu_cpu_kick_self(void);
|
||||
void qemu_timer_notify_cb(void *opaque, QEMUClockType type);
|
||||
|
||||
void cpu_synchronize_all_states(void);
|
||||
void cpu_synchronize_all_post_reset(void);
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "hw/s390x/adapter.h"
|
||||
#include "exec/gdbstub.h"
|
||||
#include "sysemu/kvm_int.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "qemu/bswap.h"
|
||||
#include "exec/memory.h"
|
||||
#include "exec/ram_addr.h"
|
||||
|
21
memory.c
21
memory.c
@ -2494,6 +2494,7 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f,
|
||||
MemoryRegionListHead submr_print_queue;
|
||||
const MemoryRegion *submr;
|
||||
unsigned int i;
|
||||
hwaddr cur_start, cur_end;
|
||||
|
||||
if (!mr) {
|
||||
return;
|
||||
@ -2503,6 +2504,18 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f,
|
||||
mon_printf(f, MTREE_INDENT);
|
||||
}
|
||||
|
||||
cur_start = base + mr->addr;
|
||||
cur_end = cur_start + MR_SIZE(mr->size);
|
||||
|
||||
/*
|
||||
* Try to detect overflow of memory region. This should never
|
||||
* happen normally. When it happens, we dump something to warn the
|
||||
* user who is observing this.
|
||||
*/
|
||||
if (cur_start < base || cur_end < cur_start) {
|
||||
mon_printf(f, "[DETECTED OVERFLOW!] ");
|
||||
}
|
||||
|
||||
if (mr->alias) {
|
||||
MemoryRegionList *ml;
|
||||
bool found = false;
|
||||
@ -2522,8 +2535,7 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f,
|
||||
mon_printf(f, TARGET_FMT_plx "-" TARGET_FMT_plx
|
||||
" (prio %d, %s): alias %s @%s " TARGET_FMT_plx
|
||||
"-" TARGET_FMT_plx "%s\n",
|
||||
base + mr->addr,
|
||||
base + mr->addr + MR_SIZE(mr->size),
|
||||
cur_start, cur_end,
|
||||
mr->priority,
|
||||
memory_region_type((MemoryRegion *)mr),
|
||||
memory_region_name(mr),
|
||||
@ -2534,8 +2546,7 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f,
|
||||
} else {
|
||||
mon_printf(f,
|
||||
TARGET_FMT_plx "-" TARGET_FMT_plx " (prio %d, %s): %s%s\n",
|
||||
base + mr->addr,
|
||||
base + mr->addr + MR_SIZE(mr->size),
|
||||
cur_start, cur_end,
|
||||
mr->priority,
|
||||
memory_region_type((MemoryRegion *)mr),
|
||||
memory_region_name(mr),
|
||||
@ -2562,7 +2573,7 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f,
|
||||
}
|
||||
|
||||
QTAILQ_FOREACH(ml, &submr_print_queue, queue) {
|
||||
mtree_print_mr(mon_printf, f, ml->mr, level + 1, base + mr->addr,
|
||||
mtree_print_mr(mon_printf, f, ml->mr, level + 1, cur_start,
|
||||
alias_print_queue);
|
||||
}
|
||||
|
||||
|
@ -77,6 +77,7 @@
|
||||
#include "qapi-event.h"
|
||||
#include "qmp-introspect.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qapi/qmp/dispatch.h"
|
||||
|
||||
|
@ -94,7 +94,7 @@ static ssize_t drop_sync(QIOChannel *ioc, size_t size)
|
||||
char small[1024];
|
||||
char *buffer;
|
||||
|
||||
buffer = sizeof(small) < size ? small : g_malloc(MIN(65536, size));
|
||||
buffer = sizeof(small) >= size ? small : g_malloc(MIN(65536, size));
|
||||
while (size > 0) {
|
||||
ssize_t count = read_sync(ioc, buffer, MIN(65536, size));
|
||||
|
||||
|
@ -252,7 +252,10 @@ drive letters depend on the target architecture. The x86 PC uses: a, b
|
||||
(floppy 1 and 2), c (first hard disk), d (first CD-ROM), n-p (Etherboot
|
||||
from network adapter 1-4), hard disk boot is the default. To apply a
|
||||
particular boot order only on the first startup, specify it via
|
||||
@option{once}.
|
||||
@option{once}. Note that the @option{order} or @option{once} parameter
|
||||
should not be used together with the @option{bootindex} property of
|
||||
devices, since the firmware implementations normally do not support both
|
||||
at the same time.
|
||||
|
||||
Interactive boot menus/prompts can be enabled via @option{menu=on} as far
|
||||
as firmware/BIOS supports them. The default is non-interactive boot.
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "replay-internal.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
|
@ -314,8 +314,18 @@ def get_arch_phdr(endianness, elfclass):
|
||||
def int128_get64(val):
|
||||
"""Returns low 64bit part of Int128 struct."""
|
||||
|
||||
assert val["hi"] == 0
|
||||
return val["lo"]
|
||||
try:
|
||||
assert val["hi"] == 0
|
||||
return val["lo"]
|
||||
except gdb.error:
|
||||
u64t = gdb.lookup_type('uint64_t').array(2)
|
||||
u64 = val.cast(u64t)
|
||||
if sys.byteorder == 'little':
|
||||
assert u64[1] == 0
|
||||
return u64[0]
|
||||
else:
|
||||
assert u64[0] == 0
|
||||
return u64[1]
|
||||
|
||||
|
||||
def qlist_foreach(head, field_str):
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "qemu/main-loop.h"
|
||||
|
||||
int use_icount;
|
||||
|
||||
@ -9,3 +10,8 @@ int64_t cpu_get_icount(void)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
void qemu_timer_notify_cb(void *opaque, QEMUClockType type)
|
||||
{
|
||||
qemu_notify_event();
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "disas/disas.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "exec/exec-all.h"
|
||||
|
@ -1824,6 +1824,12 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ret < cpu->kvm_msr_buf->nmsrs) {
|
||||
struct kvm_msr_entry *e = &cpu->kvm_msr_buf->entries[ret];
|
||||
error_report("error: failed to set MSR 0x%" PRIx32 " to 0x%" PRIx64,
|
||||
(uint32_t)e->index, (uint64_t)e->data);
|
||||
}
|
||||
|
||||
assert(ret == cpu->kvm_msr_buf->nmsrs);
|
||||
return 0;
|
||||
}
|
||||
@ -2189,6 +2195,12 @@ static int kvm_get_msrs(X86CPU *cpu)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ret < cpu->kvm_msr_buf->nmsrs) {
|
||||
struct kvm_msr_entry *e = &cpu->kvm_msr_buf->entries[ret];
|
||||
error_report("error: failed to get MSR 0x%" PRIx32,
|
||||
(uint32_t)e->index);
|
||||
}
|
||||
|
||||
assert(ret == cpu->kvm_msr_buf->nmsrs);
|
||||
/*
|
||||
* MTRR masks: Each mask consists of 5 parts
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "cpu.h"
|
||||
#include "exec/helper-proto.h"
|
||||
#include "exec/cpu_ldst.h"
|
||||
#include "qemu/main-loop.h"
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
void helper_mmu_read_debug(CPUNios2State *env, uint32_t rn)
|
||||
@ -35,7 +36,9 @@ void helper_mmu_write(CPUNios2State *env, uint32_t rn, uint32_t v)
|
||||
|
||||
void helper_check_interrupts(CPUNios2State *env)
|
||||
{
|
||||
qemu_mutex_lock_iothread();
|
||||
nios2_check_interrupts(env);
|
||||
qemu_mutex_unlock_iothread();
|
||||
}
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
||||
|
@ -438,7 +438,7 @@ static void test_multi_mutex_10(void)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
init_clocks();
|
||||
init_clocks(NULL);
|
||||
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
g_test_add_func("/aio/multi/lifecycle", test_lifecycle);
|
||||
|
@ -835,7 +835,7 @@ int main(int argc, char **argv)
|
||||
Error *local_error = NULL;
|
||||
GSource *src;
|
||||
|
||||
init_clocks();
|
||||
init_clocks(NULL);
|
||||
|
||||
ctx = aio_context_new(&local_error);
|
||||
if (!ctx) {
|
||||
|
@ -57,6 +57,7 @@
|
||||
#include "qemu/timer.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "exec/log.h"
|
||||
#include "sysemu/cpus.h"
|
||||
|
||||
/* #define DEBUG_TB_INVALIDATE */
|
||||
/* #define DEBUG_TB_FLUSH */
|
||||
|
@ -351,7 +351,7 @@ void aio_notify_accept(AioContext *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
static void aio_timerlist_notify(void *opaque)
|
||||
static void aio_timerlist_notify(void *opaque, QEMUClockType type)
|
||||
{
|
||||
aio_notify(opaque);
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "qemu/timer.h"
|
||||
#include "qemu/sockets.h" // struct in_addr needed for libslirp.h
|
||||
#include "sysemu/qtest.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "slirp/libslirp.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "block/aio.h"
|
||||
@ -143,7 +144,7 @@ int qemu_init_main_loop(Error **errp)
|
||||
GSource *src;
|
||||
Error *local_error = NULL;
|
||||
|
||||
init_clocks();
|
||||
init_clocks(qemu_timer_notify_cb);
|
||||
|
||||
ret = qemu_signal_init();
|
||||
if (ret) {
|
||||
|
@ -55,6 +55,21 @@
|
||||
#include "qemu/error-report.h"
|
||||
#endif
|
||||
|
||||
#define MAX_MEM_PREALLOC_THREAD_COUNT (MIN(sysconf(_SC_NPROCESSORS_ONLN), 16))
|
||||
|
||||
struct MemsetThread {
|
||||
char *addr;
|
||||
uint64_t numpages;
|
||||
uint64_t hpagesize;
|
||||
QemuThread pgthread;
|
||||
sigjmp_buf env;
|
||||
};
|
||||
typedef struct MemsetThread MemsetThread;
|
||||
|
||||
static MemsetThread *memset_thread;
|
||||
static int memset_num_threads;
|
||||
static bool memset_thread_failed;
|
||||
|
||||
int qemu_get_thread_id(void)
|
||||
{
|
||||
#if defined(__linux__)
|
||||
@ -316,18 +331,83 @@ char *qemu_get_exec_dir(void)
|
||||
return g_strdup(exec_dir);
|
||||
}
|
||||
|
||||
static sigjmp_buf sigjump;
|
||||
|
||||
static void sigbus_handler(int signal)
|
||||
{
|
||||
siglongjmp(sigjump, 1);
|
||||
int i;
|
||||
if (memset_thread) {
|
||||
for (i = 0; i < memset_num_threads; i++) {
|
||||
if (qemu_thread_is_self(&memset_thread[i].pgthread)) {
|
||||
siglongjmp(memset_thread[i].env, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void os_mem_prealloc(int fd, char *area, size_t memory, Error **errp)
|
||||
static void *do_touch_pages(void *arg)
|
||||
{
|
||||
MemsetThread *memset_args = (MemsetThread *)arg;
|
||||
char *addr = memset_args->addr;
|
||||
uint64_t numpages = memset_args->numpages;
|
||||
uint64_t hpagesize = memset_args->hpagesize;
|
||||
sigset_t set, oldset;
|
||||
int i = 0;
|
||||
|
||||
/* unblock SIGBUS */
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set, SIGBUS);
|
||||
pthread_sigmask(SIG_UNBLOCK, &set, &oldset);
|
||||
|
||||
if (sigsetjmp(memset_args->env, 1)) {
|
||||
memset_thread_failed = true;
|
||||
} else {
|
||||
for (i = 0; i < numpages; i++) {
|
||||
memset(addr, 0, 1);
|
||||
addr += hpagesize;
|
||||
}
|
||||
}
|
||||
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool touch_all_pages(char *area, size_t hpagesize, size_t numpages,
|
||||
int smp_cpus)
|
||||
{
|
||||
uint64_t numpages_per_thread, size_per_thread;
|
||||
char *addr = area;
|
||||
int i = 0;
|
||||
|
||||
memset_thread_failed = false;
|
||||
memset_num_threads = MIN(smp_cpus, MAX_MEM_PREALLOC_THREAD_COUNT);
|
||||
memset_thread = g_new0(MemsetThread, memset_num_threads);
|
||||
numpages_per_thread = (numpages / memset_num_threads);
|
||||
size_per_thread = (hpagesize * numpages_per_thread);
|
||||
for (i = 0; i < memset_num_threads; i++) {
|
||||
memset_thread[i].addr = addr;
|
||||
memset_thread[i].numpages = (i == (memset_num_threads - 1)) ?
|
||||
numpages : numpages_per_thread;
|
||||
memset_thread[i].hpagesize = hpagesize;
|
||||
qemu_thread_create(&memset_thread[i].pgthread, "touch_pages",
|
||||
do_touch_pages, &memset_thread[i],
|
||||
QEMU_THREAD_JOINABLE);
|
||||
addr += size_per_thread;
|
||||
numpages -= numpages_per_thread;
|
||||
}
|
||||
for (i = 0; i < memset_num_threads; i++) {
|
||||
qemu_thread_join(&memset_thread[i].pgthread);
|
||||
}
|
||||
g_free(memset_thread);
|
||||
memset_thread = NULL;
|
||||
|
||||
return memset_thread_failed;
|
||||
}
|
||||
|
||||
void os_mem_prealloc(int fd, char *area, size_t memory, int smp_cpus,
|
||||
Error **errp)
|
||||
{
|
||||
int ret;
|
||||
struct sigaction act, oldact;
|
||||
sigset_t set, oldset;
|
||||
size_t hpagesize = qemu_fd_getpagesize(fd);
|
||||
size_t numpages = DIV_ROUND_UP(memory, hpagesize);
|
||||
|
||||
memset(&act, 0, sizeof(act));
|
||||
act.sa_handler = &sigbus_handler;
|
||||
@ -340,23 +420,10 @@ void os_mem_prealloc(int fd, char *area, size_t memory, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
/* unblock SIGBUS */
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set, SIGBUS);
|
||||
pthread_sigmask(SIG_UNBLOCK, &set, &oldset);
|
||||
|
||||
if (sigsetjmp(sigjump, 1)) {
|
||||
/* touch pages simultaneously */
|
||||
if (touch_all_pages(area, hpagesize, numpages, smp_cpus)) {
|
||||
error_setg(errp, "os_mem_prealloc: Insufficient free host memory "
|
||||
"pages available to allocate guest RAM\n");
|
||||
} else {
|
||||
int i;
|
||||
size_t hpagesize = qemu_fd_getpagesize(fd);
|
||||
size_t numpages = DIV_ROUND_UP(memory, hpagesize);
|
||||
|
||||
/* MAP_POPULATE silently ignores failures */
|
||||
for (i = 0; i < numpages; i++) {
|
||||
memset(area + (hpagesize * i), 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
ret = sigaction(SIGBUS, &oldact, NULL);
|
||||
@ -365,7 +432,6 @@ void os_mem_prealloc(int fd, char *area, size_t memory, Error **errp)
|
||||
perror("os_mem_prealloc: failed to reinstall signal handler");
|
||||
exit(1);
|
||||
}
|
||||
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -541,7 +541,8 @@ int getpagesize(void)
|
||||
return system_info.dwPageSize;
|
||||
}
|
||||
|
||||
void os_mem_prealloc(int fd, char *area, size_t memory, Error **errp)
|
||||
void os_mem_prealloc(int fd, char *area, size_t memory, int smp_cpus,
|
||||
Error **errp)
|
||||
{
|
||||
int i;
|
||||
size_t pagesize = getpagesize();
|
||||
|
@ -6,7 +6,6 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include <sys/param.h>
|
||||
#include <dirent.h>
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/path.h"
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "qemu/timer.h"
|
||||
#include "sysemu/replay.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/cpus.h"
|
||||
|
||||
#ifdef CONFIG_POSIX
|
||||
#include <pthread.h>
|
||||
@ -121,7 +122,7 @@ void timerlist_free(QEMUTimerList *timer_list)
|
||||
g_free(timer_list);
|
||||
}
|
||||
|
||||
static void qemu_clock_init(QEMUClockType type)
|
||||
static void qemu_clock_init(QEMUClockType type, QEMUTimerListNotifyCB *notify_cb)
|
||||
{
|
||||
QEMUClock *clock = qemu_clock_ptr(type);
|
||||
|
||||
@ -133,7 +134,7 @@ static void qemu_clock_init(QEMUClockType type)
|
||||
clock->last = INT64_MIN;
|
||||
QLIST_INIT(&clock->timerlists);
|
||||
notifier_list_init(&clock->reset_notifiers);
|
||||
main_loop_tlg.tl[type] = timerlist_new(type, NULL, NULL);
|
||||
main_loop_tlg.tl[type] = timerlist_new(type, notify_cb, NULL);
|
||||
}
|
||||
|
||||
bool qemu_clock_use_for_deadline(QEMUClockType type)
|
||||
@ -199,7 +200,7 @@ bool timerlist_expired(QEMUTimerList *timer_list)
|
||||
expire_time = timer_list->active_timers->expire_time;
|
||||
qemu_mutex_unlock(&timer_list->active_timers_lock);
|
||||
|
||||
return expire_time < qemu_clock_get_ns(timer_list->clock->type);
|
||||
return expire_time <= qemu_clock_get_ns(timer_list->clock->type);
|
||||
}
|
||||
|
||||
bool qemu_clock_expired(QEMUClockType type)
|
||||
@ -277,7 +278,7 @@ QEMUTimerList *qemu_clock_get_main_loop_timerlist(QEMUClockType type)
|
||||
void timerlist_notify(QEMUTimerList *timer_list)
|
||||
{
|
||||
if (timer_list->notify_cb) {
|
||||
timer_list->notify_cb(timer_list->notify_opaque);
|
||||
timer_list->notify_cb(timer_list->notify_opaque, timer_list->clock->type);
|
||||
} else {
|
||||
qemu_notify_event();
|
||||
}
|
||||
@ -634,11 +635,11 @@ void qemu_clock_unregister_reset_notifier(QEMUClockType type,
|
||||
notifier_remove(notifier);
|
||||
}
|
||||
|
||||
void init_clocks(void)
|
||||
void init_clocks(QEMUTimerListNotifyCB *notify_cb)
|
||||
{
|
||||
QEMUClockType type;
|
||||
for (type = 0; type < QEMU_CLOCK_MAX; type++) {
|
||||
qemu_clock_init(type);
|
||||
qemu_clock_init(type, notify_cb);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PRCTL_PR_SET_TIMERSLACK
|
||||
@ -657,7 +658,9 @@ bool qemu_clock_run_all_timers(void)
|
||||
QEMUClockType type;
|
||||
|
||||
for (type = 0; type < QEMU_CLOCK_MAX; type++) {
|
||||
progress |= qemu_clock_run_timers(type);
|
||||
if (qemu_clock_use_for_deadline(type)) {
|
||||
progress |= qemu_clock_run_timers(type);
|
||||
}
|
||||
}
|
||||
|
||||
return progress;
|
||||
|
5
vl.c
5
vl.c
@ -1888,17 +1888,14 @@ static bool main_loop_should_exit(void)
|
||||
|
||||
static void main_loop(void)
|
||||
{
|
||||
bool nonblocking;
|
||||
int last_io = 0;
|
||||
#ifdef CONFIG_PROFILER
|
||||
int64_t ti;
|
||||
#endif
|
||||
do {
|
||||
nonblocking = tcg_enabled() && last_io > 0;
|
||||
#ifdef CONFIG_PROFILER
|
||||
ti = profile_getclock();
|
||||
#endif
|
||||
last_io = main_loop_wait(nonblocking);
|
||||
main_loop_wait(false);
|
||||
#ifdef CONFIG_PROFILER
|
||||
dev_time += profile_getclock() - ti;
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user