All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL v2 00/27] s390x updates (and friends)
@ 2018-03-01 12:58 Cornelia Huck
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 01/27] s390-ccw: refactor boot map table code Cornelia Huck
                   ` (21 more replies)
  0 siblings, 22 replies; 24+ messages in thread
From: Cornelia Huck @ 2018-03-01 12:58 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-s390x, qemu-devel, borntraeger, rth, agraf, david, thuth,
	Cornelia Huck

The following changes since commit 0a773d55ac76c5aa89ed9187a3bc5af8c5c2a6d0:

  maintainers: Add myself as a OpenBSD maintainer (2018-02-23 12:05:07 +0000)

are available in the git repository at:

  git://github.com/cohuck/qemu tags/s390x-20180301-v2

for you to fetch changes up to be8b49de2491145a7aad3201803327b6f568cbd3:

  s390x/tcg: fix loading 31bit PSWs with the highest bit set (2018-03-01 13:23:09 +0100)

----------------------------------------------------------------
- add query-cpus-fast and deprecate query-cpus, while adding s390 cpu
  information
- remove s390x memory hotplug implementation, which is not useable in
  this form
- add boot menu support in the s390-ccw bios
- expose s390x guest crash information
- fixes and cleaups

----------------------------------------------------------------

Christian Borntraeger (1):
  s390x/cpu: expose the guest crash information

Collin L. Walling (13):
  s390-ccw: refactor boot map table code
  s390-ccw: refactor eckd_block_num to use CHS
  s390-ccw: refactor IPL structs
  s390-ccw: update libc
  s390-ccw: move auxiliary IPL data to separate location
  s390-ccw: parse and set boot menu options
  s390-ccw: set up interactive boot menu parameters
  s390-ccw: read stage2 boot loader data to find menu
  s390-ccw: print zipl boot menu
  s390-ccw: read user input for boot index via the SCLP console
  s390-ccw: set cp_receive mask only when needed and consume pending
    service irqs
  s390-ccw: use zipl values when no boot menu options are present
  s390-ccw: interactive boot menu for scsi

Cornelia Huck (1):
  s390x: remove s390_get_memslot_count

David Hildenbrand (4):
  s390x/tcg: fix disabling/enabling DAT
  s390x/tcg: add various alignment checks
  s390x/sclp: remove memory hotplug support
  s390x/tcg: fix loading 31bit PSWs with the highest bit set

Dr. David Alan Gilbert (1):
  s390/stattrib: Make SaveVMHandlers data static

Halil Pasic (1):
  s390x/cpumodel: document S390FeatDef.bit not applicable

Luiz Capitulino (1):
  qmp: add query-cpus-fast

Thomas Huth (1):
  pc-bios/s390: Rebuild the s390x firmware images with the boot menu
    changes

Viktor Mihajlovski (4):
  qmp: expose s390-specific CPU info
  qmp: add architecture specific cpu data for query-cpus-fast
  qemu-doc: deprecate query-cpus
  hmp: change hmp_info_cpus to use query-cpus-fast

-- 
2.13.6

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [Qemu-devel] [PULL v2 01/27] s390-ccw: refactor boot map table code
  2018-03-01 12:58 [Qemu-devel] [PULL v2 00/27] s390x updates (and friends) Cornelia Huck
@ 2018-03-01 12:58 ` Cornelia Huck
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 02/27] s390-ccw: refactor eckd_block_num to use CHS Cornelia Huck
                   ` (20 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: Cornelia Huck @ 2018-03-01 12:58 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-s390x, qemu-devel, borntraeger, rth, agraf, david, thuth,
	Collin L. Walling

From: "Collin L. Walling" <walling@linux.vnet.ibm.com>

Some ECKD bootmap code was using structs designed for SCSI.
Even though this works, it confuses readability. Add a new
BootMapTable struct to assist with readability in bootmap
entry code. Also:

- replace ScsiMbr in ECKD code with appropriate structs
- fix read_block messages to reflect BootMapTable
- fixup ipl_scsi to use BootMapTable (referred to as Program Table)
- defined value for maximum table entries

Signed-off-by: Collin L. Walling <walling@linux.vnet.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 pc-bios/s390-ccw/bootmap.c | 60 +++++++++++++++++++++-------------------------
 pc-bios/s390-ccw/bootmap.h | 11 ++++++++-
 2 files changed, 37 insertions(+), 34 deletions(-)

diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c
index 67a6123ed4..a4eaf24c8d 100644
--- a/pc-bios/s390-ccw/bootmap.c
+++ b/pc-bios/s390-ccw/bootmap.c
@@ -182,24 +182,24 @@ static block_number_t load_eckd_segments(block_number_t blk, uint64_t *address)
     return block_nr;
 }
 
-static void run_eckd_boot_script(block_number_t mbr_block_nr)
+static void run_eckd_boot_script(block_number_t bmt_block_nr)
 {
     int i;
     unsigned int loadparm = get_loadparm_index();
     block_number_t block_nr;
     uint64_t address;
-    ScsiMbr *bte = (void *)sec; /* Eckd bootmap table entry */
+    BootMapTable *bmt = (void *)sec;
     BootMapScript *bms = (void *)sec;
 
     debug_print_int("loadparm", loadparm);
-    IPL_assert(loadparm < 31, "loadparm value greater than"
+    IPL_assert(loadparm <= MAX_TABLE_ENTRIES, "loadparm value greater than"
                " maximum number of boot entries allowed");
 
     memset(sec, FREE_SPACE_FILLER, sizeof(sec));
-    read_block(mbr_block_nr, sec, "Cannot read MBR");
+    read_block(bmt_block_nr, sec, "Cannot read Boot Map Table");
 
-    block_nr = eckd_block_num((void *)&(bte->blockptr[loadparm]));
-    IPL_assert(block_nr != -1, "No Boot Map");
+    block_nr = eckd_block_num(&bmt->entry[loadparm]);
+    IPL_assert(block_nr != -1, "Cannot find Boot Map Table Entry");
 
     memset(sec, FREE_SPACE_FILLER, sizeof(sec));
     read_block(block_nr, sec, "Cannot read Boot Map Script");
@@ -223,7 +223,7 @@ static void ipl_eckd_cdl(void)
     XEckdMbr *mbr;
     Ipl2 *ipl2 = (void *)sec;
     IplVolumeLabel *vlbl = (void *)sec;
-    block_number_t block_nr;
+    block_number_t bmt_block_nr;
 
     /* we have just read the block #0 and recognized it as "IPL1" */
     sclp_print("CDL\n");
@@ -238,8 +238,8 @@ static void ipl_eckd_cdl(void)
     IPL_assert(mbr->dev_type == DEV_TYPE_ECKD,
                "Non-ECKD device type in zIPL section of IPL2 record.");
 
-    /* save pointer to Boot Script */
-    block_nr = eckd_block_num((void *)&(mbr->blockptr));
+    /* save pointer to Boot Map Table */
+    bmt_block_nr = eckd_block_num(&mbr->blockptr);
 
     memset(sec, FREE_SPACE_FILLER, sizeof(sec));
     read_block(2, vlbl, "Cannot read Volume Label at block 2");
@@ -249,7 +249,7 @@ static void ipl_eckd_cdl(void)
                "Invalid magic of volser block");
     print_volser(vlbl->f.volser);
 
-    run_eckd_boot_script(block_nr);
+    run_eckd_boot_script(bmt_block_nr);
     /* no return */
 }
 
@@ -280,7 +280,7 @@ static void print_eckd_ldl_msg(ECKD_IPL_mode_t mode)
 
 static void ipl_eckd_ldl(ECKD_IPL_mode_t mode)
 {
-    block_number_t block_nr;
+    block_number_t bmt_block_nr;
     BootInfo *bip = (void *)(sec + 0x70); /* BootInfo is MBR for LDL */
 
     if (mode != ECKD_LDL_UNLABELED) {
@@ -299,8 +299,10 @@ static void ipl_eckd_ldl(ECKD_IPL_mode_t mode)
     }
     verify_boot_info(bip);
 
-    block_nr = eckd_block_num((void *)&(bip->bp.ipl.bm_ptr.eckd.bptr));
-    run_eckd_boot_script(block_nr);
+    /* save pointer to Boot Map Table */
+    bmt_block_nr = eckd_block_num((void *)&bip->bp.ipl.bm_ptr.eckd.bptr);
+
+    run_eckd_boot_script(bmt_block_nr);
     /* no return */
 }
 
@@ -325,7 +327,7 @@ static void print_eckd_msg(void)
 
 static void ipl_eckd(void)
 {
-    ScsiMbr *mbr = (void *)sec;
+    XEckdMbr *mbr = (void *)sec;
     LDL_VTOC *vlbl = (void *)sec;
 
     print_eckd_msg();
@@ -449,10 +451,8 @@ static void zipl_run(ScsiBlockPtr *pte)
 static void ipl_scsi(void)
 {
     ScsiMbr *mbr = (void *)sec;
-    uint8_t *ns, *ns_end;
     int program_table_entries = 0;
-    const int pte_len = sizeof(ScsiBlockPtr);
-    ScsiBlockPtr *prog_table_entry = NULL;
+    BootMapTable *prog_table = (void *)sec;
     unsigned int loadparm = get_loadparm_index();
 
     /* Grab the MBR */
@@ -467,34 +467,28 @@ static void ipl_scsi(void)
     debug_print_int("MBR Version", mbr->version_id);
     IPL_check(mbr->version_id == 1,
               "Unknown MBR layout version, assuming version 1");
-    debug_print_int("program table", mbr->blockptr[0].blockno);
-    IPL_assert(mbr->blockptr[0].blockno, "No Program Table");
+    debug_print_int("program table", mbr->pt.blockno);
+    IPL_assert(mbr->pt.blockno, "No Program Table");
 
     /* Parse the program table */
-    read_block(mbr->blockptr[0].blockno, sec,
-               "Error reading Program Table");
-
+    read_block(mbr->pt.blockno, sec, "Error reading Program Table");
     IPL_assert(magic_match(sec, ZIPL_MAGIC), "No zIPL magic in PT");
 
-    debug_print_int("loadparm index", loadparm);
-    ns_end = sec + virtio_get_block_size();
-    for (ns = (sec + pte_len); (ns + pte_len) < ns_end; ns += pte_len) {
-        prog_table_entry = (ScsiBlockPtr *)ns;
-        if (!prog_table_entry->blockno) {
+    while (program_table_entries <= MAX_TABLE_ENTRIES) {
+        if (!prog_table->entry[program_table_entries].scsi.blockno) {
             break;
         }
-
         program_table_entries++;
-        if (program_table_entries == loadparm + 1) {
-            break; /* selected entry found */
-        }
     }
 
     debug_print_int("program table entries", program_table_entries);
-
     IPL_assert(program_table_entries != 0, "Empty Program Table");
 
-    zipl_run(prog_table_entry); /* no return */
+    debug_print_int("loadparm", loadparm);
+    IPL_assert(loadparm <= MAX_TABLE_ENTRIES, "loadparm value greater than"
+               " maximum number of boot entries allowed");
+
+    zipl_run(&prog_table->entry[loadparm].scsi); /* no return */
 }
 
 /***********************************************************************
diff --git a/pc-bios/s390-ccw/bootmap.h b/pc-bios/s390-ccw/bootmap.h
index cf99a4c728..486c0f34f1 100644
--- a/pc-bios/s390-ccw/bootmap.h
+++ b/pc-bios/s390-ccw/bootmap.h
@@ -53,6 +53,15 @@ typedef union BootMapPointer {
     ExtEckdBlockPtr xeckd;
 } __attribute__ ((packed)) BootMapPointer;
 
+#define MAX_TABLE_ENTRIES  30
+
+/* aka Program Table */
+typedef struct BootMapTable {
+    uint8_t magic[4];
+    uint8_t reserved[12];
+    BootMapPointer entry[];
+} __attribute__ ((packed)) BootMapTable;
+
 typedef struct ComponentEntry {
     ScsiBlockPtr data;
     uint8_t pad[7];
@@ -70,7 +79,7 @@ typedef struct ScsiMbr {
     uint8_t magic[4];
     uint32_t version_id;
     uint8_t reserved[8];
-    ScsiBlockPtr blockptr[];
+    ScsiBlockPtr pt;   /* block pointer to program table */
 } __attribute__ ((packed)) ScsiMbr;
 
 #define ZIPL_MAGIC              "zIPL"
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [Qemu-devel] [PULL v2 02/27] s390-ccw: refactor eckd_block_num to use CHS
  2018-03-01 12:58 [Qemu-devel] [PULL v2 00/27] s390x updates (and friends) Cornelia Huck
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 01/27] s390-ccw: refactor boot map table code Cornelia Huck
@ 2018-03-01 12:58 ` Cornelia Huck
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 03/27] s390-ccw: refactor IPL structs Cornelia Huck
                   ` (19 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: Cornelia Huck @ 2018-03-01 12:58 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-s390x, qemu-devel, borntraeger, rth, agraf, david, thuth,
	Collin L. Walling

From: "Collin L. Walling" <walling@linux.vnet.ibm.com>

Add new cylinder/head/sector struct. Use it to calculate
eckd block numbers instead of a BootMapPointer (which used
eckd chs anyway).

Signed-off-by: Collin L. Walling <walling@linux.vnet.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 pc-bios/s390-ccw/bootmap.c | 28 ++++++++++++++--------------
 pc-bios/s390-ccw/bootmap.h |  8 ++++++--
 2 files changed, 20 insertions(+), 16 deletions(-)

diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c
index a4eaf24c8d..9534f56060 100644
--- a/pc-bios/s390-ccw/bootmap.c
+++ b/pc-bios/s390-ccw/bootmap.c
@@ -95,32 +95,32 @@ static inline void verify_boot_info(BootInfo *bip)
                "Bad block size in zIPL section of the 1st record.");
 }
 
-static block_number_t eckd_block_num(BootMapPointer *p)
+static block_number_t eckd_block_num(EckdCHS *chs)
 {
     const uint64_t sectors = virtio_get_sectors();
     const uint64_t heads = virtio_get_heads();
-    const uint64_t cylinder = p->eckd.cylinder
-                            + ((p->eckd.head & 0xfff0) << 12);
-    const uint64_t head = p->eckd.head & 0x000f;
+    const uint64_t cylinder = chs->cylinder
+                            + ((chs->head & 0xfff0) << 12);
+    const uint64_t head = chs->head & 0x000f;
     const block_number_t block = sectors * heads * cylinder
                                + sectors * head
-                               + p->eckd.sector
+                               + chs->sector
                                - 1; /* block nr starts with zero */
     return block;
 }
 
 static bool eckd_valid_address(BootMapPointer *p)
 {
-    const uint64_t head = p->eckd.head & 0x000f;
+    const uint64_t head = p->eckd.chs.head & 0x000f;
 
     if (head >= virtio_get_heads()
-        ||  p->eckd.sector > virtio_get_sectors()
-        ||  p->eckd.sector <= 0) {
+        ||  p->eckd.chs.sector > virtio_get_sectors()
+        ||  p->eckd.chs.sector <= 0) {
         return false;
     }
 
     if (!virtio_guessed_disk_nature() &&
-        eckd_block_num(p) >= virtio_get_blocks()) {
+        eckd_block_num(&p->eckd.chs) >= virtio_get_blocks()) {
         return false;
     }
 
@@ -140,7 +140,7 @@ static block_number_t load_eckd_segments(block_number_t blk, uint64_t *address)
     do {
         more_data = false;
         for (j = 0;; j++) {
-            block_nr = eckd_block_num((void *)&(bprs[j].xeckd));
+            block_nr = eckd_block_num(&bprs[j].xeckd.bptr.chs);
             if (is_null_block_number(block_nr)) { /* end of chunk */
                 break;
             }
@@ -198,7 +198,7 @@ static void run_eckd_boot_script(block_number_t bmt_block_nr)
     memset(sec, FREE_SPACE_FILLER, sizeof(sec));
     read_block(bmt_block_nr, sec, "Cannot read Boot Map Table");
 
-    block_nr = eckd_block_num(&bmt->entry[loadparm]);
+    block_nr = eckd_block_num(&bmt->entry[loadparm].xeckd.bptr.chs);
     IPL_assert(block_nr != -1, "Cannot find Boot Map Table Entry");
 
     memset(sec, FREE_SPACE_FILLER, sizeof(sec));
@@ -206,7 +206,7 @@ static void run_eckd_boot_script(block_number_t bmt_block_nr)
 
     for (i = 0; bms->entry[i].type == BOOT_SCRIPT_LOAD; i++) {
         address = bms->entry[i].address.load_address;
-        block_nr = eckd_block_num(&(bms->entry[i].blkptr));
+        block_nr = eckd_block_num(&bms->entry[i].blkptr.xeckd.bptr.chs);
 
         do {
             block_nr = load_eckd_segments(block_nr, &address);
@@ -239,7 +239,7 @@ static void ipl_eckd_cdl(void)
                "Non-ECKD device type in zIPL section of IPL2 record.");
 
     /* save pointer to Boot Map Table */
-    bmt_block_nr = eckd_block_num(&mbr->blockptr);
+    bmt_block_nr = eckd_block_num(&mbr->blockptr.xeckd.bptr.chs);
 
     memset(sec, FREE_SPACE_FILLER, sizeof(sec));
     read_block(2, vlbl, "Cannot read Volume Label at block 2");
@@ -300,7 +300,7 @@ static void ipl_eckd_ldl(ECKD_IPL_mode_t mode)
     verify_boot_info(bip);
 
     /* save pointer to Boot Map Table */
-    bmt_block_nr = eckd_block_num((void *)&bip->bp.ipl.bm_ptr.eckd.bptr);
+    bmt_block_nr = eckd_block_num(&bip->bp.ipl.bm_ptr.eckd.bptr.chs);
 
     run_eckd_boot_script(bmt_block_nr);
     /* no return */
diff --git a/pc-bios/s390-ccw/bootmap.h b/pc-bios/s390-ccw/bootmap.h
index 486c0f34f1..b361084073 100644
--- a/pc-bios/s390-ccw/bootmap.h
+++ b/pc-bios/s390-ccw/bootmap.h
@@ -32,10 +32,14 @@ typedef struct FbaBlockPtr {
     uint16_t blockct;
 } __attribute__ ((packed)) FbaBlockPtr;
 
-typedef struct EckdBlockPtr {
-    uint16_t cylinder; /* cylinder/head/sector is an address of the block */
+typedef struct EckdCHS {
+    uint16_t cylinder;
     uint16_t head;
     uint8_t sector;
+} __attribute__ ((packed)) EckdCHS;
+
+typedef struct EckdBlockPtr {
+    EckdCHS chs; /* cylinder/head/sector is an address of the block */
     uint16_t size;
     uint8_t count; /* (size_in_blocks-1);
                     * it's 0 for TablePtr, ScriptPtr, and SectionPtr */
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [Qemu-devel] [PULL v2 03/27] s390-ccw: refactor IPL structs
  2018-03-01 12:58 [Qemu-devel] [PULL v2 00/27] s390x updates (and friends) Cornelia Huck
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 01/27] s390-ccw: refactor boot map table code Cornelia Huck
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 02/27] s390-ccw: refactor eckd_block_num to use CHS Cornelia Huck
@ 2018-03-01 12:58 ` Cornelia Huck
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 04/27] s390-ccw: update libc Cornelia Huck
                   ` (18 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: Cornelia Huck @ 2018-03-01 12:58 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-s390x, qemu-devel, borntraeger, rth, agraf, david, thuth,
	Collin L. Walling

From: "Collin L. Walling" <walling@linux.vnet.ibm.com>

ECKD DASDs have different IPL structures for CDL and LDL
formats. The current Ipl1 and Ipl2 structs follow the CDL
format, so we prepend "EckdCdl" to them. Boot info for LDL
has been moved to a new struct: EckdLdlIpl1.

Signed-off-by: Collin L. Walling <walling@linux.vnet.ibm.com>
Acked-by: Janosch Frank <frankja@linux.vnet.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 pc-bios/s390-ccw/bootmap.c | 12 ++++++------
 pc-bios/s390-ccw/bootmap.h | 37 +++++++++++++++++++++----------------
 2 files changed, 27 insertions(+), 22 deletions(-)

diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c
index 9534f56060..a94638db2c 100644
--- a/pc-bios/s390-ccw/bootmap.c
+++ b/pc-bios/s390-ccw/bootmap.c
@@ -221,7 +221,7 @@ static void run_eckd_boot_script(block_number_t bmt_block_nr)
 static void ipl_eckd_cdl(void)
 {
     XEckdMbr *mbr;
-    Ipl2 *ipl2 = (void *)sec;
+    EckdCdlIpl2 *ipl2 = (void *)sec;
     IplVolumeLabel *vlbl = (void *)sec;
     block_number_t bmt_block_nr;
 
@@ -231,7 +231,7 @@ static void ipl_eckd_cdl(void)
     memset(sec, FREE_SPACE_FILLER, sizeof(sec));
     read_block(1, ipl2, "Cannot read IPL2 record at block 1");
 
-    mbr = &ipl2->u.x.mbr;
+    mbr = &ipl2->mbr;
     IPL_assert(magic_match(mbr, ZIPL_MAGIC), "No zIPL section in IPL2 record.");
     IPL_assert(block_size_ok(mbr->blockptr.xeckd.bptr.size),
                "Bad block size in zIPL section of IPL2 record.");
@@ -281,7 +281,7 @@ static void print_eckd_ldl_msg(ECKD_IPL_mode_t mode)
 static void ipl_eckd_ldl(ECKD_IPL_mode_t mode)
 {
     block_number_t bmt_block_nr;
-    BootInfo *bip = (void *)(sec + 0x70); /* BootInfo is MBR for LDL */
+    EckdLdlIpl1 *ipl1 = (void *)sec;
 
     if (mode != ECKD_LDL_UNLABELED) {
         print_eckd_ldl_msg(mode);
@@ -292,15 +292,15 @@ static void ipl_eckd_ldl(ECKD_IPL_mode_t mode)
     memset(sec, FREE_SPACE_FILLER, sizeof(sec));
     read_block(0, sec, "Cannot read block 0 to grab boot info.");
     if (mode == ECKD_LDL_UNLABELED) {
-        if (!magic_match(bip->magic, ZIPL_MAGIC)) {
+        if (!magic_match(ipl1->bip.magic, ZIPL_MAGIC)) {
             return; /* not applicable layout */
         }
         sclp_print("unlabeled LDL.\n");
     }
-    verify_boot_info(bip);
+    verify_boot_info(&ipl1->bip);
 
     /* save pointer to Boot Map Table */
-    bmt_block_nr = eckd_block_num(&bip->bp.ipl.bm_ptr.eckd.bptr.chs);
+    bmt_block_nr = eckd_block_num(&ipl1->bip.bp.ipl.bm_ptr.eckd.bptr.chs);
 
     run_eckd_boot_script(bmt_block_nr);
     /* no return */
diff --git a/pc-bios/s390-ccw/bootmap.h b/pc-bios/s390-ccw/bootmap.h
index b361084073..4bd95cd4d2 100644
--- a/pc-bios/s390-ccw/bootmap.h
+++ b/pc-bios/s390-ccw/bootmap.h
@@ -239,22 +239,27 @@ typedef struct BootInfo {          /* @ 0x70, record #0    */
     } bp;
 } __attribute__ ((packed)) BootInfo; /* see also XEckdMbr   */
 
-typedef struct Ipl1 {
-    unsigned char key[4]; /* == "IPL1" */
-    unsigned char data[24];
-} __attribute__((packed)) Ipl1;
-
-typedef struct Ipl2 {
-    unsigned char key[4]; /* == "IPL2" */
-    union {
-        unsigned char data[144];
-        struct {
-            unsigned char reserved1[92-4];
-            XEckdMbr mbr;
-            unsigned char reserved2[144-(92-4)-sizeof(XEckdMbr)];
-        } x;
-    } u;
-} __attribute__((packed)) Ipl2;
+/*
+ * Structs for IPL
+ */
+#define STAGE2_BLK_CNT_MAX  24 /* Stage 1b can load up to 24 blocks */
+
+typedef struct EckdCdlIpl1 {
+    uint8_t key[4]; /* == "IPL1" */
+    uint8_t data[24];
+} __attribute__((packed)) EckdCdlIpl1;
+
+typedef struct EckdCdlIpl2 {
+    uint8_t key[4]; /* == "IPL2" */
+    uint8_t reserved0[88];
+    XEckdMbr mbr;
+    uint8_t reserved[24];
+} __attribute__((packed)) EckdCdlIpl2;
+
+typedef struct EckdLdlIpl1 {
+    uint8_t reserved[112];
+    BootInfo bip; /* BootInfo is MBR for LDL */
+} __attribute__((packed)) EckdLdlIpl1;
 
 typedef struct IplVolumeLabel {
     unsigned char key[4]; /* == "VOL1" */
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [Qemu-devel] [PULL v2 04/27] s390-ccw: update libc
  2018-03-01 12:58 [Qemu-devel] [PULL v2 00/27] s390x updates (and friends) Cornelia Huck
                   ` (2 preceding siblings ...)
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 03/27] s390-ccw: refactor IPL structs Cornelia Huck
@ 2018-03-01 12:58 ` Cornelia Huck
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 05/27] s390-ccw: move auxiliary IPL data to separate location Cornelia Huck
                   ` (17 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: Cornelia Huck @ 2018-03-01 12:58 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-s390x, qemu-devel, borntraeger, rth, agraf, david, thuth,
	Collin L. Walling

From: "Collin L. Walling" <walling@linux.vnet.ibm.com>

Moved:
  memcmp from bootmap.h to libc.h (renamed from _memcmp)
  strlen from sclp.c to libc.h (renamed from _strlen)

Added C standard functions:
  isdigit

Added non C-standard function:
  uitoa
  atoui

Signed-off-by: Collin L. Walling <walling@linux.vnet.ibm.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Reviewed-by: Janosch Frank <frankja@linux.vnet.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 pc-bios/s390-ccw/Makefile  |  2 +-
 pc-bios/s390-ccw/bootmap.c |  4 +--
 pc-bios/s390-ccw/bootmap.h | 16 +--------
 pc-bios/s390-ccw/libc.c    | 88 ++++++++++++++++++++++++++++++++++++++++++++++
 pc-bios/s390-ccw/libc.h    | 37 +++++++++++++++++--
 pc-bios/s390-ccw/main.c    | 17 +--------
 pc-bios/s390-ccw/sclp.c    | 10 +-----
 7 files changed, 129 insertions(+), 45 deletions(-)
 create mode 100644 pc-bios/s390-ccw/libc.c

diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile
index 6d0c2ee691..9f7904fc20 100644
--- a/pc-bios/s390-ccw/Makefile
+++ b/pc-bios/s390-ccw/Makefile
@@ -9,7 +9,7 @@ $(call set-vpath, $(SRC_PATH)/pc-bios/s390-ccw)
 
 .PHONY : all clean build-all
 
-OBJECTS = start.o main.o bootmap.o sclp.o virtio.o virtio-scsi.o virtio-blkdev.o
+OBJECTS = start.o main.o bootmap.o sclp.o virtio.o virtio-scsi.o virtio-blkdev.o libc.o
 QEMU_CFLAGS := $(filter -W%, $(QEMU_CFLAGS))
 QEMU_CFLAGS += -ffreestanding -fno-delete-null-pointer-checks -msoft-float
 QEMU_CFLAGS += -march=z900 -fPIE -fno-strict-aliasing
diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c
index a94638db2c..092fb355fe 100644
--- a/pc-bios/s390-ccw/bootmap.c
+++ b/pc-bios/s390-ccw/bootmap.c
@@ -506,7 +506,7 @@ static bool is_iso_bc_entry_compatible(IsoBcSection *s)
                     "Failed to read image sector 0");
 
     /* Checking bytes 8 - 32 for S390 Linux magic */
