summaryrefslogtreecommitdiffstats
path: root/include/asm-i386
diff options
context:
space:
mode:
Diffstat (limited to 'include/asm-i386')
-rw-r--r--include/asm-i386/apic.h267
-rw-r--r--include/asm-i386/hw_irq.h44
-rw-r--r--include/asm-i386/irq.h2
-rw-r--r--include/asm-i386/keyboard.h24
-rw-r--r--include/asm-i386/mmx.h14
-rw-r--r--include/asm-i386/msr.h2
-rw-r--r--include/asm-i386/page.h18
-rw-r--r--include/asm-i386/processor.h3
-rw-r--r--include/asm-i386/smp.h49
-rw-r--r--include/asm-i386/string-486.h88
-rw-r--r--include/asm-i386/string.h44
-rw-r--r--include/asm-i386/uaccess.h3
12 files changed, 477 insertions, 81 deletions
diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h
index 7b035d9a3..69fcbac3e 100644
--- a/include/asm-i386/apic.h
+++ b/include/asm-i386/apic.h
@@ -10,7 +10,10 @@
#define APIC_ID 0x20
#define GET_APIC_ID(x) (((x)>>24)&0x0F)
-#define APIC_VERSION 0x30
+#define APIC_LVR 0x30
+#define GET_APIC_VERSION(x) ((x)&0xFF)
+#define GET_APIC_MAXLVT(x) (((x)>>16)&0x0F)
+#define APIC_INTEGRATED(x) ((x)&0xF0)
#define APIC_TASKPRI 0x80
#define APIC_TPRI_MASK 0xFF
#define APIC_ARBPRI 0x90
@@ -23,6 +26,7 @@
#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_ALL_CPUS 0xFF
#define APIC_DFR 0xE0
#define GET_APIC_DFR(x) (((x)>>28)&0x0F)
#define SET_APIC_DFR(x) ((x)<<28)
@@ -62,7 +66,14 @@
#define GET_APIC_DEST_FIELD(x) (((x)>>24)&0xFF)
#define SET_APIC_DEST_FIELD(x) ((x)<<24)
#define APIC_LVTT 0x320
+#define APIC_LVTPC 0x340
#define APIC_LVT0 0x350
+#define APIC_LVT_TIMER_BASE_MASK (0x3<<18)
+#define GET_APIC_TIMER_BASE(x) (((x)>>18)&0x3)
+#define SET_APIC_TIMER_BASE(x) (((x)<<18))
+#define APIC_TIMER_BASE_CLKIN 0x0
+#define APIC_TIMER_BASE_TMBASE 0x1
+#define APIC_TIMER_BASE_DIV 0x2
#define APIC_LVT_TIMER_PERIODIC (1<<17)
#define APIC_LVT_MASKED (1<<16)
#define APIC_LVT_LEVEL_TRIGGER (1<<15)
@@ -75,10 +86,11 @@
#define APIC_MODE_NMI 0x4
#define APIC_MODE_EXINT 0x7
#define APIC_LVT1 0x360
-#define APIC_LVERR 0x370
+#define APIC_LVTERR 0x370
#define APIC_TMICT 0x380
#define APIC_TMCCT 0x390
#define APIC_TDCR 0x3E0
+#define APIC_TDR_DIV_TMBASE (1<<2)
#define APIC_TDR_DIV_1 0xB
#define APIC_TDR_DIV_2 0x0
#define APIC_TDR_DIV_4 0x1
@@ -92,4 +104,255 @@
#define MAX_IO_APICS 8
+/*
+ * the local APIC register structure, memory mapped. Not terribly well
+ * tested, but we might eventually use this one in the future - the
+ * problem why we cannot use it right now is the P5 APIC, it has an
+ * errata which cannot take 8-bit reads and writes, only 32-bit ones ...
+ */
+#define u32 unsigned int
+
+#define lapic ((volatile struct local_apic *)APIC_BASE)
+
+struct local_apic {
+
+/*000*/ struct { u32 __reserved[4]; } __reserved_01;
+
+/*010*/ struct { u32 __reserved[4]; } __reserved_02;
+
+/*020*/ struct { /* APIC ID Register */
+ u32 __reserved_1 : 24,
+ phys_apic_id : 4,
+ __reserved_2 : 4;
+ u32 __reserved[3];
+ } id;
+
+/*030*/ const
+ struct { /* APIC Version Register */
+ u32 version : 8,
+ __reserved_1 : 8,
+ max_lvt : 8,
+ __reserved_2 : 8;
+ u32 __reserved[3];
+ } version;
+
+/*040*/ struct { u32 __reserved[4]; } __reserved_03;
+
+/*050*/ struct { u32 __reserved[4]; } __reserved_04;
+
+/*060*/ struct { u32 __reserved[4]; } __reserved_05;
+
+/*070*/ struct { u32 __reserved[4]; } __reserved_06;
+
+/*080*/ struct { /* Task Priority Register */
+ u32 priority : 8,
+ __reserved_1 : 24;
+ u32 __reserved_2[3];
+ } tpr;
+
+/*090*/ const
+ struct { /* Arbitration Priority Register */
+ u32 priority : 8,
+ __reserved_1 : 24;
+ u32 __reserved_2[3];
+ } apr;
+
+/*0A0*/ const
+ struct { /* Processor Priority Register */
+ u32 priority : 8,
+ __reserved_1 : 24;
+ u32 __reserved_2[3];
+ } ppr;
+
+/*0B0*/ struct { /* End Of Interrupt Register */
+ u32 eoi;
+ u32 __reserved[3];
+ } eoi;
+
+/*0C0*/ struct { u32 __reserved[4]; } __reserved_07;
+
+/*0D0*/ struct { /* Logical Destination Register */
+ u32 __reserved_1 : 24,
+ logical_dest : 8;
+ u32 __reserved_2[3];
+ } ldr;
+
+/*0E0*/ struct { /* Destination Format Register */
+ u32 __reserved_1 : 28,
+ model : 4;
+ u32 __reserved_2[3];
+ } dfr;
+
+/*0F0*/ struct { /* Spurious Interrupt Vector Register */
+ u32 spurious_vector : 8,
+ apic_enabled : 1,
+ focus_cpu : 1,
+ __reserved_2 : 22;
+ u32 __reserved_3[3];
+ } svr;
+
+/*100*/ struct { /* In Service Register */
+/*170*/ u32 bitfield;
+ u32 __reserved[3];
+ } isr [8];
+
+/*180*/ struct { /* Trigger Mode Register */
+/*1F0*/ u32 bitfield;
+ u32 __reserved[3];
+ } tmr [8];
+
+/*200*/ struct { /* Interrupt Request Register */
+/*270*/ u32 bitfield;
+ u32 __reserved[3];
+ } irr [8];
+
+/*280*/ union { /* Error Status Register */
+ struct {
+ u32 send_cs_error : 1,
+ receive_cs_error : 1,
+ send_accept_error : 1,
+ receive_accept_error : 1,
+ __reserved_1 : 1,
+ send_illegal_vector : 1,
+ receive_illegal_vector : 1,
+ illegal_register_address : 1,
+ __reserved_2 : 24;
+ u32 __reserved_3[3];
+ } error_bits;
+ struct {
+ u32 errors;
+ u32 __reserved_3[3];
+ } all_errors;
+ } esr;
+
+/*290*/ struct { u32 __reserved[4]; } __reserved_08;
+
+/*2A0*/ struct { u32 __reserved[4]; } __reserved_09;
+
+/*2B0*/ struct { u32 __reserved[4]; } __reserved_10;
+
+/*2C0*/ struct { u32 __reserved[4]; } __reserved_11;
+
+/*2D0*/ struct { u32 __reserved[4]; } __reserved_12;
+
+/*2E0*/ struct { u32 __reserved[4]; } __reserved_13;
+
+/*2F0*/ struct { u32 __reserved[4]; } __reserved_14;
+
+/*300*/ struct { /* Interrupt Command Register 1 */
+ u32 vector : 8,
+ delivery_mode : 3,
+ destination_mode : 1,
+ delivery_status : 1,
+ __reserved_1 : 1,
+ level : 1,
+ trigger : 1,
+ __reserved_2 : 2,
+ shorthand : 2,
+ __reserved_3 : 12;
+ u32 __reserved_4[3];
+ } icr1;
+
+/*310*/ struct { /* Interrupt Command Register 2 */
+ union {
+ u32 __reserved_1 : 24,
+ phys_dest : 4,
+ __reserved_2 : 4;
+ u32 __reserved_3 : 24,
+ logical_dest : 8;
+ } dest;
+ u32 __reserved_4[3];
+ } icr2;
+
+/*320*/ struct { /* LVT - Timer */
+ u32 vector : 8,
+ __reserved_1 : 4,
+ delivery_status : 1,
+ __reserved_2 : 3,
+ mask : 1,
+ timer_mode : 1,
+ __reserved_3 : 14;
+ u32 __reserved_4[3];
+ } lvt_timer;
+
+/*330*/ struct { u32 __reserved[4]; } __reserved_15;
+
+/*340*/ struct { /* LVT - Performance Counter */
+ u32 vector : 8,
+ delivery_mode : 3,
+ __reserved_1 : 1,
+ delivery_status : 1,
+ __reserved_2 : 3,
+ mask : 1,
+ __reserved_3 : 15;
+ u32 __reserved_4[3];
+ } lvt_pc;
+
+/*350*/ struct { /* LVT - LINT0 */
+ u32 vector : 8,
+ delivery_mode : 3,
+ __reserved_1 : 1,
+ delivery_status : 1,
+ polarity : 1,
+ remote_irr : 1,
+ trigger : 1,
+ mask : 1,
+ __reserved_2 : 15;
+ u32 __reserved_3[3];
+ } lvt_lint0;
+
+/*360*/ struct { /* LVT - LINT1 */
+ u32 vector : 8,
+ delivery_mode : 3,
+ __reserved_1 : 1,
+ delivery_status : 1,
+ polarity : 1,
+ remote_irr : 1,
+ trigger : 1,
+ mask : 1,
+ __reserved_2 : 15;
+ u32 __reserved_3[3];
+ } lvt_lint1;
+
+/*370*/ struct { /* LVT - Error */
+ u32 vector : 8,
+ __reserved_1 : 4,
+ delivery_status : 1,
+ __reserved_2 : 3,
+ mask : 1,
+ __reserved_3 : 15;
+ u32 __reserved_4[3];
+ } lvt_error;
+
+/*380*/ struct { /* Timer Initial Count Register */
+ u32 initial_count;
+ u32 __reserved_2[3];
+ } timer_icr;
+
+/*390*/ const
+ struct { /* Timer Current Count Register */
+ u32 curr_count;
+ u32 __reserved_2[3];
+ } timer_ccr;
+
+/*3A0*/ struct { u32 __reserved[4]; } __reserved_16;
+
+/*3B0*/ struct { u32 __reserved[4]; } __reserved_17;
+
+/*3C0*/ struct { u32 __reserved[4]; } __reserved_18;
+
+/*3D0*/ struct { u32 __reserved[4]; } __reserved_19;
+
+/*3E0*/ struct { /* Timer Divide Configuration Register */
+ u32 divisor : 4,
+ __reserved_1 : 28;
+ u32 __reserved_2[3];
+ } timer_dcr;
+
+/*3F0*/ struct { u32 __reserved[4]; } __reserved_20;
+
+} __attribute__ ((packed));
+
+#undef u32
+
#endif
diff --git a/include/asm-i386/hw_irq.h b/include/asm-i386/hw_irq.h
index 8cce40151..894055a7d 100644
--- a/include/asm-i386/hw_irq.h
+++ b/include/asm-i386/hw_irq.h
@@ -27,33 +27,40 @@
*/
/*
- * Special IRQ vectors used by the SMP architecture:
+ * Special IRQ vectors used by the SMP architecture, 0x30-0x4f
*
- * (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.)
+ * some of the following vectors are 'rare', they are merged
+ * into a single vector (CALL_FUNCTION_VECTOR) to save vector space.
+ * TLB, reschedule and local APIC vectors are performance-critical.
*/
-#define RESCHEDULE_VECTOR 0x30
-#define INVALIDATE_TLB_VECTOR 0x31
-#define STOP_CPU_VECTOR 0x40
-#define LOCAL_TIMER_VECTOR 0x41
-#define CALL_FUNCTION_VECTOR 0x50
+#define INVALIDATE_TLB_VECTOR 0x30
+#define LOCAL_TIMER_VECTOR 0x31
+#define RESCHEDULE_VECTOR 0x40
+
+/* 'rare' vectors: */
+#define CALL_FUNCTION_VECTOR 0x41
/*
- * First APIC vector available to drivers: (vectors 0x51-0xfe)
+ * These IRQs should never really happen on perfect hardware running
+ * a perfect kernel, but we nevertheless print a message to catch the
+ * rest ;) Subtle, the APIC architecture mandates the spurious vector
+ * to have bits 0-3 set to 1. Note that these vectors do not occur
+ * normally, so we violate the 'only 2 vectors per priority level'
+ * rule here.
*/
-#define IRQ0_TRAP_VECTOR 0x51
+#define SPURIOUS_APIC_VECTOR 0x3f
+#define ERROR_APIC_VECTOR 0x43
/*
- * This IRQ should never happen, but we print a message nevertheless.
+ * First APIC vector available to drivers: (vectors 0x51-0xfe)
+ * we start at 0x51 to spread out vectors between priority levels
+ * evenly. (note that 0x80 is the syscall vector)
*/
-#define SPURIOUS_APIC_VECTOR 0xff
+#define IRQ0_TRAP_VECTOR 0x51
extern int irq_vector[NR_IRQS];
#define IO_APIC_VECTOR(irq) irq_vector[irq]
-extern void init_IRQ_SMP(void);
-
/*
* Various low-level irq details needed by irq.c, process.c,
* time.c, io_apic.c and smp.c
@@ -65,18 +72,20 @@ extern void no_action(int cpl, void *dev_id, struct pt_regs *regs);
extern void mask_irq(unsigned int irq);
extern void unmask_irq(unsigned int irq);
extern void disable_8259A_irq(unsigned int irq);
+extern void enable_8259A_irq(unsigned int irq);
extern int i8259A_irq_pending(unsigned int irq);
-extern void ack_APIC_irq(void);
+extern void make_8259A_irq(unsigned int irq);
+extern void init_8259A(int aeoi);
extern void FASTCALL(send_IPI_self(int vector));
extern void init_VISWS_APIC_irqs(void);
extern void setup_IO_APIC(void);
extern int IO_APIC_get_PCI_irq_vector(int bus, int slot, int fn);
-extern void make_8259A_irq(unsigned int irq);
extern void send_IPI(int dest, int vector);
extern void init_pic_mode(void);
extern void print_IO_APIC(void);
extern unsigned long io_apic_irqs;
+extern volatile unsigned long irq_err_count;
extern char _stext, _etext;
@@ -214,6 +223,7 @@ static inline void x86_do_profile (unsigned long eip)
#ifdef __SMP__ /*more of this file should probably be ifdefed SMP */
static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) {
+ if (IO_APIC_IRQ(i))
send_IPI_self(IO_APIC_VECTOR(i));
}
#else
diff --git a/include/asm-i386/irq.h b/include/asm-i386/irq.h
index 436ad1d21..9b8f64a3c 100644
--- a/include/asm-i386/irq.h
+++ b/include/asm-i386/irq.h
@@ -13,7 +13,7 @@
#define TIMER_IRQ 0
/*
- * 16 8259A IRQ's, 240 potential APIC interrupt sources.
+ * 16 8259A IRQ's, 208 potential APIC interrupt sources.
* Right now the APIC is mostly only used for SMP.
* 256 vectors is an architectural limit. (we can have
* more than 256 devices theoretically, but they will
diff --git a/include/asm-i386/keyboard.h b/include/asm-i386/keyboard.h
index 2a7effa3c..4b308f746 100644
--- a/include/asm-i386/keyboard.h
+++ b/include/asm-i386/keyboard.h
@@ -2,8 +2,6 @@
* linux/include/asm-i386/keyboard.h
*
* Created 3 Nov 1996 by Geert Uytterhoeven
- *
- * $Id: keyboard.h,v 1.8 1999/06/10 08:02:38 ralf Exp $
*/
/*
@@ -16,6 +14,7 @@
#ifdef __KERNEL__
#include <linux/kernel.h>
+#include <linux/ioport.h>
#include <asm/io.h>
#define KEYBOARD_IRQ 1
@@ -40,6 +39,11 @@ extern unsigned char pckbd_sysrq_xlate[128];
#define SYSRQ_KEY 0x54
+/* resource allocation */
+#define kbd_request_region()
+#define kbd_request_irq(handler) request_irq(KEYBOARD_IRQ, handler, 0, \
+ "keyboard", NULL)
+
/* How to access the keyboard macros on this platform. */
#define kbd_read_input() inb(KBD_DATA_REG)
#define kbd_read_status() inb(KBD_STATUS_REG)
@@ -47,13 +51,7 @@ extern unsigned char pckbd_sysrq_xlate[128];
#define kbd_write_command(val) outb(val, KBD_CNTL_REG)
/* Some stoneage hardware needs delays after some operations. */
-#define kbd_pause() do { SLOW_DOWN_IO; } while(0)
-
-/* Get the keyboard controller registers (incomplete decode) */
-#define kbd_request_region() request_region(0x60, 16, "keyboard")
-
-#define kbd_request_irq() request_irq(KEYBOARD_IRQ, keyboard_interrupt, 0, \
- "keyboard", NULL);
+#define kbd_pause() do { } while(0)
/*
* Machine specific bits for the PS/2 driver
@@ -61,8 +59,10 @@ extern unsigned char pckbd_sysrq_xlate[128];
#define AUX_IRQ 12
-#define aux_free_irq(dev_id) free_irq(AUX_IRQ, AUX_DEV)
-request_irq(AUX_IRQ, keyboard_interrupt, SA_SHIRQ, "PS/2 Mouse", AUX_DEV)
+#define aux_request_irq(hand, dev_id) \
+ request_irq(AUX_IRQ, hand, SA_SHIRQ, "PS/2 Mouse", dev_id)
+
+#define aux_free_irq(dev_id) free_irq(AUX_IRQ, dev_id)
#endif /* __KERNEL__ */
-#endif /* __ASM_i386_KEYBOARD_H */
+#endif /* _I386_KEYBOARD_H */
diff --git a/include/asm-i386/mmx.h b/include/asm-i386/mmx.h
new file mode 100644
index 000000000..721a8e933
--- /dev/null
+++ b/include/asm-i386/mmx.h
@@ -0,0 +1,14 @@
+#ifndef _ASM_MMX_H
+#define _ASM_MMX_H
+
+/*
+ * MMX 3Dnow! helper operations
+ */
+
+#include <linux/types.h>
+
+extern void *_mmx_memcpy(void *to, const void *from, size_t size);
+extern void mmx_clear_page(long page);
+extern void mmx_copy_page(long to, long from);
+
+#endif
diff --git a/include/asm-i386/msr.h b/include/asm-i386/msr.h
index 1ed8ea851..515a8dc5c 100644
--- a/include/asm-i386/msr.h
+++ b/include/asm-i386/msr.h
@@ -23,6 +23,8 @@
#define rdtscll(val) \
__asm__ __volatile__ ("rdtsc" : "=A" (val))
+#define write_tsc(val1,val2) wrmsr(0x10, val1, val2)
+
#define rdpmc(counter,low,high) \
__asm__ __volatile__("rdpmc" \
: "=a" (low), "=d" (high) \
diff --git a/include/asm-i386/page.h b/include/asm-i386/page.h
index 2e5006f4a..c3719d5d9 100644
--- a/include/asm-i386/page.h
+++ b/include/asm-i386/page.h
@@ -11,9 +11,27 @@
#define STRICT_MM_TYPECHECKS
+#include <linux/config.h>
+
+#ifdef CONFIG_X86_USE_3DNOW
+
+#include <asm/mmx.h>
+
+#define clear_page(page) mmx_clear_page(page)
+#define copy_page(to,from) mmx_copy_page(to,from)
+
+#else
+
+/*
+ * On older X86 processors its not a win to use MMX here it seems.
+ * Maybe the K6-III ?
+ */
+
#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
#define copy_page(to,from) memcpy((void *)(to), (void *)(from), PAGE_SIZE)
+#endif
+
#ifdef STRICT_MM_TYPECHECKS
/*
* These are used to make use of C type-checking..
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index 99b291d40..939ca0b31 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -106,6 +106,9 @@ extern struct cpuinfo_x86 cpu_data[];
#define current_cpu_data boot_cpu_data
#endif
+#define cpu_has_tsc \
+ (cpu_data[smp_processor_id()].x86_capability & X86_FEATURE_TSC)
+
extern char ignore_irq13;
extern void identify_cpu(struct cpuinfo_x86 *);
diff --git a/include/asm-i386/smp.h b/include/asm-i386/smp.h
index 91199de7f..52c27bead 100644
--- a/include/asm-i386/smp.h
+++ b/include/asm-i386/smp.h
@@ -123,17 +123,19 @@ struct mpc_config_intsrc
unsigned char mpc_dstirq;
};
-#define MP_INT_VECTORED 0
-#define MP_INT_NMI 1
-#define MP_INT_SMI 2
-#define MP_INT_EXTINT 3
+enum mp_irq_source_types {
+ mp_INT = 0,
+ mp_NMI = 1,
+ mp_SMI = 2,
+ mp_ExtINT = 3
+};
#define MP_IRQDIR_DEFAULT 0
#define MP_IRQDIR_HIGH 1
#define MP_IRQDIR_LOW 3
-struct mpc_config_intlocal
+struct mpc_config_lintsrc
{
unsigned char mpc_type;
unsigned char mpc_irqtype;
@@ -150,7 +152,7 @@ struct mpc_config_intlocal
* Default configurations
*
* 1 2 CPU ISA 82489DX
- * 2 2 CPU EISA 82489DX no IRQ 8 or timer chaining
+ * 2 2 CPU EISA 82489DX neither IRQ 0 timer nor IRQ 13 DMA chaining
* 3 2 CPU EISA 82489DX
* 4 2 CPU MCA 82489DX
* 5 2 CPU ISA+PCI
@@ -165,21 +167,19 @@ struct mpc_config_intlocal
extern int smp_found_config;
extern void init_smp_config(void);
extern unsigned long smp_alloc_memory(unsigned long mem_base);
-extern unsigned char boot_cpu_id;
extern unsigned long cpu_present_map;
extern unsigned long cpu_online_map;
-extern volatile int cpu_number_map[NR_CPUS];
extern volatile unsigned long smp_invalidate_needed;
+extern int pic_mode;
extern void smp_flush_tlb(void);
-
-extern volatile unsigned long cpu_callin_map[NR_CPUS];
+extern int get_maxlvt(void);
extern void smp_message_irq(int cpl, void *dev_id, struct pt_regs *regs);
extern void smp_send_reschedule(int cpu);
-extern unsigned long ipi_count;
extern void smp_invalidate_rcv(void); /* Process an NMI */
extern void smp_local_timer_interrupt(struct pt_regs * regs);
extern void (*mtrr_hook) (void);
-extern void setup_APIC_clock (void);
+extern void setup_APIC_clocks(void);
+extern volatile int cpu_number_map[NR_CPUS];
extern volatile int __cpu_logical_map[NR_CPUS];
extern inline int cpu_logical_map(int cpu)
{
@@ -196,12 +196,35 @@ extern __inline unsigned long apic_read(unsigned long reg)
return *((volatile unsigned long *)(APIC_BASE+reg));
}
+extern unsigned int apic_timer_irqs [NR_CPUS];
+
+#ifdef CONFIG_X86_GOOD_APIC
+# define FORCE_READ_AROUND_WRITE 0
+# define apic_readaround(x)
+#else
+# define FORCE_READ_AROUND_WRITE 1
+# define apic_readaround(x) apic_read(x)
+#endif
+
+#define apic_write_around(x,y) \
+ do { apic_readaround(x); apic_write(x,y); } while (0)
+
+extern inline void ack_APIC_irq(void)
+{
+ /* Clear the IPI */
+
+ apic_readaround(APIC_EOI);
+ /*
+ * on P6+ cores (CONFIG_X86_GOOD_APIC) ack_APIC_irq() actually
+ * gets compiled as a single instruction ... yummie.
+ */
+ apic_write(APIC_EOI, 0); /* Docs say use 0 for future compatibility */
+}
/*
* General functions that each host system must provide.
*/
-extern void smp_callin(void);
extern void smp_boot_cpus(void);
extern void smp_store_cpu_info(int id); /* Store per CPU info (like the initial udelay numbers */
diff --git a/include/asm-i386/string-486.h b/include/asm-i386/string-486.h
index 34f5c16b1..4b5c5fe25 100644
--- a/include/asm-i386/string-486.h
+++ b/include/asm-i386/string-486.h
@@ -14,6 +14,8 @@
* 1994/03/15 by Alberto Vignani/Davide Parodi @crf.it
*
* Split into 2 CPU specific files by Alan Cox to keep #ifdef noise down.
+ *
+ * 99/9/15 Proper reg args for newer gcc/egcs - Petkan (petkan@spct.net)
*/
#define __HAVE_ARCH_STRCPY
@@ -180,6 +182,7 @@ return __res;
#define __HAVE_ARCH_STRRCHR
extern inline char * strrchr(const char * s, int c)
{
+int d0, d1;
register char * __res;
__asm__ __volatile__(
"cld\n\t"
@@ -190,17 +193,19 @@ __asm__ __volatile__(
"leal -1(%%esi),%0\n"
"2:\ttestb %%al,%%al\n\t"
"jne 1b"
- :"=d" (__res):"0" (0),"S" (s),"a" (c):"ax","si");
+ :"=d" (__res), "=&S" (d0), "=&a" (d1)
+ :"0" (0), "1" (s), "2" (c));
return __res;
}
#define __HAVE_ARCH_STRSPN
extern inline size_t strspn(const char * cs, const char * ct)
{
+int d0, d1;
register char * __res;
__asm__ __volatile__(
"cld\n\t"
- "movl %4,%%edi\n\t"
+ "movl %6,%%edi\n\t"
"repne\n\t"
"scasb\n\t"
"notl %%ecx\n\t"
@@ -209,24 +214,26 @@ __asm__ __volatile__(
"1:\tlodsb\n\t"
"testb %%al,%%al\n\t"
"je 2f\n\t"
- "movl %4,%%edi\n\t"
+ "movl %6,%%edi\n\t"
"movl %%edx,%%ecx\n\t"
"repne\n\t"
"scasb\n\t"
"je 1b\n"
"2:\tdecl %0"
- :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
- :"ax","cx","dx","di");
+ :"=S" (__res), "=&a" (d0), "=&c" (d1)
+ :"0" (cs), "1" (0), "2" (0xffffffff), "g" (ct)
+ :"dx", "di");
return __res-cs;
}
#define __HAVE_ARCH_STRCSPN
extern inline size_t strcspn(const char * cs, const char * ct)
{
+int d0, d1;
register char * __res;
__asm__ __volatile__(
"cld\n\t"
- "movl %4,%%edi\n\t"
+ "movl %6,%%edi\n\t"
"repne\n\t"
"scasb\n\t"
"notl %%ecx\n\t"
@@ -235,20 +242,22 @@ __asm__ __volatile__(
"1:\tlodsb\n\t"
"testb %%al,%%al\n\t"
"je 2f\n\t"
- "movl %4,%%edi\n\t"
+ "movl %6,%%edi\n\t"
"movl %%edx,%%ecx\n\t"
"repne\n\t"
"scasb\n\t"
"jne 1b\n"
"2:\tdecl %0"
- :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
- :"ax","cx","dx","di");
+ :"=S" (__res), "=&a" (d0), "=&c" (d1)
+ :"0" (cs), "1" (0), "2" (0xffffffff), "g" (ct)
+ :"dx", "di");
return __res-cs;
}
#define __HAVE_ARCH_STRPBRK
extern inline char * strpbrk(const char * cs,const char * ct)
{
+int d0, d1;
register char * __res;
__asm__ __volatile__(
"cld\n\t"
@@ -270,14 +279,16 @@ __asm__ __volatile__(
"jmp 3f\n"
"2:\txorl %0,%0\n"
"3:"
- :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
- :"ax","cx","dx","di");
+ :"=S" (__res), "=&a" (d0), "=&c" (d1)
+ :"0" (cs), "1" (0), "2" (0xffffffff), "g" (ct)
+ :"dx", "di");
return __res;
}
#define __HAVE_ARCH_STRSTR
extern inline char * strstr(const char * cs,const char * ct)
{
+int d0, d1;
register char * __res;
__asm__ __volatile__(
"cld\n\t" \
@@ -299,8 +310,9 @@ __asm__ __volatile__(
"jne 1b\n\t"
"xorl %%eax,%%eax\n\t"
"2:"
- :"=a" (__res):"0" (0),"c" (0xffffffff),"S" (cs),"g" (ct)
- :"cx","dx","di","si");
+ :"=a" (__res), "=&c" (d0), "=&S" (d1)
+ :"0" (0), "1" (0xffffffff), "2" (cs), "g" (ct)
+ :"dx", "di");
return __res;
}
@@ -328,6 +340,7 @@ return (tmp-s-1);
#define __HAVE_ARCH_STRNLEN
extern inline size_t strnlen(const char * s, size_t count)
{
+int d0;
register int __res;
__asm__ __volatile__(
"movl %1,%0\n\t"
@@ -339,9 +352,8 @@ __asm__ __volatile__(
"cmpl $-1,%2\n\t"
"jne 1b\n"
"3:\tsubl %1,%0"
- :"=a" (__res)
- :"c" (s),"d" (count)
- :"dx");
+ :"=a" (__res), "=&d" (d0)
+ :"1" (count), "c" (s));
return __res;
}
/* end of additional stuff */
@@ -464,6 +476,7 @@ return (to);
extern inline void * __memcpy_g(void * to, const void * from, size_t n)
{
+int d0, d1, d2;
register void *tmp = (void *)to;
__asm__ __volatile__ (
"cld\n\t"
@@ -475,9 +488,9 @@ __asm__ __volatile__ (
"movsw\n"
"2:\trep\n\t"
"movsl"
- : /* no output */
- :"c" (n),"D" ((long) tmp),"S" ((long) from)
- :"cx","di","si","memory");
+ :"=&c" (d0), "=&D" (d1), "=&S" (d2)
+ :"0" (n), "1" ((long) tmp), "2" ((long) from)
+ :"memory");
return (to);
}
@@ -485,29 +498,31 @@ return (to);
#define __HAVE_ARCH_MEMMOVE
extern inline void * memmove(void * dest,const void * src, size_t n)
{
+int d0, d1, d2;
register void *tmp = (void *)dest;
if (dest<src)
__asm__ __volatile__ (
"cld\n\t"
"rep\n\t"
"movsb"
- : /* no output */
- :"c" (n),"S" (src),"D" (tmp)
- :"cx","si","di");
+ :"=&c" (d0), "=&S" (d1), "=&D" (d2)
+ :"0" (n), "1" (src), "2" (tmp)
+ :"memory");
else
__asm__ __volatile__ (
"std\n\t"
"rep\n\t"
"movsb\n\t"
"cld"
- : /* no output */
- :"c" (n), "S" (n-1+(const char *)src), "D" (n-1+(char *)tmp)
- :"cx","si","di","memory");
+ :"=&c" (d0), "=&S" (d1), "=&D" (d2)
+ :"0" (n), "1" (n-1+(const char *)src), "2" (n-1+(char *)tmp)
+ :"memory");
return dest;
}
extern inline int memcmp(const void * cs,const void * ct,size_t count)
{
+int d0, d1, d2;
register int __res;
__asm__ __volatile__(
"cld\n\t"
@@ -517,14 +532,15 @@ __asm__ __volatile__(
"sbbl %0,%0\n\t"
"orb $1,%b0\n"
"1:"
- :"=abd" (__res):"0" (0),"S" (cs),"D" (ct),"c" (count)
- :"si","di","cx");
+ :"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
+ :"0" (0), "1" (cs), "2" (ct), "3" (count));
return __res;
}
#define __HAVE_ARCH_MEMCHR
extern inline void * memchr(const void * cs,int c,size_t count)
{
+int d0;
register void * __res;
if (!count)
return NULL;
@@ -535,8 +551,8 @@ __asm__ __volatile__(
"je 1f\n\t"
"movl $1,%0\n"
"1:\tdecl %0"
- :"=D" (__res):"a" (c),"D" (cs),"c" (count)
- :"cx");
+ :"=D" (__res), "=&c" (d0)
+ :"a" (c), "0" (cs), "1" (count));
return __res;
}
@@ -643,6 +659,7 @@ return s;
extern inline void * __memset_cg(void * s, char c, size_t count)
{
+int d0, d1;
register void *tmp = (void *)s;
__asm__ __volatile__ (
"shrl $1,%%ecx\n\t"
@@ -651,14 +668,15 @@ __asm__ __volatile__ (
"jnc 1f\n\t"
"movb %%al,(%%edi)\n"
"1:"
- : /* no output */
- :"c" (count),"D" (tmp), "a" (0x0101U * (unsigned char) c)
- :"cx","di","memory");
+ :"=&c" (d0), "=&D" (d1)
+ :"a" (0x0101U * (unsigned char) c), "0" (count), "1" (tmp)
+ :"memory");
return s;
}
extern inline void * __memset_gg(void * s,char c,size_t count)
{
+int d0, d1, d2;
register void *tmp = (void *)s;
__asm__ __volatile__ (
"movb %%al,%%ah\n\t"
@@ -668,9 +686,9 @@ __asm__ __volatile__ (
"jnc 1f\n\t"
"movb %%al,(%%edi)\n"
"1:"
- : /* no output */
- :"c" (count),"D" (tmp), "a" (c)
- :"cx","di","memory");
+ :"=&c" (d0), "=&D" (d1), "=&D" (d2)
+ :"0" (count), "1" (tmp), "2" (c)
+ :"memory");
return s;
}
diff --git a/include/asm-i386/string.h b/include/asm-i386/string.h
index 8417d4aba..e03928ede 100644
--- a/include/asm-i386/string.h
+++ b/include/asm-i386/string.h
@@ -293,11 +293,55 @@ __asm__ __volatile__( \
}
#define __HAVE_ARCH_MEMCPY
+
+#include <linux/config.h>
+
+#ifdef CONFIG_X86_USE_3DNOW
+
+/* All this just for in_interrupt() ... */
+
+#include <asm/system.h>
+#include <asm/ptrace.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <asm/mmx.h>
+
+/*
+ * This CPU favours 3DNow strongly (eg AMD Athlon)
+ */
+
+extern inline void * __constant_memcpy3d(void * to, const void * from, size_t len)
+{
+ if(len<512 || in_interrupt())
+ return __constant_memcpy(to, from, len);
+ return _mmx_memcpy(to, from, len);
+}
+
+extern __inline__ void *__memcpy3d(void *to, const void *from, size_t len)
+{
+ if(len<512 || in_interrupt())
+ return __memcpy(to, from, len);
+ return _mmx_memcpy(to, from, len);
+}
+
+#define memcpy(t, f, n) \
+(__builtin_constant_p(n) ? \
+ __constant_memcpy3d((t),(f),(n)) : \
+ __memcpy3d((t),(f),(n)))
+
+#else
+
+/*
+ * No 3D Now!
+ */
+
#define memcpy(t, f, n) \
(__builtin_constant_p(n) ? \
__constant_memcpy((t),(f),(n)) : \
__memcpy((t),(f),(n)))
+#endif
+
#define __HAVE_ARCH_MEMMOVE
extern inline void * memmove(void * dest,const void * src, size_t n)
{
diff --git a/include/asm-i386/uaccess.h b/include/asm-i386/uaccess.h
index 2b1b3d7f4..7546159f6 100644
--- a/include/asm-i386/uaccess.h
+++ b/include/asm-i386/uaccess.h
@@ -597,7 +597,8 @@ __constant_copy_from_user_nocheck(void *to, const void *from, unsigned long n)
long strncpy_from_user(char *dst, const char *src, long count);
long __strncpy_from_user(char *dst, const char *src, long count);
-long strlen_user(const char *str);
+#define strlen_user(str) strnlen_user(str, ~0UL >> 1)
+long strnlen_user(const char *str, long n);
unsigned long clear_user(void *mem, unsigned long len);
unsigned long __clear_user(void *mem, unsigned long len);