Re: [PATCH v5 4/4] colo: Update Documentation for continuous replication

2019-09-28 Thread Lukas Straub
On Thu, 26 Sep 2019 17:27:35 +
"Zhang, Chen"  wrote:

> > -Original Message-
> > From: Lukas Straub 
> > Sent: Monday, September 16, 2019 3:20 AM
> > To: qemu-devel 
> > Cc: Zhang, Chen ; Jason Wang
> > ; Wen Congyang ;
> > Xie Changlong ; kw...@redhat.com;
> > mre...@redhat.com
> > Subject: [PATCH v5 4/4] colo: Update Documentation for continuous
> > replication
> > 
> > Document the qemu command-line and qmp commands for continuous
> > replication
> > 
> > Signed-off-by: Lukas Straub 
> > ---
> >  docs/COLO-FT.txt   | 212 +++--
> >  docs/block-replication.txt |  28 +++--
> >  2 files changed, 173 insertions(+), 67 deletions(-)
> > 
> > diff --git a/docs/COLO-FT.txt b/docs/COLO-FT.txt index
> > ad24680d13..e98c95ca2b 100644
> > --- a/docs/COLO-FT.txt
> > +++ b/docs/COLO-FT.txt
> > @@ -145,35 +145,65 @@ The diagram just shows the main qmp command,
> > you can get the detail  in test procedure.
> > 
> >  == Test procedure ==
> > -1. Startup qemu
> > -Primary:
> > -# qemu-system-x86_64 -accel kvm -m 2048 -smp 2 -qmp stdio -name
> > primary \
> > -  -device piix3-usb-uhci -vnc :7 \
> > -  -device usb-tablet -netdev tap,id=hn0,vhost=off \
> > -  -device virtio-net-pci,id=net-pci0,netdev=hn0 \
> > -  -drive if=virtio,id=primary-disk0,driver=quorum,read-pattern=fifo,vote-
> > threshold=1,\
> > - children.0.file.filename=1.raw,\
> > - children.0.driver=raw -S
> > -Secondary:
> > -# qemu-system-x86_64 -accel kvm -m 2048 -smp 2 -qmp stdio -name
> > secondary \
> > -  -device piix3-usb-uhci -vnc :7 \
> > -  -device usb-tablet -netdev tap,id=hn0,vhost=off \
> > -  -device virtio-net-pci,id=net-pci0,netdev=hn0 \
> > -  -drive if=none,id=secondary-disk0,file.filename=1.raw,driver=raw,node-
> > name=node0 \
> > -  -drive if=virtio,id=active-disk0,driver=replication,mode=secondary,\
> > - file.driver=qcow2,top-id=active-disk0,\
> > - file.file.filename=/mnt/ramfs/active_disk.img,\
> > - file.backing.driver=qcow2,\
> > - file.backing.file.filename=/mnt/ramfs/hidden_disk.img,\
> > - file.backing.backing=secondary-disk0 \
> > -  -incoming tcp:0:
> > -
> > -2. On Secondary VM's QEMU monitor, issue command
> > +Note: Here we are running both instances on the same Machine for
> > +testing, change the IP Addresses if you want to run it on two Hosts
> > +
> > +== Startup qemu ==
> > +1. Primary:
> > +# imagefolder="/mnt/vms/colo-test"
> > +
> > +The disks for the primary and secondary need to be the same before
> > +starting colo # cp --reflink=auto $imagefolder/primary.qcow2
> > +$imagefolder/primary-copy.qcow2
> > +
> > +# qemu-system-x86_64 -enable-kvm -cpu qemu64,+kvmclock -m 512 -smp
> > 1 -qmp stdio \
> > +   -vnc :0 -device piix3-usb-uhci -device usb-tablet -name primary \
> > +   -netdev tap,id=hn0,vhost=off,helper=/usr/lib/qemu/qemu-bridge-helper
> > \
> > +   -device rtl8139,id=e0,netdev=hn0 \
> > +   -chardev socket,id=mirror0,host=127.0.0.1,port=9003,server,nowait \
> > +   -chardev socket,id=compare1,host=127.0.0.1,port=9004,server,wait \
> > +   -chardev socket,id=compare0,host=127.0.0.1,port=9001,server,nowait \
> > +   -chardev socket,id=compare0-0,host=127.0.0.1,port=9001 \
> > +   -chardev socket,id=compare_out,host=127.0.0.1,port=9005,server,nowait
> > \
> > +   -chardev socket,id=compare_out0,host=127.0.0.1,port=9005 \
> > +   -object filter-mirror,id=m0,netdev=hn0,queue=tx,outdev=mirror0 \
> > +   -object filter-
> > redirector,netdev=hn0,id=redire0,queue=rx,indev=compare_out \
> > +   -object filter-
> > redirector,netdev=hn0,id=redire1,queue=rx,outdev=compare0 \
> > +   -object iothread,id=iothread1 \
> > +   -object
> > +colo-compare,id=comp0,primary_in=compare0-
> > 0,secondary_in=compare1,\
> > +outdev=compare_out0,iothread=iothread1 \
> > +   -drive
> > +if=ide,id=colo-disk0,driver=quorum,read-pattern=fifo,vote-threshold=1,\
> > +children.0.file.filename=$imagefolder/primary.qcow2,children.0.driver=q
> > +cow2 -S
> > +
> > +2. Secondary:
> > +# imagefolder="/mnt/vms/colo-test"
> > +
> > +# qemu-img create -f qcow2 $imagefolder/secondary-active.qcow2 10G
> > +
> > +# qemu-img create -f qcow2 $imagefolder/secondary-hidden.qcow2 10G
> > +
> > +# qemu-system-x86_64 -enable-kvm -cpu qemu64,+kvmclock -m 512 -smp
> > 1 -qmp stdio \
> > +   -vnc :1 -device piix3-usb-uhci -device usb-tablet -name secondary \
> > +   -netdev tap,id=hn0,vhost=off,helper=/usr/lib/qemu/qemu-bridge-helper
> > \
> > +   -device rtl8139,id=e0,netdev=hn0 \
> > +   -chardev socket,id=red0,host=127.0.0.1,port=9003,reconnect=1 \
> > +   -chardev socket,id=red1,host=127.0.0.1,port=9004,reconnect=1 \
> > +   -object filter-redirector,id=f1,netdev=hn0,queue=tx,indev=red0 \
> > +   -object filter-redirector,id=f2,netdev=hn0,queue=rx,outdev=red1 \
> > +   -object filter-rewriter,id=rew0,netdev=hn0,queue=all \
> > +   -drive if=none,id=parent0,file.filename=$imagefolder/primary-
> > copy.qcow2,driver=qcow2 \
> > +   -drive
> > +if=non

Re: [PATCH v5 2/4] tests/test-replication.c: Add test for ignoring requests after failover

2019-09-28 Thread Lukas Straub
On Thu, 26 Sep 2019 17:40:03 +
"Zhang, Chen"  wrote:

> > -Original Message-
> > From: Lukas Straub 
> > Sent: Monday, September 16, 2019 3:20 AM
> > To: qemu-devel 
> > Cc: Zhang, Chen ; Jason Wang
> > ; Wen Congyang ;
> > Xie Changlong ; kw...@redhat.com;
> > mre...@redhat.com
> > Subject: [PATCH v5 2/4] tests/test-replication.c: Add test for ignoring
> > requests after failover
> >
> > This simulates the case that happens when we resume COLO after failover.
> >
>
> It looks change the title to "Add test for secondary node continuous backup" 
> is better.

Did you mean "continuous replication"? Would "Add test for secondary node 
continuing replication" be Ok?