-    return !_memcmp(magic_sec + 8, linux_s390_magic, 24);
+    return !memcmp(magic_sec + 8, linux_s390_magic, 24);
 }
 
 /* Location of the current sector of the directory */
@@ -635,7 +635,7 @@ static uint32_t find_iso_bc(void)
         if (vd->type == VOL_DESC_TYPE_BOOT) {
             IsoVdElTorito *et = &vd->vd.boot;
 
-            if (!_memcmp(&et->el_torito[0], el_torito_magic, 32)) {
+            if (!memcmp(&et->el_torito[0], el_torito_magic, 32)) {
                 return bswap32(et->bc_offset);
             }
         }
diff --git a/pc-bios/s390-ccw/bootmap.h b/pc-bios/s390-ccw/bootmap.h
index 4bd95cd4d2..4cf7e1e463 100644
--- a/pc-bios/s390-ccw/bootmap.h
+++ b/pc-bios/s390-ccw/bootmap.h
@@ -328,20 +328,6 @@ static inline bool magic_match(const void *data, const void *magic)
     return *((uint32_t *)data) == *((uint32_t *)magic);
 }
 
-static inline int _memcmp(const void *s1, const void *s2, size_t n)
-{
-    int i;
-    const uint8_t *p1 = s1, *p2 = s2;
-
-    for (i = 0; i < n; i++) {
-        if (p1[i] != p2[i]) {
-            return p1[i] > p2[i] ? 1 : -1;
-        }
-    }
-
-    return 0;
-}
-
 static inline uint32_t iso_733_to_u32(uint64_t x)
 {
     return (uint32_t)x;
@@ -434,7 +420,7 @@ const uint8_t vol_desc_magic[] = "CD001";
 
 static inline bool is_iso_vd_valid(IsoVolDesc *vd)
 {
-    return !_memcmp(&vd->ident[0], vol_desc_magic, 5) &&
+    return !memcmp(&vd->ident[0], vol_desc_magic, 5) &&
            vd->version == 0x1 &&
            vd->type <= VOL_DESC_TYPE_PARTITION;
 }
diff --git a/pc-bios/s390-ccw/libc.c b/pc-bios/s390-ccw/libc.c
new file mode 100644
index 0000000000..38ea77d7aa
--- /dev/null
+++ b/pc-bios/s390-ccw/libc.c
@@ -0,0 +1,88 @@
+/*
+ * libc-style definitions and functions
+ *
+ * Copyright 2018 IBM Corp.
+ * Author(s): Collin L. Walling <walling@linux.vnet.ibm.com>
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include "libc.h"
+#include "s390-ccw.h"
+
+/**
+ * atoui:
+ * @str: the string to be converted.
+ *
+ * Given a string @str, convert it to an integer. Leading spaces are
+ * ignored. Any other non-numerical value will terminate the conversion
+ * and return 0. This function only handles numbers between 0 and
+ * UINT64_MAX inclusive.
+ *
+ * Returns: an integer converted from the string @str, or the number 0
+ * if an error occurred.
+ */
+uint64_t atoui(const char *str)
+{
+    int val = 0;
+
+    if (!str || !str[0]) {
+        return 0;
+    }
+
+    while (*str == ' ') {
+        str++;
+    }
+
+    while (*str) {
+        if (!isdigit(*str)) {
+            break;
+        }
+        val = val * 10 + *str - '0';
+        str++;
+    }
+
+    return val;
+}
+
+/**
+ * uitoa:
+ * @num: an integer (base 10) to be converted.
+ * @str: a pointer to a string to store the conversion.
+ * @len: the length of the passed string.
+ *
+ * Given an integer @num, convert it to a string. The string @str must be
+ * allocated beforehand. The resulting string will be null terminated and
+ * returned. This function only handles numbers between 0 and UINT64_MAX
+ * inclusive.
+ *
+ * Returns: the string @str of the converted integer @num
+ */
+char *uitoa(uint64_t num, char *str, size_t len)
+{
+    size_t num_idx = 1; /* account for NUL */
+    uint64_t tmp = num;
+
+    IPL_assert(str != NULL, "uitoa: no space allocated to store string");
+
+    /* Count indices of num */
+    while ((tmp /= 10) != 0) {
+        num_idx++;
+    }
+
+    /* Check if we have enough space for num and NUL */
+    IPL_assert(len > num_idx, "uitoa: array too small for conversion");
+
+    str[num_idx--] = '\0';
+
+    /* Convert int to string */
+    while (num_idx >= 0) {
+        str[num_idx--] = num % 10 + '0';
+        num /= 10;
+    }
+
+    return str;
+}
diff --git a/pc-bios/s390-ccw/libc.h b/pc-bios/s390-ccw/libc.h
index 0142ea8e7b..63ece70c6b 100644
--- a/pc-bios/s390-ccw/libc.h
+++ b/pc-bios/s390-ccw/libc.h
@@ -1,6 +1,8 @@
 /*
  * libc-style definitions and functions
  *
+ * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
+ *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
  * Free Software Foundation; either version 2 of the License, or (at your
@@ -19,7 +21,7 @@ typedef unsigned long long uint64_t;
 
 static inline void *memset(void *s, int c, size_t n)
 {
-    int i;
+    size_t i;
     unsigned char *p = s;
 
     for (i = 0; i < n; i++) {
@@ -33,7 +35,7 @@ static inline void *memcpy(void *s1, const void *s2, size_t n)
 {
     uint8_t *dest = s1;
     const uint8_t *src = s2;
-    int i;
+    size_t i;
 
     for (i = 0; i < n; i++) {
         dest[i] = src[i];
@@ -42,4 +44,35 @@ static inline void *memcpy(void *s1, const void *s2, size_t n)
     return s1;
 }
 
+static inline int memcmp(const void *s1, const void *s2, size_t n)
+{
+    size_t i;
+    const uint8_t *p1 = s1, *p2 = s2;
+
+    for (i = 0; i < n; i++) {
+        if (p1[i] != p2[i]) {
+            return p1[i] > p2[i] ? 1 : -1;
+        }
+    }
+
+    return 0;
+}
+
+static inline size_t strlen(const char *str)
+{
+    size_t i;
+    for (i = 0; *str; i++) {
+        str++;
+    }
+    return i;
+}
+
+static inline int isdigit(int c)
+{
+    return (c >= '0') && (c <= '9');
+}
+
+uint64_t atoui(const char *str);
+char *uitoa(uint64_t num, char *str, size_t len);
+
 #endif
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index 401e9dbb5f..e857ce4f60 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -40,22 +40,7 @@ void panic(const char *string)
 
 unsigned int get_loadparm_index(void)
 {
-    const char *lp = loadparm;
-    int i;
-    unsigned int idx = 0;
-
-    for (i = 0; i < 8; i++) {
-        char c = lp[i];
-
-        if (c < '0' || c > '9') {
-            break;
-        }
-
-        idx *= 10;
-        idx += c - '0';
-    }
-
-    return idx;
+    return atoui(loadparm);
 }
 
 static bool find_dev(Schib *schib, int dev_no)
diff --git a/pc-bios/s390-ccw/sclp.c b/pc-bios/s390-ccw/sclp.c
index 90d1bc3147..e6a089889a 100644
--- a/pc-bios/s390-ccw/sclp.c
+++ b/pc-bios/s390-ccw/sclp.c
@@ -65,14 +65,6 @@ void sclp_setup(void)
     sclp_set_write_mask();
 }
 
-static int _strlen(const char *str)
-{
-    int i;
-    for (i = 0; *str; i++)
-        str++;
-    return i;
-}
-
 long write(int fd, const void *str, size_t len)
 {
     WriteEventData *sccb = (void *)_sccb;
@@ -113,7 +105,7 @@ long write(int fd, const void *str, size_t len)
 
 void sclp_print(const char *str)
 {
-    write(1, str, _strlen(str));
+    write(1, str, strlen(str));
 }
 
 void sclp_get_loadparm_ascii(char *loadparm)
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [Qemu-devel] [PULL v2 05/27] s390-ccw: move auxiliary IPL data to separate location
  2018-03-01 12:58 [Qemu-devel] [PULL v2 00/27] s390x updates (and friends) Cornelia Huck
                   ` (3 preceding siblings ...)
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 04/27] s390-ccw: update libc Cornelia Huck
@ 2018-03-01 12:58 ` Cornelia Huck
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 06/27] s390-ccw: parse and set boot menu options Cornelia Huck
                   ` (16 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: Cornelia Huck @ 2018-03-01 12:58 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-s390x, qemu-devel, borntraeger, rth, agraf, david, thuth,
	Collin L. Walling, Viktor Mihajlovski

From: "Collin L. Walling" <walling@linux.vnet.ibm.com>

The s390-ccw firmware needs some information in support of the
boot process which is not available on the native machine.
Examples are the netboot firmware load address and now the
boot menu parameters.

While storing that data in unused fields of the IPL parameter block
works, that approach could create problems if the parameter block
definition should change in the future. Because then a guest could
overwrite these fields using the set IPLB diagnose.

In fact the data in question is of more global nature and not really
tied to an IPL device, so separating it is rather logical.

This commit introduces a new structure to hold firmware relevant
IPL parameters set by QEMU. The data is stored at location 204 (dec)
and can contain up to 7 32-bit words. This area is available to
programming in the z/Architecture Principles of Operation and
can thus safely be used by the firmware until the IPL has completed.

Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com>
Signed-off-by: Collin L. Walling <walling@linux.vnet.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
[thuth: fixed "4 + 8 * n" comment]
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 hw/s390x/ipl.c          | 18 +++++++++++++++++-
 hw/s390x/ipl.h          | 25 +++++++++++++++++++++++--
 pc-bios/s390-ccw/iplb.h | 18 ++++++++++++++++--
 pc-bios/s390-ccw/main.c |  6 +++++-
 4 files changed, 61 insertions(+), 6 deletions(-)

diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index 0d06fc12b6..79f5a58adb 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -399,6 +399,21 @@ void s390_reipl_request(void)
     qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
 }
 
+static void s390_ipl_prepare_qipl(S390CPU *cpu)
+{
+    S390IPLState *ipl = get_ipl_device();
+    uint8_t *addr;
+    uint64_t len = 4096;
+
+    addr = cpu_physical_memory_map(cpu->env.psa, &len, 1);
+    if (!addr || len < QIPL_ADDRESS + sizeof(QemuIplParameters)) {
+        error_report("Cannot set QEMU IPL parameters");
+        return;
+    }
+    memcpy(addr + QIPL_ADDRESS, &ipl->qipl, sizeof(QemuIplParameters));
+    cpu_physical_memory_unmap(addr, len, 1, len);
+}
+
 void s390_ipl_prepare_cpu(S390CPU *cpu)
 {
     S390IPLState *ipl = get_ipl_device();
@@ -418,8 +433,9 @@ void s390_ipl_prepare_cpu(S390CPU *cpu)
             error_report_err(err);
             vm_stop(RUN_STATE_INTERNAL_ERROR);
         }
-        ipl->iplb.ccw.netboot_start_addr = cpu_to_be64(ipl->start_addr);
+        ipl->qipl.netboot_start_addr = cpu_to_be64(ipl->start_addr);
     }
+    s390_ipl_prepare_qipl(cpu);
 }
 
 static void s390_ipl_reset(DeviceState *dev)
diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h
index 8a705e0428..5cc3b770d4 100644
--- a/hw/s390x/ipl.h
+++ b/hw/s390x/ipl.h
@@ -16,8 +16,7 @@
 #include "cpu.h"
 
 struct IplBlockCcw {
-    uint64_t netboot_start_addr;
-    uint8_t  reserved0[77];
+    uint8_t  reserved0[85];
     uint8_t  ssid;
     uint16_t devno;
     uint8_t  vm_flags;
@@ -90,6 +89,27 @@ void s390_ipl_prepare_cpu(S390CPU *cpu);
 IplParameterBlock *s390_ipl_get_iplb(void);
 void s390_reipl_request(void);
 
+#define QIPL_ADDRESS  0xcc
+
+/*
+ * The QEMU IPL Parameters will be stored at absolute address
+ * 204 (0xcc) which means it is 32-bit word aligned but not
+ * double-word aligned.
+ * Placement of data fields in this area must account for
+ * their alignment needs. E.g., netboot_start_address must
+ * have an offset of 4 + n * 8 bytes within the struct in order
+ * to keep it double-word aligned.
+ * The total size of the struct must never exceed 28 bytes.
+ * This definition must be kept in sync with the defininition
+ * in pc-bios/s390-ccw/iplb.h.
+ */
+struct QemuIplParameters {
+    uint8_t  reserved1[4];
+    uint64_t netboot_start_addr;
+    uint8_t  reserved2[16];
+} QEMU_PACKED;
+typedef struct QemuIplParameters QemuIplParameters;
+
 #define TYPE_S390_IPL "s390-ipl"
 #define S390_IPL(obj) OBJECT_CHECK(S390IPLState, (obj), TYPE_S390_IPL)
 
@@ -105,6 +125,7 @@ struct S390IPLState {
     bool iplb_valid;
     bool reipl_requested;
     bool netboot;
+    QemuIplParameters qipl;
 
     /*< public >*/
     char *kernel;
diff --git a/pc-bios/s390-ccw/iplb.h b/pc-bios/s390-ccw/iplb.h
index 890aed9ece..31d2934762 100644
--- a/pc-bios/s390-ccw/iplb.h
+++ b/pc-bios/s390-ccw/iplb.h
@@ -13,8 +13,7 @@
 #define IPLB_H
 
 struct IplBlockCcw {
-    uint64_t netboot_start_addr;
-    uint8_t  reserved0[77];
+    uint8_t  reserved0[85];
     uint8_t  ssid;
     uint16_t devno;
     uint8_t  vm_flags;
@@ -73,6 +72,21 @@ typedef struct IplParameterBlock IplParameterBlock;
 
 extern IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE)));
 
