Compare commits
70 Commits
file
...
opensuse-2
Author | SHA1 | Date | |
---|---|---|---|
|
f609ef91bc | ||
|
5d2ec830b4 | ||
|
2eae80d0ad | ||
|
e70b977473 | ||
|
9ec43fe486 | ||
|
9ad9afb2ff | ||
|
b94f504fbb | ||
|
075764d38e | ||
|
2f55ce6ce2 | ||
|
a075e63d02 | ||
|
9258d36c43 | ||
|
fb4795c347 | ||
|
f1cebceb57 | ||
|
c5b839d16e | ||
|
49af37a1df | ||
|
5c94e6582a | ||
|
d4e6359ea7 | ||
|
3f2e8a7a3a | ||
|
085771b0f8 | ||
|
b591a65b23 | ||
|
a76b760980 | ||
|
0c0a6b53c5 | ||
|
e3f320a759 | ||
|
e258560116 | ||
|
52c324d64c | ||
|
243f0e345c | ||
|
de439482d4 | ||
|
0fb8a7de8e | ||
|
9938d82cc9 | ||
|
1126af0e66 | ||
|
19fed6c601 | ||
|
c58810a9fe | ||
|
857545e61d | ||
|
1798372872 | ||
|
c5ce0620bf | ||
|
52b3782f6e | ||
|
f222ce0d5a | ||
|
e30f0e39ab | ||
|
1f6cee2319 | ||
|
e828d54e5b | ||
|
e26cff5986 | ||
|
9faf6837f5 | ||
|
8b201b80c7 | ||
|
9f8f18dc79 | ||
|
6b62214c4b | ||
|
955ef0968a | ||
|
871d3d13b5 | ||
|
fac2c74e75 | ||
|
8c00316b29 | ||
|
36fc0fea8b | ||
|
761b115c27 | ||
|
cba80a9dc1 | ||
|
ca45f1d446 | ||
|
c06014909f | ||
|
9414e435ed | ||
|
bc949bb060 | ||
|
ae7b4452a2 | ||
|
c8bac440ee | ||
|
9ceca2f2c2 | ||
|
99a5283091 | ||
|
a96062c693 | ||
|
a535f471a3 | ||
|
9671d1a0e8 | ||
|
2a9ed81b68 | ||
|
b1f9433704 | ||
|
4820daf43d | ||
|
08da583bd0 | ||
|
b34c0c408d | ||
|
e9ce5f5933 | ||
|
afd1df16c2 |
@@ -31,6 +31,10 @@ PROGS+=$(QEMU_PROGW)
|
||||
endif
|
||||
STPFILES=
|
||||
|
||||
ifdef CONFIG_LINUX_USER
|
||||
PROGS+=$(QEMU_PROG)-binfmt
|
||||
endif
|
||||
|
||||
config-target.h: config-target.h-timestamp
|
||||
config-target.h-timestamp: config-target.mak
|
||||
|
||||
@@ -92,6 +96,8 @@ QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR) -I$(SRC_PATH)/linux-user
|
||||
obj-y += linux-user/
|
||||
obj-y += gdbstub.o thunk.o user-exec.o
|
||||
|
||||
obj-binfmt-y += linux-user/
|
||||
|
||||
endif #CONFIG_LINUX_USER
|
||||
|
||||
#########################################################
|
||||
@@ -137,7 +143,11 @@ endif # CONFIG_SOFTMMU
|
||||
# Workaround for http://gcc.gnu.org/PR55489, see configure.
|
||||
%/translate.o: QEMU_CFLAGS += $(TRANSLATE_OPT_CFLAGS)
|
||||
|
||||
ifdef CONFIG_LINUX_USER
|
||||
dummy := $(call unnest-vars,,obj-y obj-binfmt-y)
|
||||
else
|
||||
dummy := $(call unnest-vars,,obj-y)
|
||||
endif
|
||||
|
||||
# we are making another call to unnest-vars with different vars, protect obj-y,
|
||||
# it can be overriden in subdir Makefile.objs
|
||||
@@ -173,6 +183,9 @@ $(QEMU_PROG): $(all-obj-y) ../libqemuutil.a ../libqemustub.a
|
||||
$(call LINK,$^)
|
||||
endif
|
||||
|
||||
$(QEMU_PROG)-binfmt: $(obj-binfmt-y)
|
||||
$(call LINK,$^)
|
||||
|
||||
gdbstub-xml.c: $(TARGET_XML_FILES) $(SRC_PATH)/scripts/feature_to_c.sh
|
||||
$(call quiet-command,rm -f $@ && $(SHELL) $(SRC_PATH)/scripts/feature_to_c.sh $@ $(TARGET_XML_FILES)," GEN $(TARGET_DIR)$@")
|
||||
|
||||
|
6
block.c
6
block.c
@@ -5277,7 +5277,7 @@ void bdrv_img_create(const char *filename, const char *fmt,
|
||||
Error **errp, bool quiet)
|
||||
{
|
||||
QEMUOptionParameter *param = NULL, *create_options = NULL;
|
||||
QEMUOptionParameter *backing_fmt, *backing_file, *size;
|
||||
QEMUOptionParameter *backing_fmt, *backing_file, *size, *scsi;
|
||||
BlockDriver *drv, *proto_drv;
|
||||
BlockDriver *backing_drv = NULL;
|
||||
Error *local_err = NULL;
|
||||
@@ -5392,6 +5392,10 @@ void bdrv_img_create(const char *filename, const char *fmt,
|
||||
if (!quiet) {
|
||||
printf("Formatting '%s', fmt=%s ", filename, fmt);
|
||||
print_option_parameters(param);
|
||||
scsi = get_option_parameter(param, BLOCK_OPT_SCSI);
|
||||
if (scsi && scsi->value.n) {
|
||||
printf(", SCSI");
|
||||
}
|
||||
puts("");
|
||||
}
|
||||
ret = bdrv_create(drv, filename, param, &local_err);
|
||||
|
@@ -24,6 +24,8 @@ common-obj-y += stream.o
|
||||
common-obj-y += commit.o
|
||||
common-obj-y += mirror.o
|
||||
common-obj-y += backup.o
|
||||
common-obj-y += dictzip.o
|
||||
common-obj-y += tar.o
|
||||
|
||||
iscsi.o-cflags := $(LIBISCSI_CFLAGS)
|
||||
iscsi.o-libs := $(LIBISCSI_LIBS)
|
||||
|
596
block/dictzip.c
Normal file
596
block/dictzip.c
Normal file
@@ -0,0 +1,596 @@
|
||||
/*
|
||||
* DictZip Block driver for dictzip enabled gzip files
|
||||
*
|
||||
* Use the "dictzip" tool from the "dictd" package to create gzip files that
|
||||
* contain the extra DictZip headers.
|
||||
*
|
||||
* dictzip(1) is a compression program which creates compressed files in the
|
||||
* gzip format (see RFC 1952). However, unlike gzip(1), dictzip(1) compresses
|
||||
* the file in pieces and stores an index to the pieces in the gzip header.
|
||||
* This allows random access to the file at the granularity of the compressed
|
||||
* pieces (currently about 64kB) while maintaining good compression ratios
|
||||
* (within 5% of the expected ratio for dictionary data).
|
||||
* dictd(8) uses files stored in this format.
|
||||
*
|
||||
* For details on DictZip see http://dict.org/.
|
||||
*
|
||||
* Copyright (c) 2009 Alexander Graf <agraf@suse.de>
|
||||
*
|
||||
* 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 "block/block_int.h"
|
||||
#include <zlib.h>
|
||||
|
||||
// #define DEBUG
|
||||
|
||||
#ifdef DEBUG
|
||||
#define dprintf(fmt, ...) do { printf("dzip: " fmt, ## __VA_ARGS__); } while (0)
|
||||
#else
|
||||
#define dprintf(fmt, ...) do { } while (0)
|
||||
#endif
|
||||
|
||||
#define SECTOR_SIZE 512
|
||||
#define Z_STREAM_COUNT 4
|
||||
#define CACHE_COUNT 20
|
||||
|
||||
/* magic values */
|
||||
|
||||
#define GZ_MAGIC1 0x1f
|
||||
#define GZ_MAGIC2 0x8b
|
||||
#define DZ_MAGIC1 'R'
|
||||
#define DZ_MAGIC2 'A'
|
||||
|
||||
#define GZ_FEXTRA 0x04 /* Optional field (random access index) */
|
||||
#define GZ_FNAME 0x08 /* Original name */
|
||||
#define GZ_COMMENT 0x10 /* Zero-terminated, human-readable comment */
|
||||
#define GZ_FHCRC 0x02 /* Header CRC16 */
|
||||
|
||||
/* offsets */
|
||||
|
||||
#define GZ_ID 0 /* GZ_MAGIC (16bit) */
|
||||
#define GZ_FLG 3 /* FLaGs (see above) */
|
||||
#define GZ_XLEN 10 /* eXtra LENgth (16bit) */
|
||||
#define GZ_SI 12 /* Subfield ID (16bit) */
|
||||
#define GZ_VERSION 16 /* Version for subfield format */
|
||||
#define GZ_CHUNKSIZE 18 /* Chunk size (16bit) */
|
||||
#define GZ_CHUNKCNT 20 /* Number of chunks (16bit) */
|
||||
#define GZ_RNDDATA 22 /* Random access data (16bit) */
|
||||
|
||||
#define GZ_99_CHUNKSIZE 18 /* Chunk size (32bit) */
|
||||
#define GZ_99_CHUNKCNT 22 /* Number of chunks (32bit) */
|
||||
#define GZ_99_FILESIZE 26 /* Size of unpacked file (64bit) */
|
||||
#define GZ_99_RNDDATA 34 /* Random access data (32bit) */
|
||||
|
||||
struct BDRVDictZipState;
|
||||
|
||||
typedef struct DictZipAIOCB {
|
||||
BlockDriverAIOCB common;
|
||||
struct BDRVDictZipState *s;
|
||||
QEMUIOVector *qiov; /* QIOV of the original request */
|
||||
QEMUIOVector *qiov_gz; /* QIOV of the gz subrequest */
|
||||
QEMUBH *bh; /* BH for cache */
|
||||
z_stream *zStream; /* stream to use for decoding */
|
||||
int zStream_id; /* stream id of the above pointer */
|
||||
size_t start; /* offset into the uncompressed file */
|
||||
size_t len; /* uncompressed bytes to read */
|
||||
uint8_t *gzipped; /* the gzipped data */
|
||||
uint8_t *buf; /* cached result */
|
||||
size_t gz_len; /* amount of gzip data */
|
||||
size_t gz_start; /* uncompressed starting point of gzip data */
|
||||
uint64_t offset; /* offset for "start" into the uncompressed chunk */
|
||||
int chunks_len; /* amount of uncompressed data in all gzip data */
|
||||
} DictZipAIOCB;
|
||||
|
||||
typedef struct dict_cache {
|
||||
size_t start;
|
||||
size_t len;
|
||||
uint8_t *buf;
|
||||
} DictCache;
|
||||
|
||||
typedef struct BDRVDictZipState {
|
||||
BlockDriverState *hd;
|
||||
z_stream zStream[Z_STREAM_COUNT];
|
||||
DictCache cache[CACHE_COUNT];
|
||||
int cache_index;
|
||||
uint8_t stream_in_use;
|
||||
uint64_t chunk_len;
|
||||
uint32_t chunk_cnt;
|
||||
uint16_t *chunks;
|
||||
uint32_t *chunks32;
|
||||
uint64_t *offsets;
|
||||
int64_t file_len;
|
||||
} BDRVDictZipState;
|
||||
|
||||
static int dictzip_probe(const uint8_t *buf, int buf_size, const char *filename)
|
||||
{
|
||||
if (buf_size < 2)
|
||||
return 0;
|
||||
|
||||
/* We match on every gzip file */
|
||||
if ((buf[0] == GZ_MAGIC1) && (buf[1] == GZ_MAGIC2))
|
||||
return 100;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int start_zStream(z_stream *zStream)
|
||||
{
|
||||
zStream->zalloc = NULL;
|
||||
zStream->zfree = NULL;
|
||||
zStream->opaque = NULL;
|
||||
zStream->next_in = 0;
|
||||
zStream->avail_in = 0;
|
||||
zStream->next_out = NULL;
|
||||
zStream->avail_out = 0;
|
||||
|
||||
return inflateInit2( zStream, -15 );
|
||||
}
|
||||
|
||||
static QemuOptsList runtime_opts = {
|
||||
.name = "dzip",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
|
||||
.desc = {
|
||||
{
|
||||
.name = "filename",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "URL to the dictzip file",
|
||||
},
|
||||
{ /* end of list */ }
|
||||
},
|
||||
};
|
||||
|
||||
static int dictzip_open(BlockDriverState *bs, QDict *options, int flags, Error **errp)
|
||||
{
|
||||
BDRVDictZipState *s = bs->opaque;
|
||||
const char *err = "Unknown (read error?)";
|
||||
uint8_t magic[2];
|
||||
char buf[100];
|
||||
uint8_t header_flags;
|
||||
uint16_t chunk_len16;
|
||||
uint16_t chunk_cnt16;
|
||||
uint16_t header_ver;
|
||||
uint16_t tmp_short;
|
||||
uint64_t offset;
|
||||
int chunks_len;
|
||||
int headerLength = GZ_XLEN - 1;
|
||||
int rnd_offs;
|
||||
int ret;
|
||||
int i;
|
||||
QemuOpts *opts;
|
||||
Error *local_err = NULL;
|
||||
const char *filename;
|
||||
|
||||
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
|
||||
qemu_opts_absorb_qdict(opts, options, &local_err);
|
||||
if (error_is_set(&local_err)) {
|
||||
error_propagate(errp, local_err);
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
filename = qemu_opt_get(opts, "filename");
|
||||
|
||||
if (!strncmp(filename, "dzip://", 7))
|
||||
filename += 7;
|
||||
else if (!strncmp(filename, "dzip:", 5))
|
||||
filename += 5;
|
||||
|
||||
ret = bdrv_open(&s->hd, filename, NULL, NULL, flags | BDRV_O_PROTOCOL, NULL, &local_err);
|
||||
if (ret < 0) {
|
||||
error_propagate(errp, local_err);
|
||||
qemu_opts_del(opts);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* initialize zlib streams */
|
||||
for (i = 0; i < Z_STREAM_COUNT; i++) {
|
||||
if (start_zStream( &s->zStream[i] ) != Z_OK) {
|
||||
err = s->zStream[i].msg;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* gzip header */
|
||||
if (bdrv_pread(s->hd, GZ_ID, &magic, sizeof(magic)) != sizeof(magic))
|
||||
goto fail;
|
||||
|
||||
if (!((magic[0] == GZ_MAGIC1) && (magic[1] == GZ_MAGIC2))) {
|
||||
err = "No gzip file";
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* dzip header */
|
||||
if (bdrv_pread(s->hd, GZ_FLG, &header_flags, 1) != 1)
|
||||
goto fail;
|
||||
|
||||
if (!(header_flags & GZ_FEXTRA)) {
|
||||
err = "Not a dictzip file (wrong flags)";
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* extra length */
|
||||
if (bdrv_pread(s->hd, GZ_XLEN, &tmp_short, 2) != 2)
|
||||
goto fail;
|
||||
|
||||
headerLength += le16_to_cpu(tmp_short) + 2;
|
||||
|
||||
/* DictZip magic */
|
||||
if (bdrv_pread(s->hd, GZ_SI, &magic, 2) != 2)
|
||||
goto fail;
|
||||
|
||||
if (magic[0] != DZ_MAGIC1 || magic[1] != DZ_MAGIC2) {
|
||||
err = "Not a dictzip file (missing extra magic)";
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* DictZip version */
|
||||
if (bdrv_pread(s->hd, GZ_VERSION, &header_ver, 2) != 2)
|
||||
goto fail;
|
||||
|
||||
header_ver = le16_to_cpu(header_ver);
|
||||
|
||||
switch (header_ver) {
|
||||
case 1: /* Normal DictZip */
|
||||
/* number of chunks */
|
||||
if (bdrv_pread(s->hd, GZ_CHUNKSIZE, &chunk_len16, 2) != 2)
|
||||
goto fail;
|
||||
|
||||
s->chunk_len = le16_to_cpu(chunk_len16);
|
||||
|
||||
/* chunk count */
|
||||
if (bdrv_pread(s->hd, GZ_CHUNKCNT, &chunk_cnt16, 2) != 2)
|
||||
goto fail;
|
||||
|
||||
s->chunk_cnt = le16_to_cpu(chunk_cnt16);
|
||||
chunks_len = sizeof(short) * s->chunk_cnt;
|
||||
rnd_offs = GZ_RNDDATA;
|
||||
break;
|
||||
case 99: /* Special Alex pigz version */
|
||||
/* number of chunks */
|
||||
if (bdrv_pread(s->hd, GZ_99_CHUNKSIZE, &s->chunk_len, 4) != 4)
|
||||
goto fail;
|
||||
|
||||
dprintf("chunk len [%#x] = %d\n", GZ_99_CHUNKSIZE, s->chunk_len);
|
||||
s->chunk_len = le32_to_cpu(s->chunk_len);
|
||||
|
||||
/* chunk count */
|
||||
if (bdrv_pread(s->hd, GZ_99_CHUNKCNT, &s->chunk_cnt, 4) != 4)
|
||||
goto fail;
|
||||
|
||||
s->chunk_cnt = le32_to_cpu(s->chunk_cnt);
|
||||
|
||||
dprintf("chunk len | count = %d | %d\n", s->chunk_len, s->chunk_cnt);
|
||||
|
||||
/* file size */
|
||||
if (bdrv_pread(s->hd, GZ_99_FILESIZE, &s->file_len, 8) != 8)
|
||||
goto fail;
|
||||
|
||||
s->file_len = le64_to_cpu(s->file_len);
|
||||
chunks_len = sizeof(int) * s->chunk_cnt;
|
||||
rnd_offs = GZ_99_RNDDATA;
|
||||
break;
|
||||
default:
|
||||
err = "Invalid DictZip version";
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* random access data */
|
||||
s->chunks = g_malloc(chunks_len);
|
||||
if (header_ver == 99)
|
||||
s->chunks32 = (uint32_t *)s->chunks;
|
||||
|
||||
if (bdrv_pread(s->hd, rnd_offs, s->chunks, chunks_len) != chunks_len)
|
||||
goto fail;
|
||||
|
||||
/* orig filename */
|
||||
if (header_flags & GZ_FNAME) {
|
||||
if (bdrv_pread(s->hd, headerLength + 1, buf, sizeof(buf)) != sizeof(buf))
|
||||
goto fail;
|
||||
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
headerLength += strlen(buf) + 1;
|
||||
|
||||
if (strlen(buf) == sizeof(buf))
|
||||
goto fail;
|
||||
|
||||
dprintf("filename: %s\n", buf);
|
||||
}
|
||||
|
||||
/* comment field */
|
||||
if (header_flags & GZ_COMMENT) {
|
||||
if (bdrv_pread(s->hd, headerLength, buf, sizeof(buf)) != sizeof(buf))
|
||||
goto fail;
|
||||
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
headerLength += strlen(buf) + 1;
|
||||
|
||||
if (strlen(buf) == sizeof(buf))
|
||||
goto fail;
|
||||
|
||||
dprintf("comment: %s\n", buf);
|
||||
}
|
||||
|
||||
if (header_flags & GZ_FHCRC)
|
||||
headerLength += 2;
|
||||
|
||||
/* uncompressed file length*/
|
||||
if (!s->file_len) {
|
||||
uint32_t file_len;
|
||||
|
||||
if (bdrv_pread(s->hd, bdrv_getlength(s->hd) - 4, &file_len, 4) != 4)
|
||||
goto fail;
|
||||
|
||||
s->file_len = le32_to_cpu(file_len);
|
||||
}
|
||||
|
||||
/* compute offsets */
|
||||
s->offsets = g_malloc(sizeof( *s->offsets ) * s->chunk_cnt);
|
||||
|
||||
for (offset = headerLength + 1, i = 0; i < s->chunk_cnt; i++) {
|
||||
s->offsets[i] = offset;
|
||||
switch (header_ver) {
|
||||
case 1:
|
||||
offset += s->chunks[i];
|
||||
break;
|
||||
case 99:
|
||||
offset += s->chunks32[i];
|
||||
break;
|
||||
}
|
||||
|
||||
dprintf("chunk %#x - %#x = offset %#x -> %#x\n", i * s->chunk_len, (i+1) * s->chunk_len, s->offsets[i], offset);
|
||||
}
|
||||
qemu_opts_del(opts);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
fprintf(stderr, "DictZip: Error opening file: %s\n", err);
|
||||
bdrv_unref(s->hd);
|
||||
if (s->chunks)
|
||||
g_free(s->chunks);
|
||||
qemu_opts_del(opts);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* This callback gets invoked when we have the result in cache already */
|
||||
static void dictzip_cache_cb(void *opaque)
|
||||
{
|
||||
DictZipAIOCB *acb = (DictZipAIOCB *)opaque;
|
||||
|
||||
qemu_iovec_from_buf(acb->qiov, 0, acb->buf, acb->len);
|
||||
acb->common.cb(acb->common.opaque, 0);
|
||||
qemu_bh_delete(acb->bh);
|
||||
qemu_aio_release(acb);
|
||||
}
|
||||
|
||||
/* This callback gets invoked by the underlying block reader when we have
|
||||
* all compressed data. We uncompress in here. */
|
||||
static void dictzip_read_cb(void *opaque, int ret)
|
||||
{
|
||||
DictZipAIOCB *acb = (DictZipAIOCB *)opaque;
|
||||
struct BDRVDictZipState *s = acb->s;
|
||||
uint8_t *buf;
|
||||
DictCache *cache;
|
||||
int r;
|
||||
|
||||
buf = g_malloc(acb->chunks_len);
|
||||
|
||||
/* uncompress the chunk */
|
||||
acb->zStream->next_in = acb->gzipped;
|
||||
acb->zStream->avail_in = acb->gz_len;
|
||||
acb->zStream->next_out = buf;
|
||||
acb->zStream->avail_out = acb->chunks_len;
|
||||
|
||||
r = inflate( acb->zStream, Z_PARTIAL_FLUSH );
|
||||
if ( (r != Z_OK) && (r != Z_STREAM_END) )
|
||||
fprintf(stderr, "Error inflating: [%d] %s\n", r, acb->zStream->msg);
|
||||
|
||||
if ( r == Z_STREAM_END )
|
||||
inflateReset(acb->zStream);
|
||||
|
||||
dprintf("inflating [%d] left: %d | %d bytes\n", r, acb->zStream->avail_in, acb->zStream->avail_out);
|
||||
s->stream_in_use &= ~(1 << acb->zStream_id);
|
||||
|
||||
/* nofity the caller */
|
||||
qemu_iovec_from_buf(acb->qiov, 0, buf + acb->offset, acb->len);
|
||||
acb->common.cb(acb->common.opaque, 0);
|
||||
|
||||
/* fill the cache */
|
||||
cache = &s->cache[s->cache_index];
|
||||
s->cache_index++;
|
||||
if (s->cache_index == CACHE_COUNT)
|
||||
s->cache_index = 0;
|
||||
|
||||
cache->len = 0;
|
||||
if (cache->buf)
|
||||
g_free(cache->buf);
|
||||
cache->start = acb->gz_start;
|
||||
cache->buf = buf;
|
||||
cache->len = acb->chunks_len;
|
||||
|
||||
/* free occupied ressources */
|
||||
g_free(acb->qiov_gz);
|
||||
qemu_aio_release(acb);
|
||||
}
|
||||
|
||||
static void dictzip_aio_cancel(BlockDriverAIOCB *blockacb)
|
||||
{
|
||||
}
|
||||
|
||||
static const AIOCBInfo dictzip_aiocb_info = {
|
||||
.aiocb_size = sizeof(DictZipAIOCB),
|
||||
.cancel = dictzip_aio_cancel,
|
||||
};
|
||||
|
||||
/* This is where we get a request from a caller to read something */
|
||||
static BlockDriverAIOCB *dictzip_aio_readv(BlockDriverState *bs,
|
||||
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
|
||||
BlockDriverCompletionFunc *cb, void *opaque)
|
||||
{
|
||||
BDRVDictZipState *s = bs->opaque;
|
||||
DictZipAIOCB *acb;
|
||||
QEMUIOVector *qiov_gz;
|
||||
struct iovec *iov;
|
||||
uint8_t *buf;
|
||||
size_t start = sector_num * SECTOR_SIZE;
|
||||
size_t len = nb_sectors * SECTOR_SIZE;
|
||||
size_t end = start + len;
|
||||
size_t gz_start;
|
||||
size_t gz_len;
|
||||
int64_t gz_sector_num;
|
||||
int gz_nb_sectors;
|
||||
int first_chunk, last_chunk;
|
||||
int first_offset;
|
||||
int i;
|
||||
|
||||
acb = qemu_aio_get(&dictzip_aiocb_info, bs, cb, opaque);
|
||||
if (!acb)
|
||||
return NULL;
|
||||
|
||||
/* Search Cache */
|
||||
for (i = 0; i < CACHE_COUNT; i++) {
|
||||
if (!s->cache[i].len)
|
||||
continue;
|
||||
|
||||
if ((start >= s->cache[i].start) &&
|
||||
(end <= (s->cache[i].start + s->cache[i].len))) {
|
||||
acb->buf = s->cache[i].buf + (start - s->cache[i].start);
|
||||
acb->len = len;
|
||||
acb->qiov = qiov;
|
||||
acb->bh = qemu_bh_new(dictzip_cache_cb, acb);
|
||||
qemu_bh_schedule(acb->bh);
|
||||
|
||||
return &acb->common;
|
||||
}
|
||||
}
|
||||
|
||||
/* No cache, so let's decode */
|
||||
do {
|
||||
for (i = 0; i < Z_STREAM_COUNT; i++) {
|
||||
if (!(s->stream_in_use & (1 << i))) {
|
||||
s->stream_in_use |= (1 << i);
|
||||
acb->zStream_id = i;
|
||||
acb->zStream = &s->zStream[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while(!acb->zStream);
|
||||
|
||||
/* We need to read these chunks */
|
||||
first_chunk = start / s->chunk_len;
|
||||
first_offset = start - first_chunk * s->chunk_len;
|
||||
last_chunk = end / s->chunk_len;
|
||||
|
||||
gz_start = s->offsets[first_chunk];
|
||||
gz_len = 0;
|
||||
for (i = first_chunk; i <= last_chunk; i++) {
|
||||
if (s->chunks32)
|
||||
gz_len += s->chunks32[i];
|
||||
else
|
||||
gz_len += s->chunks[i];
|
||||
}
|
||||
|
||||
gz_sector_num = gz_start / SECTOR_SIZE;
|
||||
gz_nb_sectors = (gz_len / SECTOR_SIZE);
|
||||
|
||||
/* account for tail and heads */
|
||||
while ((gz_start + gz_len) > ((gz_sector_num + gz_nb_sectors) * SECTOR_SIZE))
|
||||
gz_nb_sectors++;
|
||||
|
||||
/* Allocate qiov, iov and buf in one chunk so we only need to free qiov */
|
||||
qiov_gz = g_malloc0(sizeof(QEMUIOVector) + sizeof(struct iovec) +
|
||||
(gz_nb_sectors * SECTOR_SIZE));
|
||||
iov = (struct iovec *)(((char *)qiov_gz) + sizeof(QEMUIOVector));
|
||||
buf = ((uint8_t *)iov) + sizeof(struct iovec *);
|
||||
|
||||
/* Kick off the read by the backing file, so we can start decompressing */
|
||||
iov->iov_base = (void *)buf;
|
||||
iov->iov_len = gz_nb_sectors * 512;
|
||||
qemu_iovec_init_external(qiov_gz, iov, 1);
|
||||
|
||||
dprintf("read %d - %d => %d - %d\n", start, end, gz_start, gz_start + gz_len);
|
||||
|
||||
acb->s = s;
|
||||
acb->qiov = qiov;
|
||||
acb->qiov_gz = qiov_gz;
|
||||
acb->start = start;
|
||||
acb->len = len;
|
||||
acb->gzipped = buf + (gz_start % SECTOR_SIZE);
|
||||
acb->gz_len = gz_len;
|
||||
acb->gz_start = first_chunk * s->chunk_len;
|
||||
acb->offset = first_offset;
|
||||
acb->chunks_len = (last_chunk - first_chunk + 1) * s->chunk_len;
|
||||
|
||||
return bdrv_aio_readv(s->hd, gz_sector_num, qiov_gz, gz_nb_sectors,
|
||||
dictzip_read_cb, acb);
|
||||
}
|
||||
|
||||
static void dictzip_close(BlockDriverState *bs)
|
||||
{
|
||||
BDRVDictZipState *s = bs->opaque;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CACHE_COUNT; i++) {
|
||||
if (!s->cache[i].len)
|
||||
continue;
|
||||
|
||||
g_free(s->cache[i].buf);
|
||||
}
|
||||
|
||||
for (i = 0; i < Z_STREAM_COUNT; i++) {
|
||||
inflateEnd(&s->zStream[i]);
|
||||
}
|
||||
|
||||
if (s->chunks)
|
||||
g_free(s->chunks);
|
||||
|
||||
if (s->offsets)
|
||||
g_free(s->offsets);
|
||||
|
||||
dprintf("Close\n");
|
||||
}
|
||||
|
||||
static int64_t dictzip_getlength(BlockDriverState *bs)
|
||||
{
|
||||
BDRVDictZipState *s = bs->opaque;
|
||||
dprintf("getlength -> %ld\n", s->file_len);
|
||||
return s->file_len;
|
||||
}
|
||||
|
||||
static BlockDriver bdrv_dictzip = {
|
||||
.format_name = "dzip",
|
||||
.protocol_name = "dzip",
|
||||
|
||||
.instance_size = sizeof(BDRVDictZipState),
|
||||
.bdrv_file_open = dictzip_open,
|
||||
.bdrv_close = dictzip_close,
|
||||
.bdrv_getlength = dictzip_getlength,
|
||||
.bdrv_probe = dictzip_probe,
|
||||
|
||||
.bdrv_aio_readv = dictzip_aio_readv,
|
||||
};
|
||||
|
||||
static void dictzip_block_init(void)
|
||||
{
|
||||
bdrv_register(&bdrv_dictzip);
|
||||
}
|
||||
|
||||
block_init(dictzip_block_init);
|
395
block/tar.c
Normal file
395
block/tar.c
Normal file
@@ -0,0 +1,395 @@
|
||||
/*
|
||||
* Tar block driver
|
||||
*
|
||||
* Copyright (c) 2009 Alexander Graf <agraf@suse.de>
|
||||
*
|
||||
* 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 "block/block_int.h"
|
||||
|
||||
// #define DEBUG
|
||||
|
||||
#ifdef DEBUG
|
||||
#define dprintf(fmt, ...) do { printf("tar: " fmt, ## __VA_ARGS__); } while (0)
|
||||
#else
|
||||
#define dprintf(fmt, ...) do { } while (0)
|
||||
#endif
|
||||
|
||||
#define SECTOR_SIZE 512
|
||||
|
||||
#define POSIX_TAR_MAGIC "ustar"
|
||||
#define OFFS_LENGTH 0x7c
|
||||
#define OFFS_TYPE 0x9c
|
||||
#define OFFS_MAGIC 0x101
|
||||
|
||||
#define OFFS_S_SP 0x182
|
||||
#define OFFS_S_EXT 0x1e2
|
||||
#define OFFS_S_LENGTH 0x1e3
|
||||
#define OFFS_SX_EXT 0x1f8
|
||||
|
||||
typedef struct SparseCache {
|
||||
uint64_t start;
|
||||
uint64_t end;
|
||||
} SparseCache;
|
||||
|
||||
typedef struct BDRVTarState {
|
||||
BlockDriverState *hd;
|
||||
size_t file_sec;
|
||||
uint64_t file_len;
|
||||
SparseCache *sparse;
|
||||
int sparse_num;
|
||||
uint64_t last_end;
|
||||
char longfile[2048];
|
||||
} BDRVTarState;
|
||||
|
||||
static int tar_probe(const uint8_t *buf, int buf_size, const char *filename)
|
||||
{
|
||||
if (buf_size < OFFS_MAGIC + 5)
|
||||
return 0;
|
||||
|
||||
/* we only support newer tar */
|
||||
if (!strncmp((char*)buf + OFFS_MAGIC, POSIX_TAR_MAGIC, 5))
|
||||
return 100;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int str_ends(char *str, const char *end)
|
||||
{
|
||||
int end_len = strlen(end);
|
||||
int str_len = strlen(str);
|
||||
|
||||
if (str_len < end_len)
|
||||
return 0;
|
||||
|
||||
return !strncmp(str + str_len - end_len, end, end_len);
|
||||
}
|
||||
|
||||
static int is_target_file(BlockDriverState *bs, char *filename,
|
||||
char *header)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
if (str_ends(filename, ".raw"))
|
||||
retval = 1;
|
||||
|
||||
if (str_ends(filename, ".qcow"))
|
||||
retval = 1;
|
||||
|
||||
if (str_ends(filename, ".qcow2"))
|
||||
retval = 1;
|
||||
|
||||
if (str_ends(filename, ".vmdk"))
|
||||
retval = 1;
|
||||
|
||||
if (retval &&
|
||||
(header[OFFS_TYPE] != '0') &&
|
||||
(header[OFFS_TYPE] != 'S')) {
|
||||
retval = 0;
|
||||
}
|
||||
|
||||
dprintf("does filename %s match? %s\n", filename, retval ? "yes" : "no");
|
||||
|
||||
/* make sure we're not using this name again */
|
||||
filename[0] = '\0';
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static uint64_t tar2u64(char *ptr)
|
||||
{
|
||||
uint64_t retval;
|
||||
char oldend = ptr[12];
|
||||
|
||||
ptr[12] = '\0';
|
||||
if (*ptr & 0x80) {
|
||||
/* XXX we only support files up to 64 bit length */
|
||||
retval = be64_to_cpu(*(uint64_t *)(ptr+4));
|
||||
dprintf("Convert %lx -> %#lx\n", *(uint64_t*)(ptr+4), retval);
|
||||
} else {
|
||||
retval = strtol(ptr, NULL, 8);
|
||||
dprintf("Convert %s -> %#lx\n", ptr, retval);
|
||||
}
|
||||
|
||||
ptr[12] = oldend;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void tar_sparse(BDRVTarState *s, uint64_t offs, uint64_t len)
|
||||
{
|
||||
SparseCache *sparse;
|
||||
|
||||
if (!len)
|
||||
return;
|
||||
if (!(offs - s->last_end)) {
|
||||
s->last_end += len;
|
||||
return;
|
||||
}
|
||||
if (s->last_end > offs)
|
||||
return;
|
||||
|
||||
dprintf("Last chunk until %lx new chunk at %lx\n", s->last_end, offs);
|
||||
|
||||
s->sparse = g_realloc(s->sparse, (s->sparse_num + 1) * sizeof(SparseCache));
|
||||
sparse = &s->sparse[s->sparse_num];
|
||||
sparse->start = s->last_end;
|
||||
sparse->end = offs;
|
||||
s->last_end = offs + len;
|
||||
s->sparse_num++;
|
||||
dprintf("Sparse at %lx end=%lx\n", sparse->start,
|
||||
sparse->end);
|
||||
}
|
||||
|
||||
static QemuOptsList runtime_opts = {
|
||||
.name = "tar",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
|
||||
.desc = {
|
||||
{
|
||||
.name = "filename",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "URL to the tar file",
|
||||
},
|
||||
{ /* end of list */ }
|
||||
},
|
||||
};
|
||||
|
||||
static int tar_open(BlockDriverState *bs, QDict *options, int flags, Error **errp)
|
||||
{
|
||||
BDRVTarState *s = bs->opaque;
|
||||
char header[SECTOR_SIZE];
|
||||
char *real_file = header;
|
||||
char *magic;
|
||||
size_t header_offs = 0;
|
||||
int ret;
|
||||
QemuOpts *opts;
|
||||
Error *local_err = NULL;
|
||||
const char *filename;
|
||||
|
||||
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
|
||||
qemu_opts_absorb_qdict(opts, options, &local_err);
|
||||
if (error_is_set(&local_err)) {
|
||||
error_propagate(errp, local_err);
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
filename = qemu_opt_get(opts, "filename");
|
||||
|
||||
if (!strncmp(filename, "tar://", 6))
|
||||
filename += 6;
|
||||
else if (!strncmp(filename, "tar:", 4))
|
||||
filename += 4;
|
||||
|
||||
ret = bdrv_open(&s->hd, filename, NULL, NULL, flags | BDRV_O_PROTOCOL, NULL, &local_err);
|
||||
if (ret < 0) {
|
||||
error_propagate(errp, local_err);
|
||||
qemu_opts_del(opts);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Search the file for an image */
|
||||
|
||||
do {
|
||||
/* tar header */
|
||||
if (bdrv_pread(s->hd, header_offs, header, SECTOR_SIZE) != SECTOR_SIZE)
|
||||
goto fail;
|
||||
|
||||
if ((header_offs > 1) && !header[0]) {
|
||||
fprintf(stderr, "Tar: No image file found in archive\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
magic = &header[OFFS_MAGIC];
|
||||
if (strncmp(magic, POSIX_TAR_MAGIC, 5)) {
|
||||
fprintf(stderr, "Tar: Invalid magic: %s\n", magic);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dprintf("file type: %c\n", header[OFFS_TYPE]);
|
||||
|
||||
/* file length*/
|
||||
s->file_len = (tar2u64(&header[OFFS_LENGTH]) + (SECTOR_SIZE - 1)) &
|
||||
~(SECTOR_SIZE - 1);
|
||||
s->file_sec = (header_offs / SECTOR_SIZE) + 1;
|
||||
|
||||
header_offs += s->file_len + SECTOR_SIZE;
|
||||
|
||||
if (header[OFFS_TYPE] == 'L') {
|
||||
bdrv_pread(s->hd, header_offs - s->file_len, s->longfile,
|
||||
sizeof(s->longfile));
|
||||
s->longfile[sizeof(s->longfile)-1] = '\0';
|
||||
real_file = header;
|
||||
} else if (s->longfile[0]) {
|
||||
real_file = s->longfile;
|
||||
} else {
|
||||
real_file = header;
|
||||
}
|
||||
} while(!is_target_file(bs, real_file, header));
|
||||
|
||||
/* We found an image! */
|
||||
|
||||
if (header[OFFS_TYPE] == 'S') {
|
||||
uint8_t isextended;
|
||||
int i;
|
||||
|
||||
for (i = OFFS_S_SP; i < (OFFS_S_SP + (4 * 24)); i += 24)
|
||||
tar_sparse(s, tar2u64(&header[i]), tar2u64(&header[i+12]));
|
||||
|
||||
s->file_len = tar2u64(&header[OFFS_S_LENGTH]);
|
||||
isextended = header[OFFS_S_EXT];
|
||||
|
||||
while (isextended) {
|
||||
if (bdrv_pread(s->hd, s->file_sec * SECTOR_SIZE, header,
|
||||
SECTOR_SIZE) != SECTOR_SIZE)
|
||||
goto fail;
|
||||
|
||||
for (i = 0; i < (21 * 24); i += 24)
|
||||
tar_sparse(s, tar2u64(&header[i]), tar2u64(&header[i+12]));
|
||||
isextended = header[OFFS_SX_EXT];
|
||||
s->file_sec++;
|
||||
}
|
||||
tar_sparse(s, s->file_len, 1);
|
||||
}
|
||||
qemu_opts_del(opts);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
fprintf(stderr, "Tar: Error opening file\n");
|
||||
bdrv_unref(s->hd);
|
||||
qemu_opts_del(opts);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
typedef struct TarAIOCB {
|
||||
BlockDriverAIOCB common;
|
||||
QEMUBH *bh;
|
||||
} TarAIOCB;
|
||||
|
||||
/* This callback gets invoked when we have pure sparseness */
|
||||
static void tar_sparse_cb(void *opaque)
|
||||
{
|
||||
TarAIOCB *acb = (TarAIOCB *)opaque;
|
||||
|
||||
acb->common.cb(acb->common.opaque, 0);
|
||||
qemu_bh_delete(acb->bh);
|
||||
qemu_aio_release(acb);
|
||||
}
|
||||
|
||||
static void tar_aio_cancel(BlockDriverAIOCB *blockacb)
|
||||
{
|
||||
}
|
||||
|
||||
static AIOCBInfo tar_aiocb_info = {
|
||||
.aiocb_size = sizeof(TarAIOCB),
|
||||
.cancel = tar_aio_cancel,
|
||||
};
|
||||
|
||||
/* This is where we get a request from a caller to read something */
|
||||
static BlockDriverAIOCB *tar_aio_readv(BlockDriverState *bs,
|
||||
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
|
||||
BlockDriverCompletionFunc *cb, void *opaque)
|
||||
{
|
||||
BDRVTarState *s = bs->opaque;
|
||||
SparseCache *sparse;
|
||||
int64_t sec_file = sector_num + s->file_sec;
|
||||
int64_t start = sector_num * SECTOR_SIZE;
|
||||
int64_t end = start + (nb_sectors * SECTOR_SIZE);
|
||||
int i;
|
||||
TarAIOCB *acb;
|
||||
|
||||
for (i = 0; i < s->sparse_num; i++) {
|
||||
sparse = &s->sparse[i];
|
||||
if (sparse->start > end) {
|
||||
/* We expect the cache to be start increasing */
|
||||
break;
|
||||
} else if ((sparse->start < start) && (sparse->end <= start)) {
|
||||
/* sparse before our offset */
|
||||
sec_file -= (sparse->end - sparse->start) / SECTOR_SIZE;
|
||||
} else if ((sparse->start <= start) && (sparse->end >= end)) {
|
||||
/* all our sectors are sparse */
|
||||
char *buf = g_malloc0(nb_sectors * SECTOR_SIZE);
|
||||
|
||||
acb = qemu_aio_get(&tar_aiocb_info, bs, cb, opaque);
|
||||
qemu_iovec_from_buf(qiov, 0, buf, nb_sectors * SECTOR_SIZE);
|
||||
g_free(buf);
|
||||
acb->bh = qemu_bh_new(tar_sparse_cb, acb);
|
||||
qemu_bh_schedule(acb->bh);
|
||||
|
||||
return &acb->common;
|
||||
} else if (((sparse->start >= start) && (sparse->start < end)) ||
|
||||
((sparse->end >= start) && (sparse->end < end))) {
|
||||
/* we're semi-sparse (worst case) */
|
||||
/* let's go synchronous and read all sectors individually */
|
||||
char *buf = g_malloc(nb_sectors * SECTOR_SIZE);
|
||||
uint64_t offs;
|
||||
|
||||
for (offs = 0; offs < (nb_sectors * SECTOR_SIZE);
|
||||
offs += SECTOR_SIZE) {
|
||||
bdrv_pread(bs, (sector_num * SECTOR_SIZE) + offs,
|
||||
buf + offs, SECTOR_SIZE);
|
||||
}
|
||||
|
||||
qemu_iovec_from_buf(qiov, 0, buf, nb_sectors * SECTOR_SIZE);
|
||||
acb = qemu_aio_get(&tar_aiocb_info, bs, cb, opaque);
|
||||
acb->bh = qemu_bh_new(tar_sparse_cb, acb);
|
||||
qemu_bh_schedule(acb->bh);
|
||||
|
||||
return &acb->common;
|
||||
}
|
||||
}
|
||||
|
||||
return bdrv_aio_readv(s->hd, sec_file, qiov, nb_sectors,
|
||||
cb, opaque);
|
||||
}
|
||||
|
||||
static void tar_close(BlockDriverState *bs)
|
||||
{
|
||||
dprintf("Close\n");
|
||||
}
|
||||
|
||||
static int64_t tar_getlength(BlockDriverState *bs)
|
||||
{
|
||||
BDRVTarState *s = bs->opaque;
|
||||
dprintf("getlength -> %ld\n", s->file_len);
|
||||
return s->file_len;
|
||||
}
|
||||
|
||||
static BlockDriver bdrv_tar = {
|
||||
.format_name = "tar",
|
||||
.protocol_name = "tar",
|
||||
|
||||
.instance_size = sizeof(BDRVTarState),
|
||||
.bdrv_file_open = tar_open,
|
||||
.bdrv_close = tar_close,
|
||||
.bdrv_getlength = tar_getlength,
|
||||
.bdrv_probe = tar_probe,
|
||||
|
||||
.bdrv_aio_readv = tar_aio_readv,
|
||||
};
|
||||
|
||||
static void tar_block_init(void)
|
||||
{
|
||||
bdrv_register(&bdrv_tar);
|
||||
}
|
||||
|
||||
block_init(tar_block_init);
|
@@ -1744,11 +1744,13 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
|
||||
fmt = options->value.s;
|
||||
} else if (!strcmp(options->name, BLOCK_OPT_ZEROED_GRAIN)) {
|
||||
zeroed_grain |= options->value.n;
|
||||
} else if (!strcmp(options->name, BLOCK_OPT_SCSI)) {
|
||||
flags |= options->value.n ? BLOCK_FLAG_SCSI: 0;
|
||||
}
|
||||
options++;
|
||||
}
|
||||
if (!adapter_type) {
|
||||
adapter_type = "ide";
|
||||
adapter_type = flags & BLOCK_FLAG_SCSI ? "lsilogic" : "ide";
|
||||
} else if (strcmp(adapter_type, "ide") &&
|
||||
strcmp(adapter_type, "buslogic") &&
|
||||
strcmp(adapter_type, "lsilogic") &&
|
||||
@@ -2096,6 +2098,11 @@ static QEMUOptionParameter vmdk_create_options[] = {
|
||||
.type = OPT_FLAG,
|
||||
.help = "Enable efficient zero writes using the zeroed-grain GTE feature"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_SCSI,
|
||||
.type = OPT_FLAG,
|
||||
.help = "SCSI image"
|
||||
},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
2
configure
vendored
2
configure
vendored
@@ -1487,7 +1487,7 @@ fi
|
||||
|
||||
if test "$pie" = ""; then
|
||||
case "$cpu-$targetos" in
|
||||
i386-Linux|x86_64-Linux|x32-Linux|i386-OpenBSD|x86_64-OpenBSD)
|
||||
i386-Linux|x86_64-Linux|x32-Linux|ppc*-Linux|i386-OpenBSD|x86_64-OpenBSD)
|
||||
;;
|
||||
*)
|
||||
pie="no"
|
||||
|
@@ -139,7 +139,6 @@ static const VMStateDescription vmstate_kbd = {
|
||||
.name = "pckbd",
|
||||
.version_id = 3,
|
||||
.minimum_version_id = 3,
|
||||
.minimum_version_id_old = 3,
|
||||
.fields = (VMStateField []) {
|
||||
VMSTATE_UINT8(write_cmd, KBDState),
|
||||
VMSTATE_UINT8(status, KBDState),
|
||||
@@ -168,12 +167,13 @@ You can see that there are several version fields:
|
||||
- minimum_version_id: the minimum version_id that VMState is able to understand
|
||||
for that device.
|
||||
- minimum_version_id_old: For devices that were not able to port to vmstate, we can
|
||||
assign a function that knows how to read this old state.
|
||||
assign a function that knows how to read this old state. This field is
|
||||
ignored if there is no load_state_old handler.
|
||||
|
||||
So, VMState is able to read versions from minimum_version_id to
|
||||
version_id. And the function load_state_old() is able to load state
|
||||
from minimum_version_id_old to minimum_version_id. This function is
|
||||
deprecated and will be removed when no more users are left.
|
||||
version_id. And the function load_state_old() (if present) is able to
|
||||
load state from minimum_version_id_old to minimum_version_id. This
|
||||
function is deprecated and will be removed when no more users are left.
|
||||
|
||||
=== Massaging functions ===
|
||||
|
||||
@@ -255,7 +255,6 @@ const VMStateDescription vmstate_ide_drive_pio_state = {
|
||||
.name = "ide_drive/pio_state",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.minimum_version_id_old = 1,
|
||||
.pre_save = ide_drive_pio_pre_save,
|
||||
.post_load = ide_drive_pio_post_load,
|
||||
.fields = (VMStateField []) {
|
||||
@@ -275,7 +274,6 @@ const VMStateDescription vmstate_ide_drive = {
|
||||
.name = "ide_drive",
|
||||
.version_id = 3,
|
||||
.minimum_version_id = 0,
|
||||
.minimum_version_id_old = 0,
|
||||
.post_load = ide_drive_post_load,
|
||||
.fields = (VMStateField []) {
|
||||
.... several fields ....
|
||||
|
2
exec.c
2
exec.c
@@ -1039,10 +1039,12 @@ static void *file_ram_alloc(RAMBlock *block,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef TARGET_PPC
|
||||
if (kvm_enabled() && !kvm_has_sync_mmu()) {
|
||||
fprintf(stderr, "host lacks kvm mmu notifiers, -mem-path unsupported\n");
|
||||
goto error;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Make name safe to use with mkstemp by replacing '/' with '_'. */
|
||||
sanitized_name = g_strdup(block->mr->name);
|
||||
|
@@ -9,6 +9,13 @@
|
||||
* the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
/* work around a broken sys/capability.h */
|
||||
#if defined(__i386__)
|
||||
typedef unsigned long long __u64;
|
||||
#endif
|
||||
#if defined(__powerpc64__)
|
||||
#include <asm/types.h>
|
||||
#endif
|
||||
#include <sys/resource.h>
|
||||
#include <getopt.h>
|
||||
#include <syslog.h>
|
||||
|
@@ -732,7 +732,7 @@ static void pxa2xx_ssp_save(QEMUFile *f, void *opaque)
|
||||
static int pxa2xx_ssp_load(QEMUFile *f, void *opaque, int version_id)
|
||||
{
|
||||
PXA2xxSSPState *s = (PXA2xxSSPState *) opaque;
|
||||
int i;
|
||||
int i, v;
|
||||
|
||||
s->enable = qemu_get_be32(f);
|
||||
|
||||
@@ -746,7 +746,11 @@ static int pxa2xx_ssp_load(QEMUFile *f, void *opaque, int version_id)
|
||||
qemu_get_8s(f, &s->ssrsa);
|
||||
qemu_get_8s(f, &s->ssacd);
|
||||
|
||||
s->rx_level = qemu_get_byte(f);
|
||||
v = qemu_get_byte(f);
|
||||
if (v < 0 || v > ARRAY_SIZE(s->rx_fifo)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
s->rx_level = v;
|
||||
s->rx_start = 0;
|
||||
for (i = 0; i < s->rx_level; i ++)
|
||||
s->rx_fifo[i] = qemu_get_byte(f);
|
||||
|
@@ -79,6 +79,12 @@ static inline void blkif_get_x86_32_req(blkif_request_t *dst, blkif_x86_32_reque
|
||||
dst->handle = src->handle;
|
||||
dst->id = src->id;
|
||||
dst->sector_number = src->sector_number;
|
||||
if (src->operation == BLKIF_OP_DISCARD) {
|
||||
struct blkif_request_discard *s = (void *)src;
|
||||
struct blkif_request_discard *d = (void *)dst;
|
||||
d->nr_sectors = s->nr_sectors;
|
||||
return;
|
||||
}
|
||||
if (n > src->nr_segments)
|
||||
n = src->nr_segments;
|
||||
for (i = 0; i < n; i++)
|
||||
@@ -94,6 +100,12 @@ static inline void blkif_get_x86_64_req(blkif_request_t *dst, blkif_x86_64_reque
|
||||
dst->handle = src->handle;
|
||||
dst->id = src->id;
|
||||
dst->sector_number = src->sector_number;
|
||||
if (src->operation == BLKIF_OP_DISCARD) {
|
||||
struct blkif_request_discard *s = (void *)src;
|
||||
struct blkif_request_discard *d = (void *)dst;
|
||||
d->nr_sectors = s->nr_sectors;
|
||||
return;
|
||||
}
|
||||
if (n > src->nr_segments)
|
||||
n = src->nr_segments;
|
||||
for (i = 0; i < n; i++)
|
||||
|
@@ -114,6 +114,7 @@ struct XenBlkDev {
|
||||
int requests_finished;
|
||||
|
||||
/* Persistent grants extension */
|
||||
gboolean feature_discard;
|
||||
gboolean feature_persistent;
|
||||
GTree *persistent_gnts;
|
||||
unsigned int persistent_gnt_count;
|
||||
@@ -253,6 +254,8 @@ static int ioreq_parse(struct ioreq *ioreq)
|
||||
case BLKIF_OP_WRITE:
|
||||
ioreq->prot = PROT_READ; /* from memory */
|
||||
break;
|
||||
case BLKIF_OP_DISCARD:
|
||||
return 0;
|
||||
default:
|
||||
xen_be_printf(&blkdev->xendev, 0, "error: unknown operation (%d)\n",
|
||||
ioreq->req.operation);
|
||||
@@ -532,6 +535,17 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
|
||||
&ioreq->v, ioreq->v.size / BLOCK_SIZE,
|
||||
qemu_aio_complete, ioreq);
|
||||
break;
|
||||
case BLKIF_OP_DISCARD:
|
||||
{
|
||||
struct blkif_request_discard *discard_req = (void *)&ioreq->req;
|
||||
bdrv_acct_start(blkdev->bs, &ioreq->acct,
|
||||
discard_req->nr_sectors * BLOCK_SIZE, BDRV_ACCT_WRITE);
|
||||
ioreq->aio_inflight++;
|
||||
bdrv_aio_discard(blkdev->bs,
|
||||
discard_req->sector_number, discard_req->nr_sectors,
|
||||
qemu_aio_complete, ioreq);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* unknown operation (shouldn't happen -- parse catches this) */
|
||||
goto err;
|
||||
@@ -710,6 +724,21 @@ static void blk_alloc(struct XenDevice *xendev)
|
||||
}
|
||||
}
|
||||
|
||||
static void blk_parse_discard(struct XenBlkDev *blkdev)
|
||||
{
|
||||
int enable;
|
||||
|
||||
blkdev->feature_discard = true;
|
||||
|
||||
if (xenstore_read_be_int(&blkdev->xendev, "discard-enable", &enable) == 0) {
|
||||
blkdev->feature_discard = !!enable;
|
||||
}
|
||||
|
||||
if (blkdev->feature_discard) {
|
||||
xenstore_write_be_int(&blkdev->xendev, "feature-discard", 1);
|
||||
}
|
||||
}
|
||||
|
||||
static int blk_init(struct XenDevice *xendev)
|
||||
{
|
||||
struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev);
|
||||
@@ -777,6 +806,8 @@ static int blk_init(struct XenDevice *xendev)
|
||||
xenstore_write_be_int(&blkdev->xendev, "feature-persistent", 1);
|
||||
xenstore_write_be_int(&blkdev->xendev, "info", info);
|
||||
|
||||
blk_parse_discard(blkdev);
|
||||
|
||||
g_free(directiosafe);
|
||||
return 0;
|
||||
|
||||
@@ -812,6 +843,9 @@ static int blk_connect(struct XenDevice *xendev)
|
||||
qflags |= BDRV_O_RDWR;
|
||||
readonly = false;
|
||||
}
|
||||
if (blkdev->feature_discard) {
|
||||
qflags |= BDRV_O_UNMAP;
|
||||
}
|
||||
|
||||
/* init qemu block driver */
|
||||
index = (blkdev->xendev.dev - 202 * 256) / 16;
|
||||
|
@@ -312,18 +312,42 @@ static int ssd0323_load(QEMUFile *f, void *opaque, int version_id)
|
||||
return -EINVAL;
|
||||
|
||||
s->cmd_len = qemu_get_be32(f);
|
||||
if (s->cmd_len < 0 || s->cmd_len > ARRAY_SIZE(s->cmd_data)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
s->cmd = qemu_get_be32(f);
|
||||
for (i = 0; i < 8; i++)
|
||||
s->cmd_data[i] = qemu_get_be32(f);
|
||||
s->row = qemu_get_be32(f);
|
||||
if (s->row < 0 || s->row >= 80) {
|
||||
return -EINVAL;
|
||||
}
|
||||
s->row_start = qemu_get_be32(f);
|
||||
if (s->row_start < 0 || s->row_start >= 80) {
|
||||
return -EINVAL;
|
||||
}
|
||||
s->row_end = qemu_get_be32(f);
|
||||
if (s->row_end < 0 || s->row_end >= 80) {
|
||||
return -EINVAL;
|
||||
}
|
||||
s->col = qemu_get_be32(f);
|
||||
if (s->col < 0 || s->col >= 64) {
|
||||
return -EINVAL;
|
||||
}
|
||||
s->col_start = qemu_get_be32(f);
|
||||
if (s->col_start < 0 || s->col_start >= 64) {
|
||||
return -EINVAL;
|
||||
}
|
||||
s->col_end = qemu_get_be32(f);
|
||||
if (s->col_end < 0 || s->col_end >= 64) {
|
||||
return -EINVAL;
|
||||
}
|
||||
s->redraw = qemu_get_be32(f);
|
||||
s->remap = qemu_get_be32(f);
|
||||
s->mode = qemu_get_be32(f);
|
||||
if (s->mode != SSD0323_CMD && s->mode != SSD0323_DATA) {
|
||||
return -EINVAL;
|
||||
}
|
||||
qemu_get_buffer(f, s->framebuffer, sizeof(s->framebuffer));
|
||||
|
||||
ss->cs = qemu_get_be32(f);
|
||||
|
@@ -203,6 +203,15 @@ static bool is_version_0 (void *opaque, int version_id)
|
||||
return version_id == 0;
|
||||
}
|
||||
|
||||
static bool vmstate_scoop_validate(void *opaque, int version_id)
|
||||
{
|
||||
ScoopInfo *s = opaque;
|
||||
|
||||
return !(s->prev_level & 0xffff0000) &&
|
||||
!(s->gpio_level & 0xffff0000) &&
|
||||
!(s->gpio_dir & 0xffff0000);
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_scoop_regs = {
|
||||
.name = "scoop",
|
||||
.version_id = 1,
|
||||
@@ -215,6 +224,7 @@ static const VMStateDescription vmstate_scoop_regs = {
|
||||
VMSTATE_UINT32(gpio_level, ScoopInfo),
|
||||
VMSTATE_UINT32(gpio_dir, ScoopInfo),
|
||||
VMSTATE_UINT32(prev_level, ScoopInfo),
|
||||
VMSTATE_VALIDATE("irq levels are 16 bit", vmstate_scoop_validate),
|
||||
VMSTATE_UINT16(mcr, ScoopInfo),
|
||||
VMSTATE_UINT16(cdr, ScoopInfo),
|
||||
VMSTATE_UINT16(ccr, ScoopInfo),
|
||||
|
@@ -1293,7 +1293,7 @@ const VMStateDescription vmstate_ahci = {
|
||||
VMSTATE_UINT32(control_regs.impl, AHCIState),
|
||||
VMSTATE_UINT32(control_regs.version, AHCIState),
|
||||
VMSTATE_UINT32(idp_index, AHCIState),
|
||||
VMSTATE_INT32(ports, AHCIState),
|
||||
VMSTATE_INT32_EQUAL(ports, AHCIState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
},
|
||||
};
|
||||
|
@@ -1070,9 +1070,21 @@ static int tsc210x_load(QEMUFile *f, void *opaque, int version_id)
|
||||
s->enabled = qemu_get_byte(f);
|
||||
s->host_mode = qemu_get_byte(f);
|
||||
s->function = qemu_get_byte(f);
|
||||
if (s->function < 0 || s->function >= ARRAY_SIZE(mode_regs)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
s->nextfunction = qemu_get_byte(f);
|
||||
if (s->nextfunction < 0 || s->nextfunction >= ARRAY_SIZE(mode_regs)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
s->precision = qemu_get_byte(f);
|
||||
if (s->precision < 0 || s->precision >= ARRAY_SIZE(resolution)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
s->nextprecision = qemu_get_byte(f);
|
||||
if (s->nextprecision < 0 || s->nextprecision >= ARRAY_SIZE(resolution)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
s->filter = qemu_get_byte(f);
|
||||
s->pin_func = qemu_get_byte(f);
|
||||
s->ref = qemu_get_byte(f);
|
||||
|
@@ -41,6 +41,7 @@
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/pci/msi.h"
|
||||
#include "qemu/bitops.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
|
||||
//#define DEBUG_OPENPIC
|
||||
|
||||
@@ -1416,7 +1417,7 @@ static void openpic_load_IRQ_queue(QEMUFile* f, IRQQueue *q)
|
||||
static int openpic_load(QEMUFile* f, void *opaque, int version_id)
|
||||
{
|
||||
OpenPICState *opp = (OpenPICState *)opaque;
|
||||
unsigned int i;
|
||||
unsigned int i, nb_cpus;
|
||||
|
||||
if (version_id != 1) {
|
||||
return -EINVAL;
|
||||
@@ -1428,7 +1429,11 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
|
||||
qemu_get_be32s(f, &opp->spve);
|
||||
qemu_get_be32s(f, &opp->tfrr);
|
||||
|
||||
qemu_get_be32s(f, &opp->nb_cpus);
|
||||
qemu_get_be32s(f, &nb_cpus);
|
||||
if (opp->nb_cpus != nb_cpus) {
|
||||
return -EINVAL;
|
||||
}
|
||||
assert(nb_cpus > 0 && nb_cpus <= MAX_CPU);
|
||||
|
||||
for (i = 0; i < opp->nb_cpus; i++) {
|
||||
qemu_get_sbe32s(f, &opp->dst[i].ctpr);
|
||||
@@ -1567,6 +1572,13 @@ static void openpic_realize(DeviceState *dev, Error **errp)
|
||||
{NULL}
|
||||
};
|
||||
|
||||
if (opp->nb_cpus > MAX_CPU) {
|
||||
error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
|
||||
TYPE_OPENPIC, "nb_cpus", (uint64_t)opp->nb_cpus,
|
||||
(uint64_t)0, (uint64_t)MAX_CPU);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (opp->model) {
|
||||
case OPENPIC_MODEL_FSL_MPIC_20:
|
||||
default:
|
||||
|
@@ -1362,10 +1362,17 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
|
||||
if (n->mac_table.in_use <= MAC_TABLE_ENTRIES) {
|
||||
qemu_get_buffer(f, n->mac_table.macs,
|
||||
n->mac_table.in_use * ETH_ALEN);
|
||||
} else if (n->mac_table.in_use) {
|
||||
uint8_t *buf = g_malloc0(n->mac_table.in_use);
|
||||
qemu_get_buffer(f, buf, n->mac_table.in_use * ETH_ALEN);
|
||||
g_free(buf);
|
||||
} else {
|
||||
int64_t i;
|
||||
|
||||
/* Overflow detected - can happen if source has a larger MAC table.
|
||||
* We simply set overflow flag so there's no need to maintain the
|
||||
* table of addresses, discard them all.
|
||||
* Note: 64 bit math to avoid integer overflow.
|
||||
*/
|
||||
for (i = 0; i < (int64_t)n->mac_table.in_use * ETH_ALEN; ++i) {
|
||||
qemu_get_byte(f);
|
||||
}
|
||||
n->mac_table.multi_overflow = n->mac_table.uni_overflow = 1;
|
||||
n->mac_table.in_use = 0;
|
||||
}
|
||||
@@ -1407,6 +1414,11 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
|
||||
}
|
||||
|
||||
n->curr_queues = qemu_get_be16(f);
|
||||
if (n->curr_queues > n->max_queues) {
|
||||
error_report("virtio-net: curr_queues %x > max_queues %x",
|
||||
n->curr_queues, n->max_queues);
|
||||
return -1;
|
||||
}
|
||||
for (i = 1; i < n->curr_queues; i++) {
|
||||
n->vqs[i].tx_waiting = qemu_get_be32(f);
|
||||
}
|
||||
|
@@ -475,7 +475,7 @@ const VMStateDescription vmstate_pci_device = {
|
||||
.minimum_version_id = 1,
|
||||
.minimum_version_id_old = 1,
|
||||
.fields = (VMStateField []) {
|
||||
VMSTATE_INT32_LE(version_id, PCIDevice),
|
||||
VMSTATE_INT32_POSITIVE_LE(version_id, PCIDevice),
|
||||
VMSTATE_BUFFER_UNSAFE_INFO(config, PCIDevice, 0,
|
||||
vmstate_info_pci_config,
|
||||
PCI_CONFIG_SPACE_SIZE),
|
||||
@@ -492,7 +492,7 @@ const VMStateDescription vmstate_pcie_device = {
|
||||
.minimum_version_id = 1,
|
||||
.minimum_version_id_old = 1,
|
||||
.fields = (VMStateField []) {
|
||||
VMSTATE_INT32_LE(version_id, PCIDevice),
|
||||
VMSTATE_INT32_POSITIVE_LE(version_id, PCIDevice),
|
||||
VMSTATE_BUFFER_UNSAFE_INFO(config, PCIDevice, 0,
|
||||
vmstate_info_pci_config,
|
||||
PCIE_CONFIG_SPACE_SIZE),
|
||||
|
@@ -795,6 +795,13 @@ static const VMStateDescription vmstate_pcie_aer_err = {
|
||||
}
|
||||
};
|
||||
|
||||
static bool pcie_aer_state_log_num_valid(void *opaque, int version_id)
|
||||
{
|
||||
PCIEAERLog *s = opaque;
|
||||
|
||||
return s->log_num <= s->log_max;
|
||||
}
|
||||
|
||||
const VMStateDescription vmstate_pcie_aer_log = {
|
||||
.name = "PCIE_AER_ERROR_LOG",
|
||||
.version_id = 1,
|
||||
@@ -802,7 +809,8 @@ const VMStateDescription vmstate_pcie_aer_log = {
|
||||
.minimum_version_id_old = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT16(log_num, PCIEAERLog),
|
||||
VMSTATE_UINT16(log_max, PCIEAERLog),
|
||||
VMSTATE_UINT16_EQUAL(log_max, PCIEAERLog),
|
||||
VMSTATE_VALIDATE("log_num <= log_max", pcie_aer_state_log_num_valid),
|
||||
VMSTATE_STRUCT_VARRAY_POINTER_UINT16(log, PCIEAERLog, log_num,
|
||||
vmstate_pcie_aer_err, PCIEAERErr),
|
||||
VMSTATE_END_OF_LIST()
|
||||
|
@@ -147,6 +147,15 @@ static void *virtio_scsi_load_request(QEMUFile *f, SCSIRequest *sreq)
|
||||
qemu_get_be32s(f, &n);
|
||||
assert(n < vs->conf.num_queues);
|
||||
qemu_get_buffer(f, (unsigned char *)&req->elem, sizeof(req->elem));
|
||||
/* TODO: add a way for SCSIBusInfo's load_request to fail,
|
||||
* and fail migration instead of asserting here.
|
||||
* When we do, we might be able to re-enable NDEBUG below.
|
||||
*/
|
||||
#ifdef NDEBUG
|
||||
#error building with NDEBUG is not supported
|
||||
#endif
|
||||
assert(req->elem.in_num <= ARRAY_SIZE(req->elem.in_sg));
|
||||
assert(req->elem.out_num <= ARRAY_SIZE(req->elem.out_sg));
|
||||
virtio_scsi_parse_req(s, vs->cmd_vqs[n], req);
|
||||
|
||||
scsi_req_ref(sreq);
|
||||
|
@@ -230,8 +230,17 @@ static int ssi_sd_load(QEMUFile *f, void *opaque, int version_id)
|
||||
for (i = 0; i < 5; i++)
|
||||
s->response[i] = qemu_get_be32(f);
|
||||
s->arglen = qemu_get_be32(f);
|
||||
if (s->mode == SSI_SD_CMDARG &&
|
||||
(s->arglen < 0 || s->arglen >= ARRAY_SIZE(s->cmdarg))) {
|
||||
return -EINVAL;
|
||||
}
|
||||
s->response_pos = qemu_get_be32(f);
|
||||
s->stopping = qemu_get_be32(f);
|
||||
if (s->mode == SSI_SD_RESPONSE &&
|
||||
(s->response_pos < 0 || s->response_pos >= ARRAY_SIZE(s->response) ||
|
||||
(!s->stopping && s->arglen > ARRAY_SIZE(s->response)))) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ss->cs = qemu_get_be32(f);
|
||||
|
||||
|
@@ -240,11 +240,25 @@ static const MemoryRegionOps pl022_ops = {
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
static int pl022_post_load(void *opaque, int version_id)
|
||||
{
|
||||
PL022State *s = opaque;
|
||||
|
||||
if (s->tx_fifo_head < 0 ||
|
||||
s->tx_fifo_head >= ARRAY_SIZE(s->tx_fifo) ||
|
||||
s->rx_fifo_head < 0 ||
|
||||
s->rx_fifo_head >= ARRAY_SIZE(s->rx_fifo)) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_pl022 = {
|
||||
.name = "pl022_ssp",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.minimum_version_id_old = 1,
|
||||
.post_load = pl022_post_load,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT32(cr0, PL022State),
|
||||
VMSTATE_UINT32(cr1, PL022State),
|
||||
|
@@ -239,6 +239,18 @@ static int hpet_pre_load(void *opaque)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool hpet_validate_num_timers(void *opaque, int version_id)
|
||||
{
|
||||
HPETState *s = opaque;
|
||||
|
||||
if (s->num_timers < HPET_MIN_TIMERS) {
|
||||
return false;
|
||||
} else if (s->num_timers > HPET_MAX_TIMERS) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int hpet_post_load(void *opaque, int version_id)
|
||||
{
|
||||
HPETState *s = opaque;
|
||||
@@ -307,6 +319,7 @@ static const VMStateDescription vmstate_hpet = {
|
||||
VMSTATE_UINT64(isr, HPETState),
|
||||
VMSTATE_UINT64(hpet_counter, HPETState),
|
||||
VMSTATE_UINT8_V(num_timers, HPETState, 2),
|
||||
VMSTATE_VALIDATE("num_timers in range", hpet_validate_num_timers),
|
||||
VMSTATE_STRUCT_VARRAY_UINT8(timer, HPETState, num_timers, 0,
|
||||
vmstate_hpet_timer, HPETTimer),
|
||||
VMSTATE_END_OF_LIST()
|
||||
|
@@ -49,7 +49,9 @@ static int usb_device_post_load(void *opaque, int version_id)
|
||||
} else {
|
||||
dev->attached = 1;
|
||||
}
|
||||
if (dev->setup_index >= sizeof(dev->data_buf) ||
|
||||
if (dev->setup_index < 0 ||
|
||||
dev->setup_len < 0 ||
|
||||
dev->setup_index >= sizeof(dev->data_buf) ||
|
||||
dev->setup_len >= sizeof(dev->data_buf)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@@ -430,6 +430,12 @@ void virtqueue_map_sg(struct iovec *sg, hwaddr *addr,
|
||||
unsigned int i;
|
||||
hwaddr len;
|
||||
|
||||
if (num_sg > VIRTQUEUE_MAX_SIZE) {
|
||||
error_report("virtio: map attempt out of bounds: %zd > %d",
|
||||
num_sg, VIRTQUEUE_MAX_SIZE);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (i = 0; i < num_sg; i++) {
|
||||
len = sg[i].iov_len;
|
||||
sg[i].iov_base = cpu_physical_memory_map(addr[i], &len, is_write);
|
||||
@@ -891,7 +897,9 @@ int virtio_set_features(VirtIODevice *vdev, uint32_t val)
|
||||
|
||||
int virtio_load(VirtIODevice *vdev, QEMUFile *f)
|
||||
{
|
||||
int num, i, ret;
|
||||
int i, ret;
|
||||
int32_t config_len;
|
||||
uint32_t num;
|
||||
uint32_t features;
|
||||
uint32_t supported_features;
|
||||
BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
|
||||
@@ -906,6 +914,9 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
|
||||
qemu_get_8s(f, &vdev->status);
|
||||
qemu_get_8s(f, &vdev->isr);
|
||||
qemu_get_be16s(f, &vdev->queue_sel);
|
||||
if (vdev->queue_sel >= VIRTIO_PCI_QUEUE_MAX) {
|
||||
return -1;
|
||||
}
|
||||
qemu_get_be32s(f, &features);
|
||||
|
||||
if (virtio_set_features(vdev, features) < 0) {
|
||||
@@ -914,11 +925,21 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
|
||||
features, supported_features);
|
||||
return -1;
|
||||
}
|
||||
vdev->config_len = qemu_get_be32(f);
|
||||
config_len = qemu_get_be32(f);
|
||||
if (config_len != vdev->config_len) {
|
||||
error_report("Unexpected config length 0x%x. Expected 0x%zx",
|
||||
config_len, vdev->config_len);
|
||||
return -1;
|
||||
}
|
||||
qemu_get_buffer(f, vdev->config, vdev->config_len);
|
||||
|
||||
num = qemu_get_be32(f);
|
||||
|
||||
if (num > VIRTIO_PCI_QUEUE_MAX) {
|
||||
error_report("Invalid number of PCI queues: 0x%x", num);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
vdev->vq[i].vring.num = qemu_get_be32(f);
|
||||
if (k->has_variable_vring_alignment) {
|
||||
|
@@ -40,10 +40,12 @@
|
||||
#define BLOCK_FLAG_ENCRYPT 1
|
||||
#define BLOCK_FLAG_COMPAT6 4
|
||||
#define BLOCK_FLAG_LAZY_REFCOUNTS 8
|
||||
#define BLOCK_FLAG_SCSI 16
|
||||
|
||||
#define BLOCK_OPT_SIZE "size"
|
||||
#define BLOCK_OPT_ENCRYPT "encryption"
|
||||
#define BLOCK_OPT_COMPAT6 "compat6"
|
||||
#define BLOCK_OPT_SCSI "scsi"
|
||||
#define BLOCK_OPT_BACKING_FILE "backing_file"
|
||||
#define BLOCK_OPT_BACKING_FMT "backing_fmt"
|
||||
#define BLOCK_OPT_CLUSTER_SIZE "cluster_size"
|
||||
|
@@ -24,6 +24,12 @@
|
||||
#include <pthread.h>
|
||||
#define spin_lock pthread_mutex_lock
|
||||
#define spin_unlock pthread_mutex_unlock
|
||||
static inline void spin_unlock_safe(pthread_mutex_t *lock)
|
||||
{
|
||||
/* unlocking an unlocked mutex results in undefined behavior */
|
||||
pthread_mutex_trylock(lock);
|
||||
pthread_mutex_unlock(lock);
|
||||
}
|
||||
#define spinlock_t pthread_mutex_t
|
||||
#define SPIN_LOCK_UNLOCKED PTHREAD_MUTEX_INITIALIZER
|
||||
|
||||
@@ -46,4 +52,8 @@ static inline void spin_unlock(spinlock_t *lock)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void spin_unlock_safe(spinlock_t *lock)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -38,6 +38,7 @@ typedef enum argtype {
|
||||
TYPE_ARRAY,
|
||||
TYPE_STRUCT,
|
||||
TYPE_OLDDEVT,
|
||||
TYPE_INTBITFIELD,
|
||||
} argtype;
|
||||
|
||||
#define MK_PTR(type) TYPE_PTR, type
|
||||
@@ -91,6 +92,7 @@ static inline int thunk_type_size(const argtype *type_ptr, int is_host)
|
||||
case TYPE_SHORT:
|
||||
return 2;
|
||||
case TYPE_INT:
|
||||
case TYPE_INTBITFIELD:
|
||||
return 4;
|
||||
case TYPE_LONGLONG:
|
||||
case TYPE_ULONGLONG:
|
||||
@@ -153,6 +155,7 @@ static inline int thunk_type_align(const argtype *type_ptr, int is_host)
|
||||
case TYPE_SHORT:
|
||||
return 2;
|
||||
case TYPE_INT:
|
||||
case TYPE_INTBITFIELD:
|
||||
return 4;
|
||||
case TYPE_LONGLONG:
|
||||
case TYPE_ULONGLONG:
|
||||
|
@@ -176,8 +176,8 @@ typedef struct VirtIONet {
|
||||
uint8_t nobcast;
|
||||
uint8_t vhost_started;
|
||||
struct {
|
||||
int in_use;
|
||||
int first_multi;
|
||||
uint32_t in_use;
|
||||
uint32_t first_multi;
|
||||
uint8_t multi_overflow;
|
||||
uint8_t uni_overflow;
|
||||
uint8_t *macs;
|
||||
|
@@ -100,6 +100,7 @@ enum VMStateFlags {
|
||||
VMS_MULTIPLY = 0x200, /* multiply "size" field by field_size */
|
||||
VMS_VARRAY_UINT8 = 0x400, /* Array with size in uint8_t field*/
|
||||
VMS_VARRAY_UINT32 = 0x800, /* Array with size in uint32_t field*/
|
||||
VMS_MUST_EXIST = 0x1000, /* Field must exist in input */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
@@ -203,6 +204,14 @@ extern const VMStateInfo vmstate_info_bitmap;
|
||||
.offset = vmstate_offset_value(_state, _field, _type), \
|
||||
}
|
||||
|
||||
/* Validate state using a boolean predicate. */
|
||||
#define VMSTATE_VALIDATE(_name, _test) { \
|
||||
.name = (_name), \
|
||||
.field_exists = (_test), \
|
||||
.flags = VMS_ARRAY | VMS_MUST_EXIST, \
|
||||
.num = 0, /* 0 elements: no data, only run _test */ \
|
||||
}
|
||||
|
||||
#define VMSTATE_POINTER(_field, _state, _version, _info, _type) { \
|
||||
.name = (stringify(_field)), \
|
||||
.version_id = (_version), \
|
||||
@@ -592,7 +601,7 @@ extern const VMStateInfo vmstate_info_bitmap;
|
||||
#define VMSTATE_UINT64_EQUAL(_f, _s) \
|
||||
VMSTATE_UINT64_EQUAL_V(_f, _s, 0)
|
||||
|
||||
#define VMSTATE_INT32_LE(_f, _s) \
|
||||
#define VMSTATE_INT32_POSITIVE_LE(_f, _s) \
|
||||
VMSTATE_SINGLE(_f, _s, 0, vmstate_info_int32_le, int32_t)
|
||||
|
||||
#define VMSTATE_UINT8_TEST(_f, _s, _t) \
|
||||
|
@@ -5,3 +5,5 @@ obj-$(TARGET_HAS_BFLT) += flatload.o
|
||||
obj-$(TARGET_I386) += vm86.o
|
||||
obj-$(TARGET_ARM) += arm/nwfpe/
|
||||
obj-$(TARGET_M68K) += m68k-sim.o
|
||||
|
||||
obj-binfmt-y = binfmt.o
|
||||
|
67
linux-user/binfmt.c
Normal file
67
linux-user/binfmt.c
Normal file
@@ -0,0 +1,67 @@
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <libgen.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __x86_64__
|
||||
#define ARCH_NAME "x86_64"
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
char *binfmt;
|
||||
char **new_argv;
|
||||
|
||||
/*
|
||||
* Check if our file name ends with -binfmt
|
||||
*/
|
||||
binfmt = argv[0] + strlen(argv[0]) - strlen("-binfmt");
|
||||
if (strcmp(binfmt, "-binfmt")) {
|
||||
fprintf(stderr, "%s: Invalid executable name\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
if (argc < 3) {
|
||||
fprintf(stderr, "%s: Please use me through binfmt with P flag\n",
|
||||
argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
binfmt[0] = '\0';
|
||||
/* Now argv[0] is the real qemu binary name */
|
||||
|
||||
#ifdef ARCH_NAME
|
||||
{
|
||||
char *hostbin;
|
||||
char *guestarch;
|
||||
|
||||
guestarch = strrchr(argv[0], '-') ;
|
||||
if (!guestarch) {
|
||||
goto skip;
|
||||
}
|
||||
guestarch++;
|
||||
asprintf(&hostbin, "/emul/" ARCH_NAME "-for-%s/%s", guestarch, argv[1]);
|
||||
if (!access(hostbin, X_OK)) {
|
||||
/*
|
||||
* We found a host binary replacement for the non-host binary. Let's
|
||||
* use that instead!
|
||||
*/
|
||||
return execve(hostbin, &argv[2], envp);
|
||||
}
|
||||
}
|
||||
skip:
|
||||
#endif
|
||||
|
||||
new_argv = (char **)malloc((argc + 2) * sizeof(*new_argv));
|
||||
if (argc > 3) {
|
||||
memcpy(&new_argv[4], &argv[3], (argc - 3) * sizeof(*new_argv));
|
||||
}
|
||||
new_argv[0] = argv[0];
|
||||
new_argv[1] = (char *)"-0";
|
||||
new_argv[2] = argv[2];
|
||||
new_argv[3] = argv[1];
|
||||
new_argv[argc + 1] = NULL;
|
||||
|
||||
return execve(new_argv[0], new_argv, envp);
|
||||
}
|
@@ -71,6 +71,24 @@
|
||||
IOCTL(BLKGETSIZE, IOC_R, MK_PTR(TYPE_ULONG))
|
||||
#ifdef BLKGETSIZE64
|
||||
IOCTL(BLKGETSIZE64, IOC_R, MK_PTR(TYPE_ULONGLONG))
|
||||
#endif
|
||||
#ifdef BLKDISCARD
|
||||
IOCTL(BLKDISCARD, IOC_W, MK_PTR(MK_STRUCT(STRUCT_blkdiscard)))
|
||||
#endif
|
||||
#ifdef BLKIOMIN
|
||||
IOCTL(BLKIOMIN, IOC_R, MK_PTR(TYPE_INT))
|
||||
#endif
|
||||
#ifdef BLKIOOPT
|
||||
IOCTL(BLKIOOPT, IOC_R, MK_PTR(TYPE_INT))
|
||||
#endif
|
||||
#ifdef BLKALIGNOFF
|
||||
IOCTL(BLKALIGNOFF, IOC_R, MK_PTR(TYPE_INT))
|
||||
#endif
|
||||
#ifdef BLKPBSZGET
|
||||
IOCTL(BLKPBSZGET, IOC_R, MK_PTR(TYPE_INT))
|
||||
#endif
|
||||
#ifdef BLKDISCARDZEROES
|
||||
IOCTL(BLKDISCARDZEROES, IOC_R, MK_PTR(TYPE_INT))
|
||||
#endif
|
||||
IOCTL(BLKFLSBUF, 0, TYPE_NULL)
|
||||
IOCTL(BLKRASET, 0, TYPE_INT)
|
||||
@@ -88,6 +106,8 @@
|
||||
IOCTL_SPECIAL(FS_IOC_FIEMAP, IOC_W | IOC_R, do_ioctl_fs_ioc_fiemap,
|
||||
MK_PTR(MK_STRUCT(STRUCT_fiemap)))
|
||||
#endif
|
||||
IOCTL(FS_IOC_GETFLAGS, IOC_R, MK_PTR(TYPE_LONG))
|
||||
IOCTL(FS_IOC_SETFLAGS, IOC_W, MK_PTR(TYPE_LONG))
|
||||
|
||||
IOCTL(SIOCATMARK, 0, TYPE_NULL)
|
||||
IOCTL(SIOCGIFNAME, IOC_RW, MK_PTR(TYPE_INT))
|
||||
@@ -316,6 +336,11 @@
|
||||
IOCTL(VFAT_IOCTL_READDIR_BOTH, IOC_R, MK_PTR(MK_ARRAY(MK_STRUCT(STRUCT_dirent), 2)))
|
||||
IOCTL(VFAT_IOCTL_READDIR_SHORT, IOC_R, MK_PTR(MK_ARRAY(MK_STRUCT(STRUCT_dirent), 2)))
|
||||
|
||||
/* FIXME: including these on x86 / x86_64 breaks qemu-i386 */
|
||||
#ifdef __powerpc__
|
||||
#include "ioctls_alsa.h"
|
||||
#endif
|
||||
|
||||
IOCTL(LOOP_SET_FD, 0, TYPE_INT)
|
||||
IOCTL(LOOP_CLR_FD, 0, TYPE_INT)
|
||||
IOCTL(LOOP_SET_STATUS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info)))
|
||||
@@ -323,6 +348,7 @@
|
||||
IOCTL(LOOP_SET_STATUS64, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info64)))
|
||||
IOCTL(LOOP_GET_STATUS64, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info64)))
|
||||
IOCTL(LOOP_CHANGE_FD, 0, TYPE_INT)
|
||||
IOCTL_SPECIAL(LOOP_BOGUS_CMD, 0, do_ioctl_fail, TYPE_INT)
|
||||
|
||||
IOCTL(MTIOCTOP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_mtop)))
|
||||
IOCTL(MTIOCGET, IOC_R, MK_PTR(MK_STRUCT(STRUCT_mtget)))
|
||||
|
467
linux-user/ioctls_alsa.h
Normal file
467
linux-user/ioctls_alsa.h
Normal file
@@ -0,0 +1,467 @@
|
||||
#define SNDRV_SEQ_IOCTL_PVERSION _IOR ('S', 0x00, int)
|
||||
#define SNDRV_SEQ_IOCTL_CLIENT_ID _IOR ('S', 0x01, int)
|
||||
#define SNDRV_SEQ_IOCTL_SYSTEM_INFO _IOWR('S', 0x02, struct sndrv_seq_system_info)
|
||||
#define SNDRV_SEQ_IOCTL_RUNNING_MODE _IOWR('S', 0x03, struct sndrv_seq_running_info)
|
||||
#define SNDRV_SEQ_IOCTL_GET_CLIENT_INFO _IOWR('S', 0x10, struct sndrv_seq_client_info)
|
||||
#define SNDRV_SEQ_IOCTL_SET_CLIENT_INFO _IOW ('S', 0x11, struct sndrv_seq_client_info)
|
||||
#define SNDRV_SEQ_IOCTL_CREATE_PORT _IOWR('S', 0x20, struct sndrv_seq_port_info)
|
||||
#define SNDRV_SEQ_IOCTL_DELETE_PORT _IOW ('S', 0x21, struct sndrv_seq_port_info)
|
||||
#define SNDRV_SEQ_IOCTL_GET_PORT_INFO _IOWR('S', 0x22, struct sndrv_seq_port_info)
|
||||
#define SNDRV_SEQ_IOCTL_SET_PORT_INFO _IOW ('S', 0x23, struct sndrv_seq_port_info)
|
||||
#define SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT _IOW ('S', 0x30, struct sndrv_seq_port_subscribe)
|
||||
#define SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT _IOW ('S', 0x31, struct sndrv_seq_port_subscribe)
|
||||
#define SNDRV_SEQ_IOCTL_CREATE_QUEUE _IOWR('S', 0x32, struct sndrv_seq_queue_info)
|
||||
#define SNDRV_SEQ_IOCTL_DELETE_QUEUE _IOW ('S', 0x33, struct sndrv_seq_queue_info)
|
||||
#define SNDRV_SEQ_IOCTL_GET_QUEUE_INFO _IOWR('S', 0x34, struct sndrv_seq_queue_info)
|
||||
#define SNDRV_SEQ_IOCTL_SET_QUEUE_INFO _IOWR('S', 0x35, struct sndrv_seq_queue_info)
|
||||
#define SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE _IOWR('S', 0x36, struct sndrv_seq_queue_info)
|
||||
#define SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS _IOWR('S', 0x40, struct sndrv_seq_queue_status)
|
||||
#define SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO _IOWR('S', 0x41, struct sndrv_seq_queue_tempo)
|
||||
#define SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO _IOW ('S', 0x42, struct sndrv_seq_queue_tempo)
|
||||
#define SNDRV_SEQ_IOCTL_GET_QUEUE_OWNER _IOWR('S', 0x43, struct sndrv_seq_queue_owner)
|
||||
#define SNDRV_SEQ_IOCTL_SET_QUEUE_OWNER _IOW ('S', 0x44, struct sndrv_seq_queue_owner)
|
||||
#define SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER _IOWR('S', 0x45, struct sndrv_seq_queue_timer)
|
||||
#define SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER _IOW ('S', 0x46, struct sndrv_seq_queue_timer)
|
||||
#define SNDRV_SEQ_IOCTL_GET_QUEUE_SYNC _IOWR('S', 0x53, struct sndrv_seq_queue_sync)
|
||||
#define SNDRV_SEQ_IOCTL_SET_QUEUE_SYNC _IOW ('S', 0x54, struct sndrv_seq_queue_sync)
|
||||
#define SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT _IOWR('S', 0x49, struct sndrv_seq_queue_client)
|
||||
#define SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT _IOW ('S', 0x4a, struct sndrv_seq_queue_client)
|
||||
#define SNDRV_SEQ_IOCTL_GET_CLIENT_POOL _IOWR('S', 0x4b, struct sndrv_seq_client_pool)
|
||||
#define SNDRV_SEQ_IOCTL_SET_CLIENT_POOL _IOW ('S', 0x4c, struct sndrv_seq_client_pool)
|
||||
#define SNDRV_SEQ_IOCTL_REMOVE_EVENTS _IOW ('S', 0x4e, struct sndrv_seq_remove_events)
|
||||
#define SNDRV_SEQ_IOCTL_QUERY_SUBS _IOWR('S', 0x4f, struct sndrv_seq_query_subs)
|
||||
#define SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION _IOWR('S', 0x50, struct sndrv_seq_port_subscribe)
|
||||
#define SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT _IOWR('S', 0x51, struct sndrv_seq_client_info)
|
||||
#define SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT _IOWR('S', 0x52, struct sndrv_seq_port_info)
|
||||
#define SNDRV_DM_FM_IOCTL_INFO _IOR('H', 0x20, snd_dm_fm_info_t)
|
||||
#define SNDRV_DM_FM_IOCTL_RESET _IO ('H', 0x21)
|
||||
#define SNDRV_DM_FM_IOCTL_PLAY_NOTE _IOW('H', 0x22, snd_dm_fm_note_t)
|
||||
#define SNDRV_DM_FM_IOCTL_SET_VOICE _IOW('H', 0x23, snd_dm_fm_voice_t)
|
||||
#define SNDRV_DM_FM_IOCTL_SET_PARAMS _IOW('H', 0x24, snd_dm_fm_params_t)
|
||||
#define SNDRV_DM_FM_IOCTL_SET_MODE _IOW('H', 0x25, int)
|
||||
#define SNDRV_DM_FM_IOCTL_SET_CONNECTION _IOW('H', 0x26, int)
|
||||
#define SNDRV_DM_FM_OSS_IOCTL_RESET 0x20
|
||||
#define SNDRV_DM_FM_OSS_IOCTL_PLAY_NOTE 0x21
|
||||
#define SNDRV_DM_FM_OSS_IOCTL_SET_VOICE 0x22
|
||||
#define SNDRV_DM_FM_OSS_IOCTL_SET_PARAMS 0x23
|
||||
#define SNDRV_DM_FM_OSS_IOCTL_SET_MODE 0x24
|
||||
#define SNDRV_DM_FM_OSS_IOCTL_SET_OPL 0x25
|
||||
#define SNDRV_HWDEP_IOCTL_PVERSION _IOR ('H', 0x00, int)
|
||||
#define SNDRV_HWDEP_IOCTL_INFO _IOR ('H', 0x01, struct sndrv_hwdep_info)
|
||||
#define SNDRV_HWDEP_IOCTL_DSP_STATUS _IOR('H', 0x02, struct sndrv_hwdep_dsp_status)
|
||||
#define SNDRV_HWDEP_IOCTL_DSP_LOAD _IOW('H', 0x03, struct sndrv_hwdep_dsp_image)
|
||||
#define SNDRV_PCM_IOCTL_PVERSION _IOR('A', 0x00, int)
|
||||
#define SNDRV_PCM_IOCTL_INFO _IOR('A', 0x01, struct sndrv_pcm_info)
|
||||
#define SNDRV_PCM_IOCTL_TSTAMP _IOW('A', 0x02, int)
|
||||
#define SNDRV_PCM_IOCTL_HW_REFINE _IOWR('A', 0x10, struct sndrv_pcm_hw_params)
|
||||
#define SNDRV_PCM_IOCTL_HW_PARAMS _IOWR('A', 0x11, struct sndrv_pcm_hw_params)
|
||||
#define SNDRV_PCM_IOCTL_HW_FREE _IO('A', 0x12)
|
||||
#define SNDRV_PCM_IOCTL_SW_PARAMS _IOWR('A', 0x13, struct sndrv_pcm_sw_params)
|
||||
#define SNDRV_PCM_IOCTL_STATUS _IOR('A', 0x20, struct sndrv_pcm_status)
|
||||
#define SNDRV_PCM_IOCTL_DELAY _IOR('A', 0x21, sndrv_pcm_sframes_t)
|
||||
#define SNDRV_PCM_IOCTL_HWSYNC _IO('A', 0x22)
|
||||
#define SNDRV_PCM_IOCTL_SYNC_PTR _IOWR('A', 0x23, struct sndrv_pcm_sync_ptr)
|
||||
#define SNDRV_PCM_IOCTL_CHANNEL_INFO _IOR('A', 0x32, struct sndrv_pcm_channel_info)
|
||||
#define SNDRV_PCM_IOCTL_PREPARE _IO('A', 0x40)
|
||||
#define SNDRV_PCM_IOCTL_RESET _IO('A', 0x41)
|
||||
#define SNDRV_PCM_IOCTL_START _IO('A', 0x42)
|
||||
#define SNDRV_PCM_IOCTL_DROP _IO('A', 0x43)
|
||||
#define SNDRV_PCM_IOCTL_DRAIN _IO('A', 0x44)
|
||||
#define SNDRV_PCM_IOCTL_PAUSE _IOW('A', 0x45, int)
|
||||
#define SNDRV_PCM_IOCTL_REWIND _IOW('A', 0x46, sndrv_pcm_uframes_t)
|
||||
#define SNDRV_PCM_IOCTL_RESUME _IO('A', 0x47)
|
||||
#define SNDRV_PCM_IOCTL_XRUN _IO('A', 0x48)
|
||||
#define SNDRV_PCM_IOCTL_FORWARD _IOW('A', 0x49, sndrv_pcm_uframes_t)
|
||||
#define SNDRV_PCM_IOCTL_WRITEI_FRAMES _IOW('A', 0x50, struct sndrv_xferi)
|
||||
#define SNDRV_PCM_IOCTL_READI_FRAMES _IOR('A', 0x51, struct sndrv_xferi)
|
||||
#define SNDRV_PCM_IOCTL_WRITEN_FRAMES _IOW('A', 0x52, struct sndrv_xfern)
|
||||
#define SNDRV_PCM_IOCTL_READN_FRAMES _IOR('A', 0x53, struct sndrv_xfern)
|
||||
#define SNDRV_PCM_IOCTL_LINK _IOW('A', 0x60, int)
|
||||
#define SNDRV_PCM_IOCTL_UNLINK _IO('A', 0x61)
|
||||
#define SNDRV_RAWMIDI_IOCTL_PVERSION _IOR('W', 0x00, int)
|
||||
#define SNDRV_RAWMIDI_IOCTL_INFO _IOR('W', 0x01, struct sndrv_rawmidi_info)
|
||||
#define SNDRV_RAWMIDI_IOCTL_PARAMS _IOWR('W', 0x10, struct sndrv_rawmidi_params)
|
||||
#define SNDRV_RAWMIDI_IOCTL_STATUS _IOWR('W', 0x20, struct sndrv_rawmidi_status)
|
||||
#define SNDRV_RAWMIDI_IOCTL_DROP _IOW('W', 0x30, int)
|
||||
#define SNDRV_RAWMIDI_IOCTL_DRAIN _IOW('W', 0x31, int)
|
||||
#define SNDRV_TIMER_IOCTL_PVERSION _IOR('T', 0x00, int)
|
||||
#define SNDRV_TIMER_IOCTL_NEXT_DEVICE _IOWR('T', 0x01, struct sndrv_timer_id)
|
||||
#define SNDRV_TIMER_IOCTL_TREAD _IOW('T', 0x02, int)
|
||||
#define SNDRV_TIMER_IOCTL_GINFO _IOWR('T', 0x03, struct sndrv_timer_ginfo)
|
||||
#define SNDRV_TIMER_IOCTL_GPARAMS _IOW('T', 0x04, struct sndrv_timer_gparams)
|
||||
#define SNDRV_TIMER_IOCTL_GSTATUS _IOWR('T', 0x05, struct sndrv_timer_gstatus)
|
||||
#define SNDRV_TIMER_IOCTL_SELECT _IOW('T', 0x10, struct sndrv_timer_select)
|
||||
#define SNDRV_TIMER_IOCTL_INFO _IOR('T', 0x11, struct sndrv_timer_info)
|
||||
#define SNDRV_TIMER_IOCTL_PARAMS _IOW('T', 0x12, struct sndrv_timer_params)
|
||||
#define SNDRV_TIMER_IOCTL_STATUS _IOR('T', 0x14, struct sndrv_timer_status)
|
||||
#define SNDRV_TIMER_IOCTL_START _IO('T', 0xa0)
|
||||
#define SNDRV_TIMER_IOCTL_STOP _IO('T', 0xa1)
|
||||
#define SNDRV_TIMER_IOCTL_CONTINUE _IO('T', 0xa2)
|
||||
#define SNDRV_TIMER_IOCTL_PAUSE _IO('T', 0xa3)
|
||||
#define SNDRV_CTL_IOCTL_PVERSION _IOR('U', 0x00, int)
|
||||
#define SNDRV_CTL_IOCTL_CARD_INFO _IOR('U', 0x01, struct sndrv_ctl_card_info)
|
||||
#define SNDRV_CTL_IOCTL_ELEM_LIST _IOWR('U', 0x10, struct sndrv_ctl_elem_list)
|
||||
#define SNDRV_CTL_IOCTL_ELEM_INFO _IOWR('U', 0x11, struct sndrv_ctl_elem_info)
|
||||
#define SNDRV_CTL_IOCTL_ELEM_READ _IOWR('U', 0x12, struct sndrv_ctl_elem_value)
|
||||
#define SNDRV_CTL_IOCTL_ELEM_WRITE _IOWR('U', 0x13, struct sndrv_ctl_elem_value)
|
||||
#define SNDRV_CTL_IOCTL_ELEM_LOCK _IOW('U', 0x14, struct sndrv_ctl_elem_id)
|
||||
#define SNDRV_CTL_IOCTL_ELEM_UNLOCK _IOW('U', 0x15, struct sndrv_ctl_elem_id)
|
||||
#define SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS _IOWR('U', 0x16, int)
|
||||
#define SNDRV_CTL_IOCTL_ELEM_ADD _IOWR('U', 0x17, struct sndrv_ctl_elem_info)
|
||||
#define SNDRV_CTL_IOCTL_ELEM_REPLACE _IOWR('U', 0x18, struct sndrv_ctl_elem_info)
|
||||
#define SNDRV_CTL_IOCTL_ELEM_REMOVE _IOWR('U', 0x19, struct sndrv_ctl_elem_id)
|
||||
#define SNDRV_CTL_IOCTL_TLV_READ _IOWR('U', 0x1a, struct sndrv_ctl_tlv)
|
||||
#define SNDRV_CTL_IOCTL_TLV_WRITE _IOWR('U', 0x1b, struct sndrv_ctl_tlv)
|
||||
#define SNDRV_CTL_IOCTL_TLV_COMMAND _IOWR('U', 0x1c, struct sndrv_ctl_tlv)
|
||||
#define SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE _IOWR('U', 0x20, int)
|
||||
#define SNDRV_CTL_IOCTL_HWDEP_INFO _IOR('U', 0x21, struct sndrv_hwdep_info)
|
||||
#define SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE _IOR('U', 0x30, int)
|
||||
#define SNDRV_CTL_IOCTL_PCM_INFO _IOWR('U', 0x31, struct sndrv_pcm_info)
|
||||
#define SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE _IOW('U', 0x32, int)
|
||||
#define SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE _IOWR('U', 0x40, int)
|
||||
#define SNDRV_CTL_IOCTL_RAWMIDI_INFO _IOWR('U', 0x41, struct sndrv_rawmidi_info)
|
||||
#define SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE _IOW('U', 0x42, int)
|
||||
#define SNDRV_CTL_IOCTL_POWER _IOWR('U', 0xd0, int)
|
||||
#define SNDRV_CTL_IOCTL_POWER_STATE _IOR('U', 0xd1, int)
|
||||
#define SNDRV_IOCTL_READV _IOW('K', 0x00, struct sndrv_xferv)
|
||||
#define SNDRV_IOCTL_WRITEV _IOW('K', 0x01, struct sndrv_xferv)
|
||||
#define SNDRV_EMU10K1_IOCTL_INFO _IOR ('H', 0x10, emu10k1_fx8010_info_t)
|
||||
#define SNDRV_EMU10K1_IOCTL_CODE_POKE _IOW ('H', 0x11, emu10k1_fx8010_code_t)
|
||||
#define SNDRV_EMU10K1_IOCTL_CODE_PEEK _IOWR('H', 0x12, emu10k1_fx8010_code_t)
|
||||
#define SNDRV_EMU10K1_IOCTL_TRAM_SETUP _IOW ('H', 0x20, int)
|
||||
#define SNDRV_EMU10K1_IOCTL_TRAM_POKE _IOW ('H', 0x21, emu10k1_fx8010_tram_t)
|
||||
#define SNDRV_EMU10K1_IOCTL_TRAM_PEEK _IOWR('H', 0x22, emu10k1_fx8010_tram_t)
|
||||
#define SNDRV_EMU10K1_IOCTL_PCM_POKE _IOW ('H', 0x30, emu10k1_fx8010_pcm_t)
|
||||
#define SNDRV_EMU10K1_IOCTL_PCM_PEEK _IOWR('H', 0x31, emu10k1_fx8010_pcm_t)
|
||||
#define SNDRV_EMU10K1_IOCTL_PVERSION _IOR ('H', 0x40, int)
|
||||
#define SNDRV_EMU10K1_IOCTL_STOP _IO ('H', 0x80)
|
||||
#define SNDRV_EMU10K1_IOCTL_CONTINUE _IO ('H', 0x81)
|
||||
#define SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER _IO ('H', 0x82)
|
||||
#define SNDRV_EMU10K1_IOCTL_SINGLE_STEP _IOW ('H', 0x83, int)
|
||||
#define SNDRV_EMU10K1_IOCTL_DBG_READ _IOR ('H', 0x84, int)
|
||||
#define SNDRV_HDSP_IOCTL_GET_PEAK_RMS _IOR('H', 0x40, hdsp_peak_rms_t)
|
||||
#define SNDRV_HDSP_IOCTL_GET_CONFIG_INFO _IOR('H', 0x41, hdsp_config_info_t)
|
||||
#define SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE _IOW('H', 0x42, hdsp_firmware_t)
|
||||
#define SNDRV_HDSP_IOCTL_GET_VERSION _IOR('H', 0x43, hdsp_version_t)
|
||||
#define SNDRV_HDSP_IOCTL_GET_MIXER _IOR('H', 0x44, hdsp_mixer_t)
|
||||
#define SNDRV_HDSP_IOCTL_GET_9632_AEB _IOR('H', 0x45, hdsp_9632_aeb_t)
|
||||
#define SNDRV_SB_CSP_IOCTL_INFO _IOR('H', 0x10, snd_sb_csp_info_t)
|
||||
#define SNDRV_SB_CSP_IOCTL_LOAD_CODE _IOW('H', 0x11, snd_sb_csp_microcode_t)
|
||||
#define SNDRV_SB_CSP_IOCTL_UNLOAD_CODE _IO('H', 0x12)
|
||||
#define SNDRV_SB_CSP_IOCTL_START _IOW('H', 0x13, snd_sb_csp_start_t)
|
||||
#define SNDRV_SB_CSP_IOCTL_STOP _IO('H', 0x14)
|
||||
#define SNDRV_SB_CSP_IOCTL_PAUSE _IO('H', 0x15)
|
||||
#define SNDRV_SB_CSP_IOCTL_RESTART _IO('H', 0x16)
|
||||
#define SND_SSCAPE_LOAD_BOOTB _IOWR('P', 100, struct sscape_bootblock)
|
||||
#define SND_SSCAPE_LOAD_MCODE _IOW ('P', 101, struct sscape_microcode)
|
||||
|
||||
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_PVERSION TARGET_IOR ('S', 0x00, int)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_CLIENT_ID TARGET_IOR ('S', 0x01, int)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_SYSTEM_INFO TARGET_IOWRU('S', 0x02)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_RUNNING_MODE TARGET_IOWRU('S', 0x03)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_GET_CLIENT_INFO TARGET_IOWRU('S', 0x10)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_SET_CLIENT_INFO TARGET_IOWU ('S', 0x11)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_CREATE_PORT TARGET_IOWRU('S', 0x20)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_DELETE_PORT TARGET_IOWU ('S', 0x21)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_GET_PORT_INFO TARGET_IOWRU('S', 0x22)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_SET_PORT_INFO TARGET_IOWU ('S', 0x23)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT TARGET_IOWU ('S', 0x30)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT TARGET_IOWU ('S', 0x31)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_CREATE_QUEUE TARGET_IOWRU('S', 0x32)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_DELETE_QUEUE TARGET_IOWU ('S', 0x33)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_GET_QUEUE_INFO TARGET_IOWRU('S', 0x34)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_SET_QUEUE_INFO TARGET_IOWRU('S', 0x35)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE TARGET_IOWRU('S', 0x36)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS TARGET_IOWRU('S', 0x40)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO TARGET_IOWRU('S', 0x41)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO TARGET_IOWU ('S', 0x42)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_GET_QUEUE_OWNER TARGET_IOWRU('S', 0x43)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_SET_QUEUE_OWNER TARGET_IOWU ('S', 0x44)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER TARGET_IOWRU('S', 0x45)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER TARGET_IOWU ('S', 0x46)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_GET_QUEUE_SYNC TARGET_IOWRU('S', 0x53)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_SET_QUEUE_SYNC TARGET_IOWU ('S', 0x54)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT TARGET_IOWRU('S', 0x49)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT TARGET_IOWU ('S', 0x4a)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_GET_CLIENT_POOL TARGET_IOWRU('S', 0x4b)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_SET_CLIENT_POOL TARGET_IOWU ('S', 0x4c)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_REMOVE_EVENTS TARGET_IOWU ('S', 0x4e)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_QUERY_SUBS TARGET_IOWRU('S', 0x4f)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION TARGET_IOWRU('S', 0x50)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT TARGET_IOWRU('S', 0x51)
|
||||
#define TARGET_SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT TARGET_IOWRU('S', 0x52)
|
||||
#define TARGET_SNDRV_DM_FM_IOCTL_INFO TARGET_IORU('H', 0x20)
|
||||
#define TARGET_SNDRV_DM_FM_IOCTL_RESET TARGET_IO ('H', 0x21)
|
||||
#define TARGET_SNDRV_DM_FM_IOCTL_PLAY_NOTE TARGET_IOWU('H', 0x22)
|
||||
#define TARGET_SNDRV_DM_FM_IOCTL_SET_VOICE TARGET_IOWU('H', 0x23)
|
||||
#define TARGET_SNDRV_DM_FM_IOCTL_SET_PARAMS TARGET_IOWU('H', 0x24)
|
||||
#define TARGET_SNDRV_DM_FM_IOCTL_SET_MODE TARGET_IOW('H', 0x25, int)
|
||||
#define TARGET_SNDRV_DM_FM_IOCTL_SET_CONNECTION TARGET_IOW('H', 0x26, int)
|
||||
#define TARGET_SNDRV_DM_FM_OSS_IOCTL_RESET 0x20
|
||||
#define TARGET_SNDRV_DM_FM_OSS_IOCTL_PLAY_NOTE 0x21
|
||||
#define TARGET_SNDRV_DM_FM_OSS_IOCTL_SET_VOICE 0x22
|
||||
#define TARGET_SNDRV_DM_FM_OSS_IOCTL_SET_PARAMS 0x23
|
||||
#define TARGET_SNDRV_DM_FM_OSS_IOCTL_SET_MODE 0x24
|
||||
#define TARGET_SNDRV_DM_FM_OSS_IOCTL_SET_OPL 0x25
|
||||
#define TARGET_SNDRV_HWDEP_IOCTL_PVERSION TARGET_IOR ('H', 0x00, int)
|
||||
#define TARGET_SNDRV_HWDEP_IOCTL_INFO TARGET_IORU ('H', 0x01)
|
||||
#define TARGET_SNDRV_HWDEP_IOCTL_DSP_STATUS TARGET_IORU('H', 0x02)
|
||||
#define TARGET_SNDRV_HWDEP_IOCTL_DSP_LOAD TARGET_IOWU('H', 0x03)
|
||||
#define TARGET_SNDRV_PCM_IOCTL_PVERSION TARGET_IOR('A', 0x00, int)
|
||||
#define TARGET_SNDRV_PCM_IOCTL_INFO TARGET_IORU('A', 0x01)
|
||||
#define TARGET_SNDRV_PCM_IOCTL_TSTAMP TARGET_IOW('A', 0x02, int)
|
||||
#define TARGET_SNDRV_PCM_IOCTL_HW_REFINE TARGET_IOWRU('A', 0x10)
|
||||
#define TARGET_SNDRV_PCM_IOCTL_HW_PARAMS TARGET_IOWRU('A', 0x11)
|
||||
#define TARGET_SNDRV_PCM_IOCTL_HW_FREE TARGET_IO('A', 0x12)
|
||||
#define TARGET_SNDRV_PCM_IOCTL_SW_PARAMS TARGET_IOWRU('A', 0x13)
|
||||
#define TARGET_SNDRV_PCM_IOCTL_STATUS TARGET_IORU('A', 0x20)
|
||||
#define TARGET_SNDRV_PCM_IOCTL_DELAY TARGET_IORU('A', 0x21)
|
||||
#define TARGET_SNDRV_PCM_IOCTL_HWSYNC TARGET_IO('A', 0x22)
|
||||
#define TARGET_SNDRV_PCM_IOCTL_SYNC_PTR TARGET_IOWRU('A', 0x23)
|
||||
#define TARGET_SNDRV_PCM_IOCTL_CHANNEL_INFO TARGET_IORU('A', 0x32)
|
||||
#define TARGET_SNDRV_PCM_IOCTL_PREPARE TARGET_IO('A', 0x40)
|
||||
#define TARGET_SNDRV_PCM_IOCTL_RESET TARGET_IO('A', 0x41)
|
||||
#define TARGET_SNDRV_PCM_IOCTL_START TARGET_IO('A', 0x42)
|
||||
#define TARGET_SNDRV_PCM_IOCTL_DROP TARGET_IO('A', 0x43)
|
||||
#define TARGET_SNDRV_PCM_IOCTL_DRAIN TARGET_IO('A', 0x44)
|
||||
#define TARGET_SNDRV_PCM_IOCTL_PAUSE TARGET_IOW('A', 0x45, int)
|
||||
#define TARGET_SNDRV_PCM_IOCTL_REWIND TARGET_IOWU('A', 0x46)
|
||||
#define TARGET_SNDRV_PCM_IOCTL_RESUME TARGET_IO('A', 0x47)
|
||||
#define TARGET_SNDRV_PCM_IOCTL_XRUN TARGET_IO('A', 0x48)
|
||||
#define TARGET_SNDRV_PCM_IOCTL_FORWARD TARGET_IOWU('A', 0x49)
|
||||
#define TARGET_SNDRV_PCM_IOCTL_WRITEI_FRAMES TARGET_IOWU('A', 0x50)
|
||||
#define TARGET_SNDRV_PCM_IOCTL_READI_FRAMES TARGET_IORU('A', 0x51)
|
||||
#define TARGET_SNDRV_PCM_IOCTL_WRITEN_FRAMES TARGET_IOWU('A', 0x52)
|
||||
#define TARGET_SNDRV_PCM_IOCTL_READN_FRAMES TARGET_IORU('A', 0x53)
|
||||
#define TARGET_SNDRV_PCM_IOCTL_LINK TARGET_IOW('A', 0x60, int)
|
||||
#define TARGET_SNDRV_PCM_IOCTL_UNLINK TARGET_IO('A', 0x61)
|
||||
#define TARGET_SNDRV_RAWMIDI_IOCTL_PVERSION TARGET_IOR('W', 0x00, int)
|
||||
#define TARGET_SNDRV_RAWMIDI_IOCTL_INFO TARGET_IORU('W', 0x01)
|
||||
#define TARGET_SNDRV_RAWMIDI_IOCTL_PARAMS TARGET_IOWRU('W', 0x10)
|
||||
#define TARGET_SNDRV_RAWMIDI_IOCTL_STATUS TARGET_IOWRU('W', 0x20)
|
||||
#define TARGET_SNDRV_RAWMIDI_IOCTL_DROP TARGET_IOW('W', 0x30, int)
|
||||
#define TARGET_SNDRV_RAWMIDI_IOCTL_DRAIN TARGET_IOW('W', 0x31, int)
|
||||
#define TARGET_SNDRV_TIMER_IOCTL_PVERSION TARGET_IOR('T', 0x00, int)
|
||||
#define TARGET_SNDRV_TIMER_IOCTL_NEXT_DEVICE TARGET_IOWRU('T', 0x01)
|
||||
#define TARGET_SNDRV_TIMER_IOCTL_TREAD TARGET_IOW('T', 0x02, int)
|
||||
#define TARGET_SNDRV_TIMER_IOCTL_GINFO TARGET_IOWRU('T', 0x03)
|
||||
#define TARGET_SNDRV_TIMER_IOCTL_GPARAMS TARGET_IOWU('T', 0x04)
|
||||
#define TARGET_SNDRV_TIMER_IOCTL_GSTATUS TARGET_IOWRU('T', 0x05)
|
||||
#define TARGET_SNDRV_TIMER_IOCTL_SELECT TARGET_IOWU('T', 0x10)
|
||||
#define TARGET_SNDRV_TIMER_IOCTL_INFO TARGET_IORU('T', 0x11)
|
||||
#define TARGET_SNDRV_TIMER_IOCTL_PARAMS TARGET_IOWU('T', 0x12)
|
||||
#define TARGET_SNDRV_TIMER_IOCTL_STATUS TARGET_IORU('T', 0x14)
|
||||
#define TARGET_SNDRV_TIMER_IOCTL_START TARGET_IO('T', 0xa0)
|
||||
#define TARGET_SNDRV_TIMER_IOCTL_STOP TARGET_IO('T', 0xa1)
|
||||
#define TARGET_SNDRV_TIMER_IOCTL_CONTINUE TARGET_IO('T', 0xa2)
|
||||
#define TARGET_SNDRV_TIMER_IOCTL_PAUSE TARGET_IO('T', 0xa3)
|
||||
#define TARGET_SNDRV_CTL_IOCTL_PVERSION TARGET_IOR('U', 0x00, int)
|
||||
#define TARGET_SNDRV_CTL_IOCTL_CARD_INFO TARGET_IORU('U', 0x01)
|
||||
#define TARGET_SNDRV_CTL_IOCTL_ELEM_LIST TARGET_IOWRU('U', 0x10)
|
||||
#define TARGET_SNDRV_CTL_IOCTL_ELEM_INFO TARGET_IOWRU('U', 0x11)
|
||||
#define TARGET_SNDRV_CTL_IOCTL_ELEM_READ TARGET_IOWRU('U', 0x12)
|
||||
#define TARGET_SNDRV_CTL_IOCTL_ELEM_WRITE TARGET_IOWRU('U', 0x13)
|
||||
#define TARGET_SNDRV_CTL_IOCTL_ELEM_LOCK TARGET_IOWU('U', 0x14)
|
||||
#define TARGET_SNDRV_CTL_IOCTL_ELEM_UNLOCK TARGET_IOWU('U', 0x15)
|
||||
#define TARGET_SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS TARGET_IOWR('U', 0x16, int)
|
||||
#define TARGET_SNDRV_CTL_IOCTL_ELEM_ADD TARGET_IOWRU('U', 0x17)
|
||||
#define TARGET_SNDRV_CTL_IOCTL_ELEM_REPLACE TARGET_IOWRU('U', 0x18)
|
||||
#define TARGET_SNDRV_CTL_IOCTL_ELEM_REMOVE TARGET_IOWRU('U', 0x19)
|
||||
#define TARGET_SNDRV_CTL_IOCTL_TLV_READ TARGET_IOWRU('U', 0x1a)
|
||||
#define TARGET_SNDRV_CTL_IOCTL_TLV_WRITE TARGET_IOWRU('U', 0x1b)
|
||||
#define TARGET_SNDRV_CTL_IOCTL_TLV_COMMAND TARGET_IOWRU('U', 0x1c)
|
||||
#define TARGET_SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE TARGET_IOWR('U', 0x20, int)
|
||||
#define TARGET_SNDRV_CTL_IOCTL_HWDEP_INFO TARGET_IORU('U', 0x21)
|
||||
#define TARGET_SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE TARGET_IOR('U', 0x30, int)
|
||||
#define TARGET_SNDRV_CTL_IOCTL_PCM_INFO TARGET_IOWRU('U', 0x31)
|
||||
#define TARGET_SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE TARGET_IOW('U', 0x32, int)
|
||||
#define TARGET_SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE TARGET_IOWR('U', 0x40, int)
|
||||
#define TARGET_SNDRV_CTL_IOCTL_RAWMIDI_INFO TARGET_IOWRU('U', 0x41)
|
||||
#define TARGET_SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE TARGET_IOW('U', 0x42, int)
|
||||
#define TARGET_SNDRV_CTL_IOCTL_POWER TARGET_IOWR('U', 0xd0, int)
|
||||
#define TARGET_SNDRV_CTL_IOCTL_POWER_STATE TARGET_IOR('U', 0xd1, int)
|
||||
#define TARGET_SNDRV_IOCTL_READV TARGET_IOWU('K', 0x00)
|
||||
#define TARGET_SNDRV_IOCTL_WRITEV TARGET_IOWU('K', 0x01)
|
||||
#define TARGET_SNDRV_EMU10K1_IOCTL_INFO TARGET_IORU ('H', 0x10)
|
||||
#define TARGET_SNDRV_EMU10K1_IOCTL_CODE_POKE TARGET_IOWU ('H', 0x11)
|
||||
#define TARGET_SNDRV_EMU10K1_IOCTL_CODE_PEEK TARGET_IOWRU('H', 0x12)
|
||||
#define TARGET_SNDRV_EMU10K1_IOCTL_TRAM_SETUP TARGET_IOW ('H', 0x20, int)
|
||||
#define TARGET_SNDRV_EMU10K1_IOCTL_TRAM_POKE TARGET_IOWU ('H', 0x21)
|
||||
#define TARGET_SNDRV_EMU10K1_IOCTL_TRAM_PEEK TARGET_IOWRU('H', 0x22)
|
||||
#define TARGET_SNDRV_EMU10K1_IOCTL_PCM_POKE TARGET_IOWU ('H', 0x30)
|
||||
#define TARGET_SNDRV_EMU10K1_IOCTL_PCM_PEEK TARGET_IOWRU('H', 0x31)
|
||||
#define TARGET_SNDRV_EMU10K1_IOCTL_PVERSION TARGET_IOR ('H', 0x40, int)
|
||||
#define TARGET_SNDRV_EMU10K1_IOCTL_STOP TARGET_IO ('H', 0x80)
|
||||
#define TARGET_SNDRV_EMU10K1_IOCTL_CONTINUE TARGET_IO ('H', 0x81)
|
||||
#define TARGET_SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER TARGET_IO ('H', 0x82)
|
||||
#define TARGET_SNDRV_EMU10K1_IOCTL_SINGLE_STEP TARGET_IOW ('H', 0x83, int)
|
||||
#define TARGET_SNDRV_EMU10K1_IOCTL_DBG_READ TARGET_IOR ('H', 0x84, int)
|
||||
#define TARGET_SNDRV_HDSP_IOCTL_GET_PEAK_RMS TARGET_IORU('H', 0x40)
|
||||
#define TARGET_SNDRV_HDSP_IOCTL_GET_CONFIG_INFO TARGET_IORU('H', 0x41)
|
||||
#define TARGET_SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE TARGET_IOWU('H', 0x42)
|
||||
#define TARGET_SNDRV_HDSP_IOCTL_GET_VERSION TARGET_IORU('H', 0x43)
|
||||
#define TARGET_SNDRV_HDSP_IOCTL_GET_MIXER TARGET_IORU('H', 0x44)
|
||||
#define TARGET_SNDRV_HDSP_IOCTL_GET_9632_AEB TARGET_IORU('H', 0x45)
|
||||
#define TARGET_SNDRV_SB_CSP_IOCTL_INFO TARGET_IORU('H', 0x10)
|
||||
#define TARGET_SNDRV_SB_CSP_IOCTL_LOAD_CODE TARGET_IOWU('H', 0x11)
|
||||
#define TARGET_SNDRV_SB_CSP_IOCTL_UNLOAD_CODE TARGET_IO('H', 0x12)
|
||||
#define TARGET_SNDRV_SB_CSP_IOCTL_START TARGET_IOWU('H', 0x13)
|
||||
#define TARGET_SNDRV_SB_CSP_IOCTL_STOP TARGET_IO('H', 0x14)
|
||||
#define TARGET_SNDRV_SB_CSP_IOCTL_PAUSE TARGET_IO('H', 0x15)
|
||||
#define TARGET_SNDRV_SB_CSP_IOCTL_RESTART TARGET_IO('H', 0x16)
|
||||
#define TARGET_SND_SSCAPE_LOAD_BOOTB TARGET_IOWRU('P', 100)
|
||||
#define TARGET_SND_SSCAPE_LOAD_MCODE TARGET_IOWU ('P', 101)
|
||||
|
||||
IOCTL( SNDRV_SEQ_IOCTL_PVERSION , IOC_R, MK_PTR(TYPE_INT) )
|
||||
IOCTL( SNDRV_SEQ_IOCTL_CLIENT_ID , IOC_R, MK_PTR(TYPE_INT) )
|
||||
IOCTL( SNDRV_SEQ_IOCTL_SYSTEM_INFO , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_system_info)) )
|
||||
IOCTL( SNDRV_SEQ_IOCTL_RUNNING_MODE , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_running_info)) )
|
||||
IOCTL( SNDRV_SEQ_IOCTL_GET_CLIENT_INFO , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_client_info)) )
|
||||
IOCTL( SNDRV_SEQ_IOCTL_SET_CLIENT_INFO , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_client_info)) )
|
||||
IOCTL( SNDRV_SEQ_IOCTL_CREATE_PORT , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_port_info)) )
|
||||
IOCTL( SNDRV_SEQ_IOCTL_DELETE_PORT , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_port_info)) )
|
||||
IOCTL( SNDRV_SEQ_IOCTL_GET_PORT_INFO , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_port_info)) )
|
||||
IOCTL( SNDRV_SEQ_IOCTL_SET_PORT_INFO , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_port_info)) )
|
||||
IOCTL( SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_port_subscribe)) )
|
||||
IOCTL( SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_port_subscribe)) )
|
||||
IOCTL( SNDRV_SEQ_IOCTL_CREATE_QUEUE , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_info)) )
|
||||
IOCTL( SNDRV_SEQ_IOCTL_DELETE_QUEUE , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_info)) )
|
||||
IOCTL( SNDRV_SEQ_IOCTL_GET_QUEUE_INFO , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_info)) )
|
||||
IOCTL( SNDRV_SEQ_IOCTL_SET_QUEUE_INFO , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_info)) )
|
||||
IOCTL( SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_info)) )
|
||||
IOCTL( SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_status)) )
|
||||
IOCTL( SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_tempo)) )
|
||||
IOCTL( SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_tempo)) )
|
||||
//IOCTL( SNDRV_SEQ_IOCTL_GET_QUEUE_OWNER , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_owner)) )
|
||||
//IOCTL( SNDRV_SEQ_IOCTL_SET_QUEUE_OWNER , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_owner)) )
|
||||
IOCTL( SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_timer)) )
|
||||
IOCTL( SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_timer)) )
|
||||
//IOCTL( SNDRV_SEQ_IOCTL_GET_QUEUE_SYNC , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_sync)) )
|
||||
//IOCTL( SNDRV_SEQ_IOCTL_SET_QUEUE_SYNC , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_sync)) )
|
||||
IOCTL( SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_client)) )
|
||||
IOCTL( SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_client)) )
|
||||
IOCTL( SNDRV_SEQ_IOCTL_GET_CLIENT_POOL , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_client_pool)) )
|
||||
IOCTL( SNDRV_SEQ_IOCTL_SET_CLIENT_POOL , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_client_pool)) )
|
||||
IOCTL( SNDRV_SEQ_IOCTL_REMOVE_EVENTS , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_remove_events)) )
|
||||
IOCTL( SNDRV_SEQ_IOCTL_QUERY_SUBS , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_query_subs)) )
|
||||
IOCTL( SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_port_subscribe)) )
|
||||
IOCTL( SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_client_info)) )
|
||||
IOCTL( SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_port_info)) )
|
||||
IOCTL( SNDRV_DM_FM_IOCTL_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_snd_dm_fm_info)) )
|
||||
IOCTL( SNDRV_DM_FM_IOCTL_RESET , 0, TYPE_NULL )
|
||||
IOCTL( SNDRV_DM_FM_IOCTL_PLAY_NOTE , IOC_W, MK_PTR(MK_STRUCT(STRUCT_snd_dm_fm_note)) )
|
||||
IOCTL( SNDRV_DM_FM_IOCTL_SET_VOICE , IOC_W, MK_PTR(MK_STRUCT(STRUCT_snd_dm_fm_voice)) )
|
||||
IOCTL( SNDRV_DM_FM_IOCTL_SET_PARAMS , IOC_W, MK_PTR(MK_STRUCT(STRUCT_snd_dm_fm_params)) )
|
||||
IOCTL( SNDRV_DM_FM_IOCTL_SET_MODE , IOC_W, MK_PTR(TYPE_INT) )
|
||||
IOCTL( SNDRV_DM_FM_IOCTL_SET_CONNECTION , IOC_W, MK_PTR(TYPE_INT) )
|
||||
IOCTL( SNDRV_HWDEP_IOCTL_PVERSION , IOC_R, MK_PTR(TYPE_INT) )
|
||||
IOCTL( SNDRV_HWDEP_IOCTL_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_hwdep_info)) )
|
||||
IOCTL( SNDRV_HWDEP_IOCTL_DSP_STATUS , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_hwdep_dsp_status)) )
|
||||
IOCTL( SNDRV_HWDEP_IOCTL_DSP_LOAD , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_hwdep_dsp_image)) )
|
||||
IOCTL( SNDRV_PCM_IOCTL_PVERSION , IOC_R, MK_PTR(TYPE_INT) )
|
||||
IOCTL( SNDRV_PCM_IOCTL_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_info)) )
|
||||
IOCTL( SNDRV_PCM_IOCTL_TSTAMP , IOC_W, MK_PTR(TYPE_INT) )
|
||||
IOCTL( SNDRV_PCM_IOCTL_HW_REFINE , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_hw_params)) )
|
||||
IOCTL( SNDRV_PCM_IOCTL_HW_PARAMS , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_hw_params)) )
|
||||
IOCTL( SNDRV_PCM_IOCTL_HW_FREE , 0, TYPE_NULL )
|
||||
IOCTL( SNDRV_PCM_IOCTL_SW_PARAMS , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_sw_params)) )
|
||||
IOCTL( SNDRV_PCM_IOCTL_STATUS , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_status)) )
|
||||
IOCTL( SNDRV_PCM_IOCTL_DELAY , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_sframes)) )
|
||||
IOCTL( SNDRV_PCM_IOCTL_HWSYNC , 0, TYPE_NULL )
|
||||
IOCTL( SNDRV_PCM_IOCTL_SYNC_PTR , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_sync_ptr)) )
|
||||
IOCTL( SNDRV_PCM_IOCTL_CHANNEL_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_channel_info)) )
|
||||
IOCTL( SNDRV_PCM_IOCTL_PREPARE , 0, TYPE_NULL )
|
||||
IOCTL( SNDRV_PCM_IOCTL_RESET , 0, TYPE_NULL )
|
||||
IOCTL( SNDRV_PCM_IOCTL_START , 0, TYPE_NULL )
|
||||
IOCTL( SNDRV_PCM_IOCTL_DROP , 0, TYPE_NULL )
|
||||
IOCTL( SNDRV_PCM_IOCTL_DRAIN , 0, TYPE_NULL )
|
||||
IOCTL( SNDRV_PCM_IOCTL_PAUSE , IOC_W, MK_PTR(TYPE_INT) )
|
||||
IOCTL( SNDRV_PCM_IOCTL_REWIND , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_uframes)) )
|
||||
IOCTL( SNDRV_PCM_IOCTL_RESUME , 0, TYPE_NULL )
|
||||
IOCTL( SNDRV_PCM_IOCTL_XRUN , 0, TYPE_NULL )
|
||||
IOCTL( SNDRV_PCM_IOCTL_FORWARD , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_uframes)) )
|
||||
IOCTL( SNDRV_PCM_IOCTL_WRITEI_FRAMES , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_xferi)) )
|
||||
IOCTL( SNDRV_PCM_IOCTL_READI_FRAMES , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_xferi)) )
|
||||
IOCTL( SNDRV_PCM_IOCTL_WRITEN_FRAMES , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_xfern)) )
|
||||
IOCTL( SNDRV_PCM_IOCTL_READN_FRAMES , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_xfern)) )
|
||||
IOCTL( SNDRV_PCM_IOCTL_LINK , IOC_W, MK_PTR(TYPE_INT) )
|
||||
IOCTL( SNDRV_PCM_IOCTL_UNLINK , 0, TYPE_NULL )
|
||||
IOCTL( SNDRV_RAWMIDI_IOCTL_PVERSION , IOC_R, MK_PTR(TYPE_INT) )
|
||||
IOCTL( SNDRV_RAWMIDI_IOCTL_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_rawmidi_info)) )
|
||||
IOCTL( SNDRV_RAWMIDI_IOCTL_PARAMS , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_rawmidi_params)) )
|
||||
IOCTL( SNDRV_RAWMIDI_IOCTL_STATUS , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_rawmidi_status)) )
|
||||
IOCTL( SNDRV_RAWMIDI_IOCTL_DROP , IOC_W, MK_PTR(TYPE_INT) )
|
||||
IOCTL( SNDRV_RAWMIDI_IOCTL_DRAIN , IOC_W, MK_PTR(TYPE_INT) )
|
||||
IOCTL( SNDRV_TIMER_IOCTL_PVERSION , IOC_R, MK_PTR(TYPE_INT) )
|
||||
IOCTL( SNDRV_TIMER_IOCTL_NEXT_DEVICE , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_timer_id)) )
|
||||
IOCTL( SNDRV_TIMER_IOCTL_TREAD , IOC_W, MK_PTR(TYPE_INT) )
|
||||
IOCTL( SNDRV_TIMER_IOCTL_GINFO , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_timer_ginfo)) )
|
||||
IOCTL( SNDRV_TIMER_IOCTL_GPARAMS , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_timer_gparams)) )
|
||||
IOCTL( SNDRV_TIMER_IOCTL_GSTATUS , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_timer_gstatus)) )
|
||||
IOCTL( SNDRV_TIMER_IOCTL_SELECT , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_timer_select)) )
|
||||
IOCTL( SNDRV_TIMER_IOCTL_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_timer_info)) )
|
||||
IOCTL( SNDRV_TIMER_IOCTL_PARAMS , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_timer_params)) )
|
||||
IOCTL( SNDRV_TIMER_IOCTL_STATUS , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_timer_status)) )
|
||||
IOCTL( SNDRV_TIMER_IOCTL_START , 0, TYPE_NULL )
|
||||
IOCTL( SNDRV_TIMER_IOCTL_STOP , 0, TYPE_NULL )
|
||||
IOCTL( SNDRV_TIMER_IOCTL_CONTINUE , 0, TYPE_NULL )
|
||||
IOCTL( SNDRV_TIMER_IOCTL_PAUSE , 0, TYPE_NULL )
|
||||
IOCTL( SNDRV_CTL_IOCTL_PVERSION , IOC_R, MK_PTR(TYPE_INT) )
|
||||
IOCTL( SNDRV_CTL_IOCTL_CARD_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_card_info)) )
|
||||
IOCTL( SNDRV_CTL_IOCTL_ELEM_LIST , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_elem_list)) )
|
||||
IOCTL( SNDRV_CTL_IOCTL_ELEM_INFO , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_elem_info)) )
|
||||
IOCTL( SNDRV_CTL_IOCTL_ELEM_READ , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_elem_value)) )
|
||||
IOCTL( SNDRV_CTL_IOCTL_ELEM_WRITE , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_elem_value)) )
|
||||
IOCTL( SNDRV_CTL_IOCTL_ELEM_LOCK , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_elem_id)) )
|
||||
IOCTL( SNDRV_CTL_IOCTL_ELEM_UNLOCK , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_elem_id)) )
|
||||
IOCTL( SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS , IOC_RW, MK_PTR(TYPE_INT) )
|
||||
IOCTL( SNDRV_CTL_IOCTL_ELEM_ADD , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_elem_info)) )
|
||||
IOCTL( SNDRV_CTL_IOCTL_ELEM_REPLACE , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_elem_info)) )
|
||||
IOCTL( SNDRV_CTL_IOCTL_ELEM_REMOVE , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_elem_id)) )
|
||||
IOCTL( SNDRV_CTL_IOCTL_TLV_READ , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_tlv)) )
|
||||
IOCTL( SNDRV_CTL_IOCTL_TLV_WRITE , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_tlv)) )
|
||||
IOCTL( SNDRV_CTL_IOCTL_TLV_COMMAND , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_tlv)) )
|
||||
IOCTL( SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE , IOC_RW, MK_PTR(TYPE_INT) )
|
||||
IOCTL( SNDRV_CTL_IOCTL_HWDEP_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_hwdep_info)) )
|
||||
IOCTL( SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE , IOC_R, MK_PTR(TYPE_INT) )
|
||||
IOCTL( SNDRV_CTL_IOCTL_PCM_INFO , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_info)) )
|
||||
IOCTL( SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE , IOC_W, MK_PTR(TYPE_INT) )
|
||||
IOCTL( SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE , IOC_RW, MK_PTR(TYPE_INT) )
|
||||
IOCTL( SNDRV_CTL_IOCTL_RAWMIDI_INFO , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_rawmidi_info)) )
|
||||
IOCTL( SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE , IOC_W, MK_PTR(TYPE_INT) )
|
||||
IOCTL( SNDRV_CTL_IOCTL_POWER , IOC_RW, MK_PTR(TYPE_INT) )
|
||||
IOCTL( SNDRV_CTL_IOCTL_POWER_STATE , IOC_R, MK_PTR(TYPE_INT) )
|
||||
IOCTL( SNDRV_IOCTL_READV , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_xferv)) )
|
||||
IOCTL( SNDRV_IOCTL_WRITEV , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_xferv)) )
|
||||
IOCTL( SNDRV_EMU10K1_IOCTL_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_emu10k1_fx8010_info)) )
|
||||
IOCTL( SNDRV_EMU10K1_IOCTL_CODE_POKE , IOC_W, MK_PTR(MK_STRUCT(STRUCT_emu10k1_fx8010_code)) )
|
||||
IOCTL( SNDRV_EMU10K1_IOCTL_CODE_PEEK , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_emu10k1_fx8010_code)) )
|
||||
IOCTL( SNDRV_EMU10K1_IOCTL_TRAM_SETUP , IOC_W, MK_PTR(TYPE_INT) )
|
||||
IOCTL( SNDRV_EMU10K1_IOCTL_TRAM_POKE , IOC_W, MK_PTR(MK_STRUCT(STRUCT_emu10k1_fx8010_tram)) )
|
||||
IOCTL( SNDRV_EMU10K1_IOCTL_TRAM_PEEK , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_emu10k1_fx8010_tram)) )
|
||||
IOCTL( SNDRV_EMU10K1_IOCTL_PCM_POKE , IOC_W, MK_PTR(MK_STRUCT(STRUCT_emu10k1_fx8010_pcm)) )
|
||||
IOCTL( SNDRV_EMU10K1_IOCTL_PCM_PEEK , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_emu10k1_fx8010_pcm)) )
|
||||
IOCTL( SNDRV_EMU10K1_IOCTL_PVERSION , IOC_R, MK_PTR(TYPE_INT) )
|
||||
IOCTL( SNDRV_EMU10K1_IOCTL_STOP , 0, TYPE_NULL )
|
||||
IOCTL( SNDRV_EMU10K1_IOCTL_CONTINUE , 0, TYPE_NULL )
|
||||
IOCTL( SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER , 0, TYPE_NULL )
|
||||
IOCTL( SNDRV_EMU10K1_IOCTL_SINGLE_STEP , IOC_W, MK_PTR(TYPE_INT) )
|
||||
IOCTL( SNDRV_EMU10K1_IOCTL_DBG_READ , IOC_R, MK_PTR(TYPE_INT) )
|
||||
IOCTL( SNDRV_HDSP_IOCTL_GET_PEAK_RMS , IOC_R, MK_PTR(MK_STRUCT(STRUCT_hdsp_peak_rms)) )
|
||||
IOCTL( SNDRV_HDSP_IOCTL_GET_CONFIG_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_hdsp_config_info)) )
|
||||
IOCTL( SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE , IOC_W, MK_PTR(MK_STRUCT(STRUCT_hdsp_firmware)) )
|
||||
IOCTL( SNDRV_HDSP_IOCTL_GET_VERSION , IOC_R, MK_PTR(MK_STRUCT(STRUCT_hdsp_version)) )
|
||||
IOCTL( SNDRV_HDSP_IOCTL_GET_MIXER , IOC_R, MK_PTR(MK_STRUCT(STRUCT_hdsp_mixer)) )
|
||||
IOCTL( SNDRV_HDSP_IOCTL_GET_9632_AEB , IOC_R, MK_PTR(MK_STRUCT(STRUCT_hdsp_9632_aeb)) )
|
||||
IOCTL( SNDRV_SB_CSP_IOCTL_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_snd_sb_csp_info)) )
|
||||
#if _IOC_SIZEBITS > 13
|
||||
IOCTL( SNDRV_SB_CSP_IOCTL_LOAD_CODE , IOC_W, MK_PTR(MK_STRUCT(STRUCT_snd_sb_csp_microcode)) )
|
||||
#endif
|
||||
IOCTL( SNDRV_SB_CSP_IOCTL_UNLOAD_CODE , 0, TYPE_NULL )
|
||||
IOCTL( SNDRV_SB_CSP_IOCTL_START , IOC_W, MK_PTR(MK_STRUCT(STRUCT_snd_sb_csp_start)) )
|
||||
IOCTL( SNDRV_SB_CSP_IOCTL_STOP , 0, TYPE_NULL )
|
||||
IOCTL( SNDRV_SB_CSP_IOCTL_PAUSE , 0, TYPE_NULL )
|
||||
IOCTL( SNDRV_SB_CSP_IOCTL_RESTART , 0, TYPE_NULL )
|
||||
IOCTL( SND_SSCAPE_LOAD_BOOTB , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sscape_bootblock)) )
|
||||
IOCTL( SND_SSCAPE_LOAD_MCODE , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sscape_microcode)) )
|
1740
linux-user/ioctls_alsa_structs.h
Normal file
1740
linux-user/ioctls_alsa_structs.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -91,5 +91,6 @@ struct loop_info64 {
|
||||
#define LOOP_SET_STATUS64 0x4C04
|
||||
#define LOOP_GET_STATUS64 0x4C05
|
||||
#define LOOP_CHANGE_FD 0x4C06
|
||||
#define LOOP_BOGUS_CMD 0x4C82
|
||||
|
||||
#endif
|
||||
|
@@ -814,15 +814,22 @@ void cpu_loop(CPUARMState *env)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
env->regs[0] = do_syscall(env,
|
||||
n,
|
||||
env->regs[0],
|
||||
env->regs[1],
|
||||
env->regs[2],
|
||||
env->regs[3],
|
||||
env->regs[4],
|
||||
env->regs[5],
|
||||
0, 0);
|
||||
TaskState *ts = cs->opaque;
|
||||
target_ulong r;
|
||||
r = do_syscall(env, n, env->regs[0], env->regs[1],
|
||||
env->regs[2], env->regs[3], env->regs[4],
|
||||
env->regs[5], 0, 0);
|
||||
if ((r == -EINTR) && ts->signal_restart &&
|
||||
syscall_restartable(n)) {
|
||||
if (env->thumb) {
|
||||
env->regs[15] -= 2;
|
||||
} else {
|
||||
env->regs[15] -= 4;
|
||||
}
|
||||
} else {
|
||||
env->regs[0] = r;
|
||||
}
|
||||
ts->signal_restart = 0;
|
||||
}
|
||||
} else {
|
||||
goto error;
|
||||
|
@@ -30,6 +30,7 @@
|
||||
|
||||
#include "qemu.h"
|
||||
#include "qemu-common.h"
|
||||
#include "tcg.h"
|
||||
|
||||
//#define DEBUG_MMAP
|
||||
|
||||
@@ -40,6 +41,7 @@ void mmap_lock(void)
|
||||
{
|
||||
if (mmap_lock_count++ == 0) {
|
||||
pthread_mutex_lock(&mmap_mutex);
|
||||
tcg_lock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +49,7 @@ void mmap_unlock(void)
|
||||
{
|
||||
if (--mmap_lock_count == 0) {
|
||||
pthread_mutex_unlock(&mmap_mutex);
|
||||
tcg_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -366,6 +369,9 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size)
|
||||
}
|
||||
}
|
||||
|
||||
#define SNDRV_PCM_MMAP_OFFSET_STATUS 0x80000000
|
||||
#define SNDRV_PCM_MMAP_OFFSET_CONTROL 0x81000000
|
||||
|
||||
/* NOTE: all the constants are the HOST ones */
|
||||
abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
||||
int flags, int fd, abi_ulong offset)
|
||||
@@ -400,6 +406,17 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Alsa tries to communcate with the kernel via mmap. This usually
|
||||
* is a good idea when user- and kernelspace are running on the
|
||||
* same architecture but does not work out when not. To make alsa
|
||||
* not to use mmap, we can just have it fail on the mmap calls that
|
||||
* would initiate this.
|
||||
*/
|
||||
if(offset == SNDRV_PCM_MMAP_OFFSET_STATUS || offset == SNDRV_PCM_MMAP_OFFSET_CONTROL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (offset & ~TARGET_PAGE_MASK) {
|
||||
errno = EINVAL;
|
||||
goto fail;
|
||||
|
@@ -134,6 +134,8 @@ typedef struct TaskState {
|
||||
struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
|
||||
struct sigqueue *first_free; /* first free siginfo queue entry */
|
||||
int signal_pending; /* non zero if a signal may be pending */
|
||||
int signal_in_syscall; /* non zero if we are in do_syscall() */
|
||||
int signal_restart; /* non zero if we need to restart a syscall */
|
||||
} __attribute__((aligned(16))) TaskState;
|
||||
|
||||
extern char *exec_path;
|
||||
@@ -187,10 +189,10 @@ abi_long memcpy_to_target(abi_ulong dest, const void *src,
|
||||
void target_set_brk(abi_ulong new_brk);
|
||||
abi_long do_brk(abi_ulong new_brk);
|
||||
void syscall_init(void);
|
||||
abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
abi_long arg2, abi_long arg3, abi_long arg4,
|
||||
abi_long arg5, abi_long arg6, abi_long arg7,
|
||||
abi_long arg8);
|
||||
abi_long do_syscall(void *cpu_env, int num, abi_ulong arg1,
|
||||
abi_ulong arg2, abi_ulong arg3, abi_ulong arg4,
|
||||
abi_ulong arg5, abi_ulong arg6, abi_ulong arg7,
|
||||
abi_ulong arg8);
|
||||
void gemu_log(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
|
||||
extern THREAD CPUState *thread_cpu;
|
||||
void cpu_loop(CPUArchState *env);
|
||||
@@ -199,6 +201,7 @@ int get_osversion(void);
|
||||
void init_qemu_uname_release(void);
|
||||
void fork_start(void);
|
||||
void fork_end(int child);
|
||||
int syscall_restartable(int syscall_nr);
|
||||
|
||||
/* Creates the initial guest address space in the host memory space using
|
||||
* the given host start address hint and size. The guest_start parameter
|
||||
|
@@ -25,6 +25,7 @@
|
||||
#include <assert.h>
|
||||
#include <sys/ucontext.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sched.h>
|
||||
|
||||
#include "qemu.h"
|
||||
#include "qemu-common.h"
|
||||
@@ -448,6 +449,10 @@ static void QEMU_NORETURN force_sig(int target_sig)
|
||||
host_sig = target_to_host_signal(target_sig);
|
||||
gdb_signalled(env, target_sig);
|
||||
|
||||
if (target_sig == 6) {
|
||||
goto no_core;
|
||||
}
|
||||
|
||||
/* dump core if supported by target binary format */
|
||||
if (core_dump_signal(target_sig) && (ts->bprm->core_dump != NULL)) {
|
||||
stop_all_tasks();
|
||||
@@ -465,6 +470,8 @@ static void QEMU_NORETURN force_sig(int target_sig)
|
||||
target_sig, strsignal(host_sig), "core dumped" );
|
||||
}
|
||||
|
||||
no_core:
|
||||
|
||||
/* The proper exit code for dying from an uncaught signal is
|
||||
* -<signal>. The kernel doesn't allow exit() or _exit() to pass
|
||||
* a negative value. To get the proper exit code we need to
|
||||
@@ -565,6 +572,11 @@ int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
|
||||
k->pending = 1;
|
||||
/* signal that a new signal is pending */
|
||||
ts->signal_pending = 1;
|
||||
/* check if we have to restart the current syscall */
|
||||
if ((sigact_table[sig - 1].sa_flags & SA_RESTART) &&
|
||||
ts->signal_in_syscall) {
|
||||
ts->signal_restart = 1;
|
||||
}
|
||||
return 1; /* indicates that the signal was queued */
|
||||
}
|
||||
}
|
||||
@@ -700,8 +712,24 @@ int do_sigaction(int sig, const struct target_sigaction *act,
|
||||
if (host_sig != SIGSEGV && host_sig != SIGBUS) {
|
||||
sigfillset(&act1.sa_mask);
|
||||
act1.sa_flags = SA_SIGINFO;
|
||||
#ifdef TARGET_ARM
|
||||
/* Breaks boehm-gc, we have to do this manually */
|
||||
/*
|
||||
* Unfortunately our hacks only work as long as we don't do parallel
|
||||
* signal delivery and futexes, so let's do a dirty hack here to
|
||||
* pin our guest process to a single host CPU if we're using the
|
||||
* boehm-gc.
|
||||
*/
|
||||
if ((k->sa_flags & TARGET_SA_RESTART) && host_sig == SIGPWR) {
|
||||
cpu_set_t mask;
|
||||
CPU_ZERO(&mask);
|
||||
CPU_SET(0, &mask);
|
||||
sched_setaffinity(0, sizeof(mask), &mask);
|
||||
}
|
||||
#else
|
||||
if (k->sa_flags & TARGET_SA_RESTART)
|
||||
act1.sa_flags |= SA_RESTART;
|
||||
#endif
|
||||
/* NOTE: it is important to update the host kernel signal
|
||||
ignore state to avoid getting unexpected interrupted
|
||||
syscalls */
|
||||
|
@@ -3188,6 +3188,11 @@ static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp,
|
||||
uint32_t outbufsz;
|
||||
int free_fm = 0;
|
||||
|
||||
if (1) {
|
||||
/* XXX agraf: fiemap breaks for me */
|
||||
return -TARGET_EINVAL;
|
||||
}
|
||||
|
||||
assert(arg_type[0] == TYPE_PTR);
|
||||
assert(ie->access == IOC_RW);
|
||||
arg_type++;
|
||||
@@ -3631,6 +3636,13 @@ static abi_long do_ioctl_rt(const IOCTLEntry *ie, uint8_t *buf_temp,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static abi_long do_ioctl_fail(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
|
||||
abi_long cmd, abi_long arg)
|
||||
{
|
||||
/* Fail silently */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static IOCTLEntry ioctl_entries[] = {
|
||||
#define IOCTL(cmd, access, ...) \
|
||||
{ TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
|
||||
@@ -3654,7 +3666,12 @@ static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
|
||||
ie = ioctl_entries;
|
||||
for(;;) {
|
||||
if (ie->target_cmd == 0) {
|
||||
gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
|
||||
int i;
|
||||
gemu_log("Unsupported ioctl: cmd=0x%04lx (%x)\n", (unsigned long)cmd, (unsigned int)(cmd & (TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) >> TARGET_IOC_SIZESHIFT);
|
||||
for (i = 0; ioctl_entries[i].target_cmd; i++) {
|
||||
if ((ioctl_entries[i].target_cmd & ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) == (cmd & ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)))
|
||||
gemu_log("%p\t->\t%s (%x)\n", (void *)(unsigned long)ioctl_entries[i].host_cmd, ioctl_entries[i].name, (ioctl_entries[i].target_cmd & (TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) >> TARGET_IOC_SIZESHIFT);
|
||||
}
|
||||
return -TARGET_ENOSYS;
|
||||
}
|
||||
if (ie->target_cmd == cmd)
|
||||
@@ -3683,6 +3700,11 @@ static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
|
||||
arg_type++;
|
||||
target_size = thunk_type_size(arg_type, 0);
|
||||
switch(ie->access) {
|
||||
/* FIXME: actually the direction given in the ioctl should be
|
||||
* correct so we can assume the communication is uni-directional.
|
||||
* The alsa developers did not like this concept though and
|
||||
* declared ioctls IOC_R and IOC_W even though they were IOC_RW.*/
|
||||
/*
|
||||
case IOC_R:
|
||||
ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
|
||||
if (!is_error(ret)) {
|
||||
@@ -3701,6 +3723,7 @@ static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
|
||||
unlock_user(argptr, arg, 0);
|
||||
ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
|
||||
break;
|
||||
*/
|
||||
default:
|
||||
case IOC_RW:
|
||||
argptr = lock_user(VERIFY_READ, arg, target_size, 1);
|
||||
@@ -4316,6 +4339,15 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
|
||||
if (nptl_flags & CLONE_SETTLS)
|
||||
cpu_set_tls (new_env, newtls);
|
||||
|
||||
/* agraf: Pin ourselves to a single CPU when running multi-threaded.
|
||||
This turned out to improve stability for me. */
|
||||
{
|
||||
cpu_set_t mask;
|
||||
CPU_ZERO(&mask);
|
||||
CPU_SET(0, &mask);
|
||||
sched_setaffinity(0, sizeof(mask), &mask);
|
||||
}
|
||||
|
||||
/* Grab a mutex so that thread setup appears atomic. */
|
||||
pthread_mutex_lock(&clone_lock);
|
||||
|
||||
@@ -5109,6 +5141,25 @@ static int open_self_stat(void *cpu_env, int fd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int open_cpuinfo(void *cpu_env, int fd)
|
||||
{
|
||||
dprintf(fd,
|
||||
"Processor : ARMv7 Processor rev 5 (v7l)\n"
|
||||
"BogoMIPS : 799.53\n"
|
||||
"Features : swp half thumb fastmult vfp edsp thumbee neon vfpv3\n"
|
||||
"CPU implementer : 0x41\n"
|
||||
"CPU architecture: 7\n"
|
||||
"CPU variant : 0x2\n"
|
||||
"CPU part : 0xc08\n"
|
||||
"CPU revision : 5\n"
|
||||
"\n"
|
||||
"Hardware : Genesi Efika MX (Smarttop)\n"
|
||||
"Revision : 51030\n"
|
||||
"Serial : 0000000000000000\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int open_self_auxv(void *cpu_env, int fd)
|
||||
{
|
||||
CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env);
|
||||
@@ -5222,6 +5273,7 @@ static int do_open(void *cpu_env, const char *pathname, int flags, mode_t mode)
|
||||
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
|
||||
{ "/proc/net/route", open_net_route, is_proc },
|
||||
#endif
|
||||
{ "cpuinfo", open_cpuinfo, is_proc_myself },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
@@ -5259,19 +5311,106 @@ static int do_open(void *cpu_env, const char *pathname, int flags, mode_t mode)
|
||||
return get_errno(open(path(pathname), flags, mode));
|
||||
}
|
||||
|
||||
int syscall_restartable(int syscall_nr)
|
||||
{
|
||||
switch (syscall_nr) {
|
||||
#ifdef TARGET_NR_sigsuspend
|
||||
case TARGET_NR_sigsuspend:
|
||||
#endif
|
||||
#ifdef TARGET_NR_pause
|
||||
case TARGET_NR_pause:
|
||||
#endif
|
||||
#ifdef TARGET_NR_setsockopt
|
||||
case TARGET_NR_setsockopt:
|
||||
#endif
|
||||
#ifdef TARGET_NR_accept
|
||||
case TARGET_NR_accept:
|
||||
#endif
|
||||
#ifdef TARGET_NR_recv
|
||||
case TARGET_NR_recv:
|
||||
#endif
|
||||
#ifdef TARGET_NR_recvfrom
|
||||
case TARGET_NR_recvfrom:
|
||||
#endif
|
||||
#ifdef TARGET_NR_recvmsg
|
||||
case TARGET_NR_recvmsg:
|
||||
#endif
|
||||
#ifdef TARGET_NR_socketcall
|
||||
case TARGET_NR_socketcall:
|
||||
#endif
|
||||
#ifdef TARGET_NR_connect
|
||||
case TARGET_NR_connect:
|
||||
#endif
|
||||
#ifdef TARGET_NR_send
|
||||
case TARGET_NR_send:
|
||||
#endif
|
||||
#ifdef TARGET_NR_sendmsg
|
||||
case TARGET_NR_sendmsg:
|
||||
#endif
|
||||
#ifdef TARGET_NR_sendto
|
||||
case TARGET_NR_sendto:
|
||||
#endif
|
||||
#ifdef TARGET_NR_poll
|
||||
case TARGET_NR_poll:
|
||||
#endif
|
||||
#ifdef TARGET_NR_ppoll
|
||||
case TARGET_NR_ppoll:
|
||||
#endif
|
||||
#if defined(TARGET_NR_select)
|
||||
case TARGET_NR_select:
|
||||
#endif
|
||||
#ifdef TARGET_NR_pselect6
|
||||
case TARGET_NR_pselect6:
|
||||
#endif
|
||||
#ifdef TARGET_NR__newselect
|
||||
case TARGET_NR__newselect:
|
||||
#endif
|
||||
#ifdef TARGET_NR_msgrcv
|
||||
case TARGET_NR_msgrcv:
|
||||
#endif
|
||||
#ifdef TARGET_NR_msgsnd
|
||||
case TARGET_NR_msgsnd:
|
||||
#endif
|
||||
#ifdef TARGET_NR_semop
|
||||
case TARGET_NR_semop:
|
||||
#endif
|
||||
#ifdef TARGET_NR_ipc
|
||||
case TARGET_NR_ipc:
|
||||
#endif
|
||||
#ifdef TARGET_NR_clock_nanosleep
|
||||
case TARGET_NR_clock_nanosleep:
|
||||
#endif
|
||||
case TARGET_NR_rt_sigsuspend:
|
||||
case TARGET_NR_rt_sigtimedwait:
|
||||
case TARGET_NR_nanosleep:
|
||||
case TARGET_NR_close:
|
||||
/* can not be restarted */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* every other syscall can be restarted */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* do_syscall() should always have a single exit point at the end so
|
||||
that actions, such as logging of syscall results, can be performed.
|
||||
All errnos that do_syscall() returns must be -TARGET_<errcode>. */
|
||||
abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
abi_long arg2, abi_long arg3, abi_long arg4,
|
||||
abi_long arg5, abi_long arg6, abi_long arg7,
|
||||
abi_long arg8)
|
||||
abi_long do_syscall(void *cpu_env, int num, abi_ulong arg1,
|
||||
abi_ulong arg2, abi_ulong arg3, abi_ulong arg4,
|
||||
abi_ulong arg5, abi_ulong arg6, abi_ulong arg7,
|
||||
abi_ulong arg8)
|
||||
{
|
||||
CPUState *cpu = ENV_GET_CPU(cpu_env);
|
||||
abi_long ret;
|
||||
struct stat st;
|
||||
struct statfs stfs;
|
||||
void *p;
|
||||
TaskState *ts = cpu->opaque;
|
||||
|
||||
if (!ts->signal_restart) {
|
||||
/* remember syscall info for restart */
|
||||
ts->signal_in_syscall = 1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
gemu_log("syscall %d", num);
|
||||
@@ -5570,9 +5709,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
case TARGET_NR_oldstat:
|
||||
goto unimplemented;
|
||||
#endif
|
||||
case TARGET_NR_lseek:
|
||||
ret = get_errno(lseek(arg1, arg2, arg3));
|
||||
case TARGET_NR_lseek: {
|
||||
off_t off = arg2;
|
||||
if (arg3 != SEEK_SET) {
|
||||
off = (abi_long)arg2;
|
||||
}
|
||||
ret = get_errno(lseek(arg1, off, arg3));
|
||||
break;
|
||||
}
|
||||
#if defined(TARGET_NR_getxpid) && defined(TARGET_ALPHA)
|
||||
/* Alpha specific */
|
||||
case TARGET_NR_getxpid:
|
||||
@@ -6316,6 +6460,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
case TARGET_NR_gettimeofday:
|
||||
{
|
||||
struct timeval tv;
|
||||
if(copy_from_user_timeval(&tv, arg1))
|
||||
goto efault;
|
||||
ret = get_errno(gettimeofday(&tv, NULL));
|
||||
if (!is_error(ret)) {
|
||||
if (copy_to_user_timeval(arg1, &tv))
|
||||
@@ -8457,7 +8603,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
cmd = target_to_host_fcntl_cmd(arg2);
|
||||
if (cmd == -TARGET_EINVAL) {
|
||||
ret = cmd;
|
||||
break;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
switch(arg2) {
|
||||
@@ -9395,6 +9541,7 @@ fail:
|
||||
#endif
|
||||
if(do_strace)
|
||||
print_syscall_ret(num, ret);
|
||||
ts->signal_in_syscall = 0;
|
||||
return ret;
|
||||
efault:
|
||||
ret = -TARGET_EFAULT;
|
||||
|
@@ -913,6 +913,12 @@ struct target_pollfd {
|
||||
#define TARGET_BLKGETSIZE64 TARGET_IOR(0x12,114,abi_ulong)
|
||||
/* return device size in bytes
|
||||
(u64 *arg) */
|
||||
#define TARGET_BLKDISCARD TARGET_IO(0x12,119)
|
||||
#define TARGET_BLKIOMIN TARGET_IO(0x12,120)
|
||||
#define TARGET_BLKIOOPT TARGET_IO(0x12,121)
|
||||
#define TARGET_BLKALIGNOFF TARGET_IO(0x12,122)
|
||||
#define TARGET_BLKPBSZGET TARGET_IO(0x12,123)
|
||||
#define TARGET_BLKDISCARDZEROES TARGET_IO(0x12,124)
|
||||
#define TARGET_FIBMAP TARGET_IO(0x00,1) /* bmap access */
|
||||
#define TARGET_FIGETBSZ TARGET_IO(0x00,2) /* get the block size used for bmap */
|
||||
#define TARGET_FS_IOC_FIEMAP TARGET_IOWR('f',11,struct fiemap)
|
||||
@@ -1044,6 +1050,7 @@ struct target_pollfd {
|
||||
#define TARGET_LOOP_SET_STATUS64 0x4C04
|
||||
#define TARGET_LOOP_GET_STATUS64 0x4C05
|
||||
#define TARGET_LOOP_CHANGE_FD 0x4C06
|
||||
#define TARGET_LOOP_BOGUS_CMD 0x4C82
|
||||
|
||||
/* fb ioctls */
|
||||
#define TARGET_FBIOGET_VSCREENINFO 0x4600
|
||||
@@ -2459,6 +2466,9 @@ struct target_f_owner_ex {
|
||||
#define TARGET_MTIOCGET TARGET_IOR('m', 2, struct mtget)
|
||||
#define TARGET_MTIOCPOS TARGET_IOR('m', 3, struct mtpos)
|
||||
|
||||
#define TARGET_FS_IOC_GETFLAGS TARGET_IORU('f', 1)
|
||||
#define TARGET_FS_IOC_SETFLAGS TARGET_IOWU('f', 2)
|
||||
|
||||
struct target_sysinfo {
|
||||
abi_long uptime; /* Seconds since boot */
|
||||
abi_ulong loads[3]; /* 1, 5, and 15 minute load averages */
|
||||
@@ -2545,6 +2555,8 @@ struct target_ucred {
|
||||
uint32_t gid;
|
||||
};
|
||||
|
||||
#include "ioctls_alsa_structs.h"
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@@ -71,6 +71,9 @@ STRUCT(kbentry,
|
||||
STRUCT(kbsentry,
|
||||
TYPE_CHAR, MK_ARRAY(TYPE_CHAR, 512))
|
||||
|
||||
STRUCT(blkdiscard,
|
||||
MK_ARRAY(TYPE_LONGLONG, 2))
|
||||
|
||||
STRUCT(audio_buf_info,
|
||||
TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT)
|
||||
|
||||
@@ -83,6 +86,11 @@ STRUCT(buffmem_desc,
|
||||
STRUCT(mixer_info,
|
||||
MK_ARRAY(TYPE_CHAR, 16), MK_ARRAY(TYPE_CHAR, 32), TYPE_INT, MK_ARRAY(TYPE_INT, 10))
|
||||
|
||||
/* FIXME: including these on x86 / x86_64 breaks qemu-i386 */
|
||||
#ifdef __powerpc__
|
||||
#include "syscall_types_alsa.h"
|
||||
#endif
|
||||
|
||||
/* loop device ioctls */
|
||||
STRUCT(loop_info,
|
||||
TYPE_INT, /* lo_number */
|
||||
|
1336
linux-user/syscall_types_alsa.h
Normal file
1336
linux-user/syscall_types_alsa.h
Normal file
File diff suppressed because it is too large
Load Diff
22
net/net.c
22
net/net.c
@@ -141,6 +141,27 @@ void qemu_format_nic_info_str(NetClientState *nc, uint8_t macaddr[6])
|
||||
macaddr[3], macaddr[4], macaddr[5]);
|
||||
}
|
||||
|
||||
static void default_mac_check(void)
|
||||
{
|
||||
static const MACAddr def_mac = { .a = { 0x52,0x54,0x00,0x12,0x34,0x56 } };
|
||||
static int warned = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_NICS; i++)
|
||||
{
|
||||
if (!nd_table[i].used)
|
||||
continue;
|
||||
if (memcmp(nd_table[i].macaddr.a, def_mac.a, 5))
|
||||
continue;
|
||||
if (nd_table[i].macaddr.a[5] >= 0x56 &&
|
||||
nd_table[i].macaddr.a[5] < 0x56 + MAX_NICS && !warned) {
|
||||
warned = 1;
|
||||
fprintf(stderr, "Warning: default mac address being used, creating "
|
||||
"potential for address conflict\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void qemu_macaddr_default_if_unset(MACAddr *macaddr)
|
||||
{
|
||||
static int index = 0;
|
||||
@@ -1251,6 +1272,7 @@ int net_init_clients(void)
|
||||
if (qemu_opts_foreach(net, net_init_client, NULL, 1) == -1) {
|
||||
return -1;
|
||||
}
|
||||
default_mac_check();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
16
qemu-char.c
16
qemu-char.c
@@ -252,6 +252,9 @@ typedef struct {
|
||||
IOEventHandler *chr_event[MAX_MUX];
|
||||
void *ext_opaque[MAX_MUX];
|
||||
CharDriverState *drv;
|
||||
#if defined(TARGET_S390X)
|
||||
QEMUTimer *accept_timer;
|
||||
#endif
|
||||
int focus;
|
||||
int mux_cnt;
|
||||
int term_got_escape;
|
||||
@@ -408,6 +411,15 @@ static void mux_chr_accept_input(CharDriverState *chr)
|
||||
d->chr_read[m](d->ext_opaque[m],
|
||||
&d->buffer[m][d->cons[m]++ & MUX_BUFFER_MASK], 1);
|
||||
}
|
||||
|
||||
#if defined(TARGET_S390X)
|
||||
/* We're still not able to sync producer and consumer, so let's wait a bit
|
||||
and try again by then. */
|
||||
if (d->prod[m] != d->cons[m]) {
|
||||
qemu_mod_timer(d->accept_timer, qemu_get_clock_ns(vm_clock)
|
||||
+ (int64_t)100000);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static int mux_chr_can_read(void *opaque)
|
||||
@@ -530,6 +542,10 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
|
||||
chr->opaque = d;
|
||||
d->drv = drv;
|
||||
d->focus = -1;
|
||||
#if defined(TARGET_S390X)
|
||||
d->accept_timer = qemu_new_timer_ns(vm_clock,
|
||||
(QEMUTimerCB*)mux_chr_accept_input, chr);
|
||||
#endif
|
||||
chr->chr_write = mux_chr_write;
|
||||
chr->chr_update_read_handler = mux_chr_update_read_handler;
|
||||
chr->chr_accept_input = mux_chr_accept_input;
|
||||
|
@@ -1154,7 +1154,7 @@ static int img_convert(int argc, char **argv)
|
||||
const uint8_t *buf1;
|
||||
BlockDriverInfo bdi;
|
||||
QEMUOptionParameter *param = NULL, *create_options = NULL;
|
||||
QEMUOptionParameter *out_baseimg_param;
|
||||
QEMUOptionParameter *out_baseimg_param, *scsi;
|
||||
char *options = NULL;
|
||||
const char *snapshot_name = NULL;
|
||||
int min_sparse = 8; /* Need at least 4k of zeros for sparse detection */
|
||||
@@ -1398,6 +1398,12 @@ static int img_convert(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if ((scsi = get_option_parameter(param, BLOCK_OPT_SCSI)) && scsi->value.n && strcmp(drv->format_name, "vmdk")) {
|
||||
error_report("SCSI devices not supported for this file format");
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!skip_create) {
|
||||
/* Create the new image */
|
||||
ret = bdrv_create(drv, out_filename, param, &local_err);
|
||||
|
@@ -2603,6 +2603,16 @@ Store the QEMU process PID in @var{file}. It is useful if you launch QEMU
|
||||
from a script.
|
||||
ETEXI
|
||||
|
||||
DEF("nooutgoing", HAS_ARG, QEMU_OPTION_nooutgoing, \
|
||||
"-nooutgoing <IP>\n" \
|
||||
" incoming traffic only from IP, no outgoing\n", \
|
||||
QEMU_ARCH_ALL)
|
||||
STEXI
|
||||
@item -nooutgoing
|
||||
Forbid userspace networking to make outgoing connections. Only accept incoming
|
||||
connections from ip address IP.
|
||||
ETEXI
|
||||
|
||||
DEF("singlestep", 0, QEMU_OPTION_singlestep, \
|
||||
"-singlestep always run in singlestep mode\n", QEMU_ARCH_ALL)
|
||||
STEXI
|
||||
|
@@ -27,46 +27,49 @@ case "$cpu" in
|
||||
armv[4-9]*)
|
||||
cpu="arm"
|
||||
;;
|
||||
sparc*)
|
||||
cpu="sparc"
|
||||
;;
|
||||
esac
|
||||
|
||||
# register the interpreter for each cpu except for the native one
|
||||
if [ $cpu != "i386" ] ; then
|
||||
echo ':i386:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-i386:' > /proc/sys/fs/binfmt_misc/register
|
||||
echo ':i486:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x06\x00:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-i386:' > /proc/sys/fs/binfmt_misc/register
|
||||
echo ':i386:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-i386-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||||
echo ':i486:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x06\x00:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-i386-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||||
fi
|
||||
if [ $cpu != "alpha" ] ; then
|
||||
echo ':alpha:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x26\x90:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-alpha:' > /proc/sys/fs/binfmt_misc/register
|
||||
echo ':alpha:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x26\x90:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-alpha-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||||
fi
|
||||
if [ $cpu != "arm" ] ; then
|
||||
echo ':arm:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-arm:' > /proc/sys/fs/binfmt_misc/register
|
||||
echo ':armeb:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-armeb:' > /proc/sys/fs/binfmt_misc/register
|
||||
echo ':arm:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-arm-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||||
echo ':armeb:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-armeb-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||||
fi
|
||||
if [ $cpu != "aarch64" ] ; then
|
||||
echo ':aarch64:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-aarch64:' > /proc/sys/fs/binfmt_misc/register
|
||||
echo ':aarch64:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-aarch64-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||||
fi
|
||||
if [ $cpu != "sparc" ] ; then
|
||||
echo ':sparc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x02:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-sparc:' > /proc/sys/fs/binfmt_misc/register
|
||||
echo ':sparc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x02:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-sparc-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||||
fi
|
||||
if [ $cpu != "ppc" ] ; then
|
||||
echo ':ppc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x14:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-ppc:' > /proc/sys/fs/binfmt_misc/register
|
||||
echo ':ppc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x14:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-ppc-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||||
fi
|
||||
if [ $cpu != "m68k" ] ; then
|
||||
echo 'Please check cpu value and header information for m68k!'
|
||||
echo ':m68k:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x04:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-m68k:' > /proc/sys/fs/binfmt_misc/register
|
||||
echo ':m68k:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x04:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-m68k-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||||
fi
|
||||
if [ $cpu != "mips" ] ; then
|
||||
# FIXME: We could use the other endianness on a MIPS host.
|
||||
echo ':mips:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-mips:' > /proc/sys/fs/binfmt_misc/register
|
||||
echo ':mipsel:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-mipsel:' > /proc/sys/fs/binfmt_misc/register
|
||||
echo ':mipsn32:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-mipsn32:' > /proc/sys/fs/binfmt_misc/register
|
||||
echo ':mipsn32el:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-mipsn32el:' > /proc/sys/fs/binfmt_misc/register
|
||||
echo ':mips64:M::\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-mips64:' > /proc/sys/fs/binfmt_misc/register
|
||||
echo ':mips64el:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-mips64el:' > /proc/sys/fs/binfmt_misc/register
|
||||
echo ':mips:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-mips-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||||
echo ':mipsel:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-mipsel-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||||
echo ':mipsn32:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-mipsn32-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||||
echo ':mipsn32el:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-mipsn32el-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||||
echo ':mips64:M::\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-mips64-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||||
echo ':mips64el:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-mips64el-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||||
fi
|
||||
if [ $cpu != "sh" ] ; then
|
||||
echo ':sh4:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a\x00:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-sh4:' > /proc/sys/fs/binfmt_misc/register
|
||||
echo ':sh4eb:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-sh4eb:' > /proc/sys/fs/binfmt_misc/register
|
||||
echo ':sh4:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a\x00:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-sh4-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||||
echo ':sh4eb:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-sh4eb-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||||
fi
|
||||
if [ $cpu != "s390x" ] ; then
|
||||
echo ':s390x:M::\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x16:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-s390x:' > /proc/sys/fs/binfmt_misc/register
|
||||
echo ':s390x:M::\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x16:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-s390x-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||||
fi
|
||||
|
@@ -532,6 +532,8 @@ sorecvfrom(struct socket *so)
|
||||
} /* if ping packet */
|
||||
}
|
||||
|
||||
extern int slirp_nooutgoing;
|
||||
|
||||
/*
|
||||
* sendto() a socket
|
||||
*/
|
||||
@@ -562,6 +564,12 @@ sosendto(struct socket *so, struct mbuf *m)
|
||||
|
||||
DEBUG_MISC((dfd, " sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%.16s\n", ntohs(addr.sin_port), inet_ntoa(addr.sin_addr)));
|
||||
|
||||
/* Only allow DNS requests */
|
||||
if (slirp_nooutgoing && ntohs(addr.sin_port) != 53) {
|
||||
errno = EHOSTUNREACH;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Don't care what port we get */
|
||||
ret = sendto(so->s, m->m_data, m->m_len, 0,
|
||||
(struct sockaddr *)&addr, sizeof (struct sockaddr));
|
||||
|
@@ -324,6 +324,9 @@ tcp_sockclosed(struct tcpcb *tp)
|
||||
* nonblocking. Connect returns after the SYN is sent, and does
|
||||
* not wait for ACK+SYN.
|
||||
*/
|
||||
|
||||
extern int slirp_nooutgoing;
|
||||
|
||||
int tcp_fconnect(struct socket *so)
|
||||
{
|
||||
Slirp *slirp = so->slirp;
|
||||
@@ -332,6 +335,11 @@ int tcp_fconnect(struct socket *so)
|
||||
DEBUG_CALL("tcp_fconnect");
|
||||
DEBUG_ARG("so = %lx", (long )so);
|
||||
|
||||
if (slirp_nooutgoing) {
|
||||
errno = EHOSTUNREACH;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( (ret = so->s = qemu_socket(AF_INET,SOCK_STREAM,0)) >= 0) {
|
||||
int opt, s=so->s;
|
||||
struct sockaddr_in addr;
|
||||
@@ -424,6 +432,11 @@ void tcp_connect(struct socket *inso)
|
||||
tcp_close(sototcpcb(so)); /* This will sofree() as well */
|
||||
return;
|
||||
}
|
||||
if (slirp_nooutgoing && addr.sin_addr.s_addr != slirp_nooutgoing) {
|
||||
tcp_close(sototcpcb(so)); /* This will sofree() as well */
|
||||
close(s);
|
||||
return;
|
||||
}
|
||||
qemu_set_nonblock(s);
|
||||
socket_set_fast_reuse(s);
|
||||
opt = 1;
|
||||
|
@@ -154,7 +154,11 @@ static void arm_cpu_reset(CPUState *s)
|
||||
* bake assumptions about into translated code, so we need to
|
||||
* tb_flush().
|
||||
*/
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
/* XXX hack alert! automoc4 segaults after spawning a new thread with this
|
||||
flush enabled */
|
||||
tb_flush(env);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
@@ -246,7 +246,7 @@ const VMStateDescription vmstate_arm_cpu = {
|
||||
/* The length-check must come before the arrays to avoid
|
||||
* incoming data possibly overflowing the array.
|
||||
*/
|
||||
VMSTATE_INT32_LE(cpreg_vmstate_array_len, ARMCPU),
|
||||
VMSTATE_INT32_POSITIVE_LE(cpreg_vmstate_array_len, ARMCPU),
|
||||
VMSTATE_VARRAY_INT32(cpreg_vmstate_indexes, ARMCPU,
|
||||
cpreg_vmstate_array_len,
|
||||
0, vmstate_info_uint64, uint64_t),
|
||||
|
@@ -7455,7 +7455,7 @@ static void disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn)
|
||||
}
|
||||
break;
|
||||
case 0x12: /* SQXTUN */
|
||||
if (u) {
|
||||
if (!u) {
|
||||
unallocated_encoding(s);
|
||||
return;
|
||||
}
|
||||
|
@@ -8328,27 +8328,39 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
|
||||
if (insn & (1 << 5))
|
||||
gen_swap_half(tmp2);
|
||||
gen_smul_dual(tmp, tmp2);
|
||||
if (insn & (1 << 6)) {
|
||||
/* This subtraction cannot overflow. */
|
||||
tcg_gen_sub_i32(tmp, tmp, tmp2);
|
||||
} else {
|
||||
/* This addition cannot overflow 32 bits;
|
||||
* however it may overflow considered as a signed
|
||||
* operation, in which case we must set the Q flag.
|
||||
*/
|
||||
gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
|
||||
}
|
||||
tcg_temp_free_i32(tmp2);
|
||||
if (insn & (1 << 22)) {
|
||||
/* smlald, smlsld */
|
||||
TCGv_i64 tmp64_2;
|
||||
|
||||
tmp64 = tcg_temp_new_i64();
|
||||
tmp64_2 = tcg_temp_new_i64();
|
||||
tcg_gen_ext_i32_i64(tmp64, tmp);
|
||||
tcg_gen_ext_i32_i64(tmp64_2, tmp2);
|
||||
tcg_temp_free_i32(tmp);
|
||||
tcg_temp_free_i32(tmp2);
|
||||
if (insn & (1 << 6)) {
|
||||
tcg_gen_sub_i64(tmp64, tmp64, tmp64_2);
|
||||
} else {
|
||||
tcg_gen_add_i64(tmp64, tmp64, tmp64_2);
|
||||
}
|
||||
tcg_temp_free_i64(tmp64_2);
|
||||
gen_addq(s, tmp64, rd, rn);
|
||||
gen_storeq_reg(s, rd, rn, tmp64);
|
||||
tcg_temp_free_i64(tmp64);
|
||||
} else {
|
||||
/* smuad, smusd, smlad, smlsd */
|
||||
if (insn & (1 << 6)) {
|
||||
/* This subtraction cannot overflow. */
|
||||
tcg_gen_sub_i32(tmp, tmp, tmp2);
|
||||
} else {
|
||||
/* This addition cannot overflow 32 bits;
|
||||
* however it may overflow considered as a
|
||||
* signed operation, in which case we must set
|
||||
* the Q flag.
|
||||
*/
|
||||
gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
|
||||
}
|
||||
tcg_temp_free_i32(tmp2);
|
||||
if (rd != 15)
|
||||
{
|
||||
tmp2 = load_reg(s, rd);
|
||||
|
@@ -717,6 +717,22 @@ static void tcg_out_call(TCGContext *s, tcg_target_long arg, int const_arg)
|
||||
tcg_out32(s, MTSPR | RS(arg) | LR);
|
||||
tcg_out32(s, BCLR | BO_ALWAYS | LK);
|
||||
}
|
||||
#elif _CALL_ELF == 2
|
||||
/* In the ELFv2 ABI, we do not need to set up the TOC pointer in r2,
|
||||
but instead we have to set up r12 to contain the destination address
|
||||
when performing an indirect call. */
|
||||
TCGReg reg = arg;
|
||||
if (const_arg) {
|
||||
/* FIXME: we could use bl if we knew that the destination uses
|
||||
the same TOC, and what its local entry point offset is.
|
||||
For now, always perform an indirect call. */
|
||||
tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R12, arg);
|
||||
reg = TCG_REG_R12;
|
||||
} else {
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_R12, arg);
|
||||
}
|
||||
tcg_out32(s, MTSPR | RS(reg) | CTR);
|
||||
tcg_out32(s, BCCTR | BO_ALWAYS | LK);
|
||||
#else
|
||||
TCGReg reg = arg;
|
||||
int ofs = 0;
|
||||
@@ -1112,7 +1128,7 @@ static void tcg_target_qemu_prologue(TCGContext *s)
|
||||
REG_SAVE_BOT - CPU_TEMP_BUF_NLONGS * sizeof(long),
|
||||
CPU_TEMP_BUF_NLONGS * sizeof(long));
|
||||
|
||||
#ifndef __APPLE__
|
||||
#if !defined(__APPLE__) && _CALL_ELF != 2
|
||||
/* First emit adhoc function descriptor */
|
||||
tcg_out64(s, (uint64_t)s->code_ptr + 24); /* entry point */
|
||||
s->code_ptr += 16; /* skip TOC and environment pointer */
|
||||
|
36
tcg/tcg.c
36
tcg/tcg.c
@@ -40,6 +40,8 @@
|
||||
#include "qemu/cache-utils.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "config-host.h"
|
||||
#include "qemu/thread.h"
|
||||
|
||||
/* Note: the long term plan is to reduce the dependencies on the QEMU
|
||||
CPU definitions. Currently they are used for qemu_ld/st
|
||||
@@ -117,6 +119,29 @@ const size_t tcg_op_defs_max = ARRAY_SIZE(tcg_op_defs);
|
||||
static TCGRegSet tcg_target_available_regs[2];
|
||||
static TCGRegSet tcg_target_call_clobber_regs;
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
static __thread int tcg_lock_count;
|
||||
#endif
|
||||
void tcg_lock(void)
|
||||
{
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
TCGContext *s = &tcg_ctx;
|
||||
if (tcg_lock_count++ == 0) {
|
||||
qemu_mutex_lock(&s->lock);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void tcg_unlock(void)
|
||||
{
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
TCGContext *s = &tcg_ctx;
|
||||
if (--tcg_lock_count == 0) {
|
||||
qemu_mutex_unlock(&s->lock);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void tcg_out8(TCGContext *s, uint8_t v)
|
||||
{
|
||||
*s->code_ptr++ = v;
|
||||
@@ -295,7 +320,8 @@ void tcg_context_init(TCGContext *s)
|
||||
|
||||
memset(s, 0, sizeof(*s));
|
||||
s->nb_globals = 0;
|
||||
|
||||
qemu_mutex_init(&s->lock);
|
||||
|
||||
/* Count total number of arguments and allocate the corresponding
|
||||
space */
|
||||
total_args = 0;
|
||||
@@ -2597,10 +2623,12 @@ int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
|
||||
}
|
||||
#endif
|
||||
|
||||
tcg_lock();
|
||||
tcg_gen_code_common(s, gen_code_buf, -1);
|
||||
|
||||
/* flush instruction cache */
|
||||
flush_icache_range((uintptr_t)gen_code_buf, (uintptr_t)s->code_ptr);
|
||||
tcg_unlock();
|
||||
|
||||
return s->code_ptr - gen_code_buf;
|
||||
}
|
||||
@@ -2611,7 +2639,11 @@ int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
|
||||
Return -1 if not found. */
|
||||
int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
|
||||
{
|
||||
return tcg_gen_code_common(s, gen_code_buf, offset);
|
||||
int r;
|
||||
tcg_lock();
|
||||
r = tcg_gen_code_common(s, gen_code_buf, offset);
|
||||
tcg_unlock();
|
||||
return r;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PROFILER
|
||||
|
@@ -54,6 +54,8 @@ typedef uint64_t tcg_target_ulong;
|
||||
#error unsupported
|
||||
#endif
|
||||
|
||||
#include "config-host.h"
|
||||
#include "qemu/thread.h"
|
||||
#include "tcg-runtime.h"
|
||||
|
||||
#if TCG_TARGET_NB_REGS <= 32
|
||||
@@ -530,6 +532,7 @@ struct TCGContext {
|
||||
|
||||
/* The TCGBackendData structure is private to tcg-target.c. */
|
||||
struct TCGBackendData *be;
|
||||
QemuMutex lock;
|
||||
};
|
||||
|
||||
extern TCGContext tcg_ctx;
|
||||
@@ -707,6 +710,9 @@ void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
|
||||
TCGArg *tcg_optimize(TCGContext *s, uint16_t *tcg_opc_ptr, TCGArg *args,
|
||||
TCGOpDef *tcg_op_def);
|
||||
|
||||
extern void tcg_lock(void);
|
||||
extern void tcg_unlock(void);
|
||||
|
||||
/* only used for debugging purposes */
|
||||
void tcg_dump_ops(TCGContext *s);
|
||||
|
||||
|
@@ -162,7 +162,9 @@ check-qtest-microblazeel-y = $(check-qtest-microblaze-y)
|
||||
check-qtest-xtensaeb-y = $(check-qtest-xtensa-y)
|
||||
|
||||
# qom-test works for all sysemu architectures:
|
||||
$(foreach target,$(SYSEMU_TARGET_LIST), \
|
||||
QTEST_SYSEMU_TARGET_LIST=$(filter-out x86_64 microblazeel xtensaeb, \
|
||||
$(SYSEMU_TARGET_LIST))
|
||||
$(foreach target,$(QTEST_SYSEMU_TARGET_LIST), \
|
||||
$(eval check-qtest-$(target)-y += tests/qom-test$(EXESUF)))
|
||||
|
||||
check-qapi-schema-y := $(addprefix tests/qapi-schema/, \
|
||||
|
@@ -34,7 +34,7 @@
|
||||
#include "qapi/qmp/json-parser.h"
|
||||
|
||||
#define MAX_IRQ 256
|
||||
#define SOCKET_TIMEOUT 5
|
||||
#define SOCKET_TIMEOUT 15
|
||||
|
||||
QTestState *global_qtest;
|
||||
|
||||
@@ -72,7 +72,8 @@ static int init_socket(const char *socket_path)
|
||||
ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
|
||||
} while (ret == -1 && errno == EINTR);
|
||||
g_assert_no_errno(ret);
|
||||
listen(sock, 1);
|
||||
ret = listen(sock, 1);
|
||||
g_assert_no_errno(ret);
|
||||
|
||||
return sock;
|
||||
}
|
||||
@@ -88,10 +89,13 @@ static int socket_accept(int sock)
|
||||
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (void *)&timeout,
|
||||
sizeof(timeout));
|
||||
|
||||
addrlen = sizeof(addr);
|
||||
do {
|
||||
addrlen = sizeof(addr);
|
||||
ret = accept(sock, (struct sockaddr *)&addr, &addrlen);
|
||||
} while (ret == -1 && errno == EINTR);
|
||||
if (ret == -1) {
|
||||
fprintf(stderr, "%s failed: %s\n", __func__, strerror(errno));
|
||||
}
|
||||
close(sock);
|
||||
|
||||
return ret;
|
||||
|
21
thunk.c
21
thunk.c
@@ -41,6 +41,7 @@ static inline const argtype *thunk_type_next(const argtype *type_ptr)
|
||||
case TYPE_CHAR:
|
||||
case TYPE_SHORT:
|
||||
case TYPE_INT:
|
||||
case TYPE_INTBITFIELD:
|
||||
case TYPE_LONGLONG:
|
||||
case TYPE_ULONGLONG:
|
||||
case TYPE_LONG:
|
||||
@@ -140,6 +141,26 @@ const argtype *thunk_convert(void *dst, const void *src,
|
||||
case TYPE_INT:
|
||||
*(uint32_t *)dst = tswap32(*(uint32_t *)src);
|
||||
break;
|
||||
case TYPE_INTBITFIELD:
|
||||
#if defined(TARGET_I386) && defined(__powerpc__)
|
||||
/* powerpc uses the MSB, whereas i386 uses the LSB
|
||||
* to store the first bit in a field */
|
||||
{
|
||||
unsigned char byte = *(uint8_t *)src;
|
||||
*(uint8_t *)dst = ((byte >> 7) & 1)
|
||||
| ((byte >> 5) & 2)
|
||||
| ((byte >> 3) & 4)
|
||||
| ((byte >> 1) & 8)
|
||||
| ((byte << 1) & 16)
|
||||
| ((byte << 3) & 32)
|
||||
| ((byte << 5) & 64)
|
||||
| ((byte << 7) & 128);
|
||||
/* FIXME: implement for bitfields > 1 byte and other archs */
|
||||
}
|
||||
#else
|
||||
*(uint32_t *)dst = tswap32(*(uint32_t *)src);
|
||||
#endif
|
||||
break;
|
||||
case TYPE_LONGLONG:
|
||||
case TYPE_ULONGLONG:
|
||||
*(uint64_t *)dst = tswap64(*(uint64_t *)src);
|
||||
|
@@ -619,19 +619,23 @@ static TranslationBlock *tb_alloc(target_ulong pc)
|
||||
{
|
||||
TranslationBlock *tb;
|
||||
|
||||
tcg_lock();
|
||||
if (tcg_ctx.tb_ctx.nb_tbs >= tcg_ctx.code_gen_max_blocks ||
|
||||
(tcg_ctx.code_gen_ptr - tcg_ctx.code_gen_buffer) >=
|
||||
tcg_ctx.code_gen_buffer_max_size) {
|
||||
tcg_unlock();
|
||||
return NULL;
|
||||
}
|
||||
tb = &tcg_ctx.tb_ctx.tbs[tcg_ctx.tb_ctx.nb_tbs++];
|
||||
tb->pc = pc;
|
||||
tb->cflags = 0;
|
||||
tcg_unlock();
|
||||
return tb;
|
||||
}
|
||||
|
||||
void tb_free(TranslationBlock *tb)
|
||||
{
|
||||
tcg_lock();
|
||||
/* In practice this is mostly used for single use temporary TB
|
||||
Ignore the hard cases and just back up if this TB happens to
|
||||
be the last one generated. */
|
||||
@@ -640,6 +644,7 @@ void tb_free(TranslationBlock *tb)
|
||||
tcg_ctx.code_gen_ptr = tb->tc_ptr;
|
||||
tcg_ctx.tb_ctx.nb_tbs--;
|
||||
}
|
||||
tcg_unlock();
|
||||
}
|
||||
|
||||
static inline void invalidate_page_bitmap(PageDesc *p)
|
||||
@@ -697,6 +702,7 @@ void tb_flush(CPUArchState *env1)
|
||||
((unsigned long)(tcg_ctx.code_gen_ptr - tcg_ctx.code_gen_buffer)) /
|
||||
tcg_ctx.tb_ctx.nb_tbs : 0);
|
||||
#endif
|
||||
tcg_lock();
|
||||
if ((unsigned long)(tcg_ctx.code_gen_ptr - tcg_ctx.code_gen_buffer)
|
||||
> tcg_ctx.code_gen_buffer_size) {
|
||||
cpu_abort(cpu, "Internal error: code buffer overflow\n");
|
||||
@@ -714,6 +720,7 @@ void tb_flush(CPUArchState *env1)
|
||||
/* XXX: flush processor icache at this point if cache flush is
|
||||
expensive */
|
||||
tcg_ctx.tb_ctx.tb_flush_count++;
|
||||
tcg_unlock();
|
||||
}
|
||||
|
||||
#ifdef DEBUG_TB_CHECK
|
||||
@@ -1022,8 +1029,10 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
|
||||
int current_flags = 0;
|
||||
#endif /* TARGET_HAS_PRECISE_SMC */
|
||||
|
||||
tcg_lock();
|
||||
p = page_find(start >> TARGET_PAGE_BITS);
|
||||
if (!p) {
|
||||
tcg_unlock();
|
||||
return;
|
||||
}
|
||||
if (!p->code_bitmap &&
|
||||
@@ -1116,6 +1125,7 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
|
||||
cpu_resume_from_signal(cpu, NULL);
|
||||
}
|
||||
#endif
|
||||
tcg_unlock();
|
||||
}
|
||||
|
||||
/* len must be <= 8 and start must be a multiple of len */
|
||||
@@ -1327,13 +1337,16 @@ static TranslationBlock *tb_find_pc(uintptr_t tc_ptr)
|
||||
{
|
||||
int m_min, m_max, m;
|
||||
uintptr_t v;
|
||||
TranslationBlock *tb;
|
||||
TranslationBlock *tb, *r;
|
||||
|
||||
tcg_lock();
|
||||
if (tcg_ctx.tb_ctx.nb_tbs <= 0) {
|
||||
tcg_unlock();
|
||||
return NULL;
|
||||
}
|
||||
if (tc_ptr < (uintptr_t)tcg_ctx.code_gen_buffer ||
|
||||
tc_ptr >= (uintptr_t)tcg_ctx.code_gen_ptr) {
|
||||
tcg_unlock();
|
||||
return NULL;
|
||||
}
|
||||
/* binary search (cf Knuth) */
|
||||
@@ -1344,6 +1357,7 @@ static TranslationBlock *tb_find_pc(uintptr_t tc_ptr)
|
||||
tb = &tcg_ctx.tb_ctx.tbs[m];
|
||||
v = (uintptr_t)tb->tc_ptr;
|
||||
if (v == tc_ptr) {
|
||||
tcg_unlock();
|
||||
return tb;
|
||||
} else if (tc_ptr < v) {
|
||||
m_max = m - 1;
|
||||
@@ -1351,7 +1365,9 @@ static TranslationBlock *tb_find_pc(uintptr_t tc_ptr)
|
||||
m_min = m + 1;
|
||||
}
|
||||
}
|
||||
return &tcg_ctx.tb_ctx.tbs[m_max];
|
||||
r = &tcg_ctx.tb_ctx.tbs[m_max];
|
||||
tcg_unlock();
|
||||
return r;
|
||||
}
|
||||
|
||||
#if defined(TARGET_HAS_ICE) && !defined(CONFIG_USER_ONLY)
|
||||
|
@@ -866,7 +866,7 @@ static void console_putchar(QemuConsole *s, int ch)
|
||||
} else {
|
||||
if (s->nb_esc_params < MAX_ESC_PARAMS)
|
||||
s->nb_esc_params++;
|
||||
if (ch == ';')
|
||||
if (ch == ';' || ch == '?')
|
||||
break;
|
||||
trace_console_putchar_csi(s->esc_params[0], s->esc_params[1],
|
||||
ch, s->nb_esc_params);
|
||||
|
71
ui/vnc.c
71
ui/vnc.c
@@ -45,6 +45,7 @@ static const struct timeval VNC_REFRESH_LOSSY = { 2, 0 };
|
||||
#include "d3des.h"
|
||||
|
||||
static VncDisplay *vnc_display; /* needed for info vnc */
|
||||
static int allowed_connections = 0;
|
||||
|
||||
static int vnc_cursor_define(VncState *vs);
|
||||
static void vnc_release_modifiers(VncState *vs);
|
||||
@@ -1031,6 +1032,7 @@ static void vnc_disconnect_start(VncState *vs)
|
||||
void vnc_disconnect_finish(VncState *vs)
|
||||
{
|
||||
int i;
|
||||
static int num_disconnects = 0;
|
||||
|
||||
vnc_jobs_join(vs); /* Wait encoding jobs */
|
||||
|
||||
@@ -1079,6 +1081,13 @@ void vnc_disconnect_finish(VncState *vs)
|
||||
}
|
||||
g_free(vs->lossy_rect);
|
||||
g_free(vs);
|
||||
|
||||
num_disconnects++;
|
||||
if (allowed_connections > 0 && allowed_connections <= num_disconnects) {
|
||||
VNC_DEBUG("Maximum number of disconnects (%d) reached:"
|
||||
" Session terminating\n", allowed_connections);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
int vnc_client_io_error(VncState *vs, int ret, int last_errno)
|
||||
@@ -3041,6 +3050,39 @@ char *vnc_display_local_addr(DisplayState *ds)
|
||||
return vnc_socket_local_addr("%s:%s", vs->lsock);
|
||||
}
|
||||
|
||||
static void read_file_password(DisplayState *ds, char *filename)
|
||||
{
|
||||
FILE *pfile = NULL;
|
||||
char *passwd = NULL;
|
||||
int start = 0, length = 0, rc = 0;
|
||||
|
||||
if(strlen(filename) == 0) {
|
||||
printf("No file supplied\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pfile = fopen(filename, "r");
|
||||
if(pfile == NULL) {
|
||||
printf("Could not read from %s\n", filename);
|
||||
return;
|
||||
}
|
||||
|
||||
start = ftell(pfile);
|
||||
fseek(pfile, 0L, SEEK_END);
|
||||
length = ftell(pfile);
|
||||
fseek(pfile, 0L, start);
|
||||
|
||||
passwd = malloc(length+1);
|
||||
rc = fread(passwd, 1, length, pfile);
|
||||
fclose(pfile);
|
||||
|
||||
if(rc == length && rc > 0) {
|
||||
vnc_display_password(ds, passwd);
|
||||
}
|
||||
|
||||
free(passwd);
|
||||
}
|
||||
|
||||
void vnc_display_open(DisplayState *ds, const char *display, Error **errp)
|
||||
{
|
||||
VncDisplay *vs = vnc_display;
|
||||
@@ -3074,6 +3116,9 @@ void vnc_display_open(DisplayState *ds, const char *display, Error **errp)
|
||||
while ((options = strchr(options, ','))) {
|
||||
options++;
|
||||
if (strncmp(options, "password", 8) == 0) {
|
||||
char *start, *end;
|
||||
start = strchr(options, '=');
|
||||
end = strchr(options, ',');
|
||||
if (fips_get_state()) {
|
||||
error_setg(errp,
|
||||
"VNC password auth disabled due to FIPS mode, "
|
||||
@@ -3082,6 +3127,32 @@ void vnc_display_open(DisplayState *ds, const char *display, Error **errp)
|
||||
goto fail;
|
||||
}
|
||||
password = 1; /* Require password auth */
|
||||
if (start && (!end || (start < end))) {
|
||||
int len = end ? end-(start+1) : strlen(start+1);
|
||||
char *text = g_malloc(len+1);
|
||||
strncpy(text, start+1, len);
|
||||
text[len] = '\0';
|
||||
|
||||
if (strncmp(options, "password-file=", 14) == 0) {
|
||||
read_file_password(ds, text);
|
||||
} else {
|
||||
vnc_display_password(ds, text);
|
||||
}
|
||||
|
||||
free(text);
|
||||
}
|
||||
} else if (strncmp(options, "allowed-connections=", 20) == 0) {
|
||||
char *start, *end;
|
||||
start = strchr(options, '=');
|
||||
end = strchr(options, ',');
|
||||
if (start && (!end || (start < end))) {
|
||||
int len = end ? end-(start+1) : strlen(start+1);
|
||||
char *text = g_malloc(len+1);
|
||||
strncpy(text, start+1, len);
|
||||
text[len] = '\0';
|
||||
VNC_DEBUG("Maximum number of disconnects: %s\n", text);
|
||||
allowed_connections = atoi(text);
|
||||
}
|
||||
} else if (strncmp(options, "reverse", 7) == 0) {
|
||||
reverse = 1;
|
||||
} else if (strncmp(options, "no-lock-key-sync", 16) == 0) {
|
||||
|
@@ -93,6 +93,10 @@ static inline int handle_cpu_signal(uintptr_t pc, unsigned long address,
|
||||
qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
|
||||
pc, address, is_write, *(unsigned long *)old_set);
|
||||
#endif
|
||||
|
||||
/* Maybe we're still holding the TB fiddling lock? */
|
||||
spin_unlock_safe(&tcg_ctx.tb_ctx.tb_lock);
|
||||
|
||||
/* XXX: locking issue */
|
||||
if (is_write && h2g_valid(address)
|
||||
&& page_unprotect(h2g(address), pc, puc)) {
|
||||
|
9
vl.c
9
vl.c
@@ -162,6 +162,7 @@ const char *vnc_display;
|
||||
int acpi_enabled = 1;
|
||||
int no_hpet = 0;
|
||||
int fd_bootchk = 1;
|
||||
int slirp_nooutgoing = 0;
|
||||
static int no_reboot;
|
||||
int no_shutdown = 0;
|
||||
int cursor_hide = 1;
|
||||
@@ -3351,6 +3352,14 @@ int main(int argc, char **argv, char **envp)
|
||||
case QEMU_OPTION_singlestep:
|
||||
singlestep = 1;
|
||||
break;
|
||||
case QEMU_OPTION_nooutgoing:
|
||||
slirp_nooutgoing = inet_addr(optarg);
|
||||
if (slirp_nooutgoing == INADDR_NONE) {
|
||||
printf("Invalid address: %s.\nOnly addresses of the format "
|
||||
"xxx.xxx.xxx.xxx are supported.\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case QEMU_OPTION_S:
|
||||
autostart = 0;
|
||||
break;
|
||||
|
26
vmstate.c
26
vmstate.c
@@ -19,11 +19,12 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
|
||||
if (version_id > vmsd->version_id) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (version_id < vmsd->minimum_version_id_old) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (version_id < vmsd->minimum_version_id) {
|
||||
return vmsd->load_state_old(f, opaque, version_id);
|
||||
if (vmsd->load_state_old &&
|
||||
version_id >= vmsd->minimum_version_id_old) {
|
||||
return vmsd->load_state_old(f, opaque, version_id);
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
if (vmsd->pre_load) {
|
||||
int ret = vmsd->pre_load(opaque);
|
||||
@@ -78,6 +79,10 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
} else if (field->flags & VMS_MUST_EXIST) {
|
||||
fprintf(stderr, "Input validation failed: %s/%s\n",
|
||||
vmsd->name, field->name);
|
||||
return -1;
|
||||
}
|
||||
field++;
|
||||
}
|
||||
@@ -138,6 +143,12 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
|
||||
field->info->put(f, addr, size);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (field->flags & VMS_MUST_EXIST) {
|
||||
fprintf(stderr, "Output state validation failed: %s/%s\n",
|
||||
vmsd->name, field->name);
|
||||
assert(!(field->flags & VMS_MUST_EXIST));
|
||||
}
|
||||
}
|
||||
field++;
|
||||
}
|
||||
@@ -323,8 +334,9 @@ const VMStateInfo vmstate_info_int32_equal = {
|
||||
.put = put_int32,
|
||||
};
|
||||
|
||||
/* 32 bit int. Check that the received value is less than or equal to
|
||||
the one in the field */
|
||||
/* 32 bit int. Check that the received value is non-negative
|
||||
* and less than or equal to the one in the field.
|
||||
*/
|
||||
|
||||
static int get_int32_le(QEMUFile *f, void *pv, size_t size)
|
||||
{
|
||||
@@ -332,7 +344,7 @@ static int get_int32_le(QEMUFile *f, void *pv, size_t size)
|
||||
int32_t loaded;
|
||||
qemu_get_sbe32s(f, &loaded);
|
||||
|
||||
if (loaded <= *cur) {
|
||||
if (loaded >= 0 && loaded <= *cur) {
|
||||
*cur = loaded;
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user