Re: [PATCH] replay: synchronize on every virtual timer callback

2020-05-18 Thread Pavel Dovgalyuk



On 18.05.2020 18:56, Alex Bennée wrote:

Philippe Mathieu-Daudé  writes:


+ Alex

On 5/6/20 10:17 AM, Pavel Dovgalyuk wrote:

Sometimes virtual timer callbacks depend on order
of virtual timer processing and warping of virtual clock.
Therefore every callback should be logged to make replay deterministic.
This patch creates a checkpoint before every virtual timer callback.
With these checkpoints virtual timers processing and clock warping
events order is completely deterministic.
Signed-off-by: Pavel Dovgalyuk 
---
   util/qemu-timer.c |5 +
   1 file changed, 5 insertions(+)
diff --git a/util/qemu-timer.c b/util/qemu-timer.c
index d548d3c1ad..47833f338f 100644
--- a/util/qemu-timer.c
+++ b/util/qemu-timer.c
@@ -588,6 +588,11 @@ bool timerlist_run_timers(QEMUTimerList *timer_list)
   qemu_mutex_lock(_list->active_timers_lock);
 progress = true;
+/*
+ * Callback may insert new checkpoints, therefore add new checkpoint
+ * for the virtual timers.
+ */
+need_replay_checkpoint = timer_list->clock->type == QEMU_CLOCK_VIRTUAL;
   }
   qemu_mutex_unlock(_list->active_timers_lock);

So the problem I have with this as with all the record/replay stuff I
need want to review is it's very hard to see things in action. I added a
*very* basic record/replay test to the aarch64 softmmu tests but they
won't exercise any of this code because no timers get fired. I'm
assuming the sort of tests that is really needed is something that not
only causes QEMU_CLOCK_VIRTUAL timers to fire and trigger logged HW
events and ensure that things don't get confused in the process.


I encounter most of the bugs in different OS boot scenarios.

We also have internal tests that include some computational, disk, and 
network interaction tasks.


Is it possible to add a test like booting a "real" OS and replaying it?



If I read up the file I just get more questions than answers. For
example why do we release the qemu_timers lock before processing the
replay event? Is it that the replay event could cause another timer to


We release the lock, because accessing the replay module may process 
some events and add more timers.



be consumed? That seems suspect to me given we should only be expiring
times in the run loop.

Could the code be re-factored to use QEMU_LOCK_GUARD? It's hard to know
and I really wouldn't want to try that re-factoring without some sort of
confidence we were properly exercising the semantics of record/replay
and alive to potential regressions.


QEMU_LOCK_GUARD looks nice. But we'll still need unlock/lock pairs 
around checkpoint and timer callback.




Please realise I do like the concept of record/replay and I'd love to
get more features merged (like for example the reverse debug patches).
However by it's very nature it gets it's fingers deeply intertwined with
the main run loop and we really need to better exercise the code in our
tests.

FWIW you can have an:

Acked-by: Alex Bennée 


Thanks.



which means it doesn't look obviously broken to me and it doesn't seem
to break the non-record/replay cases because that's all I can really
test.






Audio passthroguh

2020-05-18 Thread padma jain
Hi all,
  I want to understand, how we can differentiate the actual sound
card(PCI passthrough) and emulated sound card. Basically i want to check it
in qemu itself. Any suggestions?


Re: [PATCH] replay: implement fair mutex

2020-05-18 Thread Pavel Dovgalyuk



On 18.05.2020 19:07, Alex Bennée wrote:

Pavel Dovgalyuk  writes:


In record/replay icount mode main loop thread and vCPU thread
do not perform simultaneously. They take replay mutex to synchronize
the actions. Sometimes vCPU thread waits for locking the mutex for
very long time, because main loop releases the mutex and takes it
back again.

Where in the main loop do we keep bouncing the mutex like this? Surely
that is the problem we should fix?


I performed kind of profilng while replaying.

Sometimes main loop takes and releases this mutex without giving a 
chance to vCPU to work.


I also got reports about the opposite behavior from the users: vCPU 
takes and releases the mutex, and main loop stalls.





Standard qemu mutex do not provide the ordering
capabilities.

This patch adds a "queue" for replay mutex. Therefore thread ordering
becomes more "fair". Threads are executed in the same order as
they are trying to take the mutex.

Signed-off-by: Pavel Dovgalyuk 
---
  replay/replay-internal.c |   15 ++-
  1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/replay/replay-internal.c b/replay/replay-internal.c
index eba8246aae..2e8a3e947a 100644
--- a/replay/replay-internal.c
+++ b/replay/replay-internal.c
@@ -22,6 +22,9 @@
 It also protects replay events queue which stores events to be
 written or read to the log. */
  static QemuMutex lock;
+/* Condition and queue for fair ordering of mutex lock requests. */
+static QemuCond mutex_cond;
+static unsigned long mutex_head, mutex_tail;
  
  /* File for replay writing */

  static bool write_error;
@@ -197,9 +200,10 @@ static __thread bool replay_locked;
  void replay_mutex_init(void)
  {
  qemu_mutex_init();
+qemu_cond_init(_cond);
  /* Hold the mutex while we start-up */
-qemu_mutex_lock();
  replay_locked = true;
+++mutex_tail;
  }
  
  bool replay_mutex_locked(void)

@@ -211,10 +215,16 @@ bool replay_mutex_locked(void)
  void replay_mutex_lock(void)
  {
  if (replay_mode != REPLAY_MODE_NONE) {
+unsigned long id;
  g_assert(!qemu_mutex_iothread_locked());
  g_assert(!replay_mutex_locked());
  qemu_mutex_lock();
+id = mutex_tail++;
+while (id != mutex_head) {
+qemu_cond_wait(_cond, );
+}
  replay_locked = true;
+qemu_mutex_unlock();
  }
  }
  
@@ -222,7 +232,10 @@ void replay_mutex_unlock(void)

  {
  if (replay_mode != REPLAY_MODE_NONE) {
  g_assert(replay_mutex_locked());
+qemu_mutex_lock();
+++mutex_head;
  replay_locked = false;
+qemu_cond_broadcast(_cond);
  qemu_mutex_unlock();
  }
  }






Re: [PATCH 05/24] aspeed: Don't create unwanted "cortex-a7-arm-cpu" devices

2020-05-18 Thread Markus Armbruster
Joel Stanley  writes:

> On Mon, 18 May 2020 at 12:24, Cédric Le Goater  wrote:
>>
>> On 5/18/20 7:03 AM, Markus Armbruster wrote:
>> > The number of CPUs is controlled by property "num-cpus".
>> > aspeed_soc_ast2600_init() creates the maximum supported number.
>> > aspeed_soc_ast2600_realize() realizes only the wanted number.  Works,
>> > although it leaves unrealized devices hanging around in the QOM
>> > composition tree.  Affects machines ast2600-evb and tacoma-bmc.
>> >
>> > Make the init functions create only the wanted ones.  Visible in "info
>> > qom-tree"; here's the change for ast2600-evb:
>> >
>> >  /machine (ast2600-evb-machine)
>> >[...]
>> >/soc (ast2600-a1)
>> >  [...]
>> >  /cpu[0] (cortex-a7-arm-cpu)
>> >/unnamed-gpio-in[0] (irq)
>> >/unnamed-gpio-in[1] (irq)
>> >/unnamed-gpio-in[2] (irq)
>> >/unnamed-gpio-in[3] (irq)
>> > -/cpu[1] (cortex-a7-arm-cpu)
>> > -  /unnamed-gpio-in[0] (irq)
>> > -  /unnamed-gpio-in[1] (irq)
>> > -  /unnamed-gpio-in[2] (irq)
>> > -  /unnamed-gpio-in[3] (irq)
>> >  /ehci[0] (platform-ehci-usb)
>> >
>> > Cc: "Cédric Le Goater" 
>> > Cc: Peter Maydell 
>> > Cc: Andrew Jeffery 
>> > Cc: Joel Stanley 
>> > Cc: qemu-...@nongnu.org
>> > Signed-off-by: Markus Armbruster 
>>
>> Reviewed-by: Cédric Le Goater 
>>
>> Joel, Andrew,
>>
>> Shouldn't we enforce a default/min/max number of CPUs of 2 for the AST2600 ?
>> That's the SoC definition. The fact it is configurable in the Aspeed model
>> was nice to have during bringup but we are now done.
>
> Agreed, we want there to always be two CPUs for the 2600.

Follow-up patch welcome!




Re: [PATCH 04/24] aspeed: Don't create unwanted "ftgmac100", "aspeed-mmi" devices

2020-05-18 Thread Markus Armbruster
"Andrew Jeffery"  writes:

> On Mon, 18 May 2020, at 21:49, Cédric Le Goater wrote:
>> On 5/18/20 7:03 AM, Markus Armbruster wrote:
>> > These devices are optional, and controlled by @nb_nics.
>> > aspeed_soc_ast2600_init() and aspeed_soc_init() create the maximum
>> > supported number.  aspeed_soc_ast2600_realize() and
>> > aspeed_soc_realize() realize only the wanted number.  Works, although
>> > it can leave unrealized devices hanging around in the QOM composition
>> > tree.  Affects machines ast2500-evb, ast2600-evb, palmetto-bmc,
>> > romulus-bmc, swift-bmc, tacoma-bmc, and witherspoon-bmc.
>> > 
>> > Make the init functions create only the wanted ones.  Visible in "info
>> > qom-tree"; here's the change for ast2600-evb:
>> > 
>> >  /machine (ast2600-evb-machine)
>> >[...]
>> >/soc (ast2600-a1)
>> >  [...]
>> >  /ftgmac100[0] (ftgmac100)
>> >/ftgmac100[0] (qemu:memory-region)
>> > -/ftgmac100[1] (ftgmac100)
>> > -/ftgmac100[2] (ftgmac100)
>> > -/ftgmac100[3] (ftgmac100)
>> >  /gpio (aspeed.gpio-ast2600)
>> >  [...]
>> >  /mii[0] (aspeed-mmi)
>> >/aspeed-mmi[0] (qemu:memory-region)
>> > -/mii[1] (aspeed-mmi)
>> > -/mii[2] (aspeed-mmi)
>> > -/mii[3] (aspeed-mmi)
>> >  /rtc (aspeed.rtc)
>> > 
>> > I'm not sure creating @nb_nics devices makes sense.  How many does the
>> > physical chip provide?
>> 
>> The AST2400, AST2500 SoC have 2 macs and the AST2600 has 4. Each machine
>> define the one it uses, generally MAC0 but the tacoma board uses MAC3.
>> 
>> Shouldn't the model reflect the real address space independently from
>> the NIC backends defined on the command line ?  
>
> That's my feeling too, though I'm not sure what to make of the unrealised 
> devices
> in the QOM tree. Does it matter? It hasn't bothered me.

Depending on what the initialization code does, unrealized devices can
be anything from a little wasted memory to open bear trap.  I don't
really expect the latter extreme in the code, as I expect bear traps to
quickly catch the developer that set them.

I guess the unrealized devices cleaned up in this patch did no actual
harm.

Still, it's an unhealthy state, and that's why I clean it up.  "[PATCH
24/24] qdev: Assert onboard devices all get realized properly" should
ensure we stay clean.




Re: [PATCH] icount: fix shift=auto for record/replay

2020-05-18 Thread Pavel Dovgalyuk



On 18.05.2020 19:14, Alex Bennée wrote:

Pavel Dovgalyuk  writes:


This patch fixes shift=auto when record/replay is enabled.
Now user does not need to guess the best shift value.

Signed-off-by: Pavel Dovgalyuk 
---
  cpus.c |4 +++-
  1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/cpus.c b/cpus.c
index 5670c96bcf..dfb9f4717f 100644
--- a/cpus.c
+++ b/cpus.c
@@ -379,7 +379,8 @@ static void icount_adjust(void)
  
  seqlock_write_lock(_state.vm_clock_seqlock,

 _state.vm_clock_lock);
-cur_time = cpu_get_clock_locked();
+cur_time = REPLAY_CLOCK_LOCKED(REPLAY_CLOCK_VIRTUAL_RT,
+   cpu_get_clock_locked());
  cur_icount = cpu_get_icount_locked();
  
  delta = cur_icount - cur_time;

@@ -685,6 +686,7 @@ static const VMStateDescription icount_vmstate_timers = {
  .fields = (VMStateField[]) {
  VMSTATE_INT64(qemu_icount_bias, TimersState),
  VMSTATE_INT64(qemu_icount, TimersState),
+VMSTATE_INT16(icount_time_shift, TimersState),

Surely we should be bumping .version_id/.minimum_version_id here so we
error out gracefully. No recordings pre this change would work right?



You're right. But before this patch shift=auto doesn't work for RR at 
all. Therefore no recordings should exist.


I think, for other icount use cases would be better to move 
icount_time_shift to subsection and use it only when auto is enabled.





  VMSTATE_END_OF_LIST()
  },
  .subsections = (const VMStateDescription*[]) {






Re: [PATCH 04/24] aspeed: Don't create unwanted "ftgmac100", "aspeed-mmi" devices

2020-05-18 Thread Markus Armbruster
Joel Stanley  writes:

> On Mon, 18 May 2020 at 12:19, Cédric Le Goater  wrote:
>>
>> On 5/18/20 7:03 AM, Markus Armbruster wrote:
>> > These devices are optional, and controlled by @nb_nics.
>> > aspeed_soc_ast2600_init() and aspeed_soc_init() create the maximum
>> > supported number.  aspeed_soc_ast2600_realize() and
>> > aspeed_soc_realize() realize only the wanted number.  Works, although
>> > it can leave unrealized devices hanging around in the QOM composition
>> > tree.  Affects machines ast2500-evb, ast2600-evb, palmetto-bmc,
>> > romulus-bmc, swift-bmc, tacoma-bmc, and witherspoon-bmc.
>> >
>> > Make the init functions create only the wanted ones.  Visible in "info
>> > qom-tree"; here's the change for ast2600-evb:
>> >
>> >  /machine (ast2600-evb-machine)
>> >[...]
>> >/soc (ast2600-a1)
>> >  [...]
>> >  /ftgmac100[0] (ftgmac100)
>> >/ftgmac100[0] (qemu:memory-region)
>> > -/ftgmac100[1] (ftgmac100)
>> > -/ftgmac100[2] (ftgmac100)
>> > -/ftgmac100[3] (ftgmac100)
>> >  /gpio (aspeed.gpio-ast2600)
>> >  [...]
>> >  /mii[0] (aspeed-mmi)
>> >/aspeed-mmi[0] (qemu:memory-region)
>> > -/mii[1] (aspeed-mmi)
>> > -/mii[2] (aspeed-mmi)
>> > -/mii[3] (aspeed-mmi)
>> >  /rtc (aspeed.rtc)
>> >
>> > I'm not sure creating @nb_nics devices makes sense.  How many does the
>> > physical chip provide?
>>
>> The AST2400, AST2500 SoC have 2 macs and the AST2600 has 4. Each machine
>> define the one it uses, generally MAC0 but the tacoma board uses MAC3.
>>
>> Shouldn't the model reflect the real address space independently from
>> the NIC backends defined on the command line ?
>
> Agreed, the MAC hardware is present in all instances of the AST2600,
> so they should be present in qemu. Only some boards wire up a network
> device to the other side.

I guess an unwired NIC behaves as if no cable was plugged into the
external connector ("no carrier").

We can model that.

> It would be advantageous for us to be able to specify which device is
> being connected to on the command line. Currently we do this by
> connecting all devices up to the one we care about which is an ugly
> workaround.

We use -nic to configure onboard NICs.

The configuration gets deposited in nd_table[] for board code to pick
up.

Boards use nd_table[0] for their first NIC, nd_table[1] for the second,
and so forth.  How they order their NICs is part of their stable user
interface.

To leave a NIC unplugged, use -nice none.  Example: -nic none -nic user
leaves the first NIC unplugged, and plugs the second one using a user
network backend.

Say the board contains a SoC that provides four NICs, but the board
wires up only the last one.  Then board code should use nd_table[0] for
that last one.

I don't remember whether network device frontends can work without a
backend, or need a null backend.  If the latter, then board code needs
to supply such null backends.

>> How should we proceed in such cases ?

Model the physical hardware as faithfully as we can.

Follow-up patches welcome!




Re: [PATCH 02/24] display/xlnx_dp: Fix to realize "i2c-ddc" and "aux-to-i2c-bridge"

2020-05-18 Thread Markus Armbruster
Philippe Mathieu-Daudé  writes:

> On 5/18/20 12:30 PM, Peter Maydell wrote:
>> On Mon, 18 May 2020 at 06:04, Markus Armbruster  wrote:
>>>
>>> xlnx_dp_init() creates these two devices, but they're never realized.
>>> Affects machine xlnx-zcu102.
>>>
>>> I wonder how this ever worked.  If the "device becomes real only on
>>> realize" thing actually works, then we've always been missing these
>>> two devices, yet nobody noticed.
>>
>> It depends entirely on the implementation of the device.
>> If it happens to do nothing in the realize method that
>> matters

Also in the realize methods of supertypes.

>> (eg i2c-ddc has no realize method and does the limited
>> amount of initialization it needs in instance_init) then the
>> device will (by lucky accident) work just fine.

Yes.

>> We should really ideally have an assert() in the DeviceClass
>> reset that the device was realized, so we can keep this kind
>> of bug out of the codebase. (Last time I looked it wasn't obvious
>> exactly where to put the assert now that we have both legacy-reset
>> and three-phase-reset, unfortunately.)
>
> Your wish came true in the last patch of this series! #24:
> https://www.mail-archive.com/qemu-devel@nongnu.org/msg704239.html

Not exactly what Peter asked for, but hopefully close enough for
practical purposes.




Re: [PATCH 02/24] display/xlnx_dp: Fix to realize "i2c-ddc" and "aux-to-i2c-bridge"

2020-05-18 Thread Markus Armbruster
Fred Konrad  writes:

> Le 5/18/20 à 7:03 AM, Markus Armbruster a écrit :
>> xlnx_dp_init() creates these two devices, but they're never realized.
>> Affects machine xlnx-zcu102.
>>
>> I wonder how this ever worked.  If the "device becomes real only on
>> realize" thing actually works, then we've always been missing these
>> two devices, yet nobody noticed.
>
> I can't tell, but it used to work back in 2016 since these devices were 
> required
> to have a working framebuffer.

I don't doubt you.

I figure the "device becomes real only on realize" thing is actually
more myth than thing.




Re: [PATCH 01/24] arm/stm32f405: Fix realization of "stm32f2xx-adc" devices

2020-05-18 Thread Markus Armbruster
Alistair Francis  writes:

> On Sun, May 17, 2020 at 10:06 PM Markus Armbruster  wrote:
>>
>> stm32f405_soc_initfn() creates six such devices, but
>> stm32f405_soc_realize() realizes only one.  Affects machine
>> netduinoplus2.
>>
>> I wonder how this ever worked.  If the "device becomes real only on
>> realize" thing actually works, then we've always been missing five of
>> six such devices, yet nobody noticed.
>
> I must have just been testing the first ADC.
>
>>
>> Fix stm32f405_soc_realize() to realize all six.  Visible in "info
>> qtree":
>>
>>  bus: main-system-bus
>>type System
>>dev: stm32f405-soc, id ""
>>  cpu-type = "cortex-m4-arm-cpu"
>>dev: stm32f2xx-adc, id ""
>>  gpio-out "sysbus-irq" 1
>> -mmio /00ff
>> +mmio 40012000/00ff
>>dev: stm32f2xx-adc, id ""
>>  gpio-out "sysbus-irq" 1
>> -mmio /00ff
>> +mmio 40012000/00ff
>>dev: stm32f2xx-adc, id ""
>>  gpio-out "sysbus-irq" 1
>> -mmio /00ff
>> +mmio 40012000/00ff
>>dev: stm32f2xx-adc, id ""
>>  gpio-out "sysbus-irq" 1
>> -mmio /00ff
>> +mmio 40012000/00ff
>>dev: stm32f2xx-adc, id ""
>>  gpio-out "sysbus-irq" 1
>>  mmio 40012000/00ff
>>dev: stm32f2xx-adc, id ""
>>  gpio-out "sysbus-irq" 1
>> -mmio /00ff
>> +mmio 40012000/00ff
>>dev: armv7m, id ""
>>
>> The mmio addresses look suspicious.
>
> Good catch, thanks :)

I'd love to squash in corrections, but I don't know the correct
addresses.  Can you help?

>>
>> Fixes: 529fc5fd3e18ace8f739afd02dc0953354f39442
>> Cc: Alistair Francis 
>> Cc: Peter Maydell 
>> Cc: qemu-...@nongnu.org
>> Signed-off-by: Markus Armbruster 
>
> Reviewed-by: Alistair Francis 

Thanks!




Re: [PATCH v3 0/3] various: Remove unnecessary casts

2020-05-18 Thread Markus Armbruster
Cédric Le Goater  writes:

> On 5/18/20 3:17 PM, Markus Armbruster wrote:
>> Paolo Bonzini  writes:
>> 
>>> On 15/05/20 07:58, Markus Armbruster wrote:
 Philippe Mathieu-Daudé  writes:

> Remove unnecessary casts using coccinelle scripts.
>
> The CPU()/OBJECT() patches don't introduce logical change,
> The DEVICE() one removes various OBJECT_CHECK() calls.
 Queued, thanks!

 Managing expecations: I'm not a QOM maintainer, I don't want to become
 one, and I don't normally queue QOM patches :)

>>>
>>> I want to be again a QOM maintainer, but it's not the best time for me
>>> to be one.  So thanks for picking up my slack.
>> 
>> You're welcome :)
>
> Could you help me getting this patch merged ? :)
>
> http://patchwork.ozlabs.org/project/qemu-devel/patch/20200404153340.164861-1-...@kaod.org/

I have more QOM patches in the pipe, and I may well post another QOM
pull request while Paolo is busy with other stuff.  I'll consider
including other QOM patches then.  Non-trivial ones need an R-by from
Paolo, Daniel or Eduardo.




Re: [PATCH] target/i386: Fix OUTL debug output

2020-05-18 Thread Richard Henderson
On 5/17/20 4:01 AM, Philippe Mathieu-Daudé wrote:
> Fix OUTL instructions incorrectly displayed as OUTW.
> 
> Signed-off-by: Philippe Mathieu-Daudé 
> ---
>  target/i386/misc_helper.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Reviewed-by: Richard Henderson 

as far as it goes.  We should of course never be printing to stderr, but
logging or tracing.


r~



Re: [PATCH Kernel v21 0/8] Add UAPIs to support migration for VFIO devices

2020-05-18 Thread Xiang Zheng
Thank you very much, Kirti and Yan!

On 2020/5/18 11:36, Yan Zhao wrote:
> On Mon, May 18, 2020 at 10:39:52AM +0800, Xiang Zheng wrote:
>> Hi Kirti and Yan,
>>
>> How can I test this patch series on my SR-IOV devices?
>> I have looked through Yan's pathes for i40e VF live migration support:
>> https://patchwork.kernel.org/patch/11375177/
>>
> I just updated the patches to v4.
> https://patchwork.kernel.org/cover/11554617/.
> 
> It's based on v17 kernel + v16 qemu with some minor changes in qemu.
> 
>> However, I cannot find the detailed implementation about device state
>> saving/restoring and dirty page logging. Has i40e hardware already supported
>> these two features?
>>
> In v4, vendor driver for i40e vf reports dirty pages to vfio container.
> the detailed implementation of identifying dirty pages and device state
> is not sent yet for process reason.
> We use a software way to get dirty pages i.e. dynamically trapping of BAR 0.

Sounds interesting, is the dirty pages tracking done in the VM's vf driver or
in the host's vf-migration module? It seems done in the host side, but I still
cannot understand how dynamically trapping of BAR 0 can track the dirty pages.

> 
> Thanks
> Yan
>> And if once a device supports both features, how to implement live
>> migration for this device via this series patch?
>>
>> On 2020/5/16 5:13, Kirti Wankhede wrote:
>>> Hi,
>>>
>>> This patch set adds:
>>> * IOCTL VFIO_IOMMU_DIRTY_PAGES to get dirty pages bitmap with
>>>   respect to IOMMU container rather than per device. All pages pinned by
>>>   vendor driver through vfio_pin_pages external API has to be marked as
>>>   dirty during  migration. When IOMMU capable device is present in the
>>>   container and all pages are pinned and mapped, then all pages are marked
>>>   dirty.
>>>   When there are CPU writes, CPU dirty page tracking can identify dirtied
>>>   pages, but any page pinned by vendor driver can also be written by
>>>   device. As of now there is no device which has hardware support for
>>>   dirty page tracking. So all pages which are pinned should be considered
>>>   as dirty.
>>>   This ioctl is also used to start/stop dirty pages tracking for pinned and
>>>   unpinned pages while migration is active.
>>>
>>> * Updated IOCTL VFIO_IOMMU_UNMAP_DMA to get dirty pages bitmap before
>>>   unmapping IO virtual address range.
>>>   With vIOMMU, during pre-copy phase of migration, while CPUs are still
>>>   running, IO virtual address unmap can happen while device still keeping
>>>   reference of guest pfns. Those pages should be reported as dirty before
>>>   unmap, so that VFIO user space application can copy content of those
>>>   pages from source to destination.
>>>
>>> * Patch 8 detect if IOMMU capable device driver is smart to report pages
>>>   to be marked dirty by pinning pages using vfio_pin_pages() API.
>>>
>>>
>>> Yet TODO:
>>> Since there is no device which has hardware support for system memmory
>>> dirty bitmap tracking, right now there is no other API from vendor driver
>>> to VFIO IOMMU module to report dirty pages. In future, when such hardware
>>> support will be implemented, an API will be required such that vendor
>>> driver could report dirty pages to VFIO module during migration phases.
>>>
>>> Adding revision history from previous QEMU patch set to understand KABI
>>> changes done till now
>>>
>>> v20 -> v21
>>> - Added checkin for GET_BITMAP ioctl for vfio_dma boundaries.
>>> - Updated unmap ioctl function - as suggested by Alex.
>>> - Updated comments in DIRTY_TRACKING ioctl definition - as suggested by
>>>   Cornelia.
>>>
>>> v19 -> v20
>>> - Fixed ioctl to get dirty bitmap to get bitmap of multiple vfio_dmas
>>> - Fixed unmap ioctl to get dirty bitmap of multiple vfio_dmas.
>>> - Removed flag definition from migration capability.
>>>
>>> v18 -> v19
>>> - Updated migration capability with supported page sizes bitmap for dirty
>>>   page tracking and  maximum bitmap size supported by kernel module.
>>> - Added patch to calculate and cache pgsize_bitmap when iommu->domain_list
>>>   is updated.
>>> - Removed extra buffers added in previous version for bitmap manipulation
>>>   and optimised the code.
>>>
>>> v17 -> v18
>>> - Add migration capability to the capability chain for VFIO_IOMMU_GET_INFO
>>>   ioctl
>>> - Updated UMAP_DMA ioctl to return bitmap of multiple vfio_dma
>>>
>>> v16 -> v17
>>> - Fixed errors reported by kbuild test robot  on i386
>>>
>>> v15 -> v16
>>> - Minor edits and nit picks (Auger Eric)
>>> - On copying bitmap to user, re-populated bitmap only for pinned pages,
>>>   excluding unmapped pages and CPU dirtied pages.
>>> - Patches are on tag: next-20200318 and 1-3 patches from Yan's series
>>>   https://lkml.org/lkml/2020/3/12/1255
>>>
>>> v14 -> v15
>>> - Minor edits and nit picks.
>>> - In the verification of user allocated bitmap memory, added check of
>>>maximum size.
>>> - Patches are on tag: next-20200318 and 1-3 patches from Yan's series
>>>   

[RISU v2 16/17] aarch64: Reorg sve reginfo to save space

2020-05-18 Thread Richard Henderson
Mirror the signal frame by storing all of the registers
as a lump.  Use the signal macros to pull out the values.

Signed-off-by: Richard Henderson 
---
 risu_reginfo_aarch64.h |  16 +
 risu_reginfo_aarch64.c | 135 +
 2 files changed, 73 insertions(+), 78 deletions(-)

diff --git a/risu_reginfo_aarch64.h b/risu_reginfo_aarch64.h
index c33b86f..01076b4 100644
--- a/risu_reginfo_aarch64.h
+++ b/risu_reginfo_aarch64.h
@@ -17,20 +17,8 @@
 
 struct simd_reginfo {
 __uint128_t vregs[32];
-char end[0];
 };
 
-#ifdef SVE_MAGIC
-struct sve_reginfo {
-/* SVE */
-uint16_tvl; /* current VL */
-__uint128_t zregs[SVE_NUM_ZREGS][SVE_VQ_MAX];
-uint16_tpregs[SVE_NUM_PREGS][SVE_VQ_MAX];
-uint16_tffr[SVE_VQ_MAX];
-char end[0];
-};
-#endif
-
 /* The kernel headers set this based on future arch extensions.
The current arch maximum is 16.  Save space below.  */
 #undef SVE_VQ_MAX
@@ -47,11 +35,13 @@ struct reginfo {
 /* FP/SIMD */
 uint32_t fpsr;
 uint32_t fpcr;
+uint32_t sve_vl;
 
 union {
 struct simd_reginfo simd;
 #ifdef SVE_MAGIC
-struct sve_reginfo sve;
+char sve[SVE_SIG_CONTEXT_SIZE(16) - SVE_SIG_REGS_OFFSET]
+__attribute__((aligned(16)));
 #endif
 };
 };
