qtest: ask endianness of the target in qtest_init()
The target endianness is not deduced anymore from the architecture name but asked directly to the guest, using a new qtest command: "endianness". As it can't change (this is the value of TARGET_WORDS_BIGENDIAN), we store it to not have to ask every time we want to know if we have to byte-swap a value. Signed-off-by: Laurent Vivier <lvivier@redhat.com> CC: Greg Kurz <groug@kaod.org> CC: David Gibson <david@gibson.dropbear.id.au> CC: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
parent
44a3dd9b87
commit
54ce6f22e8
7
qtest.c
7
qtest.c
@ -537,6 +537,13 @@ static void qtest_process_command(CharDriverState *chr, gchar **words)
|
|||||||
|
|
||||||
qtest_send_prefix(chr);
|
qtest_send_prefix(chr);
|
||||||
qtest_send(chr, "OK\n");
|
qtest_send(chr, "OK\n");
|
||||||
|
} else if (strcmp(words[0], "endianness") == 0) {
|
||||||
|
qtest_send_prefix(chr);
|
||||||
|
#if defined(TARGET_WORDS_BIGENDIAN)
|
||||||
|
qtest_sendf(chr, "OK big\n");
|
||||||
|
#else
|
||||||
|
qtest_sendf(chr, "OK little\n");
|
||||||
|
#endif
|
||||||
#ifdef TARGET_PPC64
|
#ifdef TARGET_PPC64
|
||||||
} else if (strcmp(words[0], "rtas") == 0) {
|
} else if (strcmp(words[0], "rtas") == 0) {
|
||||||
uint64_t res, args, ret;
|
uint64_t res, args, ret;
|
||||||
|
@ -86,7 +86,7 @@ static uint64_t qvirtio_pci_config_readq(QVirtioDevice *d, uint64_t addr)
|
|||||||
int i;
|
int i;
|
||||||
uint64_t u64 = 0;
|
uint64_t u64 = 0;
|
||||||
|
|
||||||
if (qtest_big_endian()) {
|
if (target_big_endian()) {
|
||||||
for (i = 0; i < 8; ++i) {
|
for (i = 0; i < 8; ++i) {
|
||||||
u64 |= (uint64_t)qpci_io_readb(dev->pdev,
|
u64 |= (uint64_t)qpci_io_readb(dev->pdev,
|
||||||
(void *)(uintptr_t)addr + i) << (7 - i) * 8;
|
(void *)(uintptr_t)addr + i) << (7 - i) * 8;
|
||||||
|
@ -37,6 +37,7 @@ struct QTestState
|
|||||||
bool irq_level[MAX_IRQ];
|
bool irq_level[MAX_IRQ];
|
||||||
GString *rx;
|
GString *rx;
|
||||||
pid_t qemu_pid; /* our child QEMU process */
|
pid_t qemu_pid; /* our child QEMU process */
|
||||||
|
bool big_endian;
|
||||||
};
|
};
|
||||||
|
|
||||||
static GHookList abrt_hooks;
|
static GHookList abrt_hooks;
|
||||||
@ -47,6 +48,8 @@ static struct sigaction sigact_old;
|
|||||||
g_assert_cmpint(ret, !=, -1); \
|
g_assert_cmpint(ret, !=, -1); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
static int qtest_query_target_endianness(QTestState *s);
|
||||||
|
|
||||||
static int init_socket(const char *socket_path)
|
static int init_socket(const char *socket_path)
|
||||||
{
|
{
|
||||||
struct sockaddr_un addr;
|
struct sockaddr_un addr;
|
||||||
@ -209,6 +212,10 @@ QTestState *qtest_init(const char *extra_args)
|
|||||||
kill(s->qemu_pid, SIGSTOP);
|
kill(s->qemu_pid, SIGSTOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ask endianness of the target */
|
||||||
|
|
||||||
|
s->big_endian = qtest_query_target_endianness(s);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,6 +349,20 @@ redo:
|
|||||||
return words;
|
return words;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int qtest_query_target_endianness(QTestState *s)
|
||||||
|
{
|
||||||
|
gchar **args;
|
||||||
|
int big_endian;
|
||||||
|
|
||||||
|
qtest_sendf(s, "endianness\n");
|
||||||
|
args = qtest_rsp(s, 1);
|
||||||
|
g_assert(strcmp(args[1], "big") == 0 || strcmp(args[1], "little") == 0);
|
||||||
|
big_endian = strcmp(args[1], "big") == 0;
|
||||||
|
g_strfreev(args);
|
||||||
|
|
||||||
|
return big_endian;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
JSONMessageParser parser;
|
JSONMessageParser parser;
|
||||||
QDict *response;
|
QDict *response;
|
||||||
@ -886,50 +907,7 @@ char *hmp(const char *fmt, ...)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool qtest_big_endian(void)
|
bool qtest_big_endian(QTestState *s)
|
||||||
{
|
{
|
||||||
const char *arch = qtest_get_arch();
|
return s->big_endian;
|
||||||
int i;
|
|
||||||
|
|
||||||
static const struct {
|
|
||||||
const char *arch;
|
|
||||||
bool big_endian;
|
|
||||||
} endianness[] = {
|
|
||||||
{ "aarch64", false },
|
|
||||||
{ "alpha", false },
|
|
||||||
{ "arm", false },
|
|
||||||
{ "cris", false },
|
|
||||||
{ "i386", false },
|
|
||||||
{ "lm32", true },
|
|
||||||
{ "m68k", true },
|
|
||||||
{ "microblaze", true },
|
|
||||||
{ "microblazeel", false },
|
|
||||||
{ "mips", true },
|
|
||||||
{ "mips64", true },
|
|
||||||
{ "mips64el", false },
|
|
||||||
{ "mipsel", false },
|
|
||||||
{ "moxie", true },
|
|
||||||
{ "or32", true },
|
|
||||||
{ "ppc", true },
|
|
||||||
{ "ppc64", true },
|
|
||||||
{ "ppcemb", true },
|
|
||||||
{ "s390x", true },
|
|
||||||
{ "sh4", false },
|
|
||||||
{ "sh4eb", true },
|
|
||||||
{ "sparc", true },
|
|
||||||
{ "sparc64", true },
|
|
||||||
{ "unicore32", false },
|
|
||||||
{ "x86_64", false },
|
|
||||||
{ "xtensa", false },
|
|
||||||
{ "xtensaeb", true },
|
|
||||||
{},
|
|
||||||
};
|
|
||||||
|
|
||||||
for (i = 0; endianness[i].arch; i++) {
|
|
||||||
if (strcmp(endianness[i].arch, arch) == 0) {
|
|
||||||
return endianness[i].big_endian;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
@ -409,6 +409,14 @@ int64_t qtest_clock_step(QTestState *s, int64_t step);
|
|||||||
*/
|
*/
|
||||||
int64_t qtest_clock_set(QTestState *s, int64_t val);
|
int64_t qtest_clock_set(QTestState *s, int64_t val);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qtest_big_endian:
|
||||||
|
* @s: QTestState instance to operate on.
|
||||||
|
*
|
||||||
|
* Returns: True if the architecture under test has a big endian configuration.
|
||||||
|
*/
|
||||||
|
bool qtest_big_endian(QTestState *s);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qtest_get_arch:
|
* qtest_get_arch:
|
||||||
*
|
*
|
||||||
@ -874,12 +882,14 @@ static inline int64_t clock_set(int64_t val)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qtest_big_endian:
|
* target_big_endian:
|
||||||
*
|
*
|
||||||
* Returns: True if the architecture under test has a big endian configuration.
|
* Returns: True if the architecture under test has a big endian configuration.
|
||||||
*/
|
*/
|
||||||
bool qtest_big_endian(void);
|
static inline bool target_big_endian(void)
|
||||||
|
{
|
||||||
|
return qtest_big_endian(global_qtest);
|
||||||
|
}
|
||||||
|
|
||||||
QDict *qmp_fd_receive(int fd);
|
QDict *qmp_fd_receive(int fd);
|
||||||
void qmp_fd_sendv(int fd, const char *fmt, va_list ap);
|
void qmp_fd_sendv(int fd, const char *fmt, va_list ap);
|
||||||
|
@ -125,7 +125,7 @@ static inline void virtio_blk_fix_request(QVirtioBlkReq *req)
|
|||||||
bool host_endian = false;
|
bool host_endian = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (qtest_big_endian() != host_endian) {
|
if (target_big_endian() != host_endian) {
|
||||||
req->type = bswap32(req->type);
|
req->type = bswap32(req->type);
|
||||||
req->ioprio = bswap32(req->ioprio);
|
req->ioprio = bswap32(req->ioprio);
|
||||||
req->sector = bswap64(req->sector);
|
req->sector = bswap64(req->sector);
|
||||||
|
Loading…
Reference in New Issue
Block a user