Re: [Qemu-devel] [PATCH 5/6] tests: Run the iotests during "make check" again

2019-04-24 Thread Thomas Huth
On 24/04/2019 22.42, Wainer dos Santos Moschetta wrote:
> Hi Thomas,
> 
> 
> On 04/24/2019 07:37 AM, Thomas Huth wrote:
>> People often forget to run the iotests before submitting patches or
>> pull requests - this is likely due to the fact that we do not run the
>> tests during our mandatory "make check" tests yet. Now that we've got
>> a new "ci" group of iotests that should be fine to run in every environ-
>> ment, it should be OK to enable the iotests during "make check" again.
>> Thus we now run the "ci" tests by default from the qemu-iotests-quick.sh
>> script, and only use the former "quick" group (that contains some tests
>> that are failing in some environments) when the user decided to run
>> "make check SPEED=thorough" or something similar.
>>
>> Signed-off-by: Thomas Huth 
>> ---
>>   tests/Makefile.include  |  2 +-
>>   tests/qemu-iotests-quick.sh | 17 -
>>   2 files changed, 17 insertions(+), 2 deletions(-)
> 
> One of Patchew's runners failed with this patch series:
> https://patchew.org/QEMU/20190424103747.10173-1-th...@redhat.com/
> 
> I encountered same failures with `make check` locally on Fedora 29
> x86_64 (pulled latest qemu, and configured with defaults and
> x86_64-softmmu target):
> ---
> Not run: 233
> Failures: 069 103 114 133 140 143 197 215 226 244

Ok, thanks for the info. Looks like many tests are failing because qemu-io 
suddenly prints its program name in front of the error messages? E.g.:

--- /tmp/qemu-test/src/tests/qemu-iotests/069.out   2019-04-24 
16:52:31.0 +
+++ /tmp/qemu-test/build/tests/qemu-iotests/069.out.bad 2019-04-24 
16:59:13.310226424 +
@@ -4,5 +4,5 @@
 
 Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=131072
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 
backing_file=TEST_DIR/t.IMGFMT.base
-can't open device TEST_DIR/t.IMGFMT: Could not open backing file: Could not 
open 'TEST_DIR/t.IMGFMT.base': No such file or directory
+qemu-io: can't open device TEST_DIR/t.IMGFMT: Could not open backing file: 
Could not open 'TEST_DIR/t.IMGFMT.base': No such file or directory

Does anybody from the block folks has a clue what might be going wrong here?

 Thomas



[Qemu-devel] [PATCH v3 00/13] tests: acpi: add UEFI (ARM) testing support

2019-04-24 Thread Igor Mammedov
Changelog:
  - from v2:
  * rebase on top current master (with UEFI blobs merged)
  * added a Makefile rule to include bios-tables-test to aarch64 tests by
default into 11/13 (kept Reviewed-bys)
  * other trivial fixes and cleanups (see per patch changelogs)
   
  - from v1:
  * rebase on top
 (1) [PATCH for-4.1 v3 00/12] bundle edk2 platform firmware  with QEMU
let me to drop edk2 images and drop Makefile magic to unpack them,
Laszlo's series conveniently does it all for me.
  * use new path/names for firmware images as supplied by [1]
  * reorder patches a bit so that UEFI parts would go after generic changes

Series adds support for ACPI tables located above 4G. It adds 64-bit handling
necessary for testing arm/virt board (i.e. might be not complete wrt spec) and
uses recently merged UEFI (AVMF) firmware/test disk image which provides
an entry point[1] for fetching ACPI tables (RSDP pointer).

Git tree for testing:
   https://github.com/imammedo/qemu.git acpi_arm_tests_v3

Ref to previos vesrsion:
   [Qemu-devel] [PATCH for 4.1 v2 00/13] tests: acpi: add UEFI (ARM) testing 
support
   https://www.mail-archive.com/qemu-devel@nongnu.org/msg607564.html

CC: Laszlo Ersek 
CC: "Michael S. Tsirkin" 
CC: Gonglei 
CC: Philippe Mathieu-Daudé 
CC: Shannon Zhao 
CC: Wei Yang 
CC: Andrew Jones 
CC: Shameer Kolothum 
CC: Ben Warren 

Igor Mammedov (13):
  tests: acpi: make RSDT test routine handle XSDT
  tests: acpi: rename acpi_parse_rsdp_table() into
acpi_fetch_rsdp_table()
  tests: acpi: make pointer to RSDP 64bit
  tests: acpi: fetch X_DSDT if pointer to DSDT is 0
  tests: acpi: skip FACS table if board uses hw reduced ACPI profile
  tests: acpi: move boot_sector_init() into x86 tests branch
  tests: acpi: add acpi_find_rsdp_address_uefi() helper
  tests: acpi: add a way to start tests with UEFI firmware
  tests: acpi: ignore SMBIOS tests when UEFI firmware is used
  tests: add expected ACPI tables for arm/virt board
  tests: acpi: add simple arm/virt testcase
  tests: acpi: refactor rebuild-expected-aml.sh to dump ACPI tables for
a specified list of targets
  tests: acpi: print error unable to dump ACPI table during rebuild

 tests/acpi-utils.h  |   5 +-
 tests/Makefile.include  |   1 +
 tests/acpi-utils.c  |  58 ++
 tests/bios-tables-test.c| 133 
 tests/data/acpi/rebuild-expected-aml.sh |  23 +++---
 tests/data/acpi/virt/APIC   | Bin 0 -> 168 bytes
 tests/data/acpi/virt/DSDT   | Bin 0 -> 18476 bytes
 tests/data/acpi/virt/FACP   | Bin 0 -> 268 bytes
 tests/data/acpi/virt/GTDT   | Bin 0 -> 96 bytes
 tests/data/acpi/virt/MCFG   | Bin 0 -> 60 bytes
 tests/data/acpi/virt/SPCR   | Bin 0 -> 80 bytes
 tests/vmgenid-test.c|   2 +-
 12 files changed, 162 insertions(+), 60 deletions(-)
 create mode 100644 tests/data/acpi/virt/APIC
 create mode 100644 tests/data/acpi/virt/DSDT
 create mode 100644 tests/data/acpi/virt/FACP
 create mode 100644 tests/data/acpi/virt/GTDT
 create mode 100644 tests/data/acpi/virt/MCFG
 create mode 100644 tests/data/acpi/virt/SPCR

-- 
2.7.4




[Qemu-devel] [PATCH v3 02/13] tests: acpi: rename acpi_parse_rsdp_table() into acpi_fetch_rsdp_table()

2019-04-24 Thread Igor Mammedov
so name would reflect what the function does

Signed-off-by: Igor Mammedov 
Reviewed-by: Philippe Mathieu-Daudé 
---
 tests/acpi-utils.h   | 2 +-
 tests/acpi-utils.c   | 2 +-
 tests/bios-tables-test.c | 2 +-
 tests/vmgenid-test.c | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/tests/acpi-utils.h b/tests/acpi-utils.h
index 8c68201..75f78f2 100644
--- a/tests/acpi-utils.h
+++ b/tests/acpi-utils.h
@@ -46,7 +46,7 @@ typedef struct {
 
 uint8_t acpi_calc_checksum(const uint8_t *data, int len);
 uint32_t acpi_find_rsdp_address(QTestState *qts);
-void acpi_parse_rsdp_table(QTestState *qts, uint64_t addr, uint8_t 
*rsdp_table);
+void acpi_fetch_rsdp_table(QTestState *qts, uint64_t addr, uint8_t 
*rsdp_table);
 void acpi_fetch_table(QTestState *qts, uint8_t **aml, uint32_t *aml_len,
   const uint8_t *addr_ptr, const char *sig,
   bool verify_checksum);
diff --git a/tests/acpi-utils.c b/tests/acpi-utils.c
index 9a6d1d3..2dd4fe0 100644
--- a/tests/acpi-utils.c
+++ b/tests/acpi-utils.c
@@ -51,7 +51,7 @@ uint32_t acpi_find_rsdp_address(QTestState *qts)
 return off;
 }
 
-void acpi_parse_rsdp_table(QTestState *qts, uint64_t addr, uint8_t *rsdp_table)
+void acpi_fetch_rsdp_table(QTestState *qts, uint64_t addr, uint8_t *rsdp_table)
 {
 uint8_t revision;
 
diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c
index 24bd102..2ee044c 100644
--- a/tests/bios-tables-test.c
+++ b/tests/bios-tables-test.c
@@ -89,7 +89,7 @@ static void test_acpi_rsdp_table(test_data *data)
 uint8_t *rsdp_table = data->rsdp_table, revision;
 uint32_t addr = data->rsdp_addr;
 
-acpi_parse_rsdp_table(data->qts, addr, rsdp_table);
+acpi_fetch_rsdp_table(data->qts, addr, rsdp_table);
 revision = rsdp_table[15 /* Revision offset */];
 
 switch (revision) {
diff --git a/tests/vmgenid-test.c b/tests/vmgenid-test.c
index ae38ee5..f400184 100644
--- a/tests/vmgenid-test.c
+++ b/tests/vmgenid-test.c
@@ -40,7 +40,7 @@ static uint32_t acpi_find_vgia(QTestState *qts)
 g_assert_cmphex(rsdp_offset, <, RSDP_ADDR_INVALID);
 
 
-acpi_parse_rsdp_table(qts, rsdp_offset, rsdp_table);
+acpi_fetch_rsdp_table(qts, rsdp_offset, rsdp_table);
 acpi_fetch_table(qts, , _len, _table[16 /* RsdtAddress */],
  "RSDT", true);
 
-- 
2.7.4




[Qemu-devel] [PATCH v3 03/13] tests: acpi: make pointer to RSDP 64bit

2019-04-24 Thread Igor Mammedov
In case of UEFI, RSDP doesn't have to be located in lowmem,
it could be placed at any address. Make sure that test won't
break if it is placed above the first 4Gb of address space.

PS:
While at it cleanup some local variables as we don't really
need them.

Signed-off-by: Igor Mammedov 
Reviewed-by: Philippe Mathieu-Daudé 
---
v2:
  - s/In case of UEFI/In case of UEFI,/ (Laszlo Ersek )
---
 tests/bios-tables-test.c | 10 --
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c
index 2ee044c..c29dcf4 100644
--- a/tests/bios-tables-test.c
+++ b/tests/bios-tables-test.c
@@ -26,7 +26,7 @@
 typedef struct {
 const char *machine;
 const char *variant;
-uint32_t rsdp_addr;
+uint64_t rsdp_addr;
 uint8_t rsdp_table[36 /* ACPI 2.0+ RSDP size */];
 GArray *tables;
 uint32_t smbios_ep_addr;
@@ -86,13 +86,11 @@ static void test_acpi_rsdp_address(test_data *data)
 
 static void test_acpi_rsdp_table(test_data *data)
 {
-uint8_t *rsdp_table = data->rsdp_table, revision;
-uint32_t addr = data->rsdp_addr;
+uint8_t *rsdp_table = data->rsdp_table;
 
-acpi_fetch_rsdp_table(data->qts, addr, rsdp_table);
-revision = rsdp_table[15 /* Revision offset */];
+acpi_fetch_rsdp_table(data->qts, data->rsdp_addr, rsdp_table);
 
-switch (revision) {
+switch (rsdp_table[15 /* Revision offset */]) {
 case 0: /* ACPI 1.0 RSDP */
 /* With rev 1, checksum is only for the first 20 bytes */
 g_assert(!acpi_calc_checksum(rsdp_table,  20));
-- 
2.7.4




[Qemu-devel] [PATCH v3 07/13] tests: acpi: add acpi_find_rsdp_address_uefi() helper

2019-04-24 Thread Igor Mammedov
introduce UEFI specific counterpart to acpi_find_rsdp_address()
that will help to find RSDP address when [OA]VMF is used as
firmware. It requires guest firmware or other guest app to place
1Mb aligned UefiTestSupport structure (defined in this patch)
in RAM with UefiTestSupport::signature_guid set to
AB87A6B1-2034-BDA0-71BD-375007757785

Signed-off-by: Igor Mammedov 
Reviewed-by: Laszlo Ersek 
---
v3:
  * fix checkpatch error (separate opening brace from values in 
AcpiTestSupportGuid initializer)
v2:
  * Laszlo Ersek 
- s/uefi_find_rsdp_addr/acpi_find_rsdp_address_uefi/
- use GUID_SIZE instead of opencodding size
- make AcpiTestSupportGuid const
- s/TCI/TCG/
---
 tests/acpi-utils.h |  2 ++
 tests/acpi-utils.c | 44 
 2 files changed, 46 insertions(+)

diff --git a/tests/acpi-utils.h b/tests/acpi-utils.h
index 75f78f2..dcfa721 100644
--- a/tests/acpi-utils.h
+++ b/tests/acpi-utils.h
@@ -46,6 +46,8 @@ typedef struct {
 
 uint8_t acpi_calc_checksum(const uint8_t *data, int len);
 uint32_t acpi_find_rsdp_address(QTestState *qts);
+uint64_t acpi_find_rsdp_address_uefi(QTestState *qts, uint64_t start,
+ uint64_t size);
 void acpi_fetch_rsdp_table(QTestState *qts, uint64_t addr, uint8_t 
*rsdp_table);
 void acpi_fetch_table(QTestState *qts, uint8_t **aml, uint32_t *aml_len,
   const uint8_t *addr_ptr, const char *sig,
diff --git a/tests/acpi-utils.c b/tests/acpi-utils.c
index 2dd4fe0..197af82 100644
--- a/tests/acpi-utils.c
+++ b/tests/acpi-utils.c
@@ -99,3 +99,47 @@ void acpi_fetch_table(QTestState *qts, uint8_t **aml, 
uint32_t *aml_len,
 g_assert(!acpi_calc_checksum(*aml, *aml_len));
 }
 }
+
+#define GUID_SIZE 16
+static const uint8_t AcpiTestSupportGuid[GUID_SIZE] = {
+   0xb1, 0xa6, 0x87, 0xab,
+   0x34, 0x20,
+   0xa0, 0xbd,
+   0x71, 0xbd, 0x37, 0x50, 0x07, 0x75, 0x77, 0x85 };
+
+typedef struct {
+uint8_t signature_guid[GUID_SIZE];
+uint64_t rsdp10;
+uint64_t rsdp20;
+} __attribute__((packed)) UefiTestSupport;
+
+/* Wait at most 600 seconds (test is slow with TCG and --enable-debug) */
+#define TEST_DELAY (1 * G_USEC_PER_SEC / 10)
+#define TEST_CYCLES MAX((600 * G_USEC_PER_SEC / TEST_DELAY), 1)
+#define MB 0x10ULL
+uint64_t acpi_find_rsdp_address_uefi(QTestState *qts, uint64_t start,
+ uint64_t size)
+{
+int i, j;
+uint8_t data[GUID_SIZE];
+
+for (i = 0; i < TEST_CYCLES; ++i) {
+for (j = 0; j < size / MB; j++) {
+/* look for GUID at every 1Mb block */
+uint64_t addr = start + j * MB;
+
+qtest_memread(qts, addr, data, sizeof(data));
+if (!memcmp(AcpiTestSupportGuid, data, sizeof(data))) {
+UefiTestSupport ret;
+
+qtest_memread(qts, addr, , sizeof(ret));
+ret.rsdp10 = le64_to_cpu(ret.rsdp10);
+ret.rsdp20 = le64_to_cpu(ret.rsdp20);
+return ret.rsdp20 ? ret.rsdp20 : ret.rsdp10;
+}
+}
+g_usleep(TEST_DELAY);
+}
+g_assert_not_reached();
+return 0;
+}
-- 
2.7.4




Re: [Qemu-devel] [PATCH for-4.1 1/8] target/riscv: Name the argument sets for all of insn32 formats

2019-04-24 Thread Aleksandar Markovic
On Apr 25, 2019 7:17 AM, "Richard Henderson" 
wrote:
>
> On 4/24/19 8:31 PM, Palmer Dabbelt wrote:
> >>  # Argument sets:
> >> +
> >
> > If I understand decodetree correctly, this isn't used until patch 5.
> > Otherwise,
> >
>
> I think it's used as early as patch 3, but I haven't looked in detail to
be sure.
>
>
> r~
>

I think it is a very bad practice to leave the commit message empty, and,
in my view, the long-time contributor, like you, Richard, have the
obligation to always give examples of commit messages of good quality.
Leaving empty commit messages should not be a ”privelage” that comes with
seniority, IMHO. On the contrary.

Sincerely,
Aleksandar


[Qemu-devel] [PATCH v3 01/13] tests: acpi: make RSDT test routine handle XSDT

2019-04-24 Thread Igor Mammedov
If RSDP revision is more than 0 fetch table pointed by XSDT
and fallback to legacy RSDT table otherwise.

While at it drop unused acpi_get_xsdt_address().

Signed-off-by: Igor Mammedov 
---
PS:
 it doesn't affect existing pc/q35 machines as they use RSDP.revision == 0
 but it will be used by followup patch to enable testing arm/virt
 board which uses provides XSDT table.
---
 tests/acpi-utils.h   |  3 +--
 tests/acpi-utils.c   | 14 +-
 tests/bios-tables-test.c | 18 +-
 3 files changed, 15 insertions(+), 20 deletions(-)

diff --git a/tests/acpi-utils.h b/tests/acpi-utils.h
index ef388bb..8c68201 100644
--- a/tests/acpi-utils.h
+++ b/tests/acpi-utils.h
@@ -46,8 +46,7 @@ typedef struct {
 
 uint8_t acpi_calc_checksum(const uint8_t *data, int len);
 uint32_t acpi_find_rsdp_address(QTestState *qts);
-uint64_t acpi_get_xsdt_address(uint8_t *rsdp_table);
-void acpi_parse_rsdp_table(QTestState *qts, uint32_t addr, uint8_t 
*rsdp_table);
+void acpi_parse_rsdp_table(QTestState *qts, uint64_t addr, uint8_t 
*rsdp_table);
 void acpi_fetch_table(QTestState *qts, uint8_t **aml, uint32_t *aml_len,
   const uint8_t *addr_ptr, const char *sig,
   bool verify_checksum);
diff --git a/tests/acpi-utils.c b/tests/acpi-utils.c
index cc33b46..9a6d1d3 100644
--- a/tests/acpi-utils.c
+++ b/tests/acpi-utils.c
@@ -51,19 +51,7 @@ uint32_t acpi_find_rsdp_address(QTestState *qts)
 return off;
 }
 
-uint64_t acpi_get_xsdt_address(uint8_t *rsdp_table)
-{
-uint64_t xsdt_physical_address;
-uint8_t revision = rsdp_table[15 /* Revision offset */];
-
-/* We must have revision 2 if we're looking for an XSDT pointer */
-g_assert(revision == 2);
-
-memcpy(_physical_address, _table[24 /* XsdtAddress offset */], 
8);
-return le64_to_cpu(xsdt_physical_address);
-}
-
-void acpi_parse_rsdp_table(QTestState *qts, uint32_t addr, uint8_t *rsdp_table)
+void acpi_parse_rsdp_table(QTestState *qts, uint64_t addr, uint8_t *rsdp_table)
 {
 uint8_t revision;
 
diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c
index a506dcb..24bd102 100644
--- a/tests/bios-tables-test.c
+++ b/tests/bios-tables-test.c
@@ -107,17 +107,25 @@ static void test_acpi_rsdp_table(test_data *data)
 }
 }
 
-static void test_acpi_rsdt_table(test_data *data)
+static void test_acpi_rxsdt_table(test_data *data)
 {
+const char *sig = "RSDT";
 AcpiSdtTable rsdt = {};
+int entry_size = 4;
+int addr_off = 16 /* RsdtAddress */;
 uint8_t *ent;
 
-/* read RSDT table */
+if (data->rsdp_table[15 /* Revision offset */] != 0) {
+addr_off = 24 /* XsdtAddress */;
+entry_size = 8;
+sig = "XSDT";
+}
+/* read [RX]SDT table */
 acpi_fetch_table(data->qts, , _len,
- >rsdp_table[16 /* RsdtAddress */], "RSDT", true);
+ >rsdp_table[addr_off], sig, true);
 
 /* Load all tables and add to test list directly RSDT referenced tables */
-ACPI_FOREACH_RSDT_ENTRY(rsdt.aml, rsdt.aml_len, ent, 4 /* Entry size */) {
+ACPI_FOREACH_RSDT_ENTRY(rsdt.aml, rsdt.aml_len, ent, entry_size) {
 AcpiSdtTable ssdt_table = {};
 
 acpi_fetch_table(data->qts, _table.aml, _table.aml_len, ent,
@@ -521,7 +529,7 @@ static void test_acpi_one(const char *params, test_data 
*data)
 data->tables = g_array_new(false, true, sizeof(AcpiSdtTable));
 test_acpi_rsdp_address(data);
 test_acpi_rsdp_table(data);
-test_acpi_rsdt_table(data);
+test_acpi_rxsdt_table(data);
 test_acpi_fadt_table(data);
 
 if (iasl) {
-- 
2.7.4




[Qemu-devel] [PATCH v3 09/13] tests: acpi: ignore SMBIOS tests when UEFI firmware is used

2019-04-24 Thread Igor Mammedov
once FW provides a pointer to SMBIOS entry point like it does for
RSDP it should be possible to enable this one the same way.

Signed-off-by: Igor Mammedov 
Reviewed-by: Laszlo Ersek 
---
v3:
  - add ref to a uefi-test-tools feature req into comment (Laszlo)
---
 tests/bios-tables-test.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c
index 0f24540..1be55a1 100644
--- a/tests/bios-tables-test.c
+++ b/tests/bios-tables-test.c
@@ -573,8 +573,15 @@ static void test_acpi_one(const char *params, test_data 
*data)
 }
 }
 
-test_smbios_entry_point(data);
-test_smbios_structs(data);
+/*
+ * TODO: make SMBIOS tests work with UEFI firmware,
+ * Bug on uefi-test-tools to provide entry point:
+ * https://bugs.launchpad.net/qemu/+bug/1821884
+ */
+if (!use_uefi) {
+test_smbios_entry_point(data);
+test_smbios_structs(data);
+}
 
 assert(!global_qtest);
 qtest_quit(data->qts);
-- 
2.7.4




[Qemu-devel] [PATCH v3 04/13] tests: acpi: fetch X_DSDT if pointer to DSDT is 0

2019-04-24 Thread Igor Mammedov
that way it would be possible to test a DSDT pointed by
64bit X_DSDT field in FADT.

PS:
it will allow to enable testing arm/virt board, which sets
only newer X_DSDT field.

Signed-off-by: Igor Mammedov 
Reviewed-by: Philippe Mathieu-Daudé 
---
v2:
  add 'val = le32_to_cpu(val)' even if it doesn't necessary
  it works as reminder that value copied from table is in
  little-endian format (Philippe Mathieu-Daudé )
---
 tests/bios-tables-test.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c
index c29dcf4..ed62a17 100644
--- a/tests/bios-tables-test.c
+++ b/tests/bios-tables-test.c
@@ -140,6 +140,8 @@ static void test_acpi_fadt_table(test_data *data)
 AcpiSdtTable table = g_array_index(data->tables, typeof(table), 0);
 uint8_t *fadt_aml = table.aml;
 uint32_t fadt_len = table.aml_len;
+uint32_t val;
+int dsdt_offset = 40 /* DSDT */;
 
 g_assert(compare_signature(, "FACP"));
 
@@ -148,8 +150,13 @@ static void test_acpi_fadt_table(test_data *data)
  fadt_aml + 36 /* FIRMWARE_CTRL */, "FACS", false);
 g_array_append_val(data->tables, table);
 
+memcpy(, fadt_aml + dsdt_offset, 4);
+val = le32_to_cpu(val);
+if (!val) {
+dsdt_offset = 140 /* X_DSDT */;
+}
 acpi_fetch_table(data->qts, , _len,
- fadt_aml + 40 /* DSDT */, "DSDT", true);
+ fadt_aml + dsdt_offset, "DSDT", true);
 g_array_append_val(data->tables, table);
 
 memset(fadt_aml + 36, 0, 4); /* sanitize FIRMWARE_CTRL ptr */
-- 
2.7.4




[Qemu-devel] [PATCH v3 05/13] tests: acpi: skip FACS table if board uses hw reduced ACPI profile

2019-04-24 Thread Igor Mammedov
If FADT has HW_REDUCED_ACPI flag set, do not attempt to fetch
FACS as it's not provided by the board.

Signed-off-by: Igor Mammedov 
Reviewed-by: Philippe Mathieu-Daudé 
---
 tests/bios-tables-test.c | 10 +++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c
index ed62a17..e944d00 100644
--- a/tests/bios-tables-test.c
+++ b/tests/bios-tables-test.c
@@ -146,9 +146,13 @@ static void test_acpi_fadt_table(test_data *data)
 g_assert(compare_signature(, "FACP"));
 
 /* Since DSDT/FACS isn't in RSDT, add them to ASL test list manually */
-acpi_fetch_table(data->qts, , _len,
- fadt_aml + 36 /* FIRMWARE_CTRL */, "FACS", false);
-g_array_append_val(data->tables, table);
+memcpy(, fadt_aml + 112 /* Flags */, 4);
+val = le32_to_cpu(val);
+if (!(val & 1UL << 20 /* HW_REDUCED_ACPI */)) {
+acpi_fetch_table(data->qts, , _len,
+ fadt_aml + 36 /* FIRMWARE_CTRL */, "FACS", false);
+g_array_append_val(data->tables, table);
+}
 
 memcpy(, fadt_aml + dsdt_offset, 4);
 val = le32_to_cpu(val);
-- 
2.7.4




[Qemu-devel] [PATCH v3 11/13] tests: acpi: add simple arm/virt testcase

2019-04-24 Thread Igor Mammedov
adds simple arm/virt test case that starts guest with
bios-tables-test.aarch64.iso.qcow2 boot image which
initializes UefiTestSupport* structure in RAM once
guest is booted.

 * see commit: tests: acpi: add acpi_find_rsdp_address_uefi() helper

Signed-off-by: Igor Mammedov 
Reviewed-by: Laszlo Ersek 
Reviewed-by: Philippe Mathieu-Daudé 
---
v3:
  * use firmware blobs directly from pc-bios directory
  * use bios-tables-test.aarch64.iso.qcow2 as test boot image
  * drop leftover qtest-uefi-images-aarch64 iMakefile rule from
previos version (Laszlo)
  * add Makefile rule to include bios-tables-test into
check-qtest-aarch64 target
v2:
  * specify in test_data where board's RAM starts and RAM size
---
 tests/Makefile.include   |  1 +
 tests/bios-tables-test.c | 17 +
 2 files changed, 18 insertions(+)

diff --git a/tests/Makefile.include b/tests/Makefile.include
index e2432d5..983c8b1 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -267,6 +267,7 @@ check-qtest-arm-y += tests/hexloader-test$(EXESUF)
 check-qtest-aarch64-y = tests/numa-test$(EXESUF)
 check-qtest-aarch64-y += tests/boot-serial-test$(EXESUF)
 check-qtest-aarch64-y += tests/migration-test$(EXESUF)
+check-qtest-aarch64-y += tests/bios-tables-test$(EXESUF)
 
 check-qtest-microblazeel-y += $(check-qtest-microblaze-y)
 
diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c
index 1be55a1..f117461 100644
--- a/tests/bios-tables-test.c
+++ b/tests/bios-tables-test.c
@@ -812,6 +812,21 @@ static void test_acpi_piix4_tcg_dimm_pxm(void)
 test_acpi_tcg_dimm_pxm(MACHINE_PC);
 }
 
+static void test_acpi_virt_tcg(void)
+{
+test_data data = {
+.machine = "virt",
+.uefi_fl1 = "pc-bios/edk2-aarch64-code.fd",
+.uefi_fl2 = "pc-bios/edk2-arm-vars.fd",
+.cd = "tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2",
+.ram_start = 0x4000ULL,
+.scan_len = 128ULL * 1024 * 1024,
+};
+
+test_acpi_one("-cpu cortex-a57 ", );
+free_test_data();
+}
+
 int main(int argc, char *argv[])
 {
 const char *arch = qtest_get_arch();
@@ -840,6 +855,8 @@ int main(int argc, char *argv[])
 qtest_add_func("acpi/q35/numamem", test_acpi_q35_tcg_numamem);
 qtest_add_func("acpi/piix4/dimmpxm", test_acpi_piix4_tcg_dimm_pxm);
 qtest_add_func("acpi/q35/dimmpxm", test_acpi_q35_tcg_dimm_pxm);
+} else if (strcmp(arch, "aarch64") == 0) {
+qtest_add_func("acpi/virt", test_acpi_virt_tcg);
 }
 ret = g_test_run();
 boot_sector_cleanup(disk);
-- 
2.7.4




[Qemu-devel] [PATCH v3 06/13] tests: acpi: move boot_sector_init() into x86 tests branch

2019-04-24 Thread Igor Mammedov
boot_sector_init() won't be used by arm/virt board, so move it from
global scope to x86 branch that uses it.

Signed-off-by: Igor Mammedov 
Reviewed-by: Philippe Mathieu-Daudé 
---
v3:
  - fix checkpatch errors triggered by moved old code (ident/space/braces)
---
 tests/bios-tables-test.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c
index e944d00..5790ee4 100644
--- a/tests/bios-tables-test.c
+++ b/tests/bios-tables-test.c
@@ -786,13 +786,14 @@ int main(int argc, char *argv[])
 const char *arch = qtest_get_arch();
 int ret;
 
-ret = boot_sector_init(disk);
-if(ret)
-return ret;
-
 g_test_init(, , NULL);
 
 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
+ret = boot_sector_init(disk);
+if (ret) {
+return ret;
+}
+
 qtest_add_func("acpi/piix4", test_acpi_piix4_tcg);
 qtest_add_func("acpi/piix4/bridge", test_acpi_piix4_tcg_bridge);
 qtest_add_func("acpi/q35", test_acpi_q35_tcg);
-- 
2.7.4




[Qemu-devel] [PATCH v3 08/13] tests: acpi: add a way to start tests with UEFI firmware

2019-04-24 Thread Igor Mammedov
For testcase to use UEFI firmware, one needs to provide and specify
firmwarei and varstore blobs names in test_data { uefi_fl1, uefi_fl2) }
fields respectively and RAM start address plus size where to look for
test structure signature. Additionally testcase should specify
bootable cdrom image uefi-boot-images EFI test utility.

Signed-off-by: Igor Mammedov 
Reviewed-by: Laszlo Ersek 
---
v3:
  * drop data_dir prefix and firmware will come from pc-bios directly
  * add cdrom option so test could use it for providing boot cdrom image
  * add TODO comment convert '-drive if=pflash' to new syntax (Laszlo)
v2:
  * move RAM start address and size to test_data, as it could differ
between boards (and even versions)
---
 tests/bios-tables-test.c | 44 ++--
 1 file changed, 34 insertions(+), 10 deletions(-)

diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c
index 5790ee4..0f24540 100644
--- a/tests/bios-tables-test.c
+++ b/tests/bios-tables-test.c
@@ -26,6 +26,11 @@
 typedef struct {
 const char *machine;
 const char *variant;
+const char *uefi_fl1;
+const char *uefi_fl2;
+const char *cd;
+const uint64_t ram_start;
+const uint64_t scan_len;
 uint64_t rsdp_addr;
 uint8_t rsdp_table[36 /* ACPI 2.0+ RSDP size */];
 GArray *tables;
@@ -522,21 +527,40 @@ static void test_smbios_structs(test_data *data)
 static void test_acpi_one(const char *params, test_data *data)
 {
 char *args;
-
-/* Disable kernel irqchip to be able to override apic irq0. */
-args = g_strdup_printf("-machine %s,accel=%s,kernel-irqchip=off "
-   "-net none -display none %s "
-   "-drive id=hd0,if=none,file=%s,format=raw "
-   "-device ide-hd,drive=hd0 ",
-   data->machine, "kvm:tcg",
-   params ? params : "", disk);
+bool use_uefi = data->uefi_fl1 && data->uefi_fl2;
+
+if (use_uefi) {
+/*
+ * TODO: convert '-drive if=pflash' to new syntax (see e33763be7cd3)
+ * when arm/virt boad starts to support it.
+ */
+args = g_strdup_printf("-machine %s,accel=%s -nodefaults -nographic "
+"-drive if=pflash,format=raw,file=%s,readonly "
+"-drive if=pflash,format=raw,file=%s,snapshot=on -cdrom %s %s",
+data->machine, "kvm:tcg", data->uefi_fl1, data->uefi_fl2,
+data->cd, params ? params : "");
+
+} else {
+/* Disable kernel irqchip to be able to override apic irq0. */
+args = g_strdup_printf("-machine %s,accel=%s,kernel-irqchip=off "
+"-net none -display none %s "
+"-drive id=hd0,if=none,file=%s,format=raw "
+"-device ide-hd,drive=hd0 ",
+ data->machine, "kvm:tcg", params ? params : "", disk);
+}
 
 data->qts = qtest_init(args);
 
-boot_sector_test(data->qts);
+if (use_uefi) {
+g_assert(data->scan_len);
+data->rsdp_addr = acpi_find_rsdp_address_uefi(data->qts,
+data->ram_start, data->scan_len);
+} else {
+boot_sector_test(data->qts);
+test_acpi_rsdp_address(data);
+}
 
 data->tables = g_array_new(false, true, sizeof(AcpiSdtTable));
-test_acpi_rsdp_address(data);
 test_acpi_rsdp_table(data);
 test_acpi_rxsdt_table(data);
 test_acpi_fadt_table(data);
-- 
2.7.4




[Qemu-devel] [PATCH v3 13/13] tests: acpi: print error unable to dump ACPI table during rebuild

2019-04-24 Thread Igor Mammedov
Instead of just asserting print the error that lead to assert first.
While at it move assert into rebuild branch, which removes reduntant
check done in case of !rebuild branch is taken (the later is taken
care of by g_assert_no_error).

Signed-off-by: Igor Mammedov 
---
 tests/bios-tables-test.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c
index f117461..5a5d036 100644
--- a/tests/bios-tables-test.c
+++ b/tests/bios-tables-test.c
@@ -199,11 +199,14 @@ static void dump_aml_files(test_data *data, bool rebuild)
sdt->aml, ext);
 fd = g_open(aml_file, O_WRONLY|O_TRUNC|O_CREAT,
 S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
+if (fd < 0) {
+perror(aml_file);
+}
+g_assert(fd >= 0);
 } else {
 fd = g_file_open_tmp("aml-XX", >aml_file, );
 g_assert_no_error(error);
 }
-g_assert(fd >= 0);
 
 ret = qemu_write_full(fd, sdt->aml, sdt->aml_len);
 g_assert(ret == sdt->aml_len);
-- 
2.7.4




[Qemu-devel] [PATCH v3 12/13] tests: acpi: refactor rebuild-expected-aml.sh to dump ACPI tables for a specified list of targets

2019-04-24 Thread Igor Mammedov
Make initial list contain aarch64 and x86_64 targets.

Signed-off-by: Igor Mammedov 
Reviewed-by: Philippe Mathieu-Daudé 
---
v2:
 * fix up error message (Philippe Mathieu-Daudé )
---
 tests/data/acpi/rebuild-expected-aml.sh | 23 +++
 1 file changed, 11 insertions(+), 12 deletions(-)

diff --git a/tests/data/acpi/rebuild-expected-aml.sh 
b/tests/data/acpi/rebuild-expected-aml.sh
index abdff70..52793f3 100755
--- a/tests/data/acpi/rebuild-expected-aml.sh
+++ b/tests/data/acpi/rebuild-expected-aml.sh
@@ -7,21 +7,12 @@
 #
 # Authors:
 #  Marcel Apfelbaum 
+#  Igor Mammedov 
 #
 # This work is licensed under the terms of the GNU GPLv2.
 # See the COPYING.LIB file in the top-level directory.
 
-qemu=
-
-if [ -e x86_64-softmmu/qemu-system-x86_64 ]; then
-qemu="x86_64-softmmu/qemu-system-x86_64"
-elif [ -e i386-softmmu/qemu-system-i386 ]; then
-qemu="i386-softmmu/qemu-system-i386"
-else
-echo "Run 'make' to build the qemu exectutable!"
-echo "Run this script from the build directory."
-exit 1;
-fi
+qemu_bins="aarch64-softmmu/qemu-system-aarch64 
x86_64-softmmu/qemu-system-x86_64"
 
 if [ ! -e "tests/bios-tables-test" ]; then
 echo "Test: bios-tables-test is required! Run make check before this 
script."
@@ -29,6 +20,14 @@ if [ ! -e "tests/bios-tables-test" ]; then
 exit 1;
 fi
 
-TEST_ACPI_REBUILD_AML=y QTEST_QEMU_BINARY=$qemu tests/bios-tables-test
+for qemu in $qemu_bins; do
+if [ ! -e $qemu ]; then
+echo "Run 'make' to build the following QEMU exectutables: $qemu_bins"
+echo "Also, run this script from the build directory."
+exit 1;
+fi
+TEST_ACPI_REBUILD_AML=y QTEST_QEMU_BINARY=$qemu tests/bios-tables-test
+done
+
 
 echo "The files were rebuilt and can be added to git."
-- 
2.7.4




[Qemu-devel] [PATCH v3 10/13] tests: add expected ACPI tables for arm/virt board

2019-04-24 Thread Igor Mammedov
Signed-off-by: Igor Mammedov 
---
this patch is ahead fo "tests: acpi: add simple  arm/virt testcase"
to keep 'make check' working during bisection and not to pollute
code with binary blobs which are not reviewable.
---
 tests/data/acpi/virt/APIC | Bin 0 -> 168 bytes
 tests/data/acpi/virt/DSDT | Bin 0 -> 18476 bytes
 tests/data/acpi/virt/FACP | Bin 0 -> 268 bytes
 tests/data/acpi/virt/GTDT | Bin 0 -> 96 bytes
 tests/data/acpi/virt/MCFG | Bin 0 -> 60 bytes
 tests/data/acpi/virt/SPCR | Bin 0 -> 80 bytes
 6 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 tests/data/acpi/virt/APIC
 create mode 100644 tests/data/acpi/virt/DSDT
 create mode 100644 tests/data/acpi/virt/FACP
 create mode 100644 tests/data/acpi/virt/GTDT
 create mode 100644 tests/data/acpi/virt/MCFG
 create mode 100644 tests/data/acpi/virt/SPCR

diff --git a/tests/data/acpi/virt/APIC b/tests/data/acpi/virt/APIC
new file mode 100644
index 
..797dfde2841c51b7e72065602e99ce1714347f0d
GIT binary patch
literal 168
zcmZ<^@N{0mz`($~*~#D8BUr=ZD8>jB1F=Cg4Dd+6SPUF6788)c?E~X6Fu>G{
hBZPn~MyPrgD9sGlkD?67;f3451Xcqw(L;0RYV=2>}2A

literal 0
HcmV?d1

diff --git a/tests/data/acpi/virt/DSDT b/tests/data/acpi/virt/DSDT
new file mode 100644
index 
..20e85c7f89f645c69935c615c07084e221419960
GIT binary patch
literal 18476
zcmc)ScU)EVAII^7km3at6myGa+R|dUS|(gjDG>rqi;BuJN5jfYEla7?tSq%Xt!(eT
zr!AYd_uhN&!S8+U(D&=t`StIw9$oH>d%mB0pK#D~*=*uql2K;?26j>=!V`E
z6YJuY`dmg31mXSgWB#J~S-UqiR5Udjdl!92h)D&$WWX;hthf7M5uZl}Dl25#TNmhEvu#pquBa=?
zNU5HsVO)7EM{DBc|GlzR+b@fJLGsy(?FFt|xgHw}TBWeXJ_0W|JtBPC
ze~f4qtRGR58c`9xic(GDr9Pu9azX2pRsl1jJ8oT
zI@pY@ZAJ-xjMnWRv8Wk^He(x~5xJZ4ha|nLZ)h{N^%>FoX>Qc(=wdUr^BK|mX0kpAo_q4!)6Tk8PWS``=}YcY{m{gBYHp0kDAfjW{mI|(fesZ)QpX6M!C<3
z-cLJ3{j_7$jQ%zwZZk@w_tV0t8JpUSN}mzEpLU9xvANBt@)^4s4=
z2H1>|J|lWR?Hn~@OPevuXGHI(U7}_b+YJ3Rp7d((_T?CwzC;y
zeMa%s@e)fW`SdejB+pgPzu=p7X6ze?Sk6-*5#>0_Xck_RDm_2W7)ZK;$m)=j
zmDAD^jB3z`rSORJHgor
z-MJy08^WmrUUw?p*%{8xaCW9s=}w($+V`^yoH{^ur_!BW;p_@$S2~sM>;`8yICVhn
zPNh4$!`U6q?sO{M*#piVaOwcuol1B1gtI4{J?T`svlpDb;M4)TJC*J%g0l$DB081s
z>=Vowj2IppUD&4s`
zoSVa`6B>6a-MIyvTfn(wzh090=z?I+gC+63#8*)CrS2mG0aM
z>ye)=PCs^)Ox>J|qv@(6>N1--2g5m-PNh3_am}1V;M579JC*L#B{g#n
zg>xvKN_Xl)nmLETsS`wZD&48eXXe}*>Fa;%()GmI-zu@(w(|gX3lNl+?GzI
zJ9UA~oZG>v6Hs?5-KooB=G-36?depyQy0U`IUG)%u)0&}PF(^s=MHf0K
z=LkBL?ktD19L{nvlh-;I+gCMgR>6KIy#l^+!@ZD;oO-{r9124tcSCnPNh2=;B0`iflj46
z$H6%c(`q-8ml4@o=hF
zJDcEag0qQEr91b6b1yjeqEqS4z2V#&{eWx^o{m_knXCI+gC61m`3;C()^N=e}_6
z3+KLcD&488-uCD1esJzbr_!C1;hYTTWIC1Z+#k;U;oP52r8}p7@UW}c^I8acg}=!
zCY&?rRJ!wUI1h*Oa5|OloCW7BIA_tRbmtLp9s%bObSm9B8_wBq*<-fpZR>
zN_WnMb1s~7=~TM~v#^GG_C?mP<4qu@M>PNh5N!8s4kd2}k>c{H3y!+A8FN_QRu
z=P_^|L#NW6^WmHi=X^Sq?py%p0yr1YsdQ)2Vdlv2Y#>=dpAu-FY0G$H93V
zol18e59jf49#5yzoeSYy2w=OQ>4(W!LjVmKGWxtLC+J5PY~1UOHiQ|Znn
za4vy!37txJo(SiOaGpq~(w!&4c@mr_(W!Lj$#9+w=gD*`-MJLbrEo5#Q|ZoA;5-G+
zQ|MH>^Hexbh4WN8mF`>y=Q22#(W!LjayXa6xtva=J6FKD0?rk5D&2V+oTtHg8l6ga
zo(|{faGp-5(w%3(c?O(k(5ZCinQ)#7=b3aW-FX(AXTfZ#o=vCHo#()L
z4xH!EsdVSLaGne2xpXSsc^;hS!Fe8?N_URJ!wGI4_3tVmg)Xyadim;Jk!Rr8`%_xeCrzbSm9>
zDV&$Wc`2PrcU}hPWpG|br_!C5!+ANJm(!_q=M`{X0p}HTD&2V{oL9nmC7nulUIph>
za9%~H(w$esc{Q9@)2VdlHE>=7=QVUH-FYpX*TQ)%ol19J2j_KgUPq_Wo!7&8J)GCm
zsdVQJaNYpt4Rk8qc_W-R!g(W|N_XA_=S^_lM5of7H^X@|oHx^{bmuK_-U8<>bSm9>
zE1b8`Kbtcisl)ZE)U3r_!Cb!+ATLx6`R~=N)j~0p}fbD&2V}oOi-`C!I=n-Ua7f
zaNb3y(w%q1c{iMQ)2VdlJ#gLw=RI^P-FYvZ_riHEol1A!2j_io-bbg>o%h3eKb-f|
zsdVQ9a6SO%19U3g`5>GR!ucSbN_Rd4=Rqcl;e4DHzD&6@EoX^1d44q1MJ`3lwa6U_?
z(w%GJTnpz~I+gBx4$kM`e2z|~JD-R1c{rb^Q|ZnZ;Cunj7wA;F^F=scg!4r@mF|2A
z?ePiB6?EUxxE#IA5ky>CRW+d$8ci?;n
zy7OH)--YvCI+gBx56<`Ce2-40JKu-%eK_BzQ|ZnR;QRp259n07^Fug4g!4l>mG1lq
z^yh)$(DKZf>CR8!`~=QV=v2D%Q#e0`^HVyN?)(hS&*1!wPNh3Phx2nd
zKc`da)Bn0?se!RJ!v^IKPDROFEVA{0h#m;QWeCr8~cd^J_T2rc>$8Z{Yj}^c
zy7OB#I+gDH4$kl3{EkkgJHLnXdpN(RQ|Znh;QRs3ALvxN^G7&;g!4x_mG1lr
z$4?iB6?Ee}?mCIDe*7>CRu^`~}Wm=v2D%S2%x#^H(~R?)(kT-{Aa>PNh44hx2zh
zf2ULF%1I|C_RJ!v|IRAw6Pdb(E{0q*%;QWhDr91zI^KUr+rc>$87C2krY@t(`
zbT&3uXX$^8vEMh17mrN-KB;c&^rjx|VmXO7^5`2R-^e3;qYr+ruys>IeM3fSRO^S)h*wT1Svj`NiYWyhWBH9WZC8OmrRdkX@gRI%+|-U
z8DWHT!aHT*s2N9wx3Qi<_+e#-w|
zCa1oxxGDL|)s4+HS@l)vx2#F-LE(GJgg*#nvEqMxyAr#GzF9>hQs1W3hy3tk_y#kh
z+l;EKP5s1`C*DVANccWF>wb|tH9P$ss!chlJnyQM+f`xSx>MLUN8=H&5JIVJQNjlBbPnKQWME+3?d0$55v<@85#a0w6axw|fY>0KxE!S15v<@85#a0&6k`O6f!H7#8OTC8azL5|h^3)?DJYFj0RVOU
B2mt^9

literal 0
HcmV?d1

diff --git a/tests/data/acpi/virt/MCFG b/tests/data/acpi/virt/MCFG
new file mode 100644
index 
..e8987e1af0ec3829770bf4fe11fab02b06160dd2
GIT binary patch
literal 60
scmeZuc5}C3U|?YMck*}k2v%^42ypfViZKGkKx`0=1Oyx)oc|yS05YNo0RR91

literal 0
HcmV?d1

diff --git a/tests/data/acpi/virt/SPCR b/tests/data/acpi/virt/SPCR
new file mode 100644
index 
..377271a0e7817cc21a28c02123a89facad63604f
GIT binary patch
literal 80
zcmWFza1IJ!U|?VpcJg=j2v%^42yhMtiZKGkKx`1r48#l^3?L>agsBLmm>C$E7#RKo
I0Z0r60QF4^0RR91

literal 0
HcmV?d1

-- 
2.7.4




Re: [Qemu-devel] [PATCH for-4.1 1/8] target/riscv: Name the argument sets for all of insn32 formats

2019-04-24 Thread Richard Henderson
On 4/24/19 8:31 PM, Palmer Dabbelt wrote:
>>  # Argument sets:
>> +
> 
> If I understand decodetree correctly, this isn't used until patch 5.
> Otherwise,
> 

I think it's used as early as patch 3, but I haven't looked in detail to be 
sure.


r~



Re: [Qemu-devel] [PATCH v8 1/6] ppc: spapr: Handle "ibm, nmi-register" and "ibm, nmi-interlock" RTAS calls

2019-04-24 Thread Aravinda Prasad



On Tuesday 23 April 2019 12:15 PM, David Gibson wrote:
> On Mon, Apr 22, 2019 at 12:32:58PM +0530, Aravinda Prasad wrote:
>> This patch adds support in QEMU to handle "ibm,nmi-register"
>> and "ibm,nmi-interlock" RTAS calls.
>>
>> The machine check notification address is saved when the
>> OS issues "ibm,nmi-register" RTAS call.
>>
>> This patch also handles the case when multiple processors
>> experience machine check at or about the same time by
>> handling "ibm,nmi-interlock" call. In such cases, as per
>> PAPR, subsequent processors serialize waiting for the first
>> processor to issue the "ibm,nmi-interlock" call. The second
>> processor that also received a machine check error waits
>> till the first processor is done reading the error log.
>> The first processor issues "ibm,nmi-interlock" call
>> when the error log is consumed. This patch implements the
>> releasing part of the error-log while subsequent patch
>> (which builds error log) handles the locking part.
>>
>> Signed-off-by: Aravinda Prasad 
> 
> Reviewed-by: David Gibson 
> 
> Although I wonder if it needs to be moved later in the series to avoid
> advertising the availability of the RTAS calls to the guest before all
> the prereq patches are in place to make them work properly.

Patch 3 and 4 uses "guest_machine_check_addr", which is set in this
patch. If we push this beyond patch 4, then I feel the use of
"guest_machine_check_addr" looks odd in patch 3 and 4.

Regards,
Aravinda

> 
>> ---
>>  hw/ppc/spapr.c |   18 ++
>>  hw/ppc/spapr_rtas.c|   61 
>> 
>>  include/hw/ppc/spapr.h |9 ++-
>>  3 files changed, 87 insertions(+), 1 deletion(-)
>>
>> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
>> index c56939a..6642cb5 100644
>> --- a/hw/ppc/spapr.c
>> +++ b/hw/ppc/spapr.c
>> @@ -1805,6 +1805,11 @@ static void spapr_machine_reset(void)
>>  first_ppc_cpu->env.gpr[5] = 0;
>>  
>>  spapr->cas_reboot = false;
>> +
>> +spapr->guest_machine_check_addr = -1;
>> +
>> +/* Signal all vCPUs waiting on this condition */
>> +qemu_cond_broadcast(>mc_delivery_cond);
>>  }
>>  
>>  static void spapr_create_nvram(SpaprMachineState *spapr)
>> @@ -2095,6 +2100,16 @@ static const VMStateDescription vmstate_spapr_dtb = {
>>  },
>>  };
>>  
>> +static const VMStateDescription vmstate_spapr_machine_check = {
>> +.name = "spapr_machine_check",
>> +.version_id = 1,
>> +.minimum_version_id = 1,
>> +.fields = (VMStateField[]) {
>> +VMSTATE_UINT64(guest_machine_check_addr, SpaprMachineState),
>> +VMSTATE_END_OF_LIST()
>> +},
>> +};
>> +
>>  static const VMStateDescription vmstate_spapr = {
>>  .name = "spapr",
>>  .version_id = 3,
>> @@ -2127,6 +2142,7 @@ static const VMStateDescription vmstate_spapr = {
>>  _spapr_dtb,
>>  _spapr_cap_large_decr,
>>  _spapr_cap_ccf_assist,
>> +_spapr_machine_check,
>>  NULL
>>  }
>>  };
>> @@ -3068,6 +3084,8 @@ static void spapr_machine_init(MachineState *machine)
>>  
>>  kvmppc_spapr_enable_inkernel_multitce();
>>  }
>> +
>> +qemu_cond_init(>mc_delivery_cond);
>>  }
>>  
>>  static int spapr_kvm_type(MachineState *machine, const char *vm_type)
>> diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
>> index ee24212..c2f3991 100644
>> --- a/hw/ppc/spapr_rtas.c
>> +++ b/hw/ppc/spapr_rtas.c
>> @@ -348,6 +348,39 @@ static void rtas_get_power_level(PowerPCCPU *cpu, 
>> SpaprMachineState *spapr,
>>  rtas_st(rets, 1, 100);
>>  }
>>  
>> +static void rtas_ibm_nmi_register(PowerPCCPU *cpu,
>> +  SpaprMachineState *spapr,
>> +  uint32_t token, uint32_t nargs,
>> +  target_ulong args,
>> +  uint32_t nret, target_ulong rets)
>> +{
>> +uint64_t rtas_addr = spapr_get_rtas_addr();
>> +
>> +if (!rtas_addr) {
>> +rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
>> +return;
>> +}
>> +
>> +spapr->guest_machine_check_addr = rtas_ld(args, 1);
>> +rtas_st(rets, 0, RTAS_OUT_SUCCESS);
>> +}
>> +
>> +static void rtas_ibm_nmi_interlock(PowerPCCPU *cpu,
>> +   SpaprMachineState *spapr,
>> +   uint32_t token, uint32_t nargs,
>> +   target_ulong args,
>> +   uint32_t nret, target_ulong rets)
>> +{
>> +if (!spapr->guest_machine_check_addr) {
>> +/* NMI register not called */
>> +rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
>> +} else {
>> +qemu_cond_signal(>mc_delivery_cond);
>> +rtas_st(rets, 0, RTAS_OUT_SUCCESS);
>> +}
>> +}
>> +
>> +
>>  static struct rtas_call {
>>  const char *name;
>>  spapr_rtas_fn fn;
>> @@ -466,6 +499,30 @@ void spapr_load_rtas(SpaprMachineState *spapr, void 
>> *fdt, hwaddr addr)
>>  }
>>  }
>>  

Re: [Qemu-devel] [PATCH for-4.1 2/8] target/riscv: Use --static-decode for decodetree

2019-04-24 Thread Palmer Dabbelt

On Sun, 31 Mar 2019 20:11:49 PDT (-0700), richard.hender...@linaro.org wrote:

The generated functions are only used within translate.c
and do not need to be global, or declared.

Signed-off-by: Richard Henderson 
---
 target/riscv/translate.c   | 2 --
 target/riscv/Makefile.objs | 8 
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index dd763647ea..7ebd590486 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -538,7 +538,6 @@ static int ex_rvc_register(int reg)
 return 8 + reg;
 }

-bool decode_insn32(DisasContext *ctx, uint32_t insn);
 /* Include the auto-generated decoder for 32 bit insn */
 #include "decode_insn32.inc.c"

@@ -667,7 +666,6 @@ static bool gen_shift(DisasContext *ctx, arg_r *a,
 #include "insn_trans/trans_rvd.inc.c"
 #include "insn_trans/trans_privileged.inc.c"

-bool decode_insn16(DisasContext *ctx, uint16_t insn);
 /* auto-generated decoder*/
 #include "decode_insn16.inc.c"
 #include "insn_trans/trans_rvc.inc.c"
diff --git a/target/riscv/Makefile.objs b/target/riscv/Makefile.objs
index 9c6c109327..c7a1b063ed 100644
--- a/target/riscv/Makefile.objs
+++ b/target/riscv/Makefile.objs
@@ -7,14 +7,14 @@ decode32-$(TARGET_RISCV64) += 
$(SRC_PATH)/target/riscv/insn32-64.decode

 target/riscv/decode_insn32.inc.c: $(decode32-y) $(DECODETREE)
$(call quiet-command, \
- $(PYTHON) $(DECODETREE) -o $@ --decode decode_insn32 $(decode32-y), \
- "GEN", $(TARGET_DIR)$@)
+ $(PYTHON) $(DECODETREE) -o $@ --static-decode decode_insn32 \
+  $(decode32-y), "GEN", $(TARGET_DIR)$@)

 target/riscv/decode_insn16.inc.c: \
   $(SRC_PATH)/target/riscv/insn16.decode $(DECODETREE)
$(call quiet-command, \
- $(PYTHON) $(DECODETREE) -o $@ --decode decode_insn16 --insnwidth 16 
$<, \
- "GEN", $(TARGET_DIR)$@)
+ $(PYTHON) $(DECODETREE) -o $@ --static-decode decode_insn16 \
+  --insnwidth 16 $<, "GEN", $(TARGET_DIR)$@)

 target/riscv/translate.o: target/riscv/decode_insn32.inc.c \
target/riscv/decode_insn16.inc.c


Reviewed-by: Palmer Dabbelt 



Re: [Qemu-devel] [PATCH for-4.1 1/8] target/riscv: Name the argument sets for all of insn32 formats

2019-04-24 Thread Palmer Dabbelt

On Sun, 31 Mar 2019 20:11:48 PDT (-0700), richard.hender...@linaro.org wrote:

Signed-off-by: Richard Henderson 
---
 target/riscv/insn32.decode | 10 +++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 6f3ab7aa52..77f794ed70 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -34,9 +34,13 @@
 %imm_u12:s20 !function=ex_shift_12

 # Argument sets:
+


If I understand decodetree correctly, this isn't used until patch 5.
Otherwise,

Reviewed-by: Palmer Dabbelt 

I don't care enough about this to make you re-spin the patch set, so I'm OK
taking it as it stands unless there's anything else that crops up as I look
through the rest of the patches...

Thanks!


 imm rs2 rs1
 imm rs1 rd
+imm rd
 rd rs1 rs2
+imm rs1 rs2
+imm rd
  shamt rs1 rd
 aq rl rs2 rs1 rd

@@ -44,9 +48,9 @@
 @r   ...   . . ... . ... %rs2 %rs1 
%rd
 @i   . ... . ...   imm=%imm_i %rs1 
%rd
 @b   ...   . . ... . ...   imm=%imm_b %rs2 %rs1
-@s   ...   . . ... . ... imm=%imm_s %rs2 %rs1
-@u     . ... imm=%imm_u  
%rd
-@j     . ... imm=%imm_j  
%rd
+@s   ...   . . ... . ...   imm=%imm_s %rs2 %rs1
+@u     . ...   imm=%imm_u  
%rd
+@j     . ...   imm=%imm_j  
%rd

 @sh  ..  .. .  ... . ...   shamt=%sh10  %rs1 
%rd
 @csr    .  ... . ...   %csr %rs1 
%rd




[Qemu-devel] [PATCH] bitmap: get last word mask from nr directly

2019-04-24 Thread Wei Yang
The value left in nr is the number of bits for the last word, which
could be calculate the last word mask directly.

Remove the unnecessary size.

Signed-off-by: Wei Yang 
---
 util/bitmap.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/util/bitmap.c b/util/bitmap.c
index cb618c65a5..5aa60b8717 100644
--- a/util/bitmap.c
+++ b/util/bitmap.c
@@ -160,7 +160,6 @@ int slow_bitmap_andnot(unsigned long *dst, const unsigned 
long *bitmap1,
 void bitmap_set(unsigned long *map, long start, long nr)
 {
 unsigned long *p = map + BIT_WORD(start);
-const long size = start + nr;
 int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG);
 unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start);
 
@@ -174,7 +173,7 @@ void bitmap_set(unsigned long *map, long start, long nr)
 p++;
 }
 if (nr) {
-mask_to_set &= BITMAP_LAST_WORD_MASK(size);
+mask_to_set &= BITMAP_LAST_WORD_MASK(nr);
 *p |= mask_to_set;
 }
 }