+#define QIPL_ADDRESS  0xcc
+
+/*
+ * This definition must be kept in sync with the defininition
+ * in hw/s390x/ipl.h
+ */
+struct QemuIplParameters {
+    uint8_t  reserved1[4];
+    uint64_t netboot_start_addr;
+    uint8_t  reserved2[16];
+} __attribute__ ((packed));
+typedef struct QemuIplParameters QemuIplParameters;
+
+extern QemuIplParameters qipl;
+
 #define S390_IPL_TYPE_FCP 0x00
 #define S390_IPL_TYPE_CCW 0x02
 #define S390_IPL_TYPE_QEMU_SCSI 0xff
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index e857ce4f60..e41b264a6f 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -16,6 +16,7 @@ char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
 static SubChannelId blk_schid = { .one = 1 };
 IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE)));
 static char loadparm[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+QemuIplParameters qipl;
 
 /*
  * Priniciples of Operations (SA22-7832-09) chapter 17 requires that
@@ -81,6 +82,7 @@ static void virtio_setup(void)
     uint16_t dev_no;
     char ldp[] = "LOADPARM=[________]\n";
     VDev *vdev = virtio_get_device();
+    QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS;
 
     /*
      * We unconditionally enable mss support. In every sane configuration,
@@ -93,6 +95,8 @@ static void virtio_setup(void)
     memcpy(ldp + 10, loadparm, 8);
     sclp_print(ldp);
 
+    memcpy(&qipl, early_qipl, sizeof(QemuIplParameters));
+
     if (store_iplb(&iplb)) {
         switch (iplb.pbt) {
         case S390_IPL_TYPE_CCW:
@@ -127,7 +131,7 @@ static void virtio_setup(void)
 
     if (virtio_get_device_type() == VIRTIO_ID_NET) {
         sclp_print("Network boot device detected\n");
-        vdev->netboot_start_addr = iplb.ccw.netboot_start_addr;
+        vdev->netboot_start_addr = qipl.netboot_start_addr;
     } else {
         virtio_blk_setup_device(blk_schid);
 
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [Qemu-devel] [PULL v2 06/27] s390-ccw: parse and set boot menu options
  2018-03-01 12:58 [Qemu-devel] [PULL v2 00/27] s390x updates (and friends) Cornelia Huck
                   ` (4 preceding siblings ...)
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 05/27] s390-ccw: move auxiliary IPL data to separate location Cornelia Huck
@ 2018-03-01 12:58 ` Cornelia Huck
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 07/27] s390-ccw: set up interactive boot menu parameters Cornelia Huck
                   ` (15 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: Cornelia Huck @ 2018-03-01 12:58 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-s390x, qemu-devel, borntraeger, rth, agraf, david, thuth,
	Collin L. Walling

From: "Collin L. Walling" <walling@linux.vnet.ibm.com>

Set boot menu options for an s390 guest and store them in
the iplb. These options are set via the QEMU command line
option:

    -boot menu=on|off[,splash-time=X]

or via the libvirt domain xml:

    <os>
      <bootmenu enable='yes|no' timeout='X'/>
    </os>

Where X represents some positive integer representing
milliseconds.

Any value set for loadparm will override all boot menu options.
If loadparm=PROMPT, then the menu will be enabled without a
timeout.

Signed-off-by: Collin L. Walling <walling@linux.vnet.ibm.com>
Reviewed-by: Janosch Frank <frankja@linux.vnet.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 hw/s390x/ipl.c          | 52 +++++++++++++++++++++++++++++++++++++++++++++++++
 hw/s390x/ipl.h          |  9 +++++++--
 pc-bios/s390-ccw/iplb.h |  9 +++++++--
 3 files changed, 66 insertions(+), 4 deletions(-)

diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index 79f5a58adb..ee2039dc69 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -23,6 +23,9 @@
 #include "hw/s390x/ebcdic.h"
 #include "ipl.h"
 #include "qemu/error-report.h"
+#include "qemu/config-file.h"
+#include "qemu/cutils.h"
+#include "qemu/option.h"
 
 #define KERN_IMAGE_START                0x010000UL
 #define KERN_PARM_AREA                  0x010480UL
@@ -219,6 +222,54 @@ static Property s390_ipl_properties[] = {
     DEFINE_PROP_END_OF_LIST(),
 };
 
+static void s390_ipl_set_boot_menu(S390IPLState *ipl)
+{
+    QemuOptsList *plist = qemu_find_opts("boot-opts");
+    QemuOpts *opts = QTAILQ_FIRST(&plist->head);
+    uint8_t *flags = &ipl->qipl.qipl_flags;
+    uint32_t *timeout = &ipl->qipl.boot_menu_timeout;
+    const char *tmp;
+    unsigned long splash_time = 0;
+
+    if (!get_boot_device(0)) {
+        if (boot_menu) {
+            error_report("boot menu requires a bootindex to be specified for "
+                         "the IPL device.");
+        }
+        return;
+    }
+
+    switch (ipl->iplb.pbt) {
+    case S390_IPL_TYPE_CCW:
+        break;
+    default:
+        error_report("boot menu is not supported for this device type.");
+        return;
+    }
+
+    if (!boot_menu) {
+        return;
+    }
+
+    *flags |= QIPL_FLAG_BM_OPTS_CMD;
+
+    tmp = qemu_opt_get(opts, "splash-time");
+
+    if (tmp && qemu_strtoul(tmp, NULL, 10, &splash_time)) {
+        error_report("splash-time is invalid, forcing it to 0.");
+        *timeout = 0;
+        return;
+    }
+
+    if (splash_time > 0xffffffff) {
+        error_report("splash-time is too large, forcing it to max value.");
+        *timeout = 0xffffffff;
+        return;
+    }
+
+    *timeout = cpu_to_be32(splash_time);
+}
+
 static bool s390_gen_initial_iplb(S390IPLState *ipl)
 {
     DeviceState *dev_st;
@@ -435,6 +486,7 @@ void s390_ipl_prepare_cpu(S390CPU *cpu)
         }
         ipl->qipl.netboot_start_addr = cpu_to_be64(ipl->start_addr);
     }
+    s390_ipl_set_boot_menu(ipl);
     s390_ipl_prepare_qipl(cpu);
 }
 
diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h
index 5cc3b770d4..d6c6f75b76 100644
--- a/hw/s390x/ipl.h
+++ b/hw/s390x/ipl.h
@@ -91,6 +91,9 @@ void s390_reipl_request(void);
 
 #define QIPL_ADDRESS  0xcc
 
+/* Boot Menu flags */
+#define QIPL_FLAG_BM_OPTS_CMD   0x80
+
 /*
  * The QEMU IPL Parameters will be stored at absolute address
  * 204 (0xcc) which means it is 32-bit word aligned but not
@@ -104,9 +107,11 @@ void s390_reipl_request(void);
  * in pc-bios/s390-ccw/iplb.h.
  */
 struct QemuIplParameters {
-    uint8_t  reserved1[4];
+    uint8_t  qipl_flags;
+    uint8_t  reserved1[3];
     uint64_t netboot_start_addr;
-    uint8_t  reserved2[16];
+    uint32_t boot_menu_timeout;
+    uint8_t  reserved2[12];
 } QEMU_PACKED;
 typedef struct QemuIplParameters QemuIplParameters;
 
diff --git a/pc-bios/s390-ccw/iplb.h b/pc-bios/s390-ccw/iplb.h
index 31d2934762..832bb94440 100644
--- a/pc-bios/s390-ccw/iplb.h
+++ b/pc-bios/s390-ccw/iplb.h
@@ -74,14 +74,19 @@ extern IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE)));
 
 #define QIPL_ADDRESS  0xcc
 
+/* Boot Menu flags */
+#define QIPL_FLAG_BM_OPTS_CMD   0x80
+
 /*
  * This definition must be kept in sync with the defininition
  * in hw/s390x/ipl.h
  */
 struct QemuIplParameters {
-    uint8_t  reserved1[4];
+    uint8_t  qipl_flags;
+    uint8_t  reserved1[3];
     uint64_t netboot_start_addr;
-    uint8_t  reserved2[16];
+    uint32_t boot_menu_timeout;
+    uint8_t  reserved2[12];
 } __attribute__ ((packed));
 typedef struct QemuIplParameters QemuIplParameters;
 
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [Qemu-devel] [PULL v2 07/27] s390-ccw: set up interactive boot menu parameters
  2018-03-01 12:58 [Qemu-devel] [PULL v2 00/27] s390x updates (and friends) Cornelia Huck
                   ` (5 preceding siblings ...)
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 06/27] s390-ccw: parse and set boot menu options Cornelia Huck
@ 2018-03-01 12:58 ` Cornelia Huck
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 08/27] s390-ccw: read stage2 boot loader data to find menu Cornelia Huck
                   ` (14 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: Cornelia Huck @ 2018-03-01 12:58 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-s390x, qemu-devel, borntraeger, rth, agraf, david, thuth,
	Collin L. Walling

From: "Collin L. Walling" <walling@linux.vnet.ibm.com>

Reads boot menu flag and timeout values from the iplb and
sets the respective fields for the menu.

Signed-off-by: Collin L. Walling <walling@linux.vnet.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 pc-bios/s390-ccw/Makefile   |  2 +-
 pc-bios/s390-ccw/main.c     | 24 ++++++++++++++++++++++++
 pc-bios/s390-ccw/menu.c     | 22 ++++++++++++++++++++++
 pc-bios/s390-ccw/s390-ccw.h |  3 +++
 4 files changed, 50 insertions(+), 1 deletion(-)
 create mode 100644 pc-bios/s390-ccw/menu.c

diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile
index 9f7904fc20..1712c2d95d 100644
--- a/pc-bios/s390-ccw/Makefile
+++ b/pc-bios/s390-ccw/Makefile
@@ -9,7 +9,7 @@ $(call set-vpath, $(SRC_PATH)/pc-bios/s390-ccw)
 
 .PHONY : all clean build-all
 
-OBJECTS = start.o main.o bootmap.o sclp.o virtio.o virtio-scsi.o virtio-blkdev.o libc.o
+OBJECTS = start.o main.o bootmap.o sclp.o virtio.o virtio-scsi.o virtio-blkdev.o libc.o menu.o
 QEMU_CFLAGS := $(filter -W%, $(QEMU_CFLAGS))
 QEMU_CFLAGS += -ffreestanding -fno-delete-null-pointer-checks -msoft-float
 QEMU_CFLAGS += -march=z900 -fPIE -fno-strict-aliasing
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index e41b264a6f..32ed70ebdd 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -18,6 +18,9 @@ IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE)));
 static char loadparm[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
 QemuIplParameters qipl;
 
+#define LOADPARM_PROMPT "PROMPT  "
+#define LOADPARM_EMPTY  "........"
+
 /*
  * Priniciples of Operations (SA22-7832-09) chapter 17 requires that
  * a subsystem-identification is at 184-187 and bytes 188-191 are zero
@@ -74,6 +77,26 @@ static bool find_dev(Schib *schib, int dev_no)
     return false;
 }
 
+static void menu_setup(void)
+{
+    if (memcmp(loadparm, LOADPARM_PROMPT, 8) == 0) {
+        menu_set_parms(QIPL_FLAG_BM_OPTS_CMD, 0);
+        return;
+    }
+
+    /* If loadparm was set to any other value, then do not enable menu */
+    if (memcmp(loadparm, LOADPARM_EMPTY, 8) != 0) {
+        return;
+    }
+
+    switch (iplb.pbt) {
+    case S390_IPL_TYPE_CCW:
+        menu_set_parms(qipl.qipl_flags & QIPL_FLAG_BM_OPTS_CMD,
+                       qipl.boot_menu_timeout);
+        return;
+    }
+}
+
 static void virtio_setup(void)
 {
     Schib schib;
@@ -117,6 +140,7 @@ static void virtio_setup(void)
         default:
             panic("List-directed IPL not supported yet!\n");
         }
+        menu_setup();
     } else {
         for (ssid = 0; ssid < 0x3; ssid++) {
             blk_schid.ssid = ssid;
diff --git a/pc-bios/s390-ccw/menu.c b/pc-bios/s390-ccw/menu.c
new file mode 100644
index 0000000000..1ce33ddf3d
--- /dev/null
+++ b/pc-bios/s390-ccw/menu.c
@@ -0,0 +1,22 @@
+/*
+ * QEMU S390 Interactive Boot Menu
+ *
+ * Copyright 2018 IBM Corp.
+ * Author: Collin L. Walling <walling@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#include "libc.h"
+#include "s390-ccw.h"
+
+static uint8_t flag;
+static uint64_t timeout;
+
+void menu_set_parms(uint8_t boot_menu_flag, uint32_t boot_menu_timeout)
+{
+    flag = boot_menu_flag;
+    timeout = boot_menu_timeout;
+}
diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h
index 25d4d213ea..6cfd4b2183 100644
--- a/pc-bios/s390-ccw/s390-ccw.h
+++ b/pc-bios/s390-ccw/s390-ccw.h
@@ -84,6 +84,9 @@ ulong get_second(void);
 /* bootmap.c */
 void zipl_load(void);
 
+/* menu.c */
+void menu_set_parms(uint8_t boot_menu_flag, uint32_t boot_menu_timeout);
+
 static inline void fill_hex(char *out, unsigned char val)
 {
     const char hex[] = "0123456789abcdef";
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [Qemu-devel] [PULL v2 08/27] s390-ccw: read stage2 boot loader data to find menu
  2018-03-01 12:58 [Qemu-devel] [PULL v2 00/27] s390x updates (and friends) Cornelia Huck
                   ` (6 preceding siblings ...)
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 07/27] s390-ccw: set up interactive boot menu parameters Cornelia Huck
@ 2018-03-01 12:58 ` Cornelia Huck
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 09/27] s390-ccw: print zipl boot menu Cornelia Huck
                   ` (13 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: Cornelia Huck @ 2018-03-01 12:58 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-s390x, qemu-devel, borntraeger, rth, agraf, david, thuth,
	Collin L. Walling

From: "Collin L. Walling" <walling@linux.vnet.ibm.com>

Read the stage2 boot loader data block-by-block. We scan the
current block for the string "zIPL" to detect the start of the
boot menu banner. We then load the adjacent blocks (previous
block and next block) to account for the possibility of menu
data spanning multiple blocks.

Signed-off-by: Collin L. Walling <walling@linux.vnet.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 pc-bios/s390-ccw/bootmap.c  | 94 ++++++++++++++++++++++++++++++++++++++++++---
 pc-bios/s390-ccw/bootmap.h  | 23 ++++++++++-
 pc-bios/s390-ccw/menu.c     | 10 +++++
 pc-bios/s390-ccw/s390-ccw.h |  2 +
 4 files changed, 122 insertions(+), 7 deletions(-)

diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c
index 092fb355fe..ae93b552c9 100644
--- a/pc-bios/s390-ccw/bootmap.c
+++ b/pc-bios/s390-ccw/bootmap.c
@@ -83,6 +83,10 @@ static void jump_to_IPL_code(uint64_t address)
 
 static unsigned char _bprs[8*1024]; /* guessed "max" ECKD sector size */
 static const int max_bprs_entries = sizeof(_bprs) / sizeof(ExtEckdBlockPtr);
+static uint8_t _s2[MAX_SECTOR_SIZE * 3] __attribute__((__aligned__(PAGE_SIZE)));
+static void *s2_prev_blk = _s2;
+static void *s2_cur_blk = _s2 + MAX_SECTOR_SIZE;
+static void *s2_next_blk = _s2 + MAX_SECTOR_SIZE * 2;
 
 static inline void verify_boot_info(BootInfo *bip)
 {
@@ -182,7 +186,77 @@ static block_number_t load_eckd_segments(block_number_t blk, uint64_t *address)
     return block_nr;
 }
 
-static void run_eckd_boot_script(block_number_t bmt_block_nr)
+static bool find_zipl_boot_menu_banner(int *offset)
+{
+    int i;
+
+    /* Menu banner starts with "zIPL" */
+    for (i = 0; i < virtio_get_block_size() - 4; i++) {
+        if (magic_match(s2_cur_blk + i, ZIPL_MAGIC_EBCDIC)) {
+            *offset = i;
+            return true;
+        }
+    }
+
+    return false;
+}
+
+static int eckd_get_boot_menu_index(block_number_t s1b_block_nr)
+{
+    block_number_t cur_block_nr;
+    block_number_t prev_block_nr = 0;
+    block_number_t next_block_nr = 0;
+    EckdStage1b *s1b = (void *)sec;
+    int banner_offset;
+    int i;
+
+    /* Get Stage1b data */
+    memset(sec, FREE_SPACE_FILLER, sizeof(sec));
+    read_block(s1b_block_nr, s1b, "Cannot read stage1b boot loader");
+
+    memset(_s2, FREE_SPACE_FILLER, sizeof(_s2));
+
+    /* Get Stage2 data */
+    for (i = 0; i < STAGE2_BLK_CNT_MAX; i++) {
+        cur_block_nr = eckd_block_num(&s1b->seek[i].chs);
+
+        if (!cur_block_nr) {
+            break;
+        }
+
+        read_block(cur_block_nr, s2_cur_blk, "Cannot read stage2 boot loader");
+
+        if (find_zipl_boot_menu_banner(&banner_offset)) {
+            /*
+             * Load the adjacent blocks to account for the
+             * possibility of menu data spanning multiple blocks.
+             */
+            if (prev_block_nr) {
+                read_block(prev_block_nr, s2_prev_blk,
+                           "Cannot read stage2 boot loader");
+            }
+
+            if (i + 1 < STAGE2_BLK_CNT_MAX) {
+                next_block_nr = eckd_block_num(&s1b->seek[i + 1].chs);
+            }
+
+            if (next_block_nr) {
+                read_block(next_block_nr, s2_next_blk,
+                           "Cannot read stage2 boot loader");
+            }
+
+            return menu_get_zipl_boot_index(s2_cur_blk + banner_offset);
+        }
+
+        prev_block_nr = cur_block_nr;
+    }
+
+    sclp_print("No zipl boot menu data found. Booting default entry.");
+    return 0;
+}
+
+static void run_eckd_boot_script(block_number_t bmt_block_nr,
+                                 block_number_t s1b_block_nr)
 {
     int i;
     unsigned int loadparm = get_loadparm_index();
@@ -191,6 +265,10 @@ static void run_eckd_boot_script(block_number_t bmt_block_nr)
     BootMapTable *bmt = (void *)sec;
     BootMapScript *bms = (void *)sec;
 
+    if (menu_is_enabled_zipl()) {
+        loadparm = eckd_get_boot_menu_index(s1b_block_nr);
+    }
+
     debug_print_int("loadparm", loadparm);
     IPL_assert(loadparm <= MAX_TABLE_ENTRIES, "loadparm value greater than"
                " maximum number of boot entries allowed");
@@ -223,7 +301,7 @@ static void ipl_eckd_cdl(void)
     XEckdMbr *mbr;
     EckdCdlIpl2 *ipl2 = (void *)sec;
     IplVolumeLabel *vlbl = (void *)sec;
-    block_number_t bmt_block_nr;
+    block_number_t bmt_block_nr, s1b_block_nr;
 
     /* we have just read the block #0 and recognized it as "IPL1" */
     sclp_print("CDL\n");
@@ -241,6 +319,9 @@ static void ipl_eckd_cdl(void)
     /* save pointer to Boot Map Table */
     bmt_block_nr = eckd_block_num(&mbr->blockptr.xeckd.bptr.chs);
 
+    /* save pointer to Stage1b Data */
+    s1b_block_nr = eckd_block_num(&ipl2->stage1.seek[0].chs);
+
     memset(sec, FREE_SPACE_FILLER, sizeof(sec));
     read_block(2, vlbl, "Cannot read Volume Label at block 2");
     IPL_assert(magic_match(vlbl->key, VOL1_MAGIC),
@@ -249,7 +330,7 @@ static void ipl_eckd_cdl(void)
                "Invalid magic of volser block");
     print_volser(vlbl->f.volser);
 
-    run_eckd_boot_script(bmt_block_nr);
+    run_eckd_boot_script(bmt_block_nr, s1b_block_nr);
     /* no return */
 }
 
@@ -280,7 +361,7 @@ static void print_eckd_ldl_msg(ECKD_IPL_mode_t mode)
 
 static void ipl_eckd_ldl(ECKD_IPL_mode_t mode)
 {
-    block_number_t bmt_block_nr;
+    block_number_t bmt_block_nr, s1b_block_nr;
     EckdLdlIpl1 *ipl1 = (void *)sec;
 
     if (mode != ECKD_LDL_UNLABELED) {
@@ -302,7 +383,10 @@ static void ipl_eckd_ldl(ECKD_IPL_mode_t mode)
     /* save pointer to Boot Map Table */
     bmt_block_nr = eckd_block_num(&ipl1->bip.bp.ipl.bm_ptr.eckd.bptr.chs);
 
-    run_eckd_boot_script(bmt_block_nr);
+    /* save pointer to Stage1b Data */
+    s1b_block_nr = eckd_block_num(&ipl1->stage1.seek[0].chs);
+
+    run_eckd_boot_script(bmt_block_nr, s1b_block_nr);
     /* no return */
 }
 
diff --git a/pc-bios/s390-ccw/bootmap.h b/pc-bios/s390-ccw/bootmap.h
index 4cf7e1e463..c636626f1a 100644
--- a/pc-bios/s390-ccw/bootmap.h
+++ b/pc-bios/s390-ccw/bootmap.h
@@ -87,6 +87,7 @@ typedef struct ScsiMbr {
 } __attribute__ ((packed)) ScsiMbr;
 
 #define ZIPL_MAGIC              "zIPL"
+#define ZIPL_MAGIC_EBCDIC       "\xa9\xc9\xd7\xd3"
 #define IPL1_MAGIC "\xc9\xd7\xd3\xf1" /* == "IPL1" in EBCDIC */
 #define IPL2_MAGIC "\xc9\xd7\xd3\xf2" /* == "IPL2" in EBCDIC */
 #define VOL1_MAGIC "\xe5\xd6\xd3\xf1" /* == "VOL1" in EBCDIC */
@@ -249,15 +250,33 @@ typedef struct EckdCdlIpl1 {
     uint8_t data[24];
 } __attribute__((packed)) EckdCdlIpl1;
 
+typedef struct EckdSeekArg {
+    uint16_t pad;
+    EckdCHS chs;
+    uint8_t pad2;
+} __attribute__ ((packed)) EckdSeekArg;
+
+typedef struct EckdStage1b {
+    uint8_t reserved[32 * STAGE2_BLK_CNT_MAX];
+    struct EckdSeekArg seek[STAGE2_BLK_CNT_MAX];
+    uint8_t unused[64];
+} __attribute__ ((packed)) EckdStage1b;
+
+typedef struct EckdStage1 {
+    uint8_t reserved[72];
+    struct EckdSeekArg seek[2];
+} __attribute__ ((packed)) EckdStage1;
+
 typedef struct EckdCdlIpl2 {
     uint8_t key[4]; /* == "IPL2" */
-    uint8_t reserved0[88];
+    struct EckdStage1 stage1;
     XEckdMbr mbr;
     uint8_t reserved[24];
 } __attribute__((packed)) EckdCdlIpl2;
 
 typedef struct EckdLdlIpl1 {
-    uint8_t reserved[112];
+    uint8_t reserved[24];
+    struct EckdStage1 stage1;
     BootInfo bip; /* BootInfo is MBR for LDL */
 } __attribute__((packed)) EckdLdlIpl1;
 
diff --git a/pc-bios/s390-ccw/menu.c b/pc-bios/s390-ccw/menu.c
index 1ce33ddf3d..c1d242fed1 100644
--- a/pc-bios/s390-ccw/menu.c
+++ b/pc-bios/s390-ccw/menu.c
@@ -15,8 +15,18 @@
 static uint8_t flag;
 static uint64_t timeout;
 
+int menu_get_zipl_boot_index(const char *menu_data)
+{
+    return 0; /* implemented next patch */
+}
+
 void menu_set_parms(uint8_t boot_menu_flag, uint32_t boot_menu_timeout)
 {
     flag = boot_menu_flag;
     timeout = boot_menu_timeout;
 }
+
+bool menu_is_enabled_zipl(void)
+{
+    return flag & QIPL_FLAG_BM_OPTS_CMD;
+}
diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h
index 6cfd4b2183..c0dd37f7ba 100644
--- a/pc-bios/s390-ccw/s390-ccw.h
+++ b/pc-bios/s390-ccw/s390-ccw.h
@@ -86,6 +86,8 @@ void zipl_load(void);
 
 /* menu.c */
 void menu_set_parms(uint8_t boot_menu_flag, uint32_t boot_menu_timeout);
+int menu_get_zipl_boot_index(const char *menu_data);
+bool menu_is_enabled_zipl(void);
 
 static inline void fill_hex(char *out, unsigned char val)
 {
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [Qemu-devel] [PULL v2 09/27] s390-ccw: print zipl boot menu
  2018-03-01 12:58 [Qemu-devel] [PULL v2 00/27] s390x updates (and friends) Cornelia Huck
                   ` (7 preceding siblings ...)
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 08/27] s390-ccw: read stage2 boot loader data to find menu Cornelia Huck
@ 2018-03-01 12:58 ` Cornelia Huck
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 10/27] s390-ccw: read user input for boot index via the SCLP console Cornelia Huck
                   ` (12 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: Cornelia Huck @ 2018-03-01 12:58 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-s390x, qemu-devel, borntraeger, rth, agraf, david, thuth,
	Collin L. Walling

From: "Collin L. Walling" <walling@linux.vnet.ibm.com>

When the boot menu options are present and the guest's
disk has been configured by the zipl tool, then the user
will be presented with an interactive boot menu with
labeled entries. An example of what the menu might look
like:

zIPL v1.37.1-build-20170714 interactive boot menu.

0. default (linux-4.13.0)

  1. linux-4.13.0
  2. performance
  3. kvm

Signed-off-by: Collin L. Walling <walling@linux.vnet.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 pc-bios/s390-ccw/menu.c | 33 ++++++++++++++++++++++++++++++++-
 1 file changed, 32 insertions(+), 1 deletion(-)

diff --git a/pc-bios/s390-ccw/menu.c b/pc-bios/s390-ccw/menu.c
index c1d242fed1..730d44e36b 100644
--- a/pc-bios/s390-ccw/menu.c
+++ b/pc-bios/s390-ccw/menu.c
@@ -15,11 +15,42 @@
 static uint8_t flag;
 static uint64_t timeout;
 
-int menu_get_zipl_boot_index(const char *menu_data)
+static int get_boot_index(int entries)
 {
     return 0; /* implemented next patch */
 }
 
+static void zipl_println(const char *data, size_t len)
+{
+    char buf[len + 2];
+
+    ebcdic_to_ascii(data, buf, len);
+    buf[len] = '\n';
+    buf[len + 1] = '\0';
+
+    sclp_print(buf);
+}
+
+int menu_get_zipl_boot_index(const char *menu_data)
+{
+    size_t len;
+    int entries;
+
+    /* Print and count all menu items, including the banner */
+    for (entries = 0; *menu_data; entries++) {
+        len = strlen(menu_data);
+        zipl_println(menu_data, len);
+        menu_data += len + 1;
+
+        if (entries < 2) {
+            sclp_print("\n");
+        }
+    }
+
+    sclp_print("\n");
+    return get_boot_index(entries - 1); /* subtract 1 to exclude banner */
+}
+
 void menu_set_parms(uint8_t boot_menu_flag, uint32_t boot_menu_timeout)
 {
     flag = boot_menu_flag;
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [Qemu-devel] [PULL v2 10/27] s390-ccw: read user input for boot index via the SCLP console
  2018-03-01 12:58 [Qemu-devel] [PULL v2 00/27] s390x updates (and friends) Cornelia Huck
                   ` (8 preceding siblings ...)
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 09/27] s390-ccw: print zipl boot menu Cornelia Huck
@ 2018-03-01 12:58 ` Cornelia Huck
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 11/27] s390-ccw: set cp_receive mask only when needed and consume pending service irqs Cornelia Huck
                   ` (11 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: Cornelia Huck @ 2018-03-01 12:58 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-s390x, qemu-devel, borntraeger, rth, agraf, david, thuth,
	Collin L. Walling

From: "Collin L. Walling" <walling@linux.vnet.ibm.com>

Implements an sclp_read function to capture input from the
console and a wrapper function that handles parsing certain
characters and adding input to a buffer. The input is checked
for any erroneous values and is handled appropriately.

A prompt will persist until input is entered or the timeout
expires (if one was set). Example:

      Please choose (default will boot in 10 seconds):

Correct input will boot the respective boot index. If the
user's input is empty, 0, or if the timeout expires, then
the default zipl entry will be chosen. If the input is
within the range of available boot entries, then the
selection will be booted. Any erroneous input will cancel
the timeout and re-prompt the user.

Signed-off-by: Collin L. Walling <walling@linux.vnet.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 pc-bios/s390-ccw/menu.c     | 149 +++++++++++++++++++++++++++++++++++++++++++-
 pc-bios/s390-ccw/s390-ccw.h |   2 +
 pc-bios/s390-ccw/sclp.c     |  19 ++++++
 pc-bios/s390-ccw/virtio.c   |   2 +-
 4 files changed, 170 insertions(+), 2 deletions(-)

diff --git a/pc-bios/s390-ccw/menu.c b/pc-bios/s390-ccw/menu.c
index 730d44e36b..b99ff03298 100644
--- a/pc-bios/s390-ccw/menu.c
+++ b/pc-bios/s390-ccw/menu.c
@@ -12,12 +12,159 @@
 #include "libc.h"
 #include "s390-ccw.h"
 
+#define KEYCODE_NO_INP '\0'
+#define KEYCODE_ESCAPE '\033'
+#define KEYCODE_BACKSP '\177'
+#define KEYCODE_ENTER  '\r'
+
+#define TOD_CLOCK_MILLISECOND   0x3e8000
+
+#define LOW_CORE_EXTERNAL_INT_ADDR   0x86
+#define CLOCK_COMPARATOR_INT         0X1004
+
 static uint8_t flag;
 static uint64_t timeout;
 
+static inline void enable_clock_int(void)
+{
+    uint64_t tmp = 0;
+
+    asm volatile(
+        "stctg      0,0,%0\n"
+        "oi         6+%0, 0x8\n"
+        "lctlg      0,0,%0"
+        : : "Q" (tmp) : "memory"
+    );
+}
+
+static inline void disable_clock_int(void)
+{
+    uint64_t tmp = 0;
+
+    asm volatile(
+        "stctg      0,0,%0\n"
+        "ni         6+%0, 0xf7\n"
+        "lctlg      0,0,%0"
+        : : "Q" (tmp) : "memory"
+    );
+}
+
+static inline void set_clock_comparator(uint64_t time)
+{
+    asm volatile("sckc %0" : : "Q" (time));
+}
+
+static inline bool check_clock_int(void)
+{
+    uint16_t *code = (uint16_t *)LOW_CORE_EXTERNAL_INT_ADDR;
+
+    consume_sclp_int();
+
+    return *code == CLOCK_COMPARATOR_INT;
+}
+
+static int read_prompt(char *buf, size_t len)
+{
+    char inp[2] = {};
+    uint8_t idx = 0;
+    uint64_t time;
+
+    if (timeout) {
+        time = get_clock() + timeout * TOD_CLOCK_MILLISECOND;
+        set_clock_comparator(time);
+        enable_clock_int();
+        timeout = 0;
+    }
+
+    while (!check_clock_int()) {
+
+        sclp_read(inp, 1); /* Process only one character at a time */
+
+        switch (inp[0]) {
+        case KEYCODE_NO_INP:
+        case KEYCODE_ESCAPE:
+            continue;
+        case KEYCODE_BACKSP:
+            if (idx > 0) {
+                buf[--idx] = 0;
+                sclp_print("\b \b");
+            }
+            continue;
+        case KEYCODE_ENTER:
+            disable_clock_int();
+            return idx;
+        default:
+            /* Echo input and add to buffer */
+            if (idx < len) {
+                buf[idx++] = inp[0];
+                sclp_print(inp);
+            }
+        }
+    }
+
+    disable_clock_int();
+    *buf = 0;
+
+    return 0;
+}
+
+static int get_index(void)
+{
+    char buf[11];
+    int len;
+    int i;
+
+    memset(buf, 0, sizeof(buf));
+
+    len = read_prompt(buf, sizeof(buf) - 1);
+
+    /* If no input, boot default */
+    if (len == 0) {
+        return 0;
+    }
+
+    /* Check for erroneous input */
+    for (i = 0; i < len; i++) {
+        if (!isdigit(buf[i])) {
+            return -1;
+        }
+    }
+
+    return atoui(buf);
+}
+
+static void boot_menu_prompt(bool retry)
+{
+    char tmp[11];
+
+    if (retry) {
+        sclp_print("\nError: undefined configuration"
+                   "\nPlease choose:\n");
+    } else if (timeout > 0) {
+        sclp_print("Please choose (default will boot in ");
+        sclp_print(uitoa(timeout / 1000, tmp, sizeof(tmp)));
+        sclp_print(" seconds):\n");
+    } else {
+        sclp_print("Please choose:\n");
+    }
+}
+
 static int get_boot_index(int entries)
 {
-    return 0; /* implemented next patch */
+    int boot_index;
+    bool retry = false;
+    char tmp[5];
+
+    do {
+        boot_menu_prompt(retry);
+        boot_index = get_index();
+        retry = true;
+    } while (boot_index < 0 || boot_index >= entries);
+
+    sclp_print("\nBooting entry #");
+    sclp_print(uitoa(boot_index, tmp, sizeof(tmp)));
+
+    return boot_index;
 }
 
 static void zipl_println(const char *data, size_t len)
diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h
index c0dd37f7ba..aeba8b0a99 100644
--- a/pc-bios/s390-ccw/s390-ccw.h
+++ b/pc-bios/s390-ccw/s390-ccw.h
@@ -71,6 +71,7 @@ unsigned int get_loadparm_index(void);
 void sclp_print(const char *string);
 void sclp_setup(void);
 void sclp_get_loadparm_ascii(char *loadparm);
+int sclp_read(char *str, size_t count);
 
 /* virtio.c */
 unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2,
@@ -79,6 +80,7 @@ bool virtio_is_supported(SubChannelId schid);
 void virtio_blk_setup_device(SubChannelId schid);
 int virtio_read(ulong sector, void *load_addr);
 int enable_mss_facility(void);
+u64 get_clock(void);
 ulong get_second(void);
 
 /* bootmap.c */
diff --git a/pc-bios/s390-ccw/sclp.c b/pc-bios/s390-ccw/sclp.c
index e6a089889a..a2f25ebd4f 100644
--- a/pc-bios/s390-ccw/sclp.c
+++ b/pc-bios/s390-ccw/sclp.c
@@ -119,3 +119,22 @@ void sclp_get_loadparm_ascii(char *loadparm)
         ebcdic_to_ascii((char *) sccb->loadparm, loadparm, 8);
     }
 }
