mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-23 11:39:53 +00:00
* 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:
commit
4800819827
@ -25,6 +25,11 @@ config TPM
|
||||
|
||||
config VHOST_USER
|
||||
bool
|
||||
select VHOST
|
||||
|
||||
config VHOST_KERNEL
|
||||
bool
|
||||
select VHOST
|
||||
|
||||
config XEN
|
||||
bool
|
||||
|
@ -420,6 +420,7 @@ F: hw/block/dataplane/xen*
|
||||
F: hw/xen/
|
||||
F: hw/xenpv/
|
||||
F: hw/i386/xen/
|
||||
F: hw/pci-host/xen_igd_pt.c
|
||||
F: include/hw/block/dataplane/xen*
|
||||
F: include/hw/xen/
|
||||
F: include/sysemu/xen-mapcache.h
|
||||
|
16
Makefile
16
Makefile
@ -321,14 +321,10 @@ HELPERS-y =
|
||||
|
||||
HELPERS-$(call land,$(CONFIG_SOFTMMU),$(CONFIG_LINUX)) = qemu-bridge-helper$(EXESUF)
|
||||
|
||||
ifdef CONFIG_LINUX
|
||||
ifdef CONFIG_VIRGL
|
||||
ifdef CONFIG_GBM
|
||||
ifeq ($(CONFIG_LINUX)$(CONFIG_VIRGL)$(CONFIG_GBM)$(CONFIG_TOOLS),yyyy)
|
||||
HELPERS-y += vhost-user-gpu$(EXESUF)
|
||||
vhost-user-json-y += contrib/vhost-user-gpu/50-qemu-gpu.json
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# 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
|
||||
@ -386,6 +382,7 @@ MINIKCONF_ARGS = \
|
||||
CONFIG_OPENGL=$(CONFIG_OPENGL) \
|
||||
CONFIG_X11=$(CONFIG_X11) \
|
||||
CONFIG_VHOST_USER=$(CONFIG_VHOST_USER) \
|
||||
CONFIG_VHOST_KERNEL=$(CONFIG_VHOST_KERNEL) \
|
||||
CONFIG_VIRTFS=$(CONFIG_VIRTFS) \
|
||||
CONFIG_LINUX=$(CONFIG_LINUX) \
|
||||
CONFIG_PVRDMA=$(CONFIG_PVRDMA)
|
||||
@ -440,15 +437,10 @@ dummy := $(call unnest-vars,, \
|
||||
block-obj-y \
|
||||
block-obj-m \
|
||||
crypto-obj-y \
|
||||
crypto-user-obj-y \
|
||||
qom-obj-y \
|
||||
io-obj-y \
|
||||
common-obj-y \
|
||||
common-obj-m \
|
||||
ui-obj-y \
|
||||
ui-obj-m \
|
||||
audio-obj-y \
|
||||
audio-obj-m \
|
||||
trace-obj-y)
|
||||
|
||||
include $(SRC_PATH)/tests/Makefile.include
|
||||
@ -532,7 +524,7 @@ subdir-capstone: capstone/all
|
||||
subdir-slirp: slirp/all
|
||||
|
||||
$(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_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;
|
||||
# this works around Sphinx not handling parallel invocation on
|
||||
# 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
|
||||
manual-deps = $(wildcard $(SRC_PATH)/docs/$1/*.rst) $(SRC_PATH)/docs/$1/conf.py $(SRC_PATH)/docs/conf.py
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#######################################################################
|
||||
# Common libraries for tools and emulators
|
||||
stub-obj-y = stubs/ util/ crypto/
|
||||
util-obj-y = util/ qobject/ qapi/
|
||||
stub-obj-y = stubs/
|
||||
util-obj-y = crypto/ util/ qobject/ qapi/
|
||||
|
||||
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 = crypto/
|
||||
crypto-user-obj-y = crypto/
|
||||
|
||||
#######################################################################
|
||||
# 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-y += accel/
|
||||
common-obj-y += migration/
|
||||
|
||||
common-obj-y += audio/
|
||||
|
@ -184,7 +184,6 @@ dummy := $(call unnest-vars,.., \
|
||||
block-obj-m \
|
||||
chardev-obj-y \
|
||||
crypto-obj-y \
|
||||
crypto-user-obj-y \
|
||||
qom-obj-y \
|
||||
io-obj-y \
|
||||
common-obj-y \
|
||||
@ -193,7 +192,6 @@ all-obj-y += $(common-obj-y)
|
||||
all-obj-y += $(qom-obj-y)
|
||||
all-obj-$(CONFIG_SOFTMMU) += $(authz-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) += $(io-obj-y)
|
||||
|
||||
|
@ -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-$(CONFIG_KVM) += kvm/
|
||||
obj-$(CONFIG_TCG) += tcg/
|
||||
|
@ -28,13 +28,7 @@
|
||||
#include "hw/boards.h"
|
||||
#include "sysemu/arch_init.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "hw/xen/xen.h"
|
||||
#include "qom/object.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/option.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
static const TypeInfo accel_type = {
|
||||
.name = TYPE_ACCEL,
|
||||
@ -44,7 +38,7 @@ static const TypeInfo accel_type = {
|
||||
};
|
||||
|
||||
/* 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);
|
||||
AccelClass *ac = ACCEL_CLASS(object_class_by_name(class_name));
|
||||
@ -52,11 +46,9 @@ static AccelClass *accel_find(const char *opt_name)
|
||||
return ac;
|
||||
}
|
||||
|
||||
static int accel_init_machine(AccelClass *acc, MachineState *ms)
|
||||
int accel_init_machine(AccelState *accel, MachineState *ms)
|
||||
{
|
||||
ObjectClass *oc = OBJECT_CLASS(acc);
|
||||
const char *cname = object_class_get_name(oc);
|
||||
AccelState *accel = ACCEL(object_new(cname));
|
||||
AccelClass *acc = ACCEL_GET_CLASS(accel);
|
||||
int ret;
|
||||
ms->accelerator = accel;
|
||||
*(acc->allowed) = true;
|
||||
@ -71,65 +63,6 @@ static int accel_init_machine(AccelClass *acc, MachineState *ms)
|
||||
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)
|
||||
{
|
||||
AccelState *accel = ms->accelerator;
|
||||
|
@ -41,6 +41,9 @@
|
||||
#include "hw/irq.h"
|
||||
#include "sysemu/sev.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"
|
||||
|
||||
@ -92,6 +95,10 @@ struct KVMState
|
||||
int max_nested_state_len;
|
||||
int many_ioeventfds;
|
||||
int intx_set_mask;
|
||||
int kvm_shadow_mem;
|
||||
bool kernel_irqchip_allowed;
|
||||
bool kernel_irqchip_required;
|
||||
bool kernel_irqchip_split;
|
||||
bool sync_mmu;
|
||||
bool manual_dirty_log_protect;
|
||||
/* 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))
|
||||
|
||||
/* 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
|
||||
*
|
||||
@ -550,23 +578,9 @@ static int kvm_physical_sync_dirty_bitmap(KVMMemoryListener *kml,
|
||||
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) {
|
||||
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 */
|
||||
mem->dirty_bmap = g_malloc0(bitmap_size);
|
||||
kvm_memslot_init_dirty_bitmap(mem);
|
||||
}
|
||||
|
||||
d.dirty_bitmap = mem->dirty_bmap;
|
||||
@ -1067,6 +1081,13 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml,
|
||||
mem->ram = ram;
|
||||
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);
|
||||
if (err) {
|
||||
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));
|
||||
}
|
||||
|
||||
static void kvm_irqchip_create(MachineState *machine, KVMState *s)
|
||||
static void kvm_irqchip_create(KVMState *s)
|
||||
{
|
||||
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
|
||||
* in-kernel irqchip for us */
|
||||
ret = kvm_arch_irqchip_create(machine, s);
|
||||
ret = kvm_arch_irqchip_create(s);
|
||||
if (ret == 0) {
|
||||
if (machine_kernel_irqchip_split(machine)) {
|
||||
if (s->kernel_irqchip_split) {
|
||||
perror("Split IRQ chip mode not supported.");
|
||||
exit(1);
|
||||
} else {
|
||||
@ -2049,8 +2070,8 @@ static int kvm_init(MachineState *ms)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (machine_kernel_irqchip_allowed(ms)) {
|
||||
kvm_irqchip_create(ms, s);
|
||||
if (s->kernel_irqchip_allowed) {
|
||||
kvm_irqchip_create(s);
|
||||
}
|
||||
|
||||
if (kvm_eventfds_allowed) {
|
||||
@ -2940,6 +2961,93 @@ static bool kvm_accel_has_memory(MachineState *ms, AddressSpace *as,
|
||||
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)
|
||||
{
|
||||
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->has_memory = kvm_accel_has_memory;
|
||||
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 = {
|
||||
.name = TYPE_KVM_ACCEL,
|
||||
.parent = TYPE_ACCEL,
|
||||
.instance_init = kvm_accel_instance_init,
|
||||
.class_init = kvm_accel_class_init,
|
||||
.instance_size = sizeof(KVMState),
|
||||
};
|
||||
|
@ -30,8 +30,23 @@
|
||||
#include "cpu.h"
|
||||
#include "sysemu/cpus.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 */
|
||||
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)
|
||||
{
|
||||
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;
|
||||
mttcg_enabled = s->mttcg_enabled;
|
||||
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)
|
||||
{
|
||||
AccelClass *ac = ACCEL_CLASS(oc);
|
||||
ac->name = "tcg";
|
||||
ac->init_machine = tcg_init;
|
||||
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 = {
|
||||
.name = TYPE_TCG_ACCEL,
|
||||
.parent = TYPE_ACCEL,
|
||||
.instance_init = tcg_accel_instance_init,
|
||||
.class_init = tcg_accel_class_init,
|
||||
.instance_size = sizeof(TCGState),
|
||||
};
|
||||
|
||||
static void register_accel_types(void)
|
||||
|
12
configure
vendored
12
configure
vendored
@ -101,7 +101,7 @@ update_cxxflags() {
|
||||
# Set QEMU_CXXFLAGS from QEMU_CFLAGS by filtering out those
|
||||
# options which some versions of GCC's C++ compiler complain about
|
||||
# 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
|
||||
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="-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="$QEMU_INCLUDES -iquote \$(SRC_PATH)/disas/libvixl"
|
||||
if test "$debug_info" = "yes"; then
|
||||
CFLAGS="-g $CFLAGS"
|
||||
LDFLAGS="-g $LDFLAGS"
|
||||
@ -907,7 +908,7 @@ for binary in "${PYTHON-python3}" python python2
|
||||
do
|
||||
if has "$binary"
|
||||
then
|
||||
python="$binary"
|
||||
python=$(command -v "$binary")
|
||||
break
|
||||
fi
|
||||
done
|
||||
@ -925,7 +926,7 @@ if test "$mingw32" = "yes" ; then
|
||||
DSOSUF=".dll"
|
||||
# MinGW needs -mthreads for TLS and macro _MT.
|
||||
QEMU_CFLAGS="-mthreads $QEMU_CFLAGS"
|
||||
LIBS="-lwinmm -lws2_32 -liphlpapi $LIBS"
|
||||
LIBS="-lwinmm -lws2_32 $LIBS"
|
||||
write_c_skeleton;
|
||||
if compile_prog "" "-liberty" ; then
|
||||
LIBS="-liberty $LIBS"
|
||||
@ -6027,6 +6028,9 @@ case "$slirp" in
|
||||
mkdir -p slirp
|
||||
slirp_cflags="-I\$(SRC_PATH)/slirp/src -I\$(BUILD_DIR)/slirp/src"
|
||||
slirp_libs="-L\$(BUILD_DIR)/slirp -lslirp"
|
||||
if test "$mingw32" = "yes" ; then
|
||||
slirp_libs="$slirp_libs -lws2_32 -liphlpapi"
|
||||
fi
|
||||
;;
|
||||
|
||||
system)
|
||||
@ -6716,7 +6720,7 @@ if test "$l2tpv3" = "yes" ; then
|
||||
echo "CONFIG_L2TPV3=y" >> $config_host_mak
|
||||
fi
|
||||
if test "$cap_ng" = "yes" ; then
|
||||
echo "CONFIG_LIBCAP=y" >> $config_host_mak
|
||||
echo "CONFIG_LIBCAP_NG=y" >> $config_host_mak
|
||||
fi
|
||||
echo "CONFIG_AUDIO_DRIVERS=$audio_drv_list" >> $config_host_mak
|
||||
for drv in $audio_drv_list; do
|
||||
|
@ -115,7 +115,7 @@ static int get_cdb_len(uint8_t *cdb)
|
||||
case 4: return 16;
|
||||
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;
|
||||
}
|
||||
|
||||
|
72
cpus.c
72
cpus.c
@ -166,78 +166,6 @@ typedef struct TimersState {
|
||||
static TimersState timers_state;
|
||||
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
|
||||
* originally budgeted minus the current state of the decrementing
|
||||
|
@ -19,13 +19,10 @@ crypto-obj-y += tlscredspsk.o
|
||||
crypto-obj-y += tlscredsx509.o
|
||||
crypto-obj-y += tlssession.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-$(CONFIG_NETTLE) += pbkdf-nettle.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-essiv.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-luks.o
|
||||
|
||||
# Let the userspace emulators avoid linking stuff they won't use.
|
||||
crypto-user-obj-y = aes.o $(crypto-rng-obj-y) init.o
|
||||
|
||||
stub-obj-y += pbkdf-stub.o
|
||||
util-obj-$(CONFIG_GCRYPT) += random-gcrypt.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
|
||||
util-obj-y += aes.o init.o
|
||||
|
@ -1,14 +1,5 @@
|
||||
libvixl_OBJS = vixl/utils.o \
|
||||
common-obj-$(CONFIG_ARM_A64_DIS) = vixl/utils.o \
|
||||
vixl/compiler-intrinsics.o \
|
||||
vixl/a64/instructions-a64.o \
|
||||
vixl/a64/decoder-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)
|
||||
|
@ -54,7 +54,7 @@ needs_sphinx = '1.3'
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = ['qmp_lexer']
|
||||
extensions = ['kerneldoc', 'qmp_lexer']
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
@ -216,3 +216,8 @@ texinfo_documents = [
|
||||
|
||||
|
||||
|
||||
# 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
8
docs/devel/bitops.rst
Normal 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
|
@ -23,3 +23,4 @@ Contents:
|
||||
secure-coding-practices
|
||||
tcg
|
||||
tcg-plugins
|
||||
bitops
|
||||
|
@ -361,3 +361,8 @@ callbacks are called:
|
||||
- .impl.unaligned specifies that the *implementation* supports unaligned
|
||||
accesses; if false, unaligned accesses will be emulated by two aligned
|
||||
accesses.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
.. kernel-doc:: include/exec/memory.h
|
||||
|
172
docs/sphinx/kerneldoc.py
Normal file
172
docs/sphinx/kerneldoc.py
Normal 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
28
docs/sphinx/kernellog.py
Normal 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
7
exec.c
@ -3903,10 +3903,9 @@ int ram_block_discard_range(RAMBlock *rb, uint64_t start, size_t length)
|
||||
|
||||
if ((start + length) <= rb->used_length) {
|
||||
bool need_madvise, need_fallocate;
|
||||
uint8_t *host_endaddr = host_startaddr + length;
|
||||
if ((uintptr_t)host_endaddr & (rb->page_size - 1)) {
|
||||
error_report("ram_block_discard_range: Unaligned end address: %p",
|
||||
host_endaddr);
|
||||
if (length & (rb->page_size - 1)) {
|
||||
error_report("ram_block_discard_range: Unaligned length: %zx",
|
||||
length);
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ common-obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o
|
||||
common-obj-$(CONFIG_ACPI_VMGENID) += vmgenid.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_PC)) += acpi-x86-stub.o
|
||||
|
||||
common-obj-y += acpi_interface.o
|
||||
common-obj-y += bios-linker-loader.o
|
||||
@ -20,4 +21,4 @@ common-obj-$(call lnot,$(CONFIG_IPMI)) += ipmi-stub.o
|
||||
else
|
||||
common-obj-y += acpi-stub.o
|
||||
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
|
||||
|
@ -7,7 +7,8 @@
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/pci/pci_host.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],
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "hw/timer/i8254.h"
|
||||
#include "hw/isa/superio.h"
|
||||
#include "hw/dma/i8257.h"
|
||||
#include "net/net.h"
|
||||
#include "qemu/cutils.h"
|
||||
|
||||
#define MAX_IDE_BUS 2
|
||||
|
@ -161,7 +161,6 @@ typedef struct AC97BusMasterRegs {
|
||||
typedef struct AC97LinkState {
|
||||
PCIDevice dev;
|
||||
QEMUSoundCard card;
|
||||
uint32_t use_broken_id;
|
||||
uint32_t glob_cnt;
|
||||
uint32_t glob_sta;
|
||||
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 + 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_PIN] = 0x01; /* intr_pn interrupt pin ro */
|
||||
|
||||
@ -1411,7 +1403,6 @@ static int ac97_init (PCIBus *bus)
|
||||
|
||||
static Property ac97_properties[] = {
|
||||
DEFINE_AUDIO_PROPERTIES(AC97LinkState, card),
|
||||
DEFINE_PROP_UINT32 ("use_broken_id", AC97LinkState, use_broken_id, 0),
|
||||
DEFINE_PROP_END_OF_LIST (),
|
||||
};
|
||||
|
||||
|
@ -178,86 +178,6 @@ GlobalProperty 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)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
@ -432,20 +352,6 @@ static void machine_set_graphics(Object *obj, bool value, Error **errp)
|
||||
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)
|
||||
{
|
||||
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_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",
|
||||
machine_get_kernel, machine_set_kernel, &error_abort);
|
||||
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",
|
||||
"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",
|
||||
machine_get_firmware, machine_set_firmware,
|
||||
&error_abort);
|
||||
@ -935,9 +818,6 @@ static void machine_initfn(Object *obj)
|
||||
MachineState *ms = MACHINE(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->mem_merge = true;
|
||||
ms->enable_graphics = true;
|
||||
@ -976,7 +856,6 @@ static void machine_finalize(Object *obj)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
g_free(ms->accel);
|
||||
g_free(ms->kernel_filename);
|
||||
g_free(ms->initrd_filename);
|
||||
g_free(ms->kernel_cmdline);
|
||||
@ -994,26 +873,6 @@ bool machine_usb(MachineState *machine)
|
||||
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)
|
||||
{
|
||||
return machine->phandle_start;
|
||||
|
@ -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);
|
||||
|
||||
vga_init_vbe(&s->vga, NULL, address_space);
|
||||
memory_region_add_subregion(address_space,
|
||||
VBE_DISPI_LFB_PHYSICAL_ADDRESS,
|
||||
&s->vga.vram);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -76,7 +76,9 @@ static void vga_isa_realizefn(DeviceState *dev, Error **errp)
|
||||
memory_region_set_coalescing(vga_io_memory);
|
||||
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_add_vga(VGABIOS_FILENAME);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -60,7 +60,6 @@ typedef struct VGACommonState {
|
||||
MemoryRegion *legacy_address_space;
|
||||
uint8_t *vram_ptr;
|
||||
MemoryRegion vram;
|
||||
MemoryRegion vram_vbe;
|
||||
uint32_t vram_size;
|
||||
uint32_t vram_size_mb; /* property */
|
||||
uint32_t vbe_size;
|
||||
@ -106,7 +105,6 @@ typedef struct VGACommonState {
|
||||
uint32_t vbe_start_addr;
|
||||
uint32_t vbe_line_offset;
|
||||
uint32_t vbe_bank_mask;
|
||||
int vbe_mapped;
|
||||
/* display refresh support */
|
||||
QemuConsole *con;
|
||||
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);
|
||||
|
||||
void vga_init_vbe(VGACommonState *s, Object *obj, MemoryRegion *address_space);
|
||||
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_data(void *opaque, uint32_t addr, uint32_t val);
|
||||
|
@ -1312,11 +1312,6 @@ static void pci_vmsvga_realize(PCIDevice *dev, Error **errp)
|
||||
&s->chip.vga.vram);
|
||||
pci_register_bar(dev, 2, PCI_BASE_ADDRESS_MEM_PREFETCH,
|
||||
&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[] = {
|
||||
|
@ -6,7 +6,8 @@
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/pci/pci_host.h"
|
||||
#include "hw/ide.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/intc/i8259.h"
|
||||
|
||||
#include "hppa_hardware.h"
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "hppa_sys.h"
|
||||
#include "qemu/units.h"
|
||||
#include "qapi/error.h"
|
||||
#include "net/net.h"
|
||||
#include "qemu/log.h"
|
||||
|
||||
#define MAX_IDE_BUS 2
|
||||
|
@ -546,14 +546,14 @@ uint16_t hyperv_hcall_post_message(uint64_t param, bool fast)
|
||||
}
|
||||
|
||||
ret = HV_STATUS_INVALID_CONNECTION_ID;
|
||||
rcu_read_lock();
|
||||
QLIST_FOREACH_RCU(mh, &msg_handlers, link) {
|
||||
if (mh->conn_id == (msg->connection_id & HV_CONNECTION_ID_MASK)) {
|
||||
ret = mh->handler(msg, mh->data);
|
||||
break;
|
||||
WITH_RCU_READ_LOCK_GUARD() {
|
||||
QLIST_FOREACH_RCU(mh, &msg_handlers, link) {
|
||||
if (mh->conn_id == (msg->connection_id & HV_CONNECTION_ID_MASK)) {
|
||||
ret = mh->handler(msg, mh->data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
unmap:
|
||||
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 ret;
|
||||
EventFlagHandler *handler;
|
||||
|
||||
if (unlikely(!fast)) {
|
||||
@ -645,15 +644,12 @@ uint16_t hyperv_hcall_signal_event(uint64_t param, bool fast)
|
||||
return HV_STATUS_INVALID_HYPERCALL_INPUT;
|
||||
}
|
||||
|
||||
ret = HV_STATUS_INVALID_CONNECTION_ID;
|
||||
rcu_read_lock();
|
||||
RCU_READ_LOCK_GUARD();
|
||||
QLIST_FOREACH_RCU(handler, &event_flag_handlers, link) {
|
||||
if (handler->conn_id == param) {
|
||||
event_notifier_set(handler->notifier);
|
||||
ret = 0;
|
||||
break;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
return ret;
|
||||
return HV_STATUS_INVALID_CONNECTION_ID;
|
||||
}
|
||||
|
@ -103,11 +103,17 @@ config MICROVM
|
||||
select MC146818RTC
|
||||
select VIRTIO_MMIO
|
||||
|
||||
config X86_IOMMU
|
||||
bool
|
||||
depends on PC
|
||||
|
||||
config VTD
|
||||
bool
|
||||
select X86_IOMMU
|
||||
|
||||
config AMD_IOMMU
|
||||
bool
|
||||
select X86_IOMMU
|
||||
|
||||
config VMPORT
|
||||
bool
|
||||
|
@ -1,17 +1,19 @@
|
||||
obj-$(CONFIG_KVM) += kvm/
|
||||
obj-y += e820_memory_layout.o multiboot.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_Q35) += pc_q35.o
|
||||
obj-$(CONFIG_MICROVM) += microvm.o
|
||||
obj-y += fw_cfg.o pc_sysfw.o
|
||||
obj-y += x86-iommu.o
|
||||
obj-y += fw_cfg.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_AMD_IOMMU) += amd_iommu.o
|
||||
obj-$(CONFIG_XEN) += ../xenpv/ xen/
|
||||
obj-$(CONFIG_VMPORT) += vmport.o
|
||||
obj-$(CONFIG_VMMOUSE) += vmmouse.o
|
||||
obj-$(CONFIG_PC) += port92.o
|
||||
|
||||
obj-y += kvmvapic.o
|
||||
obj-y += acpi-build.o
|
||||
obj-$(CONFIG_PC) += acpi-build.o
|
||||
|
@ -53,6 +53,7 @@
|
||||
/* Supported chipsets: */
|
||||
#include "hw/southbridge/piix.h"
|
||||
#include "hw/acpi/pcihp.h"
|
||||
#include "hw/i386/fw_cfg.h"
|
||||
#include "hw/i386/ich9.h"
|
||||
#include "hw/pci/pci_bus.h"
|
||||
#include "hw/pci-host/q35.h"
|
||||
|
@ -16,12 +16,14 @@
|
||||
#include "sysemu/numa.h"
|
||||
#include "hw/acpi/acpi.h"
|
||||
#include "hw/firmware/smbios.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "hw/i386/fw_cfg.h"
|
||||
#include "hw/timer/hpet.h"
|
||||
#include "hw/nvram/fw_cfg.h"
|
||||
#include "e820_memory_layout.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)
|
||||
{
|
||||
@ -46,6 +48,7 @@ const char *fw_cfg_arch_key_name(uint16_t key)
|
||||
|
||||
void fw_cfg_build_smbios(MachineState *ms, FWCfgState *fw_cfg)
|
||||
{
|
||||
#ifdef CONFIG_SMBIOS
|
||||
uint8_t *smbios_tables, *smbios_anchor;
|
||||
size_t smbios_tables_len, smbios_anchor_len;
|
||||
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",
|
||||
smbios_anchor, smbios_anchor_len);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
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_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
|
||||
#ifdef CONFIG_ACPI
|
||||
fw_cfg_add_bytes(fw_cfg, FW_CFG_ACPI_TABLES,
|
||||
acpi_tables, acpi_tables_len);
|
||||
#endif
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, kvm_allows_irq0_override());
|
||||
|
||||
fw_cfg_add_bytes(fw_cfg, FW_CFG_E820_TABLE,
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include "hw/boards.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_SMBIOS_ENTRIES (FW_CFG_ARCH_LOCAL + 1)
|
||||
#define FW_CFG_IRQ0_OVERRIDE (FW_CFG_ARCH_LOCAL + 2)
|
||||
|
@ -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
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/isa/i8259_internal.h"
|
||||
#include "hw/intc/i8259.h"
|
||||
#include "qemu/module.h"
|
||||
#include "hw/i386/apic_internal.h"
|
||||
#include "hw/irq.h"
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "monitor/monitor.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "hw/i386/x86.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/qdev-properties.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;
|
||||
|
||||
struct KVMIOAPICState {
|
||||
|
@ -32,8 +32,8 @@
|
||||
#include "hw/kvm/clock.h"
|
||||
#include "hw/i386/microvm.h"
|
||||
#include "hw/i386/x86.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "target/i386/cpu.h"
|
||||
#include "hw/intc/i8259.h"
|
||||
#include "hw/timer/i8254.h"
|
||||
#include "hw/rtc/mc146818rtc.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) {
|
||||
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++) {
|
||||
gsi_state->i8259_irq[i] = i8259[i];
|
||||
}
|
||||
|
291
hw/i386/pc.c
291
hw/i386/pc.c
@ -44,6 +44,7 @@
|
||||
#include "migration/vmstate.h"
|
||||
#include "multiboot.h"
|
||||
#include "hw/rtc/mc146818rtc.h"
|
||||
#include "hw/intc/i8259.h"
|
||||
#include "hw/dma/i8257.h"
|
||||
#include "hw/timer/i8254.h"
|
||||
#include "hw/input/i8042.h"
|
||||
@ -90,18 +91,7 @@
|
||||
#include "config-devices.h"
|
||||
#include "e820_memory_layout.h"
|
||||
#include "fw_cfg.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};
|
||||
#include "trace.h"
|
||||
|
||||
GlobalProperty 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);
|
||||
|
||||
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 *s;
|
||||
@ -365,10 +344,8 @@ GSIState *pc_gsi_create(qemu_irq **irqs, bool pci_enabled)
|
||||
s = g_new0(GSIState, 1);
|
||||
if (kvm_ioapic_in_kernel()) {
|
||||
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;
|
||||
}
|
||||
@ -397,55 +374,6 @@ static uint64_t ioportF0_read(void *opaque, hwaddr addr, unsigned size)
|
||||
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 */
|
||||
|
||||
#define REG_EQUIPMENT_BYTE 0x14
|
||||
@ -745,124 +673,6 @@ void pc_cmos_init(PCMachineState *pcms,
|
||||
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)
|
||||
{
|
||||
X86CPU *cpu = opaque;
|
||||
@ -889,16 +699,6 @@ void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd)
|
||||
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)
|
||||
{
|
||||
X86CPU *cpu = opaque;
|
||||
@ -1294,11 +1094,6 @@ uint64_t pc_pci_hole64_start(void)
|
||||
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 *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_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);
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1475,7 +1271,7 @@ void pc_i8259_create(ISABus *isa_bus, qemu_irq *i8259_irqs)
|
||||
} else if (xen_enabled()) {
|
||||
i8259 = xen_interrupt_controller_init();
|
||||
} 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++) {
|
||||
@ -1485,30 +1281,6 @@ void pc_i8259_create(ISABus *isa_bus, qemu_irq *i8259_irqs)
|
||||
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,
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
PCMachineState *pcms = PC_MACHINE(obj);
|
||||
@ -2120,7 +1850,6 @@ static void pc_machine_initfn(Object *obj)
|
||||
{
|
||||
PCMachineState *pcms = PC_MACHINE(obj);
|
||||
|
||||
pcms->smm = ON_OFF_AUTO_AUTO;
|
||||
#ifdef CONFIG_VMPORT
|
||||
pcms->vmport = ON_OFF_AUTO_AUTO;
|
||||
#else
|
||||
@ -2227,12 +1956,6 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
|
||||
pc_machine_get_device_memory_region_size, NULL,
|
||||
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",
|
||||
pc_machine_get_vmport, pc_machine_set_vmport,
|
||||
NULL, NULL, &error_abort);
|
||||
|
@ -281,7 +281,7 @@ else {
|
||||
/* TODO: Populate SPD eeprom data. */
|
||||
pcms->smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
|
||||
x86ms->gsi[9], smi_irq,
|
||||
pc_machine_is_smm_enabled(pcms),
|
||||
x86_machine_is_smm_enabled(x86ms),
|
||||
&piix4_pm);
|
||||
smbus_eeprom_init(pcms->smbus, 8, NULL, 0);
|
||||
|
||||
@ -309,9 +309,9 @@ else {
|
||||
|
||||
static void pc_compat_2_3_fn(MachineState *machine)
|
||||
{
|
||||
PCMachineState *pcms = PC_MACHINE(machine);
|
||||
X86MachineState *x86ms = X86_MACHINE(machine);
|
||||
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 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)
|
||||
{
|
||||
pc_compat_1_3(machine);
|
||||
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)
|
||||
{
|
||||
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);
|
||||
m->hw_version = "1.3.0";
|
||||
m->deprecation_reason = "use a newer machine type instead";
|
||||
x86mc->compat_apic_id_mode = true;
|
||||
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);
|
||||
|
||||
|
||||
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 {
|
||||
uint16_t gpu_device_id;
|
||||
uint16_t pch_device_id;
|
||||
|
@ -276,7 +276,7 @@ static void pc_q35_init(MachineState *machine)
|
||||
0xff0104);
|
||||
|
||||
/* 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) {
|
||||
/* ahci and SATA device, for q35 1 ahci controller is built-in */
|
||||
|
126
hw/i386/port92.c
Normal file
126
hw/i386/port92.c
Normal 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)
|
@ -111,3 +111,11 @@ amdvi_ir_irte_ga_val(uint64_t hi, uint64_t lo) "hi 0x%"PRIx64" lo 0x%"PRIx64
|
||||
# vmport.c
|
||||
vmport_register(unsigned char command, void *func, void *opaque) "command: 0x%02x func: %p opaque: %p"
|
||||
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
34
hw/i386/x86-iommu-stub.c
Normal 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;
|
||||
}
|
||||
|
154
hw/i386/x86.c
154
hw/i386/x86.c
@ -34,18 +34,23 @@
|
||||
#include "sysemu/numa.h"
|
||||
#include "sysemu/replay.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "trace.h"
|
||||
|
||||
#include "hw/i386/x86.h"
|
||||
#include "target/i386/cpu.h"
|
||||
#include "hw/i386/topology.h"
|
||||
#include "hw/i386/fw_cfg.h"
|
||||
#include "hw/intc/i8259.h"
|
||||
|
||||
#include "hw/acpi/cpu_hotplug.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/nmi.h"
|
||||
#include "hw/loader.h"
|
||||
#include "multiboot.h"
|
||||
#include "elf.h"
|
||||
#include "standard-headers/asm-x86/bootparam.h"
|
||||
#include "config-devices.h"
|
||||
#include "kvm_i386.h"
|
||||
|
||||
#define BIOS_FILENAME "bios.bin"
|
||||
|
||||
@ -220,6 +225,105 @@ static long get_file_size(FILE *f)
|
||||
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 {
|
||||
uint64_t next;
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
X86MachineState *x86ms = X86_MACHINE(obj);
|
||||
|
||||
x86ms->smm = ON_OFF_AUTO_AUTO;
|
||||
x86ms->max_ram_below_4g = 0; /* use default */
|
||||
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",
|
||||
x86_machine_get_max_ram_below_4g, x86_machine_set_max_ram_below_4g,
|
||||
NULL, NULL, &error_abort);
|
||||
|
||||
object_class_property_set_description(oc, X86_MACHINE_MAX_RAM_BELOW_4G,
|
||||
"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 = {
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include "qemu/log.h"
|
||||
#include "hw/isa/isa.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "hw/input/ps2.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/input/i8042.h"
|
||||
|
@ -9,6 +9,7 @@ config PL190
|
||||
|
||||
config IOAPIC
|
||||
bool
|
||||
select I8259
|
||||
|
||||
config ARM_GIC
|
||||
bool
|
||||
@ -21,6 +22,7 @@ config OPENPIC
|
||||
config APIC
|
||||
bool
|
||||
select MSI_NONBROKEN
|
||||
select I8259
|
||||
|
||||
config ARM_GIC_KVM
|
||||
bool
|
||||
|
@ -22,10 +22,10 @@
|
||||
#include "hw/i386/apic_internal.h"
|
||||
#include "hw/i386/apic.h"
|
||||
#include "hw/i386/ioapic.h"
|
||||
#include "hw/intc/i8259.h"
|
||||
#include "hw/pci/msi.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "trace.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "hw/i386/apic-msidef.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "hw/intc/i8259.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/isa/isa.h"
|
||||
#include "qemu/timer.h"
|
||||
|
@ -24,7 +24,7 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "hw/intc/i8259.h"
|
||||
#include "hw/isa/i8259_internal.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "migration/vmstate.h"
|
||||
|
@ -23,10 +23,11 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "monitor/monitor.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "hw/i386/apic.h"
|
||||
#include "hw/i386/ioapic.h"
|
||||
#include "hw/i386/ioapic_internal.h"
|
||||
#include "hw/i386/x86.h"
|
||||
#include "hw/intc/i8259.h"
|
||||
#include "hw/pci/msi.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "sysemu/kvm.h"
|
||||
|
@ -19,8 +19,8 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/intc/i8259.h"
|
||||
#include "hw/timer/i8254.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "hw/audio/pcspk.h"
|
||||
|
@ -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
|
||||
* 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);
|
||||
if (isairq < 0 || isairq > 15) {
|
||||
if (isairq >= ISA_NUM_IRQS) {
|
||||
hw_error("isa irq %d invalid", 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));
|
||||
if (isairq >= ISA_NUM_IRQS) {
|
||||
hw_error("isa irq %d invalid", isairq);
|
||||
}
|
||||
dev->isairq[dev->nirqs] = isairq;
|
||||
*p = isa_get_irq(dev, isairq);
|
||||
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;
|
||||
isa_init_irq(isadev, &irq, isairq);
|
||||
|
@ -35,7 +35,6 @@
|
||||
#include "hw/isa/isa.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/isa/apm.h"
|
||||
#include "hw/i386/ioapic.h"
|
||||
|
@ -26,11 +26,11 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "hw/southbridge/piix.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/isa/isa.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/intc/i8259.h"
|
||||
#include "hw/dma/i8257.h"
|
||||
#include "hw/timer/i8254.h"
|
||||
#include "hw/rtc/mc146818rtc.h"
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include "hw/pci/pci_host.h"
|
||||
#include "hw/southbridge/piix.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "hw/intc/i8259.h"
|
||||
#include "hw/irq.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "trace.h"
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include "qemu/units.h"
|
||||
#include "qapi/error.h"
|
||||
#include "cpu.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "hw/intc/i8259.h"
|
||||
#include "hw/dma/i8257.h"
|
||||
#include "hw/isa/superio.h"
|
||||
#include "net/net.h"
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include "qemu-common.h"
|
||||
#include "hw/mips/mips.h"
|
||||
#include "hw/mips/cpudevs.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "hw/intc/i8259.h"
|
||||
#include "hw/dma/i8257.h"
|
||||
#include "hw/char/serial.h"
|
||||
#include "hw/char/parallel.h"
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include "cpu.h"
|
||||
#include "hw/mips/mips.h"
|
||||
#include "hw/mips/cpudevs.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "hw/intc/i8259.h"
|
||||
#include "hw/char/serial.h"
|
||||
#include "hw/isa/isa.h"
|
||||
#include "net/net.h"
|
||||
|
@ -1,6 +1,11 @@
|
||||
config PAM
|
||||
bool
|
||||
|
||||
config XEN_IGD_PASSTHROUGH
|
||||
bool
|
||||
default y
|
||||
depends on XEN && PCI_I440FX
|
||||
|
||||
config PREP_PCI
|
||||
bool
|
||||
select PCI
|
||||
|
@ -14,6 +14,7 @@ common-obj-$(CONFIG_VERSATILE_PCI) += versatile.o
|
||||
common-obj-$(CONFIG_PCI_SABRE) += sabre.o
|
||||
common-obj-$(CONFIG_FULONG) += bonito.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_GENERIC_BRIDGE) += gpex.o
|
||||
common-obj-$(CONFIG_PCI_EXPRESS_XILINX) += xilinx-pcie.o
|
||||
|
@ -41,7 +41,6 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/mips/mips.h"
|
||||
#include "hw/pci/pci_host.h"
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* QEMU i440FX/PIIX3 PCI Bridge Emulation
|
||||
* QEMU i440FX PCI Bridge Emulation
|
||||
*
|
||||
* Copyright (c) 2006 Fabrice Bellard
|
||||
*
|
||||
@ -31,7 +31,6 @@
|
||||
#include "hw/sysbus.h"
|
||||
#include "qapi/error.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "hw/pci-host/pam.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
@ -51,23 +50,6 @@ typedef struct I440FXState {
|
||||
uint32_t short_root_bus;
|
||||
} 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_SIZE 7
|
||||
#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,
|
||||
PCIBus *rootbus)
|
||||
{
|
||||
@ -514,7 +412,6 @@ static const TypeInfo i440fx_pcihost_info = {
|
||||
static void i440fx_register_types(void)
|
||||
{
|
||||
type_register_static(&i440fx_info);
|
||||
type_register_static(&igd_passthrough_i440fx_info);
|
||||
type_register_static(&i440fx_pcihost_info);
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
||||
#include "hw/pci/pci_host.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "hw/i386/pc.h"
|
||||
#include "hw/intc/i8259.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/loader.h"
|
||||
#include "hw/or-irq.h"
|
||||
|
120
hw/pci-host/xen_igd_pt.c
Normal file
120
hw/pci-host/xen_igd_pt.c
Normal 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)
|
@ -26,6 +26,7 @@
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/pci/msi.h"
|
||||
#include "hw/pci/msix.h"
|
||||
|
||||
bool msi_nonbroken;
|
||||
bool pci_available;
|
||||
@ -64,3 +65,29 @@ void msi_notify(PCIDevice *dev, unsigned int vector)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
@ -69,8 +69,6 @@ static Property pci_props[] = {
|
||||
DEFINE_PROP_UINT32("rombar", PCIDevice, rom_bar, 1),
|
||||
DEFINE_PROP_BIT("multifunction", PCIDevice, cap_present,
|
||||
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,
|
||||
QEMU_PCIE_LNKSTA_DLLLA_BITNR, true),
|
||||
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_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
|
||||
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,
|
||||
config_size - PCI_CONFIG_HEADER_SIZE);
|
||||
|
@ -793,7 +793,6 @@ static DeviceState *ppce500_init_mpic(PPCE500MachineState *pms,
|
||||
MemoryRegion *ccsr,
|
||||
IrqLines *irqs)
|
||||
{
|
||||
MachineState *machine = MACHINE(pms);
|
||||
const PPCE500MachineClass *pmc = PPCE500_MACHINE_GET_CLASS(pms);
|
||||
DeviceState *dev = NULL;
|
||||
SysBusDevice *s;
|
||||
@ -801,10 +800,10 @@ static DeviceState *ppce500_init_mpic(PPCE500MachineState *pms,
|
||||
if (kvm_enabled()) {
|
||||
Error *err = NULL;
|
||||
|
||||
if (machine_kernel_irqchip_allowed(machine)) {
|
||||
if (kvm_kernel_irqchip_allowed()) {
|
||||
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,
|
||||
"kernel_irqchip requested but unavailable: ");
|
||||
exit(1);
|
||||
|
@ -75,12 +75,11 @@ int spapr_irq_init_kvm(SpaprInterruptControllerInitKvm fn,
|
||||
uint32_t nr_servers,
|
||||
Error **errp)
|
||||
{
|
||||
MachineState *machine = MACHINE(qdev_get_machine());
|
||||
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 (machine_kernel_irqchip_required(machine)) {
|
||||
if (kvm_kernel_irqchip_required()) {
|
||||
error_prepend(&local_err,
|
||||
"kernel_irqchip requested but unavailable: ");
|
||||
error_propagate(errp, local_err);
|
||||
@ -185,7 +184,7 @@ static int spapr_irq_check(SpaprMachineState *spapr, Error **errp)
|
||||
*/
|
||||
if (kvm_enabled() &&
|
||||
spapr->irq == &spapr_irq_dual &&
|
||||
machine_kernel_irqchip_required(machine) &&
|
||||
kvm_kernel_irqchip_required() &&
|
||||
xics_kvm_has_broken_disconnect(spapr)) {
|
||||
error_setg(errp, "KVM is too old to support ic-mode=dual,kernel-irqchip=on");
|
||||
return -1;
|
||||
@ -288,20 +287,13 @@ uint32_t spapr_irq_nr_msis(SpaprMachineState *spapr)
|
||||
|
||||
void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
|
||||
{
|
||||
MachineState *machine = MACHINE(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");
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
|
@ -1,3 +1,6 @@
|
||||
config VHOST
|
||||
bool
|
||||
|
||||
config VIRTIO
|
||||
bool
|
||||
|
||||
|
@ -2,8 +2,8 @@ ifeq ($(CONFIG_VIRTIO),y)
|
||||
common-obj-y += virtio-bus.o
|
||||
obj-y += virtio.o
|
||||
|
||||
obj-$(call lor,$(CONFIG_VHOST_USER),$(CONFIG_VHOST_KERNEL)) += vhost.o vhost-backend.o
|
||||
common-obj-$(call lnot,$(call lor,$(CONFIG_VHOST_USER),$(CONFIG_VHOST_KERNEL))) += vhost-stub.o
|
||||
obj-$(CONFIG_VHOST) += vhost.o vhost-backend.o
|
||||
common-obj-$(call lnot,$(CONFIG_VHOST)) += vhost-stub.o
|
||||
obj-$(CONFIG_VHOST_USER) += vhost-user.o
|
||||
|
||||
common-obj-$(CONFIG_VIRTIO_RNG) += virtio-rng.o
|
||||
|
@ -11,7 +11,9 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qapi/error.h"
|
||||
#include "hw/xen/xen-legacy-backend.h"
|
||||
#include "hw/xen/xen_pt.h"
|
||||
#include "chardev/char.h"
|
||||
#include "sysemu/accel.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)
|
||||
{
|
||||
int rc;
|
||||
@ -177,6 +189,12 @@ static void xen_accel_class_init(ObjectClass *oc, void *data)
|
||||
ac->compat_props = g_ptr_array_new();
|
||||
|
||||
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")
|
||||
|
@ -65,6 +65,8 @@
|
||||
#include "qemu/range.h"
|
||||
#include "exec/address-spaces.h"
|
||||
|
||||
bool has_igd_gfx_passthru;
|
||||
|
||||
#define XEN_PT_NR_IRQS (256)
|
||||
static uint8_t xen_pt_mapped_machine_irq[XEN_PT_NR_IRQS] = {0};
|
||||
|
||||
|
@ -360,10 +360,14 @@ typedef struct IOMMUMemoryRegionClass {
|
||||
typedef struct CoalescedMemoryRange CoalescedMemoryRange;
|
||||
typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd;
|
||||
|
||||
/** MemoryRegion:
|
||||
*
|
||||
* A struct representing a memory region.
|
||||
*/
|
||||
struct MemoryRegion {
|
||||
Object parent_obj;
|
||||
|
||||
/* All fields are private - violators will be prosecuted */
|
||||
/* private: */
|
||||
|
||||
/* The following fields should fit in a cache line */
|
||||
bool romd_mode;
|
||||
@ -419,30 +423,232 @@ struct IOMMUMemoryRegion {
|
||||
* Use with memory_listener_register() and memory_listener_unregister().
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* @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,
|
||||
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,
|
||||
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);
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* @log_global_after_sync:
|
||||
*
|
||||
* Called after reading the dirty memory bitmap
|
||||
* for any #MemoryRegionSection.
|
||||
*
|
||||
* @listener: The #MemoryListener.
|
||||
*/
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
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;
|
||||
|
||||
/* private: */
|
||||
AddressSpace *address_space;
|
||||
QTAILQ_ENTRY(MemoryListener) link;
|
||||
QTAILQ_ENTRY(MemoryListener) link_as;
|
||||
@ -452,7 +658,7 @@ struct MemoryListener {
|
||||
* AddressSpace: describes a mapping of addresses to #MemoryRegion objects
|
||||
*/
|
||||
struct AddressSpace {
|
||||
/* All fields are private. */
|
||||
/* private: */
|
||||
struct rcu_head rcu;
|
||||
char *name;
|
||||
MemoryRegion *root;
|
||||
@ -936,6 +1142,7 @@ void memory_region_init_rom(MemoryRegion *mr,
|
||||
* @mr: the #MemoryRegion to be initialized.
|
||||
* @owner: the object that tracks the region's reference count
|
||||
* @ops: callbacks for write access handling (must not be NULL).
|
||||
* @opaque: passed to the read and write callbacks of the @ops structure.
|
||||
* @name: Region name, becomes part of RAMBlock name used in migration stream
|
||||
* must be unique within any device
|
||||
* @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,
|
||||
* 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(
|
||||
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
|
||||
* pointer to an #IOMMUTLBEntry as the opaque value; the pointer
|
||||
* 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,
|
||||
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,
|
||||
Error **errp);
|
||||
/**
|
||||
* memory_region_do_writeback: Trigger writeback for selected address range
|
||||
* [addr, addr + size]
|
||||
* memory_region_do_writeback: Trigger cache writeback or msync for
|
||||
* 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);
|
||||
|
||||
@ -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
|
||||
* region
|
||||
*
|
||||
* @mr: the region to be queried
|
||||
*/
|
||||
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.
|
||||
* It will have the following characteristics:
|
||||
* .@size = 0 iff no overlap was found
|
||||
* .@mr is non-%NULL iff an overlap was found
|
||||
* - @size = 0 iff no overlap was found
|
||||
* - @mr is non-%NULL iff an overlap was found
|
||||
*
|
||||
* Remember that in the return value the @offset_within_region is
|
||||
* 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
|
||||
* has no container (and thus is the root of the address space), the
|
||||
* following will hold:
|
||||
* .@offset_within_address_space >= @addr
|
||||
* .@offset_within_address_space + .@size <= @addr + @size
|
||||
* - @offset_within_address_space >= @addr
|
||||
* - @offset_within_address_space + .@size <= @addr + @size
|
||||
*
|
||||
* @mr: a MemoryRegion within which @addr is a relative address
|
||||
* @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
|
||||
* @attrs: memory transaction attributes
|
||||
* @buf: buffer with the data transferred
|
||||
* @len: length of the data transferred
|
||||
*/
|
||||
static inline __attribute__((__always_inline__))
|
||||
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 (len) {
|
||||
rcu_read_lock();
|
||||
RCU_READ_LOCK_GUARD();
|
||||
fv = address_space_to_flatview(as);
|
||||
l = len;
|
||||
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,
|
||||
addr1, l, mr);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
} else {
|
||||
result = address_space_read_full(as, addr, attrs, buf, len);
|
||||
|
@ -63,10 +63,6 @@ extern MachineState *current_machine;
|
||||
|
||||
void machine_run_board_init(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);
|
||||
bool machine_dump_guest_core(MachineState *machine);
|
||||
bool machine_mem_merge(MachineState *machine);
|
||||
@ -275,11 +271,9 @@ struct MachineState {
|
||||
|
||||
/*< public >*/
|
||||
|
||||
char *accel;
|
||||
bool kernel_irqchip_allowed;
|
||||
bool kernel_irqchip_required;
|
||||
bool kernel_irqchip_split;
|
||||
int kvm_shadow_mem;
|
||||
char *dtb;
|
||||
char *dumpdtb;
|
||||
int phandle_start;
|
||||
@ -288,7 +282,6 @@ struct MachineState {
|
||||
bool mem_merge;
|
||||
bool usb;
|
||||
bool usb_disabled;
|
||||
bool igd_gfx_passthru;
|
||||
char *firmware;
|
||||
bool iommu;
|
||||
bool suppress_vmdesc;
|
||||
|
@ -3,11 +3,9 @@
|
||||
|
||||
#include "exec/memory.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/isa/isa.h"
|
||||
#include "hw/block/fdc.h"
|
||||
#include "hw/block/flash.h"
|
||||
#include "net/net.h"
|
||||
#include "hw/i386/ioapic.h"
|
||||
#include "hw/i386/x86.h"
|
||||
|
||||
#include "qemu/range.h"
|
||||
@ -43,7 +41,6 @@ struct PCMachineState {
|
||||
|
||||
/* Configuration options: */
|
||||
OnOffAuto vmport;
|
||||
OnOffAuto smm;
|
||||
|
||||
bool acpi_build_enabled;
|
||||
bool smbus_enabled;
|
||||
@ -61,7 +58,6 @@ struct PCMachineState {
|
||||
#define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device"
|
||||
#define PC_MACHINE_DEVMEM_REGION_SIZE "device-memory-region-size"
|
||||
#define PC_MACHINE_VMPORT "vmport"
|
||||
#define PC_MACHINE_SMM "smm"
|
||||
#define PC_MACHINE_SMBUS "smbus"
|
||||
#define PC_MACHINE_SATA "sata"
|
||||
#define PC_MACHINE_PIT "pit"
|
||||
@ -134,27 +130,8 @@ typedef struct PCMachineClass {
|
||||
#define PC_MACHINE_CLASS(klass) \
|
||||
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 */
|
||||
|
||||
/* 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);
|
||||
|
||||
/* vmport.c */
|
||||
@ -173,7 +150,6 @@ void vmmouse_set_data(const uint32_t *data);
|
||||
/* pc.c */
|
||||
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_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 **ram_memory);
|
||||
uint64_t pc_pci_hole64_start(void);
|
||||
qemu_irq pc_allocate_cpu_irq(void);
|
||||
DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus);
|
||||
void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
|
||||
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);
|
||||
|
||||
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);
|
||||
int cmos_get_fd_drive_type(FloppyDriveType fd0);
|
||||
|
||||
#define FW_CFG_IO_BASE 0x510
|
||||
|
||||
/* port92.c */
|
||||
#define PORT92_A20_LINE "a20"
|
||||
|
||||
/* hpet.c */
|
||||
extern int no_hpet;
|
||||
#define TYPE_PORT92 "port92"
|
||||
|
||||
/* pc_sysfw.c */
|
||||
void pc_system_flash_create(PCMachineState *pcms);
|
||||
|
@ -23,6 +23,8 @@
|
||||
|
||||
#include "hw/boards.h"
|
||||
#include "hw/nmi.h"
|
||||
#include "hw/isa/isa.h"
|
||||
#include "hw/i386/ioapic.h"
|
||||
|
||||
typedef struct {
|
||||
/*< private >*/
|
||||
@ -60,6 +62,8 @@ typedef struct {
|
||||
uint16_t boot_cpus;
|
||||
unsigned smp_dies;
|
||||
|
||||
OnOffAuto smm;
|
||||
|
||||
/*
|
||||
* Address space used by IOAPIC device. All IOAPIC interrupts
|
||||
* will be translated to MSI messages in the address space.
|
||||
@ -68,6 +72,7 @@ typedef struct {
|
||||
} X86MachineState;
|
||||
|
||||
#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 X86_MACHINE(obj) \
|
||||
@ -95,4 +100,22 @@ void x86_load_linux(X86MachineState *x86ms,
|
||||
bool pvh_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
|
||||
|
12
include/hw/intc/i8259.h
Normal file
12
include/hw/intc/i8259.h
Normal 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
|
@ -25,9 +25,9 @@
|
||||
#ifndef QEMU_I8259_INTERNAL_H
|
||||
#define QEMU_I8259_INTERNAL_H
|
||||
|
||||
#include "hw/i386/pc.h"
|
||||
#include "hw/isa/isa.h"
|
||||
#include "hw/intc/intc.h"
|
||||
#include "hw/intc/i8259.h"
|
||||
|
||||
typedef struct PICCommonState PICCommonState;
|
||||
|
||||
|
@ -88,7 +88,7 @@ struct ISADevice {
|
||||
DeviceState parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
uint32_t isairq[2];
|
||||
int8_t isairq[2]; /* -1 = unassigned */
|
||||
int nirqs;
|
||||
int ioport_id;
|
||||
};
|
||||
@ -96,9 +96,9 @@ struct ISADevice {
|
||||
ISABus *isa_bus_new(DeviceState *dev, MemoryRegion *address_space,
|
||||
MemoryRegion *address_space_io, Error **errp);
|
||||
void isa_bus_irqs(ISABus *bus, qemu_irq *irqs);
|
||||
qemu_irq isa_get_irq(ISADevice *dev, int isairq);
|
||||
void isa_init_irq(ISADevice *dev, qemu_irq *p, int isairq);
|
||||
void isa_connect_gpio_out(ISADevice *isadev, int gpioirq, int isairq);
|
||||
qemu_irq isa_get_irq(ISADevice *dev, unsigned isairq);
|
||||
void isa_init_irq(ISADevice *dev, qemu_irq *p, unsigned isairq);
|
||||
void isa_connect_gpio_out(ISADevice *isadev, int gpioirq, unsigned isairq);
|
||||
void isa_bus_dma(ISABus *bus, IsaDma *dma8, IsaDma *dma16);
|
||||
IsaDma *isa_get_dma(ISABus *bus, int nchan);
|
||||
MemoryRegion *isa_address_space(ISADevice *dev);
|
||||
|
@ -13,12 +13,27 @@
|
||||
|
||||
#include "hw/hw.h"
|
||||
#include "hw/pci/pci_bus.h"
|
||||
|
||||
typedef struct PCII440FXState PCII440FXState;
|
||||
#include "hw/pci-host/pam.h"
|
||||
|
||||
#define TYPE_I440FX_PCI_HOST_BRIDGE "i440FX-pcihost"
|
||||
#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"
|
||||
|
||||
PCIBus *i440fx_init(const char *host_type, const char *pci_type,
|
||||
|
@ -174,7 +174,7 @@ enum {
|
||||
#define QEMU_PCI_CAP_MULTIFUNCTION_BITNR 3
|
||||
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
|
||||
QEMU_PCI_CAP_SERR = (1 << QEMU_PCI_CAP_SERR_BITNR),
|
||||
/* Standard hot plug controller. */
|
||||
|
@ -424,13 +424,16 @@ static inline uint64_t deposit64(uint64_t value, int start, int length,
|
||||
|
||||
/**
|
||||
* 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
|
||||
* the odd bits in the word, and the even bits are zeroed:
|
||||
* 0A0B 0C0D 0E0F 0G0H 0I0J 0K0L 0M0N 0O0P
|
||||
* the odd bits in the word, and the even bits are zeroed::
|
||||
*
|
||||
* 0A0B 0C0D 0E0F 0G0H 0I0J 0K0L 0M0N 0O0P
|
||||
*
|
||||
* 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:
|
||||
* @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
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* 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:
|
||||
* @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
|
||||
* into the low half of the word, and the high half is zeroed:
|
||||
* 0000 0000 0000 0000 ABCD EFGH IJKL MNOP
|
||||
* into the low half of the word, and the high half is zeroed::
|
||||
*
|
||||
* 0000 0000 0000 0000 ABCD EFGH IJKL MNOP
|
||||
*
|
||||
* Any even bits set in the input are ignored.
|
||||
*
|
||||
@ -504,13 +513,16 @@ static inline uint32_t half_unshuffle32(uint32_t x)
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* Any even bits set in the input are ignored.
|
||||
*
|
||||
|
@ -200,8 +200,14 @@ typedef struct InterfaceInfo InterfaceInfo;
|
||||
*
|
||||
* Interfaces allow a limited form of multiple inheritance. Instances are
|
||||
* 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
|
||||
* to one of its #Interface types and vice versa.
|
||||
* their classes and never carry any state. As a consequence, a pointer to
|
||||
* 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 #
|
||||
*
|
||||
@ -592,6 +598,18 @@ struct InterfaceClass
|
||||
((interface *)object_dynamic_cast_assert(OBJECT((obj)), (name), \
|
||||
__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:
|
||||
* @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);
|
||||
void object_set_machine_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);
|
||||
|
||||
/**
|
||||
|
@ -64,9 +64,9 @@ typedef struct AccelClass {
|
||||
#define ACCEL_GET_CLASS(obj) \
|
||||
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) */
|
||||
void accel_setup_post(MachineState *ms);
|
||||
|
||||
|
@ -40,6 +40,4 @@ extern int smp_threads;
|
||||
|
||||
void list_cpus(const char *optarg);
|
||||
|
||||
void qemu_tcg_configure(QemuOpts *opts, Error **errp);
|
||||
|
||||
#endif
|
||||
|
@ -515,14 +515,16 @@ int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n,
|
||||
int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n,
|
||||
qemu_irq irq);
|
||||
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_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:
|
||||
* @KVMState: The KVMState pointer
|
||||
* @MachineState: The MachineState pointer
|
||||
*
|
||||
* 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 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
|
||||
|
5
memory.c
5
memory.c
@ -2991,7 +2991,6 @@ struct FlatViewInfo {
|
||||
bool dispatch_tree;
|
||||
bool owner;
|
||||
AccelClass *ac;
|
||||
const char *ac_name;
|
||||
};
|
||||
|
||||
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,
|
||||
int128_get64(range->addr.start),
|
||||
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) {
|
||||
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 */
|
||||
|
@ -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->packet_num = be64_to_cpu(packet->packet_num);
|
||||
|
||||
if (p->pages->used) {
|
||||
/* make sure that ramblock is 0 terminated */
|
||||
packet->ramblock[255] = 0;
|
||||
block = qemu_ram_block_by_name(packet->ramblock);
|
||||
if (!block) {
|
||||
error_setg(errp, "multifd: unknown ram block %s",
|
||||
packet->ramblock);
|
||||
return -1;
|
||||
}
|
||||
if (p->pages->used == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* make sure that ramblock is 0 terminated */
|
||||
packet->ramblock[255] = 0;
|
||||
block = qemu_ram_block_by_name(packet->ramblock);
|
||||
if (!block) {
|
||||
error_setg(errp, "multifd: unknown ram block %s",
|
||||
packet->ramblock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < p->pages->used; i++) {
|
||||
@ -3888,26 +3890,27 @@ int colo_init_ram_cache(void)
|
||||
{
|
||||
RAMBlock *block;
|
||||
|
||||
rcu_read_lock();
|
||||
RAMBLOCK_FOREACH_NOT_IGNORED(block) {
|
||||
block->colo_cache = qemu_anon_ram_alloc(block->used_length,
|
||||
NULL,
|
||||
false);
|
||||
if (!block->colo_cache) {
|
||||
error_report("%s: Can't alloc memory for COLO cache of block %s,"
|
||||
"size 0x" RAM_ADDR_FMT, __func__, block->idstr,
|
||||
block->used_length);
|
||||
RAMBLOCK_FOREACH_NOT_IGNORED(block) {
|
||||
if (block->colo_cache) {
|
||||
qemu_anon_ram_free(block->colo_cache, block->used_length);
|
||||
block->colo_cache = NULL;
|
||||
WITH_RCU_READ_LOCK_GUARD() {
|
||||
RAMBLOCK_FOREACH_NOT_IGNORED(block) {
|
||||
block->colo_cache = qemu_anon_ram_alloc(block->used_length,
|
||||
NULL,
|
||||
false);
|
||||
if (!block->colo_cache) {
|
||||
error_report("%s: Can't alloc memory for COLO cache of block %s,"
|
||||
"size 0x" RAM_ADDR_FMT, __func__, block->idstr,
|
||||
block->used_length);
|
||||
RAMBLOCK_FOREACH_NOT_IGNORED(block) {
|
||||
if (block->colo_cache) {
|
||||
qemu_anon_ram_free(block->colo_cache, block->used_length);
|
||||
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
|
||||
* with to decide which page in cache should be flushed into SVM's RAM. Here
|
||||
|
@ -394,7 +394,7 @@ int monitor_set_cpu(int cpu_index)
|
||||
/* Callers must hold BQL. */
|
||||
static CPUState *mon_get_cpu_sync(bool synchronize)
|
||||
{
|
||||
CPUState *cpu;
|
||||
CPUState *cpu = NULL;
|
||||
|
||||
if (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);
|
||||
cpu = first_cpu;
|
||||
}
|
||||
assert(cpu != NULL);
|
||||
if (synchronize) {
|
||||
cpu_synchronize_state(cpu);
|
||||
}
|
||||
|
39
os-posix.c
39
os-posix.c
@ -80,41 +80,26 @@ void os_setup_signal_handling(void)
|
||||
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
|
||||
running from the build tree this will be "$bindir/../pc-bios". */
|
||||
#define SHARE_SUFFIX "/share/qemu"
|
||||
#define BUILD_SUFFIX "/pc-bios"
|
||||
/*
|
||||
* Find a likely location for support files using the location of the binary.
|
||||
* When running from the build tree this will be "$bindir/../pc-bios".
|
||||
* Otherwise, this is CONFIG_QEMU_DATADIR.
|
||||
*/
|
||||
char *os_find_datadir(void)
|
||||
{
|
||||
char *dir, *exec_dir;
|
||||
char *res;
|
||||
size_t max_len;
|
||||
g_autofree char *exec_dir = NULL;
|
||||
g_autofree char *dir = NULL;
|
||||
|
||||
exec_dir = qemu_get_exec_dir();
|
||||
if (exec_dir == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
dir = g_path_get_dirname(exec_dir);
|
||||
g_return_val_if_fail(exec_dir != NULL, NULL);
|
||||
|
||||
max_len = strlen(dir) +
|
||||
MAX(strlen(SHARE_SUFFIX), strlen(BUILD_SUFFIX)) + 1;
|
||||
res = g_malloc0(max_len);
|
||||
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;
|
||||
}
|
||||
dir = g_build_filename(exec_dir, "..", "pc-bios", NULL);
|
||||
if (g_file_test(dir, G_FILE_TEST_IS_DIR)) {
|
||||
return g_steal_pointer(&dir);
|
||||
}
|
||||
|
||||
g_free(dir);
|
||||
g_free(exec_dir);
|
||||
return res;
|
||||
return g_strdup(CONFIG_QEMU_DATADIR);
|
||||
}
|
||||
#undef SHARE_SUFFIX
|
||||
#undef BUILD_SUFFIX
|
||||
|
||||
void os_set_proc_name(const char *s)
|
||||
{
|
||||
|
@ -43,7 +43,7 @@
|
||||
|
||||
#include "net/tap-linux.h"
|
||||
|
||||
#ifdef CONFIG_LIBCAP
|
||||
#ifdef CONFIG_LIBCAP_NG
|
||||
#include <cap-ng.h>
|
||||
#endif
|
||||
|
||||
@ -207,7 +207,7 @@ static int send_fd(int c, int fd)
|
||||
return sendmsg(c, &msg, 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LIBCAP
|
||||
#ifdef CONFIG_LIBCAP_NG
|
||||
static int drop_privileges(void)
|
||||
{
|
||||
/* clear all capabilities */
|
||||
@ -246,7 +246,7 @@ int main(int argc, char **argv)
|
||||
int access_allowed, access_denied;
|
||||
int ret = EXIT_SUCCESS;
|
||||
|
||||
#ifdef CONFIG_LIBCAP
|
||||
#ifdef CONFIG_LIBCAP_NG
|
||||
/* if we're run from an suid binary, immediately drop privileges preserving
|
||||
* cap_net_admin */
|
||||
if (geteuid() == 0 && getuid() != geteuid()) {
|
||||
|
@ -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
|
||||
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
|
||||
|
||||
@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'
|
||||
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
|
||||
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
Loading…
Reference in New Issue
Block a user