There has been some interest for the 64-bit kernel, so I have pull together a patch against the latest sources, which contains our local fixes and changes. Could some please apply these fixes. Added file are arch/mips64/mm/c-mips64.c arch/mips64/mm/pg-mips64.c arch/mips64/mm/tlb-r4k.c include/asm-mips64/mips64_cache.h /Carsten -- _ _ ____ ___ Carsten Langgaard Mailto:carstenl@mips.com |\ /|||___)(___ MIPS Denmark Direct: +45 4486 5527 | \/ ||| ____) Lautrupvang 4B Switch: +45 4486 5555 TECHNOLOGIES 2750 Ballerup Fax...: +45 4486 5556 Denmark http://www.mips.com
Index: arch/mips64/Makefile =================================================================== RCS file: /cvs/linux/arch/mips64/Makefile,v retrieving revision 1.22.2.3 diff -u -r1.22.2.3 Makefile --- arch/mips64/Makefile 2002/02/26 23:59:53 1.22.2.3 +++ arch/mips64/Makefile 2002/06/07 12:26:00 @@ -66,6 +66,9 @@ ifdef CONFIG_CPU_SB1 CFLAGS += -mcpu=r8000 -mips4 endif +ifdef CONFIG_CPU_MIPS64 +CFLAGS += -mcpu=r8000 -mips4 +endif # # We unconditionally build the math emulator Index: arch/mips64/config.in =================================================================== RCS file: /cvs/linux/arch/mips64/config.in,v retrieving revision 1.50.2.9 diff -u -r1.50.2.9 config.in --- arch/mips64/config.in 2002/05/29 14:30:57 1.50.2.9 +++ arch/mips64/config.in 2002/06/07 12:26:00 @@ -70,10 +70,14 @@ if [ "$CONFIG_MIPS_MALTA" = "y" ]; then define_bool CONFIG_BOOT_ELF32 y define_bool CONFIG_I8259 y + define_bool CONFIG_HAVE_STD_PC_SERIAL_PORT y + define_bool CONFIG_NEW_IRQ y + define_bool CONFIG_NEW_TIME_C y define_int CONFIG_L1_CACHE_SHIFT 5 define_bool CONFIG_NONCOHERENT_IO y define_bool CONFIG_PCI y define_bool CONFIG_SWAP_IO_SPACE y + define_bool CONFIG_PC_KEYB y fi if [ "$CONFIG_SGI_IP22" = "y" ]; then define_bool CONFIG_ARC32 y @@ -118,20 +122,25 @@ mainmenu_option next_comment comment 'CPU selection' -choice 'CPU type' \ - "R4300 CONFIG_CPU_R4300 \ - R4x00 CONFIG_CPU_R4X00 \ - R5000 CONFIG_CPU_R5000 \ - R52x0 CONFIG_CPU_NEVADA \ - R8000 CONFIG_CPU_R8000 \ - R10000 CONFIG_CPU_R10000 \ - SB1 CONFIG_CPU_SB1" R4x00 +choice 'CPU type' \ + "R4300 CONFIG_CPU_R4300 \ + R4x00 CONFIG_CPU_R4X00 \ + R5000 CONFIG_CPU_R5000 \ + R52x0 CONFIG_CPU_NEVADA \ + R8000 CONFIG_CPU_R8000 \ + R10000 CONFIG_CPU_R10000 \ + SB1 CONFIG_CPU_SB1 \ + MIPS64 CONFIG_CPU_MIPS64" R4x00 endmenu if [ "$CONFIG_CPU_SB1" = "y" ]; then bool ' Workarounds for pass 1 sb1 bugs' CONFIG_SB1_PASS_1_WORKAROUNDS bool ' Support for SB1 Cache Error handler' CONFIG_SB1_CACHE_ERROR define_bool CONFIG_VTAG_ICACHE y +fi + +if [ "$CONFIG_CPU_MIPS64" = "y" ]; then + bool ' Support for Virtual Tagged I-cache' CONFIG_VTAG_ICACHE fi define_bool CONFIG_CPU_HAS_LLSC y Index: arch/mips64/kernel/Makefile =================================================================== RCS file: /cvs/linux/arch/mips64/kernel/Makefile,v retrieving revision 1.11.2.5 diff -u -r1.11.2.5 Makefile --- arch/mips64/kernel/Makefile 2002/06/03 15:16:49 1.11.2.5 +++ arch/mips64/kernel/Makefile 2002/06/07 12:26:00 @@ -15,12 +15,15 @@ export-objs = irq.o mips64_ksyms.o pci-dma.o setup.o smp.o -obj-y := branch.o entry.o irq.o proc.o process.o ptrace.o r4k_cache.o \ - r4k_fpu.o r4k_genex.o r4k_switch.o reset.o scall_64.o semaphore.o \ - setup.o signal.o syscall.o time.o traps.o unaligned.o +obj-y := branch.o entry.o proc.o process.o ptrace.o r4k_cache.o \ + r4k_fpu.o r4k_genex.o r4k_switch.o reset.o scall_64.o \ + semaphore.o setup.o signal.o syscall.o traps.o unaligned.o +obj-$(CONFIG_NEW_IRQ) += irq.o obj-$(CONFIG_I8259) += i8259.o obj-$(CONFIG_IRQ_CPU) += irq_cpu.o + +obj-$(CONFIG_NEW_TIME_C) += time.o obj-$(CONFIG_MODULES) += mips64_ksyms.o obj-$(CONFIG_MIPS32_COMPAT) += linux32.o scall_o32.o signal32.o ioctl32.o Index: arch/mips64/kernel/entry.S =================================================================== RCS file: /cvs/linux/arch/mips64/kernel/entry.S,v retrieving revision 1.11.2.4 diff -u -r1.11.2.4 entry.S --- arch/mips64/kernel/entry.S 2002/05/29 03:03:17 1.11.2.4 +++ arch/mips64/kernel/entry.S 2002/06/07 12:26:00 @@ -24,7 +24,7 @@ FEXPORT(ret_from_fork) move a0, v0 # prev jal schedule_tail - lw t0, TASK_PTRACE($28) # syscall tracing enabled? + ld t0, TASK_PTRACE($28) # syscall tracing enabled? andi t0, PT_TRACESYS bnez t0, tracesys_exit j ret_from_sys_call Index: arch/mips64/kernel/head.S =================================================================== RCS file: /cvs/linux/arch/mips64/kernel/head.S,v retrieving revision 1.34.2.4 diff -u -r1.34.2.4 head.S --- arch/mips64/kernel/head.S 2002/02/26 05:59:03 1.34.2.4 +++ arch/mips64/kernel/head.S 2002/06/07 12:26:00 @@ -92,7 +92,7 @@ __INIT NESTED(kernel_entry, 16, sp) # kernel entry point - + .set noreorder ori sp, 0xf # align stack on 16 byte. xori sp, 0xf @@ -111,8 +111,22 @@ set_saved_sp sp, t0 dsubu sp, 4*SZREG # init stack pointer + + /* The firmware/bootloader passes argc/argp/envp + * to us as arguments. But clear bss first because + * the romvec and other important info is stored there + * by prom_init(). + */ + la t0, _edata + sd zero, (t0) + la t1, (_end - 8) +1: + daddiu t0, 8 + bne t0, t1, 1b + sd zero, (t0) j init_arch + nop END(kernel_entry) #ifdef CONFIG_SMP Index: arch/mips64/kernel/ioctl32.c =================================================================== RCS file: /cvs/linux/arch/mips64/kernel/ioctl32.c,v retrieving revision 1.10.2.1 diff -u -r1.10.2.1 ioctl32.c --- arch/mips64/kernel/ioctl32.c 2001/12/03 07:26:20 1.10.2.1 +++ arch/mips64/kernel/ioctl32.c 2002/06/07 12:26:00 @@ -27,6 +27,7 @@ #include <linux/auto_fs.h> #include <linux/ext2_fs.h> #include <linux/raid/md_u.h> +#include <linux/rtc.h> #include <scsi/scsi.h> #undef __KERNEL__ /* This file was born to be ugly ... */ #include <scsi/scsi_ioctl.h> @@ -834,7 +835,25 @@ IOCTL32_DEFAULT(AUTOFS_IOC_CATATONIC), IOCTL32_DEFAULT(AUTOFS_IOC_PROTOVER), IOCTL32_HANDLER(AUTOFS_IOC_SETTIMEOUT32, ioc_settimeout), - IOCTL32_DEFAULT(AUTOFS_IOC_EXPIRE) + IOCTL32_DEFAULT(AUTOFS_IOC_EXPIRE), + + /* Little p (/dev/rtc, /dev/envctrl, etc.) */ + IOCTL32_DEFAULT(_IOR('p', 20, int[7])), /* RTCGET */ + IOCTL32_DEFAULT(_IOW('p', 21, int[7])), /* RTCSET */ + IOCTL32_DEFAULT(RTC_AIE_ON), + IOCTL32_DEFAULT(RTC_AIE_OFF), + IOCTL32_DEFAULT(RTC_UIE_ON), + IOCTL32_DEFAULT(RTC_UIE_OFF), + IOCTL32_DEFAULT(RTC_PIE_ON), + IOCTL32_DEFAULT(RTC_PIE_OFF), + IOCTL32_DEFAULT(RTC_WIE_ON), + IOCTL32_DEFAULT(RTC_WIE_OFF), + IOCTL32_DEFAULT(RTC_ALM_SET), + IOCTL32_DEFAULT(RTC_ALM_READ), + IOCTL32_DEFAULT(RTC_RD_TIME), + IOCTL32_DEFAULT(RTC_SET_TIME), + IOCTL32_DEFAULT(RTC_WKALM_SET), + IOCTL32_DEFAULT(RTC_WKALM_RD) }; #define NR_IOCTL32_HANDLERS (sizeof(ioctl32_handler_table) / \ Index: arch/mips64/kernel/pci-dma.c =================================================================== RCS file: /cvs/linux/arch/mips64/kernel/Attic/pci-dma.c,v retrieving revision 1.1.2.2 diff -u -r1.1.2.2 pci-dma.c --- arch/mips64/kernel/pci-dma.c 2002/05/29 03:03:17 1.1.2.2 +++ arch/mips64/kernel/pci-dma.c 2002/06/07 12:26:00 @@ -10,6 +10,7 @@ #include <linux/config.h> #include <linux/types.h> #include <linux/mm.h> +#include <linux/module.h> #include <linux/string.h> #include <linux/pci.h> @@ -22,24 +23,31 @@ void *ret; int gfp = GFP_ATOMIC; - if (hwdev != NULL && hwdev->dma_mask != 0xffffffff) + if (hwdev == NULL || hwdev->dma_mask != 0xffffffff) gfp |= GFP_DMA; ret = (void *) __get_free_pages(gfp, get_order(size)); - if (ret != NULL) { memset(ret, 0, size); + *dma_handle = __pa(ret); #ifdef CONFIG_NONCOHERENT_IO dma_cache_wback_inv((unsigned long) ret, size); ret = KSEG1ADDR(ret); #endif - *dma_handle = __pa(ret); - return ret; } - return NULL; + + return ret; } void pci_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) { - free_pages((unsigned long) KSEG0ADDR(vaddr), get_order(size)); + unsigned long addr = (unsigned long) vaddr; + +#ifdef CONFIG_NONCOHERENT_IO + addr = KSEG0ADDR(addr); +#endif + free_pages(addr, get_order(size)); } + +EXPORT_SYMBOL(pci_alloc_consistent); +EXPORT_SYMBOL(pci_free_consistent); Index: arch/mips64/kernel/r4k_fpu.S =================================================================== RCS file: /cvs/linux/arch/mips64/kernel/r4k_fpu.S,v retrieving revision 1.3 diff -u -r1.3 r4k_fpu.S --- arch/mips64/kernel/r4k_fpu.S 2001/05/25 20:07:50 1.3 +++ arch/mips64/kernel/r4k_fpu.S 2002/06/07 12:26:00 @@ -31,7 +31,7 @@ .set noreorder /* Save floating point context */ -LEAF(save_fp_context) +LEAF(_save_fp_context) mfc0 t1, CP0_STATUS sll t2, t1,5 @@ -79,7 +79,7 @@ jr ra li v0, 0 # success - END(save_fp_context) + END(_save_fp_context) /* * Restore FPU state: @@ -90,7 +90,7 @@ * frame on the current content of c0_status, not on the content of the * stack frame which might have been changed by the user. */ -LEAF(restore_fp_context) +LEAF(_restore_fp_context) mfc0 t1, CP0_STATUS sll t0, t1,5 bgez t0, 1f @@ -139,7 +139,7 @@ ctc1 t0, fcr31 jr ra li v0, 0 # success - END(restore_fp_context) + END(_restore_fp_context) .type fault@function .ent fault Index: arch/mips64/kernel/setup.c =================================================================== RCS file: /cvs/linux/arch/mips64/kernel/setup.c,v retrieving revision 1.31.2.6 diff -u -r1.31.2.6 setup.c --- arch/mips64/kernel/setup.c 2002/06/03 15:16:49 1.31.2.6 +++ arch/mips64/kernel/setup.c 2002/06/07 12:26:00 @@ -141,9 +141,6 @@ case CPU_NEVADA: case CPU_RM7000: case CPU_TX49XX: - case CPU_4KC: - case CPU_4KEC: - case CPU_4KSC: case CPU_5KC: /* case CPU_20KC:*/ cpu_wait = r4k_wait; @@ -182,6 +179,20 @@ #endif } +/* + * Get the FPU Implementation/Revision. + */ +static inline unsigned long cpu_get_fpu_id(void) +{ + unsigned long tmp, fpu_id; + + tmp = read_32bit_cp0_register(CP0_STATUS); + __enable_fpu(); + fpu_id = read_32bit_cp1_register(CP1_REVISION); + write_32bit_cp0_register(CP0_STATUS, tmp); + return fpu_id; +} + /* declaration of the global struct */ struct mips_cpu mips_cpu = { processor_id: PRID_IMP_UNKNOWN, @@ -194,15 +205,16 @@ static inline void cpu_probe(void) { -#ifdef CONFIG_CPU_MIPS32 - unsigned long config0 = read_32bit_cp0_register(CP0_CONFIG); - unsigned long config1; +#ifdef CONFIG_CPU_MIPS64 + unsigned int config0 = read_32bit_cp0_register(CP0_CONFIG); + unsigned int config1; if (config0 & (1 << 31)) { - /* MIPS32 compliant CPU. Read Config 1 register. */ - mips_cpu.isa_level = MIPS_CPU_ISA_M32; + /* MIPS64 compliant CPU. Read Config 1 register. */ + mips_cpu.isa_level = MIPS_CPU_ISA_M64; mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | - MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | MIPS_CPU_DIVEC; + MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | MIPS_CPU_DIVEC | + MIPS_CPU_32FPR; config1 = read_mips32_cp0_config1(); if (config1 & (1 << 3)) mips_cpu.options |= MIPS_CPU_WATCH; @@ -399,25 +411,15 @@ break; } break; -#ifdef CONFIG_CPU_MIPS32 +#ifdef CONFIG_CPU_MIPS64 case PRID_COMP_MIPS: switch (mips_cpu.processor_id & 0xff00) { - case PRID_IMP_4KC: - mips_cpu.cputype = CPU_4KC; - break; - case PRID_IMP_4KEC: - mips_cpu.cputype = CPU_4KEC; - break; - case PRID_IMP_4KSC: - mips_cpu.cputype = CPU_4KSC; - break; case PRID_IMP_5KC: mips_cpu.cputype = CPU_5KC; - mips_cpu.isa_level = MIPS_CPU_ISA_M64; break; case PRID_IMP_20KC: mips_cpu.cputype = CPU_20KC; - mips_cpu.isa_level = MIPS_CPU_ISA_M64; + break; default: mips_cpu.cputype = CPU_UNKNOWN; break; @@ -459,6 +461,8 @@ default: mips_cpu.cputype = CPU_UNKNOWN; } + if (mips_cpu.options & MIPS_CPU_FPU) + mips_cpu.fpu_id = cpu_get_fpu_id(); } static inline void cpu_report(void) @@ -721,10 +725,11 @@ #endif #ifdef CONFIG_SIBYTE_SWARM swarm_setup(); - bootmem_init(); /* XXX */ #endif - -#ifdef CONFIG_ARC_MEMORY +#ifdef CONFIG_MIPS_MALTA + malta_setup(); +#endif +#if defined(CONFIG_ARC_MEMORY) || defined(CONFIG_SIBYTE_SWARM) || defined(CONFIG_MIPS_MALTA) bootmem_init(); #endif Index: arch/mips64/kernel/traps.c =================================================================== RCS file: /cvs/linux/arch/mips64/kernel/traps.c,v retrieving revision 1.30.2.13 diff -u -r1.30.2.13 traps.c --- arch/mips64/kernel/traps.c 2002/05/28 06:33:13 1.30.2.13 +++ arch/mips64/kernel/traps.c 2002/06/07 12:26:00 @@ -607,6 +607,15 @@ } } +asmlinkage int (*save_fp_context)(struct sigcontext *sc); +asmlinkage int (*restore_fp_context)(struct sigcontext *sc); +extern asmlinkage int _save_fp_context(struct sigcontext *sc); +extern asmlinkage int _restore_fp_context(struct sigcontext *sc); + +extern asmlinkage int fpu_emulator_save_context(struct sigcontext *sc); +extern asmlinkage int fpu_emulator_restore_context(struct sigcontext *sc); + + void __init per_cpu_trap_init(void) { unsigned int cpu = smp_processor_id(); @@ -630,6 +639,7 @@ void __init trap_init(void) { extern char except_vec0; +/* extern char except_vec1_r4k;*/ extern char except_vec1_r10k; extern char except_vec2_generic, except_vec2_sb1; extern char except_vec3_generic, except_vec3_r4000; @@ -692,14 +702,18 @@ case CPU_R4600: case CPU_R5000: case CPU_NEVADA: - /* Cache error vector */ - memcpy((void *)(KSEG0 + 0x100), (void *) KSEG0, 0x80); - + case CPU_5KC: + case CPU_20KC: + case CPU_RM7000: nocache: /* Debug TLB refill handler. */ memcpy((void *)KSEG0, &except_vec0, 0x80); - memcpy((void *)KSEG0 + 0x080, &except_vec1_r10k, 0x80); - +/* if ((mips_cpu.options & MIPS_CPU_4KEX) + && (mips_cpu.options & MIPS_CPU_4KTLB)) { + memcpy((void *)KSEG0 + 0x080, &except_vec1_r4k, 0x80); + } else { */ + memcpy((void *)KSEG0 + 0x080, &except_vec1_r10k, 0x80); +/* }*/ if (mips_cpu.options & MIPS_CPU_VCE) { memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000, 0x80); @@ -746,6 +760,15 @@ default: panic("Unknown CPU type"); } + + if (mips_cpu.options & MIPS_CPU_FPU) { + save_fp_context = _save_fp_context; + restore_fp_context = _restore_fp_context; + } else { + save_fp_context = fpu_emulator_save_context; + restore_fp_context = fpu_emulator_restore_context; + } + flush_icache_range(KSEG0, KSEG0 + 0x200); if (mips_cpu.isa_level == MIPS_CPU_ISA_IV) Index: arch/mips64/mm/Makefile =================================================================== RCS file: /cvs/linux/arch/mips64/mm/Makefile,v retrieving revision 1.8.2.2 diff -u -r1.8.2.2 Makefile --- arch/mips64/mm/Makefile 2002/02/21 04:38:01 1.8.2.2 +++ arch/mips64/mm/Makefile 2002/06/07 12:26:00 @@ -17,6 +17,8 @@ obj-$(CONFIG_CPU_R10000) += andes.o tlbex-r4k.o tlb-glue-r4k.o obj-$(CONFIG_CPU_SB1) += pg-sb1.o c-sb1.o tlb-sb1.o tlbex-r4k.o \ tlb-glue-r4k.o +obj-$(CONFIG_CPU_MIPS64) += pg-mips64.o c-mips64.o tlb-r4k.o \ + tlbex-r4k.o tlb-glue-r4k.o # # Debug TLB exception handler, currently unused Index: arch/mips64/mm/loadmmu.c =================================================================== RCS file: /cvs/linux/arch/mips64/mm/loadmmu.c,v retrieving revision 1.14.2.3 diff -u -r1.14.2.3 loadmmu.c --- arch/mips64/mm/loadmmu.c 2002/02/18 01:14:46 1.14.2.3 +++ arch/mips64/mm/loadmmu.c 2002/06/07 12:26:01 @@ -54,33 +54,27 @@ extern void ld_mmu_andes(void); extern void ld_mmu_sb1(void); extern void sb1_tlb_init(void); +extern void ld_mmu_mips64(void); +extern void r4k_tlb_init(void); + void __init load_mmu(void) { - switch(mips_cpu.cputype) { + if (mips_cpu.options & MIPS_CPU_4KTLB) { #if defined (CONFIG_CPU_R4300) \ || defined (CONFIG_CPU_R4X00) \ || defined (CONFIG_CPU_R5000) \ || defined (CONFIG_CPU_NEVADA) - case CPU_R4000PC: - case CPU_R4000SC: - case CPU_R4000MC: - case CPU_R4200: - case CPU_R4300: - case CPU_R4400PC: - case CPU_R4400SC: - case CPU_R4400MC: - case CPU_R4600: - case CPU_R4640: - case CPU_R4650: - case CPU_R4700: - case CPU_R5000: - case CPU_R5000A: - case CPU_NEVADA: printk("Loading R4000 MMU routines.\n"); ld_mmu_r4xx0(); - break; #endif +#if defined(CONFIG_CPU_MIPS64) + printk("Loading MIPS64 MMU routines.\n"); + ld_mmu_mips64(); + r4k_tlb_init(); +#endif + + } else switch(mips_cpu.cputype) { #ifdef CONFIG_CPU_R10000 case CPU_R10000: printk("Loading R10000 MMU routines.\n"); @@ -94,8 +88,7 @@ sb1_tlb_init(); break; #endif - default: /* XXX We need an generic routine in the MIPS port * XXX to jabber stuff onto the screen on all machines Index: include/asm-mips64/addrspace.h =================================================================== RCS file: /cvs/linux/include/asm-mips64/addrspace.h,v retrieving revision 1.10 diff -u -r1.10 addrspace.h --- include/asm-mips64/addrspace.h 2001/07/09 00:25:37 1.10 +++ include/asm-mips64/addrspace.h 2002/06/07 12:26:15 @@ -29,15 +29,15 @@ * Returns the physical address of a KSEG0/KSEG1 address */ #define CPHYSADDR(a) (((unsigned long)(a)) & 0x000000001fffffffUL) -#define PHYSADDR(a) (((unsigned long)(a)) & 0x000000ffffffffffUL) +#define PHYSADDR(a) (((unsigned long)(a)) & 0x000000001fffffffUL) /* * Map an address to a certain kernel segment */ -#define KSEG0ADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x000000ffffffffffUL) | KSEG0)) -#define KSEG1ADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x000000ffffffffffUL) | KSEG1)) -#define KSEG2ADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x000000ffffffffffUL) | KSEG2)) -#define KSEG3ADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x000000ffffffffffUL) | KSEG3)) +#define KSEG0ADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x000000001fffffffUL) | KSEG0)) +#define KSEG1ADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x000000001fffffffUL) | KSEG1)) +#define KSEG2ADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x000000001fffffffUL) | KSEG2)) +#define KSEG3ADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x000000001fffffffUL) | KSEG3)) /* * Memory segments (64bit kernel mode addresses) Index: include/asm-mips64/cache.h =================================================================== RCS file: /cvs/linux/include/asm-mips64/cache.h,v retrieving revision 1.7.2.1 diff -u -r1.7.2.1 cache.h --- include/asm-mips64/cache.h 2002/05/29 03:03:18 1.7.2.1 +++ include/asm-mips64/cache.h 2002/06/07 12:26:15 @@ -23,6 +23,11 @@ }; #endif +/* + * Flag definitions + */ +#define MIPS_CACHE_NOT_PRESENT 0x00000001 + /* bytes per L1 cache line */ #define L1_CACHE_BYTES (1 << CONFIG_L1_CACHE_SHIFT) Index: include/asm-mips64/checksum.h =================================================================== RCS file: /cvs/linux/include/asm-mips64/checksum.h,v retrieving revision 1.12 diff -u -r1.12 checksum.h --- include/asm-mips64/checksum.h 2001/10/31 02:31:23 1.12 +++ include/asm-mips64/checksum.h 2002/06/07 12:26:15 @@ -161,9 +161,9 @@ : "=r" (sum) : "0" (daddr), "r"(saddr), #ifdef __MIPSEL__ - "r" ((ntohs(len)<<16)+proto*256), + "r" (((unsigned long)ntohs(len)<<16)+proto*256), #else - "r" (((proto)<<16)+len), + "r" ((((unsigned long)proto)<<16)+len), #endif "r" (sum)); Index: include/asm-mips64/ide.h =================================================================== RCS file: /cvs/linux/include/asm-mips64/ide.h,v retrieving revision 1.6 diff -u -r1.6 ide.h --- include/asm-mips64/ide.h 2001/08/22 03:25:05 1.6 +++ include/asm-mips64/ide.h 2002/06/07 12:26:15 @@ -18,6 +18,7 @@ #ifdef __KERNEL__ #include <linux/config.h> +#include <asm/io.h> #ifndef MAX_HWIFS # ifdef CONFIG_BLK_DEV_IDEPCI @@ -79,11 +80,19 @@ typedef union { unsigned all : 8; /* all of the bits together */ struct { +#ifdef __MIPSEB__ + unsigned bit7 : 1; /* always 1 */ + unsigned lba : 1; /* using LBA instead of CHS */ + unsigned bit5 : 1; /* always 1 */ + unsigned unit : 1; /* drive select number, 0 or 1 */ + unsigned head : 4; /* always zeros here */ +#else unsigned head : 4; /* always zeros here */ unsigned unit : 1; /* drive select number, 0 or 1 */ unsigned bit5 : 1; /* always 1 */ unsigned lba : 1; /* using LBA instead of CHS */ unsigned bit7 : 1; /* always 1 */ +#endif } b; } select_t; @@ -118,54 +127,141 @@ #if defined(CONFIG_SWAP_IO_SPACE) && defined(__MIPSEB__) -#ifdef insl -#undef insl -#endif -#ifdef outsl -#undef outsl -#endif +/* get rid of defs from io.h - ide has its private and conflicting versions */ #ifdef insw #undef insw #endif #ifdef outsw #undef outsw #endif +#ifdef insl +#undef insl +#endif +#ifdef outsl +#undef outsl +#endif + +#define insw(port, addr, count) ide_insw(port, addr, count) +#define insl(port, addr, count) ide_insl(port, addr, count) +#define outsw(port, addr, count) ide_outsw(port, addr, count) +#define outsl(port, addr, count) ide_outsl(port, addr, count) + +static inline void ide_insw(unsigned long port, void *addr, unsigned int count) +{ + while (count--) { + *(u16 *)addr = *(volatile u16 *)(mips_io_port_base + port); + addr += 2; + } +} + +static inline void ide_outsw(unsigned long port, void *addr, unsigned int count) +{ + while (count--) { + *(volatile u16 *)(mips_io_port_base + (port)) = *(u16 *)addr; + addr += 2; + } +} + +static inline void ide_insl(unsigned long port, void *addr, unsigned int count) +{ + while (count--) { + *(u32 *)addr = *(volatile u32 *)(mips_io_port_base + port); + addr += 4; + } +} + +static inline void ide_outsl(unsigned long port, void *addr, unsigned int count) +{ + while (count--) { + *(volatile u32 *)(mips_io_port_base + (port)) = *(u32 *)addr; + addr += 4; + } +} + +#define T_CHAR (0x0000) /* char: don't touch */ +#define T_SHORT (0x4000) /* short: 12 -> 21 */ +#define T_INT (0x8000) /* int: 1234 -> 4321 */ +#define T_TEXT (0xc000) /* text: 12 -> 21 */ + +#define T_MASK_TYPE (0xc000) +#define T_MASK_COUNT (0x3fff) + +#define D_CHAR(cnt) (T_CHAR | (cnt)) +#define D_SHORT(cnt) (T_SHORT | (cnt)) +#define D_INT(cnt) (T_INT | (cnt)) +#define D_TEXT(cnt) (T_TEXT | (cnt)) + +static u_short driveid_types[] = { + D_SHORT(10), /* config - vendor2 */ + D_TEXT(20), /* serial_no */ + D_SHORT(3), /* buf_type - ecc_bytes */ + D_TEXT(48), /* fw_rev - model */ + D_CHAR(2), /* max_multsect - vendor3 */ + D_SHORT(1), /* dword_io */ + D_CHAR(2), /* vendor4 - capability */ + D_SHORT(1), /* reserved50 */ + D_CHAR(4), /* vendor5 - tDMA */ + D_SHORT(4), /* field_valid - cur_sectors */ + D_INT(1), /* cur_capacity */ + D_CHAR(2), /* multsect - multsect_valid */ + D_INT(1), /* lba_capacity */ + D_SHORT(194) /* dma_1word - reservedyy */ +}; -#define insw(p,a,c) \ -do { \ - unsigned short *ptr = (unsigned short *)(a); \ - unsigned int i = (c); \ - while (i--) \ - *ptr++ = inw(p); \ -} while (0) -#define insl(p,a,c) \ -do { \ - unsigned long *ptr = (unsigned long *)(a); \ - unsigned int i = (c); \ - while (i--) \ - *ptr++ = inl(p); \ -} while (0) -#define outsw(p,a,c) \ -do { \ - unsigned short *ptr = (unsigned short *)(a); \ - unsigned int i = (c); \ - while (i--) \ - outw(*ptr++, (p)); \ -} while (0) -#define outsl(p,a,c) { \ - unsigned long *ptr = (unsigned long *)(a); \ - unsigned int i = (c); \ - while (i--) \ - outl(*ptr++, (p)); \ -} while (0) +#define num_driveid_types (sizeof(driveid_types)/sizeof(*driveid_types)) -#endif /* defined(CONFIG_SWAP_IO_SPACE) && defined(__MIPSEB__) */ +static __inline__ void ide_fix_driveid(struct hd_driveid *id) +{ + u_char *p = (u_char *)id; + int i, j, cnt; + u_char t; + + for (i = 0; i < num_driveid_types; i++) { + cnt = driveid_types[i] & T_MASK_COUNT; + switch (driveid_types[i] & T_MASK_TYPE) { + case T_CHAR: + p += cnt; + break; + case T_SHORT: + for (j = 0; j < cnt; j++) { + t = p[0]; + p[0] = p[1]; + p[1] = t; + p += 2; + } + break; + case T_INT: + for (j = 0; j < cnt; j++) { + t = p[0]; + p[0] = p[3]; + p[3] = t; + t = p[1]; + p[1] = p[2]; + p[2] = t; + p += 4; + } + break; + case T_TEXT: + for (j = 0; j < cnt; j += 2) { + t = p[0]; + p[0] = p[1]; + p[1] = t; + p += 2; + } + break; + }; + } +} +#else /* defined(CONFIG_SWAP_IO_SPACE) && defined(__MIPSEB__) */ + +#define ide_fix_driveid(id) do {} while (0) + +#endif /* * The following are not needed for the non-m68k ports */ #define ide_ack_intr(hwif) (1) -#define ide_fix_driveid(id) do {} while (0) #define ide_release_lock(lock) do {} while (0) #define ide_get_lock(lock, hdlr, data) do {} while (0) Index: include/asm-mips64/io.h =================================================================== RCS file: /cvs/linux/include/asm-mips64/io.h,v retrieving revision 1.25.2.5 diff -u -r1.25.2.5 io.h --- include/asm-mips64/io.h 2002/02/07 02:39:41 1.25.2.5 +++ include/asm-mips64/io.h 2002/06/07 12:26:15 @@ -13,6 +13,7 @@ #include <linux/config.h> #include <asm/addrspace.h> #include <asm/page.h> +#include <asm/byteorder.h> #ifdef CONFIG_MIPS_ATLAS #include <asm/mips-boards/io.h> @@ -98,23 +99,23 @@ /* * This assumes sane hardware. The Origin is. */ -#define readb(addr) (*(volatile unsigned char *) (addr)) -#define readw(addr) (*(volatile unsigned short *) (addr)) -#define readl(addr) (*(volatile unsigned int *) (addr)) +#define readb(addr) (*(volatile unsigned char *)(addr)) +#define readw(addr) __ioswab16((*(volatile unsigned short *)(addr))) +#define readl(addr) __ioswab32((*(volatile unsigned int *)(addr))) #define __raw_readb(addr) (*(volatile unsigned char *)(addr)) #define __raw_readw(addr) (*(volatile unsigned short *)(addr)) #define __raw_readl(addr) (*(volatile unsigned int *)(addr)) -#define writeb(b,addr) (*(volatile unsigned char *) (addr) = (b)) -#define writew(w,addr) (*(volatile unsigned short *) (addr) = (w)) -#define writel(l,addr) (*(volatile unsigned int *) (addr) = (l)) +#define writeb(b,addr) ((*(volatile unsigned char *)(addr)) = (__ioswab8(b))) +#define writew(b,addr) ((*(volatile unsigned short *)(addr)) = (__ioswab16(b))) +#define writel(b,addr) ((*(volatile unsigned int *)(addr)) = (__ioswab32(b))) #define __raw_writeb(b,addr) ((*(volatile unsigned char *)(addr)) = (b)) #define __raw_writew(w,addr) ((*(volatile unsigned short *)(addr)) = (w)) #define __raw_writel(l,addr) ((*(volatile unsigned int *)(addr)) = (l)) -#define memset_io(a,b,c) memset((void *) a,(b),(c)) +#define memset_io(a,b,c) memset((void *)(a),(b),(c)) #define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c)) #define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c)) @@ -154,12 +155,12 @@ */ static inline unsigned long virt_to_phys(volatile void * address) { - return (unsigned long)address - PAGE_OFFSET; + return (unsigned long)address & ~PAGE_OFFSET; } static inline void * phys_to_virt(unsigned long address) { - return (void *)(address + PAGE_OFFSET); + return (void *)(address | PAGE_OFFSET); } /* @@ -167,12 +168,12 @@ */ static inline unsigned long virt_to_bus(volatile void * address) { - return (unsigned long)address - PAGE_OFFSET; + return (unsigned long)address & ~PAGE_OFFSET; } static inline void * bus_to_virt(unsigned long address) { - return (void *)(address + PAGE_OFFSET); + return (void *)(address | PAGE_OFFSET); } @@ -229,202 +230,131 @@ return retval; } -/* - * Talk about misusing macros.. - */ -#define __OUT1(s) \ -static inline void __out##s(unsigned int value, unsigned long port) { +#define outb(val,port) \ +do { \ + *(volatile u8 *)(mips_io_port_base + (port)) = __ioswab8(val); \ +} while(0) + +#define outw(val,port) \ +do { \ + *(volatile u16 *)(mips_io_port_base + (port)) = __ioswab16(val);\ +} while(0) + +#define outl(val,port) \ +do { \ + *(volatile u32 *)(mips_io_port_base + (port)) = __ioswab32(val);\ +} while(0) + +#define outb_p(val,port) \ +do { \ + *(volatile u8 *)(mips_io_port_base + (port)) = __ioswab8(val); \ + SLOW_DOWN_IO; \ +} while(0) + +#define outw_p(val,port) \ +do { \ + *(volatile u16 *)(mips_io_port_base + (port)) = __ioswab16(val);\ + SLOW_DOWN_IO; \ +} while(0) + +#define outl_p(val,port) \ +do { \ + *(volatile u32 *)(mips_io_port_base + (port)) = __ioswab32(val);\ + SLOW_DOWN_IO; \ +} while(0) -#define __OUT2(m) \ -__asm__ __volatile__ ("s" #m "\t%0,%1(%2)" +static inline unsigned char inb(unsigned long port) +{ + return __ioswab8(*(volatile u8 *)(mips_io_port_base + port)); +} -#define __OUT(m,s) \ -__OUT1(s) __OUT2(m) : : "r" (value), "i" (0), "r" (mips_io_port_base+port)); } \ -__OUT1(s##c) __OUT2(m) : : "r" (value), "ir" (port), "r" (mips_io_port_base)); } \ -__OUT1(s##_p) __OUT2(m) : : "r" (value), "i" (0), "r" (mips_io_port_base+port)); \ - SLOW_DOWN_IO; } \ -__OUT1(s##c_p) __OUT2(m) : : "r" (value), "ir" (port), "r" (mips_io_port_base)); \ - SLOW_DOWN_IO; } - -#define __IN1(t,s) \ -static inline t __in##s(unsigned long port) { t _v; - -/* - * Required nops will be inserted by the assembler - */ -#define __IN2(m) \ -__asm__ __volatile__ ("l" #m "\t%0,%1(%2)" - -#define __IN(t,m,s) \ -__IN1(t,s) __IN2(m) : "=r" (_v) : "i" (0), "r" (mips_io_port_base+port)); return _v; } \ -__IN1(t,s##c) __IN2(m) : "=r" (_v) : "ir" (port), "r" (mips_io_port_base)); return _v; } \ -__IN1(t,s##_p) __IN2(m) : "=r" (_v) : "i" (0), "r" (mips_io_port_base+port)); SLOW_DOWN_IO; return _v; } \ -__IN1(t,s##c_p) __IN2(m) : "=r" (_v) : "ir" (port), "r" (mips_io_port_base)); SLOW_DOWN_IO; return _v; } - -#define __INS1(s) \ -static inline void __ins##s(unsigned long port, void * addr, unsigned long count) { - -#define __INS2(m) \ -if (count) \ -__asm__ __volatile__ ( \ - ".set\tnoreorder\n\t" \ - ".set\tnoat\n" \ - "1:\tl" #m "\t$1, %4(%5)\n\t" \ - "dsubu\t%1, 1\n\t" \ - "s" #m "\t$1,(%0)\n\t" \ - "bnez\t%1, 1b\n\t" \ - "daddiu\t%0, %6\n\t" \ - ".set\tat\n\t" \ - ".set\treorder" - -#define __INS(m,s,i) \ -__INS1(s) __INS2(m) \ - : "=r" (addr), "=r" (count) \ - : "0" (addr), "1" (count), "i" (0), "r" (mips_io_port_base+port), \ - "I" (i));} \ -__INS1(s##c) __INS2(m) \ - : "=r" (addr), "=r" (count) \ - : "0" (addr), "1" (count), "ir" (port), "r" (mips_io_port_base), \ - "I" (i));} - -#define __OUTS1(s) \ -static inline void __outs##s(unsigned long port, const void * addr, unsigned long count) { - -#define __OUTS2(m) \ -if (count) \ -__asm__ __volatile__ ( \ - ".set\tnoreorder\n\t" \ - ".set\tnoat\n" \ - "1:\tl" #m "\t$1, (%0)\n\t" \ - "dsubu\t%1, 1\n\t" \ - "s" #m "\t$1, %4(%5)\n\t" \ - "bnez\t%1, 1b\n\t" \ - "daddiu\t%0, %6\n\t" \ - ".set\tat\n\t" \ - ".set\treorder" - -#define __OUTS(m,s,i) \ -__OUTS1(s) __OUTS2(m) \ - : "=r" (addr), "=r" (count) \ - : "0" (addr), "1" (count), "i" (0), "r" (mips_io_port_base+port), \ - "I" (i));} \ -__OUTS1(s##c) __OUTS2(m) \ - : "=r" (addr), "=r" (count) \ - : "0" (addr), "1" (count), "ir" (port), "r" (mips_io_port_base), \ - "I" (i));} - -__IN(unsigned char,b,b) -__IN(unsigned short,h,w) -__IN(unsigned int,w,l) - -__OUT(b,b) -__OUT(h,w) -__OUT(w,l) - -__INS(b,b,1) -__INS(h,w,2) -__INS(w,l,4) - -__OUTS(b,b,1) -__OUTS(h,w,2) -__OUTS(w,l,4) - -/* - * Note that due to the way __builtin_constant_p() works, you - * - can't use it inside an inline function (it will never be true) - * - you don't have to worry about side effects within the __builtin.. - */ -#define outb(val,port) \ -((__builtin_constant_p((port)^(3)) && ((port)^(3)) < 32768) ? \ - __outbc((val),(port)^(3)) : \ - __outb((val),(port)^(3))) - -#define inb(port) \ -((__builtin_constant_p((port)^(3)) && ((port)^(3)) < 32768) ? \ - __inbc((port)^(3)) : \ - __inb((port)^(3))) - -#define outb_p(val,port) \ -((__builtin_constant_p((port)^(3)) && ((port)^(3)) < 32768) ? \ - __outbc_p((val),(port)^(3)) : \ - __outb_p((val),(port)^(3))) - -#define inb_p(port) \ -((__builtin_constant_p((port)^(3)) && ((port)^(3)) < 32768) ? \ - __inbc_p((port)^(3)) : \ - __inb_p((port)^(3))) - -#define outw(val,port) \ -((__builtin_constant_p(((port)^(2))) && ((port)^(2)) < 32768) ? \ - __outwc((val),((port)^(2))) : \ - __outw((val),((port)^(2)))) - -#define inw(port) \ -((__builtin_constant_p(((port)^(2))) && ((port)^(2)) < 32768) ? \ - __inwc((port)^(2)) : \ - __inw((port)^(2))) - -#define outw_p(val,port) \ -((__builtin_constant_p((port)^(2)) && ((port)^(2)) < 32768) ? \ - __outwc_p((val),(port)^(2)) : \ - __outw_p((val),(port)^(2))) - -#define inw_p(port) \ -((__builtin_constant_p((port)^(2)) && ((port)^(2)) < 32768) ? \ - __inwc_p((port)^(2)) : \ - __inw_p((port)^(2))) - -#define outl(val,port) \ -((__builtin_constant_p((port)) && (port) < 32768) ? \ - __outlc((val),(port)) : \ - __outl((val),(port))) - -#define inl(port) \ -((__builtin_constant_p((port)) && (port) < 32768) ? \ - __inlc(port) : \ - __inl(port)) - -#define outl_p(val,port) \ -((__builtin_constant_p((port)) && (port) < 32768) ? \ - __outlc_p((val),(port)) : \ - __outl_p((val),(port))) - -#define inl_p(port) \ -((__builtin_constant_p((port)) && (port) < 32768) ? \ - __inlc_p(port) : \ - __inl_p(port)) - - -#define outsb(port,addr,count) \ -((__builtin_constant_p((port)) && (port) < 32768) ? \ - __outsbc((port),(addr),(count)) : \ - __outsb ((port),(addr),(count))) - -#define insb(port,addr,count) \ -((__builtin_constant_p((port)) && (port) < 32768) ? \ - __insbc((port),(addr),(count)) : \ - __insb((port),(addr),(count))) - -#define outsw(port,addr,count) \ -((__builtin_constant_p((port)) && (port) < 32768) ? \ - __outswc((port),(addr),(count)) : \ - __outsw ((port),(addr),(count))) - -#define insw(port,addr,count) \ -((__builtin_constant_p((port)) && (port) < 32768) ? \ - __inswc((port),(addr),(count)) : \ - __insw((port),(addr),(count))) - -#define outsl(port,addr,count) \ -((__builtin_constant_p((port)) && (port) < 32768) ? \ - __outslc((port),(addr),(count)) : \ - __outsl ((port),(addr),(count))) - -#define insl(port,addr,count) \ -((__builtin_constant_p((port)) && (port) < 32768) ? \ - __inslc((port),(addr),(count)) : \ - __insl((port),(addr),(count))) +static inline unsigned short inw(unsigned long port) +{ + return __ioswab16(*(volatile u16 *)(mips_io_port_base + port)); +} + +static inline unsigned int inl(unsigned long port) +{ + return __ioswab32(*(volatile u32 *)(mips_io_port_base + port)); +} + +static inline unsigned char inb_p(unsigned long port) +{ + u8 __val; + + __val = *(volatile u8 *)(mips_io_port_base + port); + SLOW_DOWN_IO; + + return __ioswab8(__val); +} + +static inline unsigned short inw_p(unsigned long port) +{ + u16 __val; + + __val = *(volatile u16 *)(mips_io_port_base + port); + SLOW_DOWN_IO; + + return __ioswab16(__val); +} + +static inline unsigned int inl_p(unsigned long port) +{ + u32 __val; + + __val = *(volatile u32 *)(mips_io_port_base + port); + SLOW_DOWN_IO; + return __ioswab32(__val); +} + +static inline void outsb(unsigned long port, void *addr, unsigned int count) +{ + while (count--) { + outb(*(u8 *)addr, port); + addr++; + } +} + +static inline void insb(unsigned long port, void *addr, unsigned int count) +{ + while (count--) { + *(u8 *)addr = inb(port); + addr++; + } +} + +static inline void outsw(unsigned long port, void *addr, unsigned int count) +{ + while (count--) { + outw(*(u16 *)addr, port); + addr += 2; + } +} + +static inline void insw(unsigned long port, void *addr, unsigned int count) +{ + while (count--) { + *(u16 *)addr = inw(port); + addr += 2; + } +} + +static inline void outsl(unsigned long port, void *addr, unsigned int count) +{ + while (count--) { + outl(*(u32 *)addr, port); + addr += 4; + } +} + +static inline void insl(unsigned long port, void *addr, unsigned int count) +{ + while (count--) { + *(u32 *)addr = inl(port); + addr += 4; + } +} /* * The caches on some architectures aren't dma-coherent and have need to Index: include/asm-mips64/irq.h =================================================================== RCS file: /cvs/linux/include/asm-mips64/irq.h,v retrieving revision 1.4 diff -u -r1.4 irq.h --- include/asm-mips64/irq.h 2001/03/02 03:04:55 1.4 +++ include/asm-mips64/irq.h 2002/06/07 12:26:15 @@ -48,6 +48,12 @@ extern void disable_irq(unsigned int); extern void enable_irq(unsigned int); +#ifndef CONFIG_NEW_IRQ +#define disable_irq_nosync disable_irq +#else +extern void disable_irq_nosync(unsigned int); +#endif + /* Machine specific interrupt initialization */ extern void (*irq_setup)(void); Index: include/asm-mips64/page.h =================================================================== RCS file: /cvs/linux/include/asm-mips64/page.h,v retrieving revision 1.10.2.6 diff -u -r1.10.2.6 page.h --- include/asm-mips64/page.h 2002/01/24 23:14:28 1.10.2.6 +++ include/asm-mips64/page.h 2002/06/07 12:26:15 @@ -29,6 +29,10 @@ */ void sb1_clear_page(void * page); void sb1_copy_page(void * to, void * from); +void mips64_clear_page_dc(unsigned long page); +void mips64_clear_page_sc(unsigned long page); +void mips64_copy_page_dc(unsigned long to, unsigned long from); +void mips64_copy_page_sc(unsigned long to, unsigned long from); extern void (*_clear_page)(void * page); extern void (*_copy_page)(void * to, void * from); @@ -94,8 +98,8 @@ #define PAGE_OFFSET 0xa800000000000000UL #endif -#define __pa(x) ((unsigned long) (x) - PAGE_OFFSET) -#define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET)) +#define __pa(x) ((unsigned long) (x) & ~PAGE_OFFSET) +#define __va(x) ((void *)((unsigned long) (x) | PAGE_OFFSET)) #ifndef CONFIG_DISCONTIGMEM #define virt_to_page(kaddr) (mem_map + (__pa(kaddr) >> PAGE_SHIFT)) #define VALID_PAGE(page) ((page - mem_map) < max_mapnr) Index: include/asm-mips64/pci.h =================================================================== RCS file: /cvs/linux/include/asm-mips64/pci.h,v retrieving revision 1.16.2.2 diff -u -r1.16.2.2 pci.h --- include/asm-mips64/pci.h 2002/02/26 06:00:25 1.16.2.2 +++ include/asm-mips64/pci.h 2002/06/07 12:26:15 @@ -173,7 +173,7 @@ dma_cache_wback_inv(addr, size); #endif - return virt_to_bus(addr); + return virt_to_bus((void *)addr); } static inline void pci_unmap_page(struct pci_dev *hwdev, dma_addr_t dma_address, @@ -213,7 +213,7 @@ #ifdef CONFIG_NONCOHERENT_IO dma_cache_wback_inv((unsigned long)sg->address, sg->length); #endif - sg->dma_address = (char *)(__pa(sg->address)); +/* sg->dma_address = (char *)(__pa(sg->address));*/ } return nents; @@ -250,7 +250,7 @@ if (direction == PCI_DMA_NONE) BUG(); #ifdef CONFIG_NONCOHERENT_IO - dma_cache_wback_inv((unsigned long)__va(dma_handle - bus_to_baddr[hwdev->bus->number]), size); + dma_cache_wback_inv((unsigned long)bus_to_virt(dma_handle), size); #endif } @@ -287,7 +287,7 @@ * so we can't guarantee allocations that must be * within a tighter range than GFP_DMA.. */ - if (mask < 0x00ffffff) + if (mask < 0x1fffffff) return 0; return 1; @@ -339,7 +339,7 @@ * returns, or alternatively stop on the first sg_dma_len(sg) which * is 0. */ -#define sg_dma_address(sg) ((unsigned long)((sg)->address)) +#define sg_dma_address(sg) (virt_to_bus((sg)->address)) #define sg_dma_len(sg) ((sg)->length) #endif /* __KERNEL__ */ Index: include/asm-mips64/pgtable.h =================================================================== RCS file: /cvs/linux/include/asm-mips64/pgtable.h,v retrieving revision 1.47.2.10 diff -u -r1.47.2.10 pgtable.h --- include/asm-mips64/pgtable.h 2002/05/28 09:49:45 1.47.2.10 +++ include/asm-mips64/pgtable.h 2002/06/07 12:26:15 @@ -74,23 +74,13 @@ #else -extern void (*_flush_icache_all)(void); -extern void (*_flush_icache_range)(unsigned long start, unsigned long end); -extern void (*_flush_icache_page)(struct vm_area_struct *vma, struct page *page); - #define flush_cache_mm(mm) _flush_cache_mm(mm) #define flush_cache_range(mm,start,end) _flush_cache_range(mm,start,end) #define flush_cache_page(vma,page) _flush_cache_page(vma, page) #define flush_page_to_ram(page) _flush_page_to_ram(page) #define flush_icache_range(start, end) _flush_icache_range(start, end) #define flush_icache_page(vma, page) _flush_icache_page(vma, page) -#ifdef CONFIG_VTAG_ICACHE -#define flush_icache_all() _flush_icache_all() -#else -#define flush_icache_all() do { } while(0) -#endif - #endif /* !CONFIG_CPU_R10000 */ #define flush_cache_sigtramp(addr) _flush_cache_sigtramp(addr) @@ -198,11 +188,11 @@ #ifdef CONFIG_MIPS_UNCACHED #define PAGE_CACHABLE_DEFAULT _CACHE_UNCACHED #else /* ! UNCACHED */ -#ifdef CONFIG_SGI_IP22 -#define PAGE_CACHABLE_DEFAULT _CACHE_CACHABLE_NONCOHERENT -#else /* ! IP22 */ +#if defined(CONFIG_SGI_IP27) || defined(CONFIG_SGI_IP32) #define PAGE_CACHABLE_DEFAULT _CACHE_CACHABLE_COW -#endif /* IP22 */ +#else +#define PAGE_CACHABLE_DEFAULT _CACHE_CACHABLE_NONCOHERENT +#endif #endif /* UNCACHED */ #define PAGE_NONE __pgprot(_PAGE_PRESENT | PAGE_CACHABLE_DEFAULT) @@ -569,6 +559,8 @@ #ifndef CONFIG_DISCONTIGMEM #define kern_addr_valid(addr) (1) #endif + +#define io_remap_page_range remap_page_range /* * No page table caches to initialise Index: include/asm-mips64/serial.h =================================================================== RCS file: /cvs/linux/include/asm-mips64/serial.h,v retrieving revision 1.7.2.3 diff -u -r1.7.2.3 serial.h --- include/asm-mips64/serial.h 2002/05/29 03:03:18 1.7.2.3 +++ include/asm-mips64/serial.h 2002/06/07 12:26:15 @@ -65,7 +65,6 @@ /* * The IP32 (SGI O2) has standard serial ports (UART 16550A) mapped in memory */ - /* Standard COM flags (except for COM4, because of the 8514 problem) */ #ifdef CONFIG_SERIAL_DETECT_IRQ #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ) @@ -88,13 +87,37 @@ iomem_base: (u8*)MACE_BASE+MACEISA_SER2_BASE, \ iomem_reg_shift: 8, \ io_type: SERIAL_IO_MEM}, + #else #define IP32_SERIAL_PORT_DEFNS #endif /* CONFIG_SGI_IP31 */ +#ifdef CONFIG_HAVE_STD_PC_SERIAL_PORT + +/* Standard COM flags (except for COM4, because of the 8514 problem) */ +#ifdef CONFIG_SERIAL_DETECT_IRQ +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ) +#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ) +#else +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) +#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF +#endif + +#define STD_SERIAL_PORT_DEFNS \ + /* UART CLK PORT IRQ FLAGS */ \ + { 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS }, /* ttyS0 */ \ + { 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS }, /* ttyS1 */ \ + { 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS }, /* ttyS2 */ \ + { 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS }, /* ttyS3 */ + +#else /* CONFIG_HAVE_STD_PC_SERIAL_PORTS */ +#define STD_SERIAL_PORT_DEFNS +#endif /* CONFIG_HAVE_STD_PC_SERIAL_PORTS */ + #define SERIAL_PORT_DFNS \ IP27_SERIAL_PORT_DEFNS \ - IP32_SERIAL_PORT_DEFNS + IP32_SERIAL_PORT_DEFNS \ + STD_SERIAL_PORT_DEFNS #define RS_TABLE_SIZE 64 Index: include/asm-mips64/system.h =================================================================== RCS file: /cvs/linux/include/asm-mips64/system.h,v retrieving revision 1.18.2.7 diff -u -r1.18.2.7 system.h --- include/asm-mips64/system.h 2002/05/28 05:53:06 1.18.2.7 +++ include/asm-mips64/system.h 2002/06/07 12:26:15 @@ -202,9 +202,9 @@ extern asmlinkage void lazy_fpu_switch(void *, void *); extern asmlinkage void init_fpu(void); -extern asmlinkage void save_fp(struct task_struct *); -extern asmlinkage void restore_fp(struct task_struct *); +extern asmlinkage void save_fp(void *); +extern asmlinkage void restore_fp(void *); #ifdef CONFIG_SMP #define SWITCH_DO_LAZY_FPU \
/* * Carsten Langgaard, carstenl@mips.com * Copyright (C) 2002 MIPS Technologies, Inc. All rights reserved. * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. * * MIPS64 CPU variant specific Cache routines. * These routine are not optimized in any way, they are done in a generic way * so they can be used on all MIPS64 compliant CPUs, and also done in an * attempt not to break anything for the R4xx0 style CPUs. */ #include <linux/init.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/mm.h> #include <asm/bootinfo.h> #include <asm/cpu.h> #include <asm/bcache.h> #include <asm/io.h> #include <asm/page.h> #include <asm/pgtable.h> #include <asm/system.h> #include <asm/mmu_context.h> /* CP0 hazard avoidance. */ #define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ "nop; nop; nop; nop; nop; nop;\n\t" \ ".set reorder\n\t") /* Primary cache parameters. */ int icache_size, dcache_size; /* Size in bytes */ int ic_lsize, dc_lsize; /* LineSize in bytes */ /* Secondary cache (if present) parameters. */ unsigned int scache_size, sc_lsize; /* Again, in bytes */ #include <asm/cacheops.h> #include <asm/mips64_cache.h> #undef DEBUG_CACHE /* * Dummy cache handling routines for machines without boardcaches */ static void no_sc_noop(void) {} static struct bcache_ops no_sc_ops = { (void *)no_sc_noop, (void *)no_sc_noop, (void *)no_sc_noop, (void *)no_sc_noop }; struct bcache_ops *bcops = &no_sc_ops; static inline void mips64_flush_cache_all_sc(void) { unsigned long flags; __save_and_cli(flags); blast_dcache(); blast_icache(); blast_scache(); __restore_flags(flags); } static inline void mips64_flush_cache_all_pc(void) { unsigned long flags; __save_and_cli(flags); blast_dcache(); blast_icache(); __restore_flags(flags); } static void mips64_flush_cache_range_sc(struct mm_struct *mm, unsigned long start, unsigned long end) { struct vm_area_struct *vma; unsigned long flags; if(mm->context == 0) return; start &= PAGE_MASK; #ifdef DEBUG_CACHE printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); #endif vma = find_vma(mm, start); if(vma) { if(mm->context != current->mm->context) { mips64_flush_cache_all_sc(); } else { pgd_t *pgd; pmd_t *pmd; pte_t *pte; __save_and_cli(flags); while(start < end) { pgd = pgd_offset(mm, start); pmd = pmd_offset(pgd, start); pte = pte_offset(pmd, start); if(pte_val(*pte) & _PAGE_VALID) blast_scache_page(start); start += PAGE_SIZE; } __restore_flags(flags); } } } static void mips64_flush_cache_range_pc(struct mm_struct *mm, unsigned long start, unsigned long end) { if(mm->context != 0) { unsigned long flags; #ifdef DEBUG_CACHE printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); #endif __save_and_cli(flags); blast_dcache(); blast_icache(); __restore_flags(flags); } } /* * On architectures like the Sparc, we could get rid of lines in * the cache created only by a certain context, but on the MIPS * (and actually certain Sparc's) we cannot. */ static void mips64_flush_cache_mm_sc(struct mm_struct *mm) { if(mm->context != 0) { #ifdef DEBUG_CACHE printk("cmm[%d]", (int)mm->context); #endif mips64_flush_cache_all_sc(); } } static void mips64_flush_cache_mm_pc(struct mm_struct *mm) { if(mm->context != 0) { #ifdef DEBUG_CACHE printk("cmm[%d]", (int)mm->context); #endif mips64_flush_cache_all_pc(); } } static void mips64_flush_cache_page_sc(struct vm_area_struct *vma, unsigned long page) { struct mm_struct *mm = vma->vm_mm; unsigned long flags; pgd_t *pgdp; pmd_t *pmdp; pte_t *ptep; /* * If ownes no valid ASID yet, cannot possibly have gotten * this page into the cache. */ if (mm->context == 0) return; #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif __save_and_cli(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); ptep = pte_offset(pmdp, page); /* * If the page isn't marked valid, the page cannot possibly be * in the cache. */ if (!(pte_val(*ptep) & _PAGE_VALID)) goto out; /* * Doing flushes for another ASID than the current one is * too difficult since R4k caches do a TLB translation * for every cache flush operation. So we do indexed flushes * in that case, which doesn't overly flush the cache too much. */ if (mm->context != current->active_mm->context) { /* * Do indexed flush, too much work to get the (possible) * tlb refills to work correctly. */ page = (KSEG0 + (page & (scache_size - 1))); blast_dcache_page_indexed(page); blast_scache_page_indexed(page); } else blast_scache_page(page); out: __restore_flags(flags); } static void mips64_flush_cache_page_pc(struct vm_area_struct *vma, unsigned long page) { struct mm_struct *mm = vma->vm_mm; unsigned long flags; pgd_t *pgdp; pmd_t *pmdp; pte_t *ptep; /* * If ownes no valid ASID yet, cannot possibly have gotten * this page into the cache. */ if (mm->context == 0) return; #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif __save_and_cli(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); ptep = pte_offset(pmdp, page); /* * If the page isn't marked valid, the page cannot possibly be * in the cache. */ if (!(pte_val(*ptep) & _PAGE_VALID)) goto out; /* * Doing flushes for another ASID than the current one is * too difficult since Mips64 caches do a TLB translation * for every cache flush operation. So we do indexed flushes * in that case, which doesn't overly flush the cache too much. */ if (mm == current->active_mm) { blast_dcache_page(page); } else { /* Do indexed flush, too much work to get the (possible) * tlb refills to work correctly. */ page = (KSEG0 + (page & ((unsigned long)dcache_size - 1))); blast_dcache_page_indexed(page); } out: __restore_flags(flags); } /* If the addresses passed to these routines are valid, they are * either: * * 1) In KSEG0, so we can do a direct flush of the page. * 2) In KSEG2, and since every process can translate those * addresses all the time in kernel mode we can do a direct * flush. * 3) In KSEG1, no flush necessary. */ static void mips64_flush_page_to_ram_sc(struct page *page) { blast_scache_page((unsigned long)page_address(page)); } static void mips64_flush_page_to_ram_pc(struct page *page) { blast_dcache_page((unsigned long)page_address(page)); } static void mips64_flush_icache_page_s(struct vm_area_struct *vma, struct page *page) { /* * We did an scache flush therefore PI is already clean. */ } static void mips64_flush_icache_range(unsigned long start, unsigned long end) { flush_cache_all(); } static void mips64_flush_icache_page(struct vm_area_struct *vma, struct page *page) { unsigned long address; if (!(vma->vm_flags & VM_EXEC)) return; address = KSEG0 + ((unsigned long)page_address(page) & PAGE_MASK & ((unsigned long)dcache_size - 1)); blast_icache_page_indexed(address); } /* * Writeback and invalidate the primary cache dcache before DMA. */ static void mips64_dma_cache_wback_inv_pc(unsigned long addr, unsigned long size) { unsigned long end, a; unsigned int flags; if (size >= (unsigned long)dcache_size) { flush_cache_all(); } else { __save_and_cli(flags); a = addr & ~(dc_lsize - 1); end = (addr + size) & ~((unsigned long)dc_lsize - 1); while (1) { flush_dcache_line(a); /* Hit_Writeback_Inv_D */ if (a == end) break; a += dc_lsize; } __restore_flags(flags); } bc_wback_inv(addr, size); } static void mips64_dma_cache_wback_inv_sc(unsigned long addr, unsigned long size) { unsigned long end, a; if (size >= scache_size) { flush_cache_all(); return; } a = addr & ~(sc_lsize - 1); end = (addr + size) & ~(sc_lsize - 1); while (1) { flush_scache_line(a); /* Hit_Writeback_Inv_SD */ if (a == end) break; a += sc_lsize; } } static void mips64_dma_cache_inv_pc(unsigned long addr, unsigned long size) { unsigned long end, a; unsigned int flags; if (size >= (unsigned long)dcache_size) { flush_cache_all(); } else { __save_and_cli(flags); a = addr & ~((unsigned long)dc_lsize - 1); end = (addr + size) & ~((unsigned long)dc_lsize - 1); while (1) { flush_dcache_line(a); /* Hit_Writeback_Inv_D */ if (a == end) break; a += (unsigned long)dc_lsize; } __restore_flags(flags); } bc_inv(addr, size); } static void mips64_dma_cache_inv_sc(unsigned long addr, unsigned long size) { unsigned long end, a; if (size >= scache_size) { flush_cache_all(); return; } a = addr & ~(sc_lsize - 1); end = (addr + size) & ~(sc_lsize - 1); while (1) { flush_scache_line(a); /* Hit_Writeback_Inv_SD */ if (a == end) break; a += sc_lsize; } } static void mips64_dma_cache_wback(unsigned long addr, unsigned long size) { panic("mips64_dma_cache called - should not happen.\n"); } /* * While we're protected against bad userland addresses we don't care * very much about what happens in that case. Usually a segmentation * fault will dump the process later on anyway ... */ static void mips64_flush_cache_sigtramp(unsigned long addr) { protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); protected_flush_icache_line(addr & ~(ic_lsize - 1)); } static void mips64_flush_icache_all(void) { if (mips_cpu.cputype == CPU_20KC) { blast_icache(); } } /* Detect and size the various caches. */ static void __init probe_icache(unsigned long config) { unsigned long config1; unsigned int lsize; if (!(config & (1 << 31))) { /* * Not a MIPS64 complainant CPU. * Config 1 register not supported, we assume R4k style. */ icache_size = 1 << (12 + ((config >> 9) & 7)); ic_lsize = 16 << ((config >> 5) & 1); mips_cpu.icache.linesz = ic_lsize; /* * We cannot infer associativity - assume direct map * unless probe template indicates otherwise */ if(!mips_cpu.icache.ways) mips_cpu.icache.ways = 1; mips_cpu.icache.sets = (icache_size / ic_lsize) / mips_cpu.icache.ways; } else { config1 = read_mips32_cp0_config1(); if ((lsize = ((config1 >> 19) & 7))) mips_cpu.icache.linesz = 2 << lsize; else mips_cpu.icache.linesz = lsize; mips_cpu.icache.sets = 64 << ((config1 >> 22) & 7); mips_cpu.icache.ways = 1 + ((config1 >> 16) & 7); ic_lsize = mips_cpu.icache.linesz; icache_size = mips_cpu.icache.sets * mips_cpu.icache.ways * ic_lsize; } printk("Primary instruction cache %dkb, linesize %d bytes (%d ways)\n", icache_size >> 10, ic_lsize, mips_cpu.icache.ways); } static void __init probe_dcache(unsigned long config) { unsigned long config1; unsigned int lsize; if (!(config & (1 << 31))) { /* * Not a MIPS64 complainant CPU. * Config 1 register not supported, we assume R4k style. */ dcache_size = 1 << (12 + ((config >> 6) & 7)); dc_lsize = 16 << ((config >> 4) & 1); mips_cpu.dcache.linesz = dc_lsize; /* * We cannot infer associativity - assume direct map * unless probe template indicates otherwise */ if(!mips_cpu.dcache.ways) mips_cpu.dcache.ways = 1; mips_cpu.dcache.sets = (dcache_size / dc_lsize) / mips_cpu.dcache.ways; } else { config1 = read_mips32_cp0_config1(); if ((lsize = ((config1 >> 10) & 7))) mips_cpu.dcache.linesz = 2 << lsize; else mips_cpu.dcache.linesz= lsize; mips_cpu.dcache.sets = 64 << ((config1 >> 13) & 7); mips_cpu.dcache.ways = 1 + ((config1 >> 7) & 7); dc_lsize = mips_cpu.dcache.linesz; dcache_size = mips_cpu.dcache.sets * mips_cpu.dcache.ways * dc_lsize; } printk("Primary data cache %dkb, linesize %d bytes (%d ways)\n", dcache_size >> 10, dc_lsize, mips_cpu.dcache.ways); } /* If you even _breathe_ on this function, look at the gcc output * and make sure it does not pop things on and off the stack for * the cache sizing loop that executes in KSEG1 space or else * you will crash and burn badly. You have been warned. */ static int __init probe_scache(unsigned long config) { extern unsigned long stext; unsigned long flags, addr, begin, end, pow2; int tmp; if (mips_cpu.scache.flags == MIPS_CACHE_NOT_PRESENT) return 0; tmp = ((config >> 17) & 1); if(tmp) return 0; tmp = ((config >> 22) & 3); switch(tmp) { case 0: sc_lsize = 16; break; case 1: sc_lsize = 32; break; case 2: sc_lsize = 64; break; case 3: sc_lsize = 128; break; } begin = (unsigned long) &stext; begin &= ~((4 * 1024 * 1024) - 1); end = begin + (4 * 1024 * 1024); /* This is such a bitch, you'd think they would make it * easy to do this. Away you daemons of stupidity! */ __save_and_cli(flags); /* Fill each size-multiple cache line with a valid tag. */ pow2 = (64 * 1024); for(addr = begin; addr < end; addr = (begin + pow2)) { unsigned long *p = (unsigned long *) addr; __asm__ __volatile__("nop" : : "r" (*p)); /* whee... */ pow2 <<= 1; } /* Load first line with zero (therefore invalid) tag. */ set_taglo(0); set_taghi(0); __asm__ __volatile__("nop; nop; nop; nop;"); /* avoid the hazard */ __asm__ __volatile__("\n\t.set noreorder\n\t" "cache 8, (%0)\n\t" ".set reorder\n\t" : : "r" (begin)); __asm__ __volatile__("\n\t.set noreorder\n\t" "cache 9, (%0)\n\t" ".set reorder\n\t" : : "r" (begin)); __asm__ __volatile__("\n\t.set noreorder\n\t" "cache 11, (%0)\n\t" ".set reorder\n\t" : : "r" (begin)); /* Now search for the wrap around point. */ pow2 = (128 * 1024); tmp = 0; for(addr = (begin + (128 * 1024)); addr < (end); addr = (begin + pow2)) { __asm__ __volatile__("\n\t.set noreorder\n\t" "cache 7, (%0)\n\t" ".set reorder\n\t" : : "r" (addr)); __asm__ __volatile__("nop; nop; nop; nop;"); /* hazard... */ if(!get_taglo()) break; pow2 <<= 1; } __restore_flags(flags); addr -= begin; printk("Secondary cache sized at %dK linesize %d bytes.\n", (int) (addr >> 10), sc_lsize); scache_size = addr; return 1; } static void __init setup_noscache_funcs(void) { _clear_page = (void *)mips64_clear_page_dc; _copy_page = (void *)mips64_copy_page_dc; _flush_cache_all = mips64_flush_cache_all_pc; ___flush_cache_all = mips64_flush_cache_all_pc; _flush_cache_mm = mips64_flush_cache_mm_pc; _flush_cache_range = mips64_flush_cache_range_pc; _flush_cache_page = mips64_flush_cache_page_pc; _flush_page_to_ram = mips64_flush_page_to_ram_pc; _flush_icache_page = mips64_flush_icache_page; _dma_cache_wback_inv = mips64_dma_cache_wback_inv_pc; _dma_cache_wback = mips64_dma_cache_wback; _dma_cache_inv = mips64_dma_cache_inv_pc; } static void __init setup_scache_funcs(void) { _flush_cache_all = mips64_flush_cache_all_sc; ___flush_cache_all = mips64_flush_cache_all_sc; _flush_cache_mm = mips64_flush_cache_mm_sc; _flush_cache_range = mips64_flush_cache_range_sc; _flush_cache_page = mips64_flush_cache_page_sc; _flush_page_to_ram = mips64_flush_page_to_ram_sc; _clear_page = (void *)mips64_clear_page_sc; _copy_page = (void *)mips64_copy_page_sc; _flush_icache_page = mips64_flush_icache_page_s; _dma_cache_wback_inv = mips64_dma_cache_wback_inv_sc; _dma_cache_wback = mips64_dma_cache_wback; _dma_cache_inv = mips64_dma_cache_inv_sc; } typedef int (*probe_func_t)(unsigned long); static inline void __init setup_scache(unsigned int config) { probe_func_t probe_scache_kseg1; int sc_present = 0; /* Maybe the cpu knows about a l2 cache? */ probe_scache_kseg1 = (probe_func_t) (KSEG1ADDR(&probe_scache)); sc_present = probe_scache_kseg1(config); if (sc_present) { mips_cpu.scache.linesz = sc_lsize; /* * We cannot infer associativity - assume direct map * unless probe template indicates otherwise */ if(!mips_cpu.scache.ways) mips_cpu.scache.ways = 1; mips_cpu.scache.sets = (scache_size / sc_lsize) / mips_cpu.scache.ways; setup_scache_funcs(); return; } setup_noscache_funcs(); } void __init ld_mmu_mips64(void) { unsigned long config = read_32bit_cp0_register(CP0_CONFIG); #ifdef CONFIG_MIPS_UNCACHED change_cp0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); #else change_cp0_config(CONF_CM_CMASK, CONF_CM_CACHABLE_NONCOHERENT); #endif probe_icache(config); probe_dcache(config); setup_scache(config); _flush_cache_sigtramp = mips64_flush_cache_sigtramp; _flush_icache_range = mips64_flush_icache_range; /* Ouch */ _flush_icache_all = mips64_flush_icache_all; _flush_cache_l1 = _flush_cache_all; _flush_cache_l2 = _flush_cache_all; __flush_cache_all(); }
/* * Carsten Langgaard, carstenl@mips.com * Copyright (C) 2002 MIPS Technologies, Inc. All rights reserved. * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. * * MIPS64 CPU variant specific Cache routines. * These routine are not optimized in any way, they are done in a generic way * so they can be used on all MIPS64 compliant CPUs, and also done in an * attempt not to break anything for the R4xx0 style CPUs. */ #include <linux/sched.h> #include <linux/mm.h> #include <asm/bootinfo.h> #include <asm/cacheops.h> #include <asm/cpu.h> extern int dc_lsize, ic_lsize, sc_lsize; /* * Zero an entire page. */ void mips64_clear_page_dc(unsigned long page) { unsigned long i; if (mips_cpu.options & MIPS_CPU_CACHE_CDEX) { for (i=page; i<page+PAGE_SIZE; i+=dc_lsize) { __asm__ __volatile__( ".set\tnoreorder\n\t" ".set\tnoat\n\t" "cache\t%2,(%0)\n\t" ".set\tat\n\t" ".set\treorder" :"=r" (i) :"0" (i), "I" (Create_Dirty_Excl_D)); } } for (i=page; i<page+PAGE_SIZE; i+=sizeof(long)) *(unsigned long *)(i) = 0; } void mips64_clear_page_sc(unsigned long page) { unsigned long i; if (mips_cpu.options & MIPS_CPU_CACHE_CDEX) { for (i=page; i<page+PAGE_SIZE; i+=sc_lsize) { __asm__ __volatile__( ".set\tnoreorder\n\t" ".set\tnoat\n\t" "cache\t%2,(%0)\n\t" ".set\tat\n\t" ".set\treorder" :"=r" (i) :"0" (i), "I" (Create_Dirty_Excl_SD)); } } for (i=page; i<page+PAGE_SIZE; i+=sizeof(long)) *(unsigned long *)(i) = 0; } void mips64_copy_page_dc(unsigned long to, unsigned long from) { unsigned long i; if (mips_cpu.options & MIPS_CPU_CACHE_CDEX) { for (i=to; i<to+PAGE_SIZE; i+=dc_lsize) { __asm__ __volatile__( ".set\tnoreorder\n\t" ".set\tnoat\n\t" "cache\t%2,(%0)\n\t" ".set\tat\n\t" ".set\treorder" :"=r" (i) :"0" (i), "I" (Create_Dirty_Excl_D)); } } for (i=0; i<PAGE_SIZE; i+=sizeof(long)) *(unsigned long *)(to+i) = *(unsigned long *)(from+i); } void mips64_copy_page_sc(unsigned long to, unsigned long from) { unsigned long i; if (mips_cpu.options & MIPS_CPU_CACHE_CDEX) { for (i=to; i<to+PAGE_SIZE; i+=sc_lsize) { __asm__ __volatile__( ".set\tnoreorder\n\t" ".set\tnoat\n\t" "cache\t%2,(%0)\n\t" ".set\tat\n\t" ".set\treorder" :"=r" (i) :"0" (i), "I" (Create_Dirty_Excl_SD)); } } for (i=0; i<PAGE_SIZE; i+=sizeof(long)) *(unsigned long *)(to+i) = *(unsigned long *)(from+i); }
/* * Carsten Langgaard, carstenl@mips.com * Copyright (C) 2002 MIPS Technologies, Inc. All rights reserved. * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. * * MIPS64 CPU variant specific MMU routines. * These routine are not optimized in any way, they are done in a generic way * so they can be used on all MIPS64 compliant CPUs, and also done in an * attempt not to break anything for the R4xx0 style CPUs. */ #include <linux/init.h> #include <linux/sched.h> #include <linux/mm.h> #include <asm/cpu.h> #include <asm/bootinfo.h> #include <asm/mmu_context.h> #include <asm/pgtable.h> #include <asm/system.h> #undef DEBUG_TLB #undef DEBUG_TLBUPDATE /*extern char except_vec1_r4k;*/ /* CP0 hazard avoidance. */ #define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ "nop; nop; nop; nop; nop; nop;\n\t" \ ".set reorder\n\t") void local_flush_tlb_all(void) { unsigned long flags; unsigned long old_ctx; int entry; #ifdef DEBUG_TLB printk("[tlball]"); #endif __save_and_cli(flags); /* Save old context and create impossible VPN2 value */ old_ctx = (get_entryhi() & 0xff); set_entryhi(KSEG0); set_entrylo0(0); set_entrylo1(0); BARRIER; entry = get_wired(); /* Blast 'em all away. */ while(entry < mips_cpu.tlbsize) { /* Make sure all entries differ. */ set_entryhi(KSEG0+entry*0x2000); set_index(entry); BARRIER; tlb_write_indexed(); BARRIER; entry++; } BARRIER; set_entryhi(old_ctx); __restore_flags(flags); } void local_flush_tlb_mm(struct mm_struct *mm) { if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { unsigned long flags; #ifdef DEBUG_TLB printk("[tlbmm<%d>]", mm->context); #endif __save_and_cli(flags); get_new_mmu_context(mm, smp_processor_id()); if (mm == current->active_mm) set_entryhi(CPU_CONTEXT(smp_processor_id(), mm) & 0xff); __restore_flags(flags); } } void local_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) { if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { unsigned long flags; int size; #ifdef DEBUG_TLB printk("[tlbrange<%02x,%08lx,%08lx>]", (mm->context & 0xff), start, end); #endif __save_and_cli(flags); size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; size = (size + 1) >> 1; if(size <= mips_cpu.tlbsize/2) { int oldpid = (get_entryhi() & 0xff); int newpid = (CPU_CONTEXT(smp_processor_id(), mm) & 0xff); start &= (PAGE_MASK << 1); end += ((PAGE_SIZE << 1) - 1); end &= (PAGE_MASK << 1); while(start < end) { int idx; set_entryhi(start | newpid); start += (PAGE_SIZE << 1); BARRIER; tlb_probe(); BARRIER; idx = get_index(); set_entrylo0(0); set_entrylo1(0); if(idx < 0) continue; /* Make sure all entries differ. */ set_entryhi(KSEG0+idx*0x2000); BARRIER; tlb_write_indexed(); BARRIER; } set_entryhi(oldpid); } else { get_new_mmu_context(mm, smp_processor_id()); if (mm == current->active_mm) set_entryhi(CPU_CONTEXT(smp_processor_id(), mm) & 0xff); } __restore_flags(flags); } } void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) { if (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) != 0) { unsigned long flags; unsigned long oldpid, newpid, idx; #ifdef DEBUG_TLB printk("[tlbpage<%d,%08lx>]", vma->vm_mm->context, page); #endif newpid = (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) & 0xff); page &= (PAGE_MASK << 1); __save_and_cli(flags); oldpid = (get_entryhi() & 0xff); set_entryhi(page | newpid); BARRIER; tlb_probe(); BARRIER; idx = get_index(); set_entrylo0(0); set_entrylo1(0); if(idx < 0) goto finish; /* Make sure all entries differ. */ set_entryhi(KSEG0+idx*0x2000); BARRIER; tlb_write_indexed(); finish: BARRIER; set_entryhi(oldpid); __restore_flags(flags); } } /* * Updates the TLB with the new pte(s). */ void mips64_update_mmu_cache(struct vm_area_struct * vma, unsigned long address, pte_t pte) { unsigned long flags; pgd_t *pgdp; pmd_t *pmdp; pte_t *ptep; int idx, pid; /* * Handle debugger faulting in for debugee. */ if (current->active_mm != vma->vm_mm) return; pid = get_entryhi() & 0xff; #ifdef DEBUG_TLB if((pid != (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) & 0xff)) || (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) == 0)) { printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%d tlbpid=%d\n", (int) (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) & 0xff), pid); } #endif __save_and_cli(flags); address &= (PAGE_MASK << 1); set_entryhi(address | (pid)); pgdp = pgd_offset(vma->vm_mm, address); BARRIER; tlb_probe(); BARRIER; pmdp = pmd_offset(pgdp, address); idx = get_index(); ptep = pte_offset(pmdp, address); BARRIER; set_entrylo0(pte_val(*ptep++) >> 6); set_entrylo1(pte_val(*ptep) >> 6); set_entryhi(address | (pid)); BARRIER; if(idx < 0) { tlb_write_random(); } else { tlb_write_indexed(); } BARRIER; set_entryhi(pid); BARRIER; __restore_flags(flags); } void dump_mm_page(unsigned long addr) { pgd_t *page_dir, *pgd; pmd_t *pmd; pte_t *pte, page; unsigned long val; page_dir = pgd_offset(current->mm, 0); pgd = pgd_offset(current->mm, addr); pmd = pmd_offset(pgd, addr); pte = pte_offset(pmd, addr); page = *pte; printk("Memory Mapping: VA = %08x, PA = %08x ", addr, (unsigned int) pte_val(page)); val = pte_val(page); if (val & _PAGE_PRESENT) printk("present "); if (val & _PAGE_READ) printk("read "); if (val & _PAGE_WRITE) printk("write "); if (val & _PAGE_ACCESSED) printk("accessed "); if (val & _PAGE_MODIFIED) printk("modified "); if (val & _PAGE_R4KBUG) printk("r4kbug "); if (val & _PAGE_GLOBAL) printk("global "); if (val & _PAGE_VALID) printk("valid "); printk("\n"); } void show_tlb(void) { unsigned int flags; unsigned int old_ctx; unsigned int entry; unsigned int entrylo0, entrylo1, entryhi; __save_and_cli(flags); /* Save old context */ old_ctx = (get_entryhi() & 0xff); printk("TLB content:\n"); entry = 0; while(entry < mips_cpu.tlbsize) { set_index(entry); BARRIER; tlb_read(); BARRIER; entryhi = get_entryhi(); entrylo0 = get_entrylo0(); entrylo1 = get_entrylo1(); printk("%02d: ASID=%02d%s VA=0x%08x ", entry, entryhi & ASID_MASK, (entrylo0 & entrylo1 & 1) ? "(G)" : " ", entryhi & ~ASID_MASK); printk("PA0=0x%08x C0=%x %s%s%s\n", (entrylo0>>6)<<12, (entrylo0>>3) & 7, (entrylo0 & 4) ? "Dirty " : "", (entrylo0 & 2) ? "Valid " : "Invalid ", (entrylo0 & 1) ? "Global" : ""); printk("\t\t\t PA1=0x%08x C1=%x %s%s%s\n", (entrylo1>>6)<<12, (entrylo1>>3) & 7, (entrylo1 & 4) ? "Dirty " : "", (entrylo1 & 2) ? "Valid " : "Invalid ", (entrylo1 & 1) ? "Global" : ""); dump_mm_page(entryhi & ~0xff); dump_mm_page((entryhi & ~0xff) | 0x1000); entry++; } BARRIER; set_entryhi(old_ctx); __restore_flags(flags); } void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, unsigned long entryhi, unsigned long pagemask) { unsigned long flags; unsigned long wired; unsigned long old_pagemask; unsigned long old_ctx; __save_and_cli(flags); /* Save old context and create impossible VPN2 value */ old_ctx = (get_entryhi() & 0xff); old_pagemask = get_pagemask(); wired = get_wired(); set_wired (wired + 1); set_index (wired); BARRIER; set_pagemask (pagemask); set_entryhi(entryhi); set_entrylo0(entrylo0); set_entrylo1(entrylo1); BARRIER; tlb_write_indexed(); BARRIER; set_entryhi(old_ctx); BARRIER; set_pagemask (old_pagemask); local_flush_tlb_all(); __restore_flags(flags); } /* * Used for loading TLB entries before trap_init() has started, when we * don't actually want to add a wired entry which remains throughout the * lifetime of the system */ static int temp_tlb_entry __initdata; __init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1, unsigned long entryhi, unsigned long pagemask) { int ret = 0; unsigned long flags; unsigned long wired; unsigned long old_pagemask; unsigned long old_ctx; __save_and_cli(flags); /* Save old context and create impossible VPN2 value */ old_ctx = get_entryhi() & 0xff; old_pagemask = get_pagemask(); wired = get_wired(); if (--temp_tlb_entry < wired) { printk(KERN_WARNING "No TLB space left for add_temporary_entry\n"); ret = -ENOSPC; goto out; } set_index(temp_tlb_entry); BARRIER; set_pagemask(pagemask); set_entryhi(entryhi); set_entrylo0(entrylo0); set_entrylo1(entrylo1); BARRIER; tlb_write_indexed(); BARRIER; set_entryhi(old_ctx); BARRIER; set_pagemask(old_pagemask); out: __restore_flags(flags); return ret; } static void __init probe_tlb(unsigned long config) { unsigned long config1; if (!(config & (1 << 31))) { /* * Not a MIPS64 complainant CPU. * Config 1 register not supported, we assume R4k style. */ mips_cpu.tlbsize = 48; } else { config1 = read_mips32_cp0_config1(); if (!((config >> 7) & 3)) panic("No MMU present"); else mips_cpu.tlbsize = ((config1 >> 25) & 0x3f) + 1; } printk("Number of TLB entries %d.\n", mips_cpu.tlbsize); } void __init r4k_tlb_init(void) { unsigned long config = read_32bit_cp0_register(CP0_CONFIG); probe_tlb(config); _update_mmu_cache = mips64_update_mmu_cache; set_pagemask(PM_4K); write_32bit_cp0_register(CP0_WIRED, 0); temp_tlb_entry = mips_cpu.tlbsize - 1; local_flush_tlb_all(); /* memcpy((void *)(KSEG0 + 0x80), &except_vec1_r4k, 0x80);*/ flush_icache_range(KSEG0, KSEG0 + 0x80); }
/* * mips64_cache.h * * Carsten Langgaard, carstenl@mips.com * Copyright (C) 2002 MIPS Technologies, Inc. All rights reserved. * * ######################################################################## * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. * * ######################################################################## * * Inline assembly cache operations. * * This file is the original r4cache.c file with modification that makes the * cache handling more generic. * * FIXME: Handle split L2 caches. * */ #ifndef _MIPS_MIPS64_CACHE_H #define _MIPS_MIPS64_CACHE_H #include <asm/asm.h> #include <asm/cacheops.h> static inline void flush_icache_line_indexed(unsigned long addr) { __asm__ __volatile__( ".set noreorder\n\t" "cache %1, (%0)\n\t" ".set reorder" : : "r" (addr), "i" (Index_Invalidate_I)); } static inline void flush_dcache_line_indexed(unsigned long addr) { __asm__ __volatile__( ".set noreorder\n\t" "cache %1, (%0)\n\t" ".set reorder" : : "r" (addr), "i" (Index_Writeback_Inv_D)); } static inline void flush_scache_line_indexed(unsigned long addr) { __asm__ __volatile__( ".set noreorder\n\t" "cache %1, (%0)\n\t" ".set reorder" : : "r" (addr), "i" (Index_Writeback_Inv_SD)); } static inline void flush_icache_line(unsigned long addr) { __asm__ __volatile__( ".set noreorder\n\t" "cache %1, (%0)\n\t" ".set reorder" : : "r" (addr), "i" (Hit_Invalidate_I)); } static inline void flush_dcache_line(unsigned long addr) { __asm__ __volatile__( ".set noreorder\n\t" "cache %1, (%0)\n\t" ".set reorder" : : "r" (addr), "i" (Hit_Writeback_Inv_D)); } static inline void invalidate_dcache_line(unsigned long addr) { __asm__ __volatile__( ".set noreorder\n\t" "cache %1, (%0)\n\t" ".set reorder" : : "r" (addr), "i" (Hit_Invalidate_D)); } static inline void invalidate_scache_line(unsigned long addr) { __asm__ __volatile__( ".set noreorder\n\t" "cache %1, (%0)\n\t" ".set reorder" : : "r" (addr), "i" (Hit_Invalidate_SD)); } static inline void flush_scache_line(unsigned long addr) { __asm__ __volatile__( ".set noreorder\n\t" "cache %1, (%0)\n\t" ".set reorder" : : "r" (addr), "i" (Hit_Writeback_Inv_SD)); } /* * The next two are for badland addresses like signal trampolines. */ static inline void protected_flush_icache_line(unsigned long addr) { __asm__ __volatile__( ".set noreorder\n\t" "1:\tcache %1,(%0)\n" "2:\t.set reorder\n\t" ".section\t__ex_table,\"a\"\n\t" ".dword\t1b,2b\n\t" ".previous" : : "r" (addr), "i" (Hit_Invalidate_I)); } static inline void protected_writeback_dcache_line(unsigned long addr) { __asm__ __volatile__( ".set noreorder\n\t" "1:\tcache %1,(%0)\n" "2:\t.set reorder\n\t" ".section\t__ex_table,\"a\"\n\t" ".dword\t1b,2b\n\t" ".previous" : : "r" (addr), "i" (Hit_Writeback_D)); } #define cache_unroll(base,op) \ __asm__ __volatile__(" \ .set noreorder; \ cache %1, (%0); \ .set reorder" \ : \ : "r" (base), \ "i" (op)); static inline void blast_dcache(void) { unsigned long start = KSEG0; unsigned long end = (start + dcache_size); while(start < end) { cache_unroll(start,Index_Writeback_Inv_D); start += dc_lsize; } } static inline void blast_dcache_page(unsigned long page) { unsigned long start = page; unsigned long end = (start + PAGE_SIZE); while(start < end) { cache_unroll(start,Hit_Writeback_Inv_D); start += dc_lsize; } } static inline void blast_dcache_page_indexed(unsigned long page) { unsigned long start = page; unsigned long end = (start + PAGE_SIZE); while(start < end) { cache_unroll(start,Index_Writeback_Inv_D); start += dc_lsize; } } static inline void blast_icache(void) { unsigned long start = KSEG0; unsigned long end = (start + icache_size); while(start < end) { cache_unroll(start,Index_Invalidate_I); start += ic_lsize; } } static inline void blast_icache_page(unsigned long page) { unsigned long start = page; unsigned long end = (start + PAGE_SIZE); while(start < end) { cache_unroll(start,Hit_Invalidate_I); start += ic_lsize; } } static inline void blast_icache_page_indexed(unsigned long page) { unsigned long start = page; unsigned long end = (start + PAGE_SIZE); while(start < end) { cache_unroll(start,Index_Invalidate_I); start += ic_lsize; } } static inline void blast_scache(void) { unsigned long start = KSEG0; unsigned long end = KSEG0 + scache_size; while(start < end) { cache_unroll(start,Index_Writeback_Inv_SD); start += sc_lsize; } } static inline void blast_scache_page(unsigned long page) { unsigned long start = page; unsigned long end = page + PAGE_SIZE; while(start < end) { cache_unroll(start,Hit_Writeback_Inv_SD); start += sc_lsize; } } static inline void blast_scache_page_indexed(unsigned long page) { unsigned long start = page; unsigned long end = page + PAGE_SIZE; while(start < end) { cache_unroll(start,Index_Writeback_Inv_SD); start += sc_lsize; } } #endif /* !(_MIPS_MIPS64_CACHE_H) */