+
+int sclp_read(char *str, size_t count)
+{
+    ReadEventData *sccb = (void *)_sccb;
+    char *buf = (char *)(&sccb->ebh) + 7;
+
+    /* If count exceeds max buffer size, then restrict it to the max size */
+    if (count > SCCB_SIZE - 8) {
+        count = SCCB_SIZE - 8;
+    }
+
+    sccb->h.length = SCCB_SIZE;
+    sccb->h.function_code = SCLP_UNCONDITIONAL_READ;
+
+    sclp_service_call(SCLP_CMD_READ_EVENT_DATA, sccb);
+    memcpy(str, buf, count);
+
+    return sccb->ebh.length - 7;
+}
diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c
index c890a0330b..817e7f56ea 100644
--- a/pc-bios/s390-ccw/virtio.c
+++ b/pc-bios/s390-ccw/virtio.c
@@ -176,7 +176,7 @@ void vring_send_buf(VRing *vr, void *p, int len, int flags)
     }
 }
 
-static u64 get_clock(void)
+u64 get_clock(void)
 {
     u64 r;
 
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [Qemu-devel] [PULL v2 11/27] s390-ccw: set cp_receive mask only when needed and consume pending service irqs
  2018-03-01 12:58 [Qemu-devel] [PULL v2 00/27] s390x updates (and friends) Cornelia Huck
                   ` (9 preceding siblings ...)
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 10/27] s390-ccw: read user input for boot index via the SCLP console Cornelia Huck
@ 2018-03-01 12:58 ` Cornelia Huck
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 12/27] s390-ccw: use zipl values when no boot menu options are present Cornelia Huck
                   ` (10 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: Cornelia Huck @ 2018-03-01 12:58 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-s390x, qemu-devel, borntraeger, rth, agraf, david, thuth,
	Collin L. Walling

From: "Collin L. Walling" <walling@linux.vnet.ibm.com>

It is possible while waiting for multiple types of external
interrupts that we might have pending irqs remaining between
irq consumption and irq-type disabling. Those interrupts
could potentially propagate to the guest after IPL completes
and cause unwanted behavior.

As it is today, the SCLP will only recognize write events that
are enabled by the control program's send and receive masks. To
limit the window for, and prevent further irqs from, ASCII
console events (specifically keystrokes), we should only enable
the control program's receive mask when we need it.

While we're at it, remove assignment of the (non control program)
send and receive masks, as those are actually set by the SCLP.

Signed-off-by: Collin L. Walling <walling@linux.vnet.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 pc-bios/s390-ccw/menu.c     |  5 +++++
 pc-bios/s390-ccw/s390-ccw.h |  1 +
 pc-bios/s390-ccw/sclp.c     | 10 ++++------
 3 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/pc-bios/s390-ccw/menu.c b/pc-bios/s390-ccw/menu.c
index b99ff03298..8d55869448 100644
--- a/pc-bios/s390-ccw/menu.c
+++ b/pc-bios/s390-ccw/menu.c
@@ -11,6 +11,7 @@
 
 #include "libc.h"
 #include "s390-ccw.h"
+#include "sclp.h"
 
 #define KEYCODE_NO_INP '\0'
 #define KEYCODE_ESCAPE '\033'
@@ -116,8 +117,12 @@ static int get_index(void)
 
     memset(buf, 0, sizeof(buf));
 
+    sclp_set_write_mask(SCLP_EVENT_MASK_MSG_ASCII, SCLP_EVENT_MASK_MSG_ASCII);
+
     len = read_prompt(buf, sizeof(buf) - 1);
 
+    sclp_set_write_mask(0, SCLP_EVENT_MASK_MSG_ASCII);
+
     /* If no input, boot default */
     if (len == 0) {
         return 0;
diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h
index aeba8b0a99..c4ddf9f228 100644
--- a/pc-bios/s390-ccw/s390-ccw.h
+++ b/pc-bios/s390-ccw/s390-ccw.h
@@ -69,6 +69,7 @@ unsigned int get_loadparm_index(void);
 
 /* sclp.c */
 void sclp_print(const char *string);
+void sclp_set_write_mask(uint32_t receive_mask, uint32_t send_mask);
 void sclp_setup(void);
 void sclp_get_loadparm_ascii(char *loadparm);
 int sclp_read(char *str, size_t count);
diff --git a/pc-bios/s390-ccw/sclp.c b/pc-bios/s390-ccw/sclp.c
index a2f25ebd4f..3836cb4716 100644
--- a/pc-bios/s390-ccw/sclp.c
+++ b/pc-bios/s390-ccw/sclp.c
@@ -46,23 +46,21 @@ static int sclp_service_call(unsigned int command, void *sccb)
         return 0;
 }
 
-static void sclp_set_write_mask(void)
+void sclp_set_write_mask(uint32_t receive_mask, uint32_t send_mask)
 {
     WriteEventMask *sccb = (void *)_sccb;
 
     sccb->h.length = sizeof(WriteEventMask);
     sccb->mask_length = sizeof(unsigned int);
-    sccb->receive_mask = SCLP_EVENT_MASK_MSG_ASCII;
-    sccb->cp_receive_mask = SCLP_EVENT_MASK_MSG_ASCII;
-    sccb->send_mask = SCLP_EVENT_MASK_MSG_ASCII;
-    sccb->cp_send_mask = SCLP_EVENT_MASK_MSG_ASCII;
+    sccb->cp_receive_mask = receive_mask;
+    sccb->cp_send_mask = send_mask;
 
     sclp_service_call(SCLP_CMD_WRITE_EVENT_MASK, sccb);
 }
 
 void sclp_setup(void)
 {
-    sclp_set_write_mask();
+    sclp_set_write_mask(0, SCLP_EVENT_MASK_MSG_ASCII);
 }
 
 long write(int fd, const void *str, size_t len)
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [Qemu-devel] [PULL v2 12/27] s390-ccw: use zipl values when no boot menu options are present
  2018-03-01 12:58 [Qemu-devel] [PULL v2 00/27] s390x updates (and friends) Cornelia Huck
                   ` (10 preceding siblings ...)
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 11/27] s390-ccw: set cp_receive mask only when needed and consume pending service irqs Cornelia Huck
@ 2018-03-01 12:58 ` Cornelia Huck
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 13/27] s390-ccw: interactive boot menu for scsi Cornelia Huck
                   ` (9 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: Cornelia Huck @ 2018-03-01 12:58 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-s390x, qemu-devel, borntraeger, rth, agraf, david, thuth,
	Collin L. Walling

From: "Collin L. Walling" <walling@linux.vnet.ibm.com>

If no boot menu options are present, then flag the boot menu to
use the zipl options that were set in the zipl configuration file
(and stored on disk by zipl). These options are found at some
offset prior to the start of the zipl boot menu banner. The zipl
timeout value is limited to a 16-bit unsigned integer and stored
as seconds, so we take care to convert it to milliseconds in order
to conform to the rest of the boot menu functionality. This is
limited to CCW devices.

For reference, the zipl configuration file uses the following
fields in the menu section:

      prompt=1      enable the boot menu
      timeout=X     set the timeout to X seconds

To explicitly disregard any boot menu options, then menu=off or
<bootmenu enable='no' ... /> must be specified.

Signed-off-by: Collin L. Walling <walling@linux.vnet.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 hw/s390x/ipl.c          |  5 +++++
 hw/s390x/ipl.h          |  1 +
 pc-bios/s390-ccw/iplb.h |  1 +
 pc-bios/s390-ccw/main.c |  3 ++-
 pc-bios/s390-ccw/menu.c | 16 +++++++++++++++-
 5 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index ee2039dc69..c12e460a7f 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -241,6 +241,11 @@ static void s390_ipl_set_boot_menu(S390IPLState *ipl)
 
     switch (ipl->iplb.pbt) {
     case S390_IPL_TYPE_CCW:
+        /* In the absence of -boot menu, use zipl parameters */
+        if (!qemu_opt_get(opts, "menu")) {
+            *flags |= QIPL_FLAG_BM_OPTS_ZIPL;
+            return;
+        }
         break;
     default:
         error_report("boot menu is not supported for this device type.");
diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h
index d6c6f75b76..0570d0ad75 100644
--- a/hw/s390x/ipl.h
+++ b/hw/s390x/ipl.h
@@ -93,6 +93,7 @@ void s390_reipl_request(void);
 
 /* Boot Menu flags */
 #define QIPL_FLAG_BM_OPTS_CMD   0x80
+#define QIPL_FLAG_BM_OPTS_ZIPL  0x40
 
 /*
  * The QEMU IPL Parameters will be stored at absolute address
diff --git a/pc-bios/s390-ccw/iplb.h b/pc-bios/s390-ccw/iplb.h
index 832bb94440..7dfce4fbcf 100644
--- a/pc-bios/s390-ccw/iplb.h
+++ b/pc-bios/s390-ccw/iplb.h
@@ -76,6 +76,7 @@ extern IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE)));
 
 /* Boot Menu flags */
 #define QIPL_FLAG_BM_OPTS_CMD   0x80
+#define QIPL_FLAG_BM_OPTS_ZIPL  0x40
 
 /*
  * This definition must be kept in sync with the defininition
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index 32ed70ebdd..a7473b0397 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -20,6 +20,7 @@ QemuIplParameters qipl;
 
 #define LOADPARM_PROMPT "PROMPT  "
 #define LOADPARM_EMPTY  "........"
+#define BOOT_MENU_FLAG_MASK (QIPL_FLAG_BM_OPTS_CMD | QIPL_FLAG_BM_OPTS_ZIPL)
 
 /*
  * Priniciples of Operations (SA22-7832-09) chapter 17 requires that
@@ -91,7 +92,7 @@ static void menu_setup(void)
 
     switch (iplb.pbt) {
     case S390_IPL_TYPE_CCW:
-        menu_set_parms(qipl.qipl_flags & QIPL_FLAG_BM_OPTS_CMD,
+        menu_set_parms(qipl.qipl_flags & BOOT_MENU_FLAG_MASK,
                        qipl.boot_menu_timeout);
         return;
     }
diff --git a/pc-bios/s390-ccw/menu.c b/pc-bios/s390-ccw/menu.c
index 8d55869448..ee56939c21 100644
--- a/pc-bios/s390-ccw/menu.c
+++ b/pc-bios/s390-ccw/menu.c
@@ -18,6 +18,10 @@
 #define KEYCODE_BACKSP '\177'
 #define KEYCODE_ENTER  '\r'
 
+/* Offsets from zipl fields to zipl banner start */
+#define ZIPL_TIMEOUT_OFFSET 138
+#define ZIPL_FLAG_OFFSET    140
+
 #define TOD_CLOCK_MILLISECOND   0x3e8000
 
 #define LOW_CORE_EXTERNAL_INT_ADDR   0x86
@@ -187,6 +191,16 @@ int menu_get_zipl_boot_index(const char *menu_data)
 {
     size_t len;
     int entries;
+    uint16_t zipl_flag = *(uint16_t *)(menu_data - ZIPL_FLAG_OFFSET);
+    uint16_t zipl_timeout = *(uint16_t *)(menu_data - ZIPL_TIMEOUT_OFFSET);
+
+    if (flag == QIPL_FLAG_BM_OPTS_ZIPL) {
+        if (!zipl_flag) {
+            return 0; /* Boot default */
+        }
+        /* zipl stores timeout as seconds */
+        timeout = zipl_timeout * 1000;
+    }
 
     /* Print and count all menu items, including the banner */
     for (entries = 0; *menu_data; entries++) {
@@ -211,5 +225,5 @@ void menu_set_parms(uint8_t boot_menu_flag, uint32_t boot_menu_timeout)
 
 bool menu_is_enabled_zipl(void)
 {
-    return flag & QIPL_FLAG_BM_OPTS_CMD;
+    return flag & (QIPL_FLAG_BM_OPTS_CMD | QIPL_FLAG_BM_OPTS_ZIPL);
 }
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [Qemu-devel] [PULL v2 13/27] s390-ccw: interactive boot menu for scsi
  2018-03-01 12:58 [Qemu-devel] [PULL v2 00/27] s390x updates (and friends) Cornelia Huck
                   ` (11 preceding siblings ...)
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 12/27] s390-ccw: use zipl values when no boot menu options are present Cornelia Huck
@ 2018-03-01 12:58 ` Cornelia Huck
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 14/27] pc-bios/s390: Rebuild the s390x firmware images with the boot menu changes Cornelia Huck
                   ` (8 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: Cornelia Huck @ 2018-03-01 12:58 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-s390x, qemu-devel, borntraeger, rth, agraf, david, thuth,
	Collin L. Walling

From: "Collin L. Walling" <walling@linux.vnet.ibm.com>

Interactive boot menu for scsi. This follows a similar procedure
as the interactive menu for eckd dasd. An example follows:

    s390x Enumerated Boot Menu.

    3 entries detected. Select from index 0 to 2.

Signed-off-by: Collin L. Walling <walling@linux.vnet.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
[thuth: Added additional "break;" statement to avoid analyzer warnings]
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 hw/s390x/ipl.c              |  2 ++
 pc-bios/s390-ccw/bootmap.c  |  4 ++++
 pc-bios/s390-ccw/main.c     |  1 +
 pc-bios/s390-ccw/menu.c     | 20 ++++++++++++++++++++
 pc-bios/s390-ccw/s390-ccw.h |  2 ++
 5 files changed, 29 insertions(+)

diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index c12e460a7f..798e99aadf 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -247,6 +247,8 @@ static void s390_ipl_set_boot_menu(S390IPLState *ipl)
             return;
         }
         break;
+    case S390_IPL_TYPE_QEMU_SCSI:
+        break;
     default:
         error_report("boot menu is not supported for this device type.");
         return;
diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c
index ae93b552c9..29bfd8c875 100644
--- a/pc-bios/s390-ccw/bootmap.c
+++ b/pc-bios/s390-ccw/bootmap.c
@@ -568,6 +568,10 @@ static void ipl_scsi(void)
     debug_print_int("program table entries", program_table_entries);
     IPL_assert(program_table_entries != 0, "Empty Program Table");
 
+    if (menu_is_enabled_enum()) {
+        loadparm = menu_get_enum_boot_index(program_table_entries);
+    }
+
     debug_print_int("loadparm", loadparm);
     IPL_assert(loadparm <= MAX_TABLE_ENTRIES, "loadparm value greater than"
                " maximum number of boot entries allowed");
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index a7473b0397..9d9f8cf4d3 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -92,6 +92,7 @@ static void menu_setup(void)
 
     switch (iplb.pbt) {
     case S390_IPL_TYPE_CCW:
+    case S390_IPL_TYPE_QEMU_SCSI:
         menu_set_parms(qipl.qipl_flags & BOOT_MENU_FLAG_MASK,
                        qipl.boot_menu_timeout);
         return;
diff --git a/pc-bios/s390-ccw/menu.c b/pc-bios/s390-ccw/menu.c
index ee56939c21..96eec81e84 100644
--- a/pc-bios/s390-ccw/menu.c
+++ b/pc-bios/s390-ccw/menu.c
@@ -217,6 +217,21 @@ int menu_get_zipl_boot_index(const char *menu_data)
     return get_boot_index(entries - 1); /* subtract 1 to exclude banner */
 }
 
+
+int menu_get_enum_boot_index(int entries)
+{
+    char tmp[4];
+
+    sclp_print("s390x Enumerated Boot Menu.\n\n");
+
+    sclp_print(uitoa(entries, tmp, sizeof(tmp)));
+    sclp_print(" entries detected. Select from boot index 0 to ");
+    sclp_print(uitoa(entries - 1, tmp, sizeof(tmp)));
+    sclp_print(".\n\n");
+
+    return get_boot_index(entries);
+}
+
 void menu_set_parms(uint8_t boot_menu_flag, uint32_t boot_menu_timeout)
 {
     flag = boot_menu_flag;
@@ -227,3 +242,8 @@ bool menu_is_enabled_zipl(void)
 {
     return flag & (QIPL_FLAG_BM_OPTS_CMD | QIPL_FLAG_BM_OPTS_ZIPL);
 }
+
+bool menu_is_enabled_enum(void)
+{
+    return flag & QIPL_FLAG_BM_OPTS_CMD;
+}
diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h
index c4ddf9f228..fd18da22c6 100644
--- a/pc-bios/s390-ccw/s390-ccw.h
+++ b/pc-bios/s390-ccw/s390-ccw.h
@@ -91,6 +91,8 @@ void zipl_load(void);
 void menu_set_parms(uint8_t boot_menu_flag, uint32_t boot_menu_timeout);
 int menu_get_zipl_boot_index(const char *menu_data);
 bool menu_is_enabled_zipl(void);
+int menu_get_enum_boot_index(int entries);
+bool menu_is_enabled_enum(void);
 
 static inline void fill_hex(char *out, unsigned char val)
 {
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [Qemu-devel] [PULL v2 14/27] pc-bios/s390: Rebuild the s390x firmware images with the boot menu changes
  2018-03-01 12:58 [Qemu-devel] [PULL v2 00/27] s390x updates (and friends) Cornelia Huck
                   ` (12 preceding siblings ...)
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 13/27] s390-ccw: interactive boot menu for scsi Cornelia Huck
@ 2018-03-01 12:58 ` Cornelia Huck
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 15/27] s390x/cpu: expose the guest crash information Cornelia Huck
                   ` (7 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: Cornelia Huck @ 2018-03-01 12:58 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-s390x, qemu-devel, borntraeger, rth, agraf, david, thuth

From: Thomas Huth <thuth@redhat.com>

Provide a new s390-ccw.img binary with the boot menu patches by Collin.
Though there should not be any visible changes for the network booting,
the s390-netboot.img binary has been rebuilt, too, since some of the
changes affected the shared source files.

Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 pc-bios/s390-ccw.img     | Bin 26416 -> 34568 bytes
 pc-bios/s390-netboot.img | Bin 83864 -> 83776 bytes
 2 files changed, 0 insertions(+), 0 deletions(-)
 mode change 100755 => 100644 pc-bios/s390-netboot.img

diff --git a/pc-bios/s390-ccw.img b/pc-bios/s390-ccw.img
index 97155d2638eebc1220a63287fcada21df65b3a77..fbd76bb55ed01367c9e2e5656e9a3e2eb21f823f 100644
GIT binary patch
literal 34568
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

literal 26416
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
TU9q1v*XU23v8|{Z<HdgmK^Zp#

diff --git a/pc-bios/s390-netboot.img b/pc-bios/s390-netboot.img
old mode 100755
new mode 100644
index 24f40feae6fa02b8b930f75879a4ec9b8fcc39aa..9f5926b534cefa598618746f64fc8bb4bb25c265
GIT binary patch
literal 83776
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

literal 83864
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

-- 
2.13.6

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [Qemu-devel] [PULL v2 15/27] s390x/cpu: expose the guest crash information
  2018-03-01 12:58 [Qemu-devel] [PULL v2 00/27] s390x updates (and friends) Cornelia Huck
                   ` (13 preceding siblings ...)
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 14/27] pc-bios/s390: Rebuild the s390x firmware images with the boot menu changes Cornelia Huck
@ 2018-03-01 12:58 ` Cornelia Huck
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 16/27] s390/stattrib: Make SaveVMHandlers data static Cornelia Huck
                   ` (6 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: Cornelia Huck @ 2018-03-01 12:58 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-s390x, qemu-devel, borntraeger, rth, agraf, david, thuth,
	Cornelia Huck

From: Christian Borntraeger <borntraeger@de.ibm.com>

This patch is the s390 implementation of guest crash information,
similar to commit d187e08dc4 ("i386/cpu: add crash-information QOM
property") and the related commits. We will detect several crash
reasons, with the "disabled wait" being the most important one, since
this is used by all s390 guests as a "panic like" notification.

Demonstrate these ways with examples as follows.

  1. crash-information QOM property;

  Run qemu with -qmp unix:qmp-sock,server, then use utility "qmp-shell"
  to execute "qom-get" command, and might get the result like,

  (QEMU) (QEMU) qom-get path=/machine/unattached/device[0] \
      property=crash-information
  {"return": {"core": 0, "reason": "disabled-wait", "psw-mask": 562956395872256, \
      "type": "s390", "psw-addr": 1102832}}

  2. GUEST_PANICKED event reporting;

  Run qemu with a socket option, and telnet or nc to that,
  -chardev socket,id=qmp,port=4444,host=localhost,server \
  -mon chardev=qmp,mode=control,pretty=on \
  Negotiating the mode by { "execute": "qmp_capabilities" }, and the crash
  information will be reported on a guest crash event like,

  {
    "timestamp": {
        "seconds": 1518004739,
        "microseconds": 552563
    },
    "event": "GUEST_PANICKED",
    "data": {
        "action": "pause",
        "info": {
            "core": 0,
            "psw-addr": 1102832,
            "reason": "disabled-wait",
            "psw-mask": 562956395872256,
            "type": "s390"
        }
    }
  }

  3. log;

  Run qemu with the parameters: -D <logfile> -d guest_errors, to
  specify the logfile and log item. The results might be,

  Guest crashed on cpu 0: disabled-wait
  PSW: 0x0002000180000000 0x000000000010d3f0

Co-authored-by: Jing Liu <liujbjl@linux.vnet.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Message-Id: <20180209122543.25755-1-borntraeger@de.ibm.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
[CH: tweaked qapi comment]
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
 qapi/run-state.json   | 55 +++++++++++++++++++++++++++++++++++++++++++++++++--
 target/s390x/cpu.c    | 45 +++++++++++++++++++++++++++++++++++++++++
 target/s390x/cpu.h    |  2 ++
 target/s390x/helper.c |  5 ++++-
 target/s390x/kvm.c    | 15 +++++++-------
 vl.c                  | 11 +++++++++--
 6 files changed, 120 insertions(+), 13 deletions(-)

diff --git a/qapi/run-state.json b/qapi/run-state.json
index bca46a8785..92d29fd571 100644
--- a/qapi/run-state.json
+++ b/qapi/run-state.json
@@ -320,22 +320,29 @@
 #
 # An enumeration of the guest panic information types
 #
+# @hyper-v: hyper-v guest panic information type
+#
+# @s390: s390 guest panic information type (Since: 2.12)
+#
 # Since: 2.9
 ##
 { 'enum': 'GuestPanicInformationType',
-  'data': [ 'hyper-v'] }
+  'data': [ 'hyper-v', 's390' ] }
 
 ##
 # @GuestPanicInformation:
 #
 # Information about a guest panic
 #
+# @type: Crash type that defines the hypervisor specific information
+#
 # Since: 2.9
 ##
 {'union': 'GuestPanicInformation',
  'base': {'type': 'GuestPanicInformationType'},
  'discriminator': 'type',
- 'data': { 'hyper-v': 'GuestPanicInformationHyperV' } }
+ 'data': { 'hyper-v': 'GuestPanicInformationHyperV',
+           's390': 'GuestPanicInformationS390' } }
 
 ##
 # @GuestPanicInformationHyperV:
@@ -350,3 +357,47 @@
            'arg3': 'uint64',
            'arg4': 'uint64',
            'arg5': 'uint64' } }
+
+##
+# @S390CrashReason:
+#
+# Reason why the CPU is in a crashed state.
+#
+# @unknown: no crash reason was set
+#
+# @disabled-wait: the CPU has entered a disabled wait state
+#
+# @extint-loop: clock comparator or cpu timer interrupt with new PSW enabled
+#              for external interrupts
+#
+# @pgmint-loop: program interrupt with BAD new PSW
+#
+# @opint-loop: operation exception interrupt with invalid code at the program
+#             interrupt new PSW
+#
+# Since: 2.12
+##
+{ 'enum': 'S390CrashReason',
+  'data': [ 'unknown',
+            'disabled-wait',
+            'extint-loop',
+            'pgmint-loop',
+            'opint-loop' ] }
+
+##
+# @GuestPanicInformationS390:
+#
+# S390 specific guest panic information (PSW)
+#
+# @core: core id of the CPU that crashed
+# @psw-mask: control fields of guest PSW
+# @psw-addr: guest instruction address
+# @reason: guest crash reason
+#
+# Since: 2.12
+##
+{'struct': 'GuestPanicInformationS390',
+ 'data': { 'core': 'uint32',
+           'psw-mask': 'uint64',
+           'psw-addr': 'uint64',
+           'reason': 'S390CrashReason' } }
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
index a665b9e60e..3e1be56536 100644
--- a/target/s390x/cpu.c
+++ b/target/s390x/cpu.c
@@ -35,6 +35,8 @@
 #include "qemu/error-report.h"
 #include "trace.h"
 #include "qapi/visitor.h"
+#include "qapi-visit.h"
+#include "sysemu/hw_accel.h"
 #include "exec/exec-all.h"
 #include "hw/qdev-properties.h"
 #ifndef CONFIG_USER_ONLY
@@ -228,6 +230,46 @@ out:
     error_propagate(errp, err);
 }
 
+static GuestPanicInformation *s390_cpu_get_crash_info(CPUState *cs)
+{
+    GuestPanicInformation *panic_info;
+    S390CPU *cpu = S390_CPU(cs);
+
+    cpu_synchronize_state(cs);
+    panic_info = g_malloc0(sizeof(GuestPanicInformation));
+
+    panic_info->type = GUEST_PANIC_INFORMATION_TYPE_S390;
+#if !defined(CONFIG_USER_ONLY)
+    panic_info->u.s390.core = cpu->env.core_id;
+#else
+    panic_info->u.s390.core = 0; /* sane default for non system emulation */
+#endif
+    panic_info->u.s390.psw_mask = cpu->env.psw.mask;
+    panic_info->u.s390.psw_addr = cpu->env.psw.addr;
+    panic_info->u.s390.reason = cpu->env.crash_reason;
+
+    return panic_info;
+}
+
+static void s390_cpu_get_crash_info_qom(Object *obj, Visitor *v,
+                                        const char *name, void *opaque,
+                                        Error **errp)
+{
+    CPUState *cs = CPU(obj);
+    GuestPanicInformation *panic_info;
+
+    if (!cs->crash_occurred) {
+        error_setg(errp, "No crash occurred");
+        return;
+    }
+
+    panic_info = s390_cpu_get_crash_info(cs);
+
+    visit_type_GuestPanicInformation(v, "crash-information", &panic_info,
+                                     errp);
+    qapi_free_GuestPanicInformation(panic_info);
+}
+
 static void s390_cpu_initfn(Object *obj)
 {
     CPUState *cs = CPU(obj);
@@ -240,6 +282,8 @@ static void s390_cpu_initfn(Object *obj)
     cs->env_ptr = env;
     cs->halted = 1;
     cs->exception_index = EXCP_HLT;
+    object_property_add(obj, "crash-information", "GuestPanicInformation",
+                        s390_cpu_get_crash_info_qom, NULL, NULL, NULL, NULL);
     s390_cpu_model_register_props(obj);
 #if !defined(CONFIG_USER_ONLY)
     qemu_get_timedate(&tm, 0);
@@ -473,6 +517,7 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data)
     cc->do_interrupt = s390_cpu_do_interrupt;
 #endif
     cc->dump_state = s390_cpu_dump_state;
+    cc->get_crash_info = s390_cpu_get_crash_info;
     cc->set_pc = s390_cpu_set_pc;
     cc->gdb_read_register = s390_cpu_gdb_read_register;
     cc->gdb_write_register = s390_cpu_gdb_write_register;
diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
index 96df2fe5c9..09ec8a9b76 100644
--- a/target/s390x/cpu.h
+++ b/target/s390x/cpu.h
@@ -83,6 +83,8 @@ struct CPUS390XState {
 
     PSW psw;
 
+    S390CrashReason crash_reason;
+
     uint64_t cc_src;
     uint64_t cc_dst;
     uint64_t cc_vr;
diff --git a/target/s390x/helper.c b/target/s390x/helper.c
index 84aaef3a53..615fa24ab9 100644
--- a/target/s390x/helper.c
+++ b/target/s390x/helper.c
@@ -83,12 +83,15 @@ static inline bool is_special_wait_psw(uint64_t psw_addr)
 
 void s390_handle_wait(S390CPU *cpu)
 {
+    CPUState *cs = CPU(cpu);
+
     if (s390_cpu_halt(cpu) == 0) {
 #ifndef CONFIG_USER_ONLY
         if (is_special_wait_psw(cpu->env.psw.addr)) {
             qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
         } else {
-            qemu_system_guest_panicked(NULL);
+            cpu->env.crash_reason = S390_CRASH_REASON_DISABLED_WAIT;
+            qemu_system_guest_panicked(cpu_get_crash_info(cs));
         }
 #endif
     }
diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c
index e13c8907df..83e4eaf45d 100644
--- a/target/s390x/kvm.c
+++ b/target/s390x/kvm.c
@@ -1541,15 +1541,14 @@ static int handle_instruction(S390CPU *cpu, struct kvm_run *run)
     return r;
 }
 
-static void unmanageable_intercept(S390CPU *cpu, const char *str, int pswoffset)
+static void unmanageable_intercept(S390CPU *cpu, S390CrashReason reason,
+                                   int pswoffset)
 {
     CPUState *cs = CPU(cpu);
 
-    error_report("Unmanageable %s! CPU%i new PSW: 0x%016lx:%016lx",
-                 str, cs->cpu_index, ldq_phys(cs->as, cpu->env.psa + pswoffset),
-                 ldq_phys(cs->as, cpu->env.psa + pswoffset + 8));
     s390_cpu_halt(cpu);
-    qemu_system_guest_panicked(NULL);
+    cpu->env.crash_reason = reason;
+    qemu_system_guest_panicked(cpu_get_crash_info(cs));
 }
 
 /* try to detect pgm check loops */
@@ -1579,7 +1578,7 @@ static int handle_oper_loop(S390CPU *cpu, struct kvm_run *run)
         !(oldpsw.mask & PSW_MASK_PSTATE) &&
         (newpsw.mask & PSW_MASK_ASC) == (oldpsw.mask & PSW_MASK_ASC) &&
         (newpsw.mask & PSW_MASK_DAT) == (oldpsw.mask & PSW_MASK_DAT)) {
-        unmanageable_intercept(cpu, "operation exception loop",
+        unmanageable_intercept(cpu, S390_CRASH_REASON_OPINT_LOOP,
                                offsetof(LowCore, program_new_psw));
         return EXCP_HALTED;
     }
@@ -1600,12 +1599,12 @@ static int handle_intercept(S390CPU *cpu)
             r = handle_instruction(cpu, run);
             break;
         case ICPT_PROGRAM:
-            unmanageable_intercept(cpu, "program interrupt",
+            unmanageable_intercept(cpu, S390_CRASH_REASON_PGMINT_LOOP,
                                    offsetof(LowCore, program_new_psw));
             r = EXCP_HALTED;
             break;
         case ICPT_EXT_INT:
-            unmanageable_intercept(cpu, "external interrupt",
+            unmanageable_intercept(cpu, S390_CRASH_REASON_EXTINT_LOOP,
                                    offsetof(LowCore, external_new_psw));
             r = EXCP_HALTED;
             break;
diff --git a/vl.c b/vl.c
index 9e7235df6d..3018433706 100644
--- a/vl.c
+++ b/vl.c
@@ -1736,7 +1736,7 @@ void qemu_system_reset(ShutdownCause reason)
 
 void qemu_system_guest_panicked(GuestPanicInformation *info)
 {
-    qemu_log_mask(LOG_GUEST_ERROR, "Guest crashed\n");
+    qemu_log_mask(LOG_GUEST_ERROR, "Guest crashed");
 
     if (current_cpu) {
         current_cpu->crash_occurred = true;
@@ -1752,13 +1752,20 @@ void qemu_system_guest_panicked(GuestPanicInformation *info)
 
     if (info) {
         if (info->type == GUEST_PANIC_INFORMATION_TYPE_HYPER_V) {
-            qemu_log_mask(LOG_GUEST_ERROR, "HV crash parameters: (%#"PRIx64
+            qemu_log_mask(LOG_GUEST_ERROR, "\nHV crash parameters: (%#"PRIx64
                           " %#"PRIx64" %#"PRIx64" %#"PRIx64" %#"PRIx64")\n",
                           info->u.hyper_v.arg1,
                           info->u.hyper_v.arg2,
                           info->u.hyper_v.arg3,
                           info->u.hyper_v.arg4,
                           info->u.hyper_v.arg5);
+        } else if (info->type == GUEST_PANIC_INFORMATION_TYPE_S390) {
+            qemu_log_mask(LOG_GUEST_ERROR, " on cpu %d: %s\n"
+                          "PSW: 0x%016" PRIx64 " 0x%016" PRIx64"\n",
+                          info->u.s390.core,
+                          S390CrashReason_str(info->u.s390.reason),
+                          info->u.s390.psw_mask,
+                          info->u.s390.psw_addr);
         }
         qapi_free_GuestPanicInformation(info);
     }
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [Qemu-devel] [PULL v2 16/27] s390/stattrib: Make SaveVMHandlers data static
  2018-03-01 12:58 [Qemu-devel] [PULL v2 00/27] s390x updates (and friends) Cornelia Huck
                   ` (14 preceding siblings ...)
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 15/27] s390x/cpu: expose the guest crash information Cornelia Huck
@ 2018-03-01 12:58 ` Cornelia Huck
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 17/27] s390x/tcg: fix disabling/enabling DAT Cornelia Huck
                   ` (5 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: Cornelia Huck @ 2018-03-01 12:58 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-s390x, qemu-devel, borntraeger, rth, agraf, david, thuth,
	Dr. David Alan Gilbert, Cornelia Huck

From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>

There's no need for this to be dynamic, make it static.

Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Message-Id: <20180212154903.8859-1-dgilbert@redhat.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Claudio Imbrenda <imbrenda@linux.vnet.ibm.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
 hw/s390x/s390-stattrib.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/hw/s390x/s390-stattrib.c b/hw/s390x/s390-stattrib.c
index a1d2135a60..adf07ef312 100644
--- a/hw/s390x/s390-stattrib.c
+++ b/hw/s390x/s390-stattrib.c
@@ -365,22 +365,22 @@ static inline void s390_stattrib_set_migration_enabled(Object *obj, bool value,
     s->migration_enabled = value;
 }
 
+static SaveVMHandlers savevm_s390_stattrib_handlers = {
+    .save_setup = cmma_save_setup,
+    .save_live_iterate = cmma_save_iterate,
+    .save_live_complete_precopy = cmma_save_complete,
+    .save_live_pending = cmma_save_pending,
+    .save_cleanup = cmma_save_cleanup,
+    .load_state = cmma_load,
+    .is_active = cmma_active,
+};
+
 static void s390_stattrib_instance_init(Object *obj)
 {
     S390StAttribState *sas = S390_STATTRIB(obj);
-    SaveVMHandlers *ops;
-
-    /* ops will always be freed by qemu when unregistering */
-    ops = g_new0(SaveVMHandlers, 1);
-
-    ops->save_setup = cmma_save_setup;
-    ops->save_live_iterate = cmma_save_iterate;
-    ops->save_live_complete_precopy = cmma_save_complete;
-    ops->save_live_pending = cmma_save_pending;
-    ops->save_cleanup = cmma_save_cleanup;
-    ops->load_state = cmma_load;
-    ops->is_active = cmma_active;
-    register_savevm_live(NULL, TYPE_S390_STATTRIB, 0, 0, ops, sas);
+
+    register_savevm_live(NULL, TYPE_S390_STATTRIB, 0, 0,
+                         &savevm_s390_stattrib_handlers, sas);
 
     object_property_add_bool(obj, "migration-enabled",
                              s390_stattrib_get_migration_enabled,
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [Qemu-devel] [PULL v2 17/27] s390x/tcg: fix disabling/enabling DAT
  2018-03-01 12:58 [Qemu-devel] [PULL v2 00/27] s390x updates (and friends) Cornelia Huck
                   ` (15 preceding siblings ...)
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 16/27] s390/stattrib: Make SaveVMHandlers data static Cornelia Huck
@ 2018-03-01 12:58 ` Cornelia Huck
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 18/27] s390x/tcg: add various alignment checks Cornelia Huck
                   ` (4 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: Cornelia Huck @ 2018-03-01 12:58 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-s390x, qemu-devel, borntraeger, rth, agraf, david, thuth,
	Cornelia Huck

From: David Hildenbrand <david@redhat.com>

Currently, all memory accesses go via the MMU of the address space
(primary, secondary, ...). This is bad, because we don't flush the TLB
when disabling/enabling DAT. So we could add a tlb flush. However it
is easier to simply select the MMU we already have in place for real
memory access.

All we have to do is point at the right MMU and allow to execute these
pages.

Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20180213161240.19891-1-david@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
[CH: get rid of tabs]
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
 target/s390x/cpu.h        |  7 ++++++-
 target/s390x/mmu_helper.c |  2 +-
 target/s390x/translate.c  | 10 +++++++---
 3 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
index 09ec8a9b76..d4641663ef 100644
--- a/target/s390x/cpu.h
+++ b/target/s390x/cpu.h
@@ -312,11 +312,12 @@ extern const struct VMStateDescription vmstate_s390_cpu;
 
 #define FLAG_MASK_PSW_SHIFT     31
 #define FLAG_MASK_PER           (PSW_MASK_PER    >> FLAG_MASK_PSW_SHIFT)
+#define FLAG_MASK_DAT           (PSW_MASK_DAT    >> FLAG_MASK_PSW_SHIFT)
 #define FLAG_MASK_PSTATE        (PSW_MASK_PSTATE >> FLAG_MASK_PSW_SHIFT)
 #define FLAG_MASK_ASC           (PSW_MASK_ASC    >> FLAG_MASK_PSW_SHIFT)
 #define FLAG_MASK_64            (PSW_MASK_64     >> FLAG_MASK_PSW_SHIFT)
 #define FLAG_MASK_32            (PSW_MASK_32     >> FLAG_MASK_PSW_SHIFT)
-#define FLAG_MASK_PSW		(FLAG_MASK_PER | FLAG_MASK_PSTATE \
+#define FLAG_MASK_PSW           (FLAG_MASK_PER | FLAG_MASK_DAT | FLAG_MASK_PSTATE \
                                 | FLAG_MASK_ASC | FLAG_MASK_64 | FLAG_MASK_32)
 
 /* Control register 0 bits */
@@ -340,6 +341,10 @@ extern const struct VMStateDescription vmstate_s390_cpu;
 
 static inline int cpu_mmu_index(CPUS390XState *env, bool ifetch)
 {
+    if (!(env->psw.mask & PSW_MASK_DAT)) {
+        return MMU_REAL_IDX;
+    }
+
     switch (env->psw.mask & PSW_MASK_ASC) {
     case PSW_ASC_PRIMARY:
         return MMU_PRIMARY_IDX;
diff --git a/target/s390x/mmu_helper.c b/target/s390x/mmu_helper.c
index f477cc006a..23fb2e7501 100644
--- a/target/s390x/mmu_helper.c
+++ b/target/s390x/mmu_helper.c
@@ -544,7 +544,7 @@ int mmu_translate_real(CPUS390XState *env, target_ulong raddr, int rw,
 {
     const bool lowprot_enabled = env->cregs[0] & CR0_LOWPROT;
 
-    *flags = PAGE_READ | PAGE_WRITE;
+    *flags = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
     if (is_low_address(raddr & TARGET_PAGE_MASK) && lowprot_enabled) {
         /* see comment in mmu_translate() how this works */
         *flags |= PAGE_WRITE_INV;
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index b470d691d3..5aea3bbca6 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -252,13 +252,17 @@ static inline uint64_t ld_code4(CPUS390XState *env, uint64_t pc)
 
 static int get_mem_index(DisasContext *s)
 {
+    if (!(s->tb->flags & FLAG_MASK_DAT)) {
+        return MMU_REAL_IDX;
+    }
+
     switch (s->tb->flags & FLAG_MASK_ASC) {
     case PSW_ASC_PRIMARY >> FLAG_MASK_PSW_SHIFT:
-        return 0;
+        return MMU_PRIMARY_IDX;
     case PSW_ASC_SECONDARY >> FLAG_MASK_PSW_SHIFT:
-        return 1;
+        return MMU_SECONDARY_IDX;
     case PSW_ASC_HOME >> FLAG_MASK_PSW_SHIFT:
-        return 2;
+        return MMU_HOME_IDX;
     default:
         tcg_abort();
         break;
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [Qemu-devel] [PULL v2 18/27] s390x/tcg: add various alignment checks
  2018-03-01 12:58 [Qemu-devel] [PULL v2 00/27] s390x updates (and friends) Cornelia Huck
                   ` (16 preceding siblings ...)
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 17/27] s390x/tcg: fix disabling/enabling DAT Cornelia Huck
@ 2018-03-01 12:58 ` Cornelia Huck
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 19/27] qmp: expose s390-specific CPU info Cornelia Huck
                   ` (3 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: Cornelia Huck @ 2018-03-01 12:58 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-s390x, qemu-devel, borntraeger, rth, agraf, david, thuth,
	Cornelia Huck

From: David Hildenbrand <david@redhat.com>

Let's add proper alignment checks for a handful of instructions that
require a SPECIFICATION exception in case alignment is violated.

Introduce new wout/in functions. As we are right now only using them for
privileged instructions, we have to add ugly ifdefs to silence
compilers.

Convert STORE CPU ID right away to make use of the wout function.

Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20180215103822.15179-1-david@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
 target/s390x/insn-data.def | 16 ++++++++--------
 target/s390x/mem_helper.c  | 25 +++++++++++++++++++++++++
 target/s390x/translate.c   | 43 ++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 75 insertions(+), 9 deletions(-)

diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def
index 621e10d615..157619403d 100644
--- a/target/s390x/insn-data.def
+++ b/target/s390x/insn-data.def
@@ -1000,13 +1000,13 @@
     /* ??? Not implemented - is it necessary? */
     C(0xb204, SCK,     S,     Z,   0, 0, 0, 0, 0, 0)
 /* SET CLOCK COMPARATOR */
-    C(0xb206, SCKC,    S,     Z,   0, m2_64, 0, 0, sckc, 0)
+    C(0xb206, SCKC,    S,     Z,   0, m2_64a, 0, 0, sckc, 0)
 /* SET CLOCK PROGRAMMABLE FIELD */
     C(0x0107, SCKPF,   E,     Z,   0, 0, 0, 0, sckpf, 0)
 /* SET CPU TIMER */
-    C(0xb208, SPT,     S,     Z,   0, m2_64, 0, 0, spt, 0)
+    C(0xb208, SPT,     S,     Z,   0, m2_64a, 0, 0, spt, 0)
 /* SET PREFIX */
-    C(0xb210, SPX,     S,     Z,   0, m2_32u, 0, 0, spx, 0)
+    C(0xb210, SPX,     S,     Z,   0, m2_32ua, 0, 0, spx, 0)
 /* SET PSW KEY FROM ADDRESS */
     C(0xb20a, SPKA,    S,     Z,   0, a2, 0, 0, spka, 0)
 /* SET STORAGE KEY EXTENDED */
@@ -1021,20 +1021,20 @@
 /* STORE CLOCK EXTENDED */
     C(0xb278, STCKE,   S,     Z,   0, a2, 0, 0, stcke, 0)
 /* STORE CLOCK COMPARATOR */
-    C(0xb207, STCKC,   S,     Z,   la2, 0, new, m1_64, stckc, 0)
+    C(0xb207, STCKC,   S,     Z,   la2, 0, new, m1_64a, stckc, 0)
 /* STORE CONTROL */
     C(0xb600, STCTL,   RS_a,  Z,   0, a2, 0, 0, stctl, 0)
     C(0xeb25, STCTG,   RSY_a, Z,   0, a2, 0, 0, stctg, 0)
 /* STORE CPU ADDRESS */
-    C(0xb212, STAP,    S,     Z,   la2, 0, new, m1_16, stap, 0)
+    C(0xb212, STAP,    S,     Z,   la2, 0, new, m1_16a, stap, 0)
 /* STORE CPU ID */
-    C(0xb202, STIDP,   S,     Z,   la2, 0, new, 0, stidp, 0)
+    C(0xb202, STIDP,   S,     Z,   la2, 0, new, m1_64a, stidp, 0)
 /* STORE CPU TIMER */
-    C(0xb209, STPT,    S,     Z,   la2, 0, new, m1_64, stpt, 0)
+    C(0xb209, STPT,    S,     Z,   la2, 0, new, m1_64a, stpt, 0)
 /* STORE FACILITY LIST */
     C(0xb2b1, STFL,    S,     Z,   0, 0, 0, 0, stfl, 0)
 /* STORE PREFIX */
-    C(0xb211, STPX,    S,     Z,   la2, 0, new, m1_32, stpx, 0)
+    C(0xb211, STPX,    S,     Z,   la2, 0, new, m1_32a, stpx, 0)
 /* STORE SYSTEM INFORMATION */
     C(0xb27d, STSI,    S,     Z,   0, a2, 0, 0, stsi, 0)
 /* STORE THEN AND SYSTEM MASK */
diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index 427b795a78..d5291b246e 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -693,6 +693,11 @@ void HELPER(lam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
     uintptr_t ra = GETPC();
     int i;
 
+    if (a2 & 0x3) {
+        /* we either came here by lam or lamy, which have different lengths */
+        s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, ra);
+    }
+
     for (i = r1;; i = (i + 1) % 16) {
         env->aregs[i] = cpu_ldl_data_ra(env, a2, ra);
         a2 += 4;
@@ -709,6 +714,10 @@ void HELPER(stam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
     uintptr_t ra = GETPC();
     int i;
 
+    if (a2 & 0x3) {
+        s390_program_interrupt(env, PGM_SPECIFICATION, 4, ra);
+    }
+
     for (i = r1;; i = (i + 1) % 16) {
         cpu_stl_data_ra(env, a2, env->aregs[i], ra);
         a2 += 4;
@@ -1620,6 +1629,10 @@ void HELPER(lctlg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
     uint64_t src = a2;
     uint32_t i;
 
+    if (src & 0x7) {
+        s390_program_interrupt(env, PGM_SPECIFICATION, 6, ra);
+    }
+
     for (i = r1;; i = (i + 1) % 16) {
         uint64_t val = cpu_ldq_data_ra(env, src, ra);
         if (env->cregs[i] != val && i >= 9 && i <= 11) {
@@ -1650,6 +1663,10 @@ void HELPER(lctl)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
     uint64_t src = a2;
     uint32_t i;
 
+    if (src & 0x3) {
+        s390_program_interrupt(env, PGM_SPECIFICATION, 4, ra);
+    }
+
     for (i = r1;; i = (i + 1) % 16) {
         uint32_t val = cpu_ldl_data_ra(env, src, ra);
         if ((uint32_t)env->cregs[i] != val && i >= 9 && i <= 11) {
@@ -1677,6 +1694,10 @@ void HELPER(stctg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
     uint64_t dest = a2;
     uint32_t i;
 
+    if (dest & 0x7) {
+        s390_program_interrupt(env, PGM_SPECIFICATION, 6, ra);
+    }
+
     for (i = r1;; i = (i + 1) % 16) {
         cpu_stq_data_ra(env, dest, env->cregs[i], ra);
         dest += sizeof(uint64_t);
@@ -1693,6 +1714,10 @@ void HELPER(stctl)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
     uint64_t dest = a2;
     uint32_t i;
 
+    if (dest & 0x3) {
+        s390_program_interrupt(env, PGM_SPECIFICATION, 4, ra);
+    }
+
     for (i = r1;; i = (i + 1) % 16) {
         cpu_stl_data_ra(env, dest, env->cregs[i], ra);
         dest += sizeof(uint32_t);
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index 5aea3bbca6..7d39ab350d 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -4062,7 +4062,6 @@ static ExitStatus op_stidp(DisasContext *s, DisasOps *o)
 {
     check_privileged(s);
     tcg_gen_ld_i64(o->out, cpu_env, offsetof(CPUS390XState, cpuid));
-    tcg_gen_qemu_st_i64(o->out, o->addr1, get_mem_index(s), MO_TEQ | MO_ALIGN);
     return NO_EXIT;
 }
 
@@ -5220,18 +5219,42 @@ static void wout_m1_16(DisasContext *s, DisasFields *f, DisasOps *o)
 }
 #define SPEC_wout_m1_16 0
 
+#ifndef CONFIG_USER_ONLY
+static void wout_m1_16a(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    tcg_gen_qemu_st_tl(o->out, o->addr1, get_mem_index(s), MO_TEUW | MO_ALIGN);
+}
+#define SPEC_wout_m1_16a 0
+#endif
+
 static void wout_m1_32(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     tcg_gen_qemu_st32(o->out, o->addr1, get_mem_index(s));
 }
 #define SPEC_wout_m1_32 0
 
+#ifndef CONFIG_USER_ONLY
+static void wout_m1_32a(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    tcg_gen_qemu_st_tl(o->out, o->addr1, get_mem_index(s), MO_TEUL | MO_ALIGN);
+}
+#define SPEC_wout_m1_32a 0
+#endif
+
 static void wout_m1_64(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     tcg_gen_qemu_st64(o->out, o->addr1, get_mem_index(s));
 }
 #define SPEC_wout_m1_64 0
 
+#ifndef CONFIG_USER_ONLY
+static void wout_m1_64a(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    tcg_gen_qemu_st_i64(o->out, o->addr1, get_mem_index(s), MO_TEQ | MO_ALIGN);
+}
+#define SPEC_wout_m1_64a 0
+#endif
+
 static void wout_m2_32(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     tcg_gen_qemu_st32(o->out, o->in2, get_mem_index(s));
@@ -5657,6 +5680,15 @@ static void in2_m2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
 }
 #define SPEC_in2_m2_32u 0
 
+#ifndef CONFIG_USER_ONLY
+static void in2_m2_32ua(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    in2_a2(s, f, o);
+    tcg_gen_qemu_ld_tl(o->in2, o->in2, get_mem_index(s), MO_TEUL | MO_ALIGN);
+}
+#define SPEC_in2_m2_32ua 0
+#endif
+
 static void in2_m2_64(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     in2_a2(s, f, o);
@@ -5664,6 +5696,15 @@ static void in2_m2_64(DisasContext *s, DisasFields *f, DisasOps *o)
 }
 #define SPEC_in2_m2_64 0
 
+#ifndef CONFIG_USER_ONLY
+static void in2_m2_64a(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    in2_a2(s, f, o);
+    tcg_gen_qemu_ld_i64(o->in2, o->in2, get_mem_index(s), MO_TEQ | MO_ALIGN);
+}
+#define SPEC_in2_m2_64a 0
+#endif
+
 static void in2_mri2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     in2_ri2(s, f, o);
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [Qemu-devel] [PULL v2 19/27] qmp: expose s390-specific CPU info
  2018-03-01 12:58 [Qemu-devel] [PULL v2 00/27] s390x updates (and friends) Cornelia Huck
                   ` (17 preceding siblings ...)
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 18/27] s390x/tcg: add various alignment checks Cornelia Huck
@ 2018-03-01 12:58 ` Cornelia Huck
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 20/27] qmp: add query-cpus-fast Cornelia Huck
                   ` (2 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: Cornelia Huck @ 2018-03-01 12:58 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-s390x, qemu-devel, borntraeger, rth, agraf, david, thuth,
	Viktor Mihajlovski, Cornelia Huck

From: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com>

Presently s390x is the only architecture not exposing specific
CPU information via QMP query-cpus. Upstream discussion has shown
that it could make sense to report the architecture specific CPU
state, e.g. to detect that a CPU has been stopped.

With this change the output of query-cpus will look like this on
s390:

   [
     {"arch": "s390", "current": true,
      "props": {"core-id": 0}, "cpu-state": "operating", "CPU": 0,
      "qom_path": "/machine/unattached/device[0]",
      "halted": false, "thread_id": 63115},
     {"arch": "s390", "current": false,
      "props": {"core-id": 1}, "cpu-state": "stopped", "CPU": 1,
      "qom_path": "/machine/unattached/device[1]",
      "halted": true, "thread_id": 63116}
   ]

This change doesn't add the s390-specific data to HMP 'info cpus'.
A follow-on patch will remove all architecture specific information
from there.

Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <1518797321-28356-2-git-send-email-mihajlov@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
 cpus.c                     |  6 ++++++
 hw/intc/s390_flic.c        |  4 ++--
 hw/s390x/s390-virtio-ccw.c |  2 +-
 qapi-schema.json           | 28 +++++++++++++++++++++++++++-
 target/s390x/cpu.c         | 24 ++++++++++++------------
 target/s390x/cpu.h         |  7 ++-----
 target/s390x/kvm.c         |  8 ++++----
 target/s390x/sigp.c        | 38 +++++++++++++++++++-------------------
 8 files changed, 73 insertions(+), 44 deletions(-)

diff --git a/cpus.c b/cpus.c
index f298b659f4..6006931d3a 100644
--- a/cpus.c
+++ b/cpus.c
@@ -2100,6 +2100,9 @@ CpuInfoList *qmp_query_cpus(Error **errp)
 #elif defined(TARGET_TRICORE)
         TriCoreCPU *tricore_cpu = TRICORE_CPU(cpu);
         CPUTriCoreState *env = &tricore_cpu->env;
+#elif defined(TARGET_S390X)
+        S390CPU *s390_cpu = S390_CPU(cpu);
+        CPUS390XState *env = &s390_cpu->env;
 #endif
 
         cpu_synchronize_state(cpu);
@@ -2127,6 +2130,9 @@ CpuInfoList *qmp_query_cpus(Error **errp)
 #elif defined(TARGET_TRICORE)
         info->value->arch = CPU_INFO_ARCH_TRICORE;
         info->value->u.tricore.PC = env->PC;
+#elif defined(TARGET_S390X)
+        info->value->arch = CPU_INFO_ARCH_S390;
+        info->value->u.s390.cpu_state = env->cpu_state;
 #else
         info->value->arch = CPU_INFO_ARCH_OTHER;
 #endif
diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c
index a85a149c6d..5f8168f0f0 100644
--- a/hw/intc/s390_flic.c
+++ b/hw/intc/s390_flic.c
@@ -192,8 +192,8 @@ static void qemu_s390_flic_notify(uint32_t type)
         cs->interrupt_request |= CPU_INTERRUPT_HARD;
 
         /* ignore CPUs that are not sleeping */
-        if (s390_cpu_get_state(cpu) != CPU_STATE_OPERATING &&
-            s390_cpu_get_state(cpu) != CPU_STATE_LOAD) {
+        if (s390_cpu_get_state(cpu) != S390_CPU_STATE_OPERATING &&
+            s390_cpu_get_state(cpu) != S390_CPU_STATE_LOAD) {
             continue;
         }
 
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 4abbe89847..4d0c3deba6 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -368,7 +368,7 @@ static void s390_machine_reset(void)
 
     /* all cpus are stopped - configure and start the ipl cpu only */
     s390_ipl_prepare_cpu(ipl_cpu);
-    s390_cpu_set_state(CPU_STATE_OPERATING, ipl_cpu);
+    s390_cpu_set_state(S390_CPU_STATE_OPERATING, ipl_cpu);
 }
 
 static void s390_machine_device_plug(HotplugHandler *hotplug_dev,
diff --git a/qapi-schema.json b/qapi-schema.json
index 0262b9f20b..94d560ed13 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -410,10 +410,12 @@
 # An enumeration of cpu types that enable additional information during
 # @query-cpus.
 #
+# @s390: since 2.12
+#
 # Since: 2.6
 ##
 { 'enum': 'CpuInfoArch',
-  'data': ['x86', 'sparc', 'ppc', 'mips', 'tricore', 'other' ] }
+  'data': ['x86', 'sparc', 'ppc', 'mips', 'tricore', 's390', 'other' ] }
 
 ##
 # @CpuInfo:
@@ -452,6 +454,7 @@
             'ppc': 'CpuInfoPPC',
             'mips': 'CpuInfoMIPS',
             'tricore': 'CpuInfoTricore',
+            's390': 'CpuInfoS390',
             'other': 'CpuInfoOther' } }
 
 ##
@@ -522,6 +525,29 @@
 { 'struct': 'CpuInfoOther', 'data': { } }
 
 ##
+# @CpuS390State:
+#
+# An enumeration of cpu states that can be assumed by a virtual
+# S390 CPU
+#
+# Since: 2.12
+##
+{ 'enum': 'CpuS390State',
+  'prefix': 'S390_CPU_STATE',
+  'data': [ 'uninitialized', 'stopped', 'check-stop', 'operating', 'load' ] }
+
+##
+# @CpuInfoS390:
+#
+# Additional information about a virtual S390 CPU
+#
+# @cpu-state: the virtual CPU's state
+#
+# Since: 2.12
+##
+{ 'struct': 'CpuInfoS390', 'data': { 'cpu-state': 'CpuS390State' } }
+
+##
 # @query-cpus:
 #
 # Returns a list of information about each virtual CPU.
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
index 3e1be56536..f02ed19c70 100644
--- a/target/s390x/cpu.c
+++ b/target/s390x/cpu.c
@@ -61,8 +61,8 @@ static bool s390_cpu_has_work(CPUState *cs)
     S390CPU *cpu = S390_CPU(cs);
 
     /* STOPPED cpus can never wake up */
-    if (s390_cpu_get_state(cpu) != CPU_STATE_LOAD &&
-        s390_cpu_get_state(cpu) != CPU_STATE_OPERATING) {
+    if (s390_cpu_get_state(cpu) != S390_CPU_STATE_LOAD &&
+        s390_cpu_get_state(cpu) != S390_CPU_STATE_OPERATING) {
         return false;
     }
 
@@ -80,7 +80,7 @@ static void s390_cpu_load_normal(CPUState *s)
     S390CPU *cpu = S390_CPU(s);
     cpu->env.psw.addr = ldl_phys(s->as, 4) & PSW_MASK_ESA_ADDR;
     cpu->env.psw.mask = PSW_MASK_32 | PSW_MASK_64;
-    s390_cpu_set_state(CPU_STATE_OPERATING, cpu);
+    s390_cpu_set_state(S390_CPU_STATE_OPERATING, cpu);
 }
 #endif
 
@@ -95,7 +95,7 @@ static void s390_cpu_reset(CPUState *s)
     env->bpbc = false;
     scc->parent_reset(s);
     cpu->env.sigp_order = 0;
-    s390_cpu_set_state(CPU_STATE_STOPPED, cpu);
+    s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu);
 }
 
 /* S390CPUClass::initial_reset() */
@@ -138,7 +138,7 @@ static void s390_cpu_full_reset(CPUState *s)
 
     scc->parent_reset(s);
     cpu->env.sigp_order = 0;
-    s390_cpu_set_state(CPU_STATE_STOPPED, cpu);
+    s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu);
 
     memset(env, 0, offsetof(CPUS390XState, end_reset_fields));
 
@@ -292,7 +292,7 @@ static void s390_cpu_initfn(Object *obj)
     env->tod_basetime = 0;
     env->tod_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, s390x_tod_timer, cpu);
     env->cpu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, s390x_cpu_timer, cpu);
-    s390_cpu_set_state(CPU_STATE_STOPPED, cpu);
+    s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu);
 #endif
 }
 
@@ -320,8 +320,8 @@ static unsigned s390_count_running_cpus(void)
 
     CPU_FOREACH(cpu) {
         uint8_t state = S390_CPU(cpu)->env.cpu_state;
-        if (state == CPU_STATE_OPERATING ||
-            state == CPU_STATE_LOAD) {
+        if (state == S390_CPU_STATE_OPERATING ||
+            state == S390_CPU_STATE_LOAD) {
             if (!disabled_wait(cpu)) {
                 nr_running++;
             }
@@ -360,13 +360,13 @@ unsigned int s390_cpu_set_state(uint8_t cpu_state, S390CPU *cpu)
     trace_cpu_set_state(CPU(cpu)->cpu_index, cpu_state);
 
     switch (cpu_state) {
-    case CPU_STATE_STOPPED:
-    case CPU_STATE_CHECK_STOP:
+    case S390_CPU_STATE_STOPPED:
+    case S390_CPU_STATE_CHECK_STOP:
         /* halt the cpu for common infrastructure */
         s390_cpu_halt(cpu);
         break;
-    case CPU_STATE_OPERATING:
-    case CPU_STATE_LOAD:
+    case S390_CPU_STATE_OPERATING:
+    case S390_CPU_STATE_LOAD:
         /*
          * Starting a CPU with a PSW WAIT bit set:
          * KVM: handles this internally and triggers another WAIT exit.
diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
index d4641663ef..802324b3e2 100644
--- a/target/s390x/cpu.h
+++ b/target/s390x/cpu.h
@@ -141,12 +141,9 @@ struct CPUS390XState {
      * architectures, there is a difference between a halt and a stop on s390.
      * If all cpus are either stopped (including check stop) or in the disabled
      * wait state, the vm can be shut down.
+     * The acceptable cpu_state values are defined in the CpuInfoS390State
+     * enum.
      */
-#define CPU_STATE_UNINITIALIZED        0x00
-#define CPU_STATE_STOPPED              0x01
-#define CPU_STATE_CHECK_STOP           0x02
-#define CPU_STATE_OPERATING            0x03
-#define CPU_STATE_LOAD                 0x04
     uint8_t cpu_state;
 
     /* currently processed sigp order */
diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c
index 83e4eaf45d..8ef509ece4 100644
--- a/target/s390x/kvm.c
+++ b/target/s390x/kvm.c
@@ -1880,16 +1880,16 @@ int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state)
     }
 
     switch (cpu_state) {
-    case CPU_STATE_STOPPED:
+    case S390_CPU_STATE_STOPPED:
         mp_state.mp_state = KVM_MP_STATE_STOPPED;
         break;
-    case CPU_STATE_CHECK_STOP:
+    case S390_CPU_STATE_CHECK_STOP:
         mp_state.mp_state = KVM_MP_STATE_CHECK_STOP;
         break;
-    case CPU_STATE_OPERATING:
+    case S390_CPU_STATE_OPERATING:
         mp_state.mp_state = KVM_MP_STATE_OPERATING;
         break;
-    case CPU_STATE_LOAD:
+    case S390_CPU_STATE_LOAD:
         mp_state.mp_state = KVM_MP_STATE_LOAD;
         break;
     default:
diff --git a/target/s390x/sigp.c b/target/s390x/sigp.c
index ac3f8e7dc2..5a7a9c4cfb 100644
--- a/target/s390x/sigp.c
+++ b/target/s390x/sigp.c
@@ -46,13 +46,13 @@ static void sigp_sense(S390CPU *dst_cpu, SigpInfo *si)
     }
 
     /* sensing without locks is racy, but it's the same for real hw */
-    if (state != CPU_STATE_STOPPED && !ext_call) {
+    if (state != S390_CPU_STATE_STOPPED && !ext_call) {
         si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
     } else {
         if (ext_call) {
             status |= SIGP_STAT_EXT_CALL_PENDING;
         }
-        if (state == CPU_STATE_STOPPED) {
+        if (state == S390_CPU_STATE_STOPPED) {
             status |= SIGP_STAT_STOPPED;
         }
         set_sigp_status(si, status);
@@ -94,12 +94,12 @@ static void sigp_start(CPUState *cs, run_on_cpu_data arg)
     S390CPU *cpu = S390_CPU(cs);
     SigpInfo *si = arg.host_ptr;
 
-    if (s390_cpu_get_state(cpu) != CPU_STATE_STOPPED) {
+    if (s390_cpu_get_state(cpu) != S390_CPU_STATE_STOPPED) {
         si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
         return;
     }
 
-    s390_cpu_set_state(CPU_STATE_OPERATING, cpu);
+    s390_cpu_set_state(S390_CPU_STATE_OPERATING, cpu);
     si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
 }
 
@@ -108,14 +108,14 @@ static void sigp_stop(CPUState *cs, run_on_cpu_data arg)
     S390CPU *cpu = S390_CPU(cs);
     SigpInfo *si = arg.host_ptr;
 
-    if (s390_cpu_get_state(cpu) != CPU_STATE_OPERATING) {
+    if (s390_cpu_get_state(cpu) != S390_CPU_STATE_OPERATING) {
         si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
         return;
     }
 
     /* disabled wait - sleeping in user space */
     if (cs->halted) {
-        s390_cpu_set_state(CPU_STATE_STOPPED, cpu);
+        s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu);
     } else {
         /* execute the stop function */
         cpu->env.sigp_order = SIGP_STOP;
@@ -130,17 +130,17 @@ static void sigp_stop_and_store_status(CPUState *cs, run_on_cpu_data arg)
     SigpInfo *si = arg.host_ptr;
 
     /* disabled wait - sleeping in user space */
-    if (s390_cpu_get_state(cpu) == CPU_STATE_OPERATING && cs->halted) {
-        s390_cpu_set_state(CPU_STATE_STOPPED, cpu);
+    if (s390_cpu_get_state(cpu) == S390_CPU_STATE_OPERATING && cs->halted) {
+        s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu);
     }
 
     switch (s390_cpu_get_state(cpu)) {
-    case CPU_STATE_OPERATING:
+    case S390_CPU_STATE_OPERATING:
         cpu->env.sigp_order = SIGP_STOP_STORE_STATUS;
         cpu_inject_stop(cpu);
         /* store will be performed in do_stop_interrup() */
         break;
-    case CPU_STATE_STOPPED:
+    case S390_CPU_STATE_STOPPED:
         /* already stopped, just store the status */
         cpu_synchronize_state(cs);
         s390_store_status(cpu, S390_STORE_STATUS_DEF_ADDR, true);
@@ -156,7 +156,7 @@ static void sigp_store_status_at_address(CPUState *cs, run_on_cpu_data arg)
     uint32_t address = si->param & 0x7ffffe00u;
 
     /* cpu has to be stopped */
-    if (s390_cpu_get_state(cpu) != CPU_STATE_STOPPED) {
+    if (s390_cpu_get_state(cpu) != S390_CPU_STATE_STOPPED) {
         set_sigp_status(si, SIGP_STAT_INCORRECT_STATE);
         return;
     }
@@ -186,7 +186,7 @@ static void sigp_store_adtl_status(CPUState *cs, run_on_cpu_data arg)
     }
 
     /* cpu has to be stopped */
-    if (s390_cpu_get_state(cpu) != CPU_STATE_STOPPED) {
+    if (s390_cpu_get_state(cpu) != S390_CPU_STATE_STOPPED) {
         set_sigp_status(si, SIGP_STAT_INCORRECT_STATE);
         return;
     }
@@ -229,17 +229,17 @@ static void sigp_restart(CPUState *cs, run_on_cpu_data arg)
     SigpInfo *si = arg.host_ptr;
 
     switch (s390_cpu_get_state(cpu)) {
-    case CPU_STATE_STOPPED:
+    case S390_CPU_STATE_STOPPED:
         /* the restart irq has to be delivered prior to any other pending irq */
         cpu_synchronize_state(cs);
         /*
          * Set OPERATING (and unhalting) before loading the restart PSW.
          * load_psw() will then properly halt the CPU again if necessary (TCG).
          */
-        s390_cpu_set_state(CPU_STATE_OPERATING, cpu);
+        s390_cpu_set_state(S390_CPU_STATE_OPERATING, cpu);
         do_restart_interrupt(&cpu->env);
         break;
-    case CPU_STATE_OPERATING:
+    case S390_CPU_STATE_OPERATING:
         cpu_inject_restart(cpu);
         break;
     }
@@ -285,7 +285,7 @@ static void sigp_set_prefix(CPUState *cs, run_on_cpu_data arg)
     }
 
     /* cpu has to be stopped */
-    if (s390_cpu_get_state(cpu) != CPU_STATE_STOPPED) {
+    if (s390_cpu_get_state(cpu) != S390_CPU_STATE_STOPPED) {
         set_sigp_status(si, SIGP_STAT_INCORRECT_STATE);
         return;
     }
@@ -318,7 +318,7 @@ static void sigp_cond_emergency(S390CPU *src_cpu, S390CPU *dst_cpu,
     p_asn = dst_cpu->env.cregs[4] & 0xffff;  /* Primary ASN */
     s_asn = dst_cpu->env.cregs[3] & 0xffff;  /* Secondary ASN */
 
-    if (s390_cpu_get_state(dst_cpu) != CPU_STATE_STOPPED ||
+    if (s390_cpu_get_state(dst_cpu) != S390_CPU_STATE_STOPPED ||
         (psw_mask & psw_int_mask) != psw_int_mask ||
         (idle && psw_addr != 0) ||
         (!idle && (asn == p_asn || asn == s_asn))) {
@@ -435,7 +435,7 @@ static int sigp_set_architecture(S390CPU *cpu, uint32_t param,
         if (cur_cpu == cpu) {
             continue;
         }
-        if (s390_cpu_get_state(cur_cpu) != CPU_STATE_STOPPED) {
+        if (s390_cpu_get_state(cur_cpu) != S390_CPU_STATE_STOPPED) {
             all_stopped = false;
         }
     }
@@ -492,7 +492,7 @@ void do_stop_interrupt(CPUS390XState *env)
 {
     S390CPU *cpu = s390_env_get_cpu(env);
 
-    if (s390_cpu_set_state(CPU_STATE_STOPPED, cpu) == 0) {
+    if (s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu) == 0) {
         qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
     }
     if (cpu->env.sigp_order == SIGP_STOP_STORE_STATUS) {
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [Qemu-devel] [PULL v2 20/27] qmp: add query-cpus-fast
  2018-03-01 12:58 [Qemu-devel] [PULL v2 00/27] s390x updates (and friends) Cornelia Huck
                   ` (18 preceding siblings ...)
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 19/27] qmp: expose s390-specific CPU info Cornelia Huck
@ 2018-03-01 12:58 ` Cornelia Huck
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 21/27] qmp: add architecture specific cpu data for query-cpus-fast Cornelia Huck
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 22/27] qemu-doc: deprecate query-cpus Cornelia Huck
  21 siblings, 0 replies; 24+ messages in thread
From: Cornelia Huck @ 2018-03-01 12:58 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-s390x, qemu-devel, borntraeger, rth, agraf, david, thuth,
	Luiz Capitulino, Viktor Mihajlovski, Cornelia Huck

From: Luiz Capitulino <lcapitulino@redhat.com>

The query-cpus command has an extremely serious side effect:
it always interrupts all running vCPUs so that they can run
ioctl calls. This can cause a huge performance degradation for
some workloads. And most of the information retrieved by the
ioctl calls are not even used by query-cpus.

This commit introduces a replacement for query-cpus called
query-cpus-fast, which has the following features:

 o Never interrupt vCPUs threads. query-cpus-fast only returns
   vCPU information maintained by QEMU itself, which should be
   sufficient for most management software needs

 o Drop "halted" field as it can not be retrieved in a fast
   way on most architectures

 o Drop irrelevant fields such as "current", "pc" and "arch"

 o Rename some fields for better clarification & proper naming
   standard

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com>
Message-Id: <1518797321-28356-3-git-send-email-mihajlov@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
 cpus.c           | 38 ++++++++++++++++++++++++++++++
 qapi-schema.json | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 108 insertions(+)

diff --git a/cpus.c b/cpus.c
index 6006931d3a..6df6660ccf 100644
--- a/cpus.c
+++ b/cpus.c
@@ -2156,6 +2156,44 @@ CpuInfoList *qmp_query_cpus(Error **errp)
     return head;
 }
 
+/*
+ * fast means: we NEVER interrupt vCPU threads to retrieve
+ * information from KVM.
+ */
+CpuInfoFastList *qmp_query_cpus_fast(Error **errp)
+{
+    MachineState *ms = MACHINE(qdev_get_machine());
+    MachineClass *mc = MACHINE_GET_CLASS(ms);
+    CpuInfoFastList *head = NULL, *cur_item = NULL;
+    CPUState *cpu;
+
+    CPU_FOREACH(cpu) {
+        CpuInfoFastList *info = g_malloc0(sizeof(*info));
+        info->value = g_malloc0(sizeof(*info->value));
+
+        info->value->cpu_index = cpu->cpu_index;
+        info->value->qom_path = object_get_canonical_path(OBJECT(cpu));
+        info->value->thread_id = cpu->thread_id;
+
+        info->value->has_props = !!mc->cpu_index_to_instance_props;
+        if (info->value->has_props) {
+            CpuInstanceProperties *props;
+            props = g_malloc0(sizeof(*props));
+            *props = mc->cpu_index_to_instance_props(ms, cpu->cpu_index);
+            info->value->props = props;
+        }
+
+        if (!cur_item) {
+            head = cur_item = info;
+        } else {
+            cur_item->next = info;
+            cur_item = info;
+        }
+    }
+
+    return head;
+}
+
 void qmp_memsave(int64_t addr, int64_t size, const char *filename,
                  bool has_cpu, int64_t cpu_index, Error **errp)
 {
diff --git a/qapi-schema.json b/qapi-schema.json
index 94d560ed13..815f072876 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -552,6 +552,12 @@
 #
 # Returns a list of information about each virtual CPU.
 #
+# This command causes vCPU threads to exit to userspace, which causes
+# a small interruption to guest CPU execution. This will have a negative
+# impact on realtime guests and other latency sensitive guest workloads.
+# It is recommended to use @query-cpus-fast instead of this command to
+# avoid the vCPU interruption.
+#
 # Returns: a list of @CpuInfo for each virtual CPU
 #
 # Since: 0.14.0
@@ -585,6 +591,70 @@
 { 'command': 'query-cpus', 'returns': ['CpuInfo'] }
 
 ##
+# @CpuInfoFast:
+#
+# Information about a virtual CPU
+#
+# @cpu-index: index of the virtual CPU
+#
+# @qom-path: path to the CPU object in the QOM tree
+#
+# @thread-id: ID of the underlying host thread
+#
+# @props: properties describing to which node/socket/core/thread
+#         virtual CPU belongs to, provided if supported by board
+#
+# Since: 2.12
+#
+##
+{ 'struct': 'CpuInfoFast',
+  'data': {'cpu-index': 'int', 'qom-path': 'str',
+           'thread-id': 'int', '*props': 'CpuInstanceProperties' } }
+
+##
+# @query-cpus-fast:
+#
+# Returns information about all virtual CPUs. This command does not
+# incur a performance penalty and should be used in production
+# instead of query-cpus.
+#
+# Returns: list of @CpuInfoFast
+#
+# Notes: The CPU architecture name is not returned by query-cpus-fast.
+#        Use query-target to retrieve that information.
+#
+# Since: 2.12
+#
+# Example:
+#
+# -> { "execute": "query-cpus-fast" }
+# <- { "return": [
+#         {
+#             "thread-id": 25627,
+#             "props": {
+#                 "core-id": 0,
+#                 "thread-id": 0,
+#                 "socket-id": 0
+#             },
+#             "qom-path": "/machine/unattached/device[0]",
+#             "cpu-index": 0
+#         },
+#         {
+#             "thread-id": 25628,
+#             "props": {
+#                 "core-id": 0,
+#                 "thread-id": 0,
+#                 "socket-id": 1
+#             },
+#             "qom-path": "/machine/unattached/device[2]",
+#             "cpu-index": 1
+#         }
+#     ]
+# }
+##
+{ 'command': 'query-cpus-fast', 'returns': [ 'CpuInfoFast' ] }
+
+##
 # @IOThreadInfo:
 #
 # Information about an iothread
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [Qemu-devel] [PULL v2 21/27] qmp: add architecture specific cpu data for query-cpus-fast
  2018-03-01 12:58 [Qemu-devel] [PULL v2 00/27] s390x updates (and friends) Cornelia Huck
                   ` (19 preceding siblings ...)
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 20/27] qmp: add query-cpus-fast Cornelia Huck
@ 2018-03-01 12:58 ` Cornelia Huck
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 22/27] qemu-doc: deprecate query-cpus Cornelia Huck
  21 siblings, 0 replies; 24+ messages in thread
From: Cornelia Huck @ 2018-03-01 12:58 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-s390x, qemu-devel, borntraeger, rth, agraf, david, thuth,
	Viktor Mihajlovski, Cornelia Huck

From: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com>

The s390 CPU state can be retrieved without interrupting the
VM execution. Extendend the CpuInfoFast union with architecture
specific data and an implementation for s390.

Return data looks like this:
 [
   {"thread-id":64301,"props":{"core-id":0},
    "arch":"s390","cpu-state":"operating",
    "qom-path":"/machine/unattached/device[0]","cpu-index":0},
   {"thread-id":64302,"props":{"core-id":1},
    "arch":"s390","cpu-state":"operating",
    "qom-path":"/machine/unattached/device[1]","cpu-index":1}
]

Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <1518797321-28356-4-git-send-email-mihajlov@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
 cpus.c           | 10 ++++++++++
 qapi-schema.json | 25 ++++++++++++++++++-------
 2 files changed, 28 insertions(+), 7 deletions(-)

diff --git a/cpus.c b/cpus.c
index 6df6660ccf..af678264f6 100644
--- a/cpus.c
+++ b/cpus.c
@@ -2166,6 +2166,10 @@ CpuInfoFastList *qmp_query_cpus_fast(Error **errp)
     MachineClass *mc = MACHINE_GET_CLASS(ms);
     CpuInfoFastList *head = NULL, *cur_item = NULL;
     CPUState *cpu;
+#if defined(TARGET_S390X)
+    S390CPU *s390_cpu;
+    CPUS390XState *env;
+#endif
 
     CPU_FOREACH(cpu) {
         CpuInfoFastList *info = g_malloc0(sizeof(*info));
@@ -2183,6 +2187,12 @@ CpuInfoFastList *qmp_query_cpus_fast(Error **errp)
             info->value->props = props;
         }
 
+#if defined(TARGET_S390X)
+        s390_cpu = S390_CPU(cpu);
+        env = &s390_cpu->env;
+        info->value->arch = CPU_INFO_ARCH_S390;
+        info->value->u.s390.cpu_state = env->cpu_state;
+#endif
         if (!cur_item) {
             head = cur_item = info;
         } else {
diff --git a/qapi-schema.json b/qapi-schema.json
index 815f072876..e6ca63f718 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -408,7 +408,7 @@
 # @CpuInfoArch:
 #
 # An enumeration of cpu types that enable additional information during
-# @query-cpus.
+# @query-cpus and @query-cpus-fast.
 #
 # @s390: since 2.12
 #
@@ -604,12 +604,24 @@
 # @props: properties describing to which node/socket/core/thread
 #         virtual CPU belongs to, provided if supported by board
 #
+# @arch: architecture of the cpu, which determines which additional fields
+#        will be listed
+#
 # Since: 2.12
 #
 ##
-{ 'struct': 'CpuInfoFast',
-  'data': {'cpu-index': 'int', 'qom-path': 'str',
-           'thread-id': 'int', '*props': 'CpuInstanceProperties' } }
+{ 'union': 'CpuInfoFast',
+  'base': {'cpu-index': 'int', 'qom-path': 'str',
+           'thread-id': 'int', '*props': 'CpuInstanceProperties',
+           'arch': 'CpuInfoArch' },
+  'discriminator': 'arch',
+  'data': { 'x86': 'CpuInfoOther',
+            'sparc': 'CpuInfoOther',
+            'ppc': 'CpuInfoOther',
+            'mips': 'CpuInfoOther',
+            'tricore': 'CpuInfoOther',
+            's390': 'CpuInfoS390',
+            'other': 'CpuInfoOther' } }
 
 ##
 # @query-cpus-fast:
@@ -620,9 +632,6 @@
 #
 # Returns: list of @CpuInfoFast
 #
-# Notes: The CPU architecture name is not returned by query-cpus-fast.
-#        Use query-target to retrieve that information.
-#
 # Since: 2.12
 #
 # Example:
@@ -637,6 +646,7 @@
 #                 "socket-id": 0
 #             },
 #             "qom-path": "/machine/unattached/device[0]",
+#             "arch":"x86",
 #             "cpu-index": 0
 #         },
 #         {
@@ -647,6 +657,7 @@
 #                 "socket-id": 1
 #             },
 #             "qom-path": "/machine/unattached/device[2]",
+#             "arch":"x86",
 #             "cpu-index": 1
 #         }
 #     ]
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [Qemu-devel] [PULL v2 22/27] qemu-doc: deprecate query-cpus
  2018-03-01 12:58 [Qemu-devel] [PULL v2 00/27] s390x updates (and friends) Cornelia Huck
                   ` (20 preceding siblings ...)
  2018-03-01 12:58 ` [Qemu-devel] [PULL v2 21/27] qmp: add architecture specific cpu data for query-cpus-fast Cornelia Huck
@ 2018-03-01 12:58 ` Cornelia Huck
  21 siblings, 0 replies; 24+ messages in thread
From: Cornelia Huck @ 2018-03-01 12:58 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-s390x, qemu-devel, borntraeger, rth, agraf, david, thuth,
	Viktor Mihajlovski, Cornelia Huck

From: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com>

Start the deprecation period for QAPI query-cpus (replaced by
query-cpus-fast) beginning with 2.12.0.

Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <1518797321-28356-5-git-send-email-mihajlov@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
 qapi-schema.json | 4 ++++
 qemu-doc.texi    | 4 ++++
 2 files changed, 8 insertions(+)

diff --git a/qapi-schema.json b/qapi-schema.json
index e6ca63f718..cd98a94388 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -587,6 +587,10 @@
 #       ]
 #    }
 #
+# Notes: This interface is deprecated (since 2.12.0), and it is strongly
+#        recommended that you avoid using it. Use @query-cpus-fast to
+#        obtain information about virtual CPUs.
+#
 ##
 { 'command': 'query-cpus', 'returns': ['CpuInfo'] }
 
diff --git a/qemu-doc.texi b/qemu-doc.texi
index 8e3556976b..b3c2763624 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -2762,6 +2762,10 @@ by the ``convert -l snapshot_param'' argument instead.
 "autoload" parameter is now ignored. All bitmaps are automatically loaded
 from qcow2 images.
 
+@subsection query-cpus (since 2.12.0)
+
+The ``query-cpus'' command is replaced by the ``query-cpus-fast'' command.
+
 @section System emulator human monitor commands
 
 @subsection host_net_add (since 2.10.0)
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [Qemu-devel] [PULL v2 12/27] s390-ccw: use zipl values when no boot menu options are present
  2018-03-01 13:01 [Qemu-devel] [PULL v2 00/27] s390x updates (and friends) Cornelia Huck
@ 2018-03-01 13:01 ` Cornelia Huck
  0 siblings, 0 replies; 24+ messages in thread
From: Cornelia Huck @ 2018-03-01 13:01 UTC (permalink / raw)
  To: peter.maydell
  Cc: qemu-s390x, qemu-devel, borntraeger, rth, agraf, david, thuth,
	Collin L. Walling

From: "Collin L. Walling" <walling@linux.vnet.ibm.com>

If no boot menu options are present, then flag the boot menu to
use the zipl options that were set in the zipl configuration file
(and stored on disk by zipl). These options are found at some
offset prior to the start of the zipl boot menu banner. The zipl
timeout value is limited to a 16-bit unsigned integer and stored
as seconds, so we take care to convert it to milliseconds in order
to conform to the rest of the boot menu functionality. This is
limited to CCW devices.

For reference, the zipl configuration file uses the following
fields in the menu section:

      prompt=1      enable the boot menu
      timeout=X     set the timeout to X seconds

To explicitly disregard any boot menu options, then menu=off or
<bootmenu enable='no' ... /> must be specified.

Signed-off-by: Collin L. Walling <walling@linux.vnet.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 hw/s390x/ipl.c          |  5 +++++
 hw/s390x/ipl.h          |  1 +
 pc-bios/s390-ccw/iplb.h |  1 +
 pc-bios/s390-ccw/main.c |  3 ++-
 pc-bios/s390-ccw/menu.c | 16 +++++++++++++++-
 5 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index ee2039dc69..c12e460a7f 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -241,6 +241,11 @@ static void s390_ipl_set_boot_menu(S390IPLState *ipl)
 
     switch (ipl->iplb.pbt) {
     case S390_IPL_TYPE_CCW:
+        /* In the absence of -boot menu, use zipl parameters */
+        if (!qemu_opt_get(opts, "menu")) {
+            *flags |= QIPL_FLAG_BM_OPTS_ZIPL;
+            return;
+        }
         break;
     default:
         error_report("boot menu is not supported for this device type.");
diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h
index d6c6f75b76..0570d0ad75 100644
--- a/hw/s390x/ipl.h
+++ b/hw/s390x/ipl.h
@@ -93,6 +93,7 @@ void s390_reipl_request(void);
 
 /* Boot Menu flags */
 #define QIPL_FLAG_BM_OPTS_CMD   0x80
+#define QIPL_FLAG_BM_OPTS_ZIPL  0x40
 
 /*
  * The QEMU IPL Parameters will be stored at absolute address
diff --git a/pc-bios/s390-ccw/iplb.h b/pc-bios/s390-ccw/iplb.h
index 832bb94440..7dfce4fbcf 100644
--- a/pc-bios/s390-ccw/iplb.h
+++ b/pc-bios/s390-ccw/iplb.h
@@ -76,6 +76,7 @@ extern IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE)));
 
 /* Boot Menu flags */
 #define QIPL_FLAG_BM_OPTS_CMD   0x80
+#define QIPL_FLAG_BM_OPTS_ZIPL  0x40
 
 /*
  * This definition must be kept in sync with the defininition
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index 32ed70ebdd..a7473b0397 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -20,6 +20,7 @@ QemuIplParameters qipl;
 
 #define LOADPARM_PROMPT "PROMPT  "
 #define LOADPARM_EMPTY  "........"
+#define BOOT_MENU_FLAG_MASK (QIPL_FLAG_BM_OPTS_CMD | QIPL_FLAG_BM_OPTS_ZIPL)
 
 /*
  * Priniciples of Operations (SA22-7832-09) chapter 17 requires that
@@ -91,7 +92,7 @@ static void menu_setup(void)
 
     switch (iplb.pbt) {
     case S390_IPL_TYPE_CCW:
-        menu_set_parms(qipl.qipl_flags & QIPL_FLAG_BM_OPTS_CMD,
+        menu_set_parms(qipl.qipl_flags & BOOT_MENU_FLAG_MASK,
                        qipl.boot_menu_timeout);
         return;
     }
diff --git a/pc-bios/s390-ccw/menu.c b/pc-bios/s390-ccw/menu.c
index 8d55869448..ee56939c21 100644
--- a/pc-bios/s390-ccw/menu.c
+++ b/pc-bios/s390-ccw/menu.c
@@ -18,6 +18,10 @@
 #define KEYCODE_BACKSP '\177'
 #define KEYCODE_ENTER  '\r'
 
+/* Offsets from zipl fields to zipl banner start */
+#define ZIPL_TIMEOUT_OFFSET 138
+#define ZIPL_FLAG_OFFSET    140
+
 #define TOD_CLOCK_MILLISECOND   0x3e8000
 
 #define LOW_CORE_EXTERNAL_INT_ADDR   0x86
@@ -187,6 +191,16 @@ int menu_get_zipl_boot_index(const char *menu_data)
 {
     size_t len;
     int entries;
+    uint16_t zipl_flag = *(uint16_t *)(menu_data - ZIPL_FLAG_OFFSET);
+    uint16_t zipl_timeout = *(uint16_t *)(menu_data - ZIPL_TIMEOUT_OFFSET);
+
+    if (flag == QIPL_FLAG_BM_OPTS_ZIPL) {
+        if (!zipl_flag) {
+            return 0; /* Boot default */
+        }
+        /* zipl stores timeout as seconds */
+        timeout = zipl_timeout * 1000;
+    }
 
     /* Print and count all menu items, including the banner */
     for (entries = 0; *menu_data; entries++) {
@@ -211,5 +225,5 @@ void menu_set_parms(uint8_t boot_menu_flag, uint32_t boot_menu_timeout)
 
 bool menu_is_enabled_zipl(void)
 {
-    return flag & QIPL_FLAG_BM_OPTS_CMD;
+    return flag & (QIPL_FLAG_BM_OPTS_CMD | QIPL_FLAG_BM_OPTS_ZIPL);
 }
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2018-03-01 13:02 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-03-01 12:58 [Qemu-devel] [PULL v2 00/27] s390x updates (and friends) Cornelia Huck
2018-03-01 12:58 ` [Qemu-devel] [PULL v2 01/27] s390-ccw: refactor boot map table code Cornelia Huck
2018-03-01 12:58 ` [Qemu-devel] [PULL v2 02/27] s390-ccw: refactor eckd_block_num to use CHS Cornelia Huck
2018-03-01 12:58 ` [Qemu-devel] [PULL v2 03/27] s390-ccw: refactor IPL structs Cornelia Huck
2018-03-01 12:58 ` [Qemu-devel] [PULL v2 04/27] s390-ccw: update libc Cornelia Huck
2018-03-01 12:58 ` [Qemu-devel] [PULL v2 05/27] s390-ccw: move auxiliary IPL data to separate location Cornelia Huck
2018-03-01 12:58 ` [Qemu-devel] [PULL v2 06/27] s390-ccw: parse and set boot menu options Cornelia Huck
2018-03-01 12:58 ` [Qemu-devel] [PULL v2 07/27] s390-ccw: set up interactive boot menu parameters Cornelia Huck
2018-03-01 12:58 ` [Qemu-devel] [PULL v2 08/27] s390-ccw: read stage2 boot loader data to find menu Cornelia Huck
2018-03-01 12:58 ` [Qemu-devel] [PULL v2 09/27] s390-ccw: print zipl boot menu Cornelia Huck
2018-03-01 12:58 ` [Qemu-devel] [PULL v2 10/27] s390-ccw: read user input for boot index via the SCLP console Cornelia Huck
2018-03-01 12:58 ` [Qemu-devel] [PULL v2 11/27] s390-ccw: set cp_receive mask only when needed and consume pending service irqs Cornelia Huck
2018-03-01 12:58 ` [Qemu-devel] [PULL v2 12/27] s390-ccw: use zipl values when no boot menu options are present Cornelia Huck
2018-03-01 12:58 ` [Qemu-devel] [PULL v2 13/27] s390-ccw: interactive boot menu for scsi Cornelia Huck
2018-03-01 12:58 ` [Qemu-devel] [PULL v2 14/27] pc-bios/s390: Rebuild the s390x firmware images with the boot menu changes Cornelia Huck
2018-03-01 12:58 ` [Qemu-devel] [PULL v2 15/27] s390x/cpu: expose the guest crash information Cornelia Huck
2018-03-01 12:58 ` [Qemu-devel] [PULL v2 16/27] s390/stattrib: Make SaveVMHandlers data static Cornelia Huck
2018-03-01 12:58 ` [Qemu-devel] [PULL v2 17/27] s390x/tcg: fix disabling/enabling DAT Cornelia Huck
2018-03-01 12:58 ` [Qemu-devel] [PULL v2 18/27] s390x/tcg: add various alignment checks Cornelia Huck
2018-03-01 12:58 ` [Qemu-devel] [PULL v2 19/27] qmp: expose s390-specific CPU info Cornelia Huck
2018-03-01 12:58 ` [Qemu-devel] [PULL v2 20/27] qmp: add query-cpus-fast Cornelia Huck
2018-03-01 12:58 ` [Qemu-devel] [PULL v2 21/27] qmp: add architecture specific cpu data for query-cpus-fast Cornelia Huck
2018-03-01 12:58 ` [Qemu-devel] [PULL v2 22/27] qemu-doc: deprecate query-cpus Cornelia Huck
2018-03-01 13:01 [Qemu-devel] [PULL v2 00/27] s390x updates (and friends) Cornelia Huck
2018-03-01 13:01 ` [Qemu-devel] [PULL v2 12/27] s390-ccw: use zipl values when no boot menu options are present Cornelia Huck

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.