@@ -221,7 +220,6 @@ void bitmap_set_atomic(unsigned long *map, long start, long 
nr)
 void bitmap_clear(unsigned long *map, long start, long nr)
 {
 unsigned long *p = map + BIT_WORD(start);
-const long size = start + nr;
 int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG);
 unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start);
 
@@ -235,7 +233,7 @@ void bitmap_clear(unsigned long *map, long start, long nr)
 p++;
 }
 if (nr) {
-mask_to_clear &= BITMAP_LAST_WORD_MASK(size);
+mask_to_clear &= BITMAP_LAST_WORD_MASK(nr);
 *p &= ~mask_to_clear;
 }
 }
-- 
2.19.1




Re: [Qemu-devel] [PATCH v3 2/2] core/qdev: refactor qdev_get_machine() with type assertion

2019-04-24 Thread Like Xu

On 2019/4/25 1:21, Eduardo Habkost wrote:

On Tue, Apr 23, 2019 at 03:59:31PM +0800, Like Xu wrote:

On 2019/4/18 1:10, Eduardo Habkost wrote:

On Wed, Apr 17, 2019 at 07:14:10AM +0200, Markus Armbruster wrote:

Eduardo Habkost  writes:


On Mon, Apr 15, 2019 at 03:59:45PM +0800, Like Xu wrote:

To avoid the misuse of qdev_get_machine() if machine hasn't been created yet,
this patch uses qdev_get_machine_uncheck() for obj-common (share with user-only
mode) and adds type assertion to qdev_get_machine() in system-emulation mode.

Suggested-by: Igor Mammedov 
Signed-off-by: Like Xu 


Reviewed-by: Eduardo Habkost 

I'm queueing the series on machine-next, thanks!


Hold your horses, please.

I dislike the name qdev_get_machine_uncheck().  I could live with
qdev_get_machine_unchecked().

However, I doubt this is the right approach.

The issue at hand is undisciplined creation of QOM object /machine.

This patch adds an asseertion "undisciplined creation of /machine didn't
create crap", but only in some places.

I think we should never create /machine as (surprising!) side effect of
qdev_get_machine().  Create it explicitly instead, and have
qdev_get_machine() use object_resolve_path("/machine", NULL) to get it.
Look ma, no side effects.


OK, I'm dropping this one while we discuss it.

I really miss a good explanation why qdev_get_machine_unchecked()
needs to exist.  When exactly do we want /machine to exist but
not be TYPE_MACHINE?  Why?


AFAICT, there is no such "/machine" that is not of type TYPE_MACHINE.

The original qdev_get_machine() would always return a "/container" object in
user-only mode and there is none TYPE_MACHINE object.


I'm confused.  Both qdev_get_machine() and
qdev_get_machine_unchecked() still return the object at
"/machine".  On softmmu, /machine will be of type TYPE_MACHINE.
On user-only, /machine will be of type "container".




In system emulation mode, it returns the same "/container" object at the
beginning, until we initialize and add a TYPE_MACHINE object to the
"/container" as a child and it would return OBJECT(current_machine)
for later usages.

The starting point is to avoid using the legacy qdev_get_machine()
in system emulation mode when we haven't added the "/machine" object.
As a result, we introduced type checking assertions to avoid premature
invocations.


I believe Markus is suggesting that avoiding unwanted side
effects is even better than doing type checking after it's
already too late.  In other words, it doesn't make sense to call
container_get("/machine") on system emulation mode.


I agree.






In this proposal, the qdev_get_machine_unchecked() is only used
in user-only mode, part of which shares with system emulation mode
(such as device_set_realized, cpu_common_realizefn). The new
qdev_get_machine() is only used in system emulation mode and type checking
assertion does reduce the irrational use of this function (if any in the
future).


This part confuses me as well.  qdev_get_machine_unchecked() is
used in both user-only and softmmu, isn't?  Thus we can't say it
is only used in user-only mode.


You're right about this.



I think we all agree that qdev_get_machine() should eventually be
available in softmmu only.


I think we need to make it happen to avoid calling qdev_get_machine()
in user-only mode.



But I don't think we agree when it would be appropriate to call
qdev_get_machine_unchecked() instead of qdev_get_machine().

On both examples in your patch, the code checks for TYPE_MACHINE
immediately after calling qdev_get_machine_unchecked().  If that
code is only useful in softmmu mode, when would anybody want to
call qdev_get_machine_unchecked() in user-only mode?




We all agree to use this qdev_get_machine() as little as possible
and this patch could make future clean up work easier.



Once the expectations and use cases are explained, we can choose
a better name for qdev_get_machine_unchecked() and document it
properly.










Re: [Qemu-devel] [PATCH V3] vhost_net: don't set backend for the uninitialized virtqueue

2019-04-24 Thread Jason Wang



On 2019/4/24 下午9:51, Michael S. Tsirkin wrote:

On Tue, Apr 09, 2019 at 01:58:50PM +0800, Jason Wang wrote:

We used to set backend unconditionally, this won't work for some
guests (e.g windows driver) who may not initialize all virtqueues. For
kernel backend, this will fail since it may try to validate the rings
during setting backend.

Fixing this by simply skipping the backend set when we find desc is
not ready.

Signed-off-by: Jason Wang

Reviewed-by: Michael S. Tsirkin



Applied.

Thanks




Re: [Qemu-devel] [RFC PATCH v1 00/10] Add AMD SEV guest live migration support

2019-04-24 Thread Singh, Brijesh

On 4/24/19 7:18 PM, Steve Rutherford wrote:
> Do you mean MiB/s, MB/s or Mb/s? Since you are talking about network
> speeds, sometimes these get conflated.

It's megabits/sec. The QMP query-migration command shows the throughput
in Mbits/s. It includes PSP command execution and the network write.
Most of the time is spent in PSP FW. I have not performed raw PSP
command benchmark yet but I believe SEV FW 0.17 may reproduce up to
12Mbits/s. I will update thread after I finish the further performance
breakdown.

-Brijesh



Re: [Qemu-devel] [PATCH] mips: Fix "Unexpected FPU mode"

2019-04-24 Thread Daniel Santos
Hello,

Sorry for my slow reply.  I don't mind that, as long as I end up being
shown as the author in git. :)  I've never committed from an email
before, so I'm not sure how that works.  Does adding another "From: "
header in the body patch that up with git-am?

I don't know how much I'll be contributing to qemu in the future --
there are a few crazy things I have considered trying to add and I'll be
using qemu quite a bit in the future, so this probably won't be my only
patch.  But in this case, I just *really* needed to get something MIPS
running on my workstation.

Also, as my big "please note", it would be good for somebody more
familiar with that code to make sure anything else that isn't explicitly
initialized will behave correctly after being memset to zero.  When a
zero is OK, I often add an explicit this.that = 0; to clarify the
intention and just expect gcc to compile it away.

Thanks!
Daniel

On 4/23/19 1:00 PM, Aleksandar Markovic wrote:
> On Wed, Apr 17, 2019 at 9:50 PM Daniel Santos  wrote:
>> In load_elf_binary, struct image_info interp_info is used without being
>> properly initialized.  One result is that when the ELF's program header
>> doesn't contain an entry for the ABI flags, then the value of the struct
>> image_info's fp_abi field is set to whatever happened to be in stack
>> memory at the time.
>>
>> This patch both sanitizes interp_info and initializes fp_abi for
>> TARGET_MIPS to MIPS_ABI_FP_UNKNOWN so that when we don't know the FP
>> ABI, we don't just blow up.  Currently, this bug is a complete stopper
>> for some MIPS binaries.
>>
>> ***PLEASE NOTE***
>> There may be other bugs as a result of struct image_info interp_info
>> fields not being properly initialized -- this patch only addresses the
>> fp_abi field.  I reccomend somebody who knows the code better than I
>> audit this function and the whole of that execution path.
>>
>> Fixes bug #1825002 and affects 3.1.0 and 4.x, reccomend backporting to
>> 3.1.0.
>>
>> Signed-off-by: Daniel Santos 
>> ---
> Daniel, not knowing that you already send this patch, I included it in another
> series (with different title and commit message, but the same content):
>
> https://lists.gnu.org/archive/html/qemu-devel/2019-04/msg03813.html
>
> Please let's track this patch there.
>
> I will change the commit message to bring it closer to the yours version
> in the next version of the series, and I will review the patch from MIPS
> point of view.
>
> Just advice for the future: Before sending patches to qemu-devel,
> check what are maintainers for the applicable code. There is even a
> script for that: /scripts/get_maintainers.pl
>
> There are also other rules and conventiones, and all of them are
> mentioned on the page "How to submit a patch" on QEMU web site.
>
> But, in any case, many thanks for discovering and reporting the bug,
> and even devising the fix!
>
> Yours,
> Aleksandar
>
>>  linux-user/elfload.c | 5 +
>>  1 file changed, 5 insertions(+)
>>
>> diff --git a/linux-user/elfload.c b/linux-user/elfload.c
>> index c1a26021f8..7f09d572a2 100644
>> --- a/linux-user/elfload.c
>> +++ b/linux-user/elfload.c
>> @@ -2698,6 +2698,11 @@ int load_elf_binary(struct linux_binprm *bprm, struct 
>> image_info *info)
>>  char *elf_interpreter = NULL;
>>  char *scratch;
>>
>> +memset(_info, 0, sizeof(interp_info));
>> +#ifdef TARGET_MIPS
>> +interp_info.fp_abi = MIPS_ABI_FP_UNKNOWN;
>> +#endif
>> +
>>  info->start_mmap = (abi_ulong)ELF_START_MMAP;
>>
>>  load_elf_image(bprm->filename, bprm->fd, info,
>> --
>> 2.19.2
>>
>>




Re: [Qemu-devel] [RFC PATCH v1 00/10] Add AMD SEV guest live migration support

2019-04-24 Thread Steve Rutherford via Qemu-devel
Do you mean MiB/s, MB/s or Mb/s? Since you are talking about network
speeds, sometimes these get conflated.

I'm guessing you mean MB/s since you are also using 4kb for page size.

On Wed, Apr 24, 2019 at 2:32 PM Singh, Brijesh 
wrote:

>
>
> On 4/24/19 2:15 PM, Steve Rutherford wrote:
> > On Wed, Apr 24, 2019 at 9:10 AM Singh, Brijesh 
> wrote:
> >>
> >> The series add support for AMD SEV guest live migration commands. To
> protect the
> >> confidentiality of an SEV protected guest memory while in transit we
> need to
> >> use the SEV commands defined in SEV API spec [1].
> >>
> >> SEV guest VMs have the concept of private and shared memory. Private
> memory
> >> is encrypted with the guest-specific key, while shared memory may be
> encrypted
> >> with hypervisor key. The commands provided by the SEV FW are meant to
> be used
> >> for the private memory only. The patch series introduces a new
> hypercall.
> >> The guest OS can use this hypercall to notify the page encryption
> status.
> >> If the page is encrypted with guest specific-key then we use SEV
> command during
> >> the migration. If page is not encrypted then fallback to default.
> >>
> >> The patch adds a new ioctl KVM_GET_PAGE_ENC_BITMAP. The ioctl can be
> used
> >> by the qemu to get the page encrypted bitmap. Qemu can consult this
> bitmap
> >> during the migration to know whether the page is encrypted.
> >>
> >> [1] https://developer.amd.com/wp-content/resources/55766.PDF
> >>
> >> The series is tested with the Qemu, I am in process of cleaning
> >> up the Qemu code and will submit soon.
> >>
> >> While implementing the migration I stumbled on the follow question:
> >>
> >> - Since there is a guest OS changes required to support the migration,
> >>so how do we know whether guest OS is updated? Should we extend KVM
> >>capabilities/feature bits to check this?
> >>
> >> TODO:
> >>   - add an ioctl to build encryption bitmap. The encryption bitmap is
> built during
> >> the guest bootup/execution. We should provide an ioctl so that
> destination
> >> can build the bitmap as it receives the pages.
> >>   - reset the bitmap on guest reboot.
> >>
> >> The complete tree with patch is available at:
> >> https://github.com/codomania/kvm/tree/sev-migration-rfc-v1
> >>
> >> Cc: Thomas Gleixner 
> >> Cc: Ingo Molnar 
> >> Cc: "H. Peter Anvin" 
> >> Cc: Paolo Bonzini 
> >> Cc: "Radim Krčmář" 
> >> Cc: Joerg Roedel 
> >> Cc: Borislav Petkov 
> >> Cc: Tom Lendacky 
> >> Cc: x...@kernel.org
> >> Cc: k...@vger.kernel.org
> >> Cc: linux-ker...@vger.kernel.org
> >>
> >> Brijesh Singh (10):
> >>KVM: SVM: Add KVM_SEV SEND_START command
> >>KVM: SVM: Add KVM_SEND_UPDATE_DATA command
> >>KVM: SVM: Add KVM_SEV_SEND_FINISH command
> >>KVM: SVM: Add support for KVM_SEV_RECEIVE_START command
> >>KVM: SVM: Add KVM_SEV_RECEIVE_UPDATE_DATA command
> >>KVM: SVM: Add KVM_SEV_RECEIVE_FINISH command
> >>KVM: x86: Add AMD SEV specific Hypercall3
> >>KVM: X86: Introduce KVM_HC_PAGE_ENC_STATUS hypercall
> >>KVM: x86: Introduce KVM_GET_PAGE_ENC_BITMAP ioctl
> >>mm: x86: Invoke hypercall when page encryption status is changed
> >>
> >>   .../virtual/kvm/amd-memory-encryption.rst | 116 
> >>   Documentation/virtual/kvm/hypercalls.txt  |  14 +
> >>   arch/x86/include/asm/kvm_host.h   |   3 +
> >>   arch/x86/include/asm/kvm_para.h   |  12 +
> >>   arch/x86/include/asm/mem_encrypt.h|   3 +
> >>   arch/x86/kvm/svm.c| 560 +-
> >>   arch/x86/kvm/vmx/vmx.c|   1 +
> >>   arch/x86/kvm/x86.c|  17 +
> >>   arch/x86/mm/mem_encrypt.c |  45 +-
> >>   arch/x86/mm/pageattr.c|  15 +
> >>   include/uapi/linux/kvm.h  |  51 ++
> >>   include/uapi/linux/kvm_para.h |   1 +
> >>   12 files changed, 834 insertions(+), 4 deletions(-)
> >>
> >> --
> >> 2.17.1
> >>
> >
> > What's the back-of-the-envelope marginal cost of transferring a 16kB
> > region from one host to another? I'm interested in what the end to end
> > migration perf changes look like for this. If you have measured
> > migration perf, I'm interested in that also.
> >
>
> I have not done a complete performance analysis yet! From the qemu
> QMP prompt (query-migration) I am getting ~8mbps throughput from
> one host to another (this is with 4kb regions). I have been told
> that increasing the transfer size from 4kb -> 16kb may not give a
> huge performance gain because at FW level they still operating
> on 4kb blocks. There is possibility that future FW updates may
> give a bit better performance on 16kb size.
>
> -Brijesh
>


[Qemu-devel] [PATCH v2] hmp: delvm: use hmp_handle_error

2019-04-24 Thread Cole Robinson
This gives us the consistent 'Error:' prefix added in 66363e9a43f,
which helps users like libvirt who still need to scrape hmp error
messages to detect failure.

Reviewed-by: Eric Blake 
Signed-off-by: Cole Robinson 
---
v2:
Drop now redundant "Error while" string prefix

 hmp.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/hmp.c b/hmp.c
index 4bb3af748e..56a3ed7375 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1480,10 +1480,11 @@ void hmp_delvm(Monitor *mon, const QDict *qdict)
 const char *name = qdict_get_str(qdict, "name");
 
 if (bdrv_all_delete_snapshot(name, , ) < 0) {
-error_reportf_err(err,
-  "Error while deleting snapshot on device '%s': ",
-  bdrv_get_device_name(bs));
+error_prepend(,
+  "deleting snapshot on device '%s': ",
+  bdrv_get_device_name(bs));
 }
+hmp_handle_error(mon, );
 }
 
 void hmp_info_snapshots(Monitor *mon, const QDict *qdict)
