* "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:
Peter Maydell 2017-03-14 16:52:17 +00:00
commit 64c358a33a
35 changed files with 274 additions and 65 deletions

View File

@ -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
View File

@ -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

View File

@ -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
View File

@ -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();
}

View File

@ -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
View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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"

View File

@ -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) {

View File

@ -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.
*/

View File

@ -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);

View File

@ -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 */

View File

@ -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);

View File

@ -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"

View File

@ -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);
}

View File

@ -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"

View File

@ -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));

View File

@ -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.

View File

@ -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"

View File

@ -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):

View File

@ -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();
}

View File

@ -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"

View File

@ -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

View File

@ -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 */

View File

@ -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);

View File

@ -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) {

View File

@ -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 */

View File

@ -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);
}

View File

@ -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) {

View File

@ -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);
}

View File

@ -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();

View File

@ -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"

View File

@ -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
View File

@ -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