mirror of
https://github.com/t2linux/kernel.git
synced 2026-04-30 13:48:59 -07:00
Merge branch 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6
* 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6: (38 commits) [S390] SPIN_LOCK_UNLOCKED cleanup in drivers/s390 [S390] Clean up smp code in preparation for some larger changes. [S390] Remove debugging junk. [S390] Switch etr from tasklet to workqueue. [S390] split page_test_and_clear_dirty. [S390] Processor degradation notification. [S390] vtime: cleanup per_cpu usage. [S390] crypto: cleanup. [S390] sclp: fix coding style. [S390] vmlogrdr: stop IUCV connection in vmlogrdr_release. [S390] sclp: initialize early. [S390] ctc: kmalloc->kzalloc/casting cleanups. [S390] zfcpdump support. [S390] dasd: Add ipldev parameter. [S390] dasd: Add sysfs attribute status and generate uevents. [S390] Improved kernel stack overflow checking. [S390] Get rid of console setup functions. [S390] No execute support cleanup. [S390] Minor fault path optimization. [S390] Use generic bug. ...
This commit is contained in:
@@ -1,83 +0,0 @@
|
||||
crypto-API support for z990 Message Security Assist (MSA) instructions
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
AUTHOR: Thomas Spatzier (tspat@de.ibm.com)
|
||||
|
||||
|
||||
1. Introduction crypto-API
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
See Documentation/crypto/api-intro.txt for an introduction/description of the
|
||||
kernel crypto API.
|
||||
According to api-intro.txt support for z990 crypto instructions has been added
|
||||
in the algorithm api layer of the crypto API. Several files containing z990
|
||||
optimized implementations of crypto algorithms are placed in the
|
||||
arch/s390/crypto directory.
|
||||
|
||||
|
||||
2. Probing for availability of MSA
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
It should be possible to use Kernels with the z990 crypto implementations both
|
||||
on machines with MSA available and on those without MSA (pre z990 or z990
|
||||
without MSA). Therefore a simple probing mechanism has been implemented:
|
||||
In the init function of each crypto module the availability of MSA and of the
|
||||
respective crypto algorithm in particular will be tested. If the algorithm is
|
||||
available the module will load and register its algorithm with the crypto API.
|
||||
|
||||
If the respective crypto algorithm is not available, the init function will
|
||||
return -ENOSYS. In that case a fallback to the standard software implementation
|
||||
of the crypto algorithm must be taken ( -> the standard crypto modules are
|
||||
also built when compiling the kernel).
|
||||
|
||||
|
||||
3. Ensuring z990 crypto module preference
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
If z990 crypto instructions are available the optimized modules should be
|
||||
preferred instead of standard modules.
|
||||
|
||||
3.1. compiled-in modules
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
For compiled-in modules it has to be ensured that the z990 modules are linked
|
||||
before the standard crypto modules. Then, on system startup the init functions
|
||||
of z990 crypto modules will be called first and query for availability of z990
|
||||
crypto instructions. If instruction is available, the z990 module will register
|
||||
its crypto algorithm implementation -> the load of the standard module will fail
|
||||
since the algorithm is already registered.
|
||||
If z990 crypto instruction is not available the load of the z990 module will
|
||||
fail -> the standard module will load and register its algorithm.
|
||||
|
||||
3.2. dynamic modules
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
A system administrator has to take care of giving preference to z990 crypto
|
||||
modules. If MSA is available appropriate lines have to be added to
|
||||
/etc/modprobe.conf.
|
||||
|
||||
Example: z990 crypto instruction for SHA1 algorithm is available
|
||||
|
||||
add the following line to /etc/modprobe.conf (assuming the
|
||||
z990 crypto modules for SHA1 is called sha1_z990):
|
||||
|
||||
alias sha1 sha1_z990
|
||||
|
||||
-> when the sha1 algorithm is requested through the crypto API
|
||||
(which has a module autoloader) the z990 module will be loaded.
|
||||
|
||||
TBD: a userspace module probing mechanism
|
||||
something like 'probe sha1 sha1_z990 sha1' in modprobe.conf
|
||||
-> try module sha1_z990, if it fails to load standard module sha1
|
||||
the 'probe' statement is currently not supported in modprobe.conf
|
||||
|
||||
|
||||
4. Currently implemented z990 crypto algorithms
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The following crypto algorithms with z990 MSA support are currently implemented.
|
||||
The name of each algorithm under which it is registered in crypto API and the
|
||||
name of the respective module is given in square brackets.
|
||||
|
||||
- SHA1 Digest Algorithm [sha1 -> sha1_z990]
|
||||
- DES Encrypt/Decrypt Algorithm (64bit key) [des -> des_z990]
|
||||
- Triple DES Encrypt/Decrypt Algorithm (128bit key) [des3_ede128 -> des_z990]
|
||||
- Triple DES Encrypt/Decrypt Algorithm (192bit key) [des3_ede -> des_z990]
|
||||
|
||||
In order to load, for example, the sha1_z990 module when the sha1 algorithm is
|
||||
requested (see 3.2.) add 'alias sha1 sha1_z990' to /etc/modprobe.conf.
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
s390 SCSI dump tool (zfcpdump)
|
||||
|
||||
System z machines (z900 or higher) provide hardware support for creating system
|
||||
dumps on SCSI disks. The dump process is initiated by booting a dump tool, which
|
||||
has to create a dump of the current (probably crashed) Linux image. In order to
|
||||
not overwrite memory of the crashed Linux with data of the dump tool, the
|
||||
hardware saves some memory plus the register sets of the boot cpu before the
|
||||
dump tool is loaded. There exists an SCLP hardware interface to obtain the saved
|
||||
memory afterwards. Currently 32 MB are saved.
|
||||
|
||||
This zfcpdump implementation consists of a Linux dump kernel together with
|
||||
a userspace dump tool, which are loaded together into the saved memory region
|
||||
below 32 MB. zfcpdump is installed on a SCSI disk using zipl (as contained in
|
||||
the s390-tools package) to make the device bootable. The operator of a Linux
|
||||
system can then trigger a SCSI dump by booting the SCSI disk, where zfcpdump
|
||||
resides on.
|
||||
|
||||
The kernel part of zfcpdump is implemented as a debugfs file under "zcore/mem",
|
||||
which exports memory and registers of the crashed Linux in an s390
|
||||
standalone dump format. It can be used in the same way as e.g. /dev/mem. The
|
||||
dump format defines a 4K header followed by plain uncompressed memory. The
|
||||
register sets are stored in the prefix pages of the respective cpus. To build a
|
||||
dump enabled kernel with the zcore driver, the kernel config option
|
||||
CONFIG_ZFCPDUMP has to be set. When reading from "zcore/mem", the part of
|
||||
memory, which has been saved by hardware is read by the driver via the SCLP
|
||||
hardware interface. The second part is just copied from the non overwritten real
|
||||
memory.
|
||||
|
||||
The userspace application of zfcpdump can reside e.g. in an intitramfs or an
|
||||
initrd. It reads from zcore/mem and writes the system dump to a file on a
|
||||
SCSI disk.
|
||||
|
||||
To build a zfcpdump kernel use the following settings in your kernel
|
||||
configuration:
|
||||
* CONFIG_ZFCPDUMP=y
|
||||
* Enable ZFCP driver
|
||||
* Enable SCSI driver
|
||||
* Enable ext2 and ext3 filesystems
|
||||
* Disable as many features as possible to keep the kernel small.
|
||||
E.g. network support is not needed at all.
|
||||
|
||||
To use the zfcpdump userspace application in an initramfs you have to do the
|
||||
following:
|
||||
|
||||
* Copy the zfcpdump executable somewhere into your Linux tree.
|
||||
E.g. to "arch/s390/boot/zfcpdump. If you do not want to include
|
||||
shared libraries, compile the tool with the "-static" gcc option.
|
||||
* If you want to include e2fsck, add it to your source tree, too. The zfcpdump
|
||||
application attempts to start /sbin/e2fsck from the ramdisk.
|
||||
* Use an initramfs config file like the following:
|
||||
|
||||
dir /dev 755 0 0
|
||||
nod /dev/console 644 0 0 c 5 1
|
||||
nod /dev/null 644 0 0 c 1 3
|
||||
nod /dev/sda1 644 0 0 b 8 1
|
||||
nod /dev/sda2 644 0 0 b 8 2
|
||||
nod /dev/sda3 644 0 0 b 8 3
|
||||
nod /dev/sda4 644 0 0 b 8 4
|
||||
nod /dev/sda5 644 0 0 b 8 5
|
||||
nod /dev/sda6 644 0 0 b 8 6
|
||||
nod /dev/sda7 644 0 0 b 8 7
|
||||
nod /dev/sda8 644 0 0 b 8 8
|
||||
nod /dev/sda9 644 0 0 b 8 9
|
||||
nod /dev/sda10 644 0 0 b 8 10
|
||||
nod /dev/sda11 644 0 0 b 8 11
|
||||
nod /dev/sda12 644 0 0 b 8 12
|
||||
nod /dev/sda13 644 0 0 b 8 13
|
||||
nod /dev/sda14 644 0 0 b 8 14
|
||||
nod /dev/sda15 644 0 0 b 8 15
|
||||
file /init arch/s390/boot/zfcpdump 755 0 0
|
||||
file /sbin/e2fsck arch/s390/boot/e2fsck 755 0 0
|
||||
dir /proc 755 0 0
|
||||
dir /sys 755 0 0
|
||||
dir /mnt 755 0 0
|
||||
dir /sbin 755 0 0
|
||||
|
||||
* Issue "make image" to build the zfcpdump image with initramfs.
|
||||
|
||||
In a Linux distribution the zfcpdump enabled kernel image must be copied to
|
||||
/usr/share/zfcpdump/zfcpdump.image, where the s390 zipl tool is looking for the
|
||||
dump kernel when preparing a SCSI dump disk.
|
||||
|
||||
If you use a ramdisk copy it to "/usr/share/zfcpdump/zfcpdump.rd".
|
||||
|
||||
For more information on how to use zfcpdump refer to the s390 'Using the Dump
|
||||
Tools book', which is available from
|
||||
http://www.ibm.com/developerworks/linux/linux390.
|
||||
@@ -41,6 +41,11 @@ config GENERIC_HWEIGHT
|
||||
config GENERIC_TIME
|
||||
def_bool y
|
||||
|
||||
config GENERIC_BUG
|
||||
bool
|
||||
depends on BUG
|
||||
default y
|
||||
|
||||
config NO_IOMEM
|
||||
def_bool y
|
||||
|
||||
@@ -514,6 +519,14 @@ config KEXEC
|
||||
current kernel, and to start another kernel. It is like a reboot
|
||||
but is independent of hardware/microcode support.
|
||||
|
||||
config ZFCPDUMP
|
||||
tristate "zfcpdump support"
|
||||
select SMP
|
||||
default n
|
||||
help
|
||||
Select this option if you want to build an zfcpdump enabled kernel.
|
||||
Refer to "Documentation/s390/zfcpdump.txt" for more details on this.
|
||||
|
||||
endmenu
|
||||
|
||||
source "net/Kconfig"
|
||||
|
||||
@@ -67,8 +67,10 @@ endif
|
||||
|
||||
ifeq ($(call cc-option-yn,-mstack-size=8192 -mstack-guard=128),y)
|
||||
cflags-$(CONFIG_CHECK_STACK) += -mstack-size=$(STACK_SIZE)
|
||||
ifneq ($(call cc-option-yn,-mstack-size=8192),y)
|
||||
cflags-$(CONFIG_CHECK_STACK) += -mstack-guard=$(CONFIG_STACK_GUARD)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(call cc-option-yn,-mwarn-dynamicstack),y)
|
||||
cflags-$(CONFIG_WARN_STACK) += -mwarn-dynamicstack
|
||||
@@ -103,6 +105,9 @@ install: vmlinux
|
||||
image: vmlinux
|
||||
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
|
||||
|
||||
zfcpdump:
|
||||
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
|
||||
|
||||
archclean:
|
||||
$(Q)$(MAKE) $(clean)=$(boot)
|
||||
|
||||
|
||||
@@ -668,45 +668,7 @@ EXPORT_SYMBOL_GPL(appldata_register_ops);
|
||||
EXPORT_SYMBOL_GPL(appldata_unregister_ops);
|
||||
EXPORT_SYMBOL_GPL(appldata_diag);
|
||||
|
||||
#ifdef MODULE
|
||||
/*
|
||||
* Kernel symbols needed by appldata_mem and appldata_os modules.
|
||||
* However, if this file is compiled as a module (for testing only), these
|
||||
* symbols are not exported. In this case, we define them locally and export
|
||||
* those.
|
||||
*/
|
||||
void si_swapinfo(struct sysinfo *val)
|
||||
{
|
||||
val->freeswap = -1ul;
|
||||
val->totalswap = -1ul;
|
||||
}
|
||||
|
||||
unsigned long avenrun[3] = {-1 - FIXED_1/200, -1 - FIXED_1/200,
|
||||
-1 - FIXED_1/200};
|
||||
int nr_threads = -1;
|
||||
|
||||
void get_full_page_state(struct page_state *ps)
|
||||
{
|
||||
memset(ps, -1, sizeof(struct page_state));
|
||||
}
|
||||
|
||||
unsigned long nr_running(void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned long nr_iowait(void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*unsigned long nr_context_switches(void)
|
||||
{
|
||||
return -1;
|
||||
}*/
|
||||
#endif /* MODULE */
|
||||
EXPORT_SYMBOL_GPL(si_swapinfo);
|
||||
EXPORT_SYMBOL_GPL(nr_threads);
|
||||
EXPORT_SYMBOL_GPL(nr_running);
|
||||
EXPORT_SYMBOL_GPL(nr_iowait);
|
||||
//EXPORT_SYMBOL_GPL(nr_context_switches);
|
||||
|
||||
@@ -25,99 +25,100 @@
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <asm/scatterlist.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#include "crypt_s390.h"
|
||||
|
||||
#define SHA1_DIGEST_SIZE 20
|
||||
#define SHA1_BLOCK_SIZE 64
|
||||
|
||||
struct crypt_s390_sha1_ctx {
|
||||
u64 count;
|
||||
struct s390_sha1_ctx {
|
||||
u64 count; /* message length */
|
||||
u32 state[5];
|
||||
u32 buf_len;
|
||||
u8 buffer[2 * SHA1_BLOCK_SIZE];
|
||||
u8 buf[2 * SHA1_BLOCK_SIZE];
|
||||
};
|
||||
|
||||
static void sha1_init(struct crypto_tfm *tfm)
|
||||
{
|
||||
struct crypt_s390_sha1_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
struct s390_sha1_ctx *sctx = crypto_tfm_ctx(tfm);
|
||||
|
||||
ctx->state[0] = 0x67452301;
|
||||
ctx->state[1] = 0xEFCDAB89;
|
||||
ctx->state[2] = 0x98BADCFE;
|
||||
ctx->state[3] = 0x10325476;
|
||||
ctx->state[4] = 0xC3D2E1F0;
|
||||
|
||||
ctx->count = 0;
|
||||
ctx->buf_len = 0;
|
||||
sctx->state[0] = 0x67452301;
|
||||
sctx->state[1] = 0xEFCDAB89;
|
||||
sctx->state[2] = 0x98BADCFE;
|
||||
sctx->state[3] = 0x10325476;
|
||||
sctx->state[4] = 0xC3D2E1F0;
|
||||
sctx->count = 0;
|
||||
}
|
||||
|
||||
static void sha1_update(struct crypto_tfm *tfm, const u8 *data,
|
||||
unsigned int len)
|
||||
{
|
||||
struct crypt_s390_sha1_ctx *sctx;
|
||||
long imd_len;
|
||||
struct s390_sha1_ctx *sctx = crypto_tfm_ctx(tfm);
|
||||
unsigned int index;
|
||||
int ret;
|
||||
|
||||
sctx = crypto_tfm_ctx(tfm);
|
||||
sctx->count += len * 8; /* message bit length */
|
||||
/* how much is already in the buffer? */
|
||||
index = sctx->count & 0x3f;
|
||||
|
||||
/* anything in buffer yet? -> must be completed */
|
||||
if (sctx->buf_len && (sctx->buf_len + len) >= SHA1_BLOCK_SIZE) {
|
||||
/* complete full block and hash */
|
||||
memcpy(sctx->buffer + sctx->buf_len, data,
|
||||
SHA1_BLOCK_SIZE - sctx->buf_len);
|
||||
crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buffer,
|
||||
SHA1_BLOCK_SIZE);
|
||||
data += SHA1_BLOCK_SIZE - sctx->buf_len;
|
||||
len -= SHA1_BLOCK_SIZE - sctx->buf_len;
|
||||
sctx->buf_len = 0;
|
||||
sctx->count += len;
|
||||
|
||||
if (index + len < SHA1_BLOCK_SIZE)
|
||||
goto store;
|
||||
|
||||
/* process one stored block */
|
||||
if (index) {
|
||||
memcpy(sctx->buf + index, data, SHA1_BLOCK_SIZE - index);
|
||||
ret = crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buf,
|
||||
SHA1_BLOCK_SIZE);
|
||||
BUG_ON(ret != SHA1_BLOCK_SIZE);
|
||||
data += SHA1_BLOCK_SIZE - index;
|
||||
len -= SHA1_BLOCK_SIZE - index;
|
||||
}
|
||||
|
||||
/* rest of data contains full blocks? */
|
||||
imd_len = len & ~0x3ful;
|
||||
if (imd_len) {
|
||||
crypt_s390_kimd(KIMD_SHA_1, sctx->state, data, imd_len);
|
||||
data += imd_len;
|
||||
len -= imd_len;
|
||||
/* process as many blocks as possible */
|
||||
if (len >= SHA1_BLOCK_SIZE) {
|
||||
ret = crypt_s390_kimd(KIMD_SHA_1, sctx->state, data,
|
||||
len & ~(SHA1_BLOCK_SIZE - 1));
|
||||
BUG_ON(ret != (len & ~(SHA1_BLOCK_SIZE - 1)));
|
||||
data += ret;
|
||||
len -= ret;
|
||||
}
|
||||
/* anything left? store in buffer */
|
||||
if (len) {
|
||||
memcpy(sctx->buffer + sctx->buf_len , data, len);
|
||||
sctx->buf_len += len;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void pad_message(struct crypt_s390_sha1_ctx* sctx)
|
||||
{
|
||||
int index;
|
||||
|
||||
index = sctx->buf_len;
|
||||
sctx->buf_len = (sctx->buf_len < 56) ?
|
||||
SHA1_BLOCK_SIZE:2 * SHA1_BLOCK_SIZE;
|
||||
/* start pad with 1 */
|
||||
sctx->buffer[index] = 0x80;
|
||||
/* pad with zeros */
|
||||
index++;
|
||||
memset(sctx->buffer + index, 0x00, sctx->buf_len - index);
|
||||
/* append length */
|
||||
memcpy(sctx->buffer + sctx->buf_len - 8, &sctx->count,
|
||||
sizeof sctx->count);
|
||||
store:
|
||||
/* anything left? */
|
||||
if (len)
|
||||
memcpy(sctx->buf + index , data, len);
|
||||
}
|
||||
|
||||
/* Add padding and return the message digest. */
|
||||
static void sha1_final(struct crypto_tfm *tfm, u8 *out)
|
||||
{
|
||||
struct crypt_s390_sha1_ctx *sctx = crypto_tfm_ctx(tfm);
|
||||
struct s390_sha1_ctx *sctx = crypto_tfm_ctx(tfm);
|
||||
u64 bits;
|
||||
unsigned int index, end;
|
||||
int ret;
|
||||
|
||||
/* must perform manual padding */
|
||||
pad_message(sctx);
|
||||
crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buffer, sctx->buf_len);
|
||||
index = sctx->count & 0x3f;
|
||||
end = (index < 56) ? SHA1_BLOCK_SIZE : (2 * SHA1_BLOCK_SIZE);
|
||||
|
||||
/* start pad with 1 */
|
||||
sctx->buf[index] = 0x80;
|
||||
|
||||
/* pad with zeros */
|
||||
index++;
|
||||
memset(sctx->buf + index, 0x00, end - index - 8);
|
||||
|
||||
/* append message length */
|
||||
bits = sctx->count * 8;
|
||||
memcpy(sctx->buf + end - 8, &bits, sizeof(bits));
|
||||
|
||||
ret = crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buf, end);
|
||||
BUG_ON(ret != end);
|
||||
|
||||
/* copy digest to out */
|
||||
memcpy(out, sctx->state, SHA1_DIGEST_SIZE);
|
||||
|
||||
/* wipe context */
|
||||
memset(sctx, 0, sizeof *sctx);
|
||||
}
|
||||
@@ -128,7 +129,7 @@ static struct crypto_alg alg = {
|
||||
.cra_priority = CRYPT_S390_PRIORITY,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_DIGEST,
|
||||
.cra_blocksize = SHA1_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct crypt_s390_sha1_ctx),
|
||||
.cra_ctxsize = sizeof(struct s390_sha1_ctx),
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_list = LIST_HEAD_INIT(alg.cra_list),
|
||||
.cra_u = { .digest = {
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#define SHA256_BLOCK_SIZE 64
|
||||
|
||||
struct s390_sha256_ctx {
|
||||
u64 count;
|
||||
u64 count; /* message length */
|
||||
u32 state[8];
|
||||
u8 buf[2 * SHA256_BLOCK_SIZE];
|
||||
};
|
||||
@@ -54,10 +54,9 @@ static void sha256_update(struct crypto_tfm *tfm, const u8 *data,
|
||||
int ret;
|
||||
|
||||
/* how much is already in the buffer? */
|
||||
index = sctx->count / 8 & 0x3f;
|
||||
index = sctx->count & 0x3f;
|
||||
|
||||
/* update message bit length */
|
||||
sctx->count += len * 8;
|
||||
sctx->count += len;
|
||||
|
||||
if ((index + len) < SHA256_BLOCK_SIZE)
|
||||
goto store;
|
||||
@@ -87,12 +86,17 @@ store:
|
||||
memcpy(sctx->buf + index , data, len);
|
||||
}
|
||||
|
||||
static void pad_message(struct s390_sha256_ctx* sctx)
|
||||
/* Add padding and return the message digest */
|
||||
static void sha256_final(struct crypto_tfm *tfm, u8 *out)
|
||||
{
|
||||
int index, end;
|
||||
struct s390_sha256_ctx *sctx = crypto_tfm_ctx(tfm);
|
||||
u64 bits;
|
||||
unsigned int index, end;
|
||||
int ret;
|
||||
|
||||
index = sctx->count / 8 & 0x3f;
|
||||
end = index < 56 ? SHA256_BLOCK_SIZE : 2 * SHA256_BLOCK_SIZE;
|
||||
/* must perform manual padding */
|
||||
index = sctx->count & 0x3f;
|
||||
end = (index < 56) ? SHA256_BLOCK_SIZE : (2 * SHA256_BLOCK_SIZE);
|
||||
|
||||
/* start pad with 1 */
|
||||
sctx->buf[index] = 0x80;
|
||||
@@ -102,21 +106,11 @@ static void pad_message(struct s390_sha256_ctx* sctx)
|
||||
memset(sctx->buf + index, 0x00, end - index - 8);
|
||||
|
||||
/* append message length */
|
||||
memcpy(sctx->buf + end - 8, &sctx->count, sizeof sctx->count);
|
||||
bits = sctx->count * 8;
|
||||
memcpy(sctx->buf + end - 8, &bits, sizeof(bits));
|
||||
|
||||
sctx->count = end * 8;
|
||||
}
|
||||
|
||||
/* Add padding and return the message digest */
|
||||
static void sha256_final(struct crypto_tfm *tfm, u8 *out)
|
||||
{
|
||||
struct s390_sha256_ctx *sctx = crypto_tfm_ctx(tfm);
|
||||
|
||||
/* must perform manual padding */
|
||||
pad_message(sctx);
|
||||
|
||||
crypt_s390_kimd(KIMD_SHA_256, sctx->state, sctx->buf,
|
||||
sctx->count / 8);
|
||||
ret = crypt_s390_kimd(KIMD_SHA_256, sctx->state, sctx->buf, end);
|
||||
BUG_ON(ret != end);
|
||||
|
||||
/* copy digest to out */
|
||||
memcpy(out, sctx->state, SHA256_DIGEST_SIZE);
|
||||
|
||||
@@ -12,6 +12,7 @@ CONFIG_RWSEM_XCHGADD_ALGORITHM=y
|
||||
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
|
||||
CONFIG_GENERIC_HWEIGHT=y
|
||||
CONFIG_GENERIC_TIME=y
|
||||
CONFIG_GENERIC_BUG=y
|
||||
CONFIG_NO_IOMEM=y
|
||||
CONFIG_S390=y
|
||||
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
|
||||
@@ -166,6 +167,7 @@ CONFIG_NO_IDLE_HZ=y
|
||||
CONFIG_NO_IDLE_HZ_INIT=y
|
||||
CONFIG_S390_HYPFS_FS=y
|
||||
CONFIG_KEXEC=y
|
||||
# CONFIG_ZFCPDUMP is not set
|
||||
|
||||
#
|
||||
# Networking
|
||||
@@ -705,6 +707,7 @@ CONFIG_DEBUG_MUTEXES=y
|
||||
CONFIG_DEBUG_SPINLOCK_SLEEP=y
|
||||
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
|
||||
# CONFIG_DEBUG_KOBJECT is not set
|
||||
CONFIG_DEBUG_BUGVERBOSE=y
|
||||
# CONFIG_DEBUG_INFO is not set
|
||||
# CONFIG_DEBUG_VM is not set
|
||||
# CONFIG_DEBUG_LIST is not set
|
||||
|
||||
@@ -6,7 +6,7 @@ EXTRA_AFLAGS := -traditional
|
||||
|
||||
obj-y := bitmap.o traps.o time.o process.o base.o early.o \
|
||||
setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
|
||||
semaphore.o s390_ext.o debug.o irq.o ipl.o
|
||||
semaphore.o s390_ext.o debug.o irq.o ipl.o dis.o
|
||||
|
||||
obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o)
|
||||
obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
|
||||
|
||||
@@ -495,29 +495,34 @@ sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo)
|
||||
* sys32_execve() executes a new program after the asm stub has set
|
||||
* things up for us. This should basically do what I want it to.
|
||||
*/
|
||||
asmlinkage long
|
||||
sys32_execve(struct pt_regs regs)
|
||||
asmlinkage long sys32_execve(void)
|
||||
{
|
||||
int error;
|
||||
char * filename;
|
||||
struct pt_regs *regs = task_pt_regs(current);
|
||||
char *filename;
|
||||
unsigned long result;
|
||||
int rc;
|
||||
|
||||
filename = getname(compat_ptr(regs.orig_gpr2));
|
||||
error = PTR_ERR(filename);
|
||||
if (IS_ERR(filename))
|
||||
filename = getname(compat_ptr(regs->orig_gpr2));
|
||||
if (IS_ERR(filename)) {
|
||||
result = PTR_ERR(filename);
|
||||
goto out;
|
||||
error = compat_do_execve(filename, compat_ptr(regs.gprs[3]),
|
||||
compat_ptr(regs.gprs[4]), ®s);
|
||||
if (error == 0)
|
||||
{
|
||||
task_lock(current);
|
||||
current->ptrace &= ~PT_DTRACE;
|
||||
task_unlock(current);
|
||||
current->thread.fp_regs.fpc=0;
|
||||
asm volatile("sfpc %0,0" : : "d" (0));
|
||||
}
|
||||
rc = compat_do_execve(filename, compat_ptr(regs->gprs[3]),
|
||||
compat_ptr(regs->gprs[4]), regs);
|
||||
if (rc) {
|
||||
result = rc;
|
||||
goto out_putname;
|
||||
}
|
||||
task_lock(current);
|
||||
current->ptrace &= ~PT_DTRACE;
|
||||
task_unlock(current);
|
||||
current->thread.fp_regs.fpc=0;
|
||||
asm volatile("sfpc %0,0" : : "d" (0));
|
||||
result = regs->gprs[2];
|
||||
out_putname:
|
||||
putname(filename);
|
||||
out:
|
||||
return error;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -918,19 +923,20 @@ asmlinkage long sys32_write(unsigned int fd, char __user * buf, size_t count)
|
||||
return sys_write(fd, buf, count);
|
||||
}
|
||||
|
||||
asmlinkage long sys32_clone(struct pt_regs regs)
|
||||
asmlinkage long sys32_clone(void)
|
||||
{
|
||||
unsigned long clone_flags;
|
||||
unsigned long newsp;
|
||||
struct pt_regs *regs = task_pt_regs(current);
|
||||
unsigned long clone_flags;
|
||||
unsigned long newsp;
|
||||
int __user *parent_tidptr, *child_tidptr;
|
||||
|
||||
clone_flags = regs.gprs[3] & 0xffffffffUL;
|
||||
newsp = regs.orig_gpr2 & 0x7fffffffUL;
|
||||
parent_tidptr = compat_ptr(regs.gprs[4]);
|
||||
child_tidptr = compat_ptr(regs.gprs[5]);
|
||||
if (!newsp)
|
||||
newsp = regs.gprs[15];
|
||||
return do_fork(clone_flags, newsp, ®s, 0,
|
||||
clone_flags = regs->gprs[3] & 0xffffffffUL;
|
||||
newsp = regs->orig_gpr2 & 0x7fffffffUL;
|
||||
parent_tidptr = compat_ptr(regs->gprs[4]);
|
||||
child_tidptr = compat_ptr(regs->gprs[5]);
|
||||
if (!newsp)
|
||||
newsp = regs->gprs[15];
|
||||
return do_fork(clone_flags, newsp, regs, 0,
|
||||
parent_tidptr, child_tidptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -255,9 +255,9 @@ sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
|
||||
}
|
||||
|
||||
asmlinkage long
|
||||
sys32_sigaltstack(const stack_t32 __user *uss, stack_t32 __user *uoss,
|
||||
struct pt_regs *regs)
|
||||
sys32_sigaltstack(const stack_t32 __user *uss, stack_t32 __user *uoss)
|
||||
{
|
||||
struct pt_regs *regs = task_pt_regs(current);
|
||||
stack_t kss, koss;
|
||||
unsigned long ss_sp;
|
||||
int ret, err = 0;
|
||||
@@ -344,8 +344,9 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
|
||||
return 0;
|
||||
}
|
||||
|
||||
asmlinkage long sys32_sigreturn(struct pt_regs *regs)
|
||||
asmlinkage long sys32_sigreturn(void)
|
||||
{
|
||||
struct pt_regs *regs = task_pt_regs(current);
|
||||
sigframe32 __user *frame = (sigframe32 __user *)regs->gprs[15];
|
||||
sigset_t set;
|
||||
|
||||
@@ -370,8 +371,9 @@ badframe:
|
||||
return 0;
|
||||
}
|
||||
|
||||
asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
|
||||
asmlinkage long sys32_rt_sigreturn(void)
|
||||
{
|
||||
struct pt_regs *regs = task_pt_regs(current);
|
||||
rt_sigframe32 __user *frame = (rt_sigframe32 __user *)regs->gprs[15];
|
||||
sigset_t set;
|
||||
stack_t st;
|
||||
@@ -407,8 +409,8 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
|
||||
return regs->gprs[2];
|
||||
|
||||
badframe:
|
||||
force_sig(SIGSEGV, current);
|
||||
return 0;
|
||||
force_sig(SIGSEGV, current);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -253,11 +253,10 @@ static noinline __init void find_memory_chunks(unsigned long memsize)
|
||||
break;
|
||||
#endif
|
||||
/*
|
||||
* Finish memory detection at the first hole, unless
|
||||
* - we reached the hsa -> skip it.
|
||||
* - we know there must be more.
|
||||
* Finish memory detection at the first hole
|
||||
* if storage size is unknown.
|
||||
*/
|
||||
if (cc == -1UL && !memsize && old_addr != ADDR2G)
|
||||
if (cc == -1UL && !memsize)
|
||||
break;
|
||||
if (memsize && addr >= memsize)
|
||||
break;
|
||||
|
||||
+32
-55
@@ -249,8 +249,6 @@ sysc_do_restart:
|
||||
bnz BASED(sysc_tracesys)
|
||||
basr %r14,%r8 # call sys_xxxx
|
||||
st %r2,SP_R2(%r15) # store return value (change R2 on stack)
|
||||
# ATTENTION: check sys_execve_glue before
|
||||
# changing anything here !!
|
||||
|
||||
sysc_return:
|
||||
tm SP_PSW+1(%r15),0x01 # returning to user ?
|
||||
@@ -381,50 +379,37 @@ ret_from_fork:
|
||||
b BASED(sysc_return)
|
||||
|
||||
#
|
||||
# clone, fork, vfork, exec and sigreturn need glue,
|
||||
# because they all expect pt_regs as parameter,
|
||||
# but are called with different parameter.
|
||||
# return-address is set up above
|
||||
# kernel_execve function needs to deal with pt_regs that is not
|
||||
# at the usual place
|
||||
#
|
||||
sys_clone_glue:
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs
|
||||
l %r1,BASED(.Lclone)
|
||||
br %r1 # branch to sys_clone
|
||||
|
||||
sys_fork_glue:
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs
|
||||
l %r1,BASED(.Lfork)
|
||||
br %r1 # branch to sys_fork
|
||||
|
||||
sys_vfork_glue:
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs
|
||||
l %r1,BASED(.Lvfork)
|
||||
br %r1 # branch to sys_vfork
|
||||
|
||||
sys_execve_glue:
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs
|
||||
l %r1,BASED(.Lexecve)
|
||||
lr %r12,%r14 # save return address
|
||||
basr %r14,%r1 # call sys_execve
|
||||
ltr %r2,%r2 # check if execve failed
|
||||
bnz 0(%r12) # it did fail -> store result in gpr2
|
||||
b 4(%r12) # SKIP ST 2,SP_R2(15) after BASR 14,8
|
||||
# in system_call/sysc_tracesys
|
||||
|
||||
sys_sigreturn_glue:
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs as parameter
|
||||
l %r1,BASED(.Lsigreturn)
|
||||
br %r1 # branch to sys_sigreturn
|
||||
|
||||
sys_rt_sigreturn_glue:
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs as parameter
|
||||
l %r1,BASED(.Lrt_sigreturn)
|
||||
br %r1 # branch to sys_sigreturn
|
||||
|
||||
sys_sigaltstack_glue:
|
||||
la %r4,SP_PTREGS(%r15) # load pt_regs as parameter
|
||||
l %r1,BASED(.Lsigaltstack)
|
||||
br %r1 # branch to sys_sigreturn
|
||||
.globl kernel_execve
|
||||
kernel_execve:
|
||||
stm %r12,%r15,48(%r15)
|
||||
lr %r14,%r15
|
||||
l %r13,__LC_SVC_NEW_PSW+4
|
||||
s %r15,BASED(.Lc_spsize)
|
||||
st %r14,__SF_BACKCHAIN(%r15)
|
||||
la %r12,SP_PTREGS(%r15)
|
||||
xc 0(__PT_SIZE,%r12),0(%r12)
|
||||
l %r1,BASED(.Ldo_execve)
|
||||
lr %r5,%r12
|
||||
basr %r14,%r1
|
||||
ltr %r2,%r2
|
||||
be BASED(0f)
|
||||
a %r15,BASED(.Lc_spsize)
|
||||
lm %r12,%r15,48(%r15)
|
||||
br %r14
|
||||
# execve succeeded.
|
||||
0: stnsm __SF_EMPTY(%r15),0xfc # disable interrupts
|
||||
l %r15,__LC_KERNEL_STACK # load ksp
|
||||
s %r15,BASED(.Lc_spsize) # make room for registers & psw
|
||||
l %r9,__LC_THREAD_INFO
|
||||
mvc SP_PTREGS(__PT_SIZE,%r15),0(%r12) # copy pt_regs
|
||||
xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
|
||||
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
|
||||
l %r1,BASED(.Lexecve_tail)
|
||||
basr %r14,%r1
|
||||
b BASED(sysc_return)
|
||||
|
||||
/*
|
||||
* Program check handler routine
|
||||
@@ -1031,19 +1016,11 @@ cleanup_io_leave_insn:
|
||||
.Ldo_extint: .long do_extint
|
||||
.Ldo_signal: .long do_signal
|
||||
.Lhandle_per: .long do_single_step
|
||||
.Ldo_execve: .long do_execve
|
||||
.Lexecve_tail: .long execve_tail
|
||||
.Ljump_table: .long pgm_check_table
|
||||
.Lschedule: .long schedule
|
||||
.Lclone: .long sys_clone
|
||||
.Lexecve: .long sys_execve
|
||||
.Lfork: .long sys_fork
|
||||
.Lrt_sigreturn: .long sys_rt_sigreturn
|
||||
.Lrt_sigsuspend:
|
||||
.long sys_rt_sigsuspend
|
||||
.Lsigreturn: .long sys_sigreturn
|
||||
.Lsigsuspend: .long sys_sigsuspend
|
||||
.Lsigaltstack: .long sys_sigaltstack
|
||||
.Ltrace: .long syscall_trace
|
||||
.Lvfork: .long sys_vfork
|
||||
.Lschedtail: .long schedule_tail
|
||||
.Lsysc_table: .long sys_call_table
|
||||
#ifdef CONFIG_TRACE_IRQFLAGS
|
||||
|
||||
+28
-72
@@ -244,8 +244,6 @@ sysc_noemu:
|
||||
jnz sysc_tracesys
|
||||
basr %r14,%r8 # call sys_xxxx
|
||||
stg %r2,SP_R2(%r15) # store return value (change R2 on stack)
|
||||
# ATTENTION: check sys_execve_glue before
|
||||
# changing anything here !!
|
||||
|
||||
sysc_return:
|
||||
tm SP_PSW+1(%r15),0x01 # returning to user ?
|
||||
@@ -371,77 +369,35 @@ ret_from_fork:
|
||||
j sysc_return
|
||||
|
||||
#
|
||||
# clone, fork, vfork, exec and sigreturn need glue,
|
||||
# because they all expect pt_regs as parameter,
|
||||
# but are called with different parameter.
|
||||
# return-address is set up above
|
||||
# kernel_execve function needs to deal with pt_regs that is not
|
||||
# at the usual place
|
||||
#
|
||||
sys_clone_glue:
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs
|
||||
jg sys_clone # branch to sys_clone
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
sys32_clone_glue:
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs
|
||||
jg sys32_clone # branch to sys32_clone
|
||||
#endif
|
||||
|
||||
sys_fork_glue:
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs
|
||||
jg sys_fork # branch to sys_fork
|
||||
|
||||
sys_vfork_glue:
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs
|
||||
jg sys_vfork # branch to sys_vfork
|
||||
|
||||
sys_execve_glue:
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs
|
||||
lgr %r12,%r14 # save return address
|
||||
brasl %r14,sys_execve # call sys_execve
|
||||
ltgr %r2,%r2 # check if execve failed
|
||||
bnz 0(%r12) # it did fail -> store result in gpr2
|
||||
b 6(%r12) # SKIP STG 2,SP_R2(15) in
|
||||
# system_call/sysc_tracesys
|
||||
#ifdef CONFIG_COMPAT
|
||||
sys32_execve_glue:
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs
|
||||
lgr %r12,%r14 # save return address
|
||||
brasl %r14,sys32_execve # call sys32_execve
|
||||
ltgr %r2,%r2 # check if execve failed
|
||||
bnz 0(%r12) # it did fail -> store result in gpr2
|
||||
b 6(%r12) # SKIP STG 2,SP_R2(15) in
|
||||
# system_call/sysc_tracesys
|
||||
#endif
|
||||
|
||||
sys_sigreturn_glue:
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs as parameter
|
||||
jg sys_sigreturn # branch to sys_sigreturn
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
sys32_sigreturn_glue:
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs as parameter
|
||||
jg sys32_sigreturn # branch to sys32_sigreturn
|
||||
#endif
|
||||
|
||||
sys_rt_sigreturn_glue:
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs as parameter
|
||||
jg sys_rt_sigreturn # branch to sys_sigreturn
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
sys32_rt_sigreturn_glue:
|
||||
la %r2,SP_PTREGS(%r15) # load pt_regs as parameter
|
||||
jg sys32_rt_sigreturn # branch to sys32_sigreturn
|
||||
#endif
|
||||
|
||||
sys_sigaltstack_glue:
|
||||
la %r4,SP_PTREGS(%r15) # load pt_regs as parameter
|
||||
jg sys_sigaltstack # branch to sys_sigreturn
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
sys32_sigaltstack_glue:
|
||||
la %r4,SP_PTREGS(%r15) # load pt_regs as parameter
|
||||
jg sys32_sigaltstack_wrapper # branch to sys_sigreturn
|
||||
#endif
|
||||
.globl kernel_execve
|
||||
kernel_execve:
|
||||
stmg %r12,%r15,96(%r15)
|
||||
lgr %r14,%r15
|
||||
aghi %r15,-SP_SIZE
|
||||
stg %r14,__SF_BACKCHAIN(%r15)
|
||||
la %r12,SP_PTREGS(%r15)
|
||||
xc 0(__PT_SIZE,%r12),0(%r12)
|
||||
lgr %r5,%r12
|
||||
brasl %r14,do_execve
|
||||
ltgfr %r2,%r2
|
||||
je 0f
|
||||
aghi %r15,SP_SIZE
|
||||
lmg %r12,%r15,96(%r15)
|
||||
br %r14
|
||||
# execve succeeded.
|
||||
0: stnsm __SF_EMPTY(%r15),0xfc # disable interrupts
|
||||
lg %r15,__LC_KERNEL_STACK # load ksp
|
||||
aghi %r15,-SP_SIZE # make room for registers & psw
|
||||
lg %r13,__LC_SVC_NEW_PSW+8
|
||||
lg %r9,__LC_THREAD_INFO
|
||||
mvc SP_PTREGS(__PT_SIZE,%r15),0(%r12) # copy pt_regs
|
||||
xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
|
||||
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
|
||||
brasl %r14,execve_tail
|
||||
j sysc_return
|
||||
|
||||
/*
|
||||
* Program check handler routine
|
||||
|
||||
@@ -39,7 +39,69 @@ startup_continue:
|
||||
basr %r13,0 # get base
|
||||
.LPG1: sll %r13,1 # remove high order bit
|
||||
srl %r13,1
|
||||
lhi %r1,1 # mode 1 = esame
|
||||
|
||||
#ifdef CONFIG_ZFCPDUMP
|
||||
|
||||
# check if we have been ipled using zfcp dump:
|
||||
|
||||
tm 0xb9,0x01 # test if subchannel is enabled
|
||||
jno .nodump # subchannel disabled
|
||||
l %r1,0xb8
|
||||
la %r5,.Lipl_schib-.LPG1(%r13)
|
||||
stsch 0(%r5) # get schib of subchannel
|
||||
jne .nodump # schib not available
|
||||
tm 5(%r5),0x01 # devno valid?
|
||||
jno .nodump
|
||||
tm 4(%r5),0x80 # qdio capable device?
|
||||
jno .nodump
|
||||
l %r2,20(%r0) # address of ipl parameter block
|
||||
lhi %r3,0
|
||||
ic %r3,0x148(%r2) # get opt field
|
||||
chi %r3,0x20 # load with dump?
|
||||
jne .nodump
|
||||
|
||||
# store all prefix registers in case of load with dump:
|
||||
|
||||
la %r7,0 # base register for 0 page
|
||||
la %r8,0 # first cpu
|
||||
l %r11,.Lpref_arr_ptr-.LPG1(%r13) # address of prefix array
|
||||
ahi %r11,4 # skip boot cpu
|
||||
lr %r12,%r11
|
||||
ahi %r12,(CONFIG_NR_CPUS*4) # end of prefix array
|
||||
stap .Lcurrent_cpu+2-.LPG1(%r13) # store current cpu addr
|
||||
1:
|
||||
cl %r8,.Lcurrent_cpu-.LPG1(%r13) # is ipl cpu ?
|
||||
je 4f # if yes get next cpu
|
||||
2:
|
||||
lr %r9,%r7
|
||||
sigp %r9,%r8,0x9 # stop & store status of cpu
|
||||
brc 8,3f # accepted
|
||||
brc 4,4f # status stored: next cpu
|
||||
brc 2,2b # busy: try again
|
||||
brc 1,4f # not op: next cpu
|
||||
3:
|
||||
mvc 0(4,%r11),264(%r7) # copy prefix register to prefix array
|
||||
ahi %r11,4 # next element in prefix array
|
||||
clr %r11,%r12
|
||||
je 5f # no more space in prefix array
|
||||
4:
|
||||
ahi %r8,1 # next cpu (r8 += 1)
|
||||
cl %r8,.Llast_cpu-.LPG1(%r13) # is last possible cpu ?
|
||||
jl 1b # jump if not last cpu
|
||||
5:
|
||||
lhi %r1,2 # mode 2 = esame (dump)
|
||||
j 6f
|
||||
.align 4
|
||||
.Lipl_schib:
|
||||
.rept 13
|
||||
.long 0
|
||||
.endr
|
||||
.nodump:
|
||||
lhi %r1,1 # mode 1 = esame (normal ipl)
|
||||
6:
|
||||
#else
|
||||
lhi %r1,1 # mode 1 = esame (normal ipl)
|
||||
#endif /* CONFIG_ZFCPDUMP */
|
||||
mvi __LC_AR_MODE_ID,1 # set esame flag
|
||||
slr %r0,%r0 # set cpuid to zero
|
||||
sigp %r1,%r0,0x12 # switch to esame mode
|
||||
@@ -149,6 +211,14 @@ startup_continue:
|
||||
.L4malign:.quad 0xffffffffffc00000
|
||||
.Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8
|
||||
.Lnop: .long 0x07000700
|
||||
#ifdef CONFIG_ZFCPDUMP
|
||||
.Lcurrent_cpu:
|
||||
.long 0x0
|
||||
.Llast_cpu:
|
||||
.long 0x0000ffff
|
||||
.Lpref_arr_ptr:
|
||||
.long zfcpdump_prefix_array
|
||||
#endif /* CONFIG_ZFCPDUMP */
|
||||
.Lparmaddr:
|
||||
.quad PARMAREA
|
||||
.align 64
|
||||
|
||||
+171
-82
@@ -29,36 +29,21 @@
|
||||
#define SCCB_LOADPARM (&s390_readinfo_sccb.loadparm)
|
||||
#define SCCB_FLAG (s390_readinfo_sccb.flags)
|
||||
|
||||
enum ipl_type {
|
||||
IPL_TYPE_NONE = 1,
|
||||
IPL_TYPE_UNKNOWN = 2,
|
||||
IPL_TYPE_CCW = 4,
|
||||
IPL_TYPE_FCP = 8,
|
||||
IPL_TYPE_NSS = 16,
|
||||
};
|
||||
|
||||
#define IPL_NONE_STR "none"
|
||||
#define IPL_UNKNOWN_STR "unknown"
|
||||
#define IPL_CCW_STR "ccw"
|
||||
#define IPL_FCP_STR "fcp"
|
||||
#define IPL_NSS_STR "nss"
|
||||
|
||||
/*
|
||||
* Must be in data section since the bss section
|
||||
* is not cleared when these are accessed.
|
||||
*/
|
||||
u16 ipl_devno __attribute__((__section__(".data"))) = 0;
|
||||
u32 ipl_flags __attribute__((__section__(".data"))) = 0;
|
||||
#define IPL_UNKNOWN_STR "unknown"
|
||||
#define IPL_CCW_STR "ccw"
|
||||
#define IPL_FCP_STR "fcp"
|
||||
#define IPL_FCP_DUMP_STR "fcp_dump"
|
||||
#define IPL_NSS_STR "nss"
|
||||
|
||||
static char *ipl_type_str(enum ipl_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case IPL_TYPE_NONE:
|
||||
return IPL_NONE_STR;
|
||||
case IPL_TYPE_CCW:
|
||||
return IPL_CCW_STR;
|
||||
case IPL_TYPE_FCP:
|
||||
return IPL_FCP_STR;
|
||||
case IPL_TYPE_FCP_DUMP:
|
||||
return IPL_FCP_DUMP_STR;
|
||||
case IPL_TYPE_NSS:
|
||||
return IPL_NSS_STR;
|
||||
case IPL_TYPE_UNKNOWN:
|
||||
@@ -67,15 +52,55 @@ static char *ipl_type_str(enum ipl_type type)
|
||||
}
|
||||
}
|
||||
|
||||
enum dump_type {
|
||||
DUMP_TYPE_NONE = 1,
|
||||
DUMP_TYPE_CCW = 2,
|
||||
DUMP_TYPE_FCP = 4,
|
||||
};
|
||||
|
||||
#define DUMP_NONE_STR "none"
|
||||
#define DUMP_CCW_STR "ccw"
|
||||
#define DUMP_FCP_STR "fcp"
|
||||
|
||||
static char *dump_type_str(enum dump_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case DUMP_TYPE_NONE:
|
||||
return DUMP_NONE_STR;
|
||||
case DUMP_TYPE_CCW:
|
||||
return DUMP_CCW_STR;
|
||||
case DUMP_TYPE_FCP:
|
||||
return DUMP_FCP_STR;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Must be in data section since the bss section
|
||||
* is not cleared when these are accessed.
|
||||
*/
|
||||
static u16 ipl_devno __attribute__((__section__(".data"))) = 0;
|
||||
u32 ipl_flags __attribute__((__section__(".data"))) = 0;
|
||||
|
||||
enum ipl_method {
|
||||
IPL_METHOD_NONE,
|
||||
IPL_METHOD_CCW_CIO,
|
||||
IPL_METHOD_CCW_DIAG,
|
||||
IPL_METHOD_CCW_VM,
|
||||
IPL_METHOD_FCP_RO_DIAG,
|
||||
IPL_METHOD_FCP_RW_DIAG,
|
||||
IPL_METHOD_FCP_RO_VM,
|
||||
IPL_METHOD_NSS,
|
||||
REIPL_METHOD_CCW_CIO,
|
||||
REIPL_METHOD_CCW_DIAG,
|
||||
REIPL_METHOD_CCW_VM,
|
||||
REIPL_METHOD_FCP_RO_DIAG,
|
||||
REIPL_METHOD_FCP_RW_DIAG,
|
||||
REIPL_METHOD_FCP_RO_VM,
|
||||
REIPL_METHOD_FCP_DUMP,
|
||||
REIPL_METHOD_NSS,
|
||||
REIPL_METHOD_DEFAULT,
|
||||
};
|
||||
|
||||
enum dump_method {
|
||||
DUMP_METHOD_NONE,
|
||||
DUMP_METHOD_CCW_CIO,
|
||||
DUMP_METHOD_CCW_DIAG,
|
||||
DUMP_METHOD_CCW_VM,
|
||||
DUMP_METHOD_FCP_DIAG,
|
||||
};
|
||||
|
||||
enum shutdown_action {
|
||||
@@ -107,15 +132,15 @@ static int diag308_set_works = 0;
|
||||
static int reipl_capabilities = IPL_TYPE_UNKNOWN;
|
||||
|
||||
static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN;
|
||||
static enum ipl_method reipl_method = IPL_METHOD_NONE;
|
||||
static enum ipl_method reipl_method = REIPL_METHOD_DEFAULT;
|
||||
static struct ipl_parameter_block *reipl_block_fcp;
|
||||
static struct ipl_parameter_block *reipl_block_ccw;
|
||||
|
||||
static char reipl_nss_name[NSS_NAME_SIZE + 1];
|
||||
|
||||
static int dump_capabilities = IPL_TYPE_NONE;
|
||||
static enum ipl_type dump_type = IPL_TYPE_NONE;
|
||||
static enum ipl_method dump_method = IPL_METHOD_NONE;
|
||||
static int dump_capabilities = DUMP_TYPE_NONE;
|
||||
static enum dump_type dump_type = DUMP_TYPE_NONE;
|
||||
static enum dump_method dump_method = DUMP_METHOD_NONE;
|
||||
static struct ipl_parameter_block *dump_block_fcp;
|
||||
static struct ipl_parameter_block *dump_block_ccw;
|
||||
|
||||
@@ -134,6 +159,7 @@ int diag308(unsigned long subcode, void *addr)
|
||||
: "d" (subcode) : "cc", "memory");
|
||||
return _rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(diag308);
|
||||
|
||||
/* SYSFS */
|
||||
|
||||
@@ -197,7 +223,7 @@ static void make_attrs_ro(struct attribute **attrs)
|
||||
* ipl section
|
||||
*/
|
||||
|
||||
static enum ipl_type ipl_get_type(void)
|
||||
static __init enum ipl_type get_ipl_type(void)
|
||||
{
|
||||
struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
|
||||
|
||||
@@ -211,12 +237,44 @@ static enum ipl_type ipl_get_type(void)
|
||||
return IPL_TYPE_UNKNOWN;
|
||||
if (ipl->hdr.pbt != DIAG308_IPL_TYPE_FCP)
|
||||
return IPL_TYPE_UNKNOWN;
|
||||
if (ipl->ipl_info.fcp.opt == DIAG308_IPL_OPT_DUMP)
|
||||
return IPL_TYPE_FCP_DUMP;
|
||||
return IPL_TYPE_FCP;
|
||||
}
|
||||
|
||||
void __init setup_ipl_info(void)
|
||||
{
|
||||
ipl_info.type = get_ipl_type();
|
||||
switch (ipl_info.type) {
|
||||
case IPL_TYPE_CCW:
|
||||
ipl_info.data.ccw.dev_id.devno = ipl_devno;
|
||||
ipl_info.data.ccw.dev_id.ssid = 0;
|
||||
break;
|
||||
case IPL_TYPE_FCP:
|
||||
case IPL_TYPE_FCP_DUMP:
|
||||
ipl_info.data.fcp.dev_id.devno =
|
||||
IPL_PARMBLOCK_START->ipl_info.fcp.devno;
|
||||
ipl_info.data.fcp.dev_id.ssid = 0;
|
||||
ipl_info.data.fcp.wwpn = IPL_PARMBLOCK_START->ipl_info.fcp.wwpn;
|
||||
ipl_info.data.fcp.lun = IPL_PARMBLOCK_START->ipl_info.fcp.lun;
|
||||
break;
|
||||
case IPL_TYPE_NSS:
|
||||
strncpy(ipl_info.data.nss.name, kernel_nss_name,
|
||||
sizeof(ipl_info.data.nss.name));
|
||||
break;
|
||||
case IPL_TYPE_UNKNOWN:
|
||||
default:
|
||||
/* We have no info to copy */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct ipl_info ipl_info;
|
||||
EXPORT_SYMBOL_GPL(ipl_info);
|
||||
|
||||
static ssize_t ipl_type_show(struct subsystem *subsys, char *page)
|
||||
{
|
||||
return sprintf(page, "%s\n", ipl_type_str(ipl_get_type()));
|
||||
return sprintf(page, "%s\n", ipl_type_str(ipl_info.type));
|
||||
}
|
||||
|
||||
static struct subsys_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type);
|
||||
@@ -225,10 +283,11 @@ static ssize_t sys_ipl_device_show(struct subsystem *subsys, char *page)
|
||||
{
|
||||
struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
|
||||
|
||||
switch (ipl_get_type()) {
|
||||
switch (ipl_info.type) {
|
||||
case IPL_TYPE_CCW:
|
||||
return sprintf(page, "0.0.%04x\n", ipl_devno);
|
||||
case IPL_TYPE_FCP:
|
||||
case IPL_TYPE_FCP_DUMP:
|
||||
return sprintf(page, "0.0.%04x\n", ipl->ipl_info.fcp.devno);
|
||||
default:
|
||||
return 0;
|
||||
@@ -485,23 +544,29 @@ static int reipl_set_type(enum ipl_type type)
|
||||
switch(type) {
|
||||
case IPL_TYPE_CCW:
|
||||
if (MACHINE_IS_VM)
|
||||
reipl_method = IPL_METHOD_CCW_VM;
|
||||
reipl_method = REIPL_METHOD_CCW_VM;
|
||||
else
|
||||
reipl_method = IPL_METHOD_CCW_CIO;
|
||||
reipl_method = REIPL_METHOD_CCW_CIO;
|
||||
break;
|
||||
case IPL_TYPE_FCP:
|
||||
if (diag308_set_works)
|
||||
reipl_method = IPL_METHOD_FCP_RW_DIAG;
|
||||
reipl_method = REIPL_METHOD_FCP_RW_DIAG;
|
||||
else if (MACHINE_IS_VM)
|
||||
reipl_method = IPL_METHOD_FCP_RO_VM;
|
||||
reipl_method = REIPL_METHOD_FCP_RO_VM;
|
||||
else
|
||||
reipl_method = IPL_METHOD_FCP_RO_DIAG;
|
||||
reipl_method = REIPL_METHOD_FCP_RO_DIAG;
|
||||
break;
|
||||
case IPL_TYPE_FCP_DUMP:
|
||||
reipl_method = REIPL_METHOD_FCP_DUMP;
|
||||
break;
|
||||
case IPL_TYPE_NSS:
|
||||
reipl_method = IPL_METHOD_NSS;
|
||||
reipl_method = REIPL_METHOD_NSS;
|
||||
break;
|
||||
case IPL_TYPE_UNKNOWN:
|
||||
reipl_method = REIPL_METHOD_DEFAULT;
|
||||
break;
|
||||
default:
|
||||
reipl_method = IPL_METHOD_NONE;
|
||||
BUG();
|
||||
}
|
||||
reipl_type = type;
|
||||
return 0;
|
||||
@@ -579,22 +644,22 @@ static struct attribute_group dump_ccw_attr_group = {
|
||||
|
||||
/* dump type */
|
||||
|
||||
static int dump_set_type(enum ipl_type type)
|
||||
static int dump_set_type(enum dump_type type)
|
||||
{
|
||||
if (!(dump_capabilities & type))
|
||||
return -EINVAL;
|
||||
switch(type) {
|
||||
case IPL_TYPE_CCW:
|
||||
case DUMP_TYPE_CCW:
|
||||
if (MACHINE_IS_VM)
|
||||
dump_method = IPL_METHOD_CCW_VM;
|
||||
dump_method = DUMP_METHOD_CCW_VM;
|
||||
else
|
||||
dump_method = IPL_METHOD_CCW_CIO;
|
||||
dump_method = DUMP_METHOD_CCW_CIO;
|
||||
break;
|
||||
case IPL_TYPE_FCP:
|
||||
dump_method = IPL_METHOD_FCP_RW_DIAG;
|
||||
case DUMP_TYPE_FCP:
|
||||
dump_method = DUMP_METHOD_FCP_DIAG;
|
||||
break;
|
||||
default:
|
||||
dump_method = IPL_METHOD_NONE;
|
||||
dump_method = DUMP_METHOD_NONE;
|
||||
}
|
||||
dump_type = type;
|
||||
return 0;
|
||||
@@ -602,7 +667,7 @@ static int dump_set_type(enum ipl_type type)
|
||||
|
||||
static ssize_t dump_type_show(struct subsystem *subsys, char *page)
|
||||
{
|
||||
return sprintf(page, "%s\n", ipl_type_str(dump_type));
|
||||
return sprintf(page, "%s\n", dump_type_str(dump_type));
|
||||
}
|
||||
|
||||
static ssize_t dump_type_store(struct subsystem *subsys, const char *buf,
|
||||
@@ -610,12 +675,12 @@ static ssize_t dump_type_store(struct subsystem *subsys, const char *buf,
|
||||
{
|
||||
int rc = -EINVAL;
|
||||
|
||||
if (strncmp(buf, IPL_NONE_STR, strlen(IPL_NONE_STR)) == 0)
|
||||
rc = dump_set_type(IPL_TYPE_NONE);
|
||||
else if (strncmp(buf, IPL_CCW_STR, strlen(IPL_CCW_STR)) == 0)
|
||||
rc = dump_set_type(IPL_TYPE_CCW);
|
||||
else if (strncmp(buf, IPL_FCP_STR, strlen(IPL_FCP_STR)) == 0)
|
||||
rc = dump_set_type(IPL_TYPE_FCP);
|
||||
if (strncmp(buf, DUMP_NONE_STR, strlen(DUMP_NONE_STR)) == 0)
|
||||
rc = dump_set_type(DUMP_TYPE_NONE);
|
||||
else if (strncmp(buf, DUMP_CCW_STR, strlen(DUMP_CCW_STR)) == 0)
|
||||
rc = dump_set_type(DUMP_TYPE_CCW);
|
||||
else if (strncmp(buf, DUMP_FCP_STR, strlen(DUMP_FCP_STR)) == 0)
|
||||
rc = dump_set_type(DUMP_TYPE_FCP);
|
||||
return (rc != 0) ? rc : len;
|
||||
}
|
||||
|
||||
@@ -664,14 +729,14 @@ void do_reipl(void)
|
||||
char loadparm[LOADPARM_LEN + 1];
|
||||
|
||||
switch (reipl_method) {
|
||||
case IPL_METHOD_CCW_CIO:
|
||||
case REIPL_METHOD_CCW_CIO:
|
||||
devid.devno = reipl_block_ccw->ipl_info.ccw.devno;
|
||||
if (ipl_get_type() == IPL_TYPE_CCW && devid.devno == ipl_devno)
|
||||
if (ipl_info.type == IPL_TYPE_CCW && devid.devno == ipl_devno)
|
||||
diag308(DIAG308_IPL, NULL);
|
||||
devid.ssid = 0;
|
||||
reipl_ccw_dev(&devid);
|
||||
break;
|
||||
case IPL_METHOD_CCW_VM:
|
||||
case REIPL_METHOD_CCW_VM:
|
||||
reipl_get_ascii_loadparm(loadparm);
|
||||
if (strlen(loadparm) == 0)
|
||||
sprintf(buf, "IPL %X",
|
||||
@@ -681,30 +746,32 @@ void do_reipl(void)
|
||||
reipl_block_ccw->ipl_info.ccw.devno, loadparm);
|
||||
__cpcmd(buf, NULL, 0, NULL);
|
||||
break;
|
||||
case IPL_METHOD_CCW_DIAG:
|
||||
case REIPL_METHOD_CCW_DIAG:
|
||||
diag308(DIAG308_SET, reipl_block_ccw);
|
||||
diag308(DIAG308_IPL, NULL);
|
||||
break;
|
||||
case IPL_METHOD_FCP_RW_DIAG:
|
||||
case REIPL_METHOD_FCP_RW_DIAG:
|
||||
diag308(DIAG308_SET, reipl_block_fcp);
|
||||
diag308(DIAG308_IPL, NULL);
|
||||
break;
|
||||
case IPL_METHOD_FCP_RO_DIAG:
|
||||
case REIPL_METHOD_FCP_RO_DIAG:
|
||||
diag308(DIAG308_IPL, NULL);
|
||||
break;
|
||||
case IPL_METHOD_FCP_RO_VM:
|
||||
case REIPL_METHOD_FCP_RO_VM:
|
||||
__cpcmd("IPL", NULL, 0, NULL);
|
||||
break;
|
||||
case IPL_METHOD_NSS:
|
||||
case REIPL_METHOD_NSS:
|
||||
sprintf(buf, "IPL %s", reipl_nss_name);
|
||||
__cpcmd(buf, NULL, 0, NULL);
|
||||
break;
|
||||
case IPL_METHOD_NONE:
|
||||
default:
|
||||
case REIPL_METHOD_DEFAULT:
|
||||
if (MACHINE_IS_VM)
|
||||
__cpcmd("IPL", NULL, 0, NULL);
|
||||
diag308(DIAG308_IPL, NULL);
|
||||
break;
|
||||
case REIPL_METHOD_FCP_DUMP:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
signal_processor(smp_processor_id(), sigp_stop_and_store_status);
|
||||
}
|
||||
@@ -715,28 +782,28 @@ static void do_dump(void)
|
||||
static char buf[100];
|
||||
|
||||
switch (dump_method) {
|
||||
case IPL_METHOD_CCW_CIO:
|
||||
case DUMP_METHOD_CCW_CIO:
|
||||
smp_send_stop();
|
||||
devid.devno = dump_block_ccw->ipl_info.ccw.devno;
|
||||
devid.ssid = 0;
|
||||
reipl_ccw_dev(&devid);
|
||||
break;
|
||||
case IPL_METHOD_CCW_VM:
|
||||
case DUMP_METHOD_CCW_VM:
|
||||
smp_send_stop();
|
||||
sprintf(buf, "STORE STATUS");
|
||||
__cpcmd(buf, NULL, 0, NULL);
|
||||
sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno);
|
||||
__cpcmd(buf, NULL, 0, NULL);
|
||||
break;
|
||||
case IPL_METHOD_CCW_DIAG:
|
||||
case DUMP_METHOD_CCW_DIAG:
|
||||
diag308(DIAG308_SET, dump_block_ccw);
|
||||
diag308(DIAG308_DUMP, NULL);
|
||||
break;
|
||||
case IPL_METHOD_FCP_RW_DIAG:
|
||||
case DUMP_METHOD_FCP_DIAG:
|
||||
diag308(DIAG308_SET, dump_block_fcp);
|
||||
diag308(DIAG308_DUMP, NULL);
|
||||
break;
|
||||
case IPL_METHOD_NONE:
|
||||
case DUMP_METHOD_NONE:
|
||||
default:
|
||||
return;
|
||||
}
|
||||
@@ -777,12 +844,13 @@ static int __init ipl_init(void)
|
||||
rc = firmware_register(&ipl_subsys);
|
||||
if (rc)
|
||||
return rc;
|
||||
switch (ipl_get_type()) {
|
||||
switch (ipl_info.type) {
|
||||
case IPL_TYPE_CCW:
|
||||
rc = sysfs_create_group(&ipl_subsys.kset.kobj,
|
||||
&ipl_ccw_attr_group);
|
||||
break;
|
||||
case IPL_TYPE_FCP:
|
||||
case IPL_TYPE_FCP_DUMP:
|
||||
rc = ipl_register_fcp_files();
|
||||
break;
|
||||
case IPL_TYPE_NSS:
|
||||
@@ -852,7 +920,7 @@ static int __init reipl_ccw_init(void)
|
||||
/* FIXME: check for diag308_set_works when enabling diag ccw reipl */
|
||||
if (!MACHINE_IS_VM)
|
||||
sys_reipl_ccw_loadparm_attr.attr.mode = S_IRUGO;
|
||||
if (ipl_get_type() == IPL_TYPE_CCW)
|
||||
if (ipl_info.type == IPL_TYPE_CCW)
|
||||
reipl_block_ccw->ipl_info.ccw.devno = ipl_devno;
|
||||
reipl_capabilities |= IPL_TYPE_CCW;
|
||||
return 0;
|
||||
@@ -862,9 +930,9 @@ static int __init reipl_fcp_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if ((!diag308_set_works) && (ipl_get_type() != IPL_TYPE_FCP))
|
||||
if ((!diag308_set_works) && (ipl_info.type != IPL_TYPE_FCP))
|
||||
return 0;
|
||||
if ((!diag308_set_works) && (ipl_get_type() == IPL_TYPE_FCP))
|
||||
if ((!diag308_set_works) && (ipl_info.type == IPL_TYPE_FCP))
|
||||
make_attrs_ro(reipl_fcp_attrs);
|
||||
|
||||
reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
|
||||
@@ -875,7 +943,7 @@ static int __init reipl_fcp_init(void)
|
||||
free_page((unsigned long)reipl_block_fcp);
|
||||
return rc;
|
||||
}
|
||||
if (ipl_get_type() == IPL_TYPE_FCP) {
|
||||
if (ipl_info.type == IPL_TYPE_FCP) {
|
||||
memcpy(reipl_block_fcp, IPL_PARMBLOCK_START, PAGE_SIZE);
|
||||
} else {
|
||||
reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
|
||||
@@ -909,7 +977,7 @@ static int __init reipl_init(void)
|
||||
rc = reipl_nss_init();
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = reipl_set_type(ipl_get_type());
|
||||
rc = reipl_set_type(ipl_info.type);
|
||||
if (rc)
|
||||
return rc;
|
||||
return 0;
|
||||
@@ -931,7 +999,7 @@ static int __init dump_ccw_init(void)
|
||||
dump_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION;
|
||||
dump_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
|
||||
dump_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
|
||||
dump_capabilities |= IPL_TYPE_CCW;
|
||||
dump_capabilities |= DUMP_TYPE_CCW;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -956,7 +1024,7 @@ static int __init dump_fcp_init(void)
|
||||
dump_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN;
|
||||
dump_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP;
|
||||
dump_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_DUMP;
|
||||
dump_capabilities |= IPL_TYPE_FCP;
|
||||
dump_capabilities |= DUMP_TYPE_FCP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -995,7 +1063,7 @@ static int __init dump_init(void)
|
||||
rc = dump_fcp_init();
|
||||
if (rc)
|
||||
return rc;
|
||||
dump_set_type(IPL_TYPE_NONE);
|
||||
dump_set_type(DUMP_TYPE_NONE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1038,6 +1106,27 @@ static int __init s390_ipl_init(void)
|
||||
|
||||
__initcall(s390_ipl_init);
|
||||
|
||||
void __init ipl_save_parameters(void)
|
||||
{
|
||||
struct cio_iplinfo iplinfo;
|
||||
unsigned int *ipl_ptr;
|
||||
void *src, *dst;
|
||||
|
||||
if (cio_get_iplinfo(&iplinfo))
|
||||
return;
|
||||
|
||||
ipl_devno = iplinfo.devno;
|
||||
ipl_flags |= IPL_DEVNO_VALID;
|
||||
if (!iplinfo.is_qdio)
|
||||
return;
|
||||
ipl_flags |= IPL_PARMBLOCK_VALID;
|
||||
ipl_ptr = (unsigned int *)__LC_IPL_PARMBLOCK_PTR;
|
||||
src = (void *)(unsigned long)*ipl_ptr;
|
||||
dst = (void *)IPL_PARMBLOCK_ORIGIN;
|
||||
memmove(dst, src, PAGE_SIZE);
|
||||
*ipl_ptr = IPL_PARMBLOCK_ORIGIN;
|
||||
}
|
||||
|
||||
static LIST_HEAD(rcall);
|
||||
static DEFINE_MUTEX(rcall_mutex);
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <linux/string.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/moduleloader.h>
|
||||
#include <linux/bug.h>
|
||||
|
||||
#if 0
|
||||
#define DEBUGP printk
|
||||
@@ -398,9 +399,10 @@ int module_finalize(const Elf_Ehdr *hdr,
|
||||
struct module *me)
|
||||
{
|
||||
vfree(me->arch.syminfo);
|
||||
return 0;
|
||||
return module_bug_finalize(hdr, sechdrs, me);
|
||||
}
|
||||
|
||||
void module_arch_cleanup(struct module *mod)
|
||||
{
|
||||
module_bug_cleanup(mod);
|
||||
}
|
||||
|
||||
+47
-33
@@ -280,24 +280,26 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
asmlinkage long sys_fork(struct pt_regs regs)
|
||||
asmlinkage long sys_fork(void)
|
||||
{
|
||||
return do_fork(SIGCHLD, regs.gprs[15], ®s, 0, NULL, NULL);
|
||||
struct pt_regs *regs = task_pt_regs(current);
|
||||
return do_fork(SIGCHLD, regs->gprs[15], regs, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
asmlinkage long sys_clone(struct pt_regs regs)
|
||||
asmlinkage long sys_clone(void)
|
||||
{
|
||||
unsigned long clone_flags;
|
||||
unsigned long newsp;
|
||||
struct pt_regs *regs = task_pt_regs(current);
|
||||
unsigned long clone_flags;
|
||||
unsigned long newsp;
|
||||
int __user *parent_tidptr, *child_tidptr;
|
||||
|
||||
clone_flags = regs.gprs[3];
|
||||
newsp = regs.orig_gpr2;
|
||||
parent_tidptr = (int __user *) regs.gprs[4];
|
||||
child_tidptr = (int __user *) regs.gprs[5];
|
||||
if (!newsp)
|
||||
newsp = regs.gprs[15];
|
||||
return do_fork(clone_flags, newsp, ®s, 0,
|
||||
clone_flags = regs->gprs[3];
|
||||
newsp = regs->orig_gpr2;
|
||||
parent_tidptr = (int __user *) regs->gprs[4];
|
||||
child_tidptr = (int __user *) regs->gprs[5];
|
||||
if (!newsp)
|
||||
newsp = regs->gprs[15];
|
||||
return do_fork(clone_flags, newsp, regs, 0,
|
||||
parent_tidptr, child_tidptr);
|
||||
}
|
||||
|
||||
@@ -311,40 +313,52 @@ asmlinkage long sys_clone(struct pt_regs regs)
|
||||
* do not have enough call-clobbered registers to hold all
|
||||
* the information you need.
|
||||
*/
|
||||
asmlinkage long sys_vfork(struct pt_regs regs)
|
||||
asmlinkage long sys_vfork(void)
|
||||
{
|
||||
struct pt_regs *regs = task_pt_regs(current);
|
||||
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
|
||||
regs.gprs[15], ®s, 0, NULL, NULL);
|
||||
regs->gprs[15], regs, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
asmlinkage void execve_tail(void)
|
||||
{
|
||||
task_lock(current);
|
||||
current->ptrace &= ~PT_DTRACE;
|
||||
task_unlock(current);
|
||||
current->thread.fp_regs.fpc = 0;
|
||||
if (MACHINE_HAS_IEEE)
|
||||
asm volatile("sfpc %0,%0" : : "d" (0));
|
||||
}
|
||||
|
||||
/*
|
||||
* sys_execve() executes a new program.
|
||||
*/
|
||||
asmlinkage long sys_execve(struct pt_regs regs)
|
||||
asmlinkage long sys_execve(void)
|
||||
{
|
||||
int error;
|
||||
char * filename;
|
||||
struct pt_regs *regs = task_pt_regs(current);
|
||||
char *filename;
|
||||
unsigned long result;
|
||||
int rc;
|
||||
|
||||
filename = getname((char __user *) regs.orig_gpr2);
|
||||
error = PTR_ERR(filename);
|
||||
if (IS_ERR(filename))
|
||||
goto out;
|
||||
error = do_execve(filename, (char __user * __user *) regs.gprs[3],
|
||||
(char __user * __user *) regs.gprs[4], ®s);
|
||||
if (error == 0) {
|
||||
task_lock(current);
|
||||
current->ptrace &= ~PT_DTRACE;
|
||||
task_unlock(current);
|
||||
current->thread.fp_regs.fpc = 0;
|
||||
if (MACHINE_HAS_IEEE)
|
||||
asm volatile("sfpc %0,%0" : : "d" (0));
|
||||
filename = getname((char __user *) regs->orig_gpr2);
|
||||
if (IS_ERR(filename)) {
|
||||
result = PTR_ERR(filename);
|
||||
goto out;
|
||||
}
|
||||
putname(filename);
|
||||
rc = do_execve(filename, (char __user * __user *) regs->gprs[3],
|
||||
(char __user * __user *) regs->gprs[4], regs);
|
||||
if (rc) {
|
||||
result = rc;
|
||||
goto out_putname;
|
||||
}
|
||||
execve_tail();
|
||||
result = regs->gprs[2];
|
||||
out_putname:
|
||||
putname(filename);
|
||||
out:
|
||||
return error;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fill in the FPU structure for a core dump.
|
||||
*/
|
||||
|
||||
@@ -285,6 +285,26 @@ static void __init conmode_default(void)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE)
|
||||
static void __init setup_zfcpdump(unsigned int console_devno)
|
||||
{
|
||||
static char str[64];
|
||||
|
||||
if (ipl_info.type != IPL_TYPE_FCP_DUMP)
|
||||
return;
|
||||
if (console_devno != -1)
|
||||
sprintf(str, "cio_ignore=all,!0.0.%04x,!0.0.%04x",
|
||||
ipl_info.data.fcp.dev_id.devno, console_devno);
|
||||
else
|
||||
sprintf(str, "cio_ignore=all,!0.0.%04x",
|
||||
ipl_info.data.fcp.dev_id.devno);
|
||||
strcat(COMMAND_LINE, str);
|
||||
console_loglevel = 2;
|
||||
}
|
||||
#else
|
||||
static inline void setup_zfcpdump(unsigned int console_devno) {}
|
||||
#endif /* CONFIG_ZFCPDUMP */
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
void (*_machine_restart)(char *command) = machine_restart_smp;
|
||||
void (*_machine_halt)(void) = machine_halt_smp;
|
||||
@@ -586,13 +606,20 @@ setup_resources(void)
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long real_memory_size;
|
||||
EXPORT_SYMBOL_GPL(real_memory_size);
|
||||
|
||||
static void __init setup_memory_end(void)
|
||||
{
|
||||
unsigned long real_size, memory_size;
|
||||
unsigned long memory_size;
|
||||
unsigned long max_mem, max_phys;
|
||||
int i;
|
||||
|
||||
memory_size = real_size = 0;
|
||||
#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE)
|
||||
if (ipl_info.type == IPL_TYPE_FCP_DUMP)
|
||||
memory_end = ZFCPDUMP_HSA_SIZE;
|
||||
#endif
|
||||
memory_size = 0;
|
||||
max_phys = VMALLOC_END_INIT - VMALLOC_MIN_SIZE;
|
||||
memory_end &= PAGE_MASK;
|
||||
|
||||
@@ -601,7 +628,8 @@ static void __init setup_memory_end(void)
|
||||
for (i = 0; i < MEMORY_CHUNKS; i++) {
|
||||
struct mem_chunk *chunk = &memory_chunk[i];
|
||||
|
||||
real_size = max(real_size, chunk->addr + chunk->size);
|
||||
real_memory_size = max(real_memory_size,
|
||||
chunk->addr + chunk->size);
|
||||
if (chunk->addr >= max_mem) {
|
||||
memset(chunk, 0, sizeof(*chunk));
|
||||
continue;
|
||||
@@ -765,6 +793,7 @@ setup_arch(char **cmdline_p)
|
||||
|
||||
parse_early_param();
|
||||
|
||||
setup_ipl_info();
|
||||
setup_memory_end();
|
||||
setup_addressing_mode();
|
||||
setup_memory();
|
||||
@@ -782,6 +811,9 @@ setup_arch(char **cmdline_p)
|
||||
|
||||
/* Setup default console */
|
||||
conmode_default();
|
||||
|
||||
/* Setup zfcpdump support */
|
||||
setup_zfcpdump(console_devno);
|
||||
}
|
||||
|
||||
void print_cpu_info(struct cpuinfo_S390 *cpuinfo)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user