Re: [PATCH 0/6] audio/jack: fixes to overall jack behaviour

2020-06-13 Thread no-reply
Patchew URL: 
https://patchew.org/QEMU/20200613040518.38172-1-ge...@hostfission.com/



Hi,

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

Message-id: 20200613040518.38172-1-ge...@hostfission.com
Subject: [PATCH 0/6] audio/jack: fixes to overall jack behaviour
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 ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
Switched to a new branch 'test'
c962352 audio/jack: simplify the re-init code path
1b80c6e audio/jack: honour the enable state of the audio device
d549d5e0 audio/jack: do not remove ports when finishing
d9f3c84 audio/jack: remove invalid set of input support bool
c612550 audio/jack: remove unused stopped state
62d579e audio/jack: fix invalid minimum buffer size check

=== OUTPUT BEGIN ===
1/6 Checking commit 62d579e00e55 (audio/jack: fix invalid minimum buffer size 
check)
2/6 Checking commit c612550cb58e (audio/jack: remove unused stopped state)
3/6 Checking commit d9f3c846ec2f (audio/jack: remove invalid set of input 
support bool)
4/6 Checking commit d549d5e05a30 (audio/jack: do not remove ports when 
finishing)
5/6 Checking commit 1b80c6eb42f5 (audio/jack: honour the enable state of the 
audio device)
ERROR: space required before the open parenthesis '('
#42: FILE: audio/jackaudio.c:277:
+for(int i = 0; i < c->nchannels; ++i) {

total: 1 errors, 0 warnings, 91 lines checked

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

6/6 Checking commit c9623522cfe0 (audio/jack: simplify the re-init code path)
=== OUTPUT END ===

Test command exited with code: 1


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

[PATCH 4/6] audio/jack: do not remove ports when finishing

2020-06-13 Thread Geoffrey McRae
This fixes a hang when there is a communications issue with the JACK
server. Simply closing the connection is enough to completely clean up
and as such we do not need to remove the ports first. As JACK uses a
socket based protocol that relies on the `select` call, if there is a
communication breakdown with the server the client library waits
forever for a response to the unregister request.

Signed-off-by: Geoffrey McRae 
---
 audio/jackaudio.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/audio/jackaudio.c b/audio/jackaudio.c
index 58c7344497..249cbd3265 100644
--- a/audio/jackaudio.c
+++ b/audio/jackaudio.c
@@ -548,9 +548,6 @@ static void qjack_client_fini(QJackClient *c)
 {
 switch (c->state) {
 case QJACK_STATE_RUNNING:
-for (int i = 0; i < c->nchannels; ++i) {
-jack_port_unregister(c->client, c->port[i]);
-}
 jack_deactivate(c->client);
 /* fallthrough */
 
-- 
2.20.1




[PATCH 3/6] audio/jack: remove invalid set of input support bool

2020-06-13 Thread Geoffrey McRae
Initial code for JACK did not support audio input and as such this
boolean was set to let QEMU know, however JACK ended up including input
support making this invalid. Further investigation shows it was invalid
to set it in the first instance anyway due to a failure on my part
understand properly what this was for when the audodev was initially
developed.

Signed-off-by: Geoffrey McRae 
---
 audio/jackaudio.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/audio/jackaudio.c b/audio/jackaudio.c
index fb8efd7af7..58c7344497 100644
--- a/audio/jackaudio.c
+++ b/audio/jackaudio.c
@@ -607,9 +607,6 @@ static int qjack_thread_creator(jack_native_thread_t 
*thread,
 static void *qjack_init(Audiodev *dev)
 {
 assert(dev->driver == AUDIODEV_DRIVER_JACK);
-
-dev->u.jack.has_in = false;
-
 return dev;
 }
 
-- 
2.20.1




[PATCH 1/6] audio/jack: fix invalid minimum buffer size check

2020-06-13 Thread Geoffrey McRae
JACK does not provide us with the configured buffer size until after
activiation which was overriding this minimum value. JACK itself doesn't
have this minimum limitation, but the QEMU virtual hardware and as such
it must be enforced, failure to do so results in audio discontinuities.

Signed-off-by: Geoffrey McRae 
---
 audio/jackaudio.c | 22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/audio/jackaudio.c b/audio/jackaudio.c
index 722ddb1dfe..d0b6f748f2 100644
--- a/audio/jackaudio.c
+++ b/audio/jackaudio.c
@@ -434,17 +434,6 @@ static int qjack_client_init(QJackClient *c)
 jack_set_xrun_callback(c->client, qjack_xrun, c);
 jack_on_shutdown(c->client, qjack_shutdown, c);
 
-/*
- * ensure the buffersize is no smaller then 512 samples, some (all?) qemu
- * virtual devices do not work correctly otherwise
- */
-if (c->buffersize < 512) {
-c->buffersize = 512;
-}
-
-/* create a 2 period buffer */
-qjack_buffer_create(>fifo, c->nchannels, c->buffersize * 2);
-
 /* allocate and register the ports */
 c->port = g_malloc(sizeof(jack_port_t *) * c->nchannels);
 for (int i = 0; i < c->nchannels; ++i) {
@@ -468,6 +457,17 @@ static int qjack_client_init(QJackClient *c)
 jack_activate(c->client);
 c->buffersize = jack_get_buffer_size(c->client);
 
+/*
+ * ensure the buffersize is no smaller then 512 samples, some (all?) qemu
+ * virtual devices do not work correctly otherwise
+ */
+if (c->buffersize < 512) {
+c->buffersize = 512;
+}
+
+/* create a 2 period buffer */
+qjack_buffer_create(>fifo, c->nchannels, c->buffersize * 2);
+
 qjack_client_connect_ports(c);
 c->state = QJACK_STATE_RUNNING;
 return 0;
-- 
2.20.1




[PATCH 6/6] audio/jack: simplify the re-init code path

2020-06-13 Thread Geoffrey McRae
Instead of checking for the audodev state in each code path, centralize
the check into the initialize function itself to make it safe to call it
at any time.

Signed-off-by: Geoffrey McRae 
---
 audio/jackaudio.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/audio/jackaudio.c b/audio/jackaudio.c
index b2b53985ae..72ed7c4929 100644
--- a/audio/jackaudio.c
+++ b/audio/jackaudio.c
@@ -395,6 +395,10 @@ static int qjack_client_init(QJackClient *c)
 char client_name[jack_client_name_size()];
 jack_options_t options = JackNullOption;
 
+if (c->state == QJACK_STATE_RUNNING) {
+return 0;
+}
+
 c->connect_ports = true;
 
 snprintf(client_name, sizeof(client_name), "%s-%s",
@@ -485,9 +489,7 @@ static int qjack_init_out(HWVoiceOut *hw, struct 
audsettings *as,
 QJackOut *jo  = (QJackOut *)hw;
 Audiodev *dev = (Audiodev *)drv_opaque;
 
-if (jo->c.state != QJACK_STATE_DISCONNECTED) {
-return 0;
-}
+qjack_client_fini(>c);
 
 jo->c.out   = true;
 jo->c.enabled   = false;
@@ -523,9 +525,7 @@ static int qjack_init_in(HWVoiceIn *hw, struct audsettings 
*as,
 QJackIn  *ji  = (QJackIn *)hw;
 Audiodev *dev = (Audiodev *)drv_opaque;
 
-if (ji->c.state != QJACK_STATE_DISCONNECTED) {
-return 0;
-}
+qjack_client_fini(>c);
 
 ji->c.out   = false;
 ji->c.enabled   = false;
-- 
2.20.1




[PATCH 0/6] audio/jack: fixes to overall jack behaviour

2020-06-13 Thread Geoffrey McRae
This patch set addresses several issues that cause inconsistent
behaviour in the guest when the sound device is stopped and started or
the JACK server stops responding on the host.

Geoffrey McRae (6):
  audio/jack: fix invalid minimum buffer size check
  audio/jack: remove unused stopped state
  audio/jack: remove invalid set of input support bool
  audio/jack: do not remove ports when finishing
  audio/jack: honour the enable state of the audio device
  audio/jack: simplify the re-init code path

 audio/jackaudio.c | 73 ---
 1 file changed, 38 insertions(+), 35 deletions(-)

-- 
2.20.1




[PATCH 2/6] audio/jack: remove unused stopped state

2020-06-13 Thread Geoffrey McRae
Signed-off-by: Geoffrey McRae 
---
 audio/jackaudio.c | 4 
 1 file changed, 4 deletions(-)

diff --git a/audio/jackaudio.c b/audio/jackaudio.c
index d0b6f748f2..fb8efd7af7 100644
--- a/audio/jackaudio.c
+++ b/audio/jackaudio.c
@@ -38,7 +38,6 @@ struct QJack;
 
 typedef enum QJackState {
 QJACK_STATE_DISCONNECTED,
-QJACK_STATE_STOPPED,
 QJACK_STATE_RUNNING,
 QJACK_STATE_SHUTDOWN
 }
@@ -549,9 +548,6 @@ static void qjack_client_fini(QJackClient *c)
 {
 switch (c->state) {
 case QJACK_STATE_RUNNING:
-/* fallthrough */
-
-case QJACK_STATE_STOPPED:
 for (int i = 0; i < c->nchannels; ++i) {
 jack_port_unregister(c->client, c->port[i]);
 }
-- 
2.20.1




Re: [PATCH] target/mips: Fix PageMask with variable page size

2020-06-13 Thread no-reply
Patchew URL: 
https://patchew.org/QEMU/20200614034729.3004-1-jiaxun.y...@flygoat.com/



Hi,

This series failed the docker-quick@centos7 build test. Please find the testing 
commands and
their output below. If you have Docker installed, you can probably reproduce it
locally.

=== TEST SCRIPT BEGIN ===
#!/bin/bash
make docker-image-centos7 V=1 NETWORK=1
time make docker-test-quick@centos7 SHOW_ENV=1 J=14 NETWORK=1
=== TEST SCRIPT END ===

+++ /tmp/qemu-test/build/tests/qemu-iotests/041.out.bad 2020-06-14 
04:06:28.925257078 +
@@ -1,5 +1,30 @@
-
+WARNING:qemu.machine:qemu received signal 9: 
/tmp/qemu-test/build/tests/qemu-iotests/../../x86_64-softmmu/qemu-system-x86_64 
-display none -vga none -chardev 
socket,id=mon,path=/tmp/tmp.TpYwtp98hn/qemu-21810-monitor.sock -mon 
chardev=mon,mode=control -qtest 
unix:path=/tmp/tmp.TpYwtp98hn/qemu-21810-qtest.sock -accel qtest -nodefaults 
-display none -accel qtest -drive 
if=virtio,id=drive0,file=/tmp/qemu-test/test.img,format=qcow2,cache=writeback,aio=threads,node-name=top,backing.node-name=base
 -drive if=ide,id=drive1,media=cdrom
+...E
+==
+ERROR: test_pause (__main__.TestSingleDrive)
+--
+Traceback (most recent call last):
+  File "041", line 108, in test_pause
---
 Ran 104 tests
 
-OK
+FAILED (errors=1)
  TESTiotest-qcow2: 042
  TESTiotest-qcow2: 043
  TESTiotest-qcow2: 046
---
Not run: 259
Failures: 041
Failed 1 of 119 iotests
make: *** [check-tests/check-block.sh] Error 1
Traceback (most recent call last):
  File "./tests/docker/docker.py", line 669, in 
sys.exit(main())
---
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['sudo', '-n', 'docker', 'run', 
'--label', 'com.qemu.instance.uuid=6f22b3d3f1444c1098a62865239c3b98', '-u', 
'1003', '--security-opt', 'seccomp=unconfined', '--rm', '-e', 'TARGET_LIST=', 
'-e', 'EXTRA_CONFIGURE_OPTS=', '-e', 'V=', '-e', 'J=14', '-e', 'DEBUG=', '-e', 
'SHOW_ENV=1', '-e', 'CCACHE_DIR=/var/tmp/ccache', '-v', 
'/home/patchew2/.cache/qemu-docker-ccache:/var/tmp/ccache:z', '-v', 
'/var/tmp/patchew-tester-tmp-5di02x2_/src/docker-src.2020-06-13-23.55.49.5246:/var/tmp/qemu:z,ro',
 'qemu:centos7', '/var/tmp/qemu/run', 'test-quick']' returned non-zero exit 
status 2.
filter=--filter=label=com.qemu.instance.uuid=6f22b3d3f1444c1098a62865239c3b98
make[1]: *** [docker-run] Error 1
make[1]: Leaving directory `/var/tmp/patchew-tester-tmp-5di02x2_/src'
make: *** [docker-run-test-quick@centos7] Error 2

real17m14.597s
user0m8.192s


The full log is available at
http://patchew.org/logs/20200614034729.3004-1-jiaxun.y...@flygoat.com/testing.docker-quick@centos7/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-de...@redhat.com

[PATCH 5/6] audio/jack: honour the enable state of the audio device

2020-06-13 Thread Geoffrey McRae
When the guest closes the audio device we must start dropping input
samples from JACK and zeroing the output buffer samples. Failure to do
so causes sound artifacts during operations such as guest OS reboot, and
causes a hang of the input pipeline breaking it until QEMU is restated.

Closing and reconnecting to JACK was tested during these enable/disable
calls which works well for Linux guests, however Windows re-opens the
audio hardware repeatedly even when doing simple tasks like playing a
system sounds. As such it was decided it is better to feed silence to
JACK while the device is disabled.

Signed-off-by: Geoffrey McRae 
---
 audio/jackaudio.c | 29 +
 1 file changed, 21 insertions(+), 8 deletions(-)

diff --git a/audio/jackaudio.c b/audio/jackaudio.c
index 249cbd3265..b2b53985ae 100644
--- a/audio/jackaudio.c
+++ b/audio/jackaudio.c
@@ -56,7 +56,7 @@ typedef struct QJackClient {
 AudiodevJackPerDirectionOptions *opt;
 
 bool out;
-bool finished;
+bool enabled;
 bool connect_ports;
 int  packets;
 
@@ -271,9 +271,17 @@ static int qjack_process(jack_nframes_t nframes, void *arg)
 }
 
 if (c->out) {
-qjack_buffer_read_l(>fifo, buffers, nframes);
+if (likely(c->enabled)) {
+qjack_buffer_read_l(>fifo, buffers, nframes);
+} else {
+for(int i = 0; i < c->nchannels; ++i) {
+memset(buffers[i], 0, nframes * sizeof(float));
+}
+}
 } else {
-qjack_buffer_write_l(>fifo, buffers, nframes);
+if (likely(c->enabled)) {
+qjack_buffer_write_l(>fifo, buffers, nframes);
+}
 }
 
 return 0;
@@ -314,8 +322,8 @@ static void qjack_client_recover(QJackClient *c)
 if (c->state == QJACK_STATE_DISCONNECTED &&
 c->packets % 100 == 0) {
 
-/* if not finished then attempt to recover */
-if (!c->finished) {
+/* if enabled then attempt to recover */
+if (c->enabled) {
 dolog("attempting to reconnect to server\n");
 qjack_client_init(c);
 }
@@ -387,7 +395,6 @@ static int qjack_client_init(QJackClient *c)
 char client_name[jack_client_name_size()];
 jack_options_t options = JackNullOption;
 
-c->finished  = false;
 c->connect_ports = true;
 
 snprintf(client_name, sizeof(client_name), "%s-%s",
@@ -483,8 +490,10 @@ static int qjack_init_out(HWVoiceOut *hw, struct 
audsettings *as,
 }
 
 jo->c.out   = true;
+jo->c.enabled   = false;
 jo->c.nchannels = as->nchannels;
 jo->c.opt   = dev->u.jack.out;
+
 int ret = qjack_client_init(>c);
 if (ret != 0) {
 return ret;
@@ -519,8 +528,10 @@ static int qjack_init_in(HWVoiceIn *hw, struct audsettings 
*as,
 }
 
 ji->c.out   = false;
+ji->c.enabled   = false;
 ji->c.nchannels = as->nchannels;
 ji->c.opt   = dev->u.jack.in;
+
 int ret = qjack_client_init(>c);
 if (ret != 0) {
 return ret;
@@ -568,23 +579,25 @@ static void qjack_client_fini(QJackClient *c)
 static void qjack_fini_out(HWVoiceOut *hw)
 {
 QJackOut *jo = (QJackOut *)hw;
-jo->c.finished = true;
 qjack_client_fini(>c);
 }
 
 static void qjack_fini_in(HWVoiceIn *hw)
 {
 QJackIn *ji = (QJackIn *)hw;
-ji->c.finished = true;
 qjack_client_fini(>c);
 }
 
 static void qjack_enable_out(HWVoiceOut *hw, bool enable)
 {
+QJackOut *jo = (QJackOut *)hw;
+jo->c.enabled = enable;
 }
 
 static void qjack_enable_in(HWVoiceIn *hw, bool enable)
 {
+QJackIn *ji = (QJackIn *)hw;
+ji->c.enabled = enable;
 }
 
 static int qjack_thread_creator(jack_native_thread_t *thread,
-- 
2.20.1




[PATCH] target/mips: Fix PageMask with variable page size

2020-06-13 Thread Jiaxun Yang
Our current code assumed the target page size is always 4k
when handling PageMask and VPN2, however, variable page size
was just added to mips target and that's nolonger true.

So we refined this piece of code to handle any target page size.
Also added Big Page support defined by MIPS64 Release2.

Signed-off-by: Jiaxun Yang 
---
 target/mips/cp0_helper.c | 48 ++--
 target/mips/cpu.h|  3 ++-
 target/mips/machine.c|  2 +-
 3 files changed, 39 insertions(+), 14 deletions(-)

diff --git a/target/mips/cp0_helper.c b/target/mips/cp0_helper.c
index bbf12e4a97..7a134085f7 100644
--- a/target/mips/cp0_helper.c
+++ b/target/mips/cp0_helper.c
@@ -872,20 +872,44 @@ void helper_mtc0_memorymapid(CPUMIPSState *env, 
target_ulong arg1)
 }
 }
 
-void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask)
+void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1)
 {
-uint64_t mask = arg1 >> (TARGET_PAGE_BITS + 1);
-if (!(env->insn_flags & ISA_MIPS32R6) || (arg1 == ~0) ||
-(mask == 0x || mask == 0x0003 || mask == 0x000F ||
- mask == 0x003F || mask == 0x00FF || mask == 0x03FF ||
- mask == 0x0FFF || mask == 0x3FFF || mask == 0x)) {
-env->CP0_PageMask = arg1 & (0x1FFF & (TARGET_PAGE_MASK << 1));
+uint64_t mask;
+int maxmaskbits, maskbits;
+
+if (env->insn_flags & ISA_MIPS32R6) {
+return;
 }
-}
 
-void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1)
-{
-update_pagemask(env, arg1, >CP0_PageMask);
+/* Don't care MASKX as we don't support 1KB page */
+#ifdef TARGET_MIPS64
+if (env->CP0_Config3 & CP0C3_BPG) {
+maxmaskbits = 47;
+} else {
+maxmaskbits = 16;
+}
+#else
+maxmaskbits = 16;
+#endif
+mask = extract64((uint64_t)arg1, CP0PM_MASK, maxmaskbits);
+
+maskbits = find_first_zero_bit(, 64);
+
+/* Ensure no more set bit after first zero */
+if (mask >> maskbits) {
+goto invalid;
+}
+/* We don't support VTLB entry smaller than target page */
+if ((maskbits + 12) < TARGET_PAGE_BITS) {
+goto invalid;
+}
+env->CP0_PageMask = mask << CP0PM_MASK;
+
+return;
+
+invalid:
+maskbits = MIN(maxmaskbits, MAX(maskbits, TARGET_PAGE_BITS - 12));
+env->CP0_PageMask = ((1 << (maskbits + 1)) - 1) << CP0PM_MASK;
 }
 
 void helper_mtc0_pagegrain(CPUMIPSState *env, target_ulong arg1)
@@ -,7 +1135,7 @@ void helper_mthc0_saar(CPUMIPSState *env, target_ulong 
arg1)
 void helper_mtc0_entryhi(CPUMIPSState *env, target_ulong arg1)
 {
 target_ulong old, val, mask;
-mask = (TARGET_PAGE_MASK << 1) | env->CP0_EntryHi_ASID_mask;
+mask = ~((1 << 14) - 1) | env->CP0_EntryHi_ASID_mask;
 if (((env->CP0_Config4 >> CP0C4_IE) & 0x3) >= 2) {
 mask |= 1 << CP0EnHi_EHINV;
 }
diff --git a/target/mips/cpu.h b/target/mips/cpu.h
index 0b3c987bb3..b69806792d 100644
--- a/target/mips/cpu.h
+++ b/target/mips/cpu.h
@@ -617,7 +617,8 @@ struct CPUMIPSState {
 /*
  * CP0 Register 5
  */
-int32_t CP0_PageMask;
+target_ulong CP0_PageMask;
+#define CP0PM_MASK 13
 int32_t CP0_PageGrain_rw_bitmask;
 int32_t CP0_PageGrain;
 #define CP0PG_RIE 31
diff --git a/target/mips/machine.c b/target/mips/machine.c
index 5b23e3e912..b30a75d46b 100644
--- a/target/mips/machine.c
+++ b/target/mips/machine.c
@@ -252,7 +252,7 @@ const VMStateDescription vmstate_mips_cpu = {
 VMSTATE_UINT64(env.CP0_EntryLo1, MIPSCPU),
 VMSTATE_UINTTL(env.CP0_Context, MIPSCPU),
 VMSTATE_INT32(env.CP0_MemoryMapID, MIPSCPU),
-VMSTATE_INT32(env.CP0_PageMask, MIPSCPU),
+VMSTATE_UINTTL(env.CP0_PageMask, MIPSCPU),
 VMSTATE_INT32(env.CP0_PageGrain, MIPSCPU),
 VMSTATE_UINTTL(env.CP0_SegCtl0, MIPSCPU),
 VMSTATE_UINTTL(env.CP0_SegCtl1, MIPSCPU),
-- 
2.27.0



[Bug 1883400] Re: Windows 10 extremely slow and unresponsive

2020-06-13 Thread Toddandmargo-n
** Description changed:

  Hi,
  
  Fedora 32, x64
  qemu-5.0.0-2.fc32.x86_64
  
  https://www.microsoft.com/en-us/software-download/windows10ISO
  Win10_2004_English_x64.iso
  
  Windows 10 is excruciatingly slow since upgrading to 5.0.0-2.fc32.
  Disabling your repo and downgrading to 2:4.2.0-7.fc32 and corrects the
  issue (the package in the Fedora repo).
  
  You can duplicate this off of the Windows 10 ISO (see above) and do not
  even have to install Windows 10 itself.
  
+ No such problem with Windows 7.
+ 
+ And the clipboard works better under 2L4.2.0-07 too
+ 
  Please fix,
  
  Many thanks,
  -T

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

Title:
  Windows 10 extremely slow and unresponsive

Status in QEMU:
  New

Bug description:
  Hi,

  Fedora 32, x64
  qemu-5.0.0-2.fc32.x86_64

  https://www.microsoft.com/en-us/software-download/windows10ISO
  Win10_2004_English_x64.iso

  Windows 10 is excruciatingly slow since upgrading to 5.0.0-2.fc32.
  Disabling your repo and downgrading to 2:4.2.0-7.fc32 and corrects the
  issue (the package in the Fedora repo).

  You can duplicate this off of the Windows 10 ISO (see above) and do
  not even have to install Windows 10 itself.

  No such problem with Windows 7.

  And the clipboard works better under 2L4.2.0-07 too

  Please fix,

  Many thanks,
  -T

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



[Bug 1883400] [NEW] Windows 10 extremely slow and unresponsive

2020-06-13 Thread Toddandmargo-n
Public bug reported:

Hi,

Fedora 32, x64
qemu-5.0.0-2.fc32.x86_64

https://www.microsoft.com/en-us/software-download/windows10ISO
Win10_2004_English_x64.iso

Windows 10 is excruciatingly slow since upgrading to 5.0.0-2.fc32.
Disabling your repo and downgrading to 2:4.2.0-7.fc32 and corrects the
issue (the package in the Fedora repo).

You can duplicate this off of the Windows 10 ISO (see above) and do not
even have to install Windows 10 itself.

Please fix,

Many thanks,
-T

** Affects: qemu
 Importance: Undecided
 Status: New

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

Title:
  Windows 10 extremely slow and unresponsive

Status in QEMU:
  New

Bug description:
  Hi,

  Fedora 32, x64
  qemu-5.0.0-2.fc32.x86_64

  https://www.microsoft.com/en-us/software-download/windows10ISO
  Win10_2004_English_x64.iso

  Windows 10 is excruciatingly slow since upgrading to 5.0.0-2.fc32.
  Disabling your repo and downgrading to 2:4.2.0-7.fc32 and corrects the
  issue (the package in the Fedora repo).

  You can duplicate this off of the Windows 10 ISO (see above) and do
  not even have to install Windows 10 itself.

  Please fix,

  Many thanks,
  -T

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



Re: [PATCH RFC 00/22] Support of Virtual CPU Hotplug for ARMv8 Arch

2020-06-13 Thread no-reply
Patchew URL: 
https://patchew.org/QEMU/20200613213629.21984-1-salil.me...@huawei.com/



Hi,

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

Message-id: 20200613213629.21984-1-salil.me...@huawei.com
Subject: [PATCH RFC 00/22] Support of Virtual CPU Hotplug for ARMv8 Arch
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 ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
Switched to a new branch 'test'
dc56c53 arm/cpuhp: Add support of *unrealize* ARMCPU during vcpu hot-unplug
988141e arm/cpuhp: Changes required for reset and to support next boot
d5feac6 arm/cpuhp: Update the guest(via GED) about cpu hot-(un)plug events
185a83e arm/cpuhp: Changes required to (re)init the vcpu register info
659f80f arm/cpuhp: Changes to update GIC with vcpu hot-plug notification
bcfc8e7 arm/cpuhp: Changes to (un)wire GICC<->VCPU IRQs during hot-(un)plug
643af9e arm/cpuhp: Add/update basic hot-(un)plug framework
8e17131 arm/cpuhp: Update ACPI GED framework to support vcpu hotplug
a8d5f8e arm/cpuhp: Release objects for *disabled* possible vcpus after init
1f520fd arm/cpuhp: Add ACPI _MAT entry for Processor object
e9543c1 arm/cpuhp: MADT Tbl change to size the guest with possible vcpus
a41164f arm/cpuhp: Update GED _EVT method AML with cpu scan
72b8a98 arm/cpuhp: Update CPUs AML with cpu-(ctrl)dev change
9d81444 arm/cpuhp: Init GED framework with cpu hotplug events
96ef87b arm/cpuhp: Enable ACPI support for vcpu hotplug
be81157 arm/cpuhp: Init PMU at host for all possible vcpus
cb588d9 arm/cpuhp: Changes to pre-size GIC with possible vcpus @machine init
75fe8dd arm/cpuhp: Pre-create disabled possible vcpus @machine init
55adeca arm/cpuhp: Machine init time change common to vcpu {cold|hot}-plug
9c53779 arm/cpuhp: Add common cpu utility for possible vcpus
36a71f4 arm/cpuhp: Add new ARMCPU core-id property
ecab7ce arm/cpuhp: Add QMP vcpu params validation support

=== OUTPUT BEGIN ===
1/22 Checking commit ecab7ce0dc60 (arm/cpuhp: Add QMP vcpu params validation 
support)
2/22 Checking commit 36a71f45080c (arm/cpuhp: Add new ARMCPU core-id property)
3/22 Checking commit 9c53779a7878 (arm/cpuhp: Add common cpu utility for 
possible vcpus)
ERROR: return is not a function, parentheses are not required
#51: FILE: cpus-common.c:104:
+return (cpu && !cpu->disabled);

total: 1 errors, 0 warnings, 65 lines checked

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

4/22 Checking commit 55adeca4f0c2 (arm/cpuhp: Machine init time change common 
to vcpu {cold|hot}-plug)
ERROR: space prohibited between function name and open parenthesis '('
#206: FILE: hw/arm/virt.c:2143:
+assert (found_cpu);

ERROR: space required before the open brace '{'
#341: FILE: hw/arm/virt.c:2338:
+   (object_dynamic_cast(OBJECT(dev), TYPE_CPU))){

total: 2 errors, 0 warnings, 375 lines checked

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

5/22 Checking commit 75fe8dd750d3 (arm/cpuhp: Pre-create disabled possible 
vcpus @machine init)
ERROR: space required after that ',' (ctx:VxV)
#93: FILE: hw/arm/virt.c:1841:
+qdev_set_id(DEVICE(cpuobj),core_id);
   ^

ERROR: suspect code indent for conditional statements (12, 15)
#109: FILE: hw/arm/virt.c:1857:
+if (kvm_enabled()) {
+   kvm_arm_create_host_vcpu(ARM_CPU(cs));

WARNING: line over 80 characters
#113: FILE: hw/arm/virt.c:1861:
+ * Add disabled vcpu to cpu slot during the init phase of the virt 
machine.

WARNING: line over 80 characters
#119: FILE: hw/arm/virt.c:1867:
+ * 2. Now, after initialization of the virt machine is complete we 
could use

WARNING: line over 80 characters
#127: FILE: hw/arm/virt.c:1875:
+ *We will use the (ii) approach and release the ARMCPU objects 
after GIC

total: 2 errors, 3 warnings, 159 lines checked

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

6/22 Checking commit cb588d911d62 (arm/cpuhp: Changes to pre-size GIC with 
possible vcpus @machine init)
ERROR: braces {} are necessary for all arms of this statement
#105: FILE: hw/intc/arm_gicv3_common.c:355:
+if (qemu_present_cpu(cpu))
[...]
+else
[...]

ERROR: braces {} are necessary for all arms of this statement
#121: FILE: hw/intc/arm_gicv3_cpuif.c:782:
+if (!qemu_present_cpu(cs->cpu))
[...]

ERROR: braces {} are necessary for all arms of this statement
#161: FILE: hw/intc/arm_gicv3_kvm.c:470:
+if 

Re: [PATCH RFC 00/22] Support of Virtual CPU Hotplug for ARMv8 Arch

2020-06-13 Thread no-reply
Patchew URL: 
https://patchew.org/QEMU/20200613213629.21984-1-salil.me...@huawei.com/



Hi,

This series failed the docker-quick@centos7 build test. Please find the testing 
commands and
their output below. If you have Docker installed, you can probably reproduce it
locally.

=== TEST SCRIPT BEGIN ===
#!/bin/bash
make docker-image-centos7 V=1 NETWORK=1
time make docker-test-quick@centos7 SHOW_ENV=1 J=14 NETWORK=1
=== TEST SCRIPT END ===

  TESTcheck-unit: tests/test-char
  TESTcheck-qtest-aarch64: tests/qtest/tpm-tis-device-swtpm-test
  TESTcheck-qtest-aarch64: tests/qtest/numa-test
qemu-system-aarch64: warning: For GICv2 max-cpus must be equal to smp-cpus
qemu-system-aarch64: warning: Overriding specified max-cpus(8) with smp-cpus(8)
  TESTiotest-qcow2: 003
qemu-system-aarch64: warning: For GICv2 max-cpus must be equal to smp-cpus
qemu-system-aarch64: warning: Overriding specified max-cpus(8) with smp-cpus(8)
qemu-system-aarch64: warning: For GICv2 max-cpus must be equal to smp-cpus
qemu-system-aarch64: warning: Overriding specified max-cpus(8) with smp-cpus(8)
qemu-system-aarch64: warning: For GICv2 max-cpus must be equal to smp-cpus
qemu-system-aarch64: warning: Overriding specified max-cpus(8) with smp-cpus(8)
qemu-system-aarch64: warning: For GICv2 max-cpus must be equal to smp-cpus
qemu-system-aarch64: warning: Overriding specified max-cpus(2) with smp-cpus(2)
  TESTcheck-qtest-aarch64: tests/qtest/boot-serial-test
qemu-system-aarch64: warning: For GICv2 max-cpus must be equal to smp-cpus
qemu-system-aarch64: warning: Overriding specified max-cpus(1) with smp-cpus(1)
  TESTcheck-qtest-aarch64: tests/qtest/migration-test
  TESTcheck-unit: tests/check-qnum
  TESTiotest-qcow2: 004
---
qemu-system-aarch64: falling back to tcg
  TESTiotest-qcow2: 060
  TESTcheck-qtest-aarch64: tests/qtest/bios-tables-test
qemu-system-aarch64: warning: For GICv2 max-cpus must be equal to smp-cpus
qemu-system-aarch64: warning: Overriding specified max-cpus(1) with smp-cpus(1)
  TESTiotest-qcow2: 061
  TESTiotest-qcow2: 062
  TESTiotest-qcow2: 063
---
acpi-test: Warning! DSDT binary file mismatch. Actual [aml:/tmp/aml-3PFIM0], 
Expected [aml:tests/data/acpi/virt/DSDT].
See source file tests/qtest/bios-tables-test.c for instructions on how to 
update expected files.
to see ASL diff between mismatched files install IASL, rebuild QEMU from 
scratch and re-run tests with V=1 environment variable set**
ERROR:/tmp/qemu-test/src/tests/qtest/bios-tables-test.c:494:test_acpi_asl: 
assertion failed: (all_tables_match)
ERROR - Bail out! 
ERROR:/tmp/qemu-test/src/tests/qtest/bios-tables-test.c:494:test_acpi_asl: 
assertion failed: (all_tables_match)
make: *** [check-qtest-aarch64] Error 1
make: *** Waiting for unfinished jobs
  TESTiotest-qcow2: 073
  TESTiotest-qcow2: 074
---
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['sudo', '-n', 'docker', 'run', 
'--label', 'com.qemu.instance.uuid=85b55b455d55449297469bf3a981cabd', '-u', 
'1001', '--security-opt', 'seccomp=unconfined', '--rm', '-e', 'TARGET_LIST=', 
'-e', 'EXTRA_CONFIGURE_OPTS=', '-e', 'V=', '-e', 'J=14', '-e', 'DEBUG=', '-e', 
'SHOW_ENV=1', '-e', 'CCACHE_DIR=/var/tmp/ccache', '-v', 
'/home/patchew/.cache/qemu-docker-ccache:/var/tmp/ccache:z', '-v', 
'/var/tmp/patchew-tester-tmp-i8pzxavb/src/docker-src.2020-06-13-18.08.03.29364:/var/tmp/qemu:z,ro',
 'qemu:centos7', '/var/tmp/qemu/run', 'test-quick']' returned non-zero exit 
status 2.
filter=--filter=label=com.qemu.instance.uuid=85b55b455d55449297469bf3a981cabd
make[1]: *** [docker-run] Error 1
make[1]: Leaving directory `/var/tmp/patchew-tester-tmp-i8pzxavb/src'
make: *** [docker-run-test-quick@centos7] Error 2

real16m30.871s
user0m9.410s


The full log is available at
http://patchew.org/logs/20200613213629.21984-1-salil.me...@huawei.com/testing.docker-quick@centos7/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-de...@redhat.com

[PATCH RFC 21/22] arm/cpuhp: Changes required for reset and to support next boot

2020-06-13 Thread Salil Mehta
Updates the firmware config with the next boot cpus information and also
registers the reset callback to be called when guest reboots to reset the cpu.

Co-developed-by: Keqian Zhu 
Signed-off-by: Salil Mehta 
---
 hw/arm/boot.c |  2 +-
 hw/arm/virt.c | 18 ++
 include/hw/arm/boot.h |  2 ++
 include/hw/arm/virt.h |  1 +
 4 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index fef4072db1..05f329c1e1 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -675,7 +675,7 @@ fail:
 return -1;
 }
 
-static void do_cpu_reset(void *opaque)
+void do_cpu_reset(void *opaque)
 {
 ARMCPU *cpu = opaque;
 CPUState *cs = CPU(cpu);
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index db7eca1b84..55101c0050 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -47,6 +47,7 @@
 #include "sysemu/device_tree.h"
 #include "sysemu/numa.h"
 #include "sysemu/runstate.h"
+#include "sysemu/reset.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/tpm.h"
 #include "sysemu/kvm.h"
@@ -1149,14 +1150,13 @@ static bool virt_firmware_init(VirtMachineState *vms,
 
 static FWCfgState *create_fw_cfg(const VirtMachineState *vms, AddressSpace *as)
 {
-MachineState *ms = MACHINE(vms);
 hwaddr base = vms->memmap[VIRT_FW_CFG].base;
 hwaddr size = vms->memmap[VIRT_FW_CFG].size;
 FWCfgState *fw_cfg;
 char *nodename;
 
 fw_cfg = fw_cfg_init_mem_wide(base + 8, base, 8, base + 16, as);
-fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)ms->smp.cpus);
+fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, vms->boot_cpus);
 
 nodename = g_strdup_printf("/fw-cfg@%" PRIx64, base);
 qemu_fdt_add_subnode(vms->fdt, nodename);
@@ -2468,7 +2468,13 @@ static void virt_cpu_plug(HotplugHandler *hotplug_dev, 
DeviceState *dev,
 hhc->plug(HOTPLUG_HANDLER(vms->acpi_dev), dev, _err);
 if (local_err)
 goto fail;
-/* TODO: register this cpu for reset & update F/W info for the next 
boot */
+
+/* register this cpu for reset & update F/W info for the next boot */
+qemu_register_reset(do_cpu_reset, ARM_CPU(cs));
+vms->boot_cpus++;
+if (vms->fw_cfg) {
+fw_cfg_modify_i16(vms->fw_cfg, FW_CFG_NB_CPUS, vms->boot_cpus);
+}
 }
 
 cs->disabled = false;
@@ -2540,7 +2546,11 @@ static void virt_cpu_unplug(HotplugHandler *hotplug_dev, 
DeviceState *dev,
 unwire_gic_cpu_irqs(vms, cs);
 virt_update_gic(vms, cs);
 
-/* TODO: unregister this cpu for reset & update F/W info for the next boot 
*/
+qemu_unregister_reset(do_cpu_reset, ARM_CPU(cs));
+vms->boot_cpus--;
+if (vms->fw_cfg) {
+fw_cfg_modify_i16(vms->fw_cfg, FW_CFG_NB_CPUS, vms->boot_cpus);
+}
 
 qemu_opts_del(dev->opts);
 dev->opts = NULL;
diff --git a/include/hw/arm/boot.h b/include/hw/arm/boot.h
index ce2b48b88b..aa156967af 100644
--- a/include/hw/arm/boot.h
+++ b/include/hw/arm/boot.h
@@ -163,6 +163,8 @@ AddressSpace *arm_boot_address_space(ARMCPU *cpu,
 int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
  hwaddr addr_limit, AddressSpace *as, MachineState *ms);
 
+void do_cpu_reset(void *opaque);
+
 /* Write a secure board setup routine with a dummy handler for SMCs */
 void arm_write_secure_board_setup_dummy_smc(ARMCPU *cpu,
 const struct arm_boot_info *info,
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index c287433219..df785ea6ba 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -147,6 +147,7 @@ typedef struct {
 const int *irqmap;
 int smp_cpus;
 int max_cpus;
+uint16_t boot_cpus;
 void *fdt;
 int fdt_size;
 uint32_t clock_phandle;
-- 
2.17.1





[PATCH RFC 22/22] arm/cpuhp: Add support of *unrealize* ARMCPU during vcpu hot-unplug

2020-06-13 Thread Salil Mehta
During vcpu hot-unplug ARM cpu unrealization shall happen which should do away
with all the vcpu thread creations, allocations, registrations which happened
as part of the realization process of the ARM cpu. This change introduces the
ARM cpu unrealize function taking care of exactly that.

Note, initialized vcpus are not destroyed at host KVM but are rather parked in
the QEMU/KVM layer. These are later reused once vcpu is hotplugged again.

Co-developed-by: Keqian Zhu 
Signed-off-by: Salil Mehta 
---
 exec.c  | 24 
 gdbstub.c   | 13 +++
 include/exec/exec-all.h |  8 
 include/exec/gdbstub.h  |  1 +
 include/hw/core/cpu.h   |  2 +
 target/arm/cpu-qom.h|  3 ++
 target/arm/cpu.c| 86 +
 target/arm/cpu.h| 13 +++
 target/arm/helper.c | 31 +++
 target/arm/internals.h  |  1 +
 target/arm/kvm64.c  |  7 +++-
 11 files changed, 188 insertions(+), 1 deletion(-)

diff --git a/exec.c b/exec.c
index a0bf9d61c8..7e808affdf 100644
--- a/exec.c
+++ b/exec.c
@@ -869,6 +869,7 @@ void cpu_address_space_init(CPUState *cpu, int asidx,
 
 if (!cpu->cpu_ases) {
 cpu->cpu_ases = g_new0(CPUAddressSpace, cpu->num_ases);
+cpu->cpu_ases_ref_count = cpu->num_ases;
 }
 
 newas = >cpu_ases[asidx];
@@ -881,6 +882,29 @@ void cpu_address_space_init(CPUState *cpu, int asidx,
 }
 }
 
+void cpu_address_space_destroy(CPUState *cpu, int asidx)
+{
+CPUAddressSpace *cpuas;
+
+assert(asidx < cpu->num_ases);
+assert(asidx == 0 || !kvm_enabled());
+assert(cpu->cpu_ases);
+
+cpuas = >cpu_ases[asidx];
+if (tcg_enabled()) {
+memory_listener_unregister(>tcg_as_listener);
+}
+
+address_space_destroy(cpuas->as);
+
+if(cpu->cpu_ases_ref_count == 1) {
+g_free(cpu->cpu_ases);
+cpu->cpu_ases = NULL;
+}
+
+cpu->cpu_ases_ref_count--;
+}
+
 AddressSpace *cpu_get_address_space(CPUState *cpu, int asidx)
 {
 /* Return the AddressSpace corresponding to the specified index */
diff --git a/gdbstub.c b/gdbstub.c
index 6950fd243f..e960268d15 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -982,6 +982,19 @@ void gdb_register_coprocessor(CPUState *cpu,
 }
 }
 
+void gdb_unregister_coprocessor_all(CPUState *cpu)
+{
+GDBRegisterState *s, *p;
+
+p = cpu->gdb_regs;
+while (p) {
+s = p;
+p = p->next;
+g_free(s);
+}
+cpu->gdb_regs = NULL;
+}
+
 #ifndef CONFIG_USER_ONLY
 /* Translate GDB watchpoint type to a flags value for cpu_watchpoint_* */
 static inline int xlat_gdb_type(CPUState *cpu, int gdbtype)
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 8792bea07a..44420c144d 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -115,6 +115,14 @@ void cpu_reloading_memory_map(void);
  */
 void cpu_address_space_init(CPUState *cpu, int asidx,
 const char *prefix, MemoryRegion *mr);
+/**
+ * cpu_address_space_destroy:
+ * @cpu: CPU for which address space needs to be destroyed
+ * @asidx: integer index of this address space
+ *
+ * Note that with KVM only one address space is supported.
+ */
+void cpu_address_space_destroy(CPUState *cpu, int asidx);
 #endif
 
 #if !defined(CONFIG_USER_ONLY) && defined(CONFIG_TCG)
diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
index 94d8f83e92..db2336d0df 100644
--- a/include/exec/gdbstub.h
+++ b/include/exec/gdbstub.h
@@ -73,6 +73,7 @@ typedef int (*gdb_set_reg_cb)(CPUArchState *env, uint8_t 
*buf, int reg);
 void gdb_register_coprocessor(CPUState *cpu,
   gdb_get_reg_cb get_reg, gdb_set_reg_cb set_reg,
   int num_regs, const char *xml, int g_pos);
+void gdb_unregister_coprocessor_all(CPUState *cpu);
 
 /*
  * The GDB remote protocol transfers values in target byte order. As
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index d9cae71ea5..851f03dd83 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -379,6 +379,7 @@ struct CPUState {
 struct qemu_work_item *queued_work_first, *queued_work_last;
 
 CPUAddressSpace *cpu_ases;
+int cpu_ases_ref_count;
 int num_ases;
 AddressSpace *as;
 MemoryRegion *memory;
@@ -410,6 +411,7 @@ struct CPUState {
 int kvm_fd;
 struct KVMState *kvm_state;
 struct kvm_run *kvm_run;
+VMChangeStateEntry *vmcse;
 
 /* Used for events with 'vcpu' and *without* the 'disabled' properties */
 DECLARE_BITMAP(trace_dstate_delayed, CPU_TRACE_DSTATE_MAX_EVENTS);
diff --git a/target/arm/cpu-qom.h b/target/arm/cpu-qom.h
index 56395b87f6..d943683551 100644
--- a/target/arm/cpu-qom.h
+++ b/target/arm/cpu-qom.h
@@ -58,6 +58,7 @@ typedef struct ARMCPUClass {
 
 const ARMCPUInfo *info;
 DeviceRealize parent_realize;
+DeviceUnrealize parent_unrealize;
 DeviceReset parent_reset;
 } ARMCPUClass;
 
@@ -76,7 +77,9 @@ typedef struct AArch64CPUClass {
 } 

[PATCH RFC 18/22] arm/cpuhp: Changes to update GIC with vcpu hot-plug notification

2020-06-13 Thread Salil Mehta
Adds the notification support about vcpu hot-(un)plug required to update the
GIC so that it can update its vcpu to GIC cpu interface association.

NOTE: This is using 'struct VirtMachineState' inside the notifier function.
  Question:  Not sure if it is right to use machine related data structure
  inside GIC related files? Its design looks to be pretty much abstracted
  from any machine related stuff. @Peter Maydell

Co-developed-by: Keqian Zhu 
Signed-off-by: Salil Mehta 
---
 hw/arm/virt.c  | 12 +--
 hw/intc/arm_gicv3_common.c | 54 ++
 hw/intc/arm_gicv3_cpuif.c  |  5 +++
 hw/intc/gicv3_internal.h   |  1 +
 include/hw/arm/virt.h  |  1 +
 include/hw/intc/arm_gicv3_common.h |  1 +
 6 files changed, 72 insertions(+), 2 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index f0295e940e..b4cfd53a59 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -1928,6 +1928,8 @@ static void machvirt_init(MachineState *machine)
 
 create_fdt(vms);
 
+notifier_list_init(>cpuhp_notifiers);
+
 possible_cpus = mc->possible_cpu_arch_ids(machine);
 for (n = 0; n < possible_cpus->len; n++) {
 Object *cpuobj;
@@ -2378,6 +2380,12 @@ out:
 error_propagate(errp, local_err);
 }
 
+static void virt_update_gic(VirtMachineState *vms, CPUState *cs)
+{
+/* notify gic to stitch GICC to this new cpu */
+notifier_list_notify(>cpuhp_notifiers, cs);
+}
+
 static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
   Error **errp)
 {
@@ -2432,7 +2440,7 @@ static void virt_cpu_pre_plug(HotplugHandler 
*hotplug_dev, DeviceState *dev,
 virt_cpu_set_properties(OBJECT(cs), cpu_slot);
 
 if (dev->hotplugged) {
-/* TODO: update GIC about this hotplug change here */
+virt_update_gic(vms, cs);
 }
 }
 
@@ -2506,7 +2514,7 @@ static void virt_cpu_unplug(HotplugHandler *hotplug_dev, 
DeviceState *dev,
 /* TODO: update the acpi cpu hotplug state for cpu hot-unplug */
 
 unwire_gic_cpu_irqs(vms, cs);
-/* TODO: update the GIC about this hot unplug change */
+virt_update_gic(vms, cs);
 
 /* TODO: unregister this cpu for reset & update F/W info for the next boot 
*/
 
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
index bfa51a..f6b7b359cb 100644
--- a/hw/intc/arm_gicv3_common.c
+++ b/hw/intc/arm_gicv3_common.c
@@ -31,6 +31,7 @@
 #include "gicv3_internal.h"
 #include "hw/arm/linux-boot-if.h"
 #include "sysemu/kvm.h"
+#include "hw/arm/virt.h"
 
 
 static void gicv3_gicd_no_migration_shift_bug_post_load(GICv3State *cs)
@@ -305,8 +306,57 @@ void gicv3_init_irqs_and_mmio(GICv3State *s, 
qemu_irq_handler handler,
 }
 }
 
+static int arm_gicv3_get_proc_num(GICv3State *s, CPUState *cpu)
+{
+uint64_t mp_affinity;
+uint64_t gicr_typer;
+uint64_t cpu_affid;
+int i;
+
+mp_affinity = object_property_get_uint(OBJECT(cpu), "mp-affinity", NULL);
+/* match the cpu mp-affinity to get the gic cpuif number */
+for (i = 0; i < s->num_cpu; i++) {
+gicr_typer = s->cpu[i].gicr_typer;
+cpu_affid = (gicr_typer >> 32) & 0xFF;
+if (cpu_affid == mp_affinity) {
+return i;
+}
+}
+
+return -1;
+}
+
+static void arm_gicv3_cpu_update_notifier(Notifier * notifier, void * data)
+{
+VirtMachineState *vms = VIRT_MACHINE(qdev_get_machine());
+GICv3State *s = ARM_GICV3_COMMON(vms->gic);
+CPUState *cpu = (CPUState *)data;
+int gic_cpuif_num;
+
+/* this shall get us mapped gicv3 cpuif corresponding to mpidr */
+gic_cpuif_num = arm_gicv3_get_proc_num(s, cpu);
+if (gic_cpuif_num < 0) {
+error_report("Failed to associate cpu %d with any GIC cpuif",
+ cpu->cpu_index);
+abort();
+}
+
+/* check if update is for vcpu hot-unplug */
+if (qemu_present_cpu(cpu)) {
+s->cpu[gic_cpuif_num].cpu = NULL;
+return;
+}
+
+/* re-stitch the gic cpuif to this new cpu */
+gicv3_set_gicv3state(cpu, >cpu[gic_cpuif_num]);
+gicv3_set_cpustate(>cpu[gic_cpuif_num], cpu);
+
+/* TODO: initialize the registers info for this newly added cpu */
+}
+
 static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
 {
+VirtMachineState *vms = VIRT_MACHINE(qdev_get_machine());
 GICv3State *s = ARM_GICV3_COMMON(dev);
 int i;
 
@@ -386,12 +436,16 @@ static void arm_gicv3_common_realize(DeviceState *dev, 
Error **errp)
 (i << 8) |
 (last << 4);
 }
+
+s->cpu_update_notifier.notify = arm_gicv3_cpu_update_notifier;
+notifier_list_add(>cpuhp_notifiers, >cpu_update_notifier);
 }
 
 static void arm_gicv3_finalize(Object *obj)
 {
 GICv3State *s = ARM_GICV3_COMMON(obj);
 
+notifier_remove(>cpu_update_notifier);
 g_free(s->redist_region_count);
 }
 
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
index 

[PATCH RFC 14/22] arm/cpuhp: Release objects for *disabled* possible vcpus after init

2020-06-13 Thread Salil Mehta
During machvirt_init(), ARMCPU objects are pre-created along with the
corresponding KVM vcpus in the host. Disabled possible KVM vcpus are then
parked at the per-virt-machine list "kvm_parked_vcpus".

Prime purpose to pre-create ARMCPU objects for the disabled vcpus is to
facilitate the GIC initialization (pre-sized with possible vcpus). GIC
requires all vcpus corresponding to its GICC(GIC CPU Interface) to be
initialized and present during its own initialization.

After initialization of the machine is complete we release the ARMCPU objects
for the disabled vcpus(which shall be re-created at the time when vcpu is hot
plugged again. This newly created ARMCPU object is then attached with
corresponding parked KVM VCPU).

We have few options after the machine init where the disabled ARMCPU object
could be released:
1. Release in context to the virt_machine_done() notifier.(This is also our
   current approach)
2. Defer the release till a new vcpu object is hot plugged. Then release the
   object in context to the pre_plug() phase.
3. Never release and keep on reusing them and release once at VM exit. This
   will require some modifications within the interface of qdevice_add() to
   get old ARMCPU object instead of creating a new one for the hotplug request.

Each of the above approaches come with their own pros and cons. This prototype
uses the 1st approach.(suggestions are welcome!)

Co-developed-by: Keqian Zhu 
Signed-off-by: Salil Mehta 
---
 hw/arm/virt.c | 25 +
 1 file changed, 25 insertions(+)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index e9ead0e2dd..0faf54aa8f 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -1403,6 +1403,28 @@ static void create_secure_ram(VirtMachineState *vms,
 g_free(nodename);
 }
 
+static void virt_remove_disabled_cpus(VirtMachineState *vms)
+{
+MachineState *ms = MACHINE(vms);
+int n;
+
+/*
+ * RFC: Question: Other approach could have been to keep them forever
+ * and release it only once when qemu exits as part o finalize or when
+ * new vcpu is hotplugged. In the later old could be released for the
+ * newly created object for the same vcpu?
+ */
+for (n = vms->smp_cpus; n < vms->max_cpus; n++) {
+CPUState *cs = qemu_get_possible_cpu(n);
+if (!qemu_present_cpu(cs)) {
+CPUArchId *cpu_slot;
+cpu_slot = virt_find_cpu_slot(ms, cs->cpu_index);
+cpu_slot->cpu = NULL;
+object_unref(OBJECT(cs));
+}
+}
+}
+
 static bool virt_pmu_init(VirtMachineState *vms)
 {
 CPUArchIdList *possible_cpus = vms->parent.possible_cpus;
@@ -1500,6 +1522,9 @@ void virt_machine_done(Notifier *notifier, void *data)
 
 virt_acpi_setup(vms);
 virt_build_smbios(vms);
+
+/* release the disabled ARMCPU objects used during init for pre-sizing */
+ virt_remove_disabled_cpus(vms);
 }
 
 static uint64_t virt_cpu_mp_affinity(VirtMachineState *vms, int idx)
-- 
2.17.1





[PATCH RFC 17/22] arm/cpuhp: Changes to (un)wire GICC<->VCPU IRQs during hot-(un)plug

2020-06-13 Thread Salil Mehta
Refactors the existing gic create code to extract common code to wire the
vcpu<->gic interrupts. This function could be used with cold-plug case and also
used when vcpu is hot-plugged. It also introduces a new function to unwire the
vcpu>->gic interrupts for the vcpu hot-unplug cases.

Co-developed-by: Keqian Zhu 
Signed-off-by: Salil Mehta 
---
 hw/arm/virt.c  | 144 +
 hw/core/qdev.c |   2 +-
 include/hw/qdev-core.h |   2 +
 3 files changed, 104 insertions(+), 44 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index ac2941159a..f0295e940e 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -615,6 +615,103 @@ static void create_v2m(VirtMachineState *vms)
 fdt_add_v2m_gic_node(vms);
 }
 
+static void unwire_gic_cpu_irqs(VirtMachineState *vms, CPUState *cs)
+{
+unsigned int max_cpus = vms->max_cpus;
+DeviceState *cpudev = DEVICE(cs);
+DeviceState *gicdev = vms->gic;
+int cpu = CPU(cs)->cpu_index;
+int type = vms->gic_version;
+int irq;
+
+/* Mapping from the output timer irq lines from the CPU to the
+ * GIC PPI inputs we use for the virt board.
+ */
+const int timer_irq[] = {
+[GTIMER_PHYS] = ARCH_TIMER_NS_EL1_IRQ,
+[GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ,
+[GTIMER_HYP]  = ARCH_TIMER_NS_EL2_IRQ,
+[GTIMER_SEC]  = ARCH_TIMER_S_EL1_IRQ,
+};
+
+for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
+qdev_disconnect_gpio_out_named(cpudev, NULL, irq);
+}
+
+if (type == 3) {
+qdev_disconnect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt", 
0);
+} else if (vms->virt) {
+qdev_disconnect_gpio_out_named(gicdev, SYSBUS_DEVICE_GPIO_IRQ, cpu + 4 
* max_cpus);
+}
+
+/*
+ * RFC: Question: This currently does not takes care of intimating the 
devices
+ * which might be sitting on system bus. Do we need a 
sysbus_disconnect_irq()
+ * which also does the job of notification beside disconnection?
+ */
+qdev_disconnect_gpio_out_named(cpudev, "pmu-interrupt", 0);
+qdev_disconnect_gpio_out_named(gicdev, SYSBUS_DEVICE_GPIO_IRQ, cpu);
+qdev_disconnect_gpio_out_named(gicdev,
+   SYSBUS_DEVICE_GPIO_IRQ, cpu + max_cpus);
+qdev_disconnect_gpio_out_named(gicdev, SYSBUS_DEVICE_GPIO_IRQ,
+   cpu + 2 * max_cpus);
+qdev_disconnect_gpio_out_named(gicdev, SYSBUS_DEVICE_GPIO_IRQ,
+   cpu + 3 * max_cpus);
+}
+
+static void wire_gic_cpu_irqs(VirtMachineState *vms, CPUState *cs)
+{
+unsigned int max_cpus = vms->max_cpus;
+DeviceState *cpudev = DEVICE(cs);
+DeviceState *gicdev = vms->gic;
+int cpu = CPU(cs)->cpu_index;
+int type = vms->gic_version;
+SysBusDevice *gicbusdev;
+int ppibase;
+int irq;
+
+ppibase = NUM_IRQS + cpu * GIC_INTERNAL + GIC_NR_SGIS;
+
+/* Mapping from the output timer irq lines from the CPU to the
+ * GIC PPI inputs we use for the virt board.
+ */
+const int timer_irq[] = {
+[GTIMER_PHYS] = ARCH_TIMER_NS_EL1_IRQ,
+[GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ,
+[GTIMER_HYP]  = ARCH_TIMER_NS_EL2_IRQ,
+[GTIMER_SEC]  = ARCH_TIMER_S_EL1_IRQ,
+};
+
+for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
+qdev_connect_gpio_out(cpudev, irq,
+  qdev_get_gpio_in(gicdev,
+   ppibase + timer_irq[irq]));
+}
+
+gicbusdev = SYS_BUS_DEVICE(gicdev);
+if (type == 3) {
+qemu_irq irq = qdev_get_gpio_in(gicdev,
+ppibase + ARCH_GIC_MAINT_IRQ);
+qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
+0, irq);
+} else if (vms->virt) {
+qemu_irq irq = qdev_get_gpio_in(gicdev,
+ppibase + ARCH_GIC_MAINT_IRQ);
+sysbus_connect_irq(gicbusdev, cpu + 4 * max_cpus, irq);
+}
+
+qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
+qdev_get_gpio_in(gicdev,
+ ppibase + VIRTUAL_PMU_IRQ));
+sysbus_connect_irq(gicbusdev, cpu, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
+sysbus_connect_irq(gicbusdev, cpu + max_cpus,
+   qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
+sysbus_connect_irq(gicbusdev, cpu + 2 * max_cpus,
+   qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
+sysbus_connect_irq(gicbusdev, cpu + 3 * max_cpus,
+   qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
+}
+
 static void create_gic(VirtMachineState *vms)
 {
 /* We create a standalone GIC */
@@ -684,47 +781,7 @@ static void create_gic(VirtMachineState *vms)
  * and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's inputs.
  */
 for (i = 0; i < smp_cpus; i++) {
-DeviceState *cpudev = 

[PATCH RFC 16/22] arm/cpuhp: Add/update basic hot-(un)plug framework

2020-06-13 Thread Salil Mehta
Adds the new cpu hot-unplug hooks and updates the existing hotplug hooks with
sanity checks.

Note, Functional contents of the hooks(now left with TODO comment) shall be
gradually filled in the subsequent patches in an incremental approach to patch
and logic building which would be roughly as follows:
1. (Un-)wiring of interrupts between vcpu<->gic
2. Sending events to Guest for hot-(un)plug so that guest can take appropriate
   actions.
3. Notifying GIC about hot-(un)plug action so that vcpu could be (un-)stitched
   to the GIC CPU interface.
4. Updating the Guest with Next boot info for this vcpu in the firmware.

Co-developed-by: Keqian Zhu 
Signed-off-by: Salil Mehta 
---
 hw/arm/virt.c | 102 +-
 1 file changed, 100 insertions(+), 2 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 0faf54aa8f..ac2941159a 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2324,11 +2324,23 @@ out:
 static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
   Error **errp)
 {
+VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
 MachineState *ms = MACHINE(hotplug_dev);
 ARMCPU *cpu = ARM_CPU(dev);
 CPUState *cs = CPU(dev);
 CPUArchId *cpu_slot;
 
+if (dev->hotplugged && !vms->acpi_dev) {
+error_setg(errp, "GED acpi device does not exists");
+return;
+}
+
+if (dev->hotplugged && (vms->gic_version < VIRT_GIC_VERSION_3)) {
+error_setg(errp, "CPU hotplug not supported with GICv%d, use GICv3 or "
+   "later", vms->gic_version);
+return;
+}
+
 /* sanity check the cpu */
 if (!object_dynamic_cast(OBJECT(cpu), ms->cpu_type)) {
 error_setg(errp, "Invalid CPU type, expected cpu type: '%s'",
@@ -2361,6 +2373,10 @@ static void virt_cpu_pre_plug(HotplugHandler 
*hotplug_dev, DeviceState *dev,
 return;
 }
 virt_cpu_set_properties(OBJECT(cs), cpu_slot);
+
+if (dev->hotplugged) {
+/* TODO: update GIC about this hotplug change here */
+}
 }
 
 static void virt_cpu_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
@@ -2375,10 +2391,75 @@ static void virt_cpu_plug(HotplugHandler *hotplug_dev, 
DeviceState *dev,
 cpu_slot = virt_find_cpu_slot(ms, cpu->core_id);
 cpu_slot->cpu = OBJECT(dev);
 
+if (dev->hotplugged) {
+/* TODO: wire the gic-cpu irqs */
+/* TODO: update acpi hotplug state and send cpu hotplug event to guest 
*/
+/* TODO: register this cpu for reset & update F/W info for the next 
boot */
+}
+
 cs->disabled = false;
 return;
 }
 
+static void virt_cpu_unplug_request(HotplugHandler *hotplug_dev,
+DeviceState *dev, Error **errp)
+{
+VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
+CPUState *cs = CPU(dev);
+
+if (!vms->acpi_dev || !dev->realized) {
+error_setg(errp, "GED does not exists or device is not realized!");
+return;
+}
+
+if (vms->gic_version < VIRT_GIC_VERSION_3) {
+error_setg(errp, "CPU hot-unplug not supported with GICv%d",
+   vms->gic_version);
+return;
+}
+
+if (cs->cpu_index == first_cpu->cpu_index)
+{
+error_setg(errp, "hot-unplug of ARM boot vcpu %d not supported",
+   first_cpu->cpu_index);
+return;
+}
+
+/* TODO: request cpu hotplug from guest */
+
+return;
+}
+
+static void virt_cpu_unplug(HotplugHandler *hotplug_dev, DeviceState *dev,
+Error **errp)
+{
+VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
+MachineState *ms = MACHINE(hotplug_dev);
+CPUState *cs = CPU(dev);
+CPUArchId *cpu_slot;
+
+if (!vms->acpi_dev || !dev->realized) {
+error_setg(errp, "GED does not exists or device is not realized!");
+return;
+}
+
+cpu_slot = virt_find_cpu_slot(ms, ARM_CPU(cs)->core_id);
+
+/* TODO: update the acpi cpu hotplug state for cpu hot-unplug */
+
+/* TODO: unwire the gic-cpu irqs here */
+/* TODO: update the GIC about this hot unplug change */
+
+/* TODO: unregister this cpu for reset & update F/W info for the next boot 
*/
+
+qemu_opts_del(dev->opts);
+dev->opts = NULL;
+
+cpu_slot->cpu = NULL;
+cs->disabled = true;
+return;
+}
+
 static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
 DeviceState *dev, Error **errp)
 {
@@ -2417,8 +2498,23 @@ static void virt_machine_device_plug_cb(HotplugHandler 
*hotplug_dev,
 static void virt_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev,
   DeviceState *dev, Error **errp)
 {
-error_setg(errp, "device unplug request for unsupported device"
-   " type: %s", object_get_typename(OBJECT(dev)));
+if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
+virt_cpu_unplug_request(hotplug_dev, dev, 

[PATCH RFC 13/22] arm/cpuhp: Add ACPI _MAT entry for Processor object

2020-06-13 Thread Salil Mehta
Adds a function which builds the ACPI _MAT entry for processor objects. This
shall be called from the cpus AML for all possible vcpus.

The entry is passed to the guest kernel with ACPI_MADT_GICC_ENABLED flag when
it evaluates _MAT object. OSPM evaluates _MAT object in context to the cpu
hotplug event.

Co-developed-by: Keqian Zhu 
Signed-off-by: Salil Mehta 
---
 hw/acpi/cpu.c|  5 +
 hw/arm/virt-acpi-build.c | 20 
 include/hw/arm/virt.h|  1 +
 3 files changed, 26 insertions(+)

diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
index 867fdd6993..a79dc65120 100644
--- a/hw/acpi/cpu.c
+++ b/hw/acpi/cpu.c
@@ -565,6 +565,11 @@ void build_cpus_aml(Aml *table, MachineState *machine, 
CPUHotplugFeatures opts,
 apic->flags = cpu_to_le32(1);
 break;
 }
+case ACPI_APIC_GENERIC_CPU_INTERFACE: {
+AcpiMadtGenericCpuInterface *gicc = (void *)madt_buf->data;
+gicc->flags = cpu_to_le32(1);
+break;
+}
 default:
 assert(0);
 }
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index c654e2c9a3..354fd775f9 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -593,6 +593,22 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, 
VirtMachineState *vms)
 }
 
 /* MADT */
+static void
+build_mat_entry(AcpiDeviceIf *adev, int uid, const CPUArchIdList *arch_ids,
+GArray *entry)
+{
+AcpiMadtGenericCpuInterface *gicc = acpi_data_push(entry,sizeof(*gicc));
+MachineState *ms = MACHINE(qdev_get_machine());
+CPUArchIdList *possible_cpus = ms->possible_cpus;
+
+/* fill the relevant fields of _MAT entry for GICC */
+gicc->type = ACPI_APIC_GENERIC_CPU_INTERFACE;
+gicc->length = sizeof(*gicc);
+gicc->cpu_interface_number = cpu_to_le32(uid);
+gicc->arm_mpidr = possible_cpus->cpus[uid].arch_id;
+gicc->uid = cpu_to_le32(uid);
+}
+
 static void
 build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
 {
@@ -741,6 +757,10 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, 
VirtMachineState *vms)
  .acpi_1_compatible = false,
  .has_legacy_cphp = false
 };
+AcpiDeviceIfClass *adevc;
+/* _MAT entry shall be used within cpus aml */
+adevc = ACPI_DEVICE_IF_CLASS(DEVICE_GET_CLASS(vms->acpi_dev));
+adevc->madt_cpu = build_mat_entry;
 
 build_cpus_aml(scope, ms, opts, memmap[VIRT_CPUHP_ACPI].base,
"\\_SB", NULL, AML_SYSTEM_MEMORY);
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index e0bd9df69d..e8468d8cf6 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -37,6 +37,7 @@
 #include "hw/block/flash.h"
 #include "sysemu/kvm.h"
 #include "hw/intc/arm_gicv3_common.h"
+#include "hw/acpi/acpi_dev_interface.h"
 
 #define NUM_GICV2M_SPIS   64
 #define NUM_VIRTIO_TRANSPORTS 32
-- 
2.17.1





[PATCH RFC 20/22] arm/cpuhp: Update the guest(via GED) about cpu hot-(un)plug events

2020-06-13 Thread Salil Mehta
During any vcpu hot-(un)plug, running guest VM needs to be intimated about the
new vcpu being added or request the deletion of the vcpu which is already part
of the guest VM. This is done using the ACPI GED event which eventually gets
demultiplexed to a CPU hotplug event and further to specific hot-(un)plug event
of a particular vcpu.

This change adds the ACPI calls to the existing hot-(un)plug hooks to trigger
ACPI GED events from QEMU to guest VM.

Co-developed-by: Keqian Zhu 
Signed-off-by: Salil Mehta 
---
 hw/arm/virt.c | 32 +---
 1 file changed, 29 insertions(+), 3 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index b4cfd53a59..db7eca1b84 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2451,6 +2451,7 @@ static void virt_cpu_plug(HotplugHandler *hotplug_dev, 
DeviceState *dev,
 MachineState *ms = MACHINE(hotplug_dev);
 ARMCPU *cpu = ARM_CPU(dev);
 CPUState *cs = CPU(dev);
+Error *local_err = NULL;
 CPUArchId *cpu_slot;
 
 /* insert the cold/hot-plugged vcpu in the slot */
@@ -2458,20 +2459,31 @@ static void virt_cpu_plug(HotplugHandler *hotplug_dev, 
DeviceState *dev,
 cpu_slot->cpu = OBJECT(dev);
 
 if (dev->hotplugged) {
+HotplugHandlerClass *hhc;
+
 wire_gic_cpu_irqs(vms, cs);
-/* TODO: update acpi hotplug state and send cpu hotplug event to guest 
*/
+
+/* update acpi hotplug state and send cpu hotplug event to guest */
+hhc = HOTPLUG_HANDLER_GET_CLASS(vms->acpi_dev);
+hhc->plug(HOTPLUG_HANDLER(vms->acpi_dev), dev, _err);
+if (local_err)
+goto fail;
 /* TODO: register this cpu for reset & update F/W info for the next 
boot */
 }
 
 cs->disabled = false;
 return;
+fail:
+error_propagate(errp, local_err);
 }
 
 static void virt_cpu_unplug_request(HotplugHandler *hotplug_dev,
 DeviceState *dev, Error **errp)
 {
 VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
+HotplugHandlerClass *hhc;
 CPUState *cs = CPU(dev);
+Error *local_err = NULL;
 
 if (!vms->acpi_dev || !dev->realized) {
 error_setg(errp, "GED does not exists or device is not realized!");
@@ -2491,9 +2503,15 @@ static void virt_cpu_unplug_request(HotplugHandler 
*hotplug_dev,
 return;
 }
 
-/* TODO: request cpu hotplug from guest */
+/* request cpu hotplug from guest */
+hhc = HOTPLUG_HANDLER_GET_CLASS(vms->acpi_dev);
+hhc->unplug_request(HOTPLUG_HANDLER(vms->acpi_dev), dev, _err);
+if (local_err)
+goto fail;
 
 return;
+fail:
+error_propagate(errp, local_err);
 }
 
 static void virt_cpu_unplug(HotplugHandler *hotplug_dev, DeviceState *dev,
@@ -2501,7 +2519,9 @@ static void virt_cpu_unplug(HotplugHandler *hotplug_dev, 
DeviceState *dev,
 {
 VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
 MachineState *ms = MACHINE(hotplug_dev);
+HotplugHandlerClass *hhc;
 CPUState *cs = CPU(dev);
+Error *local_err = NULL;
 CPUArchId *cpu_slot;
 
 if (!vms->acpi_dev || !dev->realized) {
@@ -2511,7 +2531,11 @@ static void virt_cpu_unplug(HotplugHandler *hotplug_dev, 
DeviceState *dev,
 
 cpu_slot = virt_find_cpu_slot(ms, ARM_CPU(cs)->core_id);
 
-/* TODO: update the acpi cpu hotplug state for cpu hot-unplug */
+/* update the acpi cpu hotplug state for cpu hot-unplug */
+hhc = HOTPLUG_HANDLER_GET_CLASS(vms->acpi_dev);
+hhc->unplug(HOTPLUG_HANDLER(vms->acpi_dev), dev, _err);
+if (local_err)
+goto fail;
 
 unwire_gic_cpu_irqs(vms, cs);
 virt_update_gic(vms, cs);
@@ -2524,6 +2548,8 @@ static void virt_cpu_unplug(HotplugHandler *hotplug_dev, 
DeviceState *dev,
 cpu_slot->cpu = NULL;
 cs->disabled = true;
 return;
+fail:
+error_propagate(errp, local_err);
 }
 
 static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
-- 
2.17.1





[PATCH RFC 15/22] arm/cpuhp: Update ACPI GED framework to support vcpu hotplug

2020-06-13 Thread Salil Mehta
ACPI GED shall be used to convey to the guest kernel about any cpu hot-(un)plug
events. Therefore, existing ACPI GED framework inside QEMU needs to be enhanced
to support CPU hotplug state and events.

Co-developed-by: Keqian Zhu 
Signed-off-by: Salil Mehta 
---
 hw/acpi/generic_event_device.c | 42 ++
 1 file changed, 42 insertions(+)

diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
index 79177deda2..df81e9292a 100644
--- a/hw/acpi/generic_event_device.c
+++ b/hw/acpi/generic_event_device.c
@@ -13,7 +13,9 @@
 #include "qapi/error.h"
 #include "exec/address-spaces.h"
 #include "hw/acpi/acpi.h"
+#include "hw/acpi/cpu.h"
 #include "hw/acpi/generic_event_device.h"
+#include "hw/arm/virt.h"
 #include "hw/irq.h"
 #include "hw/mem/pc-dimm.h"
 #include "hw/mem/nvdimm.h"
@@ -192,12 +194,47 @@ static void acpi_ged_device_plug_cb(HotplugHandler 
*hotplug_dev,
 } else {
 acpi_memory_plug_cb(hotplug_dev, >memhp_state, dev, errp);
 }
+} else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
+acpi_cpu_plug_cb(hotplug_dev, >cpuhp_state, dev, errp);
 } else {
 error_setg(errp, "virt: device plug request for unsupported device"
" type: %s", object_get_typename(OBJECT(dev)));
 }
 }
 
+static void acpi_ged_device_unplug_request_cb(HotplugHandler *hotplug_dev,
+DeviceState *dev, Error **errp)
+{
+AcpiGedState *s = ACPI_GED(hotplug_dev);
+
+if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
+acpi_cpu_unplug_request_cb(hotplug_dev, >cpuhp_state, dev, 
errp);
+} else {
+error_setg(errp, "virt: device unplug request for the unsupported 
device"
+   " type: %s", object_get_typename(OBJECT(dev)));
+}
+}
+
+static void acpi_ged_device_unplug_cb(HotplugHandler *hotplug_dev,
+  DeviceState *dev, Error **errp)
+{
+AcpiGedState *s = ACPI_GED(hotplug_dev);
+
+if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
+acpi_cpu_unplug_cb(>cpuhp_state, dev, errp);
+ } else {
+ error_setg(errp, "virt: device plug request for unsupported device"
+" type: %s", object_get_typename(OBJECT(dev)));
+ }
+}
+
+static void acpi_ged_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list)
+{
+AcpiGedState *s = ACPI_GED(adev);
+
+acpi_cpu_ospm_status(>cpuhp_state, list);
+}
+
 static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev)
 {
 AcpiGedState *s = ACPI_GED(adev);
@@ -210,6 +247,8 @@ static void acpi_ged_send_event(AcpiDeviceIf *adev, 
AcpiEventStatusBits ev)
 sel = ACPI_GED_PWR_DOWN_EVT;
 } else if (ev & ACPI_NVDIMM_HOTPLUG_STATUS) {
 sel = ACPI_GED_NVDIMM_HOTPLUG_EVT;
+} else if (ev & ACPI_CPU_HOTPLUG_STATUS) {
+sel = ACPI_GED_CPU_HOTPLUG_EVT;
 } else {
 /* Unknown event. Return without generating interrupt. */
 warn_report("GED: Unsupported event %d. No irq injected", ev);
@@ -330,8 +369,11 @@ static void acpi_ged_class_init(ObjectClass *class, void 
*data)
 dc->vmsd = _acpi_ged;
 
 hc->plug = acpi_ged_device_plug_cb;
+hc->unplug_request = acpi_ged_device_unplug_request_cb;
+hc->unplug = acpi_ged_device_unplug_cb;
 
 adevc->send_event = acpi_ged_send_event;
+adevc->ospm_status = acpi_ged_ospm_status;
 }
 
 static const TypeInfo acpi_ged_info = {
-- 
2.17.1





[PATCH RFC 19/22] arm/cpuhp: Changes required to (re)init the vcpu register info

2020-06-13 Thread Salil Mehta
VCPU register info needs to be re-initialized each time vcpu is hot-plugged.
This has to be done both for emulation/TCG and KVM case. This is done in
context to the GIC update notification for any vcpu hot-(un)plug events. This
change adds that support and re-factors existing to maximize the code re-use.

Co-developed-by: Keqian Zhu 
Signed-off-by: Salil Mehta 
---
 hw/intc/arm_gicv3.c|   1 +
 hw/intc/arm_gicv3_common.c |   6 +-
 hw/intc/arm_gicv3_cpuif.c  | 134 -
 hw/intc/arm_gicv3_kvm.c|   7 +-
 hw/intc/gicv3_internal.h   |   1 +
 include/hw/intc/arm_gicv3_common.h |   1 +
 6 files changed, 86 insertions(+), 64 deletions(-)

diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c
index 66eaa97198..86f2f4cca7 100644
--- a/hw/intc/arm_gicv3.c
+++ b/hw/intc/arm_gicv3.c
@@ -396,6 +396,7 @@ static void arm_gicv3_class_init(ObjectClass *klass, void 
*data)
 ARMGICv3Class *agc = ARM_GICV3_CLASS(klass);
 
 agcc->post_load = arm_gicv3_post_load;
+agcc->init_cpu_reginfo = gicv3_init_cpu_reginfo;
 device_class_set_parent_realize(dc, arm_gic_realize, >parent_realize);
 }
 
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
index f6b7b359cb..01e4aba4f1 100644
--- a/hw/intc/arm_gicv3_common.c
+++ b/hw/intc/arm_gicv3_common.c
@@ -330,6 +330,7 @@ static void arm_gicv3_cpu_update_notifier(Notifier * 
notifier, void * data)
 {
 VirtMachineState *vms = VIRT_MACHINE(qdev_get_machine());
 GICv3State *s = ARM_GICV3_COMMON(vms->gic);
+ARMGICv3CommonClass *c = ARM_GICV3_COMMON_GET_CLASS(s);
 CPUState *cpu = (CPUState *)data;
 int gic_cpuif_num;
 
@@ -351,7 +352,10 @@ static void arm_gicv3_cpu_update_notifier(Notifier * 
notifier, void * data)
 gicv3_set_gicv3state(cpu, >cpu[gic_cpuif_num]);
 gicv3_set_cpustate(>cpu[gic_cpuif_num], cpu);
 
-/* TODO: initialize the registers info for this newly added cpu */
+/* initialize the registers info for this newly added cpu */
+if (c->init_cpu_reginfo) {
+c->init_cpu_reginfo(cpu);
+}
 }
 
 static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
index b3aa5979ca..1126fffa55 100644
--- a/hw/intc/arm_gicv3_cpuif.c
+++ b/hw/intc/arm_gicv3_cpuif.c
@@ -2605,6 +2605,74 @@ static const ARMCPRegInfo 
gicv3_cpuif_ich_apxr23_reginfo[] = {
 REGINFO_SENTINEL
 };
 
+void gicv3_init_cpu_reginfo(CPUState *cs)
+{
+ARMCPU *cpu = ARM_CPU(cs);
+GICv3CPUState *gcs = icc_cs_from_env(>env);
+
+/* Note that we can't just use the GICv3CPUState as an opaque pointer
+ * in define_arm_cp_regs_with_opaque(), because when we're called back
+ * it might be with code translated by CPU 0 but run by CPU 1, in
+ * which case we'd get the wrong value.
+ * So instead we define the regs with no ri->opaque info, and
+ * get back to the GICv3CPUState from the CPUARMState.
+ */
+define_arm_cp_regs(cpu, gicv3_cpuif_reginfo);
+if (arm_feature(>env, ARM_FEATURE_EL2)
+&& cpu->gic_num_lrs) {
+int j;
+
+gcs->maintenance_irq = cpu->gicv3_maintenance_interrupt;
+
+gcs->num_list_regs = cpu->gic_num_lrs;
+gcs->vpribits = cpu->gic_vpribits;
+gcs->vprebits = cpu->gic_vprebits;
+
+/* Check against architectural constraints: getting these
+ * wrong would be a bug in the CPU code defining these,
+ * and the implementation relies on them holding.
+ */
+g_assert(gcs->vprebits <= gcs->vpribits);
+g_assert(gcs->vprebits >= 5 && gcs->vprebits <= 7);
+g_assert(gcs->vpribits >= 5 && gcs->vpribits <= 8);
+
+define_arm_cp_regs(cpu, gicv3_cpuif_hcr_reginfo);
+
+for (j = 0; j < gcs->num_list_regs; j++) {
+/* Note that the AArch64 LRs are 64-bit; the AArch32 LRs
+ * are split into two cp15 regs, LR (the low part, with the
+ * same encoding as the AArch64 LR) and LRC (the high part).
+ */
+ARMCPRegInfo lr_regset[] = {
+{ .name = "ICH_LRn_EL2", .state = ARM_CP_STATE_BOTH,
+  .opc0 = 3, .opc1 = 4, .crn = 12,
+  .crm = 12 + (j >> 3), .opc2 = j & 7,
+  .type = ARM_CP_IO | ARM_CP_NO_RAW,
+  .access = PL2_RW,
+  .readfn = ich_lr_read,
+  .writefn = ich_lr_write,
+},
+{ .name = "ICH_LRCn_EL2", .state = ARM_CP_STATE_AA32,
+  .cp = 15, .opc1 = 4, .crn = 12,
+  .crm = 14 + (j >> 3), .opc2 = j & 7,
+  .type = ARM_CP_IO | ARM_CP_NO_RAW,
+  .access = PL2_RW,
+  .readfn = ich_lr_read,
+  .writefn = ich_lr_write,
+},
+REGINFO_SENTINEL
+};
+define_arm_cp_regs(cpu, lr_regset);
+}
+if (gcs->vprebits >= 

[PATCH RFC 08/22] arm/cpuhp: Enable ACPI support for vcpu hotplug

2020-06-13 Thread Salil Mehta
ACPI is required to interface QEMU with the guest. Roughly falls into below
cases,

1. Convey the possible vcpus config at the machine init time to the guest
   using various DSDT tables like MADT etc.
2. Convey vcpu hotplug events to guest(using GED)
3. Assist in evaluation of various ACPI methods(like _EVT, _STA, _OST, _EJ0,
   _MAT etc.)
4. Provides ACPI cpu hotplug state and 12 Byte memory mapped cpu hotplug
   control register interface to the OSPM/guest corresponding to each possible
   vcpu. The register interface consists of various R/W fields and their
   handling operations. These are called when ever register fields or memory
   regions are accessed(i.e. read or written) by OSPM when ever it evaluates
   various ACPI methods.

Note: lot of this framework code is inherited from the changes already done for
  x86 but still some minor changes are required to make it compatible with
  ARM64.)

This patch enables the ACPI support for virtual cpu hotplug in kconfig and
during initialization.

Co-developed-by: Keqian Zhu 
Signed-off-by: Salil Mehta 
---
 hw/acpi/cpu.c | 6 +-
 hw/arm/Kconfig| 1 +
 hw/arm/virt.c | 2 ++
 include/hw/acpi/cpu_hotplug.h | 2 ++
 include/hw/arm/virt.h | 1 +
 5 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
index 3d6a500fb7..21fe0463b9 100644
--- a/hw/acpi/cpu.c
+++ b/hw/acpi/cpu.c
@@ -218,7 +218,11 @@ void cpu_hotplug_hw_init(MemoryRegion *as, Object *owner,
 state->dev_count = id_list->len;
 state->devs = g_new0(typeof(*state->devs), state->dev_count);
 for (i = 0; i < id_list->len; i++) {
-state->devs[i].cpu =  CPU(id_list->cpus[i].cpu);
+struct CPUState *cpu = CPU(id_list->cpus[i].cpu);
+if (qemu_present_cpu(cpu))
+state->devs[i].cpu = cpu;
+else
+state->devs[i].cpu = NULL;
 state->devs[i].arch_id = id_list->cpus[i].arch_id;
 }
 memory_region_init_io(>ctrl_reg, owner, _hotplug_ops, state,
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 9afa6eee79..cb67fb806b 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -26,6 +26,7 @@ config ARM_VIRT
 select ACPI_MEMORY_HOTPLUG
 select ACPI_HW_REDUCED
 select ACPI_NVDIMM
+select ACPI_CPU_HOTPLUG
 
 config CHEETAH
 bool
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 7f938f289b..fe37babe35 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -75,6 +75,7 @@
 #include "hw/mem/pc-dimm.h"
 #include "hw/mem/nvdimm.h"
 #include "hw/acpi/generic_event_device.h"
+#include "hw/acpi/cpu_hotplug.h"
 #include "hw/virtio/virtio-iommu.h"
 #include "hw/char/pl011.h"
 #include "qemu/guest-random.h"
@@ -151,6 +152,7 @@ static const MemMapEntry base_memmap[] = {
 [VIRT_PCDIMM_ACPI] ={ 0x0907, MEMORY_HOTPLUG_IO_LEN },
 [VIRT_ACPI_GED] =   { 0x0908, ACPI_GED_EVT_SEL_LEN },
 [VIRT_NVDIMM_ACPI] ={ 0x0909, NVDIMM_ACPI_IO_LEN},
+[VIRT_CPUHP_ACPI] = { 0x090a, ACPI_CPU_HOTPLUG_REG_LEN},
 [VIRT_MMIO] =   { 0x0a00, 0x0200 },
 /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
 [VIRT_PLATFORM_BUS] =   { 0x0c00, 0x0200 },
diff --git a/include/hw/acpi/cpu_hotplug.h b/include/hw/acpi/cpu_hotplug.h
index 3b932a..48b291e45e 100644
--- a/include/hw/acpi/cpu_hotplug.h
+++ b/include/hw/acpi/cpu_hotplug.h
@@ -19,6 +19,8 @@
 #include "hw/hotplug.h"
 #include "hw/acpi/cpu.h"
 
+#define ACPI_CPU_HOTPLUG_REG_LEN 12
+
 typedef struct AcpiCpuHotplug {
 Object *device;
 MemoryRegion io;
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index 3ffbda6217..e0bd9df69d 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -80,6 +80,7 @@ enum {
 VIRT_PCDIMM_ACPI,
 VIRT_ACPI_GED,
 VIRT_NVDIMM_ACPI,
+VIRT_CPUHP_ACPI,
 VIRT_LOWMEMMAP_LAST,
 };
 
-- 
2.17.1





[PATCH RFC 10/22] arm/cpuhp: Update CPUs AML with cpu-(ctrl)dev change

2020-06-13 Thread Salil Mehta
CPUs Control device(\\_SB.PCI0) register interface for the x86 arch is based on
PCI and is IO port based and hence existing cpus AML code assumes _CRS objects
would evaluate to a system resource which describes IO Port address. But on ARM
arch CPUs control device(\\_SB.PRES) register interface is memory-mapped hence
_CRS object should evaluate to system resource which describes memory-mapped
base address.

This cpus AML code change updates the existing inerface of the build cpus AML
function to accept both IO/MEMORY type regions and update the _CRS object
correspondingly.

NOTE: Beside above CPU scan shall be triggered when OSPM evaluates _EVT method
  part of the GED framework which is covered in subsequent patch.

Co-developed-by: Keqian Zhu 
Signed-off-by: Salil Mehta 
---
 hw/acpi/cpu.c| 23 ---
 hw/arm/virt-acpi-build.c | 13 -
 hw/i386/acpi-build.c |  2 +-
 include/hw/acpi/cpu.h|  5 +++--
 4 files changed, 32 insertions(+), 11 deletions(-)

diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
index 21fe0463b9..867fdd6993 100644
--- a/hw/acpi/cpu.c
+++ b/hw/acpi/cpu.c
@@ -335,9 +335,10 @@ const VMStateDescription vmstate_cpu_hotplug = {
 #define CPU_EJECT_EVENT   "CEJ0"
 
 void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
-hwaddr io_base,
+hwaddr mmap_io_base,
 const char *res_root,
-const char *event_handler_method)
+const char *event_handler_method,
+AmlRegionSpace rs)
 {
 Aml *ifctx;
 Aml *field;
@@ -365,13 +366,19 @@ void build_cpus_aml(Aml *table, MachineState *machine, 
CPUHotplugFeatures opts,
 aml_append(cpu_ctrl_dev, aml_mutex(CPU_LOCK, 0));
 
 crs = aml_resource_template();
-aml_append(crs, aml_io(AML_DECODE16, io_base, io_base, 1,
+if (rs == AML_SYSTEM_IO) {
+aml_append(crs, aml_io(AML_DECODE16, mmap_io_base, mmap_io_base, 1,
ACPI_CPU_HOTPLUG_REG_LEN));
+} else {
+aml_append(crs, aml_memory32_fixed(mmap_io_base,
+   ACPI_CPU_HOTPLUG_REG_LEN, AML_READ_WRITE));
+}
+
 aml_append(cpu_ctrl_dev, aml_name_decl("_CRS", crs));
 
 /* declare CPU hotplug MMIO region with related access fields */
 aml_append(cpu_ctrl_dev,
-aml_operation_region("PRST", AML_SYSTEM_IO, aml_int(io_base),
+aml_operation_region("PRST", rs, aml_int(mmap_io_base),
  ACPI_CPU_HOTPLUG_REG_LEN));
 
 field = aml_field("PRST", AML_BYTE_ACC, AML_NOLOCK,
@@ -593,9 +600,11 @@ void build_cpus_aml(Aml *table, MachineState *machine, 
CPUHotplugFeatures opts,
 aml_append(sb_scope, cpus_dev);
 aml_append(table, sb_scope);
 
-method = aml_method(event_handler_method, 0, AML_NOTSERIALIZED);
-aml_append(method, aml_call0("\\_SB.CPUS." CPU_SCAN_METHOD));
-aml_append(table, method);
+if (event_handler_method) {
+method = aml_method(event_handler_method, 0, AML_NOTSERIALIZED);
+aml_append(method, aml_call0("\\_SB.CPUS." CPU_SCAN_METHOD));
+aml_append(table, method);
+}
 
 g_free(cphp_res_path);
 }
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index ca31f70f7f..d40540db61 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -731,7 +731,18 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, 
VirtMachineState *vms)
  * the RTC ACPI device at all when using UEFI.
  */
 scope = aml_scope("\\_SB");
-acpi_dsdt_add_cpus(scope, vms->smp_cpus);
+/* if GED is enabled then cpus AML shall be added as part build_cpus_aml */
+if (vms->acpi_dev) {
+CPUHotplugFeatures opts = {
+ .acpi_1_compatible = false,
+ .has_legacy_cphp = false
+};
+
+build_cpus_aml(scope, ms, opts, memmap[VIRT_CPUHP_ACPI].base,
+   "\\_SB", NULL, AML_SYSTEM_MEMORY);
+} else {
+acpi_dsdt_add_cpus(scope, vms->smp_cpus);
+}
 acpi_dsdt_add_uart(scope, [VIRT_UART],
(irqmap[VIRT_UART] + ARM_SPI_BASE));
 acpi_dsdt_add_flash(scope, [VIRT_FLASH]);
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 473cbdfffd..4b224d80a5 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1668,7 +1668,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 .acpi_1_compatible = true, .has_legacy_cphp = true
 };
 build_cpus_aml(dsdt, machine, opts, pm->cpu_hp_io_base,
-   "\\_SB.PCI0", "\\_GPE._E02");
+   "\\_SB.PCI0", "\\_GPE._E02", AML_SYSTEM_IO);
 }
 
 if (pcms->memhp_io_base && nr_mem) {
diff --git a/include/hw/acpi/cpu.h b/include/hw/acpi/cpu.h
index 62f0278ba2..c3a9981dc3 100644
--- a/include/hw/acpi/cpu.h
+++ b/include/hw/acpi/cpu.h
@@ -53,9 +53,10 @@ typedef 

[PATCH RFC 07/22] arm/cpuhp: Init PMU at host for all possible vcpus

2020-06-13 Thread Salil Mehta
PMU for all possible vcpus must be initialized at the virt machine
initialization time. This patch refactors existing code to accomodate possible
vcpus. This also assumes that all processor being used are identical at least
for now but does not affect the normal scanarios where they might not be in
future. This assumption only affects the future hotplug scenarios if ever there
exists any hetergenous processors. In such a case PMU might not be enabled on
some vcpus. Is it acceptable and doable tradeoff for now?

This perhaps needs more discussion. please check below link,
Link: https://lists.gnu.org/archive/html/qemu-devel/2020-06/msg00131.html

Co-developed-by: Keqian Zhu 
Signed-off-by: Salil Mehta 
---
 hw/arm/virt.c | 51 ++-
 include/hw/arm/virt.h |  1 +
 2 files changed, 37 insertions(+), 15 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 9e55b20685..7f938f289b 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -525,23 +525,9 @@ static void fdt_add_gic_node(VirtMachineState *vms)
 
 static void fdt_add_pmu_nodes(const VirtMachineState *vms)
 {
-CPUState *cpu;
 ARMCPU *armcpu;
 uint32_t irqflags = GIC_FDT_IRQ_FLAGS_LEVEL_HI;
 
-CPU_FOREACH(cpu) {
-armcpu = ARM_CPU(cpu);
-if (!arm_feature(>env, ARM_FEATURE_PMU)) {
-return;
-}
-if (kvm_enabled()) {
-if (kvm_irqchip_in_kernel()) {
-kvm_arm_pmu_set_irq(cpu, PPI(VIRTUAL_PMU_IRQ));
-}
-kvm_arm_pmu_init(cpu);
-}
-}
-
 if (vms->gic_version == VIRT_GIC_VERSION_2) {
 irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START,
  GIC_FDT_IRQ_PPI_CPU_WIDTH,
@@ -1414,6 +1400,38 @@ static void create_secure_ram(VirtMachineState *vms,
 g_free(nodename);
 }
 
+static bool virt_pmu_init(VirtMachineState *vms)
+{
+CPUArchIdList *possible_cpus = vms->parent.possible_cpus;
+ARMCPU *armcpu;
+int n;
+
+/*
+ * As of now KVM ensures that within the host all the vcpus have same
+ * features configured. This cannot be changed later and cannot be diferent
+ * for new vcpus being plugged in. Also, -cpu option/virt machine cpu-type
+ * ensures all the vcpus are identical.
+ */
+for (n = 0; n < possible_cpus->len; n++) {
+CPUState *cpu = qemu_get_possible_cpu(n);
+armcpu = ARM_CPU(cpu);
+
+if (!arm_feature(>env, ARM_FEATURE_PMU)) {
+warn_report("Not all vcpus might have PMU initialized");
+return false;
+}
+
+if (kvm_enabled()) {
+if (kvm_irqchip_in_kernel()) {
+kvm_arm_pmu_set_irq(cpu, PPI(VIRTUAL_PMU_IRQ));
+}
+kvm_arm_pmu_init(cpu);
+}
+}
+
+return true;
+}
+
 static void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size)
 {
 const VirtMachineState *board = container_of(binfo, VirtMachineState,
@@ -1909,7 +1927,10 @@ static void machvirt_init(MachineState *machine)
 
 create_gic(vms);
 
-fdt_add_pmu_nodes(vms);
+if (!vmc->no_pmu && virt_pmu_init(vms)) {
+vms->pmu = true;
+fdt_add_pmu_nodes(vms);
+}
 
 create_uart(vms, VIRT_UART, sysmem, serial_hd(0));
 
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index 38a9cad168..3ffbda6217 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -134,6 +134,7 @@ typedef struct {
 bool its;
 bool virt;
 bool ras;
+bool pmu;
 OnOffAuto acpi;
 VirtGICType gic_version;
 VirtIOMMUType iommu;
-- 
2.17.1





[PATCH RFC 12/22] arm/cpuhp: MADT Tbl change to size the guest with possible vcpus

2020-06-13 Thread Salil Mehta
Changes required during building of MADT Table by QEMU to accomodate disabled
possible vcpus. This info shall be used by the guest kernel to size up its
resources during boot time. This pre-sizing of the guest kernel done on
possible vcpus will facilitate hotplug of the disabled vcpus.

Co-developed-by: Keqian Zhu 
Signed-off-by: Salil Mehta 
---
 hw/arm/virt-acpi-build.c | 18 +++---
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index d40540db61..c654e2c9a3 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -603,6 +603,8 @@ build_madt(GArray *table_data, BIOSLinker *linker, 
VirtMachineState *vms)
 AcpiMultipleApicTable *madt;
 AcpiMadtGenericDistributor *gicd;
 AcpiMadtGenericMsiFrame *gic_msi;
+MachineState *ms = >parent;
+CPUArchIdList *possible_cpus = ms->possible_cpus;
 int i;
 
 madt = acpi_data_push(table_data, sizeof *madt);
@@ -613,11 +615,10 @@ build_madt(GArray *table_data, BIOSLinker *linker, 
VirtMachineState *vms)
 gicd->base_address = cpu_to_le64(memmap[VIRT_GIC_DIST].base);
 gicd->version = vms->gic_version;
 
-for (i = 0; i < vms->smp_cpus; i++) {
+for (i = 0; i < vms->max_cpus; i++) {
 AcpiMadtGenericCpuInterface *gicc = acpi_data_push(table_data,
sizeof(*gicc));
-ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i));
-
+ARMCPU *cpu = ARM_CPU(qemu_get_possible_cpu(i));
 gicc->type = ACPI_APIC_GENERIC_CPU_INTERFACE;
 gicc->length = sizeof(*gicc);
 if (vms->gic_version == 2) {
@@ -626,11 +627,14 @@ build_madt(GArray *table_data, BIOSLinker *linker, 
VirtMachineState *vms)
 gicc->gicv_base_address = cpu_to_le64(memmap[VIRT_GIC_VCPU].base);
 }
 gicc->cpu_interface_number = cpu_to_le32(i);
-gicc->arm_mpidr = cpu_to_le64(armcpu->mp_affinity);
+gicc->arm_mpidr = possible_cpus->cpus[i].arch_id;
 gicc->uid = cpu_to_le32(i);
-gicc->flags = cpu_to_le32(ACPI_MADT_GICC_ENABLED);
-
-if (arm_feature(>env, ARM_FEATURE_PMU)) {
+if ( i < vms->smp_cpus ) {
+gicc->flags = cpu_to_le32(ACPI_MADT_GICC_ENABLED);
+} else {
+gicc->flags = cpu_to_le32(0);
+}
+if ((cpu && arm_feature(>env, ARM_FEATURE_PMU)) || vms->pmu) {
 gicc->performance_interrupt = cpu_to_le32(PPI(VIRTUAL_PMU_IRQ));
 }
 if (vms->virt) {
-- 
2.17.1





[PATCH RFC 04/22] arm/cpuhp: Machine init time change common to vcpu {cold|hot}-plug

2020-06-13 Thread Salil Mehta
This refactors (+) introduces the common logic required during the
initialization of both cold and hot plugged vcpus. This also initializes the
*disabled* state of the vcpus which shall be used further during init phases
of various other components like GIC, PMU, ACPI etc as part of the virt machine
initialization.

Co-developed-by: Keqian Zhu 
Signed-off-by: Salil Mehta 
---
 hw/arm/virt.c | 250 +-
 include/hw/arm/virt.h |   2 +
 target/arm/cpu.c  |   7 ++
 target/arm/cpu64.c|   9 ++
 4 files changed, 214 insertions(+), 54 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index c4ed955776..184bed8716 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -203,6 +203,8 @@ static const char *valid_cpus[] = {
 ARM_CPU_TYPE_NAME("max"),
 };
 
+static CPUArchId *virt_find_cpu_slot(MachineState *ms, int vcpuid);
+
 static bool cpu_type_valid(const char *cpu)
 {
 int i;
@@ -1657,6 +1659,62 @@ static void finalize_gic_version(VirtMachineState *vms)
 }
 }
 
+static void virt_cpu_set_properties(Object *cpuobj, const CPUArchId *cpu_slot)
+{
+MachineState *ms = MACHINE(qdev_get_machine());
+MemoryRegion *sysmem = get_system_memory();
+VirtMachineState *vms = VIRT_MACHINE(ms);
+uint64_t mp_affinity = cpu_slot->arch_id;
+CPUState *cs = CPU(cpuobj);
+VirtMachineClass *vmc;
+
+vmc = VIRT_MACHINE_GET_CLASS(ms);
+
+/* now, set the cpu object property values */
+object_property_set_int(cpuobj, mp_affinity, "mp-affinity", NULL);
+
+numa_cpu_pre_plug(cpu_slot, DEVICE(cpuobj), _fatal);
+
+if (!vms->secure) {
+object_property_set_bool(cpuobj, false, "has_el3", NULL);
+}
+
+if (!vms->virt && object_property_find(cpuobj, "has_el2", NULL)) {
+object_property_set_bool(cpuobj, false, "has_el2", NULL);
+}
+
+if (vms->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED) {
+object_property_set_int(cpuobj, vms->psci_conduit, "psci-conduit",
+NULL);
+/* Secondary CPUs start in PSCI powered-down state */
+if (cs->cpu_index > 0)
+object_property_set_bool(cpuobj, true, "start-powered-off",
+ NULL);
+}
+
+if (vmc->kvm_no_adjvtime &&
+object_property_find(cpuobj, "kvm-no-adjvtime", NULL)) {
+object_property_set_bool(cpuobj, true, "kvm-no-adjvtime", NULL);
+}
+
+if (vmc->no_pmu && object_property_find(cpuobj, "pmu", NULL)) {
+object_property_set_bool(cpuobj, false, "pmu", NULL);
+}
+
+if (object_property_find(cpuobj, "reset-cbar", NULL)) {
+object_property_set_int(cpuobj, vms->memmap[VIRT_CPUPERIPHS].base,
+"reset-cbar", _abort);
+}
+
+object_property_set_link(cpuobj, OBJECT(sysmem), "memory",
+ _abort);
+
+if (vms->secure) {
+object_property_set_link(cpuobj, OBJECT(vms->secure_sysmem),
+ "secure-memory", _abort);
+}
+}
+
 static void machvirt_init(MachineState *machine)
 {
 VirtMachineState *vms = VIRT_MACHINE(machine);
@@ -1706,6 +1764,7 @@ static void machvirt_init(MachineState *machine)
 memory_region_init(secure_sysmem, OBJECT(machine), "secure-memory",
UINT64_MAX);
 memory_region_add_subregion_overlap(secure_sysmem, 0, sysmem, -1);
+vms->secure_sysmem = secure_sysmem;
 }
 
 firmware_loaded = virt_firmware_init(vms, sysmem,
@@ -1749,6 +1808,14 @@ static void machvirt_init(MachineState *machine)
 }
 
 vms->smp_cpus = smp_cpus;
+vms->max_cpus = max_cpus;
+if (vms->gic_version < VIRT_GIC_VERSION_3) {
+warn_report("For GICv%d max-cpus must be equal to smp-cpus",
+vms->gic_version);
+warn_report("Overriding specified max-cpus(%d) with smp-cpus(%d)",
+ max_cpus, smp_cpus);
+vms->max_cpus = smp_cpus;
+}
 
 if (vms->virt && kvm_enabled()) {
 error_report("mach-virt: KVM does not support providing "
@@ -1761,65 +1828,12 @@ static void machvirt_init(MachineState *machine)
 possible_cpus = mc->possible_cpu_arch_ids(machine);
 for (n = 0; n < possible_cpus->len; n++) {
 Object *cpuobj;
-CPUState *cs;
-
-if (n >= smp_cpus) {
-break;
-}
 
 cpuobj = object_new(possible_cpus->cpus[n].type);
-object_property_set_int(cpuobj, possible_cpus->cpus[n].arch_id,
-"mp-affinity", NULL);
-
-cs = CPU(cpuobj);
-cs->cpu_index = n;
-
-numa_cpu_pre_plug(_cpus->cpus[cs->cpu_index], DEVICE(cpuobj),
-  _fatal);
 
 aarch64 &= object_property_get_bool(cpuobj, "aarch64", NULL);
 object_property_set_int(cpuobj, n, "core-id", NULL);
 
-if (!vms->secure) {
-object_property_set_bool(cpuobj, false, "has_el3", NULL);
-}
-
-

[PATCH RFC 06/22] arm/cpuhp: Changes to pre-size GIC with possible vcpus @machine init

2020-06-13 Thread Salil Mehta
GIC needs to be pre-sized with possible vcpus at the initialization time. This
is necessary because Memory regions and resources associated with GICC/GICR
etc cannot be changed (add/del/modified) after VM has inited. Also, GIC_TYPER
needs to be initialized with mp_affinity and cpu interface number association.
This cannot be changed after GIC has initialized.

Once all the cpu interfaces of the GIC has been inited it needs to be ensured
that any updations to the GICC during reset only takes place for the present
vcpus and not the disabled ones. Therefore, proper checks are required at
various places.

Co-developed-by: Keqian Zhu 
Signed-off-by: Salil Mehta 
---
 hw/arm/virt.c  | 18 +-
 hw/intc/arm_gicv3_common.c |  8 ++--
 hw/intc/arm_gicv3_cpuif.c  |  6 ++
 hw/intc/arm_gicv3_kvm.c| 29 ++---
 include/hw/arm/virt.h  |  2 +-
 5 files changed, 48 insertions(+), 15 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 8040473d30..9e55b20685 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -628,19 +628,19 @@ static void create_v2m(VirtMachineState *vms)
 
 static void create_gic(VirtMachineState *vms)
 {
-MachineState *ms = MACHINE(vms);
 /* We create a standalone GIC */
 SysBusDevice *gicbusdev;
 const char *gictype;
 int type = vms->gic_version, i;
-unsigned int smp_cpus = ms->smp.cpus;
+unsigned int max_cpus = vms->max_cpus;
+unsigned int smp_cpus = vms->smp_cpus;
 uint32_t nb_redist_regions = 0;
 
 gictype = (type == 3) ? gicv3_class_name() : gic_class_name();
 
 vms->gic = qdev_create(NULL, gictype);
 qdev_prop_set_uint32(vms->gic, "revision", type);
-qdev_prop_set_uint32(vms->gic, "num-cpu", smp_cpus);
+qdev_prop_set_uint32(vms->gic, "num-cpu", max_cpus);
 /* Note that the num-irq property counts both internal and external
  * interrupts; there are always 32 of the former (mandated by GIC spec).
  */
@@ -652,7 +652,7 @@ static void create_gic(VirtMachineState *vms)
 if (type == 3) {
 uint32_t redist0_capacity =
 vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
-uint32_t redist0_count = MIN(smp_cpus, redist0_capacity);
+uint32_t redist0_count = MIN(max_cpus, redist0_capacity);
 
 nb_redist_regions = virt_gicv3_redist_region_count(vms);
 
@@ -665,7 +665,7 @@ static void create_gic(VirtMachineState *vms)
 vms->memmap[VIRT_HIGH_GIC_REDIST2].size / 
GICV3_REDIST_SIZE;
 
 qdev_prop_set_uint32(vms->gic, "redist-region-count[1]",
-MIN(smp_cpus - redist0_count, redist1_capacity));
+MIN(max_cpus - redist0_count, redist1_capacity));
 }
 } else {
 if (!kvm_irqchip_in_kernel()) {
@@ -722,7 +722,7 @@ static void create_gic(VirtMachineState *vms)
 } else if (vms->virt) {
 qemu_irq irq = qdev_get_gpio_in(vms->gic,
 ppibase + ARCH_GIC_MAINT_IRQ);
-sysbus_connect_irq(gicbusdev, i + 4 * smp_cpus, irq);
+sysbus_connect_irq(gicbusdev, i + 4 * max_cpus, irq);
 }
 
 qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
@@ -730,11 +730,11 @@ static void create_gic(VirtMachineState *vms)
  + VIRTUAL_PMU_IRQ));
 
 sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, 
ARM_CPU_IRQ));
-sysbus_connect_irq(gicbusdev, i + smp_cpus,
+sysbus_connect_irq(gicbusdev, i + max_cpus,
qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
-sysbus_connect_irq(gicbusdev, i + 2 * smp_cpus,
+sysbus_connect_irq(gicbusdev, i + 2 * max_cpus,
qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
-sysbus_connect_irq(gicbusdev, i + 3 * smp_cpus,
+sysbus_connect_irq(gicbusdev, i + 3 * max_cpus,
qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
 }
 
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
index 58ef65f589..bfa51a 100644
--- a/hw/intc/arm_gicv3_common.c
+++ b/hw/intc/arm_gicv3_common.c
@@ -348,11 +348,15 @@ static void arm_gicv3_common_realize(DeviceState *dev, 
Error **errp)
 s->cpu = g_new0(GICv3CPUState, s->num_cpu);
 
 for (i = 0; i < s->num_cpu; i++) {
-CPUState *cpu = qemu_get_cpu(i);
+CPUState *cpu = qemu_get_possible_cpu(i);
 uint64_t cpu_affid;
 int last;
 
-s->cpu[i].cpu = cpu;
+if (qemu_present_cpu(cpu))
+s->cpu[i].cpu = cpu;
+else
+s->cpu[i].cpu = NULL;
+
 s->cpu[i].gic = s;
 /* Store GICv3CPUState in CPUARMState gicv3state pointer */
 gicv3_set_gicv3state(cpu, >cpu[i]);
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
index 08e000e33c..90d8b0118e 100644
--- a/hw/intc/arm_gicv3_cpuif.c
+++ b/hw/intc/arm_gicv3_cpuif.c
@@ -779,6 +779,9 

[PATCH RFC 11/22] arm/cpuhp: Update GED _EVT method AML with cpu scan

2020-06-13 Thread Salil Mehta
OSPM evaluates _EVT method to map the event. The cpu hotplug event eventually
results in start of the cpu scan. Scan figures out the cpu and the kind of
event(plug/unplug) and notifies it back to the guest.

The change in this patch updates the GED AML _EVT method with the call to
\\_SB.CPUS.CSCN which will do above.

Co-developed-by: Keqian Zhu 
Signed-off-by: Salil Mehta 
---
 hw/acpi/generic_event_device.c | 4 
 include/hw/acpi/cpu_hotplug.h  | 3 +++
 2 files changed, 7 insertions(+)

diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
index 0f2c8a959e..79177deda2 100644
--- a/hw/acpi/generic_event_device.c
+++ b/hw/acpi/generic_event_device.c
@@ -108,6 +108,10 @@ void build_ged_aml(Aml *table, const char *name, 
HotplugHandler *hotplug_dev,
 aml_append(if_ctx, aml_call0(MEMORY_DEVICES_CONTAINER "."
  MEMORY_SLOT_SCAN_METHOD));
 break;
+case ACPI_GED_CPU_HOTPLUG_EVT:
+aml_append(if_ctx, aml_call0(ACPI_CPU_CONTAINER "."
+ ACPI_CPU_SCAN_METHOD));
+break;
 case ACPI_GED_PWR_DOWN_EVT:
 aml_append(if_ctx,
aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE),
diff --git a/include/hw/acpi/cpu_hotplug.h b/include/hw/acpi/cpu_hotplug.h
index 48b291e45e..f47fc8e79b 100644
--- a/include/hw/acpi/cpu_hotplug.h
+++ b/include/hw/acpi/cpu_hotplug.h
@@ -20,6 +20,9 @@
 #include "hw/acpi/cpu.h"
 
 #define ACPI_CPU_HOTPLUG_REG_LEN 12
+#define ACPI_CPU_SCAN_METHOD "CSCN"
+#define ACPI_CPU_CONTAINER "\\_SB.CPUS"
+
 
 typedef struct AcpiCpuHotplug {
 Object *device;
-- 
2.17.1





[PATCH RFC 01/22] arm/cpuhp: Add QMP vcpu params validation support

2020-06-13 Thread Salil Mehta
For now, vcpu hotplug is only supported with single socket single thread,
single die. NUMA is not supported either and everthing falls into single
node. Work to properly support these could be taken later once community
agrees with the base framework changes being presented to support ARM vcpu
hotplug in QEMU. Hence, these checks.

Co-developed-by: Keqian Zhu 
Signed-off-by: Salil Mehta 
---
 hw/arm/virt.c | 41 +
 1 file changed, 41 insertions(+)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 37462a6f78..5d1afdd031 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2201,6 +2201,46 @@ static HotplugHandler 
*virt_machine_get_hotplug_handler(MachineState *machine,
 return NULL;
 }
 
+static void virt_smp_parse(MachineState *ms, QemuOpts *opts)
+{
+if (opts) {
+unsigned cpus= qemu_opt_get_number(opts, "cpus", 1);
+unsigned sockets = qemu_opt_get_number(opts, "sockets", 1);
+unsigned cores   = qemu_opt_get_number(opts, "cores", cpus);
+unsigned threads = qemu_opt_get_number(opts, "threads", 1);
+unsigned int max_cpus;
+
+if (sockets > 1 || threads > 1) {
+error_report("does not support more than one socket or thread");
+exit(1);
+}
+
+if (cores != cpus) {
+error_report("cpu topology: "
+ "sockets (%u) * cores (%u) * threads (%u) < "
+ "smp_cpus (%u)",
+ sockets, cores, threads, cpus);
+exit(1);
+}
+
+max_cpus = qemu_opt_get_number(opts, "maxcpus", cpus);
+if (sockets * cores * threads > max_cpus) {
+error_report("cpu topology: "
+ "sockets (%u) * cores (%u) * threads (%u) > "
+ "maxcpus (%u)",
+ sockets, cores, threads,
+ max_cpus);
+exit(1);
+}
+
+ms->smp.max_cpus = max_cpus;
+ms->smp.sockets = sockets;
+ms->smp.cpus = cpus;
+ms->smp.cores = cores;
+ms->smp.threads = threads;
+}
+}
+
 /*
  * for arm64 kvm_type [7-0] encodes the requested number of bits
  * in the IPA address space
@@ -2266,6 +2306,7 @@ static void virt_machine_class_init(ObjectClass *oc, void 
*data)
 mc->nvdimm_supported = true;
 mc->auto_enable_numa_with_memhp = true;
 mc->default_ram_id = "mach-virt.ram";
+mc->smp_parse = virt_smp_parse;
 
 object_class_property_add(oc, "acpi", "OnOffAuto",
 virt_get_acpi, virt_set_acpi,
-- 
2.17.1





[PATCH RFC 05/22] arm/cpuhp: Pre-create disabled possible vcpus @machine init

2020-06-13 Thread Salil Mehta
In ARMv8 architecture, GIC needs all the vcpus to be created and present when
it is initialized. This is because:
1. GICC and MPIDR association must be fixed at the VM initialization time.
   This is represented by register GIC_TYPER(mp_afffinity, proc_num)
2. GICC(cpu interfaces), GICR(redistributors) etc all must be initialized
   at the boot time as well.
3. Memory regions associated with GICR etc. cannot be changed(add/del/mod)
   after VM has inited.

This patch adds the support to pre-create all such possible vcpus within the
host using the KVM interface as part of the virt machine initialization. These
vcpus could later be attached to QOM/ACPI while they are actually hot plugged
and made present.

NOTE: There is some refactoring related to the kvm_destroy_vcpu/kvm_get_vcpu
  (to make use of the common code) has been intentionaly left out in RFC
  version to avoid obscuring the framework change of the cpu hotplug. The
  existing code being presented in this patch could further be optimized
  later.

Co-developed-by: Keqian Zhu 
Signed-off-by: Salil Mehta 
---
 accel/kvm/kvm-all.c  | 31 +
 hw/arm/virt.c| 46 ++--
 include/sysemu/kvm.h |  2 ++
 target/arm/kvm.c | 32 ++
 target/arm/kvm_arm.h | 11 +++
 5 files changed, 120 insertions(+), 2 deletions(-)

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index d06cc04079..8e1c7b3d13 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -329,6 +329,37 @@ err:
 return ret;
 }
 
+void kvm_park_vcpu(CPUState *cs)
+{
+unsigned long vcpu_id = cs->cpu_index;
+struct KVMParkedVcpu *vcpu;
+
+vcpu = g_malloc0(sizeof(*vcpu));
+vcpu->vcpu_id = vcpu_id;
+vcpu->kvm_fd = cs->kvm_fd;
+QLIST_INSERT_HEAD(_state->kvm_parked_vcpus, vcpu, node);
+}
+
+int kvm_create_vcpu(CPUState *cpu)
+{
+unsigned long vcpu_id = cpu->cpu_index;
+KVMState *s = kvm_state;
+int ret = 0;
+
+DPRINTF("kvm_create_vcpu\n");
+
+ret = kvm_vm_ioctl(s, KVM_CREATE_VCPU, (void *)vcpu_id);
+if (ret < 0) {
+goto err;
+}
+cpu->kvm_fd = ret;
+cpu->kvm_state = s;
+cpu->vcpu_dirty = true;
+
+err:
+return ret;
+}
+
 int kvm_destroy_vcpu(CPUState *cpu)
 {
 KVMState *s = kvm_state;
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 184bed8716..8040473d30 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -1828,14 +1828,56 @@ static void machvirt_init(MachineState *machine)
 possible_cpus = mc->possible_cpu_arch_ids(machine);
 for (n = 0; n < possible_cpus->len; n++) {
 Object *cpuobj;
+CPUState *cs;
 
 cpuobj = object_new(possible_cpus->cpus[n].type);
+cs = CPU(cpuobj);
 
 aarch64 &= object_property_get_bool(cpuobj, "aarch64", NULL);
 object_property_set_int(cpuobj, n, "core-id", NULL);
 
-object_property_set_bool(cpuobj, true, "realized", _fatal);
-object_unref(cpuobj);
+if (n < vms->smp_cpus) {
+char *core_id = g_strdup_printf("core%d", n);
+qdev_set_id(DEVICE(cpuobj),core_id);
+object_property_set_bool(cpuobj, true, "realized", _fatal);
+g_free(core_id);
+object_unref(OBJECT(cs));
+} else {
+CPUArchId *cpu_slot;
+/* handling for vcpus which are yet to be hot-plugged */
+cs->cpu_index = n;
+/* ARM host vcpu features need to be fixed at the boot time */
+virt_cpu_set_properties(cpuobj, _cpus->cpus[n]);
+/*
+ * For KVM, we shall be pre-creating the now disabled/un-plugged
+ * possbile host vcpus and park them till the time they are
+ * actually hot plugged. This is required to pre-size the host
+ * GICC and GICR with the all possible vcpus for this VM.
+ */
+if (kvm_enabled()) {
+   kvm_arm_create_host_vcpu(ARM_CPU(cs));
+}
+/*
+ * Add disabled vcpu to cpu slot during the init phase of the virt 
machine.
+ * 1. We need this ARMCPU object during the GIC init. This object
+ *will facilitate in pre-realizing the gic. Any info like
+ *mp-affinity(required to derive gicr_type) etc could still be
+ *fetched while preserving QOM abstraction akin to realized
+ *vcpus.
+ * 2. Now, after initialization of the virt machine is complete we 
could use
+ *two approaches to deal with this ARMCPU object:
+ *(i) re-use this ARMCPU object during hotplug of this vcpu.
+ * OR
+ *(ii) defer release this ARMCPU object after gic has been
+ * initialized or during pre-plug phase when a vcpu is
+ * hotplugged.
+ *
+ *We will use the (ii) approach 

[PATCH RFC 03/22] arm/cpuhp: Add common cpu utility for possible vcpus

2020-06-13 Thread Salil Mehta
Adds various utility functions which might be required to fetch or check the
state of the possible vcpus. This also introduces concept of *disabled* vcpus,
which are part of the *possible* vcpus but are not part of the *present* vcpu.
This state shall be used during machine init time to check the presence of
vcpus.

Co-developed-by: Keqian Zhu 
Signed-off-by: Salil Mehta 
---
 cpus-common.c | 20 
 include/hw/core/cpu.h | 21 +
 2 files changed, 41 insertions(+)

diff --git a/cpus-common.c b/cpus-common.c
index 70a9d12981..7cf900289b 100644
--- a/cpus-common.c
+++ b/cpus-common.c
@@ -23,6 +23,7 @@
 #include "hw/core/cpu.h"
 #include "sysemu/cpus.h"
 #include "qemu/lockable.h"
+#include "hw/boards.h"
 
 static QemuMutex qemu_cpu_list_lock;
 static QemuCond exclusive_cond;
@@ -82,6 +83,25 @@ void cpu_list_add(CPUState *cpu)
 assert(!cpu_index_auto_assigned);
 }
 QTAILQ_INSERT_TAIL_RCU(, cpu, node);
+qemu_mutex_unlock(_cpu_list_lock);
+}
+
+CPUState *qemu_get_possible_cpu(int index)
+{
+MachineState *ms = MACHINE(qdev_get_machine());
+const CPUArchIdList *possible_cpus = ms->possible_cpus;
+CPUState *cpu;
+
+assert((index >= 0) && (index < possible_cpus->len));
+
+cpu = CPU(possible_cpus->cpus[index].cpu);
+
+return cpu;
+}
+
+bool qemu_present_cpu(CPUState *cpu)
+{
+return (cpu && !cpu->disabled);
 }
 
 void cpu_list_remove(CPUState *cpu)
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index 497600c49e..d9cae71ea5 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -419,6 +419,7 @@ struct CPUState {
 
 GArray *plugin_mem_cbs;
 
+bool disabled;
 /* TODO Move common fields from CPUArchState here. */
 int cpu_index;
 int cluster_index;
@@ -802,6 +803,26 @@ static inline bool cpu_in_exclusive_context(const CPUState 
*cpu)
  */
 CPUState *qemu_get_cpu(int index);
 
+/**
+ * qemu_get_possible_cpu:
+ * @index: The CPUState@cpu_index value of the CPU to obtain.
+ *
+ * Gets a CPU matching @index.
+ *
+ * Returns: The possible CPU or %NULL if there is no matching CPU.
+ */
+CPUState *qemu_get_possible_cpu(int index);
+
+/**
+ * qemu_present_cpu:
+ * @cpu: The vCPU to check
+ *
+ * Checks if the vcpu is amongst the present possible vcpus.
+ *
+ * Returns: True if it is present possible vcpu else false
+ */
+bool qemu_present_cpu(CPUState *cpu);
+
 /**
  * cpu_exists:
  * @id: Guest-exposed CPU ID to lookup.
-- 
2.17.1





[PATCH RFC 00/22] Support of Virtual CPU Hotplug for ARMv8 Arch

2020-06-13 Thread Salil Mehta
This patch-set introduces the virtual cpu hotplug support for ARMv8
architecture in QEMU. Idea is to be able to hotplug and hot-unplug the vcpus
while guest VM is running and no reboot is required. This does *not* makes any
assumption of the physical cpu hotplug availability within the host system but
rather tries to solve the problem at virtualizer/QEMU layer and by introducing
cpu hotplug hooks and event handling within the guest kernel. No changes are
required within the host kernel/KVM.

Motivation:
This allows scaling the guest VM compute capacity on-demand which would be
useful for the following example scenarios,
1. Vertical Pod Autoscaling[3][4] in the cloud: Part of the orchestration
   framework which could adjust resource requests (CPU and Mem requests) for
   the containers in a pod, based on usage.
2. Pay-as-you-grow Business Model: Infrastructure provider could allocate and
   restrict the total number of compute resources available to the guest VM
   according to the SLA(Service Level Agreement). VM owner could request for
   more compute to be hot-plugged for some cost.

Terminology:

(*) Present cpus: Total cpus with which guest has/will boot and are available
  to guest for use and can be onlined. Qemu parameter(-smp)
(*) Disabled cpus: Possible cpus which will not be available for the guest to
   use. These can be hotplugged and made present. These can be
   thought of as un-plugged vcpus. These will be included as
   part of sizing.
(*) Posssible cpus: Total vcpus which could ever exist in VM. This includes
booted cpus plus any cpus which could be later plugged.
- Qemu parameter(-maxcpus)
- Possible vcpus = Present vcpus (+) Disabled vcpus


Limitations of ARMv8 Architecture:

A. Physical Limitation to CPU Hotplug:
1. ARMv8 architecture does not support the concept of the physical cpu hotplug.
   The closest thing which is recomended to achieve the cpu hotplug on ARM is
   to bring down power state of the cpu using PSCI.
2. Other ARM components like GIC etc. have not been designed to realize
   physical cpu hotplug capability as of now. 

B. Limitations of GIC to Support Virtual CPU Hotplug:
1. GIC requires various resources(related to GICR/redistributor, GICC/cpu
   interface etc) like memory regions to be fixed at the VM init time and these
   could not be changed later on after VM has inited.
2. Associations between GICC(GIC cpu interface) and vcpu get fixed at the VM
   init time and GIC does not allows to change this association once GIC has
   initialized.

C. Known Limitation of the KVM:
1. As of now KVM allows to create VCPUs but does not allows to delete the
   already created vcpus. QEMU already provides an interface to manage created
   vcpus at KVM level and then to re-use them.
2. Inconsistency in interpretation of the MPIDR generated by KVM for vcpus
   vis-a-vis SMT/threads. This does not looks to be compliant to the MPIDR
   format(SMT is present) as mentioned in the ARMv8 spec. (Please correct my
   understanding if I am wrong here?)
   

Workaround to the problems mentioned in Section B & C1:
1. We pre-size the GIC with possible vcpus at VM init time
2. Pre-create all possible vcpus at KVM and associate them with GICC 
3. Park the unplugged vcpus (similar to x86)


(*) For all of above please refer to Marc's suggestion here[1]


Overview of the Approach:
At the time of machvirt_init() we pre-create all of the possible ARMCPU
objects along with the corresponding KVM vcpus at the host. Disabled KVM vcpu
(which are *not* "present" vcpus but are part of "possible" vcpu list) are
parked at per VM list "kvm_parked_vcpus" after their initialization.

We create the ARMCPU objects(but these are not *realized* in QOM sense) even
for the disabled vcpus to facilitate the GIC initialization (pre-sized with
possible vcpus). After Initialization of the machine is complete we release
the ARMCPU Objects for the disabled vcpus. These ARMCPU object shall be
re-created at the time when vcpu is hot plugged. This new object is then
re-attached with the earlier parked KVM vcpu which also gets unparked. The
ARMCPU object gets now "realized" in QEMU, which means creation of the
corresponding threads, pre_plug/plug phases, and event notification to the
guest using ACPI GED etc. Similarly, hot-unplug leg will lead to the
"unrealization" of the vcpus and will lead to similar ACPI GED events to the
guest for unplug and cleanup and eventually ARMCPU object shall be released and
KVM vcpus shall be parked again.

During machine init, ACPI MADT Table is sized with *possible* vcpus GICC
entries. The unplugged/disabled vcpus are presented as MADT GICC DISABLED
entries to the guest. This means the guest will have its resources pre-sized
with possible vcpus(=present+disabled)

Other approaches to deal with ARMCPU object release(after machine init):
1. The ARMCPU objects for the 

[PATCH RFC 09/22] arm/cpuhp: Init GED framework with cpu hotplug events

2020-06-13 Thread Salil Mehta
ACPI GED(as described in the ACPI 6.2 spec) can be used to generate ACPI events
when OSPM/guest receives an interrupt listed in the _CRS object of GED. OSPM
then maps or demultiplexes the event by evaluating _EVT method.

This change adds the support of cpu hotplug event initialization in the
existing GED framework.

Co-developed-by: Keqian Zhu 
Signed-off-by: Salil Mehta 
---
 hw/acpi/generic_event_device.c | 8 
 hw/arm/virt.c  | 3 ++-
 include/hw/acpi/generic_event_device.h | 5 +
 3 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
index 1cb34111e5..0f2c8a959e 100644
--- a/hw/acpi/generic_event_device.c
+++ b/hw/acpi/generic_event_device.c
@@ -25,6 +25,7 @@ static const uint32_t ged_supported_events[] = {
 ACPI_GED_MEM_HOTPLUG_EVT,
 ACPI_GED_PWR_DOWN_EVT,
 ACPI_GED_NVDIMM_HOTPLUG_EVT,
+ACPI_GED_CPU_HOTPLUG_EVT,
 };
 
 /*
@@ -305,6 +306,13 @@ static void acpi_ged_initfn(Object *obj)
  sysbus_init_mmio(sbd, >container_memhp);
  acpi_memory_hotplug_init(>container_memhp, OBJECT(dev),
   >memhp_state, 0);
+
+ s->cpuhp.device = OBJECT(s);
+ memory_region_init(>container_cpuhp, OBJECT(dev), "cpuhp container",
+ACPI_CPU_HOTPLUG_REG_LEN);
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), >container_cpuhp);
+ cpu_hotplug_hw_init(>container_cpuhp, OBJECT(dev),
+ >cpuhp_state, 0);
 }
 
 static void acpi_ged_class_init(ObjectClass *class, void *data)
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index fe37babe35..e9ead0e2dd 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -552,7 +552,7 @@ static inline DeviceState *create_acpi_ged(VirtMachineState 
*vms)
 DeviceState *dev;
 MachineState *ms = MACHINE(vms);
 int irq = vms->irqmap[VIRT_ACPI_GED];
-uint32_t event = ACPI_GED_PWR_DOWN_EVT;
+uint32_t event = ACPI_GED_PWR_DOWN_EVT | ACPI_GED_CPU_HOTPLUG_EVT;
 
 if (ms->ram_slots) {
 event |= ACPI_GED_MEM_HOTPLUG_EVT;
@@ -567,6 +567,7 @@ static inline DeviceState *create_acpi_ged(VirtMachineState 
*vms)
 
 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_ACPI_GED].base);
 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, 
vms->memmap[VIRT_PCDIMM_ACPI].base);
+sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, vms->memmap[VIRT_CPUHP_ACPI].base);
 sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(vms->gic, 
irq));
 
 qdev_init_nofail(dev);
diff --git a/include/hw/acpi/generic_event_device.h 
b/include/hw/acpi/generic_event_device.h
index 90a9180db5..b04037cf62 100644
--- a/include/hw/acpi/generic_event_device.h
+++ b/include/hw/acpi/generic_event_device.h
@@ -62,6 +62,7 @@
 #include "hw/sysbus.h"
 #include "hw/acpi/memory_hotplug.h"
 #include "hw/acpi/ghes.h"
+#include "hw/acpi/cpu_hotplug.h"
 
 #define ACPI_POWER_BUTTON_DEVICE "PWRB"
 
@@ -84,6 +85,7 @@
 #define ACPI_GED_MEM_HOTPLUG_EVT   0x1
 #define ACPI_GED_PWR_DOWN_EVT  0x2
 #define ACPI_GED_NVDIMM_HOTPLUG_EVT 0x4
+#define ACPI_GED_CPU_HOTPLUG_EVT0x8
 
 typedef struct GEDState {
 MemoryRegion evt;
@@ -94,6 +96,9 @@ typedef struct AcpiGedState {
 SysBusDevice parent_obj;
 MemHotplugState memhp_state;
 MemoryRegion container_memhp;
+CPUHotplugState cpuhp_state;
+MemoryRegion container_cpuhp;
+AcpiCpuHotplug cpuhp;
 GEDState ged_state;
 uint32_t ged_event_bitmap;
 qemu_irq irq;
-- 
2.17.1





[PATCH RFC 02/22] arm/cpuhp: Add new ARMCPU core-id property

2020-06-13 Thread Salil Mehta
This shall be used to store user specified core index and shall be directly
used as slot-index during hot{plug|unplug} of vcpu.

For now, we are not taking into account of other topology info like thread-id,
socket-id to derive mp-affinity. Host KVM uses vcpu-id to derive the mpidr for
the vcpu of the guest. This is not in exact corroboration with the ARM spec
view of the MPIDR. Hence, the concept of threads or SMT bit present as part of
the MPIDR_EL1 also gets lost.

Also, we need ACPI PPTT Table support in QEMU to be able to export this
topology info to the guest VM and the info should be consistent with what host
cpu supports if accel=kvm is being used.

Perhaps some comments on this will help? @Andrew/drjo...@redhat.com

Co-developed-by: Keqian Zhu 
Signed-off-by: Salil Mehta 
---
 hw/arm/virt.c| 5 +
 target/arm/cpu.c | 5 +
 target/arm/cpu.h | 1 +
 3 files changed, 11 insertions(+)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 5d1afdd031..c4ed955776 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -1778,6 +1778,7 @@ static void machvirt_init(MachineState *machine)
   _fatal);
 
 aarch64 &= object_property_get_bool(cpuobj, "aarch64", NULL);
+object_property_set_int(cpuobj, n, "core-id", NULL);
 
 if (!vms->secure) {
 object_property_set_bool(cpuobj, false, "has_el3", NULL);
@@ -2081,6 +2082,7 @@ static const CPUArchIdList 
*virt_possible_cpu_arch_ids(MachineState *ms)
 {
 int n;
 unsigned int max_cpus = ms->smp.max_cpus;
+unsigned int smp_threads = ms->smp.threads;
 VirtMachineState *vms = VIRT_MACHINE(ms);
 
 if (ms->possible_cpus) {
@@ -2093,8 +2095,11 @@ static const CPUArchIdList 
*virt_possible_cpu_arch_ids(MachineState *ms)
 ms->possible_cpus->len = max_cpus;
 for (n = 0; n < ms->possible_cpus->len; n++) {
 ms->possible_cpus->cpus[n].type = ms->cpu_type;
+ms->possible_cpus->cpus[n].vcpus_count = smp_threads;
 ms->possible_cpus->cpus[n].arch_id =
 virt_cpu_mp_affinity(vms, n);
+ms->possible_cpus->cpus[n].props.has_core_id = true;
+ms->possible_cpus->cpus[n].props.core_id = n;
 ms->possible_cpus->cpus[n].props.has_thread_id = true;
 ms->possible_cpus->cpus[n].props.thread_id = n;
 }
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 32bec156f2..33a58086a9 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1086,6 +1086,9 @@ static Property arm_cpu_has_dsp_property =
 static Property arm_cpu_has_mpu_property =
 DEFINE_PROP_BOOL("has-mpu", ARMCPU, has_mpu, true);
 
+static Property arm_cpu_coreid_property =
+DEFINE_PROP_INT32("core-id", ARMCPU, core_id, -1);
+
 /* This is like DEFINE_PROP_UINT32 but it doesn't set the default value,
  * because the CPU initfn will have already set cpu->pmsav7_dregion to
  * the right value for that particular CPU type, and we don't want
@@ -1168,6 +1171,8 @@ void arm_cpu_post_init(Object *obj)
 qdev_property_add_static(DEVICE(obj), _cpu_rvbar_property);
 }
 
+qdev_property_add_static(DEVICE(obj), _cpu_coreid_property);
+
 #ifndef CONFIG_USER_ONLY
 if (arm_feature(>env, ARM_FEATURE_EL3)) {
 /* Add the has_el3 state CPU property only if EL3 is allowed.  This 
will
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 677584e5da..5c4991156e 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -949,6 +949,7 @@ struct ARMCPU {
 QLIST_HEAD(, ARMELChangeHook) el_change_hooks;
 
 int32_t node_id; /* NUMA node this CPU belongs to */
+int32_t core_id; /* core-id of this ARM VCPU */
 
 /* Used to synchronize KVM and QEMU in-kernel device levels */
 uint8_t device_irq_level;
-- 
2.17.1





[PATCH] firmware: Fix a reference count leak.

2020-06-13 Thread wu000273
From: Qiushi Wu 

kobject_init_and_add() takes reference even when it fails.
If this function returns an error, kobject_put() must be called to
properly clean up the memory associated with the object.
Callback function fw_cfg_sysfs_release_entry() in kobject_put()
can handle the pointer "entry" properly.

Signed-off-by: Qiushi Wu 
---
 drivers/firmware/qemu_fw_cfg.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c
index 039e0f91dba8..6945c3c96637 100644
--- a/drivers/firmware/qemu_fw_cfg.c
+++ b/drivers/firmware/qemu_fw_cfg.c
@@ -605,8 +605,10 @@ static int fw_cfg_register_file(const struct fw_cfg_file 
*f)
/* register entry under "/sys/firmware/qemu_fw_cfg/by_key/" */
err = kobject_init_and_add(>kobj, _cfg_sysfs_entry_ktype,
   fw_cfg_sel_ko, "%d", entry->select);
-   if (err)
-   goto err_register;
+   if (err) {
+   kobject_put(>kobj);
+   return err;
+   }
 
/* add raw binary content access */
err = sysfs_create_bin_file(>kobj, _cfg_sysfs_attr_raw);
@@ -622,7 +624,6 @@ static int fw_cfg_register_file(const struct fw_cfg_file *f)
 
 err_add_raw:
kobject_del(>kobj);
-err_register:
kfree(entry);
return err;
 }
-- 
2.17.1




Re: [PATCH v25 QEMU 3/3] virtio-balloon: Replace free page hinting references to 'report' with 'hint'

2020-06-13 Thread Alexander Duyck
On Tue, May 26, 2020 at 9:14 PM Alexander Duyck
 wrote:
>
> From: Alexander Duyck 
>
> In an upcoming patch a feature named Free Page Reporting is about to be
> added. In order to avoid any confusion we should drop the use of the word
> 'report' when referring to Free Page Hinting. So what this patch does is go
> through and replace all instances of 'report' with 'hint" when we are
> referring to free page hinting.
>
> Acked-by: David Hildenbrand 
> Signed-off-by: Alexander Duyck 
> ---
>  hw/virtio/virtio-balloon.c |   78 
> ++--
>  include/hw/virtio/virtio-balloon.h |   20 +
>  2 files changed, 49 insertions(+), 49 deletions(-)
>
> diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
> index 3e2ac1104b5f..dc15409b0bb6 100644
> --- a/hw/virtio/virtio-balloon.c
> +++ b/hw/virtio/virtio-balloon.c

...

> @@ -817,14 +817,14 @@ static int virtio_balloon_post_load_device(void 
> *opaque, int version_id)
>  return 0;
>  }
>
> -static const VMStateDescription vmstate_virtio_balloon_free_page_report = {
> +static const VMStateDescription vmstate_virtio_balloon_free_page_hint = {
>  .name = "virtio-balloon-device/free-page-report",
>  .version_id = 1,
>  .minimum_version_id = 1,
>  .needed = virtio_balloon_free_page_support,
>  .fields = (VMStateField[]) {
> -VMSTATE_UINT32(free_page_report_cmd_id, VirtIOBalloon),
> -VMSTATE_UINT32(free_page_report_status, VirtIOBalloon),
> +VMSTATE_UINT32(free_page_hint_cmd_id, VirtIOBalloon),
> +VMSTATE_UINT32(free_page_hint_status, VirtIOBalloon),
>  VMSTATE_END_OF_LIST()
>  }
>  };

So I noticed this patch wasn't in the list of patches pulled, but that
is probably for the best since I believe the change above might have
broken migration as VMSTATE_UINT32 does a stringify on the first
parameter.
Any advice on how to address it, or should I just give up on renaming
free_page_report_cmd_id and free_page_report_status?

Looking at this I wonder why we even need to migrate these values? It
seems like if we are completing a migration the cmd_id should always
be "DONE" shouldn't it? It isn't as if we are going to migrate the
hinting from one host to another. We will have to start over which is
essentially the signal that the "DONE" value provides. Same thing for
the status. We shouldn't be able to migrate unless both of these are
already in the "DONE" state so if anything I wonder if we shouldn't
have that as the initial state for the device and just drop the
migration info.

Thanks.

- Alex



Re: [PATCH v2 0/5] Mac Old World ROM experiment

2020-06-13 Thread BALATON Zoltan

On Sat, 13 Jun 2020, BALATON Zoltan wrote:

On Sat, 13 Jun 2020, BALATON Zoltan wrote:

Version 2 with some more tweaks this now starts but drops in a Serial
Test Manager (see below) presumably because some POST step is failing,
I let others who know more about this machine figure out what's
missing from here.

Regards,
BALATON Zoltan


 1 :pci_update_mappings_add d=0x55a1bb6254a0 00:01.0 
0,0xf300+0x8

 1 pci_cfg_read grackle 00:0 @0x0 -> 0x21057
 1 pci_cfg_read grackle 00:0 @0xa8 -> 0x0
 1 pci_cfg_write grackle 00:0 @0xa8 <- 0x40e0c
 1 pci_cfg_read grackle 00:0 @0xac -> 0x0
 1 pci_cfg_write grackle 00:0 @0xac <- 0x1200
 1 pci_cfg_read grackle 00:0 @0xac -> 0x1200
 1 pci_cfg_write grackle 00:0 @0xac <- 0x200
 1 pci_cfg_read grackle 00:0 @0x70 -> 0x0
 1 pci_cfg_write grackle 00:0 @0x70 <- 0x1100
 1 machine_id_read(0, 2)
 1 pci_cfg_read grackle 00:0 @0x8 -> 0x6000140
 1 pci_cfg_read grackle 00:0 @0xf0 -> 0x0
 1 pci_cfg_write grackle 00:0 @0xf0 <- 0x1290
 1 machine_id_read(0, 2)
 1 portA_write unimplemented
 1 CUDA: unknown command 0x22
 1 CUDA: unknown command 0x26
 3 CUDA: unknown command 0x25
 1 pci_cfg_write grackle 00:0 @0x80 <- 0x
 1 pci_cfg_write grackle 00:0 @0x88 <- 0x
 1 pci_cfg_write grackle 00:0 @0x90 <- 0x
 1 pci_cfg_write grackle 00:0 @0x98 <- 0x
 1 pci_cfg_write grackle 00:0 @0x84 <- 0x
 1 pci_cfg_write grackle 00:0 @0x8c <- 0x
 1 pci_cfg_write grackle 00:0 @0x94 <- 0x
 1 pci_cfg_write grackle 00:0 @0x9c <- 0x
 1 pci_cfg_write grackle 00:0 @0xa0 <- 0x0
 1 pci_cfg_read grackle 00:0 @0xf0 -> 0x1290
 1 pci_cfg_write grackle 00:0 @0xf0 <- 0x1290
 1 machine_id_read(0, 2)
 1 pci_cfg_read grackle 00:0 @0x8 -> 0x6000140
 1 pci_cfg_read grackle 00:0 @0xf0 -> 0x1290
 1 pci_cfg_write grackle 00:0 @0xf0 <- 0x1294
 1 pci_cfg_write grackle 00:0 @0xf0 <- 0x1294
 1 pci_cfg_write grackle 00:0 @0xf4 <- 0x40010fe4
 1 pci_cfg_write grackle 00:0 @0xf8 <- 0x7302293
 1 pci_cfg_write grackle 00:0 @0xfc <- 0x25302220
 1 pci_cfg_read grackle 00:0 @0xa0 -> 0x0
 1 pci_cfg_write grackle 00:0 @0xa0 <- 0x6700
 1 pci_cfg_read grackle 00:0 @0xf0 -> 0x1294
 1 pci_cfg_write grackle 00:0 @0xf0 <- 0x129c
550755 Unassigned mem read f3014020


So this seems to be the missing sound device (maybe trying to play the 
startup chime). Adding some dummy implementation there gets me a little bit 
further:


 2 macio: screamer read 20  4
 1 macio: screamer write 10  4 = 60
 1 macio: screamer read 10  4
 2 macio: screamer read 20  4
 1 macio: screamer write 10  4 = 822
 1 macio: screamer read 10  4
 1 macio: screamer write 10  4 = 0
 1 macio: screamer read 10  4
 7 CUDA: unknown command 0x22
 2 macio: screamer read 20  4
 1 macio: screamer write 10  4 = 18
 1 macio: screamer read 10  4
 1 CUDA: unknown command 0x22
 1 macio: screamer read 0  4
 1 macio: screamer write 0  4 = 1105
 1 dbdma_unassigned_flush: use of unassigned channel 16
 1 dbdma_unassigned_rw: use of unassigned channel 16
 1 Unassigned mem write 00240020 = 0x10006238
 1 Unassigned mem write 00240024 = 0xffe32c00
 1 Unassigned mem write 00240028 = 0x0
 1 Unassigned mem write 0024002c = 0x84006238

then stops here, I guess it may be waiting for an interrupt so probably we


Or maybe it's the missing i2c bus in cuda (CUDA commands 0x22 and 0x25 
above) which I can imagine may try to get SPD data from RAM to configure 
memory.


Regards,
BALATON Zoltan




Re: [PATCH v2 5/5] mac_oldworld: Map macio to expected address at reset

2020-06-13 Thread BALATON Zoltan

On Sat, 13 Jun 2020, Philippe Mathieu-Daudé wrote:

On 6/13/20 3:36 PM, BALATON Zoltan wrote:

Add a reset function that maps macio to the address expected by the
firmware of the board at startup.

Signed-off-by: BALATON Zoltan 
---
 hw/ppc/mac.h  | 12 
 hw/ppc/mac_oldworld.c | 17 +++--
 2 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h
index 6af87d1fa0..35a5f21163 100644
--- a/hw/ppc/mac.h
+++ b/hw/ppc/mac.h
@@ -57,6 +57,18 @@
 #define OLDWORLD_IDE1_IRQ  0xe
 #define OLDWORLD_IDE1_DMA_IRQ  0x3

+/* g3beige machine */
+#define TYPE_HEATHROW_MACHINE MACHINE_TYPE_NAME("g3beige")
+#define HEATHROW_MACHINE(obj) OBJECT_CHECK(HeathrowMachineState, (obj), \
+   TYPE_HEATHROW_MACHINE)
+
+typedef struct HeathrowMachineState {
+/*< private >*/
+MachineState parent;
+
+PCIDevice *macio_pci;
+} HeathrowMachineState;
+
 /* New World IRQs */
 #define NEWWORLD_CUDA_IRQ  0x19
 #define NEWWORLD_PMU_IRQ   0x19
diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index 9138752ccb..fa9527410d 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -73,6 +73,15 @@ static uint64_t translate_kernel_address(void *opaque, 
uint64_t addr)
 return (addr & 0x0fff) + KERNEL_LOAD_ADDR;
 }

+static void ppc_heathrow_reset(MachineState *machine)
+{
+HeathrowMachineState *m = HEATHROW_MACHINE(machine);
+
+qemu_devices_reset();
+pci_default_write_config(m->macio_pci, PCI_COMMAND, PCI_COMMAND_MEMORY, 2);
+pci_default_write_config(m->macio_pci, PCI_BASE_ADDRESS_0, 0xf300, 4);


Hmm either this should be the default reset state of the device,
or we miss a 'BIOS' boot code that sets this state before you can
run your code.


"My code" here that I've tried _is_ the "BIOS" (actually openprom) 
firmware ROM from real machine which does not seem to do anything to get 
this mapped there so this seems to be there on reset but I don't know how 
that gets there on real hardware. This change makes the ROM happy and does 
not seem to break OpenBIOS either but if anyone knows a better way let 
us know.


Regards,
BALATON Zoltan

Re: [PATCH v2 5/5] mac_oldworld: Map macio to expected address at reset

2020-06-13 Thread Philippe Mathieu-Daudé
On 6/13/20 3:36 PM, BALATON Zoltan wrote:
> Add a reset function that maps macio to the address expected by the
> firmware of the board at startup.
> 
> Signed-off-by: BALATON Zoltan 
> ---
>  hw/ppc/mac.h  | 12 
>  hw/ppc/mac_oldworld.c | 17 +++--
>  2 files changed, 27 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h
> index 6af87d1fa0..35a5f21163 100644
> --- a/hw/ppc/mac.h
> +++ b/hw/ppc/mac.h
> @@ -57,6 +57,18 @@
>  #define OLDWORLD_IDE1_IRQ  0xe
>  #define OLDWORLD_IDE1_DMA_IRQ  0x3
>  
> +/* g3beige machine */
> +#define TYPE_HEATHROW_MACHINE MACHINE_TYPE_NAME("g3beige")
> +#define HEATHROW_MACHINE(obj) OBJECT_CHECK(HeathrowMachineState, (obj), \
> +   TYPE_HEATHROW_MACHINE)
> +
> +typedef struct HeathrowMachineState {
> +/*< private >*/
> +MachineState parent;
> +
> +PCIDevice *macio_pci;
> +} HeathrowMachineState;
> +
>  /* New World IRQs */
>  #define NEWWORLD_CUDA_IRQ  0x19
>  #define NEWWORLD_PMU_IRQ   0x19
> diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
> index 9138752ccb..fa9527410d 100644
> --- a/hw/ppc/mac_oldworld.c
> +++ b/hw/ppc/mac_oldworld.c
> @@ -73,6 +73,15 @@ static uint64_t translate_kernel_address(void *opaque, 
> uint64_t addr)
>  return (addr & 0x0fff) + KERNEL_LOAD_ADDR;
>  }
>  
> +static void ppc_heathrow_reset(MachineState *machine)
> +{
> +HeathrowMachineState *m = HEATHROW_MACHINE(machine);
> +
> +qemu_devices_reset();
> +pci_default_write_config(m->macio_pci, PCI_COMMAND, PCI_COMMAND_MEMORY, 
> 2);
> +pci_default_write_config(m->macio_pci, PCI_BASE_ADDRESS_0, 0xf300, 
> 4);

Hmm either this should be the default reset state of the device,
or we miss a 'BIOS' boot code that sets this state before you can
run your code.

> +}
> +
>  static void ppc_heathrow_cpu_reset(void *opaque)
>  {
>  PowerPCCPU *cpu = opaque;
> @@ -91,6 +100,7 @@ const MemoryRegionOps machine_id_reg_ops = {
>  
>  static void ppc_heathrow_init(MachineState *machine)
>  {
> +HeathrowMachineState *hm = HEATHROW_MACHINE(machine);
>  ram_addr_t ram_size = machine->ram_size;
>  const char *kernel_filename = machine->kernel_filename;
>  const char *kernel_cmdline = machine->kernel_cmdline;
> @@ -298,7 +308,8 @@ static void ppc_heathrow_init(MachineState *machine)
>  ide_drive_get(hd, ARRAY_SIZE(hd));
>  
>  /* MacIO */
> -macio = OLDWORLD_MACIO(pci_create(pci_bus, -1, TYPE_OLDWORLD_MACIO));
> +hm->macio_pci = pci_create(pci_bus, -1, TYPE_OLDWORLD_MACIO);
> +macio = OLDWORLD_MACIO(hm->macio_pci);
>  dev = DEVICE(macio);
>  qdev_prop_set_uint64(dev, "frequency", tbfreq);
>  object_property_set_link(OBJECT(macio), OBJECT(pic_dev), "pic",
> @@ -450,6 +461,7 @@ static void heathrow_class_init(ObjectClass *oc, void 
> *data)
>  
>  mc->desc = "Heathrow based PowerMAC";
>  mc->init = ppc_heathrow_init;
> +mc->reset = ppc_heathrow_reset;
>  mc->block_default_type = IF_IDE;
>  mc->max_cpus = MAX_CPUS;
>  #ifndef TARGET_PPC64
> @@ -466,9 +478,10 @@ static void heathrow_class_init(ObjectClass *oc, void 
> *data)
>  }
>  
>  static const TypeInfo ppc_heathrow_machine_info = {
> -.name  = MACHINE_TYPE_NAME("g3beige"),
> +.name  = TYPE_HEATHROW_MACHINE,
>  .parent= TYPE_MACHINE,
>  .class_init= heathrow_class_init,
> +.instance_size = sizeof(HeathrowMachineState),
>  .interfaces = (InterfaceInfo[]) {
>  { TYPE_FW_PATH_PROVIDER },
>  { }
> 




Re: [PATCH v2 4/5] mac_oldworld: Rename ppc_heathrow_reset reset to ppc_heathrow_cpu_reset

2020-06-13 Thread Philippe Mathieu-Daudé
On 6/13/20 3:36 PM, BALATON Zoltan wrote:
> This function resets a CPU not the whole machine so reflect that in
> its name.
> 
> Signed-off-by: BALATON Zoltan 

Reviewed-by: Philippe Mathieu-Daudé 

> ---
>  hw/ppc/mac_oldworld.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
> index 4dd872c1a3..9138752ccb 100644
> --- a/hw/ppc/mac_oldworld.c
> +++ b/hw/ppc/mac_oldworld.c
> @@ -73,7 +73,7 @@ static uint64_t translate_kernel_address(void *opaque, 
> uint64_t addr)
>  return (addr & 0x0fff) + KERNEL_LOAD_ADDR;
>  }
>  
> -static void ppc_heathrow_reset(void *opaque)
> +static void ppc_heathrow_cpu_reset(void *opaque)
>  {
>  PowerPCCPU *cpu = opaque;
>  
> @@ -127,7 +127,7 @@ static void ppc_heathrow_init(MachineState *machine)
>  
>  /* Set time-base frequency to 16.6 Mhz */
>  cpu_ppc_tb_init(env,  TBFREQ);
> -qemu_register_reset(ppc_heathrow_reset, cpu);
> +qemu_register_reset(ppc_heathrow_cpu_reset, cpu);
>  }
>  
>  /* allocate RAM */
> 




Re: [PATCH v2 0/5] Mac Old World ROM experiment

2020-06-13 Thread BALATON Zoltan

On Sat, 13 Jun 2020, BALATON Zoltan wrote:

Version 2 with some more tweaks this now starts but drops in a Serial
Test Manager (see below) presumably because some POST step is failing,
I let others who know more about this machine figure out what's
missing from here.

Regards,
BALATON Zoltan


 1 :pci_update_mappings_add d=0x55a1bb6254a0 00:01.0 0,0xf300+0x8
 1 pci_cfg_read grackle 00:0 @0x0 -> 0x21057
 1 pci_cfg_read grackle 00:0 @0xa8 -> 0x0
 1 pci_cfg_write grackle 00:0 @0xa8 <- 0x40e0c
 1 pci_cfg_read grackle 00:0 @0xac -> 0x0
 1 pci_cfg_write grackle 00:0 @0xac <- 0x1200
 1 pci_cfg_read grackle 00:0 @0xac -> 0x1200
 1 pci_cfg_write grackle 00:0 @0xac <- 0x200
 1 pci_cfg_read grackle 00:0 @0x70 -> 0x0
 1 pci_cfg_write grackle 00:0 @0x70 <- 0x1100
 1 machine_id_read(0, 2)
 1 pci_cfg_read grackle 00:0 @0x8 -> 0x6000140
 1 pci_cfg_read grackle 00:0 @0xf0 -> 0x0
 1 pci_cfg_write grackle 00:0 @0xf0 <- 0x1290
 1 machine_id_read(0, 2)
 1 portA_write unimplemented
 1 CUDA: unknown command 0x22
 1 CUDA: unknown command 0x26
 3 CUDA: unknown command 0x25
 1 pci_cfg_write grackle 00:0 @0x80 <- 0x
 1 pci_cfg_write grackle 00:0 @0x88 <- 0x
 1 pci_cfg_write grackle 00:0 @0x90 <- 0x
 1 pci_cfg_write grackle 00:0 @0x98 <- 0x
 1 pci_cfg_write grackle 00:0 @0x84 <- 0x
 1 pci_cfg_write grackle 00:0 @0x8c <- 0x
 1 pci_cfg_write grackle 00:0 @0x94 <- 0x
 1 pci_cfg_write grackle 00:0 @0x9c <- 0x
 1 pci_cfg_write grackle 00:0 @0xa0 <- 0x0
 1 pci_cfg_read grackle 00:0 @0xf0 -> 0x1290
 1 pci_cfg_write grackle 00:0 @0xf0 <- 0x1290
 1 machine_id_read(0, 2)
 1 pci_cfg_read grackle 00:0 @0x8 -> 0x6000140
 1 pci_cfg_read grackle 00:0 @0xf0 -> 0x1290
 1 pci_cfg_write grackle 00:0 @0xf0 <- 0x1294
 1 pci_cfg_write grackle 00:0 @0xf0 <- 0x1294
 1 pci_cfg_write grackle 00:0 @0xf4 <- 0x40010fe4
 1 pci_cfg_write grackle 00:0 @0xf8 <- 0x7302293
 1 pci_cfg_write grackle 00:0 @0xfc <- 0x25302220
 1 pci_cfg_read grackle 00:0 @0xa0 -> 0x0
 1 pci_cfg_write grackle 00:0 @0xa0 <- 0x6700
 1 pci_cfg_read grackle 00:0 @0xf0 -> 0x1294
 1 pci_cfg_write grackle 00:0 @0xf0 <- 0x129c
550755 Unassigned mem read f3014020


So this seems to be the missing sound device (maybe trying to play the 
startup chime). Adding some dummy implementation there gets me a little 
bit further:


  2 macio: screamer read 20  4
  1 macio: screamer write 10  4 = 60
  1 macio: screamer read 10  4
  2 macio: screamer read 20  4
  1 macio: screamer write 10  4 = 822
  1 macio: screamer read 10  4
  1 macio: screamer write 10  4 = 0
  1 macio: screamer read 10  4
  7 CUDA: unknown command 0x22
  2 macio: screamer read 20  4
  1 macio: screamer write 10  4 = 18
  1 macio: screamer read 10  4
  1 CUDA: unknown command 0x22
  1 macio: screamer read 0  4
  1 macio: screamer write 0  4 = 1105
  1 dbdma_unassigned_flush: use of unassigned channel 16
  1 dbdma_unassigned_rw: use of unassigned channel 16
  1 Unassigned mem write 00240020 = 0x10006238
  1 Unassigned mem write 00240024 = 0xffe32c00
  1 Unassigned mem write 00240028 = 0x0
  1 Unassigned mem write 0024002c = 0x84006238

then stops here, I guess it may be waiting for an interrupt so probably we 
need Mark's screamer implementation to move on. Mark, any chance you can 
look at this sometimes? Why is your email address stripped from emails 
coming from the list? Is that a list setting to exclude you from replies?


Regards,
BALATON Zoltan



[PATCH v3] mac_oldworld: Add machine ID register

2020-06-13 Thread BALATON Zoltan
The G3 beige machine has a machine ID register that is accessed by the
firmware to deternine the board config. Add basic emulation of it.

Signed-off-by: BALATON Zoltan 
---
v3: add empty write function in case anything tries to write reg

hw/ppc/mac_oldworld.c | 21 +
 1 file changed, 21 insertions(+)

diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index 3812adc441..acaf468458 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -80,6 +80,22 @@ static void ppc_heathrow_reset(void *opaque)
 cpu_reset(CPU(cpu));
 }

+static uint64_t machine_id_read(void *opaque, hwaddr addr, unsigned size)
+{
+return (addr == 0 && size == 2 ? 0x3d8c : 0);
+}
+
+static void machine_id_write(void *opaque, hwaddr addr,
+ uint64_t val, unsigned size)
+{
+return;
+}
+
+const MemoryRegionOps machine_id_reg_ops = {
+.read = machine_id_read,
+.write = machine_id_write,
+};
+
 static void ppc_heathrow_init(MachineState *machine)
 {
 ram_addr_t ram_size = machine->ram_size;
@@ -93,6 +109,7 @@ static void ppc_heathrow_init(MachineState *machine)
 char *filename;
 int linux_boot, i;
 MemoryRegion *bios = g_new(MemoryRegion, 1);
+MemoryRegion *machine_id = g_new(MemoryRegion, 1);
 uint32_t kernel_base, initrd_base, cmdline_base = 0;
 int32_t kernel_size, initrd_size;
 PCIBus *pci_bus;
@@ -227,6 +244,10 @@ static void ppc_heathrow_init(MachineState *machine)
 }
 }

+memory_region_init_io(machine_id, OBJECT(machine), _id_reg_ops,
+  NULL, "machine_id", 2);
+memory_region_add_subregion(get_system_memory(), 0xff04, machine_id);
+
 /* XXX: we register only 1 output pin for heathrow PIC */
 pic_dev = qdev_create(NULL, TYPE_HEATHROW);
 qdev_init_nofail(pic_dev);
-- 
2.21.3





[PATCH] block: file-posix: Fail unmap with NO_FALLBACK on block device

2020-06-13 Thread Nir Soffer
Punching holes on block device uses blkdev_issue_zeroout() with
BLKDEV_ZERO_NOFALLBACK but there is no guarantee that this is fast
enough for pre-zeroing an entire device.

Zeroing block device can be slow as writing zeroes or 100 times faster,
depending on the storage. There is no way to tell if zeroing it fast
enough.  The kernel BLKDEV_ZERO_NOFALLBACK flag does not mean that the
operation is fast; it just means that the kernel will not fall back to
manual zeroing.

Here is an example converting 10g image with 8g of data to block device:

$ ./qemu-img info test.img
image: test.img
file format: raw
virtual size: 10 GiB (10737418240 bytes)
disk size: 8 GiB

$ time ./qemu-img convert -f raw -O raw -t none -T none -W test.img 
/dev/test/lv1

Before:

real1m20.483s
user0m0.490s
sys 0m0.739s

After:

real0m55.831s
user0m0.610s
sys 0m0.956s

Signed-off-by: Nir Soffer 
---
 block/file-posix.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/block/file-posix.c b/block/file-posix.c
index 3ab8f5a0fa..cd2e409184 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -1621,6 +1621,16 @@ static int handle_aiocb_write_zeroes_unmap(void *opaque)
 /* First try to write zeros and unmap at the same time */
 
 #ifdef CONFIG_FALLOCATE_PUNCH_HOLE
+/*
+ * The block device fallocate() implementation in the kernel does set
+ * BLKDEV_ZERO_NOFALLBACK, but it does not guarantee that the operation is
+ * fast so we can't call this if we have to avoid slow fallbacks.
+ */
+if (aiocb->aio_type & QEMU_AIO_BLKDEV &&
+aiocb->aio_type & QEMU_AIO_NO_FALLBACK) {
+return -ENOTSUP;
+}
+
 int ret = do_fallocate(s->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
aiocb->aio_offset, aiocb->aio_nbytes);
 if (ret != -ENOTSUP) {
-- 
2.25.4




Re: [PATCH v2] Makefile: Remove generated files when doing 'distclean' (and 'clean')

2020-06-13 Thread Aleksandar Markovic
On Tue, Oct 8, 2019 at 2:41 PM Peter Maydell  wrote:
>
> On Tue, 8 Oct 2019 at 13:37, Thomas Huth  wrote:
> >
> > On 08/10/2019 14.18, Aleksandar Markovic wrote:
> > > If I remember well, QAPI-related c files are generated while doing
> > > 'make'. If that is true, these files should be deleted by 'make clean',
> > > shouldn't they?
> >
> > I think that's a philosophical question. Should "make clean" delete all
> > files that have been generated by a Makefile (i.e. not by "configure"),
> > or rather mainly the binary files?
>
> https://www.gnu.org/software/automake/manual/html_node/Clean.html
>
> The autoconf manual suggests some heuristics:
>  - If make built it, and it is commonly something that one would want
>to rebuild (for instance, a .o file), then mostlyclean should delete it.
>  - Otherwise, if make built it, then clean should delete it.
>  - If configure built it, then distclean should delete it.
>  - If the maintainer built it (for instance, a .info file), then
>maintainer-clean should delete it. However maintainer-clean should
>not delete anything that needs to exist in order to run
> './configure && make'.
>

Thomas, can we reincarnate this patch? It needs only fairly simple
corrections, as said by Peter above. It would be nice to have at least
one release of QEMU with clean clean and distclean.

Yours,
Aleksandar
> Not all of that applies for QEMU, but it seems like a reasonable
> set of ideas.
>
> thanks
> -- PMM



Re: [PULL v2 000/116] Huge miscellaneous pull request for 2020-06-11

2020-06-13 Thread Peter Maydell
On Fri, 12 Jun 2020 at 17:11, Paolo Bonzini  wrote:
>
> The following changes since commit 31d321c2b3574dcc74e9f6411af06bca6b5d10f4:
>
>   Merge remote-tracking branch 
> 'remotes/philmd-gitlab/tags/sparc-next-20200609' into staging (2020-06-09 
> 17:29:47 +0100)
>
> are available in the Git repository at:
>
>   git://github.com/bonzini/qemu.git tags/for-upstream
>
> for you to fetch changes up to 3575b0aea983ad57804c9af739ed8ff7bc168393:
>
>   target/i386: Remove obsolete TODO file (2020-06-12 11:20:15 -0400)
>
> 
> * Miscellaneous fixes and feature enablement (many)
> * SEV refactoring (David)
> * Hyper-V initial support (Jon)
> * i386 TCG fixes (x87 and SSE, Joseph)
> * vmport cleanup and improvements (Philippe, Liran)
> * Use-after-free with vCPU hot-unplug (Nengyuan)
> * run-coverity-scan improvements (myself)
> * Record/replay fixes (Pavel)
> * -machine kernel_irqchip=split improvements for INTx (Peter)
> * Code cleanups (Philippe)
> * Crash and security fixes (PJP)
> * HVF cleanups (Roman)

Applied, thanks. (I had to fix up a conflict in hw/i386/acpi-build.c;
might be worth checking that I got it right.)

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

-- PMM



[PATCH v8 14/14] target/mips: msa: Split helpers for MULV.

2020-06-13 Thread Aleksandar Markovic
Achieves clearer code and slightly better performance.

Signed-off-by: Aleksandar Markovic 
---
 target/mips/helper.h |  6 ++-
 target/mips/msa_helper.c | 79 
 target/mips/translate.c  | 15 +++-
 3 files changed, 91 insertions(+), 9 deletions(-)

diff --git a/target/mips/helper.h b/target/mips/helper.h
index 5d7ba6a847..e97655dc0e 100644
--- a/target/mips/helper.h
+++ b/target/mips/helper.h
@@ -960,6 +960,11 @@ DEF_HELPER_4(msa_msubv_h, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_msubv_w, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_msubv_d, void, env, i32, i32, i32)
 
+DEF_HELPER_4(msa_mulv_b, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_mulv_h, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_mulv_w, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_mulv_d, void, env, i32, i32, i32)
+
 DEF_HELPER_4(msa_asub_s_b, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_asub_s_h, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_asub_s_w, void, env, i32, i32, i32)
@@ -1098,7 +1103,6 @@ DEF_HELPER_5(msa_srlri_df, void, env, i32, i32, i32, i32)
 
 DEF_HELPER_5(msa_binsl_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_binsr_df, void, env, i32, i32, i32, i32)
-DEF_HELPER_5(msa_mulv_df, void, env, i32, i32, i32, i32)
 
 DEF_HELPER_4(msa_dotp_s_h, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_dotp_s_w, void, env, i32, i32, i32)
diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c
index d099e00b40..6865addaf6 100644
--- a/target/mips/msa_helper.c
+++ b/target/mips/msa_helper.c
@@ -3360,6 +3360,78 @@ void helper_msa_msubv_d(CPUMIPSState *env,
 }
 
 
+static inline int64_t msa_mulv_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+return arg1 * arg2;
+}
+
+void helper_msa_mulv_b(CPUMIPSState *env,
+   uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->b[0]  = msa_mulv_df(DF_BYTE, pws->b[0],  pwt->b[0]);
+pwd->b[1]  = msa_mulv_df(DF_BYTE, pws->b[1],  pwt->b[1]);
+pwd->b[2]  = msa_mulv_df(DF_BYTE, pws->b[2],  pwt->b[2]);
+pwd->b[3]  = msa_mulv_df(DF_BYTE, pws->b[3],  pwt->b[3]);
+pwd->b[4]  = msa_mulv_df(DF_BYTE, pws->b[4],  pwt->b[4]);
+pwd->b[5]  = msa_mulv_df(DF_BYTE, pws->b[5],  pwt->b[5]);
+pwd->b[6]  = msa_mulv_df(DF_BYTE, pws->b[6],  pwt->b[6]);
+pwd->b[7]  = msa_mulv_df(DF_BYTE, pws->b[7],  pwt->b[7]);
+pwd->b[8]  = msa_mulv_df(DF_BYTE, pws->b[8],  pwt->b[8]);
+pwd->b[9]  = msa_mulv_df(DF_BYTE, pws->b[9],  pwt->b[9]);
+pwd->b[10] = msa_mulv_df(DF_BYTE, pws->b[10], pwt->b[10]);
+pwd->b[11] = msa_mulv_df(DF_BYTE, pws->b[11], pwt->b[11]);
+pwd->b[12] = msa_mulv_df(DF_BYTE, pws->b[12], pwt->b[12]);
+pwd->b[13] = msa_mulv_df(DF_BYTE, pws->b[13], pwt->b[13]);
+pwd->b[14] = msa_mulv_df(DF_BYTE, pws->b[14], pwt->b[14]);
+pwd->b[15] = msa_mulv_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_mulv_h(CPUMIPSState *env,
+   uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->h[0]  = msa_mulv_df(DF_HALF, pws->h[0],  pwt->h[0]);
+pwd->h[1]  = msa_mulv_df(DF_HALF, pws->h[1],  pwt->h[1]);
+pwd->h[2]  = msa_mulv_df(DF_HALF, pws->h[2],  pwt->h[2]);
+pwd->h[3]  = msa_mulv_df(DF_HALF, pws->h[3],  pwt->h[3]);
+pwd->h[4]  = msa_mulv_df(DF_HALF, pws->h[4],  pwt->h[4]);
+pwd->h[5]  = msa_mulv_df(DF_HALF, pws->h[5],  pwt->h[5]);
+pwd->h[6]  = msa_mulv_df(DF_HALF, pws->h[6],  pwt->h[6]);
+pwd->h[7]  = msa_mulv_df(DF_HALF, pws->h[7],  pwt->h[7]);
+}
+
+void helper_msa_mulv_w(CPUMIPSState *env,
+   uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->w[0]  = msa_mulv_df(DF_WORD, pws->w[0],  pwt->w[0]);
+pwd->w[1]  = msa_mulv_df(DF_WORD, pws->w[1],  pwt->w[1]);
+pwd->w[2]  = msa_mulv_df(DF_WORD, pws->w[2],  pwt->w[2]);
+pwd->w[3]  = msa_mulv_df(DF_WORD, pws->w[3],  pwt->w[3]);
+}
+
+void helper_msa_mulv_d(CPUMIPSState *env,
+   uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->d[0]  = msa_mulv_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
+pwd->d[1]  = msa_mulv_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
+}
+
+
 /*
  * Int Subtract
  * 
@@ -5444,11 +5516,6 @@ MSA_TEROP_IMMU_DF(binsli, binsl)
 MSA_TEROP_IMMU_DF(binsri, binsr)
 #undef MSA_TEROP_IMMU_DF
 
-static inline int64_t msa_mulv_df(uint32_t df, int64_t arg1, int64_t arg2)
-{
-return arg1 * arg2;
-}
-
 #define CONCATENATE_AND_SLIDE(s, k) \
 do {

[PATCH v8 13/14] target/mips: msa: Split helpers for SUBV.

2020-06-13 Thread Aleksandar Markovic
Achieves clearer code and slightly better performance.

Signed-off-by: Aleksandar Markovic 
---
 target/mips/helper.h |  6 ++-
 target/mips/msa_helper.c | 81 +++-
 target/mips/translate.c  | 15 +++-
 3 files changed, 91 insertions(+), 11 deletions(-)

diff --git a/target/mips/helper.h b/target/mips/helper.h
index 4795c97f47..5d7ba6a847 100644
--- a/target/mips/helper.h
+++ b/target/mips/helper.h
@@ -998,6 +998,11 @@ DEF_HELPER_4(msa_subsuu_s_h, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_subsuu_s_w, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_subsuu_s_d, void, env, i32, i32, i32)
 
+DEF_HELPER_4(msa_subv_b, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_subv_h, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_subv_w, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_subv_d, void, env, i32, i32, i32)
+
 DEF_HELPER_4(msa_ilvev_b, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_ilvev_h, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_ilvev_w, void, env, i32, i32, i32)
@@ -1093,7 +1098,6 @@ DEF_HELPER_5(msa_srlri_df, void, env, i32, i32, i32, i32)
 
 DEF_HELPER_5(msa_binsl_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_binsr_df, void, env, i32, i32, i32, i32)
-DEF_HELPER_5(msa_subv_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_mulv_df, void, env, i32, i32, i32, i32)
 
 DEF_HELPER_4(msa_dotp_s_h, void, env, i32, i32, i32)
diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c
index 27a9c36a89..d099e00b40 100644
--- a/target/mips/msa_helper.c
+++ b/target/mips/msa_helper.c
@@ -3553,9 +3553,6 @@ void helper_msa_asub_u_d(CPUMIPSState *env,
 }
 
 
-/* TODO: insert the rest of Int Subtract group helpers here */
-
-
 static inline int64_t msa_hsub_s_df(uint32_t df, int64_t arg1, int64_t arg2)
 {
 return SIGNED_ODD(arg1, df) - SIGNED_EVEN(arg2, df);
@@ -3970,6 +3967,78 @@ void helper_msa_subsuu_s_d(CPUMIPSState *env,
 }
 
 
+static inline int64_t msa_subv_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+return arg1 - arg2;
+}
+
+void helper_msa_subv_b(CPUMIPSState *env,
+   uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->b[0]  = msa_subv_df(DF_BYTE, pws->b[0],  pwt->b[0]);
+pwd->b[1]  = msa_subv_df(DF_BYTE, pws->b[1],  pwt->b[1]);
+pwd->b[2]  = msa_subv_df(DF_BYTE, pws->b[2],  pwt->b[2]);
+pwd->b[3]  = msa_subv_df(DF_BYTE, pws->b[3],  pwt->b[3]);
+pwd->b[4]  = msa_subv_df(DF_BYTE, pws->b[4],  pwt->b[4]);
+pwd->b[5]  = msa_subv_df(DF_BYTE, pws->b[5],  pwt->b[5]);
+pwd->b[6]  = msa_subv_df(DF_BYTE, pws->b[6],  pwt->b[6]);
+pwd->b[7]  = msa_subv_df(DF_BYTE, pws->b[7],  pwt->b[7]);
+pwd->b[8]  = msa_subv_df(DF_BYTE, pws->b[8],  pwt->b[8]);
+pwd->b[9]  = msa_subv_df(DF_BYTE, pws->b[9],  pwt->b[9]);
+pwd->b[10] = msa_subv_df(DF_BYTE, pws->b[10], pwt->b[10]);
+pwd->b[11] = msa_subv_df(DF_BYTE, pws->b[11], pwt->b[11]);
+pwd->b[12] = msa_subv_df(DF_BYTE, pws->b[12], pwt->b[12]);
+pwd->b[13] = msa_subv_df(DF_BYTE, pws->b[13], pwt->b[13]);
+pwd->b[14] = msa_subv_df(DF_BYTE, pws->b[14], pwt->b[14]);
+pwd->b[15] = msa_subv_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_subv_h(CPUMIPSState *env,
+   uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->h[0]  = msa_subv_df(DF_HALF, pws->h[0],  pwt->h[0]);
+pwd->h[1]  = msa_subv_df(DF_HALF, pws->h[1],  pwt->h[1]);
+pwd->h[2]  = msa_subv_df(DF_HALF, pws->h[2],  pwt->h[2]);
+pwd->h[3]  = msa_subv_df(DF_HALF, pws->h[3],  pwt->h[3]);
+pwd->h[4]  = msa_subv_df(DF_HALF, pws->h[4],  pwt->h[4]);
+pwd->h[5]  = msa_subv_df(DF_HALF, pws->h[5],  pwt->h[5]);
+pwd->h[6]  = msa_subv_df(DF_HALF, pws->h[6],  pwt->h[6]);
+pwd->h[7]  = msa_subv_df(DF_HALF, pws->h[7],  pwt->h[7]);
+}
+
+void helper_msa_subv_w(CPUMIPSState *env,
+   uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->w[0]  = msa_subv_df(DF_WORD, pws->w[0],  pwt->w[0]);
+pwd->w[1]  = msa_subv_df(DF_WORD, pws->w[1],  pwt->w[1]);
+pwd->w[2]  = msa_subv_df(DF_WORD, pws->w[2],  pwt->w[2]);
+pwd->w[3]  = msa_subv_df(DF_WORD, pws->w[3],  pwt->w[3]);
+}
+
+void helper_msa_subv_d(CPUMIPSState *env,
+   uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->d[0]  = msa_subv_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
+pwd->d[1]  = msa_subv_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
+}
+
+
 /*
  * Interleave
  * --
@@ -5194,11 +5263,6 

[PATCH v8 09/14] target/mips: msa: Split helpers for SUBS_S.

2020-06-13 Thread Aleksandar Markovic
Achieves clearer code and slightly better performance.

Signed-off-by: Aleksandar Markovic 
---
 target/mips/helper.h |  6 ++-
 target/mips/msa_helper.c | 90 ++--
 target/mips/translate.c  | 15 ++-
 3 files changed, 97 insertions(+), 14 deletions(-)

diff --git a/target/mips/helper.h b/target/mips/helper.h
index 05d5533dfb..a93402a2d3 100644
--- a/target/mips/helper.h
+++ b/target/mips/helper.h
@@ -978,6 +978,11 @@ DEF_HELPER_4(msa_hsub_u_h, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_hsub_u_w, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_hsub_u_d, void, env, i32, i32, i32)
 
+DEF_HELPER_4(msa_subs_s_b, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_subs_s_h, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_subs_s_w, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_subs_s_d, void, env, i32, i32, i32)
+
 DEF_HELPER_4(msa_ilvev_b, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_ilvev_h, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_ilvev_w, void, env, i32, i32, i32)
@@ -1074,7 +1079,6 @@ DEF_HELPER_5(msa_srlri_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_binsl_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_binsr_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_subv_df, void, env, i32, i32, i32, i32)
-DEF_HELPER_5(msa_subs_s_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_subs_u_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_subsus_u_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_subsuu_s_df, void, env, i32, i32, i32, i32)
diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c
index 84d0073918..f08beba123 100644
--- a/target/mips/msa_helper.c
+++ b/target/mips/msa_helper.c
@@ -3650,6 +3650,84 @@ void helper_msa_hsub_u_d(CPUMIPSState *env,
 }
 
 
+static inline int64_t msa_subs_s_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+int64_t max_int = DF_MAX_INT(df);
+int64_t min_int = DF_MIN_INT(df);
+if (arg2 > 0) {
+return (min_int + arg2 < arg1) ? arg1 - arg2 : min_int;
+} else {
+return (arg1 < max_int + arg2) ? arg1 - arg2 : max_int;
+}
+}
+
+void helper_msa_subs_s_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->b[0]  = msa_subs_s_df(DF_BYTE, pws->b[0],  pwt->b[0]);
+pwd->b[1]  = msa_subs_s_df(DF_BYTE, pws->b[1],  pwt->b[1]);
+pwd->b[2]  = msa_subs_s_df(DF_BYTE, pws->b[2],  pwt->b[2]);
+pwd->b[3]  = msa_subs_s_df(DF_BYTE, pws->b[3],  pwt->b[3]);
+pwd->b[4]  = msa_subs_s_df(DF_BYTE, pws->b[4],  pwt->b[4]);
+pwd->b[5]  = msa_subs_s_df(DF_BYTE, pws->b[5],  pwt->b[5]);
+pwd->b[6]  = msa_subs_s_df(DF_BYTE, pws->b[6],  pwt->b[6]);
+pwd->b[7]  = msa_subs_s_df(DF_BYTE, pws->b[7],  pwt->b[7]);
+pwd->b[8]  = msa_subs_s_df(DF_BYTE, pws->b[8],  pwt->b[8]);
+pwd->b[9]  = msa_subs_s_df(DF_BYTE, pws->b[9],  pwt->b[9]);
+pwd->b[10] = msa_subs_s_df(DF_BYTE, pws->b[10], pwt->b[10]);
+pwd->b[11] = msa_subs_s_df(DF_BYTE, pws->b[11], pwt->b[11]);
+pwd->b[12] = msa_subs_s_df(DF_BYTE, pws->b[12], pwt->b[12]);
+pwd->b[13] = msa_subs_s_df(DF_BYTE, pws->b[13], pwt->b[13]);
+pwd->b[14] = msa_subs_s_df(DF_BYTE, pws->b[14], pwt->b[14]);
+pwd->b[15] = msa_subs_s_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_subs_s_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->h[0]  = msa_subs_s_df(DF_HALF, pws->h[0],  pwt->h[0]);
+pwd->h[1]  = msa_subs_s_df(DF_HALF, pws->h[1],  pwt->h[1]);
+pwd->h[2]  = msa_subs_s_df(DF_HALF, pws->h[2],  pwt->h[2]);
+pwd->h[3]  = msa_subs_s_df(DF_HALF, pws->h[3],  pwt->h[3]);
+pwd->h[4]  = msa_subs_s_df(DF_HALF, pws->h[4],  pwt->h[4]);
+pwd->h[5]  = msa_subs_s_df(DF_HALF, pws->h[5],  pwt->h[5]);
+pwd->h[6]  = msa_subs_s_df(DF_HALF, pws->h[6],  pwt->h[6]);
+pwd->h[7]  = msa_subs_s_df(DF_HALF, pws->h[7],  pwt->h[7]);
+}
+
+void helper_msa_subs_s_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->w[0]  = msa_subs_s_df(DF_WORD, pws->w[0],  pwt->w[0]);
+pwd->w[1]  = msa_subs_s_df(DF_WORD, pws->w[1],  pwt->w[1]);
+pwd->w[2]  = msa_subs_s_df(DF_WORD, pws->w[2],  pwt->w[2]);
+pwd->w[3]  = msa_subs_s_df(DF_WORD, pws->w[3],  pwt->w[3]);
+}
+
+void helper_msa_subs_s_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->d[0]  = msa_subs_s_df(DF_DOUBLE, 

[PATCH v8 11/14] target/mips: msa: Split helpers for SUBSUS_U.

2020-06-13 Thread Aleksandar Markovic
Achieves clearer code and slightly better performance.

Signed-off-by: Aleksandar Markovic 
---
 target/mips/helper.h |   6 ++-
 target/mips/msa_helper.c | 102 ---
 target/mips/translate.c  |  15 +-
 3 files changed, 103 insertions(+), 20 deletions(-)

diff --git a/target/mips/helper.h b/target/mips/helper.h
index 61dc1ed626..227ff76ec1 100644
--- a/target/mips/helper.h
+++ b/target/mips/helper.h
@@ -988,6 +988,11 @@ DEF_HELPER_4(msa_subs_u_h, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_subs_u_w, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_subs_u_d, void, env, i32, i32, i32)
 
+DEF_HELPER_4(msa_subsus_u_b, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_subsus_u_h, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_subsus_u_w, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_subsus_u_d, void, env, i32, i32, i32)
+
 DEF_HELPER_4(msa_ilvev_b, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_ilvev_h, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_ilvev_w, void, env, i32, i32, i32)
@@ -1084,7 +1089,6 @@ DEF_HELPER_5(msa_srlri_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_binsl_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_binsr_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_subv_df, void, env, i32, i32, i32, i32)
-DEF_HELPER_5(msa_subsus_u_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_subsuu_s_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_mulv_df, void, env, i32, i32, i32, i32)
 
diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c
index bce32abf77..f7e5c018ac 100644
--- a/target/mips/msa_helper.c
+++ b/target/mips/msa_helper.c
@@ -3802,6 +3802,90 @@ void helper_msa_subs_u_d(CPUMIPSState *env,
 }
 
 
+static inline int64_t msa_subsus_u_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+uint64_t u_arg1 = UNSIGNED(arg1, df);
+uint64_t max_uint = DF_MAX_UINT(df);
+if (arg2 >= 0) {
+uint64_t u_arg2 = (uint64_t)arg2;
+return (u_arg1 > u_arg2) ?
+(int64_t)(u_arg1 - u_arg2) :
+0;
+} else {
+uint64_t u_arg2 = (uint64_t)(-arg2);
+return (u_arg1 < max_uint - u_arg2) ?
+(int64_t)(u_arg1 + u_arg2) :
+(int64_t)max_uint;
+}
+}
+
+void helper_msa_subsus_u_b(CPUMIPSState *env,
+   uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->b[0]  = msa_subsus_u_df(DF_BYTE, pws->b[0],  pwt->b[0]);
+pwd->b[1]  = msa_subsus_u_df(DF_BYTE, pws->b[1],  pwt->b[1]);
+pwd->b[2]  = msa_subsus_u_df(DF_BYTE, pws->b[2],  pwt->b[2]);
+pwd->b[3]  = msa_subsus_u_df(DF_BYTE, pws->b[3],  pwt->b[3]);
+pwd->b[4]  = msa_subsus_u_df(DF_BYTE, pws->b[4],  pwt->b[4]);
+pwd->b[5]  = msa_subsus_u_df(DF_BYTE, pws->b[5],  pwt->b[5]);
+pwd->b[6]  = msa_subsus_u_df(DF_BYTE, pws->b[6],  pwt->b[6]);
+pwd->b[7]  = msa_subsus_u_df(DF_BYTE, pws->b[7],  pwt->b[7]);
+pwd->b[8]  = msa_subsus_u_df(DF_BYTE, pws->b[8],  pwt->b[8]);
+pwd->b[9]  = msa_subsus_u_df(DF_BYTE, pws->b[9],  pwt->b[9]);
+pwd->b[10] = msa_subsus_u_df(DF_BYTE, pws->b[10], pwt->b[10]);
+pwd->b[11] = msa_subsus_u_df(DF_BYTE, pws->b[11], pwt->b[11]);
+pwd->b[12] = msa_subsus_u_df(DF_BYTE, pws->b[12], pwt->b[12]);
+pwd->b[13] = msa_subsus_u_df(DF_BYTE, pws->b[13], pwt->b[13]);
+pwd->b[14] = msa_subsus_u_df(DF_BYTE, pws->b[14], pwt->b[14]);
+pwd->b[15] = msa_subsus_u_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_subsus_u_h(CPUMIPSState *env,
+   uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->h[0]  = msa_subsus_u_df(DF_HALF, pws->h[0],  pwt->h[0]);
+pwd->h[1]  = msa_subsus_u_df(DF_HALF, pws->h[1],  pwt->h[1]);
+pwd->h[2]  = msa_subsus_u_df(DF_HALF, pws->h[2],  pwt->h[2]);
+pwd->h[3]  = msa_subsus_u_df(DF_HALF, pws->h[3],  pwt->h[3]);
+pwd->h[4]  = msa_subsus_u_df(DF_HALF, pws->h[4],  pwt->h[4]);
+pwd->h[5]  = msa_subsus_u_df(DF_HALF, pws->h[5],  pwt->h[5]);
+pwd->h[6]  = msa_subsus_u_df(DF_HALF, pws->h[6],  pwt->h[6]);
+pwd->h[7]  = msa_subsus_u_df(DF_HALF, pws->h[7],  pwt->h[7]);
+}
+
+void helper_msa_subsus_u_w(CPUMIPSState *env,
+   uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->w[0]  = msa_subsus_u_df(DF_WORD, pws->w[0],  pwt->w[0]);
+pwd->w[1]  = msa_subsus_u_df(DF_WORD, pws->w[1],  pwt->w[1]);
+pwd->w[2]  = msa_subsus_u_df(DF_WORD, pws->w[2],  pwt->w[2]);
+pwd->w[3]  = msa_subsus_u_df(DF_WORD, pws->w[3],  pwt->w[3]);
+}
+
+void helper_msa_subsus_u_d(CPUMIPSState *env,
+   uint32_t wd, uint32_t ws, 

[PATCH v8 07/14] target/mips: msa: Split helpers for DOTP_S.

2020-06-13 Thread Aleksandar Markovic
Achieves clearer code and slightly better performance.

Signed-off-by: Aleksandar Markovic 
---
 target/mips/helper.h |  5 ++-
 target/mips/msa_helper.c | 66 
 target/mips/translate.c  | 12 +++-
 3 files changed, 69 insertions(+), 14 deletions(-)

diff --git a/target/mips/helper.h b/target/mips/helper.h
index 575f4a524c..06df3de744 100644
--- a/target/mips/helper.h
+++ b/target/mips/helper.h
@@ -1079,7 +1079,10 @@ DEF_HELPER_5(msa_subs_u_df, void, env, i32, i32, i32, 
i32)
 DEF_HELPER_5(msa_subsus_u_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_subsuu_s_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_mulv_df, void, env, i32, i32, i32, i32)
-DEF_HELPER_5(msa_dotp_s_df, void, env, i32, i32, i32, i32)
+
+DEF_HELPER_4(msa_dotp_s_h, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_dotp_s_w, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_dotp_s_d, void, env, i32, i32, i32)
 DEF_HELPER_5(msa_dotp_u_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_4(msa_dpadd_s_h, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_dpadd_s_w, void, env, i32, i32, i32)
diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c
index 33d5251a6b..201283fdd9 100644
--- a/target/mips/msa_helper.c
+++ b/target/mips/msa_helper.c
@@ -2236,6 +2236,60 @@ void helper_msa_div_u_d(CPUMIPSState *env,
 o = UNSIGNED_ODD(a, df);\
 } while (0)
 
+
+static inline int64_t msa_dotp_s_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+int64_t even_arg1;
+int64_t even_arg2;
+int64_t odd_arg1;
+int64_t odd_arg2;
+SIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df);
+SIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df);
+return (even_arg1 * even_arg2) + (odd_arg1 * odd_arg2);
+}
+
+void helper_msa_dotp_s_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->h[0]  = msa_dotp_s_df(DF_HALF, pws->h[0],  pwt->h[0]);
+pwd->h[1]  = msa_dotp_s_df(DF_HALF, pws->h[1],  pwt->h[1]);
+pwd->h[2]  = msa_dotp_s_df(DF_HALF, pws->h[2],  pwt->h[2]);
+pwd->h[3]  = msa_dotp_s_df(DF_HALF, pws->h[3],  pwt->h[3]);
+pwd->h[4]  = msa_dotp_s_df(DF_HALF, pws->h[4],  pwt->h[4]);
+pwd->h[5]  = msa_dotp_s_df(DF_HALF, pws->h[5],  pwt->h[5]);
+pwd->h[6]  = msa_dotp_s_df(DF_HALF, pws->h[6],  pwt->h[6]);
+pwd->h[7]  = msa_dotp_s_df(DF_HALF, pws->h[7],  pwt->h[7]);
+}
+
+void helper_msa_dotp_s_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->w[0]  = msa_dotp_s_df(DF_WORD, pws->w[0],  pwt->w[0]);
+pwd->w[1]  = msa_dotp_s_df(DF_WORD, pws->w[1],  pwt->w[1]);
+pwd->w[2]  = msa_dotp_s_df(DF_WORD, pws->w[2],  pwt->w[2]);
+pwd->w[3]  = msa_dotp_s_df(DF_WORD, pws->w[3],  pwt->w[3]);
+}
+
+void helper_msa_dotp_s_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->d[0]  = msa_dotp_s_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
+pwd->d[1]  = msa_dotp_s_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
+}
+
+
 static inline int64_t msa_dpadd_s_df(uint32_t df, int64_t dest, int64_t arg1,
  int64_t arg2)
 {
@@ -5010,17 +5064,6 @@ static inline int64_t msa_mulv_df(uint32_t df, int64_t 
arg1, int64_t arg2)
 return arg1 * arg2;
 }
 
-static inline int64_t msa_dotp_s_df(uint32_t df, int64_t arg1, int64_t arg2)
-{
-int64_t even_arg1;
-int64_t even_arg2;
-int64_t odd_arg1;
-int64_t odd_arg2;
-SIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df);
-SIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df);
-return (even_arg1 * even_arg2) + (odd_arg1 * odd_arg2);
-}
-
 static inline int64_t msa_dotp_u_df(uint32_t df, int64_t arg1, int64_t arg2)
 {
 int64_t even_arg1;
@@ -5155,7 +5198,6 @@ MSA_BINOP_DF(subs_u)
 MSA_BINOP_DF(subsus_u)
 MSA_BINOP_DF(subsuu_s)
 MSA_BINOP_DF(mulv)
-MSA_BINOP_DF(dotp_s)
 MSA_BINOP_DF(dotp_u)
 
 MSA_BINOP_DF(mul_q)
diff --git a/target/mips/translate.c b/target/mips/translate.c
index 3dda242643..f0bab46378 100644
--- a/target/mips/translate.c
+++ b/target/mips/translate.c
@@ -29393,7 +29393,17 @@ static void gen_msa_3r(CPUMIPSState *env, DisasContext 
*ctx)
 }
 break;
 case OPC_DOTP_S_df:
-gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
+switch (df) {
+case DF_HALF:
+gen_helper_msa_dotp_s_h(cpu_env, twd, tws, twt);
+break;
+case DF_WORD:
+gen_helper_msa_dotp_s_w(cpu_env, twd, tws, twt);
+break;
+case 

[PATCH v8 10/14] target/mips: msa: Split helpers for SUBS_U.

2020-06-13 Thread Aleksandar Markovic
Achieves clearer code and slightly better performance.

Signed-off-by: Aleksandar Markovic 
---
 target/mips/helper.h |  6 ++-
 target/mips/msa_helper.c | 82 
 target/mips/translate.c  | 15 +++-
 3 files changed, 93 insertions(+), 10 deletions(-)

diff --git a/target/mips/helper.h b/target/mips/helper.h
index a93402a2d3..61dc1ed626 100644
--- a/target/mips/helper.h
+++ b/target/mips/helper.h
@@ -983,6 +983,11 @@ DEF_HELPER_4(msa_subs_s_h, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_subs_s_w, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_subs_s_d, void, env, i32, i32, i32)
 
+DEF_HELPER_4(msa_subs_u_b, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_subs_u_h, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_subs_u_w, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_subs_u_d, void, env, i32, i32, i32)
+
 DEF_HELPER_4(msa_ilvev_b, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_ilvev_h, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_ilvev_w, void, env, i32, i32, i32)
@@ -1079,7 +1084,6 @@ DEF_HELPER_5(msa_srlri_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_binsl_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_binsr_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_subv_df, void, env, i32, i32, i32, i32)
-DEF_HELPER_5(msa_subs_u_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_subsus_u_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_subsuu_s_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_mulv_df, void, env, i32, i32, i32, i32)
diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c
index f08beba123..bce32abf77 100644
--- a/target/mips/msa_helper.c
+++ b/target/mips/msa_helper.c
@@ -3728,6 +3728,80 @@ void helper_msa_subs_s_d(CPUMIPSState *env,
 }
 
 
+static inline int64_t msa_subs_u_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+uint64_t u_arg1 = UNSIGNED(arg1, df);
+uint64_t u_arg2 = UNSIGNED(arg2, df);
+return (u_arg1 > u_arg2) ? u_arg1 - u_arg2 : 0;
+}
+
+void helper_msa_subs_u_b(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->b[0]  = msa_subs_u_df(DF_BYTE, pws->b[0],  pwt->b[0]);
+pwd->b[1]  = msa_subs_u_df(DF_BYTE, pws->b[1],  pwt->b[1]);
+pwd->b[2]  = msa_subs_u_df(DF_BYTE, pws->b[2],  pwt->b[2]);
+pwd->b[3]  = msa_subs_u_df(DF_BYTE, pws->b[3],  pwt->b[3]);
+pwd->b[4]  = msa_subs_u_df(DF_BYTE, pws->b[4],  pwt->b[4]);
+pwd->b[5]  = msa_subs_u_df(DF_BYTE, pws->b[5],  pwt->b[5]);
+pwd->b[6]  = msa_subs_u_df(DF_BYTE, pws->b[6],  pwt->b[6]);
+pwd->b[7]  = msa_subs_u_df(DF_BYTE, pws->b[7],  pwt->b[7]);
+pwd->b[8]  = msa_subs_u_df(DF_BYTE, pws->b[8],  pwt->b[8]);
+pwd->b[9]  = msa_subs_u_df(DF_BYTE, pws->b[9],  pwt->b[9]);
+pwd->b[10] = msa_subs_u_df(DF_BYTE, pws->b[10], pwt->b[10]);
+pwd->b[11] = msa_subs_u_df(DF_BYTE, pws->b[11], pwt->b[11]);
+pwd->b[12] = msa_subs_u_df(DF_BYTE, pws->b[12], pwt->b[12]);
+pwd->b[13] = msa_subs_u_df(DF_BYTE, pws->b[13], pwt->b[13]);
+pwd->b[14] = msa_subs_u_df(DF_BYTE, pws->b[14], pwt->b[14]);
+pwd->b[15] = msa_subs_u_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_subs_u_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->h[0]  = msa_subs_u_df(DF_HALF, pws->h[0],  pwt->h[0]);
+pwd->h[1]  = msa_subs_u_df(DF_HALF, pws->h[1],  pwt->h[1]);
+pwd->h[2]  = msa_subs_u_df(DF_HALF, pws->h[2],  pwt->h[2]);
+pwd->h[3]  = msa_subs_u_df(DF_HALF, pws->h[3],  pwt->h[3]);
+pwd->h[4]  = msa_subs_u_df(DF_HALF, pws->h[4],  pwt->h[4]);
+pwd->h[5]  = msa_subs_u_df(DF_HALF, pws->h[5],  pwt->h[5]);
+pwd->h[6]  = msa_subs_u_df(DF_HALF, pws->h[6],  pwt->h[6]);
+pwd->h[7]  = msa_subs_u_df(DF_HALF, pws->h[7],  pwt->h[7]);
+}
+
+void helper_msa_subs_u_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->w[0]  = msa_subs_u_df(DF_WORD, pws->w[0],  pwt->w[0]);
+pwd->w[1]  = msa_subs_u_df(DF_WORD, pws->w[1],  pwt->w[1]);
+pwd->w[2]  = msa_subs_u_df(DF_WORD, pws->w[2],  pwt->w[2]);
+pwd->w[3]  = msa_subs_u_df(DF_WORD, pws->w[3],  pwt->w[3]);
+}
+
+void helper_msa_subs_u_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->d[0]  = msa_subs_u_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
+pwd->d[1]  = msa_subs_u_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
+}
+
+
 /*
  * 

[PATCH v8 03/14] target/mips: msa: Split helpers for DPADD_S.

2020-06-13 Thread Aleksandar Markovic
Achieves clearer code and slightly better performance.

Signed-off-by: Aleksandar Markovic 
---
 target/mips/helper.h |  4 +-
 target/mips/msa_helper.c | 90 
 target/mips/translate.c  | 12 +-
 3 files changed, 78 insertions(+), 28 deletions(-)

diff --git a/target/mips/helper.h b/target/mips/helper.h
index 7ca0036807..16f2d53ad0 100644
--- a/target/mips/helper.h
+++ b/target/mips/helper.h
@@ -1081,7 +1081,9 @@ DEF_HELPER_5(msa_subsuu_s_df, void, env, i32, i32, i32, 
i32)
 DEF_HELPER_5(msa_mulv_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_dotp_s_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_dotp_u_df, void, env, i32, i32, i32, i32)
-DEF_HELPER_5(msa_dpadd_s_df, void, env, i32, i32, i32, i32)
+DEF_HELPER_4(msa_dpadd_s_h, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_dpadd_s_w, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_dpadd_s_d, void, env, i32, i32, i32)
 DEF_HELPER_5(msa_dpadd_u_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_dpsub_s_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_dpsub_u_df, void, env, i32, i32, i32, i32)
diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c
index 2b54de0959..086b56f58c 100644
--- a/target/mips/msa_helper.c
+++ b/target/mips/msa_helper.c
@@ -2224,7 +2224,70 @@ void helper_msa_div_u_d(CPUMIPSState *env,
  * +---+--+
  */
 
-/* TODO: insert Int Dot Product group helpers here */
+#define SIGNED_EXTRACT(e, o, a, df) \
+do {\
+e = SIGNED_EVEN(a, df); \
+o = SIGNED_ODD(a, df);  \
+} while (0)
+
+#define UNSIGNED_EXTRACT(e, o, a, df)   \
+do {\
+e = UNSIGNED_EVEN(a, df);   \
+o = UNSIGNED_ODD(a, df);\
+} while (0)
+
+static inline int64_t msa_dpadd_s_df(uint32_t df, int64_t dest, int64_t arg1,
+ int64_t arg2)
+{
+int64_t even_arg1;
+int64_t even_arg2;
+int64_t odd_arg1;
+int64_t odd_arg2;
+SIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df);
+SIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df);
+return dest + (even_arg1 * even_arg2) + (odd_arg1 * odd_arg2);
+}
+
+void helper_msa_dpadd_s_h(CPUMIPSState *env,
+  uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->h[0]  = msa_dpadd_s_df(DF_HALF, pwd->h[0],  pws->h[0],  pwt->h[0]);
+pwd->h[1]  = msa_dpadd_s_df(DF_HALF, pwd->h[1],  pws->h[1],  pwt->h[1]);
+pwd->h[2]  = msa_dpadd_s_df(DF_HALF, pwd->h[2],  pws->h[2],  pwt->h[2]);
+pwd->h[3]  = msa_dpadd_s_df(DF_HALF, pwd->h[3],  pws->h[3],  pwt->h[3]);
+pwd->h[4]  = msa_dpadd_s_df(DF_HALF, pwd->h[4],  pws->h[4],  pwt->h[4]);
+pwd->h[5]  = msa_dpadd_s_df(DF_HALF, pwd->h[5],  pws->h[5],  pwt->h[5]);
+pwd->h[6]  = msa_dpadd_s_df(DF_HALF, pwd->h[6],  pws->h[6],  pwt->h[6]);
+pwd->h[7]  = msa_dpadd_s_df(DF_HALF, pwd->h[7],  pws->h[7],  pwt->h[7]);
+}
+
+void helper_msa_dpadd_s_w(CPUMIPSState *env,
+  uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->w[0]  = msa_dpadd_s_df(DF_WORD, pwd->w[0],  pws->w[0],  pwt->w[0]);
+pwd->w[1]  = msa_dpadd_s_df(DF_WORD, pwd->w[1],  pws->w[1],  pwt->w[1]);
+pwd->w[2]  = msa_dpadd_s_df(DF_WORD, pwd->w[2],  pws->w[2],  pwt->w[2]);
+pwd->w[3]  = msa_dpadd_s_df(DF_WORD, pwd->w[3],  pws->w[3],  pwt->w[3]);
+}
+
+void helper_msa_dpadd_s_d(CPUMIPSState *env,
+  uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->d[0]  = msa_dpadd_s_df(DF_DOUBLE, pwd->d[0],  pws->d[0],  pwt->d[0]);
+pwd->d[1]  = msa_dpadd_s_df(DF_DOUBLE, pwd->d[1],  pws->d[1],  pwt->d[1]);
+}
 
 
 /*
@@ -4785,18 +4848,6 @@ static inline int64_t msa_mulv_df(uint32_t df, int64_t 
arg1, int64_t arg2)
 return arg1 * arg2;
 }
 
-#define SIGNED_EXTRACT(e, o, a, df) \
-do {\
-e = SIGNED_EVEN(a, df); \
-o = SIGNED_ODD(a, df);  \
-} while (0)
-
-#define UNSIGNED_EXTRACT(e, o, a, df)   \
-do {\
-e = UNSIGNED_EVEN(a, df);   \
-o = UNSIGNED_ODD(a, df);\
-} while (0)
-
 static inline int64_t msa_dotp_s_df(uint32_t df, int64_t arg1, int64_t arg2)
 {
 int64_t even_arg1;
@@ -4958,18 +5009,6 @@ void helper_msa_sld_df(CPUMIPSState *env, uint32_t df, 
uint32_t wd,
 msa_sld_df(df, pwd, pws, env->active_tc.gpr[rt]);
 }
 
-static inline int64_t msa_dpadd_s_df(uint32_t df, int64_t 

[PATCH v8 06/14] target/mips: msa: Split helpers for DPSUB_U.

2020-06-13 Thread Aleksandar Markovic
Achieves clearer code and slightly better performance.

Signed-off-by: Aleksandar Markovic 
---
 target/mips/helper.h |  4 ++-
 target/mips/msa_helper.c | 67 
 target/mips/translate.c  | 12 ++-
 3 files changed, 68 insertions(+), 15 deletions(-)

diff --git a/target/mips/helper.h b/target/mips/helper.h
index 2de14542cd..575f4a524c 100644
--- a/target/mips/helper.h
+++ b/target/mips/helper.h
@@ -1090,7 +1090,9 @@ DEF_HELPER_4(msa_dpadd_u_d, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_dpsub_s_h, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_dpsub_s_w, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_dpsub_s_d, void, env, i32, i32, i32)
-DEF_HELPER_5(msa_dpsub_u_df, void, env, i32, i32, i32, i32)
+DEF_HELPER_4(msa_dpsub_u_h, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_dpsub_u_w, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_dpsub_u_d, void, env, i32, i32, i32)
 DEF_HELPER_5(msa_sld_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_splat_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_vshf_df, void, env, i32, i32, i32, i32)
diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c
index 934f705c1e..33d5251a6b 100644
--- a/target/mips/msa_helper.c
+++ b/target/mips/msa_helper.c
@@ -2398,6 +2398,60 @@ void helper_msa_dpsub_s_d(CPUMIPSState *env,
 }
 
 
+static inline int64_t msa_dpsub_u_df(uint32_t df, int64_t dest, int64_t arg1,
+ int64_t arg2)
+{
+int64_t even_arg1;
+int64_t even_arg2;
+int64_t odd_arg1;
+int64_t odd_arg2;
+UNSIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df);
+UNSIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df);
+return dest - ((even_arg1 * even_arg2) + (odd_arg1 * odd_arg2));
+}
+
+void helper_msa_dpsub_u_h(CPUMIPSState *env,
+  uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->h[0]  = msa_dpsub_u_df(DF_HALF, pwd->h[0],  pws->h[0],  pwt->h[0]);
+pwd->h[1]  = msa_dpsub_u_df(DF_HALF, pwd->h[1],  pws->h[1],  pwt->h[1]);
+pwd->h[2]  = msa_dpsub_u_df(DF_HALF, pwd->h[2],  pws->h[2],  pwt->h[2]);
+pwd->h[3]  = msa_dpsub_u_df(DF_HALF, pwd->h[3],  pws->h[3],  pwt->h[3]);
+pwd->h[4]  = msa_dpsub_u_df(DF_HALF, pwd->h[4],  pws->h[4],  pwt->h[4]);
+pwd->h[5]  = msa_dpsub_u_df(DF_HALF, pwd->h[5],  pws->h[5],  pwt->h[5]);
+pwd->h[6]  = msa_dpsub_u_df(DF_HALF, pwd->h[6],  pws->h[6],  pwt->h[6]);
+pwd->h[7]  = msa_dpsub_u_df(DF_HALF, pwd->h[7],  pws->h[7],  pwt->h[7]);
+}
+
+void helper_msa_dpsub_u_w(CPUMIPSState *env,
+  uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->w[0]  = msa_dpsub_u_df(DF_WORD, pwd->w[0],  pws->w[0],  pwt->w[0]);
+pwd->w[1]  = msa_dpsub_u_df(DF_WORD, pwd->w[1],  pws->w[1],  pwt->w[1]);
+pwd->w[2]  = msa_dpsub_u_df(DF_WORD, pwd->w[2],  pws->w[2],  pwt->w[2]);
+pwd->w[3]  = msa_dpsub_u_df(DF_WORD, pwd->w[3],  pws->w[3],  pwt->w[3]);
+}
+
+void helper_msa_dpsub_u_d(CPUMIPSState *env,
+  uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->d[0]  = msa_dpsub_u_df(DF_DOUBLE, pwd->d[0],  pws->d[0],  pwt->d[0]);
+pwd->d[1]  = msa_dpsub_u_df(DF_DOUBLE, pwd->d[1],  pws->d[1],  pwt->d[1]);
+}
+
+
 /*
  * Int Max Min
  * ---
@@ -5117,18 +5171,6 @@ void helper_msa_sld_df(CPUMIPSState *env, uint32_t df, 
uint32_t wd,
 msa_sld_df(df, pwd, pws, env->active_tc.gpr[rt]);
 }
 
-static inline int64_t msa_dpsub_u_df(uint32_t df, int64_t dest, int64_t arg1,
- int64_t arg2)
-{
-int64_t even_arg1;
-int64_t even_arg2;
-int64_t odd_arg1;
-int64_t odd_arg2;
-UNSIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df);
-UNSIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df);
-return dest - ((even_arg1 * even_arg2) + (odd_arg1 * odd_arg2));
-}
-
 static inline int64_t msa_madd_q_df(uint32_t df, int64_t dest, int64_t arg1,
 int64_t arg2)
 {
@@ -5255,7 +5297,6 @@ void helper_msa_ ## func ## _df(CPUMIPSState *env, 
uint32_t df, uint32_t wd,  \
 } \
 }
 
-MSA_TEROP_DF(dpsub_u)
 MSA_TEROP_DF(binsl)
 MSA_TEROP_DF(binsr)
 MSA_TEROP_DF(madd_q)
diff --git a/target/mips/translate.c b/target/mips/translate.c
index 2576905e5b..3dda242643 100644
--- a/target/mips/translate.c
+++ b/target/mips/translate.c
@@ -29438,7 +29438,17 @@ static void gen_msa_3r(CPUMIPSState *env, DisasContext 
*ctx)
 }
 break;
 case OPC_DPSUB_U_df:
-gen_helper_msa_dpsub_u_df(cpu_env, tdf, 

[PATCH v8 12/14] target/mips: msa: Split helpers for SUBSUU_S.

2020-06-13 Thread Aleksandar Markovic
Achieves clearer code and slightly better performance.

Signed-off-by: Aleksandar Markovic 
---
 target/mips/helper.h |   6 ++-
 target/mips/msa_helper.c | 102 ---
 target/mips/translate.c  |  15 +-
 3 files changed, 103 insertions(+), 20 deletions(-)

diff --git a/target/mips/helper.h b/target/mips/helper.h
index 227ff76ec1..4795c97f47 100644
--- a/target/mips/helper.h
+++ b/target/mips/helper.h
@@ -993,6 +993,11 @@ DEF_HELPER_4(msa_subsus_u_h, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_subsus_u_w, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_subsus_u_d, void, env, i32, i32, i32)
 
+DEF_HELPER_4(msa_subsuu_s_b, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_subsuu_s_h, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_subsuu_s_w, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_subsuu_s_d, void, env, i32, i32, i32)
+
 DEF_HELPER_4(msa_ilvev_b, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_ilvev_h, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_ilvev_w, void, env, i32, i32, i32)
@@ -1089,7 +1094,6 @@ DEF_HELPER_5(msa_srlri_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_binsl_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_binsr_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_subv_df, void, env, i32, i32, i32, i32)
-DEF_HELPER_5(msa_subsuu_s_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_mulv_df, void, env, i32, i32, i32, i32)
 
 DEF_HELPER_4(msa_dotp_s_h, void, env, i32, i32, i32)
diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c
index f7e5c018ac..27a9c36a89 100644
--- a/target/mips/msa_helper.c
+++ b/target/mips/msa_helper.c
@@ -3886,6 +3886,90 @@ void helper_msa_subsus_u_d(CPUMIPSState *env,
 }
 
 
+static inline int64_t msa_subsuu_s_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+uint64_t u_arg1 = UNSIGNED(arg1, df);
+uint64_t u_arg2 = UNSIGNED(arg2, df);
+int64_t max_int = DF_MAX_INT(df);
+int64_t min_int = DF_MIN_INT(df);
+if (u_arg1 > u_arg2) {
+return u_arg1 - u_arg2 < (uint64_t)max_int ?
+(int64_t)(u_arg1 - u_arg2) :
+max_int;
+} else {
+return u_arg2 - u_arg1 < (uint64_t)(-min_int) ?
+(int64_t)(u_arg1 - u_arg2) :
+min_int;
+}
+}
+
+void helper_msa_subsuu_s_b(CPUMIPSState *env,
+   uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->b[0]  = msa_subsuu_s_df(DF_BYTE, pws->b[0],  pwt->b[0]);
+pwd->b[1]  = msa_subsuu_s_df(DF_BYTE, pws->b[1],  pwt->b[1]);
+pwd->b[2]  = msa_subsuu_s_df(DF_BYTE, pws->b[2],  pwt->b[2]);
+pwd->b[3]  = msa_subsuu_s_df(DF_BYTE, pws->b[3],  pwt->b[3]);
+pwd->b[4]  = msa_subsuu_s_df(DF_BYTE, pws->b[4],  pwt->b[4]);
+pwd->b[5]  = msa_subsuu_s_df(DF_BYTE, pws->b[5],  pwt->b[5]);
+pwd->b[6]  = msa_subsuu_s_df(DF_BYTE, pws->b[6],  pwt->b[6]);
+pwd->b[7]  = msa_subsuu_s_df(DF_BYTE, pws->b[7],  pwt->b[7]);
+pwd->b[8]  = msa_subsuu_s_df(DF_BYTE, pws->b[8],  pwt->b[8]);
+pwd->b[9]  = msa_subsuu_s_df(DF_BYTE, pws->b[9],  pwt->b[9]);
+pwd->b[10] = msa_subsuu_s_df(DF_BYTE, pws->b[10], pwt->b[10]);
+pwd->b[11] = msa_subsuu_s_df(DF_BYTE, pws->b[11], pwt->b[11]);
+pwd->b[12] = msa_subsuu_s_df(DF_BYTE, pws->b[12], pwt->b[12]);
+pwd->b[13] = msa_subsuu_s_df(DF_BYTE, pws->b[13], pwt->b[13]);
+pwd->b[14] = msa_subsuu_s_df(DF_BYTE, pws->b[14], pwt->b[14]);
+pwd->b[15] = msa_subsuu_s_df(DF_BYTE, pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_subsuu_s_h(CPUMIPSState *env,
+   uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->h[0]  = msa_subsuu_s_df(DF_HALF, pws->h[0],  pwt->h[0]);
+pwd->h[1]  = msa_subsuu_s_df(DF_HALF, pws->h[1],  pwt->h[1]);
+pwd->h[2]  = msa_subsuu_s_df(DF_HALF, pws->h[2],  pwt->h[2]);
+pwd->h[3]  = msa_subsuu_s_df(DF_HALF, pws->h[3],  pwt->h[3]);
+pwd->h[4]  = msa_subsuu_s_df(DF_HALF, pws->h[4],  pwt->h[4]);
+pwd->h[5]  = msa_subsuu_s_df(DF_HALF, pws->h[5],  pwt->h[5]);
+pwd->h[6]  = msa_subsuu_s_df(DF_HALF, pws->h[6],  pwt->h[6]);
+pwd->h[7]  = msa_subsuu_s_df(DF_HALF, pws->h[7],  pwt->h[7]);
+}
+
+void helper_msa_subsuu_s_w(CPUMIPSState *env,
+   uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->w[0]  = msa_subsuu_s_df(DF_WORD, pws->w[0],  pwt->w[0]);
+pwd->w[1]  = msa_subsuu_s_df(DF_WORD, pws->w[1],  pwt->w[1]);
+pwd->w[2]  = msa_subsuu_s_df(DF_WORD, pws->w[2],  pwt->w[2]);
+pwd->w[3]  = msa_subsuu_s_df(DF_WORD, pws->w[3],  pwt->w[3]);
+}
+
+void helper_msa_subsuu_s_d(CPUMIPSState *env,
+   

[PATCH v8 01/14] target/mips: msa: Split helpers for MADDV.

2020-06-13 Thread Aleksandar Markovic
Achieves clearer code and slightly better performance.

Signed-off-by: Aleksandar Markovic 
---
 target/mips/helper.h |  6 ++-
 target/mips/msa_helper.c | 79 
 target/mips/translate.c  | 19 --
 3 files changed, 92 insertions(+), 12 deletions(-)

diff --git a/target/mips/helper.h b/target/mips/helper.h
index 84fdd9fd27..e479a22559 100644
--- a/target/mips/helper.h
+++ b/target/mips/helper.h
@@ -950,6 +950,11 @@ DEF_HELPER_4(msa_mod_s_h, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_mod_s_w, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_mod_s_d, void, env, i32, i32, i32)
 
+DEF_HELPER_4(msa_maddv_b, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_maddv_h, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_maddv_w, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_maddv_d, void, env, i32, i32, i32)
+
 DEF_HELPER_4(msa_asub_s_b, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_asub_s_h, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_asub_s_w, void, env, i32, i32, i32)
@@ -1069,7 +1074,6 @@ DEF_HELPER_5(msa_subs_u_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_subsus_u_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_subsuu_s_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_mulv_df, void, env, i32, i32, i32, i32)
-DEF_HELPER_5(msa_maddv_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_msubv_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_dotp_s_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_dotp_u_df, void, env, i32, i32, i32, i32)
diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c
index c3b271934a..3b75bdc6a4 100644
--- a/target/mips/msa_helper.c
+++ b/target/mips/msa_helper.c
@@ -2883,7 +2883,77 @@ void helper_msa_mod_u_d(CPUMIPSState *env,
  * +---+--+
  */
 
-/* TODO: insert Int Multiply group helpers here */
+static inline int64_t msa_maddv_df(uint32_t df, int64_t dest, int64_t arg1,
+   int64_t arg2)
+{
+return dest + arg1 * arg2;
+}
+
+void helper_msa_maddv_b(CPUMIPSState *env,
+uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->b[0]  = msa_maddv_df(DF_BYTE, pwt->b[0],  pws->b[0],  pwt->b[0]);
+pwd->b[1]  = msa_maddv_df(DF_BYTE, pwt->b[1],  pws->b[1],  pwt->b[1]);
+pwd->b[2]  = msa_maddv_df(DF_BYTE, pwt->b[2],  pws->b[2],  pwt->b[2]);
+pwd->b[3]  = msa_maddv_df(DF_BYTE, pwt->b[3],  pws->b[3],  pwt->b[3]);
+pwd->b[4]  = msa_maddv_df(DF_BYTE, pwt->b[4],  pws->b[4],  pwt->b[4]);
+pwd->b[5]  = msa_maddv_df(DF_BYTE, pwt->b[5],  pws->b[5],  pwt->b[5]);
+pwd->b[6]  = msa_maddv_df(DF_BYTE, pwt->b[6],  pws->b[6],  pwt->b[6]);
+pwd->b[7]  = msa_maddv_df(DF_BYTE, pwt->b[7],  pws->b[7],  pwt->b[7]);
+pwd->b[8]  = msa_maddv_df(DF_BYTE, pwt->b[8],  pws->b[8],  pwt->b[8]);
+pwd->b[9]  = msa_maddv_df(DF_BYTE, pwt->b[9],  pws->b[9],  pwt->b[9]);
+pwd->b[10] = msa_maddv_df(DF_BYTE, pwt->b[10], pws->b[10], pwt->b[10]);
+pwd->b[11] = msa_maddv_df(DF_BYTE, pwt->b[11], pws->b[11], pwt->b[11]);
+pwd->b[12] = msa_maddv_df(DF_BYTE, pwt->b[12], pws->b[12], pwt->b[12]);
+pwd->b[13] = msa_maddv_df(DF_BYTE, pwt->b[13], pws->b[13], pwt->b[13]);
+pwd->b[14] = msa_maddv_df(DF_BYTE, pwt->b[14], pws->b[14], pwt->b[14]);
+pwd->b[15] = msa_maddv_df(DF_BYTE, pwt->b[15], pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_maddv_h(CPUMIPSState *env,
+uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->h[0]  = msa_maddv_df(DF_HALF, pwd->h[0],  pws->h[0],  pwt->h[0]);
+pwd->h[1]  = msa_maddv_df(DF_HALF, pwd->h[1],  pws->h[1],  pwt->h[1]);
+pwd->h[2]  = msa_maddv_df(DF_HALF, pwd->h[2],  pws->h[2],  pwt->h[2]);
+pwd->h[3]  = msa_maddv_df(DF_HALF, pwd->h[3],  pws->h[3],  pwt->h[3]);
+pwd->h[4]  = msa_maddv_df(DF_HALF, pwd->h[4],  pws->h[4],  pwt->h[4]);
+pwd->h[5]  = msa_maddv_df(DF_HALF, pwd->h[5],  pws->h[5],  pwt->h[5]);
+pwd->h[6]  = msa_maddv_df(DF_HALF, pwd->h[6],  pws->h[6],  pwt->h[6]);
+pwd->h[7]  = msa_maddv_df(DF_HALF, pwd->h[7],  pws->h[7],  pwt->h[7]);
+}
+
+void helper_msa_maddv_w(CPUMIPSState *env,
+uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->w[0]  = msa_maddv_df(DF_WORD, pwd->w[0],  pws->w[0],  pwt->w[0]);
+pwd->w[1]  = msa_maddv_df(DF_WORD, pwd->w[1],  pws->w[1],  pwt->w[1]);
+pwd->w[2]  = msa_maddv_df(DF_WORD, pwd->w[2],  pws->w[2],  pwt->w[2]);
+pwd->w[3]  = msa_maddv_df(DF_WORD, pwd->w[3],  pws->w[3],  pwt->w[3]);
+}
+
+void helper_msa_maddv_d(CPUMIPSState 

[PATCH v8 08/14] target/mips: msa: Split helpers for DOTP_U.

2020-06-13 Thread Aleksandar Markovic
Achieves clearer code and slightly better performance.

Signed-off-by: Aleksandar Markovic 
---
 target/mips/helper.h |  4 ++-
 target/mips/msa_helper.c | 65 
 target/mips/translate.c  | 12 +++-
 3 files changed, 67 insertions(+), 14 deletions(-)

diff --git a/target/mips/helper.h b/target/mips/helper.h
index 06df3de744..05d5533dfb 100644
--- a/target/mips/helper.h
+++ b/target/mips/helper.h
@@ -1083,7 +1083,9 @@ DEF_HELPER_5(msa_mulv_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_4(msa_dotp_s_h, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_dotp_s_w, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_dotp_s_d, void, env, i32, i32, i32)
-DEF_HELPER_5(msa_dotp_u_df, void, env, i32, i32, i32, i32)
+DEF_HELPER_4(msa_dotp_u_h, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_dotp_u_w, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_dotp_u_d, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_dpadd_s_h, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_dpadd_s_w, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_dpadd_s_d, void, env, i32, i32, i32)
diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c
index 201283fdd9..84d0073918 100644
--- a/target/mips/msa_helper.c
+++ b/target/mips/msa_helper.c
@@ -2290,6 +2290,59 @@ void helper_msa_dotp_s_d(CPUMIPSState *env,
 }
 
 
+static inline int64_t msa_dotp_u_df(uint32_t df, int64_t arg1, int64_t arg2)
+{
+int64_t even_arg1;
+int64_t even_arg2;
+int64_t odd_arg1;
+int64_t odd_arg2;
+UNSIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df);
+UNSIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df);
+return (even_arg1 * even_arg2) + (odd_arg1 * odd_arg2);
+}
+
+void helper_msa_dotp_u_h(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->h[0]  = msa_dotp_u_df(DF_HALF, pws->h[0],  pwt->h[0]);
+pwd->h[1]  = msa_dotp_u_df(DF_HALF, pws->h[1],  pwt->h[1]);
+pwd->h[2]  = msa_dotp_u_df(DF_HALF, pws->h[2],  pwt->h[2]);
+pwd->h[3]  = msa_dotp_u_df(DF_HALF, pws->h[3],  pwt->h[3]);
+pwd->h[4]  = msa_dotp_u_df(DF_HALF, pws->h[4],  pwt->h[4]);
+pwd->h[5]  = msa_dotp_u_df(DF_HALF, pws->h[5],  pwt->h[5]);
+pwd->h[6]  = msa_dotp_u_df(DF_HALF, pws->h[6],  pwt->h[6]);
+pwd->h[7]  = msa_dotp_u_df(DF_HALF, pws->h[7],  pwt->h[7]);
+}
+
+void helper_msa_dotp_u_w(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->w[0]  = msa_dotp_u_df(DF_WORD, pws->w[0],  pwt->w[0]);
+pwd->w[1]  = msa_dotp_u_df(DF_WORD, pws->w[1],  pwt->w[1]);
+pwd->w[2]  = msa_dotp_u_df(DF_WORD, pws->w[2],  pwt->w[2]);
+pwd->w[3]  = msa_dotp_u_df(DF_WORD, pws->w[3],  pwt->w[3]);
+}
+
+void helper_msa_dotp_u_d(CPUMIPSState *env,
+ uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->d[0]  = msa_dotp_u_df(DF_DOUBLE, pws->d[0],  pwt->d[0]);
+pwd->d[1]  = msa_dotp_u_df(DF_DOUBLE, pws->d[1],  pwt->d[1]);
+}
+
+
 static inline int64_t msa_dpadd_s_df(uint32_t df, int64_t dest, int64_t arg1,
  int64_t arg2)
 {
@@ -5064,17 +5117,6 @@ static inline int64_t msa_mulv_df(uint32_t df, int64_t 
arg1, int64_t arg2)
 return arg1 * arg2;
 }
 
-static inline int64_t msa_dotp_u_df(uint32_t df, int64_t arg1, int64_t arg2)
-{
-int64_t even_arg1;
-int64_t even_arg2;
-int64_t odd_arg1;
-int64_t odd_arg2;
-UNSIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df);
-UNSIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df);
-return (even_arg1 * even_arg2) + (odd_arg1 * odd_arg2);
-}
-
 #define CONCATENATE_AND_SLIDE(s, k) \
 do {\
 for (i = 0; i < s; i++) {   \
@@ -5198,7 +5240,6 @@ MSA_BINOP_DF(subs_u)
 MSA_BINOP_DF(subsus_u)
 MSA_BINOP_DF(subsuu_s)
 MSA_BINOP_DF(mulv)
-MSA_BINOP_DF(dotp_u)
 
 MSA_BINOP_DF(mul_q)
 MSA_BINOP_DF(mulr_q)
diff --git a/target/mips/translate.c b/target/mips/translate.c
index f0bab46378..b56bdf54af 100644
--- a/target/mips/translate.c
+++ b/target/mips/translate.c
@@ -29406,7 +29406,17 @@ static void gen_msa_3r(CPUMIPSState *env, DisasContext 
*ctx)
 }
 break;
 case OPC_DOTP_U_df:
-gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
+switch (df) {
+case DF_HALF:
+gen_helper_msa_dotp_u_h(cpu_env, twd, tws, twt);
+break;
+case DF_WORD:
+gen_helper_msa_dotp_u_w(cpu_env, twd, tws, twt);
+break;
+case DF_DOUBLE:
+

[PATCH v8 05/14] target/mips: msa: Split helpers for DPSUB_S.

2020-06-13 Thread Aleksandar Markovic
Achieves clearer code and slightly better performance.

Signed-off-by: Aleksandar Markovic 
---
 target/mips/helper.h |  4 ++-
 target/mips/msa_helper.c | 67 
 target/mips/translate.c  | 12 ++-
 3 files changed, 68 insertions(+), 15 deletions(-)

diff --git a/target/mips/helper.h b/target/mips/helper.h
index 155b6bbe3e..2de14542cd 100644
--- a/target/mips/helper.h
+++ b/target/mips/helper.h
@@ -1087,7 +1087,9 @@ DEF_HELPER_4(msa_dpadd_s_d, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_dpadd_u_h, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_dpadd_u_w, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_dpadd_u_d, void, env, i32, i32, i32)
-DEF_HELPER_5(msa_dpsub_s_df, void, env, i32, i32, i32, i32)
+DEF_HELPER_4(msa_dpsub_s_h, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_dpsub_s_w, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_dpsub_s_d, void, env, i32, i32, i32)
 DEF_HELPER_5(msa_dpsub_u_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_sld_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_splat_df, void, env, i32, i32, i32, i32)
diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c
index 9741c94d27..934f705c1e 100644
--- a/target/mips/msa_helper.c
+++ b/target/mips/msa_helper.c
@@ -2344,6 +2344,60 @@ void helper_msa_dpadd_u_d(CPUMIPSState *env,
 }
 
 
+static inline int64_t msa_dpsub_s_df(uint32_t df, int64_t dest, int64_t arg1,
+ int64_t arg2)
+{
+int64_t even_arg1;
+int64_t even_arg2;
+int64_t odd_arg1;
+int64_t odd_arg2;
+SIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df);
+SIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df);
+return dest - ((even_arg1 * even_arg2) + (odd_arg1 * odd_arg2));
+}
+
+void helper_msa_dpsub_s_h(CPUMIPSState *env,
+  uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->h[0]  = msa_dpsub_s_df(DF_HALF, pwd->h[0],  pws->h[0],  pwt->h[0]);
+pwd->h[1]  = msa_dpsub_s_df(DF_HALF, pwd->h[1],  pws->h[1],  pwt->h[1]);
+pwd->h[2]  = msa_dpsub_s_df(DF_HALF, pwd->h[2],  pws->h[2],  pwt->h[2]);
+pwd->h[3]  = msa_dpsub_s_df(DF_HALF, pwd->h[3],  pws->h[3],  pwt->h[3]);
+pwd->h[4]  = msa_dpsub_s_df(DF_HALF, pwd->h[4],  pws->h[4],  pwt->h[4]);
+pwd->h[5]  = msa_dpsub_s_df(DF_HALF, pwd->h[5],  pws->h[5],  pwt->h[5]);
+pwd->h[6]  = msa_dpsub_s_df(DF_HALF, pwd->h[6],  pws->h[6],  pwt->h[6]);
+pwd->h[7]  = msa_dpsub_s_df(DF_HALF, pwd->h[7],  pws->h[7],  pwt->h[7]);
+}
+
+void helper_msa_dpsub_s_w(CPUMIPSState *env,
+  uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->w[0]  = msa_dpsub_s_df(DF_WORD, pwd->w[0],  pws->w[0],  pwt->w[0]);
+pwd->w[1]  = msa_dpsub_s_df(DF_WORD, pwd->w[1],  pws->w[1],  pwt->w[1]);
+pwd->w[2]  = msa_dpsub_s_df(DF_WORD, pwd->w[2],  pws->w[2],  pwt->w[2]);
+pwd->w[3]  = msa_dpsub_s_df(DF_WORD, pwd->w[3],  pws->w[3],  pwt->w[3]);
+}
+
+void helper_msa_dpsub_s_d(CPUMIPSState *env,
+  uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->d[0]  = msa_dpsub_s_df(DF_DOUBLE, pwd->d[0],  pws->d[0],  pwt->d[0]);
+pwd->d[1]  = msa_dpsub_s_df(DF_DOUBLE, pwd->d[1],  pws->d[1],  pwt->d[1]);
+}
+
+
 /*
  * Int Max Min
  * ---
@@ -5063,18 +5117,6 @@ void helper_msa_sld_df(CPUMIPSState *env, uint32_t df, 
uint32_t wd,
 msa_sld_df(df, pwd, pws, env->active_tc.gpr[rt]);
 }
 
-static inline int64_t msa_dpsub_s_df(uint32_t df, int64_t dest, int64_t arg1,
- int64_t arg2)
-{
-int64_t even_arg1;
-int64_t even_arg2;
-int64_t odd_arg1;
-int64_t odd_arg2;
-SIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df);
-SIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df);
-return dest - ((even_arg1 * even_arg2) + (odd_arg1 * odd_arg2));
-}
-
 static inline int64_t msa_dpsub_u_df(uint32_t df, int64_t dest, int64_t arg1,
  int64_t arg2)
 {
@@ -5213,7 +5255,6 @@ void helper_msa_ ## func ## _df(CPUMIPSState *env, 
uint32_t df, uint32_t wd,  \
 } \
 }
 
-MSA_TEROP_DF(dpsub_s)
 MSA_TEROP_DF(dpsub_u)
 MSA_TEROP_DF(binsl)
 MSA_TEROP_DF(binsr)
diff --git a/target/mips/translate.c b/target/mips/translate.c
index 009ac5c1fb..2576905e5b 100644
--- a/target/mips/translate.c
+++ b/target/mips/translate.c
@@ -29425,7 +29425,17 @@ static void gen_msa_3r(CPUMIPSState *env, DisasContext 
*ctx)
 }
 break;
 case OPC_DPSUB_S_df:
-gen_helper_msa_dpsub_s_df(cpu_env, tdf, 

[PATCH v8 00/14] target/mips: MSA, FPU and other cleanups and improvements

2020-06-13 Thread Aleksandar Markovic
This series contains some patches that split heprers in msa_helper.c.
It will make easier for debugging tools to display involved source
code, and also introduces some modest performance improvements gains
for all involved MSA instructions.

v7->v8:

  - added six new demacroing patches

v6->v7:

  - excluded patches that have been already upstreamed
  - added six new demacroing patches

v5->v6:

  - excluded a patch that was included by mistake

v4->v5:

  - corrected some spelling and style mistakes in commit messages
  - added changing MAINTAINERS too while renaming files
  - added two patches on splitting helpers in msa_helper.c

v3->v4:

  - corrected some spelling and style mistakes in commit messages
  - added a patch on renaming some files in hw/mips

v2->v3:

  - changed Malta patch to perform logging
  - added change of Aleksandar Rikalo's email

v1->v2:

  - added more demacroing

Aleksandar Markovic (14):
  target/mips: msa: Split helpers for MADDV.
  target/mips: msa: Split helpers for MSUBV.
  target/mips: msa: Split helpers for DPADD_S.
  target/mips: msa: Split helpers for DPADD_U.
  target/mips: msa: Split helpers for DPSUB_S.
  target/mips: msa: Split helpers for DPSUB_U.
  target/mips: msa: Split helpers for DOTP_S.
  target/mips: msa: Split helpers for DOTP_U.
  target/mips: msa: Split helpers for SUBS_S.
  target/mips: msa: Split helpers for SUBS_U.
  target/mips: msa: Split helpers for SUBSUS_U.
  target/mips: msa: Split helpers for SUBSUU_S.
  target/mips: msa: Split helpers for SUBV.
  target/mips: msa: Split helpers for MULV.

 target/mips/helper.h |   73 ++-
 target/mips/msa_helper.c | 1296 ++
 target/mips/translate.c  |  200 +-
 3 files changed, 1271 insertions(+), 298 deletions(-)

-- 
2.20.1




[PATCH v8 02/14] target/mips: msa: Split helpers for MSUBV.

2020-06-13 Thread Aleksandar Markovic
Achieves clearer code and slightly better performance.

Signed-off-by: Aleksandar Markovic 
---
 target/mips/helper.h |  6 ++-
 target/mips/msa_helper.c | 79 
 target/mips/translate.c  | 19 --
 3 files changed, 93 insertions(+), 11 deletions(-)

diff --git a/target/mips/helper.h b/target/mips/helper.h
index e479a22559..7ca0036807 100644
--- a/target/mips/helper.h
+++ b/target/mips/helper.h
@@ -955,6 +955,11 @@ DEF_HELPER_4(msa_maddv_h, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_maddv_w, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_maddv_d, void, env, i32, i32, i32)
 
+DEF_HELPER_4(msa_msubv_b, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_msubv_h, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_msubv_w, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_msubv_d, void, env, i32, i32, i32)
+
 DEF_HELPER_4(msa_asub_s_b, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_asub_s_h, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_asub_s_w, void, env, i32, i32, i32)
@@ -1074,7 +1079,6 @@ DEF_HELPER_5(msa_subs_u_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_subsus_u_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_subsuu_s_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_mulv_df, void, env, i32, i32, i32, i32)
-DEF_HELPER_5(msa_msubv_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_dotp_s_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_dotp_u_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_dpadd_s_df, void, env, i32, i32, i32, i32)
diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c
index 3b75bdc6a4..2b54de0959 100644
--- a/target/mips/msa_helper.c
+++ b/target/mips/msa_helper.c
@@ -2955,6 +2955,78 @@ void helper_msa_maddv_d(CPUMIPSState *env,
 pwd->d[1]  = msa_maddv_df(DF_DOUBLE, pwd->d[1],  pws->d[1],  pwt->d[1]);
 }
 
+static inline int64_t msa_msubv_df(uint32_t df, int64_t dest, int64_t arg1,
+   int64_t arg2)
+{
+return dest - arg1 * arg2;
+}
+
+void helper_msa_msubv_b(CPUMIPSState *env,
+uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->b[0]  = msa_msubv_df(DF_BYTE, pwt->b[0],  pws->b[0],  pwt->b[0]);
+pwd->b[1]  = msa_msubv_df(DF_BYTE, pwt->b[1],  pws->b[1],  pwt->b[1]);
+pwd->b[2]  = msa_msubv_df(DF_BYTE, pwt->b[2],  pws->b[2],  pwt->b[2]);
+pwd->b[3]  = msa_msubv_df(DF_BYTE, pwt->b[3],  pws->b[3],  pwt->b[3]);
+pwd->b[4]  = msa_msubv_df(DF_BYTE, pwt->b[4],  pws->b[4],  pwt->b[4]);
+pwd->b[5]  = msa_msubv_df(DF_BYTE, pwt->b[5],  pws->b[5],  pwt->b[5]);
+pwd->b[6]  = msa_msubv_df(DF_BYTE, pwt->b[6],  pws->b[6],  pwt->b[6]);
+pwd->b[7]  = msa_msubv_df(DF_BYTE, pwt->b[7],  pws->b[7],  pwt->b[7]);
+pwd->b[8]  = msa_msubv_df(DF_BYTE, pwt->b[8],  pws->b[8],  pwt->b[8]);
+pwd->b[9]  = msa_msubv_df(DF_BYTE, pwt->b[9],  pws->b[9],  pwt->b[9]);
+pwd->b[10] = msa_msubv_df(DF_BYTE, pwt->b[10], pws->b[10], pwt->b[10]);
+pwd->b[11] = msa_msubv_df(DF_BYTE, pwt->b[11], pws->b[11], pwt->b[11]);
+pwd->b[12] = msa_msubv_df(DF_BYTE, pwt->b[12], pws->b[12], pwt->b[12]);
+pwd->b[13] = msa_msubv_df(DF_BYTE, pwt->b[13], pws->b[13], pwt->b[13]);
+pwd->b[14] = msa_msubv_df(DF_BYTE, pwt->b[14], pws->b[14], pwt->b[14]);
+pwd->b[15] = msa_msubv_df(DF_BYTE, pwt->b[15], pws->b[15], pwt->b[15]);
+}
+
+void helper_msa_msubv_h(CPUMIPSState *env,
+uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->h[0]  = msa_msubv_df(DF_HALF, pwd->h[0],  pws->h[0],  pwt->h[0]);
+pwd->h[1]  = msa_msubv_df(DF_HALF, pwd->h[1],  pws->h[1],  pwt->h[1]);
+pwd->h[2]  = msa_msubv_df(DF_HALF, pwd->h[2],  pws->h[2],  pwt->h[2]);
+pwd->h[3]  = msa_msubv_df(DF_HALF, pwd->h[3],  pws->h[3],  pwt->h[3]);
+pwd->h[4]  = msa_msubv_df(DF_HALF, pwd->h[4],  pws->h[4],  pwt->h[4]);
+pwd->h[5]  = msa_msubv_df(DF_HALF, pwd->h[5],  pws->h[5],  pwt->h[5]);
+pwd->h[6]  = msa_msubv_df(DF_HALF, pwd->h[6],  pws->h[6],  pwt->h[6]);
+pwd->h[7]  = msa_msubv_df(DF_HALF, pwd->h[7],  pws->h[7],  pwt->h[7]);
+}
+
+void helper_msa_msubv_w(CPUMIPSState *env,
+uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->w[0]  = msa_msubv_df(DF_WORD, pwd->w[0],  pws->w[0],  pwt->w[0]);
+pwd->w[1]  = msa_msubv_df(DF_WORD, pwd->w[1],  pws->w[1],  pwt->w[1]);
+pwd->w[2]  = msa_msubv_df(DF_WORD, pwd->w[2],  pws->w[2],  pwt->w[2]);
+pwd->w[3]  = msa_msubv_df(DF_WORD, pwd->w[3],  pws->w[3],  pwt->w[3]);
+}
+
+void helper_msa_msubv_d(CPUMIPSState *env,
+uint32_t wd, uint32_t ws, 

[PATCH v8 04/14] target/mips: msa: Split helpers for DPADD_U.

2020-06-13 Thread Aleksandar Markovic
Achieves clearer code and slightly better performance.

Signed-off-by: Aleksandar Markovic 
---
 target/mips/helper.h |  4 ++-
 target/mips/msa_helper.c | 67 
 target/mips/translate.c  | 12 ++-
 3 files changed, 68 insertions(+), 15 deletions(-)

diff --git a/target/mips/helper.h b/target/mips/helper.h
index 16f2d53ad0..155b6bbe3e 100644
--- a/target/mips/helper.h
+++ b/target/mips/helper.h
@@ -1084,7 +1084,9 @@ DEF_HELPER_5(msa_dotp_u_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_4(msa_dpadd_s_h, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_dpadd_s_w, void, env, i32, i32, i32)
 DEF_HELPER_4(msa_dpadd_s_d, void, env, i32, i32, i32)
-DEF_HELPER_5(msa_dpadd_u_df, void, env, i32, i32, i32, i32)
+DEF_HELPER_4(msa_dpadd_u_h, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_dpadd_u_w, void, env, i32, i32, i32)
+DEF_HELPER_4(msa_dpadd_u_d, void, env, i32, i32, i32)
 DEF_HELPER_5(msa_dpsub_s_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_dpsub_u_df, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(msa_sld_df, void, env, i32, i32, i32, i32)
diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c
index 086b56f58c..9741c94d27 100644
--- a/target/mips/msa_helper.c
+++ b/target/mips/msa_helper.c
@@ -2290,6 +2290,60 @@ void helper_msa_dpadd_s_d(CPUMIPSState *env,
 }
 
 
+static inline int64_t msa_dpadd_u_df(uint32_t df, int64_t dest, int64_t arg1,
+ int64_t arg2)
+{
+int64_t even_arg1;
+int64_t even_arg2;
+int64_t odd_arg1;
+int64_t odd_arg2;
+UNSIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df);
+UNSIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df);
+return dest + (even_arg1 * even_arg2) + (odd_arg1 * odd_arg2);
+}
+
+void helper_msa_dpadd_u_h(CPUMIPSState *env,
+  uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->h[0]  = msa_dpadd_u_df(DF_HALF, pwd->h[0],  pws->h[0],  pwt->h[0]);
+pwd->h[1]  = msa_dpadd_u_df(DF_HALF, pwd->h[1],  pws->h[1],  pwt->h[1]);
+pwd->h[2]  = msa_dpadd_u_df(DF_HALF, pwd->h[2],  pws->h[2],  pwt->h[2]);
+pwd->h[3]  = msa_dpadd_u_df(DF_HALF, pwd->h[3],  pws->h[3],  pwt->h[3]);
+pwd->h[4]  = msa_dpadd_u_df(DF_HALF, pwd->h[4],  pws->h[4],  pwt->h[4]);
+pwd->h[5]  = msa_dpadd_u_df(DF_HALF, pwd->h[5],  pws->h[5],  pwt->h[5]);
+pwd->h[6]  = msa_dpadd_u_df(DF_HALF, pwd->h[6],  pws->h[6],  pwt->h[6]);
+pwd->h[7]  = msa_dpadd_u_df(DF_HALF, pwd->h[7],  pws->h[7],  pwt->h[7]);
+}
+
+void helper_msa_dpadd_u_w(CPUMIPSState *env,
+  uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->w[0]  = msa_dpadd_u_df(DF_WORD, pwd->w[0],  pws->w[0],  pwt->w[0]);
+pwd->w[1]  = msa_dpadd_u_df(DF_WORD, pwd->w[1],  pws->w[1],  pwt->w[1]);
+pwd->w[2]  = msa_dpadd_u_df(DF_WORD, pwd->w[2],  pws->w[2],  pwt->w[2]);
+pwd->w[3]  = msa_dpadd_u_df(DF_WORD, pwd->w[3],  pws->w[3],  pwt->w[3]);
+}
+
+void helper_msa_dpadd_u_d(CPUMIPSState *env,
+  uint32_t wd, uint32_t ws, uint32_t wt)
+{
+wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+wr_t *pws = &(env->active_fpu.fpr[ws].wr);
+wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
+
+pwd->d[0]  = msa_dpadd_u_df(DF_DOUBLE, pwd->d[0],  pws->d[0],  pwt->d[0]);
+pwd->d[1]  = msa_dpadd_u_df(DF_DOUBLE, pwd->d[1],  pws->d[1],  pwt->d[1]);
+}
+
+
 /*
  * Int Max Min
  * ---
@@ -5009,18 +5063,6 @@ void helper_msa_sld_df(CPUMIPSState *env, uint32_t df, 
uint32_t wd,
 msa_sld_df(df, pwd, pws, env->active_tc.gpr[rt]);
 }
 
-static inline int64_t msa_dpadd_u_df(uint32_t df, int64_t dest, int64_t arg1,
- int64_t arg2)
-{
-int64_t even_arg1;
-int64_t even_arg2;
-int64_t odd_arg1;
-int64_t odd_arg2;
-UNSIGNED_EXTRACT(even_arg1, odd_arg1, arg1, df);
-UNSIGNED_EXTRACT(even_arg2, odd_arg2, arg2, df);
-return dest + (even_arg1 * even_arg2) + (odd_arg1 * odd_arg2);
-}
-
 static inline int64_t msa_dpsub_s_df(uint32_t df, int64_t dest, int64_t arg1,
  int64_t arg2)
 {
@@ -5171,7 +5213,6 @@ void helper_msa_ ## func ## _df(CPUMIPSState *env, 
uint32_t df, uint32_t wd,  \
 } \
 }
 
-MSA_TEROP_DF(dpadd_u)
 MSA_TEROP_DF(dpsub_s)
 MSA_TEROP_DF(dpsub_u)
 MSA_TEROP_DF(binsl)
diff --git a/target/mips/translate.c b/target/mips/translate.c
index 94c3d15f2d..009ac5c1fb 100644
--- a/target/mips/translate.c
+++ b/target/mips/translate.c
@@ -29412,7 +29412,17 @@ static void gen_msa_3r(CPUMIPSState *env, DisasContext 
*ctx)
 }
 break;
 case OPC_DPADD_U_df:
-

[PATCH v2 3/5] grackle: Set revision in PCI config to match hardware

2020-06-13 Thread BALATON Zoltan
Signed-off-by: BALATON Zoltan 
---
 hw/pci-host/grackle.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/pci-host/grackle.c b/hw/pci-host/grackle.c
index 4b3af0c704..48d11f13ab 100644
--- a/hw/pci-host/grackle.c
+++ b/hw/pci-host/grackle.c
@@ -130,7 +130,7 @@ static void grackle_pci_class_init(ObjectClass *klass, void 
*data)
 k->realize   = grackle_pci_realize;
 k->vendor_id = PCI_VENDOR_ID_MOTOROLA;
 k->device_id = PCI_DEVICE_ID_MOTOROLA_MPC106;
-k->revision  = 0x00;
+k->revision  = 0x40;
 k->class_id  = PCI_CLASS_BRIDGE_HOST;
 /*
  * PCI-facing part of the host bridge, not usable without the
-- 
2.21.3




[PATCH v2 1/5] mac_oldworld: Allow loading binary ROM image

2020-06-13 Thread BALATON Zoltan
The G3 beige machine has a 4MB firmware ROM. Fix the size of the rom
region and allow loading a binary image with -bios. This makes it
possible to test emulation with a ROM image from real hardware.

Signed-off-by: BALATON Zoltan 
---
 hw/ppc/mac_oldworld.c | 24 +++-
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index 0b4c1c6373..3812adc441 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -59,6 +59,8 @@
 #define NDRV_VGA_FILENAME "qemu_vga.ndrv"
 
 #define GRACKLE_BASE 0xfec0
+#define PROM_BASE 0xffc0
+#define PROM_SIZE (4 * MiB)
 
 static void fw_cfg_boot_set(void *opaque, const char *boot_device,
 Error **errp)
@@ -127,24 +129,28 @@ static void ppc_heathrow_init(MachineState *machine)
 
 memory_region_add_subregion(sysmem, 0, machine->ram);
 
-/* allocate and load BIOS */
-memory_region_init_rom(bios, NULL, "ppc_heathrow.bios", BIOS_SIZE,
+/* allocate and load firmware ROM */
+memory_region_init_rom(bios, NULL, "ppc_heathrow.bios", PROM_SIZE,
_fatal);
+memory_region_add_subregion(sysmem, PROM_BASE, bios);
 
-if (bios_name == NULL)
+if (!bios_name) {
 bios_name = PROM_FILENAME;
+}
 filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-memory_region_add_subregion(sysmem, PROM_ADDR, bios);
-
-/* Load OpenBIOS (ELF) */
 if (filename) {
-bios_size = load_elf(filename, NULL, 0, NULL, NULL, NULL, NULL, NULL,
- 1, PPC_ELF_MACHINE, 0, 0);
+/* Load OpenBIOS (ELF) */
+bios_size = load_elf(filename, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, 1, PPC_ELF_MACHINE, 0, 0);
+if (bios_size <= 0) {
+/* or load binary ROM image */
+bios_size = load_image_targphys(filename, PROM_BASE, PROM_SIZE);
+}
 g_free(filename);
 } else {
 bios_size = -1;
 }
-if (bios_size < 0 || bios_size > BIOS_SIZE) {
+if (bios_size < 0 || bios_size > PROM_SIZE) {
 error_report("could not load PowerPC bios '%s'", bios_name);
 exit(1);
 }
-- 
2.21.3




[PATCH v2 4/5] mac_oldworld: Rename ppc_heathrow_reset reset to ppc_heathrow_cpu_reset

2020-06-13 Thread BALATON Zoltan
This function resets a CPU not the whole machine so reflect that in
its name.

Signed-off-by: BALATON Zoltan 
---
 hw/ppc/mac_oldworld.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index 4dd872c1a3..9138752ccb 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -73,7 +73,7 @@ static uint64_t translate_kernel_address(void *opaque, 
uint64_t addr)
 return (addr & 0x0fff) + KERNEL_LOAD_ADDR;
 }
 
-static void ppc_heathrow_reset(void *opaque)
+static void ppc_heathrow_cpu_reset(void *opaque)
 {
 PowerPCCPU *cpu = opaque;
 
@@ -127,7 +127,7 @@ static void ppc_heathrow_init(MachineState *machine)
 
 /* Set time-base frequency to 16.6 Mhz */
 cpu_ppc_tb_init(env,  TBFREQ);
-qemu_register_reset(ppc_heathrow_reset, cpu);
+qemu_register_reset(ppc_heathrow_cpu_reset, cpu);
 }
 
 /* allocate RAM */
-- 
2.21.3




[PATCH v2 5/5] mac_oldworld: Map macio to expected address at reset

2020-06-13 Thread BALATON Zoltan
Add a reset function that maps macio to the address expected by the
firmware of the board at startup.

Signed-off-by: BALATON Zoltan 
---
 hw/ppc/mac.h  | 12 
 hw/ppc/mac_oldworld.c | 17 +++--
 2 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h
index 6af87d1fa0..35a5f21163 100644
--- a/hw/ppc/mac.h
+++ b/hw/ppc/mac.h
@@ -57,6 +57,18 @@
 #define OLDWORLD_IDE1_IRQ  0xe
 #define OLDWORLD_IDE1_DMA_IRQ  0x3
 
+/* g3beige machine */
+#define TYPE_HEATHROW_MACHINE MACHINE_TYPE_NAME("g3beige")
+#define HEATHROW_MACHINE(obj) OBJECT_CHECK(HeathrowMachineState, (obj), \
+   TYPE_HEATHROW_MACHINE)
+
+typedef struct HeathrowMachineState {
+/*< private >*/
+MachineState parent;
+
+PCIDevice *macio_pci;
+} HeathrowMachineState;
+
 /* New World IRQs */
 #define NEWWORLD_CUDA_IRQ  0x19
 #define NEWWORLD_PMU_IRQ   0x19
diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index 9138752ccb..fa9527410d 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -73,6 +73,15 @@ static uint64_t translate_kernel_address(void *opaque, 
uint64_t addr)
 return (addr & 0x0fff) + KERNEL_LOAD_ADDR;
 }
 
+static void ppc_heathrow_reset(MachineState *machine)
+{
+HeathrowMachineState *m = HEATHROW_MACHINE(machine);
+
+qemu_devices_reset();
+pci_default_write_config(m->macio_pci, PCI_COMMAND, PCI_COMMAND_MEMORY, 2);
+pci_default_write_config(m->macio_pci, PCI_BASE_ADDRESS_0, 0xf300, 4);
+}
+
 static void ppc_heathrow_cpu_reset(void *opaque)
 {
 PowerPCCPU *cpu = opaque;
@@ -91,6 +100,7 @@ const MemoryRegionOps machine_id_reg_ops = {
 
 static void ppc_heathrow_init(MachineState *machine)
 {
+HeathrowMachineState *hm = HEATHROW_MACHINE(machine);
 ram_addr_t ram_size = machine->ram_size;
 const char *kernel_filename = machine->kernel_filename;
 const char *kernel_cmdline = machine->kernel_cmdline;
@@ -298,7 +308,8 @@ static void ppc_heathrow_init(MachineState *machine)
 ide_drive_get(hd, ARRAY_SIZE(hd));
 
 /* MacIO */
-macio = OLDWORLD_MACIO(pci_create(pci_bus, -1, TYPE_OLDWORLD_MACIO));
+hm->macio_pci = pci_create(pci_bus, -1, TYPE_OLDWORLD_MACIO);
+macio = OLDWORLD_MACIO(hm->macio_pci);
 dev = DEVICE(macio);
 qdev_prop_set_uint64(dev, "frequency", tbfreq);
 object_property_set_link(OBJECT(macio), OBJECT(pic_dev), "pic",
@@ -450,6 +461,7 @@ static void heathrow_class_init(ObjectClass *oc, void *data)
 
 mc->desc = "Heathrow based PowerMAC";
 mc->init = ppc_heathrow_init;
+mc->reset = ppc_heathrow_reset;
 mc->block_default_type = IF_IDE;
 mc->max_cpus = MAX_CPUS;
 #ifndef TARGET_PPC64
@@ -466,9 +478,10 @@ static void heathrow_class_init(ObjectClass *oc, void 
*data)
 }
 
 static const TypeInfo ppc_heathrow_machine_info = {
-.name  = MACHINE_TYPE_NAME("g3beige"),
+.name  = TYPE_HEATHROW_MACHINE,
 .parent= TYPE_MACHINE,
 .class_init= heathrow_class_init,
+.instance_size = sizeof(HeathrowMachineState),
 .interfaces = (InterfaceInfo[]) {
 { TYPE_FW_PATH_PROVIDER },
 { }
-- 
2.21.3




[PATCH v2 0/5] Mac Old World ROM experiment

2020-06-13 Thread BALATON Zoltan
Version 2 with some more tweaks this now starts but drops in a Serial
Test Manager (see below) presumably because some POST step is failing,
I let others who know more about this machine figure out what's
missing from here.

Regards,
BALATON Zoltan


  1 :pci_update_mappings_add d=0x55a1bb6254a0 00:01.0 0,0xf300+0x8
  1 pci_cfg_read grackle 00:0 @0x0 -> 0x21057
  1 pci_cfg_read grackle 00:0 @0xa8 -> 0x0
  1 pci_cfg_write grackle 00:0 @0xa8 <- 0x40e0c
  1 pci_cfg_read grackle 00:0 @0xac -> 0x0
  1 pci_cfg_write grackle 00:0 @0xac <- 0x1200
  1 pci_cfg_read grackle 00:0 @0xac -> 0x1200
  1 pci_cfg_write grackle 00:0 @0xac <- 0x200
  1 pci_cfg_read grackle 00:0 @0x70 -> 0x0
  1 pci_cfg_write grackle 00:0 @0x70 <- 0x1100
  1 machine_id_read(0, 2)
  1 pci_cfg_read grackle 00:0 @0x8 -> 0x6000140
  1 pci_cfg_read grackle 00:0 @0xf0 -> 0x0
  1 pci_cfg_write grackle 00:0 @0xf0 <- 0x1290
  1 machine_id_read(0, 2)
  1 portA_write unimplemented
  1 CUDA: unknown command 0x22
  1 CUDA: unknown command 0x26
  3 CUDA: unknown command 0x25
  1 pci_cfg_write grackle 00:0 @0x80 <- 0x
  1 pci_cfg_write grackle 00:0 @0x88 <- 0x
  1 pci_cfg_write grackle 00:0 @0x90 <- 0x
  1 pci_cfg_write grackle 00:0 @0x98 <- 0x
  1 pci_cfg_write grackle 00:0 @0x84 <- 0x
  1 pci_cfg_write grackle 00:0 @0x8c <- 0x
  1 pci_cfg_write grackle 00:0 @0x94 <- 0x
  1 pci_cfg_write grackle 00:0 @0x9c <- 0x
  1 pci_cfg_write grackle 00:0 @0xa0 <- 0x0
  1 pci_cfg_read grackle 00:0 @0xf0 -> 0x1290
  1 pci_cfg_write grackle 00:0 @0xf0 <- 0x1290
  1 machine_id_read(0, 2)
  1 pci_cfg_read grackle 00:0 @0x8 -> 0x6000140
  1 pci_cfg_read grackle 00:0 @0xf0 -> 0x1290
  1 pci_cfg_write grackle 00:0 @0xf0 <- 0x1294
  1 pci_cfg_write grackle 00:0 @0xf0 <- 0x1294
  1 pci_cfg_write grackle 00:0 @0xf4 <- 0x40010fe4
  1 pci_cfg_write grackle 00:0 @0xf8 <- 0x7302293
  1 pci_cfg_write grackle 00:0 @0xfc <- 0x25302220
  1 pci_cfg_read grackle 00:0 @0xa0 -> 0x0
  1 pci_cfg_write grackle 00:0 @0xa0 <- 0x6700
  1 pci_cfg_read grackle 00:0 @0xf0 -> 0x1294
  1 pci_cfg_write grackle 00:0 @0xf0 <- 0x129c
 550755 Unassigned mem read f3014020
  1 
  1 >?
  1 ***
  1 * *
  1 * Serial Test Manager *
  1 * *
  1 ***
  1 
  1 T)  Execute a test, single test number follows command
  1 T0) Run ROM Checksum Test
  1 T1) Run Address Line Test
  1 T2) Run Data Line Test
  1 T3) Run Simple RAM Test
  1 T4) Run Mod3 Forward Test
  1 T5) Run Mod3 Reverse Test
  1 T6) Run NVRAM Test
  1 T8) Run AddrPattern Test
  1 T9) Run NTAWord Test
  1 A)  Execute all ROM-based tests
  1 Q)  Quick test
  1 X)  Exit STM (Continue booting)
  1 ?)  Print this menu
  1 
  1 >

BALATON Zoltan (5):
  mac_oldworld: Allow loading binary ROM image
  mac_oldworld: Add machine ID register
  grackle: Set revision in PCI config to match hardware
  mac_oldworld: Rename ppc_heathrow_reset reset to
ppc_heathrow_cpu_reset
  mac_oldworld: Map macio to expected address at reset

 hw/pci-host/grackle.c |  2 +-
 hw/ppc/mac.h  | 12 +
 hw/ppc/mac_oldworld.c | 59 +--
 3 files changed, 59 insertions(+), 14 deletions(-)

-- 
2.21.3




[PATCH v2 2/5] mac_oldworld: Add machine ID register

2020-06-13 Thread BALATON Zoltan
The G3 beige machine has a machine ID register that is accessed by the
firmware to deternine the board config. Add basic emulation of it.

Signed-off-by: BALATON Zoltan 
---
 hw/ppc/mac_oldworld.c | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index 3812adc441..4dd872c1a3 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -80,6 +80,15 @@ static void ppc_heathrow_reset(void *opaque)
 cpu_reset(CPU(cpu));
 }
 
+static uint64_t machine_id_read(void *opaque, hwaddr addr, unsigned size)
+{
+return (addr == 0 && size == 2 ? 0x3d8c : 0);
+}
+
+const MemoryRegionOps machine_id_reg_ops = {
+.read = machine_id_read,
+};
+
 static void ppc_heathrow_init(MachineState *machine)
 {
 ram_addr_t ram_size = machine->ram_size;
@@ -93,6 +102,7 @@ static void ppc_heathrow_init(MachineState *machine)
 char *filename;
 int linux_boot, i;
 MemoryRegion *bios = g_new(MemoryRegion, 1);
+MemoryRegion *machine_id = g_new(MemoryRegion, 1);
 uint32_t kernel_base, initrd_base, cmdline_base = 0;
 int32_t kernel_size, initrd_size;
 PCIBus *pci_bus;
@@ -227,6 +237,10 @@ static void ppc_heathrow_init(MachineState *machine)
 }
 }
 
+memory_region_init_io(machine_id, OBJECT(machine), _id_reg_ops,
+  NULL, "machine_id", 2);
+memory_region_add_subregion(get_system_memory(), 0xff04, machine_id);
+
 /* XXX: we register only 1 output pin for heathrow PIC */
 pic_dev = qdev_create(NULL, TYPE_HEATHROW);
 qdev_init_nofail(pic_dev);
-- 
2.21.3




[Bug 1840719] Re: win98se floppy fails to boot with isapc machine

2020-06-13 Thread Roman Bolshakov
The ticket should be closed as soon as SeaBIOS gets updated in QEMU. A patch 
has been posted to SeaBIOS mailing list:
https://mail.coreboot.org/hyperkitty/list/seab...@seabios.org/thread/XPKQNLVWZX55TSLSXZVY5S5DMFYS4CNO/

** Changed in: seabios
 Assignee: (unassigned) => Roman Bolshakov (roolebo)

** Project changed: seabios => qemu

** Changed in: qemu
   Status: Confirmed => In Progress

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

Title:
  win98se floppy fails to boot with isapc machine

Status in QEMU:
  In Progress

Bug description:
  QEMU emulator version 4.1.50 (commit 50d69ee0d)

  floppy image from:
  https://winworldpc.com/download/417d71c2-ae18-c39a-11c3-a4e284a2c3a5

  $ qemu-system-i386 -M isapc -fda Windows\ 98\ Second\ Edition\ Boot.img
  SeaBIOS (version rel-1.12.1-0...)
  Booting from Floppy...
  Boot failed: could not read the boot disk

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



[Bug 1840719] [NEW] win98se floppy fails to boot with isapc machine

2020-06-13 Thread Launchpad Bug Tracker
You have been subscribed to a public bug:

QEMU emulator version 4.1.50 (commit 50d69ee0d)

floppy image from:
https://winworldpc.com/download/417d71c2-ae18-c39a-11c3-a4e284a2c3a5

$ qemu-system-i386 -M isapc -fda Windows\ 98\ Second\ Edition\ Boot.img
SeaBIOS (version rel-1.12.1-0...)
Booting from Floppy...
Boot failed: could not read the boot disk

** Affects: qemu
 Importance: Undecided
 Assignee: Roman Bolshakov (roolebo)
 Status: Confirmed


** Tags: bios floppy x86
-- 
win98se floppy fails to boot with isapc machine
https://bugs.launchpad.net/bugs/1840719
You received this bug notification because you are a member of qemu-devel-ml, 
which is subscribed to QEMU.



[PATCH] .travis.yml: Use travis_retry() in case of network issues

2020-06-13 Thread Philippe Mathieu-Daudé
Use travis_retry() when cloning SLOF (see 31c8cc4f94e) in the
s390x container job, to avoid build failures:

  $ ( cd ${SRC_DIR} ; git submodule update --init roms/SLOF )
  Submodule 'roms/SLOF' (https://git.qemu.org/git/SLOF.git) registered for path 
'roms/SLOF'
  Cloning into '/home/travis/build/user/qemu/roms/SLOF'...
  fatal: unable to access 'https://git.qemu.org/git/SLOF.git/': Could not 
resolve host: git.qemu.org
  fatal: clone of 'https://git.qemu.org/git/SLOF.git' into submodule path 
'/home/travis/build/user/qemu/roms/SLOF' failed
  Failed to clone 'roms/SLOF'. Retry scheduled
  Cloning into '/home/travis/build/user/qemu/roms/SLOF'...
  fatal: unable to access 'https://git.qemu.org/git/SLOF.git/': Could not 
resolve host: git.qemu.org
  fatal: clone of 'https://git.qemu.org/git/SLOF.git' into submodule path 
'/home/travis/build/user/qemu/roms/SLOF' failed
  Failed to clone 'roms/SLOF' a second time, aborting
  The command "( cd ${SRC_DIR} ; git submodule update --init roms/SLOF )" 
exited with 1.

Reported-by: Mark Cave-Ayland 
Signed-off-by: Philippe Mathieu-Daudé 
---
 .travis.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index ec6367af1f..19a1b55aab 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -496,7 +496,7 @@ jobs:
 - CONFIG="--disable-containers 
--target-list=${MAIN_SOFTMMU_TARGETS},s390x-linux-user"
 - UNRELIABLE=true
   script:
-- ( cd ${SRC_DIR} ; git submodule update --init roms/SLOF )
+- ( cd ${SRC_DIR} ; travis_retry git submodule update --init roms/SLOF 
)
 - BUILD_RC=0 && make -j${JOBS} || BUILD_RC=$?
 - |
   if [ "$BUILD_RC" -eq 0 ] ; then
-- 
2.21.3




[PATCH] timer: Handle decrements of PIT counter

2020-06-13 Thread Roman Bolshakov
There's a fallback to PIT if TSC is not present but it doesn't work
properly. It prevents boot from floppy on isapc and 486 cpu [1][2].

SeaBIOS configures PIT in Mode 2. PIT counter is decremented in the mode
but timer_adjust_bits() thinks that the counter overflows and increases
32-bit tick counter on each detected "overflow". Invalid overflow
detection results in 55ms time advance (1 / 18.2Hz) on each read from
PIT counter. So all timers expire much faster and 5-second floppy
timeout expires in 83 real microseconds (or just a bit longer).

Provide counter direction to timer_adjust_bits() and normalize the
counter to advance ticks in monotonically increasing TimerLast.

1. https://bugs.launchpad.net/seabios/+bug/1840719
2. https://lists.gnu.org/archive/html/qemu-devel/2019-08/msg03924.html

Fixes: eac11944019 ("Unify pmtimer_read() and pittimer_read() code.")
Reported-by: Philippe Mathieu-Daudé 
Cc: Kevin O'Connor 
Signed-off-by: Roman Bolshakov 
---
 src/hw/timer.c | 13 +
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/src/hw/timer.c b/src/hw/timer.c
index 56bb289..2441402 100644
--- a/src/hw/timer.c
+++ b/src/hw/timer.c
@@ -156,10 +156,15 @@ u32 TimerLast VARLOW;
 
 // Add extra high bits to timers that have less than 32bits of precision.
 static u32
-timer_adjust_bits(u32 value, u32 validbits)
+timer_adjust_bits(u32 value, u32 validbits, u8 countup)
 {
 u32 last = GET_LOW(TimerLast);
-value = (last & ~validbits) | (value & validbits);
+u32 validvalue;
+if (countup)
+validvalue = value & validbits;
+else
+validvalue = validbits - (value & validbits);
+value = (last & ~validbits) | validvalue;
 if (value < last)
 value += validbits + 1;
 SET_LOW(TimerLast, value);
@@ -176,11 +181,11 @@ timer_read(void)
 return rdtscll() >> GET_GLOBAL(ShiftTSC);
 if (CONFIG_PMTIMER && port != PORT_PIT_COUNTER0)
 // Read from PMTIMER
-return timer_adjust_bits(inl(port), 0xff);
+return timer_adjust_bits(inl(port), 0xff, 1);
 // Read from PIT.
 outb(PM_SEL_READBACK | PM_READ_VALUE | PM_READ_COUNTER0, PORT_PIT_MODE);
 u16 v = inb(PORT_PIT_COUNTER0) | (inb(PORT_PIT_COUNTER0) << 8);
-return timer_adjust_bits(v, 0x);
+return timer_adjust_bits(v, 0x, 0);
 }
 
 // Return the TSC value that is 'msecs' time in the future.
-- 
2.26.1




Re: [PATCH 0/5] linux-user: Support extended clone(CLONE_VM)

2020-06-13 Thread Alex Bennée


Josh Kunz  writes:

> This patch series implements extended support for the `clone` system
> call. As best I can tell, any option combination including `CLONE_VM`
> should be supported with the addition of this patch series. The
> implementation is described in greater detail in the patches themselves.
>
> Testing:
>
>   * All targets built on x86_64.
>   * `make check` and `make check-tcg` are passing. Additional tests have
> been added to `linux-test.c` to validate clone behavior.
>
> Caveats:
>
>   * This series touches, but does not fix, several bits of code that are
> racey (namely the sigact table and the fd trans table).
>   * `exit_group` does not perform the appropriate cleanup for non-thread
> children created with `CLONE_VM`. CPUs for such children are never
> cleaned up. The correct implementation of exit-group is non-trivial
> (since it also needs to track/handle cleanup for threads in the
> clone'd child process). Also, I don't fully understand the
> interaction between QOM<->linux-user.

When the QOM object gets unrefed for the final time it should cause a
bunch of clean-up in the common vCPU management code where things like
plugin cleanup are done.

This was recently touched in 1f81ce90e31ef338ee53a0cea02344237bc470cc
where I removed linux-user messing around with the active cpu list and
left it to the core code to deal with. Previously it wasn't being
properly unrealized.

> My naive implementation based
> on the current implementation `exit(2)` was regularly crashing. If
> maintainers have suggestions for better ways to handle exit_group,
> they would be greatly appreciated. 
>   * execve does not clean up the CPUs of clone'd children, for the same
> reasons as `exit_group`.
>
> Josh Kunz (5):
>   linux-user: Refactor do_fork to use new `qemu_clone`
>   linux-user: Make fd_trans task-specific.
>   linux-user: Make sigact_table part of the task state.
>   linux-user: Support CLONE_VM and extended clone options
>   linux-user: Add PDEATHSIG test for clone process hierarchy.
>
>  linux-user/Makefile.objs|   2 +-
>  linux-user/clone.c  | 565 
>  linux-user/clone.h  |  27 ++
>  linux-user/fd-trans-tbl.c   |  13 +
>  linux-user/fd-trans-type.h  |  17 +
>  linux-user/fd-trans.c   |   3 -
>  linux-user/fd-trans.h   |  75 ++--
>  linux-user/main.c   |   1 +
>  linux-user/qemu.h   |  49 +++
>  linux-user/signal.c |  84 -
>  linux-user/syscall.c| 452 --
>  tests/tcg/multiarch/Makefile.target |   3 +
>  tests/tcg/multiarch/linux-test.c| 227 ++-
>  13 files changed, 1264 insertions(+), 254 deletions(-)
>  create mode 100644 linux-user/clone.c
>  create mode 100644 linux-user/clone.h
>  create mode 100644 linux-user/fd-trans-tbl.c
>  create mode 100644 linux-user/fd-trans-type.h


-- 
Alex Bennée



[Bug 1882065] Re: Could this cause OOB bug ?

2020-06-13 Thread Thomas Huth
I think we should fix this anyway, even if it can only be triggered when
trace functions are enabled

** Description changed:

- close!
+ 
+ In function megasas_handle_scsi(hw/scsi/megasas.c):
+ 
+ ```c
+ static int megasas_handle_scsi(MegasasState *s, MegasasCmd *cmd,
+int frame_cmd)
+ {
+ 

+ cdb = cmd->frame->pass.cdb;
+ target_id = cmd->frame->header.target_id;
+ lun_id = cmd->frame->header.lun_id;
+ cdb_len = cmd->frame->header.cdb_len;
+ 

+ if (cdb_len > 16) {
+ trace_megasas_scsi_invalid_cdb_len(
+ mfi_frame_desc[frame_cmd], is_logical,
+ target_id, lun_id, cdb_len);
+ megasas_write_sense(cmd, SENSE_CODE(INVALID_OPCODE));
+ cmd->frame->header.scsi_status = CHECK_CONDITION;
+ s->event_count++;
+ return MFI_STAT_SCSI_DONE_WITH_ERROR;
+ }
+ }
+ ```
+ 
+ Two variables, frame_cmd and cdb_len, can be controlled by guest os. So
+ can mfi_frame_desc[frame_cmd] cause OOB bug ?

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

Title:
  Could this cause OOB bug ?

Status in QEMU:
  New

Bug description:

  In function megasas_handle_scsi(hw/scsi/megasas.c):

  ```c
  static int megasas_handle_scsi(MegasasState *s, MegasasCmd *cmd,
 int frame_cmd)
  {
  

  cdb = cmd->frame->pass.cdb;
  target_id = cmd->frame->header.target_id;
  lun_id = cmd->frame->header.lun_id;
  cdb_len = cmd->frame->header.cdb_len;
  

  if (cdb_len > 16) {
  trace_megasas_scsi_invalid_cdb_len(
  mfi_frame_desc[frame_cmd], is_logical,
  target_id, lun_id, cdb_len);
  megasas_write_sense(cmd, SENSE_CODE(INVALID_OPCODE));
  cmd->frame->header.scsi_status = CHECK_CONDITION;
  s->event_count++;
  return MFI_STAT_SCSI_DONE_WITH_ERROR;
  }
  }
  ```

  Two variables, frame_cmd and cdb_len, can be controlled by guest os.
  So can mfi_frame_desc[frame_cmd] cause OOB bug ?

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



Re: [PATCH v3 4/4] spapr: Forbid nested KVM-HV in pre-power9 compat mode

2020-06-13 Thread David Gibson
On Thu, Jun 11, 2020 at 03:40:33PM +0200, Greg Kurz wrote:
> Nested KVM-HV only works on POWER9.
> 
> Signed-off-by: Greg Kurz 
> Reviewed-by: Laurent Vivier 

Hrm.  I have mixed feelings about this.  It does bring forward an
error that we'd otherwise only discover when we try to load the kvm
module in the guest.

On the other hand, it's kind of a layering violation - really it's
KVM's business to report what it can and can't do, rather than having
qemu anticipate it.

Allowing POWER8 compat for an L2 is something we hope to have in the
fairly near future.  Allowing POWER8 compat for L1, which is what this
covers, is, I'll admit, likely to never happen.


> ---
>  HW/ppc/spapr_caps.c |   10 ++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
> index 27cf2b38af27..dfe3b419daaa 100644
> --- a/hw/ppc/spapr_caps.c
> +++ b/hw/ppc/spapr_caps.c
> @@ -391,6 +391,8 @@ static void cap_nested_kvm_hv_apply(SpaprMachineState 
> *spapr,
>  uint8_t val, Error **errp)
>  {
>  ERRP_AUTO_PROPAGATE();
> +PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
> +
>  if (!val) {
>  /* capability disabled by default */
>  return;
> @@ -400,6 +402,14 @@ static void cap_nested_kvm_hv_apply(SpaprMachineState 
> *spapr,
>  error_setg(errp, "No Nested KVM-HV support in TCG");
>  error_append_hint(errp, "Try appending -machine 
> cap-nested-hv=off\n");
>  } else if (kvm_enabled()) {
> +if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, 0,
> +  spapr->max_compat_pvr)) {
> +error_setg(errp, "Nested KVM-HV only supported on POWER9");
> +error_append_hint(errp,
> +  "Try appending -machine 
> max-cpu-compat=power9\n");
> +return;
> +}
> +
>  if (!kvmppc_has_cap_nested_kvm_hv()) {
>  error_setg(errp,
> "KVM implementation does not support Nested KVM-HV");
> 
> 

-- 
David Gibson| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson


signature.asc
Description: PGP signature


Re: [PATCH v3 2/4] error: auto propagated local_err

2020-06-13 Thread David Gibson
On Thu, Jun 11, 2020 at 03:40:18PM +0200, Greg Kurz wrote:
> From: Vladimir Sementsov-Ogievskiy 
> 
> Introduce a new ERRP_AUTO_PROPAGATE macro, to be used at start of
> functions with an errp OUT parameter.
> 
> It has three goals:
> 
> 1. Fix issue with error_fatal and error_prepend/error_append_hint: user
> can't see this additional information, because exit() happens in
> error_setg earlier than information is added. [Reported by Greg Kurz]
> 
> 2. Fix issue with error_abort and error_propagate: when we wrap
> error_abort by local_err+error_propagate, the resulting coredump will
> refer to error_propagate and not to the place where error happened.
> (the macro itself doesn't fix the issue, but it allows us to [3.] drop
> the 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 could be merely updated to
> return int error code).
> 
> To achieve these goals, later patches will add invocations
> of this macro at the start of functions with either use
> error_prepend/error_append_hint (solving 1) or which use
> local_err+error_propagate to check errors, switching those
> functions to use *errp instead (solving 2 and 3).
> 
> Signed-off-by: Vladimir Sementsov-Ogievskiy 
> Reviewed-by: Paul Durrant 
> Reviewed-by: Greg Kurz 
> Reviewed-by: Eric Blake 
> Signed-off-by: Greg Kurz 
> Reviewed-by: Laurent Vivier 

I don't feel terribly qualified to comment on this generic change to
the errors mechanism.  I can take it through my tree if necessary, but
I'd want an ack from Markus.

> ---
>  include/qapi/error.h |  205 
> ++
>  1 file changed, 173 insertions(+), 32 deletions(-)
> 
> diff --git a/include/qapi/error.h b/include/qapi/error.h
> index ad5b6e896ded..30140d9bfea9 100644
> --- a/include/qapi/error.h
> +++ b/include/qapi/error.h
> @@ -15,6 +15,8 @@
>  /*
>   * Error reporting system loosely patterned after Glib's GError.
>   *
> + * = Deal with Error object =
> + *
>   * Create an error:
>   * error_setg(, "situation normal, all fouled up");
>   *
> @@ -47,28 +49,91 @@
>   * reporting it (primarily useful in testsuites):
>   * error_free_or_abort();
>   *
> - * Pass an existing error to the caller:
> - * error_propagate(errp, err);
> - * where Error **errp is a parameter, by convention the last one.
> + * = Deal with Error ** function parameter =
>   *
> - * Pass an existing error to the caller with the message modified:
> - * error_propagate_prepend(errp, err);
> + * A function may use the error system to return errors. In this case, the
> + * function defines an Error **errp parameter, by convention the last one 
> (with
> + * exceptions for functions using ... or va_list).
>   *
> - * Avoid
> - * error_propagate(errp, err);
> - * error_prepend(errp, "Could not frobnicate '%s': ", name);
> - * because this fails to prepend when @errp is _fatal.
> + * The caller may then pass in the following errp values:
>   *
> - * Create a new error and pass it to the caller:
> + * 1. _abort
> + *Any error will result in abort().
> + * 2. _fatal
> + *Any error will result in exit() with a non-zero status.
> + * 3. NULL
> + *No error reporting through errp parameter.
> + * 4. The address of a NULL-initialized Error *err
> + *Any error will populate errp with an error object.
> + *
> + * The following rules then implement the correct semantics desired by the
> + * caller.
> + *
> + * Create a new error to pass to the caller:
>   * error_setg(errp, "situation normal, all fouled up");
>   *
> - * Call a function and receive an error from it:
> + * Calling another errp-based function:
> + * f(..., errp);
> + *
> + * == Checking success of subcall ==
> + *
> + * If a function returns a value indicating an error in addition to setting
> + * errp (which is recommended), then you don't need any additional code, just
> + * do:
> + *
> + * int ret = f(..., errp);
> + * if (ret < 0) {
> + * ... handle error ...
> + * return ret;
> + * }
> + *
> + * If a function returns nothing (not recommended for new code), the only way
> + * to check success is by consulting errp; doing this safely requires the use
> + * of the ERRP_AUTO_PROPAGATE macro, like this:
> + *
> + * int our_func(..., Error **errp) {
> + * ERRP_AUTO_PROPAGATE();
> + * ...
> + * subcall(..., errp);
> + * if (*errp) {
> + * ...
> + * return -EINVAL;
> + * }
> + * ...
> + * }
> + *
> + * ERRP_AUTO_PROPAGATE takes care of wrapping the original errp as needed, so
> + * that the rest of the function can directly use errp (including
> + * dereferencing), where any errors will then be propagated on to the 
> original
> + * errp when leaving 

Re: [PATCH v1 18/18] cirrus.yml: serialise make check

2020-06-13 Thread Li-Wen Hsu
On Sat, Jun 13, 2020 at 3:08 AM Alex Bennée  wrote:
>
> We do this on our other platforms to make it easier to see what has
> broken.
>
> Signed-off-by: Alex Bennée 

Reviewed-by: Li-Wen Hsu 

> ---
>  .cirrus.yml | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/.cirrus.yml b/.cirrus.yml
> index ce7850a320e..69342ae031b 100644
> --- a/.cirrus.yml
> +++ b/.cirrus.yml
> @@ -14,7 +14,7 @@ freebsd_12_task:
>  - cd build
>  - ../configure || { cat config.log; exit 1; }
>  - gmake -j8
> -- gmake -j8 V=1 check
> +- gmake V=1 check
>
>  macos_task:
>osx_instance:
> @@ -26,7 +26,7 @@ macos_task:
>  - cd build
>  - ../configure --python=/usr/local/bin/python3 || { cat config.log; exit 
> 1; }
>  - gmake -j$(sysctl -n hw.ncpu)
> -- gmake check -j$(sysctl -n hw.ncpu)
> +- gmake check
>
>  macos_xcode_task:
>osx_instance:
> @@ -39,4 +39,4 @@ macos_xcode_task:
>  - cd build
>  - ../configure --cc=clang || { cat config.log; exit 1; }
>  - gmake -j$(sysctl -n hw.ncpu)
> -- gmake check -j$(sysctl -n hw.ncpu)
> +- gmake check
> --
> 2.20.1
>



[Qemu-devel] [PATCH 2/2] target/i386: add -cpu, lbr=true support to enable guest LBR

2020-06-13 Thread Like Xu
The LBR feature would be enabled on the guest if:
- the KVM is enabled and the PMU is enabled and,
- the msr-based-feature IA32_PERF_CAPABILITIES is supporterd and,
- the supported returned value for lbr_fmt from this msr is not zero.

The LBR feature would be disabled on the guest if:
- the msr-based-feature IA32_PERF_CAPABILITIES is unsupporterd OR,
- qemu set the IA32_PERF_CAPABILITIES msr feature without lbr_fmt values OR,
- the requested guest vcpu model doesn't support PDCM.

Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Cc: "Michael S. Tsirkin" 
Cc: Marcel Apfelbaum 
Cc: Marcelo Tosatti 
Cc: qemu-devel@nongnu.org
Signed-off-by: Like Xu 
---
 hw/i386/pc.c  |  1 +
 target/i386/cpu.c | 25 +++--
 target/i386/cpu.h |  2 ++
 target/i386/kvm.c |  7 ++-
 4 files changed, 32 insertions(+), 3 deletions(-)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 2128f3d6fe..8d8d42a8ea 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -316,6 +316,7 @@ GlobalProperty pc_compat_1_5[] = {
 { "Nehalem-" TYPE_X86_CPU, "min-level", "2" },
 { "virtio-net-pci", "any_layout", "off" },
 { TYPE_X86_CPU, "pmu", "on" },
+{ TYPE_X86_CPU, "lbr", "on" },
 { "i440FX-pcihost", "short_root_bus", "0" },
 { "q35-pcihost", "short_root_bus", "0" },
 };
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index e47c9d1604..262a2595fa 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1142,8 +1142,8 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = 
{
 [FEAT_PERF_CAPABILITIES] = {
 .type = MSR_FEATURE_WORD,
 .feat_names = {
-NULL, NULL, NULL, NULL,
-NULL, NULL, NULL, NULL,
+"lbr-fmt-bit-0", "lbr-fmt-bit-1", "lbr-fmt-bit-2", "lbr-fmt-bit-3",
+"lbr-fmt-bit-4", "lbr-fmt-bit-5", NULL, NULL,
 NULL, NULL, NULL, NULL,
 NULL, "full-width-write", NULL, NULL,
 NULL, NULL, NULL, NULL,
@@ -4187,6 +4187,13 @@ static bool lmce_supported(void)
 return !!(mce_cap & MCG_LMCE_P);
 }
 
+static inline bool lbr_supported(void)
+{
+return kvm_enabled() && (PERF_CAP_LBR_FMT &
+kvm_arch_get_supported_msr_feature(kvm_state,
+   MSR_IA32_PERF_CAPABILITIES));
+}
+
 #define CPUID_MODEL_ID_SZ 48
 
 /**
@@ -4290,6 +4297,9 @@ static void max_x86_cpu_initfn(Object *obj)
 }
 
 object_property_set_bool(OBJECT(cpu), true, "pmu", _abort);
+if (lbr_supported()) {
+object_property_set_bool(OBJECT(cpu), true, "lbr", _abort);
+}
 }
 
 static const TypeInfo max_x86_cpu_type_info = {
@@ -5510,6 +5520,10 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, 
uint32_t count,
 }
 if (!cpu->enable_pmu) {
 *ecx &= ~CPUID_EXT_PDCM;
+if (cpu->enable_lbr) {
+warn_report("LBR is unsupported since guest PMU is disabled.");
+exit(1);
+}
 }
 break;
 case 2:
@@ -6528,6 +6542,12 @@ static void x86_cpu_realizefn(DeviceState *dev, Error 
**errp)
 }
 }
 
+if (!cpu->max_features && cpu->enable_lbr &&
+!(env->features[FEAT_1_ECX] & CPUID_EXT_PDCM)) {
+warn_report("requested vcpu model doesn't support PDCM for LBR.");
+exit(1);
+}
+
 if (cpu->ucode_rev == 0) {
 /* The default is the same as KVM's.  */
 if (IS_AMD_CPU(env)) {
@@ -7165,6 +7185,7 @@ static Property x86_cpu_properties[] = {
 #endif
 DEFINE_PROP_INT32("node-id", X86CPU, node_id, CPU_UNSET_NUMA_NODE_ID),
 DEFINE_PROP_BOOL("pmu", X86CPU, enable_pmu, false),
+DEFINE_PROP_BOOL("lbr", X86CPU, enable_lbr, false),
 
 DEFINE_PROP_UINT32("hv-spinlocks", X86CPU, hyperv_spinlock_attempts,
HYPERV_SPINLOCK_NEVER_RETRY),
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index fad2f874bd..e5f65e9b0c 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -357,6 +357,7 @@ typedef enum X86Seg {
 #define ARCH_CAP_TSX_CTRL_MSR  (1<<7)
 
 #define MSR_IA32_PERF_CAPABILITIES  0x345
+#define PERF_CAP_LBR_FMT  0x3f
 
 #define MSR_IA32_TSX_CTRL  0x122
 #define MSR_IA32_TSCDEADLINE0x6e0
@@ -1686,6 +1687,7 @@ struct X86CPU {
  * capabilities) directly to the guest.
  */
 bool enable_pmu;
+bool enable_lbr;
 
 /* LMCE support can be enabled/disabled via cpu option 'lmce=on/off'. It is
  * disabled by default to avoid breaking migration between QEMU with
diff --git a/target/i386/kvm.c b/target/i386/kvm.c
index 9be6f76b2c..524ae86b0c 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -2652,8 +2652,10 @@ static void kvm_msr_entry_add_perf(X86CPU *cpu, 
FeatureWordArray f)
 uint64_t kvm_perf_cap =
 kvm_arch_get_supported_msr_feature(kvm_state,
MSR_IA32_PERF_CAPABILITIES);
-
 if (kvm_perf_cap) {
+if (!cpu->enable_lbr) {
+kvm_perf_cap &= ~PERF_CAP_LBR_FMT;

[Qemu-devel] [PATCH 1/2] target/i386: define a new MSR based feature word - FEAT_PERF_CAPABILITIES

2020-06-13 Thread Like Xu
The Perfmon and Debug Capability MSR named IA32_PERF_CAPABILITIES is
a feature-enumerating MSR, which only enumerates the feature full-width
write (via bit 13) by now which indicates the processor supports IA32_A_PMCx
interface for updating bits 32 and above of IA32_PMCx.

The existence of MSR IA32_PERF_CAPABILITIES is enumerated by CPUID.1:ECX[15].

Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Cc: Marcelo Tosatti 
Cc: qemu-devel@nongnu.org
Signed-off-by: Like Xu 
Message-Id: <20200529074347.124619-5-like...@linux.intel.com>
Signed-off-by: Paolo Bonzini 
---
 target/i386/cpu.c | 23 +++
 target/i386/cpu.h |  3 +++
 target/i386/kvm.c | 20 
 3 files changed, 46 insertions(+)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 02065e35d4..e47c9d1604 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1139,6 +1139,22 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] 
= {
 .index = MSR_IA32_CORE_CAPABILITY,
 },
 },
+[FEAT_PERF_CAPABILITIES] = {
+.type = MSR_FEATURE_WORD,
+.feat_names = {
+NULL, NULL, NULL, NULL,
+NULL, NULL, NULL, NULL,
+NULL, NULL, NULL, NULL,
+NULL, "full-width-write", NULL, NULL,
+NULL, NULL, NULL, NULL,
+NULL, NULL, NULL, NULL,
+NULL, NULL, NULL, NULL,
+NULL, NULL, NULL, NULL,
+},
+.msr = {
+.index = MSR_IA32_PERF_CAPABILITIES,
+},
+},
 
 [FEAT_VMX_PROCBASED_CTLS] = {
 .type = MSR_FEATURE_WORD,
@@ -1316,6 +1332,10 @@ static FeatureDep feature_dependencies[] = {
 .from = { FEAT_7_0_EDX, CPUID_7_0_EDX_CORE_CAPABILITY },
 .to = { FEAT_CORE_CAPABILITY,   ~0ull },
 },
+{
+.from = { FEAT_1_ECX, CPUID_EXT_PDCM },
+.to = { FEAT_PERF_CAPABILITIES,   ~0ull },
+},
 {
 .from = { FEAT_1_ECX,   CPUID_EXT_VMX },
 .to = { FEAT_VMX_PROCBASED_CTLS,~0ull },
@@ -5488,6 +5508,9 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, 
uint32_t count,
 *ebx |= (cs->nr_cores * cs->nr_threads) << 16;
 *edx |= CPUID_HT;
 }
+if (!cpu->enable_pmu) {
+*ecx &= ~CPUID_EXT_PDCM;
+}
 break;
 case 2:
 /* cache info: needed for Pentium Pro compatibility */
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 408392dbf6..fad2f874bd 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -356,6 +356,8 @@ typedef enum X86Seg {
 #define MSR_IA32_ARCH_CAPABILITIES  0x10a
 #define ARCH_CAP_TSX_CTRL_MSR  (1<<7)
 
+#define MSR_IA32_PERF_CAPABILITIES  0x345
+
 #define MSR_IA32_TSX_CTRL  0x122
 #define MSR_IA32_TSCDEADLINE0x6e0
 
@@ -529,6 +531,7 @@ typedef enum FeatureWord {
 FEAT_XSAVE_COMP_HI, /* CPUID[EAX=0xd,ECX=0].EDX */
 FEAT_ARCH_CAPABILITIES,
 FEAT_CORE_CAPABILITY,
+FEAT_PERF_CAPABILITIES,
 FEAT_VMX_PROCBASED_CTLS,
 FEAT_VMX_SECONDARY_CTLS,
 FEAT_VMX_PINBASED_CTLS,
diff --git a/target/i386/kvm.c b/target/i386/kvm.c
index 34f838728d..9be6f76b2c 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -106,6 +106,7 @@ static bool has_msr_core_capabs;
 static bool has_msr_vmx_vmfunc;
 static bool has_msr_ucode_rev;
 static bool has_msr_vmx_procbased_ctls2;
+static bool has_msr_perf_capabs;
 
 static uint32_t has_architectural_pmu_version;
 static uint32_t num_architectural_pmu_gp_counters;
@@ -2027,6 +2028,9 @@ static int kvm_get_supported_msrs(KVMState *s)
 case MSR_IA32_CORE_CAPABILITY:
 has_msr_core_capabs = true;
 break;
+case MSR_IA32_PERF_CAPABILITIES:
+has_msr_perf_capabs = true;
+break;
 case MSR_IA32_VMX_VMFUNC:
 has_msr_vmx_vmfunc = true;
 break;
@@ -2643,6 +2647,18 @@ static void kvm_msr_entry_add_vmx(X86CPU *cpu, 
FeatureWordArray f)
   VMCS12_MAX_FIELD_INDEX << 1);
 }
 
+static void kvm_msr_entry_add_perf(X86CPU *cpu, FeatureWordArray f)
+{
+uint64_t kvm_perf_cap =
+kvm_arch_get_supported_msr_feature(kvm_state,
+   MSR_IA32_PERF_CAPABILITIES);
+
+if (kvm_perf_cap) {
+kvm_msr_entry_add(cpu, MSR_IA32_PERF_CAPABILITIES,
+kvm_perf_cap & f[FEAT_PERF_CAPABILITIES]);
+}
+}
+
 static int kvm_buf_set_msrs(X86CPU *cpu)
 {
 int ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, cpu->kvm_msr_buf);
@@ -2675,6 +2691,10 @@ static void kvm_init_msrs(X86CPU *cpu)
   env->features[FEAT_CORE_CAPABILITY]);
 }
 
+if (has_msr_perf_capabs && cpu->enable_pmu) {
+kvm_msr_entry_add_perf(cpu, env->features);
+}
+
 if (has_msr_ucode_rev) {
 kvm_msr_entry_add(cpu, MSR_IA32_UCODE_REV, cpu->ucode_rev);
 }
-- 
2.21.3