* More uses of RCU_READ_LOCK_GUARD (Dave, myself)

* QOM doc improvments (Greg)
 * Cleanups from the Meson conversion (Marc-André)
 * Support for multiple -accel options (myself)
 * Many x86 machine cleanup (Philippe, myself)
 * tests/migration-test cleanup (Juan)
 * PC machine removal and next round of deprecation (Thomas)
 * kernel-doc integration (Peter, myself)
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iQEcBAABAgAGBQJd+YJGAAoJEL/70l94x66D0YYIAIZpS6i6NYJC8KHCl49fjI7U
 qHDN7MiKYTU+l3i0+iGmQL6XN5ClAY0pXkY5LBFIDpsohHR5f4jdrIKjyvcHzuIM
 gx/NLsiA45/niHYrn/hEo0P7CwGTrrdWL+SVmScnKcwYiBzMO/uYblxlbUBKLPNn
 eGaKQmEkvlUBR9GS6S1+jYg8234ZRZ4+12t5dqqADBQ7Kc0wn6KC5yebIoQxCgVc
 9F5Ezdkl7befrTI7El3EC6aT18bKhIBZIs1PT/hzqzlGFhBuKM7uKDb43Yx8c7XQ
 bk5vzHmblPAgQyK4OETQ+DM745AOk6vBiJZbR9nrDUXWvUkrEXTQZMJKU0FXdlE=
 =hyYX
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging

* More uses of RCU_READ_LOCK_GUARD (Dave, myself)
* QOM doc improvments (Greg)
* Cleanups from the Meson conversion (Marc-André)
* Support for multiple -accel options (myself)
* Many x86 machine cleanup (Philippe, myself)
* tests/migration-test cleanup (Juan)
* PC machine removal and next round of deprecation (Thomas)
* kernel-doc integration (Peter, myself)

# gpg: Signature made Wed 18 Dec 2019 01:35:02 GMT
# gpg:                using RSA key BFFBD25F78C7AE83
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full]
# gpg:                 aka "Paolo Bonzini <pbonzini@redhat.com>" [full]
# 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: (87 commits)
  vga: cleanup mapping of VRAM for non-PCI VGA
  hw/display: Remove "rombar" hack from vga-pci and vmware_vga
  hw/pci: Remove the "command_serr_enable" property
  hw/audio: Remove the "use_broken_id" hack from the AC97 device
  hw/i386: Remove the deprecated machines 0.12 up to 0.15
  hw/pci-host: Add Kconfig entry to select the IGD Passthrough Host Bridge
  hw/pci-host/i440fx: Extract the IGD passthrough host bridge device
  hw/pci-host/i440fx: Use definitions instead of magic values
  hw/pci-host/i440fx: Use size_t to iterate over ARRAY_SIZE()
  hw/pci-host/i440fx: Extract PCII440FXState to "hw/pci-host/i440fx.h"
  hw/pci-host/i440fx: Correct the header description
  Fix some comment spelling errors.
  target/i386: remove unused pci-assign codes
  WHPX: refactor load library
  migration: check length directly to make sure the range is aligned
  memory: include MemoryListener documentation and some missing function parameters
  docs: add memory API reference
  memory.h: Silence kernel-doc complaints
  docs: Create bitops.rst as example of kernel-docs
  bitops.h: Silence kernel-doc complaints
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2019-12-20 11:20:25 +00:00
commit 4800819827
133 changed files with 4247 additions and 1551 deletions

View file

@ -25,6 +25,11 @@ config TPM
config VHOST_USER config VHOST_USER
bool bool
select VHOST
config VHOST_KERNEL
bool
select VHOST
config XEN config XEN
bool bool

View file

@ -420,6 +420,7 @@ F: hw/block/dataplane/xen*
F: hw/xen/ F: hw/xen/
F: hw/xenpv/ F: hw/xenpv/
F: hw/i386/xen/ F: hw/i386/xen/
F: hw/pci-host/xen_igd_pt.c
F: include/hw/block/dataplane/xen* F: include/hw/block/dataplane/xen*
F: include/hw/xen/ F: include/hw/xen/
F: include/sysemu/xen-mapcache.h F: include/sysemu/xen-mapcache.h

View file

@ -321,14 +321,10 @@ HELPERS-y =
HELPERS-$(call land,$(CONFIG_SOFTMMU),$(CONFIG_LINUX)) = qemu-bridge-helper$(EXESUF) HELPERS-$(call land,$(CONFIG_SOFTMMU),$(CONFIG_LINUX)) = qemu-bridge-helper$(EXESUF)
ifdef CONFIG_LINUX ifeq ($(CONFIG_LINUX)$(CONFIG_VIRGL)$(CONFIG_GBM)$(CONFIG_TOOLS),yyyy)
ifdef CONFIG_VIRGL
ifdef CONFIG_GBM
HELPERS-y += vhost-user-gpu$(EXESUF) HELPERS-y += vhost-user-gpu$(EXESUF)
vhost-user-json-y += contrib/vhost-user-gpu/50-qemu-gpu.json vhost-user-json-y += contrib/vhost-user-gpu/50-qemu-gpu.json
endif endif
endif
endif
# Sphinx does not allow building manuals into the same directory as # Sphinx does not allow building manuals into the same directory as
# the source files, so if we're doing an in-tree QEMU build we must # the source files, so if we're doing an in-tree QEMU build we must
@ -386,6 +382,7 @@ MINIKCONF_ARGS = \
CONFIG_OPENGL=$(CONFIG_OPENGL) \ CONFIG_OPENGL=$(CONFIG_OPENGL) \
CONFIG_X11=$(CONFIG_X11) \ CONFIG_X11=$(CONFIG_X11) \
CONFIG_VHOST_USER=$(CONFIG_VHOST_USER) \ CONFIG_VHOST_USER=$(CONFIG_VHOST_USER) \
CONFIG_VHOST_KERNEL=$(CONFIG_VHOST_KERNEL) \
CONFIG_VIRTFS=$(CONFIG_VIRTFS) \ CONFIG_VIRTFS=$(CONFIG_VIRTFS) \
CONFIG_LINUX=$(CONFIG_LINUX) \ CONFIG_LINUX=$(CONFIG_LINUX) \
CONFIG_PVRDMA=$(CONFIG_PVRDMA) CONFIG_PVRDMA=$(CONFIG_PVRDMA)
@ -440,15 +437,10 @@ dummy := $(call unnest-vars,, \
block-obj-y \ block-obj-y \
block-obj-m \ block-obj-m \
crypto-obj-y \ crypto-obj-y \
crypto-user-obj-y \
qom-obj-y \ qom-obj-y \
io-obj-y \ io-obj-y \
common-obj-y \ common-obj-y \
common-obj-m \ common-obj-m \
ui-obj-y \
ui-obj-m \
audio-obj-y \
audio-obj-m \
trace-obj-y) trace-obj-y)
include $(SRC_PATH)/tests/Makefile.include include $(SRC_PATH)/tests/Makefile.include
@ -532,7 +524,7 @@ subdir-capstone: capstone/all
subdir-slirp: slirp/all subdir-slirp: slirp/all
$(filter %/all, $(TARGET_DIRS_RULES)): libqemuutil.a $(common-obj-y) \ $(filter %/all, $(TARGET_DIRS_RULES)): libqemuutil.a $(common-obj-y) \
$(qom-obj-y) $(crypto-user-obj-$(CONFIG_USER_ONLY)) $(qom-obj-y)
ROM_DIRS = $(addprefix pc-bios/, $(ROMS)) ROM_DIRS = $(addprefix pc-bios/, $(ROMS))
ROM_DIRS_RULES=$(foreach t, all clean, $(addsuffix /$(t), $(ROM_DIRS))) ROM_DIRS_RULES=$(foreach t, all clean, $(addsuffix /$(t), $(ROM_DIRS)))
@ -1009,7 +1001,7 @@ sphinxdocs: $(MANUAL_BUILDDIR)/devel/index.html $(MANUAL_BUILDDIR)/interop/index
# Note the use of different doctree for each (manual, builder) tuple; # Note the use of different doctree for each (manual, builder) tuple;
# this works around Sphinx not handling parallel invocation on # this works around Sphinx not handling parallel invocation on
# a single doctree: https://github.com/sphinx-doc/sphinx/issues/2946 # a single doctree: https://github.com/sphinx-doc/sphinx/issues/2946
build-manual = $(call quiet-command,CONFDIR="$(qemu_confdir)" sphinx-build $(if $(V),,-q) -W -n -b $2 -D version=$(VERSION) -D release="$(FULL_VERSION)" -d .doctrees/$1-$2 $(SRC_PATH)/docs/$1 $(MANUAL_BUILDDIR)/$1 ,"SPHINX","$(MANUAL_BUILDDIR)/$1") build-manual = $(call quiet-command,CONFDIR="$(qemu_confdir)" sphinx-build $(if $(V),,-q) -W -b $2 -D version=$(VERSION) -D release="$(FULL_VERSION)" -d .doctrees/$1-$2 $(SRC_PATH)/docs/$1 $(MANUAL_BUILDDIR)/$1 ,"SPHINX","$(MANUAL_BUILDDIR)/$1")
# We assume all RST files in the manual's directory are used in it # We assume all RST files in the manual's directory are used in it
manual-deps = $(wildcard $(SRC_PATH)/docs/$1/*.rst) $(SRC_PATH)/docs/$1/conf.py $(SRC_PATH)/docs/conf.py manual-deps = $(wildcard $(SRC_PATH)/docs/$1/*.rst) $(SRC_PATH)/docs/$1/conf.py $(SRC_PATH)/docs/conf.py

View file

@ -1,7 +1,7 @@
####################################################################### #######################################################################
# Common libraries for tools and emulators # Common libraries for tools and emulators
stub-obj-y = stubs/ util/ crypto/ stub-obj-y = stubs/
util-obj-y = util/ qobject/ qapi/ util-obj-y = crypto/ util/ qobject/ qapi/
chardev-obj-y = chardev/ chardev-obj-y = chardev/
@ -25,7 +25,6 @@ block-obj-m = block/
# crypto-obj-y is code used by both qemu system emulation and qemu-img # crypto-obj-y is code used by both qemu system emulation and qemu-img
crypto-obj-y = crypto/ crypto-obj-y = crypto/
crypto-user-obj-y = crypto/
####################################################################### #######################################################################
# qom-obj-y is code used by both qemu system emulation and qemu-img # qom-obj-y is code used by both qemu system emulation and qemu-img
@ -55,6 +54,7 @@ common-obj-$(CONFIG_POSIX) += os-posix.o
common-obj-$(CONFIG_LINUX) += fsdev/ common-obj-$(CONFIG_LINUX) += fsdev/
common-obj-y += accel/
common-obj-y += migration/ common-obj-y += migration/
common-obj-y += audio/ common-obj-y += audio/

View file

@ -184,7 +184,6 @@ dummy := $(call unnest-vars,.., \
block-obj-m \ block-obj-m \
chardev-obj-y \ chardev-obj-y \
crypto-obj-y \ crypto-obj-y \
crypto-user-obj-y \
qom-obj-y \ qom-obj-y \
io-obj-y \ io-obj-y \
common-obj-y \ common-obj-y \
@ -193,7 +192,6 @@ all-obj-y += $(common-obj-y)
all-obj-y += $(qom-obj-y) all-obj-y += $(qom-obj-y)
all-obj-$(CONFIG_SOFTMMU) += $(authz-obj-y) all-obj-$(CONFIG_SOFTMMU) += $(authz-obj-y)
all-obj-$(CONFIG_SOFTMMU) += $(block-obj-y) $(chardev-obj-y) all-obj-$(CONFIG_SOFTMMU) += $(block-obj-y) $(chardev-obj-y)
all-obj-$(CONFIG_USER_ONLY) += $(crypto-user-obj-y)
all-obj-$(CONFIG_SOFTMMU) += $(crypto-obj-y) all-obj-$(CONFIG_SOFTMMU) += $(crypto-obj-y)
all-obj-$(CONFIG_SOFTMMU) += $(io-obj-y) all-obj-$(CONFIG_SOFTMMU) += $(io-obj-y)

View file

@ -1,4 +1,4 @@
obj-$(CONFIG_SOFTMMU) += accel.o common-obj-$(CONFIG_SOFTMMU) += accel.o
obj-$(call land,$(CONFIG_SOFTMMU),$(CONFIG_POSIX)) += qtest.o obj-$(call land,$(CONFIG_SOFTMMU),$(CONFIG_POSIX)) += qtest.o
obj-$(CONFIG_KVM) += kvm/ obj-$(CONFIG_KVM) += kvm/
obj-$(CONFIG_TCG) += tcg/ obj-$(CONFIG_TCG) += tcg/

View file

@ -28,13 +28,7 @@
#include "hw/boards.h" #include "hw/boards.h"
#include "sysemu/arch_init.h" #include "sysemu/arch_init.h"
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
#include "sysemu/kvm.h"
#include "sysemu/qtest.h"
#include "hw/xen/xen.h"
#include "qom/object.h" #include "qom/object.h"
#include "qemu/error-report.h"
#include "qemu/option.h"
#include "qapi/error.h"
static const TypeInfo accel_type = { static const TypeInfo accel_type = {
.name = TYPE_ACCEL, .name = TYPE_ACCEL,
@ -44,7 +38,7 @@ static const TypeInfo accel_type = {
}; };
/* Lookup AccelClass from opt_name. Returns NULL if not found */ /* Lookup AccelClass from opt_name. Returns NULL if not found */
static AccelClass *accel_find(const char *opt_name) AccelClass *accel_find(const char *opt_name)
{ {
char *class_name = g_strdup_printf(ACCEL_CLASS_NAME("%s"), opt_name); char *class_name = g_strdup_printf(ACCEL_CLASS_NAME("%s"), opt_name);
AccelClass *ac = ACCEL_CLASS(object_class_by_name(class_name)); AccelClass *ac = ACCEL_CLASS(object_class_by_name(class_name));
@ -52,11 +46,9 @@ static AccelClass *accel_find(const char *opt_name)
return ac; return ac;
} }
static int accel_init_machine(AccelClass *acc, MachineState *ms) int accel_init_machine(AccelState *accel, MachineState *ms)
{ {
ObjectClass *oc = OBJECT_CLASS(acc); AccelClass *acc = ACCEL_GET_CLASS(accel);
const char *cname = object_class_get_name(oc);
AccelState *accel = ACCEL(object_new(cname));
int ret; int ret;
ms->accelerator = accel; ms->accelerator = accel;
*(acc->allowed) = true; *(acc->allowed) = true;
@ -71,65 +63,6 @@ static int accel_init_machine(AccelClass *acc, MachineState *ms)
return ret; return ret;
} }
void configure_accelerator(MachineState *ms, const char *progname)
{
const char *accel;
char **accel_list, **tmp;
int ret;
bool accel_initialised = false;
bool init_failed = false;
AccelClass *acc = NULL;
accel = qemu_opt_get(qemu_get_machine_opts(), "accel");
if (accel == NULL) {
/* Select the default accelerator */
int pnlen = strlen(progname);
if (pnlen >= 3 && g_str_equal(&progname[pnlen - 3], "kvm")) {
/* If the program name ends with "kvm", we prefer KVM */
accel = "kvm:tcg";
} else {
#if defined(CONFIG_TCG)
accel = "tcg";
#elif defined(CONFIG_KVM)
accel = "kvm";
#else
error_report("No accelerator selected and"
" no default accelerator available");
exit(1);
#endif
}
}
accel_list = g_strsplit(accel, ":", 0);
for (tmp = accel_list; !accel_initialised && tmp && *tmp; tmp++) {
acc = accel_find(*tmp);
if (!acc) {
continue;
}
ret = accel_init_machine(acc, ms);
if (ret < 0) {
init_failed = true;
error_report("failed to initialize %s: %s",
acc->name, strerror(-ret));
} else {
accel_initialised = true;
}
}
g_strfreev(accel_list);
if (!accel_initialised) {
if (!init_failed) {
error_report("-machine accel=%s: No accelerator found", accel);
}
exit(1);
}
if (init_failed) {
error_report("Back to %s accelerator", acc->name);
}
}
void accel_setup_post(MachineState *ms) void accel_setup_post(MachineState *ms)
{ {
AccelState *accel = ms->accelerator; AccelState *accel = ms->accelerator;

View file

@ -41,6 +41,9 @@
#include "hw/irq.h" #include "hw/irq.h"
#include "sysemu/sev.h" #include "sysemu/sev.h"
#include "sysemu/balloon.h" #include "sysemu/balloon.h"
#include "qapi/visitor.h"
#include "qapi/qapi-types-common.h"
#include "qapi/qapi-visit-common.h"
#include "hw/boards.h" #include "hw/boards.h"
@ -92,6 +95,10 @@ struct KVMState
int max_nested_state_len; int max_nested_state_len;
int many_ioeventfds; int many_ioeventfds;
int intx_set_mask; int intx_set_mask;
int kvm_shadow_mem;
bool kernel_irqchip_allowed;
bool kernel_irqchip_required;
bool kernel_irqchip_split;
bool sync_mmu; bool sync_mmu;
bool manual_dirty_log_protect; bool manual_dirty_log_protect;
/* The man page (and posix) say ioctl numbers are signed int, but /* The man page (and posix) say ioctl numbers are signed int, but
@ -518,6 +525,27 @@ static int kvm_get_dirty_pages_log_range(MemoryRegionSection *section,
#define ALIGN(x, y) (((x)+(y)-1) & ~((y)-1)) #define ALIGN(x, y) (((x)+(y)-1) & ~((y)-1))
/* Allocate the dirty bitmap for a slot */
static void kvm_memslot_init_dirty_bitmap(KVMSlot *mem)
{
/*
* XXX bad kernel interface alert
* For dirty bitmap, kernel allocates array of size aligned to
* bits-per-long. But for case when the kernel is 64bits and
* the userspace is 32bits, userspace can't align to the same
* bits-per-long, since sizeof(long) is different between kernel
* and user space. This way, userspace will provide buffer which
* may be 4 bytes less than the kernel will use, resulting in
* userspace memory corruption (which is not detectable by valgrind
* too, in most cases).
* So for now, let's align to 64 instead of HOST_LONG_BITS here, in
* a hope that sizeof(long) won't become >8 any time soon.
*/
hwaddr bitmap_size = ALIGN(((mem->memory_size) >> TARGET_PAGE_BITS),
/*HOST_LONG_BITS*/ 64) / 8;
mem->dirty_bmap = g_malloc0(bitmap_size);
}
/** /**
* kvm_physical_sync_dirty_bitmap - Sync dirty bitmap from kernel space * kvm_physical_sync_dirty_bitmap - Sync dirty bitmap from kernel space
* *
@ -550,23 +578,9 @@ static int kvm_physical_sync_dirty_bitmap(KVMMemoryListener *kml,
goto out; goto out;
} }
/* XXX bad kernel interface alert
* For dirty bitmap, kernel allocates array of size aligned to
* bits-per-long. But for case when the kernel is 64bits and
* the userspace is 32bits, userspace can't align to the same
* bits-per-long, since sizeof(long) is different between kernel
* and user space. This way, userspace will provide buffer which
* may be 4 bytes less than the kernel will use, resulting in
* userspace memory corruption (which is not detectable by valgrind
* too, in most cases).
* So for now, let's align to 64 instead of HOST_LONG_BITS here, in
* a hope that sizeof(long) won't become >8 any time soon.
*/
if (!mem->dirty_bmap) { if (!mem->dirty_bmap) {
hwaddr bitmap_size = ALIGN(((mem->memory_size) >> TARGET_PAGE_BITS),
/*HOST_LONG_BITS*/ 64) / 8;
/* Allocate on the first log_sync, once and for all */ /* Allocate on the first log_sync, once and for all */
mem->dirty_bmap = g_malloc0(bitmap_size); kvm_memslot_init_dirty_bitmap(mem);
} }
d.dirty_bitmap = mem->dirty_bmap; d.dirty_bitmap = mem->dirty_bmap;
@ -1067,6 +1081,13 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml,
mem->ram = ram; mem->ram = ram;
mem->flags = kvm_mem_flags(mr); mem->flags = kvm_mem_flags(mr);
if (mem->flags & KVM_MEM_LOG_DIRTY_PAGES) {
/*
* Reallocate the bmap; it means it doesn't disappear in
* middle of a migrate.
*/
kvm_memslot_init_dirty_bitmap(mem);
}
err = kvm_set_user_memory_region(kml, mem, true); err = kvm_set_user_memory_region(kml, mem, true);
if (err) { if (err) {
fprintf(stderr, "%s: error registering slot: %s\n", __func__, fprintf(stderr, "%s: error registering slot: %s\n", __func__,
@ -1758,7 +1779,7 @@ void kvm_irqchip_set_qemuirq_gsi(KVMState *s, qemu_irq irq, int gsi)
g_hash_table_insert(s->gsimap, irq, GINT_TO_POINTER(gsi)); g_hash_table_insert(s->gsimap, irq, GINT_TO_POINTER(gsi));
} }
static void kvm_irqchip_create(MachineState *machine, KVMState *s) static void kvm_irqchip_create(KVMState *s)
{ {
int ret; int ret;
@ -1776,9 +1797,9 @@ static void kvm_irqchip_create(MachineState *machine, KVMState *s)
/* First probe and see if there's a arch-specific hook to create the /* First probe and see if there's a arch-specific hook to create the
* in-kernel irqchip for us */ * in-kernel irqchip for us */
ret = kvm_arch_irqchip_create(machine, s); ret = kvm_arch_irqchip_create(s);
if (ret == 0) { if (ret == 0) {
if (machine_kernel_irqchip_split(machine)) { if (s->kernel_irqchip_split) {
perror("Split IRQ chip mode not supported."); perror("Split IRQ chip mode not supported.");
exit(1); exit(1);
} else { } else {
@ -2049,8 +2070,8 @@ static int kvm_init(MachineState *ms)
goto err; goto err;
} }
if (machine_kernel_irqchip_allowed(ms)) { if (s->kernel_irqchip_allowed) {
kvm_irqchip_create(ms, s); kvm_irqchip_create(s);
} }
if (kvm_eventfds_allowed) { if (kvm_eventfds_allowed) {
@ -2940,6 +2961,93 @@ static bool kvm_accel_has_memory(MachineState *ms, AddressSpace *as,
return false; return false;
} }
static void kvm_get_kvm_shadow_mem(Object *obj, Visitor *v,
const char *name, void *opaque,
Error **errp)
{
KVMState *s = KVM_STATE(obj);
int64_t value = s->kvm_shadow_mem;
visit_type_int(v, name, &value, errp);
}
static void kvm_set_kvm_shadow_mem(Object *obj, Visitor *v,
const char *name, void *opaque,
Error **errp)
{
KVMState *s = KVM_STATE(obj);
Error *error = NULL;
int64_t value;
visit_type_int(v, name, &value, &error);
if (error) {
error_propagate(errp, error);
return;
}
s->kvm_shadow_mem = value;
}
static void kvm_set_kernel_irqchip(Object *obj, Visitor *v,
const char *name, void *opaque,
Error **errp)
{
Error *err = NULL;
KVMState *s = KVM_STATE(obj);
OnOffSplit mode;
visit_type_OnOffSplit(v, name, &mode, &err);
if (err) {
error_propagate(errp, err);
return;
} else {
switch (mode) {
case ON_OFF_SPLIT_ON:
s->kernel_irqchip_allowed = true;
s->kernel_irqchip_required = true;
s->kernel_irqchip_split = false;
break;
case ON_OFF_SPLIT_OFF:
s->kernel_irqchip_allowed = false;
s->kernel_irqchip_required = false;
s->kernel_irqchip_split = false;
break;
case ON_OFF_SPLIT_SPLIT:
s->kernel_irqchip_allowed = true;
s->kernel_irqchip_required = true;
s->kernel_irqchip_split = true;
break;
default:
/* The value was checked in visit_type_OnOffSplit() above. If
* we get here, then something is wrong in QEMU.
*/
abort();
}
}
}
bool kvm_kernel_irqchip_allowed(void)
{
return kvm_state->kernel_irqchip_allowed;
}
bool kvm_kernel_irqchip_required(void)
{
return kvm_state->kernel_irqchip_required;
}
bool kvm_kernel_irqchip_split(void)
{
return kvm_state->kernel_irqchip_split;
}
static void kvm_accel_instance_init(Object *obj)
{
KVMState *s = KVM_STATE(obj);
s->kvm_shadow_mem = -1;
}
static void kvm_accel_class_init(ObjectClass *oc, void *data) static void kvm_accel_class_init(ObjectClass *oc, void *data)
{ {
AccelClass *ac = ACCEL_CLASS(oc); AccelClass *ac = ACCEL_CLASS(oc);
@ -2947,11 +3055,24 @@ static void kvm_accel_class_init(ObjectClass *oc, void *data)
ac->init_machine = kvm_init; ac->init_machine = kvm_init;
ac->has_memory = kvm_accel_has_memory; ac->has_memory = kvm_accel_has_memory;
ac->allowed = &kvm_allowed; ac->allowed = &kvm_allowed;
object_class_property_add(oc, "kernel-irqchip", "on|off|split",
NULL, kvm_set_kernel_irqchip,
NULL, NULL, &error_abort);
object_class_property_set_description(oc, "kernel-irqchip",
"Configure KVM in-kernel irqchip", &error_abort);
object_class_property_add(oc, "kvm-shadow-mem", "int",
kvm_get_kvm_shadow_mem, kvm_set_kvm_shadow_mem,
NULL, NULL, &error_abort);
object_class_property_set_description(oc, "kvm-shadow-mem",
"KVM shadow MMU size", &error_abort);
} }
static const TypeInfo kvm_accel_type = { static const TypeInfo kvm_accel_type = {
.name = TYPE_KVM_ACCEL, .name = TYPE_KVM_ACCEL,
.parent = TYPE_ACCEL, .parent = TYPE_ACCEL,
.instance_init = kvm_accel_instance_init,
.class_init = kvm_accel_class_init, .class_init = kvm_accel_class_init,
.instance_size = sizeof(KVMState), .instance_size = sizeof(KVMState),
}; };

View file

@ -30,8 +30,23 @@
#include "cpu.h" #include "cpu.h"
#include "sysemu/cpus.h" #include "sysemu/cpus.h"
#include "qemu/main-loop.h" #include "qemu/main-loop.h"
#include "tcg/tcg.h"
#include "include/qapi/error.h"
#include "include/qemu/error-report.h"
#include "include/hw/boards.h"
#include "qapi/qapi-builtin-visit.h"
unsigned long tcg_tb_size; typedef struct TCGState {
AccelState parent_obj;
bool mttcg_enabled;
unsigned long tb_size;
} TCGState;
#define TYPE_TCG_ACCEL ACCEL_CLASS_NAME("tcg")
#define TCG_STATE(obj) \
OBJECT_CHECK(TCGState, (obj), TYPE_TCG_ACCEL)
/* mask must never be zero, except for A20 change call */ /* mask must never be zero, except for A20 change call */
static void tcg_handle_interrupt(CPUState *cpu, int mask) static void tcg_handle_interrupt(CPUState *cpu, int mask)
@ -58,27 +73,153 @@ static void tcg_handle_interrupt(CPUState *cpu, int mask)
} }
} }
/*
* We default to false if we know other options have been enabled
* which are currently incompatible with MTTCG. Otherwise when each
* guest (target) has been updated to support:
* - atomic instructions
* - memory ordering primitives (barriers)
* they can set the appropriate CONFIG flags in ${target}-softmmu.mak
*
* Once a guest architecture has been converted to the new primitives
* there are two remaining limitations to check.
*
* - The guest can't be oversized (e.g. 64 bit guest on 32 bit host)
* - The host must have a stronger memory order than the guest
*
* It may be possible in future to support strong guests on weak hosts
* but that will require tagging all load/stores in a guest with their
* implicit memory order requirements which would likely slow things
* down a lot.
*/
static bool check_tcg_memory_orders_compatible(void)
{
#if defined(TCG_GUEST_DEFAULT_MO) && defined(TCG_TARGET_DEFAULT_MO)
return (TCG_GUEST_DEFAULT_MO & ~TCG_TARGET_DEFAULT_MO) == 0;
#else
return false;
#endif
}
static bool default_mttcg_enabled(void)
{
if (use_icount || TCG_OVERSIZED_GUEST) {
return false;
} else {
#ifdef TARGET_SUPPORTS_MTTCG
return check_tcg_memory_orders_compatible();
#else
return false;
#endif
}
}
static void tcg_accel_instance_init(Object *obj)
{
TCGState *s = TCG_STATE(obj);
s->mttcg_enabled = default_mttcg_enabled();
}
static int tcg_init(MachineState *ms) static int tcg_init(MachineState *ms)
{ {
tcg_exec_init(tcg_tb_size * 1024 * 1024); TCGState *s = TCG_STATE(current_machine->accelerator);
tcg_exec_init(s->tb_size * 1024 * 1024);
cpu_interrupt_handler = tcg_handle_interrupt; cpu_interrupt_handler = tcg_handle_interrupt;
mttcg_enabled = s->mttcg_enabled;
return 0; return 0;
} }
static char *tcg_get_thread(Object *obj, Error **errp)
{
TCGState *s = TCG_STATE(obj);
return g_strdup(s->mttcg_enabled ? "multi" : "single");
}
static void tcg_set_thread(Object *obj, const char *value, Error **errp)
{
TCGState *s = TCG_STATE(obj);
if (strcmp(value, "multi") == 0) {
if (TCG_OVERSIZED_GUEST) {
error_setg(errp, "No MTTCG when guest word size > hosts");
} else if (use_icount) {
error_setg(errp, "No MTTCG when icount is enabled");
} else {
#ifndef TARGET_SUPPORTS_MTTCG
warn_report("Guest not yet converted to MTTCG - "
"you may get unexpected results");
#endif
if (!check_tcg_memory_orders_compatible()) {
warn_report("Guest expects a stronger memory ordering "
"than the host provides");
error_printf("This may cause strange/hard to debug errors\n");
}
s->mttcg_enabled = true;
}
} else if (strcmp(value, "single") == 0) {
s->mttcg_enabled = false;
} else {
error_setg(errp, "Invalid 'thread' setting %s", value);
}
}
static void tcg_get_tb_size(Object *obj, Visitor *v,
const char *name, void *opaque,
Error **errp)
{
TCGState *s = TCG_STATE(obj);
uint32_t value = s->tb_size;
visit_type_uint32(v, name, &value, errp);
}
static void tcg_set_tb_size(Object *obj, Visitor *v,
const char *name, void *opaque,
Error **errp)
{
TCGState *s = TCG_STATE(obj);
Error *error = NULL;
uint32_t value;
visit_type_uint32(v, name, &value, &error);
if (error) {
error_propagate(errp, error);
return;
}
s->tb_size = value;
}
static void tcg_accel_class_init(ObjectClass *oc, void *data) static void tcg_accel_class_init(ObjectClass *oc, void *data)
{ {
AccelClass *ac = ACCEL_CLASS(oc); AccelClass *ac = ACCEL_CLASS(oc);
ac->name = "tcg"; ac->name = "tcg";
ac->init_machine = tcg_init; ac->init_machine = tcg_init;
ac->allowed = &tcg_allowed; ac->allowed = &tcg_allowed;
}
#define TYPE_TCG_ACCEL ACCEL_CLASS_NAME("tcg") object_class_property_add_str(oc, "thread",
tcg_get_thread,
tcg_set_thread,
NULL);
object_class_property_add(oc, "tb-size", "int",
tcg_get_tb_size, tcg_set_tb_size,
NULL, NULL, &error_abort);
object_class_property_set_description(oc, "tb-size",
"TCG translation block cache size", &error_abort);
}
static const TypeInfo tcg_accel_type = { static const TypeInfo tcg_accel_type = {
.name = TYPE_TCG_ACCEL, .name = TYPE_TCG_ACCEL,
.parent = TYPE_ACCEL, .parent = TYPE_ACCEL,
.instance_init = tcg_accel_instance_init,
.class_init = tcg_accel_class_init, .class_init = tcg_accel_class_init,
.instance_size = sizeof(TCGState),
}; };
static void register_accel_types(void) static void register_accel_types(void)

12
configure vendored
View file

@ -101,7 +101,7 @@ update_cxxflags() {
# Set QEMU_CXXFLAGS from QEMU_CFLAGS by filtering out those # Set QEMU_CXXFLAGS from QEMU_CFLAGS by filtering out those
# options which some versions of GCC's C++ compiler complain about # options which some versions of GCC's C++ compiler complain about
# because they only make sense for C programs. # because they only make sense for C programs.
QEMU_CXXFLAGS="$QEMU_CXXFLAGS -D__STDC_LIMIT_MACROS" QEMU_CXXFLAGS="$QEMU_CXXFLAGS -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS"
for arg in $QEMU_CFLAGS; do for arg in $QEMU_CFLAGS; do
case $arg in case $arg in
@ -595,6 +595,7 @@ QEMU_CFLAGS="-Wall -Wundef -Wwrite-strings -Wmissing-prototypes $QEMU_CFLAGS"
QEMU_CFLAGS="-Wstrict-prototypes -Wredundant-decls $QEMU_CFLAGS" QEMU_CFLAGS="-Wstrict-prototypes -Wredundant-decls $QEMU_CFLAGS"
QEMU_CFLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE $QEMU_CFLAGS" QEMU_CFLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE $QEMU_CFLAGS"
QEMU_INCLUDES="-iquote . -iquote \$(SRC_PATH) -iquote \$(SRC_PATH)/accel/tcg -iquote \$(SRC_PATH)/include" QEMU_INCLUDES="-iquote . -iquote \$(SRC_PATH) -iquote \$(SRC_PATH)/accel/tcg -iquote \$(SRC_PATH)/include"
QEMU_INCLUDES="$QEMU_INCLUDES -iquote \$(SRC_PATH)/disas/libvixl"
if test "$debug_info" = "yes"; then if test "$debug_info" = "yes"; then
CFLAGS="-g $CFLAGS" CFLAGS="-g $CFLAGS"
LDFLAGS="-g $LDFLAGS" LDFLAGS="-g $LDFLAGS"
@ -907,7 +908,7 @@ for binary in "${PYTHON-python3}" python python2
do do
if has "$binary" if has "$binary"
then then
python="$binary" python=$(command -v "$binary")
break break
fi fi
done done
@ -925,7 +926,7 @@ if test "$mingw32" = "yes" ; then
DSOSUF=".dll" DSOSUF=".dll"
# MinGW needs -mthreads for TLS and macro _MT. # MinGW needs -mthreads for TLS and macro _MT.
QEMU_CFLAGS="-mthreads $QEMU_CFLAGS" QEMU_CFLAGS="-mthreads $QEMU_CFLAGS"
LIBS="-lwinmm -lws2_32 -liphlpapi $LIBS" LIBS="-lwinmm -lws2_32 $LIBS"
write_c_skeleton; write_c_skeleton;
if compile_prog "" "-liberty" ; then if compile_prog "" "-liberty" ; then
LIBS="-liberty $LIBS" LIBS="-liberty $LIBS"
@ -6027,6 +6028,9 @@ case "$slirp" in
mkdir -p slirp mkdir -p slirp
slirp_cflags="-I\$(SRC_PATH)/slirp/src -I\$(BUILD_DIR)/slirp/src" slirp_cflags="-I\$(SRC_PATH)/slirp/src -I\$(BUILD_DIR)/slirp/src"
slirp_libs="-L\$(BUILD_DIR)/slirp -lslirp" slirp_libs="-L\$(BUILD_DIR)/slirp -lslirp"
if test "$mingw32" = "yes" ; then
slirp_libs="$slirp_libs -lws2_32 -liphlpapi"
fi
;; ;;
system) system)
@ -6716,7 +6720,7 @@ if test "$l2tpv3" = "yes" ; then
echo "CONFIG_L2TPV3=y" >> $config_host_mak echo "CONFIG_L2TPV3=y" >> $config_host_mak
fi fi
if test "$cap_ng" = "yes" ; then if test "$cap_ng" = "yes" ; then
echo "CONFIG_LIBCAP=y" >> $config_host_mak echo "CONFIG_LIBCAP_NG=y" >> $config_host_mak
fi fi
echo "CONFIG_AUDIO_DRIVERS=$audio_drv_list" >> $config_host_mak echo "CONFIG_AUDIO_DRIVERS=$audio_drv_list" >> $config_host_mak
for drv in $audio_drv_list; do for drv in $audio_drv_list; do

View file

@ -115,7 +115,7 @@ static int get_cdb_len(uint8_t *cdb)
case 4: return 16; case 4: return 16;
case 5: return 12; case 5: return 12;
} }
g_warning("Unable to determine cdb len (0x%02hhX)", cdb[0] >> 5); g_warning("Unable to determine cdb len (0x%02hhX)", (uint8_t)(cdb[0] >> 5));
return -1; return -1;
} }

