]> git.neil.brown.name Git - history.git/commitdiff
Import 2.3.12pre3 2.3.12pre3
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:26:23 +0000 (15:26 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:26:23 +0000 (15:26 -0500)
46 files changed:
Documentation/IO-APIC.txt
arch/alpha/kernel/entry.S
arch/arm/kernel/calls.S
arch/i386/kernel/entry.S
arch/i386/kernel/io_apic.c
arch/i386/kernel/irq.h
arch/i386/kernel/process.c
arch/i386/kernel/smp.c
arch/i386/mm/fault.c
arch/m68k/kernel/entry.S
arch/mips/kernel/syscalls.h
arch/ppc/kernel/misc.S
arch/sparc/kernel/systbls.S
arch/sparc64/kernel/systbls.S
fs/exec.c
include/asm-alpha/siginfo.h
include/asm-alpha/unistd.h
include/asm-arm/siginfo.h
include/asm-arm/unistd.h
include/asm-i386/apic.h [new file with mode: 0644]
include/asm-i386/fixmap.h
include/asm-i386/i82489.h [deleted file]
include/asm-i386/mmu_context.h
include/asm-i386/processor.h
include/asm-i386/siginfo.h
include/asm-i386/smp.h
include/asm-i386/unistd.h
include/asm-m68k/siginfo.h
include/asm-m68k/unistd.h
include/asm-mips/siginfo.h
include/asm-mips/unistd.h
include/asm-ppc/siginfo.h
include/asm-ppc/unistd.h
include/asm-sparc/siginfo.h
include/asm-sparc/unistd.h
include/asm-sparc64/siginfo.h
include/asm-sparc64/unistd.h
include/linux/limits.h
include/linux/sched.h
include/linux/time.h
kernel/exit.c
kernel/fork.c
kernel/itimer.c
kernel/sched.c
kernel/signal.c
kernel/time.c

index 76b939e8a317db0ddd82396d54dd1d3509455059..1a7dbd4104290f1b95b8367138a14b84ceb760e4 100644 (file)
@@ -1,51 +1,41 @@
-Most (all) Intel SMP boards have the so-called 'IO-APIC', which is
-an enhanced interrupt controller, able to route hardware interrupts
-to multiple CPUs, or to CPU groups.
+Most (all) Intel-MP compliant SMP boards have the so-called 'IO-APIC',
+which is an enhanced interrupt controller, it enables us to route
+hardware interrupts to multiple CPUs, or to CPU groups.
 
-Linux supports the IO-APIC, but unfortunately there are broken boards
-out there which make it unsafe to enable the IO-APIC unconditionally.
-The Linux policy thus is to enable the IO-APIC only if it's 100% safe, ie.:
+Linux supports all variants of compliant SMP boards, including ones with
+multiple IO-APICs. (multiple IO-APICs are used in high-end servers to
+distribute IRQ load further).
 
-          - the board is on the 'whitelist'
+There are (a few) known breakages in certain older boards, which bugs are
+usually worked around by the kernel. If your MP-compliant SMP board does
+not boot Linux, then consult the linux-smp mailing list archives first.
 
-       or - the board does not have PCI pins connected to the IO-APIC
-
-       or - the user has overridden blacklisted settings with the
-            pirq= boot option line.
-
-Kernel messages tell you whether the board is 'safe'. If your box
-boots with enabled IO-APIC IRQs, then you have nothing else to do. Your
+If your box boots fine with enabled IO-APIC IRQs, then your
 /proc/interrupts will look like this one:
 
    ---------------------------->
-   hell:~> cat /proc/interrupts
-              CPU0       CPU1
-     0:      90782          0   XT PIC   timer
-     1:       4135       2375  IO-APIC   keyboard
-     2:          0          0   XT PIC   cascade
-     3:        851        807  IO-APIC   serial
-     9:          6         22  IO-APIC   ncr53c8xx
-    11:        307        154  IO-APIC   NE2000
-    13:          4          0   XT PIC   fpu
-    14:      56000      30610  IO-APIC   ide0
-   NMI:          0
-   IPI:          0
-   <----------------------------
-
-some interrupts will still be 'XT PIC', but this is not a problem, none
-of those IRQ sources is 'heavy'.
-
-If one of your boot messages says 'unlisted/blacklisted board, DISABLING
-IO-APIC IRQs', then you should do this to get multi-CPU IO-APIC IRQs
-running:
-
-       A) if your board is unlisted, then mail to linux-smp to get
-          it into either the white or the blacklist
-       B) if your board is blacklisted, then figure out the appropriate
-          pirq= option to get your system to boot
-
-
-pirq= lines look like the following in /etc/lilo.conf:
+  hell:~> cat /proc/interrupts
+             CPU0
+    0:    1360293    IO-APIC-edge  timer
+    1:          4    IO-APIC-edge  keyboard
+    2:          0          XT-PIC  cascade
+   13:          1          XT-PIC  fpu
+   14:       1448    IO-APIC-edge  ide0
+   16:      28232   IO-APIC-level  Intel EtherExpress Pro 10/100 Ethernet
+   17:      51304   IO-APIC-level  eth0
+  NMI:          0
+  ERR:          0
+  hell:~>
+  <----------------------------
+
+some interrupts are still listed as 'XT PIC', but this is not a problem,
+none of those IRQ sources is performance-critical.
+
+
+in the unlikely case that your board does not create a working mp-table,
+you can use the pirq= boot parameter to 'hand-construct' IRQ entries. This
+is nontrivial though and cannot be automated. One sample /etc/lilo.conf
+entry:
 
        append="pirq=15,11,10"
 
@@ -111,8 +101,7 @@ permute all IRQ numbers properly ... it will take some time though. An
 won't function properly (if it's inserted as eg. a module).
 
 If you have 2 PCI buses, then you can use up to 8 pirq values. Although such
-boards tend to have a good configuration and will be included in the
-whitelist.
+boards tend to have a good configuration.
 
 Be prepared that it might happen that you need some strange pirq line:
 
@@ -120,14 +109,6 @@ Be prepared that it might happen that you need some strange pirq line:
 
 use smart try-and-err techniques to find out the correct pirq line ...
 
-
-the following pirq line can be used to force a board into the whitelist:
-
-       append="pirq=0"
-
-[if your system works with no problems after this, then it should be added
-to the official whitelist, contact us]
-
 good luck and mail to linux-smp@vger.rutgers.edu or
 linux-kernel@vger.rutgers.edu if you have any problems that are not covered
 by this document.
index b4e71bf56cd6d16b36f694219de398f51a83f0ca..79ca929137fa4a95a09c2ded4dc0daaa13dc1352 100644 (file)
@@ -1143,3 +1143,11 @@ sys_call_table:
        .quad sys_capget
        .quad sys_capset
        .quad sys_sendfile                      /* 370 */
+       .quad sys_timer_create
+       .quad sys_timer_settime
+       .quad sys_timer_gettime
+       .quad sys_timer_setoverrun
+       .quad sys_timer_delete                  /* 375 */
+       .quad sys_clock_gettime
+       .quad sys_clock_settime
+       .quad sys_clock_getres                  /* 378 */
index adad3a551c32f2f8b1ccc06e6e25a1d8bd3777db..568a0aaf74a7ef73a5be6313e0f58faf5d8be93d 100644 (file)
                .long   SYMBOL_NAME(sys_ni_syscall)
                .long   SYMBOL_NAME(sys_ni_syscall)
 /* 190 */      .long   SYMBOL_NAME(sys_vfork_wrapper)
+               .long   SYMBOL_NAME(sys_timer_create)
+               .long   SYMBOL_NAME(sys_timer_settime)
+               .long   SYMBOL_NAME(sys_timer_gettime)
+               .long   SYMBOL_NAME(sys_timer_getoverrun)
+/* 195 */      .long   SYMBOL_NAME(sys_timer_delete)
+               .long   SYMBOL_NAME(sys_clock_gettime)
+               .long   SYMBOL_NAME(sys_clock_settime)
+               .long   SYMBOL_NAME(sys_clock_getres)
 
-               .rept   NR_syscalls-186
+               .rept   NR_syscalls-198
                        .long   SYMBOL_NAME(sys_ni_syscall)
                .endr
 #endif
index 8c04667fdfc9aa147ba3af6e3b556effcce8265e..cfdac84b63bc54d4a9404aa9debab2576af5cfbb 100644 (file)
@@ -560,6 +560,14 @@ ENTRY(sys_call_table)
        .long SYMBOL_NAME(sys_ni_syscall)               /* streams1 */
        .long SYMBOL_NAME(sys_ni_syscall)               /* streams2 */
        .long SYMBOL_NAME(sys_vfork)            /* 190 */
+       .long SYMBOL_NAME(sys_timer_create)
+       .long SYMBOL_NAME(sys_timer_settime)
+       .long SYMBOL_NAME(sys_timer_gettime)
+       .long SYMBOL_NAME(sys_timer_getoverrun)
+       .long SYMBOL_NAME(sys_timer_delete)     /* 195 */
+       .long SYMBOL_NAME(sys_clock_gettime)
+       .long SYMBOL_NAME(sys_clock_settime)
+       .long SYMBOL_NAME(sys_clock_getres)     /* 198 */
 
        /*
         * NOTE!! This doesn't have to be exact - we just have
@@ -567,6 +575,6 @@ ENTRY(sys_call_table)
         * entries. Don't panic if you notice that this hasn't
         * been shrunk every time we add a new system call.
         */
-       .rept NR_syscalls-190
+       .rept NR_syscalls-198
                .long SYMBOL_NAME(sys_ni_syscall)
        .endr
index 42ebd964376fd99252c1bb006f0a96374aea4a9a..cae25555adc0fc41674db149fdcfd0b31f906a4e 100644 (file)
@@ -5,6 +5,12 @@
  *
  *     Many thanks to Stig Venaas for trying out countless experimental
  *     patches and reporting/debugging problems patiently!
+ *
+ *     (c) 1999, Multiple IO-APIC support, developed by
+ *     Ken-ichi Yaku <yaku@css1.kbnes.nec.co.jp> and
+ *      Hidemi Kishimoto <kisimoto@css1.kbnes.nec.co.jp>,
+ *     further tested and cleaned up by Zach Brown <zab@redhat.com>
+ *     and Ingo Molnar <mingo@redhat.com>
  */
 
 #include <linux/sched.h>
@@ -19,7 +25,7 @@
  * volatile is justified in this case, IO-APIC register contents
  * might change spontaneously, GCC should not cache it
  */
-#define IO_APIC_BASE ((volatile int *)fix_to_virt(FIX_IO_APIC_BASE))
+#define IO_APIC_BASE(idx) ((volatile int *)__fix_to_virt(FIX_IO_APIC_BASE_0 + idx))
 
 /*
  * The structure of the IO-APIC:
@@ -45,9 +51,10 @@ struct IO_APIC_reg_02 {
 } __attribute__ ((packed));
 
 /*
- * # of IRQ routing registers
+ * # of IO-APICs and # of IRQ routing registers
  */
-int nr_ioapic_registers = 0;
+int nr_ioapics = 0;
+int nr_ioapic_registers[MAX_IO_APICS];
 
 enum ioapic_irq_destination_types {
        dest_Fixed = 0,
@@ -94,6 +101,7 @@ enum mp_irq_source_types {
        mp_ExtINT = 3
 };
 
+struct mpc_config_ioapic mp_apics[MAX_IO_APICS];/* I/O APIC entries */
 int mp_irq_entries = 0;                                /* # of MP IRQ source entries */
 struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
                                                /* MP IRQ source entries */
@@ -108,34 +116,34 @@ int mpc_default_type = 0;                 /* non-0 if default (table-less)
  * between pins and IRQs.
  */
 
-static inline unsigned int io_apic_read(unsigned int reg)
+static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
 {
-       *IO_APIC_BASE = reg;
-       return *(IO_APIC_BASE+4);
+       *IO_APIC_BASE(apic) = reg;
+       return *(IO_APIC_BASE(apic)+4);
 }
 
-static inline void io_apic_write(unsigned int reg, unsigned int value)
+static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
 {
-       *IO_APIC_BASE = reg;
-       *(IO_APIC_BASE+4) = value;
+       *IO_APIC_BASE(apic) = reg;
+       *(IO_APIC_BASE(apic)+4) = value;
 }
 
 /*
  * Re-write a value: to be used for read-modify-write
  * cycles where the read already set up the index register.
  */
-static inline void io_apic_modify(unsigned int value)
+static inline void io_apic_modify(unsigned int apic, unsigned int value)
 {
-       *(IO_APIC_BASE+4) = value;
+       *(IO_APIC_BASE(apic)+4) = value;
 }
 
 /*
  * Synchronize the IO-APIC and the CPU by doing
  * a dummy read from the IO-APIC
  */
-static inline void io_apic_sync(void)
+static inline void io_apic_sync(unsigned int apic)
 {
-       (void) *(IO_APIC_BASE+4);
+       (void) *(IO_APIC_BASE(apic)+4);
 }
 
 /*
@@ -146,7 +154,7 @@ static inline void io_apic_sync(void)
 #define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS)
 
 static struct irq_pin_list {
-       int pin, next;
+       int apic, pin, next;
 } irq_2_pin[PIN_MAP_SIZE];
 
 /*
@@ -154,7 +162,7 @@ static struct irq_pin_list {
  * shared ISA-space IRQs, so we have to support them. We are super
  * fast in the common case, and fast for shared ISA-space IRQs.
  */
-static void add_pin_to_irq(unsigned int irq, int pin)
+static void add_pin_to_irq(unsigned int irq, int apic, int pin)
 {
        static int first_free_entry = NR_IRQS;
        struct irq_pin_list *entry = irq_2_pin + irq;
@@ -168,6 +176,7 @@ static void add_pin_to_irq(unsigned int irq, int pin)
                if (++first_free_entry >= PIN_MAP_SIZE)
                        panic("io_apic.c: whoops");
        }
+       entry->apic = apic;
        entry->pin = pin;
 }
 
