Commit 70c452ad authored by Oleg Drokin's avatar Oleg Drokin

Merge angband.namesys.com:/home/green/bk/linux-2.5

into angband.namesys.com:/home/green/bk_work/reiser3-linux-2.5-test
parents eed2a026 3150c862
......@@ -41,9 +41,10 @@ ELSA Quickstep 3000 (same settings as QS1000)
ELSA Quickstep 3000PCI
ELSA PCMCIA
ITK ix1-micro Rev.2
Eicon.Diehl Diva 2.0 ISA and PCI (S0 and U interface, no PRO version)
Eicon.Diehl Diva 2.01 ISA and PCI
Eicon.Diehl Diva Piccola
Eicon Diva 2.0 ISA and PCI (S0 and U interface, no PRO version)
Eicon Diva 2.01 ISA and PCI
Eicon Diva 2.02 PCI
Eicon Diva Piccola
ASUSCOM NETWORK INC. ISDNLink 128K PC adapter (order code I-IN100-ST-D)
Dynalink IS64PH (OEM version of ASUSCOM NETWORK INC. ISDNLink 128K adapter)
PCBIT-DP (OEM version of ASUSCOM NETWORK INC. ISDNLink)
......@@ -52,6 +53,7 @@ Sedlbauer Speed Card (Speed Win, Teledat 100, PCI, Fax+)
Sedlbauer Speed Star/Speed Star2 (PCMCIA)
Sedlbauer ISDN-Controller PC/104
USR Sportster internal TA (compatible Stollmann tina-pp V3)
USR internal TA PCI
ith Kommunikationstechnik GmbH MIC 16 ISA card
Traverse Technologie NETjet PCI S0 card and NETspider U card
Ovislink ISDN sc100-p card (NETjet driver)
......@@ -66,13 +68,14 @@ Gazel ISDN cards
HFC-PCI based cards
Winbond W6692 based cards
HFC-S+, HFC-SP/PCMCIA cards
formula-n enternow
Gerdes Power ISDN
Note: PCF, PCF-Pro: up to now, only the ISDN part is supported
PCC-8: not tested yet
Eicon.Diehl Diva U interface not tested
If you know other passive cards with the Siemens chipset, please let me know.
To use the PNP cards you need the isapnptools.
You can combine any card, if there is no conflict between the resources
(io, mem, irq).
......@@ -88,8 +91,15 @@ There is also some config needed before you compile the kernel and/or
modules. It is included in the normal "make [menu]config" target at the
kernel. Don't forget it, especially to select the right D-channel protocol.
Please note: All PnP cards need to be configured with isapnp and will work
only with the HiSax driver used as a module.
Please note: In older versions of the HiSax driver, all PnP cards
needed to be configured with isapnp and worked only with the HiSax
driver used as a module.
In the current version, HiSax will automatically use the in-kernel
ISAPnP support, provided you selected it during kernel configuration
(CONFIG_ISAPNP), if you don't give the io=, irq= command line parameters.
The affected card types are: 4,7,12,14,19,27-30
a) when built as a module
-------------------------
......@@ -190,6 +200,8 @@ Card types:
37 HFC 2BDS0 S+, SP irq,io
38 NETspider U PCI card none
39 HFC 2BDS0 SP/PCMCIA irq,io (set with cardmgr)
40 hotplug interface
41 Formula-n enter:now PCI none
At the moment IRQ sharing is only possible with PCI cards. Please make sure
that your IRQ is free and enabled for ISA use.
......@@ -215,6 +227,13 @@ Examples for module loading
(IO 1 (BASE 0x0180))
modprobe hisax type=4 protocol=2 irq=10 io0=0x580 io1=0x180
In the current version of HiSax, you can instead simply use
modprobe hisax type=4 protocol=2
if you configured your kernel for ISAPnP. Don't run isapnp in
this case!
6. Teles 16.3, Euro ISDN, I/O base 280 hex, IRQ 12 and
Teles 16.0, 1TR6, IRQ 5, Memory d0000 hex
modprobe hisax type=3,1 protocol=2,1 io=0x280 mem=0,0xd0000
......@@ -295,7 +314,9 @@ type
36 W6692 based PCI cards none
37 HFC 2BDS0 S+,SP/PCMCIA ONLY WORKS AS A MODULE !
38 NETspider U PCI card none
39 HFC 2BDS0 SP/PCMCIA ONLY WORKS AS A MODULE !
40 hotplug interface ONLY WORKS AS A MODULE !
41 Formula-n enter:now PCI none
Running the driver
------------------
......
......@@ -21,7 +21,8 @@ Command line parameters
Default is on.
* cio_ignore = <range of device numbers>, <range of device numbers>, ...
* cio_ignore = <device number> | <range of device numbers>,
<device number> | <range of device numbers>, ...
The given device numbers will be ignored by the common I/O-layer; no detection
and device sensing will be done on any of those devices. The subchannel to
......@@ -41,45 +42,27 @@ Command line parameters
By default, no devices are ignored.
* cio_proc_devinfo = yes | no
Determines whether the entries under /proc/deviceinfo/ (see below) should be
created. Since there are problems with systems with many devices attached, I
made it configurable.
Until the problems are dealt with, default is off.
/proc entries
-------------
* /proc/subchannels
Shows for each subchannel
This entry shows information on a per-subchannel basis.
The data is ordered in the following way:
- device number
- device type/model and if applicable control unit type/model
- whether the device is in use
- path installed mask, path available mask, path operational mask and last
path used mask
- the channel path IDs (chpids)
* /proc/deviceinfo/
Shows in subdirectories for each device some characteristics:
- /proc/deviceinfo/<devno>/chpids:
the channel path IDs
- /proc/deviceinfo/<devno>/in_use:
whether the device is in use
- /proc/deviceinfo/<devno>/sensedata:
the device type/model and if applicable control unit type/model of the
device
NOTE: Since the number of inodes which can be dynamically allocated by procfs
is limited, device entries will only be created up to a magic number of
devices. The kernel will utter a warning that not all entries can be
created. In this case, you shouldn't use "cio_proc_devinfo=yes" (see
above).
- subchannel number
- device type/model (if applicable; if not, this is empty) and control unit
type/model
- whether the device is in use (i. e. a device driver has requested ownership
and registered an interrupt handler)
- path installed mask (PIM), as reflected by last store subchannel
- path available mask (PAM), as reflected by last store subchannel
- path operational mask (POM), as reflected by last store subchannel
- the channel path IDs (CHPIDs)
All fields are separated by spaces, the chpids are in blocks of four chpids.
* /proc/cio_ignore
......@@ -137,3 +120,26 @@ Command line parameters
This entry counts how many times s390_process_IRQ has been called for each
CPU. This info is in /proc/interrupts on other architectures.
* /proc/chpids
This entry will only show up if you specified CONFIG_CHSC=y during kernel
config.
This entry serves a dual purpose:
- show which chpids are currently known to Linux and their status (online,
logically offline),
- toggling known chpids logically online/offline.
To toggle a known chpid logically offline, do an
echo off <chpid> > /proc/chpids
<chpid> is interpreted as hex, even if you omit the '0x'.
The chpid will be treated by Linux as if it were not online, which can mean
some devices will become unavailable.
You can toggle a logically offline chpid online again by
echo on <chpid> > /proc/chpids
If devices became unavailable by toggling the chpid logically offline, they
will become available again after you toggle the chpid online again.
......@@ -237,9 +237,10 @@ they go to 64 Bit.
On 390 our limitations & strengths make us slightly different.
For backward compatibility we are only allowed use 31 bits (2GB)
of our 32 bit addresses,however, we use entirely separate address
spaces for the user & kernel.
For backward compatibility ( because of the psw address hi bit which
indicates whether we are in 31 or 24 bit mode ) we are only allowed
use 31 bits (2GB) of our 32 bit addresses. However,
we use entirely separate address spaces for the user & kernel.
This means we can support 2GB of non Extended RAM on s/390, & more
with the Extended memory managment swap device &
......@@ -1474,6 +1475,12 @@ Now display what gpr2 is pointing to
D 00014CB4.20
V00014CB4 2F646576 2F636F6E 736F6C65 00001BF5
V00014CC4 FC00014C B4001001 E0001000 B8070707
Alternatively you can do the more elegant
D 0.20;BASE2
BASE2 telling VM to use GPR2 as the base register.
Now copy the text till the first 00 hex ( which is the end of the string
to an xterm & do hex2ascii on it.
hex2ascii 2F646576 2F636F6E 736F6C65 00
......@@ -2124,6 +2131,12 @@ now do
p/x (*(**$sp+56))&0x7fffffff
& so on.
Another good trick to look at addresses on the stack if you've somehow lost
the backchain is.
x/500xa $sp
This displays anything the name of any known functions above the stack pointer
for 500 bytes.
Disassembling instructions without debug info
---------------------------------------------
gdb typically compains if there is a lack of debugging
......
This diff is collapsed.
VERSION = 2
PATCHLEVEL = 5
SUBLEVEL = 20
SUBLEVEL = 21
EXTRAVERSION =
# We are using a recursive build, so we need to do a little thinking
......@@ -106,21 +106,23 @@ DEPMOD = /sbin/depmod
PERL = perl
MODFLAGS = -DMODULE
CFLAGS_MODULE = $(MODFLAGS)
AFLAGS_MODULE =
AFLAGS_MODULE = $(MODFLAGS)
CFLAGS_KERNEL =
AFLAGS_KERNEL =
EXPORT_FLAGS =
NOSTDINC_FLAGS = -nostdinc -iwithprefix include
export VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION KERNELRELEASE ARCH \
CONFIG_SHELL TOPDIR HPATH HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC \
CPP AR NM STRIP OBJCOPY OBJDUMP MAKE MAKEFILES GENKSYMS PERL
export CPPFLAGS EXPORT_FLAGS
export CPPFLAGS EXPORT_FLAGS NOSTDINC_FLAGS
export CFLAGS CFLAGS_KERNEL CFLAGS_MODULE
export AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
noconfig_targets := oldconfig xconfig menuconfig config clean mrproper \
distclean
noconfig_targets := xconfig menuconfig config oldconfig randconfig \
defconfig allyesconfig allnoconfig allmodconfig \
clean mrproper distclean
ifeq ($(filter $(noconfig_targets),$(MAKECMDGOALS)),)
......@@ -175,18 +177,14 @@ ifdef CONFIG_MODULES
EXPORT_FLAGS := -DEXPORT_SYMTAB
endif
INIT =init/init.o
CORE_FILES =kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o
NETWORKS =net/network.o
LIBS =$(TOPDIR)/lib/lib.a
SUBDIRS =init kernel lib drivers mm fs net ipc sound
DRIVERS-y = drivers/built-in.o
DRIVERS-$(CONFIG_SOUND) += sound/sound.o
DRIVERS := $(DRIVERS-y)
# Link components for vmlinux
# ---------------------------------------------------------------------------
SUBDIRS := init kernel mm fs ipc lib drivers sound net
INIT := init/init.o
CORE_FILES := kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o
LIBS := lib/lib.a
DRIVERS := drivers/built-in.o sound/sound.o
NETWORKS := net/network.o
include arch/$(ARCH)/Makefile
......@@ -281,8 +279,9 @@ include/asm:
# Split autoconf.h into include/linux/config/*
include/config/MARKER: scripts/split-include include/linux/autoconf.h
scripts/split-include include/linux/autoconf.h include/config
@ touch include/config/MARKER
@echo 'Splitting include/linux/autoconf.h -> include/config'
@scripts/split-include include/linux/autoconf.h include/config
@touch $@
# if .config is newer than include/linux/autoconf.h, someone tinkered
# with it and forgot to run make oldconfig
......@@ -300,8 +299,19 @@ include/linux/autoconf.h: .config
# version.h changes when $(KERNELRELEASE) etc change, as defined in
# this Makefile
uts_len := 64
include/linux/version.h: Makefile
@scripts/mkversion_h $@ $(KERNELRELEASE) $(VERSION) $(PATCHLEVEL) $(SUBLEVEL)
@if expr length "$(KERNELRELEASE)" \> $(uts_len) >/dev/null ; then \
echo '"$(KERNELRELEASE)" exceeds $(uts_len) characters' >&2; \
exit 1; \
fi;
@echo -n 'Generating $@'
@(echo \#define UTS_RELEASE \"$(KERNELRELEASE)\"; \
echo \#define LINUX_VERSION_CODE `expr $(VERSION) \\* 65536 + $(PATCHLEVEL) \\* 256 + $(SUBLEVEL)`; \
echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))'; \
) > $@.tmp
@$(update-if-changed)
# Helpers built in scripts/
# ---------------------------------------------------------------------------
......@@ -339,6 +349,7 @@ ifdef CONFIG_MODVERSIONS
include/linux/modversions.h: scripts/fixdep prepare FORCE
@rm -rf .tmp_export-objs
@$(MAKE) $(patsubst %,_sfdep_%,$(SUBDIRS))
@echo -n 'Generating $@'
@( echo "#ifndef _LINUX_MODVERSIONS_H";\
echo "#define _LINUX_MODVERSIONS_H"; \
echo "#include <linux/modsetver.h>"; \
......@@ -346,15 +357,8 @@ include/linux/modversions.h: scripts/fixdep prepare FORCE
echo "#include <linux/$${f}>"; \
done; \
echo "#endif"; \
) > $@.tmp
@rm -rf .tmp_export-objs
@if [ -r $@ ] && cmp -s $@ $@.tmp; then \
echo $@ was not updated; \
rm -f $@.tmp; \
else \
echo $@ was updated; \
mv -f $@.tmp $@; \
fi
) > $@.tmp; \
$(update-if-changed)
$(patsubst %,_sfdep_%,$(SUBDIRS)): FORCE
@$(MAKE) -C $(patsubst _sfdep_%, %, $@) fastdep
......@@ -519,20 +523,35 @@ else # ifeq ($(filter $(noconfig_targets),$(MAKECMDGOALS)),)
.PHONY: oldconfig xconfig menuconfig config \
make_with_config
oldconfig:
$(CONFIG_SHELL) scripts/Configure -d arch/$(ARCH)/config.in
xconfig:
@$(MAKE) -C scripts kconfig.tk
wish -f scripts/kconfig.tk
menuconfig:
@$(MAKE) -C scripts/lxdialog all
@$(MAKE) -C scripts lxdialog
$(CONFIG_SHELL) scripts/Menuconfig arch/$(ARCH)/config.in
config:
$(CONFIG_SHELL) scripts/Configure arch/$(ARCH)/config.in
oldconfig:
$(CONFIG_SHELL) scripts/Configure -d arch/$(ARCH)/config.in
randconfig:
$(CONFIG_SHELL) scripts/Configure -r arch/$(ARCH)/config.in
allyesconfig:
$(CONFIG_SHELL) scripts/Configure -y arch/$(ARCH)/config.in
allnoconfig:
$(CONFIG_SHELL) scripts/Configure -n arch/$(ARCH)/config.in
allmodconfig:
$(CONFIG_SHELL) scripts/Configure -m arch/$(ARCH)/config.in
defconfig:
yes '' | $(CONFIG_SHELL) scripts/Configure -d arch/$(ARCH)/config.in
# How we generate .config depends on which *config the
# user chose when calling make
......@@ -576,10 +595,6 @@ CLEAN_FILES += \
net/khttpd/times.h \
submenu*
# directories removed with 'make clean'
CLEAN_DIRS += \
modules
# files removed with 'make mrproper'
MRPROPER_FILES += \
include/linux/autoconf.h include/linux/version.h \
......@@ -616,8 +631,7 @@ clean: archclean
@find . \( -name \*.[oas] -o -name core -o -name .\*.cmd -o \
-name .\*.tmp -o -name .\*.d \) -type f -print \
| grep -v lxdialog/ | xargs rm -f
@rm -f $(CLEAN_FILES)
@rm -rf $(CLEAN_DIRS)
@rm -rf $(CLEAN_FILES)
@$(MAKE) -C Documentation/DocBook clean
mrproper: clean archmrproper
......@@ -660,5 +674,15 @@ if_changed_rule = $(if $(strip $? \
cmd = @$(if $($(quiet)$(1)),echo ' $($(quiet)$(1))' &&) $($(1))
define update-if-changed
if [ -r $@ ] && cmp -s $@ $@.tmp; then \
echo ' (unchanged)'; \
rm -f $@.tmp; \
else \
echo ' (updated)'; \
mv -f $@.tmp $@; \
fi
endef
FORCE:
......@@ -121,7 +121,7 @@ $(export-objs:.o=.i) : export_flags := $(EXPORT_FLAGS)
$(export-objs:.o=.s) : export_flags := $(EXPORT_FLAGS)
$(export-objs:.o=.lst): export_flags := $(EXPORT_FLAGS)
c_flags = $(CFLAGS) $(modkern_cflags) $(EXTRA_CFLAGS) $(CFLAGS_$(*F).o) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(export_flags)
c_flags = $(CFLAGS) $(NOSTDINC_FLAGS) $(modkern_cflags) $(EXTRA_CFLAGS) $(CFLAGS_$(*F).o) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(export_flags)
quiet_cmd_cc_s_c = CC $(RELDIR)/$@
cmd_cc_s_c = $(CC) $(c_flags) -S -o $@ $<
......@@ -159,7 +159,7 @@ $(real-objs-y:.o=.s): modkern_aflags := $(AFLAGS_KERNEL)
$(real-objs-m) : modkern_aflags := $(AFLAGS_MODULE)
$(real-objs-m:.o=.s): modkern_aflags := $(AFLAGS_MODULE)
a_flags = $(AFLAGS) $(modkern_aflags) $(EXTRA_AFLAGS) $(AFLAGS_$(*F).o)
a_flags = $(AFLAGS) $(NOSTDINC_FLAGS) $(modkern_aflags) $(EXTRA_AFLAGS) $(AFLAGS_$(*F).o)
quiet_cmd_as_s_S = CPP $(RELDIR)/$@
cmd_as_s_S = $(CPP) $(a_flags) -o $@ $<
......@@ -224,6 +224,35 @@ $(multi-used-y) : %.o: $(multi-objs-y) FORCE
$(multi-used-m) : %.o: $(multi-objs-m) FORCE
$(call if_changed,cmd_link_multi)
# Compile programs on the host
# ===========================================================================
host-progs-single := $(foreach m,$(host-progs),$(if $($(m)-objs),,$(m)))
host-progs-multi := $(foreach m,$(host-progs),$(if $($(m)-objs),$(m)))
host-progs-multi-objs := $(foreach m,$(host-progs-multi),$($(m)-objs))
quiet_cmd_host_cc__c = HOSTCC $(RELDIR)/$@
cmd_host_cc__c = $(HOSTCC) -Wp,-MD,.$(subst /,_,$@).d \
$(HOSTCFLAGS) $(HOST_EXTRACFLAGS) -o $@ $<
$(host-progs-single): %: %.c FORCE
$(call if_changed_dep,host_cc__c)
quiet_cmd_host_cc_o_c = HOSTCC $(RELDIR)/$@
cmd_host_cc_o_c = $(HOSTCC) -Wp,-MD,.$(subst /,_,$@).d \
$(HOSTCFLAGS) $(HOST_EXTRACFLAGS) -c -o $@ $<
$(host-progs-multi-objs): %.o: %.c FORCE
$(call if_changed_dep,host_cc_o_c)
quiet_cmd_host_cc__o = HOSTLD $(RELDIR)/$@
cmd_host_cc__o = $(HOSTCC) $(HOSTLDFLAGS) -o $@ $($@-objs) \
$(HOST_LOADLIBES)
$(host-progs-multi): %: $(host-progs-multi-objs) FORCE
$(call if_changed,cmd_host_cc__o)
# Descending when making module versions
# ---------------------------------------------------------------------------
......
......@@ -7,6 +7,7 @@
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
#include <asm/hwrpb.h>
#include <asm/io.h>
......@@ -1103,66 +1104,7 @@ static int SMC37c669_xlate_drq(
unsigned int drq
);
#if 0
/*
** External Data Declarations
*/
extern struct LOCK spl_atomic;
/*
** External Function Prototype Declarations
*/
/* From kernel_alpha.mar */
extern spinlock(
struct LOCK *spl
);
extern spinunlock(
struct LOCK *spl
);
/* From filesys.c */
int allocinode(
char *name,
int can_create,
struct INODE **ipp
);
extern int null_procedure( void );
int smcc669_init( void );
int smcc669_open( struct FILE *fp, char *info, char *next, char *mode );
int smcc669_read( struct FILE *fp, int size, int number, unsigned char *buf );
int smcc669_write( struct FILE *fp, int size, int number, unsigned char *buf );
int smcc669_close( struct FILE *fp );
struct DDB smc_ddb = {
"smc", /* how this routine wants to be called */
smcc669_read, /* read routine */
smcc669_write, /* write routine */
smcc669_open, /* open routine */
smcc669_close, /* close routine */
null_procedure, /* name expansion routine */
null_procedure, /* delete routine */
null_procedure, /* create routine */
null_procedure, /* setmode */
null_procedure, /* validation routine */
0, /* class specific use */
1, /* allows information */
0, /* must be stacked */
0, /* is a flash update driver */
0, /* is a block device */
0, /* not seekable */
0, /* is an Ethernet device */
0, /* is a filesystem driver */
};
#endif
#define spinlock(x)
#define spinunlock(x)
static spinlock_t smc_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED;
/*
**++
......@@ -2042,10 +1984,10 @@ static void __init SMC37c669_config_mode(
** mode. Therefore, a spinlock is placed around the two writes to
** guarantee that they complete uninterrupted.
*/
spinlock( &spl_atomic );
spin_lock(&smc_lock);
wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY );
wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY );
spinunlock( &spl_atomic );
spin_unlock(&smc_lock);
}
else {
wb( &SMC37c669->index_port, SMC37c669_CONFIG_OFF_KEY );
......
......@@ -791,7 +791,7 @@ static int e100_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct
if(!atapi) {
/* set the irq handler which will finish the request when DMA is done */
ide_set_handler(drive, &etrax_dma_intr, WAIT_CMD, NULL);
ata_set_handler(drive, &etrax_dma_intr, WAIT_CMD, NULL);
/* issue cmd to drive */
OUT_BYTE(WIN_READDMA, IDE_COMMAND_REG);
......@@ -831,7 +831,7 @@ static int e100_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct
if(!atapi) {
/* set the irq handler which will finish the request when DMA is done */
ide_set_handler(drive, &etrax_dma_intr, WAIT_CMD, NULL);
ata_set_handler(drive, &etrax_dma_intr, WAIT_CMD, NULL);
/* issue cmd to drive */
OUT_BYTE(WIN_WRITEDMA, IDE_COMMAND_REG);
......
......@@ -27,7 +27,6 @@ obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o
obj-$(CONFIG_X86_LOCAL_APIC) += mpparse.o apic.o nmi.o
obj-$(CONFIG_X86_IO_APIC) += io_apic.o
obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o
obj-$(CONFIG_ACPI_SLEEP) += suspend.o
ifdef CONFIG_VISWS
obj-y += setup-visws.o
obj-$(CONFIG_X86_VISWS_APIC) += visws_apic.o
......
#include <linux/init.h>
#include <linux/bitops.h>
#include <linux/mm.h>
#include <asm/io.h>
#include <asm/processor.h>
......
......@@ -83,13 +83,9 @@ local_bh_count = 8
#define GET_CPU_IDX \
movl TI_CPU(%ebx), %eax; \
shll $irq_array_shift, %eax
#define GET_CURRENT_CPU_IDX \
GET_THREAD_INFO(%ebx); \
GET_CPU_IDX
#define CPU_IDX (,%eax)
#else
#define GET_CPU_IDX
#define GET_CURRENT_CPU_IDX GET_THREAD_INFO(%ebx)
#define CPU_IDX
#endif
......@@ -236,6 +232,7 @@ ENTRY(resume_kernel)
movl TI_FLAGS(%ebx), %ecx
testb $_TIF_NEED_RESCHED, %cl
jz restore_all
GET_CPU_IDX
movl irq_stat+local_bh_count CPU_IDX, %ecx
addl irq_stat+local_irq_count CPU_IDX, %ecx
jnz restore_all
......
......@@ -67,6 +67,7 @@
#include <linux/miscdevice.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/spinlock.h>
#include <linux/mm.h>
#include <asm/msr.h>
#include <asm/uaccess.h>
......
......@@ -217,7 +217,7 @@ EXPORT_SYMBOL(__global_cli);
EXPORT_SYMBOL(__global_sti);
EXPORT_SYMBOL(__global_save_flags);
EXPORT_SYMBOL(__global_restore_flags);
#ifdef SPINLOCK_DEBUG
#ifdef CONFIG_DEBUG_SPINLOCK
EXPORT_SYMBOL(_raw_spin_lock);
EXPORT_SYMBOL(_raw_spin_unlock);
EXPORT_SYMBOL(_raw_spin_trylock);
......
......@@ -16,7 +16,7 @@
#include <asm/system.h>
#include <asm/io.h>
#ifdef SPINLOCK_DEBUG
#ifdef CONFIG_DEBUG_SPINLOCK
#undef INIT_STUCK
#define INIT_STUCK 200000000 /*0xffffffff*/
......
......@@ -155,7 +155,10 @@ CONFIG_IPL
IPL device.
CONFIG_IPL_TAPE
Select this option if you want to IPL the image from a Tape.
Select "tape" if you want to IPL the image from a Tape.
Select "vm_reader" if you are running under VM/ESA and want
to IPL the image from the emulated card reader.
CONFIG_FAST_IRQ
Select this option in order to get the interrupts processed faster
......@@ -164,8 +167,57 @@ CONFIG_FAST_IRQ
interrupts which will also be processed before leaving the interrupt
context. This speeds up the I/O a lot. Say "Y".
CONFIG_MACHCHK_WARNING
Select this option if you want the machine check handler on IBM S/390 or
zSeries to process warning machine checks (e.g. on power failures).
If unsure, say "Y".
CONFIG_CHSC
Select this option if you want the s390 common I/O layer to use information
obtained by channel subsystem calls. This will enable Linux to process link
failures and resource accessibility events. Moreover, if you have procfs
enabled, you'll be able to toggle chpids logically offline and online. Even
if you don't understand what this means, you should say "Y".
CONFIG_PROCESS_DEBUG
Say Y to print all process fault locations to the console. This is
a debugging option; you probably do not want to set it unless you
are an S390 port maintainer.
CONFIG_PFAULT
Select this option, if you want to use PFAULT pseudo page fault
handling under VM. If running native or in LPAR, this option
has no effect. If your VM does not support PFAULT, PAGEEX
pseudo page fault handling will be used.
Note that VM 4.2 supports PFAULT but has a bug in its
implementation that causes some problems.
Everybody who wants to run Linux under VM != VM4.2 should select
this option.
CONFIG_SHARED_KERNEL
Select this option, if you want to share the text segment of the
Linux kernel between different VM guests. This reduces memory
usage with lots of guests but greatly increases kernel size.
You should only select this option if you know what you are
doing and want to exploit this feature.
CONFIG_QDIO
This driver provides the Queued Direct I/O base support for the
IBM S/390 (G5 and G6) and eServer zSeries (z800 and z900).
For details please refer to the documentation provided by IBM at
<http://www10.software.ibm.com/developerworks/opensource/linux390>
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called qdio.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
If unsure, say Y.
Performance statistics for QDIO base support
CONFIG_QDIO_PERF_STATS
Say Y here to get performance statistics in /proc/qdio_perf
If unsure, say N.
#
# s390/Makefile
#
# This file is included by the global makefile so that you can add your own
......@@ -14,14 +14,14 @@
#
LD=$(CROSS_COMPILE)ld -m elf_s390
CPP=$(CC) -E
OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S
LDFLAGS=-e start
ifeq ($(CONFIG_SHARED_KERNEL),y)
LINKFLAGS =-T $(TOPDIR)/arch/s390/vmlinux-shared.lds $(LDFLAGS)
LINKSCRIPT := arch/s390/vmlinux-shared.lds
else
LINKFLAGS =-T $(TOPDIR)/arch/s390/vmlinux.lds $(LDFLAGS)
LINKSCRIPT := arch/s390/vmlinux.lds
endif
LINKFLAGS =-T $(TOPDIR)/$(LINKSCRIPT) $(LDFLAGS)
CFLAGS_PIPE := -pipe
CFLAGS_NSR := -fno-strength-reduce
......@@ -29,14 +29,15 @@ CFLAGS := $(CFLAGS) $(CFLAGS_PIPE) $(CFLAGS_NSR)
HEAD := arch/s390/kernel/head.o arch/s390/kernel/init_task.o
SUBDIRS := $(SUBDIRS) arch/s390/mm arch/s390/kernel arch/s390/lib \
drivers/s390 arch/s390/math-emu
SUBDIRS += arch/s390/mm arch/s390/kernel arch/s390/lib drivers/s390
CORE_FILES := arch/s390/mm/mm.o arch/s390/kernel/kernel.o $(CORE_FILES)
DRIVERS := $(DRIVERS) drivers/s390/built-in.o
LIBS := $(TOPDIR)/arch/s390/lib/lib.a $(LIBS) $(TOPDIR)/arch/s390/lib/lib.a
DRIVERS += drivers/s390/built-in.o
ifeq ($(CONFIG_MATHEMU),y)
CORE_FILES := $(CORE_FILES) arch/s390/math-emu/math-emu.o
SUBDIRS += arch/s390/math-emu
DRIVERS += arch/s390/math-emu/math-emu.o
endif
all: image listing
......@@ -46,13 +47,19 @@ listing: vmlinux
MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
vmlinux: $(LINKSCRIPT)
image: vmlinux
@$(MAKEBOOT) image
archclean:
@$(MAKEBOOT) clean
$(MAKE) -C arch/$(ARCH)/kernel clean
archmrproper:
archdep:
@$(MAKEBOOT) dep
install: vmlinux
@$(MAKEBOOT) BOOTIMAGE=image install
......@@ -4,8 +4,6 @@
OBJCOPY = $(CROSS_COMPILE)objcopy
O_TARGET :=
EXTRA_AFLAGS := -traditional
include $(TOPDIR)/Rules.make
......@@ -29,3 +27,6 @@ dep:
clean:
rm -f image listing iplfba.boot ipleckd.boot ipldump.boot
install: $(CONFIGURE) $(BOOTIMAGE)
sh -x ./install.sh $(KERNELRELEASE) $(BOOTIMAGE) $(TOPDIR)/System.map $(TOPDIR)/Kerntypes "$(INSTALL_PATH)"
#!/bin/sh
#
# arch/s390x/boot/install.sh
#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
#
# Copyright (C) 1995 by Linus Torvalds
#
# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
#
# "make install" script for s390 architecture
#
# Arguments:
# $1 - kernel version
# $2 - kernel image file
# $3 - kernel map file
# $4 - default install path (blank if root directory)
#
# User may have a custom install script
if [ -x ~/bin/installkernel ]; then exec ~/bin/installkernel "$@"; fi
if [ -x /sbin/installkernel ]; then exec /sbin/installkernel "$@"; fi
# Default install - same as make zlilo
if [ -f $4/vmlinuz ]; then
mv $4/vmlinuz $4/vmlinuz.old
fi
if [ -f $4/System.map ]; then
mv $4/System.map $4/System.old
fi
cat $2 > $4/vmlinuz
cp $3 $4/System.map
......@@ -7,8 +7,8 @@ define_bool CONFIG_ISA n
define_bool CONFIG_EISA n
define_bool CONFIG_MCA n
define_bool CONFIG_UID16 y
define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n
define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y
define_bool CONFIG_GENERIC_BUST_SPINLOCK n
mainmenu_name "Linux Kernel Configuration"
......@@ -23,8 +23,16 @@ bool 'IEEE FPU emulation' CONFIG_MATHEMU
endmenu
mainmenu_option next_comment
comment 'General setup'
comment 'Base setup'
bool 'Fast IRQ handling' CONFIG_FAST_IRQ
bool 'Process warning machine checks' CONFIG_MACHCHK_WARNING
bool 'Use chscs for Common I/O' CONFIG_CHSC
tristate 'QDIO support' CONFIG_QDIO
if [ "$CONFIG_QDIO" != "n" ]; then
bool ' Performance statistics in /proc' CONFIG_QDIO_PERF_STATS
fi
bool 'Builtin IPL record support' CONFIG_IPL
if [ "$CONFIG_IPL" = "y" ]; then
choice 'IPL method generated into head.S' \
......@@ -39,6 +47,16 @@ bool 'Pseudo page fault support' CONFIG_PFAULT
bool 'VM shared kernel support' CONFIG_SHARED_KERNEL
endmenu
mainmenu_option next_comment
comment 'SCSI support'
tristate 'SCSI support' CONFIG_SCSI
if [ "$CONFIG_SCSI" != "n" ]; then
source drivers/scsi/Config.in
fi
endmenu
source drivers/s390/Config.in
if [ "$CONFIG_NET" = "y" ]; then
......@@ -51,9 +69,9 @@ mainmenu_option next_comment
comment 'Kernel hacking'
#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
if [ "$CONFIG_CTC" = "y" ]; then
bool 'Remote GDB kernel debugging' CONFIG_REMOTE_DEBUG
fi
#if [ "$CONFIG_CTC" = "y" ]; then
# bool 'Remote GDB kernel debugging' CONFIG_REMOTE_DEBUG
#fi
bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
endmenu
......
......@@ -5,9 +5,9 @@
# CONFIG_EISA is not set
# CONFIG_MCA is not set
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
CONFIG_GENERIC_BUST_SPINLOCK=n
# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
# CONFIG_GENERIC_BUST_SPINLOCK is not set
CONFIG_ARCH_S390=y
#
......@@ -15,6 +15,14 @@ CONFIG_ARCH_S390=y
#
CONFIG_EXPERIMENTAL=y
#
# General setup
#
CONFIG_NET=y
CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
#
# Loadable module support
#
......@@ -29,16 +37,16 @@ CONFIG_SMP=y
CONFIG_MATHEMU=y
#
# General setup
# Base setup
#
CONFIG_FAST_IRQ=y
CONFIG_MACHCHK_WARNING=y
CONFIG_CHSC=y
CONFIG_QDIO=m
# CONFIG_QDIO_PERF_STATS is not set
CONFIG_IPL=y
# CONFIG_IPL_TAPE is not set
CONFIG_IPL_VM=y
CONFIG_NET=y
CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
CONFIG_KCORE_ELF=y
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
......@@ -46,6 +54,77 @@ CONFIG_BINFMT_ELF=y
CONFIG_PFAULT=y
# CONFIG_SHARED_KERNEL is not set
#
# SCSI support
#
CONFIG_SCSI=m
#
# SCSI support type (disk, tape, CD-ROM)
#
CONFIG_BLK_DEV_SD=m
CONFIG_SD_EXTRA_DEVS=40
CONFIG_CHR_DEV_ST=m
# CONFIG_CHR_DEV_OSST is not set
CONFIG_BLK_DEV_SR=m
# CONFIG_BLK_DEV_SR_VENDOR is not set
CONFIG_SR_EXTRA_DEVS=10
CONFIG_CHR_DEV_SG=m
#
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
#
CONFIG_SCSI_MULTI_LUN=y
# CONFIG_SCSI_REPORT_LUNS is not set
CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_LOGGING=y
#
# SCSI low-level drivers
#
# CONFIG_SCSI_7000FASST is not set
# CONFIG_SCSI_ACARD is not set
# CONFIG_SCSI_AHA152X is not set
# CONFIG_SCSI_AHA1542 is not set
# CONFIG_SCSI_AHA1740 is not set
# CONFIG_SCSI_AIC7XXX is not set
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_DPT_I2O is not set
# CONFIG_SCSI_ADVANSYS is not set
# CONFIG_SCSI_IN2000 is not set
# CONFIG_SCSI_AM53C974 is not set
# CONFIG_SCSI_MEGARAID is not set
# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_DTC3280 is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_EATA_DMA is not set
# CONFIG_SCSI_EATA_PIO is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_GDTH is not set
# CONFIG_SCSI_GENERIC_NCR5380 is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_PPA is not set
# CONFIG_SCSI_IMM is not set
# CONFIG_SCSI_NCR53C406A is not set
# CONFIG_SCSI_NCR53C7xx is not set
# CONFIG_SCSI_PAS16 is not set
# CONFIG_SCSI_PCI2000 is not set
# CONFIG_SCSI_PCI2220I is not set
# CONFIG_SCSI_PSI240I is not set
# CONFIG_SCSI_QLOGIC_FAS is not set
# CONFIG_SCSI_SIM710 is not set
# CONFIG_SCSI_SYM53C416 is not set
# CONFIG_SCSI_T128 is not set
# CONFIG_SCSI_U14_34F is not set
# CONFIG_SCSI_DEBUG is not set
#
# PCMCIA SCSI adapter support
#
# CONFIG_SCSI_PCMCIA is not set
#
# Block device drivers
#
......@@ -103,8 +182,8 @@ CONFIG_S390_TAPE_BLOCK=y
#
# S/390 tape hardware support
#
CONFIG_S390_TAPE_3490=y
CONFIG_S390_TAPE_3480=y
CONFIG_S390_TAPE_3490=m
CONFIG_S390_TAPE_3480=m
#
# Network device drivers
......@@ -123,6 +202,7 @@ CONFIG_TR=y
#
CONFIG_CHANDEV=y
CONFIG_HOTPLUG=y
CONFIG_LCS=m
CONFIG_CTC=m
CONFIG_IUCV=m
......@@ -131,8 +211,6 @@ CONFIG_IUCV=m
#
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_NETLINK=y
# CONFIG_RTNETLINK is not set
# CONFIG_NETLINK_DEV is not set
# CONFIG_NETFILTER is not set
# CONFIG_FILTER is not set
......@@ -144,18 +222,24 @@ CONFIG_IP_MULTICAST=y
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_IP_MROUTE is not set
# CONFIG_ARPD is not set
# CONFIG_INET_ECN is not set
# CONFIG_SYN_COOKIES is not set
CONFIG_IPV6=m
# CONFIG_IPV6_NETLINK is not set
# CONFIG_KHTTPD is not set
# CONFIG_ATM is not set
# CONFIG_VLAN_8021Q is not set
#
#
#
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
#
# Appletalk devices
#
# CONFIG_DEV_APPLETALK is not set
# CONFIG_DECNET is not set
# CONFIG_BRIDGE is not set
# CONFIG_X25 is not set
......@@ -164,7 +248,7 @@ CONFIG_IPV6=m
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_FASTROUTE is not set
CONFIG_NET_FASTROUTE=y
# CONFIG_NET_HW_FLOWCONTROL is not set
#
......@@ -176,18 +260,20 @@ CONFIG_IPV6=m
# File systems
#
# CONFIG_QUOTA is not set
# CONFIG_QFMT_V1 is not set
# CONFIG_QFMT_V2 is not set
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_REISERFS_CHECK is not set
# CONFIG_REISERFS_PROC_INFO is not set
# CONFIG_ADFS_FS is not set
# CONFIG_ADFS_FS_RW is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_CMS_FS is not set
# CONFIG_EXT3_FS is not set
# CONFIG_JBD is not set
CONFIG_EXT3_FS=y
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
# CONFIG_FAT_FS is not set
# CONFIG_MSDOS_FS is not set
......@@ -198,12 +284,15 @@ CONFIG_IPV6=m
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_TMPFS is not set
# CONFIG_RAMFS is not set
CONFIG_RAMFS=y
# CONFIG_ISO9660_FS is not set
# CONFIG_JOLIET is not set
# CONFIG_ZISOFS is not set
# CONFIG_JFS_FS is not set
# CONFIG_JFS_DEBUG is not set
# CONFIG_JFS_STATISTICS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_FREEVXFS_FS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_HPFS_FS is not set
......@@ -232,8 +321,10 @@ CONFIG_NFS_FS=y
# CONFIG_ROOT_NFS is not set
CONFIG_NFSD=y
# CONFIG_NFSD_V3 is not set
# CONFIG_NFSD_TCP is not set
CONFIG_SUNRPC=y
CONFIG_LOCKD=y
CONFIG_EXPORTFS=y
# CONFIG_SMB_FS is not set
# CONFIG_NCP_FS is not set
# CONFIG_NCPFS_PACKET_SIGNING is not set
......@@ -245,7 +336,6 @@ CONFIG_LOCKD=y
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
# CONFIG_ZISOFS_FS is not set
# CONFIG_ZLIB_FS_INFLATE is not set
#
# Partition Types
......@@ -262,6 +352,7 @@ CONFIG_IBM_PARTITION=y
# CONFIG_SGI_PARTITION is not set
# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
# CONFIG_SMB_NLS is not set
# CONFIG_NLS is not set
......@@ -269,3 +360,10 @@ CONFIG_IBM_PARTITION=y
# Kernel hacking
#
CONFIG_MAGIC_SYSRQ=y
#
# Library routines
#
# CONFIG_CRC32 is not set
# CONFIG_ZLIB_INFLATE is not set
# CONFIG_ZLIB_DEFLATE is not set
......@@ -2,8 +2,10 @@
# Makefile for the linux kernel.
#
O_TARGET := kernel.o
EXTRA_TARGETS := head.o init_task.o
EXTRA_AFLAGS := -traditional
O_TARGET := kernel.o
export-objs := debug.o ebcdic.o irq.o s390_ext.o smp.o s390_ksyms.o
obj-y := entry.o bitmap.o traps.o time.o process.o irq.o \
......@@ -18,7 +20,27 @@ obj-$(CONFIG_SMP) += smp.o
#
obj-$(CONFIG_REMOTE_DEBUG) += gdb-stub.o #gdb-low.o
EXTRA_AFLAGS := -traditional
include $(TOPDIR)/Rules.make
.PHONY: asm-offsets.h
entry.S: asm-offsets.h
asm-offsets.h: asm-offsets.c
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -S $< -o - | grep -- "->" | \
(echo "#ifndef __ASM_OFFSETS_H__"; \
echo "#define __ASM_OFFSETS_H__"; \
echo "/*"; \
echo " * DO NOT MODIFY"; \
echo " *"; \
echo " * This file was generated by arch/s390/kernel/Makefile"; \
echo " */"; \
sed -e "s:^->\([^ ]*\) \([^ ]*\) \(.*\):#define \\1 \\2 /* \\3*/:" \
-e "s:->::"; \
echo "#endif" \
) > asm-offsets.h
clean:
rm -f asm-offsets.h
/*
* Generate definitions needed by assembly language modules.
* This code generates raw asm output which is post-processed to extract
* and format the required data.
*/
#include <linux/config.h>
#include <linux/sched.h>
/* Use marker if you need to separate the values later */
#define DEFINE(sym, val, marker) \
asm volatile("\n->" #sym " %0 " #val " " #marker : : "i" (val))
#define BLANK() asm volatile("\n->" : : )
int main(void)
{
DEFINE(__THREAD_info, offsetof(struct task_struct, thread_info),);
DEFINE(__THREAD_ar2, offsetof(struct task_struct, thread.ar2),);
DEFINE(__THREAD_ar4, offsetof(struct task_struct, thread.ar4),);
DEFINE(__THREAD_ksp, offsetof(struct task_struct, thread.ksp),);
DEFINE(__THREAD_per, offsetof(struct task_struct, thread.per_info),);
BLANK();
DEFINE(__TI_task, offsetof(struct thread_info, task),);
DEFINE(__TI_domain, offsetof(struct thread_info, exec_domain),);
DEFINE(__TI_flags, offsetof(struct thread_info, flags),);
DEFINE(__TI_cpu, offsetof(struct thread_info, cpu),);
DEFINE(__TI_precount, offsetof(struct thread_info, preempt_count),);
return 0;
}
......@@ -35,3 +35,22 @@ _zb_findmap:
.byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4
.byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,8
.globl _sb_findmap
_sb_findmap:
.byte 8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
.byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
.byte 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
.byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
.byte 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
.byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
.byte 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
.byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
.byte 7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
.byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
.byte 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
.byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
.byte 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
.byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
.byte 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
.byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
......@@ -68,12 +68,6 @@ static ssize_t debug_input(struct file *file, const char *user_buf,
size_t user_len, loff_t * offset);
static int debug_open(struct inode *inode, struct file *file);
static int debug_close(struct inode *inode, struct file *file);
static struct proc_dir_entry
*debug_create_proc_dir_entry(struct proc_dir_entry *root,
const char *name, mode_t mode,
struct file_operations *fops);
static void debug_delete_proc_dir_entry(struct proc_dir_entry *root,
struct proc_dir_entry *entry);
static debug_info_t* debug_info_create(char *name, int page_order, int nr_areas, int buf_size);
static void debug_info_get(debug_info_t *);
static void debug_info_put(debug_info_t *);
......@@ -155,7 +149,6 @@ DECLARE_MUTEX(debug_lock);
static int initialized = 0;
static struct file_operations debug_file_ops = {
owner: THIS_MODULE,
read: debug_output,
write: debug_input,
open: debug_open,
......@@ -217,8 +210,10 @@ static debug_info_t* debug_info_alloc(char *name, int page_order,
strncpy(rc->name, name, MIN(strlen(name), (DEBUG_MAX_PROCF_LEN - 1)));
rc->name[MIN(strlen(name), (DEBUG_MAX_PROCF_LEN - 1))] = 0;
memset(rc->views, 0, DEBUG_MAX_VIEWS * sizeof(struct debug_view *));
#ifdef CONFIG_PROC_FS
memset(rc->proc_entries, 0 ,DEBUG_MAX_VIEWS *
sizeof(struct proc_dir_entry*));
#endif /* CONFIG_PROC_FS */
atomic_set(&(rc->ref_count), 0);
return rc;
......@@ -265,11 +260,9 @@ static debug_info_t* debug_info_create(char *name, int page_order,
/* create proc rood directory */
rc->proc_root_entry = proc_mkdir(rc->name, debug_proc_root_entry);
/* append new element to linked list */
if (debug_area_first == NULL) {
/* first element in list */
debug_area_first = rc;
......@@ -331,16 +324,22 @@ static void debug_info_put(debug_info_t *db_info)
if (!db_info)
return;
if (atomic_dec_and_test(&db_info->ref_count)) {
#ifdef DEBUG
printk(KERN_INFO "debug: freeing debug area %p (%s)\n",
db_info, db_info->name);
#endif
for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
if (db_info->views[i] != NULL)
debug_delete_proc_dir_entry
(db_info->proc_root_entry,
db_info->proc_entries[i]);
}
debug_delete_proc_dir_entry(debug_proc_root_entry,
if (db_info->views[i] == NULL)
continue;
#ifdef CONFIG_PROC_FS
remove_proc_entry(db_info->proc_entries[i]->name,
db_info->proc_root_entry);
#endif
}
#ifdef CONFIG_PROC_FS
remove_proc_entry(db_info->proc_root_entry->name,
debug_proc_root_entry);
#endif
if(db_info == debug_area_first)
debug_area_first = db_info->next;
if(db_info == debug_area_last)
......@@ -497,6 +496,7 @@ static int debug_open(struct inode *inode, struct file *file)
#ifdef DEBUG
printk("debug_open\n");
#endif
MOD_INC_USE_COUNT;
down(&debug_lock);
/* find debug log and view */
......@@ -524,14 +524,18 @@ static int debug_open(struct inode *inode, struct file *file)
debug_info_snapshot = debug_info_copy(debug_info);
if(!debug_info_snapshot){
#ifdef DEBUG
printk(KERN_ERR "debug_open: debug_info_copy failed (out of mem)\n");
#endif
rc = -ENOMEM;
goto out;
}
if ((file->private_data =
kmalloc(sizeof(file_private_info_t), GFP_ATOMIC)) == 0) {
#ifdef DEBUG
printk(KERN_ERR "debug_open: kmalloc failed\n");
#endif
debug_info_free(debug_info_snapshot);
rc = -ENOMEM;
goto out;
......@@ -549,6 +553,8 @@ static int debug_open(struct inode *inode, struct file *file)
out:
up(&debug_lock);
if (rc != 0)
MOD_DEC_USE_COUNT;
return rc;
}
......@@ -568,35 +574,10 @@ static int debug_close(struct inode *inode, struct file *file)
debug_info_free(p_info->debug_info_snap);
debug_info_put(p_info->debug_info_org);
kfree(file->private_data);
MOD_DEC_USE_COUNT;
return 0; /* success */
}
/*
* debug_create_proc_dir_entry:
* - initializes proc-dir-entry and registers it
*/
static struct proc_dir_entry *debug_create_proc_dir_entry
(struct proc_dir_entry *root, const char *name, mode_t mode,
struct file_operations *fops)
{
struct proc_dir_entry *rc = create_proc_entry(name, mode, root);
if (rc && fops)
rc->proc_fops = fops;
return rc;
}
/*
* delete_proc_dir_entry:
*/
static void debug_delete_proc_dir_entry
(struct proc_dir_entry *root, struct proc_dir_entry *proc_entry)
{
remove_proc_entry(proc_entry->name, root);
}
/*
* debug_register:
* - creates and initializes debug area for the caller
......@@ -620,9 +601,11 @@ debug_info_t *debug_register
goto out;
debug_register_view(rc, &debug_level_view);
debug_register_view(rc, &debug_flush_view);
#ifdef DEBUG
printk(KERN_INFO
"debug: reserved %d areas of %d pages for debugging %s\n",
nr_areas, 1 << page_order, rc->name);
#endif
out:
if (rc == NULL){
printk(KERN_ERR "debug: debug_register failed for %s\n",name);
......@@ -642,7 +625,9 @@ void debug_unregister(debug_info_t * id)
if (!id)
goto out;
down(&debug_lock);
#ifdef DEBUG
printk(KERN_INFO "debug: unregistering %s\n", id->name);
#endif
debug_info_put(id);
up(&debug_lock);
......@@ -849,7 +834,9 @@ int debug_init(void)
down(&debug_lock);
if (!initialized) {
#ifdef CONFIG_PROC_FS
debug_proc_root_entry = proc_mkdir(DEBUG_DIR_ROOT, NULL);
#endif /* CONFIG_PROC_FS */
printk(KERN_INFO "debug: Initialization complete\n");
initialized = 1;
}
......@@ -889,10 +876,10 @@ int debug_register_view(debug_info_t * id, struct debug_view *view)
mode |= S_IRUSR;
if (view->input_proc)
mode |= S_IWUSR;
id->proc_entries[i] =
debug_create_proc_dir_entry(id->proc_root_entry,
view->name, mode,
&debug_file_ops);
id->proc_entries[i] = create_proc_entry(view->name, mode,
id->proc_root_entry);
if (id->proc_entries[i] != NULL)
id->proc_entries[i]->proc_fops = &debug_file_ops;
rc = 0;
}
spin_unlock_irqrestore(&id->lock, flags);
......@@ -920,8 +907,10 @@ int debug_unregister_view(debug_info_t * id, struct debug_view *view)
if (i == DEBUG_MAX_VIEWS)
rc = -1;
else {
debug_delete_proc_dir_entry(id->proc_root_entry,
id->proc_entries[i]);
#ifdef CONFIG_PROC_FS
remove_proc_entry(id->proc_entries[i]->name,
id->proc_root_entry);
#endif
id->views[i] = NULL;
rc = 0;
}
......@@ -1209,7 +1198,9 @@ void cleanup_module(void)
#ifdef DEBUG
printk("debug_cleanup_module: \n");
#endif
debug_delete_proc_dir_entry(NULL, debug_proc_root_entry);
#ifdef CONFIG_PROC_FS
remove_proc_entry(debug_proc_root_entry->name, NULL);
#endif /* CONFIG_PROC_FS */
return;
}
......
This diff is collapsed.
......@@ -649,7 +649,7 @@ _stext: basr %r13,0 # get base
#
.align 8
.Ldw: .long 0x000a0000,0x00000000
.Linittu: .long init_task_union
.Linittu: .long init_thread_union
.Lstart: .long start_kernel
.Lbss_bgn: .long __bss_start
.Lbss_end: .long _end
......
/*
* arch/s390/kernel/ieee.h
*
* S390 version
* Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
*/
#include <linux/sched.h>
static inline void _adddf(int R1,int R2)
{
current->tss.fprs[R1].fd = current->tss.fprs[R1].fd +
current->tss.fprs[R2].fd;
}
static inline void _subdf(int R1,int R2)
{
current->tss.fprs[R1].fd = current->tss.fprs[R1].fd -
current->tss.fprs[R2].fd;
}
static inline void _muldf(int R1,int R2)
{
current->tss.fprs[R1].fd = current->tss.fprs[R1].fd *
current->tss.fprs[R2].fd;
}
static inline void _divdf(int R1,int R2)
{
current->tss.fprs[R1].fd = current->tss.fprs[R1].fd /
current->tss.fprs[R2].fd;
}
static inline void _negdf(int R1,int R2)
{
current->tss.fprs[R1].fd = -current->tss.fprs[R1].fd;
}
static inline void _fixdfsi(int R1,int R2)
{
current->tss.regs->gprs[R1] = (__u32) current->tss.fprs[R2].fd;
}
static inline void _extendsidf(int R1,int R2)
{
current->tss.fprs[R1].fd = (double) current->tss.regs->gprs[R2];
}
static inline void _addsf(int R1,int R2)
{
current->tss.fprs[R1].ff = current->tss.fprs[R1].ff +
current->tss.fprs[R2].ff;
}
static inline void _subsf(int R1,int R2)
{
current->tss.fprs[R1].ff = current->tss.fprs[R1].ff -
current->tss.fprs[R2].ff;
}
static inline void _mulsf(int R1,int R2)
{
current->tss.fprs[R1].ff = current->tss.fprs[R1].ff *
current->tss.fprs[R2].ff;
}
static inline void _divsf(int R1,int R2)
{
current->tss.fprs[R1].ff = current->tss.fprs[R1].ff /
current->tss.fprs[R2].ff;
}
static inline void _negsf(int R1,int R2)
{
current->tss.fprs[R1].ff = -current->tss.fprs[R1].ff;
}
static inline void _fixsfsi(int R1,int R2)
{
current->tss.regs->gprs[R1] = (__u32) current->tss.fprs[R2].ff;
}
static inline void _extendsisf(int R1,int R2)
{
current->tss.fprs[R1].ff = (double) current->tss.regs->gprs[R2];
}
......@@ -13,21 +13,26 @@
#include <asm/uaccess.h>
#include <asm/pgtable.h>
static struct vm_area_struct init_mmap = INIT_MMAP;
static struct fs_struct init_fs = INIT_FS;
static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS;
struct mm_struct init_mm = INIT_MM(init_mm);
/*
* Initial task structure.
* Initial thread structure.
*
* We need to make sure that this is 8192-byte aligned due to the
* way process stacks are handled. This is done by making sure
* the linker maps this in the .text segment right after head.S,
* and making head.S ensure the proper alignment.
* way process stacks are handled. This is done by having a special
* "init_task" linker map entry..
*/
union thread_union init_thread_union
__attribute__((__section__(".data.init_task"))) =
{ INIT_THREAD_INFO(init_task) };
/*
* Initial task structure.
*
* The things we do for performance..
* All other task structs will be allocated on slabs in fork.c
*/
union task_union init_task_union __attribute__((aligned(8192))) =
{ INIT_TASK(init_task_union.task) };
struct task_struct init_task = INIT_TASK(init_task);
......@@ -63,7 +63,6 @@ BUILD_SMP_INTERRUPT(spurious_interrupt)
int show_interrupts(struct seq_file *p, void *v)
{
int i, j;
struct irqaction * action;
seq_puts(p, " ");
......@@ -76,36 +75,13 @@ int show_interrupts(struct seq_file *p, void *v)
if (ioinfo[i] == INVALID_STORAGE_AREA)
continue;
action = ioinfo[i]->irq_desc.action;
if (!action)
continue;
seq_printf(p, "%3d: ",i);
#ifndef CONFIG_SMP
seq_printf(p, "%10u ", kstat_irqs(i));
#else
for (j=0; j<smp_num_cpus; j++)
seq_printf( p, "%10u ",
kstat.irqs[cpu_logical_map(j)][i]);
#endif
seq_printf(p, " %14s", ioinfo[i]->irq_desc.handler->typename);
seq_printf(p, " %s", action->name);
for (action=action->next; action; action = action->next)
{
seq_printf(p, ", %s", action->name);
} /* endfor */
seq_printf(p, " %s", ioinfo[i]->irq_desc.name);
seq_putc(p, '\n');
} /* endfor */
seq_printf(p, "NMI: %10u\n", nmi_counter);
#ifdef CONFIG_SMP
seq_printf(p, "IPI: %10u\n", atomic_read(&ipi_count));
#endif
return 0;
}
......@@ -132,10 +108,10 @@ atomic_t global_bh_count;
*/
#define check_smp_invalidate(cpu)
extern void show_stack(unsigned long* esp);
static void show(char * str)
{
int i;
unsigned long *stack;
int cpu = smp_processor_id();
printk("\n%s, CPU %d:\n", str, cpu);
......@@ -143,13 +119,7 @@ static void show(char * str)
atomic_read(&global_irq_count),local_irq_count(smp_processor_id()));
printk("bh: %d [%d]\n",
atomic_read(&global_bh_count),local_bh_count(smp_processor_id()));
stack = (unsigned long *) &str;
for (i = 40; i ; i--) {
unsigned long x = *++stack;
if (x > (unsigned long) &init_task_union && x < (unsigned long) &vsprintf) {
printk("<[%08lx]> ", x);
}
}
show_stack(NULL);
}
#define MAXCOUNT 100000000
......
......@@ -47,199 +47,79 @@
asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
/*
* The idle loop on a S390...
* Return saved PC of a blocked thread. used in kernel/sched.
* resume in entry.S does not create a new stack frame, it
* just stores the registers %r6-%r15 to the frame given by
* schedule. We want to return the address of the caller of
* schedule, so we have to walk the backchain one time to
* find the frame schedule() store its return address.
*/
static psw_t wait_psw;
int cpu_idle(void *unused)
unsigned long thread_saved_pc(struct task_struct *tsk)
{
/* endless idle loop with no priority at all */
init_idle();
current->nice = 20;
wait_psw.mask = _WAIT_PSW_MASK;
wait_psw.addr = (unsigned long) &&idle_wakeup | 0x80000000L;
while(1) {
if (need_resched()) {
schedule();
check_pgt_cache();
continue;
}
unsigned long bc;
/* load wait psw */
asm volatile (
"lpsw %0"
: : "m" (wait_psw) );
idle_wakeup:
}
bc = *((unsigned long *) tsk->thread.ksp);
return *((unsigned long *) (bc+56));
}
/*
As all the register will only be made displayable to the root
user ( via printk ) or checking if the uid of the user is 0 from
the /proc filesystem please god this will be secure enough DJB.
The lines are given one at a time so as not to chew stack space in
printk on a crash & also for the proc filesystem when you get
0 returned you know you've got all the lines
* The idle loop on a S390...
*/
static int sprintf_regs(int line, char *buff, struct task_struct *task, struct pt_regs *regs)
void default_idle(void)
{
int linelen=0;
int regno,chaincnt;
u32 backchain,prev_backchain,endchain;
u32 ksp = 0;
char *mode = "???";
psw_t wait_psw;
unsigned long reg;
enum
{
sp_linefeed,
sp_psw,
sp_ksp,
sp_gprs,
sp_gprs1,
sp_gprs2,
sp_gprs3,
sp_gprs4,
sp_acrs,
sp_acrs1,
sp_acrs2,
sp_acrs3,
sp_acrs4,
sp_kern_backchain,
sp_kern_backchain1
};
if (task)
ksp = task->thread.ksp;
if (regs && !(regs->psw.mask & PSW_PROBLEM_STATE))
ksp = regs->gprs[15];
if (regs)
mode = (regs->psw.mask & PSW_PROBLEM_STATE)?
"User" : "Kernel";
switch(line)
{
case sp_linefeed:
linelen=sprintf(buff,"\n");
break;
case sp_psw:
if(regs)
linelen=sprintf(buff, "%s PSW: %08lx %08lx %s\n", mode,
(unsigned long) regs->psw.mask,
(unsigned long) regs->psw.addr,
print_tainted());
else
linelen=sprintf(buff,"pt_regs=NULL some info unavailable\n");
break;
case sp_ksp:
linelen=sprintf(&buff[linelen],
"task: %08x ksp: %08x pt_regs: %08x\n",
(addr_t)task, (addr_t)ksp, (addr_t)regs);
break;
case sp_gprs:
if(regs)
linelen=sprintf(buff, "%s GPRS:\n", mode);
break;
case sp_gprs1 ... sp_gprs4:
if(regs)
{
regno=(line-sp_gprs1)*4;
linelen=sprintf(buff,"%08x %08x %08x %08x\n",
regs->gprs[regno],
regs->gprs[regno+1],
regs->gprs[regno+2],
regs->gprs[regno+3]);
}
break;
case sp_acrs:
if(regs)
linelen=sprintf(buff, "%s ACRS:\n", mode);
break;
case sp_acrs1 ... sp_acrs4:
if(regs)
{
regno=(line-sp_acrs1)*4;
linelen=sprintf(buff,"%08x %08x %08x %08x\n",
regs->acrs[regno],
regs->acrs[regno+1],
regs->acrs[regno+2],
regs->acrs[regno+3]);
if (need_resched()) {
schedule();
return;
}
break;
case sp_kern_backchain:
if (regs && (regs->psw.mask & PSW_PROBLEM_STATE))
break;
if (ksp)
linelen=sprintf(buff, "Kernel BackChain CallChain\n");
break;
default:
if (ksp)
{
backchain=ksp&PSW_ADDR_MASK;
endchain=((backchain&(-8192))+8192);
prev_backchain=backchain-1;
line-=sp_kern_backchain1;
for(chaincnt=0;;chaincnt++)
{
if((backchain==0)||(backchain>=endchain)
||(chaincnt>=8)||(prev_backchain>=backchain))
break;
if(chaincnt==line)
{
linelen+=sprintf(&buff[linelen]," %08x [<%08lx>]\n",
backchain,
*(u32 *)(backchain+56)&PSW_ADDR_MASK);
break;
}
prev_backchain=backchain;
backchain=(*((u32 *)backchain))&PSW_ADDR_MASK;
}
}
}
return(linelen);
/*
* Wait for external, I/O or machine check interrupt and
* switch of machine check bit after the wait has ended.
*/
wait_psw.mask = _WAIT_PSW_MASK;
asm volatile (
" basr %0,0\n"
"0: la %0,1f-0b(%0)\n"
" st %0,4(%1)\n"
" oi 4(%1),0x80\n"
" lpsw 0(%1)\n"
"1: la %0,2f-1b(%0)\n"
" st %0,4(%1)\n"
" oi 4(%1),0x80\n"
" ni 1(%1),0xf9\n"
" lpsw 0(%1)\n"
"2:"
: "=&a" (reg) : "a" (&wait_psw) : "memory", "cc" );
}
void show_regs(struct pt_regs *regs)
int cpu_idle(void)
{
char buff[80];
int i, line;
printk("CPU: %d\n",smp_processor_id());
printk("Process %s (pid: %d, stackpage=%08X)\n",
current->comm, current->pid, 4096+(addr_t)current);
for (line = 0; sprintf_regs(line, buff, current, regs); line++)
printk(buff);
if (regs->psw.mask & PSW_PROBLEM_STATE)
{
printk("User Code:\n");
memset(buff, 0, 20);
copy_from_user(buff,
(char *) (regs->psw.addr & PSW_ADDR_MASK), 20);
for (i = 0; i < 20; i++)
printk("%02x ", buff[i]);
printk("\n");
}
for (;;)
default_idle();
return 0;
}
char *task_show_regs(struct task_struct *task, char *buffer)
extern void show_registers(struct pt_regs *regs);
extern void show_trace(unsigned long *sp);
void show_regs(struct pt_regs *regs)
{
int line, len;
struct task_struct *tsk = current;
for (line = 0; ; line++)
{
len = sprintf_regs(line, buffer, task, task->thread.regs);
if (!len) break;
buffer += len;
}
return buffer;
}
printk("CPU: %d %s\n", tsk->thread_info->cpu, print_tainted());
printk("Process %s (pid: %d, task: %08lx, ksp: %08x)\n",
current->comm, current->pid, (unsigned long) tsk,
tsk->thread.ksp);
show_registers(regs);
/* Show stack backtrace if pt_regs is from kernel mode */
if (!(regs->psw.mask & PSW_PROBLEM_STATE))
show_trace((unsigned long *) regs->gprs[15]);
}
int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
{
......@@ -279,7 +159,7 @@ void flush_thread(void)
{
current->used_math = 0;
current->flags &= ~PF_USEDFPU;
clear_tsk_thread_flag(current, TIF_USEDFPU);
}
void release_thread(struct task_struct *dead_task)
......@@ -300,16 +180,11 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp,
unsigned long gprs[10]; /* gprs 6 -15 */
unsigned long fprs[4]; /* fpr 4 and 6 */
unsigned long empty[4];
#if CONFIG_REMOTE_DEBUG
struct gdb_pt_regs childregs;
#else
struct pt_regs childregs;
#endif
} *frame;
frame = (struct stack_frame *) (2*PAGE_SIZE + (unsigned long) p) -1;
frame = (struct stack_frame *) (((unsigned long) frame)&-8L);
p->thread.regs = (struct pt_regs *)&frame->childregs;
frame = ((struct stack_frame *)
(THREAD_SIZE + (unsigned long) p->thread_info)) - 1;
p->thread.ksp = (unsigned long) frame;
memcpy(&frame->childregs,regs,sizeof(struct pt_regs));
frame->childregs.gprs[15] = new_stackp;
......@@ -317,14 +192,14 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp,
/* new return point is ret_from_sys_call */
frame->gprs[8] = ((unsigned long) &ret_from_fork) | 0x80000000;
/* start disabled because of schedule_tick and rq->lock being held */
frame->childregs.psw.mask &= ~0x03000000;
/* fake return stack for resume(), don't go back to schedule */
frame->gprs[9] = (unsigned long) frame;
frame->childregs.old_ilc = -1; /* We are not single stepping an svc */
/* save fprs, if used in last task */
save_fp_regs(&p->thread.fp_regs);
p->thread.user_seg = __pa((unsigned long) p->mm->pgd) | _SEGMENT_TABLE;
p->thread.fs = USER_DS;
/* Don't copy debug registers */
memset(&p->thread.per_info,0,sizeof(p->thread.per_info));
return 0;
......
......@@ -41,7 +41,7 @@
void FixPerRegisters(struct task_struct *task)
{
struct pt_regs *regs = task->thread.regs;
struct pt_regs *regs = __KSTK_PTREGS(task);
per_struct *per_info=
(per_struct *)&task->thread.per_info;
......@@ -155,7 +155,7 @@ int copy_user(struct task_struct *task,saddr_t useraddr,addr_t copyaddr,int len,
mask=0xffffffff;
if(useraddr<PT_FPC)
{
realuseraddr=(addr_t)&(((u8 *)task->thread.regs)[useraddr]);
realuseraddr=((addr_t) __KSTK_PTREGS(task)) + useraddr;
if(useraddr<PT_PSWMASK)
{
copymax=PT_PSWMASK;
......@@ -217,7 +217,6 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
{
struct task_struct *child;
int ret = -EPERM;
unsigned long flags;
unsigned long tmp;
int copied;
ptrace_area parea;
......@@ -236,16 +235,18 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
ret = -ESRCH;
read_lock(&tasklist_lock);
child = find_task_by_pid(pid);
if (child)
get_task_struct(child);
read_unlock(&tasklist_lock);
if (!child)
goto out;
ret = -EPERM;
if (pid == 1) /* you may not mess with init */
goto out;
goto out_tsk;
if (request == PTRACE_ATTACH)
{
ret = ptrace_attach(child);
goto out;
goto out_tsk;
}
ret = -ESRCH;
// printk("child=%lX child->flags=%lX",child,child->flags);
......@@ -254,14 +255,14 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
if(child!=current)
{
if (!(child->ptrace & PT_PTRACED))
goto out;
goto out_tsk;
if (child->state != TASK_STOPPED)
{
if (request != PTRACE_KILL)
goto out;
goto out_tsk;
}
if (child->p_pptr != current)
goto out;
if (child->parent != current)
goto out_tsk;
}
switch (request)
{
......@@ -271,9 +272,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
copied = access_process_vm(child,ADDR_BITS_REMOVE(addr), &tmp, sizeof(tmp), 0);
ret = -EIO;
if (copied != sizeof(tmp))
goto out;
break;
ret = put_user(tmp,(unsigned long *) data);
goto out;
break;
/* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR:
......@@ -285,9 +286,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
case PTRACE_POKEDATA:
ret = 0;
if (access_process_vm(child,ADDR_BITS_REMOVE(addr), &data, sizeof(data), 1) == sizeof(data))
goto out;
break;
ret = -EIO;
goto out;
break;
case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
......@@ -300,9 +300,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
if ((unsigned long) data >= _NSIG)
break;
if (request == PTRACE_SYSCALL)
child->ptrace |= PT_TRACESYS;
set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
else
child->ptrace &= ~PT_TRACESYS;
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
child->exit_code = data;
/* make sure the single step bit is not set. */
clear_single_step(child);
......@@ -329,7 +329,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
ret = -EIO;
if ((unsigned long) data >= _NSIG)
break;
child->ptrace &= ~PT_TRACESYS;
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
child->exit_code = data;
set_single_step(child);
/* give it a chance to run. */
......@@ -346,10 +346,20 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
ret=copy_user(child,parea.kernel_addr,parea.process_addr,
parea.len,1,(request==PTRACE_POKEUSR_AREA));
break;
case PTRACE_SETOPTIONS: {
if (data & PTRACE_O_TRACESYSGOOD)
child->ptrace |= PT_TRACESYSGOOD;
else
child->ptrace &= ~PT_TRACESYSGOOD;
ret = 0;
break;
}
default:
ret = -EIO;
break;
}
out_tsk:
put_task_struct(child);
out:
unlock_kernel();
return ret;
......@@ -357,12 +367,13 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
asmlinkage void syscall_trace(void)
{
lock_kernel();
if ((current->ptrace & (PT_PTRACED|PT_TRACESYS))
!= (PT_PTRACED|PT_TRACESYS))
goto out;
current->exit_code = SIGTRAP;
set_current_state(TASK_STOPPED);
if (!test_thread_flag(TIF_SYSCALL_TRACE))
return;
if (!(current->ptrace & PT_PTRACED))
return;
current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
? 0x80 : 0);
current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD);
schedule();
/*
......@@ -374,6 +385,4 @@ asmlinkage void syscall_trace(void)
send_sig(current->exit_code, current, 1);
current->exit_code = 0;
}
out:
unlock_kernel();
}
......@@ -21,8 +21,10 @@ do_reipl: basr %r13,0
oi .Lschib+5-.Lpg0(%r13),0x84
.Lecs: xi .Lschib+27-.Lpg0(%r13),0x01
msch .Lschib-.Lpg0(%r13)
ssch .Liplorb-.Lpg0(%r13)
lhi %r0,5
.Lssch: ssch .Liplorb-.Lpg0(%r13)
jz .L001
brct %r0,.Lssch
bas %r14,.Ldisab-.Lpg0(%r13)
.L001: mvc __LC_IO_NEW_PSW(8),.Lionew-.Lpg0(%r13)
.Ltpi: lpsw .Lwaitpsw-.Lpg0(%r13)
......
......@@ -10,6 +10,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <asm/lowcore.h>
#include <asm/s390_ext.h>
......@@ -21,34 +22,31 @@
* iucv and 0x2603 pfault) this is always the first element.
*/
ext_int_info_t *ext_int_hash[256] = { 0, };
ext_int_info_t ext_int_info_timer;
ext_int_info_t ext_int_info_hwc;
ext_int_info_t ext_int_pfault;
int register_external_interrupt(__u16 code, ext_int_handler_t handler) {
ext_int_info_t *p;
int index;
index = code & 0xff;
p = ext_int_hash[index];
while (p != NULL) {
if (p->code == code)
return -EBUSY;
p = p->next;
}
if (code == 0x1004) /* time_init is done before kmalloc works :-/ */
p = &ext_int_info_timer;
else if (code == 0x2401) /* hwc_init is done too early too */
p = &ext_int_info_hwc;
else if (code == 0x2603) /* pfault_init is done too early too */
p = &ext_int_pfault;
else
p = (ext_int_info_t *)
kmalloc(sizeof(ext_int_info_t), GFP_ATOMIC);
p = (ext_int_info_t *) kmalloc(sizeof(ext_int_info_t), GFP_ATOMIC);
if (p == NULL)
return -ENOMEM;
p->code = code;
p->handler = handler;
index = code & 0xff;
p->next = ext_int_hash[index];
ext_int_hash[index] = p;
return 0;
}
int register_early_external_interrupt(__u16 code, ext_int_handler_t handler,
ext_int_info_t *p) {
int index;
if (p == NULL)
return -EINVAL;
p->code = code;
p->handler = handler;
index = code & 0xff;
p->next = ext_int_hash[index];
ext_int_hash[index] = p;
return 0;
......@@ -73,11 +71,33 @@ int unregister_external_interrupt(__u16 code, ext_int_handler_t handler) {
q->next = p->next;
else
ext_int_hash[index] = p->next;
if (code != 0x1004 && code != 0x2401 && code != 0x2603)
kfree(p);
return 0;
}
int unregister_early_external_interrupt(__u16 code, ext_int_handler_t handler,
ext_int_info_t *p) {
ext_int_info_t *q;
int index;
if (p == NULL || p->code != code || p->handler != handler)
return -EINVAL;
index = code & 0xff;
q = ext_int_hash[index];
if (p != q) {
while (q != NULL) {
if (q->next == p)
break;
q = q->next;
}
if (q == NULL)
return -ENOENT;
q->next = p->next;
} else
ext_int_hash[index] = p->next;
return 0;
}
EXPORT_SYMBOL(register_external_interrupt);
EXPORT_SYMBOL(unregister_external_interrupt);
......@@ -5,9 +5,11 @@
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/smp.h>
#include <asm/checksum.h>
#include <asm/delay.h>
#include <asm/setup.h>
#include <asm/softirq.h>
#if CONFIG_IP_MULTICAST
#include <net/arp.h>
#endif
......@@ -18,8 +20,9 @@
EXPORT_SYMBOL_NOVERS(_oi_bitmap);
EXPORT_SYMBOL_NOVERS(_ni_bitmap);
EXPORT_SYMBOL_NOVERS(_zb_findmap);
EXPORT_SYMBOL_NOVERS(__copy_from_user_fixup);
EXPORT_SYMBOL_NOVERS(__copy_to_user_fixup);
EXPORT_SYMBOL_NOVERS(__copy_from_user_asm);
EXPORT_SYMBOL_NOVERS(__copy_to_user_asm);
EXPORT_SYMBOL_NOVERS(__clear_user_asm);
/*
* semaphore ops
......@@ -27,7 +30,6 @@ EXPORT_SYMBOL_NOVERS(__copy_to_user_fixup);
EXPORT_SYMBOL(__up);
EXPORT_SYMBOL(__down);
EXPORT_SYMBOL(__down_interruptible);
EXPORT_SYMBOL(__down_trylock);
/*
* string functions
......@@ -35,6 +37,7 @@ EXPORT_SYMBOL(__down_trylock);
EXPORT_SYMBOL_NOVERS(memcmp);
EXPORT_SYMBOL_NOVERS(memset);
EXPORT_SYMBOL_NOVERS(memmove);
EXPORT_SYMBOL_NOVERS(memscan);
EXPORT_SYMBOL_NOVERS(strlen);
EXPORT_SYMBOL_NOVERS(strchr);
EXPORT_SYMBOL_NOVERS(strcmp);
......@@ -44,7 +47,6 @@ EXPORT_SYMBOL_NOVERS(strncpy);
EXPORT_SYMBOL_NOVERS(strnlen);
EXPORT_SYMBOL_NOVERS(strrchr);
EXPORT_SYMBOL_NOVERS(strstr);
EXPORT_SYMBOL_NOVERS(strsep);
EXPORT_SYMBOL_NOVERS(strpbrk);
/*
......@@ -57,5 +59,3 @@ EXPORT_SYMBOL(csum_fold);
EXPORT_SYMBOL(console_mode);
EXPORT_SYMBOL(console_device);
EXPORT_SYMBOL_NOVERS(do_call_softirq);
/*
* linux/arch/S390/kernel/semaphore.c
* linux/arch/s390/kernel/semaphore.c
*
* S390 version
* Copyright (C) 1998-2000 IBM Corporation
......@@ -10,151 +10,97 @@
*
*/
#include <linux/sched.h>
#include <linux/errno.h>
#include <asm/semaphore.h>
/*
* Semaphores are implemented using a two-way counter:
* The "count" variable is decremented for each process
* that tries to acquire the semaphore, while the "sleeping"
* variable is a count of such acquires.
*
* Notably, the inline "up()" and "down()" functions can
* efficiently test if they need to do any extra work (up
* needs to do something only if count was negative before
* the increment operation.
*
* "sleeping" and the contention routine ordering is
* protected by the semaphore spinlock.
*
* Note that these functions are only called when there is
* contention on the lock, and as such all this is the
* "non-critical" part of the whole semaphore business. The
* critical part is the inline stuff in <asm/semaphore.h>
* where we want to avoid any extra jumps and calls.
* Atomically update sem->count. Equivalent to:
* old_val = sem->count.counter;
* new_val = ((old_val >= 0) ? old_val : 0) + incr;
* sem->count.counter = new_val;
* return old_val;
*/
static inline int __sem_update_count(struct semaphore *sem, int incr)
{
int old_val, new_val;
__asm__ __volatile__(" l %0,0(%3)\n"
"0: ltr %1,%0\n"
" jhe 1f\n"
" lhi %1,0\n"
"1: ar %1,%4\n"
" cs %0,%1,0(%3)\n"
" jl 0b\n"
: "=&d" (old_val), "=&d" (new_val),
"+m" (sem->count)
: "a" (&sem->count), "d" (incr) : "cc" );
return old_val;
}
/*
* Logic:
* - only on a boundary condition do we need to care. When we go
* from a negative count to a non-negative, we wake people up.
* - when we go from a non-negative count to a negative do we
* (a) synchronize with the "sleeper" count and (b) make sure
* that we're on the wakeup list before we synchronize so that
* we cannot lose wakeup events.
* The inline function up() incremented count but the result
* was <= 0. This indicates that some process is waiting on
* the semaphore. The semaphore is free and we'll wake the
* first sleeping process, so we set count to 1 unless some
* other cpu has called up in the meantime in which case
* we just increment count by 1.
*/
void __up(struct semaphore *sem)
{
__sem_update_count(sem, 1);
wake_up(&sem->wait);
}
static spinlock_t semaphore_lock = SPIN_LOCK_UNLOCKED;
/*
* The inline function down() decremented count and the result
* was < 0. The wait loop will atomically test and update the
* semaphore counter following the rules:
* count > 0: decrement count, wake up queue and exit.
* count <= 0: set count to -1, go to sleep.
*/
void __down(struct semaphore * sem)
{
struct task_struct *tsk = current;
DECLARE_WAITQUEUE(wait, tsk);
tsk->state = TASK_UNINTERRUPTIBLE;
add_wait_queue_exclusive(&sem->wait, &wait);
spin_lock_irq(&semaphore_lock);
sem->sleepers++;
for (;;) {
int sleepers = sem->sleepers;
/*
* Add "everybody else" into it. They aren't
* playing, because we own the spinlock.
*/
if (!atomic_add_negative(sleepers - 1, &sem->count)) {
sem->sleepers = 0;
break;
}
sem->sleepers = 1; /* us - see -1 above */
spin_unlock_irq(&semaphore_lock);
while (__sem_update_count(sem, -1) <= 0) {
schedule();
tsk->state = TASK_UNINTERRUPTIBLE;
spin_lock_irq(&semaphore_lock);
}
spin_unlock_irq(&semaphore_lock);
remove_wait_queue(&sem->wait, &wait);
tsk->state = TASK_RUNNING;
wake_up(&sem->wait);
}
/*
* Same as __down() with an additional test for signals.
* If a signal is pending the count is updated as follows:
* count > 0: wake up queue and exit.
* count <= 0: set count to 0, wake up queue and exit.
*/
int __down_interruptible(struct semaphore * sem)
{
int retval = 0;
struct task_struct *tsk = current;
DECLARE_WAITQUEUE(wait, tsk);
tsk->state = TASK_INTERRUPTIBLE;
add_wait_queue_exclusive(&sem->wait, &wait);
spin_lock_irq(&semaphore_lock);
sem->sleepers ++;
for (;;) {
int sleepers = sem->sleepers;
/*
* With signals pending, this turns into
* the trylock failure case - we won't be
* sleeping, and we* can't get the lock as
* it has contention. Just correct the count
* and exit.
*/
while (__sem_update_count(sem, -1) <= 0) {
if (signal_pending(current)) {
__sem_update_count(sem, 0);
retval = -EINTR;
sem->sleepers = 0;
atomic_add(sleepers, &sem->count);
break;
}
/*
* Add "everybody else" into it. They aren't
* playing, because we own the spinlock. The
* "-1" is because we're still hoping to get
* the lock.
*/
if (!atomic_add_negative(sleepers - 1, &sem->count)) {
sem->sleepers = 0;
break;
}
sem->sleepers = 1; /* us - see -1 above */
spin_unlock_irq(&semaphore_lock);
schedule();
tsk->state = TASK_INTERRUPTIBLE;
spin_lock_irq(&semaphore_lock);
}
spin_unlock_irq(&semaphore_lock);
tsk->state = TASK_RUNNING;
remove_wait_queue(&sem->wait, &wait);
tsk->state = TASK_RUNNING;
wake_up(&sem->wait);
return retval;
}
/*
* Trylock failed - make sure we correct for
* having decremented the count.
*/
int __down_trylock(struct semaphore * sem)
{
unsigned long flags;
int sleepers;
spin_lock_irqsave(&semaphore_lock, flags);
sleepers = sem->sleepers + 1;
sem->sleepers = 0;
/*
* Add "everybody else" and us into it. They aren't
* playing, because we own the spinlock.
*/
if (!atomic_add_negative(sleepers, &sem->count))
wake_up(&sem->wait);
spin_unlock_irqrestore(&semaphore_lock, flags);
return 1;
}
......@@ -48,7 +48,7 @@ unsigned int console_mode = 0;
unsigned int console_device = -1;
unsigned long memory_size = 0;
unsigned long machine_flags = 0;
struct { unsigned long addr, size, type; } memory_chunk[16];
struct { unsigned long addr, size, type; } memory_chunk[16] = { { 0 } };
#define CHUNK_READ_WRITE 0
#define CHUNK_READ_ONLY 1
__u16 boot_cpu_addr;
......@@ -99,7 +99,7 @@ void __init cpu_init (void)
/*
* Force FPU initialization:
*/
current->flags &= ~PF_USEDFPU;
clear_thread_flag(TIF_USEDFPU);
current->used_math = 0;
/* Setup active_mm for idle_task */
......@@ -165,15 +165,15 @@ __setup("condev=", condev_setup);
static int __init conmode_setup(char *str)
{
#if defined(CONFIG_HWC_CONSOLE)
if (strncmp(str, "hwc", 4) == 0 && !MACHINE_IS_P390)
if (strncmp(str, "hwc", 4) == 0)
SET_CONSOLE_HWC;
#endif
#if defined(CONFIG_TN3215_CONSOLE)
if (strncmp(str, "3215", 5) == 0 && (MACHINE_IS_VM || MACHINE_IS_P390))
if (strncmp(str, "3215", 5) == 0)
SET_CONSOLE_3215;
#endif
#if defined(CONFIG_TN3270_CONSOLE)
if (strncmp(str, "3270", 5) == 0 && (MACHINE_IS_VM || MACHINE_IS_P390))
if (strncmp(str, "3270", 5) == 0)
SET_CONSOLE_3270;
#endif
return 1;
......@@ -233,31 +233,62 @@ static void __init conmode_default(void)
}
}
#ifdef CONFIG_SMP
extern void machine_restart_smp(char *);
extern void machine_halt_smp(void);
extern void machine_power_off_smp(void);
void (*_machine_restart)(char *command) = machine_restart_smp;
void (*_machine_halt)(void) = machine_halt_smp;
void (*_machine_power_off)(void) = machine_power_off_smp;
#else
/*
* Reboot, halt and power_off routines for non SMP.
*/
#ifndef CONFIG_SMP
void machine_restart(char * __unused)
static void do_machine_restart_nonsmp(char * __unused)
{
reipl(S390_lowcore.ipl_device);
}
void machine_halt(void)
static void do_machine_halt_nonsmp(void)
{
if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
cpcmd(vmhalt_cmd, NULL, 0);
signal_processor(smp_processor_id(), sigp_stop_and_store_status);
}
void machine_power_off(void)
static void do_machine_power_off_nonsmp(void)
{
if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
cpcmd(vmpoff_cmd, NULL, 0);
signal_processor(smp_processor_id(), sigp_stop_and_store_status);
}
void (*_machine_restart)(char *command) = do_machine_restart_nonsmp;
void (*_machine_halt)(void) = do_machine_halt_nonsmp;
void (*_machine_power_off)(void) = do_machine_power_off_nonsmp;
#endif
/*
* Reboot, halt and power_off stubs. They just call _machine_restart,
* _machine_halt or _machine_power_off.
*/
void machine_restart(char *command)
{
_machine_restart(command);
}
void machine_halt(void)
{
_machine_halt();
}
void machine_power_off(void)
{
_machine_power_off();
}
/*
* Setup function called from init/main.c just after the banner
* was printed.
......@@ -284,8 +315,8 @@ void __init setup_arch(char **cmdline_p)
* print what head.S has found out about the machine
*/
printk((MACHINE_IS_VM) ?
"We are running under VM\n" :
"We are running native\n");
"We are running under VM (31 bit mode)\n" :
"We are running native (31 bit mode)\n");
printk((MACHINE_HAS_IEEE) ?
"This machine has an IEEE fpu\n" :
"This machine has no IEEE fpu\n");
......@@ -436,9 +467,10 @@ void __init setup_arch(char **cmdline_p)
lowcore->io_new_psw.mask = _IO_PSW_MASK;
lowcore->io_new_psw.addr = _ADDR_31 + (addr_t) &io_int_handler;
lowcore->ipl_device = S390_lowcore.ipl_device;
lowcore->kernel_stack = ((__u32) &init_task_union) + 8192;
lowcore->kernel_stack = ((__u32) &init_thread_union) + 8192;
lowcore->async_stack = (__u32)
__alloc_bootmem(2*PAGE_SIZE, 2*PAGE_SIZE, 0) + 8192;
lowcore->jiffy_timer = -1LL;
set_prefix((__u32) lowcore);
cpu_init();
boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr;
......@@ -485,17 +517,18 @@ void print_cpu_info(struct cpuinfo_S390 *cpuinfo)
static int show_cpuinfo(struct seq_file *m, void *v)
{
struct cpuinfo_S390 *cpuinfo;
unsigned n = v;
unsigned long n = (unsigned long) v - 1;
if (!n--) {
if (!n) {
seq_printf(m, "vendor_id : IBM/S390\n"
"# processors : %i\n"
"bogomips per cpu: %lu.%02lu\n",
smp_num_cpus, loops_per_jiffy/(500000/HZ),
(loops_per_jiffy/(5000/HZ))%100);
} else if (cpu_online_map & (1 << n)) {
cpuinfo = &safe_get_cpu_lowcore(n).cpu_data;
seq_printf(m, "processor %i: "
}
if (cpu_online_map & (1 << n)) {
cpuinfo = &safe_get_cpu_lowcore(n)->cpu_data;
seq_printf(m, "processor %li: "
"version = %02X, "
"identification = %06X, "
"machine = %04X\n",
......@@ -508,7 +541,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
static void *c_start(struct seq_file *m, loff_t *pos)
{
return *pos <= NR_CPUS ? (void)(*pos+1) : NULL;
return *pos <= NR_CPUS ? (void *)((unsigned long) *pos + 1) : NULL;
}
static void *c_next(struct seq_file *m, void *v, loff_t *pos)
{
......
......@@ -24,7 +24,9 @@
#include <linux/ptrace.h>
#include <linux/unistd.h>
#include <linux/stddef.h>
#include <linux/tty.h>
#include <linux/personality.h>
#include <linux/binfmts.h>
#include <asm/ucontext.h>
#include <asm/uaccess.h>
......@@ -267,10 +269,10 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
static inline int map_signal(int sig)
{
if (current->exec_domain
&& current->exec_domain->signal_invmap
if (current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap
&& sig < 32)
return current->exec_domain->signal_invmap[sig];
return current_thread_info()->exec_domain->signal_invmap[sig];
else
return sig;
}
......@@ -301,6 +303,10 @@ static void setup_frame(int sig, struct k_sigaction *ka,
goto give_sigsegv;
}
/* Set up backchain. */
if (__put_user(regs->gprs[15], (addr_t *) frame))
goto give_sigsegv;
/* Set up registers for signal handler */
regs->gprs[15] = (addr_t)frame;
regs->psw.addr = FIX_PSW(ka->sa.sa_handler);
......@@ -335,7 +341,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
/* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags);
err |= __put_user(0, &frame->uc.uc_link);
err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
err |= __put_user((void *)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
err |= __put_user(sas_ss_flags(regs->gprs[15]),
&frame->uc.uc_stack.ss_flags);
err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
......@@ -354,6 +360,10 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
(u16 *)(frame->retcode));
}
/* Set up backchain. */
if (__put_user(regs->gprs[15], (addr_t *) frame))
goto give_sigsegv;
/* Set up registers for signal handler */
regs->gprs[15] = (addr_t)frame;
regs->psw.addr = FIX_PSW(ka->sa.sa_handler);
......
This diff is collapsed.
......@@ -33,19 +33,19 @@
#include <asm/irq.h>
/* change this if you have some constant time drift */
#define USECS_PER_JIFFY ((signed long)1000000/HZ)
#define CLK_TICKS_PER_JIFFY ((signed long)USECS_PER_JIFFY<<12)
#define USECS_PER_JIFFY ((unsigned long) 1000000/HZ)
#define CLK_TICKS_PER_JIFFY ((unsigned long) USECS_PER_JIFFY << 12)
#define TICK_SIZE tick
static uint64_t init_timer_cc, last_timer_cc;
static ext_int_info_t ext_int_info_timer;
static uint64_t init_timer_cc;
extern rwlock_t xtime_lock;
extern unsigned long wall_jiffies;
void tod_to_timeval(uint64_t todval, struct timeval *xtime)
void tod_to_timeval(__u64 todval, struct timeval *xtime)
{
const int high_bit = 0x80000000L;
const int c_f4240 = 0xf4240L;
......@@ -79,13 +79,15 @@ void tod_to_timeval(uint64_t todval, struct timeval *xtime)
: "cc", "memory", "2", "3", "4" );
}
unsigned long do_gettimeoffset(void)
static inline unsigned long do_gettimeoffset(void)
{
__u64 timer_cc;
__u64 now;
asm volatile ("STCK %0" : "=m" (timer_cc));
/* We require the offset from the previous interrupt */
return ((unsigned long)((timer_cc - last_timer_cc)>>12));
asm ("STCK 0(%0)" : : "a" (&now) : "memory", "cc");
now = (now - init_timer_cc) >> 12;
/* We require the offset from the latest update of xtime */
now -= (__u64) wall_jiffies*USECS_PER_JIFFY;
return (unsigned long) now;
}
/*
......@@ -95,15 +97,10 @@ void do_gettimeofday(struct timeval *tv)
{
unsigned long flags;
unsigned long usec, sec;
unsigned long lost_ticks;
read_lock_irqsave(&xtime_lock, flags);
lost_ticks = jiffies - wall_jiffies;
usec = do_gettimeoffset();
if (lost_ticks)
usec +=(USECS_PER_JIFFY*lost_ticks);
sec = xtime.tv_sec;
usec += xtime.tv_usec;
usec = xtime.tv_usec + do_gettimeoffset();
read_unlock_irqrestore(&xtime_lock, flags);
while (usec >= 1000000) {
......@@ -149,51 +146,31 @@ void do_settimeofday(struct timeval *tv)
extern __u16 boot_cpu_addr;
#endif
void do_timer_interrupt(struct pt_regs *regs, __u16 error_code)
static void do_comparator_interrupt(struct pt_regs *regs, __u16 error_code)
{
int cpu = smp_processor_id();
irq_enter(cpu, 0);
/*
* reset timer to 10ms minus time already elapsed
* since timer-interrupt pending
* set clock comparator for next tick
*/
S390_lowcore.jiffy_timer += CLK_TICKS_PER_JIFFY;
asm volatile ("SCKC %0" : : "m" (S390_lowcore.jiffy_timer));
#ifdef CONFIG_SMP
if(S390_lowcore.cpu_data.cpu_addr==boot_cpu_addr) {
if (S390_lowcore.cpu_data.cpu_addr == boot_cpu_addr)
write_lock(&xtime_lock);
last_timer_cc = S390_lowcore.jiffy_timer_cc;
}
#else
last_timer_cc = S390_lowcore.jiffy_timer_cc;
#endif
/* set clock comparator */
S390_lowcore.jiffy_timer_cc += CLK_TICKS_PER_JIFFY;
asm volatile ("SCKC %0" : : "m" (S390_lowcore.jiffy_timer_cc));
/*
* In the SMP case we use the local timer interrupt to do the
* profiling, except when we simulate SMP mode on a uniprocessor
* system, in that case we have to call the local interrupt handler.
*/
#ifdef CONFIG_SMP
/* when SMP, do smp_local_timer_interrupt for *all* CPUs,
but only do the rest for the boot CPU */
smp_local_timer_interrupt(regs);
#else
if (!user_mode(regs))
s390_do_profile(regs->psw.addr);
#endif
update_process_times(user_mode(regs));
#ifdef CONFIG_SMP
if(S390_lowcore.cpu_data.cpu_addr==boot_cpu_addr)
#endif
{
if (S390_lowcore.cpu_data.cpu_addr == boot_cpu_addr) {
do_timer(regs);
#ifdef CONFIG_SMP
write_unlock(&xtime_lock);
#endif
}
#else
do_timer(regs);
#endif
irq_exit(cpu, 0);
}
......@@ -201,19 +178,17 @@ void do_timer_interrupt(struct pt_regs *regs, __u16 error_code)
/*
* Start the clock comparator on the current CPU
*/
static long cr0 __attribute__ ((aligned (8)));
void init_100hz_timer(void)
void init_cpu_timer(void)
{
unsigned long cr0;
/* allow clock comparator timer interrupt */
asm volatile ("STCTL 0,0,%0" : "=m" (cr0) : : "memory");
cr0 |= 0x800;
asm volatile ("LCTL 0,0,%0" : : "m" (cr0) : "memory");
/* set clock comparator */
/* read the TOD clock */
asm volatile ("STCK %0" : "=m" (S390_lowcore.jiffy_timer_cc));
S390_lowcore.jiffy_timer_cc += CLK_TICKS_PER_JIFFY;
asm volatile ("SCKC %0" : : "m" (S390_lowcore.jiffy_timer_cc));
S390_lowcore.jiffy_timer = (__u64) jiffies * CLK_TICKS_PER_JIFFY;
S390_lowcore.jiffy_timer += init_timer_cc + CLK_TICKS_PER_JIFFY;
asm volatile ("SCKC %0" : : "m" (S390_lowcore.jiffy_timer));
}
/*
......@@ -222,12 +197,14 @@ void init_100hz_timer(void)
*/
void __init time_init(void)
{
__u64 set_time_cc;
int cc;
/* kick the TOD clock */
asm volatile ("STCK %1\n\t"
asm volatile ("STCK 0(%1)\n\t"
"IPM %0\n\t"
"SRL %0,28" : "=r" (cc), "=m" (init_timer_cc));
"SRL %0,28" : "=r" (cc) : "a" (&init_timer_cc)
: "memory", "cc");
switch (cc) {
case 0: /* clock in set state: all is fine */
break;
......@@ -241,12 +218,17 @@ void __init time_init(void)
printk("time_init: TOD clock stopped/non-operational\n");
break;
}
/* request the 0x1004 external interrupt */
if (register_external_interrupt(0x1004, do_timer_interrupt) != 0)
panic("Couldn't request external interrupts 0x1004");
init_100hz_timer();
init_timer_cc = S390_lowcore.jiffy_timer_cc;
init_timer_cc -= 0x8126d60e46000000LL -
/* set xtime */
set_time_cc = init_timer_cc - 0x8126d60e46000000LL +
(0x3c26700LL*1000000*4096);
tod_to_timeval(init_timer_cc, &xtime);
tod_to_timeval(set_time_cc, &xtime);
/* request the 0x1004 external interrupt */
if (register_early_external_interrupt(0x1004, do_comparator_interrupt,
&ext_int_info_timer) != 0)
panic("Couldn't request external interrupt 0x1004");
/* init CPU timer */
init_cpu_timer();
}
This diff is collapsed.
......@@ -6,46 +6,83 @@
* Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Authors(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
*
* These functions have a non-standard call interface
* These functions have standard call interface
*/
#include <asm/lowcore.h>
.text
.align 4
.globl __copy_from_user_fixup
__copy_from_user_fixup:
l 1,__LC_PGM_OLD_PSW+4
sll 4,1
srl 4,1
0: lhi 3,-4096
sll 3,1
srl 3,1
n 3,__LC_TRANS_EXC_ADDR
sr 3,4
bm 4(1)
1: mvcle 2,4,0
b 4(1)
.globl __copy_from_user_asm
__copy_from_user_asm:
lr %r5,%r3
sacf 512
0: mvcle %r2,%r4,0
jo 0b
1: sacf 0
lr %r2,%r5
br %r14
2: sll %r4,1
srl %r4,1
lhi %r3,-4096
sll %r3,1
srl %r3,1
n %r3,__LC_TRANS_EXC_ADDR
sr %r3,%r4
jm 1b
j 0b
.section __ex_table,"a"
.long 1b,0b
.long 0b,2b
.previous
.align 4
.text
.globl __copy_to_user_fixup
__copy_to_user_fixup:
l 1,__LC_PGM_OLD_PSW+4
sll 4,1
srl 4,1
0: lhi 5,-4096
sll 5,1
srl 5,1
n 5,__LC_TRANS_EXC_ADDR
sr 5,4
bm 4(1)
1: mvcle 4,2,0
b 4(1)
.globl __copy_to_user_asm
__copy_to_user_asm:
lr %r5,%r3
sacf 512
0: mvcle %r4,%r2,0
jo 0b
1: sacf 0
lr %r2,%r3
br %r14
2: sll %r4,1
srl %r4,1
lhi %r5,-4096
sll %r5,1
srl %r5,1
n %r5,__LC_TRANS_EXC_ADDR
sr %r5,%r4
jm 1b
j 0b
.section __ex_table,"a"
.long 1b,0b
.long 0b,2b
.previous
.align 4
.text
.globl __clear_user_asm
__clear_user_asm:
lr %r4,%r2
lr %r5,%r3
sr %r2,%r2
sr %r3,%r3
sacf 512
0: mvcle %r4,%r2,0
jo 0b
1: sacf 0
lr %r2,%r3
br %r14
2: sll %r4,1
srl %r4,1
lhi %r5,-4096
sll %r5,1
srl %r5,1
n %r5,__LC_TRANS_EXC_ADDR
sr %r5,%r4
jm 1b
j 0b
.section __ex_table,"a"
.long 0b,2b
.previous
This diff is collapsed.
......@@ -43,7 +43,6 @@ unsigned long
search_exception_table(unsigned long addr)
{
unsigned long ret = 0;
unsigned long flags;
#ifndef CONFIG_MODULES
addr &= 0x7fffffff; /* remove amode bit from address */
......@@ -52,6 +51,7 @@ search_exception_table(unsigned long addr)
if (ret) ret = FIX_PSW(ret);
return ret;
#else
unsigned long flags;
/* The kernel is the last "module" -- no need to treat it special. */
struct module *mp;
addr &= 0x7fffffff; /* remove amode bit from address */
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -20,6 +20,7 @@
#include <linux/pagemap.h>
#include <linux/highmem.h>
#include <linux/spinlock.h>
#include <linux/binfmts.h>
#define __NO_VERSION__
#include <linux/module.h>
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment