Compare commits
206 Commits
vfio-pci-f
...
pull-input
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
47c03744b3 | ||
|
|
6f90f3d786 | ||
|
|
5643706a09 | ||
|
|
5c07d00f1b | ||
|
|
70b52f62b8 | ||
|
|
e842c68d44 | ||
|
|
a8dfb1c34f | ||
|
|
4a33f45e2e | ||
|
|
4798648e32 | ||
|
|
2d0755d21c | ||
|
|
16b0ecd168 | ||
|
|
faecd955ce | ||
|
|
c43ce5512f | ||
|
|
21bae11a39 | ||
|
|
2e08c665cc | ||
|
|
c751a74afe | ||
|
|
f100db385d | ||
|
|
14768eba46 | ||
|
|
3ab193e662 | ||
|
|
192f81bfce | ||
|
|
edd85a3d9e | ||
|
|
502c8db5b4 | ||
|
|
d3535431e8 | ||
|
|
43579403a3 | ||
|
|
cd10032888 | ||
|
|
de8f580b23 | ||
|
|
8d447d10b7 | ||
|
|
a25f545d68 | ||
|
|
af98ba92ac | ||
|
|
d2a9260335 | ||
|
|
9784e57930 | ||
|
|
6567147588 | ||
|
|
c8b405b679 | ||
|
|
8b6b0c59a6 | ||
|
|
bbd1b1cc25 | ||
|
|
031fa96439 | ||
|
|
7ad95ff76c | ||
|
|
d4c8533755 | ||
|
|
f55ea6297c | ||
|
|
ac458e121c | ||
|
|
e00ef747f0 | ||
|
|
4a29420ea1 | ||
|
|
4fd42afe61 | ||
|
|
c2cb92f9ea | ||
|
|
739aa555b8 | ||
|
|
d47e95c0c8 | ||
|
|
57f45b6207 | ||
|
|
b774539743 | ||
|
|
25a7017555 | ||
|
|
949ceeb31b | ||
|
|
56bed4135f | ||
|
|
a105acbce3 | ||
|
|
678e48a2e4 | ||
|
|
2fc0043283 | ||
|
|
7ad993b480 | ||
|
|
aabbd472a0 | ||
|
|
2c38b60010 | ||
|
|
c2216a8a7a | ||
|
|
ab22ad96ce | ||
|
|
357765fed5 | ||
|
|
25254a7191 | ||
|
|
cae8a9289b | ||
|
|
67d065c3db | ||
|
|
777872e5c6 | ||
|
|
cc99c6f5ff | ||
|
|
aa830cdc28 | ||
|
|
7edd9ddc97 | ||
|
|
8ead601883 | ||
|
|
c5d3c49896 | ||
|
|
55e7c29e46 | ||
|
|
0064aceb29 | ||
|
|
de580dafad | ||
|
|
1c884abede | ||
|
|
de92f3f86a | ||
|
|
ffe9fe3a25 | ||
|
|
4864512389 | ||
|
|
3eba13ec25 | ||
|
|
9147d019f3 | ||
|
|
69bef7931e | ||
|
|
4b350f1de1 | ||
|
|
0c762736df | ||
|
|
a9e6a0cbe2 | ||
|
|
adccfbcd60 | ||
|
|
1b37b3442f | ||
|
|
9a05feabd5 | ||
|
|
7d6dc7f30c | ||
|
|
4ab23a9182 | ||
|
|
b53ccc30c4 | ||
|
|
d12f57ec66 | ||
|
|
64cfba6a47 | ||
|
|
d0686c7291 | ||
|
|
298f116827 | ||
|
|
7aad248d35 | ||
|
|
607dacd0a0 | ||
|
|
4835ef7784 | ||
|
|
5d31babe5c | ||
|
|
fda053875e | ||
|
|
6a519918b3 | ||
|
|
b5ba1cc626 | ||
|
|
cb48da7f81 | ||
|
|
4e47e39ab0 | ||
|
|
d2fe51bda8 | ||
|
|
fbb0621a0f | ||
|
|
cd159d0954 | ||
|
|
d844a7b656 | ||
|
|
9fbee91a13 | ||
|
|
73795cea96 | ||
|
|
af87bf290f | ||
|
|
9eb08a435a | ||
|
|
ead4cf04f8 | ||
|
|
f9681f116c | ||
|
|
7f00eb30fe | ||
|
|
1eecf41b3e | ||
|
|
04c2b5168e | ||
|
|
f7d3e46676 | ||
|
|
49f5c9e98a | ||
|
|
0ca3611221 | ||
|
|
5d739a4787 | ||
|
|
d1028f1b5b | ||
|
|
c804c2a717 | ||
|
|
6fbef18a4c | ||
|
|
477a72a1ef | ||
|
|
65e526c24e | ||
|
|
e8803d93df | ||
|
|
6e25280216 | ||
|
|
a0fa2cb8cc | ||
|
|
9da45bb217 | ||
|
|
77319f2263 | ||
|
|
f2c55d1735 | ||
|
|
0788082a4b | ||
|
|
819bd3091e | ||
|
|
3a553fc658 | ||
|
|
216db403d0 | ||
|
|
2ce5868ca1 | ||
|
|
6f6831f61a | ||
|
|
bc3fbad816 | ||
|
|
28c05edff5 | ||
|
|
c04018e933 | ||
|
|
a5ae7e3984 | ||
|
|
432a0a130e | ||
|
|
1c8be73d4e | ||
|
|
c3143ba877 | ||
|
|
024c6e2ea5 | ||
|
|
63a31905cb | ||
|
|
eb0ecd5ad9 | ||
|
|
0956ff5a4e | ||
|
|
1f79ee32b5 | ||
|
|
34222fb810 | ||
|
|
9cfa0b4e4c | ||
|
|
4cc35614a0 | ||
|
|
1ed69e82b8 | ||
|
|
d9ea7d290b | ||
|
|
cd5c11b84b | ||
|
|
0b45451e58 | ||
|
|
e60cef860f | ||
|
|
a7adc4b779 | ||
|
|
4b7fff2fab | ||
|
|
327ed10fa2 | ||
|
|
a505d7fe5f | ||
|
|
cb2e37dffa | ||
|
|
5ebafdf31a | ||
|
|
b0fe242751 | ||
|
|
91e240698f | ||
|
|
168aa23bb0 | ||
|
|
8af35c37d2 | ||
|
|
cd4da63177 | ||
|
|
0eef9d9833 | ||
|
|
7da845b0f4 | ||
|
|
67ed771ded | ||
|
|
855011be05 | ||
|
|
1da41cc1c6 | ||
|
|
0a6a7ccaae | ||
|
|
d6032e06d1 | ||
|
|
876074c228 | ||
|
|
6453fa998a | ||
|
|
c10f7fc3d1 | ||
|
|
cf143ad350 | ||
|
|
fce0a82608 | ||
|
|
775fda92a1 | ||
|
|
cba933b225 | ||
|
|
106a73b6d2 | ||
|
|
ec1efab957 | ||
|
|
ad37bb3b00 | ||
|
|
e3e48565c1 | ||
|
|
d6085e3ace | ||
|
|
41310c6878 | ||
|
|
6d3cb1f970 | ||
|
|
24a370ef23 | ||
|
|
aded6539d9 | ||
|
|
0a985b3727 | ||
|
|
f6c65bfb93 | ||
|
|
3bac80d31a | ||
|
|
cf528b8958 | ||
|
|
2e753bcc7d | ||
|
|
1f55ac4586 | ||
|
|
e96dfd110e | ||
|
|
6e50d18847 | ||
|
|
cd6c88305f | ||
|
|
d9738fd246 | ||
|
|
64cc22841e | ||
|
|
24d3bd67ac | ||
|
|
837c390137 | ||
|
|
7ef8cf9a08 | ||
|
|
703dd81aca | ||
|
|
c5f52875b9 | ||
|
|
521f438e36 |
@@ -726,7 +726,7 @@ F: vl.c
|
||||
|
||||
Human Monitor (HMP)
|
||||
M: Luiz Capitulino <lcapitulino@redhat.com>
|
||||
S: Supported
|
||||
S: Maintained
|
||||
F: monitor.c
|
||||
F: hmp.c
|
||||
F: hmp-commands.hx
|
||||
@@ -758,7 +758,7 @@ T: git git://github.com/bonzini/qemu.git nbd-next
|
||||
QAPI
|
||||
M: Luiz Capitulino <lcapitulino@redhat.com>
|
||||
M: Michael Roth <mdroth@linux.vnet.ibm.com>
|
||||
S: Supported
|
||||
S: Maintained
|
||||
F: qapi/
|
||||
T: git git://repo.or.cz/qemu/qmp-unstable.git queue/qmp
|
||||
|
||||
@@ -772,7 +772,7 @@ T: git git://repo.or.cz/qemu/qmp-unstable.git queue/qmp
|
||||
|
||||
QMP
|
||||
M: Luiz Capitulino <lcapitulino@redhat.com>
|
||||
S: Supported
|
||||
S: Maintained
|
||||
F: qmp.c
|
||||
F: monitor.c
|
||||
F: qmp-commands.hx
|
||||
|
||||
3
Makefile
3
Makefile
@@ -159,6 +159,7 @@ qemu-options.def: $(SRC_PATH)/qemu-options.hx
|
||||
SUBDIR_RULES=$(patsubst %,subdir-%, $(TARGET_DIRS))
|
||||
SOFTMMU_SUBDIR_RULES=$(filter %-softmmu,$(SUBDIR_RULES))
|
||||
|
||||
$(SOFTMMU_SUBDIR_RULES): $(block-obj-y)
|
||||
$(SOFTMMU_SUBDIR_RULES): config-all-devices.mak
|
||||
|
||||
subdir-%:
|
||||
@@ -319,7 +320,7 @@ ifdef INSTALL_BLOBS
|
||||
BLOBS=bios.bin bios-256k.bin sgabios.bin vgabios.bin vgabios-cirrus.bin \
|
||||
vgabios-stdvga.bin vgabios-vmware.bin vgabios-qxl.bin \
|
||||
acpi-dsdt.aml q35-acpi-dsdt.aml \
|
||||
ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc QEMU,tcx.bin \
|
||||
ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc QEMU,tcx.bin QEMU,cgthree.bin \
|
||||
pxe-e1000.rom pxe-eepro100.rom pxe-ne2k_pci.rom \
|
||||
pxe-pcnet.rom pxe-rtl8139.rom pxe-virtio.rom \
|
||||
efi-e1000.rom efi-eepro100.rom efi-ne2k_pci.rom \
|
||||
|
||||
64
arch_init.c
64
arch_init.c
@@ -122,7 +122,6 @@ static void check_guest_throttling(void);
|
||||
#define RAM_SAVE_FLAG_XBZRLE 0x40
|
||||
/* 0x80 is reserved in migration.h start with 0x100 next */
|
||||
|
||||
|
||||
static struct defconfig_file {
|
||||
const char *filename;
|
||||
/* Indicates it is an user config file (disabled by -no-user-config) */
|
||||
@@ -133,6 +132,7 @@ static struct defconfig_file {
|
||||
{ NULL }, /* end of list */
|
||||
};
|
||||
|
||||
static const uint8_t ZERO_TARGET_PAGE[TARGET_PAGE_SIZE];
|
||||
|
||||
int qemu_read_default_config_files(bool userconfig)
|
||||
{
|
||||
@@ -273,6 +273,34 @@ static size_t save_block_hdr(QEMUFile *f, RAMBlock *block, ram_addr_t offset,
|
||||
return size;
|
||||
}
|
||||
|
||||
/* This is the last block that we have visited serching for dirty pages
|
||||
*/
|
||||
static RAMBlock *last_seen_block;
|
||||
/* This is the last block from where we have sent data */
|
||||
static RAMBlock *last_sent_block;
|
||||
static ram_addr_t last_offset;
|
||||
static unsigned long *migration_bitmap;
|
||||
static uint64_t migration_dirty_pages;
|
||||
static uint32_t last_version;
|
||||
static bool ram_bulk_stage;
|
||||
|
||||
/* Update the xbzrle cache to reflect a page that's been sent as all 0.
|
||||
* The important thing is that a stale (not-yet-0'd) page be replaced
|
||||
* by the new data.
|
||||
* As a bonus, if the page wasn't in the cache it gets added so that
|
||||
* when a small write is made into the 0'd page it gets XBZRLE sent
|
||||
*/
|
||||
static void xbzrle_cache_zero_page(ram_addr_t current_addr)
|
||||
{
|
||||
if (ram_bulk_stage || !migrate_use_xbzrle()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* We don't care if this fails to allocate a new cache page
|
||||
* as long as it updated an old one */
|
||||
cache_insert(XBZRLE.cache, current_addr, ZERO_TARGET_PAGE);
|
||||
}
|
||||
|
||||
#define ENCODING_FLAG_XBZRLE 0x1
|
||||
|
||||
static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
|
||||
@@ -329,18 +357,6 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
|
||||
return bytes_sent;
|
||||
}
|
||||
|
||||
|
||||
/* This is the last block that we have visited serching for dirty pages
|
||||
*/
|
||||
static RAMBlock *last_seen_block;
|
||||
/* This is the last block from where we have sent data */
|
||||
static RAMBlock *last_sent_block;
|
||||
static ram_addr_t last_offset;
|
||||
static unsigned long *migration_bitmap;
|
||||
static uint64_t migration_dirty_pages;
|
||||
static uint32_t last_version;
|
||||
static bool ram_bulk_stage;
|
||||
|
||||
static inline
|
||||
ram_addr_t migration_bitmap_find_and_reset_dirty(MemoryRegion *mr,
|
||||
ram_addr_t start)
|
||||
@@ -512,6 +528,7 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
|
||||
} else {
|
||||
int ret;
|
||||
uint8_t *p;
|
||||
bool send_async = true;
|
||||
int cont = (block == last_sent_block) ?
|
||||
RAM_SAVE_FLAG_CONTINUE : 0;
|
||||
|
||||
@@ -522,6 +539,7 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
|
||||
ret = ram_control_save_page(f, block->offset,
|
||||
offset, TARGET_PAGE_SIZE, &bytes_sent);
|
||||
|
||||
current_addr = block->offset + offset;
|
||||
if (ret != RAM_SAVE_CONTROL_NOT_SUPP) {
|
||||
if (ret != RAM_SAVE_CONTROL_DELAYED) {
|
||||
if (bytes_sent > 0) {
|
||||
@@ -536,19 +554,35 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
|
||||
RAM_SAVE_FLAG_COMPRESS);
|
||||
qemu_put_byte(f, 0);
|
||||
bytes_sent++;
|
||||
/* Must let xbzrle know, otherwise a previous (now 0'd) cached
|
||||
* page would be stale
|
||||
*/
|
||||
xbzrle_cache_zero_page(current_addr);
|
||||
} else if (!ram_bulk_stage && migrate_use_xbzrle()) {
|
||||
current_addr = block->offset + offset;
|
||||
bytes_sent = save_xbzrle_page(f, p, current_addr, block,
|
||||
offset, cont, last_stage);
|
||||
if (!last_stage) {
|
||||
/* We must send exactly what's in the xbzrle cache
|
||||
* even if the page wasn't xbzrle compressed, so that
|
||||
* it's right next time.
|
||||
*/
|
||||
p = get_cached_data(XBZRLE.cache, current_addr);
|
||||
|
||||
/* Can't send this cached data async, since the cache page
|
||||
* might get updated before it gets to the wire
|
||||
*/
|
||||
send_async = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* XBZRLE overflow or normal page */
|
||||
if (bytes_sent == -1) {
|
||||
bytes_sent = save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_PAGE);
|
||||
qemu_put_buffer_async(f, p, TARGET_PAGE_SIZE);
|
||||
if (send_async) {
|
||||
qemu_put_buffer_async(f, p, TARGET_PAGE_SIZE);
|
||||
} else {
|
||||
qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
|
||||
}
|
||||
bytes_sent += TARGET_PAGE_SIZE;
|
||||
acct_info.norm_pages++;
|
||||
}
|
||||
|
||||
@@ -566,7 +566,7 @@ CharDriverState *chr_baum_init(void)
|
||||
BaumDriverState *baum;
|
||||
CharDriverState *chr;
|
||||
brlapi_handle_t *handle;
|
||||
#ifdef CONFIG_SDL
|
||||
#if defined(CONFIG_SDL) && SDL_COMPILEDVERSION < SDL_VERSIONNUM(2, 0, 0)
|
||||
SDL_SysWMinfo info;
|
||||
#endif
|
||||
int tty;
|
||||
@@ -595,7 +595,7 @@ CharDriverState *chr_baum_init(void)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SDL
|
||||
#if defined(CONFIG_SDL) && SDL_COMPILEDVERSION < SDL_VERSIONNUM(2, 0, 0)
|
||||
memset(&info, 0, sizeof(info));
|
||||
SDL_VERSION(&info.version);
|
||||
if (SDL_GetWMInfo(&info))
|
||||
|
||||
5
block.c
5
block.c
@@ -547,8 +547,9 @@ int get_tmp_filename(char *filename, int size)
|
||||
int fd;
|
||||
const char *tmpdir;
|
||||
tmpdir = getenv("TMPDIR");
|
||||
if (!tmpdir)
|
||||
tmpdir = "/tmp";
|
||||
if (!tmpdir) {
|
||||
tmpdir = "/var/tmp";
|
||||
}
|
||||
if (snprintf(filename, size, "%s/vl.XXXXXX", tmpdir) >= size) {
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
|
||||
143
block/gluster.c
143
block/gluster.c
@@ -45,11 +45,13 @@ typedef struct GlusterConf {
|
||||
|
||||
static void qemu_gluster_gconf_free(GlusterConf *gconf)
|
||||
{
|
||||
g_free(gconf->server);
|
||||
g_free(gconf->volname);
|
||||
g_free(gconf->image);
|
||||
g_free(gconf->transport);
|
||||
g_free(gconf);
|
||||
if (gconf) {
|
||||
g_free(gconf->server);
|
||||
g_free(gconf->volname);
|
||||
g_free(gconf->image);
|
||||
g_free(gconf->transport);
|
||||
g_free(gconf);
|
||||
}
|
||||
}
|
||||
|
||||
static int parse_volume_options(GlusterConf *gconf, char *path)
|
||||
@@ -272,11 +274,28 @@ static QemuOptsList runtime_opts = {
|
||||
},
|
||||
};
|
||||
|
||||
static void qemu_gluster_parse_flags(int bdrv_flags, int *open_flags)
|
||||
{
|
||||
assert(open_flags != NULL);
|
||||
|
||||
*open_flags |= O_BINARY;
|
||||
|
||||
if (bdrv_flags & BDRV_O_RDWR) {
|
||||
*open_flags |= O_RDWR;
|
||||
} else {
|
||||
*open_flags |= O_RDONLY;
|
||||
}
|
||||
|
||||
if ((bdrv_flags & BDRV_O_NOCACHE)) {
|
||||
*open_flags |= O_DIRECT;
|
||||
}
|
||||
}
|
||||
|
||||
static int qemu_gluster_open(BlockDriverState *bs, QDict *options,
|
||||
int bdrv_flags, Error **errp)
|
||||
{
|
||||
BDRVGlusterState *s = bs->opaque;
|
||||
int open_flags = O_BINARY;
|
||||
int open_flags = 0;
|
||||
int ret = 0;
|
||||
GlusterConf *gconf = g_malloc0(sizeof(GlusterConf));
|
||||
QemuOpts *opts;
|
||||
@@ -299,15 +318,7 @@ static int qemu_gluster_open(BlockDriverState *bs, QDict *options,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (bdrv_flags & BDRV_O_RDWR) {
|
||||
open_flags |= O_RDWR;
|
||||
} else {
|
||||
open_flags |= O_RDONLY;
|
||||
}
|
||||
|
||||
if ((bdrv_flags & BDRV_O_NOCACHE)) {
|
||||
open_flags |= O_DIRECT;
|
||||
}
|
||||
qemu_gluster_parse_flags(bdrv_flags, &open_flags);
|
||||
|
||||
s->fd = glfs_open(s->glfs, gconf->image, open_flags);
|
||||
if (!s->fd) {
|
||||
@@ -329,6 +340,96 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef struct BDRVGlusterReopenState {
|
||||
struct glfs *glfs;
|
||||
struct glfs_fd *fd;
|
||||
} BDRVGlusterReopenState;
|
||||
|
||||
|
||||
static int qemu_gluster_reopen_prepare(BDRVReopenState *state,
|
||||
BlockReopenQueue *queue, Error **errp)
|
||||
{
|
||||
int ret = 0;
|
||||
BDRVGlusterReopenState *reop_s;
|
||||
GlusterConf *gconf = NULL;
|
||||
int open_flags = 0;
|
||||
|
||||
assert(state != NULL);
|
||||
assert(state->bs != NULL);
|
||||
|
||||
state->opaque = g_malloc0(sizeof(BDRVGlusterReopenState));
|
||||
reop_s = state->opaque;
|
||||
|
||||
qemu_gluster_parse_flags(state->flags, &open_flags);
|
||||
|
||||
gconf = g_malloc0(sizeof(GlusterConf));
|
||||
|
||||
reop_s->glfs = qemu_gluster_init(gconf, state->bs->filename, errp);
|
||||
if (reop_s->glfs == NULL) {
|
||||
ret = -errno;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
reop_s->fd = glfs_open(reop_s->glfs, gconf->image, open_flags);
|
||||
if (reop_s->fd == NULL) {
|
||||
/* reops->glfs will be cleaned up in _abort */
|
||||
ret = -errno;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
/* state->opaque will be freed in either the _abort or _commit */
|
||||
qemu_gluster_gconf_free(gconf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void qemu_gluster_reopen_commit(BDRVReopenState *state)
|
||||
{
|
||||
BDRVGlusterReopenState *reop_s = state->opaque;
|
||||
BDRVGlusterState *s = state->bs->opaque;
|
||||
|
||||
|
||||
/* close the old */
|
||||
if (s->fd) {
|
||||
glfs_close(s->fd);
|
||||
}
|
||||
if (s->glfs) {
|
||||
glfs_fini(s->glfs);
|
||||
}
|
||||
|
||||
/* use the newly opened image / connection */
|
||||
s->fd = reop_s->fd;
|
||||
s->glfs = reop_s->glfs;
|
||||
|
||||
g_free(state->opaque);
|
||||
state->opaque = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void qemu_gluster_reopen_abort(BDRVReopenState *state)
|
||||
{
|
||||
BDRVGlusterReopenState *reop_s = state->opaque;
|
||||
|
||||
if (reop_s == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (reop_s->fd) {
|
||||
glfs_close(reop_s->fd);
|
||||
}
|
||||
|
||||
if (reop_s->glfs) {
|
||||
glfs_fini(reop_s->glfs);
|
||||
}
|
||||
|
||||
g_free(state->opaque);
|
||||
state->opaque = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_GLUSTERFS_ZEROFILL
|
||||
static coroutine_fn int qemu_gluster_co_write_zeroes(BlockDriverState *bs,
|
||||
int64_t sector_num, int nb_sectors, BdrvRequestFlags flags)
|
||||
@@ -619,6 +720,9 @@ static BlockDriver bdrv_gluster = {
|
||||
.instance_size = sizeof(BDRVGlusterState),
|
||||
.bdrv_needs_filename = true,
|
||||
.bdrv_file_open = qemu_gluster_open,
|
||||
.bdrv_reopen_prepare = qemu_gluster_reopen_prepare,
|
||||
.bdrv_reopen_commit = qemu_gluster_reopen_commit,
|
||||
.bdrv_reopen_abort = qemu_gluster_reopen_abort,
|
||||
.bdrv_close = qemu_gluster_close,
|
||||
.bdrv_create = qemu_gluster_create,
|
||||
.bdrv_getlength = qemu_gluster_getlength,
|
||||
@@ -643,6 +747,9 @@ static BlockDriver bdrv_gluster_tcp = {
|
||||
.instance_size = sizeof(BDRVGlusterState),
|
||||
.bdrv_needs_filename = true,
|
||||
.bdrv_file_open = qemu_gluster_open,
|
||||
.bdrv_reopen_prepare = qemu_gluster_reopen_prepare,
|
||||
.bdrv_reopen_commit = qemu_gluster_reopen_commit,
|
||||
.bdrv_reopen_abort = qemu_gluster_reopen_abort,
|
||||
.bdrv_close = qemu_gluster_close,
|
||||
.bdrv_create = qemu_gluster_create,
|
||||
.bdrv_getlength = qemu_gluster_getlength,
|
||||
@@ -667,6 +774,9 @@ static BlockDriver bdrv_gluster_unix = {
|
||||
.instance_size = sizeof(BDRVGlusterState),
|
||||
.bdrv_needs_filename = true,
|
||||
.bdrv_file_open = qemu_gluster_open,
|
||||
.bdrv_reopen_prepare = qemu_gluster_reopen_prepare,
|
||||
.bdrv_reopen_commit = qemu_gluster_reopen_commit,
|
||||
.bdrv_reopen_abort = qemu_gluster_reopen_abort,
|
||||
.bdrv_close = qemu_gluster_close,
|
||||
.bdrv_create = qemu_gluster_create,
|
||||
.bdrv_getlength = qemu_gluster_getlength,
|
||||
@@ -691,6 +801,9 @@ static BlockDriver bdrv_gluster_rdma = {
|
||||
.instance_size = sizeof(BDRVGlusterState),
|
||||
.bdrv_needs_filename = true,
|
||||
.bdrv_file_open = qemu_gluster_open,
|
||||
.bdrv_reopen_prepare = qemu_gluster_reopen_prepare,
|
||||
.bdrv_reopen_commit = qemu_gluster_reopen_commit,
|
||||
.bdrv_reopen_abort = qemu_gluster_reopen_abort,
|
||||
.bdrv_close = qemu_gluster_close,
|
||||
.bdrv_create = qemu_gluster_create,
|
||||
.bdrv_getlength = qemu_gluster_getlength,
|
||||
|
||||
141
block/iscsi.c
141
block/iscsi.c
@@ -145,12 +145,13 @@ iscsi_co_generic_cb(struct iscsi_context *iscsi, int status,
|
||||
|
||||
if (iTask->retries-- > 0 && status == SCSI_STATUS_CHECK_CONDITION
|
||||
&& task->sense.key == SCSI_SENSE_UNIT_ATTENTION) {
|
||||
error_report("iSCSI CheckCondition: %s", iscsi_get_error(iscsi));
|
||||
iTask->do_retry = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (status != SCSI_STATUS_GOOD) {
|
||||
error_report("iSCSI: Failure. %s", iscsi_get_error(iscsi));
|
||||
error_report("iSCSI Failure: %s", iscsi_get_error(iscsi));
|
||||
}
|
||||
|
||||
out:
|
||||
@@ -325,6 +326,7 @@ retry:
|
||||
}
|
||||
|
||||
if (iTask.do_retry) {
|
||||
iTask.complete = 0;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
@@ -399,6 +401,7 @@ retry:
|
||||
}
|
||||
|
||||
if (iTask.do_retry) {
|
||||
iTask.complete = 0;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
@@ -433,6 +436,7 @@ retry:
|
||||
}
|
||||
|
||||
if (iTask.do_retry) {
|
||||
iTask.complete = 0;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
@@ -683,6 +687,7 @@ retry:
|
||||
scsi_free_scsi_task(iTask.task);
|
||||
iTask.task = NULL;
|
||||
}
|
||||
iTask.complete = 0;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
@@ -767,6 +772,7 @@ retry:
|
||||
}
|
||||
|
||||
if (iTask.do_retry) {
|
||||
iTask.complete = 0;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
@@ -830,24 +836,26 @@ retry:
|
||||
qemu_coroutine_yield();
|
||||
}
|
||||
|
||||
if (iTask.status == SCSI_STATUS_CHECK_CONDITION &&
|
||||
iTask.task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST &&
|
||||
iTask.task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE) {
|
||||
/* WRITE SAME is not supported by the target */
|
||||
iscsilun->has_write_same = false;
|
||||
scsi_free_scsi_task(iTask.task);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (iTask.task != NULL) {
|
||||
scsi_free_scsi_task(iTask.task);
|
||||
iTask.task = NULL;
|
||||
}
|
||||
|
||||
if (iTask.do_retry) {
|
||||
iTask.complete = 0;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if (iTask.status != SCSI_STATUS_GOOD) {
|
||||
if (iTask.status == SCSI_STATUS_CHECK_CONDITION &&
|
||||
iTask.task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST &&
|
||||
iTask.task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE) {
|
||||
/* WRITE SAME is not supported by the target */
|
||||
iscsilun->has_write_same = false;
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -1060,7 +1068,7 @@ static QemuOptsList runtime_opts = {
|
||||
};
|
||||
|
||||
static struct scsi_task *iscsi_do_inquiry(struct iscsi_context *iscsi, int lun,
|
||||
int evpd, int pc, Error **errp)
|
||||
int evpd, int pc, void **inq, Error **errp)
|
||||
{
|
||||
int full_size;
|
||||
struct scsi_task *task = NULL;
|
||||
@@ -1079,14 +1087,19 @@ static struct scsi_task *iscsi_do_inquiry(struct iscsi_context *iscsi, int lun,
|
||||
}
|
||||
}
|
||||
|
||||
*inq = scsi_datain_unmarshall(task);
|
||||
if (*inq == NULL) {
|
||||
error_setg(errp, "iSCSI: failed to unmarshall inquiry datain blob");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return task;
|
||||
|
||||
fail:
|
||||
error_setg(errp, "iSCSI: Inquiry command failed : %s",
|
||||
iscsi_get_error(iscsi));
|
||||
if (task) {
|
||||
if (task != NULL) {
|
||||
scsi_free_scsi_task(task);
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -1107,11 +1120,12 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
struct iscsi_url *iscsi_url = NULL;
|
||||
struct scsi_task *task = NULL;
|
||||
struct scsi_inquiry_standard *inq = NULL;
|
||||
struct scsi_inquiry_supported_pages *inq_vpd;
|
||||
char *initiator_name = NULL;
|
||||
QemuOpts *opts;
|
||||
Error *local_err = NULL;
|
||||
const char *filename;
|
||||
int ret;
|
||||
int i, ret;
|
||||
|
||||
if ((BDRV_SECTOR_SIZE % 512) != 0) {
|
||||
error_setg(errp, "iSCSI: Invalid BDRV_SECTOR_SIZE. "
|
||||
@@ -1197,25 +1211,18 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
|
||||
iscsilun->iscsi = iscsi;
|
||||
iscsilun->lun = iscsi_url->lun;
|
||||
|
||||
task = iscsi_inquiry_sync(iscsi, iscsilun->lun, 0, 0, 36);
|
||||
|
||||
if (task == NULL || task->status != SCSI_STATUS_GOOD) {
|
||||
error_setg(errp, "iSCSI: failed to send inquiry command.");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
inq = scsi_datain_unmarshall(task);
|
||||
if (inq == NULL) {
|
||||
error_setg(errp, "iSCSI: Failed to unmarshall inquiry data.");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
iscsilun->type = inq->periperal_device_type;
|
||||
iscsilun->has_write_same = true;
|
||||
|
||||
task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 0, 0,
|
||||
(void **) &inq, errp);
|
||||
if (task == NULL) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
iscsilun->type = inq->periperal_device_type;
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
|
||||
iscsi_readcapacity_sync(iscsilun, &local_err);
|
||||
if (local_err != NULL) {
|
||||
error_propagate(errp, local_err);
|
||||
@@ -1233,46 +1240,48 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
bs->sg = 1;
|
||||
}
|
||||
|
||||
if (iscsilun->lbpme) {
|
||||
task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1,
|
||||
SCSI_INQUIRY_PAGECODE_SUPPORTED_VPD_PAGES,
|
||||
(void **) &inq_vpd, errp);
|
||||
if (task == NULL) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
for (i = 0; i < inq_vpd->num_pages; i++) {
|
||||
struct scsi_task *inq_task;
|
||||
struct scsi_inquiry_logical_block_provisioning *inq_lbp;
|
||||
task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1,
|
||||
SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING,
|
||||
errp);
|
||||
if (task == NULL) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
inq_lbp = scsi_datain_unmarshall(task);
|
||||
if (inq_lbp == NULL) {
|
||||
error_setg(errp, "iSCSI: failed to unmarshall inquiry datain blob");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
memcpy(&iscsilun->lbp, inq_lbp,
|
||||
sizeof(struct scsi_inquiry_logical_block_provisioning));
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
}
|
||||
|
||||
if (iscsilun->lbp.lbpu || iscsilun->lbp.lbpws) {
|
||||
struct scsi_inquiry_block_limits *inq_bl;
|
||||
task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1,
|
||||
SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS, errp);
|
||||
if (task == NULL) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
switch (inq_vpd->pages[i]) {
|
||||
case SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING:
|
||||
inq_task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1,
|
||||
SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING,
|
||||
(void **) &inq_lbp, errp);
|
||||
if (inq_task == NULL) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
memcpy(&iscsilun->lbp, inq_lbp,
|
||||
sizeof(struct scsi_inquiry_logical_block_provisioning));
|
||||
scsi_free_scsi_task(inq_task);
|
||||
break;
|
||||
case SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS:
|
||||
inq_task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1,
|
||||
SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS,
|
||||
(void **) &inq_bl, errp);
|
||||
if (inq_task == NULL) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
memcpy(&iscsilun->bl, inq_bl,
|
||||
sizeof(struct scsi_inquiry_block_limits));
|
||||
scsi_free_scsi_task(inq_task);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
inq_bl = scsi_datain_unmarshall(task);
|
||||
if (inq_bl == NULL) {
|
||||
error_setg(errp, "iSCSI: failed to unmarshall inquiry datain blob");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
memcpy(&iscsilun->bl, inq_bl,
|
||||
sizeof(struct scsi_inquiry_block_limits));
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
}
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
|
||||
#if defined(LIBISCSI_FEATURE_NOP_COUNTER)
|
||||
/* Set up a timer for sending out iSCSI NOPs */
|
||||
|
||||
@@ -200,11 +200,14 @@ static void quorum_report_bad(QuorumAIOCB *acb, char *node_name, int ret)
|
||||
{
|
||||
QObject *data;
|
||||
assert(node_name);
|
||||
data = qobject_from_jsonf("{ 'ret': %d"
|
||||
", 'node-name': %s"
|
||||
data = qobject_from_jsonf("{ 'node-name': %s"
|
||||
", 'sector-num': %" PRId64
|
||||
", 'sectors-count': %d }",
|
||||
ret, node_name, acb->sector_num, acb->nb_sectors);
|
||||
node_name, acb->sector_num, acb->nb_sectors);
|
||||
if (ret < 0) {
|
||||
QDict *dict = qobject_to_qdict(data);
|
||||
qdict_put(dict, "error", qstring_from_str(strerror(-ret)));
|
||||
}
|
||||
monitor_protocol_event(QEVENT_QUORUM_REPORT_BAD, data);
|
||||
qobject_decref(data);
|
||||
}
|
||||
|
||||
@@ -1184,7 +1184,7 @@ static int64_t coroutine_fn vmdk_co_get_block_status(BlockDriverState *bs,
|
||||
break;
|
||||
case VMDK_OK:
|
||||
ret = BDRV_BLOCK_DATA;
|
||||
if (extent->file == bs->file) {
|
||||
if (extent->file == bs->file && !extent->compressed) {
|
||||
ret |= BDRV_BLOCK_OFFSET_VALID | offset;
|
||||
}
|
||||
|
||||
|
||||
89
configure
vendored
89
configure
vendored
@@ -207,6 +207,7 @@ fdt=""
|
||||
netmap="no"
|
||||
pixman=""
|
||||
sdl=""
|
||||
sdlabi="1.2"
|
||||
virtfs=""
|
||||
vnc="yes"
|
||||
sparse="no"
|
||||
@@ -283,6 +284,8 @@ libusb=""
|
||||
usb_redir=""
|
||||
glx=""
|
||||
zlib="yes"
|
||||
lzo="no"
|
||||
snappy="no"
|
||||
guest_agent=""
|
||||
guest_agent_with_vss="no"
|
||||
vss_win32_sdk=""
|
||||
@@ -364,6 +367,7 @@ query_pkg_config() {
|
||||
}
|
||||
pkg_config=query_pkg_config
|
||||
sdl_config="${SDL_CONFIG-${cross_prefix}sdl-config}"
|
||||
sdl2_config="${SDL2_CONFIG-${cross_prefix}sdl2-config}"
|
||||
|
||||
# If the user hasn't specified ARFLAGS, default to 'rv', just as make does.
|
||||
ARFLAGS="${ARFLAGS-rv}"
|
||||
@@ -773,6 +777,8 @@ for opt do
|
||||
;;
|
||||
--enable-sdl) sdl="yes"
|
||||
;;
|
||||
--with-sdlabi=*) sdlabi="$optarg"
|
||||
;;
|
||||
--disable-qom-cast-debug) qom_cast_debug="no"
|
||||
;;
|
||||
--enable-qom-cast-debug) qom_cast_debug="yes"
|
||||
@@ -995,6 +1001,10 @@ for opt do
|
||||
;;
|
||||
--disable-zlib-test) zlib="no"
|
||||
;;
|
||||
--enable-lzo) lzo="yes"
|
||||
;;
|
||||
--enable-snappy) snappy="yes"
|
||||
;;
|
||||
--enable-guest-agent) guest_agent="yes"
|
||||
;;
|
||||
--disable-guest-agent) guest_agent="no"
|
||||
@@ -1190,6 +1200,7 @@ Advanced options (experts only):
|
||||
--disable-werror disable compilation abort on warning
|
||||
--disable-sdl disable SDL
|
||||
--enable-sdl enable SDL
|
||||
--with-sdlabi select preferred SDL ABI 1.2 or 2.0
|
||||
--disable-gtk disable gtk UI
|
||||
--enable-gtk enable gtk UI
|
||||
--disable-virtfs disable VirtFS
|
||||
@@ -1289,6 +1300,8 @@ Advanced options (experts only):
|
||||
--enable-libusb enable libusb (for usb passthrough)
|
||||
--disable-usb-redir disable usb network redirection support
|
||||
--enable-usb-redir enable usb network redirection support
|
||||
--enable-lzo enable the support of lzo compression library
|
||||
--enable-snappy enable the support of snappy compression library
|
||||
--disable-guest-agent disable building of the QEMU Guest Agent
|
||||
--enable-guest-agent enable building of the QEMU Guest Agent
|
||||
--with-vss-sdk=SDK-path enable Windows VSS support in QEMU Guest Agent
|
||||
@@ -1657,7 +1670,43 @@ EOF
|
||||
"Make sure to have the zlib libs and headers installed."
|
||||
fi
|
||||
fi
|
||||
libs_softmmu="$libs_softmmu -lz"
|
||||
LIBS="$LIBS -lz"
|
||||
|
||||
##########################################
|
||||
# lzo check
|
||||
|
||||
if test "$lzo" != "no" ; then
|
||||
cat > $TMPC << EOF
|
||||
#include <lzo/lzo1x.h>
|
||||
int main(void) { lzo_version(); return 0; }
|
||||
EOF
|
||||
if compile_prog "" "-llzo2" ; then
|
||||
:
|
||||
else
|
||||
error_exit "lzo check failed" \
|
||||
"Make sure to have the lzo libs and headers installed."
|
||||
fi
|
||||
|
||||
libs_softmmu="$libs_softmmu -llzo2"
|
||||
fi
|
||||
|
||||
##########################################
|
||||
# snappy check
|
||||
|
||||
if test "$snappy" != "no" ; then
|
||||
cat > $TMPC << EOF
|
||||
#include <snappy-c.h>
|
||||
int main(void) { snappy_max_compressed_length(4096); return 0; }
|
||||
EOF
|
||||
if compile_prog "" "-lsnappy" ; then
|
||||
:
|
||||
else
|
||||
error_exit "snappy check failed" \
|
||||
"Make sure to have the snappy libs and headers installed."
|
||||
fi
|
||||
|
||||
libs_softmmu="$libs_softmmu -lsnappy"
|
||||
fi
|
||||
|
||||
##########################################
|
||||
# libseccomp check
|
||||
@@ -1911,12 +1960,22 @@ fi
|
||||
|
||||
# Look for sdl configuration program (pkg-config or sdl-config). Try
|
||||
# sdl-config even without cross prefix, and favour pkg-config over sdl-config.
|
||||
if test "`basename $sdl_config`" != sdl-config && ! has ${sdl_config}; then
|
||||
sdl_config=sdl-config
|
||||
|
||||
if test $sdlabi = "2.0"; then
|
||||
sdl_config=$sdl2_config
|
||||
sdlname=sdl2
|
||||
sdlconfigname=sdl2_config
|
||||
else
|
||||
sdlname=sdl
|
||||
sdlconfigname=sdl_config
|
||||
fi
|
||||
|
||||
if $pkg_config sdl --exists; then
|
||||
sdlconfig="$pkg_config sdl"
|
||||
if test "`basename $sdl_config`" != $sdlconfigname && ! has ${sdl_config}; then
|
||||
sdl_config=$sdlconfigname
|
||||
fi
|
||||
|
||||
if $pkg_config $sdlname --exists; then
|
||||
sdlconfig="$pkg_config $sdlname"
|
||||
_sdlversion=`$sdlconfig --modversion 2>/dev/null | sed 's/[^0-9]//g'`
|
||||
elif has ${sdl_config}; then
|
||||
sdlconfig="$sdl_config"
|
||||
@@ -2249,13 +2308,21 @@ EOF
|
||||
fi
|
||||
|
||||
##########################################
|
||||
# netmap headers probe
|
||||
# netmap support probe
|
||||
# Apart from looking for netmap headers, we make sure that the host API version
|
||||
# supports the netmap backend (>=11). The upper bound (15) is meant to simulate
|
||||
# a minor/major version number. Minor new features will be marked with values up
|
||||
# to 15, and if something happens that requires a change to the backend we will
|
||||
# move above 15, submit the backend fixes and modify this two bounds.
|
||||
if test "$netmap" != "no" ; then
|
||||
cat > $TMPC << EOF
|
||||
#include <inttypes.h>
|
||||
#include <net/if.h>
|
||||
#include <net/netmap.h>
|
||||
#include <net/netmap_user.h>
|
||||
#if (NETMAP_API < 11) || (NETMAP_API > 15)
|
||||
#error
|
||||
#endif
|
||||
int main(void) { return 0; }
|
||||
EOF
|
||||
if compile_prog "" "" ; then
|
||||
@@ -4037,6 +4104,8 @@ echo "TPM passthrough $tpm_passthrough"
|
||||
echo "QOM debugging $qom_cast_debug"
|
||||
echo "vhdx $vhdx"
|
||||
echo "Quorum $quorum"
|
||||
echo "lzo support $lzo"
|
||||
echo "snappy support $snappy"
|
||||
|
||||
if test "$sdl_too_old" = "yes"; then
|
||||
echo "-> Your SDL version is too old - please upgrade to have SDL support"
|
||||
@@ -4360,6 +4429,14 @@ if test "$glx" = "yes" ; then
|
||||
echo "GLX_LIBS=$glx_libs" >> $config_host_mak
|
||||
fi
|
||||
|
||||
if test "$lzo" = "yes" ; then
|
||||
echo "CONFIG_LZO=y" >> $config_host_mak
|
||||
fi
|
||||
|
||||
if test "$snappy" = "yes" ; then
|
||||
echo "CONFIG_SNAPPY=y" >> $config_host_mak
|
||||
fi
|
||||
|
||||
if test "$libiscsi" = "yes" ; then
|
||||
echo "CONFIG_LIBISCSI=m" >> $config_host_mak
|
||||
if test "$libiscsi_version" = "1.4.0"; then
|
||||
|
||||
@@ -477,7 +477,7 @@ int cpu_exec(CPUArchState *env)
|
||||
}
|
||||
#elif defined(TARGET_ARM)
|
||||
if (interrupt_request & CPU_INTERRUPT_FIQ
|
||||
&& !(env->uncached_cpsr & CPSR_F)) {
|
||||
&& !(env->daif & PSTATE_F)) {
|
||||
env->exception_index = EXCP_FIQ;
|
||||
cc->do_interrupt(cpu);
|
||||
next_tb = 0;
|
||||
@@ -493,7 +493,7 @@ int cpu_exec(CPUArchState *env)
|
||||
pc contains a magic address. */
|
||||
if (interrupt_request & CPU_INTERRUPT_HARD
|
||||
&& ((IS_M(env) && env->regs[15] < 0xfffffff0)
|
||||
|| !(env->uncached_cpsr & CPSR_I))) {
|
||||
|| !(env->daif & PSTATE_I))) {
|
||||
env->exception_index = EXCP_IRQ;
|
||||
cc->do_interrupt(cpu);
|
||||
next_tb = 0;
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
CONFIG_VIRTIO=y
|
||||
CONFIG_SCLPCONSOLE=y
|
||||
CONFIG_S390_FLIC=$(CONFIG_KVM)
|
||||
|
||||
@@ -10,6 +10,7 @@ CONFIG_EMPTY_SLOT=y
|
||||
CONFIG_PCNET_COMMON=y
|
||||
CONFIG_LANCE=y
|
||||
CONFIG_TCX=y
|
||||
CONFIG_CG3=y
|
||||
CONFIG_SLAVIO=y
|
||||
CONFIG_CS4231=y
|
||||
CONFIG_GRLIB=y
|
||||
|
||||
@@ -225,6 +225,45 @@ Data:
|
||||
"timestamp": { "seconds": 1368697518, "microseconds": 326866 } }
|
||||
}
|
||||
|
||||
QUORUM_FAILURE
|
||||
--------------
|
||||
|
||||
Emitted by the Quorum block driver if it fails to establish a quorum.
|
||||
|
||||
Data:
|
||||
|
||||
- "reference": device name if defined else node name.
|
||||
- "sector-num": Number of the first sector of the failed read operation.
|
||||
- "sector-count": Failed read operation sector count.
|
||||
|
||||
Example:
|
||||
|
||||
{ "event": "QUORUM_FAILURE",
|
||||
"data": { "reference": "usr1", "sector-num": 345435, "sector-count": 5 },
|
||||
"timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
|
||||
|
||||
QUORUM_REPORT_BAD
|
||||
-----------------
|
||||
|
||||
Emitted to report a corruption of a Quorum file.
|
||||
|
||||
Data:
|
||||
|
||||
- "error": Error message (json-string, optional)
|
||||
Only present on failure. This field contains a human-readable
|
||||
error message. There are no semantics other than that the
|
||||
block layer reported an error and clients should not try to
|
||||
interpret the error string.
|
||||
- "node-name": The graph node name of the block driver state.
|
||||
- "sector-num": Number of the first sector of the failed read operation.
|
||||
- "sector-count": Failed read operation sector count.
|
||||
|
||||
Example:
|
||||
|
||||
{ "event": "QUORUM_REPORT_BAD",
|
||||
"data": { "node-name": "1.raw", "sector-num": 345435, "sector-count": 5 },
|
||||
"timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
|
||||
|
||||
RESET
|
||||
-----
|
||||
|
||||
@@ -500,39 +539,3 @@ Example:
|
||||
|
||||
Note: If action is "reset", "shutdown", or "pause" the WATCHDOG event is
|
||||
followed respectively by the RESET, SHUTDOWN, or STOP events.
|
||||
|
||||
QUORUM_FAILURE
|
||||
--------------
|
||||
|
||||
Emitted by the Quorum block driver if it fails to establish a quorum.
|
||||
|
||||
Data:
|
||||
|
||||
- "reference": device name if defined else node name.
|
||||
- "sector-num": Number of the first sector of the failed read operation.
|
||||
- "sector-count": Failed read operation sector count.
|
||||
|
||||
Example:
|
||||
|
||||
{ "event": "QUORUM_FAILURE",
|
||||
"data": { "reference": "usr1", "sector-num": 345435, "sector-count": 5 },
|
||||
"timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
|
||||
|
||||
QUORUM_REPORT_BAD
|
||||
-----------------
|
||||
|
||||
Emitted to report a corruption of a Quorum file.
|
||||
|
||||
Data:
|
||||
|
||||
- "ret": The IO return code.
|
||||
- "node-name": The graph node name of the block driver state.
|
||||
- "sector-num": Number of the first sector of the failed read operation.
|
||||
- "sector-count": Failed read operation sector count.
|
||||
|
||||
Example:
|
||||
|
||||
{ "event": "QUORUM_REPORT_BAD",
|
||||
"data": { "ret": 0, "node-name": "1.raw", "sector-num": 345435,
|
||||
"sector-count": 5 },
|
||||
"timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
|
||||
|
||||
@@ -66,7 +66,7 @@ bulk-phase round of the migration and can be enabled for extremely
|
||||
high-performance RDMA hardware using the following command:
|
||||
|
||||
QEMU Monitor Command:
|
||||
$ migrate_set_capability x-rdma-pin-all on # disabled by default
|
||||
$ migrate_set_capability rdma-pin-all on # disabled by default
|
||||
|
||||
Performing this action will cause all 8GB to be pinned, so if that's
|
||||
not what you want, then please ignore this step altogether.
|
||||
@@ -93,12 +93,12 @@ $ migrate_set_speed 40g # or whatever is the MAX of your RDMA device
|
||||
|
||||
Next, on the destination machine, add the following to the QEMU command line:
|
||||
|
||||
qemu ..... -incoming x-rdma:host:port
|
||||
qemu ..... -incoming rdma:host:port
|
||||
|
||||
Finally, perform the actual migration on the source machine:
|
||||
|
||||
QEMU Monitor Command:
|
||||
$ migrate -d x-rdma:host:port
|
||||
$ migrate -d rdma:host:port
|
||||
|
||||
PERFORMANCE
|
||||
===========
|
||||
@@ -120,8 +120,8 @@ For example, in the same 8GB RAM example with all 8GB of memory in
|
||||
active use and the VM itself is completely idle using the same 40 gbps
|
||||
infiniband link:
|
||||
|
||||
1. x-rdma-pin-all disabled total time: approximately 7.5 seconds @ 9.5 Gbps
|
||||
2. x-rdma-pin-all enabled total time: approximately 4 seconds @ 26 Gbps
|
||||
1. rdma-pin-all disabled total time: approximately 7.5 seconds @ 9.5 Gbps
|
||||
2. rdma-pin-all enabled total time: approximately 4 seconds @ 26 Gbps
|
||||
|
||||
These numbers would of course scale up to whatever size virtual machine
|
||||
you have to migrate using RDMA.
|
||||
@@ -407,18 +407,14 @@ socket is broken during a non-RDMA based migration.
|
||||
|
||||
TODO:
|
||||
=====
|
||||
1. 'migrate x-rdma:host:port' and '-incoming x-rdma' options will be
|
||||
renamed to 'rdma' after the experimental phase of this work has
|
||||
completed upstream.
|
||||
2. Currently, 'ulimit -l' mlock() limits as well as cgroups swap limits
|
||||
1. Currently, 'ulimit -l' mlock() limits as well as cgroups swap limits
|
||||
are not compatible with infinband memory pinning and will result in
|
||||
an aborted migration (but with the source VM left unaffected).
|
||||
3. Use of the recent /proc/<pid>/pagemap would likely speed up
|
||||
2. Use of the recent /proc/<pid>/pagemap would likely speed up
|
||||
the use of KSM and ballooning while using RDMA.
|
||||
4. Also, some form of balloon-device usage tracking would also
|
||||
3. Also, some form of balloon-device usage tracking would also
|
||||
help alleviate some issues.
|
||||
5. Move UNREGISTER requests to a separate thread.
|
||||
6. Use LRU to provide more fine-grained direction of UNREGISTER
|
||||
4. Use LRU to provide more fine-grained direction of UNREGISTER
|
||||
requests for unpinning memory in an overcommitted environment.
|
||||
7. Expose UNREGISTER support to the user by way of workload-specific
|
||||
5. Expose UNREGISTER support to the user by way of workload-specific
|
||||
hints about application behavior.
|
||||
|
||||
4
exec.c
4
exec.c
@@ -17,9 +17,7 @@
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "config.h"
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#ifndef _WIN32
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
5
hmp.c
5
hmp.c
@@ -1311,8 +1311,11 @@ void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict)
|
||||
const char *file = qdict_get_str(qdict, "filename");
|
||||
bool has_begin = qdict_haskey(qdict, "begin");
|
||||
bool has_length = qdict_haskey(qdict, "length");
|
||||
/* kdump-compressed format is not supported for HMP */
|
||||
bool has_format = false;
|
||||
int64_t begin = 0;
|
||||
int64_t length = 0;
|
||||
enum DumpGuestMemoryFormat dump_format = DUMP_GUEST_MEMORY_FORMAT_ELF;
|
||||
char *prot;
|
||||
|
||||
if (has_begin) {
|
||||
@@ -1325,7 +1328,7 @@ void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict)
|
||||
prot = g_strconcat("file:", file, NULL);
|
||||
|
||||
qmp_dump_guest_memory(paging, prot, has_begin, begin, has_length, length,
|
||||
&errp);
|
||||
has_format, dump_format, &errp);
|
||||
hmp_handle_error(mon, &errp);
|
||||
g_free(prot);
|
||||
}
|
||||
|
||||
@@ -92,8 +92,6 @@
|
||||
#define MP_ETH_CRDP3 0x4AC
|
||||
#define MP_ETH_CTDP0 0x4E0
|
||||
#define MP_ETH_CTDP1 0x4E4
|
||||
#define MP_ETH_CTDP2 0x4E8
|
||||
#define MP_ETH_CTDP3 0x4EC
|
||||
|
||||
/* MII PHY access */
|
||||
#define MP_ETH_SMIR_DATA 0x0000FFFF
|
||||
@@ -308,7 +306,7 @@ static uint64_t mv88w8618_eth_read(void *opaque, hwaddr offset,
|
||||
case MP_ETH_CRDP0 ... MP_ETH_CRDP3:
|
||||
return s->rx_queue[(offset - MP_ETH_CRDP0)/4];
|
||||
|
||||
case MP_ETH_CTDP0 ... MP_ETH_CTDP3:
|
||||
case MP_ETH_CTDP0 ... MP_ETH_CTDP1:
|
||||
return s->tx_queue[(offset - MP_ETH_CTDP0)/4];
|
||||
|
||||
default:
|
||||
@@ -362,7 +360,7 @@ static void mv88w8618_eth_write(void *opaque, hwaddr offset,
|
||||
s->cur_rx[(offset - MP_ETH_CRDP0)/4] = value;
|
||||
break;
|
||||
|
||||
case MP_ETH_CTDP0 ... MP_ETH_CTDP3:
|
||||
case MP_ETH_CTDP0 ... MP_ETH_CTDP1:
|
||||
s->tx_queue[(offset - MP_ETH_CTDP0)/4] = value;
|
||||
break;
|
||||
}
|
||||
@@ -632,7 +630,7 @@ static int musicpal_lcd_init(SysBusDevice *sbd)
|
||||
"musicpal-lcd", MP_LCD_SIZE);
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
|
||||
s->con = graphic_console_init(dev, &musicpal_gfx_ops, s);
|
||||
s->con = graphic_console_init(dev, 0, &musicpal_gfx_ops, s);
|
||||
qemu_console_resize(s->con, 128*3, 64*3);
|
||||
|
||||
qdev_init_gpio_in(dev, musicpal_lcd_gpio_brightness_in, 3);
|
||||
|
||||
@@ -272,11 +272,11 @@ static void pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||
goto message;
|
||||
|
||||
case 3:
|
||||
s->cpu->env.uncached_cpsr =
|
||||
ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
|
||||
s->cpu->env.uncached_cpsr = ARM_CPU_MODE_SVC;
|
||||
s->cpu->env.daif = PSTATE_A | PSTATE_F | PSTATE_I;
|
||||
s->cpu->env.cp15.c1_sys = 0;
|
||||
s->cpu->env.cp15.c1_coproc = 0;
|
||||
s->cpu->env.cp15.c2_base0 = 0;
|
||||
s->cpu->env.cp15.ttbr0_el1 = 0;
|
||||
s->cpu->env.cp15.c3 = 0;
|
||||
s->pm_regs[PSSR >> 2] |= 0x8; /* Set STS */
|
||||
s->pm_regs[RCSR >> 2] |= 0x8; /* Set GPR */
|
||||
|
||||
@@ -157,6 +157,9 @@ struct HDAAudioStream {
|
||||
uint32_t bpos;
|
||||
};
|
||||
|
||||
#define TYPE_HDA_AUDIO "hda-audio"
|
||||
#define HDA_AUDIO(obj) OBJECT_CHECK(HDAAudioState, (obj), TYPE_HDA_AUDIO)
|
||||
|
||||
struct HDAAudioState {
|
||||
HDACodecDevice hda;
|
||||
const char *name;
|
||||
@@ -288,7 +291,7 @@ static void hda_audio_setup(HDAAudioStream *st)
|
||||
|
||||
static void hda_audio_command(HDACodecDevice *hda, uint32_t nid, uint32_t data)
|
||||
{
|
||||
HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
|
||||
HDAAudioState *a = HDA_AUDIO(hda);
|
||||
HDAAudioStream *st;
|
||||
const desc_node *node = NULL;
|
||||
const desc_param *param;
|
||||
@@ -448,7 +451,7 @@ fail:
|
||||
|
||||
static void hda_audio_stream(HDACodecDevice *hda, uint32_t stnr, bool running, bool output)
|
||||
{
|
||||
HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
|
||||
HDAAudioState *a = HDA_AUDIO(hda);
|
||||
int s;
|
||||
|
||||
a->running_compat[stnr] = running;
|
||||
@@ -469,7 +472,7 @@ static void hda_audio_stream(HDACodecDevice *hda, uint32_t stnr, bool running, b
|
||||
|
||||
static int hda_audio_init(HDACodecDevice *hda, const struct desc_codec *desc)
|
||||
{
|
||||
HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
|
||||
HDAAudioState *a = HDA_AUDIO(hda);
|
||||
HDAAudioStream *st;
|
||||
const desc_node *node;
|
||||
const desc_param *param;
|
||||
@@ -514,7 +517,7 @@ static int hda_audio_init(HDACodecDevice *hda, const struct desc_codec *desc)
|
||||
|
||||
static int hda_audio_exit(HDACodecDevice *hda)
|
||||
{
|
||||
HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
|
||||
HDAAudioState *a = HDA_AUDIO(hda);
|
||||
HDAAudioStream *st;
|
||||
int i;
|
||||
|
||||
@@ -561,7 +564,7 @@ static int hda_audio_post_load(void *opaque, int version)
|
||||
|
||||
static void hda_audio_reset(DeviceState *dev)
|
||||
{
|
||||
HDAAudioState *a = DO_UPCAST(HDAAudioState, hda.qdev, dev);
|
||||
HDAAudioState *a = HDA_AUDIO(dev);
|
||||
HDAAudioStream *st;
|
||||
int i;
|
||||
|
||||
@@ -613,7 +616,7 @@ static Property hda_audio_properties[] = {
|
||||
|
||||
static int hda_audio_init_output(HDACodecDevice *hda)
|
||||
{
|
||||
HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
|
||||
HDAAudioState *a = HDA_AUDIO(hda);
|
||||
|
||||
if (!a->mixer) {
|
||||
return hda_audio_init(hda, &output_nomixemu);
|
||||
@@ -624,7 +627,7 @@ static int hda_audio_init_output(HDACodecDevice *hda)
|
||||
|
||||
static int hda_audio_init_duplex(HDACodecDevice *hda)
|
||||
{
|
||||
HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
|
||||
HDAAudioState *a = HDA_AUDIO(hda);
|
||||
|
||||
if (!a->mixer) {
|
||||
return hda_audio_init(hda, &duplex_nomixemu);
|
||||
@@ -635,7 +638,7 @@ static int hda_audio_init_duplex(HDACodecDevice *hda)
|
||||
|
||||
static int hda_audio_init_micro(HDACodecDevice *hda)
|
||||
{
|
||||
HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
|
||||
HDAAudioState *a = HDA_AUDIO(hda);
|
||||
|
||||
if (!a->mixer) {
|
||||
return hda_audio_init(hda, µ_nomixemu);
|
||||
@@ -644,25 +647,39 @@ static int hda_audio_init_micro(HDACodecDevice *hda)
|
||||
}
|
||||
}
|
||||
|
||||
static void hda_audio_base_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
HDACodecDeviceClass *k = HDA_CODEC_DEVICE_CLASS(klass);
|
||||
|
||||
k->exit = hda_audio_exit;
|
||||
k->command = hda_audio_command;
|
||||
k->stream = hda_audio_stream;
|
||||
set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
|
||||
dc->reset = hda_audio_reset;
|
||||
dc->vmsd = &vmstate_hda_audio;
|
||||
dc->props = hda_audio_properties;
|
||||
}
|
||||
|
||||
static const TypeInfo hda_audio_info = {
|
||||
.name = TYPE_HDA_AUDIO,
|
||||
.parent = TYPE_HDA_CODEC_DEVICE,
|
||||
.class_init = hda_audio_base_class_init,
|
||||
.abstract = true,
|
||||
};
|
||||
|
||||
static void hda_audio_output_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
HDACodecDeviceClass *k = HDA_CODEC_DEVICE_CLASS(klass);
|
||||
|
||||
k->init = hda_audio_init_output;
|
||||
k->exit = hda_audio_exit;
|
||||
k->command = hda_audio_command;
|
||||
k->stream = hda_audio_stream;
|
||||
set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
|
||||
dc->desc = "HDA Audio Codec, output-only (line-out)";
|
||||
dc->reset = hda_audio_reset;
|
||||
dc->vmsd = &vmstate_hda_audio;
|
||||
dc->props = hda_audio_properties;
|
||||
}
|
||||
|
||||
static const TypeInfo hda_audio_output_info = {
|
||||
.name = "hda-output",
|
||||
.parent = TYPE_HDA_CODEC_DEVICE,
|
||||
.parent = TYPE_HDA_AUDIO,
|
||||
.instance_size = sizeof(HDAAudioState),
|
||||
.class_init = hda_audio_output_class_init,
|
||||
};
|
||||
@@ -673,19 +690,12 @@ static void hda_audio_duplex_class_init(ObjectClass *klass, void *data)
|
||||
HDACodecDeviceClass *k = HDA_CODEC_DEVICE_CLASS(klass);
|
||||
|
||||
k->init = hda_audio_init_duplex;
|
||||
k->exit = hda_audio_exit;
|
||||
k->command = hda_audio_command;
|
||||
k->stream = hda_audio_stream;
|
||||
set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
|
||||
dc->desc = "HDA Audio Codec, duplex (line-out, line-in)";
|
||||
dc->reset = hda_audio_reset;
|
||||
dc->vmsd = &vmstate_hda_audio;
|
||||
dc->props = hda_audio_properties;
|
||||
}
|
||||
|
||||
static const TypeInfo hda_audio_duplex_info = {
|
||||
.name = "hda-duplex",
|
||||
.parent = TYPE_HDA_CODEC_DEVICE,
|
||||
.parent = TYPE_HDA_AUDIO,
|
||||
.instance_size = sizeof(HDAAudioState),
|
||||
.class_init = hda_audio_duplex_class_init,
|
||||
};
|
||||
@@ -696,25 +706,19 @@ static void hda_audio_micro_class_init(ObjectClass *klass, void *data)
|
||||
HDACodecDeviceClass *k = HDA_CODEC_DEVICE_CLASS(klass);
|
||||
|
||||
k->init = hda_audio_init_micro;
|
||||
k->exit = hda_audio_exit;
|
||||
k->command = hda_audio_command;
|
||||
k->stream = hda_audio_stream;
|
||||
set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
|
||||
dc->desc = "HDA Audio Codec, duplex (speaker, microphone)";
|
||||
dc->reset = hda_audio_reset;
|
||||
dc->vmsd = &vmstate_hda_audio;
|
||||
dc->props = hda_audio_properties;
|
||||
}
|
||||
|
||||
static const TypeInfo hda_audio_micro_info = {
|
||||
.name = "hda-micro",
|
||||
.parent = TYPE_HDA_CODEC_DEVICE,
|
||||
.parent = TYPE_HDA_AUDIO,
|
||||
.instance_size = sizeof(HDAAudioState),
|
||||
.class_init = hda_audio_micro_class_init,
|
||||
};
|
||||
|
||||
static void hda_audio_register_types(void)
|
||||
{
|
||||
type_register_static(&hda_audio_info);
|
||||
type_register_static(&hda_audio_output_info);
|
||||
type_register_static(&hda_audio_duplex_info);
|
||||
type_register_static(&hda_audio_micro_info);
|
||||
|
||||
@@ -28,6 +28,7 @@ obj-$(CONFIG_OMAP) += omap_lcdc.o
|
||||
obj-$(CONFIG_PXA2XX) += pxa2xx_lcd.o
|
||||
obj-$(CONFIG_SM501) += sm501.o
|
||||
obj-$(CONFIG_TCX) += tcx.o
|
||||
obj-$(CONFIG_CG3) += cg3.o
|
||||
|
||||
obj-$(CONFIG_VGA) += vga.o
|
||||
|
||||
|
||||
@@ -956,7 +956,7 @@ void *s1d13745_init(qemu_irq gpio_int)
|
||||
|
||||
s->fb = g_malloc(0x180000);
|
||||
|
||||
s->con = graphic_console_init(NULL, &blizzard_ops, s);
|
||||
s->con = graphic_console_init(NULL, 0, &blizzard_ops, s);
|
||||
surface = qemu_console_surface(s->con);
|
||||
|
||||
switch (surface_bits_per_pixel(surface)) {
|
||||
|
||||
385
hw/display/cg3.c
Normal file
385
hw/display/cg3.c
Normal file
@@ -0,0 +1,385 @@
|
||||
/*
|
||||
* QEMU CG3 Frame buffer
|
||||
*
|
||||
* Copyright (c) 2012 Bob Breuer
|
||||
* Copyright (c) 2013 Mark Cave-Ayland
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "ui/console.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/loader.h"
|
||||
|
||||
/* Change to 1 to enable debugging */
|
||||
#define DEBUG_CG3 0
|
||||
|
||||
#define CG3_ROM_FILE "QEMU,cgthree.bin"
|
||||
#define FCODE_MAX_ROM_SIZE 0x10000
|
||||
|
||||
#define CG3_REG_SIZE 0x20
|
||||
|
||||
#define CG3_REG_BT458_ADDR 0x0
|
||||
#define CG3_REG_BT458_COLMAP 0x4
|
||||
#define CG3_REG_FBC_CTRL 0x10
|
||||
#define CG3_REG_FBC_STATUS 0x11
|
||||
#define CG3_REG_FBC_CURSTART 0x12
|
||||
#define CG3_REG_FBC_CUREND 0x13
|
||||
#define CG3_REG_FBC_VCTRL 0x14
|
||||
|
||||
/* Control register flags */
|
||||
#define CG3_CR_ENABLE_INTS 0x80
|
||||
|
||||
/* Status register flags */
|
||||
#define CG3_SR_PENDING_INT 0x80
|
||||
#define CG3_SR_1152_900_76_B 0x60
|
||||
#define CG3_SR_ID_COLOR 0x01
|
||||
|
||||
#define CG3_VRAM_SIZE 0x100000
|
||||
#define CG3_VRAM_OFFSET 0x800000
|
||||
|
||||
#define DPRINTF(fmt, ...) do { \
|
||||
if (DEBUG_CG3) { \
|
||||
printf("CG3: " fmt , ## __VA_ARGS__); \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define TYPE_CG3 "cgthree"
|
||||
#define CG3(obj) OBJECT_CHECK(CG3State, (obj), TYPE_CG3)
|
||||
|
||||
typedef struct CG3State {
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
QemuConsole *con;
|
||||
qemu_irq irq;
|
||||
hwaddr prom_addr;
|
||||
MemoryRegion vram_mem;
|
||||
MemoryRegion rom;
|
||||
MemoryRegion reg;
|
||||
uint32_t vram_size;
|
||||
int full_update;
|
||||
uint8_t regs[16];
|
||||
uint8_t r[256], g[256], b[256];
|
||||
uint16_t width, height, depth;
|
||||
uint8_t dac_index, dac_state;
|
||||
} CG3State;
|
||||
|
||||
static void cg3_update_display(void *opaque)
|
||||
{
|
||||
CG3State *s = opaque;
|
||||
DisplaySurface *surface = qemu_console_surface(s->con);
|
||||
const uint8_t *pix;
|
||||
uint32_t *data;
|
||||
uint32_t dval;
|
||||
int x, y, y_start;
|
||||
unsigned int width, height;
|
||||
ram_addr_t page, page_min, page_max;
|
||||
|
||||
if (surface_bits_per_pixel(surface) != 32) {
|
||||
return;
|
||||
}
|
||||
width = s->width;
|
||||
height = s->height;
|
||||
|
||||
y_start = -1;
|
||||
page_min = -1;
|
||||
page_max = 0;
|
||||
page = 0;
|
||||
pix = memory_region_get_ram_ptr(&s->vram_mem);
|
||||
data = (uint32_t *)surface_data(surface);
|
||||
|
||||
for (y = 0; y < height; y++) {
|
||||
int update = s->full_update;
|
||||
|
||||
page = (y * width) & TARGET_PAGE_MASK;
|
||||
update |= memory_region_get_dirty(&s->vram_mem, page, page + width,
|
||||
DIRTY_MEMORY_VGA);
|
||||
if (update) {
|
||||
if (y_start < 0) {
|
||||
y_start = y;
|
||||
}
|
||||
if (page < page_min) {
|
||||
page_min = page;
|
||||
}
|
||||
if (page > page_max) {
|
||||
page_max = page;
|
||||
}
|
||||
|
||||
for (x = 0; x < width; x++) {
|
||||
dval = *pix++;
|
||||
dval = (s->r[dval] << 16) | (s->g[dval] << 8) | s->b[dval];
|
||||
*data++ = dval;
|
||||
}
|
||||
} else {
|
||||
if (y_start >= 0) {
|
||||
dpy_gfx_update(s->con, 0, y_start, s->width, y - y_start);
|
||||
y_start = -1;
|
||||
}
|
||||
pix += width;
|
||||
data += width;
|
||||
}
|
||||
}
|
||||
s->full_update = 0;
|
||||
if (y_start >= 0) {
|
||||
dpy_gfx_update(s->con, 0, y_start, s->width, y - y_start);
|
||||
}
|
||||
if (page_max >= page_min) {
|
||||
memory_region_reset_dirty(&s->vram_mem,
|
||||
page_min, page_max - page_min + TARGET_PAGE_SIZE,
|
||||
DIRTY_MEMORY_VGA);
|
||||
}
|
||||
/* vsync interrupt? */
|
||||
if (s->regs[0] & CG3_CR_ENABLE_INTS) {
|
||||
s->regs[1] |= CG3_SR_PENDING_INT;
|
||||
qemu_irq_raise(s->irq);
|
||||
}
|
||||
}
|
||||
|
||||
static void cg3_invalidate_display(void *opaque)
|
||||
{
|
||||
CG3State *s = opaque;
|
||||
|
||||
memory_region_set_dirty(&s->vram_mem, 0, CG3_VRAM_SIZE);
|
||||
}
|
||||
|
||||
static uint64_t cg3_reg_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
CG3State *s = opaque;
|
||||
int val;
|
||||
|
||||
switch (addr) {
|
||||
case CG3_REG_BT458_ADDR:
|
||||
case CG3_REG_BT458_COLMAP:
|
||||
val = 0;
|
||||
break;
|
||||
case CG3_REG_FBC_CTRL:
|
||||
val = s->regs[0];
|
||||
break;
|
||||
case CG3_REG_FBC_STATUS:
|
||||
/* monitor ID 6, board type = 1 (color) */
|
||||
val = s->regs[1] | CG3_SR_1152_900_76_B | CG3_SR_ID_COLOR;
|
||||
break;
|
||||
case CG3_REG_FBC_CURSTART ... CG3_REG_SIZE:
|
||||
val = s->regs[addr - 0x10];
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_UNIMP,
|
||||
"cg3: Unimplemented register read "
|
||||
"reg 0x%" HWADDR_PRIx " size 0x%x\n",
|
||||
addr, size);
|
||||
val = 0;
|
||||
break;
|
||||
}
|
||||
DPRINTF("read %02x from reg %" HWADDR_PRIx "\n", val, addr);
|
||||
return val;
|
||||
}
|
||||
|
||||
static void cg3_reg_write(void *opaque, hwaddr addr, uint64_t val,
|
||||
unsigned size)
|
||||
{
|
||||
CG3State *s = opaque;
|
||||
uint8_t regval;
|
||||
int i;
|
||||
|
||||
DPRINTF("write %" PRIx64 " to reg %" HWADDR_PRIx " size %d\n",
|
||||
val, addr, size);
|
||||
|
||||
switch (addr) {
|
||||
case CG3_REG_BT458_ADDR:
|
||||
s->dac_index = val;
|
||||
s->dac_state = 0;
|
||||
break;
|
||||
case CG3_REG_BT458_COLMAP:
|
||||
/* This register can be written to as either a long word or a byte */
|
||||
if (size == 1) {
|
||||
val <<= 24;
|
||||
}
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
regval = val >> 24;
|
||||
|
||||
switch (s->dac_state) {
|
||||
case 0:
|
||||
s->r[s->dac_index] = regval;
|
||||
s->dac_state++;
|
||||
break;
|
||||
case 1:
|
||||
s->g[s->dac_index] = regval;
|
||||
s->dac_state++;
|
||||
break;
|
||||
case 2:
|
||||
s->b[s->dac_index] = regval;
|
||||
/* Index autoincrement */
|
||||
s->dac_index = (s->dac_index + 1) & 0xff;
|
||||
default:
|
||||
s->dac_state = 0;
|
||||
break;
|
||||
}
|
||||
val <<= 8;
|
||||
}
|
||||
s->full_update = 1;
|
||||
break;
|
||||
case CG3_REG_FBC_CTRL:
|
||||
s->regs[0] = val;
|
||||
break;
|
||||
case CG3_REG_FBC_STATUS:
|
||||
if (s->regs[1] & CG3_SR_PENDING_INT) {
|
||||
/* clear interrupt */
|
||||
s->regs[1] &= ~CG3_SR_PENDING_INT;
|
||||
qemu_irq_lower(s->irq);
|
||||
}
|
||||
break;
|
||||
case CG3_REG_FBC_CURSTART ... CG3_REG_SIZE:
|
||||
s->regs[addr - 0x10] = val;
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_UNIMP,
|
||||
"cg3: Unimplemented register write "
|
||||
"reg 0x%" HWADDR_PRIx " size 0x%x value 0x%" PRIx64 "\n",
|
||||
addr, size, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const MemoryRegionOps cg3_reg_ops = {
|
||||
.read = cg3_reg_read,
|
||||
.write = cg3_reg_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
.valid = {
|
||||
.min_access_size = 1,
|
||||
.max_access_size = 4,
|
||||
},
|
||||
};
|
||||
|
||||
static const GraphicHwOps cg3_ops = {
|
||||
.invalidate = cg3_invalidate_display,
|
||||
.gfx_update = cg3_update_display,
|
||||
};
|
||||
|
||||
static void cg3_realizefn(DeviceState *dev, Error **errp)
|
||||
{
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
CG3State *s = CG3(dev);
|
||||
int ret;
|
||||
char *fcode_filename;
|
||||
|
||||
/* FCode ROM */
|
||||
memory_region_init_ram(&s->rom, NULL, "cg3.prom", FCODE_MAX_ROM_SIZE);
|
||||
vmstate_register_ram_global(&s->rom);
|
||||
memory_region_set_readonly(&s->rom, true);
|
||||
sysbus_init_mmio(sbd, &s->rom);
|
||||
|
||||
fcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, CG3_ROM_FILE);
|
||||
if (fcode_filename) {
|
||||
ret = load_image_targphys(fcode_filename, s->prom_addr,
|
||||
FCODE_MAX_ROM_SIZE);
|
||||
if (ret < 0 || ret > FCODE_MAX_ROM_SIZE) {
|
||||
error_report("cg3: could not load prom '%s'", CG3_ROM_FILE);
|
||||
}
|
||||
}
|
||||
|
||||
memory_region_init_io(&s->reg, NULL, &cg3_reg_ops, s, "cg3.reg",
|
||||
CG3_REG_SIZE);
|
||||
sysbus_init_mmio(sbd, &s->reg);
|
||||
|
||||
memory_region_init_ram(&s->vram_mem, NULL, "cg3.vram", s->vram_size);
|
||||
vmstate_register_ram_global(&s->vram_mem);
|
||||
sysbus_init_mmio(sbd, &s->vram_mem);
|
||||
|
||||
sysbus_init_irq(sbd, &s->irq);
|
||||
|
||||
s->con = graphic_console_init(DEVICE(dev), 0, &cg3_ops, s);
|
||||
qemu_console_resize(s->con, s->width, s->height);
|
||||
}
|
||||
|
||||
static int vmstate_cg3_post_load(void *opaque, int version_id)
|
||||
{
|
||||
CG3State *s = opaque;
|
||||
|
||||
cg3_invalidate_display(s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_cg3 = {
|
||||
.name = "cg3",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.post_load = vmstate_cg3_post_load,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT16(height, CG3State),
|
||||
VMSTATE_UINT16(width, CG3State),
|
||||
VMSTATE_UINT16(depth, CG3State),
|
||||
VMSTATE_BUFFER(r, CG3State),
|
||||
VMSTATE_BUFFER(g, CG3State),
|
||||
VMSTATE_BUFFER(b, CG3State),
|
||||
VMSTATE_UINT8(dac_index, CG3State),
|
||||
VMSTATE_UINT8(dac_state, CG3State),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static void cg3_reset(DeviceState *d)
|
||||
{
|
||||
CG3State *s = CG3(d);
|
||||
|
||||
/* Initialize palette */
|
||||
memset(s->r, 0, 256);
|
||||
memset(s->g, 0, 256);
|
||||
memset(s->b, 0, 256);
|
||||
|
||||
s->dac_state = 0;
|
||||
s->full_update = 1;
|
||||
qemu_irq_lower(s->irq);
|
||||
}
|
||||
|
||||
static Property cg3_properties[] = {
|
||||
DEFINE_PROP_UINT32("vram-size", CG3State, vram_size, -1),
|
||||
DEFINE_PROP_UINT16("width", CG3State, width, -1),
|
||||
DEFINE_PROP_UINT16("height", CG3State, height, -1),
|
||||
DEFINE_PROP_UINT16("depth", CG3State, depth, -1),
|
||||
DEFINE_PROP_UINT64("prom-addr", CG3State, prom_addr, -1),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void cg3_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->realize = cg3_realizefn;
|
||||
dc->reset = cg3_reset;
|
||||
dc->vmsd = &vmstate_cg3;
|
||||
dc->props = cg3_properties;
|
||||
}
|
||||
|
||||
static const TypeInfo cg3_info = {
|
||||
.name = TYPE_CG3,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(CG3State),
|
||||
.class_init = cg3_class_init,
|
||||
};
|
||||
|
||||
static void cg3_register_types(void)
|
||||
{
|
||||
type_register_static(&cg3_info);
|
||||
}
|
||||
|
||||
type_init(cg3_register_types)
|
||||
@@ -2917,7 +2917,7 @@ static void isa_cirrus_vga_realizefn(DeviceState *dev, Error **errp)
|
||||
cirrus_init_common(&d->cirrus_vga, OBJECT(dev), CIRRUS_ID_CLGD5430, 0,
|
||||
isa_address_space(isadev),
|
||||
isa_address_space_io(isadev));
|
||||
s->con = graphic_console_init(dev, s->hw_ops, s);
|
||||
s->con = graphic_console_init(dev, 0, s->hw_ops, s);
|
||||
rom_add_vga(VGABIOS_CIRRUS_FILENAME);
|
||||
/* XXX ISA-LFB support */
|
||||
/* FIXME not qdev yet */
|
||||
@@ -2963,7 +2963,7 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
|
||||
vga_common_init(&s->vga, OBJECT(dev));
|
||||
cirrus_init_common(s, OBJECT(dev), device_id, 1, pci_address_space(dev),
|
||||
pci_address_space_io(dev));
|
||||
s->vga.con = graphic_console_init(DEVICE(dev), s->vga.hw_ops, &s->vga);
|
||||
s->vga.con = graphic_console_init(DEVICE(dev), 0, s->vga.hw_ops, &s->vga);
|
||||
|
||||
/* setup PCI */
|
||||
|
||||
|
||||
@@ -1917,7 +1917,7 @@ static int exynos4210_fimd_init(SysBusDevice *dev)
|
||||
memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_fimd_mmio_ops, s,
|
||||
"exynos4210.fimd", FIMD_REGS_SIZE);
|
||||
sysbus_init_mmio(dev, &s->iomem);
|
||||
s->console = graphic_console_init(DEVICE(dev), &exynos4210_fimd_ops, s);
|
||||
s->console = graphic_console_init(DEVICE(dev), 0, &exynos4210_fimd_ops, s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -484,7 +484,7 @@ static void g364fb_init(DeviceState *dev, G364State *s)
|
||||
{
|
||||
s->vram = g_malloc0(s->vram_size);
|
||||
|
||||
s->con = graphic_console_init(dev, &g364fb_ops, s);
|
||||
s->con = graphic_console_init(dev, 0, &g364fb_ops, s);
|
||||
|
||||
memory_region_init_io(&s->mem_ctrl, NULL, &g364fb_ctrl_ops, s, "ctrl", 0x180000);
|
||||
memory_region_init_ram_ptr(&s->mem_vram, NULL, "vram",
|
||||
|
||||
@@ -271,7 +271,7 @@ static int jazz_led_init(SysBusDevice *dev)
|
||||
memory_region_init_io(&s->iomem, OBJECT(s), &led_ops, s, "led", 1);
|
||||
sysbus_init_mmio(dev, &s->iomem);
|
||||
|
||||
s->con = graphic_console_init(DEVICE(dev), &jazz_led_ops, s);
|
||||
s->con = graphic_console_init(DEVICE(dev), 0, &jazz_led_ops, s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -290,7 +290,7 @@ static int milkymist_vgafb_init(SysBusDevice *dev)
|
||||
"milkymist-vgafb", R_MAX * 4);
|
||||
sysbus_init_mmio(dev, &s->regs_region);
|
||||
|
||||
s->con = graphic_console_init(DEVICE(dev), &vgafb_ops, s);
|
||||
s->con = graphic_console_init(DEVICE(dev), 0, &vgafb_ops, s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -406,7 +406,7 @@ struct omap_lcd_panel_s *omap_lcdc_init(MemoryRegion *sysmem,
|
||||
memory_region_init_io(&s->iomem, NULL, &omap_lcdc_ops, s, "omap.lcdc", 0x100);
|
||||
memory_region_add_subregion(sysmem, base, &s->iomem);
|
||||
|
||||
s->con = graphic_console_init(NULL, &omap_ops, s);
|
||||
s->con = graphic_console_init(NULL, 0, &omap_ops, s);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -464,7 +464,7 @@ static int pl110_initfn(SysBusDevice *sbd)
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
sysbus_init_irq(sbd, &s->irq);
|
||||
qdev_init_gpio_in(dev, pl110_mux_ctrl_set, 1);
|
||||
s->con = graphic_console_init(dev, &pl110_gfx_ops, s);
|
||||
s->con = graphic_console_init(dev, 0, &pl110_gfx_ops, s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1013,7 +1013,7 @@ PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem,
|
||||
"pxa2xx-lcd-controller", 0x00100000);
|
||||
memory_region_add_subregion(sysmem, base, &s->iomem);
|
||||
|
||||
s->con = graphic_console_init(NULL, &pxa2xx_ops, s);
|
||||
s->con = graphic_console_init(NULL, 0, &pxa2xx_ops, s);
|
||||
surface = qemu_console_surface(s->con);
|
||||
|
||||
switch (surface_bits_per_pixel(surface)) {
|
||||
|
||||
@@ -2069,7 +2069,7 @@ static int qxl_init_primary(PCIDevice *dev)
|
||||
portio_list_set_flush_coalesced(qxl_vga_port_list);
|
||||
portio_list_add(qxl_vga_port_list, pci_address_space_io(dev), 0x3b0);
|
||||
|
||||
vga->con = graphic_console_init(DEVICE(dev), &qxl_ops, qxl);
|
||||
vga->con = graphic_console_init(DEVICE(dev), 0, &qxl_ops, qxl);
|
||||
qemu_spice_display_init_common(&qxl->ssd);
|
||||
|
||||
rc = qxl_init_common(qxl);
|
||||
@@ -2094,7 +2094,7 @@ static int qxl_init_secondary(PCIDevice *dev)
|
||||
qxl->vga.vram_size);
|
||||
vmstate_register_ram(&qxl->vga.vram, &qxl->pci.qdev);
|
||||
qxl->vga.vram_ptr = memory_region_get_ram_ptr(&qxl->vga.vram);
|
||||
qxl->vga.con = graphic_console_init(DEVICE(dev), &qxl_ops, qxl);
|
||||
qxl->vga.con = graphic_console_init(DEVICE(dev), 0, &qxl_ops, qxl);
|
||||
|
||||
return qxl_init_common(qxl);
|
||||
}
|
||||
|
||||
@@ -1449,5 +1449,5 @@ void sm501_init(MemoryRegion *address_space_mem, uint32_t base,
|
||||
}
|
||||
|
||||
/* create qemu graphic console */
|
||||
s->con = graphic_console_init(DEVICE(dev), &sm501_ops, s);
|
||||
s->con = graphic_console_init(DEVICE(dev), 0, &sm501_ops, s);
|
||||
}
|
||||
|
||||
@@ -299,7 +299,7 @@ static int ssd0303_init(I2CSlave *i2c)
|
||||
{
|
||||
ssd0303_state *s = SSD0303(i2c);
|
||||
|
||||
s->con = graphic_console_init(DEVICE(i2c), &ssd0303_ops, s);
|
||||
s->con = graphic_console_init(DEVICE(i2c), 0, &ssd0303_ops, s);
|
||||
qemu_console_resize(s->con, 96 * MAGNIFY, 16 * MAGNIFY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -342,7 +342,7 @@ static int ssd0323_init(SSISlave *dev)
|
||||
|
||||
s->col_end = 63;
|
||||
s->row_end = 79;
|
||||
s->con = graphic_console_init(DEVICE(dev), &ssd0323_ops, s);
|
||||
s->con = graphic_console_init(DEVICE(dev), 0, &ssd0323_ops, s);
|
||||
qemu_console_resize(s->con, 128 * MAGNIFY, 64 * MAGNIFY);
|
||||
|
||||
qdev_init_gpio_in(&dev->qdev, ssd0323_cd, 1);
|
||||
|
||||
@@ -587,7 +587,7 @@ TC6393xbState *tc6393xb_init(MemoryRegion *sysmem, uint32_t base, qemu_irq irq)
|
||||
memory_region_add_subregion(sysmem, base + 0x100000, &s->vram);
|
||||
s->scr_width = 480;
|
||||
s->scr_height = 640;
|
||||
s->con = graphic_console_init(NULL, &tc6393xb_gfx_ops, s);
|
||||
s->con = graphic_console_init(NULL, 0, &tc6393xb_gfx_ops, s);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -602,14 +602,14 @@ static int tcx_init1(SysBusDevice *dev)
|
||||
&s->vram_mem, vram_offset, size);
|
||||
sysbus_init_mmio(dev, &s->vram_cplane);
|
||||
|
||||
s->con = graphic_console_init(DEVICE(dev), &tcx24_ops, s);
|
||||
s->con = graphic_console_init(DEVICE(dev), 0, &tcx24_ops, s);
|
||||
} else {
|
||||
/* THC 8 bit (dummy) */
|
||||
memory_region_init_io(&s->thc8, OBJECT(s), &dummy_ops, s, "tcx.thc8",
|
||||
TCX_THC_NREGS_8);
|
||||
sysbus_init_mmio(dev, &s->thc8);
|
||||
|
||||
s->con = graphic_console_init(DEVICE(dev), &tcx_ops, s);
|
||||
s->con = graphic_console_init(DEVICE(dev), 0, &tcx_ops, s);
|
||||
}
|
||||
|
||||
qemu_console_resize(s->con, s->width, s->height);
|
||||
|
||||
@@ -135,7 +135,7 @@ int isa_vga_mm_init(hwaddr vram_base,
|
||||
vga_common_init(&s->vga, NULL);
|
||||
vga_mm_init(s, vram_base, ctrl_base, it_shift, address_space);
|
||||
|
||||
s->vga.con = graphic_console_init(NULL, s->vga.hw_ops, s);
|
||||
s->vga.con = graphic_console_init(NULL, 0, s->vga.hw_ops, s);
|
||||
|
||||
vga_init_vbe(&s->vga, NULL, address_space);
|
||||
return 0;
|
||||
|
||||
@@ -67,7 +67,7 @@ static void vga_isa_realizefn(DeviceState *dev, Error **errp)
|
||||
isa_mem_base + 0x000a0000,
|
||||
vga_io_memory, 1);
|
||||
memory_region_set_coalescing(vga_io_memory);
|
||||
s->con = graphic_console_init(DEVICE(dev), s->hw_ops, s);
|
||||
s->con = graphic_console_init(DEVICE(dev), 0, s->hw_ops, s);
|
||||
|
||||
vga_init_vbe(s, OBJECT(dev), isa_address_space(isadev));
|
||||
/* ROM BIOS */
|
||||
|
||||
@@ -151,7 +151,7 @@ static int pci_std_vga_initfn(PCIDevice *dev)
|
||||
vga_init(s, OBJECT(dev), pci_address_space(dev), pci_address_space_io(dev),
|
||||
true);
|
||||
|
||||
s->con = graphic_console_init(DEVICE(dev), s->hw_ops, s);
|
||||
s->con = graphic_console_init(DEVICE(dev), 0, s->hw_ops, s);
|
||||
|
||||
/* XXX: VGA_RAM_SIZE must be a power of two */
|
||||
pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram);
|
||||
|
||||
@@ -1199,7 +1199,7 @@ static void vmsvga_init(DeviceState *dev, struct vmsvga_state_s *s,
|
||||
s->scratch_size = SVGA_SCRATCH_SIZE;
|
||||
s->scratch = g_malloc(s->scratch_size * 4);
|
||||
|
||||
s->vga.con = graphic_console_init(dev, &vmsvga_ops, s);
|
||||
s->vga.con = graphic_console_init(dev, 0, &vmsvga_ops, s);
|
||||
|
||||
s->fifo_size = SVGA_FIFO_SIZE;
|
||||
memory_region_init_ram(&s->fifo_ram, NULL, "vmsvga.fifo", s->fifo_size);
|
||||
|
||||
@@ -227,7 +227,8 @@ static const VMStateDescription vmstate_pl330_queue = {
|
||||
};
|
||||
|
||||
struct PL330State {
|
||||
SysBusDevice busdev;
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
MemoryRegion iomem;
|
||||
qemu_irq irq_abort;
|
||||
qemu_irq *irq;
|
||||
@@ -577,7 +578,7 @@ static inline void pl330_queue_remove_tagged(PL330Queue *s, uint8_t tag)
|
||||
|
||||
static inline void pl330_fault(PL330Chan *ch, uint32_t flags)
|
||||
{
|
||||
DB_PRINT("ch: %p, flags: %x\n", ch, flags);
|
||||
DB_PRINT("ch: %p, flags: %" PRIx32 "\n", ch, flags);
|
||||
ch->fault_type |= flags;
|
||||
if (ch->state == pl330_chan_fault) {
|
||||
return;
|
||||
@@ -600,10 +601,12 @@ static inline void pl330_fault(PL330Chan *ch, uint32_t flags)
|
||||
* LEN - number of elements in ARGS array
|
||||
*/
|
||||
|
||||
static void pl330_dmaaddh(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
|
||||
static void pl330_dmaadxh(PL330Chan *ch, uint8_t *args, bool ra, bool neg)
|
||||
{
|
||||
uint16_t im = (((uint16_t)args[1]) << 8) | ((uint16_t)args[0]);
|
||||
uint8_t ra = (opcode >> 1) & 1;
|
||||
uint32_t im = (args[1] << 8) | args[0];
|
||||
if (neg) {
|
||||
im |= 0xffffu << 16;
|
||||
}
|
||||
|
||||
if (ch->is_manager) {
|
||||
pl330_fault(ch, PL330_FAULT_UNDEF_INSTR);
|
||||
@@ -616,6 +619,16 @@ static void pl330_dmaaddh(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
|
||||
}
|
||||
}
|
||||
|
||||
static void pl330_dmaaddh(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
|
||||
{
|
||||
pl330_dmaadxh(ch, args, extract32(opcode, 1, 1), false);
|
||||
}
|
||||
|
||||
static void pl330_dmaadnh(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
|
||||
{
|
||||
pl330_dmaadxh(ch, args, extract32(opcode, 1, 1), true);
|
||||
}
|
||||
|
||||
static void pl330_dmaend(PL330Chan *ch, uint8_t opcode,
|
||||
uint8_t *args, int len)
|
||||
{
|
||||
@@ -723,7 +736,8 @@ static void pl330_dmald(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
|
||||
ch->stall = pl330_queue_put_insn(&ch->parent->read_queue, ch->src,
|
||||
size, num, inc, 0, ch->tag);
|
||||
if (!ch->stall) {
|
||||
DB_PRINT("channel:%d address:%08x size:%d num:%d %c\n",
|
||||
DB_PRINT("channel:%" PRId8 " address:%08" PRIx32 " size:%" PRIx32
|
||||
" num:%" PRId32 " %c\n",
|
||||
ch->tag, ch->src, size, num, inc ? 'Y' : 'N');
|
||||
ch->src += inc ? size * num - (ch->src & (size - 1)) : 0;
|
||||
}
|
||||
@@ -868,9 +882,10 @@ static void pl330_dmasev(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
|
||||
}
|
||||
if (ch->parent->inten & (1 << ev_id)) {
|
||||
ch->parent->int_status |= (1 << ev_id);
|
||||
DB_PRINT("event interrupt raised %d\n", ev_id);
|
||||
DB_PRINT("event interrupt raised %" PRId8 "\n", ev_id);
|
||||
qemu_irq_raise(ch->parent->irq[ev_id]);
|
||||
}
|
||||
DB_PRINT("event raised %" PRId8 "\n", ev_id);
|
||||
ch->parent->ev_status |= (1 << ev_id);
|
||||
}
|
||||
|
||||
@@ -895,7 +910,8 @@ static void pl330_dmast(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
|
||||
ch->stall = pl330_queue_put_insn(&ch->parent->write_queue, ch->dst,
|
||||
size, num, inc, 0, ch->tag);
|
||||
if (!ch->stall) {
|
||||
DB_PRINT("channel:%d address:%08x size:%d num:%d %c\n",
|
||||
DB_PRINT("channel:%" PRId8 " address:%08" PRIx32 " size:%" PRIx32
|
||||
" num:%" PRId32 " %c\n",
|
||||
ch->tag, ch->dst, size, num, inc ? 'Y' : 'N');
|
||||
ch->dst += inc ? size * num - (ch->dst & (size - 1)) : 0;
|
||||
}
|
||||
@@ -972,6 +988,7 @@ static void pl330_dmawfe(PL330Chan *ch, uint8_t opcode,
|
||||
}
|
||||
}
|
||||
ch->parent->ev_status &= ~(1 << ev_id);
|
||||
DB_PRINT("event lowered %" PRIx8 "\n", ev_id);
|
||||
} else {
|
||||
ch->stall = 1;
|
||||
}
|
||||
@@ -1037,6 +1054,7 @@ static void pl330_dmawmb(PL330Chan *ch, uint8_t opcode,
|
||||
/* NULL terminated array of the instruction descriptions. */
|
||||
static const PL330InsnDesc insn_desc[] = {
|
||||
{ .opcode = 0x54, .opmask = 0xFD, .size = 3, .exec = pl330_dmaaddh, },
|
||||
{ .opcode = 0x5c, .opmask = 0xFD, .size = 3, .exec = pl330_dmaadnh, },
|
||||
{ .opcode = 0x00, .opmask = 0xFF, .size = 1, .exec = pl330_dmaend, },
|
||||
{ .opcode = 0x35, .opmask = 0xFF, .size = 2, .exec = pl330_dmaflushp, },
|
||||
{ .opcode = 0xA0, .opmask = 0xFD, .size = 6, .exec = pl330_dmago, },
|
||||
@@ -1108,7 +1126,6 @@ static int pl330_chan_exec(PL330Chan *ch)
|
||||
ch->state != pl330_chan_waiting_periph &&
|
||||
ch->state != pl330_chan_at_barrier &&
|
||||
ch->state != pl330_chan_waiting_event) {
|
||||
DB_PRINT("%d\n", ch->state);
|
||||
return 0;
|
||||
}
|
||||
ch->stall = 0;
|
||||
@@ -1155,7 +1172,7 @@ static int pl330_exec_cycle(PL330Chan *channel)
|
||||
|
||||
dma_memory_read(&address_space_memory, q->addr, buf, len);
|
||||
if (PL330_ERR_DEBUG > 1) {
|
||||
DB_PRINT("PL330 read from memory @%08x (size = %08x):\n",
|
||||
DB_PRINT("PL330 read from memory @%08" PRIx32 " (size = %08x):\n",
|
||||
q->addr, len);
|
||||
qemu_hexdump((char *)buf, stderr, "", len);
|
||||
}
|
||||
@@ -1187,8 +1204,8 @@ static int pl330_exec_cycle(PL330Chan *channel)
|
||||
if (fifo_res == PL330_FIFO_OK || q->z) {
|
||||
dma_memory_write(&address_space_memory, q->addr, buf, len);
|
||||
if (PL330_ERR_DEBUG > 1) {
|
||||
DB_PRINT("PL330 read from memory @%08x (size = %08x):\n",
|
||||
q->addr, len);
|
||||
DB_PRINT("PL330 read from memory @%08" PRIx32
|
||||
" (size = %08x):\n", q->addr, len);
|
||||
qemu_hexdump((char *)buf, stderr, "", len);
|
||||
}
|
||||
if (q->inc) {
|
||||
@@ -1277,7 +1294,7 @@ static void pl330_debug_exec(PL330State *s)
|
||||
args[2] = (s->dbg[1] >> 8) & 0xff;
|
||||
args[3] = (s->dbg[1] >> 16) & 0xff;
|
||||
args[4] = (s->dbg[1] >> 24) & 0xff;
|
||||
DB_PRINT("chan id: %d\n", chan_id);
|
||||
DB_PRINT("chan id: %" PRIx8 "\n", chan_id);
|
||||
if (s->dbg[0] & 1) {
|
||||
ch = &s->chan[chan_id];
|
||||
} else {
|
||||
@@ -1311,7 +1328,7 @@ static void pl330_iomem_write(void *opaque, hwaddr offset,
|
||||
uint64_t value, unsigned size)
|
||||
{
|
||||
PL330State *s = (PL330State *) opaque;
|
||||
uint32_t i;
|
||||
int i;
|
||||
|
||||
DB_PRINT("addr: %08x data: %08x\n", (unsigned)offset, (unsigned)value);
|
||||
|
||||
@@ -1467,8 +1484,8 @@ static inline uint32_t pl330_iomem_read_imp(void *opaque,
|
||||
static uint64_t pl330_iomem_read(void *opaque, hwaddr offset,
|
||||
unsigned size)
|
||||
{
|
||||
int ret = pl330_iomem_read_imp(opaque, offset);
|
||||
DB_PRINT("addr: %08x data: %08x\n", (unsigned)offset, ret);
|
||||
uint32_t ret = pl330_iomem_read_imp(opaque, offset);
|
||||
DB_PRINT("addr: %08" HWADDR_PRIx " data: %08" PRIx32 "\n", offset, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1554,7 +1571,7 @@ static void pl330_realize(DeviceState *dev, Error **errp)
|
||||
s->cfg[1] |= 5;
|
||||
break;
|
||||
default:
|
||||
error_setg(errp, "Bad value for i-cache_len property: %d\n",
|
||||
error_setg(errp, "Bad value for i-cache_len property: %" PRIx8 "\n",
|
||||
s->i_cache_len);
|
||||
return;
|
||||
}
|
||||
@@ -1589,7 +1606,7 @@ static void pl330_realize(DeviceState *dev, Error **errp)
|
||||
s->cfg[CFG_CRD] |= 0x4;
|
||||
break;
|
||||
default:
|
||||
error_setg(errp, "Bad value for data_width property: %d\n",
|
||||
error_setg(errp, "Bad value for data_width property: %" PRIx8 "\n",
|
||||
s->data_width);
|
||||
return;
|
||||
}
|
||||
@@ -1602,7 +1619,7 @@ static void pl330_realize(DeviceState *dev, Error **errp)
|
||||
|
||||
pl330_queue_init(&s->read_queue, s->rd_q_dep, s);
|
||||
pl330_queue_init(&s->write_queue, s->wr_q_dep, s);
|
||||
pl330_fifo_init(&s->fifo, s->data_buffer_dep);
|
||||
pl330_fifo_init(&s->fifo, s->data_width / 4 * s->data_buffer_dep);
|
||||
}
|
||||
|
||||
static Property pl330_properties[] = {
|
||||
|
||||
@@ -25,3 +25,4 @@ obj-$(CONFIG_SH4) += sh_intc.o
|
||||
obj-$(CONFIG_XICS) += xics.o
|
||||
obj-$(CONFIG_XICS_KVM) += xics_kvm.o
|
||||
obj-$(CONFIG_ALLWINNER_A10_PIC) += allwinner-a10-pic.o
|
||||
obj-$(CONFIG_S390_FLIC) += s390_flic.o
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*
|
||||
* Copyright (c) 2012 Linaro Limited
|
||||
* Written by Peter Maydell
|
||||
* Save/Restore logic added by Christoffer Dall.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -23,6 +24,20 @@
|
||||
#include "kvm_arm.h"
|
||||
#include "gic_internal.h"
|
||||
|
||||
//#define DEBUG_GIC_KVM
|
||||
|
||||
#ifdef DEBUG_GIC_KVM
|
||||
static const int debug_gic_kvm = 1;
|
||||
#else
|
||||
static const int debug_gic_kvm = 0;
|
||||
#endif
|
||||
|
||||
#define DPRINTF(fmt, ...) do { \
|
||||
if (debug_gic_kvm) { \
|
||||
printf("arm_gic: " fmt , ## __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define TYPE_KVM_ARM_GIC "kvm-arm-gic"
|
||||
#define KVM_ARM_GIC(obj) \
|
||||
OBJECT_CHECK(GICState, (obj), TYPE_KVM_ARM_GIC)
|
||||
@@ -72,14 +87,419 @@ static void kvm_arm_gic_set_irq(void *opaque, int irq, int level)
|
||||
kvm_set_irq(kvm_state, kvm_irq, !!level);
|
||||
}
|
||||
|
||||
static bool kvm_arm_gic_can_save_restore(GICState *s)
|
||||
{
|
||||
return s->dev_fd >= 0;
|
||||
}
|
||||
|
||||
static void kvm_gic_access(GICState *s, int group, int offset,
|
||||
int cpu, uint32_t *val, bool write)
|
||||
{
|
||||
struct kvm_device_attr attr;
|
||||
int type;
|
||||
int err;
|
||||
|
||||
cpu = cpu & 0xff;
|
||||
|
||||
attr.flags = 0;
|
||||
attr.group = group;
|
||||
attr.attr = (((uint64_t)cpu << KVM_DEV_ARM_VGIC_CPUID_SHIFT) &
|
||||
KVM_DEV_ARM_VGIC_CPUID_MASK) |
|
||||
(((uint64_t)offset << KVM_DEV_ARM_VGIC_OFFSET_SHIFT) &
|
||||
KVM_DEV_ARM_VGIC_OFFSET_MASK);
|
||||
attr.addr = (uintptr_t)val;
|
||||
|
||||
if (write) {
|
||||
type = KVM_SET_DEVICE_ATTR;
|
||||
} else {
|
||||
type = KVM_GET_DEVICE_ATTR;
|
||||
}
|
||||
|
||||
err = kvm_device_ioctl(s->dev_fd, type, &attr);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "KVM_{SET/GET}_DEVICE_ATTR failed: %s\n",
|
||||
strerror(-err));
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static void kvm_gicd_access(GICState *s, int offset, int cpu,
|
||||
uint32_t *val, bool write)
|
||||
{
|
||||
kvm_gic_access(s, KVM_DEV_ARM_VGIC_GRP_DIST_REGS,
|
||||
offset, cpu, val, write);
|
||||
}
|
||||
|
||||
static void kvm_gicc_access(GICState *s, int offset, int cpu,
|
||||
uint32_t *val, bool write)
|
||||
{
|
||||
kvm_gic_access(s, KVM_DEV_ARM_VGIC_GRP_CPU_REGS,
|
||||
offset, cpu, val, write);
|
||||
}
|
||||
|
||||
#define for_each_irq_reg(_ctr, _max_irq, _field_width) \
|
||||
for (_ctr = 0; _ctr < ((_max_irq) / (32 / (_field_width))); _ctr++)
|
||||
|
||||
/*
|
||||
* Translate from the in-kernel field for an IRQ value to/from the qemu
|
||||
* representation.
|
||||
*/
|
||||
typedef void (*vgic_translate_fn)(GICState *s, int irq, int cpu,
|
||||
uint32_t *field, bool to_kernel);
|
||||
|
||||
/* synthetic translate function used for clear/set registers to completely
|
||||
* clear a setting using a clear-register before setting the remaing bits
|
||||
* using a set-register */
|
||||
static void translate_clear(GICState *s, int irq, int cpu,
|
||||
uint32_t *field, bool to_kernel)
|
||||
{
|
||||
if (to_kernel) {
|
||||
*field = ~0;
|
||||
} else {
|
||||
/* does not make sense: qemu model doesn't use set/clear regs */
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static void translate_enabled(GICState *s, int irq, int cpu,
|
||||
uint32_t *field, bool to_kernel)
|
||||
{
|
||||
int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
|
||||
|
||||
if (to_kernel) {
|
||||
*field = GIC_TEST_ENABLED(irq, cm);
|
||||
} else {
|
||||
if (*field & 1) {
|
||||
GIC_SET_ENABLED(irq, cm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void translate_pending(GICState *s, int irq, int cpu,
|
||||
uint32_t *field, bool to_kernel)
|
||||
{
|
||||
int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
|
||||
|
||||
if (to_kernel) {
|
||||
*field = gic_test_pending(s, irq, cm);
|
||||
} else {
|
||||
if (*field & 1) {
|
||||
GIC_SET_PENDING(irq, cm);
|
||||
/* TODO: Capture is level-line is held high in the kernel */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void translate_active(GICState *s, int irq, int cpu,
|
||||
uint32_t *field, bool to_kernel)
|
||||
{
|
||||
int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
|
||||
|
||||
if (to_kernel) {
|
||||
*field = GIC_TEST_ACTIVE(irq, cm);
|
||||
} else {
|
||||
if (*field & 1) {
|
||||
GIC_SET_ACTIVE(irq, cm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void translate_trigger(GICState *s, int irq, int cpu,
|
||||
uint32_t *field, bool to_kernel)
|
||||
{
|
||||
if (to_kernel) {
|
||||
*field = (GIC_TEST_EDGE_TRIGGER(irq)) ? 0x2 : 0x0;
|
||||
} else {
|
||||
if (*field & 0x2) {
|
||||
GIC_SET_EDGE_TRIGGER(irq);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void translate_priority(GICState *s, int irq, int cpu,
|
||||
uint32_t *field, bool to_kernel)
|
||||
{
|
||||
if (to_kernel) {
|
||||
*field = GIC_GET_PRIORITY(irq, cpu) & 0xff;
|
||||
} else {
|
||||
gic_set_priority(s, cpu, irq, *field & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
static void translate_targets(GICState *s, int irq, int cpu,
|
||||
uint32_t *field, bool to_kernel)
|
||||
{
|
||||
if (to_kernel) {
|
||||
*field = s->irq_target[irq] & 0xff;
|
||||
} else {
|
||||
s->irq_target[irq] = *field & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
static void translate_sgisource(GICState *s, int irq, int cpu,
|
||||
uint32_t *field, bool to_kernel)
|
||||
{
|
||||
if (to_kernel) {
|
||||
*field = s->sgi_pending[irq][cpu] & 0xff;
|
||||
} else {
|
||||
s->sgi_pending[irq][cpu] = *field & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read a register group from the kernel VGIC */
|
||||
static void kvm_dist_get(GICState *s, uint32_t offset, int width,
|
||||
int maxirq, vgic_translate_fn translate_fn)
|
||||
{
|
||||
uint32_t reg;
|
||||
int i;
|
||||
int j;
|
||||
int irq;
|
||||
int cpu;
|
||||
int regsz = 32 / width; /* irqs per kernel register */
|
||||
uint32_t field;
|
||||
|
||||
for_each_irq_reg(i, maxirq, width) {
|
||||
irq = i * regsz;
|
||||
cpu = 0;
|
||||
while ((cpu < s->num_cpu && irq < GIC_INTERNAL) || cpu == 0) {
|
||||
kvm_gicd_access(s, offset, cpu, ®, false);
|
||||
for (j = 0; j < regsz; j++) {
|
||||
field = extract32(reg, j * width, width);
|
||||
translate_fn(s, irq + j, cpu, &field, false);
|
||||
}
|
||||
|
||||
cpu++;
|
||||
}
|
||||
offset += 4;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write a register group to the kernel VGIC */
|
||||
static void kvm_dist_put(GICState *s, uint32_t offset, int width,
|
||||
int maxirq, vgic_translate_fn translate_fn)
|
||||
{
|
||||
uint32_t reg;
|
||||
int i;
|
||||
int j;
|
||||
int irq;
|
||||
int cpu;
|
||||
int regsz = 32 / width; /* irqs per kernel register */
|
||||
uint32_t field;
|
||||
|
||||
for_each_irq_reg(i, maxirq, width) {
|
||||
irq = i * regsz;
|
||||
cpu = 0;
|
||||
while ((cpu < s->num_cpu && irq < GIC_INTERNAL) || cpu == 0) {
|
||||
reg = 0;
|
||||
for (j = 0; j < regsz; j++) {
|
||||
translate_fn(s, irq + j, cpu, &field, true);
|
||||
reg = deposit32(reg, j * width, width, field);
|
||||
}
|
||||
kvm_gicd_access(s, offset, cpu, ®, true);
|
||||
|
||||
cpu++;
|
||||
}
|
||||
offset += 4;
|
||||
}
|
||||
}
|
||||
|
||||
static void kvm_arm_gic_put(GICState *s)
|
||||
{
|
||||
/* TODO: there isn't currently a kernel interface to set the GIC state */
|
||||
uint32_t reg;
|
||||
int i;
|
||||
int cpu;
|
||||
int num_cpu;
|
||||
int num_irq;
|
||||
|
||||
if (!kvm_arm_gic_can_save_restore(s)) {
|
||||
DPRINTF("Cannot put kernel gic state, no kernel interface");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Note: We do the restore in a slightly different order than the save
|
||||
* (where the order doesn't matter and is simply ordered according to the
|
||||
* register offset values */
|
||||
|
||||
/*****************************************************************
|
||||
* Distributor State
|
||||
*/
|
||||
|
||||
/* s->enabled -> GICD_CTLR */
|
||||
reg = s->enabled;
|
||||
kvm_gicd_access(s, 0x0, 0, ®, true);
|
||||
|
||||
/* Sanity checking on GICD_TYPER and s->num_irq, s->num_cpu */
|
||||
kvm_gicd_access(s, 0x4, 0, ®, false);
|
||||
num_irq = ((reg & 0x1f) + 1) * 32;
|
||||
num_cpu = ((reg & 0xe0) >> 5) + 1;
|
||||
|
||||
if (num_irq < s->num_irq) {
|
||||
fprintf(stderr, "Restoring %u IRQs, but kernel supports max %d\n",
|
||||
s->num_irq, num_irq);
|
||||
abort();
|
||||
} else if (num_cpu != s->num_cpu) {
|
||||
fprintf(stderr, "Restoring %u CPU interfaces, kernel only has %d\n",
|
||||
s->num_cpu, num_cpu);
|
||||
/* Did we not create the VCPUs in the kernel yet? */
|
||||
abort();
|
||||
}
|
||||
|
||||
/* TODO: Consider checking compatibility with the IIDR ? */
|
||||
|
||||
/* irq_state[n].enabled -> GICD_ISENABLERn */
|
||||
kvm_dist_put(s, 0x180, 1, s->num_irq, translate_clear);
|
||||
kvm_dist_put(s, 0x100, 1, s->num_irq, translate_enabled);
|
||||
|
||||
/* s->irq_target[irq] -> GICD_ITARGETSRn
|
||||
* (restore targets before pending to ensure the pending state is set on
|
||||
* the appropriate CPU interfaces in the kernel) */
|
||||
kvm_dist_put(s, 0x800, 8, s->num_irq, translate_targets);
|
||||
|
||||
/* irq_state[n].pending + irq_state[n].level -> GICD_ISPENDRn */
|
||||
kvm_dist_put(s, 0x280, 1, s->num_irq, translate_clear);
|
||||
kvm_dist_put(s, 0x200, 1, s->num_irq, translate_pending);
|
||||
|
||||
/* irq_state[n].active -> GICD_ISACTIVERn */
|
||||
kvm_dist_put(s, 0x380, 1, s->num_irq, translate_clear);
|
||||
kvm_dist_put(s, 0x300, 1, s->num_irq, translate_active);
|
||||
|
||||
/* irq_state[n].trigger -> GICD_ICFRn */
|
||||
kvm_dist_put(s, 0xc00, 2, s->num_irq, translate_trigger);
|
||||
|
||||
/* s->priorityX[irq] -> ICD_IPRIORITYRn */
|
||||
kvm_dist_put(s, 0x400, 8, s->num_irq, translate_priority);
|
||||
|
||||
/* s->sgi_pending -> ICD_CPENDSGIRn */
|
||||
kvm_dist_put(s, 0xf10, 8, GIC_NR_SGIS, translate_clear);
|
||||
kvm_dist_put(s, 0xf20, 8, GIC_NR_SGIS, translate_sgisource);
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
* CPU Interface(s) State
|
||||
*/
|
||||
|
||||
for (cpu = 0; cpu < s->num_cpu; cpu++) {
|
||||
/* s->cpu_enabled[cpu] -> GICC_CTLR */
|
||||
reg = s->cpu_enabled[cpu];
|
||||
kvm_gicc_access(s, 0x00, cpu, ®, true);
|
||||
|
||||
/* s->priority_mask[cpu] -> GICC_PMR */
|
||||
reg = (s->priority_mask[cpu] & 0xff);
|
||||
kvm_gicc_access(s, 0x04, cpu, ®, true);
|
||||
|
||||
/* s->bpr[cpu] -> GICC_BPR */
|
||||
reg = (s->bpr[cpu] & 0x7);
|
||||
kvm_gicc_access(s, 0x08, cpu, ®, true);
|
||||
|
||||
/* s->abpr[cpu] -> GICC_ABPR */
|
||||
reg = (s->abpr[cpu] & 0x7);
|
||||
kvm_gicc_access(s, 0x1c, cpu, ®, true);
|
||||
|
||||
/* s->apr[n][cpu] -> GICC_APRn */
|
||||
for (i = 0; i < 4; i++) {
|
||||
reg = s->apr[i][cpu];
|
||||
kvm_gicc_access(s, 0xd0 + i * 4, cpu, ®, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void kvm_arm_gic_get(GICState *s)
|
||||
{
|
||||
/* TODO: there isn't currently a kernel interface to get the GIC state */
|
||||
uint32_t reg;
|
||||
int i;
|
||||
int cpu;
|
||||
|
||||
if (!kvm_arm_gic_can_save_restore(s)) {
|
||||
DPRINTF("Cannot get kernel gic state, no kernel interface");
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
* Distributor State
|
||||
*/
|
||||
|
||||
/* GICD_CTLR -> s->enabled */
|
||||
kvm_gicd_access(s, 0x0, 0, ®, false);
|
||||
s->enabled = reg & 1;
|
||||
|
||||
/* Sanity checking on GICD_TYPER -> s->num_irq, s->num_cpu */
|
||||
kvm_gicd_access(s, 0x4, 0, ®, false);
|
||||
s->num_irq = ((reg & 0x1f) + 1) * 32;
|
||||
s->num_cpu = ((reg & 0xe0) >> 5) + 1;
|
||||
|
||||
if (s->num_irq > GIC_MAXIRQ) {
|
||||
fprintf(stderr, "Too many IRQs reported from the kernel: %d\n",
|
||||
s->num_irq);
|
||||
abort();
|
||||
}
|
||||
|
||||
/* GICD_IIDR -> ? */
|
||||
kvm_gicd_access(s, 0x8, 0, ®, false);
|
||||
|
||||
/* Verify no GROUP 1 interrupts configured in the kernel */
|
||||
for_each_irq_reg(i, s->num_irq, 1) {
|
||||
kvm_gicd_access(s, 0x80 + (i * 4), 0, ®, false);
|
||||
if (reg != 0) {
|
||||
fprintf(stderr, "Unsupported GICD_IGROUPRn value: %08x\n",
|
||||
reg);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear all the IRQ settings */
|
||||
for (i = 0; i < s->num_irq; i++) {
|
||||
memset(&s->irq_state[i], 0, sizeof(s->irq_state[0]));
|
||||
}
|
||||
|
||||
/* GICD_ISENABLERn -> irq_state[n].enabled */
|
||||
kvm_dist_get(s, 0x100, 1, s->num_irq, translate_enabled);
|
||||
|
||||
/* GICD_ISPENDRn -> irq_state[n].pending + irq_state[n].level */
|
||||
kvm_dist_get(s, 0x200, 1, s->num_irq, translate_pending);
|
||||
|
||||
/* GICD_ISACTIVERn -> irq_state[n].active */
|
||||
kvm_dist_get(s, 0x300, 1, s->num_irq, translate_active);
|
||||
|
||||
/* GICD_ICFRn -> irq_state[n].trigger */
|
||||
kvm_dist_get(s, 0xc00, 2, s->num_irq, translate_trigger);
|
||||
|
||||
/* GICD_IPRIORITYRn -> s->priorityX[irq] */
|
||||
kvm_dist_get(s, 0x400, 8, s->num_irq, translate_priority);
|
||||
|
||||
/* GICD_ITARGETSRn -> s->irq_target[irq] */
|
||||
kvm_dist_get(s, 0x800, 8, s->num_irq, translate_targets);
|
||||
|
||||
/* GICD_CPENDSGIRn -> s->sgi_pending */
|
||||
kvm_dist_get(s, 0xf10, 8, GIC_NR_SGIS, translate_sgisource);
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
* CPU Interface(s) State
|
||||
*/
|
||||
|
||||
for (cpu = 0; cpu < s->num_cpu; cpu++) {
|
||||
/* GICC_CTLR -> s->cpu_enabled[cpu] */
|
||||
kvm_gicc_access(s, 0x00, cpu, ®, false);
|
||||
s->cpu_enabled[cpu] = (reg & 1);
|
||||
|
||||
/* GICC_PMR -> s->priority_mask[cpu] */
|
||||
kvm_gicc_access(s, 0x04, cpu, ®, false);
|
||||
s->priority_mask[cpu] = (reg & 0xff);
|
||||
|
||||
/* GICC_BPR -> s->bpr[cpu] */
|
||||
kvm_gicc_access(s, 0x08, cpu, ®, false);
|
||||
s->bpr[cpu] = (reg & 0x7);
|
||||
|
||||
/* GICC_ABPR -> s->abpr[cpu] */
|
||||
kvm_gicc_access(s, 0x1c, cpu, ®, false);
|
||||
s->abpr[cpu] = (reg & 0x7);
|
||||
|
||||
/* GICC_APRn -> s->apr[n][cpu] */
|
||||
for (i = 0; i < 4; i++) {
|
||||
kvm_gicc_access(s, 0xd0 + i * 4, cpu, ®, false);
|
||||
s->apr[i][cpu] = reg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void kvm_arm_gic_reset(DeviceState *dev)
|
||||
@@ -97,6 +517,7 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
|
||||
GICState *s = KVM_ARM_GIC(dev);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
KVMARMGICClass *kgc = KVM_ARM_GIC_GET_CLASS(s);
|
||||
int ret;
|
||||
|
||||
kgc->parent_realize(dev, errp);
|
||||
if (error_is_set(errp)) {
|
||||
@@ -119,13 +540,27 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
|
||||
for (i = 0; i < s->num_cpu; i++) {
|
||||
sysbus_init_irq(sbd, &s->parent_irq[i]);
|
||||
}
|
||||
|
||||
/* Try to create the device via the device control API */
|
||||
s->dev_fd = -1;
|
||||
ret = kvm_create_device(kvm_state, KVM_DEV_TYPE_ARM_VGIC_V2, false);
|
||||
if (ret >= 0) {
|
||||
s->dev_fd = ret;
|
||||
} else if (ret != -ENODEV && ret != -ENOTSUP) {
|
||||
error_setg_errno(errp, -ret, "error creating in-kernel VGIC");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Distributor */
|
||||
memory_region_init_reservation(&s->iomem, OBJECT(s),
|
||||
"kvm-gic_dist", 0x1000);
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
kvm_arm_register_device(&s->iomem,
|
||||
(KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT)
|
||||
| KVM_VGIC_V2_ADDR_TYPE_DIST);
|
||||
| KVM_VGIC_V2_ADDR_TYPE_DIST,
|
||||
KVM_DEV_ARM_VGIC_GRP_ADDR,
|
||||
KVM_VGIC_V2_ADDR_TYPE_DIST,
|
||||
s->dev_fd);
|
||||
/* CPU interface for current core. Unlike arm_gic, we don't
|
||||
* provide the "interface for core #N" memory regions, because
|
||||
* cores with a VGIC don't have those.
|
||||
@@ -135,7 +570,10 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
|
||||
sysbus_init_mmio(sbd, &s->cpuiomem[0]);
|
||||
kvm_arm_register_device(&s->cpuiomem[0],
|
||||
(KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT)
|
||||
| KVM_VGIC_V2_ADDR_TYPE_CPU);
|
||||
| KVM_VGIC_V2_ADDR_TYPE_CPU,
|
||||
KVM_DEV_ARM_VGIC_GRP_ADDR,
|
||||
KVM_VGIC_V2_ADDR_TYPE_CPU,
|
||||
s->dev_fd);
|
||||
}
|
||||
|
||||
static void kvm_arm_gic_class_init(ObjectClass *klass, void *data)
|
||||
|
||||
@@ -418,7 +418,7 @@ static int exynos4210_combiner_init(SysBusDevice *sbd)
|
||||
qdev_init_gpio_in(dev, exynos4210_combiner_handler, IIC_NIRQ);
|
||||
|
||||
/* Connect SysBusDev irqs to device specific irqs */
|
||||
for (i = 0; i < IIC_NIRQ; i++) {
|
||||
for (i = 0; i < IIC_NGRP; i++) {
|
||||
sysbus_init_irq(sbd, &s->output_irq[i]);
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
#define GIC_SET_MODEL(irq) s->irq_state[irq].model = true
|
||||
#define GIC_CLEAR_MODEL(irq) s->irq_state[irq].model = false
|
||||
#define GIC_TEST_MODEL(irq) s->irq_state[irq].model
|
||||
#define GIC_SET_LEVEL(irq, cm) s->irq_state[irq].level = (cm)
|
||||
#define GIC_SET_LEVEL(irq, cm) s->irq_state[irq].level |= (cm)
|
||||
#define GIC_CLEAR_LEVEL(irq, cm) s->irq_state[irq].level &= ~(cm)
|
||||
#define GIC_TEST_LEVEL(irq, cm) ((s->irq_state[irq].level & (cm)) != 0)
|
||||
#define GIC_SET_EDGE_TRIGGER(irq) s->irq_state[irq].edge_trigger = true
|
||||
|
||||
322
hw/intc/s390_flic.c
Normal file
322
hw/intc/s390_flic.c
Normal file
@@ -0,0 +1,322 @@
|
||||
/*
|
||||
* QEMU S390x KVM floating interrupt controller (flic)
|
||||
*
|
||||
* Copyright 2014 IBM Corp.
|
||||
* Author(s): Jens Freimann <jfrei@linux.vnet.ibm.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or (at
|
||||
* your option) any later version. See the COPYING file in the top-level
|
||||
* directory.
|
||||
*/
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include "qemu/error-report.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "migration/qemu-file.h"
|
||||
#include "hw/s390x/s390_flic.h"
|
||||
#include "trace.h"
|
||||
|
||||
#define FLIC_SAVE_INITIAL_SIZE getpagesize()
|
||||
#define FLIC_FAILED (-1UL)
|
||||
#define FLIC_SAVEVM_VERSION 1
|
||||
|
||||
void s390_flic_init(void)
|
||||
{
|
||||
DeviceState *dev;
|
||||
int r;
|
||||
|
||||
if (kvm_enabled()) {
|
||||
dev = qdev_create(NULL, "s390-flic");
|
||||
object_property_add_child(qdev_get_machine(), "s390-flic",
|
||||
OBJECT(dev), NULL);
|
||||
r = qdev_init(dev);
|
||||
if (r) {
|
||||
error_report("flic: couldn't create qdev");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* flic_get_all_irqs - store all pending irqs in buffer
|
||||
* @buf: pointer to buffer which is passed to kernel
|
||||
* @len: length of buffer
|
||||
* @flic: pointer to flic device state
|
||||
*
|
||||
* Returns: -ENOMEM if buffer is too small,
|
||||
* -EINVAL if attr.group is invalid,
|
||||
* -EFAULT if copying to userspace failed,
|
||||
* on success return number of stored interrupts
|
||||
*/
|
||||
static int flic_get_all_irqs(KVMS390FLICState *flic,
|
||||
void *buf, int len)
|
||||
{
|
||||
struct kvm_device_attr attr = {
|
||||
.group = KVM_DEV_FLIC_GET_ALL_IRQS,
|
||||
.addr = (uint64_t) buf,
|
||||
.attr = len,
|
||||
};
|
||||
int rc;
|
||||
|
||||
rc = ioctl(flic->fd, KVM_GET_DEVICE_ATTR, &attr);
|
||||
|
||||
return rc == -1 ? -errno : rc;
|
||||
}
|
||||
|
||||
static void flic_enable_pfault(KVMS390FLICState *flic)
|
||||
{
|
||||
struct kvm_device_attr attr = {
|
||||
.group = KVM_DEV_FLIC_APF_ENABLE,
|
||||
};
|
||||
int rc;
|
||||
|
||||
rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
|
||||
|
||||
if (rc) {
|
||||
fprintf(stderr, "flic: couldn't enable pfault\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void flic_disable_wait_pfault(KVMS390FLICState *flic)
|
||||
{
|
||||
struct kvm_device_attr attr = {
|
||||
.group = KVM_DEV_FLIC_APF_DISABLE_WAIT,
|
||||
};
|
||||
int rc;
|
||||
|
||||
rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
|
||||
|
||||
if (rc) {
|
||||
fprintf(stderr, "flic: couldn't disable pfault\n");
|
||||
}
|
||||
}
|
||||
|
||||
/** flic_enqueue_irqs - returns 0 on success
|
||||
* @buf: pointer to buffer which is passed to kernel
|
||||
* @len: length of buffer
|
||||
* @flic: pointer to flic device state
|
||||
*
|
||||
* Returns: -EINVAL if attr.group is unknown
|
||||
*/
|
||||
static int flic_enqueue_irqs(void *buf, uint64_t len,
|
||||
KVMS390FLICState *flic)
|
||||
{
|
||||
int rc;
|
||||
struct kvm_device_attr attr = {
|
||||
.group = KVM_DEV_FLIC_ENQUEUE,
|
||||
.addr = (uint64_t) buf,
|
||||
.attr = len,
|
||||
};
|
||||
|
||||
rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
|
||||
|
||||
return rc ? -errno : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* __get_all_irqs - store all pending irqs in buffer
|
||||
* @flic: pointer to flic device state
|
||||
* @buf: pointer to pointer to a buffer
|
||||
* @len: length of buffer
|
||||
*
|
||||
* Returns: return value of flic_get_all_irqs
|
||||
* Note: Retry and increase buffer size until flic_get_all_irqs
|
||||
* either returns a value >= 0 or a negative error code.
|
||||
* -ENOMEM is an exception, which means the buffer is too small
|
||||
* and we should try again. Other negative error codes can be
|
||||
* -EFAULT and -EINVAL which we ignore at this point
|
||||
*/
|
||||
static int __get_all_irqs(KVMS390FLICState *flic,
|
||||
void **buf, int len)
|
||||
{
|
||||
int r;
|
||||
|
||||
do {
|
||||
/* returns -ENOMEM if buffer is too small and number
|
||||
* of queued interrupts on success */
|
||||
r = flic_get_all_irqs(flic, *buf, len);
|
||||
if (r >= 0) {
|
||||
break;
|
||||
}
|
||||
len *= 2;
|
||||
*buf = g_try_realloc(*buf, len);
|
||||
if (!buf) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
} while (r == -ENOMEM && len <= KVM_S390_FLIC_MAX_BUFFER);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* kvm_flic_save - Save pending floating interrupts
|
||||
* @f: QEMUFile containing migration state
|
||||
* @opaque: pointer to flic device state
|
||||
*
|
||||
* Note: Pass buf and len to kernel. Start with one page and
|
||||
* increase until buffer is sufficient or maxium size is
|
||||
* reached
|
||||
*/
|
||||
static void kvm_flic_save(QEMUFile *f, void *opaque)
|
||||
{
|
||||
KVMS390FLICState *flic = opaque;
|
||||
int len = FLIC_SAVE_INITIAL_SIZE;
|
||||
void *buf;
|
||||
int count;
|
||||
|
||||
flic_disable_wait_pfault((struct KVMS390FLICState *) opaque);
|
||||
|
||||
buf = g_try_malloc0(len);
|
||||
if (!buf) {
|
||||
/* Storing FLIC_FAILED into the count field here will cause the
|
||||
* target system to fail when attempting to load irqs from the
|
||||
* migration state */
|
||||
error_report("flic: couldn't allocate memory");
|
||||
qemu_put_be64(f, FLIC_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
count = __get_all_irqs(flic, &buf, len);
|
||||
if (count < 0) {
|
||||
error_report("flic: couldn't retrieve irqs from kernel, rc %d",
|
||||
count);
|
||||
/* Storing FLIC_FAILED into the count field here will cause the
|
||||
* target system to fail when attempting to load irqs from the
|
||||
* migration state */
|
||||
qemu_put_be64(f, FLIC_FAILED);
|
||||
} else {
|
||||
qemu_put_be64(f, count);
|
||||
qemu_put_buffer(f, (uint8_t *) buf,
|
||||
count * sizeof(struct kvm_s390_irq));
|
||||
}
|
||||
g_free(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* kvm_flic_load - Load pending floating interrupts
|
||||
* @f: QEMUFile containing migration state
|
||||
* @opaque: pointer to flic device state
|
||||
* @version_id: version id for migration
|
||||
*
|
||||
* Returns: value of flic_enqueue_irqs, -EINVAL on error
|
||||
* Note: Do nothing when no interrupts where stored
|
||||
* in QEMUFile
|
||||
*/
|
||||
static int kvm_flic_load(QEMUFile *f, void *opaque, int version_id)
|
||||
{
|
||||
uint64_t len = 0;
|
||||
uint64_t count = 0;
|
||||
void *buf = NULL;
|
||||
int r = 0;
|
||||
|
||||
if (version_id != FLIC_SAVEVM_VERSION) {
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
flic_enable_pfault((struct KVMS390FLICState *) opaque);
|
||||
|
||||
count = qemu_get_be64(f);
|
||||
len = count * sizeof(struct kvm_s390_irq);
|
||||
if (count == FLIC_FAILED) {
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (count == 0) {
|
||||
r = 0;
|
||||
goto out;
|
||||
}
|
||||
buf = g_try_malloc0(len);
|
||||
if (!buf) {
|
||||
r = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (qemu_get_buffer(f, (uint8_t *) buf, len) != len) {
|
||||
r = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
r = flic_enqueue_irqs(buf, len, (struct KVMS390FLICState *) opaque);
|
||||
|
||||
out_free:
|
||||
g_free(buf);
|
||||
out:
|
||||
return r;
|
||||
}
|
||||
|
||||
static void kvm_s390_flic_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
KVMS390FLICState *flic_state = KVM_S390_FLIC(dev);
|
||||
struct kvm_create_device cd = {0};
|
||||
int ret;
|
||||
|
||||
flic_state->fd = -1;
|
||||
if (!kvm_check_extension(kvm_state, KVM_CAP_DEVICE_CTRL)) {
|
||||
trace_flic_no_device_api(errno);
|
||||
return;
|
||||
}
|
||||
|
||||
cd.type = KVM_DEV_TYPE_FLIC;
|
||||
ret = kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, &cd);
|
||||
if (ret < 0) {
|
||||
trace_flic_create_device(errno);
|
||||
return;
|
||||
}
|
||||
flic_state->fd = cd.fd;
|
||||
|
||||
/* Register savevm handler for floating interrupts */
|
||||
register_savevm(NULL, "s390-flic", 0, 1, kvm_flic_save,
|
||||
kvm_flic_load, (void *) flic_state);
|
||||
}
|
||||
|
||||
static void kvm_s390_flic_unrealize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
KVMS390FLICState *flic_state = KVM_S390_FLIC(dev);
|
||||
|
||||
unregister_savevm(DEVICE(flic_state), "s390-flic", flic_state);
|
||||
}
|
||||
|
||||
static void kvm_s390_flic_reset(DeviceState *dev)
|
||||
{
|
||||
KVMS390FLICState *flic = KVM_S390_FLIC(dev);
|
||||
struct kvm_device_attr attr = {
|
||||
.group = KVM_DEV_FLIC_CLEAR_IRQS,
|
||||
};
|
||||
int rc = 0;
|
||||
|
||||
if (flic->fd == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
flic_disable_wait_pfault(flic);
|
||||
|
||||
rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
|
||||
if (rc) {
|
||||
trace_flic_reset_failed(errno);
|
||||
}
|
||||
|
||||
flic_enable_pfault(flic);
|
||||
}
|
||||
|
||||
static void kvm_s390_flic_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
dc->realize = kvm_s390_flic_realize;
|
||||
dc->unrealize = kvm_s390_flic_unrealize;
|
||||
dc->reset = kvm_s390_flic_reset;
|
||||
}
|
||||
|
||||
static const TypeInfo kvm_s390_flic_info = {
|
||||
.name = TYPE_KVM_S390_FLIC,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(KVMS390FLICState),
|
||||
.class_init = kvm_s390_flic_class_init,
|
||||
};
|
||||
|
||||
static void kvm_s390_flic_register_types(void)
|
||||
{
|
||||
type_register_static(&kvm_s390_flic_info);
|
||||
}
|
||||
|
||||
type_init(kvm_s390_flic_register_types)
|
||||
@@ -276,7 +276,7 @@ static bool vexpress_cfgctrl_read(arm_sysctl_state *s, unsigned int dcc,
|
||||
}
|
||||
break;
|
||||
case SYS_CFG_OSC:
|
||||
if (site == SYS_CFG_SITE_MB && device < sizeof(s->mb_clock)) {
|
||||
if (site == SYS_CFG_SITE_MB && device < ARRAY_SIZE(s->mb_clock)) {
|
||||
/* motherboard clock */
|
||||
*val = s->mb_clock[device];
|
||||
return true;
|
||||
@@ -324,7 +324,7 @@ static bool vexpress_cfgctrl_write(arm_sysctl_state *s, unsigned int dcc,
|
||||
|
||||
switch (function) {
|
||||
case SYS_CFG_OSC:
|
||||
if (site == SYS_CFG_SITE_MB && device < sizeof(s->mb_clock)) {
|
||||
if (site == SYS_CFG_SITE_MB && device < ARRAY_SIZE(s->mb_clock)) {
|
||||
/* motherboard clock */
|
||||
s->mb_clock[device] = val;
|
||||
return true;
|
||||
|
||||
@@ -176,7 +176,8 @@ static uint64_t stellaris_enet_read(void *opaque, hwaddr offset,
|
||||
return val;
|
||||
case 0x14: /* IA0 */
|
||||
return s->conf.macaddr.a[0] | (s->conf.macaddr.a[1] << 8)
|
||||
| (s->conf.macaddr.a[2] << 16) | (s->conf.macaddr.a[3] << 24);
|
||||
| (s->conf.macaddr.a[2] << 16)
|
||||
| ((uint32_t)s->conf.macaddr.a[3] << 24);
|
||||
case 0x18: /* IA1 */
|
||||
return s->conf.macaddr.a[4] | (s->conf.macaddr.a[5] << 8);
|
||||
case 0x1c: /* THR */
|
||||
|
||||
@@ -106,7 +106,7 @@ struct vhost_net *vhost_net_init(NetClientState *backend, int devfd,
|
||||
goto fail;
|
||||
}
|
||||
net->nc = backend;
|
||||
net->dev.backend_features = tap_has_vnet_hdr(backend) ? 0 :
|
||||
net->dev.backend_features = qemu_has_vnet_hdr(backend) ? 0 :
|
||||
(1 << VHOST_NET_F_VIRTIO_NET_HDR);
|
||||
net->backend = r;
|
||||
|
||||
@@ -117,8 +117,8 @@ struct vhost_net *vhost_net_init(NetClientState *backend, int devfd,
|
||||
if (r < 0) {
|
||||
goto fail;
|
||||
}
|
||||
if (!tap_has_vnet_hdr_len(backend,
|
||||
sizeof(struct virtio_net_hdr_mrg_rxbuf))) {
|
||||
if (!qemu_has_vnet_hdr_len(backend,
|
||||
sizeof(struct virtio_net_hdr_mrg_rxbuf))) {
|
||||
net->dev.features &= ~(1 << VIRTIO_NET_F_MRG_RXBUF);
|
||||
}
|
||||
if (~net->dev.features & net->dev.backend_features) {
|
||||
|
||||
@@ -325,11 +325,7 @@ static void peer_test_vnet_hdr(VirtIONet *n)
|
||||
return;
|
||||
}
|
||||
|
||||
if (nc->peer->info->type != NET_CLIENT_OPTIONS_KIND_TAP) {
|
||||
return;
|
||||
}
|
||||
|
||||
n->has_vnet_hdr = tap_has_vnet_hdr(nc->peer);
|
||||
n->has_vnet_hdr = qemu_has_vnet_hdr(nc->peer);
|
||||
}
|
||||
|
||||
static int peer_has_vnet_hdr(VirtIONet *n)
|
||||
@@ -342,7 +338,7 @@ static int peer_has_ufo(VirtIONet *n)
|
||||
if (!peer_has_vnet_hdr(n))
|
||||
return 0;
|
||||
|
||||
n->has_ufo = tap_has_ufo(qemu_get_queue(n->nic)->peer);
|
||||
n->has_ufo = qemu_has_ufo(qemu_get_queue(n->nic)->peer);
|
||||
|
||||
return n->has_ufo;
|
||||
}
|
||||
@@ -361,8 +357,8 @@ static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, int mergeable_rx_bufs)
|
||||
nc = qemu_get_subqueue(n->nic, i);
|
||||
|
||||
if (peer_has_vnet_hdr(n) &&
|
||||
tap_has_vnet_hdr_len(nc->peer, n->guest_hdr_len)) {
|
||||
tap_set_vnet_hdr_len(nc->peer, n->guest_hdr_len);
|
||||
qemu_has_vnet_hdr_len(nc->peer, n->guest_hdr_len)) {
|
||||
qemu_set_vnet_hdr_len(nc->peer, n->guest_hdr_len);
|
||||
n->host_hdr_len = n->guest_hdr_len;
|
||||
}
|
||||
}
|
||||
@@ -463,7 +459,7 @@ static uint32_t virtio_net_bad_features(VirtIODevice *vdev)
|
||||
|
||||
static void virtio_net_apply_guest_offloads(VirtIONet *n)
|
||||
{
|
||||
tap_set_offload(qemu_get_subqueue(n->nic, 0)->peer,
|
||||
qemu_set_offload(qemu_get_queue(n->nic)->peer,
|
||||
!!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_CSUM)),
|
||||
!!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_TSO4)),
|
||||
!!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_TSO6)),
|
||||
@@ -1544,7 +1540,7 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
|
||||
peer_test_vnet_hdr(n);
|
||||
if (peer_has_vnet_hdr(n)) {
|
||||
for (i = 0; i < n->max_queues; i++) {
|
||||
tap_using_vnet_hdr(qemu_get_subqueue(n->nic, i)->peer, true);
|
||||
qemu_using_vnet_hdr(qemu_get_subqueue(n->nic, i)->peer, true);
|
||||
}
|
||||
n->host_hdr_len = sizeof(struct virtio_net_hdr);
|
||||
} else {
|
||||
|
||||
@@ -1290,12 +1290,12 @@ static void vmxnet3_update_features(VMXNET3State *s)
|
||||
s->lro_supported, rxcso_supported,
|
||||
s->rx_vlan_stripping);
|
||||
if (s->peer_has_vhdr) {
|
||||
tap_set_offload(qemu_get_queue(s->nic)->peer,
|
||||
rxcso_supported,
|
||||
s->lro_supported,
|
||||
s->lro_supported,
|
||||
0,
|
||||
0);
|
||||
qemu_set_offload(qemu_get_queue(s->nic)->peer,
|
||||
rxcso_supported,
|
||||
s->lro_supported,
|
||||
s->lro_supported,
|
||||
0,
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1883,11 +1883,9 @@ static NetClientInfo net_vmxnet3_info = {
|
||||
|
||||
static bool vmxnet3_peer_has_vnet_hdr(VMXNET3State *s)
|
||||
{
|
||||
NetClientState *peer = qemu_get_queue(s->nic)->peer;
|
||||
NetClientState *nc = qemu_get_queue(s->nic);
|
||||
|
||||
if ((NULL != peer) &&
|
||||
(peer->info->type == NET_CLIENT_OPTIONS_KIND_TAP) &&
|
||||
tap_has_vnet_hdr(peer)) {
|
||||
if (qemu_has_vnet_hdr(nc->peer)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1935,10 +1933,10 @@ static void vmxnet3_net_init(VMXNET3State *s)
|
||||
s->lro_supported = false;
|
||||
|
||||
if (s->peer_has_vhdr) {
|
||||
tap_set_vnet_hdr_len(qemu_get_queue(s->nic)->peer,
|
||||
qemu_set_vnet_hdr_len(qemu_get_queue(s->nic)->peer,
|
||||
sizeof(struct virtio_net_hdr));
|
||||
|
||||
tap_using_vnet_hdr(qemu_get_queue(s->nic)->peer, 1);
|
||||
qemu_using_vnet_hdr(qemu_get_queue(s->nic)->peer, 1);
|
||||
}
|
||||
|
||||
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
|
||||
|
||||
@@ -21,13 +21,13 @@
|
||||
#include "hw/s390x/sclp.h"
|
||||
#include "hw/s390x/event-facility.h"
|
||||
|
||||
typedef struct EventTypesBus {
|
||||
typedef struct SCLPEventsBus {
|
||||
BusState qbus;
|
||||
} EventTypesBus;
|
||||
} SCLPEventsBus;
|
||||
|
||||
struct SCLPEventFacility {
|
||||
EventTypesBus sbus;
|
||||
DeviceState *qdev;
|
||||
SysBusDevice parent_obj;
|
||||
SCLPEventsBus sbus;
|
||||
/* guest' receive mask */
|
||||
unsigned int receive_mask;
|
||||
};
|
||||
@@ -291,7 +291,7 @@ static void sclp_events_bus_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
}
|
||||
|
||||
static const TypeInfo s390_sclp_events_bus_info = {
|
||||
static const TypeInfo sclp_events_bus_info = {
|
||||
.name = TYPE_SCLP_EVENTS_BUS,
|
||||
.parent = TYPE_BUS,
|
||||
.class_init = sclp_events_bus_class_init,
|
||||
@@ -299,7 +299,7 @@ static const TypeInfo s390_sclp_events_bus_info = {
|
||||
|
||||
static void command_handler(SCLPEventFacility *ef, SCCB *sccb, uint64_t code)
|
||||
{
|
||||
switch (code) {
|
||||
switch (code & SCLP_CMD_CODE_MASK) {
|
||||
case SCLP_CMD_READ_EVENT_DATA:
|
||||
read_event_data(ef, sccb);
|
||||
break;
|
||||
@@ -315,21 +315,26 @@ static void command_handler(SCLPEventFacility *ef, SCCB *sccb, uint64_t code)
|
||||
}
|
||||
}
|
||||
|
||||
static int init_event_facility(S390SCLPDevice *sdev)
|
||||
static const VMStateDescription vmstate_event_facility = {
|
||||
.name = "vmstate-event-facility",
|
||||
.version_id = 0,
|
||||
.minimum_version_id = 0,
|
||||
.minimum_version_id_old = 0,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT32(receive_mask, SCLPEventFacility),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static int init_event_facility(SCLPEventFacility *event_facility)
|
||||
{
|
||||
SCLPEventFacility *event_facility;
|
||||
DeviceState *sdev = DEVICE(event_facility);
|
||||
DeviceState *quiesce;
|
||||
|
||||
event_facility = g_malloc0(sizeof(SCLPEventFacility));
|
||||
sdev->ef = event_facility;
|
||||
sdev->sclp_command_handler = command_handler;
|
||||
sdev->event_pending = event_pending;
|
||||
|
||||
/* Spawn a new sclp-events facility */
|
||||
/* Spawn a new bus for SCLP events */
|
||||
qbus_create_inplace(&event_facility->sbus, sizeof(event_facility->sbus),
|
||||
TYPE_SCLP_EVENTS_BUS, DEVICE(sdev), NULL);
|
||||
TYPE_SCLP_EVENTS_BUS, sdev, NULL);
|
||||
event_facility->sbus.qbus.allow_hotplug = 0;
|
||||
event_facility->qdev = (DeviceState *) sdev;
|
||||
|
||||
quiesce = qdev_create(&event_facility->sbus.qbus, "sclpquiesce");
|
||||
if (!quiesce) {
|
||||
@@ -346,43 +351,57 @@ static int init_event_facility(S390SCLPDevice *sdev)
|
||||
|
||||
static void reset_event_facility(DeviceState *dev)
|
||||
{
|
||||
S390SCLPDevice *sdev = SCLP_S390_DEVICE(dev);
|
||||
SCLPEventFacility *sdev = EVENT_FACILITY(dev);
|
||||
|
||||
sdev->ef->receive_mask = 0;
|
||||
sdev->receive_mask = 0;
|
||||
}
|
||||
|
||||
static void init_event_facility_class(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
S390SCLPDeviceClass *k = SCLP_S390_DEVICE_CLASS(klass);
|
||||
SysBusDeviceClass *sbdc = SYS_BUS_DEVICE_CLASS(klass);
|
||||
DeviceClass *dc = DEVICE_CLASS(sbdc);
|
||||
SCLPEventFacilityClass *k = EVENT_FACILITY_CLASS(dc);
|
||||
|
||||
dc->reset = reset_event_facility;
|
||||
dc->vmsd = &vmstate_event_facility;
|
||||
k->init = init_event_facility;
|
||||
k->command_handler = command_handler;
|
||||
k->event_pending = event_pending;
|
||||
}
|
||||
|
||||
static const TypeInfo s390_sclp_event_facility_info = {
|
||||
.name = "s390-sclp-event-facility",
|
||||
.parent = TYPE_DEVICE_S390_SCLP,
|
||||
.instance_size = sizeof(S390SCLPDevice),
|
||||
static const TypeInfo sclp_event_facility_info = {
|
||||
.name = TYPE_SCLP_EVENT_FACILITY,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(SCLPEventFacility),
|
||||
.class_init = init_event_facility_class,
|
||||
.class_size = sizeof(SCLPEventFacilityClass),
|
||||
};
|
||||
|
||||
static int event_qdev_init(DeviceState *qdev)
|
||||
static void event_realize(DeviceState *qdev, Error **errp)
|
||||
{
|
||||
SCLPEvent *event = DO_UPCAST(SCLPEvent, qdev, qdev);
|
||||
SCLPEvent *event = SCLP_EVENT(qdev);
|
||||
SCLPEventClass *child = SCLP_EVENT_GET_CLASS(event);
|
||||
|
||||
return child->init(event);
|
||||
if (child->init) {
|
||||
int rc = child->init(event);
|
||||
if (rc < 0) {
|
||||
error_setg(errp, "SCLP event initialization failed.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int event_qdev_exit(DeviceState *qdev)
|
||||
static void event_unrealize(DeviceState *qdev, Error **errp)
|
||||
{
|
||||
SCLPEvent *event = DO_UPCAST(SCLPEvent, qdev, qdev);
|
||||
SCLPEvent *event = SCLP_EVENT(qdev);
|
||||
SCLPEventClass *child = SCLP_EVENT_GET_CLASS(event);
|
||||
if (child->exit) {
|
||||
child->exit(event);
|
||||
int rc = child->exit(event);
|
||||
if (rc < 0) {
|
||||
error_setg(errp, "SCLP event exit failed.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void event_class_init(ObjectClass *klass, void *data)
|
||||
@@ -391,11 +410,11 @@ static void event_class_init(ObjectClass *klass, void *data)
|
||||
|
||||
dc->bus_type = TYPE_SCLP_EVENTS_BUS;
|
||||
dc->unplug = qdev_simple_unplug_cb;
|
||||
dc->init = event_qdev_init;
|
||||
dc->exit = event_qdev_exit;
|
||||
dc->realize = event_realize;
|
||||
dc->unrealize = event_unrealize;
|
||||
}
|
||||
|
||||
static const TypeInfo s390_sclp_event_type_info = {
|
||||
static const TypeInfo sclp_event_type_info = {
|
||||
.name = TYPE_SCLP_EVENT,
|
||||
.parent = TYPE_DEVICE,
|
||||
.instance_size = sizeof(SCLPEvent),
|
||||
@@ -406,9 +425,9 @@ static const TypeInfo s390_sclp_event_type_info = {
|
||||
|
||||
static void register_types(void)
|
||||
{
|
||||
type_register_static(&s390_sclp_events_bus_info);
|
||||
type_register_static(&s390_sclp_event_facility_info);
|
||||
type_register_static(&s390_sclp_event_type_info);
|
||||
type_register_static(&sclp_events_bus_info);
|
||||
type_register_static(&sclp_event_facility_info);
|
||||
type_register_static(&sclp_event_type_info);
|
||||
}
|
||||
|
||||
type_init(register_types)
|
||||
|
||||
@@ -95,7 +95,8 @@ static int s390_ipl_init(SysBusDevice *dev)
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
kernel_size = load_elf(ipl->kernel, NULL, NULL, NULL, NULL,
|
||||
uint64_t pentry = KERN_IMAGE_START;
|
||||
kernel_size = load_elf(ipl->kernel, NULL, NULL, &pentry, NULL,
|
||||
NULL, 1, ELF_MACHINE, 0);
|
||||
if (kernel_size == -1) {
|
||||
kernel_size = load_image_targphys(ipl->kernel, 0, ram_size);
|
||||
@@ -104,15 +105,19 @@ static int s390_ipl_init(SysBusDevice *dev)
|
||||
fprintf(stderr, "could not load kernel '%s'\n", ipl->kernel);
|
||||
return -1;
|
||||
}
|
||||
/* we have to overwrite values in the kernel image, which are "rom" */
|
||||
strcpy(rom_ptr(KERN_PARM_AREA), ipl->cmdline);
|
||||
|
||||
/*
|
||||
* we can not rely on the ELF entry point, since up to 3.2 this
|
||||
* value was 0x800 (the SALIPL loader) and it wont work. For
|
||||
* all (Linux) cases 0x10000 (KERN_IMAGE_START) should be fine.
|
||||
* Is it a Linux kernel (starting at 0x10000)? If yes, we fill in the
|
||||
* kernel parameters here as well. Note: For old kernels (up to 3.2)
|
||||
* we can not rely on the ELF entry point - it was 0x800 (the SALIPL
|
||||
* loader) and it won't work. For this case we force it to 0x10000, too.
|
||||
*/
|
||||
ipl->start_addr = KERN_IMAGE_START;
|
||||
if (pentry == KERN_IMAGE_START || pentry == 0x800) {
|
||||
ipl->start_addr = KERN_IMAGE_START;
|
||||
/* Overwrite parameters in the kernel image, which are "rom" */
|
||||
strcpy(rom_ptr(KERN_PARM_AREA), ipl->cmdline);
|
||||
} else {
|
||||
ipl->start_addr = pentry;
|
||||
}
|
||||
}
|
||||
if (ipl->initrd) {
|
||||
ram_addr_t initrd_offset;
|
||||
|
||||
@@ -13,13 +13,14 @@
|
||||
#include "exec/address-spaces.h"
|
||||
#include "s390-virtio.h"
|
||||
#include "hw/s390x/sclp.h"
|
||||
#include "hw/s390x/s390_flic.h"
|
||||
#include "ioinst.h"
|
||||
#include "css.h"
|
||||
#include "virtio-ccw.h"
|
||||
|
||||
void io_subsystem_reset(void)
|
||||
{
|
||||
DeviceState *css, *sclp;
|
||||
DeviceState *css, *sclp, *flic;
|
||||
|
||||
css = DEVICE(object_resolve_path_type("", "virtual-css-bridge", NULL));
|
||||
if (css) {
|
||||
@@ -30,6 +31,10 @@ void io_subsystem_reset(void)
|
||||
if (sclp) {
|
||||
qdev_reset_all(sclp);
|
||||
}
|
||||
flic = DEVICE(object_resolve_path_type("", "s390-flic", NULL));
|
||||
if (flic) {
|
||||
qdev_reset_all(flic);
|
||||
}
|
||||
}
|
||||
|
||||
static int virtio_ccw_hcall_notify(const uint64_t *args)
|
||||
@@ -99,6 +104,7 @@ static void ccw_init(QEMUMachineInitArgs *args)
|
||||
s390_sclp_init();
|
||||
s390_init_ipl_dev(args->kernel_filename, args->kernel_cmdline,
|
||||
args->initrd_filename, "s390-ccw.img");
|
||||
s390_flic_init();
|
||||
|
||||
/* register hypercalls */
|
||||
virtio_ccw_register_hcalls();
|
||||
|
||||
@@ -26,11 +26,15 @@ void s390_register_virtio_hypercall(uint64_t code, s390_virtio_fn fn)
|
||||
|
||||
int s390_virtio_hypercall(CPUS390XState *env)
|
||||
{
|
||||
s390_virtio_fn fn = s390_diag500_table[env->regs[1]];
|
||||
s390_virtio_fn fn;
|
||||
|
||||
if (!fn) {
|
||||
return -EINVAL;
|
||||
if (env->regs[1] < MAX_DIAG_SUBCODES) {
|
||||
fn = s390_diag500_table[env->regs[1]];
|
||||
if (fn) {
|
||||
env->regs[2] = fn(&env->regs[2]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return fn(&env->regs[2]);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
|
||||
#include "hw/s390x/s390-virtio-bus.h"
|
||||
#include "hw/s390x/sclp.h"
|
||||
#include "hw/s390x/s390_flic.h"
|
||||
#include "hw/s390x/s390-virtio.h"
|
||||
|
||||
//#define DEBUG_S390
|
||||
@@ -251,6 +252,7 @@ static void s390_init(QEMUMachineInitArgs *args)
|
||||
s390_sclp_init();
|
||||
s390_init_ipl_dev(args->kernel_filename, args->kernel_cmdline,
|
||||
args->initrd_filename, ZIPL_FILENAME);
|
||||
s390_flic_init();
|
||||
|
||||
/* register hypercalls */
|
||||
s390_virtio_register_hcalls();
|
||||
|
||||
@@ -18,11 +18,12 @@
|
||||
#include "sysemu/sysemu.h"
|
||||
|
||||
#include "hw/s390x/sclp.h"
|
||||
#include "hw/s390x/event-facility.h"
|
||||
|
||||
static inline S390SCLPDevice *get_event_facility(void)
|
||||
static inline SCLPEventFacility *get_event_facility(void)
|
||||
{
|
||||
ObjectProperty *op = object_property_find(qdev_get_machine(),
|
||||
"s390-sclp-event-facility",
|
||||
TYPE_SCLP_EVENT_FACILITY,
|
||||
NULL);
|
||||
assert(op);
|
||||
return op->opaque;
|
||||
@@ -89,9 +90,10 @@ static void sclp_read_cpu_info(SCCB *sccb)
|
||||
sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION);
|
||||
}
|
||||
|
||||
static void sclp_execute(SCCB *sccb, uint64_t code)
|
||||
static void sclp_execute(SCCB *sccb, uint32_t code)
|
||||
{
|
||||
S390SCLPDevice *sdev = get_event_facility();
|
||||
SCLPEventFacility *ef = get_event_facility();
|
||||
SCLPEventFacilityClass *efc = EVENT_FACILITY_GET_CLASS(ef);
|
||||
|
||||
switch (code & SCLP_CMD_CODE_MASK) {
|
||||
case SCLP_CMDW_READ_SCP_INFO:
|
||||
@@ -102,12 +104,12 @@ static void sclp_execute(SCCB *sccb, uint64_t code)
|
||||
sclp_read_cpu_info(sccb);
|
||||
break;
|
||||
default:
|
||||
sdev->sclp_command_handler(sdev->ef, sccb, code);
|
||||
efc->command_handler(ef, sccb, code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int sclp_service_call(uint32_t sccb, uint64_t code)
|
||||
int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code)
|
||||
{
|
||||
int r = 0;
|
||||
SCCB work_sccb;
|
||||
@@ -115,11 +117,16 @@ int sclp_service_call(uint32_t sccb, uint64_t code)
|
||||
hwaddr sccb_len = sizeof(SCCB);
|
||||
|
||||
/* first some basic checks on program checks */
|
||||
if (env->psw.mask & PSW_MASK_PSTATE) {
|
||||
r = -PGM_PRIVILEGED;
|
||||
goto out;
|
||||
}
|
||||
if (cpu_physical_memory_is_io(sccb)) {
|
||||
r = -PGM_ADDRESSING;
|
||||
goto out;
|
||||
}
|
||||
if (sccb & ~0x7ffffff8ul) {
|
||||
if ((sccb & ~0x1fffUL) == 0 || (sccb & ~0x1fffUL) == env->psa
|
||||
|| (sccb & ~0x7ffffff8UL) != 0) {
|
||||
r = -PGM_SPECIFICATION;
|
||||
goto out;
|
||||
}
|
||||
@@ -151,11 +158,13 @@ out:
|
||||
|
||||
void sclp_service_interrupt(uint32_t sccb)
|
||||
{
|
||||
S390SCLPDevice *sdev = get_event_facility();
|
||||
SCLPEventFacility *ef = get_event_facility();
|
||||
SCLPEventFacilityClass *efc = EVENT_FACILITY_GET_CLASS(ef);
|
||||
|
||||
uint32_t param = sccb & ~3;
|
||||
|
||||
/* Indicate whether an event is still pending */
|
||||
param |= sdev->event_pending(sdev->ef) ? 1 : 0;
|
||||
param |= efc->event_pending(ef) ? 1 : 0;
|
||||
|
||||
if (!param) {
|
||||
/* No need to send an interrupt, there's nothing to be notified about */
|
||||
@@ -168,47 +177,9 @@ void sclp_service_interrupt(uint32_t sccb)
|
||||
|
||||
void s390_sclp_init(void)
|
||||
{
|
||||
DeviceState *dev = qdev_create(NULL, "s390-sclp-event-facility");
|
||||
DeviceState *dev = qdev_create(NULL, TYPE_SCLP_EVENT_FACILITY);
|
||||
|
||||
object_property_add_child(qdev_get_machine(), "s390-sclp-event-facility",
|
||||
object_property_add_child(qdev_get_machine(), TYPE_SCLP_EVENT_FACILITY,
|
||||
OBJECT(dev), NULL);
|
||||
qdev_init_nofail(dev);
|
||||
}
|
||||
|
||||
static int s390_sclp_dev_init(SysBusDevice *dev)
|
||||
{
|
||||
int r;
|
||||
S390SCLPDevice *sdev = (S390SCLPDevice *)dev;
|
||||
S390SCLPDeviceClass *sclp = SCLP_S390_DEVICE_GET_CLASS(dev);
|
||||
|
||||
r = sclp->init(sdev);
|
||||
if (!r) {
|
||||
assert(sdev->event_pending);
|
||||
assert(sdev->sclp_command_handler);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void s390_sclp_device_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
SysBusDeviceClass *dc = SYS_BUS_DEVICE_CLASS(klass);
|
||||
|
||||
dc->init = s390_sclp_dev_init;
|
||||
}
|
||||
|
||||
static const TypeInfo s390_sclp_device_info = {
|
||||
.name = TYPE_DEVICE_S390_SCLP,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(S390SCLPDevice),
|
||||
.class_init = s390_sclp_device_class_init,
|
||||
.class_size = sizeof(S390SCLPDeviceClass),
|
||||
.abstract = true,
|
||||
};
|
||||
|
||||
static void s390_sclp_register_types(void)
|
||||
{
|
||||
type_register_static(&s390_sclp_device_info);
|
||||
}
|
||||
|
||||
type_init(s390_sclp_register_types)
|
||||
|
||||
@@ -909,7 +909,7 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
|
||||
case VERIFY_16:
|
||||
if ((buf[1] & 2) == 0) {
|
||||
cmd->xfer = 0;
|
||||
} else if ((buf[1] & 4) == 1) {
|
||||
} else if ((buf[1] & 4) != 0) {
|
||||
cmd->xfer = 1;
|
||||
}
|
||||
cmd->xfer *= dev->blocksize;
|
||||
@@ -1367,6 +1367,11 @@ const struct SCSISense sense_code_WRITE_PROTECTED = {
|
||||
.key = DATA_PROTECT, .asc = 0x27, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Data Protection, Space Allocation Failed Write Protect */
|
||||
const struct SCSISense sense_code_SPACE_ALLOC_FAILED = {
|
||||
.key = DATA_PROTECT, .asc = 0x27, .ascq = 0x07
|
||||
};
|
||||
|
||||
/*
|
||||
* scsi_build_sense
|
||||
*
|
||||
|
||||
@@ -75,6 +75,8 @@ struct SCSIDiskState
|
||||
bool media_event;
|
||||
bool eject_request;
|
||||
uint64_t wwn;
|
||||
uint64_t port_wwn;
|
||||
uint16_t port_index;
|
||||
uint64_t max_unmap_size;
|
||||
QEMUBH *bh;
|
||||
char *version;
|
||||
@@ -428,6 +430,9 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error)
|
||||
case EINVAL:
|
||||
scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
|
||||
break;
|
||||
case ENOSPC:
|
||||
scsi_check_condition(r, SENSE_CODE(SPACE_ALLOC_FAILED));
|
||||
break;
|
||||
default:
|
||||
scsi_check_condition(r, SENSE_CODE(IO_ERROR));
|
||||
break;
|
||||
@@ -617,6 +622,24 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
|
||||
stq_be_p(&outbuf[buflen], s->wwn);
|
||||
buflen += 8;
|
||||
}
|
||||
|
||||
if (s->port_wwn) {
|
||||
outbuf[buflen++] = 0x61; // SAS / Binary
|
||||
outbuf[buflen++] = 0x93; // PIV / Target port / NAA
|
||||
outbuf[buflen++] = 0; // reserved
|
||||
outbuf[buflen++] = 8;
|
||||
stq_be_p(&outbuf[buflen], s->port_wwn);
|
||||
buflen += 8;
|
||||
}
|
||||
|
||||
if (s->port_index) {
|
||||
outbuf[buflen++] = 0x61; // SAS / Binary
|
||||
outbuf[buflen++] = 0x94; // PIV / Target port / relative target port
|
||||
outbuf[buflen++] = 0; // reserved
|
||||
outbuf[buflen++] = 4;
|
||||
stw_be_p(&outbuf[buflen + 2], s->port_index);
|
||||
buflen += 4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0xb0: /* block limits */
|
||||
@@ -2536,6 +2559,8 @@ static Property scsi_hd_properties[] = {
|
||||
DEFINE_PROP_BIT("dpofua", SCSIDiskState, features,
|
||||
SCSI_DISK_F_DPOFUA, false),
|
||||
DEFINE_PROP_UINT64("wwn", SCSIDiskState, wwn, 0),
|
||||
DEFINE_PROP_UINT64("port_wwn", SCSIDiskState, port_wwn, 0),
|
||||
DEFINE_PROP_UINT16("port_index", SCSIDiskState, port_index, 0),
|
||||
DEFINE_PROP_UINT64("max_unmap_size", SCSIDiskState, max_unmap_size,
|
||||
DEFAULT_MAX_UNMAP_SIZE),
|
||||
DEFINE_BLOCK_CHS_PROPERTIES(SCSIDiskState, qdev.conf),
|
||||
@@ -2584,6 +2609,8 @@ static const TypeInfo scsi_hd_info = {
|
||||
static Property scsi_cd_properties[] = {
|
||||
DEFINE_SCSI_DISK_PROPERTIES(),
|
||||
DEFINE_PROP_UINT64("wwn", SCSIDiskState, wwn, 0),
|
||||
DEFINE_PROP_UINT64("port_wwn", SCSIDiskState, port_wwn, 0),
|
||||
DEFINE_PROP_UINT16("port_index", SCSIDiskState, port_index, 0),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
@@ -2647,6 +2674,8 @@ static Property scsi_disk_properties[] = {
|
||||
DEFINE_PROP_BIT("dpofua", SCSIDiskState, features,
|
||||
SCSI_DISK_F_DPOFUA, false),
|
||||
DEFINE_PROP_UINT64("wwn", SCSIDiskState, wwn, 0),
|
||||
DEFINE_PROP_UINT64("port_wwn", SCSIDiskState, port_wwn, 0),
|
||||
DEFINE_PROP_UINT16("port_index", SCSIDiskState, port_index, 0),
|
||||
DEFINE_PROP_UINT64("max_unmap_size", SCSIDiskState, max_unmap_size,
|
||||
DEFAULT_MAX_UNMAP_SIZE),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
|
||||
@@ -37,8 +37,6 @@ do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
|
||||
#include <scsi/sg.h>
|
||||
#include "block/scsi.h"
|
||||
|
||||
#define SCSI_SENSE_BUF_SIZE 96
|
||||
|
||||
#define SG_ERR_DRIVER_TIMEOUT 0x06
|
||||
#define SG_ERR_DRIVER_SENSE 0x08
|
||||
|
||||
|
||||
@@ -60,7 +60,6 @@
|
||||
#define VSCSI_MAX_SECTORS 4096
|
||||
#define VSCSI_REQ_LIMIT 24
|
||||
|
||||
#define SCSI_SENSE_BUF_SIZE 96
|
||||
#define SRP_RSP_SENSE_DATA_LEN 18
|
||||
|
||||
typedef union vscsi_crq {
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "hw/sysbus.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "hw/sparc/sun4m.h"
|
||||
#include "hw/timer/m48t59.h"
|
||||
@@ -561,6 +562,31 @@ static void tcx_init(hwaddr addr, int vram_size, int width,
|
||||
}
|
||||
}
|
||||
|
||||
static void cg3_init(hwaddr addr, qemu_irq irq, int vram_size, int width,
|
||||
int height, int depth)
|
||||
{
|
||||
DeviceState *dev;
|
||||
SysBusDevice *s;
|
||||
|
||||
dev = qdev_create(NULL, "cgthree");
|
||||
qdev_prop_set_uint32(dev, "vram-size", vram_size);
|
||||
qdev_prop_set_uint16(dev, "width", width);
|
||||
qdev_prop_set_uint16(dev, "height", height);
|
||||
qdev_prop_set_uint16(dev, "depth", depth);
|
||||
qdev_prop_set_uint64(dev, "prom-addr", addr);
|
||||
qdev_init_nofail(dev);
|
||||
s = SYS_BUS_DEVICE(dev);
|
||||
|
||||
/* FCode ROM */
|
||||
sysbus_mmio_map(s, 0, addr);
|
||||
/* DAC */
|
||||
sysbus_mmio_map(s, 1, addr + 0x400000ULL);
|
||||
/* 8-bit plane */
|
||||
sysbus_mmio_map(s, 2, addr + 0x800000ULL);
|
||||
|
||||
sysbus_connect_irq(s, 0, irq);
|
||||
}
|
||||
|
||||
/* NCR89C100/MACIO Internal ID register */
|
||||
|
||||
#define TYPE_MACIO_ID_REGISTER "macio_idreg"
|
||||
@@ -914,13 +940,43 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef,
|
||||
slavio_irq[16], iommu, &ledma_irq, 1);
|
||||
|
||||
if (graphic_depth != 8 && graphic_depth != 24) {
|
||||
fprintf(stderr, "qemu: Unsupported depth: %d\n", graphic_depth);
|
||||
error_report("Unsupported depth: %d", graphic_depth);
|
||||
exit (1);
|
||||
}
|
||||
num_vsimms = 0;
|
||||
if (num_vsimms == 0) {
|
||||
tcx_init(hwdef->tcx_base, 0x00100000, graphic_width, graphic_height,
|
||||
graphic_depth);
|
||||
if (vga_interface_type == VGA_CG3) {
|
||||
if (graphic_depth != 8) {
|
||||
error_report("Unsupported depth: %d", graphic_depth);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!(graphic_width == 1024 && graphic_height == 768) &&
|
||||
!(graphic_width == 1152 && graphic_height == 900)) {
|
||||
error_report("Unsupported resolution: %d x %d", graphic_width,
|
||||
graphic_height);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* sbus irq 5 */
|
||||
cg3_init(hwdef->tcx_base, slavio_irq[11], 0x00100000,
|
||||
graphic_width, graphic_height, graphic_depth);
|
||||
} else {
|
||||
/* If no display specified, default to TCX */
|
||||
if (graphic_depth != 8 && graphic_depth != 24) {
|
||||
error_report("Unsupported depth: %d", graphic_depth);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!(graphic_width == 1024 && graphic_height == 768)) {
|
||||
error_report("Unsupported resolution: %d x %d",
|
||||
graphic_width, graphic_height);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
tcx_init(hwdef->tcx_base, 0x00100000, graphic_width, graphic_height,
|
||||
graphic_depth);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = num_vsimms; i < MAX_VSIMMS; i++) {
|
||||
|
||||
@@ -320,6 +320,7 @@ static uint64_t icp_pit_read(void *opaque, hwaddr offset,
|
||||
n = offset >> 8;
|
||||
if (n > 2) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad timer %d\n", __func__, n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return arm_timer_read(s->timer[n], offset & 0xff);
|
||||
@@ -334,6 +335,7 @@ static void icp_pit_write(void *opaque, hwaddr offset,
|
||||
n = offset >> 8;
|
||||
if (n > 2) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad timer %d\n", __func__, n);
|
||||
return;
|
||||
}
|
||||
|
||||
arm_timer_write(s->timer[n], offset & 0xff, value);
|
||||
|
||||
@@ -51,7 +51,7 @@ typedef struct CPUTimerState {
|
||||
ptimer_state *timer;
|
||||
uint32_t count, counthigh, reached;
|
||||
/* processor only */
|
||||
uint32_t running;
|
||||
uint32_t run;
|
||||
uint64_t limit;
|
||||
} CPUTimerState;
|
||||
|
||||
@@ -177,7 +177,7 @@ static uint64_t slavio_timer_mem_readl(void *opaque, hwaddr addr,
|
||||
// only available in processor counter/timer
|
||||
// read start/stop status
|
||||
if (timer_index > 0) {
|
||||
ret = t->running;
|
||||
ret = t->run;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
@@ -260,16 +260,15 @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
|
||||
case TIMER_STATUS:
|
||||
if (slavio_timer_is_user(tc)) {
|
||||
// start/stop user counter
|
||||
if ((val & 1) && !t->running) {
|
||||
if (val & 1) {
|
||||
trace_slavio_timer_mem_writel_status_start(timer_index);
|
||||
ptimer_run(t->timer, 0);
|
||||
t->running = 1;
|
||||
} else if (!(val & 1) && t->running) {
|
||||
} else {
|
||||
trace_slavio_timer_mem_writel_status_stop(timer_index);
|
||||
ptimer_stop(t->timer);
|
||||
t->running = 0;
|
||||
}
|
||||
}
|
||||
t->run = val & 1;
|
||||
break;
|
||||
case TIMER_MODE:
|
||||
if (timer_index == 0) {
|
||||
@@ -284,8 +283,9 @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
|
||||
if (val & processor) { // counter -> user timer
|
||||
qemu_irq_lower(curr_timer->irq);
|
||||
// counters are always running
|
||||
ptimer_stop(curr_timer->timer);
|
||||
curr_timer->running = 0;
|
||||
if (!curr_timer->run) {
|
||||
ptimer_stop(curr_timer->timer);
|
||||
}
|
||||
// user timer limit is always the same
|
||||
curr_timer->limit = TIMER_MAX_COUNT64;
|
||||
ptimer_set_limit(curr_timer->timer,
|
||||
@@ -296,13 +296,8 @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
|
||||
s->cputimer_mode |= processor;
|
||||
trace_slavio_timer_mem_writel_mode_user(timer_index);
|
||||
} else { // user timer -> counter
|
||||
// stop the user timer if it is running
|
||||
if (curr_timer->running) {
|
||||
ptimer_stop(curr_timer->timer);
|
||||
}
|
||||
// start the counter
|
||||
ptimer_run(curr_timer->timer, 0);
|
||||
curr_timer->running = 1;
|
||||
// clear this processors user timer bit in config
|
||||
// register
|
||||
s->cputimer_mode &= ~processor;
|
||||
@@ -340,7 +335,7 @@ static const VMStateDescription vmstate_timer = {
|
||||
VMSTATE_UINT32(count, CPUTimerState),
|
||||
VMSTATE_UINT32(counthigh, CPUTimerState),
|
||||
VMSTATE_UINT32(reached, CPUTimerState),
|
||||
VMSTATE_UINT32(running, CPUTimerState),
|
||||
VMSTATE_UINT32(run , CPUTimerState),
|
||||
VMSTATE_PTIMER(timer, CPUTimerState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
@@ -373,7 +368,7 @@ static void slavio_timer_reset(DeviceState *d)
|
||||
ptimer_set_limit(curr_timer->timer,
|
||||
LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
|
||||
ptimer_run(curr_timer->timer, 0);
|
||||
curr_timer->running = 1;
|
||||
curr_timer->run = 1;
|
||||
}
|
||||
}
|
||||
s->cputimer_mode = 0;
|
||||
|
||||
@@ -98,7 +98,7 @@ static void puv3_load_kernel(const char *kernel_filename)
|
||||
}
|
||||
|
||||
/* cheat curses that we have a graphic console, only under ocd console */
|
||||
graphic_console_init(NULL, &no_ops, NULL);
|
||||
graphic_console_init(NULL, 0, &no_ops, NULL);
|
||||
}
|
||||
|
||||
static void puv3_init(QEMUMachineInitArgs *args)
|
||||
|
||||
@@ -104,6 +104,7 @@ typedef struct GICState {
|
||||
MemoryRegion cpuiomem[GIC_NCPU + 1]; /* CPU interfaces */
|
||||
uint32_t num_irq;
|
||||
uint32_t revision;
|
||||
int dev_fd; /* kvm device fd if backed by kvm vgic support */
|
||||
} GICState;
|
||||
|
||||
#define TYPE_ARM_GIC_COMMON "arm_gic_common"
|
||||
|
||||
@@ -62,6 +62,8 @@ Sun_init_header(struct Sun_nvram *header, const uint8_t *macaddr, int machine_id
|
||||
header->type = 1;
|
||||
header->machine_id = machine_id & 0xff;
|
||||
memcpy(&header->macaddr, macaddr, 6);
|
||||
memcpy(&header->hostid , &macaddr[3], 3);
|
||||
|
||||
/* Calculate checksum */
|
||||
tmp = 0;
|
||||
tmpptr = (uint8_t *)header;
|
||||
|
||||
@@ -176,4 +176,23 @@ typedef struct SCLPEventClass {
|
||||
bool (*can_handle_event)(uint8_t type);
|
||||
} SCLPEventClass;
|
||||
|
||||
#define TYPE_SCLP_EVENT_FACILITY "s390-sclp-event-facility"
|
||||
#define EVENT_FACILITY(obj) \
|
||||
OBJECT_CHECK(SCLPEventFacility, (obj), TYPE_SCLP_EVENT_FACILITY)
|
||||
#define EVENT_FACILITY_CLASS(klass) \
|
||||
OBJECT_CLASS_CHECK(SCLPEventFacilityClass, (klass), \
|
||||
TYPE_SCLP_EVENT_FACILITY)
|
||||
#define EVENT_FACILITY_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(SCLPEventFacilityClass, (obj), \
|
||||
TYPE_SCLP_EVENT_FACILITY)
|
||||
|
||||
typedef struct SCLPEventFacility SCLPEventFacility;
|
||||
|
||||
typedef struct SCLPEventFacilityClass {
|
||||
DeviceClass parent_class;
|
||||
int (*init)(SCLPEventFacility *ef);
|
||||
void (*command_handler)(SCLPEventFacility *ef, SCCB *sccb, uint64_t code);
|
||||
bool (*event_pending)(SCLPEventFacility *ef);
|
||||
} SCLPEventFacilityClass;
|
||||
|
||||
#endif
|
||||
|
||||
33
include/hw/s390x/s390_flic.h
Normal file
33
include/hw/s390x/s390_flic.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* QEMU S390x KVM floating interrupt controller (flic)
|
||||
*
|
||||
* Copyright 2014 IBM Corp.
|
||||
* Author(s): Jens Freimann <jfrei@linux.vnet.ibm.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or (at
|
||||
* your option) any later version. See the COPYING file in the top-level
|
||||
* directory.
|
||||
*/
|
||||
|
||||
#ifndef __KVM_S390_FLIC_H
|
||||
#define __KVM_S390_FLIC_H
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
#define TYPE_KVM_S390_FLIC "s390-flic"
|
||||
#define KVM_S390_FLIC(obj) \
|
||||
OBJECT_CHECK(KVMS390FLICState, (obj), TYPE_KVM_S390_FLIC)
|
||||
|
||||
typedef struct KVMS390FLICState {
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
uint32_t fd;
|
||||
} KVMS390FLICState;
|
||||
|
||||
#ifdef CONFIG_KVM
|
||||
void s390_flic_init(void);
|
||||
#else
|
||||
static inline void s390_flic_init(void) { }
|
||||
#endif
|
||||
|
||||
#endif /* __KVM_S390_FLIC_H */
|
||||
@@ -161,30 +161,6 @@ static inline int sccb_data_len(SCCB *sccb)
|
||||
return be16_to_cpu(sccb->h.length) - sizeof(sccb->h);
|
||||
}
|
||||
|
||||
#define TYPE_DEVICE_S390_SCLP "s390-sclp-device"
|
||||
#define SCLP_S390_DEVICE(obj) \
|
||||
OBJECT_CHECK(S390SCLPDevice, (obj), TYPE_DEVICE_S390_SCLP)
|
||||
#define SCLP_S390_DEVICE_CLASS(klass) \
|
||||
OBJECT_CLASS_CHECK(S390SCLPDeviceClass, (klass), \
|
||||
TYPE_DEVICE_S390_SCLP)
|
||||
#define SCLP_S390_DEVICE_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(S390SCLPDeviceClass, (obj), \
|
||||
TYPE_DEVICE_S390_SCLP)
|
||||
|
||||
typedef struct SCLPEventFacility SCLPEventFacility;
|
||||
|
||||
typedef struct S390SCLPDevice {
|
||||
SysBusDevice busdev;
|
||||
SCLPEventFacility *ef;
|
||||
void (*sclp_command_handler)(SCLPEventFacility *ef, SCCB *sccb,
|
||||
uint64_t code);
|
||||
bool (*event_pending)(SCLPEventFacility *ef);
|
||||
} S390SCLPDevice;
|
||||
|
||||
typedef struct S390SCLPDeviceClass {
|
||||
DeviceClass qdev;
|
||||
int (*init)(S390SCLPDevice *sdev);
|
||||
} S390SCLPDeviceClass;
|
||||
|
||||
void s390_sclp_init(void);
|
||||
void sclp_service_interrupt(uint32_t sccb);
|
||||
|
||||
@@ -31,7 +31,7 @@ typedef struct SCSISense {
|
||||
uint8_t ascq;
|
||||
} SCSISense;
|
||||
|
||||
#define SCSI_SENSE_BUF_SIZE 96
|
||||
#define SCSI_SENSE_BUF_SIZE 252
|
||||
|
||||
struct SCSICommand {
|
||||
uint8_t buf[SCSI_CMD_BUF_SIZE];
|
||||
@@ -223,6 +223,8 @@ extern const struct SCSISense sense_code_REPORTED_LUNS_CHANGED;
|
||||
extern const struct SCSISense sense_code_DEVICE_INTERNAL_RESET;
|
||||
/* Data Protection, Write Protected */
|
||||
extern const struct SCSISense sense_code_WRITE_PROTECTED;
|
||||
/* Data Protection, Space Allocation Failed Write Protect */
|
||||
extern const struct SCSISense sense_code_SPACE_ALLOC_FAILED;
|
||||
|
||||
#define SENSE_CODE(x) sense_code_ ## x
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ uint8_t *get_cached_data(const PageCache *cache, uint64_t addr);
|
||||
* @addr: page address
|
||||
* @pdata: pointer to the page
|
||||
*/
|
||||
int cache_insert(PageCache *cache, uint64_t addr, uint8_t *pdata);
|
||||
int cache_insert(PageCache *cache, uint64_t addr, const uint8_t *pdata);
|
||||
|
||||
/**
|
||||
* cache_resize: resize the page cache. In case of size reduction the extra
|
||||
|
||||
@@ -50,6 +50,12 @@ typedef void (NetCleanup) (NetClientState *);
|
||||
typedef void (LinkStatusChanged)(NetClientState *);
|
||||
typedef void (NetClientDestructor)(NetClientState *);
|
||||
typedef RxFilterInfo *(QueryRxFilter)(NetClientState *);
|
||||
typedef bool (HasUfo)(NetClientState *);
|
||||
typedef bool (HasVnetHdr)(NetClientState *);
|
||||
typedef bool (HasVnetHdrLen)(NetClientState *, int);
|
||||
typedef void (UsingVnetHdr)(NetClientState *, bool);
|
||||
typedef void (SetOffload)(NetClientState *, int, int, int, int, int);
|
||||
typedef void (SetVnetHdrLen)(NetClientState *, int);
|
||||
|
||||
typedef struct NetClientInfo {
|
||||
NetClientOptionsKind type;
|
||||
@@ -62,6 +68,12 @@ typedef struct NetClientInfo {
|
||||
LinkStatusChanged *link_status_changed;
|
||||
QueryRxFilter *query_rx_filter;
|
||||
NetPoll *poll;
|
||||
HasUfo *has_ufo;
|
||||
HasVnetHdr *has_vnet_hdr;
|
||||
HasVnetHdrLen *has_vnet_hdr_len;
|
||||
UsingVnetHdr *using_vnet_hdr;
|
||||
SetOffload *set_offload;
|
||||
SetVnetHdrLen *set_vnet_hdr_len;
|
||||
} NetClientInfo;
|
||||
|
||||
struct NetClientState {
|
||||
@@ -120,6 +132,13 @@ ssize_t qemu_send_packet_async(NetClientState *nc, const uint8_t *buf,
|
||||
void qemu_purge_queued_packets(NetClientState *nc);
|
||||
void qemu_flush_queued_packets(NetClientState *nc);
|
||||
void qemu_format_nic_info_str(NetClientState *nc, uint8_t macaddr[6]);
|
||||
bool qemu_has_ufo(NetClientState *nc);
|
||||
bool qemu_has_vnet_hdr(NetClientState *nc);
|
||||
bool qemu_has_vnet_hdr_len(NetClientState *nc, int len);
|
||||
void qemu_using_vnet_hdr(NetClientState *nc, bool enable);
|
||||
void qemu_set_offload(NetClientState *nc, int csum, int tso4, int tso6,
|
||||
int ecn, int ufo);
|
||||
void qemu_set_vnet_hdr_len(NetClientState *nc, int len);
|
||||
void qemu_macaddr_default_if_unset(MACAddr *macaddr);
|
||||
int qemu_show_nic_models(const char *arg, const char *const *models);
|
||||
void qemu_check_nic_model(NICInfo *nd, const char *model);
|
||||
|
||||
@@ -29,12 +29,6 @@
|
||||
#include "qemu-common.h"
|
||||
#include "qapi-types.h"
|
||||
|
||||
bool tap_has_ufo(NetClientState *nc);
|
||||
int tap_has_vnet_hdr(NetClientState *nc);
|
||||
int tap_has_vnet_hdr_len(NetClientState *nc, int len);
|
||||
void tap_using_vnet_hdr(NetClientState *nc, bool using_vnet_hdr);
|
||||
void tap_set_offload(NetClientState *nc, int csum, int tso4, int tso6, int ecn, int ufo);
|
||||
void tap_set_vnet_hdr_len(NetClientState *nc, int len);
|
||||
int tap_enable(NetClientState *nc);
|
||||
int tap_disable(NetClientState *nc);
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ void qerror_report_err(Error *err);
|
||||
ERROR_CLASS_GENERIC_ERROR, "Device '%s' does not support hotplugging"
|
||||
|
||||
#define QERR_DEVICE_NOT_ACTIVE \
|
||||
ERROR_CLASS_DEVICE_NOT_ACTIVE, "Device '%s' has not been activated"
|
||||
ERROR_CLASS_DEVICE_NOT_ACTIVE, "No %s device has been activated"
|
||||
|
||||
#define QERR_DEVICE_NOT_ENCRYPTED \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Device '%s' is not encrypted"
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include "qapi/qmp/qobject.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
|
||||
QObject *qobject_from_json(const char *string) GCC_FMT_ATTR(1, 0);
|
||||
QObject *qobject_from_json(const char *string);
|
||||
QObject *qobject_from_jsonf(const char *string, ...) GCC_FMT_ATTR(1, 2);
|
||||
QObject *qobject_from_jsonv(const char *string, va_list *ap) GCC_FMT_ATTR(1, 0);
|
||||
|
||||
|
||||
@@ -228,7 +228,7 @@ static inline int ldsb_p(const void *ptr)
|
||||
return *(int8_t *)ptr;
|
||||
}
|
||||
|
||||
static inline void stb_p(void *ptr, int v)
|
||||
static inline void stb_p(void *ptr, uint8_t v)
|
||||
{
|
||||
*(uint8_t *)ptr = v;
|
||||
}
|
||||
@@ -300,12 +300,12 @@ static inline uint64_t ldq_le_p(const void *ptr)
|
||||
return le_bswap(ldq_p(ptr), 64);
|
||||
}
|
||||
|
||||
static inline void stw_le_p(void *ptr, int v)
|
||||
static inline void stw_le_p(void *ptr, uint16_t v)
|
||||
{
|
||||
stw_p(ptr, le_bswap(v, 16));
|
||||
}
|
||||
|
||||
static inline void stl_le_p(void *ptr, int v)
|
||||
static inline void stl_le_p(void *ptr, uint32_t v)
|
||||
{
|
||||
stl_p(ptr, le_bswap(v, 32));
|
||||
}
|
||||
@@ -365,12 +365,12 @@ static inline uint64_t ldq_be_p(const void *ptr)
|
||||
return be_bswap(ldq_p(ptr), 64);
|
||||
}
|
||||
|
||||
static inline void stw_be_p(void *ptr, int v)
|
||||
static inline void stw_be_p(void *ptr, uint16_t v)
|
||||
{
|
||||
stw_p(ptr, be_bswap(v, 16));
|
||||
}
|
||||
|
||||
static inline void stl_be_p(void *ptr, int v)
|
||||
static inline void stl_be_p(void *ptr, uint32_t v)
|
||||
{
|
||||
stl_p(ptr, be_bswap(v, 32));
|
||||
}
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QEMU_CRC32_H
|
||||
#define QEMU_CRC32_H
|
||||
#ifndef QEMU_CRC32C_H
|
||||
#define QEMU_CRC32C_H
|
||||
|
||||
#include "qemu-common.h"
|
||||
|
||||
|
||||
@@ -217,7 +217,7 @@ static inline int ctz64(uint64_t val)
|
||||
}
|
||||
|
||||
/**
|
||||
* ctz64 - count trailing ones in a 64-bit value.
|
||||
* cto64 - count trailing ones in a 64-bit value.
|
||||
* @val: The value to search
|
||||
*
|
||||
* Returns 64 if the value is -1.
|
||||
|
||||
@@ -28,7 +28,8 @@
|
||||
#include "qemu/tls.h"
|
||||
#include "qemu/typedefs.h"
|
||||
|
||||
typedef int (*WriteCoreDumpFunction)(void *buf, size_t size, void *opaque);
|
||||
typedef int (*WriteCoreDumpFunction)(const void *buf, size_t size,
|
||||
void *opaque);
|
||||
|
||||
/**
|
||||
* vaddr:
|
||||
|
||||
@@ -14,12 +14,150 @@
|
||||
#ifndef DUMP_H
|
||||
#define DUMP_H
|
||||
|
||||
#define MAKEDUMPFILE_SIGNATURE "makedumpfile"
|
||||
#define MAX_SIZE_MDF_HEADER (4096) /* max size of makedumpfile_header */
|
||||
#define TYPE_FLAT_HEADER (1) /* type of flattened format */
|
||||
#define VERSION_FLAT_HEADER (1) /* version of flattened format */
|
||||
#define END_FLAG_FLAT_HEADER (-1)
|
||||
|
||||
#define ARCH_PFN_OFFSET (0)
|
||||
|
||||
#define paddr_to_pfn(X, page_shift) \
|
||||
(((unsigned long long)(X) >> (page_shift)) - ARCH_PFN_OFFSET)
|
||||
#define pfn_to_paddr(X, page_shift) \
|
||||
(((unsigned long long)(X) + ARCH_PFN_OFFSET) << (page_shift))
|
||||
|
||||
/*
|
||||
* flag for compressed format
|
||||
*/
|
||||
#define DUMP_DH_COMPRESSED_ZLIB (0x1)
|
||||
#define DUMP_DH_COMPRESSED_LZO (0x2)
|
||||
#define DUMP_DH_COMPRESSED_SNAPPY (0x4)
|
||||
|
||||
#define KDUMP_SIGNATURE "KDUMP "
|
||||
#define SIG_LEN (sizeof(KDUMP_SIGNATURE) - 1)
|
||||
#define PHYS_BASE (0)
|
||||
#define DUMP_LEVEL (1)
|
||||
#define DISKDUMP_HEADER_BLOCKS (1)
|
||||
#define BUFSIZE_BITMAP (TARGET_PAGE_SIZE)
|
||||
#define PFN_BUFBITMAP (CHAR_BIT * BUFSIZE_BITMAP)
|
||||
#define BUFSIZE_DATA_CACHE (TARGET_PAGE_SIZE * 4)
|
||||
|
||||
typedef struct ArchDumpInfo {
|
||||
int d_machine; /* Architecture */
|
||||
int d_endian; /* ELFDATA2LSB or ELFDATA2MSB */
|
||||
int d_class; /* ELFCLASS32 or ELFCLASS64 */
|
||||
} ArchDumpInfo;
|
||||
|
||||
typedef struct QEMU_PACKED MakedumpfileHeader {
|
||||
char signature[16]; /* = "makedumpfile" */
|
||||
int64_t type;
|
||||
int64_t version;
|
||||
} MakedumpfileHeader;
|
||||
|
||||
typedef struct QEMU_PACKED MakedumpfileDataHeader {
|
||||
int64_t offset;
|
||||
int64_t buf_size;
|
||||
} MakedumpfileDataHeader;
|
||||
|
||||
typedef struct QEMU_PACKED NewUtsname {
|
||||
char sysname[65];
|
||||
char nodename[65];
|
||||
char release[65];
|
||||
char version[65];
|
||||
char machine[65];
|
||||
char domainname[65];
|
||||
} NewUtsname;
|
||||
|
||||
typedef struct QEMU_PACKED DiskDumpHeader32 {
|
||||
char signature[SIG_LEN]; /* = "KDUMP " */
|
||||
uint32_t header_version; /* Dump header version */
|
||||
NewUtsname utsname; /* copy of system_utsname */
|
||||
char timestamp[10]; /* Time stamp */
|
||||
uint32_t status; /* Above flags */
|
||||
uint32_t block_size; /* Size of a block in byte */
|
||||
uint32_t sub_hdr_size; /* Size of arch dependent header in block */
|
||||
uint32_t bitmap_blocks; /* Size of Memory bitmap in block */
|
||||
uint32_t max_mapnr; /* = max_mapnr ,
|
||||
obsoleted in header_version 6 */
|
||||
uint32_t total_ram_blocks; /* Number of blocks should be written */
|
||||
uint32_t device_blocks; /* Number of total blocks in dump device */
|
||||
uint32_t written_blocks; /* Number of written blocks */
|
||||
uint32_t current_cpu; /* CPU# which handles dump */
|
||||
uint32_t nr_cpus; /* Number of CPUs */
|
||||
} DiskDumpHeader32;
|
||||
|
||||
typedef struct QEMU_PACKED DiskDumpHeader64 {
|
||||
char signature[SIG_LEN]; /* = "KDUMP " */
|
||||
uint32_t header_version; /* Dump header version */
|
||||
NewUtsname utsname; /* copy of system_utsname */
|
||||
char timestamp[22]; /* Time stamp */
|
||||
uint32_t status; /* Above flags */
|
||||
uint32_t block_size; /* Size of a block in byte */
|
||||
uint32_t sub_hdr_size; /* Size of arch dependent header in block */
|
||||
uint32_t bitmap_blocks; /* Size of Memory bitmap in block */
|
||||
uint32_t max_mapnr; /* = max_mapnr,
|
||||
obsoleted in header_version 6 */
|
||||
uint32_t total_ram_blocks; /* Number of blocks should be written */
|
||||
uint32_t device_blocks; /* Number of total blocks in dump device */
|
||||
uint32_t written_blocks; /* Number of written blocks */
|
||||
uint32_t current_cpu; /* CPU# which handles dump */
|
||||
uint32_t nr_cpus; /* Number of CPUs */
|
||||
} DiskDumpHeader64;
|
||||
|
||||
typedef struct QEMU_PACKED KdumpSubHeader32 {
|
||||
uint32_t phys_base;
|
||||
uint32_t dump_level; /* header_version 1 and later */
|
||||
uint32_t split; /* header_version 2 and later */
|
||||
uint32_t start_pfn; /* header_version 2 and later,
|
||||
obsoleted in header_version 6 */
|
||||
uint32_t end_pfn; /* header_version 2 and later,
|
||||
obsoleted in header_version 6 */
|
||||
uint64_t offset_vmcoreinfo; /* header_version 3 and later */
|
||||
uint32_t size_vmcoreinfo; /* header_version 3 and later */
|
||||
uint64_t offset_note; /* header_version 4 and later */
|
||||
uint32_t note_size; /* header_version 4 and later */
|
||||
uint64_t offset_eraseinfo; /* header_version 5 and later */
|
||||
uint32_t size_eraseinfo; /* header_version 5 and later */
|
||||
uint64_t start_pfn_64; /* header_version 6 and later */
|
||||
uint64_t end_pfn_64; /* header_version 6 and later */
|
||||
uint64_t max_mapnr_64; /* header_version 6 and later */
|
||||
} KdumpSubHeader32;
|
||||
|
||||
typedef struct QEMU_PACKED KdumpSubHeader64 {
|
||||
uint64_t phys_base;
|
||||
uint32_t dump_level; /* header_version 1 and later */
|
||||
uint32_t split; /* header_version 2 and later */
|
||||
uint64_t start_pfn; /* header_version 2 and later,
|
||||
obsoleted in header_version 6 */
|
||||
uint64_t end_pfn; /* header_version 2 and later,
|
||||
obsoleted in header_version 6 */
|
||||
uint64_t offset_vmcoreinfo; /* header_version 3 and later */
|
||||
uint64_t size_vmcoreinfo; /* header_version 3 and later */
|
||||
uint64_t offset_note; /* header_version 4 and later */
|
||||
uint64_t note_size; /* header_version 4 and later */
|
||||
uint64_t offset_eraseinfo; /* header_version 5 and later */
|
||||
uint64_t size_eraseinfo; /* header_version 5 and later */
|
||||
uint64_t start_pfn_64; /* header_version 6 and later */
|
||||
uint64_t end_pfn_64; /* header_version 6 and later */
|
||||
uint64_t max_mapnr_64; /* header_version 6 and later */
|
||||
} KdumpSubHeader64;
|
||||
|
||||
typedef struct DataCache {
|
||||
int fd; /* fd of the file where to write the cached data */
|
||||
uint8_t *buf; /* buffer for cached data */
|
||||
size_t buf_size; /* size of the buf */
|
||||
size_t data_size; /* size of cached data in buf */
|
||||
off_t offset; /* offset of the file */
|
||||
} DataCache;
|
||||
|
||||
typedef struct QEMU_PACKED PageDescriptor {
|
||||
uint64_t offset; /* the offset of the page data*/
|
||||
uint32_t size; /* the size of this dump page */
|
||||
uint32_t flags; /* flags */
|
||||
uint64_t page_flags; /* page flags */
|
||||
} PageDescriptor;
|
||||
|
||||
struct GuestPhysBlockList; /* memory_mapping.h */
|
||||
int cpu_get_dump_info(ArchDumpInfo *info,
|
||||
const struct GuestPhysBlockList *guest_phys_blocks);
|
||||
|
||||
@@ -194,6 +194,28 @@ int kvm_vm_ioctl(KVMState *s, int type, ...);
|
||||
|
||||
int kvm_vcpu_ioctl(CPUState *cpu, int type, ...);
|
||||
|
||||
/**
|
||||
* kvm_device_ioctl - call an ioctl on a kvm device
|
||||
* @fd: The KVM device file descriptor as returned from KVM_CREATE_DEVICE
|
||||
* @type: The device-ctrl ioctl number
|
||||
*
|
||||
* Returns: -errno on error, nonnegative on success
|
||||
*/
|
||||
int kvm_device_ioctl(int fd, int type, ...);
|
||||
|
||||
/**
|
||||
* kvm_create_device - create a KVM device for the device control API
|
||||
* @KVMState: The KVMState pointer
|
||||
* @type: The KVM device type (see Documentation/virtual/kvm/devices in the
|
||||
* kernel source)
|
||||
* @test: If true, only test if device can be created, but don't actually
|
||||
* create the device.
|
||||
*
|
||||
* Returns: -errno on error, nonnegative on success: @test ? 0 : device fd;
|
||||
*/
|
||||
int kvm_create_device(KVMState *s, uint64_t type, bool test);
|
||||
|
||||
|
||||
/* Arch specific hooks */
|
||||
|
||||
extern const KVMCapabilityInfo kvm_arch_required_capabilities[];
|
||||
@@ -319,4 +341,16 @@ int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq);
|
||||
void kvm_pc_gsi_handler(void *opaque, int n, int level);
|
||||
void kvm_pc_setup_irq_routing(bool pci_enabled);
|
||||
void kvm_init_irq_routing(KVMState *s);
|
||||
|
||||
/**
|
||||
* kvm_arch_irqchip_create:
|
||||
* @KVMState: The KVMState pointer
|
||||
*
|
||||
* Allow architectures to create an in-kernel irq chip themselves.
|
||||
*
|
||||
* Returns: < 0: error
|
||||
* 0: irq chip was not created
|
||||
* > 0: irq chip was created
|
||||
*/
|
||||
int kvm_arch_irqchip_create(KVMState *s);
|
||||
#endif
|
||||
|
||||
@@ -104,6 +104,7 @@ extern int autostart;
|
||||
|
||||
typedef enum {
|
||||
VGA_NONE, VGA_STD, VGA_CIRRUS, VGA_VMWARE, VGA_XENFB, VGA_QXL,
|
||||
VGA_TCX, VGA_CG3,
|
||||
} VGAInterfaceType;
|
||||
|
||||
extern int vga_interface_type;
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#define MOUSE_EVENT_LBUTTON 0x01
|
||||
#define MOUSE_EVENT_RBUTTON 0x02
|
||||
#define MOUSE_EVENT_MBUTTON 0x04
|
||||
#define MOUSE_EVENT_WHEELUP 0x08
|
||||
#define MOUSE_EVENT_WHEELDN 0x10
|
||||
|
||||
/* identical to the ps/2 keyboard bits */
|
||||
#define QEMU_SCROLL_LOCK_LED (1 << 0)
|
||||
@@ -44,17 +46,7 @@ void qemu_activate_mouse_event_handler(QEMUPutMouseEntry *entry);
|
||||
QEMUPutLEDEntry *qemu_add_led_event_handler(QEMUPutLEDEvent *func, void *opaque);
|
||||
void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry);
|
||||
|
||||
void kbd_put_keycode(int keycode);
|
||||
void kbd_put_ledstate(int ledstate);
|
||||
void kbd_mouse_event(int dx, int dy, int dz, int buttons_state);
|
||||
|
||||
/* Does the current mouse generate absolute events */
|
||||
int kbd_mouse_is_absolute(void);
|
||||
void qemu_add_mouse_mode_change_notifier(Notifier *notify);
|
||||
void qemu_remove_mouse_mode_change_notifier(Notifier *notify);
|
||||
|
||||
/* Of all the mice, is there one that generates absolute events */
|
||||
int kbd_mouse_has_absolute(void);
|
||||
|
||||
struct MouseTransformInfo {
|
||||
/* Touchscreen resolution */
|
||||
@@ -128,6 +120,14 @@ struct DisplaySurface {
|
||||
struct PixelFormat pf;
|
||||
};
|
||||
|
||||
typedef struct QemuUIInfo {
|
||||
/* geometry */
|
||||
int xoff;
|
||||
int yoff;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
} QemuUIInfo;
|
||||
|
||||
/* cursor data format is 32bit RGBA */
|
||||
typedef struct QEMUCursor {
|
||||
int width, height;
|
||||
@@ -212,6 +212,8 @@ void update_displaychangelistener(DisplayChangeListener *dcl,
|
||||
uint64_t interval);
|
||||
void unregister_displaychangelistener(DisplayChangeListener *dcl);
|
||||
|
||||
int dpy_set_ui_info(QemuConsole *con, QemuUIInfo *info);
|
||||
|
||||
void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h);
|
||||
void dpy_gfx_replace_surface(QemuConsole *con,
|
||||
DisplaySurface *surface);
|
||||
@@ -274,9 +276,10 @@ typedef struct GraphicHwOps {
|
||||
void (*gfx_update)(void *opaque);
|
||||
void (*text_update)(void *opaque, console_ch_t *text);
|
||||
void (*update_interval)(void *opaque, uint64_t interval);
|
||||
int (*ui_info)(void *opaque, uint32_t head, QemuUIInfo *info);
|
||||
} GraphicHwOps;
|
||||
|
||||
QemuConsole *graphic_console_init(DeviceState *dev,
|
||||
QemuConsole *graphic_console_init(DeviceState *dev, uint32_t head,
|
||||
const GraphicHwOps *ops,
|
||||
void *opaque);
|
||||
|
||||
@@ -285,10 +288,15 @@ void graphic_hw_invalidate(QemuConsole *con);
|
||||
void graphic_hw_text_update(QemuConsole *con, console_ch_t *chardata);
|
||||
|
||||
QemuConsole *qemu_console_lookup_by_index(unsigned int index);
|
||||
QemuConsole *qemu_console_lookup_by_device(DeviceState *dev);
|
||||
QemuConsole *qemu_console_lookup_by_device(DeviceState *dev, uint32_t head);
|
||||
bool qemu_console_is_visible(QemuConsole *con);
|
||||
bool qemu_console_is_graphic(QemuConsole *con);
|
||||
bool qemu_console_is_fixedsize(QemuConsole *con);
|
||||
int qemu_console_get_index(QemuConsole *con);
|
||||
uint32_t qemu_console_get_head(QemuConsole *con);
|
||||
QemuUIInfo *qemu_console_get_ui_info(QemuConsole *con);
|
||||
int qemu_console_get_width(QemuConsole *con, int fallback);
|
||||
int qemu_console_get_height(QemuConsole *con, int fallback);
|
||||
|
||||
void text_consoles_set_display(DisplayState *ds);
|
||||
void console_select(unsigned int index);
|
||||
@@ -334,7 +342,6 @@ void curses_display_init(DisplayState *ds, int full_screen);
|
||||
|
||||
/* input.c */
|
||||
int index_from_key(const char *key);
|
||||
int index_from_keycode(int code);
|
||||
|
||||
/* gtk.c */
|
||||
void early_gtk_display_init(void);
|
||||
|
||||
56
include/ui/input.h
Normal file
56
include/ui/input.h
Normal file
@@ -0,0 +1,56 @@
|
||||
#ifndef INPUT_H
|
||||
#define INPUT_H
|
||||
|
||||
#include "qapi-types.h"
|
||||
|
||||
#define INPUT_EVENT_MASK_KEY (1<<INPUT_EVENT_KIND_KEY)
|
||||
#define INPUT_EVENT_MASK_BTN (1<<INPUT_EVENT_KIND_BTN)
|
||||
#define INPUT_EVENT_MASK_REL (1<<INPUT_EVENT_KIND_REL)
|
||||
#define INPUT_EVENT_MASK_ABS (1<<INPUT_EVENT_KIND_ABS)
|
||||
|
||||
#define INPUT_EVENT_ABS_SIZE 0x8000
|
||||
|
||||
typedef struct QemuInputHandler QemuInputHandler;
|
||||
typedef struct QemuInputHandlerState QemuInputHandlerState;
|
||||
|
||||
typedef void (*QemuInputHandlerEvent)(DeviceState *dev, QemuConsole *src,
|
||||
InputEvent *evt);
|
||||
typedef void (*QemuInputHandlerSync)(DeviceState *dev);
|
||||
|
||||
struct QemuInputHandler {
|
||||
const char *name;
|
||||
uint32_t mask;
|
||||
QemuInputHandlerEvent event;
|
||||
QemuInputHandlerSync sync;
|
||||
};
|
||||
|
||||
QemuInputHandlerState *qemu_input_handler_register(DeviceState *dev,
|
||||
QemuInputHandler *handler);
|
||||
void qemu_input_handler_activate(QemuInputHandlerState *s);
|
||||
void qemu_input_handler_unregister(QemuInputHandlerState *s);
|
||||
void qemu_input_event_send(QemuConsole *src, InputEvent *evt);
|
||||
void qemu_input_event_sync(void);
|
||||
|
||||
InputEvent *qemu_input_event_new_key(KeyValue *key, bool down);
|
||||
void qemu_input_event_send_key(QemuConsole *src, KeyValue *key, bool down);
|
||||
void qemu_input_event_send_key_number(QemuConsole *src, int num, bool down);
|
||||
void qemu_input_event_send_key_qcode(QemuConsole *src, QKeyCode q, bool down);
|
||||
|
||||
InputEvent *qemu_input_event_new_btn(InputButton btn, bool down);
|
||||
void qemu_input_queue_btn(QemuConsole *src, InputButton btn, bool down);
|
||||
void qemu_input_update_buttons(QemuConsole *src, uint32_t *button_map,
|
||||
uint32_t button_old, uint32_t button_new);
|
||||
|
||||
bool qemu_input_is_absolute(void);
|
||||
int qemu_input_scale_axis(int value, int size_in, int size_out);
|
||||
InputEvent *qemu_input_event_new_move(InputEventKind kind,
|
||||
InputAxis axis, int value);
|
||||
void qemu_input_queue_rel(QemuConsole *src, InputAxis axis, int value);
|
||||
void qemu_input_queue_abs(QemuConsole *src, InputAxis axis,
|
||||
int value, int size);
|
||||
|
||||
void qemu_input_check_mode_change(void);
|
||||
void qemu_add_mouse_mode_change_notifier(Notifier *notify);
|
||||
void qemu_remove_mouse_mode_change_notifier(Notifier *notify);
|
||||
|
||||
#endif /* INPUT_H */
|
||||
52
kvm-all.c
52
kvm-all.c
@@ -1298,10 +1298,17 @@ static int kvm_irqchip_create(KVMState *s)
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = kvm_vm_ioctl(s, KVM_CREATE_IRQCHIP);
|
||||
/* First probe and see if there's a arch-specific hook to create the
|
||||
* in-kernel irqchip for us */
|
||||
ret = kvm_arch_irqchip_create(s);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Create kernel irqchip failed\n");
|
||||
return ret;
|
||||
} else if (ret == 0) {
|
||||
ret = kvm_vm_ioctl(s, KVM_CREATE_IRQCHIP);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Create kernel irqchip failed\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
kvm_kernel_irqchip = true;
|
||||
@@ -1428,7 +1435,7 @@ int kvm_init(void)
|
||||
} while (ret == -EINTR);
|
||||
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "ioctl(KVM_CREATE_VM) failed: %d %s\n", -s->vmfd,
|
||||
fprintf(stderr, "ioctl(KVM_CREATE_VM) failed: %d %s\n", -ret,
|
||||
strerror(-ret));
|
||||
|
||||
#ifdef TARGET_S390X
|
||||
@@ -1777,6 +1784,24 @@ int kvm_vcpu_ioctl(CPUState *cpu, int type, ...)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int kvm_device_ioctl(int fd, int type, ...)
|
||||
{
|
||||
int ret;
|
||||
void *arg;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, type);
|
||||
arg = va_arg(ap, void *);
|
||||
va_end(ap);
|
||||
|
||||
trace_kvm_device_ioctl(fd, type, arg);
|
||||
ret = ioctl(fd, type, arg);
|
||||
if (ret == -1) {
|
||||
ret = -errno;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int kvm_has_sync_mmu(void)
|
||||
{
|
||||
return kvm_check_extension(kvm_state, KVM_CAP_SYNC_MMU);
|
||||
@@ -2058,3 +2083,24 @@ int kvm_on_sigbus(int code, void *addr)
|
||||
{
|
||||
return kvm_arch_on_sigbus(code, addr);
|
||||
}
|
||||
|
||||
int kvm_create_device(KVMState *s, uint64_t type, bool test)
|
||||
{
|
||||
int ret;
|
||||
struct kvm_create_device create_dev;
|
||||
|
||||
create_dev.type = type;
|
||||
create_dev.fd = -1;
|
||||
create_dev.flags = test ? KVM_CREATE_DEVICE_TEST : 0;
|
||||
|
||||
if (!kvm_check_extension(s, KVM_CAP_DEVICE_CTRL)) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
ret = kvm_vm_ioctl(s, KVM_CREATE_DEVICE, &create_dev);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return test ? 0 : create_dev.fd;
|
||||
}
|
||||
|
||||
@@ -119,6 +119,26 @@ struct kvm_arch_memory_slot {
|
||||
#define KVM_REG_ARM_32_CRN_MASK 0x0000000000007800
|
||||
#define KVM_REG_ARM_32_CRN_SHIFT 11
|
||||
|
||||
#define ARM_CP15_REG_SHIFT_MASK(x,n) \
|
||||
(((x) << KVM_REG_ARM_ ## n ## _SHIFT) & KVM_REG_ARM_ ## n ## _MASK)
|
||||
|
||||
#define __ARM_CP15_REG(op1,crn,crm,op2) \
|
||||
(KVM_REG_ARM | (15 << KVM_REG_ARM_COPROC_SHIFT) | \
|
||||
ARM_CP15_REG_SHIFT_MASK(op1, OPC1) | \
|
||||
ARM_CP15_REG_SHIFT_MASK(crn, 32_CRN) | \
|
||||
ARM_CP15_REG_SHIFT_MASK(crm, CRM) | \
|
||||
ARM_CP15_REG_SHIFT_MASK(op2, 32_OPC2))
|
||||
|
||||
#define ARM_CP15_REG32(...) (__ARM_CP15_REG(__VA_ARGS__) | KVM_REG_SIZE_U32)
|
||||
|
||||
#define __ARM_CP15_REG64(op1,crm) \
|
||||
(__ARM_CP15_REG(op1, 0, crm, 0) | KVM_REG_SIZE_U64)
|
||||
#define ARM_CP15_REG64(...) __ARM_CP15_REG64(__VA_ARGS__)
|
||||
|
||||
#define KVM_REG_ARM_TIMER_CTL ARM_CP15_REG32(0, 14, 3, 1)
|
||||
#define KVM_REG_ARM_TIMER_CNT ARM_CP15_REG64(1, 14)
|
||||
#define KVM_REG_ARM_TIMER_CVAL ARM_CP15_REG64(3, 14)
|
||||
|
||||
/* Normal registers are mapped as coprocessor 16. */
|
||||
#define KVM_REG_ARM_CORE (0x0010 << KVM_REG_ARM_COPROC_SHIFT)
|
||||
#define KVM_REG_ARM_CORE_REG(name) (offsetof(struct kvm_regs, name) / 4)
|
||||
@@ -143,6 +163,14 @@ struct kvm_arch_memory_slot {
|
||||
#define KVM_REG_ARM_VFP_FPINST 0x1009
|
||||
#define KVM_REG_ARM_VFP_FPINST2 0x100A
|
||||
|
||||
/* Device Control API: ARM VGIC */
|
||||
#define KVM_DEV_ARM_VGIC_GRP_ADDR 0
|
||||
#define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1
|
||||
#define KVM_DEV_ARM_VGIC_GRP_CPU_REGS 2
|
||||
#define KVM_DEV_ARM_VGIC_CPUID_SHIFT 32
|
||||
#define KVM_DEV_ARM_VGIC_CPUID_MASK (0xffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT)
|
||||
#define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0
|
||||
#define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
|
||||
|
||||
/* KVM_IRQ_LINE irq field index values */
|
||||
#define KVM_ARM_IRQ_TYPE_SHIFT 24
|
||||
|
||||
@@ -55,8 +55,9 @@ struct kvm_regs {
|
||||
#define KVM_ARM_TARGET_AEM_V8 0
|
||||
#define KVM_ARM_TARGET_FOUNDATION_V8 1
|
||||
#define KVM_ARM_TARGET_CORTEX_A57 2
|
||||
#define KVM_ARM_TARGET_XGENE_POTENZA 3
|
||||
|
||||
#define KVM_ARM_NUM_TARGETS 3
|
||||
#define KVM_ARM_NUM_TARGETS 4
|
||||
|
||||
/* KVM_ARM_SET_DEVICE_ADDR ioctl id encoding */
|
||||
#define KVM_ARM_DEVICE_TYPE_SHIFT 0
|
||||
@@ -129,6 +130,33 @@ struct kvm_arch_memory_slot {
|
||||
#define KVM_REG_ARM64_SYSREG_OP2_MASK 0x0000000000000007
|
||||
#define KVM_REG_ARM64_SYSREG_OP2_SHIFT 0
|
||||
|
||||
#define ARM64_SYS_REG_SHIFT_MASK(x,n) \
|
||||
(((x) << KVM_REG_ARM64_SYSREG_ ## n ## _SHIFT) & \
|
||||
KVM_REG_ARM64_SYSREG_ ## n ## _MASK)
|
||||
|
||||
#define __ARM64_SYS_REG(op0,op1,crn,crm,op2) \
|
||||
(KVM_REG_ARM64 | KVM_REG_ARM64_SYSREG | \
|
||||
ARM64_SYS_REG_SHIFT_MASK(op0, OP0) | \
|
||||
ARM64_SYS_REG_SHIFT_MASK(op1, OP1) | \
|
||||
ARM64_SYS_REG_SHIFT_MASK(crn, CRN) | \
|
||||
ARM64_SYS_REG_SHIFT_MASK(crm, CRM) | \
|
||||
ARM64_SYS_REG_SHIFT_MASK(op2, OP2))
|
||||
|
||||
#define ARM64_SYS_REG(...) (__ARM64_SYS_REG(__VA_ARGS__) | KVM_REG_SIZE_U64)
|
||||
|
||||
#define KVM_REG_ARM_TIMER_CTL ARM64_SYS_REG(3, 3, 14, 3, 1)
|
||||
#define KVM_REG_ARM_TIMER_CNT ARM64_SYS_REG(3, 3, 14, 3, 2)
|
||||
#define KVM_REG_ARM_TIMER_CVAL ARM64_SYS_REG(3, 3, 14, 0, 2)
|
||||
|
||||
/* Device Control API: ARM VGIC */
|
||||
#define KVM_DEV_ARM_VGIC_GRP_ADDR 0
|
||||
#define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1
|
||||
#define KVM_DEV_ARM_VGIC_GRP_CPU_REGS 2
|
||||
#define KVM_DEV_ARM_VGIC_CPUID_SHIFT 32
|
||||
#define KVM_DEV_ARM_VGIC_CPUID_MASK (0xffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT)
|
||||
#define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0
|
||||
#define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
|
||||
|
||||
/* KVM_IRQ_LINE irq field index values */
|
||||
#define KVM_ARM_IRQ_TYPE_SHIFT 24
|
||||
#define KVM_ARM_IRQ_TYPE_MASK 0xff
|
||||
|
||||
@@ -545,6 +545,7 @@ struct kvm_get_htab_header {
|
||||
#define KVM_REG_PPC_TCSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb1)
|
||||
#define KVM_REG_PPC_PID (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb2)
|
||||
#define KVM_REG_PPC_ACOP (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb3)
|
||||
#define KVM_REG_PPC_WORT (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb4)
|
||||
|
||||
#define KVM_REG_PPC_VRSAVE (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb4)
|
||||
#define KVM_REG_PPC_LPCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb5)
|
||||
@@ -553,6 +554,8 @@ struct kvm_get_htab_header {
|
||||
/* Architecture compatibility level */
|
||||
#define KVM_REG_PPC_ARCH_COMPAT (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb7)
|
||||
|
||||
#define KVM_REG_PPC_DABRX (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb8)
|
||||
|
||||
/* Transactional Memory checkpointed state:
|
||||
* This is all GPRs, all VSX regs and a subset of SPRs
|
||||
*/
|
||||
|
||||
@@ -16,6 +16,22 @@
|
||||
|
||||
#define __KVM_S390
|
||||
|
||||
/* Device control API: s390-specific devices */
|
||||
#define KVM_DEV_FLIC_GET_ALL_IRQS 1
|
||||
#define KVM_DEV_FLIC_ENQUEUE 2
|
||||
#define KVM_DEV_FLIC_CLEAR_IRQS 3
|
||||
#define KVM_DEV_FLIC_APF_ENABLE 4
|
||||
#define KVM_DEV_FLIC_APF_DISABLE_WAIT 5
|
||||
/*
|
||||
* We can have up to 4*64k pending subchannels + 8 adapter interrupts,
|
||||
* as well as up to ASYNC_PF_PER_VCPU*KVM_MAX_VCPUS pfault done interrupts.
|
||||
* There are also sclp and machine checks. This gives us
|
||||
* sizeof(kvm_s390_irq)*(4*65536+8+64*64+1+1) = 72 * 266250 = 19170000
|
||||
* Lets round up to 8192 pages.
|
||||
*/
|
||||
#define KVM_S390_MAX_FLOAT_IRQS 266250
|
||||
#define KVM_S390_FLIC_MAX_BUFFER 0x2000000
|
||||
|
||||
/* for KVM_GET_REGS and KVM_SET_REGS */
|
||||
struct kvm_regs {
|
||||
/* general purpose regs for s390 */
|
||||
@@ -57,4 +73,7 @@ struct kvm_sync_regs {
|
||||
#define KVM_REG_S390_EPOCHDIFF (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x2)
|
||||
#define KVM_REG_S390_CPU_TIMER (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x3)
|
||||
#define KVM_REG_S390_CLOCK_COMP (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x4)
|
||||
#define KVM_REG_S390_PFTOKEN (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x5)
|
||||
#define KVM_REG_S390_PFCOMPARE (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x6)
|
||||
#define KVM_REG_S390_PFSELECT (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x7)
|
||||
#endif
|
||||
|
||||
@@ -28,6 +28,9 @@
|
||||
/* Partition Reference Counter (HV_X64_MSR_TIME_REF_COUNT) available*/
|
||||
#define HV_X64_MSR_TIME_REF_COUNT_AVAILABLE (1 << 1)
|
||||
|
||||
/* A partition's reference time stamp counter (TSC) page */
|
||||
#define HV_X64_MSR_REFERENCE_TSC 0x40000021
|
||||
|
||||
/*
|
||||
* There is a single feature flag that signifies the presence of the MSR
|
||||
* that can be used to retrieve both the local APIC Timer frequency as
|
||||
@@ -149,9 +152,6 @@
|
||||
/* MSR used to read the per-partition time reference counter */
|
||||
#define HV_X64_MSR_TIME_REF_COUNT 0x40000020
|
||||
|
||||
/* A partition's reference time stamp counter (TSC) page */
|
||||
#define HV_X64_MSR_REFERENCE_TSC 0x40000021
|
||||
|
||||
/* MSR used to retrieve the TSC frequency */
|
||||
#define HV_X64_MSR_TSC_FREQUENCY 0x40000022
|
||||
|
||||
@@ -201,6 +201,9 @@
|
||||
#define HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_MASK \
|
||||
(~((1ull << HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT) - 1))
|
||||
|
||||
#define HV_X64_MSR_TSC_REFERENCE_ENABLE 0x00000001
|
||||
#define HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT 12
|
||||
|
||||
#define HV_PROCESSOR_POWER_STATE_C0 0
|
||||
#define HV_PROCESSOR_POWER_STATE_C1 1
|
||||
#define HV_PROCESSOR_POWER_STATE_C2 2
|
||||
@@ -213,4 +216,11 @@
|
||||
#define HV_STATUS_INVALID_ALIGNMENT 4
|
||||
#define HV_STATUS_INSUFFICIENT_BUFFERS 19
|
||||
|
||||
typedef struct _HV_REFERENCE_TSC_PAGE {
|
||||
__u32 tsc_sequence;
|
||||
__u32 res1;
|
||||
__u64 tsc_scale;
|
||||
__s64 tsc_offset;
|
||||
} HV_REFERENCE_TSC_PAGE, *PHV_REFERENCE_TSC_PAGE;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -413,6 +413,8 @@ struct kvm_s390_psw {
|
||||
#define KVM_S390_PROGRAM_INT 0xfffe0001u
|
||||
#define KVM_S390_SIGP_SET_PREFIX 0xfffe0002u
|
||||
#define KVM_S390_RESTART 0xfffe0003u
|
||||
#define KVM_S390_INT_PFAULT_INIT 0xfffe0004u
|
||||
#define KVM_S390_INT_PFAULT_DONE 0xfffe0005u
|
||||
#define KVM_S390_MCHK 0xfffe1000u
|
||||
#define KVM_S390_INT_VIRTIO 0xffff2603u
|
||||
#define KVM_S390_INT_SERVICE 0xffff2401u
|
||||
@@ -434,6 +436,69 @@ struct kvm_s390_interrupt {
|
||||
__u64 parm64;
|
||||
};
|
||||
|
||||
struct kvm_s390_io_info {
|
||||
__u16 subchannel_id;
|
||||
__u16 subchannel_nr;
|
||||
__u32 io_int_parm;
|
||||
__u32 io_int_word;
|
||||
};
|
||||
|
||||
struct kvm_s390_ext_info {
|
||||
__u32 ext_params;
|
||||
__u32 pad;
|
||||
__u64 ext_params2;
|
||||
};
|
||||
|
||||
struct kvm_s390_pgm_info {
|
||||
__u64 trans_exc_code;
|
||||
__u64 mon_code;
|
||||
__u64 per_address;
|
||||
__u32 data_exc_code;
|
||||
__u16 code;
|
||||
__u16 mon_class_nr;
|
||||
__u8 per_code;
|
||||
__u8 per_atmid;
|
||||
__u8 exc_access_id;
|
||||
__u8 per_access_id;
|
||||
__u8 op_access_id;
|
||||
__u8 pad[3];
|
||||
};
|
||||
|
||||
struct kvm_s390_prefix_info {
|
||||
__u32 address;
|
||||
};
|
||||
|
||||
struct kvm_s390_extcall_info {
|
||||
__u16 code;
|
||||
};
|
||||
|
||||
struct kvm_s390_emerg_info {
|
||||
__u16 code;
|
||||
};
|
||||
|
||||
struct kvm_s390_mchk_info {
|
||||
__u64 cr14;
|
||||
__u64 mcic;
|
||||
__u64 failing_storage_address;
|
||||
__u32 ext_damage_code;
|
||||
__u32 pad;
|
||||
__u8 fixed_logout[16];
|
||||
};
|
||||
|
||||
struct kvm_s390_irq {
|
||||
__u64 type;
|
||||
union {
|
||||
struct kvm_s390_io_info io;
|
||||
struct kvm_s390_ext_info ext;
|
||||
struct kvm_s390_pgm_info pgm;
|
||||
struct kvm_s390_emerg_info emerg;
|
||||
struct kvm_s390_extcall_info extcall;
|
||||
struct kvm_s390_prefix_info prefix;
|
||||
struct kvm_s390_mchk_info mchk;
|
||||
char reserved[64];
|
||||
} u;
|
||||
};
|
||||
|
||||
/* for KVM_SET_GUEST_DEBUG */
|
||||
|
||||
#define KVM_GUESTDBG_ENABLE 0x00000001
|
||||
@@ -854,6 +919,8 @@ struct kvm_device_attr {
|
||||
#define KVM_DEV_VFIO_GROUP 1
|
||||
#define KVM_DEV_VFIO_GROUP_ADD 1
|
||||
#define KVM_DEV_VFIO_GROUP_DEL 2
|
||||
#define KVM_DEV_TYPE_ARM_VGIC_V2 5
|
||||
#define KVM_DEV_TYPE_FLIC 6
|
||||
|
||||
/*
|
||||
* ioctls for VM fds
|
||||
|
||||
@@ -3412,7 +3412,7 @@ void rdma_start_outgoing_migration(void *opaque,
|
||||
}
|
||||
|
||||
ret = qemu_rdma_source_init(rdma, &local_err,
|
||||
s->enabled_capabilities[MIGRATION_CAPABILITY_X_RDMA_PIN_ALL]);
|
||||
s->enabled_capabilities[MIGRATION_CAPABILITY_RDMA_PIN_ALL]);
|
||||
|
||||
if (ret) {
|
||||
goto err;
|
||||
|
||||
@@ -82,7 +82,7 @@ void qemu_start_incoming_migration(const char *uri, Error **errp)
|
||||
if (strstart(uri, "tcp:", &p))
|
||||
tcp_start_incoming_migration(p, errp);
|
||||
#ifdef CONFIG_RDMA
|
||||
else if (strstart(uri, "x-rdma:", &p))
|
||||
else if (strstart(uri, "rdma:", &p))
|
||||
rdma_start_incoming_migration(p, errp);
|
||||
#endif
|
||||
#if !defined(WIN32)
|
||||
@@ -438,7 +438,7 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk,
|
||||
if (strstart(uri, "tcp:", &p)) {
|
||||
tcp_start_outgoing_migration(s, p, &local_err);
|
||||
#ifdef CONFIG_RDMA
|
||||
} else if (strstart(uri, "x-rdma:", &p)) {
|
||||
} else if (strstart(uri, "rdma:", &p)) {
|
||||
rdma_start_outgoing_migration(s, p, &local_err);
|
||||
#endif
|
||||
#if !defined(WIN32)
|
||||
@@ -532,7 +532,7 @@ bool migrate_rdma_pin_all(void)
|
||||
|
||||
s = migrate_get_current();
|
||||
|
||||
return s->enabled_capabilities[MIGRATION_CAPABILITY_X_RDMA_PIN_ALL];
|
||||
return s->enabled_capabilities[MIGRATION_CAPABILITY_RDMA_PIN_ALL];
|
||||
}
|
||||
|
||||
bool migrate_auto_converge(void)
|
||||
|
||||
35
monitor.c
35
monitor.c
@@ -39,6 +39,7 @@
|
||||
#include "monitor/monitor.h"
|
||||
#include "qemu/readline.h"
|
||||
#include "ui/console.h"
|
||||
#include "ui/input.h"
|
||||
#include "sysemu/blockdev.h"
|
||||
#include "audio/audio.h"
|
||||
#include "disas/disas.h"
|
||||
@@ -1463,23 +1464,43 @@ static int mouse_button_state;
|
||||
|
||||
static void do_mouse_move(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
int dx, dy, dz;
|
||||
int dx, dy, dz, button;
|
||||
const char *dx_str = qdict_get_str(qdict, "dx_str");
|
||||
const char *dy_str = qdict_get_str(qdict, "dy_str");
|
||||
const char *dz_str = qdict_get_try_str(qdict, "dz_str");
|
||||
|
||||
dx = strtol(dx_str, NULL, 0);
|
||||
dy = strtol(dy_str, NULL, 0);
|
||||
dz = 0;
|
||||
if (dz_str)
|
||||
qemu_input_queue_rel(NULL, INPUT_AXIS_X, dx);
|
||||
qemu_input_queue_rel(NULL, INPUT_AXIS_Y, dy);
|
||||
|
||||
if (dz_str) {
|
||||
dz = strtol(dz_str, NULL, 0);
|
||||
kbd_mouse_event(dx, dy, dz, mouse_button_state);
|
||||
if (dz != 0) {
|
||||
button = (dz > 0) ? INPUT_BUTTON_WHEEL_UP : INPUT_BUTTON_WHEEL_DOWN;
|
||||
qemu_input_queue_btn(NULL, button, true);
|
||||
qemu_input_event_sync();
|
||||
qemu_input_queue_btn(NULL, button, false);
|
||||
}
|
||||
}
|
||||
qemu_input_event_sync();
|
||||
}
|
||||
|
||||
static void do_mouse_button(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
static uint32_t bmap[INPUT_BUTTON_MAX] = {
|
||||
[INPUT_BUTTON_LEFT] = MOUSE_EVENT_LBUTTON,
|
||||
[INPUT_BUTTON_MIDDLE] = MOUSE_EVENT_MBUTTON,
|
||||
[INPUT_BUTTON_RIGHT] = MOUSE_EVENT_RBUTTON,
|
||||
};
|
||||
int button_state = qdict_get_int(qdict, "button_state");
|
||||
|
||||
if (mouse_button_state == button_state) {
|
||||
return;
|
||||
}
|
||||
qemu_input_update_buttons(NULL, bmap, mouse_button_state, button_state);
|
||||
qemu_input_event_sync();
|
||||
mouse_button_state = button_state;
|
||||
kbd_mouse_event(0, 0, 0, mouse_button_state);
|
||||
}
|
||||
|
||||
static void do_ioport_read(Monitor *mon, const QDict *qdict)
|
||||
@@ -2021,10 +2042,6 @@ int64_t dev_time;
|
||||
|
||||
static void do_info_profile(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
int64_t total;
|
||||
total = qemu_time;
|
||||
if (total == 0)
|
||||
total = 1;
|
||||
monitor_printf(mon, "async time %" PRId64 " (%0.3f)\n",
|
||||
dev_time, dev_time / (double)get_ticks_per_sec());
|
||||
monitor_printf(mon, "qemu time %" PRId64 " (%0.3f)\n",
|
||||
|
||||
55
net/net.c
55
net/net.c
@@ -378,6 +378,61 @@ void qemu_foreach_nic(qemu_nic_foreach func, void *opaque)
|
||||
}
|
||||
}
|
||||
|
||||
bool qemu_has_ufo(NetClientState *nc)
|
||||
{
|
||||
if (!nc || !nc->info->has_ufo) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return nc->info->has_ufo(nc);
|
||||
}
|
||||
|
||||
bool qemu_has_vnet_hdr(NetClientState *nc)
|
||||
{
|
||||
if (!nc || !nc->info->has_vnet_hdr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return nc->info->has_vnet_hdr(nc);
|
||||
}
|
||||
|
||||
bool qemu_has_vnet_hdr_len(NetClientState *nc, int len)
|
||||
{
|
||||
if (!nc || !nc->info->has_vnet_hdr_len) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return nc->info->has_vnet_hdr_len(nc, len);
|
||||
}
|
||||
|
||||
void qemu_using_vnet_hdr(NetClientState *nc, bool enable)
|
||||
{
|
||||
if (!nc || !nc->info->using_vnet_hdr) {
|
||||
return;
|
||||
}
|
||||
|
||||
nc->info->using_vnet_hdr(nc, enable);
|
||||
}
|
||||
|
||||
void qemu_set_offload(NetClientState *nc, int csum, int tso4, int tso6,
|
||||
int ecn, int ufo)
|
||||
{
|
||||
if (!nc || !nc->info->set_offload) {
|
||||
return;
|
||||
}
|
||||
|
||||
nc->info->set_offload(nc, csum, tso4, tso6, ecn, ufo);
|
||||
}
|
||||
|
||||
void qemu_set_vnet_hdr_len(NetClientState *nc, int len)
|
||||
{
|
||||
if (!nc || !nc->info->set_vnet_hdr_len) {
|
||||
return;
|
||||
}
|
||||
|
||||
nc->info->set_vnet_hdr_len(nc, len);
|
||||
}
|
||||
|
||||
int qemu_can_send_packet(NetClientState *sender)
|
||||
{
|
||||
if (!sender->peer) {
|
||||
|
||||
123
net/netmap.c
123
net/netmap.c
@@ -27,10 +27,13 @@
|
||||
#include <net/if.h>
|
||||
#include <sys/mman.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#define NETMAP_WITH_LIBS
|
||||
#include <net/netmap.h>
|
||||
#include <net/netmap_user.h>
|
||||
|
||||
#include "net/net.h"
|
||||
#include "net/tap.h"
|
||||
#include "clients.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qemu/error-report.h"
|
||||
@@ -54,33 +57,9 @@ typedef struct NetmapState {
|
||||
bool read_poll;
|
||||
bool write_poll;
|
||||
struct iovec iov[IOV_MAX];
|
||||
int vnet_hdr_len; /* Current virtio-net header length. */
|
||||
} NetmapState;
|
||||
|
||||
#define D(format, ...) \
|
||||
do { \
|
||||
struct timeval __xxts; \
|
||||
gettimeofday(&__xxts, NULL); \
|
||||
printf("%03d.%06d %s [%d] " format "\n", \
|
||||
(int)__xxts.tv_sec % 1000, (int)__xxts.tv_usec, \
|
||||
__func__, __LINE__, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
/* Rate limited version of "D", lps indicates how many per second */
|
||||
#define RD(lps, format, ...) \
|
||||
do { \
|
||||
static int t0, __cnt; \
|
||||
struct timeval __xxts; \
|
||||
gettimeofday(&__xxts, NULL); \
|
||||
if (t0 != __xxts.tv_sec) { \
|
||||
t0 = __xxts.tv_sec; \
|
||||
__cnt = 0; \
|
||||
} \
|
||||
if (__cnt++ < lps) { \
|
||||
D(format, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
#define pkt_copy bcopy
|
||||
#else
|
||||
@@ -237,7 +216,7 @@ static ssize_t netmap_receive(NetClientState *nc,
|
||||
return size;
|
||||
}
|
||||
|
||||
if (ring->avail == 0) {
|
||||
if (nm_ring_empty(ring)) {
|
||||
/* No available slots in the netmap TX ring. */
|
||||
netmap_write_poll(s, true);
|
||||
return 0;
|
||||
@@ -250,8 +229,7 @@ static ssize_t netmap_receive(NetClientState *nc,
|
||||
ring->slot[i].len = size;
|
||||
ring->slot[i].flags = 0;
|
||||
pkt_copy(buf, dst, size);
|
||||
ring->cur = NETMAP_RING_NEXT(ring, i);
|
||||
ring->avail--;
|
||||
ring->cur = ring->head = nm_ring_next(ring, i);
|
||||
ioctl(s->me.fd, NIOCTXSYNC, NULL);
|
||||
|
||||
return size;
|
||||
@@ -267,17 +245,15 @@ static ssize_t netmap_receive_iov(NetClientState *nc,
|
||||
uint8_t *dst;
|
||||
int j;
|
||||
uint32_t i;
|
||||
uint32_t avail;
|
||||
|
||||
if (unlikely(!ring)) {
|
||||
/* Drop the packet. */
|
||||
return iov_size(iov, iovcnt);
|
||||
}
|
||||
|
||||
i = ring->cur;
|
||||
avail = ring->avail;
|
||||
last = i = ring->cur;
|
||||
|
||||
if (avail < iovcnt) {
|
||||
if (nm_ring_space(ring) < iovcnt) {
|
||||
/* Not enough netmap slots. */
|
||||
netmap_write_poll(s, true);
|
||||
return 0;
|
||||
@@ -293,7 +269,7 @@ static ssize_t netmap_receive_iov(NetClientState *nc,
|
||||
while (iov_frag_size) {
|
||||
nm_frag_size = MIN(iov_frag_size, ring->nr_buf_size);
|
||||
|
||||
if (unlikely(avail == 0)) {
|
||||
if (unlikely(nm_ring_empty(ring))) {
|
||||
/* We run out of netmap slots while splitting the
|
||||
iovec fragments. */
|
||||
netmap_write_poll(s, true);
|
||||
@@ -308,8 +284,7 @@ static ssize_t netmap_receive_iov(NetClientState *nc,
|
||||
pkt_copy(iov[j].iov_base + offset, dst, nm_frag_size);
|
||||
|
||||
last = i;
|
||||
i = NETMAP_RING_NEXT(ring, i);
|
||||
avail--;
|
||||
i = nm_ring_next(ring, i);
|
||||
|
||||
offset += nm_frag_size;
|
||||
iov_frag_size -= nm_frag_size;
|
||||
@@ -318,9 +293,8 @@ static ssize_t netmap_receive_iov(NetClientState *nc,
|
||||
/* The last slot must not have NS_MOREFRAG set. */
|
||||
ring->slot[last].flags &= ~NS_MOREFRAG;
|
||||
|
||||
/* Now update ring->cur and ring->avail. */
|
||||
ring->cur = i;
|
||||
ring->avail = avail;
|
||||
/* Now update ring->cur and ring->head. */
|
||||
ring->cur = ring->head = i;
|
||||
|
||||
ioctl(s->me.fd, NIOCTXSYNC, NULL);
|
||||
|
||||
@@ -343,7 +317,7 @@ static void netmap_send(void *opaque)
|
||||
|
||||
/* Keep sending while there are available packets into the netmap
|
||||
RX ring and the forwarding path towards the peer is open. */
|
||||
while (ring->avail > 0 && qemu_can_send_packet(&s->nc)) {
|
||||
while (!nm_ring_empty(ring) && qemu_can_send_packet(&s->nc)) {
|
||||
uint32_t i;
|
||||
uint32_t idx;
|
||||
bool morefrag;
|
||||
@@ -358,11 +332,10 @@ static void netmap_send(void *opaque)
|
||||
s->iov[iovcnt].iov_len = ring->slot[i].len;
|
||||
iovcnt++;
|
||||
|
||||
ring->cur = NETMAP_RING_NEXT(ring, i);
|
||||
ring->avail--;
|
||||
} while (ring->avail && morefrag);
|
||||
ring->cur = ring->head = nm_ring_next(ring, i);
|
||||
} while (!nm_ring_empty(ring) && morefrag);
|
||||
|
||||
if (unlikely(!ring->avail && morefrag)) {
|
||||
if (unlikely(nm_ring_empty(ring) && morefrag)) {
|
||||
RD(5, "[netmap_send] ran out of slots, with a pending"
|
||||
"incomplete packet\n");
|
||||
}
|
||||
@@ -394,6 +367,63 @@ static void netmap_cleanup(NetClientState *nc)
|
||||
s->me.fd = -1;
|
||||
}
|
||||
|
||||
/* Offloading manipulation support callbacks. */
|
||||
static bool netmap_has_ufo(NetClientState *nc)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool netmap_has_vnet_hdr(NetClientState *nc)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool netmap_has_vnet_hdr_len(NetClientState *nc, int len)
|
||||
{
|
||||
return len == 0 || len == sizeof(struct virtio_net_hdr) ||
|
||||
len == sizeof(struct virtio_net_hdr_mrg_rxbuf);
|
||||
}
|
||||
|
||||
static void netmap_using_vnet_hdr(NetClientState *nc, bool enable)
|
||||
{
|
||||
}
|
||||
|
||||
static void netmap_set_vnet_hdr_len(NetClientState *nc, int len)
|
||||
{
|
||||
NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
|
||||
int err;
|
||||
struct nmreq req;
|
||||
|
||||
/* Issue a NETMAP_BDG_VNET_HDR command to change the virtio-net header
|
||||
* length for the netmap adapter associated to 'me->ifname'.
|
||||
*/
|
||||
memset(&req, 0, sizeof(req));
|
||||
pstrcpy(req.nr_name, sizeof(req.nr_name), s->me.ifname);
|
||||
req.nr_version = NETMAP_API;
|
||||
req.nr_cmd = NETMAP_BDG_VNET_HDR;
|
||||
req.nr_arg1 = len;
|
||||
err = ioctl(s->me.fd, NIOCREGIF, &req);
|
||||
if (err) {
|
||||
error_report("Unable to execute NETMAP_BDG_VNET_HDR on %s: %s",
|
||||
s->me.ifname, strerror(errno));
|
||||
} else {
|
||||
/* Keep track of the current length. */
|
||||
s->vnet_hdr_len = len;
|
||||
}
|
||||
}
|
||||
|
||||
static void netmap_set_offload(NetClientState *nc, int csum, int tso4, int tso6,
|
||||
int ecn, int ufo)
|
||||
{
|
||||
NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
|
||||
|
||||
/* Setting a virtio-net header length greater than zero automatically
|
||||
* enables the offloadings.
|
||||
*/
|
||||
if (!s->vnet_hdr_len) {
|
||||
netmap_set_vnet_hdr_len(nc, sizeof(struct virtio_net_hdr));
|
||||
}
|
||||
}
|
||||
|
||||
/* NetClientInfo methods */
|
||||
static NetClientInfo net_netmap_info = {
|
||||
@@ -403,6 +433,12 @@ static NetClientInfo net_netmap_info = {
|
||||
.receive_iov = netmap_receive_iov,
|
||||
.poll = netmap_poll,
|
||||
.cleanup = netmap_cleanup,
|
||||
.has_ufo = netmap_has_ufo,
|
||||
.has_vnet_hdr = netmap_has_vnet_hdr,
|
||||
.has_vnet_hdr_len = netmap_has_vnet_hdr_len,
|
||||
.using_vnet_hdr = netmap_using_vnet_hdr,
|
||||
.set_offload = netmap_set_offload,
|
||||
.set_vnet_hdr_len = netmap_set_vnet_hdr_len,
|
||||
};
|
||||
|
||||
/* The exported init function
|
||||
@@ -428,6 +464,7 @@ int net_init_netmap(const NetClientOptions *opts,
|
||||
nc = qemu_new_net_client(&net_netmap_info, peer, "netmap", name);
|
||||
s = DO_UPCAST(NetmapState, nc, nc);
|
||||
s->me = me;
|
||||
s->vnet_hdr_len = 0;
|
||||
netmap_read_poll(s, true); /* Initially only poll for reads. */
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -669,11 +669,60 @@ static void tap_win32_send(void *opaque)
|
||||
}
|
||||
}
|
||||
|
||||
static bool tap_has_ufo(NetClientState *nc)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool tap_has_vnet_hdr(NetClientState *nc)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int tap_probe_vnet_hdr_len(int fd, int len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tap_fd_set_vnet_hdr_len(int fd, int len)
|
||||
{
|
||||
}
|
||||
|
||||
static void tap_using_vnet_hdr(NetClientState *nc, bool using_vnet_hdr)
|
||||
{
|
||||
}
|
||||
|
||||
static void tap_set_offload(NetClientState *nc, int csum, int tso4,
|
||||
int tso6, int ecn, int ufo)
|
||||
{
|
||||
}
|
||||
|
||||
struct vhost_net *tap_get_vhost_net(NetClientState *nc)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool tap_has_vnet_hdr_len(NetClientState *nc, int len)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static void tap_set_vnet_hdr_len(NetClientState *nc, int len)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
static NetClientInfo net_tap_win32_info = {
|
||||
.type = NET_CLIENT_OPTIONS_KIND_TAP,
|
||||
.size = sizeof(TAPState),
|
||||
.receive = tap_receive,
|
||||
.cleanup = tap_cleanup,
|
||||
.has_ufo = tap_has_ufo,
|
||||
.has_vnet_hdr = tap_has_vnet_hdr,
|
||||
.has_vnet_hdr_len = tap_has_vnet_hdr_len,
|
||||
.using_vnet_hdr = tap_using_vnet_hdr,
|
||||
.set_offload = tap_set_offload,
|
||||
.set_vnet_hdr_len = tap_set_vnet_hdr_len,
|
||||
};
|
||||
|
||||
static int tap_win32_init(NetClientState *peer, const char *model,
|
||||
@@ -722,49 +771,6 @@ int net_init_tap(const NetClientOptions *opts, const char *name,
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool tap_has_ufo(NetClientState *nc)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int tap_has_vnet_hdr(NetClientState *nc)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tap_probe_vnet_hdr_len(int fd, int len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tap_fd_set_vnet_hdr_len(int fd, int len)
|
||||
{
|
||||
}
|
||||
|
||||
void tap_using_vnet_hdr(NetClientState *nc, bool using_vnet_hdr)
|
||||
{
|
||||
}
|
||||
|
||||
void tap_set_offload(NetClientState *nc, int csum, int tso4,
|
||||
int tso6, int ecn, int ufo)
|
||||
{
|
||||
}
|
||||
|
||||
struct vhost_net *tap_get_vhost_net(NetClientState *nc)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int tap_has_vnet_hdr_len(NetClientState *nc, int len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tap_set_vnet_hdr_len(NetClientState *nc, int len)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
int tap_enable(NetClientState *nc)
|
||||
{
|
||||
abort();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user