@@ -183,9 +192,9 @@ static void name##_IO_APIC_irq(unsigned int irq)                    \
                pin = entry->pin;                                       \
                if (pin == -1)                                          \
                        break;                                          \
-               reg = io_apic_read(0x10 + R + pin*2);                   \
+               reg = io_apic_read(entry->apic, 0x10 + R + pin*2);      \
                reg ACTION;                                             \
-               io_apic_modify(reg);                                    \
+               io_apic_modify(entry->apic, reg);                       \
                if (!entry->next)                                       \
                        break;                                          \
                entry = irq_2_pin + entry->next;                        \
@@ -197,12 +206,12 @@ static void name##_IO_APIC_irq(unsigned int irq)                  \
  * We disable IO-APIC IRQs by setting their 'destination CPU mask' to
  * zero. Trick by Ramesh Nalluri.
  */
-DO_ACTION( disable, 1, &= 0x00ffffff, io_apic_sync())          /* destination = 0x00 */
+DO_ACTION( disable, 1, &= 0x00ffffff, io_apic_sync(entry->apic))/* destination = 0x00 */
 DO_ACTION( enable,  1, |= 0xff000000, )                                /* destination = 0xff */
-DO_ACTION( mask,    0, |= 0x00010000, io_apic_sync())          /* mask = 1 */
+DO_ACTION( mask,    0, |= 0x00010000, io_apic_sync(entry->apic))/* mask = 1 */
 DO_ACTION( unmask,  0, &= 0xfffeffff, )                                /* mask = 0 */
 
-static void clear_IO_APIC_pin(unsigned int pin)
+static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
 {
        struct IO_APIC_route_entry entry;
 
@@ -211,16 +220,17 @@ static void clear_IO_APIC_pin(unsigned int pin)
         */
        memset(&entry, 0, sizeof(entry));
        entry.mask = 1;
-       io_apic_write(0x10 + 2 * pin, *(((int *)&entry) + 0));
-       io_apic_write(0x11 + 2 * pin, *(((int *)&entry) + 1));
+       io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry) + 0));
+       io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry) + 1));
 }
 
 static void clear_IO_APIC (void)
 {
-       int pin;
+       int apic, pin;
 
-       for (pin = 0; pin < nr_ioapic_registers; pin++)
-               clear_IO_APIC_pin(pin);
+       for (apic = 0; apic < nr_ioapics; apic++)
+               for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
+                       clear_IO_APIC_pin(apic, pin);
 }
 
 /*
@@ -270,12 +280,13 @@ void __init ioapic_pirq_setup(char *str, int *ints)
 /*
  * Find the IRQ entry number of a certain pin.
  */
-static int __init find_irq_entry(int pin, int type)
+static int __init find_irq_entry(int apic, int pin, int type)
 {
        int i;
 
        for (i = 0; i < mp_irq_entries; i++)
                if ( (mp_irqs[i].mpc_irqtype == type) &&
+                       (mp_irqs[i].mpc_dstapic == mp_apics[apic].mpc_apicid) &&
                        (mp_irqs[i].mpc_dstirq == pin))
 
                        return i;
@@ -307,21 +318,26 @@ static int __init find_timer_pin(int type)
  * Find a specific PCI IRQ entry.
  * Not an initfunc, possibly needed by modules
  */
+static int __init pin_2_irq(int idx, int apic, int pin);
 int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pci_pin)
 {
-       int i;
+       int apic, i;
 
        for (i = 0; i < mp_irq_entries; i++) {
                int lbus = mp_irqs[i].mpc_srcbus;
 
-               if (IO_APIC_IRQ(mp_irqs[i].mpc_dstirq) &&
+               for (apic = 0; apic < nr_ioapics; apic++)
+                       if (mp_apics[apic].mpc_apicid == mp_irqs[i].mpc_dstapic)
+                               break;
+
+               if ((apic || IO_APIC_IRQ(mp_irqs[i].mpc_dstirq)) &&
                    (mp_bus_id_to_type[lbus] == MP_BUS_PCI) &&
                    !mp_irqs[i].mpc_irqtype &&
                    (bus == mp_bus_id_to_pci_bus[mp_irqs[i].mpc_srcbus]) &&
                    (slot == ((mp_irqs[i].mpc_srcbusirq >> 2) & 0x1f)) &&
                    (pci_pin == (mp_irqs[i].mpc_srcbusirq & 3)))
 
-                       return mp_irqs[i].mpc_dstirq;
+                       return pin_2_irq(i,apic,mp_irqs[i].mpc_dstirq);
        }
        return -1;
 }
@@ -491,9 +507,9 @@ static inline int irq_trigger(int idx)
        return MPBIOS_trigger(idx);
 }
 
-static int __init pin_2_irq(int idx, int pin)
+static int __init pin_2_irq(int idx, int apic, int pin)
 {
-       int irq;
+       int irq, i;
        int bus = mp_irqs[idx].mpc_srcbus;
 
        /*
@@ -513,9 +529,12 @@ static int __init pin_2_irq(int idx, int pin)
                case MP_BUS_PCI: /* PCI pin */
                {
                        /*
-                        * PCI IRQs are 'directly mapped'
+                        * PCI IRQs are mapped in order
                         */
-                       irq = pin;
+                       i = irq = 0;
+                       while (i < apic)
+                               irq += nr_ioapic_registers[i++];
+                       irq += pin;
                        break;
                }
                default:
@@ -545,12 +564,14 @@ static int __init pin_2_irq(int idx, int pin)
 
 static inline int IO_APIC_irq_trigger(int irq)
 {
-       int idx, pin;
+       int apic, idx, pin;
 
-       for (pin = 0; pin < nr_ioapic_registers; pin++) {
-               idx = find_irq_entry(pin,mp_INT);
-               if ((idx != -1) && (irq == pin_2_irq(idx,pin)))
-                       return irq_trigger(idx);
+       for (apic = 0; apic < nr_ioapics; apic++) {
+               for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+                       idx = find_irq_entry(apic,pin,mp_INT);
+                       if ((idx != -1) && (irq == pin_2_irq(idx,apic,pin)))
+                               return irq_trigger(idx);
+               }
        }
        /*
         * nonexistent IRQs are edge default
@@ -582,11 +603,12 @@ static int __init assign_irq_vector(int irq)
 void __init setup_IO_APIC_irqs(void)
 {
        struct IO_APIC_route_entry entry;
-       int pin, idx, bus, irq, first_notcon = 1;
+       int apic, pin, idx, irq, first_notcon = 1;
 
        printk("init IO_APIC IRQs\n");
 
-       for (pin = 0; pin < nr_ioapic_registers; pin++) {
+       for (apic = 0; apic < nr_ioapics; apic++) {
+       for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
 
                /*
                 * add it to the IO-APIC irq-routing table:
@@ -598,13 +620,13 @@ void __init setup_IO_APIC_irqs(void)
                entry.mask = 0;                         /* enable IRQ */
                entry.dest.logical.logical_dest = 0;    /* but no route */
 
-               idx = find_irq_entry(pin,mp_INT);
+               idx = find_irq_entry(apic,pin,mp_INT);
                if (idx == -1) {
                        if (first_notcon) {
-                               printk(" IO-APIC pin %d", pin);
+                               printk(" IO-APIC (apicid-pin) %d-%d", mp_apics[apic].mpc_apicid, pin);
                                first_notcon = 0;
                        } else
-                               printk(", %d", pin);
+                               printk(", %d-%d", mp_apics[apic].mpc_apicid, pin);
                        continue;
                }
 
@@ -617,18 +639,17 @@ void __init setup_IO_APIC_irqs(void)
                        entry.dest.logical.logical_dest = 0xff;
                }
 
-               irq = pin_2_irq(idx,pin);
-               add_pin_to_irq(irq, pin);
+               irq = pin_2_irq(idx,apic,pin);
+               add_pin_to_irq(irq, apic, pin);
 
-               if (!IO_APIC_IRQ(irq))
+               if (!apic && !IO_APIC_IRQ(irq))
                        continue;
 
                entry.vector = assign_irq_vector(irq);
 
-               bus = mp_irqs[idx].mpc_srcbus;
-
-               io_apic_write(0x11+2*pin, *(((int *)&entry)+1));
-               io_apic_write(0x10+2*pin, *(((int *)&entry)+0));
+               io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
+               io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
+       }
        }
 
        if (!first_notcon)
@@ -638,7 +659,7 @@ void __init setup_IO_APIC_irqs(void)
 /*
  * Set up a certain pin as ExtINT delivered interrupt
  */
-void __init setup_ExtINT_pin(unsigned int pin, int irq)
+void __init setup_ExtINT_pin(unsigned int apic, unsigned int pin, int irq)
 {
        struct IO_APIC_route_entry entry;
 
@@ -662,8 +683,8 @@ void __init setup_ExtINT_pin(unsigned int pin, int irq)
        entry.polarity = 0;
        entry.trigger = 0;
 
-       io_apic_write(0x10+2*pin, *(((int *)&entry)+0));
-       io_apic_write(0x11+2*pin, *(((int *)&entry)+1));
+       io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
+       io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
 }
 
 void __init UNEXPECTED_IO_APIC(void)
