s390/ipl: rely on diag308 store to get ipl info
For both ccw and fcp boot retrieve ipl info from ipl block received via diag308 store. Old scsi ipl parm block handling and cio_get_iplinfo are removed. Ipl type is deducted from ipl block (if valid). Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
Родитель
283abedb1b
Коммит
d08091ac96
|
@ -119,34 +119,12 @@ static void error(char *x)
|
|||
asm volatile("lpsw %0" : : "Q" (psw));
|
||||
}
|
||||
|
||||
/*
|
||||
* Safe guard the ipl parameter block against a memory area that will be
|
||||
* overwritten. The validity check for the ipl parameter block is complex
|
||||
* (see cio_get_iplinfo and ipl_save_parameters) but if the pointer to
|
||||
* the ipl parameter block intersects with the passed memory area we can
|
||||
* safely assume that we can read from that memory. In that case just copy
|
||||
* the memory to IPL_PARMBLOCK_ORIGIN even if there is no ipl parameter
|
||||
* block.
|
||||
*/
|
||||
static void check_ipl_parmblock(void *start, unsigned long size)
|
||||
{
|
||||
void *src, *dst;
|
||||
|
||||
src = (void *)(unsigned long) S390_lowcore.ipl_parmblock_ptr;
|
||||
if (src + PAGE_SIZE <= start || src >= start + size)
|
||||
return;
|
||||
dst = (void *) IPL_PARMBLOCK_ORIGIN;
|
||||
memmove(dst, src, PAGE_SIZE);
|
||||
S390_lowcore.ipl_parmblock_ptr = IPL_PARMBLOCK_ORIGIN;
|
||||
}
|
||||
|
||||
unsigned long decompress_kernel(void)
|
||||
{
|
||||
void *output, *kernel_end;
|
||||
|
||||
output = (void *) ALIGN((unsigned long) _end + HEAP_SIZE, PAGE_SIZE);
|
||||
kernel_end = output + SZ__bss_start;
|
||||
check_ipl_parmblock((void *) 0, (unsigned long) kernel_end);
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
/*
|
||||
|
@ -156,7 +134,6 @@ unsigned long decompress_kernel(void)
|
|||
* current bss section..
|
||||
*/
|
||||
if (INITRD_START && INITRD_SIZE && kernel_end > (void *) INITRD_START) {
|
||||
check_ipl_parmblock(kernel_end, INITRD_SIZE);
|
||||
memmove(kernel_end, (void *) INITRD_START, INITRD_SIZE);
|
||||
INITRD_START = (unsigned long) kernel_end;
|
||||
}
|
||||
|
|
|
@ -330,14 +330,6 @@ extern void css_schedule_reprobe(void);
|
|||
|
||||
extern void reipl_ccw_dev(struct ccw_dev_id *id);
|
||||
|
||||
struct cio_iplinfo {
|
||||
u8 ssid;
|
||||
u16 devno;
|
||||
int is_qdio;
|
||||
};
|
||||
|
||||
extern int cio_get_iplinfo(struct cio_iplinfo *iplinfo);
|
||||
|
||||
/* Function from drivers/s390/cio/chsc.c */
|
||||
int chsc_sstpc(void *page, unsigned int op, u16 ctrl, u64 *clock_delta);
|
||||
int chsc_sstpi(void *page, void *result, size_t size);
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
|
||||
#define NSS_NAME_SIZE 8
|
||||
|
||||
#define IPL_PARMBLOCK_ORIGIN 0x2000
|
||||
|
||||
#define IPL_PARM_BLK_FCP_LEN (sizeof(struct ipl_list_hdr) + \
|
||||
sizeof(struct ipl_block_fcp))
|
||||
|
||||
|
@ -92,8 +90,7 @@ void __init save_area_add_vxrs(struct save_area *, __vector128 *vxrs);
|
|||
extern void do_reipl(void);
|
||||
extern void do_halt(void);
|
||||
extern void do_poff(void);
|
||||
extern void ipl_verify_parameters(void);
|
||||
extern void ipl_update_parameters(void);
|
||||
extern void ipl_store_parameters(void);
|
||||
extern size_t append_ipl_vmparm(char *, size_t);
|
||||
extern size_t append_ipl_scpdata(char *, size_t);
|
||||
|
||||
|
|
|
@ -342,16 +342,6 @@ static __init void memmove_early(void *dst, const void *src, size_t n)
|
|||
S390_lowcore.program_new_psw = old;
|
||||
}
|
||||
|
||||
static __init noinline void ipl_save_parameters(void)
|
||||
{
|
||||
void *src, *dst;
|
||||
|
||||
src = (void *)(unsigned long) S390_lowcore.ipl_parmblock_ptr;
|
||||
dst = (void *) IPL_PARMBLOCK_ORIGIN;
|
||||
memmove_early(dst, src, PAGE_SIZE);
|
||||
S390_lowcore.ipl_parmblock_ptr = IPL_PARMBLOCK_ORIGIN;
|
||||
}
|
||||
|
||||
static __init noinline void rescue_initrd(void)
|
||||
{
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
|
@ -421,10 +411,8 @@ static void __init setup_boot_command_line(void)
|
|||
void __init startup_init(void)
|
||||
{
|
||||
reset_tod_clock();
|
||||
ipl_save_parameters();
|
||||
rescue_initrd();
|
||||
clear_bss_section();
|
||||
ipl_verify_parameters();
|
||||
time_early_init();
|
||||
init_kernel_storage_key();
|
||||
lockdep_off();
|
||||
|
@ -432,7 +420,7 @@ void __init startup_init(void)
|
|||
setup_facility_list();
|
||||
detect_machine_type();
|
||||
setup_arch_string();
|
||||
ipl_update_parameters();
|
||||
ipl_store_parameters();
|
||||
setup_boot_command_line();
|
||||
detect_diag9c();
|
||||
detect_diag44();
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include <asm/smp.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/cpcmd.h>
|
||||
#include <asm/cio.h>
|
||||
#include <asm/ebcdic.h>
|
||||
#include <asm/reset.h>
|
||||
#include <asm/sclp.h>
|
||||
|
@ -119,16 +118,6 @@ static char *dump_type_str(enum dump_type type)
|
|||
}
|
||||
}
|
||||
|
||||
enum {
|
||||
IPL_DEVNO_VALID = 1,
|
||||
IPL_PARMBLOCK_VALID = 2,
|
||||
};
|
||||
|
||||
/*
|
||||
* IPL validity flags
|
||||
*/
|
||||
static u32 ipl_flags;
|
||||
|
||||
enum ipl_method {
|
||||
REIPL_METHOD_CCW_CIO,
|
||||
REIPL_METHOD_CCW_DIAG,
|
||||
|
@ -150,6 +139,7 @@ enum dump_method {
|
|||
DUMP_METHOD_FCP_DIAG,
|
||||
};
|
||||
|
||||
static int ipl_block_valid;
|
||||
static int diag308_set_works;
|
||||
|
||||
static struct ipl_parameter_block ipl_block;
|
||||
|
@ -280,17 +270,19 @@ static void make_attrs_ro(struct attribute **attrs)
|
|||
|
||||
static __init enum ipl_type get_ipl_type(void)
|
||||
{
|
||||
if (!(ipl_flags & IPL_DEVNO_VALID))
|
||||
if (!ipl_block_valid)
|
||||
return IPL_TYPE_UNKNOWN;
|
||||
if (!(ipl_flags & IPL_PARMBLOCK_VALID))
|
||||
|
||||
switch (ipl_block.hdr.pbt) {
|
||||
case DIAG308_IPL_TYPE_CCW:
|
||||
return IPL_TYPE_CCW;
|
||||
if (ipl_block.hdr.version > IPL_MAX_SUPPORTED_VERSION)
|
||||
return IPL_TYPE_UNKNOWN;
|
||||
if (ipl_block.hdr.pbt != DIAG308_IPL_TYPE_FCP)
|
||||
return IPL_TYPE_UNKNOWN;
|
||||
if (ipl_block.ipl_info.fcp.opt == DIAG308_IPL_OPT_DUMP)
|
||||
return IPL_TYPE_FCP_DUMP;
|
||||
return IPL_TYPE_FCP;
|
||||
case DIAG308_IPL_TYPE_FCP:
|
||||
if (ipl_block.ipl_info.fcp.opt == DIAG308_IPL_OPT_DUMP)
|
||||
return IPL_TYPE_FCP_DUMP;
|
||||
else
|
||||
return IPL_TYPE_FCP;
|
||||
}
|
||||
return IPL_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
struct ipl_info ipl_info;
|
||||
|
@ -1949,30 +1941,15 @@ void __init setup_ipl(void)
|
|||
atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
|
||||
}
|
||||
|
||||
void __init ipl_update_parameters(void)
|
||||
void __init ipl_store_parameters(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = diag308(DIAG308_STORE, &ipl_block);
|
||||
if ((rc == DIAG308_RC_OK) || (rc == DIAG308_RC_NOCONFIG))
|
||||
diag308_set_works = 1;
|
||||
if (rc != DIAG308_RC_OK && (ipl_flags & IPL_PARMBLOCK_VALID))
|
||||
memcpy(&ipl_block, (void *)IPL_PARMBLOCK_ORIGIN, PAGE_SIZE);
|
||||
}
|
||||
|
||||
void __init ipl_verify_parameters(void)
|
||||
{
|
||||
struct cio_iplinfo iplinfo;
|
||||
|
||||
if (cio_get_iplinfo(&iplinfo))
|
||||
return;
|
||||
|
||||
ipl_block.ipl_info.ccw.ssid = iplinfo.ssid;
|
||||
ipl_block.ipl_info.ccw.devno = iplinfo.devno;
|
||||
ipl_flags |= IPL_DEVNO_VALID;
|
||||
if (!iplinfo.is_qdio)
|
||||
return;
|
||||
ipl_flags |= IPL_PARMBLOCK_VALID;
|
||||
if (rc == DIAG308_RC_OK && ipl_block.hdr.version <= IPL_MAX_SUPPORTED_VERSION)
|
||||
ipl_block_valid = 1;
|
||||
}
|
||||
|
||||
static LIST_HEAD(rcall);
|
||||
|
|
|
@ -990,39 +990,6 @@ void reipl_ccw_dev(struct ccw_dev_id *devid)
|
|||
do_reipl_asm(*((__u32*)&schid));
|
||||
}
|
||||
|
||||
int __init cio_get_iplinfo(struct cio_iplinfo *iplinfo)
|
||||
{
|
||||
static struct chsc_sda_area sda_area __initdata;
|
||||
struct subchannel_id schid;
|
||||
struct schib schib;
|
||||
|
||||
schid = *(struct subchannel_id *)&S390_lowcore.subchannel_id;
|
||||
if (!schid.one)
|
||||
return -ENODEV;
|
||||
|
||||
if (schid.ssid) {
|
||||
/*
|
||||
* Firmware should have already enabled MSS but whoever started
|
||||
* the kernel might have initiated a channel subsystem reset.
|
||||
* Ensure that MSS is enabled.
|
||||
*/
|
||||
memset(&sda_area, 0, sizeof(sda_area));
|
||||
if (__chsc_enable_facility(&sda_area, CHSC_SDA_OC_MSS))
|
||||
return -ENODEV;
|
||||
}
|
||||
if (stsch(schid, &schib))
|
||||
return -ENODEV;
|
||||
if (schib.pmcw.st != SUBCHANNEL_TYPE_IO)
|
||||
return -ENODEV;
|
||||
if (!schib.pmcw.dnv)
|
||||
return -ENODEV;
|
||||
|
||||
iplinfo->ssid = schid.ssid;
|
||||
iplinfo->devno = schib.pmcw.dev;
|
||||
iplinfo->is_qdio = schib.pmcw.qf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* cio_tm_start_key - perform start function
|
||||
* @sch: subchannel on which to perform the start function
|
||||
|
|
Загрузка…
Ссылка в новой задаче