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:
Linus Torvalds
2007-04-27 09:15:31 -07:00
80 changed files with 5362 additions and 2153 deletions
-83
View File
@@ -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.
+87
View File
@@ -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.
+13
View File
@@ -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"
+5
View File
@@ -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)
-38
View File
@@ -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);
+63 -62
View File
@@ -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 = {
+16 -22
View File
@@ -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);
+3
View File
@@ -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
+1 -1
View File
@@ -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)
+33 -27
View File
@@ -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]), &regs);
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, &regs, 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);
}
+8 -6
View File
@@ -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
+3 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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
+71 -1
View File
@@ -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
View File
@@ -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);
+3 -1
View File
@@ -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
View File
@@ -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], &regs, 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, &regs, 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], &regs, 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], &regs);
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.
*/
+35 -3
View File
@@ -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