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: Alexander Yarygin <yarygin@linux.vnet.ibm.com> Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
This commit is contained in:
parent
3041e3bead
commit
d046c51dad
79
pc-bios/s390-ccw/iplb.h
Normal file
79
pc-bios/s390-ccw/iplb.h
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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 */
|
@ -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;
|
||||
debug_print_int("device no. ", dev_no);
|
||||
blk_schid.ssid = (dev_info >> 16) & 0x3;
|
||||
debug_print_int("ssid ", blk_schid.ssid);
|
||||
found = find_dev(&schib, dev_no);
|
||||
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 = 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 */
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user