72
cpus.c
View file

@ -166,78 +166,6 @@ typedef struct TimersState {
static TimersState timers_state; static TimersState timers_state;
bool mttcg_enabled; bool mttcg_enabled;
/*
* We default to false if we know other options have been enabled
* which are currently incompatible with MTTCG. Otherwise when each
* guest (target) has been updated to support:
* - atomic instructions
* - memory ordering primitives (barriers)
* they can set the appropriate CONFIG flags in ${target}-softmmu.mak
*
* Once a guest architecture has been converted to the new primitives
* there are two remaining limitations to check.
*
* - The guest can't be oversized (e.g. 64 bit guest on 32 bit host)
* - The host must have a stronger memory order than the guest
*
* It may be possible in future to support strong guests on weak hosts
* but that will require tagging all load/stores in a guest with their
* implicit memory order requirements which would likely slow things
* down a lot.
*/
static bool check_tcg_memory_orders_compatible(void)
{
#if defined(TCG_GUEST_DEFAULT_MO) && defined(TCG_TARGET_DEFAULT_MO)
return (TCG_GUEST_DEFAULT_MO & ~TCG_TARGET_DEFAULT_MO) == 0;
#else
return false;
#endif
}
static bool default_mttcg_enabled(void)
{
if (use_icount || TCG_OVERSIZED_GUEST) {
return false;
} else {
#ifdef TARGET_SUPPORTS_MTTCG
return check_tcg_memory_orders_compatible();
#else
return false;
#endif
}
}
void qemu_tcg_configure(QemuOpts *opts, Error **errp)
{
const char *t = qemu_opt_get(opts, "thread");
if (t) {
if (strcmp(t, "multi") == 0) {
if (TCG_OVERSIZED_GUEST) {
error_setg(errp, "No MTTCG when guest word size > hosts");
} else if (use_icount) {
error_setg(errp, "No MTTCG when icount is enabled");
} else {
#ifndef TARGET_SUPPORTS_MTTCG
warn_report("Guest not yet converted to MTTCG - "
"you may get unexpected results");
#endif
if (!check_tcg_memory_orders_compatible()) {
warn_report("Guest expects a stronger memory ordering "
"than the host provides");
error_printf("This may cause strange/hard to debug errors\n");
}
mttcg_enabled = true;
}
} else if (strcmp(t, "single") == 0) {
mttcg_enabled = false;
} else {
error_setg(errp, "Invalid 'thread' setting %s", t);
}
} else {
mttcg_enabled = default_mttcg_enabled();
}
}
/* The current number of executed instructions is based on what we /* The current number of executed instructions is based on what we
* originally budgeted minus the current state of the decrementing * originally budgeted minus the current state of the decrementing

View file

@ -19,13 +19,10 @@ crypto-obj-y += tlscredspsk.o
crypto-obj-y += tlscredsx509.o crypto-obj-y += tlscredsx509.o
crypto-obj-y += tlssession.o crypto-obj-y += tlssession.o
crypto-obj-y += secret.o crypto-obj-y += secret.o
crypto-rng-obj-$(CONFIG_GCRYPT) += random-gcrypt.o
crypto-rng-obj-$(if $(CONFIG_GCRYPT),n,$(CONFIG_GNUTLS)) += random-gnutls.o
crypto-rng-obj-$(if $(CONFIG_GCRYPT),n,$(if $(CONFIG_GNUTLS),n,y)) += random-platform.o
crypto-obj-y += $(crypto-rng-obj-y)
crypto-obj-y += pbkdf.o crypto-obj-y += pbkdf.o
crypto-obj-$(CONFIG_NETTLE) += pbkdf-nettle.o crypto-obj-$(CONFIG_NETTLE) += pbkdf-nettle.o
crypto-obj-$(if $(CONFIG_NETTLE),n,$(CONFIG_GCRYPT)) += pbkdf-gcrypt.o crypto-obj-$(if $(CONFIG_NETTLE),n,$(CONFIG_GCRYPT)) += pbkdf-gcrypt.o
crypto-obj-$(if $(CONFIG_NETTLE),n,$(if $(CONFIG_GCRYPT),n,y)) += pbkdf-stub.o
crypto-obj-y += ivgen.o crypto-obj-y += ivgen.o
crypto-obj-y += ivgen-essiv.o crypto-obj-y += ivgen-essiv.o
crypto-obj-y += ivgen-plain.o crypto-obj-y += ivgen-plain.o
@ -36,7 +33,7 @@ crypto-obj-y += block.o
crypto-obj-y += block-qcow.o crypto-obj-y += block-qcow.o
crypto-obj-y += block-luks.o crypto-obj-y += block-luks.o
# Let the userspace emulators avoid linking stuff they won't use. util-obj-$(CONFIG_GCRYPT) += random-gcrypt.o
crypto-user-obj-y = aes.o $(crypto-rng-obj-y) init.o util-obj-$(if $(CONFIG_GCRYPT),n,$(CONFIG_GNUTLS)) += random-gnutls.o
util-obj-$(if $(CONFIG_GCRYPT),n,$(if $(CONFIG_GNUTLS),n,y)) += random-platform.o
stub-obj-y += pbkdf-stub.o util-obj-y += aes.o init.o

View file

@ -1,14 +1,5 @@
libvixl_OBJS = vixl/utils.o \ common-obj-$(CONFIG_ARM_A64_DIS) = vixl/utils.o \
vixl/compiler-intrinsics.o \ vixl/compiler-intrinsics.o \
vixl/a64/instructions-a64.o \ vixl/a64/instructions-a64.o \
vixl/a64/decoder-a64.o \ vixl/a64/decoder-a64.o \
vixl/a64/disasm-a64.o vixl/a64/disasm-a64.o
# The -Wno-sign-compare is needed only for gcc 4.6, which complains about
# some signed-unsigned equality comparisons which later gcc versions do not.
$(addprefix $(obj)/,$(libvixl_OBJS)): QEMU_CXXFLAGS := -I$(SRC_PATH)/disas/libvixl $(QEMU_CXXFLAGS) -Wno-sign-compare
# Ensure that C99 macros are defined regardless of the inclusion order of
# headers in vixl. This is required at least on NetBSD.
$(addprefix $(obj)/,$(libvixl_OBJS)): QEMU_CXXFLAGS += -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS
common-obj-$(CONFIG_ARM_A64_DIS) += $(libvixl_OBJS)

View file

@ -54,7 +54,7 @@
# Add any Sphinx extension module names here, as strings. They can be # Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones. # ones.
extensions = ['qmp_lexer'] extensions = ['kerneldoc', 'qmp_lexer']
# Add any paths that contain templates here, relative to this directory. # Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates'] templates_path = ['_templates']
@ -216,3 +216,8 @@
# We use paths starting from qemu_docdir here so that you can run
# sphinx-build from anywhere and the kerneldoc extension can still
# find everything.
kerneldoc_bin = os.path.join(qemu_docdir, '../scripts/kernel-doc')
kerneldoc_srctree = os.path.join(qemu_docdir, '..')

8
docs/devel/bitops.rst Normal file
View file

@ -0,0 +1,8 @@
==================
Bitwise operations
==================
The header ``qemu/bitops.h`` provides utility functions for
performing bitwise operations.
.. kernel-doc:: include/qemu/bitops.h

View file

@ -23,3 +23,4 @@ Contents:
secure-coding-practices secure-coding-practices
tcg tcg
tcg-plugins tcg-plugins
bitops

View file

@ -361,3 +361,8 @@ callbacks are called:
- .impl.unaligned specifies that the *implementation* supports unaligned - .impl.unaligned specifies that the *implementation* supports unaligned
accesses; if false, unaligned accesses will be emulated by two aligned accesses; if false, unaligned accesses will be emulated by two aligned
accesses. accesses.
API Reference
-------------
.. kernel-doc:: include/exec/memory.h

172
docs/sphinx/kerneldoc.py Normal file
View file

@ -0,0 +1,172 @@
# coding=utf-8
#
# Copyright © 2016 Intel Corporation
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice (including the next
# paragraph) shall be included in all copies or substantial portions of the
# Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
#
# Authors:
# Jani Nikula <jani.nikula@intel.com>
#
# Please make sure this works on both python2 and python3.
#
import codecs
import os
import subprocess
import sys
import re
import glob
from docutils import nodes, statemachine
from docutils.statemachine import ViewList
from docutils.parsers.rst import directives, Directive
#
# AutodocReporter is only good up to Sphinx 1.7
#
import sphinx
Use_SSI = sphinx.__version__[:3] >= '1.7'
if Use_SSI:
from sphinx.util.docutils import switch_source_input
else:
from sphinx.ext.autodoc import AutodocReporter
import kernellog
__version__ = '1.0'
class KernelDocDirective(Directive):
"""Extract kernel-doc comments from the specified file"""
required_argument = 1
optional_arguments = 4
option_spec = {
'doc': directives.unchanged_required,
'functions': directives.unchanged,
'export': directives.unchanged,
'internal': directives.unchanged,
}
has_content = False
def run(self):
env = self.state.document.settings.env
cmd = [env.config.kerneldoc_bin, '-rst', '-enable-lineno']
filename = env.config.kerneldoc_srctree + '/' + self.arguments[0]
export_file_patterns = []
# Tell sphinx of the dependency
env.note_dependency(os.path.abspath(filename))
tab_width = self.options.get('tab-width', self.state.document.settings.tab_width)
# FIXME: make this nicer and more robust against errors
if 'export' in self.options:
cmd += ['-export']
export_file_patterns = str(self.options.get('export')).split()
elif 'internal' in self.options:
cmd += ['-internal']
export_file_patterns = str(self.options.get('internal')).split()
elif 'doc' in self.options:
cmd += ['-function', str(self.options.get('doc'))]
elif 'functions' in self.options:
functions = self.options.get('functions').split()
if functions:
for f in functions:
cmd += ['-function', f]
else:
cmd += ['-no-doc-sections']
for pattern in export_file_patterns:
for f in glob.glob(env.config.kerneldoc_srctree + '/' + pattern):
env.note_dependency(os.path.abspath(f))
cmd += ['-export-file', f]
cmd += [filename]
try:
kernellog.verbose(env.app,
'calling kernel-doc \'%s\'' % (" ".join(cmd)))
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()
out, err = codecs.decode(out, 'utf-8'), codecs.decode(err, 'utf-8')
if p.returncode != 0:
sys.stderr.write(err)
kernellog.warn(env.app,
'kernel-doc \'%s\' failed with return code %d' % (" ".join(cmd), p.returncode))
return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))]
elif env.config.kerneldoc_verbosity > 0:
sys.stderr.write(err)
lines = statemachine.string2lines(out, tab_width, convert_whitespace=True)
result = ViewList()
lineoffset = 0;
line_regex = re.compile("^#define LINENO ([0-9]+)$")
for line in lines:
match = line_regex.search(line)
if match:
# sphinx counts lines from 0
lineoffset = int(match.group(1)) - 1
# we must eat our comments since the upset the markup
else:
result.append(line, filename, lineoffset)
lineoffset += 1
node = nodes.section()
self.do_parse(result, node)
return node.children
except Exception as e: # pylint: disable=W0703
kernellog.warn(env.app, 'kernel-doc \'%s\' processing failed with: %s' %
(" ".join(cmd), str(e)))
return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))]
def do_parse(self, result, node):
if Use_SSI:
with switch_source_input(self.state, result):
self.state.nested_parse(result, 0, node, match_titles=1)
else:
save = self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter
self.state.memo.reporter = AutodocReporter(result, self.state.memo.reporter)
self.state.memo.title_styles, self.state.memo.section_level = [], 0
try:
self.state.nested_parse(result, 0, node, match_titles=1)
finally:
self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter = save
def setup(app):
app.add_config_value('kerneldoc_bin', None, 'env')
app.add_config_value('kerneldoc_srctree', None, 'env')
app.add_config_value('kerneldoc_verbosity', 1, 'env')
app.add_directive('kernel-doc', KernelDocDirective)
return dict(
version = __version__,
parallel_read_safe = True,
parallel_write_safe = True
)

28
docs/sphinx/kernellog.py Normal file
View file

@ -0,0 +1,28 @@
# SPDX-License-Identifier: GPL-2.0
#
# Sphinx has deprecated its older logging interface, but the replacement
# only goes back to 1.6. So here's a wrapper layer to keep around for
# as long as we support 1.4.
#
import sphinx
if sphinx.__version__[:3] >= '1.6':
UseLogging = True
from sphinx.util import logging
logger = logging.getLogger('kerneldoc')
else:
UseLogging = False
def warn(app, message):
if UseLogging:
logger.warning(message)
else:
app.warn(message)
def verbose(app, message):
if UseLogging:
logger.verbose(message)
else:
app.verbose(message)

7
exec.c
View file

@ -3903,10 +3903,9 @@ int ram_block_discard_range(RAMBlock *rb, uint64_t start, size_t length)
if ((start + length) <= rb->used_length) { if ((start + length) <= rb->used_length) {
bool need_madvise, need_fallocate; bool need_madvise, need_fallocate;
uint8_t *host_endaddr = host_startaddr + length; if (length & (rb->page_size - 1)) {
if ((uintptr_t)host_endaddr & (rb->page_size - 1)) { error_report("ram_block_discard_range: Unaligned length: %zx",
error_report("ram_block_discard_range: Unaligned end address: %p", length);
host_endaddr);
goto err; goto err;
} }

View file

@ -8,6 +8,7 @@ common-obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o
common-obj-$(CONFIG_ACPI_VMGENID) += vmgenid.o common-obj-$(CONFIG_ACPI_VMGENID) += vmgenid.o
common-obj-$(CONFIG_ACPI_HW_REDUCED) += generic_event_device.o common-obj-$(CONFIG_ACPI_HW_REDUCED) += generic_event_device.o
common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o
common-obj-$(call lnot,$(CONFIG_PC)) += acpi-x86-stub.o
common-obj-y += acpi_interface.o common-obj-y += acpi_interface.o
common-obj-y += bios-linker-loader.o common-obj-y += bios-linker-loader.o
@ -20,4 +21,4 @@ common-obj-$(call lnot,$(CONFIG_IPMI)) += ipmi-stub.o
else else
common-obj-y += acpi-stub.o common-obj-y += acpi-stub.o
endif endif
common-obj-$(CONFIG_ALL) += acpi-stub.o ipmi-stub.o common-obj-$(CONFIG_ALL) += acpi-stub.o acpi-x86-stub.o ipmi-stub.o

View file

@ -7,7 +7,8 @@
#include "hw/pci/pci.h" #include "hw/pci/pci.h"
#include "hw/pci/pci_host.h" #include "hw/pci/pci_host.h"
#include "hw/ide.h" #include "hw/ide.h"
#include "hw/i386/pc.h" #include "hw/boards.h"
#include "hw/intc/i8259.h"
PCIBus *typhoon_init(ram_addr_t, ISABus **, qemu_irq *, AlphaCPU *[4], PCIBus *typhoon_init(ram_addr_t, ISABus **, qemu_irq *, AlphaCPU *[4],

View file

@ -19,6 +19,7 @@
#include "hw/timer/i8254.h" #include "hw/timer/i8254.h"
#include "hw/isa/superio.h" #include "hw/isa/superio.h"
#include "hw/dma/i8257.h" #include "hw/dma/i8257.h"
#include "net/net.h"
#include "qemu/cutils.h" #include "qemu/cutils.h"
#define MAX_IDE_BUS 2 #define MAX_IDE_BUS 2

View file

@ -161,7 +161,6 @@ typedef struct AC97BusMasterRegs {
typedef struct AC97LinkState { typedef struct AC97LinkState {
PCIDevice dev; PCIDevice dev;
QEMUSoundCard card; QEMUSoundCard card;
uint32_t use_broken_id;
uint32_t glob_cnt; uint32_t glob_cnt;
uint32_t glob_sta; uint32_t glob_sta;
uint32_t cas; uint32_t cas;
@ -1373,13 +1372,6 @@ static void ac97_realize(PCIDevice *dev, Error **errp)
c[PCI_BASE_ADDRESS_0 + 6] = 0x00; c[PCI_BASE_ADDRESS_0 + 6] = 0x00;
c[PCI_BASE_ADDRESS_0 + 7] = 0x00; c[PCI_BASE_ADDRESS_0 + 7] = 0x00;
if (s->use_broken_id) {
c[PCI_SUBSYSTEM_VENDOR_ID] = 0x86;
c[PCI_SUBSYSTEM_VENDOR_ID + 1] = 0x80;
c[PCI_SUBSYSTEM_ID] = 0x00;
c[PCI_SUBSYSTEM_ID + 1] = 0x00;
}
c[PCI_INTERRUPT_LINE] = 0x00; /* intr_ln interrupt line rw */ c[PCI_INTERRUPT_LINE] = 0x00; /* intr_ln interrupt line rw */
c[PCI_INTERRUPT_PIN] = 0x01; /* intr_pn interrupt pin ro */ c[PCI_INTERRUPT_PIN] = 0x01; /* intr_pn interrupt pin ro */
@ -1411,7 +1403,6 @@ static int ac97_init (PCIBus *bus)
static Property ac97_properties[] = { static Property ac97_properties[] = {
DEFINE_AUDIO_PROPERTIES(AC97LinkState, card), DEFINE_AUDIO_PROPERTIES(AC97LinkState, card),
DEFINE_PROP_UINT32 ("use_broken_id", AC97LinkState, use_broken_id, 0),
DEFINE_PROP_END_OF_LIST (), DEFINE_PROP_END_OF_LIST (),
}; };

View file

@ -178,86 +178,6 @@ GlobalProperty hw_compat_2_1[] = {
}; };
const size_t hw_compat_2_1_len = G_N_ELEMENTS(hw_compat_2_1); const size_t hw_compat_2_1_len = G_N_ELEMENTS(hw_compat_2_1);
static char *machine_get_accel(Object *obj, Error **errp)
{
MachineState *ms = MACHINE(obj);
return g_strdup(ms->accel);
}
static void machine_set_accel(Object *obj, const char *value, Error **errp)
{
MachineState *ms = MACHINE(obj);
g_free(ms->accel);
ms->accel = g_strdup(value);
}
static void machine_set_kernel_irqchip(Object *obj, Visitor *v,
const char *name, void *opaque,
Error **errp)
{
Error *err = NULL;
MachineState *ms = MACHINE(obj);
OnOffSplit mode;
visit_type_OnOffSplit(v, name, &mode, &err);
if (err) {
error_propagate(errp, err);
return;
} else {
switch (mode) {
case ON_OFF_SPLIT_ON:
ms->kernel_irqchip_allowed = true;
ms->kernel_irqchip_required = true;
ms->kernel_irqchip_split = false;
break;
case ON_OFF_SPLIT_OFF:
ms->kernel_irqchip_allowed = false;
ms->kernel_irqchip_required = false;
ms->kernel_irqchip_split = false;
break;
case ON_OFF_SPLIT_SPLIT:
ms->kernel_irqchip_allowed = true;
ms->kernel_irqchip_required = true;
ms->kernel_irqchip_split = true;
break;
default:
/* The value was checked in visit_type_OnOffSplit() above. If
* we get here, then something is wrong in QEMU.
*/
abort();
}
}
}
static void machine_get_kvm_shadow_mem(Object *obj, Visitor *v,
const char *name, void *opaque,
Error **errp)
{
MachineState *ms = MACHINE(obj);
int64_t value = ms->kvm_shadow_mem;
visit_type_int(v, name, &value, errp);
}
static void machine_set_kvm_shadow_mem(Object *obj, Visitor *v,
const char *name, void *opaque,
Error **errp)
{
MachineState *ms = MACHINE(obj);
Error *error = NULL;
int64_t value;
visit_type_int(v, name, &value, &error);
if (error) {
error_propagate(errp, error);
return;
}
ms->kvm_shadow_mem = value;
}
static char *machine_get_kernel(Object *obj, Error **errp) static char *machine_get_kernel(Object *obj, Error **errp)
{ {
MachineState *ms = MACHINE(obj); MachineState *ms = MACHINE(obj);
@ -432,20 +352,6 @@ static void machine_set_graphics(Object *obj, bool value, Error **errp)
ms->enable_graphics = value; ms->enable_graphics = value;
} }
static bool machine_get_igd_gfx_passthru(Object *obj, Error **errp)
{
MachineState *ms = MACHINE(obj);
return ms->igd_gfx_passthru;
}
static void machine_set_igd_gfx_passthru(Object *obj, bool value, Error **errp)
{
MachineState *ms = MACHINE(obj);
ms->igd_gfx_passthru = value;
}
static char *machine_get_firmware(Object *obj, Error **errp) static char *machine_get_firmware(Object *obj, Error **errp)
{ {
MachineState *ms = MACHINE(obj); MachineState *ms = MACHINE(obj);
@ -813,23 +719,6 @@ static void machine_class_init(ObjectClass *oc, void *data)
mc->numa_mem_align_shift = 23; mc->numa_mem_align_shift = 23;
mc->numa_auto_assign_ram = numa_default_auto_assign_ram; mc->numa_auto_assign_ram = numa_default_auto_assign_ram;
object_class_property_add_str(oc, "accel",
machine_get_accel, machine_set_accel, &error_abort);
object_class_property_set_description(oc, "accel",
"Accelerator list", &error_abort);
object_class_property_add(oc, "kernel-irqchip", "on|off|split",
NULL, machine_set_kernel_irqchip,
NULL, NULL, &error_abort);
object_class_property_set_description(oc, "kernel-irqchip",
"Configure KVM in-kernel irqchip", &error_abort);
object_class_property_add(oc, "kvm-shadow-mem", "int",
machine_get_kvm_shadow_mem, machine_set_kvm_shadow_mem,
NULL, NULL, &error_abort);
object_class_property_set_description(oc, "kvm-shadow-mem",
"KVM shadow MMU size", &error_abort);
object_class_property_add_str(oc, "kernel", object_class_property_add_str(oc, "kernel",
machine_get_kernel, machine_set_kernel, &error_abort); machine_get_kernel, machine_set_kernel, &error_abort);
object_class_property_set_description(oc, "kernel", object_class_property_set_description(oc, "kernel",
@ -887,12 +776,6 @@ static void machine_class_init(ObjectClass *oc, void *data)
object_class_property_set_description(oc, "graphics", object_class_property_set_description(oc, "graphics",
"Set on/off to enable/disable graphics emulation", &error_abort); "Set on/off to enable/disable graphics emulation", &error_abort);
object_class_property_add_bool(oc, "igd-passthru",
machine_get_igd_gfx_passthru, machine_set_igd_gfx_passthru,
&error_abort);
object_class_property_set_description(oc, "igd-passthru",
"Set on/off to enable/disable igd passthrou", &error_abort);
object_class_property_add_str(oc, "firmware", object_class_property_add_str(oc, "firmware",
machine_get_firmware, machine_set_firmware, machine_get_firmware, machine_set_firmware,
&error_abort); &error_abort);
@ -935,9 +818,6 @@ static void machine_initfn(Object *obj)
MachineState *ms = MACHINE(obj); MachineState *ms = MACHINE(obj);
MachineClass *mc = MACHINE_GET_CLASS(obj); MachineClass *mc = MACHINE_GET_CLASS(obj);
ms->kernel_irqchip_allowed = true;
ms->kernel_irqchip_split = mc->default_kernel_irqchip_split;
ms->kvm_shadow_mem = -1;
ms->dump_guest_core = true; ms->dump_guest_core = true;
ms->mem_merge = true; ms->mem_merge = true;
ms->enable_graphics = true; ms->enable_graphics = true;
@ -976,7 +856,6 @@ static void machine_finalize(Object *obj)
{ {
MachineState *ms = MACHINE(obj); MachineState *ms = MACHINE(obj);
g_free(ms->accel);
g_free(ms->kernel_filename); g_free(ms->kernel_filename);
g_free(ms->initrd_filename); g_free(ms->initrd_filename);
g_free(ms->kernel_cmdline); g_free(ms->kernel_cmdline);
@ -994,26 +873,6 @@ bool machine_usb(MachineState *machine)
return machine->usb; return machine->usb;
} }
bool machine_kernel_irqchip_allowed(MachineState *machine)
{
return machine->kernel_irqchip_allowed;
}
bool machine_kernel_irqchip_required(MachineState *machine)
{
return machine->kernel_irqchip_required;
}
bool machine_kernel_irqchip_split(MachineState *machine)
{
return machine->kernel_irqchip_split;
}
int machine_kvm_shadow_mem(MachineState *machine)
{
return machine->kvm_shadow_mem;
}
int machine_phandle_start(MachineState *machine) int machine_phandle_start(MachineState *machine)
{ {
return machine->phandle_start; return machine->phandle_start;

View file

@ -106,6 +106,9 @@ int isa_vga_mm_init(hwaddr vram_base,
s->vga.con = graphic_console_init(NULL, 0, s->vga.hw_ops, s); s->vga.con = graphic_console_init(NULL, 0, s->vga.hw_ops, s);
vga_init_vbe(&s->vga, NULL, address_space); memory_region_add_subregion(address_space,
VBE_DISPI_LFB_PHYSICAL_ADDRESS,
&s->vga.vram);
return 0; return 0;
} }

View file

@ -76,7 +76,9 @@ static void vga_isa_realizefn(DeviceState *dev, Error **errp)
memory_region_set_coalescing(vga_io_memory); memory_region_set_coalescing(vga_io_memory);
s->con = graphic_console_init(DEVICE(dev), 0, s->hw_ops, s); s->con = graphic_console_init(DEVICE(dev), 0, s->hw_ops, s);
vga_init_vbe(s, OBJECT(dev), isa_address_space(isadev)); memory_region_add_subregion(isa_address_space(isadev),
VBE_DISPI_LFB_PHYSICAL_ADDRESS,
&s->vram);
/* ROM BIOS */ /* ROM BIOS */
rom_add_vga(VGABIOS_FILENAME); rom_add_vga(VGABIOS_FILENAME);
} }

View file

@ -264,11 +264,6 @@ static void pci_std_vga_realize(PCIDevice *dev, Error **errp)
pci_register_bar(&d->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio); pci_register_bar(&d->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
} }
if (!dev->rom_bar) {
/* compatibility with pc-0.13 and older */
vga_init_vbe(s, OBJECT(dev), pci_address_space(dev));
}
} }
static void pci_std_vga_init(Object *obj) static void pci_std_vga_init(Object *obj)

