Compare commits
176 Commits
pull-input
...
pull-booti
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
54086fe5d2 | ||
|
|
4aca8a8178 | ||
|
|
d749e10c4f | ||
|
|
d2b186f96d | ||
|
|
33739c7129 | ||
|
|
89f0762dde | ||
|
|
aeb98ddc50 | ||
|
|
8dece34f26 | ||
|
|
3342ec324a | ||
|
|
4556363087 | ||
|
|
44fb6337b9 | ||
|
|
81782b6a78 | ||
|
|
295857994c | ||
|
|
abc5b3bfe1 | ||
|
|
7f6014af27 | ||
|
|
e6adae52b1 | ||
|
|
0cf63c3e35 | ||
|
|
45e8a9e123 | ||
|
|
c11f4bc9ff | ||
|
|
e25524efb0 | ||
|
|
dfe79cf268 | ||
|
|
afd7c850f5 | ||
|
|
ea3b3511cd | ||
|
|
6cb0851d62 | ||
|
|
7317bb1782 | ||
|
|
5df3bf623d | ||
|
|
aa4197c323 | ||
|
|
12da309778 | ||
|
|
a598f2ffc2 | ||
|
|
e614b54b93 | ||
|
|
bdbb5b1706 | ||
|
|
9d27572d62 | ||
|
|
694fb857ab | ||
|
|
bc74112f7e | ||
|
|
b1d28ec6a7 | ||
|
|
9d1c35dfc9 | ||
|
|
4b7757bae7 | ||
|
|
ef1df13087 | ||
|
|
71dd7e69b3 | ||
|
|
99607144a4 | ||
|
|
c9e659c9ee | ||
|
|
eb24f7c689 | ||
|
|
75973bfe41 | ||
|
|
a9fd16544d | ||
|
|
fcb2cd928f | ||
|
|
5008e5b7b8 | ||
|
|
5179502918 | ||
|
|
5748e4c2be | ||
|
|
35e4e96c4d | ||
|
|
cdebec5e40 | ||
|
|
fc02086b5a | ||
|
|
ac2da55e01 | ||
|
|
f6a1ef6440 | ||
|
|
b6011bd8a5 | ||
|
|
1a1c4db9b2 | ||
|
|
d80a190594 | ||
|
|
e52a99f756 | ||
|
|
a59b5e35d1 | ||
|
|
40645c7bfd | ||
|
|
2472b6c07b | ||
|
|
507ef2f9fa | ||
|
|
767c86d3e7 | ||
|
|
2eea5cd452 | ||
|
|
37e153fe45 | ||
|
|
e319df669d | ||
|
|
d0e3866837 | ||
|
|
e2f3f22188 | ||
|
|
f383611a0a | ||
|
|
9009b1963c | ||
|
|
1b53eab270 | ||
|
|
0d15da8e6f | ||
|
|
d95c8527e9 | ||
|
|
32592e112f | ||
|
|
3a6ce5147f | ||
|
|
b152b05a35 | ||
|
|
782c3f2939 | ||
|
|
b31f9acaaa | ||
|
|
f6dfb83547 | ||
|
|
b14a0b7469 | ||
|
|
a224655200 | ||
|
|
e8b466ef95 | ||
|
|
e54adde615 | ||
|
|
a1a9cb0ccd | ||
|
|
2067444945 | ||
|
|
01ca519f24 | ||
|
|
5dd1f02b4b | ||
|
|
16cc4ffe34 | ||
|
|
cfb429cb1a | ||
|
|
43ded1a0d2 | ||
|
|
9f781168c5 | ||
|
|
f5bebbbb28 | ||
|
|
d93162e13c | ||
|
|
6b9e03a4e7 | ||
|
|
d8f94e1bb2 | ||
|
|
1602651833 | ||
|
|
21dff8cf38 | ||
|
|
a66c9dc734 | ||
|
|
cf77b2d25e | ||
|
|
d9323e9b20 | ||
|
|
20d6cd47d0 | ||
|
|
d1319b077a | ||
|
|
fbf28a4328 | ||
|
|
18fe46d79a | ||
|
|
af95738754 | ||
|
|
b00a0ddb31 | ||
|
|
53b98718f1 | ||
|
|
fbcaca994d | ||
|
|
1831e15060 | ||
|
|
7be3c1408a | ||
|
|
2e456b2b60 | ||
|
|
c3b1060514 | ||
|
|
2c7d8736af | ||
|
|
e657d8ef3c | ||
|
|
ace89b8ff2 | ||
|
|
70a041fe2c | ||
|
|
2c79f2a2ec | ||
|
|
d3c2343af0 | ||
|
|
46c3a8c8eb | ||
|
|
d2e043a804 | ||
|
|
9e057c0b09 | ||
|
|
89ec031b09 | ||
|
|
a9fe4c957b | ||
|
|
be4d57c1ea | ||
|
|
49e7e31aa0 | ||
|
|
8e0a9320e9 | ||
|
|
d5776465ee | ||
|
|
a83cfd12d9 | ||
|
|
3df9caf88f | ||
|
|
6c25fa6cf8 | ||
|
|
eda470e41a | ||
|
|
45c270b1ea | ||
|
|
9786b592a9 | ||
|
|
5170f40b10 | ||
|
|
1880ad4f4e | ||
|
|
359eea71d9 | ||
|
|
dfb37cf7fa | ||
|
|
63c7e54268 | ||
|
|
91cb1c9b56 | ||
|
|
244e2898b7 | ||
|
|
19d339f11d | ||
|
|
c8075caf19 | ||
|
|
8f3d60e568 | ||
|
|
48833071d9 | ||
|
|
91ba212088 | ||
|
|
352fa88dfb | ||
|
|
8ee486ae33 | ||
|
|
e77ca8b92a | ||
|
|
4f456d8025 | ||
|
|
1312f12bcc | ||
|
|
c39343fd81 | ||
|
|
6a0c6b5978 | ||
|
|
7779edfeb1 | ||
|
|
b6c73a6d45 | ||
|
|
58099c8066 | ||
|
|
9c53889ba3 | ||
|
|
de8301e542 | ||
|
|
c470b663f7 | ||
|
|
9d6a7a8542 | ||
|
|
321b6c0585 | ||
|
|
90379ca84e | ||
|
|
609ac1e164 | ||
|
|
28d16f38d0 | ||
|
|
fc50ff0666 | ||
|
|
22b80e85ff | ||
|
|
45363e46ae | ||
|
|
8ce3c44c92 | ||
|
|
133771477c | ||
|
|
20e6dca1df | ||
|
|
aa8e8f83d0 | ||
|
|
c505333dab | ||
|
|
dc56b7c4fb | ||
|
|
bf359a445e | ||
|
|
9df7bfddcc | ||
|
|
7ce0425575 | ||
|
|
faf1e1fb4c | ||
|
|
61e68b3fbd |
@@ -62,6 +62,7 @@ common-obj-$(CONFIG_SPICE) += spice-qemu-char.o
|
||||
|
||||
common-obj-y += audio/
|
||||
common-obj-y += hw/
|
||||
common-obj-y += accel.o
|
||||
|
||||
common-obj-y += ui/
|
||||
common-obj-y += bt-host.o bt-vhci.o
|
||||
|
||||
@@ -127,7 +127,7 @@ endif #CONFIG_BSD_USER
|
||||
# System emulator target
|
||||
ifdef CONFIG_SOFTMMU
|
||||
obj-y += arch_init.o cpus.o monitor.o gdbstub.o balloon.o ioport.o numa.o
|
||||
obj-y += qtest.o
|
||||
obj-y += qtest.o bootdevice.o
|
||||
obj-y += hw/
|
||||
obj-$(CONFIG_FDT) += device_tree.o
|
||||
obj-$(CONFIG_KVM) += kvm-all.o
|
||||
|
||||
157
accel.c
Normal file
157
accel.c
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* QEMU System Emulator, accelerator interfaces
|
||||
*
|
||||
* Copyright (c) 2003-2008 Fabrice Bellard
|
||||
* Copyright (c) 2014 Red Hat Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "sysemu/accel.h"
|
||||
#include "hw/boards.h"
|
||||
#include "qemu-common.h"
|
||||
#include "sysemu/arch_init.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "hw/xen/xen.h"
|
||||
#include "qom/object.h"
|
||||
#include "hw/boards.h"
|
||||
|
||||
int tcg_tb_size;
|
||||
static bool tcg_allowed = true;
|
||||
|
||||
static int tcg_init(MachineState *ms)
|
||||
{
|
||||
tcg_exec_init(tcg_tb_size * 1024 * 1024);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const TypeInfo accel_type = {
|
||||
.name = TYPE_ACCEL,
|
||||
.parent = TYPE_OBJECT,
|
||||
.class_size = sizeof(AccelClass),
|
||||
.instance_size = sizeof(AccelState),
|
||||
};
|
||||
|
||||
/* Lookup AccelClass from opt_name. Returns NULL if not found */
|
||||
static AccelClass *accel_find(const char *opt_name)
|
||||
{
|
||||
char *class_name = g_strdup_printf(ACCEL_CLASS_NAME("%s"), opt_name);
|
||||
AccelClass *ac = ACCEL_CLASS(object_class_by_name(class_name));
|
||||
g_free(class_name);
|
||||
return ac;
|
||||
}
|
||||
|
||||
static int accel_init_machine(AccelClass *acc, MachineState *ms)
|
||||
{
|
||||
ObjectClass *oc = OBJECT_CLASS(acc);
|
||||
const char *cname = object_class_get_name(oc);
|
||||
AccelState *accel = ACCEL(object_new(cname));
|
||||
int ret;
|
||||
ms->accelerator = accel;
|
||||
*(acc->allowed) = true;
|
||||
ret = acc->init_machine(ms);
|
||||
if (ret < 0) {
|
||||
ms->accelerator = NULL;
|
||||
*(acc->allowed) = false;
|
||||
object_unref(OBJECT(accel));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int configure_accelerator(MachineState *ms)
|
||||
{
|
||||
const char *p;
|
||||
char buf[10];
|
||||
int ret;
|
||||
bool accel_initialised = false;
|
||||
bool init_failed = false;
|
||||
AccelClass *acc = NULL;
|
||||
|
||||
p = qemu_opt_get(qemu_get_machine_opts(), "accel");
|
||||
if (p == NULL) {
|
||||
/* Use the default "accelerator", tcg */
|
||||
p = "tcg";
|
||||
}
|
||||
|
||||
while (!accel_initialised && *p != '\0') {
|
||||
if (*p == ':') {
|
||||
p++;
|
||||
}
|
||||
p = get_opt_name(buf, sizeof(buf), p, ':');
|
||||
acc = accel_find(buf);
|
||||
if (!acc) {
|
||||
fprintf(stderr, "\"%s\" accelerator not found.\n", buf);
|
||||
continue;
|
||||
}
|
||||
if (acc->available && !acc->available()) {
|
||||
printf("%s not supported for this target\n",
|
||||
acc->name);
|
||||
continue;
|
||||
}
|
||||
ret = accel_init_machine(acc, ms);
|
||||
if (ret < 0) {
|
||||
init_failed = true;
|
||||
fprintf(stderr, "failed to initialize %s: %s\n",
|
||||
acc->name,
|
||||
strerror(-ret));
|
||||
} else {
|
||||
accel_initialised = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!accel_initialised) {
|
||||
if (!init_failed) {
|
||||
fprintf(stderr, "No accelerator found!\n");
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (init_failed) {
|
||||
fprintf(stderr, "Back to %s accelerator.\n", acc->name);
|
||||
}
|
||||
|
||||
return !accel_initialised;
|
||||
}
|
||||
|
||||
|
||||
static void tcg_accel_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
AccelClass *ac = ACCEL_CLASS(oc);
|
||||
ac->name = "tcg";
|
||||
ac->init_machine = tcg_init;
|
||||
ac->allowed = &tcg_allowed;
|
||||
}
|
||||
|
||||
#define TYPE_TCG_ACCEL ACCEL_CLASS_NAME("tcg")
|
||||
|
||||
static const TypeInfo tcg_accel_type = {
|
||||
.name = TYPE_TCG_ACCEL,
|
||||
.parent = TYPE_ACCEL,
|
||||
.class_init = tcg_accel_class_init,
|
||||
};
|
||||
|
||||
static void register_accel_types(void)
|
||||
{
|
||||
type_register_static(&accel_type);
|
||||
type_register_static(&tcg_accel_type);
|
||||
}
|
||||
|
||||
type_init(register_accel_types);
|
||||
@@ -1337,11 +1337,6 @@ void cpudef_init(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
int tcg_available(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int kvm_available(void)
|
||||
{
|
||||
#ifdef CONFIG_KVM
|
||||
|
||||
9
block.c
9
block.c
@@ -335,18 +335,13 @@ void bdrv_register(BlockDriver *bdrv)
|
||||
QLIST_INSERT_HEAD(&bdrv_drivers, bdrv, list);
|
||||
}
|
||||
|
||||
static bool bdrv_is_valid_name(const char *name)
|
||||
{
|
||||
return qemu_opts_id_wellformed(name);
|
||||
}
|
||||
|
||||
/* create a new block device (by default it is empty) */
|
||||
BlockDriverState *bdrv_new(const char *device_name, Error **errp)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
int i;
|
||||
|
||||
if (*device_name && !bdrv_is_valid_name(device_name)) {
|
||||
if (*device_name && !id_wellformed(device_name)) {
|
||||
error_setg(errp, "Invalid device name");
|
||||
return NULL;
|
||||
}
|
||||
@@ -874,7 +869,7 @@ static void bdrv_assign_node_name(BlockDriverState *bs,
|
||||
}
|
||||
|
||||
/* Check for empty string or invalid characters */
|
||||
if (!bdrv_is_valid_name(node_name)) {
|
||||
if (!id_wellformed(node_name)) {
|
||||
error_setg(errp, "Invalid node name");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -316,6 +316,13 @@ static bool is_request_lun_aligned(int64_t sector_num, int nb_sectors,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static unsigned long *iscsi_allocationmap_init(IscsiLun *iscsilun)
|
||||
{
|
||||
return bitmap_try_new(DIV_ROUND_UP(sector_lun2qemu(iscsilun->num_blocks,
|
||||
iscsilun),
|
||||
iscsilun->cluster_sectors));
|
||||
}
|
||||
|
||||
static void iscsi_allocationmap_set(IscsiLun *iscsilun, int64_t sector_num,
|
||||
int nb_sectors)
|
||||
{
|
||||
@@ -1402,9 +1409,10 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
iscsilun->cluster_sectors = (iscsilun->bl.opt_unmap_gran *
|
||||
iscsilun->block_size) >> BDRV_SECTOR_BITS;
|
||||
if (iscsilun->lbprz && !(bs->open_flags & BDRV_O_NOCACHE)) {
|
||||
iscsilun->allocationmap =
|
||||
bitmap_new(DIV_ROUND_UP(bs->total_sectors,
|
||||
iscsilun->cluster_sectors));
|
||||
iscsilun->allocationmap = iscsi_allocationmap_init(iscsilun);
|
||||
if (iscsilun->allocationmap == NULL) {
|
||||
ret = -ENOMEM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1497,10 +1505,7 @@ static int iscsi_truncate(BlockDriverState *bs, int64_t offset)
|
||||
|
||||
if (iscsilun->allocationmap != NULL) {
|
||||
g_free(iscsilun->allocationmap);
|
||||
iscsilun->allocationmap =
|
||||
bitmap_new(DIV_ROUND_UP(sector_lun2qemu(iscsilun->num_blocks,
|
||||
iscsilun),
|
||||
iscsilun->cluster_sectors));
|
||||
iscsilun->allocationmap = iscsi_allocationmap_init(iscsilun);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -2282,6 +2282,9 @@ static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs)
|
||||
.lazy_refcounts = s->compatible_features &
|
||||
QCOW2_COMPAT_LAZY_REFCOUNTS,
|
||||
.has_lazy_refcounts = true,
|
||||
.corrupt = s->incompatible_features &
|
||||
QCOW2_INCOMPAT_CORRUPT,
|
||||
.has_corrupt = true,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
10
block/ssh.c
10
block/ssh.c
@@ -517,6 +517,11 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options,
|
||||
const char *host, *user, *path, *host_key_check;
|
||||
int port;
|
||||
|
||||
if (!qdict_haskey(options, "host")) {
|
||||
ret = -EINVAL;
|
||||
error_setg(errp, "No hostname was specified");
|
||||
goto err;
|
||||
}
|
||||
host = qdict_get_str(options, "host");
|
||||
|
||||
if (qdict_haskey(options, "port")) {
|
||||
@@ -525,6 +530,11 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options,
|
||||
port = 22;
|
||||
}
|
||||
|
||||
if (!qdict_haskey(options, "path")) {
|
||||
ret = -EINVAL;
|
||||
error_setg(errp, "No path was specified");
|
||||
goto err;
|
||||
}
|
||||
path = qdict_get_str(options, "path");
|
||||
|
||||
if (qdict_haskey(options, "user")) {
|
||||
|
||||
@@ -1113,7 +1113,7 @@ static int get_cluster_offset(BlockDriverState *bs,
|
||||
uint32_t min_count, *l2_table;
|
||||
bool zeroed = false;
|
||||
int64_t ret;
|
||||
int32_t cluster_sector;
|
||||
int64_t cluster_sector;
|
||||
|
||||
if (m_data) {
|
||||
m_data->valid = 0;
|
||||
|
||||
72
blockdev.c
72
blockdev.c
@@ -60,7 +60,7 @@ static const char *const if_name[IF_COUNT] = {
|
||||
[IF_XEN] = "xen",
|
||||
};
|
||||
|
||||
static const int if_max_devs[IF_COUNT] = {
|
||||
static int if_max_devs[IF_COUNT] = {
|
||||
/*
|
||||
* Do not change these numbers! They govern how drive option
|
||||
* index maps to unit and bus. That mapping is ABI.
|
||||
@@ -79,6 +79,30 @@ static const int if_max_devs[IF_COUNT] = {
|
||||
[IF_SCSI] = 7,
|
||||
};
|
||||
|
||||
/**
|
||||
* Boards may call this to offer board-by-board overrides
|
||||
* of the default, global values.
|
||||
*/
|
||||
void override_max_devs(BlockInterfaceType type, int max_devs)
|
||||
{
|
||||
DriveInfo *dinfo;
|
||||
|
||||
if (max_devs <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
QTAILQ_FOREACH(dinfo, &drives, next) {
|
||||
if (dinfo->type == type) {
|
||||
fprintf(stderr, "Cannot override units-per-bus property of"
|
||||
" the %s interface, because a drive of that type has"
|
||||
" already been added.\n", if_name[type]);
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
if_max_devs[type] = max_devs;
|
||||
}
|
||||
|
||||
/*
|
||||
* We automatically delete the drive when a device using it gets
|
||||
* unplugged. Questionable feature, but we can't just drop it.
|
||||
@@ -111,6 +135,23 @@ void blockdev_auto_del(BlockDriverState *bs)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current mapping of how many units per bus
|
||||
* a particular interface can support.
|
||||
*
|
||||
* A positive integer indicates n units per bus.
|
||||
* 0 implies the mapping has not been established.
|
||||
* -1 indicates an invalid BlockInterfaceType was given.
|
||||
*/
|
||||
int drive_get_max_devs(BlockInterfaceType type)
|
||||
{
|
||||
if (type >= IF_IDE && type < IF_COUNT) {
|
||||
return if_max_devs[type];
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int drive_index_to_bus_id(BlockInterfaceType type, int index)
|
||||
{
|
||||
int max_devs = if_max_devs[type];
|
||||
@@ -166,6 +207,27 @@ DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool drive_check_orphaned(void)
|
||||
{
|
||||
DriveInfo *dinfo;
|
||||
bool rs = false;
|
||||
|
||||
QTAILQ_FOREACH(dinfo, &drives, next) {
|
||||
/* If dinfo->bdrv->dev is NULL, it has no device attached. */
|
||||
/* Unless this is a default drive, this may be an oversight. */
|
||||
if (!dinfo->bdrv->dev && !dinfo->is_default &&
|
||||
dinfo->type != IF_NONE) {
|
||||
fprintf(stderr, "Warning: Orphaned drive without device: "
|
||||
"id=%s,file=%s,if=%s,bus=%d,unit=%d\n",
|
||||
dinfo->id, dinfo->bdrv->filename, if_name[dinfo->type],
|
||||
dinfo->bus, dinfo->unit);
|
||||
rs = true;
|
||||
}
|
||||
}
|
||||
|
||||
return rs;
|
||||
}
|
||||
|
||||
DriveInfo *drive_get_by_index(BlockInterfaceType type, int index)
|
||||
{
|
||||
return drive_get(type,
|
||||
@@ -224,9 +286,7 @@ void drive_info_del(DriveInfo *dinfo)
|
||||
if (!dinfo) {
|
||||
return;
|
||||
}
|
||||
if (dinfo->opts) {
|
||||
qemu_opts_del(dinfo->opts);
|
||||
}
|
||||
qemu_opts_del(dinfo->opts);
|
||||
g_free(dinfo->id);
|
||||
QTAILQ_REMOVE(&drives, dinfo, next);
|
||||
g_free(dinfo->serial);
|
||||
@@ -550,6 +610,10 @@ static void qemu_opt_rename(QemuOpts *opts, const char *from, const char *to,
|
||||
"same time", to, from);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* rename all items in opts */
|
||||
while ((value = qemu_opt_get(opts, from))) {
|
||||
qemu_opt_set(opts, to, value);
|
||||
qemu_opt_unset(opts, from);
|
||||
}
|
||||
|
||||
258
bootdevice.c
Normal file
258
bootdevice.c
Normal file
@@ -0,0 +1,258 @@
|
||||
/*
|
||||
* QEMU Boot Device Implement
|
||||
*
|
||||
* Copyright (c) 2014 HUAWEI TECHNOLOGIES CO.,LTD.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
typedef struct FWBootEntry FWBootEntry;
|
||||
|
||||
struct FWBootEntry {
|
||||
QTAILQ_ENTRY(FWBootEntry) link;
|
||||
int32_t bootindex;
|
||||
DeviceState *dev;
|
||||
char *suffix;
|
||||
};
|
||||
|
||||
static QTAILQ_HEAD(, FWBootEntry) fw_boot_order =
|
||||
QTAILQ_HEAD_INITIALIZER(fw_boot_order);
|
||||
|
||||
void check_boot_index(int32_t bootindex, Error **errp)
|
||||
{
|
||||
FWBootEntry *i;
|
||||
|
||||
if (bootindex >= 0) {
|
||||
QTAILQ_FOREACH(i, &fw_boot_order, link) {
|
||||
if (i->bootindex == bootindex) {
|
||||
error_setg(errp, "The bootindex %d has already been used",
|
||||
bootindex);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void del_boot_device_path(DeviceState *dev, const char *suffix)
|
||||
{
|
||||
FWBootEntry *i;
|
||||
|
||||
if (dev == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
QTAILQ_FOREACH(i, &fw_boot_order, link) {
|
||||
if ((!suffix || !g_strcmp0(i->suffix, suffix)) &&
|
||||
i->dev == dev) {
|
||||
QTAILQ_REMOVE(&fw_boot_order, i, link);
|
||||
g_free(i->suffix);
|
||||
g_free(i);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void add_boot_device_path(int32_t bootindex, DeviceState *dev,
|
||||
const char *suffix)
|
||||
{
|
||||
FWBootEntry *node, *i;
|
||||
|
||||
if (bootindex < 0) {
|
||||
del_boot_device_path(dev, suffix);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(dev != NULL || suffix != NULL);
|
||||
|
||||
del_boot_device_path(dev, suffix);
|
||||
|
||||
node = g_malloc0(sizeof(FWBootEntry));
|
||||
node->bootindex = bootindex;
|
||||
node->suffix = g_strdup(suffix);
|
||||
node->dev = dev;
|
||||
|
||||
QTAILQ_FOREACH(i, &fw_boot_order, link) {
|
||||
if (i->bootindex == bootindex) {
|
||||
error_report("Two devices with same boot index %d", bootindex);
|
||||
exit(1);
|
||||
} else if (i->bootindex < bootindex) {
|
||||
continue;
|
||||
}
|
||||
QTAILQ_INSERT_BEFORE(i, node, link);
|
||||
return;
|
||||
}
|
||||
QTAILQ_INSERT_TAIL(&fw_boot_order, node, link);
|
||||
}
|
||||
|
||||
DeviceState *get_boot_device(uint32_t position)
|
||||
{
|
||||
uint32_t counter = 0;
|
||||
FWBootEntry *i = NULL;
|
||||
DeviceState *res = NULL;
|
||||
|
||||
if (!QTAILQ_EMPTY(&fw_boot_order)) {
|
||||
QTAILQ_FOREACH(i, &fw_boot_order, link) {
|
||||
if (counter == position) {
|
||||
res = i->dev;
|
||||
break;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function returns null terminated string that consist of new line
|
||||
* separated device paths.
|
||||
*
|
||||
* memory pointed by "size" is assigned total length of the array in bytes
|
||||
*
|
||||
*/
|
||||
char *get_boot_devices_list(size_t *size, bool ignore_suffixes)
|
||||
{
|
||||
FWBootEntry *i;
|
||||
size_t total = 0;
|
||||
char *list = NULL;
|
||||
|
||||
QTAILQ_FOREACH(i, &fw_boot_order, link) {
|
||||
char *devpath = NULL, *bootpath;
|
||||
size_t len;
|
||||
|
||||
if (i->dev) {
|
||||
devpath = qdev_get_fw_dev_path(i->dev);
|
||||
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 (total) {
|
||||
list[total-1] = '\n';
|
||||
}
|
||||
len = strlen(bootpath) + 1;
|
||||
list = g_realloc(list, total + len);
|
||||
memcpy(&list[total], bootpath, len);
|
||||
total += len;
|
||||
g_free(bootpath);
|
||||
}
|
||||
|
||||
*size = total;
|
||||
|
||||
if (boot_strict && *size > 0) {
|
||||
list[total-1] = '\n';
|
||||
list = g_realloc(list, total + 5);
|
||||
memcpy(&list[total], "HALT", 5);
|
||||
*size = total + 5;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int32_t *bootindex;
|
||||
const char *suffix;
|
||||
DeviceState *dev;
|
||||
} BootIndexProperty;
|
||||
|
||||
static void device_get_bootindex(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
BootIndexProperty *prop = opaque;
|
||||
visit_type_int32(v, prop->bootindex, name, errp);
|
||||
}
|
||||
|
||||
static void device_set_bootindex(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
BootIndexProperty *prop = opaque;
|
||||
int32_t boot_index;
|
||||
Error *local_err = NULL;
|
||||
|
||||
visit_type_int32(v, &boot_index, name, &local_err);
|
||||
if (local_err) {
|
||||
goto out;
|
||||
}
|
||||
/* check whether bootindex is present in fw_boot_order list */
|
||||
check_boot_index(boot_index, &local_err);
|
||||
if (local_err) {
|
||||
goto out;
|
||||
}
|
||||
/* change bootindex to a new one */
|
||||
*prop->bootindex = boot_index;
|
||||
|
||||
add_boot_device_path(*prop->bootindex, prop->dev, prop->suffix);
|
||||
|
||||
out:
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
}
|
||||
}
|
||||
|
||||
static void property_release_bootindex(Object *obj, const char *name,
|
||||
void *opaque)
|
||||
|
||||
{
|
||||
BootIndexProperty *prop = opaque;
|
||||
|
||||
del_boot_device_path(prop->dev, prop->suffix);
|
||||
g_free(prop);
|
||||
}
|
||||
|
||||
void device_add_bootindex_property(Object *obj, int32_t *bootindex,
|
||||
const char *name, const char *suffix,
|
||||
DeviceState *dev, Error **errp)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
BootIndexProperty *prop = g_malloc0(sizeof(*prop));
|
||||
|
||||
prop->bootindex = bootindex;
|
||||
prop->suffix = suffix;
|
||||
prop->dev = dev;
|
||||
|
||||
object_property_add(obj, name, "int32",
|
||||
device_get_bootindex,
|
||||
device_set_bootindex,
|
||||
property_release_bootindex,
|
||||
prop, &local_err);
|
||||
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
g_free(prop);
|
||||
return;
|
||||
}
|
||||
/* initialize devices' bootindex property to -1 */
|
||||
object_property_set_int(obj, -1, name, NULL);
|
||||
}
|
||||
@@ -1175,15 +1175,11 @@ static const struct sparc_opcode sparc_opcodes[] = {
|
||||
{ "subcc", F3(2, 0x14, 0), F3(~2, ~0x14, ~0)|ASI(~0), "1,2,d", 0, v6 },
|
||||
{ "subcc", F3(2, 0x14, 1), F3(~2, ~0x14, ~1), "1,i,d", 0, v6 },
|
||||
|
||||
{ "subx", F3(2, 0x0c, 0), F3(~2, ~0x0c, ~0)|ASI(~0), "1,2,d", 0, v6notv9 },
|
||||
{ "subx", F3(2, 0x0c, 1), F3(~2, ~0x0c, ~1), "1,i,d", 0, v6notv9 },
|
||||
{ "subc", F3(2, 0x0c, 0), F3(~2, ~0x0c, ~0)|ASI(~0), "1,2,d", 0, v9 },
|
||||
{ "subc", F3(2, 0x0c, 1), F3(~2, ~0x0c, ~1), "1,i,d", 0, v9 },
|
||||
{ "subc", F3(2, 0x0c, 0), F3(~2, ~0x0c, ~0)|ASI(~0), "1,2,d", 0, v6 },
|
||||
{ "subc", F3(2, 0x0c, 1), F3(~2, ~0x0c, ~1), "1,i,d", 0, v6 },
|
||||
|
||||
{ "subxcc", F3(2, 0x1c, 0), F3(~2, ~0x1c, ~0)|ASI(~0), "1,2,d", 0, v6notv9 },
|
||||
{ "subxcc", F3(2, 0x1c, 1), F3(~2, ~0x1c, ~1), "1,i,d", 0, v6notv9 },
|
||||
{ "subccc", F3(2, 0x1c, 0), F3(~2, ~0x1c, ~0)|ASI(~0), "1,2,d", 0, v9 },
|
||||
{ "subccc", F3(2, 0x1c, 1), F3(~2, ~0x1c, ~1), "1,i,d", 0, v9 },
|
||||
{ "subccc", F3(2, 0x1c, 0), F3(~2, ~0x1c, ~0)|ASI(~0), "1,2,d", 0, v6 },
|
||||
{ "subccc", F3(2, 0x1c, 1), F3(~2, ~0x1c, ~1), "1,i,d", 0, v6 },
|
||||
|
||||
{ "and", F3(2, 0x01, 0), F3(~2, ~0x01, ~0)|ASI(~0), "1,2,d", 0, v6 },
|
||||
{ "and", F3(2, 0x01, 1), F3(~2, ~0x01, ~1), "1,i,d", 0, v6 },
|
||||
@@ -1215,19 +1211,13 @@ static const struct sparc_opcode sparc_opcodes[] = {
|
||||
{ "addcc", F3(2, 0x10, 1), F3(~2, ~0x10, ~1), "1,i,d", 0, v6 },
|
||||
{ "addcc", F3(2, 0x10, 1), F3(~2, ~0x10, ~1), "i,1,d", 0, v6 },
|
||||
|
||||
{ "addx", F3(2, 0x08, 0), F3(~2, ~0x08, ~0)|ASI(~0), "1,2,d", 0, v6notv9 },
|
||||
{ "addx", F3(2, 0x08, 1), F3(~2, ~0x08, ~1), "1,i,d", 0, v6notv9 },
|
||||
{ "addx", F3(2, 0x08, 1), F3(~2, ~0x08, ~1), "i,1,d", 0, v6notv9 },
|
||||
{ "addc", F3(2, 0x08, 0), F3(~2, ~0x08, ~0)|ASI(~0), "1,2,d", 0, v9 },
|
||||
{ "addc", F3(2, 0x08, 1), F3(~2, ~0x08, ~1), "1,i,d", 0, v9 },
|
||||
{ "addc", F3(2, 0x08, 1), F3(~2, ~0x08, ~1), "i,1,d", 0, v9 },
|
||||
{ "addc", F3(2, 0x08, 0), F3(~2, ~0x08, ~0)|ASI(~0), "1,2,d", 0, v6 },
|
||||
{ "addc", F3(2, 0x08, 1), F3(~2, ~0x08, ~1), "1,i,d", 0, v6 },
|
||||
{ "addc", F3(2, 0x08, 1), F3(~2, ~0x08, ~1), "i,1,d", 0, v6 },
|
||||
|
||||
{ "addxcc", F3(2, 0x18, 0), F3(~2, ~0x18, ~0)|ASI(~0), "1,2,d", 0, v6notv9 },
|
||||
{ "addxcc", F3(2, 0x18, 1), F3(~2, ~0x18, ~1), "1,i,d", 0, v6notv9 },
|
||||
{ "addxcc", F3(2, 0x18, 1), F3(~2, ~0x18, ~1), "i,1,d", 0, v6notv9 },
|
||||
{ "addccc", F3(2, 0x18, 0), F3(~2, ~0x18, ~0)|ASI(~0), "1,2,d", 0, v9 },
|
||||
{ "addccc", F3(2, 0x18, 1), F3(~2, ~0x18, ~1), "1,i,d", 0, v9 },
|
||||
{ "addccc", F3(2, 0x18, 1), F3(~2, ~0x18, ~1), "i,1,d", 0, v9 },
|
||||
{ "addccc", F3(2, 0x18, 0), F3(~2, ~0x18, ~0)|ASI(~0), "1,2,d", 0, v6 },
|
||||
{ "addccc", F3(2, 0x18, 1), F3(~2, ~0x18, ~1), "1,i,d", 0, v6 },
|
||||
{ "addccc", F3(2, 0x18, 1), F3(~2, ~0x18, ~1), "i,1,d", 0, v6 },
|
||||
|
||||
{ "smul", F3(2, 0x0b, 0), F3(~2, ~0x0b, ~0)|ASI(~0), "1,2,d", 0, v8 },
|
||||
{ "smul", F3(2, 0x0b, 1), F3(~2, ~0x0b, ~1), "1,i,d", 0, v8 },
|
||||
@@ -2042,6 +2032,10 @@ IMPDEP ("impdep2", 0x37),
|
||||
|
||||
#undef IMPDEP
|
||||
|
||||
{ "addxc", F3F(2, 0x36, 0x011), F3F(~2, ~0x36, ~0x011), "1,2,d", 0, v9b },
|
||||
{ "addxccc", F3F(2, 0x36, 0x013), F3F(~2, ~0x36, ~0x013), "1,2,d", 0, v9b },
|
||||
{ "umulxhi", F3F(2, 0x36, 0x016), F3F(~2, ~0x36, ~0x016), "1,2,d", 0, v9b },
|
||||
|
||||
};
|
||||
|
||||
static const int sparc_num_opcodes = ((sizeof sparc_opcodes)/(sizeof sparc_opcodes[0]));
|
||||
|
||||
32
gdbstub.c
32
gdbstub.c
@@ -625,11 +625,23 @@ void gdb_register_coprocessor(CPUState *cpu,
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
static const int xlat_gdb_type[] = {
|
||||
[GDB_WATCHPOINT_WRITE] = BP_GDB | BP_MEM_WRITE,
|
||||
[GDB_WATCHPOINT_READ] = BP_GDB | BP_MEM_READ,
|
||||
[GDB_WATCHPOINT_ACCESS] = BP_GDB | BP_MEM_ACCESS,
|
||||
};
|
||||
/* Translate GDB watchpoint type to a flags value for cpu_watchpoint_* */
|
||||
static inline int xlat_gdb_type(CPUState *cpu, int gdbtype)
|
||||
{
|
||||
static const int xlat[] = {
|
||||
[GDB_WATCHPOINT_WRITE] = BP_GDB | BP_MEM_WRITE,
|
||||
[GDB_WATCHPOINT_READ] = BP_GDB | BP_MEM_READ,
|
||||
[GDB_WATCHPOINT_ACCESS] = BP_GDB | BP_MEM_ACCESS,
|
||||
};
|
||||
|
||||
CPUClass *cc = CPU_GET_CLASS(cpu);
|
||||
int cputype = xlat[gdbtype];
|
||||
|
||||
if (cc->gdb_stop_before_watchpoint) {
|
||||
cputype |= BP_STOP_BEFORE_ACCESS;
|
||||
}
|
||||
return cputype;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type)
|
||||
@@ -656,10 +668,11 @@ static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type)
|
||||
case GDB_WATCHPOINT_READ:
|
||||
case GDB_WATCHPOINT_ACCESS:
|
||||
CPU_FOREACH(cpu) {
|
||||
err = cpu_watchpoint_insert(cpu, addr, len, xlat_gdb_type[type],
|
||||
NULL);
|
||||
if (err)
|
||||
err = cpu_watchpoint_insert(cpu, addr, len,
|
||||
xlat_gdb_type(cpu, type), NULL);
|
||||
if (err) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
#endif
|
||||
@@ -692,7 +705,8 @@ static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type)
|
||||
case GDB_WATCHPOINT_READ:
|
||||
case GDB_WATCHPOINT_ACCESS:
|
||||
CPU_FOREACH(cpu) {
|
||||
err = cpu_watchpoint_remove(cpu, addr, len, xlat_gdb_type[type]);
|
||||
err = cpu_watchpoint_remove(cpu, addr, len,
|
||||
xlat_gdb_type(cpu, type));
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ static void clipper_init(MachineState *machine)
|
||||
/* IDE disk setup. */
|
||||
{
|
||||
DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
|
||||
ide_drive_get(hd, MAX_IDE_BUS);
|
||||
ide_drive_get(hd, ARRAY_SIZE(hd));
|
||||
|
||||
pci_cmd646_ide_init(pci_bus, hd, 0);
|
||||
}
|
||||
|
||||
@@ -1321,9 +1321,9 @@ static const MemoryRegionOps ac97_io_nabm_ops = {
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
static void ac97_on_reset (void *opaque)
|
||||
static void ac97_on_reset (DeviceState *dev)
|
||||
{
|
||||
AC97LinkState *s = opaque;
|
||||
AC97LinkState *s = container_of(dev, AC97LinkState, dev.qdev);
|
||||
|
||||
reset_bm_regs (s, &s->bm_regs[0]);
|
||||
reset_bm_regs (s, &s->bm_regs[1]);
|
||||
@@ -1382,9 +1382,8 @@ static int ac97_initfn (PCIDevice *dev)
|
||||
"ac97-nabm", 256);
|
||||
pci_register_bar (&s->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_nam);
|
||||
pci_register_bar (&s->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->io_nabm);
|
||||
qemu_register_reset (ac97_on_reset, s);
|
||||
AUD_register_card ("ac97", &s->card);
|
||||
ac97_on_reset (s);
|
||||
ac97_on_reset (&s->dev.qdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1413,6 +1412,7 @@ static void ac97_class_init (ObjectClass *klass, void *data)
|
||||
dc->desc = "Intel 82801AA AC97 Audio";
|
||||
dc->vmsd = &vmstate_ac97;
|
||||
dc->props = ac97_properties;
|
||||
dc->reset = ac97_on_reset;
|
||||
}
|
||||
|
||||
static const TypeInfo ac97_info = {
|
||||
|
||||
@@ -2216,9 +2216,6 @@ static void isabus_fdc_realize(DeviceState *dev, Error **errp)
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
|
||||
add_boot_device_path(isa->bootindexA, dev, "/floppy@0");
|
||||
add_boot_device_path(isa->bootindexB, dev, "/floppy@1");
|
||||
}
|
||||
|
||||
static void sysbus_fdc_initfn(Object *obj)
|
||||
@@ -2291,8 +2288,6 @@ static Property isa_fdc_properties[] = {
|
||||
DEFINE_PROP_UINT32("dma", FDCtrlISABus, dma, 2),
|
||||
DEFINE_PROP_DRIVE("driveA", FDCtrlISABus, state.drives[0].bs),
|
||||
DEFINE_PROP_DRIVE("driveB", FDCtrlISABus, state.drives[1].bs),
|
||||
DEFINE_PROP_INT32("bootindexA", FDCtrlISABus, bootindexA, -1),
|
||||
DEFINE_PROP_INT32("bootindexB", FDCtrlISABus, bootindexB, -1),
|
||||
DEFINE_PROP_BIT("check_media_rate", FDCtrlISABus, state.check_media_rate,
|
||||
0, true),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
@@ -2310,11 +2305,24 @@ static void isabus_fdc_class_init(ObjectClass *klass, void *data)
|
||||
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
|
||||
}
|
||||
|
||||
static void isabus_fdc_instance_init(Object *obj)
|
||||
{
|
||||
FDCtrlISABus *isa = ISA_FDC(obj);
|
||||
|
||||
device_add_bootindex_property(obj, &isa->bootindexA,
|
||||
"bootindexA", "/floppy@0",
|
||||
DEVICE(obj), NULL);
|
||||
device_add_bootindex_property(obj, &isa->bootindexB,
|
||||
"bootindexB", "/floppy@1",
|
||||
DEVICE(obj), NULL);
|
||||
}
|
||||
|
||||
static const TypeInfo isa_fdc_info = {
|
||||
.name = TYPE_ISA_FDC,
|
||||
.parent = TYPE_ISA_DEVICE,
|
||||
.instance_size = sizeof(FDCtrlISABus),
|
||||
.class_init = isabus_fdc_class_init,
|
||||
.instance_init = isabus_fdc_instance_init,
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_sysbus_fdc ={
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include <hw/hw.h>
|
||||
#include <hw/pci/msix.h>
|
||||
#include <hw/pci/pci.h>
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qapi/visitor.h"
|
||||
|
||||
#include "nvme.h"
|
||||
|
||||
@@ -871,11 +873,53 @@ static void nvme_class_init(ObjectClass *oc, void *data)
|
||||
dc->vmsd = &nvme_vmstate;
|
||||
}
|
||||
|
||||
static void nvme_get_bootindex(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
NvmeCtrl *s = NVME(obj);
|
||||
|
||||
visit_type_int32(v, &s->conf.bootindex, name, errp);
|
||||
}
|
||||
|
||||
static void nvme_set_bootindex(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
NvmeCtrl *s = NVME(obj);
|
||||
int32_t boot_index;
|
||||
Error *local_err = NULL;
|
||||
|
||||
visit_type_int32(v, &boot_index, name, &local_err);
|
||||
if (local_err) {
|
||||
goto out;
|
||||
}
|
||||
/* check whether bootindex is present in fw_boot_order list */
|
||||
check_boot_index(boot_index, &local_err);
|
||||
if (local_err) {
|
||||
goto out;
|
||||
}
|
||||
/* change bootindex to a new one */
|
||||
s->conf.bootindex = boot_index;
|
||||
|
||||
out:
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
}
|
||||
}
|
||||
|
||||
static void nvme_instance_init(Object *obj)
|
||||
{
|
||||
object_property_add(obj, "bootindex", "int32",
|
||||
nvme_get_bootindex,
|
||||
nvme_set_bootindex, NULL, NULL, NULL);
|
||||
object_property_set_int(obj, -1, "bootindex", NULL);
|
||||
}
|
||||
|
||||
static const TypeInfo nvme_info = {
|
||||
.name = "nvme",
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(NvmeCtrl),
|
||||
.class_init = nvme_class_init,
|
||||
.instance_init = nvme_instance_init,
|
||||
};
|
||||
|
||||
static void nvme_register_types(void)
|
||||
|
||||
@@ -768,8 +768,6 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
|
||||
bdrv_set_guest_block_size(s->bs, s->conf->logical_block_size);
|
||||
|
||||
bdrv_iostatus_enable(s->bs);
|
||||
|
||||
add_boot_device_path(s->conf->bootindex, dev, "/disk@0,0");
|
||||
}
|
||||
|
||||
static void virtio_blk_device_unrealize(DeviceState *dev, Error **errp)
|
||||
@@ -794,6 +792,9 @@ static void virtio_blk_instance_init(Object *obj)
|
||||
(Object **)&s->blk.iothread,
|
||||
qdev_prop_allow_set_link_before_realize,
|
||||
OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL);
|
||||
device_add_bootindex_property(obj, &s->blk.conf.bootindex,
|
||||
"bootindex", "/disk@0,0",
|
||||
DEVICE(obj), NULL);
|
||||
}
|
||||
|
||||
static Property virtio_blk_properties[] = {
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "hw/hw.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "ui/console.h"
|
||||
#include "ui/pixel_ops.h"
|
||||
#include "vga_int.h"
|
||||
#include "hw/loader.h"
|
||||
|
||||
@@ -2170,20 +2171,44 @@ static void cirrus_cursor_invalidate(VGACommonState *s1)
|
||||
}
|
||||
}
|
||||
|
||||
#define DEPTH 8
|
||||
#include "cirrus_vga_template.h"
|
||||
static void vga_draw_cursor_line(uint8_t *d1,
|
||||
const uint8_t *src1,
|
||||
int poffset, int w,
|
||||
unsigned int color0,
|
||||
unsigned int color1,
|
||||
unsigned int color_xor)
|
||||
{
|
||||
const uint8_t *plane0, *plane1;
|
||||
int x, b0, b1;
|
||||
uint8_t *d;
|
||||
|
||||
#define DEPTH 16
|
||||
#include "cirrus_vga_template.h"
|
||||
|
||||
#define DEPTH 32
|
||||
#include "cirrus_vga_template.h"
|
||||
d = d1;
|
||||
plane0 = src1;
|
||||
plane1 = src1 + poffset;
|
||||
for (x = 0; x < w; x++) {
|
||||
b0 = (plane0[x >> 3] >> (7 - (x & 7))) & 1;
|
||||
b1 = (plane1[x >> 3] >> (7 - (x & 7))) & 1;
|
||||
switch (b0 | (b1 << 1)) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
((uint32_t *)d)[0] ^= color_xor;
|
||||
break;
|
||||
case 2:
|
||||
((uint32_t *)d)[0] = color0;
|
||||
break;
|
||||
case 3:
|
||||
((uint32_t *)d)[0] = color1;
|
||||
break;
|
||||
}
|
||||
d += 4;
|
||||
}
|
||||
}
|
||||
|
||||
static void cirrus_cursor_draw_line(VGACommonState *s1, uint8_t *d1, int scr_y)
|
||||
{
|
||||
CirrusVGAState *s = container_of(s1, CirrusVGAState, vga);
|
||||
DisplaySurface *surface = qemu_console_surface(s->vga.con);
|
||||
int w, h, bpp, x1, x2, poffset;
|
||||
int w, h, x1, x2, poffset;
|
||||
unsigned int color0, color1;
|
||||
const uint8_t *palette, *src;
|
||||
uint32_t content;
|
||||
@@ -2212,6 +2237,8 @@ static void cirrus_cursor_draw_line(VGACommonState *s1, uint8_t *d1, int scr_y)
|
||||
} else {
|
||||
src += (s->vga.sr[0x13] & 0x3f) * 256;
|
||||
src += (scr_y - s->hw_cursor_y) * 4;
|
||||
|
||||
|
||||
poffset = 128;
|
||||
content = ((uint32_t *)src)[0] |
|
||||
((uint32_t *)(src + 128))[0];
|
||||
@@ -2229,30 +2256,14 @@ static void cirrus_cursor_draw_line(VGACommonState *s1, uint8_t *d1, int scr_y)
|
||||
x2 = s->vga.last_scr_width;
|
||||
w = x2 - x1;
|
||||
palette = s->cirrus_hidden_palette;
|
||||
color0 = s->vga.rgb_to_pixel(c6_to_8(palette[0x0 * 3]),
|
||||
c6_to_8(palette[0x0 * 3 + 1]),
|
||||
c6_to_8(palette[0x0 * 3 + 2]));
|
||||
color1 = s->vga.rgb_to_pixel(c6_to_8(palette[0xf * 3]),
|
||||
c6_to_8(palette[0xf * 3 + 1]),
|
||||
c6_to_8(palette[0xf * 3 + 2]));
|
||||
bpp = surface_bytes_per_pixel(surface);
|
||||
d1 += x1 * bpp;
|
||||
switch (surface_bits_per_pixel(surface)) {
|
||||
default:
|
||||
break;
|
||||
case 8:
|
||||
vga_draw_cursor_line_8(d1, src, poffset, w, color0, color1, 0xff);
|
||||
break;
|
||||
case 15:
|
||||
vga_draw_cursor_line_16(d1, src, poffset, w, color0, color1, 0x7fff);
|
||||
break;
|
||||
case 16:
|
||||
vga_draw_cursor_line_16(d1, src, poffset, w, color0, color1, 0xffff);
|
||||
break;
|
||||
case 32:
|
||||
vga_draw_cursor_line_32(d1, src, poffset, w, color0, color1, 0xffffff);
|
||||
break;
|
||||
}
|
||||
color0 = rgb_to_pixel32(c6_to_8(palette[0x0 * 3]),
|
||||
c6_to_8(palette[0x0 * 3 + 1]),
|
||||
c6_to_8(palette[0x0 * 3 + 2]));
|
||||
color1 = rgb_to_pixel32(c6_to_8(palette[0xf * 3]),
|
||||
c6_to_8(palette[0xf * 3 + 1]),
|
||||
c6_to_8(palette[0xf * 3 + 2]));
|
||||
d1 += x1 * 4;
|
||||
vga_draw_cursor_line(d1, src, poffset, w, color0, color1, 0xffffff);
|
||||
}
|
||||
|
||||
/***************************************
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* QEMU Cirrus VGA Emulator templates
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#if DEPTH == 8
|
||||
#define BPP 1
|
||||
#elif DEPTH == 15 || DEPTH == 16
|
||||
#define BPP 2
|
||||
#elif DEPTH == 32
|
||||
#define BPP 4
|
||||
#else
|
||||
#error unsupported depth
|
||||
#endif
|
||||
|
||||
static void glue(vga_draw_cursor_line_, DEPTH)(uint8_t *d1,
|
||||
const uint8_t *src1,
|
||||
int poffset, int w,
|
||||
unsigned int color0,
|
||||
unsigned int color1,
|
||||
unsigned int color_xor)
|
||||
{
|
||||
const uint8_t *plane0, *plane1;
|
||||
int x, b0, b1;
|
||||
uint8_t *d;
|
||||
|
||||
d = d1;
|
||||
plane0 = src1;
|
||||
plane1 = src1 + poffset;
|
||||
for (x = 0; x < w; x++) {
|
||||
b0 = (plane0[x >> 3] >> (7 - (x & 7))) & 1;
|
||||
b1 = (plane1[x >> 3] >> (7 - (x & 7))) & 1;
|
||||
#if DEPTH == 8
|
||||
switch (b0 | (b1 << 1)) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
d[0] ^= color_xor;
|
||||
break;
|
||||
case 2:
|
||||
d[0] = color0;
|
||||
break;
|
||||
case 3:
|
||||
d[0] = color1;
|
||||
break;
|
||||
}
|
||||
#elif DEPTH == 16
|
||||
switch (b0 | (b1 << 1)) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
((uint16_t *)d)[0] ^= color_xor;
|
||||
break;
|
||||
case 2:
|
||||
((uint16_t *)d)[0] = color0;
|
||||
break;
|
||||
case 3:
|
||||
((uint16_t *)d)[0] = color1;
|
||||
break;
|
||||
}
|
||||
#elif DEPTH == 32
|
||||
switch (b0 | (b1 << 1)) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
((uint32_t *)d)[0] ^= color_xor;
|
||||
break;
|
||||
case 2:
|
||||
((uint32_t *)d)[0] = color0;
|
||||
break;
|
||||
case 3:
|
||||
((uint32_t *)d)[0] = color1;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
#error unsupported depth
|
||||
#endif
|
||||
d += BPP;
|
||||
}
|
||||
}
|
||||
|
||||
#undef DEPTH
|
||||
#undef BPP
|
||||
@@ -22,41 +22,9 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#if DEPTH == 8
|
||||
#define BPP 1
|
||||
#define PIXEL_TYPE uint8_t
|
||||
#elif DEPTH == 15 || DEPTH == 16
|
||||
#define BPP 2
|
||||
#define PIXEL_TYPE uint16_t
|
||||
#elif DEPTH == 32
|
||||
#define BPP 4
|
||||
#define PIXEL_TYPE uint32_t
|
||||
#else
|
||||
#error unsupport depth
|
||||
#endif
|
||||
|
||||
#ifdef BGR_FORMAT
|
||||
#define PIXEL_NAME glue(DEPTH, bgr)
|
||||
#else
|
||||
#define PIXEL_NAME DEPTH
|
||||
#endif /* BGR_FORMAT */
|
||||
|
||||
#if DEPTH != 15 && !defined(BGR_FORMAT)
|
||||
|
||||
static inline void glue(vga_draw_glyph_line_, DEPTH)(uint8_t *d,
|
||||
uint32_t font_data,
|
||||
uint32_t xorcol,
|
||||
uint32_t bgcol)
|
||||
static inline void vga_draw_glyph_line(uint8_t *d, uint32_t font_data,
|
||||
uint32_t xorcol, uint32_t bgcol)
|
||||
{
|
||||
#if BPP == 1
|
||||
((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol;
|
||||
((uint32_t *)d)[1] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
|
||||
#elif BPP == 2
|
||||
((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol;
|
||||
((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol;
|
||||
((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol;
|
||||
((uint32_t *)d)[3] = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol;
|
||||
#else
|
||||
((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
|
||||
((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
|
||||
((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
|
||||
@@ -65,10 +33,24 @@ static inline void glue(vga_draw_glyph_line_, DEPTH)(uint8_t *d,
|
||||
((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
|
||||
((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
|
||||
((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void glue(vga_draw_glyph8_, DEPTH)(uint8_t *d, int linesize,
|
||||
static void vga_draw_glyph8(uint8_t *d, int linesize,
|
||||
const uint8_t *font_ptr, int h,
|
||||
uint32_t fgcol, uint32_t bgcol)
|
||||
{
|
||||
uint32_t font_data, xorcol;
|
||||
|
||||
xorcol = bgcol ^ fgcol;
|
||||
do {
|
||||
font_data = font_ptr[0];
|
||||
vga_draw_glyph_line(d, font_data, xorcol, bgcol);
|
||||
font_ptr += 4;
|
||||
d += linesize;
|
||||
} while (--h);
|
||||
}
|
||||
|
||||
static void vga_draw_glyph16(uint8_t *d, int linesize,
|
||||
const uint8_t *font_ptr, int h,
|
||||
uint32_t fgcol, uint32_t bgcol)
|
||||
{
|
||||
@@ -77,63 +59,24 @@ static void glue(vga_draw_glyph8_, DEPTH)(uint8_t *d, int linesize,
|
||||
xorcol = bgcol ^ fgcol;
|
||||
do {
|
||||
font_data = font_ptr[0];
|
||||
glue(vga_draw_glyph_line_, DEPTH)(d, font_data, xorcol, bgcol);
|
||||
vga_draw_glyph_line(d, expand4to8[font_data >> 4],
|
||||
xorcol, bgcol);
|
||||
vga_draw_glyph_line(d + 32, expand4to8[font_data & 0x0f],
|
||||
xorcol, bgcol);
|
||||
font_ptr += 4;
|
||||
d += linesize;
|
||||
} while (--h);
|
||||
}
|
||||
|
||||
static void glue(vga_draw_glyph16_, DEPTH)(uint8_t *d, int linesize,
|
||||
const uint8_t *font_ptr, int h,
|
||||
uint32_t fgcol, uint32_t bgcol)
|
||||
{
|
||||
uint32_t font_data, xorcol;
|
||||
|
||||
xorcol = bgcol ^ fgcol;
|
||||
do {
|
||||
font_data = font_ptr[0];
|
||||
glue(vga_draw_glyph_line_, DEPTH)(d,
|
||||
expand4to8[font_data >> 4],
|
||||
xorcol, bgcol);
|
||||
glue(vga_draw_glyph_line_, DEPTH)(d + 8 * BPP,
|
||||
expand4to8[font_data & 0x0f],
|
||||
xorcol, bgcol);
|
||||
font_ptr += 4;
|
||||
d += linesize;
|
||||
} while (--h);
|
||||
}
|
||||
|
||||
static void glue(vga_draw_glyph9_, DEPTH)(uint8_t *d, int linesize,
|
||||
const uint8_t *font_ptr, int h,
|
||||
uint32_t fgcol, uint32_t bgcol, int dup9)
|
||||
static void vga_draw_glyph9(uint8_t *d, int linesize,
|
||||
const uint8_t *font_ptr, int h,
|
||||
uint32_t fgcol, uint32_t bgcol, int dup9)
|
||||
{
|
||||
uint32_t font_data, xorcol, v;
|
||||
|
||||
xorcol = bgcol ^ fgcol;
|
||||
do {
|
||||
font_data = font_ptr[0];
|
||||
#if BPP == 1
|
||||
stl_p((uint32_t *)d, (dmask16[(font_data >> 4)] & xorcol) ^ bgcol);
|
||||
v = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
|
||||
stl_p(((uint32_t *)d)+1, v);
|
||||
if (dup9)
|
||||
((uint8_t *)d)[8] = v >> (24 * (1 - BIG));
|
||||
else
|
||||
((uint8_t *)d)[8] = bgcol;
|
||||
|
||||
#elif BPP == 2
|
||||
stl_p(((uint32_t *)d)+0, (dmask4[(font_data >> 6)] & xorcol) ^ bgcol);
|
||||
stl_p(((uint32_t *)d)+1,
|
||||
(dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol);
|
||||
stl_p(((uint32_t *)d)+2,
|
||||
(dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol);
|
||||
v = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol;
|
||||
stl_p(((uint32_t *)d)+3, v);
|
||||
if (dup9)
|
||||
((uint16_t *)d)[8] = v >> (16 * (1 - BIG));
|
||||
else
|
||||
((uint16_t *)d)[8] = bgcol;
|
||||
#else
|
||||
((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
|
||||
((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
|
||||
((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
|
||||
@@ -147,7 +90,6 @@ static void glue(vga_draw_glyph9_, DEPTH)(uint8_t *d, int linesize,
|
||||
((uint32_t *)d)[8] = v;
|
||||
else
|
||||
((uint32_t *)d)[8] = bgcol;
|
||||
#endif
|
||||
font_ptr += 4;
|
||||
d += linesize;
|
||||
} while (--h);
|
||||
@@ -156,8 +98,8 @@ static void glue(vga_draw_glyph9_, DEPTH)(uint8_t *d, int linesize,
|
||||
/*
|
||||
* 4 color mode
|
||||
*/
|
||||
static void glue(vga_draw_line2_, DEPTH)(VGACommonState *s1, uint8_t *d,
|
||||
const uint8_t *s, int width)
|
||||
static void vga_draw_line2(VGACommonState *s1, uint8_t *d,
|
||||
const uint8_t *s, int width)
|
||||
{
|
||||
uint32_t plane_mask, *palette, data, v;
|
||||
int x;
|
||||
@@ -170,36 +112,30 @@ static void glue(vga_draw_line2_, DEPTH)(VGACommonState *s1, uint8_t *d,
|
||||
data &= plane_mask;
|
||||
v = expand2[GET_PLANE(data, 0)];
|
||||
v |= expand2[GET_PLANE(data, 2)] << 2;
|
||||
((PIXEL_TYPE *)d)[0] = palette[v >> 12];
|
||||
((PIXEL_TYPE *)d)[1] = palette[(v >> 8) & 0xf];
|
||||
((PIXEL_TYPE *)d)[2] = palette[(v >> 4) & 0xf];
|
||||
((PIXEL_TYPE *)d)[3] = palette[(v >> 0) & 0xf];
|
||||
((uint32_t *)d)[0] = palette[v >> 12];
|
||||
((uint32_t *)d)[1] = palette[(v >> 8) & 0xf];
|
||||
((uint32_t *)d)[2] = palette[(v >> 4) & 0xf];
|
||||
((uint32_t *)d)[3] = palette[(v >> 0) & 0xf];
|
||||
|
||||
v = expand2[GET_PLANE(data, 1)];
|
||||
v |= expand2[GET_PLANE(data, 3)] << 2;
|
||||
((PIXEL_TYPE *)d)[4] = palette[v >> 12];
|
||||
((PIXEL_TYPE *)d)[5] = palette[(v >> 8) & 0xf];
|
||||
((PIXEL_TYPE *)d)[6] = palette[(v >> 4) & 0xf];
|
||||
((PIXEL_TYPE *)d)[7] = palette[(v >> 0) & 0xf];
|
||||
d += BPP * 8;
|
||||
((uint32_t *)d)[4] = palette[v >> 12];
|
||||
((uint32_t *)d)[5] = palette[(v >> 8) & 0xf];
|
||||
((uint32_t *)d)[6] = palette[(v >> 4) & 0xf];
|
||||
((uint32_t *)d)[7] = palette[(v >> 0) & 0xf];
|
||||
d += 32;
|
||||
s += 4;
|
||||
}
|
||||
}
|
||||
|
||||
#if BPP == 1
|
||||
#define PUT_PIXEL2(d, n, v) ((uint16_t *)d)[(n)] = (v)
|
||||
#elif BPP == 2
|
||||
#define PUT_PIXEL2(d, n, v) ((uint32_t *)d)[(n)] = (v)
|
||||
#else
|
||||
#define PUT_PIXEL2(d, n, v) \
|
||||
((uint32_t *)d)[2*(n)] = ((uint32_t *)d)[2*(n)+1] = (v)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 4 color mode, dup2 horizontal
|
||||
*/
|
||||
static void glue(vga_draw_line2d2_, DEPTH)(VGACommonState *s1, uint8_t *d,
|
||||
const uint8_t *s, int width)
|
||||
static void vga_draw_line2d2(VGACommonState *s1, uint8_t *d,
|
||||
const uint8_t *s, int width)
|
||||
{
|
||||
uint32_t plane_mask, *palette, data, v;
|
||||
int x;
|
||||
@@ -223,7 +159,7 @@ static void glue(vga_draw_line2d2_, DEPTH)(VGACommonState *s1, uint8_t *d,
|
||||
PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]);
|
||||
PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
|
||||
PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
|
||||
d += BPP * 16;
|
||||
d += 64;
|
||||
s += 4;
|
||||
}
|
||||
}
|
||||
@@ -231,8 +167,8 @@ static void glue(vga_draw_line2d2_, DEPTH)(VGACommonState *s1, uint8_t *d,
|
||||
/*
|
||||
* 16 color mode
|
||||
*/
|
||||
static void glue(vga_draw_line4_, DEPTH)(VGACommonState *s1, uint8_t *d,
|
||||
const uint8_t *s, int width)
|
||||
static void vga_draw_line4(VGACommonState *s1, uint8_t *d,
|
||||
const uint8_t *s, int width)
|
||||
{
|
||||
uint32_t plane_mask, data, v, *palette;
|
||||
int x;
|
||||
@@ -247,15 +183,15 @@ static void glue(vga_draw_line4_, DEPTH)(VGACommonState *s1, uint8_t *d,
|
||||
v |= expand4[GET_PLANE(data, 1)] << 1;
|
||||
v |= expand4[GET_PLANE(data, 2)] << 2;
|
||||
v |= expand4[GET_PLANE(data, 3)] << 3;
|
||||
((PIXEL_TYPE *)d)[0] = palette[v >> 28];
|
||||
((PIXEL_TYPE *)d)[1] = palette[(v >> 24) & 0xf];
|
||||
((PIXEL_TYPE *)d)[2] = palette[(v >> 20) & 0xf];
|
||||
((PIXEL_TYPE *)d)[3] = palette[(v >> 16) & 0xf];
|
||||
((PIXEL_TYPE *)d)[4] = palette[(v >> 12) & 0xf];
|
||||
((PIXEL_TYPE *)d)[5] = palette[(v >> 8) & 0xf];
|
||||
((PIXEL_TYPE *)d)[6] = palette[(v >> 4) & 0xf];
|
||||
((PIXEL_TYPE *)d)[7] = palette[(v >> 0) & 0xf];
|
||||
d += BPP * 8;
|
||||
((uint32_t *)d)[0] = palette[v >> 28];
|
||||
((uint32_t *)d)[1] = palette[(v >> 24) & 0xf];
|
||||
((uint32_t *)d)[2] = palette[(v >> 20) & 0xf];
|
||||
((uint32_t *)d)[3] = palette[(v >> 16) & 0xf];
|
||||
((uint32_t *)d)[4] = palette[(v >> 12) & 0xf];
|
||||
((uint32_t *)d)[5] = palette[(v >> 8) & 0xf];
|
||||
((uint32_t *)d)[6] = palette[(v >> 4) & 0xf];
|
||||
((uint32_t *)d)[7] = palette[(v >> 0) & 0xf];
|
||||
d += 32;
|
||||
s += 4;
|
||||
}
|
||||
}
|
||||
@@ -263,8 +199,8 @@ static void glue(vga_draw_line4_, DEPTH)(VGACommonState *s1, uint8_t *d,
|
||||
/*
|
||||
* 16 color mode, dup2 horizontal
|
||||
*/
|
||||
static void glue(vga_draw_line4d2_, DEPTH)(VGACommonState *s1, uint8_t *d,
|
||||
const uint8_t *s, int width)
|
||||
static void vga_draw_line4d2(VGACommonState *s1, uint8_t *d,
|
||||
const uint8_t *s, int width)
|
||||
{
|
||||
uint32_t plane_mask, data, v, *palette;
|
||||
int x;
|
||||
@@ -287,7 +223,7 @@ static void glue(vga_draw_line4d2_, DEPTH)(VGACommonState *s1, uint8_t *d,
|
||||
PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]);
|
||||
PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
|
||||
PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
|
||||
d += BPP * 16;
|
||||
d += 64;
|
||||
s += 4;
|
||||
}
|
||||
}
|
||||
@@ -297,8 +233,8 @@ static void glue(vga_draw_line4d2_, DEPTH)(VGACommonState *s1, uint8_t *d,
|
||||
*
|
||||
* XXX: add plane_mask support (never used in standard VGA modes)
|
||||
*/
|
||||
static void glue(vga_draw_line8d2_, DEPTH)(VGACommonState *s1, uint8_t *d,
|
||||
const uint8_t *s, int width)
|
||||
static void vga_draw_line8d2(VGACommonState *s1, uint8_t *d,
|
||||
const uint8_t *s, int width)
|
||||
{
|
||||
uint32_t *palette;
|
||||
int x;
|
||||
@@ -310,7 +246,7 @@ static void glue(vga_draw_line8d2_, DEPTH)(VGACommonState *s1, uint8_t *d,
|
||||
PUT_PIXEL2(d, 1, palette[s[1]]);
|
||||
PUT_PIXEL2(d, 2, palette[s[2]]);
|
||||
PUT_PIXEL2(d, 3, palette[s[3]]);
|
||||
d += BPP * 8;
|
||||
d += 32;
|
||||
s += 4;
|
||||
}
|
||||
}
|
||||
@@ -320,8 +256,8 @@ static void glue(vga_draw_line8d2_, DEPTH)(VGACommonState *s1, uint8_t *d,
|
||||
*
|
||||
* XXX: add plane_mask support (never used in standard VGA modes)
|
||||
*/
|
||||
static void glue(vga_draw_line8_, DEPTH)(VGACommonState *s1, uint8_t *d,
|
||||
const uint8_t *s, int width)
|
||||
static void vga_draw_line8(VGACommonState *s1, uint8_t *d,
|
||||
const uint8_t *s, int width)
|
||||
{
|
||||
uint32_t *palette;
|
||||
int x;
|
||||
@@ -329,107 +265,141 @@ static void glue(vga_draw_line8_, DEPTH)(VGACommonState *s1, uint8_t *d,
|
||||
palette = s1->last_palette;
|
||||
width >>= 3;
|
||||
for(x = 0; x < width; x++) {
|
||||
((PIXEL_TYPE *)d)[0] = palette[s[0]];
|
||||
((PIXEL_TYPE *)d)[1] = palette[s[1]];
|
||||
((PIXEL_TYPE *)d)[2] = palette[s[2]];
|
||||
((PIXEL_TYPE *)d)[3] = palette[s[3]];
|
||||
((PIXEL_TYPE *)d)[4] = palette[s[4]];
|
||||
((PIXEL_TYPE *)d)[5] = palette[s[5]];
|
||||
((PIXEL_TYPE *)d)[6] = palette[s[6]];
|
||||
((PIXEL_TYPE *)d)[7] = palette[s[7]];
|
||||
d += BPP * 8;
|
||||
((uint32_t *)d)[0] = palette[s[0]];
|
||||
((uint32_t *)d)[1] = palette[s[1]];
|
||||
((uint32_t *)d)[2] = palette[s[2]];
|
||||
((uint32_t *)d)[3] = palette[s[3]];
|
||||
((uint32_t *)d)[4] = palette[s[4]];
|
||||
((uint32_t *)d)[5] = palette[s[5]];
|
||||
((uint32_t *)d)[6] = palette[s[6]];
|
||||
((uint32_t *)d)[7] = palette[s[7]];
|
||||
d += 32;
|
||||
s += 8;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* DEPTH != 15 */
|
||||
|
||||
|
||||
/* XXX: optimize */
|
||||
|
||||
/*
|
||||
* 15 bit color
|
||||
*/
|
||||
static void glue(vga_draw_line15_, PIXEL_NAME)(VGACommonState *s1, uint8_t *d,
|
||||
const uint8_t *s, int width)
|
||||
static void vga_draw_line15_le(VGACommonState *s1, uint8_t *d,
|
||||
const uint8_t *s, int width)
|
||||
{
|
||||
#if DEPTH == 15 && defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
|
||||
memcpy(d, s, width * 2);
|
||||
#else
|
||||
int w;
|
||||
uint32_t v, r, g, b;
|
||||
|
||||
w = width;
|
||||
do {
|
||||
v = lduw_p((void *)s);
|
||||
v = lduw_le_p((void *)s);
|
||||
r = (v >> 7) & 0xf8;
|
||||
g = (v >> 2) & 0xf8;
|
||||
b = (v << 3) & 0xf8;
|
||||
((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b);
|
||||
((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
|
||||
s += 2;
|
||||
d += BPP;
|
||||
d += 4;
|
||||
} while (--w != 0);
|
||||
}
|
||||
|
||||
static void vga_draw_line15_be(VGACommonState *s1, uint8_t *d,
|
||||
const uint8_t *s, int width)
|
||||
{
|
||||
int w;
|
||||
uint32_t v, r, g, b;
|
||||
|
||||
w = width;
|
||||
do {
|
||||
v = lduw_be_p((void *)s);
|
||||
r = (v >> 7) & 0xf8;
|
||||
g = (v >> 2) & 0xf8;
|
||||
b = (v << 3) & 0xf8;
|
||||
((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
|
||||
s += 2;
|
||||
d += 4;
|
||||
} while (--w != 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* 16 bit color
|
||||
*/
|
||||
static void glue(vga_draw_line16_, PIXEL_NAME)(VGACommonState *s1, uint8_t *d,
|
||||
const uint8_t *s, int width)
|
||||
static void vga_draw_line16_le(VGACommonState *s1, uint8_t *d,
|
||||
const uint8_t *s, int width)
|
||||
{
|
||||
#if DEPTH == 16 && defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
|
||||
memcpy(d, s, width * 2);
|
||||
#else
|
||||
int w;
|
||||
uint32_t v, r, g, b;
|
||||
|
||||
w = width;
|
||||
do {
|
||||
v = lduw_p((void *)s);
|
||||
v = lduw_le_p((void *)s);
|
||||
r = (v >> 8) & 0xf8;
|
||||
g = (v >> 3) & 0xfc;
|
||||
b = (v << 3) & 0xf8;
|
||||
((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b);
|
||||
((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
|
||||
s += 2;
|
||||
d += BPP;
|
||||
d += 4;
|
||||
} while (--w != 0);
|
||||
}
|
||||
|
||||
static void vga_draw_line16_be(VGACommonState *s1, uint8_t *d,
|
||||
const uint8_t *s, int width)
|
||||
{
|
||||
int w;
|
||||
uint32_t v, r, g, b;
|
||||
|
||||
w = width;
|
||||
do {
|
||||
v = lduw_be_p((void *)s);
|
||||
r = (v >> 8) & 0xf8;
|
||||
g = (v >> 3) & 0xfc;
|
||||
b = (v << 3) & 0xf8;
|
||||
((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
|
||||
s += 2;
|
||||
d += 4;
|
||||
} while (--w != 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* 24 bit color
|
||||
*/
|
||||
static void glue(vga_draw_line24_, PIXEL_NAME)(VGACommonState *s1, uint8_t *d,
|
||||
const uint8_t *s, int width)
|
||||
static void vga_draw_line24_le(VGACommonState *s1, uint8_t *d,
|
||||
const uint8_t *s, int width)
|
||||
{
|
||||
int w;
|
||||
uint32_t r, g, b;
|
||||
|
||||
w = width;
|
||||
do {
|
||||
#if defined(TARGET_WORDS_BIGENDIAN)
|
||||
r = s[0];
|
||||
g = s[1];
|
||||
b = s[2];
|
||||
#else
|
||||
b = s[0];
|
||||
g = s[1];
|
||||
r = s[2];
|
||||
#endif
|
||||
((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b);
|
||||
((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
|
||||
s += 3;
|
||||
d += BPP;
|
||||
d += 4;
|
||||
} while (--w != 0);
|
||||
}
|
||||
|
||||
static void vga_draw_line24_be(VGACommonState *s1, uint8_t *d,
|
||||
const uint8_t *s, int width)
|
||||
{
|
||||
int w;
|
||||
uint32_t r, g, b;
|
||||
|
||||
w = width;
|
||||
do {
|
||||
r = s[0];
|
||||
g = s[1];
|
||||
b = s[2];
|
||||
((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
|
||||
s += 3;
|
||||
d += 4;
|
||||
} while (--w != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* 32 bit color
|
||||
*/
|
||||
static void glue(vga_draw_line32_, PIXEL_NAME)(VGACommonState *s1, uint8_t *d,
|
||||
const uint8_t *s, int width)
|
||||
static void vga_draw_line32_le(VGACommonState *s1, uint8_t *d,
|
||||
const uint8_t *s, int width)
|
||||
{
|
||||
#if DEPTH == 32 && defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) && !defined(BGR_FORMAT)
|
||||
#ifndef HOST_WORDS_BIGENDIAN
|
||||
memcpy(d, s, width * 4);
|
||||
#else
|
||||
int w;
|
||||
@@ -437,25 +407,33 @@ static void glue(vga_draw_line32_, PIXEL_NAME)(VGACommonState *s1, uint8_t *d,
|
||||
|
||||
w = width;
|
||||
do {
|
||||
#if defined(TARGET_WORDS_BIGENDIAN)
|
||||
r = s[1];
|
||||
g = s[2];
|
||||
b = s[3];
|
||||
#else
|
||||
b = s[0];
|
||||
g = s[1];
|
||||
r = s[2];
|
||||
#endif
|
||||
((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b);
|
||||
((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
|
||||
s += 4;
|
||||
d += BPP;
|
||||
d += 4;
|
||||
} while (--w != 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef PUT_PIXEL2
|
||||
#undef DEPTH
|
||||
#undef BPP
|
||||
#undef PIXEL_TYPE
|
||||
#undef PIXEL_NAME
|
||||
#undef BGR_FORMAT
|
||||
static void vga_draw_line32_be(VGACommonState *s1, uint8_t *d,
|
||||
const uint8_t *s, int width)
|
||||
{
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
memcpy(d, s, width * 4);
|
||||
#else
|
||||
int w;
|
||||
uint32_t r, g, b;
|
||||
|
||||
w = width;
|
||||
do {
|
||||
r = s[1];
|
||||
g = s[2];
|
||||
b = s[3];
|
||||
((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
|
||||
s += 4;
|
||||
d += 4;
|
||||
} while (--w != 0);
|
||||
#endif
|
||||
}
|
||||
382
hw/display/vga.c
382
hw/display/vga.c
@@ -761,14 +761,13 @@ void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
|
||||
s->vbe_regs[VBE_DISPI_INDEX_ENABLE] |= VBE_DISPI_ENABLED;
|
||||
vbe_fixup_regs(s);
|
||||
|
||||
/* clear the screen (should be done in BIOS) */
|
||||
/* clear the screen */
|
||||
if (!(val & VBE_DISPI_NOCLEARMEM)) {
|
||||
memset(s->vram_ptr, 0,
|
||||
s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
|
||||
}
|
||||
|
||||
/* we initialize the VGA graphic mode (should be done
|
||||
in BIOS) */
|
||||
/* we initialize the VGA graphic mode */
|
||||
/* graphic mode + memory map 1 */
|
||||
s->gr[VGA_GFX_MISC] = (s->gr[VGA_GFX_MISC] & ~0x0c) | 0x04 |
|
||||
VGA_GR06_GRAPHICS_MODE;
|
||||
@@ -801,7 +800,6 @@ void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
|
||||
(shift_control << 5);
|
||||
s->cr[VGA_CRTC_MAX_SCAN] &= ~0x9f; /* no double scan */
|
||||
} else {
|
||||
/* XXX: the bios should do that */
|
||||
s->bank_offset = 0;
|
||||
}
|
||||
s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
|
||||
@@ -1006,95 +1004,10 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val)
|
||||
}
|
||||
}
|
||||
|
||||
typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
|
||||
const uint8_t *font_ptr, int h,
|
||||
uint32_t fgcol, uint32_t bgcol);
|
||||
typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
|
||||
const uint8_t *font_ptr, int h,
|
||||
uint32_t fgcol, uint32_t bgcol, int dup9);
|
||||
typedef void vga_draw_line_func(VGACommonState *s1, uint8_t *d,
|
||||
const uint8_t *s, int width);
|
||||
|
||||
#define DEPTH 8
|
||||
#include "vga_template.h"
|
||||
|
||||
#define DEPTH 15
|
||||
#include "vga_template.h"
|
||||
|
||||
#define BGR_FORMAT
|
||||
#define DEPTH 15
|
||||
#include "vga_template.h"
|
||||
|
||||
#define DEPTH 16
|
||||
#include "vga_template.h"
|
||||
|
||||
#define BGR_FORMAT
|
||||
#define DEPTH 16
|
||||
#include "vga_template.h"
|
||||
|
||||
#define DEPTH 32
|
||||
#include "vga_template.h"
|
||||
|
||||
#define BGR_FORMAT
|
||||
#define DEPTH 32
|
||||
#include "vga_template.h"
|
||||
|
||||
static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
|
||||
{
|
||||
unsigned int col;
|
||||
col = rgb_to_pixel8(r, g, b);
|
||||
col |= col << 8;
|
||||
col |= col << 16;
|
||||
return col;
|
||||
}
|
||||
|
||||
static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
|
||||
{
|
||||
unsigned int col;
|
||||
col = rgb_to_pixel15(r, g, b);
|
||||
col |= col << 16;
|
||||
return col;
|
||||
}
|
||||
|
||||
static unsigned int rgb_to_pixel15bgr_dup(unsigned int r, unsigned int g,
|
||||
unsigned int b)
|
||||
{
|
||||
unsigned int col;
|
||||
col = rgb_to_pixel15bgr(r, g, b);
|
||||
col |= col << 16;
|
||||
return col;
|
||||
}
|
||||
|
||||
static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
|
||||
{
|
||||
unsigned int col;
|
||||
col = rgb_to_pixel16(r, g, b);
|
||||
col |= col << 16;
|
||||
return col;
|
||||
}
|
||||
|
||||
static unsigned int rgb_to_pixel16bgr_dup(unsigned int r, unsigned int g,
|
||||
unsigned int b)
|
||||
{
|
||||
unsigned int col;
|
||||
col = rgb_to_pixel16bgr(r, g, b);
|
||||
col |= col << 16;
|
||||
return col;
|
||||
}
|
||||
|
||||
static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
|
||||
{
|
||||
unsigned int col;
|
||||
col = rgb_to_pixel32(r, g, b);
|
||||
return col;
|
||||
}
|
||||
|
||||
static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
|
||||
{
|
||||
unsigned int col;
|
||||
col = rgb_to_pixel32bgr(r, g, b);
|
||||
return col;
|
||||
}
|
||||
#include "vga-helpers.h"
|
||||
|
||||
/* return true if the palette was modified */
|
||||
static int update_palette16(VGACommonState *s)
|
||||
@@ -1112,9 +1025,9 @@ static int update_palette16(VGACommonState *s)
|
||||
v = ((s->ar[VGA_ATC_COLOR_PAGE] & 0xc) << 4) | (v & 0x3f);
|
||||
}
|
||||
v = v * 3;
|
||||
col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
|
||||
c6_to_8(s->palette[v + 1]),
|
||||
c6_to_8(s->palette[v + 2]));
|
||||
col = rgb_to_pixel32(c6_to_8(s->palette[v]),
|
||||
c6_to_8(s->palette[v + 1]),
|
||||
c6_to_8(s->palette[v + 2]));
|
||||
if (col != palette[i]) {
|
||||
full_update = 1;
|
||||
palette[i] = col;
|
||||
@@ -1134,13 +1047,13 @@ static int update_palette256(VGACommonState *s)
|
||||
v = 0;
|
||||
for(i = 0; i < 256; i++) {
|
||||
if (s->dac_8bit) {
|
||||
col = s->rgb_to_pixel(s->palette[v],
|
||||
s->palette[v + 1],
|
||||
s->palette[v + 2]);
|
||||
col = rgb_to_pixel32(s->palette[v],
|
||||
s->palette[v + 1],
|
||||
s->palette[v + 2]);
|
||||
} else {
|
||||
col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
|
||||
c6_to_8(s->palette[v + 1]),
|
||||
c6_to_8(s->palette[v + 2]));
|
||||
col = rgb_to_pixel32(c6_to_8(s->palette[v]),
|
||||
c6_to_8(s->palette[v + 1]),
|
||||
c6_to_8(s->palette[v + 2]));
|
||||
}
|
||||
if (col != palette[i]) {
|
||||
full_update = 1;
|
||||
@@ -1202,56 +1115,6 @@ static int update_basic_params(VGACommonState *s)
|
||||
return full_update;
|
||||
}
|
||||
|
||||
#define NB_DEPTHS 7
|
||||
|
||||
static inline int get_depth_index(DisplaySurface *s)
|
||||
{
|
||||
switch (surface_bits_per_pixel(s)) {
|
||||
default:
|
||||
case 8:
|
||||
return 0;
|
||||
case 15:
|
||||
return 1;
|
||||
case 16:
|
||||
return 2;
|
||||
case 32:
|
||||
if (is_surface_bgr(s)) {
|
||||
return 4;
|
||||
} else {
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static vga_draw_glyph8_func * const vga_draw_glyph8_table[NB_DEPTHS] = {
|
||||
vga_draw_glyph8_8,
|
||||
vga_draw_glyph8_16,
|
||||
vga_draw_glyph8_16,
|
||||
vga_draw_glyph8_32,
|
||||
vga_draw_glyph8_32,
|
||||
vga_draw_glyph8_16,
|
||||
vga_draw_glyph8_16,
|
||||
};
|
||||
|
||||
static vga_draw_glyph8_func * const vga_draw_glyph16_table[NB_DEPTHS] = {
|
||||
vga_draw_glyph16_8,
|
||||
vga_draw_glyph16_16,
|
||||
vga_draw_glyph16_16,
|
||||
vga_draw_glyph16_32,
|
||||
vga_draw_glyph16_32,
|
||||
vga_draw_glyph16_16,
|
||||
vga_draw_glyph16_16,
|
||||
};
|
||||
|
||||
static vga_draw_glyph9_func * const vga_draw_glyph9_table[NB_DEPTHS] = {
|
||||
vga_draw_glyph9_8,
|
||||
vga_draw_glyph9_16,
|
||||
vga_draw_glyph9_16,
|
||||
vga_draw_glyph9_32,
|
||||
vga_draw_glyph9_32,
|
||||
vga_draw_glyph9_16,
|
||||
vga_draw_glyph9_16,
|
||||
};
|
||||
|
||||
static const uint8_t cursor_glyph[32 * 4] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
@@ -1303,18 +1166,6 @@ static void vga_get_text_resolution(VGACommonState *s, int *pwidth, int *pheight
|
||||
*pcheight = cheight;
|
||||
}
|
||||
|
||||
typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
|
||||
|
||||
static rgb_to_pixel_dup_func * const rgb_to_pixel_dup_table[NB_DEPTHS] = {
|
||||
rgb_to_pixel8_dup,
|
||||
rgb_to_pixel15_dup,
|
||||
rgb_to_pixel16_dup,
|
||||
rgb_to_pixel32_dup,
|
||||
rgb_to_pixel32bgr_dup,
|
||||
rgb_to_pixel15bgr_dup,
|
||||
rgb_to_pixel16bgr_dup,
|
||||
};
|
||||
|
||||
/*
|
||||
* Text mode update
|
||||
* Missing:
|
||||
@@ -1331,11 +1182,9 @@ static void vga_draw_text(VGACommonState *s, int full_update)
|
||||
uint32_t offset, fgcol, bgcol, v, cursor_offset;
|
||||
uint8_t *d1, *d, *src, *dest, *cursor_ptr;
|
||||
const uint8_t *font_ptr, *font_base[2];
|
||||
int dup9, line_offset, depth_index;
|
||||
int dup9, line_offset;
|
||||
uint32_t *palette;
|
||||
uint32_t *ch_attr_ptr;
|
||||
vga_draw_glyph8_func *vga_draw_glyph8;
|
||||
vga_draw_glyph9_func *vga_draw_glyph9;
|
||||
int64_t now = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
|
||||
|
||||
/* compute font data address (in plane 2) */
|
||||
@@ -1387,8 +1236,6 @@ static void vga_draw_text(VGACommonState *s, int full_update)
|
||||
s->last_cw = cw;
|
||||
full_update = 1;
|
||||
}
|
||||
s->rgb_to_pixel =
|
||||
rgb_to_pixel_dup_table[get_depth_index(surface)];
|
||||
full_update |= update_palette16(s);
|
||||
palette = s->last_palette;
|
||||
x_incr = cw * surface_bytes_per_pixel(surface);
|
||||
@@ -1422,13 +1269,6 @@ static void vga_draw_text(VGACommonState *s, int full_update)
|
||||
s->cursor_visible_phase = !s->cursor_visible_phase;
|
||||
}
|
||||
|
||||
depth_index = get_depth_index(surface);
|
||||
if (cw == 16)
|
||||
vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
|
||||
else
|
||||
vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
|
||||
vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
|
||||
|
||||
dest = surface_data(surface);
|
||||
linesize = surface_stride(surface);
|
||||
ch_attr_ptr = s->last_ch_attr;
|
||||
@@ -1458,7 +1298,10 @@ static void vga_draw_text(VGACommonState *s, int full_update)
|
||||
font_ptr += 32 * 4 * ch;
|
||||
bgcol = palette[cattr >> 4];
|
||||
fgcol = palette[cattr & 0x0f];
|
||||
if (cw != 9) {
|
||||
if (cw == 16) {
|
||||
vga_draw_glyph16(d1, linesize,
|
||||
font_ptr, cheight, fgcol, bgcol);
|
||||
} else if (cw != 9) {
|
||||
vga_draw_glyph8(d1, linesize,
|
||||
font_ptr, cheight, fgcol, bgcol);
|
||||
} else {
|
||||
@@ -1483,7 +1326,10 @@ static void vga_draw_text(VGACommonState *s, int full_update)
|
||||
if (line_last >= line_start && line_start < cheight) {
|
||||
h = line_last - line_start + 1;
|
||||
d = d1 + linesize * line_start;
|
||||
if (cw != 9) {
|
||||
if (cw == 16) {
|
||||
vga_draw_glyph16(d, linesize,
|
||||
cursor_glyph, h, fgcol, bgcol);
|
||||
} else if (cw != 9) {
|
||||
vga_draw_glyph8(d, linesize,
|
||||
cursor_glyph, h, fgcol, bgcol);
|
||||
} else {
|
||||
@@ -1518,93 +1364,32 @@ enum {
|
||||
VGA_DRAW_LINE4D2,
|
||||
VGA_DRAW_LINE8D2,
|
||||
VGA_DRAW_LINE8,
|
||||
VGA_DRAW_LINE15,
|
||||
VGA_DRAW_LINE16,
|
||||
VGA_DRAW_LINE24,
|
||||
VGA_DRAW_LINE32,
|
||||
VGA_DRAW_LINE15_LE,
|
||||
VGA_DRAW_LINE16_LE,
|
||||
VGA_DRAW_LINE24_LE,
|
||||
VGA_DRAW_LINE32_LE,
|
||||
VGA_DRAW_LINE15_BE,
|
||||
VGA_DRAW_LINE16_BE,
|
||||
VGA_DRAW_LINE24_BE,
|
||||
VGA_DRAW_LINE32_BE,
|
||||
VGA_DRAW_LINE_NB,
|
||||
};
|
||||
|
||||
static vga_draw_line_func * const vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
|
||||
vga_draw_line2_8,
|
||||
vga_draw_line2_16,
|
||||
vga_draw_line2_16,
|
||||
vga_draw_line2_32,
|
||||
vga_draw_line2_32,
|
||||
vga_draw_line2_16,
|
||||
vga_draw_line2_16,
|
||||
|
||||
vga_draw_line2d2_8,
|
||||
vga_draw_line2d2_16,
|
||||
vga_draw_line2d2_16,
|
||||
vga_draw_line2d2_32,
|
||||
vga_draw_line2d2_32,
|
||||
vga_draw_line2d2_16,
|
||||
vga_draw_line2d2_16,
|
||||
|
||||
vga_draw_line4_8,
|
||||
vga_draw_line4_16,
|
||||
vga_draw_line4_16,
|
||||
vga_draw_line4_32,
|
||||
vga_draw_line4_32,
|
||||
vga_draw_line4_16,
|
||||
vga_draw_line4_16,
|
||||
|
||||
vga_draw_line4d2_8,
|
||||
vga_draw_line4d2_16,
|
||||
vga_draw_line4d2_16,
|
||||
vga_draw_line4d2_32,
|
||||
vga_draw_line4d2_32,
|
||||
vga_draw_line4d2_16,
|
||||
vga_draw_line4d2_16,
|
||||
|
||||
vga_draw_line8d2_8,
|
||||
vga_draw_line8d2_16,
|
||||
vga_draw_line8d2_16,
|
||||
vga_draw_line8d2_32,
|
||||
vga_draw_line8d2_32,
|
||||
vga_draw_line8d2_16,
|
||||
vga_draw_line8d2_16,
|
||||
|
||||
vga_draw_line8_8,
|
||||
vga_draw_line8_16,
|
||||
vga_draw_line8_16,
|
||||
vga_draw_line8_32,
|
||||
vga_draw_line8_32,
|
||||
vga_draw_line8_16,
|
||||
vga_draw_line8_16,
|
||||
|
||||
vga_draw_line15_8,
|
||||
vga_draw_line15_15,
|
||||
vga_draw_line15_16,
|
||||
vga_draw_line15_32,
|
||||
vga_draw_line15_32bgr,
|
||||
vga_draw_line15_15bgr,
|
||||
vga_draw_line15_16bgr,
|
||||
|
||||
vga_draw_line16_8,
|
||||
vga_draw_line16_15,
|
||||
vga_draw_line16_16,
|
||||
vga_draw_line16_32,
|
||||
vga_draw_line16_32bgr,
|
||||
vga_draw_line16_15bgr,
|
||||
vga_draw_line16_16bgr,
|
||||
|
||||
vga_draw_line24_8,
|
||||
vga_draw_line24_15,
|
||||
vga_draw_line24_16,
|
||||
vga_draw_line24_32,
|
||||
vga_draw_line24_32bgr,
|
||||
vga_draw_line24_15bgr,
|
||||
vga_draw_line24_16bgr,
|
||||
|
||||
vga_draw_line32_8,
|
||||
vga_draw_line32_15,
|
||||
vga_draw_line32_16,
|
||||
vga_draw_line32_32,
|
||||
vga_draw_line32_32bgr,
|
||||
vga_draw_line32_15bgr,
|
||||
vga_draw_line32_16bgr,
|
||||
static vga_draw_line_func * const vga_draw_line_table[VGA_DRAW_LINE_NB] = {
|
||||
vga_draw_line2,
|
||||
vga_draw_line2d2,
|
||||
vga_draw_line4,
|
||||
vga_draw_line4d2,
|
||||
vga_draw_line8d2,
|
||||
vga_draw_line8,
|
||||
vga_draw_line15_le,
|
||||
vga_draw_line16_le,
|
||||
vga_draw_line24_le,
|
||||
vga_draw_line32_le,
|
||||
vga_draw_line15_be,
|
||||
vga_draw_line16_be,
|
||||
vga_draw_line24_be,
|
||||
vga_draw_line32_be,
|
||||
};
|
||||
|
||||
static int vga_get_bpp(VGACommonState *s)
|
||||
@@ -1676,11 +1461,11 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
|
||||
int disp_width, multi_scan, multi_run;
|
||||
uint8_t *d;
|
||||
uint32_t v, addr1, addr;
|
||||
vga_draw_line_func *vga_draw_line;
|
||||
#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
|
||||
static const bool byteswap = false;
|
||||
vga_draw_line_func *vga_draw_line = NULL;
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
bool byteswap = !s->big_endian_fb;
|
||||
#else
|
||||
static const bool byteswap = true;
|
||||
bool byteswap = s->big_endian_fb;
|
||||
#endif
|
||||
|
||||
full_update |= update_basic_params(s);
|
||||
@@ -1723,7 +1508,8 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
|
||||
if (s->line_offset != s->last_line_offset ||
|
||||
disp_width != s->last_width ||
|
||||
height != s->last_height ||
|
||||
s->last_depth != depth) {
|
||||
s->last_depth != depth ||
|
||||
s->last_byteswap != byteswap) {
|
||||
if (depth == 32 || (depth == 16 && !byteswap)) {
|
||||
pixman_format_code_t format =
|
||||
qemu_default_pixman_format(depth, !byteswap);
|
||||
@@ -1741,6 +1527,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
|
||||
s->last_height = height;
|
||||
s->last_line_offset = s->line_offset;
|
||||
s->last_depth = depth;
|
||||
s->last_byteswap = byteswap;
|
||||
full_update = 1;
|
||||
} else if (is_buffer_shared(surface) &&
|
||||
(full_update || surface_data(surface) != s->vram_ptr
|
||||
@@ -1753,9 +1540,6 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
|
||||
dpy_gfx_replace_surface(s->con, surface);
|
||||
}
|
||||
|
||||
s->rgb_to_pixel =
|
||||
rgb_to_pixel_dup_table[get_depth_index(surface)];
|
||||
|
||||
if (shift_control == 0) {
|
||||
full_update |= update_palette16(s);
|
||||
if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
|
||||
@@ -1786,25 +1570,24 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
|
||||
bits = 8;
|
||||
break;
|
||||
case 15:
|
||||
v = VGA_DRAW_LINE15;
|
||||
v = s->big_endian_fb ? VGA_DRAW_LINE15_BE : VGA_DRAW_LINE15_LE;
|
||||
bits = 16;
|
||||
break;
|
||||
case 16:
|
||||
v = VGA_DRAW_LINE16;
|
||||
v = s->big_endian_fb ? VGA_DRAW_LINE16_BE : VGA_DRAW_LINE16_LE;
|
||||
bits = 16;
|
||||
break;
|
||||
case 24:
|
||||
v = VGA_DRAW_LINE24;
|
||||
v = s->big_endian_fb ? VGA_DRAW_LINE24_BE : VGA_DRAW_LINE24_LE;
|
||||
bits = 24;
|
||||
break;
|
||||
case 32:
|
||||
v = VGA_DRAW_LINE32;
|
||||
v = s->big_endian_fb ? VGA_DRAW_LINE32_BE : VGA_DRAW_LINE32_LE;
|
||||
bits = 32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
vga_draw_line = vga_draw_line_table[v * NB_DEPTHS +
|
||||
get_depth_index(surface)];
|
||||
vga_draw_line = vga_draw_line_table[v];
|
||||
|
||||
if (!is_buffer_shared(surface) && s->cursor_invalidate) {
|
||||
s->cursor_invalidate(s);
|
||||
@@ -1894,7 +1677,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
|
||||
static void vga_draw_blank(VGACommonState *s, int full_update)
|
||||
{
|
||||
DisplaySurface *surface = qemu_console_surface(s->con);
|
||||
int i, w, val;
|
||||
int i, w;
|
||||
uint8_t *d;
|
||||
|
||||
if (!full_update)
|
||||
@@ -1902,17 +1685,10 @@ static void vga_draw_blank(VGACommonState *s, int full_update)
|
||||
if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
|
||||
return;
|
||||
|
||||
s->rgb_to_pixel =
|
||||
rgb_to_pixel_dup_table[get_depth_index(surface)];
|
||||
if (surface_bits_per_pixel(surface) == 8) {
|
||||
val = s->rgb_to_pixel(0, 0, 0);
|
||||
} else {
|
||||
val = 0;
|
||||
}
|
||||
w = s->last_scr_width * surface_bytes_per_pixel(surface);
|
||||
d = surface_data(surface);
|
||||
for(i = 0; i < s->last_scr_height; i++) {
|
||||
memset(d, val, w);
|
||||
memset(d, 0, w);
|
||||
d += surface_stride(surface);
|
||||
}
|
||||
dpy_gfx_update(s->con, 0, 0,
|
||||
@@ -2015,6 +1791,7 @@ void vga_common_reset(VGACommonState *s)
|
||||
s->cursor_start = 0;
|
||||
s->cursor_end = 0;
|
||||
s->cursor_offset = 0;
|
||||
s->big_endian_fb = s->default_endian_fb;
|
||||
memset(s->invalidated_y_table, '\0', sizeof(s->invalidated_y_table));
|
||||
memset(s->last_palette, '\0', sizeof(s->last_palette));
|
||||
memset(s->last_ch_attr, '\0', sizeof(s->last_ch_attr));
|
||||
@@ -2246,6 +2023,28 @@ static int vga_common_post_load(void *opaque, int version_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool vga_endian_state_needed(void *opaque)
|
||||
{
|
||||
VGACommonState *s = opaque;
|
||||
|
||||
/*
|
||||
* Only send the endian state if it's different from the
|
||||
* default one, thus ensuring backward compatibility for
|
||||
* migration of the common case
|
||||
*/
|
||||
return s->default_endian_fb != s->big_endian_fb;
|
||||
}
|
||||
|
||||
const VMStateDescription vmstate_vga_endian = {
|
||||
.name = "vga.endian",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_BOOL(big_endian_fb, VGACommonState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
const VMStateDescription vmstate_vga_common = {
|
||||
.name = "vga",
|
||||
.version_id = 2,
|
||||
@@ -2282,6 +2081,14 @@ const VMStateDescription vmstate_vga_common = {
|
||||
VMSTATE_UINT32(vbe_line_offset, VGACommonState),
|
||||
VMSTATE_UINT32(vbe_bank_mask, VGACommonState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
},
|
||||
.subsections = (VMStateSubsection []) {
|
||||
{
|
||||
.vmsd = &vmstate_vga_endian,
|
||||
.needed = vga_endian_state_needed,
|
||||
}, {
|
||||
/* empty */
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2350,6 +2157,17 @@ void vga_common_init(VGACommonState *s, Object *obj, bool global_vmstate)
|
||||
s->update_retrace_info = vga_precise_update_retrace_info;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set default fb endian based on target, could probably be turned
|
||||
* into a device attribute set by the machine/platform to remove
|
||||
* all target endian dependencies from this file.
|
||||
*/
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
s->default_endian_fb = true;
|
||||
#else
|
||||
s->default_endian_fb = false;
|
||||
#endif
|
||||
vga_dirty_log_start(s);
|
||||
}
|
||||
|
||||
|
||||
@@ -150,15 +150,16 @@ typedef struct VGACommonState {
|
||||
uint32_t last_width, last_height; /* in chars or pixels */
|
||||
uint32_t last_scr_width, last_scr_height; /* in pixels */
|
||||
uint32_t last_depth; /* in bits */
|
||||
bool last_byteswap;
|
||||
uint8_t cursor_start, cursor_end;
|
||||
bool cursor_visible_phase;
|
||||
int64_t cursor_blink_time;
|
||||
uint32_t cursor_offset;
|
||||
unsigned int (*rgb_to_pixel)(unsigned int r,
|
||||
unsigned int g, unsigned b);
|
||||
const GraphicHwOps *hw_ops;
|
||||
bool full_update_text;
|
||||
bool full_update_gfx;
|
||||
bool big_endian_fb;
|
||||
bool default_endian_fb;
|
||||
/* hardware mouse cursor support */
|
||||
uint32_t invalidated_y_table[VGA_MAX_HEIGHT / 32];
|
||||
void (*cursor_invalidate)(struct VGACommonState *s);
|
||||
|
||||
@@ -1825,8 +1825,6 @@ static int assigned_initfn(struct PCIDevice *pci_dev)
|
||||
|
||||
assigned_dev_load_option_rom(dev);
|
||||
|
||||
add_boot_device_path(dev->bootindex, &pci_dev->qdev, NULL);
|
||||
|
||||
return 0;
|
||||
|
||||
assigned_out:
|
||||
@@ -1850,13 +1848,22 @@ static void assigned_exitfn(struct PCIDevice *pci_dev)
|
||||
free_assigned_device(dev);
|
||||
}
|
||||
|
||||
static void assigned_dev_instance_init(Object *obj)
|
||||
{
|
||||
PCIDevice *pci_dev = PCI_DEVICE(obj);
|
||||
AssignedDevice *d = DO_UPCAST(AssignedDevice, dev, PCI_DEVICE(obj));
|
||||
|
||||
device_add_bootindex_property(obj, &d->bootindex,
|
||||
"bootindex", NULL,
|
||||
&pci_dev->qdev, NULL);
|
||||
}
|
||||
|
||||
static Property assigned_dev_properties[] = {
|
||||
DEFINE_PROP_PCI_HOST_DEVADDR("host", AssignedDevice, host),
|
||||
DEFINE_PROP_BIT("prefer_msi", AssignedDevice, features,
|
||||
ASSIGNED_DEVICE_PREFER_MSI_BIT, false),
|
||||
DEFINE_PROP_BIT("share_intx", AssignedDevice, features,
|
||||
ASSIGNED_DEVICE_SHARE_INTX_BIT, true),
|
||||
DEFINE_PROP_INT32("bootindex", AssignedDevice, bootindex, -1),
|
||||
DEFINE_PROP_STRING("configfd", AssignedDevice, configfd_name),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
@@ -1882,6 +1889,7 @@ static const TypeInfo assign_info = {
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(AssignedDevice),
|
||||
.class_init = assign_class_init,
|
||||
.instance_init = assigned_dev_instance_init,
|
||||
};
|
||||
|
||||
static void assign_register_types(void)
|
||||
|
||||
@@ -1524,6 +1524,7 @@ static void pc_generic_machine_class_init(ObjectClass *oc, void *data)
|
||||
mc->hot_add_cpu = qm->hot_add_cpu;
|
||||
mc->kvm_type = qm->kvm_type;
|
||||
mc->block_default_type = qm->block_default_type;
|
||||
mc->units_per_default_bus = qm->units_per_default_bus;
|
||||
mc->max_cpus = qm->max_cpus;
|
||||
mc->no_serial = qm->no_serial;
|
||||
mc->no_parallel = qm->no_parallel;
|
||||
|
||||
@@ -239,7 +239,7 @@ static void pc_init1(MachineState *machine,
|
||||
|
||||
pc_nic_init(isa_bus, pci_bus);
|
||||
|
||||
ide_drive_get(hd, MAX_IDE_BUS);
|
||||
ide_drive_get(hd, ARRAY_SIZE(hd));
|
||||
if (pci_enabled) {
|
||||
PCIDevice *dev;
|
||||
if (xen_enabled()) {
|
||||
|
||||
@@ -86,6 +86,7 @@ static void pc_q35_init(MachineState *machine)
|
||||
DeviceState *icc_bridge;
|
||||
PcGuestInfo *guest_info;
|
||||
ram_addr_t lowmem;
|
||||
DriveInfo *hd[MAX_SATA_PORTS];
|
||||
|
||||
/* Check whether RAM fits below 4G (leaving 1/2 GByte for IO memory
|
||||
* and 256 Mbytes for PCI Express Enhanced Configuration Access Mapping
|
||||
@@ -253,6 +254,9 @@ static void pc_q35_init(MachineState *machine)
|
||||
true, "ich9-ahci");
|
||||
idebus[0] = qdev_get_child_bus(&ahci->qdev, "ide.0");
|
||||
idebus[1] = qdev_get_child_bus(&ahci->qdev, "ide.1");
|
||||
g_assert_cmpint(MAX_SATA_PORTS, ==, ICH_AHCI(ahci)->ahci.ports);
|
||||
ide_drive_get(hd, ICH_AHCI(ahci)->ahci.ports);
|
||||
ahci_ide_create_devs(ahci, hd);
|
||||
|
||||
if (usb_enabled(false)) {
|
||||
/* Should we create 6 UHCI according to ich9 spec? */
|
||||
@@ -344,7 +348,8 @@ static void pc_q35_init_1_4(MachineState *machine)
|
||||
#define PC_Q35_MACHINE_OPTIONS \
|
||||
PC_DEFAULT_MACHINE_OPTIONS, \
|
||||
.desc = "Standard PC (Q35 + ICH9, 2009)", \
|
||||
.hot_add_cpu = pc_hot_add_cpu
|
||||
.hot_add_cpu = pc_hot_add_cpu, \
|
||||
.units_per_default_bus = 1
|
||||
|
||||
#define PC_Q35_2_2_MACHINE_OPTIONS \
|
||||
PC_Q35_MACHINE_OPTIONS, \
|
||||
|
||||
@@ -1419,3 +1419,18 @@ static void sysbus_ahci_register_types(void)
|
||||
}
|
||||
|
||||
type_init(sysbus_ahci_register_types)
|
||||
|
||||
void ahci_ide_create_devs(PCIDevice *dev, DriveInfo **hd)
|
||||
{
|
||||
AHCIPCIState *d = ICH_AHCI(dev);
|
||||
AHCIState *ahci = &d->ahci;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ahci->ports; i++) {
|
||||
if (hd[i] == NULL) {
|
||||
continue;
|
||||
}
|
||||
ide_create_drive(&ahci->dev[i].port, 0, hd[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -332,4 +332,6 @@ void ahci_uninit(AHCIState *s);
|
||||
|
||||
void ahci_reset(AHCIState *s);
|
||||
|
||||
void ahci_ide_create_devs(PCIDevice *dev, DriveInfo **hd);
|
||||
|
||||
#endif /* HW_IDE_AHCI_H */
|
||||
|
||||
@@ -2558,16 +2558,28 @@ const VMStateDescription vmstate_ide_bus = {
|
||||
}
|
||||
};
|
||||
|
||||
void ide_drive_get(DriveInfo **hd, int max_bus)
|
||||
void ide_drive_get(DriveInfo **hd, int n)
|
||||
{
|
||||
int i;
|
||||
int highest_bus = drive_get_max_bus(IF_IDE) + 1;
|
||||
int max_devs = drive_get_max_devs(IF_IDE);
|
||||
int n_buses = max_devs ? (n / max_devs) : n;
|
||||
|
||||
if (drive_get_max_bus(IF_IDE) >= max_bus) {
|
||||
fprintf(stderr, "qemu: too many IDE bus: %d\n", max_bus);
|
||||
/*
|
||||
* Note: The number of actual buses available is not known.
|
||||
* We compute this based on the size of the DriveInfo* array, n.
|
||||
* If it is less than max_devs * <num_real_buses>,
|
||||
* We will stop looking for drives prematurely instead of overfilling
|
||||
* the array.
|
||||
*/
|
||||
|
||||
if (highest_bus > n_buses) {
|
||||
error_report("Too many IDE buses defined (%d > %d)",
|
||||
highest_bus, n_buses);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for(i = 0; i < max_bus * MAX_IDE_DEVS; i++) {
|
||||
hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
|
||||
for (i = 0; i < n; i++) {
|
||||
hd[i] = drive_get_by_index(IF_IDE, i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "sysemu/blockdev.h"
|
||||
#include "hw/block/block.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qapi/visitor.h"
|
||||
|
||||
/* --------------------------------- */
|
||||
|
||||
@@ -191,6 +192,51 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ide_dev_get_bootindex(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
IDEDevice *d = IDE_DEVICE(obj);
|
||||
|
||||
visit_type_int32(v, &d->conf.bootindex, name, errp);
|
||||
}
|
||||
|
||||
static void ide_dev_set_bootindex(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
IDEDevice *d = IDE_DEVICE(obj);
|
||||
int32_t boot_index;
|
||||
Error *local_err = NULL;
|
||||
|
||||
visit_type_int32(v, &boot_index, name, &local_err);
|
||||
if (local_err) {
|
||||
goto out;
|
||||
}
|
||||
/* check whether bootindex is present in fw_boot_order list */
|
||||
check_boot_index(boot_index, &local_err);
|
||||
if (local_err) {
|
||||
goto out;
|
||||
}
|
||||
/* change bootindex to a new one */
|
||||
d->conf.bootindex = boot_index;
|
||||
|
||||
if (d->unit != -1) {
|
||||
add_boot_device_path(d->conf.bootindex, &d->qdev,
|
||||
d->unit ? "/disk@1" : "/disk@0");
|
||||
}
|
||||
out:
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
}
|
||||
}
|
||||
|
||||
static void ide_dev_instance_init(Object *obj)
|
||||
{
|
||||
object_property_add(obj, "bootindex", "int32",
|
||||
ide_dev_get_bootindex,
|
||||
ide_dev_set_bootindex, NULL, NULL, NULL);
|
||||
object_property_set_int(obj, -1, "bootindex", NULL);
|
||||
}
|
||||
|
||||
static int ide_hd_initfn(IDEDevice *dev)
|
||||
{
|
||||
return ide_dev_initfn(dev, IDE_HD);
|
||||
@@ -300,6 +346,7 @@ static const TypeInfo ide_device_type_info = {
|
||||
.abstract = true,
|
||||
.class_size = sizeof(IDEDeviceClass),
|
||||
.class_init = ide_device_class_init,
|
||||
.instance_init = ide_dev_instance_init,
|
||||
};
|
||||
|
||||
static void ide_register_types(void)
|
||||
|
||||
@@ -252,7 +252,7 @@ static void pc_dimm_realize(DeviceState *dev, Error **errp)
|
||||
error_setg(errp, "'" PC_DIMM_MEMDEV_PROP "' property is not set");
|
||||
return;
|
||||
}
|
||||
if (dimm->node >= nb_numa_nodes) {
|
||||
if ((nb_numa_nodes > 0) && (dimm->node >= nb_numa_nodes)) {
|
||||
error_setg(errp, "'DIMM property " PC_DIMM_NODE_PROP " has value %"
|
||||
PRIu32 "' which exceeds the number of numa nodes: %d",
|
||||
dimm->node, nb_numa_nodes);
|
||||
|
||||
@@ -350,7 +350,7 @@ static void mips_fulong2e_init(MachineState *machine)
|
||||
pci_bus = bonito_init((qemu_irq *)&(env->irq[2]));
|
||||
|
||||
/* South bridge */
|
||||
ide_drive_get(hd, MAX_IDE_BUS);
|
||||
ide_drive_get(hd, ARRAY_SIZE(hd));
|
||||
|
||||
isa_bus = vt82c686b_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 0));
|
||||
if (!isa_bus) {
|
||||
|
||||
@@ -1147,7 +1147,7 @@ void mips_malta_init(MachineState *machine)
|
||||
pci_bus = gt64120_register(isa_irq);
|
||||
|
||||
/* Southbridge */
|
||||
ide_drive_get(hd, MAX_IDE_BUS);
|
||||
ide_drive_get(hd, ARRAY_SIZE(hd));
|
||||
|
||||
piix4_devfn = piix4_init(pci_bus, &isa_bus, 80);
|
||||
|
||||
|
||||
@@ -294,7 +294,7 @@ void mips_r4k_init(MachineState *machine)
|
||||
if (nd_table[0].used)
|
||||
isa_ne2000_init(isa_bus, 0x300, 9, &nd_table[0]);
|
||||
|
||||
ide_drive_get(hd, MAX_IDE_BUS);
|
||||
ide_drive_get(hd, ARRAY_SIZE(hd));
|
||||
for(i = 0; i < MAX_IDE_BUS; i++)
|
||||
isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i], ide_irq[i],
|
||||
hd[MAX_IDE_DEVS * i],
|
||||
|
||||
@@ -4296,7 +4296,6 @@ static int vfio_initfn(PCIDevice *pdev)
|
||||
}
|
||||
}
|
||||
|
||||
add_boot_device_path(vdev->bootindex, &pdev->qdev, NULL);
|
||||
vfio_register_err_notifier(vdev);
|
||||
|
||||
return 0;
|
||||
@@ -4365,13 +4364,22 @@ post_reset:
|
||||
vfio_pci_post_reset(vdev);
|
||||
}
|
||||
|
||||
static void vfio_instance_init(Object *obj)
|
||||
{
|
||||
PCIDevice *pci_dev = PCI_DEVICE(obj);
|
||||
VFIODevice *vdev = DO_UPCAST(VFIODevice, pdev, PCI_DEVICE(obj));
|
||||
|
||||
device_add_bootindex_property(obj, &vdev->bootindex,
|
||||
"bootindex", NULL,
|
||||
&pci_dev->qdev, NULL);
|
||||
}
|
||||
|
||||
static Property vfio_pci_dev_properties[] = {
|
||||
DEFINE_PROP_PCI_HOST_DEVADDR("host", VFIODevice, host),
|
||||
DEFINE_PROP_UINT32("x-intx-mmap-timeout-ms", VFIODevice,
|
||||
intx.mmap_timeout, 1100),
|
||||
DEFINE_PROP_BIT("x-vga", VFIODevice, features,
|
||||
VFIO_FEATURE_ENABLE_VGA_BIT, false),
|
||||
DEFINE_PROP_INT32("bootindex", VFIODevice, bootindex, -1),
|
||||
/*
|
||||
* TODO - support passed fds... is this necessary?
|
||||
* DEFINE_PROP_STRING("vfiofd", VFIODevice, vfiofd_name),
|
||||
@@ -4407,6 +4415,7 @@ static const TypeInfo vfio_pci_dev_info = {
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(VFIODevice),
|
||||
.class_init = vfio_pci_dev_class_init,
|
||||
.instance_init = vfio_instance_init,
|
||||
};
|
||||
|
||||
static void register_vfio_pci_dev_type(void)
|
||||
|
||||
@@ -1569,8 +1569,6 @@ static int pci_e1000_init(PCIDevice *pci_dev)
|
||||
|
||||
qemu_format_nic_info_str(qemu_get_queue(d->nic), macaddr);
|
||||
|
||||
add_boot_device_path(d->conf.bootindex, dev, "/ethernet-phy@0");
|
||||
|
||||
d->autoneg_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, e1000_autoneg_timer, d);
|
||||
d->mit_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, e1000_mit_timer, d);
|
||||
|
||||
@@ -1621,10 +1619,19 @@ static void e1000_class_init(ObjectClass *klass, void *data)
|
||||
dc->props = e1000_properties;
|
||||
}
|
||||
|
||||
static void e1000_instance_init(Object *obj)
|
||||
{
|
||||
E1000State *n = E1000(obj);
|
||||
device_add_bootindex_property(obj, &n->conf.bootindex,
|
||||
"bootindex", "/ethernet-phy@0",
|
||||
DEVICE(n), NULL);
|
||||
}
|
||||
|
||||
static const TypeInfo e1000_base_info = {
|
||||
.name = TYPE_E1000_BASE,
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(E1000State),
|
||||
.instance_init = e1000_instance_init,
|
||||
.class_size = sizeof(E1000BaseClass),
|
||||
.abstract = true,
|
||||
};
|
||||
@@ -1668,6 +1675,7 @@ static void e1000_register_types(void)
|
||||
type_info.parent = TYPE_E1000_BASE;
|
||||
type_info.class_data = (void *)info;
|
||||
type_info.class_init = e1000_class_init;
|
||||
type_info.instance_init = e1000_instance_init;
|
||||
|
||||
type_register(&type_info);
|
||||
}
|
||||
|
||||
@@ -1901,11 +1901,17 @@ static int e100_nic_init(PCIDevice *pci_dev)
|
||||
s->vmstate->name = qemu_get_queue(s->nic)->model;
|
||||
vmstate_register(&pci_dev->qdev, -1, s->vmstate, s);
|
||||
|
||||
add_boot_device_path(s->conf.bootindex, &pci_dev->qdev, "/ethernet-phy@0");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void eepro100_instance_init(Object *obj)
|
||||
{
|
||||
EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, PCI_DEVICE(obj));
|
||||
device_add_bootindex_property(obj, &s->conf.bootindex,
|
||||
"bootindex", "/ethernet-phy@0",
|
||||
DEVICE(s), NULL);
|
||||
}
|
||||
|
||||
static E100PCIDeviceInfo e100_devices[] = {
|
||||
{
|
||||
.name = "i82550",
|
||||
@@ -2104,7 +2110,8 @@ static void eepro100_register_types(void)
|
||||
type_info.parent = TYPE_PCI_DEVICE;
|
||||
type_info.class_init = eepro100_class_init;
|
||||
type_info.instance_size = sizeof(EEPRO100State);
|
||||
|
||||
type_info.instance_init = eepro100_instance_init;
|
||||
|
||||
type_register(&type_info);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "hw/sparc/sun4m.h"
|
||||
#include "pcnet.h"
|
||||
#include "trace.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
|
||||
#define TYPE_LANCE "lance"
|
||||
#define SYSBUS_PCNET(obj) \
|
||||
@@ -143,6 +144,16 @@ static void lance_reset(DeviceState *dev)
|
||||
pcnet_h_reset(&d->state);
|
||||
}
|
||||
|
||||
static void lance_instance_init(Object *obj)
|
||||
{
|
||||
SysBusPCNetState *d = SYSBUS_PCNET(obj);
|
||||
PCNetState *s = &d->state;
|
||||
|
||||
device_add_bootindex_property(obj, &s->conf.bootindex,
|
||||
"bootindex", "/ethernet-phy@0",
|
||||
DEVICE(obj), NULL);
|
||||
}
|
||||
|
||||
static Property lance_properties[] = {
|
||||
DEFINE_PROP_PTR("dma", SysBusPCNetState, state.dma_opaque),
|
||||
DEFINE_NIC_PROPERTIES(SysBusPCNetState, state.conf),
|
||||
@@ -169,6 +180,7 @@ static const TypeInfo lance_info = {
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(SysBusPCNetState),
|
||||
.class_init = lance_class_init,
|
||||
.instance_init = lance_instance_init,
|
||||
};
|
||||
|
||||
static void lance_register_types(void)
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "net/net.h"
|
||||
#include "ne2000.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "qapi/visitor.h"
|
||||
|
||||
#define TYPE_ISA_NE2000 "ne2k_isa"
|
||||
#define ISA_NE2000(obj) OBJECT_CHECK(ISANE2000State, (obj), TYPE_ISA_NE2000)
|
||||
@@ -101,11 +102,54 @@ static void isa_ne2000_class_initfn(ObjectClass *klass, void *data)
|
||||
set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
|
||||
}
|
||||
|
||||
static void isa_ne2000_get_bootindex(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
ISANE2000State *isa = ISA_NE2000(obj);
|
||||
NE2000State *s = &isa->ne2000;
|
||||
|
||||
visit_type_int32(v, &s->c.bootindex, name, errp);
|
||||
}
|
||||
|
||||
static void isa_ne2000_set_bootindex(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
ISANE2000State *isa = ISA_NE2000(obj);
|
||||
NE2000State *s = &isa->ne2000;
|
||||
int32_t boot_index;
|
||||
Error *local_err = NULL;
|
||||
|
||||
visit_type_int32(v, &boot_index, name, &local_err);
|
||||
if (local_err) {
|
||||
goto out;
|
||||
}
|
||||
/* check whether bootindex is present in fw_boot_order list */
|
||||
check_boot_index(boot_index, &local_err);
|
||||
if (local_err) {
|
||||
goto out;
|
||||
}
|
||||
/* change bootindex to a new one */
|
||||
s->c.bootindex = boot_index;
|
||||
|
||||
out:
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
}
|
||||
}
|
||||
|
||||
static void isa_ne2000_instance_init(Object *obj)
|
||||
{
|
||||
object_property_add(obj, "bootindex", "int32",
|
||||
isa_ne2000_get_bootindex,
|
||||
isa_ne2000_set_bootindex, NULL, NULL, NULL);
|
||||
object_property_set_int(obj, -1, "bootindex", NULL);
|
||||
}
|
||||
static const TypeInfo ne2000_isa_info = {
|
||||
.name = TYPE_ISA_NE2000,
|
||||
.parent = TYPE_ISA_DEVICE,
|
||||
.instance_size = sizeof(ISANE2000State),
|
||||
.class_init = isa_ne2000_class_initfn,
|
||||
.instance_init = isa_ne2000_instance_init,
|
||||
};
|
||||
|
||||
static void ne2000_isa_register_types(void)
|
||||
|
||||
@@ -738,8 +738,6 @@ static int pci_ne2000_init(PCIDevice *pci_dev)
|
||||
object_get_typename(OBJECT(pci_dev)), pci_dev->qdev.id, s);
|
||||
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->c.macaddr.a);
|
||||
|
||||
add_boot_device_path(s->c.bootindex, &pci_dev->qdev, "/ethernet-phy@0");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -752,6 +750,17 @@ static void pci_ne2000_exit(PCIDevice *pci_dev)
|
||||
qemu_free_irq(s->irq);
|
||||
}
|
||||
|
||||
static void ne2000_instance_init(Object *obj)
|
||||
{
|
||||
PCIDevice *pci_dev = PCI_DEVICE(obj);
|
||||
PCINE2000State *d = DO_UPCAST(PCINE2000State, dev, pci_dev);
|
||||
NE2000State *s = &d->ne2000;
|
||||
|
||||
device_add_bootindex_property(obj, &s->c.bootindex,
|
||||
"bootindex", "/ethernet-phy@0",
|
||||
&pci_dev->qdev, NULL);
|
||||
}
|
||||
|
||||
static Property ne2000_properties[] = {
|
||||
DEFINE_NIC_PROPERTIES(PCINE2000State, ne2000.c),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
@@ -778,6 +787,7 @@ static const TypeInfo ne2000_info = {
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(PCINE2000State),
|
||||
.class_init = ne2000_class_init,
|
||||
.instance_init = ne2000_instance_init,
|
||||
};
|
||||
|
||||
static void ne2000_register_types(void)
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "hw/loader.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "sysemu/dma.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
|
||||
#include "pcnet.h"
|
||||
|
||||
@@ -344,6 +345,16 @@ static void pci_reset(DeviceState *dev)
|
||||
pcnet_h_reset(&d->state);
|
||||
}
|
||||
|
||||
static void pcnet_instance_init(Object *obj)
|
||||
{
|
||||
PCIPCNetState *d = PCI_PCNET(obj);
|
||||
PCNetState *s = &d->state;
|
||||
|
||||
device_add_bootindex_property(obj, &s->conf.bootindex,
|
||||
"bootindex", "/ethernet-phy@0",
|
||||
DEVICE(obj), NULL);
|
||||
}
|
||||
|
||||
static Property pcnet_properties[] = {
|
||||
DEFINE_NIC_PROPERTIES(PCIPCNetState, state.conf),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
@@ -372,6 +383,7 @@ static const TypeInfo pcnet_info = {
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(PCIPCNetState),
|
||||
.class_init = pcnet_class_init,
|
||||
.instance_init = pcnet_instance_init,
|
||||
};
|
||||
|
||||
static void pci_pcnet_register_types(void)
|
||||
|
||||
@@ -1735,8 +1735,6 @@ int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info)
|
||||
s->nic = qemu_new_nic(info, &s->conf, object_get_typename(OBJECT(dev)), dev->id, s);
|
||||
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
|
||||
|
||||
add_boot_device_path(s->conf.bootindex, dev, "/ethernet-phy@0");
|
||||
|
||||
/* Initialize the PROM */
|
||||
|
||||
/*
|
||||
|
||||
@@ -66,5 +66,4 @@ void pcnet_set_link_status(NetClientState *nc);
|
||||
void pcnet_common_cleanup(PCNetState *d);
|
||||
int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info);
|
||||
extern const VMStateDescription vmstate_pcnet;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3538,11 +3538,18 @@ static int pci_rtl8139_init(PCIDevice *dev)
|
||||
s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, rtl8139_timer, s);
|
||||
rtl8139_set_next_tctr_time(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
|
||||
|
||||
add_boot_device_path(s->conf.bootindex, d, "/ethernet-phy@0");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtl8139_instance_init(Object *obj)
|
||||
{
|
||||
RTL8139State *s = RTL8139(obj);
|
||||
|
||||
device_add_bootindex_property(obj, &s->conf.bootindex,
|
||||
"bootindex", "/ethernet-phy@0",
|
||||
DEVICE(obj), NULL);
|
||||
}
|
||||
|
||||
static Property rtl8139_properties[] = {
|
||||
DEFINE_NIC_PROPERTIES(RTL8139State, conf),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
@@ -3571,6 +3578,7 @@ static const TypeInfo rtl8139_info = {
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(RTL8139State),
|
||||
.class_init = rtl8139_class_init,
|
||||
.instance_init = rtl8139_instance_init,
|
||||
};
|
||||
|
||||
static void rtl8139_register_types(void)
|
||||
|
||||
@@ -221,11 +221,18 @@ static int spapr_vlan_init(VIOsPAPRDevice *sdev)
|
||||
object_get_typename(OBJECT(sdev)), sdev->qdev.id, dev);
|
||||
qemu_format_nic_info_str(qemu_get_queue(dev->nic), dev->nicconf.macaddr.a);
|
||||
|
||||
add_boot_device_path(dev->nicconf.bootindex, DEVICE(dev), "");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void spapr_vlan_instance_init(Object *obj)
|
||||
{
|
||||
VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(obj);
|
||||
|
||||
device_add_bootindex_property(obj, &dev->nicconf.bootindex,
|
||||
"bootindex", "",
|
||||
DEVICE(dev), NULL);
|
||||
}
|
||||
|
||||
void spapr_vlan_create(VIOsPAPRBus *bus, NICInfo *nd)
|
||||
{
|
||||
DeviceState *dev;
|
||||
@@ -553,6 +560,7 @@ static const TypeInfo spapr_vlan_info = {
|
||||
.parent = TYPE_VIO_SPAPR_DEVICE,
|
||||
.instance_size = sizeof(VIOsPAPRVLANDevice),
|
||||
.class_init = spapr_vlan_class_init,
|
||||
.instance_init = spapr_vlan_instance_init,
|
||||
};
|
||||
|
||||
static void spapr_vlan_register_types(void)
|
||||
|
||||
@@ -1661,8 +1661,6 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
|
||||
n->qdev = dev;
|
||||
register_savevm(dev, "virtio-net", -1, VIRTIO_NET_VM_VERSION,
|
||||
virtio_net_save, virtio_net_load, n);
|
||||
|
||||
add_boot_device_path(n->nic_conf.bootindex, dev, "/ethernet-phy@0");
|
||||
}
|
||||
|
||||
static void virtio_net_device_unrealize(DeviceState *dev, Error **errp)
|
||||
@@ -1714,6 +1712,9 @@ static void virtio_net_instance_init(Object *obj)
|
||||
* Can be overriden with virtio_net_set_config_size.
|
||||
*/
|
||||
n->config_size = sizeof(struct virtio_net_config);
|
||||
device_add_bootindex_property(obj, &n->nic_conf.bootindex,
|
||||
"bootindex", "/ethernet-phy@0",
|
||||
DEVICE(n), NULL);
|
||||
}
|
||||
|
||||
static Property virtio_net_properties[] = {
|
||||
|
||||
@@ -2172,11 +2172,16 @@ static int vmxnet3_pci_init(PCIDevice *pci_dev)
|
||||
register_savevm(dev, "vmxnet3-msix", -1, 1,
|
||||
vmxnet3_msix_save, vmxnet3_msix_load, s);
|
||||
|
||||
add_boot_device_path(s->conf.bootindex, dev, "/ethernet-phy@0");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vmxnet3_instance_init(Object *obj)
|
||||
{
|
||||
VMXNET3State *s = VMXNET3(obj);
|
||||
device_add_bootindex_property(obj, &s->conf.bootindex,
|
||||
"bootindex", "/ethernet-phy@0",
|
||||
DEVICE(obj), NULL);
|
||||
}
|
||||
|
||||
static void vmxnet3_pci_uninit(PCIDevice *pci_dev)
|
||||
{
|
||||
@@ -2524,6 +2529,7 @@ static const TypeInfo vmxnet3_info = {
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(VMXNET3State),
|
||||
.class_init = vmxnet3_class_init,
|
||||
.instance_init = vmxnet3_instance_init,
|
||||
};
|
||||
|
||||
static void vmxnet3_register_types(void)
|
||||
|
||||
@@ -402,6 +402,26 @@ static void fw_cfg_add_bytes_read_callback(FWCfgState *s, uint16_t key,
|
||||
s->entries[arch][key].callback_opaque = callback_opaque;
|
||||
}
|
||||
|
||||
static void *fw_cfg_modify_bytes_read(FWCfgState *s, uint16_t key,
|
||||
void *data, size_t len)
|
||||
{
|
||||
void *ptr;
|
||||
int arch = !!(key & FW_CFG_ARCH_LOCAL);
|
||||
|
||||
key &= FW_CFG_ENTRY_MASK;
|
||||
|
||||
assert(key < FW_CFG_MAX_ENTRY && len < UINT32_MAX);
|
||||
|
||||
/* return the old data to the function caller, avoid memory leak */
|
||||
ptr = s->entries[arch][key].data;
|
||||
s->entries[arch][key].data = data;
|
||||
s->entries[arch][key].len = len;
|
||||
s->entries[arch][key].callback_opaque = NULL;
|
||||
s->entries[arch][key].callback = NULL;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len)
|
||||
{
|
||||
fw_cfg_add_bytes_read_callback(s, key, NULL, NULL, data, len);
|
||||
@@ -499,13 +519,42 @@ void fw_cfg_add_file(FWCfgState *s, const char *filename,
|
||||
fw_cfg_add_file_callback(s, filename, NULL, NULL, data, len);
|
||||
}
|
||||
|
||||
static void fw_cfg_machine_ready(struct Notifier *n, void *data)
|
||||
void *fw_cfg_modify_file(FWCfgState *s, const char *filename,
|
||||
void *data, size_t len)
|
||||
{
|
||||
int i, index;
|
||||
|
||||
assert(s->files);
|
||||
|
||||
index = be32_to_cpu(s->files->count);
|
||||
assert(index < FW_CFG_FILE_SLOTS);
|
||||
|
||||
for (i = 0; i < index; i++) {
|
||||
if (strcmp(filename, s->files->f[i].name) == 0) {
|
||||
return fw_cfg_modify_bytes_read(s, FW_CFG_FILE_FIRST + i,
|
||||
data, len);
|
||||
}
|
||||
}
|
||||
/* add new one */
|
||||
fw_cfg_add_file_callback(s, filename, NULL, NULL, data, len);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void fw_cfg_machine_reset(void *opaque)
|
||||
{
|
||||
void *ptr;
|
||||
size_t len;
|
||||
FWCfgState *s = container_of(n, FWCfgState, machine_ready);
|
||||
FWCfgState *s = opaque;
|
||||
char *bootindex = get_boot_devices_list(&len, false);
|
||||
|
||||
fw_cfg_add_file(s, "bootorder", (uint8_t*)bootindex, len);
|
||||
ptr = fw_cfg_modify_file(s, "bootorder", (uint8_t *)bootindex, len);
|
||||
g_free(ptr);
|
||||
}
|
||||
|
||||
static void fw_cfg_machine_ready(struct Notifier *n, void *data)
|
||||
{
|
||||
FWCfgState *s = container_of(n, FWCfgState, machine_ready);
|
||||
qemu_register_reset(fw_cfg_machine_reset, s);
|
||||
}
|
||||
|
||||
FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
|
||||
|
||||
@@ -107,6 +107,7 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter,
|
||||
{
|
||||
SCSIBus *scsibus;
|
||||
SCSIDevice *scsidev;
|
||||
Error *local_err = NULL;
|
||||
|
||||
scsibus = (SCSIBus *)
|
||||
object_dynamic_cast(OBJECT(QLIST_FIRST(&adapter->child_bus)),
|
||||
@@ -127,8 +128,10 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter,
|
||||
dinfo->unit = qemu_opt_get_number(dinfo->opts, "unit", -1);
|
||||
dinfo->bus = scsibus->busnr;
|
||||
scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit,
|
||||
false, -1, NULL, NULL);
|
||||
false, -1, NULL, &local_err);
|
||||
if (!scsidev) {
|
||||
error_report("%s", error_get_pretty(local_err));
|
||||
error_free(local_err);
|
||||
return -1;
|
||||
}
|
||||
dinfo->unit = scsidev->id;
|
||||
|
||||
@@ -400,7 +400,7 @@ static void ppc_core99_init(MachineState *machine)
|
||||
macio_init(macio, pic_mem, escc_bar);
|
||||
|
||||
/* We only emulate 2 out of 3 IDE controllers for now */
|
||||
ide_drive_get(hd, MAX_IDE_BUS);
|
||||
ide_drive_get(hd, ARRAY_SIZE(hd));
|
||||
|
||||
macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio),
|
||||
"ide[0]"));
|
||||
|
||||
@@ -278,7 +278,7 @@ static void ppc_heathrow_init(MachineState *machine)
|
||||
pci_nic_init_nofail(&nd_table[i], pci_bus, "ne2k_pci", NULL);
|
||||
|
||||
|
||||
ide_drive_get(hd, MAX_IDE_BUS);
|
||||
ide_drive_get(hd, ARRAY_SIZE(hd));
|
||||
|
||||
macio = pci_create(pci_bus, -1, TYPE_OLDWORLD_MACIO);
|
||||
dev = DEVICE(macio);
|
||||
|
||||
@@ -519,7 +519,7 @@ static void ppc_prep_init(MachineState *machine)
|
||||
}
|
||||
}
|
||||
|
||||
ide_drive_get(hd, MAX_IDE_BUS);
|
||||
ide_drive_get(hd, ARRAY_SIZE(hd));
|
||||
for(i = 0; i < MAX_IDE_BUS; i++) {
|
||||
isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i], ide_irq[i],
|
||||
hd[2 * i],
|
||||
|
||||
@@ -176,7 +176,7 @@ static void s390_ipl_reset(DeviceState *dev)
|
||||
}
|
||||
}
|
||||
|
||||
s390_add_running_cpu(cpu);
|
||||
s390_cpu_set_state(CPU_STATE_OPERATING, cpu);
|
||||
}
|
||||
|
||||
static void s390_ipl_class_init(ObjectClass *klass, void *data)
|
||||
|
||||
@@ -159,8 +159,11 @@ static int s390_virtio_net_init(VirtIOS390Device *s390_dev)
|
||||
static void s390_virtio_net_instance_init(Object *obj)
|
||||
{
|
||||
VirtIONetS390 *dev = VIRTIO_NET_S390(obj);
|
||||
object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_NET);
|
||||
object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
|
||||
|
||||
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
|
||||
TYPE_VIRTIO_NET);
|
||||
object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev),
|
||||
"bootindex", &error_abort);
|
||||
}
|
||||
|
||||
static int s390_virtio_blk_init(VirtIOS390Device *s390_dev)
|
||||
@@ -177,12 +180,13 @@ static int s390_virtio_blk_init(VirtIOS390Device *s390_dev)
|
||||
static void s390_virtio_blk_instance_init(Object *obj)
|
||||
{
|
||||
VirtIOBlkS390 *dev = VIRTIO_BLK_S390(obj);
|
||||
object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_BLK);
|
||||
object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
|
||||
object_unref(OBJECT(&dev->vdev));
|
||||
qdev_alias_all_properties(DEVICE(&dev->vdev), obj);
|
||||
|
||||
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
|
||||
TYPE_VIRTIO_BLK);
|
||||
object_property_add_alias(obj, "iothread", OBJECT(&dev->vdev),"iothread",
|
||||
&error_abort);
|
||||
object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev),
|
||||
"bootindex", &error_abort);
|
||||
}
|
||||
|
||||
static int s390_virtio_serial_init(VirtIOS390Device *s390_dev)
|
||||
@@ -222,8 +226,9 @@ static int s390_virtio_serial_init(VirtIOS390Device *s390_dev)
|
||||
static void s390_virtio_serial_instance_init(Object *obj)
|
||||
{
|
||||
VirtIOSerialS390 *dev = VIRTIO_SERIAL_S390(obj);
|
||||
object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_SERIAL);
|
||||
object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
|
||||
|
||||
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
|
||||
TYPE_VIRTIO_SERIAL);
|
||||
}
|
||||
|
||||
static int s390_virtio_scsi_init(VirtIOS390Device *s390_dev)
|
||||
@@ -254,8 +259,9 @@ static int s390_virtio_scsi_init(VirtIOS390Device *s390_dev)
|
||||
static void s390_virtio_scsi_instance_init(Object *obj)
|
||||
{
|
||||
VirtIOSCSIS390 *dev = VIRTIO_SCSI_S390(obj);
|
||||
object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_SCSI);
|
||||
object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
|
||||
|
||||
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
|
||||
TYPE_VIRTIO_SCSI);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VHOST_SCSI
|
||||
@@ -275,8 +281,9 @@ static int s390_vhost_scsi_init(VirtIOS390Device *s390_dev)
|
||||
static void s390_vhost_scsi_instance_init(Object *obj)
|
||||
{
|
||||
VHostSCSIS390 *dev = VHOST_SCSI_S390(obj);
|
||||
object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VHOST_SCSI);
|
||||
object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
|
||||
|
||||
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
|
||||
TYPE_VHOST_SCSI);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -301,8 +308,9 @@ static int s390_virtio_rng_init(VirtIOS390Device *s390_dev)
|
||||
static void s390_virtio_rng_instance_init(Object *obj)
|
||||
{
|
||||
VirtIORNGS390 *dev = VIRTIO_RNG_S390(obj);
|
||||
object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_RNG);
|
||||
object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
|
||||
|
||||
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
|
||||
TYPE_VIRTIO_RNG);
|
||||
object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
|
||||
(Object **)&dev->vdev.conf.rng,
|
||||
qdev_prop_allow_set_link_before_realize,
|
||||
@@ -493,10 +501,8 @@ static unsigned virtio_s390_get_features(DeviceState *d)
|
||||
/**************** S390 Virtio Bus Device Descriptions *******************/
|
||||
|
||||
static Property s390_virtio_net_properties[] = {
|
||||
DEFINE_NIC_PROPERTIES(VirtIONetS390, vdev.nic_conf),
|
||||
DEFINE_VIRTIO_COMMON_FEATURES(VirtIOS390Device, host_features),
|
||||
DEFINE_VIRTIO_NET_FEATURES(VirtIOS390Device, host_features),
|
||||
DEFINE_VIRTIO_NET_PROPERTIES(VirtIONetS390, vdev.net_conf),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
@@ -533,7 +539,6 @@ static const TypeInfo s390_virtio_blk = {
|
||||
};
|
||||
|
||||
static Property s390_virtio_serial_properties[] = {
|
||||
DEFINE_VIRTIO_SERIAL_PROPERTIES(VirtIOSerialS390, vdev.serial),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
@@ -556,7 +561,6 @@ static const TypeInfo s390_virtio_serial = {
|
||||
|
||||
static Property s390_virtio_rng_properties[] = {
|
||||
DEFINE_VIRTIO_COMMON_FEATURES(VirtIOS390Device, host_features),
|
||||
DEFINE_VIRTIO_RNG_PROPERTIES(VirtIORNGS390, vdev.conf),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
@@ -614,7 +618,6 @@ static const TypeInfo virtio_s390_device_info = {
|
||||
};
|
||||
|
||||
static Property s390_virtio_scsi_properties[] = {
|
||||
DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSIS390, vdev.parent_obj.conf),
|
||||
DEFINE_VIRTIO_COMMON_FEATURES(VirtIOS390Device, host_features),
|
||||
DEFINE_VIRTIO_SCSI_FEATURES(VirtIOS390Device, host_features),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
@@ -640,7 +643,6 @@ static const TypeInfo s390_virtio_scsi = {
|
||||
#ifdef CONFIG_VHOST_SCSI
|
||||
static Property s390_vhost_scsi_properties[] = {
|
||||
DEFINE_VIRTIO_COMMON_FEATURES(VirtIOS390Device, host_features),
|
||||
DEFINE_VHOST_SCSI_PROPERTIES(VHostSCSIS390, vdev.parent_obj.conf),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
|
||||
@@ -125,38 +125,6 @@ static void s390_virtio_register_hcalls(void)
|
||||
s390_virtio_hcall_set_status);
|
||||
}
|
||||
|
||||
/*
|
||||
* The number of running CPUs. On s390 a shutdown is the state of all CPUs
|
||||
* being either stopped or disabled (for interrupts) waiting. We have to
|
||||
* track this number to call the shutdown sequence accordingly. This
|
||||
* number is modified either on startup or while holding the big qemu lock.
|
||||
*/
|
||||
static unsigned s390_running_cpus;
|
||||
|
||||
void s390_add_running_cpu(S390CPU *cpu)
|
||||
{
|
||||
CPUState *cs = CPU(cpu);
|
||||
|
||||
if (cs->halted) {
|
||||
s390_running_cpus++;
|
||||
cs->halted = 0;
|
||||
cs->exception_index = -1;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned s390_del_running_cpu(S390CPU *cpu)
|
||||
{
|
||||
CPUState *cs = CPU(cpu);
|
||||
|
||||
if (cs->halted == 0) {
|
||||
assert(s390_running_cpus >= 1);
|
||||
s390_running_cpus--;
|
||||
cs->halted = 1;
|
||||
cs->exception_index = EXCP_HLT;
|
||||
}
|
||||
return s390_running_cpus;
|
||||
}
|
||||
|
||||
void s390_init_ipl_dev(const char *kernel_filename,
|
||||
const char *kernel_cmdline,
|
||||
const char *initrd_filename,
|
||||
|
||||
@@ -792,8 +792,11 @@ static int virtio_ccw_net_init(VirtioCcwDevice *ccw_dev)
|
||||
static void virtio_ccw_net_instance_init(Object *obj)
|
||||
{
|
||||
VirtIONetCcw *dev = VIRTIO_NET_CCW(obj);
|
||||
object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_NET);
|
||||
object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
|
||||
|
||||
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
|
||||
TYPE_VIRTIO_NET);
|
||||
object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev),
|
||||
"bootindex", &error_abort);
|
||||
}
|
||||
|
||||
static int virtio_ccw_blk_init(VirtioCcwDevice *ccw_dev)
|
||||
@@ -811,12 +814,13 @@ static int virtio_ccw_blk_init(VirtioCcwDevice *ccw_dev)
|
||||
static void virtio_ccw_blk_instance_init(Object *obj)
|
||||
{
|
||||
VirtIOBlkCcw *dev = VIRTIO_BLK_CCW(obj);
|
||||
object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_BLK);
|
||||
object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
|
||||
object_unref(OBJECT(&dev->vdev));
|
||||
qdev_alias_all_properties(DEVICE(&dev->vdev), obj);
|
||||
|
||||
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
|
||||
TYPE_VIRTIO_BLK);
|
||||
object_property_add_alias(obj, "iothread", OBJECT(&dev->vdev),"iothread",
|
||||
&error_abort);
|
||||
object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev),
|
||||
"bootindex", &error_abort);
|
||||
}
|
||||
|
||||
static int virtio_ccw_serial_init(VirtioCcwDevice *ccw_dev)
|
||||
@@ -848,8 +852,9 @@ static int virtio_ccw_serial_init(VirtioCcwDevice *ccw_dev)
|
||||
static void virtio_ccw_serial_instance_init(Object *obj)
|
||||
{
|
||||
VirtioSerialCcw *dev = VIRTIO_SERIAL_CCW(obj);
|
||||
object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_SERIAL);
|
||||
object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
|
||||
|
||||
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
|
||||
TYPE_VIRTIO_SERIAL);
|
||||
}
|
||||
|
||||
static int virtio_ccw_balloon_init(VirtioCcwDevice *ccw_dev)
|
||||
@@ -896,7 +901,7 @@ static void virtio_ccw_balloon_instance_init(Object *obj)
|
||||
VirtIOBalloonCcw *dev = VIRTIO_BALLOON_CCW(obj);
|
||||
object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_BALLOON);
|
||||
object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
|
||||
|
||||
object_unref(OBJECT(&dev->vdev));
|
||||
object_property_add(obj, "guest-stats", "guest statistics",
|
||||
balloon_ccw_stats_get_all, NULL, NULL, dev, NULL);
|
||||
|
||||
@@ -934,8 +939,11 @@ static int virtio_ccw_scsi_init(VirtioCcwDevice *ccw_dev)
|
||||
static void virtio_ccw_scsi_instance_init(Object *obj)
|
||||
{
|
||||
VirtIOSCSICcw *dev = VIRTIO_SCSI_CCW(obj);
|
||||
object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_SCSI);
|
||||
object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
|
||||
|
||||
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
|
||||
TYPE_VIRTIO_SCSI);
|
||||
object_property_add_alias(obj, "iothread", OBJECT(&dev->vdev), "iothread",
|
||||
&error_abort);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VHOST_SCSI
|
||||
@@ -955,8 +963,9 @@ static int vhost_ccw_scsi_init(VirtioCcwDevice *ccw_dev)
|
||||
static void vhost_ccw_scsi_instance_init(Object *obj)
|
||||
{
|
||||
VHostSCSICcw *dev = VHOST_SCSI_CCW(obj);
|
||||
object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VHOST_SCSI);
|
||||
object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
|
||||
|
||||
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
|
||||
TYPE_VHOST_SCSI);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1374,8 +1383,6 @@ static int virtio_ccw_load_config(DeviceState *d, QEMUFile *f)
|
||||
static Property virtio_ccw_net_properties[] = {
|
||||
DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
|
||||
DEFINE_VIRTIO_NET_FEATURES(VirtioCcwDevice, host_features[0]),
|
||||
DEFINE_VIRTIO_NET_PROPERTIES(VirtIONetCcw, vdev.net_conf),
|
||||
DEFINE_NIC_PROPERTIES(VirtIONetCcw, vdev.nic_conf),
|
||||
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
|
||||
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
@@ -1428,7 +1435,6 @@ static const TypeInfo virtio_ccw_blk = {
|
||||
|
||||
static Property virtio_ccw_serial_properties[] = {
|
||||
DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
|
||||
DEFINE_VIRTIO_SERIAL_PROPERTIES(VirtioSerialCcw, vdev.serial),
|
||||
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
|
||||
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
@@ -1481,7 +1487,6 @@ static const TypeInfo virtio_ccw_balloon = {
|
||||
|
||||
static Property virtio_ccw_scsi_properties[] = {
|
||||
DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
|
||||
DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSICcw, vdev.parent_obj.conf),
|
||||
DEFINE_VIRTIO_SCSI_FEATURES(VirtioCcwDevice, host_features[0]),
|
||||
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
|
||||
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
|
||||
@@ -1510,7 +1515,6 @@ static const TypeInfo virtio_ccw_scsi = {
|
||||
#ifdef CONFIG_VHOST_SCSI
|
||||
static Property vhost_ccw_scsi_properties[] = {
|
||||
DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
|
||||
DEFINE_VHOST_SCSI_PROPERTIES(VirtIOSCSICcw, vdev.parent_obj.conf),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
@@ -1528,7 +1532,7 @@ static void vhost_ccw_scsi_class_init(ObjectClass *klass, void *data)
|
||||
static const TypeInfo vhost_ccw_scsi = {
|
||||
.name = TYPE_VHOST_SCSI_CCW,
|
||||
.parent = TYPE_VIRTIO_CCW_DEVICE,
|
||||
.instance_size = sizeof(VirtIOSCSICcw),
|
||||
.instance_size = sizeof(VHostSCSICcw),
|
||||
.instance_init = vhost_ccw_scsi_instance_init,
|
||||
.class_init = vhost_ccw_scsi_class_init,
|
||||
};
|
||||
@@ -1537,8 +1541,9 @@ static const TypeInfo vhost_ccw_scsi = {
|
||||
static void virtio_ccw_rng_instance_init(Object *obj)
|
||||
{
|
||||
VirtIORNGCcw *dev = VIRTIO_RNG_CCW(obj);
|
||||
object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_RNG);
|
||||
object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
|
||||
|
||||
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
|
||||
TYPE_VIRTIO_RNG);
|
||||
object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
|
||||
(Object **)&dev->vdev.conf.rng,
|
||||
qdev_prop_allow_set_link_before_realize,
|
||||
@@ -1547,7 +1552,6 @@ static void virtio_ccw_rng_instance_init(Object *obj)
|
||||
|
||||
static Property virtio_ccw_rng_properties[] = {
|
||||
DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
|
||||
DEFINE_VIRTIO_RNG_PROPERTIES(VirtIORNGCcw, vdev.conf),
|
||||
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
|
||||
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
|
||||
@@ -8,6 +8,6 @@ common-obj-$(CONFIG_ESP_PCI) += esp-pci.o
|
||||
obj-$(CONFIG_PSERIES) += spapr_vscsi.o
|
||||
|
||||
ifeq ($(CONFIG_VIRTIO),y)
|
||||
obj-y += virtio-scsi.o
|
||||
obj-y += virtio-scsi.o virtio-scsi-dataplane.o
|
||||
obj-$(CONFIG_VHOST_SCSI) += vhost-scsi.o
|
||||
endif
|
||||
|
||||
@@ -231,7 +231,8 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
|
||||
dev = qdev_create(&bus->qbus, driver);
|
||||
qdev_prop_set_uint32(dev, "scsi-id", unit);
|
||||
if (bootindex >= 0) {
|
||||
qdev_prop_set_int32(dev, "bootindex", bootindex);
|
||||
object_property_set_int(OBJECT(dev), bootindex, "bootindex",
|
||||
&error_abort);
|
||||
}
|
||||
if (object_property_find(OBJECT(dev), "removable", NULL)) {
|
||||
qdev_prop_set_bit(dev, "removable", removable);
|
||||
@@ -551,8 +552,11 @@ SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
|
||||
SCSIRequest *req;
|
||||
SCSIBus *bus = scsi_bus_from_device(d);
|
||||
BusState *qbus = BUS(bus);
|
||||
const int memset_off = offsetof(SCSIRequest, sense)
|
||||
+ sizeof(req->sense);
|
||||
|
||||
req = g_malloc0(reqops->size);
|
||||
req = g_slice_alloc(reqops->size);
|
||||
memset((uint8_t *)req + memset_off, 0, reqops->size - memset_off);
|
||||
req->refcount = 1;
|
||||
req->bus = bus;
|
||||
req->dev = d;
|
||||
@@ -560,10 +564,10 @@ SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
|
||||
req->lun = lun;
|
||||
req->hba_private = hba_private;
|
||||
req->status = -1;
|
||||
req->sense_len = 0;
|
||||
req->ops = reqops;
|
||||
object_ref(OBJECT(d));
|
||||
object_ref(OBJECT(qbus->parent));
|
||||
notifier_list_init(&req->cancel_notifiers);
|
||||
trace_scsi_req_alloc(req->dev->id, req->lun, req->tag);
|
||||
return req;
|
||||
}
|
||||
@@ -1603,7 +1607,7 @@ void scsi_req_unref(SCSIRequest *req)
|
||||
}
|
||||
object_unref(OBJECT(req->dev));
|
||||
object_unref(OBJECT(qbus->parent));
|
||||
g_free(req);
|
||||
g_slice_free1(req->ops->size, req);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1713,9 +1717,44 @@ void scsi_req_complete(SCSIRequest *req, int status)
|
||||
scsi_req_ref(req);
|
||||
scsi_req_dequeue(req);
|
||||
req->bus->info->complete(req, req->status, req->resid);
|
||||
|
||||
/* Cancelled requests might end up being completed instead of cancelled */
|
||||
notifier_list_notify(&req->cancel_notifiers, req);
|
||||
scsi_req_unref(req);
|
||||
}
|
||||
|
||||
/* Called by the devices when the request is canceled. */
|
||||
void scsi_req_cancel_complete(SCSIRequest *req)
|
||||
{
|
||||
assert(req->io_canceled);
|
||||
if (req->bus->info->cancel) {
|
||||
req->bus->info->cancel(req);
|
||||
}
|
||||
notifier_list_notify(&req->cancel_notifiers, req);
|
||||
scsi_req_unref(req);
|
||||
}
|
||||
|
||||
/* Cancel @req asynchronously. @notifier is added to @req's cancellation
|
||||
* notifier list, the bus will be notified the requests cancellation is
|
||||
* completed.
|
||||
* */
|
||||
void scsi_req_cancel_async(SCSIRequest *req, Notifier *notifier)
|
||||
{
|
||||
trace_scsi_req_cancel(req->dev->id, req->lun, req->tag);
|
||||
if (notifier) {
|
||||
notifier_list_add(&req->cancel_notifiers, notifier);
|
||||
}
|
||||
if (req->io_canceled) {
|
||||
return;
|
||||
}
|
||||
scsi_req_ref(req);
|
||||
scsi_req_dequeue(req);
|
||||
req->io_canceled = true;
|
||||
if (req->aiocb) {
|
||||
bdrv_aio_cancel_async(req->aiocb);
|
||||
}
|
||||
}
|
||||
|
||||
void scsi_req_cancel(SCSIRequest *req)
|
||||
{
|
||||
trace_scsi_req_cancel(req->dev->id, req->lun, req->tag);
|
||||
@@ -1725,28 +1764,9 @@ void scsi_req_cancel(SCSIRequest *req)
|
||||
scsi_req_ref(req);
|
||||
scsi_req_dequeue(req);
|
||||
req->io_canceled = true;
|
||||
if (req->ops->cancel_io) {
|
||||
req->ops->cancel_io(req);
|
||||
if (req->aiocb) {
|
||||
bdrv_aio_cancel(req->aiocb);
|
||||
}
|
||||
if (req->bus->info->cancel) {
|
||||
req->bus->info->cancel(req);
|
||||
}
|
||||
scsi_req_unref(req);
|
||||
}
|
||||
|
||||
void scsi_req_abort(SCSIRequest *req, int status)
|
||||
{
|
||||
if (!req->enqueued) {
|
||||
return;
|
||||
}
|
||||
scsi_req_ref(req);
|
||||
scsi_req_dequeue(req);
|
||||
req->io_canceled = true;
|
||||
if (req->ops->cancel_io) {
|
||||
req->ops->cancel_io(req);
|
||||
}
|
||||
scsi_req_complete(req, status);
|
||||
scsi_req_unref(req);
|
||||
}
|
||||
|
||||
static int scsi_ua_precedence(SCSISense sense)
|
||||
@@ -1997,6 +2017,16 @@ static void scsi_device_class_init(ObjectClass *klass, void *data)
|
||||
k->props = scsi_props;
|
||||
}
|
||||
|
||||
static void scsi_dev_instance_init(Object *obj)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
SCSIDevice *s = DO_UPCAST(SCSIDevice, qdev, dev);
|
||||
|
||||
device_add_bootindex_property(obj, &s->conf.bootindex,
|
||||
"bootindex", NULL,
|
||||
&s->qdev, NULL);
|
||||
}
|
||||
|
||||
static const TypeInfo scsi_device_type_info = {
|
||||
.name = TYPE_SCSI_DEVICE,
|
||||
.parent = TYPE_DEVICE,
|
||||
@@ -2004,6 +2034,7 @@ static const TypeInfo scsi_device_type_info = {
|
||||
.abstract = true,
|
||||
.class_size = sizeof(SCSIDeviceClass),
|
||||
.class_init = scsi_device_class_init,
|
||||
.instance_init = scsi_dev_instance_init,
|
||||
};
|
||||
|
||||
static void scsi_register_types(void)
|
||||
|
||||
@@ -105,23 +105,6 @@ static void scsi_check_condition(SCSIDiskReq *r, SCSISense sense)
|
||||
scsi_req_complete(&r->req, CHECK_CONDITION);
|
||||
}
|
||||
|
||||
/* Cancel a pending data transfer. */
|
||||
static void scsi_cancel_io(SCSIRequest *req)
|
||||
{
|
||||
SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
|
||||
|
||||
DPRINTF("Cancel tag=0x%x\n", req->tag);
|
||||
if (r->req.aiocb) {
|
||||
bdrv_aio_cancel(r->req.aiocb);
|
||||
|
||||
/* This reference was left in by scsi_*_data. We take ownership of
|
||||
* it the moment scsi_req_cancel is called, independent of whether
|
||||
* bdrv_aio_cancel completes the request or not. */
|
||||
scsi_req_unref(&r->req);
|
||||
}
|
||||
r->req.aiocb = NULL;
|
||||
}
|
||||
|
||||
static uint32_t scsi_init_iovec(SCSIDiskReq *r, size_t size)
|
||||
{
|
||||
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
|
||||
@@ -185,6 +168,7 @@ static void scsi_aio_complete(void *opaque, int ret)
|
||||
r->req.aiocb = NULL;
|
||||
block_acct_done(bdrv_get_stats(s->qdev.conf.bs), &r->acct);
|
||||
if (r->req.io_canceled) {
|
||||
scsi_req_cancel_complete(&r->req);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -197,9 +181,7 @@ static void scsi_aio_complete(void *opaque, int ret)
|
||||
scsi_req_complete(&r->req, GOOD);
|
||||
|
||||
done:
|
||||
if (!r->req.io_canceled) {
|
||||
scsi_req_unref(&r->req);
|
||||
}
|
||||
scsi_req_unref(&r->req);
|
||||
}
|
||||
|
||||
static bool scsi_is_cmd_fua(SCSICommand *cmd)
|
||||
@@ -233,6 +215,7 @@ static void scsi_write_do_fua(SCSIDiskReq *r)
|
||||
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
|
||||
|
||||
if (r->req.io_canceled) {
|
||||
scsi_req_cancel_complete(&r->req);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -246,9 +229,7 @@ static void scsi_write_do_fua(SCSIDiskReq *r)
|
||||
scsi_req_complete(&r->req, GOOD);
|
||||
|
||||
done:
|
||||
if (!r->req.io_canceled) {
|
||||
scsi_req_unref(&r->req);
|
||||
}
|
||||
scsi_req_unref(&r->req);
|
||||
}
|
||||
|
||||
static void scsi_dma_complete_noio(void *opaque, int ret)
|
||||
@@ -261,6 +242,7 @@ static void scsi_dma_complete_noio(void *opaque, int ret)
|
||||
block_acct_done(bdrv_get_stats(s->qdev.conf.bs), &r->acct);
|
||||
}
|
||||
if (r->req.io_canceled) {
|
||||
scsi_req_cancel_complete(&r->req);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -280,9 +262,7 @@ static void scsi_dma_complete_noio(void *opaque, int ret)
|
||||
}
|
||||
|
||||
done:
|
||||
if (!r->req.io_canceled) {
|
||||
scsi_req_unref(&r->req);
|
||||
}
|
||||
scsi_req_unref(&r->req);
|
||||
}
|
||||
|
||||
static void scsi_dma_complete(void *opaque, int ret)
|
||||
@@ -303,6 +283,7 @@ static void scsi_read_complete(void * opaque, int ret)
|
||||
r->req.aiocb = NULL;
|
||||
block_acct_done(bdrv_get_stats(s->qdev.conf.bs), &r->acct);
|
||||
if (r->req.io_canceled) {
|
||||
scsi_req_cancel_complete(&r->req);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -320,9 +301,7 @@ static void scsi_read_complete(void * opaque, int ret)
|
||||
scsi_req_data(&r->req, r->qiov.size);
|
||||
|
||||
done:
|
||||
if (!r->req.io_canceled) {
|
||||
scsi_req_unref(&r->req);
|
||||
}
|
||||
scsi_req_unref(&r->req);
|
||||
}
|
||||
|
||||
/* Actually issue a read to the block device. */
|
||||
@@ -337,6 +316,7 @@ static void scsi_do_read(void *opaque, int ret)
|
||||
block_acct_done(bdrv_get_stats(s->qdev.conf.bs), &r->acct);
|
||||
}
|
||||
if (r->req.io_canceled) {
|
||||
scsi_req_cancel_complete(&r->req);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -363,9 +343,7 @@ static void scsi_do_read(void *opaque, int ret)
|
||||
}
|
||||
|
||||
done:
|
||||
if (!r->req.io_canceled) {
|
||||
scsi_req_unref(&r->req);
|
||||
}
|
||||
scsi_req_unref(&r->req);
|
||||
}
|
||||
|
||||
/* Read more data from scsi device into buffer. */
|
||||
@@ -459,6 +437,7 @@ static void scsi_write_complete(void * opaque, int ret)
|
||||
block_acct_done(bdrv_get_stats(s->qdev.conf.bs), &r->acct);
|
||||
}
|
||||
if (r->req.io_canceled) {
|
||||
scsi_req_cancel_complete(&r->req);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -481,9 +460,7 @@ static void scsi_write_complete(void * opaque, int ret)
|
||||
}
|
||||
|
||||
done:
|
||||
if (!r->req.io_canceled) {
|
||||
scsi_req_unref(&r->req);
|
||||
}
|
||||
scsi_req_unref(&r->req);
|
||||
}
|
||||
|
||||
static void scsi_write_data(SCSIRequest *req)
|
||||
@@ -1553,6 +1530,7 @@ static void scsi_unmap_complete(void *opaque, int ret)
|
||||
|
||||
r->req.aiocb = NULL;
|
||||
if (r->req.io_canceled) {
|
||||
scsi_req_cancel_complete(&r->req);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -1582,9 +1560,7 @@ static void scsi_unmap_complete(void *opaque, int ret)
|
||||
scsi_req_complete(&r->req, GOOD);
|
||||
|
||||
done:
|
||||
if (!r->req.io_canceled) {
|
||||
scsi_req_unref(&r->req);
|
||||
}
|
||||
scsi_req_unref(&r->req);
|
||||
g_free(data);
|
||||
}
|
||||
|
||||
@@ -1654,6 +1630,7 @@ static void scsi_write_same_complete(void *opaque, int ret)
|
||||
r->req.aiocb = NULL;
|
||||
block_acct_done(bdrv_get_stats(s->qdev.conf.bs), &r->acct);
|
||||
if (r->req.io_canceled) {
|
||||
scsi_req_cancel_complete(&r->req);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -1678,9 +1655,7 @@ static void scsi_write_same_complete(void *opaque, int ret)
|
||||
scsi_req_complete(&r->req, GOOD);
|
||||
|
||||
done:
|
||||
if (!r->req.io_canceled) {
|
||||
scsi_req_unref(&r->req);
|
||||
}
|
||||
scsi_req_unref(&r->req);
|
||||
qemu_vfree(data->iov.iov_base);
|
||||
g_free(data);
|
||||
}
|
||||
@@ -2294,7 +2269,6 @@ static void scsi_realize(SCSIDevice *dev, Error **errp)
|
||||
bdrv_set_guest_block_size(s->qdev.conf.bs, s->qdev.blocksize);
|
||||
|
||||
bdrv_iostatus_enable(s->qdev.conf.bs);
|
||||
add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, NULL);
|
||||
}
|
||||
|
||||
static void scsi_hd_realize(SCSIDevice *dev, Error **errp)
|
||||
@@ -2346,7 +2320,6 @@ static const SCSIReqOps scsi_disk_emulate_reqops = {
|
||||
.send_command = scsi_disk_emulate_command,
|
||||
.read_data = scsi_disk_emulate_read_data,
|
||||
.write_data = scsi_disk_emulate_write_data,
|
||||
.cancel_io = scsi_cancel_io,
|
||||
.get_buf = scsi_get_buf,
|
||||
};
|
||||
|
||||
@@ -2356,7 +2329,6 @@ static const SCSIReqOps scsi_disk_dma_reqops = {
|
||||
.send_command = scsi_disk_dma_command,
|
||||
.read_data = scsi_read_data,
|
||||
.write_data = scsi_write_data,
|
||||
.cancel_io = scsi_cancel_io,
|
||||
.get_buf = scsi_get_buf,
|
||||
.load_request = scsi_disk_load_request,
|
||||
.save_request = scsi_disk_save_request,
|
||||
@@ -2689,7 +2661,6 @@ static const TypeInfo scsi_cd_info = {
|
||||
#ifdef __linux__
|
||||
static Property scsi_block_properties[] = {
|
||||
DEFINE_PROP_DRIVE("drive", SCSIDiskState, qdev.conf.bs),
|
||||
DEFINE_PROP_INT32("bootindex", SCSIDiskState, qdev.conf.bootindex, -1),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
|
||||
@@ -93,6 +93,10 @@ static void scsi_command_complete(void *opaque, int ret)
|
||||
SCSIGenericReq *r = (SCSIGenericReq *)opaque;
|
||||
|
||||
r->req.aiocb = NULL;
|
||||
if (r->req.io_canceled) {
|
||||
scsi_req_cancel_complete(&r->req);
|
||||
goto done;
|
||||
}
|
||||
if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
|
||||
r->req.sense_len = r->io_header.sb_len_wr;
|
||||
}
|
||||
@@ -133,26 +137,8 @@ static void scsi_command_complete(void *opaque, int ret)
|
||||
r, r->req.tag, status);
|
||||
|
||||
scsi_req_complete(&r->req, status);
|
||||
if (!r->req.io_canceled) {
|
||||
scsi_req_unref(&r->req);
|
||||
}
|
||||
}
|
||||
|
||||
/* Cancel a pending data transfer. */
|
||||
static void scsi_cancel_io(SCSIRequest *req)
|
||||
{
|
||||
SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
|
||||
|
||||
DPRINTF("Cancel tag=0x%x\n", req->tag);
|
||||
if (r->req.aiocb) {
|
||||
bdrv_aio_cancel(r->req.aiocb);
|
||||
|
||||
/* This reference was left in by scsi_*_data. We take ownership of
|
||||
* it independent of whether bdrv_aio_cancel completes the request
|
||||
* or not. */
|
||||
scsi_req_unref(&r->req);
|
||||
}
|
||||
r->req.aiocb = NULL;
|
||||
done:
|
||||
scsi_req_unref(&r->req);
|
||||
}
|
||||
|
||||
static int execute_command(BlockDriverState *bdrv,
|
||||
@@ -186,8 +172,7 @@ static void scsi_read_complete(void * opaque, int ret)
|
||||
int len;
|
||||
|
||||
r->req.aiocb = NULL;
|
||||
if (ret) {
|
||||
DPRINTF("IO error ret %d\n", ret);
|
||||
if (ret || r->req.io_canceled) {
|
||||
scsi_command_complete(r, ret);
|
||||
return;
|
||||
}
|
||||
@@ -211,9 +196,7 @@ static void scsi_read_complete(void * opaque, int ret)
|
||||
bdrv_set_guest_block_size(s->conf.bs, s->blocksize);
|
||||
|
||||
scsi_req_data(&r->req, len);
|
||||
if (!r->req.io_canceled) {
|
||||
scsi_req_unref(&r->req);
|
||||
}
|
||||
scsi_req_unref(&r->req);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,8 +229,7 @@ static void scsi_write_complete(void * opaque, int ret)
|
||||
|
||||
DPRINTF("scsi_write_complete() ret = %d\n", ret);
|
||||
r->req.aiocb = NULL;
|
||||
if (ret) {
|
||||
DPRINTF("IO error\n");
|
||||
if (ret || r->req.io_canceled) {
|
||||
scsi_command_complete(r, ret);
|
||||
return;
|
||||
}
|
||||
@@ -431,9 +413,6 @@ static void scsi_generic_realize(SCSIDevice *s, Error **errp)
|
||||
/* define device state */
|
||||
s->type = scsiid.scsi_type;
|
||||
DPRINTF("device type %d\n", s->type);
|
||||
if (s->type == TYPE_DISK || s->type == TYPE_ROM) {
|
||||
add_boot_device_path(s->conf.bootindex, &s->qdev, NULL);
|
||||
}
|
||||
|
||||
switch (s->type) {
|
||||
case TYPE_TAPE:
|
||||
@@ -465,7 +444,6 @@ const SCSIReqOps scsi_generic_req_ops = {
|
||||
.send_command = scsi_send_command,
|
||||
.read_data = scsi_read_data,
|
||||
.write_data = scsi_write_data,
|
||||
.cancel_io = scsi_cancel_io,
|
||||
.get_buf = scsi_get_buf,
|
||||
.load_request = scsi_generic_load_request,
|
||||
.save_request = scsi_generic_save_request,
|
||||
@@ -482,7 +460,6 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
|
||||
|
||||
static Property scsi_generic_properties[] = {
|
||||
DEFINE_PROP_DRIVE("drive", SCSIDevice, conf.bs),
|
||||
DEFINE_PROP_INT32("bootindex", SCSIDevice, conf.bootindex, -1),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
|
||||
@@ -77,8 +77,9 @@ typedef struct vscsi_req {
|
||||
SCSIRequest *sreq;
|
||||
uint32_t qtag; /* qemu tag != srp tag */
|
||||
bool active;
|
||||
uint32_t data_len;
|
||||
bool writing;
|
||||
bool dma_error;
|
||||
uint32_t data_len;
|
||||
uint32_t senselen;
|
||||
uint8_t sense[SCSI_SENSE_BUF_SIZE];
|
||||
|
||||
@@ -536,8 +537,8 @@ static void vscsi_transfer_data(SCSIRequest *sreq, uint32_t len)
|
||||
}
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "VSCSI: RDMA error rc=%d!\n", rc);
|
||||
vscsi_makeup_sense(s, req, HARDWARE_ERROR, 0, 0);
|
||||
scsi_req_abort(req->sreq, CHECK_CONDITION);
|
||||
req->dma_error = true;
|
||||
scsi_req_cancel(req->sreq);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -591,6 +592,12 @@ static void vscsi_request_cancelled(SCSIRequest *sreq)
|
||||
{
|
||||
vscsi_req *req = sreq->hba_private;
|
||||
|
||||
if (req->dma_error) {
|
||||
VSCSIState *s = VIO_SPAPR_VSCSI_DEVICE(sreq->bus->qbus.parent);
|
||||
|
||||
vscsi_makeup_sense(s, req, HARDWARE_ERROR, 0, 0);
|
||||
vscsi_send_rsp(s, req, CHECK_CONDITION, 0, 0);
|
||||
}
|
||||
vscsi_put_req(req);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "hw/virtio/vhost.h"
|
||||
#include "hw/virtio/virtio-scsi.h"
|
||||
#include "hw/virtio/virtio-bus.h"
|
||||
#include "hw/virtio/virtio-access.h"
|
||||
|
||||
/* Features supported by host kernel. */
|
||||
static const int kernel_feature_bits[] = {
|
||||
@@ -163,8 +164,8 @@ static void vhost_scsi_set_config(VirtIODevice *vdev,
|
||||
VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
|
||||
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
|
||||
|
||||
if ((uint32_t) ldl_p(&scsiconf->sense_size) != vs->sense_size ||
|
||||
(uint32_t) ldl_p(&scsiconf->cdb_size) != vs->cdb_size) {
|
||||
if ((uint32_t) virtio_ldl_p(vdev, &scsiconf->sense_size) != vs->sense_size ||
|
||||
(uint32_t) virtio_ldl_p(vdev, &scsiconf->cdb_size) != vs->cdb_size) {
|
||||
error_report("vhost-scsi does not support changing the sense data and CDB sizes");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
229
hw/scsi/virtio-scsi-dataplane.c
Normal file
229
hw/scsi/virtio-scsi-dataplane.c
Normal file
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Virtio SCSI dataplane
|
||||
*
|
||||
* Copyright Red Hat, Inc. 2014
|
||||
*
|
||||
* Authors:
|
||||
* Fam Zheng <famz@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hw/virtio/virtio-scsi.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include <hw/scsi/scsi.h>
|
||||
#include <block/scsi.h>
|
||||
#include <hw/virtio/virtio-bus.h>
|
||||
#include "hw/virtio/virtio-access.h"
|
||||
#include "stdio.h"
|
||||
|
||||
/* Context: QEMU global mutex held */
|
||||
void virtio_scsi_set_iothread(VirtIOSCSI *s, IOThread *iothread)
|
||||
{
|
||||
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s)));
|
||||
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
|
||||
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
|
||||
|
||||
assert(!s->ctx);
|
||||
s->ctx = iothread_get_aio_context(vs->conf.iothread);
|
||||
|
||||
/* Don't try if transport does not support notifiers. */
|
||||
if (!k->set_guest_notifiers || !k->set_host_notifier) {
|
||||
fprintf(stderr, "virtio-scsi: Failed to set iothread "
|
||||
"(transport does not support notifiers)");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static VirtIOSCSIVring *virtio_scsi_vring_init(VirtIOSCSI *s,
|
||||
VirtQueue *vq,
|
||||
EventNotifierHandler *handler,
|
||||
int n)
|
||||
{
|
||||
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s)));
|
||||
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
|
||||
VirtIOSCSIVring *r = g_slice_new(VirtIOSCSIVring);
|
||||
|
||||
/* Set up virtqueue notify */
|
||||
if (k->set_host_notifier(qbus->parent, n, true) != 0) {
|
||||
fprintf(stderr, "virtio-scsi: Failed to set host notifier\n");
|
||||
exit(1);
|
||||
}
|
||||
r->host_notifier = *virtio_queue_get_host_notifier(vq);
|
||||
r->guest_notifier = *virtio_queue_get_guest_notifier(vq);
|
||||
aio_set_event_notifier(s->ctx, &r->host_notifier, handler);
|
||||
|
||||
r->parent = s;
|
||||
|
||||
if (!vring_setup(&r->vring, VIRTIO_DEVICE(s), n)) {
|
||||
fprintf(stderr, "virtio-scsi: VRing setup failed\n");
|
||||
exit(1);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
VirtIOSCSIReq *virtio_scsi_pop_req_vring(VirtIOSCSI *s,
|
||||
VirtIOSCSIVring *vring)
|
||||
{
|
||||
VirtIOSCSIReq *req = virtio_scsi_init_req(s, NULL);
|
||||
int r;
|
||||
|
||||
req->vring = vring;
|
||||
r = vring_pop((VirtIODevice *)s, &vring->vring, &req->elem);
|
||||
if (r < 0) {
|
||||
virtio_scsi_free_req(req);
|
||||
req = NULL;
|
||||
}
|
||||
return req;
|
||||
}
|
||||
|
||||
void virtio_scsi_vring_push_notify(VirtIOSCSIReq *req)
|
||||
{
|
||||
vring_push(&req->vring->vring, &req->elem,
|
||||
req->qsgl.size + req->resp_iov.size);
|
||||
event_notifier_set(&req->vring->guest_notifier);
|
||||
}
|
||||
|
||||
static void virtio_scsi_iothread_handle_ctrl(EventNotifier *notifier)
|
||||
{
|
||||
VirtIOSCSIVring *vring = container_of(notifier,
|
||||
VirtIOSCSIVring, host_notifier);
|
||||
VirtIOSCSI *s = VIRTIO_SCSI(vring->parent);
|
||||
VirtIOSCSIReq *req;
|
||||
|
||||
event_notifier_test_and_clear(notifier);
|
||||
while ((req = virtio_scsi_pop_req_vring(s, vring))) {
|
||||
virtio_scsi_handle_ctrl_req(s, req);
|
||||
}
|
||||
}
|
||||
|
||||
static void virtio_scsi_iothread_handle_event(EventNotifier *notifier)
|
||||
{
|
||||
VirtIOSCSIVring *vring = container_of(notifier,
|
||||
VirtIOSCSIVring, host_notifier);
|
||||
VirtIOSCSI *s = vring->parent;
|
||||
VirtIODevice *vdev = VIRTIO_DEVICE(s);
|
||||
|
||||
event_notifier_test_and_clear(notifier);
|
||||
|
||||
if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (s->events_dropped) {
|
||||
virtio_scsi_push_event(s, NULL, VIRTIO_SCSI_T_NO_EVENT, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void virtio_scsi_iothread_handle_cmd(EventNotifier *notifier)
|
||||
{
|
||||
VirtIOSCSIVring *vring = container_of(notifier,
|
||||
VirtIOSCSIVring, host_notifier);
|
||||
VirtIOSCSI *s = (VirtIOSCSI *)vring->parent;
|
||||
VirtIOSCSIReq *req, *next;
|
||||
QTAILQ_HEAD(, VirtIOSCSIReq) reqs = QTAILQ_HEAD_INITIALIZER(reqs);
|
||||
|
||||
event_notifier_test_and_clear(notifier);
|
||||
while ((req = virtio_scsi_pop_req_vring(s, vring))) {
|
||||
if (virtio_scsi_handle_cmd_req_prepare(s, req)) {
|
||||
QTAILQ_INSERT_TAIL(&reqs, req, next);
|
||||
}
|
||||
}
|
||||
|
||||
QTAILQ_FOREACH_SAFE(req, &reqs, next, next) {
|
||||
virtio_scsi_handle_cmd_req_submit(s, req);
|
||||
}
|
||||
}
|
||||
|
||||
/* Context: QEMU global mutex held */
|
||||
void virtio_scsi_dataplane_start(VirtIOSCSI *s)
|
||||
{
|
||||
int i;
|
||||
int rc;
|
||||
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s)));
|
||||
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
|
||||
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
|
||||
|
||||
if (s->dataplane_started ||
|
||||
s->dataplane_starting ||
|
||||
s->ctx != iothread_get_aio_context(vs->conf.iothread)) {
|
||||
return;
|
||||
}
|
||||
|
||||
s->dataplane_starting = true;
|
||||
|
||||
/* Set up guest notifier (irq) */
|
||||
rc = k->set_guest_notifiers(qbus->parent, vs->conf.num_queues + 2, true);
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "virtio-scsi: Failed to set guest notifiers, "
|
||||
"ensure -enable-kvm is set\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
aio_context_acquire(s->ctx);
|
||||
s->ctrl_vring = virtio_scsi_vring_init(s, vs->ctrl_vq,
|
||||
virtio_scsi_iothread_handle_ctrl,
|
||||
0);
|
||||
s->event_vring = virtio_scsi_vring_init(s, vs->event_vq,
|
||||
virtio_scsi_iothread_handle_event,
|
||||
1);
|
||||
s->cmd_vrings = g_malloc0(sizeof(VirtIOSCSIVring) * vs->conf.num_queues);
|
||||
for (i = 0; i < vs->conf.num_queues; i++) {
|
||||
s->cmd_vrings[i] =
|
||||
virtio_scsi_vring_init(s, vs->cmd_vqs[i],
|
||||
virtio_scsi_iothread_handle_cmd,
|
||||
i + 2);
|
||||
}
|
||||
|
||||
aio_context_release(s->ctx);
|
||||
s->dataplane_starting = false;
|
||||
s->dataplane_started = true;
|
||||
}
|
||||
|
||||
/* Context: QEMU global mutex held */
|
||||
void virtio_scsi_dataplane_stop(VirtIOSCSI *s)
|
||||
{
|
||||
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s)));
|
||||
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
|
||||
VirtIODevice *vdev = VIRTIO_DEVICE(s);
|
||||
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
|
||||
int i;
|
||||
|
||||
if (!s->dataplane_started || s->dataplane_stopping) {
|
||||
return;
|
||||
}
|
||||
s->dataplane_stopping = true;
|
||||
assert(s->ctx == iothread_get_aio_context(vs->conf.iothread));
|
||||
|
||||
aio_context_acquire(s->ctx);
|
||||
|
||||
aio_set_event_notifier(s->ctx, &s->ctrl_vring->host_notifier, NULL);
|
||||
aio_set_event_notifier(s->ctx, &s->event_vring->host_notifier, NULL);
|
||||
for (i = 0; i < vs->conf.num_queues; i++) {
|
||||
aio_set_event_notifier(s->ctx, &s->cmd_vrings[i]->host_notifier, NULL);
|
||||
}
|
||||
|
||||
bdrv_drain_all(); /* ensure there are no in-flight requests */
|
||||
|
||||
aio_context_release(s->ctx);
|
||||
|
||||
/* Sync vring state back to virtqueue so that non-dataplane request
|
||||
* processing can continue when we disable the host notifier below.
|
||||
*/
|
||||
vring_teardown(&s->ctrl_vring->vring, vdev, 0);
|
||||
vring_teardown(&s->event_vring->vring, vdev, 1);
|
||||
for (i = 0; i < vs->conf.num_queues; i++) {
|
||||
vring_teardown(&s->cmd_vrings[i]->vring, vdev, 2 + i);
|
||||
}
|
||||
|
||||
for (i = 0; i < vs->conf.num_queues + 2; i++) {
|
||||
k->set_host_notifier(qbus->parent, i, false);
|
||||
}
|
||||
|
||||
/* Clean up guest notifier (irq) */
|
||||
k->set_guest_notifiers(qbus->parent, vs->conf.num_queues + 2, false);
|
||||
s->dataplane_stopping = false;
|
||||
s->dataplane_started = false;
|
||||
}
|
||||
@@ -20,34 +20,7 @@
|
||||
#include <block/scsi.h>
|
||||
#include <hw/virtio/virtio-bus.h>
|
||||
#include "hw/virtio/virtio-access.h"
|
||||
|
||||
typedef struct VirtIOSCSIReq {
|
||||
VirtIOSCSI *dev;
|
||||
VirtQueue *vq;
|
||||
VirtQueueElement elem;
|
||||
QEMUSGList qsgl;
|
||||
SCSIRequest *sreq;
|
||||
size_t resp_size;
|
||||
enum SCSIXferMode mode;
|
||||
QEMUIOVector resp_iov;
|
||||
union {
|
||||
VirtIOSCSICmdResp cmd;
|
||||
VirtIOSCSICtrlTMFResp tmf;
|
||||
VirtIOSCSICtrlANResp an;
|
||||
VirtIOSCSIEvent event;
|
||||
} resp;
|
||||
union {
|
||||
struct {
|
||||
VirtIOSCSICmdReq cmd;
|
||||
uint8_t cdb[];
|
||||
} QEMU_PACKED;
|
||||
VirtIOSCSICtrlTMFReq tmf;
|
||||
VirtIOSCSICtrlANReq an;
|
||||
} req;
|
||||
} VirtIOSCSIReq;
|
||||
|
||||
QEMU_BUILD_BUG_ON(offsetof(VirtIOSCSIReq, req.cdb) !=
|
||||
offsetof(VirtIOSCSIReq, req.cmd) + sizeof(VirtIOSCSICmdReq));
|
||||
#include "migration/migration.h"
|
||||
|
||||
static inline int virtio_scsi_get_lun(uint8_t *lun)
|
||||
{
|
||||
@@ -65,26 +38,29 @@ static inline SCSIDevice *virtio_scsi_device_find(VirtIOSCSI *s, uint8_t *lun)
|
||||
return scsi_device_find(&s->bus, 0, lun[1], virtio_scsi_get_lun(lun));
|
||||
}
|
||||
|
||||
static VirtIOSCSIReq *virtio_scsi_init_req(VirtIOSCSI *s, VirtQueue *vq)
|
||||
VirtIOSCSIReq *virtio_scsi_init_req(VirtIOSCSI *s, VirtQueue *vq)
|
||||
{
|
||||
VirtIOSCSIReq *req;
|
||||
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
|
||||
|
||||
req = g_malloc0(sizeof(*req) + vs->cdb_size);
|
||||
VirtIOSCSICommon *vs = (VirtIOSCSICommon *)s;
|
||||
const size_t zero_skip = offsetof(VirtIOSCSIReq, elem)
|
||||
+ sizeof(VirtQueueElement);
|
||||
|
||||
req = g_slice_alloc(sizeof(*req) + vs->cdb_size);
|
||||
req->vq = vq;
|
||||
req->dev = s;
|
||||
req->sreq = NULL;
|
||||
qemu_sglist_init(&req->qsgl, DEVICE(s), 8, &address_space_memory);
|
||||
qemu_iovec_init(&req->resp_iov, 1);
|
||||
memset((uint8_t *)req + zero_skip, 0, sizeof(*req) - zero_skip);
|
||||
return req;
|
||||
}
|
||||
|
||||
static void virtio_scsi_free_req(VirtIOSCSIReq *req)
|
||||
void virtio_scsi_free_req(VirtIOSCSIReq *req)
|
||||
{
|
||||
VirtIOSCSICommon *vs = (VirtIOSCSICommon *)req->dev;
|
||||
|
||||
qemu_iovec_destroy(&req->resp_iov);
|
||||
qemu_sglist_destroy(&req->qsgl);
|
||||
g_free(req);
|
||||
g_slice_free1(sizeof(*req) + vs->cdb_size, req);
|
||||
}
|
||||
|
||||
static void virtio_scsi_complete_req(VirtIOSCSIReq *req)
|
||||
@@ -94,13 +70,19 @@ static void virtio_scsi_complete_req(VirtIOSCSIReq *req)
|
||||
VirtIODevice *vdev = VIRTIO_DEVICE(s);
|
||||
|
||||
qemu_iovec_from_buf(&req->resp_iov, 0, &req->resp, req->resp_size);
|
||||
virtqueue_push(vq, &req->elem, req->qsgl.size + req->resp_iov.size);
|
||||
if (req->vring) {
|
||||
assert(req->vq == NULL);
|
||||
virtio_scsi_vring_push_notify(req);
|
||||
} else {
|
||||
virtqueue_push(vq, &req->elem, req->qsgl.size + req->resp_iov.size);
|
||||
virtio_notify(vdev, vq);
|
||||
}
|
||||
|
||||
if (req->sreq) {
|
||||
req->sreq->hba_private = NULL;
|
||||
scsi_req_unref(req->sreq);
|
||||
}
|
||||
virtio_scsi_free_req(req);
|
||||
virtio_notify(vdev, vq);
|
||||
}
|
||||
|
||||
static void virtio_scsi_bad_req(void)
|
||||
@@ -226,13 +208,39 @@ static void *virtio_scsi_load_request(QEMUFile *f, SCSIRequest *sreq)
|
||||
return req;
|
||||
}
|
||||
|
||||
static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
|
||||
typedef struct {
|
||||
Notifier notifier;
|
||||
VirtIOSCSIReq *tmf_req;
|
||||
} VirtIOSCSICancelNotifier;
|
||||
|
||||
static void virtio_scsi_cancel_notify(Notifier *notifier, void *data)
|
||||
{
|
||||
VirtIOSCSICancelNotifier *n = container_of(notifier,
|
||||
VirtIOSCSICancelNotifier,
|
||||
notifier);
|
||||
|
||||
if (--n->tmf_req->remaining == 0) {
|
||||
virtio_scsi_complete_req(n->tmf_req);
|
||||
}
|
||||
g_slice_free(VirtIOSCSICancelNotifier, n);
|
||||
}
|
||||
|
||||
/* Return 0 if the request is ready to be completed and return to guest;
|
||||
* -EINPROGRESS if the request is submitted and will be completed later, in the
|
||||
* case of async cancellation. */
|
||||
static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
|
||||
{
|
||||
SCSIDevice *d = virtio_scsi_device_find(s, req->req.tmf.lun);
|
||||
SCSIRequest *r, *next;
|
||||
BusChild *kid;
|
||||
int target;
|
||||
int ret = 0;
|
||||
|
||||
if (s->dataplane_started && bdrv_get_aio_context(d->conf.bs) != s->ctx) {
|
||||
aio_context_acquire(s->ctx);
|
||||
bdrv_set_aio_context(d->conf.bs, s->ctx);
|
||||
aio_context_release(s->ctx);
|
||||
}
|
||||
/* Here VIRTIO_SCSI_S_OK means "FUNCTION COMPLETE". */
|
||||
req->resp.tmf.response = VIRTIO_SCSI_S_OK;
|
||||
|
||||
@@ -264,7 +272,14 @@ static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
|
||||
*/
|
||||
req->resp.tmf.response = VIRTIO_SCSI_S_FUNCTION_SUCCEEDED;
|
||||
} else {
|
||||
scsi_req_cancel(r);
|
||||
VirtIOSCSICancelNotifier *notifier;
|
||||
|
||||
req->remaining = 1;
|
||||
notifier = g_slice_new(VirtIOSCSICancelNotifier);
|
||||
notifier->tmf_req = req;
|
||||
notifier->notifier.notify = virtio_scsi_cancel_notify;
|
||||
scsi_req_cancel_async(r, ¬ifier->notifier);
|
||||
ret = -EINPROGRESS;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -290,6 +305,13 @@ static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
|
||||
if (d->lun != virtio_scsi_get_lun(req->req.tmf.lun)) {
|
||||
goto incorrect_lun;
|
||||
}
|
||||
|
||||
/* Add 1 to "remaining" until virtio_scsi_do_tmf returns.
|
||||
* This way, if the bus starts calling back to the notifiers
|
||||
* even before we finish the loop, virtio_scsi_cancel_notify
|
||||
* will not complete the TMF too early.
|
||||
*/
|
||||
req->remaining = 1;
|
||||
QTAILQ_FOREACH_SAFE(r, &d->requests, next, next) {
|
||||
if (r->hba_private) {
|
||||
if (req->req.tmf.subtype == VIRTIO_SCSI_T_TMF_QUERY_TASK_SET) {
|
||||
@@ -299,10 +321,19 @@ static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
|
||||
req->resp.tmf.response = VIRTIO_SCSI_S_FUNCTION_SUCCEEDED;
|
||||
break;
|
||||
} else {
|
||||
scsi_req_cancel(r);
|
||||
VirtIOSCSICancelNotifier *notifier;
|
||||
|
||||
req->remaining++;
|
||||
notifier = g_slice_new(VirtIOSCSICancelNotifier);
|
||||
notifier->notifier.notify = virtio_scsi_cancel_notify;
|
||||
notifier->tmf_req = req;
|
||||
scsi_req_cancel_async(r, ¬ifier->notifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (--req->remaining > 0) {
|
||||
ret = -EINPROGRESS;
|
||||
}
|
||||
break;
|
||||
|
||||
case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET:
|
||||
@@ -323,14 +354,53 @@ static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
return ret;
|
||||
|
||||
incorrect_lun:
|
||||
req->resp.tmf.response = VIRTIO_SCSI_S_INCORRECT_LUN;
|
||||
return;
|
||||
return ret;
|
||||
|
||||
fail:
|
||||
req->resp.tmf.response = VIRTIO_SCSI_S_BAD_TARGET;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void virtio_scsi_handle_ctrl_req(VirtIOSCSI *s, VirtIOSCSIReq *req)
|
||||
{
|
||||
VirtIODevice *vdev = (VirtIODevice *)s;
|
||||
int type;
|
||||
int r = 0;
|
||||
|
||||
if (iov_to_buf(req->elem.out_sg, req->elem.out_num, 0,
|
||||
&type, sizeof(type)) < sizeof(type)) {
|
||||
virtio_scsi_bad_req();
|
||||
return;
|
||||
}
|
||||
|
||||
virtio_tswap32s(vdev, &req->req.tmf.type);
|
||||
if (req->req.tmf.type == VIRTIO_SCSI_T_TMF) {
|
||||
if (virtio_scsi_parse_req(req, sizeof(VirtIOSCSICtrlTMFReq),
|
||||
sizeof(VirtIOSCSICtrlTMFResp)) < 0) {
|
||||
virtio_scsi_bad_req();
|
||||
} else {
|
||||
r = virtio_scsi_do_tmf(s, req);
|
||||
}
|
||||
|
||||
} else if (req->req.tmf.type == VIRTIO_SCSI_T_AN_QUERY ||
|
||||
req->req.tmf.type == VIRTIO_SCSI_T_AN_SUBSCRIBE) {
|
||||
if (virtio_scsi_parse_req(req, sizeof(VirtIOSCSICtrlANReq),
|
||||
sizeof(VirtIOSCSICtrlANResp)) < 0) {
|
||||
virtio_scsi_bad_req();
|
||||
} else {
|
||||
req->resp.an.event_actual = 0;
|
||||
req->resp.an.response = VIRTIO_SCSI_S_OK;
|
||||
}
|
||||
}
|
||||
if (r == 0) {
|
||||
virtio_scsi_complete_req(req);
|
||||
} else {
|
||||
assert(r == -EINPROGRESS);
|
||||
}
|
||||
}
|
||||
|
||||
static void virtio_scsi_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
|
||||
@@ -338,35 +408,12 @@ static void virtio_scsi_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
|
||||
VirtIOSCSI *s = (VirtIOSCSI *)vdev;
|
||||
VirtIOSCSIReq *req;
|
||||
|
||||
if (s->ctx && !s->dataplane_disabled) {
|
||||
virtio_scsi_dataplane_start(s);
|
||||
return;
|
||||
}
|
||||
while ((req = virtio_scsi_pop_req(s, vq))) {
|
||||
int type;
|
||||
|
||||
if (iov_to_buf(req->elem.out_sg, req->elem.out_num, 0,
|
||||
&type, sizeof(type)) < sizeof(type)) {
|
||||
virtio_scsi_bad_req();
|
||||
continue;
|
||||
}
|
||||
|
||||
virtio_tswap32s(vdev, &req->req.tmf.type);
|
||||
if (req->req.tmf.type == VIRTIO_SCSI_T_TMF) {
|
||||
if (virtio_scsi_parse_req(req, sizeof(VirtIOSCSICtrlTMFReq),
|
||||
sizeof(VirtIOSCSICtrlTMFResp)) < 0) {
|
||||
virtio_scsi_bad_req();
|
||||
} else {
|
||||
virtio_scsi_do_tmf(s, req);
|
||||
}
|
||||
|
||||
} else if (req->req.tmf.type == VIRTIO_SCSI_T_AN_QUERY ||
|
||||
req->req.tmf.type == VIRTIO_SCSI_T_AN_SUBSCRIBE) {
|
||||
if (virtio_scsi_parse_req(req, sizeof(VirtIOSCSICtrlANReq),
|
||||
sizeof(VirtIOSCSICtrlANResp)) < 0) {
|
||||
virtio_scsi_bad_req();
|
||||
} else {
|
||||
req->resp.an.event_actual = 0;
|
||||
req->resp.an.response = VIRTIO_SCSI_S_OK;
|
||||
}
|
||||
}
|
||||
virtio_scsi_complete_req(req);
|
||||
virtio_scsi_handle_ctrl_req(s, req);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -420,13 +467,7 @@ static int virtio_scsi_parse_cdb(SCSIDevice *dev, SCSICommand *cmd,
|
||||
* host device passthrough.
|
||||
*/
|
||||
cmd->xfer = req->qsgl.size;
|
||||
if (cmd->xfer == 0) {
|
||||
cmd->mode = SCSI_XFER_NONE;
|
||||
} else if (iov_size(req->elem.in_sg, req->elem.in_num) > req->resp_size) {
|
||||
cmd->mode = SCSI_XFER_FROM_DEV;
|
||||
} else {
|
||||
cmd->mode = SCSI_XFER_TO_DEV;
|
||||
}
|
||||
cmd->mode = req->mode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -458,52 +499,79 @@ static void virtio_scsi_fail_cmd_req(VirtIOSCSIReq *req)
|
||||
virtio_scsi_complete_cmd_req(req);
|
||||
}
|
||||
|
||||
bool virtio_scsi_handle_cmd_req_prepare(VirtIOSCSI *s, VirtIOSCSIReq *req)
|
||||
{
|
||||
VirtIOSCSICommon *vs = &s->parent_obj;
|
||||
SCSIDevice *d;
|
||||
int rc;
|
||||
|
||||
rc = virtio_scsi_parse_req(req, sizeof(VirtIOSCSICmdReq) + vs->cdb_size,
|
||||
sizeof(VirtIOSCSICmdResp) + vs->sense_size);
|
||||
if (rc < 0) {
|
||||
if (rc == -ENOTSUP) {
|
||||
virtio_scsi_fail_cmd_req(req);
|
||||
} else {
|
||||
virtio_scsi_bad_req();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
d = virtio_scsi_device_find(s, req->req.cmd.lun);
|
||||
if (!d) {
|
||||
req->resp.cmd.response = VIRTIO_SCSI_S_BAD_TARGET;
|
||||
virtio_scsi_complete_cmd_req(req);
|
||||
return false;
|
||||
}
|
||||
if (s->dataplane_started && bdrv_get_aio_context(d->conf.bs) != s->ctx) {
|
||||
aio_context_acquire(s->ctx);
|
||||
bdrv_set_aio_context(d->conf.bs, s->ctx);
|
||||
aio_context_release(s->ctx);
|
||||
}
|
||||
req->sreq = scsi_req_new(d, req->req.cmd.tag,
|
||||
virtio_scsi_get_lun(req->req.cmd.lun),
|
||||
req->req.cdb, req);
|
||||
|
||||
if (req->sreq->cmd.mode != SCSI_XFER_NONE
|
||||
&& (req->sreq->cmd.mode != req->mode ||
|
||||
req->sreq->cmd.xfer > req->qsgl.size)) {
|
||||
req->resp.cmd.response = VIRTIO_SCSI_S_OVERRUN;
|
||||
virtio_scsi_complete_cmd_req(req);
|
||||
return false;
|
||||
}
|
||||
scsi_req_ref(req->sreq);
|
||||
bdrv_io_plug(d->conf.bs);
|
||||
return true;
|
||||
}
|
||||
|
||||
void virtio_scsi_handle_cmd_req_submit(VirtIOSCSI *s, VirtIOSCSIReq *req)
|
||||
{
|
||||
SCSIRequest *sreq = req->sreq;
|
||||
if (scsi_req_enqueue(sreq)) {
|
||||
scsi_req_continue(sreq);
|
||||
}
|
||||
bdrv_io_unplug(sreq->dev->conf.bs);
|
||||
scsi_req_unref(sreq);
|
||||
}
|
||||
|
||||
static void virtio_scsi_handle_cmd(VirtIODevice *vdev, VirtQueue *vq)
|
||||
{
|
||||
/* use non-QOM casts in the data path */
|
||||
VirtIOSCSI *s = (VirtIOSCSI *)vdev;
|
||||
VirtIOSCSICommon *vs = &s->parent_obj;
|
||||
|
||||
VirtIOSCSIReq *req;
|
||||
int n;
|
||||
VirtIOSCSIReq *req, *next;
|
||||
QTAILQ_HEAD(, VirtIOSCSIReq) reqs = QTAILQ_HEAD_INITIALIZER(reqs);
|
||||
|
||||
if (s->ctx && !s->dataplane_disabled) {
|
||||
virtio_scsi_dataplane_start(s);
|
||||
return;
|
||||
}
|
||||
while ((req = virtio_scsi_pop_req(s, vq))) {
|
||||
SCSIDevice *d;
|
||||
int rc;
|
||||
|
||||
rc = virtio_scsi_parse_req(req, sizeof(VirtIOSCSICmdReq) + vs->cdb_size,
|
||||
sizeof(VirtIOSCSICmdResp) + vs->sense_size);
|
||||
if (rc < 0) {
|
||||
if (rc == -ENOTSUP) {
|
||||
virtio_scsi_fail_cmd_req(req);
|
||||
} else {
|
||||
virtio_scsi_bad_req();
|
||||
}
|
||||
continue;
|
||||
if (virtio_scsi_handle_cmd_req_prepare(s, req)) {
|
||||
QTAILQ_INSERT_TAIL(&reqs, req, next);
|
||||
}
|
||||
}
|
||||
|
||||
d = virtio_scsi_device_find(s, req->req.cmd.lun);
|
||||
if (!d) {
|
||||
req->resp.cmd.response = VIRTIO_SCSI_S_BAD_TARGET;
|
||||
virtio_scsi_complete_cmd_req(req);
|
||||
continue;
|
||||
}
|
||||
req->sreq = scsi_req_new(d, req->req.cmd.tag,
|
||||
virtio_scsi_get_lun(req->req.cmd.lun),
|
||||
req->req.cdb, req);
|
||||
|
||||
if (req->sreq->cmd.mode != SCSI_XFER_NONE
|
||||
&& (req->sreq->cmd.mode != req->mode ||
|
||||
req->sreq->cmd.xfer > req->qsgl.size)) {
|
||||
req->resp.cmd.response = VIRTIO_SCSI_S_OVERRUN;
|
||||
virtio_scsi_complete_cmd_req(req);
|
||||
continue;
|
||||
}
|
||||
|
||||
n = scsi_req_enqueue(req->sreq);
|
||||
if (n) {
|
||||
scsi_req_continue(req->sreq);
|
||||
}
|
||||
QTAILQ_FOREACH_SAFE(req, &reqs, next, next) {
|
||||
virtio_scsi_handle_cmd_req_submit(s, req);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -552,6 +620,9 @@ static void virtio_scsi_reset(VirtIODevice *vdev)
|
||||
VirtIOSCSI *s = VIRTIO_SCSI(vdev);
|
||||
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
|
||||
|
||||
if (s->ctx) {
|
||||
virtio_scsi_dataplane_stop(s);
|
||||
}
|
||||
s->resetting++;
|
||||
qbus_reset_all(&s->bus.qbus);
|
||||
s->resetting--;
|
||||
@@ -582,8 +653,8 @@ static int virtio_scsi_load(QEMUFile *f, void *opaque, int version_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev,
|
||||
uint32_t event, uint32_t reason)
|
||||
void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev,
|
||||
uint32_t event, uint32_t reason)
|
||||
{
|
||||
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
|
||||
VirtIOSCSIReq *req;
|
||||
@@ -594,10 +665,19 @@ static void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev,
|
||||
return;
|
||||
}
|
||||
|
||||
req = virtio_scsi_pop_req(s, vs->event_vq);
|
||||
if (s->dataplane_started) {
|
||||
assert(s->ctx);
|
||||
aio_context_acquire(s->ctx);
|
||||
}
|
||||
|
||||
if (s->dataplane_started) {
|
||||
req = virtio_scsi_pop_req_vring(s, s->event_vring);
|
||||
} else {
|
||||
req = virtio_scsi_pop_req(s, vs->event_vq);
|
||||
}
|
||||
if (!req) {
|
||||
s->events_dropped = true;
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (s->events_dropped) {
|
||||
@@ -626,12 +706,20 @@ static void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev,
|
||||
evt->lun[3] = dev->lun & 0xFF;
|
||||
}
|
||||
virtio_scsi_complete_req(req);
|
||||
out:
|
||||
if (s->dataplane_started) {
|
||||
aio_context_release(s->ctx);
|
||||
}
|
||||
}
|
||||
|
||||
static void virtio_scsi_handle_event(VirtIODevice *vdev, VirtQueue *vq)
|
||||
{
|
||||
VirtIOSCSI *s = VIRTIO_SCSI(vdev);
|
||||
|
||||
if (s->ctx && !s->dataplane_disabled) {
|
||||
virtio_scsi_dataplane_start(s);
|
||||
return;
|
||||
}
|
||||
if (s->events_dropped) {
|
||||
virtio_scsi_push_event(s, NULL, VIRTIO_SCSI_T_NO_EVENT, 0);
|
||||
}
|
||||
@@ -717,6 +805,35 @@ void virtio_scsi_common_realize(DeviceState *dev, Error **errp,
|
||||
s->cmd_vqs[i] = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE,
|
||||
cmd);
|
||||
}
|
||||
|
||||
if (s->conf.iothread) {
|
||||
virtio_scsi_set_iothread(VIRTIO_SCSI(s), s->conf.iothread);
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable dataplane thread during live migration since it does not
|
||||
* update the dirty memory bitmap yet.
|
||||
*/
|
||||
static void virtio_scsi_migration_state_changed(Notifier *notifier, void *data)
|
||||
{
|
||||
VirtIOSCSI *s = container_of(notifier, VirtIOSCSI,
|
||||
migration_state_notifier);
|
||||
MigrationState *mig = data;
|
||||
|
||||
if (migration_in_setup(mig)) {
|
||||
if (!s->dataplane_started) {
|
||||
return;
|
||||
}
|
||||
virtio_scsi_dataplane_stop(s);
|
||||
s->dataplane_disabled = true;
|
||||
} else if (migration_has_finished(mig) ||
|
||||
migration_has_failed(mig)) {
|
||||
if (s->dataplane_started) {
|
||||
return;
|
||||
}
|
||||
bdrv_drain_all(); /* complete in-flight non-dataplane requests */
|
||||
s->dataplane_disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void virtio_scsi_device_realize(DeviceState *dev, Error **errp)
|
||||
@@ -747,6 +864,18 @@ static void virtio_scsi_device_realize(DeviceState *dev, Error **errp)
|
||||
|
||||
register_savevm(dev, "virtio-scsi", virtio_scsi_id++, 1,
|
||||
virtio_scsi_save, virtio_scsi_load, s);
|
||||
s->migration_state_notifier.notify = virtio_scsi_migration_state_changed;
|
||||
add_migration_state_change_notifier(&s->migration_state_notifier);
|
||||
}
|
||||
|
||||
static void virtio_scsi_instance_init(Object *obj)
|
||||
{
|
||||
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(obj);
|
||||
|
||||
object_property_add_link(obj, "iothread", TYPE_IOTHREAD,
|
||||
(Object **)&vs->conf.iothread,
|
||||
qdev_prop_allow_set_link_before_realize,
|
||||
OBJ_PROP_LINK_UNREF_ON_RELEASE, &error_abort);
|
||||
}
|
||||
|
||||
void virtio_scsi_common_unrealize(DeviceState *dev, Error **errp)
|
||||
@@ -763,6 +892,7 @@ static void virtio_scsi_device_unrealize(DeviceState *dev, Error **errp)
|
||||
VirtIOSCSI *s = VIRTIO_SCSI(dev);
|
||||
|
||||
unregister_savevm(dev, "virtio-scsi", s);
|
||||
remove_migration_state_change_notifier(&s->migration_state_notifier);
|
||||
|
||||
virtio_scsi_common_unrealize(dev, errp);
|
||||
}
|
||||
@@ -807,6 +937,7 @@ static const TypeInfo virtio_scsi_info = {
|
||||
.name = TYPE_VIRTIO_SCSI,
|
||||
.parent = TYPE_VIRTIO_SCSI_COMMON,
|
||||
.instance_size = sizeof(VirtIOSCSI),
|
||||
.instance_init = virtio_scsi_instance_init,
|
||||
.class_init = virtio_scsi_class_init,
|
||||
};
|
||||
|
||||
|
||||
@@ -864,7 +864,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
|
||||
for(i = 0; i < nb_nics; i++)
|
||||
pci_nic_init_nofail(&nd_table[i], pci_bus, "ne2k_pci", NULL);
|
||||
|
||||
ide_drive_get(hd, MAX_IDE_BUS);
|
||||
ide_drive_get(hd, ARRAY_SIZE(hd));
|
||||
|
||||
pci_cmd646_ide_init(pci_bus, hd, 1);
|
||||
|
||||
|
||||
@@ -1371,8 +1371,16 @@ static void usb_net_realize(USBDevice *dev, Error **errrp)
|
||||
s->conf.macaddr.a[4],
|
||||
s->conf.macaddr.a[5]);
|
||||
usb_desc_set_string(dev, STRING_ETHADDR, s->usbstring_mac);
|
||||
}
|
||||
|
||||
add_boot_device_path(s->conf.bootindex, &dev->qdev, "/ethernet@0");
|
||||
static void usb_net_instance_init(Object *obj)
|
||||
{
|
||||
USBDevice *dev = USB_DEVICE(obj);
|
||||
USBNetState *s = DO_UPCAST(USBNetState, dev, dev);
|
||||
|
||||
device_add_bootindex_property(obj, &s->conf.bootindex,
|
||||
"bootindex", "/ethernet-phy@0",
|
||||
&dev->qdev, NULL);
|
||||
}
|
||||
|
||||
static USBDevice *usb_net_init(USBBus *bus, const char *cmdline)
|
||||
@@ -1438,6 +1446,7 @@ static const TypeInfo net_info = {
|
||||
.parent = TYPE_USB_DEVICE,
|
||||
.instance_size = sizeof(USBNetState),
|
||||
.class_init = usb_net_class_initfn,
|
||||
.instance_init = usb_net_instance_init,
|
||||
};
|
||||
|
||||
static void usb_net_register_types(void)
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "monitor/monitor.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/blockdev.h"
|
||||
#include "qapi/visitor.h"
|
||||
|
||||
//#define DEBUG_MSD
|
||||
|
||||
@@ -59,6 +60,7 @@ typedef struct {
|
||||
/* usb-storage only */
|
||||
BlockConf conf;
|
||||
uint32_t removable;
|
||||
SCSIDevice *scsi_dev;
|
||||
} MSDState;
|
||||
|
||||
struct usb_msd_cbw {
|
||||
@@ -634,6 +636,7 @@ static void usb_msd_realize_storage(USBDevice *dev, Error **errp)
|
||||
}
|
||||
s->bus.qbus.allow_hotplug = 0;
|
||||
usb_msd_handle_reset(dev);
|
||||
s->scsi_dev = scsi_dev;
|
||||
|
||||
if (bdrv_key_required(bs)) {
|
||||
if (cur_mon) {
|
||||
@@ -767,6 +770,54 @@ static void usb_msd_class_initfn_storage(ObjectClass *klass, void *data)
|
||||
usb_msd_class_initfn_common(klass);
|
||||
}
|
||||
|
||||
static void usb_msd_get_bootindex(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
USBDevice *dev = USB_DEVICE(obj);
|
||||
MSDState *s = DO_UPCAST(MSDState, dev, dev);
|
||||
|
||||
visit_type_int32(v, &s->conf.bootindex, name, errp);
|
||||
}
|
||||
|
||||
static void usb_msd_set_bootindex(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
USBDevice *dev = USB_DEVICE(obj);
|
||||
MSDState *s = DO_UPCAST(MSDState, dev, dev);
|
||||
int32_t boot_index;
|
||||
Error *local_err = NULL;
|
||||
|
||||
visit_type_int32(v, &boot_index, name, &local_err);
|
||||
if (local_err) {
|
||||
goto out;
|
||||
}
|
||||
/* check whether bootindex is present in fw_boot_order list */
|
||||
check_boot_index(boot_index, &local_err);
|
||||
if (local_err) {
|
||||
goto out;
|
||||
}
|
||||
/* change bootindex to a new one */
|
||||
s->conf.bootindex = boot_index;
|
||||
|
||||
if (s->scsi_dev) {
|
||||
object_property_set_int(OBJECT(s->scsi_dev), boot_index, "bootindex",
|
||||
&error_abort);
|
||||
}
|
||||
|
||||
out:
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_msd_instance_init(Object *obj)
|
||||
{
|
||||
object_property_add(obj, "bootindex", "int32",
|
||||
usb_msd_get_bootindex,
|
||||
usb_msd_set_bootindex, NULL, NULL, NULL);
|
||||
object_property_set_int(obj, -1, "bootindex", NULL);
|
||||
}
|
||||
|
||||
static void usb_msd_class_initfn_bot(ObjectClass *klass, void *data)
|
||||
{
|
||||
USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
|
||||
@@ -780,6 +831,7 @@ static const TypeInfo msd_info = {
|
||||
.parent = TYPE_USB_DEVICE,
|
||||
.instance_size = sizeof(MSDState),
|
||||
.class_init = usb_msd_class_initfn_storage,
|
||||
.instance_init = usb_msd_instance_init,
|
||||
};
|
||||
|
||||
static const TypeInfo bot_info = {
|
||||
|
||||
@@ -978,10 +978,19 @@ static void usb_host_realize(USBDevice *udev, Error **errp)
|
||||
qemu_add_exit_notifier(&s->exit);
|
||||
|
||||
QTAILQ_INSERT_TAIL(&hostdevs, s, next);
|
||||
add_boot_device_path(s->bootindex, &udev->qdev, NULL);
|
||||
usb_host_auto_check(NULL);
|
||||
}
|
||||
|
||||
static void usb_host_instance_init(Object *obj)
|
||||
{
|
||||
USBDevice *udev = USB_DEVICE(obj);
|
||||
USBHostDevice *s = USB_HOST_DEVICE(udev);
|
||||
|
||||
device_add_bootindex_property(obj, &s->bootindex,
|
||||
"bootindex", NULL,
|
||||
&udev->qdev, NULL);
|
||||
}
|
||||
|
||||
static void usb_host_handle_destroy(USBDevice *udev)
|
||||
{
|
||||
USBHostDevice *s = USB_HOST_DEVICE(udev);
|
||||
@@ -1465,7 +1474,6 @@ static Property usb_host_dev_properties[] = {
|
||||
DEFINE_PROP_UINT32("productid", USBHostDevice, match.product_id, 0),
|
||||
DEFINE_PROP_UINT32("isobufs", USBHostDevice, iso_urb_count, 4),
|
||||
DEFINE_PROP_UINT32("isobsize", USBHostDevice, iso_urb_frames, 32),
|
||||
DEFINE_PROP_INT32("bootindex", USBHostDevice, bootindex, -1),
|
||||
DEFINE_PROP_UINT32("loglevel", USBHostDevice, loglevel,
|
||||
LIBUSB_LOG_LEVEL_WARNING),
|
||||
DEFINE_PROP_BIT("pipeline", USBHostDevice, options,
|
||||
@@ -1498,6 +1506,7 @@ static TypeInfo usb_host_dev_info = {
|
||||
.parent = TYPE_USB_DEVICE,
|
||||
.instance_size = sizeof(USBHostDevice),
|
||||
.class_init = usb_host_class_initfn,
|
||||
.instance_init = usb_host_instance_init,
|
||||
};
|
||||
|
||||
static void usb_host_register_types(void)
|
||||
|
||||
@@ -1401,7 +1401,6 @@ static void usbredir_realize(USBDevice *udev, Error **errp)
|
||||
usbredir_chardev_read, usbredir_chardev_event, dev);
|
||||
|
||||
qemu_add_vm_change_state_handler(usbredir_vm_state_change, dev);
|
||||
add_boot_device_path(dev->bootindex, &udev->qdev, NULL);
|
||||
}
|
||||
|
||||
static void usbredir_cleanup_device_queues(USBRedirDevice *dev)
|
||||
@@ -2471,7 +2470,6 @@ static Property usbredir_properties[] = {
|
||||
DEFINE_PROP_CHR("chardev", USBRedirDevice, cs),
|
||||
DEFINE_PROP_UINT8("debug", USBRedirDevice, debug, usbredirparser_warning),
|
||||
DEFINE_PROP_STRING("filter", USBRedirDevice, filter_str),
|
||||
DEFINE_PROP_INT32("bootindex", USBRedirDevice, bootindex, -1),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
@@ -2496,11 +2494,22 @@ static void usbredir_class_initfn(ObjectClass *klass, void *data)
|
||||
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
||||
}
|
||||
|
||||
static void usbredir_instance_init(Object *obj)
|
||||
{
|
||||
USBDevice *udev = USB_DEVICE(obj);
|
||||
USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
|
||||
|
||||
device_add_bootindex_property(obj, &dev->bootindex,
|
||||
"bootindex", NULL,
|
||||
&udev->qdev, NULL);
|
||||
}
|
||||
|
||||
static const TypeInfo usbredir_dev_info = {
|
||||
.name = "usb-redir",
|
||||
.parent = TYPE_USB_DEVICE,
|
||||
.instance_size = sizeof(USBRedirDevice),
|
||||
.class_init = usbredir_class_initfn,
|
||||
.instance_init = usbredir_instance_init,
|
||||
};
|
||||
|
||||
static void usbredir_register_types(void)
|
||||
|
||||
@@ -86,6 +86,9 @@
|
||||
* 12 is historical, and due to x86 page size. */
|
||||
#define VIRTIO_PCI_QUEUE_ADDR_SHIFT 12
|
||||
|
||||
/* Flags track per-device state like workarounds for quirks in older guests. */
|
||||
#define VIRTIO_PCI_FLAG_BUS_MASTER_BUG (1 << 0)
|
||||
|
||||
static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size,
|
||||
VirtIOPCIProxy *dev);
|
||||
|
||||
@@ -320,6 +323,14 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
|
||||
proxy->pci_dev.config[PCI_COMMAND] |
|
||||
PCI_COMMAND_MASTER, 1);
|
||||
}
|
||||
|
||||
/* Linux before 2.6.34 sets the device as OK without enabling
|
||||
the PCI device bus master bit. In this case we need to disable
|
||||
some safety checks. */
|
||||
if ((val & VIRTIO_CONFIG_S_DRIVER_OK) &&
|
||||
!(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
|
||||
proxy->flags |= VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
|
||||
}
|
||||
break;
|
||||
case VIRTIO_MSI_CONFIG_VECTOR:
|
||||
msix_vector_unuse(&proxy->pci_dev, vdev->config_vector);
|
||||
@@ -469,18 +480,13 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
|
||||
VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
|
||||
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
|
||||
|
||||
uint8_t cmd = proxy->pci_dev.config[PCI_COMMAND];
|
||||
|
||||
pci_default_write_config(pci_dev, address, val, len);
|
||||
|
||||
if (range_covers_byte(address, len, PCI_COMMAND) &&
|
||||
!(pci_dev->config[PCI_COMMAND] & PCI_COMMAND_MASTER) &&
|
||||
(cmd & PCI_COMMAND_MASTER)) {
|
||||
/* Bus driver disables bus mastering - make it act
|
||||
* as a kind of reset to render the device quiescent. */
|
||||
!(proxy->flags & VIRTIO_PCI_FLAG_BUS_MASTER_BUG)) {
|
||||
virtio_pci_stop_ioeventfd(proxy);
|
||||
virtio_reset(vdev);
|
||||
msix_unuse_all_vectors(&proxy->pci_dev);
|
||||
virtio_set_status(vdev, vdev->status & ~VIRTIO_CONFIG_S_DRIVER_OK);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -889,19 +895,11 @@ static void virtio_pci_vmstate_change(DeviceState *d, bool running)
|
||||
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
|
||||
|
||||
if (running) {
|
||||
/* Linux before 2.6.34 drives the device without enabling
|
||||
the PCI device bus master bit. Enable it automatically
|
||||
for the guest. This is a PCI spec violation but so is
|
||||
initiating DMA with bus master bit clear.
|
||||
Note: this only makes a difference when migrating
|
||||
across QEMU versions from an old QEMU, as for new QEMU
|
||||
bus master and driver bits are always in sync.
|
||||
TODO: consider enabling conditionally for compat machine types. */
|
||||
if (vdev->status & (VIRTIO_CONFIG_S_ACKNOWLEDGE |
|
||||
VIRTIO_CONFIG_S_DRIVER)) {
|
||||
pci_default_write_config(&proxy->pci_dev, PCI_COMMAND,
|
||||
proxy->pci_dev.config[PCI_COMMAND] |
|
||||
PCI_COMMAND_MASTER, 1);
|
||||
/* Try to find out if the guest has bus master disabled, but is
|
||||
in ready state. Then we have a buggy guest OS. */
|
||||
if ((vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) &&
|
||||
!(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
|
||||
proxy->flags |= VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
|
||||
}
|
||||
virtio_pci_start_ioeventfd(proxy);
|
||||
} else {
|
||||
@@ -926,7 +924,6 @@ static Property virtio_9p_pci_properties[] = {
|
||||
DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
|
||||
VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
|
||||
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
|
||||
DEFINE_VIRTIO_9P_PROPERTIES(V9fsPCIState, vdev.fsconf),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
@@ -948,8 +945,9 @@ static void virtio_9p_pci_class_init(ObjectClass *klass, void *data)
|
||||
static void virtio_9p_pci_instance_init(Object *obj)
|
||||
{
|
||||
V9fsPCIState *dev = VIRTIO_9P_PCI(obj);
|
||||
object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_9P);
|
||||
object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
|
||||
|
||||
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
|
||||
TYPE_VIRTIO_9P);
|
||||
}
|
||||
|
||||
static const TypeInfo virtio_9p_pci_info = {
|
||||
@@ -1042,6 +1040,7 @@ static void virtio_pci_reset(DeviceState *qdev)
|
||||
virtio_pci_stop_ioeventfd(proxy);
|
||||
virtio_bus_reset(bus);
|
||||
msix_unuse_all_vectors(&proxy->pci_dev);
|
||||
proxy->flags &= ~VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
|
||||
}
|
||||
|
||||
static Property virtio_pci_properties[] = {
|
||||
@@ -1111,12 +1110,13 @@ static void virtio_blk_pci_class_init(ObjectClass *klass, void *data)
|
||||
static void virtio_blk_pci_instance_init(Object *obj)
|
||||
{
|
||||
VirtIOBlkPCI *dev = VIRTIO_BLK_PCI(obj);
|
||||
object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_BLK);
|
||||
object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
|
||||
object_unref(OBJECT(&dev->vdev));
|
||||
qdev_alias_all_properties(DEVICE(&dev->vdev), obj);
|
||||
|
||||
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
|
||||
TYPE_VIRTIO_BLK);
|
||||
object_property_add_alias(obj, "iothread", OBJECT(&dev->vdev),"iothread",
|
||||
&error_abort);
|
||||
object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev),
|
||||
"bootindex", &error_abort);
|
||||
}
|
||||
|
||||
static const TypeInfo virtio_blk_pci_info = {
|
||||
@@ -1135,7 +1135,6 @@ static Property virtio_scsi_pci_properties[] = {
|
||||
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors,
|
||||
DEV_NVECTORS_UNSPECIFIED),
|
||||
DEFINE_VIRTIO_SCSI_FEATURES(VirtIOPCIProxy, host_features),
|
||||
DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSIPCI, vdev.parent_obj.conf),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
@@ -1185,8 +1184,11 @@ static void virtio_scsi_pci_class_init(ObjectClass *klass, void *data)
|
||||
static void virtio_scsi_pci_instance_init(Object *obj)
|
||||
{
|
||||
VirtIOSCSIPCI *dev = VIRTIO_SCSI_PCI(obj);
|
||||
object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_SCSI);
|
||||
object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
|
||||
|
||||
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
|
||||
TYPE_VIRTIO_SCSI);
|
||||
object_property_add_alias(obj, "iothread", OBJECT(&dev->vdev), "iothread",
|
||||
&error_abort);
|
||||
}
|
||||
|
||||
static const TypeInfo virtio_scsi_pci_info = {
|
||||
@@ -1203,7 +1205,6 @@ static const TypeInfo virtio_scsi_pci_info = {
|
||||
static Property vhost_scsi_pci_properties[] = {
|
||||
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors,
|
||||
DEV_NVECTORS_UNSPECIFIED),
|
||||
DEFINE_VHOST_SCSI_PROPERTIES(VHostSCSIPCI, vdev.parent_obj.conf),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
@@ -1241,8 +1242,9 @@ static void vhost_scsi_pci_class_init(ObjectClass *klass, void *data)
|
||||
static void vhost_scsi_pci_instance_init(Object *obj)
|
||||
{
|
||||
VHostSCSIPCI *dev = VHOST_SCSI_PCI(obj);
|
||||
object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VHOST_SCSI);
|
||||
object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
|
||||
|
||||
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
|
||||
TYPE_VHOST_SCSI);
|
||||
}
|
||||
|
||||
static const TypeInfo vhost_scsi_pci_info = {
|
||||
@@ -1323,7 +1325,7 @@ static void virtio_balloon_pci_instance_init(Object *obj)
|
||||
VirtIOBalloonPCI *dev = VIRTIO_BALLOON_PCI(obj);
|
||||
object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_BALLOON);
|
||||
object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
|
||||
|
||||
object_unref(OBJECT(&dev->vdev));
|
||||
object_property_add(obj, "guest-stats", "guest statistics",
|
||||
balloon_pci_stats_get_all, NULL, NULL, dev,
|
||||
NULL);
|
||||
@@ -1385,7 +1387,6 @@ static Property virtio_serial_pci_properties[] = {
|
||||
VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
|
||||
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
|
||||
DEFINE_PROP_UINT32("class", VirtIOPCIProxy, class_code, 0),
|
||||
DEFINE_VIRTIO_SERIAL_PROPERTIES(VirtIOSerialPCI, vdev.serial),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
@@ -1406,8 +1407,9 @@ static void virtio_serial_pci_class_init(ObjectClass *klass, void *data)
|
||||
static void virtio_serial_pci_instance_init(Object *obj)
|
||||
{
|
||||
VirtIOSerialPCI *dev = VIRTIO_SERIAL_PCI(obj);
|
||||
object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_SERIAL);
|
||||
object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
|
||||
|
||||
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
|
||||
TYPE_VIRTIO_SERIAL);
|
||||
}
|
||||
|
||||
static const TypeInfo virtio_serial_pci_info = {
|
||||
@@ -1425,8 +1427,6 @@ static Property virtio_net_properties[] = {
|
||||
VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false),
|
||||
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
|
||||
DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features),
|
||||
DEFINE_NIC_PROPERTIES(VirtIONetPCI, vdev.nic_conf),
|
||||
DEFINE_VIRTIO_NET_PROPERTIES(VirtIONetPCI, vdev.net_conf),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
@@ -1465,8 +1465,11 @@ static void virtio_net_pci_class_init(ObjectClass *klass, void *data)
|
||||
static void virtio_net_pci_instance_init(Object *obj)
|
||||
{
|
||||
VirtIONetPCI *dev = VIRTIO_NET_PCI(obj);
|
||||
object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_NET);
|
||||
object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
|
||||
|
||||
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
|
||||
TYPE_VIRTIO_NET);
|
||||
object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev),
|
||||
"bootindex", &error_abort);
|
||||
}
|
||||
|
||||
static const TypeInfo virtio_net_pci_info = {
|
||||
@@ -1480,7 +1483,6 @@ static const TypeInfo virtio_net_pci_info = {
|
||||
/* virtio-rng-pci */
|
||||
|
||||
static Property virtio_rng_pci_properties[] = {
|
||||
DEFINE_VIRTIO_RNG_PROPERTIES(VirtIORngPCI, vdev.conf),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
@@ -1520,8 +1522,9 @@ static void virtio_rng_pci_class_init(ObjectClass *klass, void *data)
|
||||
static void virtio_rng_initfn(Object *obj)
|
||||
{
|
||||
VirtIORngPCI *dev = VIRTIO_RNG_PCI(obj);
|
||||
object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_RNG);
|
||||
object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
|
||||
|
||||
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
|
||||
TYPE_VIRTIO_RNG);
|
||||
object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
|
||||
(Object **)&dev->vdev.conf.rng,
|
||||
qdev_prop_allow_set_link_before_realize,
|
||||
|
||||
@@ -1123,6 +1123,17 @@ static void virtio_vmstate_change(void *opaque, int running, RunState state)
|
||||
}
|
||||
}
|
||||
|
||||
void virtio_instance_init_common(Object *proxy_obj, void *data,
|
||||
size_t vdev_size, const char *vdev_name)
|
||||
{
|
||||
DeviceState *vdev = data;
|
||||
|
||||
object_initialize(vdev, vdev_size, vdev_name);
|
||||
object_property_add_child(proxy_obj, "virtio-backend", OBJECT(vdev), NULL);
|
||||
object_unref(OBJECT(vdev));
|
||||
qdev_alias_all_properties(vdev, proxy_obj);
|
||||
}
|
||||
|
||||
void virtio_init(VirtIODevice *vdev, const char *name,
|
||||
uint16_t device_id, size_t config_size)
|
||||
{
|
||||
|
||||
@@ -473,14 +473,35 @@ typedef struct {
|
||||
#define PPC_FEATURE_TRUE_LE 0x00000002
|
||||
#define PPC_FEATURE_PPC_LE 0x00000001
|
||||
|
||||
/* Bits present in AT_HWCAP, primarily for Sparc32. */
|
||||
/* Bits present in AT_HWCAP for Sparc. */
|
||||
|
||||
#define HWCAP_SPARC_FLUSH 1 /* CPU supports flush instruction. */
|
||||
#define HWCAP_SPARC_STBAR 2
|
||||
#define HWCAP_SPARC_SWAP 4
|
||||
#define HWCAP_SPARC_MULDIV 8
|
||||
#define HWCAP_SPARC_V9 16
|
||||
#define HWCAP_SPARC_ULTRA3 32
|
||||
#define HWCAP_SPARC_FLUSH 0x00000001
|
||||
#define HWCAP_SPARC_STBAR 0x00000002
|
||||
#define HWCAP_SPARC_SWAP 0x00000004
|
||||
#define HWCAP_SPARC_MULDIV 0x00000008
|
||||
#define HWCAP_SPARC_V9 0x00000010
|
||||
#define HWCAP_SPARC_ULTRA3 0x00000020
|
||||
#define HWCAP_SPARC_BLKINIT 0x00000040
|
||||
#define HWCAP_SPARC_N2 0x00000080
|
||||
#define HWCAP_SPARC_MUL32 0x00000100
|
||||
#define HWCAP_SPARC_DIV32 0x00000200
|
||||
#define HWCAP_SPARC_FSMULD 0x00000400
|
||||
#define HWCAP_SPARC_V8PLUS 0x00000800
|
||||
#define HWCAP_SPARC_POPC 0x00001000
|
||||
#define HWCAP_SPARC_VIS 0x00002000
|
||||
#define HWCAP_SPARC_VIS2 0x00004000
|
||||
#define HWCAP_SPARC_ASI_BLK_INIT 0x00008000
|
||||
#define HWCAP_SPARC_FMAF 0x00010000
|
||||
#define HWCAP_SPARC_VIS3 0x00020000
|
||||
#define HWCAP_SPARC_HPC 0x00040000
|
||||
#define HWCAP_SPARC_RANDOM 0x00080000
|
||||
#define HWCAP_SPARC_TRANS 0x00100000
|
||||
#define HWCAP_SPARC_FJFMAU 0x00200000
|
||||
#define HWCAP_SPARC_IMA 0x00400000
|
||||
#define HWCAP_SPARC_ASI_CACHE_SPARING 0x00800000
|
||||
#define HWCAP_SPARC_PAUSE 0x01000000
|
||||
#define HWCAP_SPARC_CBCOND 0x02000000
|
||||
#define HWCAP_SPARC_CRYPTO 0x04000000
|
||||
|
||||
/* Bits present in AT_HWCAP for s390. */
|
||||
|
||||
|
||||
@@ -232,8 +232,8 @@ extern uintptr_t qemu_host_page_mask;
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
void page_dump(FILE *f);
|
||||
|
||||
typedef int (*walk_memory_regions_fn)(void *, abi_ulong,
|
||||
abi_ulong, unsigned long);
|
||||
typedef int (*walk_memory_regions_fn)(void *, target_ulong,
|
||||
target_ulong, unsigned long);
|
||||
int walk_memory_regions(void *, walk_memory_regions_fn);
|
||||
|
||||
int page_get_flags(target_ulong address);
|
||||
|
||||
@@ -49,7 +49,6 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
|
||||
_conf.physical_block_size, 512), \
|
||||
DEFINE_PROP_UINT16("min_io_size", _state, _conf.min_io_size, 0), \
|
||||
DEFINE_PROP_UINT32("opt_io_size", _state, _conf.opt_io_size, 0), \
|
||||
DEFINE_PROP_INT32("bootindex", _state, _conf.bootindex, -1), \
|
||||
DEFINE_PROP_UINT32("discard_granularity", _state, \
|
||||
_conf.discard_granularity, -1)
|
||||
|
||||
|
||||
@@ -5,12 +5,11 @@
|
||||
|
||||
#include "qemu/typedefs.h"
|
||||
#include "sysemu/blockdev.h"
|
||||
#include "sysemu/accel.h"
|
||||
#include "hw/qdev.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
|
||||
typedef struct MachineState MachineState;
|
||||
|
||||
typedef void QEMUMachineInitFunc(MachineState *ms);
|
||||
|
||||
typedef void QEMUMachineResetFunc(void);
|
||||
@@ -28,6 +27,7 @@ struct QEMUMachine {
|
||||
QEMUMachineHotAddCPUFunc *hot_add_cpu;
|
||||
QEMUMachineGetKvmtypeFunc *kvm_type;
|
||||
BlockInterfaceType block_default_type;
|
||||
int units_per_default_bus;
|
||||
int max_cpus;
|
||||
unsigned int no_serial:1,
|
||||
no_parallel:1,
|
||||
@@ -86,6 +86,7 @@ struct MachineClass {
|
||||
int (*kvm_type)(const char *arg);
|
||||
|
||||
BlockInterfaceType block_default_type;
|
||||
int units_per_default_bus;
|
||||
int max_cpus;
|
||||
unsigned int no_serial:1,
|
||||
no_parallel:1,
|
||||
@@ -133,6 +134,7 @@ struct MachineState {
|
||||
char *kernel_cmdline;
|
||||
char *initrd_filename;
|
||||
const char *cpu_model;
|
||||
AccelState *accelerator;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -147,18 +147,13 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab,
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (nsyms) {
|
||||
syms = g_realloc(syms, nsyms * sizeof(*syms));
|
||||
syms = g_realloc(syms, nsyms * sizeof(*syms));
|
||||
|
||||
qsort(syms, nsyms, sizeof(*syms), glue(symcmp, SZ));
|
||||
for (i = 0; i < nsyms - 1; i++) {
|
||||
if (syms[i].st_size == 0) {
|
||||
syms[i].st_size = syms[i + 1].st_value - syms[i].st_value;
|
||||
}
|
||||
qsort(syms, nsyms, sizeof(*syms), glue(symcmp, SZ));
|
||||
for (i = 0; i < nsyms - 1; i++) {
|
||||
if (syms[i].st_size == 0) {
|
||||
syms[i].st_size = syms[i + 1].st_value - syms[i].st_value;
|
||||
}
|
||||
} else {
|
||||
g_free(syms);
|
||||
syms = NULL;
|
||||
}
|
||||
|
||||
/* String table */
|
||||
|
||||
@@ -76,6 +76,8 @@ void fw_cfg_add_file(FWCfgState *s, const char *filename, void *data,
|
||||
void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
|
||||
FWCfgReadCallback callback, void *callback_opaque,
|
||||
void *data, size_t len);
|
||||
void *fw_cfg_modify_file(FWCfgState *s, const char *filename, void *data,
|
||||
size_t len);
|
||||
FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
|
||||
hwaddr crl_addr, hwaddr data_addr);
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "block/block.h"
|
||||
#include "hw/block/block.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qemu/notify.h"
|
||||
|
||||
#define MAX_SCSI_DEVS 255
|
||||
|
||||
@@ -50,17 +51,25 @@ struct SCSIRequest {
|
||||
uint32_t tag;
|
||||
uint32_t lun;
|
||||
uint32_t status;
|
||||
void *hba_private;
|
||||
size_t resid;
|
||||
SCSICommand cmd;
|
||||
NotifierList cancel_notifiers;
|
||||
|
||||
/* Note:
|
||||
* - fields before sense are initialized by scsi_req_alloc;
|
||||
* - sense[] is uninitialized;
|
||||
* - fields after sense are memset to 0 by scsi_req_alloc.
|
||||
* */
|
||||
|
||||
uint8_t sense[SCSI_SENSE_BUF_SIZE];
|
||||
uint32_t sense_len;
|
||||
bool enqueued;
|
||||
bool io_canceled;
|
||||
bool retry;
|
||||
bool dma_started;
|
||||
BlockDriverAIOCB *aiocb;
|
||||
QEMUSGList *sg;
|
||||
bool dma_started;
|
||||
uint8_t sense[SCSI_SENSE_BUF_SIZE];
|
||||
uint32_t sense_len;
|
||||
bool enqueued;
|
||||
bool io_canceled;
|
||||
bool retry;
|
||||
void *hba_private;
|
||||
QTAILQ_ENTRY(SCSIRequest) next;
|
||||
};
|
||||
|
||||
@@ -123,7 +132,6 @@ struct SCSIReqOps {
|
||||
int32_t (*send_command)(SCSIRequest *req, uint8_t *buf);
|
||||
void (*read_data)(SCSIRequest *req);
|
||||
void (*write_data)(SCSIRequest *req);
|
||||
void (*cancel_io)(SCSIRequest *req);
|
||||
uint8_t *(*get_buf)(SCSIRequest *req);
|
||||
|
||||
void (*save_request)(QEMUFile *f, SCSIRequest *req);
|
||||
@@ -258,8 +266,9 @@ void scsi_req_data(SCSIRequest *req, int len);
|
||||
void scsi_req_complete(SCSIRequest *req, int status);
|
||||
uint8_t *scsi_req_get_buf(SCSIRequest *req);
|
||||
int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len);
|
||||
void scsi_req_abort(SCSIRequest *req, int status);
|
||||
void scsi_req_cancel_complete(SCSIRequest *req);
|
||||
void scsi_req_cancel(SCSIRequest *req);
|
||||
void scsi_req_cancel_async(SCSIRequest *req, Notifier *notifier);
|
||||
void scsi_req_retry(SCSIRequest *req);
|
||||
void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense sense);
|
||||
void scsi_device_set_ua(SCSIDevice *sdev, SCSISense sense);
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#include "hw/virtio/virtio.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/scsi/scsi.h"
|
||||
#include "sysemu/iothread.h"
|
||||
#include "hw/virtio/dataplane/vring.h"
|
||||
|
||||
#define TYPE_VIRTIO_SCSI_COMMON "virtio-scsi-common"
|
||||
#define VIRTIO_SCSI_COMMON(obj) \
|
||||
@@ -151,8 +153,18 @@ struct VirtIOSCSIConf {
|
||||
uint32_t cmd_per_lun;
|
||||
char *vhostfd;
|
||||
char *wwpn;
|
||||
IOThread *iothread;
|
||||
};
|
||||
|
||||
struct VirtIOSCSI;
|
||||
|
||||
typedef struct {
|
||||
struct VirtIOSCSI *parent;
|
||||
Vring vring;
|
||||
EventNotifier host_notifier;
|
||||
EventNotifier guest_notifier;
|
||||
} VirtIOSCSIVring;
|
||||
|
||||
typedef struct VirtIOSCSICommon {
|
||||
VirtIODevice parent_obj;
|
||||
VirtIOSCSIConf conf;
|
||||
@@ -164,14 +176,74 @@ typedef struct VirtIOSCSICommon {
|
||||
VirtQueue **cmd_vqs;
|
||||
} VirtIOSCSICommon;
|
||||
|
||||
typedef struct {
|
||||
typedef struct VirtIOSCSI {
|
||||
VirtIOSCSICommon parent_obj;
|
||||
|
||||
SCSIBus bus;
|
||||
int resetting;
|
||||
bool events_dropped;
|
||||
|
||||
/* Fields for dataplane below */
|
||||
AioContext *ctx; /* one iothread per virtio-scsi-pci for now */
|
||||
|
||||
/* Vring is used instead of vq in dataplane code, because of the underlying
|
||||
* memory layer thread safety */
|
||||
VirtIOSCSIVring *ctrl_vring;
|
||||
VirtIOSCSIVring *event_vring;
|
||||
VirtIOSCSIVring **cmd_vrings;
|
||||
bool dataplane_started;
|
||||
bool dataplane_starting;
|
||||
bool dataplane_stopping;
|
||||
bool dataplane_disabled;
|
||||
Notifier migration_state_notifier;
|
||||
} VirtIOSCSI;
|
||||
|
||||
typedef struct VirtIOSCSIReq {
|
||||
VirtIOSCSI *dev;
|
||||
VirtQueue *vq;
|
||||
QEMUSGList qsgl;
|
||||
QEMUIOVector resp_iov;
|
||||
|
||||
/* Note:
|
||||
* - fields before elem are initialized by virtio_scsi_init_req;
|
||||
* - elem is uninitialized at the time of allocation.
|
||||
* - fields after elem are zeroed by virtio_scsi_init_req.
|
||||
* */
|
||||
|
||||
VirtQueueElement elem;
|
||||
/* Set by dataplane code. */
|
||||
VirtIOSCSIVring *vring;
|
||||
|
||||
union {
|
||||
/* Used for two-stage request submission */
|
||||
QTAILQ_ENTRY(VirtIOSCSIReq) next;
|
||||
|
||||
/* Used for cancellation of request during TMFs */
|
||||
int remaining;
|
||||
};
|
||||
|
||||
SCSIRequest *sreq;
|
||||
size_t resp_size;
|
||||
enum SCSIXferMode mode;
|
||||
union {
|
||||
VirtIOSCSICmdResp cmd;
|
||||
VirtIOSCSICtrlTMFResp tmf;
|
||||
VirtIOSCSICtrlANResp an;
|
||||
VirtIOSCSIEvent event;
|
||||
} resp;
|
||||
union {
|
||||
struct {
|
||||
VirtIOSCSICmdReq cmd;
|
||||
uint8_t cdb[];
|
||||
} QEMU_PACKED;
|
||||
VirtIOSCSICtrlTMFReq tmf;
|
||||
VirtIOSCSICtrlANReq an;
|
||||
} req;
|
||||
} VirtIOSCSIReq;
|
||||
|
||||
QEMU_BUILD_BUG_ON(offsetof(VirtIOSCSIReq, req.cdb) !=
|
||||
offsetof(VirtIOSCSIReq, req.cmd) + sizeof(VirtIOSCSICmdReq));
|
||||
|
||||
#define DEFINE_VIRTIO_SCSI_PROPERTIES(_state, _conf_field) \
|
||||
DEFINE_PROP_UINT32("num_queues", _state, _conf_field.num_queues, 1), \
|
||||
DEFINE_PROP_UINT32("max_sectors", _state, _conf_field.max_sectors, 0xFFFF),\
|
||||
@@ -192,5 +264,19 @@ void virtio_scsi_common_realize(DeviceState *dev, Error **errp,
|
||||
HandleOutput cmd);
|
||||
|
||||
void virtio_scsi_common_unrealize(DeviceState *dev, Error **errp);
|
||||
void virtio_scsi_handle_ctrl_req(VirtIOSCSI *s, VirtIOSCSIReq *req);
|
||||
bool virtio_scsi_handle_cmd_req_prepare(VirtIOSCSI *s, VirtIOSCSIReq *req);
|
||||
void virtio_scsi_handle_cmd_req_submit(VirtIOSCSI *s, VirtIOSCSIReq *req);
|
||||
VirtIOSCSIReq *virtio_scsi_init_req(VirtIOSCSI *s, VirtQueue *vq);
|
||||
void virtio_scsi_free_req(VirtIOSCSIReq *req);
|
||||
void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev,
|
||||
uint32_t event, uint32_t reason);
|
||||
|
||||
void virtio_scsi_set_iothread(VirtIOSCSI *s, IOThread *iothread);
|
||||
void virtio_scsi_dataplane_start(VirtIOSCSI *s);
|
||||
void virtio_scsi_dataplane_stop(VirtIOSCSI *s);
|
||||
void virtio_scsi_vring_push_notify(VirtIOSCSIReq *req);
|
||||
VirtIOSCSIReq *virtio_scsi_pop_req_vring(VirtIOSCSI *s,
|
||||
VirtIOSCSIVring *vring);
|
||||
|
||||
#endif /* _QEMU_VIRTIO_SCSI_H */
|
||||
|
||||
@@ -161,6 +161,9 @@ typedef struct VirtioDeviceClass {
|
||||
int (*load)(VirtIODevice *vdev, QEMUFile *f, int version_id);
|
||||
} VirtioDeviceClass;
|
||||
|
||||
void virtio_instance_init_common(Object *proxy_obj, void *data,
|
||||
size_t vdev_size, const char *vdev_name);
|
||||
|
||||
void virtio_init(VirtIODevice *vdev, const char *name,
|
||||
uint16_t device_id, size_t config_size);
|
||||
void virtio_cleanup(VirtIODevice *vdev);
|
||||
|
||||
@@ -36,7 +36,6 @@ void xen_cmos_set_s3_resume(void *opaque, int irq, int level);
|
||||
|
||||
qemu_irq *xen_interrupt_controller_init(void);
|
||||
|
||||
int xen_init(MachineClass *mc);
|
||||
void xenstore_store_pv_console_info(int i, struct CharDriverState *chr);
|
||||
|
||||
#if defined(NEED_CPU_H) && !defined(CONFIG_USER_ONLY)
|
||||
|
||||
@@ -36,8 +36,7 @@ typedef struct NICConf {
|
||||
#define DEFINE_NIC_PROPERTIES(_state, _conf) \
|
||||
DEFINE_PROP_MACADDR("mac", _state, _conf.macaddr), \
|
||||
DEFINE_PROP_VLAN("vlan", _state, _conf.peers), \
|
||||
DEFINE_PROP_NETDEV("netdev", _state, _conf.peers), \
|
||||
DEFINE_PROP_INT32("bootindex", _state, _conf.bootindex, -1)
|
||||
DEFINE_PROP_NETDEV("netdev", _state, _conf.peers)
|
||||
|
||||
|
||||
/* Net clients */
|
||||
|
||||
@@ -190,6 +190,9 @@ int64_t strtosz_suffix_unit(const char *nptr, char **end,
|
||||
/* used to print char* safely */
|
||||
#define STR_OR_NULL(str) ((str) ? (str) : "null")
|
||||
|
||||
/* id.c */
|
||||
bool id_wellformed(const char *id);
|
||||
|
||||
/* path.c */
|
||||
void init_paths(const char *prefix);
|
||||
const char *path(const char *pathname);
|
||||
|
||||
@@ -88,10 +88,19 @@ int slow_bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
|
||||
int slow_bitmap_intersects(const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, long bits);
|
||||
|
||||
static inline unsigned long *bitmap_new(long nbits)
|
||||
static inline unsigned long *bitmap_try_new(long nbits)
|
||||
{
|
||||
long len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
|
||||
return g_malloc0(len);
|
||||
return g_try_malloc0(len);
|
||||
}
|
||||
|
||||
static inline unsigned long *bitmap_new(long nbits)
|
||||
{
|
||||
unsigned long *ptr = bitmap_try_new(nbits);
|
||||
if (ptr == NULL) {
|
||||
abort();
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static inline void bitmap_zero(unsigned long *dst, long nbits)
|
||||
|
||||
@@ -24,6 +24,12 @@
|
||||
#define QEMU_WARN_UNUSED_RESULT
|
||||
#endif
|
||||
|
||||
#if QEMU_GNUC_PREREQ(4, 3)
|
||||
#define QEMU_ARTIFICIAL __attribute__((always_inline, artificial))
|
||||
#else
|
||||
#define QEMU_ARTIFICIAL
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
# define QEMU_PACKED __attribute__((gcc_struct, packed))
|
||||
#else
|
||||
|
||||
@@ -38,6 +38,7 @@ void error_vprintf(const char *fmt, va_list ap) GCC_FMT_ATTR(1, 0);
|
||||
void error_printf(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
|
||||
void error_printf_unless_qmp(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
|
||||
void error_set_progname(const char *argv0);
|
||||
void error_vreport(const char *fmt, va_list ap) GCC_FMT_ATTR(1, 0);
|
||||
void error_report(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
|
||||
const char *error_get_progname(void);
|
||||
extern bool enable_timestamp_msg;
|
||||
|
||||
@@ -103,7 +103,6 @@ typedef int (*qemu_opt_loopfunc)(const char *name, const char *value, void *opaq
|
||||
int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
|
||||
int abort_on_failure);
|
||||
|
||||
int qemu_opts_id_wellformed(const char *id);
|
||||
QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id);
|
||||
QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id,
|
||||
int fail_if_exists, Error **errp);
|
||||
|
||||
@@ -47,7 +47,7 @@ int recv_all(int fd, void *buf, int len1, bool single_read);
|
||||
/* callback function for nonblocking connect
|
||||
* valid fd on success, negative error code on failure
|
||||
*/
|
||||
typedef void NonBlockingConnectHandler(int fd, void *opaque);
|
||||
typedef void NonBlockingConnectHandler(int fd, Error *errp, void *opaque);
|
||||
|
||||
InetSocketAddress *inet_parse(const char *str, Error **errp);
|
||||
int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp);
|
||||
|
||||
@@ -32,6 +32,7 @@ typedef struct MemoryMappingList MemoryMappingList;
|
||||
|
||||
typedef struct QEMUMachine QEMUMachine;
|
||||
typedef struct MachineClass MachineClass;
|
||||
typedef struct MachineState MachineState;
|
||||
typedef struct NICInfo NICInfo;
|
||||
typedef struct HCIInfo HCIInfo;
|
||||
typedef struct AudioState AudioState;
|
||||
|
||||
@@ -99,6 +99,8 @@ struct TranslationBlock;
|
||||
* @vmsd: State description for migration.
|
||||
* @gdb_num_core_regs: Number of core registers accessible to GDB.
|
||||
* @gdb_core_xml_file: File name for core registers GDB XML description.
|
||||
* @gdb_stop_before_watchpoint: Indicates whether GDB expects the CPU to stop
|
||||
* before the insn which triggers a watchpoint rather than after it.
|
||||
* @cpu_exec_enter: Callback for cpu_exec preparation.
|
||||
* @cpu_exec_exit: Callback for cpu_exec cleanup.
|
||||
* @cpu_exec_interrupt: Callback for processing interrupts in cpu_exec.
|
||||
@@ -152,6 +154,7 @@ typedef struct CPUClass {
|
||||
const struct VMStateDescription *vmsd;
|
||||
int gdb_num_core_regs;
|
||||
const char *gdb_core_xml_file;
|
||||
bool gdb_stop_before_watchpoint;
|
||||
|
||||
void (*cpu_exec_enter)(CPUState *cpu);
|
||||
void (*cpu_exec_exit)(CPUState *cpu);
|
||||
|
||||
62
include/sysemu/accel.h
Normal file
62
include/sysemu/accel.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/* QEMU accelerator interfaces
|
||||
*
|
||||
* Copyright (c) 2014 Red Hat Inc
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef HW_ACCEL_H
|
||||
#define HW_ACCEL_H
|
||||
|
||||
#include "qemu/typedefs.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
typedef struct AccelState {
|
||||
/*< private >*/
|
||||
Object parent_obj;
|
||||
} AccelState;
|
||||
|
||||
typedef struct AccelClass {
|
||||
/*< private >*/
|
||||
ObjectClass parent_class;
|
||||
/*< public >*/
|
||||
|
||||
const char *opt_name;
|
||||
const char *name;
|
||||
int (*available)(void);
|
||||
int (*init_machine)(MachineState *ms);
|
||||
bool *allowed;
|
||||
} AccelClass;
|
||||
|
||||
#define TYPE_ACCEL "accel"
|
||||
|
||||
#define ACCEL_CLASS_SUFFIX "-" TYPE_ACCEL
|
||||
#define ACCEL_CLASS_NAME(a) (a ACCEL_CLASS_SUFFIX)
|
||||
|
||||
#define ACCEL_CLASS(klass) \
|
||||
OBJECT_CLASS_CHECK(AccelClass, (klass), TYPE_ACCEL)
|
||||
#define ACCEL(obj) \
|
||||
OBJECT_CHECK(AccelState, (obj), TYPE_ACCEL)
|
||||
#define ACCEL_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(AccelClass, (obj), TYPE_ACCEL)
|
||||
|
||||
extern int tcg_tb_size;
|
||||
|
||||
int configure_accelerator(MachineState *ms);
|
||||
|
||||
#endif
|
||||
@@ -33,7 +33,6 @@ void do_smbios_option(QemuOpts *opts);
|
||||
void ram_mig_init(void);
|
||||
void cpudef_init(void);
|
||||
void audio_init(void);
|
||||
int tcg_available(void);
|
||||
int kvm_available(void);
|
||||
int xen_available(void);
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ struct DriveInfo {
|
||||
int unit;
|
||||
int auto_del; /* see blockdev_mark_auto_del() */
|
||||
bool enable_auto_del; /* Only for legacy drive_new() */
|
||||
bool is_default; /* Added by default_drive() ? */
|
||||
int media_cd;
|
||||
int cyls, heads, secs, trans;
|
||||
QemuOpts *opts;
|
||||
@@ -45,9 +46,13 @@ struct DriveInfo {
|
||||
QTAILQ_ENTRY(DriveInfo) next;
|
||||
};
|
||||
|
||||
void override_max_devs(BlockInterfaceType type, int max_devs);
|
||||
|
||||
DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit);
|
||||
bool drive_check_orphaned(void);
|
||||
DriveInfo *drive_get_by_index(BlockInterfaceType type, int index);
|
||||
int drive_get_max_bus(BlockInterfaceType type);
|
||||
int drive_get_max_devs(BlockInterfaceType type);
|
||||
DriveInfo *drive_get_next(BlockInterfaceType type);
|
||||
DriveInfo *drive_get_by_blockdev(BlockDriverState *bs);
|
||||
|
||||
|
||||
@@ -163,8 +163,6 @@ extern KVMState *kvm_state;
|
||||
|
||||
/* external API */
|
||||
|
||||
int kvm_init(MachineClass *mc);
|
||||
|
||||
int kvm_has_sync_mmu(void);
|
||||
int kvm_has_vcpu_events(void);
|
||||
int kvm_has_robust_singlestep(void);
|
||||
|
||||
@@ -26,7 +26,6 @@ static inline bool qtest_enabled(void)
|
||||
|
||||
bool qtest_driver(void);
|
||||
|
||||
int qtest_init_accel(MachineClass *mc);
|
||||
void qtest_init(const char *qtest_chrdev, const char *qtest_log, Error **errp);
|
||||
|
||||
static inline int qtest_available(void)
|
||||
|
||||
@@ -130,6 +130,7 @@ extern int no_shutdown;
|
||||
extern int semihosting_enabled;
|
||||
extern int old_param;
|
||||
extern int boot_menu;
|
||||
extern bool boot_strict;
|
||||
extern uint8_t *boot_splash_filedata;
|
||||
extern size_t boot_splash_filedata_size;
|
||||
extern uint8_t qemu_extra_params_fw[2];
|
||||
@@ -212,6 +213,11 @@ void add_boot_device_path(int32_t bootindex, DeviceState *dev,
|
||||
char *get_boot_devices_list(size_t *size, bool ignore_suffixes);
|
||||
|
||||
DeviceState *get_boot_device(uint32_t position);
|
||||
void check_boot_index(int32_t bootindex, Error **errp);
|
||||
void del_boot_device_path(DeviceState *dev, const char *suffix);
|
||||
void device_add_bootindex_property(Object *obj, int32_t *bootindex,
|
||||
const char *name, const char *suffix,
|
||||
DeviceState *dev, Error **errp);
|
||||
|
||||
QemuOpts *qemu_get_machine_opts(void);
|
||||
|
||||
|
||||
36
kvm-all.c
36
kvm-all.c
@@ -25,6 +25,7 @@
|
||||
#include "qemu/option.h"
|
||||
#include "qemu/config-file.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/accel.h"
|
||||
#include "hw/hw.h"
|
||||
#include "hw/pci/msi.h"
|
||||
#include "hw/s390x/adapter.h"
|
||||
@@ -72,6 +73,8 @@ typedef struct kvm_dirty_log KVMDirtyLog;
|
||||
|
||||
struct KVMState
|
||||
{
|
||||
AccelState parent_obj;
|
||||
|
||||
KVMSlot *slots;
|
||||
int nr_slots;
|
||||
int fd;
|
||||
@@ -106,6 +109,11 @@ struct KVMState
|
||||
#endif
|
||||
};
|
||||
|
||||
#define TYPE_KVM_ACCEL ACCEL_CLASS_NAME("kvm")
|
||||
|
||||
#define KVM_STATE(obj) \
|
||||
OBJECT_CHECK(KVMState, (obj), TYPE_KVM_ACCEL)
|
||||
|
||||
KVMState *kvm_state;
|
||||
bool kvm_kernel_irqchip;
|
||||
bool kvm_async_interrupts_allowed;
|
||||
@@ -1377,8 +1385,9 @@ static int kvm_max_vcpus(KVMState *s)
|
||||
return (ret) ? ret : kvm_recommended_vcpus(s);
|
||||
}
|
||||
|
||||
int kvm_init(MachineClass *mc)
|
||||
static int kvm_init(MachineState *ms)
|
||||
{
|
||||
MachineClass *mc = MACHINE_GET_CLASS(ms);
|
||||
static const char upgrade_note[] =
|
||||
"Please upgrade to at least kernel 2.6.29 or recent kvm-kmod\n"
|
||||
"(see http://sourceforge.net/projects/kvm).\n";
|
||||
@@ -1397,7 +1406,7 @@ int kvm_init(MachineClass *mc)
|
||||
int i, type = 0;
|
||||
const char *kvm_type;
|
||||
|
||||
s = g_malloc0(sizeof(KVMState));
|
||||
s = KVM_STATE(ms->accelerator);
|
||||
|
||||
/*
|
||||
* On systems where the kernel can support different base page
|
||||
@@ -1586,7 +1595,6 @@ err:
|
||||
close(s->fd);
|
||||
}
|
||||
g_free(s->slots);
|
||||
g_free(s);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -2225,3 +2233,25 @@ int kvm_get_one_reg(CPUState *cs, uint64_t id, void *target)
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static void kvm_accel_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
AccelClass *ac = ACCEL_CLASS(oc);
|
||||
ac->name = "KVM";
|
||||
ac->init_machine = kvm_init;
|
||||
ac->allowed = &kvm_allowed;
|
||||
}
|
||||
|
||||
static const TypeInfo kvm_accel_type = {
|
||||
.name = TYPE_KVM_ACCEL,
|
||||
.parent = TYPE_ACCEL,
|
||||
.class_init = kvm_accel_class_init,
|
||||
.instance_size = sizeof(KVMState),
|
||||
};
|
||||
|
||||
static void kvm_type_init(void)
|
||||
{
|
||||
type_register_static(&kvm_accel_type);
|
||||
}
|
||||
|
||||
type_init(kvm_type_init);
|
||||
|
||||
@@ -35,11 +35,6 @@ int kvm_init_vcpu(CPUState *cpu)
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int kvm_init(MachineClass *mc)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
void kvm_flush_coalesced_mmio_buffer(void)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1 +1,5 @@
|
||||
#include <asm-generic/kvm_para.h>
|
||||
#ifndef _ASM_MIPS_KVM_PARA_H
|
||||
#define _ASM_MIPS_KVM_PARA_H
|
||||
|
||||
|
||||
#endif /* _ASM_MIPS_KVM_PARA_H */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user