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

- vhost-scsi: add bootindex property
- RCU: fix MemoryRegion lifetime issues in PCI; document the rules;
convert of AddressSpaceDispatch and RAMList
- KVM: add kvm_exit reasons for aarch64

# gpg: Signature made Mon Feb 16 16:32:32 2015 GMT using RSA key ID 78C7AE83
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>"
# gpg:                 aka "Paolo Bonzini <pbonzini@redhat.com>"
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# 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: (21 commits)
  Convert ram_list to RCU
  exec: convert ram_list to QLIST
  cosmetic changes preparing for the following patches
  exec: protect mru_block with RCU
  rcu: add g_free_rcu
  rcu: introduce RCU-enabled QLIST
  exec: RCUify AddressSpaceDispatch
  exec: make iotlb RCU-friendly
  exec: introduce cpu_reload_memory_map
  docs: clarify memory region lifecycle
  pci: split shpc_cleanup and shpc_free
  pcie: remove mmconfig memory leak and wrap mmconfig update with transaction
  memory: keep the owner of the AddressSpace alive until do_address_space_destroy
  rcu: run RCU callbacks under the BQL
  rcu: do not let RCU callbacks pile up indefinitely
  vhost-scsi: set the bootable value of channel/target/lun
  vhost-scsi: add a property for booting
  vhost-scsi: expose the TYPE_FW_PATH_PROVIDER interface
  vhost-scsi: add bootindex property
  qdev: support to get a device firmware path directly
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell
2015-02-24 13:58:18 +00:00
36 changed files with 997 additions and 191 deletions
+51 -22
View File
@@ -52,6 +52,7 @@
#include "exec/ram_addr.h"
#include "hw/acpi/acpi.h"
#include "qemu/host-utils.h"
#include "qemu/rcu_queue.h"
#ifdef DEBUG_ARCH_INIT
#define DPRINTF(fmt, ...) \
@@ -487,7 +488,6 @@ static void migration_bitmap_sync_range(ram_addr_t start, ram_addr_t length)
}
/* Needs iothread lock! */
/* Fix me: there are too many global variables used in migration process. */
static int64_t start_time;
static int64_t bytes_xfer_prev;
@@ -500,6 +500,7 @@ static void migration_bitmap_sync_init(void)
num_dirty_pages_period = 0;
}
/* Called with iothread lock held, to protect ram_list.dirty_memory[] */
static void migration_bitmap_sync(void)
{
RAMBlock *block;
@@ -523,9 +524,12 @@ static void migration_bitmap_sync(void)
trace_migration_bitmap_sync_start();
address_space_sync_dirty_bitmap(&address_space_memory);
QTAILQ_FOREACH(block, &ram_list.blocks, next) {
rcu_read_lock();
QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
migration_bitmap_sync_range(block->mr->ram_addr, block->used_length);
}
rcu_read_unlock();
trace_migration_bitmap_sync_end(migration_dirty_pages
- num_dirty_pages_init);
num_dirty_pages_period += migration_dirty_pages - num_dirty_pages_init;
@@ -648,6 +652,8 @@ static int ram_save_page(QEMUFile *f, RAMBlock* block, ram_addr_t offset,
/*
* ram_find_and_save_block: Finds a page to send and sends it to f
*
* Called within an RCU critical section.
*
* Returns: The number of bytes written.
* 0 means no dirty pages
*/
@@ -661,7 +667,7 @@ static int ram_find_and_save_block(QEMUFile *f, bool last_stage)
MemoryRegion *mr;
if (!block)
block = QTAILQ_FIRST(&ram_list.blocks);
block = QLIST_FIRST_RCU(&ram_list.blocks);
while (true) {
mr = block->mr;
@@ -672,9 +678,9 @@ static int ram_find_and_save_block(QEMUFile *f, bool last_stage)
}
if (offset >= block->used_length) {
offset = 0;
block = QTAILQ_NEXT(block, next);
block = QLIST_NEXT_RCU(block, next);
if (!block) {
block = QTAILQ_FIRST(&ram_list.blocks);
block = QLIST_FIRST_RCU(&ram_list.blocks);
complete_round = true;
ram_bulk_stage = false;
}
@@ -688,9 +694,9 @@ static int ram_find_and_save_block(QEMUFile *f, bool last_stage)
}
}
}
last_seen_block = block;
last_offset = offset;
return bytes_sent;
}
@@ -728,9 +734,10 @@ uint64_t ram_bytes_total(void)
RAMBlock *block;
uint64_t total = 0;
QTAILQ_FOREACH(block, &ram_list.blocks, next)
rcu_read_lock();
QLIST_FOREACH_RCU(block, &ram_list.blocks, next)
total += block->used_length;
rcu_read_unlock();
return total;
}
@@ -776,6 +783,13 @@ static void reset_ram_globals(void)
#define MAX_WAIT 50 /* ms, half buffered_file limit */
/* Each of ram_save_setup, ram_save_iterate and ram_save_complete has
* long-running RCU critical section. When rcu-reclaims in the code
* start to become numerous it will be necessary to reduce the
* granularity of these critical sections.
*/
static int ram_save_setup(QEMUFile *f, void *opaque)
{
RAMBlock *block;
@@ -816,8 +830,10 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
acct_clear();
}
/* iothread lock needed for ram_list.dirty_memory[] */
qemu_mutex_lock_iothread();
qemu_mutex_lock_ramlist();
rcu_read_lock();
bytes_transferred = 0;
reset_ram_globals();
@@ -830,7 +846,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
* gaps due to alignment or unplugs.
*/
migration_dirty_pages = 0;
QTAILQ_FOREACH(block, &ram_list.blocks, next) {
QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
uint64_t block_pages;
block_pages = block->used_length >> TARGET_PAGE_BITS;
@@ -839,17 +855,18 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
memory_global_dirty_log_start();
migration_bitmap_sync();
qemu_mutex_unlock_ramlist();
qemu_mutex_unlock_iothread();
qemu_put_be64(f, ram_bytes_total() | RAM_SAVE_FLAG_MEM_SIZE);
QTAILQ_FOREACH(block, &ram_list.blocks, next) {
QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
qemu_put_byte(f, strlen(block->idstr));
qemu_put_buffer(f, (uint8_t *)block->idstr, strlen(block->idstr));
qemu_put_be64(f, block->used_length);
}
qemu_mutex_unlock_ramlist();
rcu_read_unlock();
ram_control_before_iterate(f, RAM_CONTROL_SETUP);
ram_control_after_iterate(f, RAM_CONTROL_SETUP);
@@ -866,12 +883,14 @@ static int ram_save_iterate(QEMUFile *f, void *opaque)
int64_t t0;
int total_sent = 0;
qemu_mutex_lock_ramlist();
rcu_read_lock();
if (ram_list.version != last_version) {
reset_ram_globals();
}
/* Read version before ram_list.blocks */
smp_rmb();
ram_control_before_iterate(f, RAM_CONTROL_ROUND);
t0 = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
@@ -902,8 +921,7 @@ static int ram_save_iterate(QEMUFile *f, void *opaque)
}
i++;
}
qemu_mutex_unlock_ramlist();
rcu_read_unlock();
/*
* Must occur before EOS (or any QEMUFile operation)
@@ -928,9 +946,11 @@ static int ram_save_iterate(QEMUFile *f, void *opaque)
return total_sent;
}
/* Called with iothread lock */
static int ram_save_complete(QEMUFile *f, void *opaque)
{
qemu_mutex_lock_ramlist();
rcu_read_lock();
migration_bitmap_sync();
ram_control_before_iterate(f, RAM_CONTROL_FINISH);
@@ -952,7 +972,7 @@ static int ram_save_complete(QEMUFile *f, void *opaque)
ram_control_after_iterate(f, RAM_CONTROL_FINISH);
migration_end();
qemu_mutex_unlock_ramlist();
rcu_read_unlock();
qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
return 0;
@@ -966,7 +986,9 @@ static uint64_t ram_save_pending(QEMUFile *f, void *opaque, uint64_t max_size)
if (remaining_size < max_size) {
qemu_mutex_lock_iothread();
rcu_read_lock();
migration_bitmap_sync();
rcu_read_unlock();
qemu_mutex_unlock_iothread();
remaining_size = ram_save_remaining() * TARGET_PAGE_SIZE;
}
@@ -1008,6 +1030,9 @@ static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host)
return 0;
}
/* Must be called from within a rcu critical section.
* Returns a pointer from within the RCU-protected ram_list.
*/
static inline void *host_from_stream_offset(QEMUFile *f,
ram_addr_t offset,
int flags)
@@ -1029,7 +1054,7 @@ static inline void *host_from_stream_offset(QEMUFile *f,
qemu_get_buffer(f, (uint8_t *)id, len);
id[len] = 0;
QTAILQ_FOREACH(block, &ram_list.blocks, next) {
QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
if (!strncmp(id, block->idstr, sizeof(id)) &&
block->max_length > offset) {
return memory_region_get_ram_ptr(block->mr) + offset;
@@ -1062,6 +1087,12 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
ret = -EINVAL;
}
/* This RCU critical section can be very long running.
* When RCU reclaims in the code start to become numerous,
* it will be necessary to reduce the granularity of this
* critical section.
*/
rcu_read_lock();
while (!ret && !(flags & RAM_SAVE_FLAG_EOS)) {
ram_addr_t addr, total_ram_bytes;
void *host;
@@ -1086,7 +1117,7 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
id[len] = 0;
length = qemu_get_be64(f);
QTAILQ_FOREACH(block, &ram_list.blocks, next) {
QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
if (!strncmp(id, block->idstr, sizeof(id))) {
if (length != block->used_length) {
Error *local_err = NULL;
@@ -1117,7 +1148,6 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
ret = -EINVAL;
break;
}
ch = qemu_get_byte(f);
ram_handle_compressed(host, ch, TARGET_PAGE_SIZE);
break;
@@ -1128,7 +1158,6 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
ret = -EINVAL;
break;
}
qemu_get_buffer(f, host, TARGET_PAGE_SIZE);
break;
case RAM_SAVE_FLAG_XBZRLE:
@@ -1138,7 +1167,6 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
ret = -EINVAL;
break;
}
if (load_xbzrle(f, addr, host) < 0) {
error_report("Failed to decompress XBZRLE page at "
RAM_ADDR_FMT, addr);
@@ -1163,6 +1191,7 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
}
}
rcu_read_unlock();
DPRINTF("Completed load of VM with exit code %d seq iteration "
"%" PRIu64 "\n", ret, seq_iter);
return ret;
+17 -14
View File
@@ -210,7 +210,9 @@ char *get_boot_devices_list(size_t *size, bool ignore_suffixes)
char *list = NULL;
QTAILQ_FOREACH(i, &fw_boot_order, link) {
char *devpath = NULL, *bootpath;
char *devpath = NULL, *suffix = NULL;
char *bootpath;
char *d;
size_t len;
if (i->dev) {
@@ -218,21 +220,22 @@ char *get_boot_devices_list(size_t *size, bool ignore_suffixes)
assert(devpath);
}
if (i->suffix && !ignore_suffixes && devpath) {
size_t bootpathlen = strlen(devpath) + strlen(i->suffix) + 1;
bootpath = g_malloc(bootpathlen);
snprintf(bootpath, bootpathlen, "%s%s", devpath, i->suffix);
g_free(devpath);
} else if (devpath) {
bootpath = devpath;
} else if (!ignore_suffixes) {
assert(i->suffix);
bootpath = g_strdup(i->suffix);
} else {
bootpath = g_strdup("");
if (!ignore_suffixes) {
d = qdev_get_own_fw_dev_path_from_handler(i->dev->parent_bus, i->dev);
if (d) {
assert(!i->suffix);
suffix = d;
} else {
suffix = g_strdup(i->suffix);
}
}
bootpath = g_strdup_printf("%s%s",
devpath ? devpath : "",
suffix ? suffix : "");
g_free(devpath);
g_free(suffix);
if (total) {
list[total-1] = '\n';
}
+33
View File
@@ -24,6 +24,9 @@
#include "qemu/atomic.h"
#include "sysemu/qtest.h"
#include "qemu/timer.h"
#include "exec/address-spaces.h"
#include "exec/memory-internal.h"
#include "qemu/rcu.h"
/* -icount align implementation. */
@@ -141,6 +144,33 @@ void cpu_resume_from_signal(CPUState *cpu, void *puc)
cpu->exception_index = -1;
siglongjmp(cpu->jmp_env, 1);
}
void cpu_reload_memory_map(CPUState *cpu)
{
AddressSpaceDispatch *d;
if (qemu_in_vcpu_thread()) {
/* Do not let the guest prolong the critical section as much as it
* as it desires.
*
* Currently, this is prevented by the I/O thread's periodinc kicking
* of the VCPU thread (iothread_requesting_mutex, qemu_cpu_kick_thread)
* but this will go away once TCG's execution moves out of the global
* mutex.
*
* This pair matches cpu_exec's rcu_read_lock()/rcu_read_unlock(), which
* only protects cpu->as->dispatch. Since we reload it below, we can
* split the critical section.
*/
rcu_read_unlock();
rcu_read_lock();
}
/* The CPU and TLB are protected by the iothread lock. */
d = atomic_rcu_read(&cpu->as->dispatch);
cpu->memory_dispatch = d;
tlb_flush(cpu, 1);
}
#endif
/* Execute a TB, and fix up the CPU state afterwards if necessary */
@@ -352,6 +382,8 @@ int cpu_exec(CPUArchState *env)
* an instruction scheduling constraint on modern architectures. */
smp_mb();
rcu_read_lock();
if (unlikely(exit_request)) {
cpu->exit_request = 1;
}
@@ -548,6 +580,7 @@ int cpu_exec(CPUArchState *env)
} /* for(;;) */
cc->cpu_exec_exit(cpu);
rcu_read_unlock();
/* fail safe : never use current_cpu outside cpu_exec() */
current_cpu = NULL;
+1 -1
View File
@@ -1108,7 +1108,7 @@ bool qemu_cpu_is_self(CPUState *cpu)
return qemu_thread_is_self(cpu->thread);
}
static bool qemu_in_vcpu_thread(void)
bool qemu_in_vcpu_thread(void)
{
return current_cpu && qemu_cpu_is_self(current_cpu);
}
+8 -5
View File
@@ -243,8 +243,12 @@ static void tlb_add_large_page(CPUArchState *env, target_ulong vaddr,
}
/* Add a new TLB entry. At most one entry for a given virtual address
is permitted. Only a single TARGET_PAGE_SIZE region is mapped, the
supplied size is only used by tlb_flush_page. */
* is permitted. Only a single TARGET_PAGE_SIZE region is mapped, the
* supplied size is only used by tlb_flush_page.
*
* Called from TCG-generated code, which is under an RCU read-side
* critical section.
*/
void tlb_set_page(CPUState *cpu, target_ulong vaddr,
hwaddr paddr, int prot,
int mmu_idx, target_ulong size)
@@ -265,8 +269,7 @@ void tlb_set_page(CPUState *cpu, target_ulong vaddr,
}
sz = size;
section = address_space_translate_for_iotlb(cpu->as, paddr,
&xlat, &sz);
section = address_space_translate_for_iotlb(cpu, paddr, &xlat, &sz);
assert(sz >= TARGET_PAGE_SIZE);
#if defined(DEBUG_TLB)
@@ -347,7 +350,7 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
cpu_ldub_code(env1, addr);
}
pd = env1->iotlb[mmu_idx][page_index] & ~TARGET_PAGE_MASK;
mr = iotlb_to_region(cpu->as, pd);
mr = iotlb_to_region(cpu, pd);
if (memory_region_is_unassigned(mr)) {
CPUClass *cc = CPU_GET_CLASS(cpu);
+58 -16
View File
@@ -73,17 +73,66 @@ stability.
Region lifecycle
----------------
A region is created by one of the constructor functions (memory_region_init*())
and attached to an object. It is then destroyed by object_unparent() or simply
when the parent object dies.
A region is created by one of the memory_region_init*() functions and
attached to an object, which acts as its owner or parent. QEMU ensures
that the owner object remains alive as long as the region is visible to
the guest, or as long as the region is in use by a virtual CPU or another
device. For example, the owner object will not die between an
address_space_map operation and the corresponding address_space_unmap.
In between, a region can be added to an address space
by using memory_region_add_subregion() and removed using
memory_region_del_subregion(). Destroying the region implicitly
removes the region from the address space.
After creation, a region can be added to an address space or a
container with memory_region_add_subregion(), and removed using
memory_region_del_subregion().
Various region attributes (read-only, dirty logging, coalesced mmio,
ioeventfd) can be changed during the region lifecycle. They take effect
as soon as the region is made visible. This can be immediately, later,
or never.
Destruction of a memory region happens automatically when the owner
object dies.
If however the memory region is part of a dynamically allocated data
structure, you should call object_unparent() to destroy the memory region
before the data structure is freed. For an example see VFIOMSIXInfo
and VFIOQuirk in hw/vfio/pci.c.
You must not destroy a memory region as long as it may be in use by a
device or CPU. In order to do this, as a general rule do not create or
destroy memory regions dynamically during a device's lifetime, and only
call object_unparent() in the memory region owner's instance_finalize
callback. The dynamically allocated data structure that contains the
memory region then should obviously be freed in the instance_finalize
callback as well.
If you break this rule, the following situation can happen:
- the memory region's owner had a reference taken via memory_region_ref
(for example by address_space_map)
- the region is unparented, and has no owner anymore
- when address_space_unmap is called, the reference to the memory region's
owner is leaked.
There is an exception to the above rule: it is okay to call
object_unparent at any time for an alias or a container region. It is
therefore also okay to create or destroy alias and container regions
dynamically during a device's lifetime.
This exceptional usage is valid because aliases and containers only help
QEMU building the guest's memory map; they are never accessed directly.
memory_region_ref and memory_region_unref are never called on aliases
or containers, and the above situation then cannot happen. Exploiting
this exception is rarely necessary, and therefore it is discouraged,
but nevertheless it is used in a few places.
For regions that "have no owner" (NULL is passed at creation time), the
machine object is actually used as the owner. Since instance_finalize is
never called for the machine object, you must never call object_unparent
on regions that have no owner, unless they are aliases or containers.
Region attributes may be changed at any point; they take effect once
the region becomes exposed to the guest.
Overlapping regions and priority
--------------------------------
@@ -215,13 +264,6 @@ BAR containing MMIO registers is mapped after it.
Note that if the guest maps a BAR outside the PCI hole, it would not be
visible as the pci-hole alias clips it to a 0.5GB range.
Attributes
----------
Various region attributes (read-only, dirty logging, coalesced mmio, ioeventfd)
can be changed during the region lifecycle. They take effect once the region
is made visible (which can be immediately, later, or never).
MMIO Operations
---------------
+7 -4
View File
@@ -120,12 +120,15 @@ The core RCU API is small:
void call_rcu(T *p,
void (*func)(T *p),
field-name);
void g_free_rcu(T *p,
field-name);
call_rcu1 is typically used through this macro, in the common case
where the "struct rcu_head" is the first field in the struct. In
the above case, one could have written simply:
call_rcu1 is typically used through these macro, in the common case
where the "struct rcu_head" is the first field in the struct. If
the callback function is g_free, in particular, g_free_rcu can be
used. In the above case, one could have written simply:
call_rcu(foo_reclaim, g_free, rcu);
g_free_rcu(foo_reclaim, rcu);
typeof(*p) atomic_rcu_read(p);
+208 -87
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -18,7 +18,7 @@
#include "fsdev/qemu-fsdev.h"
#include "virtio-9p-synth.h"
#include "qemu/rcu.h"
#include "qemu/rcu_queue.h"
#include <sys/stat.h>
/* Root node for synth file system */
+7
View File
@@ -818,6 +818,13 @@ static char *qdev_get_fw_dev_path_from_handler(BusState *bus, DeviceState *dev)
return d;
}
char *qdev_get_own_fw_dev_path_from_handler(BusState *bus, DeviceState *dev)
{
Object *obj = OBJECT(dev);
return fw_path_provider_try_get_dev_path(obj, bus, dev);
}
static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
{
int l = 0;
+3
View File
@@ -745,6 +745,9 @@ static inline bool vtd_is_interrupt_addr(hwaddr addr)
/* Map dev to context-entry then do a paging-structures walk to do a iommu
* translation.
*
* Called from RCU critical section.
*
* @bus_num: The bus number
* @devfn: The devfn, which is the combined of device and function number
* @is_write: The access is a write operation
+10 -4
View File
@@ -97,6 +97,11 @@ static void pci_bridge_dev_exitfn(PCIDevice *dev)
pci_bridge_exitfn(dev);
}
static void pci_bridge_dev_instance_finalize(Object *obj)
{
shpc_free(PCI_DEVICE(obj));
}
static void pci_bridge_dev_write_config(PCIDevice *d,
uint32_t address, uint32_t val, int len)
{
@@ -154,10 +159,11 @@ static void pci_bridge_dev_class_init(ObjectClass *klass, void *data)
}
static const TypeInfo pci_bridge_dev_info = {
.name = TYPE_PCI_BRIDGE_DEV,
.parent = TYPE_PCI_BRIDGE,
.instance_size = sizeof(PCIBridgeDev),
.class_init = pci_bridge_dev_class_init,
.name = TYPE_PCI_BRIDGE_DEV,
.parent = TYPE_PCI_BRIDGE,
.instance_size = sizeof(PCIBridgeDev),
.class_init = pci_bridge_dev_class_init,
.instance_finalize = pci_bridge_dev_instance_finalize,
.interfaces = (InterfaceInfo[]) {
{ TYPE_HOTPLUG_HANDLER },
{ }
+1
View File
@@ -205,6 +205,7 @@ static AddressSpace *pbm_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
return &is->iommu_as;
}
/* Called from RCU critical section */
static IOMMUTLBEntry pbm_translate_iommu(MemoryRegion *iommu, hwaddr addr,
bool is_write)
{
+5 -2
View File
@@ -88,6 +88,8 @@ static void pcie_host_init(Object *obj)
PCIExpressHost *e = PCIE_HOST_BRIDGE(obj);
e->base_addr = PCIE_BASE_ADDR_UNMAPPED;
memory_region_init_io(&e->mmio, OBJECT(e), &pcie_mmcfg_ops, e, "pcie-mmcfg-mmio",
PCIE_MMCFG_SIZE_MAX);
}
void pcie_host_mmcfg_unmap(PCIExpressHost *e)
@@ -104,8 +106,7 @@ void pcie_host_mmcfg_init(PCIExpressHost *e, uint32_t size)
assert(size >= PCIE_MMCFG_SIZE_MIN);
assert(size <= PCIE_MMCFG_SIZE_MAX);
e->size = size;
memory_region_init_io(&e->mmio, OBJECT(e), &pcie_mmcfg_ops, e,
"pcie-mmcfg", e->size);
memory_region_set_size(&e->mmio, e->size);
}
void pcie_host_mmcfg_map(PCIExpressHost *e, hwaddr addr,
@@ -121,10 +122,12 @@ void pcie_host_mmcfg_update(PCIExpressHost *e,
hwaddr addr,
uint32_t size)
{
memory_region_transaction_begin();
pcie_host_mmcfg_unmap(e);
if (enable) {
pcie_host_mmcfg_map(e, addr, size);
}
memory_region_transaction_commit();
}
static const TypeInfo pcie_host_type_info = {
+10 -1
View File
@@ -663,13 +663,22 @@ void shpc_cleanup(PCIDevice *d, MemoryRegion *bar)
SHPCDevice *shpc = d->shpc;
d->cap_present &= ~QEMU_PCI_CAP_SHPC;
memory_region_del_subregion(bar, &shpc->mmio);
object_unparent(OBJECT(&shpc->mmio));
/* TODO: cleanup config space changes? */
}
void shpc_free(PCIDevice *d)
{
SHPCDevice *shpc = d->shpc;
if (!shpc) {
return;
}
object_unparent(OBJECT(&shpc->mmio));
g_free(shpc->config);
g_free(shpc->cmask);
g_free(shpc->wmask);
g_free(shpc->w1cmask);
g_free(shpc);
d->shpc = NULL;
}
void shpc_cap_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
+1
View File
@@ -59,6 +59,7 @@ static sPAPRTCETable *spapr_tce_find_by_liobn(uint32_t liobn)
return NULL;
}
/* Called from RCU critical section */
static IOMMUTLBEntry spapr_tce_translate_iommu(MemoryRegion *iommu, hwaddr addr,
bool is_write)
{
+35
View File
@@ -24,6 +24,7 @@
#include "hw/virtio/virtio-scsi.h"
#include "hw/virtio/virtio-bus.h"
#include "hw/virtio/virtio-access.h"
#include "hw/fw-path-provider.h"
/* Features supported by host kernel. */
static const int kernel_feature_bits[] = {
@@ -250,6 +251,12 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp)
return;
}
/* At present, channel and lun both are 0 for bootable vhost-scsi disk */
s->channel = 0;
s->lun = 0;
/* Note: we can also get the minimum tpgt from kernel */
s->target = vs->conf.boot_tpgt;
error_setg(&s->migration_blocker,
"vhost-scsi does not support migration");
migrate_add_blocker(s->migration_blocker);
@@ -271,6 +278,19 @@ static void vhost_scsi_unrealize(DeviceState *dev, Error **errp)
virtio_scsi_common_unrealize(dev, errp);
}
/*
* Implementation of an interface to adjust firmware path
* for the bootindex property handling.
*/
static char *vhost_scsi_get_fw_dev_path(FWPathProvider *p, BusState *bus,
DeviceState *dev)
{
VHostSCSI *s = VHOST_SCSI(dev);
/* format: channel@channel/vhost-scsi@target,lun */
return g_strdup_printf("channel@%x/%s@%x,%x", s->channel,
qdev_fw_name(dev), s->target, s->lun);
}
static Property vhost_scsi_properties[] = {
DEFINE_VHOST_SCSI_PROPERTIES(VHostSCSI, parent_obj.conf),
DEFINE_PROP_END_OF_LIST(),
@@ -280,6 +300,7 @@ static void vhost_scsi_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(klass);
dc->props = vhost_scsi_properties;
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
@@ -288,6 +309,15 @@ static void vhost_scsi_class_init(ObjectClass *klass, void *data)
vdc->get_features = vhost_scsi_get_features;
vdc->set_config = vhost_scsi_set_config;
vdc->set_status = vhost_scsi_set_status;
fwc->get_dev_path = vhost_scsi_get_fw_dev_path;
}
static void vhost_scsi_instance_init(Object *obj)
{
VHostSCSI *dev = VHOST_SCSI(obj);
device_add_bootindex_property(obj, &dev->bootindex, "bootindex", NULL,
DEVICE(dev), NULL);
}
static const TypeInfo vhost_scsi_info = {
@@ -295,6 +325,11 @@ static const TypeInfo vhost_scsi_info = {
.parent = TYPE_VIRTIO_SCSI_COMMON,
.instance_size = sizeof(VHostSCSI),
.class_init = vhost_scsi_class_init,
.instance_init = vhost_scsi_instance_init,
.interfaces = (InterfaceInfo[]) {
{ TYPE_FW_PATH_PROVIDER },
{ }
},
};
static void virtio_register_types(void)
+2
View File
@@ -1238,6 +1238,8 @@ static void vhost_scsi_pci_instance_init(Object *obj)
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
TYPE_VHOST_SCSI);
object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev),
"bootindex", &error_abort);
}
static const TypeInfo vhost_scsi_pci_info = {
+7 -6
View File
@@ -24,6 +24,7 @@
#include "exec/memory.h"
#include "qemu/thread.h"
#include "qom/cpu.h"
#include "qemu/rcu.h"
/* some important defines:
*
@@ -268,6 +269,7 @@ CPUArchState *cpu_copy(CPUArchState *env);
typedef struct RAMBlock RAMBlock;
struct RAMBlock {
struct rcu_head rcu;
struct MemoryRegion *mr;
uint8_t *host;
ram_addr_t offset;
@@ -275,11 +277,10 @@ struct RAMBlock {
ram_addr_t max_length;
void (*resized)(const char*, uint64_t length, void *host);
uint32_t flags;
/* Protected by iothread lock. */
char idstr[256];
/* Reads can take either the iothread or the ramlist lock.
* Writes must take both locks.
*/
QTAILQ_ENTRY(RAMBlock) next;
/* RCU-enabled, writes protected by the ramlist lock */
QLIST_ENTRY(RAMBlock) next;
int fd;
};
@@ -295,8 +296,8 @@ typedef struct RAMList {
/* Protected by the iothread lock. */
unsigned long *dirty_memory[DIRTY_MEMORY_NUM];
RAMBlock *mru_block;
/* Protected by the ramlist lock. */
QTAILQ_HEAD(, RAMBlock) blocks;
/* RCU-enabled, writes protected by the ramlist lock. */
QLIST_HEAD(, RAMBlock) blocks;
uint32_t version;
} RAMList;
extern RAMList ram_list;
+1 -1
View File
@@ -34,7 +34,7 @@ extern int tlb_flush_count;
void tb_flush_jmp_cache(CPUState *cpu, target_ulong addr);
MemoryRegionSection *
address_space_translate_for_iotlb(AddressSpace *as, hwaddr addr, hwaddr *xlat,
address_space_translate_for_iotlb(CPUState *cpu, hwaddr addr, hwaddr *xlat,
hwaddr *plen);
hwaddr memory_region_section_get_iotlb(CPUState *cpu,
MemoryRegionSection *section,

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