Commit d046c51d authored by Alexander Yarygin's avatar Alexander Yarygin Committed by Cornelia Huck
Browse files

pc-bios/s390-ccw: Get device address via diag 308/6



To IPL from a device, pc-bios receives from qemu a device address via
general register 7. The better way to do it is to use diag308/6
instruction which returns so called
"IplParameterBlock". IplParameterBlock contains the device address for
IPL and additional parameters that can be used by pc-bios.

This patch allows pc-bios to get device address via diag308/6 and
doesn't use gr7 passed boot information anymore.

Signed-off-by: default avatarAlexander Yarygin <yarygin@linux.vnet.ibm.com>
Reviewed-by: default avatarDavid Hildenbrand <dahi@linux.vnet.ibm.com>
Signed-off-by: default avatarCornelia Huck <cornelia.huck@de.ibm.com>
parent 3041e3be
Loading
Loading
Loading
Loading
+79 −0
Original line number Diff line number Diff line
/*
 * QEMU S390 IPL Block
 *
 * Copyright 2015 IBM Corp.
 * Author(s): Alexander Yarygin <yarygin@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.
 */

#ifndef IPLB_H
#define IPLB_H

struct IplBlockCcw {
    uint8_t  reserved0[85];
    uint8_t  ssid;
    uint16_t devno;
    uint8_t  vm_flags;
    uint8_t  reserved3[3];
    uint32_t vm_parm_len;
    uint8_t  nss_name[8];
    uint8_t  vm_parm[64];
    uint8_t  reserved4[8];
} __attribute__ ((packed));
typedef struct IplBlockCcw IplBlockCcw;

struct IplBlockFcp {
    uint8_t  reserved1[305 - 1];
    uint8_t  opt;
    uint8_t  reserved2[3];
    uint16_t reserved3;
    uint16_t devno;
    uint8_t  reserved4[4];
    uint64_t wwpn;
    uint64_t lun;
    uint32_t bootprog;
    uint8_t  reserved5[12];
    uint64_t br_lba;
    uint32_t scp_data_len;
    uint8_t  reserved6[260];
    uint8_t  scp_data[];
} __attribute__ ((packed));
typedef struct IplBlockFcp IplBlockFcp;

struct IplParameterBlock {
    uint32_t len;
    uint8_t  reserved0[3];
    uint8_t  version;
    uint32_t blk0_len;
    uint8_t  pbt;
    uint8_t  flags;
    uint16_t reserved01;
    uint8_t  loadparm[8];
    union {
        IplBlockCcw ccw;
        IplBlockFcp fcp;
    };
} __attribute__ ((packed));
typedef struct IplParameterBlock IplParameterBlock;

extern IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE)));

#define S390_IPL_TYPE_FCP 0x00
#define S390_IPL_TYPE_CCW 0x02

static inline bool store_iplb(IplParameterBlock *iplb)
{
    register unsigned long addr asm("0") = (unsigned long) iplb;
    register unsigned long rc asm("1") = 0;

    asm volatile ("diag %0,%2,0x308\n"
                  : "+d" (addr), "+d" (rc)
                  : "d" (6)
                  : "memory", "cc");
    return rc == 0x01;
}

#endif /* IPLB_H */
+15 −10
Original line number Diff line number Diff line
@@ -12,8 +12,8 @@
#include "virtio.h"

char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
uint64_t boot_value;
static SubChannelId blk_schid = { .one = 1 };
IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE)));

/*
 * Priniciples of Operations (SA22-7832-09) chapter 17 requires that
@@ -61,7 +61,7 @@ static bool find_dev(Schib *schib, int dev_no)
    return false;
}

static void virtio_setup(uint64_t dev_info)
static void virtio_setup(void)
{
    Schib schib;
    int ssid;
@@ -75,12 +75,18 @@ static void virtio_setup(uint64_t dev_info)
     */
    enable_mss_facility();

    if (dev_info != -1) {
        dev_no = dev_info & 0xffff;
    if (store_iplb(&iplb)) {
        switch (iplb.pbt) {
        case S390_IPL_TYPE_CCW:
            dev_no = iplb.ccw.devno;
            debug_print_int("device no. ", dev_no);
        blk_schid.ssid = (dev_info >> 16) & 0x3;
            blk_schid.ssid = iplb.ccw.ssid & 0x3;
            debug_print_int("ssid ", blk_schid.ssid);
            found = find_dev(&schib, dev_no);
            break;
        default:
            panic("List-directed IPL not supported yet!\n");
        }
    } else {
        for (ssid = 0; ssid < 0x3; ssid++) {
            blk_schid.ssid = ssid;
@@ -101,8 +107,7 @@ static void virtio_setup(uint64_t dev_info)
int main(void)
{
    sclp_setup();
    debug_print_int("boot reg[7] ", boot_value);
    virtio_setup(boot_value);
    virtio_setup();

    zipl_load(); /* no return */

+1 −1
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ typedef unsigned long long __u64;
#endif

#include "cio.h"
#include "iplb.h"

typedef struct irb Irb;
typedef struct ccw1 Ccw1;
@@ -61,7 +62,6 @@ void consume_sclp_int(void);
void panic(const char *string);
void write_subsystem_identification(void);
extern char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
extern uint64_t boot_value;

/* sclp-ascii.c */
void sclp_print(const char *string);
+0 −2
Original line number Diff line number Diff line
@@ -14,8 +14,6 @@
_start:

larl	%r15, stack + 0x8000    /* Set up stack */
larl    %r6, boot_value
stg     %r7, 0(%r6)     /* save the boot_value before any function calls */
j	main                    /* And call C */

/*