@@ -674,17 +695,14 @@ void __init UNEXPECTED_IO_APIC(void)
 
 void __init print_IO_APIC(void)
 {
-       int i;
+       int apic, i;
        struct IO_APIC_reg_00 reg_00;
        struct IO_APIC_reg_01 reg_01;
        struct IO_APIC_reg_02 reg_02;
 
        printk("number of MP IRQ sources: %d.\n", mp_irq_entries);
-       printk("number of IO-APIC registers: %d.\n", nr_ioapic_registers);
-
-       *(int *)&reg_00 = io_apic_read(0);
-       *(int *)&reg_01 = io_apic_read(1);
-       *(int *)&reg_02 = io_apic_read(2);
+       for (i = 0; i < nr_ioapics; i++)
+               printk("number of IO-APIC #%d registers: %d.\n", mp_apics[i].mpc_apicid, nr_ioapic_registers[i]);
 
        /*
         * We are a bit conservative about what we expect.  We have to
@@ -692,6 +710,12 @@ void __init print_IO_APIC(void)
         */
        printk("testing the IO APIC.......................\n");
 
+       for (apic = 0; apic < nr_ioapics; apic++) {
+
+       *(int *)&reg_00 = io_apic_read(apic, 0);
+       *(int *)&reg_01 = io_apic_read(apic, 1);
+       *(int *)&reg_02 = io_apic_read(apic, 2);
+       printk("\nIO APIC #%d......\n", mp_apics[apic].mpc_apicid);
        printk(".... register #00: %08X\n", *(int *)&reg_00);
        printk(".......    : physical APIC id: %02X\n", reg_00.ID);
        if (reg_00.__reserved_1 || reg_00.__reserved_2)
@@ -706,8 +730,6 @@ void __init print_IO_APIC(void)
                (reg_01.entries != 0x3F)    /* bigger Xeon boards */
        )
                UNEXPECTED_IO_APIC();
-       if (reg_01.entries == 0x0f)
-               printk(".......       [IO-APIC cannot route PCI PIRQ 0-3]\n");
 
        printk(".......     : IO APIC version: %04X\n", reg_01.version);
        if (    (reg_01.version != 0x10) && /* oldest IO-APICs */
@@ -731,8 +753,8 @@ void __init print_IO_APIC(void)
        for (i = 0; i <= reg_01.entries; i++) {
                struct IO_APIC_route_entry entry;
 
-               *(((int *)&entry)+0) = io_apic_read(0x10+i*2);
-               *(((int *)&entry)+1) = io_apic_read(0x11+i*2);
+               *(((int *)&entry)+0) = io_apic_read(apic, 0x10+i*2);
+               *(((int *)&entry)+1) = io_apic_read(apic, 0x11+i*2);
 
                printk(" %02x %03X %02X  ",
                        i,
@@ -751,7 +773,7 @@ void __init print_IO_APIC(void)
                        entry.vector
                );
        }
-
+       }
        printk(KERN_DEBUG "IRQ to pin mappings:\n");
        for (i = 0; i < NR_IRQS; i++) {
                struct irq_pin_list *entry = irq_2_pin + i;
@@ -796,9 +818,12 @@ static void __init init_sym_mode(void)
         */
        {
                struct IO_APIC_reg_01 reg_01;
+               int i;
 
-               *(int *)&reg_01 = io_apic_read(1);
-               nr_ioapic_registers = reg_01.entries+1;
+               for (i = 0; i < nr_ioapics; i++) {
+                       *(int *)&reg_01 = io_apic_read(i, 1);
+                       nr_ioapic_registers[i] = reg_01.entries+1;
+               }
        }
 
        /*
@@ -827,55 +852,6 @@ void init_pic_mode(void)
        printk("...done.\n");
 }
 
-char ioapic_OEM_ID [16];
-char ioapic_Product_ID [16];
-
-struct ioapic_list_entry {
-       char * oem_id;
-       char * product_id;
-};
-
-struct ioapic_list_entry __initdata ioapic_whitelist [] = {
-
-       { "INTEL   "    ,       "PR440FX     "  },
-       { "INTEL   "    ,       "82440FX     "  },
-       { "AIR     "    ,       "KDI         "  },
-       { 0             ,       0               }
-};
-
-struct ioapic_list_entry __initdata ioapic_blacklist [] = {
-
-       { "OEM00000"    ,       "PROD00000000"  },
-       { 0             ,       0               }
-};
-
-static int __init in_ioapic_list(struct ioapic_list_entry * table)
-{
-       for ( ; table->oem_id ; table++)
-               if ((!strcmp(table->oem_id,ioapic_OEM_ID)) &&
-                   (!strcmp(table->product_id,ioapic_Product_ID)))
-                       return 1;
-       return 0;
-}
-
-static int __init ioapic_whitelisted(void)
-{
-/*
- * Right now, whitelist everything to see whether the new parsing
- * routines really do work for everybody.
- */
-#if 1
-       return 1;
-#else
-       return in_ioapic_list(ioapic_whitelist);
-#endif
-}
-
-static int __init ioapic_blacklisted(void)
-{
-       return in_ioapic_list(ioapic_blacklist);
-}
-
 static void __init setup_ioapic_id(void)
 {
        struct IO_APIC_reg_00 reg_00;
@@ -897,15 +873,15 @@ static void __init setup_ioapic_id(void)
        /*
         * Set the ID
         */
-       *(int *)&reg_00 = io_apic_read(0);
+       *(int *)&reg_00 = io_apic_read(0, 0);
        printk("...changing IO-APIC physical APIC ID to 2...\n");
        reg_00.ID = 0x2;
-       io_apic_write(0, *(int *)&reg_00);
+       io_apic_write(0, 0, *(int *)&reg_00);
 
        /*
         * Sanity check
         */
-       *(int *)&reg_00 = io_apic_read(0);
+       *(int *)&reg_00 = io_apic_read(0, 0);
        if (reg_00.ID != 0x2)
                panic("could not set ID");
 }
@@ -1227,7 +1203,10 @@ static inline void check_timer(void)
 
                if (pin2 != -1) {
                        printk(".. (found pin %d) ...", pin2);
-                       setup_ExtINT_pin(pin2, 0);
+                       /*
+                        * legacy devices should be connected to IO APIC #0
+                        */
+                       setup_ExtINT_pin(0, pin2, 0);
                        make_8259A_irq(0);
                }
 
@@ -1238,9 +1217,9 @@ static inline void check_timer(void)
                         * Just in case ...
                         */
                        if (pin1 != -1)
-                               clear_IO_APIC_pin(pin1);
+                               clear_IO_APIC_pin(0, pin1);
                        if (pin2 != -1)
-                               clear_IO_APIC_pin(pin2);
+                               clear_IO_APIC_pin(0, pin2);
 
                        make_8259A_irq(0);
 
@@ -1273,29 +1252,8 @@ void __init setup_IO_APIC(void)
 {
        init_sym_mode();
 
-       /*
-        * Determine the range of IRQs handled by the IO-APIC. The
-        * following boards can be fully enabled:
-        *
-        * - whitelisted ones
-        * - those which have no PCI pins connected
-        * - those for which the user has specified a pirq= parameter
-        */
-       if (    ioapic_whitelisted() ||
-               (nr_ioapic_registers == 16) ||
-               pirqs_enabled)
-       {
-               printk("ENABLING IO-APIC IRQs\n");
-               io_apic_irqs = ~PIC_IRQS;
-       } else {
-               if (ioapic_blacklisted())
-                       printk(" blacklisted board, DISABLING IO-APIC IRQs\n");
-               else
-                       printk(" unlisted board, DISABLING IO-APIC IRQs\n");
-
-               printk(" see Documentation/IO-APIC.txt to enable them\n");
-               io_apic_irqs = 0;
-       }
+       printk("ENABLING IO-APIC IRQs\n");
+       io_apic_irqs = ~PIC_IRQS;
 
        /*
         * If there are no explicit MP IRQ entries, it's either one of the
index 1023cd4da31e1997af0f7633b2be94a5fa70e89f..a6ee1948de739c2172b2c24329e0fe6404110384 100644 (file)
@@ -57,9 +57,9 @@ typedef struct {
 /*
  * Special IRQ vectors used by the SMP architecture:
  *
- * (some of the following vectors are 'rare', they might be merged
- *  into a single vector to save vector space. TLB, reschedule and
- *  local APIC vectors are performance-critical.)
+ * (some of the following vectors are 'rare', they are merged
+ *  into a single vector (FUNCTION_VECTOR) to save vector space.
+ *  TLB, reschedule and local APIC vectors are performance-critical.)
  */
 #define RESCHEDULE_VECTOR      0x30
 #define INVALIDATE_TLB_VECTOR  0x31
@@ -120,8 +120,6 @@ enum mp_bustype {
 };
 extern int mp_bus_id_to_type [MAX_MP_BUSSES];
 extern int mp_bus_id_to_pci_bus [MAX_MP_BUSSES];
-extern char ioapic_OEM_ID [16];
-extern char ioapic_Product_ID [16];
 
 extern spinlock_t irq_controller_lock;
 
index 952f5b93d78965490dd7a720ecc25329adca73c3..d98600fddfb6be4749d908f4b48b11ee803ecd6e 100644 (file)
@@ -327,8 +327,8 @@ void machine_restart(char * __unused)
         * the way we set root page dir in the future, then we wont break a
         * seldom used feature ;)
         */
-
        current->mm->pgd = swapper_pg_dir;
+       current->active_mm->pgd = swapper_pg_dir;
        activate_context();
 
        /* Write 0x1234 to absolute memory location 0x472.  The BIOS reads
@@ -757,21 +757,6 @@ void __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
        asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->fs));
        asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->gs));
 
-       /*
-        * Re-load LDT if necessary
-        */
-       if (prev_p->active_mm->segments != next_p->active_mm->segments)
-               load_LDT(next_p->mm);
-
-       /* Re-load page tables */
-       {
-               unsigned long new_cr3 = next->cr3;
-
-               tss->cr3 = new_cr3;
-               if (new_cr3 != prev->cr3)
-                       asm volatile("movl %0,%%cr3": :"r" (new_cr3));
-       }
-
        /*
         * Restore %fs and %gs.
         */
index a62937b8631e05f8925a9bb7436ec88dea4c4a71..ffeea7e1b4818ae1f68e0ba00e0f2390f36235a1 100644 (file)
@@ -128,6 +128,8 @@ volatile unsigned long ipi_count;                   /* Number of IPIs delivered                             */
 const char lk_lockmsg[] = "lock from interrupt context at %p\n"; 
 
 int mp_bus_id_to_type [MAX_MP_BUSSES] = { -1, };
+extern int nr_ioapics;
+extern struct mpc_config_ioapic mp_apics [MAX_IO_APICS];
 extern int mp_irq_entries;
 extern struct mpc_config_intsrc mp_irqs [MAX_IRQ_SOURCES];
 extern int mpc_default_type;
@@ -258,12 +260,10 @@ static int __init smp_read_mpc(struct mp_config_table *mpc)
        }
        memcpy(str,mpc->mpc_oem,8);
        str[8]=0;
-       memcpy(ioapic_OEM_ID,str,9);
        printk("OEM ID: %s ",str);
        
        memcpy(str,mpc->mpc_productid,12);
        str[12]=0;
-       memcpy(ioapic_Product_ID,str,13);
        printk("Product ID: %s ",str);
 
        printk("APIC at: 0x%lX\n",mpc->mpc_lapic);
@@ -368,11 +368,9 @@ static int __init smp_read_mpc(struct mp_config_table *mpc)
                                        printk("I/O APIC #%d Version %d at 0x%lX.\n",
                                                m->mpc_apicid,m->mpc_apicver,
                                                m->mpc_apicaddr);
-                                       /*
-                                        * we use the first one only currently
-                                        */
-                                       if (ioapics == 1)
-                                               mp_ioapic_addr = m->mpc_apicaddr;
+                                       mp_apics [nr_ioapics] = *m;
+                                       if (++nr_ioapics > MAX_IO_APICS)
+                                               --nr_ioapics;
                                }
                                mpt+=sizeof(*m);
                                count+=sizeof(*m);
@@ -404,9 +402,9 @@ static int __init smp_read_mpc(struct mp_config_table *mpc)
                        }
                }
        }
-       if (ioapics > 1)
+       if (ioapics > MAX_IO_APICS)
        {
-               printk("Warning: Multiple IO-APICs not yet supported.\n");
+               printk("Warning: Max I/O APICs exceeded (max %d, found %d).\n", MAX_IO_APICS, ioapics);
                printk("Warning: switching to non APIC mode.\n");
                skip_ioapic_setup=1;
        }