-- 
2.21.0




Re: [Qemu-devel] [PATCH 4/6] cirrus / travis: Add gnu-sed and bash for macOS and FreeBSD

2019-04-24 Thread Wainer dos Santos Moschetta

Hello Thomas,

On 04/24/2019 07:37 AM, Thomas Huth wrote:

We are going to enable the qemu-iotests during "make check" again,
and for running the iotests, we need bash and gnu-sed.

Signed-off-by: Thomas Huth 
---
  .cirrus.yml | 4 ++--
  .travis.yml | 1 +
  2 files changed, 3 insertions(+), 2 deletions(-)


It needs to get the Freebsd image [1] updated too, in order to `make 
BUILD_TARGET=check vm-build-freebsd` passes. Here it failed with:

---
env: bash: No such file or directory
gmake: *** [/var/tmp/qemu-test.6OlDFH/tests/Makefile.include:1101: 
check-tests/qemu-iotests-quick.sh] Error 1

gmake: *** Waiting for unfinished jobs
---

I'm not sure about the netbsd and openbsd images, they might need bash 
and gnu-sed as well.


[1] http://download.patchew.org/freebsd-11.1-amd64.img.xz

- Wainer



diff --git a/.cirrus.yml b/.cirrus.yml
index 47ef5bc604..8326a3a4b1 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -7,7 +7,7 @@ freebsd_12_task:
  cpu: 8
  memory: 8G
install_script: pkg install -y
-bison curl cyrus-sasl git glib gmake gnutls
+bash bison curl cyrus-sasl git glib gmake gnutls gsed
  nettle perl5 pixman pkgconf png usbredir
script:
  - mkdir build
@@ -20,7 +20,7 @@ macos_task:
osx_instance:
  image: mojave-base
install_script:
-- brew install pkg-config python glib pixman make sdl2
+- brew install pkg-config python gnu-sed glib pixman make sdl2
script:
  - ./configure --python=/usr/local/bin/python3 || { cat config.log; exit 
1; }
  - gmake -j$(sysctl -n hw.ncpu)
diff --git a/.travis.yml b/.travis.yml
index 2e06aee9d0..ba94644192 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -42,6 +42,7 @@ addons:
  packages:
- glib
- pixman
+  - gnu-sed
  
  
  # The channel name "irc.oftc.net#qemu" is encrypted against qemu/qemu





Re: [Qemu-devel] [RFC PATCH v1 00/10] Add AMD SEV guest live migration support

2019-04-24 Thread Singh, Brijesh


On 4/24/19 2:15 PM, Steve Rutherford wrote:
> On Wed, Apr 24, 2019 at 9:10 AM Singh, Brijesh  wrote:
>>
>> The series add support for AMD SEV guest live migration commands. To protect 
>> the
>> confidentiality of an SEV protected guest memory while in transit we need to
>> use the SEV commands defined in SEV API spec [1].
>>
>> SEV guest VMs have the concept of private and shared memory. Private memory
>> is encrypted with the guest-specific key, while shared memory may be 
>> encrypted
>> with hypervisor key. The commands provided by the SEV FW are meant to be used
>> for the private memory only. The patch series introduces a new hypercall.
>> The guest OS can use this hypercall to notify the page encryption status.
>> If the page is encrypted with guest specific-key then we use SEV command 
>> during
>> the migration. If page is not encrypted then fallback to default.
>>
>> The patch adds a new ioctl KVM_GET_PAGE_ENC_BITMAP. The ioctl can be used
>> by the qemu to get the page encrypted bitmap. Qemu can consult this bitmap
>> during the migration to know whether the page is encrypted.
>>
>> [1] https://developer.amd.com/wp-content/resources/55766.PDF
>>
>> The series is tested with the Qemu, I am in process of cleaning
>> up the Qemu code and will submit soon.
>>
>> While implementing the migration I stumbled on the follow question:
>>
>> - Since there is a guest OS changes required to support the migration,
>>so how do we know whether guest OS is updated? Should we extend KVM
>>capabilities/feature bits to check this?
>>
>> TODO:
>>   - add an ioctl to build encryption bitmap. The encryption bitmap is built 
>> during
>> the guest bootup/execution. We should provide an ioctl so that 
>> destination
>> can build the bitmap as it receives the pages.
>>   - reset the bitmap on guest reboot.
>>
>> The complete tree with patch is available at:
>> https://github.com/codomania/kvm/tree/sev-migration-rfc-v1
>>
>> Cc: Thomas Gleixner 
>> Cc: Ingo Molnar 
>> Cc: "H. Peter Anvin" 
>> Cc: Paolo Bonzini 
>> Cc: "Radim Krčmář" 
>> Cc: Joerg Roedel 
>> Cc: Borislav Petkov 
>> Cc: Tom Lendacky 
>> Cc: x...@kernel.org
>> Cc: k...@vger.kernel.org
>> Cc: linux-ker...@vger.kernel.org
>>
>> Brijesh Singh (10):
>>KVM: SVM: Add KVM_SEV SEND_START command
>>KVM: SVM: Add KVM_SEND_UPDATE_DATA command
>>KVM: SVM: Add KVM_SEV_SEND_FINISH command
>>KVM: SVM: Add support for KVM_SEV_RECEIVE_START command
>>KVM: SVM: Add KVM_SEV_RECEIVE_UPDATE_DATA command
>>KVM: SVM: Add KVM_SEV_RECEIVE_FINISH command
>>KVM: x86: Add AMD SEV specific Hypercall3
>>KVM: X86: Introduce KVM_HC_PAGE_ENC_STATUS hypercall
>>KVM: x86: Introduce KVM_GET_PAGE_ENC_BITMAP ioctl
>>mm: x86: Invoke hypercall when page encryption status is changed
>>
>>   .../virtual/kvm/amd-memory-encryption.rst | 116 
>>   Documentation/virtual/kvm/hypercalls.txt  |  14 +
>>   arch/x86/include/asm/kvm_host.h   |   3 +
>>   arch/x86/include/asm/kvm_para.h   |  12 +
>>   arch/x86/include/asm/mem_encrypt.h|   3 +
>>   arch/x86/kvm/svm.c| 560 +-
>>   arch/x86/kvm/vmx/vmx.c|   1 +
>>   arch/x86/kvm/x86.c|  17 +
>>   arch/x86/mm/mem_encrypt.c |  45 +-
>>   arch/x86/mm/pageattr.c|  15 +
>>   include/uapi/linux/kvm.h  |  51 ++
>>   include/uapi/linux/kvm_para.h |   1 +
>>   12 files changed, 834 insertions(+), 4 deletions(-)
>>
>> --
>> 2.17.1
>>
> 
> What's the back-of-the-envelope marginal cost of transferring a 16kB
> region from one host to another? I'm interested in what the end to end
> migration perf changes look like for this. If you have measured
> migration perf, I'm interested in that also.
> 

I have not done a complete performance analysis yet! From the qemu
QMP prompt (query-migration) I am getting ~8mbps throughput from
one host to another (this is with 4kb regions). I have been told
that increasing the transfer size from 4kb -> 16kb may not give a
huge performance gain because at FW level they still operating
on 4kb blocks. There is possibility that future FW updates may
give a bit better performance on 16kb size.

-Brijesh


[Qemu-devel] [Bug 1823458] Please test proposed package

2019-04-24 Thread Corey Bryant
Hello Dan, or anyone else affected,

Accepted qemu into ocata-proposed. The package will build now and be
available in the Ubuntu Cloud Archive in a few hours, and then in the
-proposed repository.

Please help us by testing this new package. To enable the -proposed
repository:

  sudo add-apt-repository cloud-archive:ocata-proposed
  sudo apt-get update

Your feedback will aid us getting this update out to other Ubuntu users.

If this package fixes the bug for you, please add a comment to this bug,
mentioning the version of the package you tested, and change the tag
from verification-ocata-needed to verification-ocata-done. If it does
not fix the bug for you, please add a comment stating that, and change
the tag to verification-ocata-failed. In either case, details of your
testing will help us make a better decision.

Further information regarding the verification process can be found at
https://wiki.ubuntu.com/QATeam/PerformingSRUVerification . Thank you in
advance!

** Changed in: cloud-archive/ocata
   Status: Triaged => Fix Committed

** Tags added: verification-ocata-needed

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

Title:
  race condition between vhost_net_stop and CHR_EVENT_CLOSED on shutdown
  crashes qemu

Status in Ubuntu Cloud Archive:
  Fix Released
Status in Ubuntu Cloud Archive mitaka series:
  Fix Committed
Status in Ubuntu Cloud Archive ocata series:
  Fix Committed
Status in QEMU:
  Fix Released
Status in qemu package in Ubuntu:
  Fix Released
Status in qemu source package in Trusty:
  Won't Fix
Status in qemu source package in Xenial:
  Fix Committed
Status in qemu source package in Bionic:
  Fix Released
Status in qemu source package in Cosmic:
  Fix Released
Status in qemu source package in Disco:
  Fix Released

Bug description:
  [impact]

  on shutdown of a guest, there is a race condition that results in qemu
  crashing instead of normally shutting down.  The bt looks similar to
  this (depending on the specific version of qemu, of course; this is
  taken from 2.5 version of qemu):

  (gdb) bt
  #0  __GI___pthread_mutex_lock (mutex=0x0) at ../nptl/pthread_mutex_lock.c:66
  #1  0x5636c0bc4389 in qemu_mutex_lock (mutex=mutex@entry=0x0) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/util/qemu-thread-posix.c:73
  #2  0x5636c0988130 in qemu_chr_fe_write_all (s=s@entry=0x0, 
buf=buf@entry=0x7ffe65c086a0 "\v", len=len@entry=20) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/qemu-char.c:205
  #3  0x5636c08f3483 in vhost_user_write (msg=msg@entry=0x7ffe65c086a0, 
fds=fds@entry=0x0, fd_num=fd_num@entry=0, dev=0x5636c1bf6b70, 
dev=0x5636c1bf6b70)
  at /build/qemu-7I4i1R/qemu-2.5+dfsg/hw/virtio/vhost-user.c:195
  #4  0x5636c08f411c in vhost_user_get_vring_base (dev=0x5636c1bf6b70, 
ring=0x7ffe65c087e0) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/hw/virtio/vhost-user.c:364
  #5  0x5636c08efff0 in vhost_virtqueue_stop (dev=dev@entry=0x5636c1bf6b70, 
vdev=vdev@entry=0x5636c2853338, vq=0x5636c1bf6d00, idx=1) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/hw/virtio/vhost.c:895
  #6  0x5636c08f2944 in vhost_dev_stop (hdev=hdev@entry=0x5636c1bf6b70, 
vdev=vdev@entry=0x5636c2853338) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/hw/virtio/vhost.c:1262
  #7  0x5636c08db2a8 in vhost_net_stop_one (net=0x5636c1bf6b70, 
dev=dev@entry=0x5636c2853338) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/hw/net/vhost_net.c:293
  #8  0x5636c08dbe5b in vhost_net_stop (dev=dev@entry=0x5636c2853338, 
ncs=0x5636c209d110, total_queues=total_queues@entry=1) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/hw/net/vhost_net.c:371
  #9  0x5636c08d7745 in virtio_net_vhost_status (status=7 '\a', 
n=0x5636c2853338) at /build/qemu-7I4i1R/qemu-2.5+dfsg/hw/net/virtio-net.c:150
  #10 virtio_net_set_status (vdev=, status=) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/hw/net/virtio-net.c:162
  #11 0x5636c08ec42c in virtio_set_status (vdev=0x5636c2853338, 
val=) at /build/qemu-7I4i1R/qemu-2.5+dfsg/hw/virtio/virtio.c:624
  #12 0x5636c098fed2 in vm_state_notify (running=running@entry=0, 
state=state@entry=RUN_STATE_SHUTDOWN) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/vl.c:1605
  #13 0x5636c089172a in do_vm_stop (state=RUN_STATE_SHUTDOWN) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/cpus.c:724
  #14 vm_stop (state=RUN_STATE_SHUTDOWN) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/cpus.c:1407
  #15 0x5636c085d240 in main_loop_should_exit () at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/vl.c:1883
  #16 main_loop () at /build/qemu-7I4i1R/qemu-2.5+dfsg/vl.c:1931
  #17 main (argc=, argv=, envp=) 
at /build/qemu-7I4i1R/qemu-2.5+dfsg/vl.c:4683

  [test case]

  unfortunately since this is a race condition, it's very hard to
  arbitrarily reproduce; it depends very much on the overall
  configuration of the guest as well as how exactly it's shut down -
  specifically, its vhost user net must be closed from the host side at
  a specific time during qemu shutdown.

  I have someone with 

[Qemu-devel] [Bug 1823458] Please test proposed package

2019-04-24 Thread Corey Bryant
Hello Dan, or anyone else affected,

Accepted qemu into mitaka-proposed. The package will build now and be
available in the Ubuntu Cloud Archive in a few hours, and then in the
-proposed repository.

Please help us by testing this new package. To enable the -proposed
repository:

  sudo add-apt-repository cloud-archive:mitaka-proposed
  sudo apt-get update

Your feedback will aid us getting this update out to other Ubuntu users.

If this package fixes the bug for you, please add a comment to this bug,
mentioning the version of the package you tested, and change the tag
from verification-mitaka-needed to verification-mitaka-done. If it does
not fix the bug for you, please add a comment stating that, and change
the tag to verification-mitaka-failed. In either case, details of your
testing will help us make a better decision.

Further information regarding the verification process can be found at
https://wiki.ubuntu.com/QATeam/PerformingSRUVerification . Thank you in
advance!

** Changed in: cloud-archive/mitaka
   Status: Triaged => Fix Committed

** Tags added: verification-mitaka-needed

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

Title:
  race condition between vhost_net_stop and CHR_EVENT_CLOSED on shutdown
  crashes qemu

Status in Ubuntu Cloud Archive:
  Fix Released
Status in Ubuntu Cloud Archive mitaka series:
  Fix Committed
Status in Ubuntu Cloud Archive ocata series:
  Fix Committed
Status in QEMU:
  Fix Released
Status in qemu package in Ubuntu:
  Fix Released
Status in qemu source package in Trusty:
  Won't Fix
Status in qemu source package in Xenial:
  Fix Committed
Status in qemu source package in Bionic:
  Fix Released
Status in qemu source package in Cosmic:
  Fix Released
Status in qemu source package in Disco:
  Fix Released

Bug description:
  [impact]

  on shutdown of a guest, there is a race condition that results in qemu
  crashing instead of normally shutting down.  The bt looks similar to
  this (depending on the specific version of qemu, of course; this is
  taken from 2.5 version of qemu):

  (gdb) bt
  #0  __GI___pthread_mutex_lock (mutex=0x0) at ../nptl/pthread_mutex_lock.c:66
  #1  0x5636c0bc4389 in qemu_mutex_lock (mutex=mutex@entry=0x0) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/util/qemu-thread-posix.c:73
  #2  0x5636c0988130 in qemu_chr_fe_write_all (s=s@entry=0x0, 
buf=buf@entry=0x7ffe65c086a0 "\v", len=len@entry=20) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/qemu-char.c:205
  #3  0x5636c08f3483 in vhost_user_write (msg=msg@entry=0x7ffe65c086a0, 
fds=fds@entry=0x0, fd_num=fd_num@entry=0, dev=0x5636c1bf6b70, 
dev=0x5636c1bf6b70)
  at /build/qemu-7I4i1R/qemu-2.5+dfsg/hw/virtio/vhost-user.c:195
  #4  0x5636c08f411c in vhost_user_get_vring_base (dev=0x5636c1bf6b70, 
ring=0x7ffe65c087e0) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/hw/virtio/vhost-user.c:364
  #5  0x5636c08efff0 in vhost_virtqueue_stop (dev=dev@entry=0x5636c1bf6b70, 
vdev=vdev@entry=0x5636c2853338, vq=0x5636c1bf6d00, idx=1) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/hw/virtio/vhost.c:895
  #6  0x5636c08f2944 in vhost_dev_stop (hdev=hdev@entry=0x5636c1bf6b70, 
vdev=vdev@entry=0x5636c2853338) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/hw/virtio/vhost.c:1262
  #7  0x5636c08db2a8 in vhost_net_stop_one (net=0x5636c1bf6b70, 
dev=dev@entry=0x5636c2853338) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/hw/net/vhost_net.c:293
  #8  0x5636c08dbe5b in vhost_net_stop (dev=dev@entry=0x5636c2853338, 
ncs=0x5636c209d110, total_queues=total_queues@entry=1) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/hw/net/vhost_net.c:371
  #9  0x5636c08d7745 in virtio_net_vhost_status (status=7 '\a', 
n=0x5636c2853338) at /build/qemu-7I4i1R/qemu-2.5+dfsg/hw/net/virtio-net.c:150
  #10 virtio_net_set_status (vdev=, status=) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/hw/net/virtio-net.c:162
  #11 0x5636c08ec42c in virtio_set_status (vdev=0x5636c2853338, 
val=) at /build/qemu-7I4i1R/qemu-2.5+dfsg/hw/virtio/virtio.c:624
  #12 0x5636c098fed2 in vm_state_notify (running=running@entry=0, 
state=state@entry=RUN_STATE_SHUTDOWN) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/vl.c:1605
  #13 0x5636c089172a in do_vm_stop (state=RUN_STATE_SHUTDOWN) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/cpus.c:724
  #14 vm_stop (state=RUN_STATE_SHUTDOWN) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/cpus.c:1407
  #15 0x5636c085d240 in main_loop_should_exit () at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/vl.c:1883
  #16 main_loop () at /build/qemu-7I4i1R/qemu-2.5+dfsg/vl.c:1931
  #17 main (argc=, argv=, envp=) 
at /build/qemu-7I4i1R/qemu-2.5+dfsg/vl.c:4683

  [test case]

  unfortunately since this is a race condition, it's very hard to
  arbitrarily reproduce; it depends very much on the overall
  configuration of the guest as well as how exactly it's shut down -
  specifically, its vhost user net must be closed from the host side at
  a specific time during qemu shutdown.

  I have 

Re: [Qemu-devel] [PATCH 5/6] tests: Run the iotests during "make check" again

2019-04-24 Thread Wainer dos Santos Moschetta

Hi Thomas,


On 04/24/2019 07:37 AM, Thomas Huth wrote:

People often forget to run the iotests before submitting patches or
pull requests - this is likely due to the fact that we do not run the
tests during our mandatory "make check" tests yet. Now that we've got
a new "ci" group of iotests that should be fine to run in every environ-
ment, it should be OK to enable the iotests during "make check" again.
Thus we now run the "ci" tests by default from the qemu-iotests-quick.sh
script, and only use the former "quick" group (that contains some tests
that are failing in some environments) when the user decided to run
"make check SPEED=thorough" or something similar.

Signed-off-by: Thomas Huth 
---
  tests/Makefile.include  |  2 +-
  tests/qemu-iotests-quick.sh | 17 -
  2 files changed, 17 insertions(+), 2 deletions(-)


One of Patchew's runners failed with this patch series:
https://patchew.org/QEMU/20190424103747.10173-1-th...@redhat.com/

I encountered same failures with `make check` locally on Fedora 29 
x86_64 (pulled latest qemu, and configured with defaults and 
x86_64-softmmu target):

---
Not run: 233
Failures: 069 103 114 133 140 143 197 215 226 244
Failed 10 of 91 tests
---

Let me know if you need more details.

- Wainer



diff --git a/tests/Makefile.include b/tests/Makefile.include
index 36fc73fef5..eb6a7a41e2 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -1168,7 +1168,7 @@ check-acceptance: check-venv $(TESTS_RESULTS_DIR)
  check-qapi-schema: $(patsubst %,check-%, $(check-qapi-schema-y)) 
check-tests/qapi-schema/doc-good.texi
  check-qtest: $(patsubst %,check-qtest-%, $(QTEST_TARGETS))
  check-block: $(patsubst %,check-%, $(check-block-y))
-check: check-qapi-schema check-unit check-softfloat check-qtest 
check-decodetree
+check: check-qapi-schema check-unit check-softfloat check-qtest 
check-decodetree check-block
  check-clean:
rm -rf $(check-unit-y) tests/*.o $(QEMU_IOTESTS_HELPERS-y)
rm -rf $(sort $(foreach target,$(SYSEMU_TARGET_LIST), 
$(check-qtest-$(target)-y)) $(check-qtest-generic-y))
diff --git a/tests/qemu-iotests-quick.sh b/tests/qemu-iotests-quick.sh
index 0e554bb972..416b3fc48b 100755
--- a/tests/qemu-iotests-quick.sh
+++ b/tests/qemu-iotests-quick.sh
@@ -1,8 +1,23 @@
  #!/bin/sh
  
+# Honor the SPEED environment variable, just like we do it for the qtests.

+# The default is to run all tests that still work fine in a CI environments,
+# but if the user set SPEED=slow or SPEED=thorough, we also run all other
+# tests that are still marked as "quick"
+if [ "$SPEED" = "slow" -o "$SPEED" = "thorough" ]; then
+group=quick
+else
+group=ci
+fi
+
+if [ -z "$(find . -name 'qemu-system-*' -print)" ]; then
+echo "No qemu-system binary available. Skipped qemu-iotests."
+exit 0
+fi
+
  cd tests/qemu-iotests
  
  ret=0

-TEST_DIR=${TEST_DIR:-/tmp/qemu-iotests-quick-$$} ./check -T -qcow2 -g quick || 
ret=1
+TEST_DIR=${TEST_DIR:-/tmp/qemu-iotests-quick-$$} ./check -T -qcow2 -g "$group" 
|| ret=1
  
  exit $ret





Re: [Qemu-devel] [RFC PATCH v1 00/10] Add AMD SEV guest live migration support

2019-04-24 Thread Steve Rutherford via Qemu-devel
On Wed, Apr 24, 2019 at 9:10 AM Singh, Brijesh  wrote:
>
> The series add support for AMD SEV guest live migration commands. To protect 
> the
> confidentiality of an SEV protected guest memory while in transit we need to
> use the SEV commands defined in SEV API spec [1].
>
> SEV guest VMs have the concept of private and shared memory. Private memory
> is encrypted with the guest-specific key, while shared memory may be encrypted
> with hypervisor key. The commands provided by the SEV FW are meant to be used
> for the private memory only. The patch series introduces a new hypercall.
> The guest OS can use this hypercall to notify the page encryption status.
> If the page is encrypted with guest specific-key then we use SEV command 
> during
> the migration. If page is not encrypted then fallback to default.
>
> The patch adds a new ioctl KVM_GET_PAGE_ENC_BITMAP. The ioctl can be used
> by the qemu to get the page encrypted bitmap. Qemu can consult this bitmap
> during the migration to know whether the page is encrypted.
>
> [1] https://developer.amd.com/wp-content/resources/55766.PDF
>
> The series is tested with the Qemu, I am in process of cleaning
> up the Qemu code and will submit soon.
>
> While implementing the migration I stumbled on the follow question:
>
> - Since there is a guest OS changes required to support the migration,
>   so how do we know whether guest OS is updated? Should we extend KVM
>   capabilities/feature bits to check this?
>
> TODO:
>  - add an ioctl to build encryption bitmap. The encryption bitmap is built 
> during
>the guest bootup/execution. We should provide an ioctl so that destination
>can build the bitmap as it receives the pages.
>  - reset the bitmap on guest reboot.
>
> The complete tree with patch is available at:
> https://github.com/codomania/kvm/tree/sev-migration-rfc-v1
>
> Cc: Thomas Gleixner 
> Cc: Ingo Molnar 
> Cc: "H. Peter Anvin" 
> Cc: Paolo Bonzini 
> Cc: "Radim Krčmář" 
> Cc: Joerg Roedel 
> Cc: Borislav Petkov 
> Cc: Tom Lendacky 
> Cc: x...@kernel.org
> Cc: k...@vger.kernel.org
> Cc: linux-ker...@vger.kernel.org
>
> Brijesh Singh (10):
>   KVM: SVM: Add KVM_SEV SEND_START command
>   KVM: SVM: Add KVM_SEND_UPDATE_DATA command
>   KVM: SVM: Add KVM_SEV_SEND_FINISH command
>   KVM: SVM: Add support for KVM_SEV_RECEIVE_START command
>   KVM: SVM: Add KVM_SEV_RECEIVE_UPDATE_DATA command
>   KVM: SVM: Add KVM_SEV_RECEIVE_FINISH command
>   KVM: x86: Add AMD SEV specific Hypercall3
>   KVM: X86: Introduce KVM_HC_PAGE_ENC_STATUS hypercall
>   KVM: x86: Introduce KVM_GET_PAGE_ENC_BITMAP ioctl
>   mm: x86: Invoke hypercall when page encryption status is changed
>
>  .../virtual/kvm/amd-memory-encryption.rst | 116 
>  Documentation/virtual/kvm/hypercalls.txt  |  14 +
>  arch/x86/include/asm/kvm_host.h   |   3 +
>  arch/x86/include/asm/kvm_para.h   |  12 +
>  arch/x86/include/asm/mem_encrypt.h|   3 +
>  arch/x86/kvm/svm.c| 560 +-
>  arch/x86/kvm/vmx/vmx.c|   1 +
>  arch/x86/kvm/x86.c|  17 +
>  arch/x86/mm/mem_encrypt.c |  45 +-
>  arch/x86/mm/pageattr.c|  15 +
>  include/uapi/linux/kvm.h  |  51 ++
>  include/uapi/linux/kvm_para.h |   1 +
>  12 files changed, 834 insertions(+), 4 deletions(-)
>
> --
> 2.17.1
>

What's the back-of-the-envelope marginal cost of transferring a 16kB
region from one host to another? I'm interested in what the end to end
migration perf changes look like for this. If you have measured
migration perf, I'm interested in that also.



[Qemu-devel] [PATCH v5 17/21] gdbstub: Implement v commands with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 170 +++---
 1 file changed, 110 insertions(+), 60 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 809503c20a..7bc00d7f77 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1816,6 +1816,106 @@ static void handle_step(GdbCmdContext *gdb_ctx, void 
*user_ctx)
 gdb_continue(gdb_ctx->s);
 }
 
+static void handle_v_cont_query(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+put_packet(gdb_ctx->s, "vCont;c;C;s;S");
+}
+
+static void handle_v_cont(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+int res;
+
+if (!gdb_ctx->num_params) {
+return;
+}
+
+res = gdb_handle_vcont(gdb_ctx->s, gdb_ctx->params[0].data);
+if ((res == -EINVAL) || (res == -ERANGE)) {
+put_packet(gdb_ctx->s, "E22");
+} else if (res) {
+put_packet(gdb_ctx->s, "\0");
+}
+}
+
+static void handle_v_attach(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+GDBProcess *process;
+CPUState *cpu;
+char thread_id[16];
+
+strcpy(gdb_ctx->str_buf, "E22");
+if (!gdb_ctx->num_params) {
+goto cleanup;
+}
+
+process = gdb_get_process(gdb_ctx->s, gdb_ctx->params[0].val_ul);
+if (!process) {
+goto cleanup;
+}
+
+cpu = get_first_cpu_in_process(gdb_ctx->s, process);
+if (!cpu) {
+goto cleanup;
+}
+
+process->attached = true;
+gdb_ctx->s->g_cpu = cpu;
+gdb_ctx->s->c_cpu = cpu;
+
+gdb_fmt_thread_id(gdb_ctx->s, cpu, thread_id, sizeof(thread_id));
+snprintf(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf), "T%02xthread:%s;",
+ GDB_SIGNAL_TRAP, thread_id);
+cleanup:
+put_packet(gdb_ctx->s, gdb_ctx->str_buf);
+}
+
+static void handle_v_kill(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+/* Kill the target */
+put_packet(gdb_ctx->s, "OK");
+error_report("QEMU: Terminated via GDBstub");
+exit(0);
+}
+
+static GdbCmdParseEntry gdb_v_commands_table[] = {
+/* Order is important if has same prefix */
+{
+.handler = handle_v_cont_query,
+.cmd = "Cont?",
+.cmd_startswith = 1
+},
+{
+.handler = handle_v_cont,
+.cmd = "Cont",
+.cmd_startswith = 1,
+.schema = "s0"
+},
+{
+.handler = handle_v_attach,
+.cmd = "Attach;",
+.cmd_startswith = 1,
+.schema = "l0"
+},
+{
+.handler = handle_v_kill,
+.cmd = "Kill;",
+.cmd_startswith = 1
+},
+};
+
+static void handle_v_commands(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+if (!gdb_ctx->num_params) {
+return;
+}
+
+if (process_string_cmd(gdb_ctx->s, NULL, gdb_ctx->params[0].data,
+   gdb_v_commands_table,
+   ARRAY_SIZE(gdb_v_commands_table))) {
+put_packet(gdb_ctx->s, "");
+}
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1823,7 +1923,7 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 CPUClass *cc;
 const char *p;
 uint32_t pid, tid;
-int ch, type, res;
+int ch, type;
 uint8_t mem_buf[MAX_PACKET_LENGTH];
 char buf[sizeof(mem_buf) + 1 /* trailing NUL */];
 char thread_id[16];
@@ -1872,66 +1972,16 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 }
 break;
 case 'v':
