Commit ff6b8ea6 authored by Michael Holzheu's avatar Michael Holzheu Committed by Martin Schwidefsky

[S390] ipl/dump on panic.

It is now possible to specify a ccw/fcp dump device which is used to
automatically create a system dump in case of a kernel panic. The dump
device can be configured under /sys/firmware/dump.
In addition it is now possible to specify a ccw/fcp device which is used
for the next reboot of Linux. The reipl device can be configured under
/sys/firmware/reipl.
Signed-off-by: default avatarMichael Holzheu <holzheu@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 331c982d
...@@ -6,7 +6,7 @@ EXTRA_AFLAGS := -traditional ...@@ -6,7 +6,7 @@ EXTRA_AFLAGS := -traditional
obj-y := bitmap.o traps.o time.o process.o \ obj-y := bitmap.o traps.o time.o process.o \
setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
semaphore.o s390_ext.o debug.o profile.o irq.o reipl_diag.o semaphore.o s390_ext.o debug.o profile.o irq.o ipl.o
obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o) obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o)
obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o) obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
......
...@@ -38,6 +38,7 @@ startup:basr %r13,0 # get base ...@@ -38,6 +38,7 @@ startup:basr %r13,0 # get base
startup_continue: startup_continue:
basr %r13,0 # get base basr %r13,0 # get base
.LPG1: GET_IPL_DEVICE .LPG1: GET_IPL_DEVICE
mvi __LC_AR_MODE_ID,0 # set ESA flag (mode 0)
lctl %c0,%c15,.Lctl-.LPG1(%r13) # load control registers lctl %c0,%c15,.Lctl-.LPG1(%r13) # load control registers
l %r12,.Lparmaddr-.LPG1(%r13) # pointer to parameter area l %r12,.Lparmaddr-.LPG1(%r13) # pointer to parameter area
# move IPL device to lowcore # move IPL device to lowcore
...@@ -274,6 +275,8 @@ startup_continue: ...@@ -274,6 +275,8 @@ startup_continue:
.Lparmaddr: .long PARMAREA .Lparmaddr: .long PARMAREA
.Lsccbaddr: .long .Lsccb .Lsccbaddr: .long .Lsccb
.org 0x12000 .org 0x12000
.globl s390_readinfo_sccb
s390_readinfo_sccb:
.Lsccb: .Lsccb:
.hword 0x1000 # length, one page .hword 0x1000 # length, one page
.byte 0x00,0x00,0x00 .byte 0x00,0x00,0x00
......
...@@ -41,6 +41,7 @@ startup_continue: ...@@ -41,6 +41,7 @@ startup_continue:
srl %r13,1 srl %r13,1
GET_IPL_DEVICE GET_IPL_DEVICE
lhi %r1,1 # mode 1 = esame lhi %r1,1 # mode 1 = esame
mvi __LC_AR_MODE_ID,1 # set esame flag
slr %r0,%r0 # set cpuid to zero slr %r0,%r0 # set cpuid to zero
sigp %r1,%r0,0x12 # switch to esame mode sigp %r1,%r0,0x12 # switch to esame mode
sam64 # switch to 64 bit mode sam64 # switch to 64 bit mode
...@@ -269,6 +270,8 @@ startup_continue: ...@@ -269,6 +270,8 @@ startup_continue:
.quad PARMAREA .quad PARMAREA
.org 0x12000 .org 0x12000
.globl s390_readinfo_sccb
s390_readinfo_sccb:
.Lsccb: .Lsccb:
.hword 0x1000 # length, one page .hword 0x1000 # length, one page
.byte 0x00,0x00,0x00 .byte 0x00,0x00,0x00
......
This diff is collapsed.
...@@ -8,13 +8,30 @@ ...@@ -8,13 +8,30 @@
#include <asm/lowcore.h> #include <asm/lowcore.h>
.globl do_reipl .globl do_reipl_asm
do_reipl: basr %r13,0 do_reipl_asm: basr %r13,0
.Lpg0: lpsw .Lnewpsw-.Lpg0(%r13) .Lpg0: lpsw .Lnewpsw-.Lpg0(%r13)
.Lpg1: lctl %c6,%c6,.Lall-.Lpg0(%r13)
stctl %c0,%c0,.Lctlsave-.Lpg0(%r13) # switch off lowcore protection
ni .Lctlsave-.Lpg0(%r13),0xef
lctl %c0,%c0,.Lctlsave-.Lpg0(%r13) .Lpg1: stctl %c0,%c0,.Lctlsave1-.Lpg0(%r13)
stctl %c0,%c0,.Lctlsave2-.Lpg0(%r13)
ni .Lctlsave1-.Lpg0(%r13),0xef
lctl %c0,%c0,.Lctlsave1-.Lpg0(%r13)
# do store status of all registers
stm %r0,%r15,__LC_GPREGS_SAVE_AREA
stctl %c0,%c15,__LC_CREGS_SAVE_AREA
mvc __LC_CREGS_SAVE_AREA(4),.Lctlsave2-.Lpg0(%r13)
stam %a0,%a15,__LC_AREGS_SAVE_AREA
stpx __LC_PREFIX_SAVE_AREA
stckc .Lclkcmp-.Lpg0(%r13)
mvc __LC_CLOCK_COMP_SAVE_AREA(8),.Lclkcmp-.Lpg0(%r13)
stpt __LC_CPU_TIMER_SAVE_AREA
st %r13, __LC_PSW_SAVE_AREA+4
lctl %c6,%c6,.Lall-.Lpg0(%r13)
lr %r1,%r2 lr %r1,%r2
mvc __LC_PGM_NEW_PSW(8),.Lpcnew-.Lpg0(%r13) mvc __LC_PGM_NEW_PSW(8),.Lpcnew-.Lpg0(%r13)
stsch .Lschib-.Lpg0(%r13) stsch .Lschib-.Lpg0(%r13)
...@@ -46,9 +63,11 @@ do_reipl: basr %r13,0 ...@@ -46,9 +63,11 @@ do_reipl: basr %r13,0
.Ldisab: st %r14,.Ldispsw+4-.Lpg0(%r13) .Ldisab: st %r14,.Ldispsw+4-.Lpg0(%r13)
lpsw .Ldispsw-.Lpg0(%r13) lpsw .Ldispsw-.Lpg0(%r13)
.align 8 .align 8
.Lclkcmp: .quad 0x0000000000000000
.Lall: .long 0xff000000 .Lall: .long 0xff000000
.Lnull: .long 0x00000000 .Lnull: .long 0x00000000
.Lctlsave: .long 0x00000000 .Lctlsave1: .long 0x00000000
.Lctlsave2: .long 0x00000000
.align 8 .align 8
.Lnewpsw: .long 0x00080000,0x80000000+.Lpg1 .Lnewpsw: .long 0x00080000,0x80000000+.Lpg1
.Lpcnew: .long 0x00080000,0x80000000+.Lecs .Lpcnew: .long 0x00080000,0x80000000+.Lecs
......
...@@ -8,13 +8,30 @@ ...@@ -8,13 +8,30 @@
*/ */
#include <asm/lowcore.h> #include <asm/lowcore.h>
.globl do_reipl .globl do_reipl_asm
do_reipl: basr %r13,0 do_reipl_asm: basr %r13,0
.Lpg0: lpswe .Lnewpsw-.Lpg0(%r13)
# do store status of all registers
.Lpg0: stg %r1,.Lregsave-.Lpg0(%r13)
lghi %r1,0x1000
stmg %r0,%r15,__LC_GPREGS_SAVE_AREA-0x1000(%r1)
lg %r0,.Lregsave-.Lpg0(%r13)
stg %r0,__LC_GPREGS_SAVE_AREA-0x1000+8(%r1)
stctg %c0,%c15,__LC_CREGS_SAVE_AREA-0x1000(%r1)
stam %a0,%a15,__LC_AREGS_SAVE_AREA-0x1000(%r1)
stpx __LC_PREFIX_SAVE_AREA-0x1000(%r1)
stfpc __LC_FP_CREG_SAVE_AREA-0x1000(%r1)
stckc .Lclkcmp-.Lpg0(%r13)
mvc __LC_CLOCK_COMP_SAVE_AREA-0x1000(8,%r1),.Lclkcmp-.Lpg0(%r13)
stpt __LC_CPU_TIMER_SAVE_AREA-0x1000(%r1)
stg %r13, __LC_PSW_SAVE_AREA-0x1000+8(%r1)
lpswe .Lnewpsw-.Lpg0(%r13)
.Lpg1: lctlg %c6,%c6,.Lall-.Lpg0(%r13) .Lpg1: lctlg %c6,%c6,.Lall-.Lpg0(%r13)
stctg %c0,%c0,.Lctlsave-.Lpg0(%r13) stctg %c0,%c0,.Lregsave-.Lpg0(%r13)
ni .Lctlsave+4-.Lpg0(%r13),0xef ni .Lregsave+4-.Lpg0(%r13),0xef
lctlg %c0,%c0,.Lctlsave-.Lpg0(%r13) lctlg %c0,%c0,.Lregsave-.Lpg0(%r13)
lgr %r1,%r2 lgr %r1,%r2
mvc __LC_PGM_NEW_PSW(16),.Lpcnew-.Lpg0(%r13) mvc __LC_PGM_NEW_PSW(16),.Lpcnew-.Lpg0(%r13)
stsch .Lschib-.Lpg0(%r13) stsch .Lschib-.Lpg0(%r13)
...@@ -50,8 +67,9 @@ do_reipl: basr %r13,0 ...@@ -50,8 +67,9 @@ do_reipl: basr %r13,0
st %r14,.Ldispsw+12-.Lpg0(%r13) st %r14,.Ldispsw+12-.Lpg0(%r13)
lpswe .Ldispsw-.Lpg0(%r13) lpswe .Ldispsw-.Lpg0(%r13)
.align 8 .align 8
.Lclkcmp: .quad 0x0000000000000000
.Lall: .quad 0x00000000ff000000 .Lall: .quad 0x00000000ff000000
.Lctlsave: .quad 0x0000000000000000 .Lregsave: .quad 0x0000000000000000
.Lnull: .long 0x0000000000000000 .Lnull: .long 0x0000000000000000
.align 16 .align 16
/* /*
...@@ -92,5 +110,3 @@ do_reipl: basr %r13,0 ...@@ -92,5 +110,3 @@ do_reipl: basr %r13,0
.long 0x00000000,0x00000000 .long 0x00000000,0x00000000
.long 0x00000000,0x00000000 .long 0x00000000,0x00000000
/*
* This file contains the implementation of the
* Linux re-IPL support
*
* (C) Copyright IBM Corp. 2005
*
* Author(s): Volker Sameske (sameske@de.ibm.com)
*
*/
#include <linux/kernel.h>
static unsigned int reipl_diag_rc1;
static unsigned int reipl_diag_rc2;
/*
* re-IPL the system using the last used IPL parameters
*/
void reipl_diag(void)
{
asm volatile (
" la %%r4,0\n"
" la %%r5,0\n"
" diag %%r4,%2,0x308\n"
"0:\n"
" st %%r4,%0\n"
" st %%r5,%1\n"
".section __ex_table,\"a\"\n"
#ifdef CONFIG_64BIT
" .align 8\n"
" .quad 0b, 0b\n"
#else
" .align 4\n"
" .long 0b, 0b\n"
#endif
".previous\n"
: "=m" (reipl_diag_rc1), "=m" (reipl_diag_rc2)
: "d" (3) : "cc", "4", "5" );
}
...@@ -285,16 +285,9 @@ void (*_machine_power_off)(void) = machine_power_off_smp; ...@@ -285,16 +285,9 @@ void (*_machine_power_off)(void) = machine_power_off_smp;
/* /*
* Reboot, halt and power_off routines for non SMP. * Reboot, halt and power_off routines for non SMP.
*/ */
extern void reipl(unsigned long devno);
extern void reipl_diag(void);
static void do_machine_restart_nonsmp(char * __unused) static void do_machine_restart_nonsmp(char * __unused)
{ {
reipl_diag(); do_reipl();
if (MACHINE_IS_VM)
cpcmd ("IPL", NULL, 0, NULL);
else
reipl (0x10000 | S390_lowcore.ipl_device);
} }
static void do_machine_halt_nonsmp(void) static void do_machine_halt_nonsmp(void)
...@@ -755,214 +748,3 @@ struct seq_operations cpuinfo_op = { ...@@ -755,214 +748,3 @@ struct seq_operations cpuinfo_op = {
.show = show_cpuinfo, .show = show_cpuinfo,
}; };
#define DEFINE_IPL_ATTR(_name, _format, _value) \
static ssize_t ipl_##_name##_show(struct subsystem *subsys, \
char *page) \
{ \
return sprintf(page, _format, _value); \
} \
static struct subsys_attribute ipl_##_name##_attr = \
__ATTR(_name, S_IRUGO, ipl_##_name##_show, NULL);
DEFINE_IPL_ATTR(wwpn, "0x%016llx\n", (unsigned long long)
IPL_PARMBLOCK_START->fcp.wwpn);
DEFINE_IPL_ATTR(lun, "0x%016llx\n", (unsigned long long)
IPL_PARMBLOCK_START->fcp.lun);
DEFINE_IPL_ATTR(bootprog, "%lld\n", (unsigned long long)
IPL_PARMBLOCK_START->fcp.bootprog);
DEFINE_IPL_ATTR(br_lba, "%lld\n", (unsigned long long)
IPL_PARMBLOCK_START->fcp.br_lba);
enum ipl_type_type {
ipl_type_unknown,
ipl_type_ccw,
ipl_type_fcp,
};
static enum ipl_type_type
get_ipl_type(void)
{
struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
if (!IPL_DEVNO_VALID)
return ipl_type_unknown;
if (!IPL_PARMBLOCK_VALID)
return ipl_type_ccw;
if (ipl->hdr.header.version > IPL_MAX_SUPPORTED_VERSION)
return ipl_type_unknown;
if (ipl->fcp.pbt != IPL_TYPE_FCP)
return ipl_type_unknown;
return ipl_type_fcp;
}
static ssize_t
ipl_type_show(struct subsystem *subsys, char *page)
{
switch (get_ipl_type()) {
case ipl_type_ccw:
return sprintf(page, "ccw\n");
case ipl_type_fcp:
return sprintf(page, "fcp\n");
default:
return sprintf(page, "unknown\n");
}
}
static struct subsys_attribute ipl_type_attr = __ATTR_RO(ipl_type);
static ssize_t
ipl_device_show(struct subsystem *subsys, char *page)
{
struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
switch (get_ipl_type()) {
case ipl_type_ccw:
return sprintf(page, "0.0.%04x\n", ipl_devno);
case ipl_type_fcp:
return sprintf(page, "0.0.%04x\n", ipl->fcp.devno);
default:
return 0;
}
}
static struct subsys_attribute ipl_device_attr =
__ATTR(device, S_IRUGO, ipl_device_show, NULL);
static struct attribute *ipl_fcp_attrs[] = {
&ipl_type_attr.attr,
&ipl_device_attr.attr,
&ipl_wwpn_attr.attr,
&ipl_lun_attr.attr,
&ipl_bootprog_attr.attr,
&ipl_br_lba_attr.attr,
NULL,
};
static struct attribute_group ipl_fcp_attr_group = {
.attrs = ipl_fcp_attrs,
};
static struct attribute *ipl_ccw_attrs[] = {
&ipl_type_attr.attr,
&ipl_device_attr.attr,
NULL,
};
static struct attribute_group ipl_ccw_attr_group = {
.attrs = ipl_ccw_attrs,
};
static struct attribute *ipl_unknown_attrs[] = {
&ipl_type_attr.attr,
NULL,
};
static struct attribute_group ipl_unknown_attr_group = {
.attrs = ipl_unknown_attrs,
};
static ssize_t
ipl_parameter_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
{
unsigned int size = IPL_PARMBLOCK_SIZE;
if (off > size)
return 0;
if (off + count > size)
count = size - off;
memcpy(buf, (void *) IPL_PARMBLOCK_START + off, count);
return count;
}
static struct bin_attribute ipl_parameter_attr = {
.attr = {
.name = "binary_parameter",
.mode = S_IRUGO,
.owner = THIS_MODULE,
},
.size = PAGE_SIZE,
.read = &ipl_parameter_read,
};
static ssize_t
ipl_scp_data_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
{
unsigned int size = IPL_PARMBLOCK_START->fcp.scp_data_len;
void *scp_data = &IPL_PARMBLOCK_START->fcp.scp_data;
if (off > size)
return 0;
if (off + count > size)
count = size - off;
memcpy(buf, scp_data + off, count);
return count;
}
static struct bin_attribute ipl_scp_data_attr = {
.attr = {
.name = "scp_data",
.mode = S_IRUGO,
.owner = THIS_MODULE,
},
.size = PAGE_SIZE,
.read = &ipl_scp_data_read,
};
static decl_subsys(ipl, NULL, NULL);
static int ipl_register_fcp_files(void)
{
int rc;
rc = sysfs_create_group(&ipl_subsys.kset.kobj,
&ipl_fcp_attr_group);
if (rc)
goto out;
rc = sysfs_create_bin_file(&ipl_subsys.kset.kobj,
&ipl_parameter_attr);
if (rc)
goto out_ipl_parm;
rc = sysfs_create_bin_file(&ipl_subsys.kset.kobj,
&ipl_scp_data_attr);
if (!rc)
goto out;
sysfs_remove_bin_file(&ipl_subsys.kset.kobj, &ipl_parameter_attr);
out_ipl_parm:
sysfs_remove_group(&ipl_subsys.kset.kobj, &ipl_fcp_attr_group);
out:
return rc;
}
static int __init
ipl_device_sysfs_register(void) {
int rc;
rc = firmware_register(&ipl_subsys);
if (rc)
goto out;
switch (get_ipl_type()) {
case ipl_type_ccw:
rc = sysfs_create_group(&ipl_subsys.kset.kobj,
&ipl_ccw_attr_group);
break;
case ipl_type_fcp:
rc = ipl_register_fcp_files();
break;
default:
rc = sysfs_create_group(&ipl_subsys.kset.kobj,
&ipl_unknown_attr_group);
break;
}
if (rc)
firmware_unregister(&ipl_subsys);
out:
return rc;
}
__initcall(ipl_device_sysfs_register);
...@@ -59,9 +59,6 @@ static struct task_struct *current_set[NR_CPUS]; ...@@ -59,9 +59,6 @@ static struct task_struct *current_set[NR_CPUS];
extern char vmhalt_cmd[]; extern char vmhalt_cmd[];
extern char vmpoff_cmd[]; extern char vmpoff_cmd[];
extern void reipl(unsigned long devno);
extern void reipl_diag(void);
static void smp_ext_bitcall(int, ec_bit_sig); static void smp_ext_bitcall(int, ec_bit_sig);
static void smp_ext_bitcall_others(ec_bit_sig); static void smp_ext_bitcall_others(ec_bit_sig);
...@@ -279,12 +276,7 @@ static void do_machine_restart(void * __unused) ...@@ -279,12 +276,7 @@ static void do_machine_restart(void * __unused)
* interrupted by an external interrupt and s390irq * interrupted by an external interrupt and s390irq
* locks are always held disabled). * locks are always held disabled).
*/ */
reipl_diag(); do_reipl();
if (MACHINE_IS_VM)
cpcmd ("IPL", NULL, 0, NULL);
else
reipl (0x10000 | S390_lowcore.ipl_device);
} }
void machine_restart_smp(char * __unused) void machine_restart_smp(char * __unused)
......
...@@ -841,14 +841,26 @@ __clear_subchannel_easy(struct subchannel_id schid) ...@@ -841,14 +841,26 @@ __clear_subchannel_easy(struct subchannel_id schid)
return -EBUSY; return -EBUSY;
} }
extern void do_reipl(unsigned long devno); struct sch_match_id {
static int struct subchannel_id schid;
__shutdown_subchannel_easy(struct subchannel_id schid, void *data) struct ccw_dev_id devid;
int rc;
};
static int __shutdown_subchannel_easy_and_match(struct subchannel_id schid,
void *data)
{ {
struct schib schib; struct schib schib;
struct sch_match_id *match_id = data;
if (stsch_err(schid, &schib)) if (stsch_err(schid, &schib))
return -ENXIO; return -ENXIO;
if (match_id && schib.pmcw.dnv &&
(schib.pmcw.dev == match_id->devid.devno) &&
(schid.ssid == match_id->devid.ssid)) {
match_id->schid = schid;
match_id->rc = 0;
}
if (!schib.pmcw.ena) if (!schib.pmcw.ena)
return 0; return 0;
switch(__disable_subchannel_easy(schid, &schib)) { switch(__disable_subchannel_easy(schid, &schib)) {
...@@ -864,18 +876,36 @@ __shutdown_subchannel_easy(struct subchannel_id schid, void *data) ...@@ -864,18 +876,36 @@ __shutdown_subchannel_easy(struct subchannel_id schid, void *data)
return 0; return 0;
} }
void static int clear_all_subchannels_and_match(struct ccw_dev_id *devid,
clear_all_subchannels(void) struct subchannel_id *schid)
{ {
struct sch_match_id match_id;
match_id.devid = *devid;
match_id.rc = -ENODEV;
local_irq_disable(); local_irq_disable();
for_each_subchannel(__shutdown_subchannel_easy, NULL); for_each_subchannel(__shutdown_subchannel_easy_and_match, &match_id);
if (match_id.rc == 0)
*schid = match_id.schid;
return match_id.rc;
} }
void clear_all_subchannels(void)
{
local_irq_disable();
for_each_subchannel(__shutdown_subchannel_easy_and_match, NULL);
}
extern void do_reipl_asm(__u32 schid);
/* Make sure all subchannels are quiet before we re-ipl an lpar. */ /* Make sure all subchannels are quiet before we re-ipl an lpar. */
void void reipl_ccw_dev(struct ccw_dev_id *devid)
reipl(unsigned long devno)
{ {
clear_all_subchannels(); struct subchannel_id schid;
if (clear_all_subchannels_and_match(devid, &schid))
panic("IPL Device not found\n");
cio_reset_channel_paths(); cio_reset_channel_paths();
do_reipl(devno); do_reipl_asm(*((__u32*)&schid));
} }
...@@ -270,6 +270,11 @@ struct diag210 { ...@@ -270,6 +270,11 @@ struct diag210 {
__u32 vrdccrft : 8; /* real device feature (output) */ __u32 vrdccrft : 8; /* real device feature (output) */
} __attribute__ ((packed,aligned(4))); } __attribute__ ((packed,aligned(4)));
struct ccw_dev_id {
u8 ssid;
u16 devno;
};
extern int diag210(struct diag210 *addr); extern int diag210(struct diag210 *addr);
extern void wait_cons_dev(void); extern void wait_cons_dev(void);
...@@ -280,6 +285,8 @@ extern void cio_reset_channel_paths(void); ...@@ -280,6 +285,8 @@ extern void cio_reset_channel_paths(void);
extern void css_schedule_reprobe(void); extern void css_schedule_reprobe(void);
extern void reipl_ccw_dev(struct ccw_dev_id *id);
#endif #endif
#endif #endif
...@@ -47,6 +47,7 @@ ...@@ -47,6 +47,7 @@
#define __LC_PER_ATMID 0x096 #define __LC_PER_ATMID 0x096
#define __LC_PER_ADDRESS 0x098 #define __LC_PER_ADDRESS 0x098
#define __LC_PER_ACCESS_ID 0x0A1 #define __LC_PER_ACCESS_ID 0x0A1
#define __LC_AR_MODE_ID 0x0A3
#define __LC_SUBCHANNEL_ID 0x0B8 #define __LC_SUBCHANNEL_ID 0x0B8
#define __LC_SUBCHANNEL_NR 0x0BA #define __LC_SUBCHANNEL_NR 0x0BA
...@@ -106,18 +107,28 @@ ...@@ -106,18 +107,28 @@
#define __LC_INT_CLOCK 0xDE8 #define __LC_INT_CLOCK 0xDE8
#endif /* __s390x__ */ #endif /* __s390x__ */
#define __LC_PANIC_MAGIC 0xE00
#define __LC_PANIC_MAGIC 0xE00
#ifndef __s390x__ #ifndef __s390x__
#define __LC_PFAULT_INTPARM 0x080 #define __LC_PFAULT_INTPARM 0x080
#define __LC_CPU_TIMER_SAVE_AREA 0x0D8 #define __LC_CPU_TIMER_SAVE_AREA 0x0D8
#define __LC_CLOCK_COMP_SAVE_AREA 0x0E0
#define __LC_PSW_SAVE_AREA 0x100
#define __LC_PREFIX_SAVE_AREA 0x108
#define __LC_AREGS_SAVE_AREA 0x120 #define __LC_AREGS_SAVE_AREA 0x120
#define __LC_FPREGS_SAVE_AREA 0x160
#define __LC_GPREGS_SAVE_AREA 0x180 #define __LC_GPREGS_SAVE_AREA 0x180
#define __LC_CREGS_SAVE_AREA 0x1C0 #define __LC_CREGS_SAVE_AREA 0x1C0
#else /* __s390x__ */ #else /* __s390x__ */
#define __LC_PFAULT_INTPARM 0x11B8 #define __LC_PFAULT_INTPARM 0x11B8
#define __LC_FPREGS_SAVE_AREA 0x1200
#define __LC_GPREGS_SAVE_AREA 0x1280 #define __LC_GPREGS_SAVE_AREA 0x1280
#define __LC_PSW_SAVE_AREA 0x1300
#define __LC_PREFIX_SAVE_AREA 0x1318
#define __LC_FP_CREG_SAVE_AREA 0x131C
#define __LC_TODREG_SAVE_AREA 0x1324
#define __LC_CPU_TIMER_SAVE_AREA 0x1328 #define __LC_CPU_TIMER_SAVE_AREA 0x1328
#define __LC_CLOCK_COMP_SAVE_AREA 0x1331
#define __LC_AREGS_SAVE_AREA 0x1340 #define __LC_AREGS_SAVE_AREA 0x1340
#define __LC_CREGS_SAVE_AREA 0x1380 #define __LC_CREGS_SAVE_AREA 0x1380
#endif /* __s390x__ */ #endif /* __s390x__ */
......
...@@ -68,39 +68,59 @@ extern unsigned int console_irq; ...@@ -68,39 +68,59 @@ extern unsigned int console_irq;
#define SET_CONSOLE_3215 do { console_mode = 2; } while (0) #define SET_CONSOLE_3215 do { console_mode = 2; } while (0)
#define SET_CONSOLE_3270 do { console_mode = 3; } while (0) #define SET_CONSOLE_3270 do { console_mode = 3; } while (0)
struct ipl_list_header {
u32 length; struct ipl_list_hdr {
u8 reserved[3]; u32 len;
u8 reserved1[3];
u8 version; u8 version;
u32 blk0_len;
u8 pbt;
u8 flags;
u16 reserved2;
} __attribute__((packed)); } __attribute__((packed));
struct ipl_block_fcp { struct ipl_block_fcp {
u32 length; u8 reserved1[313-1];
u8 pbt; u8 opt;
u8 reserved1[322-1]; u8 reserved2[3];
u16 reserved3;
u16 devno; u16 devno;
u8 reserved2[4]; u8 reserved4[4];
u64 wwpn; u64 wwpn;
u64 lun; u64 lun;
u32 bootprog; u32 bootprog;
u8 reserved3[12]; u8 reserved5[12];
u64 br_lba; u64 br_lba;
u32 scp_data_len; u32 scp_data_len;
u8 reserved4[260]; u8 reserved6[260];
u8 scp_data[]; u8 scp_data[];
} __attribute__((packed)); } __attribute__((packed));
struct ipl_block_ccw {
u8 load_param[8];
u8 reserved1[84];
u8 reserved2[2];
u16 devno;
u8 vm_flags;
u8 reserved3[3];
u32 vm_parm_len;
} __attribute__((packed));
struct ipl_parameter_block { struct ipl_parameter_block {
struct ipl_list_hdr hdr;
union { union {
u32 length; struct ipl_block_fcp fcp;
struct ipl_list_header header; struct ipl_block_ccw ccw;
} hdr; } ipl_info;
struct ipl_block_fcp fcp;
} __attribute__((packed)); } __attribute__((packed));
#define IPL_MAX_SUPPORTED_VERSION (0) #define IPL_PARM_BLK_FCP_LEN (sizeof(struct ipl_list_hdr) + \
sizeof(struct ipl_block_fcp))
#define IPL_TYPE_FCP (0) #define IPL_PARM_BLK_CCW_LEN (sizeof(struct ipl_list_hdr) + \
sizeof(struct ipl_block_ccw))
#define IPL_MAX_SUPPORTED_VERSION (0)
/* /*
* IPL validity flags and parameters as detected in head.S * IPL validity flags and parameters as detected in head.S
...@@ -108,12 +128,14 @@ struct ipl_parameter_block { ...@@ -108,12 +128,14 @@ struct ipl_parameter_block {
extern u32 ipl_parameter_flags; extern u32 ipl_parameter_flags;
extern u16 ipl_devno; extern u16 ipl_devno;
void do_reipl(void);
#define IPL_DEVNO_VALID (ipl_parameter_flags & 1) #define IPL_DEVNO_VALID (ipl_parameter_flags & 1)
#define IPL_PARMBLOCK_VALID (ipl_parameter_flags & 2) #define IPL_PARMBLOCK_VALID (ipl_parameter_flags & 2)
#define IPL_PARMBLOCK_START ((struct ipl_parameter_block *) \ #define IPL_PARMBLOCK_START ((struct ipl_parameter_block *) \
IPL_PARMBLOCK_ORIGIN) IPL_PARMBLOCK_ORIGIN)
#define IPL_PARMBLOCK_SIZE (IPL_PARMBLOCK_START->hdr.length) #define IPL_PARMBLOCK_SIZE (IPL_PARMBLOCK_START->hdr.len)
#else /* __ASSEMBLY__ */ #else /* __ASSEMBLY__ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment