[PULL 16/16] audio: split ctl_* functions into enable_* and volume_*

2019-09-23 Thread Gerd Hoffmann
From: Kővágó, Zoltán 

This way we no longer need vararg functions, improving compile time
error detection.  Also now it's possible to check actually what commands
are supported, without needing to manually update ctl_caps.

Signed-off-by: Kővágó, Zoltán 
Message-id: 
2b08b3773569c5be055d0a0fb2f29ff64e79f0f4.1568927990.git.dirty.ice...@gmail.com
Signed-off-by: Gerd Hoffmann 
---
 audio/audio_int.h  |  15 ++---
 audio/audio_template.h |   1 -
 audio/alsaaudio.c  |  62 
 audio/audio.c  |  45 +--
 audio/coreaudio.c  |  13 ++---
 audio/dsoundaudio.c|  50 +++-
 audio/noaudio.c|  14 ++---
 audio/ossaudio.c   |  79 ++---
 audio/paaudio.c| 127 -
 audio/sdlaudio.c   |  17 +-
 audio/spiceaudio.c | 102 ++---
 audio/wavaudio.c   |   7 +--
 12 files changed, 217 insertions(+), 315 deletions(-)

diff --git a/audio/audio_int.h b/audio/audio_int.h
index 778615ccafa4..22a703c13e1c 100644
--- a/audio/audio_int.h
+++ b/audio/audio_int.h
@@ -74,7 +74,6 @@ typedef struct HWVoiceOut {
 size_t samples;
 QLIST_HEAD (sw_out_listhead, SWVoiceOut) sw_head;
 QLIST_HEAD (sw_cap_listhead, SWVoiceCap) cap_head;
-int ctl_caps;
 struct audio_pcm_ops *pcm_ops;
 QLIST_ENTRY (HWVoiceOut) entries;
 } HWVoiceOut;
@@ -96,7 +95,6 @@ typedef struct HWVoiceIn {
 
 size_t samples;
 QLIST_HEAD (sw_in_listhead, SWVoiceIn) sw_head;
-int ctl_caps;
 struct audio_pcm_ops *pcm_ops;
 QLIST_ENTRY (HWVoiceIn) entries;
 } HWVoiceIn;
@@ -148,7 +146,6 @@ struct audio_driver {
 int max_voices_in;
 int voice_size_out;
 int voice_size_in;
-int ctl_caps;
 QLIST_ENTRY(audio_driver) next;
 };
 
@@ -168,14 +165,16 @@ struct audio_pcm_ops {
  * size may be smaller
  */
 size_t (*put_buffer_out)(HWVoiceOut *hw, void *buf, size_t size);
-int(*ctl_out) (HWVoiceOut *hw, int cmd, ...);
+void   (*enable_out)(HWVoiceOut *hw, bool enable);
+void   (*volume_out)(HWVoiceOut *hw, struct mixeng_volume *vol);
 
 int(*init_in) (HWVoiceIn *hw, audsettings *as, void *drv_opaque);
 void   (*fini_in) (HWVoiceIn *hw);
 size_t (*read)(HWVoiceIn *hw, void *buf, size_t size);
 void  *(*get_buffer_in)(HWVoiceIn *hw, size_t *size);
 void   (*put_buffer_in)(HWVoiceIn *hw, void *buf, size_t size);
-int(*ctl_in)  (HWVoiceIn *hw, int cmd, ...);
+void   (*enable_in)(HWVoiceIn *hw, bool enable);
+void   (*volume_in)(HWVoiceIn *hw, struct mixeng_volume *vol);
 };
 
 void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size);
@@ -251,12 +250,6 @@ void audio_rate_start(RateCtl *rate);
 size_t audio_rate_get_bytes(struct audio_pcm_info *info, RateCtl *rate,
 size_t bytes_avail);
 
-#define VOICE_ENABLE 1
-#define VOICE_DISABLE 2
-#define VOICE_VOLUME 3
-
-#define VOICE_VOLUME_CAP (1 << VOICE_VOLUME)
-
 static inline size_t audio_ring_dist(size_t dst, size_t src, size_t len)
 {
 return (dst >= src) ? (dst - src) : (len - src + dst);
diff --git a/audio/audio_template.h b/audio/audio_template.h
index 87c6d2d27102..235d1acbbebb 100644
--- a/audio/audio_template.h
+++ b/audio/audio_template.h
@@ -254,7 +254,6 @@ static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioState *s,
 
 hw->s = s;
 hw->pcm_ops = drv->pcm_ops;
-hw->ctl_caps = drv->ctl_caps;
 
 QLIST_INIT (&hw->sw_head);
 #ifdef DAC
diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c
index 19124d09d845..cfe42284a6aa 100644
--- a/audio/alsaaudio.c
+++ b/audio/alsaaudio.c
@@ -731,34 +731,28 @@ static int alsa_voice_ctl (snd_pcm_t *handle, const char 
*typ, int ctl)
 return 0;
 }
 
-static int alsa_ctl_out (HWVoiceOut *hw, int cmd, ...)
+static void alsa_enable_out(HWVoiceOut *hw, bool enable)
 {
 ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
 AudiodevAlsaPerDirectionOptions *apdo = alsa->dev->u.alsa.out;
 
-switch (cmd) {
-case VOICE_ENABLE:
-{
-bool poll_mode = apdo->try_poll;
+if (enable) {
+bool poll_mode = apdo->try_poll;
 
-ldebug ("enabling voice\n");
-if (poll_mode && alsa_poll_out (hw)) {
-poll_mode = 0;
-}
-hw->poll_mode = poll_mode;
-return alsa_voice_ctl (alsa->handle, "playback", 
VOICE_CTL_PREPARE);
+ldebug("enabling voice\n");
+if (poll_mode && alsa_poll_out(hw)) {
+poll_mode = 0;
 }
-
-case VOICE_DISABLE:
-ldebug ("disabling voice\n");
+hw->poll_mode = poll_mode;
+alsa_voice_ctl(alsa->handle, "playback", VOICE_CTL_PREPARE);
+} else {
+ldebug("disabling voice\n");
 if (hw->poll_mode) {
 hw->poll_mode = 0;
-alsa_fini_poll (&alsa->pollhlp);
+alsa_fini_poll(&alsa->pollhlp);
 }
-return alsa_voice_ctl (alsa->handle, "play

[PULL 08/16] ossaudio: port to the new audio backend api

2019-09-23 Thread Gerd Hoffmann
From: Kővágó, Zoltán 

Signed-off-by: Kővágó, Zoltán 
Message-id: 
22ab335146acd8099779583edcf6ed46de836bd6.1568927990.git.dirty.ice...@gmail.com
Signed-off-by: Gerd Hoffmann 
---
 audio/ossaudio.c | 288 +--
 1 file changed, 104 insertions(+), 184 deletions(-)

diff --git a/audio/ossaudio.c b/audio/ossaudio.c
index 169693368886..278251270691 100644
--- a/audio/ossaudio.c
+++ b/audio/ossaudio.c
@@ -40,19 +40,15 @@
 
 typedef struct OSSVoiceOut {
 HWVoiceOut hw;
-void *pcm_buf;
 int fd;
-int wpos;
 int nfrags;
 int fragsize;
 int mmapped;
-int pending;
 Audiodev *dev;
 } OSSVoiceOut;
 
 typedef struct OSSVoiceIn {
 HWVoiceIn hw;
-void *pcm_buf;
 int fd;
 int nfrags;
 int fragsize;
@@ -371,98 +367,87 @@ static int oss_open(int in, struct oss_params *req, 
audsettings *as,
 return -1;
 }
 
-static void oss_write_pending (OSSVoiceOut *oss)
+static size_t oss_get_available_bytes(OSSVoiceOut *oss)
 {
-HWVoiceOut *hw = &oss->hw;
+int err;
+struct count_info cntinfo;
+assert(oss->mmapped);
 
+err = ioctl(oss->fd, SNDCTL_DSP_GETOPTR, &cntinfo);
+if (err < 0) {
+oss_logerr(errno, "SNDCTL_DSP_GETOPTR failed\n");
+return 0;
+}
+
+return audio_ring_dist(cntinfo.ptr, oss->hw.pos_emul, oss->hw.size_emul);
+}
+
+static void *oss_get_buffer_out(HWVoiceOut *hw, size_t *size)
+{
+OSSVoiceOut *oss = (OSSVoiceOut *) hw;
+if (oss->mmapped) {
+*size = MIN(oss_get_available_bytes(oss), hw->size_emul - 
hw->pos_emul);
+return hw->buf_emul + hw->pos_emul;
+} else {
+return audio_generic_get_buffer_out(hw, size);
+}
+}
+
+static size_t oss_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size)
+{
+OSSVoiceOut *oss = (OSSVoiceOut *) hw;
 if (oss->mmapped) {
-return;
+assert(buf == hw->buf_emul + hw->pos_emul && size < hw->size_emul);
+
+hw->pos_emul = (hw->pos_emul + size) % hw->size_emul;
+return size;
+} else {
+return audio_generic_put_buffer_out(hw, buf, size);
+}
+}
+
+static size_t oss_write(HWVoiceOut *hw, void *buf, size_t len)
+{
+OSSVoiceOut *oss = (OSSVoiceOut *) hw;
+size_t pos;
+
+if (oss->mmapped) {
+size_t total_len;
+len = MIN(len, oss_get_available_bytes(oss));
+
+total_len = len;
+while (len) {
+size_t to_copy = MIN(len, hw->size_emul - hw->pos_emul);
+memcpy(hw->buf_emul + hw->pos_emul, buf, to_copy);
+
+hw->pos_emul = (hw->pos_emul + to_copy) % hw->pos_emul;
+buf += to_copy;
+len -= to_copy;
+}
+return total_len;
 }
 
-while (oss->pending) {
-int samples_written;
+pos = 0;
+while (len) {
 ssize_t bytes_written;
-int samples_till_end = hw->samples - oss->wpos;
-int samples_to_write = MIN (oss->pending, samples_till_end);
-int bytes_to_write = samples_to_write << hw->info.shift;
-void *pcm = advance (oss->pcm_buf, oss->wpos << hw->info.shift);
+void *pcm = advance(buf, pos);
 
-bytes_written = write (oss->fd, pcm, bytes_to_write);
+bytes_written = write(oss->fd, pcm, len);
 if (bytes_written < 0) {
 if (errno != EAGAIN) {
-oss_logerr (errno, "failed to write %d bytes\n",
-bytes_to_write);
+oss_logerr(errno, "failed to write %zu bytes\n",
+   len);
 }
-break;
-}
-
-if (bytes_written & hw->info.align) {
-dolog ("misaligned write asked for %d, but got %zd\n",
-   bytes_to_write, bytes_written);
-return;
+return pos;
 }
 
-samples_written = bytes_written >> hw->info.shift;
-oss->pending -= samples_written;
-oss->wpos = (oss->wpos + samples_written) % hw->samples;
-if (bytes_written - bytes_to_write) {
+pos += bytes_written;
+if (bytes_written < len) {
 break;
 }
+len -= bytes_written;
 }
-}
-
-static size_t oss_run_out(HWVoiceOut *hw, size_t live)
-{
-OSSVoiceOut *oss = (OSSVoiceOut *) hw;
-int err;
-size_t decr;
-struct audio_buf_info abinfo;
-struct count_info cntinfo;
-size_t bufsize;
-
-bufsize = hw->samples << hw->info.shift;
-
-if (oss->mmapped) {
-int bytes, pos;
-
-err = ioctl (oss->fd, SNDCTL_DSP_GETOPTR, &cntinfo);
-if (err < 0) {
-oss_logerr (errno, "SNDCTL_DSP_GETOPTR failed\n");
-return 0;
-}
-
-pos = hw->rpos << hw->info.shift;
-bytes = audio_ring_dist (cntinfo.ptr, pos, bufsize);
-decr = MIN (bytes >> hw->info.shift, live);
-}
-else {
-err = ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &abinfo);
-if (err < 0) {
-oss_logerr (errno, "SNDCTL_DSP

[PULL 09/16] paaudio: port to the new audio backend api

2019-09-23 Thread Gerd Hoffmann
From: Kővágó, Zoltán 

Signed-off-by: Kővágó, Zoltán 
Message-id: 
21fe8f2cf949039c8c40a0352590c593b104917d.1568927990.git.dirty.ice...@gmail.com
Signed-off-by: Gerd Hoffmann 
---
 configure|   5 -
 audio/audio_pt_int.h |  22 ---
 audio/audio_pt_int.c | 173 
 audio/paaudio.c  | 372 ++-
 audio/Makefile.objs  |   1 -
 5 files changed, 45 insertions(+), 528 deletions(-)
 delete mode 100644 audio/audio_pt_int.h
 delete mode 100644 audio/audio_pt_int.c

diff --git a/configure b/configure
index 30544f52e630..397bb476e196 100755
--- a/configure
+++ b/configure
@@ -297,7 +297,6 @@ host_cc="cc"
 libs_cpu=""
 libs_softmmu=""
 libs_tools=""
-audio_pt_int=""
 audio_win_int=""
 libs_qga=""
 debug_info="yes"
@@ -3388,7 +3387,6 @@ for drv in $audio_drv_list; do
 pa | try-pa)
 if $pkg_config libpulse --exists; then
 pulse_libs=$($pkg_config libpulse --libs)
-audio_pt_int="yes"
 if test "$drv" = "try-pa"; then
 audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-pa/pa/')
 fi
@@ -6611,9 +6609,6 @@ echo "PULSE_LIBS=$pulse_libs" >> $config_host_mak
 echo "COREAUDIO_LIBS=$coreaudio_libs" >> $config_host_mak
 echo "DSOUND_LIBS=$dsound_libs" >> $config_host_mak
 echo "OSS_LIBS=$oss_libs" >> $config_host_mak
-if test "$audio_pt_int" = "yes" ; then
-  echo "CONFIG_AUDIO_PT_INT=y" >> $config_host_mak
-fi
 if test "$audio_win_int" = "yes" ; then
   echo "CONFIG_AUDIO_WIN_INT=y" >> $config_host_mak
 fi
diff --git a/audio/audio_pt_int.h b/audio/audio_pt_int.h
deleted file mode 100644
index 4c0c15b9af94..
--- a/audio/audio_pt_int.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef QEMU_AUDIO_PT_INT_H
-#define QEMU_AUDIO_PT_INT_H
-
-#include 
-
-struct audio_pt {
-const char *drv;
-pthread_t thread;
-pthread_cond_t cond;
-pthread_mutex_t mutex;
-};
-
-int audio_pt_init (struct audio_pt *, void *(*) (void *), void *,
-   const char *, const char *);
-int audio_pt_fini (struct audio_pt *, const char *);
-int audio_pt_lock (struct audio_pt *, const char *);
-int audio_pt_unlock (struct audio_pt *, const char *);
-int audio_pt_wait (struct audio_pt *, const char *);
-int audio_pt_unlock_and_signal (struct audio_pt *, const char *);
-int audio_pt_join (struct audio_pt *, void **, const char *);
-
-#endif /* QEMU_AUDIO_PT_INT_H */
diff --git a/audio/audio_pt_int.c b/audio/audio_pt_int.c
deleted file mode 100644
index 9f9d44ad4a63..
--- a/audio/audio_pt_int.c
+++ /dev/null
@@ -1,173 +0,0 @@
-#include "qemu/osdep.h"
-#include "audio.h"
-
-#define AUDIO_CAP "audio-pt"
-
-#include "audio_int.h"
-#include "audio_pt_int.h"
-
-static void GCC_FMT_ATTR(3, 4) logerr (struct audio_pt *pt, int err,
-   const char *fmt, ...)
-{
-va_list ap;
-
-va_start (ap, fmt);
-AUD_vlog (pt->drv, fmt, ap);
-va_end (ap);
-
-AUD_log (NULL, "\n");
-AUD_log (pt->drv, "Reason: %s\n", strerror (err));
-}
-
-int audio_pt_init (struct audio_pt *p, void *(*func) (void *),
-   void *opaque, const char *drv, const char *cap)
-{
-int err, err2;
-const char *efunc;
-sigset_t set, old_set;
-
-p->drv = drv;
-
-err = sigfillset (&set);
-if (err) {
-logerr(p, errno, "%s(%s): sigfillset failed", cap, __func__);
-return -1;
-}
-
-err = pthread_mutex_init (&p->mutex, NULL);
-if (err) {
-efunc = "pthread_mutex_init";
-goto err0;
-}
-
-err = pthread_cond_init (&p->cond, NULL);
-if (err) {
-efunc = "pthread_cond_init";
-goto err1;
-}
-
-err = pthread_sigmask (SIG_BLOCK, &set, &old_set);
-if (err) {
-efunc = "pthread_sigmask";
-goto err2;
-}
-
-err = pthread_create (&p->thread, NULL, func, opaque);
-
-err2 = pthread_sigmask (SIG_SETMASK, &old_set, NULL);
-if (err2) {
-logerr(p, err2, "%s(%s): pthread_sigmask (restore) failed",
-   cap, __func__);
-/* We have failed to restore original signal mask, all bets are off,
-   so terminate the process */
-exit (EXIT_FAILURE);
-}
-
-if (err) {
-efunc = "pthread_create";
-goto err2;
-}
-
-return 0;
-
- err2:
-err2 = pthread_cond_destroy (&p->cond);
-if (err2) {
-logerr(p, err2, "%s(%s): pthread_cond_destroy failed", cap, __func__);
-}
-
- err1:
-err2 = pthread_mutex_destroy (&p->mutex);
-if (err2) {
-logerr(p, err2, "%s(%s): pthread_mutex_destroy failed", cap, __func__);
-}
-
- err0:
-logerr(p, err, "%s(%s): %s failed", cap, __func__, efunc);
-return -1;
-}
-
-int audio_pt_fini (struct audio_pt *p, const char *cap)
-{
-int err, ret = 0;
-
-err = pthread_cond_destroy (&p->cond);
-if (err) {
-logerr(p, err, "%s(%s): pthread_cond_destroy failed", cap, __func__);
-ret = -1;
-}
-
-err = pthread_mutex_destroy (&p-

[PULL 15/16] audio: common rate control code for timer based outputs

2019-09-23 Thread Gerd Hoffmann
From: Kővágó, Zoltán 

This commit removes the ad-hoc rate-limiting code from noaudio and
wavaudio, and replaces them with a (slightly modified) code from
spiceaudio.  This way multiple write calls (for example when the
circular buffer wraps around) do not cause problems.

Signed-off-by: Kővágó, Zoltán 
Message-id: 
fd0fe5b95b13fa26d09ae77a72f99d0ea411de14.1568927990.git.dirty.ice...@gmail.com
Signed-off-by: Gerd Hoffmann 
---
 audio/audio_int.h  |  9 
 audio/audio.c  | 30 +++
 audio/noaudio.c| 49 
 audio/spiceaudio.c | 51 --
 audio/wavaudio.c   | 21 +--
 5 files changed, 79 insertions(+), 81 deletions(-)

diff --git a/audio/audio_int.h b/audio/audio_int.h
index 20021df9e8be..778615ccafa4 100644
--- a/audio/audio_int.h
+++ b/audio/audio_int.h
@@ -242,6 +242,15 @@ void *audio_calloc (const char *funcname, int nmemb, 
size_t size);
 
 void audio_run(AudioState *s, const char *msg);
 
+typedef struct RateCtl {
+int64_t start_ticks;
+int64_t bytes_sent;
+} RateCtl;
+
+void audio_rate_start(RateCtl *rate);
+size_t audio_rate_get_bytes(struct audio_pcm_info *info, RateCtl *rate,
+size_t bytes_avail);
+
 #define VOICE_ENABLE 1
 #define VOICE_DISABLE 2
 #define VOICE_VOLUME 3
diff --git a/audio/audio.c b/audio/audio.c
index ba07fb77dd4f..fab1e3571838 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -2051,3 +2051,33 @@ const char *audio_get_id(QEMUSoundCard *card)
 return "";
 }
 }
+
+void audio_rate_start(RateCtl *rate)
+{
+memset(rate, 0, sizeof(RateCtl));
+rate->start_ticks = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+}
+
+size_t audio_rate_get_bytes(struct audio_pcm_info *info, RateCtl *rate,
+size_t bytes_avail)
+{
+int64_t now;
+int64_t ticks;
+int64_t bytes;
+int64_t samples;
+size_t ret;
+
+now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ticks = now - rate->start_ticks;
+bytes = muldiv64(ticks, info->bytes_per_second, NANOSECONDS_PER_SECOND);
+samples = (bytes - rate->bytes_sent) >> info->shift;
+if (samples < 0 || samples > 65536) {
+AUD_log(NULL, "Resetting rate control (%" PRId64 " samples)\n", 
samples);
+audio_rate_start(rate);
+samples = 0;
+}
+
+ret = MIN(samples << info->shift, bytes_avail);
+rate->bytes_sent += ret;
+return ret;
+}
diff --git a/audio/noaudio.c b/audio/noaudio.c
index b054fd225b66..9f1cc67df942 100644
--- a/audio/noaudio.c
+++ b/audio/noaudio.c
@@ -33,33 +33,27 @@
 
 typedef struct NoVoiceOut {
 HWVoiceOut hw;
-int64_t old_ticks;
+RateCtl rate;
 } NoVoiceOut;
 
 typedef struct NoVoiceIn {
 HWVoiceIn hw;
-int64_t old_ticks;
+RateCtl rate;
 } NoVoiceIn;
 
 static size_t no_write(HWVoiceOut *hw, void *buf, size_t len)
 {
 NoVoiceOut *no = (NoVoiceOut *) hw;
-int64_t now;
-int64_t ticks;
-int64_t bytes;
-
-now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
-ticks = now - no->old_ticks;
-bytes = muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND);
-
-no->old_ticks = now;
-return MIN(len, bytes);
+return audio_rate_get_bytes(&hw->info, &no->rate, len);
 }
 
 static int no_init_out(HWVoiceOut *hw, struct audsettings *as, void 
*drv_opaque)
 {
+NoVoiceOut *no = (NoVoiceOut *) hw;
+
 audio_pcm_init_info (&hw->info, as);
 hw->samples = 1024;
+audio_rate_start(&no->rate);
 return 0;
 }
 
@@ -70,15 +64,21 @@ static void no_fini_out (HWVoiceOut *hw)
 
 static int no_ctl_out (HWVoiceOut *hw, int cmd, ...)
 {
-(void) hw;
-(void) cmd;
+NoVoiceOut *no = (NoVoiceOut *) hw;
+
+if (cmd == VOICE_ENABLE) {
+audio_rate_start(&no->rate);
+}
 return 0;
 }
 
 static int no_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
 {
+NoVoiceIn *no = (NoVoiceIn *) hw;
+
 audio_pcm_init_info (&hw->info, as);
 hw->samples = 1024;
+audio_rate_start(&no->rate);
 return 0;
 }
 
@@ -89,25 +89,20 @@ static void no_fini_in (HWVoiceIn *hw)
 
 static size_t no_read(HWVoiceIn *hw, void *buf, size_t size)
 {
-size_t to_clear;
 NoVoiceIn *no = (NoVoiceIn *) hw;
+int64_t bytes = audio_rate_get_bytes(&hw->info, &no->rate, size);
 
-int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
-int64_t ticks = now - no->old_ticks;
-int64_t bytes =
-muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND);
-
-no->old_ticks = now;
-to_clear = MIN(bytes, size);
-
-audio_pcm_info_clear_buf(&hw->info, buf, to_clear >> hw->info.shift);
-return to_clear;
+audio_pcm_info_clear_buf(&hw->info, buf, bytes >> hw->info.shift);
+return bytes;
 }
 
 static int no_ctl_in (HWVoiceIn *hw, int cmd, ...)
 {
-(void) hw;
-(void) cmd;
+NoVoiceIn *no = (NoVoiceIn *) hw;
+
+if (cmd == VOICE_ENABLE) {
+audio_rate_start(&no-

[PULL 13/16] audio: remove remains of the old backend api

2019-09-23 Thread Gerd Hoffmann
From: Kővágó, Zoltán 

Signed-off-by: Kővágó, Zoltán 
Message-id: 
497decab6d0f0fb9529bea63ec7ce0bd7b553038.1568927990.git.dirty.ice...@gmail.com
Signed-off-by: Gerd Hoffmann 
---
 audio/audio_int.h |  7 ---
 audio/audio.c | 42 ++
 2 files changed, 6 insertions(+), 43 deletions(-)

diff --git a/audio/audio_int.h b/audio/audio_int.h
index 8fb1ca8a8d0f..c76d7c39e84c 100644
--- a/audio/audio_int.h
+++ b/audio/audio_int.h
@@ -153,7 +153,6 @@ struct audio_driver {
 struct audio_pcm_ops {
 int(*init_out)(HWVoiceOut *hw, audsettings *as, void *drv_opaque);
 void   (*fini_out)(HWVoiceOut *hw);
-size_t (*run_out)(HWVoiceOut *hw, size_t live);
 size_t (*write)   (HWVoiceOut *hw, void *buf, size_t size);
 /*
  * get a buffer that after later can be passed to put_buffer_out; optional
@@ -171,7 +170,6 @@ struct audio_pcm_ops {
 
 int(*init_in) (HWVoiceIn *hw, audsettings *as, void *drv_opaque);
 void   (*fini_in) (HWVoiceIn *hw);
-size_t (*run_in)(HWVoiceIn *hw);
 size_t (*read)(HWVoiceIn *hw, void *buf, size_t size);
 void  *(*get_buffer_in)(HWVoiceIn *hw, size_t *size);
 void   (*put_buffer_in)(HWVoiceIn *hw, void *buf, size_t size);
@@ -237,11 +235,6 @@ audio_driver *audio_driver_lookup(const char *name);
 void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as);
 void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int 
len);
 
-size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw);
-
-size_t audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf,
- size_t live, size_t pending);
-
 int audio_bug (const char *funcname, int cond);
 void *audio_calloc (const char *funcname, int nmemb, size_t size);
 
diff --git a/audio/audio.c b/audio/audio.c
index e29a1e15eb30..435bcf20c139 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -541,7 +541,7 @@ static size_t audio_pcm_hw_find_min_in (HWVoiceIn *hw)
 return m;
 }
 
-size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw)
+static size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw)
 {
 size_t live = hw->total_samples_captured - audio_pcm_hw_find_min_in (hw);
 if (audio_bug(__func__, live > hw->samples)) {
@@ -551,29 +551,7 @@ size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw)
 return live;
 }
 
-size_t audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf,
- size_t live, size_t pending)
-{
-size_t left = hw->samples - pending;
-size_t len = MIN (left, live);
-size_t clipped = 0;
-
-while (len) {
-struct st_sample *src = hw->mix_buf + hw->rpos;
-uint8_t *dst = advance (pcm_buf, hw->rpos << hw->info.shift);
-size_t samples_till_end_of_buf = hw->samples - hw->rpos;
-size_t samples_to_clip = MIN (len, samples_till_end_of_buf);
-
-hw->clip (dst, src, samples_to_clip);
-
-hw->rpos = (hw->rpos + samples_to_clip) % hw->samples;
-len -= samples_to_clip;
-clipped += samples_to_clip;
-}
-return clipped;
-}
-
-static void audio_pcm_hw_clip_out2(HWVoiceOut *hw, void *pcm_buf, size_t len)
+static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, size_t len)
 {
 size_t clipped = 0;
 size_t pos = hw->rpos;
@@ -1083,7 +1061,7 @@ static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t 
live)
 }
 
 decr = MIN(size >> hw->info.shift, live);
-audio_pcm_hw_clip_out2(hw, buf, decr);
+audio_pcm_hw_clip_out(hw, buf, decr);
 proc = hw->pcm_ops->put_buffer_out(hw, buf, decr << hw->info.shift) >>
 hw->info.shift;
 
@@ -1146,11 +1124,7 @@ static void audio_run_out (AudioState *s)
 }
 
 prev_rpos = hw->rpos;
-if (hw->pcm_ops->run_out) {
-played = hw->pcm_ops->run_out(hw, live);
-} else {
-played = audio_pcm_hw_run_out(hw, live);
-}
+played = audio_pcm_hw_run_out(hw, live);
 replay_audio_out(&played);
 if (audio_bug(__func__, hw->rpos >= hw->samples)) {
 dolog("hw->rpos=%zu hw->samples=%zu played=%zu\n",
@@ -1247,12 +1221,8 @@ static void audio_run_in (AudioState *s)
 size_t captured = 0, min;
 
 if (replay_mode != REPLAY_MODE_PLAY) {
-if (hw->pcm_ops->run_in) {
-captured = hw->pcm_ops->run_in(hw);
-} else {
-captured = audio_pcm_hw_run_in(
-hw, hw->samples - audio_pcm_hw_get_live_in(hw));
-}
+captured = audio_pcm_hw_run_in(
+hw, hw->samples - audio_pcm_hw_get_live_in(hw));
 }
 replay_audio_in(&captured, hw->conv_buf, &hw->wpos, hw->samples);
 
-- 
2.18.1




[PULL 11/16] spiceaudio: port to the new audio backend api

2019-09-23 Thread Gerd Hoffmann
From: Kővágó, Zoltán 

Signed-off-by: Kővágó, Zoltán 
Message-id: 
4d3356df9ccbffee2f710b93d456443c81e3f011.1568927990.git.dirty.ice...@gmail.com
Signed-off-by: Gerd Hoffmann 
---
 audio/spiceaudio.c | 116 -
 1 file changed, 42 insertions(+), 74 deletions(-)

diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c
index 26873c7f22a5..ff4e4dcbb022 100644
--- a/audio/spiceaudio.c
+++ b/audio/spiceaudio.c
@@ -51,7 +51,7 @@ typedef struct SpiceVoiceOut {
 SpiceRateCtl  rate;
 int   active;
 uint32_t  *frame;
-uint32_t  *fpos;
+uint32_t  fpos;
 uint32_t  fsize;
 } SpiceVoiceOut;
 
@@ -60,7 +60,6 @@ typedef struct SpiceVoiceIn {
 SpiceRecordInstance   sin;
 SpiceRateCtl  rate;
 int   active;
-uint32_t  samples[LINE_IN_SAMPLES];
 } SpiceVoiceIn;
 
 static const SpicePlaybackInterface playback_sif = {
@@ -152,44 +151,40 @@ static void line_out_fini (HWVoiceOut *hw)
 spice_server_remove_interface (&out->sin.base);
 }
 
-static size_t line_out_run (HWVoiceOut *hw, size_t live)
+static void *line_out_get_buffer(HWVoiceOut *hw, size_t *size)
 {
-SpiceVoiceOut *out = container_of (hw, SpiceVoiceOut, hw);
-size_t rpos, decr;
-size_t samples;
+SpiceVoiceOut *out = container_of(hw, SpiceVoiceOut, hw);
+size_t decr;
 
-if (!live) {
-return 0;
+if (!out->frame) {
+spice_server_playback_get_buffer(&out->sin, &out->frame, &out->fsize);
+out->fpos = 0;
 }
 
-decr = rate_get_samples (&hw->info, &out->rate);
-decr = MIN (live, decr);
+if (out->frame) {
+decr = rate_get_samples(&hw->info, &out->rate);
+decr = MIN(out->fsize - out->fpos, decr);
 
-samples = decr;
-rpos = hw->rpos;
-while (samples) {
-int left_till_end_samples = hw->samples - rpos;
-int len = MIN (samples, left_till_end_samples);
+*size = decr << hw->info.shift;
+} else {
+rate_start(&out->rate);
+}
+return out->frame + out->fpos;
+}
+
+static size_t line_out_put_buffer(HWVoiceOut *hw, void *buf, size_t size)
+{
+SpiceVoiceOut *out = container_of(hw, SpiceVoiceOut, hw);
 
-if (!out->frame) {
-spice_server_playback_get_buffer (&out->sin, &out->frame, 
&out->fsize);
-out->fpos = out->frame;
-}
-if (out->frame) {
-len = MIN (len, out->fsize);
-hw->clip (out->fpos, hw->mix_buf + rpos, len);
-out->fsize -= len;
-out->fpos  += len;
-if (out->fsize == 0) {
-spice_server_playback_put_samples (&out->sin, out->frame);
-out->frame = out->fpos = NULL;
-}
-}
-rpos = (rpos + len) % hw->samples;
-samples -= len;
+assert(buf == out->frame + out->fpos && out->fpos <= out->fsize);
+out->fpos += size >> 2;
+
+if (out->fpos == out->fsize) { /* buffer full */
+spice_server_playback_put_samples(&out->sin, out->frame);
+out->frame = NULL;
 }
-hw->rpos = rpos;
-return decr;
+
+return size;
 }
 
 static int line_out_ctl (HWVoiceOut *hw, int cmd, ...)
@@ -211,9 +206,9 @@ static int line_out_ctl (HWVoiceOut *hw, int cmd, ...)
 }
 out->active = 0;
 if (out->frame) {
-memset (out->fpos, 0, out->fsize << 2);
+memset(out->frame + out->fpos, 0, (out->fsize - out->fpos) << 2);
 spice_server_playback_put_samples (&out->sin, out->frame);
-out->frame = out->fpos = NULL;
+out->frame = NULL;
 }
 spice_server_playback_stop (&out->sin);
 break;
@@ -275,49 +270,20 @@ static void line_in_fini (HWVoiceIn *hw)
 spice_server_remove_interface (&in->sin.base);
 }
 
-static size_t line_in_run(HWVoiceIn *hw)
+static size_t line_in_read(HWVoiceIn *hw, void *buf, size_t len)
 {
 SpiceVoiceIn *in = container_of (hw, SpiceVoiceIn, hw);
-size_t num_samples;
-int ready;
-size_t len[2];
-uint64_t delta_samp;
-const uint32_t *samples;
+uint64_t delta_samp = rate_get_samples(&hw->info, &in->rate);
+uint64_t to_read = MIN(len >> 2, delta_samp);
+size_t ready = spice_server_record_get_samples(&in->sin, buf, to_read);
 
-if (!(num_samples = hw->samples - audio_pcm_hw_get_live_in (hw))) {
-return 0;
-}
-
-delta_samp = rate_get_samples (&hw->info, &in->rate);
-num_samples = MIN (num_samples, delta_samp);
-
-ready = spice_server_record_get_samples (&in->sin, in->samples, 
num_samples);
-samples = in->samples;
+/* XXX: do we need this? */
 if (ready == 0) {
-static const uint32_t silence[LINE_IN_SAMPLES];
-samples = silence;
-ready = LINE_IN_SAMPLES;
+memset(buf, 0, to_read << 2);
+ready = to_read;
 }
 
-num_samples = MIN (ready, num_samples);
-
-

[PULL 06/16] dsoundaudio: port to the new audio backend api

2019-09-23 Thread Gerd Hoffmann
From: Kővágó, Zoltán 

Signed-off-by: Kővágó, Zoltán 
Message-id: 
2ca925ab551ea832c930fc2db213a9e73d8dab7f.1568927990.git.dirty.ice...@gmail.com
Signed-off-by: Gerd Hoffmann 
---
 audio/dsound_template.h |  47 +++---
 audio/dsoundaudio.c | 329 ++--
 2 files changed, 103 insertions(+), 273 deletions(-)

diff --git a/audio/dsound_template.h b/audio/dsound_template.h
index 8ece870c9ef7..9f10b688df57 100644
--- a/audio/dsound_template.h
+++ b/audio/dsound_template.h
@@ -29,6 +29,8 @@
 #define BUFPTR LPDIRECTSOUNDCAPTUREBUFFER
 #define FIELD dsound_capture_buffer
 #define FIELD2 dsound_capture
+#define HWVOICE HWVoiceIn
+#define DSOUNDVOICE DSoundVoiceIn
 #else
 #define NAME "playback buffer"
 #define NAME2 "DirectSound"
@@ -37,6 +39,8 @@
 #define BUFPTR LPDIRECTSOUNDBUFFER
 #define FIELD dsound_buffer
 #define FIELD2 dsound
+#define HWVOICE HWVoiceOut
+#define DSOUNDVOICE DSoundVoiceOut
 #endif
 
 static int glue (dsound_unlock_, TYPE) (
@@ -72,8 +76,6 @@ static int glue (dsound_lock_, TYPE) (
 )
 {
 HRESULT hr;
-LPVOID p1 = NULL, p2 = NULL;
-DWORD blen1 = 0, blen2 = 0;
 DWORD flag;
 
 #ifdef DSBTYPE_IN
@@ -81,7 +83,7 @@ static int glue (dsound_lock_, TYPE) (
 #else
 flag = entire ? DSBLOCK_ENTIREBUFFER : 0;
 #endif
-hr = glue(IFACE, _Lock)(buf, pos, len, &p1, &blen1, &p2, &blen2, flag);
+hr = glue(IFACE, _Lock)(buf, pos, len, p1p, blen1p, p2p, blen2p, flag);
 
 if (FAILED (hr)) {
 #ifndef DSBTYPE_IN
@@ -96,34 +98,34 @@ static int glue (dsound_lock_, TYPE) (
 goto fail;
 }
 
-if ((p1 && (blen1 & info->align)) || (p2 && (blen2 & info->align))) {
-dolog ("DirectSound returned misaligned buffer %ld %ld\n",
-   blen1, blen2);
-glue (dsound_unlock_, TYPE) (buf, p1, p2, blen1, blen2);
+if ((p1p && *p1p && (*blen1p & info->align)) ||
+(p2p && *p2p && (*blen2p & info->align))) {
+dolog("DirectSound returned misaligned buffer %ld %ld\n",
+  *blen1p, *blen2p);
+glue(dsound_unlock_, TYPE)(buf, *p1p, p2p ? *p2p : NULL, *blen1p,
+   blen2p ? *blen2p : 0);
 goto fail;
 }
 
-if (!p1 && blen1) {
-dolog ("warning: !p1 && blen1=%ld\n", blen1);
-blen1 = 0;
+if (p1p && !*p1p && *blen1p) {
+dolog("warning: !p1 && blen1=%ld\n", *blen1p);
+*blen1p = 0;
 }
 
-if (!p2 && blen2) {
-dolog ("warning: !p2 && blen2=%ld\n", blen2);
-blen2 = 0;
+if (p2p && !*p2p && *blen2p) {
+dolog("warning: !p2 && blen2=%ld\n", *blen2p);
+*blen2p = 0;
 }
 
-*p1p = p1;
-*p2p = p2;
-*blen1p = blen1;
-*blen2p = blen2;
 return 0;
 
  fail:
 *p1p = NULL - 1;
-*p2p = NULL - 1;
 *blen1p = -1;
-*blen2p = -1;
+if (p2p) {
+*p2p = NULL - 1;
+*blen2p = -1;
+}
 return -1;
 }
 
@@ -242,7 +244,6 @@ static int dsound_init_out(HWVoiceOut *hw, struct 
audsettings *as,
 goto fail0;
 }
 
-ds->first_time = 1;
 obt_as.endianness = 0;
 audio_pcm_init_info (&hw->info, &obt_as);
 
@@ -252,15 +253,13 @@ static int dsound_init_out(HWVoiceOut *hw, struct 
audsettings *as,
 bc.dwBufferBytes, hw->info.align + 1
 );
 }
+hw->size_emul = bc.dwBufferBytes;
 hw->samples = bc.dwBufferBytes >> hw->info.shift;
 ds->s = s;
 
 #ifdef DEBUG_DSOUND
 dolog ("caps %ld, desc %ld\n",
bc.dwBufferBytes, bd.dwBufferBytes);
-
-dolog ("bufsize %d, freq %d, chan %d, fmt %d\n",
-   hw->bufsize, settings.freq, settings.nchannels, settings.fmt);
 #endif
 return 0;
 
@@ -276,3 +275,5 @@ static int dsound_init_out(HWVoiceOut *hw, struct 
audsettings *as,
 #undef BUFPTR
 #undef FIELD
 #undef FIELD2
+#undef HWVOICE
+#undef DSOUNDVOICE
diff --git a/audio/dsoundaudio.c b/audio/dsoundaudio.c
index 2fc118b795d0..9960247814c7 100644
--- a/audio/dsoundaudio.c
+++ b/audio/dsoundaudio.c
@@ -53,19 +53,11 @@ typedef struct {
 typedef struct {
 HWVoiceOut hw;
 LPDIRECTSOUNDBUFFER dsound_buffer;
-DWORD old_pos;
-int first_time;
 dsound *s;
-#ifdef DEBUG_DSOUND
-DWORD old_ppos;
-DWORD played;
-DWORD mixed;
-#endif
 } DSoundVoiceOut;
 
 typedef struct {
 HWVoiceIn hw;
-int first_time;
 LPDIRECTSOUNDCAPTUREBUFFER dsound_capture_buffer;
 dsound *s;
 } DSoundVoiceIn;
@@ -243,11 +235,6 @@ static void GCC_FMT_ATTR (3, 4) dsound_logerr2 (
 dsound_log_hresult (hr);
 }
 
-static uint64_t usecs_to_bytes(struct audio_pcm_info *info, uint32_t usecs)
-{
-return muldiv64(usecs, info->bytes_per_second, 100);
-}
-
 #ifdef DEBUG_DSOUND
 static void print_wave_format (WAVEFORMATEX *wfx)
 {
@@ -312,33 +299,6 @@ static int dsound_get_status_in 
(LPDIRECTSOUNDCAPTUREBUFFER dscb,
 return 0;
 }
 
-static void dsound_write_sample (HWVoiceOut *hw, uint8_t *dst, int dst_len)
-{
-int src_len1 = dst_len;
-int src_len2 = 0;
-int pos = h

[PULL 10/16] sdlaudio: port to the new audio backend api

2019-09-23 Thread Gerd Hoffmann
From: Kővágó, Zoltán 

Signed-off-by: Kővágó, Zoltán 
Message-id: 
ac1722a03fb1b530c2081f46585ce7fa80ebef6c.1568927990.git.dirty.ice...@gmail.com
Signed-off-by: Gerd Hoffmann 
---
 audio/sdlaudio.c | 87 +++-
 1 file changed, 42 insertions(+), 45 deletions(-)

diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c
index 14b11f033521..f7ac8cd10188 100644
--- a/audio/sdlaudio.c
+++ b/audio/sdlaudio.c
@@ -41,8 +41,6 @@
 
 typedef struct SDLVoiceOut {
 HWVoiceOut hw;
-size_t live;
-size_t decr;
 } SDLVoiceOut;
 
 static struct SDLAudioState {
@@ -184,62 +182,59 @@ static void sdl_callback (void *opaque, Uint8 *buf, int 
len)
 SDLVoiceOut *sdl = opaque;
 SDLAudioState *s = &glob_sdl;
 HWVoiceOut *hw = &sdl->hw;
-size_t samples = len >> hw->info.shift;
-size_t to_mix, decr;
 
-if (s->exit || !sdl->live) {
+if (s->exit) {
 return;
 }
 
 /* dolog ("in callback samples=%zu live=%zu\n", samples, sdl->live); */
 
-to_mix = MIN(samples, sdl->live);
-decr = to_mix;
-while (to_mix) {
-size_t chunk = MIN(to_mix, hw->samples - hw->rpos);
-struct st_sample *src = hw->mix_buf + hw->rpos;
-
-/* dolog ("in callback to_mix %zu, chunk %zu\n", to_mix, chunk); */
-hw->clip(buf, src, chunk);
-hw->rpos = (hw->rpos + chunk) % hw->samples;
-to_mix -= chunk;
-buf += chunk << hw->info.shift;
+while (hw->pending_emul && len) {
+size_t write_len;
+ssize_t start = ((ssize_t) hw->pos_emul) - hw->pending_emul;
+if (start < 0) {
+start += hw->size_emul;
+}
+assert(start >= 0 && start < hw->size_emul);
+
+write_len = MIN(MIN(hw->pending_emul, len),
+hw->size_emul - start);
+
+memcpy(buf, hw->buf_emul + start, write_len);
+hw->pending_emul -= write_len;
+len -= write_len;
+buf += write_len;
 }
-samples -= decr;
-sdl->live -= decr;
-sdl->decr += decr;
-
-/* dolog ("done len=%zu\n", len); */
 
-/* SDL2 does not clear the remaining buffer for us, so do it on our own */
-if (samples) {
-memset(buf, 0, samples << hw->info.shift);
+/* clear remaining buffer that we couldn't fill with data */
+if (len) {
+memset(buf, 0, len);
 }
 }
 
-static size_t sdl_run_out(HWVoiceOut *hw, size_t live)
-{
-size_t decr;
-SDLVoiceOut *sdl = (SDLVoiceOut *) hw;
-
-SDL_LockAudio();
-
-if (sdl->decr > live) {
-ldebug ("sdl->decr %d live %d sdl->live %d\n",
-sdl->decr,
-live,
-sdl->live);
+#define SDL_WRAPPER_FUNC(name, ret_type, args_decl, args, fail, unlock) \
+static ret_type glue(sdl_, name)args_decl   \
+{   \
+ret_type ret;   \
+\
+SDL_LockAudio();\
+\
+ret = glue(audio_generic_, name)args;   \
+\
+SDL_UnlockAudio();  \
+return ret; \
 }
 
-decr = MIN (sdl->decr, live);
-sdl->decr -= decr;
+SDL_WRAPPER_FUNC(get_buffer_out, void *, (HWVoiceOut *hw, size_t *size),
+ (hw, size), *size = 0, sdl_unlock)
+SDL_WRAPPER_FUNC(put_buffer_out_nowrite, size_t,
+ (HWVoiceOut *hw, void *buf, size_t size), (hw, buf, size),
+ /*nothing*/, sdl_unlock_and_post)
+SDL_WRAPPER_FUNC(write, size_t,
+ (HWVoiceOut *hw, void *buf, size_t size), (hw, buf, size),
+ /*nothing*/, sdl_unlock_and_post)
 
-sdl->live = live;
-
-SDL_UnlockAudio();
-
-return decr;
-}
+#undef SDL_WRAPPER_FUNC
 
 static void sdl_fini_out (HWVoiceOut *hw)
 {
@@ -336,7 +331,9 @@ static void sdl_audio_fini (void *opaque)
 static struct audio_pcm_ops sdl_pcm_ops = {
 .init_out = sdl_init_out,
 .fini_out = sdl_fini_out,
-.run_out  = sdl_run_out,
+.write= sdl_write,
+.get_buffer_out = sdl_get_buffer_out,
+.put_buffer_out = sdl_put_buffer_out_nowrite,
 .ctl_out  = sdl_ctl_out,
 };
 
-- 
2.18.1




[PULL 12/16] wavaudio: port to the new audio backend api

2019-09-23 Thread Gerd Hoffmann
From: Kővágó, Zoltán 

Signed-off-by: Kővágó, Zoltán 
Message-id: 
eede77aeb9c17b379948b0b6d2ac10f45d74fa62.1568927990.git.dirty.ice...@gmail.com
Signed-off-by: Gerd Hoffmann 
---
 audio/wavaudio.c | 54 
 1 file changed, 9 insertions(+), 45 deletions(-)

diff --git a/audio/wavaudio.c b/audio/wavaudio.c
index b6eeeb4e26ef..78af2f1338d2 100644
--- a/audio/wavaudio.c
+++ b/audio/wavaudio.c
@@ -36,52 +36,28 @@ typedef struct WAVVoiceOut {
 HWVoiceOut hw;
 FILE *f;
 int64_t old_ticks;
-void *pcm_buf;
 int total_samples;
 } WAVVoiceOut;
 
-static size_t wav_run_out(HWVoiceOut *hw, size_t live)
+static size_t wav_write_out(HWVoiceOut *hw, void *buf, size_t len)
 {
 WAVVoiceOut *wav = (WAVVoiceOut *) hw;
-size_t rpos, decr, samples;
-uint8_t *dst;
-struct st_sample *src;
 int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
 int64_t ticks = now - wav->old_ticks;
 int64_t bytes =
 muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND);
 
-if (bytes > INT_MAX) {
-samples = INT_MAX >> hw->info.shift;
-}
-else {
-samples = bytes >> hw->info.shift;
-}
-
+bytes = MIN(bytes, len);
+bytes = bytes >> hw->info.shift << hw->info.shift;
 wav->old_ticks = now;
-decr = MIN (live, samples);
-samples = decr;
-rpos = hw->rpos;
-while (samples) {
-int left_till_end_samples = hw->samples - rpos;
-int convert_samples = MIN (samples, left_till_end_samples);
 
-src = hw->mix_buf + rpos;
-dst = advance (wav->pcm_buf, rpos << hw->info.shift);
-
-hw->clip (dst, src, convert_samples);
-if (fwrite (dst, convert_samples << hw->info.shift, 1, wav->f) != 1) {
-dolog ("wav_run_out: fwrite of %d bytes failed\nReaons: %s\n",
-   convert_samples << hw->info.shift, strerror (errno));
-}
-
-rpos = (rpos + convert_samples) % hw->samples;
-samples -= convert_samples;
-wav->total_samples += convert_samples;
+if (bytes && fwrite(buf, bytes, 1, wav->f) != 1) {
+dolog("wav_write_out: fwrite of %" PRId64 " bytes failed\nReason: 
%s\n",
+  bytes, strerror(errno));
 }
 
-hw->rpos = rpos;
-return decr;
+wav->total_samples += bytes >> hw->info.shift;
+return bytes;
 }
 
 /* VICE code: Store number as little endian. */
@@ -137,13 +113,6 @@ static int wav_init_out(HWVoiceOut *hw, struct audsettings 
*as,
 audio_pcm_init_info (&hw->info, &wav_as);
 
 hw->samples = 1024;
-wav->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift);
-if (!wav->pcm_buf) {
-dolog("Could not allocate buffer (%zu bytes)\n",
-  hw->samples << hw->info.shift);
-return -1;
-}
-
 le_store (hdr + 22, hw->info.nchannels, 2);
 le_store (hdr + 24, hw->info.freq, 4);
 le_store (hdr + 28, hw->info.freq << (bits16 + stereo), 4);
@@ -153,8 +122,6 @@ static int wav_init_out(HWVoiceOut *hw, struct audsettings 
*as,
 if (!wav->f) {
 dolog ("Failed to open wave file `%s'\nReason: %s\n",
wav_path, strerror(errno));
-g_free (wav->pcm_buf);
-wav->pcm_buf = NULL;
 return -1;
 }
 
@@ -208,9 +175,6 @@ static void wav_fini_out (HWVoiceOut *hw)
wav->f, strerror (errno));
 }
 wav->f = NULL;
-
-g_free (wav->pcm_buf);
-wav->pcm_buf = NULL;
 }
 
 static int wav_ctl_out (HWVoiceOut *hw, int cmd, ...)
@@ -234,7 +198,7 @@ static void wav_audio_fini (void *opaque)
 static struct audio_pcm_ops wav_pcm_ops = {
 .init_out = wav_init_out,
 .fini_out = wav_fini_out,
-.run_out  = wav_run_out,
+.write= wav_write_out,
 .ctl_out  = wav_ctl_out,
 };
 
-- 
2.18.1




[PULL 04/16] alsaaudio: port to the new audio backend api

2019-09-23 Thread Gerd Hoffmann
From: Kővágó, Zoltán 

Signed-off-by: Kővágó, Zoltán 
Message-id: 
ab9768e73dfe7b7305bd6a51629846e0d77622a5.1568927990.git.dirty.ice...@gmail.com
Signed-off-by: Gerd Hoffmann 
---
 audio/alsaaudio.c | 308 +-
 1 file changed, 83 insertions(+), 225 deletions(-)

diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c
index 591344dccd1f..19124d09d845 100644
--- a/audio/alsaaudio.c
+++ b/audio/alsaaudio.c
@@ -44,9 +44,6 @@ struct pollhlp {
 
 typedef struct ALSAVoiceOut {
 HWVoiceOut hw;
-int wpos;
-int pending;
-void *pcm_buf;
 snd_pcm_t *handle;
 struct pollhlp pollhlp;
 Audiodev *dev;
@@ -55,7 +52,6 @@ typedef struct ALSAVoiceOut {
 typedef struct ALSAVoiceIn {
 HWVoiceIn hw;
 snd_pcm_t *handle;
-void *pcm_buf;
 struct pollhlp pollhlp;
 Audiodev *dev;
 } ALSAVoiceIn;
@@ -602,102 +598,64 @@ static int alsa_open(bool in, struct alsa_params_req 
*req,
 return -1;
 }
 
-static snd_pcm_sframes_t alsa_get_avail (snd_pcm_t *handle)
-{
-snd_pcm_sframes_t avail;
-
-avail = snd_pcm_avail_update (handle);
-if (avail < 0) {
-if (avail == -EPIPE) {
-if (!alsa_recover (handle)) {
-avail = snd_pcm_avail_update (handle);
-}
-}
-
-if (avail < 0) {
-alsa_logerr (avail,
- "Could not obtain number of available frames\n");
-return -1;
-}
-}
-
-return avail;
-}
-
-static void alsa_write_pending (ALSAVoiceOut *alsa)
-{
-HWVoiceOut *hw = &alsa->hw;
-
-while (alsa->pending) {
-int left_till_end_samples = hw->samples - alsa->wpos;
-int len = MIN (alsa->pending, left_till_end_samples);
-char *src = advance (alsa->pcm_buf, alsa->wpos << hw->info.shift);
-
-while (len) {
-snd_pcm_sframes_t written;
-
-written = snd_pcm_writei (alsa->handle, src, len);
-
-if (written <= 0) {
-switch (written) {
-case 0:
-trace_alsa_wrote_zero(len);
-return;
-
-case -EPIPE:
-if (alsa_recover (alsa->handle)) {
-alsa_logerr (written, "Failed to write %d frames\n",
- len);
-return;
-}
-trace_alsa_xrun_out();
-continue;
-
-case -ESTRPIPE:
-/* stream is suspended and waiting for an
-   application recovery */
-if (alsa_resume (alsa->handle)) {
-alsa_logerr (written, "Failed to write %d frames\n",
- len);
-return;
-}
-trace_alsa_resume_out();
-continue;
-
-case -EAGAIN:
-return;
-
-default:
-alsa_logerr (written, "Failed to write %d frames from 
%p\n",
- len, src);
-return;
-}
-}
-
-alsa->wpos = (alsa->wpos + written) % hw->samples;
-alsa->pending -= written;
-len -= written;
-}
-}
-}
-
-static size_t alsa_run_out(HWVoiceOut *hw, size_t live)
+static size_t alsa_write(HWVoiceOut *hw, void *buf, size_t len)
 {
 ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
-size_t decr;
-snd_pcm_sframes_t avail;
+size_t pos = 0;
+size_t len_frames = len >> hw->info.shift;
 
-avail = alsa_get_avail (alsa->handle);
-if (avail < 0) {
-dolog ("Could not get number of available playback frames\n");
-return 0;
+while (len_frames) {
+char *src = advance(buf, pos);
+snd_pcm_sframes_t written;
+
+written = snd_pcm_writei(alsa->handle, src, len_frames);
+
+if (written <= 0) {
+switch (written) {
+case 0:
+trace_alsa_wrote_zero(len_frames);
+return pos;
+
+case -EPIPE:
+if (alsa_recover(alsa->handle)) {
+alsa_logerr(written, "Failed to write %zu frames\n",
+len_frames);
+return pos;
+}
+trace_alsa_xrun_out();
+continue;
+
+case -ESTRPIPE:
+/*
+ * stream is suspended and waiting for an application
+ * recovery
+ */
+if (alsa_resume(alsa->handle)) {
+alsa_logerr(written, "Failed to write %zu frames\n",
+len_frames);
+return pos;
+}
+trace_alsa_resume_out();
+continue;
+
+case -EAGAIN:
+return pos;
+
+default:

[PULL 14/16] audio: unify input and output mixeng buffer management

2019-09-23 Thread Gerd Hoffmann
From: Kővágó, Zoltán 

Usage notes: hw->samples became hw->{mix,conv}_buf->size, except before
initialization (audio_pcm_hw_alloc_resources_*), hw->samples gives the
initial size of the STSampleBuffer.  The next commit tries to fix this
inconsistency.

Signed-off-by: Kővágó, Zoltán 
Message-id: 
a78caeb2eeb6348ecb45bb2c81709570ef8ac5b3.1568927990.git.dirty.ice...@gmail.com
Signed-off-by: Gerd Hoffmann 
---
 audio/audio_int.h  |  12 ++--
 audio/audio_template.h |  19 +++
 audio/audio.c  | 122 +
 audio/ossaudio.c   |   3 +-
 4 files changed, 80 insertions(+), 76 deletions(-)

diff --git a/audio/audio_int.h b/audio/audio_int.h
index c76d7c39e84c..20021df9e8be 100644
--- a/audio/audio_int.h
+++ b/audio/audio_int.h
@@ -52,6 +52,11 @@ struct audio_pcm_info {
 typedef struct AudioState AudioState;
 typedef struct SWVoiceCap SWVoiceCap;
 
+typedef struct STSampleBuffer {
+size_t pos, size;
+st_sample samples[];
+} STSampleBuffer;
+
 typedef struct HWVoiceOut {
 AudioState *s;
 int enabled;
@@ -60,11 +65,9 @@ typedef struct HWVoiceOut {
 struct audio_pcm_info info;
 
 f_sample *clip;
-
-size_t rpos;
 uint64_t ts_helper;
 
-struct st_sample *mix_buf;
+STSampleBuffer *mix_buf;
 void *buf_emul;
 size_t pos_emul, pending_emul, size_emul;
 
@@ -84,11 +87,10 @@ typedef struct HWVoiceIn {
 
 t_sample *conv;
 
-size_t wpos;
 size_t total_samples_captured;
 uint64_t ts_helper;
 
-struct st_sample *conv_buf;
+STSampleBuffer *conv_buf;
 void *buf_emul;
 size_t pos_emul, pending_emul, size_emul;
 
diff --git a/audio/audio_template.h b/audio/audio_template.h
index ff4a173f1810..87c6d2d27102 100644
--- a/audio/audio_template.h
+++ b/audio/audio_template.h
@@ -76,16 +76,15 @@ static void glue (audio_pcm_hw_free_resources_, TYPE) (HW 
*hw)
 HWBUF = NULL;
 }
 
-static bool glue(audio_pcm_hw_alloc_resources_, TYPE)(HW *hw)
+static void glue(audio_pcm_hw_alloc_resources_, TYPE)(HW *hw)
 {
-HWBUF = audio_calloc(__func__, hw->samples, sizeof(struct st_sample));
-if (!HWBUF) {
-dolog("Could not allocate " NAME " buffer (%zu samples)\n",
-  hw->samples);
-return false;
+size_t samples = hw->samples;
+if (audio_bug(__func__, samples == 0)) {
+dolog("Attempted to allocate empty buffer\n");
 }
 
-return true;
+HWBUF = g_malloc0(sizeof(STSampleBuffer) + sizeof(st_sample) * samples);
+HWBUF->size = samples;
 }
 
 static void glue (audio_pcm_sw_free_resources_, TYPE) (SW *sw)
@@ -104,7 +103,7 @@ static int glue (audio_pcm_sw_alloc_resources_, TYPE) (SW 
*sw)
 {
 int samples;
 
-samples = ((int64_t) sw->hw->samples << 32) / sw->ratio;
+samples = ((int64_t) sw->HWBUF->size << 32) / sw->ratio;
 
 sw->buf = audio_calloc(__func__, samples, sizeof(struct st_sample));
 if (!sw->buf) {
@@ -280,9 +279,7 @@ static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioState *s,
 [hw->info.swap_endianness]
 [audio_bits_to_index (hw->info.bits)];
 
-if (!glue(audio_pcm_hw_alloc_resources_, TYPE)(hw)) {
-goto err1;
-}
+glue(audio_pcm_hw_alloc_resources_, TYPE)(hw);
 
 QLIST_INSERT_HEAD (&s->glue (hw_head_, TYPE), hw, entries);
 glue (s->nb_hw_voices_, TYPE) -= 1;
diff --git a/audio/audio.c b/audio/audio.c
index 435bcf20c139..ba07fb77dd4f 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -544,8 +544,8 @@ static size_t audio_pcm_hw_find_min_in (HWVoiceIn *hw)
 static size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw)
 {
 size_t live = hw->total_samples_captured - audio_pcm_hw_find_min_in (hw);
-if (audio_bug(__func__, live > hw->samples)) {
-dolog("live=%zu hw->samples=%zu\n", live, hw->samples);
+if (audio_bug(__func__, live > hw->conv_buf->size)) {
+dolog("live=%zu hw->conv_buf->size=%zu\n", live, hw->conv_buf->size);
 return 0;
 }
 return live;
@@ -554,17 +554,17 @@ static size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw)
 static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, size_t len)
 {
 size_t clipped = 0;
-size_t pos = hw->rpos;
+size_t pos = hw->mix_buf->pos;
 
 while (len) {
-st_sample *src = hw->mix_buf + pos;
+st_sample *src = hw->mix_buf->samples + pos;
 uint8_t *dst = advance(pcm_buf, clipped << hw->info.shift);
-size_t samples_till_end_of_buf = hw->samples - pos;
+size_t samples_till_end_of_buf = hw->mix_buf->size - pos;
 size_t samples_to_clip = MIN(len, samples_till_end_of_buf);
 
 hw->clip(dst, src, samples_to_clip);
 
-pos = (pos + samples_to_clip) % hw->samples;
+pos = (pos + samples_to_clip) % hw->mix_buf->size;
 len -= samples_to_clip;
 clipped += samples_to_clip;
 }
@@ -579,17 +579,17 @@ static size_t audio_pcm_sw_get_rpos_in(SWVoiceIn *sw)
 ssize_t live = hw->total_samples_captured - sw->total_hw_samples_acquired;
   

[PULL 05/16] coreaudio: port to the new audio backend api

2019-09-23 Thread Gerd Hoffmann
From: Kővágó, Zoltán 

Signed-off-by: Kővágó, Zoltán 
Message-id: 
586a1e66de5cbc6c5234f9ae556d24befb6afada.1568927990.git.dirty.ice...@gmail.com
Signed-off-by: Gerd Hoffmann 
---
 audio/coreaudio.c | 130 --
 1 file changed, 69 insertions(+), 61 deletions(-)

diff --git a/audio/coreaudio.c b/audio/coreaudio.c
index d1be58b40aa8..5cde42f9826c 100644
--- a/audio/coreaudio.c
+++ b/audio/coreaudio.c
@@ -43,9 +43,6 @@ typedef struct coreaudioVoiceOut {
 UInt32 audioDevicePropertyBufferFrameSize;
 AudioStreamBasicDescription outputStreamBasicDescription;
 AudioDeviceIOProcID ioprocid;
-size_t live;
-size_t decr;
-size_t rpos;
 } coreaudioVoiceOut;
 
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
@@ -397,31 +394,29 @@ static int coreaudio_unlock (coreaudioVoiceOut *core, 
const char *fn_name)
 return 0;
 }
 
-static size_t coreaudio_run_out(HWVoiceOut *hw, size_t live)
-{
-size_t decr;
-coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
-
-if (coreaudio_lock (core, "coreaudio_run_out")) {
-return 0;
+#define COREAUDIO_WRAPPER_FUNC(name, ret_type, args_decl, args) \
+static ret_type glue(coreaudio_, name)args_decl \
+{   \
+coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; \
+ret_type ret;   \
+\
+if (coreaudio_lock(core, "coreaudio_" #name)) { \
+return 0;   \
+}   \
+\
+ret = glue(audio_generic_, name)args;   \
+\
+coreaudio_unlock(core, "coreaudio_" #name); \
+return ret; \
 }
-
-if (core->decr > live) {
-ldebug ("core->decr %d live %d core->live %d\n",
-core->decr,
-live,
-core->live);
-}
-
-decr = MIN (core->decr, live);
-core->decr -= decr;
-
-core->live = live - decr;
-hw->rpos = core->rpos;
-
-coreaudio_unlock (core, "coreaudio_run_out");
-return decr;
-}
+COREAUDIO_WRAPPER_FUNC(get_buffer_out, void *, (HWVoiceOut *hw, size_t *size),
+   (hw, size))
+COREAUDIO_WRAPPER_FUNC(put_buffer_out_nowrite, size_t,
+   (HWVoiceOut *hw, void *buf, size_t size),
+   (hw, buf, size))
+COREAUDIO_WRAPPER_FUNC(write, size_t, (HWVoiceOut *hw, void *buf, size_t size),
+   (hw, buf, size))
+#undef COREAUDIO_WRAPPER_FUNC
 
 /* callback to feed audiooutput buffer */
 static OSStatus audioDeviceIOProc(
@@ -433,19 +428,11 @@ static OSStatus audioDeviceIOProc(
 const AudioTimeStamp* inOutputTime,
 void* hwptr)
 {
-UInt32 frame, frameCount;
-float *out = outOutputData->mBuffers[0].mData;
+UInt32 frameCount, pending_frames;
+void *out = outOutputData->mBuffers[0].mData;
 HWVoiceOut *hw = hwptr;
 coreaudioVoiceOut *core = (coreaudioVoiceOut *) hwptr;
-int rpos, live;
-struct st_sample *src;
-#ifndef FLOAT_MIXENG
-#ifdef RECIPROCAL
-const float scale = 1.f / UINT_MAX;
-#else
-const float scale = UINT_MAX;
-#endif
-#endif
+size_t len;
 
 if (coreaudio_lock (core, "audioDeviceIOProc")) {
 inInputTime = 0;
@@ -453,42 +440,51 @@ static OSStatus audioDeviceIOProc(
 }
 
 frameCount = core->audioDevicePropertyBufferFrameSize;
-live = core->live;
+pending_frames = hw->pending_emul >> hw->info.shift;
 
 /* if there are not enough samples, set signal and return */
-if (live < frameCount) {
+if (pending_frames < frameCount) {
 inInputTime = 0;
 coreaudio_unlock (core, "audioDeviceIOProc(empty)");
 return 0;
 }
 
-rpos = core->rpos;
-src = hw->mix_buf + rpos;
+len = frameCount << hw->info.shift;
+while (len) {
+size_t write_len;
+ssize_t start = ((ssize_t) hw->pos_emul) - hw->pending_emul;
+if (start < 0) {
+start += hw->size_emul;
+}
+assert(start >= 0 && start < hw->size_emul);
 
-/* fill buffer */
-for (frame = 0; frame < frameCount; frame++) {
-#ifdef FLOAT_MIXENG
-*out++ = src[frame].l; /* left channel */
-*out++ = src[frame].r; /* right channel */
-#else
-#ifdef RECIPROCAL
-*out++ = src[frame].l * scale; /* left channel */
-*out++ = src[frame].r * scale; /* right channel */
-#else
-*out++ = src[frame].l / scale; /* left channel */
-*out++ = src[frame].r / scale; /* right channel */
-#endif
-#endif
+write_len = MIN(MIN(hw->pending_emul, len),
+hw->size_emu

[PULL 03/16] audio: api for mixeng code free backends

2019-09-23 Thread Gerd Hoffmann
From: Kővágó, Zoltán 

This will make it possible to skip mixeng with audio playback and
recording, allowing us to free ourselves from the limitations of the
current mixeng (stereo, int64 samples only).  In this case, HW and SW
voices will be essentially the same, for every SW voice we will create
a HW voice, since we can no longer mix multiple voices together.

Some backends expect us to call a function when we have data ready
write()/read() style, while others provide a buffer and expects us to
directly write/read it, so for optimal performance audio_pcm_ops provide
methods for both cases.  Previously backends asked mixeng for more data
in run_out/run_it, now instead mixeng or the frontends will call the
backends, so that's why two sets of functions required.  audio.c
contains glue code between the two styles, so backends only ever have to
implement one style and frontends are free to call whichever is more
convenient for them.

Signed-off-by: Kővágó, Zoltán 
Message-id: 
15a33c03a62228922d851f7324c52f73cb8d2414.1568927990.git.dirty.ice...@gmail.com
Signed-off-by: Gerd Hoffmann 
---
 audio/audio_int.h  |  41 ++--
 audio/audio_template.h |   1 +
 audio/audio.c  | 216 -
 3 files changed, 250 insertions(+), 8 deletions(-)

diff --git a/audio/audio_int.h b/audio/audio_int.h
index a674c5374a06..8fb1ca8a8d0f 100644
--- a/audio/audio_int.h
+++ b/audio/audio_int.h
@@ -65,6 +65,8 @@ typedef struct HWVoiceOut {
 uint64_t ts_helper;
 
 struct st_sample *mix_buf;
+void *buf_emul;
+size_t pos_emul, pending_emul, size_emul;
 
 size_t samples;
 QLIST_HEAD (sw_out_listhead, SWVoiceOut) sw_head;
@@ -87,6 +89,8 @@ typedef struct HWVoiceIn {
 uint64_t ts_helper;
 
 struct st_sample *conv_buf;
+void *buf_emul;
+size_t pos_emul, pending_emul, size_emul;
 
 size_t samples;
 QLIST_HEAD (sw_in_listhead, SWVoiceIn) sw_head;
@@ -147,17 +151,42 @@ struct audio_driver {
 };
 
 struct audio_pcm_ops {
-int  (*init_out)(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque);
-void (*fini_out)(HWVoiceOut *hw);
+int(*init_out)(HWVoiceOut *hw, audsettings *as, void *drv_opaque);
+void   (*fini_out)(HWVoiceOut *hw);
 size_t (*run_out)(HWVoiceOut *hw, size_t live);
-int  (*ctl_out) (HWVoiceOut *hw, int cmd, ...);
+size_t (*write)   (HWVoiceOut *hw, void *buf, size_t size);
+/*
+ * get a buffer that after later can be passed to put_buffer_out; optional
+ * returns the buffer, and writes it's size to size (in bytes)
+ * this is unrelated to the above buffer_size_out function
+ */
+void  *(*get_buffer_out)(HWVoiceOut *hw, size_t *size);
+/*
+ * put back the buffer returned by get_buffer_out; optional
+ * buf must be equal the pointer returned by get_buffer_out,
+ * size may be smaller
+ */
+size_t (*put_buffer_out)(HWVoiceOut *hw, void *buf, size_t size);
+int(*ctl_out) (HWVoiceOut *hw, int cmd, ...);
 
-int  (*init_in) (HWVoiceIn *hw, struct audsettings *as, void *drv_opaque);
-void (*fini_in) (HWVoiceIn *hw);
+int(*init_in) (HWVoiceIn *hw, audsettings *as, void *drv_opaque);
+void   (*fini_in) (HWVoiceIn *hw);
 size_t (*run_in)(HWVoiceIn *hw);
-int  (*ctl_in)  (HWVoiceIn *hw, int cmd, ...);
+size_t (*read)(HWVoiceIn *hw, void *buf, size_t size);
+void  *(*get_buffer_in)(HWVoiceIn *hw, size_t *size);
+void   (*put_buffer_in)(HWVoiceIn *hw, void *buf, size_t size);
+int(*ctl_in)  (HWVoiceIn *hw, int cmd, ...);
 };
 
+void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size);
+void audio_generic_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size);
+void *audio_generic_get_buffer_out(HWVoiceOut *hw, size_t *size);
+size_t audio_generic_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size);
+size_t audio_generic_put_buffer_out_nowrite(HWVoiceOut *hw, void *buf,
+size_t size);
+size_t audio_generic_write(HWVoiceOut *hw, void *buf, size_t size);
+size_t audio_generic_read(HWVoiceIn *hw, void *buf, size_t size);
+
 struct capture_callback {
 struct audio_capture_ops ops;
 void *opaque;
diff --git a/audio/audio_template.h b/audio/audio_template.h
index 2562bf5f0062..ff4a173f1810 100644
--- a/audio/audio_template.h
+++ b/audio/audio_template.h
@@ -71,6 +71,7 @@ static void glue(audio_init_nb_voices_, TYPE)(AudioState *s,
 
 static void glue (audio_pcm_hw_free_resources_, TYPE) (HW *hw)
 {
+g_free(hw->buf_emul);
 g_free (HWBUF);
 HWBUF = NULL;
 }
diff --git a/audio/audio.c b/audio/audio.c
index e99fcd0694e9..e29a1e15eb30 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -573,6 +573,25 @@ size_t audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf,
 return clipped;
 }
 
+static void audio_pcm_hw_clip_out2(HWVoiceOut *hw, void *pcm_buf, size_t len)
+{
+size_t clipped = 0;
+size_t pos = hw->rpos;
+
+while (len) {
+st_sa

[PULL 07/16] noaudio: port to the new audio backend api

2019-09-23 Thread Gerd Hoffmann
From: Kővágó, Zoltán 

Signed-off-by: Kővágó, Zoltán 
Message-id: 
10eebdd2e1529c2bd403ef98dd9d346c6d4ca3d1.1568927990.git.dirty.ice...@gmail.com
Signed-off-by: Gerd Hoffmann 
---
 audio/noaudio.c | 39 +++
 1 file changed, 15 insertions(+), 24 deletions(-)

diff --git a/audio/noaudio.c b/audio/noaudio.c
index 0fb2629cf283..b054fd225b66 100644
--- a/audio/noaudio.c
+++ b/audio/noaudio.c
@@ -41,10 +41,9 @@ typedef struct NoVoiceIn {
 int64_t old_ticks;
 } NoVoiceIn;
 
-static size_t no_run_out(HWVoiceOut *hw, size_t live)
+static size_t no_write(HWVoiceOut *hw, void *buf, size_t len)
 {
 NoVoiceOut *no = (NoVoiceOut *) hw;
-size_t decr, samples;
 int64_t now;
 int64_t ticks;
 int64_t bytes;
@@ -52,13 +51,9 @@ static size_t no_run_out(HWVoiceOut *hw, size_t live)
 now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
 ticks = now - no->old_ticks;
 bytes = muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND);
-bytes = MIN(bytes, SIZE_MAX);
-samples = bytes >> hw->info.shift;
 
 no->old_ticks = now;
-decr = MIN (live, samples);
-hw->rpos = (hw->rpos + decr) % hw->samples;
-return decr;
+return MIN(len, bytes);
 }
 
 static int no_init_out(HWVoiceOut *hw, struct audsettings *as, void 
*drv_opaque)
@@ -92,25 +87,21 @@ static void no_fini_in (HWVoiceIn *hw)
 (void) hw;
 }
 
-static size_t no_run_in(HWVoiceIn *hw)
+static size_t no_read(HWVoiceIn *hw, void *buf, size_t size)
 {
+size_t to_clear;
 NoVoiceIn *no = (NoVoiceIn *) hw;
-size_t live = audio_pcm_hw_get_live_in(hw);
-size_t dead = hw->samples - live;
-size_t samples = 0;
 
-if (dead) {
-int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
-int64_t ticks = now - no->old_ticks;
-int64_t bytes =
-muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND);
+int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+int64_t ticks = now - no->old_ticks;
+int64_t bytes =
+muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND);
 
-no->old_ticks = now;
-bytes = MIN (bytes, SIZE_MAX);
-samples = bytes >> hw->info.shift;
-samples = MIN (samples, dead);
-}
-return samples;
+no->old_ticks = now;
+to_clear = MIN(bytes, size);
+
+audio_pcm_info_clear_buf(&hw->info, buf, to_clear >> hw->info.shift);
+return to_clear;
 }
 
 static int no_ctl_in (HWVoiceIn *hw, int cmd, ...)
@@ -133,12 +124,12 @@ static void no_audio_fini (void *opaque)
 static struct audio_pcm_ops no_pcm_ops = {
 .init_out = no_init_out,
 .fini_out = no_fini_out,
-.run_out  = no_run_out,
+.write= no_write,
 .ctl_out  = no_ctl_out,
 
 .init_in  = no_init_in,
 .fini_in  = no_fini_in,
-.run_in   = no_run_in,
+.read = no_read,
 .ctl_in   = no_ctl_in
 };
 
-- 
2.18.1




[PULL 02/16] audio: fix ALSA period-length typo in documentation

2019-09-23 Thread Gerd Hoffmann
From: Stefan Hajnoczi 

Fixes: f0b3d811529 ("audio: -audiodev command line option: documentation")
Signed-off-by: Stefan Hajnoczi 
Message-Id: <20190918095335.7646-4-stefa...@redhat.com>
Signed-off-by: Gerd Hoffmann 
---
 qemu-options.hx | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/qemu-options.hx b/qemu-options.hx
index 569958fc0c77..565d7af8c208 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -445,7 +445,7 @@ DEF("audiodev", HAS_ARG, QEMU_OPTION_audiodev,
 #ifdef CONFIG_AUDIO_ALSA
 "-audiodev alsa,id=id[,prop[=value][,...]]\n"
 "in|out.dev= name of the audio device to use\n"
-"in|out.period-len= length of period in microseconds\n"
+"in|out.period-length= length of period in microseconds\n"
 "in|out.try-poll= attempt to use poll mode\n"
 "threshold= threshold (in microseconds) when playback 
starts\n"
 #endif
@@ -545,7 +545,7 @@ ALSA specific options are:
 Specify the ALSA @var{device} to use for input and/or output.  Default
 is @code{default}.
 
-@item in|out.period-len=@var{usecs}
+@item in|out.period-length=@var{usecs}
 Sets the period length in microseconds.
 
 @item in|out.try-poll=on|off
-- 
2.18.1




[PULL 01/16] audio: fix buffer-length typo in documentation

2019-09-23 Thread Gerd Hoffmann
From: Stefan Hajnoczi 

Fixes: f0b3d811529 ("audio: -audiodev command line option: documentation")
Signed-off-by: Stefan Hajnoczi 
Message-Id: <20190918095335.7646-2-stefa...@redhat.com>
Signed-off-by: Gerd Hoffmann 
---
 qemu-options.hx | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/qemu-options.hx b/qemu-options.hx
index 80c16fa317e5..569958fc0c77 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -439,7 +439,7 @@ DEF("audiodev", HAS_ARG, QEMU_OPTION_audiodev,
 "in|out.format= sample format to use with fixed settings\n"
 "valid values: s8, s16, s32, u8, u16, u32\n"
 "in|out.voices= number of voices to use\n"
-"in|out.buffer-len= length of buffer in microseconds\n"
+"in|out.buffer-length= length of buffer in microseconds\n"
 "-audiodev none,id=id,[,prop[=value][,...]]\n"
 "dummy driver that discards all output\n"
 #ifdef CONFIG_AUDIO_ALSA
@@ -524,7 +524,7 @@ Valid values are: @code{s8}, @code{s16}, @code{s32}, 
@code{u8},
 @item in|out.voices=@var{voices}
 Specify the number of @var{voices} to use.  Default is 1.
 
-@item in|out.buffer=@var{usecs}
+@item in|out.buffer-length=@var{usecs}
 Sets the size of the buffer in microseconds.
 
 @end table
-- 
2.18.1




[PULL 00/16] Audio 20190924 patches

2019-09-23 Thread Gerd Hoffmann
The following changes since commit 4300b7c2cd9f3f273804e8cca325842ccb93b1ad:

  Merge remote-tracking branch 'remotes/cleber/tags/python-next-pull-request' 
into staging (2019-09-20 17:28:43 +0100)

are available in the Git repository at:

  git://git.kraxel.org/qemu tags/audio-20190924-pull-request

for you to fetch changes up to 571a8c522e0095239598347ac0add93337c1e0bf:

  audio: split ctl_* functions into enable_* and volume_* (2019-09-23 12:28:47 
+0200)


audio: documentation fixes.
audio: new backend api (first part of the surround sound patch series).



Kővágó, Zoltán (14):
  audio: api for mixeng code free backends
  alsaaudio: port to the new audio backend api
  coreaudio: port to the new audio backend api
  dsoundaudio: port to the new audio backend api
  noaudio: port to the new audio backend api
  ossaudio: port to the new audio backend api
  paaudio: port to the new audio backend api
  sdlaudio: port to the new audio backend api
  spiceaudio: port to the new audio backend api
  wavaudio: port to the new audio backend api
  audio: remove remains of the old backend api
  audio: unify input and output mixeng buffer management
  audio: common rate control code for timer based outputs
  audio: split ctl_* functions into enable_* and volume_*

Stefan Hajnoczi (2):
  audio: fix buffer-length typo in documentation
  audio: fix ALSA period-length typo in documentation

 configure   |   5 -
 audio/audio_int.h   |  76 --
 audio/audio_pt_int.h|  22 --
 audio/audio_template.h  |  21 +-
 audio/dsound_template.h |  47 ++--
 audio/alsaaudio.c   | 370 +
 audio/audio.c   | 383 +++---
 audio/audio_pt_int.c| 173 --
 audio/coreaudio.c   | 143 ++--
 audio/dsoundaudio.c | 379 --
 audio/noaudio.c |  76 +++---
 audio/ossaudio.c| 364 +++--
 audio/paaudio.c | 499 
 audio/sdlaudio.c| 104 -
 audio/spiceaudio.c  | 257 +++--
 audio/wavaudio.c|  76 ++
 audio/Makefile.objs |   1 -
 qemu-options.hx |   8 +-
 18 files changed, 1083 insertions(+), 1921 deletions(-)
 delete mode 100644 audio/audio_pt_int.h
 delete mode 100644 audio/audio_pt_int.c

-- 
2.18.1




Re: [Bug 1824704] Re: -k tr not working after v20171217! turkish keyboard dont working

2019-09-23 Thread mustafa
24 Eylül 2019 Salı tarihinde Thomas Huth <1824...@bugs.launchpad.net>
yazdı:

> Can you find out which commit broke the keyboard for you? (By using "git
> bisect" for example)
>
> ** Information type changed from Private Security to Public
>
> --
> You received this bug notification because you are subscribed to the bug
> report.
> https://bugs.launchpad.net/bugs/1824704
>
> Title:
>   -k tr not working after v20171217! turkish keyboard dont working
>
> Status in QEMU:
>   New
>
> Bug description:
>   hi qemu
>
>   -k tr not working after v20171217! turkish keyboard dont working
>
>   last working without proplem at v20171217!
>
>   after this version  tr keyboard proplem.
>   freedos  , winpe  ,  linux images   all dont working tr  turkish
> keyboard.
>
>   example   press key " ç "  show " , "
>   example 2 press key " . "  show " ç "
>
>   tr keyboard work  always "en-us" kbd.
>   :
>
>   please fix this critical bug.
>
>   Sincerely
>
> To manage notifications about this bug go to:
> https://bugs.launchpad.net/qemu/+bug/1824704/+subscriptions
>


Not working turkish q keyboard

Ç pres result,
. Press. Result ç

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1824704

Title:
  -k tr not working after v20171217! turkish keyboard dont working

Status in QEMU:
  New

Bug description:
  hi qemu

  -k tr not working after v20171217! turkish keyboard dont working

  last working without proplem at v20171217!

  after this version  tr keyboard proplem.
  freedos  , winpe  ,  linux images   all dont working tr  turkish keyboard.

  example   press key " ç "  show " , "
  example 2 press key " . "  show " ç "

  tr keyboard work  always "en-us" kbd.
  :

  please fix this critical bug.

  Sincerely

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1824704/+subscriptions



[Bug 1824704] Re: -k tr not working after v20171217! turkish keyboard dont working

2019-09-23 Thread Thomas Huth
Can you find out which commit broke the keyboard for you? (By using "git
bisect" for example)

** Information type changed from Private Security to Public

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1824704

Title:
  -k tr not working after v20171217! turkish keyboard dont working

Status in QEMU:
  New

Bug description:
  hi qemu

  -k tr not working after v20171217! turkish keyboard dont working

  last working without proplem at v20171217!

  after this version  tr keyboard proplem.
  freedos  , winpe  ,  linux images   all dont working tr  turkish keyboard.

  example   press key " ç "  show " , "
  example 2 press key " . "  show " ç "

  tr keyboard work  always "en-us" kbd.
  :

  please fix this critical bug.

  Sincerely

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1824704/+subscriptions



[Bug 1842916] Re: [18.04 FEAT] Enhanced Hardware Support - Finalize Naming

2019-09-23 Thread Thomas Huth
*** This bug is a duplicate of bug 1842774 ***
https://bugs.launchpad.net/bugs/1842774

** No longer affects: qemu

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1842916

Title:
  [18.04 FEAT] Enhanced Hardware Support - Finalize Naming

Status in Ubuntu on IBM z Systems:
  Triaged
Status in linux package in Ubuntu:
  New

Bug description:
  This feature request will provide the final naming of the next machine

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu-z-systems/+bug/1842916/+subscriptions



[Bug 1842774] Re: Enhanced Hardware Support - Finalize Naming

2019-09-23 Thread Thomas Huth
Patch a0e2251132995b9 is a kernel patch, thus this is certainly not
something we need to track in the upstream QEMU bugtracker.

** No longer affects: qemu

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1842774

Title:
  Enhanced Hardware Support - Finalize Naming

Status in Ubuntu on IBM z Systems:
  Triaged
Status in linux package in Ubuntu:
  In Progress
Status in linux source package in Bionic:
  In Progress
Status in linux source package in Disco:
  In Progress

Bug description:
  SRU Justification:
  ==

  [Impact]

  * Add / activate support for IBM z15 and LinuxONE III systems

  [Fix]

  * a0e2251132995b962281aa80ab54a9288f9e0b6b a0e2251 "s390: add support
  for IBM z15 machines"

  [Test Case]

  * check and verify cpuinfo - regression testing is possible by
  Canonical/me

  * functional testing is currently only doable by IBM

  [Regression Potential]

  * There is regression potential with having new code in and the flags
  added/active

  * but the code changes are pretty straight forward, just add config,
  cases and defs

  * and are not used on existing systems, just on the new generation
  that is not yet out in the field

  [Other Info]

  * SRU of LP 1842916 merged with (this) LP 1842774

  __

  This feature request will provide the final naming of the next machine

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu-z-systems/+bug/1842774/+subscriptions



Re: [PATCH 4/4] xics: Merge TYPE_ICS_BASE and TYPE_ICS_SIMPLE classes

2019-09-23 Thread Cédric Le Goater
On 24/09/2019 06:59, David Gibson wrote:
> TYPE_ICS_SIMPLE is the only subtype of TYPE_ICS_BASE that's ever
> instantiated, and the only one we're ever likely to want.  The
> existence of different classes is just a hang over from when we
> (misguidedly) had separate subtypes for the KVM and non-KVM version of
> the device.
> 
> So, collapse the two classes together into just TYPE_ICS.


Well, I have been maintaining another subclass for the PHB3 MSI 
but it has never been merged and it will require some rework. 

Anyhow the base ICS code is cleaner with that patch and it
does not seem to break migration.

> 
> Signed-off-by: David Gibson 


Reviewed-by: Cédric Le Goater 

C.


> ---
>  hw/intc/xics.c| 57 ---
>  hw/ppc/pnv_psi.c  |  2 +-
>  hw/ppc/spapr_irq.c|  4 +--
>  include/hw/ppc/xics.h | 17 ++---
>  4 files changed, 26 insertions(+), 54 deletions(-)
> 
> diff --git a/hw/intc/xics.c b/hw/intc/xics.c
> index 9ae51bbc76..388dbba870 100644
> --- a/hw/intc/xics.c
> +++ b/hw/intc/xics.c
> @@ -555,7 +555,7 @@ static void ics_reset_irq(ICSIRQState *irq)
>  
>  static void ics_reset(DeviceState *dev)
>  {
> -ICSState *ics = ICS_BASE(dev);
> +ICSState *ics = ICS(dev);
>  int i;
>  uint8_t flags[ics->nr_irqs];
>  
> @@ -573,7 +573,7 @@ static void ics_reset(DeviceState *dev)
>  if (kvm_irqchip_in_kernel()) {
>  Error *local_err = NULL;
>  
> -ics_set_kvm_state(ICS_BASE(dev), &local_err);
> +ics_set_kvm_state(ICS(dev), &local_err);
>  if (local_err) {
>  error_report_err(local_err);
>  }
> @@ -587,7 +587,7 @@ static void ics_reset_handler(void *dev)
>  
>  static void ics_realize(DeviceState *dev, Error **errp)
>  {
> -ICSState *ics = ICS_BASE(dev);
> +ICSState *ics = ICS(dev);
>  Error *local_err = NULL;
>  Object *obj;
>  
> @@ -609,26 +609,14 @@ static void ics_realize(DeviceState *dev, Error **errp)
>  qemu_register_reset(ics_reset_handler, ics);
>  }
>  
> -static void ics_simple_class_init(ObjectClass *klass, void *data)
> +static void ics_instance_init(Object *obj)
>  {
> -}
> -
> -static const TypeInfo ics_simple_info = {
> -.name = TYPE_ICS_SIMPLE,
> -.parent = TYPE_ICS_BASE,
> -.instance_size = sizeof(ICSState),
> -.class_init = ics_simple_class_init,
> -.class_size = sizeof(ICSStateClass),
> -};
> -
> -static void ics_base_instance_init(Object *obj)
> -{
> -ICSState *ics = ICS_BASE(obj);
> +ICSState *ics = ICS(obj);
>  
>  ics->offset = XICS_IRQ_BASE;
>  }
>  
> -static int ics_base_pre_save(void *opaque)
> +static int ics_pre_save(void *opaque)
>  {
>  ICSState *ics = opaque;
>  
> @@ -639,7 +627,7 @@ static int ics_base_pre_save(void *opaque)
>  return 0;
>  }
>  
> -static int ics_base_post_load(void *opaque, int version_id)
> +static int ics_post_load(void *opaque, int version_id)
>  {
>  ICSState *ics = opaque;
>  
> @@ -657,7 +645,7 @@ static int ics_base_post_load(void *opaque, int 
> version_id)
>  return 0;
>  }
>  
> -static const VMStateDescription vmstate_ics_base_irq = {
> +static const VMStateDescription vmstate_ics_irq = {
>  .name = "ics/irq",
>  .version_id = 2,
>  .minimum_version_id = 1,
> @@ -671,46 +659,44 @@ static const VMStateDescription vmstate_ics_base_irq = {
>  },
>  };
>  
> -static const VMStateDescription vmstate_ics_base = {
> +static const VMStateDescription vmstate_ics = {
>  .name = "ics",
>  .version_id = 1,
>  .minimum_version_id = 1,
> -.pre_save = ics_base_pre_save,
> -.post_load = ics_base_post_load,
> +.pre_save = ics_pre_save,
> +.post_load = ics_post_load,
>  .fields = (VMStateField[]) {
>  /* Sanity check */
>  VMSTATE_UINT32_EQUAL(nr_irqs, ICSState, NULL),
>  
>  VMSTATE_STRUCT_VARRAY_POINTER_UINT32(irqs, ICSState, nr_irqs,
> - vmstate_ics_base_irq,
> + vmstate_ics_irq,
>   ICSIRQState),
>  VMSTATE_END_OF_LIST()
>  },
>  };
>  
> -static Property ics_base_properties[] = {
> +static Property ics_properties[] = {
>  DEFINE_PROP_UINT32("nr-irqs", ICSState, nr_irqs, 0),
>  DEFINE_PROP_END_OF_LIST(),
>  };
>  
> -static void ics_base_class_init(ObjectClass *klass, void *data)
> +static void ics_class_init(ObjectClass *klass, void *data)
>  {
>  DeviceClass *dc = DEVICE_CLASS(klass);
>  
>  dc->realize = ics_realize;
> -dc->props = ics_base_properties;
> +dc->props = ics_properties;
>  dc->reset = ics_reset;
> -dc->vmsd = &vmstate_ics_base;
> +dc->vmsd = &vmstate_ics;
>  }
>  
> -static const TypeInfo ics_base_info = {
> -.name = TYPE_ICS_BASE,
> +static const TypeInfo ics_info = {
> +.name = TYPE_ICS,
>  .parent = TYPE_DEVICE,
> -.abstract = true,
>  .instance_size = sizeof(ICSState),
> -.in

Re: [PATCH 3/4] xics: Rename misleading ics_simple_*() functions

2019-09-23 Thread Cédric Le Goater
On 24/09/2019 06:59, David Gibson wrote:
> There are a number of ics_simple_*() functions that aren't actually
> specific to TYPE_XICS_SIMPLE at all, and are equally valid on
> TYPE_XICS_BASE.  Rename them to ics_*() accordingly.
> 
> Signed-off-by: David Gibson 


Reviewed-by: Cédric Le Goater 

C.

> ---
>  hw/intc/trace-events  |  6 +++---
>  hw/intc/xics.c| 29 ++---
>  hw/intc/xics_spapr.c  | 12 ++--
>  hw/ppc/pnv_psi.c  |  4 ++--
>  hw/ppc/spapr_irq.c|  2 +-
>  include/hw/ppc/xics.h |  6 +++---
>  6 files changed, 29 insertions(+), 30 deletions(-)
> 
> diff --git a/hw/intc/trace-events b/hw/intc/trace-events
> index fdc716c2cc..527c3f76ca 100644
> --- a/hw/intc/trace-events
> +++ b/hw/intc/trace-events
> @@ -66,10 +66,10 @@ xics_icp_accept(uint32_t old_xirr, uint32_t new_xirr) 
> "icp_accept: XIRR 0x%"PRIx
>  xics_icp_eoi(int server, uint32_t xirr, uint32_t new_xirr) "icp_eoi: server 
> %d given XIRR 0x%"PRIx32" new XIRR 0x%"PRIx32
>  xics_icp_irq(int server, int nr, uint8_t priority) "cpu %d trying to deliver 
> irq 0x%"PRIx32" priority 0x%x"
>  xics_icp_raise(uint32_t xirr, uint8_t pending_priority) "raising IRQ new 
> XIRR=0x%x new pending priority=0x%x"
> -xics_ics_simple_set_irq_msi(int srcno, int nr) "set_irq_msi: srcno %d [irq 
> 0x%x]"
> +xics_ics_set_irq_msi(int srcno, int nr) "set_irq_msi: srcno %d [irq 0x%x]"
>  xics_masked_pending(void) "set_irq_msi: masked pending"
> -xics_ics_simple_set_irq_lsi(int srcno, int nr) "set_irq_lsi: srcno %d [irq 
> 0x%x]"
> -xics_ics_simple_write_xive(int nr, int srcno, int server, uint8_t priority) 
> "ics_write_xive: irq 0x%x [src %d] server 0x%x prio 0x%x"
> +xics_ics_set_irq_lsi(int srcno, int nr) "set_irq_lsi: srcno %d [irq 0x%x]"
> +xics_ics_write_xive(int nr, int srcno, int server, uint8_t priority) 
> "ics_write_xive: irq 0x%x [src %d] server 0x%x prio 0x%x"
>  xics_ics_reject(int nr, int srcno) "reject irq 0x%x [src %d]"
>  xics_ics_eoi(int nr) "ics_eoi: irq 0x%x"
>  
> diff --git a/hw/intc/xics.c b/hw/intc/xics.c
> index db0e532bd9..9ae51bbc76 100644
> --- a/hw/intc/xics.c
> +++ b/hw/intc/xics.c
> @@ -428,11 +428,11 @@ static void ics_resend_lsi(ICSState *ics, int srcno)
>  }
>  }
>  
> -static void ics_simple_set_irq_msi(ICSState *ics, int srcno, int val)
> +static void ics_set_irq_msi(ICSState *ics, int srcno, int val)
>  {
>  ICSIRQState *irq = ics->irqs + srcno;
>  
> -trace_xics_ics_simple_set_irq_msi(srcno, srcno + ics->offset);
> +trace_xics_ics_set_irq_msi(srcno, srcno + ics->offset);
>  
>  if (val) {
>  if (irq->priority == 0xff) {
> @@ -444,11 +444,11 @@ static void ics_simple_set_irq_msi(ICSState *ics, int 
> srcno, int val)
>  }
>  }
>  
> -static void ics_simple_set_irq_lsi(ICSState *ics, int srcno, int val)
> +static void ics_set_irq_lsi(ICSState *ics, int srcno, int val)
>  {
>  ICSIRQState *irq = ics->irqs + srcno;
>  
> -trace_xics_ics_simple_set_irq_lsi(srcno, srcno + ics->offset);
> +trace_xics_ics_set_irq_lsi(srcno, srcno + ics->offset);
>  if (val) {
>  irq->status |= XICS_STATUS_ASSERTED;
>  } else {
> @@ -457,7 +457,7 @@ static void ics_simple_set_irq_lsi(ICSState *ics, int 
> srcno, int val)
>  ics_resend_lsi(ics, srcno);
>  }
>  
> -void ics_simple_set_irq(void *opaque, int srcno, int val)
> +void ics_set_irq(void *opaque, int srcno, int val)
>  {
>  ICSState *ics = (ICSState *)opaque;
>  
> @@ -467,13 +467,13 @@ void ics_simple_set_irq(void *opaque, int srcno, int 
> val)
>  }
>  
>  if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
> -ics_simple_set_irq_lsi(ics, srcno, val);
> +ics_set_irq_lsi(ics, srcno, val);
>  } else {
> -ics_simple_set_irq_msi(ics, srcno, val);
> +ics_set_irq_msi(ics, srcno, val);
>  }
>  }
>  
> -static void ics_simple_write_xive_msi(ICSState *ics, int srcno)
> +static void ics_write_xive_msi(ICSState *ics, int srcno)
>  {
>  ICSIRQState *irq = ics->irqs + srcno;
>  
> @@ -486,13 +486,13 @@ static void ics_simple_write_xive_msi(ICSState *ics, 
> int srcno)
>  icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
>  }
>  
> -static void ics_simple_write_xive_lsi(ICSState *ics, int srcno)
> +static void ics_write_xive_lsi(ICSState *ics, int srcno)
>  {
>  ics_resend_lsi(ics, srcno);
>  }
>  
> -void ics_simple_write_xive(ICSState *ics, int srcno, int server,
> -   uint8_t priority, uint8_t saved_priority)
> +void ics_write_xive(ICSState *ics, int srcno, int server,
> +uint8_t priority, uint8_t saved_priority)
>  {
>  ICSIRQState *irq = ics->irqs + srcno;
>  
> @@ -500,13 +500,12 @@ void ics_simple_write_xive(ICSState *ics, int srcno, 
> int server,
>  irq->priority = priority;
>  irq->saved_priority = saved_priority;
>  
> -trace_xics_ics_simple_write_xive(ics->offset + srcno, srcno, server,
> - priority);
> +trace_xics_

Re: [PATCH 2/4] xics: Merge reset and realize hooks

2019-09-23 Thread Cédric Le Goater
On 24/09/2019 06:59, David Gibson wrote:
> Currently TYPE_XICS_BASE and TYPE_XICS_SIMPLE have their own reset and
> realize methods, using the standard technique for having the subtype
> call the supertype's methods before doing its own thing.
> 
> But TYPE_XICS_SIMPLE is the only subtype of TYPE_XICS_BASE ever
> instantiated, so there's no point having the split here.  Merge them
> together into just ics_reset() and ics_realize() functions.
> 
> Signed-off-by: David Gibson 


Reviewed-by: Cédric Le Goater 

C.

> ---
>  hw/intc/xics.c| 97 ---
>  include/hw/ppc/xics.h |  3 --
>  2 files changed, 35 insertions(+), 65 deletions(-)
> 
> diff --git a/hw/intc/xics.c b/hw/intc/xics.c
> index 93139b0189..db0e532bd9 100644
> --- a/hw/intc/xics.c
> +++ b/hw/intc/xics.c
> @@ -548,68 +548,13 @@ static void ics_eoi(ICSState *ics, uint32_t nr)
>  }
>  }
>  
> -static void ics_simple_reset(DeviceState *dev)
> -{
> -ICSStateClass *icsc = ICS_BASE_GET_CLASS(dev);
> -
> -icsc->parent_reset(dev);
> -
> -if (kvm_irqchip_in_kernel()) {
> -Error *local_err = NULL;
> -
> -ics_set_kvm_state(ICS_BASE(dev), &local_err);
> -if (local_err) {
> -error_report_err(local_err);
> -}
> -}
> -}
> -
> -static void ics_simple_reset_handler(void *dev)
> -{
> -ics_simple_reset(dev);
> -}
> -
> -static void ics_simple_realize(DeviceState *dev, Error **errp)
> -{
> -ICSState *ics = ICS_SIMPLE(dev);
> -ICSStateClass *icsc = ICS_BASE_GET_CLASS(ics);
> -Error *local_err = NULL;
> -
> -icsc->parent_realize(dev, &local_err);
> -if (local_err) {
> -error_propagate(errp, local_err);
> -return;
> -}
> -
> -qemu_register_reset(ics_simple_reset_handler, ics);
> -}
> -
> -static void ics_simple_class_init(ObjectClass *klass, void *data)
> -{
> -DeviceClass *dc = DEVICE_CLASS(klass);
> -ICSStateClass *isc = ICS_BASE_CLASS(klass);
> -
> -device_class_set_parent_realize(dc, ics_simple_realize,
> -&isc->parent_realize);
> -device_class_set_parent_reset(dc, ics_simple_reset,
> -  &isc->parent_reset);
> -}
> -
> -static const TypeInfo ics_simple_info = {
> -.name = TYPE_ICS_SIMPLE,
> -.parent = TYPE_ICS_BASE,
> -.instance_size = sizeof(ICSState),
> -.class_init = ics_simple_class_init,
> -.class_size = sizeof(ICSStateClass),
> -};
> -
>  static void ics_reset_irq(ICSIRQState *irq)
>  {
>  irq->priority = 0xff;
>  irq->saved_priority = 0xff;
>  }
>  
> -static void ics_base_reset(DeviceState *dev)
> +static void ics_reset(DeviceState *dev)
>  {
>  ICSState *ics = ICS_BASE(dev);
>  int i;
> @@ -625,17 +570,31 @@ static void ics_base_reset(DeviceState *dev)
>  ics_reset_irq(ics->irqs + i);
>  ics->irqs[i].flags = flags[i];
>  }
> +
> +if (kvm_irqchip_in_kernel()) {
> +Error *local_err = NULL;
> +
> +ics_set_kvm_state(ICS_BASE(dev), &local_err);
> +if (local_err) {
> +error_report_err(local_err);
> +}
> +}
> +}
> +
> +static void ics_reset_handler(void *dev)
> +{
> +ics_reset(dev);
>  }
>  
> -static void ics_base_realize(DeviceState *dev, Error **errp)
> +static void ics_realize(DeviceState *dev, Error **errp)
>  {
>  ICSState *ics = ICS_BASE(dev);
> +Error *local_err = NULL;
>  Object *obj;
> -Error *err = NULL;
>  
> -obj = object_property_get_link(OBJECT(dev), ICS_PROP_XICS, &err);
> +obj = object_property_get_link(OBJECT(dev), ICS_PROP_XICS, &local_err);
>  if (!obj) {
> -error_propagate_prepend(errp, err,
> +error_propagate_prepend(errp, local_err,
>  "required link '" ICS_PROP_XICS
>  "' not found: ");
>  return;
> @@ -647,8 +606,22 @@ static void ics_base_realize(DeviceState *dev, Error 
> **errp)
>  return;
>  }
>  ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState));
> +
> +qemu_register_reset(ics_reset_handler, ics);
> +}
> +
> +static void ics_simple_class_init(ObjectClass *klass, void *data)
> +{
>  }
>  
> +static const TypeInfo ics_simple_info = {
> +.name = TYPE_ICS_SIMPLE,
> +.parent = TYPE_ICS_BASE,
> +.instance_size = sizeof(ICSState),
> +.class_init = ics_simple_class_init,
> +.class_size = sizeof(ICSStateClass),
> +};
> +
>  static void ics_base_instance_init(Object *obj)
>  {
>  ICSState *ics = ICS_BASE(obj);
> @@ -725,9 +698,9 @@ static void ics_base_class_init(ObjectClass *klass, void 
> *data)
>  {
>  DeviceClass *dc = DEVICE_CLASS(klass);
>  
> -dc->realize = ics_base_realize;
> +dc->realize = ics_realize;
>  dc->props = ics_base_properties;
> -dc->reset = ics_base_reset;
> +dc->reset = ics_reset;
>  dc->vmsd = &vmstate_ics_base;
>  }
>  
> diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
> i

Re: [PATCH 1/4] xics: Eliminate 'reject', 'resend' and 'eoi' class hooks

2019-09-23 Thread Cédric Le Goater
On 24/09/2019 06:59, David Gibson wrote:
> Currently ics_reject(), ics_resend() and ics_eoi() indirect through
> class methods.  But there's only one implementation of each method,
> the one in TYPE_ICS_SIMPLE.  TYPE_ICS_BASE has no implementation, but
> it's never instantiated, and has no other subtypes.
> 
> So clean up by eliminating the method and just having ics_reject(),
> ics_resend() and ics_eoi() contain the logic directly.
> 
> Signed-off-by: David Gibson 

Reviewed-by: Cédric Le Goater 

C.


> ---
>  hw/intc/trace-events  |  4 ++--
>  hw/intc/xics.c| 54 +++
>  include/hw/ppc/xics.h |  4 
>  3 files changed, 15 insertions(+), 47 deletions(-)
> 
> diff --git a/hw/intc/trace-events b/hw/intc/trace-events
> index 719f46b516..fdc716c2cc 100644
> --- a/hw/intc/trace-events
> +++ b/hw/intc/trace-events
> @@ -70,8 +70,8 @@ xics_ics_simple_set_irq_msi(int srcno, int nr) 
> "set_irq_msi: srcno %d [irq 0x%x]
>  xics_masked_pending(void) "set_irq_msi: masked pending"
>  xics_ics_simple_set_irq_lsi(int srcno, int nr) "set_irq_lsi: srcno %d [irq 
> 0x%x]"
>  xics_ics_simple_write_xive(int nr, int srcno, int server, uint8_t priority) 
> "ics_write_xive: irq 0x%x [src %d] server 0x%x prio 0x%x"
> -xics_ics_simple_reject(int nr, int srcno) "reject irq 0x%x [src %d]"
> -xics_ics_simple_eoi(int nr) "ics_eoi: irq 0x%x"
> +xics_ics_reject(int nr, int srcno) "reject irq 0x%x [src %d]"
> +xics_ics_eoi(int nr) "ics_eoi: irq 0x%x"
>  
>  # s390_flic_kvm.c
>  flic_create_device(int err) "flic: create device failed %d"
> diff --git a/hw/intc/xics.c b/hw/intc/xics.c
> index b2fca2975c..93139b0189 100644
> --- a/hw/intc/xics.c
> +++ b/hw/intc/xics.c
> @@ -98,32 +98,8 @@ void ics_pic_print_info(ICSState *ics, Monitor *mon)
>  #define XISR(icp)   (((icp)->xirr) & XISR_MASK)
>  #define CPPR(icp)   (((icp)->xirr) >> 24)
>  
> -static void ics_reject(ICSState *ics, uint32_t nr)
> -{
> -ICSStateClass *k = ICS_BASE_GET_CLASS(ics);
> -
> -if (k->reject) {
> -k->reject(ics, nr);
> -}
> -}
> -
> -void ics_resend(ICSState *ics)
> -{
> -ICSStateClass *k = ICS_BASE_GET_CLASS(ics);
> -
> -if (k->resend) {
> -k->resend(ics);
> -}
> -}
> -
> -static void ics_eoi(ICSState *ics, int nr)
> -{
> -ICSStateClass *k = ICS_BASE_GET_CLASS(ics);
> -
> -if (k->eoi) {
> -k->eoi(ics, nr);
> -}
> -}
> +static void ics_reject(ICSState *ics, uint32_t nr);
> +static void ics_eoi(ICSState *ics, uint32_t nr);
>  
>  static void icp_check_ipi(ICPState *icp)
>  {
> @@ -427,7 +403,7 @@ Object *icp_create(Object *cpu, const char *type, 
> XICSFabric *xi, Error **errp)
>  /*
>   * ICS: Source layer
>   */
> -static void ics_simple_resend_msi(ICSState *ics, int srcno)
> +static void ics_resend_msi(ICSState *ics, int srcno)
>  {
>  ICSIRQState *irq = ics->irqs + srcno;
>  
> @@ -440,7 +416,7 @@ static void ics_simple_resend_msi(ICSState *ics, int 
> srcno)
>  }
>  }
>  
> -static void ics_simple_resend_lsi(ICSState *ics, int srcno)
> +static void ics_resend_lsi(ICSState *ics, int srcno)
>  {
>  ICSIRQState *irq = ics->irqs + srcno;
>  
> @@ -478,7 +454,7 @@ static void ics_simple_set_irq_lsi(ICSState *ics, int 
> srcno, int val)
>  } else {
>  irq->status &= ~XICS_STATUS_ASSERTED;
>  }
> -ics_simple_resend_lsi(ics, srcno);
> +ics_resend_lsi(ics, srcno);
>  }
>  
>  void ics_simple_set_irq(void *opaque, int srcno, int val)
> @@ -512,7 +488,7 @@ static void ics_simple_write_xive_msi(ICSState *ics, int 
> srcno)
>  
>  static void ics_simple_write_xive_lsi(ICSState *ics, int srcno)
>  {
> -ics_simple_resend_lsi(ics, srcno);
> +ics_resend_lsi(ics, srcno);
>  }
>  
>  void ics_simple_write_xive(ICSState *ics, int srcno, int server,
> @@ -534,11 +510,11 @@ void ics_simple_write_xive(ICSState *ics, int srcno, 
> int server,
>  }
>  }
>  
> -static void ics_simple_reject(ICSState *ics, uint32_t nr)
> +static void ics_reject(ICSState *ics, uint32_t nr)
>  {
>  ICSIRQState *irq = ics->irqs + nr - ics->offset;
>  
> -trace_xics_ics_simple_reject(nr, nr - ics->offset);
> +trace_xics_ics_reject(nr, nr - ics->offset);
>  if (irq->flags & XICS_FLAGS_IRQ_MSI) {
>  irq->status |= XICS_STATUS_REJECTED;
>  } else if (irq->flags & XICS_FLAGS_IRQ_LSI) {
> @@ -546,26 +522,26 @@ static void ics_simple_reject(ICSState *ics, uint32_t 
> nr)
>  }
>  }
>  
> -static void ics_simple_resend(ICSState *ics)
> +void ics_resend(ICSState *ics)
>  {
>  int i;
>  
>  for (i = 0; i < ics->nr_irqs; i++) {
>  /* FIXME: filter by server#? */
>  if (ics->irqs[i].flags & XICS_FLAGS_IRQ_LSI) {
> -ics_simple_resend_lsi(ics, i);
> +ics_resend_lsi(ics, i);
>  } else {
> -ics_simple_resend_msi(ics, i);
> +ics_resend_msi(ics, i);
>  }
>  }
>  }
>  
> -static void ics_simple_eoi(ICSState *ics, uint32_t nr)
> +static void ics_eoi(ICSS

Re: [PATCH 0/4] xics: Eliminate unnecessary class

2019-09-23 Thread Cédric Le Goater
On 24/09/2019 06:59, David Gibson wrote:
> The XICS interrupt controller device used to have separate subtypes
> for the KVM and non-KVM variant of the device.  That was a bad idea,
> because it leaked information that should be entirely host-side
> implementation specific to the kinda-sorta guest visible QOM class
> names.
> 
> We eliminated the KVM specific class some time ago, but it's left
> behind a distinction between the TYPE_ICS_BASE abstract class and
> TYPE_ICS_SIMPLE subtype which no longer serves any purpose.
> 
> This series collapses the two types back into one.

OK. Is it migration compatible ? because this is why we have kept
this subclass. I am glad we can remove it finally. 

Thanks,

C.


> 
> David Gibson (4):
>   xics: Eliminate 'reject', 'resend' and 'eoi' class hooks
>   xics: Merge reset and realize hooks
>   xics: Rename misleading ics_simple_*() functions
>   xics: Merge TYPE_ICS_BASE and TYPE_ICS_SIMPLE classes
> 
>  hw/intc/trace-events  |  10 +-
>  hw/intc/xics.c| 211 ++
>  hw/intc/xics_spapr.c  |  12 +--
>  hw/ppc/pnv_psi.c  |   6 +-
>  hw/ppc/spapr_irq.c|   6 +-
>  include/hw/ppc/xics.h |  30 +-
>  6 files changed, 92 insertions(+), 183 deletions(-)
> 




[PATCH 4/4] xics: Merge TYPE_ICS_BASE and TYPE_ICS_SIMPLE classes

2019-09-23 Thread David Gibson
TYPE_ICS_SIMPLE is the only subtype of TYPE_ICS_BASE that's ever
instantiated, and the only one we're ever likely to want.  The
existence of different classes is just a hang over from when we
(misguidedly) had separate subtypes for the KVM and non-KVM version of
the device.

So, collapse the two classes together into just TYPE_ICS.

Signed-off-by: David Gibson 
---
 hw/intc/xics.c| 57 ---
 hw/ppc/pnv_psi.c  |  2 +-
 hw/ppc/spapr_irq.c|  4 +--
 include/hw/ppc/xics.h | 17 ++---
 4 files changed, 26 insertions(+), 54 deletions(-)

diff --git a/hw/intc/xics.c b/hw/intc/xics.c
index 9ae51bbc76..388dbba870 100644
--- a/hw/intc/xics.c
+++ b/hw/intc/xics.c
@@ -555,7 +555,7 @@ static void ics_reset_irq(ICSIRQState *irq)
 
 static void ics_reset(DeviceState *dev)
 {
-ICSState *ics = ICS_BASE(dev);
+ICSState *ics = ICS(dev);
 int i;
 uint8_t flags[ics->nr_irqs];
 
@@ -573,7 +573,7 @@ static void ics_reset(DeviceState *dev)
 if (kvm_irqchip_in_kernel()) {
 Error *local_err = NULL;
 
-ics_set_kvm_state(ICS_BASE(dev), &local_err);
+ics_set_kvm_state(ICS(dev), &local_err);
 if (local_err) {
 error_report_err(local_err);
 }
@@ -587,7 +587,7 @@ static void ics_reset_handler(void *dev)
 
 static void ics_realize(DeviceState *dev, Error **errp)
 {
-ICSState *ics = ICS_BASE(dev);
+ICSState *ics = ICS(dev);
 Error *local_err = NULL;
 Object *obj;
 
@@ -609,26 +609,14 @@ static void ics_realize(DeviceState *dev, Error **errp)
 qemu_register_reset(ics_reset_handler, ics);
 }
 
-static void ics_simple_class_init(ObjectClass *klass, void *data)
+static void ics_instance_init(Object *obj)
 {
-}
-
-static const TypeInfo ics_simple_info = {
-.name = TYPE_ICS_SIMPLE,
-.parent = TYPE_ICS_BASE,
-.instance_size = sizeof(ICSState),
-.class_init = ics_simple_class_init,
-.class_size = sizeof(ICSStateClass),
-};
-
-static void ics_base_instance_init(Object *obj)
-{
-ICSState *ics = ICS_BASE(obj);
+ICSState *ics = ICS(obj);
 
 ics->offset = XICS_IRQ_BASE;
 }
 
-static int ics_base_pre_save(void *opaque)
+static int ics_pre_save(void *opaque)
 {
 ICSState *ics = opaque;
 
@@ -639,7 +627,7 @@ static int ics_base_pre_save(void *opaque)
 return 0;
 }
 
-static int ics_base_post_load(void *opaque, int version_id)
+static int ics_post_load(void *opaque, int version_id)
 {
 ICSState *ics = opaque;
 
@@ -657,7 +645,7 @@ static int ics_base_post_load(void *opaque, int version_id)
 return 0;
 }
 
-static const VMStateDescription vmstate_ics_base_irq = {
+static const VMStateDescription vmstate_ics_irq = {
 .name = "ics/irq",
 .version_id = 2,
 .minimum_version_id = 1,
@@ -671,46 +659,44 @@ static const VMStateDescription vmstate_ics_base_irq = {
 },
 };
 
-static const VMStateDescription vmstate_ics_base = {
+static const VMStateDescription vmstate_ics = {
 .name = "ics",
 .version_id = 1,
 .minimum_version_id = 1,
-.pre_save = ics_base_pre_save,
-.post_load = ics_base_post_load,
+.pre_save = ics_pre_save,
+.post_load = ics_post_load,
 .fields = (VMStateField[]) {
 /* Sanity check */
 VMSTATE_UINT32_EQUAL(nr_irqs, ICSState, NULL),
 
 VMSTATE_STRUCT_VARRAY_POINTER_UINT32(irqs, ICSState, nr_irqs,
- vmstate_ics_base_irq,
+ vmstate_ics_irq,
  ICSIRQState),
 VMSTATE_END_OF_LIST()
 },
 };
 
-static Property ics_base_properties[] = {
+static Property ics_properties[] = {
 DEFINE_PROP_UINT32("nr-irqs", ICSState, nr_irqs, 0),
 DEFINE_PROP_END_OF_LIST(),
 };
 
-static void ics_base_class_init(ObjectClass *klass, void *data)
+static void ics_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
 
 dc->realize = ics_realize;
-dc->props = ics_base_properties;
+dc->props = ics_properties;
 dc->reset = ics_reset;
-dc->vmsd = &vmstate_ics_base;
+dc->vmsd = &vmstate_ics;
 }
 
-static const TypeInfo ics_base_info = {
-.name = TYPE_ICS_BASE,
+static const TypeInfo ics_info = {
+.name = TYPE_ICS,
 .parent = TYPE_DEVICE,
-.abstract = true,
 .instance_size = sizeof(ICSState),
-.instance_init = ics_base_instance_init,
-.class_init = ics_base_class_init,
-.class_size = sizeof(ICSStateClass),
+.instance_init = ics_instance_init,
+.class_init = ics_class_init,
 };
 
 static const TypeInfo xics_fabric_info = {
@@ -749,8 +735,7 @@ void ics_set_irq_type(ICSState *ics, int srcno, bool lsi)
 
 static void xics_register_types(void)
 {
-type_register_static(&ics_simple_info);
-type_register_static(&ics_base_info);
+type_register_static(&ics_info);
 type_register_static(&icp_info);
 type_register_static(&xics_fabric_info);
 }
diff --git a/hw/ppc/p

[PATCH 2/4] xics: Merge reset and realize hooks

2019-09-23 Thread David Gibson
Currently TYPE_XICS_BASE and TYPE_XICS_SIMPLE have their own reset and
realize methods, using the standard technique for having the subtype
call the supertype's methods before doing its own thing.

But TYPE_XICS_SIMPLE is the only subtype of TYPE_XICS_BASE ever
instantiated, so there's no point having the split here.  Merge them
together into just ics_reset() and ics_realize() functions.

Signed-off-by: David Gibson 
---
 hw/intc/xics.c| 97 ---
 include/hw/ppc/xics.h |  3 --
 2 files changed, 35 insertions(+), 65 deletions(-)

diff --git a/hw/intc/xics.c b/hw/intc/xics.c
index 93139b0189..db0e532bd9 100644
--- a/hw/intc/xics.c
+++ b/hw/intc/xics.c
@@ -548,68 +548,13 @@ static void ics_eoi(ICSState *ics, uint32_t nr)
 }
 }
 
-static void ics_simple_reset(DeviceState *dev)
-{
-ICSStateClass *icsc = ICS_BASE_GET_CLASS(dev);
-
-icsc->parent_reset(dev);
-
-if (kvm_irqchip_in_kernel()) {
-Error *local_err = NULL;
-
-ics_set_kvm_state(ICS_BASE(dev), &local_err);
-if (local_err) {
-error_report_err(local_err);
-}
-}
-}
-
-static void ics_simple_reset_handler(void *dev)
-{
-ics_simple_reset(dev);
-}
-
-static void ics_simple_realize(DeviceState *dev, Error **errp)
-{
-ICSState *ics = ICS_SIMPLE(dev);
-ICSStateClass *icsc = ICS_BASE_GET_CLASS(ics);
-Error *local_err = NULL;
-
-icsc->parent_realize(dev, &local_err);
-if (local_err) {
-error_propagate(errp, local_err);
-return;
-}
-
-qemu_register_reset(ics_simple_reset_handler, ics);
-}
-
-static void ics_simple_class_init(ObjectClass *klass, void *data)
-{
-DeviceClass *dc = DEVICE_CLASS(klass);
-ICSStateClass *isc = ICS_BASE_CLASS(klass);
-
-device_class_set_parent_realize(dc, ics_simple_realize,
-&isc->parent_realize);
-device_class_set_parent_reset(dc, ics_simple_reset,
-  &isc->parent_reset);
-}
-
-static const TypeInfo ics_simple_info = {
-.name = TYPE_ICS_SIMPLE,
-.parent = TYPE_ICS_BASE,
-.instance_size = sizeof(ICSState),
-.class_init = ics_simple_class_init,
-.class_size = sizeof(ICSStateClass),
-};
-
 static void ics_reset_irq(ICSIRQState *irq)
 {
 irq->priority = 0xff;
 irq->saved_priority = 0xff;
 }
 
-static void ics_base_reset(DeviceState *dev)
+static void ics_reset(DeviceState *dev)
 {
 ICSState *ics = ICS_BASE(dev);
 int i;
@@ -625,17 +570,31 @@ static void ics_base_reset(DeviceState *dev)
 ics_reset_irq(ics->irqs + i);
 ics->irqs[i].flags = flags[i];
 }
+
+if (kvm_irqchip_in_kernel()) {
+Error *local_err = NULL;
+
+ics_set_kvm_state(ICS_BASE(dev), &local_err);
+if (local_err) {
+error_report_err(local_err);
+}
+}
+}
+
+static void ics_reset_handler(void *dev)
+{
+ics_reset(dev);
 }
 
-static void ics_base_realize(DeviceState *dev, Error **errp)
+static void ics_realize(DeviceState *dev, Error **errp)
 {
 ICSState *ics = ICS_BASE(dev);
+Error *local_err = NULL;
 Object *obj;
-Error *err = NULL;
 
-obj = object_property_get_link(OBJECT(dev), ICS_PROP_XICS, &err);
+obj = object_property_get_link(OBJECT(dev), ICS_PROP_XICS, &local_err);
 if (!obj) {
-error_propagate_prepend(errp, err,
+error_propagate_prepend(errp, local_err,
 "required link '" ICS_PROP_XICS
 "' not found: ");
 return;
@@ -647,8 +606,22 @@ static void ics_base_realize(DeviceState *dev, Error 
**errp)
 return;
 }
 ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState));
+
+qemu_register_reset(ics_reset_handler, ics);
+}
+
+static void ics_simple_class_init(ObjectClass *klass, void *data)
+{
 }
 
+static const TypeInfo ics_simple_info = {
+.name = TYPE_ICS_SIMPLE,
+.parent = TYPE_ICS_BASE,
+.instance_size = sizeof(ICSState),
+.class_init = ics_simple_class_init,
+.class_size = sizeof(ICSStateClass),
+};
+
 static void ics_base_instance_init(Object *obj)
 {
 ICSState *ics = ICS_BASE(obj);
@@ -725,9 +698,9 @@ static void ics_base_class_init(ObjectClass *klass, void 
*data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
 
-dc->realize = ics_base_realize;
+dc->realize = ics_realize;
 dc->props = ics_base_properties;
-dc->reset = ics_base_reset;
+dc->reset = ics_reset;
 dc->vmsd = &vmstate_ics_base;
 }
 
diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
index 34d7985b7c..0eb39c2561 100644
--- a/include/hw/ppc/xics.h
+++ b/include/hw/ppc/xics.h
@@ -103,9 +103,6 @@ struct PnvICPState {
 
 struct ICSStateClass {
 DeviceClass parent_class;
-
-DeviceRealize parent_realize;
-DeviceReset parent_reset;
 };
 
 struct ICSState {
-- 
2.21.0




Re: [PATCH] target/riscv: Bugfix reserved bits in PTE for RV64

2019-09-23 Thread Alistair Francis
On Mon, Sep 23, 2019 at 10:01 PM  wrote:
>
> From: Guo Ren 
>
> Highest 10 bits of PTE are reserved in riscv-privileged, ref: [1], so we
> need to ignore them. They can not be a part of ppn.
>
> 1: The RISC-V Instruction Set Manual, Volume II: Privileged Architecture
>4.4 Sv39: Page-Based 39-bit Virtual-Memory System
>4.5 Sv48: Page-Based 48-bit Virtual-Memory System
>
> Signed-off-by: Guo Ren 
> Reviewed-by: Liu Zhiwei 
> ---
>  target/riscv/cpu_helper.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 87dd6a6..3c5e8f6 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -260,6 +260,7 @@ restart:
>  target_ulong pte = ldl_phys(cs->as, pte_addr);
>  #elif defined(TARGET_RISCV64)
>  target_ulong pte = ldq_phys(cs->as, pte_addr);
> +pte = pte << 10 >> 10;

You can just AND with a mask instead of shifting both directions.

Alistair

>  #endif
>  hwaddr ppn = pte >> PTE_PPN_SHIFT;
>
> --
> 2.7.4
>



[PATCH] target/riscv: Bugfix reserved bits in PTE for RV64

2019-09-23 Thread guoren
From: Guo Ren 

Highest 10 bits of PTE are reserved in riscv-privileged, ref: [1], so we
need to ignore them. They can not be a part of ppn.

1: The RISC-V Instruction Set Manual, Volume II: Privileged Architecture
   4.4 Sv39: Page-Based 39-bit Virtual-Memory System
   4.5 Sv48: Page-Based 48-bit Virtual-Memory System

Signed-off-by: Guo Ren 
Reviewed-by: Liu Zhiwei 
---
 target/riscv/cpu_helper.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 87dd6a6..3c5e8f6 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -260,6 +260,7 @@ restart:
 target_ulong pte = ldl_phys(cs->as, pte_addr);
 #elif defined(TARGET_RISCV64)
 target_ulong pte = ldq_phys(cs->as, pte_addr);
+pte = pte << 10 >> 10;
 #endif
 hwaddr ppn = pte >> PTE_PPN_SHIFT;
 
-- 
2.7.4




[PATCH 3/4] xics: Rename misleading ics_simple_*() functions

2019-09-23 Thread David Gibson
There are a number of ics_simple_*() functions that aren't actually
specific to TYPE_XICS_SIMPLE at all, and are equally valid on
TYPE_XICS_BASE.  Rename them to ics_*() accordingly.

Signed-off-by: David Gibson 
---
 hw/intc/trace-events  |  6 +++---
 hw/intc/xics.c| 29 ++---
 hw/intc/xics_spapr.c  | 12 ++--
 hw/ppc/pnv_psi.c  |  4 ++--
 hw/ppc/spapr_irq.c|  2 +-
 include/hw/ppc/xics.h |  6 +++---
 6 files changed, 29 insertions(+), 30 deletions(-)

diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index fdc716c2cc..527c3f76ca 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -66,10 +66,10 @@ xics_icp_accept(uint32_t old_xirr, uint32_t new_xirr) 
"icp_accept: XIRR 0x%"PRIx
 xics_icp_eoi(int server, uint32_t xirr, uint32_t new_xirr) "icp_eoi: server %d 
given XIRR 0x%"PRIx32" new XIRR 0x%"PRIx32
 xics_icp_irq(int server, int nr, uint8_t priority) "cpu %d trying to deliver 
irq 0x%"PRIx32" priority 0x%x"
 xics_icp_raise(uint32_t xirr, uint8_t pending_priority) "raising IRQ new 
XIRR=0x%x new pending priority=0x%x"
-xics_ics_simple_set_irq_msi(int srcno, int nr) "set_irq_msi: srcno %d [irq 
0x%x]"
+xics_ics_set_irq_msi(int srcno, int nr) "set_irq_msi: srcno %d [irq 0x%x]"
 xics_masked_pending(void) "set_irq_msi: masked pending"
-xics_ics_simple_set_irq_lsi(int srcno, int nr) "set_irq_lsi: srcno %d [irq 
0x%x]"
-xics_ics_simple_write_xive(int nr, int srcno, int server, uint8_t priority) 
"ics_write_xive: irq 0x%x [src %d] server 0x%x prio 0x%x"
+xics_ics_set_irq_lsi(int srcno, int nr) "set_irq_lsi: srcno %d [irq 0x%x]"
+xics_ics_write_xive(int nr, int srcno, int server, uint8_t priority) 
"ics_write_xive: irq 0x%x [src %d] server 0x%x prio 0x%x"
 xics_ics_reject(int nr, int srcno) "reject irq 0x%x [src %d]"
 xics_ics_eoi(int nr) "ics_eoi: irq 0x%x"
 
diff --git a/hw/intc/xics.c b/hw/intc/xics.c
index db0e532bd9..9ae51bbc76 100644
--- a/hw/intc/xics.c
+++ b/hw/intc/xics.c
@@ -428,11 +428,11 @@ static void ics_resend_lsi(ICSState *ics, int srcno)
 }
 }
 
-static void ics_simple_set_irq_msi(ICSState *ics, int srcno, int val)
+static void ics_set_irq_msi(ICSState *ics, int srcno, int val)
 {
 ICSIRQState *irq = ics->irqs + srcno;
 
-trace_xics_ics_simple_set_irq_msi(srcno, srcno + ics->offset);
+trace_xics_ics_set_irq_msi(srcno, srcno + ics->offset);
 
 if (val) {
 if (irq->priority == 0xff) {
@@ -444,11 +444,11 @@ static void ics_simple_set_irq_msi(ICSState *ics, int 
srcno, int val)
 }
 }
 
-static void ics_simple_set_irq_lsi(ICSState *ics, int srcno, int val)
+static void ics_set_irq_lsi(ICSState *ics, int srcno, int val)
 {
 ICSIRQState *irq = ics->irqs + srcno;
 
-trace_xics_ics_simple_set_irq_lsi(srcno, srcno + ics->offset);
+trace_xics_ics_set_irq_lsi(srcno, srcno + ics->offset);
 if (val) {
 irq->status |= XICS_STATUS_ASSERTED;
 } else {
@@ -457,7 +457,7 @@ static void ics_simple_set_irq_lsi(ICSState *ics, int 
srcno, int val)
 ics_resend_lsi(ics, srcno);
 }
 
-void ics_simple_set_irq(void *opaque, int srcno, int val)
+void ics_set_irq(void *opaque, int srcno, int val)
 {
 ICSState *ics = (ICSState *)opaque;
 
@@ -467,13 +467,13 @@ void ics_simple_set_irq(void *opaque, int srcno, int val)
 }
 
 if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
-ics_simple_set_irq_lsi(ics, srcno, val);
+ics_set_irq_lsi(ics, srcno, val);
 } else {
-ics_simple_set_irq_msi(ics, srcno, val);
+ics_set_irq_msi(ics, srcno, val);
 }
 }
 
-static void ics_simple_write_xive_msi(ICSState *ics, int srcno)
+static void ics_write_xive_msi(ICSState *ics, int srcno)
 {
 ICSIRQState *irq = ics->irqs + srcno;
 
@@ -486,13 +486,13 @@ static void ics_simple_write_xive_msi(ICSState *ics, int 
srcno)
 icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
 }
 
-static void ics_simple_write_xive_lsi(ICSState *ics, int srcno)
+static void ics_write_xive_lsi(ICSState *ics, int srcno)
 {
 ics_resend_lsi(ics, srcno);
 }
 
-void ics_simple_write_xive(ICSState *ics, int srcno, int server,
-   uint8_t priority, uint8_t saved_priority)
+void ics_write_xive(ICSState *ics, int srcno, int server,
+uint8_t priority, uint8_t saved_priority)
 {
 ICSIRQState *irq = ics->irqs + srcno;
 
@@ -500,13 +500,12 @@ void ics_simple_write_xive(ICSState *ics, int srcno, int 
server,
 irq->priority = priority;
 irq->saved_priority = saved_priority;
 
-trace_xics_ics_simple_write_xive(ics->offset + srcno, srcno, server,
- priority);
+trace_xics_ics_write_xive(ics->offset + srcno, srcno, server, priority);
 
 if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
-ics_simple_write_xive_lsi(ics, srcno);
+ics_write_xive_lsi(ics, srcno);
 } else {
-ics_simple_write_xive_msi(ics, srcno);
+ics_write_xive_msi(ics, srcno);
 }
 }
 
diff --git

[PATCH 1/4] xics: Eliminate 'reject', 'resend' and 'eoi' class hooks

2019-09-23 Thread David Gibson
Currently ics_reject(), ics_resend() and ics_eoi() indirect through
class methods.  But there's only one implementation of each method,
the one in TYPE_ICS_SIMPLE.  TYPE_ICS_BASE has no implementation, but
it's never instantiated, and has no other subtypes.

So clean up by eliminating the method and just having ics_reject(),
ics_resend() and ics_eoi() contain the logic directly.

Signed-off-by: David Gibson 
---
 hw/intc/trace-events  |  4 ++--
 hw/intc/xics.c| 54 +++
 include/hw/ppc/xics.h |  4 
 3 files changed, 15 insertions(+), 47 deletions(-)

diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index 719f46b516..fdc716c2cc 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -70,8 +70,8 @@ xics_ics_simple_set_irq_msi(int srcno, int nr) "set_irq_msi: 
srcno %d [irq 0x%x]
 xics_masked_pending(void) "set_irq_msi: masked pending"
 xics_ics_simple_set_irq_lsi(int srcno, int nr) "set_irq_lsi: srcno %d [irq 
0x%x]"
 xics_ics_simple_write_xive(int nr, int srcno, int server, uint8_t priority) 
"ics_write_xive: irq 0x%x [src %d] server 0x%x prio 0x%x"
-xics_ics_simple_reject(int nr, int srcno) "reject irq 0x%x [src %d]"
-xics_ics_simple_eoi(int nr) "ics_eoi: irq 0x%x"
+xics_ics_reject(int nr, int srcno) "reject irq 0x%x [src %d]"
+xics_ics_eoi(int nr) "ics_eoi: irq 0x%x"
 
 # s390_flic_kvm.c
 flic_create_device(int err) "flic: create device failed %d"
diff --git a/hw/intc/xics.c b/hw/intc/xics.c
index b2fca2975c..93139b0189 100644
--- a/hw/intc/xics.c
+++ b/hw/intc/xics.c
@@ -98,32 +98,8 @@ void ics_pic_print_info(ICSState *ics, Monitor *mon)
 #define XISR(icp)   (((icp)->xirr) & XISR_MASK)
 #define CPPR(icp)   (((icp)->xirr) >> 24)
 
-static void ics_reject(ICSState *ics, uint32_t nr)
-{
-ICSStateClass *k = ICS_BASE_GET_CLASS(ics);
-
-if (k->reject) {
-k->reject(ics, nr);
-}
-}
-
-void ics_resend(ICSState *ics)
-{
-ICSStateClass *k = ICS_BASE_GET_CLASS(ics);
-
-if (k->resend) {
-k->resend(ics);
-}
-}
-
-static void ics_eoi(ICSState *ics, int nr)
-{
-ICSStateClass *k = ICS_BASE_GET_CLASS(ics);
-
-if (k->eoi) {
-k->eoi(ics, nr);
-}
-}
+static void ics_reject(ICSState *ics, uint32_t nr);
+static void ics_eoi(ICSState *ics, uint32_t nr);
 
 static void icp_check_ipi(ICPState *icp)
 {
@@ -427,7 +403,7 @@ Object *icp_create(Object *cpu, const char *type, 
XICSFabric *xi, Error **errp)
 /*
  * ICS: Source layer
  */
-static void ics_simple_resend_msi(ICSState *ics, int srcno)
+static void ics_resend_msi(ICSState *ics, int srcno)
 {
 ICSIRQState *irq = ics->irqs + srcno;
 
@@ -440,7 +416,7 @@ static void ics_simple_resend_msi(ICSState *ics, int srcno)
 }
 }
 
-static void ics_simple_resend_lsi(ICSState *ics, int srcno)
+static void ics_resend_lsi(ICSState *ics, int srcno)
 {
 ICSIRQState *irq = ics->irqs + srcno;
 
@@ -478,7 +454,7 @@ static void ics_simple_set_irq_lsi(ICSState *ics, int 
srcno, int val)
 } else {
 irq->status &= ~XICS_STATUS_ASSERTED;
 }
-ics_simple_resend_lsi(ics, srcno);
+ics_resend_lsi(ics, srcno);
 }
 
 void ics_simple_set_irq(void *opaque, int srcno, int val)
@@ -512,7 +488,7 @@ static void ics_simple_write_xive_msi(ICSState *ics, int 
srcno)
 
 static void ics_simple_write_xive_lsi(ICSState *ics, int srcno)
 {
-ics_simple_resend_lsi(ics, srcno);
+ics_resend_lsi(ics, srcno);
 }
 
 void ics_simple_write_xive(ICSState *ics, int srcno, int server,
@@ -534,11 +510,11 @@ void ics_simple_write_xive(ICSState *ics, int srcno, int 
server,
 }
 }
 
-static void ics_simple_reject(ICSState *ics, uint32_t nr)
+static void ics_reject(ICSState *ics, uint32_t nr)
 {
 ICSIRQState *irq = ics->irqs + nr - ics->offset;
 
-trace_xics_ics_simple_reject(nr, nr - ics->offset);
+trace_xics_ics_reject(nr, nr - ics->offset);
 if (irq->flags & XICS_FLAGS_IRQ_MSI) {
 irq->status |= XICS_STATUS_REJECTED;
 } else if (irq->flags & XICS_FLAGS_IRQ_LSI) {
@@ -546,26 +522,26 @@ static void ics_simple_reject(ICSState *ics, uint32_t nr)
 }
 }
 
-static void ics_simple_resend(ICSState *ics)
+void ics_resend(ICSState *ics)
 {
 int i;
 
 for (i = 0; i < ics->nr_irqs; i++) {
 /* FIXME: filter by server#? */
 if (ics->irqs[i].flags & XICS_FLAGS_IRQ_LSI) {
-ics_simple_resend_lsi(ics, i);
+ics_resend_lsi(ics, i);
 } else {
-ics_simple_resend_msi(ics, i);
+ics_resend_msi(ics, i);
 }
 }
 }
 
-static void ics_simple_eoi(ICSState *ics, uint32_t nr)
+static void ics_eoi(ICSState *ics, uint32_t nr)
 {
 int srcno = nr - ics->offset;
 ICSIRQState *irq = ics->irqs + srcno;
 
-trace_xics_ics_simple_eoi(nr);
+trace_xics_ics_eoi(nr);
 
 if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
 irq->status &= ~XICS_STATUS_SENT;
@@ -617,10 +593,6 @@ static void ics_simple_class_init(ObjectClass *klass, void 
*data)
  

[PATCH 0/4] xics: Eliminate unnecessary class

2019-09-23 Thread David Gibson
The XICS interrupt controller device used to have separate subtypes
for the KVM and non-KVM variant of the device.  That was a bad idea,
because it leaked information that should be entirely host-side
implementation specific to the kinda-sorta guest visible QOM class
names.

We eliminated the KVM specific class some time ago, but it's left
behind a distinction between the TYPE_ICS_BASE abstract class and
TYPE_ICS_SIMPLE subtype which no longer serves any purpose.

This series collapses the two types back into one.

David Gibson (4):
  xics: Eliminate 'reject', 'resend' and 'eoi' class hooks
  xics: Merge reset and realize hooks
  xics: Rename misleading ics_simple_*() functions
  xics: Merge TYPE_ICS_BASE and TYPE_ICS_SIMPLE classes

 hw/intc/trace-events  |  10 +-
 hw/intc/xics.c| 211 ++
 hw/intc/xics_spapr.c  |  12 +--
 hw/ppc/pnv_psi.c  |   6 +-
 hw/ppc/spapr_irq.c|   6 +-
 include/hw/ppc/xics.h |  30 +-
 6 files changed, 92 insertions(+), 183 deletions(-)

-- 
2.21.0




Re: [PATCH 3/4] hw/arm: Move armv7m_nvic.c to hw/arm/ and always enable it for arm builds

2019-09-23 Thread Thomas Huth
On 23/09/2019 20.50, Peter Maydell wrote:
> On Mon, 23 Sep 2019 at 19:36, Thomas Huth  wrote:
>>
>> On 23/09/2019 20.27, Peter Maydell wrote:
>>> On Mon, 23 Sep 2019 at 18:54, Thomas Huth  wrote:
 Ok, then what would you suggest to solve the problem that this file has
 always to be linked into the binary? I can't use "obj-y += ..." in
 hw/intc/Makefile.objs since that would mean that the file also gets
 compiled for non-Arm boards. Would you prefer a bunch of stubs instead
 that get used if CONFIG_ARM_V7M is not set?
>>>
>>> I thought obj-y was for only-this-target and obj-common-y was
>>> for all-boards ?
>>
>> Well, obj-y is for the current target that gets compiled. But if you use
>> it in a Makefile that gets used by all targets, the file gets compiled
>> for each target individually.
>>
>> Just try to change "obj-$(CONFIG_ARM_V7M) += armv7m_nvic.o" into
>> "obj-y += armv7m_nvic.o" in hw/int/Makefile.objs, and you'll see it break:
>>
>>   CC  alpha-softmmu/hw/intc/armv7m_nvic.o
>> In file included from include/hw/intc/armv7m_nvic.h:13,
>>  from hw/intc/armv7m_nvic.c:19:
>> target/arm/cpu.h:1416: error: "FPCR_DZE" redefined [-Werror]
>>  #define FPCR_DZE(1 << 9)/* Divide by Zero exception trap enable */
> 
> Sure, so don't define CONFIG_ARM_V7M in a default-config for
> a non-Arm architecture. Then you get the behaviour you want:
> the file is compiled only for the arm targets.

Sigh, the point of this series is that it should also possible to
compile *without* CONFIG_ARM_V7M in default-configs if you want (and
yes, there are people out there who want to be able to compile a
minimalistic QEMU). It's currently not possible to disable this switch.
But ok, if you're not really interested in providing a possibility to
make qemu-system-arm a little bit more flexible in this regard, never
mind, I'll look into other issues instead.

 Thomas




Re: [PATCH v2] numa: Introduce MachineClass::auto_enable_numa for implicit NUMA node

2019-09-23 Thread Tao Xu

Hi Eduardo,

How about this version of patch? Last month this patch is reverted from 
pull request. And I submitted this version.


Tao

On 9/5/2019 4:32 PM, Xu, Tao3 wrote:

Add MachineClass::auto_enable_numa field. When it is true, a NUMA node
is expected to be created implicitly.

Acked-by: David Gibson 
Suggested-by: Igor Mammedov 
Suggested-by: Eduardo Habkost 
Reviewed-by: Igor Mammedov 
Signed-off-by: Tao Xu 
---

Note: Parameter -numa node,mem is deprecated too. So I set
"numa_info[0].node_mem = ram_size" instead of
"NumaNodeOptions node = { .mem = ram_size }".

Changes in v2:
 - Fix the qtest error, avoid using numa_auto_assign_ram.
---
  hw/core/numa.c  | 10 --
  hw/ppc/spapr.c  |  9 +
  include/hw/boards.h |  1 +
  3 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/hw/core/numa.c b/hw/core/numa.c
index 4dfec5c95b..038c96d4ab 100644
--- a/hw/core/numa.c
+++ b/hw/core/numa.c
@@ -378,11 +378,17 @@ void numa_complete_configuration(MachineState *ms)
   *   guest tries to use it with that drivers.
   *
   * Enable NUMA implicitly by adding a new NUMA node automatically.
+ *
+ * Or if MachineClass::auto_enable_numa is true and no NUMA nodes,
+ * assume there is just one node with whole RAM.
   */
-if (ms->ram_slots > 0 && ms->numa_state->num_nodes == 0 &&
-mc->auto_enable_numa_with_memhp) {
+if (ms->numa_state->num_nodes == 0 &&
+((ms->ram_slots > 0 &&
+mc->auto_enable_numa_with_memhp) ||
+mc->auto_enable_numa)) {
  NumaNodeOptions node = { };
  parse_numa_node(ms, &node, &error_abort);
+numa_info[0].node_mem = ram_size;
  }
  
  assert(max_numa_nodeid <= MAX_NODES);

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 222a325056..f760e0f5d7 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -405,14 +405,6 @@ static int spapr_populate_memory(SpaprMachineState *spapr, 
void *fdt)
  hwaddr mem_start, node_size;
  int i, nb_nodes = machine->numa_state->num_nodes;
  NodeInfo *nodes = machine->numa_state->nodes;
-NodeInfo ramnode;
-
-/* No NUMA nodes, assume there is just one node with whole RAM */
-if (!nb_nodes) {
-nb_nodes = 1;
-ramnode.node_mem = machine->ram_size;
-nodes = &ramnode;
-}
  
  for (i = 0, mem_start = 0; i < nb_nodes; ++i) {

  if (!nodes[i].node_mem) {
@@ -4477,6 +4469,7 @@ static void spapr_machine_class_init(ObjectClass *oc, 
void *data)
   */
  mc->numa_mem_align_shift = 28;
  mc->numa_mem_supported = true;
+mc->auto_enable_numa = true;
  
  smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF;

  smc->default_caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_ON;
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 2289536e48..481e69388e 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -221,6 +221,7 @@ struct MachineClass {
  bool smbus_no_migration_support;
  bool nvdimm_supported;
  bool numa_mem_supported;
+bool auto_enable_numa;
  
  HotplugHandler *(*get_hotplug_handler)(MachineState *machine,

 DeviceState *dev);






Re: [PATCH 0/2] kvm: clear dirty bitmaps from all overlapping memslots

2019-09-23 Thread Peter Xu
On Mon, Sep 23, 2019 at 06:49:12PM +0200, Paolo Bonzini wrote:
> On 23/09/19 18:15, Igor Mammedov wrote:
> > Yep, commit message doesn't fit patch, how about following description:
> > "
> > Currently MemoryRegionSection has 1:1 mapping to KVMSlot.
> > However next patch will allow splitting MemoryRegionSection into
> > several KVMSlot-s, make sure that kvm_physical_log_slot_clear()
> > is able to handle such 1:N mapping.
> > "
> 
> Yes, that's great.

Please feel free to add my r-b directly on patch 2 with that amended.

Thanks,

-- 
Peter Xu



Re: illegal hardware instruction during MIPS-I ELF linux useremulation

2019-09-23 Thread Libo Zhou
> I would start by using the QEMU gdbstub to connect a
> MIPS-aware gdb. Then when the SIGILL arrives you can see
> what instruction the guest program was trying to execute.

Just tried it and found something interesting.
I connected gdb-multiarch to QEMU gdbstub. gdb-multiarch's architecture was set 
to mips:3000 automatically (and Wikipedia says r3k uses MIPS-I).

When I did 'layout asm', and compared the instructions displayed against test.s 
generated by my mipsel-linux-unknown-gcc, they appeared to be a little bit 
different.

The 'store word' instruction in test.s is shown as a hex '0x7f..(don't 
remember the rest)';
'load word' is shown as '0x5f..';
'load immediate' is seen as 'addi';
'j' as 'jr';

When I single-stepped the instructions, the SIGILL was thrown immediately after 
the first unrecognized 0x7f.., which is supposed to be a store word (sw).

Hence, can I conclude that MIPS-I is not implemented in QEMU out of the box?


EDIT: Or my compiler isn't implementing MIPS-I correctly because 
gdb-multiarch's r3k doesn't recognize some hexes?

Re: illegal hardware instruction during MIPS-I ELF linux useremulation

2019-09-23 Thread Libo Zhou
> I would start by using the QEMU gdbstub to connect a
> MIPS-aware gdb. Then when the SIGILL arrives you can see
> what instruction the guest program was trying to execute.

Just tried it and found something interesting.
I connected gdb-multiarch to QEMU gdbstub. gdb-multiarch's architecture was set 
to mips:3000 automatically (and Wikipedia says r3k uses MIPS-I).

When I did 'layout asm', and compared the instructions displayed against test.s 
generated by my mipsel-linux-unknown-gcc, they appeared to be a little bit 
different.

The 'store word' instruction in test.s is shown as a hex '0x7f..(don't 
remember the rest)';
'load word' is shown as '0x5f..';
'load immediate' is seen as 'addi';
'j' as 'jr';

When I single-stepped the instructions, the SIGILL was thrown immediately after 
the first unrecognized 0x7f.., which is supposed to be a store word (sw).

Hence, can I conclude that MIPS-I is not implemented in QEMU out of the box? Or 
is it possible that my compiler doesn't implement MIPS-I correctly?

Re: illegal hardware instruction during MIPS-I ELF linux useremulation

2019-09-23 Thread Libo Zhou
> I would start by using the QEMU gdbstub to connect a
> MIPS-aware gdb. Then when the SIGILL arrives you can see
> what instruction the guest program was trying to execute.

Just tried it and found something interesting.
I connected gdb-multiarch to QEMU gdbstub. gdb-multiarch's architecture was set 
to mips:3000 automatically (and Wikipedia says r3k uses MIPS-I).

When I did 'layout asm', and compared the instructions displayed against test.s 
generated by my mipsel-linux-unknown-gcc, they appeared to be a little bit 
different.

The 'store word' instruction in test.s is shown as a hex '0x7f..(don't 
remember the rest)';
'load word' is shown as '0x5f..';
'load immediate' is seen as 'addi';
'j' as 'jr';

When I single-stepped the instructions, the SIGILL was thrown immediately after 
the first unrecognized 0x7f.., which is supposed to be a store word (sw).
 
Hence, can I conclude that MIPS-I is not implemented in QEMU out of the box?

RE: [PATCH v8 01/13] vfio: KABI for migration interface

2019-09-23 Thread Tian, Kevin
> From: Tian, Kevin
> Sent: Friday, September 13, 2019 7:00 AM
> 
> > From: Alex Williamson [mailto:alex.william...@redhat.com]
> > Sent: Thursday, September 12, 2019 10:41 PM
> >
> > On Tue, 3 Sep 2019 06:57:27 +
> > "Tian, Kevin"  wrote:
> >
> > > > From: Alex Williamson [mailto:alex.william...@redhat.com]
> > > > Sent: Saturday, August 31, 2019 12:33 AM
> > > >
> > > > On Fri, 30 Aug 2019 08:06:32 +
> > > > "Tian, Kevin"  wrote:
> > > >
> > > > > > From: Tian, Kevin
> > > > > > Sent: Friday, August 30, 2019 3:26 PM
> > > > > >
> > > > > [...]
> > > > > > > How does QEMU handle the fact that IOVAs are potentially
> > dynamic
> > > > while
> > > > > > > performing the live portion of a migration?  For example, each
> > time a
> > > > > > > guest driver calls dma_map_page() or dma_unmap_page(), a
> > > > > > > MemoryRegionSection pops in or out of the AddressSpace for
> the
> > device
> > > > > > > (I'm assuming a vIOMMU where the device AddressSpace is not
> > > > > > > system_memory).  I don't see any QEMU code that intercepts
> that
> > > > change
> > > > > > > in the AddressSpace such that the IOVA dirty pfns could be
> > recorded and
> > > > > > > translated to GFNs.  The vendor driver can't track these beyond
> > getting
> > > > > > > an unmap notification since it only knows the IOVA pfns, which
> > can be
> > > > > > > re-used with different GFN backing.  Once the DMA mapping is
> > torn
> > > > down,
> > > > > > > it seems those dirty pfns are lost in the ether.  If this works in
> > QEMU,
> > > > > > > please help me find the code that handles it.
> > > > > >
> > > > > > I'm curious about this part too. Interestingly, I didn't find any
> > log_sync
> > > > > > callback registered by emulated devices in Qemu. Looks dirty
> pages
> > > > > > by emulated DMAs are recorded in some implicit way. But KVM
> > always
> > > > > > reports dirty page in GFN instead of IOVA, regardless of the
> > presence of
> > > > > > vIOMMU. If Qemu also tracks dirty pages in GFN for emulated
> DMAs
> > > > > >  (translation can be done when DMA happens), then we don't
> need
> > > > > > worry about transient mapping from IOVA to GFN. Along this way
> > we
> > > > > > also want GFN-based dirty bitmap being reported through VFIO,
> > > > > > similar to what KVM does. For vendor drivers, it needs to translate
> > > > > > from IOVA to HVA to GFN when tracking DMA activities on VFIO
> > > > > > devices. IOVA->HVA is provided by VFIO. for HVA->GFN, it can be
> > > > > > provided by KVM but I'm not sure whether it's exposed now.
> > > > > >
> > > > >
> > > > > HVA->GFN can be done through hva_to_gfn_memslot in kvm_host.h.
> > > >
> > > > I thought it was bad enough that we have vendor drivers that depend
> > on
> > > > KVM, but designing a vfio interface that only supports a KVM interface
> > > > is more undesirable.  I also note without comment that
> > gfn_to_memslot()
> > > > is a GPL symbol.  Thanks,
> > >
> > > yes it is bad, but sometimes inevitable. If you recall our discussions
> > > back to 3yrs (when discussing the 1st mdev framework), there were
> > similar
> > > hypervisor dependencies in GVT-g, e.g. querying gpa->hpa when
> > > creating some shadow structures. gpa->hpa is definitely hypervisor
> > > specific knowledge, which is easy in KVM (gpa->hva->hpa), but needs
> > > hypercall in Xen. but VFIO already makes assumption based on KVM-
> > > only flavor when implementing vfio_{un}pin_page_external.
> >
> > Where's the KVM assumption there?  The MAP_DMA ioctl takes an IOVA
> > and
> > HVA.  When an mdev vendor driver calls vfio_pin_pages(), we GUP the
> HVA
> > to get an HPA and provide an array of HPA pfns back to the caller.  The
> > other vGPU mdev vendor manages to make use of this without KVM... the
> > KVM interface used by GVT-g is GPL-only.
> 
> To be clear it's the assumption on the host-based hypervisors e.g. KVM.
> GUP is a perfect example, which doesn't work for Xen since DomU's
> memory doesn't belong to Dom0. VFIO in Dom0 has to find the HPA
> through Xen specific hypercalls.
> 
> >
> > > So GVT-g
> > > has to maintain an internal abstraction layer to support both Xen and
> > > KVM. Maybe someday we will re-consider introducing some hypervisor
> > > abstraction layer in VFIO, if this issue starts to hurt other devices and
> > > Xen guys are willing to support VFIO.
> >
> > Once upon a time, we had a KVM specific device assignment interface,
> > ie. legacy KVM devie assignment.  We developed VFIO specifically to get
> > KVM out of the business of being a (bad) device driver.  We do have
> > some awareness and interaction between VFIO and KVM in the vfio-kvm
> > pseudo device, but we still try to keep those interfaces generic.  In
> > some cases we're not very successful at that, see vfio_group_set_kvm(),
> > but that's largely just a mechanism to associate a cookie with a group
> > to be consumed by the mdev vendor driver such that it can work with
> kvm
> > external to vfio.  I don't intend to

RE: [Qemu-devel] vhost, iova, and dirty page tracking

2019-09-23 Thread Tian, Kevin
> From: Jason Wang [mailto:jasow...@redhat.com]
> Sent: Friday, September 20, 2019 9:19 AM
> 
> On 2019/9/20 上午6:54, Tian, Kevin wrote:
> >> From: Paolo Bonzini [mailto:pbonz...@redhat.com]
> >> Sent: Thursday, September 19, 2019 7:14 PM
> >>
> >> On 19/09/19 09:16, Tian, Kevin wrote:
> > why GPA1 and GPA2 should be both dirty?
> > even they have the same HVA due to overlaping virtual address
> space
> >> in
> > two processes, they still correspond to two physical pages.
> > don't get what's your meaning :)
>  The point is not leave any corner case that is hard to debug or fix in
>  the future.
> 
>  Let's just start by a single process, the API allows userspace to maps
>  HVA to both GPA1 and GPA2. Since it knows GPA1 and GPA2 are
> >> equivalent,
>  it's ok to sync just through GPA1. That means if you only log GPA2, it
>  won't work.
> >>> I noted KVM itself doesn't consider such situation (one HVA is mapped
> >>> to multiple GPAs), when doing its dirty page tracking. If you look at
> >>> kvm_vcpu_mark_page_dirty, it simply finds the unique memslot which
> >>> contains the dirty gfn and then set the dirty bit within that slot. It
> >>> doesn't attempt to walk all memslots to find out any other GPA which
> >>> may be mapped to the same HVA.
> >>>
> >>> So there must be some disconnect here. let's hear from Paolo first and
> >>> understand the rationale behind such situation.
> >> In general, userspace cannot assume that it's okay to sync just through
> >> GPA1.  It must sync the host page if *either* GPA1 or GPA2 are marked
> >> dirty.
> > Agree. In this case the kernel only needs to track whether GPA1 or
> > GPA2 is dirtied by guest operations.
> 
> 
> Not necessarily guest operations.
> 
> 
> >   The reason why vhost has to
> > set both GPA1 and GPA2 is due to its own design - it maintains
> > IOVA->HVA and GPA->HVA mappings thus given a IOVA you have
> > to reverse lookup GPA->HVA memTable which gives multiple possible
> > GPAs.
> 
> 
> So if userspace need to track both GPA1 and GPA2, vhost can just stop
> when it found a one HVA->GPA mapping there.
> 
> 
> >   But in concept if vhost can maintain a IOVA->GPA mapping,
> > then it is straightforward to set the right GPA every time when a IOVA
> > is tracked.
> 
> 
> That means, the translation is done twice by software, IOVA->GPA and
> GPA->HVA for each packet.
> 
> Thanks
> 

yes, it's not necessary if we care about only the content of the dirty GPA,
as seen in live migration. In that case, just setting the first GPA in the loop
is sufficient as you pointed out. However there is one corner case which I'm
not sure. What about an usage (e.g. VM introspection) which cares only 
about the guest access pattern i.e. which GPA is dirtied instead of poking
its content? Neither setting the first GPA nor setting all the aliasing GPAs
can provide the accurate info, if no explicit IOVA->GPA mapping is maintained
inside vhost. But I cannot tell whether maintaining such accuracy for aliasing
GPAs is really necessary. +VM introspection guys if they have some opinions.

Thanks
Kevin



Re: [PULL 0/7] Python (acceptance tests) queue - 2019-09-23

2019-09-23 Thread no-reply
Patchew URL: https://patchew.org/QEMU/20190923134019.8548-1-cr...@redhat.com/



Hi,

This series seems to have some coding style problems. See output below for
more information:

Message-id: 20190923134019.8548-1-cr...@redhat.com
Subject: [PULL 0/7] Python (acceptance tests) queue - 2019-09-23
Type: series

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

Switched to a new branch 'test'
95d8aed Acceptance tests: use avocado.utils.ssh for SSH interaction
b5d62a1 tests/acceptance: Add new test cases in linux_ssh_mips_malta.py
41b8da1 tests/acceptance: Refactor and improve reporting in 
linux_ssh_mips_malta.py
9dbf0de Acceptance test x86_cpu_model_versions: split into smaller tests
a3bdbf3 Acceptance test x86_cpu_model_versions: fix mismatches between test and 
messages
4423807 Acceptance test x86_cpu_model_versions: shutdown VMs
e3d4392 Acceptance test machine_m68k_nextcube.py: relax the error code pattern

=== OUTPUT BEGIN ===
1/7 Checking commit e3d43927ffb3 (Acceptance test machine_m68k_nextcube.py: 
relax the error code pattern)
2/7 Checking commit 44238078fcde (Acceptance test x86_cpu_model_versions: 
shutdown VMs)
3/7 Checking commit a3bdbf35dd33 (Acceptance test x86_cpu_model_versions: fix 
mismatches between test and messages)
ERROR: line over 90 characters
#25: FILE: tests/acceptance/x86_cpu_model_versions.py:283:
+ 'pc-i440fx-4.0 + Cascadelake-Server-v1 should not 
have arch-capabilities')

ERROR: line over 90 characters
#34: FILE: tests/acceptance/x86_cpu_model_versions.py:292:
+ 'pc-i440fx-4.0 + Cascadelake-Server-v2 should have 
arch-capabilities')

ERROR: line over 90 characters
#42: FILE: tests/acceptance/x86_cpu_model_versions.py:299:
+vm.add_args('-cpu', 
'Cascadelake-Server-v1,x-force-features=on,check=off,enforce=off,+arch-capabilities')

total: 3 errors, 0 warnings, 24 lines checked

Patch 3/7 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

4/7 Checking commit 9dbf0de5f7d5 (Acceptance test x86_cpu_model_versions: split 
into smaller tests)
5/7 Checking commit 41b8da1921af (tests/acceptance: Refactor and improve 
reporting in linux_ssh_mips_malta.py)
6/7 Checking commit b5d62a1def54 (tests/acceptance: Add new test cases in 
linux_ssh_mips_malta.py)
7/7 Checking commit 95d8aed259c8 (Acceptance tests: use avocado.utils.ssh for 
SSH interaction)
WARNING: line over 80 characters
#126: FILE: tests/acceptance/linux_ssh_mips_malta.py:85:
+stdout_lines = [line.rstrip() for line in 
result.stdout_text.splitlines()]

WARNING: line over 80 characters
#130: FILE: tests/acceptance/linux_ssh_mips_malta.py:88:
+stderr_lines = [line.rstrip() for line in 
result.stderr_text.splitlines()]

total: 0 errors, 2 warnings, 158 lines checked

Patch 7/7 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
=== OUTPUT END ===

Test command exited with code: 1


The full log is available at
http://patchew.org/logs/20190923134019.8548-1-cr...@redhat.com/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-de...@redhat.com

Re: [Qemu-devel] [PATCH 4/4] target/arm: Add support for DC CVAP & DC CVADP ins

2019-09-23 Thread Alex Bennée


Beata Michalska  writes:

> ARMv8.2 introduced support for Data Cache Clean instructions
> to PoP (point-of-persistence) - DC CVAP and PoDP (point-of-deep-persistence)
> - DV CVADP. Both specify conceptual points in a memory system where all writes
> that are to reach them are considered persistent.
> The support provided considers both to be actually the same so there is no
> distinction between the two. If none is available (there is no backing store
> for given memory) both will result in Data Cache Clean up to the point of
> coherency. Otherwise sync for the specified range shall be performed.
>
> Signed-off-by: Beata Michalska 
> ---
>  linux-user/elfload.c   | 18 +-
>  target/arm/cpu.h   | 13 -
>  target/arm/cpu64.c |  1 +
>  target/arm/helper.c| 24 
>  target/arm/helper.h|  1 +
>  target/arm/op_helper.c | 36 
>  target/arm/translate-a64.c |  5 +
>  7 files changed, 96 insertions(+), 2 deletions(-)
>
> diff --git a/linux-user/elfload.c b/linux-user/elfload.c
> index 3365e192eb..1ec00308d5 100644
> --- a/linux-user/elfload.c
> +++ b/linux-user/elfload.c
> @@ -609,7 +609,12 @@ enum {
>  ARM_HWCAP_A64_PACG  = 1UL << 31,
>  };
>
> +enum {
> +ARM_HWCAP2_A64_DCPODP   = 1 << 0,
> +};
> +
>  #define ELF_HWCAP get_elf_hwcap()
> +#define ELF_HWCAP2 get_elf_hwcap2()
>
>  static uint32_t get_elf_hwcap(void)
>  {
> @@ -644,12 +649,23 @@ static uint32_t get_elf_hwcap(void)
>  GET_FEATURE_ID(aa64_jscvt, ARM_HWCAP_A64_JSCVT);
>  GET_FEATURE_ID(aa64_sb, ARM_HWCAP_A64_SB);
>  GET_FEATURE_ID(aa64_condm_4, ARM_HWCAP_A64_FLAGM);
> +GET_FEATURE_ID(aa64_dcpop, ARM_HWCAP_A64_DCPOP);
>
> -#undef GET_FEATURE_ID
>
>  return hwcaps;
>  }
>
> +static uint32_t get_elf_hwcap2(void)
> +{
> +ARMCPU *cpu = ARM_CPU(thread_cpu);
> +uint32_t hwcaps = 0;
> +
> +GET_FEATURE_ID(aa64_dcpodp, ARM_HWCAP2_A64_DCPODP);
> +return hwcaps;
> +}
> +
> +#undef GET_FEATURE_ID
> +
>  #endif /* not TARGET_AARCH64 */
>  #endif /* TARGET_ARM */
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 297ad5e47a..1713d76590 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -2229,7 +2229,8 @@ static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid)
>  #define ARM_CP_NZCV  (ARM_CP_SPECIAL | 0x0300)
>  #define ARM_CP_CURRENTEL (ARM_CP_SPECIAL | 0x0400)
>  #define ARM_CP_DC_ZVA(ARM_CP_SPECIAL | 0x0500)
> -#define ARM_LAST_SPECIAL ARM_CP_DC_ZVA
> +#define ARM_CP_DC_CVAP   (ARM_CP_SPECIAL | 0x0600)
> +#define ARM_LAST_SPECIAL ARM_CP_DC_CVAP
>  #define ARM_CP_FPU   0x1000
>  #define ARM_CP_SVE   0x2000
>  #define ARM_CP_NO_GDB0x4000
> @@ -3572,6 +3573,16 @@ static inline bool isar_feature_aa64_frint(const 
> ARMISARegisters *id)
>  return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FRINTTS) != 0;
>  }
>
> +static inline bool isar_feature_aa64_dcpop(const ARMISARegisters *id)
> +{
> +return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, DPB) != 0;
> +}
> +
> +static inline bool isar_feature_aa64_dcpodp(const ARMISARegisters *id)
> +{
> +return (FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, DPB) >> 1) != 0;
> +}
> +
>  static inline bool isar_feature_aa64_fp16(const ARMISARegisters *id)
>  {
>  /* We always set the AdvSIMD and FP fields identically wrt FP16.  */
> diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
> index d7f5bf610a..20094f980d 100644
> --- a/target/arm/cpu64.c
> +++ b/target/arm/cpu64.c
> @@ -331,6 +331,7 @@ static void aarch64_max_initfn(Object *obj)
>  cpu->isar.id_aa64isar0 = t;
>
>  t = cpu->isar.id_aa64isar1;
> +t = FIELD_DP64(t, ID_AA64ISAR1, DPB, 2);
>  t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 1);
>  t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 1);
>  t = FIELD_DP64(t, ID_AA64ISAR1, APA, 1); /* PAuth, architected only 
> */
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 507026c915..99ae01b7e7 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -3843,6 +3843,22 @@ static CPAccessResult aa64_cacheop_access(CPUARMState 
> *env,
>  return CP_ACCESS_OK;
>  }
>
> +static CPAccessResult aa64_cacheop_persist_access(CPUARMState *env,
> +  const ARMCPRegInfo *ri,
> +  bool isread)
> +{
> +ARMCPU *cpu = env_archcpu(env);
> +/*
> + * Access is UNDEF if lacking implementation for either DC CVAP or DC 
> CVADP
> + * DC CVAP ->  CRm: 0xc
> + * DC CVADP -> CRm: 0xd
> + */
> +return (ri->crm == 0xc && !cpu_isar_feature(aa64_dcpop, cpu)) ||
> +   (ri->crm == 0xd && !cpu_isar_feature(aa64_dcpodp, cpu))
> +   ? CP_ACCESS_TRAP_UNCATEGORIZED
> +   : aa64_cacheop_access(env, ri, isread);
> +}
> +
>  /* See: D4.7.2 TLB maintenance requirements 

Re: illegal hardware instruction during MIPS-I ELF linux useremulation

2019-09-23 Thread Libo Zhou
> Can you run QEMU with some debugging options:

> qemu-mipsel -d in_asm,exec,cpu,unimp,guest_errors,nochain -D debug.log
> -singlestep test

> and then put the resulting debug.log somewhere we can get it?
> (it'll probably be quite large)

The logging only shows this little information. It seems like only -d cpu works 
for a short while.


IN: main
0x00400090:  bovc   sp,sp,0x400014

Trace 0: 0x563b750f7100 [/00400090/0xe2] main
pc=0x00400090 HI=0x LO=0x ds 00e2  0
GPR00: r0  at  v0  v1 
GPR04: a0  a1  a2  a3 
GPR08: t0  t1  t2  t3 
GPR12: t4  t5  t6  t7 
GPR16: s0  s1  s2  s3 
GPR20: s4  s5  s6  s7 
GPR24: t8  t9  k0  k1 
GPR28: gp  sp 7090 s8  ra 
CP0 Status  0x2410 Cause   0x EPC0x
Config0 0x8482 Config1 0x9e190c8f LLAddr 0x
Config2 0x8000 Config3 0x
Config4 0x Config5 0x

IN: main
0x00400094:  dmult.gzero,sp,s8

Trace 0: 0x563b750f7240 [/00400094/0xe2] main
pc=0x00400094 HI=0x LO=0x ds 00e2  0
GPR00: r0  at  v0  v1 
GPR04: a0  a1  a2  a3 
GPR08: t0  t1  t2  t3 
GPR12: t4  t5  t6  t7 
GPR16: s0  s1  s2  s3 
GPR20: s4  s5  s6  s7 
GPR24: t8  t9  k0  k1 
GPR28: gp  sp 7070 s8  ra 
CP0 Status  0x2410 Cause   0x EPC0x
Config0 0x8482 Config1 0x9e190c8f LLAddr 0x
Config2 0x8000 Config3 0x
Config4 0x Config5 0x

[PATCH v4 2/2] target/i386: drop the duplicated definition of cpuid AVX512_VBMI marco

2019-09-23 Thread Tao Xu
Drop the duplicated definition of cpuid AVX512_VBMI and marco and
rename it as CPUID_7_0_ECX_AVX512_VBMI. And rename CPUID_7_0_ECX_VBMI2
as CPUID_7_0_ECX_AVX512_VBMI2.

Signed-off-by: Tao Xu 
---
 target/i386/cpu.c   | 8 
 target/i386/cpu.h   | 5 ++---
 target/i386/hvf/x86_cpuid.c | 2 +-
 3 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 9e0bac31e8..71034aeb5a 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -2412,8 +2412,8 @@ static X86CPUDefinition builtin_x86_defs[] = {
 CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX |
 CPUID_7_0_EBX_SMAP,
 .features[FEAT_7_0_ECX] =
-CPUID_7_0_ECX_VBMI | CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_PKU |
-CPUID_7_0_ECX_VBMI2 | CPUID_7_0_ECX_GFNI |
+CPUID_7_0_ECX_AVX512_VBMI | CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_PKU 
|
+CPUID_7_0_ECX_AVX512_VBMI2 | CPUID_7_0_ECX_GFNI |
 CPUID_7_0_ECX_VAES | CPUID_7_0_ECX_VPCLMULQDQ |
 CPUID_7_0_ECX_AVX512VNNI | CPUID_7_0_ECX_AVX512BITALG |
 CPUID_7_0_ECX_AVX512_VPOPCNTDQ,
@@ -2470,8 +2470,8 @@ static X86CPUDefinition builtin_x86_defs[] = {
 CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512CD |
 CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT,
 .features[FEAT_7_0_ECX] =
-CPUID_7_0_ECX_VBMI | CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_PKU |
-CPUID_7_0_ECX_VBMI2 | CPUID_7_0_ECX_GFNI |
+CPUID_7_0_ECX_AVX512_VBMI | CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_PKU 
|
+CPUID_7_0_ECX_AVX512_VBMI2 | CPUID_7_0_ECX_GFNI |
 CPUID_7_0_ECX_VAES | CPUID_7_0_ECX_VPCLMULQDQ |
 CPUID_7_0_ECX_AVX512VNNI | CPUID_7_0_ECX_AVX512BITALG |
 CPUID_7_0_ECX_AVX512_VPOPCNTDQ | CPUID_7_0_ECX_LA57,
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index fa4c4cad79..8e090acd74 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -695,8 +695,7 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
 #define CPUID_7_0_EBX_AVX512VL  (1U << 31)
 
 /* AVX-512 Vector Byte Manipulation Instruction */
-#define CPUID_7_0_ECX_AVX512BMI (1U << 1)
-#define CPUID_7_0_ECX_VBMI  (1U << 1)
+#define CPUID_7_0_ECX_AVX512_VBMI   (1U << 1)
 /* User-Mode Instruction Prevention */
 #define CPUID_7_0_ECX_UMIP  (1U << 2)
 /* Protection Keys for User-mode Pages */
@@ -704,7 +703,7 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
 /* OS Enable Protection Keys */
 #define CPUID_7_0_ECX_OSPKE (1U << 4)
 /* Additional AVX-512 Vector Byte Manipulation Instruction */
-#define CPUID_7_0_ECX_VBMI2 (1U << 6)
+#define CPUID_7_0_ECX_AVX512_VBMI2  (1U << 6)
 /* Galois Field New Instructions */
 #define CPUID_7_0_ECX_GFNI  (1U << 8)
 /* Vector AES Instructions */
diff --git a/target/i386/hvf/x86_cpuid.c b/target/i386/hvf/x86_cpuid.c
index 4d957fe896..16762b6eb4 100644
--- a/target/i386/hvf/x86_cpuid.c
+++ b/target/i386/hvf/x86_cpuid.c
@@ -89,7 +89,7 @@ uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx,
 ebx &= ~CPUID_7_0_EBX_INVPCID;
 }
 
-ecx &= CPUID_7_0_ECX_AVX512BMI | CPUID_7_0_ECX_AVX512_VPOPCNTDQ;
+ecx &= CPUID_7_0_ECX_AVX512_VBMI | CPUID_7_0_ECX_AVX512_VPOPCNTDQ;
 edx &= CPUID_7_0_EDX_AVX512_4VNNIW | CPUID_7_0_EDX_AVX512_4FMAPS;
 } else {
 ebx = 0;
-- 
2.20.1




[PATCH v4 0/2] target/i386: cpu.h marcos clean up

2019-09-23 Thread Tao Xu
Add some comments, clean up comments over 80 chars per line. And there
is an extra line in comment of CPUID_8000_0008_EBX_WBNOINVD, remove
the extra enter and spaces.

Drop the duplicated definition of cpuid AVX512_VBMI marco and rename it
as CPUID_7_0_ECX_AVX512_VBMI. And rename CPUID_7_0_ECX_VBMI2
as CPUID_7_0_ECX_AVX512_VBMI2.

Changelog:
v4:
- rename CPUID_7_0_ECX_VBMI2 as CPUID_7_0_ECX_AVX512_VBMI2.
  (Suggested by Stefano Garzarella)
v3:
- split the patch into 2 patches. (Suggested by Stefano Garzarella
  and Eduardo Habkost)
v2:
- correct the comments over 80 chars per line. (Suggested by
  Philippe Mathieu-Daudé)

Tao Xu (2):
  target/i386: clean up comments over 80 chars per line
  target/i386: drop the duplicated definition of cpuid AVX512_VBMI marco

 target/i386/cpu.c   |   8 +-
 target/i386/cpu.h   | 163 +++-
 target/i386/hvf/x86_cpuid.c |   2 +-
 3 files changed, 111 insertions(+), 62 deletions(-)

-- 
2.20.1




[PATCH v4 1/2] target/i386: clean up comments over 80 chars per line

2019-09-23 Thread Tao Xu
Add some comments, clean up comments over 80 chars per line. And there
is an extra line in comment of CPUID_8000_0008_EBX_WBNOINVD, remove
the extra enter and spaces.

Acked-by: Stefano Garzarella 
Signed-off-by: Tao Xu 
---
 target/i386/cpu.h | 164 ++
 1 file changed, 107 insertions(+), 57 deletions(-)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 5f6e3a029a..fa4c4cad79 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -641,63 +641,113 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
 #define CPUID_SVM_PAUSEFILTER  (1U << 10)
 #define CPUID_SVM_PFTHRESHOLD  (1U << 12)
 
-#define CPUID_7_0_EBX_FSGSBASE (1U << 0)
-#define CPUID_7_0_EBX_BMI1 (1U << 3)
-#define CPUID_7_0_EBX_HLE  (1U << 4)
-#define CPUID_7_0_EBX_AVX2 (1U << 5)
-#define CPUID_7_0_EBX_SMEP (1U << 7)
-#define CPUID_7_0_EBX_BMI2 (1U << 8)
-#define CPUID_7_0_EBX_ERMS (1U << 9)
-#define CPUID_7_0_EBX_INVPCID  (1U << 10)
-#define CPUID_7_0_EBX_RTM  (1U << 11)
-#define CPUID_7_0_EBX_MPX  (1U << 14)
-#define CPUID_7_0_EBX_AVX512F  (1U << 16) /* AVX-512 Foundation */
-#define CPUID_7_0_EBX_AVX512DQ (1U << 17) /* AVX-512 Doubleword & Quadword 
Instrs */
-#define CPUID_7_0_EBX_RDSEED   (1U << 18)
-#define CPUID_7_0_EBX_ADX  (1U << 19)
-#define CPUID_7_0_EBX_SMAP (1U << 20)
-#define CPUID_7_0_EBX_AVX512IFMA (1U << 21) /* AVX-512 Integer Fused Multiply 
Add */
-#define CPUID_7_0_EBX_PCOMMIT  (1U << 22) /* Persistent Commit */
-#define CPUID_7_0_EBX_CLFLUSHOPT (1U << 23) /* Flush a Cache Line Optimized */
-#define CPUID_7_0_EBX_CLWB (1U << 24) /* Cache Line Write Back */
-#define CPUID_7_0_EBX_INTEL_PT (1U << 25) /* Intel Processor Trace */
-#define CPUID_7_0_EBX_AVX512PF (1U << 26) /* AVX-512 Prefetch */
-#define CPUID_7_0_EBX_AVX512ER (1U << 27) /* AVX-512 Exponential and 
Reciprocal */
-#define CPUID_7_0_EBX_AVX512CD (1U << 28) /* AVX-512 Conflict Detection */
-#define CPUID_7_0_EBX_SHA_NI   (1U << 29) /* SHA1/SHA256 Instruction 
Extensions */
-#define CPUID_7_0_EBX_AVX512BW (1U << 30) /* AVX-512 Byte and Word 
Instructions */
-#define CPUID_7_0_EBX_AVX512VL (1U << 31) /* AVX-512 Vector Length Extensions 
*/
-
-#define CPUID_7_0_ECX_AVX512BMI (1U << 1)
-#define CPUID_7_0_ECX_VBMI (1U << 1)  /* AVX-512 Vector Byte Manipulation 
Instrs */
-#define CPUID_7_0_ECX_UMIP (1U << 2)
-#define CPUID_7_0_ECX_PKU  (1U << 3)
-#define CPUID_7_0_ECX_OSPKE(1U << 4)
-#define CPUID_7_0_ECX_VBMI2(1U << 6) /* Additional VBMI Instrs */
-#define CPUID_7_0_ECX_GFNI (1U << 8)
-#define CPUID_7_0_ECX_VAES (1U << 9)
-#define CPUID_7_0_ECX_VPCLMULQDQ (1U << 10)
-#define CPUID_7_0_ECX_AVX512VNNI (1U << 11)
-#define CPUID_7_0_ECX_AVX512BITALG (1U << 12)
-#define CPUID_7_0_ECX_AVX512_VPOPCNTDQ (1U << 14) /* POPCNT for vectors of 
DW/QW */
-#define CPUID_7_0_ECX_LA57 (1U << 16)
-#define CPUID_7_0_ECX_RDPID(1U << 22)
-#define CPUID_7_0_ECX_CLDEMOTE (1U << 25)  /* CLDEMOTE Instruction */
-#define CPUID_7_0_ECX_MOVDIRI  (1U << 27)  /* MOVDIRI Instruction */
-#define CPUID_7_0_ECX_MOVDIR64B (1U << 28) /* MOVDIR64B Instruction */
-
-#define CPUID_7_0_EDX_AVX512_4VNNIW (1U << 2) /* AVX512 Neural Network 
Instructions */
-#define CPUID_7_0_EDX_AVX512_4FMAPS (1U << 3) /* AVX512 Multiply Accumulation 
Single Precision */
-#define CPUID_7_0_EDX_SPEC_CTRL (1U << 26) /* Speculation Control */
-#define CPUID_7_0_EDX_ARCH_CAPABILITIES (1U << 29)  /*Arch Capabilities*/
-#define CPUID_7_0_EDX_CORE_CAPABILITY   (1U << 30)  /*Core Capability*/
-#define CPUID_7_0_EDX_SPEC_CTRL_SSBD  (1U << 31) /* Speculative Store Bypass 
Disable */
-
-#define CPUID_7_1_EAX_AVX512_BF16 (1U << 5) /* AVX512 BFloat16 Instruction */
-
-#define CPUID_8000_0008_EBX_WBNOINVD  (1U << 9)  /* Write back and
- 
do not invalidate cache */
-#define CPUID_8000_0008_EBX_IBPB(1U << 12) /* Indirect Branch Prediction 
Barrier */
+/* Support RDFSBASE/RDGSBASE/WRFSBASE/WRGSBASE */
+#define CPUID_7_0_EBX_FSGSBASE  (1U << 0)
+/* 1st Group of Advanced Bit Manipulation Extensions */
+#define CPUID_7_0_EBX_BMI1  (1U << 3)
+/* Hardware Lock Elision */
+#define CPUID_7_0_EBX_HLE   (1U << 4)
+/* Intel Advanced Vector Extensions 2 */
+#define CPUID_7_0_EBX_AVX2  (1U << 5)
+/* Supervisor-mode Execution Prevention */
+#define CPUID_7_0_EBX_SMEP  (1U << 7)
+/* 2nd Group of Advanced Bit Manipulation Extensions */
+#define CPUID_7_0_EBX_BMI2  (1U << 8)
+/* Enhanced REP MOVSB/STOSB */
+#define CPUID_7_0_EBX_ERMS  (1U << 9)
+/* Invalidate Process-Context Identifier */
+#define CPUID_7_0_EBX_INVPCID   (1U << 10)
+/* Restricted Transactional Memory */
+#define CPUID_7_0_EBX_RTM   (1U << 11)
+/* Memory Protection Extension */
+#define CPUID_7_0_EBX_MPX   (1U << 14)
+/* AVX-512 Foundation */
+#define CPUID_7_0_EBX_AVX512F  

Re: [PATCH v1 4/6] riscv/sifive_u: Add the start-in-flash property

2019-09-23 Thread Bin Meng
On Tue, Sep 24, 2019 at 1:51 AM Alistair Francis  wrote:
>
> On Sat, Sep 21, 2019 at 7:19 PM Bin Meng  wrote:
> >
> > On Sat, Sep 21, 2019 at 6:12 AM Alistair Francis  
> > wrote:
> > >
> > > On Thu, Sep 19, 2019 at 10:15 PM Bin Meng  wrote:
> > > >
> > > > On Fri, Sep 20, 2019 at 6:32 AM Alistair Francis
> > > >  wrote:
> > > > >
> > > > > Add a property that when set to true QEMU will jump from the ROM code 
> > > > > to
> > > > > the start of flash memory instead of DRAM which is the default
> > > > > behaviour.
> > > > >
> > > > > Signed-off-by: Alistair Francis 
> > > > > ---
> > > > >  hw/riscv/sifive_u.c | 27 +++
> > > > >  include/hw/riscv/sifive_u.h |  2 ++
> > > > >  2 files changed, 29 insertions(+)
> > > > >
> > > > > diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
> > > > > index c3949fb316..b7cd3631cd 100644
> > > > > --- a/hw/riscv/sifive_u.c
> > > > > +++ b/hw/riscv/sifive_u.c
> > > > > @@ -373,6 +373,10 @@ static void riscv_sifive_u_init(MachineState 
> > > > > *machine)
> > > > > /* dtb: */
> > > > >  };
> > > > >
> > > > > +if (s->start_in_flash) {
> > > > > +reset_vec[6] = memmap[SIFIVE_U_FLASH0].base; /* start: 
> > > > > .dword FLASH0_BASE */
> > > > > +}
> > > > > +
> > > > >  /* copy in the reset vector in little_endian byte order */
> > > > >  for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
> > > > >  reset_vec[i] = cpu_to_le32(reset_vec[i]);
> > > > > @@ -544,8 +548,31 @@ static void 
> > > > > riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp)
> > > > >  memmap[SIFIVE_U_GEM_MGMT].base, 
> > > > > memmap[SIFIVE_U_GEM_MGMT].size);
> > > > >  }
> > > > >
> > > > > +static bool virt_get_start_in_flash(Object *obj, Error **errp)
> > > > > +{
> > > > > +SiFiveUState *s = RISCV_U_MACHINE(obj);
> > > > > +
> > > > > +return s->start_in_flash;
> > > > > +}
> > > > > +
> > > > > +static void virt_set_start_in_flash(Object *obj, bool value, Error 
> > > > > **errp)
> > > > > +{
> > > > > +SiFiveUState *s = RISCV_U_MACHINE(obj);
> > > > > +
> > > > > +s->start_in_flash = value;
> > > > > +}
> > > > > +
> > > > >  static void riscv_sifive_u_machine_instance_init(Object *obj)
> > > > >  {
> > > > > +SiFiveUState *s = RISCV_U_MACHINE(obj);
> > > > > +
> > > > > +s->start_in_flash = false;
> > > > > +object_property_add_bool(obj, "start-in-flash", 
> > > > > virt_get_start_in_flash,
> > > > > + virt_set_start_in_flash, NULL);
> > > > > +object_property_set_description(obj, "start-in-flash",
> > > > > +"Set on to tell QEMU's ROM to 
> > > > > jump to " \
> > > > > +"flash. Otherwise QEMU will jump 
> > > > > to DRAM",
> > > > > +NULL);
> > > > >
> > > > >  }
> > > > >
> > > > > diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h
> > > > > index a921079fbe..2656b43c58 100644
> > > > > --- a/include/hw/riscv/sifive_u.h
> > > > > +++ b/include/hw/riscv/sifive_u.h
> > > > > @@ -57,6 +57,8 @@ typedef struct SiFiveUState {
> > > > >
> > > > >  void *fdt;
> > > > >  int fdt_size;
> > > > > +
> > > > > +bool start_in_flash;
> > > > >  } SiFiveUState;
> > > > >
> > > > >  enum {
> > > >
> > > > This patch chose a different way from the one used in patch "[v1,6/6]
> > > > riscv/virt: Jump to pflash if specified":
> > > >
> > > > - this patch uses reset_vec[6] while patch [6/6] defines a variable 
> > > > start_addr
> > > > - this patch adds a "start-in-flash" property to the machine, while
> > > > patch [6/6] tests against drive IF_PFLASH
> > >
> > > Yes, we do it differently for the sifive_u board as the sifive_u board
> > > doesn't use pflash so there is no way to know if the user has loaded
> > > anything into the SPI memory.
> > >
> >
> > OK.
> >
> > > >
> > > > We should be consistent and I would prefer to use the patch [6/6] way.
> > > > On Unleashed an SPI flash is mounted so we cannot add a PFlash to
> > > > sifive_u machine like what was done on virt machine, so we should test
> > > > IF_MTD instead. Thoughts?
> > >
> > > How would we test that?
> > >
> > > Right now I am loading the binary in SPI with the -device loader
> > > option. The machine can't really know what is/isn't loaded there.
> > >
> > > It's not ideal, but I don't see a nicer way.
> >
> > I think we need write a SiFive SPI model to support this in a clean
> > way. Ideally we should simulate the hardware boot workflow as
> > documented in the FU540 manual chapter 6 "Boot Process".
>
> I really didn't want to do this. For me it's low priority and there
> are enough other things to work on rather then adding SiFive device
> models. Maybe someone who works at SiFive would be able to do this?
>
> My hope with this series is that we could unblock firmware developers
> (oreboot and coreboot) while the SPI model is 

Re: [PATCH v4 21/24] paaudio: channel-map option

2019-09-23 Thread Zoltán Kővágó

On 2019-09-23 15:12, Markus Armbruster wrote:

"Kővágó, Zoltán"  writes:


Add an option to change the channel map used by pulseaudio.  If not
specified, falls back to an OSS compatible channel map.

Signed-off-by: Kővágó, Zoltán 
---
  audio/paaudio.c | 18 ++
  qapi/audio.json |  7 +--
  qemu-options.hx |  9 +
  3 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/audio/paaudio.c b/audio/paaudio.c
index d195b1caa8..20402b0718 100644
--- a/audio/paaudio.c
+++ b/audio/paaudio.c
@@ -338,17 +338,27 @@ static pa_stream *qpa_simple_new (
  pa_stream_direction_t dir,
  const char *dev,
  const pa_sample_spec *ss,
-const pa_channel_map *map,
+const char *map,
  const pa_buffer_attr *attr,
  int *rerror)
  {
  int r;
  pa_stream *stream;
  pa_stream_flags_t flags;
+pa_channel_map pa_map;
  
  pa_threaded_mainloop_lock(c->mainloop);
  
-stream = pa_stream_new(c->context, name, ss, map);

+if (map && !pa_channel_map_parse(&pa_map, map)) {
+dolog("Invalid channel map specified: '%s'\n", map);
+map = NULL;
+}
+if (!map) {
+pa_channel_map_init_extend(&pa_map, ss->channels,
+   PA_CHANNEL_MAP_OSS);
+}
+
+stream = pa_stream_new(c->context, name, ss, &pa_map);
  if (!stream) {
  goto fail;
  }
@@ -421,7 +431,7 @@ static int qpa_init_out(HWVoiceOut *hw, struct audsettings 
*as,
  PA_STREAM_PLAYBACK,
  ppdo->has_name ? ppdo->name : NULL,
  &ss,
-NULL,   /* channel map */
+ppdo->has_channel_map ? ppdo->channel_map : NULL,
  &ba,/* buffering attributes */
  &error
  );
@@ -470,7 +480,7 @@ static int qpa_init_in(HWVoiceIn *hw, struct audsettings 
*as, void *drv_opaque)
  PA_STREAM_RECORD,
  ppdo->has_name ? ppdo->name : NULL,
  &ss,
-NULL,   /* channel map */
+ppdo->has_channel_map ? ppdo->channel_map : NULL,
  &ba,/* buffering attributes */
  &error
  );
diff --git a/qapi/audio.json b/qapi/audio.json
index 0535eff794..07003808cb 100644
--- a/qapi/audio.json
+++ b/qapi/audio.json
@@ -214,13 +214,16 @@
  # @latency: latency you want PulseAudio to achieve in microseconds
  #   (default 15000)
  #
+# @channel-map: channel map to use (default: OSS compatible map, since: 4.2)
+#
  # Since: 4.0
  ##
  { 'struct': 'AudiodevPaPerDirectionOptions',
'base': 'AudiodevPerDirectionOptions',
'data': {
-'*name': 'str',
-'*latency': 'uint32' } }
+'*name':'str',
+'*latency': 'uint32',
+'*channel-map': 'str' } }
  
  ##

  # @AudiodevPaOptions:
diff --git a/qemu-options.hx b/qemu-options.hx
index 395427422a..f3bc342f98 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -471,6 +471,7 @@ DEF("audiodev", HAS_ARG, QEMU_OPTION_audiodev,
  "-audiodev pa,id=id[,prop[=value][,...]]\n"
  "server= PulseAudio server address\n"
  "in|out.name= source/sink device name\n"
+"in|out.channel-map= channel map to use\n"
  #endif
  #ifdef CONFIG_AUDIO_SDL
  "-audiodev sdl,id=id[,prop[=value][,...]]\n"
@@ -636,6 +637,14 @@ Sets the PulseAudio @var{server} to connect to.
  @item in|out.name=@var{sink}
  Use the specified source/sink for recording/playback.
  
+@item in|out.channel-map=@var{map}

+Use the specified channel map.  The default is an OSS compatible
+channel map.  Do not forget to escape commas inside the map:


Awkward.


+
+@example
+-audiodev pa,id=example,sink.channel-map=front-left,,front-right
+@end example


Makes me realize new AudiodevPaPerDirectionOptions member @channel-map
is a list encoded in a string.  QAPI heavily frowns upon encoding stuff
in strings.  Any reason why you can't (or don't want to) make it
['str']?


Hmm, I don't think it's used too frequently on structs parsed by qapi 
opts visitor. What would be the command line format in that case? 
Something like this?


-audiodev 
pa,id=example,sink.channel-map=front-left,sink.channel-map=front-right


I think it's simply a string because while conceptually it's a string, 
we don't try to interpret it, we just pass the string to 
pa_channel_map_parse.  Of course we could take a list and instead either 
rebuild the string or reimplement half of pa_channel_map_parse by 
manually calling pa_channel_position_from_string.
Oh now that I looked again at the pulseaudio docs, channel-map doesn't 
have to be a list, it can be also a "well-known mapping name".





+
  @end table
  
  @item -audiodev sdl,id=@var{id}[,@var{prop}[=@var{value}][,...]]





Re: [PATCH v4 15/24] audio: add mixing-engine option (documentation)

2019-09-23 Thread Zoltán Kővágó

On 2019-09-23 15:08, Markus Armbruster wrote:

"Kővágó, Zoltán"  writes:


This will allow us to disable mixeng when we use a decent backend.

Disabling mixeng have a few advantages:
* we no longer convert the audio output from one format to another, when
   the underlying audio system would just convert it to a third format.
   We no longer convert, only the underlying system, when needed.
* the underlying system probably has better resampling and sample format
   converting methods anyway...
* we may support formats that the mixeng currently does not support (S24
   or float samples, more than two channels)
* when using an audio server (like pulseaudio) different sound card
   outputs will show up as separate streams, even if we use only one
   backend

Disadvantages:
* audio capturing no longer works (wavcapture, and vnc audio extension)
* some backends only support a single playback stream or very picky
   about the audio format.  In this case we can't disable mixeng.

However mixeng is not removed, only made optional, so this shouldn't be
a big concern.

Signed-off-by: Kővágó, Zoltán 
---

Notes:
 Changes from v1:
 
 * renamed mixeng to mixing-engine


  qapi/audio.json | 5 +
  qemu-options.hx | 6 ++
  2 files changed, 11 insertions(+)

diff --git a/qapi/audio.json b/qapi/audio.json
index 9fefdf5186..0535eff794 100644
--- a/qapi/audio.json
+++ b/qapi/audio.json
@@ -11,6 +11,10 @@
  # General audio backend options that are used for both playback and
  # recording.
  #
+# @mixing-engine: use QEMU's mixing engine to mix all streams inside QEMU. When
+# set to off, fixed-settings must be also off. Not every 
backend
+# compatible with the off setting (default on, since 4.2)
+#


Last sentence no verb.

Which backends are compatible?


Actually that's a simplification, it depends on a few things.  When 
mixeng is off, qemu will try to use the same format as the emulated 
sound card, and if the backend doesn't support that format, it won't 
work (no audio).  Also attaching multiple sound cards to the same 
audiodev might not work, if the backend doesn't support multiple 
playback streams.  If you use pulseaudio, it'll work without problems, 
if you use alsa, it depends on your device.  If you use a hw: device 
directly, you'll likely only be able to use one emulated sound card with 
a few selected audio formats.  If you use dmix: (and plug), alsa will 
handle the conversion and mixing, so it will work no matter what format 
the emulated sound card uses.  With OSS the situation is probably 
similar, it depends on the kernel/hw what works and what not.  wav and 
spice certainly doesn't support multiple streams.  I'm not completely 
sure about the other backends right now, but I think dsound and 
coreaudio can handle the necessary sample format conversions and mixing.



What happens when you try the off setting with incompatible backends?

See above.




  # @fixed-settings: use fixed settings for host input/output. When off,
  #  frequency, channels and format must not be
  #  specified (default true)
@@ -31,6 +35,7 @@
  ##
  { 'struct': 'AudiodevPerDirectionOptions',
'data': {
+'*mixing-engine':  'bool',
  '*fixed-settings': 'bool',
  '*frequency':  'uint32',
  '*channels':   'uint32',
diff --git a/qemu-options.hx b/qemu-options.hx
index bbfd936d29..395427422a 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -433,6 +433,7 @@ DEF("audiodev", HAS_ARG, QEMU_OPTION_audiodev,
  "specifies the audio backend to use\n"
  "id= identifier of the backend\n"
  "timer-period= timer period in microseconds\n"
+"in|out.mixing-engine= use mixing engine to mix streams inside 
QEMU\n"
  "in|out.fixed-settings= use fixed settings for host 
audio\n"
  "in|out.frequency= frequency to use with fixed settings\n"
  "in|out.channels= number of channels to use with fixed 
settings\n"
@@ -503,6 +504,11 @@ Identifies the audio backend.
  Sets the timer @var{period} used by the audio subsystem in microseconds.
  Default is 1 (10 ms).
  
+@item in|out.mixing-engine=on|off

+Use QEMU's mixing engine to mix all streams inside QEMU.  When off,
+@var{fixed-settings} must be off too.  Not every backend is fully
+compatible with the off setting.  Default is on.
+
  @item in|out.fixed-settings=on|off
  Use fixed settings for host audio.  When off, it will change based on
  how the guest opens the sound card.  In this case you must not specify





Re: Migration failure when running nested VMs

2019-09-23 Thread Paolo Bonzini
On 23/09/19 20:32, Jintack Lim wrote:
> On Mon, Sep 23, 2019 at 4:48 AM Paolo Bonzini  wrote:
>>
>> On 23/09/19 12:42, Dr. David Alan Gilbert wrote:
>>>
>>> With those two clues, I guess maybe some dirty pages made by L2 are
>>> not transferred to the destination correctly, but I'm not really sure.
>>>
>>> 3) It happens on Intel(R) Xeon(R) Silver 4114 CPU, but it does not on
>>> Intel(R) Xeon(R) CPU E5-2630 v3 CPU.
>>
>> Hmm, try disabling pml (kvm_intel.pml=0).  This would be the main
>> difference, memory-management wise, between those two machines.
>>
> 
> Thank you, Paolo.
> 
> This makes migration work successfully over 20 times in a row on
> Intel(R) Xeon(R) Silver 4114 CPU where migration failed almost always
> without disabling pml.
> 
> I guess there's a problem in KVM pml code? I'm fine with disabling
> pml. But if you have patches to fix the issue, I'm willing to test it
> on the CPU.

Yes, it's a known bug in the PML code (that I thought was not an issue
for migration, but I was wrong).  I'll try to get you a patch this week.

Paolo



Re: [PATCH] migration/postcopy: Recognise the recovery states as 'in_postcopy'

2019-09-23 Thread Peter Xu
On Mon, Sep 23, 2019 at 06:49:42PM +0100, Dr. David Alan Gilbert (git) wrote:
> From: "Dr. David Alan Gilbert" 
> 
> Various parts of the migration code do different things when they're
> in postcopy mode; prior to this patch this has been 'postcopy-active'.
> This patch extends 'in_postcopy' to include 'postcopy-paused' and
> 'postcopy-recover'.
> 
> In particular, when you set the max-postcopy-bandwidth parameter, this
> only affects the current migration fd if we're 'in_postcopy';
> this leads to a race in the postcopy recovery test where it increases
> the speed from 4k/sec to unlimited, but that increase can get ignored
> if the change is made between the point at which the reconnection
> happens and it transitions back to active.
> 
> Signed-off-by: Dr. David Alan Gilbert 

Yeh this makes quite a lot of sense to me...

Reviewed-by: Peter Xu 

-- 
Peter Xu



Re: [Qemu-devel] [PATCH 2/4] Memory: Enable writeback for given memory region

2019-09-23 Thread Alex Bennée


Beata Michalska  writes:

> Add an option to trigger memory writeback to sync given memory region
> with the corresponding backing store, case one is available.
> This extends the support for persistent memory, allowing syncing on-demand.
>
> Also, adding verification for msync support on host.
>
> Signed-off-by: Beata Michalska 
> ---
>  configure   | 24 
>  exec.c  | 38 ++
>  include/exec/memory.h   |  6 ++
>  include/exec/ram_addr.h |  6 ++
>  memory.c| 12 
>  5 files changed, 86 insertions(+)
>
> diff --git a/configure b/configure
> index 95134c0180..bdb7dc47e9 100755
> --- a/configure
> +++ b/configure
> @@ -5081,6 +5081,26 @@ if compile_prog "" "" ; then
>  fdatasync=yes
>  fi
>
> +##
> +# verify support for msyc
> +
> +msync=no
> +cat > $TMPC << EOF
> +#include 
> +#include 
> +int main(void) {
> +#if defined(_POSIX_MAPPED_FILES) && _POSIX_MAPPED_FILES > 0 \
> +&& defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
> +return msync(NULL,0, MS_SYNC);
> +#else
> +#error Not supported
> +#endif
> +}
> +EOF
> +if compile_prog "" "" ; then
> +msync=yes
> +fi
> +
>  ##
>  # check if we have madvise
>
> @@ -6413,6 +6433,7 @@ echo "fdt support   $fdt"
>  echo "membarrier$membarrier"
>  echo "preadv support$preadv"
>  echo "fdatasync $fdatasync"
> +echo "msync $msync"
>  echo "madvise   $madvise"
>  echo "posix_madvise $posix_madvise"
>  echo "posix_memalign$posix_memalign"
> @@ -6952,6 +6973,9 @@ fi
>  if test "$fdatasync" = "yes" ; then
>echo "CONFIG_FDATASYNC=y" >> $config_host_mak
>  fi
> +if test "$msync" = "yes" ; then
> +echo "CONFIG_MSYNC=y" >> $config_host_mak
> +fi

I think it's best to split this configure check into a new prequel patch and...

>  if test "$madvise" = "yes" ; then
>echo "CONFIG_MADVISE=y" >> $config_host_mak
>  fi
> diff --git a/exec.c b/exec.c
> index 235d6bc883..5ed6908368 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -65,6 +65,8 @@
>  #include "exec/ram_addr.h"
>  #include "exec/log.h"
>
> +#include "qemu/pmem.h"
> +
>  #include "migration/vmstate.h"
>
>  #include "qemu/range.h"
> @@ -2182,6 +2184,42 @@ int qemu_ram_resize(RAMBlock *block, ram_addr_t 
> newsize, Error **errp)
>  return 0;
>  }
>
> +/*
> + * Trigger sync on the given ram block for range [start, start + length]
> + * with the backing store if available.
> + * @Note: this is supposed to be a SYNC op.
> + */
> +void qemu_ram_writeback(RAMBlock *block, ram_addr_t start, ram_addr_t length)
> +{
> +void *addr = ramblock_ptr(block, start);
> +
> +/*
> + * The requested range might spread up to the very end of the block
> + */
> +if ((start + length) > block->used_length) {
> +error_report("%s: sync range outside the block boundires: "
> + "start: " RAM_ADDR_FMT " length: " RAM_ADDR_FMT
> + " block length: " RAM_ADDR_FMT " Narrowing down ..." ,
> + __func__, start, length, block->used_length);

Is this an error or just logging? error_report should be used for stuff
that the user needs to know about so it will appear on the HMP console
(or via stderr). If so what is the user expected to do? Have they
misconfigured their system?

> +length = block->used_length - start;
> +}
> +
> +#ifdef CONFIG_LIBPMEM
> +/* The lack of support for pmem should not block the sync */
> +if (ramblock_is_pmem(block)) {
> +pmem_persist(addr, length);
> +} else
> +#endif
> +if (block->fd >= 0) {
> +#ifdef CONFIG_MSYNC
> +msync((void *)((uintptr_t)addr & qemu_host_page_mask),
> +   HOST_PAGE_ALIGN(length), MS_SYNC);
> +#else
> +qemu_fdatasync(block->fd);
> +#endif

... hide the implementation details in util/cutils.c, maybe as
qemu_msync()?

> +}
> +}
> +
>  /* Called with ram_list.mutex held */
>  static void dirty_memory_extend(ram_addr_t old_ram_size,
>  ram_addr_t new_ram_size)
> diff --git a/include/exec/memory.h b/include/exec/memory.h
> index 2dd810259d..ff0d7937cf 100644
> --- a/include/exec/memory.h
> +++ b/include/exec/memory.h
> @@ -1242,6 +1242,12 @@ void *memory_region_get_ram_ptr(MemoryRegion *mr);
>   */
>  void memory_region_ram_resize(MemoryRegion *mr, ram_addr_t newsize,
>Error **errp);
> +/**
> + * memory_region_do_writeback: Trigger writeback for selected address range
> + * [addr, addr + size]
> + *
> + */
> +void memory_region_do_writeback(MemoryRegion *mr, hwaddr addr, hwaddr size);
>
>  /**
>   * memory_region_set_log: Turn dirty logging on or off for a region.
> diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
> index a327a80cfe..d4bce81a03 100644
> --- a/include/exec/ram_addr.h
> +++ b/include/exec/ram_addr.h

Re: [Qemu-devel] [PATCH 4/4] target/arm: Add support for DC CVAP & DC CVADP ins

2019-09-23 Thread Alex Bennée


Beata Michalska  writes:

> ARMv8.2 introduced support for Data Cache Clean instructions
> to PoP (point-of-persistence) - DC CVAP and PoDP (point-of-deep-persistence)
> - DV CVADP. Both specify conceptual points in a memory system where all writes
> that are to reach them are considered persistent.
> The support provided considers both to be actually the same so there is no
> distinction between the two. If none is available (there is no backing store
> for given memory) both will result in Data Cache Clean up to the point of
> coherency. Otherwise sync for the specified range shall be performed.
>
> Signed-off-by: Beata Michalska 
> ---
>  linux-user/elfload.c   | 18 +-

There are conflicts from the recent elfload.c tweaks to fix on your next rebase.

>  target/arm/cpu.h   | 13 -
>  target/arm/cpu64.c |  1 +
>  target/arm/helper.c| 24 
>  target/arm/helper.h|  1 +
>  target/arm/op_helper.c | 36 
>  target/arm/translate-a64.c |  5 +
>  7 files changed, 96 insertions(+), 2 deletions(-)
>
> diff --git a/linux-user/elfload.c b/linux-user/elfload.c
> index 3365e192eb..1ec00308d5 100644
> --- a/linux-user/elfload.c
> +++ b/linux-user/elfload.c
> @@ -609,7 +609,12 @@ enum {
>  ARM_HWCAP_A64_PACG  = 1UL << 31,
>  };
>
> +enum {
> +ARM_HWCAP2_A64_DCPODP   = 1 << 0,
> +};
> +
>  #define ELF_HWCAP get_elf_hwcap()
> +#define ELF_HWCAP2 get_elf_hwcap2()
>
>  static uint32_t get_elf_hwcap(void)
>  {
> @@ -644,12 +649,23 @@ static uint32_t get_elf_hwcap(void)
>  GET_FEATURE_ID(aa64_jscvt, ARM_HWCAP_A64_JSCVT);
>  GET_FEATURE_ID(aa64_sb, ARM_HWCAP_A64_SB);
>  GET_FEATURE_ID(aa64_condm_4, ARM_HWCAP_A64_FLAGM);
> +GET_FEATURE_ID(aa64_dcpop, ARM_HWCAP_A64_DCPOP);
>
> -#undef GET_FEATURE_ID
>
>  return hwcaps;
>  }
>
> +static uint32_t get_elf_hwcap2(void)
> +{
> +ARMCPU *cpu = ARM_CPU(thread_cpu);
> +uint32_t hwcaps = 0;
> +
> +GET_FEATURE_ID(aa64_dcpodp, ARM_HWCAP2_A64_DCPODP);
> +return hwcaps;
> +}
> +
> +#undef GET_FEATURE_ID
> +
>  #endif /* not TARGET_AARCH64 */
>  #endif /* TARGET_ARM */
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 297ad5e47a..1713d76590 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -2229,7 +2229,8 @@ static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid)
>  #define ARM_CP_NZCV  (ARM_CP_SPECIAL | 0x0300)
>  #define ARM_CP_CURRENTEL (ARM_CP_SPECIAL | 0x0400)
>  #define ARM_CP_DC_ZVA(ARM_CP_SPECIAL | 0x0500)
> -#define ARM_LAST_SPECIAL ARM_CP_DC_ZVA
> +#define ARM_CP_DC_CVAP   (ARM_CP_SPECIAL | 0x0600)
> +#define ARM_LAST_SPECIAL ARM_CP_DC_CVAP
>  #define ARM_CP_FPU   0x1000
>  #define ARM_CP_SVE   0x2000
>  #define ARM_CP_NO_GDB0x4000
> @@ -3572,6 +3573,16 @@ static inline bool isar_feature_aa64_frint(const 
> ARMISARegisters *id)
>  return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FRINTTS) != 0;
>  }
>
> +static inline bool isar_feature_aa64_dcpop(const ARMISARegisters *id)
> +{
> +return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, DPB) != 0;
> +}
> +
> +static inline bool isar_feature_aa64_dcpodp(const ARMISARegisters *id)
> +{
> +return (FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, DPB) >> 1) != 0;
> +}
> +
>  static inline bool isar_feature_aa64_fp16(const ARMISARegisters *id)
>  {
>  /* We always set the AdvSIMD and FP fields identically wrt FP16.  */
> diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
> index d7f5bf610a..20094f980d 100644
> --- a/target/arm/cpu64.c
> +++ b/target/arm/cpu64.c
> @@ -331,6 +331,7 @@ static void aarch64_max_initfn(Object *obj)
>  cpu->isar.id_aa64isar0 = t;
>
>  t = cpu->isar.id_aa64isar1;
> +t = FIELD_DP64(t, ID_AA64ISAR1, DPB, 2);
>  t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 1);
>  t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 1);
>  t = FIELD_DP64(t, ID_AA64ISAR1, APA, 1); /* PAuth, architected only 
> */
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 507026c915..99ae01b7e7 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -3843,6 +3843,22 @@ static CPAccessResult aa64_cacheop_access(CPUARMState 
> *env,
>  return CP_ACCESS_OK;
>  }
>
> +static CPAccessResult aa64_cacheop_persist_access(CPUARMState *env,
> +  const ARMCPRegInfo *ri,
> +  bool isread)
> +{
> +ARMCPU *cpu = env_archcpu(env);
> +/*
> + * Access is UNDEF if lacking implementation for either DC CVAP or DC 
> CVADP
> + * DC CVAP ->  CRm: 0xc
> + * DC CVADP -> CRm: 0xd
> + */
> +return (ri->crm == 0xc && !cpu_isar_feature(aa64_dcpop, cpu)) ||
> +   (ri->crm == 0xd && !cpu_isar_feature(aa64_dcpodp, cpu))
> +   ? CP_ACCESS_TRAP_UNCATEGORIZED
> +   : aa64_cacheo

Re: [Qemu-devel] [PATCH 1/4] tcg: cputlb: Add probe_read

2019-09-23 Thread Alex Bennée


Beata Michalska  writes:

> Add probe_read alongside the write probing equivalent.
>
> Signed-off-by: Beata Michalska 

Reviewed-by: Alex Bennée 

> ---
>  include/exec/exec-all.h | 6 ++
>  1 file changed, 6 insertions(+)
>
> diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
> index 81b02eb2fe..e1785700c3 100644
> --- a/include/exec/exec-all.h
> +++ b/include/exec/exec-all.h
> @@ -319,6 +319,12 @@ static inline void *probe_write(CPUArchState *env, 
> target_ulong addr, int size,
>  return probe_access(env, addr, size, MMU_DATA_STORE, mmu_idx, retaddr);
>  }
>
> +static inline void *probe_read(CPUArchState *env, target_ulong addr, int 
> size,
> +   int mmu_idx, uintptr_t retaddr)
> +{
> +return probe_access(env, addr, size, MMU_DATA_LOAD, mmu_idx, retaddr);
> +}
> +
>  #define CODE_GEN_ALIGN   16 /* must be >= of the size of a icache 
> line */
>
>  /* Estimated block size for TB allocation.  */


--
Alex Bennée



Re: [PATCH v3 1/2] vfio: Turn the container error into an Error handle

2019-09-23 Thread Peter Xu
On Mon, Sep 23, 2019 at 05:10:43PM -0600, Alex Williamson wrote:
> On Mon, 23 Sep 2019 13:43:08 +0200
> Auger Eric  wrote:
> 
> > On 9/23/19 9:51 AM, Peter Xu wrote:
> > > On Mon, Sep 23, 2019 at 08:55:51AM +0200, Eric Auger wrote:  
> > >> @@ -1308,9 +1319,9 @@ static int vfio_connect_container(VFIOGroup 
> > >> *group, AddressSpace *as,
> > >>   &address_space_memory);
> > >>  if (container->error) {
> > >>  memory_listener_unregister(&container->prereg_listener);
> > >> -ret = container->error;
> > >> -error_setg(errp,
> > >> -"RAM memory listener initialization failed for 
> > >> container");
> > >> +ret = -1;
> > >> +error_propagate_prepend(errp, container->error,
> > >> +"RAM memory listener initialization failed: ");  
> > > 
> > > (I saw that we've got plenty of prepended prefixes for an error
> > >  messages.  For me I'll disgard quite a few of them because the errors
> > >  will directly be delivered to the top level user, but this might be
> > >  too personal as a comment)  
> > That's true we have a lot of prefix messages.
> > 
> > The output message now is:
> > 
> > "vfio :89:00.0: failed
> > to setup container for group 2: memory listener initialization failed:
> > Region smmuv3-iommu-memory-region-0-6: device 01.00.0 requires iommu MAP
> > notifier which is not currently supported"
> > 
> > Alex, any opinion?
> 
> Peter, I don't really understand what the comment is here.  Is it the
> number of prepends on the error message?  I don't really have an
> opinion on that so long as the end message makes sense.  Seems like if
> we're familiar with the error generation it helps to unwind the
> context.  Thanks,

True, the only major difference of the error that this series is
working on is that the user can easily trigger this simply by plugging
a device hence I'm not sure whether that's too long (it's not really a
comment and that's why I put it in brackets :).  Let's just keep them.

Thanks,

-- 
Peter Xu



[PATCH] qemu-pr-helper: fix crash in mpath_reconstruct_sense

2019-09-23 Thread Maxim Levitsky
The 'r' variable was accidently shadowed, and because of this
we were always passing 0 to mpath_generic_sense, instead of original
return value, which triggers an abort()

This is an attempt to fix the
https://bugzilla.redhat.com/show_bug.cgi?id=1720047
although there might be other places in the code
that trigger qemu-pr-helper crash, and this fix might
not be the root cause.

The crash was reproduced by creating an iscsi target on a test machine,
and passing it twice to the guest like that:

-blockdev node-name=idisk0,driver=iscsi,transport=...,target=...
-device 
scsi-block,drive=idisk0,bus=scsi0.0,bootindex=-1,scsi-id=1,lun=0,share-rw=on
-device 
scsi-block,drive=idisk0,bus=scsi0.0,bootindex=-1,scsi-id=1,lun=1,share-rw=on

Then in the guest, both /dev/sda and /dev/sdb were aggregated by multipath to 
/dev/mpatha,
which was passed to a nested guest like that

-object 
pr-manager-helper,id=qemu_pr_helper,path=/root/work/vm/testvm/.run/pr_helper.socket
-blockdev 
node-name=test,driver=host_device,filename=/dev/mapper/mpatha,pr-manager=qemu_pr_helper
-device scsi-block,drive=test,bus=scsi0.0,bootindex=-1,scsi-id=0,lun=0

The nested guest run:

sg_persist --no-inquiry  -v --out --register --param-sark 0x1234 /dev/sda

Strictly speaking this is wrong configuration since qemu is where
the multipath was split, and thus the iscsi target was not aware of
multipath, and thus when libmpathpersist code rightfully tried to register
the PR key on all paths, it failed to do so.

However qemu-pr-helper should not crash in this case.

Signed-off-by: Maxim Levitsky 
---
 scsi/qemu-pr-helper.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/scsi/qemu-pr-helper.c b/scsi/qemu-pr-helper.c
index a8a74d1dba..debb18f4aa 100644
--- a/scsi/qemu-pr-helper.c
+++ b/scsi/qemu-pr-helper.c
@@ -323,10 +323,10 @@ static int mpath_reconstruct_sense(int fd, int r, uint8_t 
*sense)
  */
 uint8_t cdb[6] = { TEST_UNIT_READY };
 int sz = 0;
-int r = do_sgio(fd, cdb, sense, NULL, &sz, SG_DXFER_NONE);
+int ret = do_sgio(fd, cdb, sense, NULL, &sz, SG_DXFER_NONE);
 
-if (r != GOOD) {
-return r;
+if (ret != GOOD) {
+return ret;
 }
 scsi_build_sense(sense, mpath_generic_sense(r));
 return CHECK_CONDITION;
-- 
2.17.2




Re: [PATCH v3 1/2] vfio: Turn the container error into an Error handle

2019-09-23 Thread Alex Williamson
On Mon, 23 Sep 2019 13:43:08 +0200
Auger Eric  wrote:

> On 9/23/19 9:51 AM, Peter Xu wrote:
> > On Mon, Sep 23, 2019 at 08:55:51AM +0200, Eric Auger wrote:  
> >> @@ -1308,9 +1319,9 @@ static int vfio_connect_container(VFIOGroup *group, 
> >> AddressSpace *as,
> >>   &address_space_memory);
> >>  if (container->error) {
> >>  memory_listener_unregister(&container->prereg_listener);
> >> -ret = container->error;
> >> -error_setg(errp,
> >> -"RAM memory listener initialization failed for 
> >> container");
> >> +ret = -1;
> >> +error_propagate_prepend(errp, container->error,
> >> +"RAM memory listener initialization failed: ");  
> > 
> > (I saw that we've got plenty of prepended prefixes for an error
> >  messages.  For me I'll disgard quite a few of them because the errors
> >  will directly be delivered to the top level user, but this might be
> >  too personal as a comment)  
> That's true we have a lot of prefix messages.
> 
> The output message now is:
> 
> "vfio :89:00.0: failed
> to setup container for group 2: memory listener initialization failed:
> Region smmuv3-iommu-memory-region-0-6: device 01.00.0 requires iommu MAP
> notifier which is not currently supported"
> 
> Alex, any opinion?

Peter, I don't really understand what the comment is here.  Is it the
number of prepends on the error message?  I don't really have an
opinion on that so long as the end message makes sense.  Seems like if
we're familiar with the error generation it helps to unwind the
context.  Thanks,

Alex



[PATCH v4 16/16] cputlb: Pass retaddr to tb_check_watchpoint

2019-09-23 Thread Richard Henderson
Fixes the previous TLB_WATCHPOINT patches because we are currently
failing to set cpu->mem_io_pc with the call to cpu_check_watchpoint.
Pass down the retaddr directly because it's readily available.

Fixes: 50b107c5d61
Reviewed-by: David Hildenbrand 
Signed-off-by: Richard Henderson 
---
 accel/tcg/translate-all.h | 2 +-
 accel/tcg/translate-all.c | 6 +++---
 exec.c| 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/accel/tcg/translate-all.h b/accel/tcg/translate-all.h
index 135c1ea96a..a557b4e2bb 100644
--- a/accel/tcg/translate-all.h
+++ b/accel/tcg/translate-all.h
@@ -30,7 +30,7 @@ void tb_invalidate_phys_page_fast(struct page_collection 
*pages,
   tb_page_addr_t start, int len,
   uintptr_t retaddr);
 void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end);
-void tb_check_watchpoint(CPUState *cpu);
+void tb_check_watchpoint(CPUState *cpu, uintptr_t retaddr);
 
 #ifdef CONFIG_USER_ONLY
 int page_unprotect(target_ulong address, uintptr_t pc);
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index db77fb221b..66d4bc4341 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -2142,16 +2142,16 @@ static bool tb_invalidate_phys_page(tb_page_addr_t 
addr, uintptr_t pc)
 #endif
 
 /* user-mode: call with mmap_lock held */
-void tb_check_watchpoint(CPUState *cpu)
+void tb_check_watchpoint(CPUState *cpu, uintptr_t retaddr)
 {
 TranslationBlock *tb;
 
 assert_memory_lock();
 
-tb = tcg_tb_lookup(cpu->mem_io_pc);
+tb = tcg_tb_lookup(retaddr);
 if (tb) {
 /* We can use retranslation to find the PC.  */
-cpu_restore_state_from_tb(cpu, tb, cpu->mem_io_pc, true);
+cpu_restore_state_from_tb(cpu, tb, retaddr, true);
 tb_phys_invalidate(tb, -1);
 } else {
 /* The exception probably happened in a helper.  The CPU state should
diff --git a/exec.c b/exec.c
index b3df826039..8a0a6613b1 100644
--- a/exec.c
+++ b/exec.c
@@ -2758,7 +2758,7 @@ void cpu_check_watchpoint(CPUState *cpu, vaddr addr, 
vaddr len,
 cpu->watchpoint_hit = wp;
 
 mmap_lock();
-tb_check_watchpoint(cpu);
+tb_check_watchpoint(cpu, ra);
 if (wp->flags & BP_STOP_BEFORE_ACCESS) {
 cpu->exception_index = EXCP_DEBUG;
 mmap_unlock();
-- 
2.17.1




Re: [PATCH v3 1/2] vfio: Turn the container error into an Error handle

2019-09-23 Thread Alex Williamson
On Mon, 23 Sep 2019 08:55:51 +0200
Eric Auger  wrote:

> The container error integer field is currently used to store
> the first error potentially encountered during any
> vfio_listener_region_add() call. However this fails to propagate
> detailed error messages up to the vfio_connect_container caller.
> Instead of using an integer, let's use an Error handle.
> 
> Messages are slightly reworded to accomodate the propagation.
> 
> Signed-off-by: Eric Auger 
> ---
>  hw/vfio/common.c  | 61 +--
>  hw/vfio/spapr.c   |  4 ++-
>  include/hw/vfio/vfio-common.h |  2 +-
>  3 files changed, 40 insertions(+), 27 deletions(-)
> 
> diff --git a/hw/vfio/common.c b/hw/vfio/common.c
> index 3e03c495d8..a0670cc63a 100644
> --- a/hw/vfio/common.c
> +++ b/hw/vfio/common.c
> @@ -503,12 +503,14 @@ static void vfio_listener_region_add(MemoryListener 
> *listener,
>   MemoryRegionSection *section)
>  {
>  VFIOContainer *container = container_of(listener, VFIOContainer, 
> listener);
> +MemoryRegion *mr = section->mr;

This looks like an entirely secondary change that obscures the primary
purpose of this patch and isn't mentioned in the changelog.  It's also a
bit inconsistent in places where we're references section->size and
section->offset_within_address_space, but now mr instead of section->mr.


>  hwaddr iova, end;
>  Int128 llend, llsize;
>  void *vaddr;
>  int ret;
>  VFIOHostDMAWindow *hostwin;
>  bool hostwin_found;
> +Error *err = NULL;
>  
>  if (vfio_listener_skipped_section(section)) {
>  trace_vfio_listener_region_add_skip(
> @@ -543,6 +545,9 @@ static void vfio_listener_region_add(MemoryListener 
> *listener,
> hostwin->max_iova - hostwin->min_iova + 1,
> section->offset_within_address_space,
> int128_get64(section->size))) {
> +error_setg(&err, "Overlap with existing IOMMU range "
> + "[0x%"PRIx64",0x%"PRIx64"]", 
> hostwin->min_iova,
> + hostwin->max_iova - hostwin->min_iova + 1);
>  ret = -1;

Agree with Peter here, we should no longer be gratuitously setting ret
when it's not consumed.

Alexey or David might want to comment on the error message here since
we didn't have one previously, but we're only providing half the story
above, the existing window that interferes but not the range we
attempted to add that it interferes with.

>  goto fail;
>  }
> @@ -550,6 +555,7 @@ static void vfio_listener_region_add(MemoryListener 
> *listener,
>  
>  ret = vfio_spapr_create_window(container, section, &pgsize);
>  if (ret) {
> +error_setg_errno(&err, -ret, "Failed to create SPAPR window");
>  goto fail;
>  }
>  
> @@ -559,7 +565,7 @@ static void vfio_listener_region_add(MemoryListener 
> *listener,
>  #ifdef CONFIG_KVM
>  if (kvm_enabled()) {
>  VFIOGroup *group;
> -IOMMUMemoryRegion *iommu_mr = IOMMU_MEMORY_REGION(section->mr);
> +IOMMUMemoryRegion *iommu_mr = IOMMU_MEMORY_REGION(mr);
>  struct kvm_vfio_spapr_tce param;
>  struct kvm_device_attr attr = {
>  .group = KVM_DEV_VFIO_GROUP,
> @@ -594,18 +600,17 @@ static void vfio_listener_region_add(MemoryListener 
> *listener,
>  }
>  
>  if (!hostwin_found) {
> -error_report("vfio: IOMMU container %p can't map guest IOVA region"
> - " 0x%"HWADDR_PRIx"..0x%"HWADDR_PRIx,
> - container, iova, end);
> +error_setg(&err, "Container %p can't map guest IOVA region"
> +   " 0x%"HWADDR_PRIx"..0x%"HWADDR_PRIx, container, iova, 
> end);

Note that here we print the start and end addresses, so I'm not sure
why we chose to print [start,size] in the new message commented on
above.

>  ret = -EFAULT;
>  goto fail;
>  }
>  
> -memory_region_ref(section->mr);
> +memory_region_ref(mr);
>  
> -if (memory_region_is_iommu(section->mr)) {
> +if (memory_region_is_iommu(mr)) {
>  VFIOGuestIOMMU *giommu;
> -IOMMUMemoryRegion *iommu_mr = IOMMU_MEMORY_REGION(section->mr);
> +IOMMUMemoryRegion *iommu_mr = IOMMU_MEMORY_REGION(mr);
>  int iommu_idx;
>  
>  trace_vfio_listener_region_add_iommu(iova, end);
> @@ -632,15 +637,15 @@ static void vfio_listener_region_add(MemoryListener 
> *listener,
>  iommu_idx);
>  QLIST_INSERT_HEAD(&container->giommu_list, giommu, giommu_next);
>  
> -memory_region_register_iommu_notifier(section->mr, &giommu->n);
> +memory_region_register_iommu_notifier(mr, &giommu->n);
>  memory_region_iommu_replay(giommu->iommu, &giommu->n);
>  
>  return;
>  }
>  
> -/* Her

[PATCH v4 14/16] cputlb: Remove tb_invalidate_phys_page_range is_cpu_write_access

2019-09-23 Thread Richard Henderson
All callers pass false to this argument.  Remove it and pass the
constant on to tb_invalidate_phys_page_range__locked.

Reviewed-by: David Hildenbrand 
Signed-off-by: Richard Henderson 
---
 accel/tcg/translate-all.h | 3 +--
 accel/tcg/translate-all.c | 6 ++
 exec.c| 4 ++--
 3 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/accel/tcg/translate-all.h b/accel/tcg/translate-all.h
index 64f5fd9a05..31f2117188 100644
--- a/accel/tcg/translate-all.h
+++ b/accel/tcg/translate-all.h
@@ -28,8 +28,7 @@ struct page_collection *page_collection_lock(tb_page_addr_t 
start,
 void page_collection_unlock(struct page_collection *set);
 void tb_invalidate_phys_page_fast(struct page_collection *pages,
   tb_page_addr_t start, int len);
-void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
-   int is_cpu_write_access);
+void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end);
 void tb_check_watchpoint(CPUState *cpu);
 
 #ifdef CONFIG_USER_ONLY
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index 5d1e08b169..de4b697163 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -1983,8 +1983,7 @@ tb_invalidate_phys_page_range__locked(struct 
page_collection *pages,
  *
  * Called with mmap_lock held for user-mode emulation
  */
-void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
-   int is_cpu_write_access)
+void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end)
 {
 struct page_collection *pages;
 PageDesc *p;
@@ -1996,8 +1995,7 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, 
tb_page_addr_t end,
 return;
 }
 pages = page_collection_lock(start, end);
-tb_invalidate_phys_page_range__locked(pages, p, start, end,
-  is_cpu_write_access);
+tb_invalidate_phys_page_range__locked(pages, p, start, end, 0);
 page_collection_unlock(pages);
 }
 
diff --git a/exec.c b/exec.c
index 7d835b1a2b..b3df826039 100644
--- a/exec.c
+++ b/exec.c
@@ -1012,7 +1012,7 @@ const char *parse_cpu_option(const char *cpu_option)
 void tb_invalidate_phys_addr(target_ulong addr)
 {
 mmap_lock();
-tb_invalidate_phys_page_range(addr, addr + 1, 0);
+tb_invalidate_phys_page_range(addr, addr + 1);
 mmap_unlock();
 }
 
@@ -1039,7 +1039,7 @@ void tb_invalidate_phys_addr(AddressSpace *as, hwaddr 
addr, MemTxAttrs attrs)
 return;
 }
 ram_addr = memory_region_get_ram_addr(mr) + addr;
-tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
+tb_invalidate_phys_page_range(ram_addr, ram_addr + 1);
 rcu_read_unlock();
 }
 
-- 
2.17.1




[PATCH v4 13/16] cputlb: Remove cpu->mem_io_vaddr

2019-09-23 Thread Richard Henderson
With the merge of notdirty handling into store_helper,
the last user of cpu->mem_io_vaddr was removed.

Reviewed-by: David Hildenbrand 
Signed-off-by: Richard Henderson 
---
 include/hw/core/cpu.h | 2 --
 accel/tcg/cputlb.c| 2 --
 hw/core/cpu.c | 1 -
 3 files changed, 5 deletions(-)

diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index c7cda65c66..031f587e51 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -338,7 +338,6 @@ struct qemu_work_item;
  * @next_cpu: Next CPU sharing TB cache.
  * @opaque: User data.
  * @mem_io_pc: Host Program Counter at which the memory was accessed.
- * @mem_io_vaddr: Target virtual address at which the memory was accessed.
  * @kvm_fd: vCPU file descriptor for KVM.
  * @work_mutex: Lock to prevent multiple access to queued_work_*.
  * @queued_work_first: First asynchronous work pending.
@@ -413,7 +412,6 @@ struct CPUState {
  * we store some rarely used information in the CPU context.
  */
 uintptr_t mem_io_pc;
-vaddr mem_io_vaddr;
 /*
  * This is only needed for the legacy cpu_unassigned_access() hook;
  * when all targets using it have been converted to use
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index d0bdef1eb3..0ca6ee60b3 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -927,7 +927,6 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry 
*iotlbentry,
 cpu_io_recompile(cpu, retaddr);
 }
 
-cpu->mem_io_vaddr = addr;
 cpu->mem_io_access_type = access_type;
 
 if (mr->global_locking && !qemu_mutex_iothread_locked()) {
@@ -967,7 +966,6 @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry 
*iotlbentry,
 if (!cpu->can_do_io) {
 cpu_io_recompile(cpu, retaddr);
 }
-cpu->mem_io_vaddr = addr;
 cpu->mem_io_pc = retaddr;
 
 if (mr->global_locking && !qemu_mutex_iothread_locked()) {
diff --git a/hw/core/cpu.c b/hw/core/cpu.c
index 0035845511..73b1ee34d0 100644
--- a/hw/core/cpu.c
+++ b/hw/core/cpu.c
@@ -261,7 +261,6 @@ static void cpu_common_reset(CPUState *cpu)
 cpu->interrupt_request = 0;
 cpu->halted = 0;
 cpu->mem_io_pc = 0;
-cpu->mem_io_vaddr = 0;
 cpu->icount_extra = 0;
 atomic_set(&cpu->icount_decr_ptr->u32, 0);
 cpu->can_do_io = 1;
-- 
2.17.1




[PATCH v4 11/16] cputlb: Merge and move memory_notdirty_write_{prepare, complete}

2019-09-23 Thread Richard Henderson
Since 9458a9a1df1a, all readers of the dirty bitmaps wait
for the rcu lock, which means that they wait until the end
of any executing TranslationBlock.

As a consequence, there is no need for the actual access
to happen in between the _prepare and _complete.  Therefore,
we can improve things by merging the two functions into
notdirty_write and dropping the NotDirtyInfo structure.

In addition, the only users of notdirty_write are in cputlb.c,
so move the merged function there.  Pass in the CPUIOTLBEntry
from which the ram_addr_t may be computed.

Signed-off-by: Richard Henderson 
---
 include/exec/memory-internal.h | 65 -
 accel/tcg/cputlb.c | 76 +++---
 exec.c | 44 
 3 files changed, 42 insertions(+), 143 deletions(-)

diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
index ef4fb92371..9fcc2af25c 100644
--- a/include/exec/memory-internal.h
+++ b/include/exec/memory-internal.h
@@ -49,70 +49,5 @@ void address_space_dispatch_free(AddressSpaceDispatch *d);
 
 void mtree_print_dispatch(struct AddressSpaceDispatch *d,
   MemoryRegion *root);
-
-struct page_collection;
-
-/* Opaque struct for passing info from memory_notdirty_write_prepare()
- * to memory_notdirty_write_complete(). Callers should treat all fields
- * as private, with the exception of @active.
- *
- * @active is a field which is not touched by either the prepare or
- * complete functions, but which the caller can use if it wishes to
- * track whether it has called prepare for this struct and so needs
- * to later call the complete function.
- */
-typedef struct {
-CPUState *cpu;
-struct page_collection *pages;
-ram_addr_t ram_addr;
-vaddr mem_vaddr;
-unsigned size;
-bool active;
-} NotDirtyInfo;
-
-/**
- * memory_notdirty_write_prepare: call before writing to non-dirty memory
- * @ndi: pointer to opaque NotDirtyInfo struct
- * @cpu: CPU doing the write
- * @mem_vaddr: virtual address of write
- * @ram_addr: the ram address of the write
- * @size: size of write in bytes
- *
- * Any code which writes to the host memory corresponding to
- * guest RAM which has been marked as NOTDIRTY must wrap those
- * writes in calls to memory_notdirty_write_prepare() and
- * memory_notdirty_write_complete():
- *
- *  NotDirtyInfo ndi;
- *  memory_notdirty_write_prepare(&ndi, );
- *  ... perform write here ...
- *  memory_notdirty_write_complete(&ndi);
- *
- * These calls will ensure that we flush any TCG translated code for
- * the memory being written, update the dirty bits and (if possible)
- * remove the slowpath callback for writing to the memory.
- *
- * This must only be called if we are using TCG; it will assert otherwise.
- *
- * We may take locks in the prepare call, so callers must ensure that
- * they don't exit (via longjump or otherwise) without calling complete.
- *
- * This call must only be made inside an RCU critical section.
- * (Note that while we're executing a TCG TB we're always in an
- * RCU critical section, which is likely to be the case for callers
- * of these functions.)
- */
-void memory_notdirty_write_prepare(NotDirtyInfo *ndi,
-   CPUState *cpu,
-   vaddr mem_vaddr,
-   ram_addr_t ram_addr,
-   unsigned size);
-/**
- * memory_notdirty_write_complete: finish write to non-dirty memory
- * @ndi: pointer to the opaque NotDirtyInfo struct which was initialized
- * by memory_not_dirty_write_prepare().
- */
-void memory_notdirty_write_complete(NotDirtyInfo *ndi);
-
 #endif
 #endif
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index 05530a8b0c..09b0df87c6 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -33,6 +33,7 @@
 #include "exec/helper-proto.h"
 #include "qemu/atomic.h"
 #include "qemu/atomic128.h"
+#include "translate-all.h"
 
 /* DEBUG defines, enable DEBUG_TLB_LOG to log to the CPU_LOG_MMU target */
 /* #define DEBUG_TLB */
@@ -1084,6 +1085,37 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, 
target_ulong addr)
 return qemu_ram_addr_from_host_nofail(p);
 }
 
+static void notdirty_write(CPUState *cpu, vaddr mem_vaddr, unsigned size,
+   CPUIOTLBEntry *iotlbentry, uintptr_t retaddr)
+{
+ram_addr_t ram_addr = mem_vaddr + iotlbentry->addr;
+
+trace_memory_notdirty_write_access(mem_vaddr, ram_addr, size);
+
+if (!cpu_physical_memory_get_dirty_flag(ram_addr, DIRTY_MEMORY_CODE)) {
+struct page_collection *pages
+= page_collection_lock(ram_addr, ram_addr + size);
+
+/* We require mem_io_pc in tb_invalidate_phys_page_range.  */
+cpu->mem_io_pc = retaddr;
+
+tb_invalidate_phys_page_fast(pages, ram_addr, size);
+page_collection_unlock(pages);
+}
+
+/*
+ * Set both VGA and migration bits for simplicity an

[PATCH v4 05/16] cputlb: Split out load/store_memop

2019-09-23 Thread Richard Henderson
We will shortly be using these more than once.

Signed-off-by: Richard Henderson 
---
 accel/tcg/cputlb.c | 110 +++--
 1 file changed, 57 insertions(+), 53 deletions(-)

diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index e529af6d09..430ba4a69d 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -1281,6 +1281,29 @@ static void *atomic_mmu_lookup(CPUArchState *env, 
target_ulong addr,
 typedef uint64_t FullLoadHelper(CPUArchState *env, target_ulong addr,
 TCGMemOpIdx oi, uintptr_t retaddr);
 
+static inline uint64_t QEMU_ALWAYS_INLINE
+load_memop(const void *haddr, MemOp op)
+{
+switch (op) {
+case MO_UB:
+return ldub_p(haddr);
+case MO_BEUW:
+return lduw_be_p(haddr);
+case MO_LEUW:
+return lduw_le_p(haddr);
+case MO_BEUL:
+return (uint32_t)ldl_be_p(haddr);
+case MO_LEUL:
+return (uint32_t)ldl_le_p(haddr);
+case MO_BEQ:
+return ldq_be_p(haddr);
+case MO_LEQ:
+return ldq_le_p(haddr);
+default:
+optimize_away();
+}
+}
+
 static inline uint64_t QEMU_ALWAYS_INLINE
 load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
 uintptr_t retaddr, MemOp op, bool code_read,
@@ -1373,33 +1396,7 @@ load_helper(CPUArchState *env, target_ulong addr, 
TCGMemOpIdx oi,
 
  do_aligned_access:
 haddr = (void *)((uintptr_t)addr + entry->addend);
-switch (op) {
-case MO_UB:
-res = ldub_p(haddr);
-break;
-case MO_BEUW:
-res = lduw_be_p(haddr);
-break;
-case MO_LEUW:
-res = lduw_le_p(haddr);
-break;
-case MO_BEUL:
-res = (uint32_t)ldl_be_p(haddr);
-break;
-case MO_LEUL:
-res = (uint32_t)ldl_le_p(haddr);
-break;
-case MO_BEQ:
-res = ldq_be_p(haddr);
-break;
-case MO_LEQ:
-res = ldq_le_p(haddr);
-break;
-default:
-optimize_away();
-}
-
-return res;
+return load_memop(haddr, op);
 }
 
 /*
@@ -1415,7 +1412,8 @@ load_helper(CPUArchState *env, target_ulong addr, 
TCGMemOpIdx oi,
 static uint64_t full_ldub_mmu(CPUArchState *env, target_ulong addr,
   TCGMemOpIdx oi, uintptr_t retaddr)
 {
-return load_helper(env, addr, oi, retaddr, MO_UB, false, full_ldub_mmu);
+return load_helper(env, addr, oi, retaddr, MO_UB, false,
+   full_ldub_mmu);
 }
 
 tcg_target_ulong helper_ret_ldub_mmu(CPUArchState *env, target_ulong addr,
@@ -1530,6 +1528,36 @@ tcg_target_ulong helper_be_ldsl_mmu(CPUArchState *env, 
target_ulong addr,
  * Store Helpers
  */
 
+static inline void QEMU_ALWAYS_INLINE
+store_memop(void *haddr, uint64_t val, MemOp op)
+{
+switch (op) {
+case MO_UB:
+stb_p(haddr, val);
+break;
+case MO_BEUW:
+stw_be_p(haddr, val);
+break;
+case MO_LEUW:
+stw_le_p(haddr, val);
+break;
+case MO_BEUL:
+stl_be_p(haddr, val);
+break;
+case MO_LEUL:
+stl_le_p(haddr, val);
+break;
+case MO_BEQ:
+stq_be_p(haddr, val);
+break;
+case MO_LEQ:
+stq_le_p(haddr, val);
+break;
+default:
+optimize_away();
+}
+}
+
 static inline void QEMU_ALWAYS_INLINE
 store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
  TCGMemOpIdx oi, uintptr_t retaddr, MemOp op)
@@ -1657,31 +1685,7 @@ store_helper(CPUArchState *env, target_ulong addr, 
uint64_t val,
 
  do_aligned_access:
 haddr = (void *)((uintptr_t)addr + entry->addend);
-switch (op) {
-case MO_UB:
-stb_p(haddr, val);
-break;
-case MO_BEUW:
-stw_be_p(haddr, val);
-break;
-case MO_LEUW:
-stw_le_p(haddr, val);
-break;
-case MO_BEUL:
-stl_be_p(haddr, val);
-break;
-case MO_LEUL:
-stl_le_p(haddr, val);
-break;
-case MO_BEQ:
-stq_be_p(haddr, val);
-break;
-case MO_LEQ:
-stq_le_p(haddr, val);
-break;
-default:
-optimize_away();
-}
+store_memop(haddr, val, op);
 }
 
 void helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val,
-- 
2.17.1




[PATCH v4 10/16] cputlb: Partially inline memory_region_section_get_iotlb

2019-09-23 Thread Richard Henderson
There is only one caller, tlb_set_page_with_attrs.  We cannot
inline the entire function because the AddressSpaceDispatch
structure is private to exec.c, and cannot easily be moved to
include/exec/memory-internal.h.

Compute is_ram and is_romd once within tlb_set_page_with_attrs.
Fold the number of tests against these predicates.  Compute
cpu_physical_memory_is_clean outside of the tlb lock region.

Signed-off-by: Richard Henderson 
---
 include/exec/exec-all.h |  6 +---
 accel/tcg/cputlb.c  | 68 ++---
 exec.c  | 22 ++---
 3 files changed, 47 insertions(+), 49 deletions(-)

diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 81b02eb2fe..49db07ba0b 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -509,11 +509,7 @@ address_space_translate_for_iotlb(CPUState *cpu, int 
asidx, hwaddr addr,
   hwaddr *xlat, hwaddr *plen,
   MemTxAttrs attrs, int *prot);
 hwaddr memory_region_section_get_iotlb(CPUState *cpu,
-   MemoryRegionSection *section,
-   target_ulong vaddr,
-   hwaddr paddr, hwaddr xlat,
-   int prot,
-   target_ulong *address);
+   MemoryRegionSection *section);
 #endif
 
 /* vl.c */
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index 05212ff244..05530a8b0c 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -704,13 +704,14 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong 
vaddr,
 MemoryRegionSection *section;
 unsigned int index;
 target_ulong address;
-target_ulong code_address;
+target_ulong write_address;
 uintptr_t addend;
 CPUTLBEntry *te, tn;
 hwaddr iotlb, xlat, sz, paddr_page;
 target_ulong vaddr_page;
 int asidx = cpu_asidx_from_attrs(cpu, attrs);
 int wp_flags;
+bool is_ram, is_romd;
 
 assert_cpu_is_self(cpu);
 
@@ -739,18 +740,46 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong 
vaddr,
 if (attrs.byte_swap) {
 address |= TLB_BSWAP;
 }
-if (!memory_region_is_ram(section->mr) &&
-!memory_region_is_romd(section->mr)) {
-/* IO memory case */
-address |= TLB_MMIO;
-addend = 0;
-} else {
+
+is_ram = memory_region_is_ram(section->mr);
+is_romd = memory_region_is_romd(section->mr);
+
+if (is_ram || is_romd) {
+/* RAM and ROMD both have associated host memory. */
 addend = (uintptr_t)memory_region_get_ram_ptr(section->mr) + xlat;
+} else {
+/* I/O does not; force the host address to NULL. */
+addend = 0;
+}
+
+write_address = address;
+if (is_ram) {
+iotlb = memory_region_get_ram_addr(section->mr) + xlat;
+/*
+ * Computing is_clean is expensive; avoid all that unless
+ * the page is actually writable.
+ */
+if (prot & PAGE_WRITE) {
+if (section->readonly) {
+write_address |= TLB_ROM;
+} else if (cpu_physical_memory_is_clean(iotlb)) {
+write_address |= TLB_NOTDIRTY;
+}
+}
+} else {
+/* I/O or ROMD */
+iotlb = memory_region_section_get_iotlb(cpu, section) + xlat;
+/*
+ * Writes to romd devices must go through MMIO to enable write.
+ * Reads to romd devices go through the ram_ptr found above,
+ * but of course reads to I/O must go through MMIO.
+ */
+write_address |= TLB_MMIO;
+if (!is_romd) {
+address = write_address;
+}
 }
 
-code_address = address;
-iotlb = memory_region_section_get_iotlb(cpu, section, vaddr_page,
-paddr_page, xlat, prot, &address);
 wp_flags = cpu_watchpoint_address_matches(cpu, vaddr_page,
   TARGET_PAGE_SIZE);
 
@@ -790,8 +819,8 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong 
vaddr,
 /*
  * At this point iotlb contains a physical section number in the lower
  * TARGET_PAGE_BITS, and either
- *  + the ram_addr_t of the page base of the target RAM (if NOTDIRTY or 
ROM)
- *  + the offset within section->mr of the page base (otherwise)
+ *  + the ram_addr_t of the page base of the target RAM (RAM)
+ *  + the offset within section->mr of the page base (I/O, ROMD)
  * We subtract the vaddr_page (which is page aligned and thus won't
  * disturb the low bits) to give an offset which can be added to the
  * (non-page-aligned) vaddr of the eventual memory access to get
@@ -814,25 +843,14 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong 
vaddr,
 }
 
 if (prot & PAGE_EXEC) {
-tn.addr_code = code_address;
+tn.add

[PATCH v4 15/16] cputlb: Pass retaddr to tb_invalidate_phys_page_fast

2019-09-23 Thread Richard Henderson
Rather than rely on cpu->mem_io_pc, pass retaddr down directly.

Within tb_invalidate_phys_page_range__locked, the is_cpu_write_access
parameter is non-zero exactly when retaddr would be non-zero, so that
is a simple replacement.

Recognize that current_tb_not_found is true only when mem_io_pc
(and now retaddr) are also non-zero, so remove a redundant test.

Reviewed-by: David Hildenbrand 
Signed-off-by: Richard Henderson 
---
 accel/tcg/translate-all.h |  3 ++-
 accel/tcg/cputlb.c|  6 +-
 accel/tcg/translate-all.c | 39 +++
 3 files changed, 22 insertions(+), 26 deletions(-)

diff --git a/accel/tcg/translate-all.h b/accel/tcg/translate-all.h
index 31f2117188..135c1ea96a 100644
--- a/accel/tcg/translate-all.h
+++ b/accel/tcg/translate-all.h
@@ -27,7 +27,8 @@ struct page_collection *page_collection_lock(tb_page_addr_t 
start,
  tb_page_addr_t end);
 void page_collection_unlock(struct page_collection *set);
 void tb_invalidate_phys_page_fast(struct page_collection *pages,
-  tb_page_addr_t start, int len);
+  tb_page_addr_t start, int len,
+  uintptr_t retaddr);
 void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end);
 void tb_check_watchpoint(CPUState *cpu);
 
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index 0ca6ee60b3..ea5d12c59d 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -1093,11 +1093,7 @@ static void notdirty_write(CPUState *cpu, vaddr 
mem_vaddr, unsigned size,
 if (!cpu_physical_memory_get_dirty_flag(ram_addr, DIRTY_MEMORY_CODE)) {
 struct page_collection *pages
 = page_collection_lock(ram_addr, ram_addr + size);
-
-/* We require mem_io_pc in tb_invalidate_phys_page_range.  */
-cpu->mem_io_pc = retaddr;
-
-tb_invalidate_phys_page_fast(pages, ram_addr, size);
+tb_invalidate_phys_page_fast(pages, ram_addr, size, retaddr);
 page_collection_unlock(pages);
 }
 
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index de4b697163..db77fb221b 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -1889,7 +1889,7 @@ static void
 tb_invalidate_phys_page_range__locked(struct page_collection *pages,
   PageDesc *p, tb_page_addr_t start,
   tb_page_addr_t end,
-  int is_cpu_write_access)
+  uintptr_t retaddr)
 {
 TranslationBlock *tb;
 tb_page_addr_t tb_start, tb_end;
@@ -1897,9 +1897,9 @@ tb_invalidate_phys_page_range__locked(struct 
page_collection *pages,
 #ifdef TARGET_HAS_PRECISE_SMC
 CPUState *cpu = current_cpu;
 CPUArchState *env = NULL;
-int current_tb_not_found = is_cpu_write_access;
+bool current_tb_not_found = retaddr != 0;
+bool current_tb_modified = false;
 TranslationBlock *current_tb = NULL;
-int current_tb_modified = 0;
 target_ulong current_pc = 0;
 target_ulong current_cs_base = 0;
 uint32_t current_flags = 0;
@@ -1931,24 +1931,21 @@ tb_invalidate_phys_page_range__locked(struct 
page_collection *pages,
 if (!(tb_end <= start || tb_start >= end)) {
 #ifdef TARGET_HAS_PRECISE_SMC
 if (current_tb_not_found) {
-current_tb_not_found = 0;
-current_tb = NULL;
-if (cpu->mem_io_pc) {
-/* now we have a real cpu fault */
-current_tb = tcg_tb_lookup(cpu->mem_io_pc);
-}
+current_tb_not_found = false;
+/* now we have a real cpu fault */
+current_tb = tcg_tb_lookup(retaddr);
 }
 if (current_tb == tb &&
 (tb_cflags(current_tb) & CF_COUNT_MASK) != 1) {
-/* If we are modifying the current TB, we must stop
-its execution. We could be more precise by checking
-that the modification is after the current PC, but it
-would require a specialized function to partially
-restore the CPU state */
-
-current_tb_modified = 1;
-cpu_restore_state_from_tb(cpu, current_tb,
-  cpu->mem_io_pc, true);
+/*
+ * If we are modifying the current TB, we must stop
+ * its execution. We could be more precise by checking
+ * that the modification is after the current PC, but it
+ * would require a specialized function to partially
+ * restore the CPU state.
+ */
+current_tb_modified = true;
+cpu_restore_state_from_tb(cpu, current_tb, retaddr, true);
 cpu_get_tb_cpu_state(env, ¤t_pc, ¤t_cs_base,

[PATCH v4 07/16] exec: Adjust notdirty tracing

2019-09-23 Thread Richard Henderson
The memory_region_tb_read tracepoint is unreachable, since notdirty
is supposed to apply only to writes.  The memory_region_tb_write
tracepoint is mis-named, because notdirty is not only used for TB
invalidation.  It is also used for e.g. VGA RAM updates and migration.

Replace memory_region_tb_write with memory_notdirty_write_access,
and place it in memory_notdirty_write_prepare where it can catch
all of the instances.  Add memory_notdirty_set_dirty to log when
we no longer intercept writes to a page.

Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: David Hildenbrand 
Signed-off-by: Richard Henderson 
---
 exec.c   | 3 +++
 memory.c | 4 
 trace-events | 4 ++--
 3 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/exec.c b/exec.c
index 8b998974f8..5f2587b621 100644
--- a/exec.c
+++ b/exec.c
@@ -2755,6 +2755,8 @@ void memory_notdirty_write_prepare(NotDirtyInfo *ndi,
 ndi->size = size;
 ndi->pages = NULL;
 
+trace_memory_notdirty_write_access(mem_vaddr, ram_addr, size);
+
 assert(tcg_enabled());
 if (!cpu_physical_memory_get_dirty_flag(ram_addr, DIRTY_MEMORY_CODE)) {
 ndi->pages = page_collection_lock(ram_addr, ram_addr + size);
@@ -2779,6 +2781,7 @@ void memory_notdirty_write_complete(NotDirtyInfo *ndi)
 /* we remove the notdirty callback only if the code has been
flushed */
 if (!cpu_physical_memory_is_clean(ndi->ram_addr)) {
+trace_memory_notdirty_set_dirty(ndi->mem_vaddr);
 tlb_set_dirty(ndi->cpu, ndi->mem_vaddr);
 }
 }
diff --git a/memory.c b/memory.c
index b9dd6b94ca..57c44c97db 100644
--- a/memory.c
+++ b/memory.c
@@ -438,7 +438,6 @@ static MemTxResult  
memory_region_read_accessor(MemoryRegion *mr,
 /* Accesses to code which has previously been translated into a TB show
  * up in the MMIO path, as accesses to the io_mem_notdirty
  * MemoryRegion. */
-trace_memory_region_tb_read(get_cpu_index(), addr, tmp, size);
 } else if (TRACE_MEMORY_REGION_OPS_READ_ENABLED) {
 hwaddr abs_addr = memory_region_to_absolute_addr(mr, addr);
 trace_memory_region_ops_read(get_cpu_index(), mr, abs_addr, tmp, size);
@@ -465,7 +464,6 @@ static MemTxResult 
memory_region_read_with_attrs_accessor(MemoryRegion *mr,
 /* Accesses to code which has previously been translated into a TB show
  * up in the MMIO path, as accesses to the io_mem_notdirty
  * MemoryRegion. */
-trace_memory_region_tb_read(get_cpu_index(), addr, tmp, size);
 } else if (TRACE_MEMORY_REGION_OPS_READ_ENABLED) {
 hwaddr abs_addr = memory_region_to_absolute_addr(mr, addr);
 trace_memory_region_ops_read(get_cpu_index(), mr, abs_addr, tmp, size);
@@ -490,7 +488,6 @@ static MemTxResult 
memory_region_write_accessor(MemoryRegion *mr,
 /* Accesses to code which has previously been translated into a TB show
  * up in the MMIO path, as accesses to the io_mem_notdirty
  * MemoryRegion. */
-trace_memory_region_tb_write(get_cpu_index(), addr, tmp, size);
 } else if (TRACE_MEMORY_REGION_OPS_WRITE_ENABLED) {
 hwaddr abs_addr = memory_region_to_absolute_addr(mr, addr);
 trace_memory_region_ops_write(get_cpu_index(), mr, abs_addr, tmp, 
size);
@@ -515,7 +512,6 @@ static MemTxResult 
memory_region_write_with_attrs_accessor(MemoryRegion *mr,
 /* Accesses to code which has previously been translated into a TB show
  * up in the MMIO path, as accesses to the io_mem_notdirty
  * MemoryRegion. */
-trace_memory_region_tb_write(get_cpu_index(), addr, tmp, size);
 } else if (TRACE_MEMORY_REGION_OPS_WRITE_ENABLED) {
 hwaddr abs_addr = memory_region_to_absolute_addr(mr, addr);
 trace_memory_region_ops_write(get_cpu_index(), mr, abs_addr, tmp, 
size);
diff --git a/trace-events b/trace-events
index 823a4ae64e..20821ba545 100644
--- a/trace-events
+++ b/trace-events
@@ -52,14 +52,14 @@ dma_map_wait(void *dbs) "dbs=%p"
 find_ram_offset(uint64_t size, uint64_t offset) "size: 0x%" PRIx64 " @ 0x%" 
PRIx64
 find_ram_offset_loop(uint64_t size, uint64_t candidate, uint64_t offset, 
uint64_t next, uint64_t mingap) "trying size: 0x%" PRIx64 " @ 0x%" PRIx64 ", 
offset: 0x%" PRIx64" next: 0x%" PRIx64 " mingap: 0x%" PRIx64
 ram_block_discard_range(const char *rbname, void *hva, size_t length, bool 
need_madvise, bool need_fallocate, int ret) "%s@%p + 0x%zx: madvise: %d 
fallocate: %d ret: %d"
+memory_notdirty_write_access(uint64_t vaddr, uint64_t ram_addr, unsigned size) 
"0x%" PRIx64 " ram_addr 0x%" PRIx64 " size %u"
+memory_notdirty_set_dirty(uint64_t vaddr) "0x%" PRIx64
 
 # memory.c
 memory_region_ops_read(int cpu_index, void *mr, uint64_t addr, uint64_t value, 
unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u"
 memory_region_ops_write(int cpu_index, void *mr, uint64_t addr, uint64_t 
value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u"
 memory_region_sub

[PATCH v4 09/16] cputlb: Move NOTDIRTY handling from I/O path to TLB path

2019-09-23 Thread Richard Henderson
Pages that we want to track for NOTDIRTY are RAM.  We do not
really need to go through the I/O path to handle them.

Acked-by: David Hildenbrand 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 include/exec/cpu-common.h |  2 --
 accel/tcg/cputlb.c| 26 +---
 exec.c| 50 ---
 memory.c  | 16 -
 4 files changed, 23 insertions(+), 71 deletions(-)

diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
index 1c0e03ddc2..81753bbb34 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -100,8 +100,6 @@ void qemu_flush_coalesced_mmio_buffer(void);
 
 void cpu_flush_icache_range(hwaddr start, hwaddr len);
 
-extern struct MemoryRegion io_mem_notdirty;
-
 typedef int (RAMBlockIterFunc)(RAMBlock *rb, void *opaque);
 
 int qemu_ram_foreach_block(RAMBlockIterFunc func, void *opaque);
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index af9a44a847..05212ff244 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -904,7 +904,7 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry 
*iotlbentry,
 mr = section->mr;
 mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
 cpu->mem_io_pc = retaddr;
-if (mr != &io_mem_notdirty && !cpu->can_do_io) {
+if (!cpu->can_do_io) {
 cpu_io_recompile(cpu, retaddr);
 }
 
@@ -945,7 +945,7 @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry 
*iotlbentry,
 section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
 mr = section->mr;
 mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
-if (mr != &io_mem_notdirty && !cpu->can_do_io) {
+if (!cpu->can_do_io) {
 cpu_io_recompile(cpu, retaddr);
 }
 cpu->mem_io_vaddr = addr;
@@ -1607,7 +1607,7 @@ store_helper(CPUArchState *env, target_ulong addr, 
uint64_t val,
 need_swap = size > 1 && (tlb_addr & TLB_BSWAP);
 
 /* Handle I/O access.  */
-if (likely(tlb_addr & (TLB_MMIO | TLB_NOTDIRTY))) {
+if (tlb_addr & TLB_MMIO) {
 io_writex(env, iotlbentry, mmu_idx, val, addr, retaddr,
   op ^ (need_swap * MO_BSWAP));
 return;
@@ -1620,6 +1620,26 @@ store_helper(CPUArchState *env, target_ulong addr, 
uint64_t val,
 
 haddr = (void *)((uintptr_t)addr + entry->addend);
 
+/* Handle clean RAM pages.  */
+if (tlb_addr & TLB_NOTDIRTY) {
+NotDirtyInfo ndi;
+
+/* We require mem_io_pc in tb_invalidate_phys_page_range.  */
+env_cpu(env)->mem_io_pc = retaddr;
+
+memory_notdirty_write_prepare(&ndi, env_cpu(env), addr,
+  addr + iotlbentry->addr, size);
+
+if (unlikely(need_swap)) {
+store_memop(haddr, val, op ^ MO_BSWAP);
+} else {
+store_memop(haddr, val, op);
+}
+
+memory_notdirty_write_complete(&ndi);
+return;
+}
+
 if (unlikely(need_swap)) {
 store_memop(haddr, val, op ^ MO_BSWAP);
 } else {
diff --git a/exec.c b/exec.c
index ea8c0b18ac..dc7001f115 100644
--- a/exec.c
+++ b/exec.c
@@ -88,7 +88,6 @@ static MemoryRegion *system_io;
 AddressSpace address_space_io;
 AddressSpace address_space_memory;
 
-MemoryRegion io_mem_notdirty;
 static MemoryRegion io_mem_unassigned;
 #endif
 
@@ -191,7 +190,6 @@ typedef struct subpage_t {
 } subpage_t;
 
 #define PHYS_SECTION_UNASSIGNED 0
-#define PHYS_SECTION_NOTDIRTY 1
 
 static void io_mem_init(void);
 static void memory_map_init(void);
@@ -1472,9 +1470,6 @@ hwaddr memory_region_section_get_iotlb(CPUState *cpu,
 if (memory_region_is_ram(section->mr)) {
 /* Normal RAM.  */
 iotlb = memory_region_get_ram_addr(section->mr) + xlat;
-if (!section->readonly) {
-iotlb |= PHYS_SECTION_NOTDIRTY;
-}
 } else {
 AddressSpaceDispatch *d;
 
@@ -2783,42 +2778,6 @@ void memory_notdirty_write_complete(NotDirtyInfo *ndi)
 }
 }
 
-/* Called within RCU critical section.  */
-static void notdirty_mem_write(void *opaque, hwaddr ram_addr,
-   uint64_t val, unsigned size)
-{
-NotDirtyInfo ndi;
-
-memory_notdirty_write_prepare(&ndi, current_cpu, current_cpu->mem_io_vaddr,
- ram_addr, size);
-
-stn_p(qemu_map_ram_ptr(NULL, ram_addr), size, val);
-memory_notdirty_write_complete(&ndi);
-}
-
-static bool notdirty_mem_accepts(void *opaque, hwaddr addr,
- unsigned size, bool is_write,
- MemTxAttrs attrs)
-{
-return is_write;
-}
-
-static const MemoryRegionOps notdirty_mem_ops = {
-.write = notdirty_mem_write,
-.valid.accepts = notdirty_mem_accepts,
-.endianness = DEVICE_NATIVE_ENDIAN,
-.valid = {
-.min_access_size = 1,
-.max_access_size = 8,
- 

Re: [PATCH v2 04/16] tests/docker: reduce scary warnings from failed inspect

2019-09-23 Thread Alex Bennée


Cleber Rosa  writes:

> On Thu, Sep 19, 2019 at 06:10:03PM +0100, Alex Bennée wrote:
>> There is a race here in the clean-up code so lets just accept that
>> sometimes the active task we just looked up might have finished before
>> we got to inspect it.
>>
>> Signed-off-by: Alex Bennée 
>> ---
>>  tests/docker/docker.py | 32 ++--
>>  1 file changed, 18 insertions(+), 14 deletions(-)
>>
>> diff --git a/tests/docker/docker.py b/tests/docker/docker.py
>> index 29613afd489..4dca6006d2f 100755
>> --- a/tests/docker/docker.py
>> +++ b/tests/docker/docker.py
>> @@ -235,20 +235,24 @@ class Docker(object):
>>  if not only_active:
>>  cmd.append("-a")
>>  for i in self._output(cmd).split():
>> -resp = self._output(["inspect", i])
>> -labels = json.loads(resp)[0]["Config"]["Labels"]
>> -active = json.loads(resp)[0]["State"]["Running"]
>> -if not labels:
>> -continue
>> -instance_uuid = labels.get("com.qemu.instance.uuid", None)
>> -if not instance_uuid:
>> -continue
>> -if only_known and instance_uuid not in self._instances:
>> -continue
>> -print("Terminating", i)
>> -if active:
>> -self._do(["kill", i])
>> -self._do(["rm", i])
>> +try:
>> +resp = self._output(["inspect", i])
>> +labels = json.loads(resp)[0]["Config"]["Labels"]
>> +active = json.loads(resp)[0]["State"]["Running"]
>> +if not labels:
>> +continue
>> +instance_uuid = labels.get("com.qemu.instance.uuid", None)
>> +if not instance_uuid:
>> +continue
>> +if only_known and instance_uuid not in self._instances:
>> +continue
>> +print("Terminating", i)
>> +if active:
>> +self._do(["kill", i])
>> +self._do(["rm", i])
>
> Both podman and docker seem to handle "rm -f $INSTANCE" well, which
> would by itself consolidate the two commands in one and minimize the
> race condition.

It's the self.__output which is the real race condition because
check_output complains if the command doesn't succeed with 0. What we
really need is to find somewhat of filtering the ps just for qemu
instances and then just rm -f them as you suggest.

>
> For unexisting containers, and no other errors, podman will return "1
> if one of the specified containers did not exist, and no other
> failure", as per its man page.  I couldn't find any guarantee that
> docker will also return 1 on a similar situation, but that's what
> I've experienced too:
>
>  $ docker rm -f CONTAINER_IS_NOW_FONE
>  Error response from daemon: No such container: CONTAINER_IS_NOW_GONE
>  $ echo $?
>  1
>
> Maybe waiving exit status 1 and nothing else would do the trick here
> and not hide other real problems?
>
> - Cleber.
>
>> +except subprocess.CalledProcessError:
>> +# i likely finished running before we got here
>> +pass
>>
>>  def clean(self):
>>  self._do_kill_instances(False, False)
>> --
>> 2.20.1
>>
>>


--
Alex Bennée



[PATCH v4 12/16] cputlb: Handle TLB_NOTDIRTY in probe_access

2019-09-23 Thread Richard Henderson
We can use notdirty_write for the write and
return a valid host pointer for this case.

Signed-off-by: Richard Henderson 
---
 accel/tcg/cputlb.c | 26 +-
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index 09b0df87c6..d0bdef1eb3 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -1167,16 +1167,24 @@ void *probe_access(CPUArchState *env, target_ulong 
addr, int size,
 return NULL;
 }
 
-/* Handle watchpoints.  */
-if (tlb_addr & TLB_WATCHPOINT) {
-cpu_check_watchpoint(env_cpu(env), addr, size,
- env_tlb(env)->d[mmu_idx].iotlb[index].attrs,
- wp_access, retaddr);
-}
+if (unlikely(tlb_addr & TLB_FLAGS_MASK)) {
+CPUIOTLBEntry *iotlbentry = &env_tlb(env)->d[mmu_idx].iotlb[index];
 
-/* Reject I/O access, or other required slow-path.  */
-if (tlb_addr & (TLB_NOTDIRTY | TLB_MMIO | TLB_BSWAP | TLB_ROM)) {
-return NULL;
+/* Reject I/O access, or other required slow-path.  */
+if (tlb_addr & (TLB_MMIO | TLB_BSWAP | TLB_ROM)) {
+return NULL;
+}
+
+/* Handle watchpoints.  */
+if (tlb_addr & TLB_WATCHPOINT) {
+cpu_check_watchpoint(env_cpu(env), addr, size,
+ iotlbentry->attrs, wp_access, retaddr);
+}
+
+/* Handle clean RAM pages.  */
+if (tlb_addr & TLB_NOTDIRTY) {
+notdirty_write(env_cpu(env), addr, size, iotlbentry, retaddr);
+}
 }
 
 return (void *)((uintptr_t)addr + entry->addend);
-- 
2.17.1




[PATCH v4 06/16] cputlb: Introduce TLB_BSWAP

2019-09-23 Thread Richard Henderson
Handle bswap on ram directly in load/store_helper.  This fixes a
bug with the previous implementation in that one cannot use the
I/O path for RAM.

Fixes: a26fc6f5152b47f1
Reviewed-by: David Hildenbrand 
Signed-off-by: Richard Henderson 
---
 include/exec/cpu-all.h |  4 ++-
 accel/tcg/cputlb.c | 62 ++
 2 files changed, 36 insertions(+), 30 deletions(-)

diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index e0c8dc540c..d148bded35 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -335,12 +335,14 @@ CPUArchState *cpu_copy(CPUArchState *env);
 #define TLB_MMIO(1 << (TARGET_PAGE_BITS_MIN - 3))
 /* Set if TLB entry contains a watchpoint.  */
 #define TLB_WATCHPOINT  (1 << (TARGET_PAGE_BITS_MIN - 4))
+/* Set if TLB entry requires byte swap.  */
+#define TLB_BSWAP   (1 << (TARGET_PAGE_BITS_MIN - 5))
 
 /* Use this mask to check interception with an alignment mask
  * in a TCG backend.
  */
 #define TLB_FLAGS_MASK \
-(TLB_INVALID_MASK | TLB_NOTDIRTY | TLB_MMIO | TLB_WATCHPOINT)
+(TLB_INVALID_MASK | TLB_NOTDIRTY | TLB_MMIO | TLB_WATCHPOINT | TLB_BSWAP)
 
 /**
  * tlb_hit_page: return true if page aligned @addr is a hit against the
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index 430ba4a69d..f634edb4f4 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -737,8 +737,7 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong 
vaddr,
 address |= TLB_INVALID_MASK;
 }
 if (attrs.byte_swap) {
-/* Force the access through the I/O slow path.  */
-address |= TLB_MMIO;
+address |= TLB_BSWAP;
 }
 if (!memory_region_is_ram(section->mr) &&
 !memory_region_is_romd(section->mr)) {
@@ -901,10 +900,6 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry 
*iotlbentry,
 bool locked = false;
 MemTxResult r;
 
-if (iotlbentry->attrs.byte_swap) {
-op ^= MO_BSWAP;
-}
-
 section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
 mr = section->mr;
 mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
@@ -947,10 +942,6 @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry 
*iotlbentry,
 bool locked = false;
 MemTxResult r;
 
-if (iotlbentry->attrs.byte_swap) {
-op ^= MO_BSWAP;
-}
-
 section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
 mr = section->mr;
 mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
@@ -1133,8 +1124,8 @@ void *probe_access(CPUArchState *env, target_ulong addr, 
int size,
  wp_access, retaddr);
 }
 
-if (tlb_addr & (TLB_NOTDIRTY | TLB_MMIO)) {
-/* I/O access */
+/* Reject I/O access, or other required slow-path.  */
+if (tlb_addr & (TLB_NOTDIRTY | TLB_MMIO | TLB_BSWAP)) {
 return NULL;
 }
 
@@ -1344,6 +1335,7 @@ load_helper(CPUArchState *env, target_ulong addr, 
TCGMemOpIdx oi,
 /* Handle anything that isn't just a straight memory access.  */
 if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
 CPUIOTLBEntry *iotlbentry;
+bool need_swap;
 
 /* For anything that is unaligned, recurse through full_load.  */
 if ((addr & (size - 1)) != 0) {
@@ -1357,17 +1349,22 @@ load_helper(CPUArchState *env, target_ulong addr, 
TCGMemOpIdx oi,
 /* On watchpoint hit, this will longjmp out.  */
 cpu_check_watchpoint(env_cpu(env), addr, size,
  iotlbentry->attrs, BP_MEM_READ, retaddr);
-
-/* The backing page may or may not require I/O.  */
-tlb_addr &= ~TLB_WATCHPOINT;
-if ((tlb_addr & ~TARGET_PAGE_MASK) == 0) {
-goto do_aligned_access;
-}
 }
 
+need_swap = size > 1 && (tlb_addr & TLB_BSWAP);
+
 /* Handle I/O access.  */
-return io_readx(env, iotlbentry, mmu_idx, addr,
-retaddr, access_type, op);
+if (likely(tlb_addr & TLB_MMIO)) {
+return io_readx(env, iotlbentry, mmu_idx, addr, retaddr,
+access_type, op ^ (need_swap * MO_BSWAP));
+}
+
+haddr = (void *)((uintptr_t)addr + entry->addend);
+
+if (unlikely(need_swap)) {
+return load_memop(haddr, op ^ MO_BSWAP);
+}
+return load_memop(haddr, op);
 }
 
 /* Handle slow unaligned access (it spans two pages or IO).  */
@@ -1394,7 +1391,6 @@ load_helper(CPUArchState *env, target_ulong addr, 
TCGMemOpIdx oi,
 return res & MAKE_64BIT_MASK(0, size * 8);
 }
 
- do_aligned_access:
 haddr = (void *)((uintptr_t)addr + entry->addend);
 return load_memop(haddr, op);
 }
@@ -1592,6 +1588,7 @@ store_helper(CPUArchState *env, target_ulong addr, 
uint64_t val,
 /* Handle anything that isn't just a straight memory access.  */
 if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
 CPUIOTLBEntry *iotlbentry;
+  

[PATCH v4 02/16] cputlb: Disable __always_inline__ without optimization

2019-09-23 Thread Richard Henderson
This forced inlining can result in missing symbols,
which makes a debugging build harder to follow.

Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: David Hildenbrand 
Reported-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 include/qemu/compiler.h | 11 +++
 accel/tcg/cputlb.c  |  4 ++--
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h
index 09fc44cca4..20780e722d 100644
--- a/include/qemu/compiler.h
+++ b/include/qemu/compiler.h
@@ -170,6 +170,17 @@
 # define QEMU_NONSTRING
 #endif
 
+/*
+ * Forced inlining may be desired to encourage constant propagation
+ * of function parameters.  However, it can also make debugging harder,
+ * so disable it for a non-optimizing build.
+ */
+#if defined(__OPTIMIZE__)
+#define QEMU_ALWAYS_INLINE  __attribute__((always_inline))
+#else
+#define QEMU_ALWAYS_INLINE
+#endif
+
 /* Implement C11 _Generic via GCC builtins.  Example:
  *
  *QEMU_GENERIC(x, (float, sinf), (long double, sinl), sin) (x)
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index abae79650c..b87764 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -1281,7 +1281,7 @@ static void *atomic_mmu_lookup(CPUArchState *env, 
target_ulong addr,
 typedef uint64_t FullLoadHelper(CPUArchState *env, target_ulong addr,
 TCGMemOpIdx oi, uintptr_t retaddr);
 
-static inline uint64_t __attribute__((always_inline))
+static inline uint64_t QEMU_ALWAYS_INLINE
 load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
 uintptr_t retaddr, MemOp op, bool code_read,
 FullLoadHelper *full_load)
@@ -1530,7 +1530,7 @@ tcg_target_ulong helper_be_ldsl_mmu(CPUArchState *env, 
target_ulong addr,
  * Store Helpers
  */
 
-static inline void __attribute__((always_inline))
+static inline void QEMU_ALWAYS_INLINE
 store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
  TCGMemOpIdx oi, uintptr_t retaddr, MemOp op)
 {
-- 
2.17.1




[PATCH v4 04/16] cputlb: Use optimize_away in load/store_helpers

2019-09-23 Thread Richard Henderson
Increase the current runtime assert to a compile-time assert.

Signed-off-by: Richard Henderson 
---
 accel/tcg/cputlb.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index b87764..e529af6d09 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -1396,7 +1396,7 @@ load_helper(CPUArchState *env, target_ulong addr, 
TCGMemOpIdx oi,
 res = ldq_le_p(haddr);
 break;
 default:
-g_assert_not_reached();
+optimize_away();
 }
 
 return res;
@@ -1680,8 +1680,7 @@ store_helper(CPUArchState *env, target_ulong addr, 
uint64_t val,
 stq_le_p(haddr, val);
 break;
 default:
-g_assert_not_reached();
-break;
+optimize_away();
 }
 }
 
-- 
2.17.1




[PATCH v4 08/16] cputlb: Move ROM handling from I/O path to TLB path

2019-09-23 Thread Richard Henderson
It does not require going through the whole I/O path
in order to discard a write.

Reviewed-by: David Hildenbrand 
Signed-off-by: Richard Henderson 
---
 include/exec/cpu-all.h|  5 -
 include/exec/cpu-common.h |  1 -
 accel/tcg/cputlb.c| 35 +++--
 exec.c| 41 +--
 4 files changed, 25 insertions(+), 57 deletions(-)

diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index d148bded35..26547cd6dd 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -337,12 +337,15 @@ CPUArchState *cpu_copy(CPUArchState *env);
 #define TLB_WATCHPOINT  (1 << (TARGET_PAGE_BITS_MIN - 4))
 /* Set if TLB entry requires byte swap.  */
 #define TLB_BSWAP   (1 << (TARGET_PAGE_BITS_MIN - 5))
+/* Set if TLB entry writes ignored.  */
+#define TLB_ROM (1 << (TARGET_PAGE_BITS_MIN - 6))
 
 /* Use this mask to check interception with an alignment mask
  * in a TCG backend.
  */
 #define TLB_FLAGS_MASK \
-(TLB_INVALID_MASK | TLB_NOTDIRTY | TLB_MMIO | TLB_WATCHPOINT | TLB_BSWAP)
+(TLB_INVALID_MASK | TLB_NOTDIRTY | TLB_MMIO \
+| TLB_WATCHPOINT | TLB_BSWAP | TLB_ROM)
 
 /**
  * tlb_hit_page: return true if page aligned @addr is a hit against the
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
index f7dbe75fbc..1c0e03ddc2 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -100,7 +100,6 @@ void qemu_flush_coalesced_mmio_buffer(void);
 
 void cpu_flush_icache_range(hwaddr start, hwaddr len);
 
-extern struct MemoryRegion io_mem_rom;
 extern struct MemoryRegion io_mem_notdirty;
 
 typedef int (RAMBlockIterFunc)(RAMBlock *rb, void *opaque);
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index f634edb4f4..af9a44a847 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -577,7 +577,7 @@ static void tlb_reset_dirty_range_locked(CPUTLBEntry 
*tlb_entry,
 {
 uintptr_t addr = tlb_entry->addr_write;
 
-if ((addr & (TLB_INVALID_MASK | TLB_MMIO | TLB_NOTDIRTY)) == 0) {
+if ((addr & (TLB_INVALID_MASK | TLB_MMIO | TLB_ROM | TLB_NOTDIRTY)) == 0) {
 addr &= TARGET_PAGE_MASK;
 addr += tlb_entry->addend;
 if ((addr - start) < length) {
@@ -745,7 +745,6 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong 
vaddr,
 address |= TLB_MMIO;
 addend = 0;
 } else {
-/* TLB_MMIO for rom/romd handled below */
 addend = (uintptr_t)memory_region_get_ram_ptr(section->mr) + xlat;
 }
 
@@ -822,16 +821,17 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong 
vaddr,
 
 tn.addr_write = -1;
 if (prot & PAGE_WRITE) {
-if ((memory_region_is_ram(section->mr) && section->readonly)
-|| memory_region_is_romd(section->mr)) {
-/* Write access calls the I/O callback.  */
-tn.addr_write = address | TLB_MMIO;
-} else if (memory_region_is_ram(section->mr)
-   && cpu_physical_memory_is_clean(
-   memory_region_get_ram_addr(section->mr) + xlat)) {
-tn.addr_write = address | TLB_NOTDIRTY;
-} else {
-tn.addr_write = address;
+tn.addr_write = address;
+if (memory_region_is_romd(section->mr)) {
+/* Use the MMIO path so that the device can switch states. */
+tn.addr_write |= TLB_MMIO;
+} else if (memory_region_is_ram(section->mr)) {
+if (section->readonly) {
+tn.addr_write |= TLB_ROM;
+} else if (cpu_physical_memory_is_clean(
+memory_region_get_ram_addr(section->mr) + xlat)) {
+tn.addr_write |= TLB_NOTDIRTY;
+}
 }
 if (prot & PAGE_WRITE_INV) {
 tn.addr_write |= TLB_INVALID_MASK;
@@ -904,7 +904,7 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry 
*iotlbentry,
 mr = section->mr;
 mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
 cpu->mem_io_pc = retaddr;
-if (mr != &io_mem_rom && mr != &io_mem_notdirty && !cpu->can_do_io) {
+if (mr != &io_mem_notdirty && !cpu->can_do_io) {
 cpu_io_recompile(cpu, retaddr);
 }
 
@@ -945,7 +945,7 @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry 
*iotlbentry,
 section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
 mr = section->mr;
 mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
-if (mr != &io_mem_rom && mr != &io_mem_notdirty && !cpu->can_do_io) {
+if (mr != &io_mem_notdirty && !cpu->can_do_io) {
 cpu_io_recompile(cpu, retaddr);
 }
 cpu->mem_io_vaddr = addr;
@@ -1125,7 +1125,7 @@ void *probe_access(CPUArchState *env, target_ulong addr, 
int size,
 }
 
 /* Reject I/O access, or other required slow-path.  */
-if (tlb_addr & (TLB_NOTDIRTY | TLB_MMIO | TLB_BSWAP)) {
+if (tlb_addr & (TLB_NOTDIRTY | TLB_MMIO | TLB_BSWAP | TLB_ROM)) {
 return NULL;

[PATCH v4 03/16] qemu/compiler.h: Add optimize_away

2019-09-23 Thread Richard Henderson
Use this as a compile-time assert that a particular
code path is not reachable.

Signed-off-by: Richard Henderson 
---
 include/qemu/compiler.h | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h
index 20780e722d..6604ccea92 100644
--- a/include/qemu/compiler.h
+++ b/include/qemu/compiler.h
@@ -221,4 +221,19 @@
 #define QEMU_GENERIC9(x, a0, ...) QEMU_GENERIC_IF(x, a0, QEMU_GENERIC8(x, 
__VA_ARGS__))
 #define QEMU_GENERIC10(x, a0, ...) QEMU_GENERIC_IF(x, a0, QEMU_GENERIC9(x, 
__VA_ARGS__))
 
+/**
+ * optimize_away()
+ *
+ * The compiler, during optimization, is expected to prove that a call
+ * to this function cannot be reached and remove it.  If the compiler
+ * supports QEMU_ERROR, this will be reported at compile time; otherwise
+ * this will be reported at link time, due to the missing symbol.
+ */
+#ifdef __OPTIMIZE__
+extern void QEMU_NORETURN QEMU_ERROR("code path is reachable")
+optimize_away(void);
+#else
+#define optimize_away()  g_assert_not_reached()
+#endif
+
 #endif /* COMPILER_H */
-- 
2.17.1




[PATCH v4 00/16] Move rom and notdirty handling to cputlb

2019-09-23 Thread Richard Henderson
Changes since v3:
  * Don't accidentally include the TARGET_PAGE_BITS_VARY patch set.  ;-)
  * Remove __has_attribute(__always_inline__).
  * Use single load/store_memop function instead of separate small wrappers.
  * Introduce optimize_away to assert the code folds away as expected.

Patches without review:

0003-qemu-compiler.h-Add-optimize_away.patch
0004-cputlb-Use-optimize_away-in-load-store_helpers.patch
0005-cputlb-Split-out-load-store_memop.patch
0010-cputlb-Partially-inline-memory_region_section_get.patch
0011-cputlb-Merge-and-move-memory_notdirty_write_-prep.patch
0012-cputlb-Handle-TLB_NOTDIRTY-in-probe_access.patch


r~


Richard Henderson (16):
  exec: Use TARGET_PAGE_BITS_MIN for TLB flags
  cputlb: Disable __always_inline__ without optimization
  qemu/compiler.h: Add optimize_away
  cputlb: Use optimize_away in load/store_helpers
  cputlb: Split out load/store_memop
  cputlb: Introduce TLB_BSWAP
  exec: Adjust notdirty tracing
  cputlb: Move ROM handling from I/O path to TLB path
  cputlb: Move NOTDIRTY handling from I/O path to TLB path
  cputlb: Partially inline memory_region_section_get_iotlb
  cputlb: Merge and move memory_notdirty_write_{prepare,complete}
  cputlb: Handle TLB_NOTDIRTY in probe_access
  cputlb: Remove cpu->mem_io_vaddr
  cputlb: Remove tb_invalidate_phys_page_range is_cpu_write_access
  cputlb: Pass retaddr to tb_invalidate_phys_page_fast
  cputlb: Pass retaddr to tb_check_watchpoint

 accel/tcg/translate-all.h  |   8 +-
 include/exec/cpu-all.h |  23 ++-
 include/exec/cpu-common.h  |   3 -
 include/exec/exec-all.h|   6 +-
 include/exec/memory-internal.h |  65 ---
 include/hw/core/cpu.h  |   2 -
 include/qemu/compiler.h|  26 +++
 accel/tcg/cputlb.c | 340 +++--
 accel/tcg/translate-all.c  |  51 +++--
 exec.c | 158 +--
 hw/core/cpu.c  |   1 -
 memory.c   |  20 --
 trace-events   |   4 +-
 13 files changed, 279 insertions(+), 428 deletions(-)

-- 
2.17.1




[PATCH v4 01/16] exec: Use TARGET_PAGE_BITS_MIN for TLB flags

2019-09-23 Thread Richard Henderson
These bits do not need to vary with the actual page size
used by the guest.

Reviewed-by: David Hildenbrand 
Reviewed-by: Paolo Bonzini 
Signed-off-by: Richard Henderson 
---
 include/exec/cpu-all.h | 16 ++--
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index d2d443c4f9..e0c8dc540c 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -317,20 +317,24 @@ CPUArchState *cpu_copy(CPUArchState *env);
 
 #if !defined(CONFIG_USER_ONLY)
 
-/* Flags stored in the low bits of the TLB virtual address.  These are
- * defined so that fast path ram access is all zeros.
+/*
+ * Flags stored in the low bits of the TLB virtual address.
+ * These are defined so that fast path ram access is all zeros.
  * The flags all must be between TARGET_PAGE_BITS and
  * maximum address alignment bit.
+ *
+ * Use TARGET_PAGE_BITS_MIN so that these bits are constant
+ * when TARGET_PAGE_BITS_VARY is in effect.
  */
 /* Zero if TLB entry is valid.  */
-#define TLB_INVALID_MASK(1 << (TARGET_PAGE_BITS - 1))
+#define TLB_INVALID_MASK(1 << (TARGET_PAGE_BITS_MIN - 1))
 /* Set if TLB entry references a clean RAM page.  The iotlb entry will
contain the page physical address.  */
-#define TLB_NOTDIRTY(1 << (TARGET_PAGE_BITS - 2))
+#define TLB_NOTDIRTY(1 << (TARGET_PAGE_BITS_MIN - 2))
 /* Set if TLB entry is an IO callback.  */
-#define TLB_MMIO(1 << (TARGET_PAGE_BITS - 3))
+#define TLB_MMIO(1 << (TARGET_PAGE_BITS_MIN - 3))
 /* Set if TLB entry contains a watchpoint.  */
-#define TLB_WATCHPOINT  (1 << (TARGET_PAGE_BITS - 4))
+#define TLB_WATCHPOINT  (1 << (TARGET_PAGE_BITS_MIN - 4))
 
 /* Use this mask to check interception with an alignment mask
  * in a TCG backend.
-- 
2.17.1




Re: [Qemu-devel] [PATCH v6 0/4] 9p: Fix file ID collisions

2019-09-23 Thread Jeff King
On Mon, Sep 23, 2019 at 01:19:18PM +0200, Christian Schoenebeck wrote:

> > if (cmit_fmt_is_mail(pp->fmt)) {
> > -   if (pp->from_ident && ident_cmp(pp->from_ident, &ident)) {
> > +   if (pp->always_use_in_body_from ||
> > +   (pp->from_ident && ident_cmp(pp->from_ident, &ident))) {
> > struct strbuf buf = STRBUF_INIT;
> > 
> > strbuf_addstr(&buf, "From: ");
> > 
> > but most of the work would be ferrying that option from the command line
> > down to the pretty-print code.
> > 
> > That would work in conjunction with "--from" to avoid a duplicate. It
> > might require send-email learning about the option to avoid doing its
> > own in-body-from management. If you only care about send-email, it might
> > be easier to just add the option there.
> 
> Would it simplify the changes in git if that would be made a
> "git config [--global]" setting only? That is, would that probably simplify 
> that task to one simple function call there in pretty.c?

I think a config option would make sense, but we generally try to avoid
adding a config option that doesn't have a matching command-line option.

I also think saving implementation work there is orthogonal. You can as
easily make a global "always_use_in_body_from" as you can call a global
config_get_bool("format-patch.always_use_in_body_from"). :)

And anyway, it's not _that_ much work to pass it around. At least as
much would go into writing documentation and tests. One of the reasons I
left the patch above as a sketch is that I'm not 100% convinced this is
a useful feature. Somebody caring enough about it to make a real patch
would send a signal there.

> On the other hand, considering the already existing --from argument and 
> "format.from" config option:
> https://git-scm.com/docs/git-config#Documentation/git-config.txt-formatfrom
> 
> Wouldn't it make sense to just drop the currently existing sender != author 
> string comparison in git and simply always add the "From:" line to the 
> email's 
> body if "format.from yes" is used, instead of introducing a suggested 2nd 
> (e.g. "always-from") option? I mean sure automatically removing redundant 
> information in the generated emails if sender == author sounds nice on first 
> thought, but does it address anything useful in practice to justify 
> introduction of a 2nd related option?

Yes, the resulting mail would be correct, in the sense that it could be
applied just fine by git-am. But I think it would be uglier. IOW, I
consider the presence of the in-body From to be a clue that something
interesting is going on (like forwarding somebody else's patch). So from
my perspective, it would just be useless noise. Other communities may
have different opinions, though (I think I have seen some kernel folks
always including all of the possible in-body headers, including Date).
But it seems like it makes sense to keep both possibilities.

-Peff



Re: [PATCH v1 5/6] riscv/virt: Add the PFlash CFI01 device

2019-09-23 Thread Peter Maydell
On Fri, 20 Sep 2019 at 23:23, Alistair Francis  wrote:
> On Thu, Sep 19, 2019 at 10:15 PM Bin Meng  wrote:
> > I don't think we should mirror what is used on ARM virt board to
> > create 2 flash for sifive_u. For ARM virt, there are 2 flashes because
> > they need distinguish secure and non-secure. For sifive_u, only one is
> > enough.
>
> I went back and forward about 1 or 2. Two seems more usable as maybe
> someone wants to include two pflash files? The Xilinx machine also has
> two so I'm kind of used to 2, but I'm not really fussed.

One of the reasons for having 2 on the Arm board (we do this
even if we're not supporting secure vs non-secure) is that
then you can use one for a fixed read-only BIOS image (backed
by a file on the host filesystem shared between all VMs), and
one backed by a read-write per-VM file providing permanent
storage for BIOS environment variables. Notably UEFI likes to
work this way, but the idea applies in theory to other
boot loader or BIOSes I guess.

I would suggest also checking with Markus that your code
for instantiating the flash devices follows the current
recommendations so the backing storage can be configured
via -blockdev. (This is a fairly recent change from June or
so; current-in-master virt and sbsa boards provide an example
of doing the right thing, I think.)

thanks
-- PMM



[PATCH] ui: fix keymap file search in input-barrier object

2019-09-23 Thread Laurent Vivier
If we try to start QEMU with "-k en-us", qemu prints a message and exits
with:

qemu-system-i386: could not read keymap file: 'en-us'

It's because this function is called way too early, before
qemu_add_data_dir() is called, and so qemu_find_file() fails.

To fix that, move init_keyboard_layout() from the class init function to the
instance init function.

Reported-by: Anthony PERARD 
Fixes: 6105683da35b ("ui: add an embedded Barrier client")
Signed-off-by: Laurent Vivier 
---
 ui/input-barrier.c | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/ui/input-barrier.c b/ui/input-barrier.c
index a2c961f285a4..fe35049b83a2 100644
--- a/ui/input-barrier.c
+++ b/ui/input-barrier.c
@@ -682,6 +682,13 @@ static void input_barrier_instance_init(Object *obj)
 {
 InputBarrier *ib = INPUT_BARRIER(obj);
 
+/* always use generic keymaps */
+if (keyboard_layout && !kbd_layout) {
+/* We use X11 key id, so use VNC name2keysym */
+kbd_layout = init_keyboard_layout(name2keysym, keyboard_layout,
+  &error_fatal);
+}
+
 ib->saddr.type = SOCKET_ADDRESS_TYPE_INET;
 ib->saddr.u.inet.host = g_strdup("localhost");
 ib->saddr.u.inet.port = g_strdup("24800");
@@ -719,13 +726,6 @@ static void input_barrier_class_init(ObjectClass *oc, void 
*data)
 UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
 
 ucc->complete = input_barrier_complete;
-
-/* always use generic keymaps */
-if (keyboard_layout) {
-/* We use X11 key id, so use VNC name2keysym */
-kbd_layout = init_keyboard_layout(name2keysym, keyboard_layout,
-  &error_fatal);
-}
 }
 
 static const TypeInfo input_barrier_info = {
-- 
2.21.0




Re: [PULL 00/30] s390x/tcg update

2019-09-23 Thread Peter Maydell
On Mon, 23 Sep 2019 at 09:07, David Hildenbrand  wrote:
>
> Hi Peter,
>
> here is the updated tcg subset of the s390x update (including one more
> test).
>
> The following changes since commit 4300b7c2cd9f3f273804e8cca325842ccb93b1ad:
>
>   Merge remote-tracking branch 'remotes/cleber/tags/python-next-pull-request' 
> into staging (2019-09-20 17:28:43 +0100)
>
> are available in the Git repository at:
>
>   https://github.com/davidhildenbrand/qemu.git tags/s390x-tcg-2019-09-23
>
> for you to fetch changes up to 5d69cbdfdd5cd6dadc9f0c986899844a0e4de703:
>
>   tests/tcg: target/s390x: Test MVC (2019-09-23 09:28:29 +0200)
>
> 
> Fix a bunch of BUGs in the mem-helpers (including the MVC instruction),
> especially, to make them behave correctly on faults.
>


Applied, thanks.

Please update the changelog at https://wiki.qemu.org/ChangeLog/4.2
for any user-visible changes.

-- PMM



Re: [Qemu-block] [PATCH v6 5/8] bootdevice: Gather LCHS from all relevant devices

2019-09-23 Thread John Snow



On 8/27/19 4:24 AM, Sam Eiderman via Qemu-block wrote:
> From: Sam Eiderman 
> 
> Relevant devices are:
> * ide-hd (and ide-cd, ide-drive)
> * scsi-hd (and scsi-cd, scsi-disk, scsi-block)
> * virtio-blk-pci
> 
> We do not call del_boot_device_lchs() for ide-* since we don't need to -
> IDE block devices do not support unplugging.
> 
> Signed-off-by: Sam Eiderman 
> Reviewed-by: Karl Heubaum 
> Reviewed-by: Arbel Moshe 
> Signed-off-by: Sam Eiderman 

Acked-by: John Snow 

> ---
>  hw/block/virtio-blk.c |  6 ++
>  hw/ide/qdev.c |  5 +
>  hw/scsi/scsi-disk.c   | 12 
>  3 files changed, 23 insertions(+)
> 
> diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
> index 18851601cb..6d8ff34a16 100644
> --- a/hw/block/virtio-blk.c
> +++ b/hw/block/virtio-blk.c
> @@ -1186,6 +1186,11 @@ static void virtio_blk_device_realize(DeviceState 
> *dev, Error **errp)
>  blk_set_guest_block_size(s->blk, s->conf.conf.logical_block_size);
>  
>  blk_iostatus_enable(s->blk);
> +
> +add_boot_device_lchs(dev, "/disk@0,0",
> + conf->conf.lcyls,
> + conf->conf.lheads,
> + conf->conf.lsecs);
>  }
>  
>  static void virtio_blk_device_unrealize(DeviceState *dev, Error **errp)
> @@ -1193,6 +1198,7 @@ static void virtio_blk_device_unrealize(DeviceState 
> *dev, Error **errp)
>  VirtIODevice *vdev = VIRTIO_DEVICE(dev);
>  VirtIOBlock *s = VIRTIO_BLK(dev);
>  
> +del_boot_device_lchs(dev, "/disk@0,0");
>  virtio_blk_data_plane_destroy(s->dataplane);
>  s->dataplane = NULL;
>  qemu_del_vm_change_state_handler(s->change);
> diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
> index 6dd219944f..2ffd387a73 100644
> --- a/hw/ide/qdev.c
> +++ b/hw/ide/qdev.c
> @@ -220,6 +220,11 @@ static void ide_dev_initfn(IDEDevice *dev, IDEDriveKind 
> kind, Error **errp)
>  
>  add_boot_device_path(dev->conf.bootindex, &dev->qdev,
>   dev->unit ? "/disk@1" : "/disk@0");
> +
> +add_boot_device_lchs(&dev->qdev, dev->unit ? "/disk@1" : "/disk@0",
> + dev->conf.lcyls,
> + dev->conf.lheads,
> + dev->conf.lsecs);
>  }
>  
>  static void ide_dev_get_bootindex(Object *obj, Visitor *v, const char *name,
> diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
> index 915641a0f1..d19896fe4d 100644
> --- a/hw/scsi/scsi-disk.c
> +++ b/hw/scsi/scsi-disk.c
> @@ -35,6 +35,7 @@
>  #include "hw/block/block.h"
>  #include "hw/qdev-properties.h"
>  #include "sysemu/dma.h"
> +#include "sysemu/sysemu.h"
>  #include "qemu/cutils.h"
>  #include "trace.h"
>  
> @@ -2402,6 +2403,16 @@ static void scsi_realize(SCSIDevice *dev, Error **errp)
>  blk_set_guest_block_size(s->qdev.conf.blk, s->qdev.blocksize);
>  
>  blk_iostatus_enable(s->qdev.conf.blk);
> +
> +add_boot_device_lchs(&dev->qdev, NULL,
> + dev->conf.lcyls,
> + dev->conf.lheads,
> + dev->conf.lsecs);
> +}
> +
> +static void scsi_unrealize(SCSIDevice *dev, Error **errp)
> +{
> +del_boot_device_lchs(&dev->qdev, NULL);
>  }
>  
>  static void scsi_hd_realize(SCSIDevice *dev, Error **errp)
> @@ -3006,6 +3017,7 @@ static void scsi_hd_class_initfn(ObjectClass *klass, 
> void *data)
>  SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
>  
>  sc->realize  = scsi_hd_realize;
> +sc->unrealize= scsi_unrealize;
>  sc->alloc_req= scsi_new_request;
>  sc->unit_attention_reported = scsi_disk_unit_attention_reported;
>  dc->desc = "virtual SCSI disk";
> 



Re: Debian support lifetime (was Re: [PATCH] docker: move tests from python2 to python3)

2019-09-23 Thread John Snow



On 9/23/19 3:05 PM, Eduardo Habkost wrote:
> On Mon, Sep 23, 2019 at 01:19:41PM -0400, John Snow wrote:
>> On 9/23/19 10:50 AM, Cleber Rosa wrote:
> [...]
 diff --git a/tests/docker/dockerfiles/debian-xtensa-cross.docker 
 b/tests/docker/dockerfiles/debian-xtensa-cross.docker
 index b9c2e2e531..e6f93f65ee 100644
 --- a/tests/docker/dockerfiles/debian-xtensa-cross.docker
 +++ b/tests/docker/dockerfiles/debian-xtensa-cross.docker
 @@ -18,7 +18,7 @@ RUN apt-get update && \
  flex \
  gettext \
  git \
 -python-minimal
 +python3-minimal
>>>
>>> I'm getting Python 3.5.3-1+deb9u1 here, so it LGTM.
>>>
>>
>> Oh, that's actually a bit of a problem. I tested on 3.5+, but I think
>> some people want 3.6+.
>>
>> I don't know much about Debian, but we either need to guarantee 3.6+ or
>> backtrack our plans to 3.5+.
> 
> Good catch.  I forgot we were going to keep 3.5 support because
> of Debian 9.
> 
> Now, I'd like to clarify what the wording on our supported build
> platforms documentation is supposed to mean for Debian.
> 
> The document says:
> 
> ] For distributions with frequent, short-lifetime releases, the project will
> ] aim to support all versions that are not end of life by their respective
> ] vendors. For the purposes of identifying supported software versions, the
> ] project will look at Fedora, Ubuntu, and openSUSE distros. Other short-
> ] lifetime distros will be assumed to ship similar software versions.
> ] 

Fedora has a release every 6-9 months, and averages a support lifetime
of a little over a year, and never more than two years.

Debian releases once every two years since 2005, and has a support cycle
that averages about 3 years. (Notably, this means a release reaches EOL
one year after the next release.)

Ubuntu releases every six months, with support for just eight months.

OpenSUSE has a release about every year or so; support is presently 18
months.

> ] For distributions with long-lifetime releases, the project will aim to 
> support
> ] the most recent major version at all times. Support for the previous major
> ] version will be dropped 2 years after the new major version is released. For
> ] the purposes of identifying supported software versions, the project will 
> look
> ] at RHEL, Debian, Ubuntu LTS, and SLES distros. Other long-lifetime distros 
> will
> ] be assumed to ship similar software versions.
> 

Here's an enumeration of supported long-lifetime build platforms as
interpreted from the above text; using standard end-of-service dates
(EOS) when available in preference to EOL dates for special support
contracts.

RHEL6: 2010 - 2016 [EOS: 2021]
RHEL7: 2014 - 2021 [EOS: 2024+]
RHEL8: 2019 - ??   [EOS: 2029+]

Ubuntu 14.04 LTS: 2014-04 -- 2018-04 [EOS: 2019-04]
Ubuntu 16.04 LTS: 2016-04 -- 2020-04 [EOS: 2021-04]
Ubuntu 18.04 LTS: 2018-04 -- 2022-04 [EOS: 2023-04]
Ubuntu 20.04 LTS: 2020-04 -- 2024-04 [EOS: 2025?]

SLES 11: 2009 - 2016 [EOS: 2019]
SLES 12: 2014 - 2020 [EOS: 2024]
SLES 15: 2018 - ~2024? [EOS: 2028]

Debian 8: 2015 - 2019 [EOL: 2018]
Debian 9: 2017 - 2021 [EOL: ~2020]
Debian 10: 2019 - ~2023? [EOL: ~2022]

Whoops, our proclaimed support for Debian indeed carries on after its
EOL by an entire year.

> Debian 10 was released in July 2019.  Are we really willing to
> support Debian 9 as a supported build platform until July 2021?
> The Debian Project itself won't support Debian 9 after July 2020.
> 
> Even for other long-lifetime distros, I really think "2 years
> after the new major version is released" is too long, and I'd
> like to shorten this to 1 year.
> 

Two years for Debian feels too long, but one year for things like RHEL
feels too short.

We could treat Debian more like a "short cycle" distro in terms of our
policy -- it stands out amongst the other long-term distros with its
relatively short support lifespans.


I'd recommend something like the following:

For both enterprise distributions (Ubuntu LTS, RHEL, SLES) AND community
distributions (Ubuntu Interim, Debian Stable, Fedora, OpenSUSE); QEMU
will support previous releases for two years, until the end of standard
service, or until EOL, whichever occurs first.

In practice: this means 2 years for old versions of SLES, RHEL and
Ubuntu LTS, but we expire alongside EOL for Debian, Fedora, Ubuntu
(Interim), and OpenSUSE.

... Or, more or less, it would be like treating Debian as a short-cycle
project instead of a long-cycle one under our current rules.

--js



Re: [RFC v2 6/9] scripts: add coccinelle script to use auto propagated errp

2019-09-23 Thread Eric Blake
On 9/23/19 3:05 PM, Eric Blake wrote:

> Does running this Coccinelle script 2 times in a row add a second
> ERRP_FUNCTION_BEGIN() line?  We want it to be idempotent (no changes on
> a second run).  (Admittedly, I did not actually test that yet).  Also, I
> don't know if this can be tweaked to avoid adding the line to a function
> with an empty body, maybe:
> 
>  fn(..., Error **errp, ...)
>  {
> +ERRP_FUNCTION_BEGIN();
>  ...
>  }

Also untested:

 fn(..., Error **errp, ...)
 {
(
|
 ERRP_FUNCTION_BEGIN();
 ...
|
+ERRP_FUNCTION_BEGIN()
 ...
)
 }


> Overall, the script makes sense in my reading (but no idea if it
> actually catches everything we want, or if it missed something).

Having spot-checked 7, it definitely misses cases where it was supposed
to add ERRP_FUNCTION_BEGIN().

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3226
Virtualization:  qemu.org | libvirt.org



Re: [RFC v2 6/9] scripts: add coccinelle script to use auto propagated errp

2019-09-23 Thread Eric Blake
On 9/23/19 11:12 AM, Vladimir Sementsov-Ogievskiy wrote:
> Signed-off-by: Vladimir Sementsov-Ogievskiy 
> ---
>  scripts/coccinelle/auto-propagated-errp.cocci | 82 +++
>  1 file changed, 82 insertions(+)
>  create mode 100644 scripts/coccinelle/auto-propagated-errp.cocci
> 
> diff --git a/scripts/coccinelle/auto-propagated-errp.cocci 
> b/scripts/coccinelle/auto-propagated-errp.cocci
> new file mode 100644
> index 00..1a3f006f0b
> --- /dev/null
> +++ b/scripts/coccinelle/auto-propagated-errp.cocci
> @@ -0,0 +1,82 @@
> +@@
> +identifier fn;
> +identifier local_err;
> +@@
> +
> + fn(..., Error **errp)
> + {
> ++ERRP_FUNCTION_BEGIN();
> + }

This doesn't catch functions where Error **errp is not the last
parameter.  Some examples (some of which may need independent tweaking
in their own right for being inconsistent, although we DO want errp to
appear before any 'format, ...' arguments):

block/ssh.c:sftp_error_setg(Error **errp, BDRVSSHState *s, const char
*fs, ...)
exec.c:static void ram_block_add(RAMBlock *new_block, Error **errp, bool
shared)

Does running this Coccinelle script 2 times in a row add a second
ERRP_FUNCTION_BEGIN() line?  We want it to be idempotent (no changes on
a second run).  (Admittedly, I did not actually test that yet).  Also, I
don't know if this can be tweaked to avoid adding the line to a function
with an empty body, maybe:

 fn(..., Error **errp, ...)
 {
+ERRP_FUNCTION_BEGIN();
 ...
 }

to only add it to a function that already has a body (thanks to the ...)
- but I'm fuzzy enough on Coccinelle that I may be saying something
totally wrong.

> +
> +@rule1@
> +identifier fn;
> +identifier local_err;
> +@@
> +
> + fn(..., Error **errp)
> + {
> + <...
> +-Error *local_err = NULL;
> + ...>
> + }
> +
> +@@
> +identifier rule1.fn;
> +identifier rule1.local_err;
> +identifier out;
> +@@
> +
> + fn(...)
> + {
> + <...
> +-goto out;
> ++return;
> + ...>
> +- out:
> +-error_propagate(errp, local_err);
> + }
> +
> +@@
> +identifier rule1.fn;
> +identifier rule1.local_err;
> +@@
> +
> + fn(...)
> + {
> + <...
> +(
> +-error_free(local_err);
> +-local_err = NULL;
> ++error_free_errp(errp);
> +|
> +-error_free(local_err);
> ++error_free_errp(errp);
> +|
> +-error_report_err(local_err);
> ++error_report_errp(errp);
> +|
> +-warn_report_err(local_err);
> ++warn_report_errp(errp);
> +|
> +-error_propagate(errp, local_err);
> +)
> + ...>
> + }
> +
> +@@
> +identifier rule1.fn;
> +identifier rule1.local_err;
> +@@
> +
> + fn(...)
> + {
> + <...
> +(
> +-&local_err
> ++errp
> +|
> +-local_err
> ++*errp
> +)
> + ...>
> + }
> 

Overall, the script makes sense in my reading (but no idea if it
actually catches everything we want, or if it missed something).  At any
rate, once patch 7 is split into more manageable chunks, we can
definitely spot-check results to make sure they all look reasonable.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3226
Virtualization:  qemu.org | libvirt.org



Re: [PATCH v2 04/16] tests/docker: reduce scary warnings from failed inspect

2019-09-23 Thread Cleber Rosa
On Thu, Sep 19, 2019 at 06:10:03PM +0100, Alex Bennée wrote:
> There is a race here in the clean-up code so lets just accept that
> sometimes the active task we just looked up might have finished before
> we got to inspect it.
> 
> Signed-off-by: Alex Bennée 
> ---
>  tests/docker/docker.py | 32 ++--
>  1 file changed, 18 insertions(+), 14 deletions(-)
> 
> diff --git a/tests/docker/docker.py b/tests/docker/docker.py
> index 29613afd489..4dca6006d2f 100755
> --- a/tests/docker/docker.py
> +++ b/tests/docker/docker.py
> @@ -235,20 +235,24 @@ class Docker(object):
>  if not only_active:
>  cmd.append("-a")
>  for i in self._output(cmd).split():
> -resp = self._output(["inspect", i])
> -labels = json.loads(resp)[0]["Config"]["Labels"]
> -active = json.loads(resp)[0]["State"]["Running"]
> -if not labels:
> -continue
> -instance_uuid = labels.get("com.qemu.instance.uuid", None)
> -if not instance_uuid:
> -continue
> -if only_known and instance_uuid not in self._instances:
> -continue
> -print("Terminating", i)
> -if active:
> -self._do(["kill", i])
> -self._do(["rm", i])
> +try:
> +resp = self._output(["inspect", i])
> +labels = json.loads(resp)[0]["Config"]["Labels"]
> +active = json.loads(resp)[0]["State"]["Running"]
> +if not labels:
> +continue
> +instance_uuid = labels.get("com.qemu.instance.uuid", None)
> +if not instance_uuid:
> +continue
> +if only_known and instance_uuid not in self._instances:
> +continue
> +print("Terminating", i)
> +if active:
> +self._do(["kill", i])
> +self._do(["rm", i])

Both podman and docker seem to handle "rm -f $INSTANCE" well, which
would by itself consolidate the two commands in one and minimize the
race condition.

For unexisting containers, and no other errors, podman will return "1
if one of the specified containers did not exist, and no other
failure", as per its man page.  I couldn't find any guarantee that
docker will also return 1 on a similar situation, but that's what
I've experienced too:

 $ docker rm -f CONTAINER_IS_NOW_FONE
 Error response from daemon: No such container: CONTAINER_IS_NOW_GONE
 $ echo $?
 1

Maybe waiving exit status 1 and nothing else would do the trick here
and not hide other real problems?

- Cleber.

> +except subprocess.CalledProcessError:
> +# i likely finished running before we got here
> +pass
>  
>  def clean(self):
>  self._do_kill_instances(False, False)
> -- 
> 2.20.1
> 
> 



Re: [RFC v2 4/9] hw/core/loader-fit: fix freeing errp in fit_load_fdt

2019-09-23 Thread Eric Blake
On 9/23/19 11:12 AM, Vladimir Sementsov-Ogievskiy wrote:
> fit_load_fdt forget to zero errp. Fix it.
> 
> Signed-off-by: Vladimir Sementsov-Ogievskiy 
> ---
>  hw/core/loader-fit.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 

Independent bug fix.  Either we take the (fixed) 2-3 (to rely on the new
error_free_errp), or you could open-code the assignment of errp=NULL to
take this on its own, regardless of the hfate of the rest of the series.

Reviewed-by: Eric Blake 

> diff --git a/hw/core/loader-fit.c b/hw/core/loader-fit.c
> index 953b16bc82..fe5bcc6700 100644
> --- a/hw/core/loader-fit.c
> +++ b/hw/core/loader-fit.c
> @@ -200,7 +200,7 @@ static int fit_load_fdt(const struct fit_loader *ldr, 
> const void *itb,
>  err = fit_image_addr(itb, img_off, "load", &load_addr, errp);
>  if (err == -ENOENT) {
>  load_addr = ROUND_UP(kernel_end, 64 * KiB) + (10 * MiB);
> -error_free(*errp);
> +error_free_errp(errp);
>  } else if (err) {
>  error_prepend(errp, "unable to read FDT load address from FIT: ");
>  ret = err;
> 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3226
Virtualization:  qemu.org | libvirt.org



Re: [RFC v2 2/9] qapi/error: add (Error **errp) cleaning APIs

2019-09-23 Thread Eric Blake
On 9/23/19 11:12 AM, Vladimir Sementsov-Ogievskiy wrote:
> Signed-off-by: Vladimir Sementsov-Ogievskiy 
> ---

A "why" as the commit message body wouldn't hurt.

>  include/qapi/error.h | 22 ++
>  util/error.c |  6 +++---
>  2 files changed, 25 insertions(+), 3 deletions(-)
> 
> diff --git a/include/qapi/error.h b/include/qapi/error.h
> index f6f4fa0fac..551385aa91 100644
> --- a/include/qapi/error.h
> +++ b/include/qapi/error.h
> @@ -297,6 +297,28 @@ void warn_report_err(Error *err);
>   */
>  void error_report_err(Error *err);
>  
> +/*
> + * Functions to clean Error **errp: call corresponding Error *err cleaning
> + * function an set pointer to NULL

s/an/and/

> + */
> +static inline void error_free_errp(Error **errp)
> +{
> +error_free(*errp_in);

Fails to compile.  Did you mean for this to come after 3/9?

> +*errp_in = NULL;
> +}
> +
> +static inline void error_report_errp(Error **errp)
> +{
> +error_report_err(*errp_in);
> +*errp_in = NULL;
> +}
> +
> +static inline void warn_report_errp(Error **errp)
> +{
> +warn_report_err(*errp_in);
> +*errp_in = NULL;
> +}
> +
>  /*
>   * Convenience function to error_prepend(), warn_report() and free @err.
>   */
> diff --git a/util/error.c b/util/error.c
> index d4532ce318..dfba091757 100644
> --- a/util/error.c
> +++ b/util/error.c
> @@ -273,9 +273,9 @@ void error_free(Error *err)
>  
>  void error_free_or_abort(Error **errp)
>  {
> -assert(errp && *errp);
> -error_free(*errp);
> -*errp = NULL;
> +assert(errp_in && *errp_in);
> +error_free(*errp_in);
> +*errp_in = NULL;

Did you mean to use error_free_errp() instead of these last two lines?

>  }
>  
>  void error_propagate(Error **dst_errp, Error *local_err)
> 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3226
Virtualization:  qemu.org | libvirt.org



Re: [RFC v2 0/9] error: auto propagated local_err

2019-09-23 Thread Eric Blake
On 9/23/19 11:12 AM, Vladimir Sementsov-Ogievskiy wrote:
> Hi all!
> 
> Here is a proposal of auto propagation for local_err, to not call
> error_propagate on every exit point, when we deal with local_err.
> 
> It also fixes two issues:
> 1. Fix issue with error_fatal & error_append_hint: user can't see these
> hints, because exit() happens in error_setg earlier than hint is
> appended. [Reported by Greg Kurz]
> 
> 2. Fix issue with error_abort & error_propagate: when we wrap
> error_abort by local_err+error_propagate, resulting coredump will
> refer to error_propagate and not to the place where error happened.
> (the macro itself don't fix the issue, but it allows to [3.] drop all

doesn't

> local_err+error_propagate pattern, which will definitely fix the issue)
> [Reported by Kevin Wolf]
> 
> It's still an RFC, due to the following reasons:
> 
> 1. I'm new to coccinella, so I failed to do the following pattern:
> 
>  <...
> - goto out;
> + return;
>  ...>
> - out:
> - error_propagate(errp, local_err)
> 
> So, here is compilation fix 08.. Who can help with it? If nobody, 08 is
> to be merged to 07 by hand.

I'm not sure either; but I agree that if we can't figure out how to make
Coccinelle do quite what we want, that we are better off squashing in
compile fixes.

Also, while I like Coccinelle for automating the conversion, it's harder
to get everyone to run it; it would be nice if we could also figure out
a patch to scripts/checkpatch.pl that for any instance of 'Error
**errp)\n{\n' not followed by either } or the new macro, we flag that as
a checkpatch warning or error.

> 
> 2. Question about using new macro in empty stub functions - see 09

It would be nice if we could exempt empty functions - no need to use the
macro if there is no function body otherwise.  I'm not sure if
Coccinelle can do that filtering during the conversion, or if we clean
up by hand after the fact.

> 
> 3. What to do with huge auto-generated commit 07? Should I split it
> per-maintainer or per-subsystem, or leave it as-is?

It's big. I'd split it into multiple patches (and reduce the cc - except
for the cover letter, the rest of the patches can be limited to the
actual maintainer/subsystem affected rather than everyone involved
anywhere else in the series. With the current large cc, anyone that
replies gets several mail bounces about "too many recipients").  It may
be easier to split along directory boundaries than by maintainer
boundaries.  Markus has applied large tree-wide Coccinelle cleanups
before, maybe he has some advice.

> 
> 4. Also, checkpatch has some complains about 07 patch:
>   - using tabs.. (hmm exactly stubs functions..)
>   - empty ifs
>   Again, I don't see any ways to fix it other that by hand and merge to
>   07..

Hand cleanups for formatting or compilation fixes to Coccinelle's work
is not an uncommon issue after large patches; thankfully it's also not
very difficult (and surprisingly needed in very few places compared to
how much actually gets touched).

> 
> ==
> 
> Also, if we decide, that this all is too huge, here is plan B:
> 
> 1. apply 01
> 2. fix only functions that don't use local_err and use
> error_append_hint, by just invocation of new macro at function start -
> it will substitute Greg's series with no pain.
> 3[optional]. Do full update for some subsystems, for example, only for
> block* and nbd*

Even if we go with plan B, it's still worth checking in a Coccinelle
script that we can periodically run to make sure we aren't missing out
on the use of the macro where it is needed.

> 
> Vladimir Sementsov-Ogievskiy (9):
>   error: auto propagated local_err
>   qapi/error: add (Error **errp) cleaning APIs
>   errp: rename errp to errp_in where it is IN-argument
>   hw/core/loader-fit: fix freeing errp in fit_load_fdt
>   net/net: fix local variable shadowing in net_client_init
>   scripts: add coccinelle script to use auto propagated errp
>   Use auto-propagated errp
>   fix-compilation: empty goto
>   fix-compilation: includes
> 
>  include/hw/pci-host/spapr.h   |   2 +
>  include/monitor/hmp.h |   2 +-
>  include/qapi/error.h  |  61 -
>  target/ppc/kvm_ppc.h  |   3 +
>  target/s390x/cpu_models.h |   3 +
>  ui/vnc.h  |   2 +-

>  vl.c  |  13 +-
>  scripts/coccinelle/auto-propagated-errp.cocci |  82 +++
>  319 files changed, 2729 insertions(+), 4245 deletions(-)
>  create mode 100644 scripts/coccinelle/auto-propagated-errp.cocci

The diffstat is huge, but promising.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3226
Virtualization:  qemu.org | libvirt.org



Re: [RFC v2 3/9] errp: rename errp to errp_in where it is IN-argument

2019-09-23 Thread Eric Blake
On 9/23/19 11:12 AM, Vladimir Sementsov-Ogievskiy wrote:
> Error **errp is almost always OUT-argument: it's assumed to be NULL, or
> pointer to NULL-initialized pointer, or pointer to error_abort or
> error_fatal, for callee to report error.
> 
> But very few functions (most of the are error API) instead get Error
> **errp as IN-argument: it's assumed to be set, and callee should clean
> it. In such cases, rename errp to errp_in.
> 
> Signed-off-by: Vladimir Sementsov-Ogievskiy 
> ---
>  include/monitor/hmp.h |  2 +-
>  include/qapi/error.h  |  8 
>  ui/vnc.h  |  2 +-
>  monitor/hmp-cmds.c|  8 
>  ui/vnc.c  | 10 +-
>  util/error.c  |  2 +-
>  6 files changed, 16 insertions(+), 16 deletions(-)

This is worthwhile, regardless of the fate of the rest of the series.

Reviewed-by: Eric Blake 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3226
Virtualization:  qemu.org | libvirt.org



Re: [RFC v2 5/9] net/net: fix local variable shadowing in net_client_init

2019-09-23 Thread Eric Blake
On 9/23/19 11:12 AM, Vladimir Sementsov-Ogievskiy wrote:
> Don't shadow Error *err: it's a bad thing. This patch also simplifies
> following Error propagation conversion.
> 
> Signed-off-by: Vladimir Sementsov-Ogievskiy 
> ---
>  net/net.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)

Can be applied independently of the rest of this series.

> 
> diff --git a/net/net.c b/net/net.c
> index 84aa6d8d00..5fc72511c1 100644
> --- a/net/net.c
> +++ b/net/net.c
> @@ -1128,10 +1128,10 @@ static int net_client_init(QemuOpts *opts, bool 
> is_netdev, Error **errp)
>  
>  if (substrings[1]) {
>  /* User-specified prefix length.  */
> -int err;
> +int ret2;
>  
> -err = qemu_strtoul(substrings[1], NULL, 10, &prefix_len);
> -if (err) {
> +ret2 = qemu_strtoul(substrings[1], NULL, 10, &prefix_len);
> +if (ret2) {

In fact, you don't need ret2; you could just:

if (qemu_strtoul(...)) {

at which point you could then join:

if (substrings[1] &&
qemus_strtoul(...)) {

>  error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
> "ipv6-prefixlen", "a number");
>  goto out;
> 

Either way,

Reviewed-by: Eric Blake 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3226
Virtualization:  qemu.org | libvirt.org



Re: [RFC v2 7/9] Use auto-propagated errp

2019-09-23 Thread Eric Blake
On 9/23/19 11:12 AM, Vladimir Sementsov-Ogievskiy wrote:
> This commit is generated by command
> 
> git grep -l 'Error \*\*errp' | while read f; \
> do spatch --sp-file \
> scripts/coccinelle/auto-propagated-errp.cocci --in-place $f; done
> 

As mentioned in your cover letter, this fails syntax-check and
compilation without squashing in some followups; if we can't improve the
.cocci script to do it automatically, then manually squashing in
cleanups (and documenting what types of cleanups they were) is fine.
(The goal for a mechanical patch like this is to make it easy enough to
automate downstream, even where the file contents are changed, but where
the process for creating those changes are the same).

> Signed-off-by: Vladimir Sementsov-Ogievskiy 
> ---

Spot-checking

>  block/io.c  |  11 +-

>  block/nbd.c |  44 +++---

>  qapi/qapi-visit-core.c  |  53 ++-

just to see how it looks.

> +++ b/block/io.c
> @@ -136,7 +136,6 @@ static void bdrv_merge_limits(BlockLimits *dst, const 
> BlockLimits *src)
>  void bdrv_refresh_limits(BlockDriverState *bs, Error **errp)
>  {
>  BlockDriver *drv = bs->drv;
> -Error *local_err = NULL;
>  

Umm, no insertion of ERR_FUNCTION_BEGIN().  Oops.

>  memset(&bs->bl, 0, sizeof(bs->bl));
>  
> @@ -151,9 +150,8 @@ void bdrv_refresh_limits(BlockDriverState *bs, Error 
> **errp)
>  
>  /* Take some limits from the children as a default */
>  if (bs->file) {
> -bdrv_refresh_limits(bs->file->bs, &local_err);
> -if (local_err) {
> -error_propagate(errp, local_err);
> +bdrv_refresh_limits(bs->file->bs, errp);
> +if (*errp) {
>  return;
>  }
>  bdrv_merge_limits(&bs->bl, &bs->file->bs->bl);
> @@ -166,9 +164,8 @@ void bdrv_refresh_limits(BlockDriverState *bs, Error 
> **errp)
>  }
>  
>  if (bs->backing) {
> -bdrv_refresh_limits(bs->backing->bs, &local_err);
> -if (local_err) {
> -error_propagate(errp, local_err);
> +bdrv_refresh_limits(bs->backing->bs, errp);
> +if (*errp) {
>  return;

Rest of the changes in this file are good if the macro gets added correctly.

>  }
>  bdrv_merge_limits(&bs->bl, &bs->backing->bs->bl);

> +++ b/block/nbd.c
> @@ -808,7 +808,6 @@ static int nbd_co_receive_cmdread_reply(BDRVNBDState *s, 
> uint64_t handle,
>  NBDReplyChunkIter iter;
>  NBDReply reply;
>  void *payload = NULL;
> -Error *local_err = NULL;

Recurring problem of not inserting the macro as expected.

>  
>  NBD_FOREACH_REPLY_CHUNK(s, iter, handle, s->info.structured_reply,
>  qiov, &reply, &payload)
> @@ -827,20 +826,20 @@ static int nbd_co_receive_cmdread_reply(BDRVNBDState 
> *s, uint64_t handle,
>  break;
>  case NBD_REPLY_TYPE_OFFSET_HOLE:
>  ret = nbd_parse_offset_hole_payload(s, &reply.structured, 
> payload,
> -offset, qiov, &local_err);
> +offset, qiov, errp);
>  if (ret < 0) {
>  nbd_channel_error(s, ret);
> -nbd_iter_channel_error(&iter, ret, &local_err);
> +nbd_iter_channel_error(&iter, ret, errp);
>  }
>  break;
>  default:
>  if (!nbd_reply_type_is_error(chunk->type)) {
>  /* not allowed reply type */
>  nbd_channel_error(s, -EINVAL);
> -error_setg(&local_err,
> +error_setg(errp,
> "Unexpected reply type: %d (%s) for CMD_READ",

Could almost fold these lines (but I'm not asking you to; keeping this
patch as mechanical as possible is fine).

> chunk->type, nbd_reply_type_lookup(chunk->type));
> -nbd_iter_channel_error(&iter, -EINVAL, &local_err);
> +nbd_iter_channel_error(&iter, -EINVAL, errp);
>  }
>  }
>  
> @@ -861,7 +860,6 @@ static int nbd_co_receive_blockstatus_reply(BDRVNBDState 
> *s,
>  NBDReplyChunkIter iter;
>  NBDReply reply;
>  void *payload = NULL;
> -Error *local_err = NULL;
>  bool received = false;

Oops on the macro.

> @@ -1174,15 +1172,13 @@ static QIOChannelSocket 
> *nbd_establish_connection(SocketAddress *saddr,
>Error **errp)
>  {
>  QIOChannelSocket *sioc;
> -Error *local_err = NULL;
>  
>  sioc = qio_channel_socket_new();
>  qio_channel_set_name(QIO_CHANNEL(sioc), "nbd-client");
>  
> -qio_channel_socket_connect_sync(sioc, saddr, &local_err);
> -if (local_err) {
> +qio_channel_socket_connect_sync(sioc, saddr, errp);
> +if (*errp) {
>  object_unref(OBJECT(sioc));
> -error_propagate(errp, local_err);
>  return NULL;

But getting rid of error_propagate()

Re: [RFC v2 1/9] error: auto propagated local_err

2019-09-23 Thread Eric Blake
On 9/23/19 11:12 AM, Vladimir Sementsov-Ogievskiy wrote:
> Here is introduced ERRP_FUNCTION_BEGIN macro, to be used at start of
> any function with errp parameter.
> 
> It has three goals:
> 
> 1. Fix issue with error_fatal & error_append_hint: user can't see these
> hints, because exit() happens in error_setg earlier than hint is
> appended. [Reported by Greg Kurz]
> 
> 2. Fix issue with error_abort & error_propagate: when we wrap
> error_abort by local_err+error_propagate, resulting coredump will
> refer to error_propagate and not to the place where error happened.
> (the macro itself don't fix the issue, but it allows to [3.] drop all

doesn't

> local_err+error_propagate pattern, which will definitely fix the issue)
> [Reported by Kevin Wolf]
> 
> 3. Drop local_err+error_propagate pattern, which is used to workaround
> void functions with errp parameter, when caller wants to know resulting
> status. (Note: actually these functions should be merely updated to

Maybe:

s/should/could/

> return int error code).
> 
> Signed-off-by: Vladimir Sementsov-Ogievskiy 
> ---
>  include/qapi/error.h | 37 +
>  1 file changed, 37 insertions(+)
> 
> diff --git a/include/qapi/error.h b/include/qapi/error.h
> index 3f95141a01..f6f4fa0fac 100644
> --- a/include/qapi/error.h
> +++ b/include/qapi/error.h
> @@ -322,6 +322,43 @@ void error_set_internal(Error **errp,
>  ErrorClass err_class, const char *fmt, ...)
>  GCC_FMT_ATTR(6, 7);
>  
> +typedef struct ErrorPropagator {
> +Error *local_err;
> +Error **errp;
> +} ErrorPropagator;
> +
> +static inline void error_propagator_cleanup(ErrorPropagator *prop)
> +{
> +error_propagate(prop->errp, prop->local_err);
> +}
> +
> +G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(ErrorPropagator, error_propagator_cleanup);
> +
> +/*
> + * ERRP_FUNCTION_BEGIN
> + *
> + * This macro MUST be the first line of EACH function with Error **errp
> + * parameter.

Maybe s/EACH function/ANY non-empty function/ (allowing our stub
functions to be exemptions).

> + *
> + * If errp is NULL or points to error_fatal, it is rewritten to point to

s/to/to a/

> + * local Error object, which will be automatically propagated to original

s/to/to the/

> + * errp on function exit (see error_propagator_cleanup).
> + *
> + * After invocation of this macro it is always safe to dereference errp
> + * (as it's not NULL anymore) and to append hint (by error_append_hint)

s/append hint/append hints/

> + * (as, if it was error_fatal, we swapped it by local_error to be

s/by local_error/with a local error/

> + * propagated on cleanup).
> + *
> + * Note: we don't wrap error_abort case, as we want resulting coredump
> + * to point to the place where the error happened, not to error_propagate.

s/wrap/wrap the/

> + */
> +#define ERRP_FUNCTION_BEGIN() \
> +g_auto(ErrorPropagator) __auto_errp_prop = {.errp = errp}; \
> +Error **__local_errp_unused __attribute__ ((unused)) = \
> +(errp = (errp == NULL || *errp == error_fatal ? \
> + &__auto_errp_prop.local_err : errp))

I'm not sold on why we need the dummy declaration (yeah, I know it's so
that you don't have to fight the battle of mixing declarations and
statements - but this is in a macro call whose usage LOOKS like a
statement rather than a declaration, so we're already on fuzzy ground).
We could make this macro expansion one line shorter and still be
correct, but I'm not going to insist (we'll see what consensus is,
and/or what Markus says).

> +
> +
>  /*
>   * Special error destination to abort on error.
>   * See error_setg() and error_propagate() for details.
> 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3226
Virtualization:  qemu.org | libvirt.org



Re: [PULL 00/30] s390x/tcg update

2019-09-23 Thread no-reply
Patchew URL: https://patchew.org/QEMU/20190923080712.23951-1-da...@redhat.com/



Hi,

This series seems to have some coding style problems. See output below for
more information:

Message-id: 20190923080712.23951-1-da...@redhat.com
Subject: [PULL 00/30] s390x/tcg update
Type: series

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

From https://github.com/patchew-project/qemu
 - [tag update]  patchew/20190923080712.23951-1-da...@redhat.com -> 
patchew/20190923080712.23951-1-da...@redhat.com
Switched to a new branch 'test'
8444594 tests/tcg: target/s390x: Test MVC
ee2ed6d tests/tcg: target/s390x: Test MVO
7b0e80e s390x/tcg: MVO: Fault-safe handling
9790bed s390x/tcg: MVST: Fault-safe handling
12658d2 s390x/tcg: MVZ: Fault-safe handling
371cae1 s390x/tcg: MVN: Fault-safe handling
87a7cbd s390x/tcg: MVCIN: Fault-safe handling
200a39a s390x/tcg: NC: Fault-safe handling
08ce1db s390x/tcg: XC: Fault-safe handling
ef2eb0b s390x/tcg: OC: Fault-safe handling
1a01d78 s390x/tcg: MVCLU: Fault-safe handling
25baafe s390x/tcg: MVC: Fault-safe handling on destructive overlaps
8848832 s390x/tcg: MVCS/MVCP: Use access_memmove()
fae34f8 s390x/tcg: Fault-safe memmove
4bb7e2d s390x/tcg: Fault-safe memset
d965ec2 s390x/tcg: Always use MMU_USER_IDX for CONFIG_USER_ONLY
5a5dcf2 s390x/tcg: MVST: Fix storing back the addresses to registers
57c4578 s390x/tcg: MVST: Check for specification exceptions
b45d82e s390x/tcg: MVCS/MVCP: Properly wrap the length
96a5992 s390x/tcg: MVCOS: Lengths are 32 bit in 24/31-bit mode
97a8db7 s390x/tcg: MVCS/MVCP: Check for special operation exceptions
ba37bf0 s390x/tcg: MVCLU/MVCLE: Process max 4k bytes at a time
f2d36b3 s390x/tcg: MVPG: Properly wrap the addresses
2b5d295 s390x/tcg: MVPG: Check for specification exceptions
e8cc891 s390x/tcg: MVC: Use is_destructive_overlap()
afc7b33 s390x/tcg: MVC: Increment the length once
9720059 s390x/tcg: MVCL: Process max 4k bytes at a time
6f05a52 s390x/tcg: MVCL: Detect destructive overlaps
cdeec53 s390x/tcg: MVCL: Zero out unused bits of address
c4938ed s390x/tcg: Reset exception_index to -1 instead of 0

=== OUTPUT BEGIN ===
1/30 Checking commit c4938edb13bc (s390x/tcg: Reset exception_index to -1 
instead of 0)
2/30 Checking commit cdeec532ad35 (s390x/tcg: MVCL: Zero out unused bits of 
address)
3/30 Checking commit 6f05a524b299 (s390x/tcg: MVCL: Detect destructive overlaps)
4/30 Checking commit 97200592f682 (s390x/tcg: MVCL: Process max 4k bytes at a 
time)
5/30 Checking commit afc7b33a5e55 (s390x/tcg: MVC: Increment the length once)
6/30 Checking commit e8cc891074c3 (s390x/tcg: MVC: Use is_destructive_overlap())
7/30 Checking commit 2b5d29504cd0 (s390x/tcg: MVPG: Check for specification 
exceptions)
8/30 Checking commit f2d36b3cc65e (s390x/tcg: MVPG: Properly wrap the addresses)
9/30 Checking commit ba37bf02af24 (s390x/tcg: MVCLU/MVCLE: Process max 4k bytes 
at a time)
10/30 Checking commit 97a8db757a04 (s390x/tcg: MVCS/MVCP: Check for special 
operation exceptions)
11/30 Checking commit 96a599293f36 (s390x/tcg: MVCOS: Lengths are 32 bit in 
24/31-bit mode)
12/30 Checking commit b45d82e2df86 (s390x/tcg: MVCS/MVCP: Properly wrap the 
length)
13/30 Checking commit 57c45783106b (s390x/tcg: MVST: Check for specification 
exceptions)
14/30 Checking commit 5a5dcf274a03 (s390x/tcg: MVST: Fix storing back the 
addresses to registers)
15/30 Checking commit d965ec28dd7c (s390x/tcg: Always use MMU_USER_IDX for 
CONFIG_USER_ONLY)
16/30 Checking commit 4bb7e2d79eb8 (s390x/tcg: Fault-safe memset)
17/30 Checking commit fae34f841740 (s390x/tcg: Fault-safe memmove)
18/30 Checking commit 88488321fd07 (s390x/tcg: MVCS/MVCP: Use access_memmove())
19/30 Checking commit 25baafe3dc44 (s390x/tcg: MVC: Fault-safe handling on 
destructive overlaps)
20/30 Checking commit 1a01d784e526 (s390x/tcg: MVCLU: Fault-safe handling)
21/30 Checking commit ef2eb0b81437 (s390x/tcg: OC: Fault-safe handling)
22/30 Checking commit 08ce1db165f6 (s390x/tcg: XC: Fault-safe handling)
23/30 Checking commit 200a39a6646c (s390x/tcg: NC: Fault-safe handling)
24/30 Checking commit 87a7cbd6ecb8 (s390x/tcg: MVCIN: Fault-safe handling)
25/30 Checking commit 371cae1d272f (s390x/tcg: MVN: Fault-safe handling)
26/30 Checking commit 12658d24f74c (s390x/tcg: MVZ: Fault-safe handling)
27/30 Checking commit 9790bedceafa (s390x/tcg: MVST: Fault-safe handling)
28/30 Checking commit 7b0e80e77ad1 (s390x/tcg: MVO: Fault-safe handling)
29/30 Checking commit ee2ed6d1c8e1 (tests/tcg: target/s390x: Test MVO)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#24: 
new file mode 100644

total: 0 errors, 1 warnings, 29 lines checked

Patch 29/30 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
30

Re: [PATCH v1 5/6] riscv/virt: Add the PFlash CFI01 device

2019-09-23 Thread Alistair Francis
On Sat, Sep 21, 2019 at 7:15 PM Bin Meng  wrote:
>
> On Sat, Sep 21, 2019 at 6:16 AM Alistair Francis  wrote:
> >
> > On Thu, Sep 19, 2019 at 10:15 PM Bin Meng  wrote:
> > >
> > > On Fri, Sep 20, 2019 at 6:36 AM Alistair Francis
> > >  wrote:
> > > >
> > > > Add the CFI01 PFlash to the RISC-V virt board. This is the same PFlash
> > > > from the ARM Virt board and the implementation is based on the ARM Virt
> > > > board. This allows users to specify flash files from the command line.
> > > >
> > > > Signed-off-by: Alistair Francis 
> > > > ---
> > > >  hw/riscv/Kconfig|  1 +
> > > >  hw/riscv/virt.c | 81 +
> > > >  include/hw/riscv/virt.h |  3 ++
> > > >  3 files changed, 85 insertions(+)
> > > >
> > > > diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
> > > > index fb19b2df3a..b12660b9f8 100644
> > > > --- a/hw/riscv/Kconfig
> > > > +++ b/hw/riscv/Kconfig
> > > > @@ -36,4 +36,5 @@ config RISCV_VIRT
> > > >  select SERIAL
> > > >  select VIRTIO_MMIO
> > > >  select PCI_EXPRESS_GENERIC_BRIDGE
> > > > +select PFLASH_CFI01
> > > >  select SIFIVE
> > > > diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> > > > index d36f5625ec..ca002ecea7 100644
> > > > --- a/hw/riscv/virt.c
> > > > +++ b/hw/riscv/virt.c
> > > > @@ -26,6 +26,7 @@
> > > >  #include "hw/boards.h"
> > > >  #include "hw/loader.h"
> > > >  #include "hw/sysbus.h"
> > > > +#include "hw/qdev-properties.h"
> > > >  #include "hw/char/serial.h"
> > > >  #include "target/riscv/cpu.h"
> > > >  #include "hw/riscv/riscv_hart.h"
> > > > @@ -61,12 +62,72 @@ static const struct MemmapEntry {
> > > >  [VIRT_PLIC] ={  0xc00, 0x400 },
> > > >  [VIRT_UART0] =   { 0x1000, 0x100 },
> > > >  [VIRT_VIRTIO] =  { 0x10001000,0x1000 },
> > > > +[VIRT_FLASH] =   { 0x2000, 0x200 },
> > > >  [VIRT_DRAM] ={ 0x8000,   0x0 },
> > > >  [VIRT_PCIE_MMIO] =   { 0x4000,0x4000 },
> > > >  [VIRT_PCIE_PIO] ={ 0x0300,0x0001 },
> > > >  [VIRT_PCIE_ECAM] =   { 0x3000,0x1000 },
> > > >  };
> > > >
> > > > +#define VIRT_FLASH_SECTOR_SIZE (256 * KiB)
> > > > +
> > > > +static PFlashCFI01 *virt_flash_create1(RISCVVirtState *s,
> > > > +   const char *name,
> > > > +   const char *alias_prop_name)
> > > > +{
> > > > +/*
> > > > + * Create a single flash device.  We use the same parameters as
> > > > + * the flash devices on the ARM virt board.
> > > > + */
> > > > +DeviceState *dev = qdev_create(NULL, TYPE_PFLASH_CFI01);
> > > > +
> > > > +qdev_prop_set_uint64(dev, "sector-length", VIRT_FLASH_SECTOR_SIZE);
> > > > +qdev_prop_set_uint8(dev, "width", 4);
> > > > +qdev_prop_set_uint8(dev, "device-width", 2);
> > > > +qdev_prop_set_bit(dev, "big-endian", false);
> > > > +qdev_prop_set_uint16(dev, "id0", 0x89);
> > > > +qdev_prop_set_uint16(dev, "id1", 0x18);
> > > > +qdev_prop_set_uint16(dev, "id2", 0x00);
> > > > +qdev_prop_set_uint16(dev, "id3", 0x00);
> > > > +qdev_prop_set_string(dev, "name", name);
> > >
> > > alias_prop_name is unused? ARM virt has 2 more calls in the same function 
> > > here.
> >
> > Yep, you are right. I have removed this.
>
> Any reason of removing this?

The way the virt machine was structured didn't work with the options.
I have fixed that in v2 of the series.

Alistair

>
> >
> > >
> > > > +
> > > > +return PFLASH_CFI01(dev);
> > > > +}
> > > > +
> > > > +static void virt_flash_create(RISCVVirtState *s)
> > > > +{
> > > > +s->flash[0] = virt_flash_create1(s, "virt.flash0", "pflash0");
> > > > +s->flash[1] = virt_flash_create1(s, "virt.flash1", "pflash1");
> > >
> > > I don't think we should mirror what is used on ARM virt board to
> > > create 2 flash for sifive_u. For ARM virt, there are 2 flashes because
> > > they need distinguish secure and non-secure. For sifive_u, only one is
> > > enough.
> >
> > I went back and forward about 1 or 2. Two seems more usable as maybe
> > someone wants to include two pflash files? The Xilinx machine also has
> > two so I'm kind of used to 2, but I'm not really fussed.
> >
> > Unless anyone else wants two I will change it to 1.
>
> Regards,
> Bin



Re: [PATCH v2 03/16] tests/docker: remove python2.7 from docker9-mxe

2019-09-23 Thread John Snow



On 9/23/19 3:49 PM, Cleber Rosa wrote:
> On Thu, Sep 19, 2019 at 06:10:02PM +0100, Alex Bennée wrote:
>> From: John Snow 
>>
>> When it was based on docker8 which uses python-minimal, it needed this.
> 
> Assuming this docker8 was a typo? I mean, s/docker8/debian8/ ?
> 
> - Cleber
> 

WHOOPS, yes, I keep typo-ing "docker" and "debian" as one another.

"debian8", yes.

--js



Re: [PULL 0/7] Python (acceptance tests) queue - 2019-09-23

2019-09-23 Thread no-reply
Patchew URL: https://patchew.org/QEMU/20190923134019.8548-1-cr...@redhat.com/



Hi,

This series seems to have some coding style problems. See output below for
more information:

Message-id: 20190923134019.8548-1-cr...@redhat.com
Subject: [PULL 0/7] Python (acceptance tests) queue - 2019-09-23
Type: series

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

Switched to a new branch 'test'
b200b91 Acceptance tests: use avocado.utils.ssh for SSH interaction
333b8f1 tests/acceptance: Add new test cases in linux_ssh_mips_malta.py
cb9e32e tests/acceptance: Refactor and improve reporting in 
linux_ssh_mips_malta.py
c5b436a Acceptance test x86_cpu_model_versions: split into smaller tests
eb9f595 Acceptance test x86_cpu_model_versions: fix mismatches between test and 
messages
8bbd882 Acceptance test x86_cpu_model_versions: shutdown VMs
c5f67b5 Acceptance test machine_m68k_nextcube.py: relax the error code pattern

=== OUTPUT BEGIN ===
1/7 Checking commit c5f67b555dad (Acceptance test machine_m68k_nextcube.py: 
relax the error code pattern)
2/7 Checking commit 8bbd8828cf1e (Acceptance test x86_cpu_model_versions: 
shutdown VMs)
3/7 Checking commit eb9f595504b2 (Acceptance test x86_cpu_model_versions: fix 
mismatches between test and messages)
ERROR: line over 90 characters
#25: FILE: tests/acceptance/x86_cpu_model_versions.py:283:
+ 'pc-i440fx-4.0 + Cascadelake-Server-v1 should not 
have arch-capabilities')

ERROR: line over 90 characters
#34: FILE: tests/acceptance/x86_cpu_model_versions.py:292:
+ 'pc-i440fx-4.0 + Cascadelake-Server-v2 should have 
arch-capabilities')

ERROR: line over 90 characters
#42: FILE: tests/acceptance/x86_cpu_model_versions.py:299:
+vm.add_args('-cpu', 
'Cascadelake-Server-v1,x-force-features=on,check=off,enforce=off,+arch-capabilities')

total: 3 errors, 0 warnings, 24 lines checked

Patch 3/7 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

4/7 Checking commit c5b436a0666a (Acceptance test x86_cpu_model_versions: split 
into smaller tests)
5/7 Checking commit cb9e32eca764 (tests/acceptance: Refactor and improve 
reporting in linux_ssh_mips_malta.py)
6/7 Checking commit 333b8f13665e (tests/acceptance: Add new test cases in 
linux_ssh_mips_malta.py)
7/7 Checking commit b200b916e0e8 (Acceptance tests: use avocado.utils.ssh for 
SSH interaction)
WARNING: line over 80 characters
#126: FILE: tests/acceptance/linux_ssh_mips_malta.py:85:
+stdout_lines = [line.rstrip() for line in 
result.stdout_text.splitlines()]

WARNING: line over 80 characters
#130: FILE: tests/acceptance/linux_ssh_mips_malta.py:88:
+stderr_lines = [line.rstrip() for line in 
result.stderr_text.splitlines()]

total: 0 errors, 2 warnings, 158 lines checked

Patch 7/7 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
=== OUTPUT END ===

Test command exited with code: 1


The full log is available at
http://patchew.org/logs/20190923134019.8548-1-cr...@redhat.com/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-de...@redhat.com

Re: [PATCH v9 3/3] iotests: test nbd reconnect

2019-09-23 Thread Eric Blake
On 9/17/19 12:13 PM, Vladimir Sementsov-Ogievskiy wrote:
> Add test, which starts backup to nbd target and restarts nbd server
> during backup.
> 
> Signed-off-by: Vladimir Sementsov-Ogievskiy 
> ---
>  tests/qemu-iotests/264| 65 +++
>  tests/qemu-iotests/264.out| 12 +++
>  tests/qemu-iotests/group  |  1 +
>  tests/qemu-iotests/iotests.py |  4 +++
>  4 files changed, 82 insertions(+)
>  create mode 100755 tests/qemu-iotests/264
>  create mode 100644 tests/qemu-iotests/264.out
> 

> +import time
> +
> +import iotests
> +from iotests import qemu_img_create, file_path, qemu_nbd_popen, log
> +
> +disk_a, disk_b, nbd_sock = file_path('disk_a', 'disk_b', 'nbd-sock')
> +
> +qemu_img_create('-f', iotests.imgfmt, disk_a, '5M')
> +qemu_img_create('-f', iotests.imgfmt, disk_b, '5M')
> +srv = qemu_nbd_popen('-k', nbd_sock, '-f', iotests.imgfmt, disk_b)
> +time.sleep(1)
> +

Hard-coded sleep times can be problematic (too long, and the test is no
longer quick; too short, and heavy load can interfere); is there any way
to poll for a completion event rather than just waiting one second?

> +vm = iotests.VM().add_drive(disk_a)
> +vm.launch()
> +vm.hmp_qemu_io('drive0', 'write 0 5M')
> +
> +vm.qmp_log('blockdev-add', filters=[iotests.filter_qmp_testfiles],
> +   **{'node_name': 'backup0',
> +  'driver': 'raw',
> +  'file': {'driver': 'nbd',
> +   'server': {'type': 'unix', 'path': nbd_sock},
> +   'reconnect-delay': 10}})
> +vm.qmp_log('blockdev-backup', device='drive0', sync='full', target='backup0',
> +   speed=(1 * 1024 * 1024))

Throttling to make sure we are likely to still be going and thus test
the reconnect logic.

> +
> +time.sleep(1)
> +log('Kill NBD server')
> +srv.kill()

Again, that hard-coded sleep looks a bit risky.

> +
> +jobs = vm.qmp('query-block-jobs')['return']
> +if jobs and jobs[0]['offset'] < jobs[0]['len']:
> +log('Backup job is still in progress')
> +
> +time.sleep(1)

Why do we need yet another sleep?

> +
> +log('Start NBD server')
> +srv = qemu_nbd_popen('-k', nbd_sock, '-f', iotests.imgfmt, disk_b)
> +
> +vm.qmp_log('block-job-set-speed', device='drive0', speed=0)

So here, you release the throttle to finish the job.

> +e = vm.event_wait('BLOCK_JOB_COMPLETED')
> +log('Backup completed: {}'.format(e['data']['offset']))
> +
> +vm.qmp_log('blockdev-del', node_name='backup0')
> +srv.kill()
> +vm.shutdown()
> diff --git a/tests/qemu-iotests/264.out b/tests/qemu-iotests/264.out
> new file mode 100644
> index 00..4a2f4aa509
> --- /dev/null
> +++ b/tests/qemu-iotests/264.out
> @@ -0,0 +1,12 @@
> +{"execute": "blockdev-add", "arguments": {"driver": "raw", "file": 
> {"driver": "nbd", "reconnect-delay": 10, "server": {"path": 
> "TEST_DIR/PID-nbd-sock", "type": "unix"}}, "node-name": "backup0"}}
> +{"return": {}}
> +{"execute": "blockdev-backup", "arguments": {"device": "drive0", "speed": 
> 1048576, "sync": "full", "target": "backup0"}}
> +{"return": {}}
> +Kill NBD server
> +Backup job is still in progress
> +Start NBD server
> +{"execute": "block-job-set-speed", "arguments": {"device": "drive0", 
> "speed": 0}}
> +{"return": {}}
> +Backup completed: 5242880
> +{"execute": "blockdev-del", "arguments": {"node-name": "backup0"}}
> +{"return": {}}
> diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
> index 5d3da937e4..4f6dd6f153 100644
> --- a/tests/qemu-iotests/group
> +++ b/tests/qemu-iotests/group
> @@ -275,5 +275,6 @@
>  258 rw quick
>  262 rw quick migration
>  263 rw quick
> +264 rw quick

With that many hard-coded sleeps, is it still quick?

/me applies the patch and runs it...

264  pass   [14:49:55] [14:50:01]   6s

that's borderline enough that I would not call it quick.

>  
> +def qemu_nbd_popen(*args):
> +'''Run qemu-nbd in daemon mode and return the parent's exit code'''
> +return subprocess.Popen(qemu_nbd_args + ['--persistent'] + list(args))
> +

Should you also use a pid file here, and wait for the existence of the
pid file before returning (rather than hard-coding sleep(1))?

>  def compare_images(img1, img2, fmt1=imgfmt, fmt2=imgfmt):
>  '''Return True if two image files are identical'''
>  return qemu_img('compare', '-f', fmt1,
> 

At any rate,

Tested-by: Eric Blake 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3226
Virtualization:  qemu.org | libvirt.org



signature.asc
Description: OpenPGP digital signature


Re: [PATCH v2 03/16] tests/docker: remove python2.7 from docker9-mxe

2019-09-23 Thread Cleber Rosa
On Thu, Sep 19, 2019 at 06:10:02PM +0100, Alex Bennée wrote:
> From: John Snow 
> 
> When it was based on docker8 which uses python-minimal, it needed this.

Assuming this docker8 was a typo? I mean, s/docker8/debian8/ ?

- Cleber

> It no longer does.
> 
> Goodbye, python2.7.
> 
> Signed-off-by: John Snow 
> Message-Id: <20190918222546.11696-1-js...@redhat.com>
> Signed-off-by: Alex Bennée 
> ---
>  tests/docker/dockerfiles/debian9-mxe.docker | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/tests/docker/dockerfiles/debian9-mxe.docker 
> b/tests/docker/dockerfiles/debian9-mxe.docker
> index 7431168dad9..62ff1cecf2d 100644
> --- a/tests/docker/dockerfiles/debian9-mxe.docker
> +++ b/tests/docker/dockerfiles/debian9-mxe.docker
> @@ -16,7 +16,6 @@ RUN apt-key adv --keyserver keyserver.ubuntu.com 
> --recv-keys C6BF758A33A3A276 &&
>  RUN apt-get update && \
>  DEBIAN_FRONTEND=noninteractive eatmydata \
>  apt-get install -y --no-install-recommends \
> -libpython2.7-stdlib \
>  $(apt-get -s install -y --no-install-recommends 
> gw32.shared-mingw-w64 | egrep "^Inst mxe-x86-64-unknown-" | cut -d\  -f2)
>  
> -ENV PATH $PATH:/usr/lib/mxe/usr/bin/ 
> +ENV PATH $PATH:/usr/lib/mxe/usr/bin/
> -- 
> 2.20.1
> 
> 



Re: [PATCH v2 02/16] tests/docker: fix DOCKER_PARTIAL_IMAGES

2019-09-23 Thread Cleber Rosa
On Thu, Sep 19, 2019 at 06:10:01PM +0100, Alex Bennée wrote:
> Finger trouble in a previous clean-up inadvertently set
> DEBIAN_PARTIAL_IMAGES instead of DOCKER_PARTIAL_IMAGES. Also fix the
> typo to debian-9-mxe.
> 
> Fixes: 44d5a8bf5d2
> Signed-off-by: John Snow 
> [AJB: merged fix from Message-Id: <20190917185537.25417-1-js...@redhat.com>]
> Signed-off-by: Alex Bennée 
> Reviewed-by: Philippe Mathieu-Daudé 

Reviewed-by: Cleber Rosa 

> ---
>  tests/docker/Makefile.include | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include
> index 50a400b573a..3fc7a863e51 100644
> --- a/tests/docker/Makefile.include
> +++ b/tests/docker/Makefile.include
> @@ -7,7 +7,7 @@ DOCKER_FILES_DIR := $(SRC_PATH)/tests/docker/dockerfiles
>  DOCKER_DEPRECATED_IMAGES := debian
>  # we don't run tests on intermediate images (used as base by another image)
>  DOCKER_PARTIAL_IMAGES := debian debian8 debian9 debian10 debian-sid
> -DEBIAN_PARTIAL_IMAGES += debian8-mxe debian-9-mxe debian-ports 
> debian-bootstrap
> +DOCKER_PARTIAL_IMAGES += debian8-mxe debian9-mxe debian-ports 
> debian-bootstrap
>  DOCKER_IMAGES := $(filter-out $(DOCKER_DEPRECATED_IMAGES),$(sort $(notdir 
> $(basename $(wildcard $(DOCKER_FILES_DIR)/*.docker)
>  DOCKER_TARGETS := $(patsubst %,docker-image-%,$(DOCKER_IMAGES))
>  # Use a global constant ccache directory to speed up repetitive builds
> -- 
> 2.20.1
> 
> 



  1   2   3   4   >