diff --git a/risu_reginfo_aarch64.c b/risu_reginfo_aarch64.c
index 7044648..a1020ac 100644
--- a/risu_reginfo_aarch64.c
+++ b/risu_reginfo_aarch64.c
@@ -71,15 +71,30 @@ void process_arch_opt(int opt, const char *arg)
 
 int reginfo_size(struct reginfo *ri)
 {
-int size = offsetof(struct reginfo, simd.end);
 #ifdef SVE_MAGIC
-if (test_sve) {
-size = offsetof(struct reginfo, sve.end);
+if (ri->sve_vl) {
+int vq = sve_vq_from_vl(ri->sve_vl);
+return (offsetof(struct reginfo, sve) +
+SVE_SIG_CONTEXT_SIZE(vq) - SVE_SIG_REGS_OFFSET);
 }
 #endif
-return size;
+return offsetof(struct reginfo, simd) + sizeof(ri->simd);
 }
 
+#ifdef SVE_MAGIC
+static uint64_t *reginfo_zreg(struct reginfo *ri, int vq, int i)
+{
+return (uint64_t *)(ri->sve + SVE_SIG_ZREG_OFFSET(vq, i) -
+SVE_SIG_REGS_OFFSET);
+}
+
+static uint16_t *reginfo_preg(struct reginfo *ri, int vq, int i)
+{
+return (uint16_t *)(ri->sve + SVE_SIG_PREG_OFFSET(vq, i) -
+SVE_SIG_REGS_OFFSET);
+}
+#endif
+
 /* reginfo_init: initialize with a ucontext */
 void reginfo_init(struct reginfo *ri, ucontext_t *uc)
 {
@@ -152,8 +167,6 @@ void reginfo_init(struct reginfo *ri, ucontext_t *uc)
 return;
 }
 
-ri->sve.vl = sve->vl;
-
 if (sve->head.size < SVE_SIG_CONTEXT_SIZE(vq)) {
 if (sve->head.size == sizeof(*sve)) {
 /* SVE state is empty -- not an error.  */
@@ -164,24 +177,9 @@ void reginfo_init(struct reginfo *ri, ucontext_t *uc)
 return;
 }
 
-/* Copy ZREG's one at a time */
-for (i = 0; i < SVE_NUM_ZREGS; i++) {
-memcpy(>sve.zregs[i],
-   (void *)sve + SVE_SIG_ZREG_OFFSET(vq, i),
-   SVE_SIG_ZREG_SIZE(vq));
-}
-
-/* Copy PREG's one at a time */
-for (i = 0; i < SVE_NUM_PREGS; i++) {
-memcpy(>sve.pregs[i],
-   (void *)sve + SVE_SIG_PREG_OFFSET(vq, i),
-   SVE_SIG_PREG_SIZE(vq));
-}
-
-/* Finally the FFR */
-memcpy(>sve.ffr, (void *)sve + SVE_SIG_FFR_OFFSET(vq),
-   SVE_SIG_FFR_SIZE(vq));
-
+ri->sve_vl = sve->vl;
+memcpy(ri->sve, (char *)sve + SVE_SIG_REGS_OFFSET,
+   SVE_SIG_CONTEXT_SIZE(vq) - SVE_SIG_REGS_OFFSET);
 return;
 }
 #endif /* SVE_MAGIC */
@@ -225,18 +223,20 @@ static void sve_dump_preg_diff(FILE *f, int vq, const 
uint16_t *p1,
 fprintf(f, "\n");
 }
 
-static void sve_dump_zreg_diff(FILE *f, int vq, const __uint128_t *z1,
-   const __uint128_t *z2)
+static void sve_dump_zreg_diff(FILE *f, int vq, const uint64_t *za,
+   const uint64_t *zb)
 {
 const char *pad = "";
 int q;
 
 for (q = 0; q < vq; ++q) {
-if (z1[q] != z2[q]) {
+uint64_t za0 = za[2 * q], za1 = za[2 * q + 1];
+uint64_t zb0 = zb[2 * q], zb1 = zb[2 * q + 1];
+
+if (za0 != zb0 || za1 != zb1) {
 fprintf(f, "%sq%-2d: %016" PRIx64 "%016" PRIx64
-" vs %016" PRIx64 "%016" PRIx64"\n", pad, q,
-(uint64_t)(z1[q] >> 64), (uint64_t)z1[q],
-(uint64_t)(z2[q] >> 64), (uint64_t)z2[q]);
+" vs %016" PRIx64 "%016" PRIx64"\n",
+pad, q, za1, za0, zb1, zb0);
 pad = "  ";
 }
 }
@@ -263,28 +263,30 @@ int reginfo_dump(struct reginfo *ri, FILE * f)
 if (test_sve) {
 int q, vq = test_sve;
 
-fprintf(f, "  vl : %d\n", ri->sve.vl);
+fprintf(f, "  vl : %d\n", 

[RISU v2 17/17] Add --dump option to inspect trace files

2020-05-18 Thread Richard Henderson
Adjust some of the aarch64 code to look at the reginfo struct
instead of looking at test_sve, so that we do not need to pass
the --test-sve option in order to dump sve trace files.

Signed-off-by: Richard Henderson 
---
 risu.h |   1 +
 risu.c | 108 -
 risu_reginfo_aarch64.c |  55 +
 risu_reginfo_arm.c |   4 ++
 risu_reginfo_i386.c|   4 ++
 risu_reginfo_m68k.c|   4 ++
 risu_reginfo_ppc64.c   |   4 ++
 7 files changed, 159 insertions(+), 21 deletions(-)

diff --git a/risu.h b/risu.h
index 054cef7..3bfe765 100644
--- a/risu.h
+++ b/risu.h
@@ -23,6 +23,7 @@
 extern const struct option * const arch_long_opts;
 extern const char * const arch_extra_help;
 void process_arch_opt(int opt, const char *arg);
+void arch_init(void);
 #define FIRST_ARCH_OPT   0x100
 
 /* GCC computed include to pull in the correct risu_reginfo_*.h for
diff --git a/risu.c b/risu.c
index 95b4674..d7c7556 100644
--- a/risu.c
+++ b/risu.c
@@ -249,6 +249,93 @@ static int apprentice(void)
 }
 }
 
+static int dump_trace(void)
+{
+trace_header_t header;
+union {
+struct reginfo ri;
+unsigned char memblock[MEMBLOCKLEN];
+} u;
+const char *op_name;
+
+while (1) {
+if (read_buffer(, sizeof(header))) {
+fprintf(stderr, "Trace header read failed\n");
+return EXIT_FAILURE;
+}
+
+if (header.magic != RISU_MAGIC) {
+fprintf(stderr, "Unexpected header magic (%#x)\n", header.magic);
+return EXIT_FAILURE;
+}
+
+switch (header.risu_op) {
+case OP_COMPARE:
+   op_name = "COMPARE";
+   break;
+case OP_TESTEND:
+   op_name = "TESTEND";
+   break;
+case OP_SETMEMBLOCK:
+   op_name = "SETMEMBLOCK";
+   break;
+case OP_GETMEMBLOCK:
+   op_name = "GETMEMBLOCK";
+   break;
+case OP_COMPAREMEM:
+   op_name = "COMPAREMEM";
+   break;
+case OP_SIGILL:
+   op_name = "SIGILL";
+   break;
+default:
+   op_name = "";
+   break;
+}
+
+switch (header.risu_op) {
+case OP_COMPARE:
+case OP_TESTEND:
+case OP_SIGILL:
+if (header.size > sizeof(u.ri)) {
+fprintf(stderr, "Unexpected trace size (%u)\n", header.size);
+return EXIT_FAILURE;
+}
+if (read_buffer(, header.size)) {
+fprintf(stderr, "Reginfo read failed\n");
+return EXIT_FAILURE;
+}
+if (header.size != reginfo_size()) {
+fprintf(stderr, "Unexpected trace size (%u)\n", header.size);
+return EXIT_FAILURE;
+}
+printf("%s: (pc %#lx)\n", op_name, (unsigned long)header.pc);
+reginfo_dump(, stdout);
+putchar('\n');
+if (header.risu_op == OP_TESTEND) {
+return EXIT_SUCCESS;
+}
+break;
+
+case OP_COMPAREMEM:
+if (header.size != MEMBLOCKLEN) {
+fprintf(stderr, "Unexpected trace size (%u)\n", header.size);
+return EXIT_FAILURE;
+}
+if (read_buffer(, MEMBLOCKLEN)) {
+fprintf(stderr, "Memblock read failed\n");
+return EXIT_FAILURE;
+}
+/* TODO: Dump 8k of data? */
+/* fall through */
+
+default:
+printf("%s\n", op_name);
+break;
+}
+}
+}
+
 static int ismaster;
 
 static void usage(void)
@@ -261,6 +348,7 @@ static void usage(void)
 fprintf(stderr, "between master and apprentice risu processes.\n\n");
 fprintf(stderr, "Options:\n");
 fprintf(stderr, "  --master  Be the master (server)\n");
+fprintf(stderr, "  -d, --dump=FILE   Dump " TRACE_TYPE " trace file\n");
 fprintf(stderr, "  -t, --trace=FILE  Record/playback " TRACE_TYPE " trace 
file\n");
 fprintf(stderr,
 "  -h, --host=HOST   Specify master host machine (apprentice only)"
@@ -281,11 +369,12 @@ static struct option * setup_options(char **short_opts)
 {"host", required_argument, 0, 'h'},
 {"port", required_argument, 0, 'p'},
 {"trace", required_argument, 0, 't'},
+{"dump", required_argument, 0, 'd'},
 {0, 0, 0, 0}
 };
 struct option *lopts = _longopts[0];
 
-*short_opts = "h:p:t:";
+*short_opts = "d:h:p:t:";
 
 if (arch_long_opts) {
 const size_t osize = sizeof(struct option);
@@ -316,6 +405,7 @@ int main(int argc, char **argv)
 char *trace_fn = NULL;
 struct option *longopts;
 char *shortopts;
+bool dump = false;
 
 longopts = setup_options();
 
@@ -330,6 +420,10 @@ int main(int argc, char **argv)
 case 0:
 /* flag set by getopt_long, do nothing */
 

[RISU v2 10/17] Pass non-OK result back through siglongjmp

2020-05-18 Thread Richard Henderson
Rather than doing some work in the signal handler and
some work outside, move all of the non-resume work outside.
This works because we arranged for RES_OK to be 0, which
is the normal return from sigsetjmp.

Signed-off-by: Richard Henderson 
---
 risu.c | 50 --
 1 file changed, 24 insertions(+), 26 deletions(-)

diff --git a/risu.c b/risu.c
index 78c6b8f..d09ac0b 100644
--- a/risu.c
+++ b/risu.c
@@ -107,15 +107,10 @@ static void master_sigill(int sig, siginfo_t *si, void 
*uc)
 } else {
 r = recv_and_compare_register_info(uc);
 }
-
-switch (r) {
-case RES_OK:
-/* match OK */
+if (r == RES_OK) {
 advance_pc(uc);
-return;
-default:
-/* mismatch, or end of test */
-siglongjmp(jmpbuf, 1);
+} else {
+siglongjmp(jmpbuf, r);
 }
 }
 
@@ -129,21 +124,10 @@ static void apprentice_sigill(int sig, siginfo_t *si, 
void *uc)
 } else {
 r = send_register_info(uc);
 }
-
-switch (r) {
-case RES_OK:
-/* match OK */
+if (r == RES_OK) {
 advance_pc(uc);
-return;
-case RES_END:
-/* end of test */
-exit(EXIT_SUCCESS);
-default:
-/* mismatch */
-if (trace) {
-siglongjmp(jmpbuf, 1);
-}
-exit(EXIT_FAILURE);
+} else {
+siglongjmp(jmpbuf, r);
 }
 }
 
@@ -200,7 +184,9 @@ static void load_image(const char *imgfile)
 
 static int master(void)
 {
-if (sigsetjmp(jmpbuf, 1)) {
+RisuResult res = sigsetjmp(jmpbuf, 1);
+
+if (res != RES_OK) {
 #ifdef HAVE_ZLIB
 if (trace && comm_fd != STDOUT_FILENO) {
 gzclose(gz_trace_file);
@@ -226,15 +212,27 @@ static int master(void)
 
 static int apprentice(void)
 {
-if (sigsetjmp(jmpbuf, 1)) {
+RisuResult res = sigsetjmp(jmpbuf, 1);
+
+if (res != RES_OK) {
 #ifdef HAVE_ZLIB
 if (trace && comm_fd != STDIN_FILENO) {
 gzclose(gz_trace_file);
 }
 #endif
 close(comm_fd);
-fprintf(stderr, "finished early after %zd checkpoints\n", 
signal_count);
-return report_match_status(true);
+
+switch (res) {
+case RES_END:
+return EXIT_SUCCESS;
+default:
+if (!trace) {
+return EXIT_FAILURE;
+}
+fprintf(stderr, "finished early after %zd checkpoints\n",
+signal_count);
+return report_match_status(true);
+}
 }
 set_sigill_handler(_sigill);
 fprintf(stderr, "starting apprentice image at 0x%"PRIxPTR"\n",
-- 
2.20.1




[RISU v2 14/17] Add magic and size to the trace header

2020-05-18 Thread Richard Henderson
Sanity check that we're not getting out of sync with
the trace stream.  This will be especially bad with
the change in size of the sve save data.

Signed-off-by: Richard Henderson 
---
 risu.h|   8 ++-
 reginfo.c | 160 --
 risu.c|   6 ++
 3 files changed, 143 insertions(+), 31 deletions(-)

diff --git a/risu.h b/risu.h
index b234f93..eeb6775 100644
--- a/risu.h
+++ b/risu.h
@@ -56,6 +56,7 @@ typedef enum {
 RES_END,
 RES_MISMATCH_REG,
 RES_MISMATCH_MEM,
+RES_MISMATCH_HEAD,
 RES_BAD_IO,
 } RisuResult;
 
@@ -70,10 +71,14 @@ typedef enum {
 struct reginfo;
 
 typedef struct {
-   uintptr_t pc;
+   uint32_t magic;
+   uint32_t size;
uint32_t risu_op;
+   uintptr_t pc;
 } trace_header_t;
 
+#define RISU_MAGIC  (('R' << 24) | ('i' << 16) | ('S' << 8) | 'u')
+
 /* Socket related routines */
 int master_connect(int port);
 int apprentice_connect(const char *hostname, int port);
@@ -111,6 +116,7 @@ RisuResult recv_and_compare_register_info(void *uc);
  * done in recv_and_compare_register_info().
  */
 void report_mismatch_reg(void);
+void report_mismatch_header(void);
 
 /* Interface provided by CPU-specific code: */
 
diff --git a/reginfo.c b/reginfo.c
index a007f16..f187d9c 100644
--- a/reginfo.c
+++ b/reginfo.c
@@ -16,6 +16,7 @@
 
 static struct reginfo master_ri, apprentice_ri;
 static uint8_t master_memblock[MEMBLOCKLEN];
+static trace_header_t master_header;
 
 RisuResult send_register_info(void *uc)
 {
@@ -23,32 +24,57 @@ RisuResult send_register_info(void *uc)
 trace_header_t header;
 RisuResult res;
 RisuOp op;
+void *extra;
 
 reginfo_init(, uc);
 op = get_risuop();
 
 /* Write a header with PC/op to keep in sync */
+header.magic = RISU_MAGIC;
 header.pc = get_pc();
 header.risu_op = op;
+
+switch (op) {
+case OP_TESTEND:
+case OP_COMPARE:
+case OP_SIGILL:
+header.size = reginfo_size();
+extra = 
+break;
+
+case OP_SETMEMBLOCK:
+case OP_GETMEMBLOCK:
+header.size = 0;
+extra = NULL;
+break;
+
+case OP_COMPAREMEM:
+header.size = MEMBLOCKLEN;
+extra = memblock;
+break;
+
+default:
+abort();
+}
+
 res = write_buffer(, sizeof(header));
 if (res != RES_OK) {
 return res;
 }
+if (extra) {
+res = write_buffer(extra, header.size);
+if (res != RES_OK) {
+return res;
+}
+}
 
 switch (op) {
 case OP_COMPARE:
-case OP_TESTEND:
 case OP_SIGILL:
-/*
- * Do a simple register compare on (a) explicit request
- * (b) end of test (c) a non-risuop UNDEF
- */
-res = write_buffer(, reginfo_size());
-/* For OP_TEST_END, force exit. */
-if (res == RES_OK && op == OP_TESTEND) {
-res = RES_END;
-}
+case OP_COMPAREMEM:
 break;
+case OP_TESTEND:
+return RES_END;
 case OP_SETMEMBLOCK:
 memblock = (void *)(uintptr_t)get_reginfo_paramreg();
 break;
@@ -56,12 +82,10 @@ RisuResult send_register_info(void *uc)
 set_ucontext_paramreg(uc,
   get_reginfo_paramreg() + (uintptr_t)memblock);
 break;
-case OP_COMPAREMEM:
-return write_buffer(memblock, MEMBLOCKLEN);
 default:
 abort();
 }
-return res;
+return RES_OK;
 }
 
 /* Read register info from the socket and compare it with that from the
@@ -75,34 +99,48 @@ RisuResult send_register_info(void *uc)
 RisuResult recv_and_compare_register_info(void *uc)
 {
 RisuResult res;
-trace_header_t header;
+size_t extra_size;
 RisuOp op;
 
 reginfo_init(_ri, uc);
 op = get_risuop(_ri);
 
-res = read_buffer(, sizeof(header));
-if (res != RES_OK) {
-return res;
+switch (op) {
+case OP_TESTEND:
+case OP_COMPARE:
+case OP_SIGILL:
+extra_size = reginfo_size();
+break;
+case OP_SETMEMBLOCK:
+case OP_GETMEMBLOCK:
+extra_size = 0;
+break;
+case OP_COMPAREMEM:
+extra_size = MEMBLOCKLEN;
+break;
+default:
+abort();
 }
 
-if (header.risu_op != op) {
-/* We are out of sync.  Tell master to exit. */
-respond(RES_END);
-return RES_BAD_IO;
+res = read_buffer(_header, sizeof(master_header));
+if (res != RES_OK) {
+goto fail_header;
+}
+if (master_header.magic != RISU_MAGIC ||
+master_header.risu_op != op ||
+master_header.size != extra_size) {
+res = RES_MISMATCH_HEAD;
+goto fail_header;
 }
 
 /* send OK for the header */
 respond(RES_OK);
 
 switch (op) {
-case OP_COMPARE:
 case OP_TESTEND:
+case OP_COMPARE:
 case OP_SIGILL:
-/* Do a simple register compare on (a) explicit request
- * (b) end of test (c) a non-risuop UNDEF
- */
-res = 

[RISU v2 11/17] Always write for --master

2020-05-18 Thread Richard Henderson
For trace, master of course must write to the file we create.

For sockets, we can report mismatches from either end.  At present,
we are reporting mismatches from master.  Reverse that so that we
report mismatches from the apprentice, just as we do for trace.

Signed-off-by: Richard Henderson 
---
 risu.h|  2 +-
 reginfo.c | 38 --
 risu.c| 96 ++-
 3 files changed, 61 insertions(+), 75 deletions(-)

diff --git a/risu.h b/risu.h
index f44b781..2ded5c4 100644
--- a/risu.h
+++ b/risu.h
@@ -111,7 +111,7 @@ RisuResult recv_and_compare_register_info(void *uc);
  * Should return 0 if it was a good match (ie end of test)
  * and 1 for a mismatch.
  */
-int report_match_status(bool trace);
+int report_match_status(void);
 
 /* Interface provided by CPU-specific code: */
 
diff --git a/reginfo.c b/reginfo.c
index fee025e..c37c5df 100644
--- a/reginfo.c
+++ b/reginfo.c
@@ -14,9 +14,8 @@
 #include 
 #include "risu.h"
 
-struct reginfo master_ri, apprentice_ri;
-
-uint8_t apprentice_memblock[MEMBLOCKLEN];
+static struct reginfo master_ri, apprentice_ri;
+static uint8_t master_memblock[MEMBLOCKLEN];
 
 static int mem_used;
 static int packet_mismatch;
@@ -82,8 +81,8 @@ RisuResult recv_and_compare_register_info(void *uc)
 trace_header_t header;
 RisuOp op;
 
-reginfo_init(_ri, uc);
-op = get_risuop(_ri);
+reginfo_init(_ri, uc);
+op = get_risuop(_ri);
 
 res = read_buffer(, sizeof(header));
 if (res != RES_OK) {
@@ -107,7 +106,7 @@ RisuResult recv_and_compare_register_info(void *uc)
 /* Do a simple register compare on (a) explicit request
  * (b) end of test (c) a non-risuop UNDEF
  */
-res = read_buffer(_ri, reginfo_size());
+res = read_buffer(_ri, reginfo_size());
 if (res != RES_OK) {
 packet_mismatch = 1;
 } else if (!reginfo_is_eq(_ri, _ri)) {
@@ -119,18 +118,18 @@ RisuResult recv_and_compare_register_info(void *uc)
 respond(res);
 break;
 case OP_SETMEMBLOCK:
-memblock = (void *)(uintptr_t)get_reginfo_paramreg(_ri);
+memblock = (void *)(uintptr_t)get_reginfo_paramreg(_ri);
 break;
 case OP_GETMEMBLOCK:
-set_ucontext_paramreg(uc, get_reginfo_paramreg(_ri) +
+set_ucontext_paramreg(uc, get_reginfo_paramreg(_ri) +
   (uintptr_t)memblock);
 break;
 case OP_COMPAREMEM:
 mem_used = 1;
-res = read_buffer(apprentice_memblock, MEMBLOCKLEN);
+res = read_buffer(master_memblock, MEMBLOCKLEN);
 if (res != RES_OK) {
 packet_mismatch = 1;
-} else if (memcmp(memblock, apprentice_memblock, MEMBLOCKLEN) != 0) {
+} else if (memcmp(memblock, master_memblock, MEMBLOCKLEN) != 0) {
 /* memory mismatch */
 res = RES_MISMATCH;
 }
@@ -149,18 +148,13 @@ RisuResult recv_and_compare_register_info(void *uc)
  * Should return 0 if it was a good match (ie end of test)
  * and 1 for a mismatch.
  */
-int report_match_status(bool trace)
+int report_match_status(void)
 {
 int resp = 0;
 fprintf(stderr, "match status...\n");
 if (packet_mismatch) {
 fprintf(stderr, "packet mismatch (probably disagreement "
 "about UNDEF on load/store)\n");
-/* We don't have valid reginfo from the apprentice side
- * so stop now rather than printing anything about it.
- */
-fprintf(stderr, "%s reginfo:\n", trace ? "this" : "master");
-reginfo_dump(_ri, stderr);
 return 1;
 }
 if (!reginfo_is_eq(_ri, _ri)) {
@@ -168,7 +162,7 @@ int report_match_status(bool trace)
 resp = 1;
 }
 if (mem_used
-&& memcmp(memblock, _memblock, MEMBLOCKLEN) != 0) {
+&& memcmp(memblock, _memblock, MEMBLOCKLEN) != 0) {
 fprintf(stderr, "mismatch on memory!\n");
 resp = 1;
 }
@@ -177,15 +171,11 @@ int report_match_status(bool trace)
 return 0;
 }
 
-fprintf(stderr, "%s reginfo:\n", trace ? "this" : "master");
+fprintf(stderr, "master reginfo:\n");
 reginfo_dump(_ri, stderr);
-fprintf(stderr, "%s reginfo:\n", trace ? "trace" : "apprentice");
+fprintf(stderr, "apprentice reginfo:\n");
 reginfo_dump(_ri, stderr);
 
-if (trace) {
-reginfo_dump_mismatch(_ri, _ri, stderr);
-} else {
-reginfo_dump_mismatch(_ri, _ri, stderr);
-}
+reginfo_dump_mismatch(_ri, _ri, stderr);
 return resp;
 }
diff --git a/risu.c b/risu.c
index d09ac0b..ea4b4d3 100644
--- a/risu.c
+++ b/risu.c
@@ -102,11 +102,7 @@ static void master_sigill(int sig, siginfo_t *si, void *uc)
 RisuResult r;
 signal_count++;
 
-if (trace) {
-r = send_register_info(uc);
-} else {
-r = recv_and_compare_register_info(uc);
-}
+r = send_register_info(uc);
 if (r == RES_OK) {
 advance_pc(uc);
 } else {
@@ -119,11 

[RISU v2 13/17] Split RES_MISMATCH for registers and memory

2020-05-18 Thread Richard Henderson
By remembering the specific comparison that failed, we do not
have to try again when it comes time to report.  This makes
the mem_used flag redundant.  Also, packet_mismatch is now
redundant with RES_BAD_IO.

This means that the only thing that report_match_status does
is to report on register status, so rename to report_mismatch_reg.
Also, we know there is a failure, so don't return a status from
the report.

Signed-off-by: Richard Henderson 
---
 risu.h| 13 ++---
 reginfo.c | 45 -
 risu.c| 10 +++---
 3 files changed, 21 insertions(+), 47 deletions(-)

diff --git a/risu.h b/risu.h
index 2ded5c4..b234f93 100644
--- a/risu.h
+++ b/risu.h
@@ -54,7 +54,8 @@ typedef enum {
 typedef enum {
 RES_OK = 0,
 RES_END,
-RES_MISMATCH,
+RES_MISMATCH_REG,
+RES_MISMATCH_MEM,
 RES_BAD_IO,
 } RisuResult;
 
@@ -105,13 +106,11 @@ RisuResult send_register_info(void *uc);
  */
 RisuResult recv_and_compare_register_info(void *uc);
 
-/* Print a useful report on the status of the last comparison
- * done in recv_and_compare_register_info(). This is called on
- * exit, so need not restrict itself to signal-safe functions.
- * Should return 0 if it was a good match (ie end of test)
- * and 1 for a mismatch.
+/*
+ * Print a useful report on the status of the last reg comparison
+ * done in recv_and_compare_register_info().
  */
-int report_match_status(void);
+void report_mismatch_reg(void);
 
 /* Interface provided by CPU-specific code: */
 
diff --git a/reginfo.c b/reginfo.c
index 31bc699..a007f16 100644
--- a/reginfo.c
+++ b/reginfo.c
@@ -17,9 +17,6 @@
 static struct reginfo master_ri, apprentice_ri;
 static uint8_t master_memblock[MEMBLOCKLEN];
 
-static int mem_used;
-static int packet_mismatch;
-
 RisuResult send_register_info(void *uc)
 {
 struct reginfo ri;
@@ -107,10 +104,10 @@ RisuResult recv_and_compare_register_info(void *uc)
  */
 res = read_buffer(_ri, reginfo_size());
 if (res != RES_OK) {
-packet_mismatch = 1;
+/* fail */
 } else if (!reginfo_is_eq(_ri, _ri)) {
 /* register mismatch */
-res = RES_MISMATCH;
+res = RES_MISMATCH_REG;
 } else if (op == OP_TESTEND) {
 res = RES_END;
 }
@@ -124,13 +121,12 @@ RisuResult recv_and_compare_register_info(void *uc)
   (uintptr_t)memblock);
 break;
 case OP_COMPAREMEM:
-mem_used = 1;
 res = read_buffer(master_memblock, MEMBLOCKLEN);
 if (res != RES_OK) {
-packet_mismatch = 1;
+/* fail */
 } else if (memcmp(memblock, master_memblock, MEMBLOCKLEN) != 0) {
 /* memory mismatch */
-res = RES_MISMATCH;
+res = RES_MISMATCH_MEM;
 }
 respond(res == RES_OK ? RES_OK : RES_END);
 break;
@@ -141,40 +137,15 @@ RisuResult recv_and_compare_register_info(void *uc)
 return res;
 }
 
-/* Print a useful report on the status of the last comparison
- * done in recv_and_compare_register_info(). This is called on
- * exit, so need not restrict itself to signal-safe functions.
- * Should return 0 if it was a good match (ie end of test)
- * and 1 for a mismatch.
+/*
+ * Print a useful report on the status of the last reg comparison
+ * done in recv_and_compare_register_info().
  */
-int report_match_status(void)
+void report_mismatch_reg(void)
 {
-int resp = 0;
-fprintf(stderr, "match status...\n");
-if (packet_mismatch) {
-fprintf(stderr, "packet mismatch (probably disagreement "
-"about UNDEF on load/store)\n");
-return 1;
-}
-if (!reginfo_is_eq(_ri, _ri)) {
-fprintf(stderr, "mismatch on regs!\n");
-resp = 1;
-}
-if (mem_used
-&& memcmp(memblock, _memblock, MEMBLOCKLEN) != 0) {
-fprintf(stderr, "mismatch on memory!\n");
-resp = 1;
-}
-if (!resp) {
-fprintf(stderr, "match!\n");
-return 0;
-}
-
 fprintf(stderr, "master reginfo:\n");
 reginfo_dump(_ri, stderr);
 fprintf(stderr, "apprentice reginfo:\n");
 reginfo_dump(_ri, stderr);
-
 reginfo_dump_mismatch(_ri, _ri, stderr);
-return resp;
 }
diff --git a/risu.c b/risu.c
index ea4b4d3..398faac 100644
--- a/risu.c
+++ b/risu.c
@@ -224,9 +224,13 @@ static int apprentice(void)
 case RES_END:
 return EXIT_SUCCESS;
 
-case RES_MISMATCH:
-fprintf(stderr, "mismatch after %zd checkpoints\n", signal_count);
-report_match_status();
+case RES_MISMATCH_REG:
+fprintf(stderr, "mismatch reg after %zd checkpoints\n", signal_count);
+report_mismatch_reg();
+return EXIT_FAILURE;
+
+case RES_MISMATCH_MEM:
+fprintf(stderr, "mismatch mem after %zd checkpoints\n", signal_count);
 return EXIT_FAILURE;
 
 case RES_BAD_IO:
-- 
2.20.1




[RISU v2 15/17] Compute reginfo_size based on the reginfo

2020-05-18 Thread Richard Henderson
This will allow dumping of SVE frames without having
to know the SVE vector length beforehand.

Signed-off-by: Richard Henderson 
---
 risu.h | 2 +-
 reginfo.c  | 6 +++---
 risu_reginfo_aarch64.c | 4 ++--
 risu_reginfo_arm.c | 2 +-
 risu_reginfo_i386.c| 2 +-
 risu_reginfo_m68k.c| 2 +-
 risu_reginfo_ppc64.c   | 2 +-
 7 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/risu.h b/risu.h
index eeb6775..054cef7 100644
--- a/risu.h
+++ b/risu.h
@@ -155,6 +155,6 @@ int reginfo_dump(struct reginfo *ri, FILE * f);
 int reginfo_dump_mismatch(struct reginfo *m, struct reginfo *a, FILE *f);
 
 /* return size of reginfo */
-const int reginfo_size(void);
+int reginfo_size(struct reginfo *ri);
 
 #endif /* RISU_H */
diff --git a/reginfo.c b/reginfo.c
index f187d9c..411c2a6 100644
--- a/reginfo.c
+++ b/reginfo.c
@@ -38,7 +38,7 @@ RisuResult send_register_info(void *uc)
 case OP_TESTEND:
 case OP_COMPARE:
 case OP_SIGILL:
-header.size = reginfo_size();
+header.size = reginfo_size();
 extra = 
 break;
 
@@ -109,7 +109,7 @@ RisuResult recv_and_compare_register_info(void *uc)
 case OP_TESTEND:
 case OP_COMPARE:
 case OP_SIGILL:
-extra_size = reginfo_size();
+extra_size = reginfo_size(_ri);
 break;
 case OP_SETMEMBLOCK:
 case OP_GETMEMBLOCK:
@@ -217,7 +217,7 @@ void report_mismatch_header(void)
 case OP_COMPARE:
 case OP_SIGILL:
 kind = "reginfo";
-a_sz = reginfo_size();
+a_sz = reginfo_size(_ri);
 break;
 case OP_SETMEMBLOCK:
 case OP_GETMEMBLOCK:
diff --git a/risu_reginfo_aarch64.c b/risu_reginfo_aarch64.c
index 028c690..7044648 100644
--- a/risu_reginfo_aarch64.c
+++ b/risu_reginfo_aarch64.c
@@ -69,7 +69,7 @@ void process_arch_opt(int opt, const char *arg)
 #endif
 }
 
-const int reginfo_size(void)
+int reginfo_size(struct reginfo *ri)
 {
 int size = offsetof(struct reginfo, simd.end);
 #ifdef SVE_MAGIC
@@ -194,7 +194,7 @@ void reginfo_init(struct reginfo *ri, ucontext_t *uc)
 /* reginfo_is_eq: compare the reginfo structs, returns nonzero if equal */
 int reginfo_is_eq(struct reginfo *r1, struct reginfo *r2)
 {
-return memcmp(r1, r2, reginfo_size()) == 0;
+return memcmp(r1, r2, reginfo_size(r1)) == 0;
 }
 
 #ifdef SVE_MAGIC
diff --git a/risu_reginfo_arm.c b/risu_reginfo_arm.c
index 3662f12..3832e27 100644
--- a/risu_reginfo_arm.c
+++ b/risu_reginfo_arm.c
@@ -36,7 +36,7 @@ void process_arch_opt(int opt, const char *arg)
 abort();
 }
 
-const int reginfo_size(void)
+int reginfo_size(struct reginfo *ri)
 {
 return sizeof(struct reginfo);
 }
diff --git a/risu_reginfo_i386.c b/risu_reginfo_i386.c
index 60fc239..902d33e 100644
--- a/risu_reginfo_i386.c
+++ b/risu_reginfo_i386.c
@@ -74,7 +74,7 @@ void process_arch_opt(int opt, const char *arg)
 }
 }
 
-const int reginfo_size(void)
+int reginfo_size(struct reginfo *ri)
 {
 return sizeof(struct reginfo);
 }
diff --git a/risu_reginfo_m68k.c b/risu_reginfo_m68k.c
index 32b28c8..361f172 100644
--- a/risu_reginfo_m68k.c
+++ b/risu_reginfo_m68k.c
@@ -23,7 +23,7 @@ void process_arch_opt(int opt, const char *arg)
 abort();
 }
 
-const int reginfo_size(void)
+int reginfo_size(struct reginfo *ri)
 {
 return sizeof(struct reginfo);
 }
diff --git a/risu_reginfo_ppc64.c b/risu_reginfo_ppc64.c
index 071c951..c86313c 100644
--- a/risu_reginfo_ppc64.c
+++ b/risu_reginfo_ppc64.c
@@ -32,7 +32,7 @@ void process_arch_opt(int opt, const char *arg)
 abort();
 }
 
-const int reginfo_size(void)
+int reginfo_size(struct reginfo *ri)
 {
 return sizeof(struct reginfo);
 }
-- 
2.20.1




[RISU v2 12/17] Simplify syncing with master

2020-05-18 Thread Richard Henderson
Do not pass status like RES_BAD_IO from apprentice to master.
This means that when master reports i/o error that we know it
came from master; the apprentice will report its own i/o error.

Signed-off-by: Richard Henderson 
---
 reginfo.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/reginfo.c b/reginfo.c
index c37c5df..31bc699 100644
--- a/reginfo.c
+++ b/reginfo.c
@@ -90,10 +90,9 @@ RisuResult recv_and_compare_register_info(void *uc)
 }
 
 if (header.risu_op != op) {
-/* We are out of sync */
-res = RES_BAD_IO;
-respond(res);
-return res;
+/* We are out of sync.  Tell master to exit. */
+respond(RES_END);
+return RES_BAD_IO;
 }
 
 /* send OK for the header */
@@ -115,7 +114,7 @@ RisuResult recv_and_compare_register_info(void *uc)
 } else if (op == OP_TESTEND) {
 res = RES_END;
 }
-respond(res);
+respond(res == RES_OK ? RES_OK : RES_END);
 break;
 case OP_SETMEMBLOCK:
 memblock = (void *)(uintptr_t)get_reginfo_paramreg(_ri);
@@ -133,7 +132,7 @@ RisuResult recv_and_compare_register_info(void *uc)
 /* memory mismatch */
 res = RES_MISMATCH;
 }
-respond(res);
+respond(res == RES_OK ? RES_OK : RES_END);
 break;
 default:
 abort();
-- 
2.20.1




[RISU v2 05/17] Use EXIT_FAILURE, EXIT_SUCCESS

2020-05-18 Thread Richard Henderson
Some of the time we exit via the return value from main.
This can make it easier to tell what it is we're returning.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 comms.c| 26 +-
 risu.c | 22 +++---
 risu_reginfo_aarch64.c |  4 ++--
 risu_reginfo_i386.c|  2 +-
 4 files changed, 27 insertions(+), 27 deletions(-)

diff --git a/comms.c b/comms.c
index 6946fd9..861e845 100644
--- a/comms.c
+++ b/comms.c
@@ -31,7 +31,7 @@ int apprentice_connect(const char *hostname, int port)
 sock = socket(PF_INET, SOCK_STREAM, 0);
 if (sock < 0) {
 perror("socket");
-exit(1);
+exit(EXIT_FAILURE);
 }
 struct hostent *hostinfo;
 sa.sin_family = AF_INET;
@@ -39,12 +39,12 @@ int apprentice_connect(const char *hostname, int port)
 hostinfo = gethostbyname(hostname);
 if (!hostinfo) {
 fprintf(stderr, "Unknown host %s\n", hostname);
-exit(1);
+exit(EXIT_FAILURE);
 }
 sa.sin_addr = *(struct in_addr *) hostinfo->h_addr;
 if (connect(sock, (struct sockaddr *) , sizeof(sa)) < 0) {
 perror("connect");
-exit(1);
+exit(EXIT_FAILURE);
 }
 return sock;
 }
@@ -56,13 +56,13 @@ int master_connect(int port)
 sock = socket(PF_INET, SOCK_STREAM, 0);
 if (sock < 0) {
 perror("socket");
-exit(1);
+exit(EXIT_FAILURE);
 }
 int sora = 1;
 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, , sizeof(sora)) !=
 0) {
 perror("setsockopt(SO_REUSEADDR)");
-exit(1);
+exit(EXIT_FAILURE);
 }
 
 sa.sin_family = AF_INET;
@@ -70,11 +70,11 @@ int master_connect(int port)
 sa.sin_addr.s_addr = htonl(INADDR_ANY);
 if (bind(sock, (struct sockaddr *) , sizeof(sa)) < 0) {
 perror("bind");
-exit(1);
+exit(EXIT_FAILURE);
 }
 if (listen(sock, 1) < 0) {
 perror("listen");
-exit(1);
+exit(EXIT_FAILURE);
 }
 /* Just block until we get a connection */
 fprintf(stderr, "master: waiting for connection on port %d...\n",
@@ -84,7 +84,7 @@ int master_connect(int port)
 int nsock = accept(sock, (struct sockaddr *) , );
 if (nsock < 0) {
 perror("accept");
-exit(1);
+exit(EXIT_FAILURE);
 }
 /* We're done with the server socket now */
 close(sock);
@@ -104,7 +104,7 @@ static void recv_bytes(int sock, void *pkt, int pktlen)
 continue;
 }
 perror("read failed");
-exit(1);
+exit(EXIT_FAILURE);
 }
 pktlen -= i;
 p += i;
@@ -127,7 +127,7 @@ static void recv_and_discard_bytes(int sock, int pktlen)
 continue;
 }
 perror("read failed");
-exit(1);
+exit(EXIT_FAILURE);
 }
 pktlen -= i;
 }
@@ -186,12 +186,12 @@ int send_data_pkt(int sock, void *pkt, int pktlen)
 
 if (safe_writev(sock, iov, 2) == -1) {
 perror("writev failed");
-exit(1);
+exit(EXIT_FAILURE);
 }
 
 if (read(sock, , 1) != 1) {
 perror("read failed");
-exit(1);
+exit(EXIT_FAILURE);
 }
 return resp;
 }
@@ -217,6 +217,6 @@ void send_response_byte(int sock, int resp)
 unsigned char r = resp;
 if (write(sock, , 1) != 1) {
 perror("write failed");
-exit(1);
+exit(EXIT_FAILURE);
 }
 }
diff --git a/risu.c b/risu.c
index f404d8f..979341c 100644
--- a/risu.c
+++ b/risu.c
@@ -153,13 +153,13 @@ void apprentice_sigill(int sig, siginfo_t *si, void *uc)
 return;
 case 1:
 /* end of test */
-exit(0);
+exit(EXIT_SUCCESS);
 default:
 /* mismatch */
 if (trace) {
 siglongjmp(jmpbuf, 1);
 }
-exit(1);
+exit(EXIT_FAILURE);
 }
 }
 
@@ -173,7 +173,7 @@ static void set_sigill_handler(void (*fn) (int, siginfo_t 
*, void *))
 sigemptyset(_mask);
 if (sigaction(SIGILL, , 0) != 0) {
 perror("sigaction");
-exit(1);
+exit(EXIT_FAILURE);
 }
 }
 
@@ -190,11 +190,11 @@ void load_image(const char *imgfile)
 int fd = open(imgfile, O_RDONLY);
 if (fd < 0) {
 fprintf(stderr, "failed to open image file %s\n", imgfile);
-exit(1);
+exit(EXIT_FAILURE);
 }
 if (fstat(fd, ) != 0) {
 perror("fstat");
-exit(1);
+exit(EXIT_FAILURE);
 }
 size_t len = st.st_size;
 void *addr;
@@ -207,7 +207,7 @@ void load_image(const char *imgfile)
  0);
 if (!addr) {
 perror("mmap");
-exit(1);
+exit(EXIT_FAILURE);
 }
 close(fd);
 image_start = addr;
@@ -226,7 +226,7 @@ int master(void)
 if (trace) {
 fprintf(stderr, "trace complete after %zd checkpoints\n",
 signal_count);
-return 0;
+return 

[RISU v2 07/17] Add enum RisuOp

2020-05-18 Thread Richard Henderson
Formalize the set of defines, plus -1, into an enum.

Signed-off-by: Richard Henderson 
---
 risu.h | 23 +++
 reginfo.c  | 32 +++-
 risu_aarch64.c |  6 +++---
 risu_arm.c |  6 +++---
 risu_i386.c|  4 ++--
 risu_m68k.c|  4 ++--
 risu_ppc64.c   |  4 ++--
 7 files changed, 46 insertions(+), 33 deletions(-)

diff --git a/risu.h b/risu.h
index e2b4508..a7aa929 100644
--- a/risu.h
+++ b/risu.h
@@ -45,11 +45,17 @@ extern uintptr_t image_start_address;
 extern void *memblock;
 
 /* Ops code under test can request from risu: */
-#define OP_COMPARE 0
-#define OP_TESTEND 1
-#define OP_SETMEMBLOCK 2
-#define OP_GETMEMBLOCK 3
-#define OP_COMPAREMEM 4
+typedef enum {
+/* Any other sigill besides the destignated undefined insn.  */
+OP_SIGILL = -1,
+
+/* These are generated by the designated undefined insn. */
+OP_COMPARE = 0,
+OP_TESTEND = 1,
+OP_SETMEMBLOCK = 2,
+OP_GETMEMBLOCK = 3,
+OP_COMPAREMEM = 4,
+} RisuOp;
 
 /* The memory block should be this long */
 #define MEMBLOCKLEN 8192
@@ -114,10 +120,11 @@ void set_ucontext_paramreg(void *vuc, uint64_t value);
 /* Return the value of the parameter register from a reginfo. */
 uint64_t get_reginfo_paramreg(struct reginfo *ri);
 
-/* Return the risu operation number we have been asked to do,
- * or -1 if this was a SIGILL for a non-risuop insn.
+/*
+ * Return the risu operation number we have been asked to do,
+ * or OP_SIGILL if this was a SIGILL for a non-risuop insn.
  */
-int get_risuop(struct reginfo *ri);
+RisuOp get_risuop(struct reginfo *ri);
 
 /* Return the PC from a reginfo */
 uintptr_t get_pc(struct reginfo *ri);
diff --git a/reginfo.c b/reginfo.c
index 1b2a821..2d67c93 100644
--- a/reginfo.c
+++ b/reginfo.c
@@ -11,7 +11,7 @@
 
 #include 
 #include 
-
+#include 
 #include "risu.h"
 
 struct reginfo master_ri, apprentice_ri;
@@ -25,7 +25,7 @@ int send_register_info(write_fn write_fn, void *uc)
 {
 struct reginfo ri;
 trace_header_t header;
-int op;
+RisuOp op;
 
 reginfo_init(, uc);
 op = get_risuop();
@@ -38,11 +38,18 @@ int send_register_info(write_fn write_fn, void *uc)
 }
 
 switch (op) {
+case OP_COMPARE:
 case OP_TESTEND:
-write_fn(, reginfo_size());
-/* if we are tracing write_fn will return 0 unlike a remote
-   end, hence we force return of 1 here */
-return 1;
+case OP_SIGILL:
+/*
+ * Do a simple register compare on (a) explicit request
+ * (b) end of test (c) a non-risuop UNDEF
+ */
+if (write_fn(, reginfo_size()) != 0) {
+return -1;
+}
+/* For OP_TEST_END, force return 1 to exit. */
+return op == OP_TESTEND;
 case OP_SETMEMBLOCK:
 memblock = (void *)(uintptr_t)get_reginfo_paramreg();
 break;
@@ -53,12 +60,8 @@ int send_register_info(write_fn write_fn, void *uc)
 case OP_COMPAREMEM:
 return write_fn(memblock, MEMBLOCKLEN);
 break;
-case OP_COMPARE:
 default:
-/* Do a simple register compare on (a) explicit request
- * (b) end of test (c) a non-risuop UNDEF
- */
-return write_fn(, reginfo_size());
+abort();
 }
 return 0;
 }