View file

@ -2301,17 +2301,3 @@ void vga_init(VGACommonState *s, Object *obj, MemoryRegion *address_space,
portio_list_add(&s->vbe_port_list, address_space_io, 0x1ce); portio_list_add(&s->vbe_port_list, address_space_io, 0x1ce);
} }
} }
void vga_init_vbe(VGACommonState *s, Object *obj, MemoryRegion *system_memory)
{
/* With pc-0.12 and below we map both the PCI BAR and the fixed VBE region,
* so use an alias to avoid double-mapping the same region.
*/
memory_region_init_alias(&s->vram_vbe, obj, "vram.vbe",
&s->vram, 0, memory_region_size(&s->vram));
/* XXX: use optimized standard vga accesses */
memory_region_add_subregion(system_memory,
VBE_DISPI_LFB_PHYSICAL_ADDRESS,
&s->vram_vbe);
s->vbe_mapped = 1;
}

View file

@ -60,7 +60,6 @@ typedef struct VGACommonState {
MemoryRegion *legacy_address_space; MemoryRegion *legacy_address_space;
uint8_t *vram_ptr; uint8_t *vram_ptr;
MemoryRegion vram; MemoryRegion vram;
MemoryRegion vram_vbe;
uint32_t vram_size; uint32_t vram_size;
uint32_t vram_size_mb; /* property */ uint32_t vram_size_mb; /* property */
uint32_t vbe_size; uint32_t vbe_size;
@ -106,7 +105,6 @@ typedef struct VGACommonState {
uint32_t vbe_start_addr; uint32_t vbe_start_addr;
uint32_t vbe_line_offset; uint32_t vbe_line_offset;
uint32_t vbe_bank_mask; uint32_t vbe_bank_mask;
int vbe_mapped;
/* display refresh support */ /* display refresh support */
QemuConsole *con; QemuConsole *con;
uint32_t font_offsets[2]; uint32_t font_offsets[2];
@ -178,7 +176,6 @@ void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2);
int vga_ioport_invalid(VGACommonState *s, uint32_t addr); int vga_ioport_invalid(VGACommonState *s, uint32_t addr);
void vga_init_vbe(VGACommonState *s, Object *obj, MemoryRegion *address_space);
uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr); uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr);
void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val); void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val);
void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val); void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val);

View file

@ -1312,11 +1312,6 @@ static void pci_vmsvga_realize(PCIDevice *dev, Error **errp)
&s->chip.vga.vram); &s->chip.vga.vram);
pci_register_bar(dev, 2, PCI_BASE_ADDRESS_MEM_PREFETCH, pci_register_bar(dev, 2, PCI_BASE_ADDRESS_MEM_PREFETCH,
&s->chip.fifo_ram); &s->chip.fifo_ram);
if (!dev->rom_bar) {
/* compatibility with pc-0.13 and older */
vga_init_vbe(&s->chip.vga, OBJECT(dev), pci_address_space(dev));
}
} }
static Property vga_vmware_properties[] = { static Property vga_vmware_properties[] = {

View file

@ -6,7 +6,8 @@
#include "hw/pci/pci.h" #include "hw/pci/pci.h"
#include "hw/pci/pci_host.h" #include "hw/pci/pci_host.h"
#include "hw/ide.h" #include "hw/ide.h"
#include "hw/i386/pc.h" #include "hw/boards.h"
#include "hw/intc/i8259.h"
#include "hppa_hardware.h" #include "hppa_hardware.h"

View file

@ -19,6 +19,7 @@
#include "hppa_sys.h" #include "hppa_sys.h"
#include "qemu/units.h" #include "qemu/units.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "net/net.h"
#include "qemu/log.h" #include "qemu/log.h"
#define MAX_IDE_BUS 2 #define MAX_IDE_BUS 2

View file

@ -546,14 +546,14 @@ uint16_t hyperv_hcall_post_message(uint64_t param, bool fast)
} }
ret = HV_STATUS_INVALID_CONNECTION_ID; ret = HV_STATUS_INVALID_CONNECTION_ID;
rcu_read_lock(); WITH_RCU_READ_LOCK_GUARD() {
QLIST_FOREACH_RCU(mh, &msg_handlers, link) { QLIST_FOREACH_RCU(mh, &msg_handlers, link) {
if (mh->conn_id == (msg->connection_id & HV_CONNECTION_ID_MASK)) { if (mh->conn_id == (msg->connection_id & HV_CONNECTION_ID_MASK)) {
ret = mh->handler(msg, mh->data); ret = mh->handler(msg, mh->data);
break; break;
}
} }
} }
rcu_read_unlock();
unmap: unmap:
cpu_physical_memory_unmap(msg, len, 0, 0); cpu_physical_memory_unmap(msg, len, 0, 0);
@ -619,7 +619,6 @@ int hyperv_set_event_flag_handler(uint32_t conn_id, EventNotifier *notifier)
uint16_t hyperv_hcall_signal_event(uint64_t param, bool fast) uint16_t hyperv_hcall_signal_event(uint64_t param, bool fast)
{ {
uint16_t ret;
EventFlagHandler *handler; EventFlagHandler *handler;
if (unlikely(!fast)) { if (unlikely(!fast)) {
@ -645,15 +644,12 @@ uint16_t hyperv_hcall_signal_event(uint64_t param, bool fast)
return HV_STATUS_INVALID_HYPERCALL_INPUT; return HV_STATUS_INVALID_HYPERCALL_INPUT;
} }
ret = HV_STATUS_INVALID_CONNECTION_ID; RCU_READ_LOCK_GUARD();
rcu_read_lock();
QLIST_FOREACH_RCU(handler, &event_flag_handlers, link) { QLIST_FOREACH_RCU(handler, &event_flag_handlers, link) {
if (handler->conn_id == param) { if (handler->conn_id == param) {
event_notifier_set(handler->notifier); event_notifier_set(handler->notifier);
ret = 0; return 0;
break;
} }
} }
rcu_read_unlock(); return HV_STATUS_INVALID_CONNECTION_ID;
return ret;
} }

View file

@ -103,11 +103,17 @@ config MICROVM
select MC146818RTC select MC146818RTC
select VIRTIO_MMIO select VIRTIO_MMIO
config X86_IOMMU
bool
depends on PC
config VTD config VTD
bool bool
select X86_IOMMU
config AMD_IOMMU config AMD_IOMMU
bool bool
select X86_IOMMU
config VMPORT config VMPORT
bool bool

View file

@ -1,17 +1,19 @@
obj-$(CONFIG_KVM) += kvm/ obj-$(CONFIG_KVM) += kvm/
obj-y += e820_memory_layout.o multiboot.o obj-y += e820_memory_layout.o multiboot.o
obj-y += x86.o obj-y += x86.o
obj-y += pc.o obj-$(CONFIG_PC) += pc.o pc_sysfw.o
obj-$(CONFIG_I440FX) += pc_piix.o obj-$(CONFIG_I440FX) += pc_piix.o
obj-$(CONFIG_Q35) += pc_q35.o obj-$(CONFIG_Q35) += pc_q35.o
obj-$(CONFIG_MICROVM) += microvm.o obj-$(CONFIG_MICROVM) += microvm.o
obj-y += fw_cfg.o pc_sysfw.o obj-y += fw_cfg.o
obj-y += x86-iommu.o obj-$(CONFIG_X86_IOMMU) += x86-iommu.o
obj-$(call lnot,$(CONFIG_X86_IOMMU)) += x86-iommu-stub.o
obj-$(CONFIG_VTD) += intel_iommu.o obj-$(CONFIG_VTD) += intel_iommu.o
obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o
obj-$(CONFIG_XEN) += ../xenpv/ xen/ obj-$(CONFIG_XEN) += ../xenpv/ xen/
obj-$(CONFIG_VMPORT) += vmport.o obj-$(CONFIG_VMPORT) += vmport.o
obj-$(CONFIG_VMMOUSE) += vmmouse.o obj-$(CONFIG_VMMOUSE) += vmmouse.o
obj-$(CONFIG_PC) += port92.o
obj-y += kvmvapic.o obj-y += kvmvapic.o
obj-y += acpi-build.o obj-$(CONFIG_PC) += acpi-build.o

