Commit a2d6205f authored by Linus Torvalds's avatar Linus Torvalds

Import 2.1.35

parent 92cc7d38
...@@ -905,8 +905,9 @@ S: Australia ...@@ -905,8 +905,9 @@ S: Australia
N: Martin Mares N: Martin Mares
E: mj@k332.feld.cvut.cz E: mj@k332.feld.cvut.cz
W: http://atrey.karlin.mff.cuni.cz/~mj/
D: BIOS video mode handling code D: BIOS video mode handling code
D: Miscellaneous kernel fixes D: Miscellaneous kernel fixes and hacks
D: MOXA C-218 serial board driver D: MOXA C-218 serial board driver
D: BOOTP support D: BOOTP support
S: Kankovskeho 1241 S: Kankovskeho 1241
......
...@@ -26,7 +26,10 @@ HTML-ized shopping list. ...@@ -26,7 +26,10 @@ HTML-ized shopping list.
http://www.datanet.hu/generations/linux/Changes2.html is an http://www.datanet.hu/generations/linux/Changes2.html is an
English-language HTML version. 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 Author: Chris Ricker (gt1355b@prism.gatech.edu).
Current Minimal Requirements Current Minimal Requirements
...@@ -35,19 +38,19 @@ Current Minimal Requirements ...@@ -35,19 +38,19 @@ Current Minimal Requirements
Upgrade to at *least* these software revisions before thinking you've Upgrade to at *least* these software revisions before thinking you've
encountered a bug! encountered a bug!
- Kernel modules modutils-2.1.29-970320 - Kernel modules modutils-2.1.34
- Gnu C 2.7.2.1 - Gnu C 2.7.2.1
- Binutils 2.7.0.9 - Binutils 2.7.0.9
- Linux C Library 5.4.23 - Linux C Library 5.4.23
- Dynamic Linker (ld.so) 1.8.5 - Dynamic Linker (ld.so) 1.8.5
- Linux C++ Library 2.7.2.1 - Linux C++ Library 2.7.2.1
- Procps 1.01 - Procps 1.01
- Mount 2.5p - Mount 2.6e
- Net-tools 1.32-alpha - Net-tools 1.32-alpha
- Kbd 0.91
- Loadlin 1.6a - Loadlin 1.6a
- Sh-utils 1.16 - Sh-utils 1.16
- Ncpfs 2.1.1 - Autofs 970409
- NFS 0.4.21
Upgrade notes Upgrade notes
************* *************
...@@ -78,20 +81,22 @@ release. ...@@ -78,20 +81,22 @@ release.
If you upgrade to libc-5.4.x, you also have to upgrade your dynamic 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 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 happen. Actually, ld.so-1.8.2 and later will work, but 1.8.5 is widely
widely available, so if you need to upgrade, use it. 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 Modules
======= =======
You need to upgrade to modutils-2.1.29-970320 for kernels 2.1.29 and You need to upgrade to modutils-2.1.34 for kernels 2.1.34 and later.
later.
Binutils Binutils
======== ========
If you upgrade binutils, please read its accompanying release notes 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 Gnu C
===== =====
...@@ -126,6 +131,15 @@ presence. ...@@ -126,6 +131,15 @@ presence.
To run bootpd, you'll need to issue the following command: echo 1 To run bootpd, you'll need to issue the following command: echo 1
>/proc/sys/net/ipv4/ip_boot_agent >/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 RPM
=== ===
...@@ -151,6 +165,16 @@ Sh-utils ...@@ -151,6 +165,16 @@ Sh-utils
updated to be POSIX-compliant. As a result, your expr needs to be updated to be POSIX-compliant. As a result, your expr needs to be
updated. Use sh-utils 1.16 or later. 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 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 ...@@ -223,8 +247,9 @@ ftp://sunsite.unc.edu/pub/Linux/GCC/ld.so-1.8.5.tar.gz
Modules utilities Modules utilities
================= =================
The 2.1.29-970320 release: The 2.1.34 release:
ftp://ftp.redhat.com/pub/alphabits/modutils-2.1.29-970320.tar.gz 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 Procps utilities
================ ================
...@@ -263,10 +288,29 @@ ftp://elserv.ffm.fgan.de/pub/linux/loadlin-1.6/update-1.6a/loadlin.exe.gz ...@@ -263,10 +288,29 @@ ftp://elserv.ffm.fgan.de/pub/linux/loadlin-1.6/update-1.6a/loadlin.exe.gz
Sh-utils Sh-utils
======== ========
The 1.16 release The 1.16 release:
ftp://sunsite.unc.edu/pub/gnu/sh-utils-1.16.tar.gz 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 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 Other Info
========== ==========
......
...@@ -4439,6 +4439,12 @@ CONFIG_RTC ...@@ -4439,6 +4439,12 @@ CONFIG_RTC
have a use for such a device (such as periodic data sampling), then 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. 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 Sound card support
CONFIG_SOUND CONFIG_SOUND
If you have a Sound Card in your Computer, i.e. if it can say more 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): ...@@ -452,10 +452,10 @@ by doing the following after installing slackware (or whatever):
0. Boot from the "boot floppy" created during the installation 0. Boot from the "boot floppy" created during the installation
1. Mount your DOS partition as /dos (and stick it in /etc/fstab) 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 2. Move /boot to /dos/boot with: cp -a /boot /dos ; rm -r /boot
3. Edit /etc/lilo.conf to change /vmlinuz to /dos/vmlinuz 3. Create a symlink for LILO to use with: ln -s /dos/boot /boot
4. Move /boot to /dos/boot with: cp -a /boot /dos ; rm -r /boot 4. Move your kernel (/vmlinuz) to /boot/vmlinuz: mv /vmlinuz /boot
5. Create a symlink for LILO to use with: ln -s /dos/boot /boot 5. Edit /etc/lilo.conf to change /vmlinuz to /boot/vmlinuz
6. Re-run LILO with: lilo 6. Re-run LILO with: lilo
A danger with this approach is that whenever an MS-DOS "defragmentation" A danger with this approach is that whenever an MS-DOS "defragmentation"
......
VERSION = 2 VERSION = 2
PATCHLEVEL = 1 PATCHLEVEL = 1
SUBLEVEL = 34 SUBLEVEL = 35
ARCH := $(shell uname -m | sed s/i.86/i386/) ARCH := $(shell uname -m | sed s/i.86/i386/)
......
...@@ -151,6 +151,9 @@ endmenu ...@@ -151,6 +151,9 @@ endmenu
source fs/Config.in source fs/Config.in
source drivers/char/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 mainmenu_option next_comment
comment 'Sound' comment 'Sound'
......
...@@ -224,6 +224,7 @@ CONFIG_PSMOUSE=y ...@@ -224,6 +224,7 @@ CONFIG_PSMOUSE=y
# CONFIG_APM is not set # CONFIG_APM is not set
# CONFIG_WATCHDOG is not set # CONFIG_WATCHDOG is not set
# CONFIG_RTC is not set # CONFIG_RTC is not set
CONFIG_RTC_ARC=y
# #
# Sound # Sound
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/checksum.h> #include <asm/checksum.h>
#include <linux/interrupt.h>
#include <asm/softirq.h> #include <asm/softirq.h>
extern void bcopy (const char *src, char *dst, int len); extern void bcopy (const char *src, char *dst, int len);
...@@ -38,6 +39,7 @@ extern void __divqu (void); ...@@ -38,6 +39,7 @@ extern void __divqu (void);
extern void __remqu (void); extern void __remqu (void);
EXPORT_SYMBOL(__alpha_bh_counter); EXPORT_SYMBOL(__alpha_bh_counter);
EXPORT_SYMBOL(local_irq_count);
/* platform dependent support */ /* platform dependent support */
EXPORT_SYMBOL(_inb); EXPORT_SYMBOL(_inb);
......
...@@ -126,19 +126,8 @@ ...@@ -126,19 +126,8 @@
.ent entInt .ent entInt
entInt: entInt:
SAVE_ALL 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 ldq $8,current_set
jsr $26,do_entInt 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 br $31,ret_from_sys_call
.end entInt .end entInt
......
...@@ -24,8 +24,7 @@ __start: ...@@ -24,8 +24,7 @@ __start:
br $27,1f br $27,1f
1: ldgp $29,0($27) 1: ldgp $29,0($27)
/* We need to get current loaded up with our first task. */ /* We need to get current loaded up with our first task. */
lda $8,init_task ldq $8,current_set
stq $8,current_set
/* And then we can start the kernel. */ /* And then we can start the kernel. */
jsr $26,start_kernel jsr $26,start_kernel
halt halt
......
...@@ -26,7 +26,12 @@ ...@@ -26,7 +26,12 @@
#include <asm/bitops.h> #include <asm/bitops.h>
#include <asm/dma.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 #if NR_IRQS > 64
# error Unable to handle more than 64 irq levels. # error Unable to handle more than 64 irq levels.
...@@ -132,6 +137,7 @@ void enable_irq(unsigned int irq_nr) ...@@ -132,6 +137,7 @@ void enable_irq(unsigned int irq_nr)
/* /*
* Initial irq handlers. * Initial irq handlers.
*/ */
static struct irqaction timer_irq = { NULL, 0, 0, NULL, NULL, NULL};
static struct irqaction *irq_action[NR_IRQS]; static struct irqaction *irq_action[NR_IRQS];
int get_irq_list(char *buf) int get_irq_list(char *buf)
...@@ -143,7 +149,7 @@ int get_irq_list(char *buf) ...@@ -143,7 +149,7 @@ int get_irq_list(char *buf)
action = irq_action[i]; action = irq_action[i];
if (!action) if (!action)
continue; continue;
len += sprintf(buf+len, "%2d: %8d %c %s", len += sprintf(buf+len, "%2d: %10u %c %s",
i, kstat.interrupts[i], i, kstat.interrupts[i],
(action->flags & SA_INTERRUPT) ? '+' : ' ', (action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name); action->name);
...@@ -211,7 +217,10 @@ int request_irq(unsigned int irq, ...@@ -211,7 +217,10 @@ int request_irq(unsigned int irq,
shared = 1; 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); GFP_KERNEL);
if (!action) if (!action)
return -ENOMEM; return -ENOMEM;
...@@ -329,6 +338,7 @@ static inline void handle_irq(int irq, struct pt_regs * regs) ...@@ -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) static inline void device_interrupt(int irq, int ack, struct pt_regs * regs)
{ {
struct irqaction * action; struct irqaction * action;
int cpu = smp_processor_id();
if ((unsigned) irq > NR_IRQS) { if ((unsigned) irq > NR_IRQS) {
printk("device_interrupt: unexpected interrupt %d\n", irq); printk("device_interrupt: unexpected interrupt %d\n", irq);
...@@ -660,7 +670,9 @@ int probe_irq_off(unsigned long irqs) ...@@ -660,7 +670,9 @@ int probe_irq_off(unsigned long irqs)
{ {
int i; 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 #ifdef CONFIG_ALPHA_P2K
irqs &= ~(1 << 8); /* mask out irq 8 since that's the unused RTC input to PIC */ irqs &= ~(1 << 8); /* mask out irq 8 since that's the unused RTC input to PIC */
#endif #endif
...@@ -700,7 +712,7 @@ asmlinkage void do_entInt(unsigned long type, unsigned long vector, unsigned lon ...@@ -700,7 +712,7 @@ asmlinkage void do_entInt(unsigned long type, unsigned long vector, unsigned lon
printk("Interprocessor interrupt? You must be kidding\n"); printk("Interprocessor interrupt? You must be kidding\n");
break; break;
case 1: case 1:
timer_interrupt(&regs); handle_irq(RTC_IRQ, &regs);
return; return;
case 2: case 2:
machine_check(vector, la_ptr, &regs); machine_check(vector, la_ptr, &regs);
......
...@@ -29,6 +29,10 @@ ...@@ -29,6 +29,10 @@
#include <linux/elfcore.h> #include <linux/elfcore.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#ifdef CONFIG_RTC
#include <linux/mc146818rtc.h>
#endif
#include <asm/reg.h> #include <asm/reg.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -66,6 +70,24 @@ asmlinkage int sys_idle(void) ...@@ -66,6 +70,24 @@ asmlinkage int sys_idle(void)
void machine_restart(char * __unused) 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) #if defined(CONFIG_ALPHA_SRM) && defined(CONFIG_ALPHA_ALCOR)
/* who said DEC engineer's have no sense of humor? ;-)) */ /* who said DEC engineer's have no sense of humor? ;-)) */
*(int *) GRU_RESET = 0x0000dead; *(int *) GRU_RESET = 0x0000dead;
......
...@@ -22,6 +22,11 @@ ...@@ -22,6 +22,11 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/config.h> /* CONFIG_ALPHA_LCA etc */ #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/uaccess.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -83,9 +88,17 @@ static void init_pit (void) ...@@ -83,9 +88,17 @@ static void init_pit (void)
outb(0x18, 0x41); outb(0x18, 0x41);
#endif #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(0x36, 0x43); /* counter 0: system timer */
outb(0x00, 0x40); outb(0x00, 0x40);
outb(0x00, 0x40); outb(0x00, 0x40);
request_region(0x70, 0x10, "timer"); /* reserve rtc */
#endif
outb(0xb6, 0x43); /* counter 2: speaker */ outb(0xb6, 0x43); /* counter 2: speaker */
outb(0x31, 0x42); outb(0x31, 0x42);
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
* 1995-03-26 Markus Kuhn * 1995-03-26 Markus Kuhn
* fixed 500 ms bug at call to set_rtc_mmss, fixed DS12887 * fixed 500 ms bug at call to set_rtc_mmss, fixed DS12887
* precision CMOS clock update * precision CMOS clock update
* 1997-01-09 Adrian Sun
* use interval timer if CONFIG_RTC=y
*/ */
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/sched.h> #include <linux/sched.h>
...@@ -25,7 +27,11 @@ ...@@ -25,7 +27,11 @@
#include <linux/mc146818rtc.h> #include <linux/mc146818rtc.h>
#include <linux/timex.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; extern struct hwrpb_struct *hwrpb;
...@@ -61,7 +67,7 @@ static inline __u32 rpcc(void) ...@@ -61,7 +67,7 @@ static inline __u32 rpcc(void)
* timer_interrupt() needs to keep up the real-time clock, * timer_interrupt() needs to keep up the real-time clock,
* as well as call the "do_timer()" routine every clocktick * 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; __u32 delta, now;
...@@ -125,6 +131,10 @@ static inline unsigned long mktime(unsigned int year, unsigned int mon, ...@@ -125,6 +131,10 @@ static inline unsigned long mktime(unsigned int year, unsigned int mon,
void time_init(void) 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; unsigned int year, mon, day, hour, min, sec;
int i; int i;
...@@ -178,6 +188,21 @@ void time_init(void) ...@@ -178,6 +188,21 @@ void time_init(void)
state.scaled_ticks_per_cycle = ((unsigned long) HZ << FIX_SHIFT) / hwrpb->cycle_freq; state.scaled_ticks_per_cycle = ((unsigned long) HZ << FIX_SHIFT) / hwrpb->cycle_freq;
state.max_cycles_per_tick = (2 * hwrpb->cycle_freq) / HZ; state.max_cycles_per_tick = (2 * hwrpb->cycle_freq) / HZ;
state.last_rtc_update = 0; 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 ...@@ -17,33 +17,11 @@ AS86 =$(CROSS_COMPILE)as86 -0 -a
AS386 =$(CROSS_COMPILE)as86 -3 AS386 =$(CROSS_COMPILE)as86 -3
LD86 =$(CROSS_COMPILE)ld86 -0 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 LD=$(CROSS_COMPILE)ld -m elf_i386
CPP=$(CC) -E -D__ELF__ CPP=$(CC) -E
OBJDUMP=$(CROSS_COMPILE)objdump OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S
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
LDFLAGS=-e stext LDFLAGS=-e stext
ZLINKFLAGS =-Ttext $(ZIMAGE_OFFSET) $(ZLDFLAGS) LINKFLAGS =-T arch/i386/vmlinux.lds $(LDFLAGS)
BZLINKFLAGS =-Ttext $(BZIMAGE_OFFSET) $(ZLDFLAGS)
LINKFLAGS =-Ttext $(IMAGE_OFFSET) $(LDFLAGS)
CFLAGS := $(CFLAGS) -pipe -fno-strength-reduce CFLAGS := $(CFLAGS) -pipe -fno-strength-reduce
......
...@@ -8,29 +8,21 @@ ...@@ -8,29 +8,21 @@
# Copyright (C) 1994 by Linus Torvalds # Copyright (C) 1994 by Linus Torvalds
# #
HOSTCFLAGS := $(HOSTCFLAGS) -D__BFD__
ifdef SMP ifdef SMP
HOSTCFLAGS := $(HOSTCFLAGS) -D__SMP__ HOSTCFLAGS := $(HOSTCFLAGS) -D__SMP__
endif 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 zImage: $(CONFIGURE) bootsect setup compressed/vmlinux tools/build
if hash $(ENCAPS) 2> /dev/null; then \ $(OBJCOPY) compressed/vmlinux compressed/vmlinux.out
$(OBJDUMP) $(OBJDUMP_FLAGS) -o $(ZIMAGE_OFFSET) compressed/vmlinux > compressed/vmlinux.out; \
else \
$(OBJCOPY) compressed/vmlinux compressed/vmlinux.out; \
fi
tools/build bootsect setup compressed/vmlinux.out $(ROOT_DEV) > zImage tools/build bootsect setup compressed/vmlinux.out $(ROOT_DEV) > zImage
sync
bzImage: $(CONFIGURE) bbootsect setup compressed/bvmlinux tools/bbuild bzImage: $(CONFIGURE) bbootsect bsetup compressed/bvmlinux tools/build
if hash $(ENCAPS) 2> /dev/null; then \ $(OBJCOPY) compressed/bvmlinux compressed/bvmlinux.out
$(OBJDUMP) $(OBJDUMP_FLAGS) -o $(BZIMAGE_OFFSET) compressed/bvmlinux > compressed/bvmlinux.out; \ tools/build -b bbootsect bsetup compressed/bvmlinux.out $(ROOT_DEV) > bzImage
else \
$(OBJCOPY) compressed/bvmlinux compressed/bvmlinux.out; \
fi
tools/bbuild bbootsect setup compressed/bvmlinux.out $(ROOT_DEV) > bzImage
sync
compressed/vmlinux: $(TOPDIR)/vmlinux compressed/vmlinux: $(TOPDIR)/vmlinux
@$(MAKE) -C compressed vmlinux @$(MAKE) -C compressed vmlinux
...@@ -54,25 +46,31 @@ install: $(CONFIGURE) zImage ...@@ -54,25 +46,31 @@ install: $(CONFIGURE) zImage
tools/build: tools/build.c tools/build: tools/build.c
$(HOSTCC) $(HOSTCFLAGS) -o $@ $< -I$(TOPDIR)/include $(HOSTCC) $(HOSTCFLAGS) -o $@ $< -I$(TOPDIR)/include
tools/bbuild: tools/build.c
$(HOSTCC) $(HOSTCFLAGS) -D__BIG_KERNEL__ -o $@ $< -I$(TOPDIR)/include
setup: setup.o setup: setup.o
$(LD86) -s -o $@ $< $(LD86) -s -o $@ $<
setup.o: setup.s setup.o: setup.s
$(AS86) -o $@ $< $(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 $@ $(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 bootsect: bootsect.o
$(LD86) -s -o $@ $< $(LD86) -s -o $@ $<
bootsect.o: bootsect.s bootsect.o: bootsect.s
$(AS86) -o $@ $< $(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 $@ $(CPP) -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@
bbootsect: bbootsect.o bbootsect: bbootsect.o
...@@ -81,14 +79,13 @@ bbootsect: bbootsect.o ...@@ -81,14 +79,13 @@ bbootsect: bbootsect.o
bbootsect.o: bbootsect.s bbootsect.o: bbootsect.s
$(AS86) -o $@ $< $(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 $@ $(CPP) -D__BIG_KERNEL__ -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@
dep: dep:
clean: clean:
rm -f bootsect setup rm -f tools/build
rm -f bbootsect rm -f setup bootsect zImage compressed/vmlinux.out
rm -f zImage tools/build compressed/vmlinux.out rm -f bsetup bbootsect bzImage compressed/bvmlinux.out
rm -f bzImage tools/bbuild compressed/bvmlinux.out
@$(MAKE) -C compressed clean @$(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 ! bootsect.s Copyright (C) 1991, 1992 Linus Torvalds
! modified by Drew Eckhardt ! modified by Drew Eckhardt
! modified by Bruce Evans (bde) ! modified by Bruce Evans (bde)
...@@ -29,13 +22,17 @@ SYSSIZE = DEF_SYSSIZE ...@@ -29,13 +22,17 @@ SYSSIZE = DEF_SYSSIZE
! read errors will result in a unbreakable loop. Reboot by hand. It ! read errors will result in a unbreakable loop. Reboot by hand. It
! loads pretty fast by getting whole tracks at a time whenever possible. ! loads pretty fast by getting whole tracks at a time whenever possible.
#include <asm/boot.h>
.text .text
SETUPSECS = 4 ! nr of setup-sectors SETUPSECS = 4 ! default nr of setup-sectors
BOOTSEG = 0x07C0 ! original address of boot-sector BOOTSEG = 0x07C0 ! original address of boot-sector
INITSEG = DEF_INITSEG ! we move boot here - out of the way INITSEG = DEF_INITSEG ! we move boot here - out of the way
SETUPSEG = DEF_SETUPSEG ! setup starts here SETUPSEG = DEF_SETUPSEG ! setup starts here
SYSSEG = DEF_SYSSEG ! system loaded at 0x10000 (65536). 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 & SWAP_DEV are now written by "build".
ROOT_DEV = 0 ROOT_DEV = 0
......
...@@ -10,15 +10,22 @@ SYSTEM = $(TOPDIR)/vmlinux ...@@ -10,15 +10,22 @@ SYSTEM = $(TOPDIR)/vmlinux
OBJECTS = $(HEAD) misc.o OBJECTS = $(HEAD) misc.o
CFLAGS = -O2 -DSTDC_HEADERS 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 ifdef SMP
CFLAGS := $(CFLAGS) -D__SMP__ CFLAGS := $(CFLAGS) -D__SMP__
endif endif
TARGET=--target elf32-i386
INPUT_DATA=input_data
INPUT_LEN=input_len
all: vmlinux all: vmlinux
vmlinux: piggy.o $(OBJECTS) vmlinux: piggy.o $(OBJECTS)
...@@ -40,24 +47,14 @@ head.o: head.S $(TOPDIR)/include/linux/tasks.h ...@@ -40,24 +47,14 @@ head.o: head.S $(TOPDIR)/include/linux/tasks.h
endif endif
# You cannot compress a file and have the kernel uncompress it, it must
# be stdin
piggy.o: $(SYSTEM) piggy.o: $(SYSTEM)
tmppiggy=/tmp/$$$$piggy; \ tmppiggy=/tmp/$$$$piggy; \
rm -f $$tmppiggy $$tmppiggy.gz $$tmppiggy.lnk; \ rm -f $$tmppiggy $$tmppiggy.gz $$tmppiggy.lnk; \
if hash $(ENCAPS) 2> /dev/null; then \ $(OBJCOPY) $(SYSTEM) $$tmppiggy; \
$(OBJDUMP) $(OBJDUMP_FLAGS) -o $(IMAGE_OFFSET) $(SYSTEM) > $$tmppiggy; \
else \
$(OBJCOPY) $(SYSTEM) $$tmppiggy; \
fi; \
gzip -f -9 < $$tmppiggy > $$tmppiggy.gz; \ gzip -f -9 < $$tmppiggy > $$tmppiggy.gz; \
if hash $(ENCAPS) 2> /dev/null; then \ echo "SECTIONS { .data : { input_len = .; LONG(input_data_end - input_data) input_data = .; *(.data) input_data_end = .; }}" > $$tmppiggy.lnk; \
$(ENCAPS) $(TARGET) piggy.o $$tmppiggy.gz $(INPUT_DATA) $(INPUT_LEN); \ $(LD) -m elf_i386 -r -o piggy.o -b binary $$tmppiggy.gz -b elf32-i386 -T $$tmppiggy.lnk; \
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; \
rm -f $$tmppiggy $$tmppiggy.gz $$tmppiggy.lnk rm -f $$tmppiggy $$tmppiggy.gz $$tmppiggy.lnk
clean: clean:
rm -f xtract piggyback vmlinux bvmlinux rm -f vmlinux bvmlinux
...@@ -75,11 +75,7 @@ static void gzip_release(void **); ...@@ -75,11 +75,7 @@ static void gzip_release(void **);
* This is set up by the setup-routine at boot-time * This is set up by the setup-routine at boot-time
*/ */
#define EXT_MEM_K (*(unsigned short *)0x90002) #define EXT_MEM_K (*(unsigned short *)0x90002)
#define DRIVE_INFO (*(struct drive_info *)0x90080)
#define SCREEN_INFO (*(struct screen_info *)0x90000) #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 char input_data[];
extern int input_len; 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 @@ ...@@ -27,12 +27,12 @@
! Video handling moved to video.S by Martin Mares, March 1996 ! Video handling moved to video.S by Martin Mares, March 1996
! <mj@k332.feld.cvut.cz> ! <mj@k332.feld.cvut.cz>
! NOTE! These had better be the same as in bootsect.s!
#define __ASSEMBLY__ #define __ASSEMBLY__
#include <linux/config.h> #include <linux/config.h>
#include <asm/segment.h> #include <asm/segment.h>
#include <linux/version.h> #include <linux/version.h>
#include <linux/compile.h> #include <linux/compile.h>
#include <asm/boot.h>
! Signature words to ensure LILO loaded us right ! Signature words to ensure LILO loaded us right
#define SIG1 0xAA55 #define SIG1 0xAA55
...@@ -79,23 +79,32 @@ type_of_loader: .byte 0 ! = 0, old one (LILO, Loadlin, ...@@ -79,23 +79,32 @@ type_of_loader: .byte 0 ! = 0, old one (LILO, Loadlin,
! T=3 for SYSLX ! T=3 for SYSLX
! T=4 for ETHERBOOT ! T=4 for ETHERBOOT
! V = version ! 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, LOADED_HIGH = 1 ! bit within loadflags,
! if set, then the kernel is loaded high ! if set, then the kernel is loaded high
CAN_USE_HEAP = 0x80 ! if set, the loader also has set heap_end_ptr CAN_USE_HEAP = 0x80 ! if set, the loader also has set heap_end_ptr
! to tell how much space behind setup.S ! to tell how much space behind setup.S
| can be used for heap purposes. | can be used for heap purposes.
! Only the loader knows what is free! ! 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 setup_move_size: .word 0x8000 ! size to move, when we (setup) are not
! loaded at 0x90000. We will move ourselves ! loaded at 0x90000. We will move ourselves
! to 0x90000 then just before jumping into ! to 0x90000 then just before jumping into
! the kernel. However, only the loader ! the kernel. However, only the loader
! know how much of data behind us also needs ! know how much of data behind us also needs
! to be loaded. ! 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. ! start address for 32-bit code.
! 0x1000 = default for zImage #ifndef __BIG_KERNEL__
! 0x100000 = default for 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 ramdisk_image: .long 0 ! address of loaded ramdisk image
! Here the loader (or kernel generator) puts ! Here the loader (or kernel generator) puts
! the 32-bit address were it loaded the image. ! 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) 1991, 1992 Linus Torvalds
* Copyright (C) 1997 Martin Mares
*/ */
/* /*
...@@ -20,103 +21,84 @@ ...@@ -20,103 +21,84 @@
* Changes by tytso to allow root device specification * Changes by tytso to allow root device specification
* High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
* Cross compiling fixes by Gertjan van Wingerde, July 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 <string.h>
#include <stdlib.h> /* contains exit */ #include <stdlib.h>
#include <sys/types.h> /* unistd.h needs this */ #include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/sysmacros.h> #include <sys/sysmacros.h>
#include <unistd.h> /* contains read/write */ #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <linux/a.out.h>
#include <linux/config.h> #include <linux/config.h>
#include <errno.h> #include <asm/boot.h>
#define MINIX_HEADER 32 typedef unsigned char byte;
typedef unsigned short word;
#define N_MAGIC_OFFSET 1024 typedef unsigned long u32;
#ifndef __BFD__
static int GCC_HEADER = sizeof(struct exec);
#endif
#ifdef __BIG_KERNEL__
#define SYS_SIZE 0xffff
#else
#define SYS_SIZE DEF_SYSSIZE
#endif
#define DEFAULT_MAJOR_ROOT 0 #define DEFAULT_MAJOR_ROOT 0
#define DEFAULT_MINOR_ROOT 0 #define DEFAULT_MINOR_ROOT 0
/* max nr of sectors of setup: don't change unless you also change /* Minimal number of setup sectors (see also bootsect.S) */
* bootsect etc */
#define SETUP_SECTS 4 #define SETUP_SECTS 4
#define STRINGIFY(x) #x byte buf[1024];
int fd;
typedef union { int is_big_kernel;
int i;
long l;
short s[2];
char b[4];
} conv;
long intel_long(long l) void die(const char * str, ...)
{ {
conv t; va_list args;
va_start(args, str);
t.b[0] = l & 0xff; l >>= 8; vfprintf(stderr, str, args);
t.b[1] = l & 0xff; l >>= 8; fputc('\n', stderr);
t.b[2] = l & 0xff; l >>= 8; exit(1);
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;
} }
short intel_short(short l) /* Reading of ld86 output (Minix format) */
{
conv t;
t.b[0] = l & 0xff; l >>= 8; #define MINIX_HEADER_LEN 32
t.b[1] = l & 0xff; l >>= 8;
return t.s[0];
}
void die(const char * str) int minix_open(const char *name)
{ {
fprintf(stderr,"%s\n",str); static byte hdr[] = { 0x01, 0x03, 0x10, 0x04, 0x20, 0x00, 0x00, 0x00 };
exit(1); 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) 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 main(int argc, char ** argv)
{ {
int i,c,id,sz,tmp_int; unsigned int i, c, sz, setup_sectors;
unsigned long sys_size, tmp_long; u32 sys_size;
char buf[1024]; byte major_root, minor_root;
#ifndef __BFD__
struct exec *ex = (struct exec *)buf;
#endif
char major_root, minor_root;
struct stat sb; 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)) if ((argc < 4) || (argc > 5))
usage(); usage();
if (argc > 4) { if (argc > 4) {
...@@ -143,147 +125,79 @@ int main(int argc, char ** argv) ...@@ -143,147 +125,79 @@ int main(int argc, char ** argv)
minor_root = DEFAULT_MINOR_ROOT; minor_root = DEFAULT_MINOR_ROOT;
} }
fprintf(stderr, "Root device is (%d, %d)\n", major_root, 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) minix_open(argv[1]); /* Copy the boot sector */
die("Unable to open 'boot'"); i = read(fd, buf, sizeof(buf));
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);
fprintf(stderr,"Boot sector %d bytes.\n",i); fprintf(stderr,"Boot sector %d bytes.\n",i);
if (i != 512) if (i != 512)
die("Boot block must be exactly 512 bytes"); 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)"); die("Boot block hasn't got boot flag (0xAA55)");
buf[508] = (char) minor_root; buf[508] = minor_root;
buf[509] = (char) major_root; buf[509] = major_root;
i=write(1,buf,512); if (write(1, buf, 512) != 512)
if (i!=512)
die("Write call failed"); die("Write call failed");
close (id); close (fd);
if ((id=open(argv[2],O_RDONLY,0))<0) minix_open(argv[2]); /* Copy the setup code */
die("Unable to open 'setup'"); for (i=0 ; (c=read(fd, buf, sizeof(buf)))>0 ; i+=c )
if (read(id,buf,MINIX_HEADER) != MINIX_HEADER) if (write(1, buf, c) != c)
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)
die("Write call failed"); die("Write call failed");
#ifdef __BIG_KERNEL__
}
#endif
if (c != 0) if (c != 0)
die("read-error on 'setup'"); die("read-error on `setup'");
close (id); close (fd);
setup_sectors = (unsigned char)((i + 511) / 512);
/* for compatibility with LILO */ setup_sectors = (i + 511) / 512; /* Pad unused space with zeros */
/* for compatibility with ancient versions of LILO */
if (setup_sectors < SETUP_SECTS) if (setup_sectors < SETUP_SECTS)
setup_sectors = SETUP_SECTS; setup_sectors = SETUP_SECTS;
fprintf(stderr,"Setup is %d bytes.\n",i); fprintf(stderr, "Setup is %d bytes.\n", i);
for (c=0 ; c<sizeof(buf) ; c++) memset(buf, sizeof(buf), 0);
buf[c] = '\0';
while (i < setup_sectors * 512) { while (i < setup_sectors * 512) {
c = setup_sectors * 512 - i; c = setup_sectors * 512 - i;
if (c > sizeof(buf)) if (c > sizeof(buf))
c = sizeof(buf); c = sizeof(buf);
if (write(1,buf,c) != c) if (write(1, buf, c) != c)
die("Write call failed"); die("Write call failed");
i += c; i += c;
} }
if ((id=open(argv[3],O_RDONLY,0))<0) if ((fd = open(argv[3], O_RDONLY, 0)) < 0) /* Copy the image itself */
die("Unable to open 'system'"); die("Unable to open `%s': %m", argv[3]);
#ifndef __BFD__ if (fstat (fd, &sb))
if (read(id,buf,GCC_HEADER) != GCC_HEADER) die("Unable to stat `%s': %m", argv[3]);
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'");
}
sz = sb.st_size; sz = sb.st_size;
fprintf (stderr, "System is %d kB\n", sz/1024); fprintf (stderr, "System is %d kB\n", sz/1024);
#endif
sys_size = (sz + 15) / 16; sys_size = (sz + 15) / 16;
if (sys_size > SYS_SIZE) if (sys_size > (is_big_kernel ? 0xffff : DEF_SYSSIZE))
die("System is too big"); die("System is too big");
while (sz > 0) { while (sz > 0) {
int l, n; int l, n;
l = sz; l = (sz > sizeof(buf)) ? sizeof(buf) : sz;
if (l > sizeof(buf)) if ((n=read(fd, buf, l)) != l) {
l = sizeof(buf); if (n < 0)
if ((n=read(id, buf, l)) != l) { die("Error reading %s: %m", argv[3]);
if (n == -1)
perror(argv[1]);
else else
fprintf(stderr, "Unexpected EOF\n"); die("%s: Unexpected EOF", argv[3]);
die("Can't read 'system'");
} }
if (write(1, buf, l) != l) if (write(1, buf, l) != l)
die("Write failed"); die("Write failed");
sz -= l; sz -= l;
} }
close(id); close(fd);
if (lseek(1, 497, 0) == 497) {
if (write(1, &setup_sectors, 1) != 1) if (lseek(1, 497, SEEK_SET) != 497) /* Write sizes to the bootsector */
die("Write of setup sectors failed"); die("Output: seek failed");
} buf[0] = setup_sectors;
if (lseek(1,500,0) == 500) { if (write(1, buf, 1) != 1)
buf[0] = (sys_size & 0xff); die("Write of setup sector count failed");
buf[1] = ((sys_size >> 8) & 0xff); if (lseek(1, 500, SEEK_SET) != 500)
if (write(1, buf, 2) != 2) die("Output: seek failed");
die("Write failed"); buf[0] = (sys_size & 0xff);
} buf[1] = ((sys_size >> 8) & 0xff);
return(0); if (write(1, buf, 2) != 2)
die("Write of image length failed");
return 0; /* Everything is OK */
} }
...@@ -59,6 +59,7 @@ ...@@ -59,6 +59,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/bios32.h> #include <linux/bios32.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/init.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/segment.h> #include <asm/segment.h>
...@@ -188,7 +189,7 @@ static struct { ...@@ -188,7 +189,7 @@ static struct {
} pci_indirect = { 0, KERNEL_CS }; } 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 long signature;
unsigned char present_status; unsigned char present_status;
...@@ -710,7 +711,7 @@ static struct pci_access pci_direct_conf2 = { ...@@ -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 int tmp;
unsigned long flags; unsigned long flags;
...@@ -863,14 +864,14 @@ const char *pcibios_strerror (int error) ...@@ -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; return mem_start;
} }
#endif #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 #ifdef CONFIG_PCI
union bios32 *check; union bios32 *check;
......
...@@ -89,7 +89,7 @@ startup_32: ...@@ -89,7 +89,7 @@ startup_32:
* Clear BSS first so that there are no surprises... * Clear BSS first so that there are no surprises...
*/ */
xorl %eax,%eax xorl %eax,%eax
movl $ SYMBOL_NAME(_edata),%edi movl $ SYMBOL_NAME(__bss_start),%edi
movl $ SYMBOL_NAME(_end),%ecx movl $ SYMBOL_NAME(_end),%ecx
subl %edi,%ecx subl %edi,%ecx
cld cld
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/random.h> #include <linux/random.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/init.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -35,6 +36,8 @@ ...@@ -35,6 +36,8 @@
#include <asm/smp.h> #include <asm/smp.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include "irq.h"
#ifdef __SMP_PROF__ #ifdef __SMP_PROF__
extern volatile unsigned long smp_local_timer_ticks[1+NR_CPUS]; extern volatile unsigned long smp_local_timer_ticks[1+NR_CPUS];
#endif #endif
...@@ -146,10 +149,8 @@ BUILD_IRQ(SECOND,15,0x80) ...@@ -146,10 +149,8 @@ BUILD_IRQ(SECOND,15,0x80)
BUILD_SMP_INTERRUPT(reschedule_interrupt) BUILD_SMP_INTERRUPT(reschedule_interrupt)
BUILD_SMP_INTERRUPT(invalidate_interrupt) BUILD_SMP_INTERRUPT(invalidate_interrupt)
BUILD_SMP_INTERRUPT(stop_cpu_interrupt) BUILD_SMP_INTERRUPT(stop_cpu_interrupt)
#ifdef __SMP_PROF__
BUILD_SMP_TIMER_INTERRUPT(apic_timer_interrupt) BUILD_SMP_TIMER_INTERRUPT(apic_timer_interrupt)
#endif #endif
#endif
/* /*
* Pointers to the low-level handlers: first the general ones, then the * Pointers to the low-level handlers: first the general ones, then the
...@@ -524,40 +525,6 @@ void __global_restore_flags(unsigned long flags) ...@@ -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 #endif
/* /*
...@@ -754,7 +721,7 @@ int probe_irq_off (unsigned long irqs) ...@@ -754,7 +721,7 @@ int probe_irq_off (unsigned long irqs)
return i; return i;
} }
void init_IRQ(void) __initfunc(void init_IRQ(void))
{ {
int i; int i;
static unsigned char smptrap=0; static unsigned char smptrap=0;
...@@ -777,19 +744,25 @@ void init_IRQ(void) ...@@ -777,19 +744,25 @@ void init_IRQ(void)
*/ */
#ifdef __SMP__ #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); 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); set_intr_gate(0x21+i, invalidate_interrupt);
/* IRQ '18' - IPI for CPU halt */ /* IRQ '18' (trap 0x40) - IPI for CPU halt */
set_intr_gate(0x22+i, stop_cpu_interrupt); set_intr_gate(0x30+i, stop_cpu_interrupt);
#ifdef __SMP_PROF__ /* IRQ '19' (trap 0x41) - self generated IPI for local APIC timer */
/* IRQ '19' - self generated IPI for local APIC timer */ set_intr_gate(0x31+i, apic_timer_interrupt);
set_intr_gate(0x23+i, apic_timer_interrupt);
#endif
#endif #endif
request_region(0x20,0x20,"pic1"); request_region(0x20,0x20,"pic1");
request_region(0xa0,0x20,"pic2"); 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 @@ ...@@ -23,6 +23,7 @@
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/init.h>
/* This structure holds MCA information. Each (plug-in) adapter has /* This structure holds MCA information. Each (plug-in) adapter has
* eight POS registers. Then the machine may have integrated video and * eight POS registers. Then the machine may have integrated video and
...@@ -78,7 +79,7 @@ static struct inode_operations proc_mca_inode_operations = { ...@@ -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; unsigned int i, j;
int foundscsi = 0; int foundscsi = 0;
...@@ -417,7 +418,7 @@ int get_mca_info(char *buf) ...@@ -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; int i = 0;
struct proc_dir_entry* node = 0; struct proc_dir_entry* node = 0;
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/config.h> #include <linux/config.h>
#include <linux/init.h>
#ifdef CONFIG_APM #ifdef CONFIG_APM
#include <linux/apm_bios.h> #include <linux/apm_bios.h>
#endif #endif
...@@ -115,8 +116,8 @@ extern char empty_zero_page[PAGE_SIZE]; ...@@ -115,8 +116,8 @@ extern char empty_zero_page[PAGE_SIZE];
static char command_line[COMMAND_LINE_SIZE] = { 0, }; static char command_line[COMMAND_LINE_SIZE] = { 0, };
char saved_command_line[COMMAND_LINE_SIZE]; char saved_command_line[COMMAND_LINE_SIZE];
void setup_arch(char **cmdline_p, __initfunc(void setup_arch(char **cmdline_p,
unsigned long * memory_start_p, unsigned long * memory_end_p) unsigned long * memory_start_p, unsigned long * memory_end_p))
{ {
unsigned long memory_start, memory_end; unsigned long memory_start, memory_end;
char c = ' ', *to = command_line, *from = COMMAND_LINE; char c = ' ', *to = command_line, *from = COMMAND_LINE;
......
...@@ -39,12 +39,15 @@ ...@@ -39,12 +39,15 @@
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/init.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/bitops.h> #include <asm/bitops.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/smp.h> #include <asm/smp.h>
#include <asm/io.h> #include <asm/io.h>
#include "irq.h"
extern unsigned long start_kernel, _etext; extern unsigned long start_kernel, _etext;
void setup_APIC_clock (void); void setup_APIC_clock (void);
...@@ -170,7 +173,7 @@ volatile int smp_process_available=0; ...@@ -170,7 +173,7 @@ volatile int smp_process_available=0;
* SMP mode to <NUM>. * SMP mode to <NUM>.
*/ */
void smp_setup(char *str, int *ints) __initfunc(void smp_setup(char *str, int *ints))
{ {
if (ints && ints[0] > 0) if (ints && ints[0] > 0)
max_cpus = ints[1]; max_cpus = ints[1];
...@@ -232,7 +235,7 @@ static char *mpc_family(int family,int model) ...@@ -232,7 +235,7 @@ static char *mpc_family(int family,int model)
* Read the MPC * 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]; char str[16];
int count=sizeof(*mpc); int count=sizeof(*mpc);
...@@ -377,7 +380,7 @@ static int smp_read_mpc(struct mp_config_table *mpc) ...@@ -377,7 +380,7 @@ static int smp_read_mpc(struct mp_config_table *mpc)
* Scan the memory blocks for an SMP configuration block. * 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); unsigned long *bp=phys_to_virt(base);
struct intel_mp_floating *mpf; struct intel_mp_floating *mpf;
...@@ -535,7 +538,7 @@ extern unsigned char trampoline_end []; ...@@ -535,7 +538,7 @@ extern unsigned char trampoline_end [];
* has made sure it's suitably aligned. * 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); memcpy(mp, trampoline_data, trampoline_end - trampoline_data);
} }
...@@ -547,7 +550,7 @@ static void install_trampoline(unsigned char *mp) ...@@ -547,7 +550,7 @@ static void install_trampoline(unsigned char *mp)
* other things). * 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 */ int size=(num_processors-1)*PAGE_SIZE; /* Number of stacks needed */
...@@ -568,7 +571,7 @@ unsigned long smp_alloc_memory(unsigned long mem_base) ...@@ -568,7 +571,7 @@ unsigned long smp_alloc_memory(unsigned long mem_base)
* Hand out stacks one at a time. * Hand out stacks one at a time.
*/ */
static void *get_kernel_stack(void) __initfunc(static void *get_kernel_stack(void))
{ {
void *stack=kstack_base; void *stack=kstack_base;
if(kstack_base>=kstack_end) if(kstack_base>=kstack_end)
...@@ -583,7 +586,7 @@ static void *get_kernel_stack(void) ...@@ -583,7 +586,7 @@ static void *get_kernel_stack(void)
* a given CPU * 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]; struct cpuinfo_x86 *c=&cpu_data[id];
c->hard_math=hard_math; /* Always assumed same currently */ c->hard_math=hard_math; /* Always assumed same currently */
...@@ -614,7 +617,7 @@ void smp_store_cpu_info(int id) ...@@ -614,7 +617,7 @@ void smp_store_cpu_info(int id)
* we use to track CPU's as they power up. * 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. * Lets the callin's below out of their loop.
...@@ -623,7 +626,7 @@ void smp_commence(void) ...@@ -623,7 +626,7 @@ void smp_commence(void)
smp_commenced=1; smp_commenced=1;
} }
void smp_callin(void) __initfunc(void smp_callin(void))
{ {
extern void calibrate_delay(void); extern void calibrate_delay(void);
int cpuid=GET_APIC_ID(apic_read(APIC_ID)); int cpuid=GET_APIC_ID(apic_read(APIC_ID));
...@@ -687,7 +690,7 @@ void smp_callin(void) ...@@ -687,7 +690,7 @@ void smp_callin(void)
* Cycle through the processors sending APIC IPI's to boot each. * 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 i;
int cpucount=0; int cpucount=0;
...@@ -1093,6 +1096,7 @@ void smp_boot_cpus(void) ...@@ -1093,6 +1096,7 @@ void smp_boot_cpus(void)
void smp_message_pass(int target, int msg, unsigned long data, int wait) void smp_message_pass(int target, int msg, unsigned long data, int wait)
{ {
unsigned long flags;
unsigned long cfg; unsigned long cfg;
unsigned long target_map; unsigned long target_map;
int p=smp_processor_id(); int p=smp_processor_id();
...@@ -1121,11 +1125,12 @@ void smp_message_pass(int target, int msg, unsigned long data, int wait) ...@@ -1121,11 +1125,12 @@ void smp_message_pass(int target, int msg, unsigned long data, int wait)
break; break;
case MSG_INVALIDATE_TLB: case MSG_INVALIDATE_TLB:
/* make this a NMI some day */
irq = 0x31; irq = 0x31;
break; break;
case MSG_STOP_CPU: case MSG_STOP_CPU:
irq = 0x32; irq = 0x40;
break; break;
default: default:
...@@ -1168,15 +1173,15 @@ void smp_message_pass(int target, int msg, unsigned long data, int wait) ...@@ -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 * Just pray... there is nothing more we can do
*/ */
if(ct==1000) { if(ct==1000)
printk("CPU #%d: previous IPI still not cleared after 10mS", p); printk("CPU #%d: previous IPI still not cleared after 10mS\n", p);
ack_APIC_irq ();
}
/* /*
* Program the APIC to deliver the IPI * Program the APIC to deliver the IPI
*/ */
__save_flags(flags);
__cli();
cfg=apic_read(APIC_ICR2); cfg=apic_read(APIC_ICR2);
cfg&=0x00FFFFFF; cfg&=0x00FFFFFF;
apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(target)); /* Target chip */ 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) ...@@ -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. * 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 * Spin waiting for completion
...@@ -1300,36 +1306,6 @@ void smp_flush_tlb(void) ...@@ -1300,36 +1306,6 @@ void smp_flush_tlb(void)
/* printk("SMID\n");*/ /* 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. * Platform specific profiling function.
* it builds a 'prof_shift' resolution EIP distribution histogram * it builds a 'prof_shift' resolution EIP distribution histogram
...@@ -1337,7 +1313,7 @@ asmlinkage void smp_stop_cpu_interrupt(void) ...@@ -1337,7 +1313,7 @@ asmlinkage void smp_stop_cpu_interrupt(void)
* it's SMP safe. * 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) { if (prof_buffer && current->pid) {
extern int _stext; extern int _stext;
...@@ -1394,9 +1370,6 @@ static inline void smp_local_timer_interrupt(struct pt_regs * regs) ...@@ -1394,9 +1370,6 @@ static inline void smp_local_timer_interrupt(struct pt_regs * regs)
* *
* kernel statistics counters are updated via atomic * kernel statistics counters are updated via atomic
* operations. * operations.
*
* update_one_process() might send signals, thus
* we have to get the irq lock for that one.
*/ */
if (user_mode(regs)) if (user_mode(regs))
...@@ -1405,12 +1378,7 @@ static inline void smp_local_timer_interrupt(struct pt_regs * regs) ...@@ -1405,12 +1378,7 @@ static inline void smp_local_timer_interrupt(struct pt_regs * regs)
system=1; system=1;
if (p->pid) { if (p->pid) {
unsigned long flags; update_one_process(p, 1, user, system);
save_flags(flags);
cli();
update_one_process(current, 1, user, system);
restore_flags(flags);
p->counter -= 1; p->counter -= 1;
if (p->counter < 0) { if (p->counter < 0) {
...@@ -1464,9 +1432,63 @@ static inline void smp_local_timer_interrupt(struct pt_regs * regs) ...@@ -1464,9 +1432,63 @@ static inline void smp_local_timer_interrupt(struct pt_regs * regs)
*/ */
void smp_apic_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); 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 (); 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) ...@@ -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 * but we do not accept timer interrupts yet. We only allow the BP
* to calibrate. * to calibrate.
*/ */
unsigned int get_8254_timer_count (void) static unsigned int get_8254_timer_count (void)
{ {
unsigned int count; unsigned int count;
...@@ -1524,11 +1546,11 @@ void setup_APIC_timer (unsigned int clocks) ...@@ -1524,11 +1546,11 @@ void setup_APIC_timer (unsigned int clocks)
* mode. With the IO APIC we can re-route the external timer * 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. * 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 ;) * should be the same ;)
*/ */
tmp_value = apic_read(APIC_LVTT); 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); apic_write(APIC_LVTT , lvtt1_value);
/* /*
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/init.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -369,7 +370,7 @@ static long last_rtc_update = 0; ...@@ -369,7 +370,7 @@ static long last_rtc_update = 0;
* Move this to a header file - right now it shows * Move this to a header file - right now it shows
* up both here and in smp.c * 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) { if (prof_buffer && current->pid) {
extern int _stext; extern int _stext;
...@@ -415,11 +416,13 @@ static inline void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -415,11 +416,13 @@ static inline void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
last_rtc_update = xtime.tv_sec; last_rtc_update = xtime.tv_sec;
else else
last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ 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 /* 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 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 rigged to be safe on the 386 - basically it's a hack, so don't look
closely for now.. */ closely for now.. */
smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0); smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0);
#endif
#ifdef CONFIG_MCA #ifdef CONFIG_MCA
if( MCA_bus ) { if( MCA_bus ) {
...@@ -528,7 +531,7 @@ unsigned long get_cmos_time(void) ...@@ -528,7 +531,7 @@ unsigned long get_cmos_time(void)
static struct irqaction irq0 = { timer_interrupt, 0, 0, "timer", NULL, NULL}; 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_sec = get_cmos_time();
xtime.tv_usec = 0; xtime.tv_usec = 0;
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/init.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -375,7 +376,7 @@ asmlinkage void math_emulate(long arg) ...@@ -375,7 +376,7 @@ asmlinkage void math_emulate(long arg)
#endif /* CONFIG_MATH_EMULATION */ #endif /* CONFIG_MATH_EMULATION */
void trap_init(void) __initfunc(void trap_init(void))
{ {
int i; int i;
struct desc_struct * p; struct desc_struct * p;
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/swap.h> #include <linux/swap.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/init.h>
#ifdef CONFIG_BLK_DEV_INITRD #ifdef CONFIG_BLK_DEV_INITRD
#include <linux/blk.h> #include <linux/blk.h>
#endif #endif
...@@ -96,6 +97,11 @@ void show_mem(void) ...@@ -96,6 +97,11 @@ void show_mem(void)
extern unsigned long free_area_init(unsigned long, unsigned long); 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 * paging_init() sets up the page tables - note that the first 4MB are
* already mapped by head.S. * already mapped by head.S.
...@@ -103,7 +109,7 @@ extern unsigned long free_area_init(unsigned long, unsigned long); ...@@ -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 * This routines also unmaps the page at virtual kernel address 0, so
* that we can trap those pesky NULL-reference errors in the kernel. * 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; pgd_t * pg_dir;
pte_t * pg_table; pte_t * pg_table;
...@@ -202,14 +208,14 @@ unsigned long paging_init(unsigned long start_mem, unsigned long end_mem) ...@@ -202,14 +208,14 @@ unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
return free_area_init(start_mem, 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; unsigned long start_low_mem = PAGE_SIZE;
int codepages = 0; int codepages = 0;
int reservedpages = 0; int reservedpages = 0;
int datapages = 0; int datapages = 0;
int initpages = 0;
unsigned long tmp; unsigned long tmp;
extern int _etext;
end_mem &= PAGE_MASK; end_mem &= PAGE_MASK;
high_memory = (void *) end_mem; high_memory = (void *) end_mem;
...@@ -251,12 +257,19 @@ void mem_init(unsigned long start_mem, unsigned long end_mem) ...@@ -251,12 +257,19 @@ void mem_init(unsigned long start_mem, unsigned long end_mem)
if (tmp >= MAX_DMA_ADDRESS) if (tmp >= MAX_DMA_ADDRESS)
clear_bit(PG_DMA, &mem_map[MAP_NR(tmp)].flags); clear_bit(PG_DMA, &mem_map[MAP_NR(tmp)].flags);
if (PageReserved(mem_map+MAP_NR(tmp))) { if (PageReserved(mem_map+MAP_NR(tmp))) {
if (tmp >= 0xA0000+PAGE_OFFSET && tmp < 0x100000+PAGE_OFFSET) if (tmp >= (unsigned long) &_text && tmp < (unsigned long) &_edata) {
reservedpages++; if (tmp < (unsigned long) &_etext)
else if (tmp < (unsigned long) &_etext) codepages++;
codepages++; else
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++; datapages++;
else
reservedpages++;
continue; continue;
} }
atomic_set(&mem_map[MAP_NR(tmp)].count, 1); atomic_set(&mem_map[MAP_NR(tmp)].count, 1);
...@@ -266,12 +279,13 @@ void mem_init(unsigned long start_mem, unsigned long end_mem) ...@@ -266,12 +279,13 @@ void mem_init(unsigned long start_mem, unsigned long end_mem)
#endif #endif
free_page(tmp); 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), (unsigned long) nr_free_pages << (PAGE_SHIFT-10),
max_mapnr << (PAGE_SHIFT-10), max_mapnr << (PAGE_SHIFT-10),
codepages << (PAGE_SHIFT-10), codepages << (PAGE_SHIFT-10),
reservedpages << (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 */ /* test if the WP bit is honoured in supervisor mode */
if (wp_works_ok < 0) { if (wp_works_ok < 0) {
unsigned char tmp_reg; unsigned char tmp_reg;
...@@ -300,7 +314,14 @@ void mem_init(unsigned long start_mem, unsigned long end_mem) ...@@ -300,7 +314,14 @@ void mem_init(unsigned long start_mem, unsigned long end_mem)
void free_initmem(void) 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) 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 @@ ...@@ -56,6 +56,13 @@
#include <asm/system.h> #include <asm/system.h>
#include <asm/poll.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 * We sponge a minor off of the misc major. No need slurping
* up another valuable major dev number for this. If you add * 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, ...@@ -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)); 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 */ mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */
day = rtc_tm.tm_mday; day = rtc_tm.tm_mday;
hrs = rtc_tm.tm_hour; hrs = rtc_tm.tm_hour;
...@@ -725,6 +732,9 @@ void get_rtc_time(struct rtc_time *rtc_tm) ...@@ -725,6 +732,9 @@ void get_rtc_time(struct rtc_time *rtc_tm)
if (rtc_tm->tm_year <= 69) if (rtc_tm->tm_year <= 69)
rtc_tm->tm_year += 100; rtc_tm->tm_year += 100;
/* if ARCFUDGE == 0, the optimizer should do away with this */
rtc_tm->tm_year -= ARCFUDGE;
rtc_tm->tm_mon--; rtc_tm->tm_mon--;
} }
......
torvalds@penguin.transmeta.com
\ No newline at end of file
...@@ -491,7 +491,7 @@ struct inode * get_empty_inode(void) ...@@ -491,7 +491,7 @@ struct inode * get_empty_inode(void)
inode = first_inode; inode = first_inode;
best = NULL; best = NULL;
badness = 1000; 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) { if (!inode->i_count) {
unsigned long i = 999; unsigned long i = 999;
if (!(inode->i_lock | inode->i_dirt)) if (!(inode->i_lock | inode->i_dirt))
......
...@@ -18,7 +18,7 @@ typedef struct { int counter; } atomic_t; ...@@ -18,7 +18,7 @@ typedef struct { int counter; } atomic_t;
#define ATOMIC_INIT { 0 } #define ATOMIC_INIT { 0 }
#define atomic_read(v) ((v)->counter) #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 * Make sure gcc doesn't try to be clever and move things around
......
...@@ -136,4 +136,7 @@ ...@@ -136,4 +136,7 @@
#define ERESTART 127 /* Interrupted system call should be restarted */ #define ERESTART 127 /* Interrupted system call should be restarted */
#define ESTRPIPE 128 /* Streams pipe error */ #define ESTRPIPE 128 /* Streams pipe error */
#define ENOMEDIUM 129 /* No medium found */
#define EMEDIUMTYPE 130 /* Wrong medium type */
#endif #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 @@ ...@@ -24,43 +24,4 @@
extern void disable_irq(unsigned int); extern void disable_irq(unsigned int);
extern void enable_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 #endif
...@@ -24,18 +24,35 @@ extern void __up(struct semaphore * sem); ...@@ -24,18 +24,35 @@ extern void __up(struct semaphore * sem);
#define sema_init(sem, val) atomic_set(&((sem)->count), val) #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) static inline int waking_non_zero(struct semaphore *sem)
{ {
unsigned long flags; int ret, tmp;
int ret = 0;
__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; return ret;
} }
......
...@@ -34,10 +34,12 @@ typedef struct { ...@@ -34,10 +34,12 @@ typedef struct {
typedef struct { unsigned long a[100]; } __dummy_lock_t; typedef struct { unsigned long a[100]; } __dummy_lock_t;
#define __dummy_lock(lock) (*(__dummy_lock_t *)(lock)) #define __dummy_lock(lock) (*(__dummy_lock_t *)(lock))
#define spin_unlock(lock) \ static inline void spin_unlock(spinlock_t * lock)
__asm__ __volatile__( \ {
"mb; stq $31,%0" \ __asm__ __volatile__(
:"=m" (__dummy_lock(lock))) "mb; stq $31,%0"
:"=m" (__dummy_lock(lock)));
}
static inline void spin_lock(spinlock_t * 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 @@ ...@@ -19,226 +19,4 @@
extern void disable_irq(unsigned int); extern void disable_irq(unsigned int);
extern void enable_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 */ #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 @@ ...@@ -27,17 +27,4 @@
* in linux/version.h, and should only be used by linux/version.c * 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 #endif
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#define asmlinkage #define asmlinkage
#endif #endif
#ifdef __ELF__
#define SYMBOL_NAME_STR(X) #X #define SYMBOL_NAME_STR(X) #X
#define SYMBOL_NAME(X) X #define SYMBOL_NAME(X) X
#ifdef __STDC__ #ifdef __STDC__
...@@ -15,33 +14,13 @@ ...@@ -15,33 +14,13 @@
#else #else
#define SYMBOL_NAME_LABEL(X) X/**/: #define SYMBOL_NAME_LABEL(X) X/**/:
#endif #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__) #if !defined(__i486__) && !defined(__i586__)
#ifdef __ELF__
#define __ALIGN .align 4,0x90 #define __ALIGN .align 4,0x90
#define __ALIGN_STR ".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__ */ #else /* __i486__/__i586__ */
#ifdef __ELF__
#define __ALIGN .align 16,0x90 #define __ALIGN .align 16,0x90
#define __ALIGN_STR ".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__ */ #endif /* __i486__/__i586__ */
#ifdef __ASSEMBLY__ #ifdef __ASSEMBLY__
......
...@@ -104,6 +104,17 @@ struct sched_param { ...@@ -104,6 +104,17 @@ struct sched_param {
#ifdef __KERNEL__ #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 sched_init(void);
extern void show_state(void); extern void show_state(void);
extern void trap_init(void); extern void trap_init(void);
...@@ -460,11 +471,11 @@ extern inline void poll_wait(struct wait_queue ** wait_address, poll_table * p) ...@@ -460,11 +471,11 @@ extern inline void poll_wait(struct wait_queue ** wait_address, poll_table * p)
p->nr++; p->nr++;
} }
#define REMOVE_LINKS(p) do { unsigned long flags; \ #define REMOVE_LINKS(p) do { \
save_flags(flags) ; cli(); \ spin_lock(&tasklist_lock); \
(p)->next_task->prev_task = (p)->prev_task; \ (p)->next_task->prev_task = (p)->prev_task; \
(p)->prev_task->next_task = (p)->next_task; \ (p)->prev_task->next_task = (p)->next_task; \
restore_flags(flags); \ spin_unlock(&tasklist_lock); \
if ((p)->p_osptr) \ if ((p)->p_osptr) \
(p)->p_osptr->p_ysptr = (p)->p_ysptr; \ (p)->p_osptr->p_ysptr = (p)->p_ysptr; \
if ((p)->p_ysptr) \ if ((p)->p_ysptr) \
...@@ -473,13 +484,13 @@ extern inline void poll_wait(struct wait_queue ** wait_address, poll_table * p) ...@@ -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; \ (p)->p_pptr->p_cptr = (p)->p_osptr; \
} while (0) } while (0)
#define SET_LINKS(p) do { unsigned long flags; \ #define SET_LINKS(p) do { \
save_flags(flags); cli(); \ spin_lock(&tasklist_lock); \
(p)->next_task = &init_task; \ (p)->next_task = &init_task; \
(p)->prev_task = init_task.prev_task; \ (p)->prev_task = init_task.prev_task; \
init_task.prev_task->next_task = (p); \ init_task.prev_task->next_task = (p); \
init_task.prev_task = (p); \ init_task.prev_task = (p); \
restore_flags(flags); \ spin_unlock(&tasklist_lock); \
(p)->p_ysptr = NULL; \ (p)->p_ysptr = NULL; \
if (((p)->p_osptr = (p)->p_pptr->p_cptr) != NULL) \ if (((p)->p_osptr = (p)->p_pptr->p_cptr) != NULL) \
(p)->p_osptr->p_ysptr = p; \ (p)->p_osptr->p_ysptr = p; \
......
...@@ -129,9 +129,7 @@ rpc_set_timeout(struct rpc_clnt *clnt, unsigned int retr, unsigned long incr) ...@@ -129,9 +129,7 @@ rpc_set_timeout(struct rpc_clnt *clnt, unsigned int retr, unsigned long incr)
/* /*
* Helper function for NFSroot support * Helper function for NFSroot support
*/ */
#ifdef CONFIG_ROOT_NFS
int rpc_getport_external(struct sockaddr_in *, __u32, __u32, int); int rpc_getport_external(struct sockaddr_in *, __u32, __u32, int);
#endif
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* _LINUX_SUNRPC_CLNT_H */ #endif /* _LINUX_SUNRPC_CLNT_H */
...@@ -17,6 +17,9 @@ ...@@ -17,6 +17,9 @@
/* /*
* Modification history timex.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 * 26 Sep 94 David L. Mills
* Added defines for hybrid phase/frequency-lock loop. * Added defines for hybrid phase/frequency-lock loop.
* *
...@@ -122,15 +125,16 @@ ...@@ -122,15 +125,16 @@
#define PPS_VALID 120 /* pps signal watchdog max (s) */ #define PPS_VALID 120 /* pps signal watchdog max (s) */
#define MAXGLITCH 30 /* pps signal glitch 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__ #ifndef __alpha__
/* /*
* This definitively is wrong for the Alpha and none of the * This definitively is wrong for the Alpha and none of the
* kernel code seems to reference this anymore. * 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 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) * \ #define FINETUNE ((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \
(1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \ (1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \
<< (SHIFT_SCALE-SHIFT_HZ)) / HZ) << (SHIFT_SCALE-SHIFT_HZ)) / HZ)
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/major.h> #include <linux/major.h>
#include <linux/blk.h> #include <linux/blk.h>
#include <linux/init.h>
#ifdef CONFIG_ROOT_NFS #ifdef CONFIG_ROOT_NFS
#include <linux/nfs_fs.h> #include <linux/nfs_fs.h>
#endif #endif
...@@ -256,7 +257,7 @@ extern void dquot_init(void); ...@@ -256,7 +257,7 @@ extern void dquot_init(void);
static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, }; static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
static char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", 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; char *cur = str;
int i=1; int i=1;
...@@ -270,7 +271,7 @@ char *get_options(char *str, int *ints) ...@@ -270,7 +271,7 @@ char *get_options(char *str, int *ints)
return(cur); return(cur);
} }
static void profile_setup(char *str, int *ints) __initfunc(static void profile_setup(char *str, int *ints))
{ {
if (ints[0] > 0) if (ints[0] > 0)
prof_shift = (unsigned long) ints[1]; prof_shift = (unsigned long) ints[1];
...@@ -285,7 +286,7 @@ static void profile_setup(char *str, int *ints) ...@@ -285,7 +286,7 @@ static void profile_setup(char *str, int *ints)
struct { struct {
const char *str; const char *str;
void (*setup_func)(char *, int *); void (*setup_func)(char *, int *);
} bootsetups[] = { } bootsetups[] __initdata = {
{ "reserve=", reserve_setup }, { "reserve=", reserve_setup },
{ "profile=", profile_setup }, { "profile=", profile_setup },
#ifdef __SMP__ #ifdef __SMP__
...@@ -502,25 +503,25 @@ struct { ...@@ -502,25 +503,25 @@ struct {
}; };
#ifdef CONFIG_BLK_DEV_RAM #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) if (ints[0] > 0 && ints[1] >= 0)
rd_image_start = ints[1]; 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) if (ints[0] > 0 && ints[1] >= 0)
rd_doload = ints[1] & 1; 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) if (ints[0] > 0 && ints[1] >= 0)
rd_prompt = ints[1] & 1; 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) if (ints[0] > 0 && ints[1] >= 0)
rd_size = ints[1]; rd_size = ints[1];
...@@ -528,7 +529,7 @@ static void ramdisk_size(char *str, int *ints) ...@@ -528,7 +529,7 @@ static void ramdisk_size(char *str, int *ints)
#endif #endif
static int checksetup(char *line) __initfunc(static int checksetup(char *line))
{ {
int i = 0; int i = 0;
int ints[11]; int ints[11];
...@@ -560,7 +561,7 @@ unsigned long loops_per_sec = (1<<12); ...@@ -560,7 +561,7 @@ unsigned long loops_per_sec = (1<<12);
better than 1% */ better than 1% */
#define LPS_PREC 8 #define LPS_PREC 8
void calibrate_delay(void) __initfunc(void calibrate_delay(void))
{ {
unsigned long ticks, loopbit; unsigned long ticks, loopbit;
int lps_precision = LPS_PREC; int lps_precision = LPS_PREC;
...@@ -603,7 +604,7 @@ void calibrate_delay(void) ...@@ -603,7 +604,7 @@ void calibrate_delay(void)
((loops_per_sec+2500)/5000) % 100); ((loops_per_sec+2500)/5000) % 100);
} }
static void parse_root_dev(char * line) __initfunc(static void parse_root_dev(char * line))
{ {
int base = 0; int base = 0;
static struct dev_name_struct { static struct dev_name_struct {
...@@ -674,7 +675,7 @@ static void parse_root_dev(char * line) ...@@ -674,7 +675,7 @@ static void parse_root_dev(char * line)
* This routine also checks for options meant for the kernel. * This routine also checks for options meant for the kernel.
* These options are not given to init - they are for internal kernel use only. * 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; char *next;
int args, envs; int args, envs;
...@@ -782,7 +783,7 @@ extern int cpu_idle(void * unused); ...@@ -782,7 +783,7 @@ extern int cpu_idle(void * unused);
* Activate a secondary processor. * Activate a secondary processor.
*/ */
asmlinkage void start_secondary(void) __initfunc(asmlinkage void start_secondary(void))
{ {
trap_init(); trap_init();
init_IRQ(); init_IRQ();
...@@ -793,7 +794,7 @@ asmlinkage void start_secondary(void) ...@@ -793,7 +794,7 @@ asmlinkage void start_secondary(void)
/* Called by boot processor to activate the rest. */ /* Called by boot processor to activate the rest. */
static void smp_init(void) __initfunc(static void smp_init(void))
{ {
int i, j; int i, j;
...@@ -823,7 +824,7 @@ static void smp_init(void) ...@@ -823,7 +824,7 @@ static void smp_init(void)
* they are finished. * they are finished.
*/ */
static void smp_begin(void) __initfunc(static void smp_begin(void))
{ {
smp_threads_ready=1; smp_threads_ready=1;
smp_commence(); smp_commence();
...@@ -835,7 +836,7 @@ static void smp_begin(void) ...@@ -835,7 +836,7 @@ static void smp_begin(void)
* Activate the first processor. * Activate the first processor.
*/ */
asmlinkage void start_kernel(void) __initfunc(asmlinkage void start_kernel(void))
{ {
char * command_line; char * command_line;
...@@ -947,7 +948,7 @@ asmlinkage void start_kernel(void) ...@@ -947,7 +948,7 @@ asmlinkage void start_kernel(void)
} }
#ifdef CONFIG_BLK_DEV_INITRD #ifdef CONFIG_BLK_DEV_INITRD
static int do_linuxrc(void * shell) __initfunc(static int do_linuxrc(void * shell))
{ {
static char *argv[] = { "linuxrc", NULL, }; static char *argv[] = { "linuxrc", NULL, };
...@@ -959,7 +960,7 @@ static int do_linuxrc(void * shell) ...@@ -959,7 +960,7 @@ static int do_linuxrc(void * shell)
return execve(shell, argv, envp_init); 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; mount_initrd = 0;
} }
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
* current-task * current-task
*/ */
#include <linux/config.h>
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/timer.h> #include <linux/timer.h>
...@@ -188,6 +187,10 @@ static inline void move_last_runqueue(struct task_struct * p) ...@@ -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 * The scheduler lock is protecting against multiple entry
* into the scheduling code, and doesn't need to worry * into the scheduling code, and doesn't need to worry
* about interrupts (because interrupts cannot call the * about interrupts (because interrupts cannot call the
...@@ -196,6 +199,7 @@ static inline void move_last_runqueue(struct task_struct * p) ...@@ -196,6 +199,7 @@ static inline void move_last_runqueue(struct task_struct * p)
* The run-queue lock locks the parts that actually access * The run-queue lock locks the parts that actually access
* and change the run-queues, and have to be interrupt-safe. * 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; spinlock_t scheduler_lock = SPIN_LOCK_UNLOCKED;
static spinlock_t runqueue_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 ...@@ -300,7 +304,6 @@ static inline int goodness(struct task_struct * p, struct task_struct * prev, in
*/ */
asmlinkage void schedule(void) asmlinkage void schedule(void)
{ {
static int need_recalculate = 0;
int lock_depth; int lock_depth;
struct task_struct * prev, * next; struct task_struct * prev, * next;
unsigned long timeout; unsigned long timeout;
...@@ -384,7 +387,15 @@ asmlinkage void schedule(void) ...@@ -384,7 +387,15 @@ asmlinkage void schedule(void)
} }
p = p->next_run; 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) ...@@ -410,16 +421,7 @@ asmlinkage void schedule(void)
} }
spin_unlock(&scheduler_lock); spin_unlock(&scheduler_lock);
if (lock_depth) { reaquire_kernel_lock(prev, smp_processor_id(), 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;
}
}
} }
#ifndef __alpha__ #ifndef __alpha__
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
* Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
*/ */
#include <linux/config.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/socket.h> #include <linux/socket.h>
#include <linux/kernel.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