diff options
Diffstat (limited to 'include/asm-i386')
-rw-r--r-- | include/asm-i386/apic.h | 267 | ||||
-rw-r--r-- | include/asm-i386/hw_irq.h | 44 | ||||
-rw-r--r-- | include/asm-i386/irq.h | 2 | ||||
-rw-r--r-- | include/asm-i386/keyboard.h | 24 | ||||
-rw-r--r-- | include/asm-i386/mmx.h | 14 | ||||
-rw-r--r-- | include/asm-i386/msr.h | 2 | ||||
-rw-r--r-- | include/asm-i386/page.h | 18 | ||||
-rw-r--r-- | include/asm-i386/processor.h | 3 | ||||
-rw-r--r-- | include/asm-i386/smp.h | 49 | ||||
-rw-r--r-- | include/asm-i386/string-486.h | 88 | ||||
-rw-r--r-- | include/asm-i386/string.h | 44 | ||||
-rw-r--r-- | include/asm-i386/uaccess.h | 3 |
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); |