summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--audio/audio.c14
-rw-r--r--audio/audio.h2
-rw-r--r--chardev/char-socket.c4
-rw-r--r--include/sysemu/os-win32.h17
-rw-r--r--meson.build3
-rw-r--r--softmmu/vl.c4
-rw-r--r--target/avr/helper.c69
-rw-r--r--target/avr/translate.c26
-rw-r--r--tests/unit/socket-helpers.c16
-rw-r--r--tests/unit/socket-helpers.h9
-rw-r--r--tests/unit/test-io-channel-socket.c37
-rw-r--r--util/qemu-sockets.c25
12 files changed, 150 insertions, 76 deletions
diff --git a/audio/audio.c b/audio/audio.c
index a02f3ce5c6..76b8735b44 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -1743,7 +1743,6 @@ static AudioState *audio_init(Audiodev *dev, const char *name)
atexit(audio_cleanup);
atexit_registered = true;
}
- QTAILQ_INSERT_TAIL(&audio_states, s, list);
s->ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, audio_timer, s);
@@ -1769,6 +1768,10 @@ static AudioState *audio_init(Audiodev *dev, const char *name)
} else {
dolog ("Unknown audio driver `%s'\n", drvname);
}
+ if (!done) {
+ free_audio_state(s);
+ return NULL;
+ }
} else {
for (i = 0; audio_prio_list[i]; i++) {
AudiodevListEntry *e = audiodev_find(&head, audio_prio_list[i]);
@@ -1806,6 +1809,7 @@ static AudioState *audio_init(Audiodev *dev, const char *name)
"(Audio can continue looping even after stopping the VM)\n");
}
+ QTAILQ_INSERT_TAIL(&audio_states, s, list);
QLIST_INIT (&s->card_head);
vmstate_register (NULL, 0, &vmstate_audio, s);
return s;
@@ -2119,13 +2123,17 @@ void audio_define(Audiodev *dev)
QSIMPLEQ_INSERT_TAIL(&audiodevs, e, next);
}
-void audio_init_audiodevs(void)
+bool audio_init_audiodevs(void)
{
AudiodevListEntry *e;
QSIMPLEQ_FOREACH(e, &audiodevs, next) {
- audio_init(e->dev, NULL);
+ if (!audio_init(e->dev, NULL)) {
+ return false;
+ }
}
+
+ return true;
}
audsettings audiodev_to_audsettings(AudiodevPerDirectionOptions *pdo)
diff --git a/audio/audio.h b/audio/audio.h
index b5e17cd218..27e67079a0 100644
--- a/audio/audio.h
+++ b/audio/audio.h
@@ -170,7 +170,7 @@ void audio_sample_from_uint64(void *samples, int pos,
void audio_define(Audiodev *audio);
void audio_parse_option(const char *opt);
-void audio_init_audiodevs(void);
+bool audio_init_audiodevs(void);
void audio_legacy_help(void);
AudioState *audio_state_by_name(const char *name);
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index dc4e218eeb..879564aa8a 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -557,12 +557,10 @@ static char *qemu_chr_compute_filename(SocketChardev *s)
const char *left = "", *right = "";
switch (ss->ss_family) {
-#ifndef _WIN32
case AF_UNIX:
return g_strdup_printf("unix:%s%s",
((struct sockaddr_un *)(ss))->sun_path,
s->is_listen ? ",server=on" : "");
-#endif
case AF_INET6:
left = "[";
right = "]";
@@ -1372,10 +1370,12 @@ static void qmp_chardev_open_socket(Chardev *chr,
}
qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_RECONNECTABLE);
+#ifndef _WIN32
/* TODO SOCKET_ADDRESS_FD where fd has AF_UNIX */
if (addr->type == SOCKET_ADDRESS_TYPE_UNIX) {
qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_FD_PASS);
}
+#endif
/*
* In the chardev-change special-case, we shouldn't register a new yank
diff --git a/include/sysemu/os-win32.h b/include/sysemu/os-win32.h
index edc3b38a57..5b38c7bd04 100644
--- a/include/sysemu/os-win32.h
+++ b/include/sysemu/os-win32.h
@@ -30,6 +30,23 @@
#include <windows.h>
#include <ws2tcpip.h>
+#ifdef HAVE_AFUNIX_H
+#include <afunix.h>
+#else
+/*
+ * Fallback definitions of things we need in afunix.h, if not available from
+ * the used Windows SDK or MinGW headers.
+ */
+#define UNIX_PATH_MAX 108
+
+typedef struct sockaddr_un {
+ ADDRESS_FAMILY sun_family;
+ char sun_path[UNIX_PATH_MAX];
+} SOCKADDR_UN, *PSOCKADDR_UN;
+
+#define SIO_AF_UNIX_GETPEERPID _WSAIOR(IOC_VENDOR, 256)
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/meson.build b/meson.build
index 20fddbd707..169b18a279 100644
--- a/meson.build
+++ b/meson.build
@@ -1890,6 +1890,9 @@ config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
config_host_data.set('HAVE_SYS_DISK_H', cc.has_header('sys/disk.h'))
config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
+if targetos == 'windows'
+ config_host_data.set('HAVE_AFUNIX_H', cc.has_header('afunix.h'))
+endif
# has_function
config_host_data.set('CONFIG_ACCEPT4', cc.has_function('accept4'))
diff --git a/softmmu/vl.c b/softmmu/vl.c
index 706bd7cff7..dea4005e47 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -1885,7 +1885,9 @@ static void qemu_create_early_backends(void)
* setting machine properties, so they can be referred to.
*/
configure_blockdev(&bdo_queue, machine_class, snapshot);
- audio_init_audiodevs();
+ if (!audio_init_audiodevs()) {
+ exit(1);
+ }
}
diff --git a/target/avr/helper.c b/target/avr/helper.c
index db76452f9a..156dde4e92 100644
--- a/target/avr/helper.c
+++ b/target/avr/helper.c
@@ -28,36 +28,41 @@
bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
{
- bool ret = false;
- CPUClass *cc = CPU_GET_CLASS(cs);
AVRCPU *cpu = AVR_CPU(cs);
CPUAVRState *env = &cpu->env;
+ /*
+ * We cannot separate a skip from the next instruction,
+ * as the skip would not be preserved across the interrupt.
+ * Separating the two insn normally only happens at page boundaries.
+ */
+ if (env->skip) {
+ return false;
+ }
+
if (interrupt_request & CPU_INTERRUPT_RESET) {
if (cpu_interrupts_enabled(env)) {
cs->exception_index = EXCP_RESET;
- cc->tcg_ops->do_interrupt(cs);
+ avr_cpu_do_interrupt(cs);
cs->interrupt_request &= ~CPU_INTERRUPT_RESET;
-
- ret = true;
+ return true;
}
}
if (interrupt_request & CPU_INTERRUPT_HARD) {
if (cpu_interrupts_enabled(env) && env->intsrc != 0) {
int index = ctz32(env->intsrc);
cs->exception_index = EXCP_INT(index);
- cc->tcg_ops->do_interrupt(cs);
+ avr_cpu_do_interrupt(cs);
env->intsrc &= env->intsrc - 1; /* clear the interrupt */
if (!env->intsrc) {
cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
}
-
- ret = true;
+ return true;
}
}
- return ret;
+ return false;
}
void avr_cpu_do_interrupt(CPUState *cs)
@@ -102,38 +107,50 @@ bool avr_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
MMUAccessType access_type, int mmu_idx,
bool probe, uintptr_t retaddr)
{
- int prot = 0;
- MemTxAttrs attrs = {};
+ int prot, page_size = TARGET_PAGE_SIZE;
uint32_t paddr;
address &= TARGET_PAGE_MASK;
if (mmu_idx == MMU_CODE_IDX) {
- /* access to code in flash */
+ /* Access to code in flash. */
paddr = OFFSET_CODE + address;
prot = PAGE_READ | PAGE_EXEC;
- if (paddr + TARGET_PAGE_SIZE > OFFSET_DATA) {
+ if (paddr >= OFFSET_DATA) {
+ /*
+ * This should not be possible via any architectural operations.
+ * There is certainly not an exception that we can deliver.
+ * Accept probing that might come from generic code.
+ */
+ if (probe) {
+ return false;
+ }
error_report("execution left flash memory");
abort();
}
- } else if (address < NUMBER_OF_CPU_REGISTERS + NUMBER_OF_IO_REGISTERS) {
- /*
- * access to CPU registers, exit and rebuilt this TB to use full access
- * incase it touches specially handled registers like SREG or SP
- */
- AVRCPU *cpu = AVR_CPU(cs);
- CPUAVRState *env = &cpu->env;
- env->fullacc = 1;
- cpu_loop_exit_restore(cs, retaddr);
} else {
- /* access to memory. nothing special */
+ /* Access to memory. */
paddr = OFFSET_DATA + address;
prot = PAGE_READ | PAGE_WRITE;
+ if (address < NUMBER_OF_CPU_REGISTERS + NUMBER_OF_IO_REGISTERS) {
+ /*
+ * Access to CPU registers, exit and rebuilt this TB to use
+ * full access in case it touches specially handled registers
+ * like SREG or SP. For probing, set page_size = 1, in order
+ * to force tlb_fill to be called for the next access.
+ */
+ if (probe) {
+ page_size = 1;
+ } else {
+ AVRCPU *cpu = AVR_CPU(cs);
+ CPUAVRState *env = &cpu->env;
+ env->fullacc = 1;
+ cpu_loop_exit_restore(cs, retaddr);
+ }
+ }
}
- tlb_set_page_with_attrs(cs, address, paddr, attrs, prot,
- mmu_idx, TARGET_PAGE_SIZE);
-
+ tlb_set_page(cs, address, paddr, prot, mmu_idx, page_size);
return true;
}
diff --git a/target/avr/translate.c b/target/avr/translate.c
index dc9c3d6bcc..026753c963 100644
--- a/target/avr/translate.c
+++ b/target/avr/translate.c
@@ -2971,8 +2971,18 @@ static void avr_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
if (skip_label) {
canonicalize_skip(ctx);
gen_set_label(skip_label);
- if (ctx->base.is_jmp == DISAS_NORETURN) {
+
+ switch (ctx->base.is_jmp) {
+ case DISAS_NORETURN:
ctx->base.is_jmp = DISAS_CHAIN;
+ break;
+ case DISAS_NEXT:
+ if (ctx->base.tb->flags & TB_FLAGS_SKIP) {
+ ctx->base.is_jmp = DISAS_TOO_MANY;
+ }
+ break;
+ default:
+ break;
}
}
@@ -2989,6 +2999,11 @@ static void avr_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
{
DisasContext *ctx = container_of(dcbase, DisasContext, base);
bool nonconst_skip = canonicalize_skip(ctx);
+ /*
+ * Because we disable interrupts while env->skip is set,
+ * we must return to the main loop to re-evaluate afterward.
+ */
+ bool force_exit = ctx->base.tb->flags & TB_FLAGS_SKIP;
switch (ctx->base.is_jmp) {
case DISAS_NORETURN:
@@ -2997,7 +3012,7 @@ static void avr_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
case DISAS_NEXT:
case DISAS_TOO_MANY:
case DISAS_CHAIN:
- if (!nonconst_skip) {
+ if (!nonconst_skip && !force_exit) {
/* Note gen_goto_tb checks singlestep. */
gen_goto_tb(ctx, 1, ctx->npc);
break;
@@ -3005,8 +3020,11 @@ static void avr_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
tcg_gen_movi_tl(cpu_pc, ctx->npc);
/* fall through */
case DISAS_LOOKUP:
- tcg_gen_lookup_and_goto_ptr();
- break;
+ if (!force_exit) {
+ tcg_gen_lookup_and_goto_ptr();
+ break;
+ }
+ /* fall through */
case DISAS_EXIT:
tcg_gen_exit_tb(NULL, 0);
break;
diff --git a/tests/unit/socket-helpers.c b/tests/unit/socket-helpers.c
index 5af4de513b..eecadf3a3c 100644
--- a/tests/unit/socket-helpers.c
+++ b/tests/unit/socket-helpers.c
@@ -154,3 +154,19 @@ int socket_check_protocol_support(bool *has_ipv4, bool *has_ipv6)
return 0;
}
+
+void socket_check_afunix_support(bool *has_afunix)
+{
+ int fd;
+
+ fd = socket(PF_UNIX, SOCK_STREAM, 0);
+ closesocket(fd);
+
+#ifdef _WIN32
+ *has_afunix = (fd != (int)INVALID_SOCKET);
+#else
+ *has_afunix = (fd >= 0);
+#endif
+
+ return;
+}
diff --git a/tests/unit/socket-helpers.h b/tests/unit/socket-helpers.h
index 512a004811..ed8477ceb3 100644
--- a/tests/unit/socket-helpers.h
+++ b/tests/unit/socket-helpers.h
@@ -32,4 +32,13 @@
*/
int socket_check_protocol_support(bool *has_ipv4, bool *has_ipv6);
+/*
+ * @has_afunix: set to true on return if unix socket support is available
+ *
+ * Check whether unix domain socket support is available for use.
+ * On success, @has_afunix will be set to indicate whether AF_UNIX protocol
+ * is available.
+ */
+void socket_check_afunix_support(bool *has_afunix);
+
#endif
diff --git a/tests/unit/test-io-channel-socket.c b/tests/unit/test-io-channel-socket.c
index 6713886d02..b36a5d972a 100644
--- a/tests/unit/test-io-channel-socket.c
+++ b/tests/unit/test-io-channel-socket.c
@@ -179,10 +179,12 @@ static void test_io_channel(bool async,
test_io_channel_setup_async(listen_addr, connect_addr,
&srv, &src, &dst);
+#ifndef _WIN32
g_assert(!passFD ||
qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS));
g_assert(!passFD ||
qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS));
+#endif
g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_SHUTDOWN));
g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_SHUTDOWN));
@@ -206,10 +208,12 @@ static void test_io_channel(bool async,
test_io_channel_setup_async(listen_addr, connect_addr,
&srv, &src, &dst);
+#ifndef _WIN32
g_assert(!passFD ||
qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS));
g_assert(!passFD ||
qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS));
+#endif
g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_SHUTDOWN));
g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_SHUTDOWN));
@@ -236,10 +240,12 @@ static void test_io_channel(bool async,
test_io_channel_setup_sync(listen_addr, connect_addr,
&srv, &src, &dst);
+#ifndef _WIN32
g_assert(!passFD ||
qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS));
g_assert(!passFD ||
qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS));
+#endif
g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_SHUTDOWN));
g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_SHUTDOWN));
@@ -263,10 +269,12 @@ static void test_io_channel(bool async,
test_io_channel_setup_sync(listen_addr, connect_addr,
&srv, &src, &dst);
+#ifndef _WIN32
g_assert(!passFD ||
qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS));
g_assert(!passFD ||
qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS));
+#endif
g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_SHUTDOWN));
g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_SHUTDOWN));
@@ -367,7 +375,6 @@ static void test_io_channel_ipv6_async(void)
}
-#ifndef _WIN32
static void test_io_channel_unix(bool async)
{
SocketAddress *listen_addr = g_new0(SocketAddress, 1);
@@ -398,6 +405,7 @@ static void test_io_channel_unix_async(void)
return test_io_channel_unix(true);
}
+#ifndef _WIN32
static void test_io_channel_unix_fd_pass(void)
{
SocketAddress *listen_addr = g_new0(SocketAddress, 1);
@@ -491,6 +499,7 @@ static void test_io_channel_unix_fd_pass(void)
}
g_free(fdrecv);
}
+#endif /* _WIN32 */
static void test_io_channel_unix_listen_cleanup(void)
{
@@ -522,9 +531,6 @@ static void test_io_channel_unix_listen_cleanup(void)
unlink(TEST_SOCKET);
}
-#endif /* _WIN32 */
-
-
static void test_io_channel_ipv4_fd(void)
{
QIOChannel *ioc;
@@ -555,7 +561,7 @@ static void test_io_channel_ipv4_fd(void)
int main(int argc, char **argv)
{
- bool has_ipv4, has_ipv6;
+ bool has_ipv4, has_ipv6, has_afunix;
module_call_init(MODULE_INIT_QOM);
qemu_init_main_loop(&error_abort);
@@ -588,16 +594,19 @@ int main(int argc, char **argv)
test_io_channel_ipv6_async);
}
+ socket_check_afunix_support(&has_afunix);
+ if (has_afunix) {
+ g_test_add_func("/io/channel/socket/unix-sync",
+ test_io_channel_unix_sync);
+ g_test_add_func("/io/channel/socket/unix-async",
+ test_io_channel_unix_async);
#ifndef _WIN32
- g_test_add_func("/io/channel/socket/unix-sync",
- test_io_channel_unix_sync);
- g_test_add_func("/io/channel/socket/unix-async",
- test_io_channel_unix_async);
- g_test_add_func("/io/channel/socket/unix-fd-pass",
- test_io_channel_unix_fd_pass);
- g_test_add_func("/io/channel/socket/unix-listen-cleanup",
- test_io_channel_unix_listen_cleanup);
-#endif /* _WIN32 */
+ g_test_add_func("/io/channel/socket/unix-fd-pass",
+ test_io_channel_unix_fd_pass);
+#endif
+ g_test_add_func("/io/channel/socket/unix-listen-cleanup",
+ test_io_channel_unix_listen_cleanup);
+ }
end:
return g_test_run();
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index 0e2298278f..83f4bd6fd2 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -880,8 +880,6 @@ static int vsock_parse(VsockSocketAddress *addr, const char *str,
}
#endif /* CONFIG_AF_VSOCK */
-#ifndef _WIN32
-
static bool saddr_is_abstract(UnixSocketAddress *saddr)
{
#ifdef CONFIG_LINUX
@@ -1054,25 +1052,6 @@ static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp)
return -1;
}
-#else
-
-static int unix_listen_saddr(UnixSocketAddress *saddr,
- int num,
- Error **errp)
-{
- error_setg(errp, "unix sockets are not available on windows");
- errno = ENOTSUP;
- return -1;
-}
-
-static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp)
-{
- error_setg(errp, "unix sockets are not available on windows");
- errno = ENOTSUP;
- return -1;
-}
-#endif
-
/* compatibility wrapper */
int unix_listen(const char *str, Error **errp)
{
@@ -1335,7 +1314,6 @@ socket_sockaddr_to_address_inet(struct sockaddr_storage *sa,
}
-#ifndef WIN32
static SocketAddress *
socket_sockaddr_to_address_unix(struct sockaddr_storage *sa,
socklen_t salen,
@@ -1362,7 +1340,6 @@ socket_sockaddr_to_address_unix(struct sockaddr_storage *sa,
addr->u.q_unix.path = g_strndup(su->sun_path, salen);
return addr;
}
-#endif /* WIN32 */
#ifdef CONFIG_AF_VSOCK
static SocketAddress *
@@ -1394,10 +1371,8 @@ socket_sockaddr_to_address(struct sockaddr_storage *sa,
case AF_INET6:
return socket_sockaddr_to_address_inet(sa, salen, errp);
-#ifndef WIN32
case AF_UNIX:
return socket_sockaddr_to_address_unix(sa, salen, errp);
-#endif /* WIN32 */
#ifdef CONFIG_AF_VSOCK
case AF_VSOCK: