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
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
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
*************
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
=====
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
===
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
*************************************************
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
================
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
==========
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
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/)
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'
# CONFIG_APM is not set
# CONFIG_WATCHDOG is not set
# CONFIG_RTC is not set
+CONFIG_RTC_ARC=y
#
# Sound
#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);
extern void __remqu (void);
EXPORT_SYMBOL(__alpha_bh_counter);
+EXPORT_SYMBOL(local_irq_count);
/* platform dependent support */
EXPORT_SYMBOL(_inb);
.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
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
#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.
/*
* 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)
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);
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;
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);
{
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
printk("Interprocessor interrupt? You must be kidding\n");
break;
case 1:
- timer_interrupt(®s);
+ handle_irq(RTC_IRQ, ®s);
return;
case 2:
machine_check(vector, la_ptr, ®s);
#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>
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;
#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>
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);
* 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>
#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;
* 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;
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;
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!");
}
/*
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
# 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
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
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)
! 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
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)
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
* 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;
+++ /dev/null
-/*
- * 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);
-
-}
+++ /dev/null
-/*
- * 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);
-}
! 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
! 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
*/
/*
* 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) {
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 */
}
#include <linux/kernel.h>
#include <linux/bios32.h>
#include <linux/pci.h>
+#include <linux/init.h>
#include <asm/page.h>
#include <asm/segment.h>
} 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;
};
-static struct pci_access *check_direct_pci(void)
+__initfunc(static struct pci_access *check_direct_pci(void))
{
unsigned int tmp;
unsigned long flags;
}
-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;
* 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
#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>
#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
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
}
}
-#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
/*
return i;
}
-void init_IRQ(void)
+__initfunc(void init_IRQ(void))
{
int i;
static unsigned char smptrap=0;
*/
#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");
--- /dev/null
+#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
#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
/*--------------------------------------------------------------------*/
-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;
/*--------------------------------------------------------------------*/
-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;
#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
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;
#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);
* 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];
* 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);
* 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;
* 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);
}
* 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 */
* 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)
* 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 */
* 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.
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));
* 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;
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();
break;
case MSG_INVALIDATE_TLB:
+ /* make this a NMI some day */
irq = 0x31;
break;
case MSG_STOP_CPU:
- irq = 0x32;
+ irq = 0x40;
break;
default:
* 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 */
* 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
/* 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
* 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;
*
* 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))
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) {
*/
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 (;;) ;
}
/*
* 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;
* 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);
/*
#include <linux/interrupt.h>
#include <linux/time.h>
#include <linux/delay.h>
+#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/io.h>
* 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;
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 ) {
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;
#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>
#endif /* CONFIG_MATH_EMULATION */
-void trap_init(void)
+__initfunc(void trap_init(void))
{
int i;
struct desc_struct * p;
#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
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.
* 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;
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;
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);
#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;
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)
--- /dev/null
+/* 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) }
+}
#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
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;
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--;
}
+++ /dev/null
-torvalds@penguin.transmeta.com
\ No newline at end of file
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))
#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
#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
--- /dev/null
+#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
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
#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;
}
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)
{
--- /dev/null
+#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
--- /dev/null
+#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
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 */
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
* 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
#define asmlinkage
#endif
-#ifdef __ELF__
#define SYMBOL_NAME_STR(X) #X
#define SYMBOL_NAME(X) X
#ifdef __STDC__
#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__
#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);
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) \
(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; \
/*
* 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 */
/*
* 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.
*
#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)
#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
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;
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];
struct {
const char *str;
void (*setup_func)(char *, int *);
-} bootsetups[] = {
+} bootsetups[] __initdata = {
{ "reserve=", reserve_setup },
{ "profile=", profile_setup },
#ifdef __SMP__
};
#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];
#endif
-static int checksetup(char *line)
+__initfunc(static int checksetup(char *line))
{
int i = 0;
int ints[11];
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;
((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 {
* 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;
* Activate a secondary processor.
*/
-asmlinkage void start_secondary(void)
+__initfunc(asmlinkage void start_secondary(void))
{
trap_init();
init_IRQ();
/* Called by boot processor to activate the rest. */
-static void smp_init(void)
+__initfunc(static void smp_init(void))
{
int i, j;
* they are finished.
*/
-static void smp_begin(void)
+__initfunc(static void smp_begin(void))
{
smp_threads_ready=1;
smp_commence();
* Activate the first processor.
*/
-asmlinkage void start_kernel(void)
+__initfunc(asmlinkage void start_kernel(void))
{
char * command_line;
}
#ifdef CONFIG_BLK_DEV_INITRD
-static int do_linuxrc(void * shell)
+__initfunc(static int do_linuxrc(void * shell))
{
static char *argv[] = { "linuxrc", NULL, };
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;
}
* current-task
*/
-#include <linux/config.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/timer.h>
}
/*
+ * 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
* 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;
*/
asmlinkage void schedule(void)
{
- static int need_recalculate = 0;
int lock_depth;
struct task_struct * prev, * next;
unsigned long timeout;
}
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);
+ }
}
}
}
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__
* 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>