Compare commits
30 Commits
qemu-2.3.0
...
qemu-2.3.0
Author | SHA1 | Date | |
---|---|---|---|
|
f2a581010c | ||
|
e05ca82002 | ||
|
638b836620 | ||
|
87a8adc087 | ||
|
b6df74c465 | ||
|
0ca4f94195 | ||
|
993ebe4a0b | ||
|
6cec43e178 | ||
|
b8df9208f3 | ||
|
ae6e8ef11e | ||
|
4d0ecde44a | ||
|
342b0711cd | ||
|
c0c8584142 | ||
|
58c24a4775 | ||
|
b7ccb83f44 | ||
|
81b23ef82c | ||
|
6a460ed18a | ||
|
a6f2cb037a | ||
|
cf811fff2a | ||
|
05b685fbab | ||
|
e8d3b1a25f | ||
|
c8623c0215 | ||
|
2a6cdd6d35 | ||
|
e4603fe139 | ||
|
5a24f20a72 | ||
|
9be6e69f12 | ||
|
085feb61db | ||
|
7b4b0b5795 | ||
|
9c04146ad4 | ||
|
ecf2e5a46d |
10
.gitignore
vendored
10
.gitignore
vendored
@@ -37,14 +37,8 @@
|
||||
/qemu-tech.html
|
||||
/qemu-doc.info
|
||||
/qemu-tech.info
|
||||
/qemu.1
|
||||
/qemu.pod
|
||||
/qemu-img.1
|
||||
/qemu-img.pod
|
||||
/qemu-img
|
||||
/qemu-nbd
|
||||
/qemu-nbd.8
|
||||
/qemu-nbd.pod
|
||||
/qemu-options.def
|
||||
/qemu-options.texi
|
||||
/qemu-img-cmds.texi
|
||||
@@ -56,8 +50,7 @@
|
||||
/qmp-commands.txt
|
||||
/vscclient
|
||||
/fsdev/virtfs-proxy-helper
|
||||
/fsdev/virtfs-proxy-helper.1
|
||||
/fsdev/virtfs-proxy-helper.pod
|
||||
*.[1-9]
|
||||
*.a
|
||||
*.aux
|
||||
*.cp
|
||||
@@ -70,6 +63,7 @@
|
||||
*.ky
|
||||
*.log
|
||||
*.pdf
|
||||
*.pod
|
||||
*.cps
|
||||
*.fns
|
||||
*.kys
|
||||
|
28
async.c
28
async.c
@@ -72,12 +72,13 @@ int aio_bh_poll(AioContext *ctx)
|
||||
/* Make sure that fetching bh happens before accessing its members */
|
||||
smp_read_barrier_depends();
|
||||
next = bh->next;
|
||||
if (!bh->deleted && bh->scheduled) {
|
||||
bh->scheduled = 0;
|
||||
/* Paired with write barrier in bh schedule to ensure reading for
|
||||
* idle & callbacks coming after bh's scheduling.
|
||||
*/
|
||||
smp_rmb();
|
||||
/* The atomic_xchg is paired with the one in qemu_bh_schedule. The
|
||||
* implicit memory barrier ensures that the callback sees all writes
|
||||
* done by the scheduling thread. It also ensures that the scheduling
|
||||
* thread sees the zero before bh->cb has run, and thus will call
|
||||
* aio_notify again if necessary.
|
||||
*/
|
||||
if (!bh->deleted && atomic_xchg(&bh->scheduled, 0)) {
|
||||
if (!bh->idle)
|
||||
ret = 1;
|
||||
bh->idle = 0;
|
||||
@@ -108,33 +109,28 @@ int aio_bh_poll(AioContext *ctx)
|
||||
|
||||
void qemu_bh_schedule_idle(QEMUBH *bh)
|
||||
{
|
||||
if (bh->scheduled)
|
||||
return;
|
||||
bh->idle = 1;
|
||||
/* Make sure that idle & any writes needed by the callback are done
|
||||
* before the locations are read in the aio_bh_poll.
|
||||
*/
|
||||
smp_wmb();
|
||||
bh->scheduled = 1;
|
||||
atomic_mb_set(&bh->scheduled, 1);
|
||||
}
|
||||
|
||||
void qemu_bh_schedule(QEMUBH *bh)
|
||||
{
|
||||
AioContext *ctx;
|
||||
|
||||
if (bh->scheduled)
|
||||
return;
|
||||
ctx = bh->ctx;
|
||||
bh->idle = 0;
|
||||
/* Make sure that:
|
||||
/* The memory barrier implicit in atomic_xchg makes sure that:
|
||||
* 1. idle & any writes needed by the callback are done before the
|
||||
* locations are read in the aio_bh_poll.
|
||||
* 2. ctx is loaded before scheduled is set and the callback has a chance
|
||||
* to execute.
|
||||
*/
|
||||
smp_mb();
|
||||
bh->scheduled = 1;
|
||||
aio_notify(ctx);
|
||||
if (atomic_xchg(&bh->scheduled, 1) == 0) {
|
||||
aio_notify(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -56,6 +56,7 @@ typedef struct IscsiLun {
|
||||
uint64_t num_blocks;
|
||||
int events;
|
||||
QEMUTimer *nop_timer;
|
||||
QEMUTimer *event_timer;
|
||||
uint8_t lbpme;
|
||||
uint8_t lbprz;
|
||||
uint8_t has_write_same;
|
||||
@@ -95,6 +96,7 @@ typedef struct IscsiAIOCB {
|
||||
#endif
|
||||
} IscsiAIOCB;
|
||||
|
||||
#define EVENT_INTERVAL 250
|
||||
#define NOP_INTERVAL 5000
|
||||
#define MAX_NOP_FAILURES 3
|
||||
#define ISCSI_CMD_RETRIES ARRAY_SIZE(iscsi_retry_times)
|
||||
@@ -256,21 +258,30 @@ static void
|
||||
iscsi_set_events(IscsiLun *iscsilun)
|
||||
{
|
||||
struct iscsi_context *iscsi = iscsilun->iscsi;
|
||||
int ev;
|
||||
int ev = iscsi_which_events(iscsi);
|
||||
|
||||
/* We always register a read handler. */
|
||||
ev = POLLIN;
|
||||
ev |= iscsi_which_events(iscsi);
|
||||
if (ev != iscsilun->events) {
|
||||
aio_set_fd_handler(iscsilun->aio_context,
|
||||
iscsi_get_fd(iscsi),
|
||||
iscsi_process_read,
|
||||
(ev & POLLIN) ? iscsi_process_read : NULL,
|
||||
(ev & POLLOUT) ? iscsi_process_write : NULL,
|
||||
iscsilun);
|
||||
|
||||
iscsilun->events = ev;
|
||||
}
|
||||
|
||||
iscsilun->events = ev;
|
||||
/* newer versions of libiscsi may return zero events. In this
|
||||
* case start a timer to ensure we are able to return to service
|
||||
* once this situation changes. */
|
||||
if (!ev) {
|
||||
timer_mod(iscsilun->event_timer,
|
||||
qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + EVENT_INTERVAL);
|
||||
}
|
||||
}
|
||||
|
||||
static void iscsi_timed_set_events(void *opaque)
|
||||
{
|
||||
IscsiLun *iscsilun = opaque;
|
||||
iscsi_set_events(iscsilun);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1214,6 +1225,11 @@ static void iscsi_detach_aio_context(BlockDriverState *bs)
|
||||
timer_free(iscsilun->nop_timer);
|
||||
iscsilun->nop_timer = NULL;
|
||||
}
|
||||
if (iscsilun->event_timer) {
|
||||
timer_del(iscsilun->event_timer);
|
||||
timer_free(iscsilun->event_timer);
|
||||
iscsilun->event_timer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void iscsi_attach_aio_context(BlockDriverState *bs,
|
||||
@@ -1230,6 +1246,11 @@ static void iscsi_attach_aio_context(BlockDriverState *bs,
|
||||
iscsi_nop_timed_event, iscsilun);
|
||||
timer_mod(iscsilun->nop_timer,
|
||||
qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + NOP_INTERVAL);
|
||||
|
||||
/* Prepare a timer for a delayed call to iscsi_set_events */
|
||||
iscsilun->event_timer = aio_timer_new(iscsilun->aio_context,
|
||||
QEMU_CLOCK_REALTIME, SCALE_MS,
|
||||
iscsi_timed_set_events, iscsilun);
|
||||
}
|
||||
|
||||
static bool iscsi_is_write_protected(IscsiLun *iscsilun)
|
||||
|
@@ -140,6 +140,7 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
|
||||
return 3;
|
||||
}
|
||||
bs->backing_format[ext.len] = '\0';
|
||||
s->image_backing_format = g_strdup(bs->backing_format);
|
||||
#ifdef DEBUG_EXT
|
||||
printf("Qcow2: Got format extension %s\n", bs->backing_format);
|
||||
#endif
|
||||
@@ -884,6 +885,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
goto fail;
|
||||
}
|
||||
bs->backing_file[len] = '\0';
|
||||
s->image_backing_file = g_strdup(bs->backing_file);
|
||||
}
|
||||
|
||||
/* Internal snapshots */
|
||||
@@ -1457,6 +1459,9 @@ static void qcow2_close(BlockDriverState *bs)
|
||||
g_free(s->unknown_header_fields);
|
||||
cleanup_unknown_header_ext(bs);
|
||||
|
||||
g_free(s->image_backing_file);
|
||||
g_free(s->image_backing_format);
|
||||
|
||||
g_free(s->cluster_cache);
|
||||
qemu_vfree(s->cluster_data);
|
||||
qcow2_refcount_close(bs);
|
||||
@@ -1622,9 +1627,10 @@ int qcow2_update_header(BlockDriverState *bs)
|
||||
}
|
||||
|
||||
/* Backing file format header extension */
|
||||
if (*bs->backing_format) {
|
||||
if (s->image_backing_format) {
|
||||
ret = header_ext_add(buf, QCOW2_EXT_MAGIC_BACKING_FORMAT,
|
||||
bs->backing_format, strlen(bs->backing_format),
|
||||
s->image_backing_format,
|
||||
strlen(s->image_backing_format),
|
||||
buflen);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
@@ -1682,8 +1688,8 @@ int qcow2_update_header(BlockDriverState *bs)
|
||||
buflen -= ret;
|
||||
|
||||
/* Backing file name */
|
||||
if (*bs->backing_file) {
|
||||
size_t backing_file_len = strlen(bs->backing_file);
|
||||
if (s->image_backing_file) {
|
||||
size_t backing_file_len = strlen(s->image_backing_file);
|
||||
|
||||
if (buflen < backing_file_len) {
|
||||
ret = -ENOSPC;
|
||||
@@ -1691,7 +1697,7 @@ int qcow2_update_header(BlockDriverState *bs)
|
||||
}
|
||||
|
||||
/* Using strncpy is ok here, since buf is not NUL-terminated. */
|
||||
strncpy(buf, bs->backing_file, buflen);
|
||||
strncpy(buf, s->image_backing_file, buflen);
|
||||
|
||||
header->backing_file_offset = cpu_to_be64(buf - ((char*) header));
|
||||
header->backing_file_size = cpu_to_be32(backing_file_len);
|
||||
@@ -1712,9 +1718,17 @@ fail:
|
||||
static int qcow2_change_backing_file(BlockDriverState *bs,
|
||||
const char *backing_file, const char *backing_fmt)
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
|
||||
pstrcpy(bs->backing_file, sizeof(bs->backing_file), backing_file ?: "");
|
||||
pstrcpy(bs->backing_format, sizeof(bs->backing_format), backing_fmt ?: "");
|
||||
|
||||
g_free(s->image_backing_file);
|
||||
g_free(s->image_backing_format);
|
||||
|
||||
s->image_backing_file = backing_file ? g_strdup(bs->backing_file) : NULL;
|
||||
s->image_backing_format = backing_fmt ? g_strdup(bs->backing_format) : NULL;
|
||||
|
||||
return qcow2_update_header(bs);
|
||||
}
|
||||
|
||||
@@ -2751,8 +2765,9 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
||||
}
|
||||
|
||||
if (backing_file || backing_format) {
|
||||
ret = qcow2_change_backing_file(bs, backing_file ?: bs->backing_file,
|
||||
backing_format ?: bs->backing_format);
|
||||
ret = qcow2_change_backing_file(bs,
|
||||
backing_file ?: s->image_backing_file,
|
||||
backing_format ?: s->image_backing_format);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@@ -283,6 +283,12 @@ typedef struct BDRVQcowState {
|
||||
QLIST_HEAD(, Qcow2UnknownHeaderExtension) unknown_header_ext;
|
||||
QTAILQ_HEAD (, Qcow2DiscardRegion) discards;
|
||||
bool cache_discards;
|
||||
|
||||
/* Backing file path and format as stored in the image (this is not the
|
||||
* effective path/format, which may be the result of a runtime option
|
||||
* override) */
|
||||
char *image_backing_file;
|
||||
char *image_backing_format;
|
||||
} BDRVQcowState;
|
||||
|
||||
struct QCowAIOCB;
|
||||
|
17
configure
vendored
17
configure
vendored
@@ -327,7 +327,7 @@ seccomp=""
|
||||
glusterfs=""
|
||||
glusterfs_discard="no"
|
||||
glusterfs_zerofill="no"
|
||||
archipelago=""
|
||||
archipelago="no"
|
||||
gtk=""
|
||||
gtkabi=""
|
||||
vte=""
|
||||
@@ -1848,19 +1848,14 @@ fi
|
||||
# libseccomp check
|
||||
|
||||
if test "$seccomp" != "no" ; then
|
||||
if $pkg_config --atleast-version=2.2.0 libseccomp ||
|
||||
(test "$cpu" = "i386" || test "$cpu" = "x86_64" &&
|
||||
$pkg_config --atleast-version=2.1.1 libseccomp); then
|
||||
if test "$cpu" = "i386" || test "$cpu" = "x86_64" &&
|
||||
$pkg_config --atleast-version=2.1.1 libseccomp; then
|
||||
libs_softmmu="$libs_softmmu `$pkg_config --libs libseccomp`"
|
||||
QEMU_CFLAGS="$QEMU_CFLAGS `$pkg_config --cflags libseccomp`"
|
||||
seccomp="yes"
|
||||
else
|
||||
if test "$seccomp" = "yes"; then
|
||||
if test "$cpu" = "i386" || test "$cpu" = "x86_64"; then
|
||||
feature_not_found "libseccomp" "Install libseccomp devel >= 2.1.1"
|
||||
else
|
||||
feature_not_found "libseccomp" "Install libseccomp devel >= 2.2.0"
|
||||
fi
|
||||
fi
|
||||
seccomp="no"
|
||||
fi
|
||||
@@ -3173,6 +3168,12 @@ EOF
|
||||
archipelago="yes"
|
||||
libs_tools="$archipelago_libs $libs_tools"
|
||||
libs_softmmu="$archipelago_libs $libs_softmmu"
|
||||
|
||||
echo "WARNING: Please check the licenses of QEMU and libxseg carefully."
|
||||
echo "GPLv3 versions of libxseg may not be compatible with QEMU's"
|
||||
echo "license and therefore prevent redistribution."
|
||||
echo
|
||||
echo "To disable Archipelago, use --disable-archipelago"
|
||||
else
|
||||
if test "$archipelago" = "yes" ; then
|
||||
feature_not_found "Archipelago backend support" "Install libxseg devel"
|
||||
|
205
docs/specs/fw_cfg.txt
Normal file
205
docs/specs/fw_cfg.txt
Normal file
@@ -0,0 +1,205 @@
|
||||
QEMU Firmware Configuration (fw_cfg) Device
|
||||
===========================================
|
||||
|
||||
= Guest-side Hardware Interface =
|
||||
|
||||
This hardware interface allows the guest to retrieve various data items
|
||||
(blobs) that can influence how the firmware configures itself, or may
|
||||
contain tables to be installed for the guest OS. Examples include device
|
||||
boot order, ACPI and SMBIOS tables, virtual machine UUID, SMP and NUMA
|
||||
information, kernel/initrd images for direct (Linux) kernel booting, etc.
|
||||
|
||||
== Selector (Control) Register ==
|
||||
|
||||
* Write only
|
||||
* Location: platform dependent (IOport or MMIO)
|
||||
* Width: 16-bit
|
||||
* Endianness: little-endian (if IOport), or big-endian (if MMIO)
|
||||
|
||||
A write to this register sets the index of a firmware configuration
|
||||
item which can subsequently be accessed via the data register.
|
||||
|
||||
Setting the selector register will cause the data offset to be set
|
||||
to zero. The data offset impacts which data is accessed via the data
|
||||
register, and is explained below.
|
||||
|
||||
Bit14 of the selector register indicates whether the configuration
|
||||
setting is being written. A value of 0 means the item is only being
|
||||
read, and all write access to the data port will be ignored. A value
|
||||
of 1 means the item's data can be overwritten by writes to the data
|
||||
register. In other words, configuration write mode is enabled when
|
||||
the selector value is between 0x4000-0x7fff or 0xc000-0xffff.
|
||||
|
||||
NOTE: As of QEMU v2.4, writes to the fw_cfg data register are no
|
||||
longer supported, and will be ignored (treated as no-ops)!
|
||||
|
||||
Bit15 of the selector register indicates whether the configuration
|
||||
setting is architecture specific. A value of 0 means the item is a
|
||||
generic configuration item. A value of 1 means the item is specific
|
||||
to a particular architecture. In other words, generic configuration
|
||||
items are accessed with a selector value between 0x0000-0x7fff, and
|
||||
architecture specific configuration items are accessed with a selector
|
||||
value between 0x8000-0xffff.
|
||||
|
||||
== Data Register ==
|
||||
|
||||
* Read/Write (writes ignored as of QEMU v2.4)
|
||||
* Location: platform dependent (IOport [*] or MMIO)
|
||||
* Width: 8-bit (if IOport), 8/16/32/64-bit (if MMIO)
|
||||
* Endianness: string-preserving
|
||||
|
||||
[*] On platforms where the data register is exposed as an IOport, its
|
||||
port number will always be one greater than the port number of the
|
||||
selector register. In other words, the two ports overlap, and can not
|
||||
be mapped separately.
|
||||
|
||||
The data register allows access to an array of bytes for each firmware
|
||||
configuration data item. The specific item is selected by writing to
|
||||
the selector register, as described above.
|
||||
|
||||
Initially following a write to the selector register, the data offset
|
||||
will be set to zero. Each successful access to the data register will
|
||||
increment the data offset by the appropriate access width.
|
||||
|
||||
Each firmware configuration item has a maximum length of data
|
||||
associated with the item. After the data offset has passed the
|
||||
end of this maximum data length, then any reads will return a data
|
||||
value of 0x00, and all writes will be ignored.
|
||||
|
||||
An N-byte wide read of the data register will return the next available
|
||||
N bytes of the selected firmware configuration item, as a substring, in
|
||||
increasing address order, similar to memcpy().
|
||||
|
||||
== Register Locations ==
|
||||
|
||||
=== x86, x86_64 Register Locations ===
|
||||
|
||||
Selector Register IOport: 0x510
|
||||
Data Register IOport: 0x511
|
||||
|
||||
== Firmware Configuration Items ==
|
||||
|
||||
=== Signature (Key 0x0000, FW_CFG_SIGNATURE) ===
|
||||
|
||||
The presence of the fw_cfg selector and data registers can be verified
|
||||
by selecting the "signature" item using key 0x0000 (FW_CFG_SIGNATURE),
|
||||
and reading four bytes from the data register. If the fw_cfg device is
|
||||
present, the four bytes read will contain the characters "QEMU".
|
||||
|
||||
=== Revision (Key 0x0001, FW_CFG_ID) ===
|
||||
|
||||
A 32-bit little-endian unsigned int, this item is used as an interface
|
||||
revision number, and is currently set to 1 by QEMU when fw_cfg is
|
||||
initialized.
|
||||
|
||||
=== File Directory (Key 0x0019, FW_CFG_FILE_DIR) ===
|
||||
|
||||
Firmware configuration items stored at selector keys 0x0020 or higher
|
||||
(FW_CFG_FILE_FIRST or higher) have an associated entry in a directory
|
||||
structure, which makes it easier for guest-side firmware to identify
|
||||
and retrieve them. The format of this file directory (from fw_cfg.h in
|
||||
the QEMU source tree) is shown here, slightly annotated for clarity:
|
||||
|
||||
struct FWCfgFiles { /* the entire file directory fw_cfg item */
|
||||
uint32_t count; /* number of entries, in big-endian format */
|
||||
struct FWCfgFile f[]; /* array of file entries, see below */
|
||||
};
|
||||
|
||||
struct FWCfgFile { /* an individual file entry, 64 bytes total */
|
||||
uint32_t size; /* size of referenced fw_cfg item, big-endian */
|
||||
uint16_t select; /* selector key of fw_cfg item, big-endian */
|
||||
uint16_t reserved;
|
||||
char name[56]; /* fw_cfg item name, NUL-terminated ascii */
|
||||
};
|
||||
|
||||
=== All Other Data Items ===
|
||||
|
||||
Please consult the QEMU source for the most up-to-date and authoritative
|
||||
list of selector keys and their respective items' purpose and format.
|
||||
|
||||
=== Ranges ===
|
||||
|
||||
Theoretically, there may be up to 0x4000 generic firmware configuration
|
||||
items, and up to 0x4000 architecturally specific ones.
|
||||
|
||||
Selector Reg. Range Usage
|
||||
--------------- -----------
|
||||
0x0000 - 0x3fff Generic (0x0000 - 0x3fff, RO)
|
||||
0x4000 - 0x7fff Generic (0x0000 - 0x3fff, RW, ignored in QEMU v2.4+)
|
||||
0x8000 - 0xbfff Arch. Specific (0x0000 - 0x3fff, RO)
|
||||
0xc000 - 0xffff Arch. Specific (0x0000 - 0x3fff, RW, ignored in v2.4+)
|
||||
|
||||
In practice, the number of allowed firmware configuration items is given
|
||||
by the value of FW_CFG_MAX_ENTRY (see fw_cfg.h).
|
||||
|
||||
= Host-side API =
|
||||
|
||||
The following functions are available to the QEMU programmer for adding
|
||||
data to a fw_cfg device during guest initialization (see fw_cfg.h for
|
||||
each function's complete prototype):
|
||||
|
||||
== fw_cfg_add_bytes() ==
|
||||
|
||||
Given a selector key value, starting pointer, and size, create an item
|
||||
as a raw "blob" of the given size, available by selecting the given key.
|
||||
The data referenced by the starting pointer is only linked, NOT copied,
|
||||
into the data structure of the fw_cfg device.
|
||||
|
||||
== fw_cfg_add_string() ==
|
||||
|
||||
Instead of a starting pointer and size, this function accepts a pointer
|
||||
to a NUL-terminated ascii string, and inserts a newly allocated copy of
|
||||
the string (including the NUL terminator) into the fw_cfg device data
|
||||
structure.
|
||||
|
||||
== fw_cfg_add_iXX() ==
|
||||
|
||||
Insert an XX-bit item, where XX may be 16, 32, or 64. These functions
|
||||
will convert a 16-, 32-, or 64-bit integer to little-endian, then add
|
||||
a dynamically allocated copy of the appropriately sized item to fw_cfg
|
||||
under the given selector key value.
|
||||
|
||||
== fw_cfg_add_file() ==
|
||||
|
||||
Given a filename (i.e., fw_cfg item name), starting pointer, and size,
|
||||
create an item as a raw "blob" of the given size. Unlike fw_cfg_add_bytes()
|
||||
above, the next available selector key (above 0x0020, FW_CFG_FILE_FIRST)
|
||||
will be used, and a new entry will be added to the file directory structure
|
||||
(at key 0x0019), containing the item name, blob size, and automatically
|
||||
assigned selector key value. The data referenced by the starting pointer
|
||||
is only linked, NOT copied, into the fw_cfg data structure.
|
||||
|
||||
== fw_cfg_add_file_callback() ==
|
||||
|
||||
Like fw_cfg_add_file(), but additionally sets pointers to a callback
|
||||
function (and opaque argument), which will be executed host-side by
|
||||
QEMU each time a byte is read by the guest from this particular item.
|
||||
|
||||
NOTE: The callback function is given the opaque argument set by
|
||||
fw_cfg_add_file_callback(), but also the current data offset,
|
||||
allowing it the option of only acting upon specific offset values
|
||||
(e.g., 0, before the first data byte of the selected item is
|
||||
returned to the guest).
|
||||
|
||||
== fw_cfg_modify_file() ==
|
||||
|
||||
Given a filename (i.e., fw_cfg item name), starting pointer, and size,
|
||||
completely replace the configuration item referenced by the given item
|
||||
name with the new given blob. If an existing blob is found, its
|
||||
callback information is removed, and a pointer to the old data is
|
||||
returned to allow the caller to free it, helping avoid memory leaks.
|
||||
If a configuration item does not already exist under the given item
|
||||
name, a new item will be created as with fw_cfg_add_file(), and NULL
|
||||
is returned to the caller. In any case, the data referenced by the
|
||||
starting pointer is only linked, NOT copied, into the fw_cfg data
|
||||
structure.
|
||||
|
||||
== fw_cfg_add_callback() ==
|
||||
|
||||
Like fw_cfg_add_bytes(), but additionally sets pointers to a callback
|
||||
function (and opaque argument), which will be executed host-side by
|
||||
QEMU each time a guest-side write operation to this particular item
|
||||
completes fully overwriting the item's data.
|
||||
|
||||
NOTE: This function is deprecated, and will be completely removed
|
||||
starting with QEMU v2.4.
|
3
hmp.c
3
hmp.c
@@ -391,7 +391,8 @@ static void print_block_info(Monitor *mon, BlockInfo *info,
|
||||
inserted->iops_size);
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
/* TODO: inserted->image should never be null */
|
||||
if (verbose && inserted->image) {
|
||||
monitor_printf(mon, "\nImages:\n");
|
||||
image_info = inserted->image;
|
||||
while (1) {
|
||||
|
@@ -844,9 +844,8 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
|
||||
|
||||
/* Main memory region, 0x00.0000.0000. Real hardware supports 32GB,
|
||||
but the address space hole reserved at this point is 8TB. */
|
||||
memory_region_init_ram(&s->ram_region, OBJECT(s), "ram", ram_size,
|
||||
&error_abort);
|
||||
vmstate_register_ram_global(&s->ram_region);
|
||||
memory_region_allocate_system_memory(&s->ram_region, OBJECT(s), "ram",
|
||||
ram_size);
|
||||
memory_region_add_subregion(addr_space, 0, &s->ram_region);
|
||||
|
||||
/* TIGbus, 0x801.0000.0000, 1GB. */
|
||||
|
@@ -63,9 +63,8 @@ static void cubieboard_init(MachineState *machine)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memory_region_init_ram(&s->sdram, NULL, "cubieboard.ram",
|
||||
machine->ram_size, &error_abort);
|
||||
vmstate_register_ram_global(&s->sdram);
|
||||
memory_region_allocate_system_memory(&s->sdram, NULL, "cubieboard.ram",
|
||||
machine->ram_size);
|
||||
memory_region_add_subregion(get_system_memory(), AW_A10_SDRAM_BASE,
|
||||
&s->sdram);
|
||||
|
||||
|
@@ -51,9 +51,8 @@ typedef struct DigicBoard {
|
||||
|
||||
static void digic4_board_setup_ram(DigicBoardState *s, hwaddr ram_size)
|
||||
{
|
||||
memory_region_init_ram(&s->ram, NULL, "ram", ram_size, &error_abort);
|
||||
memory_region_allocate_system_memory(&s->ram, NULL, "ram", ram_size);
|
||||
memory_region_add_subregion(get_system_memory(), 0, &s->ram);
|
||||
vmstate_register_ram_global(&s->ram);
|
||||
}
|
||||
|
||||
static void digic4_board_init(DigicBoard *board)
|
||||
|
@@ -267,7 +267,7 @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
|
||||
|
||||
sysmem = get_system_memory();
|
||||
dram = g_new(MemoryRegion, 1);
|
||||
memory_region_init_ram(dram, NULL, "highbank.dram", ram_size, &error_abort);
|
||||
memory_region_allocate_system_memory(dram, NULL, "highbank.dram", ram_size);
|
||||
/* SDRAM at address zero. */
|
||||
memory_region_add_subregion(sysmem, 0, dram);
|
||||
|
||||
|
@@ -567,8 +567,8 @@ static void integratorcp_init(MachineState *machine)
|
||||
|
||||
cpu = ARM_CPU(cpuobj);
|
||||
|
||||
memory_region_init_ram(ram, NULL, "integrator.ram", ram_size, &error_abort);
|
||||
vmstate_register_ram_global(ram);
|
||||
memory_region_allocate_system_memory(ram, NULL, "integrator.ram",
|
||||
ram_size);
|
||||
/* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash. */
|
||||
/* ??? RAM should repeat to fill physical memory space. */
|
||||
/* SDRAM at address zero*/
|
||||
|
@@ -97,8 +97,7 @@ static void kzm_init(MachineState *machine)
|
||||
|
||||
/* On a real system, the first 16k is a `secure boot rom' */
|
||||
|
||||
memory_region_init_ram(ram, NULL, "kzm.ram", ram_size, &error_abort);
|
||||
vmstate_register_ram_global(ram);
|
||||
memory_region_allocate_system_memory(ram, NULL, "kzm.ram", ram_size);
|
||||
memory_region_add_subregion(address_space_mem, KZM_RAMADDRESS, ram);
|
||||
|
||||
memory_region_init_alias(ram_alias, NULL, "ram.alias", ram, 0, ram_size);
|
||||
|
@@ -1600,9 +1600,8 @@ static void musicpal_init(MachineState *machine)
|
||||
}
|
||||
|
||||
/* For now we use a fixed - the original - RAM size */
|
||||
memory_region_init_ram(ram, NULL, "musicpal.ram", MP_RAM_DEFAULT_SIZE,
|
||||
&error_abort);
|
||||
vmstate_register_ram_global(ram);
|
||||
memory_region_allocate_system_memory(ram, NULL, "musicpal.ram",
|
||||
MP_RAM_DEFAULT_SIZE);
|
||||
memory_region_add_subregion(address_space_mem, 0, ram);
|
||||
|
||||
memory_region_init_ram(sram, NULL, "musicpal.sram", MP_SRAM_SIZE,
|
||||
|
@@ -16,6 +16,8 @@
|
||||
* 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 "hw/boards.h"
|
||||
#include "hw/hw.h"
|
||||
#include "hw/arm/arm.h"
|
||||
#include "hw/arm/omap.h"
|
||||
@@ -3878,9 +3880,8 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
|
||||
omap_clk_init(s);
|
||||
|
||||
/* Memory-mapped stuff */
|
||||
memory_region_init_ram(&s->emiff_ram, NULL, "omap1.dram", s->sdram_size,
|
||||
&error_abort);
|
||||
vmstate_register_ram_global(&s->emiff_ram);
|
||||
memory_region_allocate_system_memory(&s->emiff_ram, NULL, "omap1.dram",
|
||||
s->sdram_size);
|
||||
memory_region_add_subregion(system_memory, OMAP_EMIFF_BASE, &s->emiff_ram);
|
||||
memory_region_init_ram(&s->imif_ram, NULL, "omap1.sram", s->sram_size,
|
||||
&error_abort);
|
||||
|
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "sysemu/blockdev.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/hw.h"
|
||||
#include "hw/arm/arm.h"
|
||||
#include "hw/arm/omap.h"
|
||||
@@ -2271,9 +2272,8 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
|
||||
omap_clk_init(s);
|
||||
|
||||
/* Memory-mapped stuff */
|
||||
memory_region_init_ram(&s->sdram, NULL, "omap2.dram", s->sdram_size,
|
||||
&error_abort);
|
||||
vmstate_register_ram_global(&s->sdram);
|
||||
memory_region_allocate_system_memory(&s->sdram, NULL, "omap2.dram",
|
||||
s->sdram_size);
|
||||
memory_region_add_subregion(sysmem, OMAP2_Q2_BASE, &s->sdram);
|
||||
memory_region_init_ram(&s->sram, NULL, "omap2.sram", s->sram_size,
|
||||
&error_abort);
|
||||
|
@@ -26,6 +26,8 @@
|
||||
* Contributions after 2012-01-13 are licensed under the terms of the
|
||||
* GNU GPL, version 2 or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include "hw/boards.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "strongarm.h"
|
||||
#include "qemu/error-report.h"
|
||||
@@ -1604,9 +1606,8 @@ StrongARMState *sa1110_init(MemoryRegion *sysmem,
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memory_region_init_ram(&s->sdram, NULL, "strongarm.sdram", sdram_size,
|
||||
&error_abort);
|
||||
vmstate_register_ram_global(&s->sdram);
|
||||
memory_region_allocate_system_memory(&s->sdram, NULL, "strongarm.sdram",
|
||||
sdram_size);
|
||||
memory_region_add_subregion(sysmem, SA_SDCS0, &s->sdram);
|
||||
|
||||
s->pic = sysbus_create_varargs("strongarm_pic", 0x90050000,
|
||||
|
@@ -226,9 +226,8 @@ static void versatile_init(MachineState *machine, int board_id)
|
||||
|
||||
cpu = ARM_CPU(cpuobj);
|
||||
|
||||
memory_region_init_ram(ram, NULL, "versatile.ram", machine->ram_size,
|
||||
&error_abort);
|
||||
vmstate_register_ram_global(ram);
|
||||
memory_region_allocate_system_memory(ram, NULL, "versatile.ram",
|
||||
machine->ram_size);
|
||||
/* ??? RAM should repeat to fill physical memory space. */
|
||||
/* SDRAM at address zero. */
|
||||
memory_region_add_subregion(sysmem, 0, ram);
|
||||
|
@@ -276,9 +276,8 @@ static void a9_daughterboard_init(const VexpressMachineState *vms,
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memory_region_init_ram(ram, NULL, "vexpress.highmem", ram_size,
|
||||
&error_abort);
|
||||
vmstate_register_ram_global(ram);
|
||||
memory_region_allocate_system_memory(ram, NULL, "vexpress.highmem",
|
||||
ram_size);
|
||||
low_ram_size = ram_size;
|
||||
if (low_ram_size > 0x4000000) {
|
||||
low_ram_size = 0x4000000;
|
||||
@@ -371,9 +370,8 @@ static void a15_daughterboard_init(const VexpressMachineState *vms,
|
||||
}
|
||||
}
|
||||
|
||||
memory_region_init_ram(ram, NULL, "vexpress.highmem", ram_size,
|
||||
&error_abort);
|
||||
vmstate_register_ram_global(ram);
|
||||
memory_region_allocate_system_memory(ram, NULL, "vexpress.highmem",
|
||||
ram_size);
|
||||
/* RAM is from 0x80000000 upwards; there is no low-memory alias for it. */
|
||||
memory_region_add_subregion(sysmem, 0x80000000, ram);
|
||||
|
||||
|
@@ -805,9 +805,8 @@ static void machvirt_init(MachineState *machine)
|
||||
fdt_add_cpu_nodes(vbi);
|
||||
fdt_add_psci_node(vbi);
|
||||
|
||||
memory_region_init_ram(ram, NULL, "mach-virt.ram", machine->ram_size,
|
||||
&error_abort);
|
||||
vmstate_register_ram_global(ram);
|
||||
memory_region_allocate_system_memory(ram, NULL, "mach-virt.ram",
|
||||
machine->ram_size);
|
||||
memory_region_add_subregion(sysmem, vbi->memmap[VIRT_MEM].base, ram);
|
||||
|
||||
create_flash(vbi);
|
||||
|
@@ -161,9 +161,8 @@ static void zynq_init(MachineState *machine)
|
||||
}
|
||||
|
||||
/* DDR remapped to address zero. */
|
||||
memory_region_init_ram(ext_ram, NULL, "zynq.ext_ram", ram_size,
|
||||
&error_abort);
|
||||
vmstate_register_ram_global(ext_ram);
|
||||
memory_region_allocate_system_memory(ext_ram, NULL, "zynq.ext_ram",
|
||||
ram_size);
|
||||
memory_region_add_subregion(address_space_mem, 0, ext_ram);
|
||||
|
||||
/* 256K of on-chip memory */
|
||||
|
@@ -167,7 +167,7 @@ static void pcspk_initfn(Object *obj)
|
||||
{
|
||||
PCSpkState *s = PC_SPEAKER(obj);
|
||||
|
||||
memory_region_init_io(&s->ioport, OBJECT(s), &pcspk_io_ops, s, "elcr", 1);
|
||||
memory_region_init_io(&s->ioport, OBJECT(s), &pcspk_io_ops, s, "pcspk", 1);
|
||||
}
|
||||
|
||||
static void pcspk_realizefn(DeviceState *dev, Error **errp)
|
||||
|
@@ -77,8 +77,7 @@ static void complete_request_vring(VirtIOBlockReq *req, unsigned char status)
|
||||
VirtIOBlockDataPlane *s = req->dev->dataplane;
|
||||
stb_p(&req->in->status, status);
|
||||
|
||||
vring_push(s->vdev, &req->dev->dataplane->vring, &req->elem,
|
||||
req->qiov.size + sizeof(*req->in));
|
||||
vring_push(s->vdev, &req->dev->dataplane->vring, &req->elem, req->in_len);
|
||||
|
||||
/* Suppress notification to guest by BH and its scheduled
|
||||
* flag because requests are completed as a batch after io
|
||||
|
@@ -33,6 +33,7 @@ VirtIOBlockReq *virtio_blk_alloc_request(VirtIOBlock *s)
|
||||
VirtIOBlockReq *req = g_slice_new(VirtIOBlockReq);
|
||||
req->dev = s;
|
||||
req->qiov.size = 0;
|
||||
req->in_len = 0;
|
||||
req->next = NULL;
|
||||
req->mr_next = NULL;
|
||||
return req;
|
||||
@@ -54,7 +55,7 @@ static void virtio_blk_complete_request(VirtIOBlockReq *req,
|
||||
trace_virtio_blk_req_complete(req, status);
|
||||
|
||||
stb_p(&req->in->status, status);
|
||||
virtqueue_push(s->vq, &req->elem, req->qiov.size + sizeof(*req->in));
|
||||
virtqueue_push(s->vq, &req->elem, req->in_len);
|
||||
virtio_notify(vdev, s->vq);
|
||||
}
|
||||
|
||||
@@ -102,6 +103,14 @@ static void virtio_blk_rw_complete(void *opaque, int ret)
|
||||
if (ret) {
|
||||
int p = virtio_ldl_p(VIRTIO_DEVICE(req->dev), &req->out.type);
|
||||
bool is_read = !(p & VIRTIO_BLK_T_OUT);
|
||||
/* Note that memory may be dirtied on read failure. If the
|
||||
* virtio request is not completed here, as is the case for
|
||||
* BLOCK_ERROR_ACTION_STOP, the memory may not be copied
|
||||
* correctly during live migration. While this is ugly,
|
||||
* it is acceptable because the device is free to write to
|
||||
* the memory until the request is completed (which will
|
||||
* happen on the other side of the migration).
|
||||
*/
|
||||
if (virtio_blk_handle_rw_error(req, -ret, is_read)) {
|
||||
continue;
|
||||
}
|
||||
@@ -496,6 +505,8 @@ void virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* We always touch the last byte, so just see how big in_iov is. */
|
||||
req->in_len = iov_size(in_iov, in_num);
|
||||
req->in = (void *)in_iov[in_num - 1].iov_base
|
||||
+ in_iov[in_num - 1].iov_len
|
||||
- sizeof(struct virtio_blk_inhdr);
|
||||
|
@@ -270,9 +270,8 @@ void axisdev88_init(MachineState *machine)
|
||||
env = &cpu->env;
|
||||
|
||||
/* allocate RAM */
|
||||
memory_region_init_ram(phys_ram, NULL, "axisdev88.ram", ram_size,
|
||||
&error_abort);
|
||||
vmstate_register_ram_global(phys_ram);
|
||||
memory_region_allocate_system_memory(phys_ram, NULL, "axisdev88.ram",
|
||||
ram_size);
|
||||
memory_region_add_subregion(address_space_mem, 0x40000000, phys_ram);
|
||||
|
||||
/* The ETRAX-FS has 128Kb on chip ram, the docs refer to it as the
|
||||
|
@@ -111,9 +111,8 @@ static void lm32_evr_init(MachineState *machine)
|
||||
|
||||
reset_info->flash_base = flash_base;
|
||||
|
||||
memory_region_init_ram(phys_ram, NULL, "lm32_evr.sdram", ram_size,
|
||||
&error_abort);
|
||||
vmstate_register_ram_global(phys_ram);
|
||||
memory_region_allocate_system_memory(phys_ram, NULL, "lm32_evr.sdram",
|
||||
ram_size);
|
||||
memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
|
||||
|
||||
dinfo = drive_get(IF_PFLASH, 0, 0);
|
||||
@@ -214,9 +213,8 @@ static void lm32_uclinux_init(MachineState *machine)
|
||||
|
||||
reset_info->flash_base = flash_base;
|
||||
|
||||
memory_region_init_ram(phys_ram, NULL, "lm32_uclinux.sdram", ram_size,
|
||||
&error_abort);
|
||||
vmstate_register_ram_global(phys_ram);
|
||||
memory_region_allocate_system_memory(phys_ram, NULL,
|
||||
"lm32_uclinux.sdram", ram_size);
|
||||
memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
|
||||
|
||||
dinfo = drive_get(IF_PFLASH, 0, 0);
|
||||
|
@@ -118,9 +118,8 @@ milkymist_init(MachineState *machine)
|
||||
|
||||
cpu_lm32_set_phys_msb_ignore(env, 1);
|
||||
|
||||
memory_region_init_ram(phys_sdram, NULL, "milkymist.sdram", sdram_size,
|
||||
&error_abort);
|
||||
vmstate_register_ram_global(phys_sdram);
|
||||
memory_region_allocate_system_memory(phys_sdram, NULL, "milkymist.sdram",
|
||||
sdram_size);
|
||||
memory_region_add_subregion(address_space_mem, sdram_base, phys_sdram);
|
||||
|
||||
dinfo = drive_get(IF_PFLASH, 0, 0);
|
||||
|
@@ -233,7 +233,7 @@ static void bonito_writel(void *opaque, hwaddr addr,
|
||||
uint32_t saddr;
|
||||
int reset = 0;
|
||||
|
||||
saddr = (addr - BONITO_REGBASE) >> 2;
|
||||
saddr = addr >> 2;
|
||||
|
||||
DPRINTF("bonito_writel "TARGET_FMT_plx" val %x saddr %x\n", addr, val, saddr);
|
||||
switch (saddr) {
|
||||
@@ -295,7 +295,7 @@ static uint64_t bonito_readl(void *opaque, hwaddr addr,
|
||||
PCIBonitoState *s = opaque;
|
||||
uint32_t saddr;
|
||||
|
||||
saddr = (addr - BONITO_REGBASE) >> 2;
|
||||
saddr = addr >> 2;
|
||||
|
||||
DPRINTF("bonito_readl "TARGET_FMT_plx"\n", addr);
|
||||
switch (saddr) {
|
||||
|
@@ -1660,7 +1660,9 @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
|
||||
|
||||
res = pci_nic_init(nd, rootbus, default_model, default_devaddr, &err);
|
||||
if (!res) {
|
||||
error_report_err(err);
|
||||
if (err) {
|
||||
error_report_err(err);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
return res;
|
||||
|
@@ -288,7 +288,7 @@ static inline void vhost_dev_log_resize(struct vhost_dev* dev, uint64_t size)
|
||||
int r;
|
||||
|
||||
log = g_malloc0(size * sizeof *log);
|
||||
log_base = (uint64_t)(unsigned long)log;
|
||||
log_base = (uintptr_t)log;
|
||||
r = dev->vhost_ops->vhost_call(dev, VHOST_SET_LOG_BASE, &log_base);
|
||||
assert(r >= 0);
|
||||
/* Sync only the range covered by the old log */
|
||||
@@ -1057,10 +1057,13 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
|
||||
}
|
||||
|
||||
if (hdev->log_enabled) {
|
||||
uint64_t log_base;
|
||||
|
||||
hdev->log_size = vhost_get_log_size(hdev);
|
||||
hdev->log = hdev->log_size ?
|
||||
g_malloc0(hdev->log_size * sizeof *hdev->log) : NULL;
|
||||
r = hdev->vhost_ops->vhost_call(hdev, VHOST_SET_LOG_BASE, hdev->log);
|
||||
log_base = (uintptr_t)hdev->log;
|
||||
r = hdev->vhost_ops->vhost_call(hdev, VHOST_SET_LOG_BASE, &log_base);
|
||||
if (r < 0) {
|
||||
r = -errno;
|
||||
goto fail_log;
|
||||
|
@@ -388,7 +388,7 @@ static const MemoryRegionOps ops = {
|
||||
.write = xen_pt_bar_write,
|
||||
};
|
||||
|
||||
static int xen_pt_register_regions(XenPCIPassthroughState *s)
|
||||
static int xen_pt_register_regions(XenPCIPassthroughState *s, uint16_t *cmd)
|
||||
{
|
||||
int i = 0;
|
||||
XenHostPCIDevice *d = &s->real_device;
|
||||
@@ -406,6 +406,7 @@ static int xen_pt_register_regions(XenPCIPassthroughState *s)
|
||||
|
||||
if (r->type & XEN_HOST_PCI_REGION_TYPE_IO) {
|
||||
type = PCI_BASE_ADDRESS_SPACE_IO;
|
||||
*cmd |= PCI_COMMAND_IO;
|
||||
} else {
|
||||
type = PCI_BASE_ADDRESS_SPACE_MEMORY;
|
||||
if (r->type & XEN_HOST_PCI_REGION_TYPE_PREFETCH) {
|
||||
@@ -414,6 +415,7 @@ static int xen_pt_register_regions(XenPCIPassthroughState *s)
|
||||
if (r->type & XEN_HOST_PCI_REGION_TYPE_MEM_64) {
|
||||
type |= PCI_BASE_ADDRESS_MEM_TYPE_64;
|
||||
}
|
||||
*cmd |= PCI_COMMAND_MEMORY;
|
||||
}
|
||||
|
||||
memory_region_init_io(&s->bar[i], OBJECT(s), &ops, &s->dev,
|
||||
@@ -638,6 +640,7 @@ static int xen_pt_initfn(PCIDevice *d)
|
||||
XenPCIPassthroughState *s = DO_UPCAST(XenPCIPassthroughState, dev, d);
|
||||
int rc = 0;
|
||||
uint8_t machine_irq = 0;
|
||||
uint16_t cmd = 0;
|
||||
int pirq = XEN_PT_UNASSIGNED_PIRQ;
|
||||
|
||||
/* register real device */
|
||||
@@ -672,7 +675,7 @@ static int xen_pt_initfn(PCIDevice *d)
|
||||
s->io_listener = xen_pt_io_listener;
|
||||
|
||||
/* Handle real device's MMIO/PIO BARs */
|
||||
xen_pt_register_regions(s);
|
||||
xen_pt_register_regions(s, &cmd);
|
||||
|
||||
/* reinitialize each config register to be emulated */
|
||||
if (xen_pt_config_init(s)) {
|
||||
@@ -736,6 +739,11 @@ static int xen_pt_initfn(PCIDevice *d)
|
||||
}
|
||||
|
||||
out:
|
||||
if (cmd) {
|
||||
xen_host_pci_set_word(&s->real_device, PCI_COMMAND,
|
||||
pci_get_word(d->config + PCI_COMMAND) | cmd);
|
||||
}
|
||||
|
||||
memory_listener_register(&s->memory_listener, &s->dev.bus_master_as);
|
||||
memory_listener_register(&s->io_listener, &address_space_io);
|
||||
XEN_PT_LOG(d,
|
||||
|
@@ -286,23 +286,6 @@ static int xen_pt_irqpin_reg_init(XenPCIPassthroughState *s,
|
||||
}
|
||||
|
||||
/* Command register */
|
||||
static int xen_pt_cmd_reg_read(XenPCIPassthroughState *s, XenPTReg *cfg_entry,
|
||||
uint16_t *value, uint16_t valid_mask)
|
||||
{
|
||||
XenPTRegInfo *reg = cfg_entry->reg;
|
||||
uint16_t valid_emu_mask = 0;
|
||||
uint16_t emu_mask = reg->emu_mask;
|
||||
|
||||
if (s->is_virtfn) {
|
||||
emu_mask |= PCI_COMMAND_MEMORY;
|
||||
}
|
||||
|
||||
/* emulate word register */
|
||||
valid_emu_mask = emu_mask & valid_mask;
|
||||
*value = XEN_PT_MERGE_VALUE(*value, cfg_entry->data, ~valid_emu_mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int xen_pt_cmd_reg_write(XenPCIPassthroughState *s, XenPTReg *cfg_entry,
|
||||
uint16_t *val, uint16_t dev_value,
|
||||
uint16_t valid_mask)
|
||||
@@ -310,18 +293,13 @@ static int xen_pt_cmd_reg_write(XenPCIPassthroughState *s, XenPTReg *cfg_entry,
|
||||
XenPTRegInfo *reg = cfg_entry->reg;
|
||||
uint16_t writable_mask = 0;
|
||||
uint16_t throughable_mask = 0;
|
||||
uint16_t emu_mask = reg->emu_mask;
|
||||
|
||||
if (s->is_virtfn) {
|
||||
emu_mask |= PCI_COMMAND_MEMORY;
|
||||
}
|
||||
|
||||
/* modify emulate register */
|
||||
writable_mask = ~reg->ro_mask & valid_mask;
|
||||
cfg_entry->data = XEN_PT_MERGE_VALUE(*val, cfg_entry->data, writable_mask);
|
||||
|
||||
/* create value for writing to I/O device register */
|
||||
throughable_mask = ~emu_mask & valid_mask;
|
||||
throughable_mask = ~reg->emu_mask & valid_mask;
|
||||
|
||||
if (*val & PCI_COMMAND_INTX_DISABLE) {
|
||||
throughable_mask |= PCI_COMMAND_INTX_DISABLE;
|
||||
@@ -603,9 +581,9 @@ static XenPTRegInfo xen_pt_emu_reg_header0[] = {
|
||||
.size = 2,
|
||||
.init_val = 0x0000,
|
||||
.ro_mask = 0xF880,
|
||||
.emu_mask = 0x0740,
|
||||
.emu_mask = 0x0743,
|
||||
.init = xen_pt_common_reg_init,
|
||||
.u.w.read = xen_pt_cmd_reg_read,
|
||||
.u.w.read = xen_pt_word_reg_read,
|
||||
.u.w.write = xen_pt_cmd_reg_write,
|
||||
},
|
||||
/* Capabilities Pointer reg */
|
||||
|
@@ -29,7 +29,7 @@
|
||||
#include "hw/timer/stm32f2xx_timer.h"
|
||||
#include "hw/char/stm32f2xx_usart.h"
|
||||
|
||||
#define TYPE_STM32F205_SOC "stm32f205_soc"
|
||||
#define TYPE_STM32F205_SOC "stm32f205-soc"
|
||||
#define STM32F205_SOC(obj) \
|
||||
OBJECT_CHECK(STM32F205State, (obj), TYPE_STM32F205_SOC)
|
||||
|
||||
|
@@ -36,7 +36,7 @@ struct vhost_dev {
|
||||
MemoryRegionSection *mem_sections;
|
||||
struct vhost_virtqueue *vqs;
|
||||
int nvqs;
|
||||
/* the first virtuque which would be used by this vhost dev */
|
||||
/* the first virtqueue which would be used by this vhost dev */
|
||||
int vq_index;
|
||||
unsigned long long features;
|
||||
unsigned long long acked_features;
|
||||
|
@@ -67,6 +67,7 @@ typedef struct VirtIOBlockReq {
|
||||
struct virtio_blk_inhdr *in;
|
||||
struct virtio_blk_outhdr out;
|
||||
QEMUIOVector qiov;
|
||||
size_t in_len;
|
||||
struct VirtIOBlockReq *next;
|
||||
struct VirtIOBlockReq *mr_next;
|
||||
BlockAcctCookie acct;
|
||||
|
@@ -31,8 +31,6 @@
|
||||
/* Maximum instruction code size */
|
||||
#define TARGET_MAX_INSN_SIZE 16
|
||||
|
||||
/* target supports implicit self modifying code */
|
||||
#define TARGET_HAS_SMC
|
||||
/* support for self modifying code even if the modified instruction is
|
||||
close to the modifying instruction */
|
||||
#define TARGET_HAS_PRECISE_SMC
|
||||
|
@@ -192,9 +192,9 @@ static int cpu_post_load(void *opaque, int version_id)
|
||||
ppc_store_sdr1(env, env->spr[SPR_SDR1]);
|
||||
}
|
||||
|
||||
/* Mark msr bits except MSR_TGPR invalid before restoring */
|
||||
/* Invalidate all msr bits except MSR_TGPR/MSR_HVB before restoring */
|
||||
msr = env->msr;
|
||||
env->msr ^= ~(1ULL << MSR_TGPR);
|
||||
env->msr ^= ~((1ULL << MSR_TGPR) | MSR_HVB);
|
||||
ppc_store_msr(env, msr);
|
||||
|
||||
hreg_compute_mem_idx(env);
|
||||
|
@@ -2573,7 +2573,7 @@ void helper_rslcx(CPUTriCoreState *env)
|
||||
/* CSU trap */
|
||||
}
|
||||
/* if (PCXI.UL == 1) then trap(CTYP); */
|
||||
if ((env->PCXI & MASK_PCXI_UL) == 1) {
|
||||
if ((env->PCXI & MASK_PCXI_UL) != 0) {
|
||||
/* CTYP trap */
|
||||
}
|
||||
/* EA = {PCXI.PCXS, 6'b0, PCXI.PCXO, 6'b0}; */
|
||||
|
@@ -808,7 +808,7 @@ void tcg_gen_ld_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
|
||||
{
|
||||
/* Since arg2 and ret have different types,
|
||||
they cannot be the same temporary */
|
||||
#ifdef TCG_TARGET_WORDS_BIGENDIAN
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset);
|
||||
tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset + 4);
|
||||
#else
|
||||
@@ -819,7 +819,7 @@ void tcg_gen_ld_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset)
|
||||
|
||||
void tcg_gen_st_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset)
|
||||
{
|
||||
#ifdef TCG_TARGET_WORDS_BIGENDIAN
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset);
|
||||
tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset + 4);
|
||||
#else
|
||||
|
95
tests/qemu-iotests/130
Executable file
95
tests/qemu-iotests/130
Executable file
@@ -0,0 +1,95 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Test that temporary backing file overrides (on the command line or in
|
||||
# blockdev-add) don't replace the original path stored in the image during
|
||||
# header updates.
|
||||
#
|
||||
# Copyright (C) 2015 Red Hat, Inc.
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
# creator
|
||||
owner=kwolf@redhat.com
|
||||
|
||||
seq="$(basename $0)"
|
||||
echo "QA output created by $seq"
|
||||
|
||||
here="$PWD"
|
||||
tmp=/tmp/$$
|
||||
status=1 # failure is the default!
|
||||
|
||||
_cleanup()
|
||||
{
|
||||
_cleanup_test_img
|
||||
}
|
||||
trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
|
||||
# get standard environment, filters and checks
|
||||
. ./common.rc
|
||||
. ./common.filter
|
||||
. ./common.qemu
|
||||
|
||||
_supported_fmt qcow2
|
||||
_supported_proto generic
|
||||
_supported_os Linux
|
||||
|
||||
qemu_comm_method="monitor"
|
||||
|
||||
|
||||
TEST_IMG="$TEST_IMG.orig" _make_test_img 64M
|
||||
TEST_IMG="$TEST_IMG.base" _make_test_img 64M
|
||||
_make_test_img 64M
|
||||
_img_info | _filter_img_info
|
||||
|
||||
echo
|
||||
echo "=== HMP commit ==="
|
||||
echo
|
||||
# bdrv_make_empty() involves a header update for qcow2
|
||||
|
||||
# Test that a backing file isn't written
|
||||
_launch_qemu -drive file="$TEST_IMG",backing.file.filename="$TEST_IMG.base"
|
||||
_send_qemu_cmd $QEMU_HANDLE "commit ide0-hd0" "(qemu)"
|
||||
_send_qemu_cmd $QEMU_HANDLE '' '(qemu)'
|
||||
_cleanup_qemu
|
||||
_img_info | _filter_img_info
|
||||
|
||||
# Make sure that if there was a backing file that was just overridden on the
|
||||
# command line, that backing file is retained, with the right format
|
||||
_make_test_img -F raw -b "$TEST_IMG.orig" 64M
|
||||
_launch_qemu -drive file="$TEST_IMG",backing.file.filename="$TEST_IMG.base",backing.driver=$IMGFMT
|
||||
_send_qemu_cmd $QEMU_HANDLE "commit ide0-hd0" "(qemu)"
|
||||
_send_qemu_cmd $QEMU_HANDLE '' '(qemu)'
|
||||
_cleanup_qemu
|
||||
_img_info | _filter_img_info
|
||||
|
||||
echo
|
||||
echo "=== Marking image dirty (lazy refcounts) ==="
|
||||
echo
|
||||
|
||||
# Test that a backing file isn't written
|
||||
_make_test_img 64M
|
||||
$QEMU_IO -c "open -o backing.file.filename=$TEST_IMG.base,lazy-refcounts=on $TEST_IMG" -c "write 0 4k" | _filter_qemu_io
|
||||
_img_info | _filter_img_info
|
||||
|
||||
# Make sure that if there was a backing file that was just overridden on the
|
||||
# command line, that backing file is retained, with the right format
|
||||
_make_test_img -F raw -b "$TEST_IMG.orig" 64M
|
||||
$QEMU_IO -c "open -o backing.file.filename=$TEST_IMG.base,backing.driver=$IMGFMT,lazy-refcounts=on $TEST_IMG" -c "write 0 4k" | _filter_qemu_io
|
||||
_img_info | _filter_img_info
|
||||
|
||||
# success, all done
|
||||
echo '*** done'
|
||||
rm -f $seq.full
|
||||
status=0
|
43
tests/qemu-iotests/130.out
Normal file
43
tests/qemu-iotests/130.out
Normal file
@@ -0,0 +1,43 @@
|
||||
QA output created by 130
|
||||
Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=67108864
|
||||
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||
image: TEST_DIR/t.IMGFMT
|
||||
file format: IMGFMT
|
||||
virtual size: 64M (67108864 bytes)
|
||||
|
||||
=== HMP commit ===
|
||||
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
(qemu) c[K[Dco[K[D[Dcom[K[D[D[Dcomm[K[D[D[D[Dcommi[K[D[D[D[D[Dcommit[K[D[D[D[D[D[Dcommit [K[D[D[D[D[D[D[Dcommit i[K[D[D[D[D[D[D[D[Dcommit id[K[D[D[D[D[D[D[D[D[Dcommit ide[K[D[D[D[D[D[D[D[D[D[Dcommit ide0[K[D[D[D[D[D[D[D[D[D[D[Dcommit ide0-[K[D[D[D[D[D[D[D[D[D[D[D[Dcommit ide0-h[K[D[D[D[D[D[D[D[D[D[D[D[D[Dcommit ide0-hd[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dcommit ide0-hd0[K
|
||||
(qemu)
|
||||
image: TEST_DIR/t.IMGFMT
|
||||
file format: IMGFMT
|
||||
virtual size: 64M (67108864 bytes)
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.orig' backing_fmt='raw'
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
(qemu) c[K[Dco[K[D[Dcom[K[D[D[Dcomm[K[D[D[D[Dcommi[K[D[D[D[D[Dcommit[K[D[D[D[D[D[Dcommit [K[D[D[D[D[D[D[Dcommit i[K[D[D[D[D[D[D[D[Dcommit id[K[D[D[D[D[D[D[D[D[Dcommit ide[K[D[D[D[D[D[D[D[D[D[Dcommit ide0[K[D[D[D[D[D[D[D[D[D[D[Dcommit ide0-[K[D[D[D[D[D[D[D[D[D[D[D[Dcommit ide0-h[K[D[D[D[D[D[D[D[D[D[D[D[D[Dcommit ide0-hd[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dcommit ide0-hd0[K
|
||||
(qemu)
|
||||
image: TEST_DIR/t.IMGFMT
|
||||
file format: IMGFMT
|
||||
virtual size: 64M (67108864 bytes)
|
||||
backing file: TEST_DIR/t.IMGFMT.orig
|
||||
backing file format: raw
|
||||
|
||||
=== Marking image dirty (lazy refcounts) ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||
wrote 4096/4096 bytes at offset 0
|
||||
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
image: TEST_DIR/t.IMGFMT
|
||||
file format: IMGFMT
|
||||
virtual size: 64M (67108864 bytes)
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.orig' backing_fmt='raw'
|
||||
wrote 4096/4096 bytes at offset 0
|
||||
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
image: TEST_DIR/t.IMGFMT
|
||||
file format: IMGFMT
|
||||
virtual size: 64M (67108864 bytes)
|
||||
backing file: TEST_DIR/t.IMGFMT.orig
|
||||
backing file format: raw
|
||||
*** done
|
@@ -124,3 +124,4 @@
|
||||
121 rw auto
|
||||
123 rw auto quick
|
||||
128 rw auto quick
|
||||
130 rw auto quick
|
||||
|
@@ -1334,8 +1334,6 @@ static inline void tb_alloc_page(TranslationBlock *tb,
|
||||
p->first_tb = (TranslationBlock *)((uintptr_t)tb | n);
|
||||
invalidate_page_bitmap(p);
|
||||
|
||||
#if defined(TARGET_HAS_SMC) || 1
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
if (p->flags & PAGE_WRITE) {
|
||||
target_ulong addr;
|
||||
@@ -1371,8 +1369,6 @@ static inline void tb_alloc_page(TranslationBlock *tb,
|
||||
tlb_protect_code(page_addr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* TARGET_HAS_SMC */
|
||||
}
|
||||
|
||||
/* add a new TB and link it to the physical page tables. phys_page2 is
|
||||
|
Reference in New Issue
Block a user