@@ -774,18 +772,22 @@ unsigned long __init init_smp_mappings(unsigned long memory_start)
 
 #ifdef CONFIG_X86_IO_APIC
        {
-               unsigned long ioapic_phys;
-
-               if (smp_found_config) {
-                       ioapic_phys = mp_ioapic_addr;
-               } else {
-                       ioapic_phys = __pa(memory_start);
-                       memset((void *)memory_start, 0, PAGE_SIZE);
-                       memory_start += PAGE_SIZE;
+               unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
+               int i;
+
+               for (i = 0; i < nr_ioapics; i++) {
+                       if (smp_found_config) {
+                               ioapic_phys = mp_apics[i].mpc_apicaddr;
+                       } else {
+                               ioapic_phys = __pa(memory_start);
+                               memset((void *)memory_start, 0, PAGE_SIZE);
+                               memory_start += PAGE_SIZE;
+                       }
+                       set_fixmap(idx,ioapic_phys);
+                       printk("mapped IOAPIC to %08lx (%08lx)\n",
+                                       __fix_to_virt(idx), ioapic_phys);
+                       idx++;
                }
-               set_fixmap(FIX_IO_APIC_BASE,ioapic_phys);
-               printk("mapped IOAPIC to %08lx (%08lx)\n",
-                               fix_to_virt(FIX_IO_APIC_BASE), ioapic_phys);
        }
 #endif
 
index 2d1f349b3107d6292eef3c6a58cb4e8b349213a0..5b160178e258615df2d64fc3248a19299b12fbbb 100644 (file)
@@ -246,8 +246,8 @@ no_context:
        printk(" printing eip:\n");
        printk("%08lx\n", regs->eip);
        __asm__("movl %%cr3,%0" : "=r" (page));
-       printk(KERN_ALERT "current->thread.cr3 = %08lx, %%cr3 = %08lx\n",
-               tsk->thread.cr3, page);
+       printk(KERN_ALERT "current->active_mm.pgd = %p, %%cr3 = %08lx\n",
+               tsk->active_mm->pgd, page);
        page = ((unsigned long *) __va(page))[address >> 22];
        printk(KERN_ALERT "*pde = %08lx\n", page);
        if (page & 1) {
index 61482c3a86544021e6d45d10b69d99c607be934b..efba7bafa8d81d75cb12a05fc680120f24787f8d 100644 (file)
@@ -609,6 +609,14 @@ SYMBOL_NAME_LABEL(sys_call_table)
        .long SYMBOL_NAME(sys_ni_syscall)               /* streams1 */
        .long SYMBOL_NAME(sys_ni_syscall)               /* streams2 */
        .long SYMBOL_NAME(sys_vfork)            /* 190 */
+       .long SYMBOL_NAME(sys_timer_create)
+       .long SYMBOL_NAME(sys_timer_settime)
+       .long SYMBOL_NAME(sys_timer_gettime)
+       .long SYMBOL_NAME(sys_timer_getoverrun)
+       .long SYMBOL_NAME(sys_timer_delete)     /* 195 */
+       .long SYMBOL_NAME(sys_clock_gettime)
+       .long SYMBOL_NAME(sys_clock_settime)
+       .long SYMBOL_NAME(sys_clock_getres)     /* 198 */
 
        .rept NR_syscalls-(.-SYMBOL_NAME(sys_call_table))/4
                .long SYMBOL_NAME(sys_ni_syscall)
index bd9fe3feb3996c1dc3bcf45225522ace1b47c7f1..4c5830679c6d55d4152633facd15b5dc5a40425a 100644 (file)
@@ -225,3 +225,11 @@ SYS(sys_sigaltstack, 2)
 SYS(sys_sendfile, 3)
 SYS(sys_ni_syscall, 0)
 SYS(sys_ni_syscall, 0)
+SYS(sys_timer_create, 3)                       /* 4210 */
+SYS(sys_timer_settime, 4)
+SYS(sys_timer_gettime, 2)
+SYS(sys_timer_getoverrun, 1)
+SYS(sys_timer_delete, 1)
+SYS(sys_clock_gettime, 2)                      /* 4215 */
+SYS(sys_clock_settime, 2)
+SYS(sys_clock_getres, 2)
index 0caf06a3b4151ee1f9581607d3ada8c791970ddd..138cbce95aa1621ad5215d4a9dc38b858c5320a8 100644 (file)
@@ -894,4 +894,12 @@ sys_call_table:
        .long sys_ni_syscall            /* streams1 */
        .long sys_ni_syscall            /* streams2 */
        .long sys_vfork
-       .space (NR_syscalls-183)*4
+       .long sys_timer_create  /* 190 */
+       .long sys_timer_settime
+       .long sys_timer_gettime
+       .long sys_timer_getoverrun
+       .long sys_timer_delete
+       .long sys_clock_gettime /* 195 */
+       .long sys_clock_settime
+       .long sys_clock_getres  /* 197 */
+       .space (NR_syscalls-197)*4
index 4d0dfff5fc493d4ede4a1b95880242bb81c565b4..fbc1776de2db32a482c6906b704e4ba05f2f9d8c 100644 (file)
@@ -68,7 +68,8 @@ sys_call_table:
 /*240*/        .long sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
 /*245*/        .long sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep
 /*250*/        .long sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
-/*255*/        .long sys_aplib, sys_nis_syscall
+/*255*/        .long sys_aplib, sys_timer_create, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
+/*260*/ .long sys_timer_delete, sys_clock_gettime, sys_clock_settime, sys_clock_getres
 
        /* Now the SunOS syscall table. */
 
index e99ae05325dc3f1c9247ec1af8cbcd094091eb39..fa411982eda252ffca3e20f8b86384da657885af 100644 (file)
@@ -68,7 +68,8 @@ sys_call_table32:
 /*240*/        .word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
        .word sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys32_sched_rr_get_interval, sys32_nanosleep
 /*250*/        .word sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys32_nfsservctl
-       .word sys_aplib
+/*255*/        .word sys_aplib, sys_timer_create, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
+/*260*/ .word sys_timer_delete, sys_clock_gettime, sys_clock_settime, sys_clock_getres
 
        /* Now the 64-bit native Linux syscall table. */
 
@@ -127,7 +128,8 @@ sys_call_table:
 /*240*/        .word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
        .word sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep
 /*250*/        .word sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
-       .word sys_aplib
+/*255*/        .word sys_aplib, sys_timer_create, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
+/*260*/ .word sys_timer_delete, sys_clock_gettime, sys_clock_settime, sys_clock_getres
 
        /* Now the 32-bit SunOS syscall table. */
 
index d8b62ab5579255ad7b8e5cd71fa741d59e67f634..5e614d8cdef72f8d126ffce941b8cd95480215cc 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -379,25 +379,20 @@ static int exec_mmap(void)
 
        mm = mm_alloc();
        if (mm) {
+               struct mm_struct *active_mm = current->active_mm;
+
                mm->cpu_vm_mask = (1UL << smp_processor_id());
-               mm->total_vm = 0;
-               mm->rss = 0;
-               mm->pgd = pgd_alloc();
-               if (mm->pgd) {
-                       struct mm_struct *active_mm = current->active_mm;
-
-                       current->mm = mm;
-                       current->active_mm = mm;
-                       activate_context();
-                       mm_release();
-                       if (old_mm) {
-                               mmput(old_mm);
-                               return 0;
-                       }
-                       mmdrop(active_mm);
+               current->mm = mm;
+               current->active_mm = mm;
+               activate_context();
+               mm_release();
+               if (old_mm) {
+                       if (active_mm != old_mm) BUG();
+                       mmput(old_mm);
                        return 0;
                }
-               kmem_cache_free(mm_cachep, mm);
+               mmdrop(active_mm);
+               return 0;
        }
        return -ENOMEM;
 }
index a8bedd8e0a2177aa81b11059a8dfda5c6dd51208..8e2275dd0b0e9f9d3e6f1755b8ef792a72b6231f 100644 (file)
@@ -67,6 +67,8 @@ typedef struct siginfo {
  */
 #define si_pid         _sifields._kill._pid
 #define si_uid         _sifields._kill._uid
+#define si_timer1      _sifields._timer._timer1
+#define si_timer2      _sifields._timer._timer2
 #define si_status      _sifields._sigchld._status
 #define si_utime       _sifields._sigchld._utime
 #define si_stime       _sifields._sigchld._stime
index df20edc7f2e2aaae199c7b8ead0467beb9eb4ced..dab8c012e68ee7064f21fa28b70e2d602c2bdc70 100644 (file)
 #define __NR_capget                    368
 #define __NR_capset                    369
 #define __NR_sendfile                  370
+#define __NR_timer_create              371
+#define __NR_timer_settime             372
+#define __NR_timer_gettime             373
+#define __NR_timer_getoverrun          374
+#define __NR_timer_delete              375
+#define __NR_clock_gettime             376
+#define __NR_clock_settime             377
+#define __NR_clock_getres              378
 
 #if defined(__LIBRARY__) && defined(__GNUC__)
 
index c08847d3252dab9b52bc16cbc52bcb7d74dbd193..ac998192a189da3f9b2278cee3f03962751b3d58 100644 (file)
@@ -67,6 +67,8 @@ typedef struct siginfo {
  */
 #define si_pid         _sifields._kill._pid
 #define si_uid         _sifields._kill._uid
+#define si_timer1      _sifields._timer._timer1
+#define si_timer2      _sifields._timer._timer2
 #define si_status      _sifields._sigchld._status
 #define si_utime       _sifields._sigchld._utime
 #define si_stime       _sifields._sigchld._stime
index f4a7ed33af05e54c17153b11eac080cee14ca1ce..9c49c8b216718ee19cfffd68ba2213ab311778c5 100644 (file)
                                        /* 188 reserved */
                                        /* 189 reserved */
 #define __NR_vfork                     (__NR_SYSCALL_BASE+190)
+#define __NR_timer_create              (__NR_SYSCALL_BASE+191)
+#define __NR_timer_settime             (__NR_SYSCALL_BASE+192)
+#define __NR_timer_gettime             (__NR_SYSCALL_BASE+193)
+#define __NR_timer_getoverrun          (__NR_SYSCALL_BASE+194)
+#define __NR_timer_delete              (__NR_SYSCALL_BASE+195)
+#define __NR_clock_gettime             (__NR_SYSCALL_BASE+196)
+#define __NR_clock_settime             (__NR_SYSCALL_BASE+197)
+#define __NR_clock_getres              (__NR_SYSCALL_BASE+198)
 
 #define __sys2(x) #x
 #define __sys1(x) __sys2(x)
diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h
new file mode 100644 (file)
index 0000000..7b035d9
--- /dev/null
@@ -0,0 +1,95 @@
+#ifndef __ASM_APIC_H
+#define __ASM_APIC_H
+
+/*
+ * Constants for various Intel APICs. (local APIC, IOAPIC, etc.)
+ *
+ * Alan Cox <Alan.Cox@linux.org>, 1995.
+ */
+#define                APIC_PHYS_BASE  0xfee00000 /* IA s/w dev Vol 3, Section 7.4 */
+#define                APIC_ID         0x20
+#define                        GET_APIC_ID(x)          (((x)>>24)&0x0F)
+#define                APIC_VERSION    0x30
+#define                APIC_TASKPRI    0x80
+#define                        APIC_TPRI_MASK          0xFF
+#define                APIC_ARBPRI     0x90
+#define                        APIC_ARBPRI_MASK        0xFF
+#define                APIC_PROCPRI    0xA0
+#define                APIC_EOI        0xB0
+#define                        APIC_EIO_ACK            0x0             /* Write this to the EOI register */
+#define                APIC_RRR        0xC0
+#define                APIC_LDR        0xD0
+#define                        APIC_LDR_MASK           (0xFF<<24)
+#define                        GET_APIC_LOGICAL_ID(x)  (((x)>>24)&0xFF)
+#define                        SET_APIC_LOGICAL_ID(x)  (((x)<<24))
+#define                APIC_DFR        0xE0
+#define                        GET_APIC_DFR(x)         (((x)>>28)&0x0F)
+#define                        SET_APIC_DFR(x)         ((x)<<28)
+#define                APIC_SPIV       0xF0
+#define                APIC_ISR        0x100
+#define                APIC_TMR        0x180
+#define        APIC_IRR        0x200
+#define        APIC_ESR        0x280
+#define                        APIC_ESR_SEND_CS        0x00001
+#define                        APIC_ESR_RECV_CS        0x00002
+#define                        APIC_ESR_SEND_ACC       0x00004
+#define                        APIC_ESR_RECV_ACC       0x00008
+#define                        APIC_ESR_SENDILL        0x00020
+#define                        APIC_ESR_RECVILL        0x00040
+#define                        APIC_ESR_ILLREGA        0x00080
+#define                APIC_ICR        0x300
+#define                        APIC_DEST_SELF          0x40000
+#define                        APIC_DEST_ALLINC        0x80000
+#define                        APIC_DEST_ALLBUT        0xC0000
+#define                        APIC_DEST_RR_MASK       0x30000
+#define                        APIC_DEST_RR_INVALID    0x00000
+#define                        APIC_DEST_RR_INPROG     0x10000
+#define                        APIC_DEST_RR_VALID      0x20000
+#define                        APIC_DEST_LEVELTRIG     0x08000
+#define                        APIC_DEST_ASSERT        0x04000
+#define                        APIC_DEST_BUSY          0x01000
+#define                        APIC_DEST_LOGICAL       0x00800
+#define                        APIC_DEST_DM_FIXED      0x00000
+#define                        APIC_DEST_DM_LOWEST     0x00100
+#define                        APIC_DEST_DM_SMI        0x00200
+#define                        APIC_DEST_DM_REMRD      0x00300
+#define                        APIC_DEST_DM_NMI        0x00400
+#define                        APIC_DEST_DM_INIT       0x00500
+#define                        APIC_DEST_DM_STARTUP    0x00600
+#define                        APIC_DEST_VECTOR_MASK   0x000FF
+#define                APIC_ICR2       0x310
+#define                        GET_APIC_DEST_FIELD(x)  (((x)>>24)&0xFF)
+#define                        SET_APIC_DEST_FIELD(x)  ((x)<<24)
+#define                APIC_LVTT       0x320
+#define                APIC_LVT0       0x350
+#define                        APIC_LVT_TIMER_PERIODIC         (1<<17)
+#define                        APIC_LVT_MASKED                 (1<<16)
+#define                        APIC_LVT_LEVEL_TRIGGER          (1<<15)
+#define                        APIC_LVT_REMOTE_IRR             (1<<14)
+#define                        APIC_INPUT_POLARITY             (1<<13)
+#define                        APIC_SEND_PENDING               (1<<12)
+#define                        GET_APIC_DELIVERY_MODE(x)       (((x)>>8)&0x7)
+#define                        SET_APIC_DELIVERY_MODE(x,y)     (((x)&~0x700)|((y)<<8))
+#define                                APIC_MODE_FIXED         0x0
+#define                                APIC_MODE_NMI           0x4
+#define                                APIC_MODE_EXINT         0x7
+#define        APIC_LVT1       0x360
+#define                APIC_LVERR      0x370
+#define                APIC_TMICT      0x380
+#define                APIC_TMCCT      0x390
+#define                APIC_TDCR       0x3E0
+#define                        APIC_TDR_DIV_1          0xB
+#define                        APIC_TDR_DIV_2          0x0
+#define                        APIC_TDR_DIV_4          0x1
+#define                        APIC_TDR_DIV_8          0x2
+#define                        APIC_TDR_DIV_16         0x3
+#define                        APIC_TDR_DIV_32         0x8
+#define                        APIC_TDR_DIV_64         0x9
+#define                        APIC_TDR_DIV_128        0xA
+
+#define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
+
+#define MAX_IO_APICS 8
+
+#endif
index c259a45ee837cf2be579099e358cf96576938fa0..7f25d6410e93772a5f4525f706baa39fb96cb701 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/config.h>
 #include <linux/kernel.h>
+#include <asm/apic.h>
 #include <asm/page.h>
 
 /*
@@ -45,7 +46,8 @@ enum fixed_addresses {
        FIX_APIC_BASE,  /* local (CPU) APIC) -- required for SMP or not */
 #endif
 #ifdef CONFIG_X86_IO_APIC
-       FIX_IO_APIC_BASE,
+       FIX_IO_APIC_BASE_0,
+       FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS-1,
 #endif
 #ifdef CONFIG_X86_VISWS_APIC
        FIX_CO_CPU,     /* Cobalt timer */
diff --git a/include/asm-i386/i82489.h b/include/asm-i386/i82489.h
deleted file mode 100644 (file)
index 76f580b..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-#ifndef __ASM_I82489_H
-#define __ASM_I82489_H
-
-/*
- *     Offsets for programming the 82489 and Pentium integrated APIC
- *
- *     Alan Cox <Alan.Cox@linux.org>, 1995.
- */
-#define                APIC_PHYS_BASE  0xfee00000 /* IA s/w dev Vol 3, Section 7.4 */
-#define                APIC_ID         0x20
-#define                        GET_APIC_ID(x)          (((x)>>24)&0x0F)
-#define                APIC_VERSION    0x30
-#define                APIC_TASKPRI    0x80
-#define                        APIC_TPRI_MASK          0xFF
-#define                APIC_ARBPRI     0x90
-#define                        APIC_ARBPRI_MASK        0xFF
-#define                APIC_PROCPRI    0xA0
-#define                APIC_EOI        0xB0
-#define                        APIC_EIO_ACK            0x0             /* Write this to the EOI register */
-#define                APIC_RRR        0xC0
-#define                APIC_LDR        0xD0
-#define                        APIC_LDR_MASK           (0xFF<<24)
-#define                        GET_APIC_LOGICAL_ID(x)  (((x)>>24)&0xFF)
-#define                        SET_APIC_LOGICAL_ID(x)  (((x)<<24))
-#define                APIC_DFR        0xE0
-#define                        GET_APIC_DFR(x)         (((x)>>28)&0x0F)
-#define                        SET_APIC_DFR(x)         ((x)<<28)
-#define                APIC_SPIV       0xF0
-#define                APIC_ISR        0x100
-#define                APIC_TMR        0x180
-#define        APIC_IRR        0x200
-#define        APIC_ESR        0x280
-#define                        APIC_ESR_SEND_CS        0x00001
-#define                        APIC_ESR_RECV_CS        0x00002
-#define                        APIC_ESR_SEND_ACC       0x00004
-#define                        APIC_ESR_RECV_ACC       0x00008
-#define                        APIC_ESR_SENDILL        0x00020
-#define                        APIC_ESR_RECVILL        0x00040
-#define                        APIC_ESR_ILLREGA        0x00080
-#define                APIC_ICR        0x300
-#define                        APIC_DEST_SELF          0x40000
-#define                        APIC_DEST_ALLINC        0x80000
-#define                        APIC_DEST_ALLBUT        0xC0000
-#define                        APIC_DEST_RR_MASK       0x30000
-#define                        APIC_DEST_RR_INVALID    0x00000
-#define                        APIC_DEST_RR_INPROG     0x10000
-#define                        APIC_DEST_RR_VALID      0x20000
-#define                        APIC_DEST_LEVELTRIG     0x08000
-#define                        APIC_DEST_ASSERT        0x04000
-#define                        APIC_DEST_BUSY          0x01000
-#define                        APIC_DEST_LOGICAL       0x00800
-#define                        APIC_DEST_DM_FIXED      0x00000
-#define                        APIC_DEST_DM_LOWEST     0x00100
-#define                        APIC_DEST_DM_SMI        0x00200
-#define                        APIC_DEST_DM_REMRD      0x00300
-#define                        APIC_DEST_DM_NMI        0x00400
-#define                        APIC_DEST_DM_INIT       0x00500
-#define                        APIC_DEST_DM_STARTUP    0x00600
-#define                        APIC_DEST_VECTOR_MASK   0x000FF
-#define                APIC_ICR2       0x310
-#define                        GET_APIC_DEST_FIELD(x)  (((x)>>24)&0xFF)
-#define                        SET_APIC_DEST_FIELD(x)  ((x)<<24)
-#define                APIC_LVTT       0x320
-#define                APIC_LVT0       0x350
-#define                        APIC_LVT_TIMER_PERIODIC         (1<<17)
-#define                        APIC_LVT_MASKED                 (1<<16)
-#define                        APIC_LVT_LEVEL_TRIGGER          (1<<15)
-#define                        APIC_LVT_REMOTE_IRR             (1<<14)
-#define                        APIC_INPUT_POLARITY             (1<<13)
-#define                        APIC_SEND_PENDING               (1<<12)
-#define                        GET_APIC_DELIVERY_MODE(x)       (((x)>>8)&0x7)
-#define                        SET_APIC_DELIVERY_MODE(x,y)     (((x)&~0x700)|((y)<<8))
-#define                                APIC_MODE_FIXED         0x0
-#define                                APIC_MODE_NMI           0x4
-#define                                APIC_MODE_EXINT         0x7
-#define        APIC_LVT1       0x360
-#define                APIC_LVERR      0x370
-#define                APIC_TMICT      0x380
-#define                APIC_TMCCT      0x390
-#define                APIC_TDCR       0x3E0
-#define                        APIC_TDR_DIV_1          0xB
-#define                        APIC_TDR_DIV_2          0x0
-#define                        APIC_TDR_DIV_4          0x1
-#define                        APIC_TDR_DIV_8          0x2
-#define                        APIC_TDR_DIV_16         0x3
-#define                        APIC_TDR_DIV_32         0x8
-#define                        APIC_TDR_DIV_64         0x9
-#define                        APIC_TDR_DIV_128        0xA
-
-#define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
-
-extern __inline void apic_write(unsigned long reg, unsigned long v)
-{
-       *((volatile unsigned long *)(APIC_BASE+reg))=v;
-}
-
-extern __inline unsigned long apic_read(unsigned long reg)
-{
-       return *((volatile unsigned long *)(APIC_BASE+reg));
-}
-
-#endif
index 3e007f13b8b8735c46c8136aa31fae298126e8dc..769fad6d4f443c59c95d4c4f6b8e607f0c3c967d 100644 (file)
@@ -3,36 +3,31 @@
 
 #include <asm/desc.h>
 
-/*
- * get a new mmu context.. x86's don't know much about contexts,
- * but we have to reload the new LDT in exec().
- *
- * We implement lazy MMU context-switching on x86 to optimize context
- * switches done to/from kernel threads. Kernel threads 'inherit' the
- * previous MM, so Linux doesnt have to flush the TLB. In most cases
- * we switch back to the same process so we preserve the TLB cache.
- * This all means that kernel threads have about as much overhead as
- * a function call ...
- */
-#define get_mmu_context(next) do { } while (0)
-#define set_mmu_context(prev,next) do { next->thread.cr3 = prev->thread.cr3; } while(0)
-
 /*
  * possibly do the LDT unload here?
  */
 #define destroy_context(mm)            do { } while(0)
-#define init_new_context(tsk,mm)       do { (tsk)->thread.cr3 = __pa((mm)->pgd); } while (0)
+#define init_new_context(tsk,mm)       do { } while (0)
 
 static inline void activate_context(void)
 {
        struct task_struct *tsk = current;
        struct mm_struct *mm = tsk->mm;
-       unsigned long cr3;
 
        load_LDT(mm);
-       cr3 = __pa(mm->pgd);
-       tsk->thread.cr3 = cr3;
-       __asm__ __volatile__("movl %0,%%cr3": :"r" (cr3));
+       __asm__ __volatile__("movl %0,%%cr3": :"r" (__pa(mm->pgd)));
+}
+
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next)
+{
+       /*
+        * Re-load LDT if necessary
+        */
+       if (prev->segments != next->segments)
+               load_LDT(next);
+
+       /* Re-load page tables */
+       asm volatile("movl %0,%%cr3": :"r" (__pa(next->pgd)));
 }
 
 #endif
index 0bc1afc9150c96e2aec45a7efd072d97be128c78..99b291d405f5372178aec8059d83cb8ee3f6fc97 100644 (file)
@@ -267,7 +267,7 @@ struct tss_struct {
        unsigned short  ss1,__ss1h;
        unsigned long   esp2;
        unsigned short  ss2,__ss2h;
-       unsigned long   cr3;
+       unsigned long   __cr3;
        unsigned long   eip;
        unsigned long   eflags;
        unsigned long   eax,ecx,edx,ebx;
@@ -292,7 +292,6 @@ struct tss_struct {
 
 struct thread_struct {
        unsigned long   esp0;
-       unsigned long   cr3;
        unsigned long   eip;
        unsigned long   esp;
        unsigned long   fs;
@@ -313,7 +312,7 @@ struct thread_struct {
 };
 
 #define INIT_THREAD  {                                         \
-       0,(long) &swapper_pg_dir - PAGE_OFFSET,                 \
+       0,                                                      \
        0, 0, 0, 0,                                             \
        { [0 ... 7] = 0 },      /* debugging registers */       \
        0, 0, 0,                                                \
@@ -330,7 +329,7 @@ struct thread_struct {
        sizeof(init_stack) + (long) &init_stack, /* esp0 */     \
        __KERNEL_DS, 0, /* ss0 */                               \
        0,0,0,0,0,0, /* stack1, stack2 */                       \
-       (long) &swapper_pg_dir - PAGE_OFFSET, /* cr3 */         \
+       0, /* cr3 */                                            \
        0,0, /* eip,eflags */                                   \
        0,0,0,0, /* eax,ecx,edx,ebx */                          \
        0,0,0,0, /* esp,ebp,esi,edi */                          \
index 7c805525c9e5143b47ec2d5361be679cbb13ee14..9b0a0204d18282db1f0decd6166adee731fbe4b2 100644 (file)
@@ -31,13 +31,14 @@ typedef struct siginfo {
                struct {
                        unsigned int _timer1;
                        unsigned int _timer2;
+                       sigval_t _sigval2;      /* FIXME: must map to _sigval below because it is the same */
                } _timer;
 
                /* POSIX.1b signals */
                struct {
                        pid_t _pid;             /* sender's pid */
                        uid_t _uid;             /* sender's uid */
-                       sigval_t _sigval;
+                       sigval_t _sigval;       /* FIXME: move out of union together with _sigval2 */
                } _rt;
 
                /* SIGCHLD */
@@ -67,6 +68,8 @@ typedef struct siginfo {
  */
 #define si_pid         _sifields._kill._pid
 #define si_uid         _sifields._kill._uid
+#define si_timer1      _sifields._timer._timer1
+#define si_timer2      _sifields._timer._timer2
 #define si_status      _sifields._sigchld._status
 #define si_utime       _sifields._sigchld._utime
 #define si_stime       _sifields._sigchld._stime
index b8a150aa7575c6284ffdcb5509e2711f33e8ad4b..91199de7f1cb2a7ccee988c4d636de836c3eece1 100644 (file)
@@ -8,7 +8,7 @@
 #ifdef CONFIG_X86_LOCAL_APIC
 #ifndef ASSEMBLY
 #include <asm/fixmap.h>
-#include <asm/i82489.h>
+#include <asm/apic.h>
 #include <asm/bitops.h>
 #endif
 #endif
@@ -186,6 +186,16 @@ extern inline int cpu_logical_map(int cpu)
        return __cpu_logical_map[cpu];
 }
 
+extern __inline void apic_write(unsigned long reg, unsigned long v)
+{
+       *((volatile unsigned long *)(APIC_BASE+reg))=v;
+}
+
+extern __inline unsigned long apic_read(unsigned long reg)
+{
+       return *((volatile unsigned long *)(APIC_BASE+reg));
+}
+
 
 /*
  *     General functions that each host system must provide.
index c961fdd2e801f2c3cbb9c5f0798f86d4e38e3101..18d814b9662c13e50251efda9d51edcccbc209a7 100644 (file)
 #define __NR_getpmsg           188     /* some people actually want streams */
 #define __NR_putpmsg           189     /* some people actually want streams */
 #define __NR_vfork             190
+#define __NR_timer_create      191
+#define __NR_timer_settime     192
+#define __NR_timer_gettime     193
+#define __NR_timer_getoverrun  194
+#define __NR_timer_delete      195
+#define __NR_clock_gettime     196
+#define __NR_clock_settime     197
+#define __NR_clock_getres      198
 
 /* user-visible error numbers are in the range -1 - -122: see <asm-i386/errno.h> */
 
index 4061e6f72946dbb4b3e1fdaa58e3decc39ccb6a5..27166cd860f6c3ce7697bdd7b74c9b5d75609730 100644 (file)
@@ -67,6 +67,8 @@ typedef struct siginfo {
  */
 #define si_pid         _sifields._kill._pid
 #define si_uid         _sifields._kill._uid
+#define si_timer1      _sifields._timer._timer1
+#define si_timer2      _sifields._timer._timer2
 #define si_status      _sifields._sigchld._status
 #define si_utime       _sifields._sigchld._utime
 #define si_stime       _sifields._sigchld._stime
index 4180f3df7c84f78a586ab66cfd5918cd29e951ca..f74f60ff718ba81ca6a797302832e292fd2a8c43 100644 (file)
 #define __NR_getpmsg           188     /* some people actually want streams */
 #define __NR_putpmsg           189     /* some people actually want streams */
 #define __NR_vfork             190
+#define __NR_timer_create      191
+#define __NR_timer_settime     192
+#define __NR_timer_gettime     193
+#define __NR_timer_getoverrun  194
+#define __NR_timer_delete      195
+#define __NR_clock_gettime     196
+#define __NR_clock_settime     197
+#define __NR_clock_getres      198
 
 /* user-visible error numbers are in the range -1 - -122: see
    <asm-m68k/errno.h> */
index 3e19a3a55b1bd615dbcd02adc33f50996c1827be..7152c88c6c258981ba9109110a9988dbc56839a1 100644 (file)
@@ -75,6 +75,8 @@ typedef struct siginfo {
  */
 #define si_pid         _sifields._kill._pid
 #define si_uid         _sifields._kill._uid
+#define si_timer1      _sifields._timer._timer1
+#define si_timer2      _sifields._timer._timer2
 #define si_status      _sifields._sigchld._status
 #define si_utime       _sifields._sigchld._utime
 #define si_stime       _sifields._sigchld._stime
index 755a4a2c66e30a8bd0024ea2cdb3cbb05816c44d..540da7a2ca79c6772911f9da4fcf5b3057fed3af 100644 (file)
 #define __NR_sendfile                  (__NR_Linux + 207)
 #define __NR_getpmsg                   (__NR_Linux + 208)
 #define __NR_putpmsg                   (__NR_Linux + 209)
+#define __NR_timer_create              (__NR_Linux + 210)
+#define __NR_timer_settime             (__NR_Linux + 211)
+#define __NR_timer_gettime             (__NR_Linux + 212)
+#define __NR_timer_getoverrun          (__NR_Linux + 213)
+#define __NR_timer_delete              (__NR_Linux + 214)
+#define __NR_clock_gettime             (__NR_Linux + 215)
+#define __NR_clock_settime             (__NR_Linux + 216)
+#define __NR_clock_getres              (__NR_Linux + 217)
 
 /*
  * Offset of the last Linux flavoured syscall
index f838fcc82adb8a3becabe73b6fa48cf5baa6a503..3d4660d8ecae04b5a092c793d56046f1fa30f255 100644 (file)
@@ -67,6 +67,8 @@ typedef struct siginfo {
  */
 #define si_pid         _sifields._kill._pid
 #define si_uid         _sifields._kill._uid
+#define si_timer1      _sifields._timer._timer1
+#define si_timer2      _sifields._timer._timer2
 #define si_status      _sifields._sigchld._status
 #define si_utime       _sifields._sigchld._utime
 #define si_stime       _sifields._sigchld._stime
@@ -122,7 +124,7 @@ typedef struct siginfo {
  * SIGSEGV si_codes
  */
 #define SEGV_MAPERR    1       /* address not mapped to object */
-#define SRGV_ACCERR    2       /* invalid permissions for mapped object */
+#define SEGV_ACCERR    2       /* invalid permissions for mapped object */
 #define NSIGSEGV       2
 
 /*
index 38372df08faee50aecf83c96e9f947686298b203..299ad0a56e936304edcc37072798e262166c86f0 100644 (file)
 #define __NR_getpmsg           187     /* some people actually want streams */
 #define __NR_putpmsg           188     /* some people actually want streams */
 #define __NR_vfork             189
+#define __NR_timer_create      190
+#define __NR_timer_settime     191
+#define __NR_timer_gettime     192
+#define __NR_timer_getoverrun  193
+#define __NR_timer_delete      194
+#define __NR_clock_gettime     195
+#define __NR_clock_settime     196
+#define __NR_clock_getres      197
 
 #define __NR(n)        #n
 
index 0a838c3a97476a46b78d6520f1eb26a4b28e3591..aab2d32a063a4ac948cfafa53d3c38f75e8ec9ac 100644 (file)
@@ -70,6 +70,8 @@ typedef struct siginfo {
  */
 #define si_pid         _sifields._kill._pid
 #define si_uid         _sifields._kill._uid
+#define si_timer1      _sifields._timer._timer1
+#define si_timer2      _sifields._timer._timer2
 #define si_status      _sifields._sigchld._status
 #define si_utime       _sifields._sigchld._utime
 #define si_stime       _sifields._sigchld._stime
@@ -126,7 +128,7 @@ typedef struct siginfo {
  * SIGSEGV si_codes
  */
 #define SEGV_MAPERR    1       /* address not mapped to object */
-#define SRGV_ACCERR    2       /* invalid permissions for mapped object */
+#define SEGV_ACCERR    2       /* invalid permissions for mapped object */
 #define NSIGSEGV       2
 
 /*
index 139dc32b542971d219dd457ae7785cf97793ba0a..50b2b77a28a8b9c27581bcd1ce3077c5a25fd5a7 100644 (file)
 #define __NR_fdatasync          253
 #define __NR_nfsservctl         254
 #define __NR_aplib              255
+#define __NR_timer_create      256
+#define __NR_timer_settime     257
+#define __NR_timer_gettime     258
+#define __NR_timer_getoverrun  259
+#define __NR_timer_delete      260
+#define __NR_clock_gettime     261
+#define __NR_clock_settime     262
+#define __NR_clock_getres      263
 
 #define _syscall0(type,name) \
 type name(void) \
index a23240e6623be151a4102d4b30fc446fcccfb00a..454e56a9dac4f025e9e6ad6d58d6858b90711bd4 100644 (file)
@@ -129,6 +129,8 @@ typedef struct siginfo32 {
  */
 #define si_pid         _sifields._kill._pid
 #define si_uid         _sifields._kill._uid
+#define si_timer1      _sifields._timer._timer1
+#define si_timer2      _sifields._timer._timer2
 #define si_status      _sifields._sigchld._status
 #define si_utime       _sifields._sigchld._utime
 #define si_stime       _sifields._sigchld._stime
@@ -185,7 +187,7 @@ typedef struct siginfo32 {
  * SIGSEGV si_codes
  */
 #define SEGV_MAPERR    1       /* address not mapped to object */
-#define SRGV_ACCERR    2       /* invalid permissions for mapped object */
+#define SEGV_ACCERR    2       /* invalid permissions for mapped object */
 #define NSIGSEGV       2
 
 /*
index 87a6833c559410205cca10e500505e3a48fd409c..466317e0e82953f7d9a34a0517e6923780258e56 100644 (file)
 #define __NR_fdatasync          253
 #define __NR_nfsservctl         254
 #define __NR_aplib              255
+#define __NR_timer_create      256
+#define __NR_timer_settime     257
+#define __NR_timer_gettime     258
+#define __NR_timer_getoverrun  259
+#define __NR_timer_delete      260
+#define __NR_clock_gettime     261
+#define __NR_clock_settime     262
+#define __NR_clock_getres      263
 
 #define _syscall0(type,name) \
 type name(void) \
index 5848688e786f41063589b50ae5a675777af1ab57..6ca0ae68b5a839889a864978759f078bca45a3e8 100644 (file)
@@ -14,6 +14,8 @@
 #define PATH_MAX        4095   /* # chars in a path name */
 #define PIPE_BUF        4096   /* # bytes in atomic write to a pipe */
 
+#define MAX_ITIMERS       32    /* # POSIX.1b itimers per process */
+
 #define RTSIG_MAX        32
 
 #endif
index c708aa628e89c3fe471dc0cc81cb2076858f7269..c1c85c98deb7d7746f183edcd45afee8c2808b48 100644 (file)
@@ -35,6 +35,7 @@ extern unsigned long event;
 #define CLONE_PID      0x00001000      /* set if pid shared */
 #define CLONE_PTRACE   0x00002000      /* set if we want to let tracing continue on the child too */
 #define CLONE_VFORK    0x00004000      /* set if the parent wants the child to wake it up on mm_release */
+#define CLONE_ITIMERS   0x00008000      /* set if POSIX.1b itimers are shared */
 
 /*
  * These are the constant used to fake the fixed-point load-average
@@ -223,6 +224,26 @@ struct signal_struct {
  */
 struct user_struct;
 
+/* POSIX.1b interval timer structure. */
+struct k_itimer {
+       spinlock_t it_lock;
+       clockid_t it_clock;             /* which timer type */
+       timer_t it_id;                  /* timer id */
+       int it_overrun;                 /* number of signals overrun */
+       struct sigevent it_signal;      /* signal to be delivered */
+       struct timespec it_interval;    /* interval (rounded to jiffies) */
+       int it_incr;                    /* interval specified in jiffies */
+       struct task_struct *it_process; /* process to send signal to */
+       struct timer_list it_timer;
+};
+
+/* Structure to maintain the dynamically created POSIX.1b interval timers. */
+struct itimer_struct {
+       atomic_t count;
+       spinlock_t its_lock;
+       struct k_itimer *itimer[MAX_ITIMERS];   
+};
+
 struct task_struct {
 /* these are hardcoded - don't touch */
        volatile long state;    /* -1 unrunnable, 0 runnable, >0 stopped */
@@ -278,6 +299,7 @@ struct task_struct {
        unsigned long it_real_value, it_prof_value, it_virt_value;
        unsigned long it_real_incr, it_prof_incr, it_virt_incr;
        struct timer_list real_timer;
+       struct itimer_struct *posix_timers; /* POSIX.1b Interval Timers */
        struct tms times;
        unsigned long start_time;
        long per_cpu_utime[NR_CPUS], per_cpu_stime[NR_CPUS];
@@ -315,6 +337,7 @@ struct task_struct {
        spinlock_t sigmask_lock;        /* Protects signal and blocked */
        struct signal_struct *sig;
        sigset_t signal, blocked;
+       siginfo_t nrt_info[SIGRTMIN];   /* siginfo for non RT signals */
        struct signal_queue *sigqueue, **sigqueue_tail;
        unsigned long sas_ss_sp;
        size_t sas_ss_size;
@@ -364,6 +387,7 @@ struct task_struct {
 /* chld wait */        __WAIT_QUEUE_HEAD_INITIALIZER(name.wait_chldexit), NULL, \
 /* timeout */  SCHED_OTHER,0,0,0,0,0,0,0, \
 /* timer */    { NULL, NULL, 0, 0, it_real_fn }, \
+/* POSIX.1b timer */ NULL, \
 /* utime */    {0,0,0,0},0, \
 /* per CPU times */ {0, }, {0, }, \
 /* flt */      0,0,0,0,0,0, \
@@ -382,7 +406,7 @@ struct task_struct {
 /* fs */       &init_fs, \
 /* files */    &init_files, \
 /* mm */       NULL, &init_mm, \
-/* signals */  SPIN_LOCK_UNLOCKED, &init_signals, {{0}}, {{0}}, NULL, &init_task.sigqueue, 0, 0, \
+/* signals */  SPIN_LOCK_UNLOCKED, &init_signals, {{0}}, {{0}}, {{0,},}, NULL, &init_task.sigqueue, 0, 0, \
 }
 
 #ifndef INIT_TASK_SIZE
@@ -614,6 +638,7 @@ extern void exit_mm(struct task_struct *);
 extern void exit_fs(struct task_struct *);
 extern void exit_files(struct task_struct *);
 extern void exit_sighand(struct task_struct *);
+extern void exit_itimers(struct task_struct *);
 
 extern int do_execve(char *, char **, char **, struct pt_regs *);
 extern int do_fork(unsigned long, unsigned long, struct pt_regs *);
index 53a125a08a14ae50347b21334d91ce2891afe783..8b30d460884b1674369915aa36627f0b2f1e7e12 100644 (file)
@@ -26,6 +26,19 @@ struct timespec {
  */
 #define MAX_JIFFY_OFFSET ((~0UL >> 1)-1)
 
+/* Parameters used to convert the timespec values */
+#ifndef USEC_PER_SEC
+#define USEC_PER_SEC (1000000L)
+#endif
+
+#ifndef NSEC_PER_SEC
+#define NSEC_PER_SEC (1000000000L)
+#endif
+
+#ifndef NSEC_PER_USEC
+#define NSEC_PER_USEC (1000L)
+#endif
+
 static __inline__ unsigned long
 timespec_to_jiffies(struct timespec *value)
 {
@@ -34,15 +47,15 @@ timespec_to_jiffies(struct timespec *value)
 
        if (sec >= (MAX_JIFFY_OFFSET / HZ))
                return MAX_JIFFY_OFFSET;
-       nsec += 1000000000L / HZ - 1;
-       nsec /= 1000000000L / HZ;
+       nsec += NSEC_PER_SEC / HZ - 1;
+       nsec /= NSEC_PER_SEC / HZ;
        return HZ * sec + nsec;
 }
 
 static __inline__ void
 jiffies_to_timespec(unsigned long jiffies, struct timespec *value)
 {
-       value->tv_nsec = (jiffies % HZ) * (1000000000L / HZ);
+       value->tv_nsec = (jiffies % HZ) * (NSEC_PER_SEC / HZ);
        value->tv_sec = jiffies / HZ;
 }
  
@@ -89,4 +102,23 @@ struct      itimerval {
        struct  timeval it_value;       /* current value */
 };
 
+
+/* 
+ * Data types for POSIX.1b interval timers.
+ */
+typedef int clockid_t;
+typedef int timer_t;
+
+/*
+ * The IDs of the various system clocks (for POSIX.1b interval timers).
+ */
+#define CLOCK_REALTIME 0
+
+/*
+ * The various flags for setting POSIX.1b interval timers.
+ */
+
+#define TIMER_ABSTIME 0x01
+
+
 #endif
index c8021906fc159dffceb82a737d5a03e6be83aed1..d95a32f65a76293b9eedb90e7ab065befbda7f26 100644 (file)
@@ -229,6 +229,34 @@ void exit_sighand(struct task_struct *tsk)
        __exit_sighand(tsk);
 }
 
+static inline void __exit_itimers(struct task_struct *tsk)
+{
+       struct itimer_struct *timers = tsk->posix_timers;
+       struct k_itimer *timr;
+       int i;
+
+       if (timers == NULL) return;
+       
+       if (atomic_dec_and_test(&timers->count)) {
+               tsk->posix_timers = NULL;
+               for (i = 0; i < MAX_ITIMERS; i++) {
+                       timr = timers->itimer[i];
+                       if (timr) {
+                               start_bh_atomic();
+                               del_timer(&timr->it_timer);
+                               end_bh_atomic();
+                               kfree(timr);
+                       }
+               }
+               kfree(timers);
+       }
+}
+
+void exit_itimers(struct task_struct *tsk)
+{
+       __exit_itimers(tsk);
+}
+
 /*
  * Turn us into a lazy TLB process if we
  * aren't already..
@@ -352,6 +380,7 @@ fake_volatile:
        __exit_files(tsk);
        __exit_fs(tsk);
        __exit_sighand(tsk);
+       __exit_itimers(tsk);
        exit_thread();
        tsk->state = TASK_ZOMBIE;
        tsk->exit_code = code;
index b11112ceb817850f1af83fc7e43dd575e7003b25..e6f1417dcf6bd1626f9ba56da92c1d520732ba14 100644 (file)
@@ -304,8 +304,12 @@ struct mm_struct * mm_alloc(void)
                atomic_set(&mm->mm_count, 1);
                init_MUTEX(&mm->mmap_sem);
                mm->page_table_lock = SPIN_LOCK_UNLOCKED;
+               mm->pgd = pgd_alloc();
+               if (mm->pgd)
+                       return mm;
+               kmem_cache_free(mm_cachep, mm);
        }
-       return mm;
+       return NULL;
 }
 
 /* Please note the differences between mmput and mm_release.
@@ -390,10 +394,6 @@ static inline int copy_mm(unsigned long clone_flags, struct task_struct * tsk)
        tsk->mm = mm;
        tsk->active_mm = mm;
 
-       mm->pgd = pgd_alloc();
-       if (!mm->pgd)
-               goto free_mm;
-
        /*
         * child gets a private LDT (if there was an LDT in the parent)
         */
@@ -411,9 +411,6 @@ good_mm:
        init_new_context(tsk,mm);
        return 0;
 
-free_mm:
-       kmem_cache_free(mm_cachep, mm);
-       return retval;
 free_pt:
        mmput(mm);
 fail_nomem:
@@ -550,6 +547,24 @@ static inline void copy_flags(unsigned long clone_flags, struct task_struct *p)
        p->flags = new_flags;
 }
 
+
+static inline int copy_itimers(unsigned long clone_flags, struct task_struct * tsk)
+{
+       if (clone_flags & CLONE_ITIMERS) {
+               atomic_inc(&tsk->posix_timers->count);
+               return 0;
+       }
+
+       tsk->posix_timers = kmalloc(sizeof(*tsk->posix_timers), GFP_KERNEL);
+       if (tsk->posix_timers == NULL) return -1;
+       spin_lock_init(&tsk->posix_timers->its_lock);
+       atomic_set(&tsk->posix_timers->count, 1);
+       memset(tsk->posix_timers->itimer, 0, sizeof(tsk->posix_timers->itimer));
+
+       return 0;
+}
+
+
 /*
  *  Ok, this is the main fork-routine. It copies the system process
  * information (task[nr]) and sets up the necessary registers. It
@@ -648,6 +663,8 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs)
                goto bad_fork_cleanup_files;
        if (copy_sighand(clone_flags, p))
                goto bad_fork_cleanup_fs;
+       if (copy_itimers(clone_flags, p))
+               goto bad_fork_cleanup_itimers;
        if (copy_mm(clone_flags, p))
                goto bad_fork_cleanup_sighand;
        retval = copy_thread(0, clone_flags, usp, p, regs);
@@ -692,6 +709,8 @@ fork_out:
                down(&sem);
        return retval;
 
+bad_fork_cleanup_itimers:
+       exit_itimers(p);
 bad_fork_cleanup_sighand:
        exit_sighand(p);
 bad_fork_cleanup_fs:
index 1b4661c397deb7552c8f10e7862c1840444b63a9..bf6d1c003f1497795cd9f446af7c4dfcf5849a56 100644 (file)
@@ -9,14 +9,16 @@
 #include <linux/mm.h>
 #include <linux/smp_lock.h>
 #include <linux/interrupt.h>
+#include <linux/malloc.h>
+#include <linux/time.h>
 
 #include <asm/uaccess.h>
 
 /*
- * change timeval to jiffies, trying to avoid the 
+ * change timeval to jiffies, trying to avoid the
  * most obvious overflows..
  *
- * The tv_*sec values are signed, but nothing seems to 
+ * The tv_*sec values are signed, but nothing seems to
  * indicate whether we really should use them as signed values
  * when doing itimers. POSIX doesn't mention this (but if
  * alarm() uses itimers without checking, we have to use unsigned
@@ -168,6 +170,389 @@ asmlinkage int sys_setitimer(int which, struct itimerval *value,
                return error;
 
        if (copy_to_user(ovalue, &get_buffer, sizeof(get_buffer)))
-               return -EFAULT; 
+               return -EFAULT;
+       return 0;
+}
+
+/* PRECONDITION:
+ * timr->it_lock must be locked
+ */
+static void timer_notify_task(struct k_itimer *timr)
+{
+       struct siginfo info;
+       int ret;
+
+       if (timr->it_signal.sigev_notify == SIGEV_SIGNAL) {
+
+               /* Send signal to the process that owns this timer. */
+               info.si_signo = timr->it_signal.sigev_signo;
+               info.si_errno = 0;
+               info.si_code = SI_TIMER;
+               /* TODO: if someone has better ideas what to put in 
+                * the next two fields...
+                * si_timer1 is currently used in signal.c to check
+                * whether a signal from this timer is already in the signal
+                * queue.
+                */
+               info.si_timer1 = timr->it_id;
+               info.si_timer2 = 0;
+               info.si_value = timr->it_signal.sigev_value;
+               ret = send_sig_info(info.si_signo, &info, timr->it_process);
+               switch (ret) {
+               case 0:         /* all's well */
+                       timr->it_overrun = 0;
+                       break;
+               case 1: /* signal from this timer was already in the queue */
+                       timr->it_overrun++;
+                       break;
+               default:
+                       printk(KERN_WARNING "sending signal failed: %d\n", ret);
+                       break;
+               }
+       }
+}
+
+/* This function gets called when a POSIX.1b interval timer expires. */
+static void posix_timer_fn(unsigned long __data)
+{  
+       struct k_itimer *timr = (struct k_itimer *)__data;
+       unsigned long interval;
+
+       spin_lock(&timr->it_lock);
+       
+       timer_notify_task(timr);
+
+       /* Set up the timer for the next interval (if there is one) */
+       if ((interval = timr->it_incr) == 0) goto out;
+               
+       if (interval > (unsigned long) LONG_MAX)
+               interval = LONG_MAX;
+       timr->it_timer.expires = jiffies + interval;
+       add_timer(&timr->it_timer);
+out:
+       spin_unlock(&timr->it_lock);
+}
+
+/* Find the first available slot for the new timer. */
+static int timer_find_slot(struct itimer_struct *timers)
+{
+       int i;
+
+       for (i = 0; i < MAX_ITIMERS; i++) {
+               if (timers->itimer[i] == NULL) return i;
+       }
+       return -1;
+}
+
+static int good_sigevent(const struct sigevent *sigev)
+{
+       switch (sigev->sigev_notify) {
+       case SIGEV_NONE:
+               break;
+       case SIGEV_SIGNAL:
+               if ((sigev->sigev_signo <= 0) ||
+                   (sigev->sigev_signo > SIGRTMAX))
+                       return 0;
+               break;
+       default:
+               return 0;
+       }
+       return 1;
+}
+
+/* Create a POSIX.1b interval timer. */
+
+asmlinkage int sys_timer_create(clockid_t which_clock,
+                               struct sigevent *timer_event_spec,
+                               timer_t *created_timer_id)
+{
+       int error = 0;
+       struct k_itimer *new_timer = NULL;
+       struct itimer_struct *timers = current->posix_timers;
+       int new_timer_id;
+       /* Right now, we only support CLOCK_REALTIME for timers. */
+       if (which_clock != CLOCK_REALTIME) return -EINVAL;
+
+       new_timer = (struct k_itimer *)kmalloc(sizeof(*new_timer), GFP_KERNEL);
+       if (new_timer == NULL) return -EAGAIN;
+
+       spin_lock_init(&new_timer->it_lock);
+       new_timer->it_clock = which_clock;
+       new_timer->it_incr = 0;
+       new_timer->it_overrun = 0;
+
+       if (timer_event_spec) {
+               if (copy_from_user(&new_timer->it_signal, timer_event_spec,
+                                  sizeof(new_timer->it_signal))) {
+                       error = -EFAULT;
+                       goto out;
+               }
+               if (!good_sigevent(&new_timer->it_signal)) {
+                       error = -EINVAL;
+                       goto out;
+               }
+       }
+       else {
+               new_timer->it_signal.sigev_notify = SIGEV_SIGNAL;
+               new_timer->it_signal.sigev_signo = SIGALRM;
+       }
+
+       new_timer->it_interval.tv_sec = 0;
+       new_timer->it_interval.tv_nsec = 0;
+       new_timer->it_process = current;
+       new_timer->it_timer.next = NULL;
+       new_timer->it_timer.prev = NULL;
+       new_timer->it_timer.expires = 0;
+       new_timer->it_timer.data = (unsigned long)new_timer;
+       new_timer->it_timer.function = posix_timer_fn;
+
+       spin_lock(&timers->its_lock);
+
+       new_timer_id = timer_find_slot(timers);
+       if (new_timer_id == -1) {
+               error = -EAGAIN;
+               goto out;
+       }
+       new_timer->it_id = new_timer_id;
+       timers->itimer[new_timer_id] = new_timer;
+       if (timer_event_spec == NULL) {
+               new_timer->it_signal.sigev_value.sival_int = new_timer_id;
+       }
+
+       if (copy_to_user(created_timer_id, &new_timer_id, sizeof(new_timer_id))) {
+               error = -EFAULT;
+               timers->itimer[new_timer_id] = NULL;
+       }
+
+       spin_unlock(&timers->its_lock);
+out:
+       if (error) {
+               kfree(new_timer);
+       }
+       return error;
+}
+
+
+/* good_timespec
+ *
+ * This function checks the elements of a timespec structure.
+ *
+ * Arguments:
+ * ts       : Pointer to the timespec structure to check
+ *
+ * Return value:
+ * If a NULL pointer was passed in, or the tv_nsec field was less than 0 or
+ * greater than NSEC_PER_SEC, or the tv_sec field was less than 0, this
+ * function returns 0. Otherwise it returns 1.
+ */
+
+static int good_timespec(const struct timespec *ts)
+{
+       if (ts == NULL) return 0;
+       if (ts->tv_sec < 0) return 0;
+       if ((ts->tv_nsec < 0) || (ts->tv_nsec >= NSEC_PER_SEC)) return 0;
+       return 1;
+}
+
+static inline struct k_itimer* lock_timer(struct task_struct *tsk, timer_t timer_id)
+{
+       struct k_itimer *timr;
+
+       if ((timer_id < 0) || (timer_id >= MAX_ITIMERS)) return NULL;
+       spin_lock(&tsk->posix_timers->its_lock);
+       timr = tsk->posix_timers->itimer[timer_id];
+       if (timr) spin_lock(&timr->it_lock);
+       spin_unlock(&tsk->posix_timers->its_lock);
+       return timr;
+}
+
+static inline void unlock_timer(struct k_itimer *timr)
+{
+       spin_unlock(&timr->it_lock);
+}
+
+/* Get the time remaining on a POSIX.1b interval timer. */
+static void do_timer_gettime(struct k_itimer *timr,
+                            struct itimerspec *cur_setting)
+{
+       unsigned long expires = timr->it_timer.expires;
+
+       if (expires) expires -= jiffies;
+       
+       jiffies_to_timespec(expires, &cur_setting->it_value);
+       cur_setting->it_interval = timr->it_interval;
+}
+
+/* Get the time remaining on a POSIX.1b interval timer. */
+asmlinkage int sys_timer_gettime(timer_t timer_id, struct itimerspec *setting)
+{
+       struct k_itimer *timr;
+       struct itimerspec cur_setting;
+
+       timr = lock_timer(current, timer_id);
+       if (!timr) return -EINVAL;
+
+       do_timer_gettime(timr, &cur_setting);
+
+       unlock_timer(timr);
+       
+       copy_to_user_ret(setting, &cur_setting, sizeof(cur_setting), -EFAULT);
+
+       return 0;
+}
+
+/* Get the number of overruns of a POSIX.1b interval timer */
+asmlinkage int sys_timer_getoverrun(timer_t timer_id)
+{
+       struct k_itimer *timr;
+       int overrun;
+
+       timr = lock_timer(current, timer_id);
+       if (!timr) return -EINVAL;
+
+       overrun = timr->it_overrun;
+       
+       unlock_timer(timr);
+
+       return overrun;
+}
+
+static void timer_value_abs_to_rel(struct timespec *val)
+{
+       struct timeval tv;
+       struct timespec ts;
+
+       do_gettimeofday(&tv);
+       ts.tv_sec = tv.tv_sec;
+       ts.tv_nsec = tv.tv_usec * NSEC_PER_USEC;
+
+       /* check whether the time lies in the past */
+       if ((val->tv_sec < ts.tv_sec) || 
+           ((val->tv_sec == ts.tv_sec) &&
+            (val->tv_nsec <= ts.tv_nsec))) {
+               /* expire immediately */
+               val->tv_sec = 0;
+               val->tv_nsec = 0;
+       }
+       else {
+               val->tv_sec -= ts.tv_sec;
+               val->tv_nsec -= ts.tv_nsec;
+               if (val->tv_nsec < 0) {
+                       val->tv_nsec += NSEC_PER_SEC;
+                       val->tv_sec--;
+               }
+       }
+}
+
+/* Set a POSIX.1b interval timer. */
+static void do_timer_settime(struct k_itimer *timr, int flags,
+                            struct itimerspec *new_setting,
+                            struct itimerspec *old_setting)
+{
+       /* disable the timer */
+       start_bh_atomic();
+       del_timer(&timr->it_timer);
+       end_bh_atomic();
+
+       if (old_setting) {
+               do_timer_gettime(timr, old_setting);
+       }
+
+       /* switch off the timer when it_value is zero */
+       if ((new_setting->it_value.tv_sec == 0) &&
+           (new_setting->it_value.tv_nsec == 0)) {
+               timr->it_incr = 0;
+               timr->it_timer.expires = 0;
+               timr->it_interval.tv_sec = 0;
+               timr->it_interval.tv_nsec = 0;
+               return;
+       }
+
+       timr->it_incr = timespec_to_jiffies(&new_setting->it_interval);
+       /* save the interval rounded to jiffies */
+       jiffies_to_timespec(timr->it_incr, &timr->it_interval);
+
+       if (flags & TIMER_ABSTIME) {
+               timer_value_abs_to_rel(&new_setting->it_value);
+       }
+
+       timr->it_timer.expires = timespec_to_jiffies(&new_setting->it_value) + jiffies;
+
+       /*
+        * For some reason the timer does not fire immediately if expires is
+        * equal to jiffies, so the timer callback function is called directly.
+        */
+       if (timr->it_timer.expires == jiffies) {
+               posix_timer_fn((unsigned long)timr);
+       }
+       else {
+               add_timer(&timr->it_timer);
+       }
+}
+
+
+/* Set a POSIX.1b interval timer */
+asmlinkage int sys_timer_settime(timer_t timer_id, int flags,
+                                const struct itimerspec *new_setting,
+                                struct itimerspec *old_setting)
+{
+       struct k_itimer *timr;
+       struct itimerspec new_spec, old_spec;
+       int error = 0;
+
+       timr = lock_timer(current, timer_id);
+       if (!timr) return -EINVAL;
+
+       if (new_setting == NULL) {
+               error = -EINVAL;
+               goto out;
+       }
+
+       if (copy_from_user(&new_spec, new_setting, sizeof(new_spec))) {
+               error = -EFAULT;
+               goto out;
+       }
+
+       if ((!good_timespec(&new_spec.it_interval)) ||
+           (!good_timespec(&new_spec.it_value))) {
+               error = -EINVAL;
+               goto out;
+       }
+
+       do_timer_settime(timr, flags, &new_spec,
+                        old_setting ? &old_spec : NULL);
+
+       if (old_setting) {
+               if (copy_to_user(old_setting, &old_spec, sizeof(old_spec))) {
+                       error = -EFAULT;
+               }
+       }
+
+out:
+       unlock_timer(timr);
+       return error;
+}
+
+
+/* Delete a POSIX.1b interval timer. */
+asmlinkage int sys_timer_delete(timer_t timer_id)
+{
+       struct k_itimer *timr;
+
+       timr = lock_timer(current, timer_id);
+       if (!timr) return -EINVAL;
+
+       start_bh_atomic();
+       del_timer(&timr->it_timer);
+       end_bh_atomic();
+
+       spin_lock(&current->posix_timers->its_lock);
+
+       kfree(timr);
+       current->posix_timers->itimer[timer_id] = NULL;
+
+       spin_unlock(&current->posix_timers->its_lock);
+
        return 0;
 }
index aed41e981afc1ecfb740570c119cdaa096ee79e8..d5da20cb2e7d5bf6f30691f95ac5bd98bc9d9cad 100644 (file)
@@ -790,16 +790,22 @@ still_running_back:
         */
        {
                struct mm_struct *mm = next->mm;
+               struct mm_struct *oldmm = prev->active_mm;
                if (!mm) {
-                       mm = prev->active_mm;
-                       set_mmu_context(prev,next);
                        if (next->active_mm) BUG();
-                       next->active_mm = mm;
-                       atomic_inc(&mm->mm_count);
+                       next->active_mm = oldmm;
+                       atomic_inc(&oldmm->mm_count);
+               } else {
+                       if (next->active_mm != mm) BUG();
+                       if (mm != oldmm)
+                               switch_mm(oldmm, mm);
                }
        }
 
-       get_mmu_context(next);
+       /*
+        * This just switches the register state and the
+        * stack.
+        */
        switch_to(prev, next, prev);
        __schedule_tail(prev);
 
index 53ee45120823cdcaf5b89c2b5a04393377373000..4cd2f6f54c57446f6b77841a8d0e40f418d5f903 100644 (file)
@@ -132,17 +132,7 @@ printk("SIG dequeue (%s:%d): %d ", current->comm, current->pid,
 
                /* Collect the siginfo appropriate to this signal.  */
                if (sig < SIGRTMIN) {
-                       /* XXX: As an extension, support queueing exactly
-                          one non-rt signal if SA_SIGINFO is set, so that
-                          we can get more detailed information about the
-                          cause of the signal.  */
-                       /* Deciding not to init these couple of fields is
-                          more expensive that just initializing them.  */
-                       info->si_signo = sig;
-                       info->si_errno = 0;
-                       info->si_code = 0;
-                       info->si_pid = 0;
-                       info->si_uid = 0;
+                       *info = current->nrt_info[sig];
                } else {
                        struct signal_queue *q, **pp;
                        pp = &current->sigqueue;
@@ -185,8 +175,6 @@ printk("SIG dequeue (%s:%d): %d ", current->comm, current->pid,
                        sigdelset(&current->signal, sig);
                recalc_sigpending(current);
 
-               /* XXX: Once POSIX.1b timers are in, if si_code == SI_TIMER,
-                  we need to xchg out the timer overrun values.  */
        } else {
                /* XXX: Once CLONE_PID is in to join those "threads" that are
                   part of the same "process", look for signals sent to the
@@ -247,6 +235,29 @@ static int ignored_signal(int sig, struct task_struct *t)
        return 1;
 }
 
+static void set_siginfo(siginfo_t *dst, const siginfo_t *src, int sig)
+{
+       switch ((unsigned long)src) {
+       case 0:
+               dst->si_signo = sig;
+               dst->si_errno = 0;
+               dst->si_code = SI_USER;
+               dst->si_pid = current->pid;
+               dst->si_uid = current->uid;
+               break;
+       case 1:
+               dst->si_signo = sig;
+               dst->si_errno = 0;
+               dst->si_code = SI_KERNEL;
+               dst->si_pid = 0;
+               dst->si_uid = 0;
+               break;
+       default:
+               *dst = *src;
+               break;
+       }
+}
+
 int
 send_sig_info(int sig, struct siginfo *info, struct task_struct *t)
 {
@@ -306,12 +317,10 @@ printk("SIG queue (%s:%d): %d ", t->comm, t->pid, sig);
 
        if (sig < SIGRTMIN) {
                /* Non-real-time signals are not queued.  */
-               /* XXX: As an extension, support queueing exactly one
-                  non-rt signal if SA_SIGINFO is set, so that we can
-                  get more detailed information about the cause of
-                  the signal.  */
                if (sigismember(&t->signal, sig))
                        goto out;
+               set_siginfo(&t->nrt_info[sig], info, sig);
+
        } else {
                /* Real-time signals must be queued if sent by sigqueue, or
                   some other real-time mechanism.  It is implementation
@@ -323,6 +332,21 @@ printk("SIG queue (%s:%d): %d ", t->comm, t->pid, sig);
 
                struct signal_queue *q = 0;
 
+               /* In case of a POSIX timer generated signal you must check 
+                  if a signal from this timer is already in the queue */
+               if (info && (info->si_code == SI_TIMER)) {
+                       for (q = t->sigqueue; q; q = q->next) {
+                               if ((q->info.si_code == SI_TIMER) &&
+                                   (q->info.si_timer1 == info->si_timer1)) {
+                                       /* this special value (1) is recognized
+                                          only by posix_timer_fn() in
+                                          itimer.c */
+                                       ret = 1;
+                                       goto out;
+                               }
+                       }
+               }
+
                if (atomic_read(&nr_queued_signals) < max_queued_signals) {
                        q = (struct signal_queue *)
                            kmem_cache_alloc(signal_queue_cachep, GFP_ATOMIC);
@@ -333,25 +357,7 @@ printk("SIG queue (%s:%d): %d ", t->comm, t->pid, sig);
                        q->next = NULL;
                        *t->sigqueue_tail = q;
                        t->sigqueue_tail = &q->next;
-                       switch ((unsigned long) info) {
-                       case 0:
-                               q->info.si_signo = sig;
-                               q->info.si_errno = 0;
-                               q->info.si_code = SI_USER;
-                               q->info.si_pid = current->pid;
-                               q->info.si_uid = current->uid;
-                               break;
-                       case 1:
-                               q->info.si_signo = sig;
-                               q->info.si_errno = 0;
-                               q->info.si_code = SI_KERNEL;
-                               q->info.si_pid = 0;
-                               q->info.si_uid = 0;
-                               break;
-                       default:
-                               q->info = *info;
-                               break;
-                       }
+                       set_siginfo(&q->info, info, sig);
                } else {
                        /* If this was sent by a rt mechanism, try again.  */
                        if (info->si_code < 0) {
index 911442dad460c4c0a032b2f835288a4c41cfa1ca..9f778fd4cdb726fefec3db45da21bbf76533571a 100644 (file)
@@ -414,3 +414,57 @@ asmlinkage int sys_adjtimex(struct timex *txc_p)
        ret = do_adjtimex(&txc);
        return copy_to_user(txc_p, &txc, sizeof(struct timex)) ? -EFAULT : ret;
 }
+
+
+/* POSIX.1b clock functions */
+
+asmlinkage int sys_clock_gettime(clockid_t clock_id, struct timespec *ts)
+{
+       struct timespec kts;
+       struct timeval ktv;
+
+       if (clock_id != CLOCK_REALTIME) return -EINVAL;
+       
+       if (ts == NULL) return 0;
+               
+       do_gettimeofday(&ktv);
+       kts.tv_sec = ktv.tv_sec;
+       kts.tv_nsec = ktv.tv_usec * NSEC_PER_USEC;
+       if (copy_to_user(ts, &kts, sizeof(kts))) return -EFAULT;
+
+       return 0;
+}
+
+
+asmlinkage int sys_clock_settime(clockid_t clock_id,
+                                const struct timespec *ts)
+{
+       struct timespec new_ts;
+       struct timeval tv;
+
+       if (clock_id != CLOCK_REALTIME) return -EINVAL;
+
+       if (ts == NULL) return 0;
+
+       if (copy_from_user(&new_ts, ts, sizeof(*ts))) return -EFAULT;
+       tv.tv_sec = new_ts.tv_sec;
+       tv.tv_usec = new_ts.tv_nsec / NSEC_PER_USEC;
+       return do_sys_settimeofday(&tv, NULL);
+}
+
+
+asmlinkage int sys_clock_getres(clockid_t clock_id,
+                               struct timespec *res)
+{
+       struct timespec kres;
+
+       if (clock_id != CLOCK_REALTIME) return -EINVAL;
+
+       if (res == NULL) return 0;
+
+       kres.tv_sec = 0;
+       kres.tv_nsec = NSEC_PER_SEC / HZ;
+       if (copy_to_user(res, &kres, sizeof(kres))) return -EFAULT;
+
+       return 0;
+}