@@ -74,8 +77,9 @@ int send_register_info(write_fn write_fn, void *uc)
 int recv_and_compare_register_info(read_fn read_fn,
respond_fn resp_fn, void *uc)
 {
-int resp = 0, op;
+int resp = 0;
 trace_header_t header;
+RisuOp op;
 
 reginfo_init(_ri, uc);
 op = get_risuop(_ri);
@@ -97,7 +101,7 @@ int recv_and_compare_register_info(read_fn read_fn,
 switch (op) {
 case OP_COMPARE:
 case OP_TESTEND:
-default:
+case OP_SIGILL:
 /* Do a simple register compare on (a) explicit request
  * (b) end of test (c) a non-risuop UNDEF
  */
@@ -130,6 +134,8 @@ int recv_and_compare_register_info(read_fn read_fn,
 }
 resp_fn(resp);
 break;
+default:
+abort();
 }
 
 return resp;
diff --git a/risu_aarch64.c b/risu_aarch64.c
index 492d141..f8a8412 100644
--- a/risu_aarch64.c
+++ b/risu_aarch64.c
@@ -29,16 +29,16 @@ uint64_t get_reginfo_paramreg(struct reginfo *ri)
 return ri->regs[0];
 }
 
-int get_risuop(struct reginfo *ri)
+RisuOp get_risuop(struct reginfo *ri)
 {
 /* Return the risuop we have been asked to do
- * (or -1 if this was a SIGILL for a non-risuop insn)
+ * (or OP_SIGILL if this was a SIGILL for a non-risuop insn)
  */
 uint32_t insn = ri->faulting_insn;
 uint32_t op = insn & 0xf;
 uint32_t key = insn & ~0xf;
 uint32_t risukey = 0x5af0;
-return (key != risukey) ? -1 : op;
+return (key != risukey) ? OP_SIGILL : op;
 }
 
 uintptr_t get_pc(struct reginfo *ri)
diff --git a/risu_arm.c b/risu_arm.c
index 5fcb2a5..a20bf73 100644
--- a/risu_arm.c
+++ b/risu_arm.c
@@ -56,17 +56,17 @@ uint64_t 

[RISU v2 01/17] Use bool for tracing variables

2020-05-18 Thread Richard Henderson
Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 risu.h| 3 ++-
 reginfo.c | 2 +-
 risu.c| 8 
 3 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/risu.h b/risu.h
index 8d2d646..e2b4508 100644
--- a/risu.h
+++ b/risu.h
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /* Extra option processing for architectures */
 extern const struct option * const arch_long_opts;
@@ -96,7 +97,7 @@ int recv_and_compare_register_info(read_fn read_fn,
  * Should return 0 if it was a good match (ie end of test)
  * and 1 for a mismatch.
  */
-int report_match_status(int trace);
+int report_match_status(bool trace);
 
 /* Interface provided by CPU-specific code: */
 
diff --git a/reginfo.c b/reginfo.c
index dd42ae2..1b2a821 100644
--- a/reginfo.c
+++ b/reginfo.c
@@ -141,7 +141,7 @@ int recv_and_compare_register_info(read_fn read_fn,
  * Should return 0 if it was a good match (ie end of test)
  * and 1 for a mismatch.
  */
-int report_match_status(int trace)
+int report_match_status(bool trace)
 {
 int resp = 0;
 fprintf(stderr, "match status...\n");
diff --git a/risu.c b/risu.c
index 01525d2..79b1092 100644
--- a/risu.c
+++ b/risu.c
@@ -31,7 +31,7 @@
 void *memblock;
 
 int apprentice_fd, master_fd;
-int trace;
+bool trace;
 size_t signal_count;
 
 #ifdef HAVE_ZLIB
@@ -228,7 +228,7 @@ int master(void)
 signal_count);
 return 0;
 } else {
-return report_match_status(0);
+return report_match_status(false);
 }
 }
 set_sigill_handler(_sigill);
@@ -250,7 +250,7 @@ int apprentice(void)
 #endif
 close(apprentice_fd);
 fprintf(stderr, "finished early after %zd checkpoints\n", 
signal_count);
-return report_match_status(1);
+return report_match_status(true);
 }
 set_sigill_handler(_sigill);
 fprintf(stderr, "starting apprentice image at 0x%"PRIxPTR"\n",
@@ -344,7 +344,7 @@ int main(int argc, char **argv)
 break;
 case 't':
 trace_fn = optarg;
-trace = 1;
+trace = true;
 break;
 case 'h':
 hostname = optarg;
-- 
2.20.1




[RISU v2 09/17] Unify i/o functions and use RisuResult

2020-05-18 Thread Richard Henderson
Push the trace check down from the function calling the reginfo
function down into the i/o function.  This means we don't have
to pass a function pointer.

Return a RisuResult from the i/o functions.  This fixes a minor bug
in send_register_info (even before the conversion to RisuResult),
which returned the write_fn result directly.

Signed-off-by: Richard Henderson 
---
 risu.h| 25 -
 comms.c   |  8 +++---
 reginfo.c | 60 
 risu.c| 82 ++-
 4 files changed, 80 insertions(+), 95 deletions(-)

diff --git a/risu.h b/risu.h
index e6d07eb..f44b781 100644
--- a/risu.h
+++ b/risu.h
@@ -34,13 +34,6 @@ void process_arch_opt(int opt, const char *arg);
 
 #include REGINFO_HEADER(ARCH)
 
-/* Socket related routines */
-int master_connect(int port);
-int apprentice_connect(const char *hostname, int port);
-int send_data_pkt(int sock, void *pkt, int pktlen);
-int recv_data_pkt(int sock, void *pkt, int pktlen);
-void send_response_byte(int sock, int resp);
-
 extern uintptr_t image_start_address;
 extern void *memblock;
 
@@ -80,6 +73,13 @@ typedef struct {
uint32_t risu_op;
 } trace_header_t;
 
+/* Socket related routines */
+int master_connect(int port);
+int apprentice_connect(const char *hostname, int port);
+RisuResult send_data_pkt(int sock, void *pkt, int pktlen);
+RisuResult recv_data_pkt(int sock, void *pkt, int pktlen);
+void send_response_byte(int sock, int resp);
+
 /* Functions operating on reginfo */
 
 /* Function prototypes for read/write helper functions.
@@ -88,23 +88,22 @@ typedef struct {
  * recv_and_compare_register_info which can either be backed by the
  * traditional network socket or a trace file.
  */
-typedef int (*write_fn) (void *ptr, size_t bytes);
-typedef int (*read_fn) (void *ptr, size_t bytes);
-typedef void (*respond_fn) (RisuResult response);
+RisuResult write_buffer(void *ptr, size_t bytes);
+RisuResult read_buffer(void *ptr, size_t bytes);
+void respond(RisuResult response);
 
 /*
  * Send the register information from the struct ucontext down the socket.
  * NB: called from a signal handler.
  */
-RisuResult send_register_info(write_fn write_fn, void *uc);
+RisuResult send_register_info(void *uc);
 
 /*
  * Read register info from the socket and compare it with that from the
  * ucontext.
  * NB: called from a signal handler.
  */
-RisuResult recv_and_compare_register_info(read_fn read_fn,
-  respond_fn respond, void *uc);
+RisuResult recv_and_compare_register_info(void *uc);
 
 /* Print a useful report on the status of the last comparison
  * done in recv_and_compare_register_info(). This is called on
diff --git a/comms.c b/comms.c
index 861e845..21968da 100644
--- a/comms.c
+++ b/comms.c
@@ -168,7 +168,7 @@ ssize_t safe_writev(int fd, struct iovec *iov_in, int 
iovcnt)
  * Note that both ends must agree on the length of the
  * block of data.
  */
-int send_data_pkt(int sock, void *pkt, int pktlen)
+RisuResult send_data_pkt(int sock, void *pkt, int pktlen)
 {
 unsigned char resp;
 /* First we send the packet length as a network-order 32 bit value.
@@ -196,7 +196,7 @@ int send_data_pkt(int sock, void *pkt, int pktlen)
 return resp;
 }
 
-int recv_data_pkt(int sock, void *pkt, int pktlen)
+RisuResult recv_data_pkt(int sock, void *pkt, int pktlen)
 {
 uint32_t net_pktlen;
 recv_bytes(sock, _pktlen, sizeof(net_pktlen));
@@ -206,10 +206,10 @@ int recv_data_pkt(int sock, void *pkt, int pktlen)
  * a response back.
  */
 recv_and_discard_bytes(sock, net_pktlen);
-return 1;
+return RES_BAD_IO;
 }
 recv_bytes(sock, pkt, pktlen);
-return 0;
+return RES_OK;
 }
 
 void send_response_byte(int sock, int resp)
diff --git a/reginfo.c b/reginfo.c
index b909a1f..fee025e 100644
--- a/reginfo.c
+++ b/reginfo.c
@@ -21,10 +21,11 @@ uint8_t apprentice_memblock[MEMBLOCKLEN];
 static int mem_used;
 static int packet_mismatch;
 
