Commit a2d6205f authored by Linus Torvalds's avatar Linus Torvalds

Import 2.1.35

parent 92cc7d38
......@@ -905,8 +905,9 @@ S: Australia
N: Martin Mares
E: mj@k332.feld.cvut.cz
W: http://atrey.karlin.mff.cuni.cz/~mj/
D: BIOS video mode handling code
D: Miscellaneous kernel fixes
D: Miscellaneous kernel fixes and hacks
D: MOXA C-218 serial board driver
D: BOOTP support
S: Kankovskeho 1241
......
......@@ -26,7 +26,10 @@ HTML-ized shopping list.
http://www.datanet.hu/generations/linux/Changes2.html is an
English-language HTML version.
Last updated: April 1, 1997.
Also, don't forget http://www.linuxhq.com/ for all your Linux kernel
needs.
Last updated: April 15, 1997.
Current Author: Chris Ricker (gt1355b@prism.gatech.edu).
Current Minimal Requirements
......@@ -35,19 +38,19 @@ Current Minimal Requirements
Upgrade to at *least* these software revisions before thinking you've
encountered a bug!
- Kernel modules modutils-2.1.29-970320
- Kernel modules modutils-2.1.34
- Gnu C 2.7.2.1
- Binutils 2.7.0.9
- Linux C Library 5.4.23
- Dynamic Linker (ld.so) 1.8.5
- Linux C++ Library 2.7.2.1
- Procps 1.01
- Mount 2.5p
- Mount 2.6e
- Net-tools 1.32-alpha
- Kbd 0.91
- Loadlin 1.6a
- Sh-utils 1.16
- Ncpfs 2.1.1
- Autofs 970409
- NFS 0.4.21
Upgrade notes
*************
......@@ -78,20 +81,22 @@ release.
If you upgrade to libc-5.4.x, you also have to upgrade your dynamic
linker (ld.so) to at least 1.8.5, or all sorts of weirdness will
happen. Actually, ld.so-1.8.2 and later will work, but only 1.8.5 is
widely available, so if you need to upgrade, use it.
happen. Actually, ld.so-1.8.2 and later will work, but 1.8.5 is widely
available, so if you need to upgrade, use it. If you get a release
later than 1.8.5, avoid 1.8.10 as it introduces a few bugs that are
fixed in later releases.
Modules
=======
You need to upgrade to modutils-2.1.29-970320 for kernels 2.1.29 and
later.
You need to upgrade to modutils-2.1.34 for kernels 2.1.34 and later.
Binutils
========
If you upgrade binutils, please read its accompanying release notes
to find out the proper way to upgrade it.
to find out the proper way to upgrade it. No, the instruction to "rm
`which encaps`" is not a joke.
Gnu C
=====
......@@ -126,6 +131,15 @@ presence.
To run bootpd, you'll need to issue the following command: echo 1
>/proc/sys/net/ipv4/ip_boot_agent
Mount and network file systems
==============================
The NFS code in the kernel is currently being revised, resulting in
much-improved performance. As a result, you'll need to upgrade mount
to a 2.6 release. Also, amd is being phased out in favor of the much
better autofs. You'll also have to get the appropriate utils to use
autofs as well as the new NFS utils.
RPM
===
......@@ -151,6 +165,16 @@ Sh-utils
updated to be POSIX-compliant. As a result, your expr needs to be
updated. Use sh-utils 1.16 or later.
Parallel Ports
==============
As of 2.1.33, parallel port support can now by handled by the parport
driver. Be aware that with Plug-and-Play support turned on, your
parallel port may no longer be where you expect it; for example, LPT1
(under DOS) was sometimes /dev/lp1 in Linux, but will probably be
/dev/lp0 with the new Plug-and-Play driver. If printing breaks with
the new driver, try checking your lpd configuration.
How to know the version of the installed programs
*************************************************
......@@ -223,8 +247,9 @@ ftp://sunsite.unc.edu/pub/Linux/GCC/ld.so-1.8.5.tar.gz
Modules utilities
=================
The 2.1.29-970320 release:
ftp://ftp.redhat.com/pub/alphabits/modutils-2.1.29-970320.tar.gz
The 2.1.34 release:
ftp://ftp.redhat.com/pub/alphabits/modutils-2.1.34.tar.gz
ftp://ftp.kernel.org/pub/linux/kernel/modutils-2.1.34.tar.gz
Procps utilities
================
......@@ -263,10 +288,29 @@ ftp://elserv.ffm.fgan.de/pub/linux/loadlin-1.6/update-1.6a/loadlin.exe.gz
Sh-utils
========
The 1.16 release
The 1.16 release:
ftp://sunsite.unc.edu/pub/gnu/sh-utils-1.16.tar.gz
ftp://prep.ai.mit.edu/pub/gnu/sh-utils-1.16.tar.gz
Mount
=====
The 2.6e release:
ftp://ftp.win.tue.nl/pub/linux/util/mount-2.6e.tar.gz
Autofs
======
The 970409 release:
ftp://ftp.kernel.org/pub/linux/daemons/autofs/autofs-970409.tar.gz
NFS
===
The 0.4.21 release:
ftp://ftp.mathematik.th-darmstadt.de/pub/linux/okir/linux-nfs-0.4.21.tar.gz
ftp://linux.nrao.edu/pub/people/okir/linux-nfs-0.4.21.tar.gz
Other Info
==========
......
......@@ -4439,6 +4439,12 @@ CONFIG_RTC
have a use for such a device (such as periodic data sampling), then
say Y here, and go read the file Documentation/rtc.txt for details.
ARC console time
CONFIG_RTC_ARC
If you boot your Alpha using the ARC firmware, say Y here. This option
adjusts the RTC clock to take into account the different starting epoch
used by ARC.
Sound card support
CONFIG_SOUND
If you have a Sound Card in your Computer, i.e. if it can say more
......
......@@ -452,10 +452,10 @@ by doing the following after installing slackware (or whatever):
0. Boot from the "boot floppy" created during the installation
1. Mount your DOS partition as /dos (and stick it in /etc/fstab)
2. Move your kernel (/vmlinuz) to /dos/vmlinuz with: mv /vmlinuz /dos
3. Edit /etc/lilo.conf to change /vmlinuz to /dos/vmlinuz
4. Move /boot to /dos/boot with: cp -a /boot /dos ; rm -r /boot
5. Create a symlink for LILO to use with: ln -s /dos/boot /boot
2. Move /boot to /dos/boot with: cp -a /boot /dos ; rm -r /boot
3. Create a symlink for LILO to use with: ln -s /dos/boot /boot
4. Move your kernel (/vmlinuz) to /boot/vmlinuz: mv /vmlinuz /boot
5. Edit /etc/lilo.conf to change /vmlinuz to /boot/vmlinuz
6. Re-run LILO with: lilo
A danger with this approach is that whenever an MS-DOS "defragmentation"
......
VERSION = 2
PATCHLEVEL = 1
SUBLEVEL = 34
SUBLEVEL = 35
ARCH := $(shell uname -m | sed s/i.86/i386/)
......
......@@ -151,6 +151,9 @@ endmenu
source fs/Config.in
source drivers/char/Config.in
if [ "$CONFIG_RTC" != "n" ]; then
bool ' ARC console time' CONFIG_RTC_ARC y
fi
mainmenu_option next_comment
comment 'Sound'
......
......@@ -224,6 +224,7 @@ CONFIG_PSMOUSE=y
# CONFIG_APM is not set
# CONFIG_WATCHDOG is not set
# CONFIG_RTC is not set
CONFIG_RTC_ARC=y
#
# Sound
......
......@@ -19,6 +19,7 @@
#include <asm/uaccess.h>
#include <asm/processor.h>
#include <asm/checksum.h>
#include <linux/interrupt.h>
#include <asm/softirq.h>
extern void bcopy (const char *src, char *dst, int len);
......@@ -38,6 +39,7 @@ extern void __divqu (void);
extern void __remqu (void);
EXPORT_SYMBOL(__alpha_bh_counter);
EXPORT_SYMBOL(local_irq_count);
/* platform dependent support */
EXPORT_SYMBOL(_inb);
......
......@@ -126,19 +126,8 @@
.ent entInt
entInt:
SAVE_ALL
/* start atomic operation with respect to software interrupts */
lda $0,intr_count
ldl $1,0($0)
addq $1,1,$1
stl $1,0($0)
/* set up the arguments to the C interrupt handler */
ldq $8,current_set
jsr $26,do_entInt
/* ok, return */
lda $0,intr_count
ldl $1,0($0)
subq $1,1,$1
stl $1,0($0)
br $31,ret_from_sys_call
.end entInt
......
......@@ -24,8 +24,7 @@ __start:
br $27,1f
1: ldgp $29,0($27)
/* We need to get current loaded up with our first task. */
lda $8,init_task
stq $8,current_set
ldq $8,current_set
/* And then we can start the kernel. */
jsr $26,start_kernel
halt
......
......@@ -26,7 +26,12 @@
#include <asm/bitops.h>
#include <asm/dma.h>
extern void timer_interrupt(struct pt_regs * regs);
#define RTC_IRQ 8
#ifdef CONFIG_RTC
#define TIMER_IRQ 0 /* timer is the pit */
#else
#define TIMER_IRQ RTC_IRQ /* the timer is, in fact, the rtc */
#endif
#if NR_IRQS > 64
# error Unable to handle more than 64 irq levels.
......@@ -132,6 +137,7 @@ void enable_irq(unsigned int irq_nr)
/*
* Initial irq handlers.
*/
static struct irqaction timer_irq = { NULL, 0, 0, NULL, NULL, NULL};
static struct irqaction *irq_action[NR_IRQS];
int get_irq_list(char *buf)
......@@ -143,7 +149,7 @@ int get_irq_list(char *buf)
action = irq_action[i];
if (!action)
continue;
len += sprintf(buf+len, "%2d: %8d %c %s",
len += sprintf(buf+len, "%2d: %10u %c %s",
i, kstat.interrupts[i],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
......@@ -211,7 +217,10 @@ int request_irq(unsigned int irq,
shared = 1;
}
action = (struct irqaction *)kmalloc(sizeof(struct irqaction),
if (irq == TIMER_IRQ)
action = &timer_irq;
else
action = (struct irqaction *)kmalloc(sizeof(struct irqaction),
GFP_KERNEL);
if (!action)
return -ENOMEM;
......@@ -329,6 +338,7 @@ static inline void handle_irq(int irq, struct pt_regs * regs)
static inline void device_interrupt(int irq, int ack, struct pt_regs * regs)
{
struct irqaction * action;
int cpu = smp_processor_id();
if ((unsigned) irq > NR_IRQS) {
printk("device_interrupt: unexpected interrupt %d\n", irq);
......@@ -660,7 +670,9 @@ int probe_irq_off(unsigned long irqs)
{
int i;
irqs &= irq_mask & ~1; /* always mask out irq 0---it's the unused timer */
/* as irq 0 & 8 handling don't use this function, i didn't
* bother changing the following: */
irqs &= irq_mask & ~1; /* always mask out irq 0---it's the unused timer */
#ifdef CONFIG_ALPHA_P2K
irqs &= ~(1 << 8); /* mask out irq 8 since that's the unused RTC input to PIC */
#endif
......@@ -700,7 +712,7 @@ asmlinkage void do_entInt(unsigned long type, unsigned long vector, unsigned lon
printk("Interprocessor interrupt? You must be kidding\n");
break;
case 1:
timer_interrupt(&regs);
handle_irq(RTC_IRQ, &regs);
return;
case 2:
machine_check(vector, la_ptr, &regs);
......
......@@ -29,6 +29,10 @@
#include <linux/elfcore.h>
#include <linux/reboot.h>
#ifdef CONFIG_RTC
#include <linux/mc146818rtc.h>
#endif
#include <asm/reg.h>
#include <asm/uaccess.h>
#include <asm/system.h>
......@@ -66,6 +70,24 @@ asmlinkage int sys_idle(void)
void machine_restart(char * __unused)
{
#ifdef CONFIG_RTC /* reset rtc to defaults */
unsigned char control;
unsigned long flags;
/* i'm not sure if i really need to disable interrupts here */
save_flags(flags);
cli();
/* reset periodic interrupt frequency */
CMOS_WRITE(0x26, RTC_FREQ_SELECT);
/* turn on periodic interrupts */
control = CMOS_READ(RTC_CONTROL);
control |= RTC_PIE;
CMOS_WRITE(control, RTC_CONTROL);
CMOS_READ(RTC_INTR_FLAGS);
restore_flags(flags);
#endif
#if defined(CONFIG_ALPHA_SRM) && defined(CONFIG_ALPHA_ALCOR)
/* who said DEC engineer's have no sense of humor? ;-)) */
*(int *) GRU_RESET = 0x0000dead;
......
......@@ -22,6 +22,11 @@
#include <linux/delay.h>
#include <linux/config.h> /* CONFIG_ALPHA_LCA etc */
#ifdef CONFIG_RTC
#include <linux/ioport.h>
#include <linux/timex.h>
#endif
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/system.h>
......@@ -83,9 +88,17 @@ static void init_pit (void)
outb(0x18, 0x41);
#endif
#ifdef CONFIG_RTC /* setup interval timer if /dev/rtc is being used */
outb(0x34, 0x43); /* binary, mode 2, LSB/MSB, ch 0 */
outb(LATCH & 0xff, 0x40); /* LSB */
outb(LATCH >> 8, 0x40); /* MSB */
request_region(0x40, 0x20, "timer"); /* reserve pit */
#else
outb(0x36, 0x43); /* counter 0: system timer */
outb(0x00, 0x40);
outb(0x00, 0x40);
request_region(0x70, 0x10, "timer"); /* reserve rtc */
#endif
outb(0xb6, 0x43); /* counter 2: speaker */
outb(0x31, 0x42);
......
......@@ -10,6 +10,8 @@
* 1995-03-26 Markus Kuhn
* fixed 500 ms bug at call to set_rtc_mmss, fixed DS12887
* precision CMOS clock update
* 1997-01-09 Adrian Sun
* use interval timer if CONFIG_RTC=y
*/
#include <linux/errno.h>
#include <linux/sched.h>
......@@ -25,7 +27,11 @@
#include <linux/mc146818rtc.h>
#include <linux/timex.h>
#define TIMER_IRQ 0
#ifdef CONFIG_RTC
#define TIMER_IRQ 0 /* using pit for timer */
#else
#define TIMER_IRQ 8 /* using rtc for timer */
#endif
extern struct hwrpb_struct *hwrpb;
......@@ -61,7 +67,7 @@ static inline __u32 rpcc(void)
* timer_interrupt() needs to keep up the real-time clock,
* as well as call the "do_timer()" routine every clocktick
*/
void timer_interrupt(struct pt_regs * regs)
void timer_interrupt(int irq, void *dev, struct pt_regs * regs)
{
__u32 delta, now;
......@@ -125,6 +131,10 @@ static inline unsigned long mktime(unsigned int year, unsigned int mon,
void time_init(void)
{
#ifdef CONFIG_RTC
unsigned char save_control;
#endif
void (*irq_handler)(int, void *, struct pt_regs *);
unsigned int year, mon, day, hour, min, sec;
int i;
......@@ -178,6 +188,21 @@ void time_init(void)
state.scaled_ticks_per_cycle = ((unsigned long) HZ << FIX_SHIFT) / hwrpb->cycle_freq;
state.max_cycles_per_tick = (2 * hwrpb->cycle_freq) / HZ;
state.last_rtc_update = 0;
#ifdef CONFIG_RTC
/* turn off RTC interrupts before /dev/rtc is initialized */
save_control = CMOS_READ(RTC_CONTROL);
save_control &= ~RTC_PIE;
save_control &= ~RTC_AIE;
save_control &= ~RTC_UIE;
CMOS_WRITE(save_control, RTC_CONTROL);
CMOS_READ(RTC_INTR_FLAGS);
#endif
/* setup timer */
irq_handler = timer_interrupt;
if (request_irq(TIMER_IRQ, irq_handler, 0, "timer", NULL))
panic("Could not allocate timer IRQ!");
}
/*
......
......@@ -17,33 +17,11 @@ AS86 =$(CROSS_COMPILE)as86 -0 -a
AS386 =$(CROSS_COMPILE)as86 -3
LD86 =$(CROSS_COMPILE)ld86 -0
#
# ZIMAGE_OFFSET is the load offset of the compression loader
# BZIMAGE_OFFSET is the load offset of the high loaded compression loader
#
ZIMAGE_OFFSET=0x1000
BZIMAGE_OFFSET=0x100000
#
# IMAGE_OFFSET is the load offset of the _real_ kernel, soon
# to be offset by another 0xC0000000...
#
IMAGE_OFFSET=0xC0100000
# This is used for ELF - it needs to migrate or be moved.
LD_RFLAG = -m elf_i386
LD=$(CROSS_COMPILE)ld -m elf_i386
CPP=$(CC) -E -D__ELF__
OBJDUMP=$(CROSS_COMPILE)objdump
OBJDUMP_FLAGS=-k -q
ENCAPS=$(CROSS_COMPILE)encaps
OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -R .stab -R .stabstr
ZLDFLAGS=-e startup_32
CPP=$(CC) -E
OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S
LDFLAGS=-e stext
ZLINKFLAGS =-Ttext $(ZIMAGE_OFFSET) $(ZLDFLAGS)
BZLINKFLAGS =-Ttext $(BZIMAGE_OFFSET) $(ZLDFLAGS)
LINKFLAGS =-Ttext $(IMAGE_OFFSET) $(LDFLAGS)
LINKFLAGS =-T arch/i386/vmlinux.lds $(LDFLAGS)
CFLAGS := $(CFLAGS) -pipe -fno-strength-reduce
......
......@@ -8,29 +8,21 @@
# Copyright (C) 1994 by Linus Torvalds
#
HOSTCFLAGS := $(HOSTCFLAGS) -D__BFD__
ifdef SMP
HOSTCFLAGS := $(HOSTCFLAGS) -D__SMP__
endif
BOOT_INCL = $(TOPDIR)/include/linux/config.h \
$(TOPDIR)/include/linux/autoconf.h \
$(TOPDIR)/include/asm/boot.h
zImage: $(CONFIGURE) bootsect setup compressed/vmlinux tools/build
if hash $(ENCAPS) 2> /dev/null; then \
$(OBJDUMP) $(OBJDUMP_FLAGS) -o $(ZIMAGE_OFFSET) compressed/vmlinux > compressed/vmlinux.out; \
else \
$(OBJCOPY) compressed/vmlinux compressed/vmlinux.out; \
fi
$(OBJCOPY) compressed/vmlinux compressed/vmlinux.out
tools/build bootsect setup compressed/vmlinux.out $(ROOT_DEV) > zImage
sync
bzImage: $(CONFIGURE) bbootsect setup compressed/bvmlinux tools/bbuild
if hash $(ENCAPS) 2> /dev/null; then \
$(OBJDUMP) $(OBJDUMP_FLAGS) -o $(BZIMAGE_OFFSET) compressed/bvmlinux > compressed/bvmlinux.out; \
else \
$(OBJCOPY) compressed/bvmlinux compressed/bvmlinux.out; \
fi
tools/bbuild bbootsect setup compressed/bvmlinux.out $(ROOT_DEV) > bzImage
sync
bzImage: $(CONFIGURE) bbootsect bsetup compressed/bvmlinux tools/build
$(OBJCOPY) compressed/bvmlinux compressed/bvmlinux.out
tools/build -b bbootsect bsetup compressed/bvmlinux.out $(ROOT_DEV) > bzImage
compressed/vmlinux: $(TOPDIR)/vmlinux
@$(MAKE) -C compressed vmlinux
......@@ -54,25 +46,31 @@ install: $(CONFIGURE) zImage
tools/build: tools/build.c
$(HOSTCC) $(HOSTCFLAGS) -o $@ $< -I$(TOPDIR)/include
tools/bbuild: tools/build.c
$(HOSTCC) $(HOSTCFLAGS) -D__BIG_KERNEL__ -o $@ $< -I$(TOPDIR)/include
setup: setup.o
$(LD86) -s -o $@ $<
setup.o: setup.s
$(AS86) -o $@ $<
setup.s: setup.S video.S $(CONFIGURE) $(TOPDIR)/include/linux/config.h Makefile
setup.s: setup.S video.S Makefile $(BOOT_INCL) $(TOPDIR)/include/linux/version.h
$(CPP) -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@
bsetup: bsetup.o
$(LD86) -s -o $@ $<
bsetup.o: bsetup.s
$(AS86) -o $@ $<
bsetup.s: setup.S video.S Makefile $(BOOT_INCL) $(TOPDIR)/include/linux/version.h
$(CPP) -D__BIG_KERNEL__ -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@
bootsect: bootsect.o
$(LD86) -s -o $@ $<
bootsect.o: bootsect.s
$(AS86) -o $@ $<
bootsect.s: bootsect.S $(CONFIGURE) $(TOPDIR)/include/linux/config.h Makefile
bootsect.s: bootsect.S Makefile $(BOOT_INCL)
$(CPP) -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@
bbootsect: bbootsect.o
......@@ -81,14 +79,13 @@ bbootsect: bbootsect.o
bbootsect.o: bbootsect.s
$(AS86) -o $@ $<
bbootsect.s: bootsect.S $(CONFIGURE) $(TOPDIR)/include/linux/config.h Makefile
bbootsect.s: bootsect.S Makefile $(BOOT_INCL)
$(CPP) -D__BIG_KERNEL__ -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@
dep:
clean:
rm -f bootsect setup
rm -f bbootsect
rm -f zImage tools/build compressed/vmlinux.out
rm -f bzImage tools/bbuild compressed/bvmlinux.out
rm -f tools/build
rm -f setup bootsect zImage compressed/vmlinux.out
rm -f bsetup bbootsect bzImage compressed/bvmlinux.out
@$(MAKE) -C compressed clean
!
! SYS_SIZE is the number of clicks (16 bytes) to be loaded.
! 0x7F00 is 0x7F000 bytes = 508kB, more than enough for current
! versions of linux which compress the kernel
!
#include <linux/config.h>
SYSSIZE = DEF_SYSSIZE
!
! bootsect.s Copyright (C) 1991, 1992 Linus Torvalds
! modified by Drew Eckhardt
! modified by Bruce Evans (bde)
......@@ -29,13 +22,17 @@ SYSSIZE = DEF_SYSSIZE
! read errors will result in a unbreakable loop. Reboot by hand. It
! loads pretty fast by getting whole tracks at a time whenever possible.
#include <asm/boot.h>
.text
SETUPSECS = 4 ! nr of setup-sectors
SETUPSECS = 4 ! default nr of setup-sectors
BOOTSEG = 0x07C0 ! original address of boot-sector
INITSEG = DEF_INITSEG ! we move boot here - out of the way
SETUPSEG = DEF_SETUPSEG ! setup starts here
SYSSEG = DEF_SYSSEG ! system loaded at 0x10000 (65536).
SYSSIZE = DEF_SYSSIZE ! system size: number of 16-byte clicks
! to be loaded
! ROOT_DEV & SWAP_DEV are now written by "build".
ROOT_DEV = 0
......
......@@ -10,15 +10,22 @@ SYSTEM = $(TOPDIR)/vmlinux
OBJECTS = $(HEAD) misc.o
CFLAGS = -O2 -DSTDC_HEADERS
ZLDFLAGS = -e startup_32
#
# ZIMAGE_OFFSET is the load offset of the compression loader
# BZIMAGE_OFFSET is the load offset of the high loaded compression loader
#
ZIMAGE_OFFSET = 0x1000
BZIMAGE_OFFSET = 0x100000
ZLINKFLAGS = -Ttext $(ZIMAGE_OFFSET) $(ZLDFLAGS)
BZLINKFLAGS = -Ttext $(BZIMAGE_OFFSET) $(ZLDFLAGS)
ifdef SMP
CFLAGS := $(CFLAGS) -D__SMP__
endif
TARGET=--target elf32-i386
INPUT_DATA=input_data
INPUT_LEN=input_len
all: vmlinux
vmlinux: piggy.o $(OBJECTS)
......@@ -40,24 +47,14 @@ head.o: head.S $(TOPDIR)/include/linux/tasks.h
endif
# You cannot compress a file and have the kernel uncompress it, it must
# be stdin
piggy.o: $(SYSTEM)
tmppiggy=/tmp/$$$$piggy; \
rm -f $$tmppiggy $$tmppiggy.gz $$tmppiggy.lnk; \
if hash $(ENCAPS) 2> /dev/null; then \
$(OBJDUMP) $(OBJDUMP_FLAGS) -o $(IMAGE_OFFSET) $(SYSTEM) > $$tmppiggy; \
else \
$(OBJCOPY) $(SYSTEM) $$tmppiggy; \
fi; \
$(OBJCOPY) $(SYSTEM) $$tmppiggy; \
gzip -f -9 < $$tmppiggy > $$tmppiggy.gz; \
if hash $(ENCAPS) 2> /dev/null; then \
$(ENCAPS) $(TARGET) piggy.o $$tmppiggy.gz $(INPUT_DATA) $(INPUT_LEN); \
else \
echo "SECTIONS { .data : { input_len = .; LONG(input_data_end - input_data) input_data = .; *(.data) input_data_end = .; }}" > $$tmppiggy.lnk; \
$(LD) -m elf_i386 -r -o piggy.o -b binary $$tmppiggy.gz -b elf32-i386 -T $$tmppiggy.lnk; \
fi; \
echo "SECTIONS { .data : { input_len = .; LONG(input_data_end - input_data) input_data = .; *(.data) input_data_end = .; }}" > $$tmppiggy.lnk; \
$(LD) -m elf_i386 -r -o piggy.o -b binary $$tmppiggy.gz -b elf32-i386 -T $$tmppiggy.lnk; \
rm -f $$tmppiggy $$tmppiggy.gz $$tmppiggy.lnk
clean:
rm -f xtract piggyback vmlinux bvmlinux
rm -f vmlinux bvmlinux
......@@ -75,11 +75,7 @@ static void gzip_release(void **);
* This is set up by the setup-routine at boot-time
*/
#define EXT_MEM_K (*(unsigned short *)0x90002)
#define DRIVE_INFO (*(struct drive_info *)0x90080)
#define SCREEN_INFO (*(struct screen_info *)0x90000)
#define RAMDISK_SIZE (*(unsigned short *)0x901F8)
#define ORIG_ROOT_DEV (*(unsigned short *)0x901FC)
#define AUX_DEVICE_INFO (*(unsigned char *)0x901FF)
extern char input_data[];
extern int input_len;
......
/*
* linux/zBoot/piggyback.c
*
* (C) 1993 Hannu Savolainen
*/
/*
* This program reads the compressed system image from stdin and
* encapsulates it into an object file written to the stdout.
*/
#include <stdio.h>
#include <unistd.h>
#include <a.out.h>
int main(int argc, char *argv[])
{
int c, n=0, len=0;
char tmp_buf[512*1024];
struct exec obj = {0x00640107}; /* object header */
char string_names[] = {"_input_data\0_input_len\0"};
struct nlist var_names[2] = /* Symbol table */
{
{ /* _input_data */
(char *)4, 7, 0, 0, 0
},
{ /* _input_len */
(char *)16, 7, 0, 0, 0
}
};
len = 0;
while ((n = read(0, &tmp_buf[len], sizeof(tmp_buf)-len+1)) > 0)
len += n;
if (n==-1)
{
perror("stdin");
exit(-1);
}
if (len >= sizeof(tmp_buf))
{
fprintf(stderr, "%s: Input too large\n", argv[0]);
exit(-1);
}
fprintf(stderr, "Compressed size %d.\n", len);
/*
* Output object header
*/
obj.a_data = len + sizeof(long);
obj.a_syms = sizeof(var_names);
write(1, (char *)&obj, sizeof(obj));
/*
* Output data segment (compressed system & len)
*/
write(1, tmp_buf, len);
write(1, (char *)&len, sizeof(len));
/*
* Output symbol table
*/
var_names[1].n_value = len;
write(1, (char *)&var_names, sizeof(var_names));
/*
* Output string table
*/
len = sizeof(string_names) + sizeof(len);
write(1, (char *)&len, sizeof(len));
write(1, string_names, sizeof(string_names));
exit(0);
}
/*
* linux/zBoot/xtract.c
*
* Copyright (C) 1993 Hannu Savolainen
*
* Extracts the system image and writes it to the stdout.
* based on tools/build.c by Linus Torvalds
*/
#include <stdio.h> /* fprintf */
#include <string.h>
#include <stdlib.h> /* contains exit */
#include <sys/types.h> /* unistd.h needs this */
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <unistd.h> /* contains read/write */
#include <fcntl.h>
#include <a.out.h>
#define N_MAGIC_OFFSET 1024
static int GCC_HEADER = sizeof(struct exec);
#define STRINGIFY(x) #x
void die(char * str)
{
fprintf(stderr,"%s\n",str);
exit(1);
}
void usage(void)
{
die("Usage: xtract system [ | gzip | piggyback > piggy.s]");
}
int main(int argc, char ** argv)
{
int i,c,id, sz;
char buf[1024];
char major_root, minor_root;
struct stat sb;
struct exec *ex = (struct exec *)buf;
if (argc != 2)
usage();
if ((id=open(argv[1],O_RDONLY,0))<0)
die("Unable to open 'system'");
if (read(id,buf,GCC_HEADER) != GCC_HEADER)
die("Unable to read header of 'system'");
if (N_MAGIC(*ex) == ZMAGIC) {
GCC_HEADER = N_MAGIC_OFFSET;
lseek(id, GCC_HEADER, SEEK_SET);
} else if (N_MAGIC(*ex) != QMAGIC)
die("Non-GCC header of 'system'");
sz = N_SYMOFF(*ex) - GCC_HEADER + 4; /* +4 to get the same result than tools/build */
fprintf(stderr, "System size is %d\n", sz);
while (sz)
{
int l, n;
l = sz;
if (l > sizeof(buf)) l = sizeof(buf);
if ((n=read(id, buf, l)) !=l)
{
if (n == -1)
perror(argv[1]);
else
fprintf(stderr, "Unexpected EOF\n");
die("Can't read system");
}
write(1, buf, l);
sz -= l;
}
close(id);
return(0);
}
......@@ -27,12 +27,12 @@
! Video handling moved to video.S by Martin Mares, March 1996
! <mj@k332.feld.cvut.cz>
! NOTE! These had better be the same as in bootsect.s!
#define __ASSEMBLY__
#include <linux/config.h>
#include <asm/segment.h>
#include <linux/version.h>
#include <linux/compile.h>
#include <asm/boot.h>
! Signature words to ensure LILO loaded us right
#define SIG1 0xAA55
......@@ -79,23 +79,32 @@ type_of_loader: .byte 0 ! = 0, old one (LILO, Loadlin,
! T=3 for SYSLX
! T=4 for ETHERBOOT
! V = version
loadflags: .byte 0 ! unused bits =0 (reserved for future development)
loadflags: ! flags, unused bits must be zero (RFU)
LOADED_HIGH = 1 ! bit within loadflags,
! if set, then the kernel is loaded high
CAN_USE_HEAP = 0x80 ! if set, the loader also has set heap_end_ptr
! to tell how much space behind setup.S
| can be used for heap purposes.
! Only the loader knows what is free!
#ifndef __BIG_KERNEL__
.byte 0x00
#else
.byte LOADED_HIGH
#endif
setup_move_size: .word 0x8000 ! size to move, when we (setup) are not
! loaded at 0x90000. We will move ourselves
! to 0x90000 then just before jumping into
! the kernel. However, only the loader
! know how much of data behind us also needs
! to be loaded.
code32_start: .long 0x1000 ! here loaders can put a different
code32_start: ! here loaders can put a different
! start address for 32-bit code.
! 0x1000 = default for zImage
! 0x100000 = default for big kernel
#ifndef __BIG_KERNEL__
.long 0x1000 ! 0x1000 = default for zImage
#else
.long 0x100000 ! 0x100000 = default for big kernel
#endif
ramdisk_image: .long 0 ! address of loaded ramdisk image
! Here the loader (or kernel generator) puts
! the 32-bit address were it loaded the image.
......
/*
* linux/tools/build.c
* arch/i386/boot/tools/build.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
* Copyright (C) 1997 Martin Mares
*/
/*
......@@ -20,103 +21,84 @@
* Changes by tytso to allow root device specification
* High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
* Cross compiling fixes by Gertjan van Wingerde, July 1996
* Rewritten by Martin Mares, April 1997
*/
#include <stdio.h> /* fprintf */
#include <stdio.h>
#include <string.h>
#include <stdlib.h> /* contains exit */
#include <sys/types.h> /* unistd.h needs this */
#include <stdlib.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <unistd.h> /* contains read/write */
#include <unistd.h>
#include <fcntl.h>
#include <linux/a.out.h>
#include <linux/config.h>
#include <errno.h>
#include <asm/boot.h>
#define MINIX_HEADER 32
#define N_MAGIC_OFFSET 1024
#ifndef __BFD__
static int GCC_HEADER = sizeof(struct exec);
#endif
#ifdef __BIG_KERNEL__
#define SYS_SIZE 0xffff
#else
#define SYS_SIZE DEF_SYSSIZE
#endif
typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned long u32;
#define DEFAULT_MAJOR_ROOT 0
#define DEFAULT_MINOR_ROOT 0
/* max nr of sectors of setup: don't change unless you also change
* bootsect etc */
/* Minimal number of setup sectors (see also bootsect.S) */
#define SETUP_SECTS 4
#define STRINGIFY(x) #x
typedef union {
int i;
long l;
short s[2];
char b[4];
} conv;
byte buf[1024];
int fd;
int is_big_kernel;
long intel_long(long l)
void die(const char * str, ...)
{
conv t;
t.b[0] = l & 0xff; l >>= 8;
t.b[1] = l & 0xff; l >>= 8;
t.b[2] = l & 0xff; l >>= 8;
t.b[3] = l & 0xff; l >>= 8;
return t.l;
}
int intel_int(int i)
{
conv t;
t.b[0] = i & 0xff; i >>= 8;
t.b[1] = i & 0xff; i >>= 8;
t.b[2] = i & 0xff; i >>= 8;
t.b[3] = i & 0xff; i >>= 8;
return t.i;
va_list args;
va_start(args, str);
vfprintf(stderr, str, args);
fputc('\n', stderr);
exit(1);
}
short intel_short(short l)
{
conv t;
/* Reading of ld86 output (Minix format) */
t.b[0] = l & 0xff; l >>= 8;
t.b[1] = l & 0xff; l >>= 8;
return t.s[0];
}
#define MINIX_HEADER_LEN 32
void die(const char * str)
int minix_open(const char *name)
{
fprintf(stderr,"%s\n",str);
exit(1);
static byte hdr[] = { 0x01, 0x03, 0x10, 0x04, 0x20, 0x00, 0x00, 0x00 };
static u32 *lb = (u32 *) buf;
if ((fd = open(name, O_RDONLY, 0)) < 0)
die("Unable to open `%s': %m", name);
if (read(fd, buf, MINIX_HEADER_LEN) != MINIX_HEADER_LEN)
die("%s: Unable to read header", name);
if (memcmp(buf, hdr, sizeof(hdr)) || lb[5])
die("%s: Non-Minix header", name);
if (lb[3])
die("%s: Illegal data segment");
if (lb[4])
die("%s: Illegal bss segment");
if (lb[7])
die("%s: Illegal symbol table");
}
void usage(void)
{
die("Usage: build bootsect setup system [rootdev] [> image]");
die("Usage: build [-b] bootsect setup system [rootdev] [> image]");
}
int main(int argc, char ** argv)
{
int i,c,id,sz,tmp_int;
unsigned long sys_size, tmp_long;
char buf[1024];
#ifndef __BFD__
struct exec *ex = (struct exec *)buf;
#endif
char major_root, minor_root;
unsigned int i, c, sz, setup_sectors;
u32 sys_size;
byte major_root, minor_root;
struct stat sb;
unsigned char setup_sectors;
if (argc > 2 && !strcmp(argv[1], "-b"))
{
is_big_kernel = 1;
argc--, argv++;
}
if ((argc < 4) || (argc > 5))
usage();
if (argc > 4) {
......@@ -143,147 +125,79 @@ int main(int argc, char ** argv)
minor_root = DEFAULT_MINOR_ROOT;
}
fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root);
for (i=0;i<sizeof buf; i++) buf[i]=0;
if ((id=open(argv[1],O_RDONLY,0))<0)
die("Unable to open 'boot'");
if (read(id,buf,MINIX_HEADER) != MINIX_HEADER)
die("Unable to read header of 'boot'");
if (((long *) buf)[0]!=intel_long(0x04100301))
die("Non-Minix header of 'boot'");
if (((long *) buf)[1]!=intel_long(MINIX_HEADER))
die("Non-Minix header of 'boot'");
if (((long *) buf)[3] != 0)
die("Illegal data segment in 'boot'");
if (((long *) buf)[4] != 0)
die("Illegal bss in 'boot'");
if (((long *) buf)[5] != 0)
die("Non-Minix header of 'boot'");
if (((long *) buf)[7] != 0)
die("Illegal symbol table in 'boot'");
i=read(id,buf,sizeof buf);
minix_open(argv[1]); /* Copy the boot sector */
i = read(fd, buf, sizeof(buf));
fprintf(stderr,"Boot sector %d bytes.\n",i);
if (i != 512)
die("Boot block must be exactly 512 bytes");
if ((*(unsigned short *)(buf+510)) != (unsigned short)intel_short(0xAA55))
if (buf[510] != 0x55 || buf[511] != 0xaa)
die("Boot block hasn't got boot flag (0xAA55)");
buf[508] = (char) minor_root;
buf[509] = (char) major_root;
i=write(1,buf,512);
if (i!=512)
buf[508] = minor_root;
buf[509] = major_root;
if (write(1, buf, 512) != 512)
die("Write call failed");
close (id);
if ((id=open(argv[2],O_RDONLY,0))<0)
die("Unable to open 'setup'");
if (read(id,buf,MINIX_HEADER) != MINIX_HEADER)
die("Unable to read header of 'setup'");
if (((long *) buf)[0]!=intel_long(0x04100301))
die("Non-Minix header of 'setup'");
if (((long *) buf)[1]!=intel_long(MINIX_HEADER))
die("Non-Minix header of 'setup'");
if (((long *) buf)[3] != 0)
die("Illegal data segment in 'setup'");
if (((long *) buf)[4] != 0)
die("Illegal bss in 'setup'");
if (((long *) buf)[5] != 0)
die("Non-Minix header of 'setup'");
if (((long *) buf)[7] != 0)
die("Illegal symbol table in 'setup'");
for (i=0 ; (c=read(id,buf,sizeof buf))>0 ; i+=c )
#ifdef __BIG_KERNEL__
{
if (!i) {
/* Working with memcpy because of alignment constraints
on Sparc - Gertjan */
memcpy(&tmp_long, &buf[2], sizeof(long));
if (tmp_long != intel_long(0x53726448) )
die("Wrong magic in loader header of 'setup'");
memcpy(&tmp_int, &buf[6], sizeof(int));
if (tmp_int < intel_int(0x200))
die("Wrong version of loader header of 'setup'");
buf[0x11] = 1; /* LOADED_HIGH */
tmp_long = intel_long(0x100000);
memcpy(&buf[0x14], &tmp_long, sizeof(long)); /* code32_start */
}
#endif
if (write(1,buf,c)!=c)
close (fd);
minix_open(argv[2]); /* Copy the setup code */
for (i=0 ; (c=read(fd, buf, sizeof(buf)))>0 ; i+=c )
if (write(1, buf, c) != c)
die("Write call failed");
#ifdef __BIG_KERNEL__
}
#endif
if (c != 0)
die("read-error on 'setup'");
close (id);
setup_sectors = (unsigned char)((i + 511) / 512);
/* for compatibility with LILO */
die("read-error on `setup'");
close (fd);
setup_sectors = (i + 511) / 512; /* Pad unused space with zeros */
/* for compatibility with ancient versions of LILO */
if (setup_sectors < SETUP_SECTS)
setup_sectors = SETUP_SECTS;
fprintf(stderr,"Setup is %d bytes.\n",i);
for (c=0 ; c<sizeof(buf) ; c++)
buf[c] = '\0';
fprintf(stderr, "Setup is %d bytes.\n", i);
memset(buf, sizeof(buf), 0);
while (i < setup_sectors * 512) {
c = setup_sectors * 512 - i;
if (c > sizeof(buf))
c = sizeof(buf);
if (write(1,buf,c) != c)
if (write(1, buf, c) != c)
die("Write call failed");
i += c;
}
if ((id=open(argv[3],O_RDONLY,0))<0)
die("Unable to open 'system'");
#ifndef __BFD__
if (read(id,buf,GCC_HEADER) != GCC_HEADER)
die("Unable to read header of 'system'");
if (N_MAGIC(*ex) == ZMAGIC) {
GCC_HEADER = N_MAGIC_OFFSET;
lseek(id, GCC_HEADER, SEEK_SET);
} else if (N_MAGIC(*ex) != QMAGIC)
die("Non-GCC header of 'system'");
fprintf(stderr,"System is %d kB (%d kB code, %d kB data and %d kB bss)\n",
(ex->a_text+ex->a_data+ex->a_bss)/1024,
ex->a_text /1024,
ex->a_data /1024,
ex->a_bss /1024);
sz = N_SYMOFF(*ex) - GCC_HEADER + 4;
#else
if (fstat (id, &sb)) {
perror ("fstat");
die ("Unable to stat 'system'");
}
if ((fd = open(argv[3], O_RDONLY, 0)) < 0) /* Copy the image itself */
die("Unable to open `%s': %m", argv[3]);
if (fstat (fd, &sb))
die("Unable to stat `%s': %m", argv[3]);
sz = sb.st_size;
fprintf (stderr, "System is %d kB\n", sz/1024);
#endif
sys_size = (sz + 15) / 16;
if (sys_size > SYS_SIZE)
if (sys_size > (is_big_kernel ? 0xffff : DEF_SYSSIZE))
die("System is too big");
while (sz > 0) {
int l, n;
l = sz;
if (l > sizeof(buf))
l = sizeof(buf);
if ((n=read(id, buf, l)) != l) {
if (n == -1)
perror(argv[1]);
l = (sz > sizeof(buf)) ? sizeof(buf) : sz;
if ((n=read(fd, buf, l)) != l) {
if (n < 0)
die("Error reading %s: %m", argv[3]);
else
fprintf(stderr, "Unexpected EOF\n");
die("Can't read 'system'");
die("%s: Unexpected EOF", argv[3]);
}
if (write(1, buf, l) != l)
die("Write failed");
sz -= l;
}
close(id);
if (lseek(1, 497, 0) == 497) {
if (write(1, &setup_sectors, 1) != 1)
die("Write of setup sectors failed");
}
if (lseek(1,500,0) == 500) {
buf[0] = (sys_size & 0xff);
buf[1] = ((sys_size >> 8) & 0xff);
if (write(1, buf, 2) != 2)
die("Write failed");
}
return(0);
close(fd);
if (lseek(1, 497, SEEK_SET) != 497) /* Write sizes to the bootsector */
die("Output: seek failed");
buf[0] = setup_sectors;
if (write(1, buf, 1) != 1)
die("Write of setup sector count failed");
if (lseek(1, 500, SEEK_SET) != 500)
die("Output: seek failed");
buf[0] = (sys_size & 0xff);
buf[1] = ((sys_size >> 8) & 0xff);
if (write(1, buf, 2) != 2)
die("Write of image length failed");
return 0; /* Everything is OK */
}
......@@ -59,6 +59,7 @@
#include <linux/kernel.h>
#include <linux/bios32.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <asm/page.h>
#include <asm/segment.h>
......@@ -188,7 +189,7 @@ static struct {
} pci_indirect = { 0, KERNEL_CS };
extern unsigned long check_pcibios(unsigned long memory_start, unsigned long memory_end)
__initfunc(static unsigned long check_pcibios(unsigned long memory_start, unsigned long memory_end))
{
unsigned long signature;
unsigned char present_status;
......@@ -710,7 +711,7 @@ static struct pci_access pci_direct_conf2 = {
};
static struct pci_access *check_direct_pci(void)
__initfunc(static struct pci_access *check_direct_pci(void))
{
unsigned int tmp;
unsigned long flags;
......@@ -863,14 +864,14 @@ const char *pcibios_strerror (int error)
}
unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end)
__initfunc(unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end))
{
return mem_start;
}
#endif
unsigned long pcibios_init(unsigned long memory_start, unsigned long memory_end)
__initfunc(unsigned long pcibios_init(unsigned long memory_start, unsigned long memory_end))
{
#ifdef CONFIG_PCI
union bios32 *check;
......
......@@ -89,7 +89,7 @@ startup_32:
* Clear BSS first so that there are no surprises...
*/
xorl %eax,%eax
movl $ SYMBOL_NAME(_edata),%edi
movl $ SYMBOL_NAME(__bss_start),%edi
movl $ SYMBOL_NAME(_end),%ecx
subl %edi,%ecx
cld
......
......@@ -27,6 +27,7 @@
#include <linux/random.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <asm/system.h>
#include <asm/io.h>
......@@ -35,6 +36,8 @@
#include <asm/smp.h>
#include <asm/pgtable.h>
#include "irq.h"
#ifdef __SMP_PROF__
extern volatile unsigned long smp_local_timer_ticks[1+NR_CPUS];
#endif
......@@ -146,10 +149,8 @@ BUILD_IRQ(SECOND,15,0x80)
BUILD_SMP_INTERRUPT(reschedule_interrupt)
BUILD_SMP_INTERRUPT(invalidate_interrupt)
BUILD_SMP_INTERRUPT(stop_cpu_interrupt)
#ifdef __SMP_PROF__
BUILD_SMP_TIMER_INTERRUPT(apic_timer_interrupt)
#endif
#endif
/*
* Pointers to the low-level handlers: first the general ones, then the
......@@ -524,40 +525,6 @@ void __global_restore_flags(unsigned long flags)
}
}
#undef INIT_STUCK
#define INIT_STUCK 200000000
#undef STUCK
#define STUCK \
if (!--stuck) {printk("irq_enter stuck (irq=%d, cpu=%d, global=%d)\n",irq,cpu,global_irq_holder); stuck = INIT_STUCK;}
inline void irq_enter(int cpu, int irq)
{
int stuck = INIT_STUCK;
hardirq_enter(cpu);
while (test_bit(0,&global_irq_lock)) {
if ((unsigned char) cpu == global_irq_holder) {
printk("BAD! Local interrupts enabled, global disabled\n");
break;
}
STUCK;
/* nothing */;
}
}
inline void irq_exit(int cpu, int irq)
{
__cli();
hardirq_exit(cpu);
release_irqlock(cpu);
}
#else
#define irq_enter(cpu, irq) (++local_irq_count[cpu])
#define irq_exit(cpu, irq) (--local_irq_count[cpu])
#endif
/*
......@@ -754,7 +721,7 @@ int probe_irq_off (unsigned long irqs)
return i;
}
void init_IRQ(void)
__initfunc(void init_IRQ(void))
{
int i;
static unsigned char smptrap=0;
......@@ -777,19 +744,25 @@ void init_IRQ(void)
*/
#ifdef __SMP__
/* IRQ '16' - IPI for rescheduling */
/*
* NOTE! The local APIC isn't very good at handling
* multiple interrupts at the same interrupt level.
* As the interrupt level is determined by taking the
* vector number and shifting that right by 4, we
* want to spread these out a bit so that they don't
* all fall in the same interrupt level
*/
/* IRQ '16' (trap 0x30) - IPI for rescheduling */
set_intr_gate(0x20+i, reschedule_interrupt);
/* IRQ '17' - IPI for invalidation */
/* IRQ '17' (trap 0x31) - IPI for invalidation */
set_intr_gate(0x21+i, invalidate_interrupt);
/* IRQ '18' - IPI for CPU halt */
set_intr_gate(0x22+i, stop_cpu_interrupt);
/* IRQ '18' (trap 0x40) - IPI for CPU halt */
set_intr_gate(0x30+i, stop_cpu_interrupt);
#ifdef __SMP_PROF__
/* IRQ '19' - self generated IPI for local APIC timer */
set_intr_gate(0x23+i, apic_timer_interrupt);
#endif
/* IRQ '19' (trap 0x41) - self generated IPI for local APIC timer */
set_intr_gate(0x31+i, apic_timer_interrupt);
#endif
request_region(0x20,0x20,"pic1");
request_region(0xa0,0x20,"pic2");
......
#ifndef __irq_h
#define __irq_h
/*
* Various low-level irq details needed by irq.c and smp.c
*
* Interrupt entry/exit code at both C and assembly level
*/
#ifdef __SMP__
#undef INIT_STUCK
#define INIT_STUCK 200000000
#undef STUCK
#define STUCK \
if (!--stuck) {printk("irq_enter stuck (irq=%d, cpu=%d, global=%d)\n",irq,cpu,global_irq_holder); stuck = INIT_STUCK;}
static inline void irq_enter(int cpu, int irq)
{
int stuck = INIT_STUCK;
hardirq_enter(cpu);
while (test_bit(0,&global_irq_lock)) {
if ((unsigned char) cpu == global_irq_holder) {
printk("BAD! Local interrupts enabled, global disabled\n");
break;
}
STUCK;
/* nothing */;
}
}
static inline void irq_exit(int cpu, int irq)
{
__cli();
hardirq_exit(cpu);
release_irqlock(cpu);
}
#else
#define irq_enter(cpu, irq) (++local_irq_count[cpu])
#define irq_exit(cpu, irq) (--local_irq_count[cpu])
#endif
#define __STR(x) #x
#define STR(x) __STR(x)
#define SAVE_ALL \
"cld\n\t" \
"push %es\n\t" \
"push %ds\n\t" \
"pushl %eax\n\t" \
"pushl %ebp\n\t" \
"pushl %edi\n\t" \
"pushl %esi\n\t" \
"pushl %edx\n\t" \
"pushl %ecx\n\t" \
"pushl %ebx\n\t" \
"movl $" STR(KERNEL_DS) ",%edx\n\t" \
"mov %dx,%ds\n\t" \
"mov %dx,%es\n\t"
/*
* SAVE_MOST/RESTORE_MOST is used for the faster version of IRQ handlers,
* installed by using the SA_INTERRUPT flag. These kinds of IRQ's don't
* call the routines that do signal handling etc on return, and can have
* more relaxed register-saving etc. They are also atomic, and are thus
* suited for small, fast interrupts like the serial lines or the harddisk
* drivers, which don't actually need signal handling etc.
*
* Also note that we actually save only those registers that are used in
* C subroutines (%eax, %edx and %ecx), so if you do something weird,
* you're on your own. The only segments that are saved (not counting the
* automatic stack and code segment handling) are %ds and %es, and they
* point to kernel space. No messing around with %fs here.
*/
#define SAVE_MOST \
"cld\n\t" \
"push %es\n\t" \
"push %ds\n\t" \
"pushl %eax\n\t" \
"pushl %edx\n\t" \
"pushl %ecx\n\t" \
"movl $" STR(KERNEL_DS) ",%edx\n\t" \
"mov %dx,%ds\n\t" \
"mov %dx,%es\n\t"
#define RESTORE_MOST \
"popl %ecx\n\t" \
"popl %edx\n\t" \
"popl %eax\n\t" \
"pop %ds\n\t" \
"pop %es\n\t" \
"iret"
/*
* Some fast irq handlers might want to access saved registers (mostly
* cs or flags)
*/
struct fast_irq_regs {
long ecx;
long edx;
long eax;
int xds;
int xes;
long eip;
int xcs;
long eflags;
long esp;
int xss;
};
/*
* The "inb" instructions are not needed, but seem to change the timings
* a bit - without them it seems that the harddisk driver won't work on
* all hardware. Arghh.
*/
#define ACK_FIRST(mask,nr) \
"inb $0x21,%al\n\t" \
"jmp 1f\n" \
"1:\tjmp 1f\n" \
"1:\torb $" #mask ","SYMBOL_NAME_STR(cache_21)"\n\t" \
"movb "SYMBOL_NAME_STR(cache_21)",%al\n\t" \
"outb %al,$0x21\n\t" \
"jmp 1f\n" \
"1:\tjmp 1f\n" \
"1:\tmovb $0x20,%al\n\t" \
"outb %al,$0x20\n\t"
#define ACK_SECOND(mask,nr) \
"inb $0xA1,%al\n\t" \
"jmp 1f\n" \
"1:\tjmp 1f\n" \
"1:\torb $" #mask ","SYMBOL_NAME_STR(cache_A1)"\n\t" \
"movb "SYMBOL_NAME_STR(cache_A1)",%al\n\t" \
"outb %al,$0xA1\n\t" \
"jmp 1f\n" \
"1:\tjmp 1f\n" \
"1:\tmovb $0x20,%al\n\t" \
"outb %al,$0xA0\n\t" \
"jmp 1f\n" \
"1:\tjmp 1f\n" \
"1:\toutb %al,$0x20\n\t"
#define UNBLK_FIRST(mask) \
"inb $0x21,%al\n\t" \
"jmp 1f\n" \
"1:\tjmp 1f\n" \
"1:\tandb $~(" #mask "),"SYMBOL_NAME_STR(cache_21)"\n\t" \
"movb "SYMBOL_NAME_STR(cache_21)",%al\n\t" \
"outb %al,$0x21\n\t"
#define UNBLK_SECOND(mask) \
"inb $0xA1,%al\n\t" \
"jmp 1f\n" \
"1:\tjmp 1f\n" \
"1:\tandb $~(" #mask "),"SYMBOL_NAME_STR(cache_A1)"\n\t" \
"movb "SYMBOL_NAME_STR(cache_A1)",%al\n\t" \
"outb %al,$0xA1\n\t"
#define IRQ_NAME2(nr) nr##_interrupt(void)
#define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
#define FAST_IRQ_NAME(nr) IRQ_NAME2(fast_IRQ##nr)
#define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr)
#ifdef __SMP__
#define GET_CURRENT \
"movl "SYMBOL_NAME_STR(apic_reg)", %ebx\n\t" \
"movl 32(%ebx), %ebx\n\t" \
"shrl $22,%ebx\n\t" \
"andl $0x3C,%ebx\n\t" \
"movl " SYMBOL_NAME_STR(current_set) "(,%ebx),%ebx\n\t"
#else
#define GET_CURRENT \
"movl " SYMBOL_NAME_STR(current_set) ",%ebx\n\t"
#endif
#ifdef __SMP__
/*
* SMP has a few special interrupts for IPI messages
*/
#define BUILD_SMP_INTERRUPT(x) \
asmlinkage void x(void); \
__asm__( \
"\n"__ALIGN_STR"\n" \
SYMBOL_NAME_STR(x) ":\n\t" \
"pushl $-1\n\t" \
SAVE_ALL \
"call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
"jmp ret_from_intr\n");
#define BUILD_SMP_TIMER_INTERRUPT(x) \
asmlinkage void x(struct pt_regs * regs); \
__asm__( \
"\n"__ALIGN_STR"\n" \
SYMBOL_NAME_STR(x) ":\n\t" \
"pushl $-1\n\t" \
SAVE_ALL \
"movl %esp,%eax\n\t" \
"pushl %eax\n\t" \
"call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
"addl $4,%esp\n\t" \
"jmp ret_from_intr\n");
#endif /* __SMP__ */
#define BUILD_IRQ(chip,nr,mask) \
asmlinkage void IRQ_NAME(nr); \
asmlinkage void FAST_IRQ_NAME(nr); \
asmlinkage void BAD_IRQ_NAME(nr); \
__asm__( \
"\n"__ALIGN_STR"\n" \
SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
"pushl $-"#nr"-2\n\t" \
SAVE_ALL \
ACK_##chip(mask,(nr&7)) \
"movl %esp,%eax\n\t" \
"pushl %eax\n\t" \
"pushl $" #nr "\n\t" \
"call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \
"addl $8,%esp\n\t" \
UNBLK_##chip(mask) \
"jmp ret_from_intr\n" \
"\n"__ALIGN_STR"\n" \
SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \
SAVE_MOST \
ACK_##chip(mask,(nr&7)) \
"pushl $" #nr "\n\t" \
"call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \
"addl $4,%esp\n\t" \
UNBLK_##chip(mask) \
RESTORE_MOST \
"\n"__ALIGN_STR"\n" \
SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \
SAVE_MOST \
ACK_##chip(mask,(nr&7)) \
RESTORE_MOST);
#define BUILD_TIMER_IRQ(chip,nr,mask) \
asmlinkage void IRQ_NAME(nr); \
asmlinkage void FAST_IRQ_NAME(nr); \
asmlinkage void BAD_IRQ_NAME(nr); \
__asm__( \
"\n"__ALIGN_STR"\n" \
SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \
SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \
SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
"pushl $-"#nr"-2\n\t" \
SAVE_ALL \
ACK_##chip(mask,(nr&7)) \
"movl %esp,%eax\n\t" \
"pushl %eax\n\t" \
"pushl $" #nr "\n\t" \
"call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \
"addl $8,%esp\n\t" \
UNBLK_##chip(mask) \
"jmp ret_from_intr\n");
#endif
......@@ -23,6 +23,7 @@
#include <linux/pagemap.h>
#include <linux/ioport.h>
#include <asm/uaccess.h>
#include <linux/init.h>
/* This structure holds MCA information. Each (plug-in) adapter has
* eight POS registers. Then the machine may have integrated video and
......@@ -78,7 +79,7 @@ static struct inode_operations proc_mca_inode_operations = {
/*--------------------------------------------------------------------*/
long mca_init(long memory_start, long memory_end)
__initfunc(long mca_init(long memory_start, long memory_end))
{
unsigned int i, j;
int foundscsi = 0;
......@@ -417,7 +418,7 @@ int get_mca_info(char *buf)
/*--------------------------------------------------------------------*/
long mca_do_proc_init( long memory_start, long memory_end )
__initfunc(long mca_do_proc_init( long memory_start, long memory_end ))
{
int i = 0;
struct proc_dir_entry* node = 0;
......
......@@ -22,6 +22,7 @@
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/config.h>
#include <linux/init.h>
#ifdef CONFIG_APM
#include <linux/apm_bios.h>
#endif
......@@ -115,8 +116,8 @@ extern char empty_zero_page[PAGE_SIZE];
static char command_line[COMMAND_LINE_SIZE] = { 0, };
char saved_command_line[COMMAND_LINE_SIZE];
void setup_arch(char **cmdline_p,
unsigned long * memory_start_p, unsigned long * memory_end_p)
__initfunc(void setup_arch(char **cmdline_p,
unsigned long * memory_start_p, unsigned long * memory_end_p))
{
unsigned long memory_start, memory_end;
char c = ' ', *to = command_line, *from = COMMAND_LINE;
......
......@@ -39,12 +39,15 @@
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <asm/pgtable.h>
#include <asm/bitops.h>
#include <asm/pgtable.h>
#include <asm/smp.h>
#include <asm/io.h>
#include "irq.h"
extern unsigned long start_kernel, _etext;
void setup_APIC_clock (void);
......@@ -170,7 +173,7 @@ volatile int smp_process_available=0;
* SMP mode to <NUM>.
*/
void smp_setup(char *str, int *ints)
__initfunc(void smp_setup(char *str, int *ints))
{
if (ints && ints[0] > 0)
max_cpus = ints[1];
......@@ -232,7 +235,7 @@ static char *mpc_family(int family,int model)
* Read the MPC
*/
static int smp_read_mpc(struct mp_config_table *mpc)
__initfunc(static int smp_read_mpc(struct mp_config_table *mpc))
{
char str[16];
int count=sizeof(*mpc);
......@@ -377,7 +380,7 @@ static int smp_read_mpc(struct mp_config_table *mpc)
* Scan the memory blocks for an SMP configuration block.
*/
int smp_scan_config(unsigned long base, unsigned long length)
__initfunc(int smp_scan_config(unsigned long base, unsigned long length))
{
unsigned long *bp=phys_to_virt(base);
struct intel_mp_floating *mpf;
......@@ -535,7 +538,7 @@ extern unsigned char trampoline_end [];
* has made sure it's suitably aligned.
*/
static void install_trampoline(unsigned char *mp)
__initfunc(static void install_trampoline(unsigned char *mp))
{
memcpy(mp, trampoline_data, trampoline_end - trampoline_data);
}
......@@ -547,7 +550,7 @@ static void install_trampoline(unsigned char *mp)
* other things).
*/
unsigned long smp_alloc_memory(unsigned long mem_base)
__initfunc(unsigned long smp_alloc_memory(unsigned long mem_base))
{
int size=(num_processors-1)*PAGE_SIZE; /* Number of stacks needed */
......@@ -568,7 +571,7 @@ unsigned long smp_alloc_memory(unsigned long mem_base)
* Hand out stacks one at a time.
*/
static void *get_kernel_stack(void)
__initfunc(static void *get_kernel_stack(void))
{
void *stack=kstack_base;
if(kstack_base>=kstack_end)
......@@ -583,7 +586,7 @@ static void *get_kernel_stack(void)
* a given CPU
*/
void smp_store_cpu_info(int id)
__initfunc(void smp_store_cpu_info(int id))
{
struct cpuinfo_x86 *c=&cpu_data[id];
c->hard_math=hard_math; /* Always assumed same currently */
......@@ -614,7 +617,7 @@ void smp_store_cpu_info(int id)
* we use to track CPU's as they power up.
*/
void smp_commence(void)
__initfunc(void smp_commence(void))
{
/*
* Lets the callin's below out of their loop.
......@@ -623,7 +626,7 @@ void smp_commence(void)
smp_commenced=1;
}
void smp_callin(void)
__initfunc(void smp_callin(void))
{
extern void calibrate_delay(void);
int cpuid=GET_APIC_ID(apic_read(APIC_ID));
......@@ -687,7 +690,7 @@ void smp_callin(void)
* Cycle through the processors sending APIC IPI's to boot each.
*/
void smp_boot_cpus(void)
__initfunc(void smp_boot_cpus(void))
{
int i;
int cpucount=0;
......@@ -1093,6 +1096,7 @@ void smp_boot_cpus(void)
void smp_message_pass(int target, int msg, unsigned long data, int wait)
{
unsigned long flags;
unsigned long cfg;
unsigned long target_map;
int p=smp_processor_id();
......@@ -1121,11 +1125,12 @@ void smp_message_pass(int target, int msg, unsigned long data, int wait)
break;
case MSG_INVALIDATE_TLB:
/* make this a NMI some day */
irq = 0x31;
break;
case MSG_STOP_CPU:
irq = 0x32;
irq = 0x40;
break;
default:
......@@ -1168,15 +1173,15 @@ void smp_message_pass(int target, int msg, unsigned long data, int wait)
* Just pray... there is nothing more we can do
*/
if(ct==1000) {
printk("CPU #%d: previous IPI still not cleared after 10mS", p);
ack_APIC_irq ();
}
if(ct==1000)
printk("CPU #%d: previous IPI still not cleared after 10mS\n", p);
/*
* Program the APIC to deliver the IPI
*/
__save_flags(flags);
__cli();
cfg=apic_read(APIC_ICR2);
cfg&=0x00FFFFFF;
apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(target)); /* Target chip */
......@@ -1210,7 +1215,8 @@ void smp_message_pass(int target, int msg, unsigned long data, int wait)
* Send the IPI. The write to APIC_ICR fires this off.
*/
apic_write(APIC_ICR, cfg);
apic_write(APIC_ICR, cfg);
__restore_flags(flags);
/*
* Spin waiting for completion
......@@ -1300,36 +1306,6 @@ void smp_flush_tlb(void)
/* printk("SMID\n");*/
}
/*
* Reschedule call back
*/
asmlinkage void smp_reschedule_interrupt(void)
{
need_resched=1;
ack_APIC_irq();
}
/*
* Invalidate call-back
*/
asmlinkage void smp_invalidate_interrupt(void)
{
if (clear_bit(smp_processor_id(), &smp_invalidate_needed))
local_flush_tlb();
ack_APIC_irq ();
}
/*
* CPU halt call-back
*/
asmlinkage void smp_stop_cpu_interrupt(void)
{
if (cpu_data[smp_processor_id()].hlt_works_ok)
for(;;) __asm__("hlt");
for (;;) ;
}
/*
* Platform specific profiling function.
* it builds a 'prof_shift' resolution EIP distribution histogram
......@@ -1337,7 +1313,7 @@ asmlinkage void smp_stop_cpu_interrupt(void)
* it's SMP safe.
*/
inline void x86_do_profile (unsigned long eip)
static inline void x86_do_profile (unsigned long eip)
{
if (prof_buffer && current->pid) {
extern int _stext;
......@@ -1394,9 +1370,6 @@ static inline void smp_local_timer_interrupt(struct pt_regs * regs)
*
* kernel statistics counters are updated via atomic
* operations.
*
* update_one_process() might send signals, thus
* we have to get the irq lock for that one.
*/
if (user_mode(regs))
......@@ -1405,12 +1378,7 @@ static inline void smp_local_timer_interrupt(struct pt_regs * regs)
system=1;
if (p->pid) {
unsigned long flags;
save_flags(flags);
cli();
update_one_process(current, 1, user, system);
restore_flags(flags);
update_one_process(p, 1, user, system);
p->counter -= 1;
if (p->counter < 0) {
......@@ -1464,9 +1432,63 @@ static inline void smp_local_timer_interrupt(struct pt_regs * regs)
*/
void smp_apic_timer_interrupt(struct pt_regs * regs)
{
int cpu = smp_processor_id();
/*
* NOTE! We'd better ACK the irq immediately,
* because timer handling can be slow, and we
* want to be able to accept NMI tlb invalidates
* during this time.
*/
ack_APIC_irq ();
/*
* After doing the above, we need to make like
* a normal interrupt - otherwise timer interrupts
* ignore the global interrupt lock, which is the
* WrongThing (tm) to do.
*/
irq_enter(cpu, 0);
smp_local_timer_interrupt(regs);
irq_exit(cpu, 0);
}
/*
* Reschedule call back
*/
asmlinkage void smp_reschedule_interrupt(void)
{
int cpu = smp_processor_id();
ack_APIC_irq();
/*
* This looks silly, but we actually do need to wait
* for the global interrupt lock.
*/
irq_enter(cpu, 0);
need_resched=1;
irq_exit(cpu, 0);
}
/*
* Invalidate call-back
*/
asmlinkage void smp_invalidate_interrupt(void)
{
if (clear_bit(smp_processor_id(), &smp_invalidate_needed))
local_flush_tlb();
ack_APIC_irq ();
}
/*
* CPU halt call-back
*/
asmlinkage void smp_stop_cpu_interrupt(void)
{
if (cpu_data[smp_processor_id()].hlt_works_ok)
for(;;) __asm__("hlt");
for (;;) ;
}
/*
......@@ -1487,7 +1509,7 @@ void smp_apic_timer_interrupt(struct pt_regs * regs)
* but we do not accept timer interrupts yet. We only allow the BP
* to calibrate.
*/
unsigned int get_8254_timer_count (void)
static unsigned int get_8254_timer_count (void)
{
unsigned int count;
......@@ -1524,11 +1546,11 @@ void setup_APIC_timer (unsigned int clocks)
* mode. With the IO APIC we can re-route the external timer
* interrupt and broadcast it as an NMI to all CPUs, so no pain.
*
* NOTE: this irq vector 19 and the gate in BUILD_SMP_TIMER_INTERRUPT
* NOTE: this trap vector (0x41) and the gate in BUILD_SMP_TIMER_INTERRUPT
* should be the same ;)
*/
tmp_value = apic_read(APIC_LVTT);
lvtt1_value = APIC_LVT_TIMER_PERIODIC | (0x20+19);
lvtt1_value = APIC_LVT_TIMER_PERIODIC | 0x41;
apic_write(APIC_LVTT , lvtt1_value);
/*
......
......@@ -22,6 +22,7 @@
#include <linux/interrupt.h>
#include <linux/time.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/io.h>
......@@ -369,7 +370,7 @@ static long last_rtc_update = 0;
* Move this to a header file - right now it shows
* up both here and in smp.c
*/
inline void x86_do_profile (unsigned long eip)
static inline void x86_do_profile (unsigned long eip)
{
if (prof_buffer && current->pid) {
extern int _stext;
......@@ -415,11 +416,13 @@ static inline void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
last_rtc_update = xtime.tv_sec;
else
last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
#if 0
/* As we return to user mode fire off the other CPU schedulers.. this is
basically because we don't yet share IRQ's around. This message is
rigged to be safe on the 386 - basically it's a hack, so don't look
closely for now.. */
smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0);
#endif
#ifdef CONFIG_MCA
if( MCA_bus ) {
......@@ -528,7 +531,7 @@ unsigned long get_cmos_time(void)
static struct irqaction irq0 = { timer_interrupt, 0, 0, "timer", NULL, NULL};
void time_init(void)
__initfunc(void time_init(void))
{
xtime.tv_sec = get_cmos_time();
xtime.tv_usec = 0;
......
......@@ -22,6 +22,7 @@
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <asm/system.h>
#include <asm/uaccess.h>
......@@ -375,7 +376,7 @@ asmlinkage void math_emulate(long arg)
#endif /* CONFIG_MATH_EMULATION */
void trap_init(void)
__initfunc(void trap_init(void))
{
int i;
struct desc_struct * p;
......
......@@ -17,6 +17,7 @@
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/smp.h>
#include <linux/init.h>
#ifdef CONFIG_BLK_DEV_INITRD
#include <linux/blk.h>
#endif
......@@ -96,6 +97,11 @@ void show_mem(void)
extern unsigned long free_area_init(unsigned long, unsigned long);
/* References to section boundaries */
extern char _text, _etext, _edata, __bss_start, _end;
extern char __init_begin, __init_end;
/*
* paging_init() sets up the page tables - note that the first 4MB are
* already mapped by head.S.
......@@ -103,7 +109,7 @@ extern unsigned long free_area_init(unsigned long, unsigned long);
* This routines also unmaps the page at virtual kernel address 0, so
* that we can trap those pesky NULL-reference errors in the kernel.
*/
unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
__initfunc(unsigned long paging_init(unsigned long start_mem, unsigned long end_mem))
{
pgd_t * pg_dir;
pte_t * pg_table;
......@@ -202,14 +208,14 @@ unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
return free_area_init(start_mem, end_mem);
}
void mem_init(unsigned long start_mem, unsigned long end_mem)
__initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
{
unsigned long start_low_mem = PAGE_SIZE;
int codepages = 0;
int reservedpages = 0;
int datapages = 0;
int initpages = 0;
unsigned long tmp;
extern int _etext;
end_mem &= PAGE_MASK;
high_memory = (void *) end_mem;
......@@ -251,12 +257,19 @@ void mem_init(unsigned long start_mem, unsigned long end_mem)
if (tmp >= MAX_DMA_ADDRESS)
clear_bit(PG_DMA, &mem_map[MAP_NR(tmp)].flags);
if (PageReserved(mem_map+MAP_NR(tmp))) {
if (tmp >= 0xA0000+PAGE_OFFSET && tmp < 0x100000+PAGE_OFFSET)
reservedpages++;
else if (tmp < (unsigned long) &_etext)
codepages++;
else
if (tmp >= (unsigned long) &_text && tmp < (unsigned long) &_edata) {
if (tmp < (unsigned long) &_etext)
codepages++;
else
datapages++;
} else if (tmp >= (unsigned long) &__init_begin
&& tmp < (unsigned long) &__init_end)
initpages++;
else if (tmp >= (unsigned long) &__bss_start
&& tmp < (unsigned long) start_mem)
datapages++;
else
reservedpages++;
continue;
}
atomic_set(&mem_map[MAP_NR(tmp)].count, 1);
......@@ -266,12 +279,13 @@ void mem_init(unsigned long start_mem, unsigned long end_mem)
#endif
free_page(tmp);
}
printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data)\n",
printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n",
(unsigned long) nr_free_pages << (PAGE_SHIFT-10),
max_mapnr << (PAGE_SHIFT-10),
codepages << (PAGE_SHIFT-10),
reservedpages << (PAGE_SHIFT-10),
datapages << (PAGE_SHIFT-10));
datapages << (PAGE_SHIFT-10),
initpages << (PAGE_SHIFT-10));
/* test if the WP bit is honoured in supervisor mode */
if (wp_works_ok < 0) {
unsigned char tmp_reg;
......@@ -300,7 +314,14 @@ void mem_init(unsigned long start_mem, unsigned long end_mem)
void free_initmem(void)
{
/* To be written */
unsigned long addr;
addr = (unsigned long)(&__init_begin);
for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved);
atomic_set(&mem_map[MAP_NR(addr)].count, 1);
free_page(addr);
}
}
void si_meminfo(struct sysinfo *val)
......
/* ld script to make i386 Linux kernel
* Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
*/
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
ENTRY(_start)
SECTIONS
{
. = 0xc0100000;
_text = .; /* Text and read-only data */
.text : {
*(.text)
*(.fixup)
*(.gnu.warning)
} = 0x9090
.rodata : { *(.rodata) }
.kstrtab : { *(.kstrtab) }
. = ALIGN(16); /* Exception table */
__start___ex_table = .;
__ex_table : { *(__ex_table) }
__stop___ex_table = .;
__start___ksymtab = .; /* Kernel symbol table */
__ksymtab : { *(__ksymtab) }
__stop___ksymtab = .;
_etext = .; /* End of text section */
.data : { /* Data */
*(.data)
CONSTRUCTORS
}
_edata = .; /* End of data section */
. = ALIGN(4096); /* Init code and data */
__init_begin = .;
.text.init : { *(.text.init) }
.data.init : { *(.data.init) }
. = ALIGN(4096);
__init_end = .;
__bss_start = .; /* BSS */
.bss : {
*(.bss)
}
_end = . ;
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
}
......@@ -56,6 +56,13 @@
#include <asm/system.h>
#include <asm/poll.h>
/* Adjust starting epoch if ARC console time is being used */
#ifdef CONFIG_RTC_ARC
#define ARCFUDGE 20
#else
#define ARCFUDGE 0
#endif
/*
* We sponge a minor off of the misc major. No need slurping
* up another valuable major dev number for this. If you add
......@@ -336,7 +343,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
copy_from_user(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time));
yrs = rtc_tm.tm_year + 1900;
yrs = rtc_tm.tm_year + 1900 + ARCFUDGE;
mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */
day = rtc_tm.tm_mday;
hrs = rtc_tm.tm_hour;
......@@ -725,6 +732,9 @@ void get_rtc_time(struct rtc_time *rtc_tm)
if (rtc_tm->tm_year <= 69)
rtc_tm->tm_year += 100;
/* if ARCFUDGE == 0, the optimizer should do away with this */
rtc_tm->tm_year -= ARCFUDGE;
rtc_tm->tm_mon--;
}
......
torvalds@penguin.transmeta.com
\ No newline at end of file
......@@ -491,7 +491,7 @@ struct inode * get_empty_inode(void)
inode = first_inode;
best = NULL;
badness = 1000;
for (i = nr_inodes/2; i > 0; i--,inode = inode->i_prev) {
for (i = nr_inodes/2; i > 0; i--,inode = inode->i_next) {
if (!inode->i_count) {
unsigned long i = 999;
if (!(inode->i_lock | inode->i_dirt))
......
......@@ -18,7 +18,7 @@ typedef struct { int counter; } atomic_t;
#define ATOMIC_INIT { 0 }
#define atomic_read(v) ((v)->counter)
#define atomic_set(v) (((v)->counter) = i)
#define atomic_set(v,i) ((v)->counter = (i))
/*
* Make sure gcc doesn't try to be clever and move things around
......
......@@ -136,4 +136,7 @@
#define ERESTART 127 /* Interrupted system call should be restarted */
#define ESTRPIPE 128 /* Streams pipe error */
#define ENOMEDIUM 129 /* No medium found */
#define EMEDIUMTYPE 130 /* Wrong medium type */
#endif
#ifndef _ALPHA_INIT_H
#define _ALPHA_INIT_H
/* Throwing the initialization code and data out is not supported yet... */
#define __init
#define __initdata
#define __initfunc(__arginit) __arginit
/* For assembly routines */
#define __INIT
#define __FINIT
#define __INITDATA
#endif
......@@ -24,43 +24,4 @@
extern void disable_irq(unsigned int);
extern void enable_irq(unsigned int);
#define __STR(x) #x
#define STR(x) __STR(x)
#define SAVE_ALL "xx"
/*
* SAVE_MOST/RESTORE_MOST is used for the faster version of IRQ handlers,
* installed by using the SA_INTERRUPT flag. These kinds of IRQ's don't
* call the routines that do signal handling etc on return, and can have
* more relaxed register-saving etc. They are also atomic, and are thus
* suited for small, fast interrupts like the serial lines or the harddisk
* drivers, which don't actually need signal handling etc.
*
* Also note that we actually save only those registers that are used in
* C subroutines, so if you do something weird, you're on your own.
*/
#define SAVE_MOST "yy"
#define RESTORE_MOST "zz"
#define ACK_FIRST(mask) "aa"
#define ACK_SECOND(mask) "dummy"
#define UNBLK_FIRST(mask) "dummy"
#define UNBLK_SECOND(mask) "dummy"
#define IRQ_NAME2(nr) nr##_interrupt(void)
#define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
#define FAST_IRQ_NAME(nr) IRQ_NAME2(fast_IRQ##nr)
#define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr)
#define BUILD_IRQ(chip,nr,mask) \
asmlinkage void IRQ_NAME(nr); \
asmlinkage void FAST_IRQ_NAME(nr); \
asmlinkage void BAD_IRQ_NAME(nr); \
asm code comes here
#endif
......@@ -24,18 +24,35 @@ extern void __up(struct semaphore * sem);
#define sema_init(sem, val) atomic_set(&((sem)->count), val)
/*
* These two _must_ execute atomically wrt each other.
*
* This is trivially done with load_locked/store_cond,
* which we have. Let the rest of the losers suck eggs.
*/
static inline void wake_one_more(struct semaphore * sem)
{
atomic_inc(&sem->waking);
}
static inline int waking_non_zero(struct semaphore *sem)
{
unsigned long flags;
int ret = 0;
int ret, tmp;
__asm__ __volatile__(
"1: ldl_l %1,%2\n"
" ble %1,2f\n"
" subl %1,1,%0\n"
" stl_c %0,%2\n"
" beq %0,3f\n"
"2:\n"
".text 2\n"
"3: br 1b\n"
".text"
: "=r"(ret), "=r"(tmp), "=m"(__atomic_fool_gcc(&sem->waking))
: "0"(0));
save_flags(flags);
cli();
if (atomic_read(&sem->waking) > 0) {
atomic_dec(&sem->waking);
ret = 1;
}
restore_flags(flags);
return ret;
}
......
......@@ -34,10 +34,12 @@ typedef struct {
typedef struct { unsigned long a[100]; } __dummy_lock_t;
#define __dummy_lock(lock) (*(__dummy_lock_t *)(lock))
#define spin_unlock(lock) \
__asm__ __volatile__( \
"mb; stq $31,%0" \
:"=m" (__dummy_lock(lock)))
static inline void spin_unlock(spinlock_t * lock)
{
__asm__ __volatile__(
"mb; stq $31,%0"
:"=m" (__dummy_lock(lock)));
}
static inline void spin_lock(spinlock_t * lock)
{
......
#ifndef _LINUX_BOOT_H
#define _LINUX_BOOT_H
/* Don't touch these, unless you really know what you're doing. */
#define DEF_INITSEG 0x9000
#define DEF_SYSSEG 0x1000
#define DEF_SETUPSEG 0x9020
#define DEF_SYSSIZE 0x7F00
/* Internal svga startup constants */
#define NORMAL_VGA 0xffff /* 80x25 mode */
#define EXTENDED_VGA 0xfffe /* 80x50 mode */
#define ASK_VGA 0xfffd /* ask for it at bootup */
#endif
#ifndef _I386_INIT_H
#define _I386_INIT_H
#ifndef MODULE
#define __init __attribute__ ((__section__ (".text.init")))
#define __initdata __attribute__ ((__section__ (".data.init")))
#define __initfunc(__arginit) \
__arginit __init; \
__arginit
/* For assembly routines */
#define __INIT .section ".text.init",#alloc,#execinstr
#define __FINIT .previous
#define __INITDATA .section ".data.init",#alloc,#write
#else
#define __init
#define __initdata
#define __initfunc(__arginit) __arginit
/* For assembly routines */
#define __INIT
#define __FINIT
#define __INITDATA
#endif
#endif
......@@ -19,226 +19,4 @@
extern void disable_irq(unsigned int);
extern void enable_irq(unsigned int);
#define __STR(x) #x
#define STR(x) __STR(x)
#define SAVE_ALL \
"cld\n\t" \
"push %es\n\t" \
"push %ds\n\t" \
"pushl %eax\n\t" \
"pushl %ebp\n\t" \
"pushl %edi\n\t" \
"pushl %esi\n\t" \
"pushl %edx\n\t" \
"pushl %ecx\n\t" \
"pushl %ebx\n\t" \
"movl $" STR(KERNEL_DS) ",%edx\n\t" \
"mov %dx,%ds\n\t" \
"mov %dx,%es\n\t"
/*
* SAVE_MOST/RESTORE_MOST is used for the faster version of IRQ handlers,
* installed by using the SA_INTERRUPT flag. These kinds of IRQ's don't
* call the routines that do signal handling etc on return, and can have
* more relaxed register-saving etc. They are also atomic, and are thus
* suited for small, fast interrupts like the serial lines or the harddisk
* drivers, which don't actually need signal handling etc.
*
* Also note that we actually save only those registers that are used in
* C subroutines (%eax, %edx and %ecx), so if you do something weird,
* you're on your own. The only segments that are saved (not counting the
* automatic stack and code segment handling) are %ds and %es, and they
* point to kernel space. No messing around with %fs here.
*/
#define SAVE_MOST \
"cld\n\t" \
"push %es\n\t" \
"push %ds\n\t" \
"pushl %eax\n\t" \
"pushl %edx\n\t" \
"pushl %ecx\n\t" \
"movl $" STR(KERNEL_DS) ",%edx\n\t" \
"mov %dx,%ds\n\t" \
"mov %dx,%es\n\t"
#define RESTORE_MOST \
"popl %ecx\n\t" \
"popl %edx\n\t" \
"popl %eax\n\t" \
"pop %ds\n\t" \
"pop %es\n\t" \
"iret"
/*
* Some fast irq handlers might want to access saved registers (mostly
* cs or flags)
*/
struct fast_irq_regs {
long ecx;
long edx;
long eax;
int xds;
int xes;
long eip;
int xcs;
long eflags;
long esp;
int xss;
};
/*
* The "inb" instructions are not needed, but seem to change the timings
* a bit - without them it seems that the harddisk driver won't work on
* all hardware. Arghh.
*/
#define ACK_FIRST(mask,nr) \
"inb $0x21,%al\n\t" \
"jmp 1f\n" \
"1:\tjmp 1f\n" \
"1:\torb $" #mask ","SYMBOL_NAME_STR(cache_21)"\n\t" \
"movb "SYMBOL_NAME_STR(cache_21)",%al\n\t" \
"outb %al,$0x21\n\t" \
"jmp 1f\n" \
"1:\tjmp 1f\n" \
"1:\tmovb $0x20,%al\n\t" \
"outb %al,$0x20\n\t"
#define ACK_SECOND(mask,nr) \
"inb $0xA1,%al\n\t" \
"jmp 1f\n" \
"1:\tjmp 1f\n" \
"1:\torb $" #mask ","SYMBOL_NAME_STR(cache_A1)"\n\t" \
"movb "SYMBOL_NAME_STR(cache_A1)",%al\n\t" \
"outb %al,$0xA1\n\t" \
"jmp 1f\n" \
"1:\tjmp 1f\n" \
"1:\tmovb $0x20,%al\n\t" \
"outb %al,$0xA0\n\t" \
"jmp 1f\n" \
"1:\tjmp 1f\n" \
"1:\toutb %al,$0x20\n\t"
#define UNBLK_FIRST(mask) \
"inb $0x21,%al\n\t" \
"jmp 1f\n" \
"1:\tjmp 1f\n" \
"1:\tandb $~(" #mask "),"SYMBOL_NAME_STR(cache_21)"\n\t" \
"movb "SYMBOL_NAME_STR(cache_21)",%al\n\t" \
"outb %al,$0x21\n\t"
#define UNBLK_SECOND(mask) \
"inb $0xA1,%al\n\t" \
"jmp 1f\n" \
"1:\tjmp 1f\n" \
"1:\tandb $~(" #mask "),"SYMBOL_NAME_STR(cache_A1)"\n\t" \
"movb "SYMBOL_NAME_STR(cache_A1)",%al\n\t" \
"outb %al,$0xA1\n\t"
#define IRQ_NAME2(nr) nr##_interrupt(void)
#define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
#define FAST_IRQ_NAME(nr) IRQ_NAME2(fast_IRQ##nr)
#define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr)
#ifdef __SMP__
#define GET_CURRENT \
"movl "SYMBOL_NAME_STR(apic_reg)", %ebx\n\t" \
"movl 32(%ebx), %ebx\n\t" \
"shrl $22,%ebx\n\t" \
"andl $0x3C,%ebx\n\t" \
"movl " SYMBOL_NAME_STR(current_set) "(,%ebx),%ebx\n\t"
#else
#define GET_CURRENT \
"movl " SYMBOL_NAME_STR(current_set) ",%ebx\n\t"
#endif
#ifdef __SMP__
/*
* SMP has a few special interrupts for IPI messages
*/
#define BUILD_SMP_INTERRUPT(x) \
asmlinkage void x(void); \
__asm__( \
"\n"__ALIGN_STR"\n" \
SYMBOL_NAME_STR(x) ":\n\t" \
"pushl $-1\n\t" \
SAVE_ALL \
"call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
"jmp ret_from_intr\n");
#define BUILD_SMP_TIMER_INTERRUPT(x) \
asmlinkage void x(struct pt_regs * regs); \
__asm__( \
"\n"__ALIGN_STR"\n" \
SYMBOL_NAME_STR(x) ":\n\t" \
"pushl $-1\n\t" \
SAVE_ALL \
"movl %esp,%eax\n\t" \
"pushl %eax\n\t" \
"call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
"addl $4,%esp\n\t" \
"jmp ret_from_intr\n");
#endif /* __SMP__ */
#define BUILD_IRQ(chip,nr,mask) \
asmlinkage void IRQ_NAME(nr); \
asmlinkage void FAST_IRQ_NAME(nr); \
asmlinkage void BAD_IRQ_NAME(nr); \
__asm__( \
"\n"__ALIGN_STR"\n" \
SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
"pushl $-"#nr"-2\n\t" \
SAVE_ALL \
ACK_##chip(mask,(nr&7)) \
"movl %esp,%eax\n\t" \
"pushl %eax\n\t" \
"pushl $" #nr "\n\t" \
"call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \
"addl $8,%esp\n\t" \
UNBLK_##chip(mask) \
"jmp ret_from_intr\n" \
"\n"__ALIGN_STR"\n" \
SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \
SAVE_MOST \
ACK_##chip(mask,(nr&7)) \
"pushl $" #nr "\n\t" \
"call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \
"addl $4,%esp\n\t" \
UNBLK_##chip(mask) \
RESTORE_MOST \
"\n"__ALIGN_STR"\n" \
SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \
SAVE_MOST \
ACK_##chip(mask,(nr&7)) \
RESTORE_MOST);
#define BUILD_TIMER_IRQ(chip,nr,mask) \
asmlinkage void IRQ_NAME(nr); \
asmlinkage void FAST_IRQ_NAME(nr); \
asmlinkage void BAD_IRQ_NAME(nr); \
__asm__( \
"\n"__ALIGN_STR"\n" \
SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \
SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \
SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
"pushl $-"#nr"-2\n\t" \
SAVE_ALL \
ACK_##chip(mask,(nr&7)) \
"movl %esp,%eax\n\t" \
"pushl %eax\n\t" \
"pushl $" #nr "\n\t" \
"call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \
"addl $8,%esp\n\t" \
UNBLK_##chip(mask) \
"jmp ret_from_intr\n");
#endif /* _ASM_IRQ_H */
#ifndef _M68K_INIT_H
#define _M68K_INIT_H
/* Throwing the initialization code and data out is not supported yet... */
#define __init
#define __initdata
#define __initfunc(__arginit) __arginit
/* For assembly routines */
#define __INIT
#define __FINIT
#define __INITDATA
#endif
#ifndef _MIPS_INIT_H
#define _MIPS_INIT_H
/* Throwing the initialization code and data out is not supported yet... */
#define __init
#define __initdata
#define __initfunc(__arginit) __arginit
/* For assembly routines */
#define __INIT
#define __FINIT
#define __INITDATA
#endif
#ifndef _PPC_INIT_H
#define _PPC_INIT_H
/* Throwing the initialization code and data out is not supported yet... */
#define __init
#define __initdata
#define __initfunc(__arginit) __arginit
/* For assembly routines */
#define __INIT
#define __FINIT
#define __INITDATA
#endif
......@@ -27,17 +27,4 @@
* in linux/version.h, and should only be used by linux/version.c
*/
/* Shouldn't these be defined somewhere in an i386 definition? */
/* Don't touch these, unless you really know what you're doing. */
#define DEF_INITSEG 0x9000
#define DEF_SYSSEG 0x1000
#define DEF_SETUPSEG 0x9020
#define DEF_SYSSIZE 0x7F00
/* internal svga startup constants */
#define NORMAL_VGA 0xffff /* 80x25 mode */
#define EXTENDED_VGA 0xfffe /* 80x50 mode */
#define ASK_VGA 0xfffd /* ask for it at bootup */
#endif
......@@ -7,7 +7,6 @@
#define asmlinkage
#endif
#ifdef __ELF__
#define SYMBOL_NAME_STR(X) #X
#define SYMBOL_NAME(X) X
#ifdef __STDC__
......@@ -15,33 +14,13 @@
#else
#define SYMBOL_NAME_LABEL(X) X/**/:
#endif
#else
#define SYMBOL_NAME_STR(X) "_"#X
#ifdef __STDC__
#define SYMBOL_NAME(X) _##X
#define SYMBOL_NAME_LABEL(X) _##X##:
#else
#define SYMBOL_NAME(X) _/**/X
#define SYMBOL_NAME_LABEL(X) _/**/X/**/:
#endif
#endif
#if !defined(__i486__) && !defined(__i586__)
#ifdef __ELF__
#define __ALIGN .align 4,0x90
#define __ALIGN_STR ".align 4,0x90"
#else /* __ELF__ */
#define __ALIGN .align 2,0x90
#define __ALIGN_STR ".align 2,0x90"
#endif /* __ELF__ */
#else /* __i486__/__i586__ */
#ifdef __ELF__
#define __ALIGN .align 16,0x90
#define __ALIGN_STR ".align 16,0x90"
#else /* __ELF__ */
#define __ALIGN .align 4,0x90
#define __ALIGN_STR ".align 4,0x90"
#endif /* __ELF__ */
#endif /* __i486__/__i586__ */
#ifdef __ASSEMBLY__
......
......@@ -104,6 +104,17 @@ struct sched_param {
#ifdef __KERNEL__
#include <asm/spinlock.h>
/*
* This serializes "schedule()" and also protects
* the run-queue from deletions/modifications (but
* _adding_ to the beginning of the run-queue has
* a separate lock).
*/
extern spinlock_t scheduler_lock;
extern spinlock_t tasklist_lock;
extern void sched_init(void);
extern void show_state(void);
extern void trap_init(void);
......@@ -460,11 +471,11 @@ extern inline void poll_wait(struct wait_queue ** wait_address, poll_table * p)
p->nr++;
}
#define REMOVE_LINKS(p) do { unsigned long flags; \
save_flags(flags) ; cli(); \
#define REMOVE_LINKS(p) do { \
spin_lock(&tasklist_lock); \
(p)->next_task->prev_task = (p)->prev_task; \
(p)->prev_task->next_task = (p)->next_task; \
restore_flags(flags); \
spin_unlock(&tasklist_lock); \
if ((p)->p_osptr) \
(p)->p_osptr->p_ysptr = (p)->p_ysptr; \
if ((p)->p_ysptr) \
......@@ -473,13 +484,13 @@ extern inline void poll_wait(struct wait_queue ** wait_address, poll_table * p)
(p)->p_pptr->p_cptr = (p)->p_osptr; \
} while (0)
#define SET_LINKS(p) do { unsigned long flags; \
save_flags(flags); cli(); \
#define SET_LINKS(p) do { \
spin_lock(&tasklist_lock); \
(p)->next_task = &init_task; \
(p)->prev_task = init_task.prev_task; \
init_task.prev_task->next_task = (p); \
init_task.prev_task = (p); \
restore_flags(flags); \
spin_unlock(&tasklist_lock); \
(p)->p_ysptr = NULL; \
if (((p)->p_osptr = (p)->p_pptr->p_cptr) != NULL) \
(p)->p_osptr->p_ysptr = p; \
......
......@@ -129,9 +129,7 @@ rpc_set_timeout(struct rpc_clnt *clnt, unsigned int retr, unsigned long incr)
/*
* Helper function for NFSroot support
*/
#ifdef CONFIG_ROOT_NFS
int rpc_getport_external(struct sockaddr_in *, __u32, __u32, int);
#endif
#endif /* __KERNEL__ */
#endif /* _LINUX_SUNRPC_CLNT_H */
......@@ -17,6 +17,9 @@
/*
* Modification history timex.h
*
* 9 Jan 97 Adrian Sun
* Shifted LATCH define to allow access to alpha machines.
*
* 26 Sep 94 David L. Mills
* Added defines for hybrid phase/frequency-lock loop.
*
......@@ -122,15 +125,16 @@
#define PPS_VALID 120 /* pps signal watchdog max (s) */
#define MAXGLITCH 30 /* pps signal glitch max (s) */
/* LATCH is used in the interval timer and ftape setup. */
#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
#define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */
#ifndef __alpha__
/*
* This definitively is wrong for the Alpha and none of the
* kernel code seems to reference this anymore.
*/
#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
#define CLOCK_TICK_FACTOR 20 /* Factor of both 1000000 and CLOCK_TICK_RATE */
#define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */
#define FINETUNE ((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \
(1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \
<< (SHIFT_SCALE-SHIFT_HZ)) / HZ)
......
......@@ -32,6 +32,7 @@
#include <linux/slab.h>
#include <linux/major.h>
#include <linux/blk.h>
#include <linux/init.h>
#ifdef CONFIG_ROOT_NFS
#include <linux/nfs_fs.h>
#endif
......@@ -256,7 +257,7 @@ extern void dquot_init(void);
static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
static char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
char *get_options(char *str, int *ints)
__initfunc(char *get_options(char *str, int *ints))
{
char *cur = str;
int i=1;
......@@ -270,7 +271,7 @@ char *get_options(char *str, int *ints)
return(cur);
}
static void profile_setup(char *str, int *ints)
__initfunc(static void profile_setup(char *str, int *ints))
{
if (ints[0] > 0)
prof_shift = (unsigned long) ints[1];
......@@ -285,7 +286,7 @@ static void profile_setup(char *str, int *ints)
struct {
const char *str;
void (*setup_func)(char *, int *);
} bootsetups[] = {
} bootsetups[] __initdata = {
{ "reserve=", reserve_setup },
{ "profile=", profile_setup },
#ifdef __SMP__
......@@ -502,25 +503,25 @@ struct {
};
#ifdef CONFIG_BLK_DEV_RAM
static void ramdisk_start_setup(char *str, int *ints)
__initfunc(static void ramdisk_start_setup(char *str, int *ints))
{
if (ints[0] > 0 && ints[1] >= 0)
rd_image_start = ints[1];
}
static void load_ramdisk(char *str, int *ints)
__initfunc(static void load_ramdisk(char *str, int *ints))
{
if (ints[0] > 0 && ints[1] >= 0)
rd_doload = ints[1] & 1;
}
static void prompt_ramdisk(char *str, int *ints)
__initfunc(static void prompt_ramdisk(char *str, int *ints))
{
if (ints[0] > 0 && ints[1] >= 0)
rd_prompt = ints[1] & 1;
}
static void ramdisk_size(char *str, int *ints)
__initfunc(static void ramdisk_size(char *str, int *ints))
{
if (ints[0] > 0 && ints[1] >= 0)
rd_size = ints[1];
......@@ -528,7 +529,7 @@ static void ramdisk_size(char *str, int *ints)
#endif
static int checksetup(char *line)
__initfunc(static int checksetup(char *line))
{
int i = 0;
int ints[11];
......@@ -560,7 +561,7 @@ unsigned long loops_per_sec = (1<<12);
better than 1% */
#define LPS_PREC 8
void calibrate_delay(void)
__initfunc(void calibrate_delay(void))
{
unsigned long ticks, loopbit;
int lps_precision = LPS_PREC;
......@@ -603,7 +604,7 @@ void calibrate_delay(void)
((loops_per_sec+2500)/5000) % 100);
}
static void parse_root_dev(char * line)
__initfunc(static void parse_root_dev(char * line))
{
int base = 0;
static struct dev_name_struct {
......@@ -674,7 +675,7 @@ static void parse_root_dev(char * line)
* This routine also checks for options meant for the kernel.
* These options are not given to init - they are for internal kernel use only.
*/
static void parse_options(char *line)
__initfunc(static void parse_options(char *line))
{
char *next;
int args, envs;
......@@ -782,7 +783,7 @@ extern int cpu_idle(void * unused);
* Activate a secondary processor.
*/
asmlinkage void start_secondary(void)
__initfunc(asmlinkage void start_secondary(void))
{
trap_init();
init_IRQ();
......@@ -793,7 +794,7 @@ asmlinkage void start_secondary(void)
/* Called by boot processor to activate the rest. */
static void smp_init(void)
__initfunc(static void smp_init(void))
{
int i, j;
......@@ -823,7 +824,7 @@ static void smp_init(void)
* they are finished.
*/
static void smp_begin(void)
__initfunc(static void smp_begin(void))
{
smp_threads_ready=1;
smp_commence();
......@@ -835,7 +836,7 @@ static void smp_begin(void)
* Activate the first processor.
*/
asmlinkage void start_kernel(void)
__initfunc(asmlinkage void start_kernel(void))
{
char * command_line;
......@@ -947,7 +948,7 @@ asmlinkage void start_kernel(void)
}
#ifdef CONFIG_BLK_DEV_INITRD
static int do_linuxrc(void * shell)
__initfunc(static int do_linuxrc(void * shell))
{
static char *argv[] = { "linuxrc", NULL, };
......@@ -959,7 +960,7 @@ static int do_linuxrc(void * shell)
return execve(shell, argv, envp_init);
}
static void no_initrd(char *s,int *ints)
__initfunc(static void no_initrd(char *s,int *ints))
{
mount_initrd = 0;
}
......
......@@ -16,7 +16,6 @@
* current-task
*/
#include <linux/config.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/timer.h>
......@@ -188,6 +187,10 @@ static inline void move_last_runqueue(struct task_struct * p)
}
/*
* The tasklist_lock protects the linked list of processes
* and doesn't need to be interrupt-safe as interrupts never
* use the task-list.
*
* The scheduler lock is protecting against multiple entry
* into the scheduling code, and doesn't need to worry
* about interrupts (because interrupts cannot call the
......@@ -196,6 +199,7 @@ static inline void move_last_runqueue(struct task_struct * p)
* The run-queue lock locks the parts that actually access
* and change the run-queues, and have to be interrupt-safe.
*/
spinlock_t tasklist_lock = SPIN_LOCK_UNLOCKED;
spinlock_t scheduler_lock = SPIN_LOCK_UNLOCKED;
static spinlock_t runqueue_lock = SPIN_LOCK_UNLOCKED;
......@@ -300,7 +304,6 @@ static inline int goodness(struct task_struct * p, struct task_struct * prev, in
*/
asmlinkage void schedule(void)
{
static int need_recalculate = 0;
int lock_depth;
struct task_struct * prev, * next;
unsigned long timeout;
......@@ -384,7 +387,15 @@ asmlinkage void schedule(void)
}
p = p->next_run;
}
need_recalculate = !c;
/* Do we need to re-calculate counters? */
if (!c) {
struct task_struct *p;
spin_lock(&tasklist_lock);
for_each_task(p)
p->counter = (p->counter >> 1) + p->priority;
spin_unlock(&tasklist_lock);
}
}
}
......@@ -410,16 +421,7 @@ asmlinkage void schedule(void)
}
spin_unlock(&scheduler_lock);
if (lock_depth) {
reaquire_kernel_lock(prev, smp_processor_id(), lock_depth);
/* Do we need to re-calculate counters? */
if (need_recalculate) {
struct task_struct *p;
for_each_task(p)
p->counter = (p->counter >> 1) + p->priority;
}
}
reaquire_kernel_lock(prev, smp_processor_id(), lock_depth);
}
#ifndef __alpha__
......
......@@ -9,6 +9,7 @@
* Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
*/
#include <linux/config.h>
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/kernel.h>
......
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