--- linux-2.5.68/arch/alpha/Kconfig 2003-04-19 20:45:17.000000000 -0700 +++ 25/arch/alpha/Kconfig 2003-04-29 20:50:34.000000000 -0700 @@ -291,7 +291,7 @@ config PCI VESA. If you have PCI, say Y, otherwise N. The PCI-HOWTO, available from - , contains valuable + , contains valuable information about which PCI hardware does work under Linux and which doesn't. @@ -514,7 +514,7 @@ config SMP See also the , , , and the SMP-HOWTO available at - . + . If you don't know what to do here, say N. @@ -688,7 +688,7 @@ config BINFMT_ELF want to say Y here. Information about ELF is contained in the ELF HOWTO available from - . + . If you find that after upgrading from Linux kernel 1.2 and saying Y here, you still can't run any ELF binaries (they just crash), then @@ -710,7 +710,7 @@ config BINFMT_MISC programs that need an interpreter to run like Java, Python or Emacs-Lisp. It's also useful if you often run DOS executables under the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, available from - ). Once you have + ). Once you have registered such a binary class with the kernel, you can start one of those programs simply by typing in its name at a shell prompt; Linux will automatically feed it to the correct interpreter. @@ -862,7 +862,7 @@ config CD_NO_IDESCSI ---help--- If you have a CD-ROM drive that is neither SCSI nor IDE/ATAPI, say Y here, otherwise N. Read the CD-ROM-HOWTO, available from - . + . Note that the answer to this question doesn't directly affect the kernel: saying N will just cause the configurator to skip all @@ -912,7 +912,7 @@ config SOUND interrupt and DMA channel), because you will be asked for it. You want to read the Sound-HOWTO, available from - . General information about + . General information about the modular sound system is contained in the files . The file contains some slightly --- linux-2.5.68/arch/alpha/kernel/core_irongate.c 2003-02-24 13:08:45.000000000 -0800 +++ 25/arch/alpha/kernel/core_irongate.c 2003-04-29 20:50:34.000000000 -0700 @@ -14,6 +14,7 @@ #include #include #include +#include #include #include --- linux-2.5.68/arch/alpha/kernel/core_marvel.c 2003-03-17 14:56:00.000000000 -0800 +++ 25/arch/alpha/kernel/core_marvel.c 2003-04-29 20:50:34.000000000 -0700 @@ -452,7 +452,6 @@ marvel_init_arch(void) /* With multiple PCI busses, we play with I/O as physical addrs. */ ioport_resource.end = ~0UL; - iomem_resource.end = ~0UL; /* PCI DMA Direct Mapping is 1GB at 2GB. */ __direct_map_base = 0x80000000; --- linux-2.5.68/arch/alpha/kernel/core_mcpcia.c 2003-01-16 18:22:19.000000000 -0800 +++ 25/arch/alpha/kernel/core_mcpcia.c 2003-04-29 20:50:34.000000000 -0700 @@ -407,7 +407,6 @@ mcpcia_init_arch(void) { /* With multiple PCI busses, we play with I/O as physical addrs. */ ioport_resource.end = ~0UL; - iomem_resource.end = ~0UL; /* Allocate hose 0. That's the one that all the ISA junk hangs off of, from which we'll be registering stuff here in a bit. --- linux-2.5.68/arch/alpha/kernel/core_titan.c 2003-03-17 14:56:00.000000000 -0800 +++ 25/arch/alpha/kernel/core_titan.c 2003-04-29 20:50:34.000000000 -0700 @@ -412,7 +412,6 @@ titan_init_arch(void) /* With multiple PCI busses, we play with I/O as physical addrs. */ ioport_resource.end = ~0UL; - iomem_resource.end = ~0UL; /* PCI DMA Direct Mapping is 1GB at 2GB. */ __direct_map_base = 0x80000000; --- linux-2.5.68/arch/alpha/kernel/core_tsunami.c 2003-01-16 18:22:01.000000000 -0800 +++ 25/arch/alpha/kernel/core_tsunami.c 2003-04-29 20:50:34.000000000 -0700 @@ -390,7 +390,6 @@ tsunami_init_arch(void) #endif /* With multiple PCI busses, we play with I/O as physical addrs. */ ioport_resource.end = ~0UL; - iomem_resource.end = ~0UL; /* Find how many hoses we have, and initialize them. TSUNAMI and TYPHOON can have 2, but might only have 1 (DS10). */ --- linux-2.5.68/arch/alpha/kernel/core_wildfire.c 2003-01-16 18:21:33.000000000 -0800 +++ 25/arch/alpha/kernel/core_wildfire.c 2003-04-29 20:50:34.000000000 -0700 @@ -309,7 +309,6 @@ wildfire_init_arch(void) /* With multiple PCI buses, we play with I/O as physical addrs. */ ioport_resource.end = ~0UL; - iomem_resource.end = ~0UL; /* Probe the hardware for info about configuration. */ --- linux-2.5.68/arch/alpha/kernel/irq.c 2003-03-17 14:56:00.000000000 -0800 +++ 25/arch/alpha/kernel/irq.c 2003-04-29 20:50:34.000000000 -0700 @@ -45,7 +45,10 @@ volatile unsigned long irq_err_count; * Special irq handlers. */ -void no_action(int cpl, void *dev_id, struct pt_regs *regs) { } +irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs) +{ + return IRQ_NONE; +} /* * Generic no controller code @@ -414,7 +417,7 @@ init_irq_proc (void) } int -request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), +request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long irqflags, const char * devname, void *dev_id) { int retval; --- linux-2.5.68/arch/alpha/kernel/proto.h 2003-04-19 20:45:17.000000000 -0700 +++ 25/arch/alpha/kernel/proto.h 2003-04-29 20:50:34.000000000 -0700 @@ -1,4 +1,5 @@ #include +#include /* Prototypes of functions used across modules here in this directory. */ @@ -128,7 +129,7 @@ extern void smp_percpu_timer_interrupt(s /* extern void reset_for_srm(void); */ /* time.c */ -extern void timer_interrupt(int irq, void *dev, struct pt_regs * regs); +extern irqreturn_t timer_interrupt(int irq, void *dev, struct pt_regs * regs); extern void common_init_rtc(void); extern unsigned long est_cycle_freq; --- linux-2.5.68/arch/alpha/kernel/setup.c 2003-04-19 20:45:17.000000000 -0700 +++ 25/arch/alpha/kernel/setup.c 2003-04-29 20:50:34.000000000 -0700 @@ -32,11 +32,7 @@ #include #include #include - -#ifdef CONFIG_BLK_DEV_INITRD -#include -#endif - +#include #ifdef CONFIG_MAGIC_SYSRQ #include #include --- linux-2.5.68/arch/alpha/kernel/srmcons.c 2003-02-10 12:24:11.000000000 -0800 +++ 25/arch/alpha/kernel/srmcons.c 2003-04-29 20:50:34.000000000 -0700 @@ -318,11 +318,11 @@ srm_console_write(struct console *co, co spin_unlock_irqrestore(&srmcons_callback_lock, flags); } -static kdev_t -srm_console_device(struct console *co) +static struct tty_driver * +srm_console_device(struct console *co, int *index) { - return mk_kdev(srmcons_driver.major, - srmcons_driver.minor_start + co->index); + *index = co->index; + return &srmcons_driver; } static int __init --- linux-2.5.68/arch/alpha/kernel/time.c 2003-04-19 20:45:17.000000000 -0700 +++ 25/arch/alpha/kernel/time.c 2003-04-29 20:50:34.000000000 -0700 @@ -94,7 +94,7 @@ static inline __u32 rpcc(void) * timer_interrupt() needs to keep up the real-time clock, * as well as call the "do_timer()" routine every clocktick */ -void timer_interrupt(int irq, void *dev, struct pt_regs * regs) +irqreturn_t timer_interrupt(int irq, void *dev, struct pt_regs * regs) { unsigned long delta; __u32 now; @@ -139,6 +139,7 @@ void timer_interrupt(int irq, void *dev, } write_sequnlock(&xtime_lock); + return IRQ_HANDLED; } void --- linux-2.5.68/arch/alpha/mm/init.c 2003-01-16 18:22:43.000000000 -0800 +++ 25/arch/alpha/mm/init.c 2003-04-29 20:50:34.000000000 -0700 @@ -66,19 +66,9 @@ pgd_alloc(struct mm_struct *mm) pte_t * pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) { - pte_t *pte; - long timeout = 10; - - retry: - pte = (pte_t *) __get_free_page(GFP_KERNEL); + pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT); if (pte) clear_page(pte); - else if (--timeout >= 0) { - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(HZ); - goto retry; - } - return pte; } --- linux-2.5.68/arch/alpha/mm/numa.c 2003-02-24 13:08:45.000000000 -0800 +++ 25/arch/alpha/mm/numa.c 2003-04-29 20:50:34.000000000 -0700 @@ -12,9 +12,7 @@ #include #include #include -#ifdef CONFIG_BLK_DEV_INITRD -#include -#endif +#include #include #include --- linux-2.5.68/arch/arm/boot/compressed/head-sa1100.S 2003-01-16 18:21:38.000000000 -0800 +++ 25/arch/arm/boot/compressed/head-sa1100.S 2003-04-29 20:50:34.000000000 -0700 @@ -50,6 +50,10 @@ __SA1100_start: 10: #endif + mrc p15, 0, r0, c1, c0, 0 @ read control reg + ands r0, r0, #0x0d + beq 99f + @ Data cache might be active. @ Be sure to flush kernel binary out of the cache, @ whatever state it is, before it is turned off. @@ -68,11 +72,4 @@ __SA1100_start: bic r0, r0, #0x0d @ clear WB, DC, MMU bic r0, r0, #0x1000 @ clear Icache mcr p15, 0, r0, c1, c0, 0 - -/* - * Pause for a short time so that we give enough time - * for the host to start a terminal up. - */ - mov r0, #0x00200000 -1: subs r0, r0, #1 - bne 1b +99: --- linux-2.5.68/arch/arm/boot/compressed/head-xscale.S 2003-04-19 20:45:17.000000000 -0700 +++ 25/arch/arm/boot/compressed/head-xscale.S 2003-04-29 20:50:34.000000000 -0700 @@ -35,7 +35,7 @@ __XScale_start: mcr p15, 0, r0, c1, c0, 0 #ifdef CONFIG_ARCH_IQ80321 - orr pc, pc, #0xa0000000 + orr pc, pc, #PHYS_OFFSET @ jump to physical memory if we are not there. nop mov r7, #MACH_TYPE_IQ80321 #endif --- linux-2.5.68/arch/arm/def-configs/shark 2003-01-16 18:21:39.000000000 -0800 +++ 25/arch/arm/def-configs/shark 2003-04-29 20:50:34.000000000 -0700 @@ -2,14 +2,9 @@ # Automatically generated make config: don't edit # CONFIG_ARM=y -# CONFIG_EISA is not set -# CONFIG_SBUS is not set -# CONFIG_MCA is not set +CONFIG_MMU=y CONFIG_UID16=y CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -# CONFIG_GENERIC_BUST_SPINLOCK is not set -# CONFIG_GENERIC_ISA_DMA is not set # # Code maturity level options @@ -19,15 +14,19 @@ CONFIG_EXPERIMENTAL=y # # General setup # -CONFIG_NET=y +CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 # # Loadable module support # CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set CONFIG_KMOD=y @@ -58,112 +57,41 @@ CONFIG_ARCH_SHARK=y # # Archimedes/A5000 Implementations (select only ONE) # -# CONFIG_ARCH_ARC is not set -# CONFIG_ARCH_A5K is not set # -# Footbridge Implementations +# CLPS711X/EP721X Implementations # -# CONFIG_ARCH_CATS is not set -# CONFIG_ARCH_PERSONAL_SERVER is not set -# CONFIG_ARCH_EBSA285_ADDIN is not set -# CONFIG_ARCH_EBSA285_HOST is not set -# CONFIG_ARCH_NETWINDER is not set # -# SA11x0 Implementations +# Epxa10db # -# CONFIG_SA1100_ASSABET is not set -# CONFIG_ASSABET_NEPONSET is not set -# CONFIG_SA1100_ADSBITSY is not set -# CONFIG_SA1100_BRUTUS is not set -# CONFIG_SA1100_CERF is not set -# CONFIG_SA1100_H3100 is not set -# CONFIG_SA1100_H3600 is not set -# CONFIG_SA1100_H3800 is not set -# CONFIG_SA1100_H3XXX is not set -# CONFIG_SA1100_EXTENEX1 is not set -# CONFIG_SA1100_FLEXANET is not set -# CONFIG_SA1100_FREEBIRD is not set -# CONFIG_SA1100_GRAPHICSCLIENT is not set -# CONFIG_SA1100_GRAPHICSMASTER is not set -# CONFIG_SA1100_BADGE4 is not set -# CONFIG_SA1100_JORNADA720 is not set -# CONFIG_SA1100_HUW_WEBPANEL is not set -# CONFIG_SA1100_ITSY is not set -# CONFIG_SA1100_LART is not set -# CONFIG_SA1100_NANOENGINE is not set -# CONFIG_SA1100_OMNIMETER is not set -# CONFIG_SA1100_PANGOLIN is not set -# CONFIG_SA1100_PLEB is not set -# CONFIG_SA1100_PT_SYSTEM3 is not set -# CONFIG_SA1100_SHANNON is not set -# CONFIG_SA1100_SHERMAN is not set -# CONFIG_SA1100_SIMPAD is not set -# CONFIG_SA1100_PFS168 is not set -# CONFIG_SA1100_VICTOR is not set -# CONFIG_SA1100_XP860 is not set -# CONFIG_SA1100_YOPY is not set -# CONFIG_SA1100_STORK is not set -# CONFIG_SA1100_USB is not set -# CONFIG_SA1100_USB_NETLINK is not set -# CONFIG_SA1100_USB_CHAR is not set -# CONFIG_H3600_SLEEVE is not set # -# Intel PXA250/210 Implementations +# Footbridge Implementations # -# CONFIG_ARCH_LUBBOCK is not set -# CONFIG_ARCH_PXA_IDP is not set # -# CLPS711X/EP721X Implementations +# IOP310 Implementation Options # -# CONFIG_ARCH_AUTCPU12 is not set -# CONFIG_ARCH_CDB89712 is not set -# CONFIG_ARCH_CLEP7312 is not set -# CONFIG_ARCH_EDB7211 is not set -# CONFIG_ARCH_P720T is not set -# CONFIG_ARCH_FORTUNET is not set -# CONFIG_ARCH_EP7211 is not set -# CONFIG_ARCH_EP7212 is not set # -# IOP310 Implementation Options +# IOP310 Chipset Features # -# CONFIG_ARCH_IQ80310 is not set # -# IOP310 Chipset Features +# Intel PXA250/210 Implementations +# + +# +# SA11x0 Implementations # -# CONFIG_IOP310_AAU is not set -# CONFIG_IOP310_DMA is not set -# CONFIG_IOP310_MU is not set -# CONFIG_IOP310_PMON is not set -# CONFIG_ARCH_ACORN is not set -# CONFIG_FOOTBRIDGE is not set -# CONFIG_FOOTBRIDGE_HOST is not set -# CONFIG_FOOTBRIDGE_ADDIN is not set -CONFIG_CPU_32=y -# CONFIG_CPU_26 is not set # # Processor Type # -# CONFIG_CPU_32v3 is not set -CONFIG_CPU_32v4=y -# CONFIG_CPU_32v5 is not set -# CONFIG_CPU_ARM610 is not set -# CONFIG_CPU_ARM710 is not set -# CONFIG_CPU_ARM720T is not set -# CONFIG_CPU_ARM920T is not set -# CONFIG_CPU_ARM922T is not set -# CONFIG_CPU_ARM926T is not set -# CONFIG_CPU_ARM1020 is not set +CONFIG_CPU_32=y CONFIG_CPU_SA110=y -# CONFIG_CPU_SA1100 is not set -# CONFIG_CPU_XSCALE is not set -# CONFIG_XSCALE_PMU is not set +CONFIG_CPU_32v4=y # # Processor Features @@ -172,19 +100,16 @@ CONFIG_CPU_SA110=y # # General setup # -# CONFIG_DISCONTIGMEM is not set CONFIG_PCI=y -# CONFIG_PCI_HOST_PLX90X0 is not set CONFIG_PCI_HOST_VIA82C505=y CONFIG_ISA=y CONFIG_ISA_DMA=y -# CONFIG_FIQ is not set # CONFIG_ZBOOT_ROM is not set -CONFIG_ZBOOT_ROM_TEXT=0 -CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_PCI_LEGACY_PROC=y # CONFIG_PCI_NAMES is not set # CONFIG_HOTPLUG is not set -# CONFIG_PCMCIA is not set # # At least one math emulation must be selected @@ -198,7 +123,6 @@ CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set # CONFIG_PM is not set # CONFIG_PREEMPT is not set -# CONFIG_APM is not set # CONFIG_ARTHUR is not set CONFIG_CMDLINE="" CONFIG_LEDS=y @@ -216,11 +140,6 @@ CONFIG_PARPORT_PC_CML1=y # CONFIG_PARPORT_PC_FIFO is not set # CONFIG_PARPORT_PC_SUPERIO is not set # CONFIG_PARPORT_ARC is not set -# CONFIG_PARPORT_AMIGA is not set -# CONFIG_PARPORT_MFC3 is not set -# CONFIG_PARPORT_ATARI is not set -# CONFIG_PARPORT_GSC is not set -# CONFIG_PARPORT_SUNBPP is not set # CONFIG_PARPORT_OTHER is not set # CONFIG_PARPORT_1284 is not set @@ -230,11 +149,9 @@ CONFIG_PARPORT_PC_CML1=y # CONFIG_MTD is not set # -# Plug and Play configuration +# Plug and Play support # # CONFIG_PNP is not set -# CONFIG_ISAPNP is not set -# CONFIG_PNPBIOS is not set # # Block devices @@ -244,7 +161,6 @@ CONFIG_PARPORT_PC_CML1=y # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_CISS_SCSI_TAPE is not set # CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_UMEM is not set CONFIG_BLK_DEV_LOOP=y @@ -257,13 +173,11 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 # Multi-device support (RAID and LVM) # # CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_MD_MULTIPATH is not set -# CONFIG_BLK_DEV_LVM is not set + +# +# Networking support +# +CONFIG_NET=y # # Networking options @@ -272,8 +186,8 @@ CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set # CONFIG_NETLINK_DEV is not set # CONFIG_NETFILTER is not set -CONFIG_FILTER=y CONFIG_UNIX=y +# CONFIG_NET_KEY is not set CONFIG_INET=y # CONFIG_IP_MULTICAST is not set # CONFIG_IP_ADVANCED_ROUTER is not set @@ -283,25 +197,23 @@ CONFIG_INET=y # CONFIG_ARPD is not set # CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set # CONFIG_IPV6 is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set - -# -# -# -# CONFIG_IPX is not set -# CONFIG_ATALK is not set +# CONFIG_XFRM_USER is not set # -# Appletalk devices +# SCTP Configuration (EXPERIMENTAL) # -# CONFIG_DEV_APPLETALK is not set +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_LLC is not set # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -314,8 +226,9 @@ CONFIG_INET=y # CONFIG_NET_SCHED is not set # -# Network device support +# Network testing # +# CONFIG_NET_PKTGEN is not set CONFIG_NETDEVICES=y # @@ -332,47 +245,43 @@ CONFIG_NETDEVICES=y # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y -# CONFIG_ARM_AM79C961A is not set -# CONFIG_SUNLANCE is not set +# CONFIG_MII is not set # CONFIG_HAPPYMEAL is not set -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set # CONFIG_SUNGEM is not set # CONFIG_NET_VENDOR_3COM is not set # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set # CONFIG_AT1700 is not set # CONFIG_DEPCA is not set # CONFIG_HP100 is not set # CONFIG_NET_ISA is not set CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set # CONFIG_AC3200 is not set # CONFIG_APRICOT is not set +# CONFIG_B44 is not set CONFIG_CS89x0=y # CONFIG_DGRS is not set # CONFIG_EEPRO100 is not set # CONFIG_E100 is not set -# CONFIG_LNE390 is not set # CONFIG_FEALNX is not set # CONFIG_NATSEMI is not set # CONFIG_NE2K_PCI is not set -# CONFIG_NE3210 is not set -# CONFIG_ES3210 is not set # CONFIG_8139CP is not set # CONFIG_8139TOO is not set -# CONFIG_8139TOO_PIO is not set -# CONFIG_8139TOO_TUNE_TWISTER is not set -# CONFIG_8139TOO_8129 is not set -# CONFIG_8139_NEW_RX_RESET is not set # CONFIG_SIS900 is not set # CONFIG_EPIC100 is not set # CONFIG_SUNDANCE is not set # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set -# CONFIG_VIA_RHINE_MMIO is not set # CONFIG_NET_POCKET is not set # @@ -381,10 +290,10 @@ CONFIG_CS89x0=y # CONFIG_ACENIC is not set # CONFIG_DL2K is not set # CONFIG_E1000 is not set -# CONFIG_MYRI_SBUS is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set # CONFIG_FDDI is not set @@ -399,9 +308,8 @@ CONFIG_CS89x0=y # CONFIG_NET_RADIO is not set # -# Token Ring devices +# Token Ring devices (depends on LLC=y) # -# CONFIG_TR is not set # CONFIG_NET_FC is not set # CONFIG_RCPCI is not set # CONFIG_SHAPER is not set @@ -412,9 +320,9 @@ CONFIG_CS89x0=y # CONFIG_WAN is not set # -# Tulip family network device support +# IrDA (infrared) support # -# CONFIG_NET_TULIP is not set +# CONFIG_IRDA is not set # # Amateur Radio support @@ -422,75 +330,32 @@ CONFIG_CS89x0=y # CONFIG_HAMRADIO is not set # -# IrDA (infrared) support +# ATA/ATAPI/MFM/RLL support # -# CONFIG_IRDA is not set +CONFIG_IDE=y # -# ATA/ATAPI/MFM/RLL support +# IDE, ATA and ATAPI Block devices # -CONFIG_IDE=y CONFIG_BLK_DEV_IDE=y -# CONFIG_BLK_DEV_HD_IDE is not set + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# # CONFIG_BLK_DEV_HD is not set CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set # CONFIG_IDEDISK_STROKE is not set -CONFIG_ATAPI=y CONFIG_BLK_DEV_IDECD=y -# CONFIG_BLK_DEV_IDETAPE is not set CONFIG_BLK_DEV_IDEFLOPPY=y # CONFIG_BLK_DEV_IDESCSI is not set -# CONFIG_BLK_DEV_IDECS is not set +# CONFIG_IDE_TASK_IOCTL is not set # -# ATA host controller support +# IDE chipset support/bugfixes # -# CONFIG_BLK_DEV_RZ1000 is not set -# CONFIG_BLK_DEV_CMD640 is not set -# CONFIG_BLK_DEV_CMD640_ENHANCED is not set -# CONFIG_BLK_DEV_ISAPNP is not set - -# -# PCI host controller support -# -# CONFIG_BLK_DEV_OFFBOARD is not set -# CONFIG_IDEPCI_SHARE_IRQ is not set -# CONFIG_BLK_DEV_IDEDMA_PCI is not set -# CONFIG_IDEDMA_PCI_AUTO is not set -# CONFIG_IDEDMA_ONLYDISK is not set -# CONFIG_BLK_DEV_IDEDMA is not set -# CONFIG_BLK_DEV_IDE_TCQ is not set -# CONFIG_BLK_DEV_IDE_TCQ_DEFAULT is not set -# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set -# CONFIG_BLK_DEV_AEC62XX is not set -# CONFIG_AEC6280_BURST is not set -# CONFIG_BLK_DEV_ALI15X3 is not set -# CONFIG_WDC_ALI15X3 is not set -# CONFIG_BLK_DEV_AMD74XX is not set -# CONFIG_BLK_DEV_CMD64X is not set -# CONFIG_BLK_DEV_CY82C693 is not set -# CONFIG_BLK_DEV_CS5530 is not set -# CONFIG_BLK_DEV_HPT34X is not set -# CONFIG_HPT34X_AUTODMA is not set -# CONFIG_BLK_DEV_HPT366 is not set -# CONFIG_BLK_DEV_PIIX is not set -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_OPTI621 is not set -# CONFIG_BLK_DEV_PDC202XX is not set -# CONFIG_PDC202XX_BURST is not set -# CONFIG_PDC202XX_FORCE is not set -# CONFIG_BLK_DEV_SVWKS is not set -# CONFIG_BLK_DEV_SIS5513 is not set -# CONFIG_BLK_DEV_TRM290 is not set -# CONFIG_BLK_DEV_VIA82CXXX is not set -# CONFIG_BLK_DEV_SL82C105 is not set +# CONFIG_BLK_DEV_IDEPCI is not set # CONFIG_IDE_CHIPSETS is not set -# CONFIG_IDEDMA_IVB is not set -# CONFIG_IDEDMA_AUTO is not set -# CONFIG_BLK_DEV_ATARAID is not set -# CONFIG_BLK_DEV_ATARAID_PDC is not set -# CONFIG_BLK_DEV_ATARAID_HPT is not set # # SCSI support @@ -501,12 +366,10 @@ CONFIG_SCSI=m # SCSI support type (disk, tape, CD-ROM) # CONFIG_BLK_DEV_SD=m -CONFIG_SD_EXTRA_DEVS=40 CONFIG_CHR_DEV_ST=m # CONFIG_CHR_DEV_OSST is not set CONFIG_BLK_DEV_SR=m # CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_SR_EXTRA_DEVS=2 CONFIG_CHR_DEV_SG=m # @@ -525,8 +388,10 @@ CONFIG_CHR_DEV_SG=m # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AHA152X is not set # CONFIG_SCSI_AHA1542 is not set +# CONFIG_SCSI_AACRAID is not set # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_IN2000 is not set @@ -537,11 +402,11 @@ CONFIG_CHR_DEV_SG=m # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_DTC3280 is not set # CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set # CONFIG_SCSI_EATA_PIO is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set # CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_PPA is not set @@ -559,11 +424,11 @@ CONFIG_CHR_DEV_SG=m # CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_SIM710 is not set # CONFIG_SCSI_SYM53C416 is not set # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_T128 is not set # CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_NSP32 is not set # CONFIG_SCSI_DEBUG is not set # @@ -575,11 +440,6 @@ CONFIG_CHR_DEV_SG=m # I2O device support # # CONFIG_I2O is not set -# CONFIG_I2O_PCI is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set # # ISDN subsystem @@ -589,47 +449,55 @@ CONFIG_CHR_DEV_SG=m # # Input device support # -# CONFIG_INPUT is not set +CONFIG_INPUT=y # # Userland interfaces # -# CONFIG_INPUT_KEYBDEV is not set -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_JOYDEV is not set # CONFIG_INPUT_TSDEV is not set # CONFIG_INPUT_TSLIBDEV is not set # CONFIG_INPUT_EVDEV is not set # CONFIG_INPUT_EVBUG is not set -# CONFIG_INPUT_UINPUT is not set # # Input I/O drivers # # CONFIG_GAMEPORT is not set CONFIG_SOUND_GAMEPORT=y -# CONFIG_GAMEPORT_NS558 is not set -# CONFIG_GAMEPORT_L4 is not set -# CONFIG_GAMEPORT_EMU10K1 is not set -# CONFIG_GAMEPORT_VORTEX is not set -# CONFIG_GAMEPORT_FM801 is not set -# CONFIG_GAMEPORT_CS461x is not set -# CONFIG_SERIO is not set -# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y # CONFIG_SERIO_SERPORT is not set # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PARKBD is not set +# CONFIG_SERIO_PCIPS2 is not set # # Input Device Drivers # +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_INPORT is not set +# CONFIG_MOUSE_LOGIBM is not set +# CONFIG_MOUSE_PC110PAD is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set # # Character devices # -CONFIG_VT=y -CONFIG_VT_CONSOLE=y +# CONFIG_VT is not set # CONFIG_SERIAL_NONSTANDARD is not set # @@ -637,33 +505,12 @@ CONFIG_VT_CONSOLE=y # CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_CS is not set # CONFIG_SERIAL_8250_EXTENDED is not set -# CONFIG_SERIAL_8250_MANY_PORTS is not set -# CONFIG_SERIAL_8250_SHARE_IRQ is not set -# CONFIG_SERIAL_8250_DETECT_IRQ is not set -# CONFIG_SERIAL_8250_MULTIPORT is not set -# CONFIG_SERIAL_8250_RSA is not set # # Non-8250 serial port support # -# CONFIG_ATOMWIDE_SERIAL is not set -# CONFIG_DUALSP_SERIAL is not set -# CONFIG_SERIAL_ANAKIN is not set -# CONFIG_SERIAL_ANAKIN_CONSOLE is not set -# CONFIG_SERIAL_AMBA is not set -# CONFIG_SERIAL_AMBA_CONSOLE is not set -# CONFIG_SERIAL_CLPS711X is not set -# CONFIG_SERIAL_CLPS711X_CONSOLE is not set -# CONFIG_SERIAL_CLPS711X_OLD_NAME is not set -# CONFIG_SERIAL_21285 is not set -# CONFIG_SERIAL_21285_OLD is not set -# CONFIG_SERIAL_21285_CONSOLE is not set -# CONFIG_SERIAL_UART00 is not set -# CONFIG_SERIAL_UART00_CONSOLE is not set -# CONFIG_SERIAL_SA1100 is not set -# CONFIG_SERIAL_SA1100_CONSOLE is not set +# CONFIG_SERIAL_DZ is not set CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y @@ -671,6 +518,7 @@ CONFIG_UNIX98_PTY_COUNT=256 CONFIG_PRINTER=m # CONFIG_LP_CONSOLE is not set # CONFIG_PPDEV is not set +# CONFIG_TIPAR is not set # # I2C support @@ -678,26 +526,30 @@ CONFIG_PRINTER=m # CONFIG_I2C is not set # -# L3 serial bus support +# I2C Hardware Sensors Mainboard support # -# CONFIG_L3 is not set -# CONFIG_L3_ALGOBIT is not set -# CONFIG_L3_BIT_SA1100_GPIO is not set # -# Other L3 adapters +# I2C Hardware Sensors Chip support # -# CONFIG_L3_SA1111 is not set -# CONFIG_BIT_SA1100_GPIO is not set + +# +# L3 serial bus support +# +# CONFIG_L3 is not set # # Mice # # CONFIG_BUSMOUSE is not set -CONFIG_PSMOUSE=y # CONFIG_QIC02_TAPE is not set # +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# # Watchdog Cards # # CONFIG_WATCHDOG is not set @@ -714,6 +566,7 @@ CONFIG_RTC=y # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set # # Multimedia devices @@ -723,84 +576,83 @@ CONFIG_RTC=y # # File systems # -# CONFIG_QUOTA is not set -# CONFIG_QFMT_V1 is not set -# CONFIG_QFMT_V2 is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set -# CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y -# CONFIG_UMSDOS_FS is not set -CONFIG_VFAT_FS=y -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# CONFIG_ISO9660_FS=y CONFIG_JOLIET=y # CONFIG_ZISOFS is not set -# CONFIG_JFS_FS is not set -# CONFIG_JFS_DEBUG is not set -# CONFIG_JFS_STATISTICS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_VXFS_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y # CONFIG_NTFS_FS is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set + +# +# Pseudo filesystems +# CONFIG_PROC_FS=y CONFIG_DEVFS_FS=y CONFIG_DEVFS_MOUNT=y # CONFIG_DEVFS_DEBUG is not set # CONFIG_DEVPTS_FS is not set +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y # CONFIG_NFS_V3 is not set -# CONFIG_ROOT_NFS is not set +# CONFIG_NFS_V4 is not set # CONFIG_NFSD is not set -# CONFIG_NFSD_V3 is not set -# CONFIG_NFSD_TCP is not set -CONFIG_SUNRPC=y CONFIG_LOCKD=y # CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set # CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set # CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set -# CONFIG_ZISOFS_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set # # Partition Types @@ -817,11 +669,11 @@ CONFIG_MSDOS_PARTITION=y # CONFIG_SOLARIS_X86_PARTITION is not set # CONFIG_UNIXWARE_DISKLABEL is not set # CONFIG_LDM_PARTITION is not set +# CONFIG_NEC98_PARTITION is not set # CONFIG_SGI_PARTITION is not set # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set # CONFIG_EFI_PARTITION is not set -# CONFIG_SMB_NLS is not set CONFIG_NLS=y # @@ -867,28 +719,18 @@ CONFIG_NLS_ISO8859_1=y # CONFIG_NLS_UTF8 is not set # -# Console drivers -# -# CONFIG_VGA_CONSOLE is not set - -# -# Frame-buffer support +# Graphics support # CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -# CONFIG_FB_CLGEN is not set +# CONFIG_FB_CIRRUS is not set # CONFIG_FB_PM2 is not set -# CONFIG_FB_PM3 is not set -# CONFIG_FB_ACORN is not set -# CONFIG_FB_ANAKIN is not set -# CONFIG_FB_CLPS711X is not set -# CONFIG_FB_SA1100 is not set CONFIG_FB_CYBER2000=y +# CONFIG_FB_IMSTT is not set # CONFIG_FB_RIVA is not set # CONFIG_FB_MATROX is not set -# CONFIG_FB_ATY is not set # CONFIG_FB_RADEON is not set # CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set # CONFIG_FB_SIS is not set # CONFIG_FB_NEOMAGIC is not set # CONFIG_FB_3DFX is not set @@ -896,14 +738,11 @@ CONFIG_FB_CYBER2000=y # CONFIG_FB_TRIDENT is not set # CONFIG_FB_PM3 is not set # CONFIG_FB_VIRTUAL is not set -# CONFIG_FBCON_ADVANCED is not set -CONFIG_FBCON_CFB8=y -CONFIG_FBCON_CFB16=y -CONFIG_FBCON_CFB24=y -# CONFIG_FBCON_FONTWIDTH8_ONLY is not set -# CONFIG_FBCON_FONTS is not set -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y + +# +# Logo configuration +# +# CONFIG_LOGO is not set # # Sound @@ -911,13 +750,17 @@ CONFIG_FONT_8x16=y CONFIG_SOUND=m # +# Advanced Linux Sound Architecture +# +# CONFIG_SND is not set + +# # Open Sound System # CONFIG_SOUND_PRIME=m # CONFIG_SOUND_BT878 is not set # CONFIG_SOUND_CMPCI is not set # CONFIG_SOUND_EMU10K1 is not set -# CONFIG_MIDI_EMU10K1 is not set # CONFIG_SOUND_FUSION is not set # CONFIG_SOUND_CS4281 is not set # CONFIG_SOUND_ES1370 is not set @@ -932,7 +775,6 @@ CONFIG_SOUND_PRIME=m # CONFIG_SOUND_MSNDCLAS is not set # CONFIG_SOUND_MSNDPIN is not set # CONFIG_SOUND_VIA82CXXX is not set -# CONFIG_MIDI_VIA82CXXX is not set CONFIG_SOUND_OSS=m # CONFIG_SOUND_TRACEINIT is not set # CONFIG_SOUND_DMAP is not set @@ -950,7 +792,6 @@ CONFIG_SOUND_ADLIB=m # CONFIG_SOUND_NM256 is not set # CONFIG_SOUND_MAD16 is not set # CONFIG_SOUND_PAS is not set -# CONFIG_PAS_JOYSTICK is not set # CONFIG_SOUND_PSS is not set CONFIG_SOUND_SB=m # CONFIG_SOUND_AWE32_SYNTH is not set @@ -960,32 +801,22 @@ CONFIG_SOUND_SB=m # CONFIG_SOUND_OPL3SA1 is not set # CONFIG_SOUND_OPL3SA2 is not set # CONFIG_SOUND_YMFPCI is not set -# CONFIG_SOUND_YMFPCI_LEGACY is not set # CONFIG_SOUND_UART6850 is not set # CONFIG_SOUND_AEDSP16 is not set -# CONFIG_SOUND_WAVEARTIST is not set -# CONFIG_SOUND_TVMIXER is not set # -# Advanced Linux Sound Architecture +# Misc devices # -# CONFIG_SND is not set # # Multimedia Capabilities Port drivers # # CONFIG_MCP is not set -# CONFIG_MCP_SA1100 is not set -# CONFIG_MCP_UCB1200 is not set -# CONFIG_MCP_UCB1200_AUDIO is not set -# CONFIG_MCP_UCB1200_TS is not set # # Console Switches # # CONFIG_SWITCHES is not set -# CONFIG_SWITCHES_SA1100 is not set -# CONFIG_SWITCHES_UCB1X00 is not set # # USB support @@ -1004,24 +835,18 @@ CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y # CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_KERNEL is not set -# CONFIG_DEBUG_SLAB is not set -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_WAITQ is not set -# CONFIG_DEBUG_BUGVERBOSE is not set -# CONFIG_DEBUG_ERRORS is not set -# CONFIG_DEBUG_LL is not set -# CONFIG_DEBUG_DC21285_PORT is not set -# CONFIG_DEBUG_CLPS711X_UART2 is not set # # Security options # -CONFIG_SECURITY_CAPABILITIES=y +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set # # Library routines # CONFIG_CRC32=y -# CONFIG_ZLIB_INFLATE is not set -# CONFIG_ZLIB_DEFLATE is not set --- linux-2.5.68/arch/arm/Kconfig 2003-04-19 20:45:17.000000000 -0700 +++ 25/arch/arm/Kconfig 2003-04-29 20:50:34.000000000 -0700 @@ -445,7 +445,7 @@ config PCI VESA. If you have PCI, say Y, otherwise N. The PCI-HOWTO, available from - , contains valuable + , contains valuable information about which PCI hardware does work under Linux and which doesn't. @@ -459,7 +459,7 @@ config PCI_INTEGRATOR VESA. If you have PCI, say Y, otherwise N. The PCI-HOWTO, available from - , contains valuable + , contains valuable information about which PCI hardware does work under Linux and which doesn't. @@ -613,23 +613,30 @@ source "drivers/pcmcia/Kconfig" comment "At least one math emulation must be selected" config FPE_NWFPE - tristate "NWFPE math emulation" + bool "NWFPE math emulation" ---help--- Say Y to include the NWFPE floating point emulator in the kernel. This is necessary to run most binaries. Linux does not currently support floating point hardware so you need to say Y here even if your machine has an FPA or floating point co-processor podule. - It is also possible to say M to build the emulator as a module - (nwfpe) or indeed to leave it out altogether. However, unless you - know what you are doing this can easily render your machine - unbootable. Saying Y is the safe option. - You may say N here if you are going to load the Acorn FPEmulator early in the bootup. +config FPE_NWFPE_XP + bool "Support extended precision" + depends on FPE_NWFPE + help + Say Y to include 80-bit support in the kernel floating-point + emulator. Otherwise, only 32 and 64-bit support is compiled in. + Note that gcc does not generate 80-bit operations by default, + so in most cases this option only enlarges the size of the + floating point emulator without any good reason. + + You almost surely want to say N here. + config FPE_FASTFPE - tristate "FastFPE math emulation (EXPERIMENTAL)" + bool "FastFPE math emulation (EXPERIMENTAL)" depends on !CPU_26 && !CPU_32v3 && EXPERIMENTAL ---help--- Say Y here to include the FAST floating point emulator in the kernel. @@ -642,11 +649,6 @@ config FPE_FASTFPE If you do not feel you need a faster FP emulation you should better choose NWFPE. - It is also possible to say M to build the emulator as a module - (fastfpe). But keep in mind that you should only load the FP - emulator early in the bootup. You should never change from NWFPE to - FASTFPE or vice versa in an active system! - choice prompt "Kernel core (/proc/kcore) format" default KCORE_ELF @@ -717,7 +719,7 @@ config BINFMT_ELF want to say Y here. Information about ELF is contained in the ELF HOWTO available from - . + . If you find that after upgrading from Linux kernel 1.2 and saying Y here, you still can't run any ELF binaries (they just crash), then @@ -739,7 +741,7 @@ config BINFMT_MISC programs that need an interpreter to run like Java, Python or Emacs-Lisp. It's also useful if you often run DOS executables under the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, available from - ). Once you have + ). Once you have registered such a binary class with the kernel, you can start one of those programs simply by typing in its name at a shell prompt; Linux will automatically feed it to the correct interpreter. @@ -770,7 +772,7 @@ config PM page on the WWW at and the Battery Powered Linux mini-HOWTO, available from - . + . Note that, even if you say N here, Linux on the x86 architecture will issue the hlt instruction if nothing is to be done, thereby @@ -809,7 +811,7 @@ config APM In order to use APM, you will need supporting software. For location and more information, read and the Battery Powered Linux mini-HOWTO, available from - . + . This driver does not spin down disk drives (see the hdparm(8) manpage ("man 8 hdparm") for that), and it doesn't turn off @@ -1063,7 +1065,7 @@ config SOUND interrupt and DMA channel), because you will be asked for it. You want to read the Sound-HOWTO, available from - . General information about + . General information about the modular sound system is contained in the files . The file contains some slightly --- linux-2.5.68/arch/arm/kernel/entry-armv.S 2003-04-19 20:45:17.000000000 -0700 +++ 25/arch/arm/kernel/entry-armv.S 2003-04-29 20:50:34.000000000 -0700 @@ -1093,8 +1093,10 @@ vector_data: @ @ @ now branch to the relevant MODE handling routine @ - mov r13, #PSR_I_BIT | MODE_SVC - msr spsr_c, r13 @ switch to SVC_32 mode + mrs r13, cpsr + bic r13, r13, #MODE_MASK + orr r13, r13, #MODE_SVC + msr spsr, r13 @ switch to SVC_32 mode and lr, lr, #15 ldr lr, [pc, lr, lsl #2] @@ -1135,8 +1137,10 @@ vector_prefetch: @ @ now branch to the relevant MODE handling routine @ - mov r13, #PSR_I_BIT | MODE_SVC - msr spsr_c, r13 @ switch to SVC_32 mode + mrs r13, cpsr + bic r13, r13, #MODE_MASK + orr r13, r13, #MODE_SVC + msr spsr, r13 @ switch to SVC_32 mode ands lr, lr, #15 ldr lr, [pc, lr, lsl #2] @@ -1176,8 +1180,10 @@ vector_undefinstr: @ @ now branch to the relevant MODE handling routine @ - mov r13, #PSR_I_BIT | MODE_SVC - msr spsr_c, r13 @ switch to SVC_32 mode + mrs r13, cpsr + bic r13, r13, #MODE_MASK + orr r13, r13, #MODE_SVC + msr spsr, r13 @ switch to SVC_32 mode and lr, lr, #15 ldr lr, [pc, lr, lsl #2] --- linux-2.5.68/arch/arm/kernel/process.c 2003-04-19 20:45:17.000000000 -0700 +++ 25/arch/arm/kernel/process.c 2003-04-29 20:50:34.000000000 -0700 @@ -2,7 +2,7 @@ * linux/arch/arm/kernel/process.c * * Copyright (C) 1996-2000 Russell King - Converted to ARM. - * Origional Copyright (C) 1995 Linus Torvalds + * Original Copyright (C) 1995 Linus Torvalds * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -418,7 +418,7 @@ unsigned long get_wchan(struct task_stru if (!p || p == current || p->state == TASK_RUNNING) return 0; - stack_page = 4096 + (unsigned long)p; + stack_page = 4096 + (unsigned long)p->thread_info; fp = thread_saved_fp(p); do { if (fp < stack_page || fp > 4092+stack_page) --- linux-2.5.68/arch/arm/kernel/setup.c 2003-04-19 20:45:17.000000000 -0700 +++ 25/arch/arm/kernel/setup.c 2003-04-29 20:50:34.000000000 -0700 @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include @@ -74,6 +74,9 @@ struct cpu_tlb_fns cpu_tlb; #ifdef MULTI_USER struct cpu_user_fns cpu_user; #endif +#ifdef MULTI_CACHE +struct cpu_cache_fns cpu_cache; +#endif unsigned char aux_device_present; char elf_platform[ELF_PLATFORM_SIZE]; @@ -282,6 +285,9 @@ static void __init setup_processor(void) #ifdef MULTI_USER cpu_user = *list->user; #endif +#ifdef MULTI_CACHE + cpu_cache = *list->cache; +#endif printk("CPU: %s [%08x] revision %d (ARMv%s)\n", cpu_name, processor_id, (int)processor_id & 15, @@ -323,58 +329,77 @@ static struct machine_desc * __init setu return list; } +static void __init early_initrd(char **p) +{ + unsigned long start, size; + + start = memparse(*p, p); + if (**p == ',') { + size = memparse((*p) + 1, p); + + phys_initrd_start = start; + phys_initrd_size = size; + } +} +__early_param("initrd=", early_initrd); + /* - * Initial parsing of the command line. We need to pick out the - * memory size. We look for mem=size@start, where start and size - * are "size[KkMm]" + * Pick out the memory size. We look for mem=size@start, + * where start and size are "size[KkMm]" */ -static void __init -parse_cmdline(struct meminfo *mi, char **cmdline_p, char *from) +static void __init early_mem(char **p) { - char c = ' ', *to = command_line; - int usermem = 0, len = 0; - - for (;;) { - if (c == ' ' && !memcmp(from, "mem=", 4)) { - unsigned long size, start; + static int usermem __initdata = 0; + unsigned long size, start; - if (to != command_line) - to -= 1; + /* + * If the user specifies memory size, we + * blow away any automatically generated + * size. + */ + if (usermem == 0) { + usermem = 1; + meminfo.nr_banks = 0; + } - /* - * If the user specifies memory size, we - * blow away any automatically generated - * size. - */ - if (usermem == 0) { - usermem = 1; - mi->nr_banks = 0; - } + start = PHYS_OFFSET; + size = memparse(*p, p); + if (**p == '@') + start = memparse(*p + 1, p); + + meminfo.bank[meminfo.nr_banks].start = start; + meminfo.bank[meminfo.nr_banks].size = size; + meminfo.bank[meminfo.nr_banks].node = PHYS_TO_NID(start); + meminfo.nr_banks += 1; +} +__early_param("mem=", early_mem); - start = PHYS_OFFSET; - size = memparse(from + 4, &from); - if (*from == '@') - start = memparse(from + 1, &from); - - mi->bank[mi->nr_banks].start = start; - mi->bank[mi->nr_banks].size = size; - mi->bank[mi->nr_banks].node = PHYS_TO_NID(start); - mi->nr_banks += 1; - } else if (c == ' ' && !memcmp(from, "initrd=", 7)) { - unsigned long start, size; - - /* - * Remove space character - */ - if (to != command_line) - to -= 1; - - start = memparse(from + 7, &from); - if (*from == ',') { - size = memparse(from + 1, &from); +/* + * Initial parsing of the command line. + */ +static void __init parse_cmdline(char **cmdline_p, char *from) +{ + char c = ' ', *to = command_line; + int len = 0; - phys_initrd_start = start; - phys_initrd_size = size; + for (;;) { + if (c == ' ') { + extern struct early_params __early_begin, __early_end; + struct early_params *p; + + for (p = &__early_begin; p < &__early_end; p++) { + int len = strlen(p->arg); + + if (memcmp(from, p->arg, len) == 0) { + if (to != command_line) + to -= 1; + from += len; + p->fn(&from); + + while (*from != ' ' && *from != '\0') + from++; + break; + } } } c = *from++; @@ -536,6 +561,8 @@ __tagtable(ATAG_RAMDISK, parse_tag_ramdi static int __init parse_tag_initrd(const struct tag *tag) { + printk(KERN_WARNING "ATAG_INITRD is deprecated; " + "please update your bootloader.\n"); phys_initrd_start = __virt_to_phys(tag->u.initrd.start); phys_initrd_size = tag->u.initrd.size; return 0; @@ -668,7 +695,7 @@ void __init setup_arch(char **cmdline_p) memcpy(saved_command_line, from, COMMAND_LINE_SIZE); saved_command_line[COMMAND_LINE_SIZE-1] = '\0'; - parse_cmdline(&meminfo, cmdline_p, from); + parse_cmdline(cmdline_p, from); bootmem_init(&meminfo); paging_init(&meminfo, mdesc); request_standard_resources(&meminfo, mdesc); --- linux-2.5.68/arch/arm/kernel/signal.c 2003-04-19 20:45:17.000000000 -0700 +++ 25/arch/arm/kernel/signal.c 2003-04-29 20:50:34.000000000 -0700 @@ -362,8 +362,8 @@ setup_return(struct pt_regs *regs, struc * Ensure that the instruction cache sees * the return code written onto the stack. */ - cpu_icache_invalidate_range((unsigned long)rc, - (unsigned long)(rc + 1)); + flush_icache_range((unsigned long)rc, + (unsigned long)(rc + 1)); retcode = ((unsigned long)rc) + thumb; } @@ -570,6 +570,9 @@ static int do_signal(sigset_t *oldset, s /* ldr pc, [sp], #12 */ put_user(0xe49df00c, &usp[2]); + flush_icache_range((unsigned long)usp, + (unsigned long)(usp + 3)); + regs->ARM_pc = regs->ARM_sp + 4; } } --- linux-2.5.68/arch/arm/mach-clps711x/fortunet.c 2003-01-16 18:22:21.000000000 -0800 +++ 25/arch/arm/mach-clps711x/fortunet.c 2003-04-29 20:50:34.000000000 -0700 @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include --- linux-2.5.68/arch/arm/mach-integrator/cpu.c 2003-03-17 14:56:00.000000000 -0800 +++ 25/arch/arm/mach-integrator/cpu.c 2003-04-29 20:50:34.000000000 -0700 @@ -12,6 +12,7 @@ * CPU support functions */ #include +#include #include #include #include @@ -173,9 +174,9 @@ static int integrator_set_target(struct return 0; } -static int integrator_cpufreq_init(struct cpufreq *policy) +static int integrator_cpufreq_init(struct cpufreq_policy *policy) { - unsigned long cus_allowed; + unsigned long cpus_allowed; unsigned int cpu = policy->cpu; u_int cm_osc, cm_stat, mem_freq_khz; struct vco vco; --- linux-2.5.68/arch/arm/mach-integrator/irq.c 2003-01-16 18:22:59.000000000 -0800 +++ 25/arch/arm/mach-integrator/irq.c 2003-04-29 20:50:34.000000000 -0700 @@ -18,6 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include +#include #include #include --- linux-2.5.68/arch/arm/mach-iop3xx/iop321-pci.c 2003-04-19 20:45:17.000000000 -0700 +++ 25/arch/arm/mach-iop3xx/iop321-pci.c 2003-04-29 20:50:34.000000000 -0700 @@ -212,13 +212,13 @@ int iop321_setup(int nr, struct pci_sys_ switch (nr) { case 0: - res[0].start = IOP321_PCI_LOWER_IO + 0x6e000000; - res[0].end = IOP321_PCI_LOWER_IO + 0x6e00ffff; + res[0].start = IOP321_PCI_IO_BASE + 0x6e000000; + res[0].end = IOP321_PCI_IO_BASE + IOP321_PCI_IO_SIZE-1 + 0x6e000000; res[0].name = "PCI IO Primary"; res[0].flags = IORESOURCE_IO; - res[1].start = IOP321_PCI_LOWER_MEM; - res[1].end = IOP321_PCI_LOWER_MEM + IOP321_PCI_WINDOW_SIZE; + res[1].start = IOP321_PCI_MEM_BASE; + res[1].end = IOP321_PCI_MEM_BASE + IOP321_PCI_MEM_SIZE; res[1].name = "PCI Memory Primary"; res[1].flags = IORESOURCE_MEM; break; --- linux-2.5.68/arch/arm/mach-iop3xx/iq80310-time.c 2003-04-19 20:45:17.000000000 -0700 +++ 25/arch/arm/mach-iop3xx/iq80310-time.c 2003-04-29 20:50:34.000000000 -0700 @@ -101,7 +101,7 @@ static void iq80310_timer_interrupt(int * * Since the timer interrupt is cascaded through the CPLD and * the 80312 and the demux code calls do_IRQ, the irq count is - * going to be atleast 2 when we get here and this will cause the + * going to be at least 2 when we get here and this will cause the * kernel to increment the system tick counter even if we're * idle. This causes it to look like there's always 100% system * time, which is not the case. To get around it, we just decrement --- linux-2.5.68/arch/arm/mach-iop3xx/mm-321.c 2003-04-19 20:45:17.000000000 -0700 +++ 25/arch/arm/mach-iop3xx/mm-321.c 2003-04-29 20:50:34.000000000 -0700 @@ -1,7 +1,7 @@ /* * linux/arch/arm/mach-iop3xx/mm.c * - * Low level memory intialization for IOP321 based systems + * Low level memory initialization for IOP321 based systems * * Author: Rory Bolt * Copyright (C) 2002 Rory Bolt @@ -31,7 +31,7 @@ static struct map_desc iop80321_std_desc /* virtual physical length type */ /* mem mapped registers */ - { 0xfff00000, 0xffffe000, 0x00002000, MT_DEVICE }, + { IOP321_VIRT_MEM_BASE, IOP321_PHY_MEM_BASE, 0x00002000, MT_DEVICE }, /* PCI IO space */ { 0xfe000000, 0x90000000, 0x00020000, MT_DEVICE } @@ -52,7 +52,7 @@ static struct map_desc iq80321_io_desc[] /* virtual physical length type */ /* on-board devices */ - { 0xfe800000, 0xfe800000, 0x00100000, MT_DEVICE } + { 0xfe800000, IQ80321_UART1, 0x00100000, MT_DEVICE } }; void __init iq80321_map_io(void) --- linux-2.5.68/arch/arm/mach-pxa/generic.c 2003-03-04 20:02:35.000000000 -0800 +++ 25/arch/arm/mach-pxa/generic.c 2003-04-29 20:50:34.000000000 -0700 @@ -13,7 +13,7 @@ * * Since this file should be linked before any other machine specific file, * the __initcall() here will be executed first. This serves as default - * initialization stuff for PXA machines which can be overriden later if + * initialization stuff for PXA machines which can be overridden later if * need be. */ #include --- linux-2.5.68/arch/arm/mach-pxa/sleep.S 2003-01-16 18:22:42.000000000 -0800 +++ 25/arch/arm/mach-pxa/sleep.S 2003-04-29 20:50:34.000000000 -0700 @@ -95,7 +95,7 @@ ENTRY(pxa_cpu_suspend) * This is to allow sleep_save_sp to be accessed with a relative load * while we can't rely on any MMU translation. We could have put * sleep_save_sp in the .text section as well, but some setups might - * insist on it to be truely read-only. + * insist on it to be truly read-only. */ .data --- linux-2.5.68/arch/arm/mach-sa1100/assabet.c 2003-04-07 13:06:52.000000000 -0700 +++ 25/arch/arm/mach-sa1100/assabet.c 2003-04-29 20:50:34.000000000 -0700 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -25,6 +26,7 @@ #include #include #include +#include #include #include --- linux-2.5.68/arch/arm/mach-sa1100/h3600.c 2003-01-16 18:21:44.000000000 -0800 +++ 25/arch/arm/mach-sa1100/h3600.c 2003-04-29 20:50:34.000000000 -0700 @@ -51,12 +51,6 @@ struct ipaq_model_ops ipaq_model_ops; EXPORT_SYMBOL(ipaq_model_ops); -static void msleep(unsigned int msec) -{ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout((msec * HZ + 999) / 1000); -} - /* * low-level UART features */ --- linux-2.5.68/arch/arm/mach-sa1100/sleep.S 2003-01-16 18:22:29.000000000 -0800 +++ 25/arch/arm/mach-sa1100/sleep.S 2003-04-29 20:50:34.000000000 -0700 @@ -54,7 +54,7 @@ ENTRY(sa1100_cpu_suspend) str r0, [r1] @ clean data cache and invalidate WB - bl cpu_sa1100_cache_clean_invalidate_all + bl v4wb_flush_kern_cache_all @ disable clock switching mcr p15, 0, r1, c15, c2, 2 @@ -171,7 +171,7 @@ sa1110_sdram_controller_fix: * This is to allow sleep_save_sp to be accessed with a relative load * while we can't rely on any MMU translation. We could have put * sleep_save_sp in the .text section as well, but some setups might - * insist on it to be truely read-only. + * insist on it to be truly read-only. */ .data --- linux-2.5.68/arch/arm/Makefile 2003-04-19 20:45:17.000000000 -0700 +++ 25/arch/arm/Makefile 2003-04-29 20:50:34.000000000 -0700 @@ -31,13 +31,15 @@ apcs-$(CONFIG_CPU_32) :=-mapcs-32 apcs-$(CONFIG_CPU_26) :=-mapcs-26 -mcpu=arm3 # This selects which instruction set is used. -# Note that GCC is lame - it doesn't numerically define an -# architecture version macro, but instead defines a whole -# series of macros. -arch-$(CONFIG_CPU_32v3) :=-D__LINUX_ARM_ARCH__=3 -march=armv3 +# Note that GCC does not numerically define an architecture version +# macro, but instead defines a whole series of macros which makes +# testing for a specific architecture or later rather impossible. +# +# Note - GCC does accept -march=armv5te, but someone messed up the assembler or the +# gcc specs file - this needs fixing properly - ie in gcc and/or binutils. +arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 -march=armv5t arch-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4 -march=armv4 -arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 -march=armv5te -arch-$(CONFIG_CPU_XSCALE) :=-D__LINUX_ARM_ARCH__=5 -march=armv4 -Wa,-mxscale #-march=armv5te +arch-$(CONFIG_CPU_32v3) :=-D__LINUX_ARM_ARCH__=3 -march=armv3 # This selects how we optimise for the processor. tune-$(CONFIG_CPU_ARM610) :=-mtune=arm610 @@ -48,13 +50,13 @@ tune-$(CONFIG_CPU_ARM922T) :=-mtune=arm9 tune-$(CONFIG_CPU_ARM926T) :=-mtune=arm9tdmi tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110 tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100 -tune-$(CONFIG_CPU_XSCALE) :=-mtune=strongarm #-mtune=xscale +tune-$(CONFIG_CPU_XSCALE) :=-mtune=strongarm -Wa,-mxscale #-mtune=xscale # Force -mno-fpu to be passed to the assembler. Some versions of gcc don't # do this with -msoft-float CFLAGS_BOOT :=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Wa,-mno-fpu -Uarm CFLAGS +=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Wa,-mno-fpu -Uarm -AFLAGS +=$(apcs-y) $(arch-y) -mno-fpu -msoft-float -Wa,-mno-fpu +AFLAGS +=$(apcs-y) $(arch-y) $(tune-y) -mno-fpu -msoft-float -Wa,-mno-fpu #Default value DATAADDR := . @@ -208,6 +210,7 @@ zi:; $(Q)$(MAKE) $(build)=$(boot) zinsta ) arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \ + include/asm-arm/.arch include/asm-arm/.proc \ include/config/MARKER include/asm-$(ARCH)/constants.h: arch/$(ARCH)/kernel/asm-offsets.s --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25/arch/arm/mm/cache-v3.S 2003-04-29 20:50:34.000000000 -0700 @@ -0,0 +1,118 @@ +/* + * linux/arch/arm/mm/cache-v3.S + * + * Copyright (C) 1997-2002 Russell king + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include "proc-macros.S" + +/* + * flush_user_cache_all() + * + * Invalidate all cache entries in a particular address + * space. + * + * - mm - mm_struct describing address space + */ +ENTRY(v3_flush_user_cache_all) + /* FALLTHROUGH */ +/* + * flush_kern_cache_all() + * + * Clean and invalidate the entire cache. + */ +ENTRY(v3_flush_kern_cache_all) + /* FALLTHROUGH */ + +/* + * flush_user_cache_range(start, end, vm_flags) + * + * Invalidate a range of cache entries in the specified + * address space. + * + * - start - start address (may not be aligned) + * - end - end address (exclusive, may not be aligned) + * - vma - vma_area_struct describing address space + */ +ENTRY(v3_flush_user_cache_range) + mov ip, #0 + mcreq p15, 0, ip, c7, c0, 0 @ flush ID cache + mov pc, lr + +/* + * coherent_kern_range(start, end) + * + * Ensure coherency between the Icache and the Dcache in the + * region described by start. If you have non-snooping + * Harvard caches, you need to implement this function. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(v3_coherent_kern_range) + mov pc, lr + +/* + * flush_kern_dcache_page(void *page) + * + * Ensure no D cache aliasing occurs, either with itself or + * the I cache + * + * - addr - page aligned address + */ +ENTRY(v3_flush_kern_dcache_page) + /* FALLTHROUGH */ + +/* + * dma_inv_range(start, end) + * + * Invalidate (discard) the specified virtual address range. + * May not write back any entries. If 'start' or 'end' + * are not cache line aligned, those lines must be written + * back. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(v3_dma_inv_range) + /* FALLTHROUGH */ + +/* + * dma_flush_range(start, end) + * + * Clean and invalidate the specified virtual address range. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(v3_dma_flush_range) + mov r0, #0 + mcr p15, 0, r0, c7, c0, 0 @ flush ID cache + /* FALLTHROUGH */ + +/* + * dma_clean_range(start, end) + * + * Clean (write back) the specified virtual address range. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(v3_dma_clean_range) + mov pc, lr + +ENTRY(v3_cache_fns) + .long v3_flush_kern_cache_all + .long v3_flush_user_cache_all + .long v3_flush_user_cache_range + .long v3_coherent_kern_range + .long v3_flush_kern_dcache_page + .long v3_dma_inv_range + .long v3_dma_clean_range + .long v3_dma_flush_range --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25/arch/arm/mm/cache-v4.S 2003-04-29 20:50:34.000000000 -0700 @@ -0,0 +1,120 @@ +/* + * linux/arch/arm/mm/cache-v4.S + * + * Copyright (C) 1997-2002 Russell king + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include "proc-macros.S" + +/* + * flush_user_cache_all() + * + * Invalidate all cache entries in a particular address + * space. + * + * - mm - mm_struct describing address space + */ +ENTRY(v4_flush_user_cache_all) + /* FALLTHROUGH */ +/* + * flush_kern_cache_all() + * + * Clean and invalidate the entire cache. + */ +ENTRY(v4_flush_kern_cache_all) + mov r0, #0 + mcr p15, 0, r0, c7, c7, 0 @ flush ID cache + mov pc, lr + +/* + * flush_user_cache_range(start, end, vma) + * + * Invalidate a range of cache entries in the specified + * address space. + * + * - start - start address (may not be aligned) + * - end - end address (exclusive, may not be aligned) + * - vma - vma_area_struct describing address space + */ +ENTRY(v4_flush_user_cache_range) + mov ip, #0 + mcreq p15, 0, ip, c7, c7, 0 @ flush ID cache + mov pc, lr + +/* + * coherent_kern_range(start, end) + * + * Ensure coherency between the Icache and the Dcache in the + * region described by start. If you have non-snooping + * Harvard caches, you need to implement this function. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(v4_coherent_kern_range) + mov pc, lr + +/* + * flush_kern_dcache_page(void *page) + * + * Ensure no D cache aliasing occurs, either with itself or + * the I cache + * + * - addr - page aligned address + */ +ENTRY(v4_flush_kern_dcache_page) + /* FALLTHROUGH */ + +/* + * dma_inv_range(start, end) + * + * Invalidate (discard) the specified virtual address range. + * May not write back any entries. If 'start' or 'end' + * are not cache line aligned, those lines must be written + * back. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(v4_dma_inv_range) + /* FALLTHROUGH */ + +/* + * dma_flush_range(start, end) + * + * Clean and invalidate the specified virtual address range. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(v4_dma_flush_range) + mov r0, #0 + mcr p15, 0, r0, c7, c7, 0 @ flush ID cache + /* FALLTHROUGH */ + +/* + * dma_clean_range(start, end) + * + * Clean (write back) the specified virtual address range. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(v4_dma_clean_range) + mov pc, lr + +ENTRY(v4_cache_fns) + .long v4_flush_kern_cache_all + .long v4_flush_user_cache_all + .long v4_flush_user_cache_range + .long v4_coherent_kern_range + .long v4_flush_kern_dcache_page + .long v4_dma_inv_range + .long v4_dma_clean_range + .long v4_dma_flush_range --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25/arch/arm/mm/cache-v4wb.S 2003-04-29 20:50:34.000000000 -0700 @@ -0,0 +1,196 @@ +/* + * linux/arch/arm/mm/cache-v4wb.S + * + * Copyright (C) 1997-2002 Russell king + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include "proc-macros.S" + +/* + * The size of one data cache line. + */ +#define CACHE_DLINESIZE 32 + +/* + * The total size of the data cache. + */ +#if defined(CONFIG_CPU_SA110) +# define CACHE_DSIZE 16384 +#elif defined(CONFIG_CPU_SA1100) +# define CACHE_DSIZE 8192 +#else +# error Unknown cache size +#endif + +/* + * This is the size at which it becomes more efficient to + * clean the whole cache, rather than using the individual + * cache line maintainence instructions. + * + * Size Clean (ticks) Dirty (ticks) + * 4096 21 20 21 53 55 54 + * 8192 40 41 40 106 100 102 + * 16384 77 77 76 140 140 138 + * 32768 150 149 150 214 216 212 <--- + * 65536 296 297 296 351 358 361 + * 131072 591 591 591 656 657 651 + * Whole 132 136 132 221 217 207 <--- + */ +#define CACHE_DLIMIT (CACHE_DSIZE * 4) + +/* + * flush_user_cache_all() + * + * Clean and invalidate all cache entries in a particular address + * space. + */ +ENTRY(v4wb_flush_user_cache_all) + /* FALLTHROUGH */ +/* + * flush_kern_cache_all() + * + * Clean and invalidate the entire cache. + */ +ENTRY(v4wb_flush_kern_cache_all) + mov ip, #0 + mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache +__flush_whole_cache: + mov r0, #FLUSH_BASE + add r1, r0, #CACHE_DSIZE +1: ldr r2, [r0], #32 + cmp r0, r1 + blo 1b + mcr p15, 0, ip, c7, c10, 4 @ drain write buffer + mov pc, lr + +/* + * flush_user_cache_range(start, end, vm_flags) + * + * Invalidate a range of cache entries in the specified + * address space. + * + * - start - start address (inclusive, page aligned) + * - end - end address (exclusive, page aligned) + * - vma - vma_area_struct describing address space + */ +ENTRY(v4wb_flush_user_cache_range) + sub r3, r1, r0 @ calculate total size + tst r2, #VM_EXEC @ executable region? + mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache + + cmp r3, #CACHE_DLIMIT @ total size >= limit? + bhs __flush_whole_cache @ flush whole D cache + +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + tst r2, #VM_EXEC + mcrne p15, 0, ip, c7, c10, 4 @ drain write buffer + mov pc, lr + +/* + * flush_kern_dcache_page(void *page) + * + * Ensure no D cache aliasing occurs, either with itself or + * the I cache + * + * - addr - page aligned address + */ +ENTRY(v4wb_flush_kern_dcache_page) + add r1, r0, #PAGE_SZ + /* fall through */ + +/* + * coherent_kern_range(start, end) + * + * Ensure coherency between the Icache and the Dcache in the + * region described by start. If you have non-snooping + * Harvard caches, you need to implement this function. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(v4wb_coherent_kern_range) + bic r0, r0, #CACHE_DLINESIZE - 1 +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + mov ip, #0 + mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache + mcr p15, 0, ip, c7, c10, 4 @ drain WB + mov pc, lr + + +/* + * dma_inv_range(start, end) + * + * Invalidate (discard) the specified virtual address range. + * May not write back any entries. If 'start' or 'end' + * are not cache line aligned, those lines must be written + * back. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(v4wb_dma_inv_range) + tst r0, #CACHE_DLINESIZE - 1 + bic r0, r0, #CACHE_DLINESIZE - 1 + mcrne p15, 0, r0, c7, c10, 1 @ clean D entry + tst r1, #CACHE_DLINESIZE - 1 + mcrne p15, 0, r1, c7, c10, 1 @ clean D entry +1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer + mov pc, lr + +/* + * dma_clean_range(start, end) + * + * Clean (write back) the specified virtual address range. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(v4wb_dma_clean_range) + bic r0, r0, #CACHE_DLINESIZE - 1 +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer + mov pc, lr + +/* + * dma_flush_range(start, end) + * + * Clean and invalidate the specified virtual address range. + * + * - start - virtual start address + * - end - virtual end address + * + * This is actually the same as v4wb_coherent_kern_range() + */ + .globl v4wb_dma_flush_range + .set v4wb_dma_flush_range, v4wb_coherent_kern_range + +ENTRY(v4wb_cache_fns) + .long v4wb_flush_kern_cache_all + .long v4wb_flush_user_cache_all + .long v4wb_flush_user_cache_range + .long v4wb_coherent_kern_range + .long v4wb_flush_kern_dcache_page + .long v4wb_dma_inv_range + .long v4wb_dma_clean_range + .long v4wb_dma_flush_range --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25/arch/arm/mm/cache-v4wt.S 2003-04-29 20:50:34.000000000 -0700 @@ -0,0 +1,170 @@ +/* + * linux/arch/arm/mm/cache-v4wt.S + * + * Copyright (C) 1997-2002 Russell king + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ARMv4 write through cache operations support. + * + * We assume that the write buffer is not enabled. + */ +#include +#include +#include +#include "proc-macros.S" + +/* + * The size of one data cache line. + */ +#define CACHE_DLINESIZE 32 + +/* + * The number of data cache segments. + */ +#define CACHE_DSEGMENTS 8 + +/* + * The number of lines in a cache segment. + */ +#define CACHE_DENTRIES 64 + +/* + * This is the size at which it becomes more efficient to + * clean the whole cache, rather than using the individual + * cache line maintainence instructions. + * + * *** This needs benchmarking + */ +#define CACHE_DLIMIT 16384 + +/* + * flush_user_cache_all() + * + * Invalidate all cache entries in a particular address + * space. + */ +ENTRY(v4wt_flush_user_cache_all) + /* FALLTHROUGH */ +/* + * flush_kern_cache_all() + * + * Clean and invalidate the entire cache. + */ +ENTRY(v4wt_flush_kern_cache_all) + mov r2, #VM_EXEC + mov ip, #0 +__flush_whole_cache: + tst r2, #VM_EXEC + mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache + mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache + mov pc, lr + +/* + * flush_user_cache_range(start, end, vm_flags) + * + * Clean and invalidate a range of cache entries in the specified + * address space. + * + * - start - start address (inclusive, page aligned) + * - end - end address (exclusive, page aligned) + * - vma - vma_area_struct describing address space + */ +ENTRY(v4wt_flush_user_cache_range) + sub r3, r1, r0 @ calculate total size + cmp r3, #CACHE_DLIMIT + bhs __flush_whole_cache + +1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry + tst r2, #VM_EXEC + mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + mov pc, lr + +/* + * coherent_kern_range(start, end) + * + * Ensure coherency between the Icache and the Dcache in the + * region described by start. If you have non-snooping + * Harvard caches, you need to implement this function. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(v4wt_coherent_kern_range) + bic r0, r0, #CACHE_DLINESIZE - 1 +1: mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + mov pc, lr + +/* + * flush_kern_dcache_page(void *page) + * + * Ensure no D cache aliasing occurs, either with itself or + * the I cache + * + * - addr - page aligned address + */ +ENTRY(v4wt_flush_kern_dcache_page) + mov r2, #0 + mcr p15, 0, r2, c7, c5, 0 @ invalidate I cache + add r1, r0, #PAGE_SZ + /* fallthrough */ + +/* + * dma_inv_range(start, end) + * + * Invalidate (discard) the specified virtual address range. + * May not write back any entries. If 'start' or 'end' + * are not cache line aligned, those lines must be written + * back. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(v4wt_dma_inv_range) + bic r0, r0, #CACHE_DLINESIZE - 1 +1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + /* FALLTHROUGH */ + +/* + * dma_clean_range(start, end) + * + * Clean the specified virtual address range. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(v4wt_dma_clean_range) + mov pc, lr + +/* + * dma_flush_range(start, end) + * + * Clean and invalidate the specified virtual address range. + * + * - start - virtual start address + * - end - virtual end address + */ + .globl v4wt_dma_flush_range + .equ v4wt_dma_flush_range, v4wt_dma_inv_range + +ENTRY(v4wt_cache_fns) + .long v4wt_flush_kern_cache_all + .long v4wt_flush_user_cache_all + .long v4wt_flush_user_cache_range + .long v4wt_coherent_kern_range + .long v4wt_flush_kern_dcache_page + .long v4wt_dma_inv_range + .long v4wt_dma_clean_range + .long v4wt_dma_flush_range + --- linux-2.5.68/arch/arm/mm/consistent.c 2003-02-17 16:21:14.000000000 -0800 +++ 25/arch/arm/mm/consistent.c 2003-04-29 20:50:34.000000000 -0700 @@ -161,11 +161,11 @@ void *consistent_alloc(int gfp, size_t s /* * Invalidate any data that might be lurking in the - * kernel direct-mapped region. + * kernel direct-mapped region for device DMA. */ { unsigned long kaddr = (unsigned long)page_address(page); - invalidate_dcache_range(kaddr, kaddr + size); + dmac_inv_range(kaddr, kaddr + size); } /* @@ -330,7 +330,7 @@ static int __init consistent_init(void) core_initcall(consistent_init); /* - * make an area consistent. + * make an area consistent for devices. */ void consistent_sync(void *vaddr, size_t size, int direction) { @@ -339,13 +339,13 @@ void consistent_sync(void *vaddr, size_t switch (direction) { case DMA_FROM_DEVICE: /* invalidate only */ - invalidate_dcache_range(start, end); + dmac_inv_range(start, end); break; case DMA_TO_DEVICE: /* writeback only */ - clean_dcache_range(start, end); + dmac_clean_range(start, end); break; case DMA_BIDIRECTIONAL: /* writeback and invalidate */ - flush_dcache_range(start, end); + dmac_flush_range(start, end); break; default: BUG(); --- linux-2.5.68/arch/arm/mm/discontig.c 2003-01-16 18:22:40.000000000 -0800 +++ 25/arch/arm/mm/discontig.c 2003-04-29 20:50:34.000000000 -0700 @@ -20,7 +20,7 @@ #endif /* - * Our node_data structure for discontigous memory. + * Our node_data structure for discontiguous memory. */ static bootmem_data_t node_bootmem_data[NR_NODES]; --- linux-2.5.68/arch/arm/mm/fault-armv.c 2003-01-16 18:21:45.000000000 -0800 +++ 25/arch/arm/mm/fault-armv.c 2003-04-29 20:50:34.000000000 -0700 @@ -184,9 +184,8 @@ void __flush_dcache_page(struct page *pa { struct mm_struct *mm = current->active_mm; struct list_head *l; - unsigned long kaddr = (unsigned long)page_address(page); - cpu_cache_clean_invalidate_range(kaddr, kaddr + PAGE_SIZE, 0); + __cpuc_flush_dcache_page(page_address(page)); if (!page->mapping) return; @@ -291,10 +290,9 @@ void update_mmu_cache(struct vm_area_str page = pfn_to_page(pfn); if (page->mapping) { int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags); - unsigned long kaddr = (unsigned long)page_address(page); if (dirty) - cpu_cache_clean_invalidate_range(kaddr, kaddr + PAGE_SIZE, 0); + __cpuc_flush_dcache_page(page_address(page)); make_coherent(vma, addr, page, dirty); } --- linux-2.5.68/arch/arm/mm/fault-common.c 2003-04-19 20:45:17.000000000 -0700 +++ 25/arch/arm/mm/fault-common.c 2003-04-29 20:50:34.000000000 -0700 @@ -12,19 +12,15 @@ #include #include #include -#include -#include #include -#include #include -#include #include #include -#include #include #include #include +#include #include #include "fault.h" --- linux-2.5.68/arch/arm/mm/init.c 2003-01-16 18:21:38.000000000 -0800 +++ 25/arch/arm/mm/init.c 2003-04-29 20:50:34.000000000 -0700 @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include --- linux-2.5.68/arch/arm/mm/Makefile 2003-02-10 12:24:11.000000000 -0800 +++ 25/arch/arm/mm/Makefile 2003-04-29 20:50:34.000000000 -0700 @@ -20,16 +20,16 @@ obj-$(CONFIG_DISCONTIGMEM) += discontig. p-$(CONFIG_CPU_26) += proc-arm2_3.o # ARMv3 -p-$(CONFIG_CPU_ARM610) += proc-arm6_7.o tlb-v3.o copypage-v3.o -p-$(CONFIG_CPU_ARM710) += proc-arm6_7.o tlb-v3.o copypage-v3.o +p-$(CONFIG_CPU_ARM610) += proc-arm6_7.o tlb-v3.o cache-v3.o copypage-v3.o +p-$(CONFIG_CPU_ARM710) += proc-arm6_7.o tlb-v3.o cache-v3.o copypage-v3.o # ARMv4 -p-$(CONFIG_CPU_ARM720T) += proc-arm720.o tlb-v4.o copypage-v4wt.o abort-lv4t.o -p-$(CONFIG_CPU_ARM920T) += proc-arm920.o tlb-v4wbi.o copypage-v4wb.o abort-ev4t.o -p-$(CONFIG_CPU_ARM922T) += proc-arm922.o tlb-v4wbi.o copypage-v4wb.o abort-ev4t.o -p-$(CONFIG_CPU_ARM1020) += proc-arm1020.o tlb-v4wbi.o copypage-v4wb.o abort-ev4t.o -p-$(CONFIG_CPU_SA110) += proc-sa110.o tlb-v4wb.o copypage-v4wb.o abort-ev4.o minicache.o -p-$(CONFIG_CPU_SA1100) += proc-sa110.o tlb-v4wb.o copypage-v4mc.o abort-ev4.o minicache.o +p-$(CONFIG_CPU_ARM720T) += proc-arm720.o tlb-v4.o cache-v4.o copypage-v4wt.o abort-lv4t.o +p-$(CONFIG_CPU_ARM920T) += proc-arm920.o tlb-v4wbi.o cache-v4wt.o copypage-v4wb.o abort-ev4t.o +p-$(CONFIG_CPU_ARM922T) += proc-arm922.o tlb-v4wbi.o cache-v4wt.o copypage-v4wb.o abort-ev4t.o +p-$(CONFIG_CPU_ARM1020) += proc-arm1020.o tlb-v4wbi.o cache-v4wt.o copypage-v4wb.o abort-ev4t.o +p-$(CONFIG_CPU_SA110) += proc-sa110.o tlb-v4wb.o cache-v4wb.o copypage-v4wb.o abort-ev4.o +p-$(CONFIG_CPU_SA1100) += proc-sa1100.o tlb-v4wb.o cache-v4wb.o copypage-v4mc.o abort-ev4.o minicache.o # ARMv5 p-$(CONFIG_CPU_ARM926T) += proc-arm926.o tlb-v4wbi.o copypage-v4wb.o abort-ev5tej.o --- linux-2.5.68/arch/arm/mm/mm-armv.c 2003-01-16 18:22:22.000000000 -0800 +++ 25/arch/arm/mm/mm-armv.c 2003-04-29 20:50:34.000000000 -0700 @@ -24,30 +24,82 @@ #include +static unsigned int cachepolicy __initdata = PMD_SECT_WB; +static unsigned int ecc_mask __initdata = 0; + +struct cachepolicy { + char *policy; + unsigned int cr_mask; + unsigned int pmd; +}; + +static struct cachepolicy cache_policies[] __initdata = { + { "uncached", CR1_W|CR1_C, PMD_SECT_UNCACHED }, + { "buffered", CR1_C, PMD_SECT_BUFFERED }, + { "writethrough", 0, PMD_SECT_WT }, +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH + { "writeback", 0, PMD_SECT_WB }, + { "writealloc", 0, PMD_SECT_WBWA } +#endif +}; + /* * These are useful for identifing cache coherency * problems by allowing the cache or the cache and * writebuffer to be turned off. (Note: the write * buffer should not be on and the cache off). */ -static int __init nocache_setup(char *__unused) +static void __init early_cachepolicy(char **p) { - cr_alignment &= ~CR1_C; - cr_no_alignment &= ~CR1_C; + int i; + + for (i = 0; i < ARRAY_SIZE(cache_policies); i++) { + int len = strlen(cache_policies[i].policy); + + if (memcmp(*p, cache_policies[i].policy, len) == 0) { + cachepolicy = cache_policies[i].pmd; + cr_alignment &= ~cache_policies[i].cr_mask; + cr_no_alignment &= ~cache_policies[i].cr_mask; + *p += len; + break; + } + } + if (i == ARRAY_SIZE(cache_policies)) + printk(KERN_ERR "ERROR: unknown or unsupported cache policy\n"); flush_cache_all(); set_cr(cr_alignment); - return 1; } -static int __init nowrite_setup(char *__unused) +static void __init early_nocache(char **__unused) { - cr_alignment &= ~(CR1_W|CR1_C); - cr_no_alignment &= ~(CR1_W|CR1_C); - flush_cache_all(); - set_cr(cr_alignment); - return 1; + char *p = "buffered"; + printk(KERN_WARNING "nocache is deprecated; use cachepolicy=%s\n", p); + early_cachepolicy(&p); +} + +static void __init early_nowrite(char **__unused) +{ + char *p = "uncached"; + printk(KERN_WARNING "nowb is deprecated; use cachepolicy=%s\n", p); + early_cachepolicy(&p); } +static void __init early_ecc(char **p) +{ + if (memcmp(*p, "on", 2) == 0) { + ecc_mask = PMD_PROTECTION; + *p += 2; + } else if (memcmp(*p, "off", 3) == 0) { + ecc_mask = 0; + *p += 3; + } +} + +__early_param("nocache", early_nocache); +__early_param("nowb", early_nowrite); +__early_param("cachepolicy=", early_cachepolicy); +__early_param("ecc=", early_ecc); + static int __init noalign_setup(char *__unused) { cr_alignment &= ~CR1_A; @@ -57,8 +109,6 @@ static int __init noalign_setup(char *__ } __setup("noalign", noalign_setup); -__setup("nocache", nocache_setup); -__setup("nowb", nowrite_setup); #define FIRST_KERNEL_PGD_NR (FIRST_USER_PGD_NR + USER_PTRS_PER_PGD) @@ -197,7 +247,7 @@ alloc_init_page(unsigned long virt, unsi pmdval = __pa(ptep) | prot_l1; pmdp[0] = __pmd(pmdval); pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t)); - cpu_flush_pmd(pmdp); + flush_pmd_entry(pmdp); } ptep = pte_offset_kernel(pmdp, virt); @@ -231,32 +281,20 @@ static struct mem_types mem_types[] __in .domain = DOMAIN_IO, }, [MT_CACHECLEAN] = { - .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | - L_PTE_CACHEABLE | L_PTE_BUFFERABLE, - .prot_l1 = PMD_TYPE_TABLE | PMD_BIT4, .prot_sect = PMD_TYPE_SECT | PMD_BIT4, .domain = DOMAIN_KERNEL, }, [MT_MINICLEAN] = { - .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | - L_PTE_CACHEABLE, - .prot_l1 = PMD_TYPE_TABLE | PMD_BIT4, .prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_MINICACHE, .domain = DOMAIN_KERNEL, }, [MT_VECTORS] = { .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | - L_PTE_CACHEABLE | L_PTE_BUFFERABLE | L_PTE_EXEC, .prot_l1 = PMD_TYPE_TABLE | PMD_BIT4, - .prot_sect = PMD_TYPE_SECT | PMD_BIT4, .domain = DOMAIN_USER, }, [MT_MEMORY] = { - .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | - L_PTE_CACHEABLE | L_PTE_BUFFERABLE | - L_PTE_EXEC | L_PTE_WRITE, - .prot_l1 = PMD_TYPE_TABLE | PMD_BIT4, .prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_AP_WRITE, .domain = DOMAIN_KERNEL, } @@ -268,37 +306,50 @@ static struct mem_types mem_types[] __in static void __init build_mem_type_table(void) { int cpu_arch = cpu_architecture(); -#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH - int writethrough = 1; -#else - int writethrough = 0; -#endif - int writealloc = 0, ecc = 0; + const char *policy; - if (cpu_arch < CPU_ARCH_ARMv5) { - writealloc = 0; - ecc = 0; + /* + * ARMv5 can use ECC memory. + */ + if (cpu_arch == CPU_ARCH_ARMv5) { + mem_types[MT_VECTORS].prot_l1 |= ecc_mask; + mem_types[MT_MEMORY].prot_sect |= ecc_mask; + } else { mem_types[MT_MINICLEAN].prot_sect &= ~PMD_SECT_TEX(1); - } - - if (writethrough) { + if (cachepolicy == PMD_SECT_WBWA) + cachepolicy = PMD_SECT_WB; + ecc_mask = 0; + } + + mem_types[MT_MEMORY].prot_sect |= cachepolicy; + + switch (cachepolicy) { + default: + case PMD_SECT_UNCACHED: + policy = "uncached"; + break; + case PMD_SECT_BUFFERED: + mem_types[MT_VECTORS].prot_pte |= PTE_BUFFERABLE; + policy = "buffered"; + break; + case PMD_SECT_WT: + mem_types[MT_VECTORS].prot_pte |= PTE_BUFFERABLE|PTE_CACHEABLE; mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WT; - mem_types[MT_VECTORS].prot_sect |= PMD_SECT_WT; - mem_types[MT_MEMORY].prot_sect |= PMD_SECT_WT; - } else { + policy = "write through"; + break; + case PMD_SECT_WB: + mem_types[MT_VECTORS].prot_pte |= PTE_BUFFERABLE|PTE_CACHEABLE; mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WB; - mem_types[MT_VECTORS].prot_sect |= PMD_SECT_WB; - - if (writealloc) - mem_types[MT_MEMORY].prot_sect |= PMD_SECT_WBWA; - else - mem_types[MT_MEMORY].prot_sect |= PMD_SECT_WB; - } - - if (ecc) { - mem_types[MT_VECTORS].prot_sect |= PMD_PROTECTION; - mem_types[MT_MEMORY].prot_sect |= PMD_PROTECTION; + policy = "write back"; + break; + case PMD_SECT_WBWA: + mem_types[MT_VECTORS].prot_pte |= PTE_BUFFERABLE|PTE_CACHEABLE; + mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WB; + policy = "write back, write allocate"; + break; } + printk("Memory policy: ECC %sabled, Data cache %s\n", + ecc_mask ? "en" : "dis", policy); } /* @@ -330,6 +381,14 @@ static void __init create_mapping(struct off = md->physical - virt; length = md->length; + if (mem_types[md->type].prot_l1 == 0 && + (virt & 0xfffff || (virt + off) & 0xfffff || (virt + length) & 0xfffff)) { + printk(KERN_WARNING "MM: map for 0x%08lx at 0x%08lx can not " + "be mapped using pages, ignoring.\n", + md->physical, md->virtual); + return; + } + while ((virt & 0xfffff || (virt + off) & 0xfffff) && length >= PAGE_SIZE) { alloc_init_page(virt, virt + off, prot_l1, prot_pte); --- linux-2.5.68/arch/arm/mm/proc-arm1020.S 2003-01-16 18:21:37.000000000 -0800 +++ 25/arch/arm/mm/proc-arm1020.S 2003-04-29 20:50:34.000000000 -0700 @@ -43,27 +43,29 @@ #define MAX_AREA_SIZE 32768 /* - * the cache line size of the I and D cache + * The size of one data cache line. */ -#define DCACHELINESIZE 32 -#define ICACHELINESIZE 32 +#define CACHE_DLINESIZE 32 /* - * and the page size + * The number of data cache segments. */ -#define PAGESIZE 4096 +#define CACHE_DSEGMENTS 16 - .text /* - * cpu_arm1020_check_bugs() + * The number of lines in a cache segment. */ -ENTRY(cpu_arm1020_check_bugs) - mrs ip, cpsr - bic ip, ip, #PSR_F_BIT - msr cpsr, ip - mov pc, lr +#define CACHE_DENTRIES 64 /* + * This is the size at which it becomes more efficient to + * clean the whole cache, rather than using the individual + * cache line maintainence instructions. + */ +#define CACHE_DLIMIT 32768 + + .text +/* * cpu_arm1020_proc_init() */ ENTRY(cpu_arm1020_proc_init) @@ -114,230 +116,233 @@ ENTRY(cpu_arm1020_do_idle) /* ================================= CACHE ================================ */ - + .align 5 /* - * cpu_arm1020_cache_clean_invalidate_all() + * flush_user_cache_all() * - * clean and invalidate all cache lines + * Invalidate all cache entries in a particular address + * space. + */ +ENTRY(arm1020_flush_user_cache_all) + /* FALLTHROUGH */ +/* + * flush_kern_cache_all() * - * Note: - * 1. we should preserve r0 at all times + * Clean and invalidate the entire cache. */ - .align 5 -ENTRY(cpu_arm1020_cache_clean_invalidate_all) - mov r2, #1 -cpu_arm1020_cache_clean_invalidate_all_r2: +ENTRY(arm1020_flush_kern_cache_all) + mov r2, #VM_EXEC + mov ip, #0 +__flush_whole_cache: #ifndef CONFIG_CPU_DCACHE_DISABLE - mcr p15, 0, ip, c7, c10, 4 - - mov r1, #0xf @ 16 segments -1: mov r3, #0x3F @ 64 entries -2: mov ip, r3, LSL #26 @ shift up entry - orr ip, ip, r1, LSL #5 @ shift in/up index - mcr p15, 0, ip, c7, c14, 2 @ Clean & Inval DCache entry - mcr p15, 0, ip, c7, c10, 4 @ drain WB - subs r3, r3, #1 - cmp r3, #0 - bge 2b @ entries 3F to 0 - subs r1, r1, #1 - cmp r1, #0 - bge 1b @ segments 7 to 0 + mcr p15, 0, ip, c7, c10, 4 @ drain WB + mov r1, #(CACHE_DSEGMENTS - 1) << 5 @ 16 segments +1: orr r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries +2: mcr p15, 0, r3, c7, c14, 2 @ clean+invalidate D index + mcr p15, 0, ip, c7, c10, 4 @ drain WB + subs r3, r3, #1 << 26 + bcs 2b @ entries 63 to 0 + subs r1, r1, #1 << 5 + bcs 1b @ segments 15 to 0 #endif + tst r2, #VM_EXEC #ifndef CONFIG_CPU_ICACHE_DISABLE - teq r2, #0 mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache #endif - mcr p15, 0, ip, c7, c10, 4 @ drain WB + mcrne p15, 0, ip, c7, c10, 4 @ drain WB mov pc, lr /* - * cpu_arm1020_cache_clean_invalidate_range(start, end, flags) + * flush_user_cache_range(start, end, flags) * - * clean and invalidate all cache lines associated with this area of memory + * Invalidate a range of cache entries in the specified + * address space. * - * start: Area start address - * end: Area end address - * flags: nonzero for I cache as well + * - start - start address (inclusive) + * - end - end address (exclusive) + * - flags - vm_flags for this space */ - .align 5 -ENTRY(cpu_arm1020_cache_clean_invalidate_range) - bic r0, r0, #DCACHELINESIZE - 1 - sub r3, r1, r0 - cmp r3, #MAX_AREA_SIZE - bgt cpu_arm1020_cache_clean_invalidate_all_r2 - mcr p15, 0, r3, c7, c10, 4 +ENTRY(arm1020_flush_user_cache_range) + mov ip, #0 + sub r3, r1, r0 @ calculate total size + cmp r3, #CACHE_DLIMIT + bhs __flush_whole_cache + #ifndef CONFIG_CPU_DCACHE_DISABLE -1: mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry - mcr p15, 0, r3, c7, c10, 4 @ drain WB - add r0, r0, #DCACHELINESIZE - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry - mcr p15, 0, r3, c7, c10, 4 @ drain WB - add r0, r0, #DCACHELINESIZE + mcr p15, 0, ip, c7, c10, 4 +1: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry + mcr p15, 0, ip, c7, c10, 4 @ drain WB + add r0, r0, #CACHE_DLINESIZE cmp r0, r1 - blt 1b + blo 1b #endif - + tst r2, #VM_EXEC #ifndef CONFIG_CPU_ICACHE_DISABLE - teq r2, #0 - movne r0, #0 - mcrne p15, 0, r0, c7, c5, 0 @ invalidate I cache + mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache #endif + mcrne p15, 0, ip, c7, c10, 4 @ drain WB mov pc, lr -/* ================================ D-CACHE =============================== */ - /* - * cpu_arm1020_dcache_invalidate_range(start, end) + * coherent_kern_range(start, end) * - * throw away all D-cached data in specified region without an obligation - * to write them back. Note however that we must clean the D-cached entries - * around the boundaries if the start and/or end address are not cache - * aligned. + * Ensure coherency between the Icache and the Dcache in the + * region described by start. If you have non-snooping + * Harvard caches, you need to implement this function. * - * start: virtual start address - * end: virtual end address + * - start - virtual start address + * - end - virtual end address */ - .align 5 -ENTRY(cpu_arm1020_dcache_invalidate_range) +ENTRY(arm1020_coherent_kern_range) + mov ip, #0 + bic r0, r0, #CACHE_DLINESIZE - 1 + mcr p15, 0, ip, c7, c10, 4 +1: #ifndef CONFIG_CPU_DCACHE_DISABLE - /* D cache are on */ - tst r0, #DCACHELINESIZE - 1 - bic r0, r0, #DCACHELINESIZE - 1 - mcrne p15, 0, r0, c7, c10, 4 - mcrne p15, 0, r0, c7, c10, 1 @ clean D entry at start - mcrne p15, 0, r0, c7, c10, 4 @ drain WB - tst r1, #DCACHELINESIZE - 1 - mcrne p15, 0, r1, c7, c10, 4 - mcrne p15, 0, r1, c7, c10, 1 @ clean D entry at end - mcrne p15, 0, r1, c7, c10, 4 @ drain WB - -1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry - add r0, r0, #DCACHELINESIZE - cmp r0, r1 - blt 1b -#else - /* D cache off, but still drain the write buffer */ - mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer + mcr p15, 0, r0, c7, c10, 1 @ clean D entry + mcr p15, 0, ip, c7, c10, 4 @ drain WB #endif +#ifndef CONFIG_CPU_ICACHE_DISABLE + mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry +#endif + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + mcr p15, 0, ip, c7, c10, 4 @ drain WB mov pc, lr /* - * cpu_arm1020_dcache_clean_range(start, end) + * flush_kern_dcache_page(void *page) * - * For the specified virtual address range, ensure that all caches contain - * clean data, such that peripheral accesses to the physical RAM fetch - * correct data. + * Ensure no D cache aliasing occurs, either with itself or + * the I cache * - * start: virtual start address - * end: virtual end address + * - page - page aligned address */ - .align 5 -ENTRY(cpu_arm1020_dcache_clean_range) - bic r0, r0, #DCACHELINESIZE - 1 - sub r3, r1, r0 - cmp r3, #MAX_AREA_SIZE - bgt cpu_arm1020_cache_clean_invalidate_all_r2 - mcr p15, 0, r3, c7, c10, 4 +ENTRY(arm1020_flush_kern_dcache_page) + mov ip, #0 #ifndef CONFIG_CPU_DCACHE_DISABLE -1: mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry - mcr p15, 0, r3, c7, c10, 4 @ drain WB - add r0, r0, #DCACHELINESIZE - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry - mcr p15, 0, r3, c7, c10, 4 @ drain WB - add r0, r0, #DCACHELINESIZE + add r1, r0, #PAGE_SZ +1: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry + mcr p15, 0, ip, c7, c10, 4 @ drain WB + add r0, r0, #CACHE_DLINESIZE cmp r0, r1 - blt 1b + blo 1b #endif + mcr p15, 0, ip, c7, c10, 4 @ drain WB mov pc, lr /* - * cpu_arm1020_dcache_clean_page(page) + * dma_inv_range(start, end) * - * Cleans a single page of dcache so that if we have any future aliased - * mappings, they will be consistent at the time that they are created. + * Invalidate (discard) the specified virtual address range. + * May not write back any entries. If 'start' or 'end' + * are not cache line aligned, those lines must be written + * back. * - * page: virtual address of page to clean from dcache + * - start - virtual start address + * - end - virtual end address * - * Note: - * 1. we don't need to flush the write buffer in this case. - * 2. we don't invalidate the entries since when we write the page - * out to disk, the entries may get reloaded into the cache. + * (same as v4wb) */ - .align 5 -ENTRY(cpu_arm1020_dcache_clean_page) - mov r1, #PAGESIZE - mcr p15, 0, r0, c7, c10, 4 +ENTRY(arm1020_dma_inv_range) + mov ip, #0 #ifndef CONFIG_CPU_DCACHE_DISABLE -1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry (drain is done by TLB fns) - mcr p15, 0, r0, c7, c10, 4 @ drain WB - add r0, r0, #DCACHELINESIZE - mcr p15, 0, r0, c7, c10, 1 @ clean D entry - mcr p15, 0, r0, c7, c10, 4 @ drain WB - add r0, r0, #DCACHELINESIZE - subs r1, r1, #2 * DCACHELINESIZE - bhi 1b + tst r0, #CACHE_DLINESIZE - 1 + bic r0, r0, #CACHE_DLINESIZE - 1 + mcrne p15, 0, ip, c7, c10, 4 + mcrne p15, 0, r0, c7, c10, 1 @ clean D entry + mcrne p15, 0, ip, c7, c10, 4 @ drain WB + tst r1, #CACHE_DLINESIZE - 1 + mcrne p15, 0, ip, c7, c10, 4 + mcrne p15, 0, r1, c7, c10, 1 @ clean D entry + mcrne p15, 0, ip, c7, c10, 4 @ drain WB +1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b #endif + mcr p15, 0, ip, c7, c10, 4 @ drain WB mov pc, lr /* - * cpu_arm1020_dcache_clean_entry(addr) + * dma_clean_range(start, end) + * + * Clean the specified virtual address range. * - * Clean the specified entry of any caches such that the MMU - * translation fetches will obtain correct data. + * - start - virtual start address + * - end - virtual end address * - * addr: cache-unaligned virtual address + * (same as v4wb) */ - .align 5 -ENTRY(cpu_arm1020_dcache_clean_entry) - mov r1, #0 - mcr p15, 0, r1, c7, c10, 4 +ENTRY(arm1020_dma_clean_range) + mov ip, #0 #ifndef CONFIG_CPU_DCACHE_DISABLE - mcr p15, 0, r0, c7, c10, 1 @ clean single D entry - mcr p15, 0, r1, c7, c10, 4 @ drain WB -#endif -#ifndef CONFIG_CPU_ICACHE_DISABLE - mcr p15, 0, r1, c7, c5, 1 @ invalidate I entry + bic r0, r0, #CACHE_DLINESIZE - 1 +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + mcr p15, 0, ip, c7, c10, 4 @ drain WB + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b #endif + mcr p15, 0, ip, c7, c10, 4 @ drain WB mov pc, lr -/* ================================ I-CACHE =============================== */ - /* - * cpu_arm1020_icache_invalidate_range(start, end) + * dma_flush_range(start, end) * - * invalidate a range of virtual addresses from the Icache + * Clean and invalidate the specified virtual address range. * - * start: virtual start address - * end: virtual end address + * - start - virtual start address + * - end - virtual end address */ - .align 5 -ENTRY(cpu_arm1020_icache_invalidate_range) -1: mcr p15, 0, r0, c7, c10, 4 +ENTRY(arm1020_dma_flush_range) + mov ip, #0 #ifndef CONFIG_CPU_DCACHE_DISABLE - mcr p15, 0, r0, c7, c10, 1 @ Clean D entry - mcr p15, 0, r0, c7, c10, 4 @ drain WB - add r0, r0, #DCACHELINESIZE - mcr p15, 0, r0, c7, c10, 1 @ Clean D entry - mcr p15, 0, r0, c7, c10, 4 @ drain WB -#endif - add r0, r0, #DCACHELINESIZE + bic r0, r0, #CACHE_DLINESIZE - 1 + mcr p15, 0, ip, c7, c10, 4 +1: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry + mcr p15, 0, ip, c7, c10, 4 @ drain WB + add r0, r0, #CACHE_DLINESIZE cmp r0, r1 blo 1b -ENTRY(cpu_arm1020_icache_invalidate_page) - mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache +#endif + mcr p15, 0, ip, c7, c10, 4 @ drain WB + mov pc, lr + +ENTRY(arm1020_cache_fns) + .long arm1020_flush_kern_cache_all + .long arm1020_flush_user_cache_all + .long arm1020_flush_user_cache_range + .long arm1020_coherent_kern_range + .long arm1020_flush_kern_dcache_page + .long arm1020_dma_inv_range + .long arm1020_dma_clean_range + .long arm1020_dma_flush_range + + .align 5 +ENTRY(cpu_arm1020_dcache_clean_area) +#ifndef CONFIG_CPU_DCACHE_DISABLE + mov ip, #0 +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + mcr p15, 0, ip, c7, c10, 4 @ drain WB + add r0, r0, #CACHE_DLINESIZE + subs r1, r1, #CACHE_DLINESIZE + bhi 1b +#endif mov pc, lr /* =============================== PageTable ============================== */ /* - * cpu_arm1020_set_pgd(pgd) + * cpu_arm1020_switch_mm(pgd) * * Set the translation base pointer to be as described by pgd. * * pgd: new page tables */ .align 5 -ENTRY(cpu_arm1020_set_pgd) +ENTRY(cpu_arm1020_switch_mm) #ifndef CONFIG_CPU_DCACHE_DISABLE mcr p15, 0, r3, c7, c10, 4 mov r1, #0xF @ 16 segments @@ -365,23 +370,6 @@ ENTRY(cpu_arm1020_set_pgd) mov pc, lr /* - * cpu_arm1020_flush_pmd(pmdp) - * - * Set a level 1 translation table entry, and clean it out of - * any caches such that the MMUs can load it correctly. - * - * pmdp: pointer to PMD entry - */ - .align 5 -ENTRY(cpu_arm1020_flush_pmd) -#ifndef CONFIG_CPU_DCACHE_DISABLE - mcr p15, 0, r0, c7, c10, 4 - mcr p15, 0, r0, c7, c10, 1 @ clean D entry (drain is done by TLB fns) -#endif - mcr p15, 0, r0, c7, c10, 4 @ drain WB - mov pc, lr - -/* * cpu_arm1020_set_pte(ptep, pte) * * Set a PTE and flush it out @@ -396,7 +384,7 @@ ENTRY(cpu_arm1020_set_pte) bic r2, r2, #3 orr r2, r2, #HPTE_TYPE_SMALL - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec? + tst r1, #LPTE_USER @ User? orrne r2, r2, #HPTE_AP_READ tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty? @@ -489,29 +477,12 @@ __arm1020_setup: .type arm1020_processor_functions, #object arm1020_processor_functions: .word v4t_early_abort - .word cpu_arm1020_check_bugs .word cpu_arm1020_proc_init .word cpu_arm1020_proc_fin .word cpu_arm1020_reset .word cpu_arm1020_do_idle - - /* cache */ - .word cpu_arm1020_cache_clean_invalidate_all - .word cpu_arm1020_cache_clean_invalidate_range - - /* dcache */ - .word cpu_arm1020_dcache_invalidate_range - .word cpu_arm1020_dcache_clean_range - .word cpu_arm1020_dcache_clean_page - .word cpu_arm1020_dcache_clean_entry - - /* icache */ - .word cpu_arm1020_icache_invalidate_range - .word cpu_arm1020_icache_invalidate_page - - /* pgtable */ - .word cpu_arm1020_set_pgd - .word cpu_arm1020_flush_pmd + .word cpu_arm1020_dcache_clean_area + .word cpu_arm1020_switch_mm .word cpu_arm1020_set_pte .size arm1020_processor_functions, . - arm1020_processor_functions @@ -542,4 +513,5 @@ __arm1020_proc_info: .long arm1020_processor_functions .long v4wbi_tlb_fns .long v4wb_user_fns + .long arm1020_cache_fns .size __arm1020_proc_info, . - __arm1020_proc_info --- linux-2.5.68/arch/arm/mm/proc-arm2_3.S 2003-01-16 18:22:13.000000000 -0800 +++ 25/arch/arm/mm/proc-arm2_3.S 2003-04-29 20:50:34.000000000 -0700 @@ -162,7 +162,7 @@ memc_phys_table_32: * and inaccessible (0x01f00000). * Params : r0 = page table pointer */ -clear_tables: ldr r1, _arm3_set_pgd - 4 +clear_tables: ldr r1, _arm3_switch_mm - 4 ldr r2, [r1] sub r1, r0, #256 * 4 @ start of MEMC tables add r2, r1, r2, lsl #2 @ end of tables @@ -186,14 +186,16 @@ clear_tables: ldr r1, _arm3_set_pgd - 4 mov pc, lr /* - * Function: *_set_pgd(pgd_t *pgd) + * Function: *_switch_mm(pgd_t *pgd) * Params : pgd New page tables/MEMC mapping * Purpose : update MEMC hardware with new mapping */ .word page_nr -_arm3_set_pgd: mcr p15, 0, r1, c1, c0, 0 @ flush cache -_arm2_set_pgd: stmfd sp!, {lr} - ldr r1, _arm3_set_pgd - 4 +_arm3_switch_mm: + mcr p15, 0, r1, c1, c0, 0 @ flush cache +_arm2_switch_mm: + stmfd sp!, {lr} + ldr r1, _arm3_switch_mm - 4 ldr r2, [r1] sub r0, r0, #256 * 4 @ start of MEMC tables add r1, r0, r2, lsl #2 @ end of tables @@ -273,9 +275,6 @@ _arm2_xchg_4: mov r2, pc _arm3_xchg_4: swp r0, r0, [r1] movs pc, lr -_arm2_3_check_bugs: - bics pc, lr, #0x04000000 @ Clear FIQ disable bit - cpu_arm2_name: .asciz "ARM 2" cpu_arm250_name: @@ -290,28 +289,25 @@ cpu_arm3_name: */ .globl arm2_processor_functions arm2_processor_functions: - .word _arm2_3_check_bugs .word _arm2_proc_init .word _arm2_proc_fin - .word _arm2_set_pgd + .word _arm2_switch_mm .word _arm2_xchg_1 .word _arm2_xchg_4 .globl arm250_processor_functions arm250_processor_functions: - .word _arm2_3_check_bugs .word _arm2_proc_init .word _arm2_proc_fin - .word _arm2_set_pgd + .word _arm2_switch_mm .word _arm3_xchg_1 .word _arm3_xchg_4 .globl arm3_processor_functions arm3_processor_functions: - .word _arm2_3_check_bugs .word _arm3_proc_init .word _arm3_proc_fin - .word _arm3_set_pgd + .word _arm3_switch_mm .word _arm3_xchg_1 .word _arm3_xchg_4 @@ -334,6 +330,7 @@ arm3_elf_name: .asciz "v2" .long arm2_processor_functions .long 0 .long 0 + .long 0 .long 0x41560250 .long 0xfffffff0 @@ -346,6 +343,7 @@ arm3_elf_name: .asciz "v2" .long arm250_processor_functions .long 0 .long 0 + .long 0 .long 0x41560300 .long 0xfffffff0 @@ -358,4 +356,5 @@ arm3_elf_name: .asciz "v2" .long arm3_processor_functions .long 0 .long 0 + .long 0 --- linux-2.5.68/arch/arm/mm/proc-arm6_7.S 2003-03-04 20:02:35.000000000 -0800 +++ 25/arch/arm/mm/proc-arm6_7.S 2003-04-29 20:50:34.000000000 -0700 @@ -16,192 +16,162 @@ #include #include -/* - * Function: arm6_7_cache_clean_invalidate_all (void) - * : arm6_7_cache_clean_invalidate_page (unsigned long address, int size, int flags) - * - * Params : address Area start address - * : size size of area - * : flags b0 = I cache as well - * - * Purpose : Flush all cache lines - */ -ENTRY(cpu_arm6_cache_clean_invalidate_all) -ENTRY(cpu_arm7_cache_clean_invalidate_all) -ENTRY(cpu_arm6_cache_clean_invalidate_range) -ENTRY(cpu_arm7_cache_clean_invalidate_range) -ENTRY(cpu_arm6_icache_invalidate_range) -ENTRY(cpu_arm7_icache_invalidate_range) -ENTRY(cpu_arm6_icache_invalidate_page) -ENTRY(cpu_arm7_icache_invalidate_page) -ENTRY(cpu_arm6_dcache_clean_range) -ENTRY(cpu_arm7_dcache_clean_range) -ENTRY(cpu_arm6_dcache_invalidate_range) -ENTRY(cpu_arm7_dcache_invalidate_range) - mov r0, #0 - mcr p15, 0, r0, c7, c0, 0 @ flush cache -ENTRY(cpu_arm6_dcache_clean_page) -ENTRY(cpu_arm7_dcache_clean_page) -ENTRY(cpu_arm6_dcache_clean_entry) -ENTRY(cpu_arm7_dcache_clean_entry) +ENTRY(cpu_arm6_dcache_clean_area) +ENTRY(cpu_arm7_dcache_clean_area) mov pc, lr /* * Function: arm6_7_data_abort () * - * Params : r0 = address of aborted instruction + * Params : r2 = address of aborted instruction + * : sp = pointer to registers * * Purpose : obtain information about current aborted instruction * * Returns : r0 = address of abort - * : r1 != 0 if writing - * : r3 = FSR - * : sp = pointer to registers + * : r1 = FSR */ -ENTRY(cpu_arm6_data_abort) - ldr r4, [r0] @ read instruction causing problem - tst r4, r4, lsr #21 @ C = bit 20 - sbc r1, r1, r1 @ r1 = C - 1 - and r2, r4, #14 << 24 - teq r2, #8 << 24 @ was it ldm/stm - bne Ldata_simple - -Ldata_ldmstm: tst r4, #1 << 21 @ check writeback bit - beq Ldata_simple - mov r7, #0x11 - orr r7, r7, r7, lsl #8 - and r0, r4, r7 - and r2, r4, r7, lsl #1 - add r0, r0, r2, lsr #1 - and r2, r4, r7, lsl #2 - add r0, r0, r2, lsr #2 - and r2, r4, r7, lsl #3 - add r0, r0, r2, lsr #3 - add r0, r0, r0, lsr #8 - add r0, r0, r0, lsr #4 - and r7, r0, #15 @ r7 = no. of registers to transfer. - and r5, r4, #15 << 16 @ Get Rn - ldr r0, [sp, r5, lsr #14] @ Get register - tst r4, #1 << 23 @ U bit - subne r7, r0, r7, lsl #2 - addeq r7, r0, r7, lsl #2 @ Do correction (signed) -Ldata_saver7: str r7, [sp, r5, lsr #14] @ Put register -Ldata_simple: mrc p15, 0, r0, c6, c0, 0 @ get FAR - mrc p15, 0, r3, c5, c0, 0 @ get FSR - and r3, r3, #255 - mov pc, lr - ENTRY(cpu_arm7_data_abort) - ldr r4, [r0] @ read instruction causing problem - tst r4, r4, lsr #21 @ C = bit 20 - sbc r1, r1, r1 @ r1 = C - 1 - and r2, r4, #15 << 24 - add pc, pc, r2, lsr #22 @ Now branch to the relevant processing routine - movs pc, lr - - b Ldata_unknown - b Ldata_unknown - b Ldata_unknown - b Ldata_unknown - b Ldata_lateldrpostconst @ ldr rd, [rn], #m - b Ldata_lateldrpreconst @ ldr rd, [rn, #m] @ RegVal - b Ldata_lateldrpostreg @ ldr rd, [rn], rm - b Ldata_lateldrprereg @ ldr rd, [rn, rm] - b Ldata_ldmstm @ ldm*a rn, - b Ldata_ldmstm @ ldm*b rn, - b Ldata_unknown - b Ldata_unknown - b Ldata_simple @ ldc rd, [rn], #m @ Same as ldr rd, [rn], #m - b Ldata_simple @ ldc rd, [rn, #m] - b Ldata_unknown -Ldata_unknown: @ Part of jumptable - mov r0, r2 - mov r1, r4 - mov r2, r3 - bl baddataabort - b ret_from_exception - -Ldata_lateldrpreconst: - tst r4, #1 << 21 @ check writeback bit - beq Ldata_simple -Ldata_lateldrpostconst: - movs r2, r4, lsl #20 @ Get offset - beq Ldata_simple - and r5, r4, #15 << 16 @ Get Rn - ldr r0, [sp, r5, lsr #14] - tst r4, #1 << 23 @ U bit - subne r7, r0, r2, lsr #20 - addeq r7, r0, r2, lsr #20 - b Ldata_saver7 - -Ldata_lateldrprereg: - tst r4, #1 << 21 @ check writeback bit - beq Ldata_simple -Ldata_lateldrpostreg: - and r5, r4, #15 - ldr r2, [sp, r5, lsl #2] @ Get Rm - mov r3, r4, lsr #7 - ands r3, r3, #31 - and r6, r4, #0x70 - orreq r6, r6, #8 - add pc, pc, r6 - mov r0, r0 - - mov r2, r2, lsl r3 @ 0: LSL #!0 - b 1f - b 1f @ 1: LSL #0 - mov r0, r0 - b 1f @ 2: MUL? - mov r0, r0 - b 1f @ 3: MUL? - mov r0, r0 - mov r2, r2, lsr r3 @ 4: LSR #!0 - b 1f - mov r2, r2, lsr #32 @ 5: LSR #32 - b 1f - b 1f @ 6: MUL? - mov r0, r0 - b 1f @ 7: MUL? - mov r0, r0 - mov r2, r2, asr r3 @ 8: ASR #!0 - b 1f - mov r2, r2, asr #32 @ 9: ASR #32 - b 1f - b 1f @ A: MUL? - mov r0, r0 - b 1f @ B: MUL? - mov r0, r0 - mov r2, r2, ror r3 @ C: ROR #!0 - b 1f - mov r2, r2, rrx @ D: RRX - b 1f - mov r0, r0 @ E: MUL? - mov r0, r0 - mov r0, r0 @ F: MUL? - - -1: and r5, r4, #15 << 16 @ Get Rn - ldr r0, [sp, r5, lsr #14] - tst r4, #1 << 23 @ U bit - subne r7, r0, r2 - addeq r7, r0, r2 - b Ldata_saver7 + mrc p15, 0, r1, c5, c0, 0 @ get FSR + mrc p15, 0, r0, c6, c0, 0 @ get FAR + ldr r8, [r0] @ read arm instruction + tst r8, #1 << 20 @ L = 1 -> write? + orreq r1, r1, #1 << 8 @ yes. + and r7, r8, #15 << 24 + add pc, pc, r7, lsr #22 @ Now branch to the relevant processing routine + nop + +/* 0 */ b .data_unknown +/* 1 */ mov pc, lr @ swp +/* 2 */ b .data_unknown +/* 3 */ b .data_unknown +/* 4 */ b .data_arm_lateldrpostconst @ ldr rd, [rn], #m +/* 5 */ b .data_arm_lateldrpreconst @ ldr rd, [rn, #m] +/* 6 */ b .data_arm_lateldrpostreg @ ldr rd, [rn], rm +/* 7 */ b .data_arm_lateldrprereg @ ldr rd, [rn, rm] +/* 8 */ b .data_arm_ldmstm @ ldm*a rn, +/* 9 */ b .data_arm_ldmstm @ ldm*b rn, +/* a */ b .data_unknown +/* b */ b .data_unknown +/* c */ mov pc, lr @ ldc rd, [rn], #m @ Same as ldr rd, [rn], #m +/* d */ mov pc, lr @ ldc rd, [rn, #m] +/* e */ b .data_unknown +/* f */ +.data_unknown: @ Part of jumptable + mov r0, r2 + mov r1, r8 + mov r2, sp + bl baddataabort + b ret_from_exception + +ENTRY(cpu_arm6_data_abort) + mrc p15, 0, r1, c5, c0, 0 @ get FSR + mrc p15, 0, r0, c6, c0, 0 @ get FAR + ldr r8, [r2] @ read arm instruction + tst r8, #1 << 20 @ L = 1 -> write? + orreq r1, r1, #1 << 8 @ yes. + and r7, r8, #14 << 24 + teq r7, #8 << 24 @ was it ldm/stm + movne pc, lr + +.data_arm_ldmstm: + tst r8, #1 << 21 @ check writeback bit + moveq pc, lr @ no writeback -> no fixup + mov r7, #0x11 + orr r7, r7, #0x1100 + and r6, r8, r7 + and r2, r8, r7, lsl #1 + add r6, r6, r2, lsr #1 + and r2, r8, r7, lsl #2 + add r6, r6, r2, lsr #2 + and r2, r8, r7, lsl #3 + add r6, r6, r2, lsr #3 + add r6, r6, r6, lsr #8 + add r6, r6, r6, lsr #4 + and r6, r6, #15 @ r6 = no. of registers to transfer. + and r5, r8, #15 << 16 @ Extract 'n' from instruction + ldr r7, [sp, r5, lsr #14] @ Get register 'Rn' + tst r8, #1 << 23 @ Check U bit + subne r7, r7, r6, lsl #2 @ Undo increment + addeq r7, r7, r6, lsl #2 @ Undo decrement + str r7, [sp, r5, lsr #14] @ Put register 'Rn' + mov pc, lr + +.data_arm_apply_r6_and_rn: + and r5, r8, #15 << 16 @ Extract 'n' from instruction + ldr r7, [sp, r5, lsr #14] @ Get register 'Rn' + tst r8, #1 << 23 @ Check U bit + subne r7, r7, r6 @ Undo incrmenet + addeq r7, r7, r6 @ Undo decrement + str r7, [sp, r5, lsr #14] @ Put register 'Rn' + mov pc, lr + +.data_arm_lateldrpreconst: + tst r8, #1 << 21 @ check writeback bit + moveq pc, lr @ no writeback -> no fixup +.data_arm_lateldrpostconst: + movs r2, r8, lsl #20 @ Get offset + moveq pc, lr @ zero -> no fixup + and r5, r8, #15 << 16 @ Extract 'n' from instruction + ldr r7, [sp, r5, lsr #14] @ Get register 'Rn' + tst r8, #1 << 23 @ Check U bit + subne r7, r7, r2, lsr #20 @ Undo increment + addeq r7, r7, r2, lsr #20 @ Undo decrement + str r7, [sp, r5, lsr #14] @ Put register 'Rn' + mov pc, lr + +.data_arm_lateldrprereg: + tst r8, #1 << 21 @ check writeback bit + moveq pc, lr @ no writeback -> no fixup +.data_arm_lateldrpostreg: + and r7, r8, #15 @ Extract 'm' from instruction + ldr r6, [sp, r7, lsl #2] @ Get register 'Rm' + mov r5, r8, lsr #7 @ get shift count + ands r5, r5, #31 + and r7, r8, #0x70 @ get shift type + orreq r7, r7, #8 @ shift count = 0 + add pc, pc, r7 + nop + + mov r6, r6, lsl r5 @ 0: LSL #!0 + b .data_arm_apply_r6_and_rn + b .data_arm_apply_r6_and_rn @ 1: LSL #0 + nop + b .data_unknown @ 2: MUL? + nop + b .data_unknown @ 3: MUL? + nop + mov r6, r6, lsr r5 @ 4: LSR #!0 + b .data_arm_apply_r6_and_rn + mov r6, r6, lsr #32 @ 5: LSR #32 + b .data_arm_apply_r6_and_rn + b .data_unknown @ 6: MUL? + nop + b .data_unknown @ 7: MUL? + nop + mov r6, r6, asr r5 @ 8: ASR #!0 + b .data_arm_apply_r6_and_rn + mov r6, r6, asr #32 @ 9: ASR #32 + b .data_arm_apply_r6_and_rn + b .data_unknown @ A: MUL? + nop + b .data_unknown @ B: MUL? + nop + mov r6, r6, ror r5 @ C: ROR #!0 + b .data_arm_apply_r6_and_rn + mov r6, r6, rrx @ D: RRX + b .data_arm_apply_r6_and_rn + b .data_unknown @ E: MUL? + nop + b .data_unknown @ F: MUL? /* - * Function: arm6_7_check_bugs (void) - * : arm6_7_proc_init (void) + * Function: arm6_7_proc_init (void) * : arm6_7_proc_fin (void) * * Notes : This processor does not require these */ -ENTRY(cpu_arm6_check_bugs) -ENTRY(cpu_arm7_check_bugs) - mrs ip, cpsr - bic ip, ip, #PSR_F_BIT - msr cpsr, ip - mov pc, lr - ENTRY(cpu_arm6_proc_init) ENTRY(cpu_arm7_proc_init) mov pc, lr @@ -216,17 +186,16 @@ ENTRY(cpu_arm7_proc_fin) ENTRY(cpu_arm6_do_idle) ENTRY(cpu_arm7_do_idle) - mov r0, #-EINVAL mov pc, lr /* - * Function: arm6_7_set_pgd(unsigned long pgd_phys) + * Function: arm6_7_switch_mm(unsigned long pgd_phys) * Params : pgd_phys Physical address of page table * Purpose : Perform a task switch, saving the old processes state, and restoring * the new. */ -ENTRY(cpu_arm6_set_pgd) -ENTRY(cpu_arm7_set_pgd) +ENTRY(cpu_arm6_switch_mm) +ENTRY(cpu_arm7_switch_mm) mov r1, #0 mcr p15, 0, r1, c7, c0, 0 @ flush cache mcr p15, 0, r0, c2, c0, 0 @ update page table ptr @@ -234,17 +203,6 @@ ENTRY(cpu_arm7_set_pgd) mov pc, lr /* - * Function: arm6_flush_pmd(pmdp) - * - * Params : r0 = Address to set - * - * Purpose : Set a PMD and flush it out of any WB cache - */ -ENTRY(cpu_arm6_flush_pmd) -ENTRY(cpu_arm7_flush_pmd) - mov pc, lr - -/* * Function: arm6_7_set_pte(pte_t *ptep, pte_t pte) * Params : r0 = Address to set * : r1 = value to set @@ -324,31 +282,13 @@ __arm7_setup: mov r0, #0 .type arm6_processor_functions, #object ENTRY(arm6_processor_functions) .word cpu_arm6_data_abort - .word cpu_arm6_check_bugs .word cpu_arm6_proc_init .word cpu_arm6_proc_fin .word cpu_arm6_reset .word cpu_arm6_do_idle - - /* cache */ - .word cpu_arm6_cache_clean_invalidate_all - .word cpu_arm6_cache_clean_invalidate_range - - /* dcache */ - .word cpu_arm6_dcache_invalidate_range - .word cpu_arm6_dcache_clean_range - .word cpu_arm6_dcache_clean_page - .word cpu_arm6_dcache_clean_entry - - /* icache */ - .word cpu_arm6_icache_invalidate_range - .word cpu_arm6_icache_invalidate_page - - /* pgtable */ - .word cpu_arm6_set_pgd - .word cpu_arm6_flush_pmd + .word cpu_arm6_dcache_clean_area + .word cpu_arm6_switch_mm .word cpu_arm6_set_pte - .size arm6_processor_functions, . - arm6_processor_functions /* @@ -358,31 +298,13 @@ ENTRY(arm6_processor_functions) .type arm7_processor_functions, #object ENTRY(arm7_processor_functions) .word cpu_arm7_data_abort - .word cpu_arm7_check_bugs .word cpu_arm7_proc_init .word cpu_arm7_proc_fin .word cpu_arm7_reset .word cpu_arm7_do_idle - - /* cache */ - .word cpu_arm7_cache_clean_invalidate_all - .word cpu_arm7_cache_clean_invalidate_range - - /* dcache */ - .word cpu_arm7_dcache_invalidate_range - .word cpu_arm7_dcache_clean_range - .word cpu_arm7_dcache_clean_page - .word cpu_arm7_dcache_clean_entry - - /* icache */ - .word cpu_arm7_icache_invalidate_range - .word cpu_arm7_icache_invalidate_page - - /* pgtable */ - .word cpu_arm7_set_pgd - .word cpu_arm7_flush_pmd + .word cpu_arm7_dcache_clean_area + .word cpu_arm7_switch_mm .word cpu_arm7_set_pte - .size arm7_processor_functions, . - arm7_processor_functions .type cpu_arch_name, #object @@ -409,6 +331,7 @@ __arm6_proc_info: .long arm6_processor_functions .long v3_tlb_fns .long v3_user_fns + .long v3_cache_fns .size __arm6_proc_info, . - __arm6_proc_info .type __arm610_proc_info, #object @@ -424,6 +347,7 @@ __arm610_proc_info: .long arm6_processor_functions .long v3_tlb_fns .long v3_user_fns + .long v3_cache_fns .size __arm610_proc_info, . - __arm610_proc_info .type __arm7_proc_info, #object @@ -439,6 +363,7 @@ __arm7_proc_info: .long arm7_processor_functions .long v3_tlb_fns .long v3_user_fns + .long v3_cache_fns .size __arm7_proc_info, . - __arm7_proc_info .type __arm710_proc_info, #object @@ -454,4 +379,5 @@ __arm710_proc_info: .long arm7_processor_functions .long v3_tlb_fns .long v3_user_fns + .long v3_cache_fns .size __arm710_proc_info, . - __arm710_proc_info --- linux-2.5.68/arch/arm/mm/proc-arm720.S 2003-01-16 18:22:22.000000000 -0800 +++ 25/arch/arm/mm/proc-arm720.S 2003-04-29 20:50:34.000000000 -0700 @@ -38,47 +38,12 @@ #include /* - * Function: arm720_cache_clean_invalidate_all (void) - * : arm720_cache_clean_invalidate_page (unsigned long address, int size, - * int flags) - * - * Params : address Area start address - * : size size of area - * : flags b0 = I cache as well - * - * Purpose : Flush all cache lines - */ -ENTRY(cpu_arm720_cache_clean_invalidate_all) -ENTRY(cpu_arm720_cache_clean_invalidate_range) -ENTRY(cpu_arm720_icache_invalidate_range) -ENTRY(cpu_arm720_icache_invalidate_page) -ENTRY(cpu_arm720_dcache_invalidate_range) - mov r0, #0 - mcr p15, 0, r0, c7, c7, 0 @ flush cache - mov pc, lr - -/* - * These just expect cache lines to be cleaned. Since we have a writethrough - * cache, we never have any dirty cachelines to worry about. - */ -ENTRY(cpu_arm720_dcache_clean_range) -ENTRY(cpu_arm720_dcache_clean_page) -ENTRY(cpu_arm720_dcache_clean_entry) - mov pc, lr - -/* - * Function: arm720_check_bugs (void) - * : arm720_proc_init (void) + * Function: arm720_proc_init (void) * : arm720_proc_fin (void) * * Notes : This processor does not require these */ -ENTRY(cpu_arm720_check_bugs) - mrs ip, cpsr - bic ip, ip, #PSR_F_BIT - msr cpsr, ip - mov pc, lr - +ENTRY(cpu_arm720_dcache_clean_area) ENTRY(cpu_arm720_proc_init) mov pc, lr @@ -102,12 +67,12 @@ ENTRY(cpu_arm720_do_idle) mov pc, lr /* - * Function: arm720_set_pgd(unsigned long pgd_phys) + * Function: arm720_switch_mm(unsigned long pgd_phys) * Params : pgd_phys Physical address of page table * Purpose : Perform a task switch, saving the old process' state and restoring * the new. */ -ENTRY(cpu_arm720_set_pgd) +ENTRY(cpu_arm720_switch_mm) mov r1, #0 mcr p15, 0, r1, c7, c7, 0 @ invalidate cache mcr p15, 0, r0, c2, c0, 0 @ update page table ptr @@ -115,16 +80,6 @@ ENTRY(cpu_arm720_set_pgd) mov pc, lr /* - * Function: arm720_flush_pmd(pmdp) - * - * Params : r0 = Address to set - * - * Purpose : Set a PMD and flush it out of any WB cache - */ -ENTRY(cpu_arm720_flush_pmd) - mov pc, lr - -/* * Function: arm720_set_pte(pte_t *ptep, pte_t pte) * Params : r0 = Address to set * : r1 = value to set @@ -140,7 +95,7 @@ ENTRY(cpu_arm720_set_pte) bic r2, r2, #3 orr r2, r2, #HPTE_TYPE_SMALL - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec? + tst r1, #LPTE_USER @ User? orrne r2, r2, #HPTE_AP_READ tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty? @@ -194,31 +149,13 @@ __arm720_setup: mov r0, #0 .type arm720_processor_functions, #object ENTRY(arm720_processor_functions) .word v4t_late_abort - .word cpu_arm720_check_bugs .word cpu_arm720_proc_init .word cpu_arm720_proc_fin .word cpu_arm720_reset .word cpu_arm720_do_idle - - /* cache */ - .word cpu_arm720_cache_clean_invalidate_all - .word cpu_arm720_cache_clean_invalidate_range - - /* dcache */ - .word cpu_arm720_dcache_invalidate_range - .word cpu_arm720_dcache_clean_range - .word cpu_arm720_dcache_clean_page - .word cpu_arm720_dcache_clean_entry - - /* icache */ - .word cpu_arm720_icache_invalidate_range - .word cpu_arm720_icache_invalidate_page - - /* pgtable */ - .word cpu_arm720_set_pgd - .word cpu_arm720_flush_pmd + .word cpu_arm720_dcache_clean_area + .word cpu_arm720_switch_mm .word cpu_arm720_set_pte - .size arm720_processor_functions, . - arm720_processor_functions .type cpu_arch_name, #object @@ -249,4 +186,5 @@ __arm720_proc_info: .long arm720_processor_functions .long v4_tlb_fns .long v4wt_user_fns + .long v4_cache_fns .size __arm720_proc_info, . - __arm720_proc_info --- linux-2.5.68/arch/arm/mm/proc-arm920.S 2003-02-10 12:24:11.000000000 -0800 +++ 25/arch/arm/mm/proc-arm920.S 2003-04-29 20:50:34.000000000 -0700 @@ -28,41 +28,35 @@ #include #include #include -#include #include #include +#include +#include "proc-macros.S" /* - * This is the maximum size of an area which will be invalidated - * using the single invalidate entry instructions. Anything larger - * than this, and we go for the whole cache. - * - * This value should be chosen such that we choose the cheapest - * alternative. + * The size of one data cache line. */ -#define MAX_AREA_SIZE 16384 +#define CACHE_DLINESIZE 32 /* - * the cache line size of the I and D cache + * The number of data cache segments. */ -#define DCACHELINESIZE 32 -#define ICACHELINESIZE 32 +#define CACHE_DSEGMENTS 8 /* - * and the page size + * The number of lines in a cache segment. */ -#define PAGESIZE 4096 +#define CACHE_DENTRIES 64 - .text /* - * cpu_arm920_check_bugs() + * This is the size at which it becomes more efficient to + * clean the whole cache, rather than using the individual + * cache line maintainence instructions. */ -ENTRY(cpu_arm920_check_bugs) - mrs ip, cpsr - bic ip, ip, #PSR_F_BIT - msr cpsr, ip - mov pc, lr +#define CACHE_DLIMIT 65536 + + .text /* * cpu_arm920_proc_init() */ @@ -76,7 +70,11 @@ ENTRY(cpu_arm920_proc_fin) stmfd sp!, {lr} mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE msr cpsr_c, ip - bl cpu_arm920_cache_clean_invalidate_all +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH + bl arm920_flush_kern_cache_all +#else + bl v4wt_flush_kern_cache_all +#endif mrc p15, 0, r0, c1, c0, 0 @ ctrl register bic r0, r0, #0x1000 @ ...i............ bic r0, r0, #0x000e @ ............wca. @@ -112,249 +110,207 @@ ENTRY(cpu_arm920_do_idle) mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt mov pc, lr -/* ================================= CACHE ================================ */ +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH /* - * cpu_arm920_cache_clean_invalidate_all() + * flush_user_cache_all() * - * clean and invalidate all cache lines - * - * Note: - * 1. we should preserve r0 at all times + * Invalidate all cache entries in a particular address + * space. */ - .align 5 -ENTRY(cpu_arm920_cache_clean_invalidate_all) - mov r2, #1 -cpu_arm920_cache_clean_invalidate_all_r2: - mov ip, #0 -#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH - mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache -#else +ENTRY(arm920_flush_user_cache_all) + /* FALLTHROUGH */ + /* - * 'Clean & Invalidate whole DCache' - * Re-written to use Index Ops. - * Uses registers r1, r3 and ip + * flush_kern_cache_all() + * + * Clean and invalidate the entire cache. */ - mov r1, #7 << 5 @ 8 segments -1: orr r3, r1, #63 << 26 @ 64 entries -2: mcr p15, 0, r3, c7, c14, 2 @ clean & invalidate D index +ENTRY(arm920_flush_kern_cache_all) + mov r2, #VM_EXEC + mov ip, #0 +__flush_whole_cache: + mov r1, #(CACHE_DSEGMENTS - 1) << 5 @ 8 segments +1: orr r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries +2: mcr p15, 0, r3, c7, c14, 2 @ clean+invalidate D index subs r3, r3, #1 << 26 bcs 2b @ entries 63 to 0 subs r1, r1, #1 << 5 bcs 1b @ segments 7 to 0 -#endif - teq r2, #0 + tst r2, #VM_EXEC mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache - mcr p15, 0, ip, c7, c10, 4 @ drain WB + mcrne p15, 0, ip, c7, c10, 4 @ drain WB mov pc, lr /* - * cpu_arm920_cache_clean_invalidate_range(start, end, flags) + * flush_user_cache_range(start, end, flags) * - * clean and invalidate all cache lines associated with this area of memory + * Invalidate a range of cache entries in the specified + * address space. * - * start: Area start address - * end: Area end address - * flags: nonzero for I cache as well - */ - .align 5 -ENTRY(cpu_arm920_cache_clean_invalidate_range) - bic r0, r0, #DCACHELINESIZE - 1 @ && added by PGM - bic r1, r1, #DCACHELINESIZE - 1 @ && added by DHM - sub r3, r1, r0 - cmp r3, #MAX_AREA_SIZE - bgt cpu_arm920_cache_clean_invalidate_all_r2 -1: teq r2, #0 -#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH - mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry - mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry - add r0, r0, #DCACHELINESIZE - mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry - mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry - add r0, r0, #DCACHELINESIZE -#else - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry - mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry - add r0, r0, #DCACHELINESIZE - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry + * - start - start address (inclusive) + * - end - end address (exclusive) + * - flags - vm_flags for address space + */ +ENTRY(arm920_flush_user_cache_range) + mov ip, #0 + sub r3, r1, r0 @ calculate total size + cmp r3, #CACHE_DLIMIT + bhs __flush_whole_cache + +1: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry + tst r2, #VM_EXEC mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry - add r0, r0, #DCACHELINESIZE -#endif + add r0, r0, #CACHE_DLINESIZE cmp r0, r1 - blt 1b - - mcr p15, 0, r1, c7, c10, 4 @ drain WB + blo 1b + tst r2, #VM_EXEC + mcrne p15, 0, ip, c7, c10, 4 @ drain WB mov pc, lr -/* ================================ D-CACHE =============================== */ - /* - * cpu_arm920_dcache_invalidate_range(start, end) + * coherent_kern_range(start, end) * - * throw away all D-cached data in specified region without an obligation - * to write them back. Note however that we must clean the D-cached entries - * around the boundaries if the start and/or end address are not cache - * aligned. + * Ensure coherency between the Icache and the Dcache in the + * region described by start, end. If you have non-snooping + * Harvard caches, you need to implement this function. * - * start: virtual start address - * end: virtual end address + * - start - virtual start address + * - end - virtual end address */ - .align 5 -ENTRY(cpu_arm920_dcache_invalidate_range) -#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH - tst r0, #DCACHELINESIZE - 1 - mcrne p15, 0, r0, c7, c10, 1 @ clean D entry - tst r1, #DCACHELINESIZE - 1 - mcrne p15, 0, r1, c7, c10, 1 @ clean D entry -#endif @ clean D entry - bic r0, r0, #DCACHELINESIZE - 1 - bic r1, r1, #DCACHELINESIZE - 1 -1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry - add r0, r0, #DCACHELINESIZE +ENTRY(arm920_coherent_kern_range) + bic r0, r0, #CACHE_DLINESIZE - 1 +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry + add r0, r0, #CACHE_DLINESIZE cmp r0, r1 - blt 1b + blo 1b + mcr p15, 0, r0, c7, c10, 4 @ drain WB mov pc, lr /* - * cpu_arm920_dcache_clean_range(start, end) + * flush_kern_dcache_page(void *page) * - * For the specified virtual address range, ensure that all caches contain - * clean data, such that peripheral accesses to the physical RAM fetch - * correct data. + * Ensure no D cache aliasing occurs, either with itself or + * the I cache * - * start: virtual start address - * end: virtual end address + * - addr - page aligned address */ - .align 5 -ENTRY(cpu_arm920_dcache_clean_range) -#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH - bic r0, r0, #DCACHELINESIZE - 1 - sub r1, r1, r0 - cmp r1, #MAX_AREA_SIZE - mov r2, #0 - bgt cpu_arm920_cache_clean_invalidate_all_r2 - - bic r1, r1, #DCACHELINESIZE -1 - add r1, r1, #DCACHELINESIZE - -1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry - add r0, r0, #DCACHELINESIZE - subs r1, r1, #DCACHELINESIZE - bpl 1b -#endif - mcr p15, 0, r2, c7, c10, 4 @ drain WB +ENTRY(arm920_flush_kern_dcache_page) + add r1, r0, #PAGE_SZ +1: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache + mcr p15, 0, r0, c7, c10, 4 @ drain WB mov pc, lr /* - * cpu_arm920_dcache_clean_page(page) + * dma_inv_range(start, end) * - * Cleans a single page of dcache so that if we have any future aliased - * mappings, they will be consistent at the time that they are created. + * Invalidate (discard) the specified virtual address range. + * May not write back any entries. If 'start' or 'end' + * are not cache line aligned, those lines must be written + * back. * - * page: virtual address of page to clean from dcache + * - start - virtual start address + * - end - virtual end address * - * Note: - * 1. we don't need to flush the write buffer in this case. - * 2. we don't invalidate the entries since when we write the page - * out to disk, the entries may get reloaded into the cache. + * (same as v4wb) */ - .align 5 -ENTRY(cpu_arm920_dcache_clean_page) -#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH - mov r1, #PAGESIZE -1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry - add r0, r0, #DCACHELINESIZE - mcr p15, 0, r0, c7, c10, 1 @ clean D entry - add r0, r0, #DCACHELINESIZE - subs r1, r1, #2 * DCACHELINESIZE - bne 1b -#endif +ENTRY(arm920_dma_inv_range) + tst r0, #CACHE_DLINESIZE - 1 + bic r0, r0, #CACHE_DLINESIZE - 1 + mcrne p15, 0, r0, c7, c10, 1 @ clean D entry + tst r1, #CACHE_DLINESIZE - 1 + mcrne p15, 0, r1, c7, c10, 1 @ clean D entry +1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + mcr p15, 0, r0, c7, c10, 4 @ drain WB mov pc, lr /* - * cpu_arm920_dcache_clean_entry(addr) + * dma_clean_range(start, end) * - * Clean the specified entry of any caches such that the MMU - * translation fetches will obtain correct data. + * Clean the specified virtual address range. * - * addr: cache-unaligned virtual address + * - start - virtual start address + * - end - virtual end address + * + * (same as v4wb) */ - .align 5 -ENTRY(cpu_arm920_dcache_clean_entry) -#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH - mcr p15, 0, r0, c7, c10, 1 @ clean D entry -#endif +ENTRY(arm920_dma_clean_range) + bic r0, r0, #CACHE_DLINESIZE - 1 +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b mcr p15, 0, r0, c7, c10, 4 @ drain WB mov pc, lr -/* ================================ I-CACHE =============================== */ - /* - * cpu_arm920_icache_invalidate_range(start, end) - * - * invalidate a range of virtual addresses from the Icache + * dma_flush_range(start, end) * - * This is a little misleading, it is not intended to clean out - * the i-cache but to make sure that any data written to the - * range is made consistent. This means that when we execute code - * in that region, everything works as we expect. + * Clean and invalidate the specified virtual address range. * - * This generally means writing back data in the Dcache and - * write buffer and flushing the Icache over that region - * - * start: virtual start address - * end: virtual end address - * - * NOTE: ICACHELINESIZE == DCACHELINESIZE (so we don't need to - * loop twice, once for i-cache, once for d-cache) + * - start - virtual start address + * - end - virtual end address */ - .align 5 -ENTRY(cpu_arm920_icache_invalidate_range) - bic r0, r0, #ICACHELINESIZE - 1 @ Safety check - sub r1, r1, r0 - cmp r1, #MAX_AREA_SIZE - bgt cpu_arm920_cache_clean_invalidate_all_r2 - - bic r1, r1, #ICACHELINESIZE - 1 - add r1, r1, #ICACHELINESIZE - -1: mcr p15, 0, r0, c7, c5, 1 @ Clean I entry - mcr p15, 0, r0, c7, c10, 1 @ Clean D entry - add r0, r0, #ICACHELINESIZE - subs r1, r1, #ICACHELINESIZE - bne 1b - - mov r0, #0 +ENTRY(arm920_dma_flush_range) + bic r0, r0, #CACHE_DLINESIZE - 1 +1: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b mcr p15, 0, r0, c7, c10, 4 @ drain WB mov pc, lr -ENTRY(cpu_arm920_icache_invalidate_page) - mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache +ENTRY(arm920_cache_fns) + .long arm920_flush_kern_cache_all + .long arm920_flush_user_cache_all + .long arm920_flush_user_cache_range + .long arm920_coherent_kern_range + .long arm920_flush_kern_dcache_page + .long arm920_dma_inv_range + .long arm920_dma_clean_range + .long arm920_dma_flush_range + +#endif + + +ENTRY(cpu_arm920_dcache_clean_area) +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #CACHE_DLINESIZE + subs r1, r1, #CACHE_DLINESIZE + bhi 1b mov pc, lr /* =============================== PageTable ============================== */ /* - * cpu_arm920_set_pgd(pgd) + * cpu_arm920_switch_mm(pgd) * * Set the translation base pointer to be as described by pgd. * * pgd: new page tables */ .align 5 -ENTRY(cpu_arm920_set_pgd) +ENTRY(cpu_arm920_switch_mm) mov ip, #0 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH - /* Any reason why we don't use mcr p15, 0, r0, c7, c7, 0 here? --rmk */ mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache #else @ && 'Clean & Invalidate whole DCache' @ && Re-written to use Index Ops. @ && Uses registers r1, r3 and ip - mov r1, #7 << 5 @ 8 segments -1: orr r3, r1, #63 << 26 @ 64 entries + mov r1, #(CACHE_DSEGMENTS - 1) << 5 @ 8 segments +1: orr r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries 2: mcr p15, 0, r3, c7, c14, 2 @ clean & invalidate D index subs r3, r3, #1 << 26 bcs 2b @ entries 63 to 0 @@ -368,28 +324,12 @@ ENTRY(cpu_arm920_set_pgd) mov pc, lr /* - * cpu_arm920_flush_pmd(pmdp) - * - * Set a level 1 translation table entry, and clean it out of - * any caches such that the MMUs can load it correctly. - * - * pmdp: pointer to PMD entry - */ - .align 5 -ENTRY(cpu_arm920_flush_pmd) - mcr p15, 0, r0, c7, c10, 1 @ clean D entry - mcr p15, 0, r0, c7, c10, 4 @ drain WB - mov pc, lr - -/* * cpu_arm920_set_pte(ptep, pte) * * Set a PTE and flush it out */ .align 5 ENTRY(cpu_arm920_set_pte) - tst r0, #2048 - streq r0, [r0, -r0] @ BUG_ON str r1, [r0], #-2048 @ linux version eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY @@ -398,7 +338,7 @@ ENTRY(cpu_arm920_set_pte) bic r2, r2, #3 orr r2, r2, #HPTE_TYPE_SMALL - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec? + tst r1, #LPTE_USER @ User or Exec? orrne r2, r2, #HPTE_AP_READ tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty? @@ -477,31 +417,13 @@ __arm920_setup: .type arm920_processor_functions, #object arm920_processor_functions: .word v4t_early_abort - .word cpu_arm920_check_bugs .word cpu_arm920_proc_init .word cpu_arm920_proc_fin .word cpu_arm920_reset .word cpu_arm920_do_idle - - /* cache */ - .word cpu_arm920_cache_clean_invalidate_all - .word cpu_arm920_cache_clean_invalidate_range - - /* dcache */ - .word cpu_arm920_dcache_invalidate_range - .word cpu_arm920_dcache_clean_range - .word cpu_arm920_dcache_clean_page - .word cpu_arm920_dcache_clean_entry - - /* icache */ - .word cpu_arm920_icache_invalidate_range - .word cpu_arm920_icache_invalidate_page - - /* pgtable */ - .word cpu_arm920_set_pgd - .word cpu_arm920_flush_pmd + .word cpu_arm920_dcache_clean_area + .word cpu_arm920_switch_mm .word cpu_arm920_set_pte - .size arm920_processor_functions, . - arm920_processor_functions .type cpu_arch_name, #object @@ -530,4 +452,9 @@ __arm920_proc_info: .long arm920_processor_functions .long v4wbi_tlb_fns .long v4wb_user_fns +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH + .long arm920_cache_fns +#else + .long v4wt_cache_fns +#endif .size __arm920_proc_info, . - __arm920_proc_info --- linux-2.5.68/arch/arm/mm/proc-arm922.S 2003-02-10 12:24:11.000000000 -0800 +++ 25/arch/arm/mm/proc-arm922.S 2003-04-29 20:50:34.000000000 -0700 @@ -29,41 +29,36 @@ #include #include #include -#include #include #include +#include +#include "proc-macros.S" /* - * This is the maximum size of an area which will be invalidated - * using the single invalidate entry instructions. Anything larger - * than this, and we go for the whole cache. - * - * This value should be chosen such that we choose the cheapest - * alternative. + * The size of one data cache line. */ -#define MAX_AREA_SIZE 8192 +#define CACHE_DLINESIZE 32 /* - * the cache line size of the I and D cache + * The number of data cache segments. */ -#define DCACHELINESIZE 32 -#define ICACHELINESIZE 32 +#define CACHE_DSEGMENTS 4 /* - * and the page size + * The number of lines in a cache segment. */ -#define PAGESIZE 4096 +#define CACHE_DENTRIES 64 - .text /* - * cpu_arm922_check_bugs() + * This is the size at which it becomes more efficient to + * clean the whole cache, rather than using the individual + * cache line maintainence instructions. (I think this should + * be 32768). */ -ENTRY(cpu_arm922_check_bugs) - mrs ip, cpsr - bic ip, ip, #PSR_F_BIT - msr cpsr, ip - mov pc, lr +#define CACHE_DLIMIT 8192 + + .text /* * cpu_arm922_proc_init() */ @@ -77,7 +72,11 @@ ENTRY(cpu_arm922_proc_fin) stmfd sp!, {lr} mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE msr cpsr_c, ip - bl cpu_arm922_cache_clean_invalidate_all +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH + bl arm922_flush_kern_cache_all +#else + bl v4wt_flush_kern_cache_all +#endif mrc p15, 0, r0, c1, c0, 0 @ ctrl register bic r0, r0, #0x1000 @ ...i............ bic r0, r0, #0x000e @ ............wca. @@ -113,249 +112,209 @@ ENTRY(cpu_arm922_do_idle) mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt mov pc, lr -/* ================================= CACHE ================================ */ +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH /* - * cpu_arm922_cache_clean_invalidate_all() + * flush_user_cache_all() * - * clean and invalidate all cache lines - * - * Note: - * 1. we should preserve r0 at all times + * Clean and invalidate all cache entries in a particular + * address space. */ - .align 5 -ENTRY(cpu_arm922_cache_clean_invalidate_all) - mov r2, #1 -cpu_arm922_cache_clean_invalidate_all_r2: - mov ip, #0 -#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH - mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache -#else +ENTRY(arm922_flush_user_cache_all) + /* FALLTHROUGH */ + /* - * 'Clean & Invalidate whole DCache' - * Re-written to use Index Ops. - * Uses registers r1, r3 and ip + * flush_kern_cache_all() + * + * Clean and invalidate the entire cache. */ - mov r1, #3 << 5 @ 4 segments -1: orr r3, r1, #63 << 26 @ 64 entries -2: mcr p15, 0, r3, c7, c14, 2 @ clean & invalidate D index +ENTRY(arm922_flush_kern_cache_all) + mov r2, #VM_EXEC + mov ip, #0 +__flush_whole_cache: + mov r1, #(CACHE_DSEGMENTS - 1) << 5 @ 8 segments +1: orr r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries +2: mcr p15, 0, r3, c7, c14, 2 @ clean+invalidate D index subs r3, r3, #1 << 26 bcs 2b @ entries 63 to 0 subs r1, r1, #1 << 5 bcs 1b @ segments 7 to 0 -#endif - teq r2, #0 + tst r2, #VM_EXEC mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache - mcr p15, 0, ip, c7, c10, 4 @ drain WB + mcrne p15, 0, ip, c7, c10, 4 @ drain WB mov pc, lr /* - * cpu_arm922_cache_clean_invalidate_range(start, end, flags) + * flush_user_cache_range(start, end, flags) * - * clean and invalidate all cache lines associated with this area of memory + * Clean and invalidate a range of cache entries in the + * specified address range. * - * start: Area start address - * end: Area end address - * flags: nonzero for I cache as well - */ - .align 5 -ENTRY(cpu_arm922_cache_clean_invalidate_range) - bic r0, r0, #DCACHELINESIZE - 1 @ && added by PGM - bic r1, r1, #DCACHELINESIZE - 1 @ && added by DHM - sub r3, r1, r0 - cmp r3, #MAX_AREA_SIZE - bgt cpu_arm922_cache_clean_invalidate_all_r2 -1: teq r2, #0 -#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH - mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry - mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry - add r0, r0, #DCACHELINESIZE - mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry - mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry - add r0, r0, #DCACHELINESIZE -#else - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry - mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry - add r0, r0, #DCACHELINESIZE - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry + * - start - start address (inclusive) + * - end - end address (exclusive) + * - flags - vm_flags describing address space + */ +ENTRY(arm922_flush_user_cache_range) + mov ip, #0 + sub r3, r1, r0 @ calculate total size + cmp r3, #CACHE_DLIMIT + bhs __flush_whole_cache + +1: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry + tst r2, #VM_EXEC mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry - add r0, r0, #DCACHELINESIZE -#endif + add r0, r0, #CACHE_DLINESIZE cmp r0, r1 - blt 1b - - mcr p15, 0, r1, c7, c10, 4 @ drain WB + blo 1b + tst r2, #VM_EXEC + mcrne p15, 0, ip, c7, c10, 4 @ drain WB mov pc, lr -/* ================================ D-CACHE =============================== */ - /* - * cpu_arm922_dcache_invalidate_range(start, end) + * coherent_kern_range(start, end) * - * throw away all D-cached data in specified region without an obligation - * to write them back. Note however that we must clean the D-cached entries - * around the boundaries if the start and/or end address are not cache - * aligned. + * Ensure coherency between the Icache and the Dcache in the + * region described by start, end. If you have non-snooping + * Harvard caches, you need to implement this function. * - * start: virtual start address - * end: virtual end address + * - start - virtual start address + * - end - virtual end address */ - .align 5 -ENTRY(cpu_arm922_dcache_invalidate_range) -#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH - tst r0, #DCACHELINESIZE - 1 - mcrne p15, 0, r0, c7, c10, 1 @ clean D entry - tst r1, #DCACHELINESIZE - 1 - mcrne p15, 0, r1, c7, c10, 1 @ clean D entry -#endif @ clean D entry - bic r0, r0, #DCACHELINESIZE - 1 - bic r1, r1, #DCACHELINESIZE - 1 -1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry - add r0, r0, #DCACHELINESIZE +ENTRY(arm922_coherent_kern_range) + bic r0, r0, #CACHE_DLINESIZE - 1 +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry + add r0, r0, #CACHE_DLINESIZE cmp r0, r1 - blt 1b + blo 1b + mcr p15, 0, r0, c7, c10, 4 @ drain WB mov pc, lr /* - * cpu_arm922_dcache_clean_range(start, end) + * flush_kern_dcache_page(void *page) * - * For the specified virtual address range, ensure that all caches contain - * clean data, such that peripheral accesses to the physical RAM fetch - * correct data. + * Ensure no D cache aliasing occurs, either with itself or + * the I cache * - * start: virtual start address - * end: virtual end address + * - addr - page aligned address */ - .align 5 -ENTRY(cpu_arm922_dcache_clean_range) -#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH - bic r0, r0, #DCACHELINESIZE - 1 - sub r1, r1, r0 - cmp r1, #MAX_AREA_SIZE - mov r2, #0 - bgt cpu_arm922_cache_clean_invalidate_all_r2 - - bic r1, r1, #DCACHELINESIZE -1 - add r1, r1, #DCACHELINESIZE - -1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry - add r0, r0, #DCACHELINESIZE - subs r1, r1, #DCACHELINESIZE - bpl 1b -#endif - mcr p15, 0, r2, c7, c10, 4 @ drain WB +ENTRY(arm922_flush_kern_dcache_page) + add r1, r0, #PAGE_SZ +1: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache + mcr p15, 0, r0, c7, c10, 4 @ drain WB mov pc, lr /* - * cpu_arm922_dcache_clean_page(page) + * dma_inv_range(start, end) * - * Cleans a single page of dcache so that if we have any future aliased - * mappings, they will be consistent at the time that they are created. + * Invalidate (discard) the specified virtual address range. + * May not write back any entries. If 'start' or 'end' + * are not cache line aligned, those lines must be written + * back. * - * page: virtual address of page to clean from dcache + * - start - virtual start address + * - end - virtual end address * - * Note: - * 1. we don't need to flush the write buffer in this case. - * 2. we don't invalidate the entries since when we write the page - * out to disk, the entries may get reloaded into the cache. + * (same as v4wb) */ - .align 5 -ENTRY(cpu_arm922_dcache_clean_page) -#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH - mov r1, #PAGESIZE -1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry - add r0, r0, #DCACHELINESIZE - mcr p15, 0, r0, c7, c10, 1 @ clean D entry - add r0, r0, #DCACHELINESIZE - subs r1, r1, #2 * DCACHELINESIZE - bne 1b -#endif +ENTRY(arm922_dma_inv_range) + tst r0, #CACHE_DLINESIZE - 1 + bic r0, r0, #CACHE_DLINESIZE - 1 + mcrne p15, 0, r0, c7, c10, 1 @ clean D entry + tst r1, #CACHE_DLINESIZE - 1 + mcrne p15, 0, r1, c7, c10, 1 @ clean D entry +1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + mcr p15, 0, r0, c7, c10, 4 @ drain WB mov pc, lr /* - * cpu_arm922_dcache_clean_entry(addr) + * dma_clean_range(start, end) + * + * Clean the specified virtual address range. * - * Clean the specified entry of any caches such that the MMU - * translation fetches will obtain correct data. + * - start - virtual start address + * - end - virtual end address * - * addr: cache-unaligned virtual address + * (same as v4wb) */ - .align 5 -ENTRY(cpu_arm922_dcache_clean_entry) -#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH - mcr p15, 0, r0, c7, c10, 1 @ clean D entry -#endif +ENTRY(arm922_dma_clean_range) + bic r0, r0, #CACHE_DLINESIZE - 1 +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b mcr p15, 0, r0, c7, c10, 4 @ drain WB mov pc, lr -/* ================================ I-CACHE =============================== */ - /* - * cpu_arm922_icache_invalidate_range(start, end) - * - * invalidate a range of virtual addresses from the Icache - * - * This is a little misleading, it is not intended to clean out - * the i-cache but to make sure that any data written to the - * range is made consistent. This means that when we execute code - * in that region, everything works as we expect. + * dma_flush_range(start, end) * - * This generally means writing back data in the Dcache and - * write buffer and flushing the Icache over that region + * Clean and invalidate the specified virtual address range. * - * start: virtual start address - * end: virtual end address - * - * NOTE: ICACHELINESIZE == DCACHELINESIZE (so we don't need to - * loop twice, once for i-cache, once for d-cache) + * - start - virtual start address + * - end - virtual end address */ - .align 5 -ENTRY(cpu_arm922_icache_invalidate_range) - bic r0, r0, #ICACHELINESIZE - 1 @ Safety check - sub r1, r1, r0 - cmp r1, #MAX_AREA_SIZE - bgt cpu_arm922_cache_clean_invalidate_all_r2 - - bic r1, r1, #ICACHELINESIZE - 1 - add r1, r1, #ICACHELINESIZE - -1: mcr p15, 0, r0, c7, c5, 1 @ Clean I entry - mcr p15, 0, r0, c7, c10, 1 @ Clean D entry - add r0, r0, #ICACHELINESIZE - subs r1, r1, #ICACHELINESIZE - bne 1b - - mov r0, #0 +ENTRY(arm922_dma_flush_range) + bic r0, r0, #CACHE_DLINESIZE - 1 +1: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b mcr p15, 0, r0, c7, c10, 4 @ drain WB mov pc, lr -ENTRY(cpu_arm922_icache_invalidate_page) - mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache +ENTRY(arm922_cache_fns) + .long arm922_flush_kern_cache_all + .long arm922_flush_user_cache_all + .long arm922_flush_user_cache_range + .long arm922_coherent_kern_range + .long arm922_flush_kern_dcache_page + .long arm922_dma_inv_range + .long arm922_dma_clean_range + .long arm922_dma_flush_range + +#endif + + +ENTRY(cpu_arm922_dcache_clean_area) +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #CACHE_DLINESIZE + subs r1, r1, #CACHE_DLINESIZE + bhi 1b +#endif mov pc, lr /* =============================== PageTable ============================== */ /* - * cpu_arm922_set_pgd(pgd) + * cpu_arm922_switch_mm(pgd) * * Set the translation base pointer to be as described by pgd. * * pgd: new page tables */ .align 5 -ENTRY(cpu_arm922_set_pgd) +ENTRY(cpu_arm922_switch_mm) mov ip, #0 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH - /* Any reason why we don't use mcr p15, 0, r0, c7, c7, 0 here? --rmk */ mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache #else @ && 'Clean & Invalidate whole DCache' @ && Re-written to use Index Ops. @ && Uses registers r1, r3 and ip - mov r1, #3 << 5 @ 4 segments -1: orr r3, r1, #63 << 26 @ 64 entries + mov r1, #(CACHE_DSEGMENTS - 1) << 5 @ 4 segments +1: orr r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries 2: mcr p15, 0, r3, c7, c14, 2 @ clean & invalidate D index subs r3, r3, #1 << 26 bcs 2b @ entries 63 to 0 @@ -369,20 +328,6 @@ ENTRY(cpu_arm922_set_pgd) mov pc, lr /* - * cpu_arm922_flush_pmd(pmdp) - * - * Set a level 1 translation table entry, and clean it out of - * any caches such that the MMUs can load it correctly. - * - * pmdp: pointer to PMD entry - */ - .align 5 -ENTRY(cpu_arm922_flush_pmd) - mcr p15, 0, r0, c7, c10, 1 @ clean D entry - mcr p15, 0, r0, c7, c10, 4 @ drain WB - mov pc, lr - -/* * cpu_arm922_set_pte(ptep, pte) * * Set a PTE and flush it out @@ -397,7 +342,7 @@ ENTRY(cpu_arm922_set_pte) bic r2, r2, #3 orr r2, r2, #HPTE_TYPE_SMALL - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec? + tst r1, #LPTE_USER @ User? orrne r2, r2, #HPTE_AP_READ tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty? @@ -476,31 +421,13 @@ __arm922_setup: .type arm922_processor_functions, #object arm922_processor_functions: .word v4t_early_abort - .word cpu_arm922_check_bugs .word cpu_arm922_proc_init .word cpu_arm922_proc_fin .word cpu_arm922_reset .word cpu_arm922_do_idle - - /* cache */ - .word cpu_arm922_cache_clean_invalidate_all - .word cpu_arm922_cache_clean_invalidate_range - - /* dcache */ - .word cpu_arm922_dcache_invalidate_range - .word cpu_arm922_dcache_clean_range - .word cpu_arm922_dcache_clean_page - .word cpu_arm922_dcache_clean_entry - - /* icache */ - .word cpu_arm922_icache_invalidate_range - .word cpu_arm922_icache_invalidate_page - - /* pgtable */ - .word cpu_arm922_set_pgd - .word cpu_arm922_flush_pmd + .word cpu_arm922_dcache_clean_area + .word cpu_arm922_switch_mm .word cpu_arm922_set_pte - .size arm922_processor_functions, . - arm922_processor_functions .type cpu_arch_name, #object @@ -529,4 +456,9 @@ __arm922_proc_info: .long arm922_processor_functions .long v4wbi_tlb_fns .long v4wb_user_fns +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH + .long arm922_cache_fns +#else + .long v4wt_cache_fns +#endif .size __arm922_proc_info, . - __arm922_proc_info --- linux-2.5.68/arch/arm/mm/proc-arm926.S 2003-02-10 12:24:11.000000000 -0800 +++ 25/arch/arm/mm/proc-arm926.S 2003-04-29 20:50:34.000000000 -0700 @@ -28,9 +28,10 @@ #include #include #include -#include #include #include +#include +#include "proc-macros.S" /* * This is the maximum size of an area which will be invalidated @@ -40,30 +41,14 @@ * This value should be chosen such that we choose the cheapest * alternative. */ -#define MAX_AREA_SIZE 16384 +#define CACHE_DLIMIT 16384 /* * the cache line size of the I and D cache */ -#define DCACHELINESIZE 32 -#define ICACHELINESIZE 32 - -/* - * and the page size - */ -#define PAGESIZE 4096 +#define CACHE_DLINESIZE 32 .text - -/* - * cpu_arm926_check_bugs() - */ -ENTRY(cpu_arm926_check_bugs) - mrs ip, cpsr - bic ip, ip, #PSR_F_BIT - msr cpsr, ip - mov pc, lr - /* * cpu_arm926_proc_init() */ @@ -77,17 +62,17 @@ ENTRY(cpu_arm926_proc_fin) stmfd sp!, {lr} mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE msr cpsr_c, ip - bl cpu_arm926_cache_clean_invalidate_all + bl arm926_flush_kern_cache_all mrc p15, 0, r0, c1, c0, 0 @ ctrl register - bic r0, r0, #0x1000 @ ...i............ - bic r0, r0, #0x000e @ ............wca. + bic r0, r0, #0x1000 @ ...i............ + bic r0, r0, #0x000e @ ............wca. mcr p15, 0, r0, c1, c0, 0 @ disable caches ldmfd sp!, {pc} /* * cpu_arm926_reset(loc) * - * Perform a soft reset of the system. Put the CPU into the + * Perform a soft reset of the system. Put the CPU into the * same state as it would be if it had been reset, and branch * to what would be the reset vector. * @@ -100,243 +85,236 @@ ENTRY(cpu_arm926_reset) mcr p15, 0, ip, c7, c10, 4 @ drain WB mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs mrc p15, 0, ip, c1, c0, 0 @ ctrl register - bic ip, ip, #0x000f @ ............wcam - bic ip, ip, #0x1100 @ ...i...s........ + bic ip, ip, #0x000f @ ............wcam + bic ip, ip, #0x1100 @ ...i...s........ mcr p15, 0, ip, c1, c0, 0 @ ctrl register mov pc, r0 /* * cpu_arm926_do_idle() + * + * Called with IRQs disabled */ - .align 5 + .align 10 ENTRY(cpu_arm926_do_idle) + mov r0, #0 + mrc p15, 0, r1, c1, c0, 0 @ Read control register + mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer + bic r2, r1, #1 << 12 + mcr p15, 0, r2, c1, c0, 0 @ Disable I cache mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt + mcr p15, 0, r1, c1, c0, 0 @ Restore ICache enable mov pc, lr -/* ================================= CACHE ================================ */ - - /* - * cpu_arm926_cache_clean_invalidate_all() + * flush_user_cache_all() * - * clean and invalidate all cache lines + * Clean and invalidate all cache entries in a particular + * address space. + */ +ENTRY(arm926_flush_user_cache_all) + /* FALLTHROUGH */ + +/* + * flush_kern_cache_all() * - * Note: - * 1. we should preserve r0 at all times + * Clean and invalidate the entire cache. */ - .align 5 -ENTRY(cpu_arm926_cache_clean_invalidate_all) - mov r2, #1 -cpu_arm926_cache_clean_invalidate_all_r2: +ENTRY(arm926_flush_kern_cache_all) + mov r2, #VM_EXEC mov ip, #0 +__flush_whole_cache: #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache #else 1: mrc p15, 0, r15, c7, c14, 3 @ test,clean,invalidate bne 1b #endif - teq r2, #0 + tst r2, #VM_EXEC mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache - mcr p15, 0, ip, c7, c10, 4 @ drain WB + mcrne p15, 0, ip, c7, c10, 4 @ drain WB mov pc, lr /* - * cpu_arm926_cache_clean_invalidate_range(start, end, flags) + * flush_user_cache_range(start, end, flags) * - * clean and invalidate all cache lines associated with this area of memory + * Clean and invalidate a range of cache entries in the + * specified address range. * - * This is a little misleading, it is not intended to clean out - * the i-cache but to make sure that any data written to the - * range is made consistent. This means that when we execute code - * in that region, everything works as we expect. - * - * This generally means writing back data in the Dcache and - * write buffer and flushing the Icache over that region - * start: Area start address - * end: Area end address - * flags: nonzero for I cache as well + * - start - start address (inclusive) + * - end - end address (exclusive) + * - flags - vm_flags describing address space */ - .align 5 -ENTRY(cpu_arm926_cache_clean_invalidate_range) - bic r0, r0, #DCACHELINESIZE - 1 @ && added by PGM - bic r1, r1, #DCACHELINESIZE - 1 @ && added by DHM - sub r3, r1, r0 - cmp r3, #MAX_AREA_SIZE - bgt cpu_arm926_cache_clean_invalidate_all_r2 - -1: teq r2, #0 +ENTRY(arm926_flush_user_cache_range) + mov ip, #0 + sub r3, r1, r0 @ calculate total size + cmp r3, #CACHE_DLIMIT + bgt __flush_whole_cache +1: tst r2, #VM_EXEC #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry - add r0, r0, #DCACHELINESIZE + add r0, r0, #CACHE_DLINESIZE mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry - add r0, r0, #DCACHELINESIZE + add r0, r0, #CACHE_DLINESIZE #else mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry - add r0, r0, #DCACHELINESIZE + add r0, r0, #CACHE_DLINESIZE mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry - add r0, r0, #DCACHELINESIZE + add r0, r0, #CACHE_DLINESIZE #endif - cmp r0, r1 - blt 1b - - mcr p15, 0, r1, c7, c10, 4 @ drain WB - + blo 1b + tst r2, #VM_EXEC + mcrne p15, 0, ip, c7, c10, 4 @ drain WB mov pc, lr -/* ================================ D-CACHE =============================== */ - /* - * cpu_arm926_dcache_invalidate_range(start, end) + * coherent_kern_range(start, end) * - * throw away all D-cached data in specified region without an obligation - * to write them back. Note however that we must clean the D-cached entries - * around the boundaries if the start and/or end address are not cache - * aligned. + * Ensure coherency between the Icache and the Dcache in the + * region described by start, end. If you have non-snooping + * Harvard caches, you need to implement this function. * - * start: virtual start address - * end: virtual end address + * - start - virtual start address + * - end - virtual end address */ - .align 5 -ENTRY(cpu_arm926_dcache_invalidate_range) -#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH - tst r0, #DCACHELINESIZE - 1 - mcrne p15, 0, r0, c7, c10, 1 @ clean D entry - tst r1, #DCACHELINESIZE - 1 - mcrne p15, 0, r1, c7, c10, 1 -#endif @ clean D entry - bic r0, r0, #DCACHELINESIZE - 1 - bic r1, r1, #DCACHELINESIZE - 1 -1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry - add r0, r0, #DCACHELINESIZE +ENTRY(arm926_coherent_kern_range) + bic r0, r0, #CACHE_DLINESIZE - 1 +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry + add r0, r0, #CACHE_DLINESIZE cmp r0, r1 - blt 1b + blo 1b + mcr p15, 0, r0, c7, c10, 4 @ drain WB mov pc, lr /* - * cpu_arm926_dcache_clean_range(start, end) + * flush_kern_dcache_page(void *page) * - * For the specified virtual address range, ensure that all caches contain - * clean data, such that peripheral accesses to the physical RAM fetch - * correct data. + * Ensure no D cache aliasing occurs, either with itself or + * the I cache * - * start: virtual start address - * end: virtual end address + * - addr - page aligned address */ - .align 5 -ENTRY(cpu_arm926_dcache_clean_range) -#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH - bic r0, r0, #DCACHELINESIZE - 1 - sub r1, r1, r0 - cmp r1, #MAX_AREA_SIZE - mov r2, #0 - bgt cpu_arm926_cache_clean_invalidate_all_r2 - - bic r1, r1, #DCACHELINESIZE -1 - add r1, r1, #DCACHELINESIZE - -1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry - add r0, r0, #DCACHELINESIZE - subs r1, r1, #DCACHELINESIZE - bpl 1b -#endif - mcr p15, 0, r2, c7, c10, 4 @ drain WB +ENTRY(arm926_flush_kern_dcache_page) + add r1, r0, #PAGE_SZ +1: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache + mcr p15, 0, r0, c7, c10, 4 @ drain WB mov pc, lr /* - * cpu_arm926_dcache_clean_page(page) + * dma_inv_range(start, end) * - * Cleans a single page of dcache so that if we have any future aliased - * mappings, they will be consistent at the time that they are created. + * Invalidate (discard) the specified virtual address range. + * May not write back any entries. If 'start' or 'end' + * are not cache line aligned, those lines must be written + * back. * - * page: virtual address of page to clean from dcache + * - start - virtual start address + * - end - virtual end address * - * Note: - * 1. we don't need to flush the write buffer in this case. - * 2. we don't invalidate the entries since when we write the page - * out to disk, the entries may get reloaded into the cache. + * (same as v4wb) */ - .align 5 -ENTRY(cpu_arm926_dcache_clean_page) +ENTRY(arm926_dma_inv_range) #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH - mov r1, #PAGESIZE -1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry - add r0, r0, #DCACHELINESIZE - mcr p15, 0, r0, c7, c10, 1 @ clean D entry - add r0, r0, #DCACHELINESIZE - subs r1, r1, #2 * DCACHELINESIZE - bne 1b + tst r0, #CACHE_DLINESIZE - 1 + mcrne p15, 0, r0, c7, c10, 1 @ clean D entry + tst r1, #CACHE_DLINESIZE - 1 + mcrne p15, 0, r1, c7, c10, 1 @ clean D entry #endif + bic r0, r0, #CACHE_DLINESIZE - 1 +1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + mcr p15, 0, r0, c7, c10, 4 @ drain WB mov pc, lr /* - * cpu_arm926_dcache_clean_entry(addr) + * dma_clean_range(start, end) * - * Clean the specified entry of any caches such that the MMU - * translation fetches will obtain correct data. + * Clean the specified virtual address range. * - * addr: cache-unaligned virtual address + * - start - virtual start address + * - end - virtual end address + * + * (same as v4wb) */ - .align 5 -ENTRY(cpu_arm926_dcache_clean_entry) +ENTRY(arm926_dma_clean_range) #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH - mcr p15, 0, r0, c7, c10, 1 @ clean D entry + bic r0, r0, #CACHE_DLINESIZE - 1 +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b #endif mcr p15, 0, r0, c7, c10, 4 @ drain WB mov pc, lr -/* ================================ I-CACHE =============================== */ - /* - * cpu_arm926_icache_invalidate_range(start, end) + * dma_flush_range(start, end) * - * invalidate a range of virtual addresses from the Icache + * Clean and invalidate the specified virtual address range. * - * start: virtual start address - * end: virtual end address + * - start - virtual start address + * - end - virtual end address */ - .align 5 -ENTRY(cpu_arm926_icache_invalidate_range) - bic r0, r0, #DCACHELINESIZE - 1 @ Safety check - sub r1, r1, r0 - cmp r1, #MAX_AREA_SIZE - bgt cpu_arm926_cache_clean_invalidate_all_r2 - - bic r1, r1, #DCACHELINESIZE - 1 - add r1, r1, #DCACHELINESIZE - -1: mcr p15, 0, r0, c7, c5, 1 @ clean I entries - add r0, r0, #DCACHELINESIZE - subs r1, r1, #DCACHELINESIZE - bne 1b - - mov r0, #0 +ENTRY(arm926_dma_flush_range) + bic r0, r0, #CACHE_DLINESIZE - 1 +1: +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH + mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry +#else + mcr p15, 0, r0, c7, c10, 1 @ clean D entry +#endif + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b mcr p15, 0, r0, c7, c10, 4 @ drain WB mov pc, lr -ENTRY(cpu_arm926_icache_invalidate_page) - mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache - mov pc, lr +ENTRY(arm926_cache_fns) + .long arm926_flush_kern_cache_all + .long arm926_flush_user_cache_all + .long arm926_flush_user_cache_range + .long arm926_coherent_kern_range + .long arm926_flush_kern_dcache_page + .long arm926_dma_inv_range + .long arm926_dma_clean_range + .long arm926_dma_flush_range +ENTRY(cpu_arm926_dcache_clean_area) +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #CACHE_DLINESIZE + subs r1, r1, #CACHE_DLINESIZE + bhi 1b +#endif + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr /* =============================== PageTable ============================== */ /* - * cpu_arm926_set_pgd(pgd) + * cpu_arm926_switch_mm(pgd) * * Set the translation base pointer to be as described by pgd. * * pgd: new page tables */ .align 5 -ENTRY(cpu_arm926_set_pgd) +ENTRY(cpu_arm926_switch_mm) mov ip, #0 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH - /* Any reason why we don't use mcr p15, 0, r0, c7, c7, 0 here? --rmk */ mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache #else @ && 'Clean & Invalidate whole DCache' @@ -350,22 +328,6 @@ ENTRY(cpu_arm926_set_pgd) mov pc, lr /* - * cpu_arm926_flush_pmd(pmdp) - * - * Set a level 1 translation table entry, and clean it out of - * any caches such that the MMUs can load it correctly. - * - * pmdp: pointer to PMD entry - */ - .align 5 -ENTRY(cpu_arm926_flush_pmd) -#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH - mcr p15, 0, r0, c7, c10, 1 @ clean D entry -#endif - mcr p15, 0, r0, c7, c10, 4 @ drain WB - mov pc, lr - -/* * cpu_arm926_set_pte(ptep, pte) * * Set a PTE and flush it out @@ -380,7 +342,7 @@ ENTRY(cpu_arm926_set_pte) bic r2, r2, #3 orr r2, r2, #HPTE_TYPE_SMALL - tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec? + tst r1, #LPTE_USER @ User? orrne r2, r2, #HPTE_AP_READ tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty? @@ -447,21 +409,21 @@ __arm926_setup: bic r0, r0, #0x0e00 bic r0, r0, #0x0002 bic r0, r0, #0x000c - bic r0, r0, #0x1000 @ ...0 000. .... 000. + bic r0, r0, #0x1000 @ ...0 000. .... 000. /* * Turn on what we want */ orr r0, r0, #0x0031 - orr r0, r0, #0x2100 @ ..1. ...1 ..11 ...1 + orr r0, r0, #0x2100 @ ..1. ...1 ..11 ...1 #ifdef CONFIG_CPU_CACHE_ROUND_ROBIN - orr r0, r0, #0x4000 @ .1.. .... .... .... + orr r0, r0, #0x4000 @ .1.. .... .... .... #endif #ifndef CONFIG_CPU_DCACHE_DISABLE - orr r0, r0, #0x0004 @ .... .... .... .1.. + orr r0, r0, #0x0004 @ .... .... .... .1.. #endif #ifndef CONFIG_CPU_ICACHE_DISABLE - orr r0, r0, #0x1000 @ ...1 .... .... .... + orr r0, r0, #0x1000 @ ...1 .... .... .... #endif mov pc, lr @@ -474,31 +436,13 @@ __arm926_setup: .type arm926_processor_functions, #object arm926_processor_functions: .word v5tej_early_abort - .word cpu_arm926_check_bugs .word cpu_arm926_proc_init .word cpu_arm926_proc_fin .word cpu_arm926_reset .word cpu_arm926_do_idle - - /* cache */ - .word cpu_arm926_cache_clean_invalidate_all - .word cpu_arm926_cache_clean_invalidate_range - - /* dcache */ - .word cpu_arm926_dcache_invalidate_range - .word cpu_arm926_dcache_clean_range - .word cpu_arm926_dcache_clean_page - .word cpu_arm926_dcache_clean_entry - - /* icache */ - .word cpu_arm926_icache_invalidate_range - .word cpu_arm926_icache_invalidate_page - - /* pgtable */ - .word cpu_arm926_set_pgd - .word cpu_arm926_flush_pmd + .word cpu_arm926_dcache_clean_area + .word cpu_arm926_switch_mm .word cpu_arm926_set_pte - .size arm926_processor_functions, . - arm926_processor_functions .type cpu_arch_name, #object @@ -522,10 +466,10 @@ __arm926_proc_info: b __arm926_setup .long cpu_arch_name .long cpu_elf_name - .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | \ - HWCAP_FAST_MULT | HWCAP_JAVA + .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_FAST_MULT | HWCAP_JAVA .long cpu_arm926_name .long arm926_processor_functions .long v4wbi_tlb_fns .long v4wb_user_fns + .long arm926_cache_fns .size __arm926_proc_info, . - __arm926_proc_info --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25/arch/arm/mm/proc-sa1100.S 2003-04-29 20:50:34.000000000 -0700 @@ -0,0 +1,297 @@ +/* + * linux/arch/arm/mm/proc-sa110.S + * + * Copyright (C) 1997-2002 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * MMU functions for SA110 + * + * These are the low level assembler for performing cache and TLB + * functions on the StrongARM-1100 and StrongARM-1110. + * + * Note that SA1100 and SA1110 share everything but their name and CPU ID. + * + * 12-jun-2000, Erik Mouw (J.A.K.Mouw@its.tudelft.nl): + * Flush the read buffer at context switches + */ +#include +#include +#include +#include +#include +#include +#include + +/* + * the cache line size of the I and D cache + */ +#define DCACHELINESIZE 32 +#define FLUSH_OFFSET 32768 + + .macro flush_1100_dcache rd, ra, re + ldr \rd, =flush_base + ldr \ra, [\rd] + eor \ra, \ra, #FLUSH_OFFSET + str \ra, [\rd] + add \re, \ra, #8192 @ only necessary for 8k +1001: ldr \rd, [\ra], #DCACHELINESIZE + teq \re, \ra + bne 1001b +#ifdef FLUSH_BASE_MINICACHE + add \ra, \ra, #FLUSH_BASE_MINICACHE - FLUSH_BASE + add \re, \ra, #512 @ only 512 bytes +1002: ldr \rd, [\ra], #DCACHELINESIZE + teq \re, \ra + bne 1002b +#endif + .endm + + .data +flush_base: + .long FLUSH_BASE + .text + + __INIT + +/* + * cpu_sa1100_proc_init() + */ +ENTRY(cpu_sa1100_proc_init) + mov r0, #0 + mcr p15, 0, r0, c15, c1, 2 @ Enable clock switching + mcr p15, 0, r0, c9, c0, 5 @ Allow read-buffer operations from userland + mov pc, lr + + .previous + +/* + * cpu_sa1100_proc_fin() + * + * Prepare the CPU for reset: + * - Disable interrupts + * - Clean and turn off caches. + */ +ENTRY(cpu_sa1100_proc_fin) + stmfd sp!, {lr} + mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE + msr cpsr_c, ip + flush_1100_dcache r0, r1, r2 @ clean caches + mov r0, #0 + mcr p15, 0, r0, c15, c2, 2 @ Disable clock switching + mrc p15, 0, r0, c1, c0, 0 @ ctrl register + bic r0, r0, #0x1000 @ ...i............ + bic r0, r0, #0x000e @ ............wca. + mcr p15, 0, r0, c1, c0, 0 @ disable caches + ldmfd sp!, {pc} + +/* + * cpu_sa1100_reset(loc) + * + * Perform a soft reset of the system. Put the CPU into the + * same state as it would be if it had been reset, and branch + * to what would be the reset vector. + * + * loc: location to jump to for soft reset + */ + .align 5 +ENTRY(cpu_sa1100_reset) + mov ip, #0 + mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches + mcr p15, 0, ip, c7, c10, 4 @ drain WB + mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs + mrc p15, 0, ip, c1, c0, 0 @ ctrl register + bic ip, ip, #0x000f @ ............wcam + bic ip, ip, #0x1100 @ ...i...s........ + mcr p15, 0, ip, c1, c0, 0 @ ctrl register + mov pc, r0 + +/* + * cpu_sa1100_do_idle(type) + * + * Cause the processor to idle + * + * type: call type: + * 0 = slow idle + * 1 = fast idle + * 2 = switch to slow processor clock + * 3 = switch to fast processor clock + */ + .align 5 +ENTRY(cpu_sa1100_do_idle) + mov r0, r0 @ 4 nop padding + mov r0, r0 + mov r0, r0 + mov r0, r0 @ 4 nop padding + mov r0, r0 + mov r0, r0 + mov r0, #0 + ldr r1, =UNCACHEABLE_ADDR @ ptr to uncacheable address + @ --- aligned to a cache line + mcr p15, 0, r0, c15, c2, 2 @ disable clock switching + ldr r1, [r1, #0] @ force switch to MCLK + mcr p15, 0, r0, c15, c8, 2 @ wait for interrupt + mov r0, r0 @ safety + mcr p15, 0, r0, c15, c1, 2 @ enable clock switching + mov pc, lr + +/* ================================= CACHE ================================ */ + +/* + * cpu_sa1100_dcache_clean_area(addr,sz) + * + * Clean the specified entry of any caches such that the MMU + * translation fetches will obtain correct data. + * + * addr: cache-unaligned virtual address + */ + .align 5 +ENTRY(cpu_sa1100_dcache_clean_area) +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #DCACHELINESIZE + subs r1, r1, #DCACHELINESIZE + bhi 1b + mov pc, lr + +/* =============================== PageTable ============================== */ + +/* + * cpu_sa1100_switch_mm(pgd) + * + * Set the translation base pointer to be as described by pgd. + * + * pgd: new page tables + */ + .align 5 +ENTRY(cpu_sa1100_switch_mm) + flush_1100_dcache r3, ip, r1 + mov ip, #0 + mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache + mcr p15, 0, ip, c9, c0, 0 @ invalidate RB + mcr p15, 0, ip, c7, c10, 4 @ drain WB + mcr p15, 0, r0, c2, c0, 0 @ load page table pointer + mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs + mov pc, lr + +/* + * cpu_sa1100_set_pte(ptep, pte) + * + * Set a PTE and flush it out + */ + .align 5 +ENTRY(cpu_sa1100_set_pte) + str r1, [r0], #-2048 @ linux version + + eor r1, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY + + bic r2, r1, #0xff0 + bic r2, r2, #3 + orr r2, r2, #PTE_TYPE_SMALL + + tst r1, #L_PTE_USER @ User or Exec? + orrne r2, r2, #PTE_SMALL_AP_URO_SRW + + tst r1, #L_PTE_WRITE | L_PTE_DIRTY @ Write and Dirty? + orreq r2, r2, #PTE_SMALL_AP_UNO_SRW + + tst r1, #L_PTE_PRESENT | L_PTE_YOUNG @ Present and Young? + movne r2, #0 + + str r2, [r0] @ hardware version + mov r0, r0 + mcr p15, 0, r0, c7, c10, 1 @ clean D entry + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + + +cpu_sa1100_name: + .asciz "StrongARM-1100" +cpu_sa1110_name: + .asciz "StrongARM-1110" + .align + + __INIT + +__sa1100_setup: + mov r10, #0 + mcr p15, 0, r10, c7, c7 @ invalidate I,D caches on v4 + mcr p15, 0, r10, c7, c10, 4 @ drain write buffer on v4 + mcr p15, 0, r10, c8, c7 @ invalidate I,D TLBs on v4 + mov r0, #0x1f @ Domains 0, 1 = client + mcr p15, 0, r0, c3, c0 @ load domain access register + mcr p15, 0, r4, c2, c0 @ load page table pointer + mrc p15, 0, r0, c1, c0 @ get control register v4 + bic r0, r0, #0x0e00 @ ..VI ZFRS BLDP WCAM + bic r0, r0, #0x0002 @ .... 000. .... ..0. + orr r0, r0, #0x003d + orr r0, r0, #0x3100 @ ..11 ...1 ..11 11.1 + mov pc, lr + + .text + +/* + * Purpose : Function pointers used to access above functions - all calls + * come through these + */ + +/* + * SA1100 and SA1110 share the same function calls + */ + .type sa1100_processor_functions, #object +ENTRY(sa1100_processor_functions) + .word v4_early_abort + .word cpu_sa1100_proc_init + .word cpu_sa1100_proc_fin + .word cpu_sa1100_reset + .word cpu_sa1100_do_idle + .word cpu_sa1100_dcache_clean_area + .word cpu_sa1100_switch_mm + .word cpu_sa1100_set_pte + .size sa1100_processor_functions, . - sa1100_processor_functions + + .type cpu_arch_name, #object +cpu_arch_name: + .asciz "armv4" + .size cpu_arch_name, . - cpu_arch_name + + .type cpu_elf_name, #object +cpu_elf_name: + .asciz "v4" + .size cpu_elf_name, . - cpu_elf_name + .align + + .section ".proc.info", #alloc, #execinstr + + .type __sa1100_proc_info,#object +__sa1100_proc_info: + .long 0x4401a110 + .long 0xfffffff0 + .long 0x00000c0e + b __sa1100_setup + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT | HWCAP_FAST_MULT + .long cpu_sa1100_name + .long sa1100_processor_functions + .long v4wb_tlb_fns + .long v4_mc_user_fns + .long v4wb_cache_fns + .size __sa1100_proc_info, . - __sa1100_proc_info + + .type __sa1110_proc_info,#object +__sa1110_proc_info: + .long 0x6901b110 + .long 0xfffffff0 + .long 0x00000c0e + b __sa1100_setup + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT | HWCAP_FAST_MULT + .long cpu_sa1110_name + .long sa1100_processor_functions + .long v4wb_tlb_fns + .long v4_mc_user_fns + .long v4wb_cache_fns + .size __sa1110_proc_info, . - __sa1110_proc_info --- linux-2.5.68/arch/arm/mm/proc-sa110.S 2003-01-16 18:22:08.000000000 -0800 +++ 25/arch/arm/mm/proc-sa110.S 2003-04-29 20:50:34.000000000 -0700 @@ -10,12 +10,7 @@ * MMU functions for SA110 * * These are the low level assembler for performing cache and TLB - * functions on the StrongARM-110, StrongARM-1100 and StrongARM-1110. - * - * Note that SA1100 and SA1110 share everything but their name and CPU ID. - * - * 12-jun-2000, Erik Mouw (J.A.K.Mouw@its.tudelft.nl): - * Flush the read buffer at context switches + * functions on the StrongARM-110. */ #include #include @@ -25,71 +20,32 @@ #include #include -/* This is the maximum size of an area which will be flushed. If the area - * is larger than this, then we flush the whole cache - */ -#define MAX_AREA_SIZE 32768 - /* * the cache line size of the I and D cache */ #define DCACHELINESIZE 32 - -/* - * and the page size - */ -#define PAGESIZE 4096 - #define FLUSH_OFFSET 32768 - .macro flush_110_dcache rd, ra, re - ldr \rd, =flush_base - ldr \ra, [\rd] - eor \ra, \ra, #FLUSH_OFFSET - str \ra, [\rd] - add \re, \ra, #16384 @ only necessary for 16k -1001: ldr \rd, [\ra], #DCACHELINESIZE - teq \re, \ra - bne 1001b - .endm - - .macro flush_1100_dcache rd, ra, re - ldr \rd, =flush_base - ldr \ra, [\rd] - eor \ra, \ra, #FLUSH_OFFSET - str \ra, [\rd] - add \re, \ra, #8192 @ only necessary for 8k -1001: ldr \rd, [\ra], #DCACHELINESIZE - teq \re, \ra - bne 1001b -#ifdef FLUSH_BASE_MINICACHE - add \ra, \ra, #FLUSH_BASE_MINICACHE - FLUSH_BASE - add \re, \ra, #512 @ only 512 bytes -1002: ldr \rd, [\ra], #DCACHELINESIZE - teq \re, \ra - bne 1002b -#endif - .endm - - .data -flush_base: .long FLUSH_BASE - .text - -/* - * cpu_sa110_check_bugs() - */ -ENTRY(cpu_sa110_check_bugs) -ENTRY(cpu_sa1100_check_bugs) - mrs ip, cpsr - bic ip, ip, #PSR_F_BIT - msr cpsr, ip - mov pc, lr + .macro flush_110_dcache rd, ra, re + ldr \rd, =flush_base + ldr \ra, [\rd] + eor \ra, \ra, #FLUSH_OFFSET + str \ra, [\rd] + add \re, \ra, #16384 @ only necessary for 16k +1001: ldr \rd, [\ra], #DCACHELINESIZE + teq \re, \ra + bne 1001b + .endm + + .data +flush_base: + .long FLUSH_BASE + .text /* * cpu_sa110_proc_init() */ ENTRY(cpu_sa110_proc_init) -ENTRY(cpu_sa1100_proc_init) mov r0, #0 mcr p15, 0, r0, c15, c1, 2 @ Enable clock switching mov pc, lr @@ -101,7 +57,7 @@ ENTRY(cpu_sa110_proc_fin) stmfd sp!, {lr} mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE msr cpsr_c, ip - bl cpu_sa110_cache_clean_invalidate_all @ clean caches + bl v4wb_flush_kern_cache_all @ clean caches 1: mov r0, #0 mcr p15, 0, r0, c15, c2, 2 @ Disable clock switching mrc p15, 0, r0, c1, c0, 0 @ ctrl register @@ -110,13 +66,6 @@ ENTRY(cpu_sa110_proc_fin) mcr p15, 0, r0, c1, c0, 0 @ disable caches ldmfd sp!, {pc} -ENTRY(cpu_sa1100_proc_fin) - stmfd sp!, {lr} - mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE - msr cpsr_c, ip - bl cpu_sa1100_cache_clean_invalidate_all @ clean caches - b 1b - /* * cpu_sa110_reset(loc) * @@ -128,7 +77,6 @@ ENTRY(cpu_sa1100_proc_fin) */ .align 5 ENTRY(cpu_sa110_reset) -ENTRY(cpu_sa1100_reset) mov ip, #0 mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches mcr p15, 0, ip, c7, c10, 4 @ drain WB @@ -151,204 +99,25 @@ ENTRY(cpu_sa1100_reset) * 3 = switch to fast processor clock */ .align 5 -idle: mcr p15, 0, r0, c15, c8, 2 @ Wait for interrupt, cache aligned - mov r0, r0 @ safety - mov pc, lr ENTRY(cpu_sa110_do_idle) - mov ip, #0 - cmp r0, #4 - addcc pc, pc, r0, lsl #2 - mov pc, lr - - b idle - b idle - b slow_clock - b fast_clock - -fast_clock: - mcr p15, 0, ip, c15, c1, 2 @ enable clock switching - mov pc, lr - -slow_clock: mcr p15, 0, ip, c15, c2, 2 @ disable clock switching ldr r1, =UNCACHEABLE_ADDR @ load from uncacheable loc ldr r1, [r1, #0] @ force switch to MCLK - mov pc, lr - - .align 5 -ENTRY(cpu_sa1100_do_idle) - mov r0, r0 @ 4 nop padding - mov r0, r0 - mov r0, r0 - mov r0, #0 - ldr r1, =UNCACHEABLE_ADDR @ ptr to uncacheable address - mrs r2, cpsr - orr r3, r2, #192 @ disallow interrupts - msr cpsr_c, r3 - @ --- aligned to a cache line - mcr p15, 0, r0, c15, c2, 2 @ disable clock switching - ldr r1, [r1, #0] @ force switch to MCLK - mcr p15, 0, r0, c15, c8, 2 @ wait for interrupt + mov r0, r0 @ safety + mov r0, r0 @ safety + mov r0, r0 @ safety + mcr p15, 0, r0, c15, c8, 2 @ Wait for interrupt, cache aligned + mov r0, r0 @ safety + mov r0, r0 @ safety mov r0, r0 @ safety mcr p15, 0, r0, c15, c1, 2 @ enable clock switching - msr cpsr_c, r2 @ allow interrupts mov pc, lr /* ================================= CACHE ================================ */ - -/* - * cpu_sa110_cache_clean_invalidate_all (void) - * - * clean and invalidate all cache lines - * - * Note: - * 1. we should preserve r0 at all times - */ - .align 5 -ENTRY(cpu_sa110_cache_clean_invalidate_all) - mov r2, #1 -cpu_sa110_cache_clean_invalidate_all_r2: - flush_110_dcache r3, ip, r1 - mov ip, #0 - teq r2, #0 - mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache - mcr p15, 0, ip, c7, c10, 4 @ drain WB - mov pc, lr - - .align 5 -ENTRY(cpu_sa1100_cache_clean_invalidate_all) - mov r2, #1 -cpu_sa1100_cache_clean_invalidate_all_r2: - flush_1100_dcache r3, ip, r1 - mov ip, #0 - teq r2, #0 - mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache - mcr p15, 0, r1, c9, c0, 0 @ invalidate RB - mcr p15, 0, ip, c7, c10, 4 @ drain WB - mov pc, lr - -/* - * cpu_sa110_cache_clean_invalidate_range(start, end, flags) - * - * clean and invalidate all cache lines associated with this area of memory - * - * start: Area start address - * end: Area end address - * flags: nonzero for I cache as well - */ - .align 5 -ENTRY(cpu_sa110_cache_clean_invalidate_range) - bic r0, r0, #DCACHELINESIZE - 1 - sub r3, r1, r0 - cmp r3, #MAX_AREA_SIZE - bhi cpu_sa110_cache_clean_invalidate_all_r2 -1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry - mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry - add r0, r0, #DCACHELINESIZE - mcr p15, 0, r0, c7, c10, 1 @ clean D entry - mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry - add r0, r0, #DCACHELINESIZE - cmp r0, r1 - blo 1b - teq r2, #0 - movne r0, #0 - mcrne p15, 0, r0, c7, c5, 0 @ invalidate I cache - mov pc, lr - -ENTRY(cpu_sa1100_cache_clean_invalidate_range) - sub r3, r1, r0 - cmp r3, #MAX_AREA_SIZE - bhi cpu_sa1100_cache_clean_invalidate_all_r2 - b 1b - -/* ================================ D-CACHE =============================== */ - -/* - * cpu_sa110_dcache_invalidate_range(start, end) - * - * throw away all D-cached data in specified region without an obligation - * to write them back. Note however that we must clean the D-cached entries - * around the boundaries if the start and/or end address are not cache - * aligned. - * - * start: virtual start address - * end: virtual end address - */ - .align 5 -ENTRY(cpu_sa110_dcache_invalidate_range) -ENTRY(cpu_sa1100_dcache_invalidate_range) - tst r0, #DCACHELINESIZE - 1 - bic r0, r0, #DCACHELINESIZE - 1 - mcrne p15, 0, r0, c7, c10, 1 @ clean D entry - tst r1, #DCACHELINESIZE - 1 - mcrne p15, 0, r1, c7, c10, 1 @ clean D entry -1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry - add r0, r0, #DCACHELINESIZE - cmp r0, r1 - blo 1b - mov pc, lr - -/* - * cpu_sa110_dcache_clean_range(start, end) - * - * For the specified virtual address range, ensure that all caches contain - * clean data, such that peripheral accesses to the physical RAM fetch - * correct data. - * - * start: virtual start address - * end: virtual end address - */ - .align 5 -ENTRY(cpu_sa110_dcache_clean_range) - bic r0, r0, #DCACHELINESIZE - 1 - sub r1, r1, r0 - cmp r1, #MAX_AREA_SIZE - mov r2, #0 - bhi cpu_sa110_cache_clean_invalidate_all_r2 -1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry - add r0, r0, #DCACHELINESIZE - mcr p15, 0, r0, c7, c10, 1 @ clean D entry - add r0, r0, #DCACHELINESIZE - subs r1, r1, #2 * DCACHELINESIZE - bpl 1b - mcr p15, 0, r2, c7, c10, 4 @ drain WB - mov pc, lr - -ENTRY(cpu_sa1100_dcache_clean_range) - bic r0, r0, #DCACHELINESIZE - 1 - sub r1, r1, r0 - cmp r1, #MAX_AREA_SIZE - mov r2, #0 - bhi cpu_sa1100_cache_clean_invalidate_all_r2 - b 1b - -/* - * cpu_sa110_clean_dcache_page(page) - * - * Cleans a single page of dcache so that if we have any future aliased - * mappings, they will be consistent at the time that they are created. - * - * Note: - * 1. we don't need to flush the write buffer in this case. - * 2. we don't invalidate the entries since when we write the page - * out to disk, the entries may get reloaded into the cache. - */ - .align 5 -ENTRY(cpu_sa110_dcache_clean_page) -ENTRY(cpu_sa1100_dcache_clean_page) - mov r1, #PAGESIZE -1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry - add r0, r0, #DCACHELINESIZE - mcr p15, 0, r0, c7, c10, 1 @ clean D entry - add r0, r0, #DCACHELINESIZE - subs r1, r1, #2 * DCACHELINESIZE - bne 1b - mov pc, lr - /* - * cpu_sa110_dcache_clean_entry(addr) + * cpu_sa110_dcache_clean_area(addr,sz) * * Clean the specified entry of any caches such that the MMU * translation fetches will obtain correct data. @@ -356,48 +125,24 @@ ENTRY(cpu_sa1100_dcache_clean_page) * addr: cache-unaligned virtual address */ .align 5 -ENTRY(cpu_sa110_dcache_clean_entry) -ENTRY(cpu_sa1100_dcache_clean_entry) - mcr p15, 0, r0, c7, c10, 1 @ clean D entry - mcr p15, 0, r0, c7, c10, 4 @ drain WB - mov pc, lr - -/* ================================ I-CACHE =============================== */ - -/* - * cpu_sa110_icache_invalidate_range(start, end) - * - * invalidate a range of virtual addresses from the Icache - * - * start: virtual start address - * end: virtual end address - */ - .align 5 -ENTRY(cpu_sa110_icache_invalidate_range) -ENTRY(cpu_sa1100_icache_invalidate_range) - bic r0, r0, #DCACHELINESIZE - 1 -1: mcr p15, 0, r0, c7, c10, 1 @ Clean D entry +ENTRY(cpu_sa110_dcache_clean_area) +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry add r0, r0, #DCACHELINESIZE - cmp r0, r1 - blo 1b - mov r0, #0 - mcr p15, 0, r0, c7, c10, 4 @ drain WB -ENTRY(cpu_sa110_icache_invalidate_page) -ENTRY(cpu_sa1100_icache_invalidate_page) - mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache + subs r1, r1, #DCACHELINESIZE + bhi 1b mov pc, lr /* =============================== PageTable ============================== */ /* - * cpu_sa110_set_pgd(pgd) + * cpu_sa110_switch_mm(pgd) * * Set the translation base pointer to be as described by pgd. * * pgd: new page tables */ .align 5 -ENTRY(cpu_sa110_set_pgd) +ENTRY(cpu_sa110_switch_mm) flush_110_dcache r3, ip, r1 mov r1, #0 mcr p15, 0, r1, c7, c5, 0 @ invalidate I cache @@ -407,48 +152,12 @@ ENTRY(cpu_sa110_set_pgd) mov pc, lr /* - * cpu_sa1100_set_pgd(pgd) - * - * Set the translation base pointer to be as described by pgd. - * - * pgd: new page tables - */ - .align 5 -ENTRY(cpu_sa1100_set_pgd) - flush_1100_dcache r3, ip, r1 - mov ip, #0 - mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache - mcr p15, 0, ip, c9, c0, 0 @ invalidate RB - mcr p15, 0, ip, c7, c10, 4 @ drain WB - mcr p15, 0, r0, c2, c0, 0 @ load page table pointer - mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs - mov pc, lr - -/* - * cpu_sa110_flush_pmd(pmdp) - * - * Set a level 1 translation table entry, and clean it out of - * any caches such that the MMUs can load it correctly. - * - * pmdp: pointer to PMD entry - */ - .align 5 -ENTRY(cpu_sa110_flush_pmd) -ENTRY(cpu_sa1100_flush_pmd) - mcr p15, 0, r0, c7, c10, 1 @ clean D entry - mcr p15, 0, r0, c7, c10, 4 @ drain WB - mov pc, lr - -/* * cpu_sa110_set_pte(ptep, pte) * * Set a PTE and flush it out */ .align 5 ENTRY(cpu_sa110_set_pte) -ENTRY(cpu_sa1100_set_pte) - tst r0, #2048 - streq r0, [r0, -r0] @ BUG_ON str r1, [r0], #-2048 @ linux version eor r1, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY @@ -457,7 +166,7 @@ ENTRY(cpu_sa1100_set_pte) bic r2, r2, #3 orr r2, r2, #PTE_TYPE_SMALL - tst r1, #L_PTE_USER | L_PTE_EXEC @ User or Exec? + tst r1, #L_PTE_USER @ User or Exec? orrne r2, r2, #PTE_SMALL_AP_URO_SRW tst r1, #L_PTE_WRITE | L_PTE_DIRTY @ Write and Dirty? @@ -475,30 +184,16 @@ ENTRY(cpu_sa1100_set_pte) cpu_sa110_name: .asciz "StrongARM-110" -cpu_sa1100_name: - .asciz "StrongARM-1100" -cpu_sa1110_name: - .asciz "StrongARM-1110" .align __INIT -__sa1100_setup: @ Allow read-buffer operations from userland - mcr p15, 0, r0, c9, c0, 5 - mrc p15, 0, r0, c1, c0 @ get control register v4 - bic r0, r0, #0x0e00 @ ..VI ZFRS BLDP WCAM - bic r0, r0, #0x0002 @ .... 000. .... ..0. - orr r0, r0, #0x003d - orr r0, r0, #0x3100 @ ..11 ...1 ..11 11.1 - b __setup_common - __sa110_setup: mrc p15, 0, r0, c1, c0 @ get control register v4 bic r0, r0, #0x2e00 @ ..VI ZFRS BLDP WCAM bic r0, r0, #0x0002 @ ..0. 000. .... ..0. orr r0, r0, #0x003d orr r0, r0, #0x1100 @ ...1 ...1 ..11 11.1 -__setup_common: mov r10, #0 mcr p15, 0, r10, c7, c7 @ invalidate I,D caches on v4 mcr p15, 0, r10, c7, c10, 4 @ drain write buffer on v4 @@ -518,66 +213,20 @@ __setup_common: .type sa110_processor_functions, #object ENTRY(sa110_processor_functions) .word v4_early_abort - .word cpu_sa110_check_bugs .word cpu_sa110_proc_init .word cpu_sa110_proc_fin .word cpu_sa110_reset .word cpu_sa110_do_idle - /* cache */ - .word cpu_sa110_cache_clean_invalidate_all - .word cpu_sa110_cache_clean_invalidate_range - /* dcache */ - .word cpu_sa110_dcache_invalidate_range - .word cpu_sa110_dcache_clean_range - .word cpu_sa110_dcache_clean_page - .word cpu_sa110_dcache_clean_entry - - /* icache */ - .word cpu_sa110_icache_invalidate_range - .word cpu_sa110_icache_invalidate_page + .word cpu_sa110_dcache_clean_area /* pgtable */ - .word cpu_sa110_set_pgd - .word cpu_sa110_flush_pmd + .word cpu_sa110_switch_mm .word cpu_sa110_set_pte .size sa110_processor_functions, . - sa110_processor_functions -/* - * SA1100 and SA1110 share the same function calls - */ - .type sa1100_processor_functions, #object -ENTRY(sa1100_processor_functions) - .word v4_early_abort - .word cpu_sa1100_check_bugs - .word cpu_sa1100_proc_init - .word cpu_sa1100_proc_fin - .word cpu_sa1100_reset - .word cpu_sa1100_do_idle - - /* cache */ - .word cpu_sa1100_cache_clean_invalidate_all - .word cpu_sa1100_cache_clean_invalidate_range - - /* dcache */ - .word cpu_sa1100_dcache_invalidate_range - .word cpu_sa1100_dcache_clean_range - .word cpu_sa1100_dcache_clean_page - .word cpu_sa1100_dcache_clean_entry - - /* icache */ - .word cpu_sa1100_icache_invalidate_range - .word cpu_sa1100_icache_invalidate_page - - /* pgtable */ - .word cpu_sa1100_set_pgd - .word cpu_sa1100_flush_pmd - .word cpu_sa1100_set_pte - - .size sa1100_processor_functions, . - sa1100_processor_functions - .type cpu_arch_name, #object cpu_arch_name: .asciz "armv4" @@ -591,7 +240,6 @@ cpu_elf_name: .section ".proc.info", #alloc, #execinstr -#ifdef CONFIG_CPU_SA110 .type __sa110_proc_info,#object __sa110_proc_info: .long 0x4401a100 @@ -605,37 +253,5 @@ __sa110_proc_info: .long sa110_processor_functions .long v4wb_tlb_fns .long v4wb_user_fns + .long v4wb_cache_fns .size __sa110_proc_info, . - __sa110_proc_info -#endif - -#ifdef CONFIG_CPU_SA1100 - .type __sa1100_proc_info,#object -__sa1100_proc_info: - .long 0x4401a110 - .long 0xfffffff0 - .long 0x00000c0e - b __sa1100_setup - .long cpu_arch_name - .long cpu_elf_name - .long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT | HWCAP_FAST_MULT - .long cpu_sa1100_name - .long sa1100_processor_functions - .long v4wb_tlb_fns - .long v4_mc_user_fns - .size __sa1100_proc_info, . - __sa1100_proc_info - - .type __sa1110_proc_info,#object -__sa1110_proc_info: - .long 0x6901b110 - .long 0xfffffff0 - .long 0x00000c0e - b __sa1100_setup - .long cpu_arch_name - .long cpu_elf_name - .long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT | HWCAP_FAST_MULT - .long cpu_sa1110_name - .long sa1100_processor_functions - .long v4wb_tlb_fns - .long v4_mc_user_fns - .size __sa1110_proc_info, . - __sa1110_proc_info -#endif --- linux-2.5.68/arch/arm/mm/proc-syms.c 2003-01-16 18:22:06.000000000 -0800 +++ 25/arch/arm/mm/proc-syms.c 2003-04-29 20:50:34.000000000 -0700 @@ -11,28 +11,28 @@ #include #include -#include #include #include EXPORT_SYMBOL(__flush_dcache_page); #ifndef MULTI_CPU -EXPORT_SYMBOL(cpu_cache_clean_invalidate_all); -EXPORT_SYMBOL(cpu_cache_clean_invalidate_range); -EXPORT_SYMBOL(cpu_dcache_clean_page); -EXPORT_SYMBOL(cpu_dcache_clean_entry); -EXPORT_SYMBOL(cpu_dcache_clean_range); -EXPORT_SYMBOL(cpu_dcache_invalidate_range); -EXPORT_SYMBOL(cpu_icache_invalidate_range); -EXPORT_SYMBOL(cpu_icache_invalidate_page); -EXPORT_SYMBOL(cpu_set_pgd); -EXPORT_SYMBOL(cpu_flush_pmd); +EXPORT_SYMBOL(cpu_dcache_clean_area); EXPORT_SYMBOL(cpu_set_pte); #else EXPORT_SYMBOL(processor); #endif +#ifndef MULTI_CACHE +EXPORT_SYMBOL_NOVERS(__cpuc_flush_kern_all); +EXPORT_SYMBOL_NOVERS(__cpuc_flush_user_all); +EXPORT_SYMBOL_NOVERS(__cpuc_flush_user_range); +EXPORT_SYMBOL_NOVERS(__cpuc_coherent_kern_range); +EXPORT_SYMBOL_NOVERS(__cpuc_flush_dcache_page); +#else +EXPORT_SYMBOL(cpu_cache); +#endif + /* * No module should need to touch the TLB (and currently * no modules do. We export this for "loadkernel" support --- linux-2.5.68/arch/arm/mm/proc-xscale.S 2003-04-19 20:45:17.000000000 -0700 +++ 25/arch/arm/mm/proc-xscale.S 2003-04-29 20:50:34.000000000 -0700 @@ -23,10 +23,11 @@ #include #include #include -#include #include #include #include +#include +#include "proc-macros.S" /* * This is the maximum size of an area which will be flushed. If the area @@ -45,11 +46,6 @@ #define CACHESIZE 32768 /* - * and the page size - */ -#define PAGESIZE 4096 - -/* * Virtual address used to allocate the cache when flushed * * This must be an address range which is _never_ used. It should @@ -112,15 +108,6 @@ clean_addr: .word CLEAN_ADDR .text /* - * cpu_xscale_check_bugs() - */ -ENTRY(cpu_xscale_check_bugs) - mrs ip, cpsr - bic ip, ip, #PSR_F_BIT - msr cpsr, ip - mov pc, lr - -/* * cpu_xscale_proc_init() * * Nothing too exciting at the moment @@ -135,11 +122,11 @@ ENTRY(cpu_xscale_proc_fin) str lr, [sp, #-4]! mov r0, #PSR_F_BIT|PSR_I_BIT|SVC_MODE msr cpsr_c, r0 + bl xscale_flush_kern_cache_all @ clean caches mrc p15, 0, r0, c1, c0, 0 @ ctrl register bic r0, r0, #0x1800 @ ...IZ........... bic r0, r0, #0x0006 @ .............CA. mcr p15, 0, r0, c1, c0, 0 @ disable caches - bl cpu_xscale_cache_clean_invalidate_all @ clean caches ldr pc, [sp], #4 /* @@ -168,16 +155,10 @@ ENTRY(cpu_xscale_reset) mov pc, r0 /* - * cpu_xscale_do_idle(type) + * cpu_xscale_do_idle() * * Cause the processor to idle * - * type: - * 0 = slow idle - * 1 = fast idle - * 2 = switch to slow processor clock - * 3 = switch to fast processor clock - * * For now we do nothing but go to idle mode for every case * * XScale supports clock switching, but using idle mode support @@ -193,226 +174,179 @@ ENTRY(cpu_xscale_do_idle) /* ================================= CACHE ================================ */ /* - * cpu_xscale_cache_clean_invalidate_all (void) + * flush_user_cache_all() * - * clean and invalidate all cache lines + * Invalidate all cache entries in a particular address + * space. + */ +ENTRY(xscale_flush_user_cache_all) + /* FALLTHROUGH */ + +/* + * flush_kern_cache_all() * - * Note: - * 1. We should preserve r0 at all times. - * 2. Even if this function implies cache "invalidation" by its name, - * we don't need to actually use explicit invalidation operations - * since the goal is to discard all valid references from the cache - * and the cleaning of it already has that effect. - * 3. Because of 2 above and the fact that kernel space memory is always - * coherent across task switches there is no need to worry about - * inconsistencies due to interrupts, ence no irq disabling. + * Clean and invalidate the entire cache. */ - .align 5 -ENTRY(cpu_xscale_cache_clean_invalidate_all) - mov r2, #1 -cpu_xscale_cache_clean_invalidate_all_r2: +ENTRY(xscale_flush_kern_cache_all) + mov r2, #VM_EXEC + mov ip, #0 +__flush_whole_cache: clean_d_cache r0, r1 - teq r2, #0 + tst r2, #VM_EXEC mcrne p15, 0, ip, c7, c5, 0 @ Invalidate I cache & BTB - mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer + mcrne p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer mov pc, lr /* - * cpu_xscale_cache_clean_invalidate_range(start, end, flags) + * flush_user_cache_range(start, end, vm_flags) * - * clean and invalidate all cache lines associated with this area of memory + * Invalidate a range of cache entries in the specified + * address space. * - * start: Area start address - * end: Area end address - * flags: nonzero for I cache as well + * - start - start address (may not be aligned) + * - end - end address (exclusive, may not be aligned) + * - vma - vma_area_struct describing address space */ .align 5 -ENTRY(cpu_xscale_cache_clean_invalidate_range) - bic r0, r0, #CACHELINESIZE - 1 @ round down to cache line - sub r3, r1, r0 +ENTRY(xscale_flush_user_cache_range) + mov ip, #0 + sub r3, r1, r0 @ calculate total size cmp r3, #MAX_AREA_SIZE - bhi cpu_xscale_cache_clean_invalidate_all_r2 -1: mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line + bhs __flush_whole_cache + +1: tst r2, #VM_EXEC + mcrne p15, 0, r0, c7, c5, 1 @ Invalidate I cache line + mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line mcr p15, 0, r0, c7, c6, 1 @ Invalidate D cache line add r0, r0, #CACHELINESIZE cmp r0, r1 blo 1b - teq r2, #0 - mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer - moveq pc, lr - sub r0, r0, r3 -1: mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line - add r0, r0, #CACHELINESIZE - cmp r0, r1 - blo 1b - mcr p15, 0, ip, c7, c5, 6 @ Invalidate BTB + tst r2, #VM_EXEC + mcrne p15, 0, ip, c7, c5, 6 @ Invalidate BTB + mcrne p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer mov pc, lr /* - * cpu_xscale_flush_ram_page(page) + * coherent_kern_range(start, end) * - * clean all cache lines associated with this memory page + * Ensure coherency between the Icache and the Dcache in the + * region described by start. If you have non-snooping + * Harvard caches, you need to implement this function. * - * page: page to clean + * - start - virtual start address + * - end - virtual end address */ - .align 5 -ENTRY(cpu_xscale_flush_ram_page) - mov r1, #PAGESIZE -1: mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line - add r0, r0, #CACHELINESIZE - mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line +ENTRY(xscale_coherent_kern_range) + bic r0, r0, #CACHELINESIZE - 1 +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry add r0, r0, #CACHELINESIZE - subs r1, r1, #2 * CACHELINESIZE - bne 1b - mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer + cmp r0, r1 + blo 1b + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 @ Invalidate I cache & BTB + mcr p15, 0, r0, c7, c10, 4 @ Drain Write (& Fill) Buffer mov pc, lr -/* ================================ D-CACHE =============================== */ - /* - * cpu_xscale_dcache_invalidate_range(start, end) + * flush_kern_dcache_page(void *page) * - * throw away all D-cached data in specified region without an obligation - * to write them back. Note however that on XScale we must clean all - * entries also due to hardware errata (80200 A0 & A1 only). + * Ensure no D cache aliasing occurs, either with itself or + * the I cache * - * start: virtual start address - * end: virtual end address + * - addr - page aligned address */ - .align 5 -ENTRY(cpu_xscale_dcache_invalidate_range) - mrc p15, 0, r2, c0, c0, 0 @ Read part no. - eor r2, r2, #0x69000000 - eor r2, r2, #0x00052000 @ 80200 XX part no. - bics r2, r2, #0x1 @ Clear LSB in revision field - moveq r2, #0 - beq cpu_xscale_cache_clean_invalidate_range @ An 80200 A0 or A1 - - tst r0, #CACHELINESIZE - 1 - mcrne p15, 0, r0, c7, c10, 1 @ Clean D cache line - tst r1, #CACHELINESIZE - 1 - mcrne p15, 0, r1, c7, c10, 1 @ Clean D cache line - bic r0, r0, #CACHELINESIZE - 1 @ round down to cache line -1: mcr p15, 0, r0, c7, c6, 1 @ Invalidate D cache line +ENTRY(xscale_flush_kern_dcache_page) + add r1, r0, #PAGE_SZ +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry add r0, r0, #CACHELINESIZE cmp r0, r1 blo 1b + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 @ Invalidate I cache & BTB + mcr p15, 0, r0, c7, c10, 4 @ Drain Write (& Fill) Buffer mov pc, lr /* - * cpu_xscale_dcache_clean_range(start, end) + * dma_inv_range(start, end) * - * For the specified virtual address range, ensure that all caches contain - * clean data, such that peripheral accesses to the physical RAM fetch - * correct data. + * Invalidate (discard) the specified virtual address range. + * May not write back any entries. If 'start' or 'end' + * are not cache line aligned, those lines must be written + * back. * - * start: virtual start address - * end: virtual end address + * - start - virtual start address + * - end - virtual end address */ - .align 5 -ENTRY(cpu_xscale_dcache_clean_range) - bic r0, r0, #CACHELINESIZE - 1 - sub r2, r1, r0 - cmp r2, #MAX_AREA_SIZE - movhi r2, #0 - bhi cpu_xscale_cache_clean_invalidate_all_r2 +ENTRY(xscale_dma_inv_range) + mrc p15, 0, r2, c0, c0, 0 @ read ID + eor r2, r2, #0x69000000 + eor r2, r2, #0x00052000 + bics r2, r2, #1 + beq xscale_dma_flush_range -1: mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line - add r0, r0, #CACHELINESIZE - mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line + tst r0, #CACHELINESIZE - 1 + bic r0, r0, #CACHELINESIZE - 1 + mcrne p15, 0, r0, c7, c10, 1 @ clean D entry + tst r1, #CACHELINESIZE - 1 + mcrne p15, 0, r1, c7, c10, 1 @ clean D entry +1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry add r0, r0, #CACHELINESIZE cmp r0, r1 blo 1b - mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer + mcr p15, 0, r0, c7, c10, 1 @ Drain Write (& Fill) Buffer mov pc, lr /* - * cpu_xscale_clean_dcache_page(page) + * dma_clean_range(start, end) * - * Cleans a single page of dcache so that if we have any future aliased - * mappings, they will be consistent at the time that they are created. + * Clean the specified virtual address range. * - * Note: - * 1. we don't need to flush the write buffer in this case. [really? -Nico] - * 2. we don't invalidate the entries since when we write the page - * out to disk, the entries may get reloaded into the cache. + * - start - virtual start address + * - end - virtual end address */ - .align 5 -ENTRY(cpu_xscale_dcache_clean_page) - mov r1, #PAGESIZE -1: mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line - add r0, r0, #CACHELINESIZE - mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line - add r0, r0, #CACHELINESIZE - mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line - add r0, r0, #CACHELINESIZE - mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line +ENTRY(xscale_dma_clean_range) + bic r0, r0, #CACHELINESIZE - 1 +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry add r0, r0, #CACHELINESIZE - subs r1, r1, #4 * CACHELINESIZE - bne 1b - mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer - mov pc, lr - -/* - * cpu_xscale_dcache_clean_entry(addr) - * - * Clean the specified entry of any caches such that the MMU - * translation fetches will obtain correct data. - * - * addr: cache-unaligned virtual address - */ - .align 5 -ENTRY(cpu_xscale_dcache_clean_entry) - mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line - mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer + cmp r0, r1 + blo 1b + mcr p15, 0, r0, c7, c10, 1 @ Drain Write (& Fill) Buffer mov pc, lr -/* ================================ I-CACHE =============================== */ - /* - * cpu_xscale_icache_invalidate_range(start, end) - * - * invalidate a range of virtual addresses from the Icache + * dma_flush_range(start, end) * - * start: virtual start address - * end: virtual end address + * Clean and invalidate the specified virtual address range. * - * Note: This is vaguely defined as supposed to bring the dcache and the - * icache in sync by the way this function is used. + * - start - virtual start address + * - end - virtual end address */ - .align 5 -ENTRY(cpu_xscale_icache_invalidate_range) +ENTRY(xscale_dma_flush_range) bic r0, r0, #CACHELINESIZE - 1 -1: mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line - mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry add r0, r0, #CACHELINESIZE cmp r0, r1 blo 1b - mcr p15, 0, ip, c7, c5, 6 @ Invalidate BTB - mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer + mcr p15, 0, r0, c7, c10, 1 @ Drain Write (& Fill) Buffer mov pc, lr -/* - * cpu_xscale_icache_invalidate_page(page) - * - * invalidate all Icache lines associated with this area of memory - * - * page: page to invalidate - */ - .align 5 -ENTRY(cpu_xscale_icache_invalidate_page) - mov r1, #PAGESIZE -1: mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line - add r0, r0, #CACHELINESIZE - mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line - add r0, r0, #CACHELINESIZE - mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line - add r0, r0, #CACHELINESIZE - mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line +ENTRY(xscale_cache_fns) + .long xscale_flush_kern_cache_all + .long xscale_flush_user_cache_all + .long xscale_flush_user_cache_range + .long xscale_coherent_kern_range + .long xscale_flush_kern_dcache_page + .long xscale_dma_inv_range + .long xscale_dma_clean_range + .long xscale_dma_flush_range + +ENTRY(cpu_xscale_dcache_clean_area) +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry add r0, r0, #CACHELINESIZE - subs r1, r1, #4 * CACHELINESIZE - bne 1b - mcr p15, 0, r0, c7, c5, 6 @ Invalidate BTB + subs r1, r1, #CACHELINESIZE + bhi 1b mov pc, lr /* ================================ CACHE LOCKING============================ @@ -553,18 +487,17 @@ ENTRY(xscale_dtlb_unlock) /* =============================== PageTable ============================== */ -#define PMD_CACHE_WRITE_ALLOCATE 0 #define PTE_CACHE_WRITE_ALLOCATE 0 /* - * cpu_xscale_set_pgd(pgd) + * cpu_xscale_switch_mm(pgd) * * Set the translation base pointer to be as described by pgd. * * pgd: new page tables */ .align 5 -ENTRY(cpu_xscale_set_pgd) +ENTRY(cpu_xscale_switch_mm) clean_d_cache r1, r2 mcr p15, 0, ip, c7, c5, 0 @ Invalidate I cache & BTB mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer @@ -573,21 +506,6 @@ ENTRY(cpu_xscale_set_pgd) cpwait_ret lr, ip /* - * cpu_xscale_flush_pmd(pmdp) - * - * Set a level 1 translation table entry, and clean it out of - * any caches such that the MMUs can load it correctly. - * - * pmdp: pointer to PMD entry - */ - .align 5 -ENTRY(cpu_xscale_flush_pmd) - mov ip, #0 - mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line - mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer - mov pc, lr - -/* * cpu_xscale_set_pte(ptep, pte) * * Set a PTE and flush it out @@ -603,7 +521,7 @@ ENTRY(cpu_xscale_set_pte) eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY - tst r3, #L_PTE_USER | L_PTE_EXEC @ User or Exec? + tst r3, #L_PTE_USER @ User? orrne r2, r2, #PTE_EXT_AP_URO_SRW @ yes -> user r/o, system r/w tst r3, #L_PTE_WRITE | L_PTE_DIRTY @ Write and Dirty? @@ -631,12 +549,10 @@ ENTRY(cpu_xscale_set_pte) @ Erratum 40: The B bit must be cleared for a user read-only @ cacheable page. @ - @ B = B & ~((U|E) & C & ~W) + @ B = B & ~(U & C & ~W) @ - and ip, r1, #L_PTE_USER | L_PTE_EXEC | L_PTE_WRITE | L_PTE_CACHEABLE + and ip, r1, #L_PTE_USER | L_PTE_WRITE | L_PTE_CACHEABLE teq ip, #L_PTE_USER | L_PTE_CACHEABLE - teqne ip, #L_PTE_EXEC | L_PTE_CACHEABLE - teqne ip, #L_PTE_USER | L_PTE_EXEC | L_PTE_CACHEABLE biceq r2, r2, #PTE_BUFFERABLE tst r3, #L_PTE_PRESENT | L_PTE_YOUNG @ Present and Young? @@ -696,30 +612,12 @@ __xscale_setup: .type xscale_processor_functions, #object ENTRY(xscale_processor_functions) .word xscale_abort - .word cpu_xscale_check_bugs .word cpu_xscale_proc_init .word cpu_xscale_proc_fin .word cpu_xscale_reset .word cpu_xscale_do_idle - - /* cache */ - .word cpu_xscale_cache_clean_invalidate_all - .word cpu_xscale_cache_clean_invalidate_range - .word cpu_xscale_flush_ram_page - - /* dcache */ - .word cpu_xscale_dcache_invalidate_range - .word cpu_xscale_dcache_clean_range - .word cpu_xscale_dcache_clean_page - .word cpu_xscale_dcache_clean_entry - - /* icache */ - .word cpu_xscale_icache_invalidate_range - .word cpu_xscale_icache_invalidate_page - - /* pgtable */ - .word cpu_xscale_set_pgd - .word cpu_xscale_flush_pmd + .word cpu_xscale_dcache_clean_area + .word cpu_xscale_switch_mm .word cpu_xscale_set_pte .size xscale_processor_functions, . - xscale_processor_functions @@ -749,6 +647,7 @@ __80200_proc_info: .long xscale_processor_functions .long v4wbi_tlb_fns .long xscale_mc_user_fns + .long xscale_cache_fns .size __80200_proc_info, . - __80200_proc_info .type __80321_proc_info,#object @@ -780,6 +679,7 @@ __pxa250_proc_info: .long xscale_processor_functions .long v4wbi_tlb_fns .long xscale_mc_user_fns + .long xscale_cache_fns .size __pxa250_proc_info, . - __pxa250_proc_info .type __pxa210_proc_info,#object --- linux-2.5.68/arch/arm/nwfpe/ChangeLog 2003-01-16 18:22:13.000000000 -0800 +++ 25/arch/arm/nwfpe/ChangeLog 2003-04-29 20:50:34.000000000 -0700 @@ -1,3 +1,11 @@ +2003-03-22 Ralph Siemsen + * Reformat all but softfloat files to get a consistent coding style. + Used "indent -kr -i8 -ts8 -sob -l132 -ss" and a few manual fixups. + * Removed dead code and fixed function protypes to match definitions. + * Consolidated use of (opcode && MASK_ARITHMETIC_OPCODE) >> 20. + * Make 80-bit precision a compile-time option. (1%) + * Only initialize FPE state once in repeat-FP situations. (6%) + 2002-01-19 Russell King * fpa11.h - Add documentation --- linux-2.5.68/arch/arm/nwfpe/double_cpdo.c 2003-01-16 18:21:34.000000000 -0800 +++ 25/arch/arm/nwfpe/double_cpdo.c 2003-04-29 20:50:34.000000000 -0700 @@ -23,6 +23,11 @@ #include "softfloat.h" #include "fpopcode.h" +union float64_components { + float64 f64; + unsigned int i[2]; +}; + float64 float64_exp(float64 Fm); float64 float64_ln(float64 Fm); float64 float64_sin(float64 rFm); @@ -32,257 +37,123 @@ float64 float64_arctan(float64 rFm); float64 float64_log(float64 rFm); float64 float64_tan(float64 rFm); float64 float64_arccos(float64 rFm); -float64 float64_pow(float64 rFn,float64 rFm); -float64 float64_pol(float64 rFn,float64 rFm); +float64 float64_pow(float64 rFn, float64 rFm); +float64 float64_pol(float64 rFn, float64 rFm); -unsigned int DoubleCPDO(const unsigned int opcode) +static float64 float64_rsf(float64 rFn, float64 rFm) { - FPA11 *fpa11 = GET_FPA11(); - float64 rFm, rFn; - unsigned int Fd, Fm, Fn, nRc = 1; - - //printk("DoubleCPDO(0x%08x)\n",opcode); - - Fm = getFm(opcode); - if (CONSTANT_FM(opcode)) - { - rFm = getDoubleConstant(Fm); - } - else - { - switch (fpa11->fType[Fm]) - { - case typeSingle: - rFm = float32_to_float64(fpa11->fpreg[Fm].fSingle); - break; - - case typeDouble: - rFm = fpa11->fpreg[Fm].fDouble; - break; - - case typeExtended: - // !! patb - //printk("not implemented! why not?\n"); - //!! ScottB - // should never get here, if extended involved - // then other operand should be promoted then - // ExtendedCPDO called. - break; - - default: return 0; - } - } - - if (!MONADIC_INSTRUCTION(opcode)) - { - Fn = getFn(opcode); - switch (fpa11->fType[Fn]) - { - case typeSingle: - rFn = float32_to_float64(fpa11->fpreg[Fn].fSingle); - break; - - case typeDouble: - rFn = fpa11->fpreg[Fn].fDouble; - break; - - default: return 0; - } - } - - Fd = getFd(opcode); - /* !! this switch isn't optimized; better (opcode & MASK_ARITHMETIC_OPCODE)>>24, sort of */ - switch (opcode & MASK_ARITHMETIC_OPCODE) - { - /* dyadic opcodes */ - case ADF_CODE: - fpa11->fpreg[Fd].fDouble = float64_add(rFn,rFm); - break; - - case MUF_CODE: - case FML_CODE: - fpa11->fpreg[Fd].fDouble = float64_mul(rFn,rFm); - break; - - case SUF_CODE: - fpa11->fpreg[Fd].fDouble = float64_sub(rFn,rFm); - break; - - case RSF_CODE: - fpa11->fpreg[Fd].fDouble = float64_sub(rFm,rFn); - break; - - case DVF_CODE: - case FDV_CODE: - fpa11->fpreg[Fd].fDouble = float64_div(rFn,rFm); - break; - - case RDF_CODE: - case FRD_CODE: - fpa11->fpreg[Fd].fDouble = float64_div(rFm,rFn); - break; - -#if 0 - case POW_CODE: - fpa11->fpreg[Fd].fDouble = float64_pow(rFn,rFm); - break; - - case RPW_CODE: - fpa11->fpreg[Fd].fDouble = float64_pow(rFm,rFn); - break; -#endif - - case RMF_CODE: - fpa11->fpreg[Fd].fDouble = float64_rem(rFn,rFm); - break; - -#if 0 - case POL_CODE: - fpa11->fpreg[Fd].fDouble = float64_pol(rFn,rFm); - break; -#endif - - /* monadic opcodes */ - case MVF_CODE: - fpa11->fpreg[Fd].fDouble = rFm; - break; - - case MNF_CODE: - { - unsigned int *p = (unsigned int*)&rFm; - p[1] ^= 0x80000000; - fpa11->fpreg[Fd].fDouble = rFm; - } - break; - - case ABS_CODE: - { - unsigned int *p = (unsigned int*)&rFm; - p[1] &= 0x7fffffff; - fpa11->fpreg[Fd].fDouble = rFm; - } - break; - - case RND_CODE: - case URD_CODE: - fpa11->fpreg[Fd].fDouble = float64_round_to_int(rFm); - break; - - case SQT_CODE: - fpa11->fpreg[Fd].fDouble = float64_sqrt(rFm); - break; - -#if 0 - case LOG_CODE: - fpa11->fpreg[Fd].fDouble = float64_log(rFm); - break; - - case LGN_CODE: - fpa11->fpreg[Fd].fDouble = float64_ln(rFm); - break; - - case EXP_CODE: - fpa11->fpreg[Fd].fDouble = float64_exp(rFm); - break; - - case SIN_CODE: - fpa11->fpreg[Fd].fDouble = float64_sin(rFm); - break; - - case COS_CODE: - fpa11->fpreg[Fd].fDouble = float64_cos(rFm); - break; - - case TAN_CODE: - fpa11->fpreg[Fd].fDouble = float64_tan(rFm); - break; - - case ASN_CODE: - fpa11->fpreg[Fd].fDouble = float64_arcsin(rFm); - break; - - case ACS_CODE: - fpa11->fpreg[Fd].fDouble = float64_arccos(rFm); - break; - - case ATN_CODE: - fpa11->fpreg[Fd].fDouble = float64_arctan(rFm); - break; -#endif - - case NRM_CODE: - break; - - default: - { - nRc = 0; - } - } - - if (0 != nRc) fpa11->fType[Fd] = typeDouble; - return nRc; + return float64_sub(rFm, rFn); } -#if 0 -float64 float64_exp(float64 rFm) +static float64 float64_rdv(float64 rFn, float64 rFm) { - return rFm; -//series + return float64_div(rFm, rFn); } -float64 float64_ln(float64 rFm) -{ - return rFm; -//series -} +static float64 (*const dyadic_double[16])(float64 rFn, float64 rFm) = { + [ADF_CODE >> 20] = float64_add, + [MUF_CODE >> 20] = float64_mul, + [SUF_CODE >> 20] = float64_sub, + [RSF_CODE >> 20] = float64_rsf, + [DVF_CODE >> 20] = float64_div, + [RDF_CODE >> 20] = float64_rdv, + [RMF_CODE >> 20] = float64_rem, -float64 float64_sin(float64 rFm) -{ - return rFm; -//series -} + /* strictly, these opcodes should not be implemented */ + [FML_CODE >> 20] = float64_mul, + [FDV_CODE >> 20] = float64_div, + [FRD_CODE >> 20] = float64_rdv, +}; -float64 float64_cos(float64 rFm) +static float64 float64_mvf(float64 rFm) { - return rFm; - //series + return rFm; } -#if 0 -float64 float64_arcsin(float64 rFm) +static float64 float64_mnf(float64 rFm) { -//series -} + union float64_components u; -float64 float64_arctan(float64 rFm) -{ - //series -} -#endif + u.f64 = rFm; + u.i[1] ^= 0x80000000; -float64 float64_log(float64 rFm) -{ - return float64_div(float64_ln(rFm),getDoubleConstant(7)); + return u.f64; } -float64 float64_tan(float64 rFm) +static float64 float64_abs(float64 rFm) { - return float64_div(float64_sin(rFm),float64_cos(rFm)); -} + union float64_components u; -float64 float64_arccos(float64 rFm) -{ -return rFm; - //return float64_sub(halfPi,float64_arcsin(rFm)); -} + u.f64 = rFm; + u.i[1] &= 0x7fffffff; -float64 float64_pow(float64 rFn,float64 rFm) -{ - return float64_exp(float64_mul(rFm,float64_ln(rFn))); + return u.f64; } -float64 float64_pol(float64 rFn,float64 rFm) +static float64 (*const monadic_double[16])(float64 rFm) = { + [MVF_CODE >> 20] = float64_mvf, + [MNF_CODE >> 20] = float64_mnf, + [ABS_CODE >> 20] = float64_abs, + [RND_CODE >> 20] = float64_round_to_int, + [URD_CODE >> 20] = float64_round_to_int, + [SQT_CODE >> 20] = float64_sqrt, + [NRM_CODE >> 20] = float64_mvf, +}; + +unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd) { - return float64_arctan(float64_div(rFn,rFm)); + FPA11 *fpa11 = GET_FPA11(); + float64 rFm; + unsigned int Fm, opc_mask_shift; + + Fm = getFm(opcode); + if (CONSTANT_FM(opcode)) { + rFm = getDoubleConstant(Fm); + } else { + switch (fpa11->fType[Fm]) { + case typeSingle: + rFm = float32_to_float64(fpa11->fpreg[Fm].fSingle); + break; + + case typeDouble: + rFm = fpa11->fpreg[Fm].fDouble; + break; + + default: + return 0; + } + } + + opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20; + if (!MONADIC_INSTRUCTION(opcode)) { + unsigned int Fn = getFn(opcode); + float64 rFn; + + switch (fpa11->fType[Fn]) { + case typeSingle: + rFn = float32_to_float64(fpa11->fpreg[Fn].fSingle); + break; + + case typeDouble: + rFn = fpa11->fpreg[Fn].fDouble; + break; + + default: + return 0; + } + + if (dyadic_double[opc_mask_shift]) { + rFd->fDouble = dyadic_double[opc_mask_shift](rFn, rFm); + } else { + return 0; + } + } else { + if (monadic_double[opc_mask_shift]) { + rFd->fDouble = monadic_double[opc_mask_shift](rFm); + } else { + return 0; + } + } + + return 1; } -#endif --- linux-2.5.68/arch/arm/nwfpe/entry26.S 2003-01-16 18:21:49.000000000 -0800 +++ 25/arch/arm/nwfpe/entry26.S 2003-04-29 20:50:34.000000000 -0700 @@ -66,7 +66,6 @@ several floating point instructions. */ .globl nwfpe_enter nwfpe_enter: mov sl, sp - ldr r5, [sp, #60] @ get contents of PC bic r5, r5, #0xfc000003 ldr r0, [r5, #-4] @ get actual instruction into r0 @@ -96,7 +95,7 @@ next: @ if condition code failed to match, next insn beq next @ get the next instruction; - + mov r0, r6 @ prepare for EmulateAll() adr lr, 1b orr lr, lr, #3 --- linux-2.5.68/arch/arm/nwfpe/entry.S 2003-01-16 18:21:34.000000000 -0800 +++ 25/arch/arm/nwfpe/entry.S 2003-04-29 20:50:34.000000000 -0700 @@ -72,37 +72,37 @@ several floating point instructions. */ .globl nwfpe_enter nwfpe_enter: - mov r4, lr @ save the failure-return addresses - mov sl, sp + mov r4, lr @ save the failure-return addresses + mov sl, sp @ we access the registers via 'sl' - ldr r5, [sp, #60] @ get contents of PC; + ldr r5, [sp, #60] @ get contents of PC; emulate: - bl EmulateAll @ emulate the instruction - cmp r0, #0 @ was emulation successful - moveq pc, r4 @ no, return failure + bl EmulateAll @ emulate the instruction + cmp r0, #0 @ was emulation successful + moveq pc, r4 @ no, return failure next: -.Lx1: ldrt r6, [r5], #4 @ get the next instruction and +.Lx1: ldrt r6, [r5], #4 @ get the next instruction and @ increment PC - and r2, r6, #0x0F000000 @ test for FP insns - teq r2, #0x0C000000 - teqne r2, #0x0D000000 - teqne r2, #0x0E000000 - movne pc, r9 @ return ok if not a fp insn - - str r5, [sp, #60] @ update PC copy in regs - - mov r0, r6 @ save a copy - ldr r1, [sp, #64] @ fetch the condition codes - bl checkCondition @ check the condition - cmp r0, #0 @ r0 = 0 ==> condition failed - - @ if condition code failed to match, next insn - beq next @ get the next instruction; - - mov r0, r6 @ prepare for EmulateAll() - b emulate @ if r0 != 0, goto EmulateAll + and r2, r6, #0x0F000000 @ test for FP insns + teq r2, #0x0C000000 + teqne r2, #0x0D000000 + teqne r2, #0x0E000000 + movne pc, r9 @ return ok if not a fp insn + + str r5, [sp, #60] @ update PC copy in regs + + mov r0, r6 @ save a copy + ldr r1, [sp, #64] @ fetch the condition codes + bl checkCondition @ check the condition + cmp r0, #0 @ r0 = 0 ==> condition failed + + @ if condition code failed to match, next insn + beq next @ get the next instruction; + + mov r0, r6 @ prepare for EmulateAll() + b emulate @ if r0 != 0, goto EmulateAll @ We need to be prepared for the instructions at .Lx1 and .Lx2 @ to fault. Emit the appropriate exception gunk to fix things up. --- linux-2.5.68/arch/arm/nwfpe/extended_cpdo.c 2003-01-16 18:22:17.000000000 -0800 +++ 25/arch/arm/nwfpe/extended_cpdo.c 2003-04-29 20:50:34.000000000 -0700 @@ -32,242 +32,123 @@ floatx80 floatx80_arctan(floatx80 rFm); floatx80 floatx80_log(floatx80 rFm); floatx80 floatx80_tan(floatx80 rFm); floatx80 floatx80_arccos(floatx80 rFm); -floatx80 floatx80_pow(floatx80 rFn,floatx80 rFm); -floatx80 floatx80_pol(floatx80 rFn,floatx80 rFm); +floatx80 floatx80_pow(floatx80 rFn, floatx80 rFm); +floatx80 floatx80_pol(floatx80 rFn, floatx80 rFm); -unsigned int ExtendedCPDO(const unsigned int opcode) +static floatx80 floatx80_rsf(floatx80 rFn, floatx80 rFm) { - FPA11 *fpa11 = GET_FPA11(); - floatx80 rFm, rFn; - unsigned int Fd, Fm, Fn, nRc = 1; - - //printk("ExtendedCPDO(0x%08x)\n",opcode); - - Fm = getFm(opcode); - if (CONSTANT_FM(opcode)) - { - rFm = getExtendedConstant(Fm); - } - else - { - switch (fpa11->fType[Fm]) - { - case typeSingle: - rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle); - break; - - case typeDouble: - rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble); - break; - - case typeExtended: - rFm = fpa11->fpreg[Fm].fExtended; - break; - - default: return 0; - } - } - - if (!MONADIC_INSTRUCTION(opcode)) - { - Fn = getFn(opcode); - switch (fpa11->fType[Fn]) - { - case typeSingle: - rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle); - break; - - case typeDouble: - rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble); - break; - - case typeExtended: - rFn = fpa11->fpreg[Fn].fExtended; - break; - - default: return 0; - } - } - - Fd = getFd(opcode); - switch (opcode & MASK_ARITHMETIC_OPCODE) - { - /* dyadic opcodes */ - case ADF_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_add(rFn,rFm); - break; - - case MUF_CODE: - case FML_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_mul(rFn,rFm); - break; - - case SUF_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_sub(rFn,rFm); - break; - - case RSF_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_sub(rFm,rFn); - break; - - case DVF_CODE: - case FDV_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_div(rFn,rFm); - break; - - case RDF_CODE: - case FRD_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_div(rFm,rFn); - break; - -#if 0 - case POW_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_pow(rFn,rFm); - break; - - case RPW_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_pow(rFm,rFn); - break; -#endif - - case RMF_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_rem(rFn,rFm); - break; - -#if 0 - case POL_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_pol(rFn,rFm); - break; -#endif - - /* monadic opcodes */ - case MVF_CODE: - fpa11->fpreg[Fd].fExtended = rFm; - break; - - case MNF_CODE: - rFm.high ^= 0x8000; - fpa11->fpreg[Fd].fExtended = rFm; - break; - - case ABS_CODE: - rFm.high &= 0x7fff; - fpa11->fpreg[Fd].fExtended = rFm; - break; - - case RND_CODE: - case URD_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_round_to_int(rFm); - break; - - case SQT_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_sqrt(rFm); - break; - -#if 0 - case LOG_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_log(rFm); - break; - - case LGN_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_ln(rFm); - break; - - case EXP_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_exp(rFm); - break; - - case SIN_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_sin(rFm); - break; - - case COS_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_cos(rFm); - break; - - case TAN_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_tan(rFm); - break; - - case ASN_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_arcsin(rFm); - break; - - case ACS_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_arccos(rFm); - break; - - case ATN_CODE: - fpa11->fpreg[Fd].fExtended = floatx80_arctan(rFm); - break; -#endif - - case NRM_CODE: - break; - - default: - { - nRc = 0; - } - } - - if (0 != nRc) fpa11->fType[Fd] = typeExtended; - return nRc; + return floatx80_sub(rFm, rFn); } -#if 0 -floatx80 floatx80_exp(floatx80 Fm) +static floatx80 floatx80_rdv(floatx80 rFn, floatx80 rFm) { -//series + return floatx80_div(rFm, rFn); } -floatx80 floatx80_ln(floatx80 Fm) -{ -//series -} +static floatx80 (*const dyadic_extended[16])(floatx80 rFn, floatx80 rFm) = { + [ADF_CODE >> 20] = floatx80_add, + [MUF_CODE >> 20] = floatx80_mul, + [SUF_CODE >> 20] = floatx80_sub, + [RSF_CODE >> 20] = floatx80_rsf, + [DVF_CODE >> 20] = floatx80_div, + [RDF_CODE >> 20] = floatx80_rdv, + [RMF_CODE >> 20] = floatx80_rem, -floatx80 floatx80_sin(floatx80 rFm) -{ -//series -} + /* strictly, these opcodes should not be implemented */ + [FML_CODE >> 20] = floatx80_mul, + [FDV_CODE >> 20] = floatx80_div, + [FRD_CODE >> 20] = floatx80_rdv, +}; -floatx80 floatx80_cos(floatx80 rFm) +static floatx80 floatx80_mvf(floatx80 rFm) { -//series + return rFm; } -floatx80 floatx80_arcsin(floatx80 rFm) +static floatx80 floatx80_mnf(floatx80 rFm) { -//series + rFm.high ^= 0x8000; + return rFm; } -floatx80 floatx80_arctan(floatx80 rFm) +static floatx80 floatx80_abs(floatx80 rFm) { - //series + rFm.high &= 0x7fff; + return rFm; } -floatx80 floatx80_log(floatx80 rFm) -{ - return floatx80_div(floatx80_ln(rFm),getExtendedConstant(7)); -} +static floatx80 (*const monadic_extended[16])(floatx80 rFm) = { + [MVF_CODE >> 20] = floatx80_mvf, + [MNF_CODE >> 20] = floatx80_mnf, + [ABS_CODE >> 20] = floatx80_abs, + [RND_CODE >> 20] = floatx80_round_to_int, + [URD_CODE >> 20] = floatx80_round_to_int, + [SQT_CODE >> 20] = floatx80_sqrt, + [NRM_CODE >> 20] = floatx80_mvf, +}; -floatx80 floatx80_tan(floatx80 rFm) +unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd) { - return floatx80_div(floatx80_sin(rFm),floatx80_cos(rFm)); -} + FPA11 *fpa11 = GET_FPA11(); + floatx80 rFm; + unsigned int Fm, opc_mask_shift; -floatx80 floatx80_arccos(floatx80 rFm) -{ - //return floatx80_sub(halfPi,floatx80_arcsin(rFm)); -} + Fm = getFm(opcode); + if (CONSTANT_FM(opcode)) { + rFm = getExtendedConstant(Fm); + } else { + switch (fpa11->fType[Fm]) { + case typeSingle: + rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle); + break; -floatx80 floatx80_pow(floatx80 rFn,floatx80 rFm) -{ - return floatx80_exp(floatx80_mul(rFm,floatx80_ln(rFn))); -} + case typeDouble: + rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble); + break; -floatx80 floatx80_pol(floatx80 rFn,floatx80 rFm) -{ - return floatx80_arctan(floatx80_div(rFn,rFm)); + case typeExtended: + rFm = fpa11->fpreg[Fm].fExtended; + break; + + default: + return 0; + } + } + + opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20; + if (!MONADIC_INSTRUCTION(opcode)) { + unsigned int Fn = getFn(opcode); + floatx80 rFn; + + switch (fpa11->fType[Fn]) { + case typeSingle: + rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle); + break; + + case typeDouble: + rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble); + break; + + case typeExtended: + rFn = fpa11->fpreg[Fn].fExtended; + break; + + default: + return 0; + } + + if (dyadic_extended[opc_mask_shift]) { + rFd->fExtended = dyadic_extended[opc_mask_shift](rFn, rFm); + } else { + return 0; + } + } else { + if (monadic_extended[opc_mask_shift]) { + rFd->fExtended = monadic_extended[opc_mask_shift](rFm); + } else { + return 0; + } + } + + return 1; } -#endif --- linux-2.5.68/arch/arm/nwfpe/fpa11.c 2003-01-16 18:22:02.000000000 -0800 +++ 25/arch/arm/nwfpe/fpa11.c 2003-04-29 20:50:34.000000000 -0700 @@ -1,6 +1,7 @@ /* NetWinder Floating Point Emulator (c) Rebel.COM, 1998,1999 + (c) Philip Blundell, 2001 Direct questions, comments to Scott Bambrough @@ -37,184 +38,105 @@ unsigned int EmulateCPRT(const unsigned /* Reset the FPA11 chip. Called to initialize and reset the emulator. */ static void resetFPA11(void) { - int i; - FPA11 *fpa11 = GET_FPA11(); - - /* initialize the register type array */ - for (i=0;i<=7;i++) - { - fpa11->fType[i] = typeNone; - } - - /* FPSR: set system id to FP_EMULATOR, set AC, clear all other bits */ - fpa11->fpsr = FP_EMULATOR | BIT_AC; - - /* FPCR: set SB, AB and DA bits, clear all others */ -#if MAINTAIN_FPCR - fpa11->fpcr = MASK_RESET; -#endif + int i; + FPA11 *fpa11 = GET_FPA11(); + + /* initialize the register type array */ + for (i = 0; i <= 7; i++) { + fpa11->fType[i] = typeNone; + } + + /* FPSR: set system id to FP_EMULATOR, set AC, clear all other bits */ + fpa11->fpsr = FP_EMULATOR | BIT_AC; } void SetRoundingMode(const unsigned int opcode) { -#if MAINTAIN_FPCR - FPA11 *fpa11 = GET_FPA11(); - fpa11->fpcr &= ~MASK_ROUNDING_MODE; -#endif - switch (opcode & MASK_ROUNDING_MODE) - { - default: - case ROUND_TO_NEAREST: - float_rounding_mode = float_round_nearest_even; -#if MAINTAIN_FPCR - fpa11->fpcr |= ROUND_TO_NEAREST; -#endif - break; - - case ROUND_TO_PLUS_INFINITY: - float_rounding_mode = float_round_up; -#if MAINTAIN_FPCR - fpa11->fpcr |= ROUND_TO_PLUS_INFINITY; -#endif - break; - - case ROUND_TO_MINUS_INFINITY: - float_rounding_mode = float_round_down; -#if MAINTAIN_FPCR - fpa11->fpcr |= ROUND_TO_MINUS_INFINITY; -#endif - break; - - case ROUND_TO_ZERO: - float_rounding_mode = float_round_to_zero; -#if MAINTAIN_FPCR - fpa11->fpcr |= ROUND_TO_ZERO; -#endif - break; - } + switch (opcode & MASK_ROUNDING_MODE) { + default: + case ROUND_TO_NEAREST: + float_rounding_mode = float_round_nearest_even; + break; + + case ROUND_TO_PLUS_INFINITY: + float_rounding_mode = float_round_up; + break; + + case ROUND_TO_MINUS_INFINITY: + float_rounding_mode = float_round_down; + break; + + case ROUND_TO_ZERO: + float_rounding_mode = float_round_to_zero; + break; + } } void SetRoundingPrecision(const unsigned int opcode) { -#if MAINTAIN_FPCR - FPA11 *fpa11 = GET_FPA11(); - fpa11->fpcr &= ~MASK_ROUNDING_PRECISION; -#endif - switch (opcode & MASK_ROUNDING_PRECISION) - { - case ROUND_SINGLE: - floatx80_rounding_precision = 32; -#if MAINTAIN_FPCR - fpa11->fpcr |= ROUND_SINGLE; -#endif - break; - - case ROUND_DOUBLE: - floatx80_rounding_precision = 64; -#if MAINTAIN_FPCR - fpa11->fpcr |= ROUND_DOUBLE; -#endif - break; - - case ROUND_EXTENDED: - floatx80_rounding_precision = 80; -#if MAINTAIN_FPCR - fpa11->fpcr |= ROUND_EXTENDED; -#endif - break; - - default: floatx80_rounding_precision = 80; - } +#ifdef CONFIG_FPE_NWFPE_XP + switch (opcode & MASK_ROUNDING_PRECISION) { + case ROUND_SINGLE: + floatx80_rounding_precision = 32; + break; + + case ROUND_DOUBLE: + floatx80_rounding_precision = 64; + break; + + case ROUND_EXTENDED: + floatx80_rounding_precision = 80; + break; + + default: + floatx80_rounding_precision = 80; + } +#endif } -void nwfpe_init(union fp_state *fp) +void nwfpe_init_fpa(union fp_state *fp) { - FPA11 *fpa11 = (FPA11 *)fp; - memset(fpa11, 0, sizeof(FPA11)); - resetFPA11(); - SetRoundingMode(ROUND_TO_NEAREST); - SetRoundingPrecision(ROUND_EXTENDED); - fpa11->initflag = 1; + FPA11 *fpa11 = (FPA11 *)fp; +#ifdef NWFPE_DEBUG + printk("NWFPE: setting up state.\n"); +#endif + memset(fpa11, 0, sizeof(FPA11)); + resetFPA11(); + SetRoundingMode(ROUND_TO_NEAREST); + SetRoundingPrecision(ROUND_EXTENDED); + fpa11->initflag = 1; } /* Emulate the instruction in the opcode. */ unsigned int EmulateAll(unsigned int opcode) { - unsigned int nRc = 1, code; - - code = opcode & 0x00000f00; - if (code == 0x00000100 || code == 0x00000200) - { - /* For coprocessor 1 or 2 (FPA11) */ - code = opcode & 0x0e000000; - if (code == 0x0e000000) - { - if (opcode & 0x00000010) - { - /* Emulate conversion opcodes. */ - /* Emulate register transfer opcodes. */ - /* Emulate comparison opcodes. */ - nRc = EmulateCPRT(opcode); - } - else - { - /* Emulate monadic arithmetic opcodes. */ - /* Emulate dyadic arithmetic opcodes. */ - nRc = EmulateCPDO(opcode); - } - } - else if (code == 0x0c000000) - { - /* Emulate load/store opcodes. */ - /* Emulate load/store multiple opcodes. */ - nRc = EmulateCPDT(opcode); - } - else - { - /* Invalid instruction detected. Return FALSE. */ - nRc = 0; - } - } + unsigned int code; - return(nRc); -} - -#if 0 -unsigned int EmulateAll1(unsigned int opcode) -{ - switch ((opcode >> 24) & 0xf) - { - case 0xc: - case 0xd: - if ((opcode >> 20) & 0x1) - { - switch ((opcode >> 8) & 0xf) - { - case 0x1: return PerformLDF(opcode); break; - case 0x2: return PerformLFM(opcode); break; - default: return 0; - } - } - else - { - switch ((opcode >> 8) & 0xf) - { - case 0x1: return PerformSTF(opcode); break; - case 0x2: return PerformSFM(opcode); break; - default: return 0; - } - } - break; - - case 0xe: - if (opcode & 0x10) - return EmulateCPDO(opcode); - else - return EmulateCPRT(opcode); - break; - - default: return 0; - } -} +#ifdef NWFPE_DEBUG + printk("NWFPE: emulating opcode %08x\n", opcode); #endif + code = opcode & 0x00000f00; + if (code == 0x00000100 || code == 0x00000200) { + /* For coprocessor 1 or 2 (FPA11) */ + code = opcode & 0x0e000000; + if (code == 0x0e000000) { + if (opcode & 0x00000010) { + /* Emulate conversion opcodes. */ + /* Emulate register transfer opcodes. */ + /* Emulate comparison opcodes. */ + return EmulateCPRT(opcode); + } else { + /* Emulate monadic arithmetic opcodes. */ + /* Emulate dyadic arithmetic opcodes. */ + return EmulateCPDO(opcode); + } + } else if (code == 0x0c000000) { + /* Emulate load/store opcodes. */ + /* Emulate load/store multiple opcodes. */ + return EmulateCPDT(opcode); + } + } + /* Invalid instruction detected. Return FALSE. */ + return 0; +} --- linux-2.5.68/arch/arm/nwfpe/fpa11_cpdo.c 2003-01-16 18:22:26.000000000 -0800 +++ 25/arch/arm/nwfpe/fpa11_cpdo.c 2003-04-29 20:50:34.000000000 -0700 @@ -1,6 +1,7 @@ /* NetWinder Floating Point Emulator (c) Rebel.COM, 1998,1999 + (c) Philip Blundell, 2001 Direct questions, comments to Scott Bambrough @@ -22,96 +23,109 @@ #include "fpa11.h" #include "fpopcode.h" -unsigned int SingleCPDO(const unsigned int opcode); -unsigned int DoubleCPDO(const unsigned int opcode); -unsigned int ExtendedCPDO(const unsigned int opcode); +unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd); +unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd); +unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd); unsigned int EmulateCPDO(const unsigned int opcode) { - FPA11 *fpa11 = GET_FPA11(); - unsigned int Fd, nType, nDest, nRc = 1; - - //printk("EmulateCPDO(0x%08x)\n",opcode); - - /* Get the destination size. If not valid let Linux perform - an invalid instruction trap. */ - nDest = getDestinationSize(opcode); - if (typeNone == nDest) return 0; - - SetRoundingMode(opcode); - - /* Compare the size of the operands in Fn and Fm. - Choose the largest size and perform operations in that size, - in order to make use of all the precision of the operands. - If Fm is a constant, we just grab a constant of a size - matching the size of the operand in Fn. */ - if (MONADIC_INSTRUCTION(opcode)) - nType = nDest; - else - nType = fpa11->fType[getFn(opcode)]; - - if (!CONSTANT_FM(opcode)) - { - register unsigned int Fm = getFm(opcode); - if (nType < fpa11->fType[Fm]) - { - nType = fpa11->fType[Fm]; - } - } - - switch (nType) - { - case typeSingle : nRc = SingleCPDO(opcode); break; - case typeDouble : nRc = DoubleCPDO(opcode); break; - case typeExtended : nRc = ExtendedCPDO(opcode); break; - default : nRc = 0; - } - - /* If the operation succeeded, check to see if the result in the - destination register is the correct size. If not force it - to be. */ - Fd = getFd(opcode); - nType = fpa11->fType[Fd]; - if ((0 != nRc) && (nDest != nType)) - { - switch (nDest) - { - case typeSingle: - { - if (typeDouble == nType) - fpa11->fpreg[Fd].fSingle = - float64_to_float32(fpa11->fpreg[Fd].fDouble); - else - fpa11->fpreg[Fd].fSingle = - floatx80_to_float32(fpa11->fpreg[Fd].fExtended); - } - break; - - case typeDouble: - { - if (typeSingle == nType) - fpa11->fpreg[Fd].fDouble = - float32_to_float64(fpa11->fpreg[Fd].fSingle); - else - fpa11->fpreg[Fd].fDouble = - floatx80_to_float64(fpa11->fpreg[Fd].fExtended); - } - break; - - case typeExtended: - { - if (typeSingle == nType) - fpa11->fpreg[Fd].fExtended = - float32_to_floatx80(fpa11->fpreg[Fd].fSingle); - else - fpa11->fpreg[Fd].fExtended = - float64_to_floatx80(fpa11->fpreg[Fd].fDouble); - } - break; - } - - fpa11->fType[Fd] = nDest; - } - - return nRc; + FPA11 *fpa11 = GET_FPA11(); + FPREG *rFd; + unsigned int nType, nDest, nRc; + + /* Get the destination size. If not valid let Linux perform + an invalid instruction trap. */ + nDest = getDestinationSize(opcode); + if (typeNone == nDest) + return 0; + + SetRoundingMode(opcode); + + /* Compare the size of the operands in Fn and Fm. + Choose the largest size and perform operations in that size, + in order to make use of all the precision of the operands. + If Fm is a constant, we just grab a constant of a size + matching the size of the operand in Fn. */ + if (MONADIC_INSTRUCTION(opcode)) + nType = nDest; + else + nType = fpa11->fType[getFn(opcode)]; + + if (!CONSTANT_FM(opcode)) { + register unsigned int Fm = getFm(opcode); + if (nType < fpa11->fType[Fm]) { + nType = fpa11->fType[Fm]; + } + } + + rFd = &fpa11->fpreg[getFd(opcode)]; + + switch (nType) { + case typeSingle: + nRc = SingleCPDO(opcode, rFd); + break; + case typeDouble: + nRc = DoubleCPDO(opcode, rFd); + break; +#ifdef CONFIG_FPE_NWFPE_XP + case typeExtended: + nRc = ExtendedCPDO(opcode, rFd); + break; +#endif + default: + nRc = 0; + } + + /* The CPDO functions used to always set the destination type + to be the same as their working size. */ + + if (nRc != 0) { + /* If the operation succeeded, check to see if the result in the + destination register is the correct size. If not force it + to be. */ + + fpa11->fType[getFd(opcode)] = nDest; + +#ifdef CONFIG_FPE_NWFPE_XP + if (nDest != nType) { + switch (nDest) { + case typeSingle: + { + if (typeDouble == nType) + rFd->fSingle = float64_to_float32(rFd->fDouble); + else + rFd->fSingle = floatx80_to_float32(rFd->fExtended); + } + break; + + case typeDouble: + { + if (typeSingle == nType) + rFd->fDouble = float32_to_float64(rFd->fSingle); + else + rFd->fDouble = floatx80_to_float64(rFd->fExtended); + } + break; + + case typeExtended: + { + if (typeSingle == nType) + rFd->fExtended = float32_to_floatx80(rFd->fSingle); + else + rFd->fExtended = float64_to_floatx80(rFd->fDouble); + } + break; + } + } +#else + if (nDest != nType) { + if (nDest == typeSingle) + rFd->fSingle = float64_to_float32(rFd->fDouble); + else + rFd->fDouble = float32_to_float64(rFd->fSingle); + } +#endif + } + + return nRc; } --- linux-2.5.68/arch/arm/nwfpe/fpa11_cpdt.c 2003-01-16 18:22:46.000000000 -0800 +++ 25/arch/arm/nwfpe/fpa11_cpdt.c 2003-04-29 20:50:34.000000000 -0700 @@ -1,7 +1,7 @@ /* NetWinder Floating Point Emulator (c) Rebel.com, 1998-1999 - (c) Philip Blundell, 1998 + (c) Philip Blundell, 1998, 2001 Direct questions, comments to Scott Bambrough @@ -28,341 +28,354 @@ #include -static inline -void loadSingle(const unsigned int Fn,const unsigned int *pMem) +static inline void loadSingle(const unsigned int Fn, const unsigned int *pMem) { - FPA11 *fpa11 = GET_FPA11(); - fpa11->fType[Fn] = typeSingle; - get_user(fpa11->fpreg[Fn].fSingle, pMem); -} - -static inline -void loadDouble(const unsigned int Fn,const unsigned int *pMem) -{ - FPA11 *fpa11 = GET_FPA11(); - unsigned int *p; - p = (unsigned int*)&fpa11->fpreg[Fn].fDouble; - fpa11->fType[Fn] = typeDouble; - get_user(p[0], &pMem[1]); - get_user(p[1], &pMem[0]); /* sign & exponent */ -} - -static inline -void loadExtended(const unsigned int Fn,const unsigned int *pMem) -{ - FPA11 *fpa11 = GET_FPA11(); - unsigned int *p; - p = (unsigned int*)&fpa11->fpreg[Fn].fExtended; - fpa11->fType[Fn] = typeExtended; - get_user(p[0], &pMem[0]); /* sign & exponent */ - get_user(p[1], &pMem[2]); /* ls bits */ - get_user(p[2], &pMem[1]); /* ms bits */ -} - -static inline -void loadMultiple(const unsigned int Fn,const unsigned int *pMem) -{ - FPA11 *fpa11 = GET_FPA11(); - register unsigned int *p; - unsigned long x; - - p = (unsigned int*)&(fpa11->fpreg[Fn]); - get_user(x, &pMem[0]); - fpa11->fType[Fn] = (x >> 14) & 0x00000003; - - switch (fpa11->fType[Fn]) - { - case typeSingle: - case typeDouble: - { - get_user(p[0], &pMem[2]); /* Single */ - get_user(p[1], &pMem[1]); /* double msw */ - p[2] = 0; /* empty */ - } - break; - - case typeExtended: - { - get_user(p[1], &pMem[2]); - get_user(p[2], &pMem[1]); /* msw */ - p[0] = (x & 0x80003fff); - } - break; - } -} - -static inline -void storeSingle(const unsigned int Fn,unsigned int *pMem) -{ - FPA11 *fpa11 = GET_FPA11(); - union - { - float32 f; - unsigned int i[1]; - } val; - - switch (fpa11->fType[Fn]) - { - case typeDouble: - val.f = float64_to_float32(fpa11->fpreg[Fn].fDouble); - break; - - case typeExtended: - val.f = floatx80_to_float32(fpa11->fpreg[Fn].fExtended); - break; - - default: val.f = fpa11->fpreg[Fn].fSingle; - } - - put_user(val.i[0], pMem); -} - -static inline -void storeDouble(const unsigned int Fn,unsigned int *pMem) -{ - FPA11 *fpa11 = GET_FPA11(); - union - { - float64 f; - unsigned int i[2]; - } val; - - switch (fpa11->fType[Fn]) - { - case typeSingle: - val.f = float32_to_float64(fpa11->fpreg[Fn].fSingle); - break; - - case typeExtended: - val.f = floatx80_to_float64(fpa11->fpreg[Fn].fExtended); - break; - - default: val.f = fpa11->fpreg[Fn].fDouble; - } - - put_user(val.i[1], &pMem[0]); /* msw */ - put_user(val.i[0], &pMem[1]); /* lsw */ -} - -static inline -void storeExtended(const unsigned int Fn,unsigned int *pMem) -{ - FPA11 *fpa11 = GET_FPA11(); - union - { - floatx80 f; - unsigned int i[3]; - } val; - - switch (fpa11->fType[Fn]) - { - case typeSingle: - val.f = float32_to_floatx80(fpa11->fpreg[Fn].fSingle); - break; - - case typeDouble: - val.f = float64_to_floatx80(fpa11->fpreg[Fn].fDouble); - break; - - default: val.f = fpa11->fpreg[Fn].fExtended; - } - - put_user(val.i[0], &pMem[0]); /* sign & exp */ - put_user(val.i[1], &pMem[2]); - put_user(val.i[2], &pMem[1]); /* msw */ -} - -static inline -void storeMultiple(const unsigned int Fn,unsigned int *pMem) -{ - FPA11 *fpa11 = GET_FPA11(); - register unsigned int nType, *p; - - p = (unsigned int*)&(fpa11->fpreg[Fn]); - nType = fpa11->fType[Fn]; - - switch (nType) - { - case typeSingle: - case typeDouble: - { - put_user(p[0], &pMem[2]); /* single */ - put_user(p[1], &pMem[1]); /* double msw */ - put_user(nType << 14, &pMem[0]); - } - break; - - case typeExtended: - { - put_user(p[2], &pMem[1]); /* msw */ - put_user(p[1], &pMem[2]); - put_user((p[0] & 0x80003fff) | (nType << 14), &pMem[0]); - } - break; - } + FPA11 *fpa11 = GET_FPA11(); + fpa11->fType[Fn] = typeSingle; + get_user(fpa11->fpreg[Fn].fSingle, pMem); } -unsigned int PerformLDF(const unsigned int opcode) +static inline void loadDouble(const unsigned int Fn, const unsigned int *pMem) +{ + FPA11 *fpa11 = GET_FPA11(); + unsigned int *p; + p = (unsigned int *) &fpa11->fpreg[Fn].fDouble; + fpa11->fType[Fn] = typeDouble; + get_user(p[0], &pMem[1]); + get_user(p[1], &pMem[0]); /* sign & exponent */ +} + +#ifdef CONFIG_FPE_NWFPE_XP +static inline void loadExtended(const unsigned int Fn, const unsigned int *pMem) +{ + FPA11 *fpa11 = GET_FPA11(); + unsigned int *p; + p = (unsigned int *) &fpa11->fpreg[Fn].fExtended; + fpa11->fType[Fn] = typeExtended; + get_user(p[0], &pMem[0]); /* sign & exponent */ + get_user(p[1], &pMem[2]); /* ls bits */ + get_user(p[2], &pMem[1]); /* ms bits */ +} +#endif + +static inline void loadMultiple(const unsigned int Fn, const unsigned int *pMem) { - unsigned int *pBase, *pAddress, *pFinal, nRc = 1, - write_back = WRITE_BACK(opcode); + FPA11 *fpa11 = GET_FPA11(); + register unsigned int *p; + unsigned long x; + + p = (unsigned int *) &(fpa11->fpreg[Fn]); + get_user(x, &pMem[0]); + fpa11->fType[Fn] = (x >> 14) & 0x00000003; + + switch (fpa11->fType[Fn]) { + case typeSingle: + case typeDouble: + { + get_user(p[0], &pMem[2]); /* Single */ + get_user(p[1], &pMem[1]); /* double msw */ + p[2] = 0; /* empty */ + } + break; + +#ifdef CONFIG_FPE_NWFPE_XP + case typeExtended: + { + get_user(p[1], &pMem[2]); + get_user(p[2], &pMem[1]); /* msw */ + p[0] = (x & 0x80003fff); + } + break; +#endif + } +} - //printk("PerformLDF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode)); +static inline void storeSingle(const unsigned int Fn, unsigned int *pMem) +{ + FPA11 *fpa11 = GET_FPA11(); + union { + float32 f; + unsigned int i[1]; + } val; + + switch (fpa11->fType[Fn]) { + case typeDouble: + val.f = float64_to_float32(fpa11->fpreg[Fn].fDouble); + break; + +#ifdef CONFIG_FPE_NWFPE_XP + case typeExtended: + val.f = floatx80_to_float32(fpa11->fpreg[Fn].fExtended); + break; +#endif - pBase = (unsigned int*)readRegister(getRn(opcode)); - if (REG_PC == getRn(opcode)) - { - pBase += 2; - write_back = 0; - } - - pFinal = pBase; - if (BIT_UP_SET(opcode)) - pFinal += getOffset(opcode); - else - pFinal -= getOffset(opcode); - - if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase; - - switch (opcode & MASK_TRANSFER_LENGTH) - { - case TRANSFER_SINGLE : loadSingle(getFd(opcode),pAddress); break; - case TRANSFER_DOUBLE : loadDouble(getFd(opcode),pAddress); break; - case TRANSFER_EXTENDED: loadExtended(getFd(opcode),pAddress); break; - default: nRc = 0; - } + default: + val.f = fpa11->fpreg[Fn].fSingle; + } + + put_user(val.i[0], pMem); +} + +static inline void storeDouble(const unsigned int Fn, unsigned int *pMem) +{ + FPA11 *fpa11 = GET_FPA11(); + union { + float64 f; + unsigned int i[2]; + } val; + + switch (fpa11->fType[Fn]) { + case typeSingle: + val.f = float32_to_float64(fpa11->fpreg[Fn].fSingle); + break; + +#ifdef CONFIG_FPE_NWFPE_XP + case typeExtended: + val.f = floatx80_to_float64(fpa11->fpreg[Fn].fExtended); + break; +#endif - if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal); - return nRc; + default: + val.f = fpa11->fpreg[Fn].fDouble; + } + + put_user(val.i[1], &pMem[0]); /* msw */ + put_user(val.i[0], &pMem[1]); /* lsw */ +} + +#ifdef CONFIG_FPE_NWFPE_XP +static inline void storeExtended(const unsigned int Fn, unsigned int *pMem) +{ + FPA11 *fpa11 = GET_FPA11(); + union { + floatx80 f; + unsigned int i[3]; + } val; + + switch (fpa11->fType[Fn]) { + case typeSingle: + val.f = float32_to_floatx80(fpa11->fpreg[Fn].fSingle); + break; + + case typeDouble: + val.f = float64_to_floatx80(fpa11->fpreg[Fn].fDouble); + break; + + default: + val.f = fpa11->fpreg[Fn].fExtended; + } + + put_user(val.i[0], &pMem[0]); /* sign & exp */ + put_user(val.i[1], &pMem[2]); + put_user(val.i[2], &pMem[1]); /* msw */ } +#endif -unsigned int PerformSTF(const unsigned int opcode) +static inline void storeMultiple(const unsigned int Fn, unsigned int *pMem) +{ + FPA11 *fpa11 = GET_FPA11(); + register unsigned int nType, *p; + + p = (unsigned int *) &(fpa11->fpreg[Fn]); + nType = fpa11->fType[Fn]; + + switch (nType) { + case typeSingle: + case typeDouble: + { + put_user(p[0], &pMem[2]); /* single */ + put_user(p[1], &pMem[1]); /* double msw */ + put_user(nType << 14, &pMem[0]); + } + break; + +#ifdef CONFIG_FPE_NWFPE_XP + case typeExtended: + { + put_user(p[2], &pMem[1]); /* msw */ + put_user(p[1], &pMem[2]); + put_user((p[0] & 0x80003fff) | (nType << 14), &pMem[0]); + } + break; +#endif + } +} + +unsigned int PerformLDF(const unsigned int opcode) { - unsigned int *pBase, *pAddress, *pFinal, nRc = 1, - write_back = WRITE_BACK(opcode); + unsigned int *pBase, *pAddress, *pFinal, nRc = 1, + write_back = WRITE_BACK(opcode); + + pBase = (unsigned int *) readRegister(getRn(opcode)); + if (REG_PC == getRn(opcode)) { + pBase += 2; + write_back = 0; + } + + pFinal = pBase; + if (BIT_UP_SET(opcode)) + pFinal += getOffset(opcode); + else + pFinal -= getOffset(opcode); + + if (PREINDEXED(opcode)) + pAddress = pFinal; + else + pAddress = pBase; + + switch (opcode & MASK_TRANSFER_LENGTH) { + case TRANSFER_SINGLE: + loadSingle(getFd(opcode), pAddress); + break; + case TRANSFER_DOUBLE: + loadDouble(getFd(opcode), pAddress); + break; +#ifdef CONFIG_FPE_NWFPE_XP + case TRANSFER_EXTENDED: + loadExtended(getFd(opcode), pAddress); + break; +#endif + default: + nRc = 0; + } + + if (write_back) + writeRegister(getRn(opcode), (unsigned int) pFinal); + return nRc; +} - //printk("PerformSTF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode)); - SetRoundingMode(ROUND_TO_NEAREST); +unsigned int PerformSTF(const unsigned int opcode) +{ + unsigned int *pBase, *pAddress, *pFinal, nRc = 1, + write_back = WRITE_BACK(opcode); - pBase = (unsigned int*)readRegister(getRn(opcode)); - if (REG_PC == getRn(opcode)) - { - pBase += 2; - write_back = 0; - } - - pFinal = pBase; - if (BIT_UP_SET(opcode)) - pFinal += getOffset(opcode); - else - pFinal -= getOffset(opcode); - - if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase; - - switch (opcode & MASK_TRANSFER_LENGTH) - { - case TRANSFER_SINGLE : storeSingle(getFd(opcode),pAddress); break; - case TRANSFER_DOUBLE : storeDouble(getFd(opcode),pAddress); break; - case TRANSFER_EXTENDED: storeExtended(getFd(opcode),pAddress); break; - default: nRc = 0; - } + SetRoundingMode(ROUND_TO_NEAREST); - if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal); - return nRc; + pBase = (unsigned int *) readRegister(getRn(opcode)); + if (REG_PC == getRn(opcode)) { + pBase += 2; + write_back = 0; + } + + pFinal = pBase; + if (BIT_UP_SET(opcode)) + pFinal += getOffset(opcode); + else + pFinal -= getOffset(opcode); + + if (PREINDEXED(opcode)) + pAddress = pFinal; + else + pAddress = pBase; + + switch (opcode & MASK_TRANSFER_LENGTH) { + case TRANSFER_SINGLE: + storeSingle(getFd(opcode), pAddress); + break; + case TRANSFER_DOUBLE: + storeDouble(getFd(opcode), pAddress); + break; +#ifdef CONFIG_FPE_NWFPE_XP + case TRANSFER_EXTENDED: + storeExtended(getFd(opcode), pAddress); + break; +#endif + default: + nRc = 0; + } + + if (write_back) + writeRegister(getRn(opcode), (unsigned int) pFinal); + return nRc; } unsigned int PerformLFM(const unsigned int opcode) { - unsigned int i, Fd, *pBase, *pAddress, *pFinal, - write_back = WRITE_BACK(opcode); + unsigned int i, Fd, *pBase, *pAddress, *pFinal, + write_back = WRITE_BACK(opcode); - pBase = (unsigned int*)readRegister(getRn(opcode)); - if (REG_PC == getRn(opcode)) - { - pBase += 2; - write_back = 0; - } - - pFinal = pBase; - if (BIT_UP_SET(opcode)) - pFinal += getOffset(opcode); - else - pFinal -= getOffset(opcode); - - if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase; - - Fd = getFd(opcode); - for (i=getRegisterCount(opcode);i>0;i--) - { - loadMultiple(Fd,pAddress); - pAddress += 3; Fd++; - if (Fd == 8) Fd = 0; - } - - if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal); - return 1; + pBase = (unsigned int *) readRegister(getRn(opcode)); + if (REG_PC == getRn(opcode)) { + pBase += 2; + write_back = 0; + } + + pFinal = pBase; + if (BIT_UP_SET(opcode)) + pFinal += getOffset(opcode); + else + pFinal -= getOffset(opcode); + + if (PREINDEXED(opcode)) + pAddress = pFinal; + else + pAddress = pBase; + + Fd = getFd(opcode); + for (i = getRegisterCount(opcode); i > 0; i--) { + loadMultiple(Fd, pAddress); + pAddress += 3; + Fd++; + if (Fd == 8) + Fd = 0; + } + + if (write_back) + writeRegister(getRn(opcode), (unsigned int) pFinal); + return 1; } unsigned int PerformSFM(const unsigned int opcode) { - unsigned int i, Fd, *pBase, *pAddress, *pFinal, - write_back = WRITE_BACK(opcode); - - pBase = (unsigned int*)readRegister(getRn(opcode)); - if (REG_PC == getRn(opcode)) - { - pBase += 2; - write_back = 0; - } - - pFinal = pBase; - if (BIT_UP_SET(opcode)) - pFinal += getOffset(opcode); - else - pFinal -= getOffset(opcode); - - if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase; - - Fd = getFd(opcode); - for (i=getRegisterCount(opcode);i>0;i--) - { - storeMultiple(Fd,pAddress); - pAddress += 3; Fd++; - if (Fd == 8) Fd = 0; - } + unsigned int i, Fd, *pBase, *pAddress, *pFinal, + write_back = WRITE_BACK(opcode); - if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal); - return 1; + pBase = (unsigned int *) readRegister(getRn(opcode)); + if (REG_PC == getRn(opcode)) { + pBase += 2; + write_back = 0; + } + + pFinal = pBase; + if (BIT_UP_SET(opcode)) + pFinal += getOffset(opcode); + else + pFinal -= getOffset(opcode); + + if (PREINDEXED(opcode)) + pAddress = pFinal; + else + pAddress = pBase; + + Fd = getFd(opcode); + for (i = getRegisterCount(opcode); i > 0; i--) { + storeMultiple(Fd, pAddress); + pAddress += 3; + Fd++; + if (Fd == 8) + Fd = 0; + } + + if (write_back) + writeRegister(getRn(opcode), (unsigned int) pFinal); + return 1; } -#if 1 unsigned int EmulateCPDT(const unsigned int opcode) { - unsigned int nRc = 0; + unsigned int nRc = 0; - //printk("EmulateCPDT(0x%08x)\n",opcode); + if (LDF_OP(opcode)) { + nRc = PerformLDF(opcode); + } else if (LFM_OP(opcode)) { + nRc = PerformLFM(opcode); + } else if (STF_OP(opcode)) { + nRc = PerformSTF(opcode); + } else if (SFM_OP(opcode)) { + nRc = PerformSFM(opcode); + } else { + nRc = 0; + } - if (LDF_OP(opcode)) - { - nRc = PerformLDF(opcode); - } - else if (LFM_OP(opcode)) - { - nRc = PerformLFM(opcode); - } - else if (STF_OP(opcode)) - { - nRc = PerformSTF(opcode); - } - else if (SFM_OP(opcode)) - { - nRc = PerformSFM(opcode); - } - else - { - nRc = 0; - } - - return nRc; + return nRc; } -#endif --- linux-2.5.68/arch/arm/nwfpe/fpa11_cprt.c 2003-01-16 18:22:23.000000000 -0800 +++ 25/arch/arm/nwfpe/fpa11_cprt.c 2003-04-29 20:50:34.000000000 -0700 @@ -1,7 +1,7 @@ /* NetWinder Floating Point Emulator (c) Rebel.COM, 1998,1999 - (c) Philip Blundell, 1999 + (c) Philip Blundell, 1999, 2001 Direct questions, comments to Scott Bambrough @@ -21,269 +21,348 @@ */ #include "fpa11.h" -#include "milieu.h" -#include "softfloat.h" #include "fpopcode.h" #include "fpa11.inl" #include "fpmodule.h" #include "fpmodule.inl" +#ifdef CONFIG_FPE_NWFPE_XP extern flag floatx80_is_nan(floatx80); -extern flag float64_is_nan( float64); -extern flag float32_is_nan( float32); +#endif +extern flag float64_is_nan(float64); +extern flag float32_is_nan(float32); void SetRoundingMode(const unsigned int opcode); unsigned int PerformFLT(const unsigned int opcode); unsigned int PerformFIX(const unsigned int opcode); -static unsigned int -PerformComparison(const unsigned int opcode); +static unsigned int PerformComparison(const unsigned int opcode); unsigned int EmulateCPRT(const unsigned int opcode) { - unsigned int nRc = 1; - - //printk("EmulateCPRT(0x%08x)\n",opcode); - if (opcode & 0x800000) - { - /* This is some variant of a comparison (PerformComparison will - sort out which one). Since most of the other CPRT - instructions are oddball cases of some sort or other it makes - sense to pull this out into a fast path. */ - return PerformComparison(opcode); - } - - /* Hint to GCC that we'd like a jump table rather than a load of CMPs */ - switch ((opcode & 0x700000) >> 20) - { - case FLT_CODE >> 20: nRc = PerformFLT(opcode); break; - case FIX_CODE >> 20: nRc = PerformFIX(opcode); break; - - case WFS_CODE >> 20: writeFPSR(readRegister(getRd(opcode))); break; - case RFS_CODE >> 20: writeRegister(getRd(opcode),readFPSR()); break; - -#if 0 /* We currently have no use for the FPCR, so there's no point - in emulating it. */ - case WFC_CODE >> 20: writeFPCR(readRegister(getRd(opcode))); - case RFC_CODE >> 20: writeRegister(getRd(opcode),readFPCR()); break; -#endif + if (opcode & 0x800000) { + /* This is some variant of a comparison (PerformComparison + will sort out which one). Since most of the other CPRT + instructions are oddball cases of some sort or other it + makes sense to pull this out into a fast path. */ + return PerformComparison(opcode); + } + + /* Hint to GCC that we'd like a jump table rather than a load of CMPs */ + switch ((opcode & 0x700000) >> 20) { + case FLT_CODE >> 20: + return PerformFLT(opcode); + break; + case FIX_CODE >> 20: + return PerformFIX(opcode); + break; + + case WFS_CODE >> 20: + writeFPSR(readRegister(getRd(opcode))); + break; + case RFS_CODE >> 20: + writeRegister(getRd(opcode), readFPSR()); + break; + + default: + return 0; + } - default: nRc = 0; - } - - return nRc; + return 1; } unsigned int PerformFLT(const unsigned int opcode) { - FPA11 *fpa11 = GET_FPA11(); - - unsigned int nRc = 1; - SetRoundingMode(opcode); - - switch (opcode & MASK_ROUNDING_PRECISION) - { - case ROUND_SINGLE: - { - fpa11->fType[getFn(opcode)] = typeSingle; - fpa11->fpreg[getFn(opcode)].fSingle = - int32_to_float32(readRegister(getRd(opcode))); - } - break; - - case ROUND_DOUBLE: - { - fpa11->fType[getFn(opcode)] = typeDouble; - fpa11->fpreg[getFn(opcode)].fDouble = - int32_to_float64(readRegister(getRd(opcode))); - } - break; - - case ROUND_EXTENDED: - { - fpa11->fType[getFn(opcode)] = typeExtended; - fpa11->fpreg[getFn(opcode)].fExtended = - int32_to_floatx80(readRegister(getRd(opcode))); - } - break; - - default: nRc = 0; - } - - return nRc; + FPA11 *fpa11 = GET_FPA11(); + SetRoundingMode(opcode); + SetRoundingPrecision(opcode); + + switch (opcode & MASK_ROUNDING_PRECISION) { + case ROUND_SINGLE: + { + fpa11->fType[getFn(opcode)] = typeSingle; + fpa11->fpreg[getFn(opcode)].fSingle = int32_to_float32(readRegister(getRd(opcode))); + } + break; + + case ROUND_DOUBLE: + { + fpa11->fType[getFn(opcode)] = typeDouble; + fpa11->fpreg[getFn(opcode)].fDouble = int32_to_float64(readRegister(getRd(opcode))); + } + break; + +#ifdef CONFIG_FPE_NWFPE_XP + case ROUND_EXTENDED: + { + fpa11->fType[getFn(opcode)] = typeExtended; + fpa11->fpreg[getFn(opcode)].fExtended = int32_to_floatx80(readRegister(getRd(opcode))); + } + break; +#endif + + default: + return 0; + } + + return 1; } unsigned int PerformFIX(const unsigned int opcode) { - FPA11 *fpa11 = GET_FPA11(); - unsigned int nRc = 1; - unsigned int Fn = getFm(opcode); - - SetRoundingMode(opcode); - - switch (fpa11->fType[Fn]) - { - case typeSingle: - { - writeRegister(getRd(opcode), - float32_to_int32(fpa11->fpreg[Fn].fSingle)); - } - break; - - case typeDouble: - { - writeRegister(getRd(opcode), - float64_to_int32(fpa11->fpreg[Fn].fDouble)); - } - break; - - case typeExtended: - { - writeRegister(getRd(opcode), - floatx80_to_int32(fpa11->fpreg[Fn].fExtended)); - } - break; - - default: nRc = 0; - } - - return nRc; -} + FPA11 *fpa11 = GET_FPA11(); + unsigned int Fn = getFm(opcode); - -static unsigned int __inline__ -PerformComparisonOperation(floatx80 Fn, floatx80 Fm) -{ - unsigned int flags = 0; + SetRoundingMode(opcode); - /* test for less than condition */ - if (floatx80_lt(Fn,Fm)) - { - flags |= CC_NEGATIVE; - } - - /* test for equal condition */ - if (floatx80_eq(Fn,Fm)) - { - flags |= CC_ZERO; - } - - /* test for greater than or equal condition */ - if (floatx80_lt(Fm,Fn)) - { - flags |= CC_CARRY; - } - - writeConditionCodes(flags); - return 1; + switch (fpa11->fType[Fn]) { + case typeSingle: + { + writeRegister(getRd(opcode), float32_to_int32(fpa11->fpreg[Fn].fSingle)); + } + break; + + case typeDouble: + { + writeRegister(getRd(opcode), float64_to_int32(fpa11->fpreg[Fn].fDouble)); + } + break; + +#ifdef CONFIG_FPE_NWFPE_XP + case typeExtended: + { + writeRegister(getRd(opcode), floatx80_to_int32(fpa11->fpreg[Fn].fExtended)); + } + break; +#endif + + default: + return 0; + } + + return 1; } /* This instruction sets the flags N, Z, C, V in the FPSR. */ - static unsigned int PerformComparison(const unsigned int opcode) { - FPA11 *fpa11 = GET_FPA11(); - unsigned int Fn, Fm; - floatx80 rFn, rFm; - int e_flag = opcode & 0x400000; /* 1 if CxFE */ - int n_flag = opcode & 0x200000; /* 1 if CNxx */ - unsigned int flags = 0; - - //printk("PerformComparison(0x%08x)\n",opcode); - - Fn = getFn(opcode); - Fm = getFm(opcode); - - /* Check for unordered condition and convert all operands to 80-bit - format. - ?? Might be some mileage in avoiding this conversion if possible. - Eg, if both operands are 32-bit, detect this and do a 32-bit - comparison (cheaper than an 80-bit one). */ - switch (fpa11->fType[Fn]) - { - case typeSingle: - //printk("single.\n"); - if (float32_is_nan(fpa11->fpreg[Fn].fSingle)) - goto unordered; - rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle); - break; - - case typeDouble: - //printk("double.\n"); - if (float64_is_nan(fpa11->fpreg[Fn].fDouble)) - goto unordered; - rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble); - break; - - case typeExtended: - //printk("extended.\n"); - if (floatx80_is_nan(fpa11->fpreg[Fn].fExtended)) - goto unordered; - rFn = fpa11->fpreg[Fn].fExtended; - break; - - default: return 0; - } - - if (CONSTANT_FM(opcode)) - { - //printk("Fm is a constant: #%d.\n",Fm); - rFm = getExtendedConstant(Fm); - if (floatx80_is_nan(rFm)) - goto unordered; - } - else - { - //printk("Fm = r%d which contains a ",Fm); - switch (fpa11->fType[Fm]) - { - case typeSingle: - //printk("single.\n"); - if (float32_is_nan(fpa11->fpreg[Fm].fSingle)) - goto unordered; - rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle); - break; - - case typeDouble: - //printk("double.\n"); - if (float64_is_nan(fpa11->fpreg[Fm].fDouble)) - goto unordered; - rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble); - break; - - case typeExtended: - //printk("extended.\n"); - if (floatx80_is_nan(fpa11->fpreg[Fm].fExtended)) - goto unordered; - rFm = fpa11->fpreg[Fm].fExtended; - break; - - default: return 0; - } - } - - if (n_flag) - { - rFm.high ^= 0x8000; - } - - return PerformComparisonOperation(rFn,rFm); - - unordered: - /* ?? The FPA data sheet is pretty vague about this, in particular - about whether the non-E comparisons can ever raise exceptions. - This implementation is based on a combination of what it says in - the data sheet, observation of how the Acorn emulator actually - behaves (and how programs expect it to) and guesswork. */ - flags |= CC_OVERFLOW; - flags &= ~(CC_ZERO | CC_NEGATIVE); + FPA11 *fpa11 = GET_FPA11(); + unsigned int Fn = getFn(opcode), Fm = getFm(opcode); + int e_flag = opcode & 0x400000; /* 1 if CxFE */ + int n_flag = opcode & 0x200000; /* 1 if CNxx */ + unsigned int flags = 0; + +#ifdef CONFIG_FPE_NWFPE_XP + floatx80 rFn, rFm; + + /* Check for unordered condition and convert all operands to 80-bit + format. + ?? Might be some mileage in avoiding this conversion if possible. + Eg, if both operands are 32-bit, detect this and do a 32-bit + comparison (cheaper than an 80-bit one). */ + switch (fpa11->fType[Fn]) { + case typeSingle: + //printk("single.\n"); + if (float32_is_nan(fpa11->fpreg[Fn].fSingle)) + goto unordered; + rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle); + break; + + case typeDouble: + //printk("double.\n"); + if (float64_is_nan(fpa11->fpreg[Fn].fDouble)) + goto unordered; + rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble); + break; + + case typeExtended: + //printk("extended.\n"); + if (floatx80_is_nan(fpa11->fpreg[Fn].fExtended)) + goto unordered; + rFn = fpa11->fpreg[Fn].fExtended; + break; + + default: + return 0; + } + + if (CONSTANT_FM(opcode)) { + //printk("Fm is a constant: #%d.\n",Fm); + rFm = getExtendedConstant(Fm); + if (floatx80_is_nan(rFm)) + goto unordered; + } else { + //printk("Fm = r%d which contains a ",Fm); + switch (fpa11->fType[Fm]) { + case typeSingle: + //printk("single.\n"); + if (float32_is_nan(fpa11->fpreg[Fm].fSingle)) + goto unordered; + rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle); + break; + + case typeDouble: + //printk("double.\n"); + if (float64_is_nan(fpa11->fpreg[Fm].fDouble)) + goto unordered; + rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble); + break; + + case typeExtended: + //printk("extended.\n"); + if (floatx80_is_nan(fpa11->fpreg[Fm].fExtended)) + goto unordered; + rFm = fpa11->fpreg[Fm].fExtended; + break; + + default: + return 0; + } + } + + if (n_flag) + rFm.high ^= 0x8000; + + /* test for less than condition */ + if (floatx80_lt(rFn, rFm)) + flags |= CC_NEGATIVE; + + /* test for equal condition */ + if (floatx80_eq(rFn, rFm)) + flags |= CC_ZERO; + + /* test for greater than or equal condition */ + if (floatx80_lt(rFm, rFn)) + flags |= CC_CARRY; + +#else + if (CONSTANT_FM(opcode)) { + /* Fm is a constant. Do the comparison in whatever precision + Fn happens to be stored in. */ + if (fpa11->fType[Fn] == typeSingle) { + float32 rFm = getSingleConstant(Fm); + float32 rFn = fpa11->fpreg[Fn].fSingle; + + if (float32_is_nan(rFn)) + goto unordered; + + if (n_flag) + rFm ^= 0x80000000; + + /* test for less than condition */ + if (float32_lt_nocheck(rFn, rFm)) + flags |= CC_NEGATIVE; + + /* test for equal condition */ + if (float32_eq_nocheck(rFn, rFm)) + flags |= CC_ZERO; + + /* test for greater than or equal condition */ + if (float32_lt_nocheck(rFm, rFn)) + flags |= CC_CARRY; + } else { + float64 rFm = getDoubleConstant(Fm); + float64 rFn = fpa11->fpreg[Fn].fDouble; + + if (float64_is_nan(rFn)) + goto unordered; + + if (n_flag) + rFm ^= 0x8000000000000000ULL; + + /* test for less than condition */ + if (float64_lt_nocheck(rFn, rFm)) + flags |= CC_NEGATIVE; + + /* test for equal condition */ + if (float64_eq_nocheck(rFn, rFm)) + flags |= CC_ZERO; + + /* test for greater than or equal condition */ + if (float64_lt_nocheck(rFm, rFn)) + flags |= CC_CARRY; + } + } else { + /* Both operands are in registers. */ + if (fpa11->fType[Fn] == typeSingle + && fpa11->fType[Fm] == typeSingle) { + float32 rFm = fpa11->fpreg[Fm].fSingle; + float32 rFn = fpa11->fpreg[Fn].fSingle; + + if (float32_is_nan(rFn) + || float32_is_nan(rFm)) + goto unordered; + + if (n_flag) + rFm ^= 0x80000000; + + /* test for less than condition */ + if (float32_lt_nocheck(rFn, rFm)) + flags |= CC_NEGATIVE; + + /* test for equal condition */ + if (float32_eq_nocheck(rFn, rFm)) + flags |= CC_ZERO; + + /* test for greater than or equal condition */ + if (float32_lt_nocheck(rFm, rFn)) + flags |= CC_CARRY; + } else { + /* Promote 32-bit operand to 64 bits. */ + float64 rFm, rFn; + + rFm = (fpa11->fType[Fm] == typeSingle) ? + float32_to_float64(fpa11->fpreg[Fm].fSingle) + : fpa11->fpreg[Fm].fDouble; + + rFn = (fpa11->fType[Fn] == typeSingle) ? + float32_to_float64(fpa11->fpreg[Fn].fSingle) + : fpa11->fpreg[Fn].fDouble; + + if (float64_is_nan(rFn) + || float64_is_nan(rFm)) + goto unordered; + + if (n_flag) + rFm ^= 0x8000000000000000ULL; + + /* test for less than condition */ + if (float64_lt_nocheck(rFn, rFm)) + flags |= CC_NEGATIVE; + + /* test for equal condition */ + if (float64_eq_nocheck(rFn, rFm)) + flags |= CC_ZERO; + + /* test for greater than or equal condition */ + if (float64_lt_nocheck(rFm, rFn)) + flags |= CC_CARRY; + } + } + +#endif + + writeConditionCodes(flags); + + return 1; + + unordered: + /* ?? The FPA data sheet is pretty vague about this, in particular + about whether the non-E comparisons can ever raise exceptions. + This implementation is based on a combination of what it says in + the data sheet, observation of how the Acorn emulator actually + behaves (and how programs expect it to) and guesswork. */ + flags |= CC_OVERFLOW; + flags &= ~(CC_ZERO | CC_NEGATIVE); - if (BIT_AC & readFPSR()) flags |= CC_CARRY; + if (BIT_AC & readFPSR()) + flags |= CC_CARRY; - if (e_flag) float_raise(float_flag_invalid); + if (e_flag) + float_raise(float_flag_invalid); - writeConditionCodes(flags); - return 1; + writeConditionCodes(flags); + return 1; } --- linux-2.5.68/arch/arm/nwfpe/fpa11.h 2003-01-16 18:22:05.000000000 -0800 +++ 25/arch/arm/nwfpe/fpa11.h 2003-04-29 20:50:34.000000000 -0700 @@ -37,6 +37,7 @@ register unsigned int *user_registers as /* includes */ #include "fpsr.h" /* FP control and status register definitions */ +#include "milieu.h" #include "softfloat.h" #define typeNone 0x00 @@ -48,9 +49,13 @@ register unsigned int *user_registers as * This must be no more and no less than 12 bytes. */ typedef union tagFPREG { - floatx80 fExtended; - float64 fDouble; - float32 fSingle; + float32 fSingle; + float64 fDouble; +#ifdef CONFIG_FPE_NWFPE_XP + floatx80 fExtended; +#else + int padding[3]; +#endif } FPREG; /* @@ -67,21 +72,21 @@ typedef union tagFPREG { * not initialise. */ typedef struct tagFPA11 { -/* 0 */ FPREG fpreg[8]; /* 8 floating point registers */ -/* 96 */ FPSR fpsr; /* floating point status register */ -/* 100 */ FPCR fpcr; /* floating point control register */ -/* 104 */ unsigned char fType[8]; /* type of floating point value held in - floating point registers. One of none - single, double or extended. */ -/* 112 */ int initflag; /* this is special. The kernel guarantees - to set it to 0 when a thread is launched, - so we can use it to detect whether this - instance of the emulator needs to be - initialised. */ +/* 0 */ FPREG fpreg[8]; /* 8 floating point registers */ +/* 96 */ FPSR fpsr; /* floating point status register */ +/* 100 */ FPCR fpcr; /* floating point control register */ +/* 104 */ unsigned char fType[8]; /* type of floating point value held in + floating point registers. One of + none, single, double or extended. */ +/* 112 */ int initflag; /* this is special. The kernel guarantees + to set it to 0 when a thread is launched, + so we can use it to detect whether this + instance of the emulator needs to be + initialised. */ } FPA11; extern void SetRoundingMode(const unsigned int); extern void SetRoundingPrecision(const unsigned int); -extern void nwfpe_init(union fp_state *fp); +extern void nwfpe_init_fpa(union fp_state *fp); #endif --- linux-2.5.68/arch/arm/nwfpe/fpa11.inl 2003-01-16 18:22:09.000000000 -0800 +++ 25/arch/arm/nwfpe/fpa11.inl 2003-04-29 20:50:34.000000000 -0700 @@ -24,28 +24,28 @@ /* Read and write floating point status register */ extern __inline__ unsigned int readFPSR(void) { - FPA11 *fpa11 = GET_FPA11(); - return(fpa11->fpsr); + FPA11 *fpa11 = GET_FPA11(); + return (fpa11->fpsr); } extern __inline__ void writeFPSR(FPSR reg) { - FPA11 *fpa11 = GET_FPA11(); - /* the sysid byte in the status register is readonly */ - fpa11->fpsr = (fpa11->fpsr & MASK_SYSID) | (reg & ~MASK_SYSID); + FPA11 *fpa11 = GET_FPA11(); + /* the sysid byte in the status register is readonly */ + fpa11->fpsr = (fpa11->fpsr & MASK_SYSID) | (reg & ~MASK_SYSID); } /* Read and write floating point control register */ extern __inline__ FPCR readFPCR(void) { - FPA11 *fpa11 = GET_FPA11(); - /* clear SB, AB and DA bits before returning FPCR */ - return(fpa11->fpcr & ~MASK_RFC); + FPA11 *fpa11 = GET_FPA11(); + /* clear SB, AB and DA bits before returning FPCR */ + return (fpa11->fpcr & ~MASK_RFC); } extern __inline__ void writeFPCR(FPCR reg) { - FPA11 *fpa11 = GET_FPA11(); - fpa11->fpcr &= ~MASK_WFC; /* clear SB, AB and DA bits */ - fpa11->fpcr |= (reg & MASK_WFC); /* write SB, AB and DA bits */ + FPA11 *fpa11 = GET_FPA11(); + fpa11->fpcr &= ~MASK_WFC; /* clear SB, AB and DA bits */ + fpa11->fpcr |= (reg & MASK_WFC); /* write SB, AB and DA bits */ } --- linux-2.5.68/arch/arm/nwfpe/fpmodule.c 2003-01-16 18:22:05.000000000 -0800 +++ 25/arch/arm/nwfpe/fpmodule.c 2003-04-29 20:50:34.000000000 -0700 @@ -42,11 +42,17 @@ #include "fpa11.inl" /* kernel symbols required for signal handling */ +#ifdef CONFIG_FPE_NWFPE_XP +#define NWFPE_BITS "extended" +#else +#define NWFPE_BITS "double" +#endif + #ifdef MODULE void fp_send_sig(unsigned long sig, struct task_struct *p, int priv); #if LINUX_VERSION_CODE > 0x20115 MODULE_AUTHOR("Scott Bambrough "); -MODULE_DESCRIPTION("NWFPE floating point emulator"); +MODULE_DESCRIPTION("NWFPE floating point emulator (" NWFPE_BITS " precision)"); #endif #else @@ -63,63 +69,45 @@ void fp_setup(void); extern void (*kern_fp_enter)(void); extern void (*fp_init)(union fp_state *); -/* Original value of fp_enter from kernel before patched by fpe_init. */ +/* Original value of fp_enter from kernel before patched by fpe_init. */ static void (*orig_fp_enter)(void); static void (*orig_fp_init)(union fp_state *); /* forward declarations */ extern void nwfpe_enter(void); -#ifdef MODULE -/* - * Return 0 if we can be unloaded. This can only happen if - * kern_fp_enter is still pointing at nwfpe_enter - */ -static int fpe_unload(void) -{ - return (kern_fp_enter == nwfpe_enter) ? 0 : 1; -} -#endif - static int __init fpe_init(void) { - if (sizeof(FPA11) > sizeof(union fp_state)) { - printk(KERN_ERR "nwfpe: bad structure size\n"); - return -EINVAL; - } - - if (sizeof(FPREG) != 12) { - printk(KERN_ERR "nwfpe: bad register size\n"); - return -EINVAL; - } + if (sizeof(FPA11) > sizeof(union fp_state)) { + printk(KERN_ERR "nwfpe: bad structure size\n"); + return -EINVAL; + } + + if (sizeof(FPREG) != 12) { + printk(KERN_ERR "nwfpe: bad register size\n"); + return -EINVAL; + } + if (fpe_type[0] && strcmp(fpe_type, "nwfpe")) + return 0; + + /* Display title, version and copyright information. */ + printk(KERN_WARNING "NetWinder Floating Point Emulator V0.97 (" + NWFPE_BITS " precision)\n"); + + /* Save pointer to the old FP handler and then patch ourselves in */ + orig_fp_enter = kern_fp_enter; + orig_fp_init = fp_init; + kern_fp_enter = nwfpe_enter; + fp_init = nwfpe_init_fpa; -#ifdef MODULE - if (!mod_member_present(&__this_module, can_unload)) - return -EINVAL; - __this_module.can_unload = fpe_unload; -#else - if (fpe_type[0] && strcmp(fpe_type, "nwfpe")) - return 0; -#endif - - /* Display title, version and copyright information. */ - printk(KERN_WARNING "NetWinder Floating Point Emulator V0.95 " - "(c) 1998-1999 Rebel.com\n"); - - /* Save pointer to the old FP handler and then patch ourselves in */ - orig_fp_enter = kern_fp_enter; - orig_fp_init = fp_init; - kern_fp_enter = nwfpe_enter; - fp_init = nwfpe_init; - - return 0; + return 0; } static void __exit fpe_exit(void) { - /* Restore the values we saved earlier. */ - kern_fp_enter = orig_fp_enter; - fp_init = orig_fp_init; + /* Restore the values we saved earlier. */ + kern_fp_enter = orig_fp_enter; + fp_init = orig_fp_init; } /* @@ -144,41 +132,42 @@ cumulative exceptions flag byte are set void float_raise(signed char flags) { - register unsigned int fpsr, cumulativeTraps; - + register unsigned int fpsr, cumulativeTraps; + #ifdef CONFIG_DEBUG_USER - printk(KERN_DEBUG "NWFPE: %s[%d] takes exception %08x at %p from %08x\n", - current->comm, current->pid, flags, - __builtin_return_address(0), GET_USERREG()[15]); + printk(KERN_DEBUG + "NWFPE: %s[%d] takes exception %08x at %p from %08x\n", + current->comm, current->pid, flags, + __builtin_return_address(0), GET_USERREG()[15]); #endif - /* Keep SoftFloat exception flags up to date. */ - float_exception_flags |= flags; + /* Keep SoftFloat exception flags up to date. */ + float_exception_flags |= flags; - /* Read fpsr and initialize the cumulativeTraps. */ - fpsr = readFPSR(); - cumulativeTraps = 0; - - /* For each type of exception, the cumulative trap exception bit is only - set if the corresponding trap enable bit is not set. */ - if ((!(fpsr & BIT_IXE)) && (flags & BIT_IXC)) - cumulativeTraps |= BIT_IXC; - if ((!(fpsr & BIT_UFE)) && (flags & BIT_UFC)) - cumulativeTraps |= BIT_UFC; - if ((!(fpsr & BIT_OFE)) && (flags & BIT_OFC)) - cumulativeTraps |= BIT_OFC; - if ((!(fpsr & BIT_DZE)) && (flags & BIT_DZC)) - cumulativeTraps |= BIT_DZC; - if ((!(fpsr & BIT_IOE)) && (flags & BIT_IOC)) - cumulativeTraps |= BIT_IOC; - - /* Set the cumulative exceptions flags. */ - if (cumulativeTraps) - writeFPSR(fpsr | cumulativeTraps); - - /* Raise an exception if necessary. */ - if (fpsr & (flags << 16)) - fp_send_sig(SIGFPE, current, 1); + /* Read fpsr and initialize the cumulativeTraps. */ + fpsr = readFPSR(); + cumulativeTraps = 0; + + /* For each type of exception, the cumulative trap exception bit is only + set if the corresponding trap enable bit is not set. */ + if ((!(fpsr & BIT_IXE)) && (flags & BIT_IXC)) + cumulativeTraps |= BIT_IXC; + if ((!(fpsr & BIT_UFE)) && (flags & BIT_UFC)) + cumulativeTraps |= BIT_UFC; + if ((!(fpsr & BIT_OFE)) && (flags & BIT_OFC)) + cumulativeTraps |= BIT_OFC; + if ((!(fpsr & BIT_DZE)) && (flags & BIT_DZC)) + cumulativeTraps |= BIT_DZC; + if ((!(fpsr & BIT_IOE)) && (flags & BIT_IOC)) + cumulativeTraps |= BIT_IOC; + + /* Set the cumulative exceptions flags. */ + if (cumulativeTraps) + writeFPSR(fpsr | cumulativeTraps); + + /* Raise an exception if necessary. */ + if (fpsr & (flags << 16)) + fp_send_sig(SIGFPE, current, 1); } module_init(fpe_init); --- linux-2.5.68/arch/arm/nwfpe/fpmodule.inl 2003-01-16 18:22:44.000000000 -0800 +++ 25/arch/arm/nwfpe/fpmodule.inl 2003-04-29 20:50:34.000000000 -0700 @@ -22,63 +22,64 @@ extern __inline__ unsigned int readRegister(const unsigned int nReg) { - /* Note: The CPU thinks it has dealt with the current instruction. As - a result the program counter has been advanced to the next - instruction, and points 4 bytes beyond the actual instruction - that caused the invalid instruction trap to occur. We adjust - for this in this routine. LDF/STF instructions with Rn = PC - depend on the PC being correct, as they use PC+8 in their - address calculations. */ - unsigned int *userRegisters = GET_USERREG(); - unsigned int val = userRegisters[nReg]; - if (REG_PC == nReg) val -= 4; - return val; + /* Note: The CPU thinks it has dealt with the current instruction. + As a result the program counter has been advanced to the next + instruction, and points 4 bytes beyond the actual instruction + that caused the invalid instruction trap to occur. We adjust + for this in this routine. LDF/STF instructions with Rn = PC + depend on the PC being correct, as they use PC+8 in their + address calculations. */ + unsigned int *userRegisters = GET_USERREG(); + unsigned int val = userRegisters[nReg]; + if (REG_PC == nReg) + val -= 4; + return val; } extern __inline__ void writeRegister(const unsigned int nReg, const unsigned int val) { - unsigned int *userRegisters = GET_USERREG(); - userRegisters[nReg] = val; + unsigned int *userRegisters = GET_USERREG(); + userRegisters[nReg] = val; } extern __inline__ unsigned int readCPSR(void) { - return(readRegister(REG_CPSR)); + return (readRegister(REG_CPSR)); } extern __inline__ void writeCPSR(const unsigned int val) { - writeRegister(REG_CPSR,val); + writeRegister(REG_CPSR, val); } extern __inline__ unsigned int readConditionCodes(void) { #ifdef __FPEM_TEST__ - return(0); + return (0); #else - return(readCPSR() & CC_MASK); + return (readCPSR() & CC_MASK); #endif } extern __inline__ void writeConditionCodes(const unsigned int val) { - unsigned int *userRegisters = GET_USERREG(); - unsigned int rval; - /* - * Operate directly on userRegisters since - * the CPSR may be the PC register itself. - */ - rval = userRegisters[REG_CPSR] & ~CC_MASK; - userRegisters[REG_CPSR] = rval | (val & CC_MASK); + unsigned int *userRegisters = GET_USERREG(); + unsigned int rval; + /* + * Operate directly on userRegisters since + * the CPSR may be the PC register itself. + */ + rval = userRegisters[REG_CPSR] & ~CC_MASK; + userRegisters[REG_CPSR] = rval | (val & CC_MASK); } extern __inline__ unsigned int readMemoryInt(unsigned int *pMem) { - return *pMem; + return *pMem; } --- linux-2.5.68/arch/arm/nwfpe/fpopcode.c 2003-01-16 18:22:04.000000000 -0800 +++ 25/arch/arm/nwfpe/fpopcode.c 2003-04-29 20:50:34.000000000 -0700 @@ -26,123 +26,64 @@ #include "fpmodule.h" #include "fpmodule.inl" +#ifdef CONFIG_FPE_NWFPE_XP const floatx80 floatx80Constant[] = { - { 0x0000, 0x0000000000000000ULL}, /* extended 0.0 */ - { 0x3fff, 0x8000000000000000ULL}, /* extended 1.0 */ - { 0x4000, 0x8000000000000000ULL}, /* extended 2.0 */ - { 0x4000, 0xc000000000000000ULL}, /* extended 3.0 */ - { 0x4001, 0x8000000000000000ULL}, /* extended 4.0 */ - { 0x4001, 0xa000000000000000ULL}, /* extended 5.0 */ - { 0x3ffe, 0x8000000000000000ULL}, /* extended 0.5 */ - { 0x4002, 0xa000000000000000ULL} /* extended 10.0 */ -}; + {0x0000, 0x0000000000000000ULL}, /* extended 0.0 */ + {0x3fff, 0x8000000000000000ULL}, /* extended 1.0 */ + {0x4000, 0x8000000000000000ULL}, /* extended 2.0 */ + {0x4000, 0xc000000000000000ULL}, /* extended 3.0 */ + {0x4001, 0x8000000000000000ULL}, /* extended 4.0 */ + {0x4001, 0xa000000000000000ULL}, /* extended 5.0 */ + {0x3ffe, 0x8000000000000000ULL}, /* extended 0.5 */ + {0x4002, 0xa000000000000000ULL} /* extended 10.0 */ +}; +#endif const float64 float64Constant[] = { - 0x0000000000000000ULL, /* double 0.0 */ - 0x3ff0000000000000ULL, /* double 1.0 */ - 0x4000000000000000ULL, /* double 2.0 */ - 0x4008000000000000ULL, /* double 3.0 */ - 0x4010000000000000ULL, /* double 4.0 */ - 0x4014000000000000ULL, /* double 5.0 */ - 0x3fe0000000000000ULL, /* double 0.5 */ - 0x4024000000000000ULL /* double 10.0 */ -}; + 0x0000000000000000ULL, /* double 0.0 */ + 0x3ff0000000000000ULL, /* double 1.0 */ + 0x4000000000000000ULL, /* double 2.0 */ + 0x4008000000000000ULL, /* double 3.0 */ + 0x4010000000000000ULL, /* double 4.0 */ + 0x4014000000000000ULL, /* double 5.0 */ + 0x3fe0000000000000ULL, /* double 0.5 */ + 0x4024000000000000ULL /* double 10.0 */ +}; const float32 float32Constant[] = { - 0x00000000, /* single 0.0 */ - 0x3f800000, /* single 1.0 */ - 0x40000000, /* single 2.0 */ - 0x40400000, /* single 3.0 */ - 0x40800000, /* single 4.0 */ - 0x40a00000, /* single 5.0 */ - 0x3f000000, /* single 0.5 */ - 0x41200000 /* single 10.0 */ -}; - -unsigned int getTransferLength(const unsigned int opcode) -{ - unsigned int nRc; - - switch (opcode & MASK_TRANSFER_LENGTH) - { - case 0x00000000: nRc = 1; break; /* single precision */ - case 0x00008000: nRc = 2; break; /* double precision */ - case 0x00400000: nRc = 3; break; /* extended precision */ - default: nRc = 0; - } - - return(nRc); -} - -unsigned int getRegisterCount(const unsigned int opcode) -{ - unsigned int nRc; - - switch (opcode & MASK_REGISTER_COUNT) - { - case 0x00000000: nRc = 4; break; - case 0x00008000: nRc = 1; break; - case 0x00400000: nRc = 2; break; - case 0x00408000: nRc = 3; break; - default: nRc = 0; - } - - return(nRc); -} - -unsigned int getRoundingPrecision(const unsigned int opcode) -{ - unsigned int nRc; - - switch (opcode & MASK_ROUNDING_PRECISION) - { - case 0x00000000: nRc = 1; break; - case 0x00000080: nRc = 2; break; - case 0x00080000: nRc = 3; break; - default: nRc = 0; - } - - return(nRc); -} - -unsigned int getDestinationSize(const unsigned int opcode) -{ - unsigned int nRc; - - switch (opcode & MASK_DESTINATION_SIZE) - { - case 0x00000000: nRc = typeSingle; break; - case 0x00000080: nRc = typeDouble; break; - case 0x00080000: nRc = typeExtended; break; - default: nRc = typeNone; - } - - return(nRc); -} + 0x00000000, /* single 0.0 */ + 0x3f800000, /* single 1.0 */ + 0x40000000, /* single 2.0 */ + 0x40400000, /* single 3.0 */ + 0x40800000, /* single 4.0 */ + 0x40a00000, /* single 5.0 */ + 0x3f000000, /* single 0.5 */ + 0x41200000 /* single 10.0 */ +}; /* condition code lookup table index into the table is test code: EQ, NE, ... LT, GT, AL, NV bit position in short is condition code: NZCV */ static const unsigned short aCC[16] = { - 0xF0F0, // EQ == Z set - 0x0F0F, // NE - 0xCCCC, // CS == C set - 0x3333, // CC - 0xFF00, // MI == N set - 0x00FF, // PL - 0xAAAA, // VS == V set - 0x5555, // VC - 0x0C0C, // HI == C set && Z clear - 0xF3F3, // LS == C clear || Z set - 0xAA55, // GE == (N==V) - 0x55AA, // LT == (N!=V) - 0x0A05, // GT == (!Z && (N==V)) - 0xF5FA, // LE == (Z || (N!=V)) - 0xFFFF, // AL always - 0 // NV + 0xF0F0, // EQ == Z set + 0x0F0F, // NE + 0xCCCC, // CS == C set + 0x3333, // CC + 0xFF00, // MI == N set + 0x00FF, // PL + 0xAAAA, // VS == V set + 0x5555, // VC + 0x0C0C, // HI == C set && Z clear + 0xF3F3, // LS == C clear || Z set + 0xAA55, // GE == (N==V) + 0x55AA, // LT == (N!=V) + 0x0A05, // GT == (!Z && (N==V)) + 0xF5FA, // LE == (Z || (N!=V)) + 0xFFFF, // AL always + 0 // NV }; unsigned int checkCondition(const unsigned int opcode, const unsigned int ccodes) { - return (aCC[opcode>>28] >> (ccodes>>28)) & 1; + return (aCC[opcode >> 28] >> (ccodes >> 28)) & 1; } --- linux-2.5.68/arch/arm/nwfpe/fpopcode.h 2003-01-16 18:21:51.000000000 -0800 +++ 25/arch/arm/nwfpe/fpopcode.h 2003-04-29 20:50:34.000000000 -0700 @@ -1,6 +1,7 @@ /* NetWinder Floating Point Emulator (c) Rebel.COM, 1998,1999 + (c) Philip Blundell, 2001 Direct questions, comments to Scott Bambrough @@ -186,7 +187,7 @@ TABLE 5 #define BIT_LOAD 0x00100000 /* masks for load/store */ -#define MASK_CPDT 0x0c000000 /* data processing opcode */ +#define MASK_CPDT 0x0c000000 /* data processing opcode */ #define MASK_OFFSET 0x000000ff #define MASK_TRANSFER_LENGTH 0x00408000 #define MASK_REGISTER_COUNT MASK_TRANSFER_LENGTH @@ -236,7 +237,7 @@ TABLE 5 #define MONADIC_INSTRUCTION(opcode) ((opcode & BIT_MONADIC) != 0) /* instruction identification masks */ -#define MASK_CPDO 0x0e000000 /* arithmetic opcode */ +#define MASK_CPDO 0x0e000000 /* arithmetic opcode */ #define MASK_ARITHMETIC_OPCODE 0x00f08000 #define MASK_DESTINATION_SIZE 0x00080080 @@ -282,7 +283,7 @@ TABLE 5 === */ -#define MASK_CPRT 0x0e000010 /* register transfer opcode */ +#define MASK_CPRT 0x0e000010 /* register transfer opcode */ #define MASK_CPRT_CODE 0x00f00000 #define FLT_CODE 0x00000000 #define FIX_CODE 0x00100000 @@ -366,25 +367,111 @@ TABLE 5 /* Get the rounding mode from the opcode. */ #define getRoundingMode(opcode) ((opcode & MASK_ROUNDING_MODE) >> 5) +#ifdef CONFIG_FPE_NWFPE_XP static inline const floatx80 getExtendedConstant(const unsigned int nIndex) { - extern const floatx80 floatx80Constant[]; - return floatx80Constant[nIndex]; -} + extern const floatx80 floatx80Constant[]; + return floatx80Constant[nIndex]; +} +#endif static inline const float64 getDoubleConstant(const unsigned int nIndex) { - extern const float64 float64Constant[]; - return float64Constant[nIndex]; -} + extern const float64 float64Constant[]; + return float64Constant[nIndex]; +} static inline const float32 getSingleConstant(const unsigned int nIndex) { - extern const float32 float32Constant[]; - return float32Constant[nIndex]; -} + extern const float32 float32Constant[]; + return float32Constant[nIndex]; +} + +static inline unsigned int getTransferLength(const unsigned int opcode) +{ + unsigned int nRc; + + switch (opcode & MASK_TRANSFER_LENGTH) { + case 0x00000000: + nRc = 1; + break; /* single precision */ + case 0x00008000: + nRc = 2; + break; /* double precision */ + case 0x00400000: + nRc = 3; + break; /* extended precision */ + default: + nRc = 0; + } + + return (nRc); +} + +static inline unsigned int getRegisterCount(const unsigned int opcode) +{ + unsigned int nRc; + + switch (opcode & MASK_REGISTER_COUNT) { + case 0x00000000: + nRc = 4; + break; + case 0x00008000: + nRc = 1; + break; + case 0x00400000: + nRc = 2; + break; + case 0x00408000: + nRc = 3; + break; + default: + nRc = 0; + } + + return (nRc); +} + +static inline unsigned int getRoundingPrecision(const unsigned int opcode) +{ + unsigned int nRc; + + switch (opcode & MASK_ROUNDING_PRECISION) { + case 0x00000000: + nRc = 1; + break; + case 0x00000080: + nRc = 2; + break; + case 0x00080000: + nRc = 3; + break; + default: + nRc = 0; + } + + return (nRc); +} + +static inline unsigned int getDestinationSize(const unsigned int opcode) +{ + unsigned int nRc; + + switch (opcode & MASK_DESTINATION_SIZE) { + case 0x00000000: + nRc = typeSingle; + break; + case 0x00000080: + nRc = typeDouble; + break; + case 0x00080000: + nRc = typeExtended; + break; + default: + nRc = typeNone; + } -extern unsigned int getRegisterCount(const unsigned int opcode); -extern unsigned int getDestinationSize(const unsigned int opcode); + return (nRc); +} #endif --- linux-2.5.68/arch/arm/nwfpe/fpsr.h 2003-01-16 18:21:41.000000000 -0800 +++ 25/arch/arm/nwfpe/fpsr.h 2003-04-29 20:50:34.000000000 -0700 @@ -38,12 +38,12 @@ The FPCR is a 32 bit register consisting ------------ Note: the system id byte is read only */ -typedef unsigned int FPSR; /* type for floating point status register */ -typedef unsigned int FPCR; /* type for floating point control register */ +typedef unsigned int FPSR; /* type for floating point status register */ +typedef unsigned int FPCR; /* type for floating point control register */ #define MASK_SYSID 0xff000000 #define BIT_HARDWARE 0x80000000 -#define FP_EMULATOR 0x01000000 /* System ID for emulator */ +#define FP_EMULATOR 0x01000000 /* System ID for emulator */ #define FP_ACCELERATOR 0x81000000 /* System ID for FPA11 */ /* EXCEPTION TRAP ENABLE BYTE @@ -51,11 +51,11 @@ typedef unsigned int FPCR; /* type for #define MASK_TRAP_ENABLE 0x00ff0000 #define MASK_TRAP_ENABLE_STRICT 0x001f0000 -#define BIT_IXE 0x00100000 /* inexact exception enable */ -#define BIT_UFE 0x00080000 /* underflow exception enable */ -#define BIT_OFE 0x00040000 /* overflow exception enable */ -#define BIT_DZE 0x00020000 /* divide by zero exception enable */ -#define BIT_IOE 0x00010000 /* invalid operation exception enable */ +#define BIT_IXE 0x00100000 /* inexact exception enable */ +#define BIT_UFE 0x00080000 /* underflow exception enable */ +#define BIT_OFE 0x00040000 /* overflow exception enable */ +#define BIT_DZE 0x00020000 /* divide by zero exception enable */ +#define BIT_IOE 0x00010000 /* invalid operation exception enable */ /* SYSTEM CONTROL BYTE ---------------------- */ --- linux-2.5.68/arch/arm/nwfpe/Makefile 2003-01-16 18:21:36.000000000 -0800 +++ 25/arch/arm/nwfpe/Makefile 2003-04-29 20:50:34.000000000 -0700 @@ -2,18 +2,12 @@ # Copyright (C) 1998, 1999, 2001 Philip Blundell # -obj-y := -obj-m := -obj-n := +obj-$(CONFIG_FPE_NWFPE) += nwfpe.o -obj-$(CONFIG_FPE_NWFPE) += nwfpe.o +nwfpe-y += fpa11.o fpa11_cpdo.o fpa11_cpdt.o \ + fpa11_cprt.o fpmodule.o fpopcode.o \ + softfloat.o single_cpdo.o double_cpdo.o -nwfpe-objs := fpa11.o fpa11_cpdo.o fpa11_cpdt.o fpa11_cprt.o \ - fpmodule.o fpopcode.o softfloat.o \ - single_cpdo.o double_cpdo.o extended_cpdo.o - -ifeq ($(CONFIG_CPU_26),y) -nwfpe-objs += entry26.o -else -nwfpe-objs += entry.o -endif +nwfpe-$(CONFIG_FPE_NWFPE_XP) += extended_cpdo.o +nwfpe-$(CONFIG_CPU_26) += entry26.o +nwfpe-$(CONFIG_CPU_32) += entry.o --- linux-2.5.68/arch/arm/nwfpe/single_cpdo.c 2003-01-16 18:22:45.000000000 -0800 +++ 25/arch/arm/nwfpe/single_cpdo.c 2003-04-29 20:50:34.000000000 -0700 @@ -1,6 +1,7 @@ /* NetWinder Floating Point Emulator (c) Rebel.COM, 1998,1999 + (c) Philip Blundell, 2001 Direct questions, comments to Scott Bambrough @@ -32,224 +33,92 @@ float32 float32_arctan(float32 rFm); float32 float32_log(float32 rFm); float32 float32_tan(float32 rFm); float32 float32_arccos(float32 rFm); -float32 float32_pow(float32 rFn,float32 rFm); -float32 float32_pol(float32 rFn,float32 rFm); +float32 float32_pow(float32 rFn, float32 rFm); +float32 float32_pol(float32 rFn, float32 rFm); -unsigned int SingleCPDO(const unsigned int opcode) +static float32 float32_rsf(float32 rFn, float32 rFm) { - FPA11 *fpa11 = GET_FPA11(); - float32 rFm, rFn; - unsigned int Fd, Fm, Fn, nRc = 1; - - Fm = getFm(opcode); - if (CONSTANT_FM(opcode)) - { - rFm = getSingleConstant(Fm); - } - else - { - switch (fpa11->fType[Fm]) - { - case typeSingle: - rFm = fpa11->fpreg[Fm].fSingle; - break; - - default: return 0; - } - } - - if (!MONADIC_INSTRUCTION(opcode)) - { - Fn = getFn(opcode); - switch (fpa11->fType[Fn]) - { - case typeSingle: - rFn = fpa11->fpreg[Fn].fSingle; - break; - - default: return 0; - } - } - - Fd = getFd(opcode); - switch (opcode & MASK_ARITHMETIC_OPCODE) - { - /* dyadic opcodes */ - case ADF_CODE: - fpa11->fpreg[Fd].fSingle = float32_add(rFn,rFm); - break; - - case MUF_CODE: - case FML_CODE: - fpa11->fpreg[Fd].fSingle = float32_mul(rFn,rFm); - break; - - case SUF_CODE: - fpa11->fpreg[Fd].fSingle = float32_sub(rFn,rFm); - break; - - case RSF_CODE: - fpa11->fpreg[Fd].fSingle = float32_sub(rFm,rFn); - break; - - case DVF_CODE: - case FDV_CODE: - fpa11->fpreg[Fd].fSingle = float32_div(rFn,rFm); - break; - - case RDF_CODE: - case FRD_CODE: - fpa11->fpreg[Fd].fSingle = float32_div(rFm,rFn); - break; - -#if 0 - case POW_CODE: - fpa11->fpreg[Fd].fSingle = float32_pow(rFn,rFm); - break; - - case RPW_CODE: - fpa11->fpreg[Fd].fSingle = float32_pow(rFm,rFn); - break; -#endif - - case RMF_CODE: - fpa11->fpreg[Fd].fSingle = float32_rem(rFn,rFm); - break; - -#if 0 - case POL_CODE: - fpa11->fpreg[Fd].fSingle = float32_pol(rFn,rFm); - break; -#endif - - /* monadic opcodes */ - case MVF_CODE: - fpa11->fpreg[Fd].fSingle = rFm; - break; - - case MNF_CODE: - rFm ^= 0x80000000; - fpa11->fpreg[Fd].fSingle = rFm; - break; - - case ABS_CODE: - rFm &= 0x7fffffff; - fpa11->fpreg[Fd].fSingle = rFm; - break; - - case RND_CODE: - case URD_CODE: - fpa11->fpreg[Fd].fSingle = float32_round_to_int(rFm); - break; - - case SQT_CODE: - fpa11->fpreg[Fd].fSingle = float32_sqrt(rFm); - break; - -#if 0 - case LOG_CODE: - fpa11->fpreg[Fd].fSingle = float32_log(rFm); - break; - - case LGN_CODE: - fpa11->fpreg[Fd].fSingle = float32_ln(rFm); - break; - - case EXP_CODE: - fpa11->fpreg[Fd].fSingle = float32_exp(rFm); - break; - - case SIN_CODE: - fpa11->fpreg[Fd].fSingle = float32_sin(rFm); - break; - - case COS_CODE: - fpa11->fpreg[Fd].fSingle = float32_cos(rFm); - break; - - case TAN_CODE: - fpa11->fpreg[Fd].fSingle = float32_tan(rFm); - break; - - case ASN_CODE: - fpa11->fpreg[Fd].fSingle = float32_arcsin(rFm); - break; - - case ACS_CODE: - fpa11->fpreg[Fd].fSingle = float32_arccos(rFm); - break; - - case ATN_CODE: - fpa11->fpreg[Fd].fSingle = float32_arctan(rFm); - break; -#endif - - case NRM_CODE: - break; - - default: - { - nRc = 0; - } - } - - if (0 != nRc) fpa11->fType[Fd] = typeSingle; - return nRc; + return float32_sub(rFm, rFn); } -#if 0 -float32 float32_exp(float32 Fm) +static float32 float32_rdv(float32 rFn, float32 rFm) { -//series + return float32_div(rFm, rFn); } -float32 float32_ln(float32 Fm) -{ -//series -} +static float32 (*const dyadic_single[16])(float32 rFn, float32 rFm) = { + [ADF_CODE >> 20] = float32_add, + [MUF_CODE >> 20] = float32_mul, + [SUF_CODE >> 20] = float32_sub, + [RSF_CODE >> 20] = float32_rsf, + [DVF_CODE >> 20] = float32_div, + [RDF_CODE >> 20] = float32_rdv, + [RMF_CODE >> 20] = float32_rem, -float32 float32_sin(float32 rFm) -{ -//series -} + [FML_CODE >> 20] = float32_mul, + [FDV_CODE >> 20] = float32_div, + [FRD_CODE >> 20] = float32_rdv, +}; -float32 float32_cos(float32 rFm) +static float32 float32_mvf(float32 rFm) { -//series + return rFm; } -float32 float32_arcsin(float32 rFm) +static float32 float32_mnf(float32 rFm) { -//series + return rFm ^ 0x80000000; } -float32 float32_arctan(float32 rFm) +static float32 float32_abs(float32 rFm) { - //series + return rFm & 0x7fffffff; } -float32 float32_arccos(float32 rFm) -{ - //return float32_sub(halfPi,float32_arcsin(rFm)); -} +static float32 (*const monadic_single[16])(float32 rFm) = { + [MVF_CODE >> 20] = float32_mvf, + [MNF_CODE >> 20] = float32_mnf, + [ABS_CODE >> 20] = float32_abs, + [RND_CODE >> 20] = float32_round_to_int, + [URD_CODE >> 20] = float32_round_to_int, + [SQT_CODE >> 20] = float32_sqrt, + [NRM_CODE >> 20] = float32_mvf, +}; -float32 float32_log(float32 rFm) +unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd) { - return float32_div(float32_ln(rFm),getSingleConstant(7)); -} + FPA11 *fpa11 = GET_FPA11(); + float32 rFm; + unsigned int Fm, opc_mask_shift; -float32 float32_tan(float32 rFm) -{ - return float32_div(float32_sin(rFm),float32_cos(rFm)); -} + Fm = getFm(opcode); + if (CONSTANT_FM(opcode)) { + rFm = getSingleConstant(Fm); + } else if (fpa11->fType[Fm] == typeSingle) { + rFm = fpa11->fpreg[Fm].fSingle; + } else { + return 0; + } -float32 float32_pow(float32 rFn,float32 rFm) -{ - return float32_exp(float32_mul(rFm,float32_ln(rFn))); -} + opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20; + if (!MONADIC_INSTRUCTION(opcode)) { + unsigned int Fn = getFn(opcode); + float32 rFn; -float32 float32_pol(float32 rFn,float32 rFm) -{ - return float32_arctan(float32_div(rFn,rFm)); + if (fpa11->fType[Fn] == typeSingle && + dyadic_single[opc_mask_shift]) { + rFn = fpa11->fpreg[Fn].fSingle; + rFd->fSingle = dyadic_single[opc_mask_shift](rFn, rFm); + } else { + return 0; + } + } else { + if (monadic_single[opc_mask_shift]) { + rFd->fSingle = monadic_single[opc_mask_shift](rFm); + } else { + return 0; + } + } + + return 1; } -#endif --- linux-2.5.68/arch/arm/nwfpe/softfloat.c 2003-01-16 18:23:01.000000000 -0800 +++ 25/arch/arm/nwfpe/softfloat.c 2003-04-29 20:50:34.000000000 -0700 @@ -29,8 +29,8 @@ this code that are retained. */ #include "fpa11.h" -#include "milieu.h" -#include "softfloat.h" +//#include "milieu.h" +//#include "softfloat.h" /* ------------------------------------------------------------------------------- @@ -142,12 +142,14 @@ INLINE int16 extractFloat32Exp( float32 Returns the sign bit of the single-precision floating-point value `a'. ------------------------------------------------------------------------------- */ +#if 0 /* in softfloat.h */ INLINE flag extractFloat32Sign( float32 a ) { return a>>31; } +#endif /* ------------------------------------------------------------------------------- @@ -184,9 +186,9 @@ INLINE float32 packFloat32( flag zSign, { #if 0 float32 f; - __asm__("@ packFloat32; \n\ - mov %0, %1, asl #31; \n\ - orr %0, %2, asl #23; \n\ + __asm__("@ packFloat32 \n\ + mov %0, %1, asl #31 \n\ + orr %0, %2, asl #23 \n\ orr %0, %3" : /* no outputs */ : "g" (f), "g" (zSign), "g" (zExp), "g" (zSig) @@ -321,12 +323,14 @@ INLINE int16 extractFloat64Exp( float64 Returns the sign bit of the double-precision floating-point value `a'. ------------------------------------------------------------------------------- */ +#if 0 /* in softfloat.h */ INLINE flag extractFloat64Sign( float64 a ) { return a>>63; } +#endif /* ------------------------------------------------------------------------------- --- linux-2.5.68/arch/arm/nwfpe/softfloat.h 2003-01-16 18:21:38.000000000 -0800 +++ 25/arch/arm/nwfpe/softfloat.h 2003-04-29 20:50:34.000000000 -0700 @@ -40,7 +40,9 @@ floating-point format `floatx80'. If th input or output the `floatx80' type will be defined. ------------------------------------------------------------------------------- */ +#ifdef CONFIG_FPE_NWFPE_XP #define FLOATX80 +#endif /* ------------------------------------------------------------------------------- @@ -229,4 +231,46 @@ char floatx80_is_signaling_nan( floatx80 #endif +static inline flag extractFloat32Sign(float32 a) +{ + return a >> 31; +} + +static inline flag float32_eq_nocheck(float32 a, float32 b) +{ + return (a == b) || ((bits32) ((a | b) << 1) == 0); +} + +static inline flag float32_lt_nocheck(float32 a, float32 b) +{ + flag aSign, bSign; + + aSign = extractFloat32Sign(a); + bSign = extractFloat32Sign(b); + if (aSign != bSign) + return aSign && ((bits32) ((a | b) << 1) != 0); + return (a != b) && (aSign ^ (a < b)); +} + +static inline flag extractFloat64Sign(float64 a) +{ + return a >> 63; +} + +static inline flag float64_eq_nocheck(float64 a, float64 b) +{ + return (a == b) || ((bits64) ((a | b) << 1) == 0); +} + +static inline flag float64_lt_nocheck(float64 a, float64 b) +{ + flag aSign, bSign; + + aSign = extractFloat64Sign(a); + bSign = extractFloat64Sign(b); + if (aSign != bSign) + return aSign && ((bits64) ((a | b) << 1) != 0); + return (a != b) && (aSign ^ (a < b)); +} + #endif --- linux-2.5.68/arch/arm/tools/mach-types 2003-04-07 13:06:52.000000000 -0700 +++ 25/arch/arm/tools/mach-types 2003-04-29 20:50:34.000000000 -0700 @@ -6,7 +6,7 @@ # To add an entry into this database, please see Documentation/arm/README, # or contact rmk@arm.linux.org.uk # -# Last update: Tue Mar 25 16:34:29 2003 +# Last update: Sat Apr 26 11:41:41 2003 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -313,3 +313,18 @@ zodiac ARCH_ZODIAC ZODIAC 301 armmodul ARCH_ARMMODUL ARMMODUL 302 ketop SA1100_KETOP KETOP 303 av7200 ARCH_AV7200 AV7200 304 +arch_ti925 ARCH_ARCH_TI925 ARCH_TI925 305 +acq200 ARCH_ACQ200 ACQ200 306 +pt_dafit SA1100_PT_DAFIT PT_DAFIT 307 +ihba ARCH_IHBA IHBA 308 +quinque ARCH_QUINQUE QUINQUE 309 +nimbraone ARCH_NIMBRAONE NIMBRAONE 310 +nimbra29x ARCH_NIMBRA29X NIMBRA29X 311 +nimbra210 ARCH_NIMBRA210 NIMBRA210 312 +hhp_d95xx ARCH_HHP_D95XX HHP_D95XX 313 +labarm ARCH_LABARM LABARM 314 +m825xx ARCH_M825XX M825XX 315 +m7100 SA1100_M7100 M7100 316 +nipc2 ARCH_NIPC2 NIPC2 317 +fu7202 ARCH_FU7202 FU7202 318 +adsagx ARCH_ADSAGX ADSAGX 319 --- linux-2.5.68/arch/arm/vmlinux-armv.lds.in 2003-04-19 20:45:17.000000000 -0700 +++ 25/arch/arm/vmlinux-armv.lds.in 2003-04-29 20:50:34.000000000 -0700 @@ -35,6 +35,9 @@ SECTIONS __setup_start = .; *(.init.setup) __setup_end = .; + __early_begin = .; + *(__early_param) + __early_end = .; __start___param = .; *(__param) __stop___param = .; --- linux-2.5.68/arch/cris/drivers/Kconfig 2003-02-10 12:24:11.000000000 -0800 +++ 25/arch/cris/drivers/Kconfig 2003-04-29 20:50:34.000000000 -0700 @@ -30,7 +30,7 @@ config NET_ETHERNET If your Linux machine will be connected to an Ethernet and you have an Ethernet network interface card (NIC) installed in your computer, say Y here and read the Ethernet-HOWTO, available from - . You will then also have + . You will then also have to say Y to the driver for your particular NIC. Note that the answer to this question won't directly affect the @@ -392,7 +392,7 @@ config PRINTER box (as opposed to using a serial printer; if the connector at the printer has 9 or 25 holes ["female"], then it's serial), say Y. Also read the Printing-HOWTO, available from - . + . It is possible to share one parallel port among several devices (e.g. printer and ZIP drive) and it is safe to compile the @@ -485,7 +485,7 @@ config BLK_DEV_IDE topics, is contained in . For detailed information about hard drives, consult the Disk-HOWTO and the Multi-Disk-HOWTO, available from - . + . To fine-tune ATA/IDE drive/interface parameters for improved performance, look for the hdparm package at --- linux-2.5.68/arch/cris/drivers/serial.c 2003-03-04 20:02:35.000000000 -0800 +++ 25/arch/cris/drivers/serial.c 2003-04-29 20:50:34.000000000 -0700 @@ -1402,7 +1402,7 @@ receive_chars(struct e100_serial *info) if (!E100_RTS_GET(info) && CIRC_SPACE(info->recv.head, info->recv.tail, SERIAL_RECV_SIZE) < TTY_THROTTLE_LIMIT) - info->tty->driver.throttle(info->tty); + info->tty->driver->throttle(info->tty); START_FLUSH_FAST_TIMER(info, "receive_chars"); @@ -1658,7 +1658,7 @@ flush_to_flip_buffer(struct e100_serial /* unthrottle if we have throttled */ if (E100_RTS_GET(info) && CIRC_SPACE(info->recv.head, info->recv.tail, SERIAL_RECV_SIZE) > TTY_THROTTLE_LIMIT) - tty->driver.unthrottle(info->tty); + tty->driver->unthrottle(info->tty); } static _INLINE_ void @@ -3049,8 +3049,8 @@ rs_close(struct tty_struct *tty, struct #endif shutdown(info); - if (tty->driver.flush_buffer) - tty->driver.flush_buffer(tty); + if (tty->driver->flush_buffer) + tty->driver->flush_buffer(tty); if (tty->ldisc.flush_buffer) tty->ldisc.flush_buffer(tty); tty->closing = 0; @@ -3169,7 +3169,7 @@ block_til_ready(struct tty_struct *tty, * If this is a callout device, then just make sure the normal * device isn't being used. */ - if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) { + if (tty->driver->subtype == SERIAL_TYPE_CALLOUT) { if (info->flags & ASYNC_NORMAL_ACTIVE) return -EBUSY; if ((info->flags & ASYNC_CALLOUT_ACTIVE) && @@ -3289,7 +3289,7 @@ rs_open(struct tty_struct *tty, struct f /* find which port we want to open */ - line = MINOR(tty->device) - tty->driver.minor_start; + line = tty->index; if (line < 0 || line >= NR_PORTS) return -ENODEV; @@ -3302,8 +3302,7 @@ rs_open(struct tty_struct *tty, struct f return -ENODEV; #ifdef SERIAL_DEBUG_OPEN - printk("[%d] rs_open %s%d, count = %d\n", current->pid, - tty->driver.name, info->line, + printk("[%d] rs_open %s, count = %d\n", current->pid, tty->name, info->count); #endif @@ -3359,7 +3358,7 @@ rs_open(struct tty_struct *tty, struct f } if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) { - if (tty->driver.subtype == SERIAL_TYPE_NORMAL) + if (tty->driver->subtype == SERIAL_TYPE_NORMAL) *tty->termios = info->normal_termios; else *tty->termios = info->callout_termios; --- linux-2.5.68/arch/cris/Kconfig 2003-03-17 14:56:00.000000000 -0800 +++ 25/arch/cris/Kconfig 2003-04-29 20:50:34.000000000 -0700 @@ -40,7 +40,7 @@ config BINFMT_ELF want to say Y here. Information about ELF is contained in the ELF HOWTO available from - . + . If you find that after upgrading from Linux kernel 1.2 and saying Y here, you still can't run any ELF binaries (they just crash), then @@ -615,7 +615,7 @@ config CD_NO_IDESCSI ---help--- If you have a CD-ROM drive that is neither SCSI nor IDE/ATAPI, say Y here, otherwise N. Read the CD-ROM-HOWTO, available from - . + . Note that the answer to this question doesn't directly affect the kernel: saying N will just cause the configurator to skip all @@ -667,7 +667,7 @@ config SOUND interrupt and DMA channel), because you will be asked for it. You want to read the Sound-HOWTO, available from - . General information about + . General information about the modular sound system is contained in the files . The file contains some slightly --- linux-2.5.68/arch/h8300/Kconfig 2003-04-19 20:45:17.000000000 -0700 +++ 25/arch/h8300/Kconfig 2003-04-29 20:50:34.000000000 -0700 @@ -181,7 +181,7 @@ config NETDEVICES telephone line with a modem either via UUCP (UUCP is a protocol to forward mail and news between unix hosts over telephone lines; read the UUCP-HOWTO, available from - ) or dialing up a shell + ) or dialing up a shell account or a BBS, even using term (term is a program which gives you almost full Internet connectivity if you have a regular dial up shell account on some Internet connected Unix computer. Read @@ -201,7 +201,7 @@ config NETDEVICES Make sure to read the NET-3-HOWTO. Eventually, you will have to read Olaf Kirch's excellent and free book "Network Administrator's - Guide", to be found in . If + Guide", to be found in . If unsure, say Y. endmenu --- linux-2.5.68/arch/i386/Kconfig 2003-04-19 20:45:17.000000000 -0700 +++ 25/arch/i386/Kconfig 2003-04-29 22:57:31.000000000 -0700 @@ -65,19 +65,16 @@ config X86_NUMAQ config X86_SUMMIT bool "Summit/EXA (IBM x440)" + depends on SMP help This option is needed for IBM systems that use the Summit/EXA chipset. In particular, it is needed for the x440. If you don't have one of these computers, you should say N here. -config ACPI_SRAT - bool - default y - depends on NUMA && X86_SUMMIT - config X86_BIGSMP bool "Support for other sub-arch SMP systems with more than 8 CPUs" + depends on SMP help This option is needed for the systems that have more than 8 CPUs and if the system is not of any sub-arch type above. @@ -95,8 +92,24 @@ config X86_VISWS A kernel compiled for the Visual Workstation will not run on PCs and vice versa. See for details. +config X86_GENERICARCH + bool "Generic architecture (Summit, bigsmp, default)" + depends on SMP + help + This option compiles in the Summit, bigsmp, default subarchitectures. + It is intended for a generic binary kernel. + endchoice +config ACPI_SRAT + bool + default y + depends on NUMA && (X86_SUMMIT || X86_GENERICARCH) + +config X86_CYCLONE_TIMER + bool + default y + depends on X86_SUMMIT || X86_GENERICARCH choice prompt "Processor family" @@ -183,7 +196,7 @@ config MPENTIUMII optimizations. config MPENTIUMIII - bool "Pentium-III/Celeron(Coppermine)" + bool "Pentium-III/Celeron(Coppermine)/Pentium-III Xeon" help Select this for Intel chips based on the Pentium-III and Celeron-Coppermine core. This option enables use of some @@ -191,7 +204,7 @@ config MPENTIUMIII extensions. config MPENTIUM4 - bool "Pentium-4/Celeron(P4-based)" + bool "Pentium-4/Celeron(P4-based)/Xeon" help Select this for Intel Pentium 4 chips. This includes both the Pentium 4 and P4-based Celeron chips. This option @@ -345,7 +358,7 @@ config X86_GOOD_APIC config X86_INTEL_USERCOPY bool - depends on MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M586MMX + depends on MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK7 default y config X86_USE_PPRO_CHECKSUM @@ -409,10 +422,40 @@ config SMP See also the , , , and the SMP-HOWTO available at - . + . If you don't know what to do here, say N. +config NR_CPUS + int "Maximum number of CPUs (2-32)" + depends on SMP + default "32" + help + This allows you to specify the maximum number of CPUs which this + kernel will support. The maximum supported value is 32 and the + minimum value which makes sense is 2. + + This is purely to save memory - each supported CPU adds + approximately eight kilobytes to the kernel image. + +choice + + prompt "Hyperthreading Support" + depends on SMP + default NR_SIBLINGS_0 + +config NR_SIBLINGS_0 + bool "off" + +config NR_SIBLINGS_2 + bool "2 siblings" + +config NR_SIBLINGS_4 + bool "4 siblings" + +endchoice + + config PREEMPT bool "Preemptible Kernel" help @@ -465,18 +508,6 @@ config X86_IO_APIC depends on !SMP && X86_UP_IOAPIC default y -config NR_CPUS - int "Maximum number of CPUs (2-32)" - depends on SMP - default "32" - help - This allows you to specify the maximum number of CPUs which this - kernel will support. The maximum supported value is 32 and the - minimum value which makes sense is 2. - - This is purely to save memory - each supported CPU adds - approximately eight kilobytes to the kernel image. - config X86_TSC bool depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2) && !X86_NUMAQ @@ -656,6 +687,44 @@ config HIGHMEM64G endchoice +choice + help + On i386, a process can only virtually address 4GB of memory. This + lets you select how much of that virtual space you would like to + devoted to userspace, and how much to the kernel. + + Some userspace programs would like to address as much as possible and + have few demands of the kernel other than it get out of the way. These + users may opt to use the 3.5GB option to give their userspace program + as much room as possible. Due to alignment issues imposed by PAE, + the "3.5GB" option is unavailable if "64GB" high memory support is + enabled. + + Other users (especially those who use PAE) may be running out of + ZONE_NORMAL memory. Those users may benefit from increasing the + kernel's virtual address space size by taking it away from userspace, + which may not need all of its space. An indicator that this is + happening is when /proc/Meminfo's "LowFree:" is a small percentage of + "LowTotal:" while "HighFree:" is very large. + + If unsure, say "3GB" + prompt "User address space size" + default 1GB + +config 05GB + bool "3.5 GB" + depends on !HIGHMEM64G + +config 1GB + bool "3 GB" + +config 2GB + bool "2 GB" + +config 3GB + bool "1 GB" +endchoice + config HIGHMEM bool depends on HIGHMEM64G || HIGHMEM4G @@ -669,7 +738,7 @@ config X86_PAE # Common NUMA Features config NUMA bool "Numa Memory Allocation Support" - depends on SMP && HIGHMEM64G && (X86_PC || X86_NUMAQ || (X86_SUMMIT && ACPI && !ACPI_HT_ONLY)) + depends on SMP && HIGHMEM64G && (X86_PC || X86_NUMAQ || X86_GENERICARCH || (X86_SUMMIT && ACPI && !ACPI_HT_ONLY)) default n if X86_PC default y if (X86_NUMAQ || X86_SUMMIT) @@ -767,7 +836,7 @@ config HAVE_DEC_LOCK # Summit needs it only when NUMA is on config BOOT_IOREMAP bool - depends on (X86_SUMMIT && NUMA) + depends on ((X86_SUMMIT || X86_GENERICARCH) && NUMA) default y endmenu @@ -790,7 +859,7 @@ config PM page on the WWW at and the Battery Powered Linux mini-HOWTO, available from - . + . Note that, even if you say N here, Linux on the x86 architecture will issue the hlt instruction if nothing is to be done, thereby @@ -798,7 +867,7 @@ config PM config SOFTWARE_SUSPEND bool "Software Suspend (EXPERIMENTAL)" - depends on EXPERIMENTAL && PM + depends on EXPERIMENTAL && PM && SWAP ---help--- Enable the possibilty of suspendig machine. It doesn't need APM. You may suspend your machine by 'swsusp' or 'shutdown -z