diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2018-08-23 19:03:53 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2018-08-23 19:03:54 +0100 |
commit | 3c825bb7c1b4289ef05f51b5b77ac0967b6a27fa (patch) | |
tree | 44c5189aacbe795b125bfb4b5144a37fe122d2e4 /include | |
parent | 5ccac548faf041ff5229a8e8342e3be14a34c8af (diff) | |
parent | b2e78fac6f27c36938353e477354778896adc08f (diff) |
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
* x86 TCG fixes for 64-bit call gates (Andrew)
* qumu-guest-agent freeze-hook tweak (Christian)
* pm_smbus improvements (Corey)
* Move validation to pre_plug for pc-dimm (David)
* Fix memory leaks (Eduardo, Marc-André)
* synchronization profiler (Emilio)
* Convert the CPU list to RCU (Emilio)
* LSI support for PPR Extended Message (George)
* vhost-scsi support for protection information (Greg)
* Mark mptsas as a storage device in the help (Guenter)
* checkpatch tweak cherry-picked from Linux (me)
* Typos, cleanups and dead-code removal (Julia, Marc-André)
* qemu-pr-helper support for old libmultipath (Murilo)
* Annotate fallthroughs (me)
* MemoryRegionOps cleanup (me, Peter)
* Make s390 qtests independent from libqos, which doesn't actually support it (me)
* Make cpu_get_ticks independent from BQL (me)
* Introspection fixes (Thomas)
* Support QEMU_MODULE_DIR environment variable (ryang)
# gpg: Signature made Thu 23 Aug 2018 17:46:30 BST
# gpg: using RSA key BFFBD25F78C7AE83
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>"
# gpg: aka "Paolo Bonzini <pbonzini@redhat.com>"
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1
# Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83
* remotes/bonzini/tags/for-upstream: (69 commits)
KVM: cleanup unnecessary #ifdef KVM_CAP_...
target/i386: update MPX flags when CPL changes
i2c: pm_smbus: Add the ability to force block transfer enable
i2c: pm_smbus: Don't delay host status register busy bit when interrupts are enabled
i2c: pm_smbus: Add interrupt handling
i2c: pm_smbus: Add block transfer capability
i2c: pm_smbus: Make the I2C block read command read-only
i2c: pm_smbus: Fix the semantics of block I2C transfers
i2c: pm_smbus: Clean up some style issues
pc-dimm: assign and verify the "addr" property during pre_plug
pc: drop memory region alignment check for 0
util/oslib-win32: indicate alignment for qemu_anon_ram_alloc()
pc-dimm: assign and verify the "slot" property during pre_plug
ipmi: Use proper struct reference for BT vmstate
vhost-scsi: expose 't10_pi' property for VIRTIO_SCSI_F_T10_PI
vhost-scsi: unify vhost-scsi get_features implementations
vhost-user-scsi: move host_features into VHostSCSICommon
cpus: allow cpu_get_ticks out of BQL
cpus: protect TimerState writes with a spinlock
seqlock: add QemuLockable support
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/chardev/char-fe.h | 10 | ||||
-rw-r--r-- | include/hw/i2c/pm_smbus.h | 24 | ||||
-rw-r--r-- | include/hw/i2c/smbus.h | 17 | ||||
-rw-r--r-- | include/hw/mem/pc-dimm.h | 5 | ||||
-rw-r--r-- | include/hw/misc/vmcoreinfo.h | 12 | ||||
-rw-r--r-- | include/hw/nvram/fw_cfg.h | 18 | ||||
-rw-r--r-- | include/hw/nvram/fw_cfg_keys.h | 45 | ||||
-rw-r--r-- | include/hw/virtio/vhost-scsi-common.h | 1 | ||||
-rw-r--r-- | include/hw/virtio/vhost-user-scsi.h | 1 | ||||
-rw-r--r-- | include/qemu/main-loop.h | 4 | ||||
-rw-r--r-- | include/qemu/qht.h | 1 | ||||
-rw-r--r-- | include/qemu/qsp.h | 29 | ||||
-rw-r--r-- | include/qemu/rcu_queue.h | 135 | ||||
-rw-r--r-- | include/qemu/seqlock.h | 22 | ||||
-rw-r--r-- | include/qemu/thread-posix.h | 4 | ||||
-rw-r--r-- | include/qemu/thread-win32.h | 5 | ||||
-rw-r--r-- | include/qemu/thread.h | 66 | ||||
-rw-r--r-- | include/qom/cpu.h | 11 | ||||
-rw-r--r-- | include/standard-headers/linux/qemu_fw_cfg.h | 97 |
19 files changed, 403 insertions, 104 deletions
diff --git a/include/chardev/char-fe.h b/include/chardev/char-fe.h index 71cd069478..c67271f1ba 100644 --- a/include/chardev/char-fe.h +++ b/include/chardev/char-fe.h @@ -113,7 +113,7 @@ void qemu_chr_fe_accept_input(CharBackend *be); /** * @qemu_chr_fe_disconnect: * - * Close a fd accpeted by character backend. + * Close a fd accepted by character backend. * Without associated Chardev, do nothing. */ void qemu_chr_fe_disconnect(CharBackend *be); @@ -122,7 +122,7 @@ void qemu_chr_fe_disconnect(CharBackend *be); * @qemu_chr_fe_wait_connected: * * Wait for characted backend to be connected, return < 0 on error or - * if no assicated Chardev. + * if no associated Chardev. */ int qemu_chr_fe_wait_connected(CharBackend *be, Error **errp); @@ -186,7 +186,7 @@ guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond, * @buf the data * @len the number of bytes to send * - * Returns: the number of bytes consumed (0 if no assicated Chardev) + * Returns: the number of bytes consumed (0 if no associated Chardev) */ int qemu_chr_fe_write(CharBackend *be, const uint8_t *buf, int len); @@ -201,7 +201,7 @@ int qemu_chr_fe_write(CharBackend *be, const uint8_t *buf, int len); * @buf the data * @len the number of bytes to send * - * Returns: the number of bytes consumed (0 if no assicated Chardev) + * Returns: the number of bytes consumed (0 if no associated Chardev) */ int qemu_chr_fe_write_all(CharBackend *be, const uint8_t *buf, int len); @@ -213,7 +213,7 @@ int qemu_chr_fe_write_all(CharBackend *be, const uint8_t *buf, int len); * @buf the data buffer * @len the number of bytes to read * - * Returns: the number of bytes read (0 if no assicated Chardev) + * Returns: the number of bytes read (0 if no associated Chardev) */ int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len); diff --git a/include/hw/i2c/pm_smbus.h b/include/hw/i2c/pm_smbus.h index 2a837afdcb..060d3c6ac0 100644 --- a/include/hw/i2c/pm_smbus.h +++ b/include/hw/i2c/pm_smbus.h @@ -1,6 +1,8 @@ #ifndef PM_SMBUS_H #define PM_SMBUS_H +#define PM_SMBUS_MAX_MSG_SIZE 32 + typedef struct PMSMBus { I2CBus *smbus; MemoryRegion io; @@ -11,10 +13,26 @@ typedef struct PMSMBus { uint8_t smb_addr; uint8_t smb_data0; uint8_t smb_data1; - uint8_t smb_data[32]; - uint8_t smb_index; + uint8_t smb_data[PM_SMBUS_MAX_MSG_SIZE]; + uint8_t smb_blkdata; + uint8_t smb_auxctl; + uint32_t smb_index; + + /* Set by pm_smbus.c */ + void (*reset)(struct PMSMBus *s); + + /* Set by the user. */ + bool i2c_enable; + void (*set_irq)(struct PMSMBus *s, bool enabled); + void *opaque; + + /* Internally used by pm_smbus. */ + + /* Set on block transfers after the last byte has been read, so the + INTR bit can be set at the right time. */ + bool op_done; } PMSMBus; -void pm_smbus_init(DeviceState *parent, PMSMBus *smb); +void pm_smbus_init(DeviceState *parent, PMSMBus *smb, bool force_aux_blk); #endif /* PM_SMBUS_H */ diff --git a/include/hw/i2c/smbus.h b/include/hw/i2c/smbus.h index 4fdba022c1..d8b1b9ee81 100644 --- a/include/hw/i2c/smbus.h +++ b/include/hw/i2c/smbus.h @@ -72,9 +72,22 @@ int smbus_read_byte(I2CBus *bus, uint8_t addr, uint8_t command); int smbus_write_byte(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t data); int smbus_read_word(I2CBus *bus, uint8_t addr, uint8_t command); int smbus_write_word(I2CBus *bus, uint8_t addr, uint8_t command, uint16_t data); -int smbus_read_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data); + +/* + * Do a block transfer from an I2C device. If recv_len is set, then the + * first received byte is a length field and is used to know how much data + * to receive. Otherwise receive "len" bytes. If send_cmd is set, send + * the command byte first before receiving the data. + */ +int smbus_read_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data, + int len, bool recv_len, bool send_cmd); + +/* + * Do a block transfer to an I2C device. If send_len is set, send the + * "len" value before the data. + */ int smbus_write_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data, - int len); + int len, bool send_len); void smbus_eeprom_init_one(I2CBus *smbus, uint8_t address, uint8_t *eeprom_buf); void smbus_eeprom_init(I2CBus *smbus, int nb_eeprom, diff --git a/include/hw/mem/pc-dimm.h b/include/hw/mem/pc-dimm.h index 26ebb7d5e9..b382eb4303 100644 --- a/include/hw/mem/pc-dimm.h +++ b/include/hw/mem/pc-dimm.h @@ -79,7 +79,8 @@ typedef struct PCDIMMDeviceClass { Error **errp); } PCDIMMDeviceClass; -void pc_dimm_plug(DeviceState *dev, MachineState *machine, uint64_t align, - Error **errp); +void pc_dimm_pre_plug(DeviceState *dev, MachineState *machine, + const uint64_t *legacy_align, Error **errp); +void pc_dimm_plug(DeviceState *dev, MachineState *machine, Error **errp); void pc_dimm_unplug(DeviceState *dev, MachineState *machine); #endif diff --git a/include/hw/misc/vmcoreinfo.h b/include/hw/misc/vmcoreinfo.h index c3aa856545..0d11578059 100644 --- a/include/hw/misc/vmcoreinfo.h +++ b/include/hw/misc/vmcoreinfo.h @@ -13,20 +13,12 @@ #define VMCOREINFO_H #include "hw/qdev.h" +#include "standard-headers/linux/qemu_fw_cfg.h" #define VMCOREINFO_DEVICE "vmcoreinfo" #define VMCOREINFO(obj) OBJECT_CHECK(VMCoreInfoState, (obj), VMCOREINFO_DEVICE) -#define VMCOREINFO_FORMAT_NONE 0x0 -#define VMCOREINFO_FORMAT_ELF 0x1 - -/* all fields are little-endian */ -typedef struct FWCfgVMCoreInfo { - uint16_t host_format; /* set on reset */ - uint16_t guest_format; - uint32_t size; - uint64_t paddr; -} QEMU_PACKED FWCfgVMCoreInfo; +typedef struct fw_cfg_vmcoreinfo FWCfgVMCoreInfo; typedef struct VMCoreInfoState { DeviceClass parent_obj; diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h index b2259cc4a3..f5a6895a74 100644 --- a/include/hw/nvram/fw_cfg.h +++ b/include/hw/nvram/fw_cfg.h @@ -2,7 +2,7 @@ #define FW_CFG_H #include "exec/hwaddr.h" -#include "hw/nvram/fw_cfg_keys.h" +#include "standard-headers/linux/qemu_fw_cfg.h" #include "hw/sysbus.h" #include "sysemu/dma.h" @@ -14,12 +14,7 @@ #define FW_CFG_IO(obj) OBJECT_CHECK(FWCfgIoState, (obj), TYPE_FW_CFG_IO) #define FW_CFG_MEM(obj) OBJECT_CHECK(FWCfgMemState, (obj), TYPE_FW_CFG_MEM) -typedef struct FWCfgFile { - uint32_t size; /* file size */ - uint16_t select; /* write this to 0x510 to read it */ - uint16_t reserved; - char name[FW_CFG_MAX_FILE_PATH]; -} FWCfgFile; +typedef struct fw_cfg_file FWCfgFile; #define FW_CFG_ORDER_OVERRIDE_VGA 70 #define FW_CFG_ORDER_OVERRIDE_NIC 80 @@ -34,14 +29,7 @@ typedef struct FWCfgFiles { FWCfgFile f[]; } FWCfgFiles; -/* Control as first field allows for different structures selected by this - * field, which might be useful in the future - */ -typedef struct FWCfgDmaAccess { - uint32_t control; - uint32_t length; - uint64_t address; -} QEMU_PACKED FWCfgDmaAccess; +typedef struct fw_cfg_dma_access FWCfgDmaAccess; typedef void (*FWCfgCallback)(void *opaque); typedef void (*FWCfgWriteCallback)(void *opaque, off_t start, size_t len); diff --git a/include/hw/nvram/fw_cfg_keys.h b/include/hw/nvram/fw_cfg_keys.h deleted file mode 100644 index b6919451f5..0000000000 --- a/include/hw/nvram/fw_cfg_keys.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef FW_CFG_KEYS_H -#define FW_CFG_KEYS_H - -#define FW_CFG_SIGNATURE 0x00 -#define FW_CFG_ID 0x01 -#define FW_CFG_UUID 0x02 -#define FW_CFG_RAM_SIZE 0x03 -#define FW_CFG_NOGRAPHIC 0x04 -#define FW_CFG_NB_CPUS 0x05 -#define FW_CFG_MACHINE_ID 0x06 -#define FW_CFG_KERNEL_ADDR 0x07 -#define FW_CFG_KERNEL_SIZE 0x08 -#define FW_CFG_KERNEL_CMDLINE 0x09 -#define FW_CFG_INITRD_ADDR 0x0a -#define FW_CFG_INITRD_SIZE 0x0b -#define FW_CFG_BOOT_DEVICE 0x0c -#define FW_CFG_NUMA 0x0d -#define FW_CFG_BOOT_MENU 0x0e -#define FW_CFG_MAX_CPUS 0x0f -#define FW_CFG_KERNEL_ENTRY 0x10 -#define FW_CFG_KERNEL_DATA 0x11 -#define FW_CFG_INITRD_DATA 0x12 -#define FW_CFG_CMDLINE_ADDR 0x13 -#define FW_CFG_CMDLINE_SIZE 0x14 -#define FW_CFG_CMDLINE_DATA 0x15 -#define FW_CFG_SETUP_ADDR 0x16 -#define FW_CFG_SETUP_SIZE 0x17 -#define FW_CFG_SETUP_DATA 0x18 -#define FW_CFG_FILE_DIR 0x19 - -#define FW_CFG_FILE_FIRST 0x20 -#define FW_CFG_FILE_SLOTS_MIN 0x10 - -#define FW_CFG_WRITE_CHANNEL 0x4000 -#define FW_CFG_ARCH_LOCAL 0x8000 -#define FW_CFG_ENTRY_MASK (~(FW_CFG_WRITE_CHANNEL | FW_CFG_ARCH_LOCAL)) - -#define FW_CFG_INVALID 0xffff - -/* width in bytes of fw_cfg control register */ -#define FW_CFG_CTL_SIZE 0x02 - -#define FW_CFG_MAX_FILE_PATH 56 - -#endif diff --git a/include/hw/virtio/vhost-scsi-common.h b/include/hw/virtio/vhost-scsi-common.h index 4553be4bc3..57fb1d87b5 100644 --- a/include/hw/virtio/vhost-scsi-common.h +++ b/include/hw/virtio/vhost-scsi-common.h @@ -35,6 +35,7 @@ typedef struct VHostSCSICommon { int channel; int target; int lun; + uint64_t host_features; } VHostSCSICommon; int vhost_scsi_common_start(VHostSCSICommon *vsc); diff --git a/include/hw/virtio/vhost-user-scsi.h b/include/hw/virtio/vhost-user-scsi.h index 3ec34ae867..e429cacd8e 100644 --- a/include/hw/virtio/vhost-user-scsi.h +++ b/include/hw/virtio/vhost-user-scsi.h @@ -30,7 +30,6 @@ typedef struct VHostUserSCSI { VHostSCSICommon parent_obj; - uint64_t host_features; VhostUserState *vhost_user; } VHostUserSCSI; diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h index 721aa2416a..e59f9ae1e9 100644 --- a/include/qemu/main-loop.h +++ b/include/qemu/main-loop.h @@ -276,7 +276,9 @@ bool qemu_mutex_iothread_locked(void); * NOTE: tools currently are single-threaded and qemu_mutex_lock_iothread * is a no-op there. */ -void qemu_mutex_lock_iothread(void); +#define qemu_mutex_lock_iothread() \ + qemu_mutex_lock_iothread_impl(__FILE__, __LINE__) +void qemu_mutex_lock_iothread_impl(const char *file, int line); /** * qemu_mutex_unlock_iothread: Unlock the main loop mutex. diff --git a/include/qemu/qht.h b/include/qemu/qht.h index 1fb9116fa0..c9a11cc29a 100644 --- a/include/qemu/qht.h +++ b/include/qemu/qht.h @@ -46,6 +46,7 @@ typedef bool (*qht_lookup_func_t)(const void *obj, const void *userp); typedef void (*qht_iter_func_t)(struct qht *ht, void *p, uint32_t h, void *up); #define QHT_MODE_AUTO_RESIZE 0x1 /* auto-resize when heavily loaded */ +#define QHT_MODE_RAW_MUTEXES 0x2 /* bypass the profiler (QSP) */ /** * qht_init - Initialize a QHT diff --git a/include/qemu/qsp.h b/include/qemu/qsp.h new file mode 100644 index 0000000000..a94c464f90 --- /dev/null +++ b/include/qemu/qsp.h @@ -0,0 +1,29 @@ +/* + * qsp.c - QEMU Synchronization Profiler + * + * Copyright (C) 2018, Emilio G. Cota <cota@braap.org> + * + * License: GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + * Note: this header file can *only* be included from thread.h. + */ +#ifndef QEMU_QSP_H +#define QEMU_QSP_H + +#include "qemu/fprintf-fn.h" + +enum QSPSortBy { + QSP_SORT_BY_TOTAL_WAIT_TIME, + QSP_SORT_BY_AVG_WAIT_TIME, +}; + +void qsp_report(FILE *f, fprintf_function cpu_fprintf, size_t max, + enum QSPSortBy sort_by, bool callsite_coalesce); + +bool qsp_is_enabled(void); +void qsp_enable(void); +void qsp_disable(void); +void qsp_reset(void); + +#endif /* QEMU_QSP_H */ diff --git a/include/qemu/rcu_queue.h b/include/qemu/rcu_queue.h index 01be77407b..904b3372dc 100644 --- a/include/qemu/rcu_queue.h +++ b/include/qemu/rcu_queue.h @@ -36,7 +36,7 @@ extern "C" { /* * List access methods. */ -#define QLIST_EMPTY_RCU(head) (atomic_rcu_read(&(head)->lh_first) == NULL) +#define QLIST_EMPTY_RCU(head) (atomic_read(&(head)->lh_first) == NULL) #define QLIST_FIRST_RCU(head) (atomic_rcu_read(&(head)->lh_first)) #define QLIST_NEXT_RCU(elm, field) (atomic_rcu_read(&(elm)->field.le_next)) @@ -112,7 +112,7 @@ extern "C" { (elm)->field.le_next->field.le_prev = \ (elm)->field.le_prev; \ } \ - *(elm)->field.le_prev = (elm)->field.le_next; \ + atomic_set((elm)->field.le_prev, (elm)->field.le_next); \ } while (/*CONSTCOND*/0) /* List traversal must occur within an RCU critical section. */ @@ -128,6 +128,137 @@ extern "C" { ((next_var) = atomic_rcu_read(&(var)->field.le_next), 1); \ (var) = (next_var)) +/* + * RCU simple queue + */ + +/* Simple queue access methods */ +#define QSIMPLEQ_EMPTY_RCU(head) (atomic_read(&(head)->sqh_first) == NULL) +#define QSIMPLEQ_FIRST_RCU(head) atomic_rcu_read(&(head)->sqh_first) +#define QSIMPLEQ_NEXT_RCU(elm, field) atomic_rcu_read(&(elm)->field.sqe_next) + +/* Simple queue functions */ +#define QSIMPLEQ_INSERT_HEAD_RCU(head, elm, field) do { \ + (elm)->field.sqe_next = (head)->sqh_first; \ + if ((elm)->field.sqe_next == NULL) { \ + (head)->sqh_last = &(elm)->field.sqe_next; \ + } \ + atomic_rcu_set(&(head)->sqh_first, (elm)); \ +} while (/*CONSTCOND*/0) + +#define QSIMPLEQ_INSERT_TAIL_RCU(head, elm, field) do { \ + (elm)->field.sqe_next = NULL; \ + atomic_rcu_set((head)->sqh_last, (elm)); \ + (head)->sqh_last = &(elm)->field.sqe_next; \ +} while (/*CONSTCOND*/0) + +#define QSIMPLEQ_INSERT_AFTER_RCU(head, listelm, elm, field) do { \ + (elm)->field.sqe_next = (listelm)->field.sqe_next; \ + if ((elm)->field.sqe_next == NULL) { \ + (head)->sqh_last = &(elm)->field.sqe_next; \ + } \ + atomic_rcu_set(&(listelm)->field.sqe_next, (elm)); \ +} while (/*CONSTCOND*/0) + +#define QSIMPLEQ_REMOVE_HEAD_RCU(head, field) do { \ + atomic_set(&(head)->sqh_first, (head)->sqh_first->field.sqe_next); \ + if ((head)->sqh_first == NULL) { \ + (head)->sqh_last = &(head)->sqh_first; \ + } \ +} while (/*CONSTCOND*/0) + +#define QSIMPLEQ_REMOVE_RCU(head, elm, type, field) do { \ + if ((head)->sqh_first == (elm)) { \ + QSIMPLEQ_REMOVE_HEAD_RCU((head), field); \ + } else { \ + struct type *curr = (head)->sqh_first; \ + while (curr->field.sqe_next != (elm)) { \ + curr = curr->field.sqe_next; \ + } \ + atomic_set(&curr->field.sqe_next, \ + curr->field.sqe_next->field.sqe_next); \ + if (curr->field.sqe_next == NULL) { \ + (head)->sqh_last = &(curr)->field.sqe_next; \ + } \ + } \ +} while (/*CONSTCOND*/0) + +#define QSIMPLEQ_FOREACH_RCU(var, head, field) \ + for ((var) = atomic_rcu_read(&(head)->sqh_first); \ + (var); \ + (var) = atomic_rcu_read(&(var)->field.sqe_next)) + +#define QSIMPLEQ_FOREACH_SAFE_RCU(var, head, field, next) \ + for ((var) = atomic_rcu_read(&(head)->sqh_first); \ + (var) && ((next) = atomic_rcu_read(&(var)->field.sqe_next), 1); \ + (var) = (next)) + +/* + * RCU tail queue + */ + +/* Tail queue access methods */ +#define QTAILQ_EMPTY_RCU(head) (atomic_read(&(head)->tqh_first) == NULL) +#define QTAILQ_FIRST_RCU(head) atomic_rcu_read(&(head)->tqh_first) +#define QTAILQ_NEXT_RCU(elm, field) atomic_rcu_read(&(elm)->field.tqe_next) + +/* Tail queue functions */ +#define QTAILQ_INSERT_HEAD_RCU(head, elm, field) do { \ + (elm)->field.tqe_next = (head)->tqh_first; \ + if ((elm)->field.tqe_next != NULL) { \ + (head)->tqh_first->field.tqe_prev = &(elm)->field.tqe_next; \ + } else { \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + } \ + atomic_rcu_set(&(head)->tqh_first, (elm)); \ + (elm)->field.tqe_prev = &(head)->tqh_first; \ +} while (/*CONSTCOND*/0) + +#define QTAILQ_INSERT_TAIL_RCU(head, elm, field) do { \ + (elm)->field.tqe_next = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + atomic_rcu_set((head)->tqh_last, (elm)); \ + (head)->tqh_last = &(elm)->field.tqe_next; \ +} while (/*CONSTCOND*/0) + +#define QTAILQ_INSERT_AFTER_RCU(head, listelm, elm, field) do { \ + (elm)->field.tqe_next = (listelm)->field.tqe_next; \ + if ((elm)->field.tqe_next != NULL) { \ + (elm)->field.tqe_next->field.tqe_prev = &(elm)->field.tqe_next; \ + } else { \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + } \ + atomic_rcu_set(&(listelm)->field.tqe_next, (elm)); \ + (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ +} while (/*CONSTCOND*/0) + +#define QTAILQ_INSERT_BEFORE_RCU(listelm, elm, field) do { \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + (elm)->field.tqe_next = (listelm); \ + atomic_rcu_set((listelm)->field.tqe_prev, (elm)); \ + (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ + } while (/*CONSTCOND*/0) + +#define QTAILQ_REMOVE_RCU(head, elm, field) do { \ + if (((elm)->field.tqe_next) != NULL) { \ + (elm)->field.tqe_next->field.tqe_prev = (elm)->field.tqe_prev; \ + } else { \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + } \ + atomic_set((elm)->field.tqe_prev, (elm)->field.tqe_next); \ + (elm)->field.tqe_prev = NULL; \ +} while (/*CONSTCOND*/0) + +#define QTAILQ_FOREACH_RCU(var, head, field) \ + for ((var) = atomic_rcu_read(&(head)->tqh_first); \ + (var); \ + (var) = atomic_rcu_read(&(var)->field.tqe_next)) + +#define QTAILQ_FOREACH_SAFE_RCU(var, head, field, next) \ + for ((var) = atomic_rcu_read(&(head)->tqh_first); \ + (var) && ((next) = atomic_rcu_read(&(var)->field.tqe_next), 1); \ + (var) = (next)) + #ifdef __cplusplus } #endif diff --git a/include/qemu/seqlock.h b/include/qemu/seqlock.h index 8dee11d101..fd408b7ec5 100644 --- a/include/qemu/seqlock.h +++ b/include/qemu/seqlock.h @@ -16,6 +16,7 @@ #include "qemu/atomic.h" #include "qemu/thread.h" +#include "qemu/lockable.h" typedef struct QemuSeqLock QemuSeqLock; @@ -45,7 +46,26 @@ static inline void seqlock_write_end(QemuSeqLock *sl) atomic_set(&sl->sequence, sl->sequence + 1); } -static inline unsigned seqlock_read_begin(QemuSeqLock *sl) +/* Lock out other writers and update the count. */ +static inline void seqlock_write_lock_impl(QemuSeqLock *sl, QemuLockable *lock) +{ + qemu_lockable_lock(lock); + seqlock_write_begin(sl); +} +#define seqlock_write_lock(sl, lock) \ + seqlock_write_lock_impl(sl, QEMU_MAKE_LOCKABLE(lock)) + +/* Lock out other writers and update the count. */ +static inline void seqlock_write_unlock_impl(QemuSeqLock *sl, QemuLockable *lock) +{ + qemu_lockable_unlock(lock); + seqlock_write_begin(sl); +} +#define seqlock_write_unlock(sl, lock) \ + seqlock_write_unlock_impl(sl, QEMU_MAKE_LOCKABLE(lock)) + + +static inline unsigned seqlock_read_begin(const QemuSeqLock *sl) { /* Always fail if a write is in progress. */ unsigned ret = atomic_read(&sl->sequence); diff --git a/include/qemu/thread-posix.h b/include/qemu/thread-posix.h index fd27b34128..c903525062 100644 --- a/include/qemu/thread-posix.h +++ b/include/qemu/thread-posix.h @@ -6,8 +6,8 @@ typedef QemuMutex QemuRecMutex; #define qemu_rec_mutex_destroy qemu_mutex_destroy -#define qemu_rec_mutex_lock qemu_mutex_lock -#define qemu_rec_mutex_trylock qemu_mutex_trylock +#define qemu_rec_mutex_lock_impl qemu_mutex_lock_impl +#define qemu_rec_mutex_trylock_impl qemu_mutex_trylock_impl #define qemu_rec_mutex_unlock qemu_mutex_unlock struct QemuMutex { diff --git a/include/qemu/thread-win32.h b/include/qemu/thread-win32.h index d668d789b4..50af5dd7ab 100644 --- a/include/qemu/thread-win32.h +++ b/include/qemu/thread-win32.h @@ -19,8 +19,9 @@ struct QemuRecMutex { }; void qemu_rec_mutex_destroy(QemuRecMutex *mutex); -void qemu_rec_mutex_lock(QemuRecMutex *mutex); -int qemu_rec_mutex_trylock(QemuRecMutex *mutex); +void qemu_rec_mutex_lock_impl(QemuRecMutex *mutex, const char *file, int line); +int qemu_rec_mutex_trylock_impl(QemuRecMutex *mutex, const char *file, + int line); void qemu_rec_mutex_unlock(QemuRecMutex *mutex); struct QemuCond { diff --git a/include/qemu/thread.h b/include/qemu/thread.h index ef7bd16123..dacebcfff0 100644 --- a/include/qemu/thread.h +++ b/include/qemu/thread.h @@ -16,6 +16,9 @@ typedef struct QemuThread QemuThread; #include "qemu/thread-posix.h" #endif +/* include QSP header once QemuMutex, QemuCond etc. are defined */ +#include "qemu/qsp.h" + #define QEMU_THREAD_JOINABLE 0 #define QEMU_THREAD_DETACHED 1 @@ -25,10 +28,52 @@ int qemu_mutex_trylock_impl(QemuMutex *mutex, const char *file, const int line); void qemu_mutex_lock_impl(QemuMutex *mutex, const char *file, const int line); void qemu_mutex_unlock_impl(QemuMutex *mutex, const char *file, const int line); -#define qemu_mutex_lock(mutex) \ - qemu_mutex_lock_impl(mutex, __FILE__, __LINE__) -#define qemu_mutex_trylock(mutex) \ - qemu_mutex_trylock_impl(mutex, __FILE__, __LINE__) +typedef void (*QemuMutexLockFunc)(QemuMutex *m, const char *f, int l); +typedef int (*QemuMutexTrylockFunc)(QemuMutex *m, const char *f, int l); +typedef void (*QemuRecMutexLockFunc)(QemuRecMutex *m, const char *f, int l); +typedef int (*QemuRecMutexTrylockFunc)(QemuRecMutex *m, const char *f, int l); +typedef void (*QemuCondWaitFunc)(QemuCond *c, QemuMutex *m, const char *f, + int l); + +extern QemuMutexLockFunc qemu_bql_mutex_lock_func; +extern QemuMutexLockFunc qemu_mutex_lock_func; +extern QemuMutexTrylockFunc qemu_mutex_trylock_func; +extern QemuRecMutexLockFunc qemu_rec_mutex_lock_func; +extern QemuRecMutexTrylockFunc qemu_rec_mutex_trylock_func; +extern QemuCondWaitFunc qemu_cond_wait_func; + +/* convenience macros to bypass the profiler */ +#define qemu_mutex_lock__raw(m) \ + qemu_mutex_lock_impl(m, __FILE__, __LINE__) +#define qemu_mutex_trylock__raw(m) \ + qemu_mutex_trylock_impl(m, __FILE__, __LINE__) + +#define qemu_mutex_lock(m) ({ \ + QemuMutexLockFunc _f = atomic_read(&qemu_mutex_lock_func); \ + _f(m, __FILE__, __LINE__); \ + }) + +#define qemu_mutex_trylock(m) ({ \ + QemuMutexTrylockFunc _f = atomic_read(&qemu_mutex_trylock_func); \ + _f(m, __FILE__, __LINE__); \ + }) + +#define qemu_rec_mutex_lock(m) ({ \ + QemuRecMutexLockFunc _f = atomic_read(&qemu_rec_mutex_lock_func); \ + _f(m, __FILE__, __LINE__); \ + }) + +#define qemu_rec_mutex_trylock(m) ({ \ + QemuRecMutexTrylockFunc _f; \ + _f = atomic_read(&qemu_rec_mutex_trylock_func); \ + _f(m, __FILE__, __LINE__); \ + }) + +#define qemu_cond_wait(c, m) ({ \ + QemuCondWaitFunc _f = atomic_read(&qemu_cond_wait_func); \ + _f(c, m, __FILE__, __LINE__); \ + }) + #define qemu_mutex_unlock(mutex) \ qemu_mutex_unlock_impl(mutex, __FILE__, __LINE__) @@ -47,6 +92,16 @@ static inline void (qemu_mutex_unlock)(QemuMutex *mutex) qemu_mutex_unlock(mutex); } +static inline void (qemu_rec_mutex_lock)(QemuRecMutex *mutex) +{ + qemu_rec_mutex_lock(mutex); +} + +static inline int (qemu_rec_mutex_trylock)(QemuRecMutex *mutex) +{ + return qemu_rec_mutex_trylock(mutex); +} + /* Prototypes for other functions are in thread-posix.h/thread-win32.h. */ void qemu_rec_mutex_init(QemuRecMutex *mutex); @@ -63,9 +118,6 @@ void qemu_cond_broadcast(QemuCond *cond); void qemu_cond_wait_impl(QemuCond *cond, QemuMutex *mutex, const char *file, const int line); -#define qemu_cond_wait(cond, mutex) \ - qemu_cond_wait_impl(cond, mutex, __FILE__, __LINE__) - static inline void (qemu_cond_wait)(QemuCond *cond, QemuMutex *mutex) { qemu_cond_wait(cond, mutex); diff --git a/include/qom/cpu.h b/include/qom/cpu.h index ecf6ed556a..dc130cd307 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -26,6 +26,7 @@ #include "exec/memattrs.h" #include "qapi/qapi-types-run-state.h" #include "qemu/bitmap.h" +#include "qemu/rcu_queue.h" #include "qemu/queue.h" #include "qemu/thread.h" @@ -442,13 +443,11 @@ struct CPUState { QTAILQ_HEAD(CPUTailQ, CPUState); extern struct CPUTailQ cpus; -#define CPU_NEXT(cpu) QTAILQ_NEXT(cpu, node) -#define CPU_FOREACH(cpu) QTAILQ_FOREACH(cpu, &cpus, node) +#define first_cpu QTAILQ_FIRST_RCU(&cpus) +#define CPU_NEXT(cpu) QTAILQ_NEXT_RCU(cpu, node) +#define CPU_FOREACH(cpu) QTAILQ_FOREACH_RCU(cpu, &cpus, node) #define CPU_FOREACH_SAFE(cpu, next_cpu) \ - QTAILQ_FOREACH_SAFE(cpu, &cpus, node, next_cpu) -#define CPU_FOREACH_REVERSE(cpu) \ - QTAILQ_FOREACH_REVERSE(cpu, &cpus, CPUTailQ, node) -#define first_cpu QTAILQ_FIRST(&cpus) + QTAILQ_FOREACH_SAFE_RCU(cpu, &cpus, node, next_cpu) extern __thread CPUState *current_cpu; diff --git a/include/standard-headers/linux/qemu_fw_cfg.h b/include/standard-headers/linux/qemu_fw_cfg.h new file mode 100644 index 0000000000..cb93f6678d --- /dev/null +++ b/include/standard-headers/linux/qemu_fw_cfg.h @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +#ifndef _LINUX_FW_CFG_H +#define _LINUX_FW_CFG_H + +#include "standard-headers/linux/types.h" + +#define FW_CFG_ACPI_DEVICE_ID "QEMU0002" + +/* selector key values for "well-known" fw_cfg entries */ +#define FW_CFG_SIGNATURE 0x00 +#define FW_CFG_ID 0x01 +#define FW_CFG_UUID 0x02 +#define FW_CFG_RAM_SIZE 0x03 +#define FW_CFG_NOGRAPHIC 0x04 +#define FW_CFG_NB_CPUS 0x05 +#define FW_CFG_MACHINE_ID 0x06 +#define FW_CFG_KERNEL_ADDR 0x07 +#define FW_CFG_KERNEL_SIZE 0x08 +#define FW_CFG_KERNEL_CMDLINE 0x09 +#define FW_CFG_INITRD_ADDR 0x0a +#define FW_CFG_INITRD_SIZE 0x0b +#define FW_CFG_BOOT_DEVICE 0x0c +#define FW_CFG_NUMA 0x0d +#define FW_CFG_BOOT_MENU 0x0e +#define FW_CFG_MAX_CPUS 0x0f +#define FW_CFG_KERNEL_ENTRY 0x10 +#define FW_CFG_KERNEL_DATA 0x11 +#define FW_CFG_INITRD_DATA 0x12 +#define FW_CFG_CMDLINE_ADDR 0x13 +#define FW_CFG_CMDLINE_SIZE 0x14 +#define FW_CFG_CMDLINE_DATA 0x15 +#define FW_CFG_SETUP_ADDR 0x16 +#define FW_CFG_SETUP_SIZE 0x17 +#define FW_CFG_SETUP_DATA 0x18 +#define FW_CFG_FILE_DIR 0x19 + +#define FW_CFG_FILE_FIRST 0x20 +#define FW_CFG_FILE_SLOTS_MIN 0x10 + +#define FW_CFG_WRITE_CHANNEL 0x4000 +#define FW_CFG_ARCH_LOCAL 0x8000 +#define FW_CFG_ENTRY_MASK (~(FW_CFG_WRITE_CHANNEL | FW_CFG_ARCH_LOCAL)) + +#define FW_CFG_INVALID 0xffff + +/* width in bytes of fw_cfg control register */ +#define FW_CFG_CTL_SIZE 0x02 + +/* fw_cfg "file name" is up to 56 characters (including terminating nul) */ +#define FW_CFG_MAX_FILE_PATH 56 + +/* size in bytes of fw_cfg signature */ +#define FW_CFG_SIG_SIZE 4 + +/* FW_CFG_ID bits */ +#define FW_CFG_VERSION 0x01 +#define FW_CFG_VERSION_DMA 0x02 + +/* fw_cfg file directory entry type */ +struct fw_cfg_file { + uint32_t size; + uint16_t select; + uint16_t reserved; + char name[FW_CFG_MAX_FILE_PATH]; +}; + +/* FW_CFG_DMA_CONTROL bits */ +#define FW_CFG_DMA_CTL_ERROR 0x01 +#define FW_CFG_DMA_CTL_READ 0x02 +#define FW_CFG_DMA_CTL_SKIP 0x04 +#define FW_CFG_DMA_CTL_SELECT 0x08 +#define FW_CFG_DMA_CTL_WRITE 0x10 + +#define FW_CFG_DMA_SIGNATURE 0x51454d5520434647ULL /* "QEMU CFG" */ + +/* Control as first field allows for different structures selected by this + * field, which might be useful in the future + */ +struct fw_cfg_dma_access { + uint32_t control; + uint32_t length; + uint64_t address; +}; + +#define FW_CFG_VMCOREINFO_FILENAME "etc/vmcoreinfo" + +#define FW_CFG_VMCOREINFO_FORMAT_NONE 0x0 +#define FW_CFG_VMCOREINFO_FORMAT_ELF 0x1 + +struct fw_cfg_vmcoreinfo { + uint16_t host_format; + uint16_t guest_format; + uint32_t size; + uint64_t paddr; +}; + +#endif |