> > Signed-off-by: Lukas Straub 
> > ---
> >  tests/test-replication.c | 52
> > 
> >  1 file changed, 52 insertions(+)
> >
> > diff --git a/tests/test-replication.c b/tests/test-replication.c index
> > f085d1993a..5addfc2227 100644
> > --- a/tests/test-replication.c
> > +++ b/tests/test-replication.c
> > @@ -489,6 +489,56 @@ static void test_secondary_stop(void)
> >  teardown_secondary();
> >  }
> >
> > +static void test_secondary_failover_then_ignore_requests(void)
>
> Same as title, I think change to "test_secondary_continuous_backup" is more 
> clear.
>
> Thanks
> Zhang Chen
>
> > +{
> > +BlockBackend *top_blk, *local_blk;
> > +Error *local_err = NULL;
> > +
> > +top_blk = start_secondary();
> > +replication_start_all(REPLICATION_MODE_SECONDARY, &local_err);
> > +g_assert(!local_err);
> > +
> > +/* write 0x22 to s_local_disk (IMG_SIZE / 2, IMG_SIZE) */
> > +local_blk = blk_by_name(S_LOCAL_DISK_ID);
> > +test_blk_write(local_blk, 0x22, IMG_SIZE / 2, IMG_SIZE / 2, false);
> > +
> > +/* replication will backup s_local_disk to s_hidden_disk */
> > +test_blk_read(top_blk, 0x11, IMG_SIZE / 2,
> > +  IMG_SIZE / 2, 0, IMG_SIZE, false);
> > +
> > +/* write 0x33 to s_active_disk (0, IMG_SIZE / 2) */
> > +test_blk_write(top_blk, 0x33, 0, IMG_SIZE / 2, false);
> > +
> > +/* do failover (active commit) */
> > +replication_stop_all(true, &local_err);
> > +g_assert(!local_err);
> > +
> > +/* it should ignore all requests from now on */
> > +
> > +/* start after failover */
> > +replication_start_all(REPLICATION_MODE_PRIMARY, &local_err);
> > +g_assert(!local_err);
> > +
> > +/* checkpoint */
> > +replication_do_checkpoint_all(&local_err);
> > +g_assert(!local_err);
> > +
> > +/* stop */
> > +replication_stop_all(true, &local_err);
> > +g_assert(!local_err);
> > +
> > +/* read from s_local_disk (0, IMG_SIZE / 2) */
> > +test_blk_read(top_blk, 0x33, 0, IMG_SIZE / 2,
> > +  0, IMG_SIZE / 2, false);
> > +
> > +
> > +/* read from s_local_disk (IMG_SIZE / 2, IMG_SIZE) */
> > +test_blk_read(top_blk, 0x22, IMG_SIZE / 2,
> > +  IMG_SIZE / 2, 0, IMG_SIZE, false);
> > +
> > +teardown_secondary();
> > +}
> > +
> >  static void test_secondary_do_checkpoint(void)
> >  {
> >  BlockBackend *top_blk, *local_blk;
> > @@ -584,6 +634,8 @@ int main(int argc, char **argv)
> >  g_test_add_func("/replication/secondary/write", test_secondary_write);
> >  g_test_add_func("/replication/secondary/start", test_secondary_start);
> >  g_test_add_func("/replication/secondary/stop",  test_secondary_stop);
> > +
> > g_test_add_func("/replication/secondary/failover_then_ignore_requests",
> > +test_secondary_failover_then_ignore_requests);
> >  g_test_add_func("/replication/secondary/do_checkpoint",
> >  test_secondary_do_checkpoint);
> >  g_test_add_func("/replication/secondary/get_error_all",
> > --
> > 2.20.1
>




Re: [PATCH v5 3/4] net/filter.c: Add Options to insert filters anywhere in the filter list

2019-09-28 Thread Lukas Straub
On Thu, 26 Sep 2019 17:02:58 +
"Zhang, Chen"  wrote:
> > diff --git a/qemu-options.hx b/qemu-options.hx index
> > 08749a3391..23fa5a344e 100644
> > --- a/qemu-options.hx
> > +++ b/qemu-options.hx
> > @@ -4368,7 +4368,7 @@ applications, they can do this through this
> > parameter. Its format is  a gnutls priority string as described at
> > @url{https://gnutls.org/manual/html_node/Priority-Strings.html}.
> >
> > -@item -object filter-
> > buffer,id=@var{id},netdev=@var{netdevid},interval=@var{t}[,queue=@var{
> > all|rx|tx}][,status=@var{on|off}]
> > +@item -object
> > +filter-buffer,id=@var{id},netdev=@var{netdevid},interval=@var{t}[,queue
> > +=@var{all|rx|tx}][,status=@var{on|off}][,position=@var{head|tail|id= > +>}][,insert=@var{behind|before}]
> >
> >  Interval @var{t} can't be 0, this filter batches the packet delivery: all  
> > packets
> > arriving in a given interval on netdev @var{netdevid} are delayed @@ -
> > 4387,11 +4387,11 @@ queue @var{all|rx|tx} is an option that can be applied
> > to any netfilter.
> >  @option{tx}: the filter is attached to the transmit queue of the netdev,
> >   where it will receive packets sent by the netdev.
> >
> > -@item -object filter-
> > mirror,id=@var{id},netdev=@var{netdevid},outdev=@var{chardevid},queue
> > =@var{all|rx|tx}[,vnet_hdr_support]
> > +@item -object
> > +filter-mirror,id=@var{id},netdev=@var{netdevid},outdev=@var{chardevid},
> > +queue=@var{all|rx|tx}[,vnet_hdr_support][,position=@var{head|tail|id=<
> > i
> > +d>}][,insert=@var{behind|before}]
> >
> >  filter-mirror on netdev @var{netdevid},mirror net packet to
> > chardev@var{chardevid}, if it has the vnet_hdr_support flag, filter-mirror 
> > will
> > mirror packet with vnet_hdr_len.
> >
>
> Please add description for the newly added parameter in each filter.
> After that:
> Reviewed-by: Zhang Chen 
>
> Thanks
> Zhang Chen

Hi,
I will add a single description like its currently done with the "queue" 
option, noting that
it applies to any netfilter. Is that Ok?

Regards,
Lukas Straub

>
> > -@item -object filter-
> > redirector,id=@var{id},netdev=@var{netdevid},indev=@var{chardevid},out
> > dev=@var{chardevid},queue=@var{all|rx|tx}[,vnet_hdr_support]
> > +@item -object
> > +filter-redirector,id=@var{id},netdev=@var{netdevid},indev=@var{chardevi
> > +d},outdev=@var{chardevid},queue=@var{all|rx|tx}[,vnet_hdr_support][,p
> > os
> > +ition=@var{head|tail|id=}][,insert=@var{behind|before}]
> >
> >  filter-redirector on netdev @var{netdevid},redirect filter's net packet to
> > chardev  @var{chardevid},and redirect indev's packet to filter.if it has the
> > vnet_hdr_support flag, @@ -4400,7 +4400,7 @@ Create a filter-redirector
> > we need to differ outdev id from indev id, id can not  be the same. we can
> > just use indev or outdev, but at least one of indev or outdev  need to be
> > specified.
> >
> > -@item -object filter-
> > rewriter,id=@var{id},netdev=@var{netdevid},queue=@var{all|rx|tx},[vnet_
> > hdr_support]
> > +@item -object
> > +filter-rewriter,id=@var{id},netdev=@var{netdevid},queue=@var{all|rx|tx}
> > +,[vnet_hdr_support][,position=@var{head|tail|id=}][,insert=@var{beh
> > +ind|before}]
> >
> >  Filter-rewriter is a part of COLO project.It will rewrite tcp packet to
> > secondary from primary to keep secondary tcp connection,and rewrite @@ -
> > 4413,7 +4413,7 @@ colo secondary:
> >  -object filter-redirector,id=f2,netdev=hn0,queue=rx,outdev=red1
> >  -object filter-rewriter,id=rew0,netdev=hn0,queue=all
> >
> > -@item -object filter-
> > dump,id=@var{id},netdev=@var{dev}[,file=@var{filename}][,maxlen=@var{
> > len}]
> > +@item -object
> > +filter-
> > dump,id=@var{id},netdev=@var{dev}[,file=@var{filename}][,maxlen=
> > +@var{len}][,position=@var{head|tail|id=}][,insert=@var{behind|befor
> > +e}]
> >
> >  Dump the network traffic on netdev @var{dev} to the file specified by
> > @var{filename}. At most @var{len} bytes (64k by default) per packet are
> > stored.
> > --
> > 2.20.1
>




Re: [PATCH v2 01/20] target/mips: Clean up helper.c

2019-09-28 Thread Markus Armbruster
"Aleksandar Markovic"  writes:

> OK, my case belongs to "used to work before" group. I used GMail
> Android app to send this particular mail, and have been using that app
> for several months without problema. I am going to find an alternative
> way of sending mails to the list.

Appreciated!

[...]



Re: target/ppc: bug in optimised vsl/vsr implementation?

2019-09-28 Thread Aleksandar Markovic
26.09.2019. 20.14, "Mark Cave-Ayland"  је
написао/ла:
>
> As part of the investigation into the DFP number issue reported at
> https://bugs.launchpad.net/qemu/+bug/1841990 it appears that there may
also be a bug
> introduced by the new optimised vsl/vsr implementation:
>
> commit 4e6d0920e7547e6af4bbac5ffe9adfe6ea621822
> Author: Stefan Brankovic 
> Date: Mon Jul 15 16:22:48 2019 +0200
>
> target/ppc: Optimize emulation of vsl and vsr instructions
>
>

(sorry in advance if the format of this message looks odd, I have some
problems with mail settings related to recent qemu-devel mailer settings
changes; I will adjust my mail settings in next few days)

Mark and Paul (and Stefan),

Thanks for spotting this and pinpointing the culprit commit. I guess Stefan
is going to respond soon, but, in the meantime, I took a look at the commit
in question:

https://github.com/qemu/qemu/commit/4e6d0920e7547e6af4bbac5ffe9adfe6ea621822

I don't have at the moment any dev/test environment handy, but I did manual
inspection of the code, and here is what I found (in order of importance,
perceived by me):

1. The code will not work correctly if the shift ammount (variable 'sh') is
0. This is because, in that case, one of succeeding invocations of TCG
shift functions will be required to shift a 64-bit TCG variable by 64 bits,
and the result of such TCG operation is undefined (shift amount must be 63
or less) - see https://github.com/qemu/qemu/blob/master/tcg/README.

2. Variable naming is better in the old helper than in the new translator.
In that light, I would advise Stefan to change 'sh' to 'shift', and
'shifted' to 'carry'.

3. Lines

tcg_gen_andi_i64(shifted, shifted, 0x7fULL);

and

tcg_gen_andi_i64(shifted, shifted, 0xfe00ULL);

appear to be spurious (albait in a harmless way). Therefore, they should be
deleted, or, alternatevely, a justification for them should be provided.

4. In the commit message, variable names were used without quotation mark,
resulting in puzzling and unclear wording.

5. (a question for Mark) After all recent changes, does get_avr64(..., ...,
true) always (for any endian configuration) return the "high" half of an
Altivec register, and get_avr64(..., ..., false) the "low" one?

Given all these circumstances, perhaps the most reasonable solution would
be to revert the commit in question, and allow Stefan enough dev and test
time to hopefully submit a new, better, version later on.

Sincerely,
Aleksandar


Re: [PATCH v25 00/22] Add RX archtecture support

2019-09-28 Thread no-reply
Patchew URL: 
https://patchew.org/QEMU/20190927062302.110144-1-ys...@users.sourceforge.jp/



Hi,

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

Type: series
Message-id: 20190927062302.110144-1-ys...@users.sourceforge.jp
Subject: [PATCH v25 00/22] Add RX archtecture support

=== 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'
1a74ffc qapi/machine.json: Add RX cpu.
c173e68 BootLinuxConsoleTest: Test the RX-Virt machine
b4e9a7a Add rx-softmmu
5bdc07e hw/rx: Restrict the RX62N microcontroller to the RX62N CPU core
2496aa4 hw/rx: Honor -accel qtest
b97a84d hw/rx: RX Target hardware definition
f806e27 hw/char: RX62N serial communication interface (SCI)
bd59212 hw/timer: RX62N internal timer modules
cb22efa hw/intc: RX62N interrupt controller (ICUa)
ae43531 target/rx: Dump bytes for each insn during disassembly
26dd1a2 target/rx: Collect all bytes during disassembly
18aeea2 target/rx: Emit all disassembly in one prt()
17d9d21 target/rx: Use prt_ldmi for XCHG_mr disassembly
2882571 target/rx: Replace operand with prt_ldmi in disassembler
bf3b3f2 target/rx: Disassemble rx_index_addr into a string
73102ce target/rx: RX disassembler
90cb197 target/rx: CPU definition
5c00dbb target/rx: TCG helper
2b15272 target/rx: TCG translation
15f28f1 hw/registerfields.h: Add 8bit and 16bit register macros
fa571c7 qemu/bitops.h: Add extract8 and extract16
15bf923 MAINTAINERS: Add RX

=== OUTPUT BEGIN ===
1/22 Checking commit 15bf92348a56 (MAINTAINERS: Add RX)
2/22 Checking commit fa571c7ef6af (qemu/bitops.h: Add extract8 and extract16)
3/22 Checking commit 15f28f1299de (hw/registerfields.h: Add 8bit and 16bit 
register macros)
Use of uninitialized value in concatenation (.) or string at 
./scripts/checkpatch.pl line 2484.
ERROR: Macros with multiple statements should be enclosed in a do - while loop
#27: FILE: include/hw/registerfields.h:25:
+#define REG8(reg, addr)  \
+enum { A_ ## reg = (addr) };  \
+enum { R_ ## reg = (addr) };

ERROR: Macros with multiple statements should be enclosed in a do - while loop
#31: FILE: include/hw/registerfields.h:29:
+#define REG16(reg, addr)  \
+enum { A_ ## reg = (addr) };  \
+enum { R_ ## reg = (addr) / 2 };

total: 2 errors, 0 warnings, 56 lines checked

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

4/22 Checking commit 2b1527203652 (target/rx: TCG translation)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#20: 
new file mode 100644

total: 0 errors, 1 warnings, 3065 lines checked

Patch 4/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
5/22 Checking commit 5c00dbb5e309 (target/rx: TCG helper)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#21: 
new file mode 100644

total: 0 errors, 1 warnings, 650 lines checked

Patch 5/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
6/22 Checking commit 90cb19738c00 (target/rx: CPU definition)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#38: 
new file mode 100644

total: 0 errors, 1 warnings, 588 lines checked

Patch 6/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
7/22 Checking commit 73102ce10f6a (target/rx: RX disassembler)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#38: 
new file mode 100644

total: 0 errors, 1 warnings, 1497 lines checked

Patch 7/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
8/22 Checking commit bf3b3f236e0b (target/rx: Disassemble rx_index_addr into a 
string)
9/22 Checking commit 2882571a240d (target/rx: Replace operand with prt_ldmi in 
disassembler)
10/22 Checking commit 17d9d217fe49 (target/rx: Use prt_ldmi for XCHG_mr 
disassembly)
11/22 Checking commit 18aeea285a8b (target/rx: Emit all disassembly in one 
prt())
12/22 Checking commit 26dd1a2ced54 (target/rx: Collect all bytes during 
disassembly)
13/22 Checking commit ae43531ca84d (target/rx: Dump bytes for each insn during 
disassembly)
14/22 Checking commit cb22efa8a743 (hw/intc: RX62N interrupt controller (ICUa))
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#40: 
new fil

[Bug 1845580] Re: issue with QEMU on Raspberry Pi failing to access CDROM

2019-09-28 Thread Chris Schneider
I compiled 4.1.0 on the Raspberry, everything seemed to compile.

I have verified with qemu-system-i386 --version displays 4.1.0

Using the below basic command line:

qemu-system-i386 -hda c.hda -cdrom FD12CD.iso -boot order=d

now when I try to execute the qemu I get only below as it just seems to
hang:


WARNING: Image format was not specified for 'c.hda' and probing guessed raw.
 Automatically detecting the format is dangerous for raw images, write 
operations on block 0 will be restricted.
 Specify the 'raw' format explicitly to remove the restrictions.
VNC server running on ::1:5901

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

Title:
  issue with QEMU on Raspberry Pi failing to access CDROM

Status in QEMU:
  New

Bug description:
  I am trying to access the CDROM (iso) from QEMU using FreeDOS and I
  get an error when doing a directory for:

  i can boot from the iso but if i exit to access the files from the
  CDROM ISO i get the attached error.

  I believe there is an issue with the QEMU for the Raspberry Pi.

  I am using a Raspberry Pi3 with the latest full Raspbian Buster load

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



[PULL 02/27] qapi: Tighten QAPISchemaFOO.check() assertions

2019-09-28 Thread Markus Armbruster
When we introduced the QAPISchema intermediate representation (commit
ac88219a6c7), we took a shortcut: we left check_exprs() & friends
alone instead of moving semantic checks into the
QAPISchemaFOO.check().  check_exprs() still checks and reports errors,
and the .check() assert check_exprs() did the job.  There are a few
gaps, though.

QAPISchemaArrayType.check() neglects to assert the element type is not
an array.  Add the assertion.

QAPISchemaObjectTypeVariants.check() neglects to assert the tag member
is not optional.  Add the assertion.

It neglects to assert the tag member is not conditional.  Add the
assertion.

It neglects to assert we actually have variants.  Add the assertion.

It asserts the variants are object types, but neglects to assert they
don't have variants.  Tighten the assertion.

QAPISchemaObjectTypeVariants.check_clash() has the same issue.
However, it can run only after .check().  Delete the assertion instead
of tightening it.

QAPISchemaAlternateType.check() neglects to assert the branch types
don't conflict.  Fixing that isn't trivial, so add just a TODO comment
for now.  It'll be resolved later in this series.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20190927134639.4284-2-arm...@redhat.com>
---
 scripts/qapi/common.py | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index b00caacca3..155b87b825 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -1362,6 +1362,7 @@ class QAPISchemaArrayType(QAPISchemaType):
 QAPISchemaType.check(self, schema)
 self.element_type = schema.lookup_type(self._element_type_name)
 assert self.element_type
+assert not isinstance(self.element_type, QAPISchemaArrayType)
 
 @property
 def ifcond(self):
@@ -1606,6 +1607,8 @@ class QAPISchemaObjectTypeVariants(object):
 self.tag_member = seen[c_name(self._tag_name)]
 assert self._tag_name == self.tag_member.name
 assert isinstance(self.tag_member.type, QAPISchemaEnumType)
+assert not self.tag_member.optional
+assert self.tag_member.ifcond == []
 if self._tag_name:# flat union
 # branches that are not explicitly covered get an empty type
 cases = set([v.name for v in self.variants])
@@ -1615,20 +1618,21 @@ class QAPISchemaObjectTypeVariants(object):
 m.ifcond)
 v.set_owner(self.tag_member.owner)
 self.variants.append(v)
+assert self.variants
 for v in self.variants:
 v.check(schema)
 # Union names must match enum values; alternate names are
 # checked separately. Use 'seen' to tell the two apart.
 if seen:
 assert v.name in self.tag_member.type.member_names()
-assert isinstance(v.type, QAPISchemaObjectType)
+assert (isinstance(v.type, QAPISchemaObjectType)
+and not v.type.variants)
 v.type.check(schema)
 
 def check_clash(self, info, seen):
 for v in self.variants:
 # Reset seen map for each variant, since qapi names from one
 # branch do not affect another branch
-assert isinstance(v.type, QAPISchemaObjectType)
 v.type.check_clash(info, dict(seen))
 
 
@@ -1659,6 +1663,7 @@ class QAPISchemaAlternateType(QAPISchemaType):
 seen = {}
 for v in self.variants.variants:
 v.check_clash(self.info, seen)
+# TODO check conflicting qtypes
 if self.doc:
 self.doc.connect_member(v)
 if self.doc:
-- 
2.21.0




[PULL 01/27] qmp-dispatch: Use CommandNotFound error for disabled commands

2019-09-28 Thread Markus Armbruster
From: Michal Privoznik 

If a command is disabled an error is reported.  But due to usage of
error_setg() the class of the error is GenericError which does not
help callers in distinguishing this case from a case where a qmp
command fails regularly due to other reasons.

We used to use class CommandDisabled until the great error
simplification (commit de253f1491 for QMP and commit 93b91c59db for
qemu-ga, both v1.2.0).

Use CommandNotFound error class, which is close enough.

Signed-off-by: Michal Privoznik 
Message-Id: 

Reviewed-by: Eric Blake 
[Test update squashed in, commit message tweaked]
Signed-off-by: Markus Armbruster 
---
 qapi/qmp-dispatch.c | 5 +++--
 tests/test-qga.c| 4 ++--
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
index 3037d353a4..bc264b3c9b 100644
--- a/qapi/qmp-dispatch.c
+++ b/qapi/qmp-dispatch.c
@@ -104,8 +104,9 @@ static QObject *do_qmp_dispatch(QmpCommandList *cmds, 
QObject *request,
 return NULL;
 }
 if (!cmd->enabled) {
-error_setg(errp, "The command %s has been disabled for this instance",
-   command);
+error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND,
+  "The command %s has been disabled for this instance",
+  command);
 return NULL;
 }
 if (oob && !(cmd->options & QCO_ALLOW_OOB)) {
diff --git a/tests/test-qga.c b/tests/test-qga.c
index 891aa3d322..1ca49bbced 100644
--- a/tests/test-qga.c
+++ b/tests/test-qga.c
@@ -668,7 +668,7 @@ static void test_qga_blacklist(gconstpointer data)
 error = qdict_get_qdict(ret, "error");
 class = qdict_get_try_str(error, "class");
 desc = qdict_get_try_str(error, "desc");
-g_assert_cmpstr(class, ==, "GenericError");
+g_assert_cmpstr(class, ==, "CommandNotFound");
 g_assert_nonnull(g_strstr_len(desc, -1, "has been disabled"));
 qobject_unref(ret);
 
@@ -677,7 +677,7 @@ static void test_qga_blacklist(gconstpointer data)
 error = qdict_get_qdict(ret, "error");
 class = qdict_get_try_str(error, "class");
 desc = qdict_get_try_str(error, "desc");
-g_assert_cmpstr(class, ==, "GenericError");
+g_assert_cmpstr(class, ==, "CommandNotFound");
 g_assert_nonnull(g_strstr_len(desc, -1, "has been disabled"));
 qobject_unref(ret);
 
-- 
2.21.0




[PULL 14/27] qapi: Make check_type()'s array case a bit more obvious

2019-09-28 Thread Markus Armbruster
check_type() checks the array's contents, then peels off the array and
falls through to the "not array" code without resetting allow_array
and allow_dict to False.  Works because the peeled value is a string,
and allow_array and allow_dict aren't used then.  Tidy up anyway:
recurse instead, defaulting allow_array and allow_dict to False.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20190927134639.4284-14-arm...@redhat.com>
---
 scripts/qapi/common.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 111a4bbe55..870d8b0ecb 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -795,7 +795,8 @@ def check_type(value, info, source,
 raise QAPISemError(info,
"%s: array type must contain single type name" %
source)
-value = value[0]
+check_type(value[0], info, source, allow_metas=allow_metas)
+return
 
 # Check if type name for value is okay
 if isinstance(value, str):
-- 
2.21.0




[PULL 10/27] qapi: Improve reporting of invalid name errors

2019-09-28 Thread Markus Armbruster
Split check_name() into check_name_is_str() and check_name_str(), keep
check_name() as a wrapper.

Move add_name()'s call into its caller check_exprs(), and inline.

This permits delaying check_name_str() there, so its error message
gains an "in definition" line.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20190927134639.4284-10-arm...@redhat.com>
---
 scripts/qapi/common.py   | 20 
 tests/qapi-schema/bad-ident.err  |  1 +
 tests/qapi-schema/command-int.err|  1 +
 tests/qapi-schema/redefined-builtin.err  |  1 +
 tests/qapi-schema/redefined-command.err  |  1 +
 tests/qapi-schema/redefined-event.err|  1 +
 tests/qapi-schema/redefined-type.err |  1 +
 tests/qapi-schema/reserved-command-q.err |  1 +
 tests/qapi-schema/reserved-type-kind.err |  1 +
 tests/qapi-schema/reserved-type-list.err |  1 +
 10 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index c909821560..6f35cd131e 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -708,11 +708,22 @@ valid_name = re.compile(r'^(__[a-zA-Z0-9.-]+_)?'
 
 def check_name(name, info, source,
allow_optional=False, enum_member=False, permit_upper=False):
+check_name_is_str(name, info, source)
+check_name_str(name, info, source,
+   allow_optional, enum_member, permit_upper)
+
+
+def check_name_is_str(name, info, source):
+if not isinstance(name, str):
+raise QAPISemError(info, "%s requires a string name" % source)
+
+
+def check_name_str(name, info, source,
+   allow_optional=False, enum_member=False,
+   permit_upper=False):
 global valid_name
 membername = name
 
-if not isinstance(name, str):
-raise QAPISemError(info, "%s requires a string name" % source)
 if name.startswith('*'):
 membername = name[1:]
 if not allow_optional:
@@ -734,7 +745,6 @@ def check_name(name, info, source,
 
 def add_name(name, info, meta):
 global all_names
-check_name(name, info, "'%s'" % meta, permit_upper=True)
 # FIXME should reject names that differ only in '_' vs. '.'
 # vs. '-', because they're liable to clash in generated C.
 if name in all_names:
@@ -1153,8 +1163,10 @@ def check_exprs(exprs):
 raise QAPISemError(info, "expression is missing metatype")
 normalize_if(expr)
 name = expr[meta]
-add_name(name, info, meta)
+check_name_is_str(name, info, "'%s'" % meta)
 info.set_defn(meta, name)
+check_name_str(name, info, "'%s'" % meta, permit_upper=True)
+add_name(name, info, meta)
 if doc and doc.symbol != name:
 raise QAPISemError(
 info,
diff --git a/tests/qapi-schema/bad-ident.err b/tests/qapi-schema/bad-ident.err
index c4190602b5..6878889854 100644
--- a/tests/qapi-schema/bad-ident.err
+++ b/tests/qapi-schema/bad-ident.err
@@ -1 +1,2 @@
+tests/qapi-schema/bad-ident.json: In struct '*oops':
 tests/qapi-schema/bad-ident.json:2: 'struct' does not allow optional name 
'*oops'
diff --git a/tests/qapi-schema/command-int.err 
b/tests/qapi-schema/command-int.err
index 0f9300679b..56b45bf656 100644
--- a/tests/qapi-schema/command-int.err
+++ b/tests/qapi-schema/command-int.err
@@ -1 +1,2 @@
+tests/qapi-schema/command-int.json: In command 'int':
 tests/qapi-schema/command-int.json:2: built-in 'int' is already defined
diff --git a/tests/qapi-schema/redefined-builtin.err 
b/tests/qapi-schema/redefined-builtin.err
index b2757225c4..67775fdb41 100644
--- a/tests/qapi-schema/redefined-builtin.err
+++ b/tests/qapi-schema/redefined-builtin.err
@@ -1 +1,2 @@
+tests/qapi-schema/redefined-builtin.json: In struct 'size':
 tests/qapi-schema/redefined-builtin.json:2: built-in 'size' is already defined
diff --git a/tests/qapi-schema/redefined-command.err 
b/tests/qapi-schema/redefined-command.err
index 82ae256e63..b77a05d354 100644
--- a/tests/qapi-schema/redefined-command.err
+++ b/tests/qapi-schema/redefined-command.err
@@ -1 +1,2 @@
+tests/qapi-schema/redefined-command.json: In command 'foo':
 tests/qapi-schema/redefined-command.json:3: command 'foo' is already defined
diff --git a/tests/qapi-schema/redefined-event.err 
b/tests/qapi-schema/redefined-event.err
index 35429cb481..fd02d38157 100644
--- a/tests/qapi-schema/redefined-event.err
+++ b/tests/qapi-schema/redefined-event.err
@@ -1 +1,2 @@
+tests/qapi-schema/redefined-event.json: In event 'EVENT_A':
 tests/qapi-schema/redefined-event.json:3: event 'EVENT_A' is already defined
diff --git a/tests/qapi-schema/redefined-type.err 
b/tests/qapi-schema/redefined-type.err
index 06ea78c478..89acc82c2d 100644
--- a/tests/qapi-schema/redefined-type.err
+++ b/tests/qapi-schema/redefined-type.err
@@ -1 +1,2 @@
+tests/qapi-schema/redefined-type.json: In enum 'foo':
 tests/qapi-schema/redefined-type.json:3: struct 'foo' is already defined
diff --git a/tests/qa

[PULL 04/27] qapi: New QAPISourceInfo, replacing dict

2019-09-28 Thread Markus Armbruster
We track source locations with a dict of the form

{'file': FNAME, 'line': LINENO, 'parent': PARENT}

where PARENT is None for the main file, and the include directive's
source location for included files.

This is serviceable enough, but the next commit will add information,
and that's going to come out cleaner if we turn this into a class.  So
do that.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20190927134639.4284-4-arm...@redhat.com>
---
 scripts/qapi/common.py | 69 +-
 1 file changed, 41 insertions(+), 28 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index bfb3e8a493..5843f3eeb2 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -13,6 +13,7 @@
 
 from __future__ import print_function
 from contextlib import contextmanager
+import copy
 import errno
 import os
 import re
@@ -53,34 +54,50 @@ struct_types = {}
 union_types = {}
 all_names = {}
 
+
 #
 # Parsing the schema into expressions
 #
 
+class QAPISourceInfo(object):
+def __init__(self, fname, line, parent):
+self.fname = fname
+self.line = line
+self.parent = parent
 
-def error_path(parent):
-res = ''
-while parent:
-res = ('In file included from %s:%d:\n' % (parent['file'],
-   parent['line'])) + res
-parent = parent['parent']
-return res
+def next_line(self):
+info = copy.copy(self)
+info.line += 1
+return info
+
+def loc(self):
+return '%s:%d' % (self.fname, self.line)
+
+def include_path(self):
+ret = ''
+parent = self.parent
+while parent:
+ret = 'In file included from %s:\n' % parent.loc() + ret
+parent = parent.parent
+return ret
+
+def __str__(self):
+return self.include_path() + self.loc()
 
 
 class QAPIError(Exception):
-def __init__(self, fname, line, col, incl_info, msg):
+def __init__(self, info, col, msg):
 Exception.__init__(self)
-self.fname = fname
-self.line = line
+self.info = info
 self.col = col
-self.info = incl_info
 self.msg = msg
 
 def __str__(self):
-loc = '%s:%d' % (self.fname, self.line)
+loc = str(self.info)
 if self.col is not None:
+assert self.info.line is not None
 loc += ':%s' % self.col
-return error_path(self.info) + '%s: %s' % (loc, self.msg)
+return loc + ': ' + self.msg
 
 
 class QAPIParseError(QAPIError):
@@ -91,14 +108,12 @@ class QAPIParseError(QAPIError):
 col = (col + 7) % 8 + 1
 else:
 col += 1
-QAPIError.__init__(self, parser.fname, parser.line, col,
-   parser.incl_info, msg)
+QAPIError.__init__(self, parser.info, col, msg)
 
 
 class QAPISemError(QAPIError):
 def __init__(self, info, msg):
-QAPIError.__init__(self, info['file'], info['line'], None,
-   info['parent'], msg)
+QAPIError.__init__(self, info, None, msg)
 
 
 class QAPIDoc(object):
@@ -382,12 +397,11 @@ class QAPISchemaParser(object):
 def __init__(self, fp, previously_included=[], incl_info=None):
 self.fname = fp.name
 previously_included.append(os.path.abspath(fp.name))
-self.incl_info = incl_info
 self.src = fp.read()
 if self.src == '' or self.src[-1] != '\n':
 self.src += '\n'
 self.cursor = 0
-self.line = 1
+self.info = QAPISourceInfo(self.fname, 1, incl_info)
 self.line_pos = 0
 self.exprs = []
 self.docs = []
@@ -395,8 +409,7 @@ class QAPISchemaParser(object):
 cur_doc = None
 
 while self.tok is not None:
-info = {'file': self.fname, 'line': self.line,
-'parent': self.incl_info}
+info = self.info
 if self.tok == '#':
 self.reject_expr_doc(cur_doc)
 cur_doc = self.get_doc(info)
@@ -456,9 +469,9 @@ class QAPISchemaParser(object):
 # catch inclusion cycle
 inf = info
 while inf:
-if incl_abs_fname == os.path.abspath(inf['file']):
+if incl_abs_fname == os.path.abspath(inf.fname):
 raise QAPISemError(info, "Inclusion loop for %s" % include)
-inf = inf['parent']
+inf = inf.parent
 
 # skip multiple include of the same file
 if incl_abs_fname in previously_included:
@@ -552,7 +565,7 @@ class QAPISchemaParser(object):
 if self.cursor == len(self.src):
 self.tok = None
 return
-self.line += 1
+self.info = self.info.next_line()
 self.line_pos = self.cursor
 elif not self.tok.isspace():
 # Show up to next structural,

[PULL 03/27] qapi: Rename .owner to .defined_in

2019-09-28 Thread Markus Armbruster
QAPISchemaMember.owner is the name of the defining entity.  That's a
confusing name when an object type inherits members from a base type.
Rename it to .defined_in.  Rename .set_owner() and ._pretty_owner() to
match.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20190927134639.4284-3-arm...@redhat.com>
---
 scripts/qapi/common.py | 61 +-
 1 file changed, 31 insertions(+), 30 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 155b87b825..bfb3e8a493 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -1319,7 +1319,7 @@ class QAPISchemaEnumType(QAPISchemaType):
 QAPISchemaType.__init__(self, name, info, doc, ifcond)
 for m in members:
 assert isinstance(m, QAPISchemaEnumMember)
-m.set_owner(name)
+m.set_defined_in(name)
 assert prefix is None or isinstance(prefix, str)
 self.members = members
 self.prefix = prefix
@@ -1405,13 +1405,13 @@ class QAPISchemaObjectType(QAPISchemaType):
 assert base is None or isinstance(base, str)
 for m in local_members:
 assert isinstance(m, QAPISchemaObjectTypeMember)
-m.set_owner(name)
+m.set_defined_in(name)
 if variants is not None:
 assert isinstance(variants, QAPISchemaObjectTypeVariants)
-variants.set_owner(name)
+variants.set_defined_in(name)
 for f in features:
 assert isinstance(f, QAPISchemaFeature)
-f.set_owner(name)
+f.set_defined_in(name)
 self._base_name = base
 self.base = None
 self.local_members = local_members
@@ -1521,15 +1521,16 @@ class QAPISchemaMember(object):
 assert isinstance(name, str)
 self.name = name
 self.ifcond = ifcond or []
-self.owner = None
+self.defined_in = None
 
-def set_owner(self, name):
-assert not self.owner
-self.owner = name
+def set_defined_in(self, name):
+assert not self.defined_in
+self.defined_in = name
 
 def check_clash(self, info, seen):
 cname = c_name(self.name)
-if cname.lower() != cname and self.owner not in name_case_whitelist:
+if (cname.lower() != cname
+and self.defined_in not in name_case_whitelist):
 raise QAPISemError(info,
"%s should not use uppercase" % self.describe())
 if cname in seen:
@@ -1537,27 +1538,27 @@ class QAPISchemaMember(object):
(self.describe(), seen[cname].describe()))
 seen[cname] = self
 
-def _pretty_owner(self):
-owner = self.owner
-if owner.startswith('q_obj_'):
+def _pretty_defined_in(self):
+defined_in = self.defined_in
+if defined_in.startswith('q_obj_'):
 # See QAPISchema._make_implicit_object_type() - reverse the
 # mapping there to create a nice human-readable description
-owner = owner[6:]
-if owner.endswith('-arg'):
-return '(parameter of %s)' % owner[:-4]
-elif owner.endswith('-base'):
-return '(base of %s)' % owner[:-5]
+defined_in = defined_in[6:]
+if defined_in.endswith('-arg'):
+return '(parameter of %s)' % defined_in[:-4]
+elif defined_in.endswith('-base'):
+return '(base of %s)' % defined_in[:-5]
 else:
-assert owner.endswith('-wrapper')
+assert defined_in.endswith('-wrapper')
 # Unreachable and not implemented
 assert False
-if owner.endswith('Kind'):
+if defined_in.endswith('Kind'):
 # See QAPISchema._make_implicit_enum_type()
-return '(branch of %s)' % owner[:-4]
-return '(%s of %s)' % (self.role, owner)
+return '(branch of %s)' % defined_in[:-4]
+return '(%s of %s)' % (self.role, defined_in)
 
 def describe(self):
-return "'%s' %s" % (self.name, self._pretty_owner())
+return "'%s' %s" % (self.name, self._pretty_defined_in())
 
 
 class QAPISchemaEnumMember(QAPISchemaMember):
@@ -1578,7 +1579,7 @@ class QAPISchemaObjectTypeMember(QAPISchemaMember):
 self.optional = optional
 
 def check(self, schema):
-assert self.owner
+assert self.defined_in
 self.type = schema.lookup_type(self._type_name)
 assert self.type
 
@@ -1598,9 +1599,9 @@ class QAPISchemaObjectTypeVariants(object):
 self.tag_member = tag_member
 self.variants = variants
 
-def set_owner(self, name):
+def set_defined_in(self, name):
 for v in self.variants:
-v.set_owner(name)
+v.set_defined_in(name)
 
 def check(self, schema, seen):
 if not self.tag_member:# flat union
@@ -1616,7 +161

[PULL 20/27] qapi: Improve reporting of invalid flags

2019-09-28 Thread Markus Armbruster
Split check_flags() off check_keys() and have check_exprs() call it
later, so its error messages gain an "in definition" line.  Tweak the
error messages.

Checking values in a function named check_keys() is unclean anyway.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20190927134639.4284-20-arm...@redhat.com>
---
 scripts/qapi/common.py | 22 --
 tests/qapi-schema/allow-preconfig-test.err |  3 ++-
 tests/qapi-schema/args-bad-boxed.err   |  3 ++-
 tests/qapi-schema/oob-test.err |  3 ++-
 tests/qapi-schema/type-bypass-bad-gen.err  |  3 ++-
 5 files changed, 20 insertions(+), 14 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 8f96974f85..4f67b73684 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -915,16 +915,17 @@ def check_keys(expr, info, meta, required, optional=[]):
 required = required + [meta]
 source = "%s '%s'" % (meta, name)
 check_known_keys(expr, info, source, required, optional)
-for (key, value) in expr.items():
-if key in ['gen', 'success-response'] and value is not False:
-raise QAPISemError(info,
-   "'%s' of %s '%s' should only use false value"
-   % (key, meta, name))
-if (key in ['boxed', 'allow-oob', 'allow-preconfig']
-and value is not True):
-raise QAPISemError(info,
-   "'%s' of %s '%s' should only use true value"
-   % (key, meta, name))
+
+
+def check_flags(expr, info):
+for key in ['gen', 'success-response']:
+if key in expr and expr[key] is not False:
+raise QAPISemError(
+info, "flag '%s' may only use false value" % key)
+for key in ['boxed', 'allow-oob', 'allow-preconfig']:
+if key in expr and expr[key] is not True:
+raise QAPISemError(
+info, "flag '%s' may only use true value" % key)
 
 
 def normalize_enum(expr):
@@ -1027,6 +1028,7 @@ def check_exprs(exprs):
 assert False, 'unexpected meta type'
 
 check_if(expr, info)
+check_flags(expr, info)
 
 if doc:
 doc.check_expr(expr)
diff --git a/tests/qapi-schema/allow-preconfig-test.err 
b/tests/qapi-schema/allow-preconfig-test.err
index 700d583306..2a4e6ce663 100644
--- a/tests/qapi-schema/allow-preconfig-test.err
+++ b/tests/qapi-schema/allow-preconfig-test.err
@@ -1 +1,2 @@
-tests/qapi-schema/allow-preconfig-test.json:2: 'allow-preconfig' of command 
'allow-preconfig-test' should only use true value
+tests/qapi-schema/allow-preconfig-test.json: In command 'allow-preconfig-test':
+tests/qapi-schema/allow-preconfig-test.json:2: flag 'allow-preconfig' may only 
use true value
diff --git a/tests/qapi-schema/args-bad-boxed.err 
b/tests/qapi-schema/args-bad-boxed.err
index ad0d417321..31d39038fc 100644
--- a/tests/qapi-schema/args-bad-boxed.err
+++ b/tests/qapi-schema/args-bad-boxed.err
@@ -1 +1,2 @@
-tests/qapi-schema/args-bad-boxed.json:2: 'boxed' of command 'foo' should only 
use true value
+tests/qapi-schema/args-bad-boxed.json: In command 'foo':
+tests/qapi-schema/args-bad-boxed.json:2: flag 'boxed' may only use true value
diff --git a/tests/qapi-schema/oob-test.err b/tests/qapi-schema/oob-test.err
index 35b60f7480..3c2ba6e0fd 100644
--- a/tests/qapi-schema/oob-test.err
+++ b/tests/qapi-schema/oob-test.err
@@ -1 +1,2 @@
-tests/qapi-schema/oob-test.json:2: 'allow-oob' of command 'oob-command-1' 
should only use true value
+tests/qapi-schema/oob-test.json: In command 'oob-command-1':
+tests/qapi-schema/oob-test.json:2: flag 'allow-oob' may only use true value
diff --git a/tests/qapi-schema/type-bypass-bad-gen.err 
b/tests/qapi-schema/type-bypass-bad-gen.err
index a83c3c655d..1077651896 100644
--- a/tests/qapi-schema/type-bypass-bad-gen.err
+++ b/tests/qapi-schema/type-bypass-bad-gen.err
@@ -1 +1,2 @@
-tests/qapi-schema/type-bypass-bad-gen.json:2: 'gen' of command 'foo' should 
only use false value
+tests/qapi-schema/type-bypass-bad-gen.json: In command 'foo':
+tests/qapi-schema/type-bypass-bad-gen.json:2: flag 'gen' may only use false 
value
-- 
2.21.0




[PULL 00/27] QAPI patches for 2019-09-28

2019-09-28 Thread Markus Armbruster
The following changes since commit c6f5012ba5fa834cbd5274b1b8369e2c5d2f5933:

  Merge remote-tracking branch 
'remotes/stsquad/tags/pull-testing-next-260919-1' into staging (2019-09-27 
15:43:41 +0100)

are available in the Git repository at:

  git://repo.or.cz/qemu/armbru.git tags/pull-qapi-2019-09-28

for you to fetch changes up to c615550df306a7b16e75d21f65ee38898c756bac:

  qapi: Improve source file read error handling (2019-09-28 17:17:48 +0200)


QAPI patches for 2019-09-28


Markus Armbruster (26):
  qapi: Tighten QAPISchemaFOO.check() assertions
  qapi: Rename .owner to .defined_in
  qapi: New QAPISourceInfo, replacing dict
  qapi: Prefix frontend errors with an "in definition" line
  qapi: Clean up member name case checking
  qapi: Change frontend error messages to start with lower case
  qapi: Improve reporting of member name clashes
  qapi: Reorder check_FOO() parameters for consistency
  qapi: Improve reporting of invalid name errors
  qapi: Use check_name_str() where it suffices
  qapi: Report invalid '*' prefix like any other invalid name
  qapi: Move check for reserved names out of add_name()
  qapi: Make check_type()'s array case a bit more obvious
  qapi: Plumb info to the QAPISchemaMember
  qapi: Inline check_name() into check_union()
  qapi: Move context-sensitive checking to the proper place
  qapi: Move context-free checking to the proper place
  qapi: Improve reporting of invalid 'if' errors
  qapi: Improve reporting of invalid flags
  qapi: Improve reporting of missing / unknown definition keys
  qapi: Avoid redundant definition references in error messages
  qapi: Improve reporting of invalid 'if' further
  qapi: Eliminate check_keys(), rename check_known_keys()
  qapi: Improve reporting of missing documentation comment
  qapi: Improve reporting of redefinition
  qapi: Improve source file read error handling

Michal Privoznik (1):
  qmp-dispatch: Use CommandNotFound error for disabled commands

 qapi/qapi-schema.json  |2 +-
 qapi/qmp-dispatch.c|5 +-
 tests/test-qga.c   |4 +-
 scripts/qapi/common.py | 1052 ++--
 scripts/qapi/events.py |2 +-
 tests/qapi-schema/allow-preconfig-test.err |3 +-
 tests/qapi-schema/alternate-any.err|3 +-
 tests/qapi-schema/alternate-array.err  |3 +-
 tests/qapi-schema/alternate-base.err   |3 +-
 tests/qapi-schema/alternate-branch-if-invalid.err  |3 +-
 tests/qapi-schema/alternate-clash.err  |3 +-
 .../qapi-schema/alternate-conflict-bool-string.err |3 +-
 tests/qapi-schema/alternate-conflict-dict.err  |3 +-
 tests/qapi-schema/alternate-conflict-enum-bool.err |3 +-
 tests/qapi-schema/alternate-conflict-enum-int.err  |3 +-
 .../qapi-schema/alternate-conflict-num-string.err  |3 +-
 tests/qapi-schema/alternate-conflict-string.err|3 +-
 tests/qapi-schema/alternate-empty.err  |3 +-
 tests/qapi-schema/alternate-invalid-dict.err   |3 +-
 tests/qapi-schema/alternate-nested.err |3 +-
 tests/qapi-schema/alternate-unknown.err|3 +-
 tests/qapi-schema/args-alternate.err   |3 +-
 tests/qapi-schema/args-any.err |3 +-
 tests/qapi-schema/args-array-empty.err |3 +-
 tests/qapi-schema/args-array-unknown.err   |3 +-
 tests/qapi-schema/args-bad-boxed.err   |3 +-
 tests/qapi-schema/args-boxed-anon.err  |3 +-
 tests/qapi-schema/args-boxed-string.err|3 +-
 tests/qapi-schema/args-int.err |3 +-
 tests/qapi-schema/args-invalid.err |3 +-
 tests/qapi-schema/args-member-array-bad.err|3 +-
 tests/qapi-schema/args-member-case.err |3 +-
 tests/qapi-schema/args-member-case.json|2 +-
 tests/qapi-schema/args-member-unknown.err  |3 +-
 tests/qapi-schema/args-name-clash.err  |3 +-
 tests/qapi-schema/args-union.err   |3 +-
 tests/qapi-schema/args-unknown.err |3 +-
 tests/qapi-schema/bad-base.err |3 +-
 tests/qapi-schema/bad-data.err |3 +-
 tests/qapi-schema/bad-ident.err|3 +-
 tests/qapi-schema/bad-if-empty-list.err|3 +-
 tests/qapi-schema/bad-if-empty.err |3 +-
 tests/qapi-schema/bad-if-list.err  |3 +-
 tests/qapi-schema/bad-if.err   |3 +-
 tests/qapi-schema/bad-type-bool.err|2 +-
 t

[PULL 16/27] qapi: Inline check_name() into check_union()

2019-09-28 Thread Markus Armbruster
check_name() consists of check_name_is_str() and check_name_str().
check_union() relies on the latter to catch optional discriminators.
The next commit will replace that by a more straightforward check.
Inlining check_name() into check_union() now should make that easier
to review.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20190927134639.4284-16-arm...@redhat.com>
---
 scripts/qapi/common.py | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 88945804dc..9acff01d3e 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -897,8 +897,10 @@ def check_union(expr, info):
 
 # The value of member 'discriminator' must name a non-optional
 # member of the base struct.
-check_name(discriminator, info,
-   "discriminator of flat union '%s'" % name)
+check_name_is_str(discriminator, info,
+  "discriminator of flat union '%s'" % name)
+check_name_str(discriminator, info,
+   "discriminator of flat union '%s'" % name)
 discriminator_value = base_members.get(discriminator)
 if not discriminator_value:
 raise QAPISemError(info,
-- 
2.21.0




[PULL 19/27] qapi: Improve reporting of invalid 'if' errors

2019-09-28 Thread Markus Armbruster
Move check_if() from check_keys() to check_exprs() and call it later,
so its error messages gain an "in definition" line.

Checking values in a function named check_keys() is unclean anyway.
The original sin was commit 0545f6b887 "qapi: Better error messages
for bad expressions", which checks the value of key 'name'.  More
sinning in commit 2cbf09925a "qapi: More rigorous checking for type
safety bypass", commit c818408e44 "qapi: Implement boxed types for
commands/events", and commit 967c885108 "qapi: add 'if' to top-level
expressions".  This commit does penance for the latter.  The next
commits will do penance for the others.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20190927134639.4284-19-arm...@redhat.com>
---
 scripts/qapi/common.py  | 4 ++--
 tests/qapi-schema/bad-if-empty-list.err | 1 +
 tests/qapi-schema/bad-if-empty.err  | 1 +
 tests/qapi-schema/bad-if-list.err   | 1 +
 tests/qapi-schema/bad-if.err| 1 +
 5 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 2e1d8158d6..8f96974f85 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -925,8 +925,6 @@ def check_keys(expr, info, meta, required, optional=[]):
 raise QAPISemError(info,
"'%s' of %s '%s' should only use true value"
% (key, meta, name))
-if key == 'if':
-check_if(expr, info)
 
 
 def normalize_enum(expr):
@@ -1028,6 +1026,8 @@ def check_exprs(exprs):
 else:
 assert False, 'unexpected meta type'
 
+check_if(expr, info)
+
 if doc:
 doc.check_expr(expr)
 
diff --git a/tests/qapi-schema/bad-if-empty-list.err 
b/tests/qapi-schema/bad-if-empty-list.err
index 75fe6497bc..2218c9279b 100644
--- a/tests/qapi-schema/bad-if-empty-list.err
+++ b/tests/qapi-schema/bad-if-empty-list.err
@@ -1 +1,2 @@
+tests/qapi-schema/bad-if-empty-list.json: In struct 'TestIfStruct':
 tests/qapi-schema/bad-if-empty-list.json:2: 'if' condition [] is useless
diff --git a/tests/qapi-schema/bad-if-empty.err 
b/tests/qapi-schema/bad-if-empty.err
index 358bdc3e51..a3fdb3009d 100644
--- a/tests/qapi-schema/bad-if-empty.err
+++ b/tests/qapi-schema/bad-if-empty.err
@@ -1 +1,2 @@
+tests/qapi-schema/bad-if-empty.json: In struct 'TestIfStruct':
 tests/qapi-schema/bad-if-empty.json:2: 'if' condition '' makes no sense
diff --git a/tests/qapi-schema/bad-if-list.err 
b/tests/qapi-schema/bad-if-list.err
index 53af099083..e03bf0fc3a 100644
--- a/tests/qapi-schema/bad-if-list.err
+++ b/tests/qapi-schema/bad-if-list.err
@@ -1 +1,2 @@
+tests/qapi-schema/bad-if-list.json: In struct 'TestIfStruct':
 tests/qapi-schema/bad-if-list.json:2: 'if' condition ' ' makes no sense
diff --git a/tests/qapi-schema/bad-if.err b/tests/qapi-schema/bad-if.err
index c2e3f5f44c..190216c109 100644
--- a/tests/qapi-schema/bad-if.err
+++ b/tests/qapi-schema/bad-if.err
@@ -1 +1,2 @@
+tests/qapi-schema/bad-if.json: In struct 'TestIfStruct':
 tests/qapi-schema/bad-if.json:2: 'if' condition must be a string or a list of 
strings
-- 
2.21.0




[PULL 13/27] qapi: Move check for reserved names out of add_name()

2019-09-28 Thread Markus Armbruster
The checks for reserved names are spread far and wide.  Move one from
add_name() to new check_defn_name_str().  This is a first step towards
collecting them all in dedicated name checking functions next to
check_name().

While there, drop the quotes around the meta-type in
check_name_str()'s error messages: "'command' uses ... name 'NAME'"
becomes "command uses ... name 'NAME'".

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20190927134639.4284-13-arm...@redhat.com>
---
 scripts/qapi/common.py   | 16 ++--
 tests/qapi-schema/bad-ident.err  |  2 +-
 tests/qapi-schema/reserved-command-q.err |  2 +-
 3 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index a4cf41f13e..111a4bbe55 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -741,6 +741,13 @@ def check_name_str(name, info, source,
 assert not membername.startswith('*')
 
 
+def check_defn_name_str(name, info, meta):
+check_name_str(name, info, meta, permit_upper=True)
+if name.endswith('Kind') or name.endswith('List'):
+raise QAPISemError(
+info, "%s '%s' should not end in '%s'" % (meta, name, name[-4:]))
+
+
 def add_name(name, info, meta):
 global all_names
 # FIXME should reject names that differ only in '_' vs. '.'
@@ -748,9 +755,6 @@ def add_name(name, info, meta):
 if name in all_names:
 raise QAPISemError(info, "%s '%s' is already defined"
% (all_names[name], name))
-if name.endswith('Kind') or name.endswith('List'):
-raise QAPISemError(info, "%s '%s' should not end in '%s'"
-   % (meta, name, name[-4:]))
 all_names[name] = meta
 
 
@@ -1162,7 +1166,7 @@ def check_exprs(exprs):
 name = expr[meta]
 check_name_is_str(name, info, "'%s'" % meta)
 info.set_defn(meta, name)
-check_name_str(name, info, "'%s'" % meta, permit_upper=True)
+check_defn_name_str(name, info, meta)
 add_name(name, info, meta)
 if doc and doc.symbol != name:
 raise QAPISemError(
@@ -1889,13 +1893,13 @@ class QAPISchema(object):
 
 def _make_implicit_enum_type(self, name, info, ifcond, values):
 # See also QAPISchemaObjectTypeMember.describe()
-name = name + 'Kind'   # Use namespace reserved by add_name()
+name = name + 'Kind'# reserved by check_defn_name_str()
 self._def_entity(QAPISchemaEnumType(
 name, info, None, ifcond, self._make_enum_members(values), None))
 return name
 
 def _make_array_type(self, element_type, info):
-name = element_type + 'List'   # Use namespace reserved by add_name()
+name = element_type + 'List'# reserved by check_defn_name_str()
 if not self.lookup_type(name):
 self._def_entity(QAPISchemaArrayType(name, info, element_type))
 return name
diff --git a/tests/qapi-schema/bad-ident.err b/tests/qapi-schema/bad-ident.err
index ddc96bd3a9..79d14758ce 100644
--- a/tests/qapi-schema/bad-ident.err
+++ b/tests/qapi-schema/bad-ident.err
@@ -1,2 +1,2 @@
 tests/qapi-schema/bad-ident.json: In struct '*oops':
-tests/qapi-schema/bad-ident.json:2: 'struct' uses invalid name '*oops'
+tests/qapi-schema/bad-ident.json:2: struct uses invalid name '*oops'
diff --git a/tests/qapi-schema/reserved-command-q.err 
b/tests/qapi-schema/reserved-command-q.err
index 0844e14b26..631cb5cdcc 100644
--- a/tests/qapi-schema/reserved-command-q.err
+++ b/tests/qapi-schema/reserved-command-q.err
@@ -1,2 +1,2 @@
 tests/qapi-schema/reserved-command-q.json: In command 'q-unix':
-tests/qapi-schema/reserved-command-q.json:5: 'command' uses invalid name 
'q-unix'
+tests/qapi-schema/reserved-command-q.json:5: command uses invalid name 'q-unix'
-- 
2.21.0




[PULL 11/27] qapi: Use check_name_str() where it suffices

2019-09-28 Thread Markus Armbruster
Replace check_name() by check_name_str() where the name is known to be
a string.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20190927134639.4284-11-arm...@redhat.com>
---
 scripts/qapi/common.py | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 6f35cd131e..d0d997f31c 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -816,8 +816,8 @@ def check_type(value, info, source,
 
 # value is a dictionary, check that each member is okay
 for (key, arg) in value.items():
-check_name(key, info, "member of %s" % source,
-   allow_optional=True, permit_upper=permit_upper)
+check_name_str(key, info, "member of %s" % source,
+   allow_optional=True, permit_upper=permit_upper)
 if c_name(key, False) == 'u' or c_name(key, False).startswith('has_'):
 raise QAPISemError(
 info, "member of %s uses reserved name '%s'" % (source, key))
@@ -920,8 +920,7 @@ def check_union(expr, info):
 raise QAPISemError(info, "union '%s' has no branches" % name)
 
 for (key, value) in members.items():
-check_name(key, info, "member of union '%s'" % name)
-
+check_name_str(key, info, "member of union '%s'" % name)
 check_known_keys(value, info,
  "member '%s' of union '%s'" % (key, name),
  ['type'], ['if'])
@@ -951,7 +950,7 @@ def check_alternate(expr, info):
 raise QAPISemError(info,
"alternate '%s' cannot have empty 'data'" % name)
 for (key, value) in members.items():
-check_name(key, info, "member of alternate '%s'" % name)
+check_name_str(key, info, "member of alternate '%s'" % name)
 check_known_keys(value, info,
  "member '%s' of alternate '%s'" % (key, name),
  ['type'], ['if'])
-- 
2.21.0




[PULL 25/27] qapi: Improve reporting of missing documentation comment

2019-09-28 Thread Markus Armbruster
Have check_exprs() check this later, so the error message gains an "in
definition line".  Tweak the error message.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20190927134639.4284-25-arm...@redhat.com>
---
 scripts/qapi/common.py| 18 --
 tests/qapi-schema/doc-missing.err |  3 ++-
 2 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index fa354b3f1e..bd834270f8 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -933,10 +933,6 @@ def check_exprs(exprs):
 if 'include' in expr:
 continue
 
-if not doc and doc_required:
-raise QAPISemError(info,
-   "definition missing documentation comment")
-
 if 'enum' in expr:
 meta = 'enum'
 elif 'union' in expr:
@@ -957,9 +953,14 @@ def check_exprs(exprs):
 info.set_defn(meta, name)
 check_defn_name_str(name, info, meta)
 
-if doc and doc.symbol != name:
-raise QAPISemError(
-info, "documentation comment is for '%s'" % doc.symbol)
+if doc:
+if doc.symbol != name:
+raise QAPISemError(
+info, "documentation comment is for '%s'" % doc.symbol)
+doc.check_expr(expr)
+elif doc_required:
+raise QAPISemError(info,
+   "documentation comment required")
 
 if meta == 'enum':
 check_keys(expr, info, meta,
@@ -1004,9 +1005,6 @@ def check_exprs(exprs):
 check_if(expr, info, meta)
 check_flags(expr, info)
 
-if doc:
-doc.check_expr(expr)
-
 return exprs
 
 
diff --git a/tests/qapi-schema/doc-missing.err 
b/tests/qapi-schema/doc-missing.err
index 08c827931a..7fbf54ff65 100644
--- a/tests/qapi-schema/doc-missing.err
+++ b/tests/qapi-schema/doc-missing.err
@@ -1 +1,2 @@
-tests/qapi-schema/doc-missing.json:5: definition missing documentation comment
+tests/qapi-schema/doc-missing.json: In command 'undocumented':
+tests/qapi-schema/doc-missing.json:5: documentation comment required
-- 
2.21.0




[PULL 06/27] qapi: Clean up member name case checking

2019-09-28 Thread Markus Armbruster
QAPISchemaMember.check_clash() checks for member names that map to the
same c_name().  Takes care of rejecting duplicate names.

It also checks a naming rule: no uppercase in member names.  That's a
rather odd place to do it.  Enforcing naming rules is
check_name_str()'s job.

qapi-code-gen.txt specifies the name case rule applies to the name as
it appears in the schema.  check_clash() checks c_name(name) instead.
No difference, as c_name() leaves alone case, but unclean.

Move the name case check into check_name_str(), less the c_name().
New argument @permit_upper suppresses it.  Pass permit_upper=True for
definitions (which are not members), and when the member's owner is
whitelisted with pragma name-case-whitelist.

Bonus: name-case-whitelist now applies to a union's inline base, too.
Update qapi/qapi-schema.json pragma to whitelist union CpuInfo instead
of CpuInfo's implicit base type's name q_obj_CpuInfo-base.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20190927134639.4284-6-arm...@redhat.com>
---
 qapi/qapi-schema.json|  2 +-
 scripts/qapi/common.py   | 25 +---
 tests/qapi-schema/args-member-case.err   |  2 +-
 tests/qapi-schema/args-member-case.json  |  2 +-
 tests/qapi-schema/enum-member-case.err   |  2 +-
 tests/qapi-schema/union-branch-case.err  |  4 ++--
 tests/qapi-schema/union-branch-case.json |  4 ++--
 7 files changed, 22 insertions(+), 19 deletions(-)

diff --git a/qapi/qapi-schema.json b/qapi/qapi-schema.json
index 920b03b0aa..9751b11f8f 100644
--- a/qapi/qapi-schema.json
+++ b/qapi/qapi-schema.json
@@ -71,7 +71,7 @@
 'QapiErrorClass',   # all members, visible through errors
 'UuidInfo', # UUID, visible through query-uuid
 'X86CPURegister32', # all members, visible indirectly through 
qom-get
-'q_obj_CpuInfo-base'# CPU, visible through query-cpu
+'CpuInfo'   # CPU, visible through query-cpu
 ] } }
 
 # Documentation generated with qapi-gen.py is in source order, with
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index f0e7d5ad34..ed4bff4479 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -704,8 +704,8 @@ valid_name = re.compile(r'^(__[a-zA-Z0-9.-]+_)?'
 '[a-zA-Z][a-zA-Z0-9_-]*$')
 
 
-def check_name(info, source, name, allow_optional=False,
-   enum_member=False):
+def check_name(info, source, name,
+   allow_optional=False, enum_member=False, permit_upper=False):
 global valid_name
 membername = name
 
@@ -725,11 +725,14 @@ def check_name(info, source, name, allow_optional=False,
 if not valid_name.match(membername) or \
c_name(membername, False).startswith('q_'):
 raise QAPISemError(info, "%s uses invalid name '%s'" % (source, name))
+if not permit_upper and name.lower() != name:
+raise QAPISemError(
+info, "%s uses uppercase in name '%s'" % (source, name))
 
 
 def add_name(name, info, meta):
 global all_names
-check_name(info, "'%s'" % meta, name)
+check_name(info, "'%s'" % meta, name, permit_upper=True)
 # FIXME should reject names that differ only in '_' vs. '.'
 # vs. '-', because they're liable to clash in generated C.
 if name in all_names:
@@ -797,10 +800,12 @@ def check_type(info, source, value,
 raise QAPISemError(info,
"%s should be an object or type name" % source)
 
+permit_upper = allow_dict in name_case_whitelist
+
 # value is a dictionary, check that each member is okay
 for (key, arg) in value.items():
 check_name(info, "Member of %s" % source, key,
-   allow_optional=True)
+   allow_optional=True, permit_upper=permit_upper)
 if c_name(key, False) == 'u' or c_name(key, False).startswith('has_'):
 raise QAPISemError(info, "Member of %s uses reserved name '%s'"
% (source, key))
@@ -870,7 +875,7 @@ def check_union(expr, info):
 else:
 # The object must have a string or dictionary 'base'.
 check_type(info, "'base' for union '%s'" % name,
-   base, allow_dict=True,
+   base, allow_dict=name,
allow_metas=['struct'])
 if not base:
 raise QAPISemError(info, "Flat union '%s' must have a base"
@@ -982,13 +987,15 @@ def check_enum(expr, info):
 raise QAPISemError(info,
"Enum '%s' requires a string for 'prefix'" % name)
 
+permit_upper = name in name_case_whitelist
+
 for member in members:
 check_known_keys(info, "member of enum '%s'" % name, member,
  ['name'], ['if'])
 check_if(member, info)
 normalize_if(member)
 check_name(info, "Member of enum '%s'" % name, member['name'],
-   enum_member=True)
+  

[PULL 15/27] qapi: Plumb info to the QAPISchemaMember

2019-09-28 Thread Markus Armbruster
Future commits will need info in the .check() methods of
QAPISchemaMember and its descendants.  Get it there.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20190927134639.4284-15-arm...@redhat.com>
---
 scripts/qapi/common.py | 76 +++---
 scripts/qapi/events.py |  2 +-
 2 files changed, 43 insertions(+), 35 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 870d8b0ecb..88945804dc 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -1574,9 +1574,10 @@ class QAPISchemaMember(object):
 """ Represents object members, enum members and features """
 role = 'member'
 
-def __init__(self, name, ifcond=None):
+def __init__(self, name, info, ifcond=None):
 assert isinstance(name, str)
 self.name = name
+self.info = info
 self.ifcond = ifcond or []
 self.defined_in = None
 
@@ -1633,8 +1634,8 @@ class QAPISchemaFeature(QAPISchemaMember):
 
 
 class QAPISchemaObjectTypeMember(QAPISchemaMember):
-def __init__(self, name, typ, optional, ifcond=None):
-QAPISchemaMember.__init__(self, name, ifcond)
+def __init__(self, name, info, typ, optional, ifcond=None):
+QAPISchemaMember.__init__(self, name, info, ifcond)
 assert isinstance(typ, str)
 assert isinstance(optional, bool)
 self._type_name = typ
@@ -1648,7 +1649,7 @@ class QAPISchemaObjectTypeMember(QAPISchemaMember):
 
 
 class QAPISchemaObjectTypeVariants(object):
-def __init__(self, tag_name, tag_member, variants):
+def __init__(self, tag_name, info, tag_member, variants):
 # Flat unions pass tag_name but not tag_member.
 # Simple unions and alternates pass tag_member but not tag_name.
 # After check(), tag_member is always set, and tag_name remains
@@ -1659,6 +1660,7 @@ class QAPISchemaObjectTypeVariants(object):
 for v in variants:
 assert isinstance(v, QAPISchemaObjectTypeVariant)
 self._tag_name = tag_name
+self.info = info
 self.tag_member = tag_member
 self.variants = variants
 
@@ -1678,8 +1680,8 @@ class QAPISchemaObjectTypeVariants(object):
 cases = set([v.name for v in self.variants])
 for m in self.tag_member.type.members:
 if m.name not in cases:
-v = QAPISchemaObjectTypeVariant(m.name, 'q_empty',
-m.ifcond)
+v = QAPISchemaObjectTypeVariant(m.name, self.info,
+'q_empty', m.ifcond)
 v.set_defined_in(self.tag_member.defined_in)
 self.variants.append(v)
 assert self.variants
@@ -1703,8 +1705,9 @@ class QAPISchemaObjectTypeVariants(object):
 class QAPISchemaObjectTypeVariant(QAPISchemaObjectTypeMember):
 role = 'branch'
 
-def __init__(self, name, typ, ifcond=None):
-QAPISchemaObjectTypeMember.__init__(self, name, typ, False, ifcond)
+def __init__(self, name, info, typ, ifcond=None):
+QAPISchemaObjectTypeMember.__init__(self, name, info, typ,
+False, ifcond)
 
 
 class QAPISchemaAlternateType(QAPISchemaType):
@@ -1880,23 +1883,26 @@ class QAPISchema(object):
 
 qtypes = ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist',
   'qbool']
-qtype_values = self._make_enum_members([{'name': n} for n in qtypes])
+qtype_values = self._make_enum_members(
+[{'name': n} for n in qtypes], None)
 
 self._def_entity(QAPISchemaEnumType('QType', None, None, None,
 qtype_values, 'QTYPE'))
 
-def _make_features(self, features):
-return [QAPISchemaFeature(f['name'], f.get('if')) for f in features]
+def _make_features(self, features, info):
+return [QAPISchemaFeature(f['name'], info, f.get('if'))
+for f in features]
 
-def _make_enum_members(self, values):
-return [QAPISchemaEnumMember(v['name'], v.get('if'))
+def _make_enum_members(self, values, info):
+return [QAPISchemaEnumMember(v['name'], info, v.get('if'))
 for v in values]
 
 def _make_implicit_enum_type(self, name, info, ifcond, values):
 # See also QAPISchemaObjectTypeMember.describe()
 name = name + 'Kind'# reserved by check_defn_name_str()
 self._def_entity(QAPISchemaEnumType(
-name, info, None, ifcond, self._make_enum_members(values), None))
+name, info, None, ifcond, self._make_enum_members(values, info),
+None))
 return name
 
 def _make_array_type(self, element_type, info):
@@ -1935,7 +1941,7 @@ class QAPISchema(object):
 ifcond = expr.get('if')
 self._def_entity(QAPISchemaEnumType(
 name, info, doc, ifcond,
-self._make_enum_mem

[PULL 12/27] qapi: Report invalid '*' prefix like any other invalid name

2019-09-28 Thread Markus Armbruster
The special "does not allow optional name" error is well meant, but
confusing in practice.  Drop it.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20190927134639.4284-12-arm...@redhat.com>
---
 scripts/qapi/common.py   | 6 ++
 tests/qapi-schema/bad-ident.err  | 2 +-
 tests/qapi-schema/flat-union-discriminator-bad-name.err  | 2 +-
 tests/qapi-schema/flat-union-discriminator-bad-name.json | 2 +-
 tests/qapi-schema/union-optional-branch.err  | 2 +-
 5 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index d0d997f31c..a4cf41f13e 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -724,11 +724,8 @@ def check_name_str(name, info, source,
 global valid_name
 membername = name
 
-if name.startswith('*'):
+if allow_optional and name.startswith('*'):
 membername = name[1:]
-if not allow_optional:
-raise QAPISemError(info, "%s does not allow optional name '%s'"
-   % (source, name))
 # Enum members can start with a digit, because the generated C
 # code always prefixes it with the enum name
 if enum_member and membername[0].isdigit():
@@ -741,6 +738,7 @@ def check_name_str(name, info, source,
 if not permit_upper and name.lower() != name:
 raise QAPISemError(
 info, "%s uses uppercase in name '%s'" % (source, name))
+assert not membername.startswith('*')
 
 
 def add_name(name, info, meta):
diff --git a/tests/qapi-schema/bad-ident.err b/tests/qapi-schema/bad-ident.err
index 6878889854..ddc96bd3a9 100644
--- a/tests/qapi-schema/bad-ident.err
+++ b/tests/qapi-schema/bad-ident.err
@@ -1,2 +1,2 @@
 tests/qapi-schema/bad-ident.json: In struct '*oops':
-tests/qapi-schema/bad-ident.json:2: 'struct' does not allow optional name 
'*oops'
+tests/qapi-schema/bad-ident.json:2: 'struct' uses invalid name '*oops'
diff --git a/tests/qapi-schema/flat-union-discriminator-bad-name.err 
b/tests/qapi-schema/flat-union-discriminator-bad-name.err
index f7f64c5c1a..44e41883b1 100644
--- a/tests/qapi-schema/flat-union-discriminator-bad-name.err
+++ b/tests/qapi-schema/flat-union-discriminator-bad-name.err
@@ -1,2 +1,2 @@
 tests/qapi-schema/flat-union-discriminator-bad-name.json: In union 'MyUnion':
-tests/qapi-schema/flat-union-discriminator-bad-name.json:7: discriminator of 
flat union 'MyUnion' does not allow optional name '*switch'
+tests/qapi-schema/flat-union-discriminator-bad-name.json:7: discriminator of 
flat union 'MyUnion' uses invalid name '*switch'
diff --git a/tests/qapi-schema/flat-union-discriminator-bad-name.json 
b/tests/qapi-schema/flat-union-discriminator-bad-name.json
index 66376084fc..ea84b75cac 100644
--- a/tests/qapi-schema/flat-union-discriminator-bad-name.json
+++ b/tests/qapi-schema/flat-union-discriminator-bad-name.json
@@ -1,5 +1,5 @@
 # discriminator '*switch' isn't a member of base, 'switch' is
-# reports "does not allow optional name", which is good enough
+# reports "uses invalid name", which is good enough
 { 'enum': 'Enum', 'data': [ 'one', 'two' ] }
 { 'struct': 'Base',
   'data': { '*switch': 'Enum' } }
diff --git a/tests/qapi-schema/union-optional-branch.err 
b/tests/qapi-schema/union-optional-branch.err
index a5677f74bc..8e9b18d7c6 100644
--- a/tests/qapi-schema/union-optional-branch.err
+++ b/tests/qapi-schema/union-optional-branch.err
@@ -1,2 +1,2 @@
 tests/qapi-schema/union-optional-branch.json: In union 'Union':
-tests/qapi-schema/union-optional-branch.json:2: member of union 'Union' does 
not allow optional name '*a'
+tests/qapi-schema/union-optional-branch.json:2: member of union 'Union' uses 
invalid name '*a'
-- 
2.21.0




[PULL 18/27] qapi: Move context-free checking to the proper place

2019-09-28 Thread Markus Armbruster
QAPISchemaCommand.check() and QAPISchemaEvent().check() check 'data'
is present when 'boxed': true.  That's context-free.  Move to
check_command() and check_event().

Tweak the error message while there.

check_exprs() & friends now check exactly what qapi-code-gen.txt calls
the second layer of syntax.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20190927134639.4284-18-arm...@redhat.com>
---
 scripts/qapi/common.py  | 16 
 tests/qapi-schema/event-boxed-empty.err |  2 +-
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index f22e84c4a8..2e1d8158d6 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -768,10 +768,12 @@ def check_type(value, info, source,
 
 def check_command(expr, info):
 name = expr['command']
+args = expr.get('data')
 boxed = expr.get('boxed', False)
 
-check_type(expr.get('data'), info,
-   "'data' for command '%s'" % name,
+if boxed and args is None:
+raise QAPISemError(info, "'boxed': true requires 'data'")
+check_type(args, info, "'data' for command '%s'" % name,
allow_dict=not boxed)
 check_type(expr.get('returns'), info,
"'returns' for command '%s'" % name,
@@ -780,10 +782,12 @@ def check_command(expr, info):
 
 def check_event(expr, info):
 name = expr['event']
+args = expr.get('data')
 boxed = expr.get('boxed', False)
 
-check_type(expr.get('data'), info,
-   "'data' for event '%s'" % name,
+if boxed and args is None:
+raise QAPISemError(info, "'boxed': true requires 'data'")
+check_type(args, info, "'data' for event '%s'" % name,
allow_dict=not boxed)
 
 
@@ -1699,8 +1703,6 @@ class QAPISchemaCommand(QAPISchemaEntity):
 self.info,
 "command's 'data' can take %s only with 'boxed': true"
 % self.arg_type.describe())
-elif self.boxed:
-raise QAPISemError(self.info, "use of 'boxed' requires 'data'")
 if self._ret_type_name:
 self.ret_type = schema.resolve_type(
 self._ret_type_name, self.info, "command's 'returns'")
@@ -1748,8 +1750,6 @@ class QAPISchemaEvent(QAPISchemaEntity):
 self.info,
 "event's 'data' can take %s only with 'boxed': true"
 % self.arg_type.describe())
-elif self.boxed:
-raise QAPISemError(self.info, "use of 'boxed' requires 'data'")
 
 def visit(self, visitor):
 QAPISchemaEntity.visit(self, visitor)
diff --git a/tests/qapi-schema/event-boxed-empty.err 
b/tests/qapi-schema/event-boxed-empty.err
index 9c691b7d97..931c10b036 100644
--- a/tests/qapi-schema/event-boxed-empty.err
+++ b/tests/qapi-schema/event-boxed-empty.err
@@ -1,2 +1,2 @@
 tests/qapi-schema/event-boxed-empty.json: In event 'FOO':
-tests/qapi-schema/event-boxed-empty.json:2: use of 'boxed' requires 'data'
+tests/qapi-schema/event-boxed-empty.json:2: 'boxed': true requires 'data'
-- 
2.21.0




[PULL 09/27] qapi: Reorder check_FOO() parameters for consistency

2019-09-28 Thread Markus Armbruster
Most check_FOO() take the thing being checked as first argument.
check_name(), check_type(), check_known_keys() don't.  Clean that up.

While there, drop a "Todo" comment that should have been dropped in
commit 87adbbffd4 "qapi: add a dictionary form for TYPE".

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20190927134639.4284-9-arm...@redhat.com>
---
 scripts/qapi/common.py | 80 --
 1 file changed, 39 insertions(+), 41 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 14d1e34c2c..c909821560 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -706,7 +706,7 @@ valid_name = re.compile(r'^(__[a-zA-Z0-9.-]+_)?'
 '[a-zA-Z][a-zA-Z0-9_-]*$')
 
 
-def check_name(info, source, name,
+def check_name(name, info, source,
allow_optional=False, enum_member=False, permit_upper=False):
 global valid_name
 membername = name
@@ -734,7 +734,7 @@ def check_name(info, source, name,
 
 def add_name(name, info, meta):
 global all_names
-check_name(info, "'%s'" % meta, name, permit_upper=True)
+check_name(name, info, "'%s'" % meta, permit_upper=True)
 # FIXME should reject names that differ only in '_' vs. '.'
 # vs. '-', because they're liable to clash in generated C.
 if name in all_names:
@@ -768,7 +768,7 @@ def check_if(expr, info):
 check_if_str(ifcond, info)
 
 
-def check_type(info, source, value,
+def check_type(value, info, source,
allow_array=False, allow_dict=False, allow_metas=[]):
 global all_names
 
@@ -806,19 +806,17 @@ def check_type(info, source, value,
 
 # value is a dictionary, check that each member is okay
 for (key, arg) in value.items():
-check_name(info, "member of %s" % source, key,
+check_name(key, info, "member of %s" % source,
allow_optional=True, permit_upper=permit_upper)
 if c_name(key, False) == 'u' or c_name(key, False).startswith('has_'):
 raise QAPISemError(
 info, "member of %s uses reserved name '%s'" % (source, key))
-# Todo: allow dictionaries to represent default values of
-# an optional argument.
-check_known_keys(info, "member '%s' of %s" % (key, source),
- arg, ['type'], ['if'])
+check_known_keys(arg, info, "member '%s' of %s" % (key, source),
+ ['type'], ['if'])
 check_if(arg, info)
 normalize_if(arg)
-check_type(info, "member '%s' of %s" % (key, source),
-   arg['type'], allow_array=True,
+check_type(arg['type'], info, "member '%s' of %s" % (key, source),
+   allow_array=True,
allow_metas=['built-in', 'union', 'alternate', 'struct',
 'enum'])
 
@@ -830,15 +828,15 @@ def check_command(expr, info):
 args_meta = ['struct']
 if boxed:
 args_meta += ['union']
-check_type(info, "'data' for command '%s'" % name,
-   expr.get('data'), allow_dict=not boxed,
-   allow_metas=args_meta)
+check_type(expr.get('data'), info,
+   "'data' for command '%s'" % name,
+   allow_dict=not boxed, allow_metas=args_meta)
 returns_meta = ['union', 'struct']
 if name in returns_whitelist:
 returns_meta += ['built-in', 'alternate', 'enum']
-check_type(info, "'returns' for command '%s'" % name,
-   expr.get('returns'), allow_array=True,
-   allow_metas=returns_meta)
+check_type(expr.get('returns'), info,
+   "'returns' for command '%s'" % name,
+   allow_array=True, allow_metas=returns_meta)
 
 
 def check_event(expr, info):
@@ -848,9 +846,9 @@ def check_event(expr, info):
 meta = ['struct']
 if boxed:
 meta += ['union']
-check_type(info, "'data' for event '%s'" % name,
-   expr.get('data'), allow_dict=not boxed,
-   allow_metas=meta)
+check_type(expr.get('data'), info,
+   "'data' for event '%s'" % name,
+   allow_dict=not boxed, allow_metas=meta)
 
 
 def enum_get_names(expr):
@@ -876,9 +874,8 @@ def check_union(expr, info):
 # Else, it's a flat union.
 else:
 # The object must have a string or dictionary 'base'.
-check_type(info, "'base' for union '%s'" % name,
-   base, allow_dict=name,
-   allow_metas=['struct'])
+check_type(base, info, "'base' for union '%s'" % name,
+   allow_dict=name, allow_metas=['struct'])
 if not base:
 raise QAPISemError(
 info, "flat union '%s' must have a base" % name)
@@ -887,8 +884,8 @@ def check_union(expr, info):
 
 # The value of member 'discriminator' must name a non-optional
 # member of the base struct.
-check_name(info, "discriminator of flat un

[PULL 23/27] qapi: Improve reporting of invalid 'if' further

2019-09-28 Thread Markus Armbruster
check_if()'s errors don't point to the offending part of the
expression.  For instance:

tests/qapi-schema/alternate-branch-if-invalid.json:2: 'if' condition ' ' 
makes no sense

Other check_FOO() do, with the help of a @source argument.  Make
check_if() do that, too.  The example above improves to:

tests/qapi-schema/alternate-branch-if-invalid.json:2: 'if' condition ' ' of 
'data' member 'branch' makes no sense

Signed-off-by: Markus Armbruster 
Message-Id: <20190927134639.4284-23-arm...@redhat.com>
Reviewed-by: Eric Blake 
---
 scripts/qapi/common.py| 27 +++
 .../alternate-branch-if-invalid.err   |  2 +-
 tests/qapi-schema/bad-if-empty-list.err   |  2 +-
 tests/qapi-schema/bad-if-empty.err|  2 +-
 tests/qapi-schema/bad-if-list.err |  2 +-
 tests/qapi-schema/bad-if.err  |  2 +-
 tests/qapi-schema/enum-if-invalid.err |  2 +-
 tests/qapi-schema/features-if-invalid.err |  2 +-
 .../qapi-schema/struct-member-if-invalid.err  |  2 +-
 tests/qapi-schema/union-branch-if-invalid.err |  2 +-
 10 files changed, 25 insertions(+), 20 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 81c217cd60..4bc8c807aa 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -692,22 +692,27 @@ def check_defn_name_str(name, info, meta):
 info, "%s name should not end in '%s'" % (meta, name[-4:]))
 
 
-def check_if(expr, info):
+def check_if(expr, info, source):
 
 def check_if_str(ifcond, info):
 if not isinstance(ifcond, str):
 raise QAPISemError(
-info, "'if' condition must be a string or a list of strings")
+info,
+"'if' condition of %s must be a string or a list of strings"
+% source)
 if ifcond.strip() == '':
-raise QAPISemError(info, "'if' condition '%s' makes no sense"
-   % ifcond)
+raise QAPISemError(
+info,
+"'if' condition '%s' of %s makes no sense"
+% (ifcond, source))
 
 ifcond = expr.get('if')
 if ifcond is None:
 return
 if isinstance(ifcond, list):
 if ifcond == []:
-raise QAPISemError(info, "'if' condition [] is useless")
+raise QAPISemError(
+info, "'if' condition [] of %s is useless" % source)
 for elt in ifcond:
 check_if_str(elt, info)
 else:
@@ -752,7 +757,7 @@ def check_type(value, info, source,
 if c_name(key, False) == 'u' or c_name(key, False).startswith('has_'):
 raise QAPISemError(info, "%s uses reserved name" % key_source)
 check_known_keys(arg, info, key_source, ['type'], ['if'])
-check_if(arg, info)
+check_if(arg, info, key_source)
 normalize_if(arg)
 check_type(arg['type'], info, key_source, allow_array=True)
 
@@ -796,7 +801,7 @@ def check_union(expr, info):
 source = "'data' member '%s'" % key
 check_name_str(key, info, source)
 check_known_keys(value, info, source, ['type'], ['if'])
-check_if(value, info)
+check_if(value, info, source)
 normalize_if(value)
 check_type(value['type'], info, source, allow_array=not base)
 
@@ -810,7 +815,7 @@ def check_alternate(expr, info):
 source = "'data' member '%s'" % key
 check_name_str(key, info, source)
 check_known_keys(value, info, source, ['type'], ['if'])
-check_if(value, info)
+check_if(value, info, source)
 normalize_if(value)
 check_type(value['type'], info, source)
 
@@ -834,7 +839,7 @@ def check_enum(expr, info):
 source = "%s '%s'" % (source, member['name'])
 check_name_str(member['name'], info, source,
enum_member=True, permit_upper=permit_upper)
-check_if(member, info)
+check_if(member, info, source)
 normalize_if(member)
 
 
@@ -856,7 +861,7 @@ def check_struct(expr, info):
 check_name_is_str(f['name'], info, source)
 source = "%s '%s'" % (source, f['name'])
 check_name_str(f['name'], info, source)
-check_if(f, info)
+check_if(f, info, source)
 normalize_if(f)
 
 
@@ -994,7 +999,7 @@ def check_exprs(exprs):
 assert False, 'unexpected meta type'
 
 normalize_if(expr)
-check_if(expr, info)
+check_if(expr, info, meta)
 check_flags(expr, info)
 
 if doc:
diff --git a/tests/qapi-schema/alternate-branch-if-invalid.err 
b/tests/qapi-schema/alternate-branch-if-invalid.err
index 8684829aca..6c68e5a922 100644
--- a/tests/qapi-schema/alternate-branch-if-invalid.err
+++ b/tests/qapi-schema/alternate-branch-if-invalid.err
@@ -1,2 +1,2 @@
 tests/qapi-schema/alternate-branch-if-invalid.json: In alternate 'Alt':
-tests/qapi-schema/alternate-branch-if-invalid.json

[PULL 27/27] qapi: Improve source file read error handling

2019-09-28 Thread Markus Armbruster
qapi-gen.py crashes when it can't open the main schema file, and when
it can't read from any schema file.  Lazy.

Change QAPISchema.__init__() to take a file name instead of a file
object.  Move the open code from _include() to __init__(), so it's
used for the main schema file, too.

Move the read into the try for good measure, and rephrase the error
message.

Reporting open or read failure for the main schema file needs a
QAPISourceInfo representing "no source".  Make QAPISourceInfo cope
with fname=None.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20190927134639.4284-27-arm...@redhat.com>
---
 scripts/qapi/common.py| 46 +++
 tests/qapi-schema/include-no-file.err |  2 +-
 2 files changed, 27 insertions(+), 21 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index a74cd957d4..d6e00c80ea 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -53,7 +53,12 @@ class QAPISourceInfo(object):
 return info
 
 def loc(self):
-return '%s:%d' % (self.fname, self.line)
+if self.fname is None:
+return sys.argv[0]
+ret = self.fname
+if self.line is not None:
+ret += ':%d' % self.line
+return ret
 
 def in_defn(self):
 if self.defn_name:
@@ -383,14 +388,26 @@ class QAPIDoc(object):
 
 class QAPISchemaParser(object):
 
-def __init__(self, fp, previously_included=[], incl_info=None):
-self.fname = fp.name
-previously_included.append(os.path.abspath(fp.name))
-self.src = fp.read()
+def __init__(self, fname, previously_included=[], incl_info=None):
+previously_included.append(os.path.abspath(fname))
+
+try:
+if sys.version_info[0] >= 3:
+fp = open(fname, 'r', encoding='utf-8')
+else:
+fp = open(fname, 'r')
+self.src = fp.read()
+except IOError as e:
+raise QAPISemError(incl_info or QAPISourceInfo(None, None, None),
+   "can't read %s file '%s': %s"
+   % ("include" if incl_info else "schema",
+  fname,
+  e.strerror))
+
 if self.src == '' or self.src[-1] != '\n':
 self.src += '\n'
 self.cursor = 0
-self.info = QAPISourceInfo(self.fname, 1, incl_info)
+self.info = QAPISourceInfo(fname, 1, incl_info)
 self.line_pos = 0
 self.exprs = []
 self.docs = []
@@ -414,7 +431,7 @@ class QAPISchemaParser(object):
 if not isinstance(include, str):
 raise QAPISemError(info,
"value of 'include' must be a string")
-incl_fname = os.path.join(os.path.dirname(self.fname),
+incl_fname = os.path.join(os.path.dirname(fname),
   include)
 self.exprs.append({'expr': {'include': incl_fname},
'info': info})
@@ -466,14 +483,7 @@ class QAPISchemaParser(object):
 if incl_abs_fname in previously_included:
 return None
 
-try:
-if sys.version_info[0] >= 3:
-fobj = open(incl_fname, 'r', encoding='utf-8')
-else:
-fobj = open(incl_fname, 'r')
-except IOError as e:
-raise QAPISemError(info, "%s: %s" % (e.strerror, incl_fname))
-return QAPISchemaParser(fobj, previously_included, info)
+return QAPISchemaParser(incl_fname, previously_included, info)
 
 def _pragma(self, name, value, info):
 global doc_required, returns_whitelist, name_case_whitelist
@@ -1734,11 +1744,7 @@ class QAPISchemaEvent(QAPISchemaEntity):
 class QAPISchema(object):
 def __init__(self, fname):
 self.fname = fname
-if sys.version_info[0] >= 3:
-f = open(fname, 'r', encoding='utf-8')
-else:
-f = open(fname, 'r')
-parser = QAPISchemaParser(f)
+parser = QAPISchemaParser(fname)
 exprs = check_exprs(parser.exprs)
 self.docs = parser.docs
 self._entity_list = []
diff --git a/tests/qapi-schema/include-no-file.err 
b/tests/qapi-schema/include-no-file.err
index e42bcf4bc1..0a6c6bb4a9 100644
--- a/tests/qapi-schema/include-no-file.err
+++ b/tests/qapi-schema/include-no-file.err
@@ -1 +1 @@
-tests/qapi-schema/include-no-file.json:1: No such file or directory: 
tests/qapi-schema/include-no-file-sub.json
+tests/qapi-schema/include-no-file.json:1: can't read include file 
'tests/qapi-schema/include-no-file-sub.json': No such file or directory
-- 
2.21.0




[PULL 21/27] qapi: Improve reporting of missing / unknown definition keys

2019-09-28 Thread Markus Armbruster
Have check_exprs() call check_keys() later, so its error messages gain
an "in definition" line.

Both check_keys() and check_name_is_str() check the definition's name
is a string.  Since check_keys() now runs after check_name_is_str()
rather than before, its check is dead.  Bury it.  Checking values in
check_keys() is unclean anyway.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20190927134639.4284-21-arm...@redhat.com>
---
 scripts/qapi/common.py  | 40 -
 tests/qapi-schema/alternate-base.err|  1 +
 tests/qapi-schema/bad-type-bool.err |  2 +-
 tests/qapi-schema/bad-type-dict.err |  2 +-
 tests/qapi-schema/double-type.err   |  1 +
 tests/qapi-schema/enum-missing-data.err |  1 +
 tests/qapi-schema/unknown-expr-key.err  |  1 +
 7 files changed, 25 insertions(+), 23 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 4f67b73684..42b9c2e36b 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -910,8 +910,6 @@ def check_known_keys(value, info, source, required, 
optional):
 
 def check_keys(expr, info, meta, required, optional=[]):
 name = expr[meta]
-if not isinstance(name, str):
-raise QAPISemError(info, "'%s' key must have a string value" % meta)
 required = required + [meta]
 source = "%s '%s'" % (meta, name)
 check_known_keys(expr, info, source, required, optional)
@@ -969,37 +967,18 @@ def check_exprs(exprs):
 
 if 'enum' in expr:
 meta = 'enum'
-check_keys(expr, info, 'enum', ['data'], ['if', 'prefix'])
-normalize_enum(expr)
 elif 'union' in expr:
 meta = 'union'
-check_keys(expr, info, 'union', ['data'],
-   ['base', 'discriminator', 'if'])
-normalize_members(expr.get('base'))
-normalize_members(expr['data'])
 elif 'alternate' in expr:
 meta = 'alternate'
-check_keys(expr, info, 'alternate', ['data'], ['if'])
-normalize_members(expr['data'])
 elif 'struct' in expr:
 meta = 'struct'
-check_keys(expr, info, 'struct', ['data'],
-   ['base', 'if', 'features'])
-normalize_members(expr['data'])
-normalize_features(expr.get('features'))
 elif 'command' in expr:
 meta = 'command'
-check_keys(expr, info, 'command', [],
-   ['data', 'returns', 'gen', 'success-response',
-'boxed', 'allow-oob', 'allow-preconfig', 'if'])
-normalize_members(expr.get('data'))
 elif 'event' in expr:
 meta = 'event'
-check_keys(expr, info, 'event', [], ['data', 'boxed', 'if'])
-normalize_members(expr.get('data'))
 else:
 raise QAPISemError(info, "expression is missing metatype")
-normalize_if(expr)
 
 name = expr[meta]
 check_name_is_str(name, info, "'%s'" % meta)
@@ -1013,20 +992,39 @@ def check_exprs(exprs):
 % (name, doc.symbol))
 
 if meta == 'enum':
+check_keys(expr, info, 'enum', ['data'], ['if', 'prefix'])
+normalize_enum(expr)
 check_enum(expr, info)
 elif meta == 'union':
+check_keys(expr, info, 'union', ['data'],
+   ['base', 'discriminator', 'if'])
+normalize_members(expr.get('base'))
+normalize_members(expr['data'])
 check_union(expr, info)
 elif meta == 'alternate':
+check_keys(expr, info, 'alternate', ['data'], ['if'])
+normalize_members(expr['data'])
 check_alternate(expr, info)
 elif meta == 'struct':
+check_keys(expr, info, 'struct', ['data'],
+   ['base', 'if', 'features'])
+normalize_members(expr['data'])
+normalize_features(expr.get('features'))
 check_struct(expr, info)
 elif meta == 'command':
+check_keys(expr, info, 'command', [],
+   ['data', 'returns', 'gen', 'success-response',
+'boxed', 'allow-oob', 'allow-preconfig', 'if'])
+normalize_members(expr.get('data'))
 check_command(expr, info)
 elif meta == 'event':
+check_keys(expr, info, 'event', [], ['data', 'boxed', 'if'])
+normalize_members(expr.get('data'))
 check_event(expr, info)
 else:
 assert False, 'unexpected meta type'
 
+normalize_if(expr)
 check_if(expr, info)
 check_flags(expr, info)
 
diff --git a/tests/qapi-schema/alternate-base.err 
b/tests/qapi-schema/alternate-base.err
index 4c9158db02..6290665ac2 100644
--- a/tests/qapi-schema/alternate-base.err
+++ b/tests/qapi-schema/alternate-base.err
@@ -1,2 +1,3 @@
+tests/qapi-schema/alternate-base.json: In alternate 'Alt':

[PULL 08/27] qapi: Improve reporting of member name clashes

2019-09-28 Thread Markus Armbruster
We report name clashes like this:

struct-base-clash.json: In struct 'Sub':
struct-base-clash.json:5: 'name' (member of Sub) collides with 'name' 
(member of Base)

The "(member of Sub)" is redundant with "In struct 'Sub'".  Comes from
QAPISchemaMember.describe().  Pass info to it, so it can detect the
redundancy and avoid it.  Result:

struct-base-clash.json: In struct 'Sub':
struct-base-clash.json:5: member 'name' collides with member 'name' of type 
'Base'

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20190927134639.4284-8-arm...@redhat.com>
---
 scripts/qapi/common.py| 36 ---
 tests/qapi-schema/alternate-clash.err |  2 +-
 tests/qapi-schema/args-name-clash.err |  2 +-
 tests/qapi-schema/enum-clash-member.err   |  2 +-
 tests/qapi-schema/features-duplicate-name.err |  2 +-
 tests/qapi-schema/flat-union-bad-base.err |  2 +-
 tests/qapi-schema/flat-union-clash-member.err |  2 +-
 tests/qapi-schema/struct-base-clash-deep.err  |  2 +-
 tests/qapi-schema/struct-base-clash.err   |  2 +-
 tests/qapi-schema/union-clash-branches.err|  2 +-
 10 files changed, 32 insertions(+), 22 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 3d73332487..14d1e34c2c 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -1575,31 +1575,41 @@ class QAPISchemaMember(object):
 def check_clash(self, info, seen):
 cname = c_name(self.name)
 if cname in seen:
-raise QAPISemError(info, "%s collides with %s" %
-   (self.describe(), seen[cname].describe()))
+raise QAPISemError(
+info,
+"%s collides with %s"
+% (self.describe(info), seen[cname].describe(info)))
 seen[cname] = self
 
-def _pretty_defined_in(self):
+def describe(self, info):
+role = self.role
 defined_in = self.defined_in
+assert defined_in
+
 if defined_in.startswith('q_obj_'):
 # See QAPISchema._make_implicit_object_type() - reverse the
 # mapping there to create a nice human-readable description
 defined_in = defined_in[6:]
 if defined_in.endswith('-arg'):
-return '(parameter of %s)' % defined_in[:-4]
+# Implicit type created for a command's dict 'data'
+assert role == 'member'
+role = 'parameter'
 elif defined_in.endswith('-base'):
-return '(base of %s)' % defined_in[:-5]
+# Implicit type created for a flat union's dict 'base'
+role = 'base ' + role
 else:
+# Implicit type created for a simple union's branch
 assert defined_in.endswith('-wrapper')
 # Unreachable and not implemented
 assert False
-if defined_in.endswith('Kind'):
+elif defined_in.endswith('Kind'):
 # See QAPISchema._make_implicit_enum_type()
-return '(branch of %s)' % defined_in[:-4]
-return '(%s of %s)' % (self.role, defined_in)
-
-def describe(self):
-return "'%s' %s" % (self.name, self._pretty_defined_in())
+# Implicit enum created for simple union's branches
+assert role == 'value'
+role = 'branch'
+elif defined_in != info.defn_name:
+return "%s '%s' of type '%s'" % (role, self.name, defined_in)
+return "%s '%s'" % (role, self.name)
 
 
 class QAPISchemaEnumMember(QAPISchemaMember):
@@ -1871,7 +1881,7 @@ class QAPISchema(object):
 for v in values]
 
 def _make_implicit_enum_type(self, name, info, ifcond, values):
-# See also QAPISchemaObjectTypeMember._pretty_defined_in()
+# See also QAPISchemaObjectTypeMember.describe()
 name = name + 'Kind'   # Use namespace reserved by add_name()
 self._def_entity(QAPISchemaEnumType(
 name, info, None, ifcond, self._make_enum_members(values), None))
@@ -1887,7 +1897,7 @@ class QAPISchema(object):
role, members):
 if not members:
 return None
-# See also QAPISchemaObjectTypeMember._pretty_defined_in()
+# See also QAPISchemaObjectTypeMember.describe()
 name = 'q_obj_%s-%s' % (name, role)
 typ = self.lookup_entity(name, QAPISchemaObjectType)
 if typ:
diff --git a/tests/qapi-schema/alternate-clash.err 
b/tests/qapi-schema/alternate-clash.err
index 426ff6a7c4..73a52d69d1 100644
--- a/tests/qapi-schema/alternate-clash.err
+++ b/tests/qapi-schema/alternate-clash.err
@@ -1,2 +1,2 @@
 tests/qapi-schema/alternate-clash.json: In alternate 'Alt1':
-tests/qapi-schema/alternate-clash.json:7: 'a_b' (branch of Alt1) collides with 
'a-b' (branch of Alt1)
+tests/qapi-schema/alternate-clash.json:7: branch 'a_b' collides with branch 
'a-b'
di

Re: [PATCH v25 00/22] Add RX archtecture support

2019-09-28 Thread no-reply
Patchew URL: 
https://patchew.org/QEMU/20190927062302.110144-1-ys...@users.sourceforge.jp/



Hi,

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

Type: series
Message-id: 20190927062302.110144-1-ys...@users.sourceforge.jp
Subject: [PATCH v25 00/22] Add RX archtecture support

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

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
Switched to a new branch 'test'
dadff51 qapi/machine.json: Add RX cpu.
ebb6621 BootLinuxConsoleTest: Test the RX-Virt machine
f81a4dd Add rx-softmmu
91354fd hw/rx: Restrict the RX62N microcontroller to the RX62N CPU core
6703279 hw/rx: Honor -accel qtest
86d0724 hw/rx: RX Target hardware definition
f85dbca hw/char: RX62N serial communication interface (SCI)
0aac3dc hw/timer: RX62N internal timer modules
189c157 hw/intc: RX62N interrupt controller (ICUa)
f4e110a target/rx: Dump bytes for each insn during disassembly
68f9b3c target/rx: Collect all bytes during disassembly
c99e307 target/rx: Emit all disassembly in one prt()
afb3c6f target/rx: Use prt_ldmi for XCHG_mr disassembly
a2ff9b7 target/rx: Replace operand with prt_ldmi in disassembler
2753df2 target/rx: Disassemble rx_index_addr into a string
6c571d3 target/rx: RX disassembler
149fc98 target/rx: CPU definition
1c56e9d target/rx: TCG helper
33ec1bb target/rx: TCG translation
6dcb4ce hw/registerfields.h: Add 8bit and 16bit register macros
15439bc qemu/bitops.h: Add extract8 and extract16
6e3543e MAINTAINERS: Add RX

=== OUTPUT BEGIN ===
1/22 Checking commit 6e3543eb958d (MAINTAINERS: Add RX)
2/22 Checking commit 15439bc03d71 (qemu/bitops.h: Add extract8 and extract16)
3/22 Checking commit 6dcb4ce925f7 (hw/registerfields.h: Add 8bit and 16bit 
register macros)
Use of uninitialized value in concatenation (.) or string at 
./scripts/checkpatch.pl line 2484.
ERROR: Macros with multiple statements should be enclosed in a do - while loop
#27: FILE: include/hw/registerfields.h:25:
+#define REG8(reg, addr)  \
+enum { A_ ## reg = (addr) };  \
+enum { R_ ## reg = (addr) };

ERROR: Macros with multiple statements should be enclosed in a do - while loop
#31: FILE: include/hw/registerfields.h:29:
+#define REG16(reg, addr)  \
+enum { A_ ## reg = (addr) };  \
+enum { R_ ## reg = (addr) / 2 };

total: 2 errors, 0 warnings, 56 lines checked

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

4/22 Checking commit 33ec1bbabfae (target/rx: TCG translation)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#20: 
new file mode 100644

total: 0 errors, 1 warnings, 3065 lines checked

Patch 4/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
5/22 Checking commit 1c56e9df0bda (target/rx: TCG helper)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#21: 
new file mode 100644

total: 0 errors, 1 warnings, 650 lines checked

Patch 5/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
6/22 Checking commit 149fc989a0b3 (target/rx: CPU definition)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#38: 
new file mode 100644

total: 0 errors, 1 warnings, 588 lines checked

Patch 6/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
7/22 Checking commit 6c571d3b6a2f (target/rx: RX disassembler)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#38: 
new file mode 100644

total: 0 errors, 1 warnings, 1497 lines checked

Patch 7/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
8/22 Checking commit 2753df288343 (target/rx: Disassemble rx_index_addr into a 
string)
9/22 Checking commit a2ff9b7af426 (target/rx: Replace operand with prt_ldmi in 
disassembler)
10/22 Checking commit afb3c6f62e73 (target/rx: Use prt_ldmi for XCHG_mr 
disassembly)
11/22 Checking commit c99e3071a323 (target/rx: Emit all disassembly in one 
prt())
12/22 Checking commit 68f9b3cbfd59 (target/rx: Collect all bytes during 
disassembly)
13/22 Checking commit f4e110a34345 (target/rx: Dump bytes for each insn during 
disassembly)
14/22 Checking commit 189c15760991 (hw/intc: RX62N interrupt controller (ICUa))
WARNING: added, moved or deleted file

[PULL 26/27] qapi: Improve reporting of redefinition

2019-09-28 Thread Markus Armbruster
Point to the previous definition, unless it's a built-in.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20190927134639.4284-26-arm...@redhat.com>
---
 scripts/qapi/common.py  | 5 +
 tests/qapi-schema/redefined-command.err | 4 +++-
 tests/qapi-schema/redefined-event.err   | 4 +++-
 tests/qapi-schema/redefined-type.err| 4 +++-
 4 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index bd834270f8..a74cd957d4 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -1759,6 +1759,11 @@ class QAPISchema(object):
 # because they're liable to clash in generated C.
 other_ent = self._entity_dict.get(ent.name)
 if other_ent:
+if other_ent.info:
+where = QAPIError(other_ent.info, None, "previous definition")
+raise QAPISemError(
+ent.info,
+"'%s' is already defined\n%s" % (ent.name, where))
 raise QAPISemError(
 ent.info, "%s is already defined" % other_ent.describe())
 self._entity_dict[ent.name] = ent
diff --git a/tests/qapi-schema/redefined-command.err 
b/tests/qapi-schema/redefined-command.err
index b77a05d354..54e366bbf3 100644
--- a/tests/qapi-schema/redefined-command.err
+++ b/tests/qapi-schema/redefined-command.err
@@ -1,2 +1,4 @@
 tests/qapi-schema/redefined-command.json: In command 'foo':
-tests/qapi-schema/redefined-command.json:3: command 'foo' is already defined
+tests/qapi-schema/redefined-command.json:3: 'foo' is already defined
+tests/qapi-schema/redefined-command.json: In command 'foo':
+tests/qapi-schema/redefined-command.json:2: previous definition
diff --git a/tests/qapi-schema/redefined-event.err 
b/tests/qapi-schema/redefined-event.err
index fd02d38157..606c6e4497 100644
--- a/tests/qapi-schema/redefined-event.err
+++ b/tests/qapi-schema/redefined-event.err
@@ -1,2 +1,4 @@
 tests/qapi-schema/redefined-event.json: In event 'EVENT_A':
-tests/qapi-schema/redefined-event.json:3: event 'EVENT_A' is already defined
+tests/qapi-schema/redefined-event.json:3: 'EVENT_A' is already defined
+tests/qapi-schema/redefined-event.json: In event 'EVENT_A':
+tests/qapi-schema/redefined-event.json:2: previous definition
diff --git a/tests/qapi-schema/redefined-type.err 
b/tests/qapi-schema/redefined-type.err
index 39f51c14ea..77786f98ae 100644
--- a/tests/qapi-schema/redefined-type.err
+++ b/tests/qapi-schema/redefined-type.err
@@ -1,2 +1,4 @@
 tests/qapi-schema/redefined-type.json: In enum 'foo':
-tests/qapi-schema/redefined-type.json:3: struct type 'foo' is already defined
+tests/qapi-schema/redefined-type.json:3: 'foo' is already defined
+tests/qapi-schema/redefined-type.json: In struct 'foo':
+tests/qapi-schema/redefined-type.json:2: previous definition
-- 
2.21.0




[PULL 24/27] qapi: Eliminate check_keys(), rename check_known_keys()

2019-09-28 Thread Markus Armbruster
check_keys() has become a trivial wrapper for check_known_keys().
Eliminate it.

This makes its name available.  Rename check_known_keys().

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20190927134639.4284-24-arm...@redhat.com>
---
 scripts/qapi/common.py | 40 +---
 1 file changed, 21 insertions(+), 19 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 4bc8c807aa..fa354b3f1e 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -756,7 +756,7 @@ def check_type(value, info, source,
allow_optional=True, permit_upper=permit_upper)
 if c_name(key, False) == 'u' or c_name(key, False).startswith('has_'):
 raise QAPISemError(info, "%s uses reserved name" % key_source)
-check_known_keys(arg, info, key_source, ['type'], ['if'])
+check_keys(arg, info, key_source, ['type'], ['if'])
 check_if(arg, info, key_source)
 normalize_if(arg)
 check_type(arg['type'], info, key_source, allow_array=True)
@@ -800,7 +800,7 @@ def check_union(expr, info):
 for (key, value) in members.items():
 source = "'data' member '%s'" % key
 check_name_str(key, info, source)
-check_known_keys(value, info, source, ['type'], ['if'])
+check_keys(value, info, source, ['type'], ['if'])
 check_if(value, info, source)
 normalize_if(value)
 check_type(value['type'], info, source, allow_array=not base)
@@ -814,7 +814,7 @@ def check_alternate(expr, info):
 for (key, value) in members.items():
 source = "'data' member '%s'" % key
 check_name_str(key, info, source)
-check_known_keys(value, info, source, ['type'], ['if'])
+check_keys(value, info, source, ['type'], ['if'])
 check_if(value, info, source)
 normalize_if(value)
 check_type(value['type'], info, source)
@@ -834,7 +834,7 @@ def check_enum(expr, info):
 
 for member in members:
 source = "'data' member"
-check_known_keys(member, info, source, ['name'], ['if'])
+check_keys(member, info, source, ['name'], ['if'])
 check_name_is_str(member['name'], info, source)
 source = "%s '%s'" % (source, member['name'])
 check_name_str(member['name'], info, source,
@@ -857,7 +857,7 @@ def check_struct(expr, info):
 for f in features:
 source = "'features' member"
 assert isinstance(f, dict)
-check_known_keys(f, info, source, ['name'], ['if'])
+check_keys(f, info, source, ['name'], ['if'])
 check_name_is_str(f['name'], info, source)
 source = "%s '%s'" % (source, f['name'])
 check_name_str(f['name'], info, source)
@@ -865,7 +865,7 @@ def check_struct(expr, info):
 normalize_if(f)
 
 
-def check_known_keys(value, info, source, required, optional):
+def check_keys(value, info, source, required, optional):
 
 def pprint(elems):
 return ', '.join("'" + e + "'" for e in sorted(elems))
@@ -887,10 +887,6 @@ def check_known_keys(value, info, source, required, 
optional):
pprint(unknown), pprint(allowed)))
 
 
-def check_keys(expr, info, meta, required, optional=[]):
-check_known_keys(expr, info, meta, required + [meta], optional)
-
-
 def check_flags(expr, info):
 for key in ['gen', 'success-response']:
 if key in expr and expr[key] is not False:
@@ -966,33 +962,39 @@ def check_exprs(exprs):
 info, "documentation comment is for '%s'" % doc.symbol)
 
 if meta == 'enum':
-check_keys(expr, info, 'enum', ['data'], ['if', 'prefix'])
+check_keys(expr, info, meta,
+   ['enum', 'data'], ['if', 'prefix'])
 normalize_enum(expr)
 check_enum(expr, info)
 elif meta == 'union':
-check_keys(expr, info, 'union', ['data'],
+check_keys(expr, info, meta,
+   ['union', 'data'],
['base', 'discriminator', 'if'])
 normalize_members(expr.get('base'))
 normalize_members(expr['data'])
 check_union(expr, info)
 elif meta == 'alternate':
-check_keys(expr, info, 'alternate', ['data'], ['if'])
+check_keys(expr, info, meta,
+   ['alternate', 'data'], ['if'])
 normalize_members(expr['data'])
 check_alternate(expr, info)
 elif meta == 'struct':
-check_keys(expr, info, 'struct', ['data'],
-   ['base', 'if', 'features'])
+check_keys(expr, info, meta,
+   ['struct', 'data'], ['base', 'if', 'features'])
 normalize_members(expr['data'])
 normalize_features(expr.get('features'))
 check_struct(expr, info)
 elif meta == 'command':
-check_keys(expr, info, 'comman

[PATCH] configure: Remove s390 (31-bit mode) from the list of supported CPUs

2019-09-28 Thread Thomas Huth
On IBM Z, KVM in the kernel is only implemented for 64-bit mode, and
with regards to TCG, we also only support 64-bit host CPUs (see the
check at the beginning of tcg/s390/tcg-target.inc.c), so we should
remove s390 (without "x", i.e. the old 31-bit mode CPUs) from the
list of supported CPUs.

Signed-off-by: Thomas Huth 
---
 configure | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/configure b/configure
index 397bb476e1..a4488c6705 100755
--- a/configure
+++ b/configure
@@ -728,7 +728,7 @@ ARCH=
 # Normalise host CPU name and set ARCH.
 # Note that this case should only have supported host CPUs, not guests.
 case "$cpu" in
-  ppc|ppc64|s390|s390x|sparc64|x32|riscv32|riscv64)
+  ppc|ppc64|s390x|sparc64|x32|riscv32|riscv64)
 supported_cpu="yes"
   ;;
   ppc64le)
-- 
2.18.1




[PULL 05/27] qapi: Prefix frontend errors with an "in definition" line

2019-09-28 Thread Markus Armbruster
We take pains to include the offending expression in error messages,
e.g.

tests/qapi-schema/alternate-any.json:2: alternate 'Alt' member 'one' cannot 
use type 'any'

But not always:

tests/qapi-schema/enum-if-invalid.json:2: 'if' condition must be a string 
or a list of strings

Instead of improving them one by one, report the offending expression
whenever it is known, like this:

tests/qapi-schema/enum-if-invalid.json: In enum 'TestIfEnum':
tests/qapi-schema/enum-if-invalid.json:2: 'if' condition must be a string 
or a list of strings

Error messages that mention the offending expression become a bit
redundant, e.g.

tests/qapi-schema/alternate-any.json: In alternate 'Alt':
tests/qapi-schema/alternate-any.json:2: alternate 'Alt' member 'one' cannot 
use type 'any'

I'll take care of that later in this series.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20190927134639.4284-5-arm...@redhat.com>
---
 scripts/qapi/common.py| 15 ++-
 tests/qapi-schema/alternate-any.err   |  1 +
 tests/qapi-schema/alternate-array.err |  1 +
 tests/qapi-schema/alternate-branch-if-invalid.err |  1 +
 tests/qapi-schema/alternate-clash.err |  1 +
 .../alternate-conflict-bool-string.err|  1 +
 tests/qapi-schema/alternate-conflict-dict.err |  1 +
 .../qapi-schema/alternate-conflict-enum-bool.err  |  1 +
 tests/qapi-schema/alternate-conflict-enum-int.err |  1 +
 .../qapi-schema/alternate-conflict-num-string.err |  1 +
 tests/qapi-schema/alternate-conflict-string.err   |  1 +
 tests/qapi-schema/alternate-empty.err |  1 +
 tests/qapi-schema/alternate-invalid-dict.err  |  1 +
 tests/qapi-schema/alternate-nested.err|  1 +
 tests/qapi-schema/alternate-unknown.err   |  1 +
 tests/qapi-schema/args-alternate.err  |  1 +
 tests/qapi-schema/args-any.err|  1 +
 tests/qapi-schema/args-array-empty.err|  1 +
 tests/qapi-schema/args-array-unknown.err  |  1 +
 tests/qapi-schema/args-boxed-anon.err |  1 +
 tests/qapi-schema/args-boxed-string.err   |  1 +
 tests/qapi-schema/args-int.err|  1 +
 tests/qapi-schema/args-invalid.err|  1 +
 tests/qapi-schema/args-member-array-bad.err   |  1 +
 tests/qapi-schema/args-member-case.err|  1 +
 tests/qapi-schema/args-member-unknown.err |  1 +
 tests/qapi-schema/args-name-clash.err |  1 +
 tests/qapi-schema/args-union.err  |  1 +
 tests/qapi-schema/args-unknown.err|  1 +
 tests/qapi-schema/bad-base.err|  1 +
 tests/qapi-schema/bad-data.err|  1 +
 tests/qapi-schema/base-cycle-direct.err   |  1 +
 tests/qapi-schema/base-cycle-indirect.err |  1 +
 tests/qapi-schema/doc-bad-symbol.err  |  1 +
 tests/qapi-schema/enum-bad-member.err |  1 +
 tests/qapi-schema/enum-bad-name.err   |  1 +
 tests/qapi-schema/enum-bad-prefix.err |  1 +
 tests/qapi-schema/enum-clash-member.err   |  1 +
 tests/qapi-schema/enum-dict-member-unknown.err|  1 +
 tests/qapi-schema/enum-if-invalid.err |  1 +
 tests/qapi-schema/enum-member-case.err|  1 +
 tests/qapi-schema/enum-wrong-data.err |  1 +
 tests/qapi-schema/event-boxed-empty.err   |  1 +
 tests/qapi-schema/event-member-invalid-dict.err   |  1 +
 tests/qapi-schema/event-nest-struct.err   |  1 +
 tests/qapi-schema/features-bad-type.err   |  1 +
 tests/qapi-schema/features-duplicate-name.err |  1 +
 tests/qapi-schema/features-if-invalid.err |  1 +
 tests/qapi-schema/features-missing-name.err   |  1 +
 tests/qapi-schema/features-name-bad-type.err  |  1 +
 tests/qapi-schema/features-no-list.err|  1 +
 tests/qapi-schema/features-unknown-key.err|  1 +
 tests/qapi-schema/flat-union-array-branch.err |  1 +
 tests/qapi-schema/flat-union-bad-base.err |  1 +
 .../qapi-schema/flat-union-bad-discriminator.err  |  1 +
 tests/qapi-schema/flat-union-base-any.err |  1 +
 tests/qapi-schema/flat-union-base-union.err   |  1 +
 tests/qapi-schema/flat-union-clash-member.err |  1 +
 .../flat-union-discriminator-bad-name.err |  1 +
 tests/qapi-schema/flat-union-empty.err|  1 +
 .../flat-union-inline-invalid-dict.err|  1 +
 tests/qapi-schema/flat-union-inline.err   |  1 +
 tests/qapi-schema/flat-union-int-branch.err   |  1 +
 .../qapi-schema/flat-union-invalid-branch-key.err |  1 +
 .../flat-union-invalid-discriminator.err  |  1 +
 .../flat-union-invalid-if-discriminator.err   |  1 +
 tests/qapi-schema/flat-union-no-base.err  |  1 +
 .../flat-union-optional-discriminator.err |  1 +
 .../flat-union-string-discriminator.err   |  1 +
 .../nested-struc

[PULL 22/27] qapi: Avoid redundant definition references in error messages

2019-09-28 Thread Markus Armbruster
Many error messages refer to the offending definition even though
they're preceded by an "in definition" line.  Rephrase them.

Signed-off-by: Markus Armbruster 
Message-Id: <20190927134639.4284-22-arm...@redhat.com>
Reviewed-by: Eric Blake 
---
 scripts/qapi/common.py| 129 +++---
 tests/qapi-schema/alternate-array.err |   2 +-
 tests/qapi-schema/alternate-base.err  |   2 +-
 tests/qapi-schema/alternate-empty.err |   2 +-
 tests/qapi-schema/alternate-invalid-dict.err  |   2 +-
 tests/qapi-schema/args-array-empty.err|   2 +-
 tests/qapi-schema/args-boxed-anon.err |   2 +-
 tests/qapi-schema/args-invalid.err|   2 +-
 tests/qapi-schema/args-member-array-bad.err   |   2 +-
 tests/qapi-schema/args-member-case.err|   2 +-
 tests/qapi-schema/bad-data.err|   2 +-
 tests/qapi-schema/bad-ident.err   |   2 +-
 tests/qapi-schema/doc-bad-symbol.err  |   2 +-
 tests/qapi-schema/double-type.err |   2 +-
 tests/qapi-schema/enum-bad-member.err |   2 +-
 tests/qapi-schema/enum-bad-name.err   |   2 +-
 tests/qapi-schema/enum-bad-prefix.err |   2 +-
 .../qapi-schema/enum-dict-member-unknown.err  |   2 +-
 tests/qapi-schema/enum-member-case.err|   2 +-
 tests/qapi-schema/enum-missing-data.err   |   2 +-
 tests/qapi-schema/enum-wrong-data.err |   2 +-
 .../qapi-schema/event-member-invalid-dict.err |   2 +-
 tests/qapi-schema/event-nest-struct.err   |   2 +-
 tests/qapi-schema/features-bad-type.err   |   2 +-
 tests/qapi-schema/features-missing-name.err   |   2 +-
 tests/qapi-schema/features-name-bad-type.err  |   2 +-
 tests/qapi-schema/features-no-list.err|   2 +-
 tests/qapi-schema/features-unknown-key.err|   2 +-
 tests/qapi-schema/flat-union-array-branch.err |   2 +-
 .../flat-union-bad-discriminator.err  |   2 +-
 .../flat-union-inline-invalid-dict.err|   2 +-
 tests/qapi-schema/flat-union-inline.err   |   2 +-
 tests/qapi-schema/flat-union-no-base.err  |   2 +-
 .../nested-struct-data-invalid-dict.err   |   2 +-
 tests/qapi-schema/nested-struct-data.err  |   2 +-
 tests/qapi-schema/reserved-command-q.err  |   2 +-
 tests/qapi-schema/reserved-enum-q.err |   2 +-
 tests/qapi-schema/reserved-member-has.err |   2 +-
 tests/qapi-schema/reserved-member-q.err   |   2 +-
 tests/qapi-schema/reserved-member-u.err   |   2 +-
 .../reserved-member-underscore.err|   2 +-
 tests/qapi-schema/reserved-type-kind.err  |   2 +-
 tests/qapi-schema/reserved-type-list.err  |   2 +-
 tests/qapi-schema/returns-array-bad.err   |   2 +-
 tests/qapi-schema/returns-dict.err|   2 +-
 tests/qapi-schema/struct-data-invalid.err |   2 +-
 .../struct-member-invalid-dict.err|   2 +-
 tests/qapi-schema/struct-member-invalid.err   |   2 +-
 .../union-base-no-discriminator.err   |   2 +-
 tests/qapi-schema/union-branch-case.err   |   2 +-
 .../qapi-schema/union-branch-invalid-dict.err |   2 +-
 tests/qapi-schema/union-optional-branch.err   |   2 +-
 tests/qapi-schema/unknown-expr-key.err|   2 +-
 53 files changed, 101 insertions(+), 132 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 42b9c2e36b..81c217cd60 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -657,13 +657,6 @@ valid_name = re.compile(r'^(__[a-zA-Z0-9.-]+_)?'
 '[a-zA-Z][a-zA-Z0-9_-]*$')
 
 
-def check_name(name, info, source,
-   allow_optional=False, enum_member=False, permit_upper=False):
-check_name_is_str(name, info, source)
-check_name_str(name, info, source,
-   allow_optional, enum_member, permit_upper)
-
-
 def check_name_is_str(name, info, source):
 if not isinstance(name, str):
 raise QAPISemError(info, "%s requires a string name" % source)
@@ -685,10 +678,10 @@ def check_name_str(name, info, source,
 # and 'q_obj_*' implicit type names.
 if not valid_name.match(membername) or \
c_name(membername, False).startswith('q_'):
-raise QAPISemError(info, "%s uses invalid name '%s'" % (source, name))
+raise QAPISemError(info, "%s has an invalid name" % source)
 if not permit_upper and name.lower() != name:
 raise QAPISemError(
-info, "%s uses uppercase in name '%s'" % (source, name))
+info, "%s uses uppercase in name" % source)
 assert not membername.startswith('*')
 
 
@@ -696,7 +689,7 @@ def check_defn_name_str(name, info, meta):
 check_name_str(name, info, meta, permit_upper=True)
 if name.endswith('Kind') or name.endswith('List'):
 raise QAPISemError(
-info, "%s '%s' should not end in '%s'" % (meta, name, name[-4:]))
+info, "%s name should not end in '%s'" % (meta, name[-4:]))
 
 
 def check_if(expr, info):
@@ -753,42 +746,35 @@ def

[PULL 17/27] qapi: Move context-sensitive checking to the proper place

2019-09-28 Thread Markus Armbruster
When we introduced the QAPISchema intermediate representation (commit
ac88219a6c7), we took a shortcut: we left check_exprs() & friends
alone instead of moving semantic checks into the
QAPISchemaFOO.check().  The .check() assert check_exprs() did its job.

Time to finish the conversion job.  Move exactly the context-sensitive
checks to the .check().  They replace assertions there.  Context-free
checks stay put.

Fixes the misleading optional tag error demonstrated by test
flat-union-optional-discriminator.

A few other error message improve.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20190927134639.4284-17-arm...@redhat.com>
---
 scripts/qapi/common.py| 424 --
 tests/qapi-schema/alternate-any.err   |   2 +-
 .../alternate-conflict-bool-string.err|   2 +-
 tests/qapi-schema/alternate-conflict-dict.err |   2 +-
 .../alternate-conflict-enum-bool.err  |   2 +-
 .../alternate-conflict-enum-int.err   |   2 +-
 .../alternate-conflict-num-string.err |   2 +-
 .../qapi-schema/alternate-conflict-string.err |   2 +-
 tests/qapi-schema/alternate-nested.err|   2 +-
 tests/qapi-schema/alternate-unknown.err   |   2 +-
 tests/qapi-schema/args-alternate.err  |   2 +-
 tests/qapi-schema/args-any.err|   2 +-
 tests/qapi-schema/args-array-unknown.err  |   2 +-
 tests/qapi-schema/args-boxed-string.err   |   2 +-
 tests/qapi-schema/args-int.err|   2 +-
 tests/qapi-schema/args-member-unknown.err |   2 +-
 tests/qapi-schema/args-union.err  |   2 +-
 tests/qapi-schema/args-unknown.err|   2 +-
 tests/qapi-schema/bad-base.err|   2 +-
 tests/qapi-schema/command-int.err |   2 +-
 tests/qapi-schema/flat-union-base-any.err |   2 +-
 tests/qapi-schema/flat-union-base-union.err   |   2 +-
 .../flat-union-discriminator-bad-name.err |   2 +-
 .../flat-union-discriminator-bad-name.json|   1 -
 tests/qapi-schema/flat-union-empty.err|   2 +-
 tests/qapi-schema/flat-union-int-branch.err   |   2 +-
 .../flat-union-invalid-branch-key.err |   2 +-
 .../flat-union-invalid-if-discriminator.err   |   2 +-
 .../flat-union-optional-discriminator.err |   2 +-
 .../flat-union-optional-discriminator.json|   1 -
 .../flat-union-string-discriminator.err   |   2 +-
 tests/qapi-schema/redefined-builtin.err   |   2 +-
 tests/qapi-schema/redefined-type.err  |   2 +-
 tests/qapi-schema/returns-alternate.err   |   2 +-
 tests/qapi-schema/returns-unknown.err |   2 +-
 tests/qapi-schema/returns-whitelist.err   |   2 +-
 tests/qapi-schema/union-empty.err |   2 +-
 tests/qapi-schema/union-invalid-base.err  |   2 +-
 tests/qapi-schema/union-unknown.err   |   2 +-
 tests/qapi-schema/union-unknown.json  |   2 +-
 40 files changed, 230 insertions(+), 270 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 9acff01d3e..f22e84c4a8 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -21,25 +21,6 @@ import string
 import sys
 from collections import OrderedDict
 
-builtin_types = {
-'null': 'QTYPE_QNULL',
-'str':  'QTYPE_QSTRING',
-'int':  'QTYPE_QNUM',
-'number':   'QTYPE_QNUM',
-'bool': 'QTYPE_QBOOL',
-'int8': 'QTYPE_QNUM',
-'int16':'QTYPE_QNUM',
-'int32':'QTYPE_QNUM',
-'int64':'QTYPE_QNUM',
-'uint8':'QTYPE_QNUM',
-'uint16':   'QTYPE_QNUM',
-'uint32':   'QTYPE_QNUM',
-'uint64':   'QTYPE_QNUM',
-'size': 'QTYPE_QNUM',
-'any':  None,   # any QType possible, actually
-'QType':'QTYPE_QSTRING',
-}
-
 # Are documentation comments required?
 doc_required = False
 
@@ -49,11 +30,6 @@ returns_whitelist = []
 # Whitelist of entities allowed to violate case conventions
 name_case_whitelist = []
 
-enum_types = {}
-struct_types = {}
-union_types = {}
-all_names = {}
-
 
 #
 # Parsing the schema into expressions
@@ -671,34 +647,9 @@ class QAPISchemaParser(object):
 
 
 #
-# Semantic analysis of schema expressions
-# TODO fold into QAPISchema
-# TODO catching name collisions in generated code would be nice
+# Check (context-free) schema expression structure
 #
 
-
-def find_base_members(base):
-if isinstance(base, dict):
-return base
-base_struct_define = struct_types.get(base)
-if not base_struct_define:
-return None
-return base_struct_define['data']
-
-
-# Return the qtype of an alternate branch, or None on error.
-def find_alternate_member_qtype(qapi_type):
-if qapi_type in builtin_types:
-return builtin_types[qapi_type]
-elif qapi_type in struct_types:
-return 'QTYPE_QDICT'
-elif qapi_type in enum_types:
-return 'QTYPE_QSTRING'
-elif qapi_type in union_types:
-return 'QTYPE_QDICT'
-return None
-
-
 # Names must be lette

[PULL 07/27] qapi: Change frontend error messages to start with lower case

2019-09-28 Thread Markus Armbruster
Starting error messages with a capital letter complicates things when
text can get interpolated both at the beginning and in the middle of
an error message.  The next patch will do that.  Switch to lower case
to keep it simpler.

For what it's worth, the GNU Coding Standards advise the message
"should not begin with a capital letter when it follows a program name
and/or file name, because that isn’t the beginning of a sentence. (The
sentence conceptually starts at the beginning of the line.)"

While there, avoid breaking lines containing multiple arguments in the
middle of an argument.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20190927134639.4284-7-arm...@redhat.com>
---
 scripts/qapi/common.py| 192 ++
 tests/qapi-schema/alternate-any.err   |   2 +-
 tests/qapi-schema/alternate-array.err |   2 +-
 tests/qapi-schema/alternate-base.err  |   2 +-
 .../alternate-conflict-bool-string.err|   2 +-
 tests/qapi-schema/alternate-conflict-dict.err |   2 +-
 .../alternate-conflict-enum-bool.err  |   2 +-
 .../alternate-conflict-enum-int.err   |   2 +-
 .../alternate-conflict-num-string.err |   2 +-
 .../qapi-schema/alternate-conflict-string.err |   2 +-
 tests/qapi-schema/alternate-empty.err |   2 +-
 tests/qapi-schema/alternate-invalid-dict.err  |   2 +-
 tests/qapi-schema/alternate-nested.err|   2 +-
 tests/qapi-schema/alternate-unknown.err   |   2 +-
 tests/qapi-schema/args-array-empty.err|   2 +-
 tests/qapi-schema/args-array-unknown.err  |   2 +-
 tests/qapi-schema/args-member-array-bad.err   |   2 +-
 tests/qapi-schema/args-member-case.err|   2 +-
 tests/qapi-schema/args-member-unknown.err |   2 +-
 tests/qapi-schema/bad-type-int.err|   2 +-
 tests/qapi-schema/base-cycle-direct.err   |   2 +-
 tests/qapi-schema/base-cycle-indirect.err |   2 +-
 .../qapi-schema/doc-bad-alternate-member.err  |   2 +-
 tests/qapi-schema/doc-bad-command-arg.err |   2 +-
 tests/qapi-schema/doc-bad-symbol.err  |   2 +-
 tests/qapi-schema/doc-bad-union-member.err|   2 +-
 tests/qapi-schema/doc-before-include.err  |   2 +-
 tests/qapi-schema/doc-before-pragma.err   |   2 +-
 tests/qapi-schema/doc-duplicated-return.err   |   2 +-
 tests/qapi-schema/doc-duplicated-since.err|   2 +-
 tests/qapi-schema/doc-empty-arg.err   |   2 +-
 tests/qapi-schema/doc-empty-section.err   |   2 +-
 tests/qapi-schema/doc-empty-symbol.err|   2 +-
 tests/qapi-schema/doc-invalid-end.err |   2 +-
 tests/qapi-schema/doc-invalid-end2.err|   2 +-
 tests/qapi-schema/doc-invalid-start.err   |   2 +-
 tests/qapi-schema/doc-missing-colon.err   |   2 +-
 tests/qapi-schema/doc-missing-expr.err|   2 +-
 tests/qapi-schema/doc-missing-space.err   |   2 +-
 tests/qapi-schema/doc-missing.err |   2 +-
 tests/qapi-schema/doc-no-symbol.err   |   2 +-
 tests/qapi-schema/double-type.err |   2 +-
 tests/qapi-schema/duplicate-key.err   |   2 +-
 tests/qapi-schema/enum-bad-member.err |   2 +-
 tests/qapi-schema/enum-bad-name.err   |   2 +-
 tests/qapi-schema/enum-bad-prefix.err |   2 +-
 .../qapi-schema/enum-dict-member-unknown.err  |   2 +-
 tests/qapi-schema/enum-int-member.err |   2 +-
 tests/qapi-schema/enum-member-case.err|   2 +-
 tests/qapi-schema/enum-missing-data.err   |   2 +-
 tests/qapi-schema/enum-wrong-data.err |   2 +-
 tests/qapi-schema/escape-outside-string.err   |   2 +-
 tests/qapi-schema/event-boxed-empty.err   |   2 +-
 .../qapi-schema/event-member-invalid-dict.err |   2 +-
 tests/qapi-schema/event-nest-struct.err   |   2 +-
 tests/qapi-schema/features-bad-type.err   |   2 +-
 tests/qapi-schema/features-missing-name.err   |   2 +-
 tests/qapi-schema/features-name-bad-type.err  |   2 +-
 tests/qapi-schema/features-no-list.err|   2 +-
 tests/qapi-schema/features-unknown-key.err|   2 +-
 tests/qapi-schema/flat-union-array-branch.err |   2 +-
 .../flat-union-bad-discriminator.err  |   2 +-
 .../flat-union-discriminator-bad-name.err |   2 +-
 tests/qapi-schema/flat-union-empty.err|   2 +-
 .../flat-union-inline-invalid-dict.err|   2 +-
 tests/qapi-schema/flat-union-inline.err   |   2 +-
 tests/qapi-schema/flat-union-int-branch.err   |   2 +-
 .../flat-union-invalid-branch-key.err |   2 +-
 .../flat-union-invalid-discriminator.err  |   2 +-
 .../flat-union-invalid-if-discriminator.err   |   2 +-
 tests/qapi-schema/flat-union-no-base.err  |   2 +-
 .../flat-union-optional-discriminator.err |   2 +-
 .../flat-union-string-discriminator.err   |   2 +-
 tests/qapi-schema/funny-char.err  |   2 +-
 tests/qapi-schema/funny-word.err  |   2 +-
 tests/qapi-schema/ident-with-escape.err   |   2 +-
 tests/qapi-sche

Re: Questions about the real mode in kvm/qemu

2019-09-28 Thread Avi Kivity

On 9/26/19 12:18 PM, Paolo Bonzini wrote:

On 26/09/19 10:59, Maxim Levitsky wrote:

If you mean to ask if there is a way to let guest access use no
paging at all, that is access host physical addresses directly, then
indeed there is no way, since regular non 'unrestricted guest' mode
required both protected mode and paging, and 'unrestricted guest'
requires EPT. Academically speaking it is of course possible to
create paging tables that are 1:1...

Not so academically, it's exactly what KVM does.  However, indeed it
would also be possible to switch out of EPT mode when CR0.PG=0.  I'm not
sure why it was done this way, maybe when the code was written it was
simpler to use the identity map.

Let's see if Avi is listening... :)



I think it was just simpler for the people who implemented it at the 
time. Switching out of EPT would have been a better solution as it would 
no longer require allocating guest physical address space with the few 
warts that requires.







Re: target/ppc: bug in optimised vsl/vsr implementation?

2019-09-28 Thread Aleksandar Markovic
28.09.2019. 19.45, "Aleksandar Markovic"  је
написао/ла:
>
>
> 26.09.2019. 20.14, "Mark Cave-Ayland"  је
написао/ла:
> >
> > As part of the investigation into the DFP number issue reported at
> > https://bugs.launchpad.net/qemu/+bug/1841990 it appears that there may
also be a bug
> > introduced by the new optimised vsl/vsr implementation:
> >
> > commit 4e6d0920e7547e6af4bbac5ffe9adfe6ea621822
> > Author: Stefan Brankovic 
> > Date: Mon Jul 15 16:22:48 2019 +0200
> >
> > target/ppc: Optimize emulation of vsl and vsr instructions
> >
> >
>
> (sorry in advance if the format of this message looks odd, I have some
problems with mail settings related to recent qemu-devel mailer settings
changes; I will adjust my mail settings in next few days)
>
> Mark and Paul (and Stefan),
>
> Thanks for spotting this and pinpointing the culprit commit. I guess
Stefan is going to respond soon, but, in the meantime, I took a look at the
commit in question:
>
>
https://github.com/qemu/qemu/commit/4e6d0920e7547e6af4bbac5ffe9adfe6ea621822
>
> I don't have at the moment any dev/test environment handy, but I did
manual inspection of the code, and here is what I found (in order of
importance, perceived by me):
>
> 1. The code will not work correctly if the shift ammount (variable 'sh')
is 0. This is because, in that case, one of succeeding invocations of TCG
shift functions will be required to shift a 64-bit TCG variable by 64 bits,
and the result of such TCG operation is undefined (shift amount must be 63
or less) - see https://github.com/qemu/qemu/blob/master/tcg/README.
>
> 2. Variable naming is better in the old helper than in the new
translator. In that light, I would advise Stefan to change 'sh' to 'shift',
and 'shifted' to 'carry'.
>
> 3. Lines
>
> tcg_gen_andi_i64(shifted, shifted, 0x7fULL);
>
> and
>
> tcg_gen_andi_i64(shifted, shifted, 0xfe00ULL);
>
> appear to be spurious (albait in a harmless way). Therefore, they should
be deleted, or, alternatevely, a justification for them should be provided.
>
> 4. In the commit message, variable names were used without quotation
mark, resulting in puzzling and unclear wording.
>
> 5. (a question for Mark) After all recent changes, does get_avr64(...,
..., true) always (for any endian configuration) return the "high" half of
an Altivec register, and get_avr64(..., ..., false) the "low" one?
>

One more hint: variables 'avrA' and 'avrB' can be a single variable, since
there is no moment during execution where both are needed; the same for
'tmp' and 'shifted'.

Also, check on the hardware the behavior listed as 'undefined' for vsl/vsr
in the docs - even though it is tehnically irrelevant, I am courious
whether the old or the new (or none of them) solution match the hardware.

> Given all these circumstances, perhaps the most reasonable solution would
be to revert the commit in question, and allow Stefan enough dev and test
time to hopefully submit a new, better, version later on.
>
> Sincerely,
> Aleksandar
>


RE: [PATCH V2] intel_iommu: TM field should not be in reserved bits

2019-09-28 Thread Zhang, Qi1


> -Original Message-
> From: Peter Xu 
> Sent: Friday, September 27, 2019 5:32 PM
> To: Zhang, Qi1 
> Cc: qemu-devel@nongnu.org; ehabk...@redhat.com; m...@redhat.com;
> pbonz...@redhat.com; r...@twiddle.net; Qi, Yadong 
> Subject: Re: [PATCH V2] intel_iommu: TM field should not be in reserved bits
> 
> On Fri, Sep 27, 2019 at 08:03:21AM +, Zhang, Qi1 wrote:
> >
> >
> > > -Original Message-
> > > From: Peter Xu 
> > > Sent: Friday, September 27, 2019 2:10 PM
> > > To: Zhang, Qi1 
> > > Cc: qemu-devel@nongnu.org; ehabk...@redhat.com; m...@redhat.com;
> > > pbonz...@redhat.com; r...@twiddle.net
> > > Subject: Re: [PATCH V2] intel_iommu: TM field should not be in
> > > reserved bits
> > >
> > > On Fri, Sep 27, 2019 at 12:58:38PM +0800, qi1.zh...@intel.com wrote:
> > > > From: "Zhang, Qi" 
> > > >
> > > > When dt is supported, TM field should not be Reserved(0).
> > > >
> > > > Refer to VT-d Spec 9.8
> > > >
> > > > Signed-off-by: Zhang, Qi 
> > > > Signed-off-by: Qi, Yadong 
> > > > ---
> > > >  hw/i386/intel_iommu.c  | 12 ++--
> > > >  hw/i386/intel_iommu_internal.h | 25 +++--
> > > >  2 files changed, 25 insertions(+), 12 deletions(-)
> > > > ---
> VTD_SPTE_PAGE_L2_RSVD_MASK(s-
> > > >aw_bits);
> > > > -vtd_paging_entry_rsvd_field[3] =
> > > >aw_bits);
> > > > +vtd_paging_entry_rsvd_field[5] =
> > > VTD_SPTE_LPAGE_L1_RSVD_MASK(s->aw_bits, x86_iommu-
> > > >dt_supported);
> > > > +vtd_paging_entry_rsvd_field[6] =
> > > VTD_SPTE_LPAGE_L2_RSVD_MASK(s->aw_bits, x86_iommu-
> > > >dt_supported);
> > > > +vtd_paging_entry_rsvd_field[7] =
> > > > + VTD_SPTE_LPAGE_L3_RSVD_MASK(s->aw_bits, x86_iommu-
> > > >dt_supported);
> > > >  vtd_paging_entry_rsvd_field[8] =
> > > >VTD_SPTE_LPAGE_L4_RSVD_MASK(s->aw_bits);
> > >
> > > Should this TM bit only affects leaves?  Say, entry 1 (4K), 5 (2M), 6 
> > > (1G).
> > > While this reminded me that I'm totally confused on why we have had
> > > entry 7, 8 after all...  Are they really used?
> > Yes. TM bit only affects. To this array, index 1, 5,6,7 may be leaf. Will 
> > update
> a new patchset for it.
> 
> Could I ask why index 7 may be leaf?
Index 7 is PDPE 1G GB leaf.
> 
> > >
> > > >
> > > >  if (x86_iommu_ir_supported(x86_iommu)) { diff --git
> > > > a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h
> > > > index c1235a7063..01f1aa6c86 100644
> > > > --- a/hw/i386/intel_iommu_internal.h
> > > > +++ b/hw/i386/intel_iommu_internal.h
> > > > @@ -387,19 +387,31 @@ typedef union VTDInvDesc VTDInvDesc;
> > > > #define VTD_INV_DESC_DEVICE_IOTLB_RSVD_LO 0xffe0fff8
> > > >
> > > >  /* Rsvd field masks for spte */
> > > > -#define VTD_SPTE_PAGE_L1_RSVD_MASK(aw) \
> > > > +#define VTD_SPTE_PAGE_L1_RSVD_MASK(aw, dt_supported) \
> > > > +dt_supported? \
> > > > +(0x800ULL | ~(VTD_HAW_MASK(aw) | VTD_SL_IGN_COM |
> > > VTD_SL_TM))
> > > > +: \
> > > >  (0x800ULL | ~(VTD_HAW_MASK(aw) | VTD_SL_IGN_COM))
> > >
> > > This seems strange too in that ~VTD_HAW_MASK(aw) probably covered
> > > bits
> > > 63-48 for aw==48 case so it should already cover VTD_SL_TM?
> > VTD_SL_IGN_COM 0xbff0ULL, TM field is cleared by ~
> > VTD_SL_IGN_COM
> > >
> > > Meanwhile when I'm reading the spec I see at least bits 61-52
> > > ignored rather than reserved.
> > Yes. Bit 61~52 is ignored. Such as the index 5 of this array is 
> > 0xfff800800.
> 
> Oops, my poor eye obviously didn't see that the "~" operator is applied over
> the whole (VTD_HAW_MASK(aw) | VTD_SL_IGN_COM)... :)
> 
> Btw, you should only touch up the macros that are leaves here.
> Non-leaves should still keep that bit as reserved.
Yes. I will.
> 
> Thanks,
> 
> --
> Peter Xu


Re: [PATCH RESEND v4 1/2] x86/cpu: Add support for UMONITOR/UMWAIT/TPAUSE

2019-09-28 Thread Tao Xu

On 9/28/2019 4:22 AM, Paolo Bonzini wrote:

On 18/09/19 09:23, Tao Xu wrote:

+} else if (function == 7 && index == 0 && reg == R_ECX) {
+if (enable_cpu_pm) {
+ret |= CPUID_7_0_ECX_WAITPKG;
+}


This should be the opposite; remove the bit if enable_cpu_pm is not set.

Paolo


Thanks, I will improve it.



[PATCH v5 1/2] x86/cpu: Add support for UMONITOR/UMWAIT/TPAUSE

2019-09-28 Thread Tao Xu
UMONITOR, UMWAIT and TPAUSE are a set of user wait instructions.
This patch adds support for user wait instructions in KVM. Availability
of the user wait instructions is indicated by the presence of the CPUID
feature flag WAITPKG CPUID.0x07.0x0:ECX[5]. User wait instructions may
be executed at any privilege level, and use IA32_UMWAIT_CONTROL MSR to
set the maximum time.

The patch enable the umonitor, umwait and tpause features in KVM.
Because umwait and tpause can put a (psysical) CPU into a power saving
state, by default we dont't expose it to kvm and enable it only when
guest CPUID has it. And use QEMU command-line "-overcommit cpu-pm=on"
(enable_cpu_pm is enabled), a VM can use UMONITOR, UMWAIT and TPAUSE
instructions. If the instruction causes a delay, the amount of time
delayed is called here the physical delay. The physical delay is first
computed by determining the virtual delay (the time to delay relative to
the VM’s timestamp counter). Otherwise, UMONITOR, UMWAIT and TPAUSE cause
an invalid-opcode exception(#UD).

The release document ref below link:
https://software.intel.com/sites/default/files/\
managed/39/c5/325462-sdm-vol-1-2abcd-3abcd.pdf

Co-developed-by: Jingqi Liu 
Signed-off-by: Jingqi Liu 
Signed-off-by: Tao Xu 
---

Changes in v5:
- Remove CPUID_7_0_ECX_WAITPKG if enable_cpu_pm is not set.
(Paolo)
---
 target/i386/cpu.c | 3 ++-
 target/i386/cpu.h | 1 +
 target/i386/kvm.c | 6 ++
 3 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 9e0bac31e8..15f888b13f 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1062,7 +1062,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = 
{
 .type = CPUID_FEATURE_WORD,
 .feat_names = {
 NULL, "avx512vbmi", "umip", "pku",
-NULL /* ospke */, NULL, "avx512vbmi2", NULL,
+NULL /* ospke */, "waitpkg", "avx512vbmi2", NULL,
 "gfni", "vaes", "vpclmulqdq", "avx512vnni",
 "avx512bitalg", NULL, "avx512-vpopcntdq", NULL,
 "la57", NULL, NULL, NULL,
@@ -5227,6 +5227,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error 
**errp)
 host_cpuid(5, 0, &cpu->mwait.eax, &cpu->mwait.ebx,
&cpu->mwait.ecx, &cpu->mwait.edx);
 env->features[FEAT_1_ECX] |= CPUID_EXT_MONITOR;
+env->features[FEAT_7_0_ECX] |= CPUID_7_0_ECX_WAITPKG;
 }
 }
 
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 5f6e3a029a..33a0b8b365 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -673,6 +673,7 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
 #define CPUID_7_0_ECX_UMIP (1U << 2)
 #define CPUID_7_0_ECX_PKU  (1U << 3)
 #define CPUID_7_0_ECX_OSPKE(1U << 4)
+#define CPUID_7_0_ECX_WAITPKG  (1U << 5) /* UMONITOR/UMWAIT/TPAUSE 
Instructions */
 #define CPUID_7_0_ECX_VBMI2(1U << 6) /* Additional VBMI Instrs */
 #define CPUID_7_0_ECX_GFNI (1U << 8)
 #define CPUID_7_0_ECX_VAES (1U << 9)
diff --git a/target/i386/kvm.c b/target/i386/kvm.c
index 92069099ab..ea9a87bfd8 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -400,6 +400,12 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, 
uint32_t function,
 if (host_tsx_blacklisted()) {
 ret &= ~(CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_HLE);
 }
+} else if (function == 7 && index == 0 && reg == R_ECX) {
+if (enable_cpu_pm) {
+ret |= CPUID_7_0_ECX_WAITPKG;
+} else {
+ret &= ~CPUID_7_0_ECX_WAITPKG;
+}
 } else if (function == 7 && index == 0 && reg == R_EDX) {
 /*
  * Linux v4.17-v4.20 incorrectly return ARCH_CAPABILITIES on SVM hosts.
-- 
2.20.1




[PATCH v5 0/2] x86: Enable user wait instructions

2019-09-28 Thread Tao Xu
UMONITOR, UMWAIT and TPAUSE are a set of user wait instructions.

UMONITOR arms address monitoring hardware using an address. A store
to an address within the specified address range triggers the
monitoring hardware to wake up the processor waiting in umwait.

UMWAIT instructs the processor to enter an implementation-dependent
optimized state while monitoring a range of addresses. The optimized
state may be either a light-weight power/performance optimized state
(c0.1 state) or an improved power/performance optimized state
(c0.2 state).

TPAUSE instructs the processor to enter an implementation-dependent
optimized state c0.1 or c0.2 state and wake up when time-stamp counter
reaches specified timeout.

Availability of the user wait instructions is indicated by the presence
of the CPUID feature flag WAITPKG CPUID.0x07.0x0:ECX[5].

The patches enable the umonitor, umwait and tpause features in KVM.
Because umwait and tpause can put a (psysical) CPU into a power saving
state, by default we dont't expose it in kvm and provide a capability to
enable it. Use kvm capability to enable UMONITOR, UMWAIT and TPAUSE when
QEMU use "-overcommit cpu-pm=on, a VM can use UMONITOR, UMWAIT and TPAUSE
instructions. If the instruction causes a delay, the amount of time
delayed is called here the physical delay. The physical delay is first
computed by determining the virtual delay (the time to delay relative to
the VM’s timestamp counter). Otherwise, UMONITOR, UMWAIT and TPAUSE cause
an invalid-opcode exception(#UD).

The release document ref below link:
https://software.intel.com/sites/default/files/\
managed/39/c5/325462-sdm-vol-1-2abcd-3abcd.pdf

Changelog:
v5:
Remove CPUID_7_0_ECX_WAITPKG if enable_cpu_pm is not set. (Paolo)
v4:
Set IA32_UMWAIT_CONTROL 32bits
v3:
Simplify the patches, expose user wait instructions when the guest
has CPUID (Paolo)
v2:
Separated from the series
https://www.mail-archive.com/qemu-devel@nongnu.org/msg549526.html
Use kvm capability to enable UMONITOR, UMWAIT and TPAUSE when
QEMU use "-overcommit cpu-pm=on"
v1:
Sent out with MOVDIRI/MOVDIR64B instructions patches

Tao Xu (2):
  x86/cpu: Add support for UMONITOR/UMWAIT/TPAUSE
  target/i386: Add support for save/load IA32_UMWAIT_CONTROL MSR

 target/i386/cpu.c |  3 ++-
 target/i386/cpu.h |  3 +++
 target/i386/kvm.c | 19 +++
 target/i386/machine.c | 20 
 4 files changed, 44 insertions(+), 1 deletion(-)

-- 
2.20.1




[PATCH v5 2/2] target/i386: Add support for save/load IA32_UMWAIT_CONTROL MSR

2019-09-28 Thread Tao Xu
UMWAIT and TPAUSE instructions use 32bits IA32_UMWAIT_CONTROL at MSR
index E1H to determines the maximum time in TSC-quanta that the processor
can reside in either C0.1 or C0.2.

This patch is to Add support for save/load IA32_UMWAIT_CONTROL MSR in
guest.

Co-developed-by: Jingqi Liu 
Signed-off-by: Jingqi Liu 
Signed-off-by: Tao Xu 
---

No changes in v5.

Changes in v4:
Set IA32_UMWAIT_CONTROL 32bits
---
 target/i386/cpu.h |  2 ++
 target/i386/kvm.c | 13 +
 target/i386/machine.c | 20 
 3 files changed, 35 insertions(+)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 33a0b8b365..bcd1cbbfc0 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -451,6 +451,7 @@ typedef enum X86Seg {
 
 #define MSR_IA32_BNDCFGS0x0d90
 #define MSR_IA32_XSS0x0da0
+#define MSR_IA32_UMWAIT_CONTROL 0xe1
 
 #define XSTATE_FP_BIT   0
 #define XSTATE_SSE_BIT  1
@@ -1393,6 +1394,7 @@ typedef struct CPUX86State {
 uint16_t fpregs_format_vmstate;
 
 uint64_t xss;
+uint32_t umwait;
 
 TPRAccess tpr_access_type;
 
diff --git a/target/i386/kvm.c b/target/i386/kvm.c
index ea9a87bfd8..8b715af8eb 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -95,6 +95,7 @@ static bool has_msr_hv_stimer;
 static bool has_msr_hv_frequencies;
 static bool has_msr_hv_reenlightenment;
 static bool has_msr_xss;
+static bool has_msr_umwait;
 static bool has_msr_spec_ctrl;
 static bool has_msr_virt_ssbd;
 static bool has_msr_smi_count;
@@ -1909,6 +1910,9 @@ static int kvm_get_supported_msrs(KVMState *s)
 case MSR_IA32_XSS:
 has_msr_xss = true;
 break;
+case MSR_IA32_UMWAIT_CONTROL:
+has_msr_umwait = true;
+break;
 case HV_X64_MSR_CRASH_CTL:
 has_msr_hv_crash = true;
 break;
@@ -2459,6 +2463,9 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
 if (has_msr_xss) {
 kvm_msr_entry_add(cpu, MSR_IA32_XSS, env->xss);
 }
+if (has_msr_umwait) {
+kvm_msr_entry_add(cpu, MSR_IA32_UMWAIT_CONTROL, env->umwait);
+}
 if (has_msr_spec_ctrl) {
 kvm_msr_entry_add(cpu, MSR_IA32_SPEC_CTRL, env->spec_ctrl);
 }
@@ -2863,6 +2870,9 @@ static int kvm_get_msrs(X86CPU *cpu)
 if (has_msr_xss) {
 kvm_msr_entry_add(cpu, MSR_IA32_XSS, 0);
 }
+if (has_msr_umwait) {
+kvm_msr_entry_add(cpu, MSR_IA32_UMWAIT_CONTROL, 0);
+}
 if (has_msr_spec_ctrl) {
 kvm_msr_entry_add(cpu, MSR_IA32_SPEC_CTRL, 0);
 }
@@ -3115,6 +3125,9 @@ static int kvm_get_msrs(X86CPU *cpu)
 case MSR_IA32_XSS:
 env->xss = msrs[i].data;
 break;
+case MSR_IA32_UMWAIT_CONTROL:
+env->umwait = msrs[i].data;
+break;
 default:
 if (msrs[i].index >= MSR_MC0_CTL &&
 msrs[i].index < MSR_MC0_CTL + (env->mcg_cap & 0xff) * 4) {
diff --git a/target/i386/machine.c b/target/i386/machine.c
index 2767b3096d..6481f846f6 100644
--- a/target/i386/machine.c
+++ b/target/i386/machine.c
@@ -943,6 +943,25 @@ static const VMStateDescription vmstate_xss = {
 }
 };
 
+static bool umwait_needed(void *opaque)
+{
+X86CPU *cpu = opaque;
+CPUX86State *env = &cpu->env;
+
+return env->umwait != 0;
+}
+
+static const VMStateDescription vmstate_umwait = {
+.name = "cpu/umwait",
+.version_id = 1,
+.minimum_version_id = 1,
+.needed = umwait_needed,
+.fields = (VMStateField[]) {
+VMSTATE_UINT32(env.umwait, X86CPU),
+VMSTATE_END_OF_LIST()
+}
+};
+
 #ifdef TARGET_X86_64
 static bool pkru_needed(void *opaque)
 {
@@ -1391,6 +1410,7 @@ VMStateDescription vmstate_x86_cpu = {
 &vmstate_msr_hyperv_reenlightenment,
 &vmstate_avx512,
 &vmstate_xss,
+&vmstate_umwait,
 &vmstate_tsc_khz,
 &vmstate_msr_smi_count,
 #ifdef TARGET_X86_64
-- 
2.20.1




Re: [PATCH V2] intel_iommu: TM field should not be in reserved bits

2019-09-28 Thread Peter Xu
On Sun, Sep 29, 2019 at 01:11:12AM +, Zhang, Qi1 wrote:
> 
> 
> > -Original Message-
> > From: Peter Xu 
> > Sent: Friday, September 27, 2019 5:32 PM
> > To: Zhang, Qi1 
> > Cc: qemu-devel@nongnu.org; ehabk...@redhat.com; m...@redhat.com;
> > pbonz...@redhat.com; r...@twiddle.net; Qi, Yadong 
> > Subject: Re: [PATCH V2] intel_iommu: TM field should not be in reserved bits
> > 
> > On Fri, Sep 27, 2019 at 08:03:21AM +, Zhang, Qi1 wrote:
> > >
> > >
> > > > -Original Message-
> > > > From: Peter Xu 
> > > > Sent: Friday, September 27, 2019 2:10 PM
> > > > To: Zhang, Qi1 
> > > > Cc: qemu-devel@nongnu.org; ehabk...@redhat.com; m...@redhat.com;
> > > > pbonz...@redhat.com; r...@twiddle.net
> > > > Subject: Re: [PATCH V2] intel_iommu: TM field should not be in
> > > > reserved bits
> > > >
> > > > On Fri, Sep 27, 2019 at 12:58:38PM +0800, qi1.zh...@intel.com wrote:
> > > > > From: "Zhang, Qi" 
> > > > >
> > > > > When dt is supported, TM field should not be Reserved(0).
> > > > >
> > > > > Refer to VT-d Spec 9.8
> > > > >
> > > > > Signed-off-by: Zhang, Qi 
> > > > > Signed-off-by: Qi, Yadong 
> > > > > ---
> > > > >  hw/i386/intel_iommu.c  | 12 ++--
> > > > >  hw/i386/intel_iommu_internal.h | 25 +++--
> > > > >  2 files changed, 25 insertions(+), 12 deletions(-)
> > > > > ---
> > VTD_SPTE_PAGE_L2_RSVD_MASK(s-
> > > > >aw_bits);
> > > > > -vtd_paging_entry_rsvd_field[3] =
> > > > >aw_bits);
> > > > > +vtd_paging_entry_rsvd_field[5] =
> > > > VTD_SPTE_LPAGE_L1_RSVD_MASK(s->aw_bits, x86_iommu-
> > > > >dt_supported);
> > > > > +vtd_paging_entry_rsvd_field[6] =
> > > > VTD_SPTE_LPAGE_L2_RSVD_MASK(s->aw_bits, x86_iommu-
> > > > >dt_supported);
> > > > > +vtd_paging_entry_rsvd_field[7] =
> > > > > + VTD_SPTE_LPAGE_L3_RSVD_MASK(s->aw_bits, x86_iommu-
> > > > >dt_supported);
> > > > >  vtd_paging_entry_rsvd_field[8] =
> > > > >VTD_SPTE_LPAGE_L4_RSVD_MASK(s->aw_bits);
> > > >
> > > > Should this TM bit only affects leaves?  Say, entry 1 (4K), 5 (2M), 6 
> > > > (1G).

[1]

> > > > While this reminded me that I'm totally confused on why we have had
> > > > entry 7, 8 after all...  Are they really used?
> > > Yes. TM bit only affects. To this array, index 1, 5,6,7 may be leaf. Will 
> > > update
> > a new patchset for it.
> > 
> > Could I ask why index 7 may be leaf?
> Index 7 is PDPE 1G GB leaf.

I thought 1G was index 6.  I've listed my understanding above [1].
Would you please double confirm?  Thanks,

-- 
Peter Xu



Re: [PATCH v18 1/6] hw/arm/virt: Introduce RAS platform version and RAS machine option

2019-09-28 Thread Xiang Zheng



On 2019/9/27 22:02, Peter Maydell wrote:
> On Fri, 6 Sep 2019 at 09:33, Xiang Zheng  wrote:
>>
>> From: Dongjiu Geng 
>>
>> Support RAS Virtualization feature since version 4.2, disable it by
>> default in the old versions. Also add a machine option which allows user
>> to enable it explicitly.
>>
>> Signed-off-by: Dongjiu Geng 
>> Signed-off-by: Xiang Zheng 
>> ---
>>  hw/arm/virt.c | 33 +
>>  include/hw/arm/virt.h |  2 ++
>>  2 files changed, 35 insertions(+)
>>
>> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
>> index d74538b021..e0451433c8 100644
>> --- a/hw/arm/virt.c
>> +++ b/hw/arm/virt.c
>> @@ -1783,6 +1783,20 @@ static void virt_set_its(Object *obj, bool value, 
>> Error **errp)
>>  vms->its = value;
>>  }
>>
>> +static bool virt_get_ras(Object *obj, Error **errp)
>> +{
>> +VirtMachineState *vms = VIRT_MACHINE(obj);
>> +
>> +return vms->ras;
>> +}
>> +
>> +static void virt_set_ras(Object *obj, bool value, Error **errp)
>> +{
>> +VirtMachineState *vms = VIRT_MACHINE(obj);
>> +
>> +vms->ras = value;
>> +}
>> +
>>  static char *virt_get_gic_version(Object *obj, Error **errp)
>>  {
>>  VirtMachineState *vms = VIRT_MACHINE(obj);
>> @@ -2026,6 +2040,19 @@ static void virt_instance_init(Object *obj)
>>  "Valid values are none and smmuv3",
>>  NULL);
>>
>> +if (vmc->no_ras) {
>> +vms->ras = false;
>> +} else {
>> +/* Default disallows RAS instantiation */
>> +vms->ras = false;
>> +object_property_add_bool(obj, "ras", virt_get_ras,
>> + virt_set_ras, NULL);
>> +object_property_set_description(obj, "ras",
>> +"Set on/off to enable/disable "
>> +"RAS instantiation",
>> +NULL);
>> +}
> 
> For a property which is disabled by default, you don't need
> to have a separate flag in the VirtMachineClass struct.
> Those are only needed for properties where we need the old machine
> types to have the property be 'off' but new machine types
> need to default to it be 'on'. Since vms->ras is false
> by default anyway, you can just have this part:
> 
>> +/* Default disallows RAS instantiation */
>> +vms->ras = false;
>> +object_property_add_bool(obj, "ras", virt_get_ras,
>> + virt_set_ras, NULL);
>> +object_property_set_description(obj, "ras",
>> +"Set on/off to enable/disable "
>> +"RAS instantiation",
>> +NULL);
> 
> Compare the 'vms->secure' flag and associated property
> for an example of this.

Thanks for pointing it out, I will remove the no_ras in the VirtMachineClass 
struct.

> 
>>  vms->irqmap = a15irqmap;
>>
>>  virt_flash_create(vms);
>> @@ -2058,8 +2085,14 @@ DEFINE_VIRT_MACHINE_AS_LATEST(4, 2)
>>
>>  static void virt_machine_4_1_options(MachineClass *mc)
>>  {
>> +VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
>> +
>>  virt_machine_4_2_options(mc);
>>  compat_props_add(mc->compat_props, hw_compat_4_1, hw_compat_4_1_len);
>> +/* Disable memory recovery feature for 4.1 as RAS support was
>> + * introduced with 4.2.
>> + */
>> +vmc->no_ras = true;
>>  }
>>  DEFINE_VIRT_MACHINE(4, 1)
> 
> thanks
> -- PMM
> 
> .
> 

-- 

Thanks,
Xiang




RE: [PATCH V2] intel_iommu: TM field should not be in reserved bits

2019-09-28 Thread Zhang, Qi1


> -Original Message-
> From: Peter Xu 
> Sent: Sunday, September 29, 2019 10:02 AM
> To: Zhang, Qi1 
> Cc: qemu-devel@nongnu.org; ehabk...@redhat.com; m...@redhat.com;
> pbonz...@redhat.com; r...@twiddle.net; Qi, Yadong 
> Subject: Re: [PATCH V2] intel_iommu: TM field should not be in reserved bits
> 
> On Sun, Sep 29, 2019 at 01:11:12AM +, Zhang, Qi1 wrote:
> >
> >
> > > -Original Message-
> > > From: Peter Xu 
> > > Sent: Friday, September 27, 2019 5:32 PM
> > > To: Zhang, Qi1 
> > > Cc: qemu-devel@nongnu.org; ehabk...@redhat.com; m...@redhat.com;
> > > pbonz...@redhat.com; r...@twiddle.net; Qi, Yadong
> > > 
> > > Subject: Re: [PATCH V2] intel_iommu: TM field should not be in
> > > reserved bits
> > >
> > > On Fri, Sep 27, 2019 at 08:03:21AM +, Zhang, Qi1 wrote:
> > > >
> > > >
> > > > > -Original Message-
> > > > > From: Peter Xu 
> > > > > Sent: Friday, September 27, 2019 2:10 PM
> > > > > To: Zhang, Qi1 
> > > > > Cc: qemu-devel@nongnu.org; ehabk...@redhat.com;
> m...@redhat.com;
> > > > > pbonz...@redhat.com; r...@twiddle.net
> > > > > Subject: Re: [PATCH V2] intel_iommu: TM field should not be in
> > > > > reserved bits
> > > > >
> > > > > On Fri, Sep 27, 2019 at 12:58:38PM +0800, qi1.zh...@intel.com wrote:
> > > > > > From: "Zhang, Qi" 
> > > > > >
> > > > > > When dt is supported, TM field should not be Reserved(0).
> > > > > >
> > > > > > Refer to VT-d Spec 9.8
> > > > > >
> > > > > > Signed-off-by: Zhang, Qi 
> > > > > > Signed-off-by: Qi, Yadong 
> > > > > > ---
> > > > > >  hw/i386/intel_iommu.c  | 12 ++--
> > > > > >  hw/i386/intel_iommu_internal.h | 25 +++--
> > > > > >  2 files changed, 25 insertions(+), 12 deletions(-)
> > > > > > ---
> > > VTD_SPTE_PAGE_L2_RSVD_MASK(s-
> > > > > >aw_bits);
> > > > > > -vtd_paging_entry_rsvd_field[3] =
> > > > > >aw_bits);
> > > > > > +vtd_paging_entry_rsvd_field[5] =
> > > > > VTD_SPTE_LPAGE_L1_RSVD_MASK(s->aw_bits, x86_iommu-
> > > > > >dt_supported);
> > > > > > +vtd_paging_entry_rsvd_field[6] =
> > > > > VTD_SPTE_LPAGE_L2_RSVD_MASK(s->aw_bits, x86_iommu-
> > > > > >dt_supported);
> > > > > > +vtd_paging_entry_rsvd_field[7] =
> > > > > > + VTD_SPTE_LPAGE_L3_RSVD_MASK(s->aw_bits, x86_iommu-
> > > > > >dt_supported);
> > > > > >  vtd_paging_entry_rsvd_field[8] =
> > > > > >VTD_SPTE_LPAGE_L4_RSVD_MASK(s->aw_bits);
> > > > >
> > > > > Should this TM bit only affects leaves?  Say, entry 1 (4K), 5 (2M), 6
> (1G).
> 
> [1]
> 
> > > > > While this reminded me that I'm totally confused on why we have
> > > > > had entry 7, 8 after all...  Are they really used?
> > > > Yes. TM bit only affects. To this array, index 1, 5,6,7 may be
> > > > leaf. Will update
> > > a new patchset for it.
> > >
> > > Could I ask why index 7 may be leaf?
> > Index 7 is PDPE 1G GB leaf.
> 
> I thought 1G was index 6.  I've listed my understanding above [1].
> Would you please double confirm?  Thanks,
Check the existing function. When level is 3 VTD_SL_PDP_LEVEL and the entry is 
leaf, it is PDPE 1G leaf and the corresponding index of this array 7.

static bool vtd_slpte_nonzero_rsvd(uint64_t slpte, uint32_t level)
{
if (slpte & VTD_SL_PT_PAGE_SIZE_MASK) {
/* Maybe large page */
return slpte & vtd_paging_entry_rsvd_field[level + 4];
} else {
return slpte & vtd_paging_entry_rsvd_field[level];
}
}
> 
> --
> Peter Xu


Re: [PATCH V2] intel_iommu: TM field should not be in reserved bits

2019-09-28 Thread Peter Xu
On Sun, Sep 29, 2019 at 10:02:20AM +0800, Peter Xu wrote:
> On Sun, Sep 29, 2019 at 01:11:12AM +, Zhang, Qi1 wrote:
> > 
> > 
> > > -Original Message-
> > > From: Peter Xu 
> > > Sent: Friday, September 27, 2019 5:32 PM
> > > To: Zhang, Qi1 
> > > Cc: qemu-devel@nongnu.org; ehabk...@redhat.com; m...@redhat.com;
> > > pbonz...@redhat.com; r...@twiddle.net; Qi, Yadong 
> > > Subject: Re: [PATCH V2] intel_iommu: TM field should not be in reserved 
> > > bits
> > > 
> > > On Fri, Sep 27, 2019 at 08:03:21AM +, Zhang, Qi1 wrote:
> > > >
> > > >
> > > > > -Original Message-
> > > > > From: Peter Xu 
> > > > > Sent: Friday, September 27, 2019 2:10 PM
> > > > > To: Zhang, Qi1 
> > > > > Cc: qemu-devel@nongnu.org; ehabk...@redhat.com; m...@redhat.com;
> > > > > pbonz...@redhat.com; r...@twiddle.net
> > > > > Subject: Re: [PATCH V2] intel_iommu: TM field should not be in
> > > > > reserved bits
> > > > >
> > > > > On Fri, Sep 27, 2019 at 12:58:38PM +0800, qi1.zh...@intel.com wrote:
> > > > > > From: "Zhang, Qi" 
> > > > > >
> > > > > > When dt is supported, TM field should not be Reserved(0).
> > > > > >
> > > > > > Refer to VT-d Spec 9.8
> > > > > >
> > > > > > Signed-off-by: Zhang, Qi 
> > > > > > Signed-off-by: Qi, Yadong 
> > > > > > ---
> > > > > >  hw/i386/intel_iommu.c  | 12 ++--
> > > > > >  hw/i386/intel_iommu_internal.h | 25 +++--
> > > > > >  2 files changed, 25 insertions(+), 12 deletions(-)
> > > > > > ---
> > > VTD_SPTE_PAGE_L2_RSVD_MASK(s-
> > > > > >aw_bits);
> > > > > > -vtd_paging_entry_rsvd_field[3] =
> > > > > >aw_bits);
> > > > > > +vtd_paging_entry_rsvd_field[5] =
> > > > > VTD_SPTE_LPAGE_L1_RSVD_MASK(s->aw_bits, x86_iommu-
> > > > > >dt_supported);
> > > > > > +vtd_paging_entry_rsvd_field[6] =
> > > > > VTD_SPTE_LPAGE_L2_RSVD_MASK(s->aw_bits, x86_iommu-
> > > > > >dt_supported);
> > > > > > +vtd_paging_entry_rsvd_field[7] =
> > > > > > + VTD_SPTE_LPAGE_L3_RSVD_MASK(s->aw_bits, x86_iommu-
> > > > > >dt_supported);
> > > > > >  vtd_paging_entry_rsvd_field[8] =
> > > > > >VTD_SPTE_LPAGE_L4_RSVD_MASK(s->aw_bits);
> > > > >
> > > > > Should this TM bit only affects leaves?  Say, entry 1 (4K), 5 (2M), 6 
> > > > > (1G).
> 
> [1]
> 
> > > > > While this reminded me that I'm totally confused on why we have had
> > > > > entry 7, 8 after all...  Are they really used?
> > > > Yes. TM bit only affects. To this array, index 1, 5,6,7 may be leaf. 
> > > > Will update
> > > a new patchset for it.
> > > 
> > > Could I ask why index 7 may be leaf?
> > Index 7 is PDPE 1G GB leaf.
> 
> I thought 1G was index 6.  I've listed my understanding above [1].
> Would you please double confirm?  Thanks,

Oh wait, You are right...  Index 6 should be for 1G because index 5
seems to be unused as well.  However then again we should drop 5
instead of 7?

I think we can do this in two patches:

Patch 1 to clean these up by only let vtd_paging_rsvd (we can rename
it to shorter one like this if going to touch it) to keep reserved
bits for non-huge pages.  Then we define a new struct
(e.g. vtd_paging_rsvd_huge) to only keep the huge page entries.  The
thing is that I see no point in keeping huge && non-huge in a single
array (and I believe that's why it caused confusion so far...). That
new one should be a size of 2 array.  Meanwhile we need to fix
vtd_slpte_nonzero_rsvd() too using the new arrays.

Then in patch 2 we do the DT bit change.

Does that look ok?

Thanks,

-- 
Peter Xu



Why on earth is this code giving me Segfaults?

2019-09-28 Thread Libo Zhou
Hi All,

I have a custom ISA that's based on MIPS. The LW and SW instructions' opcodes 
are changed into 0x17(OPC_BGTZL) and 0x1F(OPC_SPECIAL3).

I have made the following changes in target/mips/translate.c:

@@ -29331,7 +29331,11 @@ static void decode_opc(CPUMIPSState *env, DisasContext 
*ctx)
 decode_opc_special3(env, ctx);
 }
 #else
-decode_opc_special3(env, ctx);
+if (ctx->insn_flags & INSN_MYISA) {
+gen_st(ctx, OPC_SW, rt, rs, imm); /* OPC_MYISA_SW */
+} else {
+decode_opc_special3(env, ctx);
+}
 #endif
 break;
 case OPC_REGIMM:
@@ -29589,6 +29603,8 @@ static void decode_opc(CPUMIPSState *env, DisasContext 
*ctx)
 }
 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
+} else if (ctx->insn_flags & INSN_MYISA) {
+gen_ld(ctx, OPC_LW, rt, rs, imm); /* OPC_MYISA_LW */
 } else {
 /* OPC_BGTZL */
 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);

I used gdbstub to singlestep my program, and I found that my sw instruction is 
working fine, but lw gives me a segfault. I have been stuck on this for a long 
while, since it looks like I only need to add that one line of gen_ld function. 
I also tried debugging QEMU wtih gdb, but the segfault wasn't thrown 
immediately after lw instruction like gdbstub does.

Does anyone have any advice?

Thanks,
Libo Zhou

Re: [PATCH 01/14] hw/arm/raspi: Use the IEC binary prefix definitions

2019-09-28 Thread Esteban Bosse
El mié, 04-09-2019 a las 19:13 +0200, Philippe Mathieu-Daudé escribió:
> IEC binary prefixes ease code review: the unit is explicit.
> 
> Signed-off-by: Philippe Mathieu-Daudé 
> ---
>  hw/arm/raspi.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
> index 74c062d05e..615d755879 100644
> --- a/hw/arm/raspi.c
> +++ b/hw/arm/raspi.c
> @@ -230,7 +230,7 @@ static void raspi2_machine_init(MachineClass *mc)
>  mc->max_cpus = BCM283X_NCPUS;
>  mc->min_cpus = BCM283X_NCPUS;
>  mc->default_cpus = BCM283X_NCPUS;
> -mc->default_ram_size = 1024 * 1024 * 1024;
> +mc->default_ram_size = 1 * GiB;
>  mc->ignore_memory_transaction_failures = true;
>  };
>  DEFINE_MACHINE("raspi2", raspi2_machine_init)
> @@ -252,7 +252,7 @@ static void raspi3_machine_init(MachineClass *mc)
>  mc->max_cpus = BCM283X_NCPUS;
>  mc->min_cpus = BCM283X_NCPUS;
>  mc->default_cpus = BCM283X_NCPUS;
> -mc->default_ram_size = 1024 * 1024 * 1024;
> +mc->default_ram_size = 1 * GiB;
>  }
>  DEFINE_MACHINE("raspi3", raspi3_machine_init)
>  #endif

Reviewed-by: Esteban Bosse