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

2020-02-22 Thread no-reply
Patchew URL: 
https://patchew.org/QEMU/20200223065102.61652-1-ys...@users.sourceforge.jp/



Hi,

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

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

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

From https://github.com/patchew-project/qemu
 - [tag update]  patchew/20200223065102.61652-1-ys...@users.sourceforge.jp 
-> patchew/20200223065102.61652-1-ys...@users.sourceforge.jp
Switched to a new branch 'test'
d173993 qemu-doc.texi: Add RX section.
08d3f31 BootLinuxConsoleTest: Test the RX-Virt machine
140c2a9 Add rx-softmmu
b91da7c hw/rx: Restrict the RX62N microcontroller to the RX62N CPU core
a8a29a0 hw/rx: Honor -accel qtest
383596a hw/rx: RX Target hardware definition
dfecadf hw/char: RX62N serial communication interface (SCI)
72c1fb6 hw/timer: RX62N internal timer modules
6ef5b99 hw/intc: RX62N interrupt controller (ICUa)
7c9df96 target/rx: Dump bytes for each insn during disassembly
57a95b5 target/rx: Collect all bytes during disassembly
4c578dc target/rx: Emit all disassembly in one prt()
7c52762 target/rx: Use prt_ldmi for XCHG_mr disassembly
dabd7b8 target/rx: Replace operand with prt_ldmi in disassembler
cc845e0 target/rx: Disassemble rx_index_addr into a string
29fd721 target/rx: RX disassembler
c63fd90 target/rx: CPU definition
564ac35 target/rx: TCG helper
a7d0555 target/rx: TCG translation
edf076e hw/registerfields.h: Add 8bit and 16bit register macros
cdac152 qemu/bitops.h: Add extract8 and extract16
515473d MAINTAINERS: Add RX

=== OUTPUT BEGIN ===
1/22 Checking commit 515473d095ae (MAINTAINERS: Add RX)
2/22 Checking commit cdac152ea185 (qemu/bitops.h: Add extract8 and extract16)
3/22 Checking commit edf076e770e6 (hw/registerfields.h: Add 8bit and 16bit 
register macros)
Use of uninitialized value in concatenation (.) or string at 
./scripts/checkpatch.pl line 2495.
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 a7d0555170f7 (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 564ac3576864 (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 c63fd90cc1dd (target/rx: CPU definition)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#22: 
new file mode 100644

total: 0 errors, 1 warnings, 659 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 29fd721eed0f (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 cc845e0092bf (target/rx: Disassemble rx_index_addr into a 
string)
9/22 Checking commit dabd7b8f7abb (target/rx: Replace operand with prt_ldmi in 
disassembler)
10/22 Checking commit 7c52762b41d2 (target/rx: Use prt_ldmi for XCHG_mr 
disassembly)
11/22 Checking commit 4c578dc81272 (target/rx: Emit all disassembly in one 
prt())
12/22 Checking commit 57a95b515b8c (target/rx: Collect all bytes during 
disassembly)
13/22 Checking commit 7c9df9686b25 (target/rx: Dump bytes for each insn 

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

2020-02-22 Thread no-reply
Patchew URL: 
https://patchew.org/QEMU/20200223065102.61652-1-ys...@users.sourceforge.jp/



Hi,

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

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

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

From https://github.com/patchew-project/qemu
 - [tag update]  patchew/20200223065102.61652-1-ys...@users.sourceforge.jp 
-> patchew/20200223065102.61652-1-ys...@users.sourceforge.jp
Switched to a new branch 'test'
207fda1 qemu-doc.texi: Add RX section.
1d2f2ed BootLinuxConsoleTest: Test the RX-Virt machine
de2e11e Add rx-softmmu
534f2cc hw/rx: Restrict the RX62N microcontroller to the RX62N CPU core
5ced9d2 hw/rx: Honor -accel qtest
63f4519 hw/rx: RX Target hardware definition
95ec5ac hw/char: RX62N serial communication interface (SCI)
f087bf6 hw/timer: RX62N internal timer modules
9c1d3ea hw/intc: RX62N interrupt controller (ICUa)
3064ee8 target/rx: Dump bytes for each insn during disassembly
d95bde1 target/rx: Collect all bytes during disassembly
4cf6a3b target/rx: Emit all disassembly in one prt()
256823f target/rx: Use prt_ldmi for XCHG_mr disassembly
67672ed target/rx: Replace operand with prt_ldmi in disassembler
dc31fb3 target/rx: Disassemble rx_index_addr into a string
01690ad target/rx: RX disassembler
f30ec96 target/rx: CPU definition
d2d394c target/rx: TCG helper
35f89fa target/rx: TCG translation
0306f20 hw/registerfields.h: Add 8bit and 16bit register macros
8750517 qemu/bitops.h: Add extract8 and extract16
8e03a10 MAINTAINERS: Add RX

=== OUTPUT BEGIN ===
1/22 Checking commit 8e03a1004db2 (MAINTAINERS: Add RX)
2/22 Checking commit 875051703f0c (qemu/bitops.h: Add extract8 and extract16)
3/22 Checking commit 0306f201fabd (hw/registerfields.h: Add 8bit and 16bit 
register macros)
Use of uninitialized value in concatenation (.) or string at 
./scripts/checkpatch.pl line 2495.
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 35f89fa2be21 (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 d2d394c6b3fa (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 f30ec963e940 (target/rx: CPU definition)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#22: 
new file mode 100644

total: 0 errors, 1 warnings, 659 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 01690adab631 (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 dc31fb3d7505 (target/rx: Disassemble rx_index_addr into a 
string)
9/22 Checking commit 67672edb237b (target/rx: Replace operand with prt_ldmi in 
disassembler)
10/22 Checking commit 256823f4a9c3 (target/rx: Use prt_ldmi for XCHG_mr 
disassembly)
11/22 Checking commit 4cf6a3b12d30 (target/rx: Emit all disassembly in one 
prt())
12/22 Checking commit d95bde1169a7 (target/rx: Collect all bytes during 
disassembly)
13/22 Checking commit 3064ee8af26b (target/rx: Dump bytes for each insn 

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

2020-02-22 Thread no-reply
Patchew URL: 
https://patchew.org/QEMU/20200223065102.61652-1-ys...@users.sourceforge.jp/



Hi,

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

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

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

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 - [tag update]  patchew/20200223065102.61652-1-ys...@users.sourceforge.jp 
-> patchew/20200223065102.61652-1-ys...@users.sourceforge.jp
Switched to a new branch 'test'
79472fc qemu-doc.texi: Add RX section.
bd371ff BootLinuxConsoleTest: Test the RX-Virt machine
c75b5f4 Add rx-softmmu
bf2e2bc hw/rx: Restrict the RX62N microcontroller to the RX62N CPU core
b7dfe3b hw/rx: Honor -accel qtest
339fc1d hw/rx: RX Target hardware definition
c128024 hw/char: RX62N serial communication interface (SCI)
25d3642 hw/timer: RX62N internal timer modules
e5bcfcc hw/intc: RX62N interrupt controller (ICUa)
f3ed420 target/rx: Dump bytes for each insn during disassembly
d91d5de target/rx: Collect all bytes during disassembly
af1f29d target/rx: Emit all disassembly in one prt()
139d128 target/rx: Use prt_ldmi for XCHG_mr disassembly
ce57f2b target/rx: Replace operand with prt_ldmi in disassembler
6b42450 target/rx: Disassemble rx_index_addr into a string
2c0ad18 target/rx: RX disassembler
d9a2091 target/rx: CPU definition
40b7889 target/rx: TCG helper
66a8864 target/rx: TCG translation
baa046c hw/registerfields.h: Add 8bit and 16bit register macros
937a129 qemu/bitops.h: Add extract8 and extract16
223e016 MAINTAINERS: Add RX

=== OUTPUT BEGIN ===
1/22 Checking commit 223e0168cb67 (MAINTAINERS: Add RX)
2/22 Checking commit 937a12933240 (qemu/bitops.h: Add extract8 and extract16)
3/22 Checking commit baa046c7e9c4 (hw/registerfields.h: Add 8bit and 16bit 
register macros)
Use of uninitialized value in concatenation (.) or string at 
./scripts/checkpatch.pl line 2495.
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 66a88645bcf3 (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 40b78890b8cc (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 d9a209123c2b (target/rx: CPU definition)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#22: 
new file mode 100644

total: 0 errors, 1 warnings, 659 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 2c0ad1854322 (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 6b424507906f (target/rx: Disassemble rx_index_addr into a 
string)
9/22 Checking commit ce57f2b3ff96 (target/rx: Replace operand with prt_ldmi in 
disassembler)
10/22 Checking commit 139d1286a3fe (target/rx: Use prt_ldmi for XCHG_mr 
disassembly)
11/22 Checking commit af1f29d9b29c (target/rx: Emit all disassembly in one 
prt())
12/22 Checking commit d91d5de6744b (target/rx: Collect all bytes during 
disassembly)
13/22 Checking commit 

Re: [PATCH] hw/ide: Remove status register read side effect

2020-02-22 Thread jasper.lowell
I'm having another look at the SET_FEATURE Solaris 10 error. I've
enabled tracing and I see the following. The pci_cfg_read that shows up
at the end continues a few thousand times(?) but I've omitted it. This
appears to time out or something and then Solaris gives up on the
device.

ide_ioport_read 41.468 pid=147030 addr=0x7 reg=b'Status' val=0x0
bus=0x55b77f922d10 s=0x55b77f
923168
ide_ioport_write 19.677 pid=147030 addr=0x6 reg=b'Device/Head' val=0xe0
bus=0x55b77f922d10 s=0
x55b77f923168
ide_ioport_write 19.417 pid=147030 addr=0x1 reg=b'Features' val=0x3
bus=0x55b77f922d10 s=0x55b
77f922d98
ide_ioport_write 9.027 pid=147030 addr=0x2 reg=b'Sector Count' val=0x42
bus=0x55b77f922d10 s=0
x55b77f922d98
ide_ioport_write 8.025 pid=147030 addr=0x7 reg=b'Command' val=0xef
bus=0x55b77f922d10 s=0x55b7
7f922d98
ide_exec_cmd 0.461 pid=147030 bus=0x55b77f922d10 state=0x55b77f922d98
cmd=0xef
pci_cfg_read 53.231 pid=147030 dev=b'cmd646-ide' devid=0x3 fnid=0x0
offs=0x50 val=0x4
ide_ioport_read 35.577 pid=147030 addr=0x7 reg=b'Status' val=0x50
bus=0x55b77f922d10 s=0x55b77
f922d98
ide_ioport_read 29.095 pid=147030 addr=0x7 reg=b'Status' val=0x50
bus=0x55b77f922d10 s=0x55b77
f922d98
ide_ioport_write 19.146 pid=147030 addr=0x6 reg=b'Device/Head' val=0xe0
bus=0x55b77f922d10 s=0
x55b77f922d98
pci_cfg_read 9.468 pid=147030 dev=b'cmd646-ide' devid=0x3 fnid=0x0
offs=0x50 val=0x0
pci_cfg_read 127.712 pid=147030 dev=b'cmd646-ide' devid=0x3 fnid=0x0
offs=0x50 val=0x0
pci_cfg_read 101.942 pid=147030 dev=b'cmd646-ide' devid=0x3 fnid=0x0
offs=0x50 val=0x0
pci_cfg_read 101.793 pid=147030 dev=b'cmd646-ide' devid=0x3 fnid=0x0
offs=0x50 val=0x0
pci_cfg_read 101.852 pid=147030 dev=b'cmd646-ide' devid=0x3 fnid=0x0
offs=0x50 val=0x0
pci_cfg_read 101.803 pid=147030 dev=b'cmd646-ide' devid=0x3 fnid=0x0
offs=0x50 val=0x0
pci_cfg_read 101.762 pid=147030 dev=b'cmd646-ide' devid=0x3 fnid=0x0
offs=0x50 val=0x0
pci_cfg_read 105.219 pid=147030 dev=b'cmd646-ide' devid=0x3 fnid=0x0
offs=0x50 val=0x0
pci_cfg_read 102.634 pid=147030 dev=b'cmd646-ide' devid=0x3 fnid=0x0
offs=0x50 val=0x0
pci_cfg_read 101.943 pid=147030 dev=b'cmd646-ide' devid=0x3 fnid=0x0
offs=0x50 val=0x0
pci_cfg_read 101.883 pid=147030 dev=b'cmd646-ide' devid=0x3 fnid=0x0
offs=0x50 val=0x0
pci_cfg_read 101.792 pid=147030 dev=b'cmd646-ide' devid=0x3 fnid=0x0
offs=0x50 val=0x0

It looks like I've made mistakes in previous comments about the error
and what the problem might be. Excuse my inexperience. Rather than
spinning on ARTTIM23_INTR_CH1 it might be the case that Solaris 10 is
spinning on CFR_INTR_CH0. I think this because of the following trace:

pci_cfg_read 53.231 pid=147030 dev=b'cmd646-ide' devid=0x3 fnid=0x0
offs=0x50 val=0x4

The two reads on the io status register show that DRDY (drive ready
indicator bit) and DSC (drive seek complete bit). This doesn't look
unusual to me. The error bit is also not set which is reassuring.

I read through some of 
ftp://ftp.seagate.com/pub/acrobat/reference/111-1c.pdf and I'm confused
by the discussion regarding interrupts and the status register.

> INTRQ is cleared when the host reads the status register.

My understand is that INTRQ is the signal from pin 31 on the drive and
that the status register is on the drive. I understand the quoted
statement as when the host (CMD646) reads the status register of the
drive, the drive will lower the interrupt on this pin.

The CMD646 has CFR_INTR_CH0 and ARTTIM23_INTR_CH1 in it's PCI
configuration space. This is necessary to determine the source of an
interrupt when the CMD646 ports are in PCI IDE Native Mode. Are we
saying that when the drive lowers the interrupt, the CMD646 sees this
and then clears CFR_INTR_CH0 and ARTTIM23_INTR_CH1 automatically? If
this were the case then I don't know why there is an interface to clear
them by writing to them.

Also, if reading the ioport status register was enough to clear
CFR_INTR_CH0 and ARTTIM23_INTR_CH1 (specific to CMD646) I can't reason
why Linux, Solaris, and OpenBSD would have specific routines to clear
them (following the CMD646 documentation) rather than just reading the
ioport status register.

With the patch, the tracing output changes to this:
ide_ioport_read 128.512 pid=162907 addr=0x7 reg=b'Status' val=0x0
bus=0x55909512bd10 s=0x55909512c168
ide_ioport_write 22.622 pid=162907 addr=0x6 reg=b'Device/Head' val=0xe0
bus=0x55909512bd10 s=0x55909512c168
ide_ioport_write 21.330 pid=162907 addr=0x1 reg=b'Features' val=0x3
bus=0x55909512bd10 s=0x55909512bd98
ide_ioport_write 13.926 pid=162907 addr=0x2 reg=b'Sector Count'
val=0x42 bus=0x55909512bd10 s=0x55909512bd98
ide_ioport_write 9.278 pid=162907 addr=0x7 reg=b'Command' val=0xef
bus=0x55909512bd10 s=0x55909512bd98
ide_exec_cmd 0.921 pid=162907 bus=0x55909512bd10 state=0x55909512bd98
cmd=0xef
pci_cfg_read 40.647 pid=162907 dev=b'cmd646-ide' devid=0x3 fnid=0x0
offs=0x50 val=0x4
ide_ioport_read 40.445 pid=162907 addr=0x7 reg=b'Status' val=0x50
bus=0x55909512bd10 s=0x55909512bd98
ide_ioport_read 31.580 

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

2020-02-22 Thread no-reply
Patchew URL: 
https://patchew.org/QEMU/20200223065102.61652-1-ys...@users.sourceforge.jp/



Hi,

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

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

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

From https://github.com/patchew-project/qemu
 * [new tag] patchew/20200223065102.61652-1-ys...@users.sourceforge.jp 
-> patchew/20200223065102.61652-1-ys...@users.sourceforge.jp
Switched to a new branch 'test'
98aae80 qemu-doc.texi: Add RX section.
c084aad BootLinuxConsoleTest: Test the RX-Virt machine
d38442f Add rx-softmmu
b518869 hw/rx: Restrict the RX62N microcontroller to the RX62N CPU core
3649961 hw/rx: Honor -accel qtest
a354c0e hw/rx: RX Target hardware definition
279d917 hw/char: RX62N serial communication interface (SCI)
47f494d hw/timer: RX62N internal timer modules
f92e9ad hw/intc: RX62N interrupt controller (ICUa)
08a2021 target/rx: Dump bytes for each insn during disassembly
18cbc61 target/rx: Collect all bytes during disassembly
accb127 target/rx: Emit all disassembly in one prt()
7819841 target/rx: Use prt_ldmi for XCHG_mr disassembly
d2a8b8d target/rx: Replace operand with prt_ldmi in disassembler
5281766 target/rx: Disassemble rx_index_addr into a string
1c44ec2 target/rx: RX disassembler
28cd499 target/rx: CPU definition
7128a45 target/rx: TCG helper
a6df174 target/rx: TCG translation
bed06eb hw/registerfields.h: Add 8bit and 16bit register macros
862b2a3 qemu/bitops.h: Add extract8 and extract16
aa57148 MAINTAINERS: Add RX

=== OUTPUT BEGIN ===
1/22 Checking commit aa5714805044 (MAINTAINERS: Add RX)
2/22 Checking commit 862b2a3f68b6 (qemu/bitops.h: Add extract8 and extract16)
3/22 Checking commit bed06eb00edb (hw/registerfields.h: Add 8bit and 16bit 
register macros)
Use of uninitialized value in concatenation (.) or string at 
./scripts/checkpatch.pl line 2495.
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 a6df17471dbc (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 7128a45b6a9b (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 28cd4994482f (target/rx: CPU definition)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#22: 
new file mode 100644

total: 0 errors, 1 warnings, 659 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 1c44ec22dd4a (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 5281766b6573 (target/rx: Disassemble rx_index_addr into a 
string)
9/22 Checking commit d2a8b8d65cbe (target/rx: Replace operand with prt_ldmi in 
disassembler)
10/22 Checking commit 7819841c2e13 (target/rx: Use prt_ldmi for XCHG_mr 
disassembly)
11/22 Checking commit accb127df60f (target/rx: Emit all disassembly in one 
prt())
12/22 Checking commit 18cbc6142921 (target/rx: Collect all bytes during 
disassembly)
13/22 Checking commit 08a20215da87 (target/rx: Dump bytes for each insn 

[PATCH v31 22/22] qemu-doc.texi: Add RX section.

2020-02-22 Thread Yoshinori Sato
Describe emulated target specification. And two examples.

Signed-off-by: Yoshinori Sato 
---
 qemu-doc.texi | 44 
 1 file changed, 44 insertions(+)

diff --git a/qemu-doc.texi b/qemu-doc.texi
index 33b9597b1d..d80a9c64f7 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -1719,6 +1719,7 @@ differences are mentioned in the following sections.
 * Microblaze System emulator::
 * SH4 System emulator::
 * Xtensa System emulator::
+* RX System emulator::
 @end menu
 
 @node PowerPC System emulator
@@ -2487,6 +2488,49 @@ so should only be used with trusted guest OS.
 
 @c man end
 
+@node RX System emulator
+@section RX System emulator
+@cindex system emulation (RX)
+
+Use the executable @file{qemu-system-rx} to simulate a Virtual RX target.
+This target emulated following devices.
+
+@itemize @minus
+@item
+R5F562N8 MCU
+@item
+On-chip memory (ROM 512KB, RAM 96KB)
+@item
+Interrupt Control Unit (ICUa)
+@item
+8Bit Timer x 1CH (TMR0,1)
+@item
+Compare Match Timer x 2CH (CMT0,1)
+@item
+Serial Communication Interface x 1CH (SCI0)
+@item
+External memory 16MByte
+@end itemize
+
+Example of @file{qemu-system-rx} usage for rx is shown below:
+
+Download @code{u-boot_image} from 
@url{https://osdn.net/users/ysato/pf/qemu/dl/u-boot.bin.gz}
+
+Start emulation of rx-virt:
+@example
+qemu-system-rx -bios @code{u-boot_image}
+@end example
+
+Download @code{kernel_image} from 
@url{https://osdn.net/users/ysato/pf/qemu/dl/zImage}
+
+Download @code{device_tree_blob} from 
@url{https://osdn.net/users/ysato/pf/qemu/dl/rx-virt.dtb}
+
+Start emulation of rx-virt:
+@example
+qemu-system-rx -kernel @code{kernel_image} -dtb @code{device_tree_blob} \
+  -append "earlycon"
+@end example
+
 @node QEMU User space emulator
 @chapter QEMU User space emulator
 
-- 
2.20.1




[PATCH v31 07/22] target/rx: RX disassembler

2020-02-22 Thread Yoshinori Sato
Signed-off-by: Yoshinori Sato 
Reviewed-by: Richard Henderson 
Tested-by: Philippe Mathieu-Daudé 
Message-Id: <20190607091116.49044-5-ys...@users.sourceforge.jp>
Signed-off-by: Richard Henderson 
---
 include/disas/dis-asm.h |5 +
 target/rx/disas.c   | 1480 +++
 2 files changed, 1485 insertions(+)
 create mode 100644 target/rx/disas.c

diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h
index f87f468809..c5f9fa08ab 100644
--- a/include/disas/dis-asm.h
+++ b/include/disas/dis-asm.h
@@ -226,6 +226,10 @@ enum bfd_architecture
 #define bfd_mach_nios2r22
   bfd_arch_lm32,   /* Lattice Mico32 */
 #define bfd_mach_lm32 1
+  bfd_arch_rx,   /* Renesas RX */
+#define bfd_mach_rx0x75
+#define bfd_mach_rx_v2 0x76
+#define bfd_mach_rx_v3 0x77
   bfd_arch_last
   };
 #define bfd_mach_s390_31 31
@@ -436,6 +440,7 @@ int print_insn_little_nios2 (bfd_vma, 
disassemble_info*);
 int print_insn_xtensa   (bfd_vma, disassemble_info*);
 int print_insn_riscv32  (bfd_vma, disassemble_info*);
 int print_insn_riscv64  (bfd_vma, disassemble_info*);
+int print_insn_rx(bfd_vma, disassemble_info *);
 
 #if 0
 /* Fetch the disassembler for a given BFD, if that support is available.  */
diff --git a/target/rx/disas.c b/target/rx/disas.c
new file mode 100644
index 00..8cada4825d
--- /dev/null
+++ b/target/rx/disas.c
@@ -0,0 +1,1480 @@
+/*
+ * Renesas RX Disassembler
+ *
+ * Copyright (c) 2019 Yoshinori Sato 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see .
+ */
+
+#include "qemu/osdep.h"
+#include "disas/dis-asm.h"
+#include "qemu/bitops.h"
+#include "cpu.h"
+
+typedef struct DisasContext {
+disassemble_info *dis;
+uint32_t addr;
+uint32_t pc;
+} DisasContext;
+
+
+static uint32_t decode_load_bytes(DisasContext *ctx, uint32_t insn,
+   int i, int n)
+{
+bfd_byte buf;
+while (++i <= n) {
+ctx->dis->read_memory_func(ctx->addr++, , 1, ctx->dis);
+insn |= buf << (32 - i * 8);
+}
+return insn;
+}
+
+static int32_t li(DisasContext *ctx, int sz)
+{
+int32_t addr;
+bfd_byte buf[4];
+addr = ctx->addr;
+
+switch (sz) {
+case 1:
+ctx->addr += 1;
+ctx->dis->read_memory_func(addr, buf, 1, ctx->dis);
+return (int8_t)buf[0];
+case 2:
+ctx->addr += 2;
+ctx->dis->read_memory_func(addr, buf, 2, ctx->dis);
+return ldsw_le_p(buf);
+case 3:
+ctx->addr += 3;
+ctx->dis->read_memory_func(addr, buf, 3, ctx->dis);
+return (int8_t)buf[2] << 16 | lduw_le_p(buf);
+case 0:
+ctx->addr += 4;
+ctx->dis->read_memory_func(addr, buf, 4, ctx->dis);
+return ldl_le_p(buf);
+default:
+g_assert_not_reached();
+}
+}
+
+static int bdsp_s(DisasContext *ctx, int d)
+{
+/*
+ * 0 -> 8
+ * 1 -> 9
+ * 2 -> 10
+ * 3 -> 3
+ * :
+ * 7 -> 7
+ */
+if (d < 3) {
+d += 8;
+}
+return d;
+}
+
+/* Include the auto-generated decoder.  */
+#include "decode.inc.c"
+
+#define prt(...) (ctx->dis->fprintf_func)((ctx->dis->stream), __VA_ARGS__)
+
+#define RX_MEMORY_BYTE 0
+#define RX_MEMORY_WORD 1
+#define RX_MEMORY_LONG 2
+
+#define RX_IM_BYTE 0
+#define RX_IM_WORD 1
+#define RX_IM_LONG 2
+#define RX_IM_UWORD 3
+
+static const char size[] = {'b', 'w', 'l'};
+static const char cond[][4] = {
+"eq", "ne", "c", "nc", "gtu", "leu", "pz", "n",
+"ge", "lt", "gt", "le", "o", "no", "ra", "f"
+};
+static const char psw[] = {
+'c', 'z', 's', 'o', 0, 0, 0, 0,
+'i', 'u', 0, 0, 0, 0, 0, 0,
+};
+
+static uint32_t rx_index_addr(int ld, int size, DisasContext *ctx)
+{
+bfd_byte buf[2];
+switch (ld) {
+case 0:
+return 0;
+case 1:
+ctx->dis->read_memory_func(ctx->addr, buf, 1, ctx->dis);
+ctx->addr += 1;
+return ((uint8_t)buf[0]) << size;
+case 2:
+ctx->dis->read_memory_func(ctx->addr, buf, 2, ctx->dis);
+ctx->addr += 2;
+return lduw_le_p(buf) << size;
+}
+g_assert_not_reached();
+}
+
+static void operand(DisasContext *ctx, int ld, int mi, int rs, int rd)
+{
+int dsp;
+static const char sizes[][4] = {".b", ".w", ".l", ".uw", ".ub"};
+if (ld < 3) {
+switch (mi) {
+case 4:
+/* dsp[rs].ub */
+dsp = rx_index_addr(ld, 

[PATCH v31 04/22] target/rx: TCG translation

2020-02-22 Thread Yoshinori Sato
This part only supported RXv1 instructions.
Instruction manual.
https://www.renesas.com/us/en/doc/products/mpumcu/doc/rx_family/r01us0032ej0120_rxsm.pdf

Signed-off-by: Yoshinori Sato 
Reviewed-by: Richard Henderson 
Tested-by: Philippe Mathieu-Daudé 
Message-Id: <20190607091116.49044-2-ys...@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/rx/insns.decode  |  621 ++
 target/rx/translate.c   | 2432 +++
 target/rx/Makefile.objs |   12 +
 3 files changed, 3065 insertions(+)
 create mode 100644 target/rx/insns.decode
 create mode 100644 target/rx/translate.c
 create mode 100644 target/rx/Makefile.objs

diff --git a/target/rx/insns.decode b/target/rx/insns.decode
new file mode 100644
index 00..232a61fc8e
--- /dev/null
+++ b/target/rx/insns.decode
@@ -0,0 +1,621 @@
+#
+# Renesas RX instruction decode definitions.
+#
+# Copyright (c) 2019 Richard Henderson 
+# Copyright (c) 2019 Yoshinori Sato 
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, see .
+#
+
+  cd dsp sz
+  dsp sz
+  rs
+rd rs
+rd imm
+   rd rs rs2
+   rd imm rs2
+rd rs ld mi
+rs ld mi imm
+rs ld mi rs2
+  ld sz rd cd
+
+%b1_bdsp   24:3 !function=bdsp_s
+
+@b1_bcnd_s  cd:1 ...dsp=%b1_bdsp sz=1
+@b1_bra_s   dsp=%b1_bdsp sz=1
+
+%b2_r_016:4
+%b2_li_2   18:2 !function=li
+%b2_li_8   24:2 !function=li
+%b2_dsp5_3 23:4 19:1
+
+@b2_rds   rd:4  rs=%b2_r_0
+@b2_rds_li    rd:4  rs2=%b2_r_0 imm=%b2_li_8
+@b2_rds_uimm4    imm:4 rd:4 rs2=%b2_r_0
+@b2_rs2_uimm4    imm:4 rs2:4rd=0
+@b2_rds_imm5    ... imm:5 rd:4  rs2=%b2_r_0
+@b2_rd_rs_li     rs2:4 rd:4 imm=%b2_li_8
+@b2_rd_ld_ub    .. ld:2 rs:4 rd:4   mi=4
+@b2_ld_imm3 .. ld:2 rs:4 . imm:3mi=4
+@b2_bcnd_b  cd:4 dsp:s8 sz=2
+@b2_bra_b    dsp:s8 sz=2
+
+
+
+%b3_r_08:4
+%b3_li_10  18:2 !function=li
+%b3_dsp5_8 23:1 16:4
+%b3_bdsp   8:s8 16:8
+
+@b3_rd_rs      rs:4 rd:4   
+@b3_rs_rd      rd:4 rs:4   
+@b3_rd_li       rd:4 \
+rs2=%b3_r_0 imm=%b3_li_10
+@b3_rd_ld    mi:2  ld:2 rs:4 rd:4  
+@b3_rd_ld_ub      .. ld:2 rs:4 rd:4 mi=4
+@b3_rd_ld_ul      .. ld:2 rs:4 rd:4 mi=2
+@b3_rd_rs_rs2     rd:4 rs:4 rs2:4  
+@b3_rds_imm5     ... imm:5 rd:4 rs2=%b3_r_0
+@b3_rd_rs_imm5   ... imm:5 rs2:4 rd:4  
+@b3_bcnd_w  ... cd:1    dsp=%b3_bdsp sz=3
+@b3_bra_w       dsp=%b3_bdsp sz=3
+@b3_ld_rd_rs      .. ld:2 rs:4 rd:4 mi=0
+@b3_sz_ld_rd_cd   sz:2 ld:2 rd:4 cd:4  
+
+
+
+%b4_li_18  18:2 !function=li
+%b4_dsp_16 0:s8 8:8
+%b4_bdsp   0:s8 8:8 16:8
+
+@b4_rd_ldmi  mi:2  ld:2   rs:4 rd:4
+@b4_bra_a          \
+dsp=%b4_bdsp sz=4
+
+# ABS rd
+ABS_rr 0111 1110 0010  @b2_rds
+# ABS rs, rd
+ABS_rr  1100       @b3_rd_rs
+
+# ADC #imm, rd
+ADC_ir  1101 0111 ..00 0010    @b3_rd_li
+# ADC rs, rd
+ADC_rr  1100  1011     @b3_rd_rs
+# ADC dsp[rs].l, rd
+# Note only mi==2 allowed.
+ADC_mr  0110 ..10 00..  0010   @b4_rd_ldmi
+
+# ADD #uimm4, rd
+ADD_irr0110 0010   @b2_rds_uimm4
+# ADD #imm, rs, rd
+ADD_irr0111 00..   @b2_rd_rs_li
+# ADD dsp[rs].ub, rd
+# ADD rs, rd
+ADD_mr 0100 10..   @b2_rd_ld_ub
+# ADD dsp[rs], rd
+ADD_mr  0110 ..00 10..     @b3_rd_ld
+# ADD rs, rs2, rd
+ADD_rrr  0010      @b3_rd_rs_rs2
+
+# 

[PATCH v31 20/22] Add rx-softmmu

2020-02-22 Thread Yoshinori Sato
Tested-by: Philippe Mathieu-Daudé 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Yoshinori Sato 
Message-Id: <20190607091116.49044-17-ys...@users.sourceforge.jp>
Signed-off-by: Richard Henderson 
pick ed65c02993 target/rx: Add RX to SysEmuTarget
pick 01372568ae tests: Add rx to machine-none-test.c
[PMD: Squashed patches from Richard Henderson modifying
  qapi/common.json and tests/machine-none-test.c]
Signed-off-by: Philippe Mathieu-Daudé 
---
 configure   | 11 ++-
 default-configs/rx-softmmu.mak  |  3 +++
 qapi/machine.json   |  2 +-
 include/exec/poison.h   |  1 +
 include/sysemu/arch_init.h  |  1 +
 arch_init.c |  2 ++
 tests/qtest/machine-none-test.c |  1 +
 hw/Kconfig  |  1 +
 8 files changed, 20 insertions(+), 2 deletions(-)
 create mode 100644 default-configs/rx-softmmu.mak

diff --git a/configure b/configure
index d57261e3ad..d852d7101d 100755
--- a/configure
+++ b/configure
@@ -4128,7 +4128,7 @@ fi
 fdt_required=no
 for target in $target_list; do
   case $target in
-
aarch64*-softmmu|arm*-softmmu|ppc*-softmmu|microblaze*-softmmu|mips64el-softmmu|riscv*-softmmu)
+
aarch64*-softmmu|arm*-softmmu|ppc*-softmmu|microblaze*-softmmu|mips64el-softmmu|riscv*-softmmu|rx-softmmu)
   fdt_required=yes
 ;;
   esac
@@ -7793,6 +7793,12 @@ case "$target_name" in
 mttcg=yes
 gdb_xml_files="riscv-64bit-cpu.xml riscv-32bit-fpu.xml riscv-64bit-fpu.xml 
riscv-64bit-csr.xml riscv-64bit-virtual.xml"
   ;;
+  rx)
+TARGET_ARCH=rx
+bflt="yes"
+target_compiler=$cross_cc_rx
+gdb_xml_files="rx-core.xml"
+  ;;
   sh4|sh4eb)
 TARGET_ARCH=sh4
 bflt="yes"
@@ -7974,6 +7980,9 @@ for i in $ARCH $TARGET_BASE_ARCH ; do
   riscv*)
 disas_config "RISCV"
   ;;
+  rx)
+disas_config "RX"
+  ;;
   s390*)
 disas_config "S390"
   ;;
diff --git a/default-configs/rx-softmmu.mak b/default-configs/rx-softmmu.mak
new file mode 100644
index 00..a3eecefb11
--- /dev/null
+++ b/default-configs/rx-softmmu.mak
@@ -0,0 +1,3 @@
+# Default configuration for rx-softmmu
+
+CONFIG_RX_VIRT=y
diff --git a/qapi/machine.json b/qapi/machine.json
index 6c11e3cf3a..40f8b9d872 100644
--- a/qapi/machine.json
+++ b/qapi/machine.json
@@ -26,7 +26,7 @@
   'data' : [ 'aarch64', 'alpha', 'arm', 'cris', 'hppa', 'i386', 'lm32',
  'm68k', 'microblaze', 'microblazeel', 'mips', 'mips64',
  'mips64el', 'mipsel', 'moxie', 'nios2', 'or1k', 'ppc',
- 'ppc64', 'riscv32', 'riscv64', 's390x', 'sh4',
+ 'ppc64', 'riscv32', 'riscv64', 'rx', 's390x', 'sh4',
  'sh4eb', 'sparc', 'sparc64', 'tricore', 'unicore32',
  'x86_64', 'xtensa', 'xtensaeb' ] }
 
diff --git a/include/exec/poison.h b/include/exec/poison.h
index 955eb863ab..7b9ac361dc 100644
--- a/include/exec/poison.h
+++ b/include/exec/poison.h
@@ -26,6 +26,7 @@
 #pragma GCC poison TARGET_PPC
 #pragma GCC poison TARGET_PPC64
 #pragma GCC poison TARGET_ABI32
+#pragma GCC poison TARGET_RX
 #pragma GCC poison TARGET_S390X
 #pragma GCC poison TARGET_SH4
 #pragma GCC poison TARGET_SPARC
diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h
index 62c6fe4cf1..6c011acc52 100644
--- a/include/sysemu/arch_init.h
+++ b/include/sysemu/arch_init.h
@@ -24,6 +24,7 @@ enum {
 QEMU_ARCH_NIOS2 = (1 << 17),
 QEMU_ARCH_HPPA = (1 << 18),
 QEMU_ARCH_RISCV = (1 << 19),
+QEMU_ARCH_RX = (1 << 20),
 };
 
 extern const uint32_t arch_type;
diff --git a/arch_init.c b/arch_init.c
index 705d0b94ad..d9eb0ec1dd 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -77,6 +77,8 @@ int graphic_depth = 32;
 #define QEMU_ARCH QEMU_ARCH_PPC
 #elif defined(TARGET_RISCV)
 #define QEMU_ARCH QEMU_ARCH_RISCV
+#elif defined(TARGET_RX)
+#define QEMU_ARCH QEMU_ARCH_RX
 #elif defined(TARGET_S390X)
 #define QEMU_ARCH QEMU_ARCH_S390X
 #elif defined(TARGET_SH4)
diff --git a/tests/qtest/machine-none-test.c b/tests/qtest/machine-none-test.c
index 5953d31755..8bb54a6360 100644
--- a/tests/qtest/machine-none-test.c
+++ b/tests/qtest/machine-none-test.c
@@ -56,6 +56,7 @@ static struct arch2cpu cpus_map[] = {
 { "hppa", "hppa" },
 { "riscv64", "rv64gcsu-v1.10.0" },
 { "riscv32", "rv32gcsu-v1.9.1" },
+{ "rx", "rx62n" },
 };
 
 static const char *get_cpu_model_by_arch(const char *arch)
diff --git a/hw/Kconfig b/hw/Kconfig
index ecf491bf04..62f9ebdc22 100644
--- a/hw/Kconfig
+++ b/hw/Kconfig
@@ -55,6 +55,7 @@ source nios2/Kconfig
 source openrisc/Kconfig
 source ppc/Kconfig
 source riscv/Kconfig
+source rx/Kconfig
 source s390x/Kconfig
 source sh4/Kconfig
 source sparc/Kconfig
-- 
2.20.1




[PATCH v31 15/22] hw/timer: RX62N internal timer modules

2020-02-22 Thread Yoshinori Sato
renesas_tmr: 8bit timer modules.
renesas_cmt: 16bit compare match timer modules.
This part use many renesas's CPU.
Hardware manual.
https://www.renesas.com/us/en/doc/products/mpumcu/doc/rx_family/r01uh0033ej0140_rx62n.pdf

Signed-off-by: Yoshinori Sato 
Reviewed-by: Alex Bennée 
Reviewed-by: Philippe Mathieu-Daudé 
Message-Id: <20190607091116.49044-7-ys...@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 include/hw/timer/renesas_cmt.h |  38 +++
 include/hw/timer/renesas_tmr.h |  53 
 hw/timer/renesas_cmt.c | 278 
 hw/timer/renesas_tmr.c | 458 +
 hw/timer/Kconfig   |   6 +
 hw/timer/Makefile.objs |   3 +
 6 files changed, 836 insertions(+)
 create mode 100644 include/hw/timer/renesas_cmt.h
 create mode 100644 include/hw/timer/renesas_tmr.h
 create mode 100644 hw/timer/renesas_cmt.c
 create mode 100644 hw/timer/renesas_tmr.c

diff --git a/include/hw/timer/renesas_cmt.h b/include/hw/timer/renesas_cmt.h
new file mode 100644
index 00..acd25c6e0b
--- /dev/null
+++ b/include/hw/timer/renesas_cmt.h
@@ -0,0 +1,38 @@
+/*
+ * Renesas Compare-match timer Object
+ *
+ * Copyright (c) 2019 Yoshinori Sato
+ *
+ * This code is licensed under the GPL version 2 or later.
+ *
+ */
+
+#ifndef HW_RENESAS_CMT_H
+#define HW_RENESAS_CMT_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_RENESAS_CMT "renesas-cmt"
+#define RCMT(obj) OBJECT_CHECK(RCMTState, (obj), TYPE_RENESAS_CMT)
+
+enum {
+CMT_CH = 2,
+CMT_NR_IRQ = 1 * CMT_CH,
+};
+
+typedef struct RCMTState {
+SysBusDevice parent_obj;
+
+uint64_t input_freq;
+MemoryRegion memory;
+
+uint16_t cmstr;
+uint16_t cmcr[CMT_CH];
+uint16_t cmcnt[CMT_CH];
+uint16_t cmcor[CMT_CH];
+int64_t tick[CMT_CH];
+qemu_irq cmi[CMT_CH];
+QEMUTimer *timer[CMT_CH];
+} RCMTState;
+
+#endif
diff --git a/include/hw/timer/renesas_tmr.h b/include/hw/timer/renesas_tmr.h
new file mode 100644
index 00..5787004c74
--- /dev/null
+++ b/include/hw/timer/renesas_tmr.h
@@ -0,0 +1,53 @@
+/*
+ * Renesas 8bit timer Object
+ *
+ * Copyright (c) 2018 Yoshinori Sato
+ *
+ * This code is licensed under the GPL version 2 or later.
+ *
+ */
+
+#ifndef HW_RENESAS_TMR_H
+#define HW_RENESAS_TMR_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_RENESAS_TMR "renesas-tmr"
+#define RTMR(obj) OBJECT_CHECK(RTMRState, (obj), TYPE_RENESAS_TMR)
+
+enum timer_event {
+cmia = 0,
+cmib = 1,
+ovi = 2,
+none = 3,
+TMR_NR_EVENTS = 4
+};
+
+enum {
+TMR_CH = 2,
+TMR_NR_IRQ = 3 * TMR_CH,
+};
+
+typedef struct RTMRState {
+SysBusDevice parent_obj;
+
+uint64_t input_freq;
+MemoryRegion memory;
+
+uint8_t tcnt[TMR_CH];
+uint8_t tcora[TMR_CH];
+uint8_t tcorb[TMR_CH];
+uint8_t tcr[TMR_CH];
+uint8_t tccr[TMR_CH];
+uint8_t tcor[TMR_CH];
+uint8_t tcsr[TMR_CH];
+int64_t tick;
+int64_t div_round[TMR_CH];
+enum timer_event next[TMR_CH];
+qemu_irq cmia[TMR_CH];
+qemu_irq cmib[TMR_CH];
+qemu_irq ovi[TMR_CH];
+QEMUTimer *timer[TMR_CH];
+} RTMRState;
+
+#endif
diff --git a/hw/timer/renesas_cmt.c b/hw/timer/renesas_cmt.c
new file mode 100644
index 00..574772b89b
--- /dev/null
+++ b/hw/timer/renesas_cmt.c
@@ -0,0 +1,278 @@
+/*
+ * Renesas 16bit Compare-match timer
+ *
+ * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware
+ * (Rev.1.40 R01UH0033EJ0140)
+ *
+ * Copyright (c) 2019 Yoshinori Sato
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see .
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "qemu/timer.h"
+#include "cpu.h"
+#include "hw/hw.h"
+#include "hw/irq.h"
+#include "hw/sysbus.h"
+#include "hw/registerfields.h"
+#include "hw/qdev-properties.h"
+#include "hw/timer/renesas_cmt.h"
+#include "migration/vmstate.h"
+#include "qemu/error-report.h"
+
+/*
+ *  +0 CMSTR - common control
+ *  +2 CMCR  - ch0
+ *  +4 CMCNT - ch0
+ *  +6 CMCOR - ch0
+ *  +8 CMCR  - ch1
+ * +10 CMCNT - ch1
+ * +12 CMCOR - ch1
+ * If we think that the address of CH 0 has an offset of +2,
+ * we can treat it with the same address as CH 1, so define it like that.
+ */
+REG16(CMSTR, 0)
+  FIELD(CMSTR, STR0, 0, 1)
+  FIELD(CMSTR, STR1, 1, 1)
+  FIELD(CMSTR, STR,  0, 2)
+/* This addeess is channel offset */
+REG16(CMCR, 0)
+  FIELD(CMCR, CKS, 0, 2)
+  FIELD(CMCR, CMIE, 6, 

[PATCH v31 14/22] hw/intc: RX62N interrupt controller (ICUa)

2020-02-22 Thread Yoshinori Sato
This implementation supported only ICUa.
Hardware manual.
https://www.renesas.com/us/en/doc/products/mpumcu/doc/rx_family/r01uh0033ej0140_rx62n.pdf

Signed-off-by: Yoshinori Sato 
Reviewed-by: Alex Bennée 
Reviewed-by: Philippe Mathieu-Daudé 
Message-Id: <20190607091116.49044-6-ys...@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 include/hw/intc/rx_icu.h |  56 ++
 hw/intc/rx_icu.c | 379 +++
 hw/intc/Kconfig  |   3 +
 hw/intc/Makefile.objs|   1 +
 4 files changed, 439 insertions(+)
 create mode 100644 include/hw/intc/rx_icu.h
 create mode 100644 hw/intc/rx_icu.c

diff --git a/include/hw/intc/rx_icu.h b/include/hw/intc/rx_icu.h
new file mode 100644
index 00..acfcf06aef
--- /dev/null
+++ b/include/hw/intc/rx_icu.h
@@ -0,0 +1,56 @@
+#ifndef RX_ICU_H
+#define RX_ICU_H
+
+#include "qemu-common.h"
+#include "hw/irq.h"
+
+enum TRG_MODE {
+TRG_LEVEL = 0,
+TRG_NEDGE = 1,  /* Falling */
+TRG_PEDGE = 2,  /* Raising */
+TRG_BEDGE = 3,  /* Both */
+};
+
+struct IRQSource {
+enum TRG_MODE sense;
+int level;
+};
+
+enum {
+/* Software interrupt request */
+SWI = 27,
+NR_IRQS = 256,
+};
+
+struct RXICUState {
+SysBusDevice parent_obj;
+
+MemoryRegion memory;
+struct IRQSource src[NR_IRQS];
+char *icutype;
+uint32_t nr_irqs;
+uint32_t *map;
+uint32_t nr_sense;
+uint32_t *init_sense;
+
+uint8_t ir[NR_IRQS];
+uint8_t dtcer[NR_IRQS];
+uint8_t ier[NR_IRQS / 8];
+uint8_t ipr[142];
+uint8_t dmasr[4];
+uint16_t fir;
+uint8_t nmisr;
+uint8_t nmier;
+uint8_t nmiclr;
+uint8_t nmicr;
+int req_irq;
+qemu_irq _irq;
+qemu_irq _fir;
+qemu_irq _swi;
+};
+typedef struct RXICUState RXICUState;
+
+#define TYPE_RXICU "rx-icu"
+#define RXICU(obj) OBJECT_CHECK(RXICUState, (obj), TYPE_RXICU)
+
+#endif /* RX_ICU_H */
diff --git a/hw/intc/rx_icu.c b/hw/intc/rx_icu.c
new file mode 100644
index 00..ab9a300467
--- /dev/null
+++ b/hw/intc/rx_icu.c
@@ -0,0 +1,379 @@
+/*
+ * RX Interrupt Control Unit
+ *
+ * Warning: Only ICUa is supported.
+ *
+ * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware
+ * (Rev.1.40 R01UH0033EJ0140)
+ *
+ * Copyright (c) 2019 Yoshinori Sato
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see .
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "cpu.h"
+#include "hw/hw.h"
+#include "hw/irq.h"
+#include "hw/sysbus.h"
+#include "hw/registerfields.h"
+#include "hw/qdev-properties.h"
+#include "hw/intc/rx_icu.h"
+#include "migration/vmstate.h"
+#include "qemu/error-report.h"
+
+REG8(IR, 0)
+  FIELD(IR, IR,  0, 1)
+REG8(DTCER, 0x100)
+  FIELD(DTCER, DTCE,  0, 1)
+REG8(IER, 0x200)
+REG8(SWINTR, 0x2e0)
+  FIELD(SWINTR, SWINT, 0, 1)
+REG16(FIR, 0x2f0)
+  FIELD(FIR, FVCT, 0, 8)
+  FIELD(FIR, FIEN, 15, 1)
+REG8(IPR, 0x300)
+  FIELD(IPR, IPR, 0, 4)
+REG8(DMRSR, 0x400)
+REG8(IRQCR, 0x500)
+  FIELD(IRQCR, IRQMD, 2, 2)
+REG8(NMISR, 0x580)
+  FIELD(NMISR, NMIST, 0, 1)
+  FIELD(NMISR, LVDST, 1, 1)
+  FIELD(NMISR, OSTST, 2, 1)
+REG8(NMIER, 0x581)
+  FIELD(NMIER, NMIEN, 0, 1)
+  FIELD(NMIER, LVDEN, 1, 1)
+  FIELD(NMIER, OSTEN, 2, 1)
+REG8(NMICLR, 0x582)
+  FIELD(NMICLR, NMICLR, 0, 1)
+  FIELD(NMICLR, OSTCLR, 2, 1)
+REG8(NMICR, 0x583)
+  FIELD(NMICR, NMIMD, 3, 1)
+
+#define request(icu, n) (icu->ipr[icu->map[n]] << 8 | n)
+
+static void set_irq(RXICUState *icu, int n_IRQ, int req)
+{
+if ((icu->fir & R_FIR_FIEN_MASK) &&
+(icu->fir & R_FIR_FVCT_MASK) == n_IRQ) {
+qemu_set_irq(icu->_fir, req);
+} else {
+qemu_set_irq(icu->_irq, req);
+}
+}
+
+static void rxicu_request(RXICUState *icu, int n_IRQ)
+{
+int enable;
+
+enable = icu->ier[n_IRQ / 8] & (1 << (n_IRQ & 7));
+if (n_IRQ > 0 && enable != 0 && atomic_read(>req_irq) < 0) {
+atomic_set(>req_irq, n_IRQ);
+set_irq(icu, n_IRQ, request(icu, n_IRQ));
+}
+}
+
+static void rxicu_set_irq(void *opaque, int n_IRQ, int level)
+{
+RXICUState *icu = opaque;
+struct IRQSource *src;
+int issue;
+
+if (n_IRQ >= NR_IRQS) {
+error_report("%s: IRQ %d out of range", __func__, n_IRQ);
+return;
+}
+
+src = >src[n_IRQ];
+
+level = (level != 0);
+switch (src->sense) {
+case TRG_LEVEL:
+/* level-sensitive irq */

[PATCH v31 05/22] target/rx: TCG helper

2020-02-22 Thread Yoshinori Sato
Signed-off-by: Yoshinori Sato 

Message-Id: <20190616142836.10614-3-ys...@users.sourceforge.jp>
Reviewed-by: Richard Henderson 
Message-Id: <20190607091116.49044-3-ys...@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
[PMD: Removed tlb_fill, extracted from patch of Yoshinori Sato
 'Convert to CPUClass::tlb_fill']
Signed-off-by: Philippe Mathieu-Daudé 
Signed-off-by: Yoshinori Sato 
---
 target/rx/helper.h|  31 +++
 target/rx/helper.c| 149 +
 target/rx/op_helper.c | 470 ++
 3 files changed, 650 insertions(+)
 create mode 100644 target/rx/helper.h
 create mode 100644 target/rx/helper.c
 create mode 100644 target/rx/op_helper.c

diff --git a/target/rx/helper.h b/target/rx/helper.h
new file mode 100644
index 00..f0b7ebbbf7
--- /dev/null
+++ b/target/rx/helper.h
@@ -0,0 +1,31 @@
+DEF_HELPER_1(raise_illegal_instruction, noreturn, env)
+DEF_HELPER_1(raise_access_fault, noreturn, env)
+DEF_HELPER_1(raise_privilege_violation, noreturn, env)
+DEF_HELPER_1(wait, noreturn, env)
+DEF_HELPER_1(debug, noreturn, env)
+DEF_HELPER_2(rxint, noreturn, env, i32)
+DEF_HELPER_1(rxbrk, noreturn, env)
+DEF_HELPER_FLAGS_3(fadd, TCG_CALL_NO_WG, f32, env, f32, f32)
+DEF_HELPER_FLAGS_3(fsub, TCG_CALL_NO_WG, f32, env, f32, f32)
+DEF_HELPER_FLAGS_3(fmul, TCG_CALL_NO_WG, f32, env, f32, f32)
+DEF_HELPER_FLAGS_3(fdiv, TCG_CALL_NO_WG, f32, env, f32, f32)
+DEF_HELPER_FLAGS_3(fcmp, TCG_CALL_NO_WG, void, env, f32, f32)
+DEF_HELPER_FLAGS_2(ftoi, TCG_CALL_NO_WG, i32, env, f32)
+DEF_HELPER_FLAGS_2(round, TCG_CALL_NO_WG, i32, env, f32)
+DEF_HELPER_FLAGS_2(itof, TCG_CALL_NO_WG, f32, env, i32)
+DEF_HELPER_2(set_fpsw, void, env, i32)
+DEF_HELPER_FLAGS_2(racw, TCG_CALL_NO_WG, void, env, i32)
+DEF_HELPER_FLAGS_2(set_psw_rte, TCG_CALL_NO_WG, void, env, i32)
+DEF_HELPER_FLAGS_2(set_psw, TCG_CALL_NO_WG, void, env, i32)
+DEF_HELPER_1(pack_psw, i32, env)
+DEF_HELPER_FLAGS_3(div, TCG_CALL_NO_WG, i32, env, i32, i32)
+DEF_HELPER_FLAGS_3(divu, TCG_CALL_NO_WG, i32, env, i32, i32)
+DEF_HELPER_FLAGS_1(scmpu, TCG_CALL_NO_WG, void, env)
+DEF_HELPER_1(smovu, void, env)
+DEF_HELPER_1(smovf, void, env)
+DEF_HELPER_1(smovb, void, env)
+DEF_HELPER_2(sstr, void, env, i32)
+DEF_HELPER_FLAGS_2(swhile, TCG_CALL_NO_WG, void, env, i32)
+DEF_HELPER_FLAGS_2(suntil, TCG_CALL_NO_WG, void, env, i32)
+DEF_HELPER_FLAGS_2(rmpa, TCG_CALL_NO_WG, void, env, i32)
+DEF_HELPER_1(satr, void, env)
diff --git a/target/rx/helper.c b/target/rx/helper.c
new file mode 100644
index 00..a6a337a311
--- /dev/null
+++ b/target/rx/helper.c
@@ -0,0 +1,149 @@
+/*
+ *  RX emulation
+ *
+ *  Copyright (c) 2019 Yoshinori Sato
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see .
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/bitops.h"
+#include "cpu.h"
+#include "exec/log.h"
+#include "exec/cpu_ldst.h"
+#include "sysemu/sysemu.h"
+#include "hw/irq.h"
+
+void rx_cpu_unpack_psw(CPURXState *env, uint32_t psw, int rte)
+{
+if (env->psw_pm == 0) {
+env->psw_ipl = FIELD_EX32(psw, PSW, IPL);
+if (rte) {
+/* PSW.PM can write RTE and RTFI */
+env->psw_pm = FIELD_EX32(psw, PSW, PM);
+}
+env->psw_u = FIELD_EX32(psw, PSW, U);
+env->psw_i = FIELD_EX32(psw, PSW, I);
+}
+env->psw_o = FIELD_EX32(psw, PSW, O) << 31;
+env->psw_s = FIELD_EX32(psw, PSW, S) << 31;
+env->psw_z = 1 - FIELD_EX32(psw, PSW, Z);
+env->psw_c = FIELD_EX32(psw, PSW, C);
+}
+
+#define INT_FLAGS (CPU_INTERRUPT_HARD | CPU_INTERRUPT_FIR)
+void rx_cpu_do_interrupt(CPUState *cs)
+{
+RXCPU *cpu = RXCPU(cs);
+CPURXState *env = >env;
+int do_irq = cs->interrupt_request & INT_FLAGS;
+uint32_t save_psw;
+
+env->in_sleep = 0;
+
+if (env->psw_u) {
+env->usp = env->regs[0];
+} else {
+env->isp = env->regs[0];
+}
+save_psw = rx_cpu_pack_psw(env);
+env->psw_pm = env->psw_i = env->psw_u = 0;
+
+if (do_irq) {
+if (do_irq & CPU_INTERRUPT_FIR) {
+env->bpc = env->pc;
+env->bpsw = save_psw;
+env->pc = env->fintv;
+env->psw_ipl = 15;
+cs->interrupt_request &= ~CPU_INTERRUPT_FIR;
+qemu_set_irq(env->ack, env->ack_irq);
+qemu_log_mask(CPU_LOG_INT, "fast interrupt raised\n");
+} else if (do_irq & CPU_INTERRUPT_HARD) {
+env->isp -= 4;
+

[PATCH v31 17/22] hw/rx: RX Target hardware definition

2020-02-22 Thread Yoshinori Sato
rx62n - RX62N cpu.
rx-virt - RX QEMU virtual target.

Signed-off-by: Yoshinori Sato 

Message-Id: <20190616142836.10614-17-ys...@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé 
Reviewed-by: Philippe Mathieu-Daudé 
Message-Id: <20190607091116.49044-9-ys...@users.sourceforge.jp>
Signed-off-by: Richard Henderson 
[PMD: Use TYPE_RX62N_CPU, use #define for RX62N_NR_TMR/CMT/SCI,
 renamed CPU -> MCU, device -> microcontroller]
Signed-off-by: Philippe Mathieu-Daudé 
---
v23 changes.
Add missing includes.

v21 changes.
rx_load_image move to rx-virt.c

v19: Fixed typo (Peter Maydell)
Signed-off-by: Yoshinori Sato 
---
 include/hw/rx/rx.h|   7 ++
 include/hw/rx/rx62n.h |  91 
 hw/rx/rx-virt.c   | 140 +
 hw/rx/rx62n.c | 239 ++
 hw/rx/Kconfig |  14 +++
 hw/rx/Makefile.objs   |   2 +
 6 files changed, 493 insertions(+)
 create mode 100644 include/hw/rx/rx.h
 create mode 100644 include/hw/rx/rx62n.h
 create mode 100644 hw/rx/rx-virt.c
 create mode 100644 hw/rx/rx62n.c
 create mode 100644 hw/rx/Kconfig
 create mode 100644 hw/rx/Makefile.objs

diff --git a/include/hw/rx/rx.h b/include/hw/rx/rx.h
new file mode 100644
index 00..ff5924b81f
--- /dev/null
+++ b/include/hw/rx/rx.h
@@ -0,0 +1,7 @@
+#ifndef QEMU_RX_H
+#define QEMU_RX_H
+/* Definitions for RX board emulation.  */
+
+#include "target/rx/cpu-qom.h"
+
+#endif
diff --git a/include/hw/rx/rx62n.h b/include/hw/rx/rx62n.h
new file mode 100644
index 00..97ea8ddb8e
--- /dev/null
+++ b/include/hw/rx/rx62n.h
@@ -0,0 +1,91 @@
+/*
+ * RX62N MCU Object
+ *
+ * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware
+ * (Rev.1.40 R01UH0033EJ0140)
+ *
+ * Copyright (c) 2019 Yoshinori Sato
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see .
+ */
+
+#ifndef HW_RX_RX62N_H
+#define HW_RX_RX62N_H
+
+#include "hw/sysbus.h"
+#include "hw/intc/rx_icu.h"
+#include "hw/timer/renesas_tmr.h"
+#include "hw/timer/renesas_cmt.h"
+#include "hw/char/renesas_sci.h"
+#include "target/rx/cpu.h"
+#include "qemu/units.h"
+
+#define TYPE_RX62N "rx62n"
+#define RX62N(obj) OBJECT_CHECK(RX62NState, (obj), TYPE_RX62N)
+
+#define RX62N_NR_TMR2
+#define RX62N_NR_CMT2
+#define RX62N_NR_SCI6
+
+typedef struct RX62NState {
+SysBusDevice parent_obj;
+
+RXCPU cpu;
+RXICUState icu;
+RTMRState tmr[RX62N_NR_TMR];
+RCMTState cmt[RX62N_NR_CMT];
+RSCIState sci[RX62N_NR_SCI];
+
+MemoryRegion *sysmem;
+bool kernel;
+
+MemoryRegion iram;
+MemoryRegion iomem1;
+MemoryRegion d_flash;
+MemoryRegion iomem2;
+MemoryRegion iomem3;
+MemoryRegion c_flash;
+qemu_irq irq[NR_IRQS];
+} RX62NState;
+
+/*
+ * RX62N Peripheral Address
+ * See users manual section 5
+ */
+#define RX62N_ICUBASE 0x00087000
+#define RX62N_TMRBASE 0x00088200
+#define RX62N_CMTBASE 0x00088000
+#define RX62N_SCIBASE 0x00088240
+
+/*
+ * RX62N Peripheral IRQ
+ * See users manual section 11
+ */
+#define RX62N_TMR_IRQBASE 174
+#define RX62N_CMT_IRQBASE 28
+#define RX62N_SCI_IRQBASE 214
+
+/*
+ * RX62N Internal Memory
+ * It is the value of R5F562N8.
+ * Please change the size for R5F562N7.
+ */
+#define RX62N_IRAM_BASE 0x
+#define RX62N_IRAM_SIZE (96 * KiB)
+#define RX62N_DFLASH_BASE 0x0010
+#define RX62N_DFLASH_SIZE (32 * KiB)
+#define RX62N_CFLASH_BASE 0xfff8
+#define RX62N_CFLASH_SIZE (512 * KiB)
+
+#define RX62N_PCLK (48 * 1000 * 1000)
+#endif
diff --git a/hw/rx/rx-virt.c b/hw/rx/rx-virt.c
new file mode 100644
index 00..b945be9f75
--- /dev/null
+++ b/hw/rx/rx-virt.c
@@ -0,0 +1,140 @@
+/*
+ * RX QEMU virtual platform
+ *
+ * Copyright (c) 2019 Yoshinori Sato
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see .
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "cpu.h"
+#include "hw/hw.h"

[PATCH v31 16/22] hw/char: RX62N serial communication interface (SCI)

2020-02-22 Thread Yoshinori Sato
This module supported only non FIFO type.
Hardware manual.
https://www.renesas.com/us/en/doc/products/mpumcu/doc/rx_family/r01uh0033ej0140_rx62n.pdf

Signed-off-by: Yoshinori Sato 
Reviewed-by: Alex Bennée 
Reviewed-by: Philippe Mathieu-Daudé 
Message-Id: <20190607091116.49044-8-ys...@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 include/hw/char/renesas_sci.h |  45 +
 hw/char/renesas_sci.c | 342 ++
 hw/char/Kconfig   |   3 +
 hw/char/Makefile.objs |   1 +
 4 files changed, 391 insertions(+)
 create mode 100644 include/hw/char/renesas_sci.h
 create mode 100644 hw/char/renesas_sci.c

diff --git a/include/hw/char/renesas_sci.h b/include/hw/char/renesas_sci.h
new file mode 100644
index 00..50d1336944
--- /dev/null
+++ b/include/hw/char/renesas_sci.h
@@ -0,0 +1,45 @@
+/*
+ * Renesas Serial Communication Interface
+ *
+ * Copyright (c) 2018 Yoshinori Sato
+ *
+ * This code is licensed under the GPL version 2 or later.
+ *
+ */
+
+#include "chardev/char-fe.h"
+#include "qemu/timer.h"
+#include "hw/sysbus.h"
+
+#define TYPE_RENESAS_SCI "renesas-sci"
+#define RSCI(obj) OBJECT_CHECK(RSCIState, (obj), TYPE_RENESAS_SCI)
+
+enum {
+ERI = 0,
+RXI = 1,
+TXI = 2,
+TEI = 3,
+SCI_NR_IRQ = 4,
+};
+
+typedef struct {
+SysBusDevice parent_obj;
+MemoryRegion memory;
+
+uint8_t smr;
+uint8_t brr;
+uint8_t scr;
+uint8_t tdr;
+uint8_t ssr;
+uint8_t rdr;
+uint8_t scmr;
+uint8_t semr;
+
+uint8_t read_ssr;
+int64_t trtime;
+int64_t rx_next;
+QEMUTimer *timer;
+CharBackend chr;
+uint64_t input_freq;
+qemu_irq irq[SCI_NR_IRQ];
+} RSCIState;
diff --git a/hw/char/renesas_sci.c b/hw/char/renesas_sci.c
new file mode 100644
index 00..0760a51f43
--- /dev/null
+++ b/hw/char/renesas_sci.c
@@ -0,0 +1,342 @@
+/*
+ * Renesas Serial Communication Interface
+ *
+ * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware
+ * (Rev.1.40 R01UH0033EJ0140)
+ *
+ * Copyright (c) 2019 Yoshinori Sato
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see .
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "hw/hw.h"
+#include "hw/irq.h"
+#include "hw/sysbus.h"
+#include "hw/registerfields.h"
+#include "hw/qdev-properties.h"
+#include "hw/char/renesas_sci.h"
+#include "migration/vmstate.h"
+#include "qemu/error-report.h"
+
+/* SCI register map */
+REG8(SMR, 0)
+  FIELD(SMR, CKS,  0, 2)
+  FIELD(SMR, MP,   2, 1)
+  FIELD(SMR, STOP, 3, 1)
+  FIELD(SMR, PM,   4, 1)
+  FIELD(SMR, PE,   5, 1)
+  FIELD(SMR, CHR,  6, 1)
+  FIELD(SMR, CM,   7, 1)
+REG8(BRR, 1)
+REG8(SCR, 2)
+  FIELD(SCR, CKE, 0, 2)
+  FIELD(SCR, TEIE, 2, 1)
+  FIELD(SCR, MPIE, 3, 1)
+  FIELD(SCR, RE,   4, 1)
+  FIELD(SCR, TE,   5, 1)
+  FIELD(SCR, RIE,  6, 1)
+  FIELD(SCR, TIE,  7, 1)
+REG8(TDR, 3)
+REG8(SSR, 4)
+  FIELD(SSR, MPBT, 0, 1)
+  FIELD(SSR, MPB,  1, 1)
+  FIELD(SSR, TEND, 2, 1)
+  FIELD(SSR, ERR, 3, 3)
+FIELD(SSR, PER,  3, 1)
+FIELD(SSR, FER,  4, 1)
+FIELD(SSR, ORER, 5, 1)
+  FIELD(SSR, RDRF, 6, 1)
+  FIELD(SSR, TDRE, 7, 1)
+REG8(RDR, 5)
+REG8(SCMR, 6)
+  FIELD(SCMR, SMIF, 0, 1)
+  FIELD(SCMR, SINV, 2, 1)
+  FIELD(SCMR, SDIR, 3, 1)
+  FIELD(SCMR, BCP2, 7, 1)
+REG8(SEMR, 7)
+  FIELD(SEMR, ACS0, 0, 1)
+  FIELD(SEMR, ABCS, 4, 1)
+
+static int can_receive(void *opaque)
+{
+RSCIState *sci = RSCI(opaque);
+if (sci->rx_next > qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)) {
+return 0;
+} else {
+return FIELD_EX8(sci->scr, SCR, RE);
+}
+}
+
+static void receive(void *opaque, const uint8_t *buf, int size)
+{
+RSCIState *sci = RSCI(opaque);
+sci->rx_next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + sci->trtime;
+if (FIELD_EX8(sci->ssr, SSR, RDRF) || size > 1) {
+sci->ssr = FIELD_DP8(sci->ssr, SSR, ORER, 1);
+if (FIELD_EX8(sci->scr, SCR, RIE)) {
+qemu_set_irq(sci->irq[ERI], 1);
+}
+} else {
+sci->rdr = buf[0];
+sci->ssr = FIELD_DP8(sci->ssr, SSR, RDRF, 1);
+if (FIELD_EX8(sci->scr, SCR, RIE)) {
+qemu_irq_pulse(sci->irq[RXI]);
+}
+}
+}
+
+static void send_byte(RSCIState *sci)
+{
+if (qemu_chr_fe_backend_connected(>chr)) {
+qemu_chr_fe_write_all(>chr, >tdr, 1);
+}
+timer_mod(sci->timer,
+  

[PATCH v31 13/22] target/rx: Dump bytes for each insn during disassembly

2020-02-22 Thread Yoshinori Sato
From: Richard Henderson 

There are so many different forms of each RX instruction
that it will be very useful to be able to look at the bytes
to see on which path a bug may lie.

Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Yoshinori Sato 
Signed-off-by: Yoshinori Sato 
Message-Id: <20190607091116.49044-24-ys...@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/rx/disas.c | 16 +++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/target/rx/disas.c b/target/rx/disas.c
index 5a32a87534..d73b53db44 100644
--- a/target/rx/disas.c
+++ b/target/rx/disas.c
@@ -102,7 +102,21 @@ static int bdsp_s(DisasContext *ctx, int d)
 /* Include the auto-generated decoder.  */
 #include "decode.inc.c"
 
-#define prt(...) (ctx->dis->fprintf_func)((ctx->dis->stream), __VA_ARGS__)
+static void dump_bytes(DisasContext *ctx)
+{
+int i, len = ctx->len;
+
+for (i = 0; i < len; ++i) {
+ctx->dis->fprintf_func(ctx->dis->stream, "%02x ", ctx->bytes[i]);
+}
+ctx->dis->fprintf_func(ctx->dis->stream, "%*c", (8 - i) * 3, '\t');
+}
+
+#define prt(...) \
+do {\
+dump_bytes(ctx);\
+ctx->dis->fprintf_func(ctx->dis->stream, __VA_ARGS__);  \
+} while (0)
 
 #define RX_MEMORY_BYTE 0
 #define RX_MEMORY_WORD 1
-- 
2.20.1




[PATCH v31 19/22] hw/rx: Restrict the RX62N microcontroller to the RX62N CPU core

2020-02-22 Thread Yoshinori Sato
From: Philippe Mathieu-Daudé 

While the VIRT machine can use different microcontrollers,
the RX62N microcontroller is tied to the RX62N CPU core.

Signed-off-by: Philippe Mathieu-Daudé 
Signed-off-by: Yoshinori Sato 
---
 hw/rx/rx-virt.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/hw/rx/rx-virt.c b/hw/rx/rx-virt.c
index b945be9f75..6cf7936201 100644
--- a/hw/rx/rx-virt.c
+++ b/hw/rx/rx-virt.c
@@ -17,6 +17,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/error-report.h"
 #include "qapi/error.h"
 #include "qemu-common.h"
 #include "cpu.h"
@@ -56,6 +57,7 @@ static void rx_load_image(RXCPU *cpu, const char *filename,
 
 static void rxvirt_init(MachineState *machine)
 {
+MachineClass *mc = MACHINE_GET_CLASS(machine);
 RX62NState *s = g_new(RX62NState, 1);
 MemoryRegion *sysmem = get_system_memory();
 MemoryRegion *sdram = g_new(MemoryRegion, 1);
-- 
2.20.1




[PATCH v31 06/22] target/rx: CPU definition

2020-02-22 Thread Yoshinori Sato
Signed-off-by: Yoshinori Sato 

Message-Id: <20190616142836.10614-4-ys...@users.sourceforge.jp>
Reviewed-by: Richard Henderson 
Message-Id: <20190607091116.49044-4-ys...@users.sourceforge.jp>
Signed-off-by: Richard Henderson 
[PMD: Use newer QOM style, split cpu-qom.h, restrict access to
 extable array, use rx_cpu_tlb_fill() extracted from patch of
 Yoshinori Sato 'Convert to CPUClass::tlb_fill']
Signed-off-by: Philippe Mathieu-Daudé 
Acked-by: Igor Mammedov 
Signed-off-by: Yoshinori Sato 
---
 target/rx/cpu-param.h   |  31 ++
 target/rx/cpu-qom.h |  42 
 target/rx/cpu.h | 181 +
 target/rx/cpu.c | 218 
 target/rx/gdbstub.c | 112 +
 gdb-xml/rx-core.xml |  70 +
 target/rx/Makefile.objs |   1 -
 7 files changed, 654 insertions(+), 1 deletion(-)
 create mode 100644 target/rx/cpu-param.h
 create mode 100644 target/rx/cpu-qom.h
 create mode 100644 target/rx/cpu.h
 create mode 100644 target/rx/cpu.c
 create mode 100644 target/rx/gdbstub.c
 create mode 100644 gdb-xml/rx-core.xml

diff --git a/target/rx/cpu-param.h b/target/rx/cpu-param.h
new file mode 100644
index 00..5da87fbebe
--- /dev/null
+++ b/target/rx/cpu-param.h
@@ -0,0 +1,31 @@
+/*
+ *  RX cpu parameters
+ *
+ *  Copyright (c) 2019 Yoshinori Sato
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see .
+ */
+
+#ifndef RX_CPU_PARAM_H
+#define RX_CPU_PARAM_H
+
+#define TARGET_LONG_BITS 32
+#define TARGET_PAGE_BITS 12
+
+#define TARGET_PHYS_ADDR_SPACE_BITS 32
+#define TARGET_VIRT_ADDR_SPACE_BITS 32
+
+#define NB_MMU_MODES 1
+#define MMU_MODE0_SUFFIX _all
+
+#endif
diff --git a/target/rx/cpu-qom.h b/target/rx/cpu-qom.h
new file mode 100644
index 00..8328900f3f
--- /dev/null
+++ b/target/rx/cpu-qom.h
@@ -0,0 +1,42 @@
+#ifndef QEMU_RX_CPU_QOM_H
+#define QEMU_RX_CPU_QOM_H
+
+#include "hw/core/cpu.h"
+/*
+ * RX CPU
+ *
+ * Copyright (c) 2019 Yoshinori Sato
+ * SPDX-License-Identifier: LGPL-2.0+
+ */
+
+#define TYPE_RX_CPU "rx-cpu"
+
+#define TYPE_RX62N_CPU RX_CPU_TYPE_NAME("rx62n")
+
+#define RXCPU_CLASS(klass) \
+OBJECT_CLASS_CHECK(RXCPUClass, (klass), TYPE_RX_CPU)
+#define RXCPU(obj) \
+OBJECT_CHECK(RXCPU, (obj), TYPE_RX_CPU)
+#define RXCPU_GET_CLASS(obj) \
+OBJECT_GET_CLASS(RXCPUClass, (obj), TYPE_RX_CPU)
+
+/*
+ * RXCPUClass:
+ * @parent_realize: The parent class' realize handler.
+ * @parent_reset: The parent class' reset handler.
+ *
+ * A RX CPU model.
+ */
+typedef struct RXCPUClass {
+/*< private >*/
+CPUClass parent_class;
+/*< public >*/
+
+DeviceRealize parent_realize;
+void (*parent_reset)(CPUState *cpu);
+
+} RXCPUClass;
+
+#define CPUArchState struct CPURXState
+
+#endif
diff --git a/target/rx/cpu.h b/target/rx/cpu.h
new file mode 100644
index 00..2d1eb7665c
--- /dev/null
+++ b/target/rx/cpu.h
@@ -0,0 +1,181 @@
+/*
+ *  RX emulation definition
+ *
+ *  Copyright (c) 2019 Yoshinori Sato
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see .
+ */
+
+#ifndef RX_CPU_H
+#define RX_CPU_H
+
+#include "qemu/bitops.h"
+#include "qemu-common.h"
+#include "hw/registerfields.h"
+#include "cpu-qom.h"
+
+#include "exec/cpu-defs.h"
+
+/* PSW define */
+REG32(PSW, 0)
+FIELD(PSW, C, 0, 1)
+FIELD(PSW, Z, 1, 1)
+FIELD(PSW, S, 2, 1)
+FIELD(PSW, O, 3, 1)
+FIELD(PSW, I, 16, 1)
+FIELD(PSW, U, 17, 1)
+FIELD(PSW, PM, 20, 1)
+FIELD(PSW, IPL, 24, 4)
+
+/* FPSW define */
+REG32(FPSW, 0)
+FIELD(FPSW, RM, 0, 2)
+FIELD(FPSW, CV, 2, 1)
+FIELD(FPSW, CO, 3, 1)
+FIELD(FPSW, CZ, 4, 1)
+FIELD(FPSW, CU, 5, 1)
+FIELD(FPSW, CX, 6, 1)
+FIELD(FPSW, CE, 7, 1)
+FIELD(FPSW, CAUSE, 2, 6)
+FIELD(FPSW, DN, 8, 1)
+FIELD(FPSW, EV, 10, 1)
+FIELD(FPSW, EO, 11, 1)
+FIELD(FPSW, EZ, 12, 1)
+FIELD(FPSW, EU, 13, 1)
+FIELD(FPSW, EX, 14, 1)
+FIELD(FPSW, ENABLE, 10, 5)
+FIELD(FPSW, FV, 26, 1)
+FIELD(FPSW, FO, 

[PATCH v31 18/22] hw/rx: Honor -accel qtest

2020-02-22 Thread Yoshinori Sato
From: Richard Henderson 

Issue an error if no kernel, no bios, and not qtest'ing.
Fixes make check-qtest-rx: test/qom-test.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Yoshinori Sato 
Message-Id: <20190607091116.49044-16-ys...@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
We could squash this with the previous patch
---
 hw/rx/rx62n.c | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/hw/rx/rx62n.c b/hw/rx/rx62n.c
index bd4cd4b6ea..c488934f09 100644
--- a/hw/rx/rx62n.c
+++ b/hw/rx/rx62n.c
@@ -21,12 +21,14 @@
 
 #include "qemu/osdep.h"
 #include "qapi/error.h"
+#include "qemu/error-report.h"
 #include "hw/hw.h"
 #include "hw/rx/rx62n.h"
 #include "hw/loader.h"
 #include "hw/sysbus.h"
 #include "hw/qdev-properties.h"
 #include "sysemu/sysemu.h"
+#include "sysemu/qtest.h"
 #include "cpu.h"
 
 /*
@@ -191,8 +193,14 @@ static void rx62n_realize(DeviceState *dev, Error **errp)
 memory_region_init_rom(>c_flash, NULL, "codeflash",
RX62N_CFLASH_SIZE, errp);
 memory_region_add_subregion(s->sysmem, RX62N_CFLASH_BASE, >c_flash);
+
 if (!s->kernel) {
-rom_add_file_fixed(bios_name, RX62N_CFLASH_BASE, 0);
+if (bios_name) {
+rom_add_file_fixed(bios_name, RX62N_CFLASH_BASE, 0);
+}  else if (!qtest_enabled()) {
+error_report("No bios or kernel specified");
+exit(1);
+}
 }
 
 /* Initialize CPU */
-- 
2.20.1




[PATCH v31 00/22] Add RX archtecture support

2020-02-22 Thread Yoshinori Sato
Hello.
This patch series is added Renesas RX target emulation.

Changes for v30.
Follow master changes.
Fix checkpatch error.

Changes for v29.
Add target description XML. It required gdb-9.1.
Follow git master changes.

Changes for v28.
Allow -m option.
With this option, 16 Mbytes or more can be specified.
Add example for qemu-doc.
Fix build error on latest master.

Changes for v27.
Added RX section to qemu-doc.
Rebase for master

Changes for v26.
Rebase for 5.0
Update machine.json for 5.0

Changes for v25.
Update commit message.
Squashed qapi/machine.json changes.

Changes for v24.
Add note for qapi/machine.json.
Added Acked-by for 6/22.
git rebase master.

Changes for v23.
Follow master changes.

Changes for v22.
Added some include.

Changes for v21.
rebase latest master.
Remove unneeded hmp_info_tlb.

Chanegs for v20.
Reorderd patches.
Squashed v19 changes.

Changes for v19.
Follow tcg changes.
Cleanup cpu.c.
simplify rx_cpu_class_by_name and rx_load_image move to rx-virt.

My git repository is bellow.
git://git.pf.osdn.net/gitroot/y/ys/ysato/qemu.git tags/rx-20200223

Testing binaries bellow.
u-boot
Download - https://osdn.net/users/ysato/pf/qemu/dl/u-boot.bin.gz

starting
$ gzip -d u-boot.bin.gz
$ qemu-system-rx -bios u-boot.bin

linux and pico-root (only sash)
Download - https://osdn.net/users/ysato/pf/qemu/dl/zImage (kernel)
   https://osdn.net/users/ysato/pf/qemu/dl/rx-virt.dtb (DeviceTree)

starting
$ qemu-system-rx -kernel zImage -dtb rx-virt.dtb -append "earlycon"

Philippe Mathieu-Daudé (3):
  hw/registerfields.h: Add 8bit and 16bit register macros
  hw/rx: Restrict the RX62N microcontroller to the RX62N CPU core
  BootLinuxConsoleTest: Test the RX-Virt machine

Richard Henderson (7):
  target/rx: Disassemble rx_index_addr into a string
  target/rx: Replace operand with prt_ldmi in disassembler
  target/rx: Use prt_ldmi for XCHG_mr disassembly
  target/rx: Emit all disassembly in one prt()
  target/rx: Collect all bytes during disassembly
  target/rx: Dump bytes for each insn during disassembly
  hw/rx: Honor -accel qtest

Yoshinori Sato (12):
  MAINTAINERS: Add RX
  qemu/bitops.h: Add extract8 and extract16
  target/rx: TCG translation
  target/rx: TCG helper
  target/rx: CPU definition
  target/rx: RX disassembler
  hw/intc: RX62N interrupt controller (ICUa)
  hw/timer: RX62N internal timer modules
  hw/char: RX62N serial communication interface (SCI)
  hw/rx: RX Target hardware definition
  Add rx-softmmu
  qemu-doc.texi: Add RX section.

 qemu-doc.texi  |   44 +
 configure  |   11 +-
 default-configs/rx-softmmu.mak |3 +
 qapi/machine.json  |2 +-
 include/disas/dis-asm.h|5 +
 include/exec/poison.h  |1 +
 include/hw/char/renesas_sci.h  |   45 +
 include/hw/intc/rx_icu.h   |   56 +
 include/hw/registerfields.h|   32 +-
 include/hw/rx/rx.h |7 +
 include/hw/rx/rx62n.h  |   91 +
 include/hw/timer/renesas_cmt.h |   38 +
 include/hw/timer/renesas_tmr.h |   53 +
 include/qemu/bitops.h  |   38 +
 include/sysemu/arch_init.h |1 +
 target/rx/cpu-param.h  |   31 +
 target/rx/cpu-qom.h|   42 +
 target/rx/cpu.h|  181 ++
 target/rx/helper.h |   31 +
 target/rx/insns.decode |  621 ++
 arch_init.c|2 +
 hw/char/renesas_sci.c  |  342 
 hw/intc/rx_icu.c   |  379 
 hw/rx/rx-virt.c|  142 ++
 hw/rx/rx62n.c  |  247 +++
 hw/timer/renesas_cmt.c |  278 +++
 hw/timer/renesas_tmr.c |  458 +
 target/rx/cpu.c|  218 +++
 target/rx/disas.c  | 1446 ++
 target/rx/gdbstub.c|  112 ++
 target/rx/helper.c |  149 ++
 target/rx/op_helper.c  |  470 +
 target/rx/translate.c  | 2432 
 tests/qtest/machine-none-test.c|1 +
 MAINTAINERS|   19 +
 gdb-xml/rx-core.xml|   70 +
 hw/Kconfig |1 +
 hw/char/Kconfig|3 +
 hw/char/Makefile.objs  |1 +
 hw/intc/Kconfig|3 +
 hw/intc/Makefile.objs  |1 +
 hw/rx/Kconfig  |   14 +
 hw/rx/Makefile.objs|2 +
 hw/timer/Kconfig   |6 +
 hw/timer/Makefile.objs |3 +
 target/rx/Makefile.objs|   11 +
 tests/acceptance/boot_linux_console.py |   46 +
 47 files changed, 8186 insertions(+), 3 deletions(-)
 create mode 100644 default-configs/rx-softmmu.mak
 create mode 

[PATCH v31 09/22] target/rx: Replace operand with prt_ldmi in disassembler

2020-02-22 Thread Yoshinori Sato
From: Richard Henderson 

This has consistency with prt_ri().  It loads all data before
beginning output.  It uses exactly one call to prt() to emit
the full instruction.

Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Yoshinori Sato 
Signed-off-by: Yoshinori Sato 
Message-Id: <20190607091116.49044-20-ys...@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/rx/disas.c | 77 +--
 1 file changed, 27 insertions(+), 50 deletions(-)

diff --git a/target/rx/disas.c b/target/rx/disas.c
index 64342537ee..515b365528 100644
--- a/target/rx/disas.c
+++ b/target/rx/disas.c
@@ -135,18 +135,18 @@ static void rx_index_addr(DisasContext *ctx, char out[8], 
int ld, int mi)
 sprintf(out, "%u", dsp << (mi < 3 ? mi : 4 - mi));
 }
 
-static void operand(DisasContext *ctx, int ld, int mi, int rs, int rd)
+static void prt_ldmi(DisasContext *ctx, const char *insn,
+ int ld, int mi, int rs, int rd)
 {
 static const char sizes[][4] = {".b", ".w", ".l", ".uw", ".ub"};
 char dsp[8];
 
 if (ld < 3) {
 rx_index_addr(ctx, dsp, ld, mi);
-prt("%s[r%d]%s", dsp, rs, sizes[mi]);
+prt("%s\t%s[r%d]%s, r%d", insn, dsp, rs, sizes[mi], rd);
 } else {
-prt("r%d", rs);
+prt("%s\tr%d, r%d", insn, rs, rd);
 }
-prt(", r%d", rd);
 }
 
 static void prt_ir(DisasContext *ctx, const char *insn, int imm, int rd)
@@ -416,8 +416,7 @@ static bool trans_AND_ir(DisasContext *ctx, arg_AND_ir *a)
 /* and rs,rd */
 static bool trans_AND_mr(DisasContext *ctx, arg_AND_mr *a)
 {
-prt("and\t");
-operand(ctx, a->ld, a->mi, a->rs, a->rd);
+prt_ldmi(ctx, "and", a->ld, a->mi, a->rs, a->rd);
 return true;
 }
 
@@ -440,8 +439,7 @@ static bool trans_OR_ir(DisasContext *ctx, arg_OR_ir *a)
 /* or rs,rd */
 static bool trans_OR_mr(DisasContext *ctx, arg_OR_mr *a)
 {
-prt("or\t");
-operand(ctx, a->ld, a->mi, a->rs, a->rd);
+prt_ldmi(ctx, "or", a->ld, a->mi, a->rs, a->rd);
 return true;
 }
 
@@ -463,8 +461,7 @@ static bool trans_XOR_ir(DisasContext *ctx, arg_XOR_ir *a)
 /* xor rs,rd */
 static bool trans_XOR_mr(DisasContext *ctx, arg_XOR_mr *a)
 {
-prt("xor\t");
-operand(ctx, a->ld, a->mi, a->rs, a->rd);
+prt_ldmi(ctx, "xor", a->ld, a->mi, a->rs, a->rd);
 return true;
 }
 
@@ -479,8 +476,7 @@ static bool trans_TST_ir(DisasContext *ctx, arg_TST_ir *a)
 /* tst rs, rd */
 static bool trans_TST_mr(DisasContext *ctx, arg_TST_mr *a)
 {
-prt("tst\t");
-operand(ctx, a->ld, a->mi, a->rs, a->rd);
+prt_ldmi(ctx, "tst", a->ld, a->mi, a->rs, a->rd);
 return true;
 }
 
@@ -548,8 +544,7 @@ static bool trans_ADD_irr(DisasContext *ctx, arg_ADD_irr *a)
 /* add dsp[rs], rd */
 static bool trans_ADD_mr(DisasContext *ctx, arg_ADD_mr *a)
 {
-prt("add\t");
-operand(ctx, a->ld, a->mi, a->rs, a->rd);
+prt_ldmi(ctx, "add", a->ld, a->mi, a->rs, a->rd);
 return true;
 }
 
@@ -573,8 +568,7 @@ static bool trans_CMP_ir(DisasContext *ctx, arg_CMP_ir *a)
 /* cmp dsp[rs], rs2 */
 static bool trans_CMP_mr(DisasContext *ctx, arg_CMP_mr *a)
 {
-prt("cmp\t");
-operand(ctx, a->ld, a->mi, a->rs, a->rd);
+prt_ldmi(ctx, "cmp", a->ld, a->mi, a->rs, a->rd);
 return true;
 }
 
@@ -589,8 +583,7 @@ static bool trans_SUB_ir(DisasContext *ctx, arg_SUB_ir *a)
 /* sub dsp[rs], rd */
 static bool trans_SUB_mr(DisasContext *ctx, arg_SUB_mr *a)
 {
-prt("sub\t");
-operand(ctx, a->ld, a->mi, a->rs, a->rd);
+prt_ldmi(ctx, "sub", a->ld, a->mi, a->rs, a->rd);
 return true;
 }
 
@@ -611,8 +604,7 @@ static bool trans_SBB_rr(DisasContext *ctx, arg_SBB_rr *a)
 /* sbb dsp[rs], rd */
 static bool trans_SBB_mr(DisasContext *ctx, arg_SBB_mr *a)
 {
-prt("sbb\t");
-operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd);
+prt_ldmi(ctx, "sbb", a->ld, RX_IM_LONG, a->rs, a->rd);
 return true;
 }
 
@@ -640,8 +632,7 @@ static bool trans_MAX_ir(DisasContext *ctx, arg_MAX_ir *a)
 /* max dsp[rs], rd */
 static bool trans_MAX_mr(DisasContext *ctx, arg_MAX_mr *a)
 {
-prt("max\t");
-operand(ctx, a->ld, a->mi, a->rs, a->rd);
+prt_ldmi(ctx, "max", a->ld, a->mi, a->rs, a->rd);
 return true;
 }
 
@@ -656,8 +647,7 @@ static bool trans_MIN_ir(DisasContext *ctx, arg_MIN_ir *a)
 /* min dsp[rs], rd */
 static bool trans_MIN_mr(DisasContext *ctx, arg_MIN_mr *a)
 {
-prt("max\t");
-operand(ctx, a->ld, a->mi, a->rs, a->rd);
+prt_ldmi(ctx, "min", a->ld, a->mi, a->rs, a->rd);
 return true;
 }
 
@@ -673,8 +663,7 @@ static bool trans_MUL_ir(DisasContext *ctx, arg_MUL_ir *a)
 /* mul dsp[rs], rd */
 static bool trans_MUL_mr(DisasContext *ctx, arg_MUL_mr *a)
 {
-prt("mul\t");
-operand(ctx, a->ld, a->mi, a->rs, a->rd);
+prt_ldmi(ctx, "mul", a->ld, a->mi, a->rs, a->rd);
 return true;
 }
 
@@ -696,8 +685,7 @@ static bool trans_EMUL_ir(DisasContext *ctx, arg_EMUL_ir *a)
 /* emul dsp[rs], rd */
 static bool trans_EMUL_mr(DisasContext 

[PATCH v31 21/22] BootLinuxConsoleTest: Test the RX-Virt machine

2020-02-22 Thread Yoshinori Sato
From: Philippe Mathieu-Daudé 

Add two tests for the rx-virt machine, based on the recommended test
setup from Yoshinori Sato:
https://lists.gnu.org/archive/html/qemu-devel/2019-05/msg03586.html

- U-Boot prompt
- Linux kernel with Sash shell

These are very quick tests:

  $ avocado run -t arch:rx tests/acceptance/boot_linux_console.py
  JOB ID : 84a6ef01c0b87975ecbfcb31a920afd735753ace
  JOB LOG: 
/home/phil/avocado/job-results/job-2019-05-24T05.02-84a6ef0/job.log
   (1/2) tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_rx_uboot: 
PASS (0.11 s)
   (2/2) tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_rx_linux: 
PASS (0.45 s)
  RESULTS: PASS 2 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 | 
CANCEL 0

Tests can also be run with:

  $ avocado --show=console run -t arch:rx tests/acceptance/boot_linux_console.py
  console: U-Boot 2016.05-rc3-23705-ga1ef3c71cb-dirty (Feb 05 2019 - 21:56:06 
+0900)
  console: Linux version 4.19.0+ (yo-satoh@yo-satoh-debian) (gcc version 9.0.0 
20181105 (experimental) (GCC)) #137 Wed Feb 20 23:20:02 JST 2019
  console: Built 1 zonelists, mobility grouping on.  Total pages: 8128
  ...
  console: SuperH (H)SCI(F) driver initialized
  console: 88240.serial: ttySC0 at MMIO 0x88240 (irq = 215, base_baud = 0) is a 
sci
  console: console [ttySC0] enabled
  console: 88248.serial: ttySC1 at MMIO 0x88248 (irq = 219, base_baud = 0) is a 
sci

Signed-off-by: Philippe Mathieu-Daudé 
Based-on: 20190517045136.3509-1-richard.hender...@linaro.org
"RX architecture support"
Signed-off-by: Yoshinori Sato 
---
 tests/acceptance/boot_linux_console.py | 46 ++
 1 file changed, 46 insertions(+)

diff --git a/tests/acceptance/boot_linux_console.py 
b/tests/acceptance/boot_linux_console.py
index 34d37eba3b..367cf480a5 100644
--- a/tests/acceptance/boot_linux_console.py
+++ b/tests/acceptance/boot_linux_console.py
@@ -686,3 +686,49 @@ class BootLinuxConsole(Test):
 tar_hash = '49e88d9933742f0164b60839886c9739cb7a0d34'
 self.vm.add_args('-cpu', 'dc233c')
 self.do_test_advcal_2018('02', tar_hash, 'santas-sleigh-ride.elf')
+
+def test_rx_uboot(self):
+"""
+:avocado: tags=arch:rx
+:avocado: tags=machine:rx-virt
+:avocado: tags=endian:little
+"""
+uboot_url = ('https://acc.dl.osdn.jp/users/23/23888/u-boot.bin.gz')
+uboot_hash = '9b78dbd43b40b2526848c0b1ce9de02c24f4dcdb'
+uboot_path = self.fetch_asset(uboot_url, asset_hash=uboot_hash)
+uboot_path = archive.uncompress(uboot_path, self.workdir)
+
+self.vm.set_machine('rx-virt')
+self.vm.set_console()
+self.vm.add_args('-bios', uboot_path,
+ '-no-reboot')
+self.vm.launch()
+uboot_version = 'U-Boot 2016.05-rc3-23705-ga1ef3c71cb-dirty'
+self.wait_for_console_pattern(uboot_version)
+gcc_version = 'rx-unknown-linux-gcc (GCC) 9.0.0 20181105 
(experimental)'
+# FIXME limit baudrate on chardev, else we type too fast
+#self.exec_command_and_wait_for_pattern('version', gcc_version)
+
+def test_rx_linux(self):
+"""
+:avocado: tags=arch:rx
+:avocado: tags=machine:rx-virt
+:avocado: tags=endian:little
+"""
+dtb_url = ('https://acc.dl.osdn.jp/users/23/23887/rx-qemu.dtb')
+dtb_hash = '7b4e4e2c71905da44e86ce47adee2210b026ac18'
+dtb_path = self.fetch_asset(dtb_url, asset_hash=dtb_hash)
+kernel_url = ('http://acc.dl.osdn.jp/users/23/23845/zImage')
+kernel_hash = '39a81067f8d72faad90866ddfefa19165d68fc99'
+kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
+
+self.vm.set_machine('rx-virt')
+self.vm.set_console()
+kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'earlycon'
+self.vm.add_args('-kernel', kernel_path,
+ '-dtb', dtb_path,
+ '-no-reboot')
+self.vm.launch()
+self.wait_for_console_pattern('Sash command shell (version 1.1.1)')
+self.exec_command_and_wait_for_pattern('printenv',
+   'TERM=linux')
-- 
2.20.1




[PATCH v31 11/22] target/rx: Emit all disassembly in one prt()

2020-02-22 Thread Yoshinori Sato
From: Richard Henderson 

Many of the multi-part prints have been eliminated by previous
patches.  Eliminate the rest of them.

Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Yoshinori Sato 
Signed-off-by: Yoshinori Sato 
Message-Id: <20190607091116.49044-22-ys...@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/rx/disas.c | 75 ---
 1 file changed, 39 insertions(+), 36 deletions(-)

diff --git a/target/rx/disas.c b/target/rx/disas.c
index db10385fd0..ebc1a44249 100644
--- a/target/rx/disas.c
+++ b/target/rx/disas.c
@@ -228,24 +228,21 @@ static bool trans_MOV_ra(DisasContext *ctx, arg_MOV_ra *a)
 /* mov.[bwl] rs,rd */
 static bool trans_MOV_mm(DisasContext *ctx, arg_MOV_mm *a)
 {
-char dspd[8], dsps[8];
+char dspd[8], dsps[8], szc = size[a->sz];
 
-prt("mov.%c\t", size[a->sz]);
 if (a->lds == 3 && a->ldd == 3) {
 /* mov.[bwl] rs,rd */
-prt("r%d, r%d", a->rs, a->rd);
-return true;
-}
-if (a->lds == 3) {
+prt("mov.%c\tr%d, r%d", szc, a->rs, a->rd);
+} else if (a->lds == 3) {
 rx_index_addr(ctx, dspd, a->ldd, a->sz);
-prt("r%d, %s[r%d]", a->rs, dspd, a->rd);
+prt("mov.%c\tr%d, %s[r%d]", szc, a->rs, dspd, a->rd);
 } else if (a->ldd == 3) {
 rx_index_addr(ctx, dsps, a->lds, a->sz);
-prt("%s[r%d], r%d", dsps, a->rs, a->rd);
+prt("mov.%c\t%s[r%d], r%d", szc, dsps, a->rs, a->rd);
 } else {
 rx_index_addr(ctx, dsps, a->lds, a->sz);
 rx_index_addr(ctx, dspd, a->ldd, a->sz);
-prt("%s[r%d], %s[r%d]", dsps, a->rs, dspd, a->rd);
+prt("mov.%c\t%s[r%d], %s[r%d]", szc, dsps, a->rs, dspd, a->rd);
 }
 return true;
 }
@@ -254,8 +251,11 @@ static bool trans_MOV_mm(DisasContext *ctx, arg_MOV_mm *a)
 /* mov.[bwl] rs,[-rd] */
 static bool trans_MOV_rp(DisasContext *ctx, arg_MOV_rp *a)
 {
-prt("mov.%c\tr%d, ", size[a->sz], a->rs);
-prt((a->ad == 0) ? "[r%d+]" : "[-r%d]", a->rd);
+if (a->ad) {
+prt("mov.%c\tr%d, [-r%d]", size[a->sz], a->rs, a->rd);
+} else {
+prt("mov.%c\tr%d, [r%d+]", size[a->sz], a->rs, a->rd);
+}
 return true;
 }
 
@@ -263,9 +263,11 @@ static bool trans_MOV_rp(DisasContext *ctx, arg_MOV_rp *a)
 /* mov.[bwl] [-rd],rs */
 static bool trans_MOV_pr(DisasContext *ctx, arg_MOV_pr *a)
 {
-prt("mov.%c\t", size[a->sz]);
-prt((a->ad == 0) ? "[r%d+]" : "[-r%d]", a->rd);
-prt(", r%d", a->rs);
+if (a->ad) {
+prt("mov.%c\t[-r%d], r%d", size[a->sz], a->rd, a->rs);
+} else {
+prt("mov.%c\t[r%d+], r%d", size[a->sz], a->rd, a->rs);
+}
 return true;
 }
 
@@ -299,9 +301,11 @@ static bool trans_MOVU_ar(DisasContext *ctx, arg_MOVU_ar 
*a)
 /* movu.[bw] [-rs],rd */
 static bool trans_MOVU_pr(DisasContext *ctx, arg_MOVU_pr *a)
 {
-prt("movu.%c\t", size[a->sz]);
-prt((a->ad == 0) ? "[r%d+]" : "[-r%d]", a->rd);
-prt(", r%d", a->rs);
+if (a->ad) {
+prt("movu.%c\t[-r%d], r%d", size[a->sz], a->rd, a->rs);
+} else {
+prt("movu.%c\t[r%d+], r%d", size[a->sz], a->rd, a->rs);
+}
 return true;
 }
 
@@ -478,11 +482,11 @@ static bool trans_TST_mr(DisasContext *ctx, arg_TST_mr *a)
 /* not rs, rd */
 static bool trans_NOT_rr(DisasContext *ctx, arg_NOT_rr *a)
 {
-prt("not\t");
 if (a->rs != a->rd) {
-prt("r%d, ", a->rs);
+prt("not\tr%d, r%d", a->rs, a->rd);
+} else {
+prt("not\tr%d", a->rs);
 }
-prt("r%d", a->rd);
 return true;
 }
 
@@ -490,11 +494,11 @@ static bool trans_NOT_rr(DisasContext *ctx, arg_NOT_rr *a)
 /* neg rs, rd */
 static bool trans_NEG_rr(DisasContext *ctx, arg_NEG_rr *a)
 {
-prt("neg\t");
 if (a->rs != a->rd) {
-prt("r%d, ", a->rs);
+prt("neg\tr%d, r%d", a->rs, a->rd);
+} else {
+prt("neg\tr%d", a->rs);
 }
-prt("r%d", a->rd);
 return true;
 }
 
@@ -606,11 +610,10 @@ static bool trans_SBB_mr(DisasContext *ctx, arg_SBB_mr *a)
 /* abs rs, rd */
 static bool trans_ABS_rr(DisasContext *ctx, arg_ABS_rr *a)
 {
-prt("abs\t");
-if (a->rs == a->rd) {
-prt("r%d", a->rd);
+if (a->rs != a->rd) {
+prt("abs\tr%d, r%d", a->rs, a->rd);
 } else {
-prt("r%d, r%d", a->rs, a->rd);
+prt("abs\tr%d", a->rs);
 }
 return true;
 }
@@ -733,11 +736,11 @@ static bool trans_DIVU_mr(DisasContext *ctx, arg_DIVU_mr 
*a)
 /* shll #imm:5, rs, rd */
 static bool trans_SHLL_irr(DisasContext *ctx, arg_SHLL_irr *a)
 {
-prt("shll\t#%d, ", a->imm);
 if (a->rs2 != a->rd) {
-prt("r%d, ", a->rs2);
+prt("shll\t#%d, r%d, r%d", a->imm, a->rs2, a->rd);
+} else {
+prt("shll\t#%d, r%d", a->imm, a->rd);
 }
-prt("r%d", a->rd);
 return true;
 }
 
@@ -752,11 +755,11 @@ static bool trans_SHLL_rr(DisasContext *ctx, arg_SHLL_rr 
*a)
 /* shar #imm:5, rs, rd */
 static bool trans_SHAR_irr(DisasContext *ctx, 

[PATCH v31 02/22] qemu/bitops.h: Add extract8 and extract16

2020-02-22 Thread Yoshinori Sato
Signed-off-by: Yoshinori Sato 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
Message-Id: <20190607091116.49044-10-ys...@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 include/qemu/bitops.h | 38 ++
 1 file changed, 38 insertions(+)

diff --git a/include/qemu/bitops.h b/include/qemu/bitops.h
index 02c1ce6a5d..f55ce8b320 100644
--- a/include/qemu/bitops.h
+++ b/include/qemu/bitops.h
@@ -301,6 +301,44 @@ static inline uint32_t extract32(uint32_t value, int 
start, int length)
 return (value >> start) & (~0U >> (32 - length));
 }
 
+/**
+ * extract8:
+ * @value: the value to extract the bit field from
+ * @start: the lowest bit in the bit field (numbered from 0)
+ * @length: the length of the bit field
+ *
+ * Extract from the 8 bit input @value the bit field specified by the
+ * @start and @length parameters, and return it. The bit field must
+ * lie entirely within the 8 bit word. It is valid to request that
+ * all 8 bits are returned (ie @length 8 and @start 0).
+ *
+ * Returns: the value of the bit field extracted from the input value.
+ */
+static inline uint8_t extract8(uint8_t value, int start, int length)
+{
+assert(start >= 0 && length > 0 && length <= 8 - start);
+return extract32(value, start, length);
+}
+
+/**
+ * extract16:
+ * @value: the value to extract the bit field from
+ * @start: the lowest bit in the bit field (numbered from 0)
+ * @length: the length of the bit field
+ *
+ * Extract from the 16 bit input @value the bit field specified by the
+ * @start and @length parameters, and return it. The bit field must
+ * lie entirely within the 16 bit word. It is valid to request that
+ * all 16 bits are returned (ie @length 16 and @start 0).
+ *
+ * Returns: the value of the bit field extracted from the input value.
+ */
+static inline uint16_t extract16(uint16_t value, int start, int length)
+{
+assert(start >= 0 && length > 0 && length <= 16 - start);
+return extract32(value, start, length);
+}
+
 /**
  * extract64:
  * @value: the value to extract the bit field from
-- 
2.20.1




[PATCH v31 10/22] target/rx: Use prt_ldmi for XCHG_mr disassembly

2020-02-22 Thread Yoshinori Sato
From: Richard Henderson 

Note that the ld == 3 case handled by prt_ldmi is decoded as
XCHG_rr and cannot appear here.

Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Yoshinori Sato 
Signed-off-by: Yoshinori Sato 
Message-Id: <20190607091116.49044-21-ys...@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/rx/disas.c | 8 +---
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/target/rx/disas.c b/target/rx/disas.c
index 515b365528..db10385fd0 100644
--- a/target/rx/disas.c
+++ b/target/rx/disas.c
@@ -366,13 +366,7 @@ static bool trans_XCHG_rr(DisasContext *ctx, arg_XCHG_rr 
*a)
 /* xchg dsp[rs].,rd */
 static bool trans_XCHG_mr(DisasContext *ctx, arg_XCHG_mr *a)
 {
-static const char msize[][4] = {
-"b", "w", "l", "ub", "uw",
-};
-char dsp[8];
-
-rx_index_addr(ctx, dsp, a->ld, a->mi);
-prt("xchg\t%s[r%d].%s, r%d", dsp, a->rs, msize[a->mi], a->rd);
+prt_ldmi(ctx, "xchg", a->ld, a->mi, a->rs, a->rd);
 return true;
 }
 
-- 
2.20.1




[PATCH v31 03/22] hw/registerfields.h: Add 8bit and 16bit register macros

2020-02-22 Thread Yoshinori Sato
From: Philippe Mathieu-Daudé 

Some RX peripheral using 8bit and 16bit registers.
Added 8bit and 16bit APIs.

Signed-off-by: Yoshinori Sato 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
Message-Id: <20190607091116.49044-11-ys...@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé 
Reviewed-by: Alistair Francis 
Signed-off-by: Richard Henderson 
---
 include/hw/registerfields.h | 32 +++-
 1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/include/hw/registerfields.h b/include/hw/registerfields.h
index 2659a58737..a0bb0654d6 100644
--- a/include/hw/registerfields.h
+++ b/include/hw/registerfields.h
@@ -22,6 +22,14 @@
 enum { A_ ## reg = (addr) };  \
 enum { R_ ## reg = (addr) / 4 };
 
+#define REG8(reg, addr)  \
+enum { A_ ## reg = (addr) };  \
+enum { R_ ## reg = (addr) };
+
+#define REG16(reg, addr)  \
+enum { A_ ## reg = (addr) };  \
+enum { R_ ## reg = (addr) / 2 };
+
 /* Define SHIFT, LENGTH and MASK constants for a field within a register */
 
 /* This macro will define R_FOO_BAR_MASK, R_FOO_BAR_SHIFT and R_FOO_BAR_LENGTH
@@ -34,6 +42,12 @@
 MAKE_64BIT_MASK(shift, length)};
 
 /* Extract a field from a register */
+#define FIELD_EX8(storage, reg, field)\
+extract8((storage), R_ ## reg ## _ ## field ## _SHIFT,\
+  R_ ## reg ## _ ## field ## _LENGTH)
+#define FIELD_EX16(storage, reg, field)   \
+extract16((storage), R_ ## reg ## _ ## field ## _SHIFT,   \
+  R_ ## reg ## _ ## field ## _LENGTH)
 #define FIELD_EX32(storage, reg, field)   \
 extract32((storage), R_ ## reg ## _ ## field ## _SHIFT,   \
   R_ ## reg ## _ ## field ## _LENGTH)
@@ -49,6 +63,22 @@
  * Assigning values larger then the target field will result in
  * compilation warnings.
  */
+#define FIELD_DP8(storage, reg, field, val) ({\
+struct {  \
+unsigned int v:R_ ## reg ## _ ## field ## _LENGTH;\
+} v = { .v = val };   \
+uint8_t d;\
+d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT,   \
+  R_ ## reg ## _ ## field ## _LENGTH, v.v);   \
+d; })
+#define FIELD_DP16(storage, reg, field, val) ({   \
+struct {  \
+unsigned int v:R_ ## reg ## _ ## field ## _LENGTH;\
+} v = { .v = val };   \
+uint16_t d;   \
+d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT,   \
+  R_ ## reg ## _ ## field ## _LENGTH, v.v);   \
+d; })
 #define FIELD_DP32(storage, reg, field, val) ({   \
 struct {  \
 unsigned int v:R_ ## reg ## _ ## field ## _LENGTH;\
@@ -57,7 +87,7 @@
 d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT,   \
   R_ ## reg ## _ ## field ## _LENGTH, v.v);   \
 d; })
-#define FIELD_DP64(storage, reg, field, val) ({   \
+#define FIELD_DP64(storage, reg, field, val) ({ \
 struct {  \
 unsigned int v:R_ ## reg ## _ ## field ## _LENGTH;\
 } v = { .v = val };   \
-- 
2.20.1




[PATCH v31 08/22] target/rx: Disassemble rx_index_addr into a string

2020-02-22 Thread Yoshinori Sato
From: Richard Henderson 

We were eliding all zero indexes.  It is only ld==0 that does
not have an index in the instruction.  This also allows us to
avoid breaking the final print into multiple pieces.

Reviewed-by: Yoshinori Sato 
Signed-off-by: Yoshinori Sato 
Message-Id: <20190607091116.49044-19-ys...@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/rx/disas.c | 154 +-
 1 file changed, 55 insertions(+), 99 deletions(-)

diff --git a/target/rx/disas.c b/target/rx/disas.c
index 8cada4825d..64342537ee 100644
--- a/target/rx/disas.c
+++ b/target/rx/disas.c
@@ -107,49 +107,42 @@ static const char psw[] = {
 'i', 'u', 0, 0, 0, 0, 0, 0,
 };
 
-static uint32_t rx_index_addr(int ld, int size, DisasContext *ctx)
+static void rx_index_addr(DisasContext *ctx, char out[8], int ld, int mi)
 {
-bfd_byte buf[2];
+uint32_t addr = ctx->addr;
+uint8_t buf[2];
+uint16_t dsp;
+
 switch (ld) {
 case 0:
-return 0;
+/* No index; return empty string.  */
+out[0] = '\0';
+return;
 case 1:
-ctx->dis->read_memory_func(ctx->addr, buf, 1, ctx->dis);
 ctx->addr += 1;
-return ((uint8_t)buf[0]) << size;
+ctx->dis->read_memory_func(addr, buf, 1, ctx->dis);
+dsp = buf[0];
+break;
 case 2:
-ctx->dis->read_memory_func(ctx->addr, buf, 2, ctx->dis);
 ctx->addr += 2;
-return lduw_le_p(buf) << size;
+ctx->dis->read_memory_func(addr, buf, 2, ctx->dis);
+dsp = lduw_le_p(buf);
+break;
+default:
+g_assert_not_reached();
 }
-g_assert_not_reached();
+
+sprintf(out, "%u", dsp << (mi < 3 ? mi : 4 - mi));
 }
 
 static void operand(DisasContext *ctx, int ld, int mi, int rs, int rd)
 {
-int dsp;
 static const char sizes[][4] = {".b", ".w", ".l", ".uw", ".ub"};
+char dsp[8];
+
 if (ld < 3) {
-switch (mi) {
-case 4:
-/* dsp[rs].ub */
-dsp = rx_index_addr(ld, RX_MEMORY_BYTE, ctx);
-break;
-case 3:
-/* dsp[rs].uw */
-dsp = rx_index_addr(ld, RX_MEMORY_WORD, ctx);
-break;
-default:
-/* dsp[rs].b */
-/* dsp[rs].w */
-/* dsp[rs].l */
-dsp = rx_index_addr(ld, mi, ctx);
-break;
-}
-if (dsp > 0) {
-prt("%d", dsp);
-}
-prt("[r%d]%s", rs, sizes[mi]);
+rx_index_addr(ctx, dsp, ld, mi);
+prt("%s[r%d]%s", dsp, rs, sizes[mi]);
 } else {
 prt("r%d", rs);
 }
@@ -235,7 +228,7 @@ static bool trans_MOV_ra(DisasContext *ctx, arg_MOV_ra *a)
 /* mov.[bwl] rs,rd */
 static bool trans_MOV_mm(DisasContext *ctx, arg_MOV_mm *a)
 {
-int dsp;
+char dspd[8], dsps[8];
 
 prt("mov.%c\t", size[a->sz]);
 if (a->lds == 3 && a->ldd == 3) {
@@ -244,29 +237,15 @@ static bool trans_MOV_mm(DisasContext *ctx, arg_MOV_mm *a)
 return true;
 }
 if (a->lds == 3) {
-prt("r%d, ", a->rd);
-dsp = rx_index_addr(a->ldd, a->sz, ctx);
-if (dsp > 0) {
-prt("%d", dsp);
-}
-prt("[r%d]", a->rs);
+rx_index_addr(ctx, dspd, a->ldd, a->sz);
+prt("r%d, %s[r%d]", a->rs, dspd, a->rd);
 } else if (a->ldd == 3) {
-dsp = rx_index_addr(a->lds, a->sz, ctx);
-if (dsp > 0) {
-prt("%d", dsp);
-}
-prt("[r%d], r%d", a->rs, a->rd);
+rx_index_addr(ctx, dsps, a->lds, a->sz);
+prt("%s[r%d], r%d", dsps, a->rs, a->rd);
 } else {
-dsp = rx_index_addr(a->lds, a->sz, ctx);
-if (dsp > 0) {
-prt("%d", dsp);
-}
-prt("[r%d], ", a->rs);
-dsp = rx_index_addr(a->ldd, a->sz, ctx);
-if (dsp > 0) {
-prt("%d", dsp);
-}
-prt("[r%d]", a->rd);
+rx_index_addr(ctx, dsps, a->lds, a->sz);
+rx_index_addr(ctx, dspd, a->ldd, a->sz);
+prt("%s[r%d], %s[r%d]", dsps, a->rs, dspd, a->rd);
 }
 return true;
 }
@@ -357,12 +336,10 @@ static bool trans_PUSH_r(DisasContext *ctx, arg_PUSH_r *a)
 /* push dsp[rs] */
 static bool trans_PUSH_m(DisasContext *ctx, arg_PUSH_m *a)
 {
-prt("push\t");
-int dsp = rx_index_addr(a->ld, a->sz, ctx);
-if (dsp > 0) {
-prt("%d", dsp);
-}
-prt("[r%d]", a->rs);
+char dsp[8];
+
+rx_index_addr(ctx, dsp, a->ld, a->sz);
+prt("push\t%s[r%d]", dsp, a->rs);
 return true;
 }
 
@@ -389,17 +366,13 @@ static bool trans_XCHG_rr(DisasContext *ctx, arg_XCHG_rr 
*a)
 /* xchg dsp[rs].,rd */
 static bool trans_XCHG_mr(DisasContext *ctx, arg_XCHG_mr *a)
 {
-int dsp;
 static const char msize[][4] = {
 "b", "w", "l", "ub", "uw",
 };
+char dsp[8];
 
-prt("xchg\t");
-dsp = rx_index_addr(a->ld, a->mi, ctx);
-if (dsp > 0) {
-prt("%d", dsp);
-}
-

[PATCH v31 01/22] MAINTAINERS: Add RX

2020-02-22 Thread Yoshinori Sato
Signed-off-by: Yoshinori Sato 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
Message-Id: <20190607091116.49044-18-ys...@users.sourceforge.jp>
Signed-off-by: Richard Henderson 
---
 MAINTAINERS | 19 +++
 1 file changed, 19 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 1740a4fddc..c5008f638d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -274,6 +274,13 @@ F: include/hw/riscv/
 F: linux-user/host/riscv32/
 F: linux-user/host/riscv64/
 
+RENESAS RX CPUs
+M: Yoshinori Sato 
+S: Maintained
+F: target/rx/
+F: hw/rx/
+F: include/hw/rx/
+
 S390 TCG CPUs
 M: Richard Henderson 
 M: David Hildenbrand 
@@ -1167,6 +1174,18 @@ F: pc-bios/canyonlands.dt[sb]
 F: pc-bios/u-boot-sam460ex-20100605.bin
 F: roms/u-boot-sam460ex
 
+RX Machines
+---
+rx-virt
+M: Yoshinori Sato 
+S: Maintained
+F: hw/rx/rxqemu.c
+F: hw/intc/rx_icu.c
+F: hw/timer/renesas_*.c
+F: hw/char/renesas_sci.c
+F: include/hw/timer/renesas_*.h
+F: include/hw/char/renesas_sci.h
+
 SH4 Machines
 
 R2D
-- 
2.20.1




[PATCH v31 12/22] target/rx: Collect all bytes during disassembly

2020-02-22 Thread Yoshinori Sato
From: Richard Henderson 

Collected, to be used in the next patch.

Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Yoshinori Sato 
Signed-off-by: Yoshinori Sato 
Message-Id: <20190607091116.49044-23-ys...@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/rx/disas.c | 62 ---
 1 file changed, 42 insertions(+), 20 deletions(-)

diff --git a/target/rx/disas.c b/target/rx/disas.c
index ebc1a44249..5a32a87534 100644
--- a/target/rx/disas.c
+++ b/target/rx/disas.c
@@ -25,43 +25,59 @@ typedef struct DisasContext {
 disassemble_info *dis;
 uint32_t addr;
 uint32_t pc;
+uint8_t len;
+uint8_t bytes[8];
 } DisasContext;
 
 
 static uint32_t decode_load_bytes(DisasContext *ctx, uint32_t insn,
-   int i, int n)
+  int i, int n)
 {
-bfd_byte buf;
+uint32_t addr = ctx->addr;
+
+g_assert(ctx->len == i);
+g_assert(n <= ARRAY_SIZE(ctx->bytes));
+
 while (++i <= n) {
-ctx->dis->read_memory_func(ctx->addr++, , 1, ctx->dis);
-insn |= buf << (32 - i * 8);
+ctx->dis->read_memory_func(addr++, >bytes[i - 1], 1, ctx->dis);
+insn |= ctx->bytes[i - 1] << (32 - i * 8);
 }
+ctx->addr = addr;
+ctx->len = n;
+
 return insn;
 }
 
 static int32_t li(DisasContext *ctx, int sz)
 {
-int32_t addr;
-bfd_byte buf[4];
-addr = ctx->addr;
+uint32_t addr = ctx->addr;
+uintptr_t len = ctx->len;
 
 switch (sz) {
 case 1:
+g_assert(len + 1 <= ARRAY_SIZE(ctx->bytes));
 ctx->addr += 1;
-ctx->dis->read_memory_func(addr, buf, 1, ctx->dis);
-return (int8_t)buf[0];
+ctx->len += 1;
+ctx->dis->read_memory_func(addr, ctx->bytes + len, 1, ctx->dis);
+return (int8_t)ctx->bytes[len];
 case 2:
+g_assert(len + 2 <= ARRAY_SIZE(ctx->bytes));
 ctx->addr += 2;
-ctx->dis->read_memory_func(addr, buf, 2, ctx->dis);
-return ldsw_le_p(buf);
+ctx->len += 2;
+ctx->dis->read_memory_func(addr, ctx->bytes + len, 2, ctx->dis);
+return ldsw_le_p(ctx->bytes + len);
 case 3:
+g_assert(len + 3 <= ARRAY_SIZE(ctx->bytes));
 ctx->addr += 3;
-ctx->dis->read_memory_func(addr, buf, 3, ctx->dis);
-return (int8_t)buf[2] << 16 | lduw_le_p(buf);
+ctx->len += 3;
+ctx->dis->read_memory_func(addr, ctx->bytes + len, 3, ctx->dis);
+return (int8_t)ctx->bytes[len + 2] << 16 | lduw_le_p(ctx->bytes + len);
 case 0:
+g_assert(len + 4 <= ARRAY_SIZE(ctx->bytes));
 ctx->addr += 4;
-ctx->dis->read_memory_func(addr, buf, 4, ctx->dis);
-return ldl_le_p(buf);
+ctx->len += 4;
+ctx->dis->read_memory_func(addr, ctx->bytes + len, 4, ctx->dis);
+return ldl_le_p(ctx->bytes + len);
 default:
 g_assert_not_reached();
 }
@@ -110,7 +126,7 @@ static const char psw[] = {
 static void rx_index_addr(DisasContext *ctx, char out[8], int ld, int mi)
 {
 uint32_t addr = ctx->addr;
-uint8_t buf[2];
+uintptr_t len = ctx->len;
 uint16_t dsp;
 
 switch (ld) {
@@ -119,14 +135,18 @@ static void rx_index_addr(DisasContext *ctx, char out[8], 
int ld, int mi)
 out[0] = '\0';
 return;
 case 1:
+g_assert(len + 1 <= ARRAY_SIZE(ctx->bytes));
 ctx->addr += 1;
-ctx->dis->read_memory_func(addr, buf, 1, ctx->dis);
-dsp = buf[0];
+ctx->len += 1;
+ctx->dis->read_memory_func(addr, ctx->bytes + len, 1, ctx->dis);
+dsp = ctx->bytes[len];
 break;
 case 2:
+g_assert(len + 2 <= ARRAY_SIZE(ctx->bytes));
 ctx->addr += 2;
-ctx->dis->read_memory_func(addr, buf, 2, ctx->dis);
-dsp = lduw_le_p(buf);
+ctx->len += 2;
+ctx->dis->read_memory_func(addr, ctx->bytes + len, 2, ctx->dis);
+dsp = lduw_le_p(ctx->bytes + len);
 break;
 default:
 g_assert_not_reached();
@@ -1392,8 +1412,10 @@ int print_insn_rx(bfd_vma addr, disassemble_info *dis)
 DisasContext ctx;
 uint32_t insn;
 int i;
+
 ctx.dis = dis;
 ctx.pc = ctx.addr = addr;
+ctx.len = 0;
 
 insn = decode_load();
 if (!decode(, insn)) {
-- 
2.20.1




Re: [PATCH v2] riscv: sifive_u: Add a "serial" property for board serial number

2020-02-22 Thread Bin Meng
On Sun, Feb 16, 2020 at 9:55 PM Bin Meng  wrote:
>
> At present the board serial number is hard-coded to 1, and passed
> to OTP model during initialization. Firmware (FSBL, U-Boot) uses
> the serial number to generate a unique MAC address for the on-chip
> ethernet controller. When multiple QEMU 'sifive_u' instances are
> created and connected to the same subnet, they all have the same
> MAC address hence it creates a unusable network.
>
> A new "serial" property is introduced to specify the board serial
> number. When not given, the default serial number 1 is used.
>
> Signed-off-by: Bin Meng 
>
> ---
>
> Changes in v2:
> - Move setting OTP serial number property from riscv_sifive_u_soc_init()
>   to riscv_sifive_u_soc_realize(), to fix the 'check-qtest-riscv' error.
>   I am not really sure why doing so could fix the 'make check' error.
>   The v1 patch worked fine and nothing seems wrong.
>
>  hw/riscv/sifive_u.c | 21 -
>  include/hw/riscv/sifive_u.h |  1 +
>  2 files changed, 21 insertions(+), 1 deletion(-)
>

Ping?

Regards,
Bin



Re: [PATCH v2 17/19] tcg: save vaddr temp for plugin usage

2020-02-22 Thread Emilio G. Cota
On Thu, Feb 13, 2020 at 22:51:07 +, Alex Bennée wrote:
> From: Richard Henderson 
> 
> While do_gen_mem_cb does copy (via extu_tl_i64) vaddr into a new temp
> this won't help if the vaddr temp gets clobbered by the actual
> load/store op. To avoid this clobbering we explicitly copy vaddr
> before the op to ensure it is live my the time we do the
> instrumentation.

s/my the time/by the time/

Reviewed-by: Emilio G. Cota 

E.



Re: [PATCH v2 12/13] hw/arm/raspi: Add the Raspberry Pi B+ machine

2020-02-22 Thread Niek Linnenbank
Hey Philippe,

Very nice to see that the Raspberry 1 will be supported again, thanks for
contributing this!

I tried to bring up the machine using raspbian 2019-09-26. It ran throught
the early kernel initialisation
but for me it gets stuck at this point:

./arm-softmmu/qemu-system-arm -M raspi1b -kernel
$HOME/raspi/boot/kernel.img -append 'printk.time=0
earlycon=pl011,0x20201000 console=ttyAMA0 rootwait root=/dev/mmcblk0p2' \
-dtb $HOME/raspi/boot/bcm2708-rpi-b-plus.dtb -m 512 -sd
$HOME/raspi/2019-09-26-raspbian-buster-lite.img -serial stdio -s

[0.00] Booting Linux on physical CPU 0x0
[0.00] Linux version 4.19.75+ (dom@buildbot) (gcc version 4.9.3
(crosstool-NG crosstool-ng-1.22.0-88-g8460611)) #1270 Tue Sep 24 18:38:54
BST 2019
[0.00] CPU: ARMv6-compatible processor [410fb767] revision 7
(ARMv7), cr=00c5387d
[0.00] CPU: VIPT aliasing data cache, unknown instruction cache
[0.00] OF: fdt: Machine model: Raspberry Pi Model B+
[0.00] earlycon: pl11 at MMIO 0x20201000 (options '')
[0.00] bootconsole [pl11] enabled
[0.00] Memory policy: Data cache writeback
[0.00] cma: Reserved 8 MiB at 0x1b80
[0.00] random: get_random_bytes called from start_kernel+0x8c/0x49c
with crng_init=0
[0.00] Built 1 zonelists, mobility grouping on.  Total pages: 113680
[0.00] Kernel command line: printk.time=0 earlycon=pl011,0x20201000
console=ttyAMA0 rootwait root=/dev/mmcblk0p2
Dentry cache hash table entries: 65536 (order: 6, 262144 bytes)
Inode-cache hash table entries: 32768 (order: 5, 131072 bytes)
Memory: 434380K/458752K available (6973K kernel code, 635K rwdata, 2080K
rodata, 464K init, 797K bss, 16180K reserved, 8192K cma-reserved)
Virtual kernel memory layout:
vector  : 0x - 0x1000   (   4 kB)
fixmap  : 0xffc0 - 0xfff0   (3072 kB)
vmalloc : 0xdc80 - 0xff80   ( 560 MB)
lowmem  : 0xc000 - 0xdc00   ( 448 MB)
modules : 0xbf00 - 0xc000   (  16 MB)
  .text : 0x(ptrval) - 0x(ptrval)   (6975 kB)
  .init : 0x(ptrval) - 0x(ptrval)   ( 464 kB)
  .data : 0x(ptrval) - 0x(ptrval)   ( 636 kB)
   .bss : 0x(ptrval) - 0x(ptrval)   ( 798 kB)
SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
ftrace: allocating 25197 entries in 74 pages
NR_IRQS: 16, nr_irqs: 16, preallocated irqs: 16
sched_clock: 32 bits at 1000kHz, resolution 1000ns, wraps every
2147483647500ns
clocksource: timer: mask: 0x max_cycles: 0x, max_idle_ns:
1911260446275 ns
bcm2835: system timer (irq = 27)
Console: colour dummy device 80x30

Maybe it should switch to the graphical console here, but I dont see the
boot splash logo either (when using -stdio instead of -nographic).
With -M raspi2 and -dtb bcm2709-rpi-2-b.dtb the same raspbian image can
fully boot to the login console.

Regards,
Niek



On Mon, Feb 17, 2020 at 12:51 PM Philippe Mathieu-Daudé 
wrote:

>   $ qemu-system-arm -M raspi1b -serial stdio \
>   -kernel raspberrypi/firmware/boot/kernel.img \
>   -dtb raspberrypi/firmware/boot/bcm2708-rpi-b.dtb \
>   -append 'printk.time=0 earlycon=pl011,0x20201000 console=ttyAMA0'
>   [0.00] Booting Linux on physical CPU 0x0
>   [0.00] Linux version 4.19.69+ (dom@buildbot) (gcc version 4.9.3
> (crosstool-NG crosstool-ng-1.22.0-88-g8460611)) #1261 Tue Sep 3 20:21:01
> BST 2019
>   [0.00] CPU: ARMv6-compatible processor [410fb767] revision 7
> (ARMv7), cr=00c5387d
>   [0.00] CPU: VIPT aliasing data cache, unknown instruction cache
>   [0.00] OF: fdt: Machine model: Raspberry Pi Model B
>   [0.00] earlycon: pl11 at MMIO 0x20201000 (options '')
>   [0.00] bootconsole [pl11] enabled
>   [0.00] Memory policy: Data cache writeback
>   [0.00] cma: Reserved 8 MiB at 0x1b80
>   [0.00] random: get_random_bytes called from
> start_kernel+0x8c/0x49c with crng_init=0
>   [0.00] Built 1 zonelists, mobility grouping on.  Total pages:
> 113680
>   [0.00] Kernel command line: printk.time=0
> earlycon=pl011,0x20201000 console=ttyAMA0
>   Dentry cache hash table entries: 65536 (order: 6, 262144 bytes)
>   Inode-cache hash table entries: 32768 (order: 5, 131072 bytes)
>   Memory: 434380K/458752K available (6971K kernel code, 635K rwdata, 2080K
> rodata, 464K init, 797K bss, 16180K reserved, 8192K cma-reserved)
>   ...
>
> Signed-off-by: Philippe Mathieu-Daudé 
> ---
>  hw/arm/raspi.c | 13 +
>  1 file changed, 13 insertions(+)
>
> diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
> index 3537a329ac..2d9f4e3085 100644
> --- a/hw/arm/raspi.c
> +++ b/hw/arm/raspi.c
> @@ -324,6 +324,15 @@ static void
> raspi_machine_class_common_init(MachineClass *mc,
>  mc->default_ram_size = board_ram_size(board_rev);
>  };
>
> +static void raspi1b_machine_class_init(ObjectClass *oc, void *data)
> +{
> +MachineClass *mc = MACHINE_CLASS(oc);
> +RaspiMachineClass *rmc = 

Re: [PATCH] hw/ide: Remove status register read side effect

2020-02-22 Thread BALATON Zoltan

On Sat, 22 Feb 2020, BALATON Zoltan wrote:

On Sat, 22 Feb 2020, Mark Cave-Ayland wrote:

On 21/02/2020 06:50, jasper.low...@bt.com wrote:

The Linux libATA API documentation mentions that on some hardware,
reading the status register has the side effect of clearing the
interrupt condition. When emulating the generic Sun4u machine running
Solaris 10, the Solaris 10 CMD646 driver exits fatally because of this
emulated side effect. This side effect is likely to not exist on real
CMD646 hardware.

Signed-off-by: Jasper Lowell 
---
 hw/ide/core.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/hw/ide/core.c b/hw/ide/core.c
index 8eb766..82fd0632ac 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -2210,7 +2210,6 @@ uint32_t ide_ioport_read(void *opaque, uint32_t 
addr)

 } else {
 ret = s->status;
 }
-qemu_irq_lower(bus->irq);
 break;
 }


I don't think that this is correct: from memory when I last looked at this, 
there
were 2 IDE status registers: the one from the original specification which 
clears the
IRQ upon read, and another one in subsequent revisions which allows you to 
read the
value without clearing any pending IRQ. My guess would be that changing 
this would
not only cause QEMU to deviate from the specification, but causes problems 
in other OSs.


You're right, legacy ide has two status registers as described here:

ftp://ftp.seagate.com/pub/acrobat/reference/111-1c.pdf

Now question is which of these the above is emulating? Looks like CMD646


We have both ide_status_read() which does not clear irq and 
ide_ioport_read() which does. pci_ide_cmd_read() which PCI ide should use 
calls ide_status_read() so I wonder why did reading status cleared irq on 
CMD646? So maybe it's cleared from somewhere else and above change should 
not be needed.


Regards,
BALATON Zoltan



Re: [PATCH] hw/ide: Remove status register read side effect

2020-02-22 Thread BALATON Zoltan

On Sat, 22 Feb 2020, Mark Cave-Ayland wrote:

On 21/02/2020 06:50, jasper.low...@bt.com wrote:

The Linux libATA API documentation mentions that on some hardware,
reading the status register has the side effect of clearing the
interrupt condition. When emulating the generic Sun4u machine running
Solaris 10, the Solaris 10 CMD646 driver exits fatally because of this
emulated side effect. This side effect is likely to not exist on real
CMD646 hardware.

Signed-off-by: Jasper Lowell 
---
 hw/ide/core.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/hw/ide/core.c b/hw/ide/core.c
index 8eb766..82fd0632ac 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -2210,7 +2210,6 @@ uint32_t ide_ioport_read(void *opaque, uint32_t addr)
 } else {
 ret = s->status;
 }
-qemu_irq_lower(bus->irq);
 break;
 }


I don't think that this is correct: from memory when I last looked at this, 
there
were 2 IDE status registers: the one from the original specification which 
clears the
IRQ upon read, and another one in subsequent revisions which allows you to read 
the
value without clearing any pending IRQ. My guess would be that changing this 
would
not only cause QEMU to deviate from the specification, but causes problems in 
other OSs.


You're right, legacy ide has two status registers as described here:

ftp://ftp.seagate.com/pub/acrobat/reference/111-1c.pdf

Now question is which of these the above is emulating? Looks like CMD646 
should not clear interrupt when reading status reg so maybe instead of 
removing this from here another change is needed to CMD646 specific read 
func to read alternate status instead of status reg?


Regards,
BALATON Zoltan



Re: [PATCH 0/3] hw: More dma_memory_read/write() API cleanup

2020-02-22 Thread Mark Cave-Ayland
On 21/02/2020 13:25, Philippe Mathieu-Daudé wrote:

> Following up "global exec/memory/dma APIs cleanup"
> https://www.mail-archive.com/qemu-devel@nongnu.org/msg681475.html
> 
> Few more cleanups in PCNET & SCSI ESP devices.
> 
> Philippe Mathieu-Daudé (3):
>   hw/dma/sparc32_dma: Make espdma_memory_[read/write] static
>   hw/scsi/esp: Let ESPDMAMemoryReadWriteFunc take void pointer and
> size_t
>   hw/net/pcnet: Let phys_mem_read/write take void pointer and boolean
> 
>  hw/net/pcnet.h |  4 ++--
>  include/hw/scsi/esp.h  |  2 +-
>  include/hw/sparc/sparc32_dma.h |  6 ++
>  hw/dma/sparc32_dma.c   |  8 
>  hw/net/pcnet-pci.c |  5 +++--
>  hw/net/pcnet.c | 16 
>  hw/scsi/esp-pci.c  |  6 +++---
>  7 files changed, 23 insertions(+), 24 deletions(-)

LGTM.

Reviewed-by: Mark Cave-Ayland 


ATB,

Mark.



Re: [PATCH] hw/ide: Remove status register read side effect

2020-02-22 Thread Mark Cave-Ayland
On 21/02/2020 06:50, jasper.low...@bt.com wrote:

> The Linux libATA API documentation mentions that on some hardware,
> reading the status register has the side effect of clearing the
> interrupt condition. When emulating the generic Sun4u machine running
> Solaris 10, the Solaris 10 CMD646 driver exits fatally because of this
> emulated side effect. This side effect is likely to not exist on real
> CMD646 hardware.
> 
> Signed-off-by: Jasper Lowell 
> ---
>  hw/ide/core.c | 1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/hw/ide/core.c b/hw/ide/core.c
> index 8eb766..82fd0632ac 100644
> --- a/hw/ide/core.c
> +++ b/hw/ide/core.c
> @@ -2210,7 +2210,6 @@ uint32_t ide_ioport_read(void *opaque, uint32_t addr)
>  } else {
>  ret = s->status;
>  }
> -qemu_irq_lower(bus->irq);
>  break;
>  }

I don't think that this is correct: from memory when I last looked at this, 
there
were 2 IDE status registers: the one from the original specification which 
clears the
IRQ upon read, and another one in subsequent revisions which allows you to read 
the
value without clearing any pending IRQ. My guess would be that changing this 
would
not only cause QEMU to deviate from the specification, but causes problems in 
other OSs.


ATB,

Mark.



Re: [PATCH] hw/ide: Remove status register read side effect

2020-02-22 Thread BALATON Zoltan

On Sat, 22 Feb 2020, jasper.low...@bt.com wrote:

This patch doesn't solve all the problems for Solaris 10. It gets
further in the boot process but it is still unable to mount the file
system. I suspect that there are more bugs in the IDE/CMD646 emulation.
I'm going to continue looking into it. It's still possible we are being


One more idea to check is if the irq of the IDE device is mapped at the 
same IRQ line and described correctly in the open firmware device tree. 
You may need info from a real machine for that, I've tried to search for 
it but could not find any device tree dumps or info on how irqs are mapped 
in the real hardware. Since Linux can find it it's probably OK but maybe 
Solaris expects the irq to be mapped somewhere else or gets the info on 
this from some other place than Linux and that could have a bug? Not sure 
if this helps but I have no better idea.


Regards,
BALATON Zoltan



Re: [RFC PATCH v3 00/27] Add subcluster allocation to qcow2

2020-02-22 Thread Alberto Garcia
On Fri 21 Feb 2020 06:10:52 PM CET, Max Reitz wrote:

> So now I wonder on what your plans are after this series.

Apart from some fixes here and there, there are some things that I would
live to solve:

- I'm not 100% happy with the separation between QCow2ClusterType and
  QCow2SubclusterType. The former is a strict subset of the latter and
  doesn't carry any additional information, so I think there's no need
  to have both in the code. So I'm thinking to get rid of
  QCow2ClusterType altogether.

- We discussed this already, and related to the previous point, in most
  places where the (sub)cluster type is checked what we want to know is
  whether there is a valid host address, or whether the data reads as
  zeroes, etc. So one possibility is to make qcow2_get_subcluster_type()
  return status flags like the existing BDRV_BLOCK_DATA,
  BDRV_BLOCK_OFFSET_VALID, ... and check those ones instead. Some
  functions become less verbose with this kind of approach, but I'm not
  sure that it works so well with others.

- We also discussed this already, but qcow2_get_cluster_offset() returns
  an offset to the beginning of the cluster. This makes less sense when
  we start working at the subcluster level, but even at the moment the
  reality is that no one uses that offset. All callers use the final
  unaligned host offset. So I have a few patches that change that.

> Here are some things that come to my mind, and I wonder whether you
> plan to address them or whether there are more things to do still:
>
> - In v2, you had a patch for preallocation support with backing files.
> It didn’t quite work, which is why I think you dropped it for now (why
> not, it isn’t crucial).

There was already a problem with preallocation and backing files (
https://lists.gnu.org/archive/html/qemu-block/2019-11/msg00691.html ) so
I decided to withdraw the patches for subclusters and reevaluate the
situation when that was sorted out.

> - There is a TODO on subcluster zeroing.

I'm not sure if I'll fix that now, but I'll give it a try when we all
are happy with the rest the patches and the general design.

> - I think adding support to amend for switching extended_l2 on or off
> would make sense.  But maybe it’s too complicated to be worth the
> effort.

I haven't thought about that, but it does sound too complicated to be
worth it.

> - As I noted in v2, I think it’d be great if it were possible to run
> the iotests with -o extended_l2=on.  But I suppose this kind of
> depends on me adding data_file support to the Python tests first...

Yes.

Berto



Re: [PATCH] hw/ide: Remove status register read side effect

2020-02-22 Thread BALATON Zoltan

On Sat, 22 Feb 2020, jasper.low...@bt.com wrote:

I haven't found any documentation that mention that side effect either.
As you say, it only mentions that you should set the bit to clear.
While the side effect of clearing interrupts by reading the status
register doesn't appear to be in documentation anywhere (to my


The PCI bus master IDE spec also only says the status register is read / 
write clear but does not mention clearing bits on read. I've also traced 
back the origin of this code in QEMU and looks like it was there forever 
since commit fc01f7e7f90 when IDE emulation was added. Interesting that 
only Solaris driver broke because of this so maybe there are hardware 
implementations which do clear this bit so drivers are prepared to handle 
that. I think based on at least two docs it would be correct to remove 
this but wonder what other drivers would this change break. Anyway:


Reviewed-by: BALATON Zoltan 


knowledge), I do see this side effect referenced in the source code of
drivers occasionally.

In /drivers/ide/ide-io.c of the Linux kernel:
/*
* Whack the status register, just in case
* we have a leftover pending IRQ.
*/
(void)hwif->tp_ops->read_status(hwif);

Along with:
*   There's nothing really useful we can do with an unexpected
interrupt,
*   other than reading the status register (to clear it), and
logging it.

The CMD64x specific code in the Linux kernel does explicitly set the
IRQ bits in the bus master IDE status register to clear it. I'm not
sure why, so maybe someone else can chime in explaining why Linux


It seems likely that CMD646 does not clear irq on read but some other 
controllers probably do.


Regards,
BALATON Zoltan



Re: [PATCH 1/2] riscv: roms: Add 32-bit OpenSBI firmware image for sifive_u

2020-02-22 Thread Bin Meng
Hi Philippe,

On Fri, Feb 21, 2020 at 4:54 PM Philippe Mathieu-Daudé
 wrote:
>
> On 2/21/20 6:54 AM, Anup Patel wrote:
> > On Fri, Feb 21, 2020 at 8:08 AM Bin Meng  wrote:
> >>
> >> Hi Philippe,
> >>
> >> On Fri, Feb 21, 2020 at 1:31 AM Philippe Mathieu-Daudé
> >>  wrote:
> >>>
> >>> Hi Bin,
> >>>
> >>> On 2/20/20 3:42 PM, Bin Meng wrote:
>  Although the real world SiFive HiFive Unleashed board is a 64-bit
>  hardware configuration, with QEMU it is possible to test 32-bit
>  configuration with the same hardware features.
> 
>  This updates the roms Makefile to add the build rules for creating
>  the 32-bit OpenSBI firmware image for sifive_u machine. A pre-built
>  OpenSBI image (built from commit 3e7d666) has been added as the
>  default bios for 32-bit sifive_u machine.
> >>>
> >>> With QEMU:
> >>>
> >>> fatal: ambiguous argument '3e7d666': unknown revision or path not in the
> >>> working tree.
> >>>
> >>> This looks like an OpenSBI commit but QEMU only include up to v0.5.
> >>>
> >>> Can you build v0.5? Else can you update the submodule?
> >>>
> >>
> >> Will do in v2.
> >
> > We plan to release OpenSBI v0.6 on monday (24th Feb 2020) so maybe
> > you can update all RISC-V ROM images based on OpenSBI v0.6 ??
>
> Sounds cleaner.

Yes, will update all RISC-V ROM images to v0.6 in v2.

>
> Suggestions when updating a QEMU git-submodule:
>
>
> - Include output of submodule 'git-log --reverse --oneline'
>
> - Send series/pull-request with 'git-format-patch --no-binary'
>

Sure. I believe with "--no-binary" I will need provide a repo for pull?

> >
> >>
> >>> Also, can you add a CI job to build this, so we have reproducible builds
> >>> (see QEMU commit 71920809ceabed as example)?
> >>
> >> I cannot find any document for how to test CI job with gitlab CI. Does
> >> QEMU has a public CI runner for testing?
>
> There is:
>
> https://wiki.qemu.org/Testing
> https://wiki.qemu.org/Testing/CI
>
> Currently you can use whatever CI best suits you (although long term is
> probably to rely more on GitLab, because it allows adding runners on
> particular hardware/setup).

Thank you very much for the pointers. I will add a CI job in v2.

Regards,
Bin



Re: [PATCH v3 0/3] Dump QCOW2 metadata

2020-02-22 Thread Eric Blake

On 2/20/20 6:28 AM, Kevin Wolf wrote:

Am 20.02.2020 um 12:58 hat Max Reitz geschrieben:

On 14.01.20 09:22, Andrey Shinkevich wrote:

The information about QCOW2 metadata allocations in an image ELF-file is
helpful for finding issues with the image data integrity.


Sorry that I’m replying only so late – but I don’t know why we need this
in qemu, and this cover letter doesn’t provide a justification.  I mean,
it isn’t too complex (from the diffstat), but wouldn’t it be better to
just have a script for this?


Specifically, we could extend tests/qemu-iotests/qcow2.py. This seems to
be debugging output that would be in line with what the script is
already used for.


I also just discovered GNU poke, http://jemarch.net/poke, which is an 
arbitrary binary-format editor with a fairly good example of how it can 
be used to inspect ELF files.  I'm wondering if it would be easier to 
write a pickle describing the qcow2 format that would make it easier to 
do interactive browsing/editing of a qcow2 file, at the expense of 
having to depend on poke (which has not yet hit the 1.0 release and is 
not yet bundled for Fedora).


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




Re: [PATCH] target: i386: Check float overflow about register stack

2020-02-22 Thread Chen Gang
On 2020/2/22 下午3:37, Paolo Bonzini wrote:
> On 22/02/20 03:10, Chen Gang wrote:
>> Set C1 to 1 if stack overflow occurred; set to 0 otherwise".
>>
>> In helper_fxam_ST0, I guess, we need "env->fpus |= 0x200" (but I don't
>> know wheter it will be conflict with SIGND(temp)). And we have to still
>> need foverflow, because all env->fptags being 0 doesn't mean overflow.
> 
> No, you need to add "env->fpus |= 0x200" and "env->fpus &= ~0x200"
> directly to fpush, fpop, etc.
> 

OK. The content below is my next TODO, welcome your opinions.

When overflow occurs, for me, we need keep everything no touch except
set C1 flag. In fxam, we don't clear C1, but keep no touch for clearning
C1 in another places.

When underflow occurs, for me, we need keep everything no touch except
set env->fpstt 8, so the next consecutive fpop/f[i]stp* can be checked
easier, and the next fpush/f[i]ld* can work well in normal.

For fxam, we check env->fpstt == 8 and env->fptags for empty. And when
env->fpstt is 8, it need be set 7 before used in fincstp and ffree_STN.

Thanks.





Re: [PATCH] hw/ide: Remove status register read side effect

2020-02-22 Thread BALATON Zoltan

On Sat, 22 Feb 2020, jasper.low...@bt.com wrote:

I think the reason why the Solaris 10 driver crashes fatally whereas
Linux and OpenBSD ignore the side effect is because when clearing
interrupts, Solaris 10 expects the interrupt bit to be set and checks
this. Linux and OpenBSD appear to clear it regardless of its state.


I've also found this thread:

https://lucky.openbsd.misc.narkive.com/hA6XG7Fu/bus-master-dma-error-missing-interrupt

which seems to talk about missing IRQ in UDMA mode similar to our problem 
and it suggests OpenBSD detects this and downgrades to PIO mode so it 
would still work. Did you check if this is why it works with OpenBSD or it 
really uses UDMA mode?



This patch doesn't solve all the problems for Solaris 10. It gets
further in the boot process but it is still unable to mount the file
system. I suspect that there are more bugs in the IDE/CMD646 emulation.
I'm going to continue looking into it. It's still possible we are being
affected by the same bugs. Right now, I'm considering that the
unresponsive serial console under Sun4u on Solaris 10 is due to not
being able to mount the file system and pull the required assets for
the installation menu.


This is possible. The hang I get during boot with PPC OSes I've tried is 
also becuase not being able to read CD drive after switching to UDMA mode. 
This would suggest bug may be in either common ide code or ide-cd 
emulation but could as well be in irq routing (in which case it's separate 
but similar bug in different machine emulations). Is there a way to 
disable UDMA mode in Solaris to check if it would work better when only 
using PIO? That might help locate the bug further.


In my case I've tested with both on board IDE and adding an sii3112 PCI 
card emulation, these both use common bmdma code but route IRQs 
differently. I see some irqs arriving up to the interrupt controller but 
CPU irq is not raised for some reason so I'm not sure it's a bug in common 
code or somewhere else.



this change seems to break
something else according to a CI test report from patchew.


The test appears to break here in /tests/qtest/ide-test.c for obvious
reasons:
/* Reading the status register clears the IRQ */
g_assert(!qtest_get_irq(qts, IDE_PRIMARY_IRQ));

Should the patch I've suggested be correct, this test would need to be
updated. This is my first patch attempt for QEMU so I'm not sure what


OK, I haven't checked the test just noticed the failure.


the process is. Should I be submitting a new V2 patch with these
changes? I won't have the opportunity to update the patch for a few
days but will continue watching the thread for reviews.


I'd suggest to wait a few days to give people a chance to review the patch 
then submit a v2 with all the requested changes if any. You can submit v2 
right away but then if someone finds something you'll need more versions 
which is OK as well, your decision how many versions you want to submit. 
Since this patch is only 1 line there's not much people could ask to 
change about it and v2 could allow CI to run and maybe reveal problems so 
maybe in this case a v2 with also fixing the test might help to get it 
reviewed faster. I assume you're aware of the page about patch submission:


https://wiki.qemu.org/Contribute/SubmitAPatch

Regards,
BALATON Zoltan



Re: [PULL 24/31] fuzz: support for fork-based fuzzing.

2020-02-22 Thread Eric Blake

On 2/22/20 2:50 AM, Stefan Hajnoczi wrote:

From: Alexander Bulekov 

fork() is a simple way to ensure that state does not leak in between
fuzzing runs. Unfortunately, the fuzzer mutation engine relies on
bitmaps which contain coverage information for each fuzzing run, and
these bitmaps should be copied from the child to the parent(where the
mutation occurs). These bitmaps are created through compile-time
instrumentation and they are not shared with fork()-ed processes, by
default. To address this, we create a shared memory region, adjust its
size and map it _over_ the counter region. Furthermore, libfuzzer
doesn't generally expose the globals that specify the location of the
counters/coverage bitmap. As a workaround, we rely on a custom linker
script which forces all of the bitmaps we care about to be placed in a
contiguous region, which is easy to locate and mmap over.

Signed-off-by: Alexander Bulekov 
Reviewed-by: Stefan Hajnoczi 
Reviewed-by: Darren Kenny 
Message-id: 20200220041118.23264-16-alx...@bu.edu
Signed-off-by: Stefan Hajnoczi 
---


Random drive-by observation:


+++ b/tests/qtest/fuzz/fork_fuzz.ld
@@ -0,0 +1,37 @@
+/* We adjust linker script modification to place all of the stuff that needs to
+ * persist across fuzzing runs into a contiguous seciton of memory. Then, it is


section


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




Re: [PATCH v1 2/2] linux-user/riscv: Update the syscall_nr's to the 5.5 kernel

2020-02-22 Thread Laurent Vivier
Le 21/02/2020 à 00:18, Alistair Francis a écrit :
> Signed-off-by: Alistair Francis 
> ---
>  linux-user/riscv/syscall_nr.h | 160 +-
>  1 file changed, 158 insertions(+), 2 deletions(-)

Could you avoid to add blanck lines: this makes review more difficult
and patch bigger for nothing.

Perhaps it would be easier too to have two files, one for 32bit and one
for 64 bit and a syscall_nr.h like this:

#ifdef TARGET_RISCV32
#include "syscall32_nr.h"
#else
#include "syscall64_nr.h"
#endif

Thanks,
Laurent

> diff --git a/linux-user/riscv/syscall_nr.h b/linux-user/riscv/syscall_nr.h
> index 5c87282209..b2b071969b 100644
> --- a/linux-user/riscv/syscall_nr.h
> +++ b/linux-user/riscv/syscall_nr.h
> @@ -10,7 +10,10 @@
>  #define TARGET_NR_io_destroy 1
>  #define TARGET_NR_io_submit 2
>  #define TARGET_NR_io_cancel 3
> +#ifndef TARGET_RISCV32
>  #define TARGET_NR_io_getevents 4
> +#endif
> +
>  #define TARGET_NR_setxattr 5
>  #define TARGET_NR_lsetxattr 6
>  #define TARGET_NR_fsetxattr 7
> @@ -23,12 +26,17 @@
>  #define TARGET_NR_removexattr 14
>  #define TARGET_NR_lremovexattr 15
>  #define TARGET_NR_fremovexattr 16
> +
>  #define TARGET_NR_getcwd 17
> +
>  #define TARGET_NR_lookup_dcookie 18
> +
>  #define TARGET_NR_eventfd2 19
> +
>  #define TARGET_NR_epoll_create1 20
>  #define TARGET_NR_epoll_ctl 21
>  #define TARGET_NR_epoll_pwait 22
> +
>  #define TARGET_NR_dup 23
>  #define TARGET_NR_dup3 24
>  #ifdef TARGET_RISCV32
> @@ -36,27 +44,35 @@
>  #else
>  #define TARGET_NR_fcntl 25
>  #endif
> +
>  #define TARGET_NR_inotify_init1 26
>  #define TARGET_NR_inotify_add_watch 27
>  #define TARGET_NR_inotify_rm_watch 28
> +
>  #define TARGET_NR_ioctl 29
> +
>  #define TARGET_NR_ioprio_set 30
>  #define TARGET_NR_ioprio_get 31
> +
>  #define TARGET_NR_flock 32
> +
>  #define TARGET_NR_mknodat 33
>  #define TARGET_NR_mkdirat 34
>  #define TARGET_NR_unlinkat 35
>  #define TARGET_NR_symlinkat 36
>  #define TARGET_NR_linkat 37
> -#define TARGET_NR_renameat 38
> +
>  #define TARGET_NR_umount2 39
>  #define TARGET_NR_mount 40
>  #define TARGET_NR_pivot_root 41
> +
>  #define TARGET_NR_nfsservctl 42
> +
>  #define TARGET_NR_statfs 43
>  #define TARGET_NR_fstatfs 44
>  #define TARGET_NR_truncate 45
>  #define TARGET_NR_ftruncate 46
> +
>  #define TARGET_NR_fallocate 47
>  #define TARGET_NR_faccessat 48
>  #define TARGET_NR_chdir 49
> @@ -69,9 +85,13 @@
>  #define TARGET_NR_openat 56
>  #define TARGET_NR_close 57
>  #define TARGET_NR_vhangup 58
> +
>  #define TARGET_NR_pipe2 59
> +
>  #define TARGET_NR_quotactl 60
> +
>  #define TARGET_NR_getdents64 61
> +
>  #ifdef TARGET_RISCV32
>  #define TARGET_NR__llseek 62
>  #else
> @@ -85,53 +105,91 @@
>  #define TARGET_NR_pwrite64 68
>  #define TARGET_NR_preadv 69
>  #define TARGET_NR_pwritev 70
> +
>  #define TARGET_NR_sendfile 71
> +
> +#ifndef TARGET_RISCV32
>  #define TARGET_NR_pselect6 72
>  #define TARGET_NR_ppoll 73
> +#endif
> +
>  #define TARGET_NR_signalfd4 74
> +
>  #define TARGET_NR_vmsplice 75
>  #define TARGET_NR_splice 76
>  #define TARGET_NR_tee 77
> +
>  #define TARGET_NR_readlinkat 78
>  #define TARGET_NR_newfstatat 79
>  #define TARGET_NR_fstat 80
> +
>  #define TARGET_NR_sync 81
>  #define TARGET_NR_fsync 82
>  #define TARGET_NR_fdatasync 83
>  #define TARGET_NR_sync_file_range 84
> +
>  #define TARGET_NR_timerfd_create 85
> +#ifndef TARGET_RISCV32
>  #define TARGET_NR_timerfd_settime 86
>  #define TARGET_NR_timerfd_gettime 87
> +#endif
> +
> +#ifndef TARGET_RISCV32
>  #define TARGET_NR_utimensat 88
> +#endif
> +
>  #define TARGET_NR_acct 89
> +
>  #define TARGET_NR_capget 90
>  #define TARGET_NR_capset 91
> +
>  #define TARGET_NR_personality 92
> +
>  #define TARGET_NR_exit 93
>  #define TARGET_NR_exit_group 94
>  #define TARGET_NR_waitid 95
> +
>  #define TARGET_NR_set_tid_address 96
>  #define TARGET_NR_unshare 97
> +
> +#ifndef TARGET_RISCV32
>  #define TARGET_NR_futex 98
> +#endif
>  #define TARGET_NR_set_robust_list 99
>  #define TARGET_NR_get_robust_list 100
> +
> +#ifndef TARGET_RISCV32
>  #define TARGET_NR_nanosleep 101
> +#endif
> +
>  #define TARGET_NR_getitimer 102
>  #define TARGET_NR_setitimer 103
> +
>  #define TARGET_NR_kexec_load 104
> +
>  #define TARGET_NR_init_module 105
>  #define TARGET_NR_delete_module 106
> +
>  #define TARGET_NR_timer_create 107
> +#ifndef TARGET_RISCV32
>  #define TARGET_NR_timer_gettime 108
> +#endif
>  #define TARGET_NR_timer_getoverrun 109
> +#ifndef TARGET_RISCV32
>  #define TARGET_NR_timer_settime 110
> +#endif
>  #define TARGET_NR_timer_delete 111
> +#ifndef TARGET_RISCV32
>  #define TARGET_NR_clock_settime 112
>  #define TARGET_NR_clock_gettime 113
>  #define TARGET_NR_clock_getres 114
>  #define TARGET_NR_clock_nanosleep 115
> +#endif
> +
>  #define TARGET_NR_syslog 116
> +
>  #define TARGET_NR_ptrace 117
> +
>  #define TARGET_NR_sched_setparam 118
>  #define TARGET_NR_sched_setscheduler 119
>  #define TARGET_NR_sched_getscheduler 120
> @@ -141,7 +199,10 @@
>  #define 

[PATCH 3/3] qemu-img: Deprecate use of -b without -F

2020-02-22 Thread Eric Blake
Creating an image that requires format probing of the backing image is
inherently unsafe (we've had several CVEs over the years based on
probes leaking information to the guest on a subsequent boot).  If our
probing algorithm ever changes, or if other tools like libvirt
determine a different probe result than we do, then subsequent use of
that backing file under a different format will present corrupted data
to the guest.  Start a deprecation clock so that future qemu-img can
refuse to create unsafe backing chains that would rely on probing.

However, there is one time where probing is safe: when we first create
an image, no guest has yet used the new image, so as long as we record
what we probed, all future uses of the image will see the same data -
so the code now records the probe results as if the user had passed
-F.  When this happens, it is unconditionally safe to record a probe
of 'raw', but any other probe is still worth warning the user in case
our probe differed from their expectations.  Similarly, if the backing
file name uses the json: psuedo-protocol, the backing name includes
the format.

iotest 114 specifically wants to create an unsafe image for later
amendment rather than defaulting to our new default of recording a
probed format, so it needs an update.

Signed-off-by: Eric Blake 
---
 block.c| 17 -
 qemu-deprecated.texi   | 12 
 qemu-img.c |  8 +++-
 tests/qemu-iotests/114 |  4 ++--
 tests/qemu-iotests/114.out |  1 +
 5 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/block.c b/block.c
index 695decbfd7b7..6595683ac52a 100644
--- a/block.c
+++ b/block.c
@@ -6013,6 +6013,15 @@ void bdrv_img_create(const char *filename, const char 
*fmt,
   "Could not open backing image to determine 
size.\n");
 goto out;
 } else {
+if (!backing_fmt && !strstart(backing_file, "json:", NULL)) {
+backing_fmt = bs->drv->format_name;
+qemu_opt_set(opts, BLOCK_OPT_BACKING_FMT, backing_fmt, NULL);
+if (bs->drv != _raw) {
+warn_report("Deprecated use of non-raw backing file "
+"without explicit backing format, using "
+"detected format of %s", backing_fmt);
+}
+}
 if (size == -1) {
 /* Opened BS, have no size */
 size = bdrv_getlength(bs);
@@ -6026,7 +6035,13 @@ void bdrv_img_create(const char *filename, const char 
*fmt,
 }
 bdrv_unref(bs);
 }
-} /* (backing_file && !(flags & BDRV_O_NO_BACKING)) */
+/* (backing_file && !(flags & BDRV_O_NO_BACKING)) */
+} else if (backing_file && !backing_fmt &&
+   !strstart(backing_file, "json:", NULL)) {
+warn_report("Deprecated use of unopened backing file without "
+"explicit backing format, use of this image requires "
+"potentially unsafe format probing");
+}

 if (size == -1) {
 error_setg(errp, "Image creation needs a size parameter");
diff --git a/qemu-deprecated.texi b/qemu-deprecated.texi
index 0671c26c806e..9228bcecd138 100644
--- a/qemu-deprecated.texi
+++ b/qemu-deprecated.texi
@@ -318,6 +318,18 @@ The above, converted to the current supported format:

 @section Related binaries

+@subsection qemu-img backing file without format (since 5.0.0)
+
+The use of @command{qemu-img create} or @command{qemu-img rebase} to
+modify an image that depends on a backing file now recommends that an
+explicit backing format be provided.  This is for safety - if qemu
+probes a different format than what you thought, the data presented to
+the guest will be corrupt; similarly, presenting a raw image to a
+guest allows the guest a potential security exploit if a future probe
+sees non-raw.  To avoid warning messages, or even future refusal to
+create an unsafe image, you must pass @option{-F} to specify the
+intended backing format.
+
 @subsection qemu-img convert -n -o (since 4.2.0)

 All options specified in @option{-o} are image creation options, so
diff --git a/qemu-img.c b/qemu-img.c
index b9375427404d..e75ec1bdb555 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -3637,7 +3637,13 @@ static int img_rebase(int argc, char **argv)
  * doesn't change when we switch the backing file.
  */
 if (out_baseimg && *out_baseimg) {
-ret = bdrv_change_backing_file(bs, out_baseimg, out_basefmt, false);
+if (blk_new_backing && !out_basefmt) {
+out_basefmt = blk_bs(blk_new_backing)->drv->format_name;
+warn_report("Deprecated use of backing file "
+"without explicit backing format, using "
+"detected format of %s", out_basefmt);
+}
+ret = bdrv_change_backing_file(bs, out_baseimg, out_basefmt, true);
 } else {
 

[PATCH 0/3] Tighten qemu-img rules on missing backing format

2020-02-22 Thread Eric Blake
In the past, we have had CVEs caused by qemu probing one image type
when an image started out as another but the guest was able to modify
content.  The solution to those CVEs was to encode backing format
information into qcow2, to ensure that once we make a decision, we
don't have to probe any further.  However, we failed to enforce this
at the time.  And now that libvirt is switching to -blockdev, it has
come back to bite us: with -block, libvirt had no easy way (other than
json:{} pseudoprotocol) to force a backing file, but with -blockdev,
libvirt HAS to use blockdev-open on the backing chain and supply a
backing format there, and thus has to probe images.  If libvirt ever
probes differently than qemu, we are back to the potential
guest-visible data corruption or potential host CVEs.

It's time to deprecate images without backing formats.  This patch
series does two things: 1. record an implicit backing format where one
is learned (although sadly, not all qemu-img commands are able to
learn a format), 2. warn to the user any time a probe had ambiguous
results or a backing format is omitted from an image.  All previous
images without a backing format are still usable, but hopefully the
warnings (along with libvirt's complaints about images without a
backing format) help us pinpoint remaining applications that are
creating images on their own without recording a backing format.

Perhaps I need to amend patch 3 and/or add a followup patch 4 that
adds further iotest coverage of all the new warnings (patch 1 touched
all the './check -qcow2' tests that were affected by the new warnings,
except for 114 which actually wanted to trigger the warning, if you
want to apply the series out of order to see the impact of the
warnings).

Eric Blake (3):
  iotests: Specify explicit backing format where sensible
  block: Add support to warn on backing file change without format
  qemu-img: Deprecate use of -b without -F

 block.c   | 31 ---
 block/qcow2.c |  2 +-
 block/stream.c|  2 +-
 blockdev.c|  3 ++-
 include/block/block.h |  4 +--
 qemu-deprecated.texi  | 12 +
 qemu-img.c| 10 ++--
 tests/qemu-iotests/017|  2 +-
 tests/qemu-iotests/017.out|  2 +-
 tests/qemu-iotests/018|  2 +-
 tests/qemu-iotests/018.out|  2 +-
 tests/qemu-iotests/019|  5 ++--
 tests/qemu-iotests/019.out|  2 +-
 tests/qemu-iotests/020|  2 +-
 tests/qemu-iotests/020.out|  2 +-
 tests/qemu-iotests/024|  8 +++---
 tests/qemu-iotests/024.out|  5 ++--
 tests/qemu-iotests/028|  4 +--
 tests/qemu-iotests/028.out|  2 +-
 tests/qemu-iotests/030| 26 +--
 tests/qemu-iotests/034|  2 +-
 tests/qemu-iotests/034.out|  2 +-
 tests/qemu-iotests/037|  2 +-
 tests/qemu-iotests/037.out|  2 +-
 tests/qemu-iotests/038|  2 +-
 tests/qemu-iotests/038.out|  2 +-
 tests/qemu-iotests/039|  3 ++-
 tests/qemu-iotests/039.out|  2 +-
 tests/qemu-iotests/040| 47 +--
 tests/qemu-iotests/041| 37 ++-
 tests/qemu-iotests/042|  4 +--
 tests/qemu-iotests/043| 18 +++---
 tests/qemu-iotests/043.out| 16 +++-
 tests/qemu-iotests/046|  2 +-
 tests/qemu-iotests/046.out|  2 +-
 tests/qemu-iotests/050|  4 +--
 tests/qemu-iotests/050.out|  2 +-
 tests/qemu-iotests/051|  2 +-
 tests/qemu-iotests/051.out|  2 +-
 tests/qemu-iotests/051.pc.out |  2 +-
 tests/qemu-iotests/060|  2 +-
 tests/qemu-iotests/060.out|  2 +-
 tests/qemu-iotests/061| 10 
 tests/qemu-iotests/061.out| 10 
 tests/qemu-iotests/069|  2 +-
 tests/qemu-iotests/069.out|  2 +-
 tests/qemu-iotests/073|  2 +-
 tests/qemu-iotests/073.out|  2 +-
 tests/qemu-iotests/082| 16 +++-
 tests/qemu-iotests/082.out| 16 ++--
 tests/qemu-iotests/085|  4 +--
 tests/qemu-iotests/085.out|  6 ++---
 tests/qemu-iotests/089|  2 +-
 tests/qemu-iotests/089.out|  2 +-
 tests/qemu-iotests/095|  4 +--
 tests/qemu-iotests/095.out|  4 +--
 tests/qemu-iotests/097|  4 +--
 tests/qemu-iotests/097.out| 16 ++--
 tests/qemu-iotests/098|  2 +-
 tests/qemu-iotests/098.out|  8 +++---
 tests/qemu-iotests/110|  4 +--
 tests/qemu-iotests/110.out|  4 +--
 tests/qemu-iotests/114|  4 +--
 tests/qemu-iotests/114.out|  1 +
 tests/qemu-iotests/122| 27 
 tests/qemu-iotests/122.out|  8 +++---
 tests/qemu-iotests/126|  4 +--
 tests/qemu-iotests/126.out|  4 +--
 tests/qemu-iotests/127|  4 +--
 tests/qemu-iotests/127.out|  4 +--
 tests/qemu-iotests/129|  3 ++-
 tests/qemu-iotests/133|  2 +-
 

[PATCH 2/3] block: Add support to warn on backing file change without format

2020-02-22 Thread Eric Blake
For now, this is a mechanical addition; all callers pass false. But
the next patch will use it to improve 'qemu-img rebase -u' when
selecting a backing file with no format.

Signed-off-by: Eric Blake 
---
 block.c   | 14 +++---
 block/qcow2.c |  2 +-
 block/stream.c|  2 +-
 blockdev.c|  3 ++-
 include/block/block.h |  4 ++--
 qemu-img.c|  4 ++--
 6 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/block.c b/block.c
index 308a91c96bde..695decbfd7b7 100644
--- a/block.c
+++ b/block.c
@@ -1290,7 +1290,8 @@ static int bdrv_backing_update_filename(BdrvChild *c, 
BlockDriverState *base,
 }

 ret = bdrv_change_backing_file(parent, filename,
-   base->drv ? base->drv->format_name : "");
+   base->drv ? base->drv->format_name : "",
+   false);
 if (ret < 0) {
 error_setg_errno(errp, -ret, "Could not update backing file link");
 }
@@ -4508,8 +4509,8 @@ int bdrv_check(BlockDriverState *bs,
  *image file header
  * -ENOTSUP - format driver doesn't support changing the backing file
  */
-int bdrv_change_backing_file(BlockDriverState *bs,
-const char *backing_file, const char *backing_fmt)
+int bdrv_change_backing_file(BlockDriverState *bs, const char *backing_file,
+ const char *backing_fmt, bool warn)
 {
 BlockDriver *drv = bs->drv;
 int ret;
@@ -4523,6 +4524,13 @@ int bdrv_change_backing_file(BlockDriverState *bs,
 return -EINVAL;
 }

+if (warn && backing_file && !backing_fmt &&
+!strstart(backing_file, "json:", NULL)) {
+warn_report("Deprecated use of backing file without explicit "
+"backing format, use of this image requires "
+"potentially unsafe format probing");
+}
+
 if (drv->bdrv_change_backing_file != NULL) {
 ret = drv->bdrv_change_backing_file(bs, backing_file, backing_fmt);
 } else {
diff --git a/block/qcow2.c b/block/qcow2.c
index 3c754f616bf8..05a2973a3086 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -3502,7 +3502,7 @@ qcow2_co_create(BlockdevCreateOptions *create_options, 
Error **errp)
 }

 ret = bdrv_change_backing_file(blk_bs(blk), qcow2_opts->backing_file,
-   backing_format);
+   backing_format, false);
 if (ret < 0) {
 error_setg_errno(errp, -ret, "Could not assign backing file '%s' "
  "with format '%s'", qcow2_opts->backing_file,
diff --git a/block/stream.c b/block/stream.c
index 5562ccbf577a..7c4d8ee0bcf1 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -78,7 +78,7 @@ static int stream_prepare(Job *job)
 }
 }
 bdrv_set_backing_hd(bs, base, _err);
-ret = bdrv_change_backing_file(bs, base_id, base_fmt);
+ret = bdrv_change_backing_file(bs, base_id, base_fmt, false);
 if (local_err) {
 error_report_err(local_err);
 return -EPERM;
diff --git a/blockdev.c b/blockdev.c
index 011dcfec2770..c88f27941d46 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -4299,7 +4299,8 @@ void qmp_change_backing_file(const char *device,
 }

 ret = bdrv_change_backing_file(image_bs, backing_file,
-   image_bs->drv ? image_bs->drv->format_name : 
"");
+   image_bs->drv ? image_bs->drv->format_name 
: "",
+   false);

 if (ret < 0) {
 error_setg_errno(errp, -ret, "Could not change backing file to '%s'",
diff --git a/include/block/block.h b/include/block/block.h
index cd6b5b95aad2..8b1dd94f7629 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -350,8 +350,8 @@ BlockMeasureInfo *bdrv_measure(BlockDriver *drv, QemuOpts 
*opts,
 void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
 void bdrv_refresh_limits(BlockDriverState *bs, Error **errp);
 int bdrv_commit(BlockDriverState *bs);
-int bdrv_change_backing_file(BlockDriverState *bs,
-const char *backing_file, const char *backing_fmt);
+int bdrv_change_backing_file(BlockDriverState *bs, const char *backing_file,
+ const char *backing_fmt, bool warn);
 void bdrv_register(BlockDriver *bdrv);
 int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
const char *backing_file_str);
diff --git a/qemu-img.c b/qemu-img.c
index 804630a368d6..b9375427404d 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -3637,9 +3637,9 @@ static int img_rebase(int argc, char **argv)
  * doesn't change when we switch the backing file.
  */
 if (out_baseimg && *out_baseimg) {
-ret = bdrv_change_backing_file(bs, out_baseimg, out_basefmt);
+ret = bdrv_change_backing_file(bs, out_baseimg, out_basefmt, false);
 } else {
-  

RE: [RFC v3 3/3] ACPI/unit-test: Add a new test for pxb-pcie for arm

2020-02-22 Thread miaoyubo


> -Original Message-
> From: Michael S. Tsirkin [mailto:m...@redhat.com]
> Sent: Friday, February 21, 2020 7:19 PM
> To: miaoyubo 
> Cc: peter.mayd...@linaro.org; shannon.zha...@gmail.com; Xiexiangyou
> ; imamm...@redhat.com;
> qemu-devel@nongnu.org
> Subject: Re: [RFC v3 3/3] ACPI/unit-test: Add a new test for pxb-pcie for arm
> 
> On Fri, Feb 21, 2020 at 02:35:12PM +0800, Yubo Miao wrote:
> > From: miaoyubo 
> >
> > Currently, pxb-pcie could be defined by the cmdline like
> > --device pxb-pcie,id=pci.9,bus_nr=128 However pxb-pcie is not
> > described in acpi tables for arm.
> >
> > The formal two patches support pxb-pcie for arm, escpcially the
> > specification for pxb-pcie in DSDT table.
> >
> > Add a testcase to make sure the ACPI table is correct for guest.
> >
> > Signed-off-by: miaoyubo 
> 
> 
> Please look at the top of tests/qtest/bios-tables-test.c for how to add or
> update tests.
> 

Thanks for replying, I didn't notice that, I would follow the steps to rebuild 
this patch.

> > ---
> >  tests/data/acpi/virt/DSDT.pxb  | Bin 0 -> 34209 bytes
> > tests/qtest/bios-tables-test.c |  54 +
> >  2 files changed, 48 insertions(+), 6 deletions(-)  create mode 100644
> > tests/data/acpi/virt/DSDT.pxb
> >
> > diff --git a/tests/data/acpi/virt/DSDT.pxb
> > b/tests/data/acpi/virt/DSDT.pxb new file mode 100644 index
> >
> ..4eea3192c75ff28f7054d626
> a936
> > 3ca025b6c0ad
> > GIT binary patch
> 
> I can't read this.
> 

I just have a question that is: 
I just rebuild this aml with tests/data/acpi/rebuild-expected-aml.sh
and git send it or send the aml with attachment?

> > literal 34209
> >
> zcmeI*cXU+szJ~D)1PGxe5PG+us9-{YGz}UAMT!L#ks?x*Dx!d5hoIP
> d
> >
> z?}}o>iWL;GW5HgrlKbvVM??^)~qbMIProvd|8p2_U*%qO!m?AgcPkRQ( r)WX
> >
> zR3DKyBsMVKK5tZUEMJ#Z3xXj0I{cizY-H-_vUpxu>HLbszg^Hd*
> >
> zYT59@{GfDxK}u{$QSzH5MFX?4va_qcnOYVriD$G-YqqdX5KgQUqzA#0T0ymH9a
> J-P
> > zt=#;Qdf_)p=V$jH6t9{xXmH68P3ev)8EFlwrs(=X$_(9dxJh>6UU8FZi5vcVla%Bp
> >
> zz50)g^-pXvw4i9XAYFAU@nN}Xb+t___n%uw)`
> 8L
> >
> z7F4goX88!*;pB+$X8_2BOj*;OO*!h6xx+mI)uU#l*o>||BPVi3ji?#5Y(|dH
> >
> z=oUF6C2B^h<}5a88su#W_0%%JtAk+ikeZ+X7unGJtJq-j+)WHX7uzKy&`9
> %
> 
> ...

Regards,
Miao



RE: [RFC v3 2/3] acpi:pci-expender-bus: Add pxb support for arm

2020-02-22 Thread miaoyubo


> -Original Message-
> From: Michael S. Tsirkin [mailto:m...@redhat.com]
> Sent: Friday, February 21, 2020 7:18 PM
> To: miaoyubo 
> Cc: peter.mayd...@linaro.org; shannon.zha...@gmail.com; Xiexiangyou
> ; imamm...@redhat.com;
> qemu-devel@nongnu.org
> Subject: Re: [RFC v3 2/3] acpi:pci-expender-bus: Add pxb support for arm
> 
> On Fri, Feb 21, 2020 at 02:35:11PM +0800, Yubo Miao wrote:
> > From: miaoyubo 
> >
> > Currently virt machine is not supported by pxb-pcie, and only one main
> > host bridge described in ACPI tables.
> > In this patch,PXB-PCIE is supproted by arm and certain resource is
> > allocated for each pxb-pcie in acpi table.
> > The resource for the main host bridge is also reallocated.
> >
> > Signed-off-by: miaoyubo 
> > ---
> >  hw/arm/virt-acpi-build.c | 125
> +++
> >  hw/pci-host/gpex.c   |   4 ++
> >  include/hw/arm/virt.h|   7 +++
> >  3 files changed, 125 insertions(+), 11 deletions(-)
> >
> > diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index
> > 0540234b8a..2c1e0d2aaa 100644
> > --- a/hw/arm/virt-acpi-build.c
> > +++ b/hw/arm/virt-acpi-build.c
> > @@ -49,6 +49,8 @@
> >  #include "kvm_arm.h"
> >  #include "migration/vmstate.h"
> >
> > +#include "hw/arm/virt.h"
> > +#include "hw/pci/pci_bus.h"
> >  #define ARM_SPI_BASE 32
> >
> >  static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus) @@ -271,19
> > +273,117 @@ static void acpi_dsdt_add_pci_osc(Aml *dev, Aml *scope)  }
> >
> >  static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry
> *memmap,
> > -  uint32_t irq, bool use_highmem, bool
> highmem_ecam)
> > +  uint32_t irq, bool use_highmem, bool
> highmem_ecam,
> > +  VirtMachineState *vms)
> >  {
> >  int ecam_id = VIRT_ECAM_ID(highmem_ecam);
> > -Aml *method, *crs;
> > +Aml *method, *dev, *crs;
> > +int count = 0;
> >  hwaddr base_mmio = memmap[VIRT_PCIE_MMIO].base;
> >  hwaddr size_mmio = memmap[VIRT_PCIE_MMIO].size;
> >  hwaddr base_pio = memmap[VIRT_PCIE_PIO].base;
> >  hwaddr size_pio = memmap[VIRT_PCIE_PIO].size;
> >  hwaddr base_ecam = memmap[ecam_id].base;
> >  hwaddr size_ecam = memmap[ecam_id].size;
> > +/*
> > + * 0x60 would be enough for pxb device
> > + * if it is too small, there is no enough space
> > + * for a pcie device plugged in a pcie-root port
> > + */
> > +hwaddr size_addr = 0x60;
> > +hwaddr size_io = 0x4000;
> >  int nr_pcie_buses = size_ecam / PCIE_MMCFG_SIZE_MIN;
> > +int root_bus_limit = 0xFF;
> 
> what's this?
> 

Thanks for replying.
This is used to define the bus numbers for the main host bridge, 
If no pxb-pcie is defined, the bus number for the main host bridge
would range form 0 to 255.

> > +PCIBus *bus = NULL;
> > +bus = VIRT_MACHINE(vms)->bus;
> 
> So just move assignment as part of declaration.
> 

Thanks for the suggestion!

> > +
> > +if (bus) {
> > +QLIST_FOREACH(bus, >child, sibling) {
> > +uint8_t bus_num = pci_bus_num(bus);
> > +uint8_t numa_node = pci_bus_numa_node(bus);
> > +
> > +if (!pci_bus_is_root(bus)) {
> > +continue;
> > +}
> > +if (bus_num < root_bus_limit) {
> > +root_bus_limit = bus_num - 1;
> 
> what is this doing? manually coded up MIN?
> 

This coded up the MIN of busNr defined in pxb-pcie devices, 
and the Min busNr-1 would be the MAX bus Number for the main host bridge.
For example, if one pxb-pcie with busNr 128(which is 80) defined, 
The bus for the main host bridge would be 0-7F, and the bus for pxb-pcie
would be 80-81(just allocate two buses,keep the same with X86).
If pxb-pcie is not defined, the bus for main host bridge would be 0-FF.

> > +}
> > +count++;
> > +dev = aml_device("PC%.02X", bus_num);
> > +aml_append(dev, aml_name_decl("_HID",
> aml_string("PNP0A08")));
> > +aml_append(dev, aml_name_decl("_CID",
> aml_string("PNP0A03")));
> > +aml_append(dev, aml_name_decl("_ADR", aml_int(0)));
> > +aml_append(dev, aml_name_decl("_CCA", aml_int(1)));
> > +aml_append(dev, aml_name_decl("_SEG", aml_int(0)));
> > +aml_append(dev, aml_name_decl("_BBN",
> aml_int(bus_num)));
> > +aml_append(dev, aml_name_decl("_UID",
> aml_int(bus_num)));
> > +aml_append(dev, aml_name_decl("_STR", aml_unicode("pxb
> Device")));
> > +if (numa_node != NUMA_NODE_UNASSIGNED) {
> > +method = aml_method("_PXM", 0,
> AML_NOTSERIALIZED);
> > +aml_append(method,
> aml_return(aml_int(numa_node)));
> > +aml_append(dev, method);
> > +}
> > +
> >   * GPEX host
> > @@ -98,6 +99,9 @@ static void gpex_host_realize(DeviceState *dev, Error
> **errp)
> >   

Re: [PULL 00/31] Block patches

2020-02-22 Thread no-reply
Patchew URL: 
https://patchew.org/QEMU/20200222085030.1760640-1-stefa...@redhat.com/



Hi,

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

Subject: [PULL 00/31] Block patches
Message-id: 20200222085030.1760640-1-stefa...@redhat.com
Type: series

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

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 * [new tag] patchew/20200222085030.1760640-1-stefa...@redhat.com -> 
patchew/20200222085030.1760640-1-stefa...@redhat.com
Switched to a new branch 'test'
dc382b1 fuzz: add documentation to docs/devel/
003bbd0 fuzz: add virtio-scsi fuzz target
e8802f9 fuzz: add virtio-net fuzz target
69e13ad fuzz: add i440fx fuzz targets
4083dcb fuzz: add configure flag --enable-fuzzing
c3d2240 fuzz: add target/fuzz makefile rules
7c4d2fb fuzz: add support for qos-assisted fuzz targets
8518c8d fuzz: support for fork-based fuzzing.
6a286ed main: keep rcu_atfork callback enabled for qtest
ed941c7 exec: keep ram block across fork when using qtest
e24313f fuzz: add fuzzer skeleton
408df07 libqos: move useful qos-test funcs to qos_external
d7daac7 libqos: split qos-test and libqos makefile vars
4bceb01 libqos: rename i2c_send and i2c_recv
4ea92f2 qtest: add in-process incoming command handler
0adfc33 libqtest: make bufwrite rely on the TransportOps
780da9f libqtest: add a layer of abstraction to send/recv
bcc084b qtest: add qtest_server_send abstraction
266c2c5 fuzz: add FUZZ_TARGET module type
66b6939 module: check module wasn't already initialized
009494e softmmu: split off vl.c:main() into main.c
28796ad softmmu: move vl.c to softmmu/
6b8a3f7 aio-posix: make AioHandler dispatch O(1) with epoll
b839357 aio-posix: make AioHandler deletion O(1)
5c9397d qemu/queue.h: add QLIST_SAFE_REMOVE()
8cd11b4 aio-posix: don't pass ns timeout to epoll_wait()
4252dd3 aio-posix: fix use after leaving scope in aio_poll()
e850ad8 util/async: make bh_aio_poll() O(1)
3ae8e2d rcu_queue: add QSLIST functions
b593eb3 aio-posix: avoid reacquiring rcu_read_lock() when polling
6fbbd86 virtio: increase virtqueue size for virtio-scsi and virtio-blk

=== OUTPUT BEGIN ===
1/31 Checking commit 6fbbd869010e (virtio: increase virtqueue size for 
virtio-scsi and virtio-blk)
2/31 Checking commit b593eb3a32e9 (aio-posix: avoid reacquiring rcu_read_lock() 
when polling)
3/31 Checking commit 3ae8e2d89202 (rcu_queue: add QSLIST functions)
WARNING: Block comments use a leading /* on a separate line
#29: FILE: include/qemu/queue.h:217:
+} while (/*CONSTCOND*/0)

WARNING: Block comments use a leading /* on a separate line
#64: FILE: include/qemu/rcu_queue.h:278:
+} while (/*CONSTCOND*/0)

WARNING: Block comments use a leading /* on a separate line
#69: FILE: include/qemu/rcu_queue.h:283:
+} while (/*CONSTCOND*/0)

WARNING: Block comments use a leading /* on a separate line
#73: FILE: include/qemu/rcu_queue.h:287:
+} while (/*CONSTCOND*/0)

WARNING: Block comments use a leading /* on a separate line
#86: FILE: include/qemu/rcu_queue.h:300:
+} while (/*CONSTCOND*/0)

ERROR: code indent should never use tabs
#144: FILE: tests/test-rcu-list.c:155:
+^I QSLIST_REMOVE_RCU(_list_head, el, list_element, f)$

WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#156: 
new file mode 100644

total: 1 errors, 6 warnings, 119 lines checked

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

4/31 Checking commit e850ad83574b (util/async: make bh_aio_poll() O(1))
5/31 Checking commit 4252dd376d4c (aio-posix: fix use after leaving scope in 
aio_poll())
6/31 Checking commit 8cd11b46c0f8 (aio-posix: don't pass ns timeout to 
epoll_wait())
7/31 Checking commit 5c9397dad943 (qemu/queue.h: add QLIST_SAFE_REMOVE())
WARNING: Block comments use a leading /* on a separate line
#70: FILE: include/qemu/queue.h:159:
+} while (/*CONSTCOND*/0)

total: 0 errors, 1 warnings, 41 lines checked

Patch 7/31 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
8/31 Checking commit b83935774545 (aio-posix: make AioHandler deletion O(1))
9/31 Checking commit 6b8a3f79ba86 (aio-posix: make AioHandler dispatch O(1) 
with epoll)
10/31 Checking commit 28796ad5d822 (softmmu: move vl.c to softmmu/)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#83: 
new file mode 100644

total: 0 errors, 1 warnings, 42 lines checked

Patch 10/31 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
11/31 Checking commit 009494eddb10 (softmmu: split off 

[PULL 29/31] fuzz: add virtio-net fuzz target

2020-02-22 Thread Stefan Hajnoczi
From: Alexander Bulekov 

The virtio-net fuzz target feeds inputs to all three virtio-net
virtqueues, and uses forking to avoid leaking state between fuzz runs.

Signed-off-by: Alexander Bulekov 
Reviewed-by: Stefan Hajnoczi 
Reviewed-by: Darren Kenny 
Message-id: 20200220041118.23264-21-alx...@bu.edu
Signed-off-by: Stefan Hajnoczi 
---
 tests/qtest/fuzz/Makefile.include  |   1 +
 tests/qtest/fuzz/virtio_net_fuzz.c | 198 +
 2 files changed, 199 insertions(+)
 create mode 100644 tests/qtest/fuzz/virtio_net_fuzz.c

diff --git a/tests/qtest/fuzz/Makefile.include 
b/tests/qtest/fuzz/Makefile.include
index 38b8cdd9f1..77385777ef 100644
--- a/tests/qtest/fuzz/Makefile.include
+++ b/tests/qtest/fuzz/Makefile.include
@@ -8,6 +8,7 @@ fuzz-obj-y += tests/qtest/fuzz/qos_fuzz.o
 
 # Targets
 fuzz-obj-y += tests/qtest/fuzz/i440fx_fuzz.o
+fuzz-obj-y += tests/qtest/fuzz/virtio_net_fuzz.o
 
 FUZZ_CFLAGS += -I$(SRC_PATH)/tests -I$(SRC_PATH)/tests/qtest
 
diff --git a/tests/qtest/fuzz/virtio_net_fuzz.c 
b/tests/qtest/fuzz/virtio_net_fuzz.c
new file mode 100644
index 00..d08a47e278
--- /dev/null
+++ b/tests/qtest/fuzz/virtio_net_fuzz.c
@@ -0,0 +1,198 @@
+/*
+ * virtio-net Fuzzing Target
+ *
+ * Copyright Red Hat Inc., 2019
+ *
+ * Authors:
+ *  Alexander Bulekov   
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+
+#include "standard-headers/linux/virtio_config.h"
+#include "tests/qtest/libqtest.h"
+#include "tests/qtest/libqos/virtio-net.h"
+#include "fuzz.h"
+#include "fork_fuzz.h"
+#include "qos_fuzz.h"
+
+
+#define QVIRTIO_NET_TIMEOUT_US (30 * 1000 * 1000)
+#define QVIRTIO_RX_VQ 0
+#define QVIRTIO_TX_VQ 1
+#define QVIRTIO_CTRL_VQ 2
+
+static int sockfds[2];
+static bool sockfds_initialized;
+
+static void virtio_net_fuzz_multi(QTestState *s,
+const unsigned char *Data, size_t Size, bool check_used)
+{
+typedef struct vq_action {
+uint8_t queue;
+uint8_t length;
+uint8_t write;
+uint8_t next;
+uint8_t rx;
+} vq_action;
+
+uint32_t free_head = 0;
+
+QGuestAllocator *t_alloc = fuzz_qos_alloc;
+
+QVirtioNet *net_if = fuzz_qos_obj;
+QVirtioDevice *dev = net_if->vdev;
+QVirtQueue *q;
+vq_action vqa;
+while (Size >= sizeof(vqa)) {
+memcpy(, Data, sizeof(vqa));
+Data += sizeof(vqa);
+Size -= sizeof(vqa);
+
+q = net_if->queues[vqa.queue % 3];
+
+vqa.length = vqa.length >= Size ? Size :  vqa.length;
+
+/*
+ * Only attempt to write incoming packets, when using the socket
+ * backend. Otherwise, always place the input on a virtqueue.
+ */
+if (vqa.rx && sockfds_initialized) {
+write(sockfds[0], Data, vqa.length);
+} else {
+vqa.rx = 0;
+uint64_t req_addr = guest_alloc(t_alloc, vqa.length);
+/*
+ * If checking used ring, ensure that the fuzzer doesn't trigger
+ * trivial asserion failure on zero-zied buffer
+ */
+qtest_memwrite(s, req_addr, Data, vqa.length);
+
+
+free_head = qvirtqueue_add(s, q, req_addr, vqa.length,
+vqa.write, vqa.next);
+qvirtqueue_add(s, q, req_addr, vqa.length, vqa.write , vqa.next);
+qvirtqueue_kick(s, dev, q, free_head);
+}
+
+/* Run the main loop */
+qtest_clock_step(s, 100);
+flush_events(s);
+
+/* Wait on used descriptors */
+if (check_used && !vqa.rx) {
+gint64 start_time = g_get_monotonic_time();
+/*
+ * normally, we could just use qvirtio_wait_used_elem, but since we
+ * must manually run the main-loop for all the bhs to run, we use
+ * this hack with flush_events(), to run the main_loop
+ */
+while (!vqa.rx && q != net_if->queues[QVIRTIO_RX_VQ]) {
+uint32_t got_desc_idx;
+/* Input led to a virtio_error */
+if (dev->bus->get_status(dev) & VIRTIO_CONFIG_S_NEEDS_RESET) {
+break;
+}
+if (dev->bus->get_queue_isr_status(dev, q) &&
+qvirtqueue_get_buf(s, q, _desc_idx, NULL)) {
+g_assert_cmpint(got_desc_idx, ==, free_head);
+break;
+}
+g_assert(g_get_monotonic_time() - start_time
+<= QVIRTIO_NET_TIMEOUT_US);
+
+/* Run the main loop */
+qtest_clock_step(s, 100);
+flush_events(s);
+}
+}
+Data += vqa.length;
+Size -= vqa.length;
+}
+}
+
+static void virtio_net_fork_fuzz(QTestState *s,
+const unsigned char *Data, size_t Size)
+{
+if (fork() == 0) {
+virtio_net_fuzz_multi(s, Data, Size, 

[PULL 26/31] fuzz: add target/fuzz makefile rules

2020-02-22 Thread Stefan Hajnoczi
From: Alexander Bulekov 

Signed-off-by: Alexander Bulekov 
Reviewed-by: Darren Kenny 
Reviewed-by: Stefan Hajnoczi 
Message-id: 20200220041118.23264-18-alx...@bu.edu
Signed-off-by: Stefan Hajnoczi 
---
 Makefile| 15 ++-
 Makefile.target | 16 
 2 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index b5a7377cb1..18e82cca85 100644
--- a/Makefile
+++ b/Makefile
@@ -477,7 +477,7 @@ config-host.h-timestamp: config-host.mak
 qemu-options.def: $(SRC_PATH)/qemu-options.hx $(SRC_PATH)/scripts/hxtool
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > 
$@,"GEN","$@")
 
-TARGET_DIRS_RULES := $(foreach t, all clean install, $(addsuffix /$(t), 
$(TARGET_DIRS)))
+TARGET_DIRS_RULES := $(foreach t, all fuzz clean install, $(addsuffix /$(t), 
$(TARGET_DIRS)))
 
 SOFTMMU_ALL_RULES=$(filter %-softmmu/all, $(TARGET_DIRS_RULES))
 $(SOFTMMU_ALL_RULES): $(authz-obj-y)
@@ -490,6 +490,15 @@ ifdef DECOMPRESS_EDK2_BLOBS
 $(SOFTMMU_ALL_RULES): $(edk2-decompressed)
 endif
 
+SOFTMMU_FUZZ_RULES=$(filter %-softmmu/fuzz, $(TARGET_DIRS_RULES))
+$(SOFTMMU_FUZZ_RULES): $(authz-obj-y)
+$(SOFTMMU_FUZZ_RULES): $(block-obj-y)
+$(SOFTMMU_FUZZ_RULES): $(chardev-obj-y)
+$(SOFTMMU_FUZZ_RULES): $(crypto-obj-y)
+$(SOFTMMU_FUZZ_RULES): $(io-obj-y)
+$(SOFTMMU_FUZZ_RULES): config-all-devices.mak
+$(SOFTMMU_FUZZ_RULES): $(edk2-decompressed)
+
 .PHONY: $(TARGET_DIRS_RULES)
 # The $(TARGET_DIRS_RULES) are of the form SUBDIR/GOAL, so that
 # $(dir $@) yields the sub-directory, and $(notdir $@) yields the sub-goal
@@ -540,6 +549,9 @@ subdir-slirp: slirp/all
 $(filter %/all, $(TARGET_DIRS_RULES)): libqemuutil.a $(common-obj-y) \
$(qom-obj-y)
 
+$(filter %/fuzz, $(TARGET_DIRS_RULES)): libqemuutil.a $(common-obj-y) \
+   $(qom-obj-y) $(crypto-user-obj-$(CONFIG_USER_ONLY))
+
 ROM_DIRS = $(addprefix pc-bios/, $(ROMS))
 ROM_DIRS_RULES=$(foreach t, all clean, $(addsuffix /$(t), $(ROM_DIRS)))
 # Only keep -O and -g cflags
@@ -549,6 +561,7 @@ $(ROM_DIRS_RULES):
 
 .PHONY: recurse-all recurse-clean recurse-install
 recurse-all: $(addsuffix /all, $(TARGET_DIRS) $(ROM_DIRS))
+recurse-fuzz: $(addsuffix /fuzz, $(TARGET_DIRS) $(ROM_DIRS))
 recurse-clean: $(addsuffix /clean, $(TARGET_DIRS) $(ROM_DIRS))
 recurse-install: $(addsuffix /install, $(TARGET_DIRS))
 $(addsuffix /install, $(TARGET_DIRS)): all
diff --git a/Makefile.target b/Makefile.target
index 6f4dd72022..2d43dc586a 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -228,6 +228,22 @@ ifdef CONFIG_TRACE_SYSTEMTAP
rm -f *.stp
 endif
 
+ifdef CONFIG_FUZZ
+include $(SRC_PATH)/tests/qtest/fuzz/Makefile.include
+include $(SRC_PATH)/tests/qtest/Makefile.include
+
+fuzz: fuzz-vars
+fuzz-vars: QEMU_CFLAGS := $(FUZZ_CFLAGS) $(QEMU_CFLAGS)
+fuzz-vars: QEMU_LDFLAGS := $(FUZZ_LDFLAGS) $(QEMU_LDFLAGS)
+fuzz-vars: $(QEMU_PROG_FUZZ)
+dummy := $(call unnest-vars,, fuzz-obj-y)
+
+
+$(QEMU_PROG_FUZZ): config-devices.mak $(all-obj-y) $(COMMON_LDADDS) 
$(fuzz-obj-y)
+   $(call LINK, $(filter-out %.mak, $^))
+
+endif
+
 install: all
 ifneq ($(PROGS),)
$(call install-prog,$(PROGS),$(DESTDIR)$(bindir))
-- 
2.24.1



[PULL 31/31] fuzz: add documentation to docs/devel/

2020-02-22 Thread Stefan Hajnoczi
From: Alexander Bulekov 

Signed-off-by: Alexander Bulekov 
Reviewed-by: Stefan Hajnoczi 
Reviewed-by: Darren Kenny 
Message-id: 20200220041118.23264-23-alx...@bu.edu
Signed-off-by: Stefan Hajnoczi 
---
 docs/devel/fuzzing.txt | 116 +
 1 file changed, 116 insertions(+)
 create mode 100644 docs/devel/fuzzing.txt

diff --git a/docs/devel/fuzzing.txt b/docs/devel/fuzzing.txt
new file mode 100644
index 00..324d2cd92b
--- /dev/null
+++ b/docs/devel/fuzzing.txt
@@ -0,0 +1,116 @@
+= Fuzzing =
+
+== Introduction ==
+
+This document describes the virtual-device fuzzing infrastructure in QEMU and
+how to use it to implement additional fuzzers.
+
+== Basics ==
+
+Fuzzing operates by passing inputs to an entry point/target function. The
+fuzzer tracks the code coverage triggered by the input. Based on these
+findings, the fuzzer mutates the input and repeats the fuzzing.
+
+To fuzz QEMU, we rely on libfuzzer. Unlike other fuzzers such as AFL, libfuzzer
+is an _in-process_ fuzzer. For the developer, this means that it is their
+responsibility to ensure that state is reset between fuzzing-runs.
+
+== Building the fuzzers ==
+
+NOTE: If possible, build a 32-bit binary. When forking, the 32-bit fuzzer is
+much faster, since the page-map has a smaller size. This is due to the fact 
that
+AddressSanitizer mmaps ~20TB of memory, as part of its detection. This results
+in a large page-map, and a much slower fork().
+
+To build the fuzzers, install a recent version of clang:
+Configure with (substitute the clang binaries with the version you installed):
+
+CC=clang-8 CXX=clang++-8 /path/to/configure --enable-fuzzing
+
+Fuzz targets are built similarly to system/softmmu:
+
+make i386-softmmu/fuzz
+
+This builds ./i386-softmmu/qemu-fuzz-i386
+
+The first option to this command is: --fuzz_taget=FUZZ_NAME
+To list all of the available fuzzers run qemu-fuzz-i386 with no arguments.
+
+eg:
+./i386-softmmu/qemu-fuzz-i386 --fuzz-target=virtio-net-fork-fuzz
+
+Internally, libfuzzer parses all arguments that do not begin with "--".
+Information about these is available by passing -help=1
+
+Now the only thing left to do is wait for the fuzzer to trigger potential
+crashes.
+
+== Adding a new fuzzer ==
+Coverage over virtual devices can be improved by adding additional fuzzers.
+Fuzzers are kept in tests/qtest/fuzz/ and should be added to
+tests/qtest/fuzz/Makefile.include
+
+Fuzzers can rely on both qtest and libqos to communicate with virtual devices.
+
+1. Create a new source file. For example 
``tests/qtest/fuzz/foo-device-fuzz.c``.
+
+2. Write the fuzzing code using the libqtest/libqos API. See existing fuzzers
+for reference.
+
+3. Register the fuzzer in ``tests/fuzz/Makefile.include`` by appending the
+corresponding object to fuzz-obj-y
+
+Fuzzers can be more-or-less thought of as special qtest programs which can
+modify the qtest commands and/or qtest command arguments based on inputs
+provided by libfuzzer. Libfuzzer passes a byte array and length. Commonly the
+fuzzer loops over the byte-array interpreting it as a list of qtest commands,
+addresses, or values.
+
+= Implementation Details =
+
+== The Fuzzer's Lifecycle ==
+
+The fuzzer has two entrypoints that libfuzzer calls. libfuzzer provides it's
+own main(), which performs some setup, and calls the entrypoints:
+
+LLVMFuzzerInitialize: called prior to fuzzing. Used to initialize all of the
+necessary state
+
+LLVMFuzzerTestOneInput: called for each fuzzing run. Processes the input and
+resets the state at the end of each run.
+
+In more detail:
+
+LLVMFuzzerInitialize parses the arguments to the fuzzer (must start with two
+dashes, so they are ignored by libfuzzer main()). Currently, the arguments
+select the fuzz target. Then, the qtest client is initialized. If the target
+requires qos, qgraph is set up and the QOM/LIBQOS modules are initialized.
+Then the QGraph is walked and the QEMU cmd_line is determined and saved.
+
+After this, the vl.c:qemu__main is called to set up the guest. There are
+target-specific hooks that can be called before and after qemu_main, for
+additional setup(e.g. PCI setup, or VM snapshotting).
+
+LLVMFuzzerTestOneInput: Uses qtest/qos functions to act based on the fuzz
+input. It is also responsible for manually calling the main loop/main_loop_wait
+to ensure that bottom halves are executed and any cleanup required before the
+next input.
+
+Since the same process is reused for many fuzzing runs, QEMU state needs to
+be reset at the end of each run. There are currently two implemented
+options for resetting state:
+1. Reboot the guest between runs.
+   Pros: Straightforward and fast for simple fuzz targets.
+   Cons: Depending on the device, does not reset all device state. If the
+   device requires some initialization prior to being ready for fuzzing
+   (common for QOS-based targets), this initialization needs to be done after
+   each reboot.
+   Example target: 

[PULL 28/31] fuzz: add i440fx fuzz targets

2020-02-22 Thread Stefan Hajnoczi
From: Alexander Bulekov 

These three targets should simply fuzz reads/writes to a couple ioports,
but they mostly serve as examples of different ways to write targets.
They demonstrate using qtest and qos for fuzzing, as well as using
rebooting and forking to reset state, or not resetting it at all.

Signed-off-by: Alexander Bulekov 
Reviewed-by: Stefan Hajnoczi 
Reviewed-by: Darren Kenny 
Message-id: 20200220041118.23264-20-alx...@bu.edu
Signed-off-by: Stefan Hajnoczi 
---
 tests/qtest/fuzz/Makefile.include |   3 +
 tests/qtest/fuzz/i440fx_fuzz.c| 193 ++
 2 files changed, 196 insertions(+)
 create mode 100644 tests/qtest/fuzz/i440fx_fuzz.c

diff --git a/tests/qtest/fuzz/Makefile.include 
b/tests/qtest/fuzz/Makefile.include
index e3bdd33ff4..38b8cdd9f1 100644
--- a/tests/qtest/fuzz/Makefile.include
+++ b/tests/qtest/fuzz/Makefile.include
@@ -6,6 +6,9 @@ fuzz-obj-y += tests/qtest/fuzz/fuzz.o # Fuzzer skeleton
 fuzz-obj-y += tests/qtest/fuzz/fork_fuzz.o
 fuzz-obj-y += tests/qtest/fuzz/qos_fuzz.o
 
+# Targets
+fuzz-obj-y += tests/qtest/fuzz/i440fx_fuzz.o
+
 FUZZ_CFLAGS += -I$(SRC_PATH)/tests -I$(SRC_PATH)/tests/qtest
 
 # Linker Script to force coverage-counters into known regions which we can mark
diff --git a/tests/qtest/fuzz/i440fx_fuzz.c b/tests/qtest/fuzz/i440fx_fuzz.c
new file mode 100644
index 00..ab5f112584
--- /dev/null
+++ b/tests/qtest/fuzz/i440fx_fuzz.c
@@ -0,0 +1,193 @@
+/*
+ * I440FX Fuzzing Target
+ *
+ * Copyright Red Hat Inc., 2019
+ *
+ * Authors:
+ *  Alexander Bulekov   
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+
+#include "qemu/main-loop.h"
+#include "tests/qtest/libqtest.h"
+#include "tests/qtest/libqos/pci.h"
+#include "tests/qtest/libqos/pci-pc.h"
+#include "fuzz.h"
+#include "fuzz/qos_fuzz.h"
+#include "fuzz/fork_fuzz.h"
+
+
+#define I440FX_PCI_HOST_BRIDGE_CFG 0xcf8
+#define I440FX_PCI_HOST_BRIDGE_DATA 0xcfc
+
+/*
+ * the input to the fuzzing functions below is a buffer of random bytes. we
+ * want to convert these bytes into a sequence of qtest or qos calls. to do
+ * this we define some opcodes:
+ */
+enum action_id {
+WRITEB,
+WRITEW,
+WRITEL,
+READB,
+READW,
+READL,
+ACTION_MAX
+};
+
+static void i440fx_fuzz_qtest(QTestState *s,
+const unsigned char *Data, size_t Size) {
+/*
+ * loop over the Data, breaking it up into actions. each action has an
+ * opcode, address offset and value
+ */
+typedef struct QTestFuzzAction {
+uint8_t opcode;
+uint8_t addr;
+uint32_t value;
+} QTestFuzzAction;
+QTestFuzzAction a;
+
+while (Size >= sizeof(a)) {
+/* make a copy of the action so we can normalize the values in-place */
+memcpy(, Data, sizeof(a));
+/* select between two i440fx Port IO addresses */
+uint16_t addr = a.addr % 2 ? I440FX_PCI_HOST_BRIDGE_CFG :
+  I440FX_PCI_HOST_BRIDGE_DATA;
+switch (a.opcode % ACTION_MAX) {
+case WRITEB:
+qtest_outb(s, addr, (uint8_t)a.value);
+break;
+case WRITEW:
+qtest_outw(s, addr, (uint16_t)a.value);
+break;
+case WRITEL:
+qtest_outl(s, addr, (uint32_t)a.value);
+break;
+case READB:
+qtest_inb(s, addr);
+break;
+case READW:
+qtest_inw(s, addr);
+break;
+case READL:
+qtest_inl(s, addr);
+break;
+}
+/* Move to the next operation */
+Size -= sizeof(a);
+Data += sizeof(a);
+}
+flush_events(s);
+}
+
+static void i440fx_fuzz_qos(QTestState *s,
+const unsigned char *Data, size_t Size) {
+/*
+ * Same as i440fx_fuzz_qtest, but using QOS. devfn is incorporated into the
+ * value written over Port IO
+ */
+typedef struct QOSFuzzAction {
+uint8_t opcode;
+uint8_t offset;
+int devfn;
+uint32_t value;
+} QOSFuzzAction;
+
+static QPCIBus *bus;
+if (!bus) {
+bus = qpci_new_pc(s, fuzz_qos_alloc);
+}
+
+QOSFuzzAction a;
+while (Size >= sizeof(a)) {
+memcpy(, Data, sizeof(a));
+switch (a.opcode % ACTION_MAX) {
+case WRITEB:
+bus->config_writeb(bus, a.devfn, a.offset, (uint8_t)a.value);
+break;
+case WRITEW:
+bus->config_writew(bus, a.devfn, a.offset, (uint16_t)a.value);
+break;
+case WRITEL:
+bus->config_writel(bus, a.devfn, a.offset, (uint32_t)a.value);
+break;
+case READB:
+bus->config_readb(bus, a.devfn, a.offset);
+break;
+case READW:
+bus->config_readw(bus, a.devfn, a.offset);
+break;
+case READL:
+bus->config_readl(bus, a.devfn, 

[PULL 21/31] fuzz: add fuzzer skeleton

2020-02-22 Thread Stefan Hajnoczi
From: Alexander Bulekov 

tests/fuzz/fuzz.c serves as the entry point for the virtual-device
fuzzer. Namely, libfuzzer invokes the LLVMFuzzerInitialize and
LLVMFuzzerTestOneInput functions, both of which are defined in this
file. This change adds a "FuzzTarget" struct, along with the
fuzz_add_target function, which should be used to define new fuzz
targets.

Signed-off-by: Alexander Bulekov 
Reviewed-by: Stefan Hajnoczi 
Reviewed-by: Darren Kenny 
Message-id: 20200220041118.23264-13-alx...@bu.edu
Signed-off-by: Stefan Hajnoczi 
---
 MAINTAINERS   |   8 ++
 tests/qtest/fuzz/Makefile.include |   6 +
 tests/qtest/fuzz/fuzz.c   | 179 ++
 tests/qtest/fuzz/fuzz.h   |  95 
 4 files changed, 288 insertions(+)
 create mode 100644 tests/qtest/fuzz/Makefile.include
 create mode 100644 tests/qtest/fuzz/fuzz.c
 create mode 100644 tests/qtest/fuzz/fuzz.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 969329f83e..195dd58cac 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2184,6 +2184,14 @@ F: qtest.c
 F: accel/qtest.c
 F: tests/qtest/
 
+Device Fuzzing
+M: Alexander Bulekov 
+R: Paolo Bonzini 
+R: Bandan Das 
+R: Stefan Hajnoczi 
+S: Maintained
+F: tests/qtest/fuzz/
+
 Register API
 M: Alistair Francis 
 S: Maintained
diff --git a/tests/qtest/fuzz/Makefile.include 
b/tests/qtest/fuzz/Makefile.include
new file mode 100644
index 00..8632bb89f4
--- /dev/null
+++ b/tests/qtest/fuzz/Makefile.include
@@ -0,0 +1,6 @@
+QEMU_PROG_FUZZ=qemu-fuzz-$(TARGET_NAME)$(EXESUF)
+
+fuzz-obj-y += tests/qtest/libqtest.o
+fuzz-obj-y += tests/qtest/fuzz/fuzz.o # Fuzzer skeleton
+
+FUZZ_CFLAGS += -I$(SRC_PATH)/tests -I$(SRC_PATH)/tests/qtest
diff --git a/tests/qtest/fuzz/fuzz.c b/tests/qtest/fuzz/fuzz.c
new file mode 100644
index 00..0d78ac8d36
--- /dev/null
+++ b/tests/qtest/fuzz/fuzz.c
@@ -0,0 +1,179 @@
+/*
+ * fuzzing driver
+ *
+ * Copyright Red Hat Inc., 2019
+ *
+ * Authors:
+ *  Alexander Bulekov   
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+
+#include 
+
+#include "sysemu/qtest.h"
+#include "sysemu/runstate.h"
+#include "sysemu/sysemu.h"
+#include "qemu/main-loop.h"
+#include "tests/qtest/libqtest.h"
+#include "tests/qtest/libqos/qgraph.h"
+#include "fuzz.h"
+
+#define MAX_EVENT_LOOPS 10
+
+typedef struct FuzzTargetState {
+FuzzTarget *target;
+QSLIST_ENTRY(FuzzTargetState) target_list;
+} FuzzTargetState;
+
+typedef QSLIST_HEAD(, FuzzTargetState) FuzzTargetList;
+
+static const char *fuzz_arch = TARGET_NAME;
+
+static FuzzTargetList *fuzz_target_list;
+static FuzzTarget *fuzz_target;
+static QTestState *fuzz_qts;
+
+
+
+void flush_events(QTestState *s)
+{
+int i = MAX_EVENT_LOOPS;
+while (g_main_context_pending(NULL) && i-- > 0) {
+main_loop_wait(false);
+}
+}
+
+static QTestState *qtest_setup(void)
+{
+qtest_server_set_send_handler(_client_inproc_recv, _qts);
+return qtest_inproc_init(_qts, false, fuzz_arch,
+_server_inproc_recv);
+}
+
+void fuzz_add_target(const FuzzTarget *target)
+{
+FuzzTargetState *tmp;
+FuzzTargetState *target_state;
+if (!fuzz_target_list) {
+fuzz_target_list = g_new0(FuzzTargetList, 1);
+}
+
+QSLIST_FOREACH(tmp, fuzz_target_list, target_list) {
+if (g_strcmp0(tmp->target->name, target->name) == 0) {
+fprintf(stderr, "Error: Fuzz target name %s already in use\n",
+target->name);
+abort();
+}
+}
+target_state = g_new0(FuzzTargetState, 1);
+target_state->target = g_new0(FuzzTarget, 1);
+*(target_state->target) = *target;
+QSLIST_INSERT_HEAD(fuzz_target_list, target_state, target_list);
+}
+
+
+
+static void usage(char *path)
+{
+printf("Usage: %s --fuzz-target=FUZZ_TARGET [LIBFUZZER ARGUMENTS]\n", 
path);
+printf("where FUZZ_TARGET is one of:\n");
+FuzzTargetState *tmp;
+if (!fuzz_target_list) {
+fprintf(stderr, "Fuzz target list not initialized\n");
+abort();
+}
+QSLIST_FOREACH(tmp, fuzz_target_list, target_list) {
+printf(" * %s  : %s\n", tmp->target->name,
+tmp->target->description);
+}
+exit(0);
+}
+
+static FuzzTarget *fuzz_get_target(char* name)
+{
+FuzzTargetState *tmp;
+if (!fuzz_target_list) {
+fprintf(stderr, "Fuzz target list not initialized\n");
+abort();
+}
+
+QSLIST_FOREACH(tmp, fuzz_target_list, target_list) {
+if (strcmp(tmp->target->name, name) == 0) {
+return tmp->target;
+}
+}
+return NULL;
+}
+
+
+/* Executed for each fuzzing-input */
+int LLVMFuzzerTestOneInput(const unsigned char *Data, size_t Size)
+{
+/*
+ * Do the pre-fuzz-initialization before the first fuzzing iteration,
+ * instead of before the actual fuzz loop. This is needed since libfuzzer
+ * may 

[PULL 15/31] libqtest: add a layer of abstraction to send/recv

2020-02-22 Thread Stefan Hajnoczi
From: Alexander Bulekov 

This makes it simple to swap the transport functions for qtest commands
to and from the qtest client. For example, now it is possible to
directly pass qtest commands to a server handler that exists within the
same process, without the standard way of writing to a file descriptor.

Signed-off-by: Alexander Bulekov 
Reviewed-by: Stefan Hajnoczi 
Reviewed-by: Darren Kenny 
Message-id: 20200220041118.23264-7-alx...@bu.edu
Signed-off-by: Stefan Hajnoczi 
---
 tests/qtest/libqtest.c | 48 ++
 1 file changed, 39 insertions(+), 9 deletions(-)

diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c
index 76c9f8eade..e5056a1d0f 100644
--- a/tests/qtest/libqtest.c
+++ b/tests/qtest/libqtest.c
@@ -35,6 +35,15 @@
 #define SOCKET_TIMEOUT 50
 #define SOCKET_MAX_FDS 16
 
+
+typedef void (*QTestSendFn)(QTestState *s, const char *buf);
+typedef GString* (*QTestRecvFn)(QTestState *);
+
+typedef struct QTestClientTransportOps {
+QTestSendFn send;  /* for sending qtest commands */
+QTestRecvFn recv_line; /* for receiving qtest command responses */
+} QTestTransportOps;
+
 struct QTestState
 {
 int fd;
@@ -45,6 +54,7 @@ struct QTestState
 bool big_endian;
 bool irq_level[MAX_IRQ];
 GString *rx;
+QTestTransportOps ops;
 };
 
 static GHookList abrt_hooks;
@@ -52,6 +62,14 @@ static struct sigaction sigact_old;
 
 static int qtest_query_target_endianness(QTestState *s);
 
+static void qtest_client_socket_send(QTestState*, const char *buf);
+static void socket_send(int fd, const char *buf, size_t size);
+
+static GString *qtest_client_socket_recv_line(QTestState *);
+
+static void qtest_client_set_tx_handler(QTestState *s, QTestSendFn send);
+static void qtest_client_set_rx_handler(QTestState *s, QTestRecvFn recv);
+
 static int init_socket(const char *socket_path)
 {
 struct sockaddr_un addr;
@@ -234,6 +252,9 @@ QTestState *qtest_init_without_qmp_handshake(const char 
*extra_args)
 sock = init_socket(socket_path);
 qmpsock = init_socket(qmp_socket_path);
 
+qtest_client_set_rx_handler(s, qtest_client_socket_recv_line);
+qtest_client_set_tx_handler(s, qtest_client_socket_send);
+
 qtest_add_abrt_handler(kill_qemu_hook_func, s);
 
 command = g_strdup_printf("exec %s "
@@ -379,13 +400,9 @@ static void socket_send(int fd, const char *buf, size_t 
size)
 }
 }
 
-static void socket_sendf(int fd, const char *fmt, va_list ap)
+static void qtest_client_socket_send(QTestState *s, const char *buf)
 {
-gchar *str = g_strdup_vprintf(fmt, ap);
-size_t size = strlen(str);
-
-socket_send(fd, str, size);
-g_free(str);
+socket_send(s->fd, buf, strlen(buf));
 }
 
 static void GCC_FMT_ATTR(2, 3) qtest_sendf(QTestState *s, const char *fmt, ...)
@@ -393,8 +410,11 @@ static void GCC_FMT_ATTR(2, 3) qtest_sendf(QTestState *s, 
const char *fmt, ...)
 va_list ap;
 
 va_start(ap, fmt);
-socket_sendf(s->fd, fmt, ap);
+gchar *str = g_strdup_vprintf(fmt, ap);
 va_end(ap);
+
+s->ops.send(s, str);
+g_free(str);
 }
 
 /* Sends a message and file descriptors to the socket.
@@ -431,7 +451,7 @@ static void socket_send_fds(int socket_fd, int *fds, size_t 
fds_num,
 g_assert_cmpint(ret, >, 0);
 }
 
-static GString *qtest_recv_line(QTestState *s)
+static GString *qtest_client_socket_recv_line(QTestState *s)
 {
 GString *line;
 size_t offset;
@@ -468,7 +488,7 @@ static gchar **qtest_rsp(QTestState *s, int expected_args)
 int i;
 
 redo:
-line = qtest_recv_line(s);
+line = s->ops.recv_line(s);
 words = g_strsplit(line->str, " ", 0);
 g_string_free(line, TRUE);
 
@@ -1337,3 +1357,13 @@ void qmp_assert_error_class(QDict *rsp, const char 
*class)
 
 qobject_unref(rsp);
 }
+
+static void qtest_client_set_tx_handler(QTestState *s,
+QTestSendFn send)
+{
+s->ops.send = send;
+}
+static void qtest_client_set_rx_handler(QTestState *s, QTestRecvFn recv)
+{
+s->ops.recv_line = recv;
+}
-- 
2.24.1



[PULL 25/31] fuzz: add support for qos-assisted fuzz targets

2020-02-22 Thread Stefan Hajnoczi
From: Alexander Bulekov 

Signed-off-by: Alexander Bulekov 
Reviewed-by: Stefan Hajnoczi 
Reviewed-by: Darren Kenny 
Message-id: 20200220041118.23264-17-alx...@bu.edu
Signed-off-by: Stefan Hajnoczi 
---
 tests/qtest/fuzz/Makefile.include |   2 +
 tests/qtest/fuzz/qos_fuzz.c   | 234 ++
 tests/qtest/fuzz/qos_fuzz.h   |  33 +
 3 files changed, 269 insertions(+)
 create mode 100644 tests/qtest/fuzz/qos_fuzz.c
 create mode 100644 tests/qtest/fuzz/qos_fuzz.h

diff --git a/tests/qtest/fuzz/Makefile.include 
b/tests/qtest/fuzz/Makefile.include
index a90915d56d..e3bdd33ff4 100644
--- a/tests/qtest/fuzz/Makefile.include
+++ b/tests/qtest/fuzz/Makefile.include
@@ -1,8 +1,10 @@
 QEMU_PROG_FUZZ=qemu-fuzz-$(TARGET_NAME)$(EXESUF)
 
 fuzz-obj-y += tests/qtest/libqtest.o
+fuzz-obj-y += $(libqos-obj-y)
 fuzz-obj-y += tests/qtest/fuzz/fuzz.o # Fuzzer skeleton
 fuzz-obj-y += tests/qtest/fuzz/fork_fuzz.o
+fuzz-obj-y += tests/qtest/fuzz/qos_fuzz.o
 
 FUZZ_CFLAGS += -I$(SRC_PATH)/tests -I$(SRC_PATH)/tests/qtest
 
diff --git a/tests/qtest/fuzz/qos_fuzz.c b/tests/qtest/fuzz/qos_fuzz.c
new file mode 100644
index 00..bbb17470ff
--- /dev/null
+++ b/tests/qtest/fuzz/qos_fuzz.c
@@ -0,0 +1,234 @@
+/*
+ * QOS-assisted fuzzing helpers
+ *
+ * Copyright (c) 2018 Emanuele Giuseppe Esposito 
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see 
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/units.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "exec/memory.h"
+#include "exec/address-spaces.h"
+#include "sysemu/sysemu.h"
+#include "qemu/main-loop.h"
+
+#include "tests/qtest/libqtest.h"
+#include "tests/qtest/libqos/malloc.h"
+#include "tests/qtest/libqos/qgraph.h"
+#include "tests/qtest/libqos/qgraph_internal.h"
+#include "tests/qtest/libqos/qos_external.h"
+
+#include "fuzz.h"
+#include "qos_fuzz.h"
+
+#include "qapi/qapi-commands-machine.h"
+#include "qapi/qapi-commands-qom.h"
+#include "qapi/qmp/qlist.h"
+
+
+void *fuzz_qos_obj;
+QGuestAllocator *fuzz_qos_alloc;
+
+static const char *fuzz_target_name;
+static char **fuzz_path_vec;
+
+/*
+ * Replaced the qmp commands with direct qmp_marshal calls.
+ * Probably there is a better way to do this
+ */
+static void qos_set_machines_devices_available(void)
+{
+QDict *req = qdict_new();
+QObject *response;
+QDict *args = qdict_new();
+QList *lst;
+Error *err = NULL;
+
+qmp_marshal_query_machines(NULL, , );
+assert(!err);
+lst = qobject_to(QList, response);
+apply_to_qlist(lst, true);
+
+qobject_unref(response);
+
+
+qdict_put_str(req, "execute", "qom-list-types");
+qdict_put_str(args, "implements", "device");
+qdict_put_bool(args, "abstract", true);
+qdict_put_obj(req, "arguments", (QObject *) args);
+
+qmp_marshal_qom_list_types(args, , );
+assert(!err);
+lst = qobject_to(QList, response);
+apply_to_qlist(lst, false);
+qobject_unref(response);
+qobject_unref(req);
+}
+
+static char **current_path;
+
+void *qos_allocate_objects(QTestState *qts, QGuestAllocator **p_alloc)
+{
+return allocate_objects(qts, current_path + 1, p_alloc);
+}
+
+static const char *qos_build_main_args(void)
+{
+char **path = fuzz_path_vec;
+QOSGraphNode *test_node;
+GString *cmd_line = g_string_new(path[0]);
+void *test_arg;
+
+if (!path) {
+fprintf(stderr, "QOS Path not found\n");
+abort();
+}
+
+/* Before test */
+current_path = path;
+test_node = qos_graph_get_node(path[(g_strv_length(path) - 1)]);
+test_arg = test_node->u.test.arg;
+if (test_node->u.test.before) {
+test_arg = test_node->u.test.before(cmd_line, test_arg);
+}
+/* Prepend the arguments that we need */
+g_string_prepend(cmd_line,
+TARGET_NAME " -display none -machine accel=qtest -m 64 ");
+return cmd_line->str;
+}
+
+/*
+ * This function is largely a copy of qos-test.c:walk_path. Since walk_path
+ * is itself a callback, its a little annoying to add another argument/layer of
+ * indirection
+ */
+static void walk_path(QOSGraphNode *orig_path, int len)
+{
+QOSGraphNode *path;
+QOSGraphEdge *edge;
+
+/* etype set to QEDGE_CONSUMED_BY so that machine can add to the command 
line */
+QOSEdgeType etype = QEDGE_CONSUMED_BY;
+
+/* twice QOS_PATH_MAX_ELEMENT_SIZE since each edge can have its arg */
+char **path_vec = g_new0(char *, 

[PULL 24/31] fuzz: support for fork-based fuzzing.

2020-02-22 Thread Stefan Hajnoczi
From: Alexander Bulekov 

fork() is a simple way to ensure that state does not leak in between
fuzzing runs. Unfortunately, the fuzzer mutation engine relies on
bitmaps which contain coverage information for each fuzzing run, and
these bitmaps should be copied from the child to the parent(where the
mutation occurs). These bitmaps are created through compile-time
instrumentation and they are not shared with fork()-ed processes, by
default. To address this, we create a shared memory region, adjust its
size and map it _over_ the counter region. Furthermore, libfuzzer
doesn't generally expose the globals that specify the location of the
counters/coverage bitmap. As a workaround, we rely on a custom linker
script which forces all of the bitmaps we care about to be placed in a
contiguous region, which is easy to locate and mmap over.

Signed-off-by: Alexander Bulekov 
Reviewed-by: Stefan Hajnoczi 
Reviewed-by: Darren Kenny 
Message-id: 20200220041118.23264-16-alx...@bu.edu
Signed-off-by: Stefan Hajnoczi 
---
 tests/qtest/fuzz/Makefile.include |  5 +++
 tests/qtest/fuzz/fork_fuzz.c  | 55 +++
 tests/qtest/fuzz/fork_fuzz.h  | 23 +
 tests/qtest/fuzz/fork_fuzz.ld | 37 +
 4 files changed, 120 insertions(+)
 create mode 100644 tests/qtest/fuzz/fork_fuzz.c
 create mode 100644 tests/qtest/fuzz/fork_fuzz.h
 create mode 100644 tests/qtest/fuzz/fork_fuzz.ld

diff --git a/tests/qtest/fuzz/Makefile.include 
b/tests/qtest/fuzz/Makefile.include
index 8632bb89f4..a90915d56d 100644
--- a/tests/qtest/fuzz/Makefile.include
+++ b/tests/qtest/fuzz/Makefile.include
@@ -2,5 +2,10 @@ QEMU_PROG_FUZZ=qemu-fuzz-$(TARGET_NAME)$(EXESUF)
 
 fuzz-obj-y += tests/qtest/libqtest.o
 fuzz-obj-y += tests/qtest/fuzz/fuzz.o # Fuzzer skeleton
+fuzz-obj-y += tests/qtest/fuzz/fork_fuzz.o
 
 FUZZ_CFLAGS += -I$(SRC_PATH)/tests -I$(SRC_PATH)/tests/qtest
+
+# Linker Script to force coverage-counters into known regions which we can mark
+# shared
+FUZZ_LDFLAGS += -Xlinker -T$(SRC_PATH)/tests/qtest/fuzz/fork_fuzz.ld
diff --git a/tests/qtest/fuzz/fork_fuzz.c b/tests/qtest/fuzz/fork_fuzz.c
new file mode 100644
index 00..2bd0851903
--- /dev/null
+++ b/tests/qtest/fuzz/fork_fuzz.c
@@ -0,0 +1,55 @@
+/*
+ * Fork-based fuzzing helpers
+ *
+ * Copyright Red Hat Inc., 2019
+ *
+ * Authors:
+ *  Alexander Bulekov   
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "fork_fuzz.h"
+
+
+void counter_shm_init(void)
+{
+char *shm_path = g_strdup_printf("/qemu-fuzz-cntrs.%d", getpid());
+int fd = shm_open(shm_path, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
+g_free(shm_path);
+
+if (fd == -1) {
+perror("Error: ");
+exit(1);
+}
+if (ftruncate(fd, &__FUZZ_COUNTERS_END - &__FUZZ_COUNTERS_START) == -1) {
+perror("Error: ");
+exit(1);
+}
+/* Copy what's in the counter region to the shm.. */
+void *rptr = mmap(NULL ,
+&__FUZZ_COUNTERS_END - &__FUZZ_COUNTERS_START,
+PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+memcpy(rptr,
+   &__FUZZ_COUNTERS_START,
+   &__FUZZ_COUNTERS_END - &__FUZZ_COUNTERS_START);
+
+munmap(rptr, &__FUZZ_COUNTERS_END - &__FUZZ_COUNTERS_START);
+
+/* And map the shm over the counter region */
+rptr = mmap(&__FUZZ_COUNTERS_START,
+&__FUZZ_COUNTERS_END - &__FUZZ_COUNTERS_START,
+PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, 0);
+
+close(fd);
+
+if (!rptr) {
+perror("Error: ");
+exit(1);
+}
+}
+
+
diff --git a/tests/qtest/fuzz/fork_fuzz.h b/tests/qtest/fuzz/fork_fuzz.h
new file mode 100644
index 00..9ecb8b58ef
--- /dev/null
+++ b/tests/qtest/fuzz/fork_fuzz.h
@@ -0,0 +1,23 @@
+/*
+ * Fork-based fuzzing helpers
+ *
+ * Copyright Red Hat Inc., 2019
+ *
+ * Authors:
+ *  Alexander Bulekov   
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef FORK_FUZZ_H
+#define FORK_FUZZ_H
+
+extern uint8_t __FUZZ_COUNTERS_START;
+extern uint8_t __FUZZ_COUNTERS_END;
+
+void counter_shm_init(void);
+
+#endif
+
diff --git a/tests/qtest/fuzz/fork_fuzz.ld b/tests/qtest/fuzz/fork_fuzz.ld
new file mode 100644
index 00..b23a59f194
--- /dev/null
+++ b/tests/qtest/fuzz/fork_fuzz.ld
@@ -0,0 +1,37 @@
+/* We adjust linker script modification to place all of the stuff that needs to
+ * persist across fuzzing runs into a contiguous seciton of memory. Then, it is
+ * easy to re-map the counter-related memory as shared.
+*/
+
+SECTIONS
+{
+  .data.fuzz_start : ALIGN(4K)
+  {
+  __FUZZ_COUNTERS_START = .;
+  __start___sancov_cntrs = .;
+  *(_*sancov_cntrs);
+  __stop___sancov_cntrs = .;
+
+  /* Lowest stack counter */
+  *(__sancov_lowest_stack);
+  }
+  .data.fuzz_ordered :
+  {

[PULL 30/31] fuzz: add virtio-scsi fuzz target

2020-02-22 Thread Stefan Hajnoczi
From: Alexander Bulekov 

The virtio-scsi fuzz target sets up and fuzzes the available virtio-scsi
queues. After an element is placed on a queue, the fuzzer can select
whether to perform a kick, or continue adding elements.

Signed-off-by: Alexander Bulekov 
Reviewed-by: Darren Kenny 
Message-id: 20200220041118.23264-22-alx...@bu.edu
Signed-off-by: Stefan Hajnoczi 
---
 tests/qtest/fuzz/Makefile.include   |   1 +
 tests/qtest/fuzz/virtio_scsi_fuzz.c | 213 
 2 files changed, 214 insertions(+)
 create mode 100644 tests/qtest/fuzz/virtio_scsi_fuzz.c

diff --git a/tests/qtest/fuzz/Makefile.include 
b/tests/qtest/fuzz/Makefile.include
index 77385777ef..cde3e9636c 100644
--- a/tests/qtest/fuzz/Makefile.include
+++ b/tests/qtest/fuzz/Makefile.include
@@ -9,6 +9,7 @@ fuzz-obj-y += tests/qtest/fuzz/qos_fuzz.o
 # Targets
 fuzz-obj-y += tests/qtest/fuzz/i440fx_fuzz.o
 fuzz-obj-y += tests/qtest/fuzz/virtio_net_fuzz.o
+fuzz-obj-y += tests/qtest/fuzz/virtio_scsi_fuzz.o
 
 FUZZ_CFLAGS += -I$(SRC_PATH)/tests -I$(SRC_PATH)/tests/qtest
 
diff --git a/tests/qtest/fuzz/virtio_scsi_fuzz.c 
b/tests/qtest/fuzz/virtio_scsi_fuzz.c
new file mode 100644
index 00..3b95247f12
--- /dev/null
+++ b/tests/qtest/fuzz/virtio_scsi_fuzz.c
@@ -0,0 +1,213 @@
+/*
+ * virtio-serial Fuzzing Target
+ *
+ * Copyright Red Hat Inc., 2019
+ *
+ * Authors:
+ *  Alexander Bulekov   
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+
+#include "tests/qtest/libqtest.h"
+#include "libqos/virtio-scsi.h"
+#include "libqos/virtio.h"
+#include "libqos/virtio-pci.h"
+#include "standard-headers/linux/virtio_ids.h"
+#include "standard-headers/linux/virtio_pci.h"
+#include "standard-headers/linux/virtio_scsi.h"
+#include "fuzz.h"
+#include "fork_fuzz.h"
+#include "qos_fuzz.h"
+
+#define PCI_SLOT0x02
+#define PCI_FN  0x00
+#define QVIRTIO_SCSI_TIMEOUT_US (1 * 1000 * 1000)
+
+#define MAX_NUM_QUEUES 64
+
+/* Based on tests/virtio-scsi-test.c */
+typedef struct {
+int num_queues;
+QVirtQueue *vq[MAX_NUM_QUEUES + 2];
+} QVirtioSCSIQueues;
+
+static QVirtioSCSIQueues *qvirtio_scsi_init(QVirtioDevice *dev, uint64_t mask)
+{
+QVirtioSCSIQueues *vs;
+uint64_t feat;
+int i;
+
+vs = g_new0(QVirtioSCSIQueues, 1);
+
+feat = qvirtio_get_features(dev);
+if (mask) {
+feat &= ~QVIRTIO_F_BAD_FEATURE | mask;
+} else {
+feat &= ~(QVIRTIO_F_BAD_FEATURE | (1ull << VIRTIO_RING_F_EVENT_IDX));
+}
+qvirtio_set_features(dev, feat);
+
+vs->num_queues = qvirtio_config_readl(dev, 0);
+
+for (i = 0; i < vs->num_queues + 2; i++) {
+vs->vq[i] = qvirtqueue_setup(dev, fuzz_qos_alloc, i);
+}
+
+qvirtio_set_driver_ok(dev);
+
+return vs;
+}
+
+static void virtio_scsi_fuzz(QTestState *s, QVirtioSCSIQueues* queues,
+const unsigned char *Data, size_t Size)
+{
+/*
+ * Data is a sequence of random bytes. We split them up into "actions",
+ * followed by data:
+ * [vqa][][vqa][][vqa][] ...
+ * The length of the data is specified by the preceding vqa.length
+ */
+typedef struct vq_action {
+uint8_t queue;
+uint8_t length;
+uint8_t write;
+uint8_t next;
+uint8_t kick;
+} vq_action;
+
+/* Keep track of the free head for each queue we interact with */
+bool vq_touched[MAX_NUM_QUEUES + 2] = {0};
+uint32_t free_head[MAX_NUM_QUEUES + 2];
+
+QGuestAllocator *t_alloc = fuzz_qos_alloc;
+
+QVirtioSCSI *scsi = fuzz_qos_obj;
+QVirtioDevice *dev = scsi->vdev;
+QVirtQueue *q;
+vq_action vqa;
+while (Size >= sizeof(vqa)) {
+/* Copy the action, so we can normalize length, queue and flags */
+memcpy(, Data, sizeof(vqa));
+
+Data += sizeof(vqa);
+Size -= sizeof(vqa);
+
+vqa.queue = vqa.queue % queues->num_queues;
+/* Cap length at the number of remaining bytes in data */
+vqa.length = vqa.length >= Size ? Size : vqa.length;
+vqa.write = vqa.write & 1;
+vqa.next = vqa.next & 1;
+vqa.kick = vqa.kick & 1;
+
+
+q = queues->vq[vqa.queue];
+
+/* Copy the data into ram, and place it on the virtqueue */
+uint64_t req_addr = guest_alloc(t_alloc, vqa.length);
+qtest_memwrite(s, req_addr, Data, vqa.length);
+if (vq_touched[vqa.queue] == 0) {
+vq_touched[vqa.queue] = 1;
+free_head[vqa.queue] = qvirtqueue_add(s, q, req_addr, vqa.length,
+vqa.write, vqa.next);
+} else {
+qvirtqueue_add(s, q, req_addr, vqa.length, vqa.write , vqa.next);
+}
+
+if (vqa.kick) {
+qvirtqueue_kick(s, dev, q, free_head[vqa.queue]);
+free_head[vqa.queue] = 0;
+}
+Data += vqa.length;
+Size -= vqa.length;
+}
+

[PULL 11/31] softmmu: split off vl.c:main() into main.c

2020-02-22 Thread Stefan Hajnoczi
From: Alexander Bulekov 

A program might rely on functions implemented in vl.c, but implement its
own main(). By placing main into a separate source file, there are no
complaints about duplicate main()s when linking against vl.o. For
example, the virtual-device fuzzer uses a main() provided by libfuzzer,
and needs to perform some initialization before running the softmmu
initialization. Now, main simply calls three vl.c functions which
handle the guest initialization, main loop and cleanup.

Signed-off-by: Alexander Bulekov 
Reviewed-by: Stefan Hajnoczi 
Reviewed-by: Darren Kenny 
Message-id: 20200220041118.23264-3-alx...@bu.edu
Signed-off-by: Stefan Hajnoczi 
---
 MAINTAINERS |  1 +
 Makefile.target |  2 +-
 include/sysemu/sysemu.h |  4 
 softmmu/Makefile.objs   |  1 +
 softmmu/main.c  | 53 +
 softmmu/vl.c| 36 +++-
 6 files changed, 69 insertions(+), 28 deletions(-)
 create mode 100644 softmmu/main.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 6e26d2ec2a..969329f83e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2032,6 +2032,7 @@ F: include/sysemu/runstate.h
 F: util/main-loop.c
 F: util/qemu-timer.c
 F: softmmu/vl.c
+F: softmmu/main.c
 F: qapi/run-state.json
 
 Human Monitor (HMP)
diff --git a/Makefile.target b/Makefile.target
index 06c36d1161..6f4dd72022 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -203,7 +203,7 @@ endif
 COMMON_LDADDS = ../libqemuutil.a
 
 # build either PROG or PROGW
-$(QEMU_PROG_BUILD): $(all-obj-y) $(COMMON_LDADDS)
+$(QEMU_PROG_BUILD): $(all-obj-y) $(COMMON_LDADDS) $(softmmu-main-y)
$(call LINK, $(filter-out %.mak, $^))
 ifdef CONFIG_DARWIN
$(call quiet-command,Rez -append $(SRC_PATH)/pc-bios/qemu.rsrc -o 
$@,"REZ","$(TARGET_DIR)$@")
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index c0678c1ca3..dec64fcc17 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -115,6 +115,10 @@ QemuOpts *qemu_get_machine_opts(void);
 
 bool defaults_enabled(void);
 
+void qemu_init(int argc, char **argv, char **envp);
+void qemu_main_loop(void);
+void qemu_cleanup(void);
+
 extern QemuOptsList qemu_legacy_drive_opts;
 extern QemuOptsList qemu_common_drive_opts;
 extern QemuOptsList qemu_drive_opts;
diff --git a/softmmu/Makefile.objs b/softmmu/Makefile.objs
index d80a5ffe5a..dd15c24346 100644
--- a/softmmu/Makefile.objs
+++ b/softmmu/Makefile.objs
@@ -1,2 +1,3 @@
+softmmu-main-y = softmmu/main.o
 obj-y += vl.o
 vl.o-cflags := $(GPROF_CFLAGS) $(SDL_CFLAGS)
diff --git a/softmmu/main.c b/softmmu/main.c
new file mode 100644
index 00..7adc530c73
--- /dev/null
+++ b/softmmu/main.c
@@ -0,0 +1,53 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2020 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "sysemu/sysemu.h"
+
+#ifdef CONFIG_SDL
+#if defined(__APPLE__) || defined(main)
+#include 
+int main(int argc, char **argv)
+{
+return qemu_main(argc, argv, NULL);
+}
+#undef main
+#define main qemu_main
+#endif
+#endif /* CONFIG_SDL */
+
+#ifdef CONFIG_COCOA
+#undef main
+#define main qemu_main
+#endif /* CONFIG_COCOA */
+
+int main(int argc, char **argv, char **envp)
+{
+qemu_init(argc, argv, envp);
+qemu_main_loop();
+qemu_cleanup();
+
+return 0;
+}
diff --git a/softmmu/vl.c b/softmmu/vl.c
index 794f2e5733..080d3b5106 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -36,25 +36,6 @@
 #include "sysemu/seccomp.h"
 #include "sysemu/tcg.h"
 
-#ifdef CONFIG_SDL
-#if defined(__APPLE__) || defined(main)
-#include 
-int qemu_main(int argc, char **argv, char **envp);
-int main(int argc, char **argv)
-{
-return qemu_main(argc, argv, NULL);
-}
-#undef main
-#define main qemu_main
-#endif
-#endif /* CONFIG_SDL */
-
-#ifdef CONFIG_COCOA
-#undef main
-#define main qemu_main
-#endif /* CONFIG_COCOA */
-
-
 

[PULL 20/31] libqos: move useful qos-test funcs to qos_external

2020-02-22 Thread Stefan Hajnoczi
From: Alexander Bulekov 

The moved functions are not specific to qos-test and might be useful
elsewhere. For example the virtual-device fuzzer makes use of them for
qos-assisted fuzz-targets.

Signed-off-by: Alexander Bulekov 
Reviewed-by: Stefan Hajnoczi 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Darren Kenny 
Message-id: 20200220041118.23264-12-alx...@bu.edu
Signed-off-by: Stefan Hajnoczi 
---
 tests/qtest/Makefile.include  |   1 +
 tests/qtest/libqos/qos_external.c | 168 ++
 tests/qtest/libqos/qos_external.h |  28 +
 tests/qtest/qos-test.c| 132 +--
 4 files changed, 198 insertions(+), 131 deletions(-)
 create mode 100644 tests/qtest/libqos/qos_external.c
 create mode 100644 tests/qtest/libqos/qos_external.h

diff --git a/tests/qtest/Makefile.include b/tests/qtest/Makefile.include
index 838618e6f9..e769c1ad70 100644
--- a/tests/qtest/Makefile.include
+++ b/tests/qtest/Makefile.include
@@ -172,6 +172,7 @@ libqos-usb-obj-y = $(libqos-spapr-obj-y) $(libqos-pc-obj-y) 
tests/qtest/libqos/u
 # qos devices:
 libqos-obj-y =  $(libqgraph-obj-y)
 libqos-obj-y += $(libqos-pc-obj-y) $(libqos-spapr-obj-y)
+libqos-obj-y += tests/qtest/libqos/qos_external.o
 libqos-obj-y += tests/qtest/libqos/e1000e.o
 libqos-obj-y += tests/qtest/libqos/i2c.o
 libqos-obj-y += tests/qtest/libqos/i2c-imx.o
diff --git a/tests/qtest/libqos/qos_external.c 
b/tests/qtest/libqos/qos_external.c
new file mode 100644
index 00..398556dde0
--- /dev/null
+++ b/tests/qtest/libqos/qos_external.c
@@ -0,0 +1,168 @@
+/*
+ * libqos driver framework
+ *
+ * Copyright (c) 2018 Emanuele Giuseppe Esposito 
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see 
+ */
+
+#include "qemu/osdep.h"
+#include 
+#include "libqtest.h"
+#include "qapi/qmp/qdict.h"
+#include "qapi/qmp/qbool.h"
+#include "qapi/qmp/qstring.h"
+#include "qemu/module.h"
+#include "qapi/qmp/qlist.h"
+#include "libqos/malloc.h"
+#include "libqos/qgraph.h"
+#include "libqos/qgraph_internal.h"
+#include "libqos/qos_external.h"
+
+
+
+void apply_to_node(const char *name, bool is_machine, bool is_abstract)
+{
+char *machine_name = NULL;
+if (is_machine) {
+const char *arch = qtest_get_arch();
+machine_name = g_strconcat(arch, "/", name, NULL);
+name = machine_name;
+}
+qos_graph_node_set_availability(name, true);
+if (is_abstract) {
+qos_delete_cmd_line(name);
+}
+g_free(machine_name);
+}
+
+/**
+ * apply_to_qlist(): using QMP queries QEMU for a list of
+ * machines and devices available, and sets the respective node
+ * as true. If a node is found, also all its produced and contained
+ * child are marked available.
+ *
+ * See qos_graph_node_set_availability() for more info
+ */
+void apply_to_qlist(QList *list, bool is_machine)
+{
+const QListEntry *p;
+const char *name;
+bool abstract;
+QDict *minfo;
+QObject *qobj;
+QString *qstr;
+QBool *qbool;
+
+for (p = qlist_first(list); p; p = qlist_next(p)) {
+minfo = qobject_to(QDict, qlist_entry_obj(p));
+qobj = qdict_get(minfo, "name");
+qstr = qobject_to(QString, qobj);
+name = qstring_get_str(qstr);
+
+qobj = qdict_get(minfo, "abstract");
+if (qobj) {
+qbool = qobject_to(QBool, qobj);
+abstract = qbool_get_bool(qbool);
+} else {
+abstract = false;
+}
+
+apply_to_node(name, is_machine, abstract);
+qobj = qdict_get(minfo, "alias");
+if (qobj) {
+qstr = qobject_to(QString, qobj);
+name = qstring_get_str(qstr);
+apply_to_node(name, is_machine, abstract);
+}
+}
+}
+
+QGuestAllocator *get_machine_allocator(QOSGraphObject *obj)
+{
+return obj->get_driver(obj, "memory");
+}
+
+/**
+ * allocate_objects(): given an array of nodes @arg,
+ * walks the path invoking all constructors and
+ * passing the corresponding parameter in order to
+ * continue the objects allocation.
+ * Once the test is reached, return the object it consumes.
+ *
+ * Since the machine and QEDGE_CONSUMED_BY nodes allocate
+ * memory in the constructor, g_test_queue_destroy is used so
+ * that after execution they can be safely free'd.  (The test's
+ * ->before callback is also welcome to use g_test_queue_destroy).
+ *
+ * Note: as specified in walk_path() too, @arg is an array of
+ * char 

[PULL 22/31] exec: keep ram block across fork when using qtest

2020-02-22 Thread Stefan Hajnoczi
From: Alexander Bulekov 

Ram blocks were marked MADV_DONTFORK breaking fuzzing-tests which
execute each test-input in a forked process.

Signed-off-by: Alexander Bulekov 
Reviewed-by: Stefan Hajnoczi 
Reviewed-by: Darren Kenny 
Message-id: 20200220041118.23264-14-alx...@bu.edu
Signed-off-by: Stefan Hajnoczi 
---
 exec.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/exec.c b/exec.c
index 8e9cc3b47c..c930040f83 100644
--- a/exec.c
+++ b/exec.c
@@ -35,6 +35,7 @@
 #include "sysemu/kvm.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/tcg.h"
+#include "sysemu/qtest.h"
 #include "qemu/timer.h"
 #include "qemu/config-file.h"
 #include "qemu/error-report.h"
@@ -2305,8 +2306,15 @@ static void ram_block_add(RAMBlock *new_block, Error 
**errp, bool shared)
 if (new_block->host) {
 qemu_ram_setup_dump(new_block->host, new_block->max_length);
 qemu_madvise(new_block->host, new_block->max_length, 
QEMU_MADV_HUGEPAGE);
-/* MADV_DONTFORK is also needed by KVM in absence of synchronous MMU */
-qemu_madvise(new_block->host, new_block->max_length, 
QEMU_MADV_DONTFORK);
+/*
+ * MADV_DONTFORK is also needed by KVM in absence of synchronous MMU
+ * Configure it unless the machine is a qtest server, in which case
+ * KVM is not used and it may be forked (eg for fuzzing purposes).
+ */
+if (!qtest_enabled()) {
+qemu_madvise(new_block->host, new_block->max_length,
+ QEMU_MADV_DONTFORK);
+}
 ram_block_notify_add(new_block->host, new_block->max_length);
 }
 }
-- 
2.24.1



[PULL 18/31] libqos: rename i2c_send and i2c_recv

2020-02-22 Thread Stefan Hajnoczi
From: Alexander Bulekov 

The names i2c_send and i2c_recv collide with functions defined in
hw/i2c/core.c. This causes an error when linking against libqos and
softmmu simultaneously (for example when using qtest inproc). Rename the
libqos functions to avoid this.

Signed-off-by: Alexander Bulekov 
Reviewed-by: Stefan Hajnoczi 
Reviewed-by: Darren Kenny 
Acked-by: Thomas Huth 
Message-id: 20200220041118.23264-10-alx...@bu.edu
Signed-off-by: Stefan Hajnoczi 
---
 tests/qtest/libqos/i2c.c   | 10 +-
 tests/qtest/libqos/i2c.h   |  4 ++--
 tests/qtest/pca9552-test.c | 10 +-
 3 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/tests/qtest/libqos/i2c.c b/tests/qtest/libqos/i2c.c
index 156114e745..38f800dbab 100644
--- a/tests/qtest/libqos/i2c.c
+++ b/tests/qtest/libqos/i2c.c
@@ -10,12 +10,12 @@
 #include "libqos/i2c.h"
 #include "libqtest.h"
 
-void i2c_send(QI2CDevice *i2cdev, const uint8_t *buf, uint16_t len)
+void qi2c_send(QI2CDevice *i2cdev, const uint8_t *buf, uint16_t len)
 {
 i2cdev->bus->send(i2cdev->bus, i2cdev->addr, buf, len);
 }
 
-void i2c_recv(QI2CDevice *i2cdev, uint8_t *buf, uint16_t len)
+void qi2c_recv(QI2CDevice *i2cdev, uint8_t *buf, uint16_t len)
 {
 i2cdev->bus->recv(i2cdev->bus, i2cdev->addr, buf, len);
 }
@@ -23,8 +23,8 @@ void i2c_recv(QI2CDevice *i2cdev, uint8_t *buf, uint16_t len)
 void i2c_read_block(QI2CDevice *i2cdev, uint8_t reg,
 uint8_t *buf, uint16_t len)
 {
-i2c_send(i2cdev, , 1);
-i2c_recv(i2cdev, buf, len);
+qi2c_send(i2cdev, , 1);
+qi2c_recv(i2cdev, buf, len);
 }
 
 void i2c_write_block(QI2CDevice *i2cdev, uint8_t reg,
@@ -33,7 +33,7 @@ void i2c_write_block(QI2CDevice *i2cdev, uint8_t reg,
 uint8_t *cmd = g_malloc(len + 1);
 cmd[0] = reg;
 memcpy([1], buf, len);
-i2c_send(i2cdev, cmd, len + 1);
+qi2c_send(i2cdev, cmd, len + 1);
 g_free(cmd);
 }
 
diff --git a/tests/qtest/libqos/i2c.h b/tests/qtest/libqos/i2c.h
index 945b65b34c..c65f087834 100644
--- a/tests/qtest/libqos/i2c.h
+++ b/tests/qtest/libqos/i2c.h
@@ -47,8 +47,8 @@ struct QI2CDevice {
 void *i2c_device_create(void *i2c_bus, QGuestAllocator *alloc, void *addr);
 void add_qi2c_address(QOSGraphEdgeOptions *opts, QI2CAddress *addr);
 
-void i2c_send(QI2CDevice *dev, const uint8_t *buf, uint16_t len);
-void i2c_recv(QI2CDevice *dev, uint8_t *buf, uint16_t len);
+void qi2c_send(QI2CDevice *dev, const uint8_t *buf, uint16_t len);
+void qi2c_recv(QI2CDevice *dev, uint8_t *buf, uint16_t len);
 
 void i2c_read_block(QI2CDevice *dev, uint8_t reg,
 uint8_t *buf, uint16_t len);
diff --git a/tests/qtest/pca9552-test.c b/tests/qtest/pca9552-test.c
index 4b800d3c3e..d80ed93cd3 100644
--- a/tests/qtest/pca9552-test.c
+++ b/tests/qtest/pca9552-test.c
@@ -32,22 +32,22 @@ static void receive_autoinc(void *obj, void *data, 
QGuestAllocator *alloc)
 
 pca9552_init(i2cdev);
 
-i2c_send(i2cdev, , 1);
+qi2c_send(i2cdev, , 1);
 
 /* PCA9552_LS0 */
-i2c_recv(i2cdev, , 1);
+qi2c_recv(i2cdev, , 1);
 g_assert_cmphex(resp, ==, 0x54);
 
 /* PCA9552_LS1 */
-i2c_recv(i2cdev, , 1);
+qi2c_recv(i2cdev, , 1);
 g_assert_cmphex(resp, ==, 0x55);
 
 /* PCA9552_LS2 */
-i2c_recv(i2cdev, , 1);
+qi2c_recv(i2cdev, , 1);
 g_assert_cmphex(resp, ==, 0x55);
 
 /* PCA9552_LS3 */
-i2c_recv(i2cdev, , 1);
+qi2c_recv(i2cdev, , 1);
 g_assert_cmphex(resp, ==, 0x54);
 }
 
-- 
2.24.1



[PULL 09/31] aio-posix: make AioHandler dispatch O(1) with epoll

2020-02-22 Thread Stefan Hajnoczi
File descriptor monitoring is O(1) with epoll(7), but
aio_dispatch_handlers() still scans all AioHandlers instead of
dispatching just those that are ready.  This makes aio_poll() O(n) with
respect to the total number of registered handlers.

Add a local ready_list to aio_poll() so that each nested aio_poll()
builds a list of handlers ready to be dispatched.  Since file descriptor
polling is level-triggered, nested aio_poll() calls also see fds that
were ready in the parent but not yet dispatched.  This guarantees that
nested aio_poll() invocations will dispatch all fds, even those that
became ready before the nested invocation.

Since only handlers ready to be dispatched are placed onto the
ready_list, the new aio_dispatch_ready_handlers() function provides O(1)
dispatch.

Note that AioContext polling is still O(n) and currently cannot be fully
disabled.  This still needs to be fixed before aio_poll() is fully O(1).

Signed-off-by: Stefan Hajnoczi 
Reviewed-by: Sergio Lopez 
Message-id: 20200214171712.541358-6-stefa...@redhat.com
[Fix compilation error on macOS where there is no epoll(87).  The
aio_epoll() prototype was out of date and aio_add_ready_list() needed to
be moved outside the ifdef.
--Stefan]
Signed-off-by: Stefan Hajnoczi 
---
 util/aio-posix.c | 110 +--
 1 file changed, 78 insertions(+), 32 deletions(-)

diff --git a/util/aio-posix.c b/util/aio-posix.c
index b5cfdbd2f6..9e1befc0c0 100644
--- a/util/aio-posix.c
+++ b/util/aio-posix.c
@@ -35,9 +35,20 @@ struct AioHandler
 void *opaque;
 bool is_external;
 QLIST_ENTRY(AioHandler) node;
+QLIST_ENTRY(AioHandler) node_ready; /* only used during aio_poll() */
 QLIST_ENTRY(AioHandler) node_deleted;
 };
 
+/* Add a handler to a ready list */
+static void add_ready_handler(AioHandlerList *ready_list,
+  AioHandler *node,
+  int revents)
+{
+QLIST_SAFE_REMOVE(node, node_ready); /* remove from nested parent's list */
+node->pfd.revents = revents;
+QLIST_INSERT_HEAD(ready_list, node, node_ready);
+}
+
 #ifdef CONFIG_EPOLL_CREATE1
 
 /* The fd number threshold to switch to epoll */
@@ -105,7 +116,8 @@ static void aio_epoll_update(AioContext *ctx, AioHandler 
*node, bool is_new)
 }
 }
 
-static int aio_epoll(AioContext *ctx, int64_t timeout)
+static int aio_epoll(AioContext *ctx, AioHandlerList *ready_list,
+ int64_t timeout)
 {
 GPollFD pfd = {
 .fd = ctx->epollfd,
@@ -130,11 +142,13 @@ static int aio_epoll(AioContext *ctx, int64_t timeout)
 }
 for (i = 0; i < ret; i++) {
 int ev = events[i].events;
+int revents = (ev & EPOLLIN ? G_IO_IN : 0) |
+  (ev & EPOLLOUT ? G_IO_OUT : 0) |
+  (ev & EPOLLHUP ? G_IO_HUP : 0) |
+  (ev & EPOLLERR ? G_IO_ERR : 0);
+
 node = events[i].data.ptr;
-node->pfd.revents = (ev & EPOLLIN ? G_IO_IN : 0) |
-(ev & EPOLLOUT ? G_IO_OUT : 0) |
-(ev & EPOLLHUP ? G_IO_HUP : 0) |
-(ev & EPOLLERR ? G_IO_ERR : 0);
+add_ready_handler(ready_list, node, revents);
 }
 }
 out:
@@ -172,8 +186,8 @@ static void aio_epoll_update(AioContext *ctx, AioHandler 
*node, bool is_new)
 {
 }
 
-static int aio_epoll(AioContext *ctx, GPollFD *pfds,
- unsigned npfd, int64_t timeout)
+static int aio_epoll(AioContext *ctx, AioHandlerList *ready_list,
+ int64_t timeout)
 {
 assert(false);
 }
@@ -438,36 +452,63 @@ static void aio_free_deleted_handlers(AioContext *ctx)
 qemu_lockcnt_inc_and_unlock(>list_lock);
 }
 
-static bool aio_dispatch_handlers(AioContext *ctx)
+static bool aio_dispatch_handler(AioContext *ctx, AioHandler *node)
 {
-AioHandler *node, *tmp;
 bool progress = false;
+int revents;
 
-QLIST_FOREACH_SAFE_RCU(node, >aio_handlers, node, tmp) {
-int revents;
+revents = node->pfd.revents & node->pfd.events;
+node->pfd.revents = 0;
 
-revents = node->pfd.revents & node->pfd.events;
-node->pfd.revents = 0;
+if (!QLIST_IS_INSERTED(node, node_deleted) &&
+(revents & (G_IO_IN | G_IO_HUP | G_IO_ERR)) &&
+aio_node_check(ctx, node->is_external) &&
+node->io_read) {
+node->io_read(node->opaque);
 
-if (!QLIST_IS_INSERTED(node, node_deleted) &&
-(revents & (G_IO_IN | G_IO_HUP | G_IO_ERR)) &&
-aio_node_check(ctx, node->is_external) &&
-node->io_read) {
-node->io_read(node->opaque);
-
-/* aio_notify() does not count as progress */
-if (node->opaque != >notifier) {
-progress = true;
-}
-}
-if (!QLIST_IS_INSERTED(node, node_deleted) &&
-(revents & (G_IO_OUT | G_IO_ERR)) &&
-aio_node_check(ctx, node->is_external) &&
-  

[PULL 27/31] fuzz: add configure flag --enable-fuzzing

2020-02-22 Thread Stefan Hajnoczi
From: Alexander Bulekov 

Signed-off-by: Alexander Bulekov 
Reviewed-by: Stefan Hajnoczi 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Darren Kenny 
Message-id: 20200220041118.23264-19-alx...@bu.edu
Signed-off-by: Stefan Hajnoczi 
---
 configure | 39 +++
 1 file changed, 39 insertions(+)

diff --git a/configure b/configure
index d57261e3ad..48d6f89d57 100755
--- a/configure
+++ b/configure
@@ -505,6 +505,7 @@ debug_mutex="no"
 libpmem=""
 default_devices="yes"
 plugins="no"
+fuzzing="no"
 
 supported_cpu="no"
 supported_os="no"
@@ -635,6 +636,15 @@ int main(void) { return 0; }
 EOF
 }
 
+write_c_fuzzer_skeleton() {
+cat > $TMPC <
+#include 
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { return 0; }
+EOF
+}
+
 if check_define __linux__ ; then
   targetos="Linux"
 elif check_define _WIN32 ; then
@@ -1558,6 +1568,10 @@ for opt do
   ;;
   --disable-containers) use_containers="no"
   ;;
+  --enable-fuzzing) fuzzing=yes
+  ;;
+  --disable-fuzzing) fuzzing=no
+  ;;
   *)
   echo "ERROR: unknown option $opt"
   echo "Try '$0 --help' for more information"
@@ -6072,6 +6086,15 @@ EOF
   fi
 fi
 
+##
+# checks for fuzzer
+if test "$fuzzing" = "yes" ; then
+  write_c_fuzzer_skeleton
+  if compile_prog "$CPU_CFLAGS -Werror -fsanitize=address,fuzzer" ""; then
+  have_fuzzer=yes
+  fi
+fi
+
 ##
 # check for libpmem
 
@@ -,6 +6689,7 @@ echo "libpmem support   $libpmem"
 echo "libudev   $libudev"
 echo "default devices   $default_devices"
 echo "plugin support$plugins"
+echo "fuzzing support   $fuzzing"
 
 if test "$supported_cpu" = "no"; then
 echo
@@ -7504,6 +7528,16 @@ fi
 if test "$sheepdog" = "yes" ; then
   echo "CONFIG_SHEEPDOG=y" >> $config_host_mak
 fi
+if test "$fuzzing" = "yes" ; then
+  if test "$have_fuzzer" = "yes"; then
+FUZZ_LDFLAGS=" -fsanitize=address,fuzzer"
+FUZZ_CFLAGS=" -fsanitize=address,fuzzer"
+CFLAGS=" -fsanitize=address,fuzzer-no-link"
+  else
+error_exit "Your compiler doesn't support -fsanitize=address,fuzzer"
+exit 1
+  fi
+fi
 
 if test "$plugins" = "yes" ; then
 echo "CONFIG_PLUGIN=y" >> $config_host_mak
@@ -7605,6 +7639,11 @@ if test "$libudev" != "no"; then
 echo "CONFIG_LIBUDEV=y" >> $config_host_mak
 echo "LIBUDEV_LIBS=$libudev_libs" >> $config_host_mak
 fi
+if test "$fuzzing" != "no"; then
+echo "CONFIG_FUZZ=y" >> $config_host_mak
+echo "FUZZ_CFLAGS=$FUZZ_CFLAGS" >> $config_host_mak
+echo "FUZZ_LDFLAGS=$FUZZ_LDFLAGS" >> $config_host_mak
+fi
 
 if test "$edk2_blobs" = "yes" ; then
   echo "DECOMPRESS_EDK2_BLOBS=y" >> $config_host_mak
-- 
2.24.1



[PULL 16/31] libqtest: make bufwrite rely on the TransportOps

2020-02-22 Thread Stefan Hajnoczi
From: Alexander Bulekov 

When using qtest "in-process" communication, qtest_sendf directly calls
a function in the server (qtest.c). Previously, bufwrite used
socket_send, which bypasses the TransportOps enabling the call into
qtest.c. This change replaces the socket_send calls with ops->send,
maintaining the benefits of the direct socket_send call, while adding
support for in-process qtest calls.

Signed-off-by: Alexander Bulekov 
Reviewed-by: Stefan Hajnoczi 
Reviewed-by: Darren Kenny 
Message-id: 20200220041118.23264-8-alx...@bu.edu
Signed-off-by: Stefan Hajnoczi 
---
 tests/qtest/libqtest.c | 71 --
 tests/qtest/libqtest.h |  4 +++
 2 files changed, 73 insertions(+), 2 deletions(-)

diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c
index e5056a1d0f..49075b55a1 100644
--- a/tests/qtest/libqtest.c
+++ b/tests/qtest/libqtest.c
@@ -37,10 +37,18 @@
 
 
 typedef void (*QTestSendFn)(QTestState *s, const char *buf);
+typedef void (*ExternalSendFn)(void *s, const char *buf);
 typedef GString* (*QTestRecvFn)(QTestState *);
 
 typedef struct QTestClientTransportOps {
 QTestSendFn send;  /* for sending qtest commands */
+
+/*
+ * use external_send to send qtest command strings through functions which
+ * do not accept a QTestState as the first parameter.
+ */
+ExternalSendFn  external_send;
+
 QTestRecvFn recv_line; /* for receiving qtest command responses */
 } QTestTransportOps;
 
@@ -1078,8 +1086,8 @@ void qtest_bufwrite(QTestState *s, uint64_t addr, const 
void *data, size_t size)
 
 bdata = g_base64_encode(data, size);
 qtest_sendf(s, "b64write 0x%" PRIx64 " 0x%zx ", addr, size);
-socket_send(s->fd, bdata, strlen(bdata));
-socket_send(s->fd, "\n", 1);
+s->ops.send(s, bdata);
+s->ops.send(s, "\n");
 qtest_rsp(s, 0);
 g_free(bdata);
 }
@@ -1367,3 +1375,62 @@ static void qtest_client_set_rx_handler(QTestState *s, 
QTestRecvFn recv)
 {
 s->ops.recv_line = recv;
 }
+/* A type-safe wrapper for s->send() */
+static void send_wrapper(QTestState *s, const char *buf)
+{
+s->ops.external_send(s, buf);
+}
+
+static GString *qtest_client_inproc_recv_line(QTestState *s)
+{
+GString *line;
+size_t offset;
+char *eol;
+
+eol = strchr(s->rx->str, '\n');
+offset = eol - s->rx->str;
+line = g_string_new_len(s->rx->str, offset);
+g_string_erase(s->rx, 0, offset + 1);
+return line;
+}
+
+QTestState *qtest_inproc_init(QTestState **s, bool log, const char* arch,
+void (*send)(void*, const char*))
+{
+QTestState *qts;
+qts = g_new0(QTestState, 1);
+*s = qts; /* Expose qts early on, since the query endianness relies on it 
*/
+qts->wstatus = 0;
+for (int i = 0; i < MAX_IRQ; i++) {
+qts->irq_level[i] = false;
+}
+
+qtest_client_set_rx_handler(qts, qtest_client_inproc_recv_line);
+
+/* send() may not have a matching protoype, so use a type-safe wrapper */
+qts->ops.external_send = send;
+qtest_client_set_tx_handler(qts, send_wrapper);
+
+qts->big_endian = qtest_query_target_endianness(qts);
+
+/*
+ * Set a dummy path for QTEST_QEMU_BINARY. Doesn't need to exist, but this
+ * way, qtest_get_arch works for inproc qtest.
+ */
+gchar *bin_path = g_strconcat("/qemu-system-", arch, NULL);
+setenv("QTEST_QEMU_BINARY", bin_path, 0);
+g_free(bin_path);
+
+return qts;
+}
+
+void qtest_client_inproc_recv(void *opaque, const char *str)
+{
+QTestState *qts = *(QTestState **)opaque;
+
+if (!qts->rx) {
+qts->rx = g_string_new(NULL);
+}
+g_string_append(qts->rx, str);
+return;
+}
diff --git a/tests/qtest/libqtest.h b/tests/qtest/libqtest.h
index c9e21e05b3..f5cf93c386 100644
--- a/tests/qtest/libqtest.h
+++ b/tests/qtest/libqtest.h
@@ -729,4 +729,8 @@ bool qtest_probe_child(QTestState *s);
  */
 void qtest_set_expected_status(QTestState *s, int status);
 
+QTestState *qtest_inproc_init(QTestState **s, bool log, const char* arch,
+void (*send)(void*, const char*));
+
+void qtest_client_inproc_recv(void *opaque, const char *str);
 #endif
-- 
2.24.1



[PULL 17/31] qtest: add in-process incoming command handler

2020-02-22 Thread Stefan Hajnoczi
From: Alexander Bulekov 

The handler allows a qtest client to send commands to the server by
directly calling a function, rather than using a file/CharBackend

Signed-off-by: Alexander Bulekov 
Reviewed-by: Stefan Hajnoczi 
Reviewed-by: Darren Kenny 
Message-id: 20200220041118.23264-9-alx...@bu.edu
Signed-off-by: Stefan Hajnoczi 
---
 include/sysemu/qtest.h |  1 +
 qtest.c| 13 +
 2 files changed, 14 insertions(+)

diff --git a/include/sysemu/qtest.h b/include/sysemu/qtest.h
index e2f1047fd7..eedd3664f0 100644
--- a/include/sysemu/qtest.h
+++ b/include/sysemu/qtest.h
@@ -28,5 +28,6 @@ void qtest_server_init(const char *qtest_chrdev, const char 
*qtest_log, Error **
 
 void qtest_server_set_send_handler(void (*send)(void *, const char *),
  void *opaque);
+void qtest_server_inproc_recv(void *opaque, const char *buf);
 
 #endif
diff --git a/qtest.c b/qtest.c
index 8a4ba59828..43bb90f53e 100644
--- a/qtest.c
+++ b/qtest.c
@@ -804,3 +804,16 @@ bool qtest_driver(void)
 {
 return qtest_chr.chr != NULL;
 }
+
+void qtest_server_inproc_recv(void *dummy, const char *buf)
+{
+static GString *gstr;
+if (!gstr) {
+gstr = g_string_new(NULL);
+}
+g_string_append(gstr, buf);
+if (gstr->str[gstr->len - 1] == '\n') {
+qtest_process_inbuf(NULL, gstr);
+g_string_truncate(gstr, 0);
+}
+}
-- 
2.24.1



[PULL 23/31] main: keep rcu_atfork callback enabled for qtest

2020-02-22 Thread Stefan Hajnoczi
From: Alexander Bulekov 

The qtest-based fuzzer makes use of forking to reset-state between
tests. Keep the callback enabled, so the call_rcu thread gets created
within the child process.

Signed-off-by: Alexander Bulekov 
Reviewed-by: Darren Kenny 
Acked-by: Stefan Hajnoczi 
Message-id: 20200220041118.23264-15-alx...@bu.edu
Signed-off-by: Stefan Hajnoczi 
---
 softmmu/vl.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/softmmu/vl.c b/softmmu/vl.c
index 080d3b5106..92c7b3a6e9 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -3782,7 +3782,17 @@ void qemu_init(int argc, char **argv, char **envp)
 set_memory_options(_slots, _size, machine_class);
 
 os_daemonize();
-rcu_disable_atfork();
+
+/*
+ * If QTest is enabled, keep the rcu_atfork enabled, since system processes
+ * may be forked testing purposes (e.g. fork-server based fuzzing) The fork
+ * should happen before a signle cpu instruction is executed, to prevent
+ * deadlocks. See commit 73c6e40, rcu: "completely disable pthread_atfork
+ * callbacks as soon as possible"
+ */
+if (!qtest_enabled()) {
+rcu_disable_atfork();
+}
 
 if (pid_file && !qemu_write_pidfile(pid_file, )) {
 error_reportf_err(err, "cannot create PID file: ");
-- 
2.24.1



[PULL 07/31] qemu/queue.h: add QLIST_SAFE_REMOVE()

2020-02-22 Thread Stefan Hajnoczi
QLIST_REMOVE() assumes the element is in a list.  It also leaves the
element's linked list pointers dangling.

Introduce a safe version of QLIST_REMOVE() and convert open-coded
instances of this pattern.

Signed-off-by: Stefan Hajnoczi 
Reviewed-by: Sergio Lopez 
Message-id: 20200214171712.541358-4-stefa...@redhat.com
Signed-off-by: Stefan Hajnoczi 
---
 block.c  |  5 +
 chardev/spice.c  |  4 +---
 include/qemu/queue.h | 14 ++
 3 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/block.c b/block.c
index 308a91c96b..1bdb9c679d 100644
--- a/block.c
+++ b/block.c
@@ -2636,10 +2636,7 @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
 
 static void bdrv_detach_child(BdrvChild *child)
 {
-if (child->next.le_prev) {
-QLIST_REMOVE(child, next);
-child->next.le_prev = NULL;
-}
+QLIST_SAFE_REMOVE(child, next);
 
 bdrv_replace_child(child, NULL);
 
diff --git a/chardev/spice.c b/chardev/spice.c
index 241e2b7770..bf7ea1e294 100644
--- a/chardev/spice.c
+++ b/chardev/spice.c
@@ -216,9 +216,7 @@ static void char_spice_finalize(Object *obj)
 
 vmc_unregister_interface(s);
 
-if (s->next.le_prev) {
-QLIST_REMOVE(s, next);
-}
+QLIST_SAFE_REMOVE(s, next);
 
 g_free((char *)s->sin.subtype);
 g_free((char *)s->sin.portname);
diff --git a/include/qemu/queue.h b/include/qemu/queue.h
index fcecb70228..60e794a4e3 100644
--- a/include/qemu/queue.h
+++ b/include/qemu/queue.h
@@ -144,6 +144,20 @@ struct {   
 \
 *(elm)->field.le_prev = (elm)->field.le_next;   \
 } while (/*CONSTCOND*/0)
 
+/*
+ * Like QLIST_REMOVE() but safe to call when elm is not in a list
+ */
+#define QLIST_SAFE_REMOVE(elm, field) do {  \
+if ((elm)->field.le_prev != NULL) { \
+if ((elm)->field.le_next != NULL)   \
+(elm)->field.le_next->field.le_prev =   \
+(elm)->field.le_prev;   \
+*(elm)->field.le_prev = (elm)->field.le_next;   \
+(elm)->field.le_next = NULL;\
+(elm)->field.le_prev = NULL;\
+}   \
+} while (/*CONSTCOND*/0)
+
 #define QLIST_FOREACH(var, head, field) \
 for ((var) = ((head)->lh_first);\
 (var);  \
-- 
2.24.1



[PULL 13/31] fuzz: add FUZZ_TARGET module type

2020-02-22 Thread Stefan Hajnoczi
From: Alexander Bulekov 

Signed-off-by: Alexander Bulekov 
Reviewed-by: Stefan Hajnoczi 
Reviewed-by: Darren Kenny 
Message-id: 20200220041118.23264-5-alx...@bu.edu
Signed-off-by: Stefan Hajnoczi 
---
 include/qemu/module.h | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/include/qemu/module.h b/include/qemu/module.h
index 65ba596e46..684753d808 100644
--- a/include/qemu/module.h
+++ b/include/qemu/module.h
@@ -46,6 +46,7 @@ typedef enum {
 MODULE_INIT_TRACE,
 MODULE_INIT_XEN_BACKEND,
 MODULE_INIT_LIBQOS,
+MODULE_INIT_FUZZ_TARGET,
 MODULE_INIT_MAX
 } module_init_type;
 
@@ -56,7 +57,8 @@ typedef enum {
 #define xen_backend_init(function) module_init(function, \
MODULE_INIT_XEN_BACKEND)
 #define libqos_init(function) module_init(function, MODULE_INIT_LIBQOS)
-
+#define fuzz_target_init(function) module_init(function, \
+   MODULE_INIT_FUZZ_TARGET)
 #define block_module_load_one(lib) module_load_one("block-", lib)
 #define ui_module_load_one(lib) module_load_one("ui-", lib)
 #define audio_module_load_one(lib) module_load_one("audio-", lib)
-- 
2.24.1



[PULL 05/31] aio-posix: fix use after leaving scope in aio_poll()

2020-02-22 Thread Stefan Hajnoczi
epoll_handler is a stack variable and must not be accessed after it goes
out of scope:

  if (aio_epoll_check_poll(ctx, pollfds, npfd, timeout)) {
  AioHandler epoll_handler;
  ...
  add_pollfd(_handler);
  ret = aio_epoll(ctx, pollfds, npfd, timeout);
  } ...

  ...

  /* if we have any readable fds, dispatch event */
  if (ret > 0) {
  for (i = 0; i < npfd; i++) {
  nodes[i]->pfd.revents = pollfds[i].revents;
  }
  }

nodes[0] is _handler, which has already gone out of scope.

There is no need to use pollfds[] for epoll.  We don't need an
AioHandler for the epoll fd.

Signed-off-by: Stefan Hajnoczi 
Reviewed-by: Sergio Lopez 
Message-id: 20200214171712.541358-2-stefa...@redhat.com
Signed-off-by: Stefan Hajnoczi 
---
 util/aio-posix.c | 20 
 1 file changed, 8 insertions(+), 12 deletions(-)

diff --git a/util/aio-posix.c b/util/aio-posix.c
index f67f5b34e9..c964627a03 100644
--- a/util/aio-posix.c
+++ b/util/aio-posix.c
@@ -105,17 +105,18 @@ static void aio_epoll_update(AioContext *ctx, AioHandler 
*node, bool is_new)
 }
 }
 
-static int aio_epoll(AioContext *ctx, GPollFD *pfds,
- unsigned npfd, int64_t timeout)
+static int aio_epoll(AioContext *ctx, int64_t timeout)
 {
+GPollFD pfd = {
+.fd = ctx->epollfd,
+.events = G_IO_IN | G_IO_OUT | G_IO_HUP | G_IO_ERR,
+};
 AioHandler *node;
 int i, ret = 0;
 struct epoll_event events[128];
 
-assert(npfd == 1);
-assert(pfds[0].fd == ctx->epollfd);
 if (timeout > 0) {
-ret = qemu_poll_ns(pfds, npfd, timeout);
+ret = qemu_poll_ns(, 1, timeout);
 }
 if (timeout <= 0 || ret > 0) {
 ret = epoll_wait(ctx->epollfd, events,
@@ -669,13 +670,8 @@ bool aio_poll(AioContext *ctx, bool blocking)
 
 /* wait until next event */
 if (aio_epoll_check_poll(ctx, pollfds, npfd, timeout)) {
-AioHandler epoll_handler;
-
-epoll_handler.pfd.fd = ctx->epollfd;
-epoll_handler.pfd.events = G_IO_IN | G_IO_OUT | G_IO_HUP | 
G_IO_ERR;
-npfd = 0;
-add_pollfd(_handler);
-ret = aio_epoll(ctx, pollfds, npfd, timeout);
+npfd = 0; /* pollfds[] is not being used */
+ret = aio_epoll(ctx, timeout);
 } else  {
 ret = qemu_poll_ns(pollfds, npfd, timeout);
 }
-- 
2.24.1



[PULL 19/31] libqos: split qos-test and libqos makefile vars

2020-02-22 Thread Stefan Hajnoczi
From: Alexander Bulekov 

Most qos-related objects were specified in the qos-test-obj-y variable.
qos-test-obj-y also included qos-test.o which defines a main().
This made it difficult to repurpose qos-test-obj-y to link anything
beside tests/qos-test against libqos. This change separates objects that
are libqos-specific and ones that are qos-test specific into different
variables.

Signed-off-by: Alexander Bulekov 
Reviewed-by: Darren Kenny 
Reviewed-by: Stefan Hajnoczi 
Reviewed-by: Philippe Mathieu-Daudé 
Message-id: 20200220041118.23264-11-alx...@bu.edu
Signed-off-by: Stefan Hajnoczi 
---
 tests/qtest/Makefile.include | 71 ++--
 1 file changed, 36 insertions(+), 35 deletions(-)

diff --git a/tests/qtest/Makefile.include b/tests/qtest/Makefile.include
index eb0f23b108..838618e6f9 100644
--- a/tests/qtest/Makefile.include
+++ b/tests/qtest/Makefile.include
@@ -157,52 +157,53 @@ check-qtest-s390x-y += migration-test
 # libqos / qgraph :
 libqgraph-obj-y = tests/qtest/libqos/qgraph.o
 
-libqos-obj-y = $(libqgraph-obj-y) tests/qtest/libqos/pci.o 
tests/qtest/libqos/fw_cfg.o
-libqos-obj-y += tests/qtest/libqos/malloc.o
-libqos-obj-y += tests/qtest/libqos/libqos.o
-libqos-spapr-obj-y = $(libqos-obj-y) tests/qtest/libqos/malloc-spapr.o
+libqos-core-obj-y = $(libqgraph-obj-y) tests/qtest/libqos/pci.o 
tests/qtest/libqos/fw_cfg.o
+libqos-core-obj-y += tests/qtest/libqos/malloc.o
+libqos-core-obj-y += tests/qtest/libqos/libqos.o
+libqos-spapr-obj-y = $(libqos-core-obj-y) tests/qtest/libqos/malloc-spapr.o
 libqos-spapr-obj-y += tests/qtest/libqos/libqos-spapr.o
 libqos-spapr-obj-y += tests/qtest/libqos/rtas.o
 libqos-spapr-obj-y += tests/qtest/libqos/pci-spapr.o
-libqos-pc-obj-y = $(libqos-obj-y) tests/qtest/libqos/pci-pc.o
+libqos-pc-obj-y = $(libqos-core-obj-y) tests/qtest/libqos/pci-pc.o
 libqos-pc-obj-y += tests/qtest/libqos/malloc-pc.o 
tests/qtest/libqos/libqos-pc.o
 libqos-pc-obj-y += tests/qtest/libqos/ahci.o
 libqos-usb-obj-y = $(libqos-spapr-obj-y) $(libqos-pc-obj-y) 
tests/qtest/libqos/usb.o
 
 # qos devices:
-qos-test-obj-y = tests/qtest/qos-test.o $(libqgraph-obj-y)
-qos-test-obj-y += $(libqos-pc-obj-y) $(libqos-spapr-obj-y)
-qos-test-obj-y += tests/qtest/libqos/e1000e.o
-qos-test-obj-y += tests/qtest/libqos/i2c.o
-qos-test-obj-y += tests/qtest/libqos/i2c-imx.o
-qos-test-obj-y += tests/qtest/libqos/i2c-omap.o
-qos-test-obj-y += tests/qtest/libqos/sdhci.o
-qos-test-obj-y += tests/qtest/libqos/tpci200.o
-qos-test-obj-y += tests/qtest/libqos/virtio.o
-qos-test-obj-$(CONFIG_VIRTFS) += tests/qtest/libqos/virtio-9p.o
-qos-test-obj-y += tests/qtest/libqos/virtio-balloon.o
-qos-test-obj-y += tests/qtest/libqos/virtio-blk.o
-qos-test-obj-y += tests/qtest/libqos/virtio-mmio.o
-qos-test-obj-y += tests/qtest/libqos/virtio-net.o
-qos-test-obj-y += tests/qtest/libqos/virtio-pci.o
-qos-test-obj-y += tests/qtest/libqos/virtio-pci-modern.o
-qos-test-obj-y += tests/qtest/libqos/virtio-rng.o
-qos-test-obj-y += tests/qtest/libqos/virtio-scsi.o
-qos-test-obj-y += tests/qtest/libqos/virtio-serial.o
+libqos-obj-y =  $(libqgraph-obj-y)
+libqos-obj-y += $(libqos-pc-obj-y) $(libqos-spapr-obj-y)
+libqos-obj-y += tests/qtest/libqos/e1000e.o
+libqos-obj-y += tests/qtest/libqos/i2c.o
+libqos-obj-y += tests/qtest/libqos/i2c-imx.o
+libqos-obj-y += tests/qtest/libqos/i2c-omap.o
+libqos-obj-y += tests/qtest/libqos/sdhci.o
+libqos-obj-y += tests/qtest/libqos/tpci200.o
+libqos-obj-y += tests/qtest/libqos/virtio.o
+libqos-obj-$(CONFIG_VIRTFS) += tests/qtest/libqos/virtio-9p.o
+libqos-obj-y += tests/qtest/libqos/virtio-balloon.o
+libqos-obj-y += tests/qtest/libqos/virtio-blk.o
+libqos-obj-y += tests/qtest/libqos/virtio-mmio.o
+libqos-obj-y += tests/qtest/libqos/virtio-net.o
+libqos-obj-y += tests/qtest/libqos/virtio-pci.o
+libqos-obj-y += tests/qtest/libqos/virtio-pci-modern.o
+libqos-obj-y += tests/qtest/libqos/virtio-rng.o
+libqos-obj-y += tests/qtest/libqos/virtio-scsi.o
+libqos-obj-y += tests/qtest/libqos/virtio-serial.o
 
 # qos machines:
-qos-test-obj-y += tests/qtest/libqos/aarch64-xlnx-zcu102-machine.o
-qos-test-obj-y += tests/qtest/libqos/arm-imx25-pdk-machine.o
-qos-test-obj-y += tests/qtest/libqos/arm-n800-machine.o
-qos-test-obj-y += tests/qtest/libqos/arm-raspi2-machine.o
-qos-test-obj-y += tests/qtest/libqos/arm-sabrelite-machine.o
-qos-test-obj-y += tests/qtest/libqos/arm-smdkc210-machine.o
-qos-test-obj-y += tests/qtest/libqos/arm-virt-machine.o
-qos-test-obj-y += tests/qtest/libqos/arm-xilinx-zynq-a9-machine.o
-qos-test-obj-y += tests/qtest/libqos/ppc64_pseries-machine.o
-qos-test-obj-y += tests/qtest/libqos/x86_64_pc-machine.o
+libqos-obj-y += tests/qtest/libqos/aarch64-xlnx-zcu102-machine.o
+libqos-obj-y += tests/qtest/libqos/arm-imx25-pdk-machine.o
+libqos-obj-y += tests/qtest/libqos/arm-n800-machine.o
+libqos-obj-y += tests/qtest/libqos/arm-raspi2-machine.o
+libqos-obj-y += tests/qtest/libqos/arm-sabrelite-machine.o
+libqos-obj-y += tests/qtest/libqos/arm-smdkc210-machine.o

[PULL 14/31] qtest: add qtest_server_send abstraction

2020-02-22 Thread Stefan Hajnoczi
From: Alexander Bulekov 

qtest_server_send is a function pointer specifying the handler used to
transmit data to the qtest client. In the standard configuration, this
calls the CharBackend handler, but now it is possible for other types of
handlers, e.g direct-function calls if the qtest client and server
exist within the same process (inproc)

Signed-off-by: Alexander Bulekov 
Reviewed-by: Stefan Hajnoczi 
Reviewed-by: Darren Kenny 
Acked-by: Thomas Huth 
Message-id: 20200220041118.23264-6-alx...@bu.edu
Signed-off-by: Stefan Hajnoczi 
---
 include/sysemu/qtest.h |  3 +++
 qtest.c| 18 --
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/include/sysemu/qtest.h b/include/sysemu/qtest.h
index 5ed09c80b1..e2f1047fd7 100644
--- a/include/sysemu/qtest.h
+++ b/include/sysemu/qtest.h
@@ -26,4 +26,7 @@ bool qtest_driver(void);
 
 void qtest_server_init(const char *qtest_chrdev, const char *qtest_log, Error 
**errp);
 
+void qtest_server_set_send_handler(void (*send)(void *, const char *),
+ void *opaque);
+
 #endif
diff --git a/qtest.c b/qtest.c
index 587dcbb4b5..8a4ba59828 100644
--- a/qtest.c
+++ b/qtest.c
@@ -43,6 +43,8 @@ static GString *inbuf;
 static int irq_levels[MAX_IRQ];
 static qemu_timeval start_time;
 static bool qtest_opened;
+static void (*qtest_server_send)(void*, const char*);
+static void *qtest_server_send_opaque;
 
 #define FMT_timeval "%ld.%06ld"
 
@@ -229,8 +231,10 @@ static void GCC_FMT_ATTR(1, 2) qtest_log_send(const char 
*fmt, ...)
 va_end(ap);
 }
 
-static void do_qtest_send(CharBackend *chr, const char *str, size_t len)
+static void qtest_server_char_be_send(void *opaque, const char *str)
 {
+size_t len = strlen(str);
+CharBackend* chr = (CharBackend *)opaque;
 qemu_chr_fe_write_all(chr, (uint8_t *)str, len);
 if (qtest_log_fp && qtest_opened) {
 fprintf(qtest_log_fp, "%s", str);
@@ -239,7 +243,7 @@ static void do_qtest_send(CharBackend *chr, const char 
*str, size_t len)
 
 static void qtest_send(CharBackend *chr, const char *str)
 {
-do_qtest_send(chr, str, strlen(str));
+qtest_server_send(qtest_server_send_opaque, str);
 }
 
 static void GCC_FMT_ATTR(2, 3) qtest_sendf(CharBackend *chr,
@@ -784,6 +788,16 @@ void qtest_server_init(const char *qtest_chrdev, const 
char *qtest_log, Error **
 qemu_chr_fe_set_echo(_chr, true);
 
 inbuf = g_string_new("");
+
+if (!qtest_server_send) {
+qtest_server_set_send_handler(qtest_server_char_be_send, _chr);
+}
+}
+
+void qtest_server_set_send_handler(void (*send)(void*, const char*), void 
*opaque)
+{
+qtest_server_send = send;
+qtest_server_send_opaque = opaque;
 }
 
 bool qtest_driver(void)
-- 
2.24.1



[PULL 12/31] module: check module wasn't already initialized

2020-02-22 Thread Stefan Hajnoczi
From: Alexander Bulekov 

The virtual-device fuzzer must initialize QOM, prior to running
vl:qemu_init, so that it can use the qos_graph to identify the arguments
required to initialize a guest for libqos-assisted fuzzing. This change
prevents errors when vl:qemu_init tries to (re)initialize the previously
initialized QOM module.

Signed-off-by: Alexander Bulekov 
Reviewed-by: Stefan Hajnoczi 
Reviewed-by: Darren Kenny 
Reviewed-by: Philippe Mathieu-Daudé 
Message-id: 20200220041118.23264-4-alx...@bu.edu
Signed-off-by: Stefan Hajnoczi 
---
 util/module.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/util/module.c b/util/module.c
index 8c5315a7a3..236a7bb52a 100644
--- a/util/module.c
+++ b/util/module.c
@@ -30,6 +30,7 @@ typedef struct ModuleEntry
 typedef QTAILQ_HEAD(, ModuleEntry) ModuleTypeList;
 
 static ModuleTypeList init_type_list[MODULE_INIT_MAX];
+static bool modules_init_done[MODULE_INIT_MAX];
 
 static ModuleTypeList dso_init_list;
 
@@ -91,11 +92,17 @@ void module_call_init(module_init_type type)
 ModuleTypeList *l;
 ModuleEntry *e;
 
+if (modules_init_done[type]) {
+return;
+}
+
 l = find_type(type);
 
 QTAILQ_FOREACH(e, l, node) {
 e->init();
 }
+
+modules_init_done[type] = true;
 }
 
 #ifdef CONFIG_MODULES
-- 
2.24.1



[PULL 03/31] rcu_queue: add QSLIST functions

2020-02-22 Thread Stefan Hajnoczi
From: Paolo Bonzini 

QSLIST is the only family of lists for which we do not have RCU-friendly 
accessors,
add them.

Signed-off-by: Paolo Bonzini 
Reviewed-by: Stefan Hajnoczi 
Message-id: 20200220103828.24525-1-pbonz...@redhat.com
Signed-off-by: Stefan Hajnoczi 
---
 include/qemu/queue.h | 15 +++--
 include/qemu/rcu_queue.h | 47 
 tests/Makefile.include   |  2 ++
 tests/test-rcu-list.c| 16 ++
 tests/test-rcu-slist.c   |  2 ++
 5 files changed, 80 insertions(+), 2 deletions(-)
 create mode 100644 tests/test-rcu-slist.c

diff --git a/include/qemu/queue.h b/include/qemu/queue.h
index 19425f973f..fcecb70228 100644
--- a/include/qemu/queue.h
+++ b/include/qemu/queue.h
@@ -211,9 +211,20 @@ struct {   
 \
 (head)->slh_first = (head)->slh_first->field.sle_next;  \
 } while (/*CONSTCOND*/0)
 
-#define QSLIST_REMOVE_AFTER(slistelm, field) do {\
+#define QSLIST_REMOVE_AFTER(slistelm, field) do {   \
 (slistelm)->field.sle_next =\
-QSLIST_NEXT(QSLIST_NEXT((slistelm), field), field);   \
+QSLIST_NEXT(QSLIST_NEXT((slistelm), field), field); \
+} while (/*CONSTCOND*/0)
+
+#define QSLIST_REMOVE(head, elm, type, field) do {  \
+if ((head)->slh_first == (elm)) {   \
+QSLIST_REMOVE_HEAD((head), field);  \
+} else {\
+struct type *curelm = (head)->slh_first;\
+while (curelm->field.sle_next != (elm)) \
+curelm = curelm->field.sle_next;\
+curelm->field.sle_next = curelm->field.sle_next->field.sle_next; \
+}   \
 } while (/*CONSTCOND*/0)
 
 #define QSLIST_FOREACH(var, head, field) \
diff --git a/include/qemu/rcu_queue.h b/include/qemu/rcu_queue.h
index 2d386f303e..558961cc27 100644
--- a/include/qemu/rcu_queue.h
+++ b/include/qemu/rcu_queue.h
@@ -262,6 +262,53 @@ extern "C" {
  (var) && ((next) = atomic_rcu_read(&(var)->field.tqe_next), 1); \
  (var) = (next))
 
+/*
+ * RCU singly-linked list
+ */
+
+/* Singly-linked list access methods */
+#define QSLIST_EMPTY_RCU(head)  (atomic_read(&(head)->slh_first) == NULL)
+#define QSLIST_FIRST_RCU(head)   atomic_rcu_read(&(head)->slh_first)
+#define QSLIST_NEXT_RCU(elm, field)  atomic_rcu_read(&(elm)->field.sle_next)
+
+/* Singly-linked list functions */
+#define QSLIST_INSERT_HEAD_RCU(head, elm, field) do {   \
+(elm)->field.sle_next = (head)->slh_first;  \
+atomic_rcu_set(&(head)->slh_first, (elm));  \
+} while (/*CONSTCOND*/0)
+
+#define QSLIST_INSERT_AFTER_RCU(head, listelm, elm, field) do { \
+(elm)->field.sle_next = (listelm)->field.sle_next;  \
+atomic_rcu_set(&(listelm)->field.sle_next, (elm));  \
+} while (/*CONSTCOND*/0)
+
+#define QSLIST_REMOVE_HEAD_RCU(head, field) do {   \
+atomic_set(&(head)->slh_first, (head)->slh_first->field.sle_next); \
+} while (/*CONSTCOND*/0)
+
+#define QSLIST_REMOVE_RCU(head, elm, type, field) do {  \
+if ((head)->slh_first == (elm)) {   \
+QSLIST_REMOVE_HEAD_RCU((head), field);  \
+} else {\
+struct type *curr = (head)->slh_first;  \
+while (curr->field.sle_next != (elm)) { \
+curr = curr->field.sle_next;\
+}   \
+atomic_set(>field.sle_next,   \
+   curr->field.sle_next->field.sle_next);   \
+}   \
+} while (/*CONSTCOND*/0)
+
+#define QSLIST_FOREACH_RCU(var, head, field)  \
+for ((var) = atomic_rcu_read(&(head)->slh_first);   \
+ (var); \
+ (var) = atomic_rcu_read(&(var)->field.sle_next))
+
+#define QSLIST_FOREACH_SAFE_RCU(var, head, field, next)\
+for ((var) = atomic_rcu_read(&(head)->slh_first);\
+ (var) && ((next) = atomic_rcu_read(&(var)->field.sle_next), 1); \
+ (var) = (next))
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 2f1cafed72..edcbd475aa 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -98,6 +98,7 @@ check-unit-y += 

[PULL 08/31] aio-posix: make AioHandler deletion O(1)

2020-02-22 Thread Stefan Hajnoczi
It is not necessary to scan all AioHandlers for deletion.  Keep a list
of deleted handlers instead of scanning the full list of all handlers.

The AioHandler->deleted field can be dropped.  Let's check if the
handler has been inserted into the deleted list instead.  Add a new
QLIST_IS_INSERTED() API for this check.

Signed-off-by: Stefan Hajnoczi 
Reviewed-by: Sergio Lopez 
Message-id: 20200214171712.541358-5-stefa...@redhat.com
Signed-off-by: Stefan Hajnoczi 
---
 include/block/aio.h  |  6 -
 include/qemu/queue.h |  3 +++
 util/aio-posix.c | 53 +---
 3 files changed, 43 insertions(+), 19 deletions(-)

diff --git a/include/block/aio.h b/include/block/aio.h
index 1a2ce9ca26..9dd61cee7e 100644
--- a/include/block/aio.h
+++ b/include/block/aio.h
@@ -42,6 +42,7 @@ void qemu_aio_unref(void *p);
 void qemu_aio_ref(void *p);
 
 typedef struct AioHandler AioHandler;
+typedef QLIST_HEAD(, AioHandler) AioHandlerList;
 typedef void QEMUBHFunc(void *opaque);
 typedef bool AioPollFn(void *opaque);
 typedef void IOHandler(void *opaque);
@@ -71,7 +72,10 @@ struct AioContext {
 QemuRecMutex lock;
 
 /* The list of registered AIO handlers.  Protected by ctx->list_lock. */
-QLIST_HEAD(, AioHandler) aio_handlers;
+AioHandlerList aio_handlers;
+
+/* The list of AIO handlers to be deleted.  Protected by ctx->list_lock. */
+AioHandlerList deleted_aio_handlers;
 
 /* Used to avoid unnecessary event_notifier_set calls in aio_notify;
  * accessed with atomic primitives.  If this field is 0, everything
diff --git a/include/qemu/queue.h b/include/qemu/queue.h
index 60e794a4e3..294db54eb1 100644
--- a/include/qemu/queue.h
+++ b/include/qemu/queue.h
@@ -158,6 +158,9 @@ struct {
\
 }   \
 } while (/*CONSTCOND*/0)
 
+/* Is elm in a list? */
+#define QLIST_IS_INSERTED(elm, field) ((elm)->field.le_prev != NULL)
+
 #define QLIST_FOREACH(var, head, field) \
 for ((var) = ((head)->lh_first);\
 (var);  \
diff --git a/util/aio-posix.c b/util/aio-posix.c
index 58765e581e..b5cfdbd2f6 100644
--- a/util/aio-posix.c
+++ b/util/aio-posix.c
@@ -32,10 +32,10 @@ struct AioHandler
 AioPollFn *io_poll;
 IOHandler *io_poll_begin;
 IOHandler *io_poll_end;
-int deleted;
 void *opaque;
 bool is_external;
 QLIST_ENTRY(AioHandler) node;
+QLIST_ENTRY(AioHandler) node_deleted;
 };
 
 #ifdef CONFIG_EPOLL_CREATE1
@@ -68,7 +68,7 @@ static bool aio_epoll_try_enable(AioContext *ctx)
 
 QLIST_FOREACH_RCU(node, >aio_handlers, node) {
 int r;
-if (node->deleted || !node->pfd.events) {
+if (QLIST_IS_INSERTED(node, node_deleted) || !node->pfd.events) {
 continue;
 }
 event.events = epoll_events_from_pfd(node->pfd.events);
@@ -196,9 +196,11 @@ static AioHandler *find_aio_handler(AioContext *ctx, int 
fd)
 AioHandler *node;
 
 QLIST_FOREACH(node, >aio_handlers, node) {
-if (node->pfd.fd == fd)
-if (!node->deleted)
+if (node->pfd.fd == fd) {
+if (!QLIST_IS_INSERTED(node, node_deleted)) {
 return node;
+}
+}
 }
 
 return NULL;
@@ -217,7 +219,7 @@ static bool aio_remove_fd_handler(AioContext *ctx, 
AioHandler *node)
 
 /* If a read is in progress, just mark the node as deleted */
 if (qemu_lockcnt_count(>list_lock)) {
-node->deleted = 1;
+QLIST_INSERT_HEAD_RCU(>deleted_aio_handlers, node, node_deleted);
 node->pfd.revents = 0;
 return false;
 }
@@ -359,7 +361,7 @@ static void poll_set_started(AioContext *ctx, bool started)
 QLIST_FOREACH_RCU(node, >aio_handlers, node) {
 IOHandler *fn;
 
-if (node->deleted) {
+if (QLIST_IS_INSERTED(node, node_deleted)) {
 continue;
 }
 
@@ -416,6 +418,26 @@ bool aio_pending(AioContext *ctx)
 return result;
 }
 
+static void aio_free_deleted_handlers(AioContext *ctx)
+{
+AioHandler *node;
+
+if (QLIST_EMPTY_RCU(>deleted_aio_handlers)) {
+return;
+}
+if (!qemu_lockcnt_dec_if_lock(>list_lock)) {
+return; /* we are nested, let the parent do the freeing */
+}
+
+while ((node = QLIST_FIRST_RCU(>deleted_aio_handlers))) {
+QLIST_REMOVE(node, node);
+QLIST_REMOVE(node, node_deleted);
+g_free(node);
+}
+
+qemu_lockcnt_inc_and_unlock(>list_lock);
+}
+
 static bool aio_dispatch_handlers(AioContext *ctx)
 {
 AioHandler *node, *tmp;
@@ -427,7 +449,7 @@ static bool aio_dispatch_handlers(AioContext *ctx)
 revents = node->pfd.revents & node->pfd.events;
 node->pfd.revents = 0;
 
-if (!node->deleted &&
+if (!QLIST_IS_INSERTED(node, 

[PULL 10/31] softmmu: move vl.c to softmmu/

2020-02-22 Thread Stefan Hajnoczi
From: Alexander Bulekov 

Move vl.c to a separate directory, similar to linux-user/
Update the chechpatch and get_maintainer scripts, since they relied on
/vl.c for top_of_tree checks.

Signed-off-by: Alexander Bulekov 
Reviewed-by: Darren Kenny 
Message-id: 20200220041118.23264-2-alx...@bu.edu
Signed-off-by: Stefan Hajnoczi 
---
 MAINTAINERS   | 2 +-
 Makefile.objs | 2 --
 Makefile.target   | 1 +
 scripts/checkpatch.pl | 2 +-
 scripts/get_maintainer.pl | 3 ++-
 softmmu/Makefile.objs | 2 ++
 vl.c => softmmu/vl.c  | 0
 7 files changed, 7 insertions(+), 5 deletions(-)
 create mode 100644 softmmu/Makefile.objs
 rename vl.c => softmmu/vl.c (100%)

diff --git a/MAINTAINERS b/MAINTAINERS
index 1740a4fddc..6e26d2ec2a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2031,7 +2031,7 @@ F: include/qemu/main-loop.h
 F: include/sysemu/runstate.h
 F: util/main-loop.c
 F: util/qemu-timer.c
-F: vl.c
+F: softmmu/vl.c
 F: qapi/run-state.json
 
 Human Monitor (HMP)
diff --git a/Makefile.objs b/Makefile.objs
index 26b9cff954..8a1cbe8000 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -58,8 +58,6 @@ common-obj-y += ui/
 common-obj-m += ui/
 
 common-obj-y += dma-helpers.o
-common-obj-y += vl.o
-vl.o-cflags := $(GPROF_CFLAGS) $(SDL_CFLAGS)
 common-obj-$(CONFIG_TPM) += tpm.o
 
 common-obj-y += backends/
diff --git a/Makefile.target b/Makefile.target
index 6e61f607b1..06c36d1161 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -160,6 +160,7 @@ obj-y += qapi/
 obj-y += memory.o
 obj-y += memory_mapping.o
 obj-y += migration/ram.o
+obj-y += softmmu/
 LIBS := $(libs_softmmu) $(LIBS)
 
 # Hardware support
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 11512a8a09..b27e4ff5e9 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -462,7 +462,7 @@ sub top_of_kernel_tree {
my @tree_check = (
"COPYING", "MAINTAINERS", "Makefile",
"README.rst", "docs", "VERSION",
-   "vl.c"
+   "linux-user", "softmmu"
);
 
foreach my $check (@tree_check) {
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
index 27991eb1cf..271f5ff42a 100755
--- a/scripts/get_maintainer.pl
+++ b/scripts/get_maintainer.pl
@@ -795,7 +795,8 @@ sub top_of_tree {
 && (-f "${lk_path}Makefile")
 && (-d "${lk_path}docs")
 && (-f "${lk_path}VERSION")
-&& (-f "${lk_path}vl.c")) {
+&& (-d "${lk_path}linux-user/")
+&& (-d "${lk_path}softmmu/")) {
return 1;
 }
 return 0;
diff --git a/softmmu/Makefile.objs b/softmmu/Makefile.objs
new file mode 100644
index 00..d80a5ffe5a
--- /dev/null
+++ b/softmmu/Makefile.objs
@@ -0,0 +1,2 @@
+obj-y += vl.o
+vl.o-cflags := $(GPROF_CFLAGS) $(SDL_CFLAGS)
diff --git a/vl.c b/softmmu/vl.c
similarity index 100%
rename from vl.c
rename to softmmu/vl.c
-- 
2.24.1



[PULL 06/31] aio-posix: don't pass ns timeout to epoll_wait()

2020-02-22 Thread Stefan Hajnoczi
Don't pass the nanosecond timeout into epoll_wait(), which expects
milliseconds.

The epoll_wait() timeout value does not matter if qemu_poll_ns()
determined that the poll fd is ready, but passing a value in the wrong
units is still ugly.  Pass a 0 timeout to epoll_wait() instead.

Signed-off-by: Stefan Hajnoczi 
Reviewed-by: Sergio Lopez 
Message-id: 20200214171712.541358-3-stefa...@redhat.com
Signed-off-by: Stefan Hajnoczi 
---
 util/aio-posix.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/util/aio-posix.c b/util/aio-posix.c
index c964627a03..58765e581e 100644
--- a/util/aio-posix.c
+++ b/util/aio-posix.c
@@ -117,6 +117,9 @@ static int aio_epoll(AioContext *ctx, int64_t timeout)
 
 if (timeout > 0) {
 ret = qemu_poll_ns(, 1, timeout);
+if (ret > 0) {
+timeout = 0;
+}
 }
 if (timeout <= 0 || ret > 0) {
 ret = epoll_wait(ctx->epollfd, events,
-- 
2.24.1



[PULL 00/31] Block patches

2020-02-22 Thread Stefan Hajnoczi
The following changes since commit 9ac5df20f51fabcba0d902025df4bd7ea987c158:

  Merge remote-tracking branch 
'remotes/pmaydell/tags/pull-target-arm-20200221-1' into staging (2020-02-21 
16:18:38 +)

are available in the Git repository at:

  https://github.com/stefanha/qemu.git tags/block-pull-request

for you to fetch changes up to e5c59355ae9f724777c61c859292ec9db2c8c2ab:

  fuzz: add documentation to docs/devel/ (2020-02-22 08:26:48 +)


Pull request

This pull request contains a virtio-blk/scsi performance optimization, event
loop scalability improvements, and a qtest-based device fuzzing framework.  I
am including the fuzzing patches because I have reviewed them and Thomas Huth
is currently away on leave.



Alexander Bulekov (22):
  softmmu: move vl.c to softmmu/
  softmmu: split off vl.c:main() into main.c
  module: check module wasn't already initialized
  fuzz: add FUZZ_TARGET module type
  qtest: add qtest_server_send abstraction
  libqtest: add a layer of abstraction to send/recv
  libqtest: make bufwrite rely on the TransportOps
  qtest: add in-process incoming command handler
  libqos: rename i2c_send and i2c_recv
  libqos: split qos-test and libqos makefile vars
  libqos: move useful qos-test funcs to qos_external
  fuzz: add fuzzer skeleton
  exec: keep ram block across fork when using qtest
  main: keep rcu_atfork callback enabled for qtest
  fuzz: support for fork-based fuzzing.
  fuzz: add support for qos-assisted fuzz targets
  fuzz: add target/fuzz makefile rules
  fuzz: add configure flag --enable-fuzzing
  fuzz: add i440fx fuzz targets
  fuzz: add virtio-net fuzz target
  fuzz: add virtio-scsi fuzz target
  fuzz: add documentation to docs/devel/

Denis Plotnikov (1):
  virtio: increase virtqueue size for virtio-scsi and virtio-blk

Paolo Bonzini (1):
  rcu_queue: add QSLIST functions

Stefan Hajnoczi (7):
  aio-posix: avoid reacquiring rcu_read_lock() when polling
  util/async: make bh_aio_poll() O(1)
  aio-posix: fix use after leaving scope in aio_poll()
  aio-posix: don't pass ns timeout to epoll_wait()
  qemu/queue.h: add QLIST_SAFE_REMOVE()
  aio-posix: make AioHandler deletion O(1)
  aio-posix: make AioHandler dispatch O(1) with epoll

 MAINTAINERS |  11 +-
 Makefile|  15 +-
 Makefile.objs   |   2 -
 Makefile.target |  19 ++-
 block.c |   5 +-
 chardev/spice.c |   4 +-
 configure   |  39 +
 docs/devel/fuzzing.txt  | 116 ++
 exec.c  |  12 +-
 hw/block/virtio-blk.c   |   2 +-
 hw/core/machine.c   |   2 +
 hw/scsi/virtio-scsi.c   |   2 +-
 include/block/aio.h |  26 ++-
 include/qemu/module.h   |   4 +-
 include/qemu/queue.h|  32 +++-
 include/qemu/rcu_queue.h|  47 ++
 include/sysemu/qtest.h  |   4 +
 include/sysemu/sysemu.h |   4 +
 qtest.c |  31 +++-
 scripts/checkpatch.pl   |   2 +-
 scripts/get_maintainer.pl   |   3 +-
 softmmu/Makefile.objs   |   3 +
 softmmu/main.c  |  53 +++
 vl.c => softmmu/vl.c|  48 +++---
 tests/Makefile.include  |   2 +
 tests/qtest/Makefile.include|  72 +
 tests/qtest/fuzz/Makefile.include   |  18 +++
 tests/qtest/fuzz/fork_fuzz.c|  55 +++
 tests/qtest/fuzz/fork_fuzz.h|  23 +++
 tests/qtest/fuzz/fork_fuzz.ld   |  37 +
 tests/qtest/fuzz/fuzz.c | 179 +
 tests/qtest/fuzz/fuzz.h |  95 +++
 tests/qtest/fuzz/i440fx_fuzz.c  | 193 ++
 tests/qtest/fuzz/qos_fuzz.c | 234 +++
 tests/qtest/fuzz/qos_fuzz.h |  33 
 tests/qtest/fuzz/virtio_net_fuzz.c  | 198 +++
 tests/qtest/fuzz/virtio_scsi_fuzz.c | 213 +
 tests/qtest/libqos/i2c.c|  10 +-
 tests/qtest/libqos/i2c.h|   4 +-
 tests/qtest/libqos/qos_external.c   | 168 
 tests/qtest/libqos/qos_external.h   |  28 
 tests/qtest/libqtest.c  | 119 --
 tests/qtest/libqtest.h  |   4 +
 tests/qtest/pca9552-test.c  |  10 +-
 tests/qtest/qos-test.c  | 132 +---
 tests/test-aio.c|   3 +-
 tests/test-rcu-list.c   |  16 ++
 tests/test-rcu-slist.c  |   2 +
 util/aio-posix.c| 187 +++---
 util/async.c| 237 
 util/module.c   |   7 +
 51 files changed, 2365 insertions(+), 400 deletions(-)
 

[PULL 01/31] virtio: increase virtqueue size for virtio-scsi and virtio-blk

2020-02-22 Thread Stefan Hajnoczi
From: Denis Plotnikov 

The goal is to reduce the amount of requests issued by a guest on
1M reads/writes. This rises the performance up to 4% on that kind of
disk access pattern.

The maximum chunk size to be used for the guest disk accessing is
limited with seg_max parameter, which represents the max amount of
pices in the scatter-geather list in one guest disk request.

Since seg_max is virqueue_size dependent, increasing the virtqueue
size increases seg_max, which, in turn, increases the maximum size
of data to be read/write from a guest disk.

More details in the original problem statment:
https://lists.gnu.org/archive/html/qemu-devel/2017-12/msg03721.html

Suggested-by: Denis V. Lunev 
Signed-off-by: Denis Plotnikov 
Message-id: 20200214074648.958-1-dplotni...@virtuozzo.com
Signed-off-by: Stefan Hajnoczi 
---
 hw/block/virtio-blk.c | 2 +-
 hw/core/machine.c | 2 ++
 hw/scsi/virtio-scsi.c | 2 +-
 3 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index 09f46ed85f..142863a3b2 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -1272,7 +1272,7 @@ static Property virtio_blk_properties[] = {
 DEFINE_PROP_BIT("request-merging", VirtIOBlock, conf.request_merging, 0,
 true),
 DEFINE_PROP_UINT16("num-queues", VirtIOBlock, conf.num_queues, 1),
-DEFINE_PROP_UINT16("queue-size", VirtIOBlock, conf.queue_size, 128),
+DEFINE_PROP_UINT16("queue-size", VirtIOBlock, conf.queue_size, 256),
 DEFINE_PROP_BOOL("seg-max-adjust", VirtIOBlock, conf.seg_max_adjust, true),
 DEFINE_PROP_LINK("iothread", VirtIOBlock, conf.iothread, TYPE_IOTHREAD,
  IOThread *),
diff --git a/hw/core/machine.c b/hw/core/machine.c
index 84812a1d1c..ce403ccea9 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -28,6 +28,8 @@
 #include "hw/mem/nvdimm.h"
 
 GlobalProperty hw_compat_4_2[] = {
+{ "virtio-blk-device", "queue-size", "128"},
+{ "virtio-scsi-device", "virtqueue_size", "128"},
 { "virtio-blk-device", "x-enable-wce-if-config-wce", "off" },
 { "virtio-blk-device", "seg-max-adjust", "off"},
 { "virtio-scsi-device", "seg_max_adjust", "off"},
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 3b61563609..472bbd233b 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -965,7 +965,7 @@ static void virtio_scsi_device_unrealize(DeviceState *dev, 
Error **errp)
 static Property virtio_scsi_properties[] = {
 DEFINE_PROP_UINT32("num_queues", VirtIOSCSI, parent_obj.conf.num_queues, 
1),
 DEFINE_PROP_UINT32("virtqueue_size", VirtIOSCSI,
- parent_obj.conf.virtqueue_size, 128),
+ parent_obj.conf.virtqueue_size, 256),
 DEFINE_PROP_BOOL("seg_max_adjust", VirtIOSCSI,
   parent_obj.conf.seg_max_adjust, true),
 DEFINE_PROP_UINT32("max_sectors", VirtIOSCSI, parent_obj.conf.max_sectors,
-- 
2.24.1



[PULL 04/31] util/async: make bh_aio_poll() O(1)

2020-02-22 Thread Stefan Hajnoczi
The ctx->first_bh list contains all created BHs, including those that
are not scheduled.  The list is iterated by the event loop and therefore
has O(n) time complexity with respected to the number of created BHs.

Rewrite BHs so that only scheduled or deleted BHs are enqueued.
Only BHs that actually require action will be iterated.

One semantic change is required: qemu_bh_delete() enqueues the BH and
therefore invokes aio_notify().  The
tests/test-aio.c:test_source_bh_delete_from_cb() test case assumed that
g_main_context_iteration(NULL, false) returns false after
qemu_bh_delete() but it now returns true for one iteration.  Fix up the
test case.

This patch makes aio_compute_timeout() and aio_bh_poll() drop from a CPU
profile reported by perf-top(1).  Previously they combined to 9% CPU
utilization when AioContext polling is commented out and the guest has 2
virtio-blk,num-queues=1 and 99 virtio-blk,num-queues=32 devices.

Signed-off-by: Stefan Hajnoczi 
Reviewed-by: Paolo Bonzini 
Message-id: 20200221093951.1414693-1-stefa...@redhat.com
Signed-off-by: Stefan Hajnoczi 
---
 include/block/aio.h |  20 +++-
 tests/test-aio.c|   3 +-
 util/async.c| 237 ++--
 3 files changed, 158 insertions(+), 102 deletions(-)

diff --git a/include/block/aio.h b/include/block/aio.h
index 7ba9bd7874..1a2ce9ca26 100644
--- a/include/block/aio.h
+++ b/include/block/aio.h
@@ -51,6 +51,19 @@ struct ThreadPool;
 struct LinuxAioState;
 struct LuringState;
 
+/*
+ * Each aio_bh_poll() call carves off a slice of the BH list, so that newly
+ * scheduled BHs are not processed until the next aio_bh_poll() call.  All
+ * active aio_bh_poll() calls chain their slices together in a list, so that
+ * nested aio_bh_poll() calls process all scheduled bottom halves.
+ */
+typedef QSLIST_HEAD(, QEMUBH) BHList;
+typedef struct BHListSlice BHListSlice;
+struct BHListSlice {
+BHList bh_list;
+QSIMPLEQ_ENTRY(BHListSlice) next;
+};
+
 struct AioContext {
 GSource source;
 
@@ -91,8 +104,11 @@ struct AioContext {
  */
 QemuLockCnt list_lock;
 
-/* Anchor of the list of Bottom Halves belonging to the context */
-struct QEMUBH *first_bh;
+/* Bottom Halves pending aio_bh_poll() processing */
+BHList bh_list;
+
+/* Chained BH list slices for each nested aio_bh_poll() call */
+QSIMPLEQ_HEAD(, BHListSlice) bh_slice_list;
 
 /* Used by aio_notify.
  *
diff --git a/tests/test-aio.c b/tests/test-aio.c
index 86fb73b3d5..8a46078463 100644
--- a/tests/test-aio.c
+++ b/tests/test-aio.c
@@ -615,7 +615,8 @@ static void test_source_bh_delete_from_cb(void)
 g_assert_cmpint(data1.n, ==, data1.max);
 g_assert(data1.bh == NULL);
 
-g_assert(!g_main_context_iteration(NULL, false));
+assert(g_main_context_iteration(NULL, false));
+assert(!g_main_context_iteration(NULL, false));
 }
 
 static void test_source_bh_delete_from_cb_many(void)
diff --git a/util/async.c b/util/async.c
index c192a24a61..b94518b948 100644
--- a/util/async.c
+++ b/util/async.c
@@ -29,6 +29,7 @@
 #include "block/thread-pool.h"
 #include "qemu/main-loop.h"
 #include "qemu/atomic.h"
+#include "qemu/rcu_queue.h"
 #include "block/raw-aio.h"
 #include "qemu/coroutine_int.h"
 #include "trace.h"
@@ -36,16 +37,76 @@
 /***/
 /* bottom halves (can be seen as timers which expire ASAP) */
 
+/* QEMUBH::flags values */
+enum {
+/* Already enqueued and waiting for aio_bh_poll() */
+BH_PENDING   = (1 << 0),
+
+/* Invoke the callback */
+BH_SCHEDULED = (1 << 1),
+
+/* Delete without invoking callback */
+BH_DELETED   = (1 << 2),
+
+/* Delete after invoking callback */
+BH_ONESHOT   = (1 << 3),
+
+/* Schedule periodically when the event loop is idle */
+BH_IDLE  = (1 << 4),
+};
+
 struct QEMUBH {
 AioContext *ctx;
 QEMUBHFunc *cb;
 void *opaque;
-QEMUBH *next;
-bool scheduled;
-bool idle;
-bool deleted;
+QSLIST_ENTRY(QEMUBH) next;
+unsigned flags;
 };
 
+/* Called concurrently from any thread */
+static void aio_bh_enqueue(QEMUBH *bh, unsigned new_flags)
+{
+AioContext *ctx = bh->ctx;
+unsigned old_flags;
+
+/*
+ * The memory barrier implicit in atomic_fetch_or makes sure that:
+ * 1. idle & any writes needed by the callback are done before the
+ *locations are read in the aio_bh_poll.
+ * 2. ctx is loaded before the callback has a chance to execute and bh
+ *could be freed.
+ */
+old_flags = atomic_fetch_or(>flags, BH_PENDING | new_flags);
+if (!(old_flags & BH_PENDING)) {
+QSLIST_INSERT_HEAD_ATOMIC(>bh_list, bh, next);
+}
+
+aio_notify(ctx);
+}
+
+/* Only called from aio_bh_poll() and aio_ctx_finalize() */
+static QEMUBH *aio_bh_dequeue(BHList *head, unsigned *flags)
+{
+QEMUBH *bh = QSLIST_FIRST_RCU(head);
+
+if (!bh) {
+return NULL;
+}
+
+QSLIST_REMOVE_HEAD(head, next);

[PULL 02/31] aio-posix: avoid reacquiring rcu_read_lock() when polling

2020-02-22 Thread Stefan Hajnoczi
The first rcu_read_lock/unlock() is expensive.  Nested calls are cheap.

This optimization increases IOPS from 73k to 162k with a Linux guest
that has 2 virtio-blk,num-queues=1 and 99 virtio-blk,num-queues=32
devices.

Signed-off-by: Stefan Hajnoczi 
Reviewed-by: Paolo Bonzini 
Message-id: 20200218182708.914552-1-stefa...@redhat.com
Signed-off-by: Stefan Hajnoczi 
---
 util/aio-posix.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/util/aio-posix.c b/util/aio-posix.c
index a4977f538e..f67f5b34e9 100644
--- a/util/aio-posix.c
+++ b/util/aio-posix.c
@@ -15,6 +15,7 @@
 
 #include "qemu/osdep.h"
 #include "block/block.h"
+#include "qemu/rcu.h"
 #include "qemu/rcu_queue.h"
 #include "qemu/sockets.h"
 #include "qemu/cutils.h"
@@ -514,6 +515,16 @@ static bool run_poll_handlers_once(AioContext *ctx, 
int64_t *timeout)
 bool progress = false;
 AioHandler *node;
 
+/*
+ * Optimization: ->io_poll() handlers often contain RCU read critical
+ * sections and we therefore see many rcu_read_lock() -> rcu_read_unlock()
+ * -> rcu_read_lock() -> ... sequences with expensive memory
+ * synchronization primitives.  Make the entire polling loop an RCU
+ * critical section because nested rcu_read_lock()/rcu_read_unlock() calls
+ * are cheap.
+ */
+RCU_READ_LOCK_GUARD();
+
 QLIST_FOREACH_RCU(node, >aio_handlers, node) {
 if (!node->deleted && node->io_poll &&
 aio_node_check(ctx, node->is_external) &&
-- 
2.24.1



Re: [PATCH v7 01/11] qapi/error: add (Error **errp) cleaning APIs

2020-02-22 Thread Markus Armbruster
Vladimir Sementsov-Ogievskiy  writes:

> 21.02.2020 19:34, Markus Armbruster wrote:
>> Vladimir Sementsov-Ogievskiy  writes:
>>
>>> 21.02.2020 10:38, Markus Armbruster wrote:
 Vladimir Sementsov-Ogievskiy  writes:

> Add functions to clean Error **errp: call corresponding Error *err
> cleaning function an set pointer to NULL.
>
> New functions:
> error_free_errp
> error_report_errp
> warn_report_errp
>
> Signed-off-by: Vladimir Sementsov-Ogievskiy 
> Reviewed-by: Greg Kurz 
> Reviewed-by: Eric Blake 
> ---
>
> CC: Eric Blake 
> CC: Kevin Wolf 
> CC: Max Reitz 
> CC: Greg Kurz 
> CC: Stefano Stabellini 
> CC: Anthony Perard 
> CC: Paul Durrant 
> CC: Stefan Hajnoczi 
> CC: "Philippe Mathieu-Daudé" 
> CC: Laszlo Ersek 
> CC: Gerd Hoffmann 
> CC: Stefan Berger 
> CC: Markus Armbruster 
> CC: Michael Roth 
> CC: qemu-bl...@nongnu.org
> CC: xen-de...@lists.xenproject.org
>
>include/qapi/error.h | 26 ++
>1 file changed, 26 insertions(+)
>
> diff --git a/include/qapi/error.h b/include/qapi/error.h
> index ad5b6e896d..d34987148d 100644
> --- a/include/qapi/error.h
> +++ b/include/qapi/error.h
> @@ -309,6 +309,32 @@ void warn_reportf_err(Error *err, const char *fmt, 
> ...)
>void error_reportf_err(Error *err, const char *fmt, ...)
>GCC_FMT_ATTR(2, 3);
>+/*
> + * Functions to clean Error **errp: call corresponding Error *err 
> cleaning
> + * function, then set pointer to NULL.
> + */
> +static inline void error_free_errp(Error **errp)
> +{
> +assert(errp && *errp);
> +error_free(*errp);
> +*errp = NULL;
> +}
> +
> +static inline void error_report_errp(Error **errp)
> +{
> +assert(errp && *errp);
> +error_report_err(*errp);
> +*errp = NULL;
> +}
> +
> +static inline void warn_report_errp(Error **errp)
> +{
> +assert(errp && *errp);
> +warn_report_err(*errp);
> +*errp = NULL;
> +}
> +
> +
>/*
> * Just like error_setg(), except you get to specify the error class.
> * Note: use of error classes other than ERROR_CLASS_GENERIC_ERROR is

 These appear to be unused apart from the Coccinelle script in PATCH 03.

 They are used in the full "[RFC v5 000/126] error: auto propagated
 local_err" series.  Options:

 1. Pick a few more patches into this part I series, so these guys come
  with users.
>>>
>>> It needs some additional effort for this series.. But it's possible. Still,
>>> I think that we at least should not pull out patches which should be in
>>> future series (for example from ppc or block/)..
>>
>> Yes, we want to keep related stuff together.
>>
>>> Grepping through v5:
>>>   for x in {warn_report_errp,error_report_errp,error_free_errp}; do echo == 
>>> $x ==; git grep -l $x | grep -v coccinelle | grep -v 'error\.h'; echo; done
>>> == warn_report_errp ==
>>> block/file-posix.c
>>> hw/ppc/spapr.c
>>> hw/ppc/spapr_caps.c
>>> hw/ppc/spapr_irq.c
>>> hw/vfio/pci.c
>>> net/tap.c
>>> qom/object.c
>>>
>>> == error_report_errp ==
>>> hw/block/vhost-user-blk.c
>>> util/oslib-posix.c
>>>
>>> == error_free_errp ==
>>> block.c
>>> block/qapi.c
>>> block/sheepdog.c
>>> block/snapshot.c
>>> blockdev.c
>>> chardev/char-socket.c
>>> hw/audio/intel-hda.c
>>> hw/core/qdev-properties.c
>>> hw/pci-bridge/pci_bridge_dev.c
>>> hw/pci-bridge/pcie_pci_bridge.c
>>> hw/scsi/megasas.c
>>> hw/scsi/mptsas.c
>>> hw/usb/hcd-xhci.c
>>> io/net-listener.c
>>> migration/colo.c
>>> qga/commands-posix.c
>>> qga/commands-win32.c
>>> util/qemu-sockets.c
>>>
>>> What do you want to add?
>>
>> PATCH v5 032 uses both error_report_errp() and error_free_errp().
>> Adding warn_report_errp() without a user is okay with me.  What do you
>> think?
>>
>> If there are patches you consider related to 032, feel free to throw
>> them in.
>
> 032 is qga/commands-win32.c and util/oslib-posix.c
>
> Seems that they are wrongly grouped into one patch.
>
> qga/commands-win32.c matches qga/ (Michael Roth)
> and  util/oslib-posix.c matches POSIX (Paolo Bonzini)
>
> So, it should be two separate patches anyway.
>
> For [1.] I only afraid that we'll have to wait for maintainers, who were
> not interested in previous iterations, to review these new patches..

We won't.

We should and we will give every maintainer a chance to review these
patches, even though the changes are mechanical.  Maintainers are free
to decline or ignore this offer.  I will feel free to interpret that as
"go ahead and merge this through your tree".

In fact, I fully expect the bulk of the changes to go through my tree.
Chasing umpteen maintainers for each one to merge a trivial part of this
massive tree-wide change would take ages and accomplish nothing.

[...]




Re: [RFC v3.1 00/22] intel_iommu: expose Shared Virtual Addressing to VMs

2020-02-22 Thread no-reply
Patchew URL: 
https://patchew.org/QEMU/1582358843-51931-1-git-send-email-yi.l@intel.com/



Hi,

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

=== TEST SCRIPT BEGIN ===
#! /bin/bash
export ARCH=x86_64
make docker-image-fedora V=1 NETWORK=1
time make docker-test-mingw@fedora J=14 NETWORK=1
=== TEST SCRIPT END ===

 from /tmp/qemu-test/src/include/hw/pci/pci_bus.h:4,
 from /tmp/qemu-test/src/include/hw/pci-host/i440fx.h:15,
 from /tmp/qemu-test/src/stubs/pci-host-piix.c:2:
/tmp/qemu-test/src/include/hw/iommu/host_iommu_context.h:26:10: fatal error: 
linux/iommu.h: No such file or directory
 #include 
  ^~~
compilation terminated.
make: *** [/tmp/qemu-test/src/rules.mak:69: stubs/pci-host-piix.o] Error 1
make: *** Waiting for unfinished jobs
Traceback (most recent call last):
  File "./tests/docker/docker.py", line 664, in 
---
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['sudo', '-n', 'docker', 'run', 
'--label', 'com.qemu.instance.uuid=797be2e5d6284df8a28232368d5ea704', '-u', 
'1003', '--security-opt', 'seccomp=unconfined', '--rm', '-e', 'TARGET_LIST=', 
'-e', 'EXTRA_CONFIGURE_OPTS=', '-e', 'V=', '-e', 'J=14', '-e', 'DEBUG=', '-e', 
'SHOW_ENV=', '-e', 'CCACHE_DIR=/var/tmp/ccache', '-v', 
'/home/patchew2/.cache/qemu-docker-ccache:/var/tmp/ccache:z', '-v', 
'/var/tmp/patchew-tester-tmp-c3wao_ik/src/docker-src.2020-02-22-03.18.45.20389:/var/tmp/qemu:z,ro',
 'qemu:fedora', '/var/tmp/qemu/run', 'test-mingw']' returned non-zero exit 
status 2.
filter=--filter=label=com.qemu.instance.uuid=797be2e5d6284df8a28232368d5ea704
make[1]: *** [docker-run] Error 1
make[1]: Leaving directory `/var/tmp/patchew-tester-tmp-c3wao_ik/src'
make: *** [docker-run-test-mingw@fedora] Error 2

real2m30.962s
user0m7.737s


The full log is available at
http://patchew.org/logs/1582358843-51931-1-git-send-email-yi.l@intel.com/testing.docker-mingw@fedora/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-de...@redhat.com

[RFC v3.1 12/22] intel_iommu: add PASID cache management infrastructure

2020-02-22 Thread Liu Yi L
This patch adds a PASID cache management infrastructure based on
new added structure VTDPASIDAddressSpace, which is used to track
the PASID usage and future PASID tagged DMA address translation
support in vIOMMU.

struct VTDPASIDAddressSpace {
VTDBus *vtd_bus;
uint8_t devfn;
AddressSpace as;
uint32_t pasid;
IntelIOMMUState *iommu_state;
VTDContextCacheEntry context_cache_entry;
QLIST_ENTRY(VTDPASIDAddressSpace) next;
VTDPASIDCacheEntry pasid_cache_entry;
};

Ideally, a VTDPASIDAddressSpace instance is created when a PASID
is bound with a DMA AddressSpace. Intel VT-d spec requires guest
software to issue pasid cache invalidation when bind or unbind a
pasid with an address space under caching-mode. However, as
VTDPASIDAddressSpace instances also act as pasid cache in this
implementation, its creation also happens during vIOMMU PASID
tagged DMA translation. The creation in this path will not be
added in this patch since no PASID-capable emulated devices for
now.

The implementation in this patch manages VTDPASIDAddressSpace
instances per PASID+BDF (lookup and insert will use PASID and
BDF) since Intel VT-d spec allows per-BDF PASID Table. When a
guest bind a PASID with an AddressSpace, QEMU will capture the
guest pasid selective pasid cache invalidation, and allocate
remove a VTDPASIDAddressSpace instance per the invalidation
reasons:

*) a present pasid entry moved to non-present
*) a present pasid entry to be a present entry
*) a non-present pasid entry moved to present

vIOMMU emulator could figure out the reason by fetching latest
guest pasid entry.

Cc: Kevin Tian 
Cc: Jacob Pan 
Cc: Peter Xu 
Cc: Yi Sun 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Signed-off-by: Liu Yi L 
---
 hw/i386/intel_iommu.c  | 386 +
 hw/i386/intel_iommu_internal.h |  14 ++
 hw/i386/trace-events   |   1 +
 include/hw/i386/intel_iommu.h  |  33 +++-
 4 files changed, 433 insertions(+), 1 deletion(-)

diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 462449c..b032a7c 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -40,6 +40,7 @@
 #include "kvm_i386.h"
 #include "migration/vmstate.h"
 #include "trace.h"
+#include "qemu/jhash.h"
 
 /* context entry operations */
 #define VTD_CE_GET_RID2PASID(ce) \
@@ -65,6 +66,8 @@
 static void vtd_address_space_refresh_all(IntelIOMMUState *s);
 static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n);
 
+static void vtd_pasid_cache_reset(IntelIOMMUState *s);
+
 static void vtd_panic_require_caching_mode(void)
 {
 error_report("We need to set caching-mode=on for intel-iommu to enable "
@@ -276,6 +279,7 @@ static void vtd_reset_caches(IntelIOMMUState *s)
 vtd_iommu_lock(s);
 vtd_reset_iotlb_locked(s);
 vtd_reset_context_cache_locked(s);
+vtd_pasid_cache_reset(s);
 vtd_iommu_unlock(s);
 }
 
@@ -686,6 +690,11 @@ static inline bool vtd_pe_type_check(X86IOMMUState 
*x86_iommu,
 return true;
 }
 
+static inline uint16_t vtd_pe_get_domain_id(VTDPASIDEntry *pe)
+{
+return VTD_SM_PASID_ENTRY_DID((pe)->val[1]);
+}
+
 static inline bool vtd_pdire_present(VTDPASIDDirEntry *pdire)
 {
 return pdire->val & 1;
@@ -2393,19 +2402,394 @@ static bool vtd_process_iotlb_desc(IntelIOMMUState *s, 
VTDInvDesc *inv_desc)
 return true;
 }
 
+static inline void vtd_init_pasid_key(uint32_t pasid,
+ uint16_t sid,
+ struct pasid_key *key)
+{
+key->pasid = pasid;
+key->sid = sid;
+}
+
+static guint vtd_pasid_as_key_hash(gconstpointer v)
+{
+struct pasid_key *key = (struct pasid_key *)v;
+uint32_t a, b, c;
+
+/* Jenkins hash */
+a = b = c = JHASH_INITVAL + sizeof(*key);
+a += key->sid;
+b += extract32(key->pasid, 0, 16);
+c += extract32(key->pasid, 16, 16);
+
+__jhash_mix(a, b, c);
+__jhash_final(a, b, c);
+
+return c;
+}
+
+static gboolean vtd_pasid_as_key_equal(gconstpointer v1, gconstpointer v2)
+{
+const struct pasid_key *k1 = v1;
+const struct pasid_key *k2 = v2;
+
+return (k1->pasid == k2->pasid) && (k1->sid == k2->sid);
+}
+
+static inline int vtd_dev_get_pe_from_pasid(IntelIOMMUState *s,
+uint8_t bus_num,
+uint8_t devfn,
+uint32_t pasid,
+VTDPASIDEntry *pe)
+{
+VTDContextEntry ce;
+int ret;
+dma_addr_t pasid_dir_base;
+
+if (!s->root_scalable) {
+return -VTD_FR_PASID_TABLE_INV;
+}
+
+ret = vtd_dev_to_context_entry(s, bus_num, devfn, );
+if (ret) {
+return ret;
+}
+
+pasid_dir_base = VTD_CE_GET_PASID_DIR_TABLE();
+ret = vtd_get_pe_from_pasid_table(s,
+  pasid_dir_base, pasid, pe);
+
+

[RFC v3.1 20/22] intel_iommu: propagate PASID-based iotlb invalidation to host

2020-02-22 Thread Liu Yi L
This patch propagates PASID-based iotlb invalidation to host.

Intel VT-d 3.0 supports nested translation in PASID granular.
Guest SVA support could be implemented by configuring nested
translation on specific PASID. This is also known as dual stage
DMA translation.

Under such configuration, guest owns the GVA->GPA translation
which is configured as first level page table in host side for
a specific pasid, and host owns GPA->HPA translation. As guest
owns first level translation table, piotlb invalidation should
be propagated to host since host IOMMU will cache first level
page table related mappings during DMA address translation.

This patch traps the guest PASID-based iotlb flush and propagate
it to host.

Cc: Kevin Tian 
Cc: Jacob Pan 
Cc: Peter Xu 
Cc: Yi Sun 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Signed-off-by: Liu Yi L 
---
 hw/i386/intel_iommu.c  | 131 +
 hw/i386/intel_iommu_internal.h |   7 +++
 2 files changed, 138 insertions(+)

diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index b712eae..e6326ef 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -3157,15 +3157,146 @@ static bool vtd_process_pasid_desc(IntelIOMMUState *s,
 return (ret == 0) ? true : false;
 }
 
+static void vtd_invalidate_piotlb(IntelIOMMUState *s,
+  VTDBus *vtd_bus,
+  int devfn,
+  DualIOMMUStage1Cache *stage1_cache)
+{
+PCIDevice *dev;
+HostIOMMUContext *host_icx;
+dev = vtd_bus->bus->devices[devfn];
+
+host_icx = pci_device_host_iommu_context(dev);
+if (!host_icx) {
+return;
+}
+if (host_iommu_ctx_flush_stage1_cache(host_icx, stage1_cache)) {
+error_report("Cache flush failed");
+}
+}
+
+static inline bool vtd_pasid_cache_valid(
+  VTDPASIDAddressSpace *vtd_pasid_as)
+{
+return vtd_pasid_as->iommu_state &&
+   (vtd_pasid_as->iommu_state->pasid_cache_gen
+ == vtd_pasid_as->pasid_cache_entry.pasid_cache_gen);
+}
+
+/**
+ * This function is a loop function for the s->vtd_pasid_as
+ * list with VTDPIOTLBInvInfo as execution filter. It propagates
+ * the piotlb invalidation to host. Caller of this function
+ * should hold iommu_lock.
+ */
+static void vtd_flush_pasid_iotlb(gpointer key, gpointer value,
+  gpointer user_data)
+{
+VTDPIOTLBInvInfo *piotlb_info = user_data;
+VTDPASIDAddressSpace *vtd_pasid_as = value;
+uint16_t did;
+
+/*
+ * Needs to check whether the pasid entry cache stored in
+ * vtd_pasid_as is valid or not. "invalid" means the pasid
+ * cache has been flushed, thus host should have done piotlb
+ * invalidation together with a pasid cache invalidation, so
+ * no need to pass down piotlb invalidation to host for better
+ * performance. Only when pasid entry cache is "valid", should
+ * a piotlb invalidation be propagated to host since it means
+ * guest just modified a mapping in its page table.
+ */
+if (!vtd_pasid_cache_valid(vtd_pasid_as)) {
+return;
+}
+
+did = vtd_pe_get_domain_id(
+&(vtd_pasid_as->pasid_cache_entry.pasid_entry));
+
+if ((piotlb_info->domain_id == did) &&
+(piotlb_info->pasid == vtd_pasid_as->pasid)) {
+vtd_invalidate_piotlb(vtd_pasid_as->iommu_state,
+  vtd_pasid_as->vtd_bus,
+  vtd_pasid_as->devfn,
+  piotlb_info->stage1_cache);
+}
+
+/*
+ * TODO: needs to add QEMU piotlb flush when QEMU piotlb
+ * infrastructure is ready. For now, it is enough for passthru
+ * devices.
+ */
+}
+
 static void vtd_piotlb_pasid_invalidate(IntelIOMMUState *s,
 uint16_t domain_id,
 uint32_t pasid)
 {
+VTDPIOTLBInvInfo piotlb_info;
+DualIOMMUStage1Cache *stage1_cache;
+struct iommu_cache_invalidate_info *cache_info;
+
+stage1_cache = g_malloc0(sizeof(*stage1_cache));
+stage1_cache->pasid = pasid;
+
+cache_info = _cache->cache_info;
+cache_info->version = IOMMU_UAPI_VERSION;
+cache_info->cache = IOMMU_CACHE_INV_TYPE_IOTLB;
+cache_info->granularity = IOMMU_INV_GRANU_PASID;
+cache_info->pasid_info.pasid = pasid;
+cache_info->pasid_info.flags = IOMMU_INV_PASID_FLAGS_PASID;
+
+piotlb_info.domain_id = domain_id;
+piotlb_info.pasid = pasid;
+piotlb_info.stage1_cache = stage1_cache;
+
+vtd_iommu_lock(s);
+/*
+ * Here loops all the vtd_pasid_as instances in s->vtd_pasid_as
+ * to find out the affected devices since piotlb invalidation
+ * should check pasid cache per architecture point of view.
+ */
+g_hash_table_foreach(s->vtd_pasid_as,
+ vtd_flush_pasid_iotlb, _info);
+vtd_iommu_unlock(s);
+ 

[RFC v3.1 14/22] intel_iommu: bind/unbind guest page table to host

2020-02-22 Thread Liu Yi L
This patch captures the guest PASID table entry modifications and
propagates the changes to host to setup dual stage DMA translation.
The guest page table is configured as 1st level page table (GVA->GPA)
whose translation result would further go through host VT-d 2nd
level page table(GPA->HPA) under nested translation mode. This is
a key part of vSVA support, and also a key to support IOVA over 1st
level page table for Intel VT-d in virtualization environment.

Cc: Kevin Tian 
Cc: Jacob Pan 
Cc: Peter Xu 
Cc: Yi Sun 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Signed-off-by: Liu Yi L 
---
 hw/i386/intel_iommu.c  | 93 --
 hw/i386/intel_iommu_internal.h | 26 
 2 files changed, 115 insertions(+), 4 deletions(-)

diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index b032a7c..8bd27b1 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -41,6 +41,7 @@
 #include "migration/vmstate.h"
 #include "trace.h"
 #include "qemu/jhash.h"
+#include 
 
 /* context entry operations */
 #define VTD_CE_GET_RID2PASID(ce) \
@@ -695,6 +696,16 @@ static inline uint16_t vtd_pe_get_domain_id(VTDPASIDEntry 
*pe)
 return VTD_SM_PASID_ENTRY_DID((pe)->val[1]);
 }
 
+static inline uint32_t vtd_pe_get_fl_aw(VTDPASIDEntry *pe)
+{
+return 48 + ((pe->val[2] >> 2) & VTD_SM_PASID_ENTRY_FLPM) * 9;
+}
+
+static inline dma_addr_t vtd_pe_get_flpt_base(VTDPASIDEntry *pe)
+{
+return pe->val[2] & VTD_SM_PASID_ENTRY_FLPTPTR;
+}
+
 static inline bool vtd_pdire_present(VTDPASIDDirEntry *pdire)
 {
 return pdire->val & 1;
@@ -1854,6 +1865,73 @@ static void 
vtd_context_global_invalidate(IntelIOMMUState *s)
 vtd_iommu_replay_all(s);
 }
 
+static int vtd_bind_guest_pasid(IntelIOMMUState *s, VTDBus *vtd_bus,
+int devfn, int pasid, VTDPASIDEntry *pe,
+VTDPASIDOp op)
+{
+HostIOMMUContext *host_icx;
+DualIOMMUStage1BindData *bind_data;
+struct iommu_gpasid_bind_data *g_bind_data;
+PCIDevice *dev;
+int ret = -1;
+
+dev = vtd_bus->bus->devices[devfn];
+host_icx = pci_device_host_iommu_context(dev);
+if (!host_icx) {
+return ret;
+}
+
+if (host_icx->uinfo.stage1_format
+ != IOMMU_PASID_FORMAT_INTEL_VTD)
+{
+error_report_once("IOMMU Stage 1 format is not compatible!\n");
+}
+
+bind_data = g_malloc0(sizeof(*bind_data));
+bind_data->pasid = pasid;
+g_bind_data = _data->bind_data.gpasid_bind;
+
+g_bind_data->flags = 0;
+g_bind_data->vtd.flags = 0;
+switch (op) {
+case VTD_PASID_BIND:
+case VTD_PASID_UPDATE:
+g_bind_data->version = IOMMU_UAPI_VERSION;
+g_bind_data->format = IOMMU_PASID_FORMAT_INTEL_VTD;
+g_bind_data->gpgd = vtd_pe_get_flpt_base(pe);
+g_bind_data->addr_width = vtd_pe_get_fl_aw(pe);
+g_bind_data->hpasid = pasid;
+g_bind_data->gpasid = pasid;
+g_bind_data->flags |= IOMMU_SVA_GPASID_VAL;
+g_bind_data->vtd.flags =
+ (VTD_SM_PASID_ENTRY_SRE_BIT(pe->val[2]) ? 1 : 0)
+   | (VTD_SM_PASID_ENTRY_EAFE_BIT(pe->val[2]) ? 1 : 0)
+   | (VTD_SM_PASID_ENTRY_PCD_BIT(pe->val[1]) ? 1 : 0)
+   | (VTD_SM_PASID_ENTRY_PWT_BIT(pe->val[1]) ? 1 : 0)
+   | (VTD_SM_PASID_ENTRY_EMTE_BIT(pe->val[1]) ? 1 : 0)
+   | (VTD_SM_PASID_ENTRY_CD_BIT(pe->val[1]) ? 1 : 0);
+g_bind_data->vtd.pat = VTD_SM_PASID_ENTRY_PAT(pe->val[1]);
+g_bind_data->vtd.emt = VTD_SM_PASID_ENTRY_EMT(pe->val[1]);
+ret = host_iommu_ctx_bind_stage1_pgtbl(host_icx, bind_data);
+break;
+case VTD_PASID_UNBIND:
+g_bind_data->version = IOMMU_UAPI_VERSION;
+g_bind_data->format = IOMMU_PASID_FORMAT_INTEL_VTD;
+g_bind_data->gpgd = 0;
+g_bind_data->addr_width = 0;
+g_bind_data->hpasid = pasid;
+g_bind_data->gpasid = pasid;
+g_bind_data->flags |= IOMMU_SVA_GPASID_VAL;
+ret = host_iommu_ctx_unbind_stage1_pgtbl(host_icx, bind_data);
+break;
+default:
+error_report_once("Unknown VTDPASIDOp!!\n");
+break;
+}
+g_free(bind_data);
+return ret;
+}
+
 /* Do a context-cache device-selective invalidation.
  * @func_mask: FM field after shifting
  */
@@ -2533,18 +2611,20 @@ static gboolean vtd_flush_pasid(gpointer key, gpointer 
value,
 /* pasid entry was updated, thus update the pasid cache */
 pc_entry->pasid_entry = pe;
 pc_entry->pasid_cache_gen = s->pasid_cache_gen;
+vtd_bind_guest_pasid(s, vtd_bus, devfn,
+ pasid, , VTD_PASID_UPDATE);
 /*
  * TODO:
- * - send pasid bind to host for passthru devices
  * - when pasid-base-iotlb(piotlb) infrastructure is ready,
  *   should invalidate QEMU piotlb togehter 

[RFC v3.1 18/22] vfio/common: add support for flush iommu stage-1 cache

2020-02-22 Thread Liu Yi L
This patch adds flush_stage1_cache() definition in HostIOMMUOps. And
adds corresponding implementation in VFIO. This is to expose a way for
vIOMMU to flush stage-1 cache in host side since guest owns stage-1
translation structures in dual stage DMA translation.

Cc: Kevin Tian 
Cc: Jacob Pan 
Cc: Peter Xu 
Cc: Eric Auger 
Cc: Yi Sun 
Cc: David Gibson 
Cc: Alex Williamson 
Signed-off-by: Liu Yi L 
---
 hw/iommu/host_iommu_context.c | 10 ++
 hw/vfio/common.c  | 24 
 include/hw/iommu/host_iommu_context.h | 14 ++
 3 files changed, 48 insertions(+)

diff --git a/hw/iommu/host_iommu_context.c b/hw/iommu/host_iommu_context.c
index 5f7eb92..90be684 100644
--- a/hw/iommu/host_iommu_context.c
+++ b/hw/iommu/host_iommu_context.c
@@ -61,6 +61,16 @@ int host_iommu_ctx_unbind_stage1_pgtbl(HostIOMMUContext 
*host_icx,
 return -ENOENT;
 }
 
+int host_iommu_ctx_flush_stage1_cache(HostIOMMUContext *host_icx,
+DualIOMMUStage1Cache *cache)
+{
+if (host_icx && (host_icx->flags & HOST_IOMMU_NESTING) &&
+host_icx && host_icx->ops && host_icx->ops->flush_stage1_cache) {
+return host_icx->ops->flush_stage1_cache(host_icx, cache);
+}
+return -ENOENT;
+}
+
 void host_iommu_ctx_init(HostIOMMUContext *host_icx,
  uint64_t flags, HostIOMMUOps *ops,
  HostIOMMUInfo *uinfo)
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index b560fdb..305796b 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -1269,11 +1269,35 @@ static int 
vfio_host_icx_unbind_stage1_pgtbl(HostIOMMUContext *host_icx,
 return ret;
 }
 
+static int vfio_host_iommu_ctx_flush_stage1_cache(HostIOMMUContext *host_icx,
+  DualIOMMUStage1Cache *cache)
+{
+VFIOContainer *container = container_of(host_icx, VFIOContainer, host_icx);
+struct vfio_iommu_type1_cache_invalidate *cache_inv;
+unsigned long argsz;
+int ret = 0;
+
+argsz = sizeof(*cache_inv) + sizeof(cache->cache_info);
+cache_inv = g_malloc0(argsz);
+cache_inv->argsz = argsz;
+cache_inv->flags = 0;
+memcpy(_inv->cache_info, >cache_info,
+   sizeof(cache->cache_info));
+
+if (ioctl(container->fd, VFIO_IOMMU_CACHE_INVALIDATE, cache_inv)) {
+error_report("%s: iommu cache flush failed: %d", __func__, -errno);
+ret = -errno;
+}
+g_free(cache_inv);
+return ret;
+}
+
 static struct HostIOMMUOps vfio_host_icx_ops = {
 .pasid_alloc = vfio_host_icx_pasid_alloc,
 .pasid_free = vfio_host_icx_pasid_free,
 .bind_stage1_pgtbl = vfio_host_icx_bind_stage1_pgtbl,
 .unbind_stage1_pgtbl = vfio_host_icx_unbind_stage1_pgtbl,
+.flush_stage1_cache = vfio_host_iommu_ctx_flush_stage1_cache,
 };
 
 /**
diff --git a/include/hw/iommu/host_iommu_context.h 
b/include/hw/iommu/host_iommu_context.h
index 660fab8..a55d49a 100644
--- a/include/hw/iommu/host_iommu_context.h
+++ b/include/hw/iommu/host_iommu_context.h
@@ -32,6 +32,7 @@ typedef struct HostIOMMUContext HostIOMMUContext;
 typedef struct HostIOMMUOps HostIOMMUOps;
 typedef struct HostIOMMUInfo HostIOMMUInfo;
 typedef struct DualIOMMUStage1BindData DualIOMMUStage1BindData;
+typedef struct DualIOMMUStage1Cache DualIOMMUStage1Cache;
 
 struct HostIOMMUOps {
 /* Allocate pasid from HostIOMMUContext (a.k.a. host software) */
@@ -52,6 +53,12 @@ struct HostIOMMUOps {
 /* Undo a previous bind. @bind_data specifies the unbind info. */
 int (*unbind_stage1_pgtbl)(HostIOMMUContext *dsi_obj,
DualIOMMUStage1BindData *bind_data);
+/*
+ * Propagate stage-1 cache flush to host IOMMU, cache
+ * info specifid in @cache
+ */
+int (*flush_stage1_cache)(HostIOMMUContext *host_icx,
+  DualIOMMUStage1Cache *cache);
 };
 
 struct HostIOMMUInfo {
@@ -76,6 +83,11 @@ struct DualIOMMUStage1BindData {
 } bind_data;
 };
 
+struct DualIOMMUStage1Cache {
+uint32_t pasid;
+struct iommu_cache_invalidate_info cache_info;
+};
+
 int host_iommu_ctx_pasid_alloc(HostIOMMUContext *host_icx, uint32_t min,
uint32_t max, uint32_t *pasid);
 int host_iommu_ctx_pasid_free(HostIOMMUContext *host_icx, uint32_t pasid);
@@ -83,6 +95,8 @@ int host_iommu_ctx_bind_stage1_pgtbl(HostIOMMUContext 
*host_icx,
  DualIOMMUStage1BindData *data);
 int host_iommu_ctx_unbind_stage1_pgtbl(HostIOMMUContext *host_icx,
DualIOMMUStage1BindData *data);
+int host_iommu_ctx_flush_stage1_cache(HostIOMMUContext *host_icx,
+  DualIOMMUStage1Cache *cache);
 
 void host_iommu_ctx_init(HostIOMMUContext *host_icx,
  uint64_t flags, HostIOMMUOps *ops,
-- 
2.7.4




[RFC v3.1 15/22] intel_iommu: replay guest pasid bindings to host

2020-02-22 Thread Liu Yi L
This patch adds guest pasid bindings replay for domain
selective pasid cache invalidation(dsi) and global pasid
cache invalidation by walking guest pasid table.

Reason:
Guest OS may flush the pasid cache with a larger granularity.
e.g. guest does a svm_bind() but flush the pasid cache with
global or domain selective pasid cache invalidation instead
of pasid selective(psi) pasid cache invalidation. Regards to
such case, it works in host. Per spec, a global or domain
selective pasid cache invalidation should be able to cover
what a pasid selective invalidation does. The only concern
is performance deduction since dsi and global cache invalidation
will flush more than psi. To align with native, vIOMMU needs
emulator needs to do replay for the two invalidation granularity
to reflect the latest pasid bindings in guest pasid table.

Cc: Kevin Tian 
Cc: Jacob Pan 
Cc: Peter Xu 
Cc: Yi Sun 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Signed-off-by: Liu Yi L 
---
 hw/i386/intel_iommu.c  | 183 ++---
 hw/i386/intel_iommu_internal.h |   1 +
 2 files changed, 173 insertions(+), 11 deletions(-)

diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 8bd27b1..e7c9677 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -68,6 +68,8 @@ static void vtd_address_space_refresh_all(IntelIOMMUState *s);
 static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n);
 
 static void vtd_pasid_cache_reset(IntelIOMMUState *s);
+static int vtd_update_pe_cache_for_dev(IntelIOMMUState *s,
+  VTDBus *vtd_bus, int devfn, int pasid, VTDPASIDEntry *pe);
 
 static void vtd_panic_require_caching_mode(void)
 {
@@ -2631,6 +2633,127 @@ remove:
 return true;
 }
 
+/**
+ * Constant information used during pasid table walk
+   @vtd_bus, @devfn: device info
+ * @flags: indicates if it is domain selective walk
+ * @did: domain ID of the pasid table walk
+ */
+typedef struct {
+VTDBus *vtd_bus;
+uint16_t devfn;
+#define VTD_PASID_TABLE_DID_SEL_WALK   (1ULL << 0);
+uint32_t flags;
+uint16_t did;
+} vtd_pasid_table_walk_info;
+
+static bool vtd_sm_pasid_table_walk_one(IntelIOMMUState *s,
+   dma_addr_t pt_base,
+   int start,
+   int end,
+   vtd_pasid_table_walk_info *info)
+{
+VTDPASIDEntry pe;
+int pasid = start;
+int pasid_next;
+
+while (pasid < end) {
+pasid_next = pasid + 1;
+
+if (!vtd_get_pe_in_pasid_leaf_table(s, pasid, pt_base, )
+&& vtd_pe_present()) {
+if (vtd_update_pe_cache_for_dev(s, info->vtd_bus,
+  info->devfn, pasid, )) {
+error_report_once("%s, bus: %d, devfn: %d, pasid: %d",
+  __func__,
+  pci_bus_num(info->vtd_bus->bus),
+  info->devfn, pasid);
+return false;
+}
+}
+pasid = pasid_next;
+}
+return true;
+}
+
+/*
+ * Currently, VT-d scalable mode pasid table is a two level table,
+ * this function aims to loop a range of PASIDs in a given pasid
+ * table to identify the pasid config in guest.
+ */
+static void vtd_sm_pasid_table_walk(IntelIOMMUState *s,
+dma_addr_t pdt_base,
+int start,
+int end,
+vtd_pasid_table_walk_info *info)
+{
+VTDPASIDDirEntry pdire;
+int pasid = start;
+int pasid_next;
+dma_addr_t pt_base;
+
+while (pasid < end) {
+pasid_next = pasid + VTD_PASID_TBL_ENTRY_NUM;
+if (!vtd_get_pdire_from_pdir_table(pdt_base, pasid, )
+&& vtd_pdire_present()) {
+pt_base = pdire.val & VTD_PASID_TABLE_BASE_ADDR_MASK;
+if (!vtd_sm_pasid_table_walk_one(s,
+  pt_base, pasid, pasid_next, info)) {
+break;
+}
+}
+pasid = pasid_next;
+}
+}
+
+/**
+ * This function replay the guest pasid bindings to hots by
+ * walking the guest PASID table. This ensures host will have
+ * latest guest pasid bindings.
+ */
+static void vtd_replay_guest_pasid_bindings(IntelIOMMUState *s,
+uint16_t *did,
+bool is_dsi)
+{
+VTDContextEntry ce;
+VTDBus *vtd_bus;
+int bus_n, devfn;
+vtd_pasid_table_walk_info info;
+
+if (is_dsi) {
+info.flags = VTD_PASID_TABLE_DID_SEL_WALK;
+info.did = *did;
+}
+
+/*
+ * In this replay, only needs to care about the devices which
+ * has iommu_context created. For the one not have iommu_context,
+ * it is not necessary to replay the bindings since their cache
+ * could be 

[RFC v3.1 04/22] hw/iommu: introduce HostIOMMUContext

2020-02-22 Thread Liu Yi L
Currently, many platform vendors provide the capability of dual stage
DMA address translation in hardware. For example, nested translation
on Intel VT-d scalable mode, nested stage translation on ARM SMMUv3,
and etc. In dual stage DMA address translation, there are two stages
address translation, stage-1 (a.k.a first-level) and stage-2 (a.k.a
second-level) translation structures. Stage-1 translation results are
also subjected to stage-2 translation structures. Take vSVA (Virtual
Shared Virtual Addressing) as an example, guest IOMMU driver owns
stage-1 translation structures (covers GVA->GPA translation), and host
IOMMU driver owns stage-2 translation structures (covers GPA->HPA
translation). VMM is responsible to bind stage-1 translation structures
to host, thus hardware could achieve GVA->GPA and then GPA->HPA
translation. For more background on SVA, refer the below links.
 - https://www.youtube.com/watch?v=Kq_nfGK5MwQ
 - https://events19.lfasiallc.com/wp-content/uploads/2017/11/\
Shared-Virtual-Memory-in-KVM_Yi-Liu.pdf

In QEMU, vIOMMU emualtors expose IOMMUs to VM per their own spec. Devices
are pass-through to guest via device pass-through components like VFIO.
VFIO is a userspace driver framework which exposes host IOMMU programming
capability to userspace in a secure way. e.g. IOVA MAP/UNMAP requests. Thus
the major connection between VFIO and vIOMMU are MAP/UNMAP. However, with
the dual stage DMA translation support, there are more interactions between
vIOMMU and VFIO as below:
 1) PASID allocation (allow host to intercept in PASID allocation)
 2) bind stage-1 translation structures to host
 3) propagate stage-1 cache invalidation to host
 4) DMA address translation fault (I/O page fault) servicing etc.

With the above new interactions, it requires an abstract layer to abstract
the above operations and expose to vIOMMU emulators as an explicit way for
vIOMMU emulators call into VFIO. This patch introduces HostIOMMUContext to
stand for hardware IOMMU w/ dual stage DMA address translation capability.
PASID allocation/free are the first two operations included to demonstrate
the design, in future, there will be more operations like bind_stage1_pgtbl
and invalidate_stage1_cache and etc.

Cc: Kevin Tian 
Cc: Jacob Pan 
Cc: Peter Xu 
Cc: Eric Auger 
Cc: Yi Sun 
Cc: David Gibson 
Cc: Michael S. Tsirkin 
Signed-off-by: Liu Yi L 
---
 hw/Makefile.objs  |  1 +
 hw/iommu/Makefile.objs|  1 +
 hw/iommu/host_iommu_context.c | 55 +++
 include/hw/iommu/host_iommu_context.h | 61 +++
 4 files changed, 118 insertions(+)
 create mode 100644 hw/iommu/Makefile.objs
 create mode 100644 hw/iommu/host_iommu_context.c
 create mode 100644 include/hw/iommu/host_iommu_context.h

diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 660e2b4..cab83fe 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -40,6 +40,7 @@ devices-dirs-$(CONFIG_MEM_DEVICE) += mem/
 devices-dirs-$(CONFIG_NUBUS) += nubus/
 devices-dirs-y += semihosting/
 devices-dirs-y += smbios/
+devices-dirs-y += iommu/
 endif
 
 common-obj-y += $(devices-dirs-y)
diff --git a/hw/iommu/Makefile.objs b/hw/iommu/Makefile.objs
new file mode 100644
index 000..e6eed4e
--- /dev/null
+++ b/hw/iommu/Makefile.objs
@@ -0,0 +1 @@
+obj-y += host_iommu_context.o
diff --git a/hw/iommu/host_iommu_context.c b/hw/iommu/host_iommu_context.c
new file mode 100644
index 000..11b092f
--- /dev/null
+++ b/hw/iommu/host_iommu_context.c
@@ -0,0 +1,55 @@
+/*
+ * QEMU abstract of Host IOMMU
+ *
+ * Copyright (C) 2020 Intel Corporation.
+ *
+ * Authors: Liu Yi L 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see .
+ */
+
+#include "qemu/osdep.h"
+#include "hw/iommu/host_iommu_context.h"
+
+int host_iommu_ctx_pasid_alloc(HostIOMMUContext *host_icx, uint32_t min,
+   uint32_t max, uint32_t *pasid)
+{
+if (host_icx && (host_icx->flags & HOST_IOMMU_PASID_REQUEST) &&
+host_icx->ops && host_icx->ops->pasid_alloc) {
+return host_icx->ops->pasid_alloc(host_icx, min, max, pasid);
+}
+return -ENOENT;
+}
+
+int host_iommu_ctx_pasid_free(HostIOMMUContext *host_icx, uint32_t pasid)
+{
+if (host_icx && (host_icx->flags & HOST_IOMMU_PASID_REQUEST) &&
+host_icx->ops && host_icx->ops->pasid_free) {
+return 

[RFC v3.1 06/22] vfio/pci: init HostIOMMUContext per-container

2020-02-22 Thread Liu Yi L
After confirming dual stage DMA translation support with kernel by
checking VFIO_TYPE1_NESTING_IOMMU, VFIO inits HostIOMMUContet instance
and exposes it to PCI layer. Thus vIOMMU emualtors may make use of
such capability by leveraging the ops provided by HostIOMMUContext.

Cc: Kevin Tian 
Cc: Jacob Pan 
Cc: Peter Xu 
Cc: Eric Auger 
Cc: Yi Sun 
Cc: David Gibson 
Cc: Alex Williamson 
Signed-off-by: Liu Yi L 
---
 hw/vfio/common.c  | 11 +++
 hw/vfio/pci.c | 21 +
 include/hw/vfio/vfio-common.h |  2 ++
 3 files changed, 34 insertions(+)

diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index be1a9e5..9ab62a6 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -1179,10 +1179,15 @@ static int vfio_get_iommu_type(VFIOContainer *container,
 return -EINVAL;
 }
 
+static struct HostIOMMUOps vfio_host_icx_ops = {
+/* To be added later */
+};
+
 static int vfio_init_container(VFIOContainer *container, int group_fd,
Error **errp)
 {
 int iommu_type, ret;
+uint64_t flags = 0;
 
 iommu_type = vfio_get_iommu_type(container, errp);
 if (iommu_type < 0) {
@@ -1210,6 +1215,11 @@ static int vfio_init_container(VFIOContainer *container, 
int group_fd,
 return -errno;
 }
 
+if (iommu_type == VFIO_TYPE1_NESTING_IOMMU) {
+host_iommu_ctx_init(>host_icx,
+flags, _host_icx_ops);
+}
+
 container->iommu_type = iommu_type;
 return 0;
 }
@@ -1456,6 +1466,7 @@ static void vfio_disconnect_container(VFIOGroup *group)
 }
 
 trace_vfio_disconnect_container(container->fd);
+host_iommu_ctx_destroy(>host_icx);
 close(container->fd);
 g_free(container);
 
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 5e75a95..df79675 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -2712,11 +2712,20 @@ static void vfio_unregister_req_notifier(VFIOPCIDevice 
*vdev)
 vdev->req_enabled = false;
 }
 
+static HostIOMMUContext *vfio_host_dma_iommu(PCIDevice *pdev)
+{
+VFIOPCIDevice *vdev = PCI_VFIO(pdev);
+VFIOContainer *container = vdev->vbasedev.group->container;
+
+return >host_icx;
+}
+
 static void vfio_realize(PCIDevice *pdev, Error **errp)
 {
 VFIOPCIDevice *vdev = PCI_VFIO(pdev);
 VFIODevice *vbasedev_iter;
 VFIOGroup *group;
+VFIOContainer *container;
 char *tmp, *subsys, group_path[PATH_MAX], *group_name;
 Error *err = NULL;
 ssize_t len;
@@ -3028,6 +3037,11 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
 vfio_register_req_notifier(vdev);
 vfio_setup_resetfn_quirk(vdev);
 
+container = vdev->vbasedev.group->container;
+if (container->host_icx.ops) {
+pci_device_setup_iommu(pdev, vfio_host_dma_iommu);
+}
+
 return;
 
 out_deregister:
@@ -3072,9 +3086,16 @@ static void vfio_instance_finalize(Object *obj)
 static void vfio_exitfn(PCIDevice *pdev)
 {
 VFIOPCIDevice *vdev = PCI_VFIO(pdev);
+VFIOContainer *container;
 
 vfio_unregister_req_notifier(vdev);
 vfio_unregister_err_notifier(vdev);
+
+container = vdev->vbasedev.group->container;
+if (container->host_icx.ops) {
+pci_device_unset_iommu(pdev);
+}
+
 pci_device_set_intx_routing_notifier(>pdev, NULL);
 if (vdev->irqchip_change_notifier.notify) {
 kvm_irqchip_remove_change_notifier(>irqchip_change_notifier);
diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
index fd56420..36abe04 100644
--- a/include/hw/vfio/vfio-common.h
+++ b/include/hw/vfio/vfio-common.h
@@ -26,6 +26,7 @@
 #include "qemu/notify.h"
 #include "ui/console.h"
 #include "hw/display/ramfb.h"
+#include "hw/iommu/host_iommu_context.h"
 #ifdef CONFIG_LINUX
 #include 
 #endif
@@ -71,6 +72,7 @@ typedef struct VFIOContainer {
 MemoryListener listener;
 MemoryListener prereg_listener;
 unsigned iommu_type;
+HostIOMMUContext host_icx;
 Error *error;
 bool initialized;
 unsigned long pgsizes;
-- 
2.7.4




[RFC v3.1 02/22] header file update VFIO/IOMMU vSVA APIs

2020-02-22 Thread Liu Yi L
The kernel uapi/linux/iommu.h header file includes the
extensions for vSVA support. e.g. bind gpasid, iommu
fault report related user structures and etc.

Note: this should be replaced with a full header files update when
the vSVA uPAPI is stable.

Cc: Kevin Tian 
Cc: Jacob Pan 
Cc: Peter Xu 
Cc: Yi Sun 
Cc: Michael S. Tsirkin 
Cc: Cornelia Huck 
Cc: Paolo Bonzini 
Signed-off-by: Liu Yi L 
---
 linux-headers/linux/iommu.h | 372 
 linux-headers/linux/vfio.h  | 127 +++
 2 files changed, 499 insertions(+)
 create mode 100644 linux-headers/linux/iommu.h

diff --git a/linux-headers/linux/iommu.h b/linux-headers/linux/iommu.h
new file mode 100644
index 000..04cc4b0
--- /dev/null
+++ b/linux-headers/linux/iommu.h
@@ -0,0 +1,372 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * IOMMU user API definitions
+ */
+
+#ifndef _IOMMU_H
+#define _IOMMU_H
+
+#include 
+
+/**
+ * Current version of the IOMMU user API. This is intended for query
+ * between user and kernel to determine compatible data structures.
+ *
+ * Having a single UAPI version to govern the user-kernel data structures
+ * makes compatibility check straightforward. On the contrary, supporting
+ * combinations of multiple versions of the data can be a nightmare.
+ *
+ * UAPI version can be bumped up with the following rules:
+ * 1. All data structures passed between user and kernel space share
+ *the same version number. i.e. any extension to to any structure
+ *results in version bump up.
+ *
+ * 2. Data structures are open to extension but closed to modification.
+ *New fields must be added at the end of each data structure with
+ *64bit alignment. Flag bits can be added without size change but
+ *existing ones cannot be altered.
+ *
+ * 3. Versions are backward compatible.
+ *
+ * 4. Version to size lookup is supported by kernel internal API for each
+ *API function type. @version is mandatory for new data structures
+ *and must be at the beginning with type of __u32.
+ */
+#define IOMMU_UAPI_VERSION 1
+static __inline__ int iommu_get_uapi_version(void)
+{
+   return IOMMU_UAPI_VERSION;
+}
+
+/*
+ * Supported UAPI features that can be reported to user space.
+ * These types represent the capability available in the kernel.
+ *
+ * REVISIT: UAPI version also implies the capabilities. Should we
+ * report them explicitly?
+ */
+enum IOMMU_UAPI_DATA_TYPES {
+   IOMMU_UAPI_BIND_GPASID,
+   IOMMU_UAPI_CACHE_INVAL,
+   IOMMU_UAPI_PAGE_RESP,
+   NR_IOMMU_UAPI_TYPE,
+};
+
+#define IOMMU_UAPI_CAP_MASK ((1 << IOMMU_UAPI_BIND_GPASID) |   \
+   (1 << IOMMU_UAPI_CACHE_INVAL) | \
+   (1 << IOMMU_UAPI_PAGE_RESP))
+
+#define IOMMU_FAULT_PERM_READ  (1 << 0) /* read */
+#define IOMMU_FAULT_PERM_WRITE (1 << 1) /* write */
+#define IOMMU_FAULT_PERM_EXEC  (1 << 2) /* exec */
+#define IOMMU_FAULT_PERM_PRIV  (1 << 3) /* privileged */
+
+/* Generic fault types, can be expanded IRQ remapping fault */
+enum iommu_fault_type {
+   IOMMU_FAULT_DMA_UNRECOV = 1,/* unrecoverable fault */
+   IOMMU_FAULT_PAGE_REQ,   /* page request fault */
+};
+
+enum iommu_fault_reason {
+   IOMMU_FAULT_REASON_UNKNOWN = 0,
+
+   /* Could not access the PASID table (fetch caused external abort) */
+   IOMMU_FAULT_REASON_PASID_FETCH,
+
+   /* PASID entry is invalid or has configuration errors */
+   IOMMU_FAULT_REASON_BAD_PASID_ENTRY,
+
+   /*
+* PASID is out of range (e.g. exceeds the maximum PASID
+* supported by the IOMMU) or disabled.
+*/
+   IOMMU_FAULT_REASON_PASID_INVALID,
+
+   /*
+* An external abort occurred fetching (or updating) a translation
+* table descriptor
+*/
+   IOMMU_FAULT_REASON_WALK_EABT,
+
+   /*
+* Could not access the page table entry (Bad address),
+* actual translation fault
+*/
+   IOMMU_FAULT_REASON_PTE_FETCH,
+
+   /* Protection flag check failed */
+   IOMMU_FAULT_REASON_PERMISSION,
+
+   /* access flag check failed */
+   IOMMU_FAULT_REASON_ACCESS,
+
+   /* Output address of a translation stage caused Address Size fault */
+   IOMMU_FAULT_REASON_OOR_ADDRESS,
+};
+
+/**
+ * struct iommu_fault_unrecoverable - Unrecoverable fault data
+ * @reason: reason of the fault, from  iommu_fault_reason
+ * @flags: parameters of this fault (IOMMU_FAULT_UNRECOV_* values)
+ * @pasid: Process Address Space ID
+ * @perm: requested permission access using by the incoming transaction
+ *(IOMMU_FAULT_PERM_* values)
+ * @addr: offending page address
+ * @fetch_addr: address that caused a fetch abort, if any
+ */
+struct iommu_fault_unrecoverable {
+   __u32   reason;
+#define IOMMU_FAULT_UNRECOV_PASID_VALID(1 << 0)
+#define IOMMU_FAULT_UNRECOV_ADDR_VALID (1 << 1)
+#define 

[RFC v3.1 19/22] intel_iommu: process PASID-based iotlb invalidation

2020-02-22 Thread Liu Yi L
This patch adds the basic PASID-based iotlb (piotlb) invalidation
support. piotlb is used during walking Intel VT-d 1st level page
table. This patch only adds the basic processing. Detailed handling
will be added in next patch.

Cc: Kevin Tian 
Cc: Jacob Pan 
Cc: Peter Xu 
Cc: Yi Sun 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Signed-off-by: Liu Yi L 
---
 hw/i386/intel_iommu.c  | 57 ++
 hw/i386/intel_iommu_internal.h | 13 ++
 2 files changed, 70 insertions(+)

diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index cacc38b..b712eae 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -3157,6 +3157,59 @@ static bool vtd_process_pasid_desc(IntelIOMMUState *s,
 return (ret == 0) ? true : false;
 }
 
+static void vtd_piotlb_pasid_invalidate(IntelIOMMUState *s,
+uint16_t domain_id,
+uint32_t pasid)
+{
+}
+
+static void vtd_piotlb_page_invalidate(IntelIOMMUState *s, uint16_t domain_id,
+ uint32_t pasid, hwaddr addr, uint8_t am, bool ih)
+{
+}
+
+static bool vtd_process_piotlb_desc(IntelIOMMUState *s,
+VTDInvDesc *inv_desc)
+{
+uint16_t domain_id;
+uint32_t pasid;
+uint8_t am;
+hwaddr addr;
+
+if ((inv_desc->val[0] & VTD_INV_DESC_PIOTLB_RSVD_VAL0) ||
+(inv_desc->val[1] & VTD_INV_DESC_PIOTLB_RSVD_VAL1)) {
+error_report_once("non-zero-field-in-piotlb_inv_desc hi: 0x%" PRIx64
+  " lo: 0x%" PRIx64, inv_desc->val[1], inv_desc->val[0]);
+return false;
+}
+
+domain_id = VTD_INV_DESC_PIOTLB_DID(inv_desc->val[0]);
+pasid = VTD_INV_DESC_PIOTLB_PASID(inv_desc->val[0]);
+switch (inv_desc->val[0] & VTD_INV_DESC_IOTLB_G) {
+case VTD_INV_DESC_PIOTLB_ALL_IN_PASID:
+vtd_piotlb_pasid_invalidate(s, domain_id, pasid);
+break;
+
+case VTD_INV_DESC_PIOTLB_PSI_IN_PASID:
+am = VTD_INV_DESC_PIOTLB_AM(inv_desc->val[1]);
+addr = (hwaddr) VTD_INV_DESC_PIOTLB_ADDR(inv_desc->val[1]);
+if (am > VTD_MAMV) {
+error_report_once("Invalid am, > max am value, hi: 0x%" PRIx64
+" lo: 0x%" PRIx64, inv_desc->val[1], inv_desc->val[0]);
+return false;
+}
+vtd_piotlb_page_invalidate(s, domain_id, pasid,
+ addr, am, VTD_INV_DESC_PIOTLB_IH(inv_desc->val[1]));
+break;
+
+default:
+error_report_once("Invalid granularity in P-IOTLB desc hi: 0x%" PRIx64
+  " lo: 0x%" PRIx64, inv_desc->val[1], inv_desc->val[0]);
+return false;
+}
+return true;
+}
+
 static bool vtd_process_inv_iec_desc(IntelIOMMUState *s,
  VTDInvDesc *inv_desc)
 {
@@ -3271,6 +3324,10 @@ static bool vtd_process_inv_desc(IntelIOMMUState *s)
 break;
 
 case VTD_INV_DESC_PIOTLB:
+trace_vtd_inv_desc("p-iotlb", inv_desc.val[1], inv_desc.val[0]);
+if (!vtd_process_piotlb_desc(s, _desc)) {
+return false;
+}
 break;
 
 case VTD_INV_DESC_WAIT:
diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h
index d427895..17c6e84 100644
--- a/hw/i386/intel_iommu_internal.h
+++ b/hw/i386/intel_iommu_internal.h
@@ -457,6 +457,19 @@ typedef union VTDInvDesc VTDInvDesc;
 #define VTD_INV_DESC_PASIDC_PASID_SI   (1ULL << 4)
 #define VTD_INV_DESC_PASIDC_GLOBAL (3ULL << 4)
 
+#define VTD_INV_DESC_PIOTLB_ALL_IN_PASID  (2ULL << 4)
+#define VTD_INV_DESC_PIOTLB_PSI_IN_PASID  (3ULL << 4)
+
+#define VTD_INV_DESC_PIOTLB_RSVD_VAL0 0xfff0ffc0ULL
+#define VTD_INV_DESC_PIOTLB_RSVD_VAL1 0xf80ULL
+
+#define VTD_INV_DESC_PIOTLB_PASID(val)(((val) >> 32) & 0xfULL)
+#define VTD_INV_DESC_PIOTLB_DID(val)  (((val) >> 16) & \
+ VTD_DOMAIN_ID_MASK)
+#define VTD_INV_DESC_PIOTLB_ADDR(val) ((val) & ~0xfffULL)
+#define VTD_INV_DESC_PIOTLB_AM(val)   ((val) & 0x3fULL)
+#define VTD_INV_DESC_PIOTLB_IH(val)   (((val) >> 6) & 0x1)
+
 /* Information about page-selective IOTLB invalidate */
 struct VTDIOTLBPageInvInfo {
 uint16_t domain_id;
-- 
2.7.4




[RFC v3.1 13/22] vfio: add bind stage-1 page table support

2020-02-22 Thread Liu Yi L
This patch adds bind_stage1_pgtbl() definition in HostIOMMUOops, also
adds corresponding implementation in VFIO. This is to expose a way for
vIOMMU to setup dual stage DMA translation for passthru devices on hardware.

Cc: Kevin Tian 
Cc: Jacob Pan 
Cc: Peter Xu 
Cc: Eric Auger 
Cc: Yi Sun 
Cc: David Gibson 
Cc: Alex Williamson 
Signed-off-by: Liu, Yi L 
---
 hw/iommu/host_iommu_context.c | 20 ++
 hw/vfio/common.c  | 49 +++
 include/hw/iommu/host_iommu_context.h | 23 
 3 files changed, 92 insertions(+)

diff --git a/hw/iommu/host_iommu_context.c b/hw/iommu/host_iommu_context.c
index 689a087..5f7eb92 100644
--- a/hw/iommu/host_iommu_context.c
+++ b/hw/iommu/host_iommu_context.c
@@ -41,6 +41,26 @@ int host_iommu_ctx_pasid_free(HostIOMMUContext *host_icx, 
uint32_t pasid)
 return -ENOENT;
 }
 
+int host_iommu_ctx_bind_stage1_pgtbl(HostIOMMUContext *host_icx,
+ DualIOMMUStage1BindData *data)
+{
+if (host_icx && (host_icx->flags & HOST_IOMMU_NESTING) &&
+host_icx->ops && host_icx->ops->bind_stage1_pgtbl) {
+return host_icx->ops->bind_stage1_pgtbl(host_icx, data);
+}
+return -ENOENT;
+}
+
+int host_iommu_ctx_unbind_stage1_pgtbl(HostIOMMUContext *host_icx,
+   DualIOMMUStage1BindData *data)
+{
+if (host_icx && (host_icx->flags & HOST_IOMMU_NESTING) &&
+host_icx->ops && host_icx->ops->unbind_stage1_pgtbl) {
+return host_icx->ops->unbind_stage1_pgtbl(host_icx, data);
+}
+return -ENOENT;
+}
+
 void host_iommu_ctx_init(HostIOMMUContext *host_icx,
  uint64_t flags, HostIOMMUOps *ops,
  HostIOMMUInfo *uinfo)
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index 8f30a52..b560fdb 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -1223,9 +1223,57 @@ static int vfio_host_icx_pasid_free(HostIOMMUContext 
*host_icx,
 return 0;
 }
 
+static int vfio_host_icx_bind_stage1_pgtbl(HostIOMMUContext *host_icx,
+   DualIOMMUStage1BindData *bind_data)
+{
+VFIOContainer *container = container_of(host_icx, VFIOContainer, host_icx);
+struct vfio_iommu_type1_bind *bind;
+unsigned long argsz;
+int ret = 0;
+
+argsz = sizeof(*bind) + sizeof(bind_data->bind_data);
+bind = g_malloc0(argsz);
+bind->argsz = argsz;
+bind->flags = VFIO_IOMMU_BIND_GUEST_PGTBL;
+memcpy(>data, _data->bind_data, sizeof(bind_data->bind_data));
+
+if (ioctl(container->fd, VFIO_IOMMU_BIND, bind)) {
+ret = -errno;
+error_report("%s: pasid (%u) bind failed: %d",
+  __func__, bind_data->pasid, ret);
+}
+g_free(bind);
+return ret;
+}
+
+static int vfio_host_icx_unbind_stage1_pgtbl(HostIOMMUContext *host_icx,
+DualIOMMUStage1BindData *bind_data)
+{
+VFIOContainer *container = container_of(host_icx, VFIOContainer, host_icx);
+struct vfio_iommu_type1_bind *bind;
+unsigned long argsz;
+int ret = 0;
+
+argsz = sizeof(*bind) + sizeof(bind_data->bind_data);
+bind = g_malloc0(argsz);
+bind->argsz = argsz;
+bind->flags = VFIO_IOMMU_UNBIND_GUEST_PGTBL;
+memcpy(>data, _data->bind_data, sizeof(bind_data->bind_data));
+
+if (ioctl(container->fd, VFIO_IOMMU_BIND, bind)) {
+ret = -errno;
+error_report("%s: pasid (%u) unbind failed: %d",
+  __func__, bind_data->pasid, ret);
+}
+g_free(bind);
+return ret;
+}
+
 static struct HostIOMMUOps vfio_host_icx_ops = {
 .pasid_alloc = vfio_host_icx_pasid_alloc,
 .pasid_free = vfio_host_icx_pasid_free,
+.bind_stage1_pgtbl = vfio_host_icx_bind_stage1_pgtbl,
+.unbind_stage1_pgtbl = vfio_host_icx_unbind_stage1_pgtbl,
 };
 
 /**
@@ -1354,6 +1402,7 @@ static int vfio_init_container(VFIOContainer *container, 
int group_fd,
 uinfo.stage1_format = nesting.stage1_format;
 flags |= (nesting.nesting_capabilities & VFIO_IOMMU_PASID_REQS) ?
  HOST_IOMMU_PASID_REQUEST : 0;
+flags |= HOST_IOMMU_NESTING;
 host_iommu_ctx_init(>host_icx, flags,
 _host_icx_ops, );
 }
diff --git a/include/hw/iommu/host_iommu_context.h 
b/include/hw/iommu/host_iommu_context.h
index 6797f6d..660fab8 100644
--- a/include/hw/iommu/host_iommu_context.h
+++ b/include/hw/iommu/host_iommu_context.h
@@ -31,6 +31,7 @@
 typedef struct HostIOMMUContext HostIOMMUContext;
 typedef struct HostIOMMUOps HostIOMMUOps;
 typedef struct HostIOMMUInfo HostIOMMUInfo;
+typedef struct DualIOMMUStage1BindData DualIOMMUStage1BindData;
 
 struct HostIOMMUOps {
 /* Allocate pasid from HostIOMMUContext (a.k.a. host software) */
@@ -41,6 +42,16 @@ struct HostIOMMUOps {
 /* Reclaim pasid from HostIOMMUContext (a.k.a. host software) */
 int (*pasid_free)(HostIOMMUContext *host_icx,
   

[RFC v3.1 10/22] intel_iommu: add virtual command capability support

2020-02-22 Thread Liu Yi L
This patch adds virtual command support to Intel vIOMMU per
Intel VT-d 3.1 spec. And adds two virtual commands: allocate
pasid and free pasid.

Cc: Kevin Tian 
Cc: Jacob Pan 
Cc: Peter Xu 
Cc: Yi Sun 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Reviewed-by: Peter Xu 
Signed-off-by: Liu Yi L 
Signed-off-by: Yi Sun 
---
 hw/i386/intel_iommu.c  | 166 +
 hw/i386/intel_iommu_internal.h |  37 +
 hw/i386/trace-events   |   1 +
 include/hw/i386/intel_iommu.h  |   6 +-
 4 files changed, 209 insertions(+), 1 deletion(-)

diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 6258c58..fcb80cd 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -2649,6 +2649,148 @@ static void vtd_handle_iectl_write(IntelIOMMUState *s)
 }
 }
 
+static int vtd_request_pasid_alloc(IntelIOMMUState *s, uint32_t *pasid)
+{
+VTDBus *vtd_bus;
+int bus_n, devfn, ret = -1;
+
+for (bus_n = 0; bus_n < PCI_BUS_MAX; bus_n++) {
+vtd_bus = vtd_find_as_from_bus_num(s, bus_n);
+if (!vtd_bus) {
+continue;
+}
+for (devfn = 0; devfn < PCI_DEVFN_MAX; devfn++) {
+HostIOMMUContext *host_icx;
+PCIDevice *dev;
+
+dev = vtd_bus->bus->devices[devfn];
+host_icx = pci_device_host_iommu_context(dev);
+if (!host_icx) {
+continue;
+}
+
+/*
+ * We'll return the first valid result we got. It's
+ * a bit hackish in that we don't have a good global
+ * interface yet to talk to modules like vfio to deliver
+ * this allocation request, so we're leveraging this
+ * per-device iommu context to do the same thing just
+ * to make sure the allocation happens only once.
+ */
+ret = host_iommu_ctx_pasid_alloc(host_icx, VTD_MIN_HPASID,
+ VTD_MAX_HPASID, pasid);
+if (!ret) {
+break;
+}
+}
+}
+return ret;
+}
+
+static int vtd_request_pasid_free(IntelIOMMUState *s, uint32_t pasid)
+{
+VTDBus *vtd_bus;
+int bus_n, devfn, ret = -1;
+
+for (bus_n = 0; bus_n < PCI_BUS_MAX; bus_n++) {
+vtd_bus = vtd_find_as_from_bus_num(s, bus_n);
+if (!vtd_bus) {
+continue;
+}
+for (devfn = 0; devfn < PCI_DEVFN_MAX; devfn++) {
+HostIOMMUContext *host_icx;
+PCIDevice *dev;
+
+dev = vtd_bus->bus->devices[devfn];
+host_icx = pci_device_host_iommu_context(dev);
+if (!host_icx) {
+continue;
+}
+/*
+ * Similar with pasid allocation. We'll free the pasid
+ * on the first successful free operation. It's a bit
+ * hackish in that we don't have a good global interface
+ * yet to talk to modules like vfio to deliver this pasid
+ * free request, so we're leveraging this per-device iommu
+ * context to do the same thing just to make sure the free
+ * happens only once.
+ */
+ret = host_iommu_ctx_pasid_free(host_icx, pasid);
+if (!ret) {
+break;
+}
+}
+}
+return ret;
+}
+
+/*
+ * If IP is not set, set it then return.
+ * If IP is already set, return.
+ */
+static void vtd_vcmd_set_ip(IntelIOMMUState *s)
+{
+s->vcrsp = 1;
+vtd_set_quad_raw(s, DMAR_VCRSP_REG,
+ ((uint64_t) s->vcrsp));
+}
+
+static void vtd_vcmd_clear_ip(IntelIOMMUState *s)
+{
+s->vcrsp &= (~((uint64_t)(0x1)));
+vtd_set_quad_raw(s, DMAR_VCRSP_REG,
+ ((uint64_t) s->vcrsp));
+}
+
+/* Handle write to Virtual Command Register */
+static int vtd_handle_vcmd_write(IntelIOMMUState *s, uint64_t val)
+{
+uint32_t pasid;
+int ret = -1;
+
+trace_vtd_reg_write_vcmd(s->vcrsp, val);
+
+if (!(s->vccap & VTD_VCCAP_PAS) ||
+ (s->vcrsp & 1)) {
+return -1;
+}
+
+/*
+ * Since vCPU should be blocked when the guest VMCD
+ * write was trapped to here. Should be no other vCPUs
+ * try to access VCMD if guest software is well written.
+ * However, we still emulate the IP bit here in case of
+ * bad guest software. Also align with the spec.
+ */
+vtd_vcmd_set_ip(s);
+
+switch (val & VTD_VCMD_CMD_MASK) {
+case VTD_VCMD_ALLOC_PASID:
+ret = vtd_request_pasid_alloc(s, );
+if (ret) {
+s->vcrsp |= VTD_VCRSP_SC(VTD_VCMD_NO_AVAILABLE_PASID);
+} else {
+s->vcrsp |= VTD_VCRSP_RSLT(pasid);
+}
+break;
+
+case VTD_VCMD_FREE_PASID:
+pasid = VTD_VCMD_PASID_VALUE(val);
+ret = vtd_request_pasid_free(s, pasid);
+if (ret < 0) {
+s->vcrsp |= VTD_VCRSP_SC(VTD_VCMD_FREE_INVALID_PASID);
+}
+   

[RFC v3.1 07/22] vfio: get nesting iommu cap info from Kernel

2020-02-22 Thread Liu Yi L
VFIO exposes host IOMMU dual-stage DMA translation programming capability
to userspace by VFIO_TYPE1_NESTING_IOMMU type. However, userspace needs
more info on the nesting type. e.g. the supported stage 1 format and PASID
alloc/free request availability.

This patch gets the iommu nesting cap info from kernel by using IOCTL
VFIO_IOMMU_GET_INFO.

This patch referred some code from Shameer Kolothum.
https://lists.gnu.org/archive/html/qemu-devel/2018-05/msg03759.html

Cc: Kevin Tian 
Cc: Jacob Pan 
Cc: Peter Xu 
Cc: Eric Auger 
Cc: Yi Sun 
Cc: David Gibson 
Cc: Alex Williamson 
Signed-off-by: Shameer Kolothum 
Signed-off-by: Liu Yi L 
---
 hw/iommu/host_iommu_context.c |  5 +-
 hw/vfio/common.c  | 97 ++-
 include/hw/iommu/host_iommu_context.h | 10 +++-
 3 files changed, 108 insertions(+), 4 deletions(-)

diff --git a/hw/iommu/host_iommu_context.c b/hw/iommu/host_iommu_context.c
index 11b092f..689a087 100644
--- a/hw/iommu/host_iommu_context.c
+++ b/hw/iommu/host_iommu_context.c
@@ -42,10 +42,13 @@ int host_iommu_ctx_pasid_free(HostIOMMUContext *host_icx, 
uint32_t pasid)
 }
 
 void host_iommu_ctx_init(HostIOMMUContext *host_icx,
- uint64_t flags, HostIOMMUOps *ops)
+ uint64_t flags, HostIOMMUOps *ops,
+ HostIOMMUInfo *uinfo)
 {
 host_icx->flags = flags;
 host_icx->ops = ops;
+
+host_icx->uinfo.stage1_format = uinfo->stage1_format;
 }
 
 void host_iommu_ctx_destroy(HostIOMMUContext *host_icx)
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index 9ab62a6..f9be68d 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -1183,6 +1183,84 @@ static struct HostIOMMUOps vfio_host_icx_ops = {
 /* To be added later */
 };
 
+/**
+ * Get iommu info from host. Caller of this funcion should free
+ * the memory pointed by the returned pointer stored in @info
+ * after a successful calling when finished its usage.
+ */
+static int vfio_get_iommu_info(VFIOContainer *container,
+ struct vfio_iommu_type1_info **info)
+{
+
+size_t argsz = sizeof(struct vfio_iommu_type1_info);
+
+*info = g_malloc0(argsz);
+
+retry:
+(*info)->argsz = argsz;
+
+if (ioctl(container->fd, VFIO_IOMMU_GET_INFO, *info)) {
+g_free(*info);
+*info = NULL;
+return -errno;
+}
+
+if (((*info)->argsz > argsz)) {
+argsz = (*info)->argsz;
+*info = g_realloc(*info, argsz);
+goto retry;
+}
+
+return 0;
+}
+
+static struct vfio_info_cap_header *
+vfio_get_iommu_info_cap(struct vfio_iommu_type1_info *info, uint16_t id)
+{
+struct vfio_info_cap_header *hdr;
+void *ptr = info;
+
+if (!(info->flags & VFIO_IOMMU_INFO_CAPS)) {
+return NULL;
+}
+
+for (hdr = ptr + info->cap_offset; hdr != ptr; hdr = ptr + hdr->next) {
+if (hdr->id == id) {
+return hdr;
+}
+}
+
+return NULL;
+}
+
+static int vfio_get_nesting_iommu_cap(VFIOContainer *container,
+   struct vfio_iommu_type1_info_cap_nesting *cap_nesting)
+{
+struct vfio_iommu_type1_info *info;
+struct vfio_info_cap_header *hdr;
+struct vfio_iommu_type1_info_cap_nesting *cap;
+int ret;
+
+ret = vfio_get_iommu_info(container, );
+if (ret) {
+return ret;
+}
+
+hdr = vfio_get_iommu_info_cap(info,
+VFIO_IOMMU_TYPE1_INFO_CAP_NESTING);
+if (!hdr) {
+g_free(info);
+return -errno;
+}
+
+cap = container_of(hdr,
+struct vfio_iommu_type1_info_cap_nesting, header);
+*cap_nesting = *cap;
+
+g_free(info);
+return 0;
+}
+
 static int vfio_init_container(VFIOContainer *container, int group_fd,
Error **errp)
 {
@@ -1216,8 +1294,23 @@ static int vfio_init_container(VFIOContainer *container, 
int group_fd,
 }
 
 if (iommu_type == VFIO_TYPE1_NESTING_IOMMU) {
-host_iommu_ctx_init(>host_icx,
-flags, _host_icx_ops);
+struct vfio_iommu_type1_info_cap_nesting nesting = {
+ .nesting_capabilities = 0x0,
+ .stage1_format = 0, };
+HostIOMMUInfo uinfo;
+
+ret = vfio_get_nesting_iommu_cap(container, );
+if (ret) {
+error_setg_errno(errp, -ret,
+ "Failed to get nesting iommu cap");
+return ret;
+}
+
+uinfo.stage1_format = nesting.stage1_format;
+flags |= (nesting.nesting_capabilities & VFIO_IOMMU_PASID_REQS) ?
+ HOST_IOMMU_PASID_REQUEST : 0;
+host_iommu_ctx_init(>host_icx, flags,
+_host_icx_ops, );
 }
 
 container->iommu_type = iommu_type;
diff --git a/include/hw/iommu/host_iommu_context.h 
b/include/hw/iommu/host_iommu_context.h
index f4d811a..6797f6d 100644
--- 

[RFC v3.1 11/22] intel_iommu: process pasid cache invalidation

2020-02-22 Thread Liu Yi L
This patch adds PASID cache invalidation handling. When guest enabled
PASID usages (e.g. SVA), guest software should issue a proper PASID
cache invalidation when caching-mode is exposed. This patch only adds
the draft handling of pasid cache invalidation. Detailed handling will
be added in subsequent patches.

Cc: Kevin Tian 
Cc: Jacob Pan 
Cc: Peter Xu 
Cc: Yi Sun 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Reviewed-by: Peter Xu 
Signed-off-by: Liu Yi L 
---
 hw/i386/intel_iommu.c  | 66 ++
 hw/i386/intel_iommu_internal.h | 12 
 hw/i386/trace-events   |  3 ++
 3 files changed, 76 insertions(+), 5 deletions(-)

diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index fcb80cd..462449c 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -2393,6 +2393,63 @@ static bool vtd_process_iotlb_desc(IntelIOMMUState *s, 
VTDInvDesc *inv_desc)
 return true;
 }
 
+static int vtd_pasid_cache_dsi(IntelIOMMUState *s, uint16_t domain_id)
+{
+return 0;
+}
+
+static int vtd_pasid_cache_psi(IntelIOMMUState *s,
+   uint16_t domain_id, uint32_t pasid)
+{
+return 0;
+}
+
+static int vtd_pasid_cache_gsi(IntelIOMMUState *s)
+{
+return 0;
+}
+
+static bool vtd_process_pasid_desc(IntelIOMMUState *s,
+   VTDInvDesc *inv_desc)
+{
+uint16_t domain_id;
+uint32_t pasid;
+int ret = 0;
+
+if ((inv_desc->val[0] & VTD_INV_DESC_PASIDC_RSVD_VAL0) ||
+(inv_desc->val[1] & VTD_INV_DESC_PASIDC_RSVD_VAL1) ||
+(inv_desc->val[2] & VTD_INV_DESC_PASIDC_RSVD_VAL2) ||
+(inv_desc->val[3] & VTD_INV_DESC_PASIDC_RSVD_VAL3)) {
+error_report_once("non-zero-field-in-pc_inv_desc hi: 0x%" PRIx64
+  " lo: 0x%" PRIx64, inv_desc->val[1], inv_desc->val[0]);
+return false;
+}
+
+domain_id = VTD_INV_DESC_PASIDC_DID(inv_desc->val[0]);
+pasid = VTD_INV_DESC_PASIDC_PASID(inv_desc->val[0]);
+
+switch (inv_desc->val[0] & VTD_INV_DESC_PASIDC_G) {
+case VTD_INV_DESC_PASIDC_DSI:
+ret = vtd_pasid_cache_dsi(s, domain_id);
+break;
+
+case VTD_INV_DESC_PASIDC_PASID_SI:
+ret = vtd_pasid_cache_psi(s, domain_id, pasid);
+break;
+
+case VTD_INV_DESC_PASIDC_GLOBAL:
+ret = vtd_pasid_cache_gsi(s);
+break;
+
+default:
+error_report_once("invalid-inv-granu-in-pc_inv_desc hi: 0x%" PRIx64
+  " lo: 0x%" PRIx64, inv_desc->val[1], inv_desc->val[0]);
+return false;
+}
+
+return (ret == 0) ? true : false;
+}
+
 static bool vtd_process_inv_iec_desc(IntelIOMMUState *s,
  VTDInvDesc *inv_desc)
 {
@@ -2499,12 +2556,11 @@ static bool vtd_process_inv_desc(IntelIOMMUState *s)
 }
 break;
 
-/*
- * TODO: the entity of below two cases will be implemented in future 
series.
- * To make guest (which integrates scalable mode support patch set in
- * iommu driver) work, just return true is enough so far.
- */
 case VTD_INV_DESC_PC:
+trace_vtd_inv_desc("pasid-cache", inv_desc.val[1], inv_desc.val[0]);
+if (!vtd_process_pasid_desc(s, _desc)) {
+return false;
+}
 break;
 
 case VTD_INV_DESC_PIOTLB:
diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h
index 1d997a1..0ca5f0b 100644
--- a/hw/i386/intel_iommu_internal.h
+++ b/hw/i386/intel_iommu_internal.h
@@ -444,6 +444,18 @@ typedef union VTDInvDesc VTDInvDesc;
 (0x3800ULL | ~(VTD_HAW_MASK(aw) | VTD_SL_IGN_COM | VTD_SL_TM)) : \
 (0x3800ULL | ~(VTD_HAW_MASK(aw) | VTD_SL_IGN_COM))
 
+#define VTD_INV_DESC_PASIDC_G  (3ULL << 4)
+#define VTD_INV_DESC_PASIDC_PASID(val) (((val) >> 32) & 0xfULL)
+#define VTD_INV_DESC_PASIDC_DID(val)   (((val) >> 16) & VTD_DOMAIN_ID_MASK)
+#define VTD_INV_DESC_PASIDC_RSVD_VAL0  0xfff0ffc0ULL
+#define VTD_INV_DESC_PASIDC_RSVD_VAL1  0xULL
+#define VTD_INV_DESC_PASIDC_RSVD_VAL2  0xULL
+#define VTD_INV_DESC_PASIDC_RSVD_VAL3  0xULL
+
+#define VTD_INV_DESC_PASIDC_DSI(0ULL << 4)
+#define VTD_INV_DESC_PASIDC_PASID_SI   (1ULL << 4)
+#define VTD_INV_DESC_PASIDC_GLOBAL (3ULL << 4)
+
 /* Information about page-selective IOTLB invalidate */
 struct VTDIOTLBPageInvInfo {
 uint16_t domain_id;
diff --git a/hw/i386/trace-events b/hw/i386/trace-events
index 71536a7..f7cd4e5 100644
--- a/hw/i386/trace-events
+++ b/hw/i386/trace-events
@@ -22,6 +22,9 @@ vtd_inv_qi_head(uint16_t head) "read head %d"
 vtd_inv_qi_tail(uint16_t head) "write tail %d"
 vtd_inv_qi_fetch(void) ""
 vtd_context_cache_reset(void) ""
+vtd_pasid_cache_gsi(void) ""
+vtd_pasid_cache_dsi(uint16_t domain) "Domian slective PC invalidation domain 
0x%"PRIx16
+vtd_pasid_cache_psi(uint16_t domain, uint32_t pasid) "PASID slective PC 
invalidation domain 0x%"PRIx16" pasid 0x%"PRIx32

[RFC v3.1 21/22] intel_iommu: process PASID-based Device-TLB invalidation

2020-02-22 Thread Liu Yi L
This patch adds an empty handling for PASID-based Device-TLB
invalidation. For now it is enough as it is not necessary to
propagate it to host for passthru device and also there is no
emulated device has device tlb.

Cc: Kevin Tian 
Cc: Jacob Pan 
Cc: Peter Xu 
Cc: Yi Sun 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Signed-off-by: Liu Yi L 
---
 hw/i386/intel_iommu.c  | 18 ++
 hw/i386/intel_iommu_internal.h |  1 +
 2 files changed, 19 insertions(+)

diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index e6326ef..f5faa75 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -3354,6 +3354,17 @@ static bool vtd_process_inv_iec_desc(IntelIOMMUState *s,
 return true;
 }
 
+static bool vtd_process_device_piotlb_desc(IntelIOMMUState *s,
+   VTDInvDesc *inv_desc)
+{
+/*
+ * no need to handle it for passthru device, for emulated
+ * devices with device tlb, it may be required, but for now,
+ * return is enough
+ */
+return true;
+}
+
 static bool vtd_process_device_iotlb_desc(IntelIOMMUState *s,
   VTDInvDesc *inv_desc)
 {
@@ -3475,6 +3486,13 @@ static bool vtd_process_inv_desc(IntelIOMMUState *s)
 }
 break;
 
+case VTD_INV_DESC_DEV_PIOTLB:
+trace_vtd_inv_desc("device-piotlb", inv_desc.hi, inv_desc.lo);
+if (!vtd_process_device_piotlb_desc(s, _desc)) {
+return false;
+}
+break;
+
 case VTD_INV_DESC_DEVICE:
 trace_vtd_inv_desc("device", inv_desc.hi, inv_desc.lo);
 if (!vtd_process_device_iotlb_desc(s, _desc)) {
diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h
index bd241cb..dfb54fc 100644
--- a/hw/i386/intel_iommu_internal.h
+++ b/hw/i386/intel_iommu_internal.h
@@ -386,6 +386,7 @@ typedef union VTDInvDesc VTDInvDesc;
 #define VTD_INV_DESC_WAIT   0x5 /* Invalidation Wait Descriptor */
 #define VTD_INV_DESC_PIOTLB 0x6 /* PASID-IOTLB Invalidate Desc */
 #define VTD_INV_DESC_PC 0x7 /* PASID-cache Invalidate Desc */
+#define VTD_INV_DESC_DEV_PIOTLB 0x8 /* PASID-based-DIOTLB inv_desc*/
 #define VTD_INV_DESC_NONE   0   /* Not an Invalidate Descriptor */
 
 /* Masks for Invalidation Wait Descriptor*/
-- 
2.7.4




[RFC v3.1 22/22] intel_iommu: modify x-scalable-mode to be string option

2020-02-22 Thread Liu Yi L
Intel VT-d 3.0 introduces scalable mode, and it has a bunch of capabilities
related to scalable mode translation, thus there are multiple combinations.
While this vIOMMU implementation wants simplify it for user by providing
typical combinations. User could config it by "x-scalable-mode" option. The
usage is as below:

"-device intel-iommu,x-scalable-mode=["legacy"|"modern"|"off"]"

 - "legacy": gives support for SL page table
 - "modern": gives support for FL page table, pasid, virtual command
 - "off": no scalable mode support
 -  if not configured, means no scalable mode support, if not proper
configured, will throw error

Note: this patch is supposed to be merged when  the whole vSVA patch series
were merged.

Cc: Kevin Tian 
Cc: Jacob Pan 
Cc: Peter Xu 
Cc: Yi Sun 
Cc: Paolo Bonzini 
Cc: Richard Henderson 
Cc: Eduardo Habkost 
Signed-off-by: Liu Yi L 
Signed-off-by: Yi Sun 
---
 hw/i386/intel_iommu.c  | 29 +++--
 hw/i386/intel_iommu_internal.h |  4 
 include/hw/i386/intel_iommu.h  |  2 ++
 3 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index f5faa75..51b00ee 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -4205,7 +4205,7 @@ static Property vtd_properties[] = {
 DEFINE_PROP_UINT8("aw-bits", IntelIOMMUState, aw_bits,
   VTD_HOST_ADDRESS_WIDTH),
 DEFINE_PROP_BOOL("caching-mode", IntelIOMMUState, caching_mode, FALSE),
-DEFINE_PROP_BOOL("x-scalable-mode", IntelIOMMUState, scalable_mode, FALSE),
+DEFINE_PROP_STRING("x-scalable-mode", IntelIOMMUState, scalable_mode_str),
 DEFINE_PROP_BOOL("dma-drain", IntelIOMMUState, dma_drain, true),
 DEFINE_PROP_END_OF_LIST(),
 };
@@ -4768,8 +4768,12 @@ static void vtd_init(IntelIOMMUState *s)
 }
 
 /* TODO: read cap/ecap from host to decide which cap to be exposed. */
-if (s->scalable_mode) {
+if (s->scalable_mode && !s->scalable_modern) {
 s->ecap |= VTD_ECAP_SMTS | VTD_ECAP_SRS | VTD_ECAP_SLTS;
+} else if (s->scalable_mode && s->scalable_modern) {
+s->ecap |= VTD_ECAP_SMTS | VTD_ECAP_SRS | VTD_ECAP_PASID
+   | VTD_ECAP_FLTS | VTD_ECAP_PSS | VTD_ECAP_VCS;
+s->vccap |= VTD_VCCAP_PAS;
 }
 
 vtd_reset_caches(s);
@@ -4895,6 +4899,27 @@ static bool vtd_decide_config(IntelIOMMUState *s, Error 
**errp)
 return false;
 }
 
+if (s->scalable_mode_str &&
+(strcmp(s->scalable_mode_str, "modern") &&
+ strcmp(s->scalable_mode_str, "legacy"))) {
+error_setg(errp, "Invalid x-scalable-mode config,"
+ "Please use \"modern\", \"legacy\" or \"off\"");
+return false;
+}
+
+if (s->scalable_mode_str &&
+!strcmp(s->scalable_mode_str, "legacy")) {
+s->scalable_mode = true;
+s->scalable_modern = false;
+} else if (s->scalable_mode_str &&
+!strcmp(s->scalable_mode_str, "modern")) {
+s->scalable_mode = true;
+s->scalable_modern = true;
+} else {
+s->scalable_mode = false;
+s->scalable_modern = false;
+}
+
 return true;
 }
 
diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h
index dfb54fc..f7de046 100644
--- a/hw/i386/intel_iommu_internal.h
+++ b/hw/i386/intel_iommu_internal.h
@@ -196,8 +196,12 @@
 #define VTD_ECAP_PT (1ULL << 6)
 #define VTD_ECAP_MHMV   (15ULL << 20)
 #define VTD_ECAP_SRS(1ULL << 31)
+#define VTD_ECAP_PSS(19ULL << 35)
+#define VTD_ECAP_PASID  (1ULL << 40)
 #define VTD_ECAP_SMTS   (1ULL << 43)
+#define VTD_ECAP_VCS(1ULL << 44)
 #define VTD_ECAP_SLTS   (1ULL << 46)
+#define VTD_ECAP_FLTS   (1ULL << 47)
 
 /* CAP_REG */
 /* (offset >> 4) << 24 */
diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
index ff41af0..94ead20 100644
--- a/include/hw/i386/intel_iommu.h
+++ b/include/hw/i386/intel_iommu.h
@@ -259,6 +259,8 @@ struct IntelIOMMUState {
 
 bool caching_mode;  /* RO - is cap CM enabled? */
 bool scalable_mode; /* RO - is Scalable Mode supported? */
+char *scalable_mode_str;/* RO - admin's Scalable Mode config */
+bool scalable_modern;   /* RO - is modern SM supported? */
 
 dma_addr_t root;/* Current root table pointer */
 bool root_scalable; /* Type of root table (scalable or not) */
-- 
2.7.4




[RFC v3.1 00/22] intel_iommu: expose Shared Virtual Addressing to VMs

2020-02-22 Thread Liu Yi L
Shared Virtual Addressing (SVA), a.k.a, Shared Virtual Memory (SVM) on
Intel platforms allows address space sharing between device DMA and
applications. SVA can reduce programming complexity and enhance security.

This QEMU series is intended to expose SVA usage to VMs. i.e. Sharing
guest application address space with passthru devices. This is called
vSVA in this series. The whole vSVA enabling requires QEMU/VFIO/IOMMU
changes. This version is 3.1 to address comments in RFCv3. It is based
on the kernel which can be found in below github. This kernel has some
internal tweak between VFIO and VT-d iommu driver, so it is not sent
out to community review. But the interface between kernel and QEMU are
latest. So I send out this version for review.
https://github.com/luxis1999/linux-vsva: vsva-linux-5.5-rc3-rfcv3.1

The high-level architecture for SVA virtualization is as below, the key
design of vSVA support is to utilize the dual-stage IOMMU translation (
also known as IOMMU nesting translation) capability in host IOMMU.

.-.  .---.
|   vIOMMU|  | Guest process CR3, FL only|
| |  '---'
./
| PASID Entry |--- PASID cache flush -
'-'   |
| |   V
| |CR3 in GPA
'-'
Guest
--| Shadow |--|
  vv  v
Host
.-.  .--.
|   pIOMMU|  | Bind FL for GVA-GPA  |
| |  '--'
./  |
| PASID Entry | V (Nested xlate)
'\.--.
| |   |SL for GPA-HPA, default domain|
| |   '--'
'-'
Where:
 - FL = First level/stage one page tables
 - SL = Second level/stage two page tables

The complete vSVA kernel upstream patches are divided into three phases:
1. Common APIs and PCI device direct assignment
2. IOMMU-backed Mediated Device assignment
3. Page Request Services (PRS) support

This QEMU RFC patchset is aiming for the phase 1 and phase 2.

Related series:
[1] [PATCH V9 00/10] Nested Shared Virtual Address (SVA) VT-d support:
https://lkml.org/lkml/2020/1/29/37
[PATCH 0/3] IOMMU user API enhancement:
https://lkml.org/lkml/2020/1/29/45

[2] [RFC v3 0/8] vfio: expose virtual Shared Virtual Addressing to VMs
https://lkml.org/lkml/2020/1/29/255

There are roughly two parts:
 1. Introduce HostIOMMUContext as abstract of host IOMMU. It provides explicit
method for vIOMMU emulators to communicate with host IOMMU. e.g. propagate
guest page table binding to host IOMMU to setup dual-stage DMA translation
in host IOMMU and flush iommu iotlb.
 2. Setup dual-stage IOMMU translation for Intel vIOMMU. Includes 
- Check IOMMU uAPI version compatibility and VFIO Nesting capabilities which
  includes hardware compatibility (stage 1 format) and VFIO_PASID_REQ
  availability. This is preparation for setting up dual-stage DMA 
translation
  in host IOMMU.
- Propagate guest PASID allocation and free request to host.
- Propagate guest page table binding to host to setup dual-stage IOMMU DMA
  translation in host IOMMU.
- Propagate guest IOMMU cache invalidation to host to ensure iotlb
  correctness.

The complete QEMU set can be found in below link:
https://github.com/luxis1999/qemu.git: sva_qemu_rfcv3.1

Complete kernel can be found in:
https://github.com/luxis1999/linux-vsva.git: vsva-linux-5.5-rc3-rfcv3.1

Tests: basci functionality test, VM reboot/shutdown, full comapilation.
  

Changelog:
- RFC v3 -> v3.1:
  a) Drop IOMMUContext, and rename DualStageIOMMUObject to 
HostIOMMUContext.
 HostIOMMUContext is per-vfio-container, it is exposed to  vIOMMU 
via PCI
 layer. VFIO registers a PCIHostIOMMUFunc callback to PCI layer, 
vIOMMU
 could get HostIOMMUContext instance via it.
  b) Check IOMMU uAPI version by VFIO_CHECK_EXTENSION
  c) Add a check on VFIO_PASID_REQ availability via VFIO_GET_IOMMU_IHNFO
  d) Reorder the series, put vSVA linux header file update in the 
beginning
 put the x-scalable-mode option mofification in the end of the 
series.
  e) Dropped patch "[RFC v3 01/25] hw/pci: modify pci_setup_iommu() to 
set PCIIOMMUOps"
  RFCv3: https://patchwork.kernel.org/cover/11356033/

- RFC v2 -> v3:
  a) Introduce DualStageIOMMUObject to abstract the host IOMMU 
programming
  capability. e.g. request PASID from host, setup IOMMU nesting 
translation
  on host IOMMU. The pasid_alloc/bind_guest_page_table/iommu_cache_flush
  operations are moved to be DualStageIOMMUOps. Thus, 
DualStageIOMMUObject
  is an 

  1   2   >