View file

@ -53,6 +53,7 @@
/* Supported chipsets: */ /* Supported chipsets: */
#include "hw/southbridge/piix.h" #include "hw/southbridge/piix.h"
#include "hw/acpi/pcihp.h" #include "hw/acpi/pcihp.h"
#include "hw/i386/fw_cfg.h"
#include "hw/i386/ich9.h" #include "hw/i386/ich9.h"
#include "hw/pci/pci_bus.h" #include "hw/pci/pci_bus.h"
#include "hw/pci-host/q35.h" #include "hw/pci-host/q35.h"

View file

@ -16,12 +16,14 @@
#include "sysemu/numa.h" #include "sysemu/numa.h"
#include "hw/acpi/acpi.h" #include "hw/acpi/acpi.h"
#include "hw/firmware/smbios.h" #include "hw/firmware/smbios.h"
#include "hw/i386/pc.h"
#include "hw/i386/fw_cfg.h" #include "hw/i386/fw_cfg.h"
#include "hw/timer/hpet.h" #include "hw/timer/hpet.h"
#include "hw/nvram/fw_cfg.h" #include "hw/nvram/fw_cfg.h"
#include "e820_memory_layout.h" #include "e820_memory_layout.h"
#include "kvm_i386.h" #include "kvm_i386.h"
#include "config-devices.h"
struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX};
const char *fw_cfg_arch_key_name(uint16_t key) const char *fw_cfg_arch_key_name(uint16_t key)
{ {
@ -46,6 +48,7 @@ const char *fw_cfg_arch_key_name(uint16_t key)
void fw_cfg_build_smbios(MachineState *ms, FWCfgState *fw_cfg) void fw_cfg_build_smbios(MachineState *ms, FWCfgState *fw_cfg)
{ {
#ifdef CONFIG_SMBIOS
uint8_t *smbios_tables, *smbios_anchor; uint8_t *smbios_tables, *smbios_anchor;
size_t smbios_tables_len, smbios_anchor_len; size_t smbios_tables_len, smbios_anchor_len;
struct smbios_phys_mem_area *mem_array; struct smbios_phys_mem_area *mem_array;
@ -83,6 +86,7 @@ void fw_cfg_build_smbios(MachineState *ms, FWCfgState *fw_cfg)
fw_cfg_add_file(fw_cfg, "etc/smbios/smbios-anchor", fw_cfg_add_file(fw_cfg, "etc/smbios/smbios-anchor",
smbios_anchor, smbios_anchor_len); smbios_anchor, smbios_anchor_len);
} }
#endif
} }
FWCfgState *fw_cfg_arch_create(MachineState *ms, FWCfgState *fw_cfg_arch_create(MachineState *ms,
@ -114,8 +118,10 @@ FWCfgState *fw_cfg_arch_create(MachineState *ms,
*/ */
fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, apic_id_limit); fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, apic_id_limit);
fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
#ifdef CONFIG_ACPI
fw_cfg_add_bytes(fw_cfg, FW_CFG_ACPI_TABLES, fw_cfg_add_bytes(fw_cfg, FW_CFG_ACPI_TABLES,
acpi_tables, acpi_tables_len); acpi_tables, acpi_tables_len);
#endif
fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, kvm_allows_irq0_override()); fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, kvm_allows_irq0_override());
fw_cfg_add_bytes(fw_cfg, FW_CFG_E820_TABLE, fw_cfg_add_bytes(fw_cfg, FW_CFG_E820_TABLE,

View file

@ -12,6 +12,8 @@
#include "hw/boards.h" #include "hw/boards.h"
#include "hw/nvram/fw_cfg.h" #include "hw/nvram/fw_cfg.h"
#define FW_CFG_IO_BASE 0x510
#define FW_CFG_ACPI_TABLES (FW_CFG_ARCH_LOCAL + 0) #define FW_CFG_ACPI_TABLES (FW_CFG_ARCH_LOCAL + 0)
#define FW_CFG_SMBIOS_ENTRIES (FW_CFG_ARCH_LOCAL + 1) #define FW_CFG_SMBIOS_ENTRIES (FW_CFG_ARCH_LOCAL + 1)
#define FW_CFG_IRQ0_OVERRIDE (FW_CFG_ARCH_LOCAL + 2) #define FW_CFG_IRQ0_OVERRIDE (FW_CFG_ARCH_LOCAL + 2)

View file

@ -1 +1,5 @@
obj-y += clock.o apic.o i8259.o ioapic.o i8254.o obj-y += clock.o
obj-$(CONFIG_APIC) += apic.o
obj-$(CONFIG_IOAPIC) += ioapic.o
obj-$(CONFIG_I8254) += i8254.o
obj-$(CONFIG_I8259) += i8259.o

View file

@ -12,6 +12,7 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "hw/isa/i8259_internal.h" #include "hw/isa/i8259_internal.h"
#include "hw/intc/i8259.h"
#include "qemu/module.h" #include "qemu/module.h"
#include "hw/i386/apic_internal.h" #include "hw/i386/apic_internal.h"
#include "hw/irq.h" #include "hw/irq.h"

View file

@ -12,7 +12,7 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "monitor/monitor.h" #include "monitor/monitor.h"
#include "hw/i386/pc.h" #include "hw/i386/x86.h"
#include "hw/irq.h" #include "hw/irq.h"
#include "hw/qdev-properties.h" #include "hw/qdev-properties.h"
#include "hw/i386/ioapic_internal.h" #include "hw/i386/ioapic_internal.h"
@ -48,18 +48,6 @@ void kvm_pc_setup_irq_routing(bool pci_enabled)
} }
} }
void kvm_pc_gsi_handler(void *opaque, int n, int level)
{
GSIState *s = opaque;
if (n < ISA_NUM_IRQS) {
/* Kernel will forward to both PIC and IOAPIC */
qemu_set_irq(s->i8259_irq[n], level);
} else {
qemu_set_irq(s->ioapic_irq[n], level);
}
}
typedef struct KVMIOAPICState KVMIOAPICState; typedef struct KVMIOAPICState KVMIOAPICState;
struct KVMIOAPICState { struct KVMIOAPICState {

View file

@ -32,8 +32,8 @@
#include "hw/kvm/clock.h" #include "hw/kvm/clock.h"
#include "hw/i386/microvm.h" #include "hw/i386/microvm.h"
#include "hw/i386/x86.h" #include "hw/i386/x86.h"
#include "hw/i386/pc.h"
#include "target/i386/cpu.h" #include "target/i386/cpu.h"
#include "hw/intc/i8259.h"
#include "hw/timer/i8254.h" #include "hw/timer/i8254.h"
#include "hw/rtc/mc146818rtc.h" #include "hw/rtc/mc146818rtc.h"
#include "hw/char/serial.h" #include "hw/char/serial.h"
@ -132,7 +132,7 @@ static void microvm_devices_init(MicrovmMachineState *mms)
if (mms->pic == ON_OFF_AUTO_ON || mms->pic == ON_OFF_AUTO_AUTO) { if (mms->pic == ON_OFF_AUTO_ON || mms->pic == ON_OFF_AUTO_AUTO) {
qemu_irq *i8259; qemu_irq *i8259;
i8259 = i8259_init(isa_bus, pc_allocate_cpu_irq()); i8259 = i8259_init(isa_bus, x86_allocate_cpu_irq());
for (i = 0; i < ISA_NUM_IRQS; i++) { for (i = 0; i < ISA_NUM_IRQS; i++) {
gsi_state->i8259_irq[i] = i8259[i]; gsi_state->i8259_irq[i] = i8259[i];
} }

View file

@ -44,6 +44,7 @@
#include "migration/vmstate.h" #include "migration/vmstate.h"
#include "multiboot.h" #include "multiboot.h"
#include "hw/rtc/mc146818rtc.h" #include "hw/rtc/mc146818rtc.h"
#include "hw/intc/i8259.h"
#include "hw/dma/i8257.h" #include "hw/dma/i8257.h"
#include "hw/timer/i8254.h" #include "hw/timer/i8254.h"
#include "hw/input/i8042.h" #include "hw/input/i8042.h"
@ -90,18 +91,7 @@
#include "config-devices.h" #include "config-devices.h"
#include "e820_memory_layout.h" #include "e820_memory_layout.h"
#include "fw_cfg.h" #include "fw_cfg.h"
#include "trace.h"
/* debug PC/ISA interrupts */
//#define DEBUG_IRQ
#ifdef DEBUG_IRQ
#define DPRINTF(fmt, ...) \
do { printf("CPUIRQ: " fmt , ## __VA_ARGS__); } while (0)
#else
#define DPRINTF(fmt, ...)
#endif
struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX};
GlobalProperty pc_compat_4_2[] = {}; GlobalProperty pc_compat_4_2[] = {};
const size_t pc_compat_4_2_len = G_N_ELEMENTS(pc_compat_4_2); const size_t pc_compat_4_2_len = G_N_ELEMENTS(pc_compat_4_2);
@ -347,17 +337,6 @@ GlobalProperty pc_compat_1_4[] = {
}; };
const size_t pc_compat_1_4_len = G_N_ELEMENTS(pc_compat_1_4); const size_t pc_compat_1_4_len = G_N_ELEMENTS(pc_compat_1_4);
void gsi_handler(void *opaque, int n, int level)
{
GSIState *s = opaque;
DPRINTF("pc: %s GSI %d\n", level ? "raising" : "lowering", n);
if (n < ISA_NUM_IRQS) {
qemu_set_irq(s->i8259_irq[n], level);
}
qemu_set_irq(s->ioapic_irq[n], level);
}
GSIState *pc_gsi_create(qemu_irq **irqs, bool pci_enabled) GSIState *pc_gsi_create(qemu_irq **irqs, bool pci_enabled)
{ {
GSIState *s; GSIState *s;
@ -365,10 +344,8 @@ GSIState *pc_gsi_create(qemu_irq **irqs, bool pci_enabled)
s = g_new0(GSIState, 1); s = g_new0(GSIState, 1);
if (kvm_ioapic_in_kernel()) { if (kvm_ioapic_in_kernel()) {
kvm_pc_setup_irq_routing(pci_enabled); kvm_pc_setup_irq_routing(pci_enabled);
*irqs = qemu_allocate_irqs(kvm_pc_gsi_handler, s, GSI_NUM_PINS);
} else {
*irqs = qemu_allocate_irqs(gsi_handler, s, GSI_NUM_PINS);
} }
*irqs = qemu_allocate_irqs(gsi_handler, s, GSI_NUM_PINS);
return s; return s;
} }
@ -397,55 +374,6 @@ static uint64_t ioportF0_read(void *opaque, hwaddr addr, unsigned size)
return 0xffffffffffffffffULL; return 0xffffffffffffffffULL;
} }
/* TSC handling */
uint64_t cpu_get_tsc(CPUX86State *env)
{
return cpu_get_ticks();
}
/* IRQ handling */
int cpu_get_pic_interrupt(CPUX86State *env)
{
X86CPU *cpu = env_archcpu(env);
int intno;
if (!kvm_irqchip_in_kernel()) {
intno = apic_get_interrupt(cpu->apic_state);
if (intno >= 0) {
return intno;
}
/* read the irq from the PIC */
if (!apic_accept_pic_intr(cpu->apic_state)) {
return -1;
}
}
intno = pic_read_irq(isa_pic);
return intno;
}
static void pic_irq_request(void *opaque, int irq, int level)
{
CPUState *cs = first_cpu;
X86CPU *cpu = X86_CPU(cs);
DPRINTF("pic_irqs: %s irq %d\n", level? "raise" : "lower", irq);
if (cpu->apic_state && !kvm_irqchip_in_kernel()) {
CPU_FOREACH(cs) {
cpu = X86_CPU(cs);
if (apic_accept_pic_intr(cpu->apic_state)) {
apic_deliver_pic_intr(cpu->apic_state, level);
}
}
} else {
if (level) {
cpu_interrupt(cs, CPU_INTERRUPT_HARD);
} else {
cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
}
}
}
/* PC cmos mappings */ /* PC cmos mappings */
#define REG_EQUIPMENT_BYTE 0x14 #define REG_EQUIPMENT_BYTE 0x14
@ -745,124 +673,6 @@ void pc_cmos_init(PCMachineState *pcms,
qemu_register_reset(pc_cmos_init_late, &arg); qemu_register_reset(pc_cmos_init_late, &arg);
} }
#define TYPE_PORT92 "port92"
#define PORT92(obj) OBJECT_CHECK(Port92State, (obj), TYPE_PORT92)
/* port 92 stuff: could be split off */
typedef struct Port92State {
ISADevice parent_obj;
MemoryRegion io;
uint8_t outport;
qemu_irq a20_out;
} Port92State;
static void port92_write(void *opaque, hwaddr addr, uint64_t val,
unsigned size)
{
Port92State *s = opaque;
int oldval = s->outport;
DPRINTF("port92: write 0x%02" PRIx64 "\n", val);
s->outport = val;
qemu_set_irq(s->a20_out, (val >> 1) & 1);
if ((val & 1) && !(oldval & 1)) {
qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
}
}
static uint64_t port92_read(void *opaque, hwaddr addr,
unsigned size)
{
Port92State *s = opaque;
uint32_t ret;
ret = s->outport;
DPRINTF("port92: read 0x%02x\n", ret);
return ret;
}
static void port92_init(ISADevice *dev, qemu_irq a20_out)
{
qdev_connect_gpio_out_named(DEVICE(dev), PORT92_A20_LINE, 0, a20_out);
}
static const VMStateDescription vmstate_port92_isa = {
.name = "port92",
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT8(outport, Port92State),
VMSTATE_END_OF_LIST()
}
};
static void port92_reset(DeviceState *d)
{
Port92State *s = PORT92(d);
s->outport &= ~1;
}
static const MemoryRegionOps port92_ops = {
.read = port92_read,
.write = port92_write,
.impl = {
.min_access_size = 1,
.max_access_size = 1,
},
.endianness = DEVICE_LITTLE_ENDIAN,
};
static void port92_initfn(Object *obj)
{
Port92State *s = PORT92(obj);
memory_region_init_io(&s->io, OBJECT(s), &port92_ops, s, "port92", 1);
s->outport = 0;
qdev_init_gpio_out_named(DEVICE(obj), &s->a20_out, PORT92_A20_LINE, 1);
}
static void port92_realizefn(DeviceState *dev, Error **errp)
{
ISADevice *isadev = ISA_DEVICE(dev);
Port92State *s = PORT92(dev);
isa_register_ioport(isadev, &s->io, 0x92);
}
static void port92_class_initfn(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = port92_realizefn;
dc->reset = port92_reset;
dc->vmsd = &vmstate_port92_isa;
/*
* Reason: unlike ordinary ISA devices, this one needs additional
* wiring: its A20 output line needs to be wired up by
* port92_init().
*/
dc->user_creatable = false;
}
static const TypeInfo port92_info = {
.name = TYPE_PORT92,
.parent = TYPE_ISA_DEVICE,
.instance_size = sizeof(Port92State),
.instance_init = port92_initfn,
.class_init = port92_class_initfn,
};
static void port92_register_types(void)
{
type_register_static(&port92_info);
}
type_init(port92_register_types)
static void handle_a20_line_change(void *opaque, int irq, int level) static void handle_a20_line_change(void *opaque, int irq, int level)
{ {
X86CPU *cpu = opaque; X86CPU *cpu = opaque;
@ -889,16 +699,6 @@ void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd)
nb_ne2k++; nb_ne2k++;
} }
DeviceState *cpu_get_current_apic(void)
{
if (current_cpu) {
X86CPU *cpu = X86_CPU(current_cpu);
return cpu->apic_state;
} else {
return NULL;
}
}
void pc_acpi_smi_interrupt(void *opaque, int irq, int level) void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
{ {
X86CPU *cpu = opaque; X86CPU *cpu = opaque;
@ -1294,11 +1094,6 @@ uint64_t pc_pci_hole64_start(void)
return ROUND_UP(hole64_start, 1 * GiB); return ROUND_UP(hole64_start, 1 * GiB);
} }
qemu_irq pc_allocate_cpu_irq(void)
{
return qemu_allocate_irq(pic_irq_request, NULL, 0);
}
DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus) DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus)
{ {
DeviceState *dev = NULL; DeviceState *dev = NULL;
@ -1365,11 +1160,12 @@ static void pc_superio_init(ISABus *isa_bus, bool create_fdctrl, bool no_vmport)
qdev_prop_set_ptr(dev, "ps2_mouse", i8042); qdev_prop_set_ptr(dev, "ps2_mouse", i8042);
qdev_init_nofail(dev); qdev_init_nofail(dev);
} }
port92 = isa_create_simple(isa_bus, "port92"); port92 = isa_create_simple(isa_bus, TYPE_PORT92);
a20_line = qemu_allocate_irqs(handle_a20_line_change, first_cpu, 2); a20_line = qemu_allocate_irqs(handle_a20_line_change, first_cpu, 2);
i8042_setup_a20_line(i8042, a20_line[0]); i8042_setup_a20_line(i8042, a20_line[0]);
port92_init(port92, a20_line[1]); qdev_connect_gpio_out_named(DEVICE(port92),
PORT92_A20_LINE, 0, a20_line[1]);
g_free(a20_line); g_free(a20_line);
} }
@ -1475,7 +1271,7 @@ void pc_i8259_create(ISABus *isa_bus, qemu_irq *i8259_irqs)
} else if (xen_enabled()) { } else if (xen_enabled()) {
i8259 = xen_interrupt_controller_init(); i8259 = xen_interrupt_controller_init();
} else { } else {
i8259 = i8259_init(isa_bus, pc_allocate_cpu_irq()); i8259 = i8259_init(isa_bus, x86_allocate_cpu_irq());
} }
for (size_t i = 0; i < ISA_NUM_IRQS; i++) { for (size_t i = 0; i < ISA_NUM_IRQS; i++) {
@ -1485,30 +1281,6 @@ void pc_i8259_create(ISABus *isa_bus, qemu_irq *i8259_irqs)
g_free(i8259); g_free(i8259);
} }
void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name)
{
DeviceState *dev;
SysBusDevice *d;
unsigned int i;
if (kvm_ioapic_in_kernel()) {
dev = qdev_create(NULL, TYPE_KVM_IOAPIC);
} else {
dev = qdev_create(NULL, TYPE_IOAPIC);
}
if (parent_name) {
object_property_add_child(object_resolve_path(parent_name, NULL),
"ioapic", OBJECT(dev), NULL);
}
qdev_init_nofail(dev);
d = SYS_BUS_DEVICE(dev);
sysbus_mmio_map(d, 0, IO_APIC_DEFAULT_ADDRESS);
for (i = 0; i < IOAPIC_NUM_PINS; i++) {
gsi_state->ioapic_irq[i] = qdev_get_gpio_in(dev, i);
}
}
static void pc_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, static void pc_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp) Error **errp)
{ {
@ -2032,48 +1804,6 @@ static void pc_machine_set_vmport(Object *obj, Visitor *v, const char *name,
visit_type_OnOffAuto(v, name, &pcms->vmport, errp); visit_type_OnOffAuto(v, name, &pcms->vmport, errp);
} }
bool pc_machine_is_smm_enabled(PCMachineState *pcms)
{
bool smm_available = false;
if (pcms->smm == ON_OFF_AUTO_OFF) {
return false;
}
if (tcg_enabled() || qtest_enabled()) {
smm_available = true;
} else if (kvm_enabled()) {
smm_available = kvm_has_smm();
}
if (smm_available) {
return true;
}
if (pcms->smm == ON_OFF_AUTO_ON) {
error_report("System Management Mode not supported by this hypervisor.");
exit(1);
}
return false;
}
static void pc_machine_get_smm(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
PCMachineState *pcms = PC_MACHINE(obj);
OnOffAuto smm = pcms->smm;
visit_type_OnOffAuto(v, name, &smm, errp);
}
static void pc_machine_set_smm(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
PCMachineState *pcms = PC_MACHINE(obj);
visit_type_OnOffAuto(v, name, &pcms->smm, errp);
}
static bool pc_machine_get_smbus(Object *obj, Error **errp) static bool pc_machine_get_smbus(Object *obj, Error **errp)
{ {
PCMachineState *pcms = PC_MACHINE(obj); PCMachineState *pcms = PC_MACHINE(obj);
@ -2120,7 +1850,6 @@ static void pc_machine_initfn(Object *obj)
{ {
PCMachineState *pcms = PC_MACHINE(obj); PCMachineState *pcms = PC_MACHINE(obj);
pcms->smm = ON_OFF_AUTO_AUTO;
#ifdef CONFIG_VMPORT #ifdef CONFIG_VMPORT
pcms->vmport = ON_OFF_AUTO_AUTO; pcms->vmport = ON_OFF_AUTO_AUTO;
#else #else
@ -2227,12 +1956,6 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
pc_machine_get_device_memory_region_size, NULL, pc_machine_get_device_memory_region_size, NULL,
NULL, NULL, &error_abort); NULL, NULL, &error_abort);
object_class_property_add(oc, PC_MACHINE_SMM, "OnOffAuto",
pc_machine_get_smm, pc_machine_set_smm,
NULL, NULL, &error_abort);
object_class_property_set_description(oc, PC_MACHINE_SMM,
"Enable SMM (pc & q35)", &error_abort);
object_class_property_add(oc, PC_MACHINE_VMPORT, "OnOffAuto", object_class_property_add(oc, PC_MACHINE_VMPORT, "OnOffAuto",
pc_machine_get_vmport, pc_machine_set_vmport, pc_machine_get_vmport, pc_machine_set_vmport,
NULL, NULL, &error_abort); NULL, NULL, &error_abort);

View file

@ -281,7 +281,7 @@ else {
/* TODO: Populate SPD eeprom data. */ /* TODO: Populate SPD eeprom data. */
pcms->smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, pcms->smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
x86ms->gsi[9], smi_irq, x86ms->gsi[9], smi_irq,
pc_machine_is_smm_enabled(pcms), x86_machine_is_smm_enabled(x86ms),
&piix4_pm); &piix4_pm);
smbus_eeprom_init(pcms->smbus, 8, NULL, 0); smbus_eeprom_init(pcms->smbus, 8, NULL, 0);
@ -309,9 +309,9 @@ else {
static void pc_compat_2_3_fn(MachineState *machine) static void pc_compat_2_3_fn(MachineState *machine)
{ {
PCMachineState *pcms = PC_MACHINE(machine); X86MachineState *x86ms = X86_MACHINE(machine);
if (kvm_enabled()) { if (kvm_enabled()) {
pcms->smm = ON_OFF_AUTO_OFF; x86ms->smm = ON_OFF_AUTO_OFF;
} }
} }
@ -357,19 +357,13 @@ static void pc_compat_1_3(MachineState *machine)
pc_compat_1_4_fn(machine); pc_compat_1_4_fn(machine);
} }
/* PC compat function for pc-0.14 to pc-1.2 */ /* PC compat function for pc-1.0 to pc-1.2 */
static void pc_compat_1_2(MachineState *machine) static void pc_compat_1_2(MachineState *machine)
{ {
pc_compat_1_3(machine); pc_compat_1_3(machine);
x86_cpu_change_kvm_default("kvm-pv-eoi", NULL); x86_cpu_change_kvm_default("kvm-pv-eoi", NULL);
} }
/* PC compat function for pc-0.12 and pc-0.13 */
static void pc_compat_0_13(MachineState *machine)
{
pc_compat_1_2(machine);
}
static void pc_init_isa(MachineState *machine) static void pc_init_isa(MachineState *machine)
{ {
pc_init1(machine, TYPE_I440FX_PCI_HOST_BRIDGE, TYPE_I440FX_PCI_DEVICE); pc_init1(machine, TYPE_I440FX_PCI_HOST_BRIDGE, TYPE_I440FX_PCI_DEVICE);
@ -745,6 +739,7 @@ static void pc_i440fx_1_3_machine_options(MachineClass *m)
pc_i440fx_1_4_machine_options(m); pc_i440fx_1_4_machine_options(m);
m->hw_version = "1.3.0"; m->hw_version = "1.3.0";
m->deprecation_reason = "use a newer machine type instead";
x86mc->compat_apic_id_mode = true; x86mc->compat_apic_id_mode = true;
compat_props_add(m->compat_props, compat, G_N_ELEMENTS(compat)); compat_props_add(m->compat_props, compat, G_N_ELEMENTS(compat));
} }
@ -813,82 +808,6 @@ DEFINE_I440FX_MACHINE(v1_0, "pc-1.0", pc_compat_1_2,
pc_i440fx_1_0_machine_options); pc_i440fx_1_0_machine_options);
static void pc_i440fx_0_15_machine_options(MachineClass *m)
{
static GlobalProperty compat[] = {
PC_CPU_MODEL_IDS("0.15")
};
pc_i440fx_1_0_machine_options(m);
m->hw_version = "0.15";
m->deprecation_reason = "use a newer machine type instead";
compat_props_add(m->compat_props, compat, G_N_ELEMENTS(compat));
}
DEFINE_I440FX_MACHINE(v0_15, "pc-0.15", pc_compat_1_2,
pc_i440fx_0_15_machine_options);
static void pc_i440fx_0_14_machine_options(MachineClass *m)
{
static GlobalProperty compat[] = {
PC_CPU_MODEL_IDS("0.14")
{ "virtio-blk-pci", "event_idx", "off" },
{ "virtio-serial-pci", "event_idx", "off" },
{ "virtio-net-pci", "event_idx", "off" },
{ "virtio-balloon-pci", "event_idx", "off" },
{ "qxl", "revision", "2" },
{ "qxl-vga", "revision", "2" },
};
pc_i440fx_0_15_machine_options(m);
m->hw_version = "0.14";
compat_props_add(m->compat_props, compat, G_N_ELEMENTS(compat));
}
DEFINE_I440FX_MACHINE(v0_14, "pc-0.14", pc_compat_1_2,
pc_i440fx_0_14_machine_options);
static void pc_i440fx_0_13_machine_options(MachineClass *m)
{
PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
static GlobalProperty compat[] = {
PC_CPU_MODEL_IDS("0.13")
{ TYPE_PCI_DEVICE, "command_serr_enable", "off" },
{ "AC97", "use_broken_id", "1" },
{ "virtio-9p-pci", "vectors", "0" },
{ "VGA", "rombar", "0" },
{ "vmware-svga", "rombar", "0" },
};
pc_i440fx_0_14_machine_options(m);
m->hw_version = "0.13";
compat_props_add(m->compat_props, compat, G_N_ELEMENTS(compat));
pcmc->kvmclock_enabled = false;
}
DEFINE_I440FX_MACHINE(v0_13, "pc-0.13", pc_compat_0_13,
pc_i440fx_0_13_machine_options);
static void pc_i440fx_0_12_machine_options(MachineClass *m)
{
static GlobalProperty compat[] = {
PC_CPU_MODEL_IDS("0.12")
{ "virtio-serial-pci", "max_ports", "1" },
{ "virtio-serial-pci", "vectors", "0" },
{ "usb-mouse", "serial", "1" },
{ "usb-tablet", "serial", "1" },
{ "usb-kbd", "serial", "1" },
};
pc_i440fx_0_13_machine_options(m);
m->hw_version = "0.12";
compat_props_add(m->compat_props, compat, G_N_ELEMENTS(compat));
}
DEFINE_I440FX_MACHINE(v0_12, "pc-0.12", pc_compat_0_13,
pc_i440fx_0_12_machine_options);
typedef struct { typedef struct {
uint16_t gpu_device_id; uint16_t gpu_device_id;
uint16_t pch_device_id; uint16_t pch_device_id;

View file

@ -276,7 +276,7 @@ static void pc_q35_init(MachineState *machine)
0xff0104); 0xff0104);
/* connect pm stuff to lpc */ /* connect pm stuff to lpc */
ich9_lpc_pm_init(lpc, pc_machine_is_smm_enabled(pcms)); ich9_lpc_pm_init(lpc, x86_machine_is_smm_enabled(x86ms));
if (pcms->sata_enabled) { if (pcms->sata_enabled) {
/* ahci and SATA device, for q35 1 ahci controller is built-in */ /* ahci and SATA device, for q35 1 ahci controller is built-in */

126
hw/i386/port92.c Normal file
View file

@ -0,0 +1,126 @@
/*
* QEMU I/O port 0x92 (System Control Port A, to handle Fast Gate A20)
*
* Copyright (c) 2003-2004 Fabrice Bellard
*
* SPDX-License-Identifier: MIT
*/
#include "qemu/osdep.h"
#include "sysemu/runstate.h"
#include "migration/vmstate.h"
#include "hw/irq.h"
#include "hw/i386/pc.h"
#include "trace.h"
#define PORT92(obj) OBJECT_CHECK(Port92State, (obj), TYPE_PORT92)
typedef struct Port92State {
ISADevice parent_obj;
MemoryRegion io;
uint8_t outport;
qemu_irq a20_out;
} Port92State;
static void port92_write(void *opaque, hwaddr addr, uint64_t val,
unsigned size)
{
Port92State *s = opaque;
int oldval = s->outport;
trace_port92_write(val);
s->outport = val;
qemu_set_irq(s->a20_out, (val >> 1) & 1);
if ((val & 1) && !(oldval & 1)) {
qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
}
}
static uint64_t port92_read(void *opaque, hwaddr addr,
unsigned size)
{
Port92State *s = opaque;
uint32_t ret;
ret = s->outport;
trace_port92_read(ret);
return ret;
}
static const VMStateDescription vmstate_port92_isa = {
.name = "port92",
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT8(outport, Port92State),
VMSTATE_END_OF_LIST()
}
};
static void port92_reset(DeviceState *d)
{
Port92State *s = PORT92(d);
s->outport &= ~1;
}
static const MemoryRegionOps port92_ops = {
.read = port92_read,
.write = port92_write,
.impl = {
.min_access_size = 1,
.max_access_size = 1,
},
.endianness = DEVICE_LITTLE_ENDIAN,
};
static void port92_initfn(Object *obj)
{
Port92State *s = PORT92(obj);
memory_region_init_io(&s->io, OBJECT(s), &port92_ops, s, "port92", 1);
s->outport = 0;
qdev_init_gpio_out_named(DEVICE(obj), &s->a20_out, PORT92_A20_LINE, 1);
}
static void port92_realizefn(DeviceState *dev, Error **errp)
{
ISADevice *isadev = ISA_DEVICE(dev);
Port92State *s = PORT92(dev);
isa_register_ioport(isadev, &s->io, 0x92);
}
static void port92_class_initfn(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = port92_realizefn;
dc->reset = port92_reset;
dc->vmsd = &vmstate_port92_isa;
/*
* Reason: unlike ordinary ISA devices, this one needs additional
* wiring: its A20 output line needs to be wired up with
* qdev_connect_gpio_out_named().
*/
dc->user_creatable = false;
}
static const TypeInfo port92_info = {
.name = TYPE_PORT92,
.parent = TYPE_ISA_DEVICE,
.instance_size = sizeof(Port92State),
.instance_init = port92_initfn,
.class_init = port92_class_initfn,
};
static void port92_register_types(void)
{
type_register_static(&port92_info);
}
type_init(port92_register_types)

View file

@ -111,3 +111,11 @@ amdvi_ir_irte_ga_val(uint64_t hi, uint64_t lo) "hi 0x%"PRIx64" lo 0x%"PRIx64
# vmport.c # vmport.c
vmport_register(unsigned char command, void *func, void *opaque) "command: 0x%02x func: %p opaque: %p" vmport_register(unsigned char command, void *func, void *opaque) "command: 0x%02x func: %p opaque: %p"
vmport_command(unsigned char command) "command: 0x%02x" vmport_command(unsigned char command) "command: 0x%02x"
# x86.c
x86_gsi_interrupt(int irqn, int level) "GSI interrupt #%d level:%d"
x86_pic_interrupt(int irqn, int level) "PIC interrupt #%d level:%d"
# port92.c
port92_read(uint8_t val) "port92: read 0x%02x"
port92_write(uint8_t val) "port92: write 0x%02x"

34
hw/i386/x86-iommu-stub.c Normal file
View file

@ -0,0 +1,34 @@
/*
* Stubs for X86 IOMMU emulation
*
* Copyright (C) 2019 Red Hat, Inc.
*
* Author: Paolo Bonzini <pbonzini@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h"
#include "hw/i386/x86-iommu.h"
void x86_iommu_iec_register_notifier(X86IOMMUState *iommu,
iec_notify_fn fn, void *data)
{
}
X86IOMMUState *x86_iommu_get_default(void)
{
return NULL;
}

View file

@ -34,18 +34,23 @@
#include "sysemu/numa.h" #include "sysemu/numa.h"
#include "sysemu/replay.h" #include "sysemu/replay.h"
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
#include "trace.h"
#include "hw/i386/x86.h" #include "hw/i386/x86.h"
#include "target/i386/cpu.h" #include "target/i386/cpu.h"
#include "hw/i386/topology.h" #include "hw/i386/topology.h"
#include "hw/i386/fw_cfg.h" #include "hw/i386/fw_cfg.h"
#include "hw/intc/i8259.h"
#include "hw/acpi/cpu_hotplug.h" #include "hw/acpi/cpu_hotplug.h"
#include "hw/irq.h"
#include "hw/nmi.h" #include "hw/nmi.h"
#include "hw/loader.h" #include "hw/loader.h"
#include "multiboot.h" #include "multiboot.h"
#include "elf.h" #include "elf.h"
#include "standard-headers/asm-x86/bootparam.h" #include "standard-headers/asm-x86/bootparam.h"
#include "config-devices.h"
#include "kvm_i386.h"
#define BIOS_FILENAME "bios.bin" #define BIOS_FILENAME "bios.bin"
@ -220,6 +225,105 @@ static long get_file_size(FILE *f)
return size; return size;
} }
/* TSC handling */
uint64_t cpu_get_tsc(CPUX86State *env)
{
return cpu_get_ticks();
}
/* IRQ handling */
static void pic_irq_request(void *opaque, int irq, int level)
{
CPUState *cs = first_cpu;
X86CPU *cpu = X86_CPU(cs);
trace_x86_pic_interrupt(irq, level);
if (cpu->apic_state && !kvm_irqchip_in_kernel()) {
CPU_FOREACH(cs) {
cpu = X86_CPU(cs);
if (apic_accept_pic_intr(cpu->apic_state)) {
apic_deliver_pic_intr(cpu->apic_state, level);
}
}
} else {
if (level) {
cpu_interrupt(cs, CPU_INTERRUPT_HARD);
} else {
cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
}
}
}
qemu_irq x86_allocate_cpu_irq(void)
{
return qemu_allocate_irq(pic_irq_request, NULL, 0);
}
int cpu_get_pic_interrupt(CPUX86State *env)
{
X86CPU *cpu = env_archcpu(env);
int intno;
if (!kvm_irqchip_in_kernel()) {
intno = apic_get_interrupt(cpu->apic_state);
if (intno >= 0) {
return intno;
}
/* read the irq from the PIC */
if (!apic_accept_pic_intr(cpu->apic_state)) {
return -1;
}
}
intno = pic_read_irq(isa_pic);
return intno;
}
DeviceState *cpu_get_current_apic(void)
{
if (current_cpu) {
X86CPU *cpu = X86_CPU(current_cpu);
return cpu->apic_state;
} else {
return NULL;
}
}
void gsi_handler(void *opaque, int n, int level)
{
GSIState *s = opaque;
trace_x86_gsi_interrupt(n, level);
if (n < ISA_NUM_IRQS) {
/* Under KVM, Kernel will forward to both PIC and IOAPIC */
qemu_set_irq(s->i8259_irq[n], level);
}
qemu_set_irq(s->ioapic_irq[n], level);
}
void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name)
{
DeviceState *dev;
SysBusDevice *d;
unsigned int i;
assert(parent_name);
if (kvm_ioapic_in_kernel()) {
dev = qdev_create(NULL, TYPE_KVM_IOAPIC);
} else {
dev = qdev_create(NULL, TYPE_IOAPIC);
}
object_property_add_child(object_resolve_path(parent_name, NULL),
"ioapic", OBJECT(dev), NULL);
qdev_init_nofail(dev);
d = SYS_BUS_DEVICE(dev);
sysbus_mmio_map(d, 0, IO_APIC_DEFAULT_ADDRESS);
for (i = 0; i < IOAPIC_NUM_PINS; i++) {
gsi_state->ioapic_irq[i] = qdev_get_gpio_in(dev, i);
}
}
struct setup_data { struct setup_data {
uint64_t next; uint64_t next;
uint32_t type; uint32_t type;
@ -745,10 +849,53 @@ static void x86_machine_set_max_ram_below_4g(Object *obj, Visitor *v,
x86ms->max_ram_below_4g = value; x86ms->max_ram_below_4g = value;
} }
bool x86_machine_is_smm_enabled(X86MachineState *x86ms)
{
bool smm_available = false;
if (x86ms->smm == ON_OFF_AUTO_OFF) {
return false;
}
if (tcg_enabled() || qtest_enabled()) {
smm_available = true;
} else if (kvm_enabled()) {
smm_available = kvm_has_smm();
}
if (smm_available) {
return true;
}
if (x86ms->smm == ON_OFF_AUTO_ON) {
error_report("System Management Mode not supported by this hypervisor.");
exit(1);
}
return false;
}
static void x86_machine_get_smm(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
X86MachineState *x86ms = X86_MACHINE(obj);
OnOffAuto smm = x86ms->smm;
visit_type_OnOffAuto(v, name, &smm, errp);
}
static void x86_machine_set_smm(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
X86MachineState *x86ms = X86_MACHINE(obj);
visit_type_OnOffAuto(v, name, &x86ms->smm, errp);
}
static void x86_machine_initfn(Object *obj) static void x86_machine_initfn(Object *obj)
{ {
X86MachineState *x86ms = X86_MACHINE(obj); X86MachineState *x86ms = X86_MACHINE(obj);
x86ms->smm = ON_OFF_AUTO_AUTO;
x86ms->max_ram_below_4g = 0; /* use default */ x86ms->max_ram_below_4g = 0; /* use default */
x86ms->smp_dies = 1; x86ms->smp_dies = 1;
} }
@ -769,9 +916,14 @@ static void x86_machine_class_init(ObjectClass *oc, void *data)
object_class_property_add(oc, X86_MACHINE_MAX_RAM_BELOW_4G, "size", object_class_property_add(oc, X86_MACHINE_MAX_RAM_BELOW_4G, "size",
x86_machine_get_max_ram_below_4g, x86_machine_set_max_ram_below_4g, x86_machine_get_max_ram_below_4g, x86_machine_set_max_ram_below_4g,
NULL, NULL, &error_abort); NULL, NULL, &error_abort);
object_class_property_set_description(oc, X86_MACHINE_MAX_RAM_BELOW_4G, object_class_property_set_description(oc, X86_MACHINE_MAX_RAM_BELOW_4G,
"Maximum ram below the 4G boundary (32bit boundary)", &error_abort); "Maximum ram below the 4G boundary (32bit boundary)", &error_abort);
object_class_property_add(oc, X86_MACHINE_SMM, "OnOffAuto",
x86_machine_get_smm, x86_machine_set_smm,
NULL, NULL, &error_abort);
object_class_property_set_description(oc, X86_MACHINE_SMM,
"Enable SMM", &error_abort);
} }
static const TypeInfo x86_machine_info = { static const TypeInfo x86_machine_info = {

View file

@ -26,7 +26,6 @@
#include "qemu/log.h" #include "qemu/log.h"
#include "hw/isa/isa.h" #include "hw/isa/isa.h"
#include "migration/vmstate.h" #include "migration/vmstate.h"
#include "hw/i386/pc.h"
#include "hw/input/ps2.h" #include "hw/input/ps2.h"
#include "hw/irq.h" #include "hw/irq.h"
#include "hw/input/i8042.h" #include "hw/input/i8042.h"

View file

@ -9,6 +9,7 @@ config PL190
config IOAPIC config IOAPIC
bool bool
select I8259
config ARM_GIC config ARM_GIC
bool bool
@ -21,6 +22,7 @@ config OPENPIC
config APIC config APIC
bool bool
select MSI_NONBROKEN select MSI_NONBROKEN
select I8259
config ARM_GIC_KVM config ARM_GIC_KVM
bool bool

View file

@ -22,10 +22,10 @@
#include "hw/i386/apic_internal.h" #include "hw/i386/apic_internal.h"
#include "hw/i386/apic.h" #include "hw/i386/apic.h"
#include "hw/i386/ioapic.h" #include "hw/i386/ioapic.h"
#include "hw/intc/i8259.h"
#include "hw/pci/msi.h" #include "hw/pci/msi.h"
#include "qemu/host-utils.h" #include "qemu/host-utils.h"
#include "trace.h" #include "trace.h"
#include "hw/i386/pc.h"
#include "hw/i386/apic-msidef.h" #include "hw/i386/apic-msidef.h"
#include "qapi/error.h" #include "qapi/error.h"

View file

@ -23,7 +23,7 @@
*/ */
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "hw/i386/pc.h" #include "hw/intc/i8259.h"
#include "hw/irq.h" #include "hw/irq.h"
#include "hw/isa/isa.h" #include "hw/isa/isa.h"
#include "qemu/timer.h" #include "qemu/timer.h"

View file

@ -24,7 +24,7 @@
*/ */
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "hw/i386/pc.h" #include "hw/intc/i8259.h"
#include "hw/isa/i8259_internal.h" #include "hw/isa/i8259_internal.h"
#include "hw/qdev-properties.h" #include "hw/qdev-properties.h"
#include "migration/vmstate.h" #include "migration/vmstate.h"

View file

@ -23,10 +23,11 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "monitor/monitor.h" #include "monitor/monitor.h"
#include "hw/i386/pc.h"
#include "hw/i386/apic.h" #include "hw/i386/apic.h"
#include "hw/i386/ioapic.h" #include "hw/i386/ioapic.h"
#include "hw/i386/ioapic_internal.h" #include "hw/i386/ioapic_internal.h"
#include "hw/i386/x86.h"
#include "hw/intc/i8259.h"
#include "hw/pci/msi.h" #include "hw/pci/msi.h"
#include "hw/qdev-properties.h" #include "hw/qdev-properties.h"
#include "sysemu/kvm.h" #include "sysemu/kvm.h"

View file

@ -19,8 +19,8 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "hw/pci/pci.h" #include "hw/pci/pci.h"
#include "hw/i386/pc.h"
#include "hw/irq.h" #include "hw/irq.h"
#include "hw/intc/i8259.h"
#include "hw/timer/i8254.h" #include "hw/timer/i8254.h"
#include "migration/vmstate.h" #include "migration/vmstate.h"
#include "hw/audio/pcspk.h" #include "hw/audio/pcspk.h"

View file

@ -82,24 +82,27 @@ void isa_bus_irqs(ISABus *bus, qemu_irq *irqs)
* This function is only for special cases such as the 'ferr', and * This function is only for special cases such as the 'ferr', and
* temporary use for normal devices until they are converted to qdev. * temporary use for normal devices until they are converted to qdev.
*/ */
qemu_irq isa_get_irq(ISADevice *dev, int isairq) qemu_irq isa_get_irq(ISADevice *dev, unsigned isairq)
{ {
assert(!dev || ISA_BUS(qdev_get_parent_bus(DEVICE(dev))) == isabus); assert(!dev || ISA_BUS(qdev_get_parent_bus(DEVICE(dev))) == isabus);
if (isairq < 0 || isairq > 15) { if (isairq >= ISA_NUM_IRQS) {
hw_error("isa irq %d invalid", isairq); hw_error("isa irq %d invalid", isairq);
} }
return isabus->irqs[isairq]; return isabus->irqs[isairq];
} }
void isa_init_irq(ISADevice *dev, qemu_irq *p, int isairq) void isa_init_irq(ISADevice *dev, qemu_irq *p, unsigned isairq)
{ {
assert(dev->nirqs < ARRAY_SIZE(dev->isairq)); assert(dev->nirqs < ARRAY_SIZE(dev->isairq));
if (isairq >= ISA_NUM_IRQS) {
hw_error("isa irq %d invalid", isairq);
}
dev->isairq[dev->nirqs] = isairq; dev->isairq[dev->nirqs] = isairq;
*p = isa_get_irq(dev, isairq); *p = isa_get_irq(dev, isairq);
dev->nirqs++; dev->nirqs++;
} }
void isa_connect_gpio_out(ISADevice *isadev, int gpioirq, int isairq) void isa_connect_gpio_out(ISADevice *isadev, int gpioirq, unsigned isairq)
{ {
qemu_irq irq; qemu_irq irq;
isa_init_irq(isadev, &irq, isairq); isa_init_irq(isadev, &irq, isairq);

View file

@ -35,7 +35,6 @@
#include "hw/isa/isa.h" #include "hw/isa/isa.h"
#include "hw/sysbus.h" #include "hw/sysbus.h"
#include "migration/vmstate.h" #include "migration/vmstate.h"
#include "hw/i386/pc.h"
#include "hw/irq.h" #include "hw/irq.h"
#include "hw/isa/apm.h" #include "hw/isa/apm.h"
#include "hw/i386/ioapic.h" #include "hw/i386/ioapic.h"

View file

@ -26,11 +26,11 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "hw/irq.h" #include "hw/irq.h"
#include "hw/i386/pc.h"
#include "hw/southbridge/piix.h" #include "hw/southbridge/piix.h"
#include "hw/pci/pci.h" #include "hw/pci/pci.h"
#include "hw/isa/isa.h" #include "hw/isa/isa.h"
#include "hw/sysbus.h" #include "hw/sysbus.h"
#include "hw/intc/i8259.h"
#include "hw/dma/i8257.h" #include "hw/dma/i8257.h"
#include "hw/timer/i8254.h" #include "hw/timer/i8254.h"
#include "hw/rtc/mc146818rtc.h" #include "hw/rtc/mc146818rtc.h"

View file

@ -30,7 +30,7 @@
#include "hw/pci/pci_host.h" #include "hw/pci/pci_host.h"
#include "hw/southbridge/piix.h" #include "hw/southbridge/piix.h"
#include "migration/vmstate.h" #include "migration/vmstate.h"
#include "hw/i386/pc.h" #include "hw/intc/i8259.h"
#include "hw/irq.h" #include "hw/irq.h"
#include "exec/address-spaces.h" #include "exec/address-spaces.h"
#include "trace.h" #include "trace.h"

View file

@ -23,7 +23,7 @@
#include "qemu/units.h" #include "qemu/units.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "cpu.h" #include "cpu.h"
#include "hw/i386/pc.h" #include "hw/intc/i8259.h"
#include "hw/dma/i8257.h" #include "hw/dma/i8257.h"
#include "hw/isa/superio.h" #include "hw/isa/superio.h"
#include "net/net.h" #include "net/net.h"

View file

@ -26,7 +26,7 @@
#include "qemu-common.h" #include "qemu-common.h"
#include "hw/mips/mips.h" #include "hw/mips/mips.h"
#include "hw/mips/cpudevs.h" #include "hw/mips/cpudevs.h"
#include "hw/i386/pc.h" #include "hw/intc/i8259.h"
#include "hw/dma/i8257.h" #include "hw/dma/i8257.h"
#include "hw/char/serial.h" #include "hw/char/serial.h"
#include "hw/char/parallel.h" #include "hw/char/parallel.h"

View file

@ -15,7 +15,7 @@
#include "cpu.h" #include "cpu.h"
#include "hw/mips/mips.h" #include "hw/mips/mips.h"
#include "hw/mips/cpudevs.h" #include "hw/mips/cpudevs.h"
#include "hw/i386/pc.h" #include "hw/intc/i8259.h"
#include "hw/char/serial.h" #include "hw/char/serial.h"
#include "hw/isa/isa.h" #include "hw/isa/isa.h"
#include "net/net.h" #include "net/net.h"

View file

@ -1,6 +1,11 @@
config PAM config PAM
bool bool
config XEN_IGD_PASSTHROUGH
bool
default y
depends on XEN && PCI_I440FX
config PREP_PCI config PREP_PCI
bool bool
select PCI select PCI

View file

@ -14,6 +14,7 @@ common-obj-$(CONFIG_VERSATILE_PCI) += versatile.o
common-obj-$(CONFIG_PCI_SABRE) += sabre.o common-obj-$(CONFIG_PCI_SABRE) += sabre.o
common-obj-$(CONFIG_FULONG) += bonito.o common-obj-$(CONFIG_FULONG) += bonito.o
common-obj-$(CONFIG_PCI_I440FX) += i440fx.o common-obj-$(CONFIG_PCI_I440FX) += i440fx.o
common-obj-$(CONFIG_XEN_IGD_PASSTHROUGH) += xen_igd_pt.o
common-obj-$(CONFIG_PCI_EXPRESS_Q35) += q35.o common-obj-$(CONFIG_PCI_EXPRESS_Q35) += q35.o
common-obj-$(CONFIG_PCI_EXPRESS_GENERIC_BRIDGE) += gpex.o common-obj-$(CONFIG_PCI_EXPRESS_GENERIC_BRIDGE) += gpex.o
common-obj-$(CONFIG_PCI_EXPRESS_XILINX) += xilinx-pcie.o common-obj-$(CONFIG_PCI_EXPRESS_XILINX) += xilinx-pcie.o

View file

@ -41,7 +41,6 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "hw/pci/pci.h" #include "hw/pci/pci.h"
#include "hw/i386/pc.h"
#include "hw/irq.h" #include "hw/irq.h"
#include "hw/mips/mips.h" #include "hw/mips/mips.h"
#include "hw/pci/pci_host.h" #include "hw/pci/pci_host.h"

View file

@ -1,5 +1,5 @@
/* /*
* QEMU i440FX/PIIX3 PCI Bridge Emulation * QEMU i440FX PCI Bridge Emulation
* *
* Copyright (c) 2006 Fabrice Bellard * Copyright (c) 2006 Fabrice Bellard
* *
@ -31,7 +31,6 @@
#include "hw/sysbus.h" #include "hw/sysbus.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "migration/vmstate.h" #include "migration/vmstate.h"
#include "hw/pci-host/pam.h"
#include "qapi/visitor.h" #include "qapi/visitor.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
@ -51,23 +50,6 @@ typedef struct I440FXState {
uint32_t short_root_bus; uint32_t short_root_bus;
} I440FXState; } I440FXState;
#define I440FX_PCI_DEVICE(obj) \
OBJECT_CHECK(PCII440FXState, (obj), TYPE_I440FX_PCI_DEVICE)
struct PCII440FXState {
/*< private >*/
PCIDevice parent_obj;
/*< public >*/
MemoryRegion *system_memory;
MemoryRegion *pci_address_space;
MemoryRegion *ram_memory;
PAMMemoryRegion pam_regions[13];
MemoryRegion smram_region;
MemoryRegion smram, low_smram;
};
#define I440FX_PAM 0x59 #define I440FX_PAM 0x59
#define I440FX_PAM_SIZE 7 #define I440FX_PAM_SIZE 7
#define I440FX_SMRAM 0x72 #define I440FX_SMRAM 0x72
@ -386,90 +368,6 @@ static const TypeInfo i440fx_info = {
}, },
}; };
/* IGD Passthrough Host Bridge. */
typedef struct {
uint8_t offset;
uint8_t len;
} IGDHostInfo;
/* Here we just expose minimal host bridge offset subset. */
static const IGDHostInfo igd_host_bridge_infos[] = {
{0x08, 2}, /* revision id */
{0x2c, 2}, /* sybsystem vendor id */
{0x2e, 2}, /* sybsystem id */
{0x50, 2}, /* SNB: processor graphics control register */
{0x52, 2}, /* processor graphics control register */
{0xa4, 4}, /* SNB: graphics base of stolen memory */
{0xa8, 4}, /* SNB: base of GTT stolen memory */
};
static void host_pci_config_read(int pos, int len, uint32_t *val, Error **errp)
{
int rc, config_fd;
/* Access real host bridge. */
char *path = g_strdup_printf("/sys/bus/pci/devices/%04x:%02x:%02x.%d/%s",
0, 0, 0, 0, "config");
config_fd = open(path, O_RDWR);
if (config_fd < 0) {
error_setg_errno(errp, errno, "Failed to open: %s", path);
goto out;
}
if (lseek(config_fd, pos, SEEK_SET) != pos) {
error_setg_errno(errp, errno, "Failed to seek: %s", path);
goto out_close_fd;
}
do {
rc = read(config_fd, (uint8_t *)val, len);
} while (rc < 0 && (errno == EINTR || errno == EAGAIN));
if (rc != len) {
error_setg_errno(errp, errno, "Failed to read: %s", path);
}
out_close_fd:
close(config_fd);
out:
g_free(path);
}
static void igd_pt_i440fx_realize(PCIDevice *pci_dev, Error **errp)
{
uint32_t val = 0;
int i, num;
int pos, len;
Error *local_err = NULL;
num = ARRAY_SIZE(igd_host_bridge_infos);
for (i = 0; i < num; i++) {
pos = igd_host_bridge_infos[i].offset;
len = igd_host_bridge_infos[i].len;
host_pci_config_read(pos, len, &val, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
pci_default_write_config(pci_dev, pos, val, len);
}
}
static void igd_passthrough_i440fx_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
k->realize = igd_pt_i440fx_realize;
dc->desc = "IGD Passthrough Host bridge";
}
static const TypeInfo igd_passthrough_i440fx_info = {
.name = TYPE_IGD_PASSTHROUGH_I440FX_PCI_DEVICE,
.parent = TYPE_I440FX_PCI_DEVICE,
.instance_size = sizeof(PCII440FXState),
.class_init = igd_passthrough_i440fx_class_init,
};
static const char *i440fx_pcihost_root_bus_path(PCIHostState *host_bridge, static const char *i440fx_pcihost_root_bus_path(PCIHostState *host_bridge,
PCIBus *rootbus) PCIBus *rootbus)
{ {
@ -514,7 +412,6 @@ static const TypeInfo i440fx_pcihost_info = {
static void i440fx_register_types(void) static void i440fx_register_types(void)
{ {
type_register_static(&i440fx_info); type_register_static(&i440fx_info);
type_register_static(&igd_passthrough_i440fx_info);
type_register_static(&i440fx_pcihost_info); type_register_static(&i440fx_pcihost_info);
} }

View file

@ -32,7 +32,7 @@
#include "hw/pci/pci_host.h" #include "hw/pci/pci_host.h"
#include "hw/qdev-properties.h" #include "hw/qdev-properties.h"
#include "migration/vmstate.h" #include "migration/vmstate.h"
#include "hw/i386/pc.h" #include "hw/intc/i8259.h"
#include "hw/irq.h" #include "hw/irq.h"
#include "hw/loader.h" #include "hw/loader.h"
#include "hw/or-irq.h" #include "hw/or-irq.h"

120
hw/pci-host/xen_igd_pt.c Normal file
View file

@ -0,0 +1,120 @@
/*
* QEMU Intel IGD Passthrough Host Bridge Emulation
*
* Copyright (c) 2006 Fabrice Bellard
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "qemu/osdep.h"
#include "hw/pci/pci.h"
#include "hw/pci/pci_host.h"
#include "hw/pci-host/i440fx.h"
#include "qapi/error.h"
typedef struct {
uint8_t offset;
uint8_t len;
} IGDHostInfo;
/* Here we just expose minimal host bridge offset subset. */
static const IGDHostInfo igd_host_bridge_infos[] = {
{PCI_REVISION_ID, 2},
{PCI_SUBSYSTEM_VENDOR_ID, 2},
{PCI_SUBSYSTEM_ID, 2},
{0x50, 2}, /* SNB: processor graphics control register */
{0x52, 2}, /* processor graphics control register */
{0xa4, 4}, /* SNB: graphics base of stolen memory */
{0xa8, 4}, /* SNB: base of GTT stolen memory */
};
static void host_pci_config_read(int pos, int len, uint32_t *val, Error **errp)
{
int rc, config_fd;
/* Access real host bridge. */
char *path = g_strdup_printf("/sys/bus/pci/devices/%04x:%02x:%02x.%d/%s",
0, 0, 0, 0, "config");
config_fd = open(path, O_RDWR);
if (config_fd < 0) {
error_setg_errno(errp, errno, "Failed to open: %s", path);
goto out;
}
if (lseek(config_fd, pos, SEEK_SET) != pos) {
error_setg_errno(errp, errno, "Failed to seek: %s", path);
goto out_close_fd;
}
do {
rc = read(config_fd, (uint8_t *)val, len);
} while (rc < 0 && (errno == EINTR || errno == EAGAIN));
if (rc != len) {
error_setg_errno(errp, errno, "Failed to read: %s", path);
}
out_close_fd:
close(config_fd);
out:
g_free(path);
}
static void igd_pt_i440fx_realize(PCIDevice *pci_dev, Error **errp)
{
uint32_t val = 0;
size_t i;
int pos, len;
Error *local_err = NULL;
for (i = 0; i < ARRAY_SIZE(igd_host_bridge_infos); i++) {
pos = igd_host_bridge_infos[i].offset;
len = igd_host_bridge_infos[i].len;
host_pci_config_read(pos, len, &val, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
pci_default_write_config(pci_dev, pos, val, len);
}
}
static void igd_passthrough_i440fx_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
k->realize = igd_pt_i440fx_realize;
dc->desc = "IGD Passthrough Host bridge";
}
static const TypeInfo igd_passthrough_i440fx_info = {
.name = TYPE_IGD_PASSTHROUGH_I440FX_PCI_DEVICE,
.parent = TYPE_I440FX_PCI_DEVICE,
.instance_size = sizeof(PCII440FXState),
.class_init = igd_passthrough_i440fx_class_init,
};
static void igd_pt_i440fx_register_types(void)
{
type_register_static(&igd_passthrough_i440fx_info);
}
type_init(igd_pt_i440fx_register_types)

View file

@ -26,6 +26,7 @@
#include "qapi/qmp/qerror.h" #include "qapi/qmp/qerror.h"
#include "hw/pci/pci.h" #include "hw/pci/pci.h"
#include "hw/pci/msi.h" #include "hw/pci/msi.h"
#include "hw/pci/msix.h"
bool msi_nonbroken; bool msi_nonbroken;
bool pci_available; bool pci_available;
@ -64,3 +65,29 @@ void msi_notify(PCIDevice *dev, unsigned int vector)
{ {
g_assert_not_reached(); g_assert_not_reached();
} }
/* Required by target/i386/kvm.c */
bool msi_is_masked(const PCIDevice *dev, unsigned vector)
{
g_assert_not_reached();
}
MSIMessage msi_get_message(PCIDevice *dev, unsigned int vector)
{
g_assert_not_reached();
}
int msix_enabled(PCIDevice *dev)
{
return false;
}
bool msix_is_masked(PCIDevice *dev, unsigned vector)
{
g_assert_not_reached();
}
MSIMessage msix_get_message(PCIDevice *dev, unsigned int vector)
{
g_assert_not_reached();
}

View file

@ -69,8 +69,6 @@ static Property pci_props[] = {
DEFINE_PROP_UINT32("rombar", PCIDevice, rom_bar, 1), DEFINE_PROP_UINT32("rombar", PCIDevice, rom_bar, 1),
DEFINE_PROP_BIT("multifunction", PCIDevice, cap_present, DEFINE_PROP_BIT("multifunction", PCIDevice, cap_present,
QEMU_PCI_CAP_MULTIFUNCTION_BITNR, false), QEMU_PCI_CAP_MULTIFUNCTION_BITNR, false),
DEFINE_PROP_BIT("command_serr_enable", PCIDevice, cap_present,
QEMU_PCI_CAP_SERR_BITNR, true),
DEFINE_PROP_BIT("x-pcie-lnksta-dllla", PCIDevice, cap_present, DEFINE_PROP_BIT("x-pcie-lnksta-dllla", PCIDevice, cap_present,
QEMU_PCIE_LNKSTA_DLLLA_BITNR, true), QEMU_PCIE_LNKSTA_DLLLA_BITNR, true),
DEFINE_PROP_BIT("x-pcie-extcap-init", PCIDevice, cap_present, DEFINE_PROP_BIT("x-pcie-extcap-init", PCIDevice, cap_present,
@ -751,9 +749,7 @@ static void pci_init_wmask(PCIDevice *dev)
pci_set_word(dev->wmask + PCI_COMMAND, pci_set_word(dev->wmask + PCI_COMMAND,
PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
PCI_COMMAND_INTX_DISABLE); PCI_COMMAND_INTX_DISABLE);
if (dev->cap_present & QEMU_PCI_CAP_SERR) { pci_word_test_and_set_mask(dev->wmask + PCI_COMMAND, PCI_COMMAND_SERR);
pci_word_test_and_set_mask(dev->wmask + PCI_COMMAND, PCI_COMMAND_SERR);
}
memset(dev->wmask + PCI_CONFIG_HEADER_SIZE, 0xff, memset(dev->wmask + PCI_CONFIG_HEADER_SIZE, 0xff,
config_size - PCI_CONFIG_HEADER_SIZE); config_size - PCI_CONFIG_HEADER_SIZE);

View file

@ -793,7 +793,6 @@ static DeviceState *ppce500_init_mpic(PPCE500MachineState *pms,
MemoryRegion *ccsr, MemoryRegion *ccsr,
IrqLines *irqs) IrqLines *irqs)
{ {
MachineState *machine = MACHINE(pms);
const PPCE500MachineClass *pmc = PPCE500_MACHINE_GET_CLASS(pms); const PPCE500MachineClass *pmc = PPCE500_MACHINE_GET_CLASS(pms);
DeviceState *dev = NULL; DeviceState *dev = NULL;
SysBusDevice *s; SysBusDevice *s;
@ -801,10 +800,10 @@ static DeviceState *ppce500_init_mpic(PPCE500MachineState *pms,
if (kvm_enabled()) { if (kvm_enabled()) {
Error *err = NULL; Error *err = NULL;
if (machine_kernel_irqchip_allowed(machine)) { if (kvm_kernel_irqchip_allowed()) {
dev = ppce500_init_mpic_kvm(pmc, irqs, &err); dev = ppce500_init_mpic_kvm(pmc, irqs, &err);
} }
if (machine_kernel_irqchip_required(machine) && !dev) { if (kvm_kernel_irqchip_required() && !dev) {
error_reportf_err(err, error_reportf_err(err,
"kernel_irqchip requested but unavailable: "); "kernel_irqchip requested but unavailable: ");
exit(1); exit(1);

View file

@ -75,12 +75,11 @@ int spapr_irq_init_kvm(SpaprInterruptControllerInitKvm fn,
uint32_t nr_servers, uint32_t nr_servers,
Error **errp) Error **errp)
{ {
MachineState *machine = MACHINE(qdev_get_machine());
Error *local_err = NULL; Error *local_err = NULL;
if (kvm_enabled() && machine_kernel_irqchip_allowed(machine)) { if (kvm_enabled() && kvm_kernel_irqchip_allowed()) {
if (fn(intc, nr_servers, &local_err) < 0) { if (fn(intc, nr_servers, &local_err) < 0) {
if (machine_kernel_irqchip_required(machine)) { if (kvm_kernel_irqchip_required()) {
error_prepend(&local_err, error_prepend(&local_err,
"kernel_irqchip requested but unavailable: "); "kernel_irqchip requested but unavailable: ");
error_propagate(errp, local_err); error_propagate(errp, local_err);
@ -185,7 +184,7 @@ static int spapr_irq_check(SpaprMachineState *spapr, Error **errp)
*/ */
if (kvm_enabled() && if (kvm_enabled() &&
spapr->irq == &spapr_irq_dual && spapr->irq == &spapr_irq_dual &&
machine_kernel_irqchip_required(machine) && kvm_kernel_irqchip_required() &&
xics_kvm_has_broken_disconnect(spapr)) { xics_kvm_has_broken_disconnect(spapr)) {
error_setg(errp, "KVM is too old to support ic-mode=dual,kernel-irqchip=on"); error_setg(errp, "KVM is too old to support ic-mode=dual,kernel-irqchip=on");
return -1; return -1;
@ -288,20 +287,13 @@ uint32_t spapr_irq_nr_msis(SpaprMachineState *spapr)
void spapr_irq_init(SpaprMachineState *spapr, Error **errp) void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
{ {
MachineState *machine = MACHINE(spapr);
SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
if (machine_kernel_irqchip_split(machine)) { if (kvm_enabled() && kvm_kernel_irqchip_split()) {
error_setg(errp, "kernel_irqchip split mode not supported on pseries"); error_setg(errp, "kernel_irqchip split mode not supported on pseries");
return; return;
} }
if (!kvm_enabled() && machine_kernel_irqchip_required(machine)) {
error_setg(errp,
"kernel_irqchip requested but only available with KVM");
return;
}
if (spapr_irq_check(spapr, errp) < 0) { if (spapr_irq_check(spapr, errp) < 0) {
return; return;
} }

View file

@ -1,3 +1,6 @@
config VHOST
bool
config VIRTIO config VIRTIO
bool bool

View file

@ -2,8 +2,8 @@ ifeq ($(CONFIG_VIRTIO),y)
common-obj-y += virtio-bus.o common-obj-y += virtio-bus.o
obj-y += virtio.o obj-y += virtio.o
obj-$(call lor,$(CONFIG_VHOST_USER),$(CONFIG_VHOST_KERNEL)) += vhost.o vhost-backend.o obj-$(CONFIG_VHOST) += vhost.o vhost-backend.o
common-obj-$(call lnot,$(call lor,$(CONFIG_VHOST_USER),$(CONFIG_VHOST_KERNEL))) += vhost-stub.o common-obj-$(call lnot,$(CONFIG_VHOST)) += vhost-stub.o
obj-$(CONFIG_VHOST_USER) += vhost-user.o obj-$(CONFIG_VHOST_USER) += vhost-user.o
common-obj-$(CONFIG_VIRTIO_RNG) += virtio-rng.o common-obj-$(CONFIG_VIRTIO_RNG) += virtio-rng.o

View file

@ -11,7 +11,9 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "qemu/module.h" #include "qemu/module.h"
#include "qapi/error.h"
#include "hw/xen/xen-legacy-backend.h" #include "hw/xen/xen-legacy-backend.h"
#include "hw/xen/xen_pt.h"
#include "chardev/char.h" #include "chardev/char.h"
#include "sysemu/accel.h" #include "sysemu/accel.h"
#include "sysemu/runstate.h" #include "sysemu/runstate.h"
@ -124,6 +126,16 @@ static void xen_change_state_handler(void *opaque, int running,
} }
} }
static bool xen_get_igd_gfx_passthru(Object *obj, Error **errp)
{
return has_igd_gfx_passthru;
}
static void xen_set_igd_gfx_passthru(Object *obj, bool value, Error **errp)
{
has_igd_gfx_passthru = value;
}
static void xen_setup_post(MachineState *ms, AccelState *accel) static void xen_setup_post(MachineState *ms, AccelState *accel)
{ {
int rc; int rc;
@ -177,6 +189,12 @@ static void xen_accel_class_init(ObjectClass *oc, void *data)
ac->compat_props = g_ptr_array_new(); ac->compat_props = g_ptr_array_new();
compat_props_add(ac->compat_props, compat, G_N_ELEMENTS(compat)); compat_props_add(ac->compat_props, compat, G_N_ELEMENTS(compat));
object_class_property_add_bool(oc, "igd-passthru",
xen_get_igd_gfx_passthru, xen_set_igd_gfx_passthru,
&error_abort);
object_class_property_set_description(oc, "igd-passthru",
"Set on/off to enable/disable igd passthrou", &error_abort);
} }
#define TYPE_XEN_ACCEL ACCEL_CLASS_NAME("xen") #define TYPE_XEN_ACCEL ACCEL_CLASS_NAME("xen")

View file

@ -65,6 +65,8 @@
#include "qemu/range.h" #include "qemu/range.h"
#include "exec/address-spaces.h" #include "exec/address-spaces.h"
bool has_igd_gfx_passthru;
#define XEN_PT_NR_IRQS (256) #define XEN_PT_NR_IRQS (256)
static uint8_t xen_pt_mapped_machine_irq[XEN_PT_NR_IRQS] = {0}; static uint8_t xen_pt_mapped_machine_irq[XEN_PT_NR_IRQS] = {0};

View file

@ -360,10 +360,14 @@ typedef struct IOMMUMemoryRegionClass {
typedef struct CoalescedMemoryRange CoalescedMemoryRange; typedef struct CoalescedMemoryRange CoalescedMemoryRange;
typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd; typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd;
/** MemoryRegion:
*
* A struct representing a memory region.
*/
struct MemoryRegion { struct MemoryRegion {
Object parent_obj; Object parent_obj;
/* All fields are private - violators will be prosecuted */ /* private: */
/* The following fields should fit in a cache line */ /* The following fields should fit in a cache line */
bool romd_mode; bool romd_mode;
@ -419,30 +423,232 @@ struct IOMMUMemoryRegion {
* Use with memory_listener_register() and memory_listener_unregister(). * Use with memory_listener_register() and memory_listener_unregister().
*/ */
struct MemoryListener { struct MemoryListener {
/**
* @begin:
*
* Called at the beginning of an address space update transaction.
* Followed by calls to #MemoryListener.region_add(),
* #MemoryListener.region_del(), #MemoryListener.region_nop(),
* #MemoryListener.log_start() and #MemoryListener.log_stop() in
* increasing address order.
*
* @listener: The #MemoryListener.
*/
void (*begin)(MemoryListener *listener); void (*begin)(MemoryListener *listener);
/**
* @commit:
*
* Called at the end of an address space update transaction,
* after the last call to #MemoryListener.region_add(),
* #MemoryListener.region_del() or #MemoryListener.region_nop(),
* #MemoryListener.log_start() and #MemoryListener.log_stop().
*
* @listener: The #MemoryListener.
*/
void (*commit)(MemoryListener *listener); void (*commit)(MemoryListener *listener);
/**
* @region_add:
*
* Called during an address space update transaction,
* for a section of the address space that is new in this address space
* space since the last transaction.
*
* @listener: The #MemoryListener.
* @section: The new #MemoryRegionSection.
*/
void (*region_add)(MemoryListener *listener, MemoryRegionSection *section); void (*region_add)(MemoryListener *listener, MemoryRegionSection *section);
/**
* @region_del:
*
* Called during an address space update transaction,
* for a section of the address space that has disappeared in the address
* space since the last transaction.
*
* @listener: The #MemoryListener.
* @section: The old #MemoryRegionSection.
*/
void (*region_del)(MemoryListener *listener, MemoryRegionSection *section); void (*region_del)(MemoryListener *listener, MemoryRegionSection *section);
/**
* @region_nop:
*
* Called during an address space update transaction,
* for a section of the address space that is in the same place in the address
* space as in the last transaction.
*
* @listener: The #MemoryListener.
* @section: The #MemoryRegionSection.
*/
void (*region_nop)(MemoryListener *listener, MemoryRegionSection *section); void (*region_nop)(MemoryListener *listener, MemoryRegionSection *section);
/**
* @log_start:
*
* Called during an address space update transaction, after
* one of #MemoryListener.region_add(),#MemoryListener.region_del() or
* #MemoryListener.region_nop(), if dirty memory logging clients have
* become active since the last transaction.
*
* @listener: The #MemoryListener.
* @section: The #MemoryRegionSection.
* @old: A bitmap of dirty memory logging clients that were active in
* the previous transaction.
* @new: A bitmap of dirty memory logging clients that are active in
* the current transaction.
*/
void (*log_start)(MemoryListener *listener, MemoryRegionSection *section, void (*log_start)(MemoryListener *listener, MemoryRegionSection *section,
int old, int new); int old, int new);
/**
* @log_stop:
*
* Called during an address space update transaction, after
* one of #MemoryListener.region_add(), #MemoryListener.region_del() or
* #MemoryListener.region_nop() and possibly after
* #MemoryListener.log_start(), if dirty memory logging clients have
* become inactive since the last transaction.
*
* @listener: The #MemoryListener.
* @section: The #MemoryRegionSection.
* @old: A bitmap of dirty memory logging clients that were active in
* the previous transaction.
* @new: A bitmap of dirty memory logging clients that are active in
* the current transaction.
*/
void (*log_stop)(MemoryListener *listener, MemoryRegionSection *section, void (*log_stop)(MemoryListener *listener, MemoryRegionSection *section,
int old, int new); int old, int new);
/**
* @log_sync:
*
* Called by memory_region_snapshot_and_clear_dirty() and
* memory_global_dirty_log_sync(), before accessing QEMU's "official"
* copy of the dirty memory bitmap for a #MemoryRegionSection.
*
* @listener: The #MemoryListener.
* @section: The #MemoryRegionSection.
*/
void (*log_sync)(MemoryListener *listener, MemoryRegionSection *section); void (*log_sync)(MemoryListener *listener, MemoryRegionSection *section);
/**
* @log_clear:
*
* Called before reading the dirty memory bitmap for a
* #MemoryRegionSection.
*
* @listener: The #MemoryListener.
* @section: The #MemoryRegionSection.
*/
void (*log_clear)(MemoryListener *listener, MemoryRegionSection *section); void (*log_clear)(MemoryListener *listener, MemoryRegionSection *section);
/**
* @log_global_start:
*
* Called by memory_global_dirty_log_start(), which
* enables the %DIRTY_LOG_MIGRATION client on all memory regions in
* the address space. #MemoryListener.log_global_start() is also
* called when a #MemoryListener is added, if global dirty logging is
* active at that time.
*
* @listener: The #MemoryListener.
*/
void (*log_global_start)(MemoryListener *listener); void (*log_global_start)(MemoryListener *listener);
/**
* @log_global_stop:
*
* Called by memory_global_dirty_log_stop(), which
* disables the %DIRTY_LOG_MIGRATION client on all memory regions in
* the address space.
*
* @listener: The #MemoryListener.
*/
void (*log_global_stop)(MemoryListener *listener); void (*log_global_stop)(MemoryListener *listener);
/**
* @log_global_after_sync:
*
* Called after reading the dirty memory bitmap
* for any #MemoryRegionSection.
*
* @listener: The #MemoryListener.
*/
void (*log_global_after_sync)(MemoryListener *listener); void (*log_global_after_sync)(MemoryListener *listener);
/**
* @eventfd_add:
*
* Called during an address space update transaction,
* for a section of the address space that has had a new ioeventfd
* registration since the last transaction.
*
* @listener: The #MemoryListener.
* @section: The new #MemoryRegionSection.
* @match_data: The @match_data parameter for the new ioeventfd.
* @data: The @data parameter for the new ioeventfd.
* @e: The #EventNotifier parameter for the new ioeventfd.
*/
void (*eventfd_add)(MemoryListener *listener, MemoryRegionSection *section, void (*eventfd_add)(MemoryListener *listener, MemoryRegionSection *section,
bool match_data, uint64_t data, EventNotifier *e); bool match_data, uint64_t data, EventNotifier *e);
/**
* @eventfd_del:
*
* Called during an address space update transaction,
* for a section of the address space that has dropped an ioeventfd
* registration since the last transaction.
*
* @listener: The #MemoryListener.
* @section: The new #MemoryRegionSection.
* @match_data: The @match_data parameter for the dropped ioeventfd.
* @data: The @data parameter for the dropped ioeventfd.
* @e: The #EventNotifier parameter for the dropped ioeventfd.
*/
void (*eventfd_del)(MemoryListener *listener, MemoryRegionSection *section, void (*eventfd_del)(MemoryListener *listener, MemoryRegionSection *section,
bool match_data, uint64_t data, EventNotifier *e); bool match_data, uint64_t data, EventNotifier *e);
/**
* @coalesced_io_add:
*
* Called during an address space update transaction,
* for a section of the address space that has had a new coalesced
* MMIO range registration since the last transaction.
*
* @listener: The #MemoryListener.
* @section: The new #MemoryRegionSection.
* @addr: The starting address for the coalesced MMIO range.
* @len: The length of the coalesced MMIO range.
*/
void (*coalesced_io_add)(MemoryListener *listener, MemoryRegionSection *section, void (*coalesced_io_add)(MemoryListener *listener, MemoryRegionSection *section,
hwaddr addr, hwaddr len); hwaddr addr, hwaddr len);
/**
* @coalesced_io_del:
*
* Called during an address space update transaction,
* for a section of the address space that has dropped a coalesced
* MMIO range since the last transaction.
*
* @listener: The #MemoryListener.
* @section: The new #MemoryRegionSection.
* @addr: The starting address for the coalesced MMIO range.
* @len: The length of the coalesced MMIO range.
*/
void (*coalesced_io_del)(MemoryListener *listener, MemoryRegionSection *section, void (*coalesced_io_del)(MemoryListener *listener, MemoryRegionSection *section,
hwaddr addr, hwaddr len); hwaddr addr, hwaddr len);
/* Lower = earlier (during add), later (during del) */ /**
* @priority:
*
* Govern the order in which memory listeners are invoked. Lower priorities
* are invoked earlier for "add" or "start" callbacks, and later for "delete"
* or "stop" callbacks.
*/
unsigned priority; unsigned priority;
/* private: */
AddressSpace *address_space; AddressSpace *address_space;
QTAILQ_ENTRY(MemoryListener) link; QTAILQ_ENTRY(MemoryListener) link;
QTAILQ_ENTRY(MemoryListener) link_as; QTAILQ_ENTRY(MemoryListener) link_as;
@ -452,7 +658,7 @@ struct MemoryListener {
* AddressSpace: describes a mapping of addresses to #MemoryRegion objects * AddressSpace: describes a mapping of addresses to #MemoryRegion objects
*/ */
struct AddressSpace { struct AddressSpace {
/* All fields are private. */ /* private: */
struct rcu_head rcu; struct rcu_head rcu;
char *name; char *name;
MemoryRegion *root; MemoryRegion *root;
@ -936,6 +1142,7 @@ void memory_region_init_rom(MemoryRegion *mr,
* @mr: the #MemoryRegion to be initialized. * @mr: the #MemoryRegion to be initialized.
* @owner: the object that tracks the region's reference count * @owner: the object that tracks the region's reference count
* @ops: callbacks for write access handling (must not be NULL). * @ops: callbacks for write access handling (must not be NULL).
* @opaque: passed to the read and write callbacks of the @ops structure.
* @name: Region name, becomes part of RAMBlock name used in migration stream * @name: Region name, becomes part of RAMBlock name used in migration stream
* must be unique within any device * must be unique within any device
* @size: size of the region. * @size: size of the region.
@ -1024,7 +1231,7 @@ static inline IOMMUMemoryRegion *memory_region_get_iommu(MemoryRegion *mr)
* Returns pointer to IOMMUMemoryRegionClass if a memory region is an iommu, * Returns pointer to IOMMUMemoryRegionClass if a memory region is an iommu,
* otherwise NULL. This is fast path avoiding QOM checking, use with caution. * otherwise NULL. This is fast path avoiding QOM checking, use with caution.
* *
* @mr: the memory region being queried * @iommu_mr: the memory region being queried
*/ */
static inline IOMMUMemoryRegionClass *memory_region_get_iommu_class_nocheck( static inline IOMMUMemoryRegionClass *memory_region_get_iommu_class_nocheck(
IOMMUMemoryRegion *iommu_mr) IOMMUMemoryRegion *iommu_mr)
@ -1094,6 +1301,7 @@ void memory_region_notify_one(IOMMUNotifier *notifier,
* @n: the IOMMUNotifier to be added; the notify callback receives a * @n: the IOMMUNotifier to be added; the notify callback receives a
* pointer to an #IOMMUTLBEntry as the opaque value; the pointer * pointer to an #IOMMUTLBEntry as the opaque value; the pointer
* ceases to be valid on exit from the notifier. * ceases to be valid on exit from the notifier.
* @errp: pointer to Error*, to store an error if it happens.
*/ */
int memory_region_register_iommu_notifier(MemoryRegion *mr, int memory_region_register_iommu_notifier(MemoryRegion *mr,
IOMMUNotifier *n, Error **errp); IOMMUNotifier *n, Error **errp);
@ -1266,9 +1474,12 @@ void *memory_region_get_ram_ptr(MemoryRegion *mr);
void memory_region_ram_resize(MemoryRegion *mr, ram_addr_t newsize, void memory_region_ram_resize(MemoryRegion *mr, ram_addr_t newsize,
Error **errp); Error **errp);
/** /**
* memory_region_do_writeback: Trigger writeback for selected address range * memory_region_do_writeback: Trigger cache writeback or msync for
* [addr, addr + size] * selected address range
* *
* @mr: the memory region to be updated
* @addr: the initial address of the range to be written back
* @size: the size of the range to be written back
*/ */
void memory_region_do_writeback(MemoryRegion *mr, hwaddr addr, hwaddr size); void memory_region_do_writeback(MemoryRegion *mr, hwaddr addr, hwaddr size);
@ -1587,6 +1798,8 @@ void memory_region_add_subregion_overlap(MemoryRegion *mr,
/** /**
* memory_region_get_ram_addr: Get the ram address associated with a memory * memory_region_get_ram_addr: Get the ram address associated with a memory
* region * region
*
* @mr: the region to be queried
*/ */
ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr); ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr);
@ -1679,8 +1892,8 @@ bool memory_region_is_mapped(MemoryRegion *mr);
* *
* Returns a #MemoryRegionSection that describes a contiguous overlap. * Returns a #MemoryRegionSection that describes a contiguous overlap.
* It will have the following characteristics: * It will have the following characteristics:
* .@size = 0 iff no overlap was found * - @size = 0 iff no overlap was found
* .@mr is non-%NULL iff an overlap was found * - @mr is non-%NULL iff an overlap was found
* *
* Remember that in the return value the @offset_within_region is * Remember that in the return value the @offset_within_region is
* relative to the returned region (in the .@mr field), not to the * relative to the returned region (in the .@mr field), not to the
@ -1691,8 +1904,8 @@ bool memory_region_is_mapped(MemoryRegion *mr);
* returned one. However, in the special case where the @mr argument * returned one. However, in the special case where the @mr argument
* has no container (and thus is the root of the address space), the * has no container (and thus is the root of the address space), the
* following will hold: * following will hold:
* .@offset_within_address_space >= @addr * - @offset_within_address_space >= @addr
* .@offset_within_address_space + .@size <= @addr + @size * - @offset_within_address_space + .@size <= @addr + @size
* *
* @mr: a MemoryRegion within which @addr is a relative address * @mr: a MemoryRegion within which @addr is a relative address
* @addr: start of the area within @as to be searched * @addr: start of the area within @as to be searched
@ -2157,6 +2370,7 @@ static inline bool memory_access_is_direct(MemoryRegion *mr, bool is_write)
* @addr: address within that address space * @addr: address within that address space
* @attrs: memory transaction attributes * @attrs: memory transaction attributes
* @buf: buffer with the data transferred * @buf: buffer with the data transferred
* @len: length of the data transferred
*/ */
static inline __attribute__((__always_inline__)) static inline __attribute__((__always_inline__))
MemTxResult address_space_read(AddressSpace *as, hwaddr addr, MemTxResult address_space_read(AddressSpace *as, hwaddr addr,
@ -2171,7 +2385,7 @@ MemTxResult address_space_read(AddressSpace *as, hwaddr addr,
if (__builtin_constant_p(len)) { if (__builtin_constant_p(len)) {
if (len) { if (len) {
rcu_read_lock(); RCU_READ_LOCK_GUARD();
fv = address_space_to_flatview(as); fv = address_space_to_flatview(as);
l = len; l = len;
mr = flatview_translate(fv, addr, &addr1, &l, false, attrs); mr = flatview_translate(fv, addr, &addr1, &l, false, attrs);
@ -2182,7 +2396,6 @@ MemTxResult address_space_read(AddressSpace *as, hwaddr addr,
result = flatview_read_continue(fv, addr, attrs, buf, len, result = flatview_read_continue(fv, addr, attrs, buf, len,
addr1, l, mr); addr1, l, mr);
} }
rcu_read_unlock();
} }
} else { } else {
result = address_space_read_full(as, addr, attrs, buf, len); result = address_space_read_full(as, addr, attrs, buf, len);

View file

@ -63,10 +63,6 @@ extern MachineState *current_machine;
void machine_run_board_init(MachineState *machine); void machine_run_board_init(MachineState *machine);
bool machine_usb(MachineState *machine); bool machine_usb(MachineState *machine);
bool machine_kernel_irqchip_allowed(MachineState *machine);
bool machine_kernel_irqchip_required(MachineState *machine);
bool machine_kernel_irqchip_split(MachineState *machine);
int machine_kvm_shadow_mem(MachineState *machine);
int machine_phandle_start(MachineState *machine); int machine_phandle_start(MachineState *machine);
bool machine_dump_guest_core(MachineState *machine); bool machine_dump_guest_core(MachineState *machine);
bool machine_mem_merge(MachineState *machine); bool machine_mem_merge(MachineState *machine);
@ -275,11 +271,9 @@ struct MachineState {
/*< public >*/ /*< public >*/
char *accel;
bool kernel_irqchip_allowed; bool kernel_irqchip_allowed;
bool kernel_irqchip_required; bool kernel_irqchip_required;
bool kernel_irqchip_split; bool kernel_irqchip_split;
int kvm_shadow_mem;
char *dtb; char *dtb;
char *dumpdtb; char *dumpdtb;
int phandle_start; int phandle_start;
@ -288,7 +282,6 @@ struct MachineState {
bool mem_merge; bool mem_merge;
bool usb; bool usb;
bool usb_disabled; bool usb_disabled;
bool igd_gfx_passthru;
char *firmware; char *firmware;
bool iommu; bool iommu;
bool suppress_vmdesc; bool suppress_vmdesc;

View file

@ -3,11 +3,9 @@
#include "exec/memory.h" #include "exec/memory.h"
#include "hw/boards.h" #include "hw/boards.h"
#include "hw/isa/isa.h"
#include "hw/block/fdc.h" #include "hw/block/fdc.h"
#include "hw/block/flash.h" #include "hw/block/flash.h"
#include "net/net.h" #include "net/net.h"
#include "hw/i386/ioapic.h"
#include "hw/i386/x86.h" #include "hw/i386/x86.h"
#include "qemu/range.h" #include "qemu/range.h"
@ -43,7 +41,6 @@ struct PCMachineState {
/* Configuration options: */ /* Configuration options: */
OnOffAuto vmport; OnOffAuto vmport;
OnOffAuto smm;
bool acpi_build_enabled; bool acpi_build_enabled;
bool smbus_enabled; bool smbus_enabled;
@ -61,7 +58,6 @@ struct PCMachineState {
#define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device" #define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device"
#define PC_MACHINE_DEVMEM_REGION_SIZE "device-memory-region-size" #define PC_MACHINE_DEVMEM_REGION_SIZE "device-memory-region-size"
#define PC_MACHINE_VMPORT "vmport" #define PC_MACHINE_VMPORT "vmport"
#define PC_MACHINE_SMM "smm"
#define PC_MACHINE_SMBUS "smbus" #define PC_MACHINE_SMBUS "smbus"
#define PC_MACHINE_SATA "sata" #define PC_MACHINE_SATA "sata"
#define PC_MACHINE_PIT "pit" #define PC_MACHINE_PIT "pit"
@ -134,27 +130,8 @@ typedef struct PCMachineClass {
#define PC_MACHINE_CLASS(klass) \ #define PC_MACHINE_CLASS(klass) \
OBJECT_CLASS_CHECK(PCMachineClass, (klass), TYPE_PC_MACHINE) OBJECT_CLASS_CHECK(PCMachineClass, (klass), TYPE_PC_MACHINE)
/* i8259.c */
extern DeviceState *isa_pic;
qemu_irq *i8259_init(ISABus *bus, qemu_irq parent_irq);
qemu_irq *kvm_i8259_init(ISABus *bus);
int pic_read_irq(DeviceState *d);
int pic_get_output(DeviceState *d);
/* ioapic.c */ /* ioapic.c */
/* Global System Interrupts */
#define GSI_NUM_PINS IOAPIC_NUM_PINS
typedef struct GSIState {
qemu_irq i8259_irq[ISA_NUM_IRQS];
qemu_irq ioapic_irq[IOAPIC_NUM_PINS];
} GSIState;
void gsi_handler(void *opaque, int n, int level);
GSIState *pc_gsi_create(qemu_irq **irqs, bool pci_enabled); GSIState *pc_gsi_create(qemu_irq **irqs, bool pci_enabled);
/* vmport.c */ /* vmport.c */
@ -173,7 +150,6 @@ void vmmouse_set_data(const uint32_t *data);
/* pc.c */ /* pc.c */
extern int fd_bootchk; extern int fd_bootchk;
bool pc_machine_is_smm_enabled(PCMachineState *pcms);
void pc_acpi_smi_interrupt(void *opaque, int irq, int level); void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
void pc_hot_add_cpu(MachineState *ms, const int64_t id, Error **errp); void pc_hot_add_cpu(MachineState *ms, const int64_t id, Error **errp);
@ -199,7 +175,6 @@ void pc_memory_init(PCMachineState *pcms,
MemoryRegion *rom_memory, MemoryRegion *rom_memory,
MemoryRegion **ram_memory); MemoryRegion **ram_memory);
uint64_t pc_pci_hole64_start(void); uint64_t pc_pci_hole64_start(void);
qemu_irq pc_allocate_cpu_irq(void);
DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus); DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus);
void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi, void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
ISADevice **rtc_state, ISADevice **rtc_state,
@ -217,17 +192,14 @@ void pc_pci_device_init(PCIBus *pci_bus);
typedef void (*cpu_set_smm_t)(int smm, void *arg); typedef void (*cpu_set_smm_t)(int smm, void *arg);
void pc_i8259_create(ISABus *isa_bus, qemu_irq *i8259_irqs); void pc_i8259_create(ISABus *isa_bus, qemu_irq *i8259_irqs);
void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name);
ISADevice *pc_find_fdc0(void); ISADevice *pc_find_fdc0(void);
int cmos_get_fd_drive_type(FloppyDriveType fd0); int cmos_get_fd_drive_type(FloppyDriveType fd0);
#define FW_CFG_IO_BASE 0x510 /* port92.c */
#define PORT92_A20_LINE "a20" #define PORT92_A20_LINE "a20"
/* hpet.c */ #define TYPE_PORT92 "port92"
extern int no_hpet;
/* pc_sysfw.c */ /* pc_sysfw.c */
void pc_system_flash_create(PCMachineState *pcms); void pc_system_flash_create(PCMachineState *pcms);

View file

@ -23,6 +23,8 @@
#include "hw/boards.h" #include "hw/boards.h"
#include "hw/nmi.h" #include "hw/nmi.h"
#include "hw/isa/isa.h"
#include "hw/i386/ioapic.h"
typedef struct { typedef struct {
/*< private >*/ /*< private >*/
@ -60,6 +62,8 @@ typedef struct {
uint16_t boot_cpus; uint16_t boot_cpus;
unsigned smp_dies; unsigned smp_dies;
OnOffAuto smm;
/* /*
* Address space used by IOAPIC device. All IOAPIC interrupts * Address space used by IOAPIC device. All IOAPIC interrupts
* will be translated to MSI messages in the address space. * will be translated to MSI messages in the address space.
@ -68,6 +72,7 @@ typedef struct {
} X86MachineState; } X86MachineState;
#define X86_MACHINE_MAX_RAM_BELOW_4G "max-ram-below-4g" #define X86_MACHINE_MAX_RAM_BELOW_4G "max-ram-below-4g"
#define X86_MACHINE_SMM "smm"
#define TYPE_X86_MACHINE MACHINE_TYPE_NAME("x86") #define TYPE_X86_MACHINE MACHINE_TYPE_NAME("x86")
#define X86_MACHINE(obj) \ #define X86_MACHINE(obj) \
@ -95,4 +100,22 @@ void x86_load_linux(X86MachineState *x86ms,
bool pvh_enabled, bool pvh_enabled,
bool linuxboot_dma_enabled); bool linuxboot_dma_enabled);
bool x86_machine_is_smm_enabled(X86MachineState *x86ms);
/* Global System Interrupts */
#define GSI_NUM_PINS IOAPIC_NUM_PINS
typedef struct GSIState {
qemu_irq i8259_irq[ISA_NUM_IRQS];
qemu_irq ioapic_irq[IOAPIC_NUM_PINS];
} GSIState;
qemu_irq x86_allocate_cpu_irq(void);
void gsi_handler(void *opaque, int n, int level);
void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name);
/* hpet.c */
extern int no_hpet;
#endif #endif

12
include/hw/intc/i8259.h Normal file
View file

@ -0,0 +1,12 @@
#ifndef HW_I8259_H
#define HW_I8259_H
/* i8259.c */
extern DeviceState *isa_pic;
qemu_irq *i8259_init(ISABus *bus, qemu_irq parent_irq);
qemu_irq *kvm_i8259_init(ISABus *bus);
int pic_get_output(DeviceState *d);
int pic_read_irq(DeviceState *d);
#endif

View file

@ -25,9 +25,9 @@
#ifndef QEMU_I8259_INTERNAL_H #ifndef QEMU_I8259_INTERNAL_H
#define QEMU_I8259_INTERNAL_H #define QEMU_I8259_INTERNAL_H
#include "hw/i386/pc.h"
#include "hw/isa/isa.h" #include "hw/isa/isa.h"
#include "hw/intc/intc.h" #include "hw/intc/intc.h"
#include "hw/intc/i8259.h"
typedef struct PICCommonState PICCommonState; typedef struct PICCommonState PICCommonState;

View file

@ -88,7 +88,7 @@ struct ISADevice {
DeviceState parent_obj; DeviceState parent_obj;
/*< public >*/ /*< public >*/
uint32_t isairq[2]; int8_t isairq[2]; /* -1 = unassigned */
int nirqs; int nirqs;
int ioport_id; int ioport_id;
}; };
@ -96,9 +96,9 @@ struct ISADevice {
ISABus *isa_bus_new(DeviceState *dev, MemoryRegion *address_space, ISABus *isa_bus_new(DeviceState *dev, MemoryRegion *address_space,
MemoryRegion *address_space_io, Error **errp); MemoryRegion *address_space_io, Error **errp);
void isa_bus_irqs(ISABus *bus, qemu_irq *irqs); void isa_bus_irqs(ISABus *bus, qemu_irq *irqs);
qemu_irq isa_get_irq(ISADevice *dev, int isairq); qemu_irq isa_get_irq(ISADevice *dev, unsigned isairq);
void isa_init_irq(ISADevice *dev, qemu_irq *p, int isairq); void isa_init_irq(ISADevice *dev, qemu_irq *p, unsigned isairq);
void isa_connect_gpio_out(ISADevice *isadev, int gpioirq, int isairq); void isa_connect_gpio_out(ISADevice *isadev, int gpioirq, unsigned isairq);
void isa_bus_dma(ISABus *bus, IsaDma *dma8, IsaDma *dma16); void isa_bus_dma(ISABus *bus, IsaDma *dma8, IsaDma *dma16);
IsaDma *isa_get_dma(ISABus *bus, int nchan); IsaDma *isa_get_dma(ISABus *bus, int nchan);
MemoryRegion *isa_address_space(ISADevice *dev); MemoryRegion *isa_address_space(ISADevice *dev);

View file

@ -13,12 +13,27 @@
#include "hw/hw.h" #include "hw/hw.h"
#include "hw/pci/pci_bus.h" #include "hw/pci/pci_bus.h"
#include "hw/pci-host/pam.h"
typedef struct PCII440FXState PCII440FXState;
#define TYPE_I440FX_PCI_HOST_BRIDGE "i440FX-pcihost" #define TYPE_I440FX_PCI_HOST_BRIDGE "i440FX-pcihost"
#define TYPE_I440FX_PCI_DEVICE "i440FX" #define TYPE_I440FX_PCI_DEVICE "i440FX"
#define I440FX_PCI_DEVICE(obj) \
OBJECT_CHECK(PCII440FXState, (obj), TYPE_I440FX_PCI_DEVICE)
typedef struct PCII440FXState {
/*< private >*/
PCIDevice parent_obj;
/*< public >*/
MemoryRegion *system_memory;
MemoryRegion *pci_address_space;
MemoryRegion *ram_memory;
PAMMemoryRegion pam_regions[13];
MemoryRegion smram_region;
MemoryRegion smram, low_smram;
} PCII440FXState;
#define TYPE_IGD_PASSTHROUGH_I440FX_PCI_DEVICE "igd-passthrough-i440FX" #define TYPE_IGD_PASSTHROUGH_I440FX_PCI_DEVICE "igd-passthrough-i440FX"
PCIBus *i440fx_init(const char *host_type, const char *pci_type, PCIBus *i440fx_init(const char *host_type, const char *pci_type,

View file

@ -174,7 +174,7 @@ enum {
#define QEMU_PCI_CAP_MULTIFUNCTION_BITNR 3 #define QEMU_PCI_CAP_MULTIFUNCTION_BITNR 3
QEMU_PCI_CAP_MULTIFUNCTION = (1 << QEMU_PCI_CAP_MULTIFUNCTION_BITNR), QEMU_PCI_CAP_MULTIFUNCTION = (1 << QEMU_PCI_CAP_MULTIFUNCTION_BITNR),
/* command register SERR bit enabled */ /* command register SERR bit enabled - unused since QEMU v5.0 */
#define QEMU_PCI_CAP_SERR_BITNR 4 #define QEMU_PCI_CAP_SERR_BITNR 4
QEMU_PCI_CAP_SERR = (1 << QEMU_PCI_CAP_SERR_BITNR), QEMU_PCI_CAP_SERR = (1 << QEMU_PCI_CAP_SERR_BITNR),
/* Standard hot plug controller. */ /* Standard hot plug controller. */

View file

@ -424,13 +424,16 @@ static inline uint64_t deposit64(uint64_t value, int start, int length,
/** /**
* half_shuffle32: * half_shuffle32:
* @value: 32-bit value (of which only the bottom 16 bits are of interest) * @x: 32-bit value (of which only the bottom 16 bits are of interest)
*
* Given an input value::
*
* xxxx xxxx xxxx xxxx ABCD EFGH IJKL MNOP
* *
* Given an input value:
* xxxx xxxx xxxx xxxx ABCD EFGH IJKL MNOP
* return the value where the bottom 16 bits are spread out into * return the value where the bottom 16 bits are spread out into
* the odd bits in the word, and the even bits are zeroed: * the odd bits in the word, and the even bits are zeroed::
* 0A0B 0C0D 0E0F 0G0H 0I0J 0K0L 0M0N 0O0P *
* 0A0B 0C0D 0E0F 0G0H 0I0J 0K0L 0M0N 0O0P
* *
* Any bits set in the top half of the input are ignored. * Any bits set in the top half of the input are ignored.
* *
@ -450,13 +453,16 @@ static inline uint32_t half_shuffle32(uint32_t x)
/** /**
* half_shuffle64: * half_shuffle64:
* @value: 64-bit value (of which only the bottom 32 bits are of interest) * @x: 64-bit value (of which only the bottom 32 bits are of interest)
*
* Given an input value::
*
* xxxx xxxx xxxx .... xxxx xxxx ABCD EFGH IJKL MNOP QRST UVWX YZab cdef
* *
* Given an input value:
* xxxx xxxx xxxx .... xxxx xxxx ABCD EFGH IJKL MNOP QRST UVWX YZab cdef
* return the value where the bottom 32 bits are spread out into * return the value where the bottom 32 bits are spread out into
* the odd bits in the word, and the even bits are zeroed: * the odd bits in the word, and the even bits are zeroed::
* 0A0B 0C0D 0E0F 0G0H 0I0J 0K0L 0M0N .... 0U0V 0W0X 0Y0Z 0a0b 0c0d 0e0f *
* 0A0B 0C0D 0E0F 0G0H 0I0J 0K0L 0M0N .... 0U0V 0W0X 0Y0Z 0a0b 0c0d 0e0f
* *
* Any bits set in the top half of the input are ignored. * Any bits set in the top half of the input are ignored.
* *
@ -477,13 +483,16 @@ static inline uint64_t half_shuffle64(uint64_t x)
/** /**
* half_unshuffle32: * half_unshuffle32:
* @value: 32-bit value (of which only the odd bits are of interest) * @x: 32-bit value (of which only the odd bits are of interest)
*
* Given an input value::
*
* xAxB xCxD xExF xGxH xIxJ xKxL xMxN xOxP
* *
* Given an input value:
* xAxB xCxD xExF xGxH xIxJ xKxL xMxN xOxP
* return the value where all the odd bits are compressed down * return the value where all the odd bits are compressed down
* into the low half of the word, and the high half is zeroed: * into the low half of the word, and the high half is zeroed::
* 0000 0000 0000 0000 ABCD EFGH IJKL MNOP *
* 0000 0000 0000 0000 ABCD EFGH IJKL MNOP
* *
* Any even bits set in the input are ignored. * Any even bits set in the input are ignored.
* *
@ -504,13 +513,16 @@ static inline uint32_t half_unshuffle32(uint32_t x)
/** /**
* half_unshuffle64: * half_unshuffle64:
* @value: 64-bit value (of which only the odd bits are of interest) * @x: 64-bit value (of which only the odd bits are of interest)
*
* Given an input value::
*
* xAxB xCxD xExF xGxH xIxJ xKxL xMxN .... xUxV xWxX xYxZ xaxb xcxd xexf
* *
* Given an input value:
* xAxB xCxD xExF xGxH xIxJ xKxL xMxN .... xUxV xWxX xYxZ xaxb xcxd xexf
* return the value where all the odd bits are compressed down * return the value where all the odd bits are compressed down
* into the low half of the word, and the high half is zeroed: * into the low half of the word, and the high half is zeroed::
* 0000 0000 0000 .... 0000 0000 ABCD EFGH IJKL MNOP QRST UVWX YZab cdef *
* 0000 0000 0000 .... 0000 0000 ABCD EFGH IJKL MNOP QRST UVWX YZab cdef
* *
* Any even bits set in the input are ignored. * Any even bits set in the input are ignored.
* *

View file

@ -200,8 +200,14 @@ typedef struct InterfaceInfo InterfaceInfo;
* *
* Interfaces allow a limited form of multiple inheritance. Instances are * Interfaces allow a limited form of multiple inheritance. Instances are
* similar to normal types except for the fact that are only defined by * similar to normal types except for the fact that are only defined by
* their classes and never carry any state. You can dynamically cast an object * their classes and never carry any state. As a consequence, a pointer to
* to one of its #Interface types and vice versa. * an interface instance should always be of incomplete type in order to be
* sure it cannot be dereferenced. That is, you should define the
* 'typedef struct SomethingIf SomethingIf' so that you can pass around
* 'SomethingIf *si' arguments, but not define a 'struct SomethingIf { ... }'.
* The only things you can validly do with a 'SomethingIf *' are to pass it as
* an argument to a method on its corresponding SomethingIfClass, or to
* dynamically cast it to an object that implements the interface.
* *
* # Methods # * # Methods #
* *
@ -592,6 +598,18 @@ struct InterfaceClass
((interface *)object_dynamic_cast_assert(OBJECT((obj)), (name), \ ((interface *)object_dynamic_cast_assert(OBJECT((obj)), (name), \
__FILE__, __LINE__, __func__)) __FILE__, __LINE__, __func__))
/**
* object_new_with_class:
* @klass: The class to instantiate.
*
* This function will initialize a new object using heap allocated memory.
* The returned object has a reference count of 1, and will be freed when
* the last reference is dropped.
*
* Returns: The newly allocated and instantiated object.
*/
Object *object_new_with_class(ObjectClass *klass);
/** /**
* object_new: * object_new:
* @typename: The name of the type of the object to instantiate. * @typename: The name of the type of the object to instantiate.
@ -679,6 +697,7 @@ void object_apply_global_props(Object *obj, const GPtrArray *props,
Error **errp); Error **errp);
void object_set_machine_compat_props(GPtrArray *compat_props); void object_set_machine_compat_props(GPtrArray *compat_props);
void object_set_accelerator_compat_props(GPtrArray *compat_props); void object_set_accelerator_compat_props(GPtrArray *compat_props);
void object_register_sugar_prop(const char *driver, const char *prop, const char *value);
void object_apply_compat_props(Object *obj); void object_apply_compat_props(Object *obj);
/** /**

View file

@ -64,9 +64,9 @@ typedef struct AccelClass {
#define ACCEL_GET_CLASS(obj) \ #define ACCEL_GET_CLASS(obj) \
OBJECT_GET_CLASS(AccelClass, (obj), TYPE_ACCEL) OBJECT_GET_CLASS(AccelClass, (obj), TYPE_ACCEL)
extern unsigned long tcg_tb_size; AccelClass *accel_find(const char *opt_name);
int accel_init_machine(AccelState *accel, MachineState *ms);
void configure_accelerator(MachineState *ms, const char *progname);
/* Called just before os_setup_post (ie just before drop OS privs) */ /* Called just before os_setup_post (ie just before drop OS privs) */
void accel_setup_post(MachineState *ms); void accel_setup_post(MachineState *ms);

View file

@ -40,6 +40,4 @@ extern int smp_threads;
void list_cpus(const char *optarg); void list_cpus(const char *optarg);
void qemu_tcg_configure(QemuOpts *opts, Error **errp);
#endif #endif

View file

@ -515,14 +515,16 @@ int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n,
int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n,
qemu_irq irq); qemu_irq irq);
void kvm_irqchip_set_qemuirq_gsi(KVMState *s, qemu_irq irq, int gsi); void kvm_irqchip_set_qemuirq_gsi(KVMState *s, qemu_irq irq, int gsi);
void kvm_pc_gsi_handler(void *opaque, int n, int level);
void kvm_pc_setup_irq_routing(bool pci_enabled); void kvm_pc_setup_irq_routing(bool pci_enabled);
void kvm_init_irq_routing(KVMState *s); void kvm_init_irq_routing(KVMState *s);
bool kvm_kernel_irqchip_allowed(void);
bool kvm_kernel_irqchip_required(void);
bool kvm_kernel_irqchip_split(void);
/** /**
* kvm_arch_irqchip_create: * kvm_arch_irqchip_create:
* @KVMState: The KVMState pointer * @KVMState: The KVMState pointer
* @MachineState: The MachineState pointer
* *
* Allow architectures to create an in-kernel irq chip themselves. * Allow architectures to create an in-kernel irq chip themselves.
* *
@ -530,7 +532,7 @@ void kvm_init_irq_routing(KVMState *s);
* 0: irq chip was not created * 0: irq chip was not created
* > 0: irq chip was created * > 0: irq chip was created
*/ */
int kvm_arch_irqchip_create(MachineState *ms, KVMState *s); int kvm_arch_irqchip_create(KVMState *s);
/** /**
* kvm_set_one_reg - set a register value in KVM via KVM_SET_ONE_REG ioctl * kvm_set_one_reg - set a register value in KVM via KVM_SET_ONE_REG ioctl

View file

@ -2991,7 +2991,6 @@ struct FlatViewInfo {
bool dispatch_tree; bool dispatch_tree;
bool owner; bool owner;
AccelClass *ac; AccelClass *ac;
const char *ac_name;
}; };
static void mtree_print_flatview(gpointer key, gpointer value, static void mtree_print_flatview(gpointer key, gpointer value,
@ -3061,7 +3060,7 @@ static void mtree_print_flatview(gpointer key, gpointer value,
if (fvi->ac->has_memory(current_machine, as, if (fvi->ac->has_memory(current_machine, as,
int128_get64(range->addr.start), int128_get64(range->addr.start),
MR_SIZE(range->addr.size) + 1)) { MR_SIZE(range->addr.size) + 1)) {
qemu_printf(" %s", fvi->ac_name); qemu_printf(" %s", fvi->ac->name);
} }
} }
} }
@ -3109,8 +3108,6 @@ void mtree_info(bool flatview, bool dispatch_tree, bool owner)
if (ac->has_memory) { if (ac->has_memory) {
fvi.ac = ac; fvi.ac = ac;
fvi.ac_name = current_machine->accel ? current_machine->accel :
object_class_get_name(OBJECT_CLASS(ac));
} }
/* Gather all FVs in one table */ /* Gather all FVs in one table */

View file

@ -863,15 +863,17 @@ static int multifd_recv_unfill_packet(MultiFDRecvParams *p, Error **errp)
p->next_packet_size = be32_to_cpu(packet->next_packet_size); p->next_packet_size = be32_to_cpu(packet->next_packet_size);
p->packet_num = be64_to_cpu(packet->packet_num); p->packet_num = be64_to_cpu(packet->packet_num);
if (p->pages->used) { if (p->pages->used == 0) {
/* make sure that ramblock is 0 terminated */ return 0;
packet->ramblock[255] = 0; }
block = qemu_ram_block_by_name(packet->ramblock);
if (!block) { /* make sure that ramblock is 0 terminated */
error_setg(errp, "multifd: unknown ram block %s", packet->ramblock[255] = 0;
packet->ramblock); block = qemu_ram_block_by_name(packet->ramblock);
return -1; if (!block) {
} error_setg(errp, "multifd: unknown ram block %s",
packet->ramblock);
return -1;
} }
for (i = 0; i < p->pages->used; i++) { for (i = 0; i < p->pages->used; i++) {
@ -3888,26 +3890,27 @@ int colo_init_ram_cache(void)
{ {
RAMBlock *block; RAMBlock *block;
rcu_read_lock(); WITH_RCU_READ_LOCK_GUARD() {
RAMBLOCK_FOREACH_NOT_IGNORED(block) { RAMBLOCK_FOREACH_NOT_IGNORED(block) {
block->colo_cache = qemu_anon_ram_alloc(block->used_length, block->colo_cache = qemu_anon_ram_alloc(block->used_length,
NULL, NULL,
false); false);
if (!block->colo_cache) { if (!block->colo_cache) {
error_report("%s: Can't alloc memory for COLO cache of block %s," error_report("%s: Can't alloc memory for COLO cache of block %s,"
"size 0x" RAM_ADDR_FMT, __func__, block->idstr, "size 0x" RAM_ADDR_FMT, __func__, block->idstr,
block->used_length); block->used_length);
RAMBLOCK_FOREACH_NOT_IGNORED(block) { RAMBLOCK_FOREACH_NOT_IGNORED(block) {
if (block->colo_cache) { if (block->colo_cache) {
qemu_anon_ram_free(block->colo_cache, block->used_length); qemu_anon_ram_free(block->colo_cache, block->used_length);
block->colo_cache = NULL; block->colo_cache = NULL;
}
} }
return -errno;
} }
return -errno; memcpy(block->colo_cache, block->host, block->used_length);
} }
memcpy(block->colo_cache, block->host, block->used_length);
} }
rcu_read_unlock();
/* /*
* Record the dirty pages that sent by PVM, we use this dirty bitmap together * Record the dirty pages that sent by PVM, we use this dirty bitmap together
* with to decide which page in cache should be flushed into SVM's RAM. Here * with to decide which page in cache should be flushed into SVM's RAM. Here

View file

@ -394,7 +394,7 @@ int monitor_set_cpu(int cpu_index)
/* Callers must hold BQL. */ /* Callers must hold BQL. */
static CPUState *mon_get_cpu_sync(bool synchronize) static CPUState *mon_get_cpu_sync(bool synchronize)
{ {
CPUState *cpu; CPUState *cpu = NULL;
if (cur_mon->mon_cpu_path) { if (cur_mon->mon_cpu_path) {
cpu = (CPUState *) object_resolve_path_type(cur_mon->mon_cpu_path, cpu = (CPUState *) object_resolve_path_type(cur_mon->mon_cpu_path,
@ -411,6 +411,7 @@ static CPUState *mon_get_cpu_sync(bool synchronize)
monitor_set_cpu(first_cpu->cpu_index); monitor_set_cpu(first_cpu->cpu_index);
cpu = first_cpu; cpu = first_cpu;
} }
assert(cpu != NULL);
if (synchronize) { if (synchronize) {
cpu_synchronize_state(cpu); cpu_synchronize_state(cpu);
} }

View file

@ -80,41 +80,26 @@ void os_setup_signal_handling(void)
sigaction(SIGTERM, &act, NULL); sigaction(SIGTERM, &act, NULL);
} }
/* Find a likely location for support files using the location of the binary. /*
For installed binaries this will be "$bindir/../share/qemu". When * Find a likely location for support files using the location of the binary.
running from the build tree this will be "$bindir/../pc-bios". */ * When running from the build tree this will be "$bindir/../pc-bios".
#define SHARE_SUFFIX "/share/qemu" * Otherwise, this is CONFIG_QEMU_DATADIR.
#define BUILD_SUFFIX "/pc-bios" */
char *os_find_datadir(void) char *os_find_datadir(void)
{ {
char *dir, *exec_dir; g_autofree char *exec_dir = NULL;
char *res; g_autofree char *dir = NULL;
size_t max_len;
exec_dir = qemu_get_exec_dir(); exec_dir = qemu_get_exec_dir();
if (exec_dir == NULL) { g_return_val_if_fail(exec_dir != NULL, NULL);
return NULL;
}
dir = g_path_get_dirname(exec_dir);
max_len = strlen(dir) + dir = g_build_filename(exec_dir, "..", "pc-bios", NULL);
MAX(strlen(SHARE_SUFFIX), strlen(BUILD_SUFFIX)) + 1; if (g_file_test(dir, G_FILE_TEST_IS_DIR)) {
res = g_malloc0(max_len); return g_steal_pointer(&dir);
snprintf(res, max_len, "%s%s", dir, SHARE_SUFFIX);
if (access(res, R_OK)) {
snprintf(res, max_len, "%s%s", dir, BUILD_SUFFIX);
if (access(res, R_OK)) {
g_free(res);
res = NULL;
}
} }
g_free(dir); return g_strdup(CONFIG_QEMU_DATADIR);
g_free(exec_dir);
return res;
} }
#undef SHARE_SUFFIX
#undef BUILD_SUFFIX
void os_set_proc_name(const char *s) void os_set_proc_name(const char *s)
{ {

View file

@ -43,7 +43,7 @@
#include "net/tap-linux.h" #include "net/tap-linux.h"
#ifdef CONFIG_LIBCAP #ifdef CONFIG_LIBCAP_NG
#include <cap-ng.h> #include <cap-ng.h>
#endif #endif
@ -207,7 +207,7 @@ static int send_fd(int c, int fd)
return sendmsg(c, &msg, 0); return sendmsg(c, &msg, 0);
} }
#ifdef CONFIG_LIBCAP #ifdef CONFIG_LIBCAP_NG
static int drop_privileges(void) static int drop_privileges(void)
{ {
/* clear all capabilities */ /* clear all capabilities */
@ -246,7 +246,7 @@ int main(int argc, char **argv)
int access_allowed, access_denied; int access_allowed, access_denied;
int ret = EXIT_SUCCESS; int ret = EXIT_SUCCESS;
#ifdef CONFIG_LIBCAP #ifdef CONFIG_LIBCAP_NG
/* if we're run from an suid binary, immediately drop privileges preserving /* if we're run from an suid binary, immediately drop privileges preserving
* cap_net_admin */ * cap_net_admin */
if (geteuid() == 0 && getuid() != geteuid()) { if (geteuid() == 0 && getuid() != geteuid()) {

View file

@ -142,6 +142,12 @@ QEMU 4.1 has three options, please migrate to one of these three:
to do is specify the kernel they want to boot with the -kernel option to do is specify the kernel they want to boot with the -kernel option
3. ``-bios <file>`` - Tells QEMU to load the specified file as the firmwrae. 3. ``-bios <file>`` - Tells QEMU to load the specified file as the firmwrae.
@subsection -tb-size option (since 5.0)
QEMU 5.0 introduced an alternative syntax to specify the size of the translation
block cache, @option{-accel tcg,tb-size=}. The new syntax deprecates the
previously available @option{-tb-size} option.
@section QEMU Machine Protocol (QMP) commands @section QEMU Machine Protocol (QMP) commands
@subsection change (since 2.5.0) @subsection change (since 2.5.0)
@ -259,7 +265,7 @@ The 'scsi-disk' device is deprecated. Users should use 'scsi-hd' or
This machine type is very old and unmaintained. Users should use the 'malta' This machine type is very old and unmaintained. Users should use the 'malta'
machine type instead. machine type instead.
@subsection pc-0.12, pc-0.13, pc-0.14 and pc-0.15 (since 4.0) @subsection pc-1.0, pc-1.1, pc-1.2 and pc-1.3 (since 5.0)
These machine types are very old and likely can not be used for live migration These machine types are very old and likely can not be used for live migration
from old QEMU versions anymore. A newer machine type should be used instead. from old QEMU versions anymore. A newer machine type should be used instead.

Some files were not shown because too many files have changed in this diff Show more