-if (strncmp(p, "Cont", 4) == 0) {
-p += 4;
-if (*p == '?') {
-put_packet(s, "vCont;c;C;s;S");
-break;
-}
-
-res = gdb_handle_vcont(s, p);
-
-if (res) {
-if ((res == -EINVAL) || (res == -ERANGE)) {
-put_packet(s, "E22");
-break;
-}
-goto unknown_command;
-}
-break;
-} else if (strncmp(p, "Attach;", 7) == 0) {
-unsigned long pid;
-
-p += 7;
-
-if (qemu_strtoul(p, , 16, )) {
-put_packet(s, "E22");
-break;
-}
-
-process = gdb_get_process(s, pid);
-
-if (process == NULL) {
-put_packet(s, "E22");
-break;
-}
-
-cpu = get_first_cpu_in_process(s, process);
-
-if (cpu == NULL) {
-/* Refuse to attach an empty process */
-put_packet(s, "E22");
-break;
-}
-
-process->attached = true;
-
-s->g_cpu = cpu;
-s->c_cpu = cpu;
-
-snprintf(buf, sizeof(buf), "T%02xthread:%s;", GDB_SIGNAL_TRAP,
- gdb_fmt_thread_id(s, cpu, thread_id, sizeof(thread_id)));
-
-put_packet(s, buf);
-break;
-} else if (strncmp(p, "Kill;", 5) == 0) {
-/* Kill the target */
-put_packet(s, "OK");
-error_report("QEMU: Terminated via GDBstub");
-   

[Qemu-devel] [PATCH v5 20/21] gdbstub Implement target halted (? pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 36 ++--
 1 file changed, 26 insertions(+), 10 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 779da2aa77..8838241209 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -2248,13 +2248,30 @@ static void handle_gen_set(GdbCmdContext *gdb_ctx, void 
*user_ctx)
 put_packet(gdb_ctx->s, "");
 }
 
+static void handle_target_halt(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+char thread_id[16];
+
+/* TODO: Make this return the correct value for user-mode.  */
+gdb_fmt_thread_id(gdb_ctx->s, gdb_ctx->s->c_cpu, thread_id,
+  sizeof(thread_id));
+snprintf(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf), "T%02xthread:%s;",
+ GDB_SIGNAL_TRAP, thread_id);
+put_packet(gdb_ctx->s, gdb_ctx->str_buf);
+/*
+ * Remove all the breakpoints when this query is issued,
+ * because gdb is doing and initial connect and the state
+ * should be cleaned up.
+ */
+gdb_breakpoint_remove_all();
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 const char *p;
 int ch;
 uint8_t mem_buf[MAX_PACKET_LENGTH];
 char buf[sizeof(mem_buf) + 1 /* trailing NUL */];
-char thread_id[16];
 const GdbCmdParseEntry *cmd_parser = NULL;
 
 trace_gdbstub_io_command(line_buf);
@@ -2266,15 +2283,14 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 put_packet(s, "OK");
 break;
 case '?':
-/* TODO: Make this return the correct value for user-mode.  */
-snprintf(buf, sizeof(buf), "T%02xthread:%s;", GDB_SIGNAL_TRAP,
- gdb_fmt_thread_id(s, s->c_cpu, thread_id, sizeof(thread_id)));
-put_packet(s, buf);
-/* Remove all the breakpoints when this query is issued,
- * because gdb is doing and initial connect and the state
- * should be cleaned up.
- */
-gdb_breakpoint_remove_all();
+{
+static const GdbCmdParseEntry target_halted_cmd_desc = {
+.handler = handle_target_halt,
+.cmd = "?",
+.cmd_startswith = 1
+};
+cmd_parser = _halted_cmd_desc;
+}
 break;
 case 'c':
 {
-- 
2.20.1




[Qemu-devel] [PATCH v5 14/21] gdbstub: Implement read all registers (g pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 31 +++
 1 file changed, 23 insertions(+), 8 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index acf0e75908..3a7ef5eea6 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1758,6 +1758,21 @@ static void handle_write_all_regs(GdbCmdContext 
*gdb_ctx, void *user_ctx)
 put_packet(gdb_ctx->s, "OK");
 }
 
+static void handle_read_all_regs(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+target_ulong addr, len;
+
+cpu_synchronize_state(gdb_ctx->s->g_cpu);
+len = 0;
+for (addr = 0; addr < gdb_ctx->s->g_cpu->gdb_num_g_regs; addr++) {
+len += gdb_read_register(gdb_ctx->s->g_cpu, gdb_ctx->mem_buf + len,
+ addr);
+}
+
+memtohex(gdb_ctx->str_buf, gdb_ctx->mem_buf, len);
+put_packet(gdb_ctx->s, gdb_ctx->str_buf);
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1765,7 +1780,7 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 CPUClass *cc;
 const char *p;
 uint32_t pid, tid;
-int ch, reg_size, type, res;
+int ch, type, res;
 uint8_t mem_buf[MAX_PACKET_LENGTH];
 char buf[sizeof(mem_buf) + 1 /* trailing NUL */];
 char thread_id[16];
@@ -1924,14 +1939,14 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 }
 break;
 case 'g':
-cpu_synchronize_state(s->g_cpu);
-len = 0;
-for (addr = 0; addr < s->g_cpu->gdb_num_g_regs; addr++) {
-reg_size = gdb_read_register(s->g_cpu, mem_buf + len, addr);
-len += reg_size;
+{
+static const GdbCmdParseEntry read_all_regs_cmd_desc = {
+.handler = handle_read_all_regs,
+.cmd = "g",
+.cmd_startswith = 1
+};
+cmd_parser = _all_regs_cmd_desc;
 }
-memtohex(buf, mem_buf, len);
-put_packet(s, buf);
 break;
 case 'G':
 {
-- 
2.20.1




[Qemu-devel] [PATCH v5 19/21] gdbstub: Implement generic set (Q pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 213 +++---
 1 file changed, 25 insertions(+), 188 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index a2db1ec661..779da2aa77 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1130,14 +1130,6 @@ static GDBThreadIdKind read_thread_id(const char *buf, 
const char **end_buf,
 return GDB_ONE_THREAD;
 }
 
-static int is_query_packet(const char *p, const char *query, char separator)
-{
-unsigned int query_len = strlen(query);
-
-return strncmp(p, query, query_len) == 0 &&
-(p[query_len] == '\0' || p[query_len] == separator);
-}
-
 /**
  * gdb_handle_vcont - Parses and handles a vCont packet.
  * returns -ENOTSUP if a command is unsupported, -EINVAL or -ERANGE if there is
@@ -2241,18 +2233,28 @@ static void handle_gen_query(GdbCmdContext *gdb_ctx, 
void *user_ctx)
 }
 }
 
+static void handle_gen_set(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+if (!gdb_ctx->num_params) {
+return;
+}
+
+if (!process_string_cmd(gdb_ctx->s, NULL, gdb_ctx->params[0].data,
+gdb_gen_query_set_common_table,
+ARRAY_SIZE(gdb_gen_query_set_common_table))) {
+return;
+}
+
+put_packet(gdb_ctx->s, "");
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
-CPUState *cpu;
-GDBProcess *process;
-CPUClass *cc;
 const char *p;
-uint32_t pid, tid;
-int ch, type;
+int ch;
 uint8_t mem_buf[MAX_PACKET_LENGTH];
 char buf[sizeof(mem_buf) + 1 /* trailing NUL */];
 char thread_id[16];
-target_ulong addr, len;
 const GdbCmdParseEntry *cmd_parser = NULL;
 
 trace_gdbstub_io_command(line_buf);
@@ -2465,182 +2467,17 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 }
 break;
 case 'Q':
-/* parse any 'q' packets here */
-if (!strcmp(p,"qemu.sstepbits")) {
-/* Query Breakpoint bit definitions */
-snprintf(buf, sizeof(buf), "ENABLE=%x,NOIRQ=%x,NOTIMER=%x",
- SSTEP_ENABLE,
- SSTEP_NOIRQ,
- SSTEP_NOTIMER);
-put_packet(s, buf);
-break;
-} else if (is_query_packet(p, "qemu.sstep", '=')) {
-/* Display or change the sstep_flags */
-p += 10;
-if (*p != '=') {
-/* Display current setting */
-snprintf(buf, sizeof(buf), "0x%x", sstep_flags);
-put_packet(s, buf);
-break;
-}
-p++;
-type = strtoul(p, (char **), 16);
-sstep_flags = type;
-put_packet(s, "OK");
-break;
-} else if (strcmp(p,"C") == 0) {
-/*
- * "Current thread" remains vague in the spec, so always return
- * the first thread of the current process (gdb returns the
- * first thread).
- */
-cpu = get_first_cpu_in_process(s, gdb_get_cpu_process(s, 
s->g_cpu));
-snprintf(buf, sizeof(buf), "QC%s",
- gdb_fmt_thread_id(s, cpu, thread_id, sizeof(thread_id)));
-put_packet(s, buf);
-break;
-} else if (strcmp(p,"fThreadInfo") == 0) {
-s->query_cpu = gdb_first_attached_cpu(s);
-goto report_cpuinfo;
-} else if (strcmp(p,"sThreadInfo") == 0) {
-report_cpuinfo:
-if (s->query_cpu) {
-snprintf(buf, sizeof(buf), "m%s",
- gdb_fmt_thread_id(s, s->query_cpu,
-   thread_id, sizeof(thread_id)));
-put_packet(s, buf);
-s->query_cpu = gdb_next_attached_cpu(s, s->query_cpu);
-} else
-put_packet(s, "l");
-break;
-} else if (strncmp(p,"ThreadExtraInfo,", 16) == 0) {
-if (read_thread_id(p + 16, , , ) == GDB_READ_THREAD_ERR) 
{
-put_packet(s, "E22");
-break;
-}
-cpu = gdb_get_cpu(s, pid, tid);
-if (cpu != NULL) {
-cpu_synchronize_state(cpu);
-
-if (s->multiprocess && (s->process_num > 1)) {
-/* Print the CPU model and name in multiprocess mode */
-ObjectClass *oc = object_get_class(OBJECT(cpu));
-const char *cpu_model = object_class_get_name(oc);
-char *cpu_name =
-object_get_canonical_path_component(OBJECT(cpu));
-len = snprintf((char *)mem_buf, sizeof(buf) / 2,
-   "%s %s [%s]", cpu_model, cpu_name,
-   cpu->halted ? "halted " : "running");
-g_free(cpu_name);
-} else {
-/* memtohex() doubles the required space */
-len = 

[Qemu-devel] [PATCH v5 13/21] gdbstub: Implement write all registers (G pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 41 +++--
 1 file changed, 31 insertions(+), 10 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 5b60c1369c..acf0e75908 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1735,6 +1735,29 @@ static void handle_read_mem(GdbCmdContext *gdb_ctx, void 
*user_ctx)
 put_packet(gdb_ctx->s, gdb_ctx->str_buf);
 }
 
+static void handle_write_all_regs(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+target_ulong addr, len;
+uint8_t *registers;
+int reg_size;
+
+if (!gdb_ctx->num_params) {
+return;
+}
+
+cpu_synchronize_state(gdb_ctx->s->g_cpu);
+registers = gdb_ctx->mem_buf;
+len = strlen(gdb_ctx->params[0].data) / 2;
+hextomem(registers, gdb_ctx->params[0].data, len);
+for (addr = 0; addr < gdb_ctx->s->g_cpu->gdb_num_g_regs && len > 0;
+ addr++) {
+reg_size = gdb_write_register(gdb_ctx->s->g_cpu, registers, addr);
+len -= reg_size;
+registers += reg_size;
+}
+put_packet(gdb_ctx->s, "OK");
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1746,7 +1769,6 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 uint8_t mem_buf[MAX_PACKET_LENGTH];
 char buf[sizeof(mem_buf) + 1 /* trailing NUL */];
 char thread_id[16];
-uint8_t *registers;
 target_ulong addr, len;
 const GdbCmdParseEntry *cmd_parser = NULL;
 
@@ -1912,16 +1934,15 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 put_packet(s, buf);
 break;
 case 'G':
-cpu_synchronize_state(s->g_cpu);
-registers = mem_buf;
-len = strlen(p) / 2;
-hextomem((uint8_t *)registers, p, len);
-for (addr = 0; addr < s->g_cpu->gdb_num_g_regs && len > 0; addr++) {
-reg_size = gdb_write_register(s->g_cpu, registers, addr);
-len -= reg_size;
-registers += reg_size;
+{
+static const GdbCmdParseEntry write_all_regs_cmd_desc = {
+.handler = handle_write_all_regs,
+.cmd = "G",
+.cmd_startswith = 1,
+.schema = "s0"
+};
+cmd_parser = _all_regs_cmd_desc;
 }
-put_packet(s, "OK");
 break;
 case 'm':
 {
-- 
2.20.1




[Qemu-devel] [PATCH v5 16/21] gdbstub: Implement step (s pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 25 +++--
 1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 18949120be..809503c20a 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1806,6 +1806,16 @@ static void handle_file_io(GdbCmdContext *gdb_ctx, void 
*user_ctx)
 gdb_continue(gdb_ctx->s);
 }
 
+static void handle_step(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+if (gdb_ctx->num_params) {
+gdb_set_cpu_pc(gdb_ctx->s, (target_ulong)gdb_ctx->params[0].val_ull);
+}
+
+cpu_single_step(gdb_ctx->s->c_cpu, sstep_flags);
+gdb_continue(gdb_ctx->s);
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1938,13 +1948,16 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 }
 break;
 case 's':
-if (*p != '\0') {
-addr = strtoull(p, (char **), 16);
-gdb_set_cpu_pc(s, addr);
+{
+static const GdbCmdParseEntry step_cmd_desc = {
+.handler = handle_step,
+.cmd = "s",
+.cmd_startswith = 1,
+.schema = "L0"
+};
+cmd_parser = _cmd_desc;
 }
-cpu_single_step(s->c_cpu, sstep_flags);
-gdb_continue(s);
-return RS_IDLE;
+break;
 case 'F':
 {
 static const GdbCmdParseEntry file_io_cmd_desc = {
-- 
2.20.1




[Qemu-devel] [PATCH v5 21/21] gdbstub: Clear unused variables in gdb_handle_packet

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 11 ++-
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 8838241209..32aeefbbe6 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -2268,17 +2268,11 @@ static void handle_target_halt(GdbCmdContext *gdb_ctx, 
void *user_ctx)
 
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
-const char *p;
-int ch;
-uint8_t mem_buf[MAX_PACKET_LENGTH];
-char buf[sizeof(mem_buf) + 1 /* trailing NUL */];
 const GdbCmdParseEntry *cmd_parser = NULL;
 
 trace_gdbstub_io_command(line_buf);
 
-p = line_buf;
-ch = *p++;
-switch(ch) {
+switch(line_buf[0]) {
 case '!':
 put_packet(s, "OK");
 break;
@@ -2495,8 +2489,7 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 break;
 default:
 /* put empty packet */
-buf[0] = '\0';
-put_packet(s, buf);
+put_packet(s, "");
 break;
 }
 
-- 
2.20.1




[Qemu-devel] [PATCH v5 12/21] gdbstub: Implement read memory (m pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 48 
 1 file changed, 32 insertions(+), 16 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 4522c93fa2..5b60c1369c 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1711,6 +1711,30 @@ static void handle_write_mem(GdbCmdContext *gdb_ctx, 
void *user_ctx)
 put_packet(gdb_ctx->s, "OK");
 }
 
+static void handle_read_mem(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+if (gdb_ctx->num_params < 2) {
+put_packet(gdb_ctx->s, "E22");
+return;
+}
+
+/* memtohex() doubles the required space */
+if (gdb_ctx->params[1].val_ull > MAX_PACKET_LENGTH / 2) {
+put_packet(gdb_ctx->s, "E22");
+return;
+}
+
+if (target_memory_rw_debug(gdb_ctx->s->g_cpu, gdb_ctx->params[0].val_ull,
+   gdb_ctx->mem_buf,
+   gdb_ctx->params[1].val_ull, false)) {
+put_packet(gdb_ctx->s, "E14");
+return;
+}
+
+memtohex(gdb_ctx->str_buf, gdb_ctx->mem_buf, gdb_ctx->params[1].val_ull);
+put_packet(gdb_ctx->s, gdb_ctx->str_buf);
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1900,22 +1924,14 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 put_packet(s, "OK");
 break;
 case 'm':
-addr = strtoull(p, (char **), 16);
-if (*p == ',')
-p++;
-len = strtoull(p, NULL, 16);
-
-/* memtohex() doubles the required space */
-if (len > MAX_PACKET_LENGTH / 2) {
-put_packet (s, "E22");
-break;
-}
-
-if (target_memory_rw_debug(s->g_cpu, addr, mem_buf, len, false) != 0) {
-put_packet (s, "E14");
-} else {
-memtohex(buf, mem_buf, len);
-put_packet(s, buf);
+{
+static const GdbCmdParseEntry read_mem_cmd_desc = {
+.handler = handle_read_mem,
+.cmd = "m",
+.cmd_startswith = 1,
+.schema = "L,L0"
+};
+cmd_parser = _mem_cmd_desc;
 }
 break;
 case 'M':
-- 
2.20.1




[Qemu-devel] [PATCH v5 08/21] gdbstub: Implement remove breakpoint (z pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 49 -
 1 file changed, 32 insertions(+), 17 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 8e0446d305..80f2a92da6 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1612,6 +1612,29 @@ static void handle_insert_bp(GdbCmdContext *gdb_ctx, 
void *user_ctx)
 put_packet(gdb_ctx->s, "E22");
 }
 
+static void handle_remove_bp(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+int res;
+
+if (gdb_ctx->num_params < 3) {
+put_packet(gdb_ctx->s, "E22");
+return;
+}
+
+res = gdb_breakpoint_remove(gdb_ctx->params[1].val_ull,
+gdb_ctx->params[2].val_ull,
+gdb_ctx->params[0].val_ul);
+if (res >= 0) {
+put_packet(gdb_ctx->s, "OK");
+return;
+} else if (res == -ENOSYS) {
+put_packet(gdb_ctx->s, "");
+return;
+}
+
+put_packet(gdb_ctx->s, "E22");
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1878,23 +1901,15 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 }
 break;
 case 'z':
-type = strtoul(p, (char **), 16);
-if (*p == ',')
-p++;
-addr = strtoull(p, (char **), 16);
-if (*p == ',')
-p++;
-len = strtoull(p, (char **), 16);
-if (ch == 'Z')
-res = gdb_breakpoint_insert(addr, len, type);
-else
-res = gdb_breakpoint_remove(addr, len, type);
-if (res >= 0)
- put_packet(s, "OK");
-else if (res == -ENOSYS)
-put_packet(s, "");
-else
-put_packet(s, "E22");
+{
+static const GdbCmdParseEntry remove_bp_cmd_desc = {
+.handler = handle_remove_bp,
+.cmd = "z",
+.cmd_startswith = 1,
+.schema = "l?L?L0"
+};
+cmd_parser = _bp_cmd_desc;
+}
 break;
 case 'H':
 {
-- 
2.20.1




[Qemu-devel] [PATCH v5 15/21] gdbstub: Implement file io (F pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 62 +++
 1 file changed, 40 insertions(+), 22 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 3a7ef5eea6..18949120be 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1773,6 +1773,39 @@ static void handle_read_all_regs(GdbCmdContext *gdb_ctx, 
void *user_ctx)
 put_packet(gdb_ctx->s, gdb_ctx->str_buf);
 }
 
+static void handle_file_io(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+int num_syscall_params;
+GdbCmdVariant syscall_params[3] = {};
+
+if (!gdb_ctx->num_params) {
+return;
+}
+
+if (cmd_parse_params(gdb_ctx->params[0].data, "L,L,o0", syscall_params,
+ _syscall_params)) {
+return;
+}
+
+if (!num_syscall_params) {
+return;
+}
+
+if (gdb_ctx->s->current_syscall_cb) {
+gdb_ctx->s->current_syscall_cb(gdb_ctx->s->c_cpu,
+   (target_ulong)syscall_params[0].val_ull,
+   
(target_ulong)syscall_params[1].val_ull);
+gdb_ctx->s->current_syscall_cb = NULL;
+}
+
+if (syscall_params[2].opcode == (uint8_t)'C') {
+put_packet(gdb_ctx->s, "T02");
+return;
+}
+
+gdb_continue(gdb_ctx->s);
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1914,28 +1947,13 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 return RS_IDLE;
 case 'F':
 {
-target_ulong ret;
-target_ulong err;
-
-ret = strtoull(p, (char **), 16);
-if (*p == ',') {
-p++;
-err = strtoull(p, (char **), 16);
-} else {
-err = 0;
-}
-if (*p == ',')
-p++;
-type = *p;
-if (s->current_syscall_cb) {
-s->current_syscall_cb(s->c_cpu, ret, err);
-s->current_syscall_cb = NULL;
-}
-if (type == 'C') {
-put_packet(s, "T02");
-} else {
-gdb_continue(s);
-}
+static const GdbCmdParseEntry file_io_cmd_desc = {
+.handler = handle_file_io,
+.cmd = "F",
+.cmd_startswith = 1,
+.schema = "s0"
+};
+cmd_parser = _io_cmd_desc;
 }
 break;
 case 'g':
-- 
2.20.1




[Qemu-devel] [PATCH v5 11/21] gdbstub: Implement write memory (M pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 51 +--
 1 file changed, 33 insertions(+), 18 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index c439b8e796..4522c93fa2 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1686,6 +1686,31 @@ static void handle_get_reg(GdbCmdContext *gdb_ctx, void 
*user_ctx)
 put_packet(gdb_ctx->s, gdb_ctx->str_buf);
 }
 
+static void handle_write_mem(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+if (gdb_ctx->num_params < 3) {
+put_packet(gdb_ctx->s, "E22");
+return;
+}
+
+/* hextomem() reads 2*len bytes */
+if (gdb_ctx->params[1].val_ull > strlen(gdb_ctx->params[2].data) / 2) {
+put_packet(gdb_ctx->s, "E22");
+return;
+}
+
+hextomem(gdb_ctx->mem_buf, gdb_ctx->params[2].data,
+ gdb_ctx->params[1].val_ull);
+if (target_memory_rw_debug(gdb_ctx->s->g_cpu, gdb_ctx->params[0].val_ull,
+   gdb_ctx->mem_buf,
+   gdb_ctx->params[1].val_ull, true)) {
+put_packet(gdb_ctx->s, "E14");
+return;
+}
+
+put_packet(gdb_ctx->s, "OK");
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1894,24 +1919,14 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 }
 break;
 case 'M':
-addr = strtoull(p, (char **), 16);
-if (*p == ',')
-p++;
-len = strtoull(p, (char **), 16);
-if (*p == ':')
-p++;
-
-/* hextomem() reads 2*len bytes */
-if (len > strlen(p) / 2) {
-put_packet (s, "E22");
-break;
-}
-hextomem(mem_buf, p, len);
-if (target_memory_rw_debug(s->g_cpu, addr, mem_buf, len,
-   true) != 0) {
-put_packet(s, "E14");
-} else {
-put_packet(s, "OK");
+{
+static const GdbCmdParseEntry write_mem_cmd_desc = {
+.handler = handle_write_mem,
+.cmd = "M",
+.cmd_startswith = 1,
+.schema = "L,L:s0"
+};
+cmd_parser = _mem_cmd_desc;
 }
 break;
 case 'p':
-- 
2.20.1




[Qemu-devel] [PATCH v5 18/21] gdbstub: Implement generic query (q pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 335 ++
 1 file changed, 335 insertions(+)

diff --git a/gdbstub.c b/gdbstub.c
index 7bc00d7f77..a2db1ec661 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1916,6 +1916,331 @@ static void handle_v_commands(GdbCmdContext *gdb_ctx, 
void *user_ctx)
 }
 }
 
+static void handle_query_qemu_sstepbits(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+snprintf(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf),
+ "ENABLE=%x,NOIRQ=%x,NOTIMER=%x", SSTEP_ENABLE,
+ SSTEP_NOIRQ, SSTEP_NOTIMER);
+put_packet(gdb_ctx->s, gdb_ctx->str_buf);
+}
+
+static void handle_set_qemu_sstep(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+if (!gdb_ctx->num_params) {
+return;
+}
+
+sstep_flags = gdb_ctx->params[0].val_ul;
+put_packet(gdb_ctx->s, "OK");
+}
+
+static void handle_query_qemu_sstep(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+snprintf(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf), "0x%x", sstep_flags);
+put_packet(gdb_ctx->s, gdb_ctx->str_buf);
+}
+
+static void handle_query_curr_tid(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+CPUState *cpu;
+GDBProcess *process;
+char thread_id[16];
+
+/*
+ * "Current thread" remains vague in the spec, so always return
+ * the first thread of the current process (gdb returns the
+ * first thread).
+ */
+process = gdb_get_cpu_process(gdb_ctx->s, gdb_ctx->s->g_cpu);
+cpu = get_first_cpu_in_process(gdb_ctx->s, process);
+gdb_fmt_thread_id(gdb_ctx->s, cpu, thread_id, sizeof(thread_id));
+snprintf(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf), "QC%s", thread_id);
+put_packet(gdb_ctx->s, gdb_ctx->str_buf);
+}
+
+static void handle_query_threads(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+char thread_id[16];
+
+if (!gdb_ctx->s->query_cpu) {
+put_packet(gdb_ctx->s, "l");
+return;
+}
+
+gdb_fmt_thread_id(gdb_ctx->s, gdb_ctx->s->query_cpu, thread_id,
+  sizeof(thread_id));
+snprintf(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf), "m%s", thread_id);
+put_packet(gdb_ctx->s, gdb_ctx->str_buf);
+gdb_ctx->s->query_cpu =
+gdb_next_attached_cpu(gdb_ctx->s, gdb_ctx->s->query_cpu);
+}
+
+static void handle_query_first_threads(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+gdb_ctx->s->query_cpu = gdb_first_attached_cpu(gdb_ctx->s);
+handle_query_threads(gdb_ctx, user_ctx);
+}
+
+static void handle_query_thread_extra(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+CPUState *cpu;
+int len;
+
+if (!gdb_ctx->num_params ||
+gdb_ctx->params[0].thread_id.kind == GDB_READ_THREAD_ERR) {
+put_packet(gdb_ctx->s, "E22");
+return;
+}
+
+cpu = gdb_get_cpu(gdb_ctx->s, gdb_ctx->params[0].thread_id.pid,
+  gdb_ctx->params[0].thread_id.tid);
+if (!cpu) {
+return;
+}
+
+cpu_synchronize_state(cpu);
+
+if (gdb_ctx->s->multiprocess && (gdb_ctx->s->process_num > 1)) {
+/* Print the CPU model and name in multiprocess mode */
+ObjectClass *oc = object_get_class(OBJECT(cpu));
+const char *cpu_model = object_class_get_name(oc);
+char *cpu_name = object_get_canonical_path_component(OBJECT(cpu));
+len = snprintf((char *)gdb_ctx->mem_buf, sizeof(gdb_ctx->str_buf) / 2,
+   "%s %s [%s]", cpu_model, cpu_name,
+   cpu->halted ? "halted " : "running");
+g_free(cpu_name);
+} else {
+/* memtohex() doubles the required space */
+len = snprintf((char *)gdb_ctx->mem_buf, sizeof(gdb_ctx->str_buf) / 2,
+"CPU#%d [%s]", cpu->cpu_index,
+cpu->halted ? "halted " : "running");
+}
+trace_gdbstub_op_extra_info((char *)gdb_ctx->mem_buf);
+memtohex(gdb_ctx->str_buf, gdb_ctx->mem_buf, len);
+put_packet(gdb_ctx->s, gdb_ctx->str_buf);
+}
+
+#ifdef CONFIG_USER_ONLY
+static void handle_query_offsets(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+TaskState *ts;
+
+ts = gdb_ctx->s->c_cpu->opaque;
+snprintf(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf),
+ "Text=" TARGET_ABI_FMT_lx ";Data=" TARGET_ABI_FMT_lx
+ ";Bss=" TARGET_ABI_FMT_lx,
+ ts->info->code_offset,
+ ts->info->data_offset,
+ ts->info->data_offset);
+put_packet(gdb_ctx->s, gdb_ctx->str_buf);
+}
+#else
+static void handle_query_rcmd(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+int len;
+
+if (!gdb_ctx->num_params) {
+put_packet(gdb_ctx->s, "E22");
+return;
+}
+
+len = strlen(gdb_ctx->params[0].data);
+if (len % 2) {
+put_packet(gdb_ctx->s, "E01");
+return;
+}
+
+len = len / 2;
+hextomem(gdb_ctx->mem_buf, gdb_ctx->params[0].data, len);
+gdb_ctx->mem_buf[len++] = 0;
+qemu_chr_be_write(gdb_ctx->s->mon_chr, gdb_ctx->mem_buf, len);
+put_packet(gdb_ctx->s, "OK");
+

[Qemu-devel] [PATCH v5 10/21] gdbstub: Implement get register (p pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 50 ++
 1 file changed, 38 insertions(+), 12 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 49db09ef52..c439b8e796 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1656,6 +1656,36 @@ static void handle_set_reg(GdbCmdContext *gdb_ctx, void 
*user_ctx)
 put_packet(gdb_ctx->s, "OK");
 }
 
+static void handle_get_reg(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+int reg_size;
+
+/*
+ * Older gdb are really dumb, and don't use 'g' if 'p' is avaialable.
+ * This works, but can be very slow.  Anything new enough to
+ * understand XML also knows how to use this properly.
+ */
+if (!gdb_has_xml) {
+put_packet(gdb_ctx->s, "");
+return;
+}
+
+if (!gdb_ctx->num_params) {
+put_packet(gdb_ctx->s, "E14");
+return;
+}
+
+reg_size = gdb_read_register(gdb_ctx->s->g_cpu, gdb_ctx->mem_buf,
+ gdb_ctx->params[0].val_ull);
+if (!reg_size) {
+put_packet(gdb_ctx->s, "E14");
+return;
+}
+
+memtohex(gdb_ctx->str_buf, gdb_ctx->mem_buf, reg_size);
+put_packet(gdb_ctx->s, gdb_ctx->str_buf);
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1885,18 +1915,14 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 }
 break;
 case 'p':
-/* Older gdb are really dumb, and don't use 'g' if 'p' is avaialable.
-   This works, but can be very slow.  Anything new enough to
-   understand XML also knows how to use this properly.  */
-if (!gdb_has_xml)
-goto unknown_command;
-addr = strtoull(p, (char **), 16);
-reg_size = gdb_read_register(s->g_cpu, mem_buf, addr);
-if (reg_size) {
-memtohex(buf, mem_buf, reg_size);
-put_packet(s, buf);
-} else {
-put_packet(s, "E14");
+{
+static const GdbCmdParseEntry get_reg_cmd_desc = {
+.handler = handle_get_reg,
+.cmd = "p",
+.cmd_startswith = 1,
+.schema = "L0"
+};
+cmd_parser = _reg_cmd_desc;
 }
 break;
 case 'P':
-- 
2.20.1




[Qemu-devel] [PATCH v5 06/21] gdbstub: Implement set_thread (H pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 79 ++-
 1 file changed, 49 insertions(+), 30 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 8e922a2df4..83757def9b 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1548,6 +1548,47 @@ static void handle_cont_with_sig(GdbCmdContext *gdb_ctx, 
void *user_ctx)
 gdb_continue(gdb_ctx->s);
 }
 
+static void handle_set_thread(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+CPUState *cpu;
+
+if (gdb_ctx->num_params < 2) {
+put_packet(gdb_ctx->s, "E22");
+return;
+}
+
+if (gdb_ctx->params[1].thread_id.kind == GDB_READ_THREAD_ERR) {
+put_packet(gdb_ctx->s, "E22");
+return;
+}
+
+if (gdb_ctx->params[1].thread_id.kind != GDB_ONE_THREAD) {
+put_packet(gdb_ctx->s, "OK");
+return;
+}
+
+cpu = gdb_get_cpu(gdb_ctx->s, gdb_ctx->params[1].thread_id.pid,
+  gdb_ctx->params[1].thread_id.tid);
+if (!cpu) {
+put_packet(gdb_ctx->s, "E22");
+return;
+}
+
+switch (gdb_ctx->params[0].opcode) {
+case 'c':
+gdb_ctx->s->c_cpu = cpu;
+put_packet(gdb_ctx->s, "OK");
+break;
+case 'g':
+gdb_ctx->s->g_cpu = cpu;
+put_packet(gdb_ctx->s, "OK");
+break;
+default:
+put_packet(gdb_ctx->s, "E22");
+break;
+}
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1561,7 +1602,6 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 char thread_id[16];
 uint8_t *registers;
 target_ulong addr, len;
-GDBThreadIdKind thread_kind;
 const GdbCmdParseEntry *cmd_parser = NULL;
 
 trace_gdbstub_io_command(line_buf);
@@ -1824,35 +1864,14 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 put_packet(s, "E22");
 break;
 case 'H':
-type = *p++;
-
-thread_kind = read_thread_id(p, , , );
-if (thread_kind == GDB_READ_THREAD_ERR) {
-put_packet(s, "E22");
-break;
-}
-
-if (thread_kind != GDB_ONE_THREAD) {
-put_packet(s, "OK");
-break;
-}
-cpu = gdb_get_cpu(s, pid, tid);
-if (cpu == NULL) {
-put_packet(s, "E22");
-break;
-}
-switch (type) {
-case 'c':
-s->c_cpu = cpu;
-put_packet(s, "OK");
-break;
-case 'g':
-s->g_cpu = cpu;
-put_packet(s, "OK");
-break;
-default:
- put_packet(s, "E22");
- break;
+{
+static const GdbCmdParseEntry set_thread_cmd_desc = {
+.handler = handle_set_thread,
+.cmd = "H",
+.cmd_startswith = 1,
+.schema = "o.t0"
+};
+cmd_parser = _thread_cmd_desc;
 }
 break;
 case 'T':
-- 
2.20.1




[Qemu-devel] [PATCH v5 05/21] gdbstub: Implement continue with signal (C pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 30 +-
 1 file changed, 25 insertions(+), 5 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index a38f9d4ef9..8e922a2df4 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1533,6 +1533,21 @@ static void handle_continue(GdbCmdContext *gdb_ctx, void 
*user_ctx)
 gdb_continue(gdb_ctx->s);
 }
 
+static void handle_cont_with_sig(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+unsigned long signal = 0;
+
+if (gdb_ctx->num_params) {
+signal = gdb_ctx->params[0].val_ul;
+}
+
+gdb_ctx->s->signal = gdb_signal_to_target(signal);
+if (gdb_ctx->s->signal == -1) {
+gdb_ctx->s->signal = 0;
+}
+gdb_continue(gdb_ctx->s);
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1580,11 +1595,16 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 }
 break;
 case 'C':
-s->signal = gdb_signal_to_target (strtoul(p, (char **), 16));
-if (s->signal == -1)
-s->signal = 0;
-gdb_continue(s);
-return RS_IDLE;
+{
+static const GdbCmdParseEntry cont_with_sig_cmd_desc = {
+.handler = handle_cont_with_sig,
+.cmd = "C",
+.cmd_startswith = 1,
+.schema = "l0"
+};
+cmd_parser = _with_sig_cmd_desc;
+}
+break;
 case 'v':
 if (strncmp(p, "Cont", 4) == 0) {
 p += 4;
-- 
2.20.1




[Qemu-devel] [PATCH v5 07/21] gdbstub: Implement insert breakpoint (Z pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 33 +
 1 file changed, 33 insertions(+)

diff --git a/gdbstub.c b/gdbstub.c
index 83757def9b..8e0446d305 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1589,6 +1589,29 @@ static void handle_set_thread(GdbCmdContext *gdb_ctx, 
void *user_ctx)
 }
 }
 
+static void handle_insert_bp(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+int res;
+
+if (gdb_ctx->num_params < 3) {
+put_packet(gdb_ctx->s, "E22");
+return;
+}
+
+res = gdb_breakpoint_insert(gdb_ctx->params[1].val_ull,
+gdb_ctx->params[2].val_ull,
+gdb_ctx->params[0].val_ul);
+if (res >= 0) {
+put_packet(gdb_ctx->s, "OK");
+return;
+} else if (res == -ENOSYS) {
+put_packet(gdb_ctx->s, "");
+return;
+}
+
+put_packet(gdb_ctx->s, "E22");
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1844,6 +1867,16 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 put_packet(s, "OK");
 break;
 case 'Z':
+{
+static const GdbCmdParseEntry insert_bp_cmd_desc = {
+.handler = handle_insert_bp,
+.cmd = "Z",
+.cmd_startswith = 1,
+.schema = "l?L?L0"
+};
+cmd_parser = _bp_cmd_desc;
+}
+break;
 case 'z':
 type = strtoul(p, (char **), 16);
 if (*p == ',')
-- 
2.20.1




[Qemu-devel] [PATCH v5 03/21] gdbstub: Implement thread_alive (T pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 43 ---
 1 file changed, 32 insertions(+), 11 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index fdad1ac466..29ca6be3df 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1499,6 +1499,30 @@ static void handle_detach(GdbCmdContext *gdb_ctx, void 
*user_ctx)
 put_packet(s, "OK");
 }
 
+static void handle_thread_alive(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+CPUState *cpu;
+
+if (!gdb_ctx->num_params) {
+put_packet(gdb_ctx->s, "E22");
+return;
+}
+
+if (gdb_ctx->params[0].thread_id.kind == GDB_READ_THREAD_ERR) {
+put_packet(gdb_ctx->s, "E22");
+return;
+}
+
+cpu = gdb_get_cpu(gdb_ctx->s, gdb_ctx->params[0].thread_id.pid,
+  gdb_ctx->params[0].thread_id.tid);
+if (!cpu) {
+put_packet(gdb_ctx->s, "E22");
+return;
+}
+
+put_packet(gdb_ctx->s, "OK");
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1799,17 +1823,14 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 }
 break;
 case 'T':
-thread_kind = read_thread_id(p, , , );
-if (thread_kind == GDB_READ_THREAD_ERR) {
-put_packet(s, "E22");
-break;
-}
-cpu = gdb_get_cpu(s, pid, tid);
-
-if (cpu != NULL) {
-put_packet(s, "OK");
-} else {
-put_packet(s, "E22");
+{
+static const GdbCmdParseEntry thread_alive_cmd_desc = {
+.handler = handle_thread_alive,
+.cmd = "T",
+.cmd_startswith = 1,
+.schema = "t0"
+};
+cmd_parser = _alive_cmd_desc;
 }
 break;
 case 'q':
-- 
2.20.1




[Qemu-devel] [PATCH v5 01/21] gdbstub: Add infrastructure to parse cmd packets

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 200 ++
 1 file changed, 200 insertions(+)

diff --git a/gdbstub.c b/gdbstub.c
index d54abd17cc..3308279fa8 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1268,6 +1268,206 @@ out:
 return res;
 }
 
+typedef union GdbCmdVariant {
+const char *data;
+uint8_t opcode;
+unsigned long val_ul;
+unsigned long long val_ull;
+struct {
+GDBThreadIdKind kind;
+uint32_t pid;
+uint32_t tid;
+} thread_id;
+} GdbCmdVariant;
+
+static const char *cmd_next_param(const char *param, const char delimiter)
+{
+static const char all_delimiters[] = ",;:=";
+char curr_delimiters[2] = {0};
+const char *delimiters;
+
+if (delimiter == '?') {
+delimiters = all_delimiters;
+} else if (delimiter == '0') {
+return strchr(param, '\0');
+} else if (delimiter == '.' && *param) {
+return param + 1;
+} else {
+curr_delimiters[0] = delimiter;
+delimiters = curr_delimiters;
+}
+
+param += strcspn(param, delimiters);
+if (*param) {
+param++;
+}
+return param;
+}
+
+static int cmd_parse_params(const char *data, const char *schema,
+GdbCmdVariant *params, int *num_params)
+{
+int curr_param;
+const char *curr_schema, *curr_data;
+
+*num_params = 0;
+
+if (!schema) {
+return 0;
+}
+
+curr_schema = schema;
+curr_param = 0;
+curr_data = data;
+while (curr_schema[0] && curr_schema[1] && *curr_data) {
+switch (curr_schema[0]) {
+case 'l':
+if (qemu_strtoul(curr_data, _data, 16,
+ [curr_param].val_ul)) {
+return -EINVAL;
+}
+curr_param++;
+curr_data = cmd_next_param(curr_data, curr_schema[1]);
+break;
+case 'L':
+if (qemu_strtou64(curr_data, _data, 16,
+  (uint64_t *)[curr_param].val_ull)) {
+return -EINVAL;
+}
+curr_param++;
+curr_data = cmd_next_param(curr_data, curr_schema[1]);
+break;
+case 's':
+params[curr_param].data = curr_data;
+curr_param++;
+curr_data = cmd_next_param(curr_data, curr_schema[1]);
+break;
+case 'o':
+params[curr_param].opcode = *(uint8_t *)curr_data;
+curr_param++;
+curr_data = cmd_next_param(curr_data, curr_schema[1]);
+break;
+case 't':
+params[curr_param].thread_id.kind =
+read_thread_id(curr_data, _data,
+   [curr_param].thread_id.pid,
+   [curr_param].thread_id.tid);
+curr_param++;
+curr_data = cmd_next_param(curr_data, curr_schema[1]);
+break;
+case '?':
+curr_data = cmd_next_param(curr_data, curr_schema[1]);
+break;
+default:
+return -EINVAL;
+}
+curr_schema += 2;
+}
+
+*num_params = curr_param;
+return 0;
+}
+
+typedef struct GdbCmdContext {
+GDBState *s;
+GdbCmdVariant *params;
+int num_params;
+uint8_t mem_buf[MAX_PACKET_LENGTH];
+char str_buf[MAX_PACKET_LENGTH + 1];
+} GdbCmdContext;
+
+typedef void (*GdbCmdHandler)(GdbCmdContext *gdb_ctx, void *user_ctx);
+
+/*
+ * cmd_startswith -> cmd is compared using startswith
+ * cmd_full_match -> cmd is compared using strcmp
+ *
+ *
+ * schema definitions:
+ * Each schema parameter entry consists of 2 chars,
+ * the first char represents the parameter type handling
+ * the second char represents the delimiter for the next parameter
+ *
+ * Currently supported schema types:
+ * 'l' -> unsigned long (stored in .val_ul)
+ * 'L' -> unsigned long long (stored in .val_ull)
+ * 's' -> string (stored in .data)
+ * 'o' -> single char (stored in .opcode)
+ * 't' -> thread id (stored in .thread_id)
+ * '?' -> skip according to delimiter
+ *
+ * Currently supported delimiters:
+ * '?' -> Stop at any delimiter (",;:=\0")
+ * '0' -> Stop at "\0"
+ * '.' -> Skip 1 char unless reached "\0"
+ * Any other value is treated as the delimiter value itself
+ */
+typedef struct GdbCmdParseEntry {
+GdbCmdHandler handler;
+const char *cmd;
+union {
+int flags;
+struct {
+int cmd_startswith:1;
+int cmd_full_match:1;
+};
+};
+const char *schema;
+} GdbCmdParseEntry;
+
+static inline int startswith(const char *string, const char *pattern)
+{
+  return !strncmp(string, pattern, strlen(pattern));
+}
+
+__attribute__((unused)) static int process_string_cmd(
+GDBState *s, void *user_ctx, const char *data,
+const GdbCmdParseEntry *cmds, int num_cmds);
+
+static int process_string_cmd(GDBState *s, void *user_ctx, const char *data,
+  

[Qemu-devel] [PATCH v5 04/21] gdbstub: Implement continue (c pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 25 +++--
 1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 29ca6be3df..a38f9d4ef9 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1523,6 +1523,16 @@ static void handle_thread_alive(GdbCmdContext *gdb_ctx, 
void *user_ctx)
 put_packet(gdb_ctx->s, "OK");
 }
 
+static void handle_continue(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+if (gdb_ctx->num_params) {
+gdb_set_cpu_pc(gdb_ctx->s, gdb_ctx->params[0].val_ull);
+}
+
+gdb_ctx->s->signal = 0;
+gdb_continue(gdb_ctx->s);
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1559,13 +1569,16 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 gdb_breakpoint_remove_all();
 break;
 case 'c':
-if (*p != '\0') {
-addr = strtoull(p, (char **), 16);
-gdb_set_cpu_pc(s, addr);
+{
+static const GdbCmdParseEntry continue_cmd_desc = {
+.handler = handle_continue,
+.cmd = "c",
+.cmd_startswith = 1,
+.schema = "L0"
+};
+cmd_parser = _cmd_desc;
 }
-s->signal = 0;
-gdb_continue(s);
-return RS_IDLE;
+break;
 case 'C':
 s->signal = gdb_signal_to_target (strtoul(p, (char **), 16));
 if (s->signal == -1)
-- 
2.20.1




[Qemu-devel] [PATCH v5 09/21] gdbstub: Implement set register (P pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 39 ++-
 1 file changed, 30 insertions(+), 9 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 80f2a92da6..49db09ef52 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1635,6 +1635,27 @@ static void handle_remove_bp(GdbCmdContext *gdb_ctx, 
void *user_ctx)
 put_packet(gdb_ctx->s, "E22");
 }
 
+static void handle_set_reg(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+int reg_size;
+
+if (!gdb_has_xml) {
+put_packet(gdb_ctx->s, "");
+return;
+}
+
+if (gdb_ctx->num_params < 2) {
+put_packet(gdb_ctx->s, "");
+return;
+}
+
+reg_size = strlen(gdb_ctx->params[1].data) / 2;
+hextomem(gdb_ctx->mem_buf, gdb_ctx->params[1].data, reg_size);
+gdb_write_register(gdb_ctx->s->g_cpu, gdb_ctx->mem_buf,
+   gdb_ctx->params[0].val_ull);
+put_packet(gdb_ctx->s, "OK");
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1879,15 +1900,15 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 }
 break;
 case 'P':
-if (!gdb_has_xml)
-goto unknown_command;
-addr = strtoull(p, (char **), 16);
-if (*p == '=')
-p++;
-reg_size = strlen(p) / 2;
-hextomem(mem_buf, p, reg_size);
-gdb_write_register(s->g_cpu, mem_buf, addr);
-put_packet(s, "OK");
+{
+static const GdbCmdParseEntry set_reg_cmd_desc = {
+.handler = handle_set_reg,
+.cmd = "P",
+.cmd_startswith = 1,
+.schema = "L?s0"
+};
+cmd_parser = _reg_cmd_desc;
+}
 break;
 case 'Z':
 {
-- 
2.20.1




[Qemu-devel] [PATCH v5 02/21] gdbstub: Implement deatch (D pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-otff-by: Jon Doron 
---
 gdbstub.c | 89 +++
 1 file changed, 50 insertions(+), 39 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 3308279fa8..fdad1ac466 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1420,10 +1420,6 @@ static inline int startswith(const char *string, const 
char *pattern)
   return !strncmp(string, pattern, strlen(pattern));
 }
 
-__attribute__((unused)) static int process_string_cmd(
-GDBState *s, void *user_ctx, const char *data,
-const GdbCmdParseEntry *cmds, int num_cmds);
-
 static int process_string_cmd(GDBState *s, void *user_ctx, const char *data,
   const GdbCmdParseEntry *cmds, int num_cmds)
 {
@@ -1468,6 +1464,41 @@ static int process_string_cmd(GDBState *s, void 
*user_ctx, const char *data,
 return -1;
 }
 
+static void handle_detach(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+GDBProcess *process;
+GDBState *s = gdb_ctx->s;
+uint32_t pid = 1;
+
+if (s->multiprocess) {
+if (!gdb_ctx->num_params) {
+put_packet(s, "E22");
+return;
+}
+
+pid = gdb_ctx->params[0].val_ul;
+}
+
+process = gdb_get_process(s, pid);
+gdb_process_breakpoint_remove_all(s, process);
+process->attached = false;
+
+if (pid == gdb_get_cpu_pid(s, s->c_cpu)) {
+s->c_cpu = gdb_first_attached_cpu(s);
+}
+
+if (pid == gdb_get_cpu_pid(s, s->g_cpu)) {
+s->g_cpu = gdb_first_attached_cpu(s);
+}
+
+if (!s->c_cpu) {
+/* No more process attached */
+gdb_syscall_mode = GDB_SYS_DISABLED;
+gdb_continue(s);
+}
+put_packet(s, "OK");
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1482,6 +1513,7 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 uint8_t *registers;
 target_ulong addr, len;
 GDBThreadIdKind thread_kind;
+const GdbCmdParseEntry *cmd_parser = NULL;
 
 trace_gdbstub_io_command(line_buf);
 
@@ -1582,42 +1614,15 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 error_report("QEMU: Terminated via GDBstub");
 exit(0);
 case 'D':
-/* Detach packet */
-pid = 1;
-
-if (s->multiprocess) {
-unsigned long lpid;
-if (*p != ';') {
-put_packet(s, "E22");
-break;
-}
-
-if (qemu_strtoul(p + 1, , 16, )) {
-put_packet(s, "E22");
-break;
-}
-
-pid = lpid;
-}
-
-process = gdb_get_process(s, pid);
-gdb_process_breakpoint_remove_all(s, process);
-process->attached = false;
-
-if (pid == gdb_get_cpu_pid(s, s->c_cpu)) {
-s->c_cpu = gdb_first_attached_cpu(s);
-}
-
-if (pid == gdb_get_cpu_pid(s, s->g_cpu)) {
-s->g_cpu = gdb_first_attached_cpu(s);
-}
-
-if (s->c_cpu == NULL) {
-/* No more process attached */
-gdb_syscall_mode = GDB_SYS_DISABLED;
-gdb_continue(s);
+{
+static const GdbCmdParseEntry detach_cmd_desc = {
+.handler = handle_detach,
+.cmd = "D",
+.cmd_startswith = 1,
+.schema = "?.l0"
+};
+cmd_parser = _cmd_desc;
 }
-put_packet(s, "OK");
 break;
 case 's':
 if (*p != '\0') {
@@ -1990,6 +1995,12 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 put_packet(s, buf);
 break;
 }
+
+if (cmd_parser &&
+process_string_cmd(s, NULL, line_buf, cmd_parser, 1)) {
+put_packet(s, "");
+}
+
 return RS_IDLE;
 }
 
-- 
2.20.1




[Qemu-devel] [PATCH v2 1/1] util/path: Do not cache all filenames at startup

2019-04-24 Thread Richard Henderson
If one uses -L $PATH to point to a full chroot, the startup time
is significant.  In addition, the existing probing algorithm fails
to handle symlink loops.

Instead, probe individual paths on demand.  Cache both positive
and negative results within $PATH, so that any one filename is
probed only once.

Use glib filename functions for clarity.

Signed-off-by: Richard Henderson 
---
 util/path.c | 201 
 1 file changed, 47 insertions(+), 154 deletions(-)

diff --git a/util/path.c b/util/path.c
index 7f9fc272fb..8e174eb436 100644
--- a/util/path.c
+++ b/util/path.c
@@ -8,170 +8,63 @@
 #include 
 #include "qemu/cutils.h"
 #include "qemu/path.h"
+#include "qemu/thread.h"
 
-struct pathelem
-{
-/* Name of this, eg. lib */
-char *name;
-/* Full path name, eg. /usr/gnemul/x86-linux/lib. */
-char *pathname;
-struct pathelem *parent;
-/* Children */
-unsigned int num_entries;
-struct pathelem *entries[0];
-};
-
-static struct pathelem *base;
-
-/* First N chars of S1 match S2, and S2 is N chars long. */
-static int strneq(const char *s1, unsigned int n, const char *s2)
-{
-unsigned int i;
-
-for (i = 0; i < n; i++)
-if (s1[i] != s2[i])
-return 0;
-return s2[i] == 0;
-}
-
-static struct pathelem *add_entry(struct pathelem *root, const char *name,
-  unsigned type);
-
-static struct pathelem *new_entry(const char *root,
-  struct pathelem *parent,
-  const char *name)
-{
-struct pathelem *new = g_malloc(sizeof(*new));
-new->name = g_strdup(name);
-new->pathname = g_strdup_printf("%s/%s", root, name);
-new->num_entries = 0;
-return new;
-}
-
-#define streq(a,b) (strcmp((a), (b)) == 0)
-
-/* Not all systems provide this feature */
-#if defined(DT_DIR) && defined(DT_UNKNOWN) && defined(DT_LNK)
-# define dirent_type(dirent) ((dirent)->d_type)
-# define is_dir_maybe(type) \
-((type) == DT_DIR || (type) == DT_UNKNOWN || (type) == DT_LNK)
-#else
-# define dirent_type(dirent) (1)
-# define is_dir_maybe(type)  (type)
-#endif
-
-static struct pathelem *add_dir_maybe(struct pathelem *path)
-{
-DIR *dir;
-
-if ((dir = opendir(path->pathname)) != NULL) {
-struct dirent *dirent;
-
-while ((dirent = readdir(dir)) != NULL) {
-if (!streq(dirent->d_name,".") && !streq(dirent->d_name,"..")){
-path = add_entry(path, dirent->d_name, dirent_type(dirent));
-}
-}
-closedir(dir);
-}
-return path;
-}
-
-static struct pathelem *add_entry(struct pathelem *root, const char *name,
-  unsigned type)
-{
-struct pathelem **e;
-
-root->num_entries++;
-
-root = g_realloc(root, sizeof(*root)
-   + sizeof(root->entries[0])*root->num_entries);
-e = >entries[root->num_entries-1];
-
-*e = new_entry(root->pathname, root, name);
-if (is_dir_maybe(type)) {
-*e = add_dir_maybe(*e);
-}
-
-return root;
-}
-
-/* This needs to be done after tree is stabilized (ie. no more reallocs!). */
-static void set_parents(struct pathelem *child, struct pathelem *parent)
-{
-unsigned int i;
-
-child->parent = parent;
-for (i = 0; i < child->num_entries; i++)
-set_parents(child->entries[i], child);
-}
-
-/* FIXME: Doesn't handle DIR/.. where DIR is not in emulated dir. */
-static const char *
-follow_path(const struct pathelem *cursor, const char *name)
-{
-unsigned int i, namelen;
-
-name += strspn(name, "/");
-namelen = strcspn(name, "/");
-
-if (namelen == 0)
-return cursor->pathname;
-
-if (strneq(name, namelen, ".."))
-return follow_path(cursor->parent, name + namelen);
-
-if (strneq(name, namelen, "."))
-return follow_path(cursor, name + namelen);
-
-for (i = 0; i < cursor->num_entries; i++)
-if (strneq(name, namelen, cursor->entries[i]->name))
-return follow_path(cursor->entries[i], name + namelen);
-
-/* Not found */
-return NULL;
-}
+static const char *base;
+static GHashTable *hash;
+static QemuMutex lock;
 
 void init_paths(const char *prefix)
 {
-char pref_buf[PATH_MAX];
-
-if (prefix[0] == '\0' ||
-!strcmp(prefix, "/"))
+if (prefix[0] == '\0' || !strcmp(prefix, "/")) {
 return;
-
-if (prefix[0] != '/') {
-char *cwd = getcwd(NULL, 0);
-size_t pref_buf_len = sizeof(pref_buf);
-
-if (!cwd)
-abort();
-pstrcpy(pref_buf, sizeof(pref_buf), cwd);
-pstrcat(pref_buf, pref_buf_len, "/");
-pstrcat(pref_buf, pref_buf_len, prefix);
-free(cwd);
-} else
-pstrcpy(pref_buf, sizeof(pref_buf), prefix + 1);
-
-base = new_entry("", NULL, pref_buf);
-base = add_dir_maybe(base);
-if (base->num_entries == 0) {
-g_free(base->pathname);
-

[Qemu-devel] [PATCH v2 0/1] util/path: Do not cache all filenames at startup

2019-04-24 Thread Richard Henderson
Changes for v2:

Drop use of g_canonicalize_filename.

While Daniel pointed out how to add stuff to glib-compat.h,
full canonicalization is overkill for path() in any case.
I also discovered that I'd been testing w/ glib 2.56 and so
hadn't been testing the g_canonicalize_filename case anyway.

Cover from v1:

This is a third variant attempting to fix the problem of
the -L interp_prefix handling not coping well pointing to
a full chroot.

Previous versions include:
https://lists.gnu.org/archive/html/qemu-devel/2018-05/msg06592.html
https://lists.gnu.org/archive/html/qemu-devel/2018-05/msg07304.html

Both of the other versions keep an open file descriptor to
the directory that is interp_prefix.  While this seems to be
efficient, they also leak a file descriptor into the guest.
This has follow-on effects on the emulation, causing failures
e.g. within the LTP testsuite.

This version uses only string manipulation and access(2).

A plausible criticism of this is the mutex and the cache.
Are they really needed?  I have no idea.  I can imagine
removing that is actually more efficient, not needing a
lock around a shared data structure.


r~


Richard Henderson (1):
  util/path: Do not cache all filenames at startup

 util/path.c | 201 
 1 file changed, 47 insertions(+), 154 deletions(-)

-- 
2.17.1




Re: [Qemu-devel] [PULL 00/12] bundle edk2 platform firmware with QEMU

2019-04-24 Thread Laszlo Ersek
On 04/24/19 15:47, Peter Maydell wrote:
> On Tue, 23 Apr 2019 at 18:15, Laszlo Ersek  wrote:
>>
>> Picked up the new feedback tags from the v4 thread, which had been
>> posted at:
>> - https://lists.gnu.org/archive/html/qemu-devel/2019-04/msg01549.html
>> - 20190409230022.6462-1-lersek@redhat.com">http://mid.mail-archive.com/20190409230022.6462-1-lersek@redhat.com
>>
>> The following changes since commit eeba63fc7fface36f438bcbc0d3b02e7dcb59983:
>>
>>   Update version for v4.0.0-rc4 release (2019-04-16 21:53:00 +0100)
>>
>> are available in the Git repository at:
>>
>>   https://github.com/lersek/qemu.git tags/edk2-pull-2019-04-22
>>
>> for you to fetch changes up to 6739df3fafaa3e2ec37af23fd77d2119869f4a4f:
>>
>>   MAINTAINERS: add the "EDK2 Firmware" subsystem (2019-04-17 15:38:35 +0200)
>>
>> 
>> Advance the roms/edk2 submodule to the "edk2-stable201903" release, and
>> build and capture platform firmware binaries from that release. The
>> binaries are meant to be used by both end-users and by the "BIOS tables"
>> unit tests in qtest ("make check").
>>
>> 
>> Laszlo Ersek (12):
>>   roms: lift "edk2-funcs.sh" from "tests/uefi-test-tools/build.sh"
>>   roms/edk2-funcs.sh: require gcc-4.8+ for building i386 and x86_64
>>   tests/uefi-test-tools/build.sh: work around TianoCore#1607
>>   roms/edk2: advance to tag edk2-stable201903
>>   roms/edk2-funcs.sh: add the qemu_edk2_get_thread_count() function
>>   roms/Makefile: replace the $(EDK2_EFIROM) target with "edk2-basetools"
>>   roms: build edk2 firmware binaries and variable store templates
>>   pc-bios: add edk2 firmware binaries and variable store templates
>>   pc-bios: document the edk2 firmware images; add firmware descriptors
>>   tests: add missing dependency to build QTEST_QEMU_BINARY, round 2
>>   Makefile: install the edk2 firmware images and their descriptors
>>   MAINTAINERS: add the "EDK2 Firmware" subsystem
> 
> 
> 
> Applied, thanks.

Awesome, thanks!

I'll soon get to work on .

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

Done, at .

Thanks!
Laszlo



[Qemu-devel] [PATCH v4 05/20] gdbstub: Implement continue with signal (C pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 30 +-
 1 file changed, 25 insertions(+), 5 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 47b1e7e7a4..edcb7bfd17 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1542,6 +1542,21 @@ static void handle_continue(GdbCmdContext *gdb_ctx, void 
*user_ctx)
 gdb_continue(gdb_ctx->s);
 }
 
+static void handle_cont_with_sig(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+unsigned long signal = 0;
+
+if (gdb_ctx->num_params) {
+signal = gdb_ctx->params[0].val_ul;
+}
+
+gdb_ctx->s->signal = gdb_signal_to_target(signal);
+if (gdb_ctx->s->signal == -1) {
+gdb_ctx->s->signal = 0;
+}
+gdb_continue(gdb_ctx->s);
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1588,11 +1603,16 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 }
 break;
 case 'C':
-s->signal = gdb_signal_to_target (strtoul(p, (char **), 16));
-if (s->signal == -1)
-s->signal = 0;
-gdb_continue(s);
-return RS_IDLE;
+{
+static GdbCmdParseEntry cont_with_sig_cmd_desc = {
+.handler = handle_cont_with_sig,
+.cmd = "C",
+.cmd_startswith = 1,
+.schema = "l0"
+};
+process_string_cmd(s, NULL, line_buf, _with_sig_cmd_desc, 1);
+}
+break;
 case 'v':
 if (strncmp(p, "Cont", 4) == 0) {
 p += 4;
-- 
2.20.1




[Qemu-devel] [PATCH v4 12/20] gdbstub: Implement read memory (m pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 48 
 1 file changed, 32 insertions(+), 16 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index f29042cac0..af37222034 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1720,6 +1720,30 @@ static void handle_write_mem(GdbCmdContext *gdb_ctx, 
void *user_ctx)
 put_packet(gdb_ctx->s, "OK");
 }
 
+static void handle_read_mem(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+if (gdb_ctx->num_params < 2) {
+put_packet(gdb_ctx->s, "E22");
+return;
+}
+
+/* memtohex() doubles the required space */
+if (gdb_ctx->params[1].val_ull > MAX_PACKET_LENGTH / 2) {
+put_packet(gdb_ctx->s, "E22");
+return;
+}
+
+if (target_memory_rw_debug(gdb_ctx->s->g_cpu, gdb_ctx->params[0].val_ull,
+   gdb_ctx->mem_buf,
+   gdb_ctx->params[1].val_ull, false)) {
+put_packet(gdb_ctx->s, "E14");
+return;
+}
+
+memtohex(gdb_ctx->str_buf, gdb_ctx->mem_buf, gdb_ctx->params[1].val_ull);
+put_packet(gdb_ctx->s, gdb_ctx->str_buf);
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1908,22 +1932,14 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 put_packet(s, "OK");
 break;
 case 'm':
-addr = strtoull(p, (char **), 16);
-if (*p == ',')
-p++;
-len = strtoull(p, NULL, 16);
-
-/* memtohex() doubles the required space */
-if (len > MAX_PACKET_LENGTH / 2) {
-put_packet (s, "E22");
-break;
-}
-
-if (target_memory_rw_debug(s->g_cpu, addr, mem_buf, len, false) != 0) {
-put_packet (s, "E14");
-} else {
-memtohex(buf, mem_buf, len);
-put_packet(s, buf);
+{
+static GdbCmdParseEntry read_mem_cmd_desc = {
+.handler = handle_read_mem,
+.cmd = "m",
+.cmd_startswith = 1,
+.schema = "L,L0"
+};
+process_string_cmd(s, NULL, line_buf, _mem_cmd_desc, 1);
 }
 break;
 case 'M':
-- 
2.20.1




[Qemu-devel] [PATCH v4 03/20] gdbstub: Implement thread_alive (T pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 43 ---
 1 file changed, 32 insertions(+), 11 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 952a6d92ef..7704edd69c 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1508,6 +1508,30 @@ static void handle_detach(GdbCmdContext *gdb_ctx, void 
*user_ctx)
 put_packet(s, "OK");
 }
 
+static void handle_thread_alive(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+CPUState *cpu;
+
+if (!gdb_ctx->num_params) {
+put_packet(gdb_ctx->s, "E22");
+return;
+}
+
+if (gdb_ctx->params[0].thread_id.kind == GDB_READ_THREAD_ERR) {
+put_packet(gdb_ctx->s, "E22");
+return;
+}
+
+cpu = gdb_get_cpu(gdb_ctx->s, gdb_ctx->params[0].thread_id.pid,
+  gdb_ctx->params[0].thread_id.tid);
+if (!cpu) {
+put_packet(gdb_ctx->s, "E22");
+return;
+}
+
+put_packet(gdb_ctx->s, "OK");
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1807,17 +1831,14 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 }
 break;
 case 'T':
-thread_kind = read_thread_id(p, , , );
-if (thread_kind == GDB_READ_THREAD_ERR) {
-put_packet(s, "E22");
-break;
-}
-cpu = gdb_get_cpu(s, pid, tid);
-
-if (cpu != NULL) {
-put_packet(s, "OK");
-} else {
-put_packet(s, "E22");
+{
+static GdbCmdParseEntry thread_alive_cmd_desc = {
+.handler = handle_thread_alive,
+.cmd = "T",
+.cmd_startswith = 1,
+.schema = "t0"
+};
+process_string_cmd(s, NULL, line_buf, _alive_cmd_desc, 1);
 }
 break;
 case 'q':
-- 
2.20.1




[Qemu-devel] [PATCH v4 07/20] gdbstub: Implement insert breakpoint (Z pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 33 +
 1 file changed, 33 insertions(+)

diff --git a/gdbstub.c b/gdbstub.c
index c1ec36a062..03553a1a32 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1598,6 +1598,29 @@ static void handle_set_thread(GdbCmdContext *gdb_ctx, 
void *user_ctx)
 }
 }
 
+static void handle_insert_bp(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+int res;
+
+if (gdb_ctx->num_params < 3) {
+put_packet(gdb_ctx->s, "E22");
+return;
+}
+
+res = gdb_breakpoint_insert(gdb_ctx->params[1].val_ull,
+gdb_ctx->params[2].val_ull,
+gdb_ctx->params[0].val_ul);
+if (res >= 0) {
+put_packet(gdb_ctx->s, "OK");
+return;
+} else if (res == -ENOSYS) {
+put_packet(gdb_ctx->s, "");
+return;
+}
+
+put_packet(gdb_ctx->s, "E22");
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1852,6 +1875,16 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 put_packet(s, "OK");
 break;
 case 'Z':
+{
+static GdbCmdParseEntry insert_bp_cmd_desc = {
+.handler = handle_insert_bp,
+.cmd = "Z",
+.cmd_startswith = 1,
+.schema = "l?L?L0"
+};
+process_string_cmd(s, NULL, line_buf, _bp_cmd_desc, 1);
+}
+break;
 case 'z':
 type = strtoul(p, (char **), 16);
 if (*p == ',')
-- 
2.20.1




[Qemu-devel] [PATCH v4 11/20] gdbstub: Implement write memory (M pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 51 +--
 1 file changed, 33 insertions(+), 18 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 58b665d303..f29042cac0 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1695,6 +1695,31 @@ static void handle_get_reg(GdbCmdContext *gdb_ctx, void 
*user_ctx)
 put_packet(gdb_ctx->s, gdb_ctx->str_buf);
 }
 
+static void handle_write_mem(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+if (gdb_ctx->num_params < 3) {
+put_packet(gdb_ctx->s, "E22");
+return;
+}
+
+/* hextomem() reads 2*len bytes */
+if (gdb_ctx->params[1].val_ull > strlen(gdb_ctx->params[2].data) / 2) {
+put_packet(gdb_ctx->s, "E22");
+return;
+}
+
+hextomem(gdb_ctx->mem_buf, gdb_ctx->params[2].data,
+ gdb_ctx->params[1].val_ull);
+if (target_memory_rw_debug(gdb_ctx->s->g_cpu, gdb_ctx->params[0].val_ull,
+   gdb_ctx->mem_buf,
+   gdb_ctx->params[1].val_ull, true)) {
+put_packet(gdb_ctx->s, "E14");
+return;
+}
+
+put_packet(gdb_ctx->s, "OK");
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1902,24 +1927,14 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 }
 break;
 case 'M':
-addr = strtoull(p, (char **), 16);
-if (*p == ',')
-p++;
-len = strtoull(p, (char **), 16);
-if (*p == ':')
-p++;
-
-/* hextomem() reads 2*len bytes */
-if (len > strlen(p) / 2) {
-put_packet (s, "E22");
-break;
-}
-hextomem(mem_buf, p, len);
-if (target_memory_rw_debug(s->g_cpu, addr, mem_buf, len,
-   true) != 0) {
-put_packet(s, "E14");
-} else {
-put_packet(s, "OK");
+{
+static GdbCmdParseEntry write_mem_cmd_desc = {
+.handler = handle_write_mem,
+.cmd = "M",
+.cmd_startswith = 1,
+.schema = "L,L:s0"
+};
+process_string_cmd(s, NULL, line_buf, _mem_cmd_desc, 1);
 }
 break;
 case 'p':
-- 
2.20.1




[Qemu-devel] [PATCH v4 04/20] gdbstub: Implement continue (c pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 25 +++--
 1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 7704edd69c..47b1e7e7a4 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1532,6 +1532,16 @@ static void handle_thread_alive(GdbCmdContext *gdb_ctx, 
void *user_ctx)
 put_packet(gdb_ctx->s, "OK");
 }
 
+static void handle_continue(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+if (gdb_ctx->num_params) {
+gdb_set_cpu_pc(gdb_ctx->s, gdb_ctx->params[0].val_ull);
+}
+
+gdb_ctx->s->signal = 0;
+gdb_continue(gdb_ctx->s);
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1567,13 +1577,16 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 gdb_breakpoint_remove_all();
 break;
 case 'c':
-if (*p != '\0') {
-addr = strtoull(p, (char **), 16);
-gdb_set_cpu_pc(s, addr);
+{
+static GdbCmdParseEntry continue_cmd_desc = {
+.handler = handle_continue,
+.cmd = "c",
+.cmd_startswith = 1,
+.schema = "L0"
+};
+process_string_cmd(s, NULL, line_buf, _cmd_desc, 1);
 }
-s->signal = 0;
-gdb_continue(s);
-return RS_IDLE;
+break;
 case 'C':
 s->signal = gdb_signal_to_target (strtoul(p, (char **), 16));
 if (s->signal == -1)
-- 
2.20.1




[Qemu-devel] [PATCH v4 15/20] gdbstub: Implement file io (F pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 62 +++
 1 file changed, 40 insertions(+), 22 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index b9ac9401ed..772bcd2e1f 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1782,6 +1782,39 @@ static void handle_read_all_regs(GdbCmdContext *gdb_ctx, 
void *user_ctx)
 put_packet(gdb_ctx->s, gdb_ctx->str_buf);
 }
 
+static void handle_file_io(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+int num_syscall_params;
+GdbCmdVariant syscall_params[3] = {};
+
+if (!gdb_ctx->num_params) {
+return;
+}
+
+if (cmd_parse_params(gdb_ctx->params[0].data, "L,L,o0", syscall_params,
+ _syscall_params)) {
+return;
+}
+
+if (!num_syscall_params) {
+return;
+}
+
+if (gdb_ctx->s->current_syscall_cb) {
+gdb_ctx->s->current_syscall_cb(gdb_ctx->s->c_cpu,
+   (target_ulong)syscall_params[0].val_ull,
+   
(target_ulong)syscall_params[1].val_ull);
+gdb_ctx->s->current_syscall_cb = NULL;
+}
+
+if (syscall_params[2].opcode == (uint8_t)'C') {
+put_packet(gdb_ctx->s, "T02");
+return;
+}
+
+gdb_continue(gdb_ctx->s);
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1922,28 +1955,13 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 return RS_IDLE;
 case 'F':
 {
-target_ulong ret;
-target_ulong err;
-
-ret = strtoull(p, (char **), 16);
-if (*p == ',') {
-p++;
-err = strtoull(p, (char **), 16);
-} else {
-err = 0;
-}
-if (*p == ',')
-p++;
-type = *p;
-if (s->current_syscall_cb) {
-s->current_syscall_cb(s->c_cpu, ret, err);
-s->current_syscall_cb = NULL;
-}
-if (type == 'C') {
-put_packet(s, "T02");
-} else {
-gdb_continue(s);
-}
+static GdbCmdParseEntry file_io_cmd_desc = {
+.handler = handle_file_io,
+.cmd = "F",
+.cmd_startswith = 1,
+.schema = "s0"
+};
+process_string_cmd(s, NULL, line_buf, _io_cmd_desc, 1);
 }
 break;
 case 'g':
-- 
2.20.1




[Qemu-devel] [PATCH v4 02/20] gdbstub: Implement deatch (D pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-otff-by: Jon Doron 
---
 gdbstub.c | 82 +--
 1 file changed, 43 insertions(+), 39 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 64680722fc..952a6d92ef 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1429,10 +1429,6 @@ static inline int startswith(const char *string, const 
char *pattern)
   return !strncmp(string, pattern, strlen(pattern));
 }
 
-__attribute__((unused)) static int process_string_cmd(
-GDBState *s, void *user_ctx, const char *data,
-GdbCmdParseEntry *cmds, int num_cmds);
-
 static int process_string_cmd(GDBState *s, void *user_ctx, const char *data,
   GdbCmdParseEntry *cmds, int num_cmds)
 {
@@ -1477,6 +1473,41 @@ static int process_string_cmd(GDBState *s, void 
*user_ctx, const char *data,
 return -1;
 }
 
+static void handle_detach(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+GDBProcess *process;
+GDBState *s = gdb_ctx->s;
+uint32_t pid = 1;
+
+if (s->multiprocess) {
+if (!gdb_ctx->num_params) {
+put_packet(s, "E22");
+return;
+}
+
+pid = gdb_ctx->params[0].val_ul;
+}
+
+process = gdb_get_process(s, pid);
+gdb_process_breakpoint_remove_all(s, process);
+process->attached = false;
+
+if (pid == gdb_get_cpu_pid(s, s->c_cpu)) {
+s->c_cpu = gdb_first_attached_cpu(s);
+}
+
+if (pid == gdb_get_cpu_pid(s, s->g_cpu)) {
+s->g_cpu = gdb_first_attached_cpu(s);
+}
+
+if (!s->c_cpu) {
+/* No more process attached */
+gdb_syscall_mode = GDB_SYS_DISABLED;
+gdb_continue(s);
+}
+put_packet(s, "OK");
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1591,42 +1622,15 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 error_report("QEMU: Terminated via GDBstub");
 exit(0);
 case 'D':
-/* Detach packet */
-pid = 1;
-
-if (s->multiprocess) {
-unsigned long lpid;
-if (*p != ';') {
-put_packet(s, "E22");
-break;
-}
-
-if (qemu_strtoul(p + 1, , 16, )) {
-put_packet(s, "E22");
-break;
-}
-
-pid = lpid;
-}
-
-process = gdb_get_process(s, pid);
-gdb_process_breakpoint_remove_all(s, process);
-process->attached = false;
-
-if (pid == gdb_get_cpu_pid(s, s->c_cpu)) {
-s->c_cpu = gdb_first_attached_cpu(s);
-}
-
-if (pid == gdb_get_cpu_pid(s, s->g_cpu)) {
-s->g_cpu = gdb_first_attached_cpu(s);
-}
-
-if (s->c_cpu == NULL) {
-/* No more process attached */
-gdb_syscall_mode = GDB_SYS_DISABLED;
-gdb_continue(s);
+{
+static GdbCmdParseEntry deatch_cmd_desc = {
+.handler = handle_detach,
+.cmd = "D",
+.cmd_startswith = 1,
+.schema = "?.l0"
+};
+process_string_cmd(s, NULL, line_buf, _cmd_desc, 1);
 }
-put_packet(s, "OK");
 break;
 case 's':
 if (*p != '\0') {
-- 
2.20.1




[Qemu-devel] [PATCH v4 09/20] gdbstub: Implement set register (P pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 39 ++-
 1 file changed, 30 insertions(+), 9 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index b5d568603c..d3d688a747 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1644,6 +1644,27 @@ static void handle_remove_bp(GdbCmdContext *gdb_ctx, 
void *user_ctx)
 put_packet(gdb_ctx->s, "E22");
 }
 
+static void handle_set_reg(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+int reg_size;
+
+if (!gdb_has_xml) {
+put_packet(gdb_ctx->s, "");
+return;
+}
+
+if (gdb_ctx->num_params < 2) {
+put_packet(gdb_ctx->s, "");
+return;
+}
+
+reg_size = strlen(gdb_ctx->params[1].data) / 2;
+hextomem(gdb_ctx->mem_buf, gdb_ctx->params[1].data, reg_size);
+gdb_write_register(gdb_ctx->s->g_cpu, gdb_ctx->mem_buf,
+   gdb_ctx->params[0].val_ull);
+put_packet(gdb_ctx->s, "OK");
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1887,15 +1908,15 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 }
 break;
 case 'P':
-if (!gdb_has_xml)
-goto unknown_command;
-addr = strtoull(p, (char **), 16);
-if (*p == '=')
-p++;
-reg_size = strlen(p) / 2;
-hextomem(mem_buf, p, reg_size);
-gdb_write_register(s->g_cpu, mem_buf, addr);
-put_packet(s, "OK");
+{
+static GdbCmdParseEntry set_reg_cmd_desc = {
+.handler = handle_set_reg,
+.cmd = "P",
+.cmd_startswith = 1,
+.schema = "L?s0"
+};
+process_string_cmd(s, NULL, line_buf, _reg_cmd_desc, 1);
+}
 break;
 case 'Z':
 {
-- 
2.20.1




[Qemu-devel] [PATCH v4 01/20] gdbstub: Add infrastructure to parse cmd packets

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 209 ++
 1 file changed, 209 insertions(+)

diff --git a/gdbstub.c b/gdbstub.c
index d54abd17cc..64680722fc 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1268,6 +1268,215 @@ out:
 return res;
 }
 
+typedef union GdbCmdVariant {
+const char *data;
+uint8_t opcode;
+unsigned long val_ul;
+unsigned long long val_ull;
+struct {
+GDBThreadIdKind kind;
+uint32_t pid;
+uint32_t tid;
+} thread_id;
+} GdbCmdVariant;
+
+static const char *cmd_next_param(const char *param, const char delimiter)
+{
+const char *delim;
+static char all_delimiters[] = ",;:=";
+static char no_delimiter[] = "\0";
+char curr_delimiters[2] = {0};
+const char *delimiters;
+
+if (delimiter == '?') {
+delimiters = all_delimiters;
+} else if (delimiter == '0') {
+delimiters = no_delimiter;
+} else if (delimiter == '.' && *param) {
+return param + 1;
+} else {
+curr_delimiters[0] = delimiter;
+delimiters = curr_delimiters;
+}
+
+while (*param) {
+delim = delimiters;
+while (*delim) {
+if (*param == *delim) {
+return param + 1;
+}
+delim++;
+}
+param++;
+}
+
+return param;
+}
+
+static int cmd_parse_params(const char *data, const char *schema,
+GdbCmdVariant *params, int *num_params)
+{
+int curr_param;
+const char *curr_schema, *curr_data;
+
+*num_params = 0;
+
+if (!schema) {
+return 0;
+}
+
+curr_schema = schema;
+curr_param = 0;
+curr_data = data;
+while (curr_schema[0] && curr_schema[1] && *curr_data) {
+switch (curr_schema[0]) {
+case 'l':
+if (qemu_strtoul(curr_data, _data, 16,
+ [curr_param].val_ul)) {
+return -EINVAL;
+}
+curr_param++;
+curr_data = cmd_next_param(curr_data, curr_schema[1]);
+break;
+case 'L':
+if (qemu_strtou64(curr_data, _data, 16,
+  (uint64_t *)[curr_param].val_ull)) {
+return -EINVAL;
+}
+curr_param++;
+curr_data = cmd_next_param(curr_data, curr_schema[1]);
+break;
+case 's':
+params[curr_param].data = curr_data;
+curr_param++;
+curr_data = cmd_next_param(curr_data, curr_schema[1]);
+break;
+case 'o':
+params[curr_param].opcode = *(uint8_t *)curr_data;
+curr_param++;
+curr_data = cmd_next_param(curr_data, curr_schema[1]);
+break;
+case 't':
+params[curr_param].thread_id.kind =
+read_thread_id(curr_data, _data,
+   [curr_param].thread_id.pid,
+   [curr_param].thread_id.tid);
+curr_param++;
+curr_data = cmd_next_param(curr_data, curr_schema[1]);
+break;
+case '?':
+curr_data = cmd_next_param(curr_data, curr_schema[1]);
+break;
+default:
+return -EINVAL;
+}
+curr_schema += 2;
+}
+
+*num_params = curr_param;
+return 0;
+}
+
+typedef struct GdbCmdContext {
+GDBState *s;
+GdbCmdVariant *params;
+int num_params;
+uint8_t mem_buf[MAX_PACKET_LENGTH];
+char str_buf[MAX_PACKET_LENGTH + 1];
+} GdbCmdContext;
+
+typedef void (*GdbCmdHandler)(GdbCmdContext *gdb_ctx, void *user_ctx);
+
+/*
+ * cmd_startswith -> cmd is compared using startswith
+ * cmd_full_match -> cmd is compared using strcmp
+ *
+ *
+ * schema definitions:
+ * Each schema parameter entry consists of 2 chars,
+ * the first char represents the parameter type handling
+ * the second char represents the delimiter for the next parameter
+ *
+ * Currently supported schema types:
+ * 'l' -> unsigned long (stored in .val_ul)
+ * 'L' -> unsigned long long (stored in .val_ull)
+ * 's' -> string (stored in .data)
+ * 'o' -> single char (stored in .opcode)
+ * 't' -> thread id (stored in .thread_id)
+ * '?' -> skip according to delimiter
+ *
+ * Currently supported delimiters:
+ * '?' -> Stop at any delimiter (",;:=\0")
+ * '0' -> Stop at "\0"
+ * '.' -> Skip 1 char unless reached "\0"
+ * Any other value is treated as the delimiter value itself
+ */
+typedef struct GdbCmdParseEntry {
+GdbCmdHandler handler;
+const char *cmd;
+union {
+int flags;
+struct {
+int cmd_startswith:1;
+int cmd_full_match:1;
+};
+};
+const char *schema;
+} GdbCmdParseEntry;
+
+static inline int startswith(const char *string, const char *pattern)
+{
+  return !strncmp(string, pattern, strlen(pattern));
+}
+
+__attribute__((unused)) static int process_string_cmd(
+GDBState *s, 

[Qemu-devel] [PATCH v4 06/20] gdbstub: Implement set_thread (H pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 79 ++-
 1 file changed, 49 insertions(+), 30 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index edcb7bfd17..c1ec36a062 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1557,6 +1557,47 @@ static void handle_cont_with_sig(GdbCmdContext *gdb_ctx, 
void *user_ctx)
 gdb_continue(gdb_ctx->s);
 }
 
+static void handle_set_thread(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+CPUState *cpu;
+
+if (gdb_ctx->num_params < 2) {
+put_packet(gdb_ctx->s, "E22");
+return;
+}
+
+if (gdb_ctx->params[1].thread_id.kind == GDB_READ_THREAD_ERR) {
+put_packet(gdb_ctx->s, "E22");
+return;
+}
+
+if (gdb_ctx->params[1].thread_id.kind != GDB_ONE_THREAD) {
+put_packet(gdb_ctx->s, "OK");
+return;
+}
+
+cpu = gdb_get_cpu(gdb_ctx->s, gdb_ctx->params[1].thread_id.pid,
+  gdb_ctx->params[1].thread_id.tid);
+if (!cpu) {
+put_packet(gdb_ctx->s, "E22");
+return;
+}
+
+switch (gdb_ctx->params[0].opcode) {
+case 'c':
+gdb_ctx->s->c_cpu = cpu;
+put_packet(gdb_ctx->s, "OK");
+break;
+case 'g':
+gdb_ctx->s->g_cpu = cpu;
+put_packet(gdb_ctx->s, "OK");
+break;
+default:
+put_packet(gdb_ctx->s, "E22");
+break;
+}
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1570,7 +1611,6 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 char thread_id[16];
 uint8_t *registers;
 target_ulong addr, len;
-GDBThreadIdKind thread_kind;
 
 trace_gdbstub_io_command(line_buf);
 
@@ -1832,35 +1872,14 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 put_packet(s, "E22");
 break;
 case 'H':
-type = *p++;
-
-thread_kind = read_thread_id(p, , , );
-if (thread_kind == GDB_READ_THREAD_ERR) {
-put_packet(s, "E22");
-break;
-}
-
-if (thread_kind != GDB_ONE_THREAD) {
-put_packet(s, "OK");
-break;
-}
-cpu = gdb_get_cpu(s, pid, tid);
-if (cpu == NULL) {
-put_packet(s, "E22");
-break;
-}
-switch (type) {
-case 'c':
-s->c_cpu = cpu;
-put_packet(s, "OK");
-break;
-case 'g':
-s->g_cpu = cpu;
-put_packet(s, "OK");
-break;
-default:
- put_packet(s, "E22");
- break;
+{
+static GdbCmdParseEntry set_thread_cmd_desc = {
+.handler = handle_set_thread,
+.cmd = "H",
+.cmd_startswith = 1,
+.schema = "o.t0"
+};
+process_string_cmd(s, NULL, line_buf, _thread_cmd_desc, 1);
 }
 break;
 case 'T':
-- 
2.20.1




[Qemu-devel] [PATCH v4 14/20] gdbstub: Implement read all registers (g pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 31 +++
 1 file changed, 23 insertions(+), 8 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 084c688f75..b9ac9401ed 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1767,6 +1767,21 @@ static void handle_write_all_regs(GdbCmdContext 
*gdb_ctx, void *user_ctx)
 put_packet(gdb_ctx->s, "OK");
 }
 
+static void handle_read_all_regs(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+target_ulong addr, len;
+
+cpu_synchronize_state(gdb_ctx->s->g_cpu);
+len = 0;
+for (addr = 0; addr < gdb_ctx->s->g_cpu->gdb_num_g_regs; addr++) {
+len += gdb_read_register(gdb_ctx->s->g_cpu, gdb_ctx->mem_buf + len,
+ addr);
+}
+
+memtohex(gdb_ctx->str_buf, gdb_ctx->mem_buf, len);
+put_packet(gdb_ctx->s, gdb_ctx->str_buf);
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1774,7 +1789,7 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 CPUClass *cc;
 const char *p;
 uint32_t pid, tid;
-int ch, reg_size, type, res;
+int ch, type, res;
 uint8_t mem_buf[MAX_PACKET_LENGTH];
 char buf[sizeof(mem_buf) + 1 /* trailing NUL */];
 char thread_id[16];
@@ -1932,14 +1947,14 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 }
 break;
 case 'g':
-cpu_synchronize_state(s->g_cpu);
-len = 0;
-for (addr = 0; addr < s->g_cpu->gdb_num_g_regs; addr++) {
-reg_size = gdb_read_register(s->g_cpu, mem_buf + len, addr);
-len += reg_size;
+{
+static GdbCmdParseEntry read_all_regs_cmd_desc = {
+.handler = handle_read_all_regs,
+.cmd = "g",
+.cmd_startswith = 1
+};
+process_string_cmd(s, NULL, line_buf, _all_regs_cmd_desc, 1);
 }
-memtohex(buf, mem_buf, len);
-put_packet(s, buf);
 break;
 case 'G':
 {
-- 
2.20.1




[Qemu-devel] [PATCH v4 18/20] gdbstub: Implement generic query (q pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 335 ++
 1 file changed, 335 insertions(+)

diff --git a/gdbstub.c b/gdbstub.c
index 8c79e36923..8de4e09caa 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1925,6 +1925,331 @@ static void handle_v_commands(GdbCmdContext *gdb_ctx, 
void *user_ctx)
 }
 }
 
+static void handle_query_qemu_sstepbits(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+snprintf(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf),
+ "ENABLE=%x,NOIRQ=%x,NOTIMER=%x", SSTEP_ENABLE,
+ SSTEP_NOIRQ, SSTEP_NOTIMER);
+put_packet(gdb_ctx->s, gdb_ctx->str_buf);
+}
+
+static void handle_set_qemu_sstep(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+if (!gdb_ctx->num_params) {
+return;
+}
+
+sstep_flags = gdb_ctx->params[0].val_ul;
+put_packet(gdb_ctx->s, "OK");
+}
+
+static void handle_query_qemu_sstep(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+snprintf(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf), "0x%x", sstep_flags);
+put_packet(gdb_ctx->s, gdb_ctx->str_buf);
+}
+
+static void handle_query_curr_tid(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+CPUState *cpu;
+GDBProcess *process;
+char thread_id[16];
+
+/*
+ * "Current thread" remains vague in the spec, so always return
+ * the first thread of the current process (gdb returns the
+ * first thread).
+ */
+process = gdb_get_cpu_process(gdb_ctx->s, gdb_ctx->s->g_cpu);
+cpu = get_first_cpu_in_process(gdb_ctx->s, process);
+gdb_fmt_thread_id(gdb_ctx->s, cpu, thread_id, sizeof(thread_id));
+snprintf(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf), "QC%s", thread_id);
+put_packet(gdb_ctx->s, gdb_ctx->str_buf);
+}
+
+static void handle_query_threads(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+char thread_id[16];
+
+if (!gdb_ctx->s->query_cpu) {
+put_packet(gdb_ctx->s, "l");
+return;
+}
+
+gdb_fmt_thread_id(gdb_ctx->s, gdb_ctx->s->query_cpu, thread_id,
+  sizeof(thread_id));
+snprintf(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf), "m%s", thread_id);
+put_packet(gdb_ctx->s, gdb_ctx->str_buf);
+gdb_ctx->s->query_cpu =
+gdb_next_attached_cpu(gdb_ctx->s, gdb_ctx->s->query_cpu);
+}
+
+static void handle_query_first_threads(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+gdb_ctx->s->query_cpu = gdb_first_attached_cpu(gdb_ctx->s);
+handle_query_threads(gdb_ctx, user_ctx);
+}
+
+static void handle_query_thread_extra(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+CPUState *cpu;
+int len;
+
+if (!gdb_ctx->num_params ||
+gdb_ctx->params[0].thread_id.kind == GDB_READ_THREAD_ERR) {
+put_packet(gdb_ctx->s, "E22");
+return;
+}
+
+cpu = gdb_get_cpu(gdb_ctx->s, gdb_ctx->params[0].thread_id.pid,
+  gdb_ctx->params[0].thread_id.tid);
+if (!cpu) {
+return;
+}
+
+cpu_synchronize_state(cpu);
+
+if (gdb_ctx->s->multiprocess && (gdb_ctx->s->process_num > 1)) {
+/* Print the CPU model and name in multiprocess mode */
+ObjectClass *oc = object_get_class(OBJECT(cpu));
+const char *cpu_model = object_class_get_name(oc);
+char *cpu_name = object_get_canonical_path_component(OBJECT(cpu));
+len = snprintf((char *)gdb_ctx->mem_buf, sizeof(gdb_ctx->str_buf) / 2,
+   "%s %s [%s]", cpu_model, cpu_name,
+   cpu->halted ? "halted " : "running");
+g_free(cpu_name);
+} else {
+/* memtohex() doubles the required space */
+len = snprintf((char *)gdb_ctx->mem_buf, sizeof(gdb_ctx->str_buf) / 2,
+"CPU#%d [%s]", cpu->cpu_index,
+cpu->halted ? "halted " : "running");
+}
+trace_gdbstub_op_extra_info((char *)gdb_ctx->mem_buf);
+memtohex(gdb_ctx->str_buf, gdb_ctx->mem_buf, len);
+put_packet(gdb_ctx->s, gdb_ctx->str_buf);
+}
+
+#ifdef CONFIG_USER_ONLY
+static void handle_query_offsets(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+TaskState *ts;
+
+ts = gdb_ctx->s->c_cpu->opaque;
+snprintf(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf),
+ "Text=" TARGET_ABI_FMT_lx ";Data=" TARGET_ABI_FMT_lx
+ ";Bss=" TARGET_ABI_FMT_lx,
+ ts->info->code_offset,
+ ts->info->data_offset,
+ ts->info->data_offset);
+put_packet(gdb_ctx->s, gdb_ctx->str_buf);
+}
+#else
+static void handle_query_rcmd(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+int len;
+
+if (!gdb_ctx->num_params) {
+put_packet(gdb_ctx->s, "E22");
+return;
+}
+
+len = strlen(gdb_ctx->params[0].data);
+if (len % 2) {
+put_packet(gdb_ctx->s, "E01");
+return;
+}
+
+len = len / 2;
+hextomem(gdb_ctx->mem_buf, gdb_ctx->params[0].data, len);
+gdb_ctx->mem_buf[len++] = 0;
+qemu_chr_be_write(gdb_ctx->s->mon_chr, gdb_ctx->mem_buf, len);
+put_packet(gdb_ctx->s, "OK");
+

[Qemu-devel] [PATCH v4 10/20] gdbstub: Implement get register (p pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 50 ++
 1 file changed, 38 insertions(+), 12 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index d3d688a747..58b665d303 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1665,6 +1665,36 @@ static void handle_set_reg(GdbCmdContext *gdb_ctx, void 
*user_ctx)
 put_packet(gdb_ctx->s, "OK");
 }
 
+static void handle_get_reg(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+int reg_size;
+
+/*
+ * Older gdb are really dumb, and don't use 'g' if 'p' is avaialable.
+ * This works, but can be very slow.  Anything new enough to
+ * understand XML also knows how to use this properly.
+ */
+if (!gdb_has_xml) {
+put_packet(gdb_ctx->s, "");
+return;
+}
+
+if (!gdb_ctx->num_params) {
+put_packet(gdb_ctx->s, "E14");
+return;
+}
+
+reg_size = gdb_read_register(gdb_ctx->s->g_cpu, gdb_ctx->mem_buf,
+ gdb_ctx->params[0].val_ull);
+if (!reg_size) {
+put_packet(gdb_ctx->s, "E14");
+return;
+}
+
+memtohex(gdb_ctx->str_buf, gdb_ctx->mem_buf, reg_size);
+put_packet(gdb_ctx->s, gdb_ctx->str_buf);
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1893,18 +1923,14 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 }
 break;
 case 'p':
-/* Older gdb are really dumb, and don't use 'g' if 'p' is avaialable.
-   This works, but can be very slow.  Anything new enough to
-   understand XML also knows how to use this properly.  */
-if (!gdb_has_xml)
-goto unknown_command;
-addr = strtoull(p, (char **), 16);
-reg_size = gdb_read_register(s->g_cpu, mem_buf, addr);
-if (reg_size) {
-memtohex(buf, mem_buf, reg_size);
-put_packet(s, buf);
-} else {
-put_packet(s, "E14");
+{
+static GdbCmdParseEntry get_reg_cmd_desc = {
+.handler = handle_get_reg,
+.cmd = "p",
+.cmd_startswith = 1,
+.schema = "L0"
+};
+process_string_cmd(s, NULL, line_buf, _reg_cmd_desc, 1);
 }
 break;
 case 'P':
-- 
2.20.1




[Qemu-devel] [PATCH v4 16/20] gdbstub: Implement step (s pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 25 +++--
 1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 772bcd2e1f..265a6e3aeb 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1815,6 +1815,16 @@ static void handle_file_io(GdbCmdContext *gdb_ctx, void 
*user_ctx)
 gdb_continue(gdb_ctx->s);
 }
 
+static void handle_step(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+if (gdb_ctx->num_params) {
+gdb_set_cpu_pc(gdb_ctx->s, (target_ulong)gdb_ctx->params[0].val_ull);
+}
+
+cpu_single_step(gdb_ctx->s->c_cpu, sstep_flags);
+gdb_continue(gdb_ctx->s);
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1946,13 +1956,16 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 }
 break;
 case 's':
-if (*p != '\0') {
-addr = strtoull(p, (char **), 16);
-gdb_set_cpu_pc(s, addr);
+{
+static GdbCmdParseEntry step_cmd_desc = {
+.handler = handle_step,
+.cmd = "s",
+.cmd_startswith = 1,
+.schema = "L0"
+};
+process_string_cmd(s, NULL, line_buf, _cmd_desc, 1);
 }
-cpu_single_step(s->c_cpu, sstep_flags);
-gdb_continue(s);
-return RS_IDLE;
+break;
 case 'F':
 {
 static GdbCmdParseEntry file_io_cmd_desc = {
-- 
2.20.1




[Qemu-devel] [PATCH v4 08/20] gdbstub: Implement remove breakpoint (z pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 49 -
 1 file changed, 32 insertions(+), 17 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 03553a1a32..b5d568603c 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1621,6 +1621,29 @@ static void handle_insert_bp(GdbCmdContext *gdb_ctx, 
void *user_ctx)
 put_packet(gdb_ctx->s, "E22");
 }
 
+static void handle_remove_bp(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+int res;
+
+if (gdb_ctx->num_params < 3) {
+put_packet(gdb_ctx->s, "E22");
+return;
+}
+
+res = gdb_breakpoint_remove(gdb_ctx->params[1].val_ull,
+gdb_ctx->params[2].val_ull,
+gdb_ctx->params[0].val_ul);
+if (res >= 0) {
+put_packet(gdb_ctx->s, "OK");
+return;
+} else if (res == -ENOSYS) {
+put_packet(gdb_ctx->s, "");
+return;
+}
+
+put_packet(gdb_ctx->s, "E22");
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1886,23 +1909,15 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 }
 break;
 case 'z':
-type = strtoul(p, (char **), 16);
-if (*p == ',')
-p++;
-addr = strtoull(p, (char **), 16);
-if (*p == ',')
-p++;
-len = strtoull(p, (char **), 16);
-if (ch == 'Z')
-res = gdb_breakpoint_insert(addr, len, type);
-else
-res = gdb_breakpoint_remove(addr, len, type);
-if (res >= 0)
- put_packet(s, "OK");
-else if (res == -ENOSYS)
-put_packet(s, "");
-else
-put_packet(s, "E22");
+{
+static GdbCmdParseEntry remove_bp_cmd_desc = {
+.handler = handle_remove_bp,
+.cmd = "z",
+.cmd_startswith = 1,
+.schema = "l?L?L0"
+};
+process_string_cmd(s, NULL, line_buf, _bp_cmd_desc, 1);
+}
 break;
 case 'H':
 {
-- 
2.20.1




[Qemu-devel] [PATCH v4 20/20] gdbstub: Refactor parse handle packet to work with a static array

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 386 ++
 1 file changed, 158 insertions(+), 228 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 61ab630d9e..69b3a5185e 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -2257,240 +2257,170 @@ static void handle_gen_set(GdbCmdContext *gdb_ctx, 
void *user_ctx)
 put_packet(gdb_ctx->s, "");
 }
 
-static int gdb_handle_packet(GDBState *s, const char *line_buf)
+static void handle_extend_mode(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+put_packet(gdb_ctx->s, "OK");
+}
+
+static void handle_target_halt(GdbCmdContext *gdb_ctx, void *user_ctx)
 {
-const char *p;
-int ch;
-uint8_t mem_buf[MAX_PACKET_LENGTH];
-char buf[sizeof(mem_buf) + 1 /* trailing NUL */];
 char thread_id[16];
 
+/* TODO: Make this return the correct value for user-mode.  */
+gdb_fmt_thread_id(gdb_ctx->s, gdb_ctx->s->c_cpu, thread_id,
+  sizeof(thread_id));
+snprintf(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf), "T%02xthread:%s;",
+ GDB_SIGNAL_TRAP, thread_id);
+put_packet(gdb_ctx->s, gdb_ctx->str_buf);
+/*
+ * Remove all the breakpoints when this query is issued,
+ * because gdb is doing and initial connect and the state
+ * should be cleaned up.
+ */
+gdb_breakpoint_remove_all();
+}
+
+static void handle_kill(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+/* Kill the target */
+error_report("QEMU: Terminated via GDBstub");
+exit(0);
+}
+
+static GdbCmdParseEntry gdb_packet_table[0x100] = {
+['!'] = {
+.handler = handle_extend_mode,
+.cmd = "!",
+.cmd_startswith = 1
+},
+['?'] = {
+.handler = handle_target_halt,
+.cmd = "?",
+.cmd_startswith = 1
+},
+['c'] = {
+.handler = handle_continue,
+.cmd = "c",
+.cmd_startswith = 1,
+.schema = "L0"
+},
+['C'] = {
+.handler = handle_cont_with_sig,
+.cmd = "C",
+.cmd_startswith = 1,
+.schema = "l0"
+},
+['v'] = {
+.handler = handle_v_commands,
+.cmd = "v",
+.cmd_startswith = 1,
+.schema = "s0"
+},
+['k'] = {
+.handler = handle_kill,
+.cmd = "k",
+.cmd_startswith = 1
+},
+['D'] = {
+.handler = handle_detach,
+.cmd = "D",
+.cmd_startswith = 1,
+.schema = "?.l0"
+},
+['s'] = {
+.handler = handle_step,
+.cmd = "s",
+.cmd_startswith = 1,
+.schema = "L0"
+},
+['F'] = {
+.handler = handle_file_io,
+.cmd = "F",
+.cmd_startswith = 1,
+.schema = "s0"
+},
+['g'] = {
+.handler = handle_read_all_regs,
+.cmd = "g",
+.cmd_startswith = 1
+},
+['G'] = {
+.handler = handle_write_all_regs,
+.cmd = "G",
+.cmd_startswith = 1,
+.schema = "s0"
+},
+['m'] = {
+.handler = handle_read_mem,
+.cmd = "m",
+.cmd_startswith = 1,
+.schema = "L,L0"
+},
+['M'] = {
+.handler = handle_write_mem,
+.cmd = "M",
+.cmd_startswith = 1,
+.schema = "L,L:s0"
+},
+['p'] = {
+.handler = handle_get_reg,
+.cmd = "p",
+.cmd_startswith = 1,
+.schema = "L0"
+},
+['P'] = {
+.handler = handle_set_reg,
+.cmd = "P",
+.cmd_startswith = 1,
+.schema = "L?s0"
+},
+['Z'] = {
+.handler = handle_insert_bp,
+.cmd = "Z",
+.cmd_startswith = 1,
+.schema = "l?L?L0"
+},
+['z'] = {
+.handler = handle_remove_bp,
+.cmd = "z",
+.cmd_startswith = 1,
+.schema = "l?L?L0"
+},
+['H'] = {
+.handler = handle_set_thread,
+.cmd = "H",
+.cmd_startswith = 1,
+.schema = "o.t0"
+},
+['T'] = {
+.handler = handle_thread_alive,
+.cmd = "T",
+.cmd_startswith = 1,
+.schema = "t0"
+},
+['q'] = {
+.handler = handle_gen_query,
+.cmd = "q",
+.cmd_startswith = 1,
+.schema = "s0"
+},
+['Q'] = {
+.handler = handle_gen_set,
+.cmd = "Q",
+.cmd_startswith = 1,
+.schema = "s0"
+},
+};
+
+static int gdb_handle_packet(GDBState *s, const char *line_buf)
+{
 trace_gdbstub_io_command(line_buf);
 
-p = line_buf;
-ch = *p++;
-switch(ch) {
-case '!':
-put_packet(s, "OK");
-break;
-case '?':
-/* TODO: Make this return the correct value for user-mode.  */
-snprintf(buf, sizeof(buf), "T%02xthread:%s;", GDB_SIGNAL_TRAP,
- gdb_fmt_thread_id(s, s->c_cpu, thread_id, sizeof(thread_id)));
-put_packet(s, buf);
-/* Remove all the breakpoints when this query is issued,
- * because gdb is doing and initial connect and the state
- * 

[Qemu-devel] [PATCH v4 19/20] gdbstub: Implement generic set (Q pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 213 +++---
 1 file changed, 25 insertions(+), 188 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 8de4e09caa..61ab630d9e 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1130,14 +1130,6 @@ static GDBThreadIdKind read_thread_id(const char *buf, 
const char **end_buf,
 return GDB_ONE_THREAD;
 }
 
-static int is_query_packet(const char *p, const char *query, char separator)
-{
-unsigned int query_len = strlen(query);
-
-return strncmp(p, query, query_len) == 0 &&
-(p[query_len] == '\0' || p[query_len] == separator);
-}
-
 /**
  * gdb_handle_vcont - Parses and handles a vCont packet.
  * returns -ENOTSUP if a command is unsupported, -EINVAL or -ERANGE if there is
@@ -2250,18 +2242,28 @@ static void handle_gen_query(GdbCmdContext *gdb_ctx, 
void *user_ctx)
 }
 }
 
+static void handle_gen_set(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+if (!gdb_ctx->num_params) {
+return;
+}
+
+if (!process_string_cmd(gdb_ctx->s, NULL, gdb_ctx->params[0].data,
+gdb_gen_query_set_common_table,
+ARRAY_SIZE(gdb_gen_query_set_common_table))) {
+return;
+}
+
+put_packet(gdb_ctx->s, "");
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
-CPUState *cpu;
-GDBProcess *process;
-CPUClass *cc;
 const char *p;
-uint32_t pid, tid;
-int ch, type;
+int ch;
 uint8_t mem_buf[MAX_PACKET_LENGTH];
 char buf[sizeof(mem_buf) + 1 /* trailing NUL */];
 char thread_id[16];
-target_ulong addr, len;
 
 trace_gdbstub_io_command(line_buf);
 
@@ -2473,182 +2475,17 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 }
 break;
 case 'Q':
-/* parse any 'q' packets here */
-if (!strcmp(p,"qemu.sstepbits")) {
-/* Query Breakpoint bit definitions */
-snprintf(buf, sizeof(buf), "ENABLE=%x,NOIRQ=%x,NOTIMER=%x",
- SSTEP_ENABLE,
- SSTEP_NOIRQ,
- SSTEP_NOTIMER);
-put_packet(s, buf);
-break;
-} else if (is_query_packet(p, "qemu.sstep", '=')) {
-/* Display or change the sstep_flags */
-p += 10;
-if (*p != '=') {
-/* Display current setting */
-snprintf(buf, sizeof(buf), "0x%x", sstep_flags);
-put_packet(s, buf);
-break;
-}
-p++;
-type = strtoul(p, (char **), 16);
-sstep_flags = type;
-put_packet(s, "OK");
-break;
-} else if (strcmp(p,"C") == 0) {
-/*
- * "Current thread" remains vague in the spec, so always return
- * the first thread of the current process (gdb returns the
- * first thread).
- */
-cpu = get_first_cpu_in_process(s, gdb_get_cpu_process(s, 
s->g_cpu));
-snprintf(buf, sizeof(buf), "QC%s",
- gdb_fmt_thread_id(s, cpu, thread_id, sizeof(thread_id)));
-put_packet(s, buf);
-break;
-} else if (strcmp(p,"fThreadInfo") == 0) {
-s->query_cpu = gdb_first_attached_cpu(s);
-goto report_cpuinfo;
-} else if (strcmp(p,"sThreadInfo") == 0) {
-report_cpuinfo:
-if (s->query_cpu) {
-snprintf(buf, sizeof(buf), "m%s",
- gdb_fmt_thread_id(s, s->query_cpu,
-   thread_id, sizeof(thread_id)));
-put_packet(s, buf);
-s->query_cpu = gdb_next_attached_cpu(s, s->query_cpu);
-} else
-put_packet(s, "l");
-break;
-} else if (strncmp(p,"ThreadExtraInfo,", 16) == 0) {
-if (read_thread_id(p + 16, , , ) == GDB_READ_THREAD_ERR) 
{
-put_packet(s, "E22");
-break;
-}
-cpu = gdb_get_cpu(s, pid, tid);
-if (cpu != NULL) {
-cpu_synchronize_state(cpu);
-
-if (s->multiprocess && (s->process_num > 1)) {
-/* Print the CPU model and name in multiprocess mode */
-ObjectClass *oc = object_get_class(OBJECT(cpu));
-const char *cpu_model = object_class_get_name(oc);
-char *cpu_name =
-object_get_canonical_path_component(OBJECT(cpu));
-len = snprintf((char *)mem_buf, sizeof(buf) / 2,
-   "%s %s [%s]", cpu_model, cpu_name,
-   cpu->halted ? "halted " : "running");
-g_free(cpu_name);
-} else {
-/* memtohex() doubles the required space */
-len = snprintf((char *)mem_buf, sizeof(buf) / 2,
-

[Qemu-devel] [PATCH v4 17/20] gdbstub: Implement v commands with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 170 +++---
 1 file changed, 110 insertions(+), 60 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 265a6e3aeb..8c79e36923 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1825,6 +1825,106 @@ static void handle_step(GdbCmdContext *gdb_ctx, void 
*user_ctx)
 gdb_continue(gdb_ctx->s);
 }
 
+static void handle_v_cont_query(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+put_packet(gdb_ctx->s, "vCont;c;C;s;S");
+}
+
+static void handle_v_cont(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+int res;
+
+if (!gdb_ctx->num_params) {
+return;
+}
+
+res = gdb_handle_vcont(gdb_ctx->s, gdb_ctx->params[0].data);
+if ((res == -EINVAL) || (res == -ERANGE)) {
+put_packet(gdb_ctx->s, "E22");
+} else if (res) {
+put_packet(gdb_ctx->s, "\0");
+}
+}
+
+static void handle_v_attach(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+GDBProcess *process;
+CPUState *cpu;
+char thread_id[16];
+
+strcpy(gdb_ctx->str_buf, "E22");
+if (!gdb_ctx->num_params) {
+goto cleanup;
+}
+
+process = gdb_get_process(gdb_ctx->s, gdb_ctx->params[0].val_ul);
+if (!process) {
+goto cleanup;
+}
+
+cpu = get_first_cpu_in_process(gdb_ctx->s, process);
+if (!cpu) {
+goto cleanup;
+}
+
+process->attached = true;
+gdb_ctx->s->g_cpu = cpu;
+gdb_ctx->s->c_cpu = cpu;
+
+gdb_fmt_thread_id(gdb_ctx->s, cpu, thread_id, sizeof(thread_id));
+snprintf(gdb_ctx->str_buf, sizeof(gdb_ctx->str_buf), "T%02xthread:%s;",
+ GDB_SIGNAL_TRAP, thread_id);
+cleanup:
+put_packet(gdb_ctx->s, gdb_ctx->str_buf);
+}
+
+static void handle_v_kill(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+/* Kill the target */
+put_packet(gdb_ctx->s, "OK");
+error_report("QEMU: Terminated via GDBstub");
+exit(0);
+}
+
+static GdbCmdParseEntry gdb_v_commands_table[] = {
+/* Order is important if has same prefix */
+{
+.handler = handle_v_cont_query,
+.cmd = "Cont?",
+.cmd_startswith = 1
+},
+{
+.handler = handle_v_cont,
+.cmd = "Cont",
+.cmd_startswith = 1,
+.schema = "s0"
+},
+{
+.handler = handle_v_attach,
+.cmd = "Attach;",
+.cmd_startswith = 1,
+.schema = "l0"
+},
+{
+.handler = handle_v_kill,
+.cmd = "Kill;",
+.cmd_startswith = 1
+},
+};
+
+static void handle_v_commands(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+if (!gdb_ctx->num_params) {
+return;
+}
+
+if (process_string_cmd(gdb_ctx->s, NULL, gdb_ctx->params[0].data,
+   gdb_v_commands_table,
+   ARRAY_SIZE(gdb_v_commands_table))) {
+put_packet(gdb_ctx->s, "");
+}
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1832,7 +1932,7 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 CPUClass *cc;
 const char *p;
 uint32_t pid, tid;
-int ch, type, res;
+int ch, type;
 uint8_t mem_buf[MAX_PACKET_LENGTH];
 char buf[sizeof(mem_buf) + 1 /* trailing NUL */];
 char thread_id[16];
@@ -1880,66 +1980,16 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 }
 break;
 case 'v':
-if (strncmp(p, "Cont", 4) == 0) {
-p += 4;
-if (*p == '?') {
-put_packet(s, "vCont;c;C;s;S");
-break;
-}
-
-res = gdb_handle_vcont(s, p);
-
-if (res) {
-if ((res == -EINVAL) || (res == -ERANGE)) {
-put_packet(s, "E22");
-break;
-}
-goto unknown_command;
-}
-break;
-} else if (strncmp(p, "Attach;", 7) == 0) {
-unsigned long pid;
-
-p += 7;
-
-if (qemu_strtoul(p, , 16, )) {
-put_packet(s, "E22");
-break;
-}
-
-process = gdb_get_process(s, pid);
-
-if (process == NULL) {
-put_packet(s, "E22");
-break;
-}
-
-cpu = get_first_cpu_in_process(s, process);
-
-if (cpu == NULL) {
-/* Refuse to attach an empty process */
-put_packet(s, "E22");
-break;
-}
-
-process->attached = true;
-
-s->g_cpu = cpu;
-s->c_cpu = cpu;
-
-snprintf(buf, sizeof(buf), "T%02xthread:%s;", GDB_SIGNAL_TRAP,
- gdb_fmt_thread_id(s, cpu, thread_id, sizeof(thread_id)));
-
-put_packet(s, buf);
-break;
-} else if (strncmp(p, "Kill;", 5) == 0) {
-/* Kill the target */
-put_packet(s, "OK");
-error_report("QEMU: Terminated via GDBstub");
-   

[Qemu-devel] [PATCH v4 13/20] gdbstub: Implement write all registers (G pkt) with new infra

2019-04-24 Thread Jon Doron
Signed-off-by: Jon Doron 
---
 gdbstub.c | 41 +++--
 1 file changed, 31 insertions(+), 10 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index af37222034..084c688f75 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1744,6 +1744,29 @@ static void handle_read_mem(GdbCmdContext *gdb_ctx, void 
*user_ctx)
 put_packet(gdb_ctx->s, gdb_ctx->str_buf);
 }
 
+static void handle_write_all_regs(GdbCmdContext *gdb_ctx, void *user_ctx)
+{
+target_ulong addr, len;
+uint8_t *registers;
+int reg_size;
+
+if (!gdb_ctx->num_params) {
+return;
+}
+
+cpu_synchronize_state(gdb_ctx->s->g_cpu);
+registers = gdb_ctx->mem_buf;
+len = strlen(gdb_ctx->params[0].data) / 2;
+hextomem(registers, gdb_ctx->params[0].data, len);
+for (addr = 0; addr < gdb_ctx->s->g_cpu->gdb_num_g_regs && len > 0;
+ addr++) {
+reg_size = gdb_write_register(gdb_ctx->s->g_cpu, registers, addr);
+len -= reg_size;
+registers += reg_size;
+}
+put_packet(gdb_ctx->s, "OK");
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
 CPUState *cpu;
@@ -1755,7 +1778,6 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 uint8_t mem_buf[MAX_PACKET_LENGTH];
 char buf[sizeof(mem_buf) + 1 /* trailing NUL */];
 char thread_id[16];
-uint8_t *registers;
 target_ulong addr, len;
 
 trace_gdbstub_io_command(line_buf);
@@ -1920,16 +1942,15 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 put_packet(s, buf);
 break;
 case 'G':
-cpu_synchronize_state(s->g_cpu);
-registers = mem_buf;
-len = strlen(p) / 2;
-hextomem((uint8_t *)registers, p, len);
-for (addr = 0; addr < s->g_cpu->gdb_num_g_regs && len > 0; addr++) {
-reg_size = gdb_write_register(s->g_cpu, registers, addr);
-len -= reg_size;
-registers += reg_size;
+{
+static GdbCmdParseEntry write_all_regs_cmd_desc = {
+.handler = handle_write_all_regs,
+.cmd = "G",
+.cmd_startswith = 1,
+.schema = "s0"
+};
+process_string_cmd(s, NULL, line_buf, _all_regs_cmd_desc, 1);
 }
-put_packet(s, "OK");
 break;
 case 'm':
 {
-- 
2.20.1




Re: [Qemu-devel] [PATCH 1/3] qapi: SupportStatusInfo struct

2019-04-24 Thread Eduardo Habkost
On Wed, Apr 24, 2019 at 09:26:52AM +0100, Daniel P. Berrangé wrote:
> On Tue, Apr 23, 2019 at 06:22:44PM -0300, Eduardo Habkost wrote:
> > This struct will be used to represent support and deprecation
> > status of QEMU features.
> > 
> > Signed-off-by: Eduardo Habkost 
> > ---
> >  qapi/common.json | 24 
> >  1 file changed, 24 insertions(+)
> > 
> > diff --git a/qapi/common.json b/qapi/common.json
> > index 99d313ef3b..b59d0dc66b 100644
> > --- a/qapi/common.json
> > +++ b/qapi/common.json
> > @@ -193,3 +193,27 @@
> >   'ppc64', 'riscv32', 'riscv64', 's390x', 'sh4',
> >   'sh4eb', 'sparc', 'sparc64', 'tricore', 'unicore32',
> >   'x86_64', 'xtensa', 'xtensaeb' ] }
> > +
> > +##
> > +# @SupportStatusInfo:
> > +#
> > +# Information on support status of a given feature
> > +# (e.g. machine type)
> > +#
> > +# @deprecated: if true, the given feature is deprecated and may be removed
> > +#  in future versions of QEMU according to the QEMU deprecation
> > +#  policy.
> > +#
> > +# @status-message: Human readable message describing support status
> > +#  of the feature.
> > +#
> > +# @suggested-alternative: Optional.  Suggested alternative for a deprecated
> > +# feature.  For machine types, this should be the 
> > name
> > +# of an available machine-type.
> > +#
> > +# Since: 4.1
> > +##
> > +{ 'struct': 'SupportStatusInfo',
> > +  'data': { 'deprecated': 'bool',
> > +'*status-message': 'str',
> > +'*suggested-alternative': 'str' } }
> 
> I see status-message has to be optional, since you're embedding the
> struct into another struct and want deprecated==false by default.
> 
> I'd be inclined to change it to embed a pointer to the struct and
> drop the deprecated field, and make both status-message and
> suggested-alternative be mandatory. ie a struct  "DeprecationInfo" 
> the pointer to which is NULL if not deprecated.

That could be a simple solution if we were sure we would only
track deprecation info.  But I would like us to track additional
support status on that struct eventually.

Also, I'd like to explicitly differentiate "information is not
available because QEMU is old" from "information is available and
machine type is not deprecated".

-- 
Eduardo



Re: [Qemu-devel] [PATCH 2/3] machine: Use SupportStatusInfo for deprecation info

2019-04-24 Thread Eduardo Habkost
On Wed, Apr 24, 2019 at 09:23:09AM +0100, Daniel P. Berrangé wrote:
> On Tue, Apr 23, 2019 at 06:22:45PM -0300, Eduardo Habkost wrote:
> > Use SupportStatusInfo to represent deprecation information of
> > machine types.
> > 
> > Instead of using a generic "use XXX instead" message for humans,
> > encode the suggested alternative in a machine-friendly way at the
> > 'suggested_alternatives' field.
> > 
> > Signed-off-by: Eduardo Habkost 
> > ---
> >  include/hw/boards.h |  7 ---
> >  hw/i386/pc_piix.c   |  4 +++-
> >  hw/ppc/prep.c   |  4 +++-
> >  vl.c| 13 +
> >  4 files changed, 19 insertions(+), 9 deletions(-)
> > 
> > diff --git a/include/hw/boards.h b/include/hw/boards.h
> > index e231860666..243bf3c7ce 100644
> > --- a/include/hw/boards.h
> > +++ b/include/hw/boards.h
> > @@ -8,6 +8,8 @@
> >  #include "hw/qdev.h"
> >  #include "qom/object.h"
> >  #include "qom/cpu.h"
> > +#include "qapi/qapi-types-common.h"
> > +
> >  
> >  /**
> >   * memory_region_allocate_system_memory - Allocate a board's main memory
> > @@ -105,8 +107,7 @@ typedef struct {
> >  
> >  /**
> >   * MachineClass:
> > - * @deprecation_reason: If set, the machine is marked as deprecated. The
> > - *string should provide some clear information about what to use 
> > instead.
> > + * @support_status: Support and deprecation status of machine type.
> >   * @max_cpus: maximum number of CPUs supported. Default: 1
> >   * @min_cpus: minimum number of CPUs supported. Default: 1
> >   * @default_cpus: number of CPUs instantiated if none are specified. 
> > Default: 1
> > @@ -169,7 +170,7 @@ struct MachineClass {
> >  char *name;
> >  const char *alias;
> >  const char *desc;
> > -const char *deprecation_reason;
> > +SupportStatusInfo support_status;
> >  
> >  void (*init)(MachineState *state);
> >  void (*reset)(void);
> > diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
> > index 8ad8e885c6..97bd401618 100644
> > --- a/hw/i386/pc_piix.c
> > +++ b/hw/i386/pc_piix.c
> > @@ -781,7 +781,9 @@ static void pc_i440fx_0_15_machine_options(MachineClass 
> > *m)
> >  
> >  pc_i440fx_1_0_machine_options(m);
> >  m->hw_version = "0.15";
> > -m->deprecation_reason = "use a newer machine type instead";
> > +m->support_status.deprecated = true;
> > +m->support_status.has_suggested_alternative = true;
> > +m->support_status.suggested_alternative = g_strdup("pc");
> >  compat_props_add(m->compat_props, compat, G_N_ELEMENTS(compat));
> >  }
> >  
> > diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
> > index 847d320465..9a02b0eec4 100644
> > --- a/hw/ppc/prep.c
> > +++ b/hw/ppc/prep.c
> > @@ -587,7 +587,9 @@ static void ppc_prep_init(MachineState *machine)
> >  
> >  static void prep_machine_init(MachineClass *mc)
> >  {
> > -mc->deprecation_reason = "use 40p machine type instead";
> > +mc->support_status.deprecated = true;
> > +mc->support_status.has_suggested_alternative = true;
> > +mc->support_status.suggested_alternative = g_strdup("40p");
> >  mc->desc = "PowerPC PREP platform";
> >  mc->init = ppc_prep_init;
> >  mc->block_default_type = IF_IDE;
> > diff --git a/vl.c b/vl.c
> > index c696ad2a13..99b857ed2a 100644
> > --- a/vl.c
> > +++ b/vl.c
> > @@ -2610,7 +2610,7 @@ static gint machine_class_cmp(gconstpointer a, 
> > gconstpointer b)
> >  }
> >  printf("%-20s %s%s%s\n", mc->name, mc->desc,
> > mc->is_default ? " (default)" : "",
> > -   mc->deprecation_reason ? " (deprecated)" : "");
> > +   mc->support_status.deprecated ? " (deprecated)" : "");
> >  }
> >  }
> >  
> > @@ -4308,9 +4308,14 @@ int main(int argc, char **argv, char **envp)
> >   * called from configure_accelerator().
> >   */
> >  
> > -if (!qtest_enabled() && machine_class->deprecation_reason) {
> > -error_report("Machine type '%s' is deprecated: %s",
> > - machine_class->name, 
> > machine_class->deprecation_reason);
> > +if (!qtest_enabled() && machine_class->support_status.deprecated) {
> > +error_report("Machine type '%s' is deprecated%s%s", 
> > machine_class->name,
> > + machine_class->support_status.status_message ? ": " : 
> > "",
> > + machine_class->support_status.status_message ?: "");
> > +if (machine_class->support_status.suggested_alternative) {
> > +error_report("Suggested solution: use '%s' machine type 
> > instead",
> > + 
> > machine_class->support_status.suggested_alternative);
> 
> I'd just drop the word "Suggested solution: " as I think it is fine to just
> say "Use foobar machine type instead".

I'm not sure.  Can we reword this, but in a way that it still
sounds like a suggestion, not as a definitive solution?

Sometimes the provided alternative won't work for everybody.
e.g. if one day we deprecate pc-i440fx, we can't be 

Re: [Qemu-devel] [PATCH 1/3] qapi: SupportStatusInfo struct

2019-04-24 Thread Eduardo Habkost
On Wed, Apr 24, 2019 at 12:23:33AM +0200, Philippe Mathieu-Daudé wrote:
> Hi Eduardo,
> 
> On 4/23/19 11:22 PM, Eduardo Habkost wrote:
> > This struct will be used to represent support and deprecation
> > status of QEMU features.
> 
> Excellent idea!
> 
> > 
> > Signed-off-by: Eduardo Habkost 
> > ---
> >  qapi/common.json | 24 
> >  1 file changed, 24 insertions(+)
> > 
> > diff --git a/qapi/common.json b/qapi/common.json
> > index 99d313ef3b..b59d0dc66b 100644
> > --- a/qapi/common.json
> > +++ b/qapi/common.json
> > @@ -193,3 +193,27 @@
> >   'ppc64', 'riscv32', 'riscv64', 's390x', 'sh4',
> >   'sh4eb', 'sparc', 'sparc64', 'tricore', 'unicore32',
> >   'x86_64', 'xtensa', 'xtensaeb' ] }
> > +
> > +##
> > +# @SupportStatusInfo:
> > +#
> > +# Information on support status of a given feature
> > +# (e.g. machine type)
> 
> Hopefully it is generic, we can use it for devices too.

Yes, I want to keep it generic.

> 
> > +#
> > +# @deprecated: if true, the given feature is deprecated and may be removed
> > +#  in future versions of QEMU according to the QEMU deprecation
> > +#  policy.
> > +#
> > +# @status-message: Human readable message describing support status
> > +#  of the feature.
> > +#
> > +# @suggested-alternative: Optional.  Suggested alternative for a deprecated
> > +# feature.  For machine types, this should be the 
> > name
> > +# of an available machine-type.
> > +#
> > +# Since: 4.1
> > +##
> > +{ 'struct': 'SupportStatusInfo',
> > +  'data': { 'deprecated': 'bool',
> > +'*status-message': 'str',
> 
> This one shouldn't be optional IMHO, we should enforce developpers to
> give a reason for their deprecation.
> 
> With this argument not optional:
> 
> Reviewed-by: Philippe Mathieu-Daudé 

I might agree with you if you show me what would be a good
"reason for deprecation" string for pc-0.15 and spapr.  :)

The only information contained in these machines today is "use
another machine instead", and this is already encoded in the
suggested-alternative field.

-- 
Eduardo



Re: [Qemu-devel] [PATCH 0/3] Export machine type deprecation info through QMP

2019-04-24 Thread Eduardo Habkost
On Wed, Apr 24, 2019 at 09:31:13AM +0100, Daniel P. Berrangé wrote:
> On Wed, Apr 24, 2019 at 09:56:53AM +0200, Thomas Huth wrote:
> > On 23/04/2019 23.22, Eduardo Habkost wrote:
> > > This series adds machine type deprecation information to the
> > > output of the `query-machines` QMP command.  With this, libvirt
> > > and management software will be able to show this information to
> > > users and/or suggest changes to VM configuration to avoid
> > > deprecated machine types.
> > > 
> > > Eduardo Habkost (3):
> > >   qapi: SupportStatusInfo struct
> > >   machine: Use SupportStatusInfo for deprecation info
> > >   qmp: Add deprecation information to query-machines
> > > 
> > >  qapi/common.json   | 24 
> > >  qapi/misc.json |  5 -
> > >  include/hw/boards.h|  7 ---
> > >  hw/i386/pc_piix.c  |  4 +++-
> > >  hw/ppc/prep.c  |  4 +++-
> > >  vl.c   | 19 +++
> > >  tests/acceptance/query_machines.py | 27 +++
> > >  7 files changed, 80 insertions(+), 10 deletions(-)
> > >  create mode 100644 tests/acceptance/query_machines.py
> > 
> > Good idea, but some questions come to my mind:
> > 
> > - What about devices? IIRC Gerd wrote a patch series last year that does
> >   something similar for devices... It would be good to synchronize the
> >   work, so that we do not have two completely interfaces between devices
> >   and machines here in the end...
> 
> Might as well add  CPU models to that too as there's plenty of awful
> CPUs no one should use with KVM. The tricky thing is they are fine
> / sensible with TCG still.

Right.  We also have devices that are supported in some machines
but not in others.  We will probably need a separate API that
takes a (device type, machine type, accelerator) tuple as input.

-- 
Eduardo



Re: [Qemu-devel] [PATCH 0/3] Export machine type deprecation info through QMP

2019-04-24 Thread Eduardo Habkost
On Wed, Apr 24, 2019 at 09:56:53AM +0200, Thomas Huth wrote:
> On 23/04/2019 23.22, Eduardo Habkost wrote:
> > This series adds machine type deprecation information to the
> > output of the `query-machines` QMP command.  With this, libvirt
> > and management software will be able to show this information to
> > users and/or suggest changes to VM configuration to avoid
> > deprecated machine types.
> > 
> > Eduardo Habkost (3):
> >   qapi: SupportStatusInfo struct
> >   machine: Use SupportStatusInfo for deprecation info
> >   qmp: Add deprecation information to query-machines
> > 
> >  qapi/common.json   | 24 
> >  qapi/misc.json |  5 -
> >  include/hw/boards.h|  7 ---
> >  hw/i386/pc_piix.c  |  4 +++-
> >  hw/ppc/prep.c  |  4 +++-
> >  vl.c   | 19 +++
> >  tests/acceptance/query_machines.py | 27 +++
> >  7 files changed, 80 insertions(+), 10 deletions(-)
> >  create mode 100644 tests/acceptance/query_machines.py
> 
> Good idea, but some questions come to my mind:
> 
> - What about devices? IIRC Gerd wrote a patch series last year that does
>   something similar for devices... It would be good to synchronize the
>   work, so that we do not have two completely interfaces between devices
>   and machines here in the end...

My plan is to support this on devices, too.  I even had a version
where documentation of SupportStatusInfo mentioned device types,
but I decided to leave that out until we actually implement a
device deprecation info API.

> 
> - Is deprecation as a status enough, or do we want to carry more
>   information here? E.g. is the machine maintained or orphan? Is it
>   stable or rather experimental? And didn't Gerd have also some
>   patches for this last year? ... yes, I think it was this series here:
>   http://lists.gnu.org/archive/html/qemu-ppc/2018-11/msg00039.html
>   ... actually, I like that idea with QemuSupportState... maybe you
>   could base your work on that series instead?

We might want to carry more information eventually.  The
possibility of extending the data later is the main reason I
called the struct SupportStatusInfo and not just DeprecationInfo.

But I'd really like us to export the existing information first,
before extending the data.  Having important data available
through stderr and not QMP is a bug.  Tracking additional data
may be desirable, but it would be an additional feature.

-- 
Eduardo



Re: [Qemu-devel] [PATCH v3 02/20] gdbstub: Implement deatch (D pkt) with new infra

2019-04-24 Thread Richard Henderson
On 4/24/19 7:26 AM, ari...@gmail.com wrote:
> +{
> +static GdbCmdParseEntry deatch_cmd_desc = {

static const.  s/deatch/detach/.

That'll require changes to patch 1, since process_string_cmd doesn't take a
const GdbCmdParseEntry pointer.

> +.handler = handle_detach,
> +.cmd = "D",
> +.cmd_startswith = 1,
> +.schema = "?.l0"
> +};
> +process_string_cmd(s, NULL, line_buf, _cmd_desc, 1);

process_string_cmd returns errors, which you make no attempt to handle here.
Should the errors returns in fact be asserts?


r~



Re: [Qemu-devel] [PATCH v3 20/20] gdbstub: Refactor parse handle packet to work with a static array

2019-04-24 Thread Richard Henderson
On 4/24/19 7:27 AM, ari...@gmail.com wrote:
> +static GdbCmdParseEntry gdb_packet_table[0x100] = {

21 out of 256 entries used?  That's a pretty poor occupancy rate.
What was wrong with the switch statement?

Or a modified version in which you sink the call to process_string_cmd
and only load the pointer to the structure within the switch.


r~



Re: [Qemu-devel] [PATCH v3 2/2] core/qdev: refactor qdev_get_machine() with type assertion

2019-04-24 Thread Eduardo Habkost
On Tue, Apr 23, 2019 at 03:59:31PM +0800, Like Xu wrote:
> On 2019/4/18 1:10, Eduardo Habkost wrote:
> > On Wed, Apr 17, 2019 at 07:14:10AM +0200, Markus Armbruster wrote:
> > > Eduardo Habkost  writes:
> > > 
> > > > On Mon, Apr 15, 2019 at 03:59:45PM +0800, Like Xu wrote:
> > > > > To avoid the misuse of qdev_get_machine() if machine hasn't been 
> > > > > created yet,
> > > > > this patch uses qdev_get_machine_uncheck() for obj-common (share with 
> > > > > user-only
> > > > > mode) and adds type assertion to qdev_get_machine() in 
> > > > > system-emulation mode.
> > > > > 
> > > > > Suggested-by: Igor Mammedov 
> > > > > Signed-off-by: Like Xu 
> > > > 
> > > > Reviewed-by: Eduardo Habkost 
> > > > 
> > > > I'm queueing the series on machine-next, thanks!
> > > 
> > > Hold your horses, please.
> > > 
> > > I dislike the name qdev_get_machine_uncheck().  I could live with
> > > qdev_get_machine_unchecked().
> > > 
> > > However, I doubt this is the right approach.
> > > 
> > > The issue at hand is undisciplined creation of QOM object /machine.
> > > 
> > > This patch adds an asseertion "undisciplined creation of /machine didn't
> > > create crap", but only in some places.
> > > 
> > > I think we should never create /machine as (surprising!) side effect of
> > > qdev_get_machine().  Create it explicitly instead, and have
> > > qdev_get_machine() use object_resolve_path("/machine", NULL) to get it.
> > > Look ma, no side effects.
> > 
> > OK, I'm dropping this one while we discuss it.
> > 
> > I really miss a good explanation why qdev_get_machine_unchecked()
> > needs to exist.  When exactly do we want /machine to exist but
> > not be TYPE_MACHINE?  Why?
> 
> AFAICT, there is no such "/machine" that is not of type TYPE_MACHINE.
> 
> The original qdev_get_machine() would always return a "/container" object in
> user-only mode and there is none TYPE_MACHINE object.

I'm confused.  Both qdev_get_machine() and
qdev_get_machine_unchecked() still return the object at
"/machine".  On softmmu, /machine will be of type TYPE_MACHINE.
On user-only, /machine will be of type "container".


> 
> In system emulation mode, it returns the same "/container" object at the
> beginning, until we initialize and add a TYPE_MACHINE object to the
> "/container" as a child and it would return OBJECT(current_machine)
> for later usages.
> 
> The starting point is to avoid using the legacy qdev_get_machine()
> in system emulation mode when we haven't added the "/machine" object.
> As a result, we introduced type checking assertions to avoid premature
> invocations.

I believe Markus is suggesting that avoiding unwanted side
effects is even better than doing type checking after it's
already too late.  In other words, it doesn't make sense to call
container_get("/machine") on system emulation mode.


> 
> In this proposal, the qdev_get_machine_unchecked() is only used
> in user-only mode, part of which shares with system emulation mode
> (such as device_set_realized, cpu_common_realizefn). The new
> qdev_get_machine() is only used in system emulation mode and type checking
> assertion does reduce the irrational use of this function (if any in the
> future).

This part confuses me as well.  qdev_get_machine_unchecked() is
used in both user-only and softmmu, isn't?  Thus we can't say it
is only used in user-only mode.

I think we all agree that qdev_get_machine() should eventually be
available in softmmu only.

But I don't think we agree when it would be appropriate to call
qdev_get_machine_unchecked() instead of qdev_get_machine().

On both examples in your patch, the code checks for TYPE_MACHINE
immediately after calling qdev_get_machine_unchecked().  If that
code is only useful in softmmu mode, when would anybody want to
call qdev_get_machine_unchecked() in user-only mode?


> 
> We all agree to use this qdev_get_machine() as little as possible
> and this patch could make future clean up work easier.
> 
> > 
> > Once the expectations and use cases are explained, we can choose
> > a better name for qdev_get_machine_unchecked() and document it
> > properly.
> > 
> 

-- 
Eduardo



Re: [Qemu-devel] [PATCH v3 01/20] gdbstub: Add infrastructure to parse cmd packets

2019-04-24 Thread Richard Henderson
On 4/24/19 7:26 AM, ari...@gmail.com wrote:
> +static const char *cmd_next_param(const char *param, const char delimiter)
> +{
> +const char *delim;
> +static char all_delimiters[] = ",;:=";

static const char

> +static char no_delimiter[] = "\0";
> +char curr_delimiters[2] = {0};
> +const char *delimiters;
> +
> +if (delimiter == '?') {
> +delimiters = all_delimiters;
> +} else if (delimiter == '0') {
> +delimiters = no_delimiter;

return strchr(param, '\0')

> +while (*param) {
> +delim = delimiters;
> +while (*delim) {
> +if (*param == *delim) {
> +return param + 1;
> +}
> +delim++;
> +}
> +param++;
> +}

Maybe

param += strcspn(param, delim);
if (*param) {
param++;
}
return param;


r~



Re: [Qemu-devel] [PATCH] virtio: clarify VirtioPCIDeviceTypeInfo usage

2019-04-24 Thread Eduardo Habkost
On Wed, Apr 24, 2019 at 04:24:01PM +0100, Stefan Hajnoczi wrote:
> How to use .base_name, .generic_name, .transitional_name, and
> .non_transitional_name can be confusing.
> 
> Existing devices have .generic_name but its behavior is somewhat magic.
> 
> Devices added to new versions of the VIRTIO specification should forego
> transitional mode completely and always operate in non-transitional mode
> because there are no existing drivers for them that require backwards
> compatibility.
> 
> This patch adds comments that hopefully make it easier for developers to
> decide how to fill out VirtioPCIDeviceTypeInfo.
> 
> Signed-off-by: Stefan Hajnoczi 
> ---
>  hw/virtio/virtio-pci.h | 7 ++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h
> index 18581854ca..debdee28b3 100644
> --- a/hw/virtio/virtio-pci.h
> +++ b/hw/virtio/virtio-pci.h
> @@ -209,7 +209,9 @@ typedef struct VirtioPCIDeviceTypeInfo {
>   * Implements both INTERFACE_PCIE_DEVICE and 
> INTERFACE_CONVENTIONAL_PCI_DEVICE,
>   * but PCI Express is supported only in non-transitional mode.
>   *
> - * The only type implemented by QEMU 3.1 and older.
> + * The only type implemented by QEMU 3.1 and older.  This type is less
> + * explicit than the transitional and non-transitional device types.  Its
> + * behavior can be affected by machine type compat properties.

I'm not sure what you mean here.  All types can be affected by
machine type compat properties when necessary, don't they?

>   */
>  const char *generic_name;
>  /*
> @@ -222,6 +224,9 @@ typedef struct VirtioPCIDeviceTypeInfo {
>   * The non-transitional device type.  Optional.
>   *
>   * Implements INTERFACE_CONVENTIONAL_PCI_DEVICE only.
> + *
> + * New virtio device types should only define this and base_name, thereby
> + * allowing only non-transitional mode.
>   */
>  const char *non_transitional_name;
>  
> -- 
> 2.20.1
> 

-- 
Eduardo



Re: [Qemu-devel] [PATCH v1] gdbstub: Refactor gdb packets handler

2019-04-24 Thread no-reply
Patchew URL: https://patchew.org/QEMU/20190424124414.17775-1-ari...@gmail.com/



Hi,

This series failed the asan 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
time make docker-test-debug@fedora TARGET_LIST=x86_64-softmmu J=14 NETWORK=1
=== TEST SCRIPT END ===

  CC  x86_64-softmmu/ioport.o
  CC  x86_64-softmmu/numa.o
  CC  x86_64-softmmu/qtest.o
/tmp/qemu-test/src/gdbstub.c:1660:40: error: suggest braces around 
initialization of subobject [-Werror,-Wmissing-braces]
GdbCmdVariant syscall_params[3] = {0};
   ^
   {}


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

[Qemu-devel] [Bug 1823458] Re: race condition between vhost_net_stop and CHR_EVENT_CLOSED on shutdown crashes qemu

2019-04-24 Thread Dan Streetman
** Patch added: "lp1823458-ocata.debdiff"
   
https://bugs.launchpad.net/cloud-archive/+bug/1823458/+attachment/5258683/+files/lp1823458-ocata.debdiff

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

Title:
  race condition between vhost_net_stop and CHR_EVENT_CLOSED on shutdown
  crashes qemu

Status in Ubuntu Cloud Archive:
  Fix Released
Status in Ubuntu Cloud Archive mitaka series:
  Triaged
Status in Ubuntu Cloud Archive ocata series:
  Triaged
Status in QEMU:
  Fix Released
Status in qemu package in Ubuntu:
  Fix Released
Status in qemu source package in Trusty:
  Won't Fix
Status in qemu source package in Xenial:
  Fix Committed
Status in qemu source package in Bionic:
  Fix Released
Status in qemu source package in Cosmic:
  Fix Released
Status in qemu source package in Disco:
  Fix Released

Bug description:
  [impact]

  on shutdown of a guest, there is a race condition that results in qemu
  crashing instead of normally shutting down.  The bt looks similar to
  this (depending on the specific version of qemu, of course; this is
  taken from 2.5 version of qemu):

  (gdb) bt
  #0  __GI___pthread_mutex_lock (mutex=0x0) at ../nptl/pthread_mutex_lock.c:66
  #1  0x5636c0bc4389 in qemu_mutex_lock (mutex=mutex@entry=0x0) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/util/qemu-thread-posix.c:73
  #2  0x5636c0988130 in qemu_chr_fe_write_all (s=s@entry=0x0, 
buf=buf@entry=0x7ffe65c086a0 "\v", len=len@entry=20) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/qemu-char.c:205
  #3  0x5636c08f3483 in vhost_user_write (msg=msg@entry=0x7ffe65c086a0, 
fds=fds@entry=0x0, fd_num=fd_num@entry=0, dev=0x5636c1bf6b70, 
dev=0x5636c1bf6b70)
  at /build/qemu-7I4i1R/qemu-2.5+dfsg/hw/virtio/vhost-user.c:195
  #4  0x5636c08f411c in vhost_user_get_vring_base (dev=0x5636c1bf6b70, 
ring=0x7ffe65c087e0) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/hw/virtio/vhost-user.c:364
  #5  0x5636c08efff0 in vhost_virtqueue_stop (dev=dev@entry=0x5636c1bf6b70, 
vdev=vdev@entry=0x5636c2853338, vq=0x5636c1bf6d00, idx=1) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/hw/virtio/vhost.c:895
  #6  0x5636c08f2944 in vhost_dev_stop (hdev=hdev@entry=0x5636c1bf6b70, 
vdev=vdev@entry=0x5636c2853338) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/hw/virtio/vhost.c:1262
  #7  0x5636c08db2a8 in vhost_net_stop_one (net=0x5636c1bf6b70, 
dev=dev@entry=0x5636c2853338) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/hw/net/vhost_net.c:293
  #8  0x5636c08dbe5b in vhost_net_stop (dev=dev@entry=0x5636c2853338, 
ncs=0x5636c209d110, total_queues=total_queues@entry=1) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/hw/net/vhost_net.c:371
  #9  0x5636c08d7745 in virtio_net_vhost_status (status=7 '\a', 
n=0x5636c2853338) at /build/qemu-7I4i1R/qemu-2.5+dfsg/hw/net/virtio-net.c:150
  #10 virtio_net_set_status (vdev=, status=) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/hw/net/virtio-net.c:162
  #11 0x5636c08ec42c in virtio_set_status (vdev=0x5636c2853338, 
val=) at /build/qemu-7I4i1R/qemu-2.5+dfsg/hw/virtio/virtio.c:624
  #12 0x5636c098fed2 in vm_state_notify (running=running@entry=0, 
state=state@entry=RUN_STATE_SHUTDOWN) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/vl.c:1605
  #13 0x5636c089172a in do_vm_stop (state=RUN_STATE_SHUTDOWN) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/cpus.c:724
  #14 vm_stop (state=RUN_STATE_SHUTDOWN) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/cpus.c:1407
  #15 0x5636c085d240 in main_loop_should_exit () at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/vl.c:1883
  #16 main_loop () at /build/qemu-7I4i1R/qemu-2.5+dfsg/vl.c:1931
  #17 main (argc=, argv=, envp=) 
at /build/qemu-7I4i1R/qemu-2.5+dfsg/vl.c:4683

  [test case]

  unfortunately since this is a race condition, it's very hard to
  arbitrarily reproduce; it depends very much on the overall
  configuration of the guest as well as how exactly it's shut down -
  specifically, its vhost user net must be closed from the host side at
  a specific time during qemu shutdown.

  I have someone with such a setup who has reported to me their setup is
  able to reproduce this reliably, but the config is too complex for me
  to reproduce so I have relied on their reproduction and testing to
  debug and craft the patch for this.

  [regression potential]

  the change adds a flag to prevent repeated calls to vhost_net_stop().
  This also prevents any calls to vhost_net_cleanup() from
  net_vhost_user_event().  Any regression would be seen when stopping
  and/or cleaning up a vhost net.  Regressions might include failure to
  hot-remove a vhost net from a guest, or failure to cleanup (i.e. mem
  leak), or crashes during cleanup or stopping a vhost net.

  [other info]

  this was originally seen in the 2.5 version of qemu - specifically,
  the UCA version in trusty-mitaka (which uses the xenial qemu
  codebase).

  After discussion upstream, it appears this was fixed upstream by
  commit e7c83a885f8, which is included starting in version 2.9.
  

[Qemu-devel] [Bug 1823458] Re: race condition between vhost_net_stop and CHR_EVENT_CLOSED on shutdown crashes qemu

2019-04-24 Thread Dan Streetman
uca: workaround patches are needed in mitaka and ocata.  Mitaka can pull
from Xenial build as usual, and debdiff for Ocata attached.  Other UCA
releases are later than 2.9 and so are fixed with the upstream fix
mentioned in the description.

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

Title:
  race condition between vhost_net_stop and CHR_EVENT_CLOSED on shutdown
  crashes qemu

Status in Ubuntu Cloud Archive:
  Fix Released
Status in Ubuntu Cloud Archive mitaka series:
  Triaged
Status in Ubuntu Cloud Archive ocata series:
  Triaged
Status in QEMU:
  Fix Released
Status in qemu package in Ubuntu:
  Fix Released
Status in qemu source package in Trusty:
  Won't Fix
Status in qemu source package in Xenial:
  Fix Committed
Status in qemu source package in Bionic:
  Fix Released
Status in qemu source package in Cosmic:
  Fix Released
Status in qemu source package in Disco:
  Fix Released

Bug description:
  [impact]

  on shutdown of a guest, there is a race condition that results in qemu
  crashing instead of normally shutting down.  The bt looks similar to
  this (depending on the specific version of qemu, of course; this is
  taken from 2.5 version of qemu):

  (gdb) bt
  #0  __GI___pthread_mutex_lock (mutex=0x0) at ../nptl/pthread_mutex_lock.c:66
  #1  0x5636c0bc4389 in qemu_mutex_lock (mutex=mutex@entry=0x0) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/util/qemu-thread-posix.c:73
  #2  0x5636c0988130 in qemu_chr_fe_write_all (s=s@entry=0x0, 
buf=buf@entry=0x7ffe65c086a0 "\v", len=len@entry=20) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/qemu-char.c:205
  #3  0x5636c08f3483 in vhost_user_write (msg=msg@entry=0x7ffe65c086a0, 
fds=fds@entry=0x0, fd_num=fd_num@entry=0, dev=0x5636c1bf6b70, 
dev=0x5636c1bf6b70)
  at /build/qemu-7I4i1R/qemu-2.5+dfsg/hw/virtio/vhost-user.c:195
  #4  0x5636c08f411c in vhost_user_get_vring_base (dev=0x5636c1bf6b70, 
ring=0x7ffe65c087e0) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/hw/virtio/vhost-user.c:364
  #5  0x5636c08efff0 in vhost_virtqueue_stop (dev=dev@entry=0x5636c1bf6b70, 
vdev=vdev@entry=0x5636c2853338, vq=0x5636c1bf6d00, idx=1) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/hw/virtio/vhost.c:895
  #6  0x5636c08f2944 in vhost_dev_stop (hdev=hdev@entry=0x5636c1bf6b70, 
vdev=vdev@entry=0x5636c2853338) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/hw/virtio/vhost.c:1262
  #7  0x5636c08db2a8 in vhost_net_stop_one (net=0x5636c1bf6b70, 
dev=dev@entry=0x5636c2853338) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/hw/net/vhost_net.c:293
  #8  0x5636c08dbe5b in vhost_net_stop (dev=dev@entry=0x5636c2853338, 
ncs=0x5636c209d110, total_queues=total_queues@entry=1) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/hw/net/vhost_net.c:371
  #9  0x5636c08d7745 in virtio_net_vhost_status (status=7 '\a', 
n=0x5636c2853338) at /build/qemu-7I4i1R/qemu-2.5+dfsg/hw/net/virtio-net.c:150
  #10 virtio_net_set_status (vdev=, status=) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/hw/net/virtio-net.c:162
  #11 0x5636c08ec42c in virtio_set_status (vdev=0x5636c2853338, 
val=) at /build/qemu-7I4i1R/qemu-2.5+dfsg/hw/virtio/virtio.c:624
  #12 0x5636c098fed2 in vm_state_notify (running=running@entry=0, 
state=state@entry=RUN_STATE_SHUTDOWN) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/vl.c:1605
  #13 0x5636c089172a in do_vm_stop (state=RUN_STATE_SHUTDOWN) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/cpus.c:724
  #14 vm_stop (state=RUN_STATE_SHUTDOWN) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/cpus.c:1407
  #15 0x5636c085d240 in main_loop_should_exit () at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/vl.c:1883
  #16 main_loop () at /build/qemu-7I4i1R/qemu-2.5+dfsg/vl.c:1931
  #17 main (argc=, argv=, envp=) 
at /build/qemu-7I4i1R/qemu-2.5+dfsg/vl.c:4683

  [test case]

  unfortunately since this is a race condition, it's very hard to
  arbitrarily reproduce; it depends very much on the overall
  configuration of the guest as well as how exactly it's shut down -
  specifically, its vhost user net must be closed from the host side at
  a specific time during qemu shutdown.

  I have someone with such a setup who has reported to me their setup is
  able to reproduce this reliably, but the config is too complex for me
  to reproduce so I have relied on their reproduction and testing to
  debug and craft the patch for this.

  [regression potential]

  the change adds a flag to prevent repeated calls to vhost_net_stop().
  This also prevents any calls to vhost_net_cleanup() from
  net_vhost_user_event().  Any regression would be seen when stopping
  and/or cleaning up a vhost net.  Regressions might include failure to
  hot-remove a vhost net from a guest, or failure to cleanup (i.e. mem
  leak), or crashes during cleanup or stopping a vhost net.

  [other info]

  this was originally seen in the 2.5 version of qemu - specifically,
  the UCA version in trusty-mitaka (which uses the xenial qemu
  codebase).

  After discussion upstream, it appears this 

Re: [Qemu-devel] [PATCH v2 0/3] vhost-scsi: Support migration

2019-04-24 Thread Liran Alon



> On 18 Apr 2019, at 12:41, Stefan Hajnoczi  wrote:
> 
> On Tue, Apr 16, 2019 at 03:59:09PM +0300, Liran Alon wrote:
>> Hi,
>> 
>> This patch series aims to add supprot to migrate a VM with a vhost-scsi 
>> device.
>> 
>> The 1st patch fixes a bug of mistakenly not stopping vhost-scsi backend when 
>> a
>> VM is stopped (As happens on migratino pre-copy completion).
>> 
>> The 2nd patch adds ability to save/load vhost-scsi device state in VMState.
>> 
>> The 3rd and final paqtch adds a flag to vhost-scsi which allows admin to 
>> specify
>> it's setup supports vhost-scsi migratino. For more detailed information on 
>> why
>> this is valid, see commit message of specific patch.
>> 
>> Regards,
>> -Liran
> 
> Looks fine for vhost_scsi.ko.  I have not checked how this interacts
> with vhost-user-scsi.
> 
> Reviewed-by: Stefan Hajnoczi 

Gentle Ping.

-Liran


Re: [Qemu-devel] [PATCH v4 02/11] block: Filtered children access functions

2019-04-24 Thread Max Reitz
On 19.04.19 12:23, Vladimir Sementsov-Ogievskiy wrote:
> 17.04.2019 19:22, Max Reitz wrote:
>> On 16.04.19 12:02, Vladimir Sementsov-Ogievskiy wrote:
>>> 10.04.2019 23:20, Max Reitz wrote:
 What bs->file and bs->backing mean depends on the node.  For filter
 nodes, both signify a node that will eventually receive all R/W
 accesses.  For format nodes, bs->file contains metadata and data, and
 bs->backing will not receive writes -- instead, writes are COWed to
 bs->file.  Usually.

 In any case, it is not trivial to guess what a child means exactly with
 our currently limited form of expression.  It is better to introduce
 some functions that actually guarantee a meaning:

 - bdrv_filtered_cow_child() will return the child that receives requests
 filtered through COW.  That is, reads may or may not be forwarded
 (depending on the overlay's allocation status), but writes never go to
 this child.

 - bdrv_filtered_rw_child() will return the child that receives requests
 filtered through some very plain process.  Reads and writes issued to
 the parent will go to the child as well (although timing, etc. may be
 modified).

 - All drivers but quorum (but quorum is pretty opaque to the general
 block layer anyway) always only have one of these children: All read
 requests must be served from the filtered_rw_child (if it exists), so
 if there was a filtered_cow_child in addition, it would not receive
 any requests at all.
 (The closest here is mirror, where all requests are passed on to the
 source, but with write-blocking, write requests are "COWed" to the
 target.  But that just means that the target is a special child that
 cannot be introspected by the generic block layer functions, and that
 source is a filtered_rw_child.)
 Therefore, we can also add bdrv_filtered_child() which returns that
 one child (or NULL, if there is no filtered child).

 Also, many places in the current block layer should be skipping filters
 (all filters or just the ones added implicitly, it depends) when going
 through a block node chain.  They do not do that currently, but this
 patch makes them.

 One example for this is qemu-img map, which should skip filters and only
 look at the COW elements in the graph.  The change to iotest 204's
 reference output shows how using blkdebug on top of a COW node used to
 make qemu-img map disregard the rest of the backing chain, but with this
 patch, the allocation in the base image is reported correctly.

 Furthermore, a note should be made that sometimes we do want to access
 bs->backing directly.  This is whenever the operation in question is not
 about accessing the COW child, but the "backing" child, be it COW or
 not.  This is the case in functions such as bdrv_open_backing_file() or
 whenever we have to deal with the special behavior of @backing as a
 blockdev option, which is that it does not default to null like all
 other child references do.

 Finally, the query functions (query-block and query-named-block-nodes)
 are modified to return any filtered child under "backing", not just
 bs->backing or COW children.  This is so that filters do not interrupt
 the reported backing chain.  This changes the output of iotest 184, as
 the throttled node now appears as a backing child.

 Signed-off-by: Max Reitz 
 ---
qapi/block-core.json   |   4 +
include/block/block.h  |   1 +
include/block/block_int.h  |  40 +--
block.c| 210 +++--
block/backup.c |   8 +-
block/block-backend.c  |  16 ++-
block/commit.c |  33 +++---
block/io.c |  45 ---
block/mirror.c |  21 ++--
block/qapi.c   |  30 +++--
block/stream.c |  13 +-
blockdev.c |  88 +++---
migration/block-dirty-bitmap.c |   4 +-
nbd/server.c   |   6 +-
qemu-img.c |  29 ++---
tests/qemu-iotests/184.out |   7 +-
tests/qemu-iotests/204.out |   1 +
17 files changed, 411 insertions(+), 145 deletions(-)
>>>
>>> really huge... didn't you consider conversion file-by-file?
>>
>> Frankly, no, I just didn’t consider it.
>>
>> Hm.  I don’t know, 30-patch series always look so frightening.
>>
 diff --git a/block.c b/block.c
 index 16615bc876..e8f6febda0 100644
 --- a/block.c
 +++ b/block.c
>>>
>>> [..]
>>>

 @@ -3467,14 +3469,17 @@ static int 
 bdrv_reopen_parse_backing(BDRVReopenState *reopen_state,
/*
 * 

[Qemu-devel] [Bug 1823458] Re: race condition between vhost_net_stop and CHR_EVENT_CLOSED on shutdown crashes qemu

2019-04-24 Thread Corey Bryant
** Also affects: cloud-archive/ocata
   Importance: Undecided
   Status: New

** Changed in: cloud-archive/ocata
   Importance: Undecided => Medium

** Changed in: cloud-archive/ocata
   Status: New => Triaged

** Changed in: cloud-archive
   Status: New => Fix Released

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

Title:
  race condition between vhost_net_stop and CHR_EVENT_CLOSED on shutdown
  crashes qemu

Status in Ubuntu Cloud Archive:
  Fix Released
Status in Ubuntu Cloud Archive mitaka series:
  Triaged
Status in Ubuntu Cloud Archive ocata series:
  Triaged
Status in QEMU:
  Fix Released
Status in qemu package in Ubuntu:
  Fix Released
Status in qemu source package in Trusty:
  Won't Fix
Status in qemu source package in Xenial:
  Fix Committed
Status in qemu source package in Bionic:
  Fix Released
Status in qemu source package in Cosmic:
  Fix Released
Status in qemu source package in Disco:
  Fix Released

Bug description:
  [impact]

  on shutdown of a guest, there is a race condition that results in qemu
  crashing instead of normally shutting down.  The bt looks similar to
  this (depending on the specific version of qemu, of course; this is
  taken from 2.5 version of qemu):

  (gdb) bt
  #0  __GI___pthread_mutex_lock (mutex=0x0) at ../nptl/pthread_mutex_lock.c:66
  #1  0x5636c0bc4389 in qemu_mutex_lock (mutex=mutex@entry=0x0) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/util/qemu-thread-posix.c:73
  #2  0x5636c0988130 in qemu_chr_fe_write_all (s=s@entry=0x0, 
buf=buf@entry=0x7ffe65c086a0 "\v", len=len@entry=20) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/qemu-char.c:205
  #3  0x5636c08f3483 in vhost_user_write (msg=msg@entry=0x7ffe65c086a0, 
fds=fds@entry=0x0, fd_num=fd_num@entry=0, dev=0x5636c1bf6b70, 
dev=0x5636c1bf6b70)
  at /build/qemu-7I4i1R/qemu-2.5+dfsg/hw/virtio/vhost-user.c:195
  #4  0x5636c08f411c in vhost_user_get_vring_base (dev=0x5636c1bf6b70, 
ring=0x7ffe65c087e0) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/hw/virtio/vhost-user.c:364
  #5  0x5636c08efff0 in vhost_virtqueue_stop (dev=dev@entry=0x5636c1bf6b70, 
vdev=vdev@entry=0x5636c2853338, vq=0x5636c1bf6d00, idx=1) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/hw/virtio/vhost.c:895
  #6  0x5636c08f2944 in vhost_dev_stop (hdev=hdev@entry=0x5636c1bf6b70, 
vdev=vdev@entry=0x5636c2853338) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/hw/virtio/vhost.c:1262
  #7  0x5636c08db2a8 in vhost_net_stop_one (net=0x5636c1bf6b70, 
dev=dev@entry=0x5636c2853338) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/hw/net/vhost_net.c:293
  #8  0x5636c08dbe5b in vhost_net_stop (dev=dev@entry=0x5636c2853338, 
ncs=0x5636c209d110, total_queues=total_queues@entry=1) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/hw/net/vhost_net.c:371
  #9  0x5636c08d7745 in virtio_net_vhost_status (status=7 '\a', 
n=0x5636c2853338) at /build/qemu-7I4i1R/qemu-2.5+dfsg/hw/net/virtio-net.c:150
  #10 virtio_net_set_status (vdev=, status=) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/hw/net/virtio-net.c:162
  #11 0x5636c08ec42c in virtio_set_status (vdev=0x5636c2853338, 
val=) at /build/qemu-7I4i1R/qemu-2.5+dfsg/hw/virtio/virtio.c:624
  #12 0x5636c098fed2 in vm_state_notify (running=running@entry=0, 
state=state@entry=RUN_STATE_SHUTDOWN) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/vl.c:1605
  #13 0x5636c089172a in do_vm_stop (state=RUN_STATE_SHUTDOWN) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/cpus.c:724
  #14 vm_stop (state=RUN_STATE_SHUTDOWN) at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/cpus.c:1407
  #15 0x5636c085d240 in main_loop_should_exit () at 
/build/qemu-7I4i1R/qemu-2.5+dfsg/vl.c:1883
  #16 main_loop () at /build/qemu-7I4i1R/qemu-2.5+dfsg/vl.c:1931
  #17 main (argc=, argv=, envp=) 
at /build/qemu-7I4i1R/qemu-2.5+dfsg/vl.c:4683

  [test case]

  unfortunately since this is a race condition, it's very hard to
  arbitrarily reproduce; it depends very much on the overall
  configuration of the guest as well as how exactly it's shut down -
  specifically, its vhost user net must be closed from the host side at
  a specific time during qemu shutdown.

  I have someone with such a setup who has reported to me their setup is
  able to reproduce this reliably, but the config is too complex for me
  to reproduce so I have relied on their reproduction and testing to
  debug and craft the patch for this.

  [regression potential]

  the change adds a flag to prevent repeated calls to vhost_net_stop().
  This also prevents any calls to vhost_net_cleanup() from
  net_vhost_user_event().  Any regression would be seen when stopping
  and/or cleaning up a vhost net.  Regressions might include failure to
  hot-remove a vhost net from a guest, or failure to cleanup (i.e. mem
  leak), or crashes during cleanup or stopping a vhost net.

  [other info]

  this was originally seen in the 2.5 version of qemu - specifically,
  the UCA version in trusty-mitaka (which uses the xenial qemu
  codebase).

  

[Qemu-devel] [RFC PATCH v1 06/10] KVM: SVM: Add KVM_SEV_RECEIVE_FINISH command

2019-04-24 Thread Singh, Brijesh
The command finalize the guest receiving process and make the SEV guest
ready for the execution.

Cc: Thomas Gleixner 
Cc: Ingo Molnar 
Cc: "H. Peter Anvin" 
Cc: Paolo Bonzini 
Cc: "Radim Krčmář" 
Cc: Joerg Roedel 
Cc: Borislav Petkov 
Cc: Tom Lendacky 
Cc: x...@kernel.org
Cc: k...@vger.kernel.org
Cc: linux-ker...@vger.kernel.org
Signed-off-by: Brijesh Singh 
---
 .../virtual/kvm/amd-memory-encryption.rst |  8 +++
 arch/x86/kvm/svm.c| 23 +++
 2 files changed, 31 insertions(+)

diff --git a/Documentation/virtual/kvm/amd-memory-encryption.rst 
b/Documentation/virtual/kvm/amd-memory-encryption.rst
index b9c3dc02f344..72c45f93abd7 100644
--- a/Documentation/virtual/kvm/amd-memory-encryption.rst
+++ b/Documentation/virtual/kvm/amd-memory-encryption.rst
@@ -346,6 +346,14 @@ Returns: 0 on success, -negative on error
 __u32 trans_len;
 };
 
+15. KVM_SEV_RECEIVE_FINISH
+
+
+After completion of the migration flow, the KVM_SEV_RECEIVE_FINISH command can 
be
+issued by the hypervisor to make the guest ready for the execution.
+
+Returns: 0 on success, -negative on error
+
 References
 ==
 
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index c81cac09c5af..74b57ab742ad 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -7350,6 +7350,26 @@ static int sev_receive_update_data(struct kvm *kvm, 
struct kvm_sev_cmd *argp)
return ret;
 }
 
+static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp)
+{
+   struct kvm_sev_info *sev = _kvm_svm(kvm)->sev_info;
+   struct sev_data_receive_finish *data;
+   int ret;
+
+   if (!sev_guest(kvm))
+   return -ENOTTY;
+
+   data = kzalloc(sizeof(*data), GFP_KERNEL);
+   if (!data)
+   return -ENOMEM;
+
+   data->handle = sev->handle;
+   ret = sev_issue_cmd(kvm, SEV_CMD_RECEIVE_FINISH, data, >error);
+
+   kfree(data);
+   return ret;
+}
+
 static int svm_mem_enc_op(struct kvm *kvm, void __user *argp)
 {
struct kvm_sev_cmd sev_cmd;
@@ -7406,6 +7426,9 @@ static int svm_mem_enc_op(struct kvm *kvm, void __user 
*argp)
case KVM_SEV_RECEIVE_UPDATE_DATA:
r = sev_receive_update_data(kvm, _cmd);
break;
+   case KVM_SEV_RECEIVE_FINISH:
+   r = sev_receive_finish(kvm, _cmd);
+   break;
default:
r = -EINVAL;
goto out;
-- 
2.17.1



[Qemu-devel] [RFC PATCH v1 03/10] KVM: SVM: Add KVM_SEV_SEND_FINISH command

2019-04-24 Thread Singh, Brijesh
The command is used to finailize the encryption context created with
KVM_SEV_SEND_START command.

Cc: Thomas Gleixner 
Cc: Ingo Molnar 
Cc: "H. Peter Anvin" 
Cc: Paolo Bonzini 
Cc: "Radim Krčmář" 
Cc: Joerg Roedel 
Cc: Borislav Petkov 
Cc: Tom Lendacky 
Cc: x...@kernel.org
Cc: k...@vger.kernel.org
Cc: linux-ker...@vger.kernel.org
Signed-off-by: Brijesh Singh 
---
 .../virtual/kvm/amd-memory-encryption.rst |  8 +++
 arch/x86/kvm/svm.c| 23 +++
 2 files changed, 31 insertions(+)

diff --git a/Documentation/virtual/kvm/amd-memory-encryption.rst 
b/Documentation/virtual/kvm/amd-memory-encryption.rst
index a0208e171489..006832256ae3 100644
--- a/Documentation/virtual/kvm/amd-memory-encryption.rst
+++ b/Documentation/virtual/kvm/amd-memory-encryption.rst
@@ -285,6 +285,14 @@ Returns: 0 on success, -negative on error
 __u32 trans_len;
 };
 
+12. KVM_SEV_SEND_FINISH
+
+
+After completion of the migration flow, the KVM_SEV_SEND_FINISH command can be
+issued by the hypervisor to delete the encryption context.
+
+Returns: 0 on success, -negative on error
+
 References
 ==
 
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index a1cfd36d6195..263f3c7deae7 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -7172,6 +7172,26 @@ static int sev_send_update_data(struct kvm *kvm, struct 
kvm_sev_cmd *argp)
return ret;
 }
 
+static int sev_send_finish(struct kvm *kvm, struct kvm_sev_cmd *argp)
+{
+   struct kvm_sev_info *sev = _kvm_svm(kvm)->sev_info;
+   struct sev_data_send_finish *data;
+   int ret;
+
+   if (!sev_guest(kvm))
+   return -ENOTTY;
+
+   data = kzalloc(sizeof(*data), GFP_KERNEL);
+   if (!data)
+   return -ENOMEM;
+
+   data->handle = sev->handle;
+   ret = sev_issue_cmd(kvm, SEV_CMD_SEND_FINISH, data, >error);
+
+   kfree(data);
+   return ret;
+}
+
 static int svm_mem_enc_op(struct kvm *kvm, void __user *argp)
 {
struct kvm_sev_cmd sev_cmd;
@@ -7219,6 +7239,9 @@ static int svm_mem_enc_op(struct kvm *kvm, void __user 
*argp)
case KVM_SEV_SEND_UPDATE_DATA:
r = sev_send_update_data(kvm, _cmd);
break;
+   case KVM_SEV_SEND_FINISH:
+   r = sev_send_finish(kvm, _cmd);
+   break;
default:
r = -EINVAL;
goto out;
-- 
2.17.1



[Qemu-devel] [RFC PATCH v1 08/10] KVM: X86: Introduce KVM_HC_PAGE_ENC_STATUS hypercall

2019-04-24 Thread Singh, Brijesh
The hypercall can be used by the SEV guest to notify the page encryption
status to the hypervisor. The hypercall should be invoked only when
the encryption attribute is changed from encrypted -> decrypted and vice
versa. By default all the guest pages should be considered encrypted.

Cc: Thomas Gleixner 
Cc: Ingo Molnar 
Cc: "H. Peter Anvin" 
Cc: Paolo Bonzini 
Cc: "Radim Krčmář" 
Cc: Joerg Roedel 
Cc: Borislav Petkov 
Cc: Tom Lendacky 
Cc: x...@kernel.org
Cc: k...@vger.kernel.org
Cc: linux-ker...@vger.kernel.org
Signed-off-by: Brijesh Singh 
---
 Documentation/virtual/kvm/hypercalls.txt | 14 +
 arch/x86/include/asm/kvm_host.h  |  2 +
 arch/x86/kvm/svm.c   | 69 
 arch/x86/kvm/vmx/vmx.c   |  1 +
 arch/x86/kvm/x86.c   |  5 ++
 include/uapi/linux/kvm_para.h|  1 +
 6 files changed, 92 insertions(+)

diff --git a/Documentation/virtual/kvm/hypercalls.txt 
b/Documentation/virtual/kvm/hypercalls.txt
index da24c138c8d1..ecd44e488679 100644
--- a/Documentation/virtual/kvm/hypercalls.txt
+++ b/Documentation/virtual/kvm/hypercalls.txt
@@ -141,3 +141,17 @@ a0 corresponds to the APIC ID in the third argument (a2), 
bit 1
 corresponds to the APIC ID a2+1, and so on.
 
 Returns the number of CPUs to which the IPIs were delivered successfully.
+
+7. KVM_HC_PAGE_ENC_STATUS
+-
+Architecture: x86
+Status: active
+Purpose: Notify the encryption status changes in guest page table (SEV guest)
+
+a0: the guest physical address of the start page
+a1: the number of pages
+a2: set or clear the encryption attribute
+
+   Where:
+   * 1: Encryption attribute is set
+   * 0: Encryption attribute is cleared
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index a9d03af34030..adb0ca035b97 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1196,6 +1196,8 @@ struct kvm_x86_ops {
uint16_t (*nested_get_evmcs_version)(struct kvm_vcpu *vcpu);
 
bool (*need_emulation_on_page_fault)(struct kvm_vcpu *vcpu);
+   int (*page_enc_status_hc)(struct kvm *kvm, unsigned long gpa,
+ unsigned long sz, unsigned long mode);
 };
 
 struct kvm_arch_async_pf {
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 74b57ab742ad..f024f208b052 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -138,6 +138,8 @@ struct kvm_sev_info {
int fd; /* SEV device fd */
unsigned long pages_locked; /* Number of pages locked */
struct list_head regions_list;  /* List of registered regions */
+   unsigned long *page_enc_bmap;
+   unsigned long page_enc_bmap_size;
 };
 
 struct kvm_svm {
@@ -1911,6 +1913,8 @@ static void sev_vm_destroy(struct kvm *kvm)
 
sev_unbind_asid(kvm, sev->handle);
sev_asid_free(kvm);
+
+   kvfree(sev->page_enc_bmap);
 }
 
 static void avic_vm_destroy(struct kvm *kvm)
@@ -7370,6 +7374,69 @@ static int sev_receive_finish(struct kvm *kvm, struct 
kvm_sev_cmd *argp)
return ret;
 }
 
+static int sev_resize_page_enc_bitmap(struct kvm *kvm, unsigned long new_size)
+{
+   struct kvm_sev_info *sev = _kvm_svm(kvm)->sev_info;
+   unsigned long *map;
+   unsigned long sz;
+
+   if (sev->page_enc_bmap_size >= new_size)
+   return 0;
+
+   sz = ALIGN(new_size, BITS_PER_LONG) / 8;
+
+   if (sz > PAGE_SIZE)
+   map = vmalloc(sz);
+   else
+   map = kmalloc(sz, GFP_KERNEL);
+
+   if (!map) {
+   pr_err_once("Failed to allocate decrypted bitmap size %lx\n", 
sz);
+   return 1;
+   }
+
+   /* mark the page encrypted (by default) */
+   memset(map, 0xff, sz);
+
+   bitmap_copy(map, sev->page_enc_bmap, sev->page_enc_bmap_size);
+   kvfree(sev->page_enc_bmap);
+
+   sev->page_enc_bmap = map;
+   sev->page_enc_bmap_size = new_size;
+
+   return 0;
+}
+
+static int svm_page_enc_status_hc(struct kvm *kvm, unsigned long gpa,
+ unsigned long npages, unsigned long enc)
+{
+   struct kvm_sev_info *sev = _kvm_svm(kvm)->sev_info;
+   gfn_t gfn_start, gfn_end;
+   int r;
+
+   if (!npages)
+   return 0;
+
+   gfn_start = gpa_to_gfn(gpa);
+   gfn_end = gfn_start + npages;
+
+   mutex_lock(>lock);
+
+   r = 1;
+   if (sev_resize_page_enc_bitmap(kvm, gfn_end))
+   goto unlock;
+
+   if (enc)
+   __bitmap_set(sev->page_enc_bmap, gfn_start, gfn_end - 
gfn_start);
+   else
+   __bitmap_clear(sev->page_enc_bmap, gfn_start, gfn_end - 
gfn_start);
+
+   r = 0;
+unlock:
+   mutex_unlock(>lock);
+   return r;
+}
+
 static int svm_mem_enc_op(struct kvm *kvm, void __user *argp)
 {
struct kvm_sev_cmd sev_cmd;
@@ -7711,6 +7778,8 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {

[Qemu-devel] [RFC PATCH v1 09/10] KVM: x86: Introduce KVM_GET_PAGE_ENC_BITMAP ioctl

2019-04-24 Thread Singh, Brijesh
The ioctl can be used to retrieve page encryption bitmap for a given
kvm memory slot.

Cc: Thomas Gleixner 
Cc: Ingo Molnar 
Cc: "H. Peter Anvin" 
Cc: Paolo Bonzini 
Cc: "Radim Krčmář" 
Cc: Joerg Roedel 
Cc: Borislav Petkov 
Cc: Tom Lendacky 
Cc: x...@kernel.org
Cc: k...@vger.kernel.org
Cc: linux-ker...@vger.kernel.org
Signed-off-by: Brijesh Singh 
---
 arch/x86/include/asm/kvm_host.h |  1 +
 arch/x86/kvm/svm.c  | 54 -
 arch/x86/kvm/x86.c  | 12 
 include/uapi/linux/kvm.h| 12 
 4 files changed, 78 insertions(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index adb0ca035b97..9947c4be825d 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1198,6 +1198,7 @@ struct kvm_x86_ops {
bool (*need_emulation_on_page_fault)(struct kvm_vcpu *vcpu);
int (*page_enc_status_hc)(struct kvm *kvm, unsigned long gpa,
  unsigned long sz, unsigned long mode);
+   int (*get_page_enc_bitmap)(struct kvm *kvm, struct kvm_page_enc_bitmap 
*bmap);
 };
 
 struct kvm_arch_async_pf {
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index f024f208b052..f386d72c929b 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -7437,6 +7437,57 @@ static int svm_page_enc_status_hc(struct kvm *kvm, 
unsigned long gpa,
return r;
 }
 
+static int svm_get_page_enc_bitmap(struct kvm *kvm,
+  struct kvm_page_enc_bitmap *bmap)
+{
+   struct kvm_sev_info *sev = _kvm_svm(kvm)->sev_info;
+   unsigned long gfn_start, gfn_end;
+   struct kvm_memory_slot *memslot;
+   struct kvm_memslots *slots;
+   unsigned long *bitmap;
+   unsigned long sz, i;
+   int ret, as_id, id;
+
+   if (!sev_guest(kvm))
+   return -ENOTTY;
+
+   as_id = bmap->slot >> 16;
+   id = (u16)bmap->slot;
+   if (as_id >= KVM_ADDRESS_SPACE_NUM || id >= KVM_USER_MEM_SLOTS)
+   return -EINVAL;
+
+   slots = __kvm_memslots(kvm, as_id);
+   memslot = id_to_memslot(slots, id);
+
+   gfn_start = memslot->base_gfn;
+   gfn_end = gfn_start + memslot->npages;
+
+   sz = ALIGN(memslot->npages, BITS_PER_LONG) / 8;
+   bitmap = kmalloc(sz, GFP_KERNEL);
+   if (!bitmap)
+   return -ENOMEM;
+
+   memset(bitmap, 0xff, sz); /* by default all pages are marked encrypted 
*/
+
+   mutex_lock(>lock);
+   if (sev->page_enc_bmap) {
+   i = gfn_start;
+   for_each_clear_bit_from(i, sev->page_enc_bmap,
+ min(sev->page_enc_bmap_size, gfn_end))
+   clear_bit(i - gfn_start, bitmap);
+   }
+   mutex_unlock(>lock);
+
+   ret = -EFAULT;
+   if (copy_to_user(bmap->enc_bitmap, bitmap, sz))
+   goto out;
+
+   ret = 0;
+out:
+   kfree(bitmap);
+   return ret;
+}
+
 static int svm_mem_enc_op(struct kvm *kvm, void __user *argp)
 {
struct kvm_sev_cmd sev_cmd;
@@ -7779,7 +7830,8 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
 
.need_emulation_on_page_fault = svm_need_emulation_on_page_fault,
 
-   .page_enc_status_hc = svm_page_enc_status_hc
+   .page_enc_status_hc = svm_page_enc_status_hc,
+   .get_page_enc_bitmap = svm_get_page_enc_bitmap
 };
 
 static int __init svm_init(void)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index dea644be5992..44079979b1c5 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4882,6 +4882,18 @@ long kvm_arch_vm_ioctl(struct file *filp,
r = kvm_vm_ioctl_hv_eventfd(kvm, );
break;
}
+   case KVM_GET_PAGE_ENC_BITMAP: {
+   struct kvm_page_enc_bitmap bitmap;
+
+   r = -EFAULT;
+   if (copy_from_user(, argp, sizeof(bitmap)))
+   goto out;
+
+   r = -ENOTTY;
+   if (kvm_x86_ops->get_page_enc_bitmap)
+   r = kvm_x86_ops->get_page_enc_bitmap(kvm, );
+   break;
+   }
default:
r = -ENOTTY;
}
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 07e058a3ec11..7f944d4e252c 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -492,6 +492,16 @@ struct kvm_dirty_log {
};
 };
 
+/* for KVM_GET_PAGE_ENC_BITMAP */
+struct kvm_page_enc_bitmap {
+   __u32 slot;
+   __u32 padding1;
+   union {
+   void __user *enc_bitmap; /* one bit per page */
+   __u64 padding2;
+   };
+};
+
 /* for KVM_CLEAR_DIRTY_LOG */
 struct kvm_clear_dirty_log {
__u32 slot;
@@ -1440,6 +1450,8 @@ struct kvm_enc_region {
 /* Available with KVM_CAP_HYPERV_CPUID */
 #define KVM_GET_SUPPORTED_HV_CPUID _IOWR(KVMIO, 0xc1, struct kvm_cpuid2)
 
+#define KVM_GET_PAGE_ENC_BITMAP_IOW(KVMIO, 0xc2, struct 

[Qemu-devel] [RFC PATCH v1 07/10] KVM: x86: Add AMD SEV specific Hypercall3

2019-04-24 Thread Singh, Brijesh
KVM hypercall framework relies on alternative framework to patch the
VMCALL -> VMMCALL on AMD platform. If a hypercall is made before
apply_alternative() is called then it defaults to VMCALL. The approach
works fine on non SEV guest. A VMCALL would causes #UD, and hypervisor
will be able to decode the instruction and do the right things. But
when SEV is active, guest memory is encrypted with guest key and
hypervisor will not be able to decode the instruction bytes.

Add SEV specific hypercall3, it unconditionally uses VMMCALL. The hypercall
will be used by the SEV guest to notify encrypted pages to the hypervisor.

Cc: Thomas Gleixner 
Cc: Ingo Molnar 
Cc: "H. Peter Anvin" 
Cc: Paolo Bonzini 
Cc: "Radim Krčmář" 
Cc: Joerg Roedel 
Cc: Borislav Petkov 
Cc: Tom Lendacky 
Cc: x...@kernel.org
Cc: k...@vger.kernel.org
Cc: linux-ker...@vger.kernel.org
Signed-off-by: Brijesh Singh 
---
 arch/x86/include/asm/kvm_para.h | 12 
 1 file changed, 12 insertions(+)

diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h
index 5ed3cf1c3934..94e91c0bc2e0 100644
--- a/arch/x86/include/asm/kvm_para.h
+++ b/arch/x86/include/asm/kvm_para.h
@@ -84,6 +84,18 @@ static inline long kvm_hypercall4(unsigned int nr, unsigned 
long p1,
return ret;
 }
 
+static inline long kvm_sev_hypercall3(unsigned int nr, unsigned long p1,
+ unsigned long p2, unsigned long p3)
+{
+   long ret;
+
+   asm volatile("vmmcall"
+: "=a"(ret)
+: "a"(nr), "b"(p1), "c"(p2), "d"(p3)
+: "memory");
+   return ret;
+}
+
 #ifdef CONFIG_KVM_GUEST
 bool kvm_para_available(void);
 unsigned int kvm_arch_para_features(void);
-- 
2.17.1



[Qemu-devel] [RFC PATCH v1 05/10] KVM: SVM: Add KVM_SEV_RECEIVE_UPDATE_DATA command

2019-04-24 Thread Singh, Brijesh
The command is used for copying the incoming buffer into the
SEV guest memory space.

Cc: Thomas Gleixner 
Cc: Ingo Molnar 
Cc: "H. Peter Anvin" 
Cc: Paolo Bonzini 
Cc: "Radim Krčmář" 
Cc: Joerg Roedel 
Cc: Borislav Petkov 
Cc: Tom Lendacky 
Cc: x...@kernel.org
Cc: k...@vger.kernel.org
Cc: linux-ker...@vger.kernel.org
Signed-off-by: Brijesh Singh 
---
 .../virtual/kvm/amd-memory-encryption.rst | 24 ++
 arch/x86/kvm/svm.c| 84 +++
 include/uapi/linux/kvm.h  |  9 ++
 3 files changed, 117 insertions(+)

diff --git a/Documentation/virtual/kvm/amd-memory-encryption.rst 
b/Documentation/virtual/kvm/amd-memory-encryption.rst
index acdff2454649..b9c3dc02f344 100644
--- a/Documentation/virtual/kvm/amd-memory-encryption.rst
+++ b/Documentation/virtual/kvm/amd-memory-encryption.rst
@@ -322,6 +322,30 @@ On success, the 'handle' field contains a new handle and 
on error, a negative va
 
 For more details, see SEV spec Section 6.12.
 
+14. KVM_SEV_RECEIVE_UPDATE_DATA
+
+
+The KVM_SEV_RECEIVE_UPDATE_DATA command can be used by the hypervisor to copy
+the incoming buffers into the guest memory region with encryption context
+created during the KVM_SEV_RECEIVE_START.
+
+Parameters (in): struct kvm_sev_receive_update_data
+
+Returns: 0 on success, -negative on error
+
+::
+
+struct kvm_sev_launch_receive_update_data {
+__u64 hdr_uaddr;/* userspace address containing the 
packet header */
+__u32 hdr_len;
+
+__u64 guest_uaddr;  /* the destination guest memory region 
*/
+__u32 guest_len;
+
+__u64 trans_uaddr;  /* the incoming buffer memory region  
*/
+__u32 trans_len;
+};
+
 References
 ==
 
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index a7dcf19baefb..c81cac09c5af 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -7269,6 +7269,87 @@ static int sev_receive_start(struct kvm *kvm, struct 
kvm_sev_cmd *argp)
return ret;
 }
 
+static int sev_receive_update_data(struct kvm *kvm, struct kvm_sev_cmd *argp)
+{
+   struct kvm_sev_info *sev = _kvm_svm(kvm)->sev_info;
+   struct kvm_sev_receive_update_data params;
+   struct sev_data_receive_update_data *data;
+   void *hdr = NULL, *trans = NULL;
+   struct page **guest_page;
+   unsigned long n;
+   int ret, offset;
+
+   if (!sev_guest(kvm))
+   return -EINVAL;
+
+   if (copy_from_user(, (void __user *)(uintptr_t)argp->data,
+   sizeof(struct kvm_sev_receive_update_data)))
+   return -EFAULT;
+
+   if (!params.hdr_uaddr || !params.hdr_len ||
+   !params.guest_uaddr || !params.guest_len ||
+   !params.trans_uaddr || !params.trans_len)
+   return -EINVAL;
+
+   /* Check if we are crossing the page boundry */
+   offset = params.guest_uaddr & (PAGE_SIZE - 1);
+   if ((params.guest_len + offset > PAGE_SIZE))
+   return -EINVAL;
+
+   data = kzalloc(sizeof(*data), GFP_KERNEL);
+   if (!data)
+   return -ENOMEM;
+
+   hdr = psp_copy_user_blob(params.hdr_uaddr, params.hdr_len);
+   if (IS_ERR(hdr)) {
+   ret = PTR_ERR(hdr);
+   goto e_free;
+   }
+
+   data->hdr_address = __psp_pa(hdr);
+   data->hdr_len = params.hdr_len;
+
+   trans = psp_copy_user_blob(params.trans_uaddr, params.trans_len);
+   if (IS_ERR(trans)) {
+   ret = PTR_ERR(trans);
+   goto e_free;
+   }
+
+   data->trans_address = __psp_pa(trans);
+   data->trans_len = params.trans_len;
+
+   /* Pin guest memory */
+   ret = -EFAULT;
+   guest_page = sev_pin_memory(kvm, params.guest_uaddr & PAGE_MASK,
+   PAGE_SIZE, , 0);
+   if (!guest_page)
+   goto e_free;
+
+   data->guest_address = __sme_page_pa(guest_page[0]) + offset;
+   data->guest_len = params.guest_len;
+
+   /*
+* The RECEIVE_UPDATE_DATA command requires C-bit to be always set.
+* The __sme_page_pa() takes care of setting the C-bit only when SME
+* is enabled on the host. But we need to set the C-bit regarless of
+* the SME state.
+*/
+   data->guest_address |= me_mask;
+
+   /* flush the caches to ensure that DRAM has recent contents */
+   sev_clflush_pages(guest_page, n);
+
+   data->handle = sev->handle;
+   ret = sev_issue_cmd(kvm, SEV_CMD_RECEIVE_UPDATE_DATA, data, 
>error);
+
+   sev_unpin_memory(kvm, guest_page, n);
+e_free:
+   kfree(data);
+   kfree(hdr);
+   kfree(trans);
+   return ret;
+}
+
 static int svm_mem_enc_op(struct kvm *kvm, void __user *argp)
 {
struct kvm_sev_cmd sev_cmd;
@@ -7322,6 +7403,9 @@ static int svm_mem_enc_op(struct kvm *kvm, void __user 
*argp)
case 

[Qemu-devel] [RFC PATCH v1 01/10] KVM: SVM: Add KVM_SEV SEND_START command

2019-04-24 Thread Singh, Brijesh
The command is used to create an outgoing SEV guest encryption context.

Cc: Thomas Gleixner 
Cc: Ingo Molnar 
Cc: "H. Peter Anvin" 
Cc: Paolo Bonzini 
Cc: "Radim Krčmář" 
Cc: Joerg Roedel 
Cc: Borislav Petkov 
Cc: Tom Lendacky 
Cc: x...@kernel.org
Cc: k...@vger.kernel.org
Cc: linux-ker...@vger.kernel.org
Signed-off-by: Brijesh Singh 
---
 .../virtual/kvm/amd-memory-encryption.rst |  24 +
 arch/x86/kvm/svm.c| 101 ++
 include/uapi/linux/kvm.h  |  12 +++
 3 files changed, 137 insertions(+)

diff --git a/Documentation/virtual/kvm/amd-memory-encryption.rst 
b/Documentation/virtual/kvm/amd-memory-encryption.rst
index 659bbc093b52..340ac4f87321 100644
--- a/Documentation/virtual/kvm/amd-memory-encryption.rst
+++ b/Documentation/virtual/kvm/amd-memory-encryption.rst
@@ -238,6 +238,30 @@ Returns: 0 on success, -negative on error
 __u32 trans_len;
 };
 
+10. KVM_SEV_SEND_START
+--
+
+The KVM_SEV_SEND_START command can be used by the hypervisor to create an
+outgoing guest encryption context.
+
+Parameters (in): struct kvm_sev_send_start
+
+Returns: 0 on success, -negative on error
+
+::
+struct kvm_sev_send_start {
+__u32 policy; /* guest policy */
+
+__u64 pdh_cert_uaddr; /* platform Diffie-Hellman 
certificate */
+__u32 pdh_cert_len;
+
+__u64 plat_cert_uaddr;/* platform certificate chain */
+__u32 plat_cert_len;
+
+__u64 amd_cert_uaddr; /* AMD certificate */
+__u32 amd_cert_len;
+};
+
 References
 ==
 
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 406b558abfef..4c2a225ba546 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -6955,6 +6955,104 @@ static int sev_launch_secret(struct kvm *kvm, struct 
kvm_sev_cmd *argp)
return ret;
 }
 
+static int sev_send_start(struct kvm *kvm, struct kvm_sev_cmd *argp)
+{
+   struct kvm_sev_info *sev = _kvm_svm(kvm)->sev_info;
+   void *amd_cert = NULL, *session_data = NULL;
+   void *pdh_cert = NULL, *plat_cert = NULL;
+   struct sev_data_send_start *data = NULL;
+   struct kvm_sev_send_start params;
+   int ret;
+
+   if (!sev_guest(kvm))
+   return -ENOTTY;
+
+   if (copy_from_user(, (void __user *)(uintptr_t)argp->data,
+   sizeof(struct kvm_sev_send_start)))
+   return -EFAULT;
+
+   data = kzalloc(sizeof(*data), GFP_KERNEL);
+   if (!data)
+   return -ENOMEM;
+
+   /* userspace wants to query the session length */
+   if (!params.session_len)
+   goto cmd;
+
+   if (!params.pdh_cert_uaddr || !params.pdh_cert_len ||
+   !params.session_uaddr)
+   return -EINVAL;
+
+   /* copy the certificate blobs from userspace */
+   pdh_cert = psp_copy_user_blob(params.pdh_cert_uaddr, 
params.pdh_cert_len);
+   if (IS_ERR(pdh_cert)) {
+   ret = PTR_ERR(pdh_cert);
+   goto e_free;
+   }
+
+   data->pdh_cert_address = __psp_pa(pdh_cert);
+   data->pdh_cert_len = params.pdh_cert_len;
+
+   plat_cert = psp_copy_user_blob(params.plat_cert_uaddr, 
params.plat_cert_len);
+   if (IS_ERR(plat_cert)) {
+   ret = PTR_ERR(plat_cert);
+   goto e_free_pdh;
+   }
+
+   data->plat_cert_address = __psp_pa(plat_cert);
+   data->plat_cert_len = params.plat_cert_len;
+
+   amd_cert = psp_copy_user_blob(params.amd_cert_uaddr, 
params.amd_cert_len);
+   if (IS_ERR(amd_cert)) {
+   ret = PTR_ERR(amd_cert);
+   goto e_free_plat_cert;
+   }
+
+   data->amd_cert_address = __psp_pa(amd_cert);
+   data->amd_cert_len = params.amd_cert_len;
+
+   ret = -ENOMEM;
+   session_data = kmalloc(params.session_len, GFP_KERNEL);
+   if (!session_data)
+   goto e_free_amd_cert;
+
+   data->session_address = __psp_pa(session_data);
+   data->session_len = params.session_len;
+cmd:
+   data->handle = sev->handle;
+   ret = sev_issue_cmd(kvm, SEV_CMD_SEND_START, data, >error);
+
+   /* if we queried the session length, FW responded with expected data */
+   if (!params.session_len)
+   goto done;
+
+   if (copy_to_user((void __user *)(uintptr_t) params.session_uaddr,
+   session_data, params.session_len)) {
+   ret = -EFAULT;
+   goto e_free_session;
+   }
+
+   params.policy = data->policy;
+
+done:
+   params.session_len = data->session_len;
+   if (copy_to_user((void __user *)(uintptr_t)argp->data, ,
+   sizeof(struct kvm_sev_send_start)))
+   ret = -EFAULT;
+
+e_free_session:
+   kfree(session_data);
+e_free_amd_cert:
+   kfree(amd_cert);
+e_free_plat_cert:
+  

  1   2   3   >