-RisuResult send_register_info(write_fn write_fn, void *uc)
+RisuResult send_register_info(void *uc)
 {
 struct reginfo ri;
 trace_header_t header;
+RisuResult res;
 RisuOp op;
 
 reginfo_init(, uc);
@@ -33,8 +34,9 @@ RisuResult send_register_info(write_fn write_fn, void *uc)
 /* Write a header with PC/op to keep in sync */
 header.pc = get_pc();
 header.risu_op = op;
-if (write_fn(, sizeof(header)) != 0) {
-return RES_BAD_IO;
+res = write_buffer(, sizeof(header));
+if (res != RES_OK) {
+return res;
 }
 
 switch (op) {
@@ -45,11 +47,12 @@ RisuResult send_register_info(write_fn write_fn, void *uc)
  * Do a simple register compare on (a) explicit request
  * (b) end of test (c) a non-risuop UNDEF
  */
-if (write_fn(, reginfo_size()) != 0) {
-return RES_BAD_IO;
+res = write_buffer(, reginfo_size());
+/* For OP_TEST_END, force 

[RISU v2 08/17] Add enum RisuResult

2020-05-18 Thread Richard Henderson
Formalize the random set of numbers into an enum.  Doing this
makes it easy to see that one of the responses in
recv_and_compare_register_info was inconsistent.

Signed-off-by: Richard Henderson 
---
 risu.h| 25 +
 reginfo.c | 32 
 risu.c| 18 +-
 3 files changed, 42 insertions(+), 33 deletions(-)

diff --git a/risu.h b/risu.h
index a7aa929..e6d07eb 100644
--- a/risu.h
+++ b/risu.h
@@ -57,6 +57,14 @@ typedef enum {
 OP_COMPAREMEM = 4,
 } RisuOp;
 
+/* Result of operation */
+typedef enum {
+RES_OK = 0,
+RES_END,
+RES_MISMATCH,
+RES_BAD_IO,
+} RisuResult;
+
 /* The memory block should be this long */
 #define MEMBLOCKLEN 8192
 
@@ -82,20 +90,21 @@ typedef struct {
  */
 typedef int (*write_fn) (void *ptr, size_t bytes);
 typedef int (*read_fn) (void *ptr, size_t bytes);
-typedef void (*respond_fn) (int response);
+typedef void (*respond_fn) (RisuResult response);
 
-/* Send the register information from the struct ucontext down the socket.
- * Return the response code from the master.
+/*
+ * Send the register information from the struct ucontext down the socket.
  * NB: called from a signal handler.
  */
-int send_register_info(write_fn write_fn, void *uc);
+RisuResult send_register_info(write_fn write_fn, void *uc);
 
-/* Read register info from the socket and compare it with that from the
- * ucontext. Return 0 for match, 1 for end-of-test, 2 for mismatch.
+/*
+ * Read register info from the socket and compare it with that from the
+ * ucontext.
  * NB: called from a signal handler.
  */
-int recv_and_compare_register_info(read_fn read_fn,
-   respond_fn respond, void *uc);
+RisuResult recv_and_compare_register_info(read_fn read_fn,
+  respond_fn respond, void *uc);
 
 /* Print a useful report on the status of the last comparison
  * done in recv_and_compare_register_info(). This is called on
diff --git a/reginfo.c b/reginfo.c
index 2d67c93..b909a1f 100644
--- a/reginfo.c
+++ b/reginfo.c
@@ -21,7 +21,7 @@ uint8_t apprentice_memblock[MEMBLOCKLEN];
 static int mem_used;
 static int packet_mismatch;
 
-int send_register_info(write_fn write_fn, void *uc)
+RisuResult send_register_info(write_fn write_fn, void *uc)
 {
 struct reginfo ri;
 trace_header_t header;
@@ -34,7 +34,7 @@ int send_register_info(write_fn write_fn, void *uc)
 header.pc = get_pc();
 header.risu_op = op;
 if (write_fn(, sizeof(header)) != 0) {
-return -1;
+return RES_BAD_IO;
 }
 
 switch (op) {
@@ -46,10 +46,10 @@ int send_register_info(write_fn write_fn, void *uc)
  * (b) end of test (c) a non-risuop UNDEF
  */
 if (write_fn(, reginfo_size()) != 0) {
-return -1;
+return RES_BAD_IO;
 }
 /* For OP_TEST_END, force return 1 to exit. */
-return op == OP_TESTEND;
+return op == OP_TESTEND ? RES_END : RES_OK;
 case OP_SETMEMBLOCK:
 memblock = (void *)(uintptr_t)get_reginfo_paramreg();
 break;
@@ -63,7 +63,7 @@ int send_register_info(write_fn write_fn, void *uc)
 default:
 abort();
 }
-return 0;
+return RES_OK;
 }
 
 /* Read register info from the socket and compare it with that from the
@@ -74,10 +74,10 @@ int send_register_info(write_fn write_fn, void *uc)
  * that says whether it is register or memory data, so if the two
  * sides get out of sync then we will fail obscurely.
  */
-int recv_and_compare_register_info(read_fn read_fn,
-   respond_fn resp_fn, void *uc)
+RisuResult recv_and_compare_register_info(read_fn read_fn,
+  respond_fn resp_fn, void *uc)
 {
-int resp = 0;
+RisuResult resp = RES_OK;
 trace_header_t header;
 RisuOp op;
 
@@ -85,18 +85,18 @@ int recv_and_compare_register_info(read_fn read_fn,
 op = get_risuop(_ri);
 
 if (read_fn(, sizeof(header)) != 0) {
-return -1;
+return RES_BAD_IO;
 }
 
 if (header.risu_op != op) {
 /* We are out of sync */
-resp = 2;
+resp = RES_BAD_IO;
 resp_fn(resp);
 return resp;
 }
 
 /* send OK for the header */
-resp_fn(0);
+resp_fn(RES_OK);
 
 switch (op) {
 case OP_COMPARE:
@@ -107,12 +107,12 @@ int recv_and_compare_register_info(read_fn read_fn,
  */
 if (read_fn(_ri, reginfo_size())) {
 packet_mismatch = 1;
-resp = 2;
+resp = RES_BAD_IO;
 } else if (!reginfo_is_eq(_ri, _ri)) {
 /* register mismatch */
-resp = 2;
+resp = RES_MISMATCH;
 } else if (op == OP_TESTEND) {
-resp = 1;
+resp = RES_END;
 }
 resp_fn(resp);
 break;
@@ -127,10 +127,10 @@ int recv_and_compare_register_info(read_fn read_fn,
 mem_used = 1;
 if 

[RISU v2 03/17] Hoist trace file opening

2020-05-18 Thread Richard Henderson
We will want to share this code with --dump.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 risu.c | 37 +
 1 file changed, 17 insertions(+), 20 deletions(-)

diff --git a/risu.c b/risu.c
index 059348f..1c66885 100644
--- a/risu.c
+++ b/risu.c
@@ -363,6 +363,21 @@ int main(int argc, char **argv)
 }
 }
 
+if (trace) {
+if (strcmp(trace_fn, "-") == 0) {
+comm_fd = ismaster ? STDOUT_FILENO : STDIN_FILENO;
+} else {
+if (ismaster) {
+comm_fd = open(trace_fn, O_WRONLY | O_CREAT, S_IRWXU);
+} else {
+comm_fd = open(trace_fn, O_RDONLY);
+}
+#ifdef HAVE_ZLIB
+gz_trace_file = gzdopen(comm_fd, ismaster ? "wb9" : "rb");
+#endif
+}
+}
+
 imgfile = argv[optind];
 if (!imgfile) {
 fprintf(stderr, "Error: must specify image file name\n\n");
@@ -373,31 +388,13 @@ int main(int argc, char **argv)
 load_image(imgfile);
 
 if (ismaster) {
-if (trace) {
-if (strcmp(trace_fn, "-") == 0) {
-comm_fd = STDOUT_FILENO;
-} else {
-comm_fd = open(trace_fn, O_WRONLY | O_CREAT, S_IRWXU);
-#ifdef HAVE_ZLIB
-gz_trace_file = gzdopen(comm_fd, "wb9");
-#endif
-}
-} else {
+if (!trace) {
 fprintf(stderr, "master port %d\n", port);
 comm_fd = master_connect(port);
 }
 return master();
 } else {
-if (trace) {
-if (strcmp(trace_fn, "-") == 0) {
-comm_fd = STDIN_FILENO;
-} else {
-comm_fd = open(trace_fn, O_RDONLY);
-#ifdef HAVE_ZLIB
-gz_trace_file = gzdopen(comm_fd, "rb");
-#endif
-}
-} else {
+if (!trace) {
 fprintf(stderr, "apprentice host %s port %d\n", hostname, port);
 comm_fd = apprentice_connect(hostname, port);
 }
-- 
2.20.1




[RISU v2 02/17] Unify master_fd and apprentice_fd to comm_fd

2020-05-18 Thread Richard Henderson
Any one invocation cannot be both master and apprentice.
Let's use only one variable for the file descriptor.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 risu.c | 40 
 1 file changed, 20 insertions(+), 20 deletions(-)

diff --git a/risu.c b/risu.c
index 79b1092..059348f 100644
--- a/risu.c
+++ b/risu.c
@@ -30,7 +30,7 @@
 
 void *memblock;
 
-int apprentice_fd, master_fd;
+static int comm_fd;
 bool trace;
 size_t signal_count;
 
@@ -50,7 +50,7 @@ sigjmp_buf jmpbuf;
 
 int read_sock(void *ptr, size_t bytes)
 {
-return recv_data_pkt(master_fd, ptr, bytes);
+return recv_data_pkt(comm_fd, ptr, bytes);
 }
 
 int write_trace(void *ptr, size_t bytes)
@@ -58,9 +58,9 @@ int write_trace(void *ptr, size_t bytes)
 size_t res;
 
 #ifdef HAVE_ZLIB
-if (master_fd == STDOUT_FILENO) {
+if (comm_fd == STDOUT_FILENO) {
 #endif
-res = write(master_fd, ptr, bytes);
+res = write(comm_fd, ptr, bytes);
 #ifdef HAVE_ZLIB
 } else {
 res = gzwrite(gz_trace_file, ptr, bytes);
@@ -71,14 +71,14 @@ int write_trace(void *ptr, size_t bytes)
 
 void respond_sock(int r)
 {
-send_response_byte(master_fd, r);
+send_response_byte(comm_fd, r);
 }
 
 /* Apprentice function */
 
 int write_sock(void *ptr, size_t bytes)
 {
-return send_data_pkt(apprentice_fd, ptr, bytes);
+return send_data_pkt(comm_fd, ptr, bytes);
 }
 
 int read_trace(void *ptr, size_t bytes)
@@ -86,9 +86,9 @@ int read_trace(void *ptr, size_t bytes)
 size_t res;
 
 #ifdef HAVE_ZLIB
-if (apprentice_fd == STDIN_FILENO) {
+if (comm_fd == STDIN_FILENO) {
 #endif
-res = read(apprentice_fd, ptr, bytes);
+res = read(comm_fd, ptr, bytes);
 #ifdef HAVE_ZLIB
 } else {
 res = gzread(gz_trace_file, ptr, bytes);
@@ -218,11 +218,11 @@ int master(void)
 {
 if (sigsetjmp(jmpbuf, 1)) {
 #ifdef HAVE_ZLIB
-if (trace && master_fd != STDOUT_FILENO) {
+if (trace && comm_fd != STDOUT_FILENO) {
 gzclose(gz_trace_file);
 }
 #endif
-close(master_fd);
+close(comm_fd);
 if (trace) {
 fprintf(stderr, "trace complete after %zd checkpoints\n",
 signal_count);
@@ -244,11 +244,11 @@ int apprentice(void)
 {
 if (sigsetjmp(jmpbuf, 1)) {
 #ifdef HAVE_ZLIB
-if (trace && apprentice_fd != STDIN_FILENO) {
+if (trace && comm_fd != STDIN_FILENO) {
 gzclose(gz_trace_file);
 }
 #endif
-close(apprentice_fd);
+close(comm_fd);
 fprintf(stderr, "finished early after %zd checkpoints\n", 
signal_count);
 return report_match_status(true);
 }
@@ -375,31 +375,31 @@ int main(int argc, char **argv)
 if (ismaster) {
 if (trace) {
 if (strcmp(trace_fn, "-") == 0) {
-master_fd = STDOUT_FILENO;
+comm_fd = STDOUT_FILENO;
 } else {
-master_fd = open(trace_fn, O_WRONLY | O_CREAT, S_IRWXU);
+comm_fd = open(trace_fn, O_WRONLY | O_CREAT, S_IRWXU);
 #ifdef HAVE_ZLIB
-gz_trace_file = gzdopen(master_fd, "wb9");
+gz_trace_file = gzdopen(comm_fd, "wb9");
 #endif
 }
 } else {
 fprintf(stderr, "master port %d\n", port);
-master_fd = master_connect(port);
+comm_fd = master_connect(port);
 }
 return master();
 } else {
 if (trace) {
 if (strcmp(trace_fn, "-") == 0) {
-apprentice_fd = STDIN_FILENO;
+comm_fd = STDIN_FILENO;
 } else {
-apprentice_fd = open(trace_fn, O_RDONLY);
+comm_fd = open(trace_fn, O_RDONLY);
 #ifdef HAVE_ZLIB
-gz_trace_file = gzdopen(apprentice_fd, "rb");
+gz_trace_file = gzdopen(comm_fd, "rb");
 #endif
 }
 } else {
 fprintf(stderr, "apprentice host %s port %d\n", hostname, port);
-apprentice_fd = apprentice_connect(hostname, port);
+comm_fd = apprentice_connect(hostname, port);
 }
 return apprentice();
 }
-- 
2.20.1




[RISU v2 06/17] Make some risu.c symbols static

2020-05-18 Thread Richard Henderson
These are unused in other translation units.

Signed-off-by: Richard Henderson 
---
 risu.c | 24 
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/risu.c b/risu.c
index 979341c..24ada8f 100644
--- a/risu.c
+++ b/risu.c
@@ -31,18 +31,18 @@
 void *memblock;
 
 static int comm_fd;
-bool trace;
-size_t signal_count;
+static bool trace;
+static size_t signal_count;
 
 #ifdef HAVE_ZLIB
 #include 
-gzFile gz_trace_file;
+static gzFile gz_trace_file;
 #define TRACE_TYPE "compressed"
 #else
 #define TRACE_TYPE "uncompressed"
 #endif
 
-sigjmp_buf jmpbuf;
+static sigjmp_buf jmpbuf;
 
 #define ARRAY_SIZE(x)  (sizeof(x) / sizeof((x)[0]))
 
@@ -113,7 +113,7 @@ void respond_trace(int r)
 }
 }
 
-void master_sigill(int sig, siginfo_t *si, void *uc)
+static void master_sigill(int sig, siginfo_t *si, void *uc)
 {
 int r;
 signal_count++;
@@ -135,7 +135,7 @@ void master_sigill(int sig, siginfo_t *si, void *uc)
 }
 }
 
-void apprentice_sigill(int sig, siginfo_t *si, void *uc)
+static void apprentice_sigill(int sig, siginfo_t *si, void *uc)
 {
 int r;
 signal_count++;
@@ -180,9 +180,9 @@ static void set_sigill_handler(void (*fn) (int, siginfo_t 
*, void *))
 typedef void entrypoint_fn(void);
 
 uintptr_t image_start_address;
-entrypoint_fn *image_start;
+static entrypoint_fn *image_start;
 
-void load_image(const char *imgfile)
+static void load_image(const char *imgfile)
 {
 /* Load image file into memory as executable */
 struct stat st;
@@ -214,7 +214,7 @@ void load_image(const char *imgfile)
 image_start_address = (uintptr_t) addr;
 }
 
-int master(void)
+static int master(void)
 {
 if (sigsetjmp(jmpbuf, 1)) {
 #ifdef HAVE_ZLIB
@@ -240,7 +240,7 @@ int master(void)
 return EXIT_FAILURE;
 }
 
-int apprentice(void)
+static int apprentice(void)
 {
 if (sigsetjmp(jmpbuf, 1)) {
 #ifdef HAVE_ZLIB
@@ -261,9 +261,9 @@ int apprentice(void)
 return EXIT_FAILURE;
 }
 
-int ismaster;
+static int ismaster;
 
-void usage(void)
+static void usage(void)
 {
 fprintf(stderr,
 "Usage: risu [--master] [--host ] [--port ] "
-- 
2.20.1




[RISU v2 04/17] Adjust tracefile open for write

2020-05-18 Thread Richard Henderson
Truncate the new output file.  Rely on umask to remove
group+other file permissions, if desired.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 risu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/risu.c b/risu.c
index 1c66885..f404d8f 100644
--- a/risu.c
+++ b/risu.c
@@ -368,7 +368,7 @@ int main(int argc, char **argv)
 comm_fd = ismaster ? STDOUT_FILENO : STDIN_FILENO;
 } else {
 if (ismaster) {
-comm_fd = open(trace_fn, O_WRONLY | O_CREAT, S_IRWXU);
+comm_fd = open(trace_fn, O_WRONLY | O_CREAT | O_TRUNC, 0666);
 } else {
 comm_fd = open(trace_fn, O_RDONLY);
 }
-- 
2.20.1




[RISU v2 00/17] risu cleanups and improvements

2020-05-18 Thread Richard Henderson
This patch set does alter the format of the trace files, and thus
means we'll have to re-generate these.  However, the space saved
for sve trace files is significant, so I consider it worthwhile.

In addition, the new --dump option allows one to inspect the
contents of the trace file.

Version 2 adds a number of patches that clean up the whole
reporting of errors thing.  This allows us to give sensible
output when things go awry.

If using old trace files with the new risu, you get

mismatch header after 1 checkpoints
header mismatch detail (master : apprentice):
  magic: 00fc vs 52695375

If for somehow you use different risu for master and apprentice
on sockets, you get

i/o error after 1 checkpoints

Which is less helpful, but since the master has not written
enough data to the socket, the apprentice notices and reports
the i/o error before having a look at the header contents.


r~


Richard Henderson (17):
  Use bool for tracing variables
  Unify master_fd and apprentice_fd to comm_fd
  Hoist trace file opening
  Adjust tracefile open for write
  Use EXIT_FAILURE, EXIT_SUCCESS
  Make some risu.c symbols static
  Add enum RisuOp
  Add enum RisuResult
  Unify i/o functions and use RisuResult
  Pass non-OK result back through siglongjmp
  Always write for --master
  Simplify syncing with master
  Split RES_MISMATCH for registers and memory
  Add magic and size to the trace header
  Compute reginfo_size based on the reginfo
  aarch64: Reorg sve reginfo to save space
  Add --dump option to inspect trace files

 risu.h |  88 +
 risu_reginfo_aarch64.h |  16 +-
 comms.c|  34 ++--
 reginfo.c  | 274 ---
 risu.c | 409 +
 risu_aarch64.c |   6 +-
 risu_arm.c |   6 +-
 risu_i386.c|   4 +-
 risu_m68k.c|   4 +-
 risu_ppc64.c   |   4 +-
 risu_reginfo_aarch64.c | 192 ++-
 risu_reginfo_arm.c |   6 +-
 risu_reginfo_i386.c|   8 +-
 risu_reginfo_m68k.c|   6 +-
 risu_reginfo_ppc64.c   |   6 +-
 15 files changed, 635 insertions(+), 428 deletions(-)

-- 
2.20.1




RE: Simplifying the Hexagon frontend

2020-05-18 Thread Taylor Simpson


> -Original Message-
> From: Alessandro Di Federico 
> Sent: Monday, May 18, 2020 4:15 PM
> To: qemu-devel@nongnu.org Developers 
> Cc: Taylor Simpson ; Niccolò Izzo ;
> Brian Cain 
> Subject: Simplifying the Hexagon frontend
>
> Hi, this e-mail is intended to bootstrap a public discussion on how to
> improve the Hexagon frontend implementation. At rev.ng, Niccolò and I,
> developed an Hexagon frontend, and we're (finally!) joining forces with
> the QuIC guys to merge our efforts (did you see our talk [1]?).
>
> The status is as follows:
>
> * QuIC has its own fully working implementation that has been submitted
>   for review.
> * We're working to integrate in their implementation our mechanism to
>   automatically generate code to generate tiny code. But this will take
>   some more work.
>
> In the following, some initial considerations on how the latest
> patchset could be simplified.
>
> Here you can find a graph I've put together of the build process:
>
> https://rev.ng/downloads/qemu-hexagon/temporary/graph.svg
> https://rev.ng/downloads/qemu-hexagon/temporary/graph.dot
>
> Colors indicate language.
> Oval nodes are generated.
> Rectangles are hand-written.
>
> Taylor, I think some simplifications can be made to the process in order
> to ease the review process.
>
> * As far as I understand, from he "Source of Truth" set of files
>   (`alu.idef`, `encode_pp.def`...), through `gen_semantics`, you
>   generate `semantics_generated.pyinc`, which is then included by
>   `do_qemu.py` script, which does the real job.
>
>   I would suggest to keep `gen_semantics` and all its inputs
>   out-of-tree. It increases complexity in a non-negligible way, while
>   bringing a reduced benefit in terms of automation.

I'm not a lawyer, but I believe the original sources are required to conform to 
the license.

>
>   I'd suggest replace `gen_semantics`'s output
>   (`semantics_generated.pyinc`) with a human readable JSON file that
>   could be manipulated by hand and is then parsed by `do_qemu.py`. I
>   think JSON is more appropriate than generating executable python code
>   that is then imported.

I'm not married to python, but we need something that is executable.  The 
python code looks at the semantics of each instruction to determine the number 
and types of the helper arguments.  It also looks at some of the attributes to 
decide if certain things are needed (e.g., FPOP_START) and it scans the 
semantics (see need_part1 and need_ea_functions in do_qemu.py).

>
> * I suggest to switch to the decoding approach developed by Richard.
>   That would simplify the build process and reduce the code that has to
>   be reviewed.
>   I'm not 100% of the effort required to do this, maybe Richard can
>   weigh on this.
>

I agree in principal, but I haven't looked into it.  One thing to consider is 
that we'll need to reorder the instructions in a packet so that .new producer 
instructions are ahead of the consumer.

> * The current implementation can generate a helper function for each
>   Hexagon instruction and, for a subset of instructions, it has an
>   "override" mechanism to directly generate tiny code instructions
>   corresponding to the semantics of the original instruction (i.e.,
>   without using helpers).
>
>   This override mechanism is implemented with the `fWRAP` macros. They
>   have benefits, but they are quite convoluted. We should strive to
>   minimize the number of macros and alternative macro implementations
>   to what's strictly necessary in order to generate as much code as we
>   can from the "Source of Truth", but no more than that.
>

I think the problem is that fWRAP is a pretty generic name and it serves 
multiple purposes.  I'll change it to a single purpose.  Each instruction will 
check for fGEN_TCG_.  If this macro is defined, we won't create a helper, 
and we'll execute the GEN_TCG macro instead.  The generator will genterate:

#ifdef fGEN_TCG_
fGEN_TCG_();
#else
gen_helper_();
#endif

This will also let us get rid of the qemu_wrap_generated.h file.

I'll include this in the next version of the patch series.



>   As a simpler override mechanism, we could use weak functions. But I
>   think that, for simplicity, we should try to get in tree a simpler
>   version of the frontend that relies exclusively on helper functions.
>   It won't have optimal performances, but it will be fully functional.

If it makes the review more straightforward, I can remove the overrides from 
the patch series.  Also, the series has a definite point where the scalar core 
is fully implemented, and the remaining patches in the series add the HVX 
vector coprocessor.

Would these changes make it easier for the community to review?


>
>   Later on, once our work for automatically generating functions
>   generating tiny code is mature enough, we can extend the existing
>   implementation with an appropriate override system.
>
> In the meantime, we're setting up a Dockerfile based on 

[Bug 1879425] [NEW] The thread of "CPU 0 /KVM" keeping 99.9%CPU

2020-05-18 Thread cliff chen
Public bug reported:

Hi Expert:

The VM is hung here after (2, or 3, or 5 and the longest time is 10 hours) by 
qemu-kvm.
Notes: 
for VM:
  OS: RHEL 7.6
  CPU: 1
  MEM:4G
For qemu-kvm:
  1) version:
 /usr/libexec/qemu-kvm -version
 QEMU emulator version 2.10.0(qemu-kvm-ev-2.10.0-21.el7_5.4.1)
  2) once the issue is occurred, the CPU of "CPU0 /KVM" is more than 99% by com 
"top -p VM_pro_ID"
PID  UDER   PR NI RES   S  % CPU %MEM  TIME+COMMAND
872067   qemu   20 0  1.6g  R   99.9  0.6  37:08.87 CPU 0/KVM
  3) use "pstack 493307" and below is function trace
Thread 1 (Thread 0x7f2572e73040 (LWP 872067)):
#0  0x7f256cad8fcf in ppoll () from /lib64/libc.so.6
#1  0x55ff34bdf4a9 in qemu_poll_ns ()
#2  0x55ff34be02a8 in main_loop_wait ()
#3  0x55ff348bfb1a in main ()
  4) use strace "strace -tt -ff -p 872067 -o cfx" and below log keep printing
21:24:02.977833 ppoll([{fd=4, events=POLLIN}, {fd=6, events=POLLIN}, {fd=8, 
events=POLLIN}, {fd=9, events=POLLIN}, {fd=80, events=POLLIN}, {fd=82, 
events=POLLIN}, {fd=84, events=POLLIN}, {fd=115, events=POLLIN}, {fd=121, 
events=POLLIN}], 9, {0, 0}, NULL, 8) = 0 (Timeout)
21:24:02.977918 ppoll([{fd=4, events=POLLIN}, {fd=6, events=POLLIN}, {fd=8, 
events=POLLIN}, {fd=9, events=POLLIN}, {fd=80, events=POLLIN}, {fd=82, 
events=POLLIN}, {fd=84, events=POLLIN}, {fd=115, events=POLLIN}, {fd=121, 
events=POLLIN}], 9, {0, 911447}, NULL, 8) = 0 (Timeout)
21:24:02.978945 ppoll([{fd=4, events=POLLIN}, {fd=6, events=POLLIN}, {fd=8, 
events=POLLIN}, {fd=9, events=POLLIN}, {fd=80, events=POLLIN}, {fd=82, 
events=POLLIN}, {fd=84, events=POLLIN}, {fd=115, events=POLLIN}, {fd=121, 
events=POLLIN}], 9, {0, 0}, NULL, 8) = 0 (Timeout)
Therefore, I think the thread "CPU 0/KVM" is in tight loop.
  5) use reset can recover this issue. however, it will reoccurred again.
Current work around is increase one CPU for this VM, then issue is gone.

thanks
Cliff

** 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/1879425

Title:
  The thread of "CPU 0 /KVM" keeping 99.9%CPU

Status in QEMU:
  New

Bug description:
  Hi Expert:

  The VM is hung here after (2, or 3, or 5 and the longest time is 10 hours) by 
qemu-kvm.
  Notes: 
  for VM:
OS: RHEL 7.6
CPU: 1
MEM:4G
  For qemu-kvm:
1) version:
   /usr/libexec/qemu-kvm -version
   QEMU emulator version 2.10.0(qemu-kvm-ev-2.10.0-21.el7_5.4.1)
2) once the issue is occurred, the CPU of "CPU0 /KVM" is more than 99% by 
com "top -p VM_pro_ID"
  PID  UDER   PR NI RES   S  % CPU %MEM  TIME+COMMAND
  872067   qemu   20 0  1.6g  R   99.9  0.6  37:08.87 CPU 0/KVM
3) use "pstack 493307" and below is function trace
  Thread 1 (Thread 0x7f2572e73040 (LWP 872067)):
  #0  0x7f256cad8fcf in ppoll () from /lib64/libc.so.6
  #1  0x55ff34bdf4a9 in qemu_poll_ns ()
  #2  0x55ff34be02a8 in main_loop_wait ()
  #3  0x55ff348bfb1a in main ()
4) use strace "strace -tt -ff -p 872067 -o cfx" and below log keep printing
  21:24:02.977833 ppoll([{fd=4, events=POLLIN}, {fd=6, events=POLLIN}, {fd=8, 
events=POLLIN}, {fd=9, events=POLLIN}, {fd=80, events=POLLIN}, {fd=82, 
events=POLLIN}, {fd=84, events=POLLIN}, {fd=115, events=POLLIN}, {fd=121, 
events=POLLIN}], 9, {0, 0}, NULL, 8) = 0 (Timeout)
  21:24:02.977918 ppoll([{fd=4, events=POLLIN}, {fd=6, events=POLLIN}, {fd=8, 
events=POLLIN}, {fd=9, events=POLLIN}, {fd=80, events=POLLIN}, {fd=82, 
events=POLLIN}, {fd=84, events=POLLIN}, {fd=115, events=POLLIN}, {fd=121, 
events=POLLIN}], 9, {0, 911447}, NULL, 8) = 0 (Timeout)
  21:24:02.978945 ppoll([{fd=4, events=POLLIN}, {fd=6, events=POLLIN}, {fd=8, 
events=POLLIN}, {fd=9, events=POLLIN}, {fd=80, events=POLLIN}, {fd=82, 
events=POLLIN}, {fd=84, events=POLLIN}, {fd=115, events=POLLIN}, {fd=121, 
events=POLLIN}], 9, {0, 0}, NULL, 8) = 0 (Timeout)
  Therefore, I think the thread "CPU 0/KVM" is in tight loop.
5) use reset can recover this issue. however, it will reoccurred again.
  Current work around is increase one CPU for this VM, then issue is gone.

  thanks
  Cliff

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



Re: checkpatch error checking target arch in libvhost-user

2020-05-18 Thread Raphael Norwitz
> Can we make it a run-time value instead?

It's definitely possible, but will require a bit of refactoring. How
about for now I set a reasonable maximum which is supported by all
platforms (32)? That still increases it a lot from 8, and we can
figure out how best increase it even more for other target
architectures later.



Re: [PATCH 05/24] aspeed: Don't create unwanted "cortex-a7-arm-cpu" devices

2020-05-18 Thread Joel Stanley
On Mon, 18 May 2020 at 12:24, Cédric Le Goater  wrote:
>
> On 5/18/20 7:03 AM, Markus Armbruster wrote:
> > The number of CPUs is controlled by property "num-cpus".
> > aspeed_soc_ast2600_init() creates the maximum supported number.
> > aspeed_soc_ast2600_realize() realizes only the wanted number.  Works,
> > although it leaves unrealized devices hanging around in the QOM
> > composition tree.  Affects machines ast2600-evb and tacoma-bmc.
> >
> > Make the init functions create only the wanted ones.  Visible in "info
> > qom-tree"; here's the change for ast2600-evb:
> >
> >  /machine (ast2600-evb-machine)
> >[...]
> >/soc (ast2600-a1)
> >  [...]
> >  /cpu[0] (cortex-a7-arm-cpu)
> >/unnamed-gpio-in[0] (irq)
> >/unnamed-gpio-in[1] (irq)
> >/unnamed-gpio-in[2] (irq)
> >/unnamed-gpio-in[3] (irq)
> > -/cpu[1] (cortex-a7-arm-cpu)
> > -  /unnamed-gpio-in[0] (irq)
> > -  /unnamed-gpio-in[1] (irq)
> > -  /unnamed-gpio-in[2] (irq)
> > -  /unnamed-gpio-in[3] (irq)
> >  /ehci[0] (platform-ehci-usb)
> >
> > Cc: "Cédric Le Goater" 
> > Cc: Peter Maydell 
> > Cc: Andrew Jeffery 
> > Cc: Joel Stanley 
> > Cc: qemu-...@nongnu.org
> > Signed-off-by: Markus Armbruster 
>
> Reviewed-by: Cédric Le Goater 
>
> Joel, Andrew,
>
> Shouldn't we enforce a default/min/max number of CPUs of 2 for the AST2600 ?
> That's the SoC definition. The fact it is configurable in the Aspeed model
> was nice to have during bringup but we are now done.

Agreed, we want there to always be two CPUs for the 2600.

>
> Thanks,
>
> C.
>
> > ---
> >  hw/arm/aspeed_ast2600.c | 3 +++
> >  1 file changed, 3 insertions(+)
> >
> > diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
> > index 0a6a77dd54..6ffa587a7f 100644
> > --- a/hw/arm/aspeed_ast2600.c
> > +++ b/hw/arm/aspeed_ast2600.c
> > @@ -287,6 +287,9 @@ static void aspeed_soc_ast2600_realize(DeviceState 
> > *dev, Error **errp)
> >  return;
> >  }
> >  }
> > +for (; i < sc->num_cpus; i++) {
> > +object_unparent(OBJECT(>cpu[i]));
> > +}
> >
> >  /* A7MPCORE */
> >  object_property_set_int(OBJECT(>a7mpcore), s->num_cpus, "num-cpu",
> >
>



Re: [PATCH 04/24] aspeed: Don't create unwanted "ftgmac100", "aspeed-mmi" devices

2020-05-18 Thread Joel Stanley
On Mon, 18 May 2020 at 12:19, Cédric Le Goater  wrote:
>
> On 5/18/20 7:03 AM, Markus Armbruster wrote:
> > These devices are optional, and controlled by @nb_nics.
> > aspeed_soc_ast2600_init() and aspeed_soc_init() create the maximum
> > supported number.  aspeed_soc_ast2600_realize() and
> > aspeed_soc_realize() realize only the wanted number.  Works, although
> > it can leave unrealized devices hanging around in the QOM composition
> > tree.  Affects machines ast2500-evb, ast2600-evb, palmetto-bmc,
> > romulus-bmc, swift-bmc, tacoma-bmc, and witherspoon-bmc.
> >
> > Make the init functions create only the wanted ones.  Visible in "info
> > qom-tree"; here's the change for ast2600-evb:
> >
> >  /machine (ast2600-evb-machine)
> >[...]
> >/soc (ast2600-a1)
> >  [...]
> >  /ftgmac100[0] (ftgmac100)
> >/ftgmac100[0] (qemu:memory-region)
> > -/ftgmac100[1] (ftgmac100)
> > -/ftgmac100[2] (ftgmac100)
> > -/ftgmac100[3] (ftgmac100)
> >  /gpio (aspeed.gpio-ast2600)
> >  [...]
> >  /mii[0] (aspeed-mmi)
> >/aspeed-mmi[0] (qemu:memory-region)
> > -/mii[1] (aspeed-mmi)
> > -/mii[2] (aspeed-mmi)
> > -/mii[3] (aspeed-mmi)
> >  /rtc (aspeed.rtc)
> >
> > I'm not sure creating @nb_nics devices makes sense.  How many does the
> > physical chip provide?
>
> The AST2400, AST2500 SoC have 2 macs and the AST2600 has 4. Each machine
> define the one it uses, generally MAC0 but the tacoma board uses MAC3.
>
> Shouldn't the model reflect the real address space independently from
> the NIC backends defined on the command line ?

Agreed, the MAC hardware is present in all instances of the AST2600,
so they should be present in qemu. Only some boards wire up a network
device to the other side.

It would be advantageous for us to be able to specify which device is
being connected to on the command line. Currently we do this by
connecting all devices up to the one we care about which is an ugly
workaround.

> How should we proceed in such cases ?
>
> Thanks,
>
> C.
>
> >
> > Cc: "Cédric Le Goater" 
> > Cc: Peter Maydell 
> > Cc: Andrew Jeffery 
> > Cc: Joel Stanley 
> > Cc: qemu-...@nongnu.org
> > Signed-off-by: Markus Armbruster 
> > ---
> >  hw/arm/aspeed_ast2600.c | 2 +-
> >  hw/arm/aspeed_soc.c | 2 +-
> >  2 files changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
> > index 71a0acfe26..0a6a77dd54 100644
> > --- a/hw/arm/aspeed_ast2600.c
> > +++ b/hw/arm/aspeed_ast2600.c
> > @@ -188,7 +188,7 @@ static void aspeed_soc_ast2600_init(Object *obj)
> >sizeof(s->wdt[i]), typename);
> >  }
> >
> > -for (i = 0; i < sc->macs_num; i++) {
> > +for (i = 0; i < nb_nics && i < sc->macs_num; i++) {
> >  sysbus_init_child_obj(obj, "ftgmac100[*]", 
> > OBJECT(>ftgmac100[i]),
> >sizeof(s->ftgmac100[i]), TYPE_FTGMAC100);
> >
> > diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
> > index cf6b6dd116..7ca860392a 100644
> > --- a/hw/arm/aspeed_soc.c
> > +++ b/hw/arm/aspeed_soc.c
> > @@ -203,7 +203,7 @@ static void aspeed_soc_init(Object *obj)
> >sizeof(s->wdt[i]), typename);
> >  }
> >
> > -for (i = 0; i < sc->macs_num; i++) {
> > +for (i = 0; i < nb_nics && i < sc->macs_num; i++) {
> >  sysbus_init_child_obj(obj, "ftgmac100[*]", 
> > OBJECT(>ftgmac100[i]),
> >sizeof(s->ftgmac100[i]), TYPE_FTGMAC100);
> >  }
> >
>



Re: [PATCH RFC 01/32] python/qemu: create qemu.lib module

2020-05-18 Thread John Snow



On 5/18/20 3:33 PM, Vladimir Sementsov-Ogievskiy wrote:
> 18.05.2020 21:23, John Snow wrote:
>>
>>
>> On 5/18/20 2:14 PM, Vladimir Sementsov-Ogievskiy wrote:
>>> 14.05.2020 08:53, John Snow wrote:
 move python/qemu/*.py to python/qemu/lib/*.py.

 To create a namespace package, the 'qemu' directory itself shouldn't
 have module files in it. Thus, these files will go under a 'lib'
 package
 directory instead.
>>>
>>> Hmm..
>>>
>>> On the first glance, it looks better to have
>>>
>>>    from qemu import QEMUMachine
>>>
>>> than
>>>      from qemu.lib import QEMUMachine
>>>
>>> why do we need this extra ".lib" part?
>>>
>>> Is it needed only for internal use?
>>>
>>> Assume we have installed qemu package. Can we write
>>>
>>>    from qemu import QEMUMachine
>>>
>>> ? Or we still need qemu.lib ?
>>>
>>> I don't remember any python package, which made me to write "import from
>>> package_name.lib ..."
>>>
>>>
>>
>> It's a strategy to create "qemu" as a PEP420 namespace package; i.e.
>> "qemu" forms a namespace, but you need a name for the actual package
>> underneath it.
>>
>> "qemu.lib" is one package, with qmp, qtest, and machine modules. "qemu"
>> isn't really a package in this system, it's just a namespace.
>>
>> The idea is that this allows us to create a more modular rollout of
>> various python scripts and services as desired instead of monolithically
>> bundling them all inside of a "qemu" package.
>>
>> It also allows us to fork or split out the sub-packages to separate
>> repos, if we wish. i.e., let's say we create a "qemu.sdk" subpackage, we
>> can eventually fork it off into its own repo with its own installer and
>> so forth. These subpackages can be installed and managed separately.
>>
> 
> Okay, I understand.. No real objections than.
> 
> Still, maybe, everything should not go into lib, maybe something like
> 
> qemu/vm/  - qmp, QEMUMachine, etc
> qemu/qtest/  - qtest
> 
> would be more user friendly? But I'm not sure. I just thought that "lib"
> is too generic.
> 

lib is a very generic name, I agree.

Splitting accel, qmp and QEMUMachine in one package and keeping qtest in
another is fine too. I'm not sure if I like "vm" for the name of that
core package, though.

I want to avoid using "qemu/sdk" because I have some plans for trying to
generate and package a "real" SDK using that namespace.

"devkit"? "testkit"? "core"? Naming things is always the worst part.

--js




Re: [PATCH 04/24] aspeed: Don't create unwanted "ftgmac100", "aspeed-mmi" devices

2020-05-18 Thread Andrew Jeffery



On Mon, 18 May 2020, at 21:49, Cédric Le Goater wrote:
> On 5/18/20 7:03 AM, Markus Armbruster wrote:
> > These devices are optional, and controlled by @nb_nics.
> > aspeed_soc_ast2600_init() and aspeed_soc_init() create the maximum
> > supported number.  aspeed_soc_ast2600_realize() and
> > aspeed_soc_realize() realize only the wanted number.  Works, although
> > it can leave unrealized devices hanging around in the QOM composition
> > tree.  Affects machines ast2500-evb, ast2600-evb, palmetto-bmc,
> > romulus-bmc, swift-bmc, tacoma-bmc, and witherspoon-bmc.
> > 
> > Make the init functions create only the wanted ones.  Visible in "info
> > qom-tree"; here's the change for ast2600-evb:
> > 
> >  /machine (ast2600-evb-machine)
> >[...]
> >/soc (ast2600-a1)
> >  [...]
> >  /ftgmac100[0] (ftgmac100)
> >/ftgmac100[0] (qemu:memory-region)
> > -/ftgmac100[1] (ftgmac100)
> > -/ftgmac100[2] (ftgmac100)
> > -/ftgmac100[3] (ftgmac100)
> >  /gpio (aspeed.gpio-ast2600)
> >  [...]
> >  /mii[0] (aspeed-mmi)
> >/aspeed-mmi[0] (qemu:memory-region)
> > -/mii[1] (aspeed-mmi)
> > -/mii[2] (aspeed-mmi)
> > -/mii[3] (aspeed-mmi)
> >  /rtc (aspeed.rtc)
> > 
> > I'm not sure creating @nb_nics devices makes sense.  How many does the
> > physical chip provide?
> 
> The AST2400, AST2500 SoC have 2 macs and the AST2600 has 4. Each machine
> define the one it uses, generally MAC0 but the tacoma board uses MAC3.
> 
> Shouldn't the model reflect the real address space independently from
> the NIC backends defined on the command line ?  

That's my feeling too, though I'm not sure what to make of the unrealised 
devices
in the QOM tree. Does it matter? It hasn't bothered me.

Andrew



Re: [PATCH v7 00/14] LUKS: encryption slot management using amend interface

2020-05-18 Thread no-reply
Patchew URL: 
https://patchew.org/QEMU/20200518122041.10694-1-mlevi...@redhat.com/



Hi,

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

Message-id: 20200518122041.10694-1-mlevi...@redhat.com
Subject: [PATCH v7 00/14] LUKS: encryption slot management using amend interface
Type: series

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

Switched to a new branch 'test'
a170aa5 iotests: add tests for blockdev-amend
ccf4ad8 block/qcow2: implement blockdev-amend
f669823 block/crypto: implement blockdev-amend
d14e032 block/core: add generic infrastructure for x-blockdev-amend qmp command
cd60243 iotests: qemu-img tests for luks key management
669924e iotests: filter few more luks specific create options
9b2a290 block/qcow2: extend qemu-img amend interface with crypto options
fe70cac block/crypto: implement the encryption key management
05e4264 block/crypto: rename two functions
50ec885 block/amend: refactor qcow2 amend options
a824f7d block/amend: separate amend and create options for qemu-img
cee3ceb block/amend: add 'force' option
0d15e95 qcrypto/luks: implement encryption key management
fc17979 qcrypto/core: add generic infrastructure for crypto options amendment

=== OUTPUT BEGIN ===
1/14 Checking commit fc17979ac832 (qcrypto/core: add generic infrastructure for 
crypto options amendment)
2/14 Checking commit 0d15e95c3354 (qcrypto/luks: implement encryption key 
management)
3/14 Checking commit cee3cebe91c6 (block/amend: add 'force' option)
4/14 Checking commit a824f7d24eec (block/amend: separate amend and create 
options for qemu-img)
ERROR: Macros with multiple statements should be enclosed in a do - while loop
#32: FILE: block/qcow2.c:5637:
+#define QCOW_COMMON_OPTIONS \
+{   \
+.name = BLOCK_OPT_SIZE, \
+.type = QEMU_OPT_SIZE,  \
+.help = "Virtual disk size" \
+},  \
+{   \
+.name = BLOCK_OPT_COMPAT_LEVEL, \
+.type = QEMU_OPT_STRING,\
+.help = "Compatibility level (v2 [0.10] or v3 [1.1])"   \
+},  \
+{   \
+.name = BLOCK_OPT_BACKING_FILE, \
+.type = QEMU_OPT_STRING,\
+.help = "File name of a base image" \
+},  \
+{   \
+.name = BLOCK_OPT_BACKING_FMT,  \
+.type = QEMU_OPT_STRING,\
+.help = "Image format of the base image"\
+},  \
+{   \
+.name = BLOCK_OPT_DATA_FILE,\
+.type = QEMU_OPT_STRING,\
+.help = "File name of an external data file"\
+},  \
+{   \
+.name = BLOCK_OPT_DATA_FILE_RAW,\
+.type = QEMU_OPT_BOOL,  \
+.help = "The external data file must stay valid "   \
+"as a raw image"\
+},  \
+{   \
+.name = BLOCK_OPT_ENCRYPT,  \
+.type = QEMU_OPT_BOOL,  \
+.help = "Encrypt the image with format 'aes'. (Deprecated " \
+"in favor of " BLOCK_OPT_ENCRYPT_FORMAT "=aes)",\
+},  \
+{   \
+.name = BLOCK_OPT_ENCRYPT_FORMAT,   \
+.type = QEMU_OPT_STRING,\
+.help = "Encrypt the image, format choices: 'aes', 'luks'", \
+},  \
+

Re: [PATCH Kernel v22 5/8] vfio iommu: Implementation of ioctl for dirty pages tracking

2020-05-18 Thread Alex Williamson
On Mon, 18 May 2020 11:26:34 +0530
Kirti Wankhede  wrote:

> VFIO_IOMMU_DIRTY_PAGES ioctl performs three operations:
> - Start dirty pages tracking while migration is active
> - Stop dirty pages tracking.
> - Get dirty pages bitmap. Its user space application's responsibility to
>   copy content of dirty pages from source to destination during migration.
> 
> To prevent DoS attack, memory for bitmap is allocated per vfio_dma
> structure. Bitmap size is calculated considering smallest supported page
> size. Bitmap is allocated for all vfio_dmas when dirty logging is enabled
> 
> Bitmap is populated for already pinned pages when bitmap is allocated for
> a vfio_dma with the smallest supported page size. Update bitmap from
> pinning functions when tracking is enabled. When user application queries
> bitmap, check if requested page size is same as page size used to
> populated bitmap. If it is equal, copy bitmap, but if not equal, return
> error.
> 
> Signed-off-by: Kirti Wankhede 
> Reviewed-by: Neo Jia 
> 
> Fixed error reported by build bot by changing pgsize type from uint64_t
> to size_t.
> Reported-by: kbuild test robot 
> ---
>  drivers/vfio/vfio_iommu_type1.c | 313 
> +++-
>  1 file changed, 307 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
> index de17787ffece..bf740fef196f 100644
> --- a/drivers/vfio/vfio_iommu_type1.c
> +++ b/drivers/vfio/vfio_iommu_type1.c
> @@ -72,6 +72,7 @@ struct vfio_iommu {
>   uint64_tpgsize_bitmap;
>   boolv2;
>   boolnesting;
> + booldirty_page_tracking;
>  };
>  
>  struct vfio_domain {
> @@ -92,6 +93,7 @@ struct vfio_dma {
>   boollock_cap;   /* capable(CAP_IPC_LOCK) */
>   struct task_struct  *task;
>   struct rb_root  pfn_list;   /* Ex-user pinned pfn list */
> + unsigned long   *bitmap;
>  };
>  
>  struct vfio_group {
> @@ -126,6 +128,19 @@ struct vfio_regions {
>  #define IS_IOMMU_CAP_DOMAIN_IN_CONTAINER(iommu)  \
>   (!list_empty(>domain_list))
>  
> +#define DIRTY_BITMAP_BYTES(n)(ALIGN(n, BITS_PER_TYPE(u64)) / 
> BITS_PER_BYTE)
> +
> +/*
> + * Input argument of number of bits to bitmap_set() is unsigned integer, 
> which
> + * further casts to signed integer for unaligned multi-bit operation,
> + * __bitmap_set().
> + * Then maximum bitmap size supported is 2^31 bits divided by 2^3 bits/byte,
> + * that is 2^28 (256 MB) which maps to 2^31 * 2^12 = 2^43 (8TB) on 4K page
> + * system.
> + */
> +#define DIRTY_BITMAP_PAGES_MAX((u64)INT_MAX)
> +#define DIRTY_BITMAP_SIZE_MAX 
> DIRTY_BITMAP_BYTES(DIRTY_BITMAP_PAGES_MAX)
> +
>  static int put_pfn(unsigned long pfn, int prot);
>  
>  /*
> @@ -176,6 +191,74 @@ static void vfio_unlink_dma(struct vfio_iommu *iommu, 
> struct vfio_dma *old)
>   rb_erase(>node, >dma_list);
>  }
>  
> +
> +static int vfio_dma_bitmap_alloc(struct vfio_dma *dma, size_t pgsize)
> +{
> + uint64_t npages = dma->size / pgsize;
> +
> + if (npages > DIRTY_BITMAP_PAGES_MAX)
> + return -EINVAL;
> +
> + dma->bitmap = kvzalloc(DIRTY_BITMAP_BYTES(npages), GFP_KERNEL);

Curious that the extra 8-bytes are added in the next patch, but they're
just as necessary here.

We also have the explanation above about why we have the signed int
size limitation, but we sort of ignore that when adding the bytes here.
That limitation is derived from __bitmap_set(), whereas we only need
these extra bits for bitmap_shift_left(), where I can't spot a signed
int limitation.  Do you come to the same conclusion?  Maybe worth a
comment why we think we can exceed DIRTY_BITMAP_PAGES_MAX for that
extra padding.

> + if (!dma->bitmap)
> + return -ENOMEM;
> +
> + return 0;
> +}
> +
> +static void vfio_dma_bitmap_free(struct vfio_dma *dma)
> +{
> + kfree(dma->bitmap);
> + dma->bitmap = NULL;
> +}
> +
> +static void vfio_dma_populate_bitmap(struct vfio_dma *dma, size_t pgsize)
> +{
> + struct rb_node *p;
> +
> + for (p = rb_first(>pfn_list); p; p = rb_next(p)) {
> + struct vfio_pfn *vpfn = rb_entry(p, struct vfio_pfn, node);
> +
> + bitmap_set(dma->bitmap, (vpfn->iova - dma->iova) / pgsize, 1);
> + }
> +}
> +
> +static int vfio_dma_bitmap_alloc_all(struct vfio_iommu *iommu, size_t pgsize)
> +{
> + struct rb_node *n = rb_first(>dma_list);
> +
> + for (; n; n = rb_next(n)) {

Nit, the previous function above sets the initial value in the for()
statement, it looks like it would fit in 80 columns here too.  We have
examples either way in the code, so not a must fix.

> + struct vfio_dma *dma = rb_entry(n, struct vfio_dma, node);
> + int ret;
> +
> + ret = vfio_dma_bitmap_alloc(dma, pgsize);
> + if (ret) {
> + 

[PATCH v2 2/2] spapr: Add a new level of NUMA for GPUs

2020-05-18 Thread Reza Arbab
NUMA nodes corresponding to GPU memory currently have the same
affinity/distance as normal memory nodes. Add a third NUMA associativity
reference point enabling us to give GPU nodes more distance.

This is guest visible information, which shouldn't change under a
running guest across migration between different qemu versions, so make
the change effective only in new (pseries > 5.0) machine types.

Before, `numactl -H` output in a guest with 4 GPUs (nodes 2-5):

node distances:
node   0   1   2   3   4   5
  0:  10  40  40  40  40  40
  1:  40  10  40  40  40  40
  2:  40  40  10  40  40  40
  3:  40  40  40  10  40  40
  4:  40  40  40  40  10  40
  5:  40  40  40  40  40  10

After:

node distances:
node   0   1   2   3   4   5
  0:  10  40  80  80  80  80
  1:  40  10  80  80  80  80
  2:  80  80  10  80  80  80
  3:  80  80  80  10  80  80
  4:  80  80  80  80  10  80
  5:  80  80  80  80  80  10

These are the same distances as on the host, mirroring the change made
to host firmware in skiboot commit f845a648b8cb ("numa/associativity:
Add a new level of NUMA for GPU's").

Signed-off-by: Reza Arbab 
---
 hw/ppc/spapr.c | 11 +--
 hw/ppc/spapr_pci_nvlink2.c |  2 +-
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 88b4a1f17716..1d9193d5ee49 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -893,7 +893,11 @@ static void spapr_dt_rtas(SpaprMachineState *spapr, void 
*fdt)
 int rtas;
 GString *hypertas = g_string_sized_new(256);
 GString *qemu_hypertas = g_string_sized_new(256);
-uint32_t refpoints[] = { cpu_to_be32(0x4), cpu_to_be32(0x4) };
+uint32_t refpoints[] = {
+cpu_to_be32(0x4),
+cpu_to_be32(0x4),
+cpu_to_be32(0x2),
+};
 uint32_t nr_refpoints;
 uint64_t max_device_addr = MACHINE(spapr)->device_memory->base +
 memory_region_size((spapr)->device_memory->mr);
@@ -4544,7 +4548,7 @@ static void spapr_machine_class_init(ObjectClass *oc, 
void *data)
 smc->linux_pci_probe = true;
 smc->smp_threads_vsmt = true;
 smc->nr_xirqs = SPAPR_NR_XIRQS;
-smc->nr_assoc_refpoints = 2;
+smc->nr_assoc_refpoints = 3;
 xfc->match_nvt = spapr_match_nvt;
 }
 
@@ -4611,8 +4615,11 @@ DEFINE_SPAPR_MACHINE(5_1, "5.1", true);
  */
 static void spapr_machine_5_0_class_options(MachineClass *mc)
 {
+SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+
 spapr_machine_5_1_class_options(mc);
 compat_props_add(mc->compat_props, hw_compat_5_0, hw_compat_5_0_len);
+smc->nr_assoc_refpoints = 2;
 }
 
 DEFINE_SPAPR_MACHINE(5_0, "5.0", false);
diff --git a/hw/ppc/spapr_pci_nvlink2.c b/hw/ppc/spapr_pci_nvlink2.c
index 8332d5694e46..247fd48731e2 100644
--- a/hw/ppc/spapr_pci_nvlink2.c
+++ b/hw/ppc/spapr_pci_nvlink2.c
@@ -362,7 +362,7 @@ void spapr_phb_nvgpu_ram_populate_dt(SpaprPhbState *sphb, 
void *fdt)
 uint32_t associativity[] = {
 cpu_to_be32(0x4),
 SPAPR_GPU_NUMA_ID,
-SPAPR_GPU_NUMA_ID,
+cpu_to_be32(nvslot->numa_id),
 SPAPR_GPU_NUMA_ID,
 cpu_to_be32(nvslot->numa_id)
 };
-- 
2.18.2




[PATCH v2 1/2] spapr: Add associativity reference point count to machine info

2020-05-18 Thread Reza Arbab
Make the number of NUMA associativity reference points a
machine-specific value, using the currently assumed default (two
reference points). This preps the next patch to conditionally change it.

Signed-off-by: Reza Arbab 
---
 hw/ppc/spapr.c | 6 +-
 include/hw/ppc/spapr.h | 1 +
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index c18eab0a2305..88b4a1f17716 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -889,10 +889,12 @@ static int spapr_dt_rng(void *fdt)
 static void spapr_dt_rtas(SpaprMachineState *spapr, void *fdt)
 {
 MachineState *ms = MACHINE(spapr);
+SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(ms);
 int rtas;
 GString *hypertas = g_string_sized_new(256);
 GString *qemu_hypertas = g_string_sized_new(256);
 uint32_t refpoints[] = { cpu_to_be32(0x4), cpu_to_be32(0x4) };
+uint32_t nr_refpoints;
 uint64_t max_device_addr = MACHINE(spapr)->device_memory->base +
 memory_region_size((spapr)->device_memory->mr);
 uint32_t lrdr_capacity[] = {
@@ -944,8 +946,9 @@ static void spapr_dt_rtas(SpaprMachineState *spapr, void 
*fdt)
  qemu_hypertas->str, qemu_hypertas->len));
 g_string_free(qemu_hypertas, TRUE);
 
+nr_refpoints = MIN(smc->nr_assoc_refpoints, ARRAY_SIZE(refpoints));
 _FDT(fdt_setprop(fdt, rtas, "ibm,associativity-reference-points",
- refpoints, sizeof(refpoints)));
+ refpoints, nr_refpoints * sizeof(uint32_t)));
 
 _FDT(fdt_setprop(fdt, rtas, "ibm,max-associativity-domains",
  maxdomains, sizeof(maxdomains)));
@@ -4541,6 +4544,7 @@ static void spapr_machine_class_init(ObjectClass *oc, 
void *data)
 smc->linux_pci_probe = true;
 smc->smp_threads_vsmt = true;
 smc->nr_xirqs = SPAPR_NR_XIRQS;
+smc->nr_assoc_refpoints = 2;
 xfc->match_nvt = spapr_match_nvt;
 }
 
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index e579eaf28c05..abaf9a92adc0 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -129,6 +129,7 @@ struct SpaprMachineClass {
 bool linux_pci_probe;
 bool smp_threads_vsmt; /* set VSMT to smp_threads by default */
 hwaddr rma_limit;  /* clamp the RMA to this size */
+uint32_t nr_assoc_refpoints;
 
 void (*phb_placement)(SpaprMachineState *spapr, uint32_t index,
   uint64_t *buid, hwaddr *pio, 
-- 
2.18.2




Re: [PATCH RFC v2 5/5] iotests: add 287 for block-dirty-bitmap-populate

2020-05-18 Thread Eric Blake

On 5/13/20 10:49 PM, John Snow wrote:

Give block-dirty-bitmap-populate a workout.

Signed-off-by: John Snow 
---
  tests/qemu-iotests/287 |  242 ++
  tests/qemu-iotests/287.out | 4544 


Sheesh, that output file is a workout indeed.


  tests/qemu-iotests/group   |1 +
  3 files changed, 4787 insertions(+)
  create mode 100755 tests/qemu-iotests/287
  create mode 100644 tests/qemu-iotests/287.out


287 has been created in the meantime (commit dd488fc1c00); we'll have to 
rebase.  (Vladimir's series to rename iotests to something sensible 
instead of three digits may help...)



+
+class Drive:
+def __init__(self, path, vm):
+self.path = path
+self.vm = vm
+self.fmt = None
+self.size = None
+self.node = None
+
+def img_create(self, fmt, size):
+self.fmt = fmt
+self.size = size
+iotests.qemu_img_create('-f', self.fmt, self.path, str(self.size))


Are we creating images with backing files anywhere in this test?  Should 
we be?  (The question of what is allocated in the top layer is more 
interesting to answer when there is a backing layer)


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




Simplifying the Hexagon frontend

2020-05-18 Thread Alessandro Di Federico
Hi, this e-mail is intended to bootstrap a public discussion on how to
improve the Hexagon frontend implementation. At rev.ng, Niccolò and I,
developed an Hexagon frontend, and we're (finally!) joining forces with
the QuIC guys to merge our efforts (did you see our talk [1]?).

The status is as follows:

* QuIC has its own fully working implementation that has been submitted
  for review.
* We're working to integrate in their implementation our mechanism to
  automatically generate code to generate tiny code. But this will take
  some more work.

In the following, some initial considerations on how the latest
patchset could be simplified.

Here you can find a graph I've put together of the build process:

https://rev.ng/downloads/qemu-hexagon/temporary/graph.svg
https://rev.ng/downloads/qemu-hexagon/temporary/graph.dot

Colors indicate language.
Oval nodes are generated.
Rectangles are hand-written.

Taylor, I think some simplifications can be made to the process in order
to ease the review process.

* As far as I understand, from he "Source of Truth" set of files
  (`alu.idef`, `encode_pp.def`...), through `gen_semantics`, you
  generate `semantics_generated.pyinc`, which is then included by
  `do_qemu.py` script, which does the real job.

  I would suggest to keep `gen_semantics` and all its inputs
  out-of-tree. It increases complexity in a non-negligible way, while
  bringing a reduced benefit in terms of automation.

  I'd suggest replace `gen_semantics`'s output
  (`semantics_generated.pyinc`) with a human readable JSON file that
  could be manipulated by hand and is then parsed by `do_qemu.py`. I
  think JSON is more appropriate than generating executable python code
  that is then imported.

* I suggest to switch to the decoding approach developed by Richard.
  That would simplify the build process and reduce the code that has to
  be reviewed.
  I'm not 100% of the effort required to do this, maybe Richard can
  weigh on this.

* The current implementation can generate a helper function for each
  Hexagon instruction and, for a subset of instructions, it has an
  "override" mechanism to directly generate tiny code instructions
  corresponding to the semantics of the original instruction (i.e.,
  without using helpers).

  This override mechanism is implemented with the `fWRAP` macros. They
  have benefits, but they are quite convoluted. We should strive to
  minimize the number of macros and alternative macro implementations
  to what's strictly necessary in order to generate as much code as we
  can from the "Source of Truth", but no more than that.

  As a simpler override mechanism, we could use weak functions. But I
  think that, for simplicity, we should try to get in tree a simpler
  version of the frontend that relies exclusively on helper functions.
  It won't have optimal performances, but it will be fully functional.

  Later on, once our work for automatically generating functions
  generating tiny code is mature enough, we can extend the existing
  implementation with an appropriate override system.

In the meantime, we're setting up a Dockerfile based on Debian 10
providing a minimal C toolchain that we can use to automate testing.

Feedback is more than welcome.

-- 
Alessandro Di Federico
rev.ng

[1] https://www.youtube.com/watch?v=3EpnTYBOXCI



Re: [PATCH RFC v2 3/5] qmp: expose block-dirty-bitmap-populate

2020-05-18 Thread Eric Blake

On 5/13/20 10:49 PM, John Snow wrote:

This is a new job-creating command.

Signed-off-by: John Snow 
---
  qapi/block-core.json  | 18 +++
  qapi/transaction.json |  2 ++
  blockdev.c| 74 +++
  3 files changed, 94 insertions(+)

diff --git a/qapi/block-core.json b/qapi/block-core.json
index 0fb527a9a1..f7cae77fc9 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -2250,6 +2250,24 @@
  '*auto-finalize': 'bool',
  '*auto-dismiss': 'bool' } }
  
+##

+# @block-dirty-bitmap-populate:
+#
+# Creates a new job that writes a pattern into a dirty bitmap.
+#
+# Since: 5.0


5.1


+++ b/qapi/transaction.json
@@ -50,6 +50,7 @@
  # - @block-dirty-bitmap-enable: since 4.0
  # - @block-dirty-bitmap-disable: since 4.0
  # - @block-dirty-bitmap-merge: since 4.0
+# - @block-dirty-bitmap-populate: since 5.0


ditto



+++ b/blockdev.c
@@ -2233,6 +2233,63 @@ static void 
block_dirty_bitmap_remove_commit(BlkActionState *common)
  bdrv_release_dirty_bitmap(state->bitmap);
  }
  
+static void block_dirty_bitmap_populate_prepare(BlkActionState *common,

+Error **errp)
+{
+BlockJobActionState *state = DO_UPCAST(BlockJobActionState, common, 
common);
+BlockDirtyBitmapPopulate *bitpop;
+BlockDriverState *bs;
+AioContext *aio_context;
+BdrvDirtyBitmap *bmap = NULL;
+int job_flags = JOB_DEFAULT;
+
+assert(common->action->type == \
+   TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_POPULATE);


\ is not necessary here.


+bitpop = common->action->u.block_dirty_bitmap_populate.data;
+
+bmap = block_dirty_bitmap_lookup(bitpop->node, bitpop->name, , errp);
+if (!bmap) {
+return;
+}


So the bitmap has to already exist, and we are just merging into it, 
correct?


Otherwise looks good.

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




Re: [PATCH not-for-merge 2/5] qom: Make "info qom-tree" show children sorted

2020-05-18 Thread Eric Blake

On 5/18/20 12:19 AM, Markus Armbruster wrote:

"info qom-tree" prints children in unstable order.  This is a pain
when diffing output for different versions to find change.  Print it
sorted.


Yes, this does seem reasonable to include even without the rest of the 
series.




Signed-off-by: Markus Armbruster 
---
  qom/qom-hmp-cmds.c | 40 +++-
  1 file changed, 39 insertions(+), 1 deletion(-)

diff --git a/qom/qom-hmp-cmds.c b/qom/qom-hmp-cmds.c
index 4a61ee1b8c..cf0af8f6b5 100644
--- a/qom/qom-hmp-cmds.c
+++ b/qom/qom-hmp-cmds.c
@@ -78,6 +78,35 @@ static int print_qom_composition_child(Object *obj, void 
*opaque)
  return 0;
  }
  
+static int qom_composition_compare(const void *a, const void *b, void *ignore)

+{
+Object *obja = (void *)a, *objb = (void *)b;


Casting away const...


+const char *namea, *nameb;
+
+if (obja == object_get_root()) {
+namea = g_strdup("");
+} else {
+namea = object_get_canonical_path_component(obja);


...should we instead improve object_get_canonical_path_component to work 
with 'const Object *'?



+}
+
+if (objb == object_get_root()) {
+nameb = g_strdup("");
+} else {
+nameb = object_get_canonical_path_component(objb);
+}
+
+
+return strcmp(namea, nameb);


Why the two blank lines?  This leaks namea and/or nameb if either object 
is the object root.  Should you instead use g_strcmp0 here, with namea/b 
set to NULL instead of g_strdup("") above?




@@ -105,7 +134,16 @@ static void print_qom_composition(Monitor *mon, Object 
*obj, int indent)
  monitor_printf(mon, "%*s/%s (%s)\n", indent, "", name,
 object_get_typename(obj));
  g_free(name);
-object_child_foreach(obj, print_qom_composition_child, );
+
+GQueue children;
+Object *child;


Mid-function declarations - I assume you'd clean this up if we want this 
for real?



+g_queue_init();
+object_child_foreach(obj, insert_qom_composition_child, );
+while ((child = g_queue_pop_head())) {
+print_qom_composition(mon, child, indent + 2);
+}
+(void)s;
+(void)print_qom_composition_child;


Also, this looks like leftover debugger aids?


  }
  
  void hmp_info_qom_tree(Monitor *mon, const QDict *dict)




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




[PULL 7/7] qemu-img: Add bitmap sub-command

2020-05-18 Thread Eric Blake
Include actions for --add, --remove, --clear, --enable, --disable, and
--merge (note that --clear is a bit of fluff, because the same can be
accomplished by removing a bitmap and then adding a new one in its
place, but it matches what QMP commands exist).  Listing is omitted,
because it does not require a bitmap name and because it was already
possible with 'qemu-img info'.  A single command line can play one or
more bitmap commands in sequence on the same bitmap name (although all
added bitmaps share the same granularity, and and all merged bitmaps
come from the same source file).  Merge defaults to other bitmaps in
the primary image, but can also be told to merge bitmaps from a
distinct image.

While this supports --image-opts for the file being modified, I did
not think it worth the extra complexity to support that for the source
file in a cross-file merges.  Likewise, I chose to have --merge only
take a single source rather than following the QMP support for
multiple merges in one go (although you can still use more than one
--merge in the command line); in part because qemu-img is offline and
therefore atomicity is not an issue.

Upcoming patches will add iotest coverage of these commands while
also testing other features.

Signed-off-by: Eric Blake 
Reviewed-by: Max Reitz 
Message-Id: <20200513011648.166876-7-ebl...@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy 
---
 docs/tools/qemu-img.rst |  24 
 qemu-img.c  | 249 
 qemu-img-cmds.hx|   7 ++
 3 files changed, 280 insertions(+)

diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst
index 7d08c48d308f..219483cec279 100644
--- a/docs/tools/qemu-img.rst
+++ b/docs/tools/qemu-img.rst
@@ -281,6 +281,30 @@ Command description:
   For write tests, by default a buffer filled with zeros is written. This can 
be
   overridden with a pattern byte specified by *PATTERN*.

+.. option:: bitmap (--merge SOURCE | --add | --remove | --clear | --enable | 
--disable)... [-b SOURCE_FILE [-F SOURCE_FMT]] [-g GRANULARITY] [--object 
OBJECTDEF] [--image-opts | -f FMT] FILENAME BITMAP
+
+  Perform one or more modifications of the persistent bitmap *BITMAP*
+  in the disk image *FILENAME*.  The various modifications are:
+
+  ``--add`` to create *BITMAP*, enabled to record future edits.
+
+  ``--remove`` to remove *BITMAP*.
+
+  ``--clear`` to clear *BITMAP*.
+
+  ``--enable`` to change *BITMAP* to start recording future edits.
+
+  ``--disable`` to change *BITMAP* to stop recording future edits.
+
+  ``--merge`` to merge the contents of *SOURCE_BITMAP* into *BITMAP*.
+
+  Additional options include ``-g`` which sets a non-default
+  *GRANULARITY* for ``--add``, and ``-b`` and ``-F`` which select an
+  alternative source file for all *SOURCE* bitmaps used by
+  ``--merge``.
+
+  To see what bitmaps are present in an image, use ``qemu-img info``.
+
 .. option:: check [--object OBJECTDEF] [--image-opts] [-q] [-f FMT] 
[--output=OFMT] [-r [leaks | all]] [-T SRC_CACHE] [-U] FILENAME

   Perform a consistency check on the disk image *FILENAME*. The command can
diff --git a/qemu-img.c b/qemu-img.c
index b6e8af9202a5..f940137cb0e5 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -28,6 +28,7 @@
 #include "qemu-common.h"
 #include "qemu-version.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-block-core.h"
 #include "qapi/qapi-visit-block-core.h"
 #include "qapi/qobject-output-visitor.h"
 #include "qapi/qmp/qjson.h"
@@ -71,6 +72,12 @@ enum {
 OPTION_SHRINK = 266,
 OPTION_SALVAGE = 267,
 OPTION_TARGET_IS_ZERO = 268,
+OPTION_ADD = 269,
+OPTION_REMOVE = 270,
+OPTION_CLEAR = 271,
+OPTION_ENABLE = 272,
+OPTION_DISABLE = 273,
+OPTION_MERGE = 274,
 };

 typedef enum OutputFormat {
@@ -169,6 +176,14 @@ static void QEMU_NORETURN help(void)
"  '-n' skips the target volume creation (useful if the volume is 
created\n"
"   prior to running qemu-img)\n"
"\n"
+   "Parameters to bitmap subcommand:\n"
+   "  'bitmap' is the name of the bitmap to manipulate, through one or 
more\n"
+   "   actions from '--add', '--remove', '--clear', '--enable', 
'--disable',\n"
+   "   or '--merge source'\n"
+   "  '-g granularity' sets the granularity for '--add' actions\n"
+   "  '-b source' and '-F src_fmt' tell '--merge' actions to find the 
source\n"
+   "   bitmaps from an alternative file\n"
+   "\n"
"Parameters to check subcommand:\n"
"  '-r' tries to repair any inconsistencies that are found during 
the check.\n"
"   '-r leaks' repairs only cluster leaks, whereas '-r all' 
fixes all\n"
@@ -4461,6 +4476,240 @@ out:
 return 0;
 }

+enum ImgBitmapAct {
+BITMAP_ADD,
+BITMAP_REMOVE,
+BITMAP_CLEAR,
+BITMAP_ENABLE,
+BITMAP_DISABLE,
+BITMAP_MERGE,
+};
+typedef struct ImgBitmapAction {
+enum ImgBitmapAct act;
+  

[PULL 6/7] blockdev: Split off basic bitmap operations for qemu-img

2020-05-18 Thread Eric Blake
Upcoming patches want to add some basic bitmap manipulation abilities
to qemu-img.  But blockdev.o is too heavyweight to link into qemu-img
(among other things, it would drag in block jobs and transaction
support - qemu-img does offline manipulation, where atomicity is less
important because there are no concurrent modifications to compete
with), so it's time to split off the bare bones of what we will need
into a new file block/monitor/bitmap-qmp-cmds.o.

This is sufficient to expose 6 QMP commands for use by qemu-img (add,
remove, clear, enable, disable, merge), as well as move the three
helper functions touched in the previous patch.  Regarding
MAINTAINERS, the new file is automatically part of block core, but
also makes sense as related to other dirty bitmap files.

Signed-off-by: Eric Blake 
Reviewed-by: Max Reitz 
Message-Id: <20200513011648.166876-6-ebl...@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy 
---
 Makefile.objs   |   3 +-
 block/monitor/bitmap-qmp-cmds.c | 321 
 blockdev.c  | 284 
 MAINTAINERS |   1 +
 block/monitor/Makefile.objs |   1 +
 5 files changed, 324 insertions(+), 286 deletions(-)
 create mode 100644 block/monitor/bitmap-qmp-cmds.c

diff --git a/Makefile.objs b/Makefile.objs
index a7c967633acf..99774cfd2545 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -13,9 +13,8 @@ chardev-obj-y = chardev/

 authz-obj-y = authz/

-block-obj-y = nbd/
+block-obj-y = block/ block/monitor/ nbd/ scsi/
 block-obj-y += block.o blockjob.o job.o
-block-obj-y += block/ scsi/
 block-obj-y += qemu-io-cmds.o
 block-obj-$(CONFIG_REPLICATION) += replication.o

diff --git a/block/monitor/bitmap-qmp-cmds.c b/block/monitor/bitmap-qmp-cmds.c
new file mode 100644
index ..9f11deec6467
--- /dev/null
+++ b/block/monitor/bitmap-qmp-cmds.c
@@ -0,0 +1,321 @@
+/*
+ * QEMU block dirty bitmap QMP commands
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later.  See the COPYING file in the top-level directory.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+
+#include "block/block_int.h"
+#include "qapi/qapi-commands-block.h"
+#include "qapi/error.h"
+
+/**
+ * block_dirty_bitmap_lookup:
+ * Return a dirty bitmap (if present), after validating
+ * the node reference and bitmap names.
+ *
+ * @node: The name of the BDS node to search for bitmaps
+ * @name: The name of the bitmap to search for
+ * @pbs: Output pointer for BDS lookup, if desired. Can be NULL.
+ * @errp: Output pointer for error information. Can be NULL.
+ *
+ * @return: A bitmap object on success, or NULL on failure.
+ */
+BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node,
+   const char *name,
+   BlockDriverState **pbs,
+   Error **errp)
+{
+BlockDriverState *bs;
+BdrvDirtyBitmap *bitmap;
+
+if (!node) {
+error_setg(errp, "Node cannot be NULL");
+return NULL;
+}
+if (!name) {
+error_setg(errp, "Bitmap name cannot be NULL");
+return NULL;
+}
+bs = bdrv_lookup_bs(node, node, NULL);
+if (!bs) {
+error_setg(errp, "Node '%s' not found", node);
+return NULL;
+}
+
+bitmap = bdrv_find_dirty_bitmap(bs, name);
+if (!bitmap) {
+error_setg(errp, "Dirty bitmap '%s' not found", name);
+return NULL;
+}
+
+if (pbs) {
+*pbs = bs;
+}
+
+return bitmap;
+}
+
+void qmp_block_dirty_bitmap_add(const char *node, const char *name,
+bool has_granularity, uint32_t 

[PULL 4/7] block: Make it easier to learn which BDS support bitmaps

2020-05-18 Thread Eric Blake
Upcoming patches will enhance bitmap support in qemu-img, but in doing
so, it turns out to be nice to suppress output when persistent bitmaps
make no sense (such as on a qcow2 v2 image).  Add a hook to make this
easier to query.

This patch adds a new callback .bdrv_supports_persistent_dirty_bitmap,
rather than trying to shoehorn the answer in via existing callbacks.
In particular, while it might have been possible to overload
.bdrv_co_can_store_new_dirty_bitmap to special-case a NULL input to
answer whether any persistent bitmaps are supported, that is at odds
with whether a particular bitmap can be stored (for example, even on
an image that supports persistent bitmaps but has currently filled up
the maximum number of bitmaps, attempts to store another one should
fail); and the new functionality doesn't require coroutine safety.
Similarly, we could have added one more piece of information to
.bdrv_get_info, but then again, most callers to that function tend to
already discard extraneous information, and making it a catch-all
rather than a series of dedicated scalar queries hasn't really
simplified life.

In the future, when we improve the ability to look up bitmaps through
a filter, we will probably also want to teach the block layer to
automatically let filters pass this request on through.

Signed-off-by: Eric Blake 
Message-Id: <20200513011648.166876-4-ebl...@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy 
---
 block/qcow2.h| 1 +
 include/block/block_int.h| 1 +
 include/block/dirty-bitmap.h | 1 +
 block/dirty-bitmap.c | 9 +
 block/qcow2-bitmap.c | 7 +++
 block/qcow2.c| 2 ++
 6 files changed, 21 insertions(+)

diff --git a/block/qcow2.h b/block/qcow2.h
index 6a8b82e6ccb1..402e8acb1cb7 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -782,6 +782,7 @@ bool qcow2_co_can_store_new_dirty_bitmap(BlockDriverState 
*bs,
 int qcow2_co_remove_persistent_dirty_bitmap(BlockDriverState *bs,
 const char *name,
 Error **errp);
+bool qcow2_supports_persistent_dirty_bitmap(BlockDriverState *bs);

 ssize_t coroutine_fn
 qcow2_co_compress(BlockDriverState *bs, void *dest, size_t dest_size,
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 7ba8c8903609..786bd2d092ea 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -561,6 +561,7 @@ struct BlockDriver {
  uint64_t parent_perm, uint64_t parent_shared,
  uint64_t *nperm, uint64_t *nshared);

+bool (*bdrv_supports_persistent_dirty_bitmap)(BlockDriverState *bs);
 bool (*bdrv_co_can_store_new_dirty_bitmap)(BlockDriverState *bs,
const char *name,
uint32_t granularity,
diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
index 8a1002941892..5a8d52e4deaf 100644
--- a/include/block/dirty-bitmap.h
+++ b/include/block/dirty-bitmap.h
@@ -16,6 +16,7 @@ typedef enum BitmapCheckFlags {

 #define BDRV_BITMAP_MAX_NAME_SIZE 1023

+bool bdrv_supports_persistent_dirty_bitmap(BlockDriverState *bs);
 BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs,
   uint32_t granularity,
   const char *name,
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
index 063793e31606..f9bfc77985e8 100644
--- a/block/dirty-bitmap.c
+++ b/block/dirty-bitmap.c
@@ -478,6 +478,15 @@ int bdrv_remove_persistent_dirty_bitmap(BlockDriverState 
*bs, const char *name,
 }
 }

+bool
+bdrv_supports_persistent_dirty_bitmap(BlockDriverState *bs)
+{
+if (bs->drv && bs->drv->bdrv_supports_persistent_dirty_bitmap) {
+return bs->drv->bdrv_supports_persistent_dirty_bitmap(bs);
+}
+return false;
+}
+
 static bool coroutine_fn
 bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
uint32_t granularity, Error **errp)
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index cb06954b4a5a..1cf6d2ab77a3 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -1748,3 +1748,10 @@ fail:
   name, bdrv_get_device_or_node_name(bs));
 return false;
 }
+
+bool qcow2_supports_persistent_dirty_bitmap(BlockDriverState *bs)
+{
+BDRVQcow2State *s = bs->opaque;
+
+return s->qcow_version >= 3;
+}
diff --git a/block/qcow2.c b/block/qcow2.c
index ad9ab4fafa00..6406027a77eb 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -5783,6 +5783,8 @@ BlockDriver bdrv_qcow2 = {
 .bdrv_detach_aio_context  = qcow2_detach_aio_context,
 .bdrv_attach_aio_context  = qcow2_attach_aio_context,

+.bdrv_supports_persistent_dirty_bitmap =
+qcow2_supports_persistent_dirty_bitmap,
 .bdrv_co_can_store_new_dirty_bitmap = qcow2_co_can_store_new_dirty_bitmap,
  

Re: [PATCH RFC v2 2/5] blockdev: combine DriveBackupState and BlockdevBackupState

2020-05-18 Thread Eric Blake

On 5/13/20 10:49 PM, John Snow wrote:

They have the same fields -- rename it BlockJobState.


This says BlockJobState...



Signed-off-by: John Snow 
---
  blockdev.c | 30 --
  1 file changed, 12 insertions(+), 18 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index b3c840ec03..d3e8a6ca22 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1702,11 +1702,11 @@ static void external_snapshot_clean(BlkActionState 
*common)
  aio_context_release(aio_context);
  }
  
-typedef struct DriveBackupState {

+typedef struct BlockJobActionState {


...but this does not.  I'm assuming it is just a typo in the commit message?

Otherwise,
Reviewed-by: Eric Blake 

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




[PULL 5/7] blockdev: Promote several bitmap functions to non-static

2020-05-18 Thread Eric Blake
The next patch will split blockdev.c, which will require accessing
some previously-static functions from more than one .c file.  But part
of promoting a function to public is picking a naming scheme that does
not reek of exposing too many internals (two of the three functions
were named starting with 'do_').  To make future code motion easier,
perform the function rename and non-static promotion into its own
patch.

Signed-off-by: Eric Blake 
Reviewed-by: Max Reitz 
Message-Id: <20200513011648.166876-5-ebl...@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy 
---
 include/block/block_int.h | 12 ++
 blockdev.c| 47 ---
 2 files changed, 31 insertions(+), 28 deletions(-)

diff --git a/include/block/block_int.h b/include/block/block_int.h
index 786bd2d092ea..4810e6fa5f2c 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -1345,4 +1345,16 @@ int coroutine_fn bdrv_co_create_opts_simple(BlockDriver 
*drv,
 Error **errp);
 extern QemuOptsList bdrv_create_opts_simple;

+BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node,
+   const char *name,
+   BlockDriverState **pbs,
+   Error **errp);
+BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, const char *target,
+  BlockDirtyBitmapMergeSourceList *bms,
+  HBitmap **backup, Error **errp);
+BdrvDirtyBitmap *block_dirty_bitmap_remove(const char *node, const char *name,
+   bool release,
+   BlockDriverState **bitmap_bs,
+   Error **errp);
+
 #endif /* BLOCK_INT_H */
diff --git a/blockdev.c b/blockdev.c
index b3c840ec0312..69a30613a3dd 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1197,10 +1197,10 @@ out_aio_context:
  *
  * @return: A bitmap object on success, or NULL on failure.
  */
-static BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node,
-  const char *name,
-  BlockDriverState **pbs,
-  Error **errp)
+BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node,
+   const char *name,
+   BlockDriverState **pbs,
+   Error **errp)
 {
 BlockDriverState *bs;
 BdrvDirtyBitmap *bitmap;
@@ -2171,11 +2171,6 @@ static void 
block_dirty_bitmap_disable_abort(BlkActionState *common)
 }
 }

-static BdrvDirtyBitmap *do_block_dirty_bitmap_merge(
-const char *node, const char *target,
-BlockDirtyBitmapMergeSourceList *bitmaps,
-HBitmap **backup, Error **errp);
-
 static void block_dirty_bitmap_merge_prepare(BlkActionState *common,
  Error **errp)
 {
@@ -2189,15 +2184,11 @@ static void 
block_dirty_bitmap_merge_prepare(BlkActionState *common,

 action = common->action->u.block_dirty_bitmap_merge.data;

-state->bitmap = do_block_dirty_bitmap_merge(action->node, action->target,
-action->bitmaps, 
>backup,
-errp);
+state->bitmap = block_dirty_bitmap_merge(action->node, action->target,
+ action->bitmaps, >backup,
+ errp);
 }

-static BdrvDirtyBitmap *do_block_dirty_bitmap_remove(
-const char *node, const char *name, bool release,
-BlockDriverState **bitmap_bs, Error **errp);
-
 static void block_dirty_bitmap_remove_prepare(BlkActionState *common,
   Error **errp)
 {
@@ -2211,8 +2202,8 @@ static void 
block_dirty_bitmap_remove_prepare(BlkActionState *common,

 action = common->action->u.block_dirty_bitmap_remove.data;

-state->bitmap = do_block_dirty_bitmap_remove(action->node, action->name,
- false, >bs, errp);
+state->bitmap = block_dirty_bitmap_remove(action->node, action->name,
+  false, >bs, errp);
 if (state->bitmap) {
 bdrv_dirty_bitmap_skip_store(state->bitmap, true);
 bdrv_dirty_bitmap_set_busy(state->bitmap, true);
@@ -2504,9 +2495,10 @@ out:
 aio_context_release(aio_context);
 }

-static BdrvDirtyBitmap *do_block_dirty_bitmap_remove(
-const char *node, const char *name, bool release,
-BlockDriverState **bitmap_bs, Error **errp)
+BdrvDirtyBitmap *block_dirty_bitmap_remove(const char *node, const char *name,
+   bool release,
+  

Re: [PATCH not-for-merge 0/5] Instrumentation for "Fixes around device realization"

2020-05-18 Thread Mark Cave-Ayland
On 18/05/2020 06:19, Markus Armbruster wrote:

> This is the instrumentation mentioned in "[PATCH 00/24] Fixes around
> device realization".
> 
> PATCH 2/5 might have value on its own.  You tell me.
> 
> Shell script to smoke-test all machines:
> 
> #!/bin/sh
> success=0
> fail=0
> ulimit -c 0
> git-describe --dirty --match v\*
> git-log --oneline -1
> for i in bld/*-softmmu
> do
> t=${i%-softmmu}
> t=${t##*/}
> q=$i/qemu-system-$t
> echo "= $t ="
> 
> for m in `$q -M help | sed -n '/(alias of/d;2,$s/ .*//p'`
> do
>   echo "== $m =="
>   echo -e 'info qom-tree\ninfo qtree\nq' | $q -S -accel qtest -display 
> none -L smoke-mon-roms -M $m -monitor stdio
>   if [ $? -eq 0 ]
>   then echo "*** Success: $m ***"; let success++
>   else echo "*** Fail: $m"; let fail++
>   fi
> done
> done
> echo $success succeeded, $fail failed
> 
> 
> Markus Armbruster (5):
>   qom: Instrument to detect missed realize
>   qom: Make "info qom-tree" show children sorted
>   qdev: Make "info qtree" show child devices sorted by QOM path
>   qdev: Instrument to detect missed QOM parenting
>   qdev: Instrument to detect bus mismatch
> 
>  hw/core/qdev.c | 17 
>  qdev-monitor.c | 32 -
>  qom/qom-hmp-cmds.c | 51 +-
>  3 files changed, 98 insertions(+), 2 deletions(-)

Thanks for sharing these patches! I certainly think that they have value and 
after a
quick read through I'm thinking:

- Patch 1 I assume is no longer needed once you previous series is merged

- Patches 2 & 3 would be really useful at the start of your previous series (as
someone who has gone crossed-eyed enough trying to spot these differences, this 
is
really helpful)

- Patches 4 and 5 are good sanity checks for developers but I'm wondering what 
is the
extent of work that needs to be done? Could existing failures be whitelisted 
with the
aim of removal which would then at least prevent new devices being added that 
aren't
correct?


ATB,

Mark.



[PULL 1/7] bitmaps: Update maintainer

2020-05-18 Thread Eric Blake
Dirty bitmaps are important to incremental backups, including exposure
over NBD where I'm already maintainer.  Also, I'm aware that lately I
have been doing as much code/review on bitmaps as John Snow who is
trying to scale back in order to focus elsewhere; and many of the
recent patches have come from Vladimir, who is also interested in
taking on maintainer duties, but would like to start with
co-maintainership.  Therefore, it's time to revamp the ownership of
this category, as agreed between the three of us.

Signed-off-by: Eric Blake 
Message-Id: <20200514180003.325406-1-ebl...@redhat.com>
Acked-by: John Snow 
Reviewed-by: John Snow 
---
 MAINTAINERS | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 47ef3139e6d6..4e99bb05dad8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2011,8 +2011,9 @@ F: qapi/transaction.json
 T: git https://repo.or.cz/qemu/armbru.git block-next

 Dirty Bitmaps
-M: John Snow 
-R: Vladimir Sementsov-Ogievskiy 
+M: Eric Blake 
+M: Vladimir Sementsov-Ogievskiy 
+R: John Snow 
 L: qemu-bl...@nongnu.org
 S: Supported
 F: include/qemu/hbitmap.h
@@ -2023,7 +2024,7 @@ F: migration/block-dirty-bitmap.c
 F: util/hbitmap.c
 F: tests/test-hbitmap.c
 F: docs/interop/bitmaps.rst
-T: git https://github.com/jnsnow/qemu.git bitmaps
+T: git https://repo.or.cz/qemu/ericb.git bitmaps

 Character device backends
 M: Marc-André Lureau 
-- 
2.26.2




[PULL 3/7] qemu-img: Fix stale comments on doc location

2020-05-18 Thread Eric Blake
Missed in commit e13c59fa.

Signed-off-by: Eric Blake 
Reviewed-by: Max Reitz 
Message-Id: <20200513011648.166876-3-ebl...@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy 
---
 qemu-img.c   | 2 +-
 qemu-img-cmds.hx | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/qemu-img.c b/qemu-img.c
index 6a4327aaba56..b6e8af9202a5 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -108,7 +108,7 @@ static void QEMU_NORETURN unrecognized_option(const char 
*option)
 error_exit("unrecognized option '%s'", option);
 }

-/* Please keep in synch with qemu-img.texi */
+/* Please keep in synch with docs/tools/qemu-img.rst */
 static void QEMU_NORETURN help(void)
 {
 const char *help_msg =
diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
index c9c54de1df40..e0886437b1f2 100644
--- a/qemu-img-cmds.hx
+++ b/qemu-img-cmds.hx
@@ -7,7 +7,7 @@ HXCOMM command structures and help message.
 HXCOMM HXCOMM can be used for comments, discarded from both rST and C

 HXCOMM When amending the rST sections, please remember to copy the usage
-HXCOMM over to the per-command sections in qemu-img.texi.
+HXCOMM over to the per-command sections in docs/tools/qemu-img.rst.

 DEF("amend", img_amend,
 "amend [--object objectdef] [--image-opts] [-p] [-q] [-f fmt] [-t cache] 
-o options filename")
-- 
2.26.2




[PULL 2/7] docs: Sort sections on qemu-img subcommand parameters

2020-05-18 Thread Eric Blake
We already list the subcommand summaries alphabetically, we should do
the same for the documentation related to subcommand-specific
parameters.

Signed-off-by: Eric Blake 
Reviewed-by: Max Reitz 
Message-Id: <20200513011648.166876-2-ebl...@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy 
---
 docs/tools/qemu-img.rst | 48 -
 1 file changed, 24 insertions(+), 24 deletions(-)

diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst
index 0080f83a76c9..7d08c48d308f 100644
--- a/docs/tools/qemu-img.rst
+++ b/docs/tools/qemu-img.rst
@@ -142,30 +142,6 @@ by the used format or see the format descriptions below 
for details.
   the documentation of the emulator's ``-drive cache=...`` option for allowed
   values.

-Parameters to snapshot subcommand:
-
-.. program:: qemu-img-snapshot
-
-.. option:: snapshot
-
-  Is the name of the snapshot to create, apply or delete
-
-.. option:: -a
-
-  Applies a snapshot (revert disk to saved state)
-
-.. option:: -c
-
-  Creates a snapshot
-
-.. option:: -d
-
-  Deletes a snapshot
-
-.. option:: -l
-
-  Lists all snapshots in the given image
-
 Parameters to compare subcommand:

 .. program:: qemu-img-compare
@@ -245,6 +221,30 @@ Parameters to dd subcommand:

   Sets the number of input blocks to skip

+Parameters to snapshot subcommand:
+
+.. program:: qemu-img-snapshot
+
+.. option:: snapshot
+
+  Is the name of the snapshot to create, apply or delete
+
+.. option:: -a
+
+  Applies a snapshot (revert disk to saved state)
+
+.. option:: -c
+
+  Creates a snapshot
+
+.. option:: -d
+
+  Deletes a snapshot
+
+.. option:: -l
+
+  Lists all snapshots in the given image
+
 Command description:

 .. program:: qemu-img-commands
-- 
2.26.2




[PULL 0/7] bitmaps patches for 2020-05-18

2020-05-18 Thread Eric Blake
The following changes since commit a28c9c8c9fc42484efe1bf5a77affe842e54e38b:

  Merge remote-tracking branch 'remotes/kraxel/tags/vga-20200518-pull-request' 
into staging (2020-05-18 16:37:09 +0100)

are available in the Git repository at:

  https://repo.or.cz/qemu/ericb.git tags/pull-bitmaps-2020-05-18

for you to fetch changes up to 6660c3a69c668ff98e2a86bca0b1301648ff4b02:

  qemu-img: Add bitmap sub-command (2020-05-18 15:32:56 -0500)


bitmaps patches for 2020-05-18

- update bitmaps maintainers
- add 'qemu-img bitmap' subcommand


Eric Blake (7):
  bitmaps: Update maintainer
  docs: Sort sections on qemu-img subcommand parameters
  qemu-img: Fix stale comments on doc location
  block: Make it easier to learn which BDS support bitmaps
  blockdev: Promote several bitmap functions to non-static
  blockdev: Split off basic bitmap operations for qemu-img
  qemu-img: Add bitmap sub-command

 docs/tools/qemu-img.rst |  72 ++---
 Makefile.objs   |   3 +-
 block/qcow2.h   |   1 +
 include/block/block_int.h   |  13 ++
 include/block/dirty-bitmap.h|   1 +
 block/dirty-bitmap.c|   9 ++
 block/monitor/bitmap-qmp-cmds.c | 321 
 block/qcow2-bitmap.c|   7 +
 block/qcow2.c   |   2 +
 blockdev.c  | 303 +
 qemu-img.c  | 251 ++-
 MAINTAINERS |   8 +-
 block/monitor/Makefile.objs |   1 +
 qemu-img-cmds.hx|   9 +-
 14 files changed, 672 insertions(+), 329 deletions(-)
 create mode 100644 block/monitor/bitmap-qmp-cmds.c

-- 
2.26.2




Re: [PULL 0/6] NBD patches for 2020-05-18

2020-05-18 Thread Eric Blake

On 5/18/20 11:32 AM, Eric Blake wrote:

The following changes since commit debe78ce14bf8f8940c2bdf3ef387505e9e035a9:

   Merge remote-tracking branch 'remotes/rth/tags/pull-fpu-20200515' into 
staging (2020-05-15 19:51:16 +0100)




nbd patches for 2020-05-20


Typo in my signed tag (today is the 18th, not the 20th).  Do you want me 
to send a v2 pull request correcting just that, or shall we overlook it?




- fix stranded fd in 'qemu-nbd -c /dev/nbd0'
- add 'qemu-img map --start-offset --max-length' options



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




Re: [PATCH RFC v2 1/5] block: add bitmap-populate job

2020-05-18 Thread Eric Blake

On 5/13/20 10:49 PM, John Snow wrote:

This job copies the allocation map into a bitmap. It's a job because
there's no guarantee that allocation interrogation will be quick (or
won't hang), so it cannot be retrofit into block-dirty-bitmap-merge.


retrofitted



It was designed with different possible population patterns in mind,
but only top layer allocation was implemented for now.

Signed-off-by: John Snow 
---



+++ b/qapi/block-core.json
@@ -2202,6 +2202,54 @@
{ 'command': 'block-dirty-bitmap-merge',
  'data': 'BlockDirtyBitmapMerge' }
  
+##

+# @BitmapPattern:
+#
+# An enumeration of possible patterns that can be written into a bitmap.
+#
+# @allocation-top: The allocation status of the top layer
+#  of the attached storage node.


Presumably, allocated => bits are set.


+#
+# Since: 5.0


5.1, now


+##
+{ 'enum': 'BitmapPattern',
+  'data': ['allocation-top'] }
+
+##
+# @BlockDirtyBitmapPopulate:
+#
+# @job-id: identifier for the newly-created block job.
+#
+# @pattern: What pattern should be written into the bitmap?
+#
+# @on-error: the action to take if an error is encountered on a bitmap's
+#attached node, default 'report'.
+#'stop' and 'enospc' can only be used if the block device supports
+#io-status (see BlockInfo).
+#
+# @auto-finalize: When false, this job will wait in a PENDING state after it 
has
+# finished its work, waiting for @block-job-finalize before
+# making any block graph changes.
+# When true, this job will automatically
+# perform its abort or commit actions.
+# Defaults to true.
+#
+# @auto-dismiss: When false, this job will wait in a CONCLUDED state after it
+#has completely ceased all work, and awaits @block-job-dismiss.
+#When true, this job will automatically disappear from the 
query
+#list without user intervention.
+#Defaults to true.
+#
+# Since: 5.0


5.1


+##
+{ 'struct': 'BlockDirtyBitmapPopulate',
+  'base': 'BlockDirtyBitmap',
+  'data': { 'job-id': 'str',
+'pattern': 'BitmapPattern',
+'*on-error': 'BlockdevOnError',
+'*auto-finalize': 'bool',
+'*auto-dismiss': 'bool' } }
+
  ##
  # @BlockDirtyBitmapSha256:
  #
diff --git a/qapi/job.json b/qapi/job.json
index 5e658281f5..5f496d4630 100644
--- a/qapi/job.json
+++ b/qapi/job.json
@@ -22,7 +22,7 @@
  # Since: 1.7
  ##
  { 'enum': 'JobType',
-  'data': ['commit', 'stream', 'mirror', 'backup', 'create'] }
+  'data': ['commit', 'stream', 'mirror', 'backup', 'create', 
'bitmap-populate'] }


Missing docs that 'bitmap-populate' is since 5.1.


+++ b/block/bitmap-alloc.c
@@ -0,0 +1,207 @@


New file, but no MAINTAINERS update.  It is covered by 'Block layer 
core', but shouldn't it also be covered by 'Dirty Bitmaps'?




+BlockJob *bitpop_job_create(
+const char *job_id,
+BlockDriverState *bs,
+BdrvDirtyBitmap *target_bitmap,
+BitmapPattern pattern,
+BlockdevOnError on_error,
+int creation_flags,
+BlockCompletionFunc *cb,
+void *opaque,
+JobTxn *txn,
+Error **errp)
+{



+
+/* NB: new bitmap is anonymous and enabled */
+cluster_size = bdrv_dirty_bitmap_granularity(target_bitmap);
+new_bitmap = bdrv_create_dirty_bitmap(bs, cluster_size, NULL, errp);
+if (!new_bitmap) {
+return NULL;
+}


This means if the guest writes to the disk while the job is ongoing, the 
bitmap will be updated to mark that portion of the bitmap as set, even 
if it was not allocated at the time the job started.  But then again, 
the guest writes are causing allocation, so this seems like the right 
thing to do.


Do we need to worry about the converse case where the job started with 
something allocated but runs in parallel with the guest trimming, such 
that our bitmap marks something as set even though at the conclusion of 
our job it is no longer allocated?


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




Re: [PATCH 22/24] qdev: Assert devices are plugged into a bus that can take them

2020-05-18 Thread Mark Cave-Ayland
On 18/05/2020 06:04, Markus Armbruster wrote:

> This would have caught some of the bugs I just fixed.
> 
> Signed-off-by: Markus Armbruster 
> ---
>  hw/core/qdev.c | 5 +
>  1 file changed, 5 insertions(+)
> 
> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
> index 9e5538aeae..0df995eb94 100644
> --- a/hw/core/qdev.c
> +++ b/hw/core/qdev.c
> @@ -97,6 +97,11 @@ static void bus_add_child(BusState *bus, DeviceState 
> *child)
>  void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
>  {
>  BusState *old_parent_bus = dev->parent_bus;
> +DeviceClass *dc = DEVICE_GET_CLASS(dev);
> +
> +assert(dc->bus_type
> +   ? bus && object_dynamic_cast(OBJECT(bus), dc->bus_type)
> +   : !bus);
>  
>  if (old_parent_bus) {
>  trace_qdev_update_parent_bus(dev, object_get_typename(OBJECT(dev)),

Works for me. If you've managed to fix up a large number of bad cases, let's not
allow people to go on making the same mistakes.

Reviewed-by: Mark Cave-Ayland 


ATB,

Mark.



Re: [PATCH 15/24] macio: Fix macio-bus to be a subtype of System bus

2020-05-18 Thread Mark Cave-Ayland
On 18/05/2020 06:03, Markus Armbruster wrote:

> The devices we plug into the macio-bus are all sysbus devices
> (DeviceClass member bus_type is TYPE_SYSTEM_BUS), but macio-bus does
> not derive from TYPE_SYSTEM_BUS.  Fix that.
> 
> "info qtree" now shows the devices' mmio ranges, as it should
> 
> Cc: Mark Cave-Ayland 
> Cc: David Gibson 
> Cc: qemu-...@nongnu.org
> Signed-off-by: Markus Armbruster 
> ---
>  hw/misc/macio/macio.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c
> index ebc96cc8f6..53a9fd5696 100644
> --- a/hw/misc/macio/macio.c
> +++ b/hw/misc/macio/macio.c
> @@ -492,7 +492,7 @@ static void macio_class_init(ObjectClass *klass, void 
> *data)
>  
>  static const TypeInfo macio_bus_info = {
>  .name = TYPE_MACIO_BUS,
> -.parent = TYPE_BUS,
> +.parent = TYPE_SYSTEM_BUS,
>  .instance_size = sizeof(MacIOBusState),
>  };

Here I learned something new: a device that has a class TYPE_SYS_BUS_DEVICE 
should be
attached to a bus that derives from TYPE_SYSTEM_BUS. I have a feeling that 
there are
going to be quite a few instances of this around, particularly in places where
existing sysbus devices have been borrowed from the PC world and reused.


ATB,

Mark.



Re: [PATCH 14/24] macio: Put "macio-nvram" device on the macio bus

2020-05-18 Thread Mark Cave-Ayland
On 18/05/2020 06:03, Markus Armbruster wrote:

> macio_oldworld_init() creates a "macio-nvram", sysbus device, but
> neglects to but it on a bus.
> 
> Put it on the macio bus.  Affects machine g3beige.  Visible in "info
> qtree":
> 
>  bus: macio.0
>type macio-bus
>[...]
> +  dev: macio-nvram, id ""
> +size = 8192 (0x2000)
> +it_shift = 4 (0x4)
> 
> This also makes it a QOM child of macio-oldworld.  Visible in "info
> qom-tree":
> 
>  /machine (g3beige-machine)
>[...]
>/unattached (container)
>  [...]
>  /device[6] (macio-oldworld)
>[...]
> -/device[7] (macio-nvram)
> -  /macio-nvram[0] (qemu:memory-region)
> +  /nvram (macio-nvram)
> +/macio-nvram[0] (qemu:memory-region)
>  [rest of device[*] renumbered...]
> 
> Cc: Mark Cave-Ayland 
> Cc: David Gibson 
> Cc: qemu-...@nongnu.org
> Signed-off-by: Markus Armbruster 
> ---
>  hw/misc/macio/macio.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c
> index b3dddf8be7..ebc96cc8f6 100644
> --- a/hw/misc/macio/macio.c
> +++ b/hw/misc/macio/macio.c
> @@ -245,7 +245,8 @@ static void macio_oldworld_init(Object *obj)
>  
>  macio_init_child_obj(s, "cuda", >cuda, sizeof(s->cuda), TYPE_CUDA);
>  
> -object_initialize(>nvram, sizeof(os->nvram), TYPE_MACIO_NVRAM);
> +macio_init_child_obj(s, "nvram", >nvram, sizeof(os->nvram),
> + TYPE_MACIO_NVRAM);
>  dev = DEVICE(>nvram);
>  qdev_prop_set_uint32(dev, "size", 0x2000);
>  qdev_prop_set_uint32(dev, "it_shift", 4);

Reviewed-by: Mark Cave-Ayland 


ATB,

Mark.



[PATCH v3 1/3] crypto/secret: move main logic from 'secret' to 'secret_common'.

2020-05-18 Thread Alexey Krasikov
Create base class 'common secret'. Move common data and logic from
'secret' to 'common_secret' class. This allowed adding abstraction layer
for easier adding new 'secret' objects in future.
Convert 'secret' class to child from basic 'secret_common' with 'data'
and 'file' properties.

Signed-off-by: Alexey Krasikov 
---
 crypto/Makefile.objs   |   1 +
 crypto/secret.c| 351 +---
 crypto/secret_common.c | 407 +
 include/crypto/secret.h|  20 +-
 include/crypto/secret_common.h |  68 ++
 5 files changed, 486 insertions(+), 361 deletions(-)
 create mode 100644 crypto/secret_common.c
 create mode 100644 include/crypto/secret_common.h

diff --git a/crypto/Makefile.objs b/crypto/Makefile.objs
index c2a371b0b4..695da72dd1 100644
--- a/crypto/Makefile.objs
+++ b/crypto/Makefile.objs
@@ -18,6 +18,7 @@ crypto-obj-y += tlscredsanon.o
 crypto-obj-y += tlscredspsk.o
 crypto-obj-y += tlscredsx509.o
 crypto-obj-y += tlssession.o
+crypto-obj-y += secret_common.o
 crypto-obj-y += secret.o
 crypto-obj-y += pbkdf.o
 crypto-obj-$(CONFIG_NETTLE) += pbkdf-nettle.o
diff --git a/crypto/secret.c b/crypto/secret.c
index a846a3c87c..c1e1145232 100644
--- a/crypto/secret.c
+++ b/crypto/secret.c
@@ -20,16 +20,14 @@
 
 #include "qemu/osdep.h"
 #include "crypto/secret.h"
-#include "crypto/cipher.h"
 #include "qapi/error.h"
 #include "qom/object_interfaces.h"
-#include "qemu/base64.h"
 #include "qemu/module.h"
 #include "trace.h"
 
 
 static void
-qcrypto_secret_load_data(QCryptoSecret *secret,
+qcrypto_secret_load_data(QCryptoSecretCommon *sec_common,
  uint8_t **output,
  size_t *outputlen,
  Error **errp)
@@ -38,6 +36,8 @@ qcrypto_secret_load_data(QCryptoSecret *secret,
 size_t length = 0;
 GError *gerr = NULL;
 
+QCryptoSecret *secret = QCRYPTO_SECRET(sec_common);
+
 *output = NULL;
 *outputlen = 0;
 
@@ -65,198 +65,6 @@ qcrypto_secret_load_data(QCryptoSecret *secret,
 }
 
 
-static void qcrypto_secret_decrypt(QCryptoSecret *secret,
-   const uint8_t *input,
-   size_t inputlen,
-   uint8_t **output,
-   size_t *outputlen,
-   Error **errp)
-{
-g_autofree uint8_t *key = NULL;
-g_autofree uint8_t *ciphertext = NULL;
-g_autofree uint8_t *iv = NULL;
-size_t keylen, ciphertextlen, ivlen;
-g_autoptr(QCryptoCipher) aes = NULL;
-g_autofree uint8_t *plaintext = NULL;
-
-*output = NULL;
-*outputlen = 0;
-
-if (qcrypto_secret_lookup(secret->keyid,
-  , ,
-  errp) < 0) {
-return;
-}
-
-if (keylen != 32) {
-error_setg(errp, "Key should be 32 bytes in length");
-return;
-}
-
-if (!secret->iv) {
-error_setg(errp, "IV is required to decrypt secret");
-return;
-}
-
-iv = qbase64_decode(secret->iv, -1, , errp);
-if (!iv) {
-return;
-}
-if (ivlen != 16) {
-error_setg(errp, "IV should be 16 bytes in length not %zu",
-   ivlen);
-return;
-}
-
-aes = qcrypto_cipher_new(QCRYPTO_CIPHER_ALG_AES_256,
- QCRYPTO_CIPHER_MODE_CBC,
- key, keylen,
- errp);
-if (!aes) {
-return;
-}
-
-if (qcrypto_cipher_setiv(aes, iv, ivlen, errp) < 0) {
-return;
-}
-
-if (secret->format == QCRYPTO_SECRET_FORMAT_BASE64) {
-ciphertext = qbase64_decode((const gchar*)input,
-inputlen,
-,
-errp);
-if (!ciphertext) {
-return;
-}
-plaintext = g_new0(uint8_t, ciphertextlen + 1);
-} else {
-ciphertextlen = inputlen;
-plaintext = g_new0(uint8_t, inputlen + 1);
-}
-if (qcrypto_cipher_decrypt(aes,
-   ciphertext ? ciphertext : input,
-   plaintext,
-   ciphertextlen,
-   errp) < 0) {
-return;
-}
-
-if (plaintext[ciphertextlen - 1] > 16 ||
-plaintext[ciphertextlen - 1] > ciphertextlen) {
-error_setg(errp, "Incorrect number of padding bytes (%d) "
-   "found on decrypted data",
-   (int)plaintext[ciphertextlen - 1]);
-return;
-}
-
-/* Even though plaintext may contain arbitrary NUL
- * ensure it is explicitly NUL terminated.
- */
-ciphertextlen -= plaintext[ciphertextlen - 1];
-plaintext[ciphertextlen] = '\0';
-
-*output = g_steal_pointer();
-*outputlen = ciphertextlen;
-}
-
-
-static void qcrypto_secret_decode(const uint8_t *input,
- 

Re: [PATCH v3 4/7] migration/block-dirty-bitmap: fix bitmaps pre-blockdev migration during mirror job

2020-05-18 Thread Eric Blake

On 5/15/20 7:40 AM, Vladimir Sementsov-Ogievskiy wrote:

Important thing for bitmap migration is to select destination block
node to obtain the migrated bitmap.

Prepatch, on source we use bdrv_get_device_or_node_name() to identify
the node, and on target we do bdrv_lookup_bs.
bdrv_get_device_or_node_name() returns blk name only for direct
children of blk. So, bitmaps of direct children of blks are migrated by
blk name and others - by node name.

Old libvirt is unprepared to bitmap migration by node-name,
node-names are mostly auto-generated. So actually only migration by blk
name works for it.

Newer libvirt will use new interface (which will be added soon) to
specify node-mapping for bitmaps migration explicitly. Still, let's
improve the current behavior a bit.

Now, consider classic libvirt migrations assisted by mirror block job:
mirror block job inserts filter, so our source is not a direct child of
blk, and bitmaps are migrated by node-names. And this just don't work


either "won't" or "doesn't"


with auto-generated node names


trailing '.'



Let's fix it by allowing use blk-name even if some implicit filters are
inserted.


s/allowing use/using/



Note2: we, of course, can't skip filters and use blk name to migrate
bitmaps in filtered node by blk name for this blk if these filters have
named bitmaps which should be migrated.

Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1652424
Signed-off-by: Vladimir Sementsov-Ogievskiy 
---
  migration/block-dirty-bitmap.c | 39 +-
  1 file changed, 38 insertions(+), 1 deletion(-)

diff --git a/migration/block-dirty-bitmap.c b/migration/block-dirty-bitmap.c
index 7e93718086..5d3a7d2b07 100644
--- a/migration/block-dirty-bitmap.c
+++ b/migration/block-dirty-bitmap.c
@@ -319,14 +319,48 @@ static int init_dirty_bitmap_migration(void)
  {
  BlockDriverState *bs;
  DirtyBitmapMigBitmapState *dbms;
+GHashTable *handled_by_blk = g_hash_table_new(NULL, NULL);
+BlockBackend *blk;
  
  dirty_bitmap_mig_state.bulk_completed = false;

  dirty_bitmap_mig_state.prev_bs = NULL;
  dirty_bitmap_mig_state.prev_bitmap = NULL;
  dirty_bitmap_mig_state.no_bitmaps = false;
  
+/*

+ * Use blockdevice name for direct (or filtered) children of named block
+ * backends.
+ */
+for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
+const char *name = blk_name(blk);
+
+if (!name || strcmp(name, "") == 0) {
+continue;
+}
+
+bs = blk_bs(blk);
+
+/* Skip filters without bitmaos */
+while (bs && bs->drv && bs->drv->is_filter &&
+   !bdrv_has_named_bitmaps(bs))
+{
+bs = bs->backing->bs ?: bs->file->bs;


Is this correct, or should it be:

bs = bs->backing ? bs->backing->bs : bs->file->bs;

Otherwise looks reasonable, but I'm hesitant to include it in today's 
bitmap pull request in order to give it more review/testing time.  It 
should be ready for a pull request next week, though.


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




[PATCH v3 3/3] test-crypto-secret: add 'secret_keyring' object tests.

2020-05-18 Thread Alexey Krasikov
Add tests:
  test_secret_keyring_good;
  test_secret_keyring_revoked_key;
  test_secret_keyring_expired_key;
  test_secret_keyring_bad_serial_key;
  test_secret_keyring_bad_key_access_right;

Added tests require libkeyutils. The absence of this library is not
critical, because these tests will be skipped in this case.

Signed-off-by: Alexey Krasikov 
---
 configure  |  25 ++
 tests/Makefile.include |   4 +
 tests/test-crypto-secret.c | 154 +
 3 files changed, 183 insertions(+)

diff --git a/configure b/configure
index 1bae5ec0a1..2ab7d2961c 100755
--- a/configure
+++ b/configure
@@ -6283,6 +6283,28 @@ but not implemented on your system"
 fi
 fi
 
+##
+# check for usable keyutils.h
+
+if test "$linux" = "yes" ; then
+
+have_keyutils=no
+cat > $TMPC << EOF
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+int main(void) {
+return request_key("user", NULL, NULL, 0);
+}
+EOF
+if compile_prog "" "-lkeyutils"; then
+have_keyutils=yes
+fi
+fi
+
 
 ##
 # End of CC checks
@@ -7650,6 +7672,9 @@ fi
 
 if test "$secret_keyring" = "yes" ; then
   echo "CONFIG_SECRET_KEYRING=y" >> $config_host_mak
+  if test "$have_keyutils" = "yes" ; then
+echo "CONFIG_TEST_SECRET_KEYRING=y" >> $config_host_mak
+  fi
 fi
 
 if test "$tcg_interpreter" = "yes"; then
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 03a74b60f6..de13908701 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -538,6 +538,10 @@ tests/benchmark-crypto-cipher$(EXESUF): 
tests/benchmark-crypto-cipher.o $(test-c
 tests/test-crypto-secret$(EXESUF): tests/test-crypto-secret.o 
$(test-crypto-obj-y)
 tests/test-crypto-xts$(EXESUF): tests/test-crypto-xts.o $(test-crypto-obj-y)
 
+ifeq ($(CONFIG_TEST_SECRET_KEYRING),y)
+tests/test-crypto-secret.o-libs := -lkeyutils
+endif
+
 tests/crypto-tls-x509-helpers.o-cflags := $(TASN1_CFLAGS)
 tests/crypto-tls-x509-helpers.o-libs := $(TASN1_LIBS)
 tests/pkix_asn1_tab.o-cflags := $(TASN1_CFLAGS)
diff --git a/tests/test-crypto-secret.c b/tests/test-crypto-secret.c
index 13fc6c4c75..34f5ed75ff 100644
--- a/tests/test-crypto-secret.c
+++ b/tests/test-crypto-secret.c
@@ -24,6 +24,10 @@
 #include "crypto/secret.h"
 #include "qapi/error.h"
 #include "qemu/module.h"
+#ifdef CONFIG_TEST_SECRET_KEYRING
+#include "crypto/secret_keyring.h"
+#include 
+#endif
 
 static void test_secret_direct(void)
 {
@@ -124,6 +128,143 @@ static void test_secret_indirect_emptyfile(void)
 g_free(fname);
 }
 
+#ifdef CONFIG_TEST_SECRET_KEYRING
+
+#define DESCRIPTION "qemu_test_secret"
+#define PAYLOAD "Test Payload"
+
+
+static void test_secret_keyring_good(void)
+{
+char key_str[16];
+Object *sec;
+int32_t key = add_key("user", DESCRIPTION, PAYLOAD,
+  strlen(PAYLOAD), KEY_SPEC_PROCESS_KEYRING);
+
+g_assert(key >= 0);
+
+snprintf(key_str, sizeof(key_str), "0x%08x", key);
+sec = object_new_with_props(
+TYPE_QCRYPTO_SECRET_KEYRING,
+object_get_objects_root(),
+"sec0",
+_abort,
+"serial", key_str,
+NULL);
+
+assert(0 <= keyctl_unlink(key, KEY_SPEC_PROCESS_KEYRING));
+char *pw = qcrypto_secret_lookup_as_utf8("sec0",
+ _abort);
+g_assert_cmpstr(pw, ==, PAYLOAD);
+
+object_unparent(sec);
+g_free(pw);
+}
+
+
+static void test_secret_keyring_revoked_key(void)
+{
+char key_str[16];
+Object *sec;
+int32_t key = add_key("user", DESCRIPTION, PAYLOAD,
+  strlen(PAYLOAD), KEY_SPEC_PROCESS_KEYRING);
+g_assert(key >= 0);
+g_assert_false(keyctl_revoke(key));
+
+snprintf(key_str, sizeof(key_str), "0x%08x", key);
+sec = object_new_with_props(
+TYPE_QCRYPTO_SECRET_KEYRING,
+object_get_objects_root(),
+"sec0",
+NULL,
+"serial", key_str,
+NULL);
+
+g_assert(errno == EKEYREVOKED);
+g_assert(sec == NULL);
+
+keyctl_unlink(key, KEY_SPEC_PROCESS_KEYRING);
+}
+
+
+static void test_secret_keyring_expired_key(void)
+{
+char key_str[16];
+Object *sec;
+int32_t key = add_key("user", DESCRIPTION, PAYLOAD,
+  strlen(PAYLOAD), KEY_SPEC_PROCESS_KEYRING);
+g_assert(key >= 0);
+g_assert_false(keyctl_set_timeout(key, 1));
+sleep(1);
+
+snprintf(key_str, sizeof(key_str), "0x%08x", key);
+sec = object_new_with_props(
+TYPE_QCRYPTO_SECRET_KEYRING,
+object_get_objects_root(),
+"sec0",
+NULL,
+"serial", key_str,
+NULL);
+
+g_assert(errno == EKEYEXPIRED);
+g_assert(sec == NULL);
+
+keyctl_unlink(key, KEY_SPEC_PROCESS_KEYRING);
+}
+
+
+static void test_secret_keyring_bad_serial_key(void)
+{
+Object *sec;
+
+sec = object_new_with_props(
+TYPE_QCRYPTO_SECRET_KEYRING,
+

Re: [PATCH 10/24] macio: Bury unwanted "macio-gpio" devices

2020-05-18 Thread Mark Cave-Ayland
On 18/05/2020 06:03, Markus Armbruster wrote:

> These devices go with the "via-pmu" device, which is controlled by
> property "has-pmu".  macio_newworld_init() creates it unconditionally,
> because the property has not been set then.  macio_newworld_realize()
> realizes it only when the property is true.  Works, although it can
> leave an unrealized device hanging around in the QOM composition tree.
> Affects machine mac99 with via=cuda (default).
> 
> Bury the unwanted device by making macio_newworld_realize() unparent
> it.  Visible in "info qom-tree":
> 
>  /machine (mac99-machine)
>[...]
>/unattached (container)
>  /device[9] (macio-newworld)
>[...]
>/escc-legacy-port[8] (qemu:memory-region)
>/escc-legacy-port[9] (qemu:memory-region)
>/escc-legacy[0] (qemu:memory-region)
> -  /gpio (macio-gpio)
> -/gpio[0] (qemu:memory-region)
>/ide[0] (macio-ide)
>  /ide.0 (IDE)
>  /pmac-ide[0] (qemu:memory-region)
> 
> Cc: Mark Cave-Ayland 
> Cc: David Gibson 
> Cc: qemu-...@nongnu.org
> Signed-off-by: Markus Armbruster 
> ---
>  hw/misc/macio/macio.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c
> index 3779865ab2..b3dddf8be7 100644
> --- a/hw/misc/macio/macio.c
> +++ b/hw/misc/macio/macio.c
> @@ -368,6 +368,8 @@ static void macio_newworld_realize(PCIDevice *d, Error 
> **errp)
>  memory_region_add_subregion(>bar, 0x16000,
>  sysbus_mmio_get_region(sysbus_dev, 0));
>  } else {
> +object_unparent(OBJECT(>gpio));
> +
>  /* CUDA */
>  object_initialize_child(OBJECT(s), "cuda", >cuda, sizeof(s->cuda),
>  TYPE_CUDA, _abort, NULL);

This one is a little more interesting because it comes back to the previous
discussions around if you have a device that contains other devices, should you 
init
all the children in your container device init, and the realize all your 
children in
your container device realize?

If so I guess this patch isn't technically wrong, but it is somewhat misleading 
given
that the existing init/realize pattern here is incorrect. Perhaps it should go 
ahead
and make everything work the "right way"?


ATB,

Mark.



[PATCH v3 2/3] crypto/linux_keyring: add 'secret_keyring' secret object.

2020-05-18 Thread Alexey Krasikov
Add the ability for the secret object to obtain secret data from the
Linux in-kernel key managment and retention facility, as an extra option
to the existing ones: reading from a file or passing directly as a
string.

The secret is identified by the key serial number. The upper layers
need to instantiate the key and make sure the QEMU process has access
permissions to read it.

Signed-off-by: Alexey Krasikov 
---
 configure   |  38 
 crypto/Makefile.objs|   1 +
 crypto/secret_keyring.c | 148 
 include/crypto/secret_keyring.h |  52 +++
 4 files changed, 239 insertions(+)
 create mode 100644 crypto/secret_keyring.c
 create mode 100644 include/crypto/secret_keyring.h

diff --git a/configure b/configure
index 0d69c360c0..1bae5ec0a1 100755
--- a/configure
+++ b/configure
@@ -509,6 +509,7 @@ libpmem=""
 default_devices="yes"
 plugins="no"
 fuzzing="no"
+secret_keyring="yes"
 
 supported_cpu="no"
 supported_os="no"
@@ -1601,6 +1602,10 @@ for opt do
   ;;
   --gdb=*) gdb_bin="$optarg"
   ;;
+  --enable-keyring) secret_keyring="yes"
+  ;;
+  --disable-keyring) secret_keyring="no"
+  ;;
   *)
   echo "ERROR: unknown option $opt"
   echo "Try '$0 --help' for more information"
@@ -6250,6 +6255,34 @@ case "$slirp" in
 ;;
 esac
 
+##
+# check for usable __NR_keyctl syscall
+
+if test "$linux" = "yes" ; then
+
+have_keyring=no
+cat > $TMPC << EOF
+#include 
+#include 
+#include 
+#include 
+int main(void) {
+return syscall(__NR_keyctl, KEYCTL_READ, 0, NULL, NULL, 0);
+}
+EOF
+if compile_prog "" "" ; then
+have_keyring=yes
+fi
+fi
+if test "$secret_keyring" = "yes"
+then
+if test "$have_keyring" != "yes"
+then
+error_exit "syscall __NR_keyctl requested, \
+but not implemented on your system"
+fi
+fi
+
 
 ##
 # End of CC checks
@@ -6733,6 +6766,7 @@ echo "default devices   $default_devices"
 echo "plugin support$plugins"
 echo "fuzzing support   $fuzzing"
 echo "gdb   $gdb_bin"
+echo "Linux keyring support $secret_keyring"
 
 if test "$supported_cpu" = "no"; then
 echo
@@ -7614,6 +7648,10 @@ if test -n "$gdb_bin" ; then
 echo "HAVE_GDB_BIN=$gdb_bin" >> $config_host_mak
 fi
 
+if test "$secret_keyring" = "yes" ; then
+  echo "CONFIG_SECRET_KEYRING=y" >> $config_host_mak
+fi
+
 if test "$tcg_interpreter" = "yes"; then
   QEMU_INCLUDES="-iquote \$(SRC_PATH)/tcg/tci $QEMU_INCLUDES"
 elif test "$ARCH" = "sparc64" ; then
diff --git a/crypto/Makefile.objs b/crypto/Makefile.objs
index 695da72dd1..872c928ac0 100644
--- a/crypto/Makefile.objs
+++ b/crypto/Makefile.objs
@@ -20,6 +20,7 @@ crypto-obj-y += tlscredsx509.o
 crypto-obj-y += tlssession.o
 crypto-obj-y += secret_common.o
 crypto-obj-y += secret.o
+crypto-obj-$(CONFIG_SECRET_KEYRING) += secret_keyring.o
 crypto-obj-y += pbkdf.o
 crypto-obj-$(CONFIG_NETTLE) += pbkdf-nettle.o
 crypto-obj-$(if $(CONFIG_NETTLE),n,$(CONFIG_GCRYPT)) += pbkdf-gcrypt.o
diff --git a/crypto/secret_keyring.c b/crypto/secret_keyring.c
new file mode 100644
index 00..8f256ee3b8
--- /dev/null
+++ b/crypto/secret_keyring.c
@@ -0,0 +1,148 @@
+/*
+ * QEMU crypto secret support
+ *
+ * Copyright 2020 Yandex N.V.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ *
+ */
+
+#include "qemu/osdep.h"
+#include 
+#include 
+#include "qapi/error.h"
+#include "qom/object_interfaces.h"
+#include "trace.h"
+#include "crypto/secret_keyring.h"
+
+
+static inline
+long keyctl_read(int32_t key, uint8_t *buffer, size_t buflen)
+{
+return syscall(__NR_keyctl, KEYCTL_READ, key, buffer, buflen, 0);
+}
+
+
+static void
+qcrypto_secret_keyring_load_data(QCryptoSecretCommon *sec_common,
+ uint8_t **output,
+ size_t  *outputlen,
+ Error   **errp)
+{
+QCryptoSecretKeyring *secret = QCRYPTO_SECRET_KEYRING(sec_common);
+uint8_t  *buffer = NULL;
+long retcode;
+
+*output= NULL;
+*outputlen = 0;
+
+if (!secret->serial) {
+error_setg(errp, "'serial' parameter must be provided");
+return;
+}
+
+retcode = keyctl_read(secret->serial, NULL, 0);
+if (retcode <= 0) {
+

[PATCH v3 0/3] Add secret_keyring object

2020-05-18 Thread Alexey Krasikov
Add the ability to store encryption keys in the Linux keyring
facility.

For that, factor out common parts from secret to a new abstract class
secret_common, and introduce new user-creatable secret_keyring class
inheriting from it.
Use '--enable-keyring/--disable-keyring' configuration parameters
to provide this feature.

Example:

$QEMU -object secret_keyring,id=sec0,serial=0x15968230

Alexey Krasikov (3):
  crypto/secret: move main logic from 'secret' to 'secret_common'.
  crypto/linux_keyring: add 'secret_keyring' secret object.
  test-crypto-secret: add 'secret_keyring' object tests.

 configure   |  63 +
 crypto/Makefile.objs|   2 +
 crypto/secret.c | 351 +--
 crypto/secret_common.c  | 405 
 crypto/secret_keyring.c | 141 +++
 include/crypto/secret.h |  20 +-
 include/crypto/secret_common.h  |  68 ++
 include/crypto/secret_keyring.h |  45 
 tests/Makefile.include  |   4 +
 tests/test-crypto-secret.c  | 154 
 10 files changed, 892 insertions(+), 361 deletions(-)
 create mode 100644 crypto/secret_common.c
 create mode 100644 crypto/secret_keyring.c
 create mode 100644 include/crypto/secret_common.h
 create mode 100644 include/crypto/secret_keyring.h

-- 
2.17.1




[PATCH v6 21/21] hw/mips: Rename malta/mipssim/r4k/jazz files in hw/mips

2020-05-18 Thread Aleksandar Markovic
Machine file names should not have prefix "mips_".

Fuloong2e machine source file will be handled in a separate patch,
to avoid conflicts. That patch is pending integration into the
main tree.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Aleksandar Markovic 
---
 MAINTAINERS   | 9 -
 hw/mips/Makefile.objs | 8 
 hw/mips/{mips_jazz.c => jazz.c}   | 0
 hw/mips/{mips_malta.c => malta.c} | 0
 hw/mips/{mips_mipssim.c => mipssim.c} | 0
 hw/mips/{mips_r4k.c => r4k.c} | 0
 6 files changed, 8 insertions(+), 9 deletions(-)
 rename hw/mips/{mips_jazz.c => jazz.c} (100%)
 rename hw/mips/{mips_malta.c => malta.c} (100%)
 rename hw/mips/{mips_mipssim.c => mipssim.c} (100%)
 rename hw/mips/{mips_r4k.c => r4k.c} (100%)

diff --git a/MAINTAINERS b/MAINTAINERS
index 8d5562c5c7..883d15c9d7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11,7 +11,6 @@ consult qemu-devel and not any specific individual privately.
 
 Descriptions of section entries:
 
-   M: Mail patches to: FullName 
   Maintainers are looking after a certain area and must be CCed on
   patches. They are considered the main contact point.
R: Designated reviewer: FullName 
@@ -1043,7 +1042,7 @@ Jazz
 M: Hervé Poussineau 
 R: Aleksandar Rikalo 
 S: Maintained
-F: hw/mips/mips_jazz.c
+F: hw/mips/jazz.c
 F: hw/display/jazz_led.c
 F: hw/dma/rc4030.c
 
@@ -1054,7 +1053,7 @@ R: Aurelien Jarno 
 S: Maintained
 F: hw/isa/piix4.c
 F: hw/acpi/piix4.c
-F: hw/mips/mips_malta.c
+F: hw/mips/malta.c
 F: hw/mips/gt64xxx_pci.c
 F: include/hw/southbridge/piix.h
 F: tests/acceptance/linux_ssh_mips_malta.py
@@ -1064,7 +1063,7 @@ Mipssim
 M: Aleksandar Markovic 
 R: Aleksandar Rikalo 
 S: Odd Fixes
-F: hw/mips/mips_mipssim.c
+F: hw/mips/mipssim.c
 F: hw/net/mipsnet.c
 
 R4000
@@ -1072,7 +1071,7 @@ M: Aleksandar Markovic 
 R: Aurelien Jarno 
 R: Aleksandar Rikalo 
 S: Obsolete
-F: hw/mips/mips_r4k.c
+F: hw/mips/r4k.c
 
 Fulong 2E
 M: Philippe Mathieu-Daudé 
diff --git a/hw/mips/Makefile.objs b/hw/mips/Makefile.objs
index 525809af07..1d767ed9a8 100644
--- a/hw/mips/Makefile.objs
+++ b/hw/mips/Makefile.objs
@@ -1,8 +1,8 @@
 obj-y += addr.o mips_int.o
-obj-$(CONFIG_R4K) += mips_r4k.o
-obj-$(CONFIG_MALTA) += gt64xxx_pci.o mips_malta.o
-obj-$(CONFIG_MIPSSIM) += mips_mipssim.o
-obj-$(CONFIG_JAZZ) += mips_jazz.o
+obj-$(CONFIG_R4K) += r4k.o
+obj-$(CONFIG_MALTA) += gt64xxx_pci.o malta.o
+obj-$(CONFIG_MIPSSIM) += mipssim.o
+obj-$(CONFIG_JAZZ) += jazz.o
 obj-$(CONFIG_FULONG) += mips_fulong2e.o
 obj-$(CONFIG_MIPS_CPS) += cps.o
 obj-$(CONFIG_MIPS_BOSTON) += boston.o
diff --git a/hw/mips/mips_jazz.c b/hw/mips/jazz.c
similarity index 100%
rename from hw/mips/mips_jazz.c
rename to hw/mips/jazz.c
diff --git a/hw/mips/mips_malta.c b/hw/mips/malta.c
similarity index 100%
rename from hw/mips/mips_malta.c
rename to hw/mips/malta.c
diff --git a/hw/mips/mips_mipssim.c b/hw/mips/mipssim.c
similarity index 100%
rename from hw/mips/mips_mipssim.c
rename to hw/mips/mipssim.c
diff --git a/hw/mips/mips_r4k.c b/hw/mips/r4k.c
similarity index 100%
rename from hw/mips/mips_r4k.c
rename to hw/mips/r4k.c
-- 
2.20.1




[PATCH v6 19/21] target/mips: msa: Split helpers for MSUBV.

2020-05-18 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 6af9d3b752..a0aac3ee10 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 v6 18/21] target/mips: msa: Split helpers for MADDV.

2020-05-18 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 c520405929..6af9d3b752 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 

Re: [PATCH 08/24] mac_via: Fix to realize "mos6522-q800-via*" devices

2020-05-18 Thread Mark Cave-Ayland
On 18/05/2020 06:03, Markus Armbruster wrote:

> mac_via_realize() creates a "mos6522-q800-via1" and a
> "mos6522-q800-via2" device, but neglects to realize them.  Affects
> machine q800.
> 
> I wonder how this ever worked.  If the "device becomes real only on
> realize" thing actually works, then we've always been missing these
> two devices, yet nobody noticed.
> 
> Fix by realizing them right away.
> 
> Fixes: 6dca62af95e0b7020aa00d0ca9b2c421f341
> Cc: Laurent Vivier 
> Signed-off-by: Markus Armbruster 
> ---
>  hw/misc/mac_via.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c
> index e05623d730..ee32f72d75 100644
> --- a/hw/misc/mac_via.c
> +++ b/hw/misc/mac_via.c
> @@ -890,6 +890,9 @@ static void mac_via_realize(DeviceState *dev, Error 
> **errp)
>  object_property_add_alias(OBJECT(dev), "irq[1]", OBJECT(ms),
>SYSBUS_DEVICE_GPIO_IRQ "[0]");
>  
> +qdev_init_nofail(DEVICE(>mos6522_via1));
> +qdev_init_nofail(DEVICE(>mos6522_via2));
> +
>  /* Pass through mos6522 input IRQs */
>  qdev_pass_gpios(DEVICE(>mos6522_via1), dev, "via1-irq");
>  qdev_pass_gpios(DEVICE(>mos6522_via2), dev, "via2-irq");

Reviewed-by: Mark Cave-Ayland 


ATB,

Mark.



[PATCH v6 16/21] target/mips: fpu: Refactor conversion from ieee to mips exception flags

2020-05-18 Thread Aleksandar Markovic
The original coversion function is used for regular and MSA floating
point instructions handling. Since there are some nuanced differences
between regular and MSA floating point exception handling, provide two
instances of the conversion function, rather than just a single common
one. Inline both instances of this function instances for the sake of
performance. Improve variable naming in surrounding code for clarity.

Reviewed-by: Aleksandar Rikalo 
Signed-off-by: Aleksandar Markovic 
---
 target/mips/fpu_helper.c | 55 +++-
 target/mips/internal.h   |  1 -
 target/mips/msa_helper.c | 77 +++-
 3 files changed, 82 insertions(+), 51 deletions(-)

diff --git a/target/mips/fpu_helper.c b/target/mips/fpu_helper.c
index dbb8ca5692..7a3a61cab3 100644
--- a/target/mips/fpu_helper.c
+++ b/target/mips/fpu_helper.c
@@ -189,43 +189,48 @@ void helper_ctc1(CPUMIPSState *env, target_ulong arg1, 
uint32_t fs, uint32_t rt)
 }
 }
 
-int ieee_ex_to_mips(int xcpt)
+static inline int ieee_to_mips_xcpt(int ieee_xcpt)
 {
-int ret = 0;
-if (xcpt) {
-if (xcpt & float_flag_invalid) {
-ret |= FP_INVALID;
-}
-if (xcpt & float_flag_overflow) {
-ret |= FP_OVERFLOW;
-}
-if (xcpt & float_flag_underflow) {
-ret |= FP_UNDERFLOW;
-}
-if (xcpt & float_flag_divbyzero) {
-ret |= FP_DIV0;
-}
-if (xcpt & float_flag_inexact) {
-ret |= FP_INEXACT;
-}
+int mips_xcpt = 0;
+
+if (ieee_xcpt & float_flag_invalid) {
+mips_xcpt |= FP_INVALID;
+}
+if (ieee_xcpt & float_flag_overflow) {
+mips_xcpt |= FP_OVERFLOW;
 }
-return ret;
+if (ieee_xcpt & float_flag_underflow) {
+mips_xcpt |= FP_UNDERFLOW;
+}
+if (ieee_xcpt & float_flag_divbyzero) {
+mips_xcpt |= FP_DIV0;
+}
+if (ieee_xcpt & float_flag_inexact) {
+mips_xcpt |= FP_INEXACT;
+}
+
+return mips_xcpt;
 }
 
 static inline void update_fcr31(CPUMIPSState *env, uintptr_t pc)
 {
-int tmp = ieee_ex_to_mips(get_float_exception_flags(
-  >active_fpu.fp_status));
+int ieee_exception_flags = get_float_exception_flags(
+   >active_fpu.fp_status);
+int mips_exception_flags = 0;
+
+if (ieee_exception_flags) {
+mips_exception_flags = ieee_to_mips_xcpt(ieee_exception_flags);
+}
 
-SET_FP_CAUSE(env->active_fpu.fcr31, tmp);
+SET_FP_CAUSE(env->active_fpu.fcr31, mips_exception_flags);
 
-if (tmp) {
+if (mips_exception_flags)  {
 set_float_exception_flags(0, >active_fpu.fp_status);
 
-if (GET_FP_ENABLE(env->active_fpu.fcr31) & tmp) {
+if (GET_FP_ENABLE(env->active_fpu.fcr31) & mips_exception_flags) {
 do_raise_exception(env, EXCP_FPE, pc);
 } else {
-UPDATE_FP_FLAGS(env->active_fpu.fcr31, tmp);
+UPDATE_FP_FLAGS(env->active_fpu.fcr31, mips_exception_flags);
 }
 }
 }
diff --git a/target/mips/internal.h b/target/mips/internal.h
index 1bf274b3ef..684356e309 100644
--- a/target/mips/internal.h
+++ b/target/mips/internal.h
@@ -224,7 +224,6 @@ uint32_t float_class_s(uint32_t arg, float_status *fst);
 uint64_t float_class_d(uint64_t arg, float_status *fst);
 
 extern unsigned int ieee_rm[];
-int ieee_ex_to_mips(int xcpt);
 void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask);
 
 static inline void restore_rounding_mode(CPUMIPSState *env)
diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c
index 4065cfe4f7..c520405929 100644
--- a/target/mips/msa_helper.c
+++ b/target/mips/msa_helper.c
@@ -5419,54 +5419,81 @@ static inline void check_msacsr_cause(CPUMIPSState 
*env, uintptr_t retaddr)
 #define CLEAR_IS_INEXACT   2
 #define RECIPROCAL_INEXACT 4
 
-static inline int update_msacsr(CPUMIPSState *env, int action, int denormal)
+
+static inline int ieee_to_mips_xcpt_msa(int ieee_xcpt)
 {
-int ieee_ex;
+int mips_xcpt = 0;
 
-int c;
+if (ieee_xcpt & float_flag_invalid) {
+mips_xcpt |= FP_INVALID;
+}
+if (ieee_xcpt & float_flag_overflow) {
+mips_xcpt |= FP_OVERFLOW;
+}
+if (ieee_xcpt & float_flag_underflow) {
+mips_xcpt |= FP_UNDERFLOW;
+}
+if (ieee_xcpt & float_flag_divbyzero) {
+mips_xcpt |= FP_DIV0;
+}
+if (ieee_xcpt & float_flag_inexact) {
+mips_xcpt |= FP_INEXACT;
+}
+
+return mips_xcpt;
+}
+
+static inline int update_msacsr(CPUMIPSState *env, int action, int denormal)
+{
+int ieee_exception_flags;
+int mips_exception_flags = 0;
 int cause;
 int enable;
 
-ieee_ex = get_float_exception_flags(>active_tc.msa_fp_status);
+ieee_exception_flags = get_float_exception_flags(
+   >active_tc.msa_fp_status);
 
 /* QEMU softfloat does not signal all underflow cases */
 if 

[PATCH v6 15/21] target/mips: fpu: Name better paired-single variables

2020-05-18 Thread Aleksandar Markovic
Use consistently 'l' and 'h' for low and high halves.

Reviewed-by: Aleksandar Rikalo 
Signed-off-by: Aleksandar Markovic 
---
 target/mips/fpu_helper.c | 62 
 1 file changed, 31 insertions(+), 31 deletions(-)

diff --git a/target/mips/fpu_helper.c b/target/mips/fpu_helper.c
index 56ba49104e..dbb8ca5692 100644
--- a/target/mips/fpu_helper.c
+++ b/target/mips/fpu_helper.c
@@ -1059,14 +1059,14 @@ uint32_t helper_float_recip1_s(CPUMIPSState *env, 
uint32_t fst0)
 
 uint64_t helper_float_recip1_ps(CPUMIPSState *env, uint64_t fdt0)
 {
-uint32_t fst2;
+uint32_t fstl2;
 uint32_t fsth2;
 
-fst2 = float32_div(float32_one, fdt0 & 0X,
-   >active_fpu.fp_status);
+fstl2 = float32_div(float32_one, fdt0 & 0X,
+>active_fpu.fp_status);
 fsth2 = float32_div(float32_one, fdt0 >> 32, >active_fpu.fp_status);
 update_fcr31(env, GETPC());
-return ((uint64_t)fsth2 << 32) | fst2;
+return ((uint64_t)fsth2 << 32) | fstl2;
 }
 
 uint64_t helper_float_rsqrt1_d(CPUMIPSState *env, uint64_t fdt0)
@@ -1091,15 +1091,15 @@ uint32_t helper_float_rsqrt1_s(CPUMIPSState *env, 
uint32_t fst0)
 
 uint64_t helper_float_rsqrt1_ps(CPUMIPSState *env, uint64_t fdt0)
 {
-uint32_t fst2;
+uint32_t fstl2;
 uint32_t fsth2;
 
-fst2 = float32_sqrt(fdt0 & 0X, >active_fpu.fp_status);
+fstl2 = float32_sqrt(fdt0 & 0X, >active_fpu.fp_status);
 fsth2 = float32_sqrt(fdt0 >> 32, >active_fpu.fp_status);
-fst2 = float32_div(float32_one, fst2, >active_fpu.fp_status);
+fstl2 = float32_div(float32_one, fstl2, >active_fpu.fp_status);
 fsth2 = float32_div(float32_one, fsth2, >active_fpu.fp_status);
 update_fcr31(env, GETPC());
-return ((uint64_t)fsth2 << 32) | fst2;
+return ((uint64_t)fsth2 << 32) | fstl2;
 }
 
 uint64_t helper_float_rint_d(CPUMIPSState *env, uint64_t fs)
@@ -1367,19 +1367,19 @@ uint32_t helper_float_recip2_s(CPUMIPSState *env, 
uint32_t fst0, uint32_t fst2)
 
 uint64_t helper_float_recip2_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t 
fdt2)
 {
-uint32_t fst0 = fdt0 & 0X;
+uint32_t fstl0 = fdt0 & 0X;
 uint32_t fsth0 = fdt0 >> 32;
-uint32_t fst2 = fdt2 & 0X;
+uint32_t fstl2 = fdt2 & 0X;
 uint32_t fsth2 = fdt2 >> 32;
 
-fst2 = float32_mul(fst0, fst2, >active_fpu.fp_status);
+fstl2 = float32_mul(fstl0, fstl2, >active_fpu.fp_status);
 fsth2 = float32_mul(fsth0, fsth2, >active_fpu.fp_status);
-fst2 = float32_chs(float32_sub(fst2, float32_one,
+fstl2 = float32_chs(float32_sub(fstl2, float32_one,
>active_fpu.fp_status));
 fsth2 = float32_chs(float32_sub(fsth2, float32_one,
>active_fpu.fp_status));
 update_fcr31(env, GETPC());
-return ((uint64_t)fsth2 << 32) | fst2;
+return ((uint64_t)fsth2 << 32) | fstl2;
 }
 
 uint64_t helper_float_rsqrt2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2)
@@ -1404,51 +1404,51 @@ uint32_t helper_float_rsqrt2_s(CPUMIPSState *env, 
uint32_t fst0, uint32_t fst2)
 
 uint64_t helper_float_rsqrt2_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t 
fdt2)
 {
-uint32_t fst0 = fdt0 & 0X;
+uint32_t fstl0 = fdt0 & 0X;
 uint32_t fsth0 = fdt0 >> 32;
-uint32_t fst2 = fdt2 & 0X;
+uint32_t fstl2 = fdt2 & 0X;
 uint32_t fsth2 = fdt2 >> 32;
 
-fst2 = float32_mul(fst0, fst2, >active_fpu.fp_status);
+fstl2 = float32_mul(fstl0, fstl2, >active_fpu.fp_status);
 fsth2 = float32_mul(fsth0, fsth2, >active_fpu.fp_status);
-fst2 = float32_sub(fst2, float32_one, >active_fpu.fp_status);
+fstl2 = float32_sub(fstl2, float32_one, >active_fpu.fp_status);
 fsth2 = float32_sub(fsth2, float32_one, >active_fpu.fp_status);
-fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32,
+fstl2 = float32_chs(float32_div(fstl2, FLOAT_TWO32,
>active_fpu.fp_status));
 fsth2 = float32_chs(float32_div(fsth2, FLOAT_TWO32,
>active_fpu.fp_status));
 update_fcr31(env, GETPC());
-return ((uint64_t)fsth2 << 32) | fst2;
+return ((uint64_t)fsth2 << 32) | fstl2;
 }
 
 uint64_t helper_float_addr_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt1)
 {
-uint32_t fst0 = fdt0 & 0X;
+uint32_t fstl0 = fdt0 & 0X;
 uint32_t fsth0 = fdt0 >> 32;
-uint32_t fst1 = fdt1 & 0X;
+uint32_t fstl1 = fdt1 & 0X;
 uint32_t fsth1 = fdt1 >> 32;
-uint32_t fst2;
+uint32_t fstl2;
 uint32_t fsth2;
 
-fst2 = float32_add(fst0, fsth0, >active_fpu.fp_status);
-fsth2 = float32_add(fst1, fsth1, >active_fpu.fp_status);
+fstl2 = float32_add(fstl0, fsth0, >active_fpu.fp_status);
+fsth2 = float32_add(fstl1, fsth1, >active_fpu.fp_status);
 update_fcr31(env, GETPC());
-return ((uint64_t)fsth2 << 32) | fst2;

[PATCH v6 10/21] target/mips: fpu: Remove now unused UNFUSED_FMA and FLOAT_FMA macros

2020-05-18 Thread Aleksandar Markovic
After demacroing ., these macros
are not needed anymore.

Reviewed-by: Aleksandar Rikalo 
Signed-off-by: Aleksandar Markovic 
---
 target/mips/fpu_helper.c | 50 
 1 file changed, 50 deletions(-)

diff --git a/target/mips/fpu_helper.c b/target/mips/fpu_helper.c
index 927bac24ac..e8e50e4bc0 100644
--- a/target/mips/fpu_helper.c
+++ b/target/mips/fpu_helper.c
@@ -1446,56 +1446,6 @@ FLOAT_MINMAX(mina_d, 64, minnummag)
 #undef FLOAT_MINMAX
 
 /* ternary operations */
-#define UNFUSED_FMA(prefix, a, b, c, flags)  \
-{\
-a = prefix##_mul(a, b, >active_fpu.fp_status);  \
-if ((flags) & float_muladd_negate_c) {   \
-a = prefix##_sub(a, c, >active_fpu.fp_status);  \
-} else { \
-a = prefix##_add(a, c, >active_fpu.fp_status);  \
-}\
-if ((flags) & float_muladd_negate_result) {  \
-a = prefix##_chs(a); \
-}\
-}
-
-/* FMA based operations */
-#define FLOAT_FMA(name, type)\
-uint64_t helper_float_ ## name ## _d(CPUMIPSState *env,  \
- uint64_t fdt0, uint64_t fdt1,   \
- uint64_t fdt2)  \
-{\
-UNFUSED_FMA(float64, fdt0, fdt1, fdt2, type);\
-update_fcr31(env, GETPC());  \
-return fdt0; \
-}\
- \
-uint32_t helper_float_ ## name ## _s(CPUMIPSState *env,  \
- uint32_t fst0, uint32_t fst1,   \
- uint32_t fst2)  \
-{\
-UNFUSED_FMA(float32, fst0, fst1, fst2, type);\
-update_fcr31(env, GETPC());  \
-return fst0; \
-}\
- \
-uint64_t helper_float_ ## name ## _ps(CPUMIPSState *env, \
-  uint64_t fdt0, uint64_t fdt1,  \
-  uint64_t fdt2) \
-{\
-uint32_t fst0 = fdt0 & 0X;   \
-uint32_t fsth0 = fdt0 >> 32; \
-uint32_t fst1 = fdt1 & 0X;   \
-uint32_t fsth1 = fdt1 >> 32; \
-uint32_t fst2 = fdt2 & 0X;   \
-uint32_t fsth2 = fdt2 >> 32; \
- \
-UNFUSED_FMA(float32, fst0, fst1, fst2, type);\
-UNFUSED_FMA(float32, fsth0, fsth1, fsth2, type); \
-update_fcr31(env, GETPC());  \
-return ((uint64_t)fsth0 << 32) | fst0;   \
-}
-#undef FLOAT_FMA
 
 uint64_t helper_float_madd_d(CPUMIPSState *env, uint64_t fst0,
  uint64_t fst1, uint64_t fst2)
-- 
2.20.1




[PATCH v6 13/21] target/mips: fpu: Demacro RINT.

2020-05-18 Thread Aleksandar Markovic
This is just a cosmetic change to enable tools like gcov, gdb,
callgrind, etc. to better display involved source code.

Reviewed-by: Aleksandar Rikalo 
Signed-off-by: Aleksandar Markovic 
---
 target/mips/fpu_helper.c | 20 ++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/target/mips/fpu_helper.c b/target/mips/fpu_helper.c
index e227e53f70..dae1331f23 100644
--- a/target/mips/fpu_helper.c
+++ b/target/mips/fpu_helper.c
@@ -1113,10 +1113,26 @@ uint ## bits ## _t helper_float_ ## name(CPUMIPSState 
*env, \
 return fdret;   \
 }
 
-FLOAT_RINT(rint_s, 32)
-FLOAT_RINT(rint_d, 64)
 #undef FLOAT_RINT
 
+uint64_t helper_float_rint_d(CPUMIPSState *env, uint64_t fs)
+{
+uint64_t fdret;
+
+fdret = float64_round_to_int(fs, >active_fpu.fp_status);
+update_fcr31(env, GETPC());
+return fdret;
+}
+
+uint32_t helper_float_rint_s(CPUMIPSState *env, uint32_t fs)
+{
+uint32_t fdret;
+
+fdret = float32_round_to_int(fs, >active_fpu.fp_status);
+update_fcr31(env, GETPC());
+return fdret;
+}
+
 #define FLOAT_CLASS_SIGNALING_NAN  0x001
 #define FLOAT_CLASS_QUIET_NAN  0x002
 #define FLOAT_CLASS_NEGATIVE_INFINITY  0x004
-- 
2.20.1




[PATCH v6 09/21] target/mips: fpu: Demacro NMSUB.

2020-05-18 Thread Aleksandar Markovic
This is just a cosmetic change to enable tools like gcov, gdb,
callgrind, etc. to better display involved source code.

Reviewed-by: Aleksandar Rikalo 
Signed-off-by: Aleksandar Markovic 
---
 target/mips/fpu_helper.c | 44 +++-
 1 file changed, 43 insertions(+), 1 deletion(-)

diff --git a/target/mips/fpu_helper.c b/target/mips/fpu_helper.c
index d4c065f281..927bac24ac 100644
--- a/target/mips/fpu_helper.c
+++ b/target/mips/fpu_helper.c
@@ -1495,7 +1495,6 @@ uint64_t helper_float_ ## name ## _ps(CPUMIPSState *env,  
   \
 update_fcr31(env, GETPC());  \
 return ((uint64_t)fsth0 << 32) | fst0;   \
 }
-FLOAT_FMA(nmsub, float_muladd_negate_result | float_muladd_negate_c)
 #undef FLOAT_FMA
 
 uint64_t helper_float_madd_d(CPUMIPSState *env, uint64_t fst0,
@@ -1619,6 +1618,49 @@ uint64_t helper_float_nmadd_ps(CPUMIPSState *env, 
uint64_t fdt0,
 return ((uint64_t)fsth0 << 32) | fstl0;
 }
 
+uint64_t helper_float_nmsub_d(CPUMIPSState *env, uint64_t fst0,
+ uint64_t fst1, uint64_t fst2)
+{
+fst0 = float64_mul(fst0, fst1, >active_fpu.fp_status);
+fst0 = float64_sub(fst0, fst2, >active_fpu.fp_status);
+fst0 = float64_chs(fst0);
+
+update_fcr31(env, GETPC());
+return fst0;
+}
+
+uint32_t helper_float_nmsub_s(CPUMIPSState *env, uint32_t fst0,
+ uint32_t fst1, uint32_t fst2)
+{
+fst0 = float32_mul(fst0, fst1, >active_fpu.fp_status);
+fst0 = float32_sub(fst0, fst2, >active_fpu.fp_status);
+fst0 = float32_chs(fst0);
+
+update_fcr31(env, GETPC());
+return fst0;
+}
+
+uint64_t helper_float_nmsub_ps(CPUMIPSState *env, uint64_t fdt0,
+  uint64_t fdt1, uint64_t fdt2)
+{
+uint32_t fstl0 = fdt0 & 0X;
+uint32_t fsth0 = fdt0 >> 32;
+uint32_t fstl1 = fdt1 & 0X;
+uint32_t fsth1 = fdt1 >> 32;
+uint32_t fstl2 = fdt2 & 0X;
+uint32_t fsth2 = fdt2 >> 32;
+
+fstl0 = float32_mul(fstl0, fstl1, >active_fpu.fp_status);
+fstl0 = float32_sub(fstl0, fstl2, >active_fpu.fp_status);
+fstl0 = float32_chs(fstl0);
+fsth0 = float32_mul(fsth0, fsth1, >active_fpu.fp_status);
+fsth0 = float32_sub(fsth0, fsth2, >active_fpu.fp_status);
+fsth0 = float32_chs(fsth0);
+
+update_fcr31(env, GETPC());
+return ((uint64_t)fsth0 << 32) | fstl0;
+}
+
 
 #define FLOAT_FMADDSUB(name, bits, muladd_arg)  \
 uint ## bits ## _t helper_float_ ## name(CPUMIPSState *env, \
-- 
2.20.1




[PATCH v6 20/21] hw/mips: Add some logging for bad register offset cases

2020-05-18 Thread Aleksandar Markovic
Log the cases where a guest attempts read or write using bad
register offset.

Reviewed-by: Philippe Mathieu-Daudé 
Tested-by: Philippe Mathieu-Daudé 
Signed-off-by: Aleksandar Markovic 
---
 hw/mips/mips_malta.c | 14 ++
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index e4c4de1b4e..88869b828e 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -427,10 +427,9 @@ static uint64_t malta_fpga_read(void *opaque, hwaddr addr,
 break;
 
 default:
-#if 0
-printf("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n",
-   addr);
-#endif
+qemu_log_mask(LOG_GUEST_ERROR,
+  "malta_fpga_read: Bad register offset 0x"
+  TARGET_FMT_lx "\n", addr);
 break;
 }
 return val;
@@ -515,10 +514,9 @@ static void malta_fpga_write(void *opaque, hwaddr addr,
 break;
 
 default:
-#if 0
-printf("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n",
-   addr);
-#endif
+qemu_log_mask(LOG_GUEST_ERROR,
+  "malta_fpga_write: Bad register offset 0x"
+  TARGET_FMT_lx "\n", addr);
 break;
 }
 }
-- 
2.20.1




[PATCH v6 05/21] target/mips: fpu: Remove now unused macro FLOAT_BINOP

2020-05-18 Thread Aleksandar Markovic
After demacroing ., this macro is not
needed anymore.

Reviewed-by: Aleksandar Rikalo 
Signed-off-by: Aleksandar Markovic 
---
 target/mips/fpu_helper.c | 39 ---
 1 file changed, 39 deletions(-)

diff --git a/target/mips/fpu_helper.c b/target/mips/fpu_helper.c
index 2759c9989d..a3a39681f8 100644
--- a/target/mips/fpu_helper.c
+++ b/target/mips/fpu_helper.c
@@ -1170,45 +1170,6 @@ FLOAT_CLASS(class_d, 64)
 #undef FLOAT_CLASS
 
 /* binary operations */
-#define FLOAT_BINOP(name)  \
-uint64_t helper_float_ ## name ## _d(CPUMIPSState *env,\
- uint64_t fdt0, uint64_t fdt1) \
-{  \
-uint64_t dt2;  \
-   \
-dt2 = float64_ ## name(fdt0, fdt1, >active_fpu.fp_status);\
-update_fcr31(env, GETPC());\
-return dt2;\
-}  \
-   \
-uint32_t helper_float_ ## name ## _s(CPUMIPSState *env,\
- uint32_t fst0, uint32_t fst1) \
-{  \
-uint32_t wt2;  \
-   \
-wt2 = float32_ ## name(fst0, fst1, >active_fpu.fp_status);\
-update_fcr31(env, GETPC());\
-return wt2;\
-}  \
-   \
-uint64_t helper_float_ ## name ## _ps(CPUMIPSState *env,   \
-  uint64_t fdt0,   \
-  uint64_t fdt1)   \
-{  \
-uint32_t fst0 = fdt0 & 0X; \
-uint32_t fsth0 = fdt0 >> 32;   \
-uint32_t fst1 = fdt1 & 0X; \
-uint32_t fsth1 = fdt1 >> 32;   \
-uint32_t wt2;  \
-uint32_t wth2; \
-   \
-wt2 = float32_ ## name(fst0, fst1, >active_fpu.fp_status); \
-wth2 = float32_ ## name(fsth0, fsth1, >active_fpu.fp_status);  \
-update_fcr31(env, GETPC());\
-return ((uint64_t)wth2 << 32) | wt2;   \
-}
-
-#undef FLOAT_BINOP
 
 uint64_t helper_float_add_d(CPUMIPSState *env,
 uint64_t fdt0, uint64_t fdt1)
-- 
2.20.1




[PATCH v6 12/21] target/mips: fpu: Remove now unused FLOAT_CLASS macro

2020-05-18 Thread Aleksandar Markovic
After demacroing CLASS., this macro is not needed anymore.

Reviewed-by: Aleksandar Rikalo 
Signed-off-by: Aleksandar Markovic 
---
 target/mips/fpu_helper.c | 39 ---
 1 file changed, 39 deletions(-)

diff --git a/target/mips/fpu_helper.c b/target/mips/fpu_helper.c
index b3903f5357..e227e53f70 100644
--- a/target/mips/fpu_helper.c
+++ b/target/mips/fpu_helper.c
@@ -1128,45 +1128,6 @@ FLOAT_RINT(rint_d, 64)
 #define FLOAT_CLASS_POSITIVE_SUBNORMAL 0x100
 #define FLOAT_CLASS_POSITIVE_ZERO  0x200
 
-#define FLOAT_CLASS(name, bits)  \
-uint ## bits ## _t float_ ## name(uint ## bits ## _t arg,\
-  float_status *status)  \
-{\
-if (float ## bits ## _is_signaling_nan(arg, status)) {   \
-return FLOAT_CLASS_SIGNALING_NAN;\
-} else if (float ## bits ## _is_quiet_nan(arg, status)) {\
-return FLOAT_CLASS_QUIET_NAN;\
-} else if (float ## bits ## _is_neg(arg)) {  \
-if (float ## bits ## _is_infinity(arg)) {\
-return FLOAT_CLASS_NEGATIVE_INFINITY;\
-} else if (float ## bits ## _is_zero(arg)) { \
-return FLOAT_CLASS_NEGATIVE_ZERO;\
-} else if (float ## bits ## _is_zero_or_denormal(arg)) { \
-return FLOAT_CLASS_NEGATIVE_SUBNORMAL;   \
-} else { \
-return FLOAT_CLASS_NEGATIVE_NORMAL;  \
-}\
-} else { \
-if (float ## bits ## _is_infinity(arg)) {\
-return FLOAT_CLASS_POSITIVE_INFINITY;\
-} else if (float ## bits ## _is_zero(arg)) { \
-return FLOAT_CLASS_POSITIVE_ZERO;\
-} else if (float ## bits ## _is_zero_or_denormal(arg)) { \
-return FLOAT_CLASS_POSITIVE_SUBNORMAL;   \
-} else { \
-return FLOAT_CLASS_POSITIVE_NORMAL;  \
-}\
-}\
-}\
- \
-uint ## bits ## _t helper_float_ ## name(CPUMIPSState *env,  \
- uint ## bits ## _t arg) \
-{\
-return float_ ## name(arg, >active_fpu.fp_status);  \
-}
-
-#undef FLOAT_CLASS
-
 uint64_t float_class_d(uint64_t arg, float_status *status)
 {
 if (float64_is_signaling_nan(arg, status)) {
-- 
2.20.1




[PATCH v6 14/21] target/mips: fpu: Remove now unused FLOAT_RINT macro

2020-05-18 Thread Aleksandar Markovic
After demacroing RINT., this macro is not needed anymore.

Reviewed-by: Aleksandar Rikalo 
Signed-off-by: Aleksandar Markovic 
---
 target/mips/fpu_helper.c | 13 -
 1 file changed, 13 deletions(-)

diff --git a/target/mips/fpu_helper.c b/target/mips/fpu_helper.c
index dae1331f23..56ba49104e 100644
--- a/target/mips/fpu_helper.c
+++ b/target/mips/fpu_helper.c
@@ -1102,19 +1102,6 @@ uint64_t helper_float_rsqrt1_ps(CPUMIPSState *env, 
uint64_t fdt0)
 return ((uint64_t)fsth2 << 32) | fst2;
 }
 
-#define FLOAT_RINT(name, bits)  \
-uint ## bits ## _t helper_float_ ## name(CPUMIPSState *env, \
- uint ## bits ## _t fs) \
-{   \
-uint ## bits ## _t fdret;   \
-\
-fdret = float ## bits ## _round_to_int(fs, >active_fpu.fp_status); \
-update_fcr31(env, GETPC()); \
-return fdret;   \
-}
-
-#undef FLOAT_RINT
-
 uint64_t helper_float_rint_d(CPUMIPSState *env, uint64_t fs)
 {
 uint64_t fdret;
-- 
2.20.1




[PATCH v6 04/21] target/mips: fpu: Demacro DIV.

2020-05-18 Thread Aleksandar Markovic
This is just a cosmetic change to enable tools like gcov, gdb,
callgrind, etc. to better display involved source code.

Reviewed-by: Aleksandar Rikalo 
Signed-off-by: Aleksandar Markovic 
---
 target/mips/fpu_helper.c | 37 -
 1 file changed, 36 insertions(+), 1 deletion(-)

diff --git a/target/mips/fpu_helper.c b/target/mips/fpu_helper.c
index 449e945166..2759c9989d 100644
--- a/target/mips/fpu_helper.c
+++ b/target/mips/fpu_helper.c
@@ -1208,7 +1208,6 @@ uint64_t helper_float_ ## name ## _ps(CPUMIPSState *env,  
 \
 return ((uint64_t)wth2 << 32) | wt2;   \
 }
 
-FLOAT_BINOP(div)
 #undef FLOAT_BINOP
 
 uint64_t helper_float_add_d(CPUMIPSState *env,
@@ -1319,6 +1318,42 @@ uint64_t helper_float_mul_ps(CPUMIPSState *env,
 return ((uint64_t)wth2 << 32) | wtl2;
 }
 
+uint64_t helper_float_div_d(CPUMIPSState *env,
+uint64_t fdt0, uint64_t fdt1)
+{
+uint64_t dt2;
+
+dt2 = float64_div(fdt0, fdt1, >active_fpu.fp_status);
+update_fcr31(env, GETPC());
+return dt2;
+}
+
+uint32_t helper_float_div_s(CPUMIPSState *env,
+uint32_t fst0, uint32_t fst1)
+{
+uint32_t wt2;
+
+wt2 = float32_div(fst0, fst1, >active_fpu.fp_status);
+update_fcr31(env, GETPC());
+return wt2;
+}
+
+uint64_t helper_float_div_ps(CPUMIPSState *env,
+ uint64_t fdt0, uint64_t fdt1)
+{
+uint32_t fstl0 = fdt0 & 0X;
+uint32_t fsth0 = fdt0 >> 32;
+uint32_t fstl1 = fdt1 & 0X;
+uint32_t fsth1 = fdt1 >> 32;
+uint32_t wtl2;
+uint32_t wth2;
+
+wtl2 = float32_div(fstl0, fstl1, >active_fpu.fp_status);
+wth2 = float32_div(fsth0, fsth1, >active_fpu.fp_status);
+update_fcr31(env, GETPC());
+return ((uint64_t)wth2 << 32) | wtl2;
+}
+
 
 /* MIPS specific binary operations */
 uint64_t helper_float_recip2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2)
-- 
2.20.1




[PATCH v6 11/21] target/mips: fpu: Demacro CLASS.

2020-05-18 Thread Aleksandar Markovic
This is just a cosmetic change to enable tools like gcov, gdb,
callgrind, etc. to better display involved source code.

Reviewed-by: Aleksandar Rikalo 
Signed-off-by: Aleksandar Markovic 
---
 target/mips/fpu_helper.c | 70 ++--
 1 file changed, 68 insertions(+), 2 deletions(-)

diff --git a/target/mips/fpu_helper.c b/target/mips/fpu_helper.c
index e8e50e4bc0..b3903f5357 100644
--- a/target/mips/fpu_helper.c
+++ b/target/mips/fpu_helper.c
@@ -1165,10 +1165,76 @@ uint ## bits ## _t helper_float_ ## name(CPUMIPSState 
*env,  \
 return float_ ## name(arg, >active_fpu.fp_status);  \
 }
 
-FLOAT_CLASS(class_s, 32)
-FLOAT_CLASS(class_d, 64)
 #undef FLOAT_CLASS
 
+uint64_t float_class_d(uint64_t arg, float_status *status)
+{
+if (float64_is_signaling_nan(arg, status)) {
+return FLOAT_CLASS_SIGNALING_NAN;
+} else if (float64_is_quiet_nan(arg, status)) {
+return FLOAT_CLASS_QUIET_NAN;
+} else if (float64_is_neg(arg)) {
+if (float64_is_infinity(arg)) {
+return FLOAT_CLASS_NEGATIVE_INFINITY;
+} else if (float64_is_zero(arg)) {
+return FLOAT_CLASS_NEGATIVE_ZERO;
+} else if (float64_is_zero_or_denormal(arg)) {
+return FLOAT_CLASS_NEGATIVE_SUBNORMAL;
+} else {
+return FLOAT_CLASS_NEGATIVE_NORMAL;
+}
+} else {
+if (float64_is_infinity(arg)) {
+return FLOAT_CLASS_POSITIVE_INFINITY;
+} else if (float64_is_zero(arg)) {
+return FLOAT_CLASS_POSITIVE_ZERO;
+} else if (float64_is_zero_or_denormal(arg)) {
+return FLOAT_CLASS_POSITIVE_SUBNORMAL;
+} else {
+return FLOAT_CLASS_POSITIVE_NORMAL;
+}
+}
+}
+
+uint64_t helper_float_class_d(CPUMIPSState *env, uint64_t arg)
+{
+return float_class_d(arg, >active_fpu.fp_status);
+}
+
+uint32_t float_class_s(uint32_t arg, float_status *status)
+{
+if (float32_is_signaling_nan(arg, status)) {
+return FLOAT_CLASS_SIGNALING_NAN;
+} else if (float32_is_quiet_nan(arg, status)) {
+return FLOAT_CLASS_QUIET_NAN;
+} else if (float32_is_neg(arg)) {
+if (float32_is_infinity(arg)) {
+return FLOAT_CLASS_NEGATIVE_INFINITY;
+} else if (float32_is_zero(arg)) {
+return FLOAT_CLASS_NEGATIVE_ZERO;
+} else if (float32_is_zero_or_denormal(arg)) {
+return FLOAT_CLASS_NEGATIVE_SUBNORMAL;
+} else {
+return FLOAT_CLASS_NEGATIVE_NORMAL;
+}
+} else {
+if (float32_is_infinity(arg)) {
+return FLOAT_CLASS_POSITIVE_INFINITY;
+} else if (float32_is_zero(arg)) {
+return FLOAT_CLASS_POSITIVE_ZERO;
+} else if (float32_is_zero_or_denormal(arg)) {
+return FLOAT_CLASS_POSITIVE_SUBNORMAL;
+} else {
+return FLOAT_CLASS_POSITIVE_NORMAL;
+}
+}
+}
+
+uint32_t helper_float_class_s(CPUMIPSState *env, uint32_t arg)
+{
+return float_class_s(arg, >active_fpu.fp_status);
+}
+
 /* binary operations */
 
 uint64_t helper_float_add_d(CPUMIPSState *env,
-- 
2.20.1




[PATCH v6 17/21] MAINTAINERS: Change Aleksandar Rikalo's email address

2020-05-18 Thread Aleksandar Markovic
Aleksandar Rikalo wants to use a different email address from
now on.

Reviewed-by: Aleksandar Rikalo 
Reviewed-by: Philippe Mathieu-Daudé 
Tested-by: Philippe Mathieu-Daudé 
Signed-off-by: Aleksandar Markovic 
---
 .mailmap|  3 ++-
 MAINTAINERS | 12 ++--
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/.mailmap b/.mailmap
index 6412067bde..e3628c7a66 100644
--- a/.mailmap
+++ b/.mailmap
@@ -42,7 +42,8 @@ Justin Terry (VM)  Justin Terry (VM) 
via Qemu-devel  

 Aleksandar Markovic  

 Aleksandar Markovic  
-Aleksandar Rikalo  
+Aleksandar Rikalo  
+Aleksandar Rikalo  
 Anthony Liguori  Anthony Liguori 
 James Hogan  
 Leif Lindholm  
diff --git a/MAINTAINERS b/MAINTAINERS
index 1f84e3ae2c..8d5562c5c7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -212,7 +212,7 @@ F: disas/microblaze.c
 MIPS TCG CPUs
 M: Aleksandar Markovic 
 R: Aurelien Jarno 
-R: Aleksandar Rikalo 
+R: Aleksandar Rikalo 
 S: Maintained
 F: target/mips/
 F: default-configs/*mips*
@@ -1041,7 +1041,7 @@ MIPS Machines
 -
 Jazz
 M: Hervé Poussineau 
-R: Aleksandar Rikalo 
+R: Aleksandar Rikalo 
 S: Maintained
 F: hw/mips/mips_jazz.c
 F: hw/display/jazz_led.c
@@ -1062,7 +1062,7 @@ F: tests/acceptance/machine_mips_malta.py
 
 Mipssim
 M: Aleksandar Markovic 
-R: Aleksandar Rikalo 
+R: Aleksandar Rikalo 
 S: Odd Fixes
 F: hw/mips/mips_mipssim.c
 F: hw/net/mipsnet.c
@@ -1070,7 +1070,7 @@ F: hw/net/mipsnet.c
 R4000
 M: Aleksandar Markovic 
 R: Aurelien Jarno 
-R: Aleksandar Rikalo 
+R: Aleksandar Rikalo 
 S: Obsolete
 F: hw/mips/mips_r4k.c
 
@@ -1085,7 +1085,7 @@ F: include/hw/isa/vt82c686.h
 
 Boston
 M: Paul Burton 
-R: Aleksandar Rikalo 
+R: Aleksandar Rikalo 
 S: Maintained
 F: hw/core/loader-fit.c
 F: hw/mips/boston.c
@@ -2582,7 +2582,7 @@ F: disas/i386.c
 MIPS TCG target
 M: Aleksandar Markovic 
 R: Aurelien Jarno 
-R: Aleksandar Rikalo 
+R: Aleksandar Rikalo 
 S: Maintained
 F: tcg/mips/
 
-- 
2.20.1




[PATCH v6 03/21] target/mips: fpu: Demacro MUL.

2020-05-18 Thread Aleksandar Markovic
This is just a cosmetic change to enable tools like gcov, gdb,
callgrind, etc. to better display involved source code.

Reviewed-by: Aleksandar Rikalo 
Signed-off-by: Aleksandar Markovic 
---
 target/mips/fpu_helper.c | 37 -
 1 file changed, 36 insertions(+), 1 deletion(-)

diff --git a/target/mips/fpu_helper.c b/target/mips/fpu_helper.c
index 715a872cae..449e945166 100644
--- a/target/mips/fpu_helper.c
+++ b/target/mips/fpu_helper.c
@@ -1208,7 +1208,6 @@ uint64_t helper_float_ ## name ## _ps(CPUMIPSState *env,  
 \
 return ((uint64_t)wth2 << 32) | wt2;   \
 }
 
-FLOAT_BINOP(mul)
 FLOAT_BINOP(div)
 #undef FLOAT_BINOP
 
@@ -1284,6 +1283,42 @@ uint64_t helper_float_sub_ps(CPUMIPSState *env,
 return ((uint64_t)wth2 << 32) | wtl2;
 }
 
+uint64_t helper_float_mul_d(CPUMIPSState *env,
+uint64_t fdt0, uint64_t fdt1)
+{
+uint64_t dt2;
+
+dt2 = float64_mul(fdt0, fdt1, >active_fpu.fp_status);
+update_fcr31(env, GETPC());
+return dt2;
+}
+
+uint32_t helper_float_mul_s(CPUMIPSState *env,
+uint32_t fst0, uint32_t fst1)
+{
+uint32_t wt2;
+
+wt2 = float32_mul(fst0, fst1, >active_fpu.fp_status);
+update_fcr31(env, GETPC());
+return wt2;
+}
+
+uint64_t helper_float_mul_ps(CPUMIPSState *env,
+ uint64_t fdt0, uint64_t fdt1)
+{
+uint32_t fstl0 = fdt0 & 0X;
+uint32_t fsth0 = fdt0 >> 32;
+uint32_t fstl1 = fdt1 & 0X;
+uint32_t fsth1 = fdt1 >> 32;
+uint32_t wtl2;
+uint32_t wth2;
+
+wtl2 = float32_mul(fstl0, fstl1, >active_fpu.fp_status);
+wth2 = float32_mul(fsth0, fsth1, >active_fpu.fp_status);
+update_fcr31(env, GETPC());
+return ((uint64_t)wth2 << 32) | wtl2;
+}
+
 
 /* MIPS specific binary operations */
 uint64_t helper_float_recip2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2)
-- 
2.20.1




[PATCH v6 08/21] target/mips: fpu: Demacro NMADD.

2020-05-18 Thread Aleksandar Markovic
This is just a cosmetic change to enable tools like gcov, gdb,
callgrind, etc. to better display involved source code.

Reviewed-by: Aleksandar Rikalo 
Signed-off-by: Aleksandar Markovic 
---
 target/mips/fpu_helper.c | 44 +++-
 1 file changed, 43 insertions(+), 1 deletion(-)

diff --git a/target/mips/fpu_helper.c b/target/mips/fpu_helper.c
index e37fc4075d..d4c065f281 100644
--- a/target/mips/fpu_helper.c
+++ b/target/mips/fpu_helper.c
@@ -1495,7 +1495,6 @@ uint64_t helper_float_ ## name ## _ps(CPUMIPSState *env,  
   \
 update_fcr31(env, GETPC());  \
 return ((uint64_t)fsth0 << 32) | fst0;   \
 }
-FLOAT_FMA(nmadd, float_muladd_negate_result)
 FLOAT_FMA(nmsub, float_muladd_negate_result | float_muladd_negate_c)
 #undef FLOAT_FMA
 
@@ -1577,6 +1576,49 @@ uint64_t helper_float_msub_ps(CPUMIPSState *env, 
uint64_t fdt0,
 return ((uint64_t)fsth0 << 32) | fstl0;
 }
 
+uint64_t helper_float_nmadd_d(CPUMIPSState *env, uint64_t fst0,
+ uint64_t fst1, uint64_t fst2)
+{
+fst0 = float64_mul(fst0, fst1, >active_fpu.fp_status);
+fst0 = float64_add(fst0, fst2, >active_fpu.fp_status);
+fst0 = float64_chs(fst0);
+
+update_fcr31(env, GETPC());
+return fst0;
+}
+
+uint32_t helper_float_nmadd_s(CPUMIPSState *env, uint32_t fst0,
+ uint32_t fst1, uint32_t fst2)
+{
+fst0 = float32_mul(fst0, fst1, >active_fpu.fp_status);
+fst0 = float32_add(fst0, fst2, >active_fpu.fp_status);
+fst0 = float32_chs(fst0);
+
+update_fcr31(env, GETPC());
+return fst0;
+}
+
+uint64_t helper_float_nmadd_ps(CPUMIPSState *env, uint64_t fdt0,
+  uint64_t fdt1, uint64_t fdt2)
+{
+uint32_t fstl0 = fdt0 & 0X;
+uint32_t fsth0 = fdt0 >> 32;
+uint32_t fstl1 = fdt1 & 0X;
+uint32_t fsth1 = fdt1 >> 32;
+uint32_t fstl2 = fdt2 & 0X;
+uint32_t fsth2 = fdt2 >> 32;
+
+fstl0 = float32_mul(fstl0, fstl1, >active_fpu.fp_status);
+fstl0 = float32_add(fstl0, fstl2, >active_fpu.fp_status);
+fstl0 = float32_chs(fstl0);
+fsth0 = float32_mul(fsth0, fsth1, >active_fpu.fp_status);
+fsth0 = float32_add(fsth0, fsth2, >active_fpu.fp_status);
+fsth0 = float32_chs(fsth0);
+
+update_fcr31(env, GETPC());
+return ((uint64_t)fsth0 << 32) | fstl0;
+}
+
 
 #define FLOAT_FMADDSUB(name, bits, muladd_arg)  \
 uint ## bits ## _t helper_float_ ## name(CPUMIPSState *env, \
-- 
2.20.1




[PATCH v6 07/21] target/mips: fpu: Demacro MSUB.

2020-05-18 Thread Aleksandar Markovic
This is just a cosmetic change to enable tools like gcov, gdb,
callgrind, etc. to better display involved source code.

Reviewed-by: Aleksandar Rikalo 
Signed-off-by: Aleksandar Markovic 
---
 target/mips/fpu_helper.c | 40 +++-
 1 file changed, 39 insertions(+), 1 deletion(-)

diff --git a/target/mips/fpu_helper.c b/target/mips/fpu_helper.c
index c070081cbc..e37fc4075d 100644
--- a/target/mips/fpu_helper.c
+++ b/target/mips/fpu_helper.c
@@ -1495,7 +1495,6 @@ uint64_t helper_float_ ## name ## _ps(CPUMIPSState *env,  
   \
 update_fcr31(env, GETPC());  \
 return ((uint64_t)fsth0 << 32) | fst0;   \
 }
-FLOAT_FMA(msub, float_muladd_negate_c)
 FLOAT_FMA(nmadd, float_muladd_negate_result)
 FLOAT_FMA(nmsub, float_muladd_negate_result | float_muladd_negate_c)
 #undef FLOAT_FMA
@@ -1539,6 +1538,45 @@ uint64_t helper_float_madd_ps(CPUMIPSState *env, 
uint64_t fdt0,
 return ((uint64_t)fsth0 << 32) | fstl0;
 }
 
+uint64_t helper_float_msub_d(CPUMIPSState *env, uint64_t fst0,
+ uint64_t fst1, uint64_t fst2)
+{
+fst0 = float64_mul(fst0, fst1, >active_fpu.fp_status);
+fst0 = float64_sub(fst0, fst2, >active_fpu.fp_status);
+
+update_fcr31(env, GETPC());
+return fst0;
+}
+
+uint32_t helper_float_msub_s(CPUMIPSState *env, uint32_t fst0,
+ uint32_t fst1, uint32_t fst2)
+{
+fst0 = float32_mul(fst0, fst1, >active_fpu.fp_status);
+fst0 = float32_sub(fst0, fst2, >active_fpu.fp_status);
+
+update_fcr31(env, GETPC());
+return fst0;
+}
+
+uint64_t helper_float_msub_ps(CPUMIPSState *env, uint64_t fdt0,
+  uint64_t fdt1, uint64_t fdt2)
+{
+uint32_t fstl0 = fdt0 & 0X;
+uint32_t fsth0 = fdt0 >> 32;
+uint32_t fstl1 = fdt1 & 0X;
+uint32_t fsth1 = fdt1 >> 32;
+uint32_t fstl2 = fdt2 & 0X;
+uint32_t fsth2 = fdt2 >> 32;
+
+fstl0 = float32_mul(fstl0, fstl1, >active_fpu.fp_status);
+fstl0 = float32_sub(fstl0, fstl2, >active_fpu.fp_status);
+fsth0 = float32_mul(fsth0, fsth1, >active_fpu.fp_status);
+fsth0 = float32_sub(fsth0, fsth2, >active_fpu.fp_status);
+
+update_fcr31(env, GETPC());
+return ((uint64_t)fsth0 << 32) | fstl0;
+}
+
 
 #define FLOAT_FMADDSUB(name, bits, muladd_arg)  \
 uint ## bits ## _t helper_float_ ## name(CPUMIPSState *env, \
-- 
2.20.1




[PATCH v6 06/21] target/mips: fpu: Demacro MADD.

2020-05-18 Thread Aleksandar Markovic
This is just a cosmetic change to enable tools like gcov, gdb,
callgrind, etc. to better display involved source code.

Reviewed-by: Aleksandar Rikalo 
Signed-off-by: Aleksandar Markovic 
---
 target/mips/fpu_helper.c | 41 +++-
 1 file changed, 40 insertions(+), 1 deletion(-)

diff --git a/target/mips/fpu_helper.c b/target/mips/fpu_helper.c
index a3a39681f8..c070081cbc 100644
--- a/target/mips/fpu_helper.c
+++ b/target/mips/fpu_helper.c
@@ -1495,12 +1495,51 @@ uint64_t helper_float_ ## name ## _ps(CPUMIPSState 
*env, \
 update_fcr31(env, GETPC());  \
 return ((uint64_t)fsth0 << 32) | fst0;   \
 }
-FLOAT_FMA(madd, 0)
 FLOAT_FMA(msub, float_muladd_negate_c)
 FLOAT_FMA(nmadd, float_muladd_negate_result)
 FLOAT_FMA(nmsub, float_muladd_negate_result | float_muladd_negate_c)
 #undef FLOAT_FMA
 
+uint64_t helper_float_madd_d(CPUMIPSState *env, uint64_t fst0,
+ uint64_t fst1, uint64_t fst2)
+{
+fst0 = float64_mul(fst0, fst1, >active_fpu.fp_status);
+fst0 = float64_add(fst0, fst2, >active_fpu.fp_status);
+
+update_fcr31(env, GETPC());
+return fst0;
+}
+
+uint32_t helper_float_madd_s(CPUMIPSState *env, uint32_t fst0,
+ uint32_t fst1, uint32_t fst2)
+{
+fst0 = float32_mul(fst0, fst1, >active_fpu.fp_status);
+fst0 = float32_add(fst0, fst2, >active_fpu.fp_status);
+
+update_fcr31(env, GETPC());
+return fst0;
+}
+
+uint64_t helper_float_madd_ps(CPUMIPSState *env, uint64_t fdt0,
+  uint64_t fdt1, uint64_t fdt2)
+{
+uint32_t fstl0 = fdt0 & 0X;
+uint32_t fsth0 = fdt0 >> 32;
+uint32_t fstl1 = fdt1 & 0X;
+uint32_t fsth1 = fdt1 >> 32;
+uint32_t fstl2 = fdt2 & 0X;
+uint32_t fsth2 = fdt2 >> 32;
+
+fstl0 = float32_mul(fstl0, fstl1, >active_fpu.fp_status);
+fstl0 = float32_add(fstl0, fstl2, >active_fpu.fp_status);
+fsth0 = float32_mul(fsth0, fsth1, >active_fpu.fp_status);
+fsth0 = float32_add(fsth0, fsth2, >active_fpu.fp_status);
+
+update_fcr31(env, GETPC());
+return ((uint64_t)fsth0 << 32) | fstl0;
+}
+
+
 #define FLOAT_FMADDSUB(name, bits, muladd_arg)  \
 uint ## bits ## _t helper_float_ ## name(CPUMIPSState *env, \
  uint ## bits ## _t fs, \
-- 
2.20.1




[PATCH v6 00/21] target/mips: MSA, FPU and other cleanups and improvements

2020-05-18 Thread Aleksandar Markovic
This series contains some pathces 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.

Also, this series contains mostly cosmetic FPU cleanups aimed to make
source code recognition easier for tools like gdb, gcov, calgrind,
and others.

There is also a patch that refactors conversion from ieee to mips
fp exception flags. This refactoring will improve the performance
of almost all fp-related mips instructions, albait very modestly
(less that one percent).

There is a patch that introduces some logging in mips_malta.c.

There is a patch on change of Aleksandar Rikalo's email.

Finally, there is a patch on renaming some files in hw/mips folder.

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 (21):
  target/mips: fpu: Demacro ADD.
  target/mips: fpu: Demacro SUB.
  target/mips: fpu: Demacro MUL.
  target/mips: fpu: Demacro DIV.
  target/mips: fpu: Remove now unused macro FLOAT_BINOP
  target/mips: fpu: Demacro MADD.
  target/mips: fpu: Demacro MSUB.
  target/mips: fpu: Demacro NMADD.
  target/mips: fpu: Demacro NMSUB.
  target/mips: fpu: Remove now unused UNFUSED_FMA and FLOAT_FMA macros
  target/mips: fpu: Demacro CLASS.
  target/mips: fpu: Remove now unused FLOAT_CLASS macro
  target/mips: fpu: Demacro RINT.
  target/mips: fpu: Remove now unused FLOAT_RINT macro
  target/mips: fpu: Name better paired-single variables
  target/mips: fpu: Refactor conversion from ieee to mips exception
flags
  MAINTAINERS: Change Aleksandar Rikalo's email address
  target/mips: msa: Split helpers for MADDV.
  target/mips: msa: Split helpers for MSUBV.
  hw/mips: Add some logging for bad register offset cases
  hw/mips: Rename malta/mipssim/r4k/jazz files in hw/mips

 .mailmap  |   3 +-
 MAINTAINERS   |  21 +-
 hw/mips/Makefile.objs |   8 +-
 hw/mips/{mips_jazz.c => jazz.c}   |   0
 hw/mips/{mips_malta.c => malta.c} |  14 +-
 hw/mips/{mips_mipssim.c => mipssim.c} |   0
 hw/mips/{mips_r4k.c => r4k.c} |   0
 target/mips/fpu_helper.c  | 658 ++
 target/mips/helper.h  |  12 +-
 target/mips/internal.h|   1 -
 target/mips/msa_helper.c  | 235 +++--
 target/mips/translate.c   |  38 +-
 12 files changed, 712 insertions(+), 278 deletions(-)
 rename hw/mips/{mips_jazz.c => jazz.c} (100%)
 rename hw/mips/{mips_malta.c => malta.c} (99%)
 rename hw/mips/{mips_mipssim.c => mipssim.c} (100%)
 rename hw/mips/{mips_r4k.c => r4k.c} (100%)

-- 
2.20.1




[PATCH v6 02/21] target/mips: fpu: Demacro SUB.

2020-05-18 Thread Aleksandar Markovic
This is just a cosmetic change to enable tools like gcov, gdb,
callgrind, etc. to better display involved source code.

Reviewed-by: Aleksandar Rikalo 
Signed-off-by: Aleksandar Markovic 
---
 target/mips/fpu_helper.c | 37 -
 1 file changed, 36 insertions(+), 1 deletion(-)

diff --git a/target/mips/fpu_helper.c b/target/mips/fpu_helper.c
index 984f3f4dfb..715a872cae 100644
--- a/target/mips/fpu_helper.c
+++ b/target/mips/fpu_helper.c
@@ -1208,7 +1208,6 @@ uint64_t helper_float_ ## name ## _ps(CPUMIPSState *env,  
 \
 return ((uint64_t)wth2 << 32) | wt2;   \
 }
 
-FLOAT_BINOP(sub)
 FLOAT_BINOP(mul)
 FLOAT_BINOP(div)
 #undef FLOAT_BINOP
@@ -1249,6 +1248,42 @@ uint64_t helper_float_add_ps(CPUMIPSState *env,
 return ((uint64_t)wth2 << 32) | wtl2;
 }
 
+uint64_t helper_float_sub_d(CPUMIPSState *env,
+uint64_t fdt0, uint64_t fdt1)
+{
+uint64_t dt2;
+
+dt2 = float64_sub(fdt0, fdt1, >active_fpu.fp_status);
+update_fcr31(env, GETPC());
+return dt2;
+}
+
+uint32_t helper_float_sub_s(CPUMIPSState *env,
+uint32_t fst0, uint32_t fst1)
+{
+uint32_t wt2;
+
+wt2 = float32_sub(fst0, fst1, >active_fpu.fp_status);
+update_fcr31(env, GETPC());
+return wt2;
+}
+
+uint64_t helper_float_sub_ps(CPUMIPSState *env,
+ uint64_t fdt0, uint64_t fdt1)
+{
+uint32_t fstl0 = fdt0 & 0X;
+uint32_t fsth0 = fdt0 >> 32;
+uint32_t fstl1 = fdt1 & 0X;
+uint32_t fsth1 = fdt1 >> 32;
+uint32_t wtl2;
+uint32_t wth2;
+
+wtl2 = float32_sub(fstl0, fstl1, >active_fpu.fp_status);
+wth2 = float32_sub(fsth0, fsth1, >active_fpu.fp_status);
+update_fcr31(env, GETPC());
+return ((uint64_t)wth2 << 32) | wtl2;
+}
+
 
 /* MIPS specific binary operations */
 uint64_t helper_float_recip2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2)
-- 
2.20.1




[PATCH v6 01/21] target/mips: fpu: Demacro ADD.

2020-05-18 Thread Aleksandar Markovic
This is just a cosmetic change to enable tools like gcov, gdb,
callgrind, etc. to better display involved source code.

Reviewed-by: Aleksandar Rikalo 
Signed-off-by: Aleksandar Markovic 
---
 target/mips/fpu_helper.c | 38 +-
 1 file changed, 37 insertions(+), 1 deletion(-)

diff --git a/target/mips/fpu_helper.c b/target/mips/fpu_helper.c
index 5287c86c61..984f3f4dfb 100644
--- a/target/mips/fpu_helper.c
+++ b/target/mips/fpu_helper.c
@@ -1208,12 +1208,48 @@ uint64_t helper_float_ ## name ## _ps(CPUMIPSState 
*env,   \
 return ((uint64_t)wth2 << 32) | wt2;   \
 }
 
-FLOAT_BINOP(add)
 FLOAT_BINOP(sub)
 FLOAT_BINOP(mul)
 FLOAT_BINOP(div)
 #undef FLOAT_BINOP
 
+uint64_t helper_float_add_d(CPUMIPSState *env,
+uint64_t fdt0, uint64_t fdt1)
+{
+uint64_t dt2;
+
+dt2 = float64_add(fdt0, fdt1, >active_fpu.fp_status);
+update_fcr31(env, GETPC());
+return dt2;
+}
+
+uint32_t helper_float_add_s(CPUMIPSState *env,
+uint32_t fst0, uint32_t fst1)
+{
+uint32_t wt2;
+
+wt2 = float32_sub(fst0, fst1, >active_fpu.fp_status);
+update_fcr31(env, GETPC());
+return wt2;
+}
+
+uint64_t helper_float_add_ps(CPUMIPSState *env,
+ uint64_t fdt0, uint64_t fdt1)
+{
+uint32_t fstl0 = fdt0 & 0X;
+uint32_t fsth0 = fdt0 >> 32;
+uint32_t fstl1 = fdt1 & 0X;
+uint32_t fsth1 = fdt1 >> 32;
+uint32_t wtl2;
+uint32_t wth2;
+
+wtl2 = float32_add(fstl0, fstl1, >active_fpu.fp_status);
+wth2 = float32_add(fsth0, fsth1, >active_fpu.fp_status);
+update_fcr31(env, GETPC());
+return ((uint64_t)wth2 << 32) | wtl2;
+}
+
+
 /* MIPS specific binary operations */
 uint64_t helper_float_recip2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2)
 {
-- 
2.20.1




Re: QEMU 5.1: Can we require each new device/machine to provided a test?

2020-05-18 Thread John Snow



On 5/15/20 6:23 AM, Daniel P. Berrangé wrote:
> On Fri, May 15, 2020 at 12:11:17PM +0200, Thomas Huth wrote:
>> On 07/04/2020 12.59, Philippe Mathieu-Daudé wrote:
>>> Hello,
>>>
>>> Following Markus thread on deprecating unmaintained (untested) code
>>> (machines) [1] and the effort done to gather the information shared in
>>> the replies [2], and the various acceptance tests added, is it
>>> feasible to require for the next release that each new device/machine
>>> is provided a test covering it?
>>>
>>> If no, what is missing?
>>
>> If a qtest is feasible, yes, I think we should require one for new
>> devices. But what about machines - you normally need a test image for
>> this. In that case, there is still the question where testing images
>> could be hosted. Not every developer has a web space where they could
>> put their test images onto. And what about images that contain non-free
>> code?
> 
> Yep, it isn't feasible to make this a hard rule.
> 
> IMHO this is where a support tier classification comes into play
> 
>  - Tier 1: actively maintained, qtest coverage available. Expected
>to work reliably at all times since every commit is CI
>  tested
> 
>   - Tier 2: actively maintained, no qtest coverage. Should usually
>work but regression may creep in due to reliance on the
>  maintainer to manually test on adhoc basis
> 
>   - Tier 3: not actively maintained, unknown state but liable to
> be broken indefinitely
> 
> Tier 1 is obviously the most desirable state we would like everthing to
> be at. Contributors will have to fix problems their patches cause as
> they will be blocked by CI.
> 
> Tier 2 is an admission that reality gets in the way. Ideally stuff in
> this tier will graduate to Tier 1 at some point. Even if it doesn't
> though, it is still valid to keep it in QEMU long term. Contributors
> shouldn't gratuitously break stuff in these board, but if they do,
> then the maintainer is ultimately responsible for fixing it, as the
> contributors don't have a test rig for it.
> 
> Tier 3 is abandonware. If a maintainer doesn't appear, users should
> not expect it to continue to exist long term. Contributors are free
> to send patches which break this, and are under no obligation to
> fix problems in these boards. We may deprecate & delete it after a
> while
> 
> 
> Over time we'll likely add more criteria to stuff in Tier 1. This
> could lead to some things dropping from Tier 1 to Tier 2. This is
> OK, as it doesn't make those things worse than they already were.
> We're just saying that Tier 2 isn't as thoroughly tested as we
> would like it to be in an ideal world.
> 
> Regards,
> Daniel
> 

I really like the idea of device support tiers codified directly in the
QEMU codebase, to give upstream users some idea of which devices we
expect to work and which we ... don't, really.

Not every last device we offer is enterprise production ready, but we
don't necessarily do a good job of explaining which devices fall into
which categories, and we've got quite a few of them.

I wonder if a 2.5th tier would be useful; something like a "hobbyist"
tier for pet project SoC boards and the like -- they're not abandoned,
but we also don't expect them to work, exactly.

Mild semantic difference from Tier 3.

--js




Re: [PATCH v4 7/9] qcow2: Expose bitmaps' size during measure

2020-05-18 Thread Vladimir Sementsov-Ogievskiy

18.05.2020 22:17, Eric Blake wrote:

On 5/18/20 8:07 AM, Vladimir Sementsov-Ogievskiy wrote:

13.05.2020 04:16, Eric Blake wrote:

It's useful to know how much space can be occupied by qcow2 persistent
bitmaps, even though such metadata is unrelated to the guest-visible
data.  Report this value as an additional QMP field, present when
measuring an existing image and output format that both support
bitmaps.  Update iotest 178 and 190 to updated output, as well as new
coverage in 190 demonstrating non-zero values made possible with the
recently-added qemu-img bitmap command.




@@ -616,6 +616,7 @@ Command description:

  required size: 524288
  fully allocated size: 1074069504
+    bitmaps: 0

    The ``required size`` is the file size of the new image.  It may be smaller
    than the virtual disk size if the image format supports compact 
representation.
@@ -625,6 +626,13 @@ Command description:
    occupy with the exception of internal snapshots, dirty bitmaps, vmstate 
data,
    and other advanced image format features.

+  The ``bitmaps size`` is the additional size required if the


you called it "bitmaps" in example output above. Should it be consistent? Either 
"``bitmaps``" here, or "bitmaps size: 0" above?


"bitmaps size: 0" is better. Will fix the description above.


+++ b/qapi/block-core.json
@@ -633,18 +633,23 @@
  # efficiently so file size may be smaller than virtual disk size.
  #
  # The values are upper bounds that are guaranteed to fit the new image file.
-# Subsequent modification, such as internal snapshot or bitmap creation, may
-# require additional space and is not covered here.
+# Subsequent modification, such as internal snapshot or further bitmap
+# creation, may require additional space and is not covered here.
  #
-# @required: Size required for a new image file, in bytes.
+# @required: Size required for a new image file, in bytes, when copying just
+#    guest-visible contents.
  #
  # @fully-allocated: Image file size, in bytes, once data has been written
-#   to all sectors.
+#   to all sectors, when copying just guest-visible contents.


"copying just guest-visible" sounds like something less than "all fully-allocated 
sectors"..
But I don't have better suggestion.. Just, "not including bitmaps" sounds weird 
too.


If we ever add support for copying internal snapshots, that would not be included either. 
 Maybe "copying just allocated guest-visible contents" for @required, and no 
change to the wording for @fully-allocated.


Not sure is it better or not, so, I'm OK with any variant.





@@ -4796,13 +4797,38 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, 
BlockDriverState *in_bs,




+    FOR_EACH_DIRTY_BITMAP(in_bs, bm) {
+    if (bdrv_dirty_bitmap_get_persistence(bm)) {
+    const char *name = bdrv_dirty_bitmap_name(bm);
+    uint32_t granularity = bdrv_dirty_bitmap_granularity(bm);
+    uint64_t bmbits = DIV_ROUND_UP(bdrv_dirty_bitmap_size(bm),
+   granularity);
+    uint64_t bmclusters = DIV_ROUND_UP(DIV_ROUND_UP(bmbits,
+ CHAR_BIT),
+   cluster_size);
+
+    /* Assume the entire bitmap is allocated */
+    bitmaps_size += bmclusters * cluster_size;
+    /* Also reserve space for the bitmap table entries */
+    bitmaps_size += ROUND_UP(bmclusters * sizeof(uint64_t),
+ cluster_size);
+    /* And space for contribution to bitmap directory size */
+    bitmap_dir_size += ROUND_UP(strlen(name) + 24,
+    sizeof(uint64_t));


Could we instead reuse code from qcow2_co_can_store_new_dirty_bitmap(), which 
calls calc_dir_entry_size() for this thing?
Possibly, make a function qcow2_measure_bitmaps in block/qcow2-bitmaps.c with 
this FOR_EACH? All details about qcow2 bitmap structures sounds better in 
block/qcow2-bitmaps.c


Could do.  Sounds like I'm better off submitting a v5 for this patch, although 
I'll go ahead and stage 1-6 for pull request today to minimize future rebase 
churn.


Thanks!





+    info->has_bitmaps = version >= 3 && in_bs &&
+    bdrv_supports_persistent_dirty_bitmap(in_bs);
+    info->bitmaps = bitmaps_size;


AFAIK, in QAPI, if has_ field is false, than  must be 
zero. Maybe, it's only about nested structured fields, not about simple numbers, but I 
think it's better keep bitmaps 0 in case when has_bitmaps is false.


During creation (including when parsing QMP from the user over the monitor), 
everything is indeed guaranteed to be zero-initialized.  But we don't have any 
requirement that things remain zero-initialized even when has_FOO is false; at 
the same time, it's easy enough to make this code conditional.



Also, it seems a bit better to check version earlier, and don't do all 

[PATCH v5 22/22] hw/mips: Rename malta/mipssim/r4k/jazz files in hw/mips

2020-05-18 Thread Aleksandar Markovic
Machine file names should not have prefix "mips_".

Fuloong2e machine source file will be handled in a separate patch,
to avoid conflicts. That patch is pending integration into the
main tree.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Aleksandar Markovic 
---
 MAINTAINERS   | 9 -
 hw/mips/Makefile.objs | 8 
 hw/mips/{mips_jazz.c => jazz.c}   | 0
 hw/mips/{mips_malta.c => malta.c} | 0
 hw/mips/{mips_mipssim.c => mipssim.c} | 0
 hw/mips/{mips_r4k.c => r4k.c} | 0
 6 files changed, 8 insertions(+), 9 deletions(-)
 rename hw/mips/{mips_jazz.c => jazz.c} (100%)
 rename hw/mips/{mips_malta.c => malta.c} (100%)
 rename hw/mips/{mips_mipssim.c => mipssim.c} (100%)
 rename hw/mips/{mips_r4k.c => r4k.c} (100%)

diff --git a/MAINTAINERS b/MAINTAINERS
index 8d5562c5c7..883d15c9d7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11,7 +11,6 @@ consult qemu-devel and not any specific individual privately.
 
 Descriptions of section entries:
 
-   M: Mail patches to: FullName 
   Maintainers are looking after a certain area and must be CCed on
   patches. They are considered the main contact point.
R: Designated reviewer: FullName 
@@ -1043,7 +1042,7 @@ Jazz
 M: Hervé Poussineau 
 R: Aleksandar Rikalo 
 S: Maintained
-F: hw/mips/mips_jazz.c
+F: hw/mips/jazz.c
 F: hw/display/jazz_led.c
 F: hw/dma/rc4030.c
 
@@ -1054,7 +1053,7 @@ R: Aurelien Jarno 
 S: Maintained
 F: hw/isa/piix4.c
 F: hw/acpi/piix4.c
-F: hw/mips/mips_malta.c
+F: hw/mips/malta.c
 F: hw/mips/gt64xxx_pci.c
 F: include/hw/southbridge/piix.h
 F: tests/acceptance/linux_ssh_mips_malta.py
@@ -1064,7 +1063,7 @@ Mipssim
 M: Aleksandar Markovic 
 R: Aleksandar Rikalo 
 S: Odd Fixes
-F: hw/mips/mips_mipssim.c
+F: hw/mips/mipssim.c
 F: hw/net/mipsnet.c
 
 R4000
@@ -1072,7 +1071,7 @@ M: Aleksandar Markovic 
 R: Aurelien Jarno 
 R: Aleksandar Rikalo 
 S: Obsolete
-F: hw/mips/mips_r4k.c
+F: hw/mips/r4k.c
 
 Fulong 2E
 M: Philippe Mathieu-Daudé 
diff --git a/hw/mips/Makefile.objs b/hw/mips/Makefile.objs
index 525809af07..1d767ed9a8 100644
--- a/hw/mips/Makefile.objs
+++ b/hw/mips/Makefile.objs
@@ -1,8 +1,8 @@
 obj-y += addr.o mips_int.o
-obj-$(CONFIG_R4K) += mips_r4k.o
-obj-$(CONFIG_MALTA) += gt64xxx_pci.o mips_malta.o
-obj-$(CONFIG_MIPSSIM) += mips_mipssim.o
-obj-$(CONFIG_JAZZ) += mips_jazz.o
+obj-$(CONFIG_R4K) += r4k.o
+obj-$(CONFIG_MALTA) += gt64xxx_pci.o malta.o
+obj-$(CONFIG_MIPSSIM) += mipssim.o
+obj-$(CONFIG_JAZZ) += jazz.o
 obj-$(CONFIG_FULONG) += mips_fulong2e.o
 obj-$(CONFIG_MIPS_CPS) += cps.o
 obj-$(CONFIG_MIPS_BOSTON) += boston.o
diff --git a/hw/mips/mips_jazz.c b/hw/mips/jazz.c
similarity index 100%
rename from hw/mips/mips_jazz.c
rename to hw/mips/jazz.c
diff --git a/hw/mips/mips_malta.c b/hw/mips/malta.c
similarity index 100%
rename from hw/mips/mips_malta.c
rename to hw/mips/malta.c
diff --git a/hw/mips/mips_mipssim.c b/hw/mips/mipssim.c
similarity index 100%
rename from hw/mips/mips_mipssim.c
rename to hw/mips/mipssim.c
diff --git a/hw/mips/mips_r4k.c b/hw/mips/r4k.c
similarity index 100%
rename from hw/mips/mips_r4k.c
rename to hw/mips/r4k.c
-- 
2.20.1




[PATCH v5 20/22] target/mips: msa: Split helpers for MSUBV.

2020-05-18 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 6af9d3b752..a0aac3ee10 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 v5 18/22] MAINTAINERS: Change Aleksandar Rikalo's email address

2020-05-18 Thread Aleksandar Markovic
Aleksandar Rikalo wants to use a different email address from
now on.

Reviewed-by: Aleksandar Rikalo 
Reviewed-by: Philippe Mathieu-Daudé 
Tested-by: Philippe Mathieu-Daudé 
Signed-off-by: Aleksandar Markovic 
---
 .mailmap|  3 ++-
 MAINTAINERS | 12 ++--
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/.mailmap b/.mailmap
index 6412067bde..e3628c7a66 100644
--- a/.mailmap
+++ b/.mailmap
@@ -42,7 +42,8 @@ Justin Terry (VM)  Justin Terry (VM) 
via Qemu-devel  

 Aleksandar Markovic  

 Aleksandar Markovic  
-Aleksandar Rikalo  
+Aleksandar Rikalo  
+Aleksandar Rikalo  
 Anthony Liguori  Anthony Liguori 
 James Hogan  
 Leif Lindholm  
diff --git a/MAINTAINERS b/MAINTAINERS
index 1f84e3ae2c..8d5562c5c7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -212,7 +212,7 @@ F: disas/microblaze.c
 MIPS TCG CPUs
 M: Aleksandar Markovic 
 R: Aurelien Jarno 
-R: Aleksandar Rikalo 
+R: Aleksandar Rikalo 
 S: Maintained
 F: target/mips/
 F: default-configs/*mips*
@@ -1041,7 +1041,7 @@ MIPS Machines
 -
 Jazz
 M: Hervé Poussineau 
-R: Aleksandar Rikalo 
+R: Aleksandar Rikalo 
 S: Maintained
 F: hw/mips/mips_jazz.c
 F: hw/display/jazz_led.c
@@ -1062,7 +1062,7 @@ F: tests/acceptance/machine_mips_malta.py
 
 Mipssim
 M: Aleksandar Markovic 
-R: Aleksandar Rikalo 
+R: Aleksandar Rikalo 
 S: Odd Fixes
 F: hw/mips/mips_mipssim.c
 F: hw/net/mipsnet.c
@@ -1070,7 +1070,7 @@ F: hw/net/mipsnet.c
 R4000
 M: Aleksandar Markovic 
 R: Aurelien Jarno 
-R: Aleksandar Rikalo 
+R: Aleksandar Rikalo 
 S: Obsolete
 F: hw/mips/mips_r4k.c
 
@@ -1085,7 +1085,7 @@ F: include/hw/isa/vt82c686.h
 
 Boston
 M: Paul Burton 
-R: Aleksandar Rikalo 
+R: Aleksandar Rikalo 
 S: Maintained
 F: hw/core/loader-fit.c
 F: hw/mips/boston.c
@@ -2582,7 +2582,7 @@ F: disas/i386.c
 MIPS TCG target
 M: Aleksandar Markovic 
 R: Aurelien Jarno 
-R: Aleksandar Rikalo 
+R: Aleksandar Rikalo 
 S: Maintained
 F: tcg/mips/
 
-- 
2.20.1




Re: [PATCH v5 01/22] hw/tpm: fix usage of bool in tpm-tis.c

2020-05-18 Thread Aleksandar Markovic
пон, 18. мај 2020. у 21:42 Aleksandar Markovic
 је написао/ла:
>
> From: Jafar Abdi 
>

This patch was selected by mistake to be included in this series. A ne
version of this series will be sent without this patch.

Sorry about this.

Aleksnadar

> Clean up wrong usage of FALSE and TRUE in places that use "bool" from 
> stdbool.h.
>
> FALSE and TRUE (with capital letters) are the constants defined by glib for
> being used with the "gboolean" type of glib. But some parts of the code also 
> use
> TRUE and FALSE for variables that are declared as "bool" (the type from 
> ).
>
> Signed-off-by: Jafar Abdi 
> Reviewed-by: Thomas Huth 
> Reviewed-by: Stefan Berger 
> Signed-off-by: Stefan Berger 
> ---
>  hw/tpm/tpm_tis_common.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/hw/tpm/tpm_tis_common.c b/hw/tpm/tpm_tis_common.c
> index 9ce64d4836..1af4bce139 100644
> --- a/hw/tpm/tpm_tis_common.c
> +++ b/hw/tpm/tpm_tis_common.c
> @@ -536,7 +536,7 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr,
>  while ((TPM_TIS_IS_VALID_LOCTY(s->active_locty) &&
>  locty > s->active_locty) ||
>  !TPM_TIS_IS_VALID_LOCTY(s->active_locty)) {
> -bool higher_seize = FALSE;
> +bool higher_seize = false;
>
>  /* already a pending SEIZE ? */
>  if ((s->loc[locty].access & TPM_TIS_ACCESS_SEIZE)) {
> @@ -546,7 +546,7 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr,
>  /* check for ongoing seize by a higher locality */
>  for (l = locty + 1; l < TPM_TIS_NUM_LOCALITIES; l++) {
>  if ((s->loc[l].access & TPM_TIS_ACCESS_SEIZE)) {
> -higher_seize = TRUE;
> +higher_seize = true;
>  break;
>  }
>  }
> --
> 2.20.1
>



[PATCH v5 16/22] target/mips: fpu: Name better paired-single variables

2020-05-18 Thread Aleksandar Markovic
Use consistently 'l' and 'h' for low and high halves.

Reviewed-by: Aleksandar Rikalo 
Signed-off-by: Aleksandar Markovic 
---
 target/mips/fpu_helper.c | 62 
 1 file changed, 31 insertions(+), 31 deletions(-)

diff --git a/target/mips/fpu_helper.c b/target/mips/fpu_helper.c
index 56ba49104e..dbb8ca5692 100644
--- a/target/mips/fpu_helper.c
+++ b/target/mips/fpu_helper.c
@@ -1059,14 +1059,14 @@ uint32_t helper_float_recip1_s(CPUMIPSState *env, 
uint32_t fst0)
 
 uint64_t helper_float_recip1_ps(CPUMIPSState *env, uint64_t fdt0)
 {
-uint32_t fst2;
+uint32_t fstl2;
 uint32_t fsth2;
 
-fst2 = float32_div(float32_one, fdt0 & 0X,
-   >active_fpu.fp_status);
+fstl2 = float32_div(float32_one, fdt0 & 0X,
+>active_fpu.fp_status);
 fsth2 = float32_div(float32_one, fdt0 >> 32, >active_fpu.fp_status);
 update_fcr31(env, GETPC());
-return ((uint64_t)fsth2 << 32) | fst2;
+return ((uint64_t)fsth2 << 32) | fstl2;
 }
 
 uint64_t helper_float_rsqrt1_d(CPUMIPSState *env, uint64_t fdt0)
@@ -1091,15 +1091,15 @@ uint32_t helper_float_rsqrt1_s(CPUMIPSState *env, 
uint32_t fst0)
 
 uint64_t helper_float_rsqrt1_ps(CPUMIPSState *env, uint64_t fdt0)
 {
-uint32_t fst2;
+uint32_t fstl2;
 uint32_t fsth2;
 
-fst2 = float32_sqrt(fdt0 & 0X, >active_fpu.fp_status);
+fstl2 = float32_sqrt(fdt0 & 0X, >active_fpu.fp_status);
 fsth2 = float32_sqrt(fdt0 >> 32, >active_fpu.fp_status);
-fst2 = float32_div(float32_one, fst2, >active_fpu.fp_status);
+fstl2 = float32_div(float32_one, fstl2, >active_fpu.fp_status);
 fsth2 = float32_div(float32_one, fsth2, >active_fpu.fp_status);
 update_fcr31(env, GETPC());
-return ((uint64_t)fsth2 << 32) | fst2;
+return ((uint64_t)fsth2 << 32) | fstl2;
 }
 
 uint64_t helper_float_rint_d(CPUMIPSState *env, uint64_t fs)
@@ -1367,19 +1367,19 @@ uint32_t helper_float_recip2_s(CPUMIPSState *env, 
uint32_t fst0, uint32_t fst2)
 
 uint64_t helper_float_recip2_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t 
fdt2)
 {
-uint32_t fst0 = fdt0 & 0X;
+uint32_t fstl0 = fdt0 & 0X;
 uint32_t fsth0 = fdt0 >> 32;
-uint32_t fst2 = fdt2 & 0X;
+uint32_t fstl2 = fdt2 & 0X;
 uint32_t fsth2 = fdt2 >> 32;
 
-fst2 = float32_mul(fst0, fst2, >active_fpu.fp_status);
+fstl2 = float32_mul(fstl0, fstl2, >active_fpu.fp_status);
 fsth2 = float32_mul(fsth0, fsth2, >active_fpu.fp_status);
-fst2 = float32_chs(float32_sub(fst2, float32_one,
+fstl2 = float32_chs(float32_sub(fstl2, float32_one,
>active_fpu.fp_status));
 fsth2 = float32_chs(float32_sub(fsth2, float32_one,
>active_fpu.fp_status));
 update_fcr31(env, GETPC());
-return ((uint64_t)fsth2 << 32) | fst2;
+return ((uint64_t)fsth2 << 32) | fstl2;
 }
 
 uint64_t helper_float_rsqrt2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2)
@@ -1404,51 +1404,51 @@ uint32_t helper_float_rsqrt2_s(CPUMIPSState *env, 
uint32_t fst0, uint32_t fst2)
 
 uint64_t helper_float_rsqrt2_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t 
fdt2)
 {
-uint32_t fst0 = fdt0 & 0X;
+uint32_t fstl0 = fdt0 & 0X;
 uint32_t fsth0 = fdt0 >> 32;
-uint32_t fst2 = fdt2 & 0X;
+uint32_t fstl2 = fdt2 & 0X;
 uint32_t fsth2 = fdt2 >> 32;
 
-fst2 = float32_mul(fst0, fst2, >active_fpu.fp_status);
+fstl2 = float32_mul(fstl0, fstl2, >active_fpu.fp_status);
 fsth2 = float32_mul(fsth0, fsth2, >active_fpu.fp_status);
-fst2 = float32_sub(fst2, float32_one, >active_fpu.fp_status);
+fstl2 = float32_sub(fstl2, float32_one, >active_fpu.fp_status);
 fsth2 = float32_sub(fsth2, float32_one, >active_fpu.fp_status);
-fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32,
+fstl2 = float32_chs(float32_div(fstl2, FLOAT_TWO32,
>active_fpu.fp_status));
 fsth2 = float32_chs(float32_div(fsth2, FLOAT_TWO32,
>active_fpu.fp_status));
 update_fcr31(env, GETPC());
-return ((uint64_t)fsth2 << 32) | fst2;
+return ((uint64_t)fsth2 << 32) | fstl2;
 }
 
 uint64_t helper_float_addr_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt1)
 {
-uint32_t fst0 = fdt0 & 0X;
+uint32_t fstl0 = fdt0 & 0X;
 uint32_t fsth0 = fdt0 >> 32;
-uint32_t fst1 = fdt1 & 0X;
+uint32_t fstl1 = fdt1 & 0X;
 uint32_t fsth1 = fdt1 >> 32;
-uint32_t fst2;
+uint32_t fstl2;
 uint32_t fsth2;
 
-fst2 = float32_add(fst0, fsth0, >active_fpu.fp_status);
-fsth2 = float32_add(fst1, fsth1, >active_fpu.fp_status);
+fstl2 = float32_add(fstl0, fsth0, >active_fpu.fp_status);
+fsth2 = float32_add(fstl1, fsth1, >active_fpu.fp_status);
 update_fcr31(env, GETPC());
-return ((uint64_t)fsth2 << 32) | fst2;

[PATCH v5 17/22] target/mips: fpu: Refactor conversion from ieee to mips exception flags

2020-05-18 Thread Aleksandar Markovic
The original coversion function is used for regular and MSA floating
point instructions handling. Since there are some nuanced differences
between regular and MSA floating point exception handling, provide two
instances of the conversion function, rather than just a single common
one. Inline both instances of this function instances for the sake of
performance. Improve variable naming in surrounding code for clarity.

Reviewed-by: Aleksandar Rikalo 
Signed-off-by: Aleksandar Markovic 
---
 target/mips/fpu_helper.c | 55 +++-
 target/mips/internal.h   |  1 -
 target/mips/msa_helper.c | 77 +++-
 3 files changed, 82 insertions(+), 51 deletions(-)

diff --git a/target/mips/fpu_helper.c b/target/mips/fpu_helper.c
index dbb8ca5692..7a3a61cab3 100644
--- a/target/mips/fpu_helper.c
+++ b/target/mips/fpu_helper.c
@@ -189,43 +189,48 @@ void helper_ctc1(CPUMIPSState *env, target_ulong arg1, 
uint32_t fs, uint32_t rt)
 }
 }
 
-int ieee_ex_to_mips(int xcpt)
+static inline int ieee_to_mips_xcpt(int ieee_xcpt)
 {
-int ret = 0;
-if (xcpt) {
-if (xcpt & float_flag_invalid) {
-ret |= FP_INVALID;
-}
-if (xcpt & float_flag_overflow) {
-ret |= FP_OVERFLOW;
-}
-if (xcpt & float_flag_underflow) {
-ret |= FP_UNDERFLOW;
-}
-if (xcpt & float_flag_divbyzero) {
-ret |= FP_DIV0;
-}
-if (xcpt & float_flag_inexact) {
-ret |= FP_INEXACT;
-}
+int mips_xcpt = 0;
+
+if (ieee_xcpt & float_flag_invalid) {
+mips_xcpt |= FP_INVALID;
+}
+if (ieee_xcpt & float_flag_overflow) {
+mips_xcpt |= FP_OVERFLOW;
 }
-return ret;
+if (ieee_xcpt & float_flag_underflow) {
+mips_xcpt |= FP_UNDERFLOW;
+}
+if (ieee_xcpt & float_flag_divbyzero) {
+mips_xcpt |= FP_DIV0;
+}
+if (ieee_xcpt & float_flag_inexact) {
+mips_xcpt |= FP_INEXACT;
+}
+
+return mips_xcpt;
 }
 
 static inline void update_fcr31(CPUMIPSState *env, uintptr_t pc)
 {
-int tmp = ieee_ex_to_mips(get_float_exception_flags(
-  >active_fpu.fp_status));
+int ieee_exception_flags = get_float_exception_flags(
+   >active_fpu.fp_status);
+int mips_exception_flags = 0;
+
+if (ieee_exception_flags) {
+mips_exception_flags = ieee_to_mips_xcpt(ieee_exception_flags);
+}
 
-SET_FP_CAUSE(env->active_fpu.fcr31, tmp);
+SET_FP_CAUSE(env->active_fpu.fcr31, mips_exception_flags);
 
-if (tmp) {
+if (mips_exception_flags)  {
 set_float_exception_flags(0, >active_fpu.fp_status);
 
-if (GET_FP_ENABLE(env->active_fpu.fcr31) & tmp) {
+if (GET_FP_ENABLE(env->active_fpu.fcr31) & mips_exception_flags) {
 do_raise_exception(env, EXCP_FPE, pc);
 } else {
-UPDATE_FP_FLAGS(env->active_fpu.fcr31, tmp);
+UPDATE_FP_FLAGS(env->active_fpu.fcr31, mips_exception_flags);
 }
 }
 }
diff --git a/target/mips/internal.h b/target/mips/internal.h
index 1bf274b3ef..684356e309 100644
--- a/target/mips/internal.h
+++ b/target/mips/internal.h
@@ -224,7 +224,6 @@ uint32_t float_class_s(uint32_t arg, float_status *fst);
 uint64_t float_class_d(uint64_t arg, float_status *fst);
 
 extern unsigned int ieee_rm[];
-int ieee_ex_to_mips(int xcpt);
 void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask);
 
 static inline void restore_rounding_mode(CPUMIPSState *env)
diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c
index 4065cfe4f7..c520405929 100644
--- a/target/mips/msa_helper.c
+++ b/target/mips/msa_helper.c
@@ -5419,54 +5419,81 @@ static inline void check_msacsr_cause(CPUMIPSState 
*env, uintptr_t retaddr)
 #define CLEAR_IS_INEXACT   2
 #define RECIPROCAL_INEXACT 4
 
-static inline int update_msacsr(CPUMIPSState *env, int action, int denormal)
+
+static inline int ieee_to_mips_xcpt_msa(int ieee_xcpt)
 {
-int ieee_ex;
+int mips_xcpt = 0;
 
-int c;
+if (ieee_xcpt & float_flag_invalid) {
+mips_xcpt |= FP_INVALID;
+}
+if (ieee_xcpt & float_flag_overflow) {
+mips_xcpt |= FP_OVERFLOW;
+}
+if (ieee_xcpt & float_flag_underflow) {
+mips_xcpt |= FP_UNDERFLOW;
+}
+if (ieee_xcpt & float_flag_divbyzero) {
+mips_xcpt |= FP_DIV0;
+}
+if (ieee_xcpt & float_flag_inexact) {
+mips_xcpt |= FP_INEXACT;
+}
+
+return mips_xcpt;
+}
+
+static inline int update_msacsr(CPUMIPSState *env, int action, int denormal)
+{
+int ieee_exception_flags;
+int mips_exception_flags = 0;
 int cause;
 int enable;
 
-ieee_ex = get_float_exception_flags(>active_tc.msa_fp_status);
+ieee_exception_flags = get_float_exception_flags(
+   >active_tc.msa_fp_status);
 
 /* QEMU softfloat does not signal all underflow cases */
 if 

[PATCH v5 14/22] target/mips: fpu: Demacro RINT.

2020-05-18 Thread Aleksandar Markovic
This is just a cosmetic change to enable tools like gcov, gdb,
callgrind, etc. to better display involved source code.

Reviewed-by: Aleksandar Rikalo 
Signed-off-by: Aleksandar Markovic 
---
 target/mips/fpu_helper.c | 20 ++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/target/mips/fpu_helper.c b/target/mips/fpu_helper.c
index e227e53f70..dae1331f23 100644
--- a/target/mips/fpu_helper.c
+++ b/target/mips/fpu_helper.c
@@ -1113,10 +1113,26 @@ uint ## bits ## _t helper_float_ ## name(CPUMIPSState 
*env, \
 return fdret;   \
 }
 
-FLOAT_RINT(rint_s, 32)
-FLOAT_RINT(rint_d, 64)
 #undef FLOAT_RINT
 
+uint64_t helper_float_rint_d(CPUMIPSState *env, uint64_t fs)
+{
+uint64_t fdret;
+
+fdret = float64_round_to_int(fs, >active_fpu.fp_status);
+update_fcr31(env, GETPC());
+return fdret;
+}
+
+uint32_t helper_float_rint_s(CPUMIPSState *env, uint32_t fs)
+{
+uint32_t fdret;
+
+fdret = float32_round_to_int(fs, >active_fpu.fp_status);
+update_fcr31(env, GETPC());
+return fdret;
+}
+
 #define FLOAT_CLASS_SIGNALING_NAN  0x001
 #define FLOAT_CLASS_QUIET_NAN  0x002
 #define FLOAT_CLASS_NEGATIVE_INFINITY  0x004
-- 
2.20.1




Re: [RISU 0/9] risu cleanups and improvements

2020-05-18 Thread Richard Henderson
On 5/18/20 12:33 PM, Richard Henderson wrote:
> On 5/18/20 11:39 AM, Peter Maydell wrote:
>> Richard: if you feed an old trace file to the new risu, what
>> error message does it give?
> 
> Bah, it should have generated an error vs the magic number, but doesn't -- it
> silently exits with success.  Alex, expect a v2.

Double bah.  Typo in git checkout, so I didn't actually switch branches for the
test.  It does print an error, but not a useful one:

match status...
mismatch on regs!

I'll improve this.


r~




